diff options
Diffstat (limited to 'src/post/goom/mmx.h')
-rwxr-xr-x | src/post/goom/mmx.h | 183 |
1 files changed, 181 insertions, 2 deletions
diff --git a/src/post/goom/mmx.h b/src/post/goom/mmx.h index 2a0ca62a4..fe095de12 100755 --- a/src/post/goom/mmx.h +++ b/src/post/goom/mmx.h @@ -54,6 +54,183 @@ typedef union { float s[2]; /* Single-precision (32-bit) value */ } __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */ + + +/* Function to test if multimedia instructions are supported... +*/ +inline extern int +mm_support(void) +{ + /* Returns 1 if MMX instructions are supported, + 3 if Cyrix MMX and Extended MMX instructions are supported + 5 if AMD MMX and 3DNow! instructions are supported + 13 if AMD Extended MMX, &3dNow supported + 0 if hardware does not support any of these + */ + register int rval = 0; + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %%eax\n\t" + + /* ... Compare and test result */ + "xorl %%eax, %%ecx\n\t" + "testl $0x200000, %%ecx\n\t" + "jz NotSupported1\n\t" /* CPUID not supported */ + + + /* Get standard CPUID information, and + go to a specific vendor section */ + "movl $0, %%eax\n\t" + "cpuid\n\t" + + /* Check for Intel */ + "cmpl $0x756e6547, %%ebx\n\t" + "jne TryAMD\n\t" + "cmpl $0x49656e69, %%edx\n\t" + "jne TryAMD\n\t" + "cmpl $0x6c65746e, %%ecx\n" + "jne TryAMD\n\t" + "jmp Intel\n\t" + + /* Check for AMD */ + "\nTryAMD:\n\t" + "cmpl $0x68747541, %%ebx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x69746e65, %%edx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x444d4163, %%ecx\n" + "jne TryCyrix\n\t" + "jmp AMD\n\t" + + /* Check for Cyrix */ + "\nTryCyrix:\n\t" + "cmpl $0x69727943, %%ebx\n\t" + "jne NotSupported2\n\t" + "cmpl $0x736e4978, %%edx\n\t" + "jne NotSupported3\n\t" + "cmpl $0x64616574, %%ecx\n\t" + "jne NotSupported4\n\t" + /* Drop through to Cyrix... */ + + + /* Cyrix Section */ + /* See if extended CPUID level 80000001 is supported */ + /* The value of CPUID/80000001 for the 6x86MX is undefined + according to the Cyrix CPU Detection Guide (Preliminary + Rev. 1.01 table 1), so we'll check the value of eax for + CPUID/0 to see if standard CPUID level 2 is supported. + According to the table, the only CPU which supports level + 2 is also the only one which supports extended CPUID levels. + */ + "cmpl $0x2, %%eax\n\t" + "jne MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported (in theory), so get extended + features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%eax\n\t" /* Test for MMX */ + "jz NotSupported5\n\t" /* MMX not supported */ + "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ + "jnz EMMXSupported\n\t" + "movl $1, %0\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "EMMXSupported:\n\t" + "movl $3, %0\n\n\t" /* EMMX and MMX Supported */ + "jmp Return\n\t" + + + /* AMD Section */ + "AMD:\n\t" + + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported6\n\t" /* MMX not supported */ + "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ + "jnz ThreeDNowSupported\n\t" + "movl $1, %0\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "ThreeDNowSupported:\n\t" + "testl $0x40000000, %%edx\n\t" /* Test AMD Extended MMX */ + "jnz AMDXMMXSupported\n\t" + "movl $5, %0\n\n\t" /* 3DNow! and MMX Supported */ + "jmp Return\n\t" + "AMDXMMXSupported:\n\t" + "movl $13, %0\n\n\t" /* XMMX, 3DNow! and MMX Supported */ + "jmp Return\n\t" + + + /* Intel Section */ + "Intel:\n\t" + + /* Check for MMX */ + "MMXtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported7\n\t" /* MMX Not supported */ + "movl $1, %0\n\n\t" /* MMX Supported */ + "jmp Return\n\t" + + /* Nothing supported */ + "\nNotSupported1:\n\t" + "#movl $101, %0\n\n\t" + "\nNotSupported2:\n\t" + "#movl $102, %0\n\n\t" + "\nNotSupported3:\n\t" + "#movl $103, %0\n\n\t" + "\nNotSupported4:\n\t" + "#movl $104, %0\n\n\t" + "\nNotSupported5:\n\t" + "#movl $105, %0\n\n\t" + "\nNotSupported6:\n\t" + "#movl $106, %0\n\n\t" + "\nNotSupported7:\n\t" + "#movl $107, %0\n\n\t" + "movl $0, %0\n\n\t" + + "Return:\n\t" + : "=X" (rval) + : /* no input */ + : "eax", "ebx", "ecx", "edx" + ); + + /* Return */ + return(rval); +} + +/* Function to test if mmx instructions are supported... +*/ +inline extern int +mmx_ok(void) +{ + /* Returns 1 if MMX instructions are supported, 0 otherwise */ + return ( mm_support() & 0x1 ); +} + + /* Helper functions for the instruction macros that follow... (note that memory-to-register, m2r, instructions are nearly as efficient as register-to-register, r2r, instructions; @@ -521,12 +698,14 @@ typedef union { #define emms() \ { \ printf("emms()\n"); \ - __asm__ __volatile__ ("emms"); \ + __asm__ __volatile__ ("emms" \ + "st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"); \ } #else -#define emms() __asm__ __volatile__ ("emms") +#define emms() __asm__ __volatile__ ("emms"::: \ + "st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)") #endif |