From 4405f46aeca57b257223df691c234943cd87e2f5 Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 16 May 2020 20:29:39 +0300 Subject: [PATCH] SPU MFC: Fix SN interrupts --- rpcs3/Emu/Cell/SPUInterpreter.cpp | 6 +----- rpcs3/Emu/Cell/SPUThread.cpp | 26 ++++++++++++++++++++++++++ rpcs3/Emu/Cell/SPUThread.h | 1 + 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.cpp b/rpcs3/Emu/Cell/SPUInterpreter.cpp index 267b7304cc..b0af342823 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.cpp +++ b/rpcs3/Emu/Cell/SPUInterpreter.cpp @@ -112,11 +112,7 @@ void spu_interpreter::set_interrupt_status(spu_thread& spu, spu_opcode_t op) spu.set_interrupt_status(false); } - if (spu.interrupts_enabled && (spu.ch_event_mask & spu.ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0) - { - spu.interrupts_enabled = false; - spu.srr0 = std::exchange(spu.pc, 0); - } + spu.check_mfc_interrupts(spu.pc); } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 82bc1ffeaf..8e0c5a1411 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1865,6 +1865,27 @@ void spu_thread::do_mfc(bool wait) ch_tag_upd = 0; } } + + if (check_mfc_interrupts(pc + 4)) + { + spu_runtime::g_escape(this); + } +} + +bool spu_thread::check_mfc_interrupts(u32 next_pc) +{ + if (interrupts_enabled && (ch_event_mask & ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0) + { + interrupts_enabled.release(false); + srr0 = next_pc; + + // Test for BR/BRA instructions (they are equivalent at zero pc) + const u32 br = _ref(0); + pc = (br & 0xfd80007f) == 0x30000000 ? (br >> 5) & 0x3fffc : 0; + return true; + } + + return false; } u32 spu_thread::get_mfc_completed() @@ -2190,6 +2211,11 @@ bool spu_thread::process_mfc_cmd() mfc_barrier |= utils::rol32(1, cmd.tag); } + if (check_mfc_interrupts(pc + 4)) + { + spu_runtime::g_escape(this); + } + return true; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 8de43c215d..097dc8ca9a 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -669,6 +669,7 @@ public: u32 get_events(bool waiting = false); void set_events(u32 mask); void set_interrupt_status(bool enable); + bool check_mfc_interrupts(u32 nex_pc); u32 get_ch_count(u32 ch); s64 get_ch_value(u32 ch); bool set_ch_value(u32 ch, u32 value);