DSP JIT: Fix infinite loop if an exception is suppressed

I'm not 100% sure about the LoadRegs(false) part.
This commit is contained in:
Pokechu22 2023-01-15 17:50:28 -08:00
commit 59e59e6903
4 changed files with 21 additions and 16 deletions

View file

@ -213,11 +213,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--)
{ {
@ -236,7 +236,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
{ {
@ -246,6 +246,8 @@ void SDSP::CheckExceptions()
} }
} }
} }
return false;
} }
u16 SDSP::ReadRegister(size_t reg) const u16 SDSP::ReadRegister(size_t reg) const
@ -530,9 +532,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

@ -382,8 +382,9 @@ struct SDSP
// and sets a flag in the pending exception register. // and sets a flag in the pending exception register.
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 and updates the DSP state as appropriate.
void CheckExceptions(); // Returns true if PC changed.
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);
@ -529,8 +530,9 @@ public:
// Coming from the CPU // Coming from the CPU
void CheckExternalInterrupt(); void CheckExternalInterrupt();
// Checks if any exceptions occurred an updates the DSP state as appropriate. // Checks if any exceptions occurred and updates the DSP state as appropriate.
void CheckExceptions(); // Returns true if PC changed.
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,13 +99,13 @@ 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 bool CheckExceptionsThunk(DSPCore& dsp)
{ {
dsp.CheckExceptions(); return dsp.CheckExceptions();
} }
// Must go out of block if exception is detected // Must go out of block if exception is detected
void DSPEmitter::checkExceptions(u32 retval) void DSPEmitter::checkExceptions(u16 retval)
{ {
// Check for interrupts and exceptions // Check for interrupts and exceptions
TEST(8, M_SDSP_exceptions(), Imm8(0xff)); TEST(8, M_SDSP_exceptions(), Imm8(0xff));
@ -116,9 +116,10 @@ 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);
MOV(32, R(EAX), Imm32(retval)); TEST(8, R(ABI_RETURN), R(ABI_RETURN));
JMP(m_return_dispatcher, Jump::Near); MOV(16, R(EAX), Imm16(retval));
m_gpr.LoadRegs(false); J_CC(CC_NZ, m_return_dispatcher);
m_gpr.LoadRegs(false); // TODO: Does this still make sense?
m_gpr.FlushRegs(c, false); m_gpr.FlushRegs(c, false);
SetJumpTarget(skipCheck); SetJumpTarget(skipCheck);

View file

@ -263,7 +263,7 @@ private:
// Register helpers // Register helpers
void setCompileSR(u16 bit); void setCompileSR(u16 bit);
void clrCompileSR(u16 bit); void clrCompileSR(u16 bit);
void checkExceptions(u32 retval); void checkExceptions(u16 retval);
// Memory helper functions // Memory helper functions
void increment_addr_reg(int reg); void increment_addr_reg(int reg);