From 1559ce3f262b5b6a99808ab17c521e17860e4360 Mon Sep 17 00:00:00 2001 From: elad335 <18193363+elad335@users.noreply.github.com> Date: Tue, 13 May 2025 17:32:12 +0300 Subject: [PATCH] SPU: Improved GETLLAR spin detection conditions --- rpcs3/Emu/Cell/SPUThread.cpp | 21 +++++++++++++++++++++ rpcs3/Emu/Cell/SPUThread.h | 1 + 2 files changed, 22 insertions(+) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 8f812b5a4c..a227480a48 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4781,6 +4781,26 @@ bool spu_thread::process_mfc_cmd() return true; } + if (last_getllar != pc || last_getllar_lsa != ch_mfc_cmd.lsa) + { + getllar_busy_waiting_switch = umax; + getllar_spin_count = 0; + return true; + } + + // Check if LSA points to an OUT buffer on the stack from a caller - unlikely to be a loop + if (last_getllar_lsa >= SPU_LS_SIZE - 0x10000 && last_getllar_lsa > last_getllar_gpr1) + { + auto cs = dump_callstack_list(); + + if (!cs.empty() && last_getllar_lsa > cs[0].second) + { + getllar_busy_waiting_switch = umax; + getllar_spin_count = 0; + return true; + } + } + getllar_spin_count = std::min(getllar_spin_count + 1, u16{umax}); if (getllar_busy_waiting_switch == umax && getllar_spin_count == 4) @@ -4826,6 +4846,7 @@ bool spu_thread::process_mfc_cmd() last_getllar = pc; last_getllar_gpr1 = gpr[1]._u32[3]; + last_getllar_lsa = ch_mfc_cmd.lsa; if (getllar_busy_waiting_switch == 1) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index ce84e9e1b1..5a0d9bab31 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -802,6 +802,7 @@ public: u32 last_getllar = umax; // LS address of last GETLLAR (if matches current GETLLAR we can let the thread rest) u32 last_getllar_gpr1 = umax; u32 last_getllar_addr = umax; + u32 last_getllar_lsa = umax; u32 getllar_spin_count = 0; u32 getllar_busy_waiting_switch = umax; // umax means the test needs evaluation, otherwise it's a boolean u64 getllar_evaluate_time = 0;