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

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

Issue 630033003: Adds ldp and stp instructions to ARM64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 months 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 encoding_ = other.encoding_; 98 encoding_ = other.encoding_;
99 type_ = other.type_; 99 type_ = other.type_;
100 base_ = other.base_; 100 base_ = other.base_;
101 return *this; 101 return *this;
102 } 102 }
103 103
104 enum AddressType { 104 enum AddressType {
105 Offset, 105 Offset,
106 PreIndex, 106 PreIndex,
107 PostIndex, 107 PostIndex,
108 PairOffset,
109 PairPreIndex,
110 PairPostIndex,
108 Reg, 111 Reg,
109 PCOffset, 112 PCOffset,
110 Unknown, 113 Unknown,
111 }; 114 };
112 115
113 // Offset is in bytes. For the unsigned imm12 case, we unscale based on the 116 // Offset is in bytes. For the unsigned imm12 case, we unscale based on the
114 // operand size, and assert that offset is aligned accordingly. 117 // operand size, and assert that offset is aligned accordingly.
115 // For the smaller signed imm9 case, the offset is the number of bytes, but 118 // For the smaller signed imm9 case, the offset is the number of bytes, but
116 // is unscaled. 119 // is unscaled.
117 Address(Register rn, int32_t offset = 0, AddressType at = Offset, 120 Address(Register rn, int32_t offset = 0, AddressType at = Offset,
118 OperandSize sz = kDoubleWord) { 121 OperandSize sz = kDoubleWord) {
119 ASSERT((rn != R31) && (rn != ZR)); 122 ASSERT((rn != R31) && (rn != ZR));
120 ASSERT(CanHoldOffset(offset, at, sz)); 123 ASSERT(CanHoldOffset(offset, at, sz));
121 const Register crn = ConcreteRegister(rn); 124 const Register crn = ConcreteRegister(rn);
122 const int32_t scale = Log2OperandSizeBytes(sz); 125 const int32_t scale = Log2OperandSizeBytes(sz);
123 if ((at == Offset) && 126 if ((at == Offset) &&
124 Utils::IsUint(12 + scale, offset) && 127 Utils::IsUint(12 + scale, offset) &&
125 (offset == ((offset >> scale) << scale))) { 128 (offset == ((offset >> scale) << scale))) {
126 encoding_ = 129 encoding_ =
127 B24 | 130 B24 |
128 ((offset >> scale) << kImm12Shift) | 131 ((offset >> scale) << kImm12Shift) |
129 (static_cast<int32_t>(crn) << kRnShift); 132 (static_cast<int32_t>(crn) << kRnShift);
130 } else if ((at == Offset) && 133 } else if ((at == Offset) &&
131 Utils::IsInt(9, offset)) { 134 Utils::IsInt(9, offset)) {
132 encoding_ = 135 encoding_ =
133 ((offset & 0x1ff) << kImm9Shift) | 136 ((offset & 0x1ff) << kImm9Shift) |
134 (static_cast<int32_t>(crn) << kRnShift); 137 (static_cast<int32_t>(crn) << kRnShift);
135 } else { 138 } else if ((at == PreIndex) || (at == PostIndex)) {
136 ASSERT(Utils::IsInt(9, offset)); 139 ASSERT(Utils::IsInt(9, offset));
137 ASSERT((at == PreIndex) || (at == PostIndex));
138 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10); 140 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10);
139 encoding_ = 141 encoding_ =
140 idx | 142 idx |
141 ((offset & 0x1ff) << kImm9Shift) | 143 ((offset & 0x1ff) << kImm9Shift) |
142 (static_cast<int32_t>(crn) << kRnShift); 144 (static_cast<int32_t>(crn) << kRnShift);
145 } else {
146 ASSERT((at == PairOffset) || (at == PairPreIndex) ||
147 (at == PairPostIndex));
148 ASSERT(Utils::IsInt(7 + scale, offset) &&
149 (offset == ((offset >> scale) << scale)));
150 int32_t idx = 0;
151 switch (at) {
152 case PairPostIndex: idx = B23; break;
153 case PairPreIndex: idx = B24 | B23; break;
154 case PairOffset: idx = B24; break;
155 default: UNREACHABLE(); break;
156 }
157 encoding_ =
158 idx |
159 (((offset >> scale) << kImm7Shift) & kImm7Mask) |
160 (static_cast<int32_t>(crn) << kRnShift);
143 } 161 }
144 type_ = at; 162 type_ = at;
145 base_ = crn; 163 base_ = crn;
146 } 164 }
147 165
148 // This addressing mode does not exist. 166 // This addressing mode does not exist.
149 Address(Register rn, Register offset, AddressType at, 167 Address(Register rn, Register offset, AddressType at,
150 OperandSize sz = kDoubleWord); 168 OperandSize sz = kDoubleWord);
151 169
152 static bool CanHoldOffset(int32_t offset, AddressType at = Offset, 170 static bool CanHoldOffset(int32_t offset, AddressType at = Offset,
153 OperandSize sz = kDoubleWord) { 171 OperandSize sz = kDoubleWord) {
154 if (at == Offset) { 172 if (at == Offset) {
155 // Offset fits in 12 bit unsigned and has right alignment for sz, 173 // Offset fits in 12 bit unsigned and has right alignment for sz,
156 // or fits in 9 bit signed offset with no alignment restriction. 174 // or fits in 9 bit signed offset with no alignment restriction.
157 const int32_t scale = Log2OperandSizeBytes(sz); 175 const int32_t scale = Log2OperandSizeBytes(sz);
158 return (Utils::IsUint(12 + scale, offset) && 176 return (Utils::IsUint(12 + scale, offset) &&
159 (offset == ((offset >> scale) << scale))) || 177 (offset == ((offset >> scale) << scale))) ||
160 (Utils::IsInt(9, offset)); 178 (Utils::IsInt(9, offset));
161 } else if (at == PCOffset) { 179 } else if (at == PCOffset) {
162 return Utils::IsInt(21, offset) && 180 return Utils::IsInt(21, offset) &&
163 (offset == ((offset >> 2) << 2)); 181 (offset == ((offset >> 2) << 2));
182 } else if ((at == PreIndex) || (at == PostIndex)) {
183 return Utils::IsInt(9, offset);
164 } else { 184 } else {
165 ASSERT((at == PreIndex) || (at == PostIndex)); 185 ASSERT((at == PairOffset) || (at == PairPreIndex) ||
166 return Utils::IsInt(9, offset); 186 (at == PairPostIndex));
187 const int32_t scale = Log2OperandSizeBytes(sz);
188 return (Utils::IsInt(7 + scale, offset) &&
189 (offset == ((offset >> scale) << scale)));
167 } 190 }
168 } 191 }
169 192
170 // PC-relative load address. 193 // PC-relative load address.
171 static Address PC(int32_t pc_off) { 194 static Address PC(int32_t pc_off) {
172 ASSERT(CanHoldOffset(pc_off, PCOffset)); 195 ASSERT(CanHoldOffset(pc_off, PCOffset));
173 Address addr; 196 Address addr;
174 addr.encoding_ = (((pc_off >> 2) << kImm19Shift) & kImm19Mask); 197 addr.encoding_ = (((pc_off >> 2) << kImm19Shift) & kImm19Mask);
175 addr.base_ = kNoRegister; 198 addr.base_ = kNoRegister;
176 addr.type_ = PCOffset; 199 addr.type_ = PCOffset;
177 return addr; 200 return addr;
178 } 201 }
179 202
203 static Address Pair(Register rn,
204 int32_t offset = 0,
205 AddressType at = PairOffset,
206 OperandSize sz = kDoubleWord) {
207 return Address(rn, offset, at, sz);
208 }
209
180 // This addressing mode does not exist. 210 // This addressing mode does not exist.
181 static Address PC(Register r); 211 static Address PC(Register r);
182 212
183 enum Scaling { 213 enum Scaling {
184 Unscaled, 214 Unscaled,
185 Scaled, 215 Scaled,
186 }; 216 };
187 217
188 // Base register rn with offset rm. rm is sign-extended according to ext. 218 // Base register rn with offset rm. rm is sign-extended according to ext.
189 // If ext is UXTX, rm may be optionally scaled by the 219 // If ext is UXTX, rm may be optionally scaled by the
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); 653 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord);
624 } 654 }
625 void movz(Register rd, const Immediate& imm, int hw_idx) { 655 void movz(Register rd, const Immediate& imm, int hw_idx) {
626 ASSERT(rd != CSP); 656 ASSERT(rd != CSP);
627 const Register crd = ConcreteRegister(rd); 657 const Register crd = ConcreteRegister(rd);
628 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); 658 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord);
629 } 659 }
630 660
631 // Loads and Stores. 661 // Loads and Stores.
632 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) { 662 void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) {
663 ASSERT((a.type() != Address::PairOffset) &&
664 (a.type() != Address::PairPostIndex) &&
665 (a.type() != Address::PairPreIndex));
633 if (a.type() == Address::PCOffset) { 666 if (a.type() == Address::PCOffset) {
634 ASSERT(sz == kDoubleWord); 667 ASSERT(sz == kDoubleWord);
635 EmitLoadRegLiteral(LDRpc, rt, a, sz); 668 EmitLoadRegLiteral(LDRpc, rt, a, sz);
636 } else { 669 } else {
637 // If we are doing pre-/post-indexing, and the base and result registers 670 // If we are doing pre-/post-indexing, and the base and result registers
638 // are the same, then the result of the load will be clobbered by the 671 // are the same, then the result of the load will be clobbered by the
639 // writeback, which is unlikely to be useful. 672 // writeback, which is unlikely to be useful.
640 ASSERT(((a.type() != Address::PreIndex) && 673 ASSERT(((a.type() != Address::PreIndex) &&
641 (a.type() != Address::PostIndex)) || 674 (a.type() != Address::PostIndex)) ||
642 (rt != a.base())); 675 (rt != a.base()));
643 if (IsSignedOperand(sz)) { 676 if (IsSignedOperand(sz)) {
644 EmitLoadStoreReg(LDRS, rt, a, sz); 677 EmitLoadStoreReg(LDRS, rt, a, sz);
645 } else { 678 } else {
646 EmitLoadStoreReg(LDR, rt, a, sz); 679 EmitLoadStoreReg(LDR, rt, a, sz);
647 } 680 }
648 } 681 }
649 } 682 }
650 void str(Register rt, Address a, OperandSize sz = kDoubleWord) { 683 void str(Register rt, Address a, OperandSize sz = kDoubleWord) {
684 ASSERT((a.type() != Address::PairOffset) &&
685 (a.type() != Address::PairPostIndex) &&
686 (a.type() != Address::PairPreIndex));
651 EmitLoadStoreReg(STR, rt, a, sz); 687 EmitLoadStoreReg(STR, rt, a, sz);
652 } 688 }
653 689
690 void ldp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
691 ASSERT((a.type() == Address::PairOffset) ||
692 (a.type() == Address::PairPostIndex) ||
693 (a.type() == Address::PairPreIndex));
694 EmitLoadStoreRegPair(LDP, rt, rt2, a, sz);
695 }
696 void stp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
697 ASSERT((a.type() == Address::PairOffset) ||
698 (a.type() == Address::PairPostIndex) ||
699 (a.type() == Address::PairPreIndex));
700 EmitLoadStoreRegPair(STP, rt, rt2, a, sz);
701 }
702
654 // Conditional select. 703 // Conditional select.
655 void csel(Register rd, Register rn, Register rm, Condition cond) { 704 void csel(Register rd, Register rn, Register rm, Condition cond) {
656 EmitConditionalSelect(CSEL, rd, rn, rm, cond, kDoubleWord); 705 EmitConditionalSelect(CSEL, rd, rn, rm, cond, kDoubleWord);
657 } 706 }
658 void csinc(Register rd, Register rn, Register rm, Condition cond) { 707 void csinc(Register rd, Register rn, Register rm, Condition cond) {
659 EmitConditionalSelect(CSINC, rd, rn, rm, cond, kDoubleWord); 708 EmitConditionalSelect(CSINC, rd, rn, rm, cond, kDoubleWord);
660 } 709 }
661 void cinc(Register rd, Register rn, Condition cond) { 710 void cinc(Register rd, Register rn, Condition cond) {
662 csinc(rd, rn, rn, InvertCondition(cond)); 711 csinc(rd, rn, rn, InvertCondition(cond));
663 } 712 }
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 ASSERT((rt != CSP) && (rt != R31)); 1643 ASSERT((rt != CSP) && (rt != R31));
1595 const Register crt = ConcreteRegister(rt); 1644 const Register crt = ConcreteRegister(rt);
1596 const int32_t size = (sz == kDoubleWord) ? B30 : 0; 1645 const int32_t size = (sz == kDoubleWord) ? B30 : 0;
1597 const int32_t encoding = 1646 const int32_t encoding =
1598 op | size | 1647 op | size |
1599 (static_cast<int32_t>(crt) << kRtShift) | 1648 (static_cast<int32_t>(crt) << kRtShift) |
1600 a.encoding(); 1649 a.encoding();
1601 Emit(encoding); 1650 Emit(encoding);
1602 } 1651 }
1603 1652
1653 void EmitLoadStoreRegPair(LoadStoreRegPairOp op,
1654 Register rt, Register rt2, Address a,
1655 OperandSize sz) {
1656 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
1657 ASSERT((rt != CSP) && (rt != R31));
1658 ASSERT((rt2 != CSP) && (rt2 != R31));
1659 const Register crt = ConcreteRegister(rt);
1660 const Register crt2 = ConcreteRegister(rt2);
1661 int32_t opc;
1662 switch (sz) {
1663 case kDoubleWord: opc = B31; break;
1664 case kWord: opc = B30; break;
1665 case kUnsignedWord: opc = 0; break;
1666 default: UNREACHABLE(); break;
1667 }
1668 const int32_t encoding =
1669 opc | op |
1670 (static_cast<int32_t>(crt) << kRtShift) |
1671 (static_cast<int32_t>(crt2) << kRt2Shift) |
1672 a.encoding();
1673 Emit(encoding);
1674 }
1675
1604 void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) { 1676 void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) {
1605 ASSERT(Utils::IsInt(21, imm.value())); 1677 ASSERT(Utils::IsInt(21, imm.value()));
1606 ASSERT((rd != R31) && (rd != CSP)); 1678 ASSERT((rd != R31) && (rd != CSP));
1607 const Register crd = ConcreteRegister(rd); 1679 const Register crd = ConcreteRegister(rd);
1608 const int32_t loimm = (imm.value() & 0x3) << 29; 1680 const int32_t loimm = (imm.value() & 0x3) << 29;
1609 const int32_t hiimm = ((imm.value() >> 2) << kImm19Shift) & kImm19Mask; 1681 const int32_t hiimm = ((imm.value() >> 2) << kImm19Shift) & kImm19Mask;
1610 const int32_t encoding = 1682 const int32_t encoding =
1611 op | loimm | hiimm | 1683 op | loimm | hiimm |
1612 (static_cast<int32_t>(crd) << kRdShift); 1684 (static_cast<int32_t>(crd) << kRdShift);
1613 Emit(encoding); 1685 Emit(encoding);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 Register value, 1820 Register value,
1749 Label* no_update); 1821 Label* no_update);
1750 1822
1751 DISALLOW_ALLOCATION(); 1823 DISALLOW_ALLOCATION();
1752 DISALLOW_COPY_AND_ASSIGN(Assembler); 1824 DISALLOW_COPY_AND_ASSIGN(Assembler);
1753 }; 1825 };
1754 1826
1755 } // namespace dart 1827 } // namespace dart
1756 1828
1757 #endif // VM_ASSEMBLER_ARM64_H_ 1829 #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