| 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 Unscaled, | 160 Unscaled, |
| 161 Scaled, | 161 Scaled, |
| 162 }; | 162 }; |
| 163 | 163 |
| 164 // Base register rn with offset rm. rm is sign-extended according to ext. | 164 // Base register rn with offset rm. rm is sign-extended according to ext. |
| 165 // If ext is UXTX, rm may be optionally scaled by the | 165 // If ext is UXTX, rm may be optionally scaled by the |
| 166 // Log2OperandSize (specified by the instruction). | 166 // Log2OperandSize (specified by the instruction). |
| 167 Address(Register rn, Register rm, | 167 Address(Register rn, Register rm, |
| 168 Extend ext = UXTX, Scaling scale = Unscaled) { | 168 Extend ext = UXTX, Scaling scale = Unscaled) { |
| 169 ASSERT((rn != R31) && (rn != ZR)); | 169 ASSERT((rn != R31) && (rn != ZR)); |
| 170 ASSERT((rm != R31) && (rm != SP)); | 170 ASSERT((rm != R31) && (rm != CSP)); |
| 171 // Can only scale when ext = UXTX. | 171 // Can only scale when ext = UXTX. |
| 172 ASSERT((scale != Scaled) || (ext == UXTX)); | 172 ASSERT((scale != Scaled) || (ext == UXTX)); |
| 173 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); | 173 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); |
| 174 const Register crn = ConcreteRegister(rn); | 174 const Register crn = ConcreteRegister(rn); |
| 175 const Register crm = ConcreteRegister(rm); | 175 const Register crm = ConcreteRegister(rm); |
| 176 const int32_t s = (scale == Scaled) ? B12 : 0; | 176 const int32_t s = (scale == Scaled) ? B12 : 0; |
| 177 encoding_ = | 177 encoding_ = |
| 178 B21 | B11 | s | | 178 B21 | B11 | s | |
| 179 (static_cast<int32_t>(crn) << kRnShift) | | 179 (static_cast<int32_t>(crn) << kRnShift) | |
| 180 (static_cast<int32_t>(crm) << kRmShift) | | 180 (static_cast<int32_t>(crm) << kRmShift) | |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 Operand(const Operand& other) | 274 Operand(const Operand& other) |
| 275 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } | 275 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } |
| 276 | 276 |
| 277 Operand& operator=(const Operand& other) { | 277 Operand& operator=(const Operand& other) { |
| 278 type_ = other.type_; | 278 type_ = other.type_; |
| 279 encoding_ = other.encoding_; | 279 encoding_ = other.encoding_; |
| 280 return *this; | 280 return *this; |
| 281 } | 281 } |
| 282 | 282 |
| 283 explicit Operand(Register rm) { | 283 explicit Operand(Register rm) { |
| 284 ASSERT((rm != R31) && (rm != SP)); | 284 ASSERT((rm != R31) && (rm != CSP)); |
| 285 const Register crm = ConcreteRegister(rm); | 285 const Register crm = ConcreteRegister(rm); |
| 286 encoding_ = (static_cast<int32_t>(crm) << kRmShift); | 286 encoding_ = (static_cast<int32_t>(crm) << kRmShift); |
| 287 type_ = Shifted; | 287 type_ = Shifted; |
| 288 } | 288 } |
| 289 | 289 |
| 290 Operand(Register rm, Shift shift, int32_t imm) { | 290 Operand(Register rm, Shift shift, int32_t imm) { |
| 291 ASSERT(Utils::IsUint(6, imm)); | 291 ASSERT(Utils::IsUint(6, imm)); |
| 292 ASSERT((rm != R31) && (rm != SP)); | 292 ASSERT((rm != R31) && (rm != CSP)); |
| 293 const Register crm = ConcreteRegister(rm); | 293 const Register crm = ConcreteRegister(rm); |
| 294 encoding_ = | 294 encoding_ = |
| 295 (imm << kImm6Shift) | | 295 (imm << kImm6Shift) | |
| 296 (static_cast<int32_t>(crm) << kRmShift) | | 296 (static_cast<int32_t>(crm) << kRmShift) | |
| 297 (static_cast<int32_t>(shift) << kShiftTypeShift); | 297 (static_cast<int32_t>(shift) << kShiftTypeShift); |
| 298 type_ = Shifted; | 298 type_ = Shifted; |
| 299 } | 299 } |
| 300 | 300 |
| 301 Operand(Register rm, Extend extend, int32_t imm) { | 301 Operand(Register rm, Extend extend, int32_t imm) { |
| 302 ASSERT(Utils::IsUint(3, imm)); | 302 ASSERT(Utils::IsUint(3, imm)); |
| 303 ASSERT((rm != R31) && (rm != SP)); | 303 ASSERT((rm != R31) && (rm != CSP)); |
| 304 const Register crm = ConcreteRegister(rm); | 304 const Register crm = ConcreteRegister(rm); |
| 305 encoding_ = | 305 encoding_ = |
| 306 B21 | | 306 B21 | |
| 307 (static_cast<int32_t>(crm) << kRmShift) | | 307 (static_cast<int32_t>(crm) << kRmShift) | |
| 308 (static_cast<int32_t>(extend) << kExtendTypeShift) | | 308 (static_cast<int32_t>(extend) << kExtendTypeShift) | |
| 309 ((imm & 0x7) << kImm3Shift); | 309 ((imm & 0x7) << kImm3Shift); |
| 310 type_ = Extended; | 310 type_ = Extended; |
| 311 } | 311 } |
| 312 | 312 |
| 313 explicit Operand(int32_t imm) { | 313 explicit Operand(int32_t imm) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 | 456 |
| 457 // Emit data (e.g encoded instruction or immediate) in instruction stream. | 457 // Emit data (e.g encoded instruction or immediate) in instruction stream. |
| 458 void Emit(int32_t value); | 458 void Emit(int32_t value); |
| 459 | 459 |
| 460 // On some other platforms, we draw a distinction between safe and unsafe | 460 // On some other platforms, we draw a distinction between safe and unsafe |
| 461 // smis. | 461 // smis. |
| 462 static bool IsSafe(const Object& object) { return true; } | 462 static bool IsSafe(const Object& object) { return true; } |
| 463 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } | 463 static bool IsSafeSmi(const Object& object) { return object.IsSmi(); } |
| 464 | 464 |
| 465 // Addition and subtraction. | 465 // Addition and subtraction. |
| 466 // For add and sub, to use SP for rn, o must be of type Operand::Extend. | 466 // For add and sub, to use CSP for rn, o must be of type Operand::Extend. |
| 467 // For an unmodified rm in this case, use Operand(rm, UXTX, 0); | 467 // For an unmodified rm in this case, use Operand(rm, UXTX, 0); |
| 468 void add(Register rd, Register rn, Operand o) { | 468 void add(Register rd, Register rn, Operand o) { |
| 469 AddSubHelper(kDoubleWord, false, false, rd, rn, o); | 469 AddSubHelper(kDoubleWord, false, false, rd, rn, o); |
| 470 } | 470 } |
| 471 void adds(Register rd, Register rn, Operand o) { | 471 void adds(Register rd, Register rn, Operand o) { |
| 472 AddSubHelper(kDoubleWord, true, false, rd, rn, o); | 472 AddSubHelper(kDoubleWord, true, false, rd, rn, o); |
| 473 } | 473 } |
| 474 void addw(Register rd, Register rn, Operand o) { | 474 void addw(Register rd, Register rn, Operand o) { |
| 475 AddSubHelper(kWord, false, false, rd, rn, o); | 475 AddSubHelper(kWord, false, false, rd, rn, o); |
| 476 } | 476 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 } | 565 } |
| 566 void msub(Register rd, Register rn, Register rm, Register ra) { | 566 void msub(Register rd, Register rn, Register rm, Register ra) { |
| 567 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); | 567 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); |
| 568 } | 568 } |
| 569 void smulh(Register rd, Register rn, Register rm) { | 569 void smulh(Register rd, Register rn, Register rm) { |
| 570 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); | 570 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); |
| 571 } | 571 } |
| 572 | 572 |
| 573 // Move wide immediate. | 573 // Move wide immediate. |
| 574 void movk(Register rd, uint16_t imm, int hw_idx) { | 574 void movk(Register rd, uint16_t imm, int hw_idx) { |
| 575 ASSERT(rd != SP); | 575 ASSERT(rd != CSP); |
| 576 const Register crd = ConcreteRegister(rd); | 576 const Register crd = ConcreteRegister(rd); |
| 577 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); | 577 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 578 } | 578 } |
| 579 void movn(Register rd, uint16_t imm, int hw_idx) { | 579 void movn(Register rd, uint16_t imm, int hw_idx) { |
| 580 ASSERT(rd != SP); | 580 ASSERT(rd != CSP); |
| 581 const Register crd = ConcreteRegister(rd); | 581 const Register crd = ConcreteRegister(rd); |
| 582 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); | 582 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); |
| 583 } | 583 } |
| 584 void movz(Register rd, uint16_t imm, int hw_idx) { | 584 void movz(Register rd, uint16_t imm, int hw_idx) { |
| 585 ASSERT(rd != SP); | 585 ASSERT(rd != CSP); |
| 586 const Register crd = ConcreteRegister(rd); | 586 const Register crd = ConcreteRegister(rd); |
| 587 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); | 587 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| 588 } | 588 } |
| 589 | 589 |
| 590 // Loads and Stores. | 590 // Loads and Stores. |
| 591 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { | 591 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { |
| 592 if (a.type() == Address::PCOffset) { | 592 if (a.type() == Address::PCOffset) { |
| 593 ASSERT(sz == kDoubleWord); | 593 ASSERT(sz == kDoubleWord); |
| 594 EmitLoadRegLiteral(LDRpc, rt, a, sz); | 594 EmitLoadRegLiteral(LDRpc, rt, a, sz); |
| 595 } else { | 595 } else { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 } | 628 } |
| 629 void cinv(Register rd, Register rn, Condition cond) { | 629 void cinv(Register rd, Register rn, Condition cond) { |
| 630 csinv(rd, rn, rn, InvertCondition(cond)); | 630 csinv(rd, rn, rn, InvertCondition(cond)); |
| 631 } | 631 } |
| 632 void csetm(Register rd, Condition cond) { | 632 void csetm(Register rd, Condition cond) { |
| 633 csinv(rd, ZR, ZR, InvertCondition(cond)); | 633 csinv(rd, ZR, ZR, InvertCondition(cond)); |
| 634 } | 634 } |
| 635 | 635 |
| 636 // Comparison. | 636 // Comparison. |
| 637 // rn cmp o. | 637 // rn cmp o. |
| 638 // For add and sub, to use SP for rn, o must be of type Operand::Extend. | 638 // For add and sub, to use CSP for rn, o must be of type Operand::Extend. |
| 639 // For an unmodified rm in this case, use Operand(rm, UXTX, 0); | 639 // For an unmodified rm in this case, use Operand(rm, UXTX, 0); |
| 640 void cmp(Register rn, Operand o) { | 640 void cmp(Register rn, Operand o) { |
| 641 subs(ZR, rn, o); | 641 subs(ZR, rn, o); |
| 642 } | 642 } |
| 643 // rn cmp -o. | 643 // rn cmp -o. |
| 644 void cmn(Register rn, Operand o) { | 644 void cmn(Register rn, Operand o) { |
| 645 adds(ZR, rn, o); | 645 adds(ZR, rn, o); |
| 646 } | 646 } |
| 647 | 647 |
| 648 void CompareRegisters(Register rn, Register rm) { | 648 void CompareRegisters(Register rn, Register rm) { |
| 649 if (rn == SP) { | 649 if (rn == CSP) { |
| 650 // UXTX 0 on a 64-bit register (rm) is a nop, but forces R31 to be | 650 // UXTX 0 on a 64-bit register (rm) is a nop, but forces R31 to be |
| 651 // interpreted as SP. | 651 // interpreted as CSP. |
| 652 cmp(SP, Operand(rm, UXTX, 0)); | 652 cmp(CSP, Operand(rm, UXTX, 0)); |
| 653 } else { | 653 } else { |
| 654 cmp(rn, Operand(rm)); | 654 cmp(rn, Operand(rm)); |
| 655 } | 655 } |
| 656 } | 656 } |
| 657 | 657 |
| 658 // Conditional branch. | 658 // Conditional branch. |
| 659 void b(Label* label, Condition cond = AL) { | 659 void b(Label* label, Condition cond = AL) { |
| 660 EmitBranch(BCOND, cond, label); | 660 EmitBranch(BCOND, cond, label); |
| 661 } | 661 } |
| 662 | 662 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 const uint8_t imm8 = (bit7 << 7) | (bit6 << 6) | (bit54 << 4) | bit30; | 695 const uint8_t imm8 = (bit7 << 7) | (bit6 << 6) | (bit54 << 4) | bit30; |
| 696 const int64_t expimm8 = Instr::VFPExpandImm(imm8); | 696 const int64_t expimm8 = Instr::VFPExpandImm(imm8); |
| 697 if (imm64 != expimm8) { | 697 if (imm64 != expimm8) { |
| 698 return false; | 698 return false; |
| 699 } | 699 } |
| 700 EmitFPImm(FMOVDI, vd, imm8); | 700 EmitFPImm(FMOVDI, vd, imm8); |
| 701 return true; | 701 return true; |
| 702 } | 702 } |
| 703 void fmovdr(VRegister vd, Register rn) { | 703 void fmovdr(VRegister vd, Register rn) { |
| 704 ASSERT(rn != R31); | 704 ASSERT(rn != R31); |
| 705 ASSERT(rn != SP); | 705 ASSERT(rn != CSP); |
| 706 const Register crn = ConcreteRegister(rn); | 706 const Register crn = ConcreteRegister(rn); |
| 707 EmitFPIntCvtOp(FMOVDR, static_cast<Register>(vd), crn); | 707 EmitFPIntCvtOp(FMOVDR, static_cast<Register>(vd), crn); |
| 708 } | 708 } |
| 709 void fmovrd(Register rd, VRegister vn) { | 709 void fmovrd(Register rd, VRegister vn) { |
| 710 ASSERT(rd != R31); | 710 ASSERT(rd != R31); |
| 711 ASSERT(rd != SP); | 711 ASSERT(rd != CSP); |
| 712 const Register crd = ConcreteRegister(rd); | 712 const Register crd = ConcreteRegister(rd); |
| 713 EmitFPIntCvtOp(FMOVRD, crd, static_cast<Register>(vn)); | 713 EmitFPIntCvtOp(FMOVRD, crd, static_cast<Register>(vn)); |
| 714 } | 714 } |
| 715 void scvtfd(VRegister vd, Register rn) { | 715 void scvtfd(VRegister vd, Register rn) { |
| 716 ASSERT(rn != R31); | 716 ASSERT(rn != R31); |
| 717 ASSERT(rn != SP); | 717 ASSERT(rn != CSP); |
| 718 const Register crn = ConcreteRegister(rn); | 718 const Register crn = ConcreteRegister(rn); |
| 719 EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn); | 719 EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn); |
| 720 } | 720 } |
| 721 void fcvtzds(Register rd, VRegister vn) { | 721 void fcvtzds(Register rd, VRegister vn) { |
| 722 ASSERT(rd != R31); | 722 ASSERT(rd != R31); |
| 723 ASSERT(rd != SP); | 723 ASSERT(rd != CSP); |
| 724 const Register crd = ConcreteRegister(rd); | 724 const Register crd = ConcreteRegister(rd); |
| 725 EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn)); | 725 EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn)); |
| 726 } | 726 } |
| 727 void fmovdd(VRegister vd, VRegister vn) { | 727 void fmovdd(VRegister vd, VRegister vn) { |
| 728 EmitFPOneSourceOp(FMOVDD, vd, vn); | 728 EmitFPOneSourceOp(FMOVDD, vd, vn); |
| 729 } | 729 } |
| 730 void fabsd(VRegister vd, VRegister vn) { | 730 void fabsd(VRegister vd, VRegister vn) { |
| 731 EmitFPOneSourceOp(FABSD, vd, vn); | 731 EmitFPOneSourceOp(FABSD, vd, vn); |
| 732 } | 732 } |
| 733 void fnegd(VRegister vd, VRegister vn) { | 733 void fnegd(VRegister vd, VRegister vn) { |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 const VRegister vd = static_cast<VRegister>(rd); | 926 const VRegister vd = static_cast<VRegister>(rd); |
| 927 EmitSIMDCopyOp(VMOVW, vd, vn, kWord, 0, sidx); | 927 EmitSIMDCopyOp(VMOVW, vd, vn, kWord, 0, sidx); |
| 928 } | 928 } |
| 929 void vmovrd(Register rd, VRegister vn, int32_t sidx) { | 929 void vmovrd(Register rd, VRegister vn, int32_t sidx) { |
| 930 const VRegister vd = static_cast<VRegister>(rd); | 930 const VRegister vd = static_cast<VRegister>(rd); |
| 931 EmitSIMDCopyOp(VMOVX, vd, vn, kDoubleWord, 0, sidx); | 931 EmitSIMDCopyOp(VMOVX, vd, vn, kDoubleWord, 0, sidx); |
| 932 } | 932 } |
| 933 | 933 |
| 934 // Aliases. | 934 // Aliases. |
| 935 void mov(Register rd, Register rn) { | 935 void mov(Register rd, Register rn) { |
| 936 if ((rd == SP) || (rn == SP)) { | 936 if ((rd == CSP) || (rn == CSP)) { |
| 937 add(rd, rn, Operand(0)); | 937 add(rd, rn, Operand(0)); |
| 938 } else { | 938 } else { |
| 939 orr(rd, ZR, Operand(rn)); | 939 orr(rd, ZR, Operand(rn)); |
| 940 } | 940 } |
| 941 } | 941 } |
| 942 void vmov(VRegister vd, VRegister vn) { | 942 void vmov(VRegister vd, VRegister vn) { |
| 943 vorr(vd, vn, vn); | 943 vorr(vd, vn, vn); |
| 944 } | 944 } |
| 945 void mvn(Register rd, Register rm) { | 945 void mvn(Register rd, Register rm) { |
| 946 orn(rd, ZR, Operand(rm)); | 946 orn(rd, ZR, Operand(rm)); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 | 1279 |
| 1280 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, | 1280 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, |
| 1281 Register rd, Register rn, Operand o) { | 1281 Register rd, Register rn, Operand o) { |
| 1282 ASSERT((rd != R31) && (rn != R31)); | 1282 ASSERT((rd != R31) && (rn != R31)); |
| 1283 const Register crd = ConcreteRegister(rd); | 1283 const Register crd = ConcreteRegister(rd); |
| 1284 const Register crn = ConcreteRegister(rn); | 1284 const Register crn = ConcreteRegister(rn); |
| 1285 if (o.type() == Operand::Immediate) { | 1285 if (o.type() == Operand::Immediate) { |
| 1286 ASSERT(rn != ZR); | 1286 ASSERT(rn != ZR); |
| 1287 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); | 1287 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); |
| 1288 } else if (o.type() == Operand::Shifted) { | 1288 } else if (o.type() == Operand::Shifted) { |
| 1289 ASSERT((rd != SP) && (rn != SP)); | 1289 ASSERT((rd != CSP) && (rn != CSP)); |
| 1290 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | 1290 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
| 1291 } else { | 1291 } else { |
| 1292 ASSERT(o.type() == Operand::Extended); | 1292 ASSERT(o.type() == Operand::Extended); |
| 1293 ASSERT((rd != SP) && (rn != ZR)); | 1293 ASSERT((rd != CSP) && (rn != ZR)); |
| 1294 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); | 1294 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); |
| 1295 } | 1295 } |
| 1296 } | 1296 } |
| 1297 | 1297 |
| 1298 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, | 1298 void EmitAddSubImmOp(AddSubImmOp op, Register rd, Register rn, |
| 1299 Operand o, OperandSize sz, bool set_flags) { | 1299 Operand o, OperandSize sz, bool set_flags) { |
| 1300 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1300 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1301 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1301 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1302 const int32_t s = set_flags ? B29 : 0; | 1302 const int32_t s = set_flags ? B29 : 0; |
| 1303 const int32_t encoding = | 1303 const int32_t encoding = |
| 1304 op | size | s | | 1304 op | size | s | |
| 1305 (static_cast<int32_t>(rd) << kRdShift) | | 1305 (static_cast<int32_t>(rd) << kRdShift) | |
| 1306 (static_cast<int32_t>(rn) << kRnShift) | | 1306 (static_cast<int32_t>(rn) << kRnShift) | |
| 1307 o.encoding(); | 1307 o.encoding(); |
| 1308 Emit(encoding); | 1308 Emit(encoding); |
| 1309 } | 1309 } |
| 1310 | 1310 |
| 1311 void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn, | 1311 void EmitLogicalImmOp(LogicalImmOp op, Register rd, Register rn, |
| 1312 Operand o, OperandSize sz) { | 1312 Operand o, OperandSize sz) { |
| 1313 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1313 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1314 ASSERT((rd != R31) && (rn != R31)); | 1314 ASSERT((rd != R31) && (rn != R31)); |
| 1315 ASSERT(rn != SP); | 1315 ASSERT(rn != CSP); |
| 1316 ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR. | 1316 ASSERT((op == ANDIS) || (rd != ZR)); // op != ANDIS => rd != ZR. |
| 1317 ASSERT((op != ANDIS) || (rd != SP)); // op == ANDIS => rd != SP. | 1317 ASSERT((op != ANDIS) || (rd != CSP)); // op == ANDIS => rd != CSP. |
| 1318 ASSERT(o.type() == Operand::BitfieldImm); | 1318 ASSERT(o.type() == Operand::BitfieldImm); |
| 1319 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1319 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1320 const Register crd = ConcreteRegister(rd); | 1320 const Register crd = ConcreteRegister(rd); |
| 1321 const Register crn = ConcreteRegister(rn); | 1321 const Register crn = ConcreteRegister(rn); |
| 1322 const int32_t encoding = | 1322 const int32_t encoding = |
| 1323 op | size | | 1323 op | size | |
| 1324 (static_cast<int32_t>(crd) << kRdShift) | | 1324 (static_cast<int32_t>(crd) << kRdShift) | |
| 1325 (static_cast<int32_t>(crn) << kRnShift) | | 1325 (static_cast<int32_t>(crn) << kRnShift) | |
| 1326 o.encoding(); | 1326 o.encoding(); |
| 1327 Emit(encoding); | 1327 Emit(encoding); |
| 1328 } | 1328 } |
| 1329 | 1329 |
| 1330 void EmitLogicalShiftOp(LogicalShiftOp op, | 1330 void EmitLogicalShiftOp(LogicalShiftOp op, |
| 1331 Register rd, Register rn, Operand o, OperandSize sz) { | 1331 Register rd, Register rn, Operand o, OperandSize sz) { |
| 1332 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1332 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1333 ASSERT((rd != R31) && (rn != R31)); | 1333 ASSERT((rd != R31) && (rn != R31)); |
| 1334 ASSERT((rd != SP) && (rn != SP)); | 1334 ASSERT((rd != CSP) && (rn != CSP)); |
| 1335 ASSERT(o.type() == Operand::Shifted); | 1335 ASSERT(o.type() == Operand::Shifted); |
| 1336 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1336 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1337 const Register crd = ConcreteRegister(rd); | 1337 const Register crd = ConcreteRegister(rd); |
| 1338 const Register crn = ConcreteRegister(rn); | 1338 const Register crn = ConcreteRegister(rn); |
| 1339 const int32_t encoding = | 1339 const int32_t encoding = |
| 1340 op | size | | 1340 op | size | |
| 1341 (static_cast<int32_t>(crd) << kRdShift) | | 1341 (static_cast<int32_t>(crd) << kRdShift) | |
| 1342 (static_cast<int32_t>(crn) << kRnShift) | | 1342 (static_cast<int32_t>(crn) << kRnShift) | |
| 1343 o.encoding(); | 1343 o.encoding(); |
| 1344 Emit(encoding); | 1344 Emit(encoding); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 | 1391 |
| 1392 int64_t DecodeImm26BranchOffset(int32_t instr) { | 1392 int64_t DecodeImm26BranchOffset(int32_t instr) { |
| 1393 const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4; | 1393 const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4; |
| 1394 return static_cast<int64_t>(off); | 1394 return static_cast<int64_t>(off); |
| 1395 } | 1395 } |
| 1396 | 1396 |
| 1397 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, | 1397 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, |
| 1398 OperandSize sz) { | 1398 OperandSize sz) { |
| 1399 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1399 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1400 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); | 1400 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| 1401 ASSERT((rt != SP) && (rt != R31)); | 1401 ASSERT((rt != CSP) && (rt != R31)); |
| 1402 const Register crt = ConcreteRegister(rt); | 1402 const Register crt = ConcreteRegister(rt); |
| 1403 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1403 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1404 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); | 1404 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); |
| 1405 const int32_t encoding = | 1405 const int32_t encoding = |
| 1406 op | size | | 1406 op | size | |
| 1407 (static_cast<int32_t>(crt) << kRtShift) | | 1407 (static_cast<int32_t>(crt) << kRtShift) | |
| 1408 encoded_offset; | 1408 encoded_offset; |
| 1409 Emit(encoding); | 1409 Emit(encoding); |
| 1410 } | 1410 } |
| 1411 | 1411 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 } | 1456 } |
| 1457 | 1457 |
| 1458 void EmitUnconditionalBranchOp(UnconditionalBranchOp op, int64_t offset) { | 1458 void EmitUnconditionalBranchOp(UnconditionalBranchOp op, int64_t offset) { |
| 1459 ASSERT(CanEncodeImm26BranchOffset(offset)); | 1459 ASSERT(CanEncodeImm26BranchOffset(offset)); |
| 1460 const int32_t off = (offset >> 2) << kImm26Shift; | 1460 const int32_t off = (offset >> 2) << kImm26Shift; |
| 1461 const int32_t encoding = op | off; | 1461 const int32_t encoding = op | off; |
| 1462 Emit(encoding); | 1462 Emit(encoding); |
| 1463 } | 1463 } |
| 1464 | 1464 |
| 1465 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { | 1465 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { |
| 1466 ASSERT((rn != SP) && (rn != R31)); | 1466 ASSERT((rn != CSP) && (rn != R31)); |
| 1467 const Register crn = ConcreteRegister(rn); | 1467 const Register crn = ConcreteRegister(rn); |
| 1468 const int32_t encoding = | 1468 const int32_t encoding = |
| 1469 op | (static_cast<int32_t>(crn) << kRnShift); | 1469 op | (static_cast<int32_t>(crn) << kRnShift); |
| 1470 Emit(encoding); | 1470 Emit(encoding); |
| 1471 } | 1471 } |
| 1472 | 1472 |
| 1473 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { | 1473 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { |
| 1474 const int32_t encoding = | 1474 const int32_t encoding = |
| 1475 op | (static_cast<int32_t>(imm) << kImm16Shift); | 1475 op | (static_cast<int32_t>(imm) << kImm16Shift); |
| 1476 Emit(encoding); | 1476 Emit(encoding); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1496 const int32_t encoding = | 1496 const int32_t encoding = |
| 1497 op | ((size & 0x3) << kSzShift) | | 1497 op | ((size & 0x3) << kSzShift) | |
| 1498 (static_cast<int32_t>(crt) << kRtShift) | | 1498 (static_cast<int32_t>(crt) << kRtShift) | |
| 1499 a.encoding(); | 1499 a.encoding(); |
| 1500 Emit(encoding); | 1500 Emit(encoding); |
| 1501 } | 1501 } |
| 1502 | 1502 |
| 1503 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, | 1503 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a, |
| 1504 OperandSize sz) { | 1504 OperandSize sz) { |
| 1505 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1505 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1506 ASSERT((rt != SP) && (rt != R31)); | 1506 ASSERT((rt != CSP) && (rt != R31)); |
| 1507 const Register crt = ConcreteRegister(rt); | 1507 const Register crt = ConcreteRegister(rt); |
| 1508 const int32_t size = (sz == kDoubleWord) ? B30 : 0; | 1508 const int32_t size = (sz == kDoubleWord) ? B30 : 0; |
| 1509 const int32_t encoding = | 1509 const int32_t encoding = |
| 1510 op | size | | 1510 op | size | |
| 1511 (static_cast<int32_t>(crt) << kRtShift) | | 1511 (static_cast<int32_t>(crt) << kRtShift) | |
| 1512 a.encoding(); | 1512 a.encoding(); |
| 1513 Emit(encoding); | 1513 Emit(encoding); |
| 1514 } | 1514 } |
| 1515 | 1515 |
| 1516 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { | 1516 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { |
| 1517 ASSERT(Utils::IsInt(21, imm)); | 1517 ASSERT(Utils::IsInt(21, imm)); |
| 1518 ASSERT((rd != R31) && (rd != SP)); | 1518 ASSERT((rd != R31) && (rd != CSP)); |
| 1519 const Register crd = ConcreteRegister(rd); | 1519 const Register crd = ConcreteRegister(rd); |
| 1520 const int32_t loimm = (imm & 0x3) << 29; | 1520 const int32_t loimm = (imm & 0x3) << 29; |
| 1521 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; | 1521 const int32_t hiimm = ((imm >> 2) << kImm19Shift) & kImm19Mask; |
| 1522 const int32_t encoding = | 1522 const int32_t encoding = |
| 1523 op | loimm | hiimm | | 1523 op | loimm | hiimm | |
| 1524 (static_cast<int32_t>(crd) << kRdShift); | 1524 (static_cast<int32_t>(crd) << kRdShift); |
| 1525 Emit(encoding); | 1525 Emit(encoding); |
| 1526 } | 1526 } |
| 1527 | 1527 |
| 1528 void EmitMiscDP2Source(MiscDP2SourceOp op, | 1528 void EmitMiscDP2Source(MiscDP2SourceOp op, |
| 1529 Register rd, Register rn, Register rm, | 1529 Register rd, Register rn, Register rm, |
| 1530 OperandSize sz) { | 1530 OperandSize sz) { |
| 1531 ASSERT((rd != SP) && (rn != SP) && (rm != SP)); | 1531 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); |
| 1532 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1532 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1533 const Register crd = ConcreteRegister(rd); | 1533 const Register crd = ConcreteRegister(rd); |
| 1534 const Register crn = ConcreteRegister(rn); | 1534 const Register crn = ConcreteRegister(rn); |
| 1535 const Register crm = ConcreteRegister(rm); | 1535 const Register crm = ConcreteRegister(rm); |
| 1536 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1536 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1537 const int32_t encoding = | 1537 const int32_t encoding = |
| 1538 op | size | | 1538 op | size | |
| 1539 (static_cast<int32_t>(crd) << kRdShift) | | 1539 (static_cast<int32_t>(crd) << kRdShift) | |
| 1540 (static_cast<int32_t>(crn) << kRnShift) | | 1540 (static_cast<int32_t>(crn) << kRnShift) | |
| 1541 (static_cast<int32_t>(crm) << kRmShift); | 1541 (static_cast<int32_t>(crm) << kRmShift); |
| 1542 Emit(encoding); | 1542 Emit(encoding); |
| 1543 } | 1543 } |
| 1544 | 1544 |
| 1545 void EmitMiscDP3Source(MiscDP3SourceOp op, | 1545 void EmitMiscDP3Source(MiscDP3SourceOp op, |
| 1546 Register rd, Register rn, Register rm, Register ra, | 1546 Register rd, Register rn, Register rm, Register ra, |
| 1547 OperandSize sz) { | 1547 OperandSize sz) { |
| 1548 ASSERT((rd != SP) && (rn != SP) && (rm != SP) && (ra != SP)); | 1548 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP) && (ra != CSP)); |
| 1549 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1549 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1550 const Register crd = ConcreteRegister(rd); | 1550 const Register crd = ConcreteRegister(rd); |
| 1551 const Register crn = ConcreteRegister(rn); | 1551 const Register crn = ConcreteRegister(rn); |
| 1552 const Register crm = ConcreteRegister(rm); | 1552 const Register crm = ConcreteRegister(rm); |
| 1553 const Register cra = ConcreteRegister(ra); | 1553 const Register cra = ConcreteRegister(ra); |
| 1554 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1554 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1555 const int32_t encoding = | 1555 const int32_t encoding = |
| 1556 op | size | | 1556 op | size | |
| 1557 (static_cast<int32_t>(crd) << kRdShift) | | 1557 (static_cast<int32_t>(crd) << kRdShift) | |
| 1558 (static_cast<int32_t>(crn) << kRnShift) | | 1558 (static_cast<int32_t>(crn) << kRnShift) | |
| 1559 (static_cast<int32_t>(crm) << kRmShift) | | 1559 (static_cast<int32_t>(crm) << kRmShift) | |
| 1560 (static_cast<int32_t>(cra) << kRaShift); | 1560 (static_cast<int32_t>(cra) << kRaShift); |
| 1561 Emit(encoding); | 1561 Emit(encoding); |
| 1562 } | 1562 } |
| 1563 | 1563 |
| 1564 void EmitConditionalSelect(ConditionalSelectOp op, | 1564 void EmitConditionalSelect(ConditionalSelectOp op, |
| 1565 Register rd, Register rn, Register rm, | 1565 Register rd, Register rn, Register rm, |
| 1566 Condition cond, OperandSize sz) { | 1566 Condition cond, OperandSize sz) { |
| 1567 ASSERT((rd != SP) && (rn != SP) && (rm != SP)); | 1567 ASSERT((rd != CSP) && (rn != CSP) && (rm != CSP)); |
| 1568 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1568 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1569 const Register crd = ConcreteRegister(rd); | 1569 const Register crd = ConcreteRegister(rd); |
| 1570 const Register crn = ConcreteRegister(rn); | 1570 const Register crn = ConcreteRegister(rn); |
| 1571 const Register crm = ConcreteRegister(rm); | 1571 const Register crm = ConcreteRegister(rm); |
| 1572 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1572 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1573 const int32_t encoding = | 1573 const int32_t encoding = |
| 1574 op | size | | 1574 op | size | |
| 1575 (static_cast<int32_t>(crd) << kRdShift) | | 1575 (static_cast<int32_t>(crd) << kRdShift) | |
| 1576 (static_cast<int32_t>(crn) << kRnShift) | | 1576 (static_cast<int32_t>(crn) << kRnShift) | |
| 1577 (static_cast<int32_t>(crm) << kRmShift) | | 1577 (static_cast<int32_t>(crm) << kRmShift) | |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1660 Register value, | 1660 Register value, |
| 1661 Label* no_update); | 1661 Label* no_update); |
| 1662 | 1662 |
| 1663 DISALLOW_ALLOCATION(); | 1663 DISALLOW_ALLOCATION(); |
| 1664 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1664 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1665 }; | 1665 }; |
| 1666 | 1666 |
| 1667 } // namespace dart | 1667 } // namespace dart |
| 1668 | 1668 |
| 1669 #endif // VM_ASSEMBLER_ARM64_H_ | 1669 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |