arm_cpudetect.c revision 1b362b15af34006e6a11974088a46d42b903418e
1538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* 2538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * 4538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * Use of this source code is governed by a BSD-style license 5538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * that can be found in the LICENSE file in the root of the source 6538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * tree. An additional intellectual property rights grant can be found 7538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * in the file PATENTS. All contributing project authors may 8538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * be found in the AUTHORS file in the root of the source tree. 9538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */ 10538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 11538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <stdlib.h> 12538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <string.h> 13538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "arm.h" 14538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 15538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int arm_cpu_env_flags(int *flags) 16538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{ 17538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber char *env; 18538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber env = getenv("VPX_SIMD_CAPS"); 19538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (env && *env) 20538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 21538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *flags = (int)strtol(env, NULL, 0); 22538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return 0; 23538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 24538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *flags = 0; 25538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return -1; 26538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 27538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 28538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int arm_cpu_env_mask(void) 29538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{ 30538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber char *env; 31538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber env = getenv("VPX_SIMD_CAPS_MASK"); 32538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return env && *env ? (int)strtol(env, NULL, 0) : ~0; 33538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 34538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 351b362b15af34006e6a11974088a46d42b903418eJohann#if !CONFIG_RUNTIME_CPU_DETECT 36538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 371b362b15af34006e6a11974088a46d42b903418eJohannint arm_cpu_caps(void) 381b362b15af34006e6a11974088a46d42b903418eJohann{ 391b362b15af34006e6a11974088a46d42b903418eJohann /* This function should actually be a no-op. There is no way to adjust any of 401b362b15af34006e6a11974088a46d42b903418eJohann * these because the RTCD tables do not exist: the functions are called 411b362b15af34006e6a11974088a46d42b903418eJohann * statically */ 421b362b15af34006e6a11974088a46d42b903418eJohann int flags; 431b362b15af34006e6a11974088a46d42b903418eJohann int mask; 441b362b15af34006e6a11974088a46d42b903418eJohann if (!arm_cpu_env_flags(&flags)) 451b362b15af34006e6a11974088a46d42b903418eJohann { 461b362b15af34006e6a11974088a46d42b903418eJohann return flags; 471b362b15af34006e6a11974088a46d42b903418eJohann } 481b362b15af34006e6a11974088a46d42b903418eJohann mask = arm_cpu_env_mask(); 491b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 501b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_EDSP; 511b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 521b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 531b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_MEDIA; 541b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 551b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 561b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_NEON; 571b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 581b362b15af34006e6a11974088a46d42b903418eJohann return flags & mask; 591b362b15af34006e6a11974088a46d42b903418eJohann} 601b362b15af34006e6a11974088a46d42b903418eJohann 611b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(_MSC_VER) /* end !CONFIG_RUNTIME_CPU_DETECT */ 62538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ 63538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define WIN32_LEAN_AND_MEAN 64538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define WIN32_EXTRA_LEAN 65538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <windows.h> 66538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 67538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint arm_cpu_caps(void) 68538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{ 69538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber int flags; 70538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber int mask; 71538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (!arm_cpu_env_flags(&flags)) 72538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 73538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return flags; 74538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 75538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber mask = arm_cpu_env_mask(); 76538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /* MSVC has no inline __asm support for ARM, but it does let you __emit 77538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * instructions via their assembled hex code. 78538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * All of these instructions should be essentially nops. 79538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */ 801b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 81538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (mask & HAS_EDSP) 82538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 83538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __try 84538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 85538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*PLD [r13]*/ 86538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __emit(0xF5DDF000); 87538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_EDSP; 88538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 89538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 90538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 91538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*Ignore exception.*/ 92538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 93538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 941b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 95538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (mask & HAS_MEDIA) 96538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __try 97538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 98538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*SHADD8 r3,r3,r3*/ 99538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __emit(0xE6333F93); 100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_MEDIA; 101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*Ignore exception.*/ 105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 1071b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (mask & HAS_NEON) 109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __try 111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*VORR q0,q0,q0*/ 113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __emit(0xF2200150); 114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_NEON; 115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /*Ignore exception.*/ 119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 1211b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 1221b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 1231b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 1241b362b15af34006e6a11974088a46d42b903418eJohann return flags & mask; 1251b362b15af34006e6a11974088a46d42b903418eJohann} 1261b362b15af34006e6a11974088a46d42b903418eJohann 1271b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__ANDROID__) /* end _MSC_VER */ 1281b362b15af34006e6a11974088a46d42b903418eJohann#include <cpu-features.h> 1291b362b15af34006e6a11974088a46d42b903418eJohann 1301b362b15af34006e6a11974088a46d42b903418eJohannint arm_cpu_caps(void) 1311b362b15af34006e6a11974088a46d42b903418eJohann{ 1321b362b15af34006e6a11974088a46d42b903418eJohann int flags; 1331b362b15af34006e6a11974088a46d42b903418eJohann int mask; 1341b362b15af34006e6a11974088a46d42b903418eJohann uint64_t features; 1351b362b15af34006e6a11974088a46d42b903418eJohann if (!arm_cpu_env_flags(&flags)) 1361b362b15af34006e6a11974088a46d42b903418eJohann { 1371b362b15af34006e6a11974088a46d42b903418eJohann return flags; 1381b362b15af34006e6a11974088a46d42b903418eJohann } 1391b362b15af34006e6a11974088a46d42b903418eJohann mask = arm_cpu_env_mask(); 1401b362b15af34006e6a11974088a46d42b903418eJohann features = android_getCpuFeatures(); 1411b362b15af34006e6a11974088a46d42b903418eJohann 1421b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 1431b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_EDSP; 1441b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 1451b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 1461b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_MEDIA; 1471b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 1481b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 1491b362b15af34006e6a11974088a46d42b903418eJohann if (features & ANDROID_CPU_ARM_FEATURE_NEON) 1501b362b15af34006e6a11974088a46d42b903418eJohann flags |= HAS_NEON; 1511b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return flags & mask; 153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 1551b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__linux__) /* end __ANDROID__ */ 156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <stdio.h> 157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint arm_cpu_caps(void) 159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{ 160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber FILE *fin; 161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber int flags; 162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber int mask; 163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (!arm_cpu_env_flags(&flags)) 164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return flags; 166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber mask = arm_cpu_env_mask(); 168538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /* Reading /proc/self/auxv would be easier, but that doesn't work reliably 169538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * on Android. 170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * This also means that detection will fail in Scratchbox. 171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */ 172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber fin = fopen("/proc/cpuinfo","r"); 173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if(fin != NULL) 174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber /* 512 should be enough for anybody (it's even enough for all the flags 176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * that x86 has accumulated... so far). 177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */ 178538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber char buf[512]; 179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber while (fgets(buf, 511, fin) != NULL) 180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 1811b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP || HAVE_NEON 182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (memcmp(buf, "Features", 8) == 0) 183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber char *p; 1851b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber p=strstr(buf, " edsp"); 187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (p != NULL && (p[5] == ' ' || p[5] == '\n')) 188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_EDSP; 190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 1911b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber p = strstr(buf, " neon"); 193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (p != NULL && (p[5] == ' ' || p[5] == '\n')) 194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_NEON; 196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 1971b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 1981b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 199538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 2001b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP || HAVE_NEON */ 2011b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (memcmp(buf, "CPU architecture:",17) == 0){ 203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber int version; 204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber version = atoi(buf+17); 205538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber if (version >= 6) 206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber { 207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber flags |= HAS_MEDIA; 208538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 209538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 2101b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 211538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 212538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber fclose(fin); 213538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 214538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber return flags & mask; 215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 2161b362b15af34006e6a11974088a46d42b903418eJohann#else /* end __linux__ */ 217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#error "--enable-runtime-cpu-detect selected, but no CPU detection method " \ 2181b362b15af34006e6a11974088a46d42b903418eJohann "available for your platform. Reconfigure with --disable-runtime-cpu-detect." 219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#endif 220