| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 VM_ASSEMBLER_ARM64_H_ | 5 #ifndef VM_ASSEMBLER_ARM64_H_ |
| 6 #define VM_ASSEMBLER_ARM64_H_ | 6 #define VM_ASSEMBLER_ARM64_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 } | 62 } |
| 63 | 63 |
| 64 friend class Assembler; | 64 friend class Assembler; |
| 65 DISALLOW_COPY_AND_ASSIGN(Label); | 65 DISALLOW_COPY_AND_ASSIGN(Label); |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 | 68 |
| 69 class Address : public ValueObject { | 69 class Address : public ValueObject { |
| 70 public: | 70 public: |
| 71 Address(const Address& other) | 71 Address(const Address& other) |
| 72 : ValueObject(), encoding_(other.encoding_) { | 72 : ValueObject(), |
| 73 encoding_(other.encoding_), |
| 74 type_(other.type_), |
| 75 base_(other.base_) { |
| 73 } | 76 } |
| 74 | 77 |
| 75 Address& operator=(const Address& other) { | 78 Address& operator=(const Address& other) { |
| 76 encoding_ = other.encoding_; | 79 encoding_ = other.encoding_; |
| 80 type_ = other.type_; |
| 81 base_ = other.base_; |
| 77 return *this; | 82 return *this; |
| 78 } | 83 } |
| 79 | 84 |
| 80 Address(Register rn, int32_t offset = 0) { | 85 enum AddressType { |
| 81 ASSERT(Utils::IsAbsoluteUint(12, offset)); | 86 Offset, |
| 82 encoding_ = -1; | 87 PreIndex, |
| 88 PostIndex, |
| 89 Reg, |
| 90 }; |
| 91 |
| 92 // Offset is in bytes. For the unsigned imm12 case, we unscale based on the |
| 93 // operand size, and assert that offset is aligned accordingly. |
| 94 // For the smaller signed imm9 case, the offset is the number of bytes, but |
| 95 // is unscaled. |
| 96 Address(Register rn, int32_t offset = 0, AddressType at = Offset, |
| 97 OperandSize sz = kDoubleWord) { |
| 98 ASSERT((rn != R31) && (rn != ZR)); |
| 99 const Register crn = ConcreteRegister(rn); |
| 100 const int32_t scale = Log2OperandSizeBytes(sz); |
| 101 if (Utils::IsUint(12 + scale, offset) && (at == Offset)) { |
| 102 ASSERT(offset == ((offset >> scale) << scale)); |
| 103 encoding_ = |
| 104 B24 | |
| 105 ((offset >> scale) << kImm12Shift) | |
| 106 (static_cast<int32_t>(crn) << kRnShift); |
| 107 } else { |
| 108 ASSERT(Utils::IsInt(9, offset)); |
| 109 ASSERT((at == PreIndex) || (at == PostIndex)); |
| 110 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10); |
| 111 encoding_ = |
| 112 idx | |
| 113 ((offset & 0x1ff) << kImm9Shift) | |
| 114 (static_cast<int32_t>(crn) << kRnShift); |
| 115 } |
| 116 type_ = at; |
| 117 base_ = crn; |
| 118 } |
| 119 |
| 120 // TODO(zra): Write CanHoldOffset(int32_t off, AddressType, OperandSize). |
| 121 // TODO(zra): Write constructor for PC-relative load address. |
| 122 |
| 123 // Base register rn with offset rm. rm is sign-extended according to ext. |
| 124 // If ext is UXTX, rm may be optionally scaled by the |
| 125 // Log2OperandSize (specified by the instruction). |
| 126 Address(Register rn, Register rm, Extend ext = UXTX, bool scaled = false) { |
| 127 ASSERT((rn != R31) && (rn != ZR)); |
| 128 ASSERT((rm != R31) && (rm != SP)); |
| 129 ASSERT(!scaled || (ext == UXTX)); // Can only scale when ext = UXTX. |
| 130 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); |
| 131 const Register crn = ConcreteRegister(rn); |
| 132 const Register crm = ConcreteRegister(rm); |
| 133 const int32_t s = scaled ? B12 : 0; |
| 134 encoding_ = |
| 135 B21 | B11 | s | |
| 136 (static_cast<int32_t>(crn) << kRnShift) | |
| 137 (static_cast<int32_t>(crm) << kRmShift) | |
| 138 (static_cast<int32_t>(ext) << kExtendTypeShift); |
| 139 type_ = Reg; |
| 140 base_ = crn; |
| 83 } | 141 } |
| 84 | 142 |
| 85 private: | 143 private: |
| 86 uint32_t encoding() const { return encoding_; } | 144 uint32_t encoding() const { return encoding_; } |
| 145 AddressType type() const { return type_; } |
| 146 Register base() const { return base_; } |
| 87 | 147 |
| 88 uint32_t encoding_; | 148 uint32_t encoding_; |
| 149 AddressType type_; |
| 150 Register base_; |
| 89 | 151 |
| 90 friend class Assembler; | 152 friend class Assembler; |
| 91 }; | 153 }; |
| 92 | 154 |
| 93 | 155 |
| 94 class FieldAddress : public Address { | 156 class FieldAddress : public Address { |
| 95 public: | 157 public: |
| 96 FieldAddress(Register base, int32_t disp) | 158 FieldAddress(Register base, int32_t disp) |
| 97 : Address(base, disp - kHeapObjectTag) { } | 159 : Address(base, disp - kHeapObjectTag) { } |
| 98 | 160 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 ASSERT(rd != SP); | 343 ASSERT(rd != SP); |
| 282 const Register crd = ConcreteRegister(rd); | 344 const Register crd = ConcreteRegister(rd); |
| 283 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); | 345 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); |
| 284 } | 346 } |
| 285 void movz(Register rd, int32_t imm, int32_t hw_idx) { | 347 void movz(Register rd, int32_t imm, int32_t hw_idx) { |
| 286 ASSERT(rd != SP); | 348 ASSERT(rd != SP); |
| 287 const Register crd = ConcreteRegister(rd); | 349 const Register crd = ConcreteRegister(rd); |
| 288 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); | 350 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| 289 } | 351 } |
| 290 | 352 |
| 353 // Loads and Stores. |
| 354 void ldr(Register rt, Address a) { |
| 355 // If we are doing pre-/post-indexing, and the base and result registers |
| 356 // are the same, then the result of the load will be clobbered by the |
| 357 // writeback, which is unlikely to be useful. |
| 358 ASSERT(((a.type() != Address::PreIndex) && |
| 359 (a.type() != Address::PostIndex)) || |
| 360 (rt != a.base())); |
| 361 EmitLoadStoreReg(LDR, rt, a, kDoubleWord); |
| 362 } |
| 363 void str(Register rt, Address a) { |
| 364 EmitLoadStoreReg(STR, rt, a, kDoubleWord); |
| 365 } |
| 291 | 366 |
| 292 // Function return. | 367 // Function return. |
| 293 void ret(Register rn = R30) { | 368 void ret(Register rn = R30) { |
| 294 EmitUnconditionalBranchRegOp(RET, rn); | 369 EmitUnconditionalBranchRegOp(RET, rn); |
| 295 } | 370 } |
| 296 | 371 |
| 297 private: | 372 private: |
| 298 AssemblerBuffer buffer_; // Contains position independent code. | 373 AssemblerBuffer buffer_; // Contains position independent code. |
| 299 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. | 374 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
| 300 int32_t prologue_offset_; | 375 int32_t prologue_offset_; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 ASSERT((sz == kDoubleWord) || (sz == kWord)); | 451 ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| 377 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 452 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 378 const int32_t encoding = | 453 const int32_t encoding = |
| 379 op | size | | 454 op | size | |
| 380 (static_cast<int32_t>(rd) << kRdShift) | | 455 (static_cast<int32_t>(rd) << kRdShift) | |
| 381 (hw_idx << kHWShift) | | 456 (hw_idx << kHWShift) | |
| 382 (imm << kImm16Shift); | 457 (imm << kImm16Shift); |
| 383 Emit(encoding); | 458 Emit(encoding); |
| 384 } | 459 } |
| 385 | 460 |
| 461 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, |
| 462 OperandSize sz) { |
| 463 const int32_t size = Log2OperandSizeBytes(sz); |
| 464 const int32_t encoding = |
| 465 op | (size << kSzShift) | |
| 466 (static_cast<int32_t>(rt) << kRtShift) | |
| 467 a.encoding(); |
| 468 Emit(encoding); |
| 469 } |
| 470 |
| 386 DISALLOW_ALLOCATION(); | 471 DISALLOW_ALLOCATION(); |
| 387 DISALLOW_COPY_AND_ASSIGN(Assembler); | 472 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 388 }; | 473 }; |
| 389 | 474 |
| 390 } // namespace dart | 475 } // namespace dart |
| 391 | 476 |
| 392 #endif // VM_ASSEMBLER_ARM64_H_ | 477 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |