xref: /aosp_15_r20/external/libaom/aom_ports/aarch32_cpudetect.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 // Feature detection code for Armv7-A / AArch32.
12 
13 #include "arm_cpudetect.h"
14 
15 #if !CONFIG_RUNTIME_CPU_DETECT
16 
arm_get_cpu_caps(void)17 static int arm_get_cpu_caps(void) {
18   // This function should actually be a no-op. There is no way to adjust any of
19   // these because the RTCD tables do not exist: the functions are called
20   // statically.
21   int flags = 0;
22 #if HAVE_NEON
23   flags |= HAS_NEON;
24 #endif  // HAVE_NEON
25   return flags;
26 }
27 
28 #elif defined(_MSC_VER)  // end !CONFIG_RUNTIME_CPU_DETECT
29 
arm_get_cpu_caps(void)30 static int arm_get_cpu_caps(void) {
31   int flags = 0;
32 #if HAVE_NEON
33   // MSVC has no inline __asm support for Arm, but it does let you __emit
34   // instructions via their assembled hex code.
35   // All of these instructions should be essentially nops.
36   __try {
37     // VORR q0,q0,q0
38     __emit(0xF2200150);
39     flags |= HAS_NEON;
40   } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) {
41     // Ignore exception.
42   }
43 #endif  // HAVE_NEON
44   return flags;
45 }
46 
47 #elif defined(AOM_USE_ANDROID_CPU_FEATURES)
48 
arm_get_cpu_caps(void)49 static int arm_get_cpu_caps(void) {
50   int flags = 0;
51 #if HAVE_NEON
52   uint64_t features = android_getCpuFeatures();
53   if (features & ANDROID_CPU_ARM_FEATURE_NEON) flags |= HAS_NEON;
54 #endif  // HAVE_NEON
55   return flags;
56 }
57 
58 #elif defined(__linux__)  // end defined(AOM_USE_ANDROID_CPU_FEATURES)
59 
60 #include <sys/auxv.h>
61 
62 // Define hwcap values ourselves: building with an old auxv header where these
63 // hwcap values are not defined should not prevent features from being enabled.
64 #define AOM_AARCH32_HWCAP_NEON (1 << 12)
65 
arm_get_cpu_caps(void)66 static int arm_get_cpu_caps(void) {
67   int flags = 0;
68   unsigned long hwcap = getauxval(AT_HWCAP);
69 #if HAVE_NEON
70   if (hwcap & AOM_AARCH32_HWCAP_NEON) flags |= HAS_NEON;
71 #endif  // HAVE_NEON
72   return flags;
73 }
74 #else   // end __linux__
75 #error \
76     "Runtime CPU detection selected, but no CPU detection method " \
77 "available for your platform. Rerun cmake with -DCONFIG_RUNTIME_CPU_DETECT=0."
78 #endif
79 
aom_arm_cpu_caps(void)80 int aom_arm_cpu_caps(void) {
81   int flags = 0;
82   if (arm_cpu_env_flags(&flags)) {
83     return flags;
84   }
85   return arm_get_cpu_caps() & arm_cpu_env_mask();
86 }
87