diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index a33f973df8..2673685bb2 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4125,7 +4125,7 @@ bool spu_thread::process_mfc_cmd() if (raddr != addr) { // Last check for event before we replace the reservation with a new one - if (reservation_check(raddr, rdata)) + if (~ch_events.load().events & SPU_EVENT_LR && reservation_check(raddr, rdata, addr)) { set_events(SPU_EVENT_LR); } @@ -4821,7 +4821,7 @@ bool spu_thread::process_mfc_cmd() ch_mfc_cmd.cmd, ch_mfc_cmd.lsa, ch_mfc_cmd.eal, ch_mfc_cmd.tag, ch_mfc_cmd.size); } -bool spu_thread::reservation_check(u32 addr, const decltype(rdata)& data) const +bool spu_thread::reservation_check(u32 addr, const decltype(rdata)& data, u32 current_eal) const { if (!addr) { @@ -4840,6 +4840,21 @@ bool spu_thread::reservation_check(u32 addr, const decltype(rdata)& data) const return !cmp_rdata(data, *vm::get_super_ptr(addr)); } + if ((addr >> 20) == (current_eal >> 20)) + { + if (vm::check_addr(addr, vm::page_1m_size)) + { + // Same random-access-memory page as the current MFC command, assume allocated + return !cmp_rdata(data, vm::_ref(addr)); + } + + if ((addr >> 16) == (current_eal >> 16) && vm::check_addr(addr, vm::page_64k_size)) + { + // Same random-access-memory page as the current MFC command, assume allocated + return !cmp_rdata(data, vm::_ref(addr)); + } + } + // Ensure data is allocated (HACK: would raise LR event if not) // Set range_lock first optimistically range_lock->store(u64{128} << 32 | addr | vm::range_readable); diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 36d24ff55e..9adb15a47c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -901,7 +901,8 @@ public: // Returns true if reservation existed but was just discovered to be lost // It is safe to use on any address, even if not directly accessed by SPU (so it's slower) - bool reservation_check(u32 addr, const decltype(rdata)& data) const; + // Optionally pass a known allocated address for internal optimization (the current Effective-Address of the MFC command) + bool reservation_check(u32 addr, const decltype(rdata)& data, u32 current_eal = 0) const; static bool reservation_check(u32 addr, u32 hash, atomic_t* range_lock); usz register_cache_line_waiter(u32 addr); void deregister_cache_line_waiter(usz index);