bctr and conditional returns

This commit is contained in:
Sajid 2024-09-13 20:27:05 +06:00
parent cbc28c6451
commit 27f6604072

View File

@ -18,9 +18,19 @@ size_t Function::SearchBlock(size_t address) const
const auto begin = base + block.base; const auto begin = base + block.base;
const auto end = begin + block.size; const auto end = begin + block.size;
if (address >= begin && address < end) if (begin != end)
{ {
return i; if (address >= begin && address < end)
{
return i;
}
}
else // fresh block
{
if (address == begin)
{
return i;
}
} }
} }
@ -53,6 +63,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
} }
auto& curBlock = blocks[blockStack.back()]; auto& curBlock = blocks[blockStack.back()];
DEBUG(const auto blockBase = curBlock.base);
const auto instruction = std::byteswap(*data); const auto instruction = std::byteswap(*data);
const auto op = PPC_OP(instruction); const auto op = PPC_OP(instruction);
@ -98,7 +109,6 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
if (lBlock == -1) if (lBlock == -1)
{ {
DEBUG(const auto blockBase = curBlock.base);
blocks.emplace_back(lBase, 0).projectedSize = rBase - lBase; blocks.emplace_back(lBase, 0).projectedSize = rBase - lBase;
lBlock = blocks.size() - 1; lBlock = blocks.size() - 1;
@ -110,7 +120,6 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
auto rBlock = fn.SearchBlock(base + rBase); auto rBlock = fn.SearchBlock(base + rBase);
if (rBlock == -1) if (rBlock == -1)
{ {
DEBUG(const auto blockBase = curBlock.base);
blocks.emplace_back(branchDest - base, 0); blocks.emplace_back(branchDest - base, 0);
rBlock = blocks.size() - 1; rBlock = blocks.size() - 1;
@ -120,7 +129,7 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
RESTORE_DATA(); RESTORE_DATA();
} }
else if (op == PPC_OP_B || instruction == 0 || (insn.opcode != nullptr && insn.opcode->id == PPC_INST_BLR)) // b, blr, end padding else if (op == PPC_OP_B || instruction == 0 || (op == PPC_OP_CTR && (xop == 16 || xop == 528))) // b, blr, end padding
{ {
if (!isLink) if (!isLink)
{ {
@ -135,7 +144,6 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
continue; 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);
@ -160,15 +168,36 @@ Function Function::Analyze(const void* code, size_t size, size_t base)
if (branchBlock == -1) if (branchBlock == -1)
{ {
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;
} }
} }
else if (op == PPC_OP_CTR)
{
// 5th bit of BO tells cpu to ignore the counter, which is a blr/bctr otherwise it's conditional
const auto conditional = !(PPC_BO(instruction) & 0x10);
if (conditional)
{
// right block's just going to return
const auto lBase = (addr - base) + 4;
auto lBlock = fn.SearchBlock(lBase);
if (lBlock == -1)
{
blocks.emplace_back(lBase, 0);
lBlock = blocks.size() - 1;
DEBUG(blocks[lBlock].parent = blockBase);
blockStack.emplace_back(lBlock);
RESTORE_DATA();
continue;
}
}
}
RESTORE_DATA(); RESTORE_DATA();
} }