1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/arm/Architecture-arm.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,293 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "jit/arm/Architecture-arm.h" 1.11 + 1.12 +#ifndef JS_ARM_SIMULATOR 1.13 +#include <elf.h> 1.14 +#endif 1.15 + 1.16 +#include <fcntl.h> 1.17 +#include <unistd.h> 1.18 + 1.19 +#include "jit/arm/Assembler-arm.h" 1.20 + 1.21 +#define HWCAP_USE_HARDFP_ABI (1 << 28) 1.22 + 1.23 +#if !(defined(ANDROID) || defined(MOZ_B2G)) && !defined(JS_ARM_SIMULATOR) 1.24 +#define HWCAP_ARMv7 (1 << 29) 1.25 +#include <asm/hwcap.h> 1.26 +#else 1.27 +#define HWCAP_VFP (1<<0) 1.28 +#define HWCAP_VFPv3 (1<<1) 1.29 +#define HWCAP_VFPv3D16 (1<<2) 1.30 +#define HWCAP_VFPv4 (1<<3) 1.31 +#define HWCAP_IDIVA (1<<4) 1.32 +#define HWCAP_IDIVT (1<<5) 1.33 +#define HWCAP_NEON (1<<6) 1.34 +#define HWCAP_ARMv7 (1<<7) 1.35 +#endif 1.36 + 1.37 +namespace js { 1.38 +namespace jit { 1.39 + 1.40 +uint32_t GetARMFlags() 1.41 +{ 1.42 + static bool isSet = false; 1.43 + static uint32_t flags = 0; 1.44 + if (isSet) 1.45 + return flags; 1.46 + 1.47 +#ifdef JS_CODEGEN_ARM_HARDFP 1.48 + flags |= HWCAP_USE_HARDFP_ABI; 1.49 +#endif 1.50 + 1.51 + static const char *env = getenv("ARMHWCAP"); 1.52 + 1.53 + if (env && env[0]) { 1.54 + if (strstr(env, "help")) { 1.55 + fflush(NULL); 1.56 + printf( 1.57 + "\n" 1.58 + "usage: ARMHWCAP=option,option,option,... where options can be:\n" 1.59 + "\n" 1.60 + " armv7 \n" 1.61 + " vfp \n" 1.62 + " neon \n" 1.63 + " vfpv3 \n" 1.64 + " vfpv3d16 \n" 1.65 + " vfpv4 \n" 1.66 + " idiva \n" 1.67 + " idivt \n" 1.68 +#if defined(JS_ARM_SIMULATOR) 1.69 + " hardfp \n" 1.70 +#endif 1.71 + "\n" 1.72 + ); 1.73 + exit(0); 1.74 + /*NOTREACHED*/ 1.75 + } else { 1.76 + // Canonicalize each token to have a leading and trailing space. 1.77 + const char *start = env; // Token start. 1.78 + for (;;) { 1.79 + char ch = *start; 1.80 + if (!ch) { 1.81 + // End of string. 1.82 + break; 1.83 + } 1.84 + if (ch == ' ' || ch == ',') { 1.85 + // Skip separator characters. 1.86 + start++; 1.87 + continue; 1.88 + } 1.89 + // Find the end of the token. 1.90 + const char *end = start + 1; 1.91 + for (; ; end++) { 1.92 + ch = *end; 1.93 + if (!ch || ch == ' ' || ch == ',') 1.94 + break; 1.95 + } 1.96 + size_t count = end - start; 1.97 + if (count == 3 && strncmp(start, "vfp", 3) == 0) 1.98 + flags |= HWCAP_VFP; 1.99 + else if (count == 5 && strncmp(start, "vfpv3", 5) == 0) 1.100 + flags |= HWCAP_VFPv3; 1.101 + else if (count == 8 && strncmp(start, "vfpv3d16", 8) == 0) 1.102 + flags |= HWCAP_VFPv3D16; 1.103 + else if (count == 5 && strncmp(start, "vfpv4", 5) == 0) 1.104 + flags |= HWCAP_VFPv4; 1.105 + else if (count == 5 && strncmp(start, "idiva", 5) == 0) 1.106 + flags |= HWCAP_IDIVA; 1.107 + else if (count == 5 && strncmp(start, "idivt", 5) == 0) 1.108 + flags |= HWCAP_IDIVT; 1.109 + else if (count == 4 && strncmp(start, "neon", 4) == 0) 1.110 + flags |= HWCAP_NEON; 1.111 + else if (count == 5 && strncmp(start, "armv7", 5) == 0) 1.112 + flags |= HWCAP_ARMv7; 1.113 +#if defined(JS_ARM_SIMULATOR) 1.114 + else if (count == 6 && strncmp(start, "hardfp", 6) == 0) 1.115 + flags |= HWCAP_USE_HARDFP_ABI; 1.116 +#endif 1.117 + else 1.118 + fprintf(stderr, "Warning: unexpected ARMHWCAP flag at: %s\n", start); 1.119 + start = end; 1.120 + } 1.121 +#ifdef DEBUG 1.122 + IonSpew(IonSpew_Codegen, "ARMHWCAP: '%s'\n flags: 0x%x\n", env, flags); 1.123 +#endif 1.124 + isSet = true; 1.125 + return flags; 1.126 + } 1.127 + } 1.128 + 1.129 +#ifdef JS_ARM_SIMULATOR 1.130 + isSet = true; 1.131 + flags = HWCAP_ARMv7 | HWCAP_VFP | HWCAP_VFPv3 | HWCAP_VFPv4 | HWCAP_NEON; 1.132 + return flags; 1.133 +#else 1.134 + 1.135 +#if WTF_OS_LINUX 1.136 + int fd = open("/proc/self/auxv", O_RDONLY); 1.137 + if (fd > 0) { 1.138 + Elf32_auxv_t aux; 1.139 + while (read(fd, &aux, sizeof(Elf32_auxv_t))) { 1.140 + if (aux.a_type == AT_HWCAP) { 1.141 + close(fd); 1.142 + flags = aux.a_un.a_val; 1.143 + isSet = true; 1.144 +#if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__) 1.145 + // this should really be detected at runtime, but 1.146 + // /proc/*/auxv doesn't seem to carry the ISA 1.147 + // I could look in /proc/cpuinfo as well, but 1.148 + // the chances that it will be different from this 1.149 + // are low. 1.150 + flags |= HWCAP_ARMv7; 1.151 +#endif 1.152 + return flags; 1.153 + } 1.154 + } 1.155 + close(fd); 1.156 + } 1.157 + 1.158 +#if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__) 1.159 + flags = HWCAP_ARMv7; 1.160 +#endif 1.161 + isSet = true; 1.162 + return flags; 1.163 + 1.164 +#elif defined(WTF_OS_ANDROID) || defined(MOZ_B2G) 1.165 + FILE *fp = fopen("/proc/cpuinfo", "r"); 1.166 + if (!fp) 1.167 + return false; 1.168 + 1.169 + char buf[1024]; 1.170 + memset(buf, 0, sizeof(buf)); 1.171 + size_t len = fread(buf, sizeof(char), sizeof(buf) - 2, fp); 1.172 + fclose(fp); 1.173 + // Canonicalize each token to have a leading and trailing space. 1.174 + buf[len] = ' '; 1.175 + buf[len + 1] = '\0'; 1.176 + for (size_t i = 0; i < len; i++) { 1.177 + char ch = buf[i]; 1.178 + if (!ch) 1.179 + break; 1.180 + else if (ch == '\n') 1.181 + buf[i] = 0x20; 1.182 + else 1.183 + buf[i] = ch; 1.184 + } 1.185 + 1.186 + if (strstr(buf, " vfp ")) 1.187 + flags |= HWCAP_VFP; 1.188 + 1.189 + if (strstr(buf, " vfpv3 ")) 1.190 + flags |= HWCAP_VFPv3; 1.191 + 1.192 + if (strstr(buf, " vfpv3d16 ")) 1.193 + flags |= HWCAP_VFPv3D16; 1.194 + 1.195 + if (strstr(buf, " vfpv4 ")) 1.196 + flags |= HWCAP_VFPv4; 1.197 + 1.198 + if (strstr(buf, " idiva ")) 1.199 + flags |= HWCAP_IDIVA; 1.200 + 1.201 + if (strstr(buf, " idivt ")) 1.202 + flags |= HWCAP_IDIVT; 1.203 + 1.204 + if (strstr(buf, " neon ")) 1.205 + flags |= HWCAP_NEON; 1.206 + 1.207 + // not part of the HWCAP flag, but I need to know this, and we're not using 1.208 + // that bit, so... I'm using it 1.209 + if (strstr(buf, "ARMv7")) 1.210 + flags |= HWCAP_ARMv7; 1.211 + 1.212 +#ifdef DEBUG 1.213 + IonSpew(IonSpew_Codegen, "ARMHWCAP: '%s'\n flags: 0x%x\n", buf, flags); 1.214 +#endif 1.215 + 1.216 + isSet = true; 1.217 + return flags; 1.218 +#endif 1.219 + 1.220 + return 0; 1.221 +#endif // JS_ARM_SIMULATOR 1.222 +} 1.223 + 1.224 +bool hasMOVWT() 1.225 +{ 1.226 + return GetARMFlags() & HWCAP_ARMv7; 1.227 +} 1.228 +bool hasVFPv3() 1.229 +{ 1.230 + return GetARMFlags() & HWCAP_VFPv3; 1.231 +} 1.232 +bool hasVFP() 1.233 +{ 1.234 + return GetARMFlags() & HWCAP_VFP; 1.235 +} 1.236 + 1.237 +bool has32DP() 1.238 +{ 1.239 + return !(GetARMFlags() & HWCAP_VFPv3D16 && !(GetARMFlags() & HWCAP_NEON)); 1.240 +} 1.241 +bool useConvReg() 1.242 +{ 1.243 + return has32DP(); 1.244 +} 1.245 + 1.246 +bool hasIDIV() 1.247 +{ 1.248 +#if defined HWCAP_IDIVA 1.249 + return GetARMFlags() & HWCAP_IDIVA; 1.250 +#else 1.251 + return false; 1.252 +#endif 1.253 +} 1.254 + 1.255 +// This is defined in the header and inlined when not using the simulator. 1.256 +#if defined(JS_ARM_SIMULATOR) 1.257 +bool useHardFpABI() 1.258 +{ 1.259 + return GetARMFlags() & HWCAP_USE_HARDFP_ABI; 1.260 +} 1.261 +#endif 1.262 + 1.263 +Registers::Code 1.264 +Registers::FromName(const char *name) 1.265 +{ 1.266 + // Check for some register aliases first. 1.267 + if (strcmp(name, "ip") == 0) 1.268 + return ip; 1.269 + if (strcmp(name, "r13") == 0) 1.270 + return r13; 1.271 + if (strcmp(name, "lr") == 0) 1.272 + return lr; 1.273 + if (strcmp(name, "r15") == 0) 1.274 + return r15; 1.275 + 1.276 + for (size_t i = 0; i < Total; i++) { 1.277 + if (strcmp(GetName(i), name) == 0) 1.278 + return Code(i); 1.279 + } 1.280 + 1.281 + return Invalid; 1.282 +} 1.283 + 1.284 +FloatRegisters::Code 1.285 +FloatRegisters::FromName(const char *name) 1.286 +{ 1.287 + for (size_t i = 0; i < Total; i++) { 1.288 + if (strcmp(GetName(i), name) == 0) 1.289 + return Code(i); 1.290 + } 1.291 + 1.292 + return Invalid; 1.293 +} 1.294 + 1.295 +} // namespace jit 1.296 +} // namespace js