• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
11,168c1,187
2< /* CpuArch.c -- CPU specific code
3< 2010-10-26: Igor Pavlov : Public domain */
4<
5< #include "CpuArch.h"
6<
7< #ifdef MY_CPU_X86_OR_AMD64
8<
9< #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
10< #define USE_ASM
11< #endif
12<
13< #if defined(USE_ASM) && !defined(MY_CPU_AMD64)
14< static UInt32 CheckFlag(UInt32 flag)
15< {
16<   #ifdef _MSC_VER
17<   __asm pushfd;
18<   __asm pop EAX;
19<   __asm mov EDX, EAX;
20<   __asm xor EAX, flag;
21<   __asm push EAX;
22<   __asm popfd;
23<   __asm pushfd;
24<   __asm pop EAX;
25<   __asm xor EAX, EDX;
26<   __asm push EDX;
27<   __asm popfd;
28<   __asm and flag, EAX;
29<   #else
30<   __asm__ __volatile__ (
31<     "pushf\n\t"
32<     "pop  %%EAX\n\t"
33<     "movl %%EAX,%%EDX\n\t"
34<     "xorl %0,%%EAX\n\t"
35<     "push %%EAX\n\t"
36<     "popf\n\t"
37<     "pushf\n\t"
38<     "pop  %%EAX\n\t"
39<     "xorl %%EDX,%%EAX\n\t"
40<     "push %%EDX\n\t"
41<     "popf\n\t"
42<     "andl %%EAX, %0\n\t":
43<     "=c" (flag) : "c" (flag));
44<   #endif
45<   return flag;
46< }
47< #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
48< #else
49< #define CHECK_CPUID_IS_SUPPORTED
50< #endif
51<
52< static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
53< {
54<   #ifdef USE_ASM
55<
56<   #ifdef _MSC_VER
57<
58<   UInt32 a2, b2, c2, d2;
59<   __asm xor EBX, EBX;
60<   __asm xor ECX, ECX;
61<   __asm xor EDX, EDX;
62<   __asm mov EAX, function;
63<   __asm cpuid;
64<   __asm mov a2, EAX;
65<   __asm mov b2, EBX;
66<   __asm mov c2, ECX;
67<   __asm mov d2, EDX;
68<
69<   *a = a2;
70<   *b = b2;
71<   *c = c2;
72<   *d = d2;
73<
74<   #else
75<
76<   __asm__ __volatile__ (
77<     "cpuid"
78<     : "=a" (*a) ,
79<       "=b" (*b) ,
80<       "=c" (*c) ,
81<       "=d" (*d)
82<     : "0" (function)) ;
83<
84<   #endif
85<
86<   #else
87<
88<   int CPUInfo[4];
89<   __cpuid(CPUInfo, function);
90<   *a = CPUInfo[0];
91<   *b = CPUInfo[1];
92<   *c = CPUInfo[2];
93<   *d = CPUInfo[3];
94<
95<   #endif
96< }
97<
98< Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
99< {
100<   CHECK_CPUID_IS_SUPPORTED
101<   MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
102<   MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
103<   return True;
104< }
105<
106< static UInt32 kVendors[][3] =
107< {
108<   { 0x756E6547, 0x49656E69, 0x6C65746E},
109<   { 0x68747541, 0x69746E65, 0x444D4163},
110<   { 0x746E6543, 0x48727561, 0x736C7561}
111< };
112<
113< int x86cpuid_GetFirm(const Cx86cpuid *p)
114< {
115<   unsigned i;
116<   for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
117<   {
118<     const UInt32 *v = kVendors[i];
119<     if (v[0] == p->vendor[0] &&
120<         v[1] == p->vendor[1] &&
121<         v[2] == p->vendor[2])
122<       return (int)i;
123<   }
124<   return -1;
125< }
126<
127< Bool CPU_Is_InOrder()
128< {
129<   Cx86cpuid p;
130<   int firm;
131<   UInt32 family, model;
132<   if (!x86cpuid_CheckAndRead(&p))
133<     return True;
134<   family = x86cpuid_GetFamily(&p);
135<   model = x86cpuid_GetModel(&p);
136<   firm = x86cpuid_GetFirm(&p);
137<   switch (firm)
138<   {
139<     case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
140<     case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
141<     case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
142<   }
143<   return True;
144< }
145<
146< #if !defined(MY_CPU_AMD64) && defined(_WIN32)
147< static Bool CPU_Sys_Is_SSE_Supported()
148< {
149<   OSVERSIONINFO vi;
150<   vi.dwOSVersionInfoSize = sizeof(vi);
151<   if (!GetVersionEx(&vi))
152<     return False;
153<   return (vi.dwMajorVersion >= 5);
154< }
155< #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
156< #else
157< #define CHECK_SYS_SSE_SUPPORT
158< #endif
159<
160< Bool CPU_Is_Aes_Supported()
161< {
162<   Cx86cpuid p;
163<   CHECK_SYS_SSE_SUPPORT
164<   if (!x86cpuid_CheckAndRead(&p))
165<     return False;
166<   return (p.c >> 25) & 1;
167< }
168<
169< #endif
170---
171> /* CpuArch.c -- CPU specific code
172> 2010-10-26: Igor Pavlov : Public domain */
173>
174> #include "CpuArch.h"
175>
176> #ifdef MY_CPU_X86_OR_AMD64
177>
178> #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
179> #define USE_ASM
180> #endif
181>
182> #if defined(USE_ASM) && !defined(MY_CPU_AMD64)
183> static UInt32 CheckFlag(UInt32 flag)
184> {
185>   #ifdef _MSC_VER
186>   __asm pushfd;
187>   __asm pop EAX;
188>   __asm mov EDX, EAX;
189>   __asm xor EAX, flag;
190>   __asm push EAX;
191>   __asm popfd;
192>   __asm pushfd;
193>   __asm pop EAX;
194>   __asm xor EAX, EDX;
195>   __asm push EDX;
196>   __asm popfd;
197>   __asm and flag, EAX;
198>   #else
199>   __asm__ __volatile__ (
200>     "pushf\n\t"
201>     "pop  %%EAX\n\t"
202>     "movl %%EAX,%%EDX\n\t"
203>     "xorl %0,%%EAX\n\t"
204>     "push %%EAX\n\t"
205>     "popf\n\t"
206>     "pushf\n\t"
207>     "pop  %%EAX\n\t"
208>     "xorl %%EDX,%%EAX\n\t"
209>     "push %%EDX\n\t"
210>     "popf\n\t"
211>     "andl %%EAX, %0\n\t":
212>     "=c" (flag) : "c" (flag):
213>     "%eax", "%edx" );
214>   #endif
215>   return flag;
216> }
217> #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
218> #else
219> #define CHECK_CPUID_IS_SUPPORTED
220> #endif
221>
222> static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
223> {
224>   #ifdef USE_ASM
225>
226>   #ifdef _MSC_VER
227>
228>   UInt32 a2, b2, c2, d2;
229>   __asm xor EBX, EBX;
230>   __asm xor ECX, ECX;
231>   __asm xor EDX, EDX;
232>   __asm mov EAX, function;
233>   __asm cpuid;
234>   __asm mov a2, EAX;
235>   __asm mov b2, EBX;
236>   __asm mov c2, ECX;
237>   __asm mov d2, EDX;
238>
239>   *a = a2;
240>   *b = b2;
241>   *c = c2;
242>   *d = d2;
243>
244>   #else
245>
246>   #if defined(MY_CPU_AMD64)
247>
248>   __asm__ __volatile__ (
249>     "mov %%rbx, %%rdi\n"
250>     "cpuid\n"
251>     "xchg %%rdi, %%rbx\n"
252>     : "=a" (*a) ,
253>       "=D" (*b) ,
254>       "=c" (*c) ,
255>       "=d" (*d)
256>     : "0" (function)) ;
257>
258>   #else
259>
260>   __asm__ __volatile__ (
261>     "mov %%ebx, %%edi\n"
262>     "cpuid\n"
263>     "xchg %%edi, %%ebx\n"
264>     : "=a" (*a) ,
265>       "=D" (*b) ,
266>       "=c" (*c) ,
267>       "=d" (*d)
268>     : "0" (function)) ;
269>
270>   #endif
271>
272>   #endif
273>
274>   #else
275>
276>   int CPUInfo[4];
277>   __cpuid(CPUInfo, function);
278>   *a = CPUInfo[0];
279>   *b = CPUInfo[1];
280>   *c = CPUInfo[2];
281>   *d = CPUInfo[3];
282>
283>   #endif
284> }
285>
286> Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
287> {
288>   CHECK_CPUID_IS_SUPPORTED
289>   MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
290>   MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
291>   return True;
292> }
293>
294> static UInt32 kVendors[][3] =
295> {
296>   { 0x756E6547, 0x49656E69, 0x6C65746E},
297>   { 0x68747541, 0x69746E65, 0x444D4163},
298>   { 0x746E6543, 0x48727561, 0x736C7561}
299> };
300>
301> int x86cpuid_GetFirm(const Cx86cpuid *p)
302> {
303>   unsigned i;
304>   for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
305>   {
306>     const UInt32 *v = kVendors[i];
307>     if (v[0] == p->vendor[0] &&
308>         v[1] == p->vendor[1] &&
309>         v[2] == p->vendor[2])
310>       return (int)i;
311>   }
312>   return -1;
313> }
314>
315> Bool CPU_Is_InOrder()
316> {
317>   Cx86cpuid p;
318>   int firm;
319>   UInt32 family, model;
320>   if (!x86cpuid_CheckAndRead(&p))
321>     return True;
322>   family = x86cpuid_GetFamily(&p);
323>   model = x86cpuid_GetModel(&p);
324>   firm = x86cpuid_GetFirm(&p);
325>   switch (firm)
326>   {
327>     case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
328>     case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
329>     case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
330>   }
331>   return True;
332> }
333>
334> #if !defined(MY_CPU_AMD64) && defined(_WIN32)
335> static Bool CPU_Sys_Is_SSE_Supported()
336> {
337>   OSVERSIONINFO vi;
338>   vi.dwOSVersionInfoSize = sizeof(vi);
339>   if (!GetVersionEx(&vi))
340>     return False;
341>   return (vi.dwMajorVersion >= 5);
342> }
343> #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
344> #else
345> #define CHECK_SYS_SSE_SUPPORT
346> #endif
347>
348> Bool CPU_Is_Aes_Supported()
349> {
350>   Cx86cpuid p;
351>   CHECK_SYS_SSE_SUPPORT
352>   if (!x86cpuid_CheckAndRead(&p))
353>     return False;
354>   return (p.c >> 25) & 1;
355> }
356>
357> #endif
358