[go: nahoru, domu]

blob: 7cd1ea88de9a0fcf2830b8c5348ff4ec6d911ff9 [file] [log] [blame]
waffles@chromium.org52847df12013-07-19 02:10:2111,168c1,187
waffles@chromium.orgf6820ba92013-06-17 20:33:112< /* 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<
waffles@chromium.orgf6820ba92013-06-17 20:33:1176< __asm__ __volatile__ (
waffles@chromium.org52847df12013-07-19 02:10:2177< "cpuid"
waffles@chromium.orgf6820ba92013-06-17 20:33:1178< : "=a" (*a) ,
waffles@chromium.org52847df12013-07-19 02:10:2179< "=b" (*b) ,
waffles@chromium.orgf6820ba92013-06-17 20:33:1180< "=c" (*c) ,
81< "=d" (*d)
82< : "0" (function)) ;
waffles@chromium.orgf6820ba92013-06-17 20:33:1183<
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
scottmg@chromium.org234aab22013-06-14 04:07:59170---
waffles@chromium.orgf6820ba92013-06-17 20:33:11171> /* 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":
waffles@chromium.org52847df12013-07-19 02:10:21212> "=c" (flag) : "c" (flag):
213> "%eax", "%edx" );
waffles@chromium.orgf6820ba92013-06-17 20:33:11214> #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>
waffles@chromium.org52847df12013-07-19 02:10:21246> #if defined(MY_CPU_AMD64)
247>
waffles@chromium.orgf6820ba92013-06-17 20:33:11248> __asm__ __volatile__ (
waffles@chromium.org52847df12013-07-19 02:10:21249> "mov %%rbx, %%rdi\n"
250> "cpuid\n"
251> "xchg %%rdi, %%rbx\n"
waffles@chromium.orgf6820ba92013-06-17 20:33:11252> : "=a" (*a) ,
waffles@chromium.org52847df12013-07-19 02:10:21253> "=D" (*b) ,
waffles@chromium.orgf6820ba92013-06-17 20:33:11254> "=c" (*c) ,
255> "=d" (*d)
256> : "0" (function)) ;
257>
waffles@chromium.org52847df12013-07-19 02:10:21258> #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>
waffles@chromium.orgf6820ba92013-06-17 20:33:11272> #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