PPU Analyser fix

This commit is contained in:
Nekotekina 2017-04-06 16:57:32 +03:00
parent 7a1fd27ecc
commit ed7883ba07
4 changed files with 23 additions and 22 deletions

View File

@ -467,8 +467,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
}
}
// Secondary attempt (TODO, needs better strategy)
if (/*secs.empty() &&*/ lib_toc)
// Secondary attempt
if (TOCs.empty() && lib_toc)
{
add_toc(lib_toc);
}
@ -598,7 +598,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
if (ptr + 1 <= fend && (ptr[0] & 0xfc000001) == B({}, {}))
{
// Simple gate
// Simple trampoline
const u32 target = (ptr[0] & 0x2 ? 0 : ptr.addr()) + ppu_opcode_t{ptr[0]}.bt24;
if (target == func.addr)
@ -612,7 +612,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
if (target >= start && target < end)
{
auto& new_func = add_func(target, func.toc, func.addr);
auto& new_func = add_func(target, 0, func.addr);
if (new_func.blocks.empty())
{
@ -623,8 +623,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
func.size = 0x4;
func.blocks.emplace(func.addr, func.size);
func.attr += new_func.attr & ppu_attr::no_return;
func.called_from.emplace(target);
func.gate_target = target;
func.calls.emplace(target);
func.trampoline = target;
continue;
}
}
@ -635,12 +635,12 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
ptr[2] == MTCTR(r11) &&
ptr[3] == BCTR())
{
// Simple gate
// Simple trampoline
const u32 target = (ptr[0] << 16) + ppu_opcode_t{ptr[1]}.simm16;
if (target >= start && target < end)
{
auto& new_func = add_func(target, func.toc, func.addr);
auto& new_func = add_func(target, 0, func.addr);
if (new_func.blocks.empty())
{
@ -651,8 +651,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
func.size = 0x10;
func.blocks.emplace(func.addr, func.size);
func.attr += new_func.attr & ppu_attr::no_return;
func.called_from.emplace(target);
func.gate_target = target;
func.calls.emplace(target);
func.trampoline = target;
continue;
}
}
@ -663,7 +663,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
(ptr[2] & 0xffff0000) == ADDI(r2, r2, {}) &&
(ptr[3] & 0xfc000001) == B({}, {}))
{
// TOC change gate
// Trampoline with TOC
const u32 new_toc = func.toc && func.toc != -1 ? func.toc + (ptr[1] << 16) + s16(ptr[2]) : 0;
const u32 target = (ptr[3] & 0x2 ? 0 : (ptr + 3).addr()) + ppu_opcode_t{ptr[3]}.bt24;
@ -671,7 +671,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
{
add_toc(new_toc);
auto& new_func = add_func(target, new_toc, func.addr);
auto& new_func = add_func(target, 0, func.addr);
if (new_func.blocks.empty())
{
@ -682,8 +682,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
func.size = 0x10;
func.blocks.emplace(func.addr, func.size);
func.attr += new_func.attr & ppu_attr::no_return;
func.called_from.emplace(target);
func.gate_target = target;
func.calls.emplace(target);
func.trampoline = target;
continue;
}
}
@ -699,6 +699,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
ptr[7] == BCTR())
{
// The most used simple import stub
func.toc = -1;
func.size = 0x20;
func.blocks.emplace(func.addr, func.size);
func.attr += ppu_attr::known_addr;
@ -717,7 +718,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
p2[6] == MTCTR(r0) &&
p2[7] == BCTR())
{
auto& next = add_func(p2.addr(), 0, func.addr);
auto& next = add_func(p2.addr(), -1, func.addr);
next.size = 0x20;
next.blocks.emplace(next.addr, next.size);
next.attr += ppu_attr::known_addr;
@ -1017,8 +1018,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
{
if (target < func.addr || target >= func.addr + func.size)
{
func.called_from.emplace(target);
add_func(target, func.toc, func.addr);
func.calls.emplace(target);
add_func(target, 0, func.addr);
}
}
}

View File

@ -29,10 +29,10 @@ struct ppu_function
bs_t<ppu_attr> attr{};
u32 stack_frame = 0;
u32 gate_target = 0;
u32 trampoline = 0;
std::map<u32, u32> blocks; // Basic blocks: addr -> size
std::set<u32> called_from; // Set of called functions
std::set<u32> calls; // Set of called functions
};
// PPU Module Information

View File

@ -1252,7 +1252,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
{
// Analyse executable
std::vector<ppu_function> main_funcs = ppu_analyse(segments, sections, 0);
std::vector<ppu_function> main_funcs = ppu_analyse(segments, sections, vm::read32(elf.header.e_entry + 4));
ppu_validate(vfs::get(Emu.GetPath()), main_funcs, 0);

View File

@ -129,7 +129,7 @@ static bool ppu_fallback(ppu_thread& ppu, ppu_opcode_t op)
{
if (g_cfg_ppu_decoder.get() == ppu_decoder_type::llvm)
{
fmt::throw_exception("Unregistered PPU function [0x%08x]", ppu.cia);
fmt::throw_exception("Unregistered PPU function");
}
ppu_ref(ppu.cia) = ppu_cache(ppu.cia);
@ -141,7 +141,7 @@ extern void ppu_register_range(u32 addr, u32 size)
if (!size)
{
LOG_ERROR(PPU, "ppu_register_range(0x%x): empty range", addr);
return;
return;
}
// Register executable range at