diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index f90dc79bfe..007bedae2e 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -52,6 +52,8 @@ enum HLE_AFTER_RUN_INTERRUPTS = 0x10, // Switch to CORE_STEPPING after the syscall (for debugging.) HLE_AFTER_DEBUG_BREAK = 0x20, + // Don't fill temp regs with 0xDEADBEEF. + HLE_AFTER_SKIP_DEADBEEF = 0x40, }; typedef std::vector SyscallVector; @@ -287,6 +289,11 @@ void hleDebugBreak() hleAfterSyscall |= HLE_AFTER_DEBUG_BREAK; } +void hleSkipDeadbeef() +{ + hleAfterSyscall |= HLE_AFTER_SKIP_DEADBEEF; +} + // Pauses execution after an HLE call. bool hleExecuteDebugBreak(const HLEFunction &func) { @@ -341,8 +348,26 @@ void hleEatMicro(int usec) hleEatCycles((int) usToCycles(usec)); } +const static u32 deadbeefRegs[12] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF}; +inline static void SetDeadbeefRegs() +{ + // TODO: Debug setting? + currentMIPS->r[MIPS_REG_COMPILER_SCRATCH] = 0xDEADBEEF; + // Set all the arguments and temp regs. + memcpy(¤tMIPS->r[MIPS_REG_A0], deadbeefRegs, sizeof(deadbeefRegs)); + // Using a magic number since there's confusion/disagreement on reg names. + currentMIPS->r[24] = 0xDEADBEEF; + currentMIPS->r[25] = 0xDEADBEEF; + + currentMIPS->lo = 0xDEADBEEF; + currentMIPS->hi = 0xDEADBEEF; +} + inline void hleFinishSyscall(int modulenum, int funcnum) { + if ((hleAfterSyscall & HLE_AFTER_SKIP_DEADBEEF) == 0) + SetDeadbeefRegs(); + if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) __KernelForceCallbacks(); @@ -449,6 +474,8 @@ void CallSyscall(MIPSOpcode op) if (hleAfterSyscall != HLE_AFTER_NOTHING) hleFinishSyscall(modulenum, funcnum); + else + SetDeadbeefRegs(); } else { diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 3e22d2e2a3..5650022168 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -91,6 +91,8 @@ void hleReSchedule(bool callbacks, const char *reason); void hleRunInterrupts(); // Pause emulation after the syscall finishes. void hleDebugBreak(); +// Don't set temp regs to 0xDEADBEEF. +void hleSkipDeadbeef(); // Delays the result for usec microseconds, allowing other threads to run during this time. u32 hleDelayResult(u32 result, const char *reason, int usec); diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 0ffda2646e..e38d01e432 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -405,6 +405,8 @@ void __KernelReturnFromInterrupt() { VERBOSE_LOG(SCEINTC, "Left interrupt handler at %08x", currentMIPS->pc); + hleSkipDeadbeef(); + // This is what we just ran. PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 204ddfe25f..db5e1e1a2a 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1601,6 +1601,7 @@ u32 sceKernelStopUnloadSelfModuleWithStatus(u32 exitCode, u32 argSize, u32 argp, void __KernelReturnFromModuleFunc() { // Return from the thread as normal. + hleSkipDeadbeef(); __KernelReturnFromThread(); SceUID leftModuleID = __KernelGetCurThreadModuleId(); diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 17bf47c846..7c9ea34949 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1284,6 +1284,7 @@ bool __KernelSwitchOffThread(const char *reason) Thread *t = kernelObjects.GetFast(threadIdleID[0]); if (t) { + hleSkipDeadbeef(); __KernelSwitchContext(t, reason); return true; } @@ -1327,6 +1328,8 @@ bool __KernelSwitchToThread(SceUID threadID, const char *reason) void __KernelIdle() { + hleSkipDeadbeef(); + CoreTiming::Idle(); // Advance must happen between Idle and Reschedule, so that threads that were waiting for something // that was triggered at the end of the Idle period must get a chance to be scheduled. @@ -2206,6 +2209,8 @@ int sceKernelGetThreadStackFreeSize(SceUID threadID) void __KernelReturnFromThread() { + hleSkipDeadbeef(); + int exitStatus = currentMIPS->r[MIPS_REG_V0]; Thread *thread = __GetCurrentThread(); _dbg_assert_msg_(SCEKERNEL, thread != NULL, "Returned from a NULL thread."); @@ -3001,11 +3006,14 @@ u32 sceKernelExtendThreadStack(u32 size, u32 entryAddr, u32 entryParameter) // Stack should stay aligned even though we saved only 3 regs. currentMIPS->r[MIPS_REG_SP] = thread->currentStack.end - 0x10; + hleSkipDeadbeef(); return 0; } void __KernelReturnFromExtendStack() { + hleSkipDeadbeef(); + Thread *thread = __GetCurrentThread(); if (!thread) { @@ -3269,6 +3277,7 @@ bool __CanExecuteCallbackNow(Thread *thread) { void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, const u32 args[], int numargs, bool reschedAfter, SceUID cbId) { + hleSkipDeadbeef(); _dbg_assert_msg_(SCEKERNEL, numargs <= 6, "MipsCalls can only take 6 args."); if (thread) { @@ -3376,6 +3385,8 @@ void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter) void __KernelReturnFromMipsCall() { + hleSkipDeadbeef(); + Thread *cur = __GetCurrentThread(); if (cur == NULL) {