Index: runtime/vm/assembler_arm.cc |
=================================================================== |
--- runtime/vm/assembler_arm.cc (revision 18162) |
+++ runtime/vm/assembler_arm.cc (working copy) |
@@ -72,7 +72,7 @@ |
const uint32_t offset_mask = (1 << 12) - 1; |
uint32_t offset = encoding_ & offset_mask; |
ASSERT(offset < (1 << 10)); // In the range 0 to +1020. |
- ASSERT(Utils::Utils::IsAligned(offset, 2)); // Multiple of 4. |
+ ASSERT(Utils::IsAligned(offset, 4)); // Multiple of 4. |
int mode = encoding_ & ((8|4|1) << 21); |
ASSERT((mode == Offset) || (mode == NegOffset)); |
uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); |
@@ -83,6 +83,17 @@ |
} |
+void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { |
+ ASSERT(Utils::IsAligned(data, 4)); |
+ ASSERT(Utils::IsAligned(length, 4)); |
+ const uword end = data + length; |
+ while (data < end) { |
+ *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; |
+ data += 4; |
+ } |
+} |
+ |
+ |
void Assembler::Emit(int32_t value) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
buffer_.Emit<int32_t>(value); |
@@ -1020,7 +1031,18 @@ |
void Assembler::LoadObject(Register rd, const Object& object) { |
- UNIMPLEMENTED(); |
+ // TODO(regis): If the object is never relocated (null, true, false, ...), |
+ // load as immediate. |
+ int32_t offset = AddObject(object); |
+ ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); |
+ if (Address::CanHoldLoadOffset(kLoadWord, offset)) { |
+ ldr(rd, Address(CP, offset)); |
+ } else { |
+ int32_t offset12_hi = offset & ~kOffset12Mask; // signed |
+ uint32_t offset12_lo = offset & kOffset12Mask; // unsigned |
+ AddConstant(rd, CP, offset12_hi); |
+ ldr(rd, Address(rd, offset12_lo)); |
+ } |
} |
@@ -1139,22 +1161,28 @@ |
void Assembler::Branch(const ExternalLabel* label) { |
- // TODO(regis): Revisit this code sequence. |
LoadImmediate(IP, label->address()); // Target address is never patched. |
mov(PC, ShifterOperand(IP)); |
} |
void Assembler::BranchLink(const ExternalLabel* label) { |
- // TODO(regis): Revisit this code sequence. |
- // Make sure that CodePatcher is able to patch this code sequence. |
+ // TODO(regis): Make sure that CodePatcher is able to patch the label referred |
+ // to by this code sequence. |
// For added code robustness, use 'blx lr' in a patchable sequence and |
// use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
- ldr(LR, Address(PC)); |
- Label skip; |
- b(&skip); |
- Emit(label->address()); // May get patched. |
- Bind(&skip); |
+ int32_t offset = AddExternalLabel(label); |
+ ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); |
+ if (Address::CanHoldLoadOffset(kLoadWord, offset)) { |
+ ldr(LR, Address(CP, offset)); |
+ } else { |
+ int32_t offset12_hi = offset & ~kOffset12Mask; // signed |
+ uint32_t offset12_lo = offset & kOffset12Mask; // unsigned |
+ // TODO(regis): Using AddConstant may generate too many sequences to be |
+ // easily decoded by CodePatcher. If so, use a simpler fixed sequence. |
+ AddConstant(LR, CP, offset12_hi); |
Ivan Posva
2013/02/06 23:33:50
As discussed, please do not use macros here as the
regis
2013/02/07 00:53:24
Done.
|
+ ldr(LR, Address(LR, offset12_lo)); |
+ } |
blx(LR); // Use blx instruction so that the return branch prediction works. |
} |
@@ -1494,6 +1522,32 @@ |
return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); |
} |
+ |
+int32_t Assembler::AddObject(const Object& obj) { |
+ for (int i = 0; i < objects_.Length(); i++) { |
Ivan Posva
2013/02/06 23:33:50
As discussed we should just return the offset here
regis
2013/02/07 00:53:24
Done.
|
+ if (objects_.At(i) == obj.raw()) { |
+ // TODO(regis): Skip over header. |
+ return /*kCodeObjectsHeaderSize +*/ 4*i; |
+ } |
+ } |
+ objects_.Add(obj); |
+ // TODO(regis): Skip over header. |
+ return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); |
+} |
+ |
+ |
+int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
+ const uword address = label->address(); |
+ ASSERT(Utils::IsAligned(address, 4)); |
+ // The address is stored in the object array as a RawSmi. |
+ const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); |
+ // Do not reuse an existing entry, since each reference may be patched |
+ // independently. |
+ objects_.Add(smi); |
+ // TODO(regis): Skip over header. |
+ return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); |
Ivan Posva
2013/02/06 23:33:50
ditto.
regis
2013/02/07 00:53:24
Done.
|
+} |
+ |
} // namespace dart |
#endif // defined TARGET_ARCH_ARM |