mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-20 15:40:23 +00:00
SPU LLVM: make savestates unsavable inside the code
This commit is contained in:
parent
8153e5338f
commit
39d17a94c6
@ -3982,9 +3982,6 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||
llvm::GlobalVariable* m_scale_float_to{};
|
||||
llvm::GlobalVariable* m_scale_to_float{};
|
||||
|
||||
// Helper for check_state
|
||||
llvm::GlobalVariable* m_fake_global1{};
|
||||
|
||||
// Function for check_state execution
|
||||
llvm::Function* m_test_state{};
|
||||
|
||||
@ -4880,7 +4877,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||
}
|
||||
|
||||
// Call cpu_thread::check_state if necessary and return or continue (full check)
|
||||
void check_state(u32 addr, bool may_be_unsafe_for_savestate = true)
|
||||
void check_state(u32 addr)
|
||||
{
|
||||
const auto pstate = spu_ptr<u32>(&spu_thread::state);
|
||||
const auto _body = llvm::BasicBlock::Create(m_context, "", m_function);
|
||||
@ -4888,19 +4885,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||
m_ir->CreateCondBr(m_ir->CreateICmpEQ(m_ir->CreateLoad(get_type<u32>(), pstate, true), m_ir->getInt32(0)), _body, check, m_md_likely);
|
||||
m_ir->SetInsertPoint(check);
|
||||
update_pc(addr);
|
||||
|
||||
if (may_be_unsafe_for_savestate && std::none_of(std::begin(m_block->phi), std::end(m_block->phi), FN(!!x)))
|
||||
{
|
||||
may_be_unsafe_for_savestate = false;
|
||||
}
|
||||
|
||||
m_ir->CreateStore(m_ir->getInt1(may_be_unsafe_for_savestate), m_fake_global1);
|
||||
|
||||
if (may_be_unsafe_for_savestate)
|
||||
{
|
||||
m_ir->CreateStore(m_ir->getInt8(0), spu_ptr<u8>(&spu_thread::unsavable));
|
||||
}
|
||||
|
||||
m_ir->CreateCall(m_test_state, {m_thread});
|
||||
m_ir->CreateBr(_body);
|
||||
m_ir->SetInsertPoint(_body);
|
||||
}
|
||||
@ -5013,9 +4998,6 @@ public:
|
||||
IRBuilder<> irb(m_context);
|
||||
m_ir = &irb;
|
||||
|
||||
// Helper for check_state. Used to not interfere with LICM pass.
|
||||
m_fake_global1 = new llvm::GlobalVariable(*m_module, get_type<bool>(), false, llvm::GlobalValue::InternalLinkage, m_ir->getFalse());
|
||||
|
||||
// Add entry function (contains only state/code check)
|
||||
const auto main_func = llvm::cast<llvm::Function>(m_module->getOrInsertFunction(m_hash, get_ftype<void, u8*, u8*, u64>()).getCallee());
|
||||
const auto main_arg2 = main_func->getArg(2);
|
||||
@ -5033,6 +5015,7 @@ public:
|
||||
|
||||
// Emit state check
|
||||
const auto pstate = spu_ptr<u32>(&spu_thread::state);
|
||||
m_ir->CreateStore(m_ir->getInt8(false), spu_ptr<u8>(&spu_thread::unsavable));
|
||||
m_ir->CreateCondBr(m_ir->CreateICmpNE(m_ir->CreateLoad(get_type<u32>(), pstate), m_ir->getInt32(0)), label_stop, label_test, m_md_unlikely);
|
||||
|
||||
// Emit code check
|
||||
@ -5200,6 +5183,7 @@ public:
|
||||
m_ir->SetInsertPoint(label_body);
|
||||
const auto pbcount = spu_ptr<u64>(&spu_thread::block_counter);
|
||||
m_ir->CreateStore(m_ir->CreateAdd(m_ir->CreateLoad(get_type<u64>(), pbcount), m_ir->getInt64(check_iterations)), pbcount);
|
||||
m_ir->CreateStore(m_ir->getInt8(true), spu_ptr<u8>(&spu_thread::unsavable));
|
||||
|
||||
// Call the entry function chunk
|
||||
const auto entry_chunk = add_function(m_pos);
|
||||
@ -5634,38 +5618,6 @@ public:
|
||||
{
|
||||
const auto f = func.second.fn ? func.second.fn : func.second.chunk;
|
||||
pm.run(*f);
|
||||
|
||||
for (auto& bb : *f)
|
||||
{
|
||||
for (auto& i : bb)
|
||||
{
|
||||
// Replace fake store with spu_test_state call
|
||||
if (auto si = dyn_cast<StoreInst>(&i); si && si->getOperand(1) == m_fake_global1)
|
||||
{
|
||||
m_ir->SetInsertPoint(si);
|
||||
|
||||
if (si->getOperand(0) == m_ir->getTrue())
|
||||
{
|
||||
m_ir->CreateStore(m_ir->getInt8(1), _ptr<u8>(f->getArg(0), ::offset32(&spu_thread::unsavable)));
|
||||
}
|
||||
|
||||
CallInst* ci{};
|
||||
if (si->getOperand(0) == m_ir->getTrue() || si->getOperand(0) == m_ir->getFalse())
|
||||
{
|
||||
ci = m_ir->CreateCall(m_test_state, {f->getArg(0)});
|
||||
ci->setCallingConv(m_test_state->getCallingConv());
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
si->replaceAllUsesWith(ci);
|
||||
si->eraseFromParent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear context (TODO)
|
||||
@ -6321,11 +6273,6 @@ public:
|
||||
return exec_rdch(_spu, SPU_RdEventStat);
|
||||
}
|
||||
|
||||
void ensure_gpr_stores()
|
||||
{
|
||||
m_block->store.fill(nullptr);
|
||||
}
|
||||
|
||||
llvm::Value* get_rdch(spu_opcode_t op, u32 off, bool atomic)
|
||||
{
|
||||
const auto ptr = _ptr<u64>(m_thread, off);
|
||||
@ -6382,7 +6329,6 @@ public:
|
||||
case SPU_RdInMbox:
|
||||
{
|
||||
update_pc();
|
||||
ensure_gpr_stores();
|
||||
res.value = call("spu_read_in_mbox", &exec_read_in_mbox, m_thread);
|
||||
break;
|
||||
}
|
||||
@ -6398,13 +6344,11 @@ public:
|
||||
}
|
||||
case SPU_RdSigNotify1:
|
||||
{
|
||||
ensure_gpr_stores();
|
||||
res.value = get_rdch(op, ::offset32(&spu_thread::ch_snr1), true);
|
||||
break;
|
||||
}
|
||||
case SPU_RdSigNotify2:
|
||||
{
|
||||
ensure_gpr_stores();
|
||||
res.value = get_rdch(op, ::offset32(&spu_thread::ch_snr2), true);
|
||||
break;
|
||||
}
|
||||
@ -6446,7 +6390,6 @@ public:
|
||||
default:
|
||||
{
|
||||
update_pc();
|
||||
ensure_gpr_stores();
|
||||
res.value = call("spu_read_channel", &exec_rdch, m_thread, m_ir->getInt32(op.ra));
|
||||
break;
|
||||
}
|
||||
@ -6792,7 +6735,6 @@ public:
|
||||
case MFC_GETLB_CMD:
|
||||
case MFC_GETLF_CMD:
|
||||
{
|
||||
ensure_gpr_stores();
|
||||
[[fallthrough]];
|
||||
}
|
||||
case MFC_SDCRZ_CMD:
|
||||
@ -7081,7 +7023,6 @@ public:
|
||||
m_ir->CreateCondBr(m_ir->CreateICmpNE(_old, _new), _mfc, next);
|
||||
m_ir->SetInsertPoint(_mfc);
|
||||
update_pc();
|
||||
ensure_gpr_stores();
|
||||
call("spu_list_unstall", &exec_list_unstall, m_thread, eval(val & 0x1f).value);
|
||||
m_ir->CreateBr(next);
|
||||
m_ir->SetInsertPoint(next);
|
||||
@ -7105,7 +7046,6 @@ public:
|
||||
}
|
||||
|
||||
update_pc();
|
||||
ensure_gpr_stores();
|
||||
call("spu_write_channel", &exec_wrch, m_thread, m_ir->getInt32(op.ra), val.value);
|
||||
}
|
||||
|
||||
@ -7126,7 +7066,6 @@ public:
|
||||
{
|
||||
m_block->block_end = m_ir->GetInsertBlock();
|
||||
update_pc(m_pos + 4);
|
||||
ensure_gpr_stores();
|
||||
tail_chunk(m_dispatch);
|
||||
}
|
||||
}
|
||||
@ -10444,7 +10383,7 @@ public:
|
||||
{
|
||||
// Can't afford external tail call in true functions
|
||||
m_ir->CreateStore(m_ir->getInt32("BIJT"_u32), _ptr<u32>(m_memptr, 0xffdead20));
|
||||
m_ir->CreateStore(m_ir->getFalse(), m_fake_global1);
|
||||
m_ir->CreateCall(m_test_state, {m_thread});
|
||||
m_ir->CreateBr(sw->getDefaultDest());
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user