Fix/fix jump tables (#65)

* feat: multipass discover additional entrypoints

* feat: added helpers for returning
feat: added game overrides

* added missing PS2_SHUFFLE_EPI8 macro after report from @playmer

* fix: fix jump tables

* fix: fix MMI comments
This commit is contained in:
Ranieri
2026-02-18 22:07:20 -03:00
committed by GitHub
parent 934672ac9a
commit 8b1f4e00f2
2 changed files with 98 additions and 7 deletions
+30 -6
View File
@@ -186,8 +186,7 @@ namespace ps2recomp
std::vector<uint32_t> sortedInternalTargets;
if (branchInst.opcode == OPCODE_SPECIAL &&
branchInst.function == SPECIAL_JR &&
rs_reg == 31 &&
(branchInst.function == SPECIAL_JR || branchInst.function == SPECIAL_JALR) &&
!internalTargets.empty())
{
sortedInternalTargets.reserve(internalTargets.size());
@@ -260,7 +259,11 @@ namespace ps2recomp
}
else
{
ss << " " << funcName << "(rdram, ctx, runtime);\n";
ss << " {\n";
ss << " const uint32_t __entryPc = ctx->pc;\n";
ss << " " << funcName << "(rdram, ctx, runtime);\n";
ss << fmt::format(" if (ctx->pc == __entryPc) {{ ctx->pc = 0x{:X}u; }}\n", fallthroughPc);
ss << " }\n";
ss << fmt::format(" if (ctx->pc != 0x{:X}u) {{ return; }}\n", fallthroughPc);
}
}
@@ -303,6 +306,7 @@ namespace ps2recomp
{
ss << " {\n";
ss << fmt::format(" auto targetFn = runtime->lookupFunction(0x{:X}u);\n", target);
ss << " const uint32_t __entryPc = ctx->pc;\n";
ss << " targetFn(rdram, ctx, runtime);\n";
if (branchInst.opcode == OPCODE_J)
{
@@ -310,6 +314,7 @@ namespace ps2recomp
}
else
{
ss << fmt::format(" if (ctx->pc == __entryPc) {{ ctx->pc = 0x{:X}u; }}\n", fallthroughPc);
ss << fmt::format(" if (ctx->pc != 0x{:X}u) {{ return; }}\n", fallthroughPc);
}
ss << " }\n";
@@ -339,7 +344,7 @@ namespace ps2recomp
ss << " ctx->pc = jumpTarget;\n";
if (branchInst.function == SPECIAL_JR && rs_reg == 31 && !sortedInternalTargets.empty())
if (!sortedInternalTargets.empty())
{
ss << " switch (jumpTarget) {\n";
for (uint32_t t : sortedInternalTargets)
@@ -358,7 +363,9 @@ namespace ps2recomp
{
ss << " {\n";
ss << " auto targetFn = runtime->lookupFunction(jumpTarget);\n";
ss << " const uint32_t __entryPc = ctx->pc;\n";
ss << " targetFn(rdram, ctx, runtime);\n";
ss << fmt::format(" if (ctx->pc == __entryPc) {{ ctx->pc = 0x{:X}u; }}\n", fallthroughPc);
ss << fmt::format(" if (ctx->pc != 0x{:X}u) {{ return; }}\n", fallthroughPc);
ss << " }\n";
}
@@ -558,10 +565,17 @@ namespace ps2recomp
std::unordered_set<uint32_t> targets;
std::unordered_set<uint32_t> instructionAddresses;
instructionAddresses.reserve(instructions.size());
bool hasIndirectRegisterJump = false;
for (const auto &inst : instructions)
{
instructionAddresses.insert(inst.address);
if (inst.opcode == OPCODE_SPECIAL &&
((inst.function == SPECIAL_JR && inst.rs != 31) ||
inst.function == SPECIAL_JALR))
{
hasIndirectRegisterJump = true;
}
}
for (const auto &inst : instructions)
@@ -600,6 +614,17 @@ namespace ps2recomp
}
}
if (hasIndirectRegisterJump)
{
for (uint32_t addr : instructionAddresses)
{
if (addr >= function.start && addr < function.end)
{
targets.insert(addr);
}
}
}
return targets;
}
@@ -621,7 +646,6 @@ namespace ps2recomp
}
std::unordered_set<uint32_t> internalTargets = collectInternalBranchTargets(function, instructions);
ss << "// Function: " << function.name << "\n";
ss << "// Address: 0x" << std::hex << function.start << " - 0x" << function.end << std::dec << "\n";
@@ -1633,7 +1657,7 @@ namespace ps2recomp
switch (subfunc)
{
case MMI3_PMADDUW:
return fmt::format("Unhandled PMADDUW instruction: function 0x{:X}", subfunc);
return fmt::format("// Unhandled PMADDUW instruction: function 0x{:X}", subfunc);
case MMI3_PSRAVW:
return fmt::format("SET_GPR_VEC(ctx, {}, PS2_PSRAVW(GPR_VEC(ctx, {}), GPR_VEC(ctx, {})));", rd, rs, rt);
case MMI3_PMTHI: