diff options
author | Danny Smith <dannysmith@users.sourceforge.net> | 2006-07-03 10:32:58 +0000 |
---|---|---|
committer | Danny Smith <dannysmith@users.sourceforge.net> | 2006-07-03 10:32:58 +0000 |
commit | f34428eb356a001928e1786d51cbfe216ebeef83 (patch) | |
tree | d6319e46a0cc4bdaae18f49f4a4ad821677f895e /winsup/mingw/cpu_features.c | |
parent | 69d5f3329f4869d6d0e20f610926934fc0044dce (diff) | |
download | cygnal-f34428eb356a001928e1786d51cbfe216ebeef83.tar.gz cygnal-f34428eb356a001928e1786d51cbfe216ebeef83.tar.bz2 cygnal-f34428eb356a001928e1786d51cbfe216ebeef83.zip |
Support SSE float environment in fenv.h functions.
* cpu_features.c: New file.
* cpu_features.h: New file.
* crt1.c: Include "cpu_features.h".
(__mingw_CRTStartup): Call cpu_features_init().
* Makefile.in (MING_OBJS): Add cpu_features.c.
(SRCDIST_FILES): Add cpu_features.c, cpu_features.h.
* include/fenv,h ( fenv_t;): Append __mxcsr field.
(__MXCSR_EXCEPT_FLAG_SHIFT): New define.
(__MXCSR_EXCEPT_MASK_SHIFT): New define.
(__MXCSR_ROUND_FLAG_SHIFT): New define.
* mingwex/feclearexcept.c: Include "cpu_features.h".
Handle SSE environment.
* mingwex/fegetenv.c: Likewise.
* mingwex/feholdexcept.c: Likewise.
* mingwex/fesetenv.c: Likewise.
* mingwex/fesetexceptflag.c: Likewise.
* mingwex/fesetround.c: Likewise.
* mingwex/fetestexcept.c: Likewise.
* mingwex/feupdateenv.c: Likewise.
* mingwex/fegetround.c: Add comment.
Diffstat (limited to 'winsup/mingw/cpu_features.c')
-rwxr-xr-x | winsup/mingw/cpu_features.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/winsup/mingw/cpu_features.c b/winsup/mingw/cpu_features.c new file mode 100755 index 000000000..0eccfbfe3 --- /dev/null +++ b/winsup/mingw/cpu_features.c @@ -0,0 +1,105 @@ +#include <stdbool.h> +#include "cpu_features.h" + +/* level 1 edx bits */ +#define EDX_CX8 (1 << 8) /* CMPXCHG8B */ +#define EDX_CMOV (1 << 15) +#define EDX_MMX (1 << 23) +#define EDX_FXSR (1 << 24) /* FXSAVE and FXRSTOR */ +#define EDX_SSE (1 << 25) +#define EDX_SSE2 (1 << 26) + +/* level 1 ecx bits */ +#define ECX_SSE3 (1 << 0) +#define ECX_CX16 (1 << 13) /* CMPXCHG16B */ + +/* extended level 0x80000001 edx bits */ +#define EDX_3DNOW (1 << 31) +#define EDX_3DNOWP (1 << 30) +#define EDX_LM (1 << 29) /*LONG MODE */ + +#define __cpuid(level,a,b,c,d) \ + __asm__ __volatile__ ("cpuid;" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d)\ + : "0" (level)) + +/* Combine the different cpuid flags into a single bitmap. */ + +unsigned int __cpu_features = 0; + +void __cpu_features_init (void) +{ + unsigned int eax, ebx, ecx, edx; + /* Try to change the value of CPUID bit (bit 21) in EFLAGS. + If the bit can be toggled, CPUID is supported. */ + asm volatile ("pushfl; pushfl; popl %0;" + "movl %0,%1; xorl %2,%0;" + "pushl %0; popfl; pushfl; popl %0; popfl" + : "=&r" (eax), "=&r" (ebx) + : "i" (0x00200000)); + + if (((eax ^ ebx) & 0x00200000) == 0) + return; + + __cpuid (0, eax, ebx, ecx, edx); + if (eax == 0) + return; + + __cpuid (1, eax, ebx, ecx, edx); + + if (edx & EDX_CX8) + __cpu_features |= _CRT_CMPXCHG8B; + if (edx & EDX_CMOV) + __cpu_features |= _CRT_CMOV; + + if (edx & EDX_MMX) + __cpu_features |= _CRT_MMX; + if (edx & EDX_FXSR) + __cpu_features |= _CRT_FXSR; + if (edx & EDX_SSE) + __cpu_features |= _CRT_SSE; + if (edx & EDX_SSE2) + __cpu_features |= _CRT_SSE2; + + + if (ecx & ECX_SSE3) + __cpu_features |= _CRT_SSE3; + if (ecx & ECX_CX16) + __cpu_features |= _CRT_CMPXCHG16B; + + __cpuid (0x80000000, eax, ebx, ecx, edx); + if (eax < 0x80000001) + return; + __cpuid (0x80000001, eax, ebx, ecx, edx); + if (edx & EDX_3DNOW); + __cpu_features |= _CRT_3DNOW; + if (edx & EDX_3DNOWP) + __cpu_features |= _CRT_3DNOWP; + + return; +} + +#ifdef TEST + +#include <stdio.h> +#define report(feature) \ + if ((feature) & __cpu_features) printf( #feature " found\n") + +int main() +{ + __cpu_features_init(); + + report(_CRT_CMPXCHG8B); + report(_CRT_CMOV); + report(_CRT_MMX); + report(_CRT_FXSR); + report(_CRT_SSE); + report(_CRT_SSE2); + report(_CRT_SSE3); + report(_CRT_CMPXCHG16B); + report(_CRT_3DNOW); + report(_CRT_3DNOWP); + return 0; +} + +#endif |