From: ga Date: Wed, 16 Mar 2022 22:05:49 +0000 (+0000) Subject: Make the break instruction useful. The previous implementation X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=ee7434d5f74210dda9615629dcb6f40ffc943783;p=sx%2Fsimavr.git 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. --- 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 };