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 #ifndef RUNTIME_VM_ASSEMBLER_ARM_H_ | 5 #ifndef RUNTIME_VM_ASSEMBLER_ARM_H_ |
6 #define RUNTIME_VM_ASSEMBLER_ARM_H_ | 6 #define RUNTIME_VM_ASSEMBLER_ARM_H_ |
7 | 7 |
8 #ifndef RUNTIME_VM_ASSEMBLER_H_ | 8 #ifndef RUNTIME_VM_ASSEMBLER_H_ |
9 #error Do not include assembler_arm.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
11 | 11 |
12 #include "platform/assert.h" | 12 #include "platform/assert.h" |
13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
14 #include "vm/constants_arm.h" | 14 #include "vm/constants_arm.h" |
15 #include "vm/cpu.h" | 15 #include "vm/cpu.h" |
16 #include "vm/hash_map.h" | 16 #include "vm/hash_map.h" |
17 #include "vm/object.h" | 17 #include "vm/object.h" |
18 #include "vm/simulator.h" | 18 #include "vm/simulator.h" |
19 | 19 |
20 namespace dart { | 20 namespace dart { |
21 | 21 |
22 // Forward declarations. | 22 // Forward declarations. |
23 class RuntimeEntry; | 23 class RuntimeEntry; |
24 class StubEntry; | 24 class StubEntry; |
25 | 25 |
26 | 26 |
27 // Instruction encoding bits. | 27 // Instruction encoding bits. |
28 enum { | 28 enum { |
29 H = 1 << 5, // halfword (or byte) | 29 H = 1 << 5, // halfword (or byte) |
30 L = 1 << 20, // load (or store) | 30 L = 1 << 20, // load (or store) |
31 S = 1 << 20, // set condition code (or leave unchanged) | 31 S = 1 << 20, // set condition code (or leave unchanged) |
32 W = 1 << 21, // writeback base register (or leave unchanged) | 32 W = 1 << 21, // writeback base register (or leave unchanged) |
33 A = 1 << 21, // accumulate in multiply instruction (or not) | 33 A = 1 << 21, // accumulate in multiply instruction (or not) |
34 B = 1 << 22, // unsigned byte (or word) | 34 B = 1 << 22, // unsigned byte (or word) |
35 D = 1 << 22, // high/lo bit of start of s/d register range | 35 D = 1 << 22, // high/lo bit of start of s/d register range |
36 N = 1 << 22, // long (or short) | 36 N = 1 << 22, // long (or short) |
37 U = 1 << 23, // positive (or negative) offset/index | 37 U = 1 << 23, // positive (or negative) offset/index |
38 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) | 38 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) |
39 I = 1 << 25, // immediate shifter operand (or not) | 39 I = 1 << 25, // immediate shifter operand (or not) |
40 | 40 |
41 B0 = 1, | 41 B0 = 1, |
42 B1 = 1 << 1, | 42 B1 = 1 << 1, |
43 B2 = 1 << 2, | 43 B2 = 1 << 2, |
44 B3 = 1 << 3, | 44 B3 = 1 << 3, |
45 B4 = 1 << 4, | 45 B4 = 1 << 4, |
46 B5 = 1 << 5, | 46 B5 = 1 << 5, |
47 B6 = 1 << 6, | 47 B6 = 1 << 6, |
48 B7 = 1 << 7, | 48 B7 = 1 << 7, |
49 B8 = 1 << 8, | 49 B8 = 1 << 8, |
(...skipping 11 matching lines...) Expand all Loading... |
61 B23 = 1 << 23, | 61 B23 = 1 << 23, |
62 B24 = 1 << 24, | 62 B24 = 1 << 24, |
63 B25 = 1 << 25, | 63 B25 = 1 << 25, |
64 B26 = 1 << 26, | 64 B26 = 1 << 26, |
65 B27 = 1 << 27, | 65 B27 = 1 << 27, |
66 }; | 66 }; |
67 | 67 |
68 | 68 |
69 class Label : public ValueObject { | 69 class Label : public ValueObject { |
70 public: | 70 public: |
71 Label() : position_(0) { } | 71 Label() : position_(0) {} |
72 | 72 |
73 ~Label() { | 73 ~Label() { |
74 // Assert if label is being destroyed with unresolved branches pending. | 74 // Assert if label is being destroyed with unresolved branches pending. |
75 ASSERT(!IsLinked()); | 75 ASSERT(!IsLinked()); |
76 } | 76 } |
77 | 77 |
78 // Returns the position for bound and linked labels. Cannot be used | 78 // Returns the position for bound and linked labels. Cannot be used |
79 // for unused labels. | 79 // for unused labels. |
80 intptr_t Position() const { | 80 intptr_t Position() const { |
81 ASSERT(!IsUnused()); | 81 ASSERT(!IsUnused()); |
82 return IsBound() ? -position_ - kWordSize : position_ - kWordSize; | 82 return IsBound() ? -position_ - kWordSize : position_ - kWordSize; |
83 } | 83 } |
84 | 84 |
85 bool IsBound() const { return position_ < 0; } | 85 bool IsBound() const { return position_ < 0; } |
86 bool IsUnused() const { return position_ == 0; } | 86 bool IsUnused() const { return position_ == 0; } |
87 bool IsLinked() const { return position_ > 0; } | 87 bool IsLinked() const { return position_ > 0; } |
88 | 88 |
89 private: | 89 private: |
90 intptr_t position_; | 90 intptr_t position_; |
91 | 91 |
92 void Reinitialize() { | 92 void Reinitialize() { position_ = 0; } |
93 position_ = 0; | |
94 } | |
95 | 93 |
96 void BindTo(intptr_t position) { | 94 void BindTo(intptr_t position) { |
97 ASSERT(!IsBound()); | 95 ASSERT(!IsBound()); |
98 position_ = -position - kWordSize; | 96 position_ = -position - kWordSize; |
99 ASSERT(IsBound()); | 97 ASSERT(IsBound()); |
100 } | 98 } |
101 | 99 |
102 void LinkTo(intptr_t position) { | 100 void LinkTo(intptr_t position) { |
103 ASSERT(!IsBound()); | 101 ASSERT(!IsBound()); |
104 position_ = position + kWordSize; | 102 position_ = position + kWordSize; |
105 ASSERT(IsLinked()); | 103 ASSERT(IsLinked()); |
106 } | 104 } |
107 | 105 |
108 friend class Assembler; | 106 friend class Assembler; |
109 DISALLOW_COPY_AND_ASSIGN(Label); | 107 DISALLOW_COPY_AND_ASSIGN(Label); |
110 }; | 108 }; |
111 | 109 |
112 | 110 |
113 // Encodes Addressing Mode 1 - Data-processing operands. | 111 // Encodes Addressing Mode 1 - Data-processing operands. |
114 class Operand : public ValueObject { | 112 class Operand : public ValueObject { |
115 public: | 113 public: |
116 // Data-processing operands - Uninitialized. | 114 // Data-processing operands - Uninitialized. |
117 Operand() : type_(-1), encoding_(-1) { } | 115 Operand() : type_(-1), encoding_(-1) {} |
118 | 116 |
119 // Data-processing operands - Copy constructor. | 117 // Data-processing operands - Copy constructor. |
120 Operand(const Operand& other) | 118 Operand(const Operand& other) |
121 : ValueObject(), type_(other.type_), encoding_(other.encoding_) { } | 119 : ValueObject(), type_(other.type_), encoding_(other.encoding_) {} |
122 | 120 |
123 // Data-processing operands - Assignment operator. | 121 // Data-processing operands - Assignment operator. |
124 Operand& operator=(const Operand& other) { | 122 Operand& operator=(const Operand& other) { |
125 type_ = other.type_; | 123 type_ = other.type_; |
126 encoding_ = other.encoding_; | 124 encoding_ = other.encoding_; |
127 return *this; | 125 return *this; |
128 } | 126 } |
129 | 127 |
130 // Data-processing operands - Immediate. | 128 // Data-processing operands - Immediate. |
131 explicit Operand(uint32_t immediate) { | 129 explicit Operand(uint32_t immediate) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 | 164 |
167 static bool CanHold(uint32_t immediate, Operand* o) { | 165 static bool CanHold(uint32_t immediate, Operand* o) { |
168 // Avoid the more expensive test for frequent small immediate values. | 166 // Avoid the more expensive test for frequent small immediate values. |
169 if (immediate < (1 << kImmed8Bits)) { | 167 if (immediate < (1 << kImmed8Bits)) { |
170 o->type_ = 1; | 168 o->type_ = 1; |
171 o->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); | 169 o->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); |
172 return true; | 170 return true; |
173 } | 171 } |
174 // Note that immediate must be unsigned for the test to work correctly. | 172 // Note that immediate must be unsigned for the test to work correctly. |
175 for (int rot = 0; rot < 16; rot++) { | 173 for (int rot = 0; rot < 16; rot++) { |
176 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); | 174 uint32_t imm8 = (immediate << 2 * rot) | (immediate >> (32 - 2 * rot)); |
177 if (imm8 < (1 << kImmed8Bits)) { | 175 if (imm8 < (1 << kImmed8Bits)) { |
178 o->type_ = 1; | 176 o->type_ = 1; |
179 o->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); | 177 o->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); |
180 return true; | 178 return true; |
181 } | 179 } |
182 } | 180 } |
183 return false; | 181 return false; |
184 } | 182 } |
185 | 183 |
186 private: | 184 private: |
(...skipping 27 matching lines...) Expand all Loading... |
214 kWordPair, | 212 kWordPair, |
215 kSWord, | 213 kSWord, |
216 kDWord, | 214 kDWord, |
217 kRegList, | 215 kRegList, |
218 }; | 216 }; |
219 | 217 |
220 | 218 |
221 // Load/store multiple addressing mode. | 219 // Load/store multiple addressing mode. |
222 enum BlockAddressMode { | 220 enum BlockAddressMode { |
223 // bit encoding P U W | 221 // bit encoding P U W |
224 DA = (0|0|0) << 21, // decrement after | 222 DA = (0 | 0 | 0) << 21, // decrement after |
225 IA = (0|4|0) << 21, // increment after | 223 IA = (0 | 4 | 0) << 21, // increment after |
226 DB = (8|0|0) << 21, // decrement before | 224 DB = (8 | 0 | 0) << 21, // decrement before |
227 IB = (8|4|0) << 21, // increment before | 225 IB = (8 | 4 | 0) << 21, // increment before |
228 DA_W = (0|0|1) << 21, // decrement after with writeback to base | 226 DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base |
229 IA_W = (0|4|1) << 21, // increment after with writeback to base | 227 IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base |
230 DB_W = (8|0|1) << 21, // decrement before with writeback to base | 228 DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base |
231 IB_W = (8|4|1) << 21 // increment before with writeback to base | 229 IB_W = (8 | 4 | 1) << 21 // increment before with writeback to base |
232 }; | 230 }; |
233 | 231 |
234 | 232 |
235 class Address : public ValueObject { | 233 class Address : public ValueObject { |
236 public: | 234 public: |
237 enum OffsetKind { | 235 enum OffsetKind { |
238 Immediate, | 236 Immediate, |
239 IndexRegister, | 237 IndexRegister, |
240 ScaledIndexRegister, | 238 ScaledIndexRegister, |
241 }; | 239 }; |
242 | 240 |
243 // Memory operand addressing mode | 241 // Memory operand addressing mode |
244 enum Mode { | 242 enum Mode { |
245 kModeMask = (8|4|1) << 21, | 243 kModeMask = (8 | 4 | 1) << 21, |
246 // bit encoding P U W | 244 // bit encoding P U W |
247 Offset = (8|4|0) << 21, // offset (w/o writeback to base) | 245 Offset = (8 | 4 | 0) << 21, // offset (w/o writeback to base) |
248 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback | 246 PreIndex = (8 | 4 | 1) << 21, // pre-indexed addressing with writeback |
249 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback | 247 PostIndex = (0 | 4 | 0) << 21, // post-indexed addressing with writeback |
250 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base) | 248 NegOffset = (8 | 0 | 0) << 21, // negative offset (w/o writeback to base) |
251 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback | 249 NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback |
252 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback | 250 NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback |
253 }; | 251 }; |
254 | 252 |
255 Address(const Address& other) | 253 Address(const Address& other) |
256 : ValueObject(), encoding_(other.encoding_), kind_(other.kind_) { | 254 : ValueObject(), encoding_(other.encoding_), kind_(other.kind_) {} |
257 } | |
258 | 255 |
259 Address& operator=(const Address& other) { | 256 Address& operator=(const Address& other) { |
260 encoding_ = other.encoding_; | 257 encoding_ = other.encoding_; |
261 kind_ = other.kind_; | 258 kind_ = other.kind_; |
262 return *this; | 259 return *this; |
263 } | 260 } |
264 | 261 |
265 bool Equals(const Address& other) const { | 262 bool Equals(const Address& other) const { |
266 return (encoding_ == other.encoding_) && (kind_ == other.kind_); | 263 return (encoding_ == other.encoding_) && (kind_ == other.kind_); |
267 } | 264 } |
268 | 265 |
269 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { | 266 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { |
270 ASSERT(Utils::IsAbsoluteUint(12, offset)); | 267 ASSERT(Utils::IsAbsoluteUint(12, offset)); |
271 kind_ = Immediate; | 268 kind_ = Immediate; |
272 if (offset < 0) { | 269 if (offset < 0) { |
273 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. | 270 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. |
274 } else { | 271 } else { |
275 encoding_ = am | offset; | 272 encoding_ = am | offset; |
276 } | 273 } |
277 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; | 274 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; |
278 } | 275 } |
279 | 276 |
280 // There is no register offset mode unless Mode is Offset, in which case the | 277 // There is no register offset mode unless Mode is Offset, in which case the |
281 // shifted register case below should be used. | 278 // shifted register case below should be used. |
282 Address(Register rn, Register r, Mode am); | 279 Address(Register rn, Register r, Mode am); |
283 | 280 |
284 Address(Register rn, Register rm, | 281 Address(Register rn, |
285 Shift shift = LSL, uint32_t shift_imm = 0, Mode am = Offset) { | 282 Register rm, |
| 283 Shift shift = LSL, |
| 284 uint32_t shift_imm = 0, |
| 285 Mode am = Offset) { |
286 Operand o(rm, shift, shift_imm); | 286 Operand o(rm, shift, shift_imm); |
287 | 287 |
288 if ((shift == LSL) && (shift_imm == 0)) { | 288 if ((shift == LSL) && (shift_imm == 0)) { |
289 kind_ = IndexRegister; | 289 kind_ = IndexRegister; |
290 } else { | 290 } else { |
291 kind_ = ScaledIndexRegister; | 291 kind_ = ScaledIndexRegister; |
292 } | 292 } |
293 encoding_ = o.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); | 293 encoding_ = o.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift); |
294 } | 294 } |
295 | 295 |
(...skipping 11 matching lines...) Expand all Loading... |
307 static bool CanHoldImmediateOffset(bool is_load, | 307 static bool CanHoldImmediateOffset(bool is_load, |
308 intptr_t cid, | 308 intptr_t cid, |
309 int64_t offset); | 309 int64_t offset); |
310 | 310 |
311 private: | 311 private: |
312 Register rn() const { | 312 Register rn() const { |
313 return Instr::At(reinterpret_cast<uword>(&encoding_))->RnField(); | 313 return Instr::At(reinterpret_cast<uword>(&encoding_))->RnField(); |
314 } | 314 } |
315 | 315 |
316 Register rm() const { | 316 Register rm() const { |
317 return ((kind() == IndexRegister) || (kind() == ScaledIndexRegister)) ? | 317 return ((kind() == IndexRegister) || (kind() == ScaledIndexRegister)) |
318 Instr::At(reinterpret_cast<uword>(&encoding_))->RmField() : | 318 ? Instr::At(reinterpret_cast<uword>(&encoding_))->RmField() |
319 kNoRegister; | 319 : kNoRegister; |
320 } | 320 } |
321 | 321 |
322 Mode mode() const { return static_cast<Mode>(encoding() & kModeMask); } | 322 Mode mode() const { return static_cast<Mode>(encoding() & kModeMask); } |
323 | 323 |
324 bool has_writeback() const { | 324 bool has_writeback() const { |
325 return (mode() == PreIndex) || (mode() == PostIndex) || | 325 return (mode() == PreIndex) || (mode() == PostIndex) || |
326 (mode() == NegPreIndex) || (mode() == NegPostIndex); | 326 (mode() == NegPreIndex) || (mode() == NegPostIndex); |
327 } | 327 } |
328 | 328 |
329 uint32_t encoding() const { return encoding_; } | 329 uint32_t encoding() const { return encoding_; } |
(...skipping 10 matching lines...) Expand all Loading... |
340 | 340 |
341 OffsetKind kind_; | 341 OffsetKind kind_; |
342 | 342 |
343 friend class Assembler; | 343 friend class Assembler; |
344 }; | 344 }; |
345 | 345 |
346 | 346 |
347 class FieldAddress : public Address { | 347 class FieldAddress : public Address { |
348 public: | 348 public: |
349 FieldAddress(Register base, int32_t disp) | 349 FieldAddress(Register base, int32_t disp) |
350 : Address(base, disp - kHeapObjectTag) { } | 350 : Address(base, disp - kHeapObjectTag) {} |
351 | 351 |
352 // This addressing mode does not exist. | 352 // This addressing mode does not exist. |
353 FieldAddress(Register base, Register r); | 353 FieldAddress(Register base, Register r); |
354 | 354 |
355 FieldAddress(const FieldAddress& other) : Address(other) { } | 355 FieldAddress(const FieldAddress& other) : Address(other) {} |
356 | 356 |
357 FieldAddress& operator=(const FieldAddress& other) { | 357 FieldAddress& operator=(const FieldAddress& other) { |
358 Address::operator=(other); | 358 Address::operator=(other); |
359 return *this; | 359 return *this; |
360 } | 360 } |
361 }; | 361 }; |
362 | 362 |
363 | 363 |
364 class Assembler : public ValueObject { | 364 class Assembler : public ValueObject { |
365 public: | 365 public: |
366 explicit Assembler(bool use_far_branches = false) | 366 explicit Assembler(bool use_far_branches = false) |
367 : buffer_(), | 367 : buffer_(), |
368 prologue_offset_(-1), | 368 prologue_offset_(-1), |
369 has_single_entry_point_(true), | 369 has_single_entry_point_(true), |
370 use_far_branches_(use_far_branches), | 370 use_far_branches_(use_far_branches), |
371 comments_(), | 371 comments_(), |
372 constant_pool_allowed_(false) { | 372 constant_pool_allowed_(false) {} |
373 } | |
374 | 373 |
375 ~Assembler() { } | 374 ~Assembler() {} |
376 | 375 |
377 void PopRegister(Register r) { Pop(r); } | 376 void PopRegister(Register r) { Pop(r); } |
378 | 377 |
379 void Bind(Label* label); | 378 void Bind(Label* label); |
380 void Jump(Label* label) { b(label); } | 379 void Jump(Label* label) { b(label); } |
381 | 380 |
382 // Misc. functionality | 381 // Misc. functionality |
383 intptr_t CodeSize() const { return buffer_.Size(); } | 382 intptr_t CodeSize() const { return buffer_.Size(); } |
384 intptr_t prologue_offset() const { return prologue_offset_; } | 383 intptr_t prologue_offset() const { return prologue_offset_; } |
385 bool has_single_entry_point() const { return has_single_entry_point_; } | 384 bool has_single_entry_point() const { return has_single_entry_point_; } |
(...skipping 13 matching lines...) Expand all Loading... |
399 return object_pool_wrapper_.MakeObjectPool(); | 398 return object_pool_wrapper_.MakeObjectPool(); |
400 } | 399 } |
401 | 400 |
402 bool use_far_branches() const { | 401 bool use_far_branches() const { |
403 return FLAG_use_far_branches || use_far_branches_; | 402 return FLAG_use_far_branches || use_far_branches_; |
404 } | 403 } |
405 | 404 |
406 #if defined(TESTING) || defined(DEBUG) | 405 #if defined(TESTING) || defined(DEBUG) |
407 // Used in unit tests and to ensure predictable verification code size in | 406 // Used in unit tests and to ensure predictable verification code size in |
408 // FlowGraphCompiler::EmitEdgeCounter. | 407 // FlowGraphCompiler::EmitEdgeCounter. |
409 void set_use_far_branches(bool b) { | 408 void set_use_far_branches(bool b) { use_far_branches_ = b; } |
410 use_far_branches_ = b; | |
411 } | |
412 #endif // TESTING || DEBUG | 409 #endif // TESTING || DEBUG |
413 | 410 |
414 void FinalizeInstructions(const MemoryRegion& region) { | 411 void FinalizeInstructions(const MemoryRegion& region) { |
415 buffer_.FinalizeInstructions(region); | 412 buffer_.FinalizeInstructions(region); |
416 } | 413 } |
417 | 414 |
418 // Debugging and bringup support. | 415 // Debugging and bringup support. |
419 void Stop(const char* message); | 416 void Stop(const char* message); |
420 void Unimplemented(const char* message); | 417 void Unimplemented(const char* message); |
421 void Untested(const char* message); | 418 void Untested(const char* message); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 | 473 |
477 void mvn(Register rd, Operand o, Condition cond = AL); | 474 void mvn(Register rd, Operand o, Condition cond = AL); |
478 void mvns(Register rd, Operand o, Condition cond = AL); | 475 void mvns(Register rd, Operand o, Condition cond = AL); |
479 | 476 |
480 // Miscellaneous data-processing instructions. | 477 // Miscellaneous data-processing instructions. |
481 void clz(Register rd, Register rm, Condition cond = AL); | 478 void clz(Register rd, Register rm, Condition cond = AL); |
482 | 479 |
483 // Multiply instructions. | 480 // Multiply instructions. |
484 void mul(Register rd, Register rn, Register rm, Condition cond = AL); | 481 void mul(Register rd, Register rn, Register rm, Condition cond = AL); |
485 void muls(Register rd, Register rn, Register rm, Condition cond = AL); | 482 void muls(Register rd, Register rn, Register rm, Condition cond = AL); |
486 void mla(Register rd, Register rn, Register rm, Register ra, | 483 void mla(Register rd, |
| 484 Register rn, |
| 485 Register rm, |
| 486 Register ra, |
487 Condition cond = AL); | 487 Condition cond = AL); |
488 void mls(Register rd, Register rn, Register rm, Register ra, | 488 void mls(Register rd, |
| 489 Register rn, |
| 490 Register rm, |
| 491 Register ra, |
489 Condition cond = AL); | 492 Condition cond = AL); |
490 void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, | 493 void smull(Register rd_lo, |
| 494 Register rd_hi, |
| 495 Register rn, |
| 496 Register rm, |
491 Condition cond = AL); | 497 Condition cond = AL); |
492 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, | 498 void umull(Register rd_lo, |
| 499 Register rd_hi, |
| 500 Register rn, |
| 501 Register rm, |
493 Condition cond = AL); | 502 Condition cond = AL); |
494 void smlal(Register rd_lo, Register rd_hi, Register rn, Register rm, | 503 void smlal(Register rd_lo, |
| 504 Register rd_hi, |
| 505 Register rn, |
| 506 Register rm, |
495 Condition cond = AL); | 507 Condition cond = AL); |
496 void umlal(Register rd_lo, Register rd_hi, Register rn, Register rm, | 508 void umlal(Register rd_lo, |
| 509 Register rd_hi, |
| 510 Register rn, |
| 511 Register rm, |
497 Condition cond = AL); | 512 Condition cond = AL); |
498 | 513 |
499 // Emulation of this instruction uses IP and the condition codes. Therefore, | 514 // Emulation of this instruction uses IP and the condition codes. Therefore, |
500 // none of the registers can be IP, and the instruction can only be used | 515 // none of the registers can be IP, and the instruction can only be used |
501 // unconditionally. | 516 // unconditionally. |
502 void umaal(Register rd_lo, Register rd_hi, Register rn, Register rm); | 517 void umaal(Register rd_lo, Register rd_hi, Register rn, Register rm); |
503 | 518 |
504 // Division instructions. | 519 // Division instructions. |
505 void sdiv(Register rd, Register rn, Register rm, Condition cond = AL); | 520 void sdiv(Register rd, Register rn, Register rm, Condition cond = AL); |
506 void udiv(Register rd, Register rn, Register rm, Condition cond = AL); | 521 void udiv(Register rd, Register rn, Register rm, Condition cond = AL); |
507 | 522 |
508 // Load/store instructions. | 523 // Load/store instructions. |
509 void ldr(Register rd, Address ad, Condition cond = AL); | 524 void ldr(Register rd, Address ad, Condition cond = AL); |
510 void str(Register rd, Address ad, Condition cond = AL); | 525 void str(Register rd, Address ad, Condition cond = AL); |
511 | 526 |
512 void ldrb(Register rd, Address ad, Condition cond = AL); | 527 void ldrb(Register rd, Address ad, Condition cond = AL); |
513 void strb(Register rd, Address ad, Condition cond = AL); | 528 void strb(Register rd, Address ad, Condition cond = AL); |
514 | 529 |
515 void ldrh(Register rd, Address ad, Condition cond = AL); | 530 void ldrh(Register rd, Address ad, Condition cond = AL); |
516 void strh(Register rd, Address ad, Condition cond = AL); | 531 void strh(Register rd, Address ad, Condition cond = AL); |
517 | 532 |
518 void ldrsb(Register rd, Address ad, Condition cond = AL); | 533 void ldrsb(Register rd, Address ad, Condition cond = AL); |
519 void ldrsh(Register rd, Address ad, Condition cond = AL); | 534 void ldrsh(Register rd, Address ad, Condition cond = AL); |
520 | 535 |
521 // ldrd and strd actually support the full range of addressing modes, but | 536 // ldrd and strd actually support the full range of addressing modes, but |
522 // we don't use them, and we need to split them up into two instructions for | 537 // we don't use them, and we need to split them up into two instructions for |
523 // ARMv5TE, so we only support the base + offset mode. | 538 // ARMv5TE, so we only support the base + offset mode. |
524 // rd must be an even register and rd2 must be rd + 1. | 539 // rd must be an even register and rd2 must be rd + 1. |
525 void ldrd(Register rd, Register rd2, Register rn, int32_t offset, | 540 void ldrd(Register rd, |
| 541 Register rd2, |
| 542 Register rn, |
| 543 int32_t offset, |
526 Condition cond = AL); | 544 Condition cond = AL); |
527 void strd(Register rd, Register rd2, Register rn, int32_t offset, | 545 void strd(Register rd, |
| 546 Register rd2, |
| 547 Register rn, |
| 548 int32_t offset, |
528 Condition cond = AL); | 549 Condition cond = AL); |
529 | 550 |
530 void ldm(BlockAddressMode am, Register base, | 551 void ldm(BlockAddressMode am, |
531 RegList regs, Condition cond = AL); | 552 Register base, |
532 void stm(BlockAddressMode am, Register base, | 553 RegList regs, |
533 RegList regs, Condition cond = AL); | 554 Condition cond = AL); |
| 555 void stm(BlockAddressMode am, |
| 556 Register base, |
| 557 RegList regs, |
| 558 Condition cond = AL); |
534 | 559 |
535 void ldrex(Register rd, Register rn, Condition cond = AL); | 560 void ldrex(Register rd, Register rn, Condition cond = AL); |
536 void strex(Register rd, Register rt, Register rn, Condition cond = AL); | 561 void strex(Register rd, Register rt, Register rn, Condition cond = AL); |
537 | 562 |
538 // Miscellaneous instructions. | 563 // Miscellaneous instructions. |
539 void clrex(); | 564 void clrex(); |
540 void nop(Condition cond = AL); | 565 void nop(Condition cond = AL); |
541 | 566 |
542 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. | 567 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. |
543 void bkpt(uint16_t imm16); | 568 void bkpt(uint16_t imm16); |
544 | 569 |
545 static int32_t BkptEncoding(uint16_t imm16) { | 570 static int32_t BkptEncoding(uint16_t imm16) { |
546 // bkpt requires that the cond field is AL. | 571 // bkpt requires that the cond field is AL. |
547 return (AL << kConditionShift) | B24 | B21 | | 572 return (AL << kConditionShift) | B24 | B21 | ((imm16 >> 4) << 8) | B6 | B5 | |
548 ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf); | 573 B4 | (imm16 & 0xf); |
549 } | 574 } |
550 | 575 |
551 static uword GetBreakInstructionFiller() { | 576 static uword GetBreakInstructionFiller() { return BkptEncoding(0); } |
552 return BkptEncoding(0); | |
553 } | |
554 | 577 |
555 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). | 578 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). |
556 void vmovsr(SRegister sn, Register rt, Condition cond = AL); | 579 void vmovsr(SRegister sn, Register rt, Condition cond = AL); |
557 void vmovrs(Register rt, SRegister sn, Condition cond = AL); | 580 void vmovrs(Register rt, SRegister sn, Condition cond = AL); |
558 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL); | 581 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL); |
559 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL); | 582 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL); |
560 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL); | 583 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL); |
561 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL); | 584 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL); |
562 void vmovdr(DRegister dd, int i, Register rt, Condition cond = AL); | 585 void vmovdr(DRegister dd, int i, Register rt, Condition cond = AL); |
563 void vmovs(SRegister sd, SRegister sm, Condition cond = AL); | 586 void vmovs(SRegister sd, SRegister sm, Condition cond = AL); |
564 void vmovd(DRegister dd, DRegister dm, Condition cond = AL); | 587 void vmovd(DRegister dd, DRegister dm, Condition cond = AL); |
565 void vmovq(QRegister qd, QRegister qm); | 588 void vmovq(QRegister qd, QRegister qm); |
566 | 589 |
567 // Returns false if the immediate cannot be encoded. | 590 // Returns false if the immediate cannot be encoded. |
568 bool vmovs(SRegister sd, float s_imm, Condition cond = AL); | 591 bool vmovs(SRegister sd, float s_imm, Condition cond = AL); |
569 bool vmovd(DRegister dd, double d_imm, Condition cond = AL); | 592 bool vmovd(DRegister dd, double d_imm, Condition cond = AL); |
570 | 593 |
571 void vldrs(SRegister sd, Address ad, Condition cond = AL); | 594 void vldrs(SRegister sd, Address ad, Condition cond = AL); |
572 void vstrs(SRegister sd, Address ad, Condition cond = AL); | 595 void vstrs(SRegister sd, Address ad, Condition cond = AL); |
573 void vldrd(DRegister dd, Address ad, Condition cond = AL); | 596 void vldrd(DRegister dd, Address ad, Condition cond = AL); |
574 void vstrd(DRegister dd, Address ad, Condition cond = AL); | 597 void vstrd(DRegister dd, Address ad, Condition cond = AL); |
575 | 598 |
576 void vldms(BlockAddressMode am, Register base, | 599 void vldms(BlockAddressMode am, |
577 SRegister first, SRegister last, Condition cond = AL); | 600 Register base, |
578 void vstms(BlockAddressMode am, Register base, | 601 SRegister first, |
579 SRegister first, SRegister last, Condition cond = AL); | 602 SRegister last, |
| 603 Condition cond = AL); |
| 604 void vstms(BlockAddressMode am, |
| 605 Register base, |
| 606 SRegister first, |
| 607 SRegister last, |
| 608 Condition cond = AL); |
580 | 609 |
581 void vldmd(BlockAddressMode am, Register base, | 610 void vldmd(BlockAddressMode am, |
582 DRegister first, intptr_t count, Condition cond = AL); | 611 Register base, |
583 void vstmd(BlockAddressMode am, Register base, | 612 DRegister first, |
584 DRegister first, intptr_t count, Condition cond = AL); | 613 intptr_t count, |
| 614 Condition cond = AL); |
| 615 void vstmd(BlockAddressMode am, |
| 616 Register base, |
| 617 DRegister first, |
| 618 intptr_t count, |
| 619 Condition cond = AL); |
585 | 620 |
586 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); | 621 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
587 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); | 622 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
588 void vaddqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm); | 623 void vaddqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm); |
589 void vaddqs(QRegister qd, QRegister qn, QRegister qm); | 624 void vaddqs(QRegister qd, QRegister qn, QRegister qm); |
590 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); | 625 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
591 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); | 626 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); |
592 void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm); | 627 void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm); |
593 void vsubqs(QRegister qd, QRegister qn, QRegister qm); | 628 void vsubqs(QRegister qd, QRegister qn, QRegister qm); |
594 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); | 629 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 // Emit a call that shares its object pool entries with other calls | 722 // Emit a call that shares its object pool entries with other calls |
688 // that have the same equivalence marker. | 723 // that have the same equivalence marker. |
689 void BranchLinkWithEquivalence(const StubEntry& stub_entry, | 724 void BranchLinkWithEquivalence(const StubEntry& stub_entry, |
690 const Object& equivalence); | 725 const Object& equivalence); |
691 | 726 |
692 // Branch and link to [base + offset]. Call sequence is never patched. | 727 // Branch and link to [base + offset]. Call sequence is never patched. |
693 void BranchLinkOffset(Register base, int32_t offset); | 728 void BranchLinkOffset(Register base, int32_t offset); |
694 | 729 |
695 // Add signed immediate value to rd. May clobber IP. | 730 // Add signed immediate value to rd. May clobber IP. |
696 void AddImmediate(Register rd, int32_t value, Condition cond = AL); | 731 void AddImmediate(Register rd, int32_t value, Condition cond = AL); |
697 void AddImmediate(Register rd, Register rn, int32_t value, | 732 void AddImmediate(Register rd, |
| 733 Register rn, |
| 734 int32_t value, |
698 Condition cond = AL); | 735 Condition cond = AL); |
699 void AddImmediateSetFlags(Register rd, Register rn, int32_t value, | 736 void AddImmediateSetFlags(Register rd, |
| 737 Register rn, |
| 738 int32_t value, |
700 Condition cond = AL); | 739 Condition cond = AL); |
701 void SubImmediateSetFlags(Register rd, Register rn, int32_t value, | 740 void SubImmediateSetFlags(Register rd, |
| 741 Register rn, |
| 742 int32_t value, |
702 Condition cond = AL); | 743 Condition cond = AL); |
703 void AndImmediate(Register rd, Register rs, int32_t imm, Condition cond = AL); | 744 void AndImmediate(Register rd, Register rs, int32_t imm, Condition cond = AL); |
704 | 745 |
705 // Test rn and immediate. May clobber IP. | 746 // Test rn and immediate. May clobber IP. |
706 void TestImmediate(Register rn, int32_t imm, Condition cond = AL); | 747 void TestImmediate(Register rn, int32_t imm, Condition cond = AL); |
707 | 748 |
708 // Compare rn with signed immediate value. May clobber IP. | 749 // Compare rn with signed immediate value. May clobber IP. |
709 void CompareImmediate(Register rn, int32_t value, Condition cond = AL); | 750 void CompareImmediate(Register rn, int32_t value, Condition cond = AL); |
710 | 751 |
711 | 752 |
712 // Signed integer division of left by right. Checks to see if integer | 753 // Signed integer division of left by right. Checks to see if integer |
713 // division is supported. If not, uses the FPU for division with | 754 // division is supported. If not, uses the FPU for division with |
714 // temporary registers tmpl and tmpr. tmpl and tmpr must be different | 755 // temporary registers tmpl and tmpr. tmpl and tmpr must be different |
715 // registers. | 756 // registers. |
716 void IntegerDivide(Register result, Register left, Register right, | 757 void IntegerDivide(Register result, |
717 DRegister tmpl, DRegister tmpr); | 758 Register left, |
| 759 Register right, |
| 760 DRegister tmpl, |
| 761 DRegister tmpr); |
718 | 762 |
719 // Load and Store. | 763 // Load and Store. |
720 // These three do not clobber IP. | 764 // These three do not clobber IP. |
721 void LoadPatchableImmediate(Register rd, int32_t value, Condition cond = AL); | 765 void LoadPatchableImmediate(Register rd, int32_t value, Condition cond = AL); |
722 void LoadDecodableImmediate(Register rd, int32_t value, Condition cond = AL); | 766 void LoadDecodableImmediate(Register rd, int32_t value, Condition cond = AL); |
723 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); | 767 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); |
724 // These two may clobber IP. | 768 // These two may clobber IP. |
725 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); | 769 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); |
726 void LoadDImmediate(DRegister dd, double value, | 770 void LoadDImmediate(DRegister dd, |
727 Register scratch, Condition cond = AL); | 771 double value, |
| 772 Register scratch, |
| 773 Condition cond = AL); |
728 | 774 |
729 void MarkExceptionHandler(Label* label); | 775 void MarkExceptionHandler(Label* label); |
730 | 776 |
731 void Drop(intptr_t stack_elements); | 777 void Drop(intptr_t stack_elements); |
732 | 778 |
733 void RestoreCodePointer(); | 779 void RestoreCodePointer(); |
734 void LoadPoolPointer(Register reg = PP); | 780 void LoadPoolPointer(Register reg = PP); |
735 | 781 |
736 void LoadIsolate(Register rd); | 782 void LoadIsolate(Register rd); |
737 | 783 |
738 void LoadObject(Register rd, const Object& object, Condition cond = AL); | 784 void LoadObject(Register rd, const Object& object, Condition cond = AL); |
739 void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL); | 785 void LoadUniqueObject(Register rd, const Object& object, Condition cond = AL); |
740 void LoadFunctionFromCalleePool(Register dst, | 786 void LoadFunctionFromCalleePool(Register dst, |
741 const Function& function, | 787 const Function& function, |
742 Register new_pp); | 788 Register new_pp); |
743 void LoadNativeEntry(Register dst, | 789 void LoadNativeEntry(Register dst, |
744 const ExternalLabel* label, | 790 const ExternalLabel* label, |
745 Patchability patchable, | 791 Patchability patchable, |
746 Condition cond = AL); | 792 Condition cond = AL); |
747 void PushObject(const Object& object); | 793 void PushObject(const Object& object); |
748 void CompareObject(Register rn, const Object& object); | 794 void CompareObject(Register rn, const Object& object); |
749 | 795 |
750 void StoreIntoObject(Register object, // Object we are storing into. | 796 void StoreIntoObject(Register object, // Object we are storing into. |
751 const Address& dest, // Where we are storing into. | 797 const Address& dest, // Where we are storing into. |
752 Register value, // Value we are storing. | 798 Register value, // Value we are storing. |
753 bool can_value_be_smi = true); | 799 bool can_value_be_smi = true); |
754 void StoreIntoObjectOffset(Register object, | 800 void StoreIntoObjectOffset(Register object, |
755 int32_t offset, | 801 int32_t offset, |
756 Register value, | 802 Register value, |
757 bool can_value_be_smi = true); | 803 bool can_value_be_smi = true); |
758 | 804 |
759 void StoreIntoObjectNoBarrier(Register object, | 805 void StoreIntoObjectNoBarrier(Register object, |
760 const Address& dest, | 806 const Address& dest, |
761 Register value); | 807 Register value); |
762 void StoreIntoObjectNoBarrier(Register object, | 808 void StoreIntoObjectNoBarrier(Register object, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 | 881 |
836 void LoadMultipleDFromOffset(DRegister first, | 882 void LoadMultipleDFromOffset(DRegister first, |
837 intptr_t count, | 883 intptr_t count, |
838 Register base, | 884 Register base, |
839 int32_t offset); | 885 int32_t offset); |
840 void StoreMultipleDToOffset(DRegister first, | 886 void StoreMultipleDToOffset(DRegister first, |
841 intptr_t count, | 887 intptr_t count, |
842 Register base, | 888 Register base, |
843 int32_t offset); | 889 int32_t offset); |
844 | 890 |
845 void CopyDoubleField(Register dst, Register src, | 891 void CopyDoubleField(Register dst, |
846 Register tmp1, Register tmp2, DRegister dtmp); | 892 Register src, |
847 void CopyFloat32x4Field(Register dst, Register src, | 893 Register tmp1, |
848 Register tmp1, Register tmp2, DRegister dtmp); | 894 Register tmp2, |
849 void CopyFloat64x2Field(Register dst, Register src, | 895 DRegister dtmp); |
850 Register tmp1, Register tmp2, DRegister dtmp); | 896 void CopyFloat32x4Field(Register dst, |
| 897 Register src, |
| 898 Register tmp1, |
| 899 Register tmp2, |
| 900 DRegister dtmp); |
| 901 void CopyFloat64x2Field(Register dst, |
| 902 Register src, |
| 903 Register tmp1, |
| 904 Register tmp2, |
| 905 DRegister dtmp); |
851 | 906 |
852 void Push(Register rd, Condition cond = AL); | 907 void Push(Register rd, Condition cond = AL); |
853 void Pop(Register rd, Condition cond = AL); | 908 void Pop(Register rd, Condition cond = AL); |
854 | 909 |
855 void PushList(RegList regs, Condition cond = AL); | 910 void PushList(RegList regs, Condition cond = AL); |
856 void PopList(RegList regs, Condition cond = AL); | 911 void PopList(RegList regs, Condition cond = AL); |
857 | 912 |
858 void MoveRegister(Register rd, Register rm, Condition cond = AL); | 913 void MoveRegister(Register rd, Register rm, Condition cond = AL); |
859 | 914 |
860 // Convenience shift instructions. Use mov instruction with shifter operand | 915 // Convenience shift instructions. Use mov instruction with shifter operand |
861 // for variants setting the status flags. | 916 // for variants setting the status flags. |
862 void Lsl(Register rd, Register rm, const Operand& shift_imm, | 917 void Lsl(Register rd, |
| 918 Register rm, |
| 919 const Operand& shift_imm, |
863 Condition cond = AL); | 920 Condition cond = AL); |
864 void Lsl(Register rd, Register rm, Register rs, Condition cond = AL); | 921 void Lsl(Register rd, Register rm, Register rs, Condition cond = AL); |
865 void Lsr(Register rd, Register rm, const Operand& shift_imm, | 922 void Lsr(Register rd, |
| 923 Register rm, |
| 924 const Operand& shift_imm, |
866 Condition cond = AL); | 925 Condition cond = AL); |
867 void Lsr(Register rd, Register rm, Register rs, Condition cond = AL); | 926 void Lsr(Register rd, Register rm, Register rs, Condition cond = AL); |
868 void Asr(Register rd, Register rm, const Operand& shift_imm, | 927 void Asr(Register rd, |
| 928 Register rm, |
| 929 const Operand& shift_imm, |
869 Condition cond = AL); | 930 Condition cond = AL); |
870 void Asr(Register rd, Register rm, Register rs, Condition cond = AL); | 931 void Asr(Register rd, Register rm, Register rs, Condition cond = AL); |
871 void Asrs(Register rd, Register rm, const Operand& shift_imm, | 932 void Asrs(Register rd, |
| 933 Register rm, |
| 934 const Operand& shift_imm, |
872 Condition cond = AL); | 935 Condition cond = AL); |
873 void Ror(Register rd, Register rm, const Operand& shift_imm, | 936 void Ror(Register rd, |
| 937 Register rm, |
| 938 const Operand& shift_imm, |
874 Condition cond = AL); | 939 Condition cond = AL); |
875 void Ror(Register rd, Register rm, Register rs, Condition cond = AL); | 940 void Ror(Register rd, Register rm, Register rs, Condition cond = AL); |
876 void Rrx(Register rd, Register rm, Condition cond = AL); | 941 void Rrx(Register rd, Register rm, Condition cond = AL); |
877 | 942 |
878 // Fill rd with the sign of rm. | 943 // Fill rd with the sign of rm. |
879 void SignFill(Register rd, Register rm, Condition cond = AL); | 944 void SignFill(Register rd, Register rm, Condition cond = AL); |
880 | 945 |
881 void Vreciprocalqs(QRegister qd, QRegister qm); | 946 void Vreciprocalqs(QRegister qd, QRegister qm); |
882 void VreciprocalSqrtqs(QRegister qd, QRegister qm); | 947 void VreciprocalSqrtqs(QRegister qd, QRegister qm); |
883 // If qm must be preserved, then provide a (non-QTMP) temporary. | 948 // If qm must be preserved, then provide a (non-QTMP) temporary. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 void EnterStubFrame(); | 1012 void EnterStubFrame(); |
948 void LeaveStubFrame(); | 1013 void LeaveStubFrame(); |
949 | 1014 |
950 void MonomorphicCheckedEntry(); | 1015 void MonomorphicCheckedEntry(); |
951 | 1016 |
952 // The register into which the allocation stats table is loaded with | 1017 // The register into which the allocation stats table is loaded with |
953 // LoadAllocationStatsAddress should be passed to | 1018 // LoadAllocationStatsAddress should be passed to |
954 // IncrementAllocationStats(WithSize) as stats_addr_reg to update the | 1019 // IncrementAllocationStats(WithSize) as stats_addr_reg to update the |
955 // allocation stats. These are separate assembler macros so we can | 1020 // allocation stats. These are separate assembler macros so we can |
956 // avoid a dependent load too nearby the load of the table address. | 1021 // avoid a dependent load too nearby the load of the table address. |
957 void LoadAllocationStatsAddress(Register dest, | 1022 void LoadAllocationStatsAddress(Register dest, intptr_t cid); |
958 intptr_t cid); | |
959 void IncrementAllocationStats(Register stats_addr, | 1023 void IncrementAllocationStats(Register stats_addr, |
960 intptr_t cid, | 1024 intptr_t cid, |
961 Heap::Space space); | 1025 Heap::Space space); |
962 void IncrementAllocationStatsWithSize(Register stats_addr_reg, | 1026 void IncrementAllocationStatsWithSize(Register stats_addr_reg, |
963 Register size_reg, | 1027 Register size_reg, |
964 Heap::Space space); | 1028 Heap::Space space); |
965 | 1029 |
966 Address ElementAddressForIntIndex(bool is_load, | 1030 Address ElementAddressForIntIndex(bool is_load, |
967 bool is_external, | 1031 bool is_external, |
968 intptr_t cid, | 1032 intptr_t cid, |
(...skipping 26 matching lines...) Expand all Loading... |
995 Register index); | 1059 Register index); |
996 | 1060 |
997 void LoadHalfWordUnaligned(Register dst, Register addr, Register tmp); | 1061 void LoadHalfWordUnaligned(Register dst, Register addr, Register tmp); |
998 void LoadHalfWordUnsignedUnaligned(Register dst, Register addr, Register tmp); | 1062 void LoadHalfWordUnsignedUnaligned(Register dst, Register addr, Register tmp); |
999 void StoreHalfWordUnaligned(Register src, Register addr, Register tmp); | 1063 void StoreHalfWordUnaligned(Register src, Register addr, Register tmp); |
1000 void LoadWordUnaligned(Register dst, Register addr, Register tmp); | 1064 void LoadWordUnaligned(Register dst, Register addr, Register tmp); |
1001 void StoreWordUnaligned(Register src, Register addr, Register tmp); | 1065 void StoreWordUnaligned(Register src, Register addr, Register tmp); |
1002 | 1066 |
1003 // If allocation tracing for |cid| is enabled, will jump to |trace| label, | 1067 // If allocation tracing for |cid| is enabled, will jump to |trace| label, |
1004 // which will allocate in the runtime where tracing occurs. | 1068 // which will allocate in the runtime where tracing occurs. |
1005 void MaybeTraceAllocation(intptr_t cid, | 1069 void MaybeTraceAllocation(intptr_t cid, Register temp_reg, Label* trace); |
1006 Register temp_reg, | |
1007 Label* trace); | |
1008 | 1070 |
1009 // Inlined allocation of an instance of class 'cls', code has no runtime | 1071 // Inlined allocation of an instance of class 'cls', code has no runtime |
1010 // calls. Jump to 'failure' if the instance cannot be allocated here. | 1072 // calls. Jump to 'failure' if the instance cannot be allocated here. |
1011 // Allocated instance is returned in 'instance_reg'. | 1073 // Allocated instance is returned in 'instance_reg'. |
1012 // Only the tags field of the object is initialized. | 1074 // Only the tags field of the object is initialized. |
1013 void TryAllocate(const Class& cls, | 1075 void TryAllocate(const Class& cls, |
1014 Label* failure, | 1076 Label* failure, |
1015 Register instance_reg, | 1077 Register instance_reg, |
1016 Register temp_reg); | 1078 Register temp_reg); |
1017 | 1079 |
1018 void TryAllocateArray(intptr_t cid, | 1080 void TryAllocateArray(intptr_t cid, |
1019 intptr_t instance_size, | 1081 intptr_t instance_size, |
1020 Label* failure, | 1082 Label* failure, |
1021 Register instance, | 1083 Register instance, |
1022 Register end_address, | 1084 Register end_address, |
1023 Register temp1, | 1085 Register temp1, |
1024 Register temp2); | 1086 Register temp2); |
1025 | 1087 |
1026 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 1088 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
1027 void Emit(int32_t value); | 1089 void Emit(int32_t value); |
1028 | 1090 |
1029 // On some other platforms, we draw a distinction between safe and unsafe | 1091 // On some other platforms, we draw a distinction between safe and unsafe |
1030 // smis. | 1092 // smis. |
1031 static bool IsSafe(const Object& object) { return true; } | 1093 static bool IsSafe(const Object& object) { return true; } |
1032 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } | 1094 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } |
1033 | 1095 |
1034 bool constant_pool_allowed() const { | 1096 bool constant_pool_allowed() const { return constant_pool_allowed_; } |
1035 return constant_pool_allowed_; | 1097 void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; } |
1036 } | |
1037 void set_constant_pool_allowed(bool b) { | |
1038 constant_pool_allowed_ = b; | |
1039 } | |
1040 | 1098 |
1041 private: | 1099 private: |
1042 AssemblerBuffer buffer_; // Contains position independent code. | 1100 AssemblerBuffer buffer_; // Contains position independent code. |
1043 ObjectPoolWrapper object_pool_wrapper_; | 1101 ObjectPoolWrapper object_pool_wrapper_; |
1044 int32_t prologue_offset_; | 1102 int32_t prologue_offset_; |
1045 bool has_single_entry_point_; | 1103 bool has_single_entry_point_; |
1046 bool use_far_branches_; | 1104 bool use_far_branches_; |
1047 | 1105 |
1048 // If you are thinking of using one or both of these instructions directly, | 1106 // If you are thinking of using one or both of these instructions directly, |
1049 // instead LoadImmediate should probably be used. | 1107 // instead LoadImmediate should probably be used. |
1050 void movw(Register rd, uint16_t imm16, Condition cond = AL); | 1108 void movw(Register rd, uint16_t imm16, Condition cond = AL); |
1051 void movt(Register rd, uint16_t imm16, Condition cond = AL); | 1109 void movt(Register rd, uint16_t imm16, Condition cond = AL); |
1052 | 1110 |
1053 void BindARMv6(Label* label); | 1111 void BindARMv6(Label* label); |
1054 void BindARMv7(Label* label); | 1112 void BindARMv7(Label* label); |
1055 | 1113 |
1056 void LoadWordFromPoolOffset(Register rd, | 1114 void LoadWordFromPoolOffset(Register rd, |
1057 int32_t offset, | 1115 int32_t offset, |
1058 Register pp, | 1116 Register pp, |
1059 Condition cond); | 1117 Condition cond); |
1060 | 1118 |
1061 void BranchLink(const ExternalLabel* label); | 1119 void BranchLink(const ExternalLabel* label); |
1062 | 1120 |
1063 class CodeComment : public ZoneAllocated { | 1121 class CodeComment : public ZoneAllocated { |
1064 public: | 1122 public: |
1065 CodeComment(intptr_t pc_offset, const String& comment) | 1123 CodeComment(intptr_t pc_offset, const String& comment) |
1066 : pc_offset_(pc_offset), comment_(comment) { } | 1124 : pc_offset_(pc_offset), comment_(comment) {} |
1067 | 1125 |
1068 intptr_t pc_offset() const { return pc_offset_; } | 1126 intptr_t pc_offset() const { return pc_offset_; } |
1069 const String& comment() const { return comment_; } | 1127 const String& comment() const { return comment_; } |
1070 | 1128 |
1071 private: | 1129 private: |
1072 intptr_t pc_offset_; | 1130 intptr_t pc_offset_; |
1073 const String& comment_; | 1131 const String& comment_; |
1074 | 1132 |
1075 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 1133 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
1076 }; | 1134 }; |
(...skipping 11 matching lines...) Expand all Loading... |
1088 void EmitType01(Condition cond, | 1146 void EmitType01(Condition cond, |
1089 int type, | 1147 int type, |
1090 Opcode opcode, | 1148 Opcode opcode, |
1091 int set_cc, | 1149 int set_cc, |
1092 Register rn, | 1150 Register rn, |
1093 Register rd, | 1151 Register rd, |
1094 Operand o); | 1152 Operand o); |
1095 | 1153 |
1096 void EmitType5(Condition cond, int32_t offset, bool link); | 1154 void EmitType5(Condition cond, int32_t offset, bool link); |
1097 | 1155 |
1098 void EmitMemOp(Condition cond, | 1156 void EmitMemOp(Condition cond, bool load, bool byte, Register rd, Address ad); |
1099 bool load, | |
1100 bool byte, | |
1101 Register rd, | |
1102 Address ad); | |
1103 | 1157 |
1104 void EmitMemOpAddressMode3(Condition cond, | 1158 void EmitMemOpAddressMode3(Condition cond, |
1105 int32_t mode, | 1159 int32_t mode, |
1106 Register rd, | 1160 Register rd, |
1107 Address ad); | 1161 Address ad); |
1108 | 1162 |
1109 void EmitMultiMemOp(Condition cond, | 1163 void EmitMultiMemOp(Condition cond, |
1110 BlockAddressMode am, | 1164 BlockAddressMode am, |
1111 bool load, | 1165 bool load, |
1112 Register base, | 1166 Register base, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 SRegister sd, | 1210 SRegister sd, |
1157 SRegister sn, | 1211 SRegister sn, |
1158 SRegister sm); | 1212 SRegister sm); |
1159 | 1213 |
1160 void EmitVFPddd(Condition cond, | 1214 void EmitVFPddd(Condition cond, |
1161 int32_t opcode, | 1215 int32_t opcode, |
1162 DRegister dd, | 1216 DRegister dd, |
1163 DRegister dn, | 1217 DRegister dn, |
1164 DRegister dm); | 1218 DRegister dm); |
1165 | 1219 |
1166 void EmitVFPsd(Condition cond, | 1220 void EmitVFPsd(Condition cond, int32_t opcode, SRegister sd, DRegister dm); |
1167 int32_t opcode, | |
1168 SRegister sd, | |
1169 DRegister dm); | |
1170 | 1221 |
1171 void EmitVFPds(Condition cond, | 1222 void EmitVFPds(Condition cond, int32_t opcode, DRegister dd, SRegister sm); |
1172 int32_t opcode, | |
1173 DRegister dd, | |
1174 SRegister sm); | |
1175 | 1223 |
1176 void EmitSIMDqqq(int32_t opcode, OperandSize sz, | 1224 void EmitSIMDqqq(int32_t opcode, |
1177 QRegister qd, QRegister qn, QRegister qm); | 1225 OperandSize sz, |
| 1226 QRegister qd, |
| 1227 QRegister qn, |
| 1228 QRegister qm); |
1178 | 1229 |
1179 void EmitSIMDddd(int32_t opcode, OperandSize sz, | 1230 void EmitSIMDddd(int32_t opcode, |
1180 DRegister dd, DRegister dn, DRegister dm); | 1231 OperandSize sz, |
| 1232 DRegister dd, |
| 1233 DRegister dn, |
| 1234 DRegister dm); |
1181 | 1235 |
1182 void EmitFarBranch(Condition cond, int32_t offset, bool link); | 1236 void EmitFarBranch(Condition cond, int32_t offset, bool link); |
1183 void EmitBranch(Condition cond, Label* label, bool link); | 1237 void EmitBranch(Condition cond, Label* label, bool link); |
1184 int32_t EncodeBranchOffset(int32_t offset, int32_t inst); | 1238 int32_t EncodeBranchOffset(int32_t offset, int32_t inst); |
1185 static int32_t DecodeBranchOffset(int32_t inst); | 1239 static int32_t DecodeBranchOffset(int32_t inst); |
1186 int32_t EncodeTstOffset(int32_t offset, int32_t inst); | 1240 int32_t EncodeTstOffset(int32_t offset, int32_t inst); |
1187 int32_t DecodeTstOffset(int32_t inst); | 1241 int32_t DecodeTstOffset(int32_t inst); |
1188 | 1242 |
1189 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 1243 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
1190 | 1244 |
1191 // Shorter filtering sequence that assumes that value is not a smi. | 1245 // Shorter filtering sequence that assumes that value is not a smi. |
1192 void StoreIntoObjectFilterNoSmi(Register object, | 1246 void StoreIntoObjectFilterNoSmi(Register object, |
1193 Register value, | 1247 Register value, |
1194 Label* no_update); | 1248 Label* no_update); |
1195 | 1249 |
1196 DISALLOW_ALLOCATION(); | 1250 DISALLOW_ALLOCATION(); |
1197 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1251 DISALLOW_COPY_AND_ASSIGN(Assembler); |
1198 }; | 1252 }; |
1199 | 1253 |
1200 } // namespace dart | 1254 } // namespace dart |
1201 | 1255 |
1202 #endif // RUNTIME_VM_ASSEMBLER_ARM_H_ | 1256 #endif // RUNTIME_VM_ASSEMBLER_ARM_H_ |
OLD | NEW |