Index: src/mips/macro-assembler-mips.cc |
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc |
index d014660aa0200c5841ab1cc3acbdd4f1cd50b45d..990b4995f5ca785eb6f85a7e15fa9a09ef643905 100644 |
--- a/src/mips/macro-assembler-mips.cc |
+++ b/src/mips/macro-assembler-mips.cc |
@@ -1116,7 +1116,54 @@ void MacroAssembler::GetLeastBitsFromInt32(Register dst, |
(cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
+bool MacroAssembler::UseAbsoluteCodePointers() { |
+ if (is_trampoline_emitted()) { |
+ return true; |
+ } else { |
+ return false; |
+ } |
+} |
+ |
+ |
void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { |
+ BranchShort(offset, bdslot); |
+} |
+ |
+ |
+void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
+ BranchShort(offset, cond, rs, rt, bdslot); |
+} |
+ |
+ |
+void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { |
+ bool is_label_near = is_near(L); |
+ if (UseAbsoluteCodePointers() && !is_label_near) { |
+ Jr(L, bdslot); |
+ } else { |
+ BranchShort(L, bdslot); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
+ bool is_label_near = is_near(L); |
+ if (UseAbsoluteCodePointers() && !is_label_near) { |
+ Label skip; |
+ Condition neg_cond = NegateCondition(cond); |
+ BranchShort(&skip, neg_cond, rs, rt); |
+ Jr(L, bdslot); |
+ bind(&skip); |
+ } else { |
+ BranchShort(L, cond, rs, rt, bdslot); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) { |
b(offset); |
// Emit a nop in the branch delay slot if required. |
@@ -1125,9 +1172,9 @@ void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { |
} |
-void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
- const Operand& rt, |
- BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
BRANCH_ARGS_CHECK(cond, rs, rt); |
ASSERT(!rs.is(zero_reg)); |
Register r2 = no_reg; |
@@ -1199,7 +1246,8 @@ void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
break; |
case Uless: |
if (r2.is(zero_reg)) { |
- b(offset); |
+ // No code needs to be emitted. |
+ return; |
} else { |
sltu(scratch, rs, r2); |
bne(scratch, zero_reg, offset); |
@@ -1258,7 +1306,7 @@ void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
} else { |
r2 = scratch; |
li(r2, rt); |
- sltu(scratch, rs, r2); |
+ slt(scratch, rs, r2); |
beq(scratch, zero_reg, offset); |
} |
break; |
@@ -1311,7 +1359,8 @@ void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
break; |
case Uless: |
if (rt.imm32_ == 0) { |
- b(offset); |
+ // No code needs to be emitted. |
+ return; |
} else if (is_int16(rt.imm32_)) { |
sltiu(scratch, rs, rt.imm32_); |
bne(scratch, zero_reg, offset); |
@@ -1342,7 +1391,7 @@ void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
} |
-void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { |
// We use branch_offset as an argument for the branch instructions to be sure |
// it is called just before generating the branch instruction, as needed. |
@@ -1354,9 +1403,9 @@ void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { |
} |
-void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
- const Operand& rt, |
- BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
BRANCH_ARGS_CHECK(cond, rs, rt); |
int32_t offset; |
@@ -1444,8 +1493,8 @@ void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
break; |
case Uless: |
if (r2.is(zero_reg)) { |
- offset = shifted_branch_offset(L, false); |
- b(offset); |
+ // No code needs to be emitted. |
+ return; |
} else { |
sltu(scratch, rs, r2); |
offset = shifted_branch_offset(L, false); |
@@ -1510,7 +1559,7 @@ void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
} else { |
r2 = scratch; |
li(r2, rt); |
- sltu(scratch, rs, r2); |
+ slt(scratch, rs, r2); |
offset = shifted_branch_offset(L, false); |
beq(scratch, zero_reg, offset); |
} |
@@ -1574,8 +1623,8 @@ void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
break; |
case Uless: |
if (rt.imm32_ == 0) { |
- offset = shifted_branch_offset(L, false); |
- b(offset); |
+ // No code needs to be emitted. |
+ return; |
} else if (is_int16(rt.imm32_)) { |
sltiu(scratch, rs, rt.imm32_); |
offset = shifted_branch_offset(L, false); |
@@ -1612,11 +1661,49 @@ void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
} |
+void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { |
+ BranchAndLinkShort(offset, bdslot); |
+} |
+ |
+ |
+void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
+ BranchAndLinkShort(offset, cond, rs, rt, bdslot); |
+} |
+ |
+ |
+void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { |
+ bool is_label_near = is_near(L); |
+ if (UseAbsoluteCodePointers() && !is_label_near) { |
+ Jalr(L, bdslot); |
+ } else { |
+ BranchAndLinkShort(L, bdslot); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
+ bool is_label_near = is_near(L); |
+ if (UseAbsoluteCodePointers() && !is_label_near) { |
+ Label skip; |
+ Condition neg_cond = NegateCondition(cond); |
+ BranchShort(&skip, neg_cond, rs, rt); |
+ Jalr(L, bdslot); |
+ bind(&skip); |
+ } else { |
+ BranchAndLinkShort(L, cond, rs, rt, bdslot); |
+ } |
+} |
+ |
+ |
// We need to use a bgezal or bltzal, but they can't be used directly with the |
// slt instructions. We could use sub or add instead but we would miss overflow |
// cases, so we keep slt and add an intermediate third instruction. |
-void MacroAssembler::BranchAndLink(int16_t offset, |
- BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchAndLinkShort(int16_t offset, |
+ BranchDelaySlot bdslot) { |
bal(offset); |
// Emit a nop in the branch delay slot if required. |
@@ -1625,9 +1712,9 @@ void MacroAssembler::BranchAndLink(int16_t offset, |
} |
-void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, |
- const Operand& rt, |
- BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond, |
+ Register rs, const Operand& rt, |
+ BranchDelaySlot bdslot) { |
BRANCH_ARGS_CHECK(cond, rs, rt); |
Register r2 = no_reg; |
Register scratch = at; |
@@ -1707,7 +1794,7 @@ void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, |
} |
-void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) { |
bal(shifted_branch_offset(L, false)); |
// Emit a nop in the branch delay slot if required. |
@@ -1716,9 +1803,9 @@ void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { |
} |
-void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, |
- const Operand& rt, |
- BranchDelaySlot bdslot) { |
+void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs, |
+ const Operand& rt, |
+ BranchDelaySlot bdslot) { |
BRANCH_ARGS_CHECK(cond, rs, rt); |
int32_t offset; |
@@ -1814,6 +1901,64 @@ void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, |
} |
+void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) { |
+ BlockTrampolinePoolScope block_trampoline_pool(this); |
+ |
+ uint32_t imm28; |
+ imm28 = jump_address(L); |
+ imm28 &= kImm28Mask; |
+ { BlockGrowBufferScope block_buf_growth(this); |
+ // Buffer growth (and relocation) must be blocked for internal references |
+ // until associated instructions are emitted and available to be patched. |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ j(imm28); |
+ } |
+ // Emit a nop in the branch delay slot if required. |
+ if (bdslot == PROTECT) |
+ nop(); |
+} |
+ |
+ |
+void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) { |
+ BlockTrampolinePoolScope block_trampoline_pool(this); |
+ |
+ uint32_t imm32; |
+ imm32 = jump_address(L); |
+ { BlockGrowBufferScope block_buf_growth(this); |
+ // Buffer growth (and relocation) must be blocked for internal references |
+ // until associated instructions are emitted and available to be patched. |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ lui(at, (imm32 & kHiMask) >> kLuiShift); |
+ ori(at, at, (imm32 & kImm16Mask)); |
+ } |
+ jr(at); |
+ |
+ // Emit a nop in the branch delay slot if required. |
+ if (bdslot == PROTECT) |
+ nop(); |
+} |
+ |
+ |
+void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) { |
+ BlockTrampolinePoolScope block_trampoline_pool(this); |
+ |
+ uint32_t imm32; |
+ imm32 = jump_address(L); |
+ { BlockGrowBufferScope block_buf_growth(this); |
+ // Buffer growth (and relocation) must be blocked for internal references |
+ // until associated instructions are emitted and available to be patched. |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ lui(at, (imm32 & kHiMask) >> kLuiShift); |
+ ori(at, at, (imm32 & kImm16Mask)); |
+ } |
+ jalr(at); |
+ |
+ // Emit a nop in the branch delay slot if required. |
+ if (bdslot == PROTECT) |
+ nop(); |
+} |
+ |
+ |
void MacroAssembler::Jump(const Operand& target, BranchDelaySlot bdslot) { |
BlockTrampolinePoolScope block_trampoline_pool(this); |
if (target.is_reg()) { |