| Index: runtime/vm/assembler_mips.cc
|
| ===================================================================
|
| --- runtime/vm/assembler_mips.cc (revision 25483)
|
| +++ runtime/vm/assembler_mips.cc (working copy)
|
| @@ -17,6 +17,7 @@
|
| DECLARE_FLAG(bool, trace_sim);
|
| #endif
|
| DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
|
| +DEFINE_FLAG(bool, mips_far_branches, false, "Enable far branches on MIPS");
|
| DECLARE_FLAG(bool, inline_alloc);
|
|
|
| void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) {
|
| @@ -34,13 +35,30 @@
|
| ASSERT(!label->IsBound());
|
| int bound_pc = buffer_.Size();
|
| while (label->IsLinked()) {
|
| - const int32_t position = label->Position();
|
| - const int32_t next = buffer_.Load<int32_t>(position);
|
| - // Relative destination from an instruction after the branch.
|
| - const int32_t dest = bound_pc - (position + Instr::kInstrSize);
|
| - const int32_t encoded = Assembler::EncodeBranchOffset(dest, next);
|
| - buffer_.Store<int32_t>(position, encoded);
|
| - label->position_ = Assembler::DecodeBranchOffset(next);
|
| + if (FLAG_mips_far_branches) {
|
| + const int32_t position = label->Position();
|
| + const int32_t high = buffer_.Load<int32_t>(position);
|
| + const int32_t low = buffer_.Load<int32_t>(position + Instr::kInstrSize);
|
| +
|
| + // Relative destination from an instruction after the branch.
|
| + const int32_t dest = bound_pc - (position + 7 * Instr::kInstrSize);
|
| + const int32_t encoded_low =
|
| + Assembler::EncodeLoadImmediate(dest & kBranchOffsetMask, low);
|
| + const int32_t encoded_high =
|
| + Assembler::EncodeLoadImmediate(dest >> 16, high);
|
| +
|
| + buffer_.Store<int32_t>(position, encoded_high);
|
| + buffer_.Store<int32_t>(position + Instr::kInstrSize, encoded_low);
|
| + label->position_ = Assembler::DecodeLoadImmediate(low, high);
|
| + } else {
|
| + const int32_t position = label->Position();
|
| + const int32_t next = buffer_.Load<int32_t>(position);
|
| + // Relative destination from an instruction after the branch.
|
| + const int32_t dest = bound_pc - (position + Instr::kInstrSize);
|
| + const int32_t encoded = Assembler::EncodeBranchOffset(dest, next);
|
| + buffer_.Store<int32_t>(position, encoded);
|
| + label->position_ = Assembler::DecodeBranchOffset(next);
|
| + }
|
| }
|
| label->BindTo(bound_pc);
|
| delay_slot_available_ = false;
|
| @@ -64,6 +82,16 @@
|
| }
|
|
|
|
|
| +int32_t Assembler::DecodeLoadImmediate(int32_t low, int32_t high) {
|
| + return (((high & kBranchOffsetMask) << 16) | (low & kBranchOffsetMask));
|
| +}
|
| +
|
| +
|
| +int32_t Assembler::EncodeLoadImmediate(int32_t dest, int32_t instr) {
|
| + return ((instr & ~kBranchOffsetMask) | (dest & kBranchOffsetMask));
|
| +}
|
| +
|
| +
|
| void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) {
|
| ASSERT(rd != PP);
|
| if (Address::CanHoldOffset(offset)) {
|
| @@ -231,8 +259,8 @@
|
| // if the bit is not set. We can't destroy the object.
|
| nor(TMP1, ZR, object);
|
| and_(TMP1, value, TMP1);
|
| - andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset));
|
| - beq(TMP1, ZR, no_update);
|
| + andi(CMPRES1, TMP1, Immediate(kNewObjectAlignmentOffset));
|
| + beq(CMPRES1, ZR, no_update);
|
| }
|
|
|
|
|
| @@ -245,10 +273,10 @@
|
| sll(TMP1, value, kObjectAlignmentLog2 - 1);
|
| and_(TMP1, value, TMP1);
|
| // And the result with the negated space bit of the object.
|
| - nor(CMPRES, ZR, object);
|
| - and_(TMP1, TMP1, CMPRES);
|
| - andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset));
|
| - beq(TMP1, ZR, no_update);
|
| + nor(CMPRES1, ZR, object);
|
| + and_(TMP1, TMP1, CMPRES1);
|
| + andi(CMPRES1, TMP1, Immediate(kNewObjectAlignmentOffset));
|
| + beq(CMPRES1, ZR, no_update);
|
| }
|
|
|
|
|
| @@ -359,15 +387,13 @@
|
| sw(PP, Address(SP, 0 * kWordSize));
|
| addiu(FP, SP, Immediate(1 * kWordSize));
|
| // Setup pool pointer for this stub.
|
| - Label next;
|
| - bal(&next);
|
| - delay_slot()->mov(TMP1, RA);
|
|
|
| + GetNextPC(TMP1, false); // TMP1 gets the address of the next instruction.
|
| +
|
| const intptr_t object_pool_pc_dist =
|
| Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| CodeSize();
|
|
|
| - Bind(&next);
|
| lw(PP, Address(TMP1, -object_pool_pc_dist));
|
| } else {
|
| addiu(SP, SP, Immediate(-3 * kWordSize));
|
| @@ -465,20 +491,13 @@
|
| sw(FP, Address(SP, 1 * kWordSize));
|
| sw(PP, Address(SP, 0 * kWordSize));
|
|
|
| - Label next;
|
| - // Branch and link to the instruction after the delay slot to get the PC.
|
| - bal(&next);
|
| - // RA is the address of the sw instruction below. Save it in T0.
|
| - delay_slot()->mov(TMP1, RA);
|
| + GetNextPC(TMP1, false); // TMP1 gets the address of the next instruction.
|
|
|
| // Calculate the offset of the pool pointer from the PC.
|
| const intptr_t object_pool_pc_dist =
|
| Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| CodeSize();
|
|
|
| - // TMP1 has the address of the next instruction.
|
| - Bind(&next);
|
| -
|
| // Save PC in frame for fast identification of corresponding code.
|
| AddImmediate(TMP1, -offset);
|
| sw(TMP1, Address(SP, 3 * kWordSize));
|
| @@ -501,12 +520,9 @@
|
| // allocate. We must also set up the pool pointer for the function.
|
| void Assembler::EnterOsrFrame(intptr_t extra_size) {
|
| Comment("EnterOsrFrame");
|
| - Label next;
|
| - // Branch and link to the instruction after the delay slot to get the PC.
|
| - bal(&next);
|
| - // RA is the address of the sw instruction below. Save it in T0.
|
| - delay_slot()->mov(TMP, RA);
|
|
|
| + GetNextPC(TMP, false); // TMP gets the address of the next instruction.
|
| +
|
| // The runtime system assumes that the code marker address is
|
| // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no
|
| // code to set up the frame pointer, etc., the address needs to be adjusted.
|
| @@ -516,9 +532,6 @@
|
| Instructions::HeaderSize() - Instructions::object_pool_offset() +
|
| CodeSize();
|
|
|
| - // temp has the address of the next instruction.
|
| - Bind(&next);
|
| -
|
| // Adjust PC by the offset, and store it in the stack frame.
|
| AddImmediate(TMP, TMP, offset);
|
| sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
|
|
|