mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 10:09:32 +01:00
Debugger: Fix breakpoints swallowed or reported twice when resuming
The skip-first marker suppressed everything at the address you resume or step from. That's needed for the pause, or you could never get off a breakpoint, but it also dropped the log and hit count. So a log breakpoint you'd stepped onto, or were parked on for some other reason, never logged when execution moved on. Now the skip only drops the pause, unless the breakpoint at that address is the one that stopped us, which has already logged and counted this execution. The check moves into the Exec* functions instead of being repeated in the interpreter, IR interpreter and three JITs, where the register breakpoint path only applied it to the pause and so logged twice when stepping off a log+pause one. The marker gets an explicit valid flag, since address 0 meant "none", and Core_Break() clears it. Based on the earlier cleanup-skip-first branch, reduced to one marker plus a flag. Checked over the WebSocket debugger on the interpreter, IR, x86 JIT and JIT-IR: log breakpoints on a parked and a stepped-onto address each log once, and stepping off a log+pause one doesn't report it again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ab0fa898ae
commit
6a458bf148
7 files changed
+142
-41
No files matched your search
@@ -1297,7 +1297,7 @@ static inline int GetGPRWriteTarget(const MIPSInstruction *instr, MIPSOpcode op)
|
||||
}
|
||||
|
||||
static bool CheckExecBreakpoints(const MIPSState *mips, u32 pc) {
|
||||
if (g_breakpoints.HasBreakPoints() && g_breakpoints.NeedsBreakCheckAt(pc) && g_breakpoints.CheckSkipFirst() != mips->pc) {
|
||||
if (g_breakpoints.HasBreakPoints() && g_breakpoints.NeedsBreakCheckAt(pc)) {
|
||||
g_breakpoints.ExecBreakPoint(pc);
|
||||
// No temp-breakpoint cleanup needed here (the JIT path never had any either) - Core_Break()
|
||||
// drops it for us on the way into stepping, whichever breakpoint it was that stopped us.
|
||||
@@ -1309,7 +1309,7 @@ static bool CheckExecBreakpoints(const MIPSState *mips, u32 pc) {
|
||||
|
||||
// instr must not be null - the callers skip these checks for undecodable opcodes.
|
||||
static bool CheckMemBreakpoints(const MIPSState *mips, const MIPSInstruction *instr, const MIPSOpcode op) {
|
||||
if ((instr->flags & (IN_MEM | OUT_MEM)) != 0 && g_breakpoints.CheckSkipFirst() != mips->pc && instr->interpret != &Int_Syscall) {
|
||||
if ((instr->flags & (IN_MEM | OUT_MEM)) != 0 && instr->interpret != &Int_Syscall) {
|
||||
// This is common for all IN_MEM/OUT_MEM funcs.
|
||||
int offset = (instr->flags & IS_VFPU) != 0 ? SignExtend16ToS32(op & 0xFFFC) : SignExtend16ToS32(op);
|
||||
u32 addr = (mips->r[_RS(op)] + offset) & 0xFFFFFFFC;
|
||||
@@ -1327,7 +1327,7 @@ static bool CheckMemBreakpoints(const MIPSState *mips, const MIPSInstruction *in
|
||||
}
|
||||
|
||||
static bool CheckRegBreakpoints(const MIPSState *mips, const MIPSInstruction *instr, const MIPSOpcode op, u32 regBPMask) {
|
||||
if ((instr->flags & (OUT_RT | OUT_RD | OUT_RA)) != 0 && g_breakpoints.CheckSkipFirst() != mips->pc) {
|
||||
if ((instr->flags & (OUT_RT | OUT_RD | OUT_RA)) != 0) {
|
||||
int regTarget = GetGPRWriteTarget(instr, op);
|
||||
if (regTarget >= 0 && (regBPMask & (1u << regTarget)) != 0) {
|
||||
g_breakpoints.ExecRegBreakpoint(regTarget, mips->pc);
|
||||
|
||||
Reference in new issue
Block a user