PPU Analyzer: Minor Fixup

This commit is contained in:
Elad 2025-02-08 17:00:07 +02:00
parent c7e853bf99
commit 9a7b8e41eb

View file

@ -566,7 +566,7 @@ struct reg_state_t
// Get maximum bound // Get maximum bound
u64 operator()(max_value_tag) const u64 operator()(max_value_tag) const
{ {
return value_range ? (ge_than | bit_range) + value_range : u64{umax}; return value_range ? (ge_than | bit_range) + value_range : 0;
} }
u64 operator()(load_addr_tag) const u64 operator()(load_addr_tag) const
@ -703,7 +703,7 @@ struct reg_state_t
// Bitwise shift left // Bitwise shift left
bool shift_left(u64 value, u32& reg_tag_allocator) bool shift_left(u64 value, u32& reg_tag_allocator)
{ {
if (!value) if (!value || !value_range)
{ {
return true; return true;
} }
@ -727,8 +727,8 @@ struct reg_state_t
} }
ge_than <<= value; ge_than <<= value;
value_range <<= value;
bit_range <<= value; bit_range <<= value;
value_range = ((value_range - 1) << value) + 1;
return true; return true;
} }
@ -1360,6 +1360,18 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
// Make sure to re-initialize this for every function! // Make sure to re-initialize this for every function!
std::vector<reg_state_t> reg_state_storage(64 * (is_relocatable ? 256 : 1024)); std::vector<reg_state_t> reg_state_storage(64 * (is_relocatable ? 256 : 1024));
struct block_local_info_t
{
u32 addr = 0;
u32 size = 0;
u32 parent_block_idx = umax;
u64 mapped_registers_mask = 0;
u64 moved_registers_mask = 0;
};
// Block analysis workload
std::vector<block_local_info_t> block_queue_storage;
// Main loop (func_queue may grow) // Main loop (func_queue may grow)
for (usz i = 0; i < func_queue.size(); i++) for (usz i = 0; i < func_queue.size(); i++)
{ {
@ -1719,17 +1731,8 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
// Get function limit // Get function limit
const u32 func_end = std::min<u32>(get_limit(func.addr + 1), func.attr & ppu_attr::known_size ? func.addr + func.size : end); const u32 func_end = std::min<u32>(get_limit(func.addr + 1), func.attr & ppu_attr::known_size ? func.addr + func.size : end);
struct block_local_info_t auto& block_queue = block_queue_storage;
{ block_queue.clear();
u32 addr = 0;
u32 size = 0;
u32 parent_block_idx = umax;
u64 mapped_registers_mask = 0;
u64 moved_registers_mask = 0;
};
// Block analysis workload
std::vector<block_local_info_t> block_queue;
u32 reg_tag_allocator = 1; u32 reg_tag_allocator = 1;
auto make_unknown_reg_state = [&]() auto make_unknown_reg_state = [&]()
@ -1751,12 +1754,13 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
if (_pair.second) if (_pair.second)
{ {
block_queue.emplace_back(block_local_info_t{addr}); auto& block = block_queue.emplace_back(block_local_info_t{addr});
block_queue.back().parent_block_idx = parent_block; block.parent_block_idx = parent_block;
if (parent_block != umax) if (parent_block != umax)
{ {
block_queue.back().mapped_registers_mask = ::at32(block_queue, parent_block).mapped_registers_mask; // Inherit loaded registers mask (lazily)
block.mapped_registers_mask = ::at32(block_queue, parent_block).mapped_registers_mask;
} }
return static_cast<u32>(block_queue.size() - 1); return static_cast<u32>(block_queue.size() - 1);
@ -1786,10 +1790,10 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
std::for_each(addr_heap.lower_bound(func.addr), addr_heap.lower_bound(func_end2), [&](auto a) { add_block(a.first, umax); }); std::for_each(addr_heap.lower_bound(func.addr), addr_heap.lower_bound(func_end2), [&](auto a) { add_block(a.first, umax); });
} }
const bool was_empty = block_queue.empty(); bool postpone_analysis = false;
// Block loop (block_queue may grow, may be aborted via clearing) // Block loop (block_queue may grow, may be aborted via clearing)
for (u32 j = 0; j < block_queue.size(); [&]() for (u32 j = 0; !postpone_analysis && j < block_queue.size(); [&]()
{ {
if (u32 size = block_queue[j].size) if (u32 size = block_queue[j].size)
{ {
@ -1934,7 +1938,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
if (pfunc && pfunc->blocks.empty()) if (pfunc && pfunc->blocks.empty())
{ {
// Postpone analysis (no info) // Postpone analysis (no info)
block_queue.clear(); postpone_analysis = true;
break; break;
} }
@ -2098,6 +2102,8 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
jt_addr = jumpatble_off.addr(); jt_addr = jumpatble_off.addr();
jt_end = segs_end;
for (const auto& seg : segs) for (const auto& seg : segs)
{ {
if (seg.size) if (seg.size)
@ -2110,7 +2116,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
} }
} }
jt_end = static_cast<u32>(std::min<u64>(jt_end, ctr(maxv))); jt_end = utils::align<u32>(static_cast<u32>(std::min<u64>(jt_end - 1, ctr(maxv) - 1) + 1), 4);
get_jumptable_end(jumpatble_off, jumpatble_ptr, false); get_jumptable_end(jumpatble_off, jumpatble_ptr, false);
@ -2160,7 +2166,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
func.attr += ppu_attr::no_size; func.attr += ppu_attr::no_size;
add_block(jt_addr, j); add_block(jt_addr, j);
block_queue.clear(); postpone_analysis = true;
} }
else else
{ {
@ -2312,9 +2318,14 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
rd.ge_than = const_reg(minv); rd.ge_than = const_reg(minv);
if (off_reg.value_range != 0 && off_reg(minv) < segs_end && rd(minv) < segs_end - off_reg(minv)) if (off_reg.value_range != 0 && off_reg(minv) < segs_end && const_reg(minv) < segs_end - off_reg(minv))
{ {
rd.ge_than += off_reg(minv); rd.ge_than += off_reg(minv);
if (off_reg(maxv) - 1 < segs_end - 1 && const_reg(minv) <= segs_end - off_reg(maxv))
{
rd.value_range = off_reg.value_range;
}
} }
} }
} }
@ -2440,7 +2451,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
} }
} }
if (block_queue.empty() && !was_empty) if (postpone_analysis)
{ {
// Block aborted: abort function, postpone // Block aborted: abort function, postpone
func_queue.emplace_back(func); func_queue.emplace_back(func);