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 15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int arm_cpu_env_flags(int *flags) { 16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang char *env; 17ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang env = getenv("VPX_SIMD_CAPS"); 18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (env && *env) { 19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *flags = (int)strtol(env, NULL, 0); 20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return 0; 21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *flags = 0; 23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return -1; 24538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 25538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int arm_cpu_env_mask(void) { 27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang char *env; 28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang env = getenv("VPX_SIMD_CAPS_MASK"); 29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return env && *env ? (int)strtol(env, NULL, 0) : ~0; 30538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 31538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 321b362b15af34006e6a11974088a46d42b903418eJohann#if !CONFIG_RUNTIME_CPU_DETECT 33538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint arm_cpu_caps(void) { 351b362b15af34006e6a11974088a46d42b903418eJohann /* This function should actually be a no-op. There is no way to adjust any of 361b362b15af34006e6a11974088a46d42b903418eJohann * these because the RTCD tables do not exist: the functions are called 371b362b15af34006e6a11974088a46d42b903418eJohann * statically */ 38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int flags; 39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int mask; 40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (!arm_cpu_env_flags(&flags)) { 41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags; 42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang mask = arm_cpu_env_mask(); 441b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_EDSP; 461b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 471b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_MEDIA; 491b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 501b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_NEON; 521b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags & mask; 541b362b15af34006e6a11974088a46d42b903418eJohann} 551b362b15af34006e6a11974088a46d42b903418eJohann 561b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(_MSC_VER) /* end !CONFIG_RUNTIME_CPU_DETECT */ 57538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ 58538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define WIN32_LEAN_AND_MEAN 59538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define WIN32_EXTRA_LEAN 60538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <windows.h> 61538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint arm_cpu_caps(void) { 63ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int flags; 64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int mask; 65ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (!arm_cpu_env_flags(&flags)) { 66ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags; 67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang mask = arm_cpu_env_mask(); 69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /* MSVC has no inline __asm support for ARM, but it does let you __emit 70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * instructions via their assembled hex code. 71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * All of these instructions should be essentially nops. 72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */ 731b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 74ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (mask & HAS_EDSP) { 75ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __try { 76ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*PLD [r13]*/ 77ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __emit(0xF5DDF000); 78ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_EDSP; 79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*Ignore exception.*/ 81538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 831b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 84ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (mask & HAS_MEDIA) 85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __try { 86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*SHADD8 r3,r3,r3*/ 87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __emit(0xE6333F93); 88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_MEDIA; 89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*Ignore exception.*/ 91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 931b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangif (mask &HAS_NEON) { 95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __try { 96ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*VORR q0,q0,q0*/ 97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang __emit(0xF2200150); 98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_NEON; 99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /*Ignore exception.*/ 101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang} 1031b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 1041b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 1051b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangreturn flags & mask; 1071b362b15af34006e6a11974088a46d42b903418eJohann} 1081b362b15af34006e6a11974088a46d42b903418eJohann 1091b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__ANDROID__) /* end _MSC_VER */ 1101b362b15af34006e6a11974088a46d42b903418eJohann#include <cpu-features.h> 1111b362b15af34006e6a11974088a46d42b903418eJohann 112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint arm_cpu_caps(void) { 113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int flags; 114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int mask; 115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang uint64_t features; 116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (!arm_cpu_env_flags(&flags)) { 117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags; 118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang mask = arm_cpu_env_mask(); 120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang features = android_getCpuFeatures(); 1211b362b15af34006e6a11974088a46d42b903418eJohann 1221b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_EDSP; 1241b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 1251b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_MEDIA; 1271b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_MEDIA */ 1281b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (features & ANDROID_CPU_ARM_FEATURE_NEON) 130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_NEON; 1311b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags & mask; 133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 134538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 1351b362b15af34006e6a11974088a46d42b903418eJohann#elif defined(__linux__) /* end __ANDROID__ */ 136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <stdio.h> 138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber 139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint arm_cpu_caps(void) { 140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang FILE *fin; 141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int flags; 142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int mask; 143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (!arm_cpu_env_flags(&flags)) { 144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags; 145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang mask = arm_cpu_env_mask(); 147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /* Reading /proc/self/auxv would be easier, but that doesn't work reliably 148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * on Android. 149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * This also means that detection will fail in Scratchbox. 150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */ 151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang fin = fopen("/proc/cpuinfo", "r"); 152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (fin != NULL) { 153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang /* 512 should be enough for anybody (it's even enough for all the flags 154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang * that x86 has accumulated... so far). 155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */ 156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang char buf[512]; 157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang while (fgets(buf, 511, fin) != NULL) { 1581b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP || HAVE_NEON 159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (memcmp(buf, "Features", 8) == 0) { 160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang char *p; 1611b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_EDSP 162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang p = strstr(buf, " edsp"); 163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_EDSP; 165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 1661b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_NEON 167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang p = strstr(buf, " neon"); 168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_NEON; 170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 1711b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_NEON */ 1721b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP */ 173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 1741b362b15af34006e6a11974088a46d42b903418eJohann#endif /* HAVE_EDSP || HAVE_NEON */ 1751b362b15af34006e6a11974088a46d42b903418eJohann#if HAVE_MEDIA 176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (memcmp(buf, "CPU architecture:", 17) == 0) { 177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang int version; 178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang version = atoi(buf + 17); 179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang if (version >= 6) { 180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang flags |= HAS_MEDIA; 181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif /* HAVE_MEDIA */ 184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber } 185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang fclose(fin); 186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang } 187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang return flags & mask; 188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} 1891b362b15af34006e6a11974088a46d42b903418eJohann#else /* end __linux__ */ 190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#error "--enable-runtime-cpu-detect selected, but no CPU detection method " \ 191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang"available for your platform. Reconfigure with --disable-runtime-cpu-detect." 192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#endif 193