Commit c766f739 authored by Miran.Karic's avatar Miran.Karic Committed by Commit bot

MIPS: Replace JR/JALR with JIC/JIALC for r6

This is the first step in process of replacing JR and JALR instructions
with JIC and JIALC for r6. Trampoline in r6 now uses JIC. Also
BranchLong and BranchAndLinkLong MacroAssembler functions now use JIC
and JIALC in r6 if branch delay slot is not used.

BUG=

Review URL: https://codereview.chromium.org/1573983002

Cr-Commit-Position: refs/heads/master@{#34236}
parent e3453a86
......@@ -160,19 +160,30 @@ Address Assembler::target_address_from_return_address(Address pc) {
void Assembler::set_target_internal_reference_encoded_at(Address pc,
Address target) {
// Encoded internal references are lui/ori load of 32-bit abolute address.
Instr instr_lui = Assembler::instr_at(pc + 0 * Assembler::kInstrSize);
Instr instr_ori = Assembler::instr_at(pc + 1 * Assembler::kInstrSize);
DCHECK(Assembler::IsLui(instr_lui));
DCHECK(Assembler::IsOri(instr_ori));
instr_lui &= ~kImm16Mask;
instr_ori &= ~kImm16Mask;
Instr instr1 = Assembler::instr_at(pc + 0 * Assembler::kInstrSize);
Instr instr2 = Assembler::instr_at(pc + 1 * Assembler::kInstrSize);
DCHECK(Assembler::IsLui(instr1));
DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
instr1 &= ~kImm16Mask;
instr2 &= ~kImm16Mask;
int32_t imm = reinterpret_cast<int32_t>(target);
DCHECK((imm & 3) == 0);
Assembler::instr_at_put(pc + 0 * Assembler::kInstrSize,
instr_lui | ((imm >> kLuiShift) & kImm16Mask));
Assembler::instr_at_put(pc + 1 * Assembler::kInstrSize,
instr_ori | (imm & kImm16Mask));
if (Assembler::IsJicOrJialc(instr2)) {
// Encoded internal references are lui/jic load of 32-bit absolute address.
uint32_t lui_offset_u, jic_offset_u;
Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
Assembler::instr_at_put(pc + 0 * Assembler::kInstrSize,
instr1 | lui_offset_u);
Assembler::instr_at_put(pc + 1 * Assembler::kInstrSize,
instr2 | jic_offset_u);
} else {
// Encoded internal references are lui/ori load of 32-bit absolute address.
Assembler::instr_at_put(pc + 0 * Assembler::kInstrSize,
instr1 | ((imm >> kLuiShift) & kImm16Mask));
Assembler::instr_at_put(pc + 1 * Assembler::kInstrSize,
instr2 | (imm & kImm16Mask));
}
// Currently used only by deserializer, and all code will be flushed
// after complete deserialization, no need to flush on each reference.
......@@ -230,14 +241,19 @@ Address RelocInfo::target_internal_reference() {
if (rmode_ == INTERNAL_REFERENCE) {
return Memory::Address_at(pc_);
} else {
// Encoded internal references are lui/ori load of 32-bit abolute address.
// Encoded internal references are lui/ori or lui/jic load of 32-bit
// absolute address.
DCHECK(rmode_ == INTERNAL_REFERENCE_ENCODED);
Instr instr_lui = Assembler::instr_at(pc_ + 0 * Assembler::kInstrSize);
Instr instr_ori = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
DCHECK(Assembler::IsLui(instr_lui));
DCHECK(Assembler::IsOri(instr_ori));
int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
Instr instr1 = Assembler::instr_at(pc_ + 0 * Assembler::kInstrSize);
Instr instr2 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
DCHECK(Assembler::IsLui(instr1));
DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
if (Assembler::IsJicOrJialc(instr2)) {
return reinterpret_cast<Address>(
Assembler::CreateTargetAddress(instr1, instr2));
}
int32_t imm = (instr1 & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
imm |= (instr2 & static_cast<int32_t>(kImm16Mask));
return reinterpret_cast<Address>(imm);
}
}
......
This diff is collapsed.
......@@ -1082,6 +1082,7 @@ class Assembler : public AssemblerBase {
static bool IsBnezc(Instr instr);
static bool IsBeqc(Instr instr);
static bool IsBnec(Instr instr);
static bool IsJicOrJialc(Instr instr);
static bool IsJump(Instr instr);
static bool IsJ(Instr instr);
......@@ -1121,12 +1122,20 @@ class Assembler : public AssemblerBase {
static int32_t GetBranchOffset(Instr instr);
static bool IsLw(Instr instr);
static int16_t GetLwOffset(Instr instr);
static int16_t GetJicOrJialcOffset(Instr instr);
static int16_t GetLuiOffset(Instr instr);
static Instr SetLwOffset(Instr instr, int16_t offset);
static bool IsSw(Instr instr);
static Instr SetSwOffset(Instr instr, int16_t offset);
static bool IsAddImmediate(Instr instr);
static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
static uint32_t CreateTargetAddress(Instr instr_lui, Instr instr_jic);
static void UnpackTargetAddress(uint32_t address, int16_t& lui_offset,
int16_t& jic_offset);
static void UnpackTargetAddressUnsigned(uint32_t address,
uint32_t& lui_offset,
uint32_t& jic_offset);
static bool IsAndImmediate(Instr instr);
static bool IsEmittedConstant(Instr instr);
......@@ -1213,6 +1222,8 @@ class Assembler : public AssemblerBase {
inline void CheckTrampolinePoolQuick(int extra_instructions = 0);
inline void CheckBuffer();
private:
inline static void set_target_internal_reference_encoded_at(Address pc,
Address target);
......@@ -1259,7 +1270,6 @@ class Assembler : public AssemblerBase {
enum class CompactBranchType : bool { NO = false, COMPACT_BRANCH = true };
// Code emission.
inline void CheckBuffer();
void GrowBuffer();
inline void emit(Instr x,
CompactBranchType is_compact_branch = CompactBranchType::NO);
......@@ -1406,7 +1416,11 @@ class Assembler : public AssemblerBase {
// branch instruction generation, where we use jump instructions rather
// than regular branch instructions.
bool trampoline_emitted_;
#ifdef _MIPS_ARCH_MIPS32R6
static const int kTrampolineSlotsSize = 2 * kInstrSize;
#else
static const int kTrampolineSlotsSize = 4 * kInstrSize;
#endif
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
static const int kInvalidSlotPos = -1;
......
......@@ -3198,18 +3198,35 @@ void MacroAssembler::BranchLong(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_ENCODED);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
if (IsMipsArchVariant(kMips32r6) && bdslot != USE_DELAY_SLOT) {
uint32_t lui_offset, jic_offset;
UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
{
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_ENCODED);
lui(at, lui_offset);
jic(at, jic_offset);
}
CheckBuffer();
} else {
{
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_ENCODED);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
}
CheckBuffer();
jr(at);
// Emit a nop in the branch delay slot if required.
if (bdslot == PROTECT) nop();
}
jr(at);
// Emit a nop in the branch delay slot if required.
if (bdslot == PROTECT) nop();
}
}
......@@ -3222,18 +3239,34 @@ void MacroAssembler::BranchAndLinkLong(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_ENCODED);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
if (IsMipsArchVariant(kMips32r6) && bdslot != USE_DELAY_SLOT) {
uint32_t lui_offset, jic_offset;
UnpackTargetAddressUnsigned(imm32, lui_offset, jic_offset);
{
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_ENCODED);
lui(at, lui_offset);
jialc(at, jic_offset);
}
CheckBuffer();
} else {
{
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_ENCODED);
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();
}
jalr(at);
// Emit a nop in the branch delay slot if required.
if (bdslot == PROTECT) nop();
}
}
......
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