OLD | NEW |
1 /* CpuArch.c -- CPU specific code | 1 /* CpuArch.c -- CPU specific code |
2 2010-10-26: Igor Pavlov : Public domain */ | 2 2015-03-25: Igor Pavlov : Public domain */ |
| 3 |
| 4 #include "Precomp.h" |
3 | 5 |
4 #include "CpuArch.h" | 6 #include "CpuArch.h" |
5 | 7 |
6 #ifdef MY_CPU_X86_OR_AMD64 | 8 #ifdef MY_CPU_X86_OR_AMD64 |
7 | 9 |
8 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) | 10 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) |
9 #define USE_ASM | 11 #define USE_ASM |
10 #endif | 12 #endif |
11 | 13 |
| 14 #if !defined(USE_ASM) && _MSC_VER >= 1500 |
| 15 #include <intrin.h> |
| 16 #endif |
| 17 |
12 #if defined(USE_ASM) && !defined(MY_CPU_AMD64) | 18 #if defined(USE_ASM) && !defined(MY_CPU_AMD64) |
13 static UInt32 CheckFlag(UInt32 flag) | 19 static UInt32 CheckFlag(UInt32 flag) |
14 { | 20 { |
15 #ifdef _MSC_VER | 21 #ifdef _MSC_VER |
16 __asm pushfd; | 22 __asm pushfd; |
17 __asm pop EAX; | 23 __asm pop EAX; |
18 __asm mov EDX, EAX; | 24 __asm mov EDX, EAX; |
19 __asm xor EAX, flag; | 25 __asm xor EAX, flag; |
20 __asm push EAX; | 26 __asm push EAX; |
21 __asm popfd; | 27 __asm popfd; |
(...skipping 20 matching lines...) Expand all Loading... |
42 "=c" (flag) : "c" (flag): | 48 "=c" (flag) : "c" (flag): |
43 "%eax", "%edx" ); | 49 "%eax", "%edx" ); |
44 #endif | 50 #endif |
45 return flag; | 51 return flag; |
46 } | 52 } |
47 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 2
1) == 0) return False; | 53 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 2
1) == 0) return False; |
48 #else | 54 #else |
49 #define CHECK_CPUID_IS_SUPPORTED | 55 #define CHECK_CPUID_IS_SUPPORTED |
50 #endif | 56 #endif |
51 | 57 |
52 static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) | 58 void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) |
53 { | 59 { |
54 #ifdef USE_ASM | 60 #ifdef USE_ASM |
55 | 61 |
56 #ifdef _MSC_VER | 62 #ifdef _MSC_VER |
57 | 63 |
58 UInt32 a2, b2, c2, d2; | 64 UInt32 a2, b2, c2, d2; |
59 __asm xor EBX, EBX; | 65 __asm xor EBX, EBX; |
60 __asm xor ECX, ECX; | 66 __asm xor ECX, ECX; |
61 __asm xor EDX, EDX; | 67 __asm xor EDX, EDX; |
62 __asm mov EAX, function; | 68 __asm mov EAX, function; |
63 __asm cpuid; | 69 __asm cpuid; |
64 __asm mov a2, EAX; | 70 __asm mov a2, EAX; |
65 __asm mov b2, EBX; | 71 __asm mov b2, EBX; |
66 __asm mov c2, ECX; | 72 __asm mov c2, ECX; |
67 __asm mov d2, EDX; | 73 __asm mov d2, EDX; |
68 | 74 |
69 *a = a2; | 75 *a = a2; |
70 *b = b2; | 76 *b = b2; |
71 *c = c2; | 77 *c = c2; |
72 *d = d2; | 78 *d = d2; |
73 | 79 |
74 #else | 80 #else |
75 | 81 |
| 82 __asm__ __volatile__ ( |
76 #if defined(MY_CPU_AMD64) | 83 #if defined(MY_CPU_AMD64) |
77 | |
78 __asm__ __volatile__ ( | |
79 "mov %%rbx, %%rdi\n" | 84 "mov %%rbx, %%rdi\n" |
80 "cpuid\n" | 85 "cpuid\n" |
81 "xchg %%rdi, %%rbx\n" | 86 "xchg %%rdi, %%rbx\n" |
82 : "=a" (*a) , | 87 : "=a" (*a) , |
83 "=D" (*b) , | 88 "=D" (*b) , |
84 "=c" (*c) , | 89 #elif defined(MY_CPU_X86) && defined(__PIC__) |
85 "=d" (*d) | 90 "mov %%ebx, %%edi;" |
86 : "0" (function)) ; | 91 "cpuid;" |
87 | 92 "xchgl %%ebx, %%edi;" |
88 #else | |
89 | |
90 __asm__ __volatile__ ( | |
91 "mov %%ebx, %%edi\n" | |
92 "cpuid\n" | |
93 "xchg %%edi, %%ebx\n" | |
94 : "=a" (*a) , | 93 : "=a" (*a) , |
95 "=D" (*b) , | 94 "=D" (*b) , |
| 95 #else |
| 96 "cpuid" |
| 97 : "=a" (*a) , |
| 98 "=b" (*b) , |
| 99 #endif |
96 "=c" (*c) , | 100 "=c" (*c) , |
97 "=d" (*d) | 101 "=d" (*d) |
98 : "0" (function)) ; | 102 : "0" (function)) ; |
99 | 103 |
100 #endif | 104 #endif |
101 | |
102 #endif | |
103 | 105 |
104 #else | 106 #else |
105 | 107 |
106 int CPUInfo[4]; | 108 int CPUInfo[4]; |
107 __cpuid(CPUInfo, function); | 109 __cpuid(CPUInfo, function); |
108 *a = CPUInfo[0]; | 110 *a = CPUInfo[0]; |
109 *b = CPUInfo[1]; | 111 *b = CPUInfo[1]; |
110 *c = CPUInfo[2]; | 112 *c = CPUInfo[2]; |
111 *d = CPUInfo[3]; | 113 *d = CPUInfo[3]; |
112 | 114 |
113 #endif | 115 #endif |
114 } | 116 } |
115 | 117 |
116 Bool x86cpuid_CheckAndRead(Cx86cpuid *p) | 118 Bool x86cpuid_CheckAndRead(Cx86cpuid *p) |
117 { | 119 { |
118 CHECK_CPUID_IS_SUPPORTED | 120 CHECK_CPUID_IS_SUPPORTED |
119 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); | 121 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); |
120 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); | 122 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); |
121 return True; | 123 return True; |
122 } | 124 } |
123 | 125 |
124 static UInt32 kVendors[][3] = | 126 static const UInt32 kVendors[][3] = |
125 { | 127 { |
126 { 0x756E6547, 0x49656E69, 0x6C65746E}, | 128 { 0x756E6547, 0x49656E69, 0x6C65746E}, |
127 { 0x68747541, 0x69746E65, 0x444D4163}, | 129 { 0x68747541, 0x69746E65, 0x444D4163}, |
128 { 0x746E6543, 0x48727561, 0x736C7561} | 130 { 0x746E6543, 0x48727561, 0x736C7561} |
129 }; | 131 }; |
130 | 132 |
131 int x86cpuid_GetFirm(const Cx86cpuid *p) | 133 int x86cpuid_GetFirm(const Cx86cpuid *p) |
132 { | 134 { |
133 unsigned i; | 135 unsigned i; |
134 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) | 136 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) |
135 { | 137 { |
136 const UInt32 *v = kVendors[i]; | 138 const UInt32 *v = kVendors[i]; |
137 if (v[0] == p->vendor[0] && | 139 if (v[0] == p->vendor[0] && |
138 v[1] == p->vendor[1] && | 140 v[1] == p->vendor[1] && |
139 v[2] == p->vendor[2]) | 141 v[2] == p->vendor[2]) |
140 return (int)i; | 142 return (int)i; |
141 } | 143 } |
142 return -1; | 144 return -1; |
143 } | 145 } |
144 | 146 |
145 Bool CPU_Is_InOrder() | 147 Bool CPU_Is_InOrder() |
146 { | 148 { |
147 Cx86cpuid p; | 149 Cx86cpuid p; |
148 int firm; | 150 int firm; |
149 UInt32 family, model; | 151 UInt32 family, model; |
150 if (!x86cpuid_CheckAndRead(&p)) | 152 if (!x86cpuid_CheckAndRead(&p)) |
151 return True; | 153 return True; |
152 family = x86cpuid_GetFamily(&p); | 154 |
153 model = x86cpuid_GetModel(&p); | 155 family = x86cpuid_GetFamily(p.ver); |
| 156 model = x86cpuid_GetModel(p.ver); |
| 157 |
154 firm = x86cpuid_GetFirm(&p); | 158 firm = x86cpuid_GetFirm(&p); |
| 159 |
155 switch (firm) | 160 switch (firm) |
156 { | 161 { |
157 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C))
; | 162 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( |
| 163 /* In-Order Atom CPU */ |
| 164 model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ |
| 165 || model == 0x26 /* 45 nm, Z6xx */ |
| 166 || model == 0x27 /* 32 nm, Z2460 */ |
| 167 || model == 0x35 /* 32 nm, Z2760 */ |
| 168 || model == 0x36 /* 32 nm, N2xxx, D2xxx */ |
| 169 ))); |
158 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model
== 0xA))); | 170 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model
== 0xA))); |
159 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); | 171 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); |
160 } | 172 } |
161 return True; | 173 return True; |
162 } | 174 } |
163 | 175 |
164 #if !defined(MY_CPU_AMD64) && defined(_WIN32) | 176 #if !defined(MY_CPU_AMD64) && defined(_WIN32) |
| 177 #include <windows.h> |
165 static Bool CPU_Sys_Is_SSE_Supported() | 178 static Bool CPU_Sys_Is_SSE_Supported() |
166 { | 179 { |
167 OSVERSIONINFO vi; | 180 OSVERSIONINFO vi; |
168 vi.dwOSVersionInfoSize = sizeof(vi); | 181 vi.dwOSVersionInfoSize = sizeof(vi); |
169 if (!GetVersionEx(&vi)) | 182 if (!GetVersionEx(&vi)) |
170 return False; | 183 return False; |
171 return (vi.dwMajorVersion >= 5); | 184 return (vi.dwMajorVersion >= 5); |
172 } | 185 } |
173 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; | 186 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; |
174 #else | 187 #else |
175 #define CHECK_SYS_SSE_SUPPORT | 188 #define CHECK_SYS_SSE_SUPPORT |
176 #endif | 189 #endif |
177 | 190 |
178 Bool CPU_Is_Aes_Supported() | 191 Bool CPU_Is_Aes_Supported() |
179 { | 192 { |
180 Cx86cpuid p; | 193 Cx86cpuid p; |
181 CHECK_SYS_SSE_SUPPORT | 194 CHECK_SYS_SSE_SUPPORT |
182 if (!x86cpuid_CheckAndRead(&p)) | 195 if (!x86cpuid_CheckAndRead(&p)) |
183 return False; | 196 return False; |
184 return (p.c >> 25) & 1; | 197 return (p.c >> 25) & 1; |
185 } | 198 } |
186 | 199 |
187 #endif | 200 #endif |
OLD | NEW |