diff options
author | Michael Pavone <pavone@retrodev.com> | 2017-04-24 20:49:31 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2017-04-24 20:49:31 -0700 |
commit | 3f8fd3720d38bded32fdf88ed3824f9c8745a4a7 (patch) | |
tree | a89fd02a712b39a83eee336471a3752f5bb5797f /m68k_core.c | |
parent | 8d362430c6785dcc4b9ed3a7a97acba8ebb15950 (diff) |
Fix interaction between 68K debugger and instruction retranslation due to self modifying code or bank switching
Diffstat (limited to 'm68k_core.c')
-rw-r--r-- | m68k_core.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/m68k_core.c b/m68k_core.c index c5b40c2..a3a3c32 100644 --- a/m68k_core.c +++ b/m68k_core.c @@ -780,6 +780,49 @@ uint16_t m68k_get_ir(m68k_context *context) return 0xFFFF; } +static m68k_debug_handler find_breakpoint(m68k_context *context, uint32_t address) +{ + for (uint32_t i = 0; i < context->num_breakpoints; i++) + { + if (context->breakpoints[i].address == address) { + return context->breakpoints[i].handler; + } + } + return NULL; +} + +void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler) +{ + if (!find_breakpoint(context, address)) { + if (context->bp_storage == context->num_breakpoints) { + context->bp_storage *= 2; + if (context->bp_storage < 4) { + context->bp_storage = 4; + } + context->breakpoints = realloc(context->breakpoints, context->bp_storage * sizeof(m68k_breakpoint)); + } + context->breakpoints[context->num_breakpoints++] = (m68k_breakpoint){ + .handler = bp_handler, + .address = address + }; + m68k_breakpoint_patch(context, address, bp_handler, NULL); + } +} + +m68k_context *m68k_bp_dispatcher(m68k_context *context, uint32_t address) +{ + m68k_debug_handler handler = find_breakpoint(context, address); + if (handler) { + handler(context, address); + } else { + //spurious breakoint? + warning("Spurious breakpoing at %X\n", address); + remove_breakpoint(context, address); + } + + return context; +} + typedef enum { RAW_FUNC = 1, BINARY_ARITH, @@ -895,13 +938,21 @@ static impl_info m68k_impls[] = { RAW_IMPL(M68K_TAS, translate_m68k_tas), }; -static void translate_m68k(m68k_options * opts, m68kinst * inst) +static void translate_m68k(m68k_context *context, m68kinst * inst) { + m68k_options * opts = context->options; if (inst->address & 1) { translate_m68k_odd(opts, inst); return; } + code_ptr start = opts->gen.code.cur; check_cycles_int(&opts->gen, inst->address); + + m68k_debug_handler bp; + if ((bp = find_breakpoint(context, inst->address))) { + m68k_breakpoint_patch(context, inst->address, bp, start); + } + //log_address(&opts->gen, inst->address, "M68K: %X @ %d\n"); if ( (inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE) @@ -981,7 +1032,7 @@ void translate_m68k_stream(uint32_t address, m68k_context * context) //make sure the beginning of the code for an instruction is contiguous check_code_prologue(code); code_ptr start = code->cur; - translate_m68k(opts, &instbuf); + translate_m68k(context, &instbuf); code_ptr after = code->cur; map_native_address(context, instbuf.address, start, m68k_size, after-start); } while(!m68k_is_terminal(&instbuf) && !(address & 1)); @@ -1009,7 +1060,7 @@ void * m68k_retranslate_inst(uint32_t address, m68k_context * context) //make sure we have enough code space for the max size instruction check_alloc_code(code, MAX_NATIVE_SIZE); code_ptr native_start = code->cur; - translate_m68k(opts, &instbuf); + translate_m68k(context, &instbuf); code_ptr native_end = code->cur; /*uint8_t is_terminal = m68k_is_terminal(&instbuf); if ((native_end - native_start) <= orig_size) { @@ -1025,7 +1076,7 @@ void * m68k_retranslate_inst(uint32_t address, m68k_context * context) tmp.last = code->last; code->cur = orig_code.cur; code->last = orig_code.last; - translate_m68k(opts, &instbuf); + translate_m68k(context, &instbuf); native_end = orig_code.cur = code->cur; code->cur = tmp.cur; code->last = tmp.last; @@ -1056,7 +1107,7 @@ void * m68k_retranslate_inst(uint32_t address, m68k_context * context) } else { code_info tmp = *code; *code = orig_code; - translate_m68k(opts, &instbuf); + translate_m68k(context, &instbuf); orig_code = *code; *code = tmp; if (!m68k_is_terminal(&instbuf)) { @@ -1079,7 +1130,20 @@ code_ptr get_native_address_trans(m68k_context * context, uint32_t address) void remove_breakpoint(m68k_context * context, uint32_t address) { + for (uint32_t i = 0; i < context->num_breakpoints; i++) + { + if (context->breakpoints[i].address == address) { + if (i != (context->num_breakpoints-1)) { + context->breakpoints[i] = context->breakpoints[context->num_breakpoints-1]; + } + context->num_breakpoints--; + break; + } + } code_ptr native = get_native_address(context->options, address); + if (!native) { + return; + } code_info tmp = context->options->gen.code; context->options->gen.code.cur = native; context->options->gen.code.last = native + MAX_NATIVE_SIZE; |