| Index: runtime/vm/assembler_arm64.h
|
| ===================================================================
|
| --- runtime/vm/assembler_arm64.h (revision 40940)
|
| +++ runtime/vm/assembler_arm64.h (working copy)
|
| @@ -105,6 +105,9 @@
|
| Offset,
|
| PreIndex,
|
| PostIndex,
|
| + PairOffset,
|
| + PairPreIndex,
|
| + PairPostIndex,
|
| Reg,
|
| PCOffset,
|
| Unknown,
|
| @@ -132,14 +135,29 @@
|
| encoding_ =
|
| ((offset & 0x1ff) << kImm9Shift) |
|
| (static_cast<int32_t>(crn) << kRnShift);
|
| - } else {
|
| + } else if ((at == PreIndex) || (at == PostIndex)) {
|
| ASSERT(Utils::IsInt(9, offset));
|
| - ASSERT((at == PreIndex) || (at == PostIndex));
|
| int32_t idx = (at == PostIndex) ? B10 : (B11 | B10);
|
| encoding_ =
|
| idx |
|
| ((offset & 0x1ff) << kImm9Shift) |
|
| (static_cast<int32_t>(crn) << kRnShift);
|
| + } else {
|
| + ASSERT((at == PairOffset) || (at == PairPreIndex) ||
|
| + (at == PairPostIndex));
|
| + ASSERT(Utils::IsInt(7 + scale, offset) &&
|
| + (offset == ((offset >> scale) << scale)));
|
| + int32_t idx = 0;
|
| + switch (at) {
|
| + case PairPostIndex: idx = B23; break;
|
| + case PairPreIndex: idx = B24 | B23; break;
|
| + case PairOffset: idx = B24; break;
|
| + default: UNREACHABLE(); break;
|
| + }
|
| + encoding_ =
|
| + idx |
|
| + (((offset >> scale) << kImm7Shift) & kImm7Mask) |
|
| + (static_cast<int32_t>(crn) << kRnShift);
|
| }
|
| type_ = at;
|
| base_ = crn;
|
| @@ -161,9 +179,14 @@
|
| } else if (at == PCOffset) {
|
| return Utils::IsInt(21, offset) &&
|
| (offset == ((offset >> 2) << 2));
|
| + } else if ((at == PreIndex) || (at == PostIndex)) {
|
| + return Utils::IsInt(9, offset);
|
| } else {
|
| - ASSERT((at == PreIndex) || (at == PostIndex));
|
| - return Utils::IsInt(9, offset);
|
| + ASSERT((at == PairOffset) || (at == PairPreIndex) ||
|
| + (at == PairPostIndex));
|
| + const int32_t scale = Log2OperandSizeBytes(sz);
|
| + return (Utils::IsInt(7 + scale, offset) &&
|
| + (offset == ((offset >> scale) << scale)));
|
| }
|
| }
|
|
|
| @@ -177,6 +200,13 @@
|
| return addr;
|
| }
|
|
|
| + static Address Pair(Register rn,
|
| + int32_t offset = 0,
|
| + AddressType at = PairOffset,
|
| + OperandSize sz = kDoubleWord) {
|
| + return Address(rn, offset, at, sz);
|
| + }
|
| +
|
| // This addressing mode does not exist.
|
| static Address PC(Register r);
|
|
|
| @@ -630,6 +660,9 @@
|
|
|
| // Loads and Stores.
|
| void ldr(Register rt, Address a, OperandSize sz = kDoubleWord) {
|
| + ASSERT((a.type() != Address::PairOffset) &&
|
| + (a.type() != Address::PairPostIndex) &&
|
| + (a.type() != Address::PairPreIndex));
|
| if (a.type() == Address::PCOffset) {
|
| ASSERT(sz == kDoubleWord);
|
| EmitLoadRegLiteral(LDRpc, rt, a, sz);
|
| @@ -648,9 +681,25 @@
|
| }
|
| }
|
| void str(Register rt, Address a, OperandSize sz = kDoubleWord) {
|
| + ASSERT((a.type() != Address::PairOffset) &&
|
| + (a.type() != Address::PairPostIndex) &&
|
| + (a.type() != Address::PairPreIndex));
|
| EmitLoadStoreReg(STR, rt, a, sz);
|
| }
|
|
|
| + void ldp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
|
| + ASSERT((a.type() == Address::PairOffset) ||
|
| + (a.type() == Address::PairPostIndex) ||
|
| + (a.type() == Address::PairPreIndex));
|
| + EmitLoadStoreRegPair(LDP, rt, rt2, a, sz);
|
| + }
|
| + void stp(Register rt, Register rt2, Address a, OperandSize sz = kDoubleWord) {
|
| + ASSERT((a.type() == Address::PairOffset) ||
|
| + (a.type() == Address::PairPostIndex) ||
|
| + (a.type() == Address::PairPreIndex));
|
| + EmitLoadStoreRegPair(STP, rt, rt2, a, sz);
|
| + }
|
| +
|
| // Conditional select.
|
| void csel(Register rd, Register rn, Register rm, Condition cond) {
|
| EmitConditionalSelect(CSEL, rd, rn, rm, cond, kDoubleWord);
|
| @@ -1601,6 +1650,29 @@
|
| Emit(encoding);
|
| }
|
|
|
| + void EmitLoadStoreRegPair(LoadStoreRegPairOp op,
|
| + Register rt, Register rt2, Address a,
|
| + OperandSize sz) {
|
| + ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord));
|
| + ASSERT((rt != CSP) && (rt != R31));
|
| + ASSERT((rt2 != CSP) && (rt2 != R31));
|
| + const Register crt = ConcreteRegister(rt);
|
| + const Register crt2 = ConcreteRegister(rt2);
|
| + int32_t opc;
|
| + switch (sz) {
|
| + case kDoubleWord: opc = B31; break;
|
| + case kWord: opc = B30; break;
|
| + case kUnsignedWord: opc = 0; break;
|
| + default: UNREACHABLE(); break;
|
| + }
|
| + const int32_t encoding =
|
| + opc | op |
|
| + (static_cast<int32_t>(crt) << kRtShift) |
|
| + (static_cast<int32_t>(crt2) << kRt2Shift) |
|
| + a.encoding();
|
| + Emit(encoding);
|
| + }
|
| +
|
| void EmitPCRelOp(PCRelOp op, Register rd, const Immediate& imm) {
|
| ASSERT(Utils::IsInt(21, imm.value()));
|
| ASSERT((rd != R31) && (rd != CSP));
|
|
|