Merge pull request #1073 from phire/save_jitil2

Fix Idle Skipping in JitIL.
This commit is contained in:
Dolphin Bot 2014-09-13 18:40:57 +02:00
commit d72f61d62f
4 changed files with 33 additions and 19 deletions

View File

@ -909,7 +909,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
regMarkUse(RI, I, getOp1(I), 1); regMarkUse(RI, I, getOp1(I), 1);
break; break;
case IdleBranch: case IdleBranch:
regMarkUse(RI, I, getOp1(getOp1(I)), 1); regMarkUse(RI, I, getOp1(I), 1);
break; break;
case BranchCond: case BranchCond:
{ {
@ -2088,9 +2088,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
case IdleBranch: case IdleBranch:
{ {
Jit->CMP(32, regLocForInst(RI, getOp1(getOp1(I))), // If value is 0, we don't need to call out to the idle function.
Imm32(RI.Build->GetImmValue(getOp2(getOp1(I))))); OpArg value = regLocForInst(RI, getOp1(I));
FixupBranch cont = Jit->J_CC(CC_NE); Jit->TEST(32, value, value);
FixupBranch noidle = Jit->J_CC(CC_NZ);
RI.Jit->Cleanup(); // is it needed? RI.Jit->Cleanup(); // is it needed?
Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL); Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL);
@ -2098,9 +2099,9 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->MOV(32, PPCSTATE(pc), Imm32(ibuild->GetImmValue( getOp2(I) ))); Jit->MOV(32, PPCSTATE(pc), Imm32(ibuild->GetImmValue( getOp2(I) )));
Jit->WriteExceptionExit(); Jit->WriteExceptionExit();
Jit->SetJumpTarget(cont); Jit->SetJumpTarget(noidle);
if (RI.IInfo[I - RI.FirstI] & 4) if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, getOp1(getOp1(I))); regClearInst(RI, getOp1(I));
if (RI.IInfo[I - RI.FirstI] & 8) if (RI.IInfo[I - RI.FirstI] & 8)
regClearInst(RI, getOp2(I)); regClearInst(RI, getOp2(I));
break; break;

View File

@ -1083,11 +1083,6 @@ InstLoc IRBuilder::FoldBranchCond(InstLoc Op1, InstLoc Op2)
return EmitBiOp(BranchCond, Op1, Op2); return EmitBiOp(BranchCond, Op1, Op2);
} }
InstLoc IRBuilder::FoldIdleBranch(InstLoc Op1, InstLoc Op2)
{
return EmitBiOp(IdleBranch, EmitICmpEq(getOp1(getOp1(Op1)), getOp2(getOp1(Op1))), Op2);
}
InstLoc IRBuilder::FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2) InstLoc IRBuilder::FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2)
{ {
if (isImm(*Op1)) if (isImm(*Op1))
@ -1245,8 +1240,6 @@ InstLoc IRBuilder::FoldBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, unsigned
return FoldRol(Op1, Op2); return FoldRol(Op1, Op2);
case BranchCond: case BranchCond:
return FoldBranchCond(Op1, Op2); return FoldBranchCond(Op1, Op2);
case IdleBranch:
return FoldIdleBranch(Op1, Op2);
case ICmpEq: case ICmpNe: case ICmpEq: case ICmpNe:
case ICmpUgt: case ICmpUlt: case ICmpUge: case ICmpUle: case ICmpUgt: case ICmpUlt: case ICmpUge: case ICmpUle:
case ICmpSgt: case ICmpSlt: case ICmpSge: case ICmpSle: case ICmpSgt: case ICmpSlt: case ICmpSge: case ICmpSle:

View File

@ -138,6 +138,10 @@ void JitILBase::bcx(UGeckoInstruction inst)
else else
destination = js.compilerPC + SignExt16(inst.BD << 2); destination = js.compilerPC + SignExt16(inst.BD << 2);
// Idle skipping:
// The main Idle skipping is done in the LoadStore code, but there is an optimization here.
// If idle skipping is enabled, then this branch will only be reached when the branch is not
// taken.
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
inst.hex == 0x4182fff8 && inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 && (Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
@ -145,7 +149,7 @@ void JitILBase::bcx(UGeckoInstruction inst)
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000)) (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
) )
{ {
ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination)); // Uh, Do nothing.
} }
else else
{ {

View File

@ -33,6 +33,22 @@ void JitILBase::lXz(UGeckoInstruction inst)
ibuild.EmitStoreGReg(addr, inst.RA); ibuild.EmitStoreGReg(addr, inst.RA);
IREmitter::InstLoc val; IREmitter::InstLoc val;
// Idle Skipping. This really should be done somewhere else.
// Either lower in the IR or higher in PPCAnalyist
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
inst.OPCD == 32 && // Lwx
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
{
val = ibuild.EmitLoad32(addr);
ibuild.EmitIdleBranch(val, ibuild.EmitIntConst(js.compilerPC));
ibuild.EmitStoreGReg(val, inst.RD);
return;
}
switch (inst.OPCD & ~0x1) switch (inst.OPCD & ~0x1)
{ {
case 32: // lwz case 32: // lwz