From 4afb917f03758c286ca85ad9a45be13e852b6a84 Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Sat, 8 Feb 2014 23:37:09 -0800 Subject: Initial GDB remote debugging support. Lacks some features, but breakpoints and basic inspection of registers and memory work. --- blastem.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index e50c79b..8e8f785 100644 --- a/blastem.c +++ b/blastem.c @@ -10,6 +10,7 @@ #include "vdp.h" #include "render.h" #include "blastem.h" +#include "gdb_remote.h" #include "gst.h" #include "util.h" #include @@ -1585,7 +1586,7 @@ void save_sram() printf("Saved SRAM to %s\n", sram_filename); } -void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * statefile) +void init_run_cpu(genesis_context * gen, FILE * address_log, char * statefile, uint8_t * debugger) { m68k_context context; x86_68k_options opts; @@ -1706,15 +1707,15 @@ void init_run_cpu(genesis_context * gen, int debug, FILE * address_log, char * s exit(1); } printf("Loaded %s\n", statefile); - if (debug) { - insert_breakpoint(&context, pc, (uint8_t *)debugger); + if (debugger) { + insert_breakpoint(&context, pc, debugger); } adjust_int_cycle(gen->m68k, gen->vdp); gen->z80->native_pc = z80_get_native_address_trans(gen->z80, gen->z80->pc); start_68k_context(&context, pc); } else { - if (debug) { - insert_breakpoint(&context, address, (uint8_t *)debugger); + if (debugger) { + insert_breakpoint(&context, address, debugger); } m68k_reset(&context); } @@ -1808,6 +1809,7 @@ int main(int argc, char ** argv) char * romfname = NULL; FILE *address_log = NULL; char * statefile = NULL; + uint8_t * debuggerfun = NULL; uint8_t fullscreen = 0, use_gl = 1; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { @@ -1822,7 +1824,11 @@ int main(int argc, char ** argv) exit_after = atoi(argv[i]); break; case 'd': - debug = 1; + debuggerfun = (uint8_t *)debugger; + break; + case 'D': + gdb_remote_init(); + debuggerfun = (uint8_t *)gdb_debug_enter; break; case 'f': fullscreen = 1; @@ -1980,6 +1986,6 @@ int main(int argc, char ** argv) } set_keybindings(); - init_run_cpu(&gen, debug, address_log, statefile); + init_run_cpu(&gen, address_log, statefile, debuggerfun); return 0; } -- cgit v1.2.3 From 8ba7f3897a02057091e8850b9b44de7f30062bac Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Sun, 9 Feb 2014 00:42:43 -0800 Subject: Properly handle jmp instructions in the debugger next command --- blastem.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 8e8f785..0d173fc 100644 --- a/blastem.c +++ b/blastem.c @@ -1465,7 +1465,7 @@ m68k_context * debugger(m68k_context * context, uint32_t address) printf(format, param, value); break; case 'n': - //TODO: Deal with jmp, dbcc, rtr and rte + //TODO: Deal with dbcc, rtr and rte if (inst.op == M68K_RTS) { after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) { @@ -1476,6 +1476,56 @@ m68k_context * debugger(m68k_context * context, uint32_t address) branch_t = inst.address + 2 + inst.src.params.immed; insert_breakpoint(context, branch_t, (uint8_t *)debugger); } + } else if(inst.op == M68K_JMP) { + switch(inst.src.addr_mode) + { + case MODE_AREG_INDIRECT: + after = context->aregs[inst.src.params.regs.pri]; + break; + case MODE_AREG_INDEX_DISP8: { + uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7; + after = context->aregs[inst.src.params.regs.pri]; + uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs; + if (inst.src.params.regs.sec & 1) { + //32-bit index register + after += regfile[sec_reg]; + } else { + //16-bit index register + if (regfile[sec_reg] & 0x8000) { + after += (0xFFFF0000 | regfile[sec_reg]); + } else { + after += regfile[sec_reg]; + } + } + after += inst.src.params.regs.displacement; + break; + } + case MODE_PC_DISPLACE: + after = inst.src.params.regs.displacement + address + 2; + break; + case MODE_PC_INDEX_DISP8: { + uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7; + after = address + 2; + uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs; + if (inst.src.params.regs.sec & 1) { + //32-bit index register + after += regfile[sec_reg]; + } else { + //16-bit index register + if (regfile[sec_reg] & 0x8000) { + after += (0xFFFF0000 | regfile[sec_reg]); + } else { + after += regfile[sec_reg]; + } + } + after += inst.src.params.regs.displacement; + break; + } + case MODE_ABSOLUTE: + case MODE_ABSOLUTE_SHORT: + after = inst.src.params.immed; + break; + } } insert_breakpoint(context, after, (uint8_t *)debugger); debugging = 0; -- cgit v1.2.3 From eabf30121c4f8412a6bf841b01383557ab5a9202 Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Sun, 9 Feb 2014 10:29:29 -0800 Subject: Properly handle dbcc, rtr and rte in the debugger next command --- blastem.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 0d173fc..d7cf953 100644 --- a/blastem.c +++ b/blastem.c @@ -1465,17 +1465,27 @@ m68k_context * debugger(m68k_context * context, uint32_t address) printf(format, param, value); break; case 'n': - //TODO: Deal with dbcc, rtr and rte if (inst.op == M68K_RTS) { after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); + } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { + after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) { - if (inst.extra.cond = COND_TRUE) { + if (inst.extra.cond == COND_TRUE) { after = inst.address + 2 + inst.src.params.immed; } else { branch_f = after; branch_t = inst.address + 2 + inst.src.params.immed; insert_breakpoint(context, branch_t, (uint8_t *)debugger); } + } else if(inst.op == M68K_DBCC) { + if (inst.extra.cond == COND_FALSE) { + if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { + after = inst.address + 2 + inst.src.params.immed; + } + } else if (inst.extra.cond != COND_TRUE) { + branch_t = after; + branch_f = inst.address + 2 + inst.src.params.immed; + } } else if(inst.op == M68K_JMP) { switch(inst.src.addr_mode) { -- cgit v1.2.3 From 57324b7ae6acb13034f6f23001c0ce306d9c2cf0 Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Sun, 9 Feb 2014 12:35:27 -0800 Subject: Refactor debugger next command --- blastem.c | 71 +++++++-------------------------------------------------------- 1 file changed, 8 insertions(+), 63 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index d7cf953..6b13ed5 100644 --- a/blastem.c +++ b/blastem.c @@ -1469,72 +1469,17 @@ m68k_context * debugger(m68k_context * context, uint32_t address) after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); - } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) { - if (inst.extra.cond == COND_TRUE) { - after = inst.address + 2 + inst.src.params.immed; - } else { + } else if(m68k_is_noncall_branch(&inst)) { + if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { branch_f = after; - branch_t = inst.address + 2 + inst.src.params.immed; + branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); insert_breakpoint(context, branch_t, (uint8_t *)debugger); - } - } else if(inst.op == M68K_DBCC) { - if (inst.extra.cond == COND_FALSE) { - if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { - after = inst.address + 2 + inst.src.params.immed; - } - } else if (inst.extra.cond != COND_TRUE) { + } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) { branch_t = after; - branch_f = inst.address + 2 + inst.src.params.immed; - } - } else if(inst.op == M68K_JMP) { - switch(inst.src.addr_mode) - { - case MODE_AREG_INDIRECT: - after = context->aregs[inst.src.params.regs.pri]; - break; - case MODE_AREG_INDEX_DISP8: { - uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7; - after = context->aregs[inst.src.params.regs.pri]; - uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs; - if (inst.src.params.regs.sec & 1) { - //32-bit index register - after += regfile[sec_reg]; - } else { - //16-bit index register - if (regfile[sec_reg] & 0x8000) { - after += (0xFFFF0000 | regfile[sec_reg]); - } else { - after += regfile[sec_reg]; - } - } - after += inst.src.params.regs.displacement; - break; - } - case MODE_PC_DISPLACE: - after = inst.src.params.regs.displacement + address + 2; - break; - case MODE_PC_INDEX_DISP8: { - uint8_t sec_reg = inst.src.params.regs.sec >> 1 & 0x7; - after = address + 2; - uint32_t * regfile = inst.src.params.regs.sec & 0x10 ? context->aregs : context->dregs; - if (inst.src.params.regs.sec & 1) { - //32-bit index register - after += regfile[sec_reg]; - } else { - //16-bit index register - if (regfile[sec_reg] & 0x8000) { - after += (0xFFFF0000 | regfile[sec_reg]); - } else { - after += regfile[sec_reg]; - } - } - after += inst.src.params.regs.displacement; - break; - } - case MODE_ABSOLUTE: - case MODE_ABSOLUTE_SHORT: - after = inst.src.params.immed; - break; + branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); + insert_breakpoint(context, branch_f, (uint8_t *)debugger); + } else { + after = m68k_branch_target(&inst, context->dregs, context->aregs); } } insert_breakpoint(context, after, (uint8_t *)debugger); -- cgit v1.2.3 From 04b527cd9945160456e8112afb221acef5e1c4fe Mon Sep 17 00:00:00 2001 From: Mike Pavone Date: Sun, 9 Feb 2014 17:16:55 -0800 Subject: Added step and step-over debugger commands. step-over is like next except it doesn't follow conditional branches to lower addresses. This makes it useful for advancing to the end of a loop. Also fixed a bug in next introduced by the refactor. --- blastem.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'blastem.c') diff --git a/blastem.c b/blastem.c index 6b13ed5..847f777 100644 --- a/blastem.c +++ b/blastem.c @@ -1411,7 +1411,7 @@ m68k_context * debugger(m68k_context * context, uint32_t address) case 'd': param = find_param(input_buf); if (!param) { - fputs("b command requires a parameter\n", stderr); + fputs("d command requires a parameter\n", stderr); break; } value = atoi(param); @@ -1474,7 +1474,66 @@ m68k_context * debugger(m68k_context * context, uint32_t address) branch_f = after; branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); insert_breakpoint(context, branch_t, (uint8_t *)debugger); - } else if(inst.op == M68K_BCC && inst.extra.cond != COND_FALSE) { + } else if(inst.op == M68K_DBCC) { + if ( inst.extra.cond == COND_FALSE) { + if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { + after = m68k_branch_target(&inst, context->dregs, context->aregs); + } + } else { + branch_t = after; + branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); + insert_breakpoint(context, branch_f, (uint8_t *)debugger); + } + } else { + after = m68k_branch_target(&inst, context->dregs, context->aregs); + } + } + insert_breakpoint(context, after, (uint8_t *)debugger); + debugging = 0; + break; + case 'o': + if (inst.op == M68K_RTS) { + after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); + } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { + after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); + } else if(m68k_is_noncall_branch(&inst)) { + if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { + branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); + if (branch_t < after) { + branch_t = 0; + } else { + branch_f = after; + insert_breakpoint(context, branch_t, (uint8_t *)debugger); + } + } else if(inst.op == M68K_DBCC) { + uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs); + if (target > after) { + if (inst.extra.cond == COND_FALSE) { + after = target; + } else { + branch_f = target; + branch_t = after; + insert_breakpoint(context, branch_f, (uint8_t *)debugger); + } + } + } else { + after = m68k_branch_target(&inst, context->dregs, context->aregs); + } + } + insert_breakpoint(context, after, (uint8_t *)debugger); + debugging = 0; + break; + case 's': + if (inst.op == M68K_RTS) { + after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); + } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { + after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); + } else if(m68k_is_branch(&inst)) { + if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { + branch_f = after; + branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); + insert_breakpoint(context, branch_t, (uint8_t *)debugger); + } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) { branch_t = after; branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); insert_breakpoint(context, branch_f, (uint8_t *)debugger); -- cgit v1.2.3