Fix the bug

This commit is contained in:
Pokechu22 2023-01-21 22:53:29 -08:00
commit d688850c79
6 changed files with 18 additions and 85 deletions

View file

@ -197,28 +197,21 @@ void SDSP::SetException(ExceptionType exception)
exceptions |= 1 << static_cast<std::underlying_type_t<ExceptionType>>(exception);
}
void SDSP::SetExternalInterrupt(bool val)
{
external_interrupt_waiting.store(val, std::memory_order_release);
}
void SDSP::CheckExternalInterrupt()
{
if (!IsSRFlagSet(SR_EXT_INT_ENABLE))
return;
// Signal the SPU about new mail
SetException(ExceptionType::ExternalInterrupt);
control_reg &= ~CR_EXTERNAL_INT;
}
bool SDSP::CheckExceptions()
{
// Early out to skip the loop in the common case.
if (exceptions == 0)
if (exceptions == 0 && (control_reg & CR_EXTERNAL_INT) == 0)
return false;
if ((control_reg & CR_EXTERNAL_INT) != 0)
{
if (IsSRFlagSet(SR_EXT_INT_ENABLE) && IsSRFlagSet(SR_EXT_INT_ENABLE_2))
{
SetException(ExceptionType::ExternalInterrupt);
control_reg &= ~CR_EXTERNAL_INT;
}
}
for (int i = 7; i > 0; i--)
{
// Seems exp int are not masked by sr_int_enable
@ -232,10 +225,7 @@ bool SDSP::CheckExceptions()
pc = static_cast<u16>(i * 2);
exceptions &= ~(1 << i);
if (i == 7)
r.sr &= ~SR_EXT_INT_ENABLE;
else
r.sr &= ~SR_INT_ENABLE;
r.sr &= ~SR_EXT_INT_ENABLE;
return true;
}
else
@ -384,7 +374,6 @@ void SDSP::DoState(PointerWrap& p)
p.Do(control_reg_init_code_clear_time);
p.Do(reg_stack_ptrs);
p.Do(exceptions);
p.Do(external_interrupt_waiting);
for (auto& stack : reg_stacks)
{
@ -522,16 +511,6 @@ void DSPCore::SetException(ExceptionType exception)
m_dsp.SetException(exception);
}
void DSPCore::SetExternalInterrupt(bool val)
{
m_dsp.SetExternalInterrupt(val);
}
void DSPCore::CheckExternalInterrupt()
{
m_dsp.CheckExternalInterrupt();
}
bool DSPCore::CheckExceptions()
{
return m_dsp.CheckExceptions();

View file

@ -400,12 +400,6 @@ struct SDSP
// Returns true if PC changed.
bool CheckExceptions();
// Notify that an external interrupt is pending (used by thread mode)
void SetExternalInterrupt(bool val);
// Coming from the CPU
void CheckExternalInterrupt();
// Stores a value into the specified stack
void StoreStack(StackRegister stack_reg, u16 val);
@ -443,7 +437,6 @@ struct SDSP
u8 reg_stack_ptrs[4]{};
u8 exceptions = 0; // pending exceptions
std::atomic<bool> external_interrupt_waiting = false;
bool reset_dspjit_codespace = false;
// DSP hardware stacks. They're mapped to a bunch of registers, such that writes
@ -538,12 +531,6 @@ public:
// and sets a flag in the pending exception register.
void SetException(ExceptionType exception);
// Notify that an external interrupt is pending (used by thread mode)
void SetExternalInterrupt(bool val);
// Coming from the CPU
void CheckExternalInterrupt();
// Checks if any exceptions occurred and updates the DSP state as appropriate.
// Returns true if PC changed.
bool CheckExceptions();

View file

@ -90,11 +90,6 @@ int Interpreter::RunCyclesThread(int cycles)
if ((state.control_reg & CR_HALT) != 0)
return 0;
if (state.external_interrupt_waiting.exchange(false, std::memory_order_acquire))
{
m_dsp_core.CheckExternalInterrupt();
}
Step();
cycles--;
if (cycles <= 0)

View file

@ -50,12 +50,6 @@ DSPEmitter::~DSPEmitter()
u16 DSPEmitter::RunCycles(u16 cycles)
{
if (m_dsp_core.DSPState().external_interrupt_waiting.exchange(false, std::memory_order_acquire))
{
m_dsp_core.CheckExternalInterrupt();
m_dsp_core.CheckExceptions();
}
m_cycles_left = cycles;
auto exec_addr = (DSPCompiledCode)m_enter_dispatcher;
exec_addr();
@ -109,7 +103,12 @@ void DSPEmitter::checkExceptions(u16 retval)
{
// Check for interrupts and exceptions
TEST(8, M_SDSP_exceptions(), Imm8(0xff));
FixupBranch skipCheck = J_CC(CC_Z, Jump::Near);
FixupBranch skipCheck = J_CC(CC_NZ, Jump::Near);
TEST(16, M_SDSP_control_reg(), Imm16(CR_EXTERNAL_INT));
FixupBranch skipCheck2 = J_CC(CC_Z, Jump::Near);
SetJumpTarget(skipCheck);
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc));
@ -122,7 +121,7 @@ void DSPEmitter::checkExceptions(u16 retval)
m_gpr.LoadRegs(false); // TODO: Does this still make sense?
m_gpr.FlushRegs(c, false);
SetJumpTarget(skipCheck);
SetJumpTarget(skipCheck2);
}
bool DSPEmitter::FlagsNeeded() const
@ -437,13 +436,6 @@ void DSPEmitter::CompileDispatcher()
const u8* dispatcherLoop = GetCodePtr();
FixupBranch exceptionExit;
if (Host::OnThread())
{
CMP(8, M_SDSP_external_interrupt_waiting(), Imm8(0));
exceptionExit = J_CC(CC_NE);
}
// Check for DSP halt
TEST(8, M_SDSP_control_reg(), Imm8(CR_HALT));
FixupBranch _halt = J_CC(CC_NE);
@ -463,10 +455,6 @@ void DSPEmitter::CompileDispatcher()
// DSP gave up the remaining cycles.
SetJumpTarget(_halt);
if (Host::OnThread())
{
SetJumpTarget(exceptionExit);
}
// MOV(32, M(&cyclesLeft), Imm32(0));
ABI_PopRegistersAndAdjustStack(registers_used, 8);
RET();
@ -491,14 +479,6 @@ Gen::OpArg DSPEmitter::M_SDSP_control_reg()
return MDisp(R15, static_cast<int>(offsetof(SDSP, control_reg)));
}
Gen::OpArg DSPEmitter::M_SDSP_external_interrupt_waiting()
{
static_assert(decltype(SDSP::external_interrupt_waiting)::is_always_lock_free &&
sizeof(SDSP::external_interrupt_waiting) == sizeof(u8));
return MDisp(R15, static_cast<int>(offsetof(SDSP, external_interrupt_waiting)));
}
Gen::OpArg DSPEmitter::M_SDSP_r_st(size_t index)
{
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.st) + sizeof(SDSP::r.st[0]) * index));

View file

@ -293,7 +293,6 @@ private:
Gen::OpArg M_SDSP_pc();
Gen::OpArg M_SDSP_exceptions();
Gen::OpArg M_SDSP_control_reg();
Gen::OpArg M_SDSP_external_interrupt_waiting();
Gen::OpArg M_SDSP_r_st(size_t index);
Gen::OpArg M_SDSP_reg_stack_ptrs(size_t index);

View file

@ -192,13 +192,6 @@ u16 DSPLLE::DSP_WriteControlRegister(u16 value)
// External interrupt pending: this is the zelda ucode.
// Disable the DSP thread because there is no performance gain.
m_request_disable_thread = true;
m_dsp_core.SetExternalInterrupt(true);
}
else
{
m_dsp_core.CheckExternalInterrupt();
m_dsp_core.CheckExceptions();
}
}