1 /* CpuArch.c -- CPU specific code
2 2024-03-02 : Igor Pavlov : Public domain */
10 #ifdef MY_CPU_X86_OR_AMD64
12 #undef NEED_CHECK_FOR_CPUID
13 #if !defined(MY_CPU_AMD64)
14 #define NEED_CHECK_FOR_CPUID
18 cpuid instruction supports (subFunction) parameter in ECX,
19 that is used only with some specific (function) parameter values.
20 But we always use only (subFunction==0).
23 __cpuid(): MSVC and GCC/CLANG use same function/macro name
24 but parameters are different.
25 We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function.
28 #if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \
29 || defined(__clang__) /* && (__clang_major__ >= 10) */
31 /* there was some CLANG/GCC compilers that have issues with
32 rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined).
33 compiler's <cpuid.h> contains the macro __cpuid() that is similar to our code.
34 The history of __cpuid() changes in CLANG/GCC:
36 2007: it preserved ebx for (__PIC__ && __i386__)
37 2013: it preserved rbx and ebx for __PIC__
38 2014: it doesn't preserves rbx and ebx anymore
39 we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem.
41 2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check.
42 Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)?
43 Do we need __PIC__ test for CLANG or we must care about rbx even if
44 __PIC__ is not defined?
49 #if defined(MY_CPU_AMD64) && defined(__PIC__) \
50 && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
52 #define x86_cpuid_MACRO(p, func) { \
53 __asm__ __volatile__ ( \
54 ASM_LN "mov %%rbx, %q1" \
56 ASM_LN "xchg %%rbx, %q1" \
57 : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
59 /* "=&r" selects free register. It can select even rbx, if that register is free.
60 "=&D" for (RDI) also works, but the code can be larger with "=&D"
61 "2"(0) means (subFunction = 0),
62 2 is (zero-based) index in the output constraint list "=c" (ECX). */
64 #elif defined(MY_CPU_X86) && defined(__PIC__) \
65 && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))
67 #define x86_cpuid_MACRO(p, func) { \
68 __asm__ __volatile__ ( \
69 ASM_LN "mov %%ebx, %k1" \
71 ASM_LN "xchg %%ebx, %k1" \
72 : "=a" ((p)[0]), "=&r" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
76 #define x86_cpuid_MACRO(p, func) { \
77 __asm__ __volatile__ ( \
79 : "=a" ((p)[0]), "=b" ((p)[1]), "=c" ((p)[2]), "=d" ((p)[3]) : "0" (func), "2"(0)); }
84 void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
86 x86_cpuid_MACRO(p, func)
91 UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
93 #if defined(NEED_CHECK_FOR_CPUID)
94 #define EFALGS_CPUID_BIT 21
96 __asm__ __volatile__ (
100 // ASM_LN "movl %0, %1"
101 // ASM_LN "xorl $0x200000, %0"
107 ASM_LN "xorl (%%esp), %0"
112 : "i" (EFALGS_CPUID_BIT)
114 if ((a & (1 << EFALGS_CPUID_BIT)) == 0)
119 x86_cpuid_MACRO(p, 0)
126 #elif !defined(_MSC_VER)
129 // for gcc/clang and other: we can try to use __cpuid macro:
131 void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
133 __cpuid(func, p[0], p[1], p[2], p[3]);
135 UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
137 return (UInt32)__get_cpuid_max(0, NULL);
140 // for unsupported cpuid:
141 void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
144 p[0] = p[1] = p[2] = p[3] = 0;
146 UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
153 #if !defined(MY_CPU_AMD64)
155 UInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
157 #if defined(NEED_CHECK_FOR_CPUID)
158 #define EFALGS_CPUID_BIT 21
163 // __asm mov edx, eax
164 __asm btc eax, EFALGS_CPUID_BIT
167 __asm btc dword ptr [esp], EFALGS_CPUID_BIT
171 // __asm xor eax, edx
175 __asm and eax, (1 shl EFALGS_CPUID_BIT)
179 __asm xor eax, eax // func
180 __asm xor ecx, ecx // subFunction (optional) for (func == 0)
183 #if defined(NEED_CHECK_FOR_CPUID)
189 void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
195 __asm mov edi, ecx // p
196 __asm mov eax, edx // func
197 __asm xor ecx, ecx // subfunction (optional) for (func == 0)
199 __asm mov [edi ], eax
200 __asm mov [edi + 4], ebx
201 __asm mov [edi + 8], ecx
202 __asm mov [edi + 12], edx
208 #else // MY_CPU_AMD64
212 #define MY_cpuidex __cpuidex
215 __cpuid (func == (0 or 7)) requires subfunction number in ECX.
216 MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction.
217 __cpuid() in new MSVC clears ECX.
218 __cpuid() in old MSVC (14.00) x64 doesn't clear ECX
219 We still can use __cpuid for low (func) values that don't require ECX,
220 but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).
221 So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,
222 where ECX value is first parameter for FASTCALL / NO_INLINE func,
223 So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and
224 old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.
226 DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!
229 Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)
231 UNUSED_VAR(subFunction)
232 __cpuid(CPUInfo, func);
234 #define MY_cpuidex(info, func, func2) MY_cpuidex_HACK(func2, func, info)
235 #pragma message("======== MY_cpuidex_HACK WAS USED ========")
236 #endif // _MSC_VER >= 1600
238 #if !defined(MY_CPU_AMD64)
239 /* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code,
240 so we disable inlining here */
243 void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
245 MY_cpuidex((Int32 *)p, (Int32)func, 0);
249 UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
256 #endif // MY_CPU_AMD64
259 #if defined(NEED_CHECK_FOR_CPUID)
260 #define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; }
262 #define CHECK_CPUID_IS_SUPPORTED
264 #undef NEED_CHECK_FOR_CPUID
268 BoolInt x86cpuid_Func_1(UInt32 *p)
270 CHECK_CPUID_IS_SUPPORTED
276 static const UInt32 kVendors[][1] =
278 { 0x756E6547 }, // , 0x49656E69, 0x6C65746E },
279 { 0x68747541 }, // , 0x69746E65, 0x444D4163 },
280 { 0x746E6543 } // , 0x48727561, 0x736C7561 }
301 int x86cpuid_GetFirm(const Cx86cpuid *p);
302 #define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf))
303 #define x86cpuid_ver_GetModel(ver) (((ver >> 12) & 0xf0) | ((ver >> 4) & 0xf))
304 #define x86cpuid_ver_GetStepping(ver) (ver & 0xf)
306 int x86cpuid_GetFirm(const Cx86cpuid *p)
309 for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++)
311 const UInt32 *v = kVendors[i];
312 if (v[0] == p->vendor[0]
313 // && v[1] == p->vendor[1]
314 // && v[2] == p->vendor[2]
321 BoolInt CPU_Is_InOrder()
324 UInt32 family, model;
325 if (!x86cpuid_CheckAndRead(&p))
328 family = x86cpuid_ver_GetFamily(p.ver);
329 model = x86cpuid_ver_GetModel(p.ver);
331 switch (x86cpuid_GetFirm(&p))
333 case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
335 model == 0x1C // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330
336 || model == 0x26 // 45 nm, Z6xx
337 || model == 0x27 // 32 nm, Z2460
338 || model == 0x35 // 32 nm, Z2760
339 || model == 0x36 // 32 nm, N2xxx, D2xxx
341 case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
342 case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
344 return False; // v23 : unknown processors are not In-Order
349 #include "7zWindows.h"
352 #if !defined(MY_CPU_AMD64) && defined(_WIN32)
354 /* for legacy SSE ia32: there is no user-space cpu instruction to check
355 that OS supports SSE register storing/restoring on context switches.
356 So we need some OS-specific function to check that it's safe to use SSE registers.
360 static BoolInt CPU_Sys_Is_SSE_Supported(void)
363 #pragma warning(push)
364 #pragma warning(disable : 4996) // `GetVersion': was declared deprecated
366 /* low byte is major version of Windows
367 We suppose that any Windows version since
368 Windows2000 (major == 5) supports SSE registers */
369 return (Byte)GetVersion() >= 5;
370 #if defined(_MSC_VER)
374 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
376 #define CHECK_SYS_SSE_SUPPORT
380 #if !defined(MY_CPU_AMD64)
382 BoolInt CPU_IsSupported_CMOV(void)
385 if (!x86cpuid_Func_1(&a[0]))
387 return (BoolInt)(a[3] >> 15) & 1;
390 BoolInt CPU_IsSupported_SSE(void)
393 CHECK_SYS_SSE_SUPPORT
394 if (!x86cpuid_Func_1(&a[0]))
396 return (BoolInt)(a[3] >> 25) & 1;
399 BoolInt CPU_IsSupported_SSE2(void)
402 CHECK_SYS_SSE_SUPPORT
403 if (!x86cpuid_Func_1(&a[0]))
405 return (BoolInt)(a[3] >> 26) & 1;
411 static UInt32 x86cpuid_Func_1_ECX(void)
414 CHECK_SYS_SSE_SUPPORT
415 if (!x86cpuid_Func_1(&a[0]))
420 BoolInt CPU_IsSupported_AES(void)
422 return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;
425 BoolInt CPU_IsSupported_SSSE3(void)
427 return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;
430 BoolInt CPU_IsSupported_SSE41(void)
432 return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;
435 BoolInt CPU_IsSupported_SHA(void)
437 CHECK_SYS_SSE_SUPPORT
439 if (z7_x86_cpuid_GetMaxFunc() < 7)
444 return (BoolInt)(d[1] >> 29) & 1;
449 MSVC: _xgetbv() intrinsic is available since VS2010SP1.
450 MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in
451 <immintrin.h> that we can use or check.
452 For any 32-bit x86 we can use asm code in MSVC,
453 but MSVC asm code is huge after compilation.
454 So _xgetbv() is better
456 ICC: _xgetbv() intrinsic is available (in what version of ICC?)
457 ICC defines (__GNUC___) and it supports gnu assembler
458 also ICC supports MASM style code with -use-msasm switch.
459 but ICC doesn't support __attribute__((__target__))
462 _xgetbv() is macro that works via __builtin_ia32_xgetbv()
463 and we need __attribute__((__target__("xsave")).
464 But with __target__("xsave") the function will be not
465 inlined to function that has no __target__("xsave") attribute.
466 If we want _xgetbv() call inlining, then we should use asm version
467 instead of calling _xgetbv().
468 Note:intrinsic is broke before GCC 8.2:
469 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684
472 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \
473 || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219) \
474 || defined(__GNUC__) && (__GNUC__ >= 9) \
475 || defined(__clang__) && (__clang_major__ >= 9)
476 // we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler
477 #if defined(__INTEL_COMPILER)
478 #define ATTRIB_XGETBV
479 #elif defined(__GNUC__) || defined(__clang__)
480 // we don't define ATTRIB_XGETBV here, because asm version is better for inlining.
481 // #define ATTRIB_XGETBV __attribute__((__target__("xsave")))
483 #define ATTRIB_XGETBV
487 #if defined(ATTRIB_XGETBV)
488 #include <immintrin.h>
492 // XFEATURE_ENABLED_MASK/XCR0
493 #define MY_XCR_XFEATURE_ENABLED_MASK 0
495 #if defined(ATTRIB_XGETBV)
498 static UInt64 x86_xgetbv_0(UInt32 num)
500 #if defined(ATTRIB_XGETBV)
503 #if (defined(_MSC_VER))
506 __builtin_ia32_xgetbv(
507 #if !defined(__clang__)
514 #elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)
517 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
521 : "=a"(a), "=d"(d) : "c"(num) : "cc"
526 ".byte 0x0f, 0x01, 0xd0" "\n\t"
527 : "=a"(a), "=d"(d) : "c"(num) : "cc"
530 return ((UInt64)d << 32) | a;
533 #elif defined(_MSC_VER) && !defined(MY_CPU_AMD64)
541 // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK
551 return ((UInt64)d << 32) | a;
554 #else // it's unknown compiler
555 // #error "Need xgetbv function"
557 // for MSVC-X64 we could call external function from external file.
558 /* Actually we had checked OSXSAVE/AVX in cpuid before.
559 So it's expected that OS supports at least AVX and below. */
560 // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0
571 Windows versions do not know about new ISA extensions that
572 can be introduced. But we still can use new extensions,
573 even if Windows doesn't report about supporting them,
574 But we can use new extensions, only if Windows knows about new ISA extension
575 that changes the number or size of registers: SSE, AVX/XSAVE, AVX512
576 So it's enough to check
577 MY_PF_AVX_INSTRUCTIONS_AVAILABLE
579 MY_PF_AVX2_INSTRUCTIONS_AVAILABLE
581 #define MY_PF_XSAVE_ENABLED 17
582 // #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE 36
583 // #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37
584 // #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38
585 // #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE 39
586 // #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE 40
587 // #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE 41
590 BoolInt CPU_IsSupported_AVX(void)
593 if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED))
595 /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from
596 some latest Win10 revisions. But we need AVX in older Windows also.
597 So we don't use the following check: */
599 if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE))
605 OS must use new special XSAVE/XRSTOR instructions to save
606 AVX registers when it required for context switching.
608 OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions.
609 Also OS sets bitmask in XCR0 register that defines what
610 registers will be processed by XSAVE instruction:
611 XCR0.SSE[bit 0] - x87 registers and state
612 XCR0.SSE[bit 1] - SSE registers and state
613 XCR0.AVX[bit 2] - AVX registers and state
614 CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27].
615 So we can read that bit in user-space.
616 XCR0 is available for reading in user-space by new XGETBV instruction.
619 const UInt32 c = x86cpuid_Func_1_ECX();
621 & (c >> 28) // AVX instructions are supported by hardware
622 & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS.
627 CPUID.1:ECX.XSAVE [bit 26] : that shows that
628 XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware.
629 But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */
631 /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1),
632 in most cases we expect that OS also will support storing/restoring
633 for AVX and SSE states at least.
634 But to be ensure for that we call user-space instruction
635 XGETBV(0) to get XCR0 value that contains bitmask that defines
636 what exact states(registers) OS have enabled for storing/restoring.
640 const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
641 // printf("\n=== XGetBV=%d\n", bm);
643 & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring
644 & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring
646 // since Win7SP1: we can use GetEnabledXStateFeatures();
650 BoolInt CPU_IsSupported_AVX2(void)
652 if (!CPU_IsSupported_AVX())
654 if (z7_x86_cpuid_GetMaxFunc() < 7)
659 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
661 & (BoolInt)(d[1] >> 5); // avx2
667 BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)
669 if (!CPU_IsSupported_AVX())
671 if (z7_x86_cpuid_GetMaxFunc() < 7)
676 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
678 & (BoolInt)(d[1] >> 16) // avx512-f
679 & (BoolInt)(d[1] >> 31); // avx512-Vl
684 BoolInt CPU_IsSupported_VAES_AVX2(void)
686 if (!CPU_IsSupported_AVX())
688 if (z7_x86_cpuid_GetMaxFunc() < 7)
693 // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
695 & (BoolInt)(d[1] >> 5) // avx2
696 // & (d[1] >> 31) // avx512vl
697 & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX
701 BoolInt CPU_IsSupported_PageGB(void)
703 CHECK_CPUID_IS_SUPPORTED
706 z7_x86_cpuid(d, 0x80000000);
707 if (d[0] < 0x80000001)
709 z7_x86_cpuid(d, 0x80000001);
710 return (BoolInt)(d[3] >> 26) & 1;
715 #elif defined(MY_CPU_ARM_OR_ARM64)
719 #include "7zWindows.h"
721 BoolInt CPU_IsSupported_CRC32(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
722 BoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
723 BoolInt CPU_IsSupported_NEON(void) { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }
727 #if defined(__APPLE__)
732 static void Print_sysctlbyname(const char *name)
734 size_t bufSize = 256;
736 int res = sysctlbyname(name, &buf, &bufSize, NULL, 0);
739 printf("\nres = %d : %s : '%s' : bufSize = %d, numeric", res, name, buf, (unsigned)bufSize);
740 for (i = 0; i < 20; i++)
741 printf(" %2x", (unsigned)(Byte)buf[i]);
747 Print_sysctlbyname("hw.pagesize");
748 Print_sysctlbyname("machdep.cpu.brand_string");
751 static BoolInt z7_sysctlbyname_Get_BoolInt(const char *name)
754 if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1)
759 BoolInt CPU_IsSupported_CRC32(void)
761 return z7_sysctlbyname_Get_BoolInt("hw.optional.armv8_crc32");
764 BoolInt CPU_IsSupported_NEON(void)
766 return z7_sysctlbyname_Get_BoolInt("hw.optional.neon");
770 #define APPLE_CRYPTO_SUPPORT_VAL 1
772 #define APPLE_CRYPTO_SUPPORT_VAL 0
775 BoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
776 BoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; }
777 BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
782 #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
783 #define Z7_GETAUXV_AVAILABLE
785 // #pragma message("=== is not NEW GLIBC === ")
786 #if defined __has_include
787 #if __has_include (<sys/auxv.h>)
788 // #pragma message("=== sys/auxv.h is avail=== ")
789 #define Z7_GETAUXV_AVAILABLE
794 #ifdef Z7_GETAUXV_AVAILABLE
795 // #pragma message("=== Z7_GETAUXV_AVAILABLE === ")
796 #include <sys/auxv.h>
802 #if defined(__FreeBSD__)
803 static unsigned long MY_getauxval(int aux)
806 if (elf_aux_info(aux, &val, sizeof(val)))
811 #define MY_getauxval getauxval
812 #if defined __has_include
813 #if __has_include (<asm/hwcap.h>)
814 #include <asm/hwcap.h>
819 #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
820 BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); }
823 #define MY_HWCAP_CHECK_FUNC(name) \
824 MY_HWCAP_CHECK_FUNC_2(name, name)
825 #if 1 || defined(__ARM_NEON)
826 BoolInt CPU_IsSupported_NEON(void) { return True; }
828 MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
830 // MY_HWCAP_CHECK_FUNC (ASIMD)
831 #elif defined(MY_CPU_ARM)
832 #define MY_HWCAP_CHECK_FUNC(name) \
833 BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }
834 MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
839 #define MY_HWCAP_CHECK_FUNC(name) \
840 BoolInt CPU_IsSupported_ ## name(void) { return 0; }
842 #if defined(__SWITCH__) || defined(__vita__)
843 BoolInt CPU_IsSupported_NEON(void) { return 1; }
845 MY_HWCAP_CHECK_FUNC(NEON)
850 MY_HWCAP_CHECK_FUNC (CRC32)
851 MY_HWCAP_CHECK_FUNC (SHA1)
852 MY_HWCAP_CHECK_FUNC (SHA2)
853 MY_HWCAP_CHECK_FUNC (AES)
858 #endif // MY_CPU_ARM_OR_ARM64
864 #include <sys/sysctl.h>
866 int z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize)
868 return sysctlbyname(name, buf, bufSize, NULL, 0);
871 int z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val)
873 size_t bufSize = sizeof(*val);
874 const int res = z7_sysctlbyname_Get(name, val, &bufSize);
875 if (res == 0 && bufSize != sizeof(*val))