Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: runtime/vm/assembler_arm64.h

Issue 701233003: Implement bigint intrinsics on arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } 668 }
669 void madd(Register rd, Register rn, Register rm, Register ra) { 669 void madd(Register rd, Register rn, Register rm, Register ra) {
670 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); 670 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord);
671 } 671 }
672 void msub(Register rd, Register rn, Register rm, Register ra) { 672 void msub(Register rd, Register rn, Register rm, Register ra) {
673 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord); 673 EmitMiscDP3Source(MSUB, rd, rn, rm, ra, kDoubleWord);
674 } 674 }
675 void smulh(Register rd, Register rn, Register rm) { 675 void smulh(Register rd, Register rn, Register rm) {
676 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord); 676 EmitMiscDP3Source(SMULH, rd, rn, rm, R0, kDoubleWord);
677 } 677 }
678 void umaddl(Register rd, Register rn, Register rm, Register ra) {
679 EmitMiscDP3Source(UMADDL, rd, rn, rm, ra, kDoubleWord);
680 }
678 681
679 // Move wide immediate. 682 // Move wide immediate.
680 void movk(Register rd, const Immediate& imm, int hw_idx) { 683 void movk(Register rd, const Immediate& imm, int hw_idx) {
681 ASSERT(rd != CSP); 684 ASSERT(rd != CSP);
682 const Register crd = ConcreteRegister(rd); 685 const Register crd = ConcreteRegister(rd);
683 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); 686 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
684 } 687 }
685 void movn(Register rd, const Immediate& imm, int hw_idx) { 688 void movn(Register rd, const Immediate& imm, int hw_idx) {
686 ASSERT(rd != CSP); 689 ASSERT(rd != CSP);
687 const Register crd = ConcreteRegister(rd); 690 const Register crd = ConcreteRegister(rd);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 // UXTX 0 on a 64-bit register (rm) is a nop, but forces R31 to be 778 // UXTX 0 on a 64-bit register (rm) is a nop, but forces R31 to be
776 // interpreted as CSP. 779 // interpreted as CSP.
777 cmp(CSP, Operand(rm, UXTX, 0)); 780 cmp(CSP, Operand(rm, UXTX, 0));
778 } else { 781 } else {
779 cmp(rn, Operand(rm)); 782 cmp(rn, Operand(rm));
780 } 783 }
781 } 784 }
782 785
783 // Conditional branch. 786 // Conditional branch.
784 void b(Label* label, Condition cond = AL) { 787 void b(Label* label, Condition cond = AL) {
785 EmitBranch(BCOND, cond, label); 788 EmitConditionalBranch(BCOND, cond, label);
786 } 789 }
787 790
788 void b(int32_t offset) { 791 void b(int32_t offset) {
789 EmitUnconditionalBranchOp(B, offset); 792 EmitUnconditionalBranchOp(B, offset);
790 } 793 }
791 void bl(int32_t offset) { 794 void bl(int32_t offset) {
792 EmitUnconditionalBranchOp(BL, offset); 795 EmitUnconditionalBranchOp(BL, offset);
793 } 796 }
794 797
795 // TODO(zra): cbz, cbnz. 798 void cbz(Label* label, Register rt, OperandSize sz = kDoubleWord) {
799 EmitCompareAndBranch(CBZ, rt, label, sz);
800 }
801
802 void cbnz(Label* label, Register rt, OperandSize sz = kDoubleWord) {
803 EmitCompareAndBranch(CBNZ, rt, label, sz);
804 }
796 805
797 // Branch, link, return. 806 // Branch, link, return.
798 void br(Register rn) { 807 void br(Register rn) {
799 EmitUnconditionalBranchRegOp(BR, rn); 808 EmitUnconditionalBranchRegOp(BR, rn);
800 } 809 }
801 void blr(Register rn) { 810 void blr(Register rn) {
802 EmitUnconditionalBranchRegOp(BLR, rn); 811 EmitUnconditionalBranchRegOp(BLR, rn);
803 } 812 }
804 void ret(Register rn = R30) { 813 void ret(Register rn = R30) {
805 EmitUnconditionalBranchRegOp(RET, rn); 814 EmitUnconditionalBranchRegOp(RET, rn);
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 const int32_t imm32 = static_cast<int32_t>(imm); 1602 const int32_t imm32 = static_cast<int32_t>(imm);
1594 const int32_t off = (((imm32 >> 2) << kImm26Shift) & kImm26Mask); 1603 const int32_t off = (((imm32 >> 2) << kImm26Shift) & kImm26Mask);
1595 return (instr & ~kImm26Mask) | off; 1604 return (instr & ~kImm26Mask) | off;
1596 } 1605 }
1597 1606
1598 int64_t DecodeImm26BranchOffset(int32_t instr) { 1607 int64_t DecodeImm26BranchOffset(int32_t instr) {
1599 const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4; 1608 const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4;
1600 return static_cast<int64_t>(off); 1609 return static_cast<int64_t>(off);
1601 } 1610 }
1602 1611
1603 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, 1612 void EmitCompareAndBranchOp(CompareAndBranchOp op, Register rt, int64_t imm,
1604 OperandSize sz) { 1613 OperandSize sz) {
1605 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); 1614 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
1606 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); 1615 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0));
1607 ASSERT((rt != CSP) && (rt != R31)); 1616 ASSERT((rt != CSP) && (rt != R31));
1608 const Register crt = ConcreteRegister(rt); 1617 const Register crt = ConcreteRegister(rt);
1609 const int32_t size = (sz == kDoubleWord) ? B31 : 0; 1618 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
1610 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); 1619 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0);
1611 const int32_t encoding = 1620 const int32_t encoding =
1612 op | size | 1621 op | size |
1613 (static_cast<int32_t>(crt) << kRtShift) | 1622 (static_cast<int32_t>(crt) << kRtShift) |
1614 encoded_offset; 1623 encoded_offset;
1615 Emit(encoding); 1624 Emit(encoding);
1616 } 1625 }
1617 1626
1618 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, 1627 void EmitConditionalBranchOp(ConditionalBranchOp op, Condition cond,
1619 int64_t imm) { 1628 int64_t imm) {
1620 const int32_t off = EncodeImm19BranchOffset(imm, 0); 1629 const int32_t off = EncodeImm19BranchOffset(imm, 0);
1621 const int32_t encoding = 1630 const int32_t encoding =
1622 op | 1631 op |
1623 (static_cast<int32_t>(cond) << kCondShift) | 1632 (static_cast<int32_t>(cond) << kCondShift) |
1624 off; 1633 off;
1625 Emit(encoding); 1634 Emit(encoding);
1626 } 1635 }
1627 1636
1628 bool CanEncodeImm19BranchOffset(int64_t offset) { 1637 bool CanEncodeImm19BranchOffset(int64_t offset) {
1629 ASSERT(Utils::IsAligned(offset, 4)); 1638 ASSERT(Utils::IsAligned(offset, 4));
1630 return Utils::IsInt(21, offset); 1639 return Utils::IsInt(21, offset);
1631 } 1640 }
1632 1641
1633 void EmitBranch(ConditionalBranchOp op, Condition cond, Label* label) { 1642 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond,
1643 Label* label) {
1634 if (label->IsBound()) { 1644 if (label->IsBound()) {
1635 const int64_t dest = label->Position() - buffer_.Size(); 1645 const int64_t dest = label->Position() - buffer_.Size();
1636 if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) { 1646 if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) {
1637 if (cond == AL) { 1647 if (cond == AL) {
1638 // If the condition is AL, we must always branch to dest. There is 1648 // If the condition is AL, we must always branch to dest. There is
1639 // no need for a guard branch. 1649 // no need for a guard branch.
1640 b(dest); 1650 b(dest);
1641 } else { 1651 } else {
1642 EmitConditionalBranch( 1652 EmitConditionalBranchOp(
1643 op, InvertCondition(cond), 2 * Instr::kInstrSize); 1653 op, InvertCondition(cond), 2 * Instr::kInstrSize);
1644 b(dest); 1654 b(dest);
1645 } 1655 }
1646 } else { 1656 } else {
1647 EmitConditionalBranch(op, cond, dest); 1657 EmitConditionalBranchOp(op, cond, dest);
1648 } 1658 }
1649 } else { 1659 } else {
1650 const int64_t position = buffer_.Size(); 1660 const int64_t position = buffer_.Size();
1651 if (use_far_branches()) { 1661 if (use_far_branches()) {
1652 // When cond is AL, this guard branch will be rewritten as a nop when 1662 // When cond is AL, this guard branch will be rewritten as a nop when
1653 // the label is bound. We don't write it as a nop initially because it 1663 // the label is bound. We don't write it as a nop initially because it
1654 // makes the decoding code in Bind simpler. 1664 // makes the decoding code in Bind simpler.
1655 EmitConditionalBranch(op, InvertCondition(cond), 2 * Instr::kInstrSize); 1665 EmitConditionalBranchOp(
1666 op, InvertCondition(cond), 2 * Instr::kInstrSize);
1656 b(label->position_); 1667 b(label->position_);
1657 } else { 1668 } else {
1658 EmitConditionalBranch(op, cond, label->position_); 1669 EmitConditionalBranchOp(op, cond, label->position_);
1670 }
1671 label->LinkTo(position);
1672 }
1673 }
1674
1675 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt,
zra 2014/11/06 00:30:59 You also need to detect these instructions in Bind
1676 Label* label, OperandSize sz) {
1677 if (label->IsBound()) {
1678 const int64_t dest = label->Position() - buffer_.Size();
1679 if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) {
1680 EmitCompareAndBranchOp(
1681 op == CBZ ? CBNZ : CBZ, rt, 2 * Instr::kInstrSize, sz);
1682 b(dest);
1683 } else {
1684 EmitCompareAndBranchOp(op, rt, dest, sz);
1685 }
1686 } else {
1687 const int64_t position = buffer_.Size();
1688 if (use_far_branches()) {
1689 EmitCompareAndBranchOp(
1690 op == CBZ ? CBNZ : CBZ, rt, 2 * Instr::kInstrSize, sz);
1691 b(label->position_);
1692 } else {
1693 EmitCompareAndBranchOp(op, rt, label->position_, sz);
1659 } 1694 }
1660 label->LinkTo(position); 1695 label->LinkTo(position);
1661 } 1696 }
1662 } 1697 }
1663 1698
1664 bool CanEncodeImm26BranchOffset(int64_t offset) { 1699 bool CanEncodeImm26BranchOffset(int64_t offset) {
1665 ASSERT(Utils::IsAligned(offset, 4)); 1700 ASSERT(Utils::IsAligned(offset, 4));
1666 return Utils::IsInt(26, offset); 1701 return Utils::IsInt(26, offset);
1667 } 1702 }
1668 1703
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 Register value, 1933 Register value,
1899 Label* no_update); 1934 Label* no_update);
1900 1935
1901 DISALLOW_ALLOCATION(); 1936 DISALLOW_ALLOCATION();
1902 DISALLOW_COPY_AND_ASSIGN(Assembler); 1937 DISALLOW_COPY_AND_ASSIGN(Assembler);
1903 }; 1938 };
1904 1939
1905 } // namespace dart 1940 } // namespace dart
1906 1941
1907 #endif // VM_ASSEMBLER_ARM64_H_ 1942 #endif // VM_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698