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

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

Issue 183803024: Adds support for ARMv6. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Added tests. Created 6 years, 9 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" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h"
8 #include "vm/constants_arm.h" 9 #include "vm/constants_arm.h"
9 #include "vm/cpu.h" 10 #include "vm/cpu.h"
10 #include "vm/instructions.h" 11 #include "vm/instructions.h"
11 #include "vm/object.h" 12 #include "vm/object.h"
12 13
13 namespace dart { 14 namespace dart {
14 15
15 CallPattern::CallPattern(uword pc, const Code& code) 16 CallPattern::CallPattern(uword pc, const Code& code)
16 : object_pool_(Array::Handle(code.ObjectPool())), 17 : object_pool_(Array::Handle(code.ObjectPool())),
17 end_(pc), 18 end_(pc),
18 args_desc_load_end_(0), 19 args_desc_load_end_(0),
19 ic_data_load_end_(0), 20 ic_data_load_end_(0),
20 target_address_pool_index_(-1), 21 target_address_pool_index_(-1),
21 args_desc_(Array::Handle()), 22 args_desc_(Array::Handle()),
22 ic_data_(ICData::Handle()) { 23 ic_data_(ICData::Handle()) {
23 ASSERT(code.ContainsInstructionAt(pc)); 24 ASSERT(code.ContainsInstructionAt(pc));
24 // Last instruction: blx lr. 25 // Last instruction: blx lr.
25 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); 26 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e);
26 27
27 Register reg; 28 Register reg;
28 ic_data_load_end_ = 29 ic_data_load_end_ =
29 InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize, 30 InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize,
30 &reg, 31 &reg,
31 &target_address_pool_index_); 32 &target_address_pool_index_);
32 ASSERT(reg == LR); 33 ASSERT(reg == LR);
33 } 34 }
34 35
35 36
37 int CallPattern::LengthInBytes() {
38 if (TargetCPUFeatures::arm_version() == ARMv6) {
39 return 5 * Instr::kInstrSize;
40 } else {
41 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
42 return 3 * Instr::kInstrSize;
43 }
44 }
45
46
36 // Decodes a load sequence ending at 'end' (the last instruction of the load 47 // Decodes a load sequence ending at 'end' (the last instruction of the load
37 // sequence is the instruction before the one at end). Returns a pointer to 48 // sequence is the instruction before the one at end). Returns a pointer to
38 // the first instruction in the sequence. Returns the register being loaded 49 // the first instruction in the sequence. Returns the register being loaded
39 // and the loaded object in the output parameters 'reg' and 'obj' 50 // and the loaded object in the output parameters 'reg' and 'obj'
40 // respectively. 51 // respectively.
41 uword InstructionPattern::DecodeLoadObject(uword end, 52 uword InstructionPattern::DecodeLoadObject(uword end,
42 const Array& object_pool, 53 const Array& object_pool,
43 Register* reg, 54 Register* reg,
44 Object* obj) { 55 Object* obj) {
45 uword start = 0; 56 uword start = 0;
(...skipping 16 matching lines...) Expand all
62 // sequence is the instruction before the one at end). Returns a pointer to 73 // sequence is the instruction before the one at end). Returns a pointer to
63 // the first instruction in the sequence. Returns the register being loaded 74 // the first instruction in the sequence. Returns the register being loaded
64 // and the loaded immediate value in the output parameters 'reg' and 'value' 75 // and the loaded immediate value in the output parameters 'reg' and 'value'
65 // respectively. 76 // respectively.
66 uword InstructionPattern::DecodeLoadWordImmediate(uword end, 77 uword InstructionPattern::DecodeLoadWordImmediate(uword end,
67 Register* reg, 78 Register* reg,
68 intptr_t* value) { 79 intptr_t* value) {
69 uword start = end - Instr::kInstrSize; 80 uword start = end - Instr::kInstrSize;
70 int32_t instr = Instr::At(start)->InstructionBits(); 81 int32_t instr = Instr::At(start)->InstructionBits();
71 intptr_t imm = 0; 82 intptr_t imm = 0;
72 if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, #imm_hi 83 if (TargetCPUFeatures::arm_version() == ARMv6) {
73 imm |= (instr & 0xf0000) << 12; 84 ASSERT((instr & 0xfff00000) == 0xe3800000); // orr rd, rd, byte0
74 imm |= (instr & 0xfff) << 16; 85 imm |= (instr & 0x000000ff);
86
75 start -= Instr::kInstrSize; 87 start -= Instr::kInstrSize;
76 instr = Instr::At(start)->InstructionBits(); 88 instr = Instr::At(start)->InstructionBits();
89 ASSERT((instr & 0xfff00000) == 0xe3800c00); // orr rd, rd, (byte1 rot 12)
90 imm |= (instr & 0x000000ff);
91
92 start -= Instr::kInstrSize;
93 instr = Instr::At(start)->InstructionBits();
94 ASSERT((instr & 0xfff00f00) == 0xe3800800); // orr rd, rd, (byte2 rot 8)
95 imm |= (instr & 0x000000ff);
96
97 start -= Instr::kInstrSize;
98 instr = Instr::At(start)->InstructionBits();
99 ASSERT((instr & 0xffff0f00) == 0xe3a00400); // mov rd, (byte3 rot 4)
100 imm |= (instr & 0x000000ff);
101
102 *reg = static_cast<Register>((instr & 0x0000f000) >> 12);
103 *value = imm;
104 } else {
105 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
106 if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, #imm_hi
107 imm |= (instr & 0xf0000) << 12;
108 imm |= (instr & 0xfff) << 16;
109 start -= Instr::kInstrSize;
110 instr = Instr::At(start)->InstructionBits();
111 }
112 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo
113 imm |= (instr & 0xf0000) >> 4;
114 imm |= instr & 0xfff;
115 *reg = static_cast<Register>((instr & 0xf000) >> 12);
116 *value = imm;
77 } 117 }
78 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo
79 imm |= (instr & 0xf0000) >> 4;
80 imm |= instr & 0xfff;
81 *reg = static_cast<Register>((instr & 0xf000) >> 12);
82 *value = imm;
83 return start; 118 return start;
84 } 119 }
85 120
86 121
87 // Decodes a load sequence ending at 'end' (the last instruction of the load 122 // Decodes a load sequence ending at 'end' (the last instruction of the load
88 // sequence is the instruction before the one at end). Returns a pointer to 123 // sequence is the instruction before the one at end). Returns a pointer to
89 // the first instruction in the sequence. Returns the register being loaded 124 // the first instruction in the sequence. Returns the register being loaded
90 // and the index in the pool being read from in the output parameters 'reg' 125 // and the index in the pool being read from in the output parameters 'reg'
91 // and 'index' respectively. 126 // and 'index' respectively.
92 uword InstructionPattern::DecodeLoadWordFromPool(uword end, 127 uword InstructionPattern::DecodeLoadWordFromPool(uword end,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 void CallPattern::SetTargetAddress(uword target_address) const { 196 void CallPattern::SetTargetAddress(uword target_address) const {
162 ASSERT(Utils::IsAligned(target_address, 4)); 197 ASSERT(Utils::IsAligned(target_address, 4));
163 // The address is stored in the object array as a RawSmi. 198 // The address is stored in the object array as a RawSmi.
164 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address)); 199 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
165 object_pool_.SetAt(target_address_pool_index_, smi); 200 object_pool_.SetAt(target_address_pool_index_, smi);
166 // No need to flush the instruction cache, since the code is not modified. 201 // No need to flush the instruction cache, since the code is not modified.
167 } 202 }
168 203
169 204
170 void CallPattern::InsertAt(uword pc, uword target_address) { 205 void CallPattern::InsertAt(uword pc, uword target_address) {
171 uint16_t target_lo = target_address & 0xffff; 206 if (TargetCPUFeatures::arm_version() == ARMv6) {
172 uint16_t target_hi = target_address >> 16; 207 const uint32_t byte0 = (target_address & 0x000000ff);
173 uword movw_ip = 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff); 208 const uint32_t byte1 = (target_address & 0x0000ff00) >> 8;
174 uword movt_ip = 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff); 209 const uint32_t byte2 = (target_address & 0x00ff0000) >> 16;
175 uword blx_ip = 0xe12fff3c; 210 const uint32_t byte3 = (target_address & 0xff000000) >> 24;
176 *reinterpret_cast<uword*>(pc + (0 * Instr::kInstrSize)) = movw_ip; 211
177 *reinterpret_cast<uword*>(pc + (1 * Instr::kInstrSize)) = movt_ip; 212 const uword mov_ip = 0xe3a0c400 | byte3; // mov ip, (byte3 rot 4)
178 *reinterpret_cast<uword*>(pc + (2 * Instr::kInstrSize)) = blx_ip; 213 const uword or1_ip = 0xe38cc800 | byte2; // orr ip, ip, (byte2 rot 8)
179 ASSERT(kFixedLengthInBytes == 3 * Instr::kInstrSize); 214 const uword or2_ip = 0xe38ccc00 | byte1; // orr ip, ip, (byte1 rot 12)
180 CPU::FlushICache(pc, kFixedLengthInBytes); 215 const uword or3_ip = 0xe38cc000 | byte0; // orr ip, ip, byte0
216 const uword blx_ip = 0xe12fff3c;
217
218 *reinterpret_cast<uword*>(pc + (0 * Instr::kInstrSize)) = mov_ip;
219 *reinterpret_cast<uword*>(pc + (1 * Instr::kInstrSize)) = or1_ip;
220 *reinterpret_cast<uword*>(pc + (2 * Instr::kInstrSize)) = or2_ip;
221 *reinterpret_cast<uword*>(pc + (3 * Instr::kInstrSize)) = or3_ip;
222 *reinterpret_cast<uword*>(pc + (4 * Instr::kInstrSize)) = blx_ip;
223
224 ASSERT(LengthInBytes() == 5 * Instr::kInstrSize);
225 CPU::FlushICache(pc, LengthInBytes());
226 } else {
227 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
228 const uint16_t target_lo = target_address & 0xffff;
229 const uint16_t target_hi = target_address >> 16;
230
231 const uword movw_ip =
232 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff);
233 const uword movt_ip =
234 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff);
235 const uword blx_ip = 0xe12fff3c;
236
237 *reinterpret_cast<uword*>(pc + (0 * Instr::kInstrSize)) = movw_ip;
238 *reinterpret_cast<uword*>(pc + (1 * Instr::kInstrSize)) = movt_ip;
239 *reinterpret_cast<uword*>(pc + (2 * Instr::kInstrSize)) = blx_ip;
240
241 ASSERT(LengthInBytes() == 3 * Instr::kInstrSize);
242 CPU::FlushICache(pc, LengthInBytes());
243 }
181 } 244 }
182 245
183 246
184 JumpPattern::JumpPattern(uword pc, const Code& code) : pc_(pc) { } 247 JumpPattern::JumpPattern(uword pc, const Code& code) : pc_(pc) { }
185 248
186 249
250 int JumpPattern::pattern_length_in_bytes() {
251 if (TargetCPUFeatures::arm_version() == ARMv6) {
252 return 5 * Instr::kInstrSize;
253 } else {
254 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
255 return 3 * Instr::kInstrSize;
256 }
257 }
258
259
187 bool JumpPattern::IsValid() const { 260 bool JumpPattern::IsValid() const {
188 Instr* movw_ip = Instr::At(pc_ + (0 * Instr::kInstrSize)); // target_lo 261 if (TargetCPUFeatures::arm_version() == ARMv6) {
189 Instr* movt_ip = Instr::At(pc_ + (1 * Instr::kInstrSize)); // target_hi 262 Instr* mov_ip = Instr::At(pc_ + (0 * Instr::kInstrSize));
190 Instr* bx_ip = Instr::At(pc_ + (2 * Instr::kInstrSize)); 263 Instr* or1_ip = Instr::At(pc_ + (1 * Instr::kInstrSize));
191 return (movw_ip->InstructionBits() & 0xfff0f000) == 0xe300c000 && 264 Instr* or2_ip = Instr::At(pc_ + (2 * Instr::kInstrSize));
192 (movt_ip->InstructionBits() & 0xfff0f000) == 0xe340c000 && 265 Instr* or3_ip = Instr::At(pc_ + (3 * Instr::kInstrSize));
193 (bx_ip->InstructionBits() & 0xffffffff) == 0xe12fff1c; 266 Instr* bx_ip = Instr::At(pc_ + (4 * Instr::kInstrSize));
267 return ((mov_ip->InstructionBits() & 0xffffff00) == 0xe3a0c400) &&
268 ((or1_ip->InstructionBits() & 0xffffff00) == 0xe38cc800) &&
269 ((or2_ip->InstructionBits() & 0xffffff00) == 0xe38ccc00) &&
270 ((or3_ip->InstructionBits() & 0xffffff00) == 0xe38cc000) &&
271 ((bx_ip->InstructionBits() & 0xffffffff) == 0xe12fff1c);
272 } else {
273 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
274 Instr* movw_ip = Instr::At(pc_ + (0 * Instr::kInstrSize)); // target_lo
275 Instr* movt_ip = Instr::At(pc_ + (1 * Instr::kInstrSize)); // target_hi
276 Instr* bx_ip = Instr::At(pc_ + (2 * Instr::kInstrSize));
277 return (movw_ip->InstructionBits() & 0xfff0f000) == 0xe300c000 &&
278 (movt_ip->InstructionBits() & 0xfff0f000) == 0xe340c000 &&
279 (bx_ip->InstructionBits() & 0xffffffff) == 0xe12fff1c;
280 }
194 } 281 }
195 282
196 283
197 uword JumpPattern::TargetAddress() const { 284 uword JumpPattern::TargetAddress() const {
198 Instr* movw_ip = Instr::At(pc_ + (0 * Instr::kInstrSize)); // target_lo 285 if (TargetCPUFeatures::arm_version() == ARMv6) {
199 Instr* movt_ip = Instr::At(pc_ + (1 * Instr::kInstrSize)); // target_hi 286 Instr* mov_ip = Instr::At(pc_ + (0 * Instr::kInstrSize));
200 uint16_t target_lo = movw_ip->MovwField(); 287 Instr* or1_ip = Instr::At(pc_ + (1 * Instr::kInstrSize));
201 uint16_t target_hi = movt_ip->MovwField(); 288 Instr* or2_ip = Instr::At(pc_ + (2 * Instr::kInstrSize));
202 return (target_hi << 16) | target_lo; 289 Instr* or3_ip = Instr::At(pc_ + (3 * Instr::kInstrSize));
290 uword imm = 0;
291 imm |= or3_ip->Immed8Field();
292 imm |= or2_ip->Immed8Field() << 8;
293 imm |= or1_ip->Immed8Field() << 16;
294 imm |= mov_ip->Immed8Field() << 24;
295 return imm;
296 } else {
297 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
298 Instr* movw_ip = Instr::At(pc_ + (0 * Instr::kInstrSize)); // target_lo
299 Instr* movt_ip = Instr::At(pc_ + (1 * Instr::kInstrSize)); // target_hi
300 uint16_t target_lo = movw_ip->MovwField();
301 uint16_t target_hi = movt_ip->MovwField();
302 return (target_hi << 16) | target_lo;
303 }
203 } 304 }
204 305
205 306
206 void JumpPattern::SetTargetAddress(uword target_address) const { 307 void JumpPattern::SetTargetAddress(uword target_address) const {
207 uint16_t target_lo = target_address & 0xffff; 308 if (TargetCPUFeatures::arm_version() == ARMv6) {
208 uint16_t target_hi = target_address >> 16; 309 const uint32_t byte0 = (target_address & 0x000000ff);
209 uword movw_ip = 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff); 310 const uint32_t byte1 = (target_address & 0x0000ff00) >> 8;
210 uword movt_ip = 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff); 311 const uint32_t byte2 = (target_address & 0x00ff0000) >> 16;
211 *reinterpret_cast<uword*>(pc_ + (0 * Instr::kInstrSize)) = movw_ip; 312 const uint32_t byte3 = (target_address & 0xff000000) >> 24;
212 *reinterpret_cast<uword*>(pc_ + (1 * Instr::kInstrSize)) = movt_ip; 313
213 CPU::FlushICache(pc_, 2 * Instr::kInstrSize); 314 const uword mov_ip = 0xe3a0c400 | byte3; // mov ip, (byte3 rot 4)
315 const uword or1_ip = 0xe38cc800 | byte2; // orr ip, ip, (byte2 rot 8)
316 const uword or2_ip = 0xe38ccc00 | byte1; // orr ip, ip, (byte1 rot 12)
317 const uword or3_ip = 0xe38cc000 | byte0; // orr ip, ip, byte0
318
319 *reinterpret_cast<uword*>(pc_ + (0 * Instr::kInstrSize)) = mov_ip;
320 *reinterpret_cast<uword*>(pc_ + (1 * Instr::kInstrSize)) = or1_ip;
321 *reinterpret_cast<uword*>(pc_ + (2 * Instr::kInstrSize)) = or2_ip;
322 *reinterpret_cast<uword*>(pc_ + (3 * Instr::kInstrSize)) = or3_ip;
323 CPU::FlushICache(pc_, 4 * Instr::kInstrSize);
324 } else {
325 ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
326 const uint16_t target_lo = target_address & 0xffff;
327 const uint16_t target_hi = target_address >> 16;
328
329 const uword movw_ip =
330 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff);
331 const uword movt_ip =
332 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff);
333
334 *reinterpret_cast<uword*>(pc_ + (0 * Instr::kInstrSize)) = movw_ip;
335 *reinterpret_cast<uword*>(pc_ + (1 * Instr::kInstrSize)) = movt_ip;
336 CPU::FlushICache(pc_, 2 * Instr::kInstrSize);
337 }
214 } 338 }
215 339
216 } // namespace dart 340 } // namespace dart
217 341
218 #endif // defined TARGET_ARCH_ARM 342 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698