From ee7434d5f74210dda9615629dcb6f40ffc943783 Mon Sep 17 00:00:00 2001 From: ga Date: Wed, 16 Mar 2022 22:05:49 +0000 Subject: [PATCH] Make the break instruction useful. The previous implementation could never move past it, as gdb knows it is in ROM and will not replace it. Distinguish hard and soft breaks. --- simavr/sim/sim_core.c | 12 +++--- simavr/sim/sim_gdb.c | 91 +++++++++++++++++++++++++++---------------- simavr/sim/sim_gdb.h | 1 + 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index 4dae91e..a1a9ac9 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -164,7 +164,8 @@ uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) "CORE: *** Wrapping read address " "PC=%04x SP=%04x O=%04x Address %04x %% %04x --> %04x\n" FONT_DEFAULT, - avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc), addr, (avr->ramend + 1), addr % (avr->ramend + 1)); + avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc), + addr, (avr->ramend + 1), addr % (avr->ramend + 1)); addr = addr % (avr->ramend + 1); } @@ -938,12 +939,9 @@ run_one_again: case 0x9598: { // BREAK -- 1001 0101 1001 1000 STATE("break\n"); if (avr->gdb) { - // if gdb is on, we break here as in here - // and we do so until gdb restores the instruction - // that was here before - avr->state = cpu_StepDone; - new_pc = avr->pc; - cycle = 0; + // if gdb is on, break here. + avr->state = cpu_Stopped; + avr_gdb_handle_break(avr); } } break; case 0x95a8: { // WDR -- Watchdog Reset -- 1001 0101 1010 1000 diff --git a/simavr/sim/sim_gdb.c b/simavr/sim/sim_gdb.c index 40ed524..6d6ef97 100644 --- a/simavr/sim/sim_gdb.c +++ b/simavr/sim/sim_gdb.c @@ -201,22 +201,41 @@ gdb_send_reply( send(g->s, reply, dst - reply + 3, 0); } +static void +gdb_send_stop_status( + avr_gdb_t * g, + uint8_t signal, + const char * reason, + uint32_t * pp ) +{ + avr_t * avr; + uint8_t sreg; + int n; + char cmd[64]; + + avr = g->avr; + READ_SREG_INTO(avr, sreg); + + n = sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;", + signal, sreg, + avr->data[R_SPL], avr->data[R_SPH], + avr->pc & 0xff, (avr->pc >> 8) & 0xff, + (avr->pc >> 16) & 0xff); + if (reason) { + if (pp) + sprintf(cmd + n, "%s:%x;", reason, *pp); + else + sprintf(cmd + n, "%s:;", reason); + } + gdb_send_reply(g, cmd); +} + static void gdb_send_quick_status( avr_gdb_t * g, uint8_t signal ) { - char cmd[64]; - uint8_t sreg; - - READ_SREG_INTO(g->avr, sreg); - - sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;", - signal, sreg, - g->avr->data[R_SPL], g->avr->data[R_SPH], - g->avr->pc & 0xff, (g->avr->pc >> 8) & 0xff, - (g->avr->pc >> 16) & 0xff); - gdb_send_reply(g, cmd); + gdb_send_stop_status(g, signal, NULL, NULL); } static int @@ -227,14 +246,14 @@ gdb_change_breakpoint( uint32_t addr, uint32_t size ) { - DBG(printf("set %d kind %d addr %08x len %d\n", set, kind, addr, size);) + DBG(printf("%s kind %d addr %08x len %d\n", set ? "Set" : "Clear", + kind, addr, size);) if (set) { return gdb_watch_add_or_update(w, kind, addr, size); } else { return gdb_watch_rm(w, kind, addr); } - return -1; } @@ -500,9 +519,9 @@ gdb_handle_command( if (strncmp(cmd, "Supported", 9) == 0) { /* If GDB asked what features we support, report back * the features we support, which is just memory layout - * information for now. + * information and stop reasons for now. */ - gdb_send_reply(g, "qXfer:memory-map:read+"); + gdb_send_reply(g, "qXfer:memory-map:read+;swbreak+;hwbreak+"); break; } else if (strncmp(cmd, "Attached", 8) == 0) { /* Respond that we are attached to an existing process.. @@ -715,16 +734,19 @@ gdb_handle_command( break; } } break; - case 'k': // kill - avr->state = cpu_Done; - gdb_send_reply(g, "OK"); - break; case 'D': // detach - avr->state = cpu_Running; +#ifdef DETACHABLE + if (avr->state = cpu_Stopped) + avr->state = cpu_Running; gdb_send_reply(g, "OK"); close(g->s); g->s = -1; break; +#endif + case 'k': // kill + avr->state = cpu_Done; + gdb_send_reply(g, "OK"); + break; case 'v': handle_v(avr, g, cmd, length); break; @@ -828,6 +850,14 @@ gdb_network_handler( return 1; } +/* Called on a hardware break instruction. */ +void avr_gdb_handle_break(avr_t *avr) +{ + avr_gdb_t *g = avr->gdb; + + gdb_send_stop_status(g, 5, "hwbreak", NULL); +} + /** * If an applicable watchpoint exists for addr, stop the cpu and send a status report. * type is one of AVR_GDB_WATCH_READ, AVR_GDB_WATCH_WRITE depending on the type of access. @@ -839,6 +869,7 @@ avr_gdb_handle_watchpoints( enum avr_gdb_watch_type type ) { avr_gdb_t *g = avr->gdb; + uint32_t false_addr; int i = gdb_watch_find_range(&g->watchpoints, addr); if (i == -1) { @@ -850,19 +881,13 @@ avr_gdb_handle_watchpoints( addr, i, g->watchpoints.points[i].size, kind, type);) if (kind & type) { /* Send gdb reply (see GDB user manual appendix E.3). */ - char cmd[78]; - uint8_t sreg; - - READ_SREG_INTO(g->avr, sreg); - sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;%s:%06x;", - 5, sreg, - g->avr->data[R_SPL], g->avr->data[R_SPH], - g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff, - kind & AVR_GDB_WATCH_ACCESS ? "awatch" : - kind & AVR_GDB_WATCH_WRITE ? "watch" : "rwatch", - addr | 0x800000); - gdb_send_reply(g, cmd); + const char * what; + + what = (kind & AVR_GDB_WATCH_ACCESS) ? "awatch" : + (kind & AVR_GDB_WATCH_WRITE) ? "watch" : "rwatch"; + false_addr = addr + 0x800000; + gdb_send_stop_status(g, 5, what, &false_addr); avr->state = cpu_Stopped; } } @@ -879,7 +904,7 @@ avr_gdb_processor( if (avr->state == cpu_Running && gdb_watch_find(&g->breakpoints, avr->pc) != -1) { DBG(printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);) - gdb_send_quick_status(g, 5); + gdb_send_stop_status(g, 5, "hwbreak", NULL); avr->state = cpu_Stopped; } else if (avr->state == cpu_StepDone) { gdb_send_quick_status(g, 0); diff --git a/simavr/sim/sim_gdb.h b/simavr/sim/sim_gdb.h index 4ff6430..2936df7 100644 --- a/simavr/sim/sim_gdb.h +++ b/simavr/sim/sim_gdb.h @@ -46,6 +46,7 @@ int avr_gdb_processor(avr_t * avr, int sleep); // Called from sim_core.c void avr_gdb_handle_watchpoints(avr_t * g, uint16_t addr, enum avr_gdb_watch_type type); +void avr_gdb_handle_break(avr_t *); #ifdef __cplusplus }; -- 2.39.5