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