| 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()) {
|
|
|