ramdisk Makefile: CLEANFILES fix
[minix.git] / lib / libminlib / i386 / _cpufeature.c
blob1a7c011d585a91d13d9ba74b8716f6bee792d859
1 #include <sys/types.h>
2 #include <stdint.h>
3 #include <minix/minlib.h>
4 #include <minix/cpufeature.h>
5 #include <machine/vm.h>
6 #include <string.h>
8 int _cpufeature(int cpufeature)
10 u32_t eax, ebx, ecx, edx;
11 u32_t ef_eax = 0, ef_ebx = 0, ef_ecx = 0, ef_edx = 0;
12 unsigned int family, model, stepping;
13 int is_intel = 0, is_amd = 0;
15 eax = ebx = ecx = edx = 0;
17 /* We assume >= pentium for cpuid */
18 eax = 0;
19 _cpuid(&eax, &ebx, &ecx, &edx);
20 if(eax > 0) {
21 char vendor[12];
22 memcpy(vendor, &ebx, sizeof(ebx));
23 memcpy(vendor+4, &edx, sizeof(edx));
24 memcpy(vendor+8, &ecx, sizeof(ecx));
25 if(!strncmp(vendor, "GenuineIntel", sizeof(vendor)))
26 is_intel = 1;
27 if(!strncmp(vendor, "AuthenticAMD", sizeof(vendor)))
28 is_amd = 1;
29 eax = 1;
30 _cpuid(&eax, &ebx, &ecx, &edx);
31 } else return 0;
33 stepping = eax & 0xf;
34 model = (eax >> 4) & 0xf;
36 if(model == 0xf || model == 0x6) {
37 model += ((eax >> 16) & 0xf) << 4;
40 family = (eax >> 8) & 0xf;
42 if(family == 0xf) {
43 family += (eax >> 20) & 0xff;
46 if(is_amd) {
47 ef_eax = 0x80000001;
48 _cpuid(&ef_eax, &ef_ebx, &ef_ecx, &ef_edx);
51 switch(cpufeature) {
52 case _CPUF_I386_PSE:
53 return edx & CPUID1_EDX_PSE;
54 case _CPUF_I386_PGE:
55 return edx & CPUID1_EDX_PGE;
56 case _CPUF_I386_APIC_ON_CHIP:
57 return edx & CPUID1_EDX_APIC_ON_CHIP;
58 case _CPUF_I386_TSC:
59 return edx & CPUID1_EDX_TSC;
60 case _CPUF_I386_FPU:
61 return edx & CPUID1_EDX_FPU;
62 #define SSE_FULL_EDX (CPUID1_EDX_FXSR | CPUID1_EDX_SSE | CPUID1_EDX_SSE2)
63 #define SSE_FULL_ECX (CPUID1_ECX_SSE3 | CPUID1_ECX_SSSE3 | \
64 CPUID1_ECX_SSE4_1 | CPUID1_ECX_SSE4_2)
65 case _CPUF_I386_SSE1234_12:
66 return (edx & SSE_FULL_EDX) == SSE_FULL_EDX &&
67 (ecx & SSE_FULL_ECX) == SSE_FULL_ECX;
68 case _CPUF_I386_FXSR:
69 return edx & CPUID1_EDX_FXSR;
70 case _CPUF_I386_SSE:
71 return edx & CPUID1_EDX_SSE;
72 case _CPUF_I386_SSE2:
73 return edx & CPUID1_EDX_SSE2;
74 case _CPUF_I386_SSE3:
75 return ecx & CPUID1_ECX_SSE3;
76 case _CPUF_I386_SSSE3:
77 return ecx & CPUID1_ECX_SSSE3;
78 case _CPUF_I386_SSE4_1:
79 return ecx & CPUID1_ECX_SSE4_1;
80 case _CPUF_I386_SSE4_2:
81 return ecx & CPUID1_ECX_SSE4_2;
82 case _CPUF_I386_HTT:
83 return edx & CPUID1_EDX_HTT;
84 case _CPUF_I386_HTT_MAX_NUM:
85 return (ebx >> 16) & 0xff;
86 case _CPUF_I386_SYSENTER:
87 if(!is_intel) return 0;
88 if(!(edx & CPUID1_EDX_SYSENTER)) return 0;
89 if(family == 6 && model < 3 && stepping < 3) return 0;
90 return 1;
91 case _CPUF_I386_SYSCALL:
92 if(!is_amd) return 0;
93 if(!(ef_edx & CPUID_EF_EDX_SYSENTER)) return 0;
94 return 1;
97 return 0;