1 #include "../../zbuild.h"
2 
3 #if defined(__linux__) && defined(HAVE_SYS_AUXV_H)
4 #  include <sys/auxv.h>
5 #  ifdef ARM_ASM_HWCAP
6 #    include <asm/hwcap.h>
7 #  endif
8 #elif defined(__FreeBSD__) && defined(__aarch64__)
9 #  include <machine/armreg.h>
10 #  ifndef ID_AA64ISAR0_CRC32_VAL
11 #    define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
12 #  endif
13 #elif defined(__APPLE__)
14 #  if !defined(_DARWIN_C_SOURCE)
15 #    define _DARWIN_C_SOURCE /* enable types aliases (eg u_int) */
16 #  endif
17 #  include <sys/sysctl.h>
18 #elif defined(_WIN32)
19 #  include <winapifamily.h>
20 #endif
21 
arm_has_crc32()22 static int arm_has_crc32() {
23 #if defined(__linux__) && defined(ARM_AUXV_HAS_CRC32)
24 #  ifdef HWCAP_CRC32
25     return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0 ? 1 : 0;
26 #  else
27     return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0;
28 #  endif
29 #elif defined(__FreeBSD__) && defined(__aarch64__)
30     return getenv("QEMU_EMULATING") == NULL
31       && ID_AA64ISAR0_CRC32_VAL(READ_SPECIALREG(id_aa64isar0_el1)) >= ID_AA64ISAR0_CRC32_BASE;
32 #elif defined(__APPLE__)
33     int hascrc32;
34     size_t size = sizeof(hascrc32);
35     return sysctlbyname("hw.optional.armv8_crc32", &hascrc32, &size, NULL, 0) == 0
36       && hascrc32 == 1;
37 #elif defined(ARM_NOCHECK_ACLE)
38     return 1;
39 #else
40     return 0;
41 #endif
42 }
43 
44 /* AArch64 has neon. */
45 #if !defined(__aarch64__) && !defined(_M_ARM64)
arm_has_neon()46 static inline int arm_has_neon() {
47 #if defined(__linux__) && defined(ARM_AUXV_HAS_NEON)
48 #  ifdef HWCAP_ARM_NEON
49     return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON) != 0 ? 1 : 0;
50 #  else
51     return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0;
52 #  endif
53 #elif defined(__APPLE__)
54     int hasneon;
55     size_t size = sizeof(hasneon);
56     return sysctlbyname("hw.optional.neon", &hasneon, &size, NULL, 0) == 0
57       && hasneon == 1;
58 #elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION)
59 #  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
60     return 1; /* Always supported */
61 #  endif
62 #endif
63 
64 #if defined(ARM_NOCHECK_NEON)
65     return 1;
66 #else
67     return 0;
68 #endif
69 }
70 #endif
71 
72 Z_INTERNAL int arm_cpu_has_neon;
73 Z_INTERNAL int arm_cpu_has_crc32;
74 
arm_check_features(void)75 void Z_INTERNAL arm_check_features(void) {
76 #if defined(__aarch64__) || defined(_M_ARM64)
77     arm_cpu_has_neon = 1; /* always available */
78 #else
79     arm_cpu_has_neon = arm_has_neon();
80 #endif
81     arm_cpu_has_crc32 = arm_has_crc32();
82 }
83