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

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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698