Merge pull request #12811 from JosJuice/ppcanalyst-refactor-mtspr
PPCAnalyst: Refactor mtspr handling code
This commit is contained in:
commit
6cc2133f27
|
@ -202,21 +202,27 @@ static void AnalyzeFunction2(PPCSymbolDB* func_db, Common::Symbol* func)
|
|||
func->flags = flags;
|
||||
}
|
||||
|
||||
static bool IsMfspr(UGeckoInstruction inst)
|
||||
{
|
||||
return inst.OPCD == 31 && inst.SUBOP10 == 339;
|
||||
}
|
||||
|
||||
static bool IsMtspr(UGeckoInstruction inst)
|
||||
{
|
||||
return inst.OPCD == 31 && inst.SUBOP10 == 467;
|
||||
}
|
||||
|
||||
static bool IsSprInstructionUsingMmcr(UGeckoInstruction inst)
|
||||
static u32 GetSPRIndex(UGeckoInstruction inst)
|
||||
{
|
||||
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
|
||||
return index == SPR_MMCR0 || index == SPR_MMCR1;
|
||||
DEBUG_ASSERT(IsMfspr(inst) || IsMtspr(inst));
|
||||
return (inst.SPRU << 5) | (inst.SPRL & 0x1F);
|
||||
}
|
||||
|
||||
static bool InstructionCanEndBlock(const CodeOp& op)
|
||||
{
|
||||
return (op.opinfo->flags & FL_ENDBLOCK) &&
|
||||
(!IsMtspr(op.inst) || IsSprInstructionUsingMmcr(op.inst));
|
||||
(!IsMtspr(op.inst) || GetSPRIndex(op.inst) == SPR_MMCR0 ||
|
||||
GetSPRIndex(op.inst) == SPR_MMCR1);
|
||||
}
|
||||
|
||||
bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const
|
||||
|
@ -637,10 +643,10 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code,
|
|||
|
||||
// mfspr/mtspr can affect/use XER, so be super careful here
|
||||
// we need to note specifically that mfspr needs CA in XER, not in the x86 carry flag
|
||||
if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 339) // mfspr
|
||||
code->wantsCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
|
||||
if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 467) // mtspr
|
||||
code->outputCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
|
||||
if (IsMfspr(code->inst))
|
||||
code->wantsCA = GetSPRIndex(code->inst) == SPR_XER;
|
||||
if (IsMtspr(code->inst))
|
||||
code->outputCA = GetSPRIndex(code->inst) == SPR_XER;
|
||||
|
||||
code->regsIn = BitSet32(0);
|
||||
code->regsOut = BitSet32(0);
|
||||
|
@ -892,7 +898,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||
// Through it would be easy to track the upper level of call/return,
|
||||
// we can't guarantee the LR value. The PPC ABI forces all functions to push
|
||||
// the LR value on the stack as there are no spare registers. So we'd need
|
||||
// to check all store instruction to not alias with the stack.
|
||||
// to check all store instructions to not alias with the stack.
|
||||
follow = true;
|
||||
found_call = false;
|
||||
code[i].skip = true;
|
||||
|
@ -901,16 +907,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||
code[caller].skipLRStack = true;
|
||||
}
|
||||
}
|
||||
else if (inst.OPCD == 31 && inst.SUBOP10 == 467)
|
||||
else if (IsMtspr(inst) && GetSPRIndex(inst) == SPR_LR)
|
||||
{
|
||||
// mtspr, skip CALL/RET merging as LR is overwritten.
|
||||
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
|
||||
if (index == SPR_LR)
|
||||
{
|
||||
// We give up to follow the return address
|
||||
// because we have to check the register usage.
|
||||
found_call = false;
|
||||
}
|
||||
// LR has been overwritten, so we give up on following the return address.
|
||||
found_call = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -962,8 +962,8 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||
}
|
||||
if (conditional_continue)
|
||||
{
|
||||
// If we skip any conditional branch, we can't garantee to get the matching CALL/RET pair.
|
||||
// So we stop inling the RET here and let the BLR optitmization handle this case.
|
||||
// If we skip any conditional branch, we can't guarantee to get the matching CALL/RET pair.
|
||||
// So we stop inlining the RET here and let the BLR optimization handle this case.
|
||||
found_call = false;
|
||||
}
|
||||
}
|
||||
|
@ -1142,9 +1142,9 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||
gqrUsed[gqr] = true;
|
||||
}
|
||||
|
||||
if (op.inst.OPCD == 31 && op.inst.SUBOP10 == 467) // mtspr
|
||||
if (IsMtspr(op.inst))
|
||||
{
|
||||
const int gqr = ((op.inst.SPRU << 5) | op.inst.SPRL) - SPR_GQR0;
|
||||
const int gqr = GetSPRIndex(op.inst) - SPR_GQR0;
|
||||
if (gqr >= 0 && gqr <= 7)
|
||||
gqrModified[gqr] = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue