From 88b545002e553f1e21fab1aff854a3e325976ad3 Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Mon, 4 Nov 2019 22:57:29 +0100 Subject: Improve gdb watchpoint handling * show old/new values * stop at correct instruction --- func.c | 2 ++ remote.c | 12 +++++++----- riscv.c | 20 ++++++++++++++++++-- sis.h | 1 + sparc.c | 13 ++++++++++++- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/func.c b/func.c index d63c511..8fd004f 100644 --- a/func.c +++ b/func.c @@ -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); } } diff --git a/remote.c b/remote.c index 95e1a32..2587750 100644 --- a/remote.c +++ b/remote.c @@ -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 */ diff --git a/riscv.c b/riscv.c index 450283d..7498fce 100644 --- a/riscv.c +++ b/riscv.c @@ -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; } } diff --git a/sis.h b/sis.h index 493afbb..4e12686 100644 --- a/sis.h +++ b/sis.h @@ -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; diff --git a/sparc.c b/sparc.c index db40e8d..a06aa6b 100644 --- a/sparc.c +++ b/sparc.c @@ -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) -- cgit v1.2.3