From 9f5be1666313c54ea535343ccddfde2ff641892d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Feb 2026 00:37:45 +0100 Subject: [PATCH 1/2] Jit: Remove the Jal-to-replacement optimization (really not all that benificial) --- Core/HLE/ReplaceTables.cpp | 34 +------------------ Core/HLE/ReplaceTables.h | 2 -- Core/MIPS/ARM/ArmCompBranch.cpp | 3 -- Core/MIPS/ARM/ArmJit.cpp | 52 ----------------------------- Core/MIPS/ARM/ArmJit.h | 2 -- Core/MIPS/ARM64/Arm64CompBranch.cpp | 3 -- Core/MIPS/ARM64/Arm64Jit.cpp | 46 ------------------------- Core/MIPS/ARM64/Arm64Jit.h | 2 -- Core/MIPS/x86/CompBranch.cpp | 7 ---- Core/MIPS/x86/Jit.cpp | 45 ------------------------- Core/MIPS/x86/Jit.h | 1 - 11 files changed, 1 insertion(+), 196 deletions(-) diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index dcc46dbe37..d733822f0b 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -1611,7 +1611,7 @@ static const ReplacementTableEntry entries[] = { { "strncpy", &Replace_strncpy, 0, REPFLAG_DISABLED }, { "strcmp", &Replace_strcmp, 0, REPFLAG_DISABLED }, { "strncmp", &Replace_strncmp, 0, REPFLAG_DISABLED }, - { "fabsf", &Replace_fabsf, JITFUNC(Replace_fabsf), REPFLAG_ALLOWINLINE | REPFLAG_DISABLED }, + { "fabsf", &Replace_fabsf, JITFUNC(Replace_fabsf), REPFLAG_DISABLED }, { "dl_write_matrix", &Replace_dl_write_matrix, 0, REPFLAG_DISABLED }, // &MIPSComp::Jit::Replace_dl_write_matrix, REPFLAG_DISABLED }, { "dl_write_matrix_2", &Replace_dl_write_matrix, 0, REPFLAG_DISABLED }, { "gta_dl_write_matrix", &Replace_gta_dl_write_matrix, 0, REPFLAG_DISABLED }, @@ -1873,35 +1873,3 @@ bool GetReplacedOpAt(u32 address, u32 *op) { } return false; } - -bool CanReplaceJalTo(u32 dest, const ReplacementTableEntry **entry, u32 *funcSize) { - MIPSOpcode op(Memory::Read_Opcode_JIT(dest)); - if (!MIPS_IS_REPLACEMENT(op.encoding)) - return false; - - // Make sure we don't replace if there are any breakpoints inside. - *funcSize = g_symbolMap->GetFunctionSize(dest); - if (*funcSize == SymbolMap::INVALID_ADDRESS) { - if (g_breakpoints.IsAddressBreakPoint(dest)) { - return false; - } - *funcSize = (u32)sizeof(u32); - } else { - if (g_breakpoints.RangeContainsBreakPoint(dest, *funcSize)) { - return false; - } - } - - int index = op.encoding & MIPS_EMUHACK_VALUE_MASK; - *entry = GetReplacementFunc(index); - if (!*entry) { - ERROR_LOG(Log::HLE, "ReplaceJalTo: Invalid replacement op %08x at %08x", op.encoding, dest); - return false; - } - - if ((*entry)->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT | REPFLAG_DISABLED | REPFLAG_SLICED)) { - // If it's a hook, we can't replace the jal, we have to go inside the func. - return false; - } - return true; -} diff --git a/Core/HLE/ReplaceTables.h b/Core/HLE/ReplaceTables.h index 0115ffa9df..33b7cc0ed0 100644 --- a/Core/HLE/ReplaceTables.h +++ b/Core/HLE/ReplaceTables.h @@ -46,7 +46,6 @@ typedef int (* ReplaceFunc)(); enum { - REPFLAG_ALLOWINLINE = 0x01, // Used to keep things around but disable them. REPFLAG_DISABLED = 0x02, // Note that this will re-execute in a function that loops at start. @@ -77,7 +76,6 @@ void WriteReplaceInstructions(u32 address, u64 hash, int size); void RestoreReplacedInstruction(u32 address); void RestoreReplacedInstructions(u32 startAddr, u32 endAddr); bool GetReplacedOpAt(u32 address, u32 *op); -bool CanReplaceJalTo(u32 dest, const ReplacementTableEntry **entry, u32 *funcSize); // For savestates. If you call SaveAndClearReplacements(), you must call RestoreSavedReplacements(). std::map SaveAndClearReplacements(); diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 3bed30a3f7..a9ea2a4ce9 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -543,9 +543,6 @@ void ArmJit::Comp_Jump(MIPSOpcode op) { break; case 3: //jal - if (ReplaceJalTo(targetAddr)) - return; - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 189c3949f1..b2eb7a95de 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -481,58 +481,6 @@ void ArmJit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { } } -bool ArmJit::ReplaceJalTo(u32 dest) { - const ReplacementTableEntry *entry = nullptr; - u32 funcSize = 0; - if (!CanReplaceJalTo(dest, &entry, &funcSize)) { - return false; - } - - // Warning - this might be bad if the code at the destination changes... - if (entry->flags & REPFLAG_ALLOWINLINE) { - // Jackpot! Just do it, no flushing. The code will be entirely inlined. - - // First, compile the delay slot. It's unconditional so no issues. - CompileDelaySlot(DELAYSLOT_NICE); - // Technically, we should write the unused return address to RA, but meh. - MIPSReplaceFunc repl = entry->jitReplaceFunc; - int cycles = (this->*repl)(); - js.downcountAmount += cycles; - } else { - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - FlushAll(); - SaveDowncount(); - RestoreRoundingMode(); - - if (BLInRange((const void *)(entry->replaceFunc))) { - BL((const void *)(entry->replaceFunc)); - } else { - MOVI2R(R0, (uintptr_t)entry->replaceFunc); - BL(R0); - } - ApplyRoundingMode(); - RestoreDowncount(); - - WriteDownCountR(R0); - } - - js.compilerPC += 4; - // No writing exits, keep going! - - if (g_breakpoints.HasMemChecks()) { - // We could modify coreState, so we need to write PC and check. - // Otherwise, PC may end up on the jal. We add 4 to skip the delay slot. - FlushAll(); - WriteExit(GetCompilerPC() + 4, js.nextExit++); - js.compiling = false; - } - - // Add a trigger so that if the inlined code changes, we invalidate this block. - blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr()); - return true; -} - void ArmJit::Comp_ReplacementFunc(MIPSOpcode op) { // We get here if we execute the first instruction of a replaced function. This means diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 292a107d1c..9eb4814a57 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -213,8 +213,6 @@ private: void MovFromPC(ArmGen::ARMReg r); void MovToPC(ArmGen::ARMReg r); - bool ReplaceJalTo(u32 dest); - void SaveDowncount(); void RestoreDowncount(); diff --git a/Core/MIPS/ARM64/Arm64CompBranch.cpp b/Core/MIPS/ARM64/Arm64CompBranch.cpp index efc556f629..89ffbbef15 100644 --- a/Core/MIPS/ARM64/Arm64CompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64CompBranch.cpp @@ -558,9 +558,6 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { break; case 3: //jal - if (ReplaceJalTo(targetAddr)) - return; - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 318de0c074..034bfc3055 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -493,52 +493,6 @@ void Arm64Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { } } -bool Arm64Jit::ReplaceJalTo(u32 dest) { -#if PPSSPP_ARCH(ARM64) - const ReplacementTableEntry *entry = nullptr; - u32 funcSize = 0; - if (!CanReplaceJalTo(dest, &entry, &funcSize)) { - return false; - } - - // Warning - this might be bad if the code at the destination changes... - if (entry->flags & REPFLAG_ALLOWINLINE) { - // Jackpot! Just do it, no flushing. The code will be entirely inlined. - // First, compile the delay slot. It's unconditional so no issues. - CompileDelaySlot(DELAYSLOT_NICE); - // Technically, we should write the unused return address to RA, but meh. - MIPSReplaceFunc repl = entry->jitReplaceFunc; - int cycles = (this->*repl)(); - js.downcountAmount += cycles; - } else { - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - FlushAll(); - SaveStaticRegisters(); - RestoreRoundingMode(); - QuickCallFunction(SCRATCH1_64, (const void *)(entry->replaceFunc)); - ApplyRoundingMode(); - LoadStaticRegisters(); - WriteDownCountR(W0); // W0 is the return value from entry->replaceFunc. Neither LoadStaticRegisters nor ApplyRoundingMode can trash it. - } - - js.compilerPC += 4; - // No writing exits, keep going! - - if (g_breakpoints.HasMemChecks()) { - // We could modify coreState, so we need to write PC and check. - // Otherwise, PC may end up on the jal. We add 4 to skip the delay slot. - FlushAll(); - WriteExit(GetCompilerPC() + 4, js.nextExit++); - js.compiling = false; - } - - // Add a trigger so that if the inlined code changes, we invalidate this block. - blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr()); -#endif - return true; -} - void Arm64Jit::Comp_ReplacementFunc(MIPSOpcode op) { // We get here if we execute the first instruction of a replaced function. This means diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index 15ff701c81..f00e0b9809 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -212,8 +212,6 @@ private: void MovFromPC(Arm64Gen::ARM64Reg r); void MovToPC(Arm64Gen::ARM64Reg r); - bool ReplaceJalTo(u32 dest); - // Clobbers SCRATCH2. void SaveStaticRegisters(); // Clobbers SCRATCH2. diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index a1172fbf9f..c905563801 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -601,13 +601,6 @@ void Jit::Comp_Jump(MIPSOpcode op) { break; case 3: //jal - // Special case for branches to "replace functions": - if (ReplaceJalTo(targetAddr)) - return; - - // Check for small function inlining (future) - - // Save return address - might be overwritten by delay slot. gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 46dd4ec9cd..954716e506 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -538,51 +538,6 @@ void Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { } } -bool Jit::ReplaceJalTo(u32 dest) { - const ReplacementTableEntry *entry = nullptr; - u32 funcSize = 0; - if (!CanReplaceJalTo(dest, &entry, &funcSize)) { - return false; - } - - // Warning - this might be bad if the code at the destination changes... - if (entry->flags & REPFLAG_ALLOWINLINE) { - // Jackpot! Just do it, no flushing. The code will be entirely inlined. - - // First, compile the delay slot. It's unconditional so no issues. - CompileDelaySlot(DELAYSLOT_NICE); - // Technically, we should write the unused return address to RA, but meh. - MIPSReplaceFunc repl = entry->jitReplaceFunc; - int cycles = (this->*repl)(); - js.downcountAmount += cycles; - } else { - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - FlushAll(); - MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC())); - RestoreRoundingMode(); - ABI_CallFunction(entry->replaceFunc); - SUB(32, MIPSSTATE_VAR(downcount), R(EAX)); - ApplyRoundingMode(); - } - - js.compilerPC += 4; - // No writing exits, keep going! - - if (g_breakpoints.HasMemChecks()) { - // We could modify coreState, so we need to write PC and check. - // Otherwise, PC may end up on the jal. We add 4 to skip the delay slot. - MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC() + 4)); - js.afterOp |= JitState::AFTER_CORE_STATE; - } - - // Add a trigger so that if the inlined code changes, we invalidate this block. - blocks.CreateProxyBlock(js.blockStart, dest, funcSize / sizeof(u32), GetCodePtr()); - return true; -} - - - void Jit::Comp_ReplacementFunc(MIPSOpcode op) { // We get here if we execute the first instruction of a replaced function. This means // that we do need to return to RA. diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 87463ad522..11d2040dca 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -187,7 +187,6 @@ private: void FlushAll(); void FlushPrefixV(); void WriteDowncount(int offset = 0); - bool ReplaceJalTo(u32 dest); u32 GetCompilerPC(); // See CompileDelaySlotFlags for flags. From f0ba391a4e9895b4a99c92d60557951c8c30b314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Feb 2026 00:52:58 +0100 Subject: [PATCH 2/2] Remove the whole concept of proxy blocks from the block cache, and experimental uses of it. --- Core/MIPS/ARM/ArmCompBranch.cpp | 66 --------------- Core/MIPS/ARM/ArmJit.cpp | 19 +---- Core/MIPS/ARM/ArmJit.h | 1 - Core/MIPS/ARM64/Arm64CompBranch.cpp | 66 --------------- Core/MIPS/ARM64/Arm64Jit.cpp | 17 +--- Core/MIPS/ARM64/Arm64Jit.h | 1 - Core/MIPS/IR/IRFrontend.cpp | 1 - Core/MIPS/IR/IRJit.cpp | 2 +- Core/MIPS/IR/IRJit.h | 2 +- Core/MIPS/IR/IRNativeCommon.cpp | 4 +- Core/MIPS/IR/IRNativeCommon.h | 2 +- Core/MIPS/JitCommon/JitBlockCache.cpp | 115 ++------------------------ Core/MIPS/JitCommon/JitBlockCache.h | 21 +---- Core/MIPS/JitCommon/JitState.cpp | 4 - Core/MIPS/JitCommon/JitState.h | 4 - Core/MIPS/fake/FakeJit.cpp | 4 - Core/MIPS/fake/FakeJit.h | 1 - Core/MIPS/x86/CompBranch.cpp | 73 ---------------- Core/MIPS/x86/Jit.cpp | 17 +--- Core/MIPS/x86/Jit.h | 17 ---- 20 files changed, 19 insertions(+), 418 deletions(-) diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index a9ea2a4ce9..35fb62d541 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -98,24 +98,6 @@ void ArmJit::BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely) immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) { - if (!immBranchTaken) { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - CompileDelaySlot(DELAYSLOT_NICE); - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -225,29 +207,6 @@ void ArmJit::BranchRSZeroComp(MIPSOpcode op, CCFlags cc, bool andLink, bool like immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) { - if (!immBranchTaken) { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -530,14 +489,6 @@ void ArmJit::Comp_Jump(MIPSOpcode op) { switch (op >> 26) { case 2: //j CompileDelaySlot(DELAYSLOT_NICE); - if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); WriteExit(targetAddr, js.nextExit++); break; @@ -545,14 +496,6 @@ void ArmJit::Comp_Jump(MIPSOpcode op) { case 3: //jal gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); WriteExit(targetAddr, js.nextExit++); break; @@ -606,15 +549,6 @@ void ArmJit::Comp_JumpReg(MIPSOpcode op) gpr.DiscardR(MIPS_REG_T9); } - if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(gpr.GetImm(rs)); - // Account for the increment in the loop. - js.compilerPC = gpr.GetImm(rs) - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - gpr.MapReg(rs); destReg = gpr.R(rs); // Safe because FlushAll doesn't change any regs FlushAll(); diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index b2eb7a95de..262321e034 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -405,24 +405,7 @@ void ArmJit::DoJit(u32 em_address, JitBlock *b) { // Don't forget to zap the newly written instructions in the instruction cache! FlushIcache(); - if (js.lastContinuedPC == 0) - b->originalSize = js.numInstructions; - else - { - // We continued at least once. Add the last proxy and set the originalSize correctly. - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - b->originalSize = js.initialBlockSize; - } -} - -void ArmJit::AddContinuedBlock(u32 dest) -{ - // The first block is the root block. When we continue, we create proxy blocks after that. - if (js.lastContinuedPC == 0) - js.initialBlockSize = js.numInstructions; - else - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - js.lastContinuedPC = dest; + b->originalSize = js.numInstructions; } bool ArmJit::DescribeCodePtr(const u8 *ptr, std::string &name) diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 9eb4814a57..27f8f1ac35 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -202,7 +202,6 @@ private: u32 GetCompilerPC(); void CompileDelaySlot(int flags); void EatInstruction(MIPSOpcode op); - void AddContinuedBlock(u32 dest); MIPSOpcode GetOffsetInstruction(int offset); void WriteDownCount(int offset = 0); diff --git a/Core/MIPS/ARM64/Arm64CompBranch.cpp b/Core/MIPS/ARM64/Arm64CompBranch.cpp index 89ffbbef15..7cd137a2dd 100644 --- a/Core/MIPS/ARM64/Arm64CompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64CompBranch.cpp @@ -98,24 +98,6 @@ void Arm64Jit::BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely) immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) { - if (!immBranchTaken) { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - CompileDelaySlot(DELAYSLOT_NICE); - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -242,29 +224,6 @@ void Arm64Jit::BranchRSZeroComp(MIPSOpcode op, CCFlags cc, bool andLink, bool li immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) { - if (!immBranchTaken) { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -545,14 +504,6 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { switch (op >> 26) { case 2: //j CompileDelaySlot(DELAYSLOT_NICE); - if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); WriteExit(targetAddr, js.nextExit++); break; @@ -560,14 +511,6 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { case 3: //jal gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (jo.continueJumps && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); WriteExit(targetAddr, js.nextExit++); break; @@ -621,15 +564,6 @@ void Arm64Jit::Comp_JumpReg(MIPSOpcode op) gpr.DiscardR(MIPS_REG_T9); } - if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) { - AddContinuedBlock(gpr.GetImm(rs)); - // Account for the increment in the loop. - js.compilerPC = gpr.GetImm(rs) - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - gpr.MapReg(rs); destReg = gpr.R(rs); // Safe because FlushAll doesn't change any regs FlushAll(); diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 034bfc3055..59ffbb975c 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -394,22 +394,7 @@ void Arm64Jit::DoJit(u32 em_address, JitBlock *b) { if (dontLogBlocks > 0) dontLogBlocks--; - if (js.lastContinuedPC == 0) { - b->originalSize = js.numInstructions; - } else { - // We continued at least once. Add the last proxy and set the originalSize correctly. - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - b->originalSize = js.initialBlockSize; - } -} - -void Arm64Jit::AddContinuedBlock(u32 dest) { - // The first block is the root block. When we continue, we create proxy blocks after that. - if (js.lastContinuedPC == 0) - js.initialBlockSize = js.numInstructions; - else - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - js.lastContinuedPC = dest; + b->originalSize = js.numInstructions; } bool Arm64Jit::DescribeCodePtr(const u8 *ptr, std::string &name) { diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index f00e0b9809..3edc9db85c 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -201,7 +201,6 @@ private: u32 GetCompilerPC(); void CompileDelaySlot(int flags); void EatInstruction(MIPSOpcode op); - void AddContinuedBlock(u32 dest); MIPSOpcode GetOffsetInstruction(int offset); void WriteDownCount(int offset = 0, bool updateFlags = true); diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index 69072fe5e3..38337623f6 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -243,7 +243,6 @@ void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &m js.cancel = false; js.blockStart = em_address; js.compilerPC = em_address; - js.lastContinuedPC = 0; js.initialBlockSize = 0; js.nextExit = 0; js.downcountAmount = 0; diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 94f85dcb83..f495d4fd64 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -511,7 +511,7 @@ void IRBlockCache::ComputeStats(BlockCacheStats &bcStats) const { bcStats.avgBloat = totalBloat / (double)blocks_.size(); } -int IRBlockCache::GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly) const { +int IRBlockCache::GetBlockNumberFromStartAddress(u32 em_address) const { u32 page = AddressToPage(em_address); const auto iter = byPage_.find(page); diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index cf87552717..c9b6cb9b59 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -185,7 +185,7 @@ public: #endif } void ComputeStats(BlockCacheStats &bcStats) const override; - int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override; + int GetBlockNumberFromStartAddress(u32 em_address) const override; bool SupportsProfiling() const override { #ifdef IR_PROFILING diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index 60d4472734..5ff1d94855 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -719,8 +719,8 @@ int IRNativeBlockCacheDebugInterface::GetNumBlocks() const { return irBlocks_.GetNumBlocks(); } -int IRNativeBlockCacheDebugInterface::GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly) const { - return irBlocks_.GetBlockNumberFromStartAddress(em_address, realBlocksOnly); +int IRNativeBlockCacheDebugInterface::GetBlockNumberFromStartAddress(u32 em_address) const { + return irBlocks_.GetBlockNumberFromStartAddress(em_address); } JitBlockProfileStats IRNativeBlockCacheDebugInterface::GetBlockProfileStats(int blockNum) const { diff --git a/Core/MIPS/IR/IRNativeCommon.h b/Core/MIPS/IR/IRNativeCommon.h index a432fa1a1d..f4a9352e36 100644 --- a/Core/MIPS/IR/IRNativeCommon.h +++ b/Core/MIPS/IR/IRNativeCommon.h @@ -163,7 +163,7 @@ public: IRNativeBlockCacheDebugInterface(const MIPSComp::IRBlockCache &irBlocks); void Init(const IRNativeBackend *backend); int GetNumBlocks() const override; - int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override; + int GetBlockNumberFromStartAddress(u32 em_address) const override; JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override; JitBlockMeta GetBlockMeta(int blockNum) const override; JitBlockProfileStats GetBlockProfileStats(int blockNum) const override; diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 4a08353d2a..233b423331 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -77,8 +77,8 @@ JitBlockCache::~JitBlockCache() { } bool JitBlockCache::IsFull() const { - // Subtract some amount to safely leave space for some proxy blocks, which we don't check before we allocate (not ideal, but should be enough). - return num_blocks_ >= MAX_NUM_BLOCKS - 512; + // Subtract some amount to safely leave space for some proxy blocks (now obsolete, but let's still have some extra margin). + return num_blocks_ >= MAX_NUM_BLOCKS - 64; } void JitBlockCache::Init() { @@ -101,7 +101,6 @@ void JitBlockCache::Clear() { for (int i = 0; i < num_blocks_; i++) { DestroyBlock(i, DestroyType::CLEAR); } - proxyBlockMap_.clear(); links_to_.clear(); num_blocks_ = 0; @@ -120,22 +119,6 @@ int JitBlockCache::AllocateBlock(u32 startAddress) { JitBlock &b = blocks_[num_blocks_]; - b.proxyFor = 0; - // If there's an existing pure proxy block at the address, we need to ditch it and create a new one, - // taking over the proxied blocks. - int num = GetBlockNumberFromStartAddress(startAddress, false); - if (num >= 0) { - if (blocks_[num].IsPureProxy()) { - RemoveBlockMap(num); - blocks_[num].invalid = true; - b.proxyFor = new std::vector(); - *b.proxyFor = *blocks_[num].proxyFor; - blocks_[num].proxyFor->clear(); - delete blocks_[num].proxyFor; - blocks_[num].proxyFor = 0; - } - } - b.invalid = false; b.originalAddress = startAddress; for (int i = 0; i < MAX_JIT_BLOCK_EXITS; ++i) { @@ -149,43 +132,6 @@ int JitBlockCache::AllocateBlock(u32 startAddress) { return num_blocks_ - 1; } -void JitBlockCache::CreateProxyBlock(u32 rootAddress, u32 startAddress, u32 size, const u8 *codePtr) { - _assert_(num_blocks_ < MAX_NUM_BLOCKS); - - // If there's an existing block at the startAddress, add rootAddress as a proxy root of that block - // instead of creating a new block. - int num = GetBlockNumberFromStartAddress(startAddress, false); - if (num != -1) { - DEBUG_LOG(Log::HLE, "Adding proxy root %08x to block at %08x", rootAddress, startAddress); - if (!blocks_[num].proxyFor) { - blocks_[num].proxyFor = new std::vector(); - } - blocks_[num].proxyFor->push_back(rootAddress); - } - - JitBlock &b = blocks_[num_blocks_]; - b.invalid = false; - b.originalAddress = startAddress; - b.originalSize = size; - for (int i = 0; i < MAX_JIT_BLOCK_EXITS; ++i) { - b.exitAddress[i] = INVALID_EXIT; - b.exitPtrs[i] = 0; - b.linkStatus[i] = false; - } - b.exitAddress[0] = rootAddress; - b.blockNum = num_blocks_; - b.proxyFor = new std::vector(); - b.SetPureProxy(); // flag as pure proxy block. - - // Make binary searches and stuff work ok - b.normalEntry = codePtr; - b.checkedEntry = codePtr; - proxyBlockMap_.emplace(startAddress, num_blocks_); - AddBlockMap(num_blocks_); - - num_blocks_++; //commit the current block -} - void JitBlockCache::AddBlockMap(int block_num) { const JitBlock &b = blocks_[block_num]; // Convert the logical address to a physical address for the block map @@ -223,7 +169,7 @@ static void ExpandRange(std::pair &range, u32 newStart, u32 newEnd) { void JitBlockCache::FinalizeBlock(int block_num, bool block_link) { JitBlock &b = blocks_[block_num]; - _assert_msg_(Memory::IsValidAddress(b.originalAddress), "FinalizeBlock: Bad originalAddress %08x in block %d (b.num: %d) proxy: %s sz: %d", b.originalAddress, block_num, b.blockNum, b.proxyFor ? "y" : "n", b.codeSize); + _assert_msg_(Memory::IsValidAddress(b.originalAddress), "FinalizeBlock: Bad originalAddress %08x in block %d (b.num: %d) sz: %d", b.originalAddress, block_num, b.blockNum, b.codeSize); b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); MIPSOpcode opcode = GetEmuHackOpForBlock(block_num); @@ -307,22 +253,13 @@ MIPSOpcode JitBlockCache::GetEmuHackOpForBlock(int blockNum) const { return MIPSOpcode(MIPS_EMUHACK_OPCODE | off); } -int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr, bool realBlocksOnly) const { +int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr) const { if (!blocks_ || !Memory::IsValidAddress(addr)) return -1; MIPSOpcode inst = MIPSOpcode(Memory::Read_U32(addr)); int bl = GetBlockNumberFromEmuHackOp(inst); if (bl < 0) { - if (!realBlocksOnly) { - // Wasn't an emu hack op, look through proxyBlockMap_. - auto range = proxyBlockMap_.equal_range(addr); - for (auto it = range.first; it != range.second; ++it) { - const int blockIndex = it->second; - if (blocks_[blockIndex].originalAddress == addr && !blocks_[blockIndex].proxyFor && !blocks_[blockIndex].invalid) - return blockIndex; - } - } return -1; } @@ -374,14 +311,10 @@ void JitBlockCache::LinkBlockExits(int i) { // This block is dead. Don't relink it. return; } - if (b.IsPureProxy()) { - // Pure proxies can't link, since they don't have code. - return; - } for (int e = 0; e < MAX_JIT_BLOCK_EXITS; e++) { if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e]) { - int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e], true); + int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); if (destinationBlock == -1) { continue; } @@ -477,32 +410,6 @@ void JitBlockCache::DestroyBlock(int block_num, DestroyType type) { // No point it being in there anymore. RemoveBlockMap(block_num); - // Pure proxy blocks always point directly to a real block, there should be no chains of - // proxy-only blocks pointing to proxy-only blocks. - // Follow a block proxy chain. - // Destroy the block that transitively has this as a proxy. Likely the root block once inlined - // this block or its 'parent', so now that this block has changed, the root block must be destroyed. - if (b->proxyFor) { - for (size_t i = 0; i < b->proxyFor->size(); i++) { - int proxied_blocknum = GetBlockNumberFromStartAddress((*b->proxyFor)[i], false); - // If it was already cleared, we don't know which to destroy. - if (proxied_blocknum != -1) { - DestroyBlock(proxied_blocknum, type); - } - } - b->proxyFor->clear(); - delete b->proxyFor; - b->proxyFor = 0; - } - auto range = proxyBlockMap_.equal_range(b->originalAddress); - for (auto it = range.first; it != range.second; ++it) { - if (it->second == block_num) { - // Found it. Delete and bail. - proxyBlockMap_.erase(it); - break; - } - } - // TODO: Handle the case when there's a proxy block and a regular JIT block at the same location. // In this case we probably "leak" the proxy block currently (no memory leak but it'll stay enabled). @@ -513,9 +420,8 @@ void JitBlockCache::DestroyBlock(int block_num, DestroyType type) { } b->invalid = true; - if (!b->IsPureProxy()) { - if (Memory::ReadUnchecked_U32(b->originalAddress) == GetEmuHackOpForBlock(block_num).encoding) - Memory::Write_Opcode_JIT(b->originalAddress, b->originalFirstOpcode); + if (Memory::ReadUnchecked_U32(b->originalAddress) == GetEmuHackOpForBlock(block_num).encoding) { + Memory::Write_Opcode_JIT(b->originalAddress, b->originalFirstOpcode); } // It's not safe to set normalEntry to 0 here, since we use a binary search @@ -523,11 +429,6 @@ void JitBlockCache::DestroyBlock(int block_num, DestroyType type) { UnlinkBlock(block_num); - // Don't change the jit code when invalidating a pure proxy block. - if (b->IsPureProxy()) { - return; - } - if (b->checkedEntry) { // We can skip this if we're clearing anyway, which cuts down on protect back and forth on WX exclusive. if (type != DestroyType::CLEAR) { @@ -579,7 +480,7 @@ void JitBlockCache::InvalidateChangedBlocks() { // The primary goal of this is to make sure block linking is cleared up. for (int block_num = 0; block_num < num_blocks_; ++block_num) { JitBlock &b = blocks_[block_num]; - if (b.invalid || b.IsPureProxy()) + if (b.invalid) continue; bool changed = false; diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index b461e2a362..a29095bae9 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -76,18 +76,6 @@ struct JitBlock { bool invalid; bool linkStatus[MAX_JIT_BLOCK_EXITS]; - - // By having a pointer, we avoid a constructor/destructor call being generated if unused, - // thus avoiding dog slow performance in debug build. - std::vector *proxyFor; - - bool IsPureProxy() const { - return originalFirstOpcode.encoding == 0x68FF0000; - } - void SetPureProxy() { - // Magic number that won't be a real opcode. - originalFirstOpcode.encoding = 0x68FF0000; - } }; typedef void (*CompiledCode)(); @@ -114,7 +102,7 @@ struct JitBlockMeta { class JitBlockCacheDebugInterface { public: virtual int GetNumBlocks() const = 0; - virtual int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const = 0; + virtual int GetBlockNumberFromStartAddress(u32 em_address) const = 0; virtual JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const = 0; // Expensive virtual JitBlockMeta GetBlockMeta(int blockNum) const = 0; virtual JitBlockProfileStats GetBlockProfileStats(int blockNum) const = 0; @@ -131,8 +119,6 @@ public: ~JitBlockCache(); int AllocateBlock(u32 em_address); - // When a proxy block is invalidated, the block located at the rootAddress is invalidated too. - void CreateProxyBlock(u32 rootAddress, u32 startAddress, u32 size, const u8 *codePtr); void FinalizeBlock(int block_num, bool block_link); void Clear(); @@ -148,7 +134,7 @@ public: const JitBlock *GetBlock(int no) const { return &blocks_[no]; } // Fast way to get a block. Only works on the first source-cpu instruction of a block. - int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override; + int GetBlockNumberFromStartAddress(u32 em_address) const override; // slower, but can get numbers from within blocks, not just the first instruction. // WARNING! WILL NOT WORK WITH JIT INLINING ENABLED (not yet a feature but will be soon) @@ -210,7 +196,6 @@ private: CodeBlockCommon *codeBlock_; JitBlock *blocks_ = nullptr; - std::unordered_multimap proxyBlockMap_; int num_blocks_ = 0; std::unordered_multimap links_to_; @@ -222,7 +207,7 @@ private: JITBLOCK_RANGE_RAMTOP = 2, JITBLOCK_RANGE_COUNT = 3, }; - std::pair blockMemRanges_[3]; + std::pair blockMemRanges_[JITBLOCK_RANGE_COUNT]; enum { // Where does this number come from? diff --git a/Core/MIPS/JitCommon/JitState.cpp b/Core/MIPS/JitCommon/JitState.cpp index a33628ae6e..d4b3f7ea60 100644 --- a/Core/MIPS/JitCommon/JitState.cpp +++ b/Core/MIPS/JitCommon/JitState.cpp @@ -28,7 +28,6 @@ void JitState::Begin(JitBlock *block) { cancel = false; blockStart = block->originalAddress; compilerPC = block->originalAddress; - lastContinuedPC = 0; initialBlockSize = 0; nextExit = 0; downcountAmount = 0; @@ -65,9 +64,6 @@ void JitState::Begin(JitBlock *block) { #else enableBlocklink = !Disabled(JitDisable::BLOCKLINK); #endif - immBranches = false; - continueJumps = false; - continueMaxInstructions = 300; useStaticAlloc = false; enablePointerify = false; diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index 5d8893cccb..d450eed570 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -54,7 +54,6 @@ namespace MIPSComp { u32 compilerPC; u32 blockStart; - u32 lastContinuedPC; u32 initialBlockSize; int nextExit; bool cancel; @@ -240,8 +239,5 @@ namespace MIPSComp { // Common bool enableBlocklink; - bool immBranches; - bool continueJumps; - int continueMaxInstructions; }; } diff --git a/Core/MIPS/fake/FakeJit.cpp b/Core/MIPS/fake/FakeJit.cpp index 82011bb55e..a9df164c23 100644 --- a/Core/MIPS/fake/FakeJit.cpp +++ b/Core/MIPS/fake/FakeJit.cpp @@ -136,10 +136,6 @@ void FakeJit::DoJit(u32 em_address, JitBlock *b) { _assert_(false); } -void FakeJit::AddContinuedBlock(u32 dest) -{ -} - bool FakeJit::DescribeCodePtr(const u8 *ptr, std::string &name) { // TODO: Not used by anything yet. diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h index 1b88fb37d3..bab59c000f 100644 --- a/Core/MIPS/fake/FakeJit.h +++ b/Core/MIPS/fake/FakeJit.h @@ -53,7 +53,6 @@ public: void CompileDelaySlot(int flags); void EatInstruction(MIPSOpcode op); - void AddContinuedBlock(u32 dest); void Comp_RunBlock(MIPSOpcode op) override; void Comp_ReplacementFunc(MIPSOpcode op) override; diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index c905563801..138b11147f 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -299,26 +299,6 @@ void Jit::BranchRSRTComp(MIPSOpcode op, Gen::CCFlags cc, bool likely) immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) - { - if (!immBranchTaken) - { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - CompileDelaySlot(DELAYSLOT_NICE); - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -379,31 +359,6 @@ void Jit::BranchRSZeroComp(MIPSOpcode op, Gen::CCFlags cc, bool andLink, bool li immBranchTaken = !immBranchNotTaken; } - if (jo.immBranches && immBranch && js.numInstructions < jo.continueMaxInstructions) - { - if (!immBranchTaken) - { - // Skip the delay slot if likely, otherwise it'll be the next instruction. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - if (likely) - js.compilerPC += 4; - return; - } - - // Branch taken. Always compile the delay slot, and then go to dest. - if (andLink) - gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); - CompileDelaySlot(DELAYSLOT_NICE); - - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - js.downcountAmount += MIPSGetInstructionCycleEstimate(branchInfo.delaySlotOp); u32 notTakenTarget = ResolveNotTakenTarget(branchInfo); @@ -586,15 +541,6 @@ void Jit::Comp_Jump(MIPSOpcode op) { switch (op >> 26) { case 2: //j CompileDelaySlot(DELAYSLOT_NICE); - if (CanContinueJump(targetAddr)) - { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); CONDITIONAL_LOG_EXIT(targetAddr); WriteExit(targetAddr, js.nextExit++); @@ -604,15 +550,6 @@ void Jit::Comp_Jump(MIPSOpcode op) { // Save return address - might be overwritten by delay slot. gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (CanContinueJump(targetAddr)) - { - AddContinuedBlock(targetAddr); - // Account for the increment in the loop. - js.compilerPC = targetAddr - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } FlushAll(); CONDITIONAL_LOG_EXIT(targetAddr); WriteExit(targetAddr, js.nextExit++); @@ -675,16 +612,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) gpr.DiscardRegContentsIfCached(MIPS_REG_T9); } - if (gpr.IsImm(rs) && CanContinueJump(gpr.GetImm(rs))) - { - AddContinuedBlock(gpr.GetImm(rs)); - // Account for the increment in the loop. - js.compilerPC = gpr.GetImm(rs) - 4; - // In case the delay slot was a break or something. - js.compiling = true; - return; - } - if (gpr.R(rs).IsSimpleReg()) { destReg = gpr.R(rs).GetSimpleReg(); } else { diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 954716e506..276b966cdc 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -429,22 +429,7 @@ void Jit::DoJit(u32 em_address, JitBlock *b) { NOP(); AlignCode4(); - if (js.lastContinuedPC == 0) { - b->originalSize = js.numInstructions; - } else { - // We continued at least once. Add the last proxy and set the originalSize correctly. - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - b->originalSize = js.initialBlockSize; - } -} - -void Jit::AddContinuedBlock(u32 dest) { - // The first block is the root block. When we continue, we create proxy blocks after that. - if (js.lastContinuedPC == 0) - js.initialBlockSize = js.numInstructions; - else - blocks.CreateProxyBlock(js.blockStart, js.lastContinuedPC, (GetCompilerPC() - js.lastContinuedPC) / sizeof(u32), GetCodePtr()); - js.lastContinuedPC = dest; + b->originalSize = js.numInstructions; } bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) { diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 11d2040dca..55b1ca8bb9 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -195,7 +195,6 @@ private: CompileDelaySlot(flags, &state); } void EatInstruction(MIPSOpcode op); - void AddContinuedBlock(u32 dest); MIPSOpcode GetOffsetInstruction(int offset); void WriteExit(u32 destination, int exit_num); @@ -267,22 +266,6 @@ private: } bool PredictTakeBranch(u32 targetAddr, bool likely); - bool CanContinueJump(u32 targetAddr) { - if (!jo.continueJumps || js.numInstructions >= jo.continueMaxInstructions) { - return false; - } - if (!targetAddr) { - return false; - } - return true; - } - bool CanContinueImmBranch(u32 targetAddr) { - if (!jo.immBranches || js.numInstructions >= jo.continueMaxInstructions) { - return false; - } - return true; - } - bool IsAtDispatchFetch(const u8 *codePtr) const override { return codePtr == dispatcherFetch; }