Chromium Code Reviews| Index: runtime/vm/assembler_arm64.h |
| =================================================================== |
| --- runtime/vm/assembler_arm64.h (revision 35380) |
| +++ runtime/vm/assembler_arm64.h (working copy) |
| @@ -155,17 +155,24 @@ |
| return addr; |
| } |
| + enum Scaling { |
| + Unscaled, |
| + Scaled, |
| + }; |
| + |
| // 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) { |
| + Address(Register rn, Register rm, |
| + Extend ext = UXTX, Scaling scale = Unscaled) { |
| ASSERT((rn != R31) && (rn != ZR)); |
| ASSERT((rm != R31) && (rm != SP)); |
| - ASSERT(!scaled || (ext == UXTX)); // Can only scale when ext = UXTX. |
| + // Can only scale when ext = UXTX. |
| + ASSERT((scale != Scaled) || (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; |
| + const int32_t s = (scale == Scaled) ? B12 : 0; |
| encoding_ = |
| B21 | B11 | s | |
| (static_cast<int32_t>(crn) << kRnShift) | |
| @@ -543,6 +550,11 @@ |
| EmitLoadStoreReg(STR, rt, a, sz); |
| } |
| + // Conditional select. |
| + void csel(Register rd, Register rn, Register rm, Condition cond) { |
| + EmitCoditionalSelect(CSEL, rd, rn, rm, cond, kDoubleWord); |
| + } |
| + |
| // Comparison. |
| // rn cmp o. |
| // For add and sub, to use SP for rn, o must be of type Operand::Extend. |
| @@ -619,8 +631,8 @@ |
| } |
| void TagAndPushPP() { |
| // Add the heap object tag back to PP before putting it on the stack. |
| - add(PP, PP, Operand(kHeapObjectTag)); |
| - str(PP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
| + add(TMP, PP, Operand(kHeapObjectTag)); |
| + str(TMP, Address(SP, -1 * kWordSize, Address::PreIndex)); |
| } |
| void PopAndUntagPP() { |
| ldr(PP, Address(SP, 1 * kWordSize, Address::PostIndex)); |
| @@ -646,6 +658,9 @@ |
| void SmiUntag(Register reg) { |
| Asr(reg, reg, kSmiTagSize); |
| } |
| + void SmiTag(Register reg) { |
| + Lsl(reg, reg, kSmiTagSize); |
| + } |
| // Branching to ExternalLabels. |
| void BranchPatchable(const ExternalLabel* label, Register pp) { |
| @@ -713,6 +728,9 @@ |
| // Object pool, loading from pool, etc. |
| void LoadPoolPointer(Register pp); |
| + // Index of constant pool entries pointing to debugger stubs. |
| + static const int kBreakpointRuntimeCPIndex = 5; |
| + |
| enum Patchability { |
| kPatchable, |
| kNotPatchable, |
| @@ -737,6 +755,11 @@ |
| Push(TMP); |
| } |
| + void LoadClassId(Register result, Register object); |
| + void LoadClassById(Register result, Register class_id); |
| + void LoadClass(Register result, Register object); |
| + void CompareClassId(Register object, intptr_t class_id); |
| + |
| void EnterFrame(intptr_t frame_size); |
| void LeaveFrame(); |
| @@ -913,7 +936,7 @@ |
| } |
| int64_t DecodeImm19BranchOffset(int32_t instr) { |
| - const int32_t off = (((instr >> kImm19Shift) & kImm19Shift) << 13) >> 13; |
| + const int32_t off = (((instr & kImm19Mask) >> kImm19Shift) << 13) >> 11; |
| return static_cast<int64_t>(off); |
| } |
| @@ -944,7 +967,7 @@ |
| bool CanEncodeImm19BranchOffset(int64_t offset) { |
| ASSERT(Utils::IsAligned(offset, 4)); |
| - return Utils::IsInt(19, offset); |
| + return Utils::IsInt(21, offset); |
| } |
| // TODO(zra): Implement far branches. Requires loading large immediates. |
| @@ -1028,6 +1051,7 @@ |
| Register rd, Register rn, Register rm, |
| OperandSize sz) { |
| ASSERT((rd != SP) && (rn != SP) && (rm != SP)); |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
|
regis
2014/04/25 18:39:05
Should kUnsignedWord be allowed as well? (here and
zra
2014/04/25 18:54:23
Done.
|
| const Register crd = ConcreteRegister(rd); |
| const Register crn = ConcreteRegister(rn); |
| const Register crm = ConcreteRegister(rm); |
| @@ -1044,6 +1068,7 @@ |
| Register rd, Register rn, Register rm, Register ra, |
| OperandSize sz) { |
| ASSERT((rd != SP) && (rn != SP) && (rm != SP) && (ra != SP)); |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| const Register crd = ConcreteRegister(rd); |
| const Register crn = ConcreteRegister(rn); |
| const Register crm = ConcreteRegister(rm); |
| @@ -1058,6 +1083,24 @@ |
| Emit(encoding); |
| } |
| + void EmitCoditionalSelect(ConditionalSelectOp op, |
| + Register rd, Register rn, Register rm, |
| + Condition cond, OperandSize sz) { |
| + ASSERT((rd != SP) && (rn != SP) && (rm != SP)); |
| + ASSERT((sz == kDoubleWord) || (sz == kWord)); |
| + const Register crd = ConcreteRegister(rd); |
| + const Register crn = ConcreteRegister(rn); |
| + const Register crm = ConcreteRegister(rm); |
| + const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| + const int32_t encoding = |
| + op | size | |
| + (static_cast<int32_t>(crd) << kRdShift) | |
| + (static_cast<int32_t>(crn) << kRnShift) | |
| + (static_cast<int32_t>(crm) << kRmShift) | |
| + (static_cast<int32_t>(cond) << kSelCondShift); |
| + Emit(encoding); |
| + } |
| + |
| void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
| // Shorter filtering sequence that assumes that value is not a smi. |