Index: src/mips/assembler-mips.cc |
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc |
index 30888f133f88f28fa3587ecbfde0ba373659b267..81554fd594d9168c934ec8d09d7bdc174937b3b8 100644 |
--- a/src/mips/assembler-mips.cc |
+++ b/src/mips/assembler-mips.cc |
@@ -849,12 +849,13 @@ void Assembler::bind_to(Label* L, int pos) { |
target_at_put(fixup_pos, pos, is_internal); |
} else { |
if (IsBranch(instr)) { |
- if (dist > kMaxBranchOffset) { |
+ int branch_offset = BranchOffset(instr); |
+ if (dist > branch_offset) { |
if (trampoline_pos == kInvalidSlotPos) { |
trampoline_pos = get_trampoline_entry(fixup_pos); |
CHECK(trampoline_pos != kInvalidSlotPos); |
} |
- CHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); |
+ CHECK((trampoline_pos - fixup_pos) <= branch_offset); |
target_at_put(fixup_pos, trampoline_pos, false); |
fixup_pos = trampoline_pos; |
dist = pos - fixup_pos; |
@@ -894,22 +895,46 @@ void Assembler::next(Label* L, bool is_internal) { |
bool Assembler::is_near(Label* L) { |
DCHECK(L->is_bound()); |
- return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize); |
+ return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize; |
} |
bool Assembler::is_near(Label* L, OffsetSize bits) { |
if (L == nullptr || !L->is_bound()) return true; |
- return ((pc_offset() - L->pos()) < |
- (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize); |
+ return pc_offset() - L->pos() < (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize; |
} |
bool Assembler::is_near_branch(Label* L) { |
DCHECK(L->is_bound()); |
- int max_offset = |
- IsMipsArchVariant(kMips32r6) ? kMaxCompactBranchOffset : kMaxBranchOffset; |
- return pc_offset() - L->pos() < max_offset - 4 * kInstrSize; |
+ return IsMipsArchVariant(kMips32r6) ? is_near_r6(L) : is_near_pre_r6(L); |
+} |
+ |
+ |
+int Assembler::BranchOffset(Instr instr) { |
+ // At pre-R6 and for other R6 branches the offset is 16 bits. |
+ int bits = OffsetSize::kOffset16; |
+ |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ uint32_t opcode = GetOpcodeField(instr); |
+ switch (opcode) { |
+ // Checks BC or BALC. |
+ case BC: |
+ case BALC: |
+ bits = OffsetSize::kOffset26; |
+ break; |
+ |
+ // Checks BEQZC or BNEZC. |
+ case POP66: |
+ case POP76: |
+ if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21; |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ return (1 << (bits + 2 - 1)) - 1; |
} |
@@ -1398,6 +1423,7 @@ void Assembler::beqc(Register rs, Register rt, int16_t offset) { |
void Assembler::beqzc(Register rs, int32_t offset) { |
DCHECK(IsMipsArchVariant(kMips32r6)); |
DCHECK(!(rs.is(zero_reg))); |
+ DCHECK(is_int21(offset)); |
GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH); |
} |
@@ -1416,6 +1442,7 @@ void Assembler::bnec(Register rs, Register rt, int16_t offset) { |
void Assembler::bnezc(Register rs, int32_t offset) { |
DCHECK(IsMipsArchVariant(kMips32r6)); |
DCHECK(!(rs.is(zero_reg))); |
+ DCHECK(is_int21(offset)); |
GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH); |
} |
@@ -1818,7 +1845,7 @@ void Assembler::lwpc(Register rs, int32_t offset19) { |
void Assembler::auipc(Register rs, int16_t imm16) { |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- DCHECK(rs.is_valid() && is_int16(imm16)); |
+ DCHECK(rs.is_valid()); |
uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); |
GenInstrImmediate(PCREL, rs, imm21); |
} |
@@ -1826,7 +1853,7 @@ void Assembler::auipc(Register rs, int16_t imm16) { |
void Assembler::aluipc(Register rs, int16_t imm16) { |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- DCHECK(rs.is_valid() && is_int16(imm16)); |
+ DCHECK(rs.is_valid()); |
uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); |
GenInstrImmediate(PCREL, rs, imm21); |
} |