mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
JitArm64: Add utility for calling a function with arguments
With this, situations where multiple arguments need to be moved from multiple registers become easy to handle, and we also get compile-time checking that the number of arguments is correct.
This commit is contained in:
@ -197,10 +197,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
||||
}
|
||||
|
||||
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
|
||||
MOVP2R(ARM64Reg::X8, instr);
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetInterpreter());
|
||||
MOVI2R(ARM64Reg::W1, inst.hex);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(instr, &m_system.GetInterpreter(), inst.hex);
|
||||
|
||||
// If the instruction wrote to any registers which were marked as discarded,
|
||||
// we must mark them as no longer discarded
|
||||
@ -248,10 +245,7 @@ void JitArm64::HLEFunction(u32 hook_index)
|
||||
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
|
||||
MOVP2R(ARM64Reg::X8, &HLE::ExecuteFromJIT);
|
||||
MOVI2R(ARM64Reg::W0, js.compilerPC);
|
||||
MOVI2R(ARM64Reg::W1, hook_index);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&HLE::ExecuteFromJIT, js.compilerPC, hook_index);
|
||||
}
|
||||
|
||||
void JitArm64::DoNothing(UGeckoInstruction inst)
|
||||
@ -275,21 +269,15 @@ void JitArm64::Cleanup()
|
||||
SUB(ARM64Reg::X0, ARM64Reg::X0, ARM64Reg::X1);
|
||||
CMP(ARM64Reg::X0, GPFifo::GATHER_PIPE_SIZE);
|
||||
FixupBranch exit = B(CC_LT);
|
||||
MOVP2R(ARM64Reg::X1, &GPFifo::UpdateGatherPipe);
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetGPFifo());
|
||||
BLR(ARM64Reg::X1);
|
||||
ABI_CallFunction(&GPFifo::UpdateGatherPipe, &m_system.GetGPFifo());
|
||||
SetJumpTarget(exit);
|
||||
}
|
||||
|
||||
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
|
||||
if (MMCR0(m_ppc_state).Hex || MMCR1(m_ppc_state).Hex)
|
||||
{
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::UpdatePerformanceMonitor);
|
||||
MOVI2R(ARM64Reg::X0, js.downcountAmount);
|
||||
MOVI2R(ARM64Reg::X1, js.numLoadStoreInst);
|
||||
MOVI2R(ARM64Reg::X2, js.numFloatingPointInst);
|
||||
MOVP2R(ARM64Reg::X3, &m_ppc_state);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, js.numLoadStoreInst,
|
||||
js.numFloatingPointInst, &m_ppc_state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,10 +319,8 @@ void JitArm64::IntializeSpeculativeConstants()
|
||||
fail = GetCodePtr();
|
||||
MOVI2R(DISPATCHER_PC, js.blockStart);
|
||||
STR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
MOVP2R(ARM64Reg::X8, &JitInterface::CompileExceptionCheckFromJIT);
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetJitInterface());
|
||||
MOVI2R(ARM64Reg::W1, static_cast<u32>(JitInterface::ExceptionType::SpeculativeConstants));
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&JitInterface::CompileExceptionCheckFromJIT, &m_system.GetJitInterface(),
|
||||
static_cast<u32>(JitInterface::ExceptionType::SpeculativeConstants));
|
||||
B(dispatcher_no_check);
|
||||
SwitchToNearCode();
|
||||
}
|
||||
@ -652,12 +638,10 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
|
||||
static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc));
|
||||
STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC());
|
||||
if (only_external)
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptionsFromJIT);
|
||||
else
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptionsFromJIT);
|
||||
BLR(EncodeRegTo64(DISPATCHER_PC));
|
||||
const auto f =
|
||||
only_external ? &PowerPC::CheckExternalExceptionsFromJIT : &PowerPC::CheckExceptionsFromJIT;
|
||||
ABI_CallFunction(f, &m_system.GetPowerPC());
|
||||
|
||||
EmitUpdateMembase();
|
||||
|
||||
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
|
||||
@ -998,10 +982,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||
SetJumpTarget(fail);
|
||||
MOVI2R(DISPATCHER_PC, js.blockStart);
|
||||
STR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetJitInterface());
|
||||
MOVI2R(ARM64Reg::W1, static_cast<u32>(JitInterface::ExceptionType::PairedQuantize));
|
||||
MOVP2R(ARM64Reg::X2, &JitInterface::CompileExceptionCheckFromJIT);
|
||||
BLR(ARM64Reg::X2);
|
||||
ABI_CallFunction(&JitInterface::CompileExceptionCheckFromJIT, &m_system.GetJitInterface(),
|
||||
static_cast<u32>(JitInterface::ExceptionType::PairedQuantize));
|
||||
B(dispatcher_no_check);
|
||||
SwitchToNearCode();
|
||||
SetJumpTarget(no_fail);
|
||||
@ -1064,9 +1046,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||
|
||||
ABI_PushRegisters(regs_in_use);
|
||||
m_float_emit.ABI_PushRegisters(fprs_in_use, ARM64Reg::X30);
|
||||
MOVP2R(ARM64Reg::X8, &GPFifo::FastCheckGatherPipe);
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetGPFifo());
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&GPFifo::FastCheckGatherPipe, &m_system.GetGPFifo());
|
||||
m_float_emit.ABI_PopRegisters(fprs_in_use, ARM64Reg::X30);
|
||||
ABI_PopRegisters(regs_in_use);
|
||||
|
||||
@ -1182,9 +1162,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||
|
||||
MOVI2R(DISPATCHER_PC, op.address);
|
||||
STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC());
|
||||
MOVP2R(ARM64Reg::X1, &PowerPC::CheckBreakPointsFromJIT);
|
||||
BLR(ARM64Reg::X1);
|
||||
ABI_CallFunction(&PowerPC::CheckBreakPointsFromJIT, &m_system.GetPowerPC());
|
||||
|
||||
LDR(IndexType::Unsigned, ARM64Reg::W0, ARM64Reg::X0,
|
||||
MOVPage2R(ARM64Reg::X0, cpu.GetStatePtr()));
|
||||
|
@ -211,55 +211,45 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
|
||||
src_reg = dst_reg;
|
||||
}
|
||||
|
||||
if (dst_reg != src_reg)
|
||||
MOV(dst_reg, src_reg);
|
||||
|
||||
const bool reverse = (flags & BackPatchInfo::FLAG_REVERSE) != 0;
|
||||
|
||||
MOVP2R(ARM64Reg::X2, &m_mmu);
|
||||
|
||||
if (access_size == 64)
|
||||
{
|
||||
MOVP2R(ARM64Reg::X8,
|
||||
reverse ? &PowerPC::WriteU64SwapFromJitArm64 : &PowerPC::WriteU64FromJitArm64);
|
||||
ABI_CallFunction(reverse ? &PowerPC::WriteU64SwapFromJitArm64 :
|
||||
&PowerPC::WriteU64FromJitArm64,
|
||||
src_reg, ARM64Reg::W1, &m_mmu);
|
||||
}
|
||||
else if (access_size == 32)
|
||||
{
|
||||
MOVP2R(ARM64Reg::X8,
|
||||
reverse ? &PowerPC::WriteU32SwapFromJitArm64 : &PowerPC::WriteU32FromJitArm64);
|
||||
ABI_CallFunction(reverse ? &PowerPC::WriteU32SwapFromJitArm64 :
|
||||
&PowerPC::WriteU32FromJitArm64,
|
||||
src_reg, ARM64Reg::W1, &m_mmu);
|
||||
}
|
||||
else if (access_size == 16)
|
||||
{
|
||||
MOVP2R(ARM64Reg::X8,
|
||||
reverse ? &PowerPC::WriteU16SwapFromJitArm64 : &PowerPC::WriteU16FromJitArm64);
|
||||
ABI_CallFunction(reverse ? &PowerPC::WriteU16SwapFromJitArm64 :
|
||||
&PowerPC::WriteU16FromJitArm64,
|
||||
src_reg, ARM64Reg::W1, &m_mmu);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::WriteU8FromJitArm64);
|
||||
ABI_CallFunction(&PowerPC::WriteU8FromJitArm64, src_reg, ARM64Reg::W1, &m_mmu);
|
||||
}
|
||||
|
||||
BLR(ARM64Reg::X8);
|
||||
}
|
||||
else if (flags & BackPatchInfo::FLAG_ZERO_256)
|
||||
{
|
||||
MOVP2R(ARM64Reg::X1, &m_mmu);
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::ClearDCacheLineFromJitArm64);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&PowerPC::ClearDCacheLineFromJitArm64, ARM64Reg::W0, &m_mmu);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOVP2R(ARM64Reg::X1, &m_mmu);
|
||||
|
||||
if (access_size == 64)
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU64FromJitArm64);
|
||||
ABI_CallFunction(&PowerPC::ReadU64FromJitArm64, ARM64Reg::W0, &m_mmu);
|
||||
else if (access_size == 32)
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU32FromJitArm64);
|
||||
ABI_CallFunction(&PowerPC::ReadU32FromJitArm64, ARM64Reg::W0, &m_mmu);
|
||||
else if (access_size == 16)
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU16FromJitArm64);
|
||||
ABI_CallFunction(&PowerPC::ReadU16FromJitArm64, ARM64Reg::W0, &m_mmu);
|
||||
else
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::ReadU8FromJitArm64);
|
||||
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&PowerPC::ReadU8FromJitArm64, ARM64Reg::W0, &m_mmu);
|
||||
}
|
||||
|
||||
m_float_emit.ABI_PopRegisters(fprs_to_push, ARM64Reg::X30);
|
||||
|
@ -770,13 +770,17 @@ void JitArm64::dcbx(UGeckoInstruction inst)
|
||||
ABI_PushRegisters(gprs_to_push);
|
||||
m_float_emit.ABI_PushRegisters(fprs_to_push, WA);
|
||||
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetJitInterface());
|
||||
// effective_address and loop_counter are already in W1 and W2 respectively
|
||||
// For efficiency, effective_addr and loop_counter are already in W1 and W2 respectively
|
||||
if (make_loop)
|
||||
MOVP2R(ARM64Reg::X8, &JitInterface::InvalidateICacheLinesFromJIT);
|
||||
{
|
||||
ABI_CallFunction(&JitInterface::InvalidateICacheLinesFromJIT, &m_system.GetJitInterface(),
|
||||
effective_addr, loop_counter);
|
||||
}
|
||||
else
|
||||
MOVP2R(ARM64Reg::X8, &JitInterface::InvalidateICacheLineFromJIT);
|
||||
BLR(ARM64Reg::X8);
|
||||
{
|
||||
ABI_CallFunction(&JitInterface::InvalidateICacheLineFromJIT, &m_system.GetJitInterface(),
|
||||
effective_addr);
|
||||
}
|
||||
|
||||
m_float_emit.ABI_PopRegisters(fprs_to_push, WA);
|
||||
ABI_PopRegisters(gprs_to_push);
|
||||
|
@ -78,9 +78,7 @@ void JitArm64::UpdateRoundingMode()
|
||||
|
||||
ABI_PushRegisters(gprs_to_save);
|
||||
m_float_emit.ABI_PushRegisters(fprs_to_save, ARM64Reg::X8);
|
||||
MOVP2R(ARM64Reg::X0, &m_ppc_state);
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::RoundingModeUpdated);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&PowerPC::RoundingModeUpdated, &m_ppc_state);
|
||||
m_float_emit.ABI_PopRegisters(fprs_to_save, ARM64Reg::X8);
|
||||
ABI_PopRegisters(gprs_to_save);
|
||||
}
|
||||
|
@ -169,10 +169,7 @@ void JitArm64::GenerateAsm()
|
||||
|
||||
// Call JIT
|
||||
ResetStack();
|
||||
MOVP2R(ARM64Reg::X0, this);
|
||||
MOV(ARM64Reg::W1, DISPATCHER_PC);
|
||||
MOVP2R(ARM64Reg::X8, reinterpret_cast<void*>(&JitTrampoline));
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&JitTrampoline, this, DISPATCHER_PC);
|
||||
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
B(dispatcher_no_check);
|
||||
|
||||
@ -189,8 +186,7 @@ void JitArm64::GenerateAsm()
|
||||
FixupBranch exit = CBNZ(ARM64Reg::W0);
|
||||
|
||||
SetJumpTarget(to_start_of_timing_slice);
|
||||
MOVP2R(ARM64Reg::X8, &CoreTiming::GlobalAdvance);
|
||||
BLR(ARM64Reg::X8);
|
||||
ABI_CallFunction(&CoreTiming::GlobalAdvance);
|
||||
|
||||
// When we've just entered the jit we need to update the membase
|
||||
// GlobalAdvance also checks exceptions after which we need to
|
||||
|
@ -78,10 +78,8 @@ private:
|
||||
|
||||
m_emit->ABI_PushRegisters(m_gprs_in_use);
|
||||
float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1);
|
||||
m_emit->MOVP2R(ARM64Reg::X1, m_system);
|
||||
m_emit->MOVI2R(ARM64Reg::W2, m_address);
|
||||
m_emit->MOV(ARM64Reg::W3, m_src_reg);
|
||||
m_emit->BLR(m_emit->ABI_SetupLambda(lambda));
|
||||
|
||||
m_emit->ABI_CallLambdaFunction(lambda, m_system, m_address, m_src_reg);
|
||||
|
||||
float_emit.ABI_PopRegisters(m_fprs_in_use, ARM64Reg::X1);
|
||||
m_emit->ABI_PopRegisters(m_gprs_in_use);
|
||||
@ -176,9 +174,9 @@ private:
|
||||
|
||||
m_emit->ABI_PushRegisters(m_gprs_in_use);
|
||||
float_emit.ABI_PushRegisters(m_fprs_in_use, ARM64Reg::X1);
|
||||
m_emit->MOVP2R(ARM64Reg::X1, m_system);
|
||||
m_emit->MOVI2R(ARM64Reg::W2, m_address);
|
||||
m_emit->BLR(m_emit->ABI_SetupLambda(lambda));
|
||||
|
||||
m_emit->ABI_CallLambdaFunction(lambda, m_system, m_address);
|
||||
|
||||
if (m_sign_extend)
|
||||
m_emit->SBFM(m_dst_reg, ARM64Reg::W0, 0, sbits - 1);
|
||||
else
|
||||
|
Reference in New Issue
Block a user