xref: /aosp_15_r20/external/lzma/C/CpuArch.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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