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 |