Mercurial > repos > blastem
diff debug.c @ 2396:bf4f1a8d1d48
Implement 68K watchpoints in internal debugger
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 23 Dec 2023 17:37:57 -0800 |
parents | ebca8ab02701 |
children | c97609fe8315 |
line wrap: on
line diff
--- a/debug.c Wed Dec 13 20:09:18 2023 -0800 +++ b/debug.c Sat Dec 23 17:37:57 2023 -0800 @@ -380,11 +380,20 @@ bp_def ** find_breakpoint(bp_def ** cur, uint32_t address, uint8_t type) { - while (*cur) { - if ((*cur)->type == type && (*cur)->address == (((*cur)->mask) & address)) { - break; + if (type == BP_TYPE_CPU_WATCH) { + while (*cur) { + if ((*cur)->type == type && address >= (*cur)->address && address < ((*cur)->address + (*cur)->mask)) { + break; + } + cur = &((*cur)->next); } - cur = &((*cur)->next); + } else { + while (*cur) { + if ((*cur)->type == type && (*cur)->address == (((*cur)->mask) & address)) { + break; + } + cur = &((*cur)->next); + } } return cur; } @@ -3114,7 +3123,7 @@ debug_val val; debug_array * arr = NULL; if (cmd->args[1].parsed->type == EXPR_MEM) { - + if (!eval_expr(root, cmd->args[1].parsed->left, &val)) { fprintf(stderr, "Failed to eval start index\n"); goto cleanup; @@ -3277,7 +3286,7 @@ debug_val val; debug_array * arr = NULL; if (cmd->args[1].parsed->type == EXPR_MEM) { - + if (!eval_expr(root, cmd->args[1].parsed->left, &val)) { fprintf(stderr, "Failed to eval start index\n"); goto cleanup; @@ -3440,6 +3449,8 @@ bp_def *tmp = *this_bp; if (tmp->type == BP_TYPE_CPU) { remove_breakpoint(root->cpu_context, tmp->address); + } else if (tmp->type == BP_TYPE_CPU_WATCH) { + m68k_remove_watchpoint(root->cpu_context, tmp->address, tmp->mask); } *this_bp = (*this_bp)->next; if (tmp->commands) { @@ -3472,6 +3483,35 @@ return 1; } +static uint8_t cmd_watchpoint_m68k(debug_root *root, parsed_command *cmd) +{ + uint32_t address; + if (!debug_cast_int(cmd->args[0].value, &address)) { + fprintf(stderr, "First argument to watchpoint must be an integer\n"); + return 1; + } + uint32_t size; + if (cmd->num_args > 1) { + if (!debug_cast_int(cmd->args[1].value, &size)) { + fprintf(stderr, "Second argument to watchpoint must be an integer if provided\n"); + return 1; + } + } else { + //default to byte for odd addresses, word for even + size = (address & 1) ? 1 : 2; + } + m68k_add_watchpoint(root->cpu_context, address, size); + bp_def *new_bp = calloc(1, sizeof(bp_def)); + new_bp->next = root->breakpoints; + new_bp->address = address; + new_bp->mask = size; + new_bp->index = root->bp_index++; + new_bp->type = BP_TYPE_CPU_WATCH; + root->breakpoints = new_bp; + printf("68K Watchpoint %d set for $%X\n", new_bp->index, address); + return 1; +} + static void on_vdp_reg_write(vdp_context *context, uint16_t reg, uint16_t value) { value &= 0xFF; @@ -4102,6 +4142,16 @@ }, { .names = (const char *[]){ + "watchpoint", NULL + }, + .usage = "watchpoint ADDRESS [SIZE]", + .desc = "Set a watchpoint at ADDRESS with an optional SIZE in bytes. SIZE defaults to 2 for even address and 1 for odd", + .impl = cmd_watchpoint_m68k, + .min_args = 1, + .max_args = 2 + }, + { + .names = (const char *[]){ "advance", NULL }, .usage = "advance ADDRESS", @@ -5195,10 +5245,6 @@ init_terminal(); context->options->sync_components(context, 0); - if (context->system == current_system) { - genesis_context *gen = context->system; - vdp_force_update_framebuffer(gen->vdp); - } debug_root *root = find_m68k_root(context); if (!root) { return; @@ -5243,11 +5289,48 @@ if (debugging) { printf("68K Breakpoint %d hit\n", (*this_bp)->index); } else { + fflush(stdout); return; } } else { remove_breakpoint(context, address); } + if (context->wp_hit) { + context->wp_hit = 0; + this_bp = find_breakpoint(&root->breakpoints, context->wp_hit_address, BP_TYPE_CPU_WATCH); + if (*this_bp) { + if ((*this_bp)->condition) { + debug_val condres; + if (eval_expr(root, (*this_bp)->condition, &condres)) { + if (!condres.v.u32) { + 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); + } + if (debugging) { + if (context->wp_old_value != context->wp_hit_value) { + printf("68K Watchpoint %d hit, old value: %X, new value %X\n", (*this_bp)->index, context->wp_old_value, context->wp_hit_value); + } else { + printf("68K Watchpoint %d hit\n", (*this_bp)->index); + } + } else { + fflush(stdout); + return; + } + } + } + if (context->system == current_system) { + genesis_context *gen = context->system; + vdp_force_update_framebuffer(gen->vdp); + } uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); root->after = after; root->inst = &inst;