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 b71eb50
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 8 deletions.
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

0 comments on commit b71eb50

Please sign in to comment.