cpu.c (4512B)
1 /* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #include "libavutil/cpu.h" 20 #include "libavutil/cpu_internal.h" 21 #include "config.h" 22 23 #if HAVE_GETAUXVAL || HAVE_ELF_AUX_INFO 24 #include <stdint.h> 25 #include <sys/auxv.h> 26 27 #define HWCAP_AARCH64_ASIMDDP (1 << 20) 28 #define HWCAP_AARCH64_SVE (1 << 22) 29 #define HWCAP2_AARCH64_SVE2 (1 << 1) 30 #define HWCAP2_AARCH64_I8MM (1 << 13) 31 32 static int detect_flags(void) 33 { 34 int flags = 0; 35 36 unsigned long hwcap = ff_getauxval(AT_HWCAP); 37 unsigned long hwcap2 = ff_getauxval(AT_HWCAP2); 38 39 if (hwcap & HWCAP_AARCH64_ASIMDDP) 40 flags |= AV_CPU_FLAG_DOTPROD; 41 if (hwcap & HWCAP_AARCH64_SVE) 42 flags |= AV_CPU_FLAG_SVE; 43 if (hwcap2 & HWCAP2_AARCH64_SVE2) 44 flags |= AV_CPU_FLAG_SVE2; 45 if (hwcap2 & HWCAP2_AARCH64_I8MM) 46 flags |= AV_CPU_FLAG_I8MM; 47 48 return flags; 49 } 50 51 #elif defined(__APPLE__) && HAVE_SYSCTLBYNAME 52 #include <sys/sysctl.h> 53 54 static int have_feature(const char *feature) { 55 uint32_t value = 0; 56 size_t size = sizeof(value); 57 if (!sysctlbyname(feature, &value, &size, NULL, 0)) 58 return value; 59 return 0; 60 } 61 62 static int detect_flags(void) 63 { 64 int flags = 0; 65 66 if (have_feature("hw.optional.arm.FEAT_DotProd")) 67 flags |= AV_CPU_FLAG_DOTPROD; 68 if (have_feature("hw.optional.arm.FEAT_I8MM")) 69 flags |= AV_CPU_FLAG_I8MM; 70 71 return flags; 72 } 73 74 #elif defined(__OpenBSD__) 75 #include <machine/armreg.h> 76 #include <machine/cpu.h> 77 #include <sys/types.h> 78 #include <sys/sysctl.h> 79 80 static int detect_flags(void) 81 { 82 int flags = 0; 83 84 #ifdef CPU_ID_AA64ISAR0 85 int mib[2]; 86 uint64_t isar0; 87 uint64_t isar1; 88 size_t len; 89 90 mib[0] = CTL_MACHDEP; 91 mib[1] = CPU_ID_AA64ISAR0; 92 len = sizeof(isar0); 93 if (sysctl(mib, 2, &isar0, &len, NULL, 0) != -1) { 94 if (ID_AA64ISAR0_DP(isar0) >= ID_AA64ISAR0_DP_IMPL) 95 flags |= AV_CPU_FLAG_DOTPROD; 96 } 97 98 mib[0] = CTL_MACHDEP; 99 mib[1] = CPU_ID_AA64ISAR1; 100 len = sizeof(isar1); 101 if (sysctl(mib, 2, &isar1, &len, NULL, 0) != -1) { 102 #ifdef ID_AA64ISAR1_I8MM_IMPL 103 if (ID_AA64ISAR1_I8MM(isar1) >= ID_AA64ISAR1_I8MM_IMPL) 104 flags |= AV_CPU_FLAG_I8MM; 105 #endif 106 } 107 #endif 108 109 return flags; 110 } 111 112 #elif defined(_WIN32) 113 #include <windows.h> 114 115 static int detect_flags(void) 116 { 117 int flags = 0; 118 #ifdef PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 119 if (IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)) 120 flags |= AV_CPU_FLAG_DOTPROD; 121 #endif 122 #ifdef PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE 123 /* There's no PF_* flag that indicates whether plain I8MM is available 124 * or not. But if SVE_I8MM is available, that also implies that 125 * regular I8MM is available. */ 126 if (IsProcessorFeaturePresent(PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE)) 127 flags |= AV_CPU_FLAG_I8MM; 128 #endif 129 #ifdef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE 130 if (IsProcessorFeaturePresent(PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)) 131 flags |= AV_CPU_FLAG_SVE; 132 #endif 133 #ifdef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE 134 if (IsProcessorFeaturePresent(PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)) 135 flags |= AV_CPU_FLAG_SVE2; 136 #endif 137 return flags; 138 } 139 #else 140 141 static int detect_flags(void) 142 { 143 return 0; 144 } 145 146 #endif 147 148 int ff_get_cpu_flags_aarch64(void) 149 { 150 int flags = AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | 151 AV_CPU_FLAG_NEON * HAVE_NEON; 152 153 #ifdef __ARM_FEATURE_DOTPROD 154 flags |= AV_CPU_FLAG_DOTPROD; 155 #endif 156 #ifdef __ARM_FEATURE_MATMUL_INT8 157 flags |= AV_CPU_FLAG_I8MM; 158 #endif 159 #ifdef __ARM_FEATURE_SVE 160 flags |= AV_CPU_FLAG_SVE; 161 #endif 162 #ifdef __ARM_FEATURE_SVE2 163 flags |= AV_CPU_FLAG_SVE2; 164 #endif 165 166 flags |= detect_flags(); 167 168 return flags; 169 } 170 171 size_t ff_get_cpu_max_align_aarch64(void) 172 { 173 int flags = av_get_cpu_flags(); 174 175 if (flags & AV_CPU_FLAG_NEON) 176 return 16; 177 178 return 8; 179 }