summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Gaisler <jiri@gaisler.se>2019-11-05 17:45:01 +0100
committerJiri Gaisler <jiri@gaisler.se>2019-11-08 22:33:22 +0100
commit8828fb20a0df7f0747d5c6678328d261f310fc64 (patch)
tree1402f18a68786214439b2ef772905e5ff9746527
parentImprove gdb watchpoint handling (diff)
downloadsis-8828fb20a0df7f0747d5c6678328d261f310fc64.tar.bz2
Replaced windows flushing with reg cache
-rw-r--r--interf.c7
-rw-r--r--sis.h8
-rw-r--r--sparc.c80
-rw-r--r--sparc.h7
4 files changed, 46 insertions, 56 deletions
diff --git a/interf.c b/interf.c
index 259e793..d23d3a0 100644
--- a/interf.c
+++ b/interf.c
@@ -98,6 +98,11 @@ sim_read (uint32 mem, char *buf, int length)
{
int i, len;
+ if (sis_gdb_break && (cputype <= CPU_LEON3) && (length >= 4))
+ {
+ if (gdb_sp_read (mem, buf, length))
+ return length;
+ }
for (i = 0; i < length; i++)
{
ms->sis_memory_read ((mem + i) ^ arch->endian, &buf[i], 1);
@@ -124,7 +129,7 @@ sim_resume (int step)
simstat = run_sim_gdb (UINT64_MAX / 2, 0);
if (sis_gdb_break && (cputype != CPU_RISCV))
- flush_windows (&sregs[cpu]);
+ save_sp (&sregs[cpu]);
}
int
diff --git a/sis.h b/sis.h
index 4e12686..04f0a6b 100644
--- a/sis.h
+++ b/sis.h
@@ -23,6 +23,7 @@
#define VAL(x) strtoul(x,(char **)NULL,0)
#define I_ACC_EXC 1
+#define NWIN 8
/* Maximum events in event queue */
#define EVENT_MAX 256
@@ -164,6 +165,8 @@ struct pstate
uint64 l1imiss;
uint32 l1dtags[L1DTAGS];
uint64 l1dmiss;
+
+ uint32 sp[NWIN];
};
struct evcell
@@ -307,7 +310,7 @@ extern int delta; /* time slice for MP simulation */
extern void pwd_enter (struct pstate *sregs);
extern void remove_event (void (*cfunc) (), int32 arg);
extern int run_sim (uint64 icount, int dis);
-void flush_windows (struct pstate *sregs);
+void save_sp (struct pstate *sregs);
void cov_start (int address);
void cov_exec (int address);
void cov_bt (int address1, int address2);
@@ -379,6 +382,9 @@ 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);
+/* sparc.c */
+extern int gdb_sp_read (uint32 mem, char *buf, int length);
+
/* FPU timing based on Meiko */
#define T_FABSs 2
diff --git a/sparc.c b/sparc.c
index a06aa6b..1fad8d2 100644
--- a/sparc.c
+++ b/sparc.c
@@ -1,10 +1,13 @@
-#include "sparc.h"
#include <inttypes.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include "sparc.h"
+
+static int fpexec (uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
+ struct pstate *sregs);
static uint32
sub_cc (psr, operand1, operand2, result)
@@ -2250,65 +2253,46 @@ disp_reg (sregs, reg)
sparc_disp_regs (sregs, VAL (&reg[1]));
}
-/* Flush all register windows out to the stack. Starting after the invalid
- window, flush all windows up to, and including the current window. This
- allows GDB to do backtraces and look at local variables for frames that
- are still in the register windows. Note that strictly speaking, this
- behavior is *wrong* for several reasons. First, it doesn't use the window
- overflow handlers. It therefore assumes standard frame layouts and window
- handling policies. Second, it changes system state behind the back of the
- target program. I expect this to mainly pose problems when debugging trap
- handlers.
+/* Save stack pointer in each valid register window. Used to detect if gdb
+ wants to read a memory location which is cached in a register.
*/
void
-flush_windows (struct pstate *sregs)
+save_sp (struct pstate *sregs)
{
- int invwin;
- int cwp;
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;
-
- /* Calculate the invalid window from the wim. */
-
- for (invwin = 0; invwin <= PSR_CWP; invwin++)
- if ((sregs->wim >> invwin) & 1)
- break;
-
- /* Start saving with the window after the invalid window. */
+ for (win = 0; win < NWIN; win++)
+ {
+ if ((sregs->wim >> win) & 1)
+ sregs->sp[win] = 0;
+ else
+ sregs->sp[win] = sregs->r[win * 16 + 14];
+ }
+}
- invwin = (invwin - 1) & PSR_CWP;
+int
+gdb_sp_read (uint32 mem, char *buf, int length)
+{
+ int i, j, len;
+ char *data;
- for (win = invwin;; win = (win - 1) & PSR_CWP)
+ for (i = 0; i < NWIN; i++)
{
- uint32 sp;
- int i;
-
- sp = sregs->r[(win * 16 + 14) & 0x7f];
-#if 1
- if (sis_verbose > 2)
+ if ((mem >= sregs[cpu].sp[i]) && (mem < (sregs[cpu].sp[i] + 64)))
{
- uint32 fp = sregs->r[(win * 16 + 30) & 0x7f];
- printf ("flush_window: win %d, sp %x, fp %x\n", win, sp, fp);
+ data =
+ (char *) &sregs[cpu].
+ r[((i + 1) * 16 + ((mem - sregs->sp[i]) >> 2)) % (NWIN * 16)];
+ for (j = 0; j < length; j++)
+ buf[j] = data[j ^ arch->endian];
+ if (sis_verbose)
+ printf("gdb_sp_read: 0x%08x\n", mem);
+ return length;
}
-#endif
-
- for (i = 0; i < 16; i++)
- ms->memory_write (sp + 4 * i, &sregs->r[(win * 16 + 16 + i) & 0x7f],
- 2, &ws);
-
- if (win == cwp)
- break;
}
+
+ return 0;
}
static void
diff --git a/sparc.h b/sparc.h
index 19f3561..2d69713 100644
--- a/sparc.h
+++ b/sparc.h
@@ -54,7 +54,7 @@
#define PSR_V 0x0200000
#define PSR_C 0x0100000
#define PSR_CC 0x0F00000
-#define PSR_CWP 0x7
+#define PSR_CWP (NWIN - 1)
#define PSR_PIL 0x0f00
#define ICC_N (icc >> 3)
@@ -191,8 +191,3 @@
/* # of cycles overhead when a trap is taken */
#define TRAP_C 3
-
-/* Forward declarations */
-
-static int fpexec (uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
- struct pstate *sregs);