| 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 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 } | 506 } |
| 507 void lsrv(Register rd, Register rn, Register rm) { | 507 void lsrv(Register rd, Register rn, Register rm) { |
| 508 EmitMiscDP2Source(LSRV, rd, rn, rm, kDoubleWord); | 508 EmitMiscDP2Source(LSRV, rd, rn, rm, kDoubleWord); |
| 509 } | 509 } |
| 510 void asrv(Register rd, Register rn, Register rm) { | 510 void asrv(Register rd, Register rn, Register rm) { |
| 511 EmitMiscDP2Source(ASRV, rd, rn, rm, kDoubleWord); | 511 EmitMiscDP2Source(ASRV, rd, rn, rm, kDoubleWord); |
| 512 } | 512 } |
| 513 void madd(Register rd, Register rn, Register rm, Register ra) { | 513 void madd(Register rd, Register rn, Register rm, Register ra) { |
| 514 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); | 514 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); |
| 515 } | 515 } |
| 516 void msub(Register rd, Register rn, Register rm, Register ra) { |
| 517 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); |
| 518 } |
| 519 void smulh(Register rd, Register rn, Register rm) { |
| 520 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); |
| 521 } |
| 516 | 522 |
| 517 // Move wide immediate. | 523 // Move wide immediate. |
| 518 void movk(Register rd, uint16_t imm, int hw_idx) { | 524 void movk(Register rd, uint16_t imm, int hw_idx) { |
| 519 ASSERT(rd != SP); | 525 ASSERT(rd != SP); |
| 520 const Register crd = ConcreteRegister(rd); | 526 const Register crd = ConcreteRegister(rd); |
| 521 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); | 527 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); |
| 522 } | 528 } |
| 523 void movn(Register rd, uint16_t imm, int hw_idx) { | 529 void movn(Register rd, uint16_t imm, int hw_idx) { |
| 524 ASSERT(rd != SP); | 530 ASSERT(rd != SP); |
| 525 const Register crd = ConcreteRegister(rd); | 531 const Register crd = ConcreteRegister(rd); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 } | 621 } |
| 616 EmitFPImm(FMOVDI, vd, imm8); | 622 EmitFPImm(FMOVDI, vd, imm8); |
| 617 return true; | 623 return true; |
| 618 } | 624 } |
| 619 void fmovdr(VRegister vd, Register rn) { | 625 void fmovdr(VRegister vd, Register rn) { |
| 620 EmitFPIntCvtOp(FMOVDR, static_cast<Register>(vd), rn); | 626 EmitFPIntCvtOp(FMOVDR, static_cast<Register>(vd), rn); |
| 621 } | 627 } |
| 622 void fmovrd(Register rd, VRegister vn) { | 628 void fmovrd(Register rd, VRegister vn) { |
| 623 EmitFPIntCvtOp(FMOVRD, rd, static_cast<Register>(vn)); | 629 EmitFPIntCvtOp(FMOVRD, rd, static_cast<Register>(vn)); |
| 624 } | 630 } |
| 631 void fmovdd(VRegister vd, VRegister vn) { |
| 632 EmitFPOneSourceOp(FMOVDD, vd, vn); |
| 633 } |
| 625 | 634 |
| 626 void fldrd(VRegister vt, Address a) { | 635 void fldrd(VRegister vt, Address a) { |
| 627 ASSERT(a.type() != Address::PCOffset); | 636 ASSERT(a.type() != Address::PCOffset); |
| 628 EmitLoadStoreReg(FLDR, static_cast<Register>(vt), a, kDoubleWord); | 637 EmitLoadStoreReg(FLDR, static_cast<Register>(vt), a, kDoubleWord); |
| 629 } | 638 } |
| 630 void fstrd(VRegister vt, Address a) { | 639 void fstrd(VRegister vt, Address a) { |
| 631 ASSERT(a.type() != Address::PCOffset); | 640 ASSERT(a.type() != Address::PCOffset); |
| 632 EmitLoadStoreReg(FSTR, static_cast<Register>(vt), a, kDoubleWord); | 641 EmitLoadStoreReg(FSTR, static_cast<Register>(vt), a, kDoubleWord); |
| 633 } | 642 } |
| 634 | 643 |
| 635 // Aliases. | 644 // Aliases. |
| 636 void mov(Register rd, Register rn) { | 645 void mov(Register rd, Register rn) { |
| 637 if ((rd == SP) || (rn == SP)) { | 646 if ((rd == SP) || (rn == SP)) { |
| 638 add(rd, rn, Operand(0)); | 647 add(rd, rn, Operand(0)); |
| 639 } else { | 648 } else { |
| 640 orr(rd, ZR, Operand(rn)); | 649 orr(rd, ZR, Operand(rn)); |
| 641 } | 650 } |
| 642 } | 651 } |
| 643 void mvn(Register rd, Register rm) { | 652 void mvn(Register rd, Register rm) { |
| 644 orr(rd, ZR, Operand(rm)); | 653 orn(rd, ZR, Operand(rm)); |
| 645 } | 654 } |
| 646 void neg(Register rd, Register rm) { | 655 void neg(Register rd, Register rm) { |
| 647 sub(rd, ZR, Operand(rm)); | 656 sub(rd, ZR, Operand(rm)); |
| 648 } | 657 } |
| 649 void negs(Register rd, Register rm) { | 658 void negs(Register rd, Register rm) { |
| 650 subs(rd, ZR, Operand(rm)); | 659 subs(rd, ZR, Operand(rm)); |
| 651 } | 660 } |
| 652 void mul(Register rd, Register rn, Register rm) { | 661 void mul(Register rd, Register rn, Register rm) { |
| 653 madd(rd, rn, rm, ZR); | 662 madd(rd, rn, rm, ZR); |
| 654 } | 663 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 void BranchLinkPatchable(const ExternalLabel* label) { | 738 void BranchLinkPatchable(const ExternalLabel* label) { |
| 730 LoadExternalLabel(TMP, label, kPatchable, PP); | 739 LoadExternalLabel(TMP, label, kPatchable, PP); |
| 731 blr(TMP); | 740 blr(TMP); |
| 732 } | 741 } |
| 733 | 742 |
| 734 // Macros accepting a pp Register argument may attempt to load values from | 743 // Macros accepting a pp Register argument may attempt to load values from |
| 735 // the object pool when possible. Unless you are sure that the untagged object | 744 // the object pool when possible. Unless you are sure that the untagged object |
| 736 // pool pointer is in another register, or that it is not available at all, | 745 // pool pointer is in another register, or that it is not available at all, |
| 737 // PP should be passed for pp. | 746 // PP should be passed for pp. |
| 738 void AddImmediate(Register dest, Register rn, int64_t imm, Register pp); | 747 void AddImmediate(Register dest, Register rn, int64_t imm, Register pp); |
| 748 void AddImmediateSetFlags( |
| 749 Register dest, Register rn, int64_t imm, Register pp); |
| 750 void AndImmediate(Register rd, Register rn, int64_t imm, Register pp); |
| 751 void OrImmediate(Register rd, Register rn, int64_t imm, Register pp); |
| 752 void XorImmediate(Register rd, Register rn, int64_t imm, Register pp); |
| 739 void TestImmediate(Register rn, int64_t imm, Register pp); | 753 void TestImmediate(Register rn, int64_t imm, Register pp); |
| 740 void CompareImmediate(Register rn, int64_t imm, Register pp); | 754 void CompareImmediate(Register rn, int64_t imm, Register pp); |
| 741 | 755 |
| 742 void LoadFromOffset(Register dest, Register base, int32_t offset, | 756 void LoadFromOffset(Register dest, Register base, int32_t offset, |
| 743 OperandSize sz = kDoubleWord); | 757 OperandSize sz = kDoubleWord); |
| 744 void LoadFieldFromOffset(Register dest, Register base, int32_t offset) { | 758 void LoadFieldFromOffset(Register dest, Register base, int32_t offset) { |
| 745 LoadFromOffset(dest, base, offset - kHeapObjectTag); | 759 LoadFromOffset(dest, base, offset - kHeapObjectTag); |
| 746 } | 760 } |
| 747 void LoadDFromOffset(VRegister dest, Register base, int32_t offset); | 761 void LoadDFromOffset(VRegister dest, Register base, int32_t offset); |
| 748 void LoadDFieldFromOffset(VRegister dest, Register base, int32_t offset) { | 762 void LoadDFieldFromOffset(VRegister dest, Register base, int32_t offset) { |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 } | 1193 } |
| 1180 | 1194 |
| 1181 void EmitFPIntCvtOp(FPIntCvtOp op, Register rd, Register rn) { | 1195 void EmitFPIntCvtOp(FPIntCvtOp op, Register rd, Register rn) { |
| 1182 const int32_t encoding = | 1196 const int32_t encoding = |
| 1183 op | | 1197 op | |
| 1184 (static_cast<int32_t>(rd) << kRdShift) | | 1198 (static_cast<int32_t>(rd) << kRdShift) | |
| 1185 (static_cast<int32_t>(rn) << kRnShift); | 1199 (static_cast<int32_t>(rn) << kRnShift); |
| 1186 Emit(encoding); | 1200 Emit(encoding); |
| 1187 } | 1201 } |
| 1188 | 1202 |
| 1203 void EmitFPOneSourceOp(FPOneSourceOp op, VRegister vd, VRegister vn) { |
| 1204 const int32_t encoding = |
| 1205 op | |
| 1206 (static_cast<int32_t>(vd) << kVdShift) | |
| 1207 (static_cast<int32_t>(vn) << kVnShift); |
| 1208 Emit(encoding); |
| 1209 } |
| 1210 |
| 1189 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 1211 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
| 1190 | 1212 |
| 1191 // Shorter filtering sequence that assumes that value is not a smi. | 1213 // Shorter filtering sequence that assumes that value is not a smi. |
| 1192 void StoreIntoObjectFilterNoSmi(Register object, | 1214 void StoreIntoObjectFilterNoSmi(Register object, |
| 1193 Register value, | 1215 Register value, |
| 1194 Label* no_update); | 1216 Label* no_update); |
| 1195 | 1217 |
| 1196 DISALLOW_ALLOCATION(); | 1218 DISALLOW_ALLOCATION(); |
| 1197 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1219 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1198 }; | 1220 }; |
| 1199 | 1221 |
| 1200 } // namespace dart | 1222 } // namespace dart |
| 1201 | 1223 |
| 1202 #endif // VM_ASSEMBLER_ARM64_H_ | 1224 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |