1/* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include <stdlib.h> 12#include <string.h> 13#include "arm.h" 14 15#ifdef WINAPI_FAMILY 16#include <winapifamily.h> 17#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 18#define getenv(x) NULL 19#endif 20#endif 21 22static int arm_cpu_env_flags(int *flags) { 23 char *env; 24 env = getenv("VPX_SIMD_CAPS"); 25 if (env && *env) { 26 *flags = (int)strtol(env, NULL, 0); 27 return 0; 28 } 29 *flags = 0; 30 return -1; 31} 32 33static int arm_cpu_env_mask(void) { 34 char *env; 35 env = getenv("VPX_SIMD_CAPS_MASK"); 36 return env && *env ? (int)strtol(env, NULL, 0) : ~0; 37} 38 39#if !CONFIG_RUNTIME_CPU_DETECT 40 41int arm_cpu_caps(void) { 42 /* This function should actually be a no-op. There is no way to adjust any of 43 * these because the RTCD tables do not exist: the functions are called 44 * statically */ 45 int flags; 46 int mask; 47 if (!arm_cpu_env_flags(&flags)) { 48 return flags; 49 } 50 mask = arm_cpu_env_mask(); 51#if HAVE_EDSP 52 flags |= HAS_EDSP; 53#endif /* HAVE_EDSP */ 54#if HAVE_MEDIA 55 flags |= HAS_MEDIA; 56#endif /* HAVE_MEDIA */ 57#if HAVE_NEON 58 flags |= HAS_NEON; 59#endif /* HAVE_NEON */ 60 return flags & mask; 61} 62 63#elif defined(_MSC_VER) /* end !CONFIG_RUNTIME_CPU_DETECT */ 64/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ 65#define WIN32_LEAN_AND_MEAN 66#define WIN32_EXTRA_LEAN 67#include <windows.h> 68 69int arm_cpu_caps(void) { 70 int flags; 71 int mask; 72 if (!arm_cpu_env_flags(&flags)) { 73 return flags; 74 } 75 mask = arm_cpu_env_mask(); 76 /* MSVC has no inline __asm support for ARM, but it does let you __emit 77 * instructions via their assembled hex code. 78 * All of these instructions should be essentially nops. 79 */ 80#if HAVE_EDSP 81 if (mask & HAS_EDSP) { 82 __try { 83 /*PLD [r13]*/ 84 __emit(0xF5DDF000); 85 flags |= HAS_EDSP; 86 } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 87 /*Ignore exception.*/ 88 } 89 } 90#if HAVE_MEDIA 91 if (mask & HAS_MEDIA) 92 __try { 93 /*SHADD8 r3,r3,r3*/ 94 __emit(0xE6333F93); 95 flags |= HAS_MEDIA; 96 } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 97 /*Ignore exception.*/ 98 } 99} 100#if HAVE_NEON 101if (mask &HAS_NEON) { 102 __try { 103 /*VORR q0,q0,q0*/ 104 __emit(0xF2200150); 105 flags |= HAS_NEON; 106 } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 107 /*Ignore exception.*/ 108 } 109} 110#endif /* HAVE_NEON */ 111#endif /* HAVE_MEDIA */ 112#endif /* HAVE_EDSP */ 113return flags & mask; 114} 115 116#elif defined(__ANDROID__) /* end _MSC_VER */ 117#include <cpu-features.h> 118 119int arm_cpu_caps(void) { 120 int flags; 121 int mask; 122 uint64_t features; 123 if (!arm_cpu_env_flags(&flags)) { 124 return flags; 125 } 126 mask = arm_cpu_env_mask(); 127 features = android_getCpuFeatures(); 128 129#if HAVE_EDSP 130 flags |= HAS_EDSP; 131#endif /* HAVE_EDSP */ 132#if HAVE_MEDIA 133 flags |= HAS_MEDIA; 134#endif /* HAVE_MEDIA */ 135#if HAVE_NEON 136 if (features & ANDROID_CPU_ARM_FEATURE_NEON) 137 flags |= HAS_NEON; 138#endif /* HAVE_NEON */ 139 return flags & mask; 140} 141 142#elif defined(__linux__) /* end __ANDROID__ */ 143 144#include <stdio.h> 145 146int arm_cpu_caps(void) { 147 FILE *fin; 148 int flags; 149 int mask; 150 if (!arm_cpu_env_flags(&flags)) { 151 return flags; 152 } 153 mask = arm_cpu_env_mask(); 154 /* Reading /proc/self/auxv would be easier, but that doesn't work reliably 155 * on Android. 156 * This also means that detection will fail in Scratchbox. 157 */ 158 fin = fopen("/proc/cpuinfo", "r"); 159 if (fin != NULL) { 160 /* 512 should be enough for anybody (it's even enough for all the flags 161 * that x86 has accumulated... so far). 162 */ 163 char buf[512]; 164 while (fgets(buf, 511, fin) != NULL) { 165#if HAVE_EDSP || HAVE_NEON 166 if (memcmp(buf, "Features", 8) == 0) { 167 char *p; 168#if HAVE_EDSP 169 p = strstr(buf, " edsp"); 170 if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 171 flags |= HAS_EDSP; 172 } 173#if HAVE_NEON 174 p = strstr(buf, " neon"); 175 if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 176 flags |= HAS_NEON; 177 } 178#endif /* HAVE_NEON */ 179#endif /* HAVE_EDSP */ 180 } 181#endif /* HAVE_EDSP || HAVE_NEON */ 182#if HAVE_MEDIA 183 if (memcmp(buf, "CPU architecture:", 17) == 0) { 184 int version; 185 version = atoi(buf + 17); 186 if (version >= 6) { 187 flags |= HAS_MEDIA; 188 } 189 } 190#endif /* HAVE_MEDIA */ 191 } 192 fclose(fin); 193 } 194 return flags & mask; 195} 196#else /* end __linux__ */ 197#error "--enable-runtime-cpu-detect selected, but no CPU detection method " \ 198"available for your platform. Reconfigure with --disable-runtime-cpu-detect." 199#endif 200