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