xref: /aosp_15_r20/external/libvpx/vpx_ports/aarch64_cpudetect.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2023 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
12*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/arm.h"
13*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/arm_cpudetect.h"
14*fb1b10abSAndroid Build Coastguard Worker 
15*fb1b10abSAndroid Build Coastguard Worker #if defined(__APPLE__)
16*fb1b10abSAndroid Build Coastguard Worker #include <sys/sysctl.h>
17*fb1b10abSAndroid Build Coastguard Worker #endif
18*fb1b10abSAndroid Build Coastguard Worker 
19*fb1b10abSAndroid Build Coastguard Worker #if !CONFIG_RUNTIME_CPU_DETECT
20*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)21*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
22*fb1b10abSAndroid Build Coastguard Worker   // This function should actually be a no-op. There is no way to adjust any of
23*fb1b10abSAndroid Build Coastguard Worker   // these because the RTCD tables do not exist: the functions are called
24*fb1b10abSAndroid Build Coastguard Worker   // statically.
25*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
26*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
27*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;
28*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
29*fb1b10abSAndroid Build Coastguard Worker   return flags;
30*fb1b10abSAndroid Build Coastguard Worker }
31*fb1b10abSAndroid Build Coastguard Worker 
32*fb1b10abSAndroid Build Coastguard Worker #elif defined(__APPLE__)  // end !CONFIG_RUNTIME_CPU_DETECT
33*fb1b10abSAndroid Build Coastguard Worker 
34*fb1b10abSAndroid Build Coastguard Worker // sysctlbyname() parameter documentation for instruction set characteristics:
35*fb1b10abSAndroid Build Coastguard Worker // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
have_feature(const char * feature)36*fb1b10abSAndroid Build Coastguard Worker static INLINE int64_t have_feature(const char *feature) {
37*fb1b10abSAndroid Build Coastguard Worker   int64_t feature_present = 0;
38*fb1b10abSAndroid Build Coastguard Worker   size_t size = sizeof(feature_present);
39*fb1b10abSAndroid Build Coastguard Worker   if (sysctlbyname(feature, &feature_present, &size, NULL, 0) != 0) {
40*fb1b10abSAndroid Build Coastguard Worker     return 0;
41*fb1b10abSAndroid Build Coastguard Worker   }
42*fb1b10abSAndroid Build Coastguard Worker   return feature_present;
43*fb1b10abSAndroid Build Coastguard Worker }
44*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)45*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
46*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
47*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
48*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;
49*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
50*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_DOTPROD
51*fb1b10abSAndroid Build Coastguard Worker   if (have_feature("hw.optional.arm.FEAT_DotProd")) {
52*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_DOTPROD;
53*fb1b10abSAndroid Build Coastguard Worker   }
54*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_DOTPROD
55*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_I8MM
56*fb1b10abSAndroid Build Coastguard Worker   if (have_feature("hw.optional.arm.FEAT_I8MM")) {
57*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_I8MM;
58*fb1b10abSAndroid Build Coastguard Worker   }
59*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_I8MM
60*fb1b10abSAndroid Build Coastguard Worker   return flags;
61*fb1b10abSAndroid Build Coastguard Worker }
62*fb1b10abSAndroid Build Coastguard Worker 
63*fb1b10abSAndroid Build Coastguard Worker #elif defined(_WIN32)  // end __APPLE__
64*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)65*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
66*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
67*fb1b10abSAndroid Build Coastguard Worker // IsProcessorFeaturePresent() parameter documentation:
68*fb1b10abSAndroid Build Coastguard Worker // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent#parameters
69*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
70*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;  // Neon is mandatory in Armv8.0-A.
71*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
72*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_DOTPROD
73*fb1b10abSAndroid Build Coastguard Worker // Support for PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE was added in Windows SDK
74*fb1b10abSAndroid Build Coastguard Worker // 20348, supported by Windows 11 and Windows Server 2022.
75*fb1b10abSAndroid Build Coastguard Worker #if defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)
76*fb1b10abSAndroid Build Coastguard Worker   if (IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) {
77*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_DOTPROD;
78*fb1b10abSAndroid Build Coastguard Worker   }
79*fb1b10abSAndroid Build Coastguard Worker #endif  // defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)
80*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_DOTPROD
81*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_I8MM
82*fb1b10abSAndroid Build Coastguard Worker // Support for PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE was added in Windows SDK
83*fb1b10abSAndroid Build Coastguard Worker // 26100.
84*fb1b10abSAndroid Build Coastguard Worker #if defined(PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE)
85*fb1b10abSAndroid Build Coastguard Worker   // There's no PF_* flag that indicates whether plain I8MM is available
86*fb1b10abSAndroid Build Coastguard Worker   // or not. But if SVE_I8MM is available, that also implies that
87*fb1b10abSAndroid Build Coastguard Worker   // regular I8MM is available.
88*fb1b10abSAndroid Build Coastguard Worker   if (IsProcessorFeaturePresent(PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE)) {
89*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_I8MM;
90*fb1b10abSAndroid Build Coastguard Worker   }
91*fb1b10abSAndroid Build Coastguard Worker #endif  // defined(PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE)
92*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_I8MM
93*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SVE
94*fb1b10abSAndroid Build Coastguard Worker // Support for PF_ARM_SVE_INSTRUCTIONS_AVAILABLE was added in Windows SDK 26100.
95*fb1b10abSAndroid Build Coastguard Worker #if defined(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)
96*fb1b10abSAndroid Build Coastguard Worker   if (IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)) {
97*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_SVE;
98*fb1b10abSAndroid Build Coastguard Worker   }
99*fb1b10abSAndroid Build Coastguard Worker #endif  // defined(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)
100*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SVE
101*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SVE2
102*fb1b10abSAndroid Build Coastguard Worker // Support for PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE was added in Windows SDK
103*fb1b10abSAndroid Build Coastguard Worker // 26100.
104*fb1b10abSAndroid Build Coastguard Worker #if defined(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)
105*fb1b10abSAndroid Build Coastguard Worker   if (IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)) {
106*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_SVE2;
107*fb1b10abSAndroid Build Coastguard Worker   }
108*fb1b10abSAndroid Build Coastguard Worker #endif  // defined(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)
109*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SVE2
110*fb1b10abSAndroid Build Coastguard Worker   return flags;
111*fb1b10abSAndroid Build Coastguard Worker }
112*fb1b10abSAndroid Build Coastguard Worker 
113*fb1b10abSAndroid Build Coastguard Worker #elif defined(VPX_USE_ANDROID_CPU_FEATURES)
114*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)115*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
116*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
117*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
118*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;  // Neon is mandatory in Armv8.0-A.
119*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
120*fb1b10abSAndroid Build Coastguard Worker   return flags;
121*fb1b10abSAndroid Build Coastguard Worker }
122*fb1b10abSAndroid Build Coastguard Worker 
123*fb1b10abSAndroid Build Coastguard Worker #elif defined(__linux__)  // end defined(VPX_USE_ANDROID_CPU_FEATURES)
124*fb1b10abSAndroid Build Coastguard Worker 
125*fb1b10abSAndroid Build Coastguard Worker #include <sys/auxv.h>
126*fb1b10abSAndroid Build Coastguard Worker 
127*fb1b10abSAndroid Build Coastguard Worker // Define hwcap values ourselves: building with an old auxv header where these
128*fb1b10abSAndroid Build Coastguard Worker // hwcap values are not defined should not prevent features from being enabled.
129*fb1b10abSAndroid Build Coastguard Worker #define VPX_AARCH64_HWCAP_ASIMDDP (1 << 20)
130*fb1b10abSAndroid Build Coastguard Worker #define VPX_AARCH64_HWCAP_SVE (1 << 22)
131*fb1b10abSAndroid Build Coastguard Worker #define VPX_AARCH64_HWCAP2_SVE2 (1 << 1)
132*fb1b10abSAndroid Build Coastguard Worker #define VPX_AARCH64_HWCAP2_I8MM (1 << 13)
133*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)134*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
135*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
136*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_DOTPROD || HAVE_SVE
137*fb1b10abSAndroid Build Coastguard Worker   unsigned long hwcap = getauxval(AT_HWCAP);
138*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_DOTPROD || HAVE_SVE
139*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_I8MM || HAVE_SVE2
140*fb1b10abSAndroid Build Coastguard Worker   unsigned long hwcap2 = getauxval(AT_HWCAP2);
141*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_I8MM || HAVE_SVE2
142*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
143*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;  // Neon is mandatory in Armv8.0-A.
144*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
145*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_DOTPROD
146*fb1b10abSAndroid Build Coastguard Worker   if (hwcap & VPX_AARCH64_HWCAP_ASIMDDP) {
147*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_DOTPROD;
148*fb1b10abSAndroid Build Coastguard Worker   }
149*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_DOTPROD
150*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_I8MM
151*fb1b10abSAndroid Build Coastguard Worker   if (hwcap2 & VPX_AARCH64_HWCAP2_I8MM) {
152*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_I8MM;
153*fb1b10abSAndroid Build Coastguard Worker   }
154*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_I8MM
155*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SVE
156*fb1b10abSAndroid Build Coastguard Worker   if (hwcap & VPX_AARCH64_HWCAP_SVE) {
157*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_SVE;
158*fb1b10abSAndroid Build Coastguard Worker   }
159*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SVE
160*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SVE2
161*fb1b10abSAndroid Build Coastguard Worker   if (hwcap2 & VPX_AARCH64_HWCAP2_SVE2) {
162*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_SVE2;
163*fb1b10abSAndroid Build Coastguard Worker   }
164*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SVE2
165*fb1b10abSAndroid Build Coastguard Worker   return flags;
166*fb1b10abSAndroid Build Coastguard Worker }
167*fb1b10abSAndroid Build Coastguard Worker 
168*fb1b10abSAndroid Build Coastguard Worker #elif defined(__Fuchsia__)  // end __linux__
169*fb1b10abSAndroid Build Coastguard Worker 
170*fb1b10abSAndroid Build Coastguard Worker #include <zircon/features.h>
171*fb1b10abSAndroid Build Coastguard Worker #include <zircon/syscalls.h>
172*fb1b10abSAndroid Build Coastguard Worker 
173*fb1b10abSAndroid Build Coastguard Worker // Added in https://fuchsia-review.googlesource.com/c/fuchsia/+/894282.
174*fb1b10abSAndroid Build Coastguard Worker #ifndef ZX_ARM64_FEATURE_ISA_I8MM
175*fb1b10abSAndroid Build Coastguard Worker #define ZX_ARM64_FEATURE_ISA_I8MM ((uint32_t)(1u << 19))
176*fb1b10abSAndroid Build Coastguard Worker #endif
177*fb1b10abSAndroid Build Coastguard Worker // Added in https://fuchsia-review.googlesource.com/c/fuchsia/+/895083.
178*fb1b10abSAndroid Build Coastguard Worker #ifndef ZX_ARM64_FEATURE_ISA_SVE
179*fb1b10abSAndroid Build Coastguard Worker #define ZX_ARM64_FEATURE_ISA_SVE ((uint32_t)(1u << 20))
180*fb1b10abSAndroid Build Coastguard Worker #endif
181*fb1b10abSAndroid Build Coastguard Worker 
arm_get_cpu_caps(void)182*fb1b10abSAndroid Build Coastguard Worker static int arm_get_cpu_caps(void) {
183*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
184*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON
185*fb1b10abSAndroid Build Coastguard Worker   flags |= HAS_NEON;  // Neon is mandatory in Armv8.0-A.
186*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON
187*fb1b10abSAndroid Build Coastguard Worker   uint32_t features;
188*fb1b10abSAndroid Build Coastguard Worker   zx_status_t status = zx_system_get_features(ZX_FEATURE_KIND_CPU, &features);
189*fb1b10abSAndroid Build Coastguard Worker   if (status != ZX_OK) {
190*fb1b10abSAndroid Build Coastguard Worker     return flags;
191*fb1b10abSAndroid Build Coastguard Worker   }
192*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_DOTPROD
193*fb1b10abSAndroid Build Coastguard Worker   if (features & ZX_ARM64_FEATURE_ISA_DP) {
194*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_DOTPROD;
195*fb1b10abSAndroid Build Coastguard Worker   }
196*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_DOTPROD
197*fb1b10abSAndroid Build Coastguard Worker #if HAVE_NEON_I8MM
198*fb1b10abSAndroid Build Coastguard Worker   if (features & ZX_ARM64_FEATURE_ISA_I8MM) {
199*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_NEON_I8MM;
200*fb1b10abSAndroid Build Coastguard Worker   }
201*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_NEON_I8MM
202*fb1b10abSAndroid Build Coastguard Worker #if HAVE_SVE
203*fb1b10abSAndroid Build Coastguard Worker   if (features & ZX_ARM64_FEATURE_ISA_SVE) {
204*fb1b10abSAndroid Build Coastguard Worker     flags |= HAS_SVE;
205*fb1b10abSAndroid Build Coastguard Worker   }
206*fb1b10abSAndroid Build Coastguard Worker #endif  // HAVE_SVE
207*fb1b10abSAndroid Build Coastguard Worker   return flags;
208*fb1b10abSAndroid Build Coastguard Worker }
209*fb1b10abSAndroid Build Coastguard Worker 
210*fb1b10abSAndroid Build Coastguard Worker #else  // end __Fuchsia__
211*fb1b10abSAndroid Build Coastguard Worker #error \
212*fb1b10abSAndroid Build Coastguard Worker     "Runtime CPU detection selected, but no CPU detection method available" \
213*fb1b10abSAndroid Build Coastguard Worker "for your platform. Rerun configure with --disable-runtime-cpu-detect."
214*fb1b10abSAndroid Build Coastguard Worker #endif
215*fb1b10abSAndroid Build Coastguard Worker 
arm_cpu_caps(void)216*fb1b10abSAndroid Build Coastguard Worker int arm_cpu_caps(void) {
217*fb1b10abSAndroid Build Coastguard Worker   int flags = 0;
218*fb1b10abSAndroid Build Coastguard Worker   if (!arm_cpu_env_flags(&flags)) {
219*fb1b10abSAndroid Build Coastguard Worker     flags = arm_get_cpu_caps() & arm_cpu_env_mask();
220*fb1b10abSAndroid Build Coastguard Worker   }
221*fb1b10abSAndroid Build Coastguard Worker 
222*fb1b10abSAndroid Build Coastguard Worker   // Restrict flags: FEAT_I8MM assumes that FEAT_DotProd is available.
223*fb1b10abSAndroid Build Coastguard Worker   if (!(flags & HAS_NEON_DOTPROD)) {
224*fb1b10abSAndroid Build Coastguard Worker     flags &= ~HAS_NEON_I8MM;
225*fb1b10abSAndroid Build Coastguard Worker   }
226*fb1b10abSAndroid Build Coastguard Worker 
227*fb1b10abSAndroid Build Coastguard Worker   // Restrict flags: FEAT_SVE assumes that FEAT_{DotProd,I8MM} are available.
228*fb1b10abSAndroid Build Coastguard Worker   if (!(flags & HAS_NEON_DOTPROD)) {
229*fb1b10abSAndroid Build Coastguard Worker     flags &= ~HAS_SVE;
230*fb1b10abSAndroid Build Coastguard Worker   }
231*fb1b10abSAndroid Build Coastguard Worker   if (!(flags & HAS_NEON_I8MM)) {
232*fb1b10abSAndroid Build Coastguard Worker     flags &= ~HAS_SVE;
233*fb1b10abSAndroid Build Coastguard Worker   }
234*fb1b10abSAndroid Build Coastguard Worker 
235*fb1b10abSAndroid Build Coastguard Worker   // Restrict flags: FEAT_SVE2 assumes that FEAT_SVE is available.
236*fb1b10abSAndroid Build Coastguard Worker   if (!(flags & HAS_SVE)) {
237*fb1b10abSAndroid Build Coastguard Worker     flags &= ~HAS_SVE2;
238*fb1b10abSAndroid Build Coastguard Worker   }
239*fb1b10abSAndroid Build Coastguard Worker 
240*fb1b10abSAndroid Build Coastguard Worker   return flags;
241*fb1b10abSAndroid Build Coastguard Worker }
242