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;
}
if (true)
if (g_cfg.core.spu_accurate_reservations)
{
// Because enabling it is a hack, as it turns out
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)
{
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;
@ -1207,71 +1207,53 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
const auto _dest = vm::get_super_ptr<atomic_t<nse_t<v128>>>(dest);
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)))
{
vm::reservation_update(raddr);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS);
_spu->raddr = 0;
return;
return true;
}
const u64 rtime = _spu->rtime;
auto& res = vm::reservation_acquire(eal);
if (res != rtime)
if (res % 128)
{
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
return false;
}
rsx::reservation_lock rsx_lock(raddr, 128);
// Touch memory
utils::trigger_write_page_fault(vm::base(dest ^ (4096 / 2)));
auto [old_res, ok] = res.fetch_op([&](u64& rval)
{
if (rtime != rval)
rsx::reservation_lock rsx_lock(raddr, 128);
// Touch memory
utils::trigger_write_page_fault(vm::base(dest ^ (4096 / 2)));
auto [old_res, ok] = res.fetch_op([&](u64& rval)
{
if (rval % 128)
{
return false;
}
rval |= 127;
return true;
});
if (!ok)
{
return false;
}
rval |= 127;
return true;
});
if (!_dest->compare_and_swap_test(rdata, to_write))
{
res.release(old_res);
return false;
}
if (!ok)
{
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
// Success
res.release(old_res + 128);
}
if (!_dest->compare_and_swap_test(rdata, to_write))
{
res.release(old_res);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
}
// Success
res.release(old_res + 128);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS);
_spu->raddr = 0;
@ -1279,10 +1261,12 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
{
res.notify_all();
}
return true;
}, 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);
call("PUTLLC16_fail", +on_fail, m_thread, _eal);