mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 15:01:16 +01:00
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;
|
func->flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsMfspr(UGeckoInstruction inst)
|
||||||
|
{
|
||||||
|
return inst.OPCD == 31 && inst.SUBOP10 == 339;
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsMtspr(UGeckoInstruction inst)
|
static bool IsMtspr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
return inst.OPCD == 31 && inst.SUBOP10 == 467;
|
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);
|
DEBUG_ASSERT(IsMfspr(inst) || IsMtspr(inst));
|
||||||
return index == SPR_MMCR0 || index == SPR_MMCR1;
|
return (inst.SPRU << 5) | (inst.SPRL & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InstructionCanEndBlock(const CodeOp& op)
|
static bool InstructionCanEndBlock(const CodeOp& op)
|
||||||
{
|
{
|
||||||
return (op.opinfo->flags & FL_ENDBLOCK) &&
|
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
|
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
|
// 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
|
// 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
|
if (IsMfspr(code->inst))
|
||||||
code->wantsCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
|
code->wantsCA = GetSPRIndex(code->inst) == SPR_XER;
|
||||||
if (code->inst.OPCD == 31 && code->inst.SUBOP10 == 467) // mtspr
|
if (IsMtspr(code->inst))
|
||||||
code->outputCA = ((code->inst.SPRU << 5) | (code->inst.SPRL & 0x1F)) == SPR_XER;
|
code->outputCA = GetSPRIndex(code->inst) == SPR_XER;
|
||||||
|
|
||||||
code->regsIn = BitSet32(0);
|
code->regsIn = BitSet32(0);
|
||||||
code->regsOut = 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,
|
// 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
|
// 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
|
// 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;
|
follow = true;
|
||||||
found_call = false;
|
found_call = false;
|
||||||
code[i].skip = true;
|
code[i].skip = true;
|
||||||
@ -901,16 +907,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||||||
code[caller].skipLRStack = true;
|
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.
|
// LR has been overwritten, so we give up on following the return address.
|
||||||
const u32 index = (inst.SPRU << 5) | (inst.SPRL & 0x1F);
|
found_call = false;
|
||||||
if (index == SPR_LR)
|
|
||||||
{
|
|
||||||
// We give up to follow the return address
|
|
||||||
// because we have to check the register usage.
|
|
||||||
found_call = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -962,8 +962,8 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||||||
}
|
}
|
||||||
if (conditional_continue)
|
if (conditional_continue)
|
||||||
{
|
{
|
||||||
// If we skip any conditional branch, we can't garantee to get the matching CALL/RET pair.
|
// If we skip any conditional branch, we can't guarantee to get the matching CALL/RET pair.
|
||||||
// So we stop inling the RET here and let the BLR optitmization handle this case.
|
// So we stop inlining the RET here and let the BLR optimization handle this case.
|
||||||
found_call = false;
|
found_call = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1142,9 +1142,9 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
|
|||||||
gqrUsed[gqr] = true;
|
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)
|
if (gqr >= 0 && gqr <= 7)
|
||||||
gqrModified[gqr] = true;
|
gqrModified[gqr] = true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user