summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Gaisler <jiri@gaisler.se>2019-10-27 22:30:43 +0100
committerJiri Gaisler <jiri@gaisler.se>2019-11-02 19:18:32 +0100
commite4eccd1f9f33c5f3d1f751c706705a93ef742313 (patch)
tree1ce378c51e5f9ff31285b9ba2f9c24f5d4addee8
parentUpdated to version 2.17 (diff)
downloadsis-e4eccd1f9f33c5f3d1f751c706705a93ef742313.tar.bz2
Added support for gdb hw break/watchpoints
-rw-r--r--func.c30
-rw-r--r--interf.c94
-rw-r--r--remote.c55
-rw-r--r--sis.h2
-rw-r--r--sparc.c5
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
@@ -135,6 +135,41 @@ sim_stop (SIM_DESC sd)
}
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)
{
if (ebase.wprnum < WPR_MAX)
@@ -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;