From 259734bd471c3417a5f248874e047ac091eafbfb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Sep 2023 22:52:16 -0700 Subject: [PATCH] irjit: Fix likely delay slot breakpoints. --- Core/Debugger/Breakpoints.cpp | 2 +- Core/MIPS/IR/IRFrontend.cpp | 44 ++++++++++++++++++++++++---------- Core/MIPS/IR/IRInterpreter.cpp | 2 +- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 3189acf76c34..b02b35c7ade1 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -311,7 +311,7 @@ BreakAction CBreakPoints::ExecBreakPoint(u32 addr) { std::unique_lock guard(breakPointsMutex_); size_t bp = FindBreakpoint(addr, false); if (bp != INVALID_BREAKPOINT) { - BreakPoint info = breakPoints_[bp]; + const BreakPoint &info = breakPoints_[bp]; guard.unlock(); if (info.hasCond) { diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index 38d54eb4970c..8243ac7b671e 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -340,13 +340,24 @@ void IRFrontend::CheckBreakpoint(u32 addr) { if (CBreakPoints::IsAddressBreakPoint(addr)) { FlushAll(); + if (GetCompilerPC() != js.blockStart) + ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); + RestoreRoundingMode(); - ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); - // 0 because we normally execute before increasing. - // TODO: In likely branches, downcount will be incorrect. - int downcountOffset = js.inDelaySlot && js.downcountAmount >= 2 ? -2 : 0; + // At this point, downcount HAS the delay slot, but not the instruction itself. + int downcountOffset = 0; + if (js.inDelaySlot) { + MIPSOpcode branchOp = Memory::Read_Opcode_JIT(GetCompilerPC()); + MIPSOpcode delayOp = Memory::Read_Opcode_JIT(addr); + downcountOffset = -MIPSGetInstructionCycleEstimate(delayOp); + if ((MIPSGetInfo(branchOp) & LIKELY) != 0) { + // Okay, we're in a likely branch. Also negate the branch cycles. + downcountOffset += -MIPSGetInstructionCycleEstimate(branchOp); + } + } int downcountAmount = js.downcountAmount + downcountOffset; - ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); + if (downcountAmount != 0) + ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); // Note that this means downcount can't be metadata on the block. js.downcountAmount = -downcountOffset; ir.Write(IROp::Breakpoint, 0, ir.AddConstant(addr)); @@ -360,16 +371,25 @@ void IRFrontend::CheckMemoryBreakpoint(int rs, int offset) { if (CBreakPoints::HasMemChecks()) { FlushAll(); + if (GetCompilerPC() != js.blockStart) + ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); + RestoreRoundingMode(); - ir.Write(IROp::SetPCConst, 0, ir.AddConstant(GetCompilerPC())); - // 0 because we normally execute before increasing. - int downcountOffset = js.inDelaySlot ? -2 : -1; - // TODO: In likely branches, downcount will be incorrect. This might make resume fail. - if (js.downcountAmount == 0) { - downcountOffset = 0; + // At this point, downcount HAS the delay slot, but not the instruction itself. + int downcountOffset = 0; + if (js.inDelaySlot) { + // We assume delay slot in compilerPC + 4. + MIPSOpcode branchOp = Memory::Read_Opcode_JIT(GetCompilerPC()); + MIPSOpcode delayOp = Memory::Read_Opcode_JIT(GetCompilerPC() + 4); + downcountOffset = -MIPSGetInstructionCycleEstimate(delayOp); + if ((MIPSGetInfo(branchOp) & LIKELY) != 0) { + // Okay, we're in a likely branch. Also negate the branch cycles. + downcountOffset += -MIPSGetInstructionCycleEstimate(branchOp); + } } int downcountAmount = js.downcountAmount + downcountOffset; - ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); + if (downcountAmount != 0) + ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount)); // Note that this means downcount can't be metadata on the block. js.downcountAmount = -downcountOffset; ir.Write(IROp::MemoryCheck, js.inDelaySlot ? 4 : 0, rs, ir.AddConstant(offset)); diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index 01c6f05d42bf..8fa713d80929 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -1053,7 +1053,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { break; case IROp::Downcount: - mips->downcount -= inst->constant; + mips->downcount -= (int)inst->constant; break; case IROp::SetPC: