PPU LLVM: Filter out functions with patches
This commit is contained in:
@@ -145,6 +145,7 @@ struct ppu_module : public Type
|
|||||||
std::shared_ptr<std::pair<u32, u32>> jit_bounds; // JIT instance modules addresses range
|
std::shared_ptr<std::pair<u32, u32>> jit_bounds; // JIT instance modules addresses range
|
||||||
std::unordered_map<u32, void*> imports; // Imports information for release upon unload (TODO: OVL implementation!)
|
std::unordered_map<u32, void*> imports; // Imports information for release upon unload (TODO: OVL implementation!)
|
||||||
std::map<u32, std::vector<std::pair<ppua_reg_mask_t, u64>>> stub_addr_to_constant_state_of_registers; // Tells possible constant states of registers of functions
|
std::map<u32, std::vector<std::pair<ppua_reg_mask_t, u64>>> stub_addr_to_constant_state_of_registers; // Tells possible constant states of registers of functions
|
||||||
|
std::vector<u32> excluded_funcs; // Function code not be overwritten
|
||||||
bool is_relocatable = false; // Is code relocatable(?)
|
bool is_relocatable = false; // Is code relocatable(?)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -934,13 +934,40 @@ struct ppu_far_jumps_t
|
|||||||
ppu_far_jumps_t(int) noexcept {}
|
ppu_far_jumps_t(int) noexcept {}
|
||||||
|
|
||||||
std::map<u32, all_info_t> vals;
|
std::map<u32, all_info_t> vals;
|
||||||
|
std::pair<u32, u32> vals_range{0, 0};
|
||||||
::jit_runtime rt;
|
::jit_runtime rt;
|
||||||
|
|
||||||
mutable shared_mutex mutex;
|
mutable shared_mutex mutex;
|
||||||
|
|
||||||
|
void add_value(u32 addr, all_info_t info)
|
||||||
|
{
|
||||||
|
vals.insert_or_assign(addr, std::move(info));
|
||||||
|
|
||||||
|
if (vals.size() == 1)
|
||||||
|
{
|
||||||
|
vals_range.first = addr;
|
||||||
|
vals_range.second = addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vals_range.first = std::min<u32>(vals_range.first, addr);
|
||||||
|
vals_range.second = std::max<u32>(vals_range.second, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get target address, 'ppu' is used in ppu_far_jump in order to modify registers
|
// Get target address, 'ppu' is used in ppu_far_jump in order to modify registers
|
||||||
u32 get_target(u32 pc, ppu_thread* ppu = nullptr)
|
u32 get_target(u32 pc, ppu_thread* ppu = nullptr)
|
||||||
{
|
{
|
||||||
|
if (vals_range.first > pc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vals_range.second < pc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
reader_lock lock(mutex);
|
reader_lock lock(mutex);
|
||||||
|
|
||||||
if (auto it = vals.find(pc); it != vals.end())
|
if (auto it = vals.find(pc); it != vals.end())
|
||||||
@@ -949,7 +976,7 @@ struct ppu_far_jumps_t
|
|||||||
return all_info.get_target(pc, ppu);
|
return all_info.get_target(pc, ppu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get function patches in range (entry -> target)
|
// Get function patches in range (entry -> target)
|
||||||
@@ -957,6 +984,16 @@ struct ppu_far_jumps_t
|
|||||||
{
|
{
|
||||||
std::vector<std::pair<u32, u32>> targets;
|
std::vector<std::pair<u32, u32>> targets;
|
||||||
|
|
||||||
|
if (vals_range.first >= pc + size)
|
||||||
|
{
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vals_range.second < pc)
|
||||||
|
{
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
reader_lock lock(mutex);
|
reader_lock lock(mutex);
|
||||||
|
|
||||||
auto it = vals.lower_bound(pc);
|
auto it = vals.lower_bound(pc);
|
||||||
@@ -1110,7 +1147,7 @@ bool ppu_form_branch_to_code(u32 entry, u32 target, bool link, bool with_toc, st
|
|||||||
auto& jumps = g_fxo->get<ppu_far_jumps_t>();
|
auto& jumps = g_fxo->get<ppu_far_jumps_t>();
|
||||||
|
|
||||||
std::lock_guard lock(jumps.mutex);
|
std::lock_guard lock(jumps.mutex);
|
||||||
jumps.vals.insert_or_assign(entry, ppu_far_jumps_t::all_info_t{target, link, with_toc, std::move(module_name)});
|
jumps.add_value(entry, ppu_far_jumps_t::all_info_t{target, link, with_toc, std::move(module_name)});
|
||||||
ppu_register_function_at(entry, 4, g_cfg.core.ppu_decoder == ppu_decoder_type::_static ? &ppu_far_jump : ensure(g_fxo->get<ppu_far_jumps_t>().gen_jump<false>(entry)));
|
ppu_register_function_at(entry, 4, g_cfg.core.ppu_decoder == ppu_decoder_type::_static ? &ppu_far_jump : ensure(g_fxo->get<ppu_far_jumps_t>().gen_jump<false>(entry)));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -5214,6 +5251,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
{
|
{
|
||||||
// Replace the function with ppu_far_jump
|
// Replace the function with ppu_far_jump
|
||||||
fpos++;
|
fpos++;
|
||||||
|
part.excluded_funcs.emplace_back(func.addr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5246,6 +5284,11 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::count(part.excluded_funcs.begin(), part.excluded_funcs.end(), func.addr))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const be_t<u32> addr = func.addr - reloc;
|
const be_t<u32> addr = func.addr - reloc;
|
||||||
const be_t<u32> size = func.size;
|
const be_t<u32> size = func.size;
|
||||||
sha1_update(&ctx, reinterpret_cast<const u8*>(&addr), sizeof(addr));
|
sha1_update(&ctx, reinterpret_cast<const u8*>(&addr), sizeof(addr));
|
||||||
@@ -5343,6 +5386,13 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_fxo->is_init<ppu_far_jumps_t>() && !g_fxo->get<ppu_far_jumps_t>().get_targets(func.addr, func.size).empty())
|
||||||
|
{
|
||||||
|
// Filter out functions with patches
|
||||||
|
part.excluded_funcs.emplace_back(func.addr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
addrs.emplace_back(func.addr - reloc);
|
addrs.emplace_back(func.addr - reloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5779,6 +5829,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
|
|||||||
{
|
{
|
||||||
if (func.size)
|
if (func.size)
|
||||||
{
|
{
|
||||||
|
if (std::count(module_part.excluded_funcs.begin(), module_part.excluded_funcs.end(), func.addr))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto f = cast<Function>(_module->getOrInsertFunction(fmt::format("__0x%x", func.addr - reloc), _func).getCallee());
|
const auto f = cast<Function>(_module->getOrInsertFunction(fmt::format("__0x%x", func.addr - reloc), _func).getCallee());
|
||||||
f->setCallingConv(CallingConv::GHC);
|
f->setCallingConv(CallingConv::GHC);
|
||||||
f->addParamAttr(1, llvm::Attribute::NoAlias);
|
f->addParamAttr(1, llvm::Attribute::NoAlias);
|
||||||
@@ -5834,6 +5889,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
|
|||||||
|
|
||||||
if (mod_func.size)
|
if (mod_func.size)
|
||||||
{
|
{
|
||||||
|
if (std::count(module_part.excluded_funcs.begin(), module_part.excluded_funcs.end(), mod_func.addr))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
num_func++;
|
num_func++;
|
||||||
guest_code_size += mod_func.size;
|
guest_code_size += mod_func.size;
|
||||||
max_addr = std::max<u32>(max_addr, mod_func.addr + mod_func.size);
|
max_addr = std::max<u32>(max_addr, mod_func.addr + mod_func.size);
|
||||||
|
|||||||
@@ -364,6 +364,12 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::count(info.excluded_funcs.begin(), info.excluded_funcs.end(), f.addr))
|
||||||
|
{
|
||||||
|
// Excluded function (possibly patched)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
vec_addrs.push_back(static_cast<u32>(f.addr - base));
|
vec_addrs.push_back(static_cast<u32>(f.addr - base));
|
||||||
functions.push_back(cast<Function>(m_module->getOrInsertFunction(fmt::format("__0x%x", f.addr - base), ftype).getCallee()));
|
functions.push_back(cast<Function>(m_module->getOrInsertFunction(fmt::format("__0x%x", f.addr - base), ftype).getCallee()));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user