Add a utility function for all the ABIs to call functions with a pointer arg. Use to call Advance from the JIT with the MIPSContext. Indent some code better.

This commit is contained in:
Henrik Rydgård committed 2026-08-13 08:09:30 +02:00
1 parent 95f1dc648d
commit eb0813c0e3
22 files changed
+90 -52

No files matched your search

+1 -1
View File
@@ -442,7 +442,7 @@ void XEmitter::ABI_CallFunctionPPC(const void *func, void *param1, void *param2,
// Pass a register as a parameter.
void XEmitter::ABI_CallFunctionR(const void *func, X64Reg reg1) {
if (reg1 != ABI_PARAM1)
MOV(32, R(ABI_PARAM1), R(reg1));
MOV(64, R(ABI_PARAM1), R(reg1));
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
+15 -2
View File
@@ -1044,8 +1044,21 @@ void ARM64XEmitter::BL(const void* ptr)
}
void ARM64XEmitter::QuickCallFunction(ARM64Reg scratchreg, const void *func) {
s64 distance = (s64)func - (s64)m_code;
distance >>= 2; // Can only branch to opcode-aligned (4) addresses
s64 distance = ((s64)func - (s64)m_code) >> 2;
if (!IsInRangeImm26(distance)) {
// WARN_LOG(Log::JIT, "Distance too far in function call (%p to %p)! Using scratch.", m_code, func);
MOVI2R(scratchreg, (uintptr_t)func);
BLR(scratchreg);
} else {
BL(func);
}
}
void ARM64XEmitter::QuickCallFunctionR(ARM64Reg scratchreg, const void *func, ARM64Reg arg) {
s64 distance = ((s64)func - (s64)m_code) >> 2;
if (arg != X0) {
MOV(X0, arg);
}
if (!IsInRangeImm26(distance)) {
// WARN_LOG(Log::JIT, "Distance too far in function call (%p to %p)! Using scratch.", m_code, func);
MOVI2R(scratchreg, (uintptr_t)func);
+5
View File
@@ -776,6 +776,11 @@ public:
template <typename T> void QuickCallFunction(ARM64Reg scratchreg, T func) {
QuickCallFunction(scratchreg, (const void *)func);
}
void QuickCallFunctionR(ARM64Reg scratchreg, const void *func, ARM64Reg arg);
template <typename T> void QuickCallFunctionR(ARM64Reg scratchreg, T func, ARM64Reg arg) {
QuickCallFunctionR(scratchreg, (const void *)func, arg);
}
};
class ARM64FloatEmitter
+12
View File
@@ -557,6 +557,18 @@ void ARMXEmitter::QuickCallFunction(ARMReg reg, const void *func) {
}
}
void ARMXEmitter::QuickCallFunctionR(ARMReg reg, const void *func, ARMReg arg) {
if (arg != R0) {
MOV(R0, arg);
}
if (BLInRange(func)) {
BL(func);
} else {
MOVP2R(reg, func);
BL(reg);
}
}
void ARMXEmitter::SetCodePointer(u8 *ptr, u8 *writePtr)
{
code = ptr;
+4
View File
@@ -854,6 +854,10 @@ public:
template <typename T> void QuickCallFunction(ARMReg scratchreg, T func) {
QuickCallFunction(scratchreg, (const void *)func);
}
void QuickCallFunctionR(ARMReg scratchreg, const void *func, ARMReg arg);
template <typename T> void QuickCallFunctionR(ARMReg scratchreg, T func, ARMReg arg) {
QuickCallFunctionR(scratchreg, (const void *)func, arg);
}
// Wrapper around MOVT/MOVW with fallbacks.
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
+9 -1
View File
@@ -165,7 +165,15 @@ public:
static_assert(std::is_function<T>::value, "QuickCallFunction without function");
QuickCallFunction((const u8 *)func, scratchreg);
}
void QuickCallFunctionR(const u8 *func, LoongArch64Reg arg, LoongArch64Reg scratchreg = R_RA) {
MOVE(LoongArch64Reg::X4, arg);
QuickJump(scratchreg, R_RA, func);
}
template <typename T>
void QuickCallFunctionR(T *func, LoongArch64Reg arg, LoongArch64Reg scratchreg = R_RA) {
static_assert(std::is_function<T>::value, "QuickCallFunction without function");
QuickCallFunctionR((const u8 *)func, arg, scratchreg);
}
// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
// https://github.com/loongson-community/loongarch-opcodes/
+11
View File
@@ -226,6 +226,17 @@ public:
QuickCallFunction((const u8 *)func, scratchreg);
}
void QuickCallFunctionR(const u8 *func, RiscVReg arg, RiscVReg scratchreg = R_RA) {
if (arg != RiscVReg::X10) { // A0
MV(RiscVReg::X10, arg);
}
QuickJAL(scratchreg, R_RA, func);
}
template <typename T>
void QuickCallFunctionR(T *func, RiscVReg arg, RiscVReg scratchreg = R_RA) {
static_assert(std::is_function<T>::value, "QuickCallFunction without function");
QuickCallFunctionR((const u8 *)func, arg, scratchreg);
}
void LUI(RiscVReg rd, s32 simm32);
void AUIPC(RiscVReg rd, s32 simm32);
+1 -2
View File
@@ -379,8 +379,7 @@ void ForceCheck(MIPSState *mips) {
#endif
}
void Advance() {
MIPSState *mips = currentMIPS; // TODO: Move to parameter
void Advance(MIPSState *mips) {
PROFILE_THIS_SCOPE("advance");
int cyclesExecuted = slicelength - mips->downcount;
globalTimer += cyclesExecuted;
+1 -1
View File
@@ -113,7 +113,7 @@ namespace CoreTiming {
const Event *GetFirstEvent();
void RemoveEvent(int event_type);
bool IsScheduled(int event_type);
void Advance();
void Advance(MIPSState *mips);
void ForceCheck(MIPSState *mips);
// Pretend that the main CPU has executed enough cycles to reach the next event.
+16 -22
View File
@@ -605,8 +605,8 @@ void hleEnqueueCall(u32 func, int argc, const u32 *argv, PSPAction *afterAction)
hleAfterSyscall |= HLE_AFTER_QUEUED_CALLS;
}
void hleFlushCalls() {
u32 &sp = currentMIPS->r[MIPS_REG_SP];
static void hleFlushCalls(MIPSState *mips) {
u32 &sp = mips->r[MIPS_REG_SP];
PSPPointer<HLEMipsCallStack> stackData;
_dbg_assert_(g_stackSize == 0);
VERBOSE_LOG(Log::HLE, "Flushing %d HLE mips calls from %s, sp=%08x", (int)enqueuedMipsCalls.size(), g_stackSize ? g_stack[0]->name : "?", sp);
@@ -615,15 +615,15 @@ void hleFlushCalls() {
sp -= sizeof(HLEMipsCallStack);
stackData.ptr = sp;
stackData->nextOff = 0xFFFFFFFF;
stackData->ra = currentMIPS->pc;
stackData->v0 = currentMIPS->r[MIPS_REG_V0];
stackData->v1 = currentMIPS->r[MIPS_REG_V1];
stackData->ra = mips->pc;
stackData->v0 = mips->r[MIPS_REG_V0];
stackData->v1 = mips->r[MIPS_REG_V1];
// Now we'll set up the first in the chain.
currentMIPS->pc = enqueuedMipsCalls[0].func;
currentMIPS->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
mips->pc = enqueuedMipsCalls[0].func;
mips->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
for (int i = 0; i < (int)enqueuedMipsCalls[0].args.size(); i++) {
currentMIPS->r[MIPS_REG_A0 + i] = enqueuedMipsCalls[0].args[i];
mips->r[MIPS_REG_A0 + i] = enqueuedMipsCalls[0].args[i];
}
// For stack info, process the first enqueued call last, so we run it first.
@@ -653,6 +653,7 @@ void hleFlushCalls() {
DEBUG_LOG(Log::HLE, "Executing HLE mips call at %08x, sp=%08x", currentMIPS->pc, sp);
}
// This is a HLE function.
void HLEReturnFromMipsCall() {
u32 &sp = currentMIPS->r[MIPS_REG_SP];
PSPPointer<HLEMipsCallStack> stackData;
@@ -777,7 +778,7 @@ static void hleFinishSyscall(const HLEFunction *info) {
SetDeadbeefRegs();
if ((hleAfterSyscall & HLE_AFTER_QUEUED_CALLS) != 0)
hleFlushCalls();
hleFlushCalls(currentMIPS);
if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0 && (hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) == 0)
__KernelForceCallbacks();
@@ -806,15 +807,13 @@ void hleFinishSyscallAfterGe() {
hleFinishSyscall(nullptr);
}
static void updateSyscallStats(int modulenum, int funcnum, double total)
{
static void updateSyscallStats(int modulenum, int funcnum, double total) {
const char *name = moduleDB[modulenum].funcTable[funcnum].name;
// Ignore this one, especially for msInSyscalls (although that ignores CoreTiming events.)
if (0 == strcmp(name, "_sceKernelIdle"))
return;
if (total > kernelStats.slowestSyscallTime)
{
if (total > kernelStats.slowestSyscallTime) {
kernelStats.slowestSyscallTime = total;
kernelStats.slowestSyscallName = name;
}
@@ -822,20 +821,15 @@ static void updateSyscallStats(int modulenum, int funcnum, double total)
KernelStatsSyscall statCall(modulenum, funcnum);
auto summedStat = kernelStats.summedMsInSyscalls.find(statCall);
if (summedStat == kernelStats.summedMsInSyscalls.end())
{
if (summedStat == kernelStats.summedMsInSyscalls.end()) {
kernelStats.summedMsInSyscalls[statCall] = total;
if (total > kernelStats.summedSlowestSyscallTime)
{
if (total > kernelStats.summedSlowestSyscallTime) {
kernelStats.summedSlowestSyscallTime = total;
kernelStats.summedSlowestSyscallName = name;
}
}
else
{
} else {
double newTotal = kernelStats.summedMsInSyscalls[statCall] += total;
if (newTotal > kernelStats.summedSlowestSyscallTime)
{
if (newTotal > kernelStats.summedSlowestSyscallTime) {
kernelStats.summedSlowestSyscallTime = newTotal;
kernelStats.summedSlowestSyscallName = name;
}
+1 -1
View File
@@ -1638,7 +1638,7 @@ void __KernelReSchedule(const char *reason)
__KernelCheckCallbacks();
// Execute any pending events while we're doing scheduling.
CoreTiming::Advance();
CoreTiming::Advance(currentMIPS);
if (__IsInInterrupt() || !__KernelIsDispatchEnabled()) {
// Threads don't get changed within interrupts or while dispatch is disabled.
reason = "In Interrupt Or Callback";
+1 -1
View File
@@ -159,7 +159,7 @@ void ArmJit::GenerateFixedCode() {
outerLoop = GetCodePtr();
SaveDowncount();
RestoreRoundingMode(true);
QuickCallFunction(R0, &CoreTiming::Advance);
QuickCallFunctionR(R1, &CoreTiming::Advance, CTXREG);
ApplyRoundingMode(true);
RestoreDowncount();
FixupBranch skipToCoreStateCheck = B(); //skip the downcount check
+1 -1
View File
@@ -204,7 +204,7 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
outerLoop = GetCodePtr();
SaveStaticRegisters(); // Advance can change the downcount, so must save/restore
RestoreRoundingMode(true);
QuickCallFunction(SCRATCH1_64, &CoreTiming::Advance);
QuickCallFunctionR(SCRATCH1_64, &CoreTiming::Advance, CTXREG);
ApplyRoundingMode(true);
LoadStaticRegisters();
FixupBranch skipToCoreStateCheck = B(); //skip the downcount check
+1 -1
View File
@@ -169,7 +169,7 @@ void Arm64JitBackend::GenerateFixedCode(MIPSState *mipsState) {
SaveStaticRegisters(); // Advance can change the downcount, so must save/restore
RestoreRoundingMode(true);
WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE);
QuickCallFunction(SCRATCH1_64, &CoreTiming::Advance);
QuickCallFunctionR(SCRATCH1_64, &CoreTiming::Advance, CTXREG);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
ApplyRoundingMode(true);
LoadStaticRegisters();
+1 -1
View File
@@ -175,7 +175,7 @@ void IRJit::RunLoopUntil(u64 globalticks) {
MIPSState *mips = mips_;
while (true) {
// RestoreRoundingMode(true);
CoreTiming::Advance();
CoreTiming::Advance(currentMIPS);
// ApplyRoundingMode(true);
if (coreState != 0) {
break;
+1 -1
View File
@@ -134,7 +134,7 @@ void LoongArch64JitBackend::GenerateFixedCode(MIPSState *mipsState) {
SaveStaticRegisters();
RestoreRoundingMode(true);
WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE);
QuickCallFunction(&CoreTiming::Advance, R20);
QuickCallFunctionR(&CoreTiming::Advance, CTXREG, R20);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
ApplyRoundingMode(true);
LoadStaticRegisters();
+1 -1
View File
@@ -325,7 +325,7 @@ void MIPSState::DoState(PointerWrap &p) {
void MIPSState::SingleStep() {
int cycles = MIPS_SingleStep(this);
downcount -= cycles;
CoreTiming::Advance();
CoreTiming::Advance(currentMIPS);
}
// returns 1 if reached ticks limit
+2 -2
View File
@@ -1197,9 +1197,9 @@ static void RunUntilDowncountZeroWithChecks(MIPSState *mips, u64 globalTicks) {
int MIPSInterpret_RunUntil(MIPSState *mips, u64 globalTicks) {
while (coreState == CORE_RUNNING_CPU) {
CoreTiming::Advance();
CoreTiming::Advance(mips);
uint64_t ticksLeft = globalTicks - CoreTiming::GetTicks(currentMIPS);
uint64_t ticksLeft = globalTicks - CoreTiming::GetTicks(mips);
if (g_breakpoints.HasBreakPoints() || g_breakpoints.HasMemChecks() || ticksLeft <= mips->downcount) {
RunUntilDowncountZeroWithChecks(mips, globalTicks);
} else {
+1 -1
View File
@@ -143,7 +143,7 @@ void RiscVJitBackend::GenerateFixedCode(MIPSState *mipsState) {
SaveStaticRegisters();
RestoreRoundingMode(true);
WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE);
QuickCallFunction(&CoreTiming::Advance, X7);
QuickCallFunctionR(&CoreTiming::Advance, CTXREG, X7);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
ApplyRoundingMode(true);
LoadStaticRegisters();
+2 -1
View File
@@ -125,7 +125,8 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
outerLoop = GetCodePtr();
RestoreRoundingMode(true);
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
LEA(PTRBITS, ECX, MDisp(CTXREG, -(s32)offsetof(MIPSState, f[0]))); // Adjust to get the real pointer.
ABI_CallFunctionR(reinterpret_cast<void *>(&CoreTiming::Advance), ECX);
ApplyRoundingMode(true);
FixupBranch skipToCoreStateCheck = J(); //skip the downcount check
+2 -1
View File
@@ -167,7 +167,8 @@ void X64JitBackend::GenerateFixedCode(MIPSState *mipsState) {
SaveStaticRegisters();
RestoreRoundingMode(true);
WriteDebugProfilerStatus(IRProfilerStatus::TIMER_ADVANCE);
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
LEA(PTRBITS, ECX, MDisp(CTXREG, -(s32)offsetof(MIPSState, f[0]))); // Adjust to get the real pointer.
ABI_CallFunctionR(reinterpret_cast<void *>(&CoreTiming::Advance), ECX);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
ApplyRoundingMode(true);
LoadStaticRegisters();
+1 -11
View File
@@ -147,16 +147,6 @@ bool TestJit() {
u32 addr = currentMIPS->pc;
DebugInterface *dbg = currentDebugMIPS;
for (int i = 0; i < 100; ++i) {
/*
// VFPU ops aren't supported by MIPSAsm yet.
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
*/
std::string error;
for (size_t j = 0; j < ARRAY_SIZE(lines); ++j) {
p++;
@@ -192,7 +182,7 @@ bool TestJit() {
jit_speed = ExecCPUTest();
#if !PPSSPP_PLATFORM(MAC)
mipsr4k.UpdateCore(CPUCore::JIT_IR);
jit_ir_speed = ExecCPUTest(false);
jit_ir_speed = ExecCPUTest(false); // not clearing, so the below can do things.
#endif
// Disassemble