SPU Analyzer: Fix jumptable analysis for SPU Block Mega

This commit is contained in:
Elad 2025-11-23 17:48:38 +02:00
parent ecba1d2cb7
commit 7472d95b0c

View file

@ -3153,6 +3153,35 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
} }
} }
for (usz i = 0; i < jt_abs.size(); i++)
{
if (jt_abs[i] == start + jt_abs.size() * 4)
{
// If jumptable contains absolute address of code start after the jumptable itself
// It is likely an absolute-type jumptable
bool is_good_conclusion = true;
// For verification: make sure there is none like this in relative table
for (u32 target : jt_rel)
{
if (target == start + jt_rel.size() * 4)
{
is_good_conclusion = false;
break;
}
}
if (is_good_conclusion)
{
jt_rel.clear();
}
break;
}
}
// Choose position after the jt as an anchor and compute the average distance // Choose position after the jt as an anchor and compute the average distance
for (u32 target : jt_abs) for (u32 target : jt_abs)
{ {
@ -7241,6 +7270,19 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
// Blocks starting from 0x0 or invalid instruction won't be compiled, may need special interpreter fallback // Blocks starting from 0x0 or invalid instruction won't be compiled, may need special interpreter fallback
} }
for (u32 i = 0; i < result.data.size(); i++)
{
const be_t<u32> ls_val = ls[result.lower_bound / 4 + i];
if (result.data[i] && std::bit_cast<u32>(ls_val) != result.data[i])
{
std::string out_dump;
dump(result, out_dump);
spu_log.error("SPU Function Dump:\n%s", out_dump);
fmt::throw_exception("SPU Analyzer failed: Instruction mismatch at 0x%x [read: 0x%x vs LS: 0x%x] (i=0x%x)", result.lower_bound + i * 4, std::bit_cast<be_t<u32>>(result.data[i]), ls_val, i);
}
}
return result; return result;
} }