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 Workerstatic 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 Workerstatic 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 Workerstatic 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 Workerstatic 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 Workerstatic 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 Workerstatic 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 Workerstatic 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 Workerint 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