mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-06-06 18:31:03 +00:00
Chase after branches again, but better
This commit is contained in:
parent
c167e5c90c
commit
6e48ca31ab
@ -120,39 +120,53 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
|
|||||||
|
|
||||||
RESTORE_DATA();
|
RESTORE_DATA();
|
||||||
}
|
}
|
||||||
else if (op == PPC_OP_B || (op == PPC_OP_CTR && xop == 16) || instruction == 0) // b, blr, end padding
|
else if (op == PPC_OP_B || instruction == 0 || insn.opcode->id == PPC_INST_BLR) // b, blr, end padding
|
||||||
{
|
{
|
||||||
if (!isLink)
|
if (!isLink)
|
||||||
{
|
{
|
||||||
blockStack.pop_back();
|
blockStack.pop_back();
|
||||||
|
|
||||||
// Keep analyzing if we have continuity
|
|
||||||
if (op == PPC_OP_B)
|
if (op == PPC_OP_B)
|
||||||
{
|
{
|
||||||
|
// Tail call, no need to chase
|
||||||
|
if (blocks.size() == 1)
|
||||||
|
{
|
||||||
|
RESTORE_DATA();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep analyzing if we have continuity
|
||||||
assert(!PPC_BA(instruction));
|
assert(!PPC_BA(instruction));
|
||||||
const auto branchDest = addr + PPC_BI(instruction);
|
const auto branchDest = addr + PPC_BI(instruction);
|
||||||
|
|
||||||
const auto branchBase = branchDest - base;
|
const auto branchBase = branchDest - base;
|
||||||
const auto branchBlock = fn.SearchBlock(branchDest);
|
const auto branchBlock = fn.SearchBlock(branchDest);
|
||||||
|
|
||||||
|
if (branchDest < base)
|
||||||
|
{
|
||||||
|
// Branches before base are just tail calls, no need to chase after those
|
||||||
|
RESTORE_DATA();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// carry over our projection if blocks are next to each other
|
// carry over our projection if blocks are next to each other
|
||||||
const auto isContinious = branchBase == curBlock.base + curBlock.size;
|
const auto isContinuous = branchBase == curBlock.base + curBlock.size;
|
||||||
auto sizeProjection = (size_t)-1;
|
auto sizeProjection = (size_t)-1;
|
||||||
|
|
||||||
if (isContinious && curBlock.projectedSize != -1)
|
if (curBlock.projectedSize != -1 && isContinuous)
|
||||||
{
|
{
|
||||||
sizeProjection = curBlock.projectedSize - curBlock.size;
|
sizeProjection = curBlock.projectedSize - curBlock.size;
|
||||||
|
}
|
||||||
|
|
||||||
if (branchBlock == -1)
|
if (branchBlock == -1)
|
||||||
{
|
{
|
||||||
DEBUG(const auto blockBase = curBlock.base);
|
DEBUG(const auto blockBase = curBlock.base);
|
||||||
blocks.emplace_back(branchBase, 0, sizeProjection);
|
blocks.emplace_back(branchBase, 0, sizeProjection);
|
||||||
|
|
||||||
blockStack.emplace_back(blocks.size() - 1);
|
blockStack.emplace_back(blocks.size() - 1);
|
||||||
DEBUG(blocks.back().parent = blockBase);
|
DEBUG(blocks.back().parent = blockBase);
|
||||||
RESTORE_DATA();
|
RESTORE_DATA();
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +175,32 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort and invalidate discontinuous blocks
|
||||||
|
if (blocks.size() > 1)
|
||||||
|
{
|
||||||
|
std::ranges::sort(blocks, [](const Block& a, const Block& b)
|
||||||
|
{
|
||||||
|
return a.base < b.base;
|
||||||
|
});
|
||||||
|
|
||||||
|
size_t discontinuity = -1;
|
||||||
|
for (size_t i = 0; i < blocks.size() - 1; i++)
|
||||||
|
{
|
||||||
|
if (blocks[i].base + blocks[i].size >= blocks[i + 1].base)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
discontinuity = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discontinuity != -1)
|
||||||
|
{
|
||||||
|
blocks.erase(blocks.begin() + discontinuity, blocks.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn.size = 0;
|
fn.size = 0;
|
||||||
for (const auto& block : blocks)
|
for (const auto& block : blocks)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user