# HG changeset patch # User Michael Pavone # Date 1660456291 25200 # Node ID 2d7f8195be3bae4157b4c0a25c5a08cd1f43721b # Parent 0c723b8b637cb79bf0d00628df484543d226f872 Add support for conditional breakpoints diff -r 0c723b8b637c -r 2d7f8195be3b debug.c --- a/debug.c Sat Aug 13 20:04:02 2022 -0700 +++ b/debug.c Sat Aug 13 22:51:31 2022 -0700 @@ -1327,6 +1327,27 @@ return 1; } +static uint8_t cmd_condition(debug_root *root, char *format, int num_args, command_arg *args) +{ + if (!eval_expr(root, args[0].parsed, &args[0].value)) { + fprintf(stderr, "Failed to evaluate breakpoint number: %s\n", args[0].raw); + return 1; + } + bp_def **target = find_breakpoint_idx(&root->breakpoints, args[0].value); + if (!*target) { + fprintf(stderr, "Failed to find breakpoint %u\n", args[0].value); + return 1; + } + free_expr((*target)->condition); + if (num_args > 1 && args[1].parsed) { + (*target)->condition = args[1].parsed; + args[1].parsed = NULL; + } else { + (*target)->condition = NULL; + } + return 1; +} + static uint8_t cmd_delete_m68k(debug_root *root, char *format, int num_args, command_arg *args) { bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value); @@ -1736,6 +1757,16 @@ .raw_impl = cmd_binddown, .min_args = 1, .max_args = 1 + }, + { + .names = (const char *[]){ + "condition", NULL + }, + .usage = "condition BREAKPOINT [EXPRESSION]", + .desc = "Makes breakpoint BREAKPOINT conditional on the value of EXPRESSION or removes a condition if EXPRESSION is omitted", + .impl = cmd_condition, + .min_args = 1, + .max_args = 2 } }; #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) @@ -2670,6 +2701,18 @@ //Check if this is a user set breakpoint, or just a temporary one bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); if (*this_bp) { + if ((*this_bp)->condition) { + uint32_t condres; + if (eval_expr(root, (*this_bp)->condition, &condres)) { + if (!condres) { + return context; + } + } else { + fprintf(stderr, "Failed to eval condition for Z80 breakpoint %u\n", (*this_bp)->index); + free_expr((*this_bp)->condition); + (*this_bp)->condition = NULL; + } + } printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); } else { zremove_breakpoint(context, address); @@ -2746,14 +2789,23 @@ root->branch_t = root->branch_f = 0; } - uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); root->address = address; - root->after = after; - root->inst = &inst; int debugging = 1; //Check if this is a user set breakpoint, or just a temporary one bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); if (*this_bp) { + if ((*this_bp)->condition) { + uint32_t condres; + if (eval_expr(root, (*this_bp)->condition, &condres)) { + if (!condres) { + return; + } + } else { + fprintf(stderr, "Failed to eval condition for M68K breakpoint %u\n", (*this_bp)->index); + free_expr((*this_bp)->condition); + (*this_bp)->condition = NULL; + } + } for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++) { debugging = run_command(root, (*this_bp)->commands + i); @@ -2766,6 +2818,9 @@ } else { remove_breakpoint(context, address); } + uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); + root->after = after; + root->inst = &inst; for (disp_def * cur = root->displays; cur; cur = cur->next) { cmd_print(root, cur->format, cur->num_args, cur->args); } diff -r 0c723b8b637c -r 2d7f8195be3b debug.h --- a/debug.h Sat Aug 13 20:04:02 2022 -0700 +++ b/debug.h Sat Aug 13 22:51:31 2022 -0700 @@ -90,6 +90,7 @@ typedef struct bp_def { struct bp_def *next; parsed_command *commands; + expr *condition; uint32_t num_commands; uint32_t address; uint32_t index;