PPCAnalyst: EvaluateBranchTarget improved

This commit is contained in:
Sepalani
2017-05-07 03:39:39 +01:00
parent ef4a1f0ec7
commit 95d0a48759

View File

@ -53,7 +53,15 @@ static u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc)
{ {
switch (instr.OPCD) switch (instr.OPCD)
{ {
case 18: // branch instruction case 16: // bcx - Branch Conditional instructions
{
u32 target = SignExt16(instr.BD << 2);
if (!instr.AA)
target += pc;
return target;
}
case 18: // bx - Branch instructions
{ {
u32 target = SignExt26(instr.LI << 2); u32 target = SignExt26(instr.LI << 2);
if (!instr.AA) if (!instr.AA)
@ -83,11 +91,10 @@ bool AnalyzeFunction(u32 startAddr, Symbol& func, int max_size)
func.callers.clear(); func.callers.clear();
func.size = 0; func.size = 0;
func.flags = FFLAG_LEAF; func.flags = FFLAG_LEAF;
u32 addr = startAddr;
u32 farthestInternalBranchTarget = startAddr; u32 farthestInternalBranchTarget = startAddr;
int numInternalBranches = 0; int numInternalBranches = 0;
while (true) for (u32 addr = startAddr; true; addr += 4)
{ {
func.size += 4; func.size += 4;
if (func.size >= CODEBUFFER_SIZE * 4 || !PowerPC::HostIsRAMAddress(addr)) // weird if (func.size >= CODEBUFFER_SIZE * 4 || !PowerPC::HostIsRAMAddress(addr)) // weird
@ -110,22 +117,19 @@ bool AnalyzeFunction(u32 startAddr, Symbol& func, int max_size)
// 4e800021 is blrl, not the end of a function // 4e800021 is blrl, not the end of a function
if (instr.hex == 0x4e800020 || instr.hex == 0x4C000064) if (instr.hex == 0x4e800020 || instr.hex == 0x4C000064)
{ {
// Not this one, continue..
if (farthestInternalBranchTarget > addr) if (farthestInternalBranchTarget > addr)
{ continue;
// bah, not this one, continue..
} // A final blr!
else // We're done! Looks like we have a neat valid function. Perfect.
{ // Let's calc the checksum and get outta here
// a final blr! func.address = startAddr;
// We're done! Looks like we have a neat valid function. Perfect. func.analyzed = true;
// Let's calc the checksum and get outta here func.hash = HashSignatureDB::ComputeCodeChecksum(startAddr, addr);
func.address = startAddr; if (numInternalBranches == 0)
func.analyzed = true; func.flags |= FFLAG_STRAIGHT;
func.hash = HashSignatureDB::ComputeCodeChecksum(startAddr, addr); return true;
if (numInternalBranches == 0)
func.flags |= FFLAG_STRAIGHT;
return true;
}
} }
/* /*
else if ((instr.hex & 0xFC000000) == (0x4b000000 & 0xFC000000) && !instr.LK) else if ((instr.hex & 0xFC000000) == (0x4b000000 & 0xFC000000) && !instr.LK)
@ -155,36 +159,31 @@ bool AnalyzeFunction(u32 startAddr, Symbol& func, int max_size)
} }
else else
{ {
if (instr.OPCD == 16) u32 target = EvaluateBranchTarget(instr, addr);
if (target == INVALID_BRANCH_TARGET)
continue;
if (instr.LK)
{ {
u32 target = SignExt16(instr.BD << 2); // Found a branch-n-link
func.calls.emplace_back(target, addr);
if (!instr.AA) func.flags &= ~FFLAG_LEAF;
target += addr; }
else if (instr.OPCD == 16)
if (target > farthestInternalBranchTarget && !instr.LK) {
// Found a conditional branch
if (target > farthestInternalBranchTarget)
{ {
farthestInternalBranchTarget = target; farthestInternalBranchTarget = target;
} }
numInternalBranches++; numInternalBranches++;
} }
else
{
u32 target = EvaluateBranchTarget(instr, addr);
if (target != INVALID_BRANCH_TARGET && instr.LK)
{
// we found a branch-n-link!
func.calls.emplace_back(target, addr);
func.flags &= ~FFLAG_LEAF;
}
}
} }
} }
else else
{ {
return false; return false;
} }
addr += 4;
} }
} }