Skip to content

Commit

Permalink
PPU LLVM: Patch unregistered BLRs
Browse files Browse the repository at this point in the history
Fixes "Unregistered PPU Function" in "Jak and Daxter Collection"
  • Loading branch information
elad335 committed Sep 5, 2023
1 parent eacfa36 commit ff4485d
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions rpcs3/Emu/Cell/PPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4662,6 +4662,9 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
#ifdef __APPLE__
pthread_jit_write_protect_np(false);
#endif
// Try to patch all single and unregistered BLRs with the same function (TODO: Maybe generalize it into PIC code detection and patching)
ppu_intrp_func_t BLR_func = nullptr;

if (jit && !jit_mod.init)
{
jit->fin();
Expand All @@ -4675,6 +4678,11 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
const auto addr = ensure(reinterpret_cast<ppu_intrp_func_t>(jit->get(name)));
jit_mod.funcs.emplace_back(addr);

if (func.size == 4 & !BLR_func && *info.get_ptr<u32>(func.addr) == ppu_instructions::BLR())
{
BLR_func = addr;
}

ppu_register_function_at(func.addr, 4, addr);

if (g_cfg.core.ppu_debug)
Expand All @@ -4694,6 +4702,11 @@ bool ppu_initialize(const ppu_module& info, bool check_only)

const u64 addr = reinterpret_cast<uptr>(ensure(jit_mod.funcs[index++]));

if (func.size == 4 & !BLR_func && *info.get_ptr<u32>(func.addr) == ppu_instructions::BLR())
{
BLR_func = reinterpret_cast<ppu_intrp_func_t>(addr);
}

ppu_register_function_at(func.addr, 4, addr);

if (g_cfg.core.ppu_debug)
Expand All @@ -4703,6 +4716,19 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
index = 0;
}

if (BLR_func)
{
auto inst_ptr = info.get_ptr<u32>(info.segs[0].addr);

for (u32 addr = info.segs[0].addr; addr < info.segs[0].addr + info.segs[0].size; addr += 4, inst_ptr++)
{
if (*inst_ptr == ppu_instructions::BLR() && (reinterpret_cast<uptr>(ppu_ref(addr)) << 16 >> 16) == reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
{
ppu_register_function_at(addr, 4, BLR_func);
}
}
}

return compiled_new;
#else
fmt::throw_exception("LLVM is not available in this build.");
Expand Down

0 comments on commit ff4485d

Please sign in to comment.