Commit 286602a5 authored by Predrag Rudic's avatar Predrag Rudic Committed by Commit Bot

MIPS[64] Fix BranchLong PIC optimization

In case of switching from non-optimized to optimized version
of BranchLong macro, we forgot to take the instruction which
is located in the branch delay slot of the unoptimized version
and copy it to branch delay slot of the optimized version.

This CL implements the missing functionality.

Change-Id: I5e4adcccd0e85fd381a97eea8588e07bd8b045ef
Reviewed-on: https://chromium-review.googlesource.com/1165082Reviewed-by: 's avatarIvica Bogosavljevic <ibogosavljevic@wavecomp.com>
Commit-Queue: Ivica Bogosavljevic <ibogosavljevic@wavecomp.com>
Cr-Commit-Position: refs/heads/master@{#54970}
parent a27cf3d5
......@@ -964,8 +964,16 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos,
Instr instr_b = BEQ;
instr_b = SetBranchOffset(pos, target_pos, instr_b);
instr_at_put(pos, instr_b);
instr_at_put(pos + 1 * kInstrSize, 0);
Instr instr_j = instr_at(pos + 5 * kInstrSize);
Instr instr_branch_delay;
if (IsJump(instr_j)) {
instr_branch_delay = instr_at(pos + 6 * kInstrSize);
} else {
instr_branch_delay = instr_at(pos + 7 * kInstrSize);
}
instr_at_put(pos + 0 * kInstrSize, instr_b);
instr_at_put(pos + 1 * kInstrSize, instr_branch_delay);
} else {
int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset);
DCHECK_EQ(imm & 3, 0);
......@@ -3915,11 +3923,15 @@ void Assembler::CheckTrampolinePool() {
bind(&find_pc);
ori(t9, t9, 0);
addu(t9, ra, t9);
// Instruction jr will take or_ from the next trampoline.
// in its branch delay slot. This is the expected behavior
// in order to decrease size of trampoline pool.
or_(ra, t8, zero_reg);
jr(t9);
or_(ra, t8, zero_reg); // Branch delay slot.
}
}
}
nop();
bind(&after_pool);
trampoline_ = Trampoline(pool_start, unbound_labels_count_);
......
......@@ -942,8 +942,16 @@ void Assembler::target_at_put(int pos, int target_pos, bool is_internal) {
Instr instr_b = BEQ;
instr_b = SetBranchOffset(pos, target_pos, instr_b);
Instr instr_j = instr_at(pos + 5 * kInstrSize);
Instr instr_branch_delay;
if (IsJump(instr_j)) {
instr_branch_delay = instr_at(pos + 6 * kInstrSize);
} else {
instr_branch_delay = instr_at(pos + 7 * kInstrSize);
}
instr_at_put(pos, instr_b);
instr_at_put(pos + 1 * kInstrSize, 0);
instr_at_put(pos + 1 * kInstrSize, instr_branch_delay);
} else {
int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset);
DCHECK_EQ(imm & 3, 0);
......@@ -4262,11 +4270,15 @@ void Assembler::CheckTrampolinePool() {
bind(&find_pc);
ori(t9, t9, 0);
daddu(t9, ra, t9);
or_(ra, t8, zero_reg);
// Instruction jr will take or_ from the next trampoline.
// in its branch delay slot. This is the expected behavior
// in order to decrease size of trampoline pool.
jr(t9);
or_(ra, t8, zero_reg); // Branch delay slot.
}
}
}
nop();
bind(&after_pool);
trampoline_ = Trampoline(pool_start, unbound_labels_count_);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment