| 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 : Address(base) { |
| 278 UNREACHABLE(); |
| 279 } |
| 280 |
| 249 FieldAddress(const FieldAddress& other) : Address(other) { } | 281 FieldAddress(const FieldAddress& other) : Address(other) { } |
| 250 | 282 |
| 251 FieldAddress& operator=(const FieldAddress& other) { | 283 FieldAddress& operator=(const FieldAddress& other) { |
| 252 Address::operator=(other); | 284 Address::operator=(other); |
| 253 return *this; | 285 return *this; |
| 254 } | 286 } |
| 255 }; | 287 }; |
| 256 | 288 |
| 257 | 289 |
| 258 class Operand : public ValueObject { | 290 class Operand : public ValueObject { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 289 ASSERT(Utils::IsUint(6, imm)); | 321 ASSERT(Utils::IsUint(6, imm)); |
| 290 ASSERT((rm != R31) && (rm != CSP)); | 322 ASSERT((rm != R31) && (rm != CSP)); |
| 291 const Register crm = ConcreteRegister(rm); | 323 const Register crm = ConcreteRegister(rm); |
| 292 encoding_ = | 324 encoding_ = |
| 293 (imm << kImm6Shift) | | 325 (imm << kImm6Shift) | |
| 294 (static_cast<int32_t>(crm) << kRmShift) | | 326 (static_cast<int32_t>(crm) << kRmShift) | |
| 295 (static_cast<int32_t>(shift) << kShiftTypeShift); | 327 (static_cast<int32_t>(shift) << kShiftTypeShift); |
| 296 type_ = Shifted; | 328 type_ = Shifted; |
| 297 } | 329 } |
| 298 | 330 |
| 331 // This operand type does not exist. |
| 332 Operand(Register rm, Shift shift, Register r); |
| 333 |
| 299 Operand(Register rm, Extend extend, int32_t imm) { | 334 Operand(Register rm, Extend extend, int32_t imm) { |
| 300 ASSERT(Utils::IsUint(3, imm)); | 335 ASSERT(Utils::IsUint(3, imm)); |
| 301 ASSERT((rm != R31) && (rm != CSP)); | 336 ASSERT((rm != R31) && (rm != CSP)); |
| 302 const Register crm = ConcreteRegister(rm); | 337 const Register crm = ConcreteRegister(rm); |
| 303 encoding_ = | 338 encoding_ = |
| 304 B21 | | 339 B21 | |
| 305 (static_cast<int32_t>(crm) << kRmShift) | | 340 (static_cast<int32_t>(crm) << kRmShift) | |
| 306 (static_cast<int32_t>(extend) << kExtendTypeShift) | | 341 (static_cast<int32_t>(extend) << kExtendTypeShift) | |
| 307 ((imm & 0x7) << kImm3Shift); | 342 ((imm & 0x7) << kImm3Shift); |
| 308 type_ = Extended; | 343 type_ = Extended; |
| 309 } | 344 } |
| 310 | 345 |
| 346 // This operand type does not exist. |
| 347 Operand(Register rm, Extend extend, Register r); |
| 348 |
| 311 explicit Operand(int32_t imm) { | 349 explicit Operand(int32_t imm) { |
| 312 if (Utils::IsUint(12, imm)) { | 350 if (Utils::IsUint(12, imm)) { |
| 313 encoding_ = imm << kImm12Shift; | 351 encoding_ = imm << kImm12Shift; |
| 314 } else { | 352 } else { |
| 315 // imm only has bits in [12, 24) set. | 353 // imm only has bits in [12, 24) set. |
| 316 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); | 354 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); |
| 317 encoding_ = B22 | ((imm >> 12) << kImm12Shift); | 355 encoding_ = B22 | ((imm >> 12) << kImm12Shift); |
| 318 } | 356 } |
| 319 type_ = Immediate; | 357 type_ = Immediate; |
| 320 } | 358 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 static const char* FpuRegisterName(FpuRegister reg); | 479 static const char* FpuRegisterName(FpuRegister reg); |
| 442 | 480 |
| 443 void SetPrologueOffset() { | 481 void SetPrologueOffset() { |
| 444 if (prologue_offset_ == -1) { | 482 if (prologue_offset_ == -1) { |
| 445 prologue_offset_ = CodeSize(); | 483 prologue_offset_ = CodeSize(); |
| 446 } | 484 } |
| 447 } | 485 } |
| 448 | 486 |
| 449 void ReserveAlignedFrameSpace(intptr_t frame_space); | 487 void ReserveAlignedFrameSpace(intptr_t frame_space); |
| 450 | 488 |
| 451 // TODO(zra): Make sure this is right. | |
| 452 // Instruction pattern from entrypoint is used in Dart frame prologs | 489 // 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 | 490 // 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. | 491 // RawInstruction object corresponding to the code running in the frame. |
| 455 static const intptr_t kEntryPointToPcMarkerOffset = 0; | 492 static const intptr_t kEntryPointToPcMarkerOffset = 0; |
| 456 static intptr_t EntryPointToPcMarkerOffset() { | 493 static intptr_t EntryPointToPcMarkerOffset() { |
| 457 return kEntryPointToPcMarkerOffset; | 494 return kEntryPointToPcMarkerOffset; |
| 458 } | 495 } |
| 459 | 496 |
| 460 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 497 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
| 461 void Emit(int32_t value); | 498 void Emit(int32_t value); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 478 AddSubHelper(kWord, false, false, rd, rn, o); | 515 AddSubHelper(kWord, false, false, rd, rn, o); |
| 479 } | 516 } |
| 480 void sub(Register rd, Register rn, Operand o) { | 517 void sub(Register rd, Register rn, Operand o) { |
| 481 AddSubHelper(kDoubleWord, false, true, rd, rn, o); | 518 AddSubHelper(kDoubleWord, false, true, rd, rn, o); |
| 482 } | 519 } |
| 483 void subs(Register rd, Register rn, Operand o) { | 520 void subs(Register rd, Register rn, Operand o) { |
| 484 AddSubHelper(kDoubleWord, true, true, rd, rn, o); | 521 AddSubHelper(kDoubleWord, true, true, rd, rn, o); |
| 485 } | 522 } |
| 486 | 523 |
| 487 // PC relative immediate add. imm is in bytes. | 524 // PC relative immediate add. imm is in bytes. |
| 488 void adr(Register rd, int64_t imm) { | 525 void adr(Register rd, const Immediate& imm) { |
| 489 EmitPCRelOp(ADR, rd, imm); | 526 EmitPCRelOp(ADR, rd, imm); |
| 490 } | 527 } |
| 491 | 528 |
| 492 // Logical immediate operations. | 529 // Logical immediate operations. |
| 493 void andi(Register rd, Register rn, uint64_t imm) { | 530 void andi(Register rd, Register rn, const Immediate& imm) { |
| 494 Operand imm_op; | 531 Operand imm_op; |
| 495 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 532 const bool immok = |
| 533 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 496 ASSERT(immok); | 534 ASSERT(immok); |
| 497 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); | 535 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); |
| 498 } | 536 } |
| 499 void orri(Register rd, Register rn, uint64_t imm) { | 537 void orri(Register rd, Register rn, const Immediate& imm) { |
| 500 Operand imm_op; | 538 Operand imm_op; |
| 501 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 539 const bool immok = |
| 540 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 502 ASSERT(immok); | 541 ASSERT(immok); |
| 503 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord); | 542 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord); |
| 504 } | 543 } |
| 505 void eori(Register rd, Register rn, uint64_t imm) { | 544 void eori(Register rd, Register rn, const Immediate& imm) { |
| 506 Operand imm_op; | 545 Operand imm_op; |
| 507 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 546 const bool immok = |
| 547 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 508 ASSERT(immok); | 548 ASSERT(immok); |
| 509 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord); | 549 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord); |
| 510 } | 550 } |
| 511 void andis(Register rd, Register rn, uint64_t imm) { | 551 void andis(Register rd, Register rn, const Immediate& imm) { |
| 512 Operand imm_op; | 552 Operand imm_op; |
| 513 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 553 const bool immok = |
| 554 Operand::IsImmLogical(imm.value(), kXRegSizeInBits, &imm_op); |
| 514 ASSERT(immok); | 555 ASSERT(immok); |
| 515 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord); | 556 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord); |
| 516 } | 557 } |
| 517 | 558 |
| 518 // Logical (shifted) register operations. | 559 // Logical (shifted) register operations. |
| 519 void and_(Register rd, Register rn, Operand o) { | 560 void and_(Register rd, Register rn, Operand o) { |
| 520 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); | 561 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); |
| 521 } | 562 } |
| 522 void andw_(Register rd, Register rn, Operand o) { | 563 void andw_(Register rd, Register rn, Operand o) { |
| 523 EmitLogicalShiftOp(AND, rd, rn, o, kWord); | 564 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); | 608 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); |
| 568 } | 609 } |
| 569 void msub(Register rd, Register rn, Register rm, Register ra) { | 610 void msub(Register rd, Register rn, Register rm, Register ra) { |
| 570 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); | 611 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); |
| 571 } | 612 } |
| 572 void smulh(Register rd, Register rn, Register rm) { | 613 void smulh(Register rd, Register rn, Register rm) { |
| 573 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); | 614 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); |
| 574 } | 615 } |
| 575 | 616 |
| 576 // Move wide immediate. | 617 // Move wide immediate. |
| 577 void movk(Register rd, uint16_t imm, int hw_idx) { | 618 void movk(Register rd, const Immediate& imm, int hw_idx) { |
| 578 ASSERT(rd != CSP); | 619 ASSERT(rd != CSP); |
| 579 const Register crd = ConcreteRegister(rd); | 620 const Register crd = ConcreteRegister(rd); |
| 580 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); | 621 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 581 } | 622 } |
| 582 void movn(Register rd, uint16_t imm, int hw_idx) { | 623 void movn(Register rd, const Immediate& imm, int hw_idx) { |
| 583 ASSERT(rd != CSP); | 624 ASSERT(rd != CSP); |
| 584 const Register crd = ConcreteRegister(rd); | 625 const Register crd = ConcreteRegister(rd); |
| 585 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); | 626 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); |
| 586 } | 627 } |
| 587 void movz(Register rd, uint16_t imm, int hw_idx) { | 628 void movz(Register rd, const Immediate& imm, int hw_idx) { |
| 588 ASSERT(rd != CSP); | 629 ASSERT(rd != CSP); |
| 589 const Register crd = ConcreteRegister(rd); | 630 const Register crd = ConcreteRegister(rd); |
| 590 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); | 631 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| 591 } | 632 } |
| 592 | 633 |
| 593 // Loads and Stores. | 634 // Loads and Stores. |
| 594 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { | 635 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { |
| 595 if (a.type() == Address::PCOffset) { | 636 if (a.type() == Address::PCOffset) { |
| 596 ASSERT(sz == kDoubleWord); | 637 ASSERT(sz == kDoubleWord); |
| 597 EmitLoadRegLiteral(LDRpc, rt, a, sz); | 638 EmitLoadRegLiteral(LDRpc, rt, a, sz); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 add(TMP, PP, Operand(kHeapObjectTag)); | 1032 add(TMP, PP, Operand(kHeapObjectTag)); |
| 992 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); | 1033 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
| 993 } | 1034 } |
| 994 void PopAndUntagPP() { | 1035 void PopAndUntagPP() { |
| 995 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); | 1036 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
| 996 sub(PP, PP, Operand(kHeapObjectTag)); | 1037 sub(PP, PP, Operand(kHeapObjectTag)); |
| 997 } | 1038 } |
| 998 void tst(Register rn, Operand o) { | 1039 void tst(Register rn, Operand o) { |
| 999 ands(ZR, rn, o); | 1040 ands(ZR, rn, o); |
| 1000 } | 1041 } |
| 1001 void tsti(Register rn, uint64_t imm) { | 1042 void tsti(Register rn, const Immediate& imm) { |
| 1002 andis(ZR, rn, imm); | 1043 andis(ZR, rn, imm); |
| 1003 } | 1044 } |
| 1004 | 1045 |
| 1005 void LslImmediate(Register rd, Register rn, int shift) { | 1046 void LslImmediate(Register rd, Register rn, int shift) { |
| 1006 add(rd, ZR, Operand(rn, LSL, shift)); | 1047 add(rd, ZR, Operand(rn, LSL, shift)); |
| 1007 } | 1048 } |
| 1008 void LsrImmediate(Register rd, Register rn, int shift) { | 1049 void LsrImmediate(Register rd, Register rn, int shift) { |
| 1009 add(rd, ZR, Operand(rn, LSR, shift)); | 1050 add(rd, ZR, Operand(rn, LSR, shift)); |
| 1010 } | 1051 } |
| 1011 void AsrImmediate(Register rd, Register rn, int shift) { | 1052 void AsrImmediate(Register rd, Register rn, int shift) { |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 op | (static_cast<int32_t>(crn) << kRnShift); | 1554 op | (static_cast<int32_t>(crn) << kRnShift); |
| 1514 Emit(encoding); | 1555 Emit(encoding); |
| 1515 } | 1556 } |
| 1516 | 1557 |
| 1517 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { | 1558 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { |
| 1518 const int32_t encoding = | 1559 const int32_t encoding = |
| 1519 op | (static_cast<int32_t>(imm) << kImm16Shift); | 1560 op | (static_cast<int32_t>(imm) << kImm16Shift); |
| 1520 Emit(encoding); | 1561 Emit(encoding); |
| 1521 } | 1562 } |
| 1522 | 1563 |
| 1523 void EmitMoveWideOp(MoveWideOp op, Register rd, uint16_t imm, int hw_idx, | 1564 void EmitMoveWideOp(MoveWideOp op, Register rd, const Immediate& imm, |
| 1524 OperandSize sz) { | 1565 int hw_idx, OperandSize sz) { |
| 1525 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); | 1566 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); |
| 1526 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1567 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1527 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1568 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1528 const int32_t encoding = | 1569 const int32_t encoding = |
| 1529 op | size | | 1570 op | size | |
| 1530 (static_cast<int32_t>(rd) << kRdShift) | | 1571 (static_cast<int32_t>(rd) << kRdShift) | |
| 1531 (static_cast<int32_t>(hw_idx) << kHWShift) | | 1572 (static_cast<int32_t>(hw_idx) << kHWShift) | |
| 1532 (static_cast<int32_t>(imm) << kImm16Shift); | 1573 (static_cast<int32_t>(imm.value() & 0xffff) << kImm16Shift); |
| 1533 Emit(encoding); | 1574 Emit(encoding); |
| 1534 } | 1575 } |
| 1535 | 1576 |
| 1536 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, | 1577 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, |
| 1537 OperandSize sz) { | 1578 OperandSize sz) { |
| 1538 const Register crt = ConcreteRegister(rt); | 1579 const Register crt = ConcreteRegister(rt); |
| 1539 const int32_t size = Log2OperandSizeBytes(sz); | 1580 const int32_t size = Log2OperandSizeBytes(sz); |
| 1540 const int32_t encoding = | 1581 const int32_t encoding = |
| 1541 op | ((size & 0x3) << kSzShift) | | 1582 op | ((size & 0x3) << kSzShift) | |
| 1542 (static_cast<int32_t>(crt) << kRtShift) | | 1583 (static_cast<int32_t>(crt) << kRtShift) | |
| 1543 a.encoding(); | 1584 a.encoding(); |
| 1544 Emit(encoding); | 1585 Emit(encoding); |
| 1545 } | 1586 } |
| 1546 | 1587 |
| 1547 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, | 1588 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, |
| 1548 OperandSize sz) { | 1589 OperandSize sz) { |
| 1549 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1590 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1550 ASSERT((rt != CSP) && (rt != R31)); | 1591 ASSERT((rt != CSP) && (rt != R31)); |
| 1551 const Register crt = ConcreteRegister(rt); | 1592 const Register crt = ConcreteRegister(rt); |
| 1552 const int32_t size = (sz == kDoubleWord) ? B30 : 0; | 1593 const int32_t size = (sz == kDoubleWord) ? B30 : 0; |
| 1553 const int32_t encoding = | 1594 const int32_t encoding = |
| 1554 op | size | | 1595 op | size | |
| 1555 (static_cast<int32_t>(crt) << kRtShift) | | 1596 (static_cast<int32_t>(crt) << kRtShift) | |
| 1556 a.encoding(); | 1597 a.encoding(); |
| 1557 Emit(encoding); | 1598 Emit(encoding); |
| 1558 } | 1599 } |
| 1559 | 1600 |
| 1560 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { | 1601 void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) { |
| 1561 ASSERT(Utils::IsInt(21, imm)); | 1602 ASSERT(Utils::IsInt(21, imm.value())); |
| 1562 ASSERT((rd != R31) && (rd != CSP)); | 1603 ASSERT((rd != R31) && (rd != CSP)); |
| 1563 const Register crd = ConcreteRegister(rd); | 1604 const Register crd = ConcreteRegister(rd); |
| 1564 const int32_t loimm = (imm & 0x3) << 29; | 1605 const int32_t loimm = (imm.value() & 0x3) << 29; |
| 1565 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; | 1606 const int32_t hiimm = ((imm.value() >> 2) << kImm19Shift) & kImm19Mask; |
| 1566 const int32_t encoding = | 1607 const int32_t encoding = |
| 1567 op | loimm | hiimm | | 1608 op | loimm | hiimm | |
| 1568 (static_cast<int32_t>(crd) << kRdShift); | 1609 (static_cast<int32_t>(crd) << kRdShift); |
| 1569 Emit(encoding); | 1610 Emit(encoding); |
| 1570 } | 1611 } |
| 1571 | 1612 |
| 1572 void EmitMiscDP2Source(MiscDP2SourceOp op, | 1613 void EmitMiscDP2Source(MiscDP2SourceOp op, |
| 1573 Register rd, Register rn, Register rm, | 1614 Register rd, Register rn, Register rm, |
| 1574 OperandSize sz) { | 1615 OperandSize sz) { |
| 1575 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); | 1616 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 Register value, | 1745 Register value, |
| 1705 Label* no_update); | 1746 Label* no_update); |
| 1706 | 1747 |
| 1707 DISALLOW_ALLOCATION(); | 1748 DISALLOW_ALLOCATION(); |
| 1708 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1749 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1709 }; | 1750 }; |
| 1710 | 1751 |
| 1711 } // namespace dart | 1752 } // namespace dart |
| 1712 | 1753 |
| 1713 #endif // VM_ASSEMBLER_ARM64_H_ | 1754 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |