diff options
author | Jiri Gaisler <jiri@gaisler.se> | 2019-11-04 22:57:29 +0100 |
---|---|---|
committer | Jiri Gaisler <jiri@gaisler.se> | 2019-11-08 22:33:05 +0100 |
commit | 88b545002e553f1e21fab1aff854a3e325976ad3 (patch) | |
tree | 45aaddcb10ccc2d17706e2fee31d367042bbd2f0 | |
parent | 4e080cdb1dd910750fb28de1f764934206554301 (diff) |
Improve gdb watchpoint handling
* show old/new values
* stop at correct instruction
-rw-r--r-- | func.c | 2 | ||||
-rw-r--r-- | remote.c | 12 | ||||
-rw-r--r-- | riscv.c | 20 | ||||
-rw-r--r-- | sis.h | 1 | ||||
-rw-r--r-- | sparc.c | 13 |
5 files changed, 40 insertions, 8 deletions
@@ -1092,6 +1092,7 @@ check_wpr (struct pstate *sregs, int32 address, unsigned char mask) ebase.wpaddress = address; if (ebase.wphit) return (0); + ebase.wptype = 3; return (WPT_HIT); } } @@ -1111,6 +1112,7 @@ check_wpw (struct pstate *sregs, int32 address, unsigned char mask) ebase.wpaddress = ebase.wpws[i]; if (ebase.wphit) return (0); + ebase.wptype = 2; return (WPT_HIT); } } @@ -288,12 +288,14 @@ gdb_remote_exec (char *buf) case 'c': sim_resume (0); i = sim_stat (); - /* The T watch response does not seem to work with sparc/gdb, disable ... - if ((i == SIGTRAP) && ebase.wphit) - sprintf (txbuf, "T%02xwatch:%x;", i, ebase.wpaddress); - else - */ sprintf (txbuf, "S%02x", i); + if ((i == SIGTRAP) && ebase.wphit) + { + if (ebase.wptype == 2) + sprintf (txbuf, "T%02xwatch:%x;", i, ebase.wpaddress); + else if (ebase.wptype == 3) + sprintf (txbuf, "T%02xrwatch:%x;", i, ebase.wpaddress); + } break; case 'k': /* kill */ case 'R': /* restart */ @@ -870,6 +870,13 @@ riscv_dispatch_instruction (sregs) break; case OP_STORE: /* store instructions */ + /* skip store if we resume after a write watchpoint */ + if (sis_gdb_break && ebase.wphit) + { + ebase.wphit = 0; + break; + } + #if defined(STAT) || defined(ENABLE_L1CACHE) sregs->nstore++; #endif @@ -882,7 +889,10 @@ riscv_dispatch_instruction (sregs) if ((ebase.wphit = check_wpw (sregs, address, funct3 & 3))) { sregs->trap = WPT_TRAP; - break; + /* gdb seems to expect that the write goes trough when the + * watchpoint is hit, but PC stays on the store instruction */ + if (!sis_gdb_break) + break; } } @@ -940,6 +950,11 @@ riscv_dispatch_instruction (sregs) break; case OP_FSW: /* F store instructions */ + if (sis_gdb_break && ebase.wphit) + { + ebase.wphit = 0; + break; + } #if defined(STAT) || defined(ENABLE_L1CACHE) sregs->nstore++; #endif @@ -952,7 +967,8 @@ riscv_dispatch_instruction (sregs) if ((ebase.wphit = check_wpw (sregs, address, funct3 & 3))) { sregs->trap = WPT_TRAP; - break; + if (!sis_gdb_break) + break; } } @@ -207,6 +207,7 @@ struct estate uint32 bpsave[BPT_MAX]; /* Saved opcode */ uint32 wprnum; uint32 wphit; + uint32 wptype; uint32 wprs[WPR_MAX]; /* Read Watchpoints */ unsigned char wprm[WPR_MAX]; /* Read Watchpoint masks */ uint32 wpwnum; @@ -961,12 +961,23 @@ sparc_dispatch_instruction (sregs) if (op3 & 4) { sregs->icnt = T_ST; /* Set store instruction count */ + + /* skip store if we resume after a write watchpoint */ + if (sis_gdb_break && ebase.wphit) + { + ebase.wphit = 0; + break; + } + if (ebase.wpwnum) { if ((ebase.wphit = check_wpw (sregs, address, wpmask (op3)))) { sregs->trap = WPT_TRAP; - break; + /* gdb seems to expect that the write goes trough when the + * watchpoint is hit, but PC stays on the store instruction */ + if (!sis_gdb_break) + break; } } #if defined(STAT) || defined(ENABLE_L1CACHE) |