src/third-party/lzma/CpuArch.c (view raw)
1/* CpuArch.c -- CPU specific code
22018-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)
19static 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
58void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
59{
60 #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 __asm__ __volatile__ (
83 #if defined(MY_CPU_AMD64) && defined(__PIC__)
84 "mov %%rbx, %%rdi;"
85 "cpuid;"
86 "xchg %%rbx, %%rdi;"
87 : "=a" (*a) ,
88 "=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 "=c" (*c) ,
101 "=d" (*d)
102 : "0" (function)) ;
103
104 #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}
117
118BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
119{
120 CHECK_CPUID_IS_SUPPORTED
121 MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
122 MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
123 return True;
124}
125
126static const UInt32 kVendors[][3] =
127{
128 { 0x756E6547, 0x49656E69, 0x6C65746E},
129 { 0x68747541, 0x69746E65, 0x444D4163},
130 { 0x746E6543, 0x48727561, 0x736C7561}
131};
132
133int x86cpuid_GetFirm(const Cx86cpuid *p)
134{
135 unsigned i;
136 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
137 {
138 const UInt32 *v = kVendors[i];
139 if (v[0] == p->vendor[0] &&
140 v[1] == p->vendor[1] &&
141 v[2] == p->vendor[2])
142 return (int)i;
143 }
144 return -1;
145}
146
147BoolInt CPU_Is_InOrder()
148{
149 Cx86cpuid p;
150 int firm;
151 UInt32 family, model;
152 if (!x86cpuid_CheckAndRead(&p))
153 return True;
154
155 family = x86cpuid_GetFamily(p.ver);
156 model = x86cpuid_GetModel(p.ver);
157
158 firm = x86cpuid_GetFirm(&p);
159
160 switch (firm)
161 {
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 )));
170 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
171 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
172 }
173 return True;
174}
175
176#if !defined(MY_CPU_AMD64) && defined(_WIN32)
177#include <windows.h>
178static 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
191BoolInt CPU_Is_Aes_Supported()
192{
193 Cx86cpuid p;
194 CHECK_SYS_SSE_SUPPORT
195 if (!x86cpuid_CheckAndRead(&p))
196 return False;
197 return (p.c >> 25) & 1;
198}
199
200BoolInt CPU_IsSupported_PageGB()
201{
202 Cx86cpuid cpuid;
203 if (!x86cpuid_CheckAndRead(&cpuid))
204 return False;
205 {
206 UInt32 d[4] = { 0 };
207 MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
208 if (d[0] < 0x80000001)
209 return False;
210 }
211 {
212 UInt32 d[4] = { 0 };
213 MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
214 return (d[3] >> 26) & 1;
215 }
216}
217
218#endif