| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/simulator.h" | 9 #include "vm/simulator.h" |
| 10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
| 11 #include "vm/stack_frame.h" | 11 #include "vm/stack_frame.h" |
| 12 #include "vm/stub_code.h" | 12 #include "vm/stub_code.h" |
| 13 | 13 |
| 14 // An extra check since we are assuming the existence of /proc/cpuinfo below. | 14 // An extra check since we are assuming the existence of /proc/cpuinfo below. |
| 15 #if !defined(USING_SIMULATOR) && !defined(__linux__) | 15 #if !defined(USING_SIMULATOR) && !defined(__linux__) |
| 16 #error ARM cross-compile only supported on Linux | 16 #error ARM cross-compile only supported on Linux |
| 17 #endif | 17 #endif |
| 18 | 18 |
| 19 namespace dart { | 19 namespace dart { |
| 20 | 20 |
| 21 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); | 21 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
| 22 DECLARE_FLAG(bool, inline_alloc); | 22 DECLARE_FLAG(bool, inline_alloc); |
| 23 | 23 |
| 24 bool CPUFeatures::integer_division_supported_ = false; | 24 bool CPUFeatures::integer_division_supported_ = false; |
| 25 bool CPUFeatures::neon_supported_ = false; |
| 25 #if defined(DEBUG) | 26 #if defined(DEBUG) |
| 26 bool CPUFeatures::initialized_ = false; | 27 bool CPUFeatures::initialized_ = false; |
| 27 #endif | 28 #endif |
| 28 | 29 |
| 29 | 30 |
| 30 bool CPUFeatures::integer_division_supported() { | 31 bool CPUFeatures::integer_division_supported() { |
| 31 DEBUG_ASSERT(initialized_); | 32 DEBUG_ASSERT(initialized_); |
| 32 return integer_division_supported_; | 33 return integer_division_supported_; |
| 33 } | 34 } |
| 34 | 35 |
| 35 | 36 |
| 37 bool CPUFeatures::neon_supported() { |
| 38 DEBUG_ASSERT(initialized_); |
| 39 return neon_supported_; |
| 40 } |
| 41 |
| 42 |
| 36 // If we are using the simulator, allow tests to enable/disable support for | 43 // If we are using the simulator, allow tests to enable/disable support for |
| 37 // integer division. | 44 // integer division. |
| 38 #if defined(USING_SIMULATOR) | 45 #if defined(USING_SIMULATOR) |
| 39 void CPUFeatures::set_integer_division_supported(bool supported) { | 46 void CPUFeatures::set_integer_division_supported(bool supported) { |
| 40 integer_division_supported_ = supported; | 47 integer_division_supported_ = supported; |
| 41 } | 48 } |
| 49 |
| 50 |
| 51 void CPUFeatures::set_neon_supported(bool supported) { |
| 52 neon_supported_ = supported; |
| 53 } |
| 42 #endif | 54 #endif |
| 43 | 55 |
| 44 | 56 |
| 45 // Probe /proc/cpuinfo for features of the ARM processor. | 57 // Probe /proc/cpuinfo for features of the ARM processor. |
| 46 #if !defined(USING_SIMULATOR) | 58 #if !defined(USING_SIMULATOR) |
| 47 static bool CPUInfoContainsString(const char* search_string) { | 59 static bool CPUInfoContainsString(const char* search_string) { |
| 48 const char* file_name = "/proc/cpuinfo"; | 60 const char* file_name = "/proc/cpuinfo"; |
| 49 // This is written as a straight shot one pass parser | 61 // This is written as a straight shot one pass parser |
| 50 // and not using STL string and ifstream because, | 62 // and not using STL string and ifstream because, |
| 51 // on Linux, it's reading from a (non-mmap-able) | 63 // on Linux, it's reading from a (non-mmap-able) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 74 fclose(f); | 86 fclose(f); |
| 75 | 87 |
| 76 // Did not find string in the proc file. | 88 // Did not find string in the proc file. |
| 77 return false; | 89 return false; |
| 78 } | 90 } |
| 79 #endif | 91 #endif |
| 80 | 92 |
| 81 void CPUFeatures::InitOnce() { | 93 void CPUFeatures::InitOnce() { |
| 82 #if defined(USING_SIMULATOR) | 94 #if defined(USING_SIMULATOR) |
| 83 integer_division_supported_ = true; | 95 integer_division_supported_ = true; |
| 96 neon_supported_ = true; |
| 84 #else | 97 #else |
| 85 ASSERT(CPUInfoContainsString("ARMv7")); // Implements ARMv7. | 98 ASSERT(CPUInfoContainsString("ARMv7")); // Implements ARMv7. |
| 86 ASSERT(CPUInfoContainsString("vfp")); // Has floating point unit. | 99 ASSERT(CPUInfoContainsString("vfp")); // Has floating point unit. |
| 87 // Has integer division. | 100 // Has integer division. |
| 88 integer_division_supported_ = CPUInfoContainsString("idiva"); | 101 integer_division_supported_ = CPUInfoContainsString("idiva"); |
| 102 neon_supported_ = CPUInfoContainsString("neon"); |
| 89 #endif // defined(USING_SIMULATOR) | 103 #endif // defined(USING_SIMULATOR) |
| 90 #if defined(DEBUG) | 104 #if defined(DEBUG) |
| 91 initialized_ = true; | 105 initialized_ = true; |
| 92 #endif | 106 #endif |
| 93 } | 107 } |
| 94 | 108 |
| 95 | 109 |
| 96 // Instruction encoding bits. | 110 // Instruction encoding bits. |
| 97 enum { | 111 enum { |
| 98 H = 1 << 5, // halfword (or byte) | 112 H = 1 << 5, // halfword (or byte) |
| (...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR | 1212 void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR |
| 1199 ASSERT(cond != kNoCondition); | 1213 ASSERT(cond != kNoCondition); |
| 1200 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | | 1214 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | |
| 1201 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | | 1215 B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | |
| 1202 (static_cast<int32_t>(PC)*B12) | | 1216 (static_cast<int32_t>(PC)*B12) | |
| 1203 B11 | B9 | B4; | 1217 B11 | B9 | B4; |
| 1204 Emit(encoding); | 1218 Emit(encoding); |
| 1205 } | 1219 } |
| 1206 | 1220 |
| 1207 | 1221 |
| 1222 void Assembler::EmitSIMDqqq(int32_t opcode, int sz, |
| 1223 QRegister qd, QRegister qn, QRegister qm) { |
| 1224 int32_t encoding = |
| 1225 (static_cast<int32_t>(kSpecialCondition) << kConditionShift) | |
| 1226 B25 | B6 | |
| 1227 opcode | ((sz & 0x3) * B20) | |
| 1228 ((static_cast<int32_t>(qd * 2) >> 4)*B22) | |
| 1229 ((static_cast<int32_t>(qn * 2) & 0xf)*B16) | |
| 1230 ((static_cast<int32_t>(qd * 2) & 0xf)*B12) | |
| 1231 ((static_cast<int32_t>(qn * 2) >> 4)*B7) | |
| 1232 ((static_cast<int32_t>(qm * 2) >> 4)*B5) | |
| 1233 (static_cast<int32_t>(qm * 2) & 0xf); |
| 1234 Emit(encoding); |
| 1235 } |
| 1236 |
| 1237 |
| 1238 void Assembler::vaddqi(int sz, QRegister qd, QRegister qn, QRegister qm) { |
| 1239 ASSERT((sz >= 0) && (sz <= 3)); |
| 1240 EmitSIMDqqq(B11, sz, qd, qn, qm); |
| 1241 } |
| 1242 |
| 1243 |
| 1244 void Assembler::vaddqs(QRegister qd, QRegister qn, QRegister qm) { |
| 1245 EmitSIMDqqq(B11 | B10 | B8, 0, qd, qn, qm); |
| 1246 } |
| 1247 |
| 1248 |
| 1208 void Assembler::svc(uint32_t imm24, Condition cond) { | 1249 void Assembler::svc(uint32_t imm24, Condition cond) { |
| 1209 ASSERT(cond != kNoCondition); | 1250 ASSERT(cond != kNoCondition); |
| 1210 ASSERT(imm24 < (1 << 24)); | 1251 ASSERT(imm24 < (1 << 24)); |
| 1211 int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24; | 1252 int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24; |
| 1212 Emit(encoding); | 1253 Emit(encoding); |
| 1213 } | 1254 } |
| 1214 | 1255 |
| 1215 | 1256 |
| 1216 void Assembler::bkpt(uint16_t imm16) { | 1257 void Assembler::bkpt(uint16_t imm16) { |
| 1217 // bkpt requires that the cond field is AL. | 1258 // bkpt requires that the cond field is AL. |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1)); | 2051 bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1)); |
| 2011 } | 2052 } |
| 2012 } | 2053 } |
| 2013 | 2054 |
| 2014 | 2055 |
| 2015 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 2056 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
| 2016 // Preserve volatile CPU registers. | 2057 // Preserve volatile CPU registers. |
| 2017 EnterFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR), 0); | 2058 EnterFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR), 0); |
| 2018 | 2059 |
| 2019 // Preserve all volatile FPU registers. | 2060 // Preserve all volatile FPU registers. |
| 2020 vstmd(DB_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); | 2061 DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg); |
| 2062 DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg); |
| 2063 vstmd(DB_W, SP, firstv, lastv); |
| 2021 | 2064 |
| 2022 ReserveAlignedFrameSpace(frame_space); | 2065 ReserveAlignedFrameSpace(frame_space); |
| 2023 } | 2066 } |
| 2024 | 2067 |
| 2025 | 2068 |
| 2026 void Assembler::LeaveCallRuntimeFrame() { | 2069 void Assembler::LeaveCallRuntimeFrame() { |
| 2027 // SP might have been modified to reserve space for arguments | 2070 // SP might have been modified to reserve space for arguments |
| 2028 // and ensure proper alignment of the stack frame. | 2071 // and ensure proper alignment of the stack frame. |
| 2029 // We need to restore it before restoring registers. | 2072 // We need to restore it before restoring registers. |
| 2030 const intptr_t kPushedRegistersSize = | 2073 const intptr_t kPushedRegistersSize = |
| 2031 kDartVolatileCpuRegCount * kWordSize + | 2074 kDartVolatileCpuRegCount * kWordSize + |
| 2032 kDartVolatileFpuRegCount * 2 * kWordSize; | 2075 kDartVolatileFpuRegCount * 2 * kWordSize; |
| 2033 AddImmediate(SP, FP, -kPushedRegistersSize); | 2076 AddImmediate(SP, FP, -kPushedRegistersSize); |
| 2034 | 2077 |
| 2035 // Restore all volatile FPU registers. | 2078 // Restore all volatile FPU registers. |
| 2036 vldmd(IA_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg); | 2079 DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg); |
| 2080 DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg); |
| 2081 vldmd(IA_W, SP, firstv, lastv); |
| 2037 | 2082 |
| 2038 // Restore volatile CPU registers. | 2083 // Restore volatile CPU registers. |
| 2039 LeaveFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR)); | 2084 LeaveFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR)); |
| 2040 } | 2085 } |
| 2041 | 2086 |
| 2042 | 2087 |
| 2043 void Assembler::CallRuntime(const RuntimeEntry& entry) { | 2088 void Assembler::CallRuntime(const RuntimeEntry& entry) { |
| 2044 entry.Call(this); | 2089 entry.Call(this); |
| 2045 } | 2090 } |
| 2046 | 2091 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2240 }; | 2285 }; |
| 2241 | 2286 |
| 2242 | 2287 |
| 2243 const char* Assembler::RegisterName(Register reg) { | 2288 const char* Assembler::RegisterName(Register reg) { |
| 2244 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); | 2289 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); |
| 2245 return cpu_reg_names[reg]; | 2290 return cpu_reg_names[reg]; |
| 2246 } | 2291 } |
| 2247 | 2292 |
| 2248 | 2293 |
| 2249 static const char* fpu_reg_names[kNumberOfFpuRegisters] = { | 2294 static const char* fpu_reg_names[kNumberOfFpuRegisters] = { |
| 2250 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", | 2295 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", |
| 2251 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", | |
| 2252 #ifdef VFPv3_D32 | 2296 #ifdef VFPv3_D32 |
| 2253 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", | 2297 "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", |
| 2254 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", | |
| 2255 #endif | 2298 #endif |
| 2256 }; | 2299 }; |
| 2257 | 2300 |
| 2258 | 2301 |
| 2259 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2302 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 2260 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 2303 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 2261 return fpu_reg_names[reg]; | 2304 return fpu_reg_names[reg]; |
| 2262 } | 2305 } |
| 2263 | 2306 |
| 2264 } // namespace dart | 2307 } // namespace dart |
| 2265 | 2308 |
| 2266 #endif // defined TARGET_ARCH_ARM | 2309 #endif // defined TARGET_ARCH_ARM |
| 2267 | 2310 |
| OLD | NEW |