1*f6dc9357SAndroid Build Coastguard Worker /* CpuArch.c -- CPU specific code
2*f6dc9357SAndroid Build Coastguard Worker Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker
6*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_X86_OR_AMD64
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #undef NEED_CHECK_FOR_CPUID
13*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_AMD64)
14*f6dc9357SAndroid Build Coastguard Worker #define NEED_CHECK_FOR_CPUID
15*f6dc9357SAndroid Build Coastguard Worker #endif
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker /*
18*f6dc9357SAndroid Build Coastguard Worker cpuid instruction supports (subFunction) parameter in ECX,
19*f6dc9357SAndroid Build Coastguard Worker that is used only with some specific (function) parameter values.
20*f6dc9357SAndroid Build Coastguard Worker most functions use only (subFunction==0).
21*f6dc9357SAndroid Build Coastguard Worker */
22*f6dc9357SAndroid Build Coastguard Worker /*
23*f6dc9357SAndroid Build Coastguard Worker __cpuid(): MSVC and GCC/CLANG use same function/macro name
24*f6dc9357SAndroid Build Coastguard Worker but parameters are different.
25*f6dc9357SAndroid Build Coastguard Worker We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function.
26*f6dc9357SAndroid Build Coastguard Worker */
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \
29*f6dc9357SAndroid Build Coastguard Worker || defined(__clang__) /* && (__clang_major__ >= 10) */
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker /* there was some CLANG/GCC compilers that have issues with
32*f6dc9357SAndroid Build Coastguard Worker rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined).
33*f6dc9357SAndroid Build Coastguard Worker compiler's <cpuid.h> contains the macro __cpuid() that is similar to our code.
34*f6dc9357SAndroid Build Coastguard Worker The history of __cpuid() changes in CLANG/GCC:
35*f6dc9357SAndroid Build Coastguard Worker GCC:
36*f6dc9357SAndroid Build Coastguard Worker 2007: it preserved ebx for (__PIC__ && __i386__)
37*f6dc9357SAndroid Build Coastguard Worker 2013: it preserved rbx and ebx for __PIC__
38*f6dc9357SAndroid Build Coastguard Worker 2014: it doesn't preserves rbx and ebx anymore
39*f6dc9357SAndroid Build Coastguard Worker we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem.
40*f6dc9357SAndroid Build Coastguard Worker CLANG:
41*f6dc9357SAndroid Build Coastguard Worker 2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check.
42*f6dc9357SAndroid Build Coastguard Worker Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)?
43*f6dc9357SAndroid Build Coastguard Worker Do we need __PIC__ test for CLANG or we must care about rbx even if
44*f6dc9357SAndroid Build Coastguard Worker __PIC__ is not defined?
45*f6dc9357SAndroid Build Coastguard Worker */
46*f6dc9357SAndroid Build Coastguard Worker
47*f6dc9357SAndroid Build Coastguard Worker #define ASM_LN "\n"
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_AMD64) && defined(__PIC__) \
50*f6dc9357SAndroid Build Coastguard Worker && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker /* "=&r" selects free register. It can select even rbx, if that register is free.
53*f6dc9357SAndroid Build Coastguard Worker "=&D" for (RDI) also works, but the code can be larger with "=&D"
54*f6dc9357SAndroid Build Coastguard Worker "2"(subFun) : 2 is (zero-based) index in the output constraint list "=c" (ECX). */
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker #define x86_cpuid_MACRO_2(p, func, subFunc) { \
57*f6dc9357SAndroid Build Coastguard Worker __asm__ __volatile__ ( \
58*f6dc9357SAndroid Build Coastguard Worker ASM_LN "mov %%rbx, %q1" \
59*f6dc9357SAndroid Build Coastguard Worker ASM_LN "cpuid" \
60*f6dc9357SAndroid Build Coastguard Worker ASM_LN "xchg %%rbx, %q1" \
61*f6dc9357SAndroid Build Coastguard Worker : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker #elif defined(MY_CPU_X86) && defined(__PIC__) \
64*f6dc9357SAndroid Build Coastguard Worker && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
65*f6dc9357SAndroid Build Coastguard Worker
66*f6dc9357SAndroid Build Coastguard Worker #define x86_cpuid_MACRO_2(p, func, subFunc) { \
67*f6dc9357SAndroid Build Coastguard Worker __asm__ __volatile__ ( \
68*f6dc9357SAndroid Build Coastguard Worker ASM_LN "mov %%ebx, %k1" \
69*f6dc9357SAndroid Build Coastguard Worker ASM_LN "cpuid" \
70*f6dc9357SAndroid Build Coastguard Worker ASM_LN "xchg %%ebx, %k1" \
71*f6dc9357SAndroid Build Coastguard Worker : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
72*f6dc9357SAndroid Build Coastguard Worker
73*f6dc9357SAndroid Build Coastguard Worker #else
74*f6dc9357SAndroid Build Coastguard Worker
75*f6dc9357SAndroid Build Coastguard Worker #define x86_cpuid_MACRO_2(p, func, subFunc) { \
76*f6dc9357SAndroid Build Coastguard Worker __asm__ __volatile__ ( \
77*f6dc9357SAndroid Build Coastguard Worker ASM_LN "cpuid" \
78*f6dc9357SAndroid Build Coastguard Worker : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(subFunc)); }
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker #endif
81*f6dc9357SAndroid Build Coastguard Worker
82*f6dc9357SAndroid Build Coastguard Worker #define x86_cpuid_MACRO(p, func) x86_cpuid_MACRO_2(p, func, 0)
83*f6dc9357SAndroid Build Coastguard Worker
z7_x86_cpuid(UInt32 p[4],UInt32 func)84*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
85*f6dc9357SAndroid Build Coastguard Worker {
86*f6dc9357SAndroid Build Coastguard Worker x86_cpuid_MACRO(p, func)
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker
89*f6dc9357SAndroid Build Coastguard Worker static
z7_x86_cpuid_subFunc(UInt32 p[4],UInt32 func,UInt32 subFunc)90*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker x86_cpuid_MACRO_2(p, func, subFunc)
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
z7_x86_cpuid_GetMaxFunc(void)97*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker #if defined(NEED_CHECK_FOR_CPUID)
100*f6dc9357SAndroid Build Coastguard Worker #define EFALGS_CPUID_BIT 21
101*f6dc9357SAndroid Build Coastguard Worker UInt32 a;
102*f6dc9357SAndroid Build Coastguard Worker __asm__ __volatile__ (
103*f6dc9357SAndroid Build Coastguard Worker ASM_LN "pushf"
104*f6dc9357SAndroid Build Coastguard Worker ASM_LN "pushf"
105*f6dc9357SAndroid Build Coastguard Worker ASM_LN "pop %0"
106*f6dc9357SAndroid Build Coastguard Worker // ASM_LN "movl %0, %1"
107*f6dc9357SAndroid Build Coastguard Worker // ASM_LN "xorl $0x200000, %0"
108*f6dc9357SAndroid Build Coastguard Worker ASM_LN "btc %1, %0"
109*f6dc9357SAndroid Build Coastguard Worker ASM_LN "push %0"
110*f6dc9357SAndroid Build Coastguard Worker ASM_LN "popf"
111*f6dc9357SAndroid Build Coastguard Worker ASM_LN "pushf"
112*f6dc9357SAndroid Build Coastguard Worker ASM_LN "pop %0"
113*f6dc9357SAndroid Build Coastguard Worker ASM_LN "xorl (%%esp), %0"
114*f6dc9357SAndroid Build Coastguard Worker
115*f6dc9357SAndroid Build Coastguard Worker ASM_LN "popf"
116*f6dc9357SAndroid Build Coastguard Worker ASM_LN
117*f6dc9357SAndroid Build Coastguard Worker : "=&r" (a) // "=a"
118*f6dc9357SAndroid Build Coastguard Worker : "i" (EFALGS_CPUID_BIT)
119*f6dc9357SAndroid Build Coastguard Worker );
120*f6dc9357SAndroid Build Coastguard Worker if ((a & (1 << EFALGS_CPUID_BIT)) == 0)
121*f6dc9357SAndroid Build Coastguard Worker return 0;
122*f6dc9357SAndroid Build Coastguard Worker #endif
123*f6dc9357SAndroid Build Coastguard Worker {
124*f6dc9357SAndroid Build Coastguard Worker UInt32 p[4];
125*f6dc9357SAndroid Build Coastguard Worker x86_cpuid_MACRO(p, 0)
126*f6dc9357SAndroid Build Coastguard Worker return p[0];
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker
130*f6dc9357SAndroid Build Coastguard Worker #undef ASM_LN
131*f6dc9357SAndroid Build Coastguard Worker
132*f6dc9357SAndroid Build Coastguard Worker #elif !defined(_MSC_VER)
133*f6dc9357SAndroid Build Coastguard Worker
134*f6dc9357SAndroid Build Coastguard Worker /*
135*f6dc9357SAndroid Build Coastguard Worker // for gcc/clang and other: we can try to use __cpuid macro:
136*f6dc9357SAndroid Build Coastguard Worker #include <cpuid.h>
137*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker __cpuid(func, p[0], p[1], p[2], p[3]);
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker return (UInt32)__get_cpuid_max(0, NULL);
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker */
146*f6dc9357SAndroid Build Coastguard Worker // for unsupported cpuid:
z7_x86_cpuid(UInt32 p[4],UInt32 func)147*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(func)
150*f6dc9357SAndroid Build Coastguard Worker p[0] = p[1] = p[2] = p[3] = 0;
151*f6dc9357SAndroid Build Coastguard Worker }
z7_x86_cpuid_GetMaxFunc(void)152*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker return 0;
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker
157*f6dc9357SAndroid Build Coastguard Worker #else // _MSC_VER
158*f6dc9357SAndroid Build Coastguard Worker
159*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_AMD64)
160*f6dc9357SAndroid Build Coastguard Worker
z7_x86_cpuid_GetMaxFunc(void)161*f6dc9357SAndroid Build Coastguard Worker UInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
162*f6dc9357SAndroid Build Coastguard Worker {
163*f6dc9357SAndroid Build Coastguard Worker #if defined(NEED_CHECK_FOR_CPUID)
164*f6dc9357SAndroid Build Coastguard Worker #define EFALGS_CPUID_BIT 21
165*f6dc9357SAndroid Build Coastguard Worker __asm pushfd
166*f6dc9357SAndroid Build Coastguard Worker __asm pushfd
167*f6dc9357SAndroid Build Coastguard Worker /*
168*f6dc9357SAndroid Build Coastguard Worker __asm pop eax
169*f6dc9357SAndroid Build Coastguard Worker // __asm mov edx, eax
170*f6dc9357SAndroid Build Coastguard Worker __asm btc eax, EFALGS_CPUID_BIT
171*f6dc9357SAndroid Build Coastguard Worker __asm push eax
172*f6dc9357SAndroid Build Coastguard Worker */
173*f6dc9357SAndroid Build Coastguard Worker __asm btc dword ptr [esp], EFALGS_CPUID_BIT
174*f6dc9357SAndroid Build Coastguard Worker __asm popfd
175*f6dc9357SAndroid Build Coastguard Worker __asm pushfd
176*f6dc9357SAndroid Build Coastguard Worker __asm pop eax
177*f6dc9357SAndroid Build Coastguard Worker // __asm xor eax, edx
178*f6dc9357SAndroid Build Coastguard Worker __asm xor eax, [esp]
179*f6dc9357SAndroid Build Coastguard Worker // __asm push edx
180*f6dc9357SAndroid Build Coastguard Worker __asm popfd
181*f6dc9357SAndroid Build Coastguard Worker __asm and eax, (1 shl EFALGS_CPUID_BIT)
182*f6dc9357SAndroid Build Coastguard Worker __asm jz end_func
183*f6dc9357SAndroid Build Coastguard Worker #endif
184*f6dc9357SAndroid Build Coastguard Worker __asm push ebx
185*f6dc9357SAndroid Build Coastguard Worker __asm xor eax, eax // func
186*f6dc9357SAndroid Build Coastguard Worker __asm xor ecx, ecx // subFunction (optional) for (func == 0)
187*f6dc9357SAndroid Build Coastguard Worker __asm cpuid
188*f6dc9357SAndroid Build Coastguard Worker __asm pop ebx
189*f6dc9357SAndroid Build Coastguard Worker #if defined(NEED_CHECK_FOR_CPUID)
190*f6dc9357SAndroid Build Coastguard Worker end_func:
191*f6dc9357SAndroid Build Coastguard Worker #endif
192*f6dc9357SAndroid Build Coastguard Worker __asm ret 0
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker
z7_x86_cpuid(UInt32 p[4],UInt32 func)195*f6dc9357SAndroid Build Coastguard Worker void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(p)
198*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(func)
199*f6dc9357SAndroid Build Coastguard Worker __asm push ebx
200*f6dc9357SAndroid Build Coastguard Worker __asm push edi
201*f6dc9357SAndroid Build Coastguard Worker __asm mov edi, ecx // p
202*f6dc9357SAndroid Build Coastguard Worker __asm mov eax, edx // func
203*f6dc9357SAndroid Build Coastguard Worker __asm xor ecx, ecx // subfunction (optional) for (func == 0)
204*f6dc9357SAndroid Build Coastguard Worker __asm cpuid
205*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi ], eax
206*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 4], ebx
207*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 8], ecx
208*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 12], edx
209*f6dc9357SAndroid Build Coastguard Worker __asm pop edi
210*f6dc9357SAndroid Build Coastguard Worker __asm pop ebx
211*f6dc9357SAndroid Build Coastguard Worker __asm ret 0
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker
214*f6dc9357SAndroid Build Coastguard Worker static
z7_x86_cpuid_subFunc(UInt32 p[4],UInt32 func,UInt32 subFunc)215*f6dc9357SAndroid Build Coastguard Worker void __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(p)
218*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(func)
219*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(subFunc)
220*f6dc9357SAndroid Build Coastguard Worker __asm push ebx
221*f6dc9357SAndroid Build Coastguard Worker __asm push edi
222*f6dc9357SAndroid Build Coastguard Worker __asm mov edi, ecx // p
223*f6dc9357SAndroid Build Coastguard Worker __asm mov eax, edx // func
224*f6dc9357SAndroid Build Coastguard Worker __asm mov ecx, [esp + 12] // subFunc
225*f6dc9357SAndroid Build Coastguard Worker __asm cpuid
226*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi ], eax
227*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 4], ebx
228*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 8], ecx
229*f6dc9357SAndroid Build Coastguard Worker __asm mov [edi + 12], edx
230*f6dc9357SAndroid Build Coastguard Worker __asm pop edi
231*f6dc9357SAndroid Build Coastguard Worker __asm pop ebx
232*f6dc9357SAndroid Build Coastguard Worker __asm ret 4
233*f6dc9357SAndroid Build Coastguard Worker }
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker #else // MY_CPU_AMD64
236*f6dc9357SAndroid Build Coastguard Worker
237*f6dc9357SAndroid Build Coastguard Worker #if _MSC_VER >= 1600
238*f6dc9357SAndroid Build Coastguard Worker #include <intrin.h>
239*f6dc9357SAndroid Build Coastguard Worker #define MY_cpuidex __cpuidex
240*f6dc9357SAndroid Build Coastguard Worker
241*f6dc9357SAndroid Build Coastguard Worker static
z7_x86_cpuid_subFunc(UInt32 p[4],UInt32 func,UInt32 subFunc)242*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
243*f6dc9357SAndroid Build Coastguard Worker {
244*f6dc9357SAndroid Build Coastguard Worker __cpuidex((int *)p, func, subFunc);
245*f6dc9357SAndroid Build Coastguard Worker }
246*f6dc9357SAndroid Build Coastguard Worker
247*f6dc9357SAndroid Build Coastguard Worker #else
248*f6dc9357SAndroid Build Coastguard Worker /*
249*f6dc9357SAndroid Build Coastguard Worker __cpuid (func == (0 or 7)) requires subfunction number in ECX.
250*f6dc9357SAndroid Build Coastguard Worker MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction.
251*f6dc9357SAndroid Build Coastguard Worker __cpuid() in new MSVC clears ECX.
252*f6dc9357SAndroid Build Coastguard Worker __cpuid() in old MSVC (14.00) x64 doesn't clear ECX
253*f6dc9357SAndroid Build Coastguard Worker We still can use __cpuid for low (func) values that don't require ECX,
254*f6dc9357SAndroid Build Coastguard Worker but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).
255*f6dc9357SAndroid Build Coastguard Worker So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
256*f6dc9357SAndroid Build Coastguard Worker where ECX value is first parameter for FASTCALL / NO_INLINE func.
257*f6dc9357SAndroid Build Coastguard Worker So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and
258*f6dc9357SAndroid Build Coastguard Worker old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
259*f6dc9357SAndroid Build Coastguard Worker
260*f6dc9357SAndroid Build Coastguard Worker DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!
261*f6dc9357SAndroid Build Coastguard Worker */
262*f6dc9357SAndroid Build Coastguard Worker static
MY_cpuidex_HACK(Int32 subFunction,Int32 func,Int32 * CPUInfo)263*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)
264*f6dc9357SAndroid Build Coastguard Worker {
265*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(subFunction)
266*f6dc9357SAndroid Build Coastguard Worker __cpuid(CPUInfo, func);
267*f6dc9357SAndroid Build Coastguard Worker }
268*f6dc9357SAndroid Build Coastguard Worker #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info)
269*f6dc9357SAndroid Build Coastguard Worker #pragma message("======== MY_cpuidex_HACK WAS USED ========")
270*f6dc9357SAndroid Build Coastguard Worker static
z7_x86_cpuid_subFunc(UInt32 p[4],UInt32 func,UInt32 subFunc)271*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)
272*f6dc9357SAndroid Build Coastguard Worker {
273*f6dc9357SAndroid Build Coastguard Worker MY_cpuidex_HACK(subFunc, func, (Int32 *)p);
274*f6dc9357SAndroid Build Coastguard Worker }
275*f6dc9357SAndroid Build Coastguard Worker #endif // _MSC_VER >= 1600
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_AMD64)
278*f6dc9357SAndroid Build Coastguard Worker /* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code,
279*f6dc9357SAndroid Build Coastguard Worker so we disable inlining here */
280*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
281*f6dc9357SAndroid Build Coastguard Worker #endif
z7_x86_cpuid(UInt32 p[4],UInt32 func)282*f6dc9357SAndroid Build Coastguard Worker void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
283*f6dc9357SAndroid Build Coastguard Worker {
284*f6dc9357SAndroid Build Coastguard Worker MY_cpuidex((Int32 *)p, (Int32)func, 0);
285*f6dc9357SAndroid Build Coastguard Worker }
286*f6dc9357SAndroid Build Coastguard Worker
287*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
z7_x86_cpuid_GetMaxFunc(void)288*f6dc9357SAndroid Build Coastguard Worker UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
289*f6dc9357SAndroid Build Coastguard Worker {
290*f6dc9357SAndroid Build Coastguard Worker Int32 a[4];
291*f6dc9357SAndroid Build Coastguard Worker MY_cpuidex(a, 0, 0);
292*f6dc9357SAndroid Build Coastguard Worker return a[0];
293*f6dc9357SAndroid Build Coastguard Worker }
294*f6dc9357SAndroid Build Coastguard Worker
295*f6dc9357SAndroid Build Coastguard Worker #endif // MY_CPU_AMD64
296*f6dc9357SAndroid Build Coastguard Worker #endif // _MSC_VER
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker #if defined(NEED_CHECK_FOR_CPUID)
299*f6dc9357SAndroid Build Coastguard Worker #define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; }
300*f6dc9357SAndroid Build Coastguard Worker #else
301*f6dc9357SAndroid Build Coastguard Worker #define CHECK_CPUID_IS_SUPPORTED
302*f6dc9357SAndroid Build Coastguard Worker #endif
303*f6dc9357SAndroid Build Coastguard Worker #undef NEED_CHECK_FOR_CPUID
304*f6dc9357SAndroid Build Coastguard Worker
305*f6dc9357SAndroid Build Coastguard Worker
306*f6dc9357SAndroid Build Coastguard Worker static
x86cpuid_Func_1(UInt32 * p)307*f6dc9357SAndroid Build Coastguard Worker BoolInt x86cpuid_Func_1(UInt32 *p)
308*f6dc9357SAndroid Build Coastguard Worker {
309*f6dc9357SAndroid Build Coastguard Worker CHECK_CPUID_IS_SUPPORTED
310*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(p, 1);
311*f6dc9357SAndroid Build Coastguard Worker return True;
312*f6dc9357SAndroid Build Coastguard Worker }
313*f6dc9357SAndroid Build Coastguard Worker
314*f6dc9357SAndroid Build Coastguard Worker /*
315*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kVendors[][1] =
316*f6dc9357SAndroid Build Coastguard Worker {
317*f6dc9357SAndroid Build Coastguard Worker { 0x756E6547 }, // , 0x49656E69, 0x6C65746E },
318*f6dc9357SAndroid Build Coastguard Worker { 0x68747541 }, // , 0x69746E65, 0x444D4163 },
319*f6dc9357SAndroid Build Coastguard Worker { 0x746E6543 } // , 0x48727561, 0x736C7561 }
320*f6dc9357SAndroid Build Coastguard Worker };
321*f6dc9357SAndroid Build Coastguard Worker */
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker /*
324*f6dc9357SAndroid Build Coastguard Worker typedef struct
325*f6dc9357SAndroid Build Coastguard Worker {
326*f6dc9357SAndroid Build Coastguard Worker UInt32 maxFunc;
327*f6dc9357SAndroid Build Coastguard Worker UInt32 vendor[3];
328*f6dc9357SAndroid Build Coastguard Worker UInt32 ver;
329*f6dc9357SAndroid Build Coastguard Worker UInt32 b;
330*f6dc9357SAndroid Build Coastguard Worker UInt32 c;
331*f6dc9357SAndroid Build Coastguard Worker UInt32 d;
332*f6dc9357SAndroid Build Coastguard Worker } Cx86cpuid;
333*f6dc9357SAndroid Build Coastguard Worker
334*f6dc9357SAndroid Build Coastguard Worker enum
335*f6dc9357SAndroid Build Coastguard Worker {
336*f6dc9357SAndroid Build Coastguard Worker CPU_FIRM_INTEL,
337*f6dc9357SAndroid Build Coastguard Worker CPU_FIRM_AMD,
338*f6dc9357SAndroid Build Coastguard Worker CPU_FIRM_VIA
339*f6dc9357SAndroid Build Coastguard Worker };
340*f6dc9357SAndroid Build Coastguard Worker int x86cpuid_GetFirm(const Cx86cpuid *p);
341*f6dc9357SAndroid Build Coastguard Worker #define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf))
342*f6dc9357SAndroid Build Coastguard Worker #define x86cpuid_ver_GetModel(ver) (((ver >> 12) & 0xf0) | ((ver >> 4) & 0xf))
343*f6dc9357SAndroid Build Coastguard Worker #define x86cpuid_ver_GetStepping(ver) (ver & 0xf)
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker int x86cpuid_GetFirm(const Cx86cpuid *p)
346*f6dc9357SAndroid Build Coastguard Worker {
347*f6dc9357SAndroid Build Coastguard Worker unsigned i;
348*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++)
349*f6dc9357SAndroid Build Coastguard Worker {
350*f6dc9357SAndroid Build Coastguard Worker const UInt32 *v = kVendors[i];
351*f6dc9357SAndroid Build Coastguard Worker if (v[0] == p->vendor[0]
352*f6dc9357SAndroid Build Coastguard Worker // && v[1] == p->vendor[1]
353*f6dc9357SAndroid Build Coastguard Worker // && v[2] == p->vendor[2]
354*f6dc9357SAndroid Build Coastguard Worker )
355*f6dc9357SAndroid Build Coastguard Worker return (int)i;
356*f6dc9357SAndroid Build Coastguard Worker }
357*f6dc9357SAndroid Build Coastguard Worker return -1;
358*f6dc9357SAndroid Build Coastguard Worker }
359*f6dc9357SAndroid Build Coastguard Worker
360*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_Is_InOrder()
361*f6dc9357SAndroid Build Coastguard Worker {
362*f6dc9357SAndroid Build Coastguard Worker Cx86cpuid p;
363*f6dc9357SAndroid Build Coastguard Worker UInt32 family, model;
364*f6dc9357SAndroid Build Coastguard Worker if (!x86cpuid_CheckAndRead(&p))
365*f6dc9357SAndroid Build Coastguard Worker return True;
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker family = x86cpuid_ver_GetFamily(p.ver);
368*f6dc9357SAndroid Build Coastguard Worker model = x86cpuid_ver_GetModel(p.ver);
369*f6dc9357SAndroid Build Coastguard Worker
370*f6dc9357SAndroid Build Coastguard Worker switch (x86cpuid_GetFirm(&p))
371*f6dc9357SAndroid Build Coastguard Worker {
372*f6dc9357SAndroid Build Coastguard Worker case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
373*f6dc9357SAndroid Build Coastguard Worker // In-Order Atom CPU
374*f6dc9357SAndroid Build Coastguard Worker model == 0x1C // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330
375*f6dc9357SAndroid Build Coastguard Worker || model == 0x26 // 45 nm, Z6xx
376*f6dc9357SAndroid Build Coastguard Worker || model == 0x27 // 32 nm, Z2460
377*f6dc9357SAndroid Build Coastguard Worker || model == 0x35 // 32 nm, Z2760
378*f6dc9357SAndroid Build Coastguard Worker || model == 0x36 // 32 nm, N2xxx, D2xxx
379*f6dc9357SAndroid Build Coastguard Worker )));
380*f6dc9357SAndroid Build Coastguard Worker case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
381*f6dc9357SAndroid Build Coastguard Worker case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker return False; // v23 : unknown processors are not In-Order
384*f6dc9357SAndroid Build Coastguard Worker }
385*f6dc9357SAndroid Build Coastguard Worker */
386*f6dc9357SAndroid Build Coastguard Worker
387*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
388*f6dc9357SAndroid Build Coastguard Worker #include "7zWindows.h"
389*f6dc9357SAndroid Build Coastguard Worker #endif
390*f6dc9357SAndroid Build Coastguard Worker
391*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_AMD64) && defined(_WIN32)
392*f6dc9357SAndroid Build Coastguard Worker
393*f6dc9357SAndroid Build Coastguard Worker /* for legacy SSE ia32: there is no user-space cpu instruction to check
394*f6dc9357SAndroid Build Coastguard Worker that OS supports SSE register storing/restoring on context switches.
395*f6dc9357SAndroid Build Coastguard Worker So we need some OS-specific function to check that it's safe to use SSE registers.
396*f6dc9357SAndroid Build Coastguard Worker */
397*f6dc9357SAndroid Build Coastguard Worker
398*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
CPU_Sys_Is_SSE_Supported(void)399*f6dc9357SAndroid Build Coastguard Worker static BoolInt CPU_Sys_Is_SSE_Supported(void)
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker #ifdef _MSC_VER
402*f6dc9357SAndroid Build Coastguard Worker #pragma warning(push)
403*f6dc9357SAndroid Build Coastguard Worker #pragma warning(disable : 4996) // `GetVersion': was declared deprecated
404*f6dc9357SAndroid Build Coastguard Worker #endif
405*f6dc9357SAndroid Build Coastguard Worker /* low byte is major version of Windows
406*f6dc9357SAndroid Build Coastguard Worker We suppose that any Windows version since
407*f6dc9357SAndroid Build Coastguard Worker Windows2000 (major == 5) supports SSE registers */
408*f6dc9357SAndroid Build Coastguard Worker return (Byte)GetVersion() >= 5;
409*f6dc9357SAndroid Build Coastguard Worker #if defined(_MSC_VER)
410*f6dc9357SAndroid Build Coastguard Worker #pragma warning(pop)
411*f6dc9357SAndroid Build Coastguard Worker #endif
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
414*f6dc9357SAndroid Build Coastguard Worker #else
415*f6dc9357SAndroid Build Coastguard Worker #define CHECK_SYS_SSE_SUPPORT
416*f6dc9357SAndroid Build Coastguard Worker #endif
417*f6dc9357SAndroid Build Coastguard Worker
418*f6dc9357SAndroid Build Coastguard Worker
419*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_AMD64)
420*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_CMOV(void)421*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_CMOV(void)
422*f6dc9357SAndroid Build Coastguard Worker {
423*f6dc9357SAndroid Build Coastguard Worker UInt32 a[4];
424*f6dc9357SAndroid Build Coastguard Worker if (!x86cpuid_Func_1(&a[0]))
425*f6dc9357SAndroid Build Coastguard Worker return 0;
426*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(a[3] >> 15) & 1;
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SSE(void)429*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SSE(void)
430*f6dc9357SAndroid Build Coastguard Worker {
431*f6dc9357SAndroid Build Coastguard Worker UInt32 a[4];
432*f6dc9357SAndroid Build Coastguard Worker CHECK_SYS_SSE_SUPPORT
433*f6dc9357SAndroid Build Coastguard Worker if (!x86cpuid_Func_1(&a[0]))
434*f6dc9357SAndroid Build Coastguard Worker return 0;
435*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(a[3] >> 25) & 1;
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SSE2(void)438*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SSE2(void)
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker UInt32 a[4];
441*f6dc9357SAndroid Build Coastguard Worker CHECK_SYS_SSE_SUPPORT
442*f6dc9357SAndroid Build Coastguard Worker if (!x86cpuid_Func_1(&a[0]))
443*f6dc9357SAndroid Build Coastguard Worker return 0;
444*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(a[3] >> 26) & 1;
445*f6dc9357SAndroid Build Coastguard Worker }
446*f6dc9357SAndroid Build Coastguard Worker
447*f6dc9357SAndroid Build Coastguard Worker #endif
448*f6dc9357SAndroid Build Coastguard Worker
449*f6dc9357SAndroid Build Coastguard Worker
x86cpuid_Func_1_ECX(void)450*f6dc9357SAndroid Build Coastguard Worker static UInt32 x86cpuid_Func_1_ECX(void)
451*f6dc9357SAndroid Build Coastguard Worker {
452*f6dc9357SAndroid Build Coastguard Worker UInt32 a[4];
453*f6dc9357SAndroid Build Coastguard Worker CHECK_SYS_SSE_SUPPORT
454*f6dc9357SAndroid Build Coastguard Worker if (!x86cpuid_Func_1(&a[0]))
455*f6dc9357SAndroid Build Coastguard Worker return 0;
456*f6dc9357SAndroid Build Coastguard Worker return a[2];
457*f6dc9357SAndroid Build Coastguard Worker }
458*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_AES(void)459*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_AES(void)
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;
462*f6dc9357SAndroid Build Coastguard Worker }
463*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SSSE3(void)464*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SSSE3(void)
465*f6dc9357SAndroid Build Coastguard Worker {
466*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;
467*f6dc9357SAndroid Build Coastguard Worker }
468*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SSE41(void)469*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SSE41(void)
470*f6dc9357SAndroid Build Coastguard Worker {
471*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SHA(void)474*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA(void)
475*f6dc9357SAndroid Build Coastguard Worker {
476*f6dc9357SAndroid Build Coastguard Worker CHECK_SYS_SSE_SUPPORT
477*f6dc9357SAndroid Build Coastguard Worker
478*f6dc9357SAndroid Build Coastguard Worker if (z7_x86_cpuid_GetMaxFunc() < 7)
479*f6dc9357SAndroid Build Coastguard Worker return False;
480*f6dc9357SAndroid Build Coastguard Worker {
481*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
482*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 7);
483*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(d[1] >> 29) & 1;
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker }
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SHA512(void)488*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA512(void)
489*f6dc9357SAndroid Build Coastguard Worker {
490*f6dc9357SAndroid Build Coastguard Worker if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here
491*f6dc9357SAndroid Build Coastguard Worker
492*f6dc9357SAndroid Build Coastguard Worker if (z7_x86_cpuid_GetMaxFunc() < 7)
493*f6dc9357SAndroid Build Coastguard Worker return False;
494*f6dc9357SAndroid Build Coastguard Worker {
495*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
496*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid_subFunc(d, 7, 0);
497*f6dc9357SAndroid Build Coastguard Worker if (d[0] < 1) // d[0] - is max supported subleaf value
498*f6dc9357SAndroid Build Coastguard Worker return False;
499*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid_subFunc(d, 7, 1);
500*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(d[0]) & 1;
501*f6dc9357SAndroid Build Coastguard Worker }
502*f6dc9357SAndroid Build Coastguard Worker }
503*f6dc9357SAndroid Build Coastguard Worker
504*f6dc9357SAndroid Build Coastguard Worker /*
505*f6dc9357SAndroid Build Coastguard Worker MSVC: _xgetbv() intrinsic is available since VS2010SP1.
506*f6dc9357SAndroid Build Coastguard Worker MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in
507*f6dc9357SAndroid Build Coastguard Worker <immintrin.h> that we can use or check.
508*f6dc9357SAndroid Build Coastguard Worker For any 32-bit x86 we can use asm code in MSVC,
509*f6dc9357SAndroid Build Coastguard Worker but MSVC asm code is huge after compilation.
510*f6dc9357SAndroid Build Coastguard Worker So _xgetbv() is better
511*f6dc9357SAndroid Build Coastguard Worker
512*f6dc9357SAndroid Build Coastguard Worker ICC: _xgetbv() intrinsic is available (in what version of ICC?)
513*f6dc9357SAndroid Build Coastguard Worker ICC defines (__GNUC___) and it supports gnu assembler
514*f6dc9357SAndroid Build Coastguard Worker also ICC supports MASM style code with -use-msasm switch.
515*f6dc9357SAndroid Build Coastguard Worker but ICC doesn't support __attribute__((__target__))
516*f6dc9357SAndroid Build Coastguard Worker
517*f6dc9357SAndroid Build Coastguard Worker GCC/CLANG 9:
518*f6dc9357SAndroid Build Coastguard Worker _xgetbv() is macro that works via __builtin_ia32_xgetbv()
519*f6dc9357SAndroid Build Coastguard Worker and we need __attribute__((__target__("xsave")).
520*f6dc9357SAndroid Build Coastguard Worker But with __target__("xsave") the function will be not
521*f6dc9357SAndroid Build Coastguard Worker inlined to function that has no __target__("xsave") attribute.
522*f6dc9357SAndroid Build Coastguard Worker If we want _xgetbv() call inlining, then we should use asm version
523*f6dc9357SAndroid Build Coastguard Worker instead of calling _xgetbv().
524*f6dc9357SAndroid Build Coastguard Worker Note:intrinsic is broke before GCC 8.2:
525*f6dc9357SAndroid Build Coastguard Worker https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684
526*f6dc9357SAndroid Build Coastguard Worker */
527*f6dc9357SAndroid Build Coastguard Worker
528*f6dc9357SAndroid Build Coastguard Worker #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \
529*f6dc9357SAndroid Build Coastguard Worker || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219) \
530*f6dc9357SAndroid Build Coastguard Worker || defined(__GNUC__) && (__GNUC__ >= 9) \
531*f6dc9357SAndroid Build Coastguard Worker || defined(__clang__) && (__clang_major__ >= 9)
532*f6dc9357SAndroid Build Coastguard Worker // we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler
533*f6dc9357SAndroid Build Coastguard Worker #if defined(__INTEL_COMPILER)
534*f6dc9357SAndroid Build Coastguard Worker #define ATTRIB_XGETBV
535*f6dc9357SAndroid Build Coastguard Worker #elif defined(__GNUC__) || defined(__clang__)
536*f6dc9357SAndroid Build Coastguard Worker // we don't define ATTRIB_XGETBV here, because asm version is better for inlining.
537*f6dc9357SAndroid Build Coastguard Worker // #define ATTRIB_XGETBV __attribute__((__target__("xsave")))
538*f6dc9357SAndroid Build Coastguard Worker #else
539*f6dc9357SAndroid Build Coastguard Worker #define ATTRIB_XGETBV
540*f6dc9357SAndroid Build Coastguard Worker #endif
541*f6dc9357SAndroid Build Coastguard Worker #endif
542*f6dc9357SAndroid Build Coastguard Worker
543*f6dc9357SAndroid Build Coastguard Worker #if defined(ATTRIB_XGETBV)
544*f6dc9357SAndroid Build Coastguard Worker #include <immintrin.h>
545*f6dc9357SAndroid Build Coastguard Worker #endif
546*f6dc9357SAndroid Build Coastguard Worker
547*f6dc9357SAndroid Build Coastguard Worker
548*f6dc9357SAndroid Build Coastguard Worker // XFEATURE_ENABLED_MASK/XCR0
549*f6dc9357SAndroid Build Coastguard Worker #define MY_XCR_XFEATURE_ENABLED_MASK 0
550*f6dc9357SAndroid Build Coastguard Worker
551*f6dc9357SAndroid Build Coastguard Worker #if defined(ATTRIB_XGETBV)
552*f6dc9357SAndroid Build Coastguard Worker ATTRIB_XGETBV
553*f6dc9357SAndroid Build Coastguard Worker #endif
x86_xgetbv_0(UInt32 num)554*f6dc9357SAndroid Build Coastguard Worker static UInt64 x86_xgetbv_0(UInt32 num)
555*f6dc9357SAndroid Build Coastguard Worker {
556*f6dc9357SAndroid Build Coastguard Worker #if defined(ATTRIB_XGETBV)
557*f6dc9357SAndroid Build Coastguard Worker {
558*f6dc9357SAndroid Build Coastguard Worker return
559*f6dc9357SAndroid Build Coastguard Worker #if (defined(_MSC_VER))
560*f6dc9357SAndroid Build Coastguard Worker _xgetbv(num);
561*f6dc9357SAndroid Build Coastguard Worker #else
562*f6dc9357SAndroid Build Coastguard Worker __builtin_ia32_xgetbv(
563*f6dc9357SAndroid Build Coastguard Worker #if !defined(__clang__)
564*f6dc9357SAndroid Build Coastguard Worker (int)
565*f6dc9357SAndroid Build Coastguard Worker #endif
566*f6dc9357SAndroid Build Coastguard Worker num);
567*f6dc9357SAndroid Build Coastguard Worker #endif
568*f6dc9357SAndroid Build Coastguard Worker }
569*f6dc9357SAndroid Build Coastguard Worker
570*f6dc9357SAndroid Build Coastguard Worker #elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)
571*f6dc9357SAndroid Build Coastguard Worker
572*f6dc9357SAndroid Build Coastguard Worker UInt32 a, d;
573*f6dc9357SAndroid Build Coastguard Worker #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
574*f6dc9357SAndroid Build Coastguard Worker __asm__
575*f6dc9357SAndroid Build Coastguard Worker (
576*f6dc9357SAndroid Build Coastguard Worker "xgetbv"
577*f6dc9357SAndroid Build Coastguard Worker : "=a"(a), "=d"(d) : "c"(num) : "cc"
578*f6dc9357SAndroid Build Coastguard Worker );
579*f6dc9357SAndroid Build Coastguard Worker #else // is old gcc
580*f6dc9357SAndroid Build Coastguard Worker __asm__
581*f6dc9357SAndroid Build Coastguard Worker (
582*f6dc9357SAndroid Build Coastguard Worker ".byte 0x0f, 0x01, 0xd0" "\n\t"
583*f6dc9357SAndroid Build Coastguard Worker : "=a"(a), "=d"(d) : "c"(num) : "cc"
584*f6dc9357SAndroid Build Coastguard Worker );
585*f6dc9357SAndroid Build Coastguard Worker #endif
586*f6dc9357SAndroid Build Coastguard Worker return ((UInt64)d << 32) | a;
587*f6dc9357SAndroid Build Coastguard Worker // return a;
588*f6dc9357SAndroid Build Coastguard Worker
589*f6dc9357SAndroid Build Coastguard Worker #elif defined(_MSC_VER) && !defined(MY_CPU_AMD64)
590*f6dc9357SAndroid Build Coastguard Worker
591*f6dc9357SAndroid Build Coastguard Worker UInt32 a, d;
592*f6dc9357SAndroid Build Coastguard Worker __asm {
593*f6dc9357SAndroid Build Coastguard Worker push eax
594*f6dc9357SAndroid Build Coastguard Worker push edx
595*f6dc9357SAndroid Build Coastguard Worker push ecx
596*f6dc9357SAndroid Build Coastguard Worker mov ecx, num;
597*f6dc9357SAndroid Build Coastguard Worker // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK
598*f6dc9357SAndroid Build Coastguard Worker _emit 0x0f
599*f6dc9357SAndroid Build Coastguard Worker _emit 0x01
600*f6dc9357SAndroid Build Coastguard Worker _emit 0xd0
601*f6dc9357SAndroid Build Coastguard Worker mov a, eax
602*f6dc9357SAndroid Build Coastguard Worker mov d, edx
603*f6dc9357SAndroid Build Coastguard Worker pop ecx
604*f6dc9357SAndroid Build Coastguard Worker pop edx
605*f6dc9357SAndroid Build Coastguard Worker pop eax
606*f6dc9357SAndroid Build Coastguard Worker }
607*f6dc9357SAndroid Build Coastguard Worker return ((UInt64)d << 32) | a;
608*f6dc9357SAndroid Build Coastguard Worker // return a;
609*f6dc9357SAndroid Build Coastguard Worker
610*f6dc9357SAndroid Build Coastguard Worker #else // it's unknown compiler
611*f6dc9357SAndroid Build Coastguard Worker // #error "Need xgetbv function"
612*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(num)
613*f6dc9357SAndroid Build Coastguard Worker // for MSVC-X64 we could call external function from external file.
614*f6dc9357SAndroid Build Coastguard Worker /* Actually we had checked OSXSAVE/AVX in cpuid before.
615*f6dc9357SAndroid Build Coastguard Worker So it's expected that OS supports at least AVX and below. */
616*f6dc9357SAndroid Build Coastguard Worker // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0
617*f6dc9357SAndroid Build Coastguard Worker return
618*f6dc9357SAndroid Build Coastguard Worker // (1 << 0) | // x87
619*f6dc9357SAndroid Build Coastguard Worker (1 << 1) // SSE
620*f6dc9357SAndroid Build Coastguard Worker | (1 << 2); // AVX
621*f6dc9357SAndroid Build Coastguard Worker
622*f6dc9357SAndroid Build Coastguard Worker #endif
623*f6dc9357SAndroid Build Coastguard Worker }
624*f6dc9357SAndroid Build Coastguard Worker
625*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
626*f6dc9357SAndroid Build Coastguard Worker /*
627*f6dc9357SAndroid Build Coastguard Worker Windows versions do not know about new ISA extensions that
628*f6dc9357SAndroid Build Coastguard Worker can be introduced. But we still can use new extensions,
629*f6dc9357SAndroid Build Coastguard Worker even if Windows doesn't report about supporting them,
630*f6dc9357SAndroid Build Coastguard Worker But we can use new extensions, only if Windows knows about new ISA extension
631*f6dc9357SAndroid Build Coastguard Worker that changes the number or size of registers: SSE, AVX/XSAVE, AVX512
632*f6dc9357SAndroid Build Coastguard Worker So it's enough to check
633*f6dc9357SAndroid Build Coastguard Worker MY_PF_AVX_INSTRUCTIONS_AVAILABLE
634*f6dc9357SAndroid Build Coastguard Worker instead of
635*f6dc9357SAndroid Build Coastguard Worker MY_PF_AVX2_INSTRUCTIONS_AVAILABLE
636*f6dc9357SAndroid Build Coastguard Worker */
637*f6dc9357SAndroid Build Coastguard Worker #define MY_PF_XSAVE_ENABLED 17
638*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE 36
639*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37
640*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38
641*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE 39
642*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE 40
643*f6dc9357SAndroid Build Coastguard Worker // #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE 41
644*f6dc9357SAndroid Build Coastguard Worker #endif
645*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_AVX(void)646*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_AVX(void)
647*f6dc9357SAndroid Build Coastguard Worker {
648*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
649*f6dc9357SAndroid Build Coastguard Worker if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED))
650*f6dc9357SAndroid Build Coastguard Worker return False;
651*f6dc9357SAndroid Build Coastguard Worker /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from
652*f6dc9357SAndroid Build Coastguard Worker some latest Win10 revisions. But we need AVX in older Windows also.
653*f6dc9357SAndroid Build Coastguard Worker So we don't use the following check: */
654*f6dc9357SAndroid Build Coastguard Worker /*
655*f6dc9357SAndroid Build Coastguard Worker if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE))
656*f6dc9357SAndroid Build Coastguard Worker return False;
657*f6dc9357SAndroid Build Coastguard Worker */
658*f6dc9357SAndroid Build Coastguard Worker #endif
659*f6dc9357SAndroid Build Coastguard Worker
660*f6dc9357SAndroid Build Coastguard Worker /*
661*f6dc9357SAndroid Build Coastguard Worker OS must use new special XSAVE/XRSTOR instructions to save
662*f6dc9357SAndroid Build Coastguard Worker AVX registers when it required for context switching.
663*f6dc9357SAndroid Build Coastguard Worker At OS statring:
664*f6dc9357SAndroid Build Coastguard Worker OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions.
665*f6dc9357SAndroid Build Coastguard Worker Also OS sets bitmask in XCR0 register that defines what
666*f6dc9357SAndroid Build Coastguard Worker registers will be processed by XSAVE instruction:
667*f6dc9357SAndroid Build Coastguard Worker XCR0.SSE[bit 0] - x87 registers and state
668*f6dc9357SAndroid Build Coastguard Worker XCR0.SSE[bit 1] - SSE registers and state
669*f6dc9357SAndroid Build Coastguard Worker XCR0.AVX[bit 2] - AVX registers and state
670*f6dc9357SAndroid Build Coastguard Worker CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27].
671*f6dc9357SAndroid Build Coastguard Worker So we can read that bit in user-space.
672*f6dc9357SAndroid Build Coastguard Worker XCR0 is available for reading in user-space by new XGETBV instruction.
673*f6dc9357SAndroid Build Coastguard Worker */
674*f6dc9357SAndroid Build Coastguard Worker {
675*f6dc9357SAndroid Build Coastguard Worker const UInt32 c = x86cpuid_Func_1_ECX();
676*f6dc9357SAndroid Build Coastguard Worker if (0 == (1
677*f6dc9357SAndroid Build Coastguard Worker & (c >> 28) // AVX instructions are supported by hardware
678*f6dc9357SAndroid Build Coastguard Worker & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS.
679*f6dc9357SAndroid Build Coastguard Worker return False;
680*f6dc9357SAndroid Build Coastguard Worker }
681*f6dc9357SAndroid Build Coastguard Worker
682*f6dc9357SAndroid Build Coastguard Worker /* also we can check
683*f6dc9357SAndroid Build Coastguard Worker CPUID.1:ECX.XSAVE [bit 26] : that shows that
684*f6dc9357SAndroid Build Coastguard Worker XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware.
685*f6dc9357SAndroid Build Coastguard Worker But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */
686*f6dc9357SAndroid Build Coastguard Worker
687*f6dc9357SAndroid Build Coastguard Worker /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1),
688*f6dc9357SAndroid Build Coastguard Worker in most cases we expect that OS also will support storing/restoring
689*f6dc9357SAndroid Build Coastguard Worker for AVX and SSE states at least.
690*f6dc9357SAndroid Build Coastguard Worker But to be ensure for that we call user-space instruction
691*f6dc9357SAndroid Build Coastguard Worker XGETBV(0) to get XCR0 value that contains bitmask that defines
692*f6dc9357SAndroid Build Coastguard Worker what exact states(registers) OS have enabled for storing/restoring.
693*f6dc9357SAndroid Build Coastguard Worker */
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker {
696*f6dc9357SAndroid Build Coastguard Worker const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
697*f6dc9357SAndroid Build Coastguard Worker // printf("\n=== XGetBV=0x%x\n", bm);
698*f6dc9357SAndroid Build Coastguard Worker return 1
699*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring
700*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring
701*f6dc9357SAndroid Build Coastguard Worker }
702*f6dc9357SAndroid Build Coastguard Worker // since Win7SP1: we can use GetEnabledXStateFeatures();
703*f6dc9357SAndroid Build Coastguard Worker }
704*f6dc9357SAndroid Build Coastguard Worker
705*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_AVX2(void)706*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_AVX2(void)
707*f6dc9357SAndroid Build Coastguard Worker {
708*f6dc9357SAndroid Build Coastguard Worker if (!CPU_IsSupported_AVX())
709*f6dc9357SAndroid Build Coastguard Worker return False;
710*f6dc9357SAndroid Build Coastguard Worker if (z7_x86_cpuid_GetMaxFunc() < 7)
711*f6dc9357SAndroid Build Coastguard Worker return False;
712*f6dc9357SAndroid Build Coastguard Worker {
713*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
714*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 7);
715*f6dc9357SAndroid Build Coastguard Worker // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
716*f6dc9357SAndroid Build Coastguard Worker return 1
717*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(d[1] >> 5); // avx2
718*f6dc9357SAndroid Build Coastguard Worker }
719*f6dc9357SAndroid Build Coastguard Worker }
720*f6dc9357SAndroid Build Coastguard Worker
721*f6dc9357SAndroid Build Coastguard Worker #if 0
722*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)
723*f6dc9357SAndroid Build Coastguard Worker {
724*f6dc9357SAndroid Build Coastguard Worker if (!CPU_IsSupported_AVX())
725*f6dc9357SAndroid Build Coastguard Worker return False;
726*f6dc9357SAndroid Build Coastguard Worker if (z7_x86_cpuid_GetMaxFunc() < 7)
727*f6dc9357SAndroid Build Coastguard Worker return False;
728*f6dc9357SAndroid Build Coastguard Worker {
729*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
730*f6dc9357SAndroid Build Coastguard Worker BoolInt v;
731*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 7);
732*f6dc9357SAndroid Build Coastguard Worker // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
733*f6dc9357SAndroid Build Coastguard Worker v = 1
734*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(d[1] >> 16) // avx512f
735*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(d[1] >> 31); // avx512vl
736*f6dc9357SAndroid Build Coastguard Worker if (!v)
737*f6dc9357SAndroid Build Coastguard Worker return False;
738*f6dc9357SAndroid Build Coastguard Worker }
739*f6dc9357SAndroid Build Coastguard Worker {
740*f6dc9357SAndroid Build Coastguard Worker const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
741*f6dc9357SAndroid Build Coastguard Worker // printf("\n=== XGetBV=0x%x\n", bm);
742*f6dc9357SAndroid Build Coastguard Worker return 1
743*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(bm >> 5) // OPMASK
744*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(bm >> 6) // ZMM upper 256-bit
745*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(bm >> 7); // ZMM16 ... ZMM31
746*f6dc9357SAndroid Build Coastguard Worker }
747*f6dc9357SAndroid Build Coastguard Worker }
748*f6dc9357SAndroid Build Coastguard Worker #endif
749*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_VAES_AVX2(void)750*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_VAES_AVX2(void)
751*f6dc9357SAndroid Build Coastguard Worker {
752*f6dc9357SAndroid Build Coastguard Worker if (!CPU_IsSupported_AVX())
753*f6dc9357SAndroid Build Coastguard Worker return False;
754*f6dc9357SAndroid Build Coastguard Worker if (z7_x86_cpuid_GetMaxFunc() < 7)
755*f6dc9357SAndroid Build Coastguard Worker return False;
756*f6dc9357SAndroid Build Coastguard Worker {
757*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
758*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 7);
759*f6dc9357SAndroid Build Coastguard Worker // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
760*f6dc9357SAndroid Build Coastguard Worker return 1
761*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(d[1] >> 5) // avx2
762*f6dc9357SAndroid Build Coastguard Worker // & (d[1] >> 31) // avx512vl
763*f6dc9357SAndroid Build Coastguard Worker & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_PageGB(void)767*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_PageGB(void)
768*f6dc9357SAndroid Build Coastguard Worker {
769*f6dc9357SAndroid Build Coastguard Worker CHECK_CPUID_IS_SUPPORTED
770*f6dc9357SAndroid Build Coastguard Worker {
771*f6dc9357SAndroid Build Coastguard Worker UInt32 d[4];
772*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 0x80000000);
773*f6dc9357SAndroid Build Coastguard Worker if (d[0] < 0x80000001)
774*f6dc9357SAndroid Build Coastguard Worker return False;
775*f6dc9357SAndroid Build Coastguard Worker z7_x86_cpuid(d, 0x80000001);
776*f6dc9357SAndroid Build Coastguard Worker return (BoolInt)(d[3] >> 26) & 1;
777*f6dc9357SAndroid Build Coastguard Worker }
778*f6dc9357SAndroid Build Coastguard Worker }
779*f6dc9357SAndroid Build Coastguard Worker
780*f6dc9357SAndroid Build Coastguard Worker
781*f6dc9357SAndroid Build Coastguard Worker #elif defined(MY_CPU_ARM_OR_ARM64)
782*f6dc9357SAndroid Build Coastguard Worker
783*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
784*f6dc9357SAndroid Build Coastguard Worker
785*f6dc9357SAndroid Build Coastguard Worker #include "7zWindows.h"
786*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_CRC32(void)787*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_CRC32(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
CPU_IsSupported_CRYPTO(void)788*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
CPU_IsSupported_NEON(void)789*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_NEON(void) { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
790*f6dc9357SAndroid Build Coastguard Worker
791*f6dc9357SAndroid Build Coastguard Worker #else
792*f6dc9357SAndroid Build Coastguard Worker
793*f6dc9357SAndroid Build Coastguard Worker #if defined(__APPLE__)
794*f6dc9357SAndroid Build Coastguard Worker
795*f6dc9357SAndroid Build Coastguard Worker /*
796*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
797*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
798*f6dc9357SAndroid Build Coastguard Worker static void Print_sysctlbyname(const char *name)
799*f6dc9357SAndroid Build Coastguard Worker {
800*f6dc9357SAndroid Build Coastguard Worker size_t bufSize = 256;
801*f6dc9357SAndroid Build Coastguard Worker char buf[256];
802*f6dc9357SAndroid Build Coastguard Worker int res = sysctlbyname(name, &buf, &bufSize, NULL, 0);
803*f6dc9357SAndroid Build Coastguard Worker {
804*f6dc9357SAndroid Build Coastguard Worker int i;
805*f6dc9357SAndroid Build Coastguard Worker printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize);
806*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < 20; i++)
807*f6dc9357SAndroid Build Coastguard Worker printf(" %2x", (unsigned)(Byte)buf[i]);
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker }
810*f6dc9357SAndroid Build Coastguard Worker }
811*f6dc9357SAndroid Build Coastguard Worker */
812*f6dc9357SAndroid Build Coastguard Worker /*
813*f6dc9357SAndroid Build Coastguard Worker Print_sysctlbyname("hw.pagesize");
814*f6dc9357SAndroid Build Coastguard Worker Print_sysctlbyname("machdep.cpu.brand_string");
815*f6dc9357SAndroid Build Coastguard Worker */
816*f6dc9357SAndroid Build Coastguard Worker
z7_sysctlbyname_Get_BoolInt(const char * name)817*f6dc9357SAndroid Build Coastguard Worker static BoolInt z7_sysctlbyname_Get_BoolInt(const char *name)
818*f6dc9357SAndroid Build Coastguard Worker {
819*f6dc9357SAndroid Build Coastguard Worker UInt32 val = 0;
820*f6dc9357SAndroid Build Coastguard Worker if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1)
821*f6dc9357SAndroid Build Coastguard Worker return 1;
822*f6dc9357SAndroid Build Coastguard Worker return 0;
823*f6dc9357SAndroid Build Coastguard Worker }
824*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_CRC32(void)825*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_CRC32(void)
826*f6dc9357SAndroid Build Coastguard Worker {
827*f6dc9357SAndroid Build Coastguard Worker return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32");
828*f6dc9357SAndroid Build Coastguard Worker }
829*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_NEON(void)830*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_NEON(void)
831*f6dc9357SAndroid Build Coastguard Worker {
832*f6dc9357SAndroid Build Coastguard Worker return z7_sysctlbyname_Get_BoolInt("hw.optional.neon");
833*f6dc9357SAndroid Build Coastguard Worker }
834*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SHA512(void)835*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA512(void)
836*f6dc9357SAndroid Build Coastguard Worker {
837*f6dc9357SAndroid Build Coastguard Worker return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha512");
838*f6dc9357SAndroid Build Coastguard Worker }
839*f6dc9357SAndroid Build Coastguard Worker
840*f6dc9357SAndroid Build Coastguard Worker /*
841*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA3(void)
842*f6dc9357SAndroid Build Coastguard Worker {
843*f6dc9357SAndroid Build Coastguard Worker return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_2_sha3");
844*f6dc9357SAndroid Build Coastguard Worker }
845*f6dc9357SAndroid Build Coastguard Worker */
846*f6dc9357SAndroid Build Coastguard Worker
847*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_ARM64
848*f6dc9357SAndroid Build Coastguard Worker #define APPLE_CRYPTO_SUPPORT_VAL 1
849*f6dc9357SAndroid Build Coastguard Worker #else
850*f6dc9357SAndroid Build Coastguard Worker #define APPLE_CRYPTO_SUPPORT_VAL 0
851*f6dc9357SAndroid Build Coastguard Worker #endif
852*f6dc9357SAndroid Build Coastguard Worker
CPU_IsSupported_SHA1(void)853*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
CPU_IsSupported_SHA2(void)854*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
CPU_IsSupported_AES(void)855*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
856*f6dc9357SAndroid Build Coastguard Worker
857*f6dc9357SAndroid Build Coastguard Worker
858*f6dc9357SAndroid Build Coastguard Worker #else // __APPLE__
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
861*f6dc9357SAndroid Build Coastguard Worker #define Z7_GETAUXV_AVAILABLE
862*f6dc9357SAndroid Build Coastguard Worker #else
863*f6dc9357SAndroid Build Coastguard Worker // #pragma message("=== is not NEW GLIBC === ")
864*f6dc9357SAndroid Build Coastguard Worker #if defined __has_include
865*f6dc9357SAndroid Build Coastguard Worker #if __has_include (<sys/auxv.h>)
866*f6dc9357SAndroid Build Coastguard Worker // #pragma message("=== sys/auxv.h is avail=== ")
867*f6dc9357SAndroid Build Coastguard Worker #define Z7_GETAUXV_AVAILABLE
868*f6dc9357SAndroid Build Coastguard Worker #endif
869*f6dc9357SAndroid Build Coastguard Worker #endif
870*f6dc9357SAndroid Build Coastguard Worker #endif
871*f6dc9357SAndroid Build Coastguard Worker
872*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_GETAUXV_AVAILABLE
873*f6dc9357SAndroid Build Coastguard Worker // #pragma message("=== Z7_GETAUXV_AVAILABLE === ")
874*f6dc9357SAndroid Build Coastguard Worker #include <sys/auxv.h>
875*f6dc9357SAndroid Build Coastguard Worker #define USE_HWCAP
876*f6dc9357SAndroid Build Coastguard Worker #endif
877*f6dc9357SAndroid Build Coastguard Worker
878*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_HWCAP
879*f6dc9357SAndroid Build Coastguard Worker
880*f6dc9357SAndroid Build Coastguard Worker #if defined(__FreeBSD__)
MY_getauxval(int aux)881*f6dc9357SAndroid Build Coastguard Worker static unsigned long MY_getauxval(int aux)
882*f6dc9357SAndroid Build Coastguard Worker {
883*f6dc9357SAndroid Build Coastguard Worker unsigned long val;
884*f6dc9357SAndroid Build Coastguard Worker if (elf_aux_info(aux, &val, sizeof(val)))
885*f6dc9357SAndroid Build Coastguard Worker return 0;
886*f6dc9357SAndroid Build Coastguard Worker return val;
887*f6dc9357SAndroid Build Coastguard Worker }
888*f6dc9357SAndroid Build Coastguard Worker #else
889*f6dc9357SAndroid Build Coastguard Worker #define MY_getauxval getauxval
890*f6dc9357SAndroid Build Coastguard Worker #if defined __has_include
891*f6dc9357SAndroid Build Coastguard Worker #if __has_include (<asm/hwcap.h>)
892*f6dc9357SAndroid Build Coastguard Worker #include <asm/hwcap.h>
893*f6dc9357SAndroid Build Coastguard Worker #endif
894*f6dc9357SAndroid Build Coastguard Worker #endif
895*f6dc9357SAndroid Build Coastguard Worker #endif
896*f6dc9357SAndroid Build Coastguard Worker
897*f6dc9357SAndroid Build Coastguard Worker #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
898*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); }
899*f6dc9357SAndroid Build Coastguard Worker
900*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_ARM64
901*f6dc9357SAndroid Build Coastguard Worker #define MY_HWCAP_CHECK_FUNC(name) \
902*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC_2(name, name)
903*f6dc9357SAndroid Build Coastguard Worker #if 1 || defined(__ARM_NEON)
CPU_IsSupported_NEON(void)904*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_NEON(void) { return True; }
905*f6dc9357SAndroid Build Coastguard Worker #else
MY_HWCAP_CHECK_FUNC_2(NEON,ASIMD)906*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
907*f6dc9357SAndroid Build Coastguard Worker #endif
908*f6dc9357SAndroid Build Coastguard Worker // MY_HWCAP_CHECK_FUNC (ASIMD)
909*f6dc9357SAndroid Build Coastguard Worker #elif defined(MY_CPU_ARM)
910*f6dc9357SAndroid Build Coastguard Worker #define MY_HWCAP_CHECK_FUNC(name) \
911*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }
912*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
913*f6dc9357SAndroid Build Coastguard Worker #endif
914*f6dc9357SAndroid Build Coastguard Worker
915*f6dc9357SAndroid Build Coastguard Worker #else // USE_HWCAP
916*f6dc9357SAndroid Build Coastguard Worker
917*f6dc9357SAndroid Build Coastguard Worker #define MY_HWCAP_CHECK_FUNC(name) \
918*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_ ## name(void) { return 0; }
919*f6dc9357SAndroid Build Coastguard Worker #if defined(__ARM_NEON)
920*f6dc9357SAndroid Build Coastguard Worker BoolInt CPU_IsSupported_NEON(void) { return True; }
921*f6dc9357SAndroid Build Coastguard Worker #else
922*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC(NEON)
923*f6dc9357SAndroid Build Coastguard Worker #endif
924*f6dc9357SAndroid Build Coastguard Worker
925*f6dc9357SAndroid Build Coastguard Worker #endif // USE_HWCAP
926*f6dc9357SAndroid Build Coastguard Worker
927*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC (CRC32)
928*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC (SHA1)
929*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC (SHA2)
930*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC (AES)
931*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_ARM64
932*f6dc9357SAndroid Build Coastguard Worker // <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017.
933*f6dc9357SAndroid Build Coastguard Worker // we define them here, if they are not defined
934*f6dc9357SAndroid Build Coastguard Worker #ifndef HWCAP_SHA3
935*f6dc9357SAndroid Build Coastguard Worker // #define HWCAP_SHA3 (1 << 17)
936*f6dc9357SAndroid Build Coastguard Worker #endif
937*f6dc9357SAndroid Build Coastguard Worker #ifndef HWCAP_SHA512
938*f6dc9357SAndroid Build Coastguard Worker // #pragma message("=== HWCAP_SHA512 define === ")
939*f6dc9357SAndroid Build Coastguard Worker #define HWCAP_SHA512 (1 << 21)
940*f6dc9357SAndroid Build Coastguard Worker #endif
941*f6dc9357SAndroid Build Coastguard Worker MY_HWCAP_CHECK_FUNC (SHA512)
942*f6dc9357SAndroid Build Coastguard Worker // MY_HWCAP_CHECK_FUNC (SHA3)
943*f6dc9357SAndroid Build Coastguard Worker #endif
944*f6dc9357SAndroid Build Coastguard Worker
945*f6dc9357SAndroid Build Coastguard Worker #endif // __APPLE__
946*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32
947*f6dc9357SAndroid Build Coastguard Worker
948*f6dc9357SAndroid Build Coastguard Worker #endif // MY_CPU_ARM_OR_ARM64
949*f6dc9357SAndroid Build Coastguard Worker
950*f6dc9357SAndroid Build Coastguard Worker
951*f6dc9357SAndroid Build Coastguard Worker
952*f6dc9357SAndroid Build Coastguard Worker #ifdef __APPLE__
953*f6dc9357SAndroid Build Coastguard Worker
954*f6dc9357SAndroid Build Coastguard Worker #include <sys/sysctl.h>
955*f6dc9357SAndroid Build Coastguard Worker
956*f6dc9357SAndroid Build Coastguard Worker int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize)
957*f6dc9357SAndroid Build Coastguard Worker {
958*f6dc9357SAndroid Build Coastguard Worker return sysctlbyname(name, buf, bufSize, NULL, 0);
959*f6dc9357SAndroid Build Coastguard Worker }
960*f6dc9357SAndroid Build Coastguard Worker
z7_sysctlbyname_Get_UInt32(const char * name,UInt32 * val)961*f6dc9357SAndroid Build Coastguard Worker int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val)
962*f6dc9357SAndroid Build Coastguard Worker {
963*f6dc9357SAndroid Build Coastguard Worker size_t bufSize = sizeof(*val);
964*f6dc9357SAndroid Build Coastguard Worker const int res = z7_sysctlbyname_Get(name, val, &bufSize);
965*f6dc9357SAndroid Build Coastguard Worker if (res == 0 && bufSize != sizeof(*val))
966*f6dc9357SAndroid Build Coastguard Worker return EFAULT;
967*f6dc9357SAndroid Build Coastguard Worker return res;
968*f6dc9357SAndroid Build Coastguard Worker }
969*f6dc9357SAndroid Build Coastguard Worker
970*f6dc9357SAndroid Build Coastguard Worker #endif
971