CPU/Recompiler: Add unconditional EmitBranch

This commit is contained in:
Connor McLaughlin 2019-12-26 00:02:15 +10:00
parent 4f2c1e1a6b
commit 390b6da0b8
3 changed files with 36 additions and 0 deletions

View File

@ -78,6 +78,9 @@ public:
Value EmitLoadGuestMemory(const Value& address, RegSize size); Value EmitLoadGuestMemory(const Value& address, RegSize size);
void EmitStoreGuestMemory(const Value& address, const Value& value); void EmitStoreGuestMemory(const Value& address, const Value& value);
// Unconditional branch to pointer. May allocate a scratch register.
void EmitBranch(const void* address, bool allow_scratch = true);
// Branching, generates two paths. // Branching, generates two paths.
void EmitBranch(Condition condition, Reg lr_reg, Value&& branch_target); void EmitBranch(Condition condition, Reg lr_reg, Value&& branch_target);
void EmitBranchIfBitClear(HostReg reg, RegSize size, u8 bit, LabelType* label); void EmitBranchIfBitClear(HostReg reg, RegSize size, u8 bit, LabelType* label);

View File

@ -1390,6 +1390,24 @@ void CodeGenerator::EmitCancelInterpreterLoadDelayForReg(Reg reg)
m_emit->Bind(&skip_cancel); m_emit->Bind(&skip_cancel);
} }
void CodeGenerator::EmitBranch(const void* address, bool allow_scratch)
{
const s64 jump_distance =
static_cast<s64>(reinterpret_cast<intptr_t>(address) - reinterpret_cast<intptr_t>(GetCurrentCodePointer()));
Assert(Common::IsAligned(jump_distance, 4));
if (a64::Instruction::IsValidImmPCOffset(a64::UncondBranchType, jump_distance >> 2))
{
m_emit->b(jump_distance >> 2);
return;
}
Assert(allow_scratch);
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->Mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(address));
m_emit->br(GetHostReg64(temp));
}
template<typename T> template<typename T>
static void EmitConditionalJump(Condition condition, bool invert, a64::MacroAssembler* emit, const T& label) static void EmitConditionalJump(Condition condition, bool invert, a64::MacroAssembler* emit, const T& label)
{ {

View File

@ -1792,6 +1792,21 @@ void CodeGenerator::EmitCancelInterpreterLoadDelayForReg(Reg reg)
m_emit->L(skip_cancel); m_emit->L(skip_cancel);
} }
void CodeGenerator::EmitBranch(const void* address, bool allow_scratch)
{
if (Xbyak::inner::IsInInt32(reinterpret_cast<uintptr_t>(address)))
{
m_emit->jmp(address);
return;
}
Assert(allow_scratch);
Value temp = m_register_cache.AllocateScratch(RegSize_64);
m_emit->mov(GetHostReg64(temp), reinterpret_cast<uintptr_t>(address));
m_emit->jmp(GetHostReg64(temp));
}
template<typename T> template<typename T>
static void EmitConditionalJump(Condition condition, bool invert, Xbyak::CodeGenerator* emit, const T& label) static void EmitConditionalJump(Condition condition, bool invert, Xbyak::CodeGenerator* emit, const T& label)
{ {