From 5a95e267fb1c56595d296bbc43b1ddc4413cc2e9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 8 Nov 2013 12:30:31 +0100 Subject: [PATCH] Add an optimization to discard registers at the end of functions when possible. Works in some games but crashes many so hiding it for now. Do not add UI. --- Core/Config.cpp | 3 +++ Core/Config.h | 3 +++ Core/MIPS/ARM/ArmCompBranch.cpp | 12 +++++++++++- Core/MIPS/ARM/ArmRegCache.cpp | 11 +++++++++++ Core/MIPS/ARM/ArmRegCache.h | 1 + Core/MIPS/MIPS.h | 7 +++++++ Core/MIPS/x86/CompBranch.cpp | 14 +++++++++++++- 7 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 5a54230695..5c1be4e32e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -315,6 +315,9 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { speedhacks->Get("PrescaleUV", &bPrescaleUV, false); speedhacks->Get("DisableAlphaTest", &bDisableAlphaTest, false); + IniFile::Section *jitConfig = iniFile.GetOrCreateSection("JIT"); + jitConfig->Get("DiscardRegsOnJRRA", &bDiscardRegsOnJRRA, false); + INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str()); bSaveSettings = true; diff --git a/Core/Config.h b/Core/Config.h index d44ecccd4b..51af3b3e57 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -185,6 +185,9 @@ public: bool bDisableAlphaTest; // Helps PowerVR immensely, breaks some graphics // End GLES hacks. + // Risky JIT optimizations + bool bDiscardRegsOnJRRA; + // SystemParam std::string sNickName; int iLanguage; diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index c9bf8e87d7..414af608f9 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -16,7 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/Reporting.h" - +#include "Core/Config.h" #include "Core/HLE/HLE.h" #include "Core/HLE/HLETables.h" @@ -388,6 +388,16 @@ void Jit::Comp_JumpReg(MIPSOpcode op) CompileDelaySlot(DELAYSLOT_NICE); gpr.MapReg(rs); destReg = gpr.R(rs); // Safe because FlushAll doesn't change any regs + if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + // According to the MIPS ABI, there are some regs we don't need to preserve. + // Let's discard them so we don't need to write them back. + // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash + // with this enabled. + for (int i = MIPS_REG_A0; i <= MIPS_REG_T7; i++) + gpr.DiscardR((MIPSGPReg)i); + gpr.DiscardR(MIPS_REG_T8); + gpr.DiscardR(MIPS_REG_T9); + } FlushAll(); } else { // Delay slot diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index c1573a77c6..51bf71b1ca 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -200,6 +200,17 @@ void ArmRegCache::FlushArmReg(ARMReg r) { ar[r].mipsReg = -1; } +void ArmRegCache::DiscardR(MIPSReg r) { + if (mr[r].loc == ML_ARMREG) { + ARMReg a = mr[r].reg; + ar[a].isDirty = false; + ar[a].mipsReg = -1; + mr[r].reg = INVALID_REG; + mr[r].loc = ML_MEM; + mr[r].imm = 0; + } +} + void ArmRegCache::FlushR(MIPSReg r) { switch (mr[r].loc) { case ML_IMM: diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h index 9d3c6d1d8c..58ca3a5ea5 100644 --- a/Core/MIPS/ARM/ArmRegCache.h +++ b/Core/MIPS/ARM/ArmRegCache.h @@ -101,6 +101,7 @@ public: void FlushR(MIPSReg r); void FlushBeforeCall(); void FlushAll(); + void DiscardR(MIPSReg r); ARMReg R(int preg); // Returns a cached register diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index 07eebbca10..3fc6dbef49 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -39,6 +39,11 @@ enum MIPSGPReg MIPS_REG_A4=8, // Seems to be N32 register calling convention - there are 8 args instead of 4. MIPS_REG_A5=9, + MIPS_REG_T4=12, + MIPS_REG_T5=13, + MIPS_REG_T6=14, + MIPS_REG_T7=15, + MIPS_REG_S0=16, MIPS_REG_S1=17, MIPS_REG_S2=18, @@ -47,6 +52,8 @@ enum MIPSGPReg MIPS_REG_S5=21, MIPS_REG_S6=22, MIPS_REG_S7=23, + MIPS_REG_T8=24, + MIPS_REG_T9=25, MIPS_REG_K0=26, MIPS_REG_K1=27, MIPS_REG_GP=28, diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 75368a74d2..40134f6f5b 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -16,7 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/Reporting.h" - +#include "Core/Config.h" #include "Core/HLE/HLE.h" #include "Core/HLE/HLETables.h" #include "Core/Host.h" @@ -596,6 +596,18 @@ void Jit::Comp_JumpReg(MIPSOpcode op) { CompileDelaySlot(DELAYSLOT_NICE); MOV(32, R(EAX), gpr.R(rs)); + + if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + // According to the MIPS ABI, there are some regs we don't need to preserve. + // Let's discard them so we don't need to write them back. + // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash + // with this enabled. + for (int i = MIPS_REG_A0; i <= MIPS_REG_T7; i++) + gpr.DiscardRegContentsIfCached((MIPSGPReg)i); + gpr.DiscardRegContentsIfCached(MIPS_REG_T8); + gpr.DiscardRegContentsIfCached(MIPS_REG_T9); + } + FlushAll(); } else