diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index f38e2a3a08..915e9fa5f3 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -74,7 +74,7 @@ extern atomic_t g_progr_ptotal; extern atomic_t g_progr_pdone; // Should be of the same type -using spu_rdata_t = decltype(ppu_thread::full_rdata); +using spu_rdata_t = decltype(ppu_thread::rdata); extern void mov_rdata(spu_rdata_t& _dst, const spu_rdata_t& _src); extern bool cmp_rdata(const spu_rdata_t& _lhs, const spu_rdata_t& _rhs); @@ -1182,12 +1182,11 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr) continue; } - const u64 rdata = data; + const auto rdata = data.load(); if (ppu.use_full_rdata) { - mov_rdata(ppu.full_rdata, vm::_ref(addr & -128)); - reinterpret_cast&>(ppu.full_rdata[addr & 0x78]) = rdata; // Must match with rdata and must be of atomic 64-bits load + mov_rdata(ppu.rdata, vm::_ref(addr & -128)); } if ((vm::reservation_acquire(addr, sizeof(T)) & mask_res) == ppu.rtime) [[likely]] @@ -1197,8 +1196,8 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr) ppu_log.warning("%s took too long: %u", sizeof(T) == 4 ? "LWARX" : "LDARX", count); } - ppu.rdata = rdata; - return static_cast(ppu.rdata << data_off >> size_off); + std::memcpy(&ppu.rdata[addr & 0x78], &rdata, 8); // Store atomic 64bits of rdata + return static_cast(rdata << data_off >> size_off); } } } @@ -1384,7 +1383,7 @@ const auto ppu_stcx_accurate_tx = build_function_asm(cpu_flag::wait)); + c.lock().bts(x86::dword_ptr(args[2], ::offset32(&ppu_thread::state) - ::offset32(&ppu_thread::rdata)), static_cast(cpu_flag::wait)); // Touch memory if transaction failed without RETRY flag on the first attempt c.cmp(x86::r12, 1); @@ -1514,7 +1513,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) auto& data = vm::_ref>(addr & -8); auto& res = vm::reservation_acquire(addr, sizeof(T)); - const u64 old_data = ppu.rdata; + const u64 old_data = reinterpret_cast&>(ppu.rdata[addr & 0x78]); const u64 rtime = ppu.rtime; if constexpr (sizeof(T) == sizeof(u32)) @@ -1564,7 +1563,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) { if (g_use_rtm) [[likely]] { - switch (ppu_stcx_accurate_tx(addr & -8, rtime, ppu.full_rdata, reg_value)) + switch (ppu_stcx_accurate_tx(addr & -8, rtime, ppu.rdata, reg_value)) { case 0: { @@ -1581,7 +1580,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) cpu_thread::suspend_all cpu_lock(&ppu); // Give up if PUTLLUC happened - if (res == (rtime | 1) && cmp_rdata(ppu.full_rdata, vm::_ref(addr & -128))) + if (res == (rtime | 1) && cmp_rdata(ppu.rdata, vm::_ref(addr & -128))) { data.release(reg_value); res.release(rtime + 128); @@ -1616,7 +1615,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) // TODO: vm::check_addr vm::writer_lock lock(addr); - if (cmp_rdata(ppu.full_rdata, super_data)) + if (cmp_rdata(ppu.rdata, super_data)) { data.release(reg_value); res.release(rtime + 128); @@ -1665,7 +1664,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value) return false; } - if (!vm::reservation_trylock(res, ppu.rtime)) + if (!vm::reservation_trylock(res, rtime)) { return false; } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 6e5d3ca16b..4fb4cfdc07 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -193,8 +193,7 @@ public: u32 raddr{0}; // Reservation addr u64 rtime{0}; - u64 rdata{0}; // Reservation data - alignas(64) std::byte full_rdata[128]{}; // Full reservation data + alignas(64) std::byte rdata[128]{}; // Reservation data bool use_full_rdata{}; atomic_t prio{0}; // Thread priority (0..3071)