mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-27 04:36:18 +00:00
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:
parent
dd76c0d1a0
commit
59e59e6903
4 changed files with 21 additions and 16 deletions
|
@ -213,11 +213,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--)
|
||||
{
|
||||
|
@ -236,7 +236,7 @@ void SDSP::CheckExceptions()
|
|||
r.sr &= ~SR_EXT_INT_ENABLE;
|
||||
else
|
||||
r.sr &= ~SR_INT_ENABLE;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -246,6 +246,8 @@ void SDSP::CheckExceptions()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u16 SDSP::ReadRegister(size_t reg) const
|
||||
|
@ -530,9 +532,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
|
||||
|
|
|
@ -382,8 +382,9 @@ struct SDSP
|
|||
// and sets a flag in the pending exception register.
|
||||
void SetException(ExceptionType exception);
|
||||
|
||||
// Checks if any exceptions occurred an updates the DSP state as appropriate.
|
||||
void CheckExceptions();
|
||||
// Checks if any exceptions occurred and updates the DSP state as appropriate.
|
||||
// Returns true if PC changed.
|
||||
bool CheckExceptions();
|
||||
|
||||
// Notify that an external interrupt is pending (used by thread mode)
|
||||
void SetExternalInterrupt(bool val);
|
||||
|
@ -529,8 +530,9 @@ public:
|
|||
// Coming from the CPU
|
||||
void CheckExternalInterrupt();
|
||||
|
||||
// Checks if any exceptions occurred an updates the DSP state as appropriate.
|
||||
void CheckExceptions();
|
||||
// Checks if any exceptions occurred and updates the DSP state as appropriate.
|
||||
// Returns true if PC changed.
|
||||
bool CheckExceptions();
|
||||
|
||||
// Reads the current value from a particular register.
|
||||
u16 ReadRegister(size_t reg) const;
|
||||
|
|
|
@ -99,13 +99,13 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
|
|||
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
|
||||
void DSPEmitter::checkExceptions(u32 retval)
|
||||
void DSPEmitter::checkExceptions(u16 retval)
|
||||
{
|
||||
// Check for interrupts and exceptions
|
||||
TEST(8, M_SDSP_exceptions(), Imm8(0xff));
|
||||
|
@ -116,9 +116,10 @@ void DSPEmitter::checkExceptions(u32 retval)
|
|||
DSPJitRegCache c(m_gpr);
|
||||
m_gpr.SaveRegs();
|
||||
ABI_CallFunctionP(CheckExceptionsThunk, &m_dsp_core);
|
||||
MOV(32, R(EAX), Imm32(retval));
|
||||
JMP(m_return_dispatcher, Jump::Near);
|
||||
m_gpr.LoadRegs(false);
|
||||
TEST(8, R(ABI_RETURN), R(ABI_RETURN));
|
||||
MOV(16, R(EAX), Imm16(retval));
|
||||
J_CC(CC_NZ, m_return_dispatcher);
|
||||
m_gpr.LoadRegs(false); // TODO: Does this still make sense?
|
||||
m_gpr.FlushRegs(c, false);
|
||||
|
||||
SetJumpTarget(skipCheck);
|
||||
|
|
|
@ -263,7 +263,7 @@ private:
|
|||
// Register helpers
|
||||
void setCompileSR(u16 bit);
|
||||
void clrCompileSR(u16 bit);
|
||||
void checkExceptions(u32 retval);
|
||||
void checkExceptions(u16 retval);
|
||||
|
||||
// Memory helper functions
|
||||
void increment_addr_reg(int reg);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue