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:
parent
4ce1b33e55
commit
6683b194ff
|
@ -444,6 +444,13 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
|||
BKPT(0x7777);
|
||||
}
|
||||
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))
|
||||
{
|
||||
// Don't do this yet
|
||||
|
|
|
@ -161,7 +161,8 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
|
|||
ArmCRegs[regindex].PS1 = PS1;
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -178,7 +179,8 @@ ARMReg ArmFPRCache::GetPPCReg(u32 preg, bool PS1, bool preLoad)
|
|||
ArmCRegs[lastRegIndex].PS1 = PS1;
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,4 +45,6 @@ public:
|
|||
void Flush(FlushMode mode = FLUSH_ALL);
|
||||
ArmGen::ARMReg R0(u32 preg, bool preLoad = true); // Returns a cached register
|
||||
ArmGen::ARMReg R1(u32 preg, bool preLoad = true);
|
||||
|
||||
void StoreFromRegister(u32 preg);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,4 +135,6 @@ public:
|
|||
// Public function doesn't kill immediates
|
||||
// In reality when you call R(u32) it'll bind an immediate there
|
||||
void BindToRegister(u32 preg, bool doLoad = true);
|
||||
|
||||
void StoreFromRegister(u32 preg);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue