diff --git a/Core/MIPS/ARM/ArmAsm.cpp b/Core/MIPS/ARM/ArmAsm.cpp index 0a8a906af3..6c8ed26180 100644 --- a/Core/MIPS/ARM/ArmAsm.cpp +++ b/Core/MIPS/ARM/ArmAsm.cpp @@ -116,12 +116,14 @@ void Jit::GenerateFixedCode() MOVI2R(R11, (u32)Memory::base); MOVI2R(R10, (u32)mips_); MOVI2R(R9, (u32)GetBasePtr()); - + RestoreDowncount(); MovFromPC(R0); outerLoopPCInR0 = GetCodePtr(); MovToPC(R0); outerLoop = GetCodePtr(); + SaveDowncount(); QuickCallFunction(R0, (void *)&CoreTiming::Advance); + RestoreDowncount(); FixupBranch skipToRealDispatch = B(); //skip the sync and compare first time dispatcherCheckCoreState = GetCodePtr(); @@ -174,7 +176,9 @@ void Jit::GenerateFixedCode() SetCC(CC_AL); //Ok, no block, let's jit + SaveDowncount(); QuickCallFunction(R2, (void *)&JitAt); + RestoreDowncount(); B(dispatcherNoCheck); // no point in special casing this @@ -187,8 +191,8 @@ void Jit::GenerateFixedCode() B_CC(CC_EQ, outerLoop); SetJumpTarget(badCoreState); - breakpointBailout = GetCodePtr(); + SaveDowncount(); ADD(_SP, _SP, 4); diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 0b2bf2b553..65146598aa 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -414,7 +414,9 @@ void Jit::Comp_Syscall(u32 op) js.downcountAmount = -offset; MOVI2R(R0, op); + SaveDowncount(); QuickCallFunction(R1, (void *)&CallSyscall); + RestoreDowncount(); WriteSyscallExit(); js.compiling = false; diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 693372b956..7a842f8f2b 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -56,7 +56,7 @@ void DisassembleArm(const u8 *data, int size) { namespace MIPSComp { -Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips), fpr(mips), mips_(mips) +Jit::Jit(MIPSState *mips) : blocks(mips, this), gpr(mips, &jo), fpr(mips), mips_(mips) { blocks.Init(); gpr.SetEmitter(this); @@ -286,10 +286,12 @@ void Jit::Comp_Generic(u32 op) MIPSInterpretFunc func = MIPSGetInterpretFunc(op); if (func) { + SaveDowncount(); MOVI2R(R0, js.compilerPC); MovToPC(R0); MOVI2R(R0, op); QuickCallFunction(R1, (void *)func); + RestoreDowncount(); } // Might have eaten prefixes, hard to tell... @@ -305,21 +307,45 @@ void Jit::MovToPC(ARMReg r) { STR(r, CTXREG, offsetof(MIPSState, pc)); } +void Jit::SaveDowncount() { + if (jo.downcountInRegister) + STR(R7, CTXREG, offsetof(MIPSState, downcount)); +} + +void Jit::RestoreDowncount() { + if (jo.downcountInRegister) + LDR(R7, CTXREG, offsetof(MIPSState, downcount)); +} + void Jit::WriteDownCount(int offset) { - int theDowncount = js.downcountAmount + offset; - LDR(R1, CTXREG, offsetof(MIPSState, downcount)); - Operand2 op2; - if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations - { - SUBS(R1, R1, op2); - STR(R1, CTXREG, offsetof(MIPSState, downcount)); + if (jo.downcountInRegister) { + int theDowncount = js.downcountAmount + offset; + Operand2 op2; + if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations + { + SUBS(R7, R7, op2); + } else { + // Should be fine to use R2 here, flushed the regcache anyway. + // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway. + MOVI2R(R2, theDowncount); + SUBS(R7, R7, R2); + } } else { - // Should be fine to use R2 here, flushed the regcache anyway. - // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway. - MOVI2R(R2, theDowncount); - SUBS(R1, R1, R2); - STR(R1, CTXREG, offsetof(MIPSState, downcount)); + int theDowncount = js.downcountAmount + offset; + LDR(R1, CTXREG, offsetof(MIPSState, downcount)); + Operand2 op2; + if (TryMakeOperand2(theDowncount, op2)) // We can enlarge this if we used rotations + { + SUBS(R1, R1, op2); + STR(R1, CTXREG, offsetof(MIPSState, downcount)); + } else { + // Should be fine to use R2 here, flushed the regcache anyway. + // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway. + MOVI2R(R2, theDowncount); + SUBS(R1, R1, R2); + STR(R1, CTXREG, offsetof(MIPSState, downcount)); + } } } diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 2bd36823a6..8a61acf1db 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -36,9 +36,11 @@ struct ArmJitOptions ArmJitOptions() { enableBlocklink = true; + downcountInRegister = true; } bool enableBlocklink; + bool downcountInRegister; }; struct ArmJitState @@ -230,6 +232,9 @@ private: void MovFromPC(ARMReg r); void MovToPC(ARMReg r); + void SaveDowncount(); + void RestoreDowncount(); + void WriteExit(u32 destination, int exit_num); void WriteExitDestInR(ARMReg Reg); void WriteSyscallExit(); diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index a153137254..00795433f9 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -17,6 +17,7 @@ #include "ArmRegCache.h" #include "ArmEmitter.h" +#include "ArmJit.h" #if defined(MAEMO) #include "stddef.h" @@ -24,7 +25,7 @@ using namespace ArmGen; -ArmRegCache::ArmRegCache(MIPSState *mips) : mips_(mips) { +ArmRegCache::ArmRegCache(MIPSState *mips, MIPSComp::ArmJitOptions *options) : mips_(mips), options_(options) { } void ArmRegCache::Init(ARMXEmitter *emitter) { @@ -44,18 +45,26 @@ void ArmRegCache::Start(MIPSAnalyst::AnalysisResults &stats) { } } -static const ARMReg *GetMIPSAllocationOrder(int &count) { +const ARMReg *ArmRegCache::GetMIPSAllocationOrder(int &count) { // Note that R0 is reserved as scratch for now. // R1 could be used as it's only used for scratch outside "regalloc space" now. // R12 is also potentially usable. // R4-R7 are registers we could use for static allocation or downcount. // R8 is used to preserve flags in nasty branches. // R9 and upwards are reserved for jit basics. - static const ARMReg allocationOrder[] = { - R2, R3, R4, R5, R6, R7, R12, - }; - count = sizeof(allocationOrder) / sizeof(const int); - return allocationOrder; + if (options_->downcountInRegister) { + static const ARMReg allocationOrder[] = { + R2, R3, R4, R5, R6, R12, + }; + count = sizeof(allocationOrder) / sizeof(const int); + return allocationOrder; + } else { + static const ARMReg allocationOrder2[] = { + R2, R3, R4, R5, R6, R7, R12, + }; + count = sizeof(allocationOrder2) / sizeof(const int); + return allocationOrder2; + } } // TODO: Somewhat smarter spilling - currently simply spills the first available, should do diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h index 3cbe27f4da..1138df726a 100644 --- a/Core/MIPS/ARM/ArmRegCache.h +++ b/Core/MIPS/ARM/ArmRegCache.h @@ -68,10 +68,14 @@ enum { MAP_NOINIT = 2, }; +namespace MIPSComp { + struct ArmJitOptions; +} + class ArmRegCache { public: - ArmRegCache(MIPSState *mips); + ArmRegCache(MIPSState *mips, MIPSComp::ArmJitOptions *options); ~ArmRegCache() {} void Init(ARMXEmitter *emitter); @@ -107,7 +111,10 @@ public: int GetMipsRegOffset(MIPSReg r); private: + const ARMReg *GetMIPSAllocationOrder(int &count); + MIPSState *mips_; + MIPSComp::ArmJitOptions *options_; ARMXEmitter *emit; u32 compilerPC_;