diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index f122fa9a61..c330f05535 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -21,7 +21,7 @@ void RawSPUThread::cpu_task() SPUThread::cpu_task(); // save next PC and current SPU Interrupt status - npc = pc | ((ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0); + npc = pc | (interrupts_enabled); } void RawSPUThread::on_init(const std::shared_ptr& _this) diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 3fcb4e6bf9..3c10a896fd 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -376,12 +376,12 @@ void spu_recompiler::FunctionCall() fmt::throw_exception("Undefined behaviour" HERE); } - _spu->set_interrupt_status(true); + _spu->interrupts_enabled = true; _spu->pc &= ~0x4000000; } else if (_spu->pc & 0x8000000) { - _spu->set_interrupt_status(false); + _spu->interrupts_enabled = false; _spu->pc &= ~0x8000000; } diff --git a/rpcs3/Emu/Cell/SPUInterpreter.cpp b/rpcs3/Emu/Cell/SPUInterpreter.cpp index fee84ae482..9f3532b3c6 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/SPUInterpreter.cpp @@ -50,9 +50,9 @@ void spu_interpreter::set_interrupt_status(SPUThread& spu, spu_opcode_t op) spu.set_interrupt_status(false); } - if ((spu.ch_event_stat & SPU_EVENT_INTR_TEST & spu.ch_event_mask) > SPU_EVENT_INTR_ENABLED) + if (spu.interrupts_enabled && (spu.ch_event_mask & spu.ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0) { - spu.ch_event_stat &= ~SPU_EVENT_INTR_ENABLED; + spu.interrupts_enabled = false; spu.srr0 = std::exchange(spu.pc, -4) + 4; } } diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 60cecc7bdf..3e1f7b0d93 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -86,9 +86,9 @@ void spu_recompiler_base::enter(SPUThread& spu) spu.pc = res & 0x3fffc; - if ((spu.ch_event_stat & SPU_EVENT_INTR_TEST & spu.ch_event_mask) > SPU_EVENT_INTR_ENABLED) + if (spu.interrupts_enabled && (spu.ch_event_mask & spu.ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0) { - spu.ch_event_stat &= ~SPU_EVENT_INTR_ENABLED; + spu.interrupts_enabled = false; spu.srr0 = std::exchange(spu.pc, 0); } } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index ccc22b1ec5..211f0e16d0 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -292,6 +292,7 @@ void SPUThread::cpu_init() ch_event_mask = 0; ch_event_stat = 0; + interrupts_enabled = false; raddr = 0; ch_dec_start_timestamp = get_timebased_time(); // ??? @@ -974,12 +975,11 @@ void SPUThread::set_interrupt_status(bool enable) { fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, mask); } - - ch_event_stat |= SPU_EVENT_INTR_ENABLED; + interrupts_enabled = true; } else { - ch_event_stat &= ~SPU_EVENT_INTR_ENABLED; + interrupts_enabled = false; } } @@ -1165,7 +1165,7 @@ bool SPUThread::get_ch_value(u32 ch, u32& out) { // HACK: "Not isolated" status // Return SPU Interrupt status in LSB - out = (ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0; + out = interrupts_enabled == true; return true; } } @@ -1467,7 +1467,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value) case SPU_WrEventMask: { // detect masking events with enabled interrupt status - if (value & ~SPU_EVENT_INTR_IMPLEMENTED && ch_event_stat & SPU_EVENT_INTR_ENABLED) + if (value & ~SPU_EVENT_INTR_IMPLEMENTED && interrupts_enabled) { fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, value); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 9e209146d1..91e61daebd 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -68,9 +68,9 @@ enum : u32 SPU_EVENT_WAITING = 0x80000000, // Originally unused, set when SPU thread starts waiting on ch_event_stat //SPU_EVENT_AVAILABLE = 0x40000000, // Originally unused, channel count of the SPU_RdEventStat channel - SPU_EVENT_INTR_ENABLED = 0x20000000, // Originally unused, represents "SPU Interrupts Enabled" status + //SPU_EVENT_INTR_ENABLED = 0x20000000, // Originally unused, represents "SPU Interrupts Enabled" status - SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_ENABLED | SPU_EVENT_INTR_IMPLEMENTED + SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_IMPLEMENTED }; // SPU Class 0 Interrupts @@ -562,6 +562,7 @@ public: atomic_t ch_event_mask; atomic_t ch_event_stat; + atomic_t interrupts_enabled; u64 ch_dec_start_timestamp; // timestamp of writing decrementer value u32 ch_dec_value; // written decrementer value