mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Patches/PPU: Add jump_link patch type
This commit is contained in:
parent
fafefb2cf5
commit
f98595bee5
@ -40,6 +40,7 @@ void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
|
||||
case patch_type::alloc: return "alloc";
|
||||
case patch_type::code_alloc: return "calloc";
|
||||
case patch_type::jump: return "jump";
|
||||
case patch_type::jump_link: return "jumpl";
|
||||
case patch_type::load: return "load";
|
||||
case patch_type::byte: return "byte";
|
||||
case patch_type::le16: return "le16";
|
||||
@ -551,7 +552,7 @@ void patch_engine::append_title_patches(const std::string& title_id)
|
||||
}
|
||||
|
||||
void ppu_register_range(u32 addr, u32 size);
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target);
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target, bool link = false);
|
||||
|
||||
void unmap_vm_area(std::shared_ptr<vm::block_t>& ptr)
|
||||
{
|
||||
@ -737,12 +738,13 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
break;
|
||||
}
|
||||
case patch_type::jump:
|
||||
case patch_type::jump_link:
|
||||
{
|
||||
const u32 out_branch = vm::try_get_addr(dst + (offset & -4)).first;
|
||||
const u32 dest = static_cast<u32>(p.value.long_value);
|
||||
|
||||
// Allow only if points to a PPU executable instruction
|
||||
if (!ppu_form_branch_to_code(out_branch, dest))
|
||||
if (!ppu_form_branch_to_code(out_branch, dest, p.type == patch_type::jump_link))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ enum class patch_type
|
||||
alloc, // Allocate memory at address (zeroized executable memory)
|
||||
code_alloc,// Allocate memory somewhere, saves branch to memory at specfied address (filled with PPU NOP and branch for returning)
|
||||
jump, // Install special 32-bit jump instruction (PPU only atm)
|
||||
jump_link, // jump + set link (PPU only atm)
|
||||
byte,
|
||||
le16,
|
||||
le32,
|
||||
|
@ -528,7 +528,7 @@ struct ppu_prx_module_info
|
||||
be_t<u32> unk5;
|
||||
};
|
||||
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target);
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target, bool link = false);
|
||||
|
||||
// Load and register exports; return special exports found (nameless module)
|
||||
static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 exports_end)
|
||||
|
@ -487,11 +487,11 @@ extern void ppu_register_function_at(u32 addr, u32 size, u64 ptr)
|
||||
|
||||
struct ppu_far_jumps_t
|
||||
{
|
||||
std::unordered_map<u32, u32> vals;
|
||||
std::unordered_map<u32, std::pair<u32, bool>> vals;
|
||||
|
||||
mutable shared_mutex mutex;
|
||||
|
||||
u32 get_target(u32 pc) const
|
||||
std::pair<u32, bool> get_target(u32 pc) const
|
||||
{
|
||||
reader_lock lock(mutex);
|
||||
|
||||
@ -500,23 +500,25 @@ struct ppu_far_jumps_t
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
u32 ppu_get_far_jump(u32 pc)
|
||||
{
|
||||
g_fxo->init<ppu_far_jumps_t>();
|
||||
return g_fxo->get<const ppu_far_jumps_t>().get_target(pc);
|
||||
return g_fxo->get<const ppu_far_jumps_t>().get_target(pc).first;
|
||||
}
|
||||
|
||||
static bool ppu_far_jump(ppu_thread& ppu)
|
||||
{
|
||||
ppu.cia = g_fxo->get<const ppu_far_jumps_t>().get_target(ppu.cia);
|
||||
auto [cia, link] = g_fxo->get<const ppu_far_jumps_t>().get_target(ppu.cia);
|
||||
if (link) ppu.lr = ppu.cia + 4;
|
||||
ppu.cia = cia;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target)
|
||||
bool ppu_form_branch_to_code(u32 entry, u32 target, bool link)
|
||||
{
|
||||
entry &= -4;
|
||||
target &= -4;
|
||||
@ -532,7 +534,7 @@ bool ppu_form_branch_to_code(u32 entry, u32 target)
|
||||
auto& jumps = g_fxo->get<ppu_far_jumps_t>();
|
||||
|
||||
std::lock_guard lock(jumps.mutex);
|
||||
jumps.vals.insert_or_assign(entry, target);
|
||||
jumps.vals.insert_or_assign(entry, std::make_pair(target, link));
|
||||
ppu_register_function_at(entry, 4, &ppu_far_jump);
|
||||
|
||||
return true;
|
||||
@ -691,7 +693,7 @@ std::array<u32, 2> op_branch_targets(u32 pc, ppu_opcode_t op)
|
||||
|
||||
g_fxo->need<ppu_far_jumps_t>();
|
||||
|
||||
if (u32 target = g_fxo->get<const ppu_far_jumps_t>().get_target(pc))
|
||||
if (u32 target = g_fxo->get<const ppu_far_jumps_t>().get_target(pc).first)
|
||||
{
|
||||
res[0] = target;
|
||||
return res;
|
||||
@ -3253,9 +3255,11 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
|
||||
if (!func.size) continue;
|
||||
|
||||
const auto name = fmt::format("__0x%x", func.addr - reloc);
|
||||
const u64 addr = ensure(jit->get(name));
|
||||
jit_mod.funcs.emplace_back(reinterpret_cast<ppu_function_t>(addr));
|
||||
ppu_register_function_at(func.addr, 4, jit_mod.funcs.back());
|
||||
const auto addr = ensure(reinterpret_cast<ppu_function_t>(jit->get(name)));
|
||||
jit_mod.funcs.emplace_back(addr);
|
||||
|
||||
if (ppu_ref(func.addr) != reinterpret_cast<u64>(ppu_far_jump))
|
||||
ppu_register_function_at(func.addr, 4, addr);
|
||||
|
||||
if (g_cfg.core.ppu_debug)
|
||||
ppu_log.notice("Installing function %s at 0x%x: %p (reloc = 0x%x)", name, func.addr, ppu_ref(func.addr), reloc);
|
||||
@ -3272,8 +3276,10 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
|
||||
{
|
||||
if (!func.size) continue;
|
||||
|
||||
const u64 addr = ensure(reinterpret_cast<uptr>(jit_mod.funcs[index++]));
|
||||
ppu_ref(func.addr) = (addr & 0x7fff'ffff'ffffu) | (ppu_ref(func.addr) & ~0x7fff'ffff'ffffu);
|
||||
const u64 addr = reinterpret_cast<uptr>(ensure(jit_mod.funcs[index++]));
|
||||
|
||||
if (ppu_ref(func.addr) != reinterpret_cast<u64>(ppu_far_jump))
|
||||
ppu_register_function_at(func.addr, 4, addr);
|
||||
|
||||
if (g_cfg.core.ppu_debug)
|
||||
ppu_log.notice("Reinstalling function at 0x%x: %p (reloc=0x%x)", func.addr, ppu_ref(func.addr), reloc);
|
||||
|
@ -234,10 +234,11 @@ Function* PPUTranslator::Translate(const ppu_function& info)
|
||||
m_rel = nullptr;
|
||||
}
|
||||
|
||||
if (u32 target = ppu_get_far_jump(m_addr + base))
|
||||
if (ppu_get_far_jump(m_addr + base))
|
||||
{
|
||||
// Branch into an HLEd instruction using the jump table
|
||||
FlushRegisters();
|
||||
CallFunction(0, m_ir->getInt64(target));
|
||||
CallFunction(0, m_reloc ? m_ir->CreateAdd(m_ir->getInt64(m_addr), m_seg0) : m_ir->getInt64(m_addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user