Index: src/mips/assembler-mips.cc |
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc |
index 182183f547bc9f7f7bf81baffbac69c228c4cd50..96cccbb87a7a5b0395b86b6d6087a3738cb60dc2 100644 |
--- a/src/mips/assembler-mips.cc |
+++ b/src/mips/assembler-mips.cc |
@@ -673,8 +673,6 @@ int Assembler::target_at(int32_t pos) { |
return (imm18 + pos); |
} |
} |
- // Check we have a branch or jump instruction. |
- DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); |
// Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
// the compiler uses arithmectic shifts for signed integers. |
if (IsBranch(instr)) { |
@@ -702,7 +700,7 @@ int Assembler::target_at(int32_t pos) { |
DCHECK(pos > delta); |
return pos - delta; |
} |
- } else { |
+ } else if (IsJ(instr)) { |
int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
if (imm28 == kEndOfJumpChain) { |
// EndOfChain sentinel is returned directly, not relative to pc or pos. |
@@ -714,6 +712,14 @@ int Assembler::target_at(int32_t pos) { |
DCHECK(pos > delta); |
return pos - delta; |
} |
+ } else { // IsLabel(instr) |
+ int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
+ if (imm28 == kEndOfJumpChain) { |
+ // EndOfChain sentinel is returned directly, not relative to pc or pos. |
+ return kEndOfChain; |
+ } else { |
+ return pos + imm28; |
+ } |
} |
} |
@@ -728,7 +734,6 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) { |
return; |
} |
- DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); |
if (IsBranch(instr)) { |
int32_t imm18 = target_pos - (pos + kBranchPCOffset); |
DCHECK((imm18 & 3) == 0); |
@@ -752,7 +757,7 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) { |
instr_lui | ((imm & kHiMask) >> kLuiShift)); |
instr_at_put(pos + 1 * Assembler::kInstrSize, |
instr_ori | (imm & kImm16Mask)); |
- } else { |
+ } else if (IsJ(instr)) { |
uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
imm28 &= kImm28Mask; |
DCHECK((imm28 & 3) == 0); |
@@ -762,6 +767,9 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos) { |
DCHECK(is_uint26(imm26)); |
instr_at_put(pos, instr | (imm26 & kImm26Mask)); |
+ } else { |
+ uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
+ instr_at_put(pos, imm); |
} |
} |
@@ -816,7 +824,6 @@ void Assembler::bind_to(Label* L, int pos) { |
} |
target_at_put(fixup_pos, pos); |
} else { |
- DCHECK(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr)); |
target_at_put(fixup_pos, pos); |
} |
} |
@@ -2358,7 +2365,6 @@ void Assembler::RecordDeoptReason(const int reason, const int raw_position) { |
int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
Instr instr = instr_at(pc); |
- DCHECK(IsJ(instr) || IsLui(instr)); |
if (IsLui(instr)) { |
Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); |
@@ -2379,7 +2385,7 @@ int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
instr_at_put(pc + 1 * Assembler::kInstrSize, |
instr_ori | (imm & kImm16Mask)); |
return 2; // Number of instructions patched. |
- } else { |
+ } else if (IsJ(instr)) { |
uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
return 0; // Number of instructions patched. |
@@ -2394,6 +2400,14 @@ int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
instr_at_put(pc, instr | (imm26 & kImm26Mask)); |
return 1; // Number of instructions patched. |
+ } else { // IsLabel(instr) |
+ int32_t* p = reinterpret_cast<int32_t*>(pc); |
+ uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
+ if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
+ return 0; // Number of instructions patched. |
+ } |
+ *p += pc_delta; |
+ return 1; // Number of instructions patched. |
} |
} |
@@ -2458,6 +2472,35 @@ void Assembler::dd(uint32_t data) { |
} |
+void Assembler::dd(Label* label) { |
+ CheckBuffer(); |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ if (label->is_bound()) { |
+ uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos()); |
+ *reinterpret_cast<uint32_t*>(pc_) = data; |
+ pc_ += sizeof(uint32_t); |
+ } else { |
+ int target_pos; |
+ if (label->is_linked()) { |
+ // Point to previous instruction that uses the link. |
+ target_pos = label->pos(); |
+ } else { |
+ // First entry of the link chain points to itself. |
+ target_pos = pc_offset(); |
+ } |
+ label->link_to(pc_offset()); |
+ // Encode internal reference to unbound label. We set the least significant |
+ // bit to distinguish unbound internal references in GrowBuffer() below. |
+ int diff = target_pos - pc_offset(); |
+ DCHECK_EQ(0, diff & 3); |
+ int imm26 = diff >> 2; |
+ DCHECK(is_int26(imm26)); |
+ // Emit special LABEL instruction. |
+ emit(LABEL | (imm26 & kImm26Mask)); |
+ } |
+} |
+ |
+ |
void Assembler::emit_code_stub_address(Code* stub) { |
CheckBuffer(); |
*reinterpret_cast<uint32_t*>(pc_) = |