From e4eccd1f9f33c5f3d1f751c706705a93ef742313 Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Sun, 27 Oct 2019 22:30:43 +0100 Subject: Added support for gdb hw break/watchpoints --- func.c | 30 +++++++++------------ interf.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++------------------ remote.c | 55 +++++++++++++++++++------------------ sis.h | 2 ++ sparc.c | 5 ++++ 5 files changed, 117 insertions(+), 69 deletions(-) diff --git a/func.c b/func.c index 7dc0e67..d63c511 100644 --- a/func.c +++ b/func.c @@ -190,10 +190,9 @@ exec_cmd (const char *cmd) */ if (len) { - ebase.bpts[ebase.bptnum] = len & ~0x1; - printf ("added breakpoint %d at 0x%08x\n", - ebase.bptnum + 1, ebase.bpts[ebase.bptnum]); - ebase.bptnum += 1; + if (sim_set_watchpoint (len & ~1, 4, 1)) + printf ("added breakpoint %d at 0x%08x\n", + ebase.bptnum, ebase.bpts[ebase.bptnum - 1]); } } else @@ -576,15 +575,14 @@ exec_cmd (const char *cmd) printf (" %d : 0x%08x (write)\n", i + 1, ebase.wpws[i]); } } - else if (strncmp (cmd1, "+wpr", clen) == 0) + else if ((strncmp (cmd1, "+wpr", clen) == 0) || + (strncmp (cmd1, "rwatch", clen) == 0)) { if ((cmd1 = strtok (NULL, " \t\n\r")) != NULL) { - ebase.wprs[ebase.wprnum] = VAL (cmd1) & ~0x3; - ebase.wprm[ebase.wprnum] = 3; - printf ("added read watchpoint %d at 0x%08x\n", - ebase.wprnum + 1, ebase.wprs[ebase.wprnum]); - ebase.wprnum += 1; + if (sim_set_watchpoint (VAL (cmd1) & ~0x3, 4, 3)) + printf ("added read watchpoint %d at 0x%08x\n", + ebase.wprnum, ebase.wprs[ebase.wprnum - 1]); } } else if (strncmp (cmd1, "-wpr", clen) == 0) @@ -609,11 +607,9 @@ exec_cmd (const char *cmd) { if ((cmd1 = strtok (NULL, " \t\n\r")) != NULL) { - ebase.wpws[ebase.wpwnum] = VAL (cmd1) & ~0x3; - ebase.wpwm[ebase.wpwnum] = 3; - printf ("added write watchpoint %d at 0x%08x\n", - ebase.wpwnum + 1, ebase.wpws[ebase.wpwnum]); - ebase.wpwnum += 1; + if (sim_set_watchpoint (VAL (cmd1) & ~0x3, 4, 2)) + printf ("added write watchpoint %d at 0x%08x\n", + ebase.wpwnum, ebase.wpws[ebase.wpwnum - 1]); } else { @@ -730,8 +726,8 @@ show_stat (sregs) ebase.freq * (double) (sregs[i].ninst - sregs[i].finst) / (double) (stime - sregs[i].pwdtime), ebase.freq * (double) sregs[i].finst / (double) (stime - - sregs[i]. - pwdtime), + sregs + [i].pwdtime), (double) (stime - sregs[i].pwdtime) / (double) (sregs[i].ninst + 1), 100.0 * (1.0 - ((double) sregs[i].pwdtime / (double) stime)) diff --git a/interf.c b/interf.c index 8062021..259e793 100644 --- a/interf.c +++ b/interf.c @@ -134,6 +134,41 @@ sim_stop (SIM_DESC sd) return 1; } +static int +sis_insert_hw_breakpoint (int addr) +{ + if (ebase.wprnum < BPT_MAX) + { + ebase.bpts[ebase.bptnum] = addr; + ebase.bptnum++; + if (sis_verbose) + printf ("inserted hw breakpoint at %x\n", addr); + return SIM_RC_OK; + } + else + return SIM_RC_FAIL; +} + +static int +sis_remove_hw_breakpoint (int addr) +{ + int i = 0; + + if (!ebase.bptnum) + return 1; + while ((i < ebase.bptnum) && (ebase.bpts[i] != addr)) + i++; + if (addr == ebase.bpts[i]) + { + for (; i < ebase.bptnum - 1; i++) + ebase.wprs[i] = ebase.bpts[i + 1]; + ebase.bptnum -= 1; + if (sis_verbose) + printf ("removed hw breakpoint at %x\n", addr); + } + return 1; +} + static int sis_insert_watchpoint_read (int addr, unsigned char mask) { @@ -155,6 +190,8 @@ sis_remove_watchpoint_read (int addr) { int i = 0; + if (!ebase.wprnum) + return 1; while ((i < ebase.wprnum) && (ebase.wprs[i] != addr)) i++; if (addr == ebase.wprs[i]) @@ -164,7 +201,6 @@ sis_remove_watchpoint_read (int addr) ebase.wprnum -= 1; if (sis_verbose) printf ("removed read watchpoint at %x\n", addr); - return 0; } return 1; } @@ -190,6 +226,8 @@ sis_remove_watchpoint_write (int addr) { int i = 0; + if (!ebase.wpwnum) + return 1; while ((i < ebase.wpwnum) && (ebase.wpws[i] != addr)) i++; if (addr == ebase.wpws[i]) @@ -199,9 +237,8 @@ sis_remove_watchpoint_write (int addr) ebase.wpwnum -= 1; if (sis_verbose) printf ("removed write watchpoint at %x\n", addr); - return SIM_RC_OK; } - return SIM_RC_FAIL; + return SIM_RC_OK; } int @@ -215,68 +252,73 @@ sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype) int -sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type) +sim_set_watchpoint (uint32 mem, int length, int type) { int res; unsigned char mask; - switch (length) - { - case 1: - mask = 0; - break; - case 2: - mask = 1; - break; - case 4: - mask = 3; - break; - default: - mask = 7; - break; - } + if (!length) + return 1; /* used by gdb for probing of watchpoints */ + + mask = length - 1; switch (type) { case 0: - res = sis_insert_watchpoint_write (mem, mask); + res = sim_insert_swbreakpoint (mem, length); break; case 1: - res = sis_insert_watchpoint_read (mem, mask); + res = sis_insert_hw_breakpoint (mem); break; case 2: + res = sis_insert_watchpoint_write (mem, mask); + break; + case 3: + res = sis_insert_watchpoint_read (mem, mask); + break; + case 4: if ((res = sis_insert_watchpoint_write (mem, mask)) == SIM_RC_OK) res = sis_insert_watchpoint_read (mem, mask); if (res == SIM_RC_FAIL) sis_remove_watchpoint_read (mem); break; default: - res = -1; + res = 0; } return (res); } int -sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type) +sim_clear_watchpoint (uint32 mem, int length, int type) { int res; + + if (!length) + return 1; + switch (type) { case 0: - res = sis_remove_watchpoint_write (mem); + res = sim_remove_swbreakpoint (mem, length); break; case 1: - res = sis_remove_watchpoint_read (mem); + res = sis_remove_hw_breakpoint (mem); break; case 2: + res = sis_remove_watchpoint_write (mem); + break; + case 3: + res = sis_remove_watchpoint_read (mem); + break; + case 4: if ((res = sis_remove_watchpoint_write (mem)) == SIM_RC_OK) res = sis_remove_watchpoint_read (mem); else sis_remove_watchpoint_read (mem); break; default: - res = -1; + res = 0; } return (res); } diff --git a/remote.c b/remote.c index f18baa8..95e1a32 100644 --- a/remote.c +++ b/remote.c @@ -164,6 +164,9 @@ sim_stat () int i; switch (simstat) { + case OK: + i = 0; + break; case NULL_HIT: i = SIGSEGV; break; @@ -285,6 +288,11 @@ 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); break; case 'k': /* kill */ @@ -331,30 +339,25 @@ gdb_remote_exec (char *buf) i = sim_stat (); sprintf (txbuf, "S%02x", i); break; - case 'z': - case 'Z': - if (buf[1] == '0') - { /* insert sw break */ - i = 3; - addr = 0; - while (buf[i] && (buf[i] != ',')) - { - addr = (addr << 4) | hex (buf[i]); - i++; - } + case 'Z': /* add break/watch point */ + case 'z': /* remove break/watch point */ + i = 3; + addr = 0; + while (buf[i] && (buf[i] != ',')) + { + addr = (addr << 4) | hex (buf[i]); i++; - len = hex (buf[i]); - if (buf[0] == 'Z') - j = sim_insert_swbreakpoint (addr, len); - else - j = sim_remove_swbreakpoint (addr, len); - if (j) - strcpy (txbuf, "OK"); - else - strcpy (txbuf, "E01"); } + i++; + len = hex (buf[i]); + if (buf[0] == 'Z') + j = sim_set_watchpoint (addr, len, hex (buf[1])); + else + j = sim_clear_watchpoint (addr, len, hex (buf[1])); + if (j) + strcpy (txbuf, "OK"); else - printf ("%s\n", buf); + strcpy (txbuf, "E01"); break; case 'q': /* query */ if (strncmp (&buf[1], "fThreadInfo", 11) == 0) @@ -425,12 +428,12 @@ gdb_remote (int port) { len = read (new_socket, buffer, 2048); buffer[len] = 0; - if (sis_verbose) + if (sis_verbose > 1) printf ("%s (%d)\n", buffer, len); if (len == 1) if (buffer[0] == '-') { - if (sis_verbose) + if (sis_verbose > 1) printf ("tx: %s\n", sendbuf); send (new_socket, sendbuf, strlen (sendbuf), 0); } @@ -458,7 +461,7 @@ gdb_remote (int port) res = check_pkg (buffer, len); if (res > 0) { - if (sis_verbose) + if (sis_verbose > 1) printf ("tx: +\n"); send (new_socket, &ack, 1, 0); if (detach) @@ -469,14 +472,14 @@ gdb_remote (int port) { strcpy (sendbuf, "$"); cont = gdb_remote_exec ((char *) &buffer[res]); - if (sis_verbose) + if (sis_verbose > 1) printf ("tx: %s\n", sendbuf); send (new_socket, sendbuf, strlen (sendbuf), 0); } } else { - if (sis_verbose) + if (sis_verbose > 1) printf ("tx: -\n"); send (new_socket, &nok, 1, 0); } diff --git a/sis.h b/sis.h index 8ddb6bb..493afbb 100644 --- a/sis.h +++ b/sis.h @@ -375,6 +375,8 @@ extern void sim_create_inferior (); extern void sim_resume (int step); extern int sim_insert_swbreakpoint (uint32 addr, int len); extern int sim_remove_swbreakpoint (uint32 addr, int len); +extern int sim_set_watchpoint (uint32 mem, int length, int type); +extern int sim_clear_watchpoint (uint32 mem, int length, int type); /* FPU timing based on Meiko */ diff --git a/sparc.c b/sparc.c index 8b49831..db40e8d 100644 --- a/sparc.c +++ b/sparc.c @@ -2258,6 +2258,11 @@ flush_windows (struct pstate *sregs) int win; int ws; + /* Skip if window potentially not valid */ + + if ((!(sregs->psr & PSR_ET)) || ((sregs->psr & PSR_PIL) == 0x0f00)) + return; + /* Keep current window handy */ cwp = sregs->psr & PSR_CWP; -- cgit v1.2.3