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