crc32c_arm64_check.h
1 // Copyright 2017 The CRC32C Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. See the AUTHORS file for names of contributors. 4 5 // ARM-specific code checking for the availability of CRC32C instructions. 6 7 #ifndef CRC32C_CRC32C_ARM_CHECK_H_ 8 #define CRC32C_CRC32C_ARM_CHECK_H_ 9 10 #include <cstddef> 11 #include <cstdint> 12 13 #ifdef CRC32C_HAVE_CONFIG_H 14 #include "crc32c/crc32c_config.h" 15 #endif 16 17 #if HAVE_ARM64_CRC32C 18 19 #ifdef __linux__ 20 #if HAVE_STRONG_GETAUXVAL 21 #include <sys/auxv.h> 22 #elif HAVE_WEAK_GETAUXVAL 23 // getauxval() is not available on Android until API level 20. Link it as a weak 24 // symbol. 25 extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak)); 26 27 #define AT_HWCAP 16 28 #endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL 29 #endif // defined (__linux__) 30 31 #ifdef __APPLE__ 32 #include <sys/types.h> 33 #include <sys/sysctl.h> 34 #endif // defined (__APPLE__) 35 36 namespace crc32c { 37 38 inline bool CanUseArm64Crc32() { 39 #if defined (__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL) 40 // From 'arch/arm64/include/uapi/asm/hwcap.h' in Linux kernel source code. 41 constexpr unsigned long kHWCAP_PMULL = 1 << 4; 42 constexpr unsigned long kHWCAP_CRC32 = 1 << 7; 43 unsigned long hwcap = 44 #if HAVE_STRONG_GETAUXVAL 45 // Some compilers warn on (&getauxval != nullptr) in the block below. 46 getauxval(AT_HWCAP); 47 #elif HAVE_WEAK_GETAUXVAL 48 (&getauxval != nullptr) ? getauxval(AT_HWCAP) : 0; 49 #else 50 #error This is supposed to be nested inside a check for HAVE_*_GETAUXVAL. 51 #endif // HAVE_STRONG_GETAUXVAL 52 return (hwcap & (kHWCAP_PMULL | kHWCAP_CRC32)) == 53 (kHWCAP_PMULL | kHWCAP_CRC32); 54 #elif defined(__APPLE__) 55 int val = 0; 56 size_t len = sizeof(val); 57 return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0 58 && val != 0; 59 #else 60 return false; 61 #endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL 62 } 63 64 } // namespace crc32c 65 66 #endif // HAVE_ARM64_CRC32C 67 68 #endif // CRC32C_CRC32C_ARM_CHECK_H_