mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
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:
1 parent
95f1dc648d
commit
eb0813c0e3
22 files changed
+90
-52
No files matched your search
+1
-1
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user