| 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 |
| 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_arm64.h" | 14 #include "vm/constants_arm64.h" |
| 15 #include "vm/hash_map.h" | 15 #include "vm/hash_map.h" |
| 16 #include "vm/longjump.h" | 16 #include "vm/longjump.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 | 24 |
| 25 class Immediate : public ValueObject { |
| 26 public: |
| 27 explicit Immediate(int64_t value) : value_(value) { } |
| 28 |
| 29 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) { } |
| 30 Immediate& operator=(const Immediate& other) { |
| 31 value_ = other.value_; |
| 32 return *this; |
| 33 } |
| 34 |
| 35 private: |
| 36 int64_t value_; |
| 37 |
| 38 int64_t value() const { return value_; } |
| 39 |
| 40 friend class Assembler; |
| 41 }; |
| 42 |
| 43 |
| 25 class Label : public ValueObject { | 44 class Label : public ValueObject { |
| 26 public: | 45 public: |
| 27 Label() : position_(0) { } | 46 Label() : position_(0) { } |
| 28 | 47 |
| 29 ~Label() { | 48 ~Label() { |
| 30 // Assert if label is being destroyed with unresolved branches pending. | 49 // Assert if label is being destroyed with unresolved branches pending. |
| 31 ASSERT(!IsLinked()); | 50 ASSERT(!IsLinked()); |
| 32 } | 51 } |
| 33 | 52 |
| 34 // Returns the position for bound and linked labels. Cannot be used | 53 // Returns the position for bound and linked labels. Cannot be used |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10); | 138 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10); |
| 120 encoding_ = | 139 encoding_ = |
| 121 idx | | 140 idx | |
| 122 ((offset & 0x1ff) << kImm9Shift) | | 141 ((offset & 0x1ff) << kImm9Shift) | |
| 123 (static_cast<int32_t>(crn) << kRnShift); | 142 (static_cast<int32_t>(crn) << kRnShift); |
| 124 } | 143 } |
| 125 type_ = at; | 144 type_ = at; |
| 126 base_ = crn; | 145 base_ = crn; |
| 127 } | 146 } |
| 128 | 147 |
| 148 // This addressing mode does not exist. |
| 149 Address(Register rn, Register offset, AddressType at, |
| 150 OperandSize sz = kDoubleWord); |
| 151 |
| 129 static bool CanHoldOffset(int32_t offset, AddressType at = Offset, | 152 static bool CanHoldOffset(int32_t offset, AddressType at = Offset, |
| 130 OperandSize sz = kDoubleWord) { | 153 OperandSize sz = kDoubleWord) { |
| 131 if (at == Offset) { | 154 if (at == Offset) { |
| 132 // Offset fits in 12 bit unsigned and has right alignment for sz, | 155 // Offset fits in 12 bit unsigned and has right alignment for sz, |
| 133 // or fits in 9 bit signed offset with no alignment restriction. | 156 // or fits in 9 bit signed offset with no alignment restriction. |
| 134 const int32_t scale = Log2OperandSizeBytes(sz); | 157 const int32_t scale = Log2OperandSizeBytes(sz); |
| 135 return (Utils::IsUint(12 + scale, offset) && | 158 return (Utils::IsUint(12 + scale, offset) && |
| 136 (offset == ((offset >> scale) << scale))) || | 159 (offset == ((offset >> scale) << scale))) || |
| 137 (Utils::IsInt(9, offset)); | 160 (Utils::IsInt(9, offset)); |
| 138 } else if (at == PCOffset) { | 161 } else if (at == PCOffset) { |
| 139 return Utils::IsInt(21, offset) && | 162 return Utils::IsInt(21, offset) && |
| 140 (offset == ((offset >> 2) << 2)); | 163 (offset == ((offset >> 2) << 2)); |
| 141 } else { | 164 } else { |
| 142 ASSERT((at == PreIndex) || (at == PostIndex)); | 165 ASSERT((at == PreIndex) || (at == PostIndex)); |
| 143 return Utils::IsInt(9, offset); | 166 return Utils::IsInt(9, offset); |
| 144 } | 167 } |
| 145 } | 168 } |
| 146 | 169 |
| 147 // PC-relative load address. | 170 // PC-relative load address. |
| 148 static Address PC(int32_t pc_off) { | 171 static Address PC(int32_t pc_off) { |
| 149 ASSERT(CanHoldOffset(pc_off, PCOffset)); | 172 ASSERT(CanHoldOffset(pc_off, PCOffset)); |
| 150 Address addr; | 173 Address addr; |
| 151 addr.encoding_ = (((pc_off >> 2) << kImm19Shift) & kImm19Mask); | 174 addr.encoding_ = (((pc_off >> 2) << kImm19Shift) & kImm19Mask); |
| 152 addr.base_ = kNoRegister; | 175 addr.base_ = kNoRegister; |
| 153 addr.type_ = PCOffset; | 176 addr.type_ = PCOffset; |
| 154 return addr; | 177 return addr; |
| 155 } | 178 } |
| 156 | 179 |
| 180 // This addressing mode does not exist. |
| 181 static Address PC(Register r); |
| 182 |
| 157 enum Scaling { | 183 enum Scaling { |
| 158 Unscaled, | 184 Unscaled, |
| 159 Scaled, | 185 Scaled, |
| 160 }; | 186 }; |
| 161 | 187 |
| 162 // Base register rn with offset rm. rm is sign-extended according to ext. | 188 // Base register rn with offset rm. rm is sign-extended according to ext. |
| 163 // If ext is UXTX, rm may be optionally scaled by the | 189 // If ext is UXTX, rm may be optionally scaled by the |
| 164 // Log2OperandSize (specified by the instruction). | 190 // Log2OperandSize (specified by the instruction). |
| 165 Address(Register rn, Register rm, | 191 Address(Register rn, Register rm, |
| 166 Extend ext = UXTX, Scaling scale = Unscaled) { | 192 Extend ext = UXTX, Scaling scale = Unscaled) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 265 |
| 240 friend class Assembler; | 266 friend class Assembler; |
| 241 }; | 267 }; |
| 242 | 268 |
| 243 | 269 |
| 244 class FieldAddress : public Address { | 270 class FieldAddress : public Address { |
| 245 public: | 271 public: |
| 246 FieldAddress(Register base, int32_t disp, OperandSize sz = kDoubleWord) | 272 FieldAddress(Register base, int32_t disp, OperandSize sz = kDoubleWord) |
| 247 : Address(base, disp - kHeapObjectTag, Offset, sz) { } | 273 : Address(base, disp - kHeapObjectTag, Offset, sz) { } |
| 248 | 274 |
| 275 // This addressing mode does not exist. |
| 276 FieldAddress(Register base, Register disp, OperandSize sz = kDoubleWord); |
| 277 |
| 249 FieldAddress(const FieldAddress& other) : Address(other) { } | 278 FieldAddress(const FieldAddress& other) : Address(other) { } |
| 250 | 279 |
| 251 FieldAddress& operator=(const FieldAddress& other) { | 280 FieldAddress& operator=(const FieldAddress& other) { |
| 252 Address::operator=(other); | 281 Address::operator=(other); |
| 253 return *this; | 282 return *this; |
| 254 } | 283 } |
| 255 }; | 284 }; |
| 256 | 285 |
| 257 | 286 |
| 258 class Operand : public ValueObject { | 287 class Operand : public ValueObject { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 289 ASSERT(Utils::IsUint(6, imm)); | 318 ASSERT(Utils::IsUint(6, imm)); |
| 290 ASSERT((rm != R31) && (rm != CSP)); | 319 ASSERT((rm != R31) && (rm != CSP)); |
| 291 const Register crm = ConcreteRegister(rm); | 320 const Register crm = ConcreteRegister(rm); |
| 292 encoding_ = | 321 encoding_ = |
| 293 (imm << kImm6Shift) | | 322 (imm << kImm6Shift) | |
| 294 (static_cast<int32_t>(crm) << kRmShift) | | 323 (static_cast<int32_t>(crm) << kRmShift) | |
| 295 (static_cast<int32_t>(shift) << kShiftTypeShift); | 324 (static_cast<int32_t>(shift) << kShiftTypeShift); |
| 296 type_ = Shifted; | 325 type_ = Shifted; |
| 297 } | 326 } |
| 298 | 327 |
| 328 // This operand type does not exist. |
| 329 Operand(Register rm, Shift shift, Register r); |
| 330 |
| 299 Operand(Register rm, Extend extend, int32_t imm) { | 331 Operand(Register rm, Extend extend, int32_t imm) { |
| 300 ASSERT(Utils::IsUint(3, imm)); | 332 ASSERT(Utils::IsUint(3, imm)); |
| 301 ASSERT((rm != R31) && (rm != CSP)); | 333 ASSERT((rm != R31) && (rm != CSP)); |
| 302 const Register crm = ConcreteRegister(rm); | 334 const Register crm = ConcreteRegister(rm); |
| 303 encoding_ = | 335 encoding_ = |
| 304 B21 | | 336 B21 | |
| 305 (static_cast<int32_t>(crm) << kRmShift) | | 337 (static_cast<int32_t>(crm) << kRmShift) | |
| 306 (static_cast<int32_t>(extend) << kExtendTypeShift) | | 338 (static_cast<int32_t>(extend) << kExtendTypeShift) | |
| 307 ((imm & 0x7) << kImm3Shift); | 339 ((imm & 0x7) << kImm3Shift); |
| 308 type_ = Extended; | 340 type_ = Extended; |
| 309 } | 341 } |
| 310 | 342 |
| 343 // This operand type does not exist. |
| 344 Operand(Register rm, Extend extend, Register r); |
| 345 |
| 311 explicit Operand(int32_t imm) { | 346 explicit Operand(int32_t imm) { |
| 312 if (Utils::IsUint(12, imm)) { | 347 if (Utils::IsUint(12, imm)) { |
| 313 encoding_ = imm << kImm12Shift; | 348 encoding_ = imm << kImm12Shift; |
| 314 } else { | 349 } else { |
| 315 // imm only has bits in [12, 24) set. | 350 // imm only has bits in [12, 24) set. |
| 316 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); | 351 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); |
| 317 encoding_ = B22 | ((imm >> 12) << kImm12Shift); | 352 encoding_ = B22 | ((imm >> 12) << kImm12Shift); |
| 318 } | 353 } |
| 319 type_ = Immediate; | 354 type_ = Immediate; |
| 320 } | 355 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 static const char* FpuRegisterName(FpuRegister reg); | 476 static const char* FpuRegisterName(FpuRegister reg); |
| 442 | 477 |
| 443 void SetPrologueOffset() { | 478 void SetPrologueOffset() { |
| 444 if (prologue_offset_ == -1) { | 479 if (prologue_offset_ == -1) { |
| 445 prologue_offset_ = CodeSize(); | 480 prologue_offset_ = CodeSize(); |
| 446 } | 481 } |
| 447 } | 482 } |
| 448 | 483 |
| 449 void ReserveAlignedFrameSpace(intptr_t frame_space); | 484 void ReserveAlignedFrameSpace(intptr_t frame_space); |
| 450 | 485 |
| 451 // TODO(zra): Make sure this is right. | |
| 452 // Instruction pattern from entrypoint is used in Dart frame prologs | 486 // Instruction pattern from entrypoint is used in Dart frame prologs |
| 453 // to set up the frame and save a PC which can be used to figure out the | 487 // to set up the frame and save a PC which can be used to figure out the |
| 454 // RawInstruction object corresponding to the code running in the frame. | 488 // RawInstruction object corresponding to the code running in the frame. |
| 455 static const intptr_t kEntryPointToPcMarkerOffset = 0; | 489 static const intptr_t kEntryPointToPcMarkerOffset = 0; |
| 456 static intptr_t EntryPointToPcMarkerOffset() { | 490 static intptr_t EntryPointToPcMarkerOffset() { |
| 457 return kEntryPointToPcMarkerOffset; | 491 return kEntryPointToPcMarkerOffset; |
| 458 } | 492 } |
| 459 | 493 |
| 460 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 494 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
| 461 void Emit(int32_t value); | 495 void Emit(int32_t value); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 478 AddSubHelper(kWord, false, false, rd, rn, o); | 512 AddSubHelper(kWord, false, false, rd, rn, o); |
| 479 } | 513 } |
| 480 void sub(Register rd, Register rn, Operand o) { | 514 void sub(Register rd, Register rn, Operand o) { |
| 481 AddSubHelper(kDoubleWord, false, true, rd, rn, o); | 515 AddSubHelper(kDoubleWord, false, true, rd, rn, o); |
| 482 } | 516 } |
| 483 void subs(Register rd, Register rn, Operand o) { | 517 void subs(Register rd, Register rn, Operand o) { |
| 484 AddSubHelper(kDoubleWord, true, true, rd, rn, o); | 518 AddSubHelper(kDoubleWord, true, true, rd, rn, o); |
| 485 } | 519 } |
| 486 | 520 |
| 487 // PC relative immediate add. imm is in bytes. | 521 // PC relative immediate add. imm is in bytes. |
| 488 void adr(Register rd, int64_t imm) { | 522 void adr(Register rd, const Immediate& imm) { |
| 489 EmitPCRelOp(ADR, rd, imm); | 523 EmitPCRelOp(ADR, rd, imm); |
| 490 } | 524 } |
| 491 | 525 |
| 492 // Logical immediate operations. | 526 // Logical immediate operations. |
| 493 void andi(Register rd, Register rn, uint64_t imm) { | 527 void andi(Register rd, Register rn, const Immediate& imm) { |
| 494 Operand imm_op; | 528 Operand imm_op; |
| 495 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 529 const bool immok = |
| 530 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 496 ASSERT(immok); | 531 ASSERT(immok); |
| 497 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); | 532 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); |
| 498 } | 533 } |
| 499 void orri(Register rd, Register rn, uint64_t imm) { | 534 void orri(Register rd, Register rn, const Immediate& imm) { |
| 500 Operand imm_op; | 535 Operand imm_op; |
| 501 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 536 const bool immok = |
| 537 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 502 ASSERT(immok); | 538 ASSERT(immok); |
| 503 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord); | 539 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord); |
| 504 } | 540 } |
| 505 void eori(Register rd, Register rn, uint64_t imm) { | 541 void eori(Register rd, Register rn, const Immediate& imm) { |
| 506 Operand imm_op; | 542 Operand imm_op; |
| 507 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 543 const bool immok = |
| 544 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 508 ASSERT(immok); | 545 ASSERT(immok); |
| 509 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord); | 546 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord); |
| 510 } | 547 } |
| 511 void andis(Register rd, Register rn, uint64_t imm) { | 548 void andis(Register rd, Register rn, const Immediate& imm) { |
| 512 Operand imm_op; | 549 Operand imm_op; |
| 513 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 550 const bool immok = |
| 551 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 514 ASSERT(immok); | 552 ASSERT(immok); |
| 515 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord); | 553 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord); |
| 516 } | 554 } |
| 517 | 555 |
| 518 // Logical (shifted) register operations. | 556 // Logical (shifted) register operations. |
| 519 void and_(Register rd, Register rn, Operand o) { | 557 void and_(Register rd, Register rn, Operand o) { |
| 520 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); | 558 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); |
| 521 } | 559 } |
| 522 void andw_(Register rd, Register rn, Operand o) { | 560 void andw_(Register rd, Register rn, Operand o) { |
| 523 EmitLogicalShiftOp(AND, rd, rn, o, kWord); | 561 EmitLogicalShiftOp(AND, rd, rn, o, kWord); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); | 605 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); |
| 568 } | 606 } |
| 569 void msub(Register rd, Register rn, Register rm, Register ra) { | 607 void msub(Register rd, Register rn, Register rm, Register ra) { |
| 570 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); | 608 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); |
| 571 } | 609 } |
| 572 void smulh(Register rd, Register rn, Register rm) { | 610 void smulh(Register rd, Register rn, Register rm) { |
| 573 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); | 611 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); |
| 574 } | 612 } |
| 575 | 613 |
| 576 // Move wide immediate. | 614 // Move wide immediate. |
| 577 void movk(Register rd, uint16_t imm, int hw_idx) { | 615 void movk(Register rd, const Immediate& imm, int hw_idx) { |
| 578 ASSERT(rd != CSP); | 616 ASSERT(rd != CSP); |
| 579 const Register crd = ConcreteRegister(rd); | 617 const Register crd = ConcreteRegister(rd); |
| 580 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); | 618 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 581 } | 619 } |
| 582 void movn(Register rd, uint16_t imm, int hw_idx) { | 620 void movn(Register rd, const Immediate& imm, int hw_idx) { |
| 583 ASSERT(rd != CSP); | 621 ASSERT(rd != CSP); |
| 584 const Register crd = ConcreteRegister(rd); | 622 const Register crd = ConcreteRegister(rd); |
| 585 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); | 623 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); |
| 586 } | 624 } |
| 587 void movz(Register rd, uint16_t imm, int hw_idx) { | 625 void movz(Register rd, const Immediate& imm, int hw_idx) { |
| 588 ASSERT(rd != CSP); | 626 ASSERT(rd != CSP); |
| 589 const Register crd = ConcreteRegister(rd); | 627 const Register crd = ConcreteRegister(rd); |
| 590 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); | 628 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| 591 } | 629 } |
| 592 | 630 |
| 593 // Loads and Stores. | 631 // Loads and Stores. |
| 594 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { | 632 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { |
| 595 if (a.type() == Address::PCOffset) { | 633 if (a.type() == Address::PCOffset) { |
| 596 ASSERT(sz == kDoubleWord); | 634 ASSERT(sz == kDoubleWord); |
| 597 EmitLoadRegLiteral(LDRpc, rt, a, sz); | 635 EmitLoadRegLiteral(LDRpc, rt, a, sz); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 add(TMP, PP, Operand(kHeapObjectTag)); | 1029 add(TMP, PP, Operand(kHeapObjectTag)); |
| 992 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); | 1030 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
| 993 } | 1031 } |
| 994 void PopAndUntagPP() { | 1032 void PopAndUntagPP() { |
| 995 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); | 1033 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
| 996 sub(PP, PP, Operand(kHeapObjectTag)); | 1034 sub(PP, PP, Operand(kHeapObjectTag)); |
| 997 } | 1035 } |
| 998 void tst(Register rn, Operand o) { | 1036 void tst(Register rn, Operand o) { |
| 999 ands(ZR, rn, o); | 1037 ands(ZR, rn, o); |
| 1000 } | 1038 } |
| 1001 void tsti(Register rn, uint64_t imm) { | 1039 void tsti(Register rn, const Immediate& imm) { |
| 1002 andis(ZR, rn, imm); | 1040 andis(ZR, rn, imm); |
| 1003 } | 1041 } |
| 1004 | 1042 |
| 1005 void LslImmediate(Register rd, Register rn, int shift) { | 1043 void LslImmediate(Register rd, Register rn, int shift) { |
| 1006 add(rd, ZR, Operand(rn, LSL, shift)); | 1044 add(rd, ZR, Operand(rn, LSL, shift)); |
| 1007 } | 1045 } |
| 1008 void LsrImmediate(Register rd, Register rn, int shift) { | 1046 void LsrImmediate(Register rd, Register rn, int shift) { |
| 1009 add(rd, ZR, Operand(rn, LSR, shift)); | 1047 add(rd, ZR, Operand(rn, LSR, shift)); |
| 1010 } | 1048 } |
| 1011 void AsrImmediate(Register rd, Register rn, int shift) { | 1049 void AsrImmediate(Register rd, Register rn, int shift) { |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 op | (static_cast<int32_t>(crn) << kRnShift); | 1557 op | (static_cast<int32_t>(crn) << kRnShift); |
| 1520 Emit(encoding); | 1558 Emit(encoding); |
| 1521 } | 1559 } |
| 1522 | 1560 |
| 1523 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { | 1561 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { |
| 1524 const int32_t encoding = | 1562 const int32_t encoding = |
| 1525 op | (static_cast<int32_t>(imm) << kImm16Shift); | 1563 op | (static_cast<int32_t>(imm) << kImm16Shift); |
| 1526 Emit(encoding); | 1564 Emit(encoding); |
| 1527 } | 1565 } |
| 1528 | 1566 |
| 1529 void EmitMoveWideOp(MoveWideOp op, Register rd, uint16_t imm, int hw_idx, | 1567 void EmitMoveWideOp(MoveWideOp op, Register rd, const Immediate& imm, |
| 1530 OperandSize sz) { | 1568 int hw_idx, OperandSize sz) { |
| 1531 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); | 1569 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); |
| 1532 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1570 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1533 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1571 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1534 const int32_t encoding = | 1572 const int32_t encoding = |
| 1535 op | size | | 1573 op | size | |
| 1536 (static_cast<int32_t>(rd) << kRdShift) | | 1574 (static_cast<int32_t>(rd) << kRdShift) | |
| 1537 (static_cast<int32_t>(hw_idx) << kHWShift) | | 1575 (static_cast<int32_t>(hw_idx) << kHWShift) | |
| 1538 (static_cast<int32_t>(imm) << kImm16Shift); | 1576 (static_cast<int32_t>(imm.value() & 0xffff) << kImm16Shift); |
| 1539 Emit(encoding); | 1577 Emit(encoding); |
| 1540 } | 1578 } |
| 1541 | 1579 |
| 1542 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, | 1580 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, |
| 1543 OperandSize sz) { | 1581 OperandSize sz) { |
| 1544 const Register crt = ConcreteRegister(rt); | 1582 const Register crt = ConcreteRegister(rt); |
| 1545 const int32_t size = Log2OperandSizeBytes(sz); | 1583 const int32_t size = Log2OperandSizeBytes(sz); |
| 1546 const int32_t encoding = | 1584 const int32_t encoding = |
| 1547 op | ((size & 0x3) << kSzShift) | | 1585 op | ((size & 0x3) << kSzShift) | |
| 1548 (static_cast<int32_t>(crt) << kRtShift) | | 1586 (static_cast<int32_t>(crt) << kRtShift) | |
| 1549 a.encoding(); | 1587 a.encoding(); |
| 1550 Emit(encoding); | 1588 Emit(encoding); |
| 1551 } | 1589 } |
| 1552 | 1590 |
| 1553 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, | 1591 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, |
| 1554 OperandSize sz) { | 1592 OperandSize sz) { |
| 1555 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1593 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1556 ASSERT((rt != CSP) && (rt != R31)); | 1594 ASSERT((rt != CSP) && (rt != R31)); |
| 1557 const Register crt = ConcreteRegister(rt); | 1595 const Register crt = ConcreteRegister(rt); |
| 1558 const int32_t size = (sz == kDoubleWord) ? B30 : 0; | 1596 const int32_t size = (sz == kDoubleWord) ? B30 : 0; |
| 1559 const int32_t encoding = | 1597 const int32_t encoding = |
| 1560 op | size | | 1598 op | size | |
| 1561 (static_cast<int32_t>(crt) << kRtShift) | | 1599 (static_cast<int32_t>(crt) << kRtShift) | |
| 1562 a.encoding(); | 1600 a.encoding(); |
| 1563 Emit(encoding); | 1601 Emit(encoding); |
| 1564 } | 1602 } |
| 1565 | 1603 |
| 1566 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { | 1604 void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) { |
| 1567 ASSERT(Utils::IsInt(21, imm)); | 1605 ASSERT(Utils::IsInt(21, imm.value())); |
| 1568 ASSERT((rd != R31) && (rd != CSP)); | 1606 ASSERT((rd != R31) && (rd != CSP)); |
| 1569 const Register crd = ConcreteRegister(rd); | 1607 const Register crd = ConcreteRegister(rd); |
| 1570 const int32_t loimm = (imm & 0x3) << 29; | 1608 const int32_t loimm = (imm.value() & 0x3) << 29; |
| 1571 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; | 1609 const int32_t hiimm = ((imm.value() >> 2) << kImm19Shift) & kImm19Mask; |
| 1572 const int32_t encoding = | 1610 const int32_t encoding = |
| 1573 op | loimm | hiimm | | 1611 op | loimm | hiimm | |
| 1574 (static_cast<int32_t>(crd) << kRdShift); | 1612 (static_cast<int32_t>(crd) << kRdShift); |
| 1575 Emit(encoding); | 1613 Emit(encoding); |
| 1576 } | 1614 } |
| 1577 | 1615 |
| 1578 void EmitMiscDP2Source(MiscDP2SourceOp op, | 1616 void EmitMiscDP2Source(MiscDP2SourceOp op, |
| 1579 Register rd, Register rn, Register rm, | 1617 Register rd, Register rn, Register rm, |
| 1580 OperandSize sz) { | 1618 OperandSize sz) { |
| 1581 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); | 1619 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 Register value, | 1748 Register value, |
| 1711 Label* no_update); | 1749 Label* no_update); |
| 1712 | 1750 |
| 1713 DISALLOW_ALLOCATION(); | 1751 DISALLOW_ALLOCATION(); |
| 1714 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1752 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1715 }; | 1753 }; |
| 1716 | 1754 |
| 1717 } // namespace dart | 1755 } // namespace dart |
| 1718 | 1756 |
| 1719 #endif // VM_ASSEMBLER_ARM64_H_ | 1757 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |