Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(516)

Side by Side Diff: runtime/vm/assembler_arm.cc

Issue 18684008: Begins implementation of ARM neon instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698