From cc9e0755732b58f342f3a0aca9c3c3f918c8026d Mon Sep 17 00:00:00 2001 From: Ran-j Date: Wed, 2 Sep 2026 16:45:57 -0300 Subject: [PATCH] feat: analyzer resolve the complete constant-producing sequence with five-instruction backward scan stopped at LUI and therefore --- ps2xAnalyzer/src/elf_analyzer.cpp | 74 ++++++++++++------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/ps2xAnalyzer/src/elf_analyzer.cpp b/ps2xAnalyzer/src/elf_analyzer.cpp index b13ce20..5c57cdb 100644 --- a/ps2xAnalyzer/src/elf_analyzer.cpp +++ b/ps2xAnalyzer/src/elf_analyzer.cpp @@ -1,4 +1,5 @@ #include "ps2recomp/elf_analyzer.h" +#include "ps2recomp/gif_dma_kick_analyzer.h" #include "ps2recomp/analysis_passes.h" #include "ps2recomp/elf_parser.h" #include "ps2recomp/r5900_decoder.h" @@ -358,9 +359,11 @@ namespace ps2recomp } const auto &instructions = getDecodedInstructions(func); + ConstantRegisterState constantRegisters; for (const auto &inst : instructions) { + const MemoryAccessHint directAddress = resolveMemoryAccessHint(inst, constantRegisters); if (inst.opcode == OPCODE_LW || inst.opcode == OPCODE_SW || inst.opcode == OPCODE_LB || inst.opcode == OPCODE_SB || inst.opcode == OPCODE_LH || inst.opcode == OPCODE_SH || @@ -420,65 +423,46 @@ namespace ps2recomp } } } - // Also check for direct addressing with LUI+ADDIU combinations - else if (inst.opcode == OPCODE_LW || inst.opcode == OPCODE_SW) + + else if ((inst.opcode == OPCODE_LW || inst.opcode == OPCODE_SW) && directAddress.hasAddress) { - // Look for the LUI instruction that sets up the high bits - uint32_t baseAddr = 0; - for (int i = 1; i <= 5 && static_cast(inst.address) - i * 4 >= static_cast(func.start); i++) - { - uint32_t prevAddr = inst.address - i * 4; - uint32_t prevInst = 0; - if (!tryReadWord(m_elfParser.get(), prevAddr, prevInst)) - { - continue; - } + const uint32_t targetAddr = directAddress.address; - // Check if it's a LUI instruction for the same register - if (OPCODE(prevInst) == OPCODE_LUI && RT(prevInst) == inst.rs) - { - baseAddr = IMMEDIATE(prevInst) << 16; - break; - } + // Detect MMIO accesses + if ( + (targetAddr >= 0x10000000 && targetAddr < 0x14000000) || // I/O + (targetAddr >= 0x70000000 && targetAddr < 0x70004000) // Scratchpad + ) + { + m_mmioByInstructionAddress[inst.address] = targetAddr; + std::cout << "Detected MMIO access at " << std::hex << inst.address << " -> " << targetAddr << std::dec << std::endl; } - if (baseAddr != 0) + for (const auto §ion : m_context.sections) { - uint32_t targetAddr = baseAddr + static_cast(inst.immediate); - - // Detect MMIO accesses - if ((targetAddr >= 0x10000000 && targetAddr < 0x14000000) || // I/O - (targetAddr >= 0x70000000 && targetAddr < 0x70004000)) // Scratchpad + if (targetAddr >= section.address && targetAddr < section.address + section.size) { - m_mmioByInstructionAddress[inst.address] = targetAddr; - std::cout << "Detected MMIO access at " << std::hex << inst.address - << " -> " << targetAddr << std::dec << std::endl; - } + auto symIt = std::find_if(m_context.symbols.begin(), m_context.symbols.end(), + [targetAddr](const Symbol &s) + { return !s.isFunction && s.address <= targetAddr && + s.address + s.size > targetAddr; }); - for (const auto §ion : m_context.sections) - { - if (targetAddr >= section.address && targetAddr < section.address + section.size) + if (symIt != m_context.symbols.end()) { - auto symIt = std::find_if(m_context.symbols.begin(), m_context.symbols.end(), - [targetAddr](const Symbol &s) - { return !s.isFunction && s.address <= targetAddr && - s.address + s.size > targetAddr; }); + std::cout << "Function " << func.name << " directly accesses " + << (inst.opcode == OPCODE_LW ? "reads from" : "writes to") + << " data symbol " << symIt->name + << " at 0x" << std::hex << targetAddr << std::dec << std::endl; - if (symIt != m_context.symbols.end()) - { - std::cout << "Function " << func.name << " directly accesses " - << (inst.opcode == OPCODE_LW ? "reads from" : "writes to") - << " data symbol " << symIt->name - << " at 0x" << std::hex << targetAddr << std::dec << std::endl; - - m_functionDataUsage[func.name].insert(symIt->name); - } - break; + m_functionDataUsage[func.name].insert(symIt->name); } + break; } } } } + + updateConstantRegisters(inst, constantRegisters); } }