Skip to content

Commit

Permalink
SPU LLVM: Implement PUTLLC16 for accurate RSX reservations
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed May 24, 2024
1 parent e8899bf commit 1fd8a5a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
2 changes: 1 addition & 1 deletion 3rdparty/curl/curl
Submodule curl updated 753 files
6 changes: 0 additions & 6 deletions rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6698,12 +6698,6 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
continue;
}

if (g_cfg.core.rsx_accurate_res_access)
{
// For now it is skipped completely in this case
continue;
}

union putllc16_info
{
u32 data;
Expand Down
83 changes: 83 additions & 0 deletions rpcs3/Emu/Cell/SPULLVMRecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "Emu/IdManager.h"
#include "Emu/Cell/timers.hpp"
#include "Emu/Memory/vm_reservation.h"
#include "Emu/RSX/Core/RSXReservationLock.hpp"
#include "Crypto/sha1.h"
#include "Utilities/JIT.h"

Expand Down Expand Up @@ -1189,6 +1190,87 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
dest = m_ir->CreateAnd(m_ir->CreateAdd(get_reg32(info.reg), get_reg32(info.reg2)), 0x3fff0);
}

if (g_cfg.core.rsx_accurate_res_access)
{
call("spu_putllc16_rsx_res", +[](spu_thread* _spu, u32 ls_dst, u32 lsa, u32 eal, bool notify)
{
const u32 raddr = _spu->raddr;

if (raddr != (eal & -128))
{
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->raddr = 0;
return;
}

const v128 rdata = v128::loadu(_spu->rdata, ls_dst % 0x80);
const v128 to_write = _spu->_ref<const v128>(ls_dst);

const auto dest = raddr | (ls_dst & 127);

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;
}

auto& res = vm::reservation_acquire(eal);

if (res & 127)
{
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->raddr = 0;
return;
}

rsx::reservation_lock rsx_lock(raddr, 128);

// Tocuh memory
vm::_ref<atomic_t<u8>>(dest).compare_and_swap_test(0, 0);

auto [old_res, ok] = res.fetch_op([](u64& rval)
{
if (rval & 127)
{
return false;
}

rval |= 127;
return true;
});

if (!ok)
{
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->raddr = 0;
return;
}

if (!vm::get_super_ptr<atomic_t<v128>>(dest)->compare_and_swap_test(rdata, to_write))
{
res.release(old_res - 127);
_spu->ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
_spu->raddr = 0;
return;
}

// Success
res.release(old_res + 1);

_spu->ch_atomic_stat.set_value(MFC_PUTLLC_SUCCESS);
_spu->raddr = 0;

if (notify)
{
res.notify_all();
}
}, m_thread, dest, _lsa, _eal, m_ir->getInt32(!info.no_notify));

return;
}

const auto diff = m_ir->CreateZExt(m_ir->CreateSub(dest, _lsa), get_type<u64>());

const auto _new = m_ir->CreateAlignedLoad(get_type<u128>(), _ptr<u128>(m_lsptr, dest), llvm::MaybeAlign{16});
Expand Down Expand Up @@ -1230,6 +1312,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator

const auto last_rval = m_ir->CreateExtractValue(cmp_res, 0);
rval->addIncoming(last_rval, _repeat_lock_fail);

m_ir->CreateCondBr(is_accurate_op ? m_ir->CreateICmpEQ(last_rval, rval) : m_ir->CreateIsNull(m_ir->CreateAnd(last_rval, 0x7f)), _repeat_lock, _fail);

m_ir->SetInsertPoint(_lock_success);
Expand Down

0 comments on commit 1fd8a5a

Please sign in to comment.