Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPU LLVM: Implement PUTLLC16 for accurate RSX reservations #15621

Merged
merged 1 commit into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions rpcs3/Emu/Cell/SPUCommonRecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5305,7 +5305,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s

if (insert_entry)
{
const u32 target_size = get_block_targets(stackframe_pc).size();
const usz target_size = get_block_targets(stackframe_pc).size();

spu_log.trace("Emplacing: block_id=%d, pc=0x%x, target_it=%d/%d, new_pc=0x%x (has_it=%d)", reg_state_it[stackframe_it].iterator_id, stackframe_pc, entry_index + 1, target_size, target_pc, atomic16_info.active);
auto& next = reg_state_it.emplace_back(target_pc, stackframe_it, 0);
Expand All @@ -5321,7 +5321,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
}

next.iterator_id = iterator_id_alloc++;
wi = stackframe_it + 1;
wi = static_cast<u32>(stackframe_it + 1);
ensure(stackframe_it + 1 == reg_state_it.size() - 1);
}
}
Expand Down 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
88 changes: 88 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,92 @@ 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, u32 notify)
{
const u32 raddr = eal;

const v128 rdata = read_from_ptr<v128>(_spu->rdata, ls_dst % 0x80);
const v128 to_write = _spu->_ref<const nse_t<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->set_events(SPU_EVENT_LR);
_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->set_events(SPU_EVENT_LR);
_spu->raddr = 0;
return;
}

if (!vm::get_super_ptr<atomic_t<nse_t<v128>>>(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;

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


m_ir->CreateBr(_final);

m_ir->SetInsertPoint(_fail);
call("PUTLLC16_fail", +on_fail, m_thread, _eal);
m_ir->CreateStore(m_ir->getInt64(spu_channel::bit_count | MFC_PUTLLC_FAILURE), spu_ptr<u64>(&spu_thread::ch_atomic_stat));
m_ir->CreateBr(_final);

m_ir->SetInsertPoint(_final);
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 +1317,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