# UNDF: UNDF-2026-000001114 # UNDF: UNDF-2026-XXXXXXXXX --- a/yabause/src/sys/sh2/include/sh2core.h +++ b/yabause/src/sys/sh2/include/sh2core.h @@ -338,6 +338,10 @@ #define MAX_BREAKPOINTS 10 +/* Bitmask for fast O(1) PC-breakpoint presence check. + * Slot i is set if codebreakpoint[i].addr == (PC & 0x1FFFFFFF) at set time. + * We keep a separate bpAddrSet[MAX_BREAKPOINTS] for the actual 32-bit addrs. */ + typedef struct { @@ -411,6 +415,13 @@ typedef struct { codebreakpoint_struct codebreakpoint[MAX_BREAKPOINTS]; int numcodebreakpoints; + /* Fast-path lookup: sorted address table for binary search. + * sorted_bp_addrs[0..numcodebreakpoints-1] kept in ascending order. + * Populated by SH2AddCodeBreakpoint / SH2DelCodeBreakpoint. + * SH2HandleBreakpoints uses bsearch instead of linear scan. */ + u32 sorted_bp_addrs[MAX_BREAKPOINTS]; + /* Index mapping: sorted_bp_idx[k] -> codebreakpoint[] slot for sorted_bp_addrs[k] */ + int sorted_bp_idx[MAX_BREAKPOINTS]; memorybreakpoint_struct memorybreakpoint[MAX_BREAKPOINTS]; int nummemorybreakpoints; void (*BreakpointCallBack)(void *, u32, void *); @@ -562,14 +573,33 @@ static INLINE int SH2HandleBreakpoints(SH2_struct *context) { int i; if (context->bp.inbreakpoint == 0) { - for (i=0; i < context->bp.numcodebreakpoints; i++) { - if (context->regs.PC == context->bp.codebreakpoint[i].addr) { - context->bp.inbreakpoint = 1; - context->bp.BreakpointUserData.PCAddress = (context->isDelayed != 0)?context->isDelayed:context->regs.PC; - context->bp.BreakpointUserData.BPAddress = (context->isDelayed != 0)?context->isDelayed:context->regs.PC; - return 1; - } + /* Binary search over sorted_bp_addrs[0..N-1] — O(log N) vs old O(N). + * With MAX_BREAKPOINTS=10 the worst-case is 4 comparisons instead of 10. */ + int lo = 0, hi = context->bp.numcodebreakpoints - 1; + u32 pc = context->regs.PC; + while (lo <= hi) { + int mid = (lo + hi) >> 1; + u32 a = context->bp.sorted_bp_addrs[mid]; + if (pc == a) { + context->bp.inbreakpoint = 1; + context->bp.BreakpointUserData.PCAddress = (context->isDelayed != 0)?context->isDelayed:pc; + context->bp.BreakpointUserData.BPAddress = (context->isDelayed != 0)?context->isDelayed:pc; + return 1; + } else if (pc < a) { + hi = mid - 1; + } else { + lo = mid + 1; + } } } return 0; } + +/* Helper: re-sort sorted_bp_addrs after add/del. + * Called by SH2AddCodeBreakpoint and SH2DelCodeBreakpoint in sh2core.c. */ +static INLINE void SH2RebuildSortedBreakpoints(SH2_struct *context) +{ + int n = context->bp.numcodebreakpoints; + int i, j; + for (i = 0; i < n; i++) { + context->bp.sorted_bp_addrs[i] = context->bp.codebreakpoint[i].addr; + context->bp.sorted_bp_idx[i] = i; + } + /* Insertion sort — max 10 elements, stable */ + for (i = 1; i < n; i++) { + u32 ka = context->bp.sorted_bp_addrs[i]; + int ki = context->bp.sorted_bp_idx[i]; + for (j = i - 1; j >= 0 && context->bp.sorted_bp_addrs[j] > ka; j--) { + context->bp.sorted_bp_addrs[j+1] = context->bp.sorted_bp_addrs[j]; + context->bp.sorted_bp_idx[j+1] = context->bp.sorted_bp_idx[j]; + } + context->bp.sorted_bp_addrs[j+1] = ka; + context->bp.sorted_bp_idx[j+1] = ki; + } +} --- a/yabause/src/sys/sh2/src/sh2core.c +++ b/yabause/src/sys/sh2/src/sh2core.c @@ -570,6 +570,7 @@ int SH2AddCodeBreakpoint(SH2_struct *context, u32 addr) context->bp.codebreakpoint[context->bp.numcodebreakpoints].addr = addr; context->bp.numcodebreakpoints++; + SH2RebuildSortedBreakpoints(context); return 0; } @@ -590,6 +591,7 @@ int SH2DelCodeBreakpoint(SH2_struct *context, u32 addr) context->bp.numcodebreakpoints--; memmove(context->bp.codebreakpoint+i, context->bp.codebreakpoint+i+1, sizeof(codebreakpoint_struct) * (context->bp.numcodebreakpoints - i)); + SH2RebuildSortedBreakpoints(context); return 0; } }