OSDN Git Service

Eliminate all references to non-standard __NO_ISOCEXT macro.
[mingw/mingw-org-wsl.git] / mingwrt / cpu_features.c
1 #include <stdbool.h>
2 #include "cpu_features.h"
3
4 /* level 1 edx bits */
5 #define EDX_CX8 (1 << 8) /* CMPXCHG8B */
6 #define EDX_CMOV (1 << 15)
7 #define EDX_MMX (1 << 23)
8 #define EDX_FXSR (1 << 24) /* FXSAVE and FXRSTOR */
9 #define EDX_SSE (1 << 25)
10 #define EDX_SSE2 (1 << 26)
11
12 /*  level 1 ecx bits */
13 #define ECX_SSE3 (1 << 0)
14 #define ECX_CX16 (1 << 13) /* CMPXCHG16B */
15
16 /* extended level 0x80000001 edx bits */
17 #define EDX_3DNOW (1 << 31)
18 #define EDX_3DNOWP (1 << 30)
19 #define EDX_LM (1 << 29) /*LONG MODE */
20
21 #define __cpuid(level,a,b,c,d)                                  \
22   asm volatile ("cpuid;"                                \
23                         : "=a" (a), "=b" (b), "=c" (c), "=d" (d)\
24                         : "0" (level))
25
26 /* Combine the different cpuid flags into a single bitmap.  */
27
28 unsigned int __cpu_features = 0;
29
30 void  __cpu_features_init (void)
31 {
32   unsigned int eax, ebx, ecx, edx;
33   /* Try to change the value of CPUID bit (bit 21) in EFLAGS.
34      If the bit can be toggled, CPUID is supported.  */
35   asm volatile ("pushfl; pushfl; popl %0;"
36                 "movl %0,%1; xorl %2,%0;"
37                 "pushl %0; popfl; pushfl; popl %0; popfl"
38                 : "=&r" (eax), "=&r" (ebx)
39                 : "i" (0x00200000));
40
41   if (((eax ^ ebx) & 0x00200000) == 0)
42     return;
43
44   __cpuid (0, eax, ebx, ecx, edx);
45   if (eax == 0)
46     return;
47
48   __cpuid (1, eax, ebx, ecx, edx);
49
50   if (edx & EDX_CX8)
51      __cpu_features |= _CRT_CMPXCHG8B;
52   if (edx & EDX_CMOV)
53      __cpu_features |= _CRT_CMOV;
54
55   if (edx & EDX_MMX)
56      __cpu_features |= _CRT_MMX;
57   if (edx & EDX_FXSR)
58      __cpu_features |= _CRT_FXSR;
59   if (edx & EDX_SSE)
60      __cpu_features |= _CRT_SSE;
61   if (edx & EDX_SSE2)
62      __cpu_features |= _CRT_SSE2;
63
64
65   if (ecx & ECX_SSE3)
66      __cpu_features |= _CRT_SSE3;
67   if (ecx & ECX_CX16)
68      __cpu_features |= _CRT_CMPXCHG16B;
69
70   __cpuid (0x80000000, eax, ebx, ecx, edx);
71   if (eax < 0x80000001)
72     return;
73   __cpuid (0x80000001, eax, ebx, ecx, edx);
74   if (edx & EDX_3DNOW)
75     __cpu_features |= _CRT_3DNOW;
76   if (edx & EDX_3DNOWP)
77     __cpu_features |= _CRT_3DNOWP;
78
79   return;
80 }
81
82 #ifdef TEST
83
84 #include <stdio.h>
85 #define report(feature) \
86   if ((feature) & __cpu_features) printf( #feature " found\n")
87
88 int main()
89 {
90   __cpu_features_init();
91
92   report(_CRT_CMPXCHG8B);
93   report(_CRT_CMOV);
94   report(_CRT_MMX);
95   report(_CRT_FXSR);
96   report(_CRT_SSE);
97   report(_CRT_SSE2);
98   report(_CRT_SSE3);
99   report(_CRT_CMPXCHG16B);
100   report(_CRT_3DNOW);
101   report(_CRT_3DNOWP);
102  return 0;
103 }
104
105 #endif