SPU LLVM: Enable PUTLLC16 if accurate reservations is off

This commit is contained in:
Elad Ashkenazi 2024-08-11 16:31:18 +03:00
parent f980c59860
commit 60b7448d8a
2 changed files with 33 additions and 48 deletions

View file

@ -7133,8 +7133,9 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
value.reg2 = pattern.reg2; value.reg2 = pattern.reg2;
} }
if (true) if (g_cfg.core.spu_accurate_reservations)
{ {
// Because enabling it is a hack, as it turns out
continue; continue;
} }

View file

@ -1196,7 +1196,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (g_cfg.core.rsx_accurate_res_access) if (g_cfg.core.rsx_accurate_res_access)
{ {
call("spu_putllc16_rsx_res", +[](spu_thread* _spu, u32 ls_dst, u32 lsa, u32 eal, u32 notify) const auto success = call("spu_putllc16_rsx_res", +[](spu_thread* _spu, u32 ls_dst, u32 lsa, u32 eal, u32 notify) -> bool
{ {
const u32 raddr = eal; const u32 raddr = eal;
@ -1207,35 +1207,22 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto _dest = vm::get_super_ptr<atomic_t<nse_t<v128>>>(dest); const auto _dest = vm::get_super_ptr<atomic_t<nse_t<v128>>>(dest);
using spu_rdata_t = decltype(spu_thread::rdata); using spu_rdata_t = decltype(spu_thread::rdata);
extern bool cmp_rdata(const spu_rdata_t& _lhs, const spu_rdata_t& _rhs);
// if (!cmp_rdata(*reinterpret_cast<const decltype(_spu->rdata)*>(_dest), _spu->rdata))
// {
// _spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
// _spu->set_events(SPU_EVENT_LR);
// _spu->raddr = 0;
// return;
// }
if (rdata == to_write || ((lsa ^ ls_dst) & (SPU_LS_SIZE - 128))) if (rdata == to_write || ((lsa ^ ls_dst) & (SPU_LS_SIZE - 128)))
{ {
vm::reservation_update(raddr); vm::reservation_update(raddr);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS); _spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS);
_spu->raddr = 0; _spu->raddr = 0;
return; return true;
} }
const u64 rtime = _spu->rtime;
auto& res = vm::reservation_acquire(eal); auto& res = vm::reservation_acquire(eal);
if (res != rtime) if (res % 128)
{ {
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE); return false;
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
} }
{
rsx::reservation_lock rsx_lock(raddr, 128); rsx::reservation_lock rsx_lock(raddr, 128);
// Touch memory // Touch memory
@ -1243,7 +1230,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
auto [old_res, ok] = res.fetch_op([&](u64& rval) auto [old_res, ok] = res.fetch_op([&](u64& rval)
{ {
if (rtime != rval) if (rval % 128)
{ {
return false; return false;
} }
@ -1254,23 +1241,18 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
if (!ok) if (!ok)
{ {
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE); return false;
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
} }
if (!_dest->compare_and_swap_test(rdata, to_write)) if (!_dest->compare_and_swap_test(rdata, to_write))
{ {
res.release(old_res); res.release(old_res);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE); return false;
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
} }
// Success // Success
res.release(old_res + 128); res.release(old_res + 128);
}
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS); _spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS);
_spu->raddr = 0; _spu->raddr = 0;
@ -1279,10 +1261,12 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
{ {
res.notify_all(); res.notify_all();
} }
return true;
}, m_thread, dest, _lsa, _eal, m_ir->getInt32(!info.no_notify)); }, m_thread, dest, _lsa, _eal, m_ir->getInt32(!info.no_notify));
m_ir->CreateBr(_final); m_ir->CreateCondBr(success, _final, _fail);
m_ir->SetInsertPoint(_fail); m_ir->SetInsertPoint(_fail);
call("PUTLLC16_fail", +on_fail, m_thread, _eal); call("PUTLLC16_fail", +on_fail, m_thread, _eal);