Mercurial > repos > blastem
changeset 2676:7e86ec94c899
Implement breakpoints in new 68K core
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 15 Mar 2025 23:15:05 -0700 |
parents | dbff641a33df |
children | 2df04125ac78 |
files | backend.h cpu_dsl.py debug.c debug.h gdb_remote.c gdb_remote.h m68k.cpu m68k_core.c m68k_core.h m68k_core_x86.c m68k_internal.h m68k_util.c |
diffstat | 12 files changed, 85 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/backend.h Fri Mar 14 01:18:11 2025 -0700 +++ b/backend.h Sat Mar 15 23:15:05 2025 -0700 @@ -84,6 +84,12 @@ uint8_t align_error_mask; } cpu_options; +typedef void (*debug_handler)(void *context, uint32_t pc); +typedef struct { + debug_handler handler; + uint32_t address; +} breakpoint; + typedef uint8_t * (*native_addr_func)(void * context, uint32_t address); typedef uint16_t (*interp_read_16)(uint32_t address, void *context, void *data);
--- a/cpu_dsl.py Fri Mar 14 01:18:11 2025 -0700 +++ b/cpu_dsl.py Sat Mar 15 23:15:05 2025 -0700 @@ -2056,6 +2056,8 @@ self.interrupt = info.get('interrupt', [None])[0] self.sync_cycle = info.get('sync_cycle', [None])[0] self.includes = info.get('include', []) + self.pc_reg = info.get('pc_reg', [None])[0] + self.pc_offset = info.get('pc_offset', [0])[0] self.flags = flags self.lastDst = None self.scopes = [] @@ -2088,6 +2090,8 @@ hFile.write('\n#define {0}_'.format(macro)) hFile.write('\n#include <stdio.h>') hFile.write('\n#include "backend.h"') + if self.pc_reg: + hFile.write('\n#include "tern.h"') hFile.write(f'\n\ntypedef struct {self.prefix}options {self.prefix}options;') hFile.write(f'\n\ntypedef struct {self.prefix}context {self.prefix}context;') for decl in self.declares: @@ -2100,6 +2104,8 @@ hFile.write('\n};') hFile.write(f'\n\nstruct {self.prefix}context {{') hFile.write(f'\n\t{self.prefix}options *opts;') + if self.pc_reg: + hFile.write('\n\ttern_node *breakpoints;'); self.regs.writeHeader(otype, hFile) hFile.write('\n};') hFile.write('\n') @@ -2201,6 +2207,36 @@ pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) pieces.append('\n{') pieces.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle)) + if self.pc_reg: + pieces.append('\n\tif (context->breakpoints) {') + pieces.append('\n\t\twhile (context->cycles < target_cycle)') + pieces.append('\n\t\t{') + if self.interrupt in self.subroutines: + pieces.append('\n\t\t\tif (context->cycles >= context->sync_cycle) {') + pieces.append(f'\n\t\t\t\t{self.sync_cycle}(context, target_cycle);') + pieces.append('\n\t\t\t}') + self.meta = {} + self.temp = {} + intpieces = [] + self.subroutines[self.interrupt].inline(self, [], intpieces, otype, None) + for size in self.temp: + pieces.append('\n\t\t\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size)) + pieces += intpieces + if self.pc_offset: + pieces.append(f'\n\t\t\tuint32_t debug_pc = context->{self.pc_reg} - {self.pc_offset};') + pc_reg = 'debug_pc' + else: + pc_reg = 'context->' + self.pc_reg + pieces.append('\n\t\t\tchar key_buf[6];') + pieces.append(f'\n\t\t\tdebug_handler handler = tern_find_ptr(context->breakpoints, tern_int_key({pc_reg}, key_buf));') + pieces.append('\n\t\t\tif (handler) {') + pieces.append(f'\n\t\t\t\thandler(context, {pc_reg});') + pieces.append('\n\t\t\t}') + self.meta = {} + self.temp = {} + self.subroutines[self.body].inline(self, [], pieces, otype, None) + pieces.append('\n\t}') + pieces.append('\n\t} else {') pieces.append('\n\twhile (context->cycles < target_cycle)') pieces.append('\n\t{') if self.interrupt in self.subroutines: @@ -2218,6 +2254,8 @@ self.temp = {} self.subroutines[self.body].inline(self, [], pieces, otype, None) pieces.append('\n\t}') + if self.pc_reg: + pieces.append('\n\t}') pieces.append('\n}') body.append('\nstatic void unimplemented({pre}context *context, uint32_t target_cycle)'.format(pre = self.prefix)) body.append('\n{')
--- a/debug.c Fri Mar 14 01:18:11 2025 -0700 +++ b/debug.c Sat Mar 15 23:15:05 2025 -0700 @@ -5559,11 +5559,12 @@ #endif -void debugger(m68k_context * context, uint32_t address) +void debugger(void *vcontext, uint32_t address) { static char last_cmd[1024]; char input_buf[1024]; m68kinst inst; + m68k_context *context = vcontext; init_terminal(); @@ -5656,11 +5657,9 @@ genesis_context *gen = context->system; vdp_force_update_framebuffer(gen->vdp); } -#ifndef NEW_CORE uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); root->after = after; root->inst = &inst; -#endif for (disp_def * cur = root->displays; cur; cur = cur->next) { char format_str[8]; make_format_str(format_str, cur->format);
--- a/debug.h Fri Mar 14 01:18:11 2025 -0700 +++ b/debug.h Sat Mar 15 23:15:05 2025 -0700 @@ -219,7 +219,7 @@ bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index); void add_display(disp_def ** head, uint32_t *index, char format_char, char * param); void remove_display(disp_def ** head, uint32_t index); -void debugger(m68k_context * context, uint32_t address); +void debugger(void * vcontext, uint32_t address); z80_context * zdebugger(z80_context * context, uint16_t address); void print_m68k_help(); void print_z80_help();
--- a/gdb_remote.c Fri Mar 14 01:18:11 2025 -0700 +++ b/gdb_remote.c Sat Mar 15 23:15:05 2025 -0700 @@ -501,8 +501,9 @@ fatal_error("Command %s is not implemented, exiting...\n", command); } -void gdb_debug_enter(m68k_context * context, uint32_t pc) +void gdb_debug_enter(void *vcontext, uint32_t pc) { + m68k_context *context = vcontext; dfprintf(stderr, "Entered debugger at address %X\n", pc); if (expect_break_response) { if (context->wp_hit) {
--- a/gdb_remote.h Fri Mar 14 01:18:11 2025 -0700 +++ b/gdb_remote.h Sat Mar 15 23:15:05 2025 -0700 @@ -3,6 +3,6 @@ #include "genesis.h" void gdb_remote_init(void); -void gdb_debug_enter(m68k_context * context, uint32_t pc); +void gdb_debug_enter(void *vcontext, uint32_t pc); #endif //GDB_REMOTE_H_
--- a/m68k.cpu Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k.cpu Sat Mar 15 23:15:05 2025 -0700 @@ -6,6 +6,8 @@ interrupt m68k_interrupt include m68k_util.c sync_cycle m68k_sync_cycle + pc_reg pc + pc_offset 2 declare typedef m68k_context *(sync_fun)(m68k_context * context, uint32_t address); @@ -18,6 +20,9 @@ void m68k_serialize(m68k_context *context, uint32_t pc, serialize_buffer *buf); void m68k_deserialize(deserialize_buffer *buf, void *vcontext); void start_68k_context(m68k_context *context, uint32_t pc); + void insert_breakpoint(m68k_context *context, uint32_t address, debug_handler handler); + void remove_breakpoint(m68k_context *context, uint32_t address); + uint16_t m68k_instruction_fetch(uint32_t address, void *vcontext); define NUM_MEM_AREAS 10 define M68K_OPT_BROKEN_READ_MODIFY 1 define INT_PENDING_SR_CHANGE 254 @@ -27,8 +32,6 @@ define m68k_options_free free define m68k_handle_code_write(address, context) define resume_68k(context) m68k_execute(context, context->target_cycle) - define insert_breakpoint(context, address, handler) - define remove_breakpoint(context, address) define m68k_add_watchpoint(context, address, size) define m68k_remove_watchpoint(context, address, size)
--- a/m68k_core.c Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k_core.c Sat Mar 15 23:15:05 2025 -0700 @@ -792,7 +792,7 @@ return 0xFFFF; } -static m68k_debug_handler find_breakpoint(m68k_context *context, uint32_t address) +static debug_handler find_breakpoint(m68k_context *context, uint32_t address) { for (uint32_t i = 0; i < context->num_breakpoints; i++) { @@ -803,7 +803,7 @@ return NULL; } -void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler) +void insert_breakpoint(m68k_context * context, uint32_t address, debug_handler bp_handler) { if (!find_breakpoint(context, address)) { if (context->bp_storage == context->num_breakpoints) { @@ -811,9 +811,9 @@ if (context->bp_storage < 4) { context->bp_storage = 4; } - context->breakpoints = realloc(context->breakpoints, context->bp_storage * sizeof(m68k_breakpoint)); + context->breakpoints = realloc(context->breakpoints, context->bp_storage * sizeof(breakpoint)); } - context->breakpoints[context->num_breakpoints++] = (m68k_breakpoint){ + context->breakpoints[context->num_breakpoints++] = (breakpoint){ .handler = bp_handler, .address = address }; @@ -823,7 +823,7 @@ m68k_context *m68k_bp_dispatcher(m68k_context *context, uint32_t address) { - m68k_debug_handler handler = find_breakpoint(context, address); + debug_handler handler = find_breakpoint(context, address); if (handler) { handler(context, address); } else { @@ -1085,7 +1085,7 @@ code_ptr start = opts->gen.code.cur; check_cycles_int(&opts->gen, inst->address); - m68k_debug_handler bp; + debug_handler bp; if ((bp = find_breakpoint(context, inst->address))) { m68k_breakpoint_patch(context, inst->address, bp, start); }
--- a/m68k_core.h Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k_core.h Sat Mar 15 23:15:05 2025 -0700 @@ -73,13 +73,6 @@ code_word prologue_start; } m68k_options; -typedef void (*m68k_debug_handler)(m68k_context *context, uint32_t pc); - -typedef struct { - m68k_debug_handler handler; - uint32_t address; -} m68k_breakpoint; - typedef struct { uint32_t start; uint32_t end; @@ -112,7 +105,7 @@ void *system; void *host_sp_entry; void *stack_storage[M68K_STACK_STORAGE]; - m68k_breakpoint *breakpoints; + breakpoint *breakpoints; uint32_t num_breakpoints; uint32_t bp_storage; uint32_t watchpoint_min; @@ -141,7 +134,7 @@ m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler); void m68k_reset(m68k_context * context); void m68k_options_free(m68k_options *opts); -void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler); +void insert_breakpoint(m68k_context * context, uint32_t address, debug_handler bp_handler); void remove_breakpoint(m68k_context * context, uint32_t address); void m68k_add_watchpoint(m68k_context *context, uint32_t address, uint32_t size); void m68k_remove_watchpoint(m68k_context *context, uint32_t address, uint32_t size);
--- a/m68k_core_x86.c Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k_core_x86.c Sat Mar 15 23:15:05 2025 -0700 @@ -2563,7 +2563,7 @@ } } -void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr) +void m68k_breakpoint_patch(m68k_context *context, uint32_t address, debug_handler bp_handler, code_ptr native_addr) { m68k_options * opts = context->opts; code_info native;
--- a/m68k_internal.h Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k_internal.h Sat Mar 15 23:15:05 2025 -0700 @@ -35,7 +35,7 @@ void m68k_set_last_prefetch(m68k_options *opts, uint32_t address); void translate_m68k_odd(m68k_options *opts, m68kinst *inst); void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst); -void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr); +void m68k_breakpoint_patch(m68k_context *context, uint32_t address, debug_handler bp_handler, code_ptr native_addr); void m68k_check_cycles_int_latch(m68k_options *opts); uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst);
--- a/m68k_util.c Fri Mar 14 01:18:11 2025 -0700 +++ b/m68k_util.c Sat Mar 15 23:15:05 2025 -0700 @@ -1,4 +1,7 @@ #include <string.h> +#ifdef DEBUG_DISASM +#include "68kinst.h" +#endif void m68k_read_8(m68k_context *context) { @@ -14,14 +17,12 @@ #endif } -#ifdef DEBUG_DISASM -#include "68kinst.h" -static uint16_t debug_disasm_fetch(uint32_t address, void *vcontext) +uint16_t m68k_instruction_fetch(uint32_t address, void *vcontext) { m68k_context *context = vcontext; - return read_word(address, (void**)context->mem_pointers, &context->opts->gen, context); + return read_word(address, (void **)context->mem_pointers, &context->opts->gen, context); } -#endif + void m68k_read_16(m68k_context *context) { context->cycles += 4 * context->opts->gen.clock_divider; @@ -372,3 +373,17 @@ context->prefetch = context->scratch1; context->pc += 2; } + +void insert_breakpoint(m68k_context *context, uint32_t address, debug_handler handler) +{ + char buf[6]; + address &= context->opts->gen.address_mask; + context->breakpoints = tern_insert_ptr(context->breakpoints, tern_int_key(address, buf), handler); +} + +void remove_breakpoint(m68k_context *context, uint32_t address) +{ + char buf[6]; + address &= context->opts->gen.address_mask; + tern_delete(&context->breakpoints, tern_int_key(address, buf), NULL); +}