etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / arch / i386 / _cpufeature.c
blob7448c5c9af3f642e0e1a26135855ca4563de1993
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_PAE:
55 return edx & CPUID1_EDX_PAE;
56 case _CPUF_I386_PGE:
57 return edx & CPUID1_EDX_PGE;
58 case _CPUF_I386_APIC_ON_CHIP:
59 return edx & CPUID1_EDX_APIC_ON_CHIP;
60 case _CPUF_I386_TSC:
61 return edx & CPUID1_EDX_TSC;
62 case _CPUF_I386_FPU:
63 return edx & CPUID1_EDX_FPU;
64 #define SSE_FULL_EDX (CPUID1_EDX_FXSR | CPUID1_EDX_SSE | CPUID1_EDX_SSE2)
65 #define SSE_FULL_ECX (CPUID1_ECX_SSE3 | CPUID1_ECX_SSSE3 | \
66 CPUID1_ECX_SSE4_1 | CPUID1_ECX_SSE4_2)
67 case _CPUF_I386_SSE1234_12:
68 return (edx & SSE_FULL_EDX) == SSE_FULL_EDX &&
69 (ecx & SSE_FULL_ECX) == SSE_FULL_ECX;
70 case _CPUF_I386_FXSR:
71 return edx & CPUID1_EDX_FXSR;
72 case _CPUF_I386_SSE:
73 return edx & CPUID1_EDX_SSE;
74 case _CPUF_I386_SSE2:
75 return edx & CPUID1_EDX_SSE2;
76 case _CPUF_I386_SSE3:
77 return ecx & CPUID1_ECX_SSE3;
78 case _CPUF_I386_SSSE3:
79 return ecx & CPUID1_ECX_SSSE3;
80 case _CPUF_I386_SSE4_1:
81 return ecx & CPUID1_ECX_SSE4_1;
82 case _CPUF_I386_SSE4_2:
83 return ecx & CPUID1_ECX_SSE4_2;
84 case _CPUF_I386_HTT:
85 return edx & CPUID1_EDX_HTT;
86 case _CPUF_I386_HTT_MAX_NUM:
87 return (ebx >> 16) & 0xff;
88 case _CPUF_I386_SYSENTER:
89 if(!is_intel) return 0;
90 if(!(edx & CPUID1_EDX_SYSENTER)) return 0;
91 if(family == 6 && model < 3 && stepping < 3) return 0;
92 return 1;
93 case _CPUF_I386_SYSCALL:
94 if(!is_amd) return 0;
95 if(!(ef_edx & CPUID_EF_EDX_SYSENTER)) return 0;
96 return 1;
99 return 0;