# UNDF: UNDF-2026-000001055 # UNDF: UNDF-2026-XXXXXXXXX --- a/Core/debugger.c +++ b/Core/debugger.c @@ -1421,6 +1421,8 @@ static unsigned should_break(GB_gameboy_t *gb, uint16_t addr, bool jump_to) static unsigned should_break(GB_gameboy_t *gb, uint16_t addr, bool jump_to) { if (unlikely(gb->backstep_instructions)) return false; + /* O(1) fast-path: no breakpoint registered at this address */ + if (!gb->breakpoint_address_set[addr]) return 0; uint16_t bank = bank_for_addr(gb, addr); for (unsigned i = 0; i < gb->n_breakpoints; i++) { struct GB_breakpoint_s *breakpoint = &gb->breakpoints[i]; @@ -1093,6 +1093,10 @@ static bool breakpoint(GB_gameboy_t *gb, char *arguments, char *modifiers, const gb->breakpoints[gb->n_breakpoints++] = (struct GB_breakpoint_s){ .id = id, .key = key, .condition = condition? strdup(condition) : NULL, .is_jump_to = is_jump_to, .length = length, .inclusive = inclusive, }; + /* Mark all addresses covered by this breakpoint range in O(1) lookup */ + for (uint32_t a = result.value; a <= (uint32_t)result.value + length + inclusive; a++) { + gb->breakpoint_address_set[(uint16_t)a] = true; + } --- a/Core/gb.h +++ b/Core/gb.h @@ -749,6 +749,8 @@ struct GB_gameboy_internal_s { uint16_t n_breakpoints; struct GB_breakpoint_s *breakpoints; bool has_jump_to_breakpoints, has_software_breakpoints; + /* Boolean lookup table: true if any breakpoint covers this 16-bit address. + Provides O(1) per-instruction bail-out in should_break() hot path. */ + bool breakpoint_address_set[0x10000]; --- a/Core/debugger.c (rebuild helper) +++ b/Core/debugger.c (rebuild helper) +static void rebuild_breakpoint_address_set(GB_gameboy_t *gb) +{ + memset(gb->breakpoint_address_set, 0, sizeof(gb->breakpoint_address_set)); + for (unsigned i = 0; i < gb->n_breakpoints; i++) { + struct GB_breakpoint_s *bp = &gb->breakpoints[i]; + for (uint32_t a = bp->addr; a <= (uint32_t)bp->addr + bp->length + bp->inclusive; a++) { + gb->breakpoint_address_set[(uint16_t)a] = true; + } + } +}