ARMv7 register cache optimizations.

Enable support for not loading a destination register on FPR cache.
Dump registers if they won't be used later in the block. Stolen from Fiora.
This commit is contained in:
Ryan Houdek 2014-11-15 22:12:24 +00:00
parent 4ce1b33e55
commit 6683b194ff
5 changed files with 55 additions and 2 deletions

View File

@ -444,6 +444,13 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
BKPT(0x7777); BKPT(0x7777);
} }
JitArmTables::CompileInstruction(ops[i]); JitArmTables::CompileInstruction(ops[i]);
// If we have a register that will never be used again, flush it.
for (int j : ~ops[i].gprInUse)
gpr.StoreFromRegister(j);
for (int j : ~ops[i].fprInUse)
fpr.StoreFromRegister(j);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{ {
// Don't do this yet // Don't do this yet

View File

@ -161,7 +161,8 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
ArmCRegs[regindex].PS1 = PS1; ArmCRegs[regindex].PS1 = PS1;
_regs[preg][PS1].LoadToReg(regindex); _regs[preg][PS1].LoadToReg(regindex);
emit->VLDR(ArmCRegs[regindex].Reg, R9, offset); if (preLoad)
emit->VLDR(ArmCRegs[regindex].Reg, R9, offset);
return ArmCRegs[regindex].Reg; return ArmCRegs[regindex].Reg;
} }
@ -178,7 +179,8 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
ArmCRegs[lastRegIndex].PS1 = PS1; ArmCRegs[lastRegIndex].PS1 = PS1;
_regs[preg][PS1].LoadToReg(lastRegIndex); _regs[preg][PS1].LoadToReg(lastRegIndex);
emit->VLDR(ArmCRegs[lastRegIndex].Reg, R9, offsetNew); if (preLoad)
emit->VLDR(ArmCRegs[lastRegIndex].Reg, R9, offsetNew);
return ArmCRegs[lastRegIndex].Reg; return ArmCRegs[lastRegIndex].Reg;
} }
@ -225,3 +227,26 @@ void ArmFPRCache::Flush(FlushMode mode)
} }
} }
void ArmFPRCache::StoreFromRegister(u32 preg)
{
if (_regs[preg][0].GetType() != REG_NOTLOADED)
{
s16 offset = PPCSTATE_OFF(ps) + (preg * 16);
u32 regindex = _regs[preg][0].GetRegIndex();
emit->VSTR(ArmCRegs[regindex].Reg, R9, offset);
ArmCRegs[regindex].PPCReg = 33;
ArmCRegs[regindex].LastLoad = 0;
_regs[preg][0].Flush();
}
if (_regs[preg][1].GetType() != REG_NOTLOADED)
{
s16 offset = PPCSTATE_OFF(ps) + (preg * 16) + 8;
u32 regindex = _regs[preg][1].GetRegIndex();
emit->VSTR(ArmCRegs[regindex].Reg, R9, offset);
ArmCRegs[regindex].PPCReg = 33;
ArmCRegs[regindex].LastLoad = 0;
_regs[preg][1].Flush();
}
}

View File

@ -45,4 +45,6 @@ public:
void Flush(FlushMode mode = FLUSH_ALL); void Flush(FlushMode mode = FLUSH_ALL);
ArmGen::ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register ArmGen::ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register
ArmGen::ARMReg R1(u32 preg, bool preLoad = true); ArmGen::ARMReg R1(u32 preg, bool preLoad = true);
void StoreFromRegister(u32 preg);
}; };

View File

@ -300,3 +300,20 @@ void ArmRegCache::Flush(FlushMode mode)
} }
} }
void ArmRegCache::StoreFromRegister(u32 preg)
{
if (regs[preg].GetType() == REG_IMM)
{
// This changes the type over to a REG_REG and gets caught below.
BindToRegister(preg, true, true);
}
if (regs[preg].GetType() == REG_REG)
{
u32 regindex = regs[preg].GetRegIndex();
emit->STR(ArmCRegs[regindex].Reg, R9, PPCSTATE_OFF(gpr) + preg * 4);
ArmCRegs[regindex].PPCReg = 33;
ArmCRegs[regindex].LastLoad = 0;
regs[preg].Flush();
}
}

View File

@ -135,4 +135,6 @@ public:
// Public function doesn't kill immediates // Public function doesn't kill immediates
// In reality when you call R(u32) it'll bind an immediate there // In reality when you call R(u32) it'll bind an immediate there
void BindToRegister(u32 preg, bool doLoad = true); void BindToRegister(u32 preg, bool doLoad = true);
void StoreFromRegister(u32 preg);
}; };