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 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 void subs(Register rd, Register rn, Operand o) { | 435 void subs(Register rd, Register rn, Operand o) { |
436 AddSubHelper(kDoubleWord, true, true, rd, rn, o); | 436 AddSubHelper(kDoubleWord, true, true, rd, rn, o); |
437 } | 437 } |
438 | 438 |
439 // PC relative immediate add. imm is in bytes. | 439 // PC relative immediate add. imm is in bytes. |
440 void adr(Register rd, int64_t imm) { | 440 void adr(Register rd, int64_t imm) { |
441 EmitPCRelOp(ADR, rd, imm); | 441 EmitPCRelOp(ADR, rd, imm); |
442 } | 442 } |
443 | 443 |
444 // Logical immediate operations. | 444 // Logical immediate operations. |
445 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer | |
446 // sequence on failure. | |
447 void andi(Register rd, Register rn, uint64_t imm) { | 445 void andi(Register rd, Register rn, uint64_t imm) { |
448 Operand imm_op; | 446 Operand imm_op; |
449 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 447 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); |
450 ASSERT(immok); | 448 ASSERT(immok); |
451 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); | 449 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); |
452 } | 450 } |
453 void orri(Register rd, Register rn, uint64_t imm) { | 451 void orri(Register rd, Register rn, uint64_t imm) { |
454 Operand imm_op; | 452 Operand imm_op; |
455 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); | 453 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op); |
456 ASSERT(immok); | 454 ASSERT(immok); |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
727 EmitFPTwoSourceOp(FDIVD, vd, vn, vm); | 725 EmitFPTwoSourceOp(FDIVD, vd, vn, vm); |
728 } | 726 } |
729 void faddd(VRegister vd, VRegister vn, VRegister vm) { | 727 void faddd(VRegister vd, VRegister vn, VRegister vm) { |
730 EmitFPTwoSourceOp(FADDD, vd, vn, vm); | 728 EmitFPTwoSourceOp(FADDD, vd, vn, vm); |
731 } | 729 } |
732 void fsubd(VRegister vd, VRegister vn, VRegister vm) { | 730 void fsubd(VRegister vd, VRegister vn, VRegister vm) { |
733 EmitFPTwoSourceOp(FSUBD, vd, vn, vm); | 731 EmitFPTwoSourceOp(FSUBD, vd, vn, vm); |
734 } | 732 } |
735 | 733 |
736 // SIMD operations. | 734 // SIMD operations. |
735 void vand(VRegister vd, VRegister vn, VRegister vm) { | |
736 EmitSIMDThreeSameOp(VAND, vd, vn, vm); | |
737 } | |
738 void vorr(VRegister vd, VRegister vn, VRegister vm) { | |
739 EmitSIMDThreeSameOp(VORR, vd, vn, vm); | |
740 } | |
741 void veor(VRegister vd, VRegister vn, VRegister vm) { | |
742 EmitSIMDThreeSameOp(VEOR, vd, vn, vm); | |
743 } | |
744 void vaddw(VRegister vd, VRegister vn, VRegister vm) { | |
745 EmitSIMDThreeSameOp(VADDW, vd, vn, vm); | |
746 } | |
747 void vaddx(VRegister vd, VRegister vn, VRegister vm) { | |
748 EmitSIMDThreeSameOp(VADDX, vd, vn, vm); | |
749 } | |
750 void vsubw(VRegister vd, VRegister vn, VRegister vm) { | |
751 EmitSIMDThreeSameOp(VSUBW, vd, vn, vm); | |
752 } | |
753 void vsubx(VRegister vd, VRegister vn, VRegister vm) { | |
754 EmitSIMDThreeSameOp(VSUBX, vd, vn, vm); | |
755 } | |
737 void vadds(VRegister vd, VRegister vn, VRegister vm) { | 756 void vadds(VRegister vd, VRegister vn, VRegister vm) { |
738 EmitSIMDThreeSameOp(VADDS, vd, vn, vm); | 757 EmitSIMDThreeSameOp(VADDS, vd, vn, vm); |
739 } | 758 } |
740 void vaddd(VRegister vd, VRegister vn, VRegister vm) { | 759 void vaddd(VRegister vd, VRegister vn, VRegister vm) { |
741 EmitSIMDThreeSameOp(VADDD, vd, vn, vm); | 760 EmitSIMDThreeSameOp(VADDD, vd, vn, vm); |
742 } | 761 } |
743 void vsubs(VRegister vd, VRegister vn, VRegister vm) { | 762 void vsubs(VRegister vd, VRegister vn, VRegister vm) { |
744 EmitSIMDThreeSameOp(VSUBS, vd, vn, vm); | 763 EmitSIMDThreeSameOp(VSUBS, vd, vn, vm); |
745 } | 764 } |
746 void vsubd(VRegister vd, VRegister vn, VRegister vm) { | 765 void vsubd(VRegister vd, VRegister vn, VRegister vm) { |
747 EmitSIMDThreeSameOp(VSUBD, vd, vn, vm); | 766 EmitSIMDThreeSameOp(VSUBD, vd, vn, vm); |
748 } | 767 } |
749 void vmuls(VRegister vd, VRegister vn, VRegister vm) { | 768 void vmuls(VRegister vd, VRegister vn, VRegister vm) { |
750 EmitSIMDThreeSameOp(VMULS, vd, vn, vm); | 769 EmitSIMDThreeSameOp(VMULS, vd, vn, vm); |
751 } | 770 } |
752 void vmuld(VRegister vd, VRegister vn, VRegister vm) { | 771 void vmuld(VRegister vd, VRegister vn, VRegister vm) { |
753 EmitSIMDThreeSameOp(VMULD, vd, vn, vm); | 772 EmitSIMDThreeSameOp(VMULD, vd, vn, vm); |
754 } | 773 } |
755 void vdivs(VRegister vd, VRegister vn, VRegister vm) { | 774 void vdivs(VRegister vd, VRegister vn, VRegister vm) { |
756 EmitSIMDThreeSameOp(VDIVS, vd, vn, vm); | 775 EmitSIMDThreeSameOp(VDIVS, vd, vn, vm); |
757 } | 776 } |
758 void vdivd(VRegister vd, VRegister vn, VRegister vm) { | 777 void vdivd(VRegister vd, VRegister vn, VRegister vm) { |
759 EmitSIMDThreeSameOp(VDIVD, vd, vn, vm); | 778 EmitSIMDThreeSameOp(VDIVD, vd, vn, vm); |
760 } | 779 } |
780 void vnot(VRegister vd, VRegister vn) { | |
781 EmitSIMDTwoRegOp(VNOT, vd, vn); | |
782 } | |
783 void vabss(VRegister vd, VRegister vn) { | |
784 EmitSIMDTwoRegOp(VABSS, vd, vn); | |
785 } | |
786 void vabsd(VRegister vd, VRegister vn) { | |
787 EmitSIMDTwoRegOp(VABSD, vd, vn); | |
788 } | |
789 void vnegs(VRegister vd, VRegister vn) { | |
790 EmitSIMDTwoRegOp(VNEGS, vd, vn); | |
791 } | |
792 void vnegd(VRegister vd, VRegister vn) { | |
793 EmitSIMDTwoRegOp(VNEGD, vd, vn); | |
794 } | |
795 void vdupw(VRegister vd, Register rn) { | |
796 const VRegister vn = static_cast<VRegister>(rn); | |
797 EmitSIMDCopyOp(VDUPI, vd, vn, kWord, 0, 0); | |
798 } | |
799 void vdupx(VRegister vd, Register rn) { | |
800 const VRegister vn = static_cast<VRegister>(rn); | |
801 EmitSIMDCopyOp(VDUPI, vd, vn, kDoubleWord, 0, 0); | |
802 } | |
761 void vdups(VRegister vd, VRegister vn, int32_t idx) { | 803 void vdups(VRegister vd, VRegister vn, int32_t idx) { |
762 EmitSIMDCopyOp(VDUP, vd, vn, kSWord, 0, idx); | 804 EmitSIMDCopyOp(VDUP, vd, vn, kSWord, 0, idx); |
763 } | 805 } |
764 void vdupd(VRegister vd, VRegister vn, int32_t idx) { | 806 void vdupd(VRegister vd, VRegister vn, int32_t idx) { |
765 EmitSIMDCopyOp(VDUP, vd, vn, kDWord, 0, idx); | 807 EmitSIMDCopyOp(VDUP, vd, vn, kDWord, 0, idx); |
766 } | 808 } |
809 void vinsw(VRegister vd, int32_t didx, Register rn) { | |
810 const VRegister vn = static_cast<VRegister>(rn); | |
811 EmitSIMDCopyOp(VINSI, vd, vn, kWord, 0, didx); | |
812 } | |
813 void vinsx(VRegister vd, int32_t didx, Register rn) { | |
814 const VRegister vn = static_cast<VRegister>(rn); | |
815 EmitSIMDCopyOp(VINSI, vd, vn, kDoubleWord, 0, didx); | |
816 } | |
767 void vinss(VRegister vd, int32_t didx, VRegister vn, int32_t sidx) { | 817 void vinss(VRegister vd, int32_t didx, VRegister vn, int32_t sidx) { |
768 EmitSIMDCopyOp(VINS, vd, vn, kSWord, sidx, didx); | 818 EmitSIMDCopyOp(VINS, vd, vn, kSWord, sidx, didx); |
769 } | 819 } |
770 void vinsd(VRegister vd, int32_t didx, VRegister vn, int32_t sidx) { | 820 void vinsd(VRegister vd, int32_t didx, VRegister vn, int32_t sidx) { |
771 EmitSIMDCopyOp(VINS, vd, vn, kDWord, sidx, didx); | 821 EmitSIMDCopyOp(VINS, vd, vn, kDWord, sidx, didx); |
772 } | 822 } |
823 void vmovrs(Register rd, VRegister vn, int32_t sidx) { | |
824 const VRegister vd = static_cast<VRegister>(rd); | |
825 EmitSIMDCopyOp(VMOVW, vd, vn, kWord, 0, sidx); | |
826 } | |
827 void vmovrd(Register rd, VRegister vn, int32_t sidx) { | |
828 const VRegister vd = static_cast<VRegister>(rd); | |
829 EmitSIMDCopyOp(VMOVX, vd, vn, kDoubleWord, 0, sidx); | |
830 } | |
773 | 831 |
774 // Aliases. | 832 // Aliases. |
775 void mov(Register rd, Register rn) { | 833 void mov(Register rd, Register rn) { |
776 if ((rd == SP) || (rn == SP)) { | 834 if ((rd == SP) || (rn == SP)) { |
777 add(rd, rn, Operand(0)); | 835 add(rd, rn, Operand(0)); |
778 } else { | 836 } else { |
779 orr(rd, ZR, Operand(rn)); | 837 orr(rd, ZR, Operand(rn)); |
780 } | 838 } |
781 } | 839 } |
840 void vmov(VRegister vd, VRegister vn) { | |
841 vorr(vd, vn, vn); | |
842 } | |
782 void mvn(Register rd, Register rm) { | 843 void mvn(Register rd, Register rm) { |
783 orn(rd, ZR, Operand(rm)); | 844 orn(rd, ZR, Operand(rm)); |
784 } | 845 } |
785 void neg(Register rd, Register rm) { | 846 void neg(Register rd, Register rm) { |
786 sub(rd, ZR, Operand(rm)); | 847 sub(rd, ZR, Operand(rm)); |
787 } | 848 } |
788 void negs(Register rd, Register rm) { | 849 void negs(Register rd, Register rm) { |
789 subs(rd, ZR, Operand(rm)); | 850 subs(rd, ZR, Operand(rm)); |
790 } | 851 } |
791 void mul(Register rd, Register rn, Register rm) { | 852 void mul(Register rd, Register rn, Register rm) { |
792 madd(rd, rn, rm, ZR); | 853 madd(rd, rn, rm, ZR); |
793 } | 854 } |
794 void Push(Register reg) { | 855 void Push(Register reg) { |
795 ASSERT(reg != PP); // Only push PP with TagAndPushPP(). | 856 ASSERT(reg != PP); // Only push PP with TagAndPushPP(). |
796 str(reg, Address(SP, -1 * kWordSize, Address::PreIndex)); | 857 str(reg, Address(SP, -1 * kWordSize, Address::PreIndex)); |
797 } | 858 } |
798 void Pop(Register reg) { | 859 void Pop(Register reg) { |
799 ASSERT(reg != PP); // Only pop PP with PopAndUntagPP(). | 860 ASSERT(reg != PP); // Only pop PP with PopAndUntagPP(). |
800 ldr(reg, Address(SP, 1 * kWordSize, Address::PostIndex)); | 861 ldr(reg, Address(SP, 1 * kWordSize, Address::PostIndex)); |
801 } | 862 } |
863 void PushFloat(VRegister reg) { | |
864 const int sword_bytes = 1 << Log2OperandSizeBytes(kSWord); | |
865 fstrs(reg, Address(SP, -1 * sword_bytes, Address::PreIndex)); | |
regis
2014/05/23 19:50:24
Use kFloatSize
zra
2014/05/23 20:12:58
Done.
| |
866 } | |
802 void PushDouble(VRegister reg) { | 867 void PushDouble(VRegister reg) { |
803 fstrd(reg, Address(SP, -1 * kWordSize, Address::PreIndex)); | 868 const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord); |
869 fstrd(reg, Address(SP, -1 * dword_bytes, Address::PreIndex)); | |
regis
2014/05/23 19:50:24
Use kDoubleSize
zra
2014/05/23 20:12:58
Done.
| |
870 } | |
871 void PushQuad(VRegister reg) { | |
872 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord); | |
873 fstrq(reg, Address(SP, -1 * qword_bytes, Address::PreIndex)); | |
regis
2014/05/23 19:50:24
Define a kQuadSize in globals.h
zra
2014/05/23 20:12:58
Done.
| |
874 } | |
875 void PopFloat(VRegister reg) { | |
876 const int sword_bytes = 1 << Log2OperandSizeBytes(kSWord); | |
877 fldrs(reg, Address(SP, 1 * sword_bytes, Address::PostIndex)); | |
regis
2014/05/23 19:50:24
ditto
zra
2014/05/23 20:12:58
Done.
| |
804 } | 878 } |
805 void PopDouble(VRegister reg) { | 879 void PopDouble(VRegister reg) { |
806 fldrd(reg, Address(SP, 1 * kWordSize, Address::PostIndex)); | 880 const int dword_bytes = 1 << Log2OperandSizeBytes(kDWord); |
881 fldrd(reg, Address(SP, 1 * dword_bytes, Address::PostIndex)); | |
regis
2014/05/23 19:50:24
ditto
zra
2014/05/23 20:12:58
Done.
| |
882 } | |
883 void PopQuad(VRegister reg) { | |
884 const int qword_bytes = 1 << Log2OperandSizeBytes(kQWord); | |
885 fldrq(reg, Address(SP, 1 * qword_bytes, Address::PostIndex)); | |
regis
2014/05/23 19:50:24
ditto
zra
2014/05/23 20:12:58
Done.
| |
807 } | 886 } |
808 void TagAndPushPP() { | 887 void TagAndPushPP() { |
809 // Add the heap object tag back to PP before putting it on the stack. | 888 // Add the heap object tag back to PP before putting it on the stack. |
810 add(TMP, PP, Operand(kHeapObjectTag)); | 889 add(TMP, PP, Operand(kHeapObjectTag)); |
811 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); | 890 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
812 } | 891 } |
813 void PopAndUntagPP() { | 892 void PopAndUntagPP() { |
814 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); | 893 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
815 sub(PP, PP, Operand(kHeapObjectTag)); | 894 sub(PP, PP, Operand(kHeapObjectTag)); |
816 } | 895 } |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1457 const int32_t imm4 = (idx4 << shift) & 0xf; | 1536 const int32_t imm4 = (idx4 << shift) & 0xf; |
1458 const int32_t encoding = | 1537 const int32_t encoding = |
1459 op | | 1538 op | |
1460 (imm5 << kImm5Shift) | | 1539 (imm5 << kImm5Shift) | |
1461 (imm4 << kImm4Shift) | | 1540 (imm4 << kImm4Shift) | |
1462 (static_cast<int32_t>(vd) << kVdShift) | | 1541 (static_cast<int32_t>(vd) << kVdShift) | |
1463 (static_cast<int32_t>(vn) << kVnShift); | 1542 (static_cast<int32_t>(vn) << kVnShift); |
1464 Emit(encoding); | 1543 Emit(encoding); |
1465 } | 1544 } |
1466 | 1545 |
1546 void EmitSIMDTwoRegOp(SIMDTwoRegOp op, VRegister vd, VRegister vn) { | |
1547 const int32_t encoding = | |
1548 op | | |
1549 (static_cast<int32_t>(vd) << kVdShift) | | |
1550 (static_cast<int32_t>(vn) << kVnShift); | |
1551 Emit(encoding); | |
1552 } | |
1553 | |
1467 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 1554 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
1468 | 1555 |
1469 // Shorter filtering sequence that assumes that value is not a smi. | 1556 // Shorter filtering sequence that assumes that value is not a smi. |
1470 void StoreIntoObjectFilterNoSmi(Register object, | 1557 void StoreIntoObjectFilterNoSmi(Register object, |
1471 Register value, | 1558 Register value, |
1472 Label* no_update); | 1559 Label* no_update); |
1473 | 1560 |
1474 DISALLOW_ALLOCATION(); | 1561 DISALLOW_ALLOCATION(); |
1475 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1562 DISALLOW_COPY_AND_ASSIGN(Assembler); |
1476 }; | 1563 }; |
1477 | 1564 |
1478 } // namespace dart | 1565 } // namespace dart |
1479 | 1566 |
1480 #endif // VM_ASSEMBLER_ARM64_H_ | 1567 #endif // VM_ASSEMBLER_ARM64_H_ |
OLD | NEW |