/src/lzma-fuzz/sdk/C/CpuArch.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* CpuArch.c -- CPU specific code |
2 | | 2018-02-18: 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 <intrin.h> |
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 | | "%eax", "%edx"); |
50 | | #endif |
51 | | return flag; |
52 | | } |
53 | | #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; |
54 | | #else |
55 | | #define CHECK_CPUID_IS_SUPPORTED |
56 | | #endif |
57 | | |
58 | | void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) |
59 | 9.80k | { |
60 | 9.80k | #ifdef USE_ASM |
61 | | |
62 | | #ifdef _MSC_VER |
63 | | |
64 | | UInt32 a2, b2, c2, d2; |
65 | | __asm xor EBX, EBX; |
66 | | __asm xor ECX, ECX; |
67 | | __asm xor EDX, EDX; |
68 | | __asm mov EAX, function; |
69 | | __asm cpuid; |
70 | | __asm mov a2, EAX; |
71 | | __asm mov b2, EBX; |
72 | | __asm mov c2, ECX; |
73 | | __asm mov d2, EDX; |
74 | | |
75 | | *a = a2; |
76 | | *b = b2; |
77 | | *c = c2; |
78 | | *d = d2; |
79 | | |
80 | | #else |
81 | | |
82 | 9.80k | __asm__ __volatile__ ( |
83 | 9.80k | #if defined(MY_CPU_AMD64) && defined(__PIC__) |
84 | 9.80k | "mov %%rbx, %%rdi;" |
85 | 9.80k | "cpuid;" |
86 | 9.80k | "xchg %%rbx, %%rdi;" |
87 | 9.80k | : "=a" (*a) , |
88 | 9.80k | "=D" (*b) , |
89 | | #elif defined(MY_CPU_X86) && defined(__PIC__) |
90 | | "mov %%ebx, %%edi;" |
91 | | "cpuid;" |
92 | | "xchgl %%ebx, %%edi;" |
93 | | : "=a" (*a) , |
94 | | "=D" (*b) , |
95 | | #else |
96 | | "cpuid" |
97 | | : "=a" (*a) , |
98 | | "=b" (*b) , |
99 | | #endif |
100 | 9.80k | "=c" (*c) , |
101 | 9.80k | "=d" (*d) |
102 | 9.80k | : "0" (function)) ; |
103 | | |
104 | 9.80k | #endif |
105 | | |
106 | | #else |
107 | | |
108 | | int CPUInfo[4]; |
109 | | __cpuid(CPUInfo, function); |
110 | | *a = CPUInfo[0]; |
111 | | *b = CPUInfo[1]; |
112 | | *c = CPUInfo[2]; |
113 | | *d = CPUInfo[3]; |
114 | | |
115 | | #endif |
116 | 9.80k | } |
117 | | |
118 | | BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p) |
119 | 4.90k | { |
120 | 4.90k | CHECK_CPUID_IS_SUPPORTED |
121 | 4.90k | MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); |
122 | 4.90k | MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); |
123 | 4.90k | return True; |
124 | 4.90k | } |
125 | | |
126 | | static const UInt32 kVendors[][3] = |
127 | | { |
128 | | { 0x756E6547, 0x49656E69, 0x6C65746E}, |
129 | | { 0x68747541, 0x69746E65, 0x444D4163}, |
130 | | { 0x746E6543, 0x48727561, 0x736C7561} |
131 | | }; |
132 | | |
133 | | int x86cpuid_GetFirm(const Cx86cpuid *p) |
134 | 4.90k | { |
135 | 4.90k | unsigned i; |
136 | 4.90k | for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) |
137 | 4.90k | { |
138 | 4.90k | const UInt32 *v = kVendors[i]; |
139 | 4.90k | if (v[0] == p->vendor[0] && |
140 | 4.90k | v[1] == p->vendor[1] && |
141 | 4.90k | v[2] == p->vendor[2]) |
142 | 4.90k | return (int)i; |
143 | 4.90k | } |
144 | 0 | return -1; |
145 | 4.90k | } |
146 | | |
147 | | BoolInt CPU_Is_InOrder() |
148 | 4.90k | { |
149 | 4.90k | Cx86cpuid p; |
150 | 4.90k | int firm; |
151 | 4.90k | UInt32 family, model; |
152 | 4.90k | if (!x86cpuid_CheckAndRead(&p)) |
153 | 0 | return True; |
154 | | |
155 | 4.90k | family = x86cpuid_GetFamily(p.ver); |
156 | 4.90k | model = x86cpuid_GetModel(p.ver); |
157 | | |
158 | 4.90k | firm = x86cpuid_GetFirm(&p); |
159 | | |
160 | 4.90k | switch (firm) |
161 | 4.90k | { |
162 | 4.90k | case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( |
163 | | /* In-Order Atom CPU */ |
164 | 4.90k | model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ |
165 | 4.90k | || model == 0x26 /* 45 nm, Z6xx */ |
166 | 4.90k | || model == 0x27 /* 32 nm, Z2460 */ |
167 | 4.90k | || model == 0x35 /* 32 nm, Z2760 */ |
168 | 4.90k | || model == 0x36 /* 32 nm, N2xxx, D2xxx */ |
169 | 4.90k | ))); |
170 | 0 | case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); |
171 | 0 | case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); |
172 | 4.90k | } |
173 | 0 | return True; |
174 | 4.90k | } |
175 | | |
176 | | #if !defined(MY_CPU_AMD64) && defined(_WIN32) |
177 | | #include <windows.h> |
178 | | static BoolInt CPU_Sys_Is_SSE_Supported() |
179 | | { |
180 | | OSVERSIONINFO vi; |
181 | | vi.dwOSVersionInfoSize = sizeof(vi); |
182 | | if (!GetVersionEx(&vi)) |
183 | | return False; |
184 | | return (vi.dwMajorVersion >= 5); |
185 | | } |
186 | | #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; |
187 | | #else |
188 | | #define CHECK_SYS_SSE_SUPPORT |
189 | | #endif |
190 | | |
191 | | BoolInt CPU_Is_Aes_Supported() |
192 | 0 | { |
193 | 0 | Cx86cpuid p; |
194 | 0 | CHECK_SYS_SSE_SUPPORT |
195 | 0 | if (!x86cpuid_CheckAndRead(&p)) |
196 | 0 | return False; |
197 | 0 | return (p.c >> 25) & 1; |
198 | 0 | } |
199 | | |
200 | | BoolInt CPU_IsSupported_PageGB() |
201 | 0 | { |
202 | 0 | Cx86cpuid cpuid; |
203 | 0 | if (!x86cpuid_CheckAndRead(&cpuid)) |
204 | 0 | return False; |
205 | 0 | { |
206 | 0 | UInt32 d[4] = { 0 }; |
207 | 0 | MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]); |
208 | 0 | if (d[0] < 0x80000001) |
209 | 0 | return False; |
210 | 0 | } |
211 | 0 | { |
212 | 0 | UInt32 d[4] = { 0 }; |
213 | 0 | MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]); |
214 | 0 | return (d[3] >> 26) & 1; |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | #endif |