Index: runtime/vm/assembler_mips.cc |
=================================================================== |
--- runtime/vm/assembler_mips.cc (revision 20565) |
+++ runtime/vm/assembler_mips.cc (working copy) |
@@ -76,6 +76,27 @@ |
} |
+void Assembler::LoadObject(Register rd, const Object& object) { |
+ // Smi's and VM heap objects are never relocated; do not use object pool. |
+ if (object.IsSmi()) { |
+ LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); |
+ } else if (object.InVMHeap()) { |
+ // Make sure that class CallPattern is able to decode this load immediate. |
+ int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); |
+ const uint16_t object_low = Utils::Low16Bits(object_raw); |
+ const uint16_t object_high = Utils::High16Bits(object_raw); |
+ lui(rd, Immediate(object_high)); |
+ ori(rd, rd, Immediate(object_low)); |
+ } else { |
+ // Make sure that class CallPattern is able to decode this load from the |
+ // object pool. |
+ const int32_t offset = |
+ Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; |
+ LoadWordFromPoolOffset(rd, offset); |
+ } |
+} |
+ |
+ |
int32_t Assembler::AddObject(const Object& obj) { |
ASSERT(obj.IsNotTemporaryScopedHandle()); |
ASSERT(obj.IsOld()); |
@@ -94,6 +115,107 @@ |
} |
+void Assembler::PushObject(const Object& object) { |
+ LoadObject(TMP, object); |
+ Push(TMP); |
+} |
+ |
+ |
+void Assembler::CompareObject(Register rd, Register rn, const Object& object) { |
+ ASSERT(rn != TMP); |
+ LoadObject(TMP, object); |
+ subu(rd, rn, TMP); |
+} |
+ |
+ |
+void Assembler::GetPC(Register rd) { |
+ Label next; |
+ |
+ mov(TMP, RA); // Save the return address. |
regis
2013/03/29 00:23:32
As mentioned, this may not always be necessary.
zra
2013/03/29 17:10:44
I have removed this function and inlined it.
|
+ bal(&next); // Branch and link to the next instruction. |
+ |
+ // This instruction is the return address for the bal, so rd will |
+ // have the PC of this mov instruction. |
+ Bind(&next); |
+ mov(rd, RA); |
regis
2013/03/29 00:23:32
Couldn't this mov be in the delay slot?
zra
2013/03/29 17:10:44
Done.
|
+ |
+ mov(RA, TMP); // Restore the return address. |
+ return; |
+} |
+ |
+ |
+void Assembler::EnterStubFrame() { |
+ // Push 0 as saved PC for stub frames. |
+ mov(TMP, RA); |
+ mov(RA, ZR); |
regis
2013/03/29 00:23:32
These moves are not required. No need to emulate A
zra
2013/03/29 17:10:44
Done.
|
+ |
+ addiu(SP, SP, Immediate(-3 * kWordSize)); |
+ sw(RA, Address(SP, 2 * kWordSize)); |
+ sw(FP, Address(SP, 1 * kWordSize)); |
+ sw(TMP, Address(SP, 0 * kWordSize)); |
regis
2013/03/29 00:23:32
I am not sure why you store the return address bel
zra
2013/03/29 17:10:44
Done.
|
+ |
+ addiu(FP, SP, Immediate(1 * kWordSize)); |
+} |
+ |
+ |
+void Assembler::LeaveStubFrame() { |
+ addiu(SP, FP, Immediate(-1 * kWordSize)); |
+ |
+ lw(RA, Address(SP, 0 * kWordSize)); |
+ lw(FP, Address(SP, 1 * kWordSize)); |
+ addiu(SP, SP, Immediate(3 * kWordSize)); |
regis
2013/03/29 00:23:32
And this one should be:
mov(SP, FP);
lw(FP, Addres
zra
2013/03/29 17:10:44
Done.
|
+} |
+ |
+ |
+void Assembler::EnterDartFrame(intptr_t frame_size) { |
+ const intptr_t offset = CodeSize(); |
+ |
+ // Save PC in frame for fast identification of corresponding code. |
+ GetPC(T0); |
regis
2013/03/29 00:23:32
You can get the PC after saving RA in the frame an
zra
2013/03/29 17:10:44
Done.
|
+ |
+ addiu(SP, SP, Immediate(-4 * kWordSize)); |
+ sw(T0, Address(SP, 3 * kWordSize)); |
+ sw(RA, Address(SP, 2 * kWordSize)); |
+ sw(FP, Address(SP, 1 * kWordSize)); |
+ sw(PP, Address(SP, 0 * kWordSize)); |
+ |
+ // Set FP to the saved previous FP. |
+ addiu(FP, SP, Immediate(kWordSize)); |
+ |
+ if (offset != 0) { |
+ // Adjust saved PC for any intrinsic code that could have been generated |
+ // before a frame is created. Use PP as temp register. |
+ lw(PP, Address(FP, 2 * kWordSize)); |
+ addiu(PP, PP, Immediate(-offset)); |
+ sw(PP, Address(FP, 2 * kWordSize)); |
+ } |
+ |
+ // Grab the PC again for looking up the pool pointer. |
+ GetPC(T0); |
regis
2013/03/29 00:23:32
Not necessary. You still have the PC in T0.
zra
2013/03/29 17:10:44
Done.
|
+ |
+ // Setup pool pointer for this dart function. |
+ const intptr_t object_pool_pc_dist = |
+ Instructions::HeaderSize() - Instructions::object_pool_offset() + |
+ CodeSize() - (2 * Instr::kInstrSize); |
+ lw(PP, Address(T0 /* PC - 8 */, -object_pool_pc_dist)); |
+ |
+ // Reserve space for locals. |
+ addiu(SP, SP, Immediate(-frame_size)); |
+} |
+ |
+ |
+void Assembler::LeaveDartFrame() { |
+ addiu(SP, FP, Immediate(-kWordSize)); |
+ |
+ lw(RA, Address(SP, 2 * kWordSize)); |
+ lw(FP, Address(SP, 1 * kWordSize)); |
+ lw(PP, Address(SP, 0 * kWordSize)); |
+ |
+ // Adjust SP for PC pushed in EnterDartFrame. |
+ addiu(SP, SP, Immediate(4 * kWordSize)); |
+} |
+ |
+ |
int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
if (object_pool_.IsNull()) { |
// The object pool cannot be used in the vm isolate. |