summaryrefslogtreecommitdiff
path: root/interf.c
diff options
context:
space:
mode:
authorJiri Gaisler <jiri@gaisler.se>2019-03-22 10:00:07 +0100
committerJiri Gaisler <jiri@gaisler.se>2019-05-14 22:26:21 +0200
commit865b177d0e2fd534270ef158030e7c3056a930e3 (patch)
tree4edbf27496977adaed90287d11eaffbe357ac757 /interf.c
Standalone sis - initial commit
Diffstat (limited to 'interf.c')
-rw-r--r--interf.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/interf.c b/interf.c
new file mode 100644
index 0000000..e79a6cb
--- /dev/null
+++ b/interf.c
@@ -0,0 +1,321 @@
+/* This file is part of SIS (SPARC instruction simulator)
+
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Contributed by Jiri Gaisler, European Space Agency
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "sis.h"
+
+#define PSR_CWP 0x7
+#define SIM_DESC int
+#define SIM_ADDR uint32
+#define SIM_RC int
+#define SIM_RC_FAIL 0
+#define SIM_RC_OK 1
+#define EBREAK 0x00100073
+#define CEBREAK 0x90002
+
+static int
+run_sim_gdb(icount, dis)
+ uint64 icount;
+ int dis;
+{
+ int res;
+
+ if ((sregs[cpu].pc != 0) && (ebase.simtime == 0))
+ ms->boot_init ();
+ res = run_sim(icount, dis);
+ ms->sim_halt();
+ clearerr(stdin);
+ return res;
+}
+
+void
+sim_close(sd, quitting)
+ SIM_DESC sd;
+ int quitting;
+{
+
+ ms->exit_sim ();
+#if defined(F_GETFL) && defined(F_SETFL)
+ fcntl(0, F_SETFL, termsave);
+#endif
+
+};
+
+void
+sim_create_inferior()
+{
+ int i;
+
+ if (sis_verbose)
+ printf("interf: sim_create_inferior()");
+ ebase.simtime = 0;
+ ebase.simstart = 0;
+ reset_all();
+ reset_stat(sregs);
+ for (i=0; i<ncpu; i++){
+ sregs[i].pc = last_load_addr & ~1;
+ sregs[i].npc = sregs[i].pc + 4;
+ }
+}
+
+int
+sim_write (uint32 mem, const unsigned char *buf, int length)
+{
+ int i, len;
+
+ for (i = 0; i < length; i++) {
+ ms->sis_memory_write ((mem + i) ^ arch->endian, &buf[i], 1);
+ }
+ return length;
+}
+
+int
+sim_read (uint32 mem, unsigned char *buf, int length)
+{
+ int i, len;
+
+ for (i = 0; i < length; i++) {
+ ms->sis_memory_read ((mem + i) ^ arch->endian, &buf[i], 1);
+ }
+ return length;
+}
+
+void
+sim_info(sd, verbose)
+ SIM_DESC sd;
+ int verbose;
+{
+ show_stat(&sregs[cpu]);
+}
+
+int simstat = OK;
+
+void
+sim_resume(int step)
+{
+ if (step)
+ simstat = run_sim_gdb(1, 0);
+ else
+ simstat = run_sim_gdb(UINT64_MAX/2, 0);
+
+ if (sis_gdb_break && (cputype != CPU_RISCV))
+ flush_windows (&sregs[cpu]);
+}
+
+int
+sim_stop (SIM_DESC sd)
+{
+ ctrl_c = 1;
+ return 1;
+}
+
+static int
+sis_insert_watchpoint_read(int addr, unsigned char mask)
+{
+ if (ebase.wprnum < WPR_MAX) {
+ ebase.wprs[ebase.wprnum] = addr;
+ ebase.wprm[ebase.wprnum] = mask;
+ ebase.wprnum++;
+ if (sis_verbose)
+ printf ("inserted read watchpoint at %x\n", addr);
+ return SIM_RC_OK;
+ } else
+ return SIM_RC_FAIL;
+}
+
+static int
+sis_remove_watchpoint_read(int addr)
+{
+ int i = 0;
+
+ while ((i < ebase.wprnum) && (ebase.wprs[i] != addr))
+ i++;
+ if (addr == ebase.wprs[i]) {
+ for (; i < ebase.wprnum - 1; i++)
+ ebase.wprs[i] = ebase.wprs[i + 1];
+ ebase.wprnum -= 1;
+ if (sis_verbose)
+ printf ("removed read watchpoint at %x\n", addr);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sis_insert_watchpoint_write(int32 addr, unsigned char mask)
+{
+ if (ebase.wpwnum < WPR_MAX) {
+ ebase.wpws[ebase.wpwnum] = addr;
+ ebase.wpwm[ebase.wpwnum] = mask;
+ ebase.wpwnum++;
+ if (sis_verbose)
+ printf ("sim_insert_watchpoint_write: 0x%08x : %x\n", addr, mask);
+ return SIM_RC_OK;
+ } else
+ return SIM_RC_FAIL;
+}
+
+static int
+sis_remove_watchpoint_write(int addr)
+{
+ int i = 0;
+
+ while ((i < ebase.wpwnum) && (ebase.wpws[i] != addr))
+ i++;
+ if (addr == ebase.wpws[i]) {
+ for (; i < ebase.wpwnum - 1; i++)
+ ebase.wpws[i] = ebase.wpws[i + 1];
+ ebase.wpwnum -= 1;
+ if (sis_verbose)
+ printf ("removed write watchpoint at %x\n", addr);
+ return SIM_RC_OK;
+ }
+ return SIM_RC_FAIL;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+ if (type == 2) /* bp_hardware_breakpoint not supported */
+ return 0;
+ else
+ return 1;
+}
+
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR 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;
+ }
+
+ switch (type) {
+ case 0:
+ res = sis_insert_watchpoint_write (mem, mask);
+ break;
+ case 1:
+ res = sis_insert_watchpoint_read (mem, mask);
+ break;
+ case 2:
+ 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;
+ }
+ return (res);
+}
+
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+ int res;
+ switch (type) {
+ case 0:
+ res = sis_remove_watchpoint_write (mem);
+ break;
+ case 1:
+ res = sis_remove_watchpoint_read (mem);
+ break;
+ case 2:
+ 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;
+ }
+ return (res);
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+ if (sis_verbose)
+ printf ("sim_stopped_by_watchpoint %x\n", ebase.wphit);
+ return((ebase.wphit != 0));
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+ if (sis_verbose)
+ printf("sim__watchpoint_address %x\n", ebase.wpaddress);
+ return(ebase.wpaddress);
+}
+
+int
+sim_insert_swbreakpoint(uint32 addr, int len)
+{
+ uint32 breakinsn;
+
+ if (ebase.bptnum < BPT_MAX) {
+ ebase.bpts[ebase.bptnum] = addr;
+ ms->sis_memory_read (addr, (char *) &ebase.bpsave[ebase.bptnum] , len);
+ if (len == 4) {
+ breakinsn = EBREAK;
+ ms->sis_memory_write (addr, (char *) &breakinsn , 4);
+ } else {
+ breakinsn = CEBREAK;
+ ms->sis_memory_write (addr, (char *) &breakinsn , 2);
+ }
+ if (sis_verbose)
+ printf("sim_insert_swbreakpoint: added breakpoint %d at 0x%08x\n", ebase.bptnum + 1, addr);
+ ebase.bptnum += 1;
+ return 1;
+ }
+ return 0; /* Too many breakpoints */
+}
+
+int
+sim_remove_swbreakpoint(uint32 addr, int len)
+{
+ int i;
+
+ /* find breakpoint to remove */
+ for (i=0; i<ebase.bptnum;i++) {
+ if (ebase.bpts[i] == addr)
+ break;
+ }
+ if (ebase.bpts[i] == addr) {
+ /* write back saved opcode */
+ ms->sis_memory_write (addr, (char *) &ebase.bpsave[i] , len);
+ if (sis_verbose)
+ printf("sim_remove_swbreakpoint: remove breakpoint %d at 0x%08x\n", i, addr);
+ /* shift down remaining breakpoints */
+ for (; i<ebase.bptnum;i++) {
+ ebase.bpts[i] = ebase.bpts[i + 1];
+ }
+ ebase.bptnum -= 1;
+ return 1;
+ }
+ return 0; /* breakpoint not found */
+}