diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp index 813657778583..b16772df40a6 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.cpp +++ b/rpcs3/Emu/Cell/PPUTranslator.cpp @@ -765,6 +765,25 @@ llvm::Value* PPUTranslator::GetMemory(llvm::Value* addr) return m_ir->CreateGEP(get_type(), m_base, addr); } +void PPUTranslator::TestAborted() +{ + const auto body = BasicBlock::Create(m_context, fmt::format("__body_0x%x_%s", m_cia, m_ir->GetInsertBlock()->getName().str()), m_function); + + // Check status register in the entry block + auto ptr = llvm::dyn_cast(m_ir->CreateStructGEP(m_thread_type, m_thread, 1)); + assert(ptr->getResultElementType() == GetType()); + const auto vstate = m_ir->CreateLoad(ptr->getResultElementType(), ptr, true); + const auto vcheck = BasicBlock::Create(m_context, fmt::format("__test_0x%x_%s", m_cia, m_ir->GetInsertBlock()->getName().str()), m_function); + m_ir->CreateCondBr(m_ir->CreateIsNull(m_ir->CreateAnd(vstate, static_cast(cpu_flag::again + cpu_flag::exit))), body, vcheck, m_md_likely); + + m_ir->SetInsertPoint(vcheck); + + // Create tail call to the check function + Call(GetType(), "__check", m_thread, GetAddr())->setTailCall(); + m_ir->CreateRetVoid(); + m_ir->SetInsertPoint(body); +} + Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align) { const u32 size = ::narrow(+type->getPrimitiveSizeInBits()); @@ -797,8 +816,13 @@ Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align) if (m_may_be_mmio && size == 32) { + FlushRegisters(); + RegStore(Trunc(GetAddr()), m_cia); + ppu_log.notice("LLVM: Detected potential MMIO32 read at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0)); value = Call(GetType(), "__read_maybe_mmio32", m_base, addr); + + TestAborted(); } else { @@ -812,8 +836,13 @@ Value* PPUTranslator::ReadMemory(Value* addr, Type* type, bool is_be, u32 align) if (m_may_be_mmio && size == 32) { + FlushRegisters(); + RegStore(Trunc(GetAddr()), m_cia); + ppu_log.notice("LLVM: Detected potential MMIO32 read at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0)); - return Call(GetType(), "__read_maybe_mmio32", m_base, addr); + Value* r = Call(GetType(), "__read_maybe_mmio32", m_base, addr); + TestAborted(); + return r; } // Read normally @@ -846,8 +875,12 @@ void PPUTranslator::WriteMemory(Value* addr, Value* value, bool is_be, u32 align { if (ppu_test_address_may_be_mmio(std::span(ptr->insts))) { + FlushRegisters(); + RegStore(Trunc(GetAddr()), m_cia); + ppu_log.notice("LLVM: Detected potential MMIO32 write at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0)); Call(GetType(), "__write_maybe_mmio32", m_base, addr, value); + TestAborted(); return; } } diff --git a/rpcs3/Emu/Cell/PPUTranslator.h b/rpcs3/Emu/Cell/PPUTranslator.h index d3c8d877a6d1..a71e42a033da 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.h +++ b/rpcs3/Emu/Cell/PPUTranslator.h @@ -150,6 +150,9 @@ class PPUTranslator final : public cpu_translator // Emit function call void CallFunction(u64 target, llvm::Value* indirect = nullptr); + // Emit state check mid-block + void TestAborted(); + // Initialize global for writing llvm::Value* RegInit(llvm::Value*& local);