Merge pull request #13732 from AdmiralCurtiss/dsp-jit-exceptions

DSP LLE Recompiler: Fix exception handling after #10766
This commit is contained in:
JMC47
2025-06-05 15:17:30 -04:00
committed by GitHub
4 changed files with 19 additions and 12 deletions

View File

@ -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 // If an instruction potentially raises exceptions, mark the following
// instruction as needing to check for exceptions // instruction as needing to check for exceptions
if (opcode->opcode == 0x00c0 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || if (opcode->opcode == 0x00c0 || opcode->opcode == 0x00e0 || opcode->opcode == 0x1600 ||
opcode->opcode == 0x1900 || opcode->opcode == 0x1980 || opcode->opcode == 0x2000 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || opcode->opcode == 0x1900 ||
opcode->extended) 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<u16>(addr + opcode->size)] |= CODE_CHECK_EXC; m_code_flags[static_cast<u16>(addr + opcode->size)] |= CODE_CHECK_EXC;
} }

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);