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 static int arm_cpu_env_flags(int *flags) 16 { 17 char *env; 18 env = getenv("VPX_SIMD_CAPS"); 19 if (env && *env) 20 { 21 *flags = (int)strtol(env, NULL, 0); 22 return 0; 23 } 24 *flags = 0; 25 return -1; 26 } 27 28 static int arm_cpu_env_mask(void) 29 { 30 char *env; 31 env = getenv("VPX_SIMD_CAPS_MASK"); 32 return env && *env ? (int)strtol(env, NULL, 0) : ~0; 33 } 34 35 36 #if defined(_MSC_VER) 37 /*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ 38 #define WIN32_LEAN_AND_MEAN 39 #define WIN32_EXTRA_LEAN 40 #include <windows.h> 41 42 int arm_cpu_caps(void) 43 { 44 int flags; 45 int mask; 46 if (!arm_cpu_env_flags(&flags)) 47 { 48 return flags; 49 } 50 mask = arm_cpu_env_mask(); 51 /* MSVC has no inline __asm support for ARM, but it does let you __emit 52 * instructions via their assembled hex code. 53 * All of these instructions should be essentially nops. 54 */ 55 #if defined(HAVE_ARMV5TE) 56 if (mask & HAS_EDSP) 57 { 58 __try 59 { 60 /*PLD [r13]*/ 61 __emit(0xF5DDF000); 62 flags |= HAS_EDSP; 63 } 64 __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 65 { 66 /*Ignore exception.*/ 67 } 68 } 69 #if defined(HAVE_ARMV6) 70 if (mask & HAS_MEDIA) 71 __try 72 { 73 /*SHADD8 r3,r3,r3*/ 74 __emit(0xE6333F93); 75 flags |= HAS_MEDIA; 76 } 77 __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 78 { 79 /*Ignore exception.*/ 80 } 81 } 82 #if defined(HAVE_ARMV7) 83 if (mask & HAS_NEON) 84 { 85 __try 86 { 87 /*VORR q0,q0,q0*/ 88 __emit(0xF2200150); 89 flags |= HAS_NEON; 90 } 91 __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) 92 { 93 /*Ignore exception.*/ 94 } 95 } 96 #endif 97 #endif 98 #endif 99 return flags & mask; 100 } 101 102 #elif defined(__linux__) 103 #include <stdio.h> 104 105 int arm_cpu_caps(void) 106 { 107 FILE *fin; 108 int flags; 109 int mask; 110 if (!arm_cpu_env_flags(&flags)) 111 { 112 return flags; 113 } 114 mask = arm_cpu_env_mask(); 115 /* Reading /proc/self/auxv would be easier, but that doesn't work reliably 116 * on Android. 117 * This also means that detection will fail in Scratchbox. 118 */ 119 fin = fopen("/proc/cpuinfo","r"); 120 if(fin != NULL) 121 { 122 /* 512 should be enough for anybody (it's even enough for all the flags 123 * that x86 has accumulated... so far). 124 */ 125 char buf[512]; 126 while (fgets(buf, 511, fin) != NULL) 127 { 128 #if defined(HAVE_ARMV5TE) || defined(HAVE_ARMV7) 129 if (memcmp(buf, "Features", 8) == 0) 130 { 131 char *p; 132 #if defined(HAVE_ARMV5TE) 133 p=strstr(buf, " edsp"); 134 if (p != NULL && (p[5] == ' ' || p[5] == '\n')) 135 { 136 flags |= HAS_EDSP; 137 } 138 #if defined(HAVE_ARMV7) 139 p = strstr(buf, " neon"); 140 if (p != NULL && (p[5] == ' ' || p[5] == '\n')) 141 { 142 flags |= HAS_NEON; 143 } 144 #endif 145 #endif 146 } 147 #endif 148 #if defined(HAVE_ARMV6) 149 if (memcmp(buf, "CPU architecture:",17) == 0){ 150 int version; 151 version = atoi(buf+17); 152 if (version >= 6) 153 { 154 flags |= HAS_MEDIA; 155 } 156 } 157 #endif 158 } 159 fclose(fin); 160 } 161 return flags & mask; 162 } 163 164 #elif !CONFIG_RUNTIME_CPU_DETECT 165 166 int arm_cpu_caps(void) 167 { 168 int flags; 169 int mask; 170 if (!arm_cpu_env_flags(&flags)) 171 { 172 return flags; 173 } 174 mask = arm_cpu_env_mask(); 175 #if defined(HAVE_ARMV5TE) 176 flags |= HAS_EDSP; 177 #endif 178 #if defined(HAVE_ARMV6) 179 flags |= HAS_MEDIA; 180 #endif 181 #if defined(HAVE_ARMV7) 182 flags |= HAS_NEON; 183 #endif 184 return flags & mask; 185 } 186 187 #else 188 #error "--enable-runtime-cpu-detect selected, but no CPU detection method " \ 189 "available for your platform. Reconfigure without --enable-runtime-cpu-detect." 190 #endif 191