1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mozglue/build/arm.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,241 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* compile-time and runtime tests for whether to use various ARM extensions */ 1.9 + 1.10 +#include "mozilla/NullPtr.h" 1.11 + 1.12 +#include "arm.h" 1.13 + 1.14 +#if defined(MOZILLA_ARM_HAVE_CPUID_DETECTION) 1.15 +namespace { 1.16 + 1.17 +// arm.h has parallel #ifs which declare MOZILLA_ARM_HAVE_CPUID_DETECTION. 1.18 +// We don't check it here so that we get compile errors if it's defined, but 1.19 +// we don't compile one of these detection methods. The detection code here is 1.20 +// based on the CPU detection in libtheora. 1.21 + 1.22 +# if defined(_MSC_VER) 1.23 +//For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION. 1.24 +# define WIN32_LEAN_AND_MEAN 1.25 +# define WIN32_EXTRA_LEAN 1.26 +# include <windows.h> 1.27 + 1.28 +# if !defined(MOZILLA_PRESUME_EDSP) 1.29 +static bool 1.30 +check_edsp(void) 1.31 +{ 1.32 +# if defined(MOZILLA_MAY_SUPPORT_EDSP) 1.33 + __try 1.34 + { 1.35 + //PLD [r13] 1.36 + __emit(0xF5DDF000); 1.37 + return true; 1.38 + } 1.39 + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION) 1.40 + { 1.41 + //Ignore exception. 1.42 + } 1.43 +# endif 1.44 + return false; 1.45 +} 1.46 +# endif // !MOZILLA_PRESUME_EDSP 1.47 + 1.48 +# if !defined(MOZILLA_PRESUME_ARMV6) 1.49 +static bool 1.50 +check_armv6(void) 1.51 +{ 1.52 +# if defined(MOZILLA_MAY_SUPPORT_ARMV6) 1.53 + __try 1.54 + { 1.55 + //SHADD8 r3,r3,r3 1.56 + __emit(0xE6333F93); 1.57 + return true; 1.58 + } 1.59 + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION) 1.60 + { 1.61 + //Ignore exception. 1.62 + } 1.63 +# endif 1.64 + return false; 1.65 +} 1.66 +# endif // !MOZILLA_PRESUME_ARMV6 1.67 + 1.68 +# if !defined(MOZILLA_PRESUME_ARMV7) 1.69 +static bool 1.70 +check_armv7(void) 1.71 +{ 1.72 +# if defined(MOZILLA_MAY_SUPPORT_ARMV7) 1.73 + __try 1.74 + { 1.75 + // ARMv7 DMB (Data Memory Barrier) for stores (DMB.ST) 1.76 + // The Data Memory Barrier existed before ARMv7 as a 1.77 + // cp15 operation, but ARMv7 introduced a dedicated 1.78 + // instruction, DMB. 1.79 + emit(0xF57FF05E); 1.80 + return true; 1.81 + } 1.82 + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION) 1.83 + { 1.84 + //Ignore exception. 1.85 + } 1.86 +# endif 1.87 + return false; 1.88 +} 1.89 +# endif // !MOZILLA_PRESUME_ARMV7 1.90 + 1.91 +# if !defined(MOZILLA_PRESUME_NEON) 1.92 +static bool 1.93 +check_neon(void) 1.94 +{ 1.95 +# if defined(MOZILLA_MAY_SUPPORT_NEON) 1.96 + __try 1.97 + { 1.98 + //VORR q0,q0,q0 1.99 + __emit(0xF2200150); 1.100 + return true; 1.101 + } 1.102 + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION) 1.103 + { 1.104 + //Ignore exception. 1.105 + } 1.106 +# endif 1.107 + return false; 1.108 +} 1.109 +# endif // !MOZILLA_PRESUME_NEON 1.110 + 1.111 +# elif defined(__linux__) || defined(ANDROID) 1.112 +# include <stdio.h> 1.113 +# include <stdlib.h> 1.114 +# include <string.h> 1.115 + 1.116 +enum{ 1.117 + MOZILLA_HAS_EDSP_FLAG=1, 1.118 + MOZILLA_HAS_ARMV6_FLAG=2, 1.119 + MOZILLA_HAS_ARMV7_FLAG=4, 1.120 + MOZILLA_HAS_NEON_FLAG=8 1.121 +}; 1.122 + 1.123 +static unsigned 1.124 +get_arm_cpu_flags(void) 1.125 +{ 1.126 + unsigned flags; 1.127 + FILE *fin; 1.128 + bool armv6_processor = false; 1.129 + flags = 0; 1.130 + /*Reading /proc/self/auxv would be easier, but that doesn't work reliably on 1.131 + Android. This also means that detection will fail in Scratchbox, which is 1.132 + desirable, as NEON does not work in the qemu shipped with the Maemo 5 SDK. 1.133 + I don't know if /proc/self/auxv would do any better in that case, anyway, 1.134 + or if it would return random flags from the host CPU.*/ 1.135 + fin = fopen ("/proc/cpuinfo","r"); 1.136 + if (fin != nullptr) 1.137 + { 1.138 + /*512 should be enough for anybody (it's even enough for all the flags that 1.139 + x86 has accumulated... so far).*/ 1.140 + char buf[512]; 1.141 + while (fgets(buf, 511, fin) != nullptr) 1.142 + { 1.143 + if (memcmp(buf, "Features", 8) == 0) 1.144 + { 1.145 + char *p; 1.146 + p = strstr(buf, " edsp"); 1.147 + if (p != nullptr && (p[5] == ' ' || p[5] == '\n')) 1.148 + flags |= MOZILLA_HAS_EDSP_FLAG; 1.149 + p = strstr(buf, " neon"); 1.150 + if( p != nullptr && (p[5] == ' ' || p[5] == '\n')) 1.151 + flags |= MOZILLA_HAS_NEON_FLAG; 1.152 + } 1.153 + if (memcmp(buf, "CPU architecture:", 17) == 0) 1.154 + { 1.155 + int version; 1.156 + version = atoi(buf + 17); 1.157 + if (version >= 6) 1.158 + flags |= MOZILLA_HAS_ARMV6_FLAG; 1.159 + if (version >= 7) 1.160 + flags |= MOZILLA_HAS_ARMV7_FLAG; 1.161 + } 1.162 + /* media/webrtc/trunk/src/system_wrappers/source/cpu_features_arm.c 1.163 + * Unfortunately, it seems that certain ARMv6-based CPUs 1.164 + * report an incorrect architecture number of 7! 1.165 + * 1.166 + * We try to correct this by looking at the 'elf_format' 1.167 + * field reported by the 'Processor' field, which is of the 1.168 + * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for 1.169 + * an ARMv6-one. 1.170 + */ 1.171 + if (memcmp(buf, "Processor\t:", 11) == 0) { 1.172 + if (strstr(buf, "(v6l)") != 0) { 1.173 + armv6_processor = true; 1.174 + } 1.175 + } 1.176 + } 1.177 + fclose(fin); 1.178 + } 1.179 + if (armv6_processor) { 1.180 + // ARMv6 pretending to be ARMv7? clear flag 1.181 + if (flags & MOZILLA_HAS_ARMV7_FLAG) { 1.182 + flags &= ~MOZILLA_HAS_ARMV7_FLAG; 1.183 + } 1.184 + } 1.185 + return flags; 1.186 +} 1.187 + 1.188 +// Cache a local copy so we only have to read /proc/cpuinfo once. 1.189 +static unsigned arm_cpu_flags = get_arm_cpu_flags(); 1.190 + 1.191 +# if !defined(MOZILLA_PRESUME_EDSP) 1.192 +static bool 1.193 +check_edsp(void) 1.194 +{ 1.195 + return (arm_cpu_flags & MOZILLA_HAS_EDSP_FLAG) != 0; 1.196 +} 1.197 +# endif 1.198 + 1.199 +# if !defined(MOZILLA_PRESUME_ARMV6) 1.200 +static bool 1.201 +check_armv6(void) 1.202 +{ 1.203 + return (arm_cpu_flags & MOZILLA_HAS_ARMV6_FLAG) != 0; 1.204 +} 1.205 +# endif 1.206 + 1.207 +# if !defined(MOZILLA_PRESUME_ARMV7) 1.208 +static bool 1.209 +check_armv7(void) 1.210 +{ 1.211 + return (arm_cpu_flags & MOZILLA_HAS_ARMV7_FLAG) != 0; 1.212 +} 1.213 +# endif 1.214 + 1.215 +# if !defined(MOZILLA_PRESUME_NEON) 1.216 +static bool 1.217 +check_neon(void) 1.218 +{ 1.219 + return (arm_cpu_flags & MOZILLA_HAS_NEON_FLAG) != 0; 1.220 +} 1.221 +# endif 1.222 + 1.223 +# endif // defined(__linux__) || defined(ANDROID) 1.224 + 1.225 +} 1.226 + 1.227 +namespace mozilla { 1.228 + namespace arm_private { 1.229 +# if !defined(MOZILLA_PRESUME_EDSP) 1.230 + bool edsp_enabled = check_edsp(); 1.231 +# endif 1.232 +# if !defined(MOZILLA_PRESUME_ARMV6) 1.233 + bool armv6_enabled = check_armv6(); 1.234 +# endif 1.235 +# if !defined(MOZILLA_PRESUME_ARMV7) 1.236 + bool armv7_enabled = check_armv7(); 1.237 +# endif 1.238 +# if !defined(MOZILLA_PRESUME_NEON) 1.239 + bool neon_enabled = check_neon(); 1.240 +# endif 1.241 + } // namespace arm_private 1.242 +} // namespace mozilla 1.243 + 1.244 +#endif // MOZILLA_ARM_HAVE_CPUID_DETECTION