---- == Pentium의 MMX의 사용 == [[TableOfContents]] * 작성자 : 조재혁([minzkn], [mailto:minzkn_at_infoeq.comminzkn_at_infoeq.com]) === MMX란? === * MMX는 '''M'''ulti'''M'''edia e'''X'''tension의 약자로 그 목적은 범용레지스터의 크기보다 큰 정수연산을 보다 빠르게 하기 위함입니다. * 이 문서를 작성하는 현재시점을 기준으로 MM0 ~ 7까지의 특수 명칭이 MMX에 사용되고 있으며 이름만 이렇게 사용될뿐 사실상 부동소수점 연산용 레지스터를 사용하게 됩니다. (이러한 이유로 아래 설명하지만 EMMS의 명령에 대해서 필요한 이유를 이해하세요!) * MMX의 가장 대표적인 기능으로는 8바이트 단위로 Data를 전송하는 것인데 이것 말고도 기본 산술연산 및 논리연산을 할수 있게 되어 있습니다. * MMX는 범용레지스터로 하는 기능과 비교했을 때 다른 점이 Packed mode라는 것이 있는데 아직 이것에 대한 필요성을 제가 못느끼고 있는 관계로 나중에 필요성이 생기면 정리좀 해보겠습니다. === MMX의 지원여부 판단 === * 아래와 같이 '''cpuid'''명령을 통하여 해당 기능의 지원 여부를 확인 할수 있습니다. 이밖에 3D-NOW같은 경우도 비슷한 방법으로 지원여부를 알수 있겠습니다. {{{#!vim c int MZ_IsMMX(void) { static int s_Return = (-1);^I if(s_Return == (-1)) { __asm__ __volatile__( "\n\t" "movl $1, %%eax\n\t" "cpuid\n\t" "xorl %%eax, %%eax\n\t" "testl $0x800000, %%edx\n\t" "jz L_Return\n\t" "incl %%eax\n\t" "L_Return:\n\t" "movl %%eax, %0\n\t" "\n\t" : "=m"(s_Return) : : "ebx" ); } return(s_Return); } }}} === MMX 명령어 요약표 === * 특별한 설명이 없더라도 아래의 요약표를 보시면 어셈블리 개발자분들이라면 그리 어렵지 않게 접근하실수 있을겁니다. * EMMS에 대해 간단히 추가설명하자면 부동소수점 연산을 하기 위해서 상태를 지울 필요가 있는데 그런 경우에 적절히 삽입하여 사용하여야 합니다. (즉, MMX명령을 사용하게 되면 EMMS명령은 뒤따라야 골치아픈 오동작 계산을 방지할수 있습니다.) || '''기능''' || '''값의 순환이 고려될 때''' || '''부호가 고려될 때''' || '''부호가 고려되지 않을 때''' || || 산술덧셈 || PADDB, PADDW, PADDD || PADDSB, PADDSW || PADDUB, PADDUW || || 산술뺄셈 || PSUBB, PSUBW, PSUBD || PSUBSB, PSUBSW || PSUBUB, PSUBUW || || 산술곱셈 || PMULL, PMULH || || || || 산술곱셈자리올림 || PMADD || || || || 비교 || PCMPEQB, PCMPEQW, PCMPEQD || || || || PCMPGTPB, PCMPGTPW, PCMPGTPD || || || || 변환 || PUNPCKHBW || PACKSSWB || PACKUSWB || || PUNPCKHWD || PACKSSDW || || || PUNPCKHDQ || || || || PUNPCKLBW || || || || PUNPCKLWD || || || || PUNPCKLDQ || || || || 논리연산 || '''묶음의 단위''' || '''Quad단위''' || || || PAND || || || PANDN || || || POR || || || PXOR || || || PSLLQ || || || PSRLQ || || 전송 || '''Double word 전송''' || '''Quad word 전송''' || || MOVD || MOVQ || || MMX 상태를 비움 || EMMS || === 프로그램에 적용해보기 === ==== Inline assembly에 어떻게 적용할 것인가? ==== * Clobber에 어떻게 두어야 사용할수 있을까요? 아래의 간단한 예제를 보시다시피 "X"라는 것이 현재로서는 적당한듯 싶군요. 필자는 사실상 이렇게 쓰는것이 별로 마음에 내키지 못하여 그냥 *.s 로 Inline이 아닌 상태로 대부분 사용하기는 하지만 가끔은 Inline을 아래와 같이 사용하기는 합니다. 혹시 더 적당한 Clobber를 알고 계시다면 주저없이 알려주시면 좋겠군요. * "X"는 어떠한 인자라도 허용하는 것이라는 점을 노파심에 설명 드리며 사실상 왠만한거는 모르겠다 싶으면 이것을 쓰면 잘 되죠. (안되면 골치아픈거 아시죠?) {{{#!vim c unsigned long long MZ_NopMMX(unsigned long long s_Value) { unsigned long long s_Return; __asm__ volatile( "\n\t" "movd %1, %%mm0\n\t" "movd %%mm0, %0\n\t" "emms\n\t" "\n\t" : "=X"(s_Return) : "X"(s_Value) ); return(s_Return); } }}} === 문서를 마치며 === * 이 문서를 작성하기 위해 Intel pentium manual을 참조하였습니다. 자세한것은 Intel의 홈페이지를 방문하세요. * 본 문서의 최근 버젼은 [http://minzkn.pe.ky http://minzkn.pe.ky]에서 보실수 있습니다. ----