xref: /aosp_15_r20/external/webrtc/third_party/crc32c/src/src/crc32c_arm64_check.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #include "crc32c/crc32c_config.h"
14 
15 #if HAVE_ARM64_CRC32C
16 
17 #ifdef __linux__
18 #if HAVE_STRONG_GETAUXVAL
19 #include <sys/auxv.h>
20 #elif HAVE_WEAK_GETAUXVAL
21 // getauxval() is not available on Android until API level 20. Link it as a weak
22 // symbol.
23 extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak));
24 
25 #define AT_HWCAP 16
26 #endif  // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
27 #endif  // defined (__linux__)
28 
29 #ifdef __APPLE__
30 #include <sys/types.h>
31 #include <sys/sysctl.h>
32 #endif  // defined (__APPLE__)
33 
34 namespace crc32c {
35 
CanUseArm64Crc32()36 inline bool CanUseArm64Crc32() {
37 #if defined (__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL)
38   // From 'arch/arm64/include/uapi/asm/hwcap.h' in Linux kernel source code.
39   constexpr unsigned long kHWCAP_PMULL = 1 << 4;
40   constexpr unsigned long kHWCAP_CRC32 = 1 << 7;
41   unsigned long hwcap =
42 #if HAVE_STRONG_GETAUXVAL
43       // Some compilers warn on (&getauxval != nullptr) in the block below.
44       getauxval(AT_HWCAP);
45 #elif HAVE_WEAK_GETAUXVAL
46       (&getauxval != nullptr) ? getauxval(AT_HWCAP) : 0;
47 #else
48 #error This is supposed to be nested inside a check for HAVE_*_GETAUXVAL.
49 #endif  // HAVE_STRONG_GETAUXVAL
50   return (hwcap & (kHWCAP_PMULL | kHWCAP_CRC32)) ==
51          (kHWCAP_PMULL | kHWCAP_CRC32);
52 #elif defined(__APPLE__)
53   int val = 0;
54   size_t len = sizeof(val);
55   return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0
56              && val != 0;
57 #else
58   return false;
59 #endif  // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
60 }
61 
62 }  // namespace crc32c
63 
64 #endif  // HAVE_ARM64_CRC32C
65 
66 #endif  // CRC32C_CRC32C_ARM_CHECK_H_
67