feat: analyzer resolve the complete constant-producing sequence with five-instruction backward scan stopped at LUI and therefore

This commit is contained in:
Ran-j
2026-09-02 16:45:57 -03:00
parent a293fa433a
commit cc9e075573
+29 -45
View File
@@ -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<int>(inst.address) - i * 4 >= static_cast<int>(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 &section : m_context.sections)
{
uint32_t targetAddr = baseAddr + static_cast<int16_t>(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 &section : 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);
}
}