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 fstrs(reg, Address(SP, -1 * kFloatSize, Address::PreIndex)); |
| 865 } |
802 void PushDouble(VRegister reg) { | 866 void PushDouble(VRegister reg) { |
803 fstrd(reg, Address(SP, -1 * kWordSize, Address::PreIndex)); | 867 fstrd(reg, Address(SP, -1 * kDoubleSize, Address::PreIndex)); |
| 868 } |
| 869 void PushQuad(VRegister reg) { |
| 870 fstrq(reg, Address(SP, -1 * kQuadSize, Address::PreIndex)); |
| 871 } |
| 872 void PopFloat(VRegister reg) { |
| 873 fldrs(reg, Address(SP, 1 * kFloatSize, Address::PostIndex)); |
804 } | 874 } |
805 void PopDouble(VRegister reg) { | 875 void PopDouble(VRegister reg) { |
806 fldrd(reg, Address(SP, 1 * kWordSize, Address::PostIndex)); | 876 fldrd(reg, Address(SP, 1 * kDoubleSize, Address::PostIndex)); |
| 877 } |
| 878 void PopQuad(VRegister reg) { |
| 879 fldrq(reg, Address(SP, 1 * kQuadSize, Address::PostIndex)); |
807 } | 880 } |
808 void TagAndPushPP() { | 881 void TagAndPushPP() { |
809 // Add the heap object tag back to PP before putting it on the stack. | 882 // Add the heap object tag back to PP before putting it on the stack. |
810 add(TMP, PP, Operand(kHeapObjectTag)); | 883 add(TMP, PP, Operand(kHeapObjectTag)); |
811 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); | 884 str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
812 } | 885 } |
813 void PopAndUntagPP() { | 886 void PopAndUntagPP() { |
814 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); | 887 ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
815 sub(PP, PP, Operand(kHeapObjectTag)); | 888 sub(PP, PP, Operand(kHeapObjectTag)); |
816 } | 889 } |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 const int32_t imm4 = (idx4 << shift) & 0xf; | 1530 const int32_t imm4 = (idx4 << shift) & 0xf; |
1458 const int32_t encoding = | 1531 const int32_t encoding = |
1459 op | | 1532 op | |
1460 (imm5 << kImm5Shift) | | 1533 (imm5 << kImm5Shift) | |
1461 (imm4 << kImm4Shift) | | 1534 (imm4 << kImm4Shift) | |
1462 (static_cast<int32_t>(vd) << kVdShift) | | 1535 (static_cast<int32_t>(vd) << kVdShift) | |
1463 (static_cast<int32_t>(vn) << kVnShift); | 1536 (static_cast<int32_t>(vn) << kVnShift); |
1464 Emit(encoding); | 1537 Emit(encoding); |
1465 } | 1538 } |
1466 | 1539 |
| 1540 void EmitSIMDTwoRegOp(SIMDTwoRegOp op, VRegister vd, VRegister vn) { |
| 1541 const int32_t encoding = |
| 1542 op | |
| 1543 (static_cast<int32_t>(vd) << kVdShift) | |
| 1544 (static_cast<int32_t>(vn) << kVnShift); |
| 1545 Emit(encoding); |
| 1546 } |
| 1547 |
1467 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 1548 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
1468 | 1549 |
1469 // Shorter filtering sequence that assumes that value is not a smi. | 1550 // Shorter filtering sequence that assumes that value is not a smi. |
1470 void StoreIntoObjectFilterNoSmi(Register object, | 1551 void StoreIntoObjectFilterNoSmi(Register object, |
1471 Register value, | 1552 Register value, |
1472 Label* no_update); | 1553 Label* no_update); |
1473 | 1554 |
1474 DISALLOW_ALLOCATION(); | 1555 DISALLOW_ALLOCATION(); |
1475 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1556 DISALLOW_COPY_AND_ASSIGN(Assembler); |
1476 }; | 1557 }; |
1477 | 1558 |
1478 } // namespace dart | 1559 } // namespace dart |
1479 | 1560 |
1480 #endif // VM_ASSEMBLER_ARM64_H_ | 1561 #endif // VM_ASSEMBLER_ARM64_H_ |
OLD | NEW |