From f4af3f2987a27a28025be2b7711be4b2771cebe9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 28 Apr 2018 20:09:35 +0300 Subject: [PATCH] PPU: improve LWARX/LDARX consistency --- rpcs3/Emu/Cell/PPUThread.cpp | 46 ++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index db10680317..c89d6fa6f0 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -934,22 +934,48 @@ static void ppu_trace(u64 addr) LOG_NOTICE(PPU, "Trace: 0x%llx", addr); } +template +static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr) +{ + auto& data = vm::_ref>(addr); + + ppu.raddr = addr; + + // Do several attemps + for (uint i = 0; i < 5; i++) + { + ppu.rtime = vm::reservation_acquire(addr, sizeof(T)); + _mm_lfence(); + + // Check LSB: atomic store may be in progress + if (LIKELY((ppu.rtime & 1) == 0)) + { + ppu.rdata = data; + _mm_lfence(); + + if (LIKELY(vm::reservation_acquire(addr, sizeof(T)) == ppu.rtime)) + { + return static_cast(ppu.rdata); + } + } + + busy_wait(300); + } + + vm::reader_lock lock; + ppu.rtime = vm::reservation_acquire(addr, sizeof(T)); + ppu.rdata = data; + return static_cast(ppu.rdata); +} + extern u32 ppu_lwarx(ppu_thread& ppu, u32 addr) { - ppu.rtime = vm::reservation_acquire(addr, sizeof(u32)); - _mm_lfence(); - ppu.raddr = addr; - ppu.rdata = vm::_ref>(addr); - return static_cast(ppu.rdata); + return ppu_load_acquire_reservation(ppu, addr); } extern u64 ppu_ldarx(ppu_thread& ppu, u32 addr) { - ppu.rtime = vm::reservation_acquire(addr, sizeof(u64)); - _mm_lfence(); - ppu.raddr = addr; - ppu.rdata = vm::_ref>(addr); - return ppu.rdata; + return ppu_load_acquire_reservation(ppu, addr); } extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)