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); };