b730cc11a9a65fd63a892b8f9fc0df7e347ef37b
[reactos.git] / reactos / lib / mingw / 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 #ifdef __i386__
33 unsigned int eax, ebx, ecx, edx;
34 /* Try to change the value of CPUID bit (bit 21) in EFLAGS.
35 If the bit can be toggled, CPUID is supported. */
36 asm volatile ("pushfl; pushfl; popl %0;"
37 "movl %0,%1; xorl %2,%0;"
38 "pushl %0; popfl; pushfl; popl %0; popfl"
39 : "=&r" (eax), "=&r" (ebx)
40 : "i" (0x00200000));
41
42 if (((eax ^ ebx) & 0x00200000) == 0)
43 return;
44
45 __cpuid (0, eax, ebx, ecx, edx);
46 if (eax == 0)
47 return;
48
49 __cpuid (1, eax, ebx, ecx, edx);
50
51 if (edx & EDX_CX8)
52 __cpu_features |= _CRT_CMPXCHG8B;
53 if (edx & EDX_CMOV)
54 __cpu_features |= _CRT_CMOV;
55
56 if (edx & EDX_MMX)
57 __cpu_features |= _CRT_MMX;
58 if (edx & EDX_FXSR)
59 __cpu_features |= _CRT_FXSR;
60 if (edx & EDX_SSE)
61 __cpu_features |= _CRT_SSE;
62 if (edx & EDX_SSE2)
63 __cpu_features |= _CRT_SSE2;
64
65
66 if (ecx & ECX_SSE3)
67 __cpu_features |= _CRT_SSE3;
68 if (ecx & ECX_CX16)
69 __cpu_features |= _CRT_CMPXCHG16B;
70
71 __cpuid (0x80000000, eax, ebx, ecx, edx);
72 if (eax < 0x80000001)
73 return;
74 __cpuid (0x80000001, eax, ebx, ecx, edx);
75 if (edx & EDX_3DNOW);
76 __cpu_features |= _CRT_3DNOW;
77 if (edx & EDX_3DNOWP)
78 __cpu_features |= _CRT_3DNOWP;
79 #endif
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