Commit ee7434d5f74210dda9615629dcb6f40ffc943783
authorga <ga@oldell.fish>
Wed, 16 Mar 2022 22:05:49 +0000 (22:05 +0000)
committerga <ga@oldell.fish>
Wed, 16 Mar 2022 22:05:49 +0000 (22:05 +0000)
could never move past it, as gdb knows it is in ROM and will
not replace it.  Distinguish hard and soft breaks.

3 files changed:
simavr/sim/sim_core.c
simavr/sim/sim_gdb.c
simavr/sim/sim_gdb.h

index 4dae91ed5ce6d24640e5aeadf84e06fc270c08e1..a1a9ac926aad24604496de090b8d0aa727282eea 100644 (file)
@@ -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
index 40ed524d04f118086ca38d59c15ecc15ca306aac..6d6ef97525f617ca1c79b2efd053d5290c7e6ce6 100644 (file)
@@ -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);
index 4ff64306196557004fba8c6592fba5b7d9e1906a..2936df79ee361d40e94ff9dbb368d82a74e2f323 100644 (file)
@@ -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
 };