DSP/Jit: Don't return to dispatcher if no exception was generated

This commit is contained in:
Admiral H. Curtiss
2025-06-05 17:35:42 +02:00
parent a43fc68452
commit ea959f2651
3 changed files with 14 additions and 9 deletions

View File

@ -224,11 +224,11 @@ void SDSP::CheckExternalInterrupt()
control_reg &= ~CR_EXTERNAL_INT; control_reg &= ~CR_EXTERNAL_INT;
} }
void SDSP::CheckExceptions() bool SDSP::CheckExceptions()
{ {
// Early out to skip the loop in the common case. // Early out to skip the loop in the common case.
if (exceptions == 0) if (exceptions == 0)
return; return false;
for (int i = 7; i > 0; i--) for (int i = 7; i > 0; i--)
{ {
@ -247,7 +247,7 @@ void SDSP::CheckExceptions()
r.sr &= ~SR_EXT_INT_ENABLE; r.sr &= ~SR_EXT_INT_ENABLE;
else else
r.sr &= ~SR_INT_ENABLE; r.sr &= ~SR_INT_ENABLE;
break; return true;
} }
else else
{ {
@ -257,6 +257,8 @@ void SDSP::CheckExceptions()
} }
} }
} }
return false;
} }
u16 SDSP::ReadRegister(size_t reg) const u16 SDSP::ReadRegister(size_t reg) const
@ -541,9 +543,9 @@ void DSPCore::CheckExternalInterrupt()
m_dsp.CheckExternalInterrupt(); m_dsp.CheckExternalInterrupt();
} }
void DSPCore::CheckExceptions() bool DSPCore::CheckExceptions()
{ {
m_dsp.CheckExceptions(); return m_dsp.CheckExceptions();
} }
u16 DSPCore::ReadRegister(size_t reg) const u16 DSPCore::ReadRegister(size_t reg) const

View File

@ -383,7 +383,7 @@ struct SDSP
void SetException(ExceptionType exception); void SetException(ExceptionType exception);
// Checks if any exceptions occurred an updates the DSP state as appropriate. // 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) // Notify that an external interrupt is pending (used by thread mode)
void SetExternalInterrupt(bool val); void SetExternalInterrupt(bool val);
@ -530,7 +530,7 @@ public:
void CheckExternalInterrupt(); void CheckExternalInterrupt();
// Checks if any exceptions occurred an updates the DSP state as appropriate. // Checks if any exceptions occurred an updates the DSP state as appropriate.
void CheckExceptions(); bool CheckExceptions();
// Reads the current value from a particular register. // Reads the current value from a particular register.
u16 ReadRegister(size_t reg) const; u16 ReadRegister(size_t reg) const;

View File

@ -99,9 +99,9 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
m_dsp_core.DSPState().reset_dspjit_codespace = false; 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 // Must go out of block if exception is detected
@ -116,8 +116,11 @@ void DSPEmitter::checkExceptions(u32 retval)
DSPJitRegCache c(m_gpr); DSPJitRegCache c(m_gpr);
m_gpr.SaveRegs(); m_gpr.SaveRegs();
ABI_CallFunctionP(CheckExceptionsThunk, &m_dsp_core); 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)); MOV(32, R(EAX), Imm32(retval));
JMP(m_return_dispatcher, Jump::Near); JMP(m_return_dispatcher, Jump::Near);
SetJumpTarget(skip_return);
m_gpr.LoadRegs(false); m_gpr.LoadRegs(false);
m_gpr.FlushRegs(c, false); m_gpr.FlushRegs(c, false);