Index: runtime/vm/instructions_arm64.cc |
=================================================================== |
--- runtime/vm/instructions_arm64.cc (revision 35975) |
+++ runtime/vm/instructions_arm64.cc (working copy) |
@@ -34,6 +34,11 @@ |
} |
+intptr_t InstructionPattern::OffsetFromPPIndex(intptr_t index) { |
+ return Array::element_offset(index); |
+} |
+ |
+ |
// Decodes a load sequence ending at 'end' (the last instruction of the load |
// sequence is the instruction before the one at end). Returns a pointer to |
// the first instruction in the sequence. Returns the register being loaded |
@@ -147,7 +152,10 @@ |
intptr_t* index) { |
// 1. ldr dst, [pp, offset] |
// or |
- // 2. movz dst, low_offset, 0 |
+ // 2. add dst, pp, #offset_hi12 |
+ // ldr dst [dst, #offset_lo12] |
+ // or |
+ // 3. movz dst, low_offset, 0 |
// movk dst, hi_offset, 1 (optional) |
// ldr dst, [pp, dst] |
uword start = end - Instr::kInstrSize; |
@@ -162,9 +170,17 @@ |
*reg = instr->RtField(); |
if (instr->Bit(24) == 1) { |
- // pp + scaled unsigned 12-bit immediate offset. |
+ // base + scaled unsigned 12-bit immediate offset. |
// Case 1. |
- offset = instr->Imm12Field() << 3; |
+ offset |= (instr->Imm12Field() << 3); |
+ if (instr->RnField() == *reg) { |
+ start -= Instr::kInstrSize; |
+ instr = Instr::At(start); |
+ ASSERT(instr->IsAddSubImmOp()); |
+ ASSERT(instr->RnField() == PP); |
+ ASSERT(instr->RdField() == *reg); |
+ offset |= (instr->Imm12Field() << 12); |
+ } |
} else { |
ASSERT(instr->Bits(10, 2) == 2); |
// We have to look at the preceding one or two instructions to find the |
@@ -198,6 +214,27 @@ |
} |
+// Encodes a load sequence ending at 'end'. Encodes a fixed length two |
+// instruction load from the pool pointer in PP using the destination |
+// register reg as a temporary for the base address. |
+// Assumes that the location has already been validated for patching. |
+void InstructionPattern::EncodeLoadWordFromPoolFixed(uword end, |
+ int32_t offset) { |
+ uword start = end - Instr::kInstrSize; |
+ Instr* instr = Instr::At(start); |
+ const int32_t upper12 = offset & 0x00fff000; |
+ const int32_t lower12 = offset & 0x00000fff; |
+ ASSERT((offset & 0xff000000) == 0); // Can't encode > 24 bits. |
+ ASSERT(((lower12 >> 3) << 3) == lower12); // 8-byte aligned. |
+ instr->SetImm12Bits(instr->InstructionBits(), lower12 >> 3); |
+ |
+ start -= Instr::kInstrSize; |
+ instr = Instr::At(start); |
+ instr->SetImm12Bits(instr->InstructionBits(), upper12 >> 12); |
+ instr->SetInstructionBits(instr->InstructionBits() | B22); |
+} |
+ |
+ |
RawICData* CallPattern::IcData() { |
if (ic_data_.IsNull()) { |
Register reg; |