mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-21 09:49:01 +00:00
Fix the bug
This commit is contained in:
parent
e7daeeac09
commit
d688850c79
6 changed files with 18 additions and 85 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue