mirror of https://github.com/RPCS3/rpcs3.git
PPU Analyser fix
This commit is contained in:
parent
94da0dbd4d
commit
0a5b518aea
|
@ -367,14 +367,15 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get next function address
|
// Get next reliable function address
|
||||||
auto get_limit = [&](u32 addr) -> u32
|
auto get_limit = [&](u32 addr) -> u32
|
||||||
{
|
{
|
||||||
const auto found = funcs.lower_bound(addr);
|
for (auto it = funcs.lower_bound(addr), end = funcs.end(); it != end; it++)
|
||||||
|
|
||||||
if (found != funcs.end())
|
|
||||||
{
|
{
|
||||||
return found->first;
|
if (it->second.attr & ppu_attr::known_addr)
|
||||||
|
{
|
||||||
|
return it->first;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
|
@ -396,6 +397,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
TOCs.emplace(toc);
|
TOCs.emplace(toc);
|
||||||
|
|
||||||
auto& func = add_func(addr, toc, ptr.addr());
|
auto& func = add_func(addr, toc, ptr.addr());
|
||||||
|
func.attr += ppu_attr::known_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -469,14 +471,15 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
u32 addr = 0;
|
u32 addr = 0;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
|
|
||||||
if ((ptr[2] == -1 || ptr[2] == 0) && ptr[4] == 0)
|
if (ptr[2] == 0 && ptr[3] == 0)
|
||||||
|
{
|
||||||
|
size = ptr[5];
|
||||||
|
}
|
||||||
|
else if ((ptr[2] == -1 || ptr[2] == 0) && ptr[4] == 0)
|
||||||
{
|
{
|
||||||
addr = ptr[3] + ptr.addr() + 8;
|
addr = ptr[3] + ptr.addr() + 8;
|
||||||
size = ptr[5];
|
size = ptr[5];
|
||||||
}
|
}
|
||||||
else if (ptr[2] == 0 && ptr[3] == 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (ptr[2] != -1 && ptr[4])
|
else if (ptr[2] != -1 && ptr[4])
|
||||||
{
|
{
|
||||||
addr = ptr[2];
|
addr = ptr[2];
|
||||||
|
@ -499,6 +502,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& func = add_func(addr, 0, ptr.addr());
|
auto& func = add_func(addr, 0, ptr.addr());
|
||||||
|
func.attr += ppu_attr::known_addr;
|
||||||
func.attr += ppu_attr::known_size;
|
func.attr += ppu_attr::known_size;
|
||||||
func.size = size;
|
func.size = size;
|
||||||
}
|
}
|
||||||
|
@ -565,6 +569,8 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
// The most used simple import stub
|
// The most used simple import stub
|
||||||
func.size = 0x20;
|
func.size = 0x20;
|
||||||
func.blocks.emplace(func.addr, func.size);
|
func.blocks.emplace(func.addr, func.size);
|
||||||
|
func.attr += ppu_attr::known_addr;
|
||||||
|
func.attr += ppu_attr::known_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,12 +598,20 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
func.blocks.emplace(vm::cast(func.addr), 0);
|
func.blocks.emplace(vm::cast(func.addr), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get function limit
|
||||||
|
const u32 func_end = get_limit(func.addr + 1);
|
||||||
|
|
||||||
// Block analysis workload
|
// Block analysis workload
|
||||||
std::vector<std::reference_wrapper<std::pair<const u32, u32>>> block_queue;
|
std::vector<std::reference_wrapper<std::pair<const u32, u32>>> block_queue;
|
||||||
|
|
||||||
// Add new block for analysis
|
// Add new block for analysis
|
||||||
auto add_block = [&](u32 addr) -> bool
|
auto add_block = [&](u32 addr) -> bool
|
||||||
{
|
{
|
||||||
|
if (addr < func.addr || addr >= func_end)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto _pair = func.blocks.emplace(addr, 0);
|
const auto _pair = func.blocks.emplace(addr, 0);
|
||||||
|
|
||||||
if (_pair.second)
|
if (_pair.second)
|
||||||
|
@ -611,7 +625,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
|
|
||||||
for (auto& block : func.blocks)
|
for (auto& block : func.blocks)
|
||||||
{
|
{
|
||||||
if (!block.second)
|
if (!block.second && block.first < func_end)
|
||||||
{
|
{
|
||||||
block_queue.emplace_back(block);
|
block_queue.emplace_back(block);
|
||||||
}
|
}
|
||||||
|
@ -620,7 +634,11 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
// TODO: lower priority?
|
// TODO: lower priority?
|
||||||
if (func.attr & ppu_attr::no_size)
|
if (func.attr & ppu_attr::no_size)
|
||||||
{
|
{
|
||||||
const u32 next = get_limit(func.blocks.crbegin()->first + 1);
|
// Get next function
|
||||||
|
const auto _next = funcs.lower_bound(func.blocks.crbegin()->first + 1);
|
||||||
|
|
||||||
|
// Get limit
|
||||||
|
const u32 func_end2 = _next == funcs.end() ? func_end : std::min<u32>(_next->first, func_end);
|
||||||
|
|
||||||
// Find more block entries
|
// Find more block entries
|
||||||
for (const auto& seg : segs)
|
for (const auto& seg : segs)
|
||||||
|
@ -629,7 +647,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
{
|
{
|
||||||
const u32 value = *ptr;
|
const u32 value = *ptr;
|
||||||
|
|
||||||
if (value % 4 == 0 && value >= func.addr && value < next)
|
if (value % 4 == 0 && value >= func.addr && value < func_end2)
|
||||||
{
|
{
|
||||||
add_block(value);
|
add_block(value);
|
||||||
}
|
}
|
||||||
|
@ -644,7 +662,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
{
|
{
|
||||||
auto& block = block_queue[j].get();
|
auto& block = block_queue[j].get();
|
||||||
|
|
||||||
for (vm::cptr<u32> _ptr = vm::cast(block.first); _ptr.addr() < end;)
|
for (vm::cptr<u32> _ptr = vm::cast(block.first); _ptr.addr() < func_end;)
|
||||||
{
|
{
|
||||||
const u32 iaddr = _ptr.addr();
|
const u32 iaddr = _ptr.addr();
|
||||||
const ppu_opcode_t op{*_ptr++};
|
const ppu_opcode_t op{*_ptr++};
|
||||||
|
@ -685,7 +703,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
{
|
{
|
||||||
// Nothing
|
// Nothing
|
||||||
}
|
}
|
||||||
else if (is_call || target < func.addr/* || target >= get_limit(_ptr.addr())*/)
|
else if (is_call || target < func.addr || target >= func_end)
|
||||||
{
|
{
|
||||||
// Add function call (including obvious tail call)
|
// Add function call (including obvious tail call)
|
||||||
add_func(target, 0, func.addr);
|
add_func(target, 0, func.addr);
|
||||||
|
@ -719,7 +737,7 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
{
|
{
|
||||||
// Analyse jumptable (TODO)
|
// Analyse jumptable (TODO)
|
||||||
const u32 jt_addr = _ptr.addr();
|
const u32 jt_addr = _ptr.addr();
|
||||||
const u32 jt_end = end;
|
const u32 jt_end = func_end;
|
||||||
|
|
||||||
for (; _ptr.addr() < jt_end; _ptr++)
|
for (; _ptr.addr() < jt_end; _ptr++)
|
||||||
{
|
{
|
||||||
|
@ -771,6 +789,11 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Just set the max
|
||||||
|
func.size = std::max<u32>(func.size, block.first + block.second - func.addr);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Disabled (TODO)
|
||||||
if (expected == block.first)
|
if (expected == block.first)
|
||||||
{
|
{
|
||||||
func.size += block.second;
|
func.size += block.second;
|
||||||
|
@ -869,13 +892,15 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function shrinkage (TODO: it's potentially dangerous but improvable)
|
// Function shrinkage, disabled (TODO: it's potentially dangerous but improvable)
|
||||||
for (auto& _pair : funcs)
|
for (auto& _pair : funcs)
|
||||||
{
|
{
|
||||||
auto& func = _pair.second;
|
auto& func = _pair.second;
|
||||||
|
|
||||||
// Next function start
|
// Get next function addr
|
||||||
const u32 next = get_limit(_pair.first + 1);
|
const auto _next = funcs.lower_bound(_pair.first + 1);
|
||||||
|
|
||||||
|
const u32 next = _next == funcs.end() ? end : _next->first;
|
||||||
|
|
||||||
// Just ensure that functions don't overlap
|
// Just ensure that functions don't overlap
|
||||||
if (func.addr + func.size > next)
|
if (func.addr + func.size > next)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
// PPU Function Attributes
|
// PPU Function Attributes
|
||||||
enum class ppu_attr : u32
|
enum class ppu_attr : u32
|
||||||
{
|
{
|
||||||
|
known_addr,
|
||||||
known_size,
|
known_size,
|
||||||
no_return,
|
no_return,
|
||||||
no_size,
|
no_size,
|
||||||
|
|
Loading…
Reference in New Issue