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 |