From ec6d1fb1ba7e5c9e437d267c1ec5158388f953c9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 2 Jun 2018 13:45:28 +0300 Subject: [PATCH] SPU: optimize GETLLAR (TSX) Add an option "Accurate GETLLAR" --- rpcs3/Emu/Cell/SPUThread.cpp | 46 +++++++++++++++++++++++++++++++----- rpcs3/Emu/System.h | 1 + 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 50c2ccf55a..069af53ca3 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1155,9 +1155,8 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) if (is_polling) { rtime = vm::reservation_acquire(raddr, 128); - _mm_lfence(); - while (vm::reservation_acquire(raddr, 128) == rtime && rdata == data) + while (rdata == data && vm::reservation_acquire(raddr, 128) == rtime) { if (test(state, cpu_flag::stop)) { @@ -1170,7 +1169,26 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) if (LIKELY(g_use_rtm)) { - const u64 count = spu_getll_tx(raddr, rdata.data(), &rtime); + u64 count = 0; + + if (g_cfg.core.spu_accurate_getllar) + { + count = spu_getll_tx(raddr, rdata.data(), &rtime); + } + + if (count == 0) + { + for (++count;; count++, busy_wait(300)) + { + rtime = vm::reservation_acquire(raddr, 128); + rdata = data; + + if (LIKELY(vm::reservation_acquire(raddr, 128) == rtime)) + { + break; + } + } + } if (count > 9) { @@ -1180,9 +1198,25 @@ bool SPUThread::process_mfc_cmd(spu_mfc_cmd args) else { auto& res = vm::reservation_lock(raddr, 128); - rtime = res & ~1ull; - rdata = data; - res &= ~1ull; + + if (g_cfg.core.spu_accurate_getllar) + { + vm::_ref>(raddr) += 0; + + // Full lock (heavyweight) + // TODO: vm::check_addr + vm::writer_lock lock(1); + + rtime = res & ~1ull; + rdata = data; + res &= ~1ull; + } + else + { + rtime = res & ~1ull; + rdata = data; + res &= ~1ull; + } } // Copy to LS diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index dfaf5e05a1..ffb947ea09 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -321,6 +321,7 @@ struct cfg_root : cfg::node cfg::_bool spu_loop_detection{this, "SPU loop detection", true}; //Try to detect wait loops and trigger thread yield cfg::_bool spu_shared_runtime{this, "SPU Shared Runtime", true}; // Share compiled SPU functions between all threads cfg::_enum spu_block_size{this, "SPU Block Size"}; + cfg::_bool spu_accurate_getllar{this, "Accurate GETLLAR", false}; cfg::_enum lib_loading{this, "Lib Loader", lib_loading_type::liblv2only}; cfg::_bool hook_functions{this, "Hook static functions"};