diff --git a/Source/Core/Core/DSP/DSPAnalyzer.cpp b/Source/Core/Core/DSP/DSPAnalyzer.cpp index a62de02771..67d913e278 100644 --- a/Source/Core/Core/DSP/DSPAnalyzer.cpp +++ b/Source/Core/Core/DSP/DSPAnalyzer.cpp @@ -135,9 +135,11 @@ void Analyzer::FindInstructionStarts(const SDSP& dsp, u16 start_addr, u16 end_ad // If an instruction potentially raises exceptions, mark the following // instruction as needing to check for exceptions - if (opcode->opcode == 0x00c0 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || - opcode->opcode == 0x1900 || opcode->opcode == 0x1980 || opcode->opcode == 0x2000 || - opcode->extended) + if (opcode->opcode == 0x00c0 || opcode->opcode == 0x00e0 || opcode->opcode == 0x1600 || + opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || opcode->opcode == 0x1900 || + opcode->opcode == 0x1980 || opcode->opcode == 0x1a00 || opcode->opcode == 0x1a80 || + opcode->opcode == 0x1b00 || opcode->opcode == 0x1b80 || opcode->opcode == 0x2000 || + opcode->opcode == 0x2800 || opcode->opcode == 0x2c00 || opcode->extended) { m_code_flags[static_cast(addr + opcode->size)] |= CODE_CHECK_EXC; } diff --git a/Source/Core/Core/DSP/DSPCore.cpp b/Source/Core/Core/DSP/DSPCore.cpp index 731d71e023..41c10b2428 100644 --- a/Source/Core/Core/DSP/DSPCore.cpp +++ b/Source/Core/Core/DSP/DSPCore.cpp @@ -224,11 +224,11 @@ void SDSP::CheckExternalInterrupt() control_reg &= ~CR_EXTERNAL_INT; } -void SDSP::CheckExceptions() +bool SDSP::CheckExceptions() { // Early out to skip the loop in the common case. if (exceptions == 0) - return; + return false; for (int i = 7; i > 0; i--) { @@ -247,7 +247,7 @@ void SDSP::CheckExceptions() r.sr &= ~SR_EXT_INT_ENABLE; else r.sr &= ~SR_INT_ENABLE; - break; + return true; } else { @@ -257,6 +257,8 @@ void SDSP::CheckExceptions() } } } + + return false; } u16 SDSP::ReadRegister(size_t reg) const @@ -541,9 +543,9 @@ void DSPCore::CheckExternalInterrupt() m_dsp.CheckExternalInterrupt(); } -void DSPCore::CheckExceptions() +bool DSPCore::CheckExceptions() { - m_dsp.CheckExceptions(); + return m_dsp.CheckExceptions(); } u16 DSPCore::ReadRegister(size_t reg) const diff --git a/Source/Core/Core/DSP/DSPCore.h b/Source/Core/Core/DSP/DSPCore.h index c0a5c0dba7..29bded217a 100644 --- a/Source/Core/Core/DSP/DSPCore.h +++ b/Source/Core/Core/DSP/DSPCore.h @@ -383,7 +383,7 @@ struct SDSP void SetException(ExceptionType exception); // Checks if any exceptions occurred an updates the DSP state as appropriate. - void CheckExceptions(); + bool CheckExceptions(); // Notify that an external interrupt is pending (used by thread mode) void SetExternalInterrupt(bool val); @@ -530,7 +530,7 @@ public: void CheckExternalInterrupt(); // Checks if any exceptions occurred an updates the DSP state as appropriate. - void CheckExceptions(); + bool CheckExceptions(); // Reads the current value from a particular register. u16 ReadRegister(size_t reg) const; diff --git a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp index 7066209530..f1b57ea504 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp @@ -99,9 +99,9 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset() m_dsp_core.DSPState().reset_dspjit_codespace = false; } -static void CheckExceptionsThunk(DSPCore& dsp) +static u32 CheckExceptionsThunk(DSPCore& dsp) { - dsp.CheckExceptions(); + return dsp.CheckExceptions() ? 1u : 0u; } // Must go out of block if exception is detected @@ -116,8 +116,11 @@ void DSPEmitter::checkExceptions(u32 retval) DSPJitRegCache c(m_gpr); m_gpr.SaveRegs(); ABI_CallFunctionP(CheckExceptionsThunk, &m_dsp_core); + TEST(32, R(ABI_RETURN), R(ABI_RETURN)); + FixupBranch skip_return = J_CC(CC_Z, Jump::Short); MOV(32, R(EAX), Imm32(retval)); JMP(m_return_dispatcher, Jump::Near); + SetJumpTarget(skip_return); m_gpr.LoadRegs(false); m_gpr.FlushRegs(c, false);