Chromium Code Reviews| Index: runtime/vm/assembler_arm64.h |
| =================================================================== |
| --- runtime/vm/assembler_arm64.h (revision 34800) |
| +++ runtime/vm/assembler_arm64.h (working copy) |
| @@ -69,23 +69,83 @@ |
| class Address : public ValueObject { |
| public: |
| Address(const Address& other) |
| - : ValueObject(), encoding_(other.encoding_) { |
| + : ValueObject(), |
| + encoding_(other.encoding_), |
| + type_(other.type_), |
| + base_(other.base_) { |
| } |
| Address& operator=(const Address& other) { |
| encoding_ = other.encoding_; |
| + type_ = other.type_; |
| + base_ = other.base_; |
| return *this; |
| } |
| - Address(Register rn, int32_t offset = 0) { |
| - ASSERT(Utils::IsAbsoluteUint(12, offset)); |
| - encoding_ = -1; |
| + enum AddressType { |
| + Offset, |
| + PreIndex, |
| + PostIndex, |
| + Reg, |
| + }; |
| + |
| + // Offset is in bytes. We translate to number of operands for the larger |
| + // unsigned imm12 case based on the OperandSize. For the smaller signed |
| + // imm9 case, the offset is the number of bytes, but is unscaled. |
|
regis
2014/04/07 23:38:19
I do not understand "We translate to number of ope
zra
2014/04/08 15:14:13
Tried to clarify. Also added an assert.
|
| + Address(Register rn, int32_t offset = 0, AddressType at = Offset, |
| + OperandSize sz = kDoubleWord) { |
| + ASSERT((rn != R31) && (rn != ZR)); |
| + const Register crn = ConcreteRegister(rn); |
| + const int32_t scale = Log2OperandSizeBytes(sz); |
| + if (Utils::IsUint(12 + scale, offset) && (at == Offset)) { |
| + encoding_ = |
| + B24 | |
| + ((offset >> scale) << kImm12Shift) | |
| + (static_cast<int32_t>(crn) << kRnShift); |
| + } else { |
| + 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); |
| + } |
| + type_ = at; |
| + base_ = crn; |
| } |
| + // TODO(zra): Write CanHoldOffset(int32_t off, AddressType, OperandSize). |
| + // TODO(zra): Write constructor for PC-relative load address. |
| + |
| + // Base register rn with offset rm. rm is sign-extended according to ext. |
| + // If ext is UXTX, rm may be optionally scaled by the |
| + // Log2OperandSize (specified by the instruction). |
| + Address(Register rn, Register rm, Extend ext = UXTX, bool scaled = false) { |
| + ASSERT((rn != R31) && (rn != ZR)); |
| + ASSERT((rm != R31) && (rm != SP)); |
| + ASSERT(!scaled || (ext == UXTX)); // Can only scale when ext = UXTX. |
| + ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); |
| + const Register crn = ConcreteRegister(rn); |
| + const Register crm = ConcreteRegister(rm); |
| + const int32_t s = scaled ? B12 : 0; |
| + encoding_ = |
| + B21 | B11 | s | |
| + (static_cast<int32_t>(crn) << kRnShift) | |
| + (static_cast<int32_t>(crm) << kRmShift) | |
| + (static_cast<int32_t>(ext) << kExtendTypeShift); |
| + type_ = Reg; |
| + base_ = crn; |
| + } |
| + |
| private: |
| uint32_t encoding() const { return encoding_; } |
| + AddressType type() const { return type_; } |
| + Register base() const { return base_; } |
| uint32_t encoding_; |
| + AddressType type_; |
| + Register base_; |
| friend class Assembler; |
| }; |
| @@ -288,6 +348,19 @@ |
| EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); |
| } |
| + // Loads and Stores. |
| + void ldr(Register rt, Address a) { |
| + // If we are doing pre-/post-indexing, and the base and result registers |
| + // are the same, then the result of the load will be clobbered by the |
| + // writeback, which is unlikely to be useful. |
| + ASSERT(((a.type() != Address::PreIndex) && |
| + (a.type() != Address::PostIndex)) || |
| + (rt != a.base())); |
| + EmitLoadStoreReg(LDR, rt, a, kDoubleWord); |
| + } |
| + void str(Register rt, Address a) { |
| + EmitLoadStoreReg(STR, rt, a, kDoubleWord); |
| + } |
| // Function return. |
| void ret(Register rn = R30) { |
| @@ -383,6 +456,16 @@ |
| Emit(encoding); |
| } |
| + void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, |
| + OperandSize sz) { |
| + const int32_t size = Log2OperandSizeBytes(sz); |
| + const int32_t encoding = |
| + op | (size << kSzShift) | |
| + (static_cast<int32_t>(rt) << kRtShift) | |
| + a.encoding(); |
| + Emit(encoding); |
| + } |
| + |
| DISALLOW_ALLOCATION(); |
| DISALLOW_COPY_AND_ASSIGN(Assembler); |
| }; |