mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 23:41:26 +12:00
SPU: improve jumptable detection
This commit is contained in:
parent
cfa9b163fd
commit
acfe22e5bc
1 changed files with 49 additions and 7 deletions
|
@ -198,7 +198,7 @@ std::vector<u32> spu_recompiler_base::block(SPUThread& spu, u32 lsa, std::bitset
|
||||||
case spu_itype::STOP:
|
case spu_itype::STOP:
|
||||||
case spu_itype::STOPD:
|
case spu_itype::STOPD:
|
||||||
{
|
{
|
||||||
if (data == 0 || data == 0x80)
|
if (data == 0 || data == 3)
|
||||||
{
|
{
|
||||||
// Stop before null data
|
// Stop before null data
|
||||||
blocks[pos / 4] = true;
|
blocks[pos / 4] = true;
|
||||||
|
@ -267,12 +267,14 @@ std::vector<u32> spu_recompiler_base::block(SPUThread& spu, u32 lsa, std::bitset
|
||||||
std::basic_string<u32> jt_rel;
|
std::basic_string<u32> jt_rel;
|
||||||
const u32 start = pos + 4;
|
const u32 start = pos + 4;
|
||||||
const u32 limit = 0x40000;
|
const u32 limit = 0x40000;
|
||||||
|
u64 dabs = 0;
|
||||||
|
u64 drel = 0;
|
||||||
|
|
||||||
for (u32 i = start; i < limit; i += 4)
|
for (u32 i = start; i < limit; i += 4)
|
||||||
{
|
{
|
||||||
const u32 target = spu._ref<u32>(i);
|
const u32 target = spu._ref<u32>(i);
|
||||||
|
|
||||||
if (target % 4)
|
if (target == 0 || target % 4)
|
||||||
{
|
{
|
||||||
// Address cannot be misaligned: abort
|
// Address cannot be misaligned: abort
|
||||||
break;
|
break;
|
||||||
|
@ -297,22 +299,62 @@ std::vector<u32> spu_recompiler_base::block(SPUThread& spu, u32 lsa, std::bitset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add detected jump table blocks (TODO: avoid adding both)
|
// Choose position after the jt as an anchor and compute the average distance
|
||||||
|
for (u32 target : jt_abs)
|
||||||
|
{
|
||||||
|
dabs += std::abs(static_cast<s32>(target - start - jt_abs.size() * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 target : jt_rel)
|
||||||
|
{
|
||||||
|
drel += std::abs(static_cast<s32>(target - start - jt_rel.size() * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add detected jump table blocks
|
||||||
if (jt_abs.size() >= 3 || jt_rel.size() >= 3)
|
if (jt_abs.size() >= 3 || jt_rel.size() >= 3)
|
||||||
{
|
{
|
||||||
|
if (jt_abs.size() == jt_rel.size())
|
||||||
|
{
|
||||||
|
if (dabs < drel)
|
||||||
|
{
|
||||||
|
jt_rel.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dabs > drel)
|
||||||
|
{
|
||||||
|
jt_abs.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (jt_abs.size() >= jt_rel.size())
|
if (jt_abs.size() >= jt_rel.size())
|
||||||
{
|
{
|
||||||
for (u32 target : jt_abs)
|
const u32 new_size = (start - lsa) / 4 + 1 + jt_abs.size();
|
||||||
|
|
||||||
|
if (result.size() < new_size)
|
||||||
{
|
{
|
||||||
add_block(target);
|
result.resize(new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < jt_abs.size(); i++)
|
||||||
|
{
|
||||||
|
add_block(jt_abs[i]);
|
||||||
|
result[(start - lsa) / 4 + 1 + i] = se_storage<u32>::swap(jt_abs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jt_rel.size() >= jt_abs.size())
|
if (jt_rel.size() >= jt_abs.size())
|
||||||
{
|
{
|
||||||
for (u32 target : jt_rel)
|
const u32 new_size = (start - lsa) / 4 + 1 + jt_rel.size();
|
||||||
|
|
||||||
|
if (result.size() < new_size)
|
||||||
{
|
{
|
||||||
add_block(target);
|
result.resize(new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < jt_rel.size(); i++)
|
||||||
|
{
|
||||||
|
add_block(jt_rel[i]);
|
||||||
|
result[(start - lsa) / 4 + 1 + i] = se_storage<u32>::swap(jt_rel[i] - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue