diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index 04f5d5954e..5c0e10b9d5 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -529,15 +529,13 @@ namespace ppu_patterns }; } -void ppu_module::analyse(u32 lib_toc, u32 entry, u32 end) +void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end) { // Assume first segment is executable const u32 start = segs[0].addr; - if (!end) - { - end = segs[0].addr + segs[0].size; - } + // End of executable segment (may change) + u32 end = sec_end ? sec_end : segs[0].addr + segs[0].size; // Known TOCs (usually only 1) std::unordered_set TOCs; @@ -1529,6 +1527,12 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, u32 end) ppu_log.notice("Function analysis: %zu functions (%zu enqueued)", fmap.size(), func_queue.size()); // Decompose functions to basic blocks + if (!entry && !sec_end) + { + // Regenerate end from blocks + end = 0; + } + for (auto&& [_, func] : as_rvalue(std::move(fmap))) { if (func.attr & ppu_attr::no_size && entry) @@ -1570,10 +1574,10 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, u32 end) block.toc = func.toc; ppu_log.trace("Block __0x%x added (func=0x%x, size=0x%x, toc=0x%x)", block.addr, _, block.size, block.toc); - if (!entry) + if (!entry && !sec_end) { // Workaround for SPRX: update end to the last found function - end = block.addr + block.size; + end = std::max(end, block.addr + block.size); } } } diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 08aff7024c..ddcccf4ac0 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -868,7 +868,6 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri if (prog.p_flags & 0x1) { ppu_register_range(addr, mem_size); - end = std::max(end, addr + mem_size); } _seg.addr = addr; @@ -885,11 +884,6 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri } } - if (!elf.shdrs.empty()) - { - end = 0; - } - for (const auto& s : elf.shdrs) { ppu_loader.notice("** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", s.sh_type, s.sh_addr, s.sh_size, s.sh_flags); @@ -915,7 +909,7 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri _sec.filesz = 0; prx->secs.emplace_back(_sec); - if (_sec.flags & 0x4) + if (_sec.flags & 0x4 && i == 0) { end = std::max(end, _sec.addr + _sec.size); } @@ -1271,7 +1265,6 @@ bool ppu_load_exec(const ppu_exec_object& elf) if (prog.p_flags & 0x1) { ppu_register_range(addr, size); - end = std::max(end, addr + size); } // Store only LOAD segments (TODO) @@ -1279,11 +1272,6 @@ bool ppu_load_exec(const ppu_exec_object& elf) } } - if (!elf.shdrs.empty()) - { - end = 0; - } - // Load section list, used by the analyser for (const auto& s : elf.shdrs) { @@ -1303,7 +1291,7 @@ bool ppu_load_exec(const ppu_exec_object& elf) { _main->secs.emplace_back(_sec); - if (_sec.flags & 0x4) + if (_sec.flags & 0x4 && addr >= _main->segs[0].addr && addr + size <= _main->segs[0].addr + _main->segs[0].size) { end = std::max(end, addr + size); } @@ -1828,7 +1816,6 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex if (prog.p_flags & 0x1) { ppu_register_range(addr, size); - end = std::max(end, addr + size); } // Store only LOAD segments (TODO) @@ -1836,11 +1823,6 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex } } - if (elf.shdrs.size()) - { - end = 0; - } - // Load section list, used by the analyser for (const auto& s : elf.shdrs) { @@ -1860,7 +1842,7 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex { ovlm->secs.emplace_back(_sec); - if (_sec.flags & 0x4) + if (_sec.flags & 0x4 && addr >= ovlm->segs[0].addr && addr + size <= ovlm->segs[0].addr + ovlm->segs[0].size) { end = std::max(end, addr + size); }