From d688850c79bca13a1a256feedea0bdaa51912282 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sat, 21 Jan 2023 22:53:29 -0800 Subject: [PATCH] Fix the bug --- Source/Core/Core/DSP/DSPCore.cpp | 43 +++++-------------- Source/Core/Core/DSP/DSPCore.h | 13 ------ .../Core/DSP/Interpreter/DSPInterpreter.cpp | 5 --- Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp | 34 +++------------ Source/Core/Core/DSP/Jit/x64/DSPEmitter.h | 1 - Source/Core/Core/HW/DSPLLE/DSPLLE.cpp | 7 --- 6 files changed, 18 insertions(+), 85 deletions(-) diff --git a/Source/Core/Core/DSP/DSPCore.cpp b/Source/Core/Core/DSP/DSPCore.cpp index 1c3cc19709..be40b269dd 100644 --- a/Source/Core/Core/DSP/DSPCore.cpp +++ b/Source/Core/Core/DSP/DSPCore.cpp @@ -197,28 +197,21 @@ void SDSP::SetException(ExceptionType exception) exceptions |= 1 << static_cast>(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(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(); diff --git a/Source/Core/Core/DSP/DSPCore.h b/Source/Core/Core/DSP/DSPCore.h index ff5d441692..ee3ee5d417 100644 --- a/Source/Core/Core/DSP/DSPCore.h +++ b/Source/Core/Core/DSP/DSPCore.h @@ -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 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(); diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp index c15a606281..c5b58a8b77 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp @@ -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) diff --git a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp index 8bcda1800a..5a8ba36de9 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp @@ -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(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(offsetof(SDSP, external_interrupt_waiting))); -} - Gen::OpArg DSPEmitter::M_SDSP_r_st(size_t index) { return MDisp(R15, static_cast(offsetof(SDSP, r.st) + sizeof(SDSP::r.st[0]) * index)); diff --git a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h index e4a97d2336..c0e0645d5a 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h +++ b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h @@ -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); diff --git a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp index 7b3abdb14e..f6b8c2721e 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp @@ -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(); } }