summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2014-11-15 22:12:24 +0000
committerRyan Houdek <Sonicadvance1@gmail.com>2014-11-16 09:29:22 +0000
commit6683b194ffb06b68643c041f2f5b8df6eabe9863 (patch)
tree3550e207819e2384fd0a341c2a26564ee279f8da /Source
parent4ce1b33e55f9b608bd97f5d71bf517af3622b3c5 (diff)
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.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/PowerPC/JitArm32/Jit.cpp7
-rw-r--r--Source/Core/Core/PowerPC/JitArm32/JitFPRCache.cpp29
-rw-r--r--Source/Core/Core/PowerPC/JitArm32/JitFPRCache.h2
-rw-r--r--Source/Core/Core/PowerPC/JitArm32/JitRegCache.cpp17
-rw-r--r--Source/Core/Core/PowerPC/JitArm32/JitRegCache.h2
5 files changed, 55 insertions, 2 deletions
diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp
index cf2ef79562..b8a4ad91a3 100644
--- a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp
+++ b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp
@@ -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
diff --git a/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.cpp b/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.cpp
index 3d2af8453e..3dd1b59a9f 100644
--- a/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.cpp
+++ b/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.cpp
@@ -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();
+ }
+}
diff --git a/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.h b/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.h
index cf873eaa57..fd77b4da1b 100644
--- a/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.h
+++ b/Source/Core/Core/PowerPC/JitArm32/JitFPRCache.h
@@ -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);
};
diff --git a/Source/Core/Core/PowerPC/JitArm32/JitRegCache.cpp b/Source/Core/Core/PowerPC/JitArm32/JitRegCache.cpp
index fc057fdc9e..cb11ed5644 100644
--- a/Source/Core/Core/PowerPC/JitArm32/JitRegCache.cpp
+++ b/Source/Core/Core/PowerPC/JitArm32/JitRegCache.cpp
@@ -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();
+ }
+}
diff --git a/Source/Core/Core/PowerPC/JitArm32/JitRegCache.h b/Source/Core/Core/PowerPC/JitArm32/JitRegCache.h
index 7e7acaaf9a..7ccf8eae2c 100644
--- a/Source/Core/Core/PowerPC/JitArm32/JitRegCache.h
+++ b/Source/Core/Core/PowerPC/JitArm32/JitRegCache.h
@@ -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);
};