| 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_) =
|
|
|