From ef67e7f6ce48681c3653827b24262098f542971d Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Wed, 23 Dec 2015 16:17:10 -0500
Subject: [PATCH 01/11] sim/erc32: Use gdb callback for UART I/O when linked
 with gdb.

	* erc32.c (<errno.h>): new include.
	(init_stdio, restore_stdio): don't set tty attributes if ttys not open.
	(DO_STDIO_READ, port_init, read_uart, write_uart, flush_uart, uarta_tx,
	uartb_tx, uart_rx): Use gdb callbacks for console I/O, fix whitespace.

	* func.c (dumbio, tty_setup): new variables.
	(nouartrx): new variable, set to 1 if UART receiver should be disabled.
	(sim_callback): new variable, pointer to gdb host callback structure.

	* interf.c (dumbio): remove duplicate extern declaration.
	(sim_callback): moved to func.c.
	(sim_open): add -nouartrx switch to disable UART input.

	* sis.c (main): Add -nouartrx switch to disable UART input.

	* sis.h (nouartrx, sim_callback, dumbio, tty_setup): add external declare.
---
 sim/erc32/erc32.c  | 161 +++++++++++++++++++++++++++++++++++------------------
 sim/erc32/func.c   |   8 +++
 sim/erc32/interf.c |   6 +-
 sim/erc32/sis.c    |   2 +
 sim/erc32/sis.h    |   5 ++
 5 files changed, 124 insertions(+), 58 deletions(-)

diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index d722508..c6bf9f8 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -19,6 +19,7 @@
 /* The control space devices */
 
 #include "config.h"
+#include <errno.h>
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
@@ -35,8 +36,6 @@ extern int32    sparclite, sparclite_board;
 extern int      rom8,wrp,uben;
 extern char     uart_dev1[], uart_dev2[];
 
-int dumbio = 0; /* normal, smart, terminal oriented IO by default */
-
 /* MEC registers */
 #define MEC_START 	0x01f80000
 #define MEC_END 	0x01f80100
@@ -293,7 +292,6 @@ static void	store_bytes (unsigned char *mem, uint32 waddr,
 
 extern int	ext_irl;
 
-
 /* One-time init */
 
 void
@@ -935,44 +933,49 @@ void
 init_stdio()
 {
     if (dumbio)
-        return; /* do nothing */
-    if (!ifd1)
+	return; /* do nothing */
+    if (ifd1 == 0 && f1open) {
 	tcsetattr(0, TCSANOW, &ioc1);
-    if (!ifd2)
+	tcflush (ifd1, TCIFLUSH);
+    }
+    if (ifd2 == 0 && f1open) {
 	tcsetattr(0, TCSANOW, &ioc2);
+	tcflush (ifd2, TCIFLUSH);
+    }
 }
 
 void
 restore_stdio()
 {
     if (dumbio)
-        return; /* do nothing */
-    if (!ifd1)
+	return; /* do nothing */
+    if (ifd1 == 0 && f1open && tty_setup)
 	tcsetattr(0, TCSANOW, &iocold1);
-    if (!ifd2)
+    if (ifd2 == 0 && f2open && tty_setup)
 	tcsetattr(0, TCSANOW, &iocold2);
 }
 
 #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
-             ( dumbio                                \
-               ? (0) /* no bytes read, no delay */   \
-               : read( _fd_, _buf_, _len_ ) )
-
+	( dumbio || nouartrx \
+	? (0) /* no bytes read, no delay */   \
+	: (_fd_) == 1 && sim_callback ? \
+	sim_callback->read_stdin (sim_callback, _buf_, _len_) :  \
+	read( _fd_, _buf_, _len_ ) )
 
 static void
 port_init()
 {
 
     if (uben) {
-    f2in = stdin;
-    f1in = NULL;
-    f2out = stdout;
-    f1out = NULL;
+	f2in = stdin;
+	f1in = NULL;
+	f2out = stdout;
+	f1out = NULL;
     } else {
-    f1in = stdin;
-    f2in = NULL;
-    f1out = stdout;
-    f2out = NULL;
+	f1in = stdin;
+	f2in = NULL;
+	f1out = stdout;
+	f2out = NULL;
     }
     if (uart_dev1[0] != 0)
 	if ((fd1 = open(uart_dev1, O_RDWR | O_NONBLOCK)) < 0) {
@@ -984,23 +987,29 @@ port_init()
 	    setbuf(f1out, NULL);
 	    f1open = 1;
 	}
-    if (f1in) ifd1 = fileno(f1in);
+    if (f1in)
+	ifd1 = fileno(f1in);
     if (ifd1 == 0) {
+        if (sim_callback && !sim_callback->isatty (sim_callback, ifd1))
+	    tty_setup = 0;
 	if (sis_verbose)
 	    printf("serial port A on stdin/stdout\n");
         if (!dumbio) {
-            tcgetattr(ifd1, &ioc1);
-            iocold1 = ioc1;
-            ioc1.c_lflag &= ~(ICANON | ECHO);
-            ioc1.c_cc[VMIN] = 0;
-            ioc1.c_cc[VTIME] = 0;
+	    tcgetattr (ifd1, &ioc1);
+	    if (tty_setup) {
+		iocold1 = ioc1;
+		ioc1.c_lflag &= ~(ICANON | ECHO);
+		ioc1.c_cc[VMIN] = 0;
+		ioc1.c_cc[VTIME] = 0;
+	    }
         }
 	f1open = 1;
     }
 
     if (f1out) {
 	ofd1 = fileno(f1out);
-    	if (!dumbio && ofd1 == 1) setbuf(f1out, NULL);
+	if (!dumbio && tty_setup && ofd1 == 1)
+	    setbuf (f1out, NULL);
     }
 
     if (uart_dev2[0] != 0)
@@ -1019,17 +1028,20 @@ port_init()
 	    printf("serial port B on stdin/stdout\n");
         if (!dumbio) {
             tcgetattr(ifd2, &ioc2);
-            iocold2 = ioc2;
-            ioc2.c_lflag &= ~(ICANON | ECHO);
-            ioc2.c_cc[VMIN] = 0;
-            ioc2.c_cc[VTIME] = 0;
+            if (tty_setup) {
+		iocold2 = ioc2;
+		ioc2.c_lflag &= ~(ICANON | ECHO);
+		ioc2.c_cc[VMIN] = 0;
+		ioc2.c_cc[VTIME] = 0;
+	    }
         }
 	f2open = 1;
     }
 
     if (f2out) {
 	ofd2 = fileno(f2out);
-        if (!dumbio && ofd2 == 1) setbuf(f2out, NULL);
+	if (!dumbio && tty_setup && ofd2 == 1)
+	    setbuf (f2out, NULL);
     }
 
     wnuma = wnumb = 0;
@@ -1055,9 +1067,10 @@ read_uart(addr)
 		mec_irq(4);
 	    return (0x700 | (uint32) aq[aind++]);
 	} else {
-	    if (f1open) {
-	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
-	    }
+	    if (f1open)
+		anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+	    else
+		anum = 0;
 	    if (anum > 0) {
 		aind = 0;
 		if ((aind + 1) < anum)
@@ -1087,9 +1100,10 @@ read_uart(addr)
 		mec_irq(5);
 	    return (0x700 | (uint32) bq[bind++]);
 	} else {
-	    if (f2open) {
+	    if (f2open)
 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
-	    }
+	    else
+		bnum = 0;
 	    if (bnum > 0) {
 		bind = 0;
 		if ((bind + 1) < bnum)
@@ -1119,9 +1133,10 @@ read_uart(addr)
 	if (aind < anum) {
 	    Ucontrol |= 0x00000001;
 	} else {
-	    if (f1open) {
-	        anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
-            }
+	    if (f1open)
+		anum = DO_STDIO_READ(ifd1, aq, UARTBUF);
+	    else
+		anum = 0;
 	    if (anum > 0) {
 		Ucontrol |= 0x00000001;
 		aind = 0;
@@ -1131,9 +1146,10 @@ read_uart(addr)
 	if (bind < bnum) {
 	    Ucontrol |= 0x00010000;
 	} else {
-	    if (f2open) {
+	    if (f2open)
 		bnum = DO_STDIO_READ(ifd2, bq, UARTBUF);
-	    }
+	    else
+		bnum = 0;
 	    if (bnum > 0) {
 		Ucontrol |= 0x00010000;
 		bind = 0;
@@ -1174,9 +1190,13 @@ write_uart(addr, data)
 	    if (wnuma < UARTBUF)
 	        wbufa[wnuma++] = c;
 	    else {
-	        while (wnuma)
-		    wnuma -= fwrite(wbufa, 1, wnuma, f1out);
-	        wbufa[wnuma++] = c;
+	        while (wnuma) {
+		    if (ofd1 == 1 && sim_callback)
+			wnuma -= sim_callback->write_stdout (sim_callback, wbufa, wnuma);
+		    else
+			wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+		}
+		wbufa[wnuma++] = c;
 	    }
 	}
 	mec_irq(4);
@@ -1198,8 +1218,12 @@ write_uart(addr, data)
 	    if (wnumb < UARTBUF)
 		wbufb[wnumb++] = c;
 	    else {
-		while (wnumb)
-		    wnumb -= fwrite(wbufb, 1, wnumb, f2out);
+		while (wnumb) {
+		    if (ofd1 == 1 && sim_callback)
+			wnumb -= sim_callback->write_stdout (sim_callback, wbufb, wnumb);
+		    else
+			wnumb -= fwrite (wbufb, 1, wnumb, f2out);
+		}
 		wbufb[wnumb++] = c;
 	    }
 	}
@@ -1237,10 +1261,20 @@ write_uart(addr, data)
 static void
 flush_uart()
 {
-    while (wnuma && f1open)
-	wnuma -= fwrite(wbufa, 1, wnuma, f1out);
-    while (wnumb && f2open)
-	wnumb -= fwrite(wbufb, 1, wnumb, f2out);
+    while (wnuma && f1open) {
+	if (ofd1 == 1 && sim_callback) {
+	    wnuma -= sim_callback->write_stdout (sim_callback, wbufa, wnuma);
+	    sim_callback->flush_stdout (sim_callback);
+	} else
+	    wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+    }
+    while (wnumb && f2open) {
+	if (ofd2 == 1 && sim_callback) {
+	    wnuma -= sim_callback->write_stdout (sim_callback, wbufb, wnuma);
+	    sim_callback->flush_stdout (sim_callback);
+	} else
+	wnumb -= fwrite (wbufb, 1, wnumb, f2out);
+    }
 }
 
 
@@ -1248,8 +1282,14 @@ flush_uart()
 static void
 uarta_tx()
 {
-
-    while (f1open && fwrite(&uarta_sreg, 1, 1, f1out) != 1);
+    while (f1open) {
+	if (ofd1 == 1 && sim_callback)
+	    while (sim_callback->write_stdout (sim_callback, &uarta_sreg, 1) != 1)
+		continue;
+	else
+	    while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
+		continue;
+    }
     if (uart_stat_reg & UARTA_HRE) {
 	uart_stat_reg |= UARTA_SRE;
     } else {
@@ -1263,7 +1303,14 @@ uarta_tx()
 static void
 uartb_tx()
 {
-    while (f2open && fwrite(&uartb_sreg, 1, 1, f2out) != 1);
+    while (f2open) {
+	if (ofd2 == 1 && sim_callback)
+	    while (sim_callback->write_stdout (sim_callback, &uarta_sreg, 1) != 1)
+		continue;
+	else
+	    while (fwrite(&uartb_sreg, 1, 1, f2out) != 1)
+		continue;
+    }
     if (uart_stat_reg & UARTB_HRE) {
 	uart_stat_reg |= UARTB_SRE;
     } else {
@@ -1285,6 +1332,8 @@ uart_rx(arg)
     rsize = 0;
     if (f1open)
         rsize = DO_STDIO_READ(ifd1, &rxd, 1);
+    else
+        rsize = 0;
     if (rsize > 0) {
 	uarta_data = UART_DR | rxd;
 	if (uart_stat_reg & UARTA_HRE)
@@ -1301,6 +1350,8 @@ uart_rx(arg)
     rsize = 0;
     if (f2open)
         rsize = DO_STDIO_READ(ifd2, &rxd, 1);
+    else
+        rsize = 0;
     if (rsize) {
 	uartb_data = UART_DR | rxd;
 	if (uart_stat_reg & UARTB_HRE)
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index 5d3b9b9..63a6596 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -29,6 +29,12 @@
 
 #define	VAL(x)	strtoul(x,(char **)NULL,0)
 
+/* set if UART device cannot handle attributes, terminal oriented IO by default */
+int dumbio = 0;
+
+/* set if UARTs are connected to a tty, enable by default */
+int tty_setup = 1;
+
 struct disassemble_info dinfo;
 struct pstate   sregs;
 extern struct estate ebase;
@@ -47,6 +53,8 @@ char            uart_dev1[128] = "";
 char            uart_dev2[128] = "";
 extern	int	ext_irl;
 uint32		last_load_addr = 0;
+int		nouartrx = 0;
+host_callback 	*sim_callback;
 
 #ifdef ERRINJ
 uint32		errcnt = 0;
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 45be1b3..0f7d16b 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -50,15 +50,12 @@ extern struct evcell evbuf[];
 extern struct irqcell irqarr[];
 extern int      irqpend, ext_irl;
 extern int      sparclite;
-extern int      dumbio;
 extern int      sparclite_board;
 extern int      termsave;
 extern char     uart_dev1[], uart_dev2[];
 
 int             sis_gdb_break = 1;
 
-host_callback *sim_callback;
-
 int
 run_sim(sregs, icount, dis)
     struct pstate  *sregs;
@@ -192,6 +189,9 @@ sim_open (kind, callback, abfd, argv)
             if (strcmp(argv[stat], "-dumbio") == 0) {
 		dumbio = 1;
 	    } else
+            if (strcmp(argv[stat], "-nouartrx") == 0) {
+		nouartrx = 1;
+	    } else
             if (strcmp(argv[stat], "-wrp") == 0) {
                 wrp = 1;
 	    } else
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index b203c23..aea68cf 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -199,6 +199,8 @@ main(argc, argv)
 #endif
             } else if (strcmp(argv[stat], "-dumbio") == 0) {
 		dumbio = 1;
+	    } else if (strcmp(argv[stat], "-nouartrx") == 0) {
+		nouartrx = 1;
 	    } else {
 		printf("unknown option %s\n", argv[stat]);
 		usage();
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index b5bb907..dbdb5b2 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -200,6 +200,11 @@ extern void	sys_reset (void);
 extern void	sys_halt (void);
 extern int	bfd_load (const char *fname);
 extern double	get_time (void);
+extern int	nouartrx;
+extern		host_callback *sim_callback;
+extern int	dumbio;
+extern int	tty_setup;
+
 
 /* exec.c */
 extern int	dispatch_instruction (struct pstate *sregs);
-- 
2.7.4

From ee465cb547aaebb783d747c494d47a0a2afa27f6 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Wed, 23 Dec 2015 16:21:52 -0500
Subject: [PATCH 02/11] sim/erc32: Access memory subsystem through struct
 memsys.

	Introduce an common API to access emulated memory. This allows
	to emulate different types of SPARC-based CPUs.

	* erc32.c (reset, error_mode, sim_halt, close_port, exit_sim, init_stdio,
	restore_stdio, memory_iread, memory_read, memory_write, sis_memory_write,
	sis_memory_read): Mark static.
	(sim_stop): Move to interf.c.
	(erc32sys): New variable, exporting memory operations through struct memsys.
	* exec.c (dispatch_instruction): Access memory through common API.
	* func.c (ms): New global, pointing to active memory sub-system.
	(exec_cmd, print_insn_sparc_sis, dis_mem, reset_all, bfd_load): Access memory
	through common API.
	* interf.c (sregs, ctrl_c, sis_verbose): move extern declaration to sis.h.
	(run_sim, sim_close, sim_write, sim_read, flush_windows): Access memory through
	common API.
	(sim_stop): Add.
	* sis.c (sregs, ctrl_c, sis_verbose): move extern declaration to sis.h.
	(run_sim, main): Access memory through common API.
	* sis.h (memsys): Define struct memsys as common memory API. Remove declaration
	of functions marked as static.
---
 sim/erc32/erc32.c  | 46 +++++++++++++++++++++++++++-------------------
 sim/erc32/exec.c   | 42 +++++++++++++++++++++---------------------
 sim/erc32/func.c   | 32 ++++++++++++++++----------------
 sim/erc32/interf.c | 34 +++++++++++++++++++---------------
 sim/erc32/sis.c    | 35 ++++++++++++++++-------------------
 sim/erc32/sis.h    | 42 +++++++++++++++++++++++++-----------------
 6 files changed, 124 insertions(+), 107 deletions(-)

diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index c6bf9f8..25b5bb4 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -294,7 +294,7 @@ extern int	ext_irl;
 
 /* One-time init */
 
-void
+static void
 init_sim()
 {
     port_init();
@@ -302,7 +302,7 @@ init_sim()
 
 /* Power-on reset init */
 
-void
+static void
 reset()
 {
     mec_reset();
@@ -382,7 +382,7 @@ mecparerror()
 
 /* IU error mode manager */
 
-void
+static void
 error_mode(pc)
     uint32          pc;
 {
@@ -453,7 +453,7 @@ decode_mcr()
 
 /* Flush ports when simulator stops */
 
-void
+static void
 sim_halt()
 {
 #ifdef FAST_UART
@@ -461,13 +461,6 @@ sim_halt()
 #endif
 }
 
-int
-sim_stop(SIM_DESC sd)
-{
-  ctrl_c = 1;
-  return 1;
-}
-
 static void
 close_port()
 {
@@ -477,7 +470,7 @@ close_port()
 	fclose(f2in);
 }
 
-void
+static void
 exit_sim()
 {
     close_port();
@@ -929,7 +922,7 @@ mec_write(addr, data)
 
 static int      ifd1 = -1, ifd2 = -1, ofd1 = -1, ofd2 = -1;
 
-void
+static void
 init_stdio()
 {
     if (dumbio)
@@ -944,7 +937,7 @@ init_stdio()
     }
 }
 
-void
+static void
 restore_stdio()
 {
     if (dumbio)
@@ -1602,7 +1595,7 @@ store_bytes (unsigned char *mem, uint32 waddr, uint32 *data, int32 sz,
 
 /* Memory emulation */
 
-int
+static int
 memory_iread (uint32 addr, uint32 *data, int32 *ws)
 {
     uint32          asi;
@@ -1627,7 +1620,7 @@ memory_iread (uint32 addr, uint32 *data, int32 *ws)
     return 1;
 }
 
-int
+static int
 memory_read(asi, addr, data, sz, ws)
     int32           asi;
     uint32          addr;
@@ -1698,7 +1691,7 @@ memory_read(asi, addr, data, sz, ws)
     return 1;
 }
 
-int
+static int
 memory_write(asi, addr, data, sz, ws)
     int32           asi;
     uint32          addr;
@@ -1832,7 +1825,7 @@ get_mem_ptr(addr, size)
     return (char *) -1;
 }
 
-int
+static int
 sis_memory_write(addr, data, length)
     uint32               addr;
     const unsigned char *data;
@@ -1847,7 +1840,7 @@ sis_memory_write(addr, data, length)
     return length;
 }
 
-int
+static int
 sis_memory_read(addr, data, length)
     uint32          addr;
     char           *data;
@@ -1877,3 +1870,18 @@ boot_init (void)
     sregs.r[14] = sregs.r[30] - 96 * 4;
     mec_mcr |= 1;		/* power-down enabled */
 }
+
+const struct memsys erc32sys = {
+    init_sim,
+    reset,
+    error_mode,
+    sim_halt,
+    exit_sim,
+    init_stdio,
+    restore_stdio,
+    memory_iread,
+    memory_read,
+    memory_write,
+    sis_memory_write,
+    sis_memory_read
+};
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index c52474b..8192a84 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -1241,9 +1241,9 @@ dispatch_instruction(sregs)
 		else
 		    rdd = &(sregs->g[rd]);
 	    }
-	    mexc = memory_read (asi, address, ddata, 2, &ws);
+	    mexc = ms->memory_read (asi, address, ddata, 2, &ws);
 	    sregs->hold += ws;
-	    mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
+	    mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDD;
 	    if (mexc) {
@@ -1264,7 +1264,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_read(asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1275,7 +1275,7 @@ dispatch_instruction(sregs)
 	case LDSTUBA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
 	case LDSTUB:
-	    mexc = memory_read(asi, address, &data, 0, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDST;
 	    if (mexc) {
@@ -1285,7 +1285,7 @@ dispatch_instruction(sregs)
 	    data = extract_byte (data, address);
 	    *rdd = data;
 	    data = 0x0ff;
-	    mexc = memory_write(asi, address, &data, 0, &ws);
+	    mexc = ms->memory_write (asi, address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1299,7 +1299,7 @@ dispatch_instruction(sregs)
 	    if (!chk_asi(sregs, &asi, op3)) break;
 	case LDSB:
 	case LDUB:
-	    mexc = memory_read(asi, address, &data, 0, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1320,7 +1320,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_read(asi, address, &data, 1, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 1, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1346,7 +1346,7 @@ dispatch_instruction(sregs)
 		    (sregs->frs2 == rd))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = memory_read(asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    sregs->flrd = rd;
 	    sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
@@ -1372,9 +1372,9 @@ dispatch_instruction(sregs)
 		    ((sregs->frs2 >> 1) == (rd >> 1)))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = memory_read (asi, address, ddata, 2, &ws);
+	    mexc = ms->memory_read (asi, address, ddata, 2, &ws);
 	    sregs->hold += ws;
-	    mexc |= memory_read (asi, address+4, &ddata[1], 2, &ws);
+	    mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDD;
 	    if (mexc) {
@@ -1403,7 +1403,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_read(asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1425,7 +1425,7 @@ dispatch_instruction(sregs)
 	    if (ebase.simtime < sregs->ftime) {
 		sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
+	    mexc = ms->memory_write (asi, address, &sregs->fsr, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1439,7 +1439,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_write(asi, address, rdd, 2, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1448,7 +1448,7 @@ dispatch_instruction(sregs)
 	case STBA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
 	case STB:
-	    mexc = memory_write(asi, address, rdd, 0, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1468,7 +1468,7 @@ dispatch_instruction(sregs)
 		else
 		    rdd = &(sregs->g[rd]);
 	    }
-	    mexc = memory_write(asi, address, rdd, 3, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1497,7 +1497,7 @@ dispatch_instruction(sregs)
 		break;
 	    }
 	    rdd = &(sregs->fpq[0]);
-	    mexc = memory_write(asi, address, rdd, 3, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1518,7 +1518,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_write(asi, address, rdd, 1, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 1, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1537,7 +1537,7 @@ dispatch_instruction(sregs)
 		if (sregs->frd == rd)
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
+	    mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1557,7 +1557,7 @@ dispatch_instruction(sregs)
 		if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = memory_write(asi, address, &sregs->fsi[rd], 3, &ws);
+	    mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1574,13 +1574,13 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = memory_read(asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
 		break;
 	    }
-	    mexc = memory_write(asi, address, rdd, 2, &ws);
+	    mexc = ms->memory_write (asi, address, rdd, 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDST;
 	    if (mexc) {
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index 63a6596..98423da 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -55,6 +55,7 @@ extern	int	ext_irl;
 uint32		last_load_addr = 0;
 int		nouartrx = 0;
 host_callback 	*sim_callback;
+const struct memsys *ms = &erc32sys;
 
 #ifdef ERRINJ
 uint32		errcnt = 0;
@@ -423,7 +424,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 		stat = run_sim(sregs, VAL(cmd1), 0);
 	    }
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "debug", clen) == 0) {
 	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
 		sis_verbose = VAL(cmd1);
@@ -474,7 +475,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 		stat = run_sim(sregs, UINT64_MAX, 0);
 	    }
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "help", clen) == 0) {
 	    gen_help();
 	} else if (strncmp(cmd1, "history", clen) == 0) {
@@ -548,7 +549,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 		stat = run_sim(sregs, VAL(cmd1), 0);
 	    }
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "shell", clen) == 0) {
 	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
 		if (system(&cmdsave[clen])) {
@@ -558,12 +559,12 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	} else if (strncmp(cmd1, "step", clen) == 0) {
 	    stat = run_sim(sregs, 1, 1);
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "tcont", clen) == 0) {
 	    sregs->tlimit = limcalc(sregs->freq);
 	    stat = run_sim(sregs, UINT64_MAX, 0);
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "tgo", clen) == 0) {
 	    if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
 		len = last_load_addr;
@@ -576,7 +577,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    printf("resuming at 0x%08x\n",sregs->pc);
 	    stat = run_sim(sregs, UINT64_MAX, 0);
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "tlimit", clen) == 0) {
 	   sregs->tlimit = limcalc(sregs->freq);
 	   if (sregs->tlimit != (uint32) -1)
@@ -590,7 +591,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    }
 	    printf("\n");
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else if (strncmp(cmd1, "trun", clen) == 0) {
 	    ebase.simtime = 0;
 	    reset_all();
@@ -598,7 +599,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    sregs->tlimit = limcalc(sregs->freq);
 	    stat = run_sim(sregs, UINT64_MAX, 0);
 	    daddr = sregs->pc;
-	    sim_halt();
+	    ms->sim_halt ();
 	} else
 	    printf("syntax error\n");
     }
@@ -770,7 +771,7 @@ static void print_insn_sparc_sis(uint32 addr, struct disassemble_info *info)
 {
     unsigned char           i[4];
 
-    sis_memory_read(addr, i, 4);
+    ms->sis_memory_read (addr, i, 4);
     dinfo.buffer_vma = addr;
     dinfo.buffer_length = 4;
     dinfo.buffer = i;
@@ -786,10 +787,10 @@ disp_ctrl(sregs)
 
     printf("\n psr: %08X   wim: %08X   tbr: %08X   y: %08X\n",
 	   sregs->psr, sregs->wim, sregs->tbr, sregs->y);
-    sis_memory_read (sregs->pc, (char *) &i, 4);
+    ms->sis_memory_read (sregs->pc, (char *) &i, 4);
     printf ("\n  pc: %08X = %08X    ", sregs->pc, i);
     print_insn_sparc_sis(sregs->pc, &dinfo);
-    sis_memory_read (sregs->npc, (char *) &i, 4);
+    ms->sis_memory_read (sregs->npc, (char *) &i, 4);
     printf ("\n npc: %08X = %08X    ", sregs->npc, i);
     print_insn_sparc_sis(sregs->npc, &dinfo);
     if (sregs->err_mode)
@@ -814,7 +815,7 @@ disp_mem(addr, len)
     for (i = addr & ~3; i < ((addr + len) & ~3); i += 16) {
 	printf("\n %8X  ", i);
 	for (j = 0; j < 4; j++) {
-	    sis_memory_read ((i + (j * 4)), data.u8, 4);
+	    ms->sis_memory_read ((i + (j * 4)), data.u8, 4);
 	    printf ("%08x  ", data.u32);
 	    mem[j] = data.u32;
 	}
@@ -843,7 +844,7 @@ dis_mem(addr, len, info)
     } data;
 
     for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
-	sis_memory_read (i, data.u8, 4);
+	ms->sis_memory_read (i, data.u8, 4);
 	printf (" %08x  %08x  ", i, data.u32);
 	print_insn_sparc_sis(i, info);
         if (i >= 0xfffffffc) break;
@@ -1007,7 +1008,7 @@ reset_all()
 {
     init_event();		/* Clear event queue */
     init_regs(&sregs);
-    reset();
+    ms->reset ();
 #ifdef ERRINJ
     errinjstart();
 #endif
@@ -1113,8 +1114,7 @@ bfd_load (const char *fname)
 		    bfd_get_section_contents(pbfd, section, buffer, fptr, count);
 
 		    for (i = 0; i < count; i++)
-			sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1);
-
+			ms->sis_memory_write ((section_address + i) ^ EBT, &buffer[i], 1);
 		    section_address += count;
 		    fptr += count;
 		    section_size -= count;
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 0f7d16b..6661dfe 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -34,16 +34,13 @@
 #define PSR_CWP 0x7
 
 extern struct disassemble_info dinfo;
-extern struct pstate sregs;
 extern struct estate ebase;
 
-extern int      ctrl_c;
 extern int      nfp;
 extern int      ift;
 extern int      rom8;
 extern int      wrp;
 extern int      uben;
-extern int      sis_verbose;
 extern char    *sis_version;
 extern struct estate ebase;
 extern struct evcell evbuf[];
@@ -67,7 +64,7 @@ run_sim(sregs, icount, dis)
     if (sis_verbose)
 	(*sim_callback->printf_filtered) (sim_callback, "resuming at %x\n",
 					  sregs->pc);
-   init_stdio();
+   ms->init_stdio ();
    sregs->starttime = get_time();
    irq = 0;
    if ((sregs->pc != 0) && (ebase.simtime == 0))
@@ -88,7 +85,7 @@ run_sim(sregs, icount, dis)
             if (sregs->pc == 0 || sregs->npc == 0)
                 printf ("bogus pc or npc\n");
 #endif
-        mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+        mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
 #if 0	/* DELETE ME! for debugging purposes only */
         if (sis_verbose > 2)
             printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
@@ -114,8 +111,8 @@ run_sim(sregs, icount, dis)
 			if (sis_verbose)
 			    (*sim_callback->printf_filtered) (sim_callback,
 							      "SW BP hit at %x\n", sregs->pc);
-                        sim_halt();
-			restore_stdio();
+                        ms->sim_halt ();
+			ms->restore_stdio ();
 			clearerr(stdin);
 			return BPT_HIT;
 		    } else
@@ -133,12 +130,12 @@ run_sim(sregs, icount, dis)
 	    icount = 0;
 	}
     }
-    sim_halt();
+    ms->sim_halt ();
     sregs->tottime += get_time() - sregs->starttime;
-    restore_stdio();
+    ms->restore_stdio ();
     clearerr(stdin);
     if (sregs->err_mode)
-	error_mode(sregs->pc);
+	ms->error_mode (sregs->pc);
     if (sregs->err_mode)
 	return ERROR;
     if (sregs->bphit) {
@@ -254,7 +251,7 @@ sim_open (kind, callback, abfd, argv)
 #endif
     reset_all();
     ebase.simtime = 0;
-    init_sim();
+    ms->init_sim ();
     init_bpt(&sregs);
     reset_stat(&sregs);
 
@@ -268,7 +265,7 @@ sim_close(sd, quitting)
      int quitting;
 {
 
-    exit_sim();
+    ms->exit_sim ();
     fcntl(0, F_SETFL, termsave);
 
 };
@@ -336,7 +333,7 @@ sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
     int i, len;
 
     for (i = 0; i < length; i++) {
-	sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
+	ms->sis_memory_write ((mem + i) ^ EBT, &buf[i], 1);
     }
     return length;
 }
@@ -347,7 +344,7 @@ sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
     int i, len;
 
     for (i = 0; i < length; i++) {
-	sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
+	ms->sis_memory_read ((mem + i) ^ EBT, &buf[i], 1);
     }
     return length;
 }
@@ -435,7 +432,7 @@ flush_windows ()
 #endif
 
       for (i = 0; i < 16; i++)
-	memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
+	ms->memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
 		      &ws);
 
       if (win == cwp)
@@ -465,6 +462,13 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
   return NULL;
 }
 
+int
+sim_stop (SIM_DESC sd)
+{
+  ctrl_c = 1;
+  return 1;
+}
+
 #if 0 /* FIXME: These shouldn't exist.  */
 
 int
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index aea68cf..96b6567 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -40,16 +40,13 @@
 #define HIST_LEN	64
 
 extern struct disassemble_info dinfo;
-extern struct pstate sregs;
 extern struct estate ebase;
 
-extern int      ctrl_c;
 extern int      nfp;
 extern int      ift;
 extern int      wrp;
 extern int      rom8;
 extern int      uben;
-extern int      sis_verbose;
 extern char    *sis_version;
 extern struct estate ebase;
 extern struct evcell evbuf[];
@@ -75,13 +72,13 @@ run_sim(sregs, icount, dis)
     int             irq, mexc, deb;
 
     sregs->starttime = get_time();
-    init_stdio();
+    ms->init_stdio ();
     if (sregs->err_mode) icount = 0;
     deb = dis || sregs->histlen || sregs->bptnum;
     irq = 0;
     while (icount > 0) {
 
-	mexc = memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
+	mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
 	sregs->icnt = 1;
 	if (sregs->annul) {
 	    sregs->annul = 0;
@@ -95,21 +92,21 @@ run_sim(sregs, icount, dis)
 		    sregs->trap = I_ACC_EXC;
 		} else {
 		    if (deb) {
-	    		if ((sregs->bphit = check_bpt(sregs)) != 0) {
-            		    restore_stdio();
-	    		    return BPT_HIT;
-	    		}
+			if ((sregs->bphit = check_bpt(sregs)) != 0) {
+			    ms->restore_stdio ();
+			    return BPT_HIT;
+			}
 		        if (sregs->histlen) {
 			    sregs->histbuf[sregs->histind].addr = sregs->pc;
 			    sregs->histbuf[sregs->histind].time = ebase.simtime;
 			    sregs->histind++;
 			    if (sregs->histind >= sregs->histlen)
-			        sregs->histind = 0;
-		        }
-		        if (dis) {
+				sregs->histind = 0;
+			}
+			if (dis) {
 			    printf(" %8" PRIu64 " ", ebase.simtime);
 			    dis_mem(sregs->pc, 1, &dinfo);
-		        }
+			}
 		    }
 		    dispatch_instruction(sregs);
 		    icount--;
@@ -118,10 +115,10 @@ run_sim(sregs, icount, dis)
 	    if (sregs->trap) {
 		irq = 0;
 		sregs->err_mode = execute_trap(sregs);
-        	if (sregs->err_mode) {
-	            error_mode(sregs->pc);
-	            icount = 0;
-	        }
+		if (sregs->err_mode) {
+		    ms->error_mode (sregs->pc);
+		    icount = 0;
+		}
 	    }
 	}
 	advance_time(sregs);
@@ -131,7 +128,7 @@ run_sim(sregs, icount, dis)
 	}
     }
     sregs->tottime += get_time() - sregs->starttime;
-    restore_stdio();
+    ms->restore_stdio ();
     if (sregs->err_mode)
 	return ERROR;
     if (ctrl_c) {
@@ -232,7 +229,7 @@ main(argc, argv)
     ebase.simtime = 0;
     reset_all();
     init_bpt(&sregs);
-    init_sim();
+    ms->init_sim ();
     if (lfile)
         last_load_addr = bfd_load(argv[lfile]);
 #ifdef STAT
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index dbdb5b2..83c752c 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -158,25 +158,12 @@ struct irqcell {
 /* Prototypes  */
 
 /* erc32.c */
-extern void	init_sim (void);
-extern void	reset (void);
-extern void	error_mode (uint32 pc);
-extern void	sim_halt (void);
-extern void	exit_sim (void);
-extern void	init_stdio (void);
-extern void	restore_stdio (void);
-extern int	memory_iread (uint32 addr, uint32 *data, int32 *ws);
-extern int	memory_read (int32 asi, uint32 addr, uint32 *data,
-			     int32 sz, int32 *ws);
-extern int	memory_write (int32 asi, uint32 addr, uint32 *data,
-			      int32 sz, int32 *ws);
-extern int	sis_memory_write (uint32 addr,
-				  const unsigned char *data, uint32 length);
-extern int	sis_memory_read (uint32 addr, char *data,
-				 uint32 length);
+extern const struct memsys erc32sys;
 
 /* func.c */
-extern struct pstate  sregs;
+extern struct	pstate  sregs;
+extern int      ctrl_c;
+extern int      sis_verbose;
 extern void	set_regi (struct pstate *sregs, int32 reg,
 			  uint32 rval);
 extern void	get_regi (struct pstate *sregs, int32 reg, char *buf);
@@ -224,3 +211,24 @@ extern void	set_fsr (uint32 fsr);
 /* help.c */
 extern void	usage (void);
 extern void	gen_help (void);
+
+struct memsys {
+    void	(*init_sim) (void);
+    void	(*reset) (void);
+    void	(*error_mode) (uint32 pc);
+    void	(*sim_halt) (void);
+    void	(*exit_sim) (void);
+    void	(*init_stdio) (void);
+    void	(*restore_stdio) (void);
+    int	        (*memory_iread) (uint32 addr, uint32 *data, int32 *ws);
+    int	        (*memory_read) (int32 asi, uint32 addr, uint32 *data,
+			     int32 sz, int32 *ws);
+    int	        (*memory_write) (int32 asi, uint32 addr, uint32 *data,
+			      int32 sz, int32 *ws);
+    int	        (*sis_memory_write) (uint32 addr,
+				  const unsigned char *data, uint32 length);
+    int	        (*sis_memory_read) (uint32 addr, char *data,
+				 uint32 length);
+};
+
+extern const struct memsys *ms;
-- 
2.7.4

From 8ab50cce988cfa5cf282444756414773f61f60af Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Thu, 24 Dec 2015 09:41:50 -0500
Subject: [PATCH 03/11] sim/erc32: Move local extern declarations into sis.h.

	* erc32.c (ctrl_c, sis_verbose, sparclite, sparclite_board, rom8,
	wrp, uben, uart_dev[], ext_irl, sregs): Remove extern declarations
	* exec.c (sis_verbose, sparclite, ebase, nfp, ift, irqarr): As above.
	* func.c (ebase, dinfo, ext_irl): As above.
	(ebase, evbuf, irqarr, dinfo): Move declaration to top of file
	* interf.c (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
	evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
	termsave, uart_dev): Remove extern declarations
	* sis.c (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
	evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
	termsave, uart_dev, last_load_addr): Remove extern declarations
	* sis.h (dinfo, ebase, nfp, ift, rom8, wrp, uben, sis_version,
	evbuf, irqarr, irqpend, ext_irl, sparclite, sparclite_board,
	termsave, uart_dev, last_load_addr): Add extern declarations
---
 sim/erc32/erc32.c  | 10 ----------
 sim/erc32/exec.c   |  7 -------
 sim/erc32/func.c   | 12 ++++--------
 sim/erc32/interf.c | 18 ------------------
 sim/erc32/sis.c    | 20 --------------------
 sim/erc32/sis.h    | 20 +++++++++++++++++++-
 6 files changed, 23 insertions(+), 64 deletions(-)

diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index 25b5bb4..2ab8cf9 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -30,12 +30,6 @@
 #include "sis.h"
 #include "sim-config.h"
 
-extern int      ctrl_c;
-extern int32    sis_verbose;
-extern int32    sparclite, sparclite_board;
-extern int      rom8,wrp,uben;
-extern char     uart_dev1[], uart_dev2[];
-
 /* MEC registers */
 #define MEC_START 	0x01f80000
 #define MEC_END 	0x01f80100
@@ -290,8 +284,6 @@ static unsigned char *
 static void	store_bytes (unsigned char *mem, uint32 waddr,
 			uint32 *data, int sz, int32 *ws);
 
-extern int	ext_irl;
-
 /* One-time init */
 
 static void
@@ -1855,8 +1847,6 @@ sis_memory_read(addr, data, length)
     return length;
 }
 
-extern struct pstate sregs;
-
 void
 boot_init (void)
 {
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index 8192a84..d6a8460 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -21,7 +21,6 @@
 #include <math.h>
 #include <stdio.h>
 
-extern int32    sis_verbose, sparclite;
 int ext_irl = 0;
 
 /* Load/store interlock delay */
@@ -225,10 +224,6 @@ static int	fpexec (uint32 op3, uint32 rd, uint32 rs1, uint32 rs2,
 			struct pstate *sregs);
 static int	chk_asi (struct pstate *sregs, uint32 *asi, uint32 op3);
 
-
-extern struct estate ebase;
-extern int32    nfp,ift;
-
 #ifdef ERRINJ
 extern uint32 errtt, errftt;
 #endif
@@ -2014,8 +2009,6 @@ execute_trap(sregs)
 
 }
 
-extern struct irqcell irqarr[16];
-
 int
 check_interrupts(sregs)
     struct pstate  *sregs;
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index 98423da..482e21d 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -37,7 +37,10 @@ int tty_setup = 1;
 
 struct disassemble_info dinfo;
 struct pstate   sregs;
-extern struct estate ebase;
+struct estate   ebase;
+struct evcell   evbuf[EVENT_MAX];
+struct irqcell  irqarr[16];
+
 int             ctrl_c = 0;
 int             sis_verbose = 0;
 char           *sis_version = "2.7.5";
@@ -51,7 +54,6 @@ int             sparclite = 0;		/* emulating SPARClite instructions? */
 int             sparclite_board = 0;	/* emulating SPARClite board RAM? */
 char            uart_dev1[128] = "";
 char            uart_dev2[128] = "";
-extern	int	ext_irl;
 uint32		last_load_addr = 0;
 int		nouartrx = 0;
 host_callback 	*sim_callback;
@@ -716,12 +718,6 @@ init_signals()
 }
 
 
-extern struct disassemble_info dinfo;
-
-struct estate   ebase;
-struct evcell   evbuf[EVENT_MAX];
-struct irqcell  irqarr[16];
-
 static int
 disp_fpu(sregs)
     struct pstate  *sregs;
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 6661dfe..aaaca08 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -33,24 +33,6 @@
 
 #define PSR_CWP 0x7
 
-extern struct disassemble_info dinfo;
-extern struct estate ebase;
-
-extern int      nfp;
-extern int      ift;
-extern int      rom8;
-extern int      wrp;
-extern int      uben;
-extern char    *sis_version;
-extern struct estate ebase;
-extern struct evcell evbuf[];
-extern struct irqcell irqarr[];
-extern int      irqpend, ext_irl;
-extern int      sparclite;
-extern int      sparclite_board;
-extern int      termsave;
-extern char     uart_dev1[], uart_dev2[];
-
 int             sis_gdb_break = 1;
 
 int
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 96b6567..935550a 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -39,26 +39,6 @@
 /* Command history buffer length - MUST be binary */
 #define HIST_LEN	64
 
-extern struct disassemble_info dinfo;
-extern struct estate ebase;
-
-extern int      nfp;
-extern int      ift;
-extern int      wrp;
-extern int      rom8;
-extern int      uben;
-extern char    *sis_version;
-extern struct estate ebase;
-extern struct evcell evbuf[];
-extern struct irqcell irqarr[];
-extern int      irqpend, ext_irl;
-extern int      termsave;
-extern int      sparclite;
-extern int      dumbio;
-extern char     uart_dev1[];
-extern char     uart_dev2[];
-extern uint32   last_load_addr;
-
 #ifdef ERA
 extern int era;
 #endif
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index 83c752c..c596a8c0 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -20,7 +20,7 @@
 #include <sim-config.h>
 #include <stdint.h>
 
-#if HOST_BYTE_ORDER == BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
 #define HOST_BIG_ENDIAN
 #define EBT 0
 #else
@@ -162,8 +162,25 @@ extern const struct memsys erc32sys;
 
 /* func.c */
 extern struct	pstate  sregs;
+extern struct   estate ebase;
+extern struct   evcell evbuf[];
+extern struct   irqcell irqarr[];
+extern int      nfp;
+extern int      ift;
 extern int      ctrl_c;
 extern int      sis_verbose;
+extern char    *sis_version;
+extern int      sparclite;
+extern int      sparclite_board;
+extern uint32   last_load_addr;
+extern int      wrp;
+extern int      rom8;
+extern int      uben;
+extern int      irqpend;
+extern int      ext_irl;
+extern int      termsave;
+extern char     uart_dev1[];
+extern char     uart_dev2[];
 extern void	set_regi (struct pstate *sregs, int32 reg,
 			  uint32 rval);
 extern void	get_regi (struct pstate *sregs, int32 reg, char *buf);
@@ -174,6 +191,7 @@ extern void	init_bpt (struct pstate  *sregs);
 extern void	init_signals (void);
 
 struct disassemble_info;
+extern struct   disassemble_info dinfo;
 extern void	dis_mem (uint32 addr, uint32 len,
 			 struct disassemble_info *info);
 extern void	event (void (*cfunc) (), int32 arg, uint64 delta);
-- 
2.7.4

From e879c2de7b4bff83cfbd1990a6da81070128dc18 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Sun, 27 Dec 2015 19:46:23 -0500
Subject: [PATCH 04/11] sim/erc32: Add LEON3 processor emulation.

	Added memory and I/O sub-system to emulate a LEON3 processor.
	The cache and MMU are not emulated but enough functionallity
	is provided to run any RTEMS and BCC compiled application.
	The code is based on erc32.c and modified to emulate the
	LEON3 address space and peripheral operations.

	* Makefile.in: Added new object files
	* README.leon3: New file, documentation for leon3 emulation
	* README.sis: Updated documentation for simulator commands
	* grlib.c: New file, emulates leon3/grlib peripheral devices
	* grlib.h: New file, definition of grlib plug&play values
	* leon3.c: New file, emulation of leon3 memory and interrupt controller
	* erc32.c (memory_read, memory_write): Remove asi from parameters,
	compute locally.
	(memory_read_asi, memory_write_asi): New memory function with asi
	parameter.
	(get_mem_ptr): Allow reading of I/O registers if access has exactly
	4 byte size.
	(boot_init): Mark as static. Add new struct members.
	* exec.c (dispatch_instruction): Emulate leon3 V8 mul/div and asr17.
	Emulate LDA/LDDA/LDUBA/LDUHA/LDSTA/SWAPA/STA/STBA/SHA/STDA instructions
	separately.
	(fpexec): Use integer operations for FMOV to avoid FPU traps on x86. Add
	FSMULD instruction to LEON3 targets.
	(execute_trap): Support single vector trapping for leon3
	(exec_cmd): Add emulation of CASA instruction
	(init_regs): Add leon3 vendor/device ID to %psr.
	* func.c (sis_version): Set version to 2.8 to indicate support of leon3.
	(exec_cmd): Call boot_init through memsys structure. Set PC to start
	address of last loaded binary, and initialize registers if not 0. Add
	wmem internal command for writing memory.
	(show_stat): Use 64-bit floats when calculating simulator statistics.
	(bfd_load): switch to bfd_get_section_lma().
	* interf.c (run_sim): Call boot_init through memsys struct. Add -leon3
	option.
	(sim_open): Set leon3 default frequency to 50 MHz. Print out current
	emulation mode (erc32/leon3).
	(flush_windows): Skip asi when flushing windows.
	* sis.c (main): Update maintainer email. Add -leon3 switch. Set default
	leon3 frequency to 50 MHz. Print out current emulation mode.
	* sis.h: Add memsys struct for leon3.
---
 sim/erc32/Makefile.in  |    8 +-
 sim/erc32/README.leon3 |   53 +++
 sim/erc32/README.sis   |   99 ++---
 sim/erc32/erc32.c      |   50 ++-
 sim/erc32/exec.c       |  269 ++++++++++--
 sim/erc32/func.c       |   66 +--
 sim/erc32/grlib.c      |  106 +++++
 sim/erc32/grlib.h      |   60 +++
 sim/erc32/interf.c     |   26 +-
 sim/erc32/leon3.c      | 1067 ++++++++++++++++++++++++++++++++++++++++++++++++
 sim/erc32/sis.c        |   22 +-
 sim/erc32/sis.h        |   14 +-
 12 files changed, 1698 insertions(+), 142 deletions(-)
 create mode 100644 sim/erc32/README.leon3
 create mode 100644 sim/erc32/grlib.c
 create mode 100644 sim/erc32/grlib.h
 create mode 100644 sim/erc32/leon3.c

diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
index bd250f9..f062b10 100644
--- a/sim/erc32/Makefile.in
+++ b/sim/erc32/Makefile.in
@@ -21,7 +21,10 @@
 TERMCAP_LIB = @TERMCAP@
 READLINE_LIB = @READLINE@
 
-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
+# `sis' doesn't need interf.o.
+SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
+
+SIM_OBJS = $(SIS_OFILES) interf.o
 SIM_RUN_OBJS = sis.o
 SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
 SIM_EXTRA_ALL = sis
@@ -35,9 +38,6 @@ SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcroot)
 
 ## COMMON_POST_CONFIG_FRAG
 
-# `sis' doesn't need interf.o.
-SIS_OFILES = exec.o erc32.o func.o help.o float.o
-
 sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
 	$(CC) $(ALL_CFLAGS) -o sis \
 	  sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS)
diff --git a/sim/erc32/README.leon3 b/sim/erc32/README.leon3
new file mode 100644
index 0000000..e6d5f5e
--- /dev/null
+++ b/sim/erc32/README.leon3
@@ -0,0 +1,53 @@
+
+1. LEON3 emulation
+
+The file 'leon3.c' contains a model of simple LEON3 sub-system. It
+contains 16 Mbyte ROM and 16 Mbyte RAM. Standard peripherals
+such as interrupt controller, UART and timer are provided.
+The model can execute leon3 binaries that do not require an
+MMU.
+
+To start sis in Leon3 mode, add the -leon3 switch. In gdb,
+use 'target sim -leon3' .
+
+1.1 UART
+
+The UART emulates an APBUART and is located at address 0x80000100.
+The following registers are implemented:
+
+- UART RX and TX register	(0x80000100)
+- UART status register		(0x80000104)
+
+The UART generates interrupt 3.
+
+1.2 Timer unit (GPTIMER)
+
+The GPTIMER programmable counter is emulated and located at
+address 0x80000300. It is configured with two timers and separate
+interrupts (8 and 9).
+
+1.3 Interrupt controller
+
+The IRQMP interrupt controller is implemented as described in the
+GRLIB IP manual, with the exception of the interrupt level register.
+Extended interrupts are not supported. The registers are located
+at address 0x80000200.
+
+1.5 Memory interface
+
+The following memory areas are valid for the Leon3 simulator:
+
+0x00000000 - 0x01000000		ROM (16 Mbyte, loaded at start-up)
+0x40000000 - 0x41000000		RAM (16 Mbyte, loaded at start-up)
+0x80000000 - 0x81000000		APB bus, including plug&play
+0xFFFFF000 - 0xFFFFFFFF		AHB plug&play area
+
+Access to non-existing memory will result in a memory exception trap.
+
+1.8 Power-down mode
+
+The Leon3 power-down feature (%asr19) is supported. When power-down is
+entered, time is skipped forward until the next event in the event queue.
+However, if the simulator event queue is empty, power-down mode is not
+entered since no interrupt would be generated to exit from the mode. A
+Ctrl-C in the simulator window will exit the power-down mode.
diff --git a/sim/erc32/README.sis b/sim/erc32/README.sis
index b119f03..22d998b 100644
--- a/sim/erc32/README.sis
+++ b/sim/erc32/README.sis
@@ -1,40 +1,40 @@
 
-SIS - Sparc Instruction Simulator README file  (v2.0, 05-02-1996)
+SIS - Sparc Instruction Simulator README file  (v2.8, 10-11-2014)
 -------------------------------------------------------------------
 
 1. Introduction
 
-The SIS is a SPARC V7 architecture simulator. It consist of two parts,
+The SIS is a SPARC V7/V8 architecture simulator. It consist of two parts,
 the simulator core and a user defined memory module. The simulator
 core executes the instructions while the memory module emulates memory
-and peripherals. 
+and peripherals.
 
 2. Usage
 
-The simulator is started as follows: 
+The simulator is started as follows:
 
-sis [-uart1 uart_device1] [-uart2 uart_device2] 
-    [-nfp] [-freq frequency] [-c batch_file] [files] 
+sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
+    [-nfp] [-freq frequency] [-c batch_file] [files]
+
+By default, SIS emulates an ERC32 system. The -leon3 switch
+enables emulation of a LEON3 SOC system.
+
+The emulated console uart is connected to stdin/stdout. The -uart[1,2]
+switch can be used to connect the uarts to other devices.
 
-The default uart devices for SIS are /dev/ptypc and /dev/ptypd. The
--uart[1,2] switch can be used to connect the uarts to other devices.
-Use 'tip /dev/ttypc'  to connect a terminal emulator to the uarts.
 The '-nfp' will disable the simulated FPU, so each FPU instruction will
 generate a FPU disabled trap. The '-freq' switch can be used to define
 which "frequency" the simulator runs at. This is used by the 'perf'
 command to calculated the MIPS figure for a particular configuration.
-The give frequency must be an integer indicating the frequency in MHz.
+The frequency must be an integer indicating the frequency in MHz.
 
-The -c option indicates that sis commands should be read from 'batch_file' 
+The -c option indicates that sis commands should be read from 'batch_file'
 at startup.
 
-Files to be loaded must be in one of the supported formats (see INSTALLATION),
-and will be loaded into the simulated memory. The file formats are
-automatically recognised.
+Files to be loaded must be in one of the supported formats (elf, a.out, srec),
+and will be loaded into the simulated memory.
 
-The script 'startsim' will start the simulator in one xterm window and
-open a terminal emulator (tip) connected to the UART A in a second
-xterm window. Below is description of commands  that are recognized by 
+Below is description of commands  that are recognized by
 the simulator. The command-line is parsed using GNU readline. A command
 history of 64 commands is maintained. Use the up/down arrows to recall
 previous commands. For more details, see the readline documentation.
@@ -77,8 +77,8 @@ Prints the FPU registers
 go <address> [inst_count]
 
 The go command will set pc to <address> and npc to <address> + 4, and start
-execution. No other initialisation will be done. If inst_count is given, 
-execution will stop after the specified number of instructions.
+execution. If inst_count is given, execution will stop after the specified
+number of instructions.
 
 help
 
@@ -112,7 +112,7 @@ command also resets the statistic information.
 
 reg [reg_name] [value]
 
-Prints and sets the IU regiters. 'reg' without parameters prints the IU
+Prints and sets the IU registers. 'reg' without parameters prints the IU
 registers. 'reg [reg_name] [value]' sets the corresponding register to
 [value]. Valid register names are psr, tbr, wim, y, g1-g7, o0-o7 and
 l0-l7.
@@ -146,14 +146,20 @@ interpreted as 'cont'.
 
 3. Simulator core
 
-The SIS emulates the behavior of the 90C601E and 90C602E sparc IU and
-FPU from Matra MHS. These are roughly equivalent to the Cypress C601
-and C602.  The simulator is cycle true, i.e a simulator time is
-maintained and inremented according the IU and FPU instruction timing.
+In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E
+sparc IU and FPU from Matra MHS. These are roughly equivalent to the
+Cypress C601 and C602. The simulator is cycle accurate, i.e a simulator
+time is maintained and incremented according the IU and FPU instruction timing.
 The parallel execution between the IU and FPU is modelled, as well as
-stalls due to operand dependencies (FPU). The core interacts with the
-user-defined memory modules through a number of functions. The memory
-module must provide the following functions:
+stalls due to operand dependencies (FPU).
+
+In Leon3 mode, the core emulates the Leon3 SPARC V8 core from
+Gaisler Research. All SPARC V8 instructions are supported but
+emulation is not fully cycle-true as the cache is not emulated.
+
+The core interacts with the user-defined memory modules through
+a number of functions. The memory module must provide the following
+functions:
 
 int memory_read(asi,addr,data,ws)
 int asi;
@@ -214,13 +220,13 @@ the least significant in data[1].
 
 sis_memory_write() is used by the simulator during loading of programs.
 The function should copy 'length' bytes from *data to the simulated
-memory starting at 'addr'. sis_memory_write() should return 1 on 
-success and 0 on failure. Failure should only be indicated if access 
-to unimplemented memory is attempted. See erc32.c for more details 
+memory starting at 'addr'. sis_memory_write() should return 1 on
+success and 0 on failure. Failure should only be indicated if access
+to unimplemented memory is attempted. See erc32.c for more details
 on how to define the memory emulation functions.
 
 The 'init_sim' is called once when the simulator is started. This function
-should be used to perform initialisations of user defined memory or 
+should be used to perform initialisations of user defined memory or
 peripherals that only have to be done once, such as opening files etc.
 
 The 'reset' is called every time the simulator is reset, i.e. when a
@@ -272,7 +278,7 @@ See 'erc32.c' for examples on how to use events and interrupts.
 
 5. Memory module
 
-The supplied memory module (erc32.c) emulates the functions of memory and
+The ERC32 memory module (erc32.c) emulates the functions of memory and
 the MEC asic developed for the 90C601/2. It includes the following functions:
 
 * UART A & B
@@ -284,28 +290,27 @@ the MEC asic developed for the 90C601/2. It includes the following functions:
 * 512 Kbyte ROM
 * 4 Mbyte RAM
 
-See README.erc32 on how the MEC functions are emulated.  For a detailed MEC
-specification, look at the ERC32 home page at URL:
+See README.erc32 on how the MEC functions are emulated.
 
-http://www.estec.esa.nl/wsmwww/erc32
+The Leon3 memory module (leon3.c) emulates on-chip peripherals and
+external memory for a simple Leon3 system. The modules includes the
+following functions:
 
-6. Compile and linking programs
+* AHB and APB buses with plug&play
+* UART (APBUART)
+* Interrupt controller (IRQMP)
+* Timer unit with two timers (GPTIMER)
+* PROM/SRAM memory controller (SRCTRL)
+* 16 Mbyte PROM, 16 Mbyte SRAM
 
-The directory 'examples' contain some code fragments for SIS.
-The script gccx indicates how the native sunos gcc and linker can be used
-to produce executables for the simulator. To compile and link the provided
-'hello.c', type 'gccx hello.c'. This will build the executable 'hello'.
-Start the simulator by running 'startsim hello', and issue the command 'run.
-After the program is terminated, the IU will be force to error mode through
-a software trap and halt. 
+See README.leon3 for further details on Leon3 emulation.
 
-The programs are linked with a start-up file, srt0.S. This file includes
-the traptable and window underflow/overflow trap routines.
+6. Compile and linking programs
 
 7. IU and FPU instruction timing.
 
-The simulator provides cycle true simulation. The following table shows
-the emulated instruction timing for 90C601E & 90C602E:
+The simulator provides cycle true simulation for ERC32. The following table
+shows the emulated instruction timing for 90C601E & 90C602E:
 
 Instructions	      Cycles
 
diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index 2ab8cf9..3ab70c2 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -1613,19 +1613,16 @@ memory_iread (uint32 addr, uint32 *data, int32 *ws)
 }
 
 static int
-memory_read(asi, addr, data, sz, ws)
-    int32           asi;
-    uint32          addr;
-    uint32         *data;
-    int32           sz;
-    int32          *ws;
+memory_read (uint32 addr, uint32 *data, int32 sz, int32 *ws)
 {
     int32           mexc;
+    int32           asi;
 
 #ifdef ERRINJ
     if (errmec) {
 	if (sis_verbose)
 	    printf("Inserted MEC error %d\n",errmec);
+	asi = (sregs.psr & 0x080) ? 11 : 10;
 	set_sfsr(errmec, addr, asi, 1);
 	if (errmec == 5) mecparerror();
 	if (errmec == 6) iucomperr();
@@ -1639,6 +1636,7 @@ memory_read(asi, addr, data, sz, ws)
 	*ws = mem_ramr_ws;
 	return 0;
     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+	asi = (sregs.psr & 0x080) ? 11 : 10;
 	mexc = mec_read(addr, asi, data);
 	if (mexc) {
 	    set_sfsr(MEC_ACC, addr, asi, 1);
@@ -1678,18 +1676,20 @@ memory_read(asi, addr, data, sz, ws)
 
     if (sis_verbose)
 	printf ("Memory exception at %x (illegal address)\n", addr);
+    asi = (sregs.psr & 0x080) ? 11 : 10;
     set_sfsr(UIMP_ACC, addr, asi, 1);
     *ws = MEM_EX_WS;
     return 1;
 }
 
 static int
-memory_write(asi, addr, data, sz, ws)
-    int32           asi;
-    uint32          addr;
-    uint32         *data;
-    int32           sz;
-    int32          *ws;
+memory_read_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws)
+{
+  return memory_read (addr, data, sz, ws);
+}
+
+static int
+memory_write (uint32 addr, uint32 *data, int32 sz, int32 *ws)
 {
     uint32          byte_addr;
     uint32          byte_mask;
@@ -1698,11 +1698,13 @@ memory_write(asi, addr, data, sz, ws)
     int32           mexc;
     int             i;
     int             wphit[2];
+    int             asi;
 
 #ifdef ERRINJ
     if (errmec) {
 	if (sis_verbose)
 	    printf("Inserted MEC error %d\n",errmec);
+	asi = (sregs.psr & 0x080) ? 11 : 10;
 	set_sfsr(errmec, addr, asi, 0);
 	if (errmec == 5) mecparerror();
 	if (errmec == 6) iucomperr();
@@ -1715,6 +1717,7 @@ memory_write(asi, addr, data, sz, ws)
 	if (mem_accprot) {
 
 	    waddr = (addr & 0x7fffff) >> 2;
+	    asi = (sregs.psr & 0x080) ? 11 : 10;
 	    for (i = 0; i < 2; i++)
 		wphit[i] =
 		    (((asi == 0xa) && (mec_wpr[i] & 1)) ||
@@ -1736,6 +1739,7 @@ memory_write(asi, addr, data, sz, ws)
 	store_bytes (ramb, waddr, data, sz, ws);
 	return 0;
     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+	asi = (sregs.psr & 0x080) ? 11 : 10;
 	if ((sz != 2) || (asi != 0xb)) {
 	    set_sfsr(MEC_ACC, addr, asi, 0);
 	    *ws = MEM_EX_WS;
@@ -1792,10 +1796,17 @@ memory_write(asi, addr, data, sz, ws)
     }
 	
     *ws = MEM_EX_WS;
+    asi = (sregs.psr & 0x080) ? 11 : 10;
     set_sfsr(UIMP_ACC, addr, asi, 0);
     return 1;
 }
 
+static int
+memory_write_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws)
+{
+  return memory_write (addr, data, sz, ws);
+}
+
 static unsigned char  *
 get_mem_ptr(addr, size)
     uint32          addr;
@@ -1839,6 +1850,14 @@ sis_memory_read(addr, data, length)
     uint32          length;
 {
     char           *mem;
+    int            ws;
+    int            w4;
+
+    if (length == 4) {
+	memory_read (addr, &w4, length, &ws);
+	memcpy(data, &w4, length);
+	return 4;
+    }
 
     if ((mem = get_mem_ptr(addr, length)) == ((char *) -1))
 	return 0;
@@ -1847,7 +1866,7 @@ sis_memory_read(addr, data, length)
     return length;
 }
 
-void
+static void
 boot_init (void)
 {
     mec_write(MEC_WCR, 0);	/* zero waitstates */
@@ -1871,7 +1890,10 @@ const struct memsys erc32sys = {
     restore_stdio,
     memory_iread,
     memory_read,
+    memory_read_asi,
     memory_write,
+    memory_write_asi,
     sis_memory_write,
-    sis_memory_read
+    sis_memory_read,
+    boot_init
 };
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index d6a8460..2c3ceaa 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -207,6 +207,7 @@ int ext_irl = 0;
 #define SWAP	0x0F
 #define SWAPA	0x1F
 #define FLUSH	0x3B
+#define CASA	0x3C
 
 #define SIGN_BIT 0x80000000
 
@@ -1062,17 +1063,13 @@ dispatch_instruction(sregs)
 		*rdd = sregs->psr;
 		break;
 	    case RDY:
-                if (!sparclite)
-                    *rdd = sregs->y;
-                else {
+                *rdd = sregs->y;
+                if ((sparclite) || (cputype == CPU_LEON3)) {
                     int rs1_is_asr = (sregs->inst >> 14) & 0x1f;
                     if ( 0 == rs1_is_asr )
                         *rdd = sregs->y;
-                    else if ( 17 == rs1_is_asr )
+                    else if ( 17 == rs1_is_asr ) {
                         *rdd = sregs->asr17;
-                    else {
-                        sregs->trap = TRAP_UNIMP;
-                        break;
                     }
                 }
 		break;
@@ -1118,16 +1115,18 @@ dispatch_instruction(sregs)
 		    ((rs1 ^ operand2) & 0xfffff000);
 		break;
 	    case WRY:
-                if (!sparclite)
+                if ((!sparclite) && (cputype != CPU_LEON3))
                     sregs->y = (rs1 ^ operand2);
                 else {
                     if ( 0 == rd )
                         sregs->y = (rs1 ^ operand2);
-                    else if ( 17 == rd )
-                        sregs->asr17 = (rs1 ^ operand2);
-                    else {
-                        sregs->trap = TRAP_UNIMP;
-                        break;
+                    else if ( 17 == rd ) {
+                        if (sparclite)
+                            sregs->asr17 = (rs1 ^ operand2);
+                    }
+                    else if ( 19 == rd ) {
+                        if (cputype == CPU_LEON3)
+                            wait_for_irq();
                     }
                 }
 		break;
@@ -1224,6 +1223,32 @@ dispatch_instruction(sregs)
 	switch (op3) {
 	case LDDA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x7) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    if (rd & 1) {
+		rd &= 0x1e;
+		if (rd > 7)
+		    rdd = &(sregs->r[(cwp + rd) & 0x7f]);
+		else
+		    rdd = &(sregs->g[rd]);
+	    }
+	    mexc = ms->memory_read_asi (asi, address, ddata, 2, &ws);
+	    sregs->hold += ws;
+	    mexc |= ms->memory_read_asi (asi, address+4, &ddata[1], 2, &ws);
+	    sregs->hold += ws;
+	    sregs->icnt = T_LDD;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+	    else {
+		rdd[0] = ddata[0];
+		rdd[1] = ddata[1];
+#ifdef STAT
+		sregs->nload++;	/* Double load counts twice */
+#endif
+	    }
+	    break;
 	case LDD:
 	    if (address & 0x7) {
 		sregs->trap = TRAP_UNALI;
@@ -1236,9 +1261,9 @@ dispatch_instruction(sregs)
 		else
 		    rdd = &(sregs->g[rd]);
 	    }
-	    mexc = ms->memory_read (asi, address, ddata, 2, &ws);
+	    mexc = ms->memory_read (address, ddata, 2, &ws);
 	    sregs->hold += ws;
-	    mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
+	    mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDD;
 	    if (mexc) {
@@ -1254,12 +1279,23 @@ dispatch_instruction(sregs)
 
 	case LDA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x3) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_read_asi (asi, address, &data, 2, &ws);
+	    sregs->hold += ws;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+	    else
+		*rdd = data;
+	    break;
 	case LD:
 	    if (address & 0x3) {
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1269,8 +1305,26 @@ dispatch_instruction(sregs)
 	    break;
 	case LDSTUBA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    mexc = ms->memory_read_asi (asi, address, &data, 0, &ws);
+	    sregs->hold += ws;
+	    sregs->icnt = T_LDST;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    data = extract_byte (data, address);
+	    *rdd = data;
+	    data = 0x0ff;
+	    mexc = ms->memory_write_asi (asi, address, &data, 0, &ws);
+	    sregs->hold += ws;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+#ifdef STAT
+	    sregs->nload++;
+#endif
+	    break;
 	case LDSTUB:
-	    mexc = ms->memory_read (asi, address, &data, 0, &ws);
+	    mexc = ms->memory_read (address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDST;
 	    if (mexc) {
@@ -1280,7 +1334,7 @@ dispatch_instruction(sregs)
 	    data = extract_byte (data, address);
 	    *rdd = data;
 	    data = 0x0ff;
-	    mexc = ms->memory_write (asi, address, &data, 0, &ws);
+	    mexc = ms->memory_write (address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1292,9 +1346,21 @@ dispatch_instruction(sregs)
 	case LDSBA:
 	case LDUBA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    mexc = ms->memory_read_asi (asi, address, &data, 0, &ws);
+	    sregs->hold += ws;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    if (op3 == LDSB)
+	        data = extract_byte_signed (data, address);
+	    else
+	        data = extract_byte (data, address);
+	    *rdd = data;
+	    break;
 	case LDSB:
 	case LDUB:
-	    mexc = ms->memory_read (asi, address, &data, 0, &ws);
+	    mexc = ms->memory_read (address, &data, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1309,13 +1375,29 @@ dispatch_instruction(sregs)
 	case LDSHA:
 	case LDUHA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x1) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_read_asi (asi, address, &data, 1, &ws);
+	    sregs->hold += ws;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    if (op3 == LDSH)
+	        data = extract_short_signed (data, address);
+	    else
+	        data = extract_short (data, address);
+	    *rdd = data;
+	    break;
 	case LDSH:
 	case LDUH:
 	    if (address & 0x1) {
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_read (asi, address, &data, 1, &ws);
+	    mexc = ms->memory_read (address, &data, 1, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1341,7 +1423,7 @@ dispatch_instruction(sregs)
 		    (sregs->frs2 == rd))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    sregs->flrd = rd;
 	    sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
@@ -1367,9 +1449,9 @@ dispatch_instruction(sregs)
 		    ((sregs->frs2 >> 1) == (rd >> 1)))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = ms->memory_read (asi, address, ddata, 2, &ws);
+	    mexc = ms->memory_read (address, ddata, 2, &ws);
 	    sregs->hold += ws;
-	    mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws);
+	    mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDD;
 	    if (mexc) {
@@ -1398,7 +1480,7 @@ dispatch_instruction(sregs)
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1420,7 +1502,7 @@ dispatch_instruction(sregs)
 	    if (ebase.simtime < sregs->ftime) {
 		sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = ms->memory_write (asi, address, &sregs->fsr, 2, &ws);
+	    mexc = ms->memory_write (address, &sregs->fsr, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1429,12 +1511,21 @@ dispatch_instruction(sregs)
 
 	case STA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x3) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws);
+	    sregs->hold += ws;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+	    break;
 	case ST:
 	    if (address & 0x3) {
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_write (asi, address, rdd, 2, &ws);
+	    mexc = ms->memory_write (address, rdd, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1442,8 +1533,13 @@ dispatch_instruction(sregs)
 	    break;
 	case STBA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    mexc = ms->memory_write_asi (asi, address, rdd, 0, &ws);
+	    sregs->hold += ws;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+	    break;
 	case STB:
-	    mexc = ms->memory_write (asi, address, rdd, 0, &ws);
+	    mexc = ms->memory_write (address, rdd, 0, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1451,6 +1547,28 @@ dispatch_instruction(sregs)
 	    break;
 	case STDA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x7) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    if (rd & 1) {
+		rd &= 0x1e;
+		if (rd > 7)
+		    rdd = &(sregs->r[(cwp + rd) & 0x7f]);
+		else
+		    rdd = &(sregs->g[rd]);
+	    }
+	    mexc = ms->memory_write_asi (asi, address, rdd, 3, &ws);
+	    sregs->hold += ws;
+	    sregs->icnt = T_STD;
+#ifdef STAT
+	    sregs->nstore++;	/* Double store counts twice */
+#endif
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    break;
 	case STD:
 	    if (address & 0x7) {
 		sregs->trap = TRAP_UNALI;
@@ -1463,7 +1581,7 @@ dispatch_instruction(sregs)
 		else
 		    rdd = &(sregs->g[rd]);
 	    }
-	    mexc = ms->memory_write (asi, address, rdd, 3, &ws);
+	    mexc = ms->memory_write (address, rdd, 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1492,7 +1610,7 @@ dispatch_instruction(sregs)
 		break;
 	    }
 	    rdd = &(sregs->fpq[0]);
-	    mexc = ms->memory_write (asi, address, rdd, 3, &ws);
+	    mexc = ms->memory_write (address, rdd, 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1508,12 +1626,21 @@ dispatch_instruction(sregs)
 	    break;
 	case STHA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x1) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_write_asi (asi, address, rdd, 1, &ws);
+	    sregs->hold += ws;
+	    if (mexc)
+		sregs->trap = TRAP_DEXC;
+	    break;
 	case STH:
 	    if (address & 0x1) {
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_write (asi, address, rdd, 1, &ws);
+	    mexc = ms->memory_write (address, rdd, 1, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1532,7 +1659,7 @@ dispatch_instruction(sregs)
 		if (sregs->frd == rd)
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 2, &ws);
+	    mexc = ms->memory_write (address, &sregs->fsi[rd], 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
@@ -1552,7 +1679,7 @@ dispatch_instruction(sregs)
 		if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
 		    sregs->fhold += (sregs->ftime - ebase.simtime);
 	    }
-	    mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 3, &ws);
+	    mexc = ms->memory_write (address, &sregs->fsi[rd], 3, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_STD;
 #ifdef STAT
@@ -1564,18 +1691,40 @@ dispatch_instruction(sregs)
 	    break;
 	case SWAPA:
 	    if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x3) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_read_asi (asi, address, &data, 2, &ws);
+	    sregs->hold += ws;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws);
+	    sregs->hold += ws;
+	    sregs->icnt = T_LDST;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    } else
+		*rdd = data;
+#ifdef STAT
+	    sregs->nload++;
+#endif
+	    break;
 	case SWAP:
 	    if (address & 0x3) {
 		sregs->trap = TRAP_UNALI;
 		break;
 	    }
-	    mexc = ms->memory_read (asi, address, &data, 2, &ws);
+	    mexc = ms->memory_read (address, &data, 2, &ws);
 	    sregs->hold += ws;
 	    if (mexc) {
 		sregs->trap = TRAP_DEXC;
 		break;
 	    }
-	    mexc = ms->memory_write (asi, address, rdd, 2, &ws);
+	    mexc = ms->memory_write (address, rdd, 2, &ws);
 	    sregs->hold += ws;
 	    sregs->icnt = T_LDST;
 	    if (mexc) {
@@ -1587,7 +1736,34 @@ dispatch_instruction(sregs)
 	    sregs->nload++;
 #endif
 	    break;
-
+	case CASA:
+	    asi = (sregs->inst >> 5) & 0x0ff;
+	    address = rs1;
+	    if (!((asi == 10) || (asi == 11)))
+		if (!chk_asi(sregs, &asi, op3)) break;
+	    if (address & 0x3) {
+		sregs->trap = TRAP_UNALI;
+		break;
+	    }
+	    mexc = ms->memory_read_asi (asi, address, &data, 2, &ws);
+	    sregs->hold += ws;
+	    if (mexc) {
+		sregs->trap = TRAP_DEXC;
+		break;
+	    }
+	    if (data == operand2) {
+		mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws);
+		if (mexc) {
+		    sregs->trap = TRAP_DEXC;
+		    break;
+		} else
+		    *rdd = data;
+	    } else
+		*rdd = data;
+#ifdef STAT
+	    sregs->nload++;
+#endif
+	    break;
 
 	default:
 	    sregs->trap = TRAP_UNIMP;
@@ -1652,6 +1828,7 @@ dispatch_instruction(sregs)
 #define FMOVs	0x01
 #define FMULs	0x49
 #define FMULd	0x4A
+#define FsMULd	0x69
 #define FNEGs	0x05
 #define FSQRTs	0x29
 #define FSQRTd	0x2A
@@ -1811,7 +1988,7 @@ fpexec(op3, rd, rs1, rs2, sregs)
 	sregs->ftime += T_FDIVd;
 	break;
     case FMOVs:
-	sregs->fs[rd] = sregs->fs[rs2];
+	sregs->fsi[rd] = sregs->fsi[rs2];
 	sregs->ftime += T_FMOVs;
 	sregs->frs1 = 32;	/* rs1 ignored */
 	break;
@@ -1819,6 +1996,15 @@ fpexec(op3, rd, rs1, rs2, sregs)
 	sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
 	sregs->ftime += T_FMULs;
 	break;
+    case FsMULd:
+	if (cputype == CPU_LEON3) {	/* FSMULD only supported for LEON3 */
+	    sregs->fd[rd>>1] = (double)sregs->fs[rs1] * (double)sregs->fs[rs2];
+	    sregs->ftime += T_FMULd;
+	} else {
+	    sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
+	    sregs->fpstate = FP_EXC_PE;
+	}
+	break;
     case FMULd:
 	sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
 	sregs->ftime += T_FMULd;
@@ -1993,7 +2179,7 @@ execute_trap(sregs)
 	sregs->pc = sregs->tbr;
 	sregs->npc = sregs->tbr + 4;
 
-        if ( 0 != (1 & sregs->asr17) ) {
+        if ( 0 != (1 & (sregs->asr17 >> 13)) ) {
             /* single vector trapping! */
             sregs->pc = sregs->tbr & 0xfffff000;
             sregs->npc = sregs->pc + 4;
@@ -2040,7 +2226,10 @@ init_regs(sregs)
     sregs->npc = 4;
     sregs->trap = 0;
     sregs->psr &= 0x00f03fdf;
-    sregs->psr |= 0x11000080;	/* Set supervisor bit */
+    if (cputype == CPU_LEON3)
+      sregs->psr |= 0xF3000080;	/* Set supervisor bit */
+    else
+      sregs->psr |= 0x11000080;	/* Set supervisor bit */
     sregs->breakpoint = 0;
     sregs->annul = 0;
     sregs->fpstate = FP_EXE_MODE;
@@ -2069,4 +2258,8 @@ init_regs(sregs)
 
     sregs->rett_err = 0;
     sregs->jmpltime = 0;
+    if (cputype == CPU_LEON3) {
+        sregs->asr17 = 0x107;
+        if (!nfp) sregs->asr17 |= (3 << 10);  /* Meiko FPU */
+    }
 }
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index 482e21d..ada4d28 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -26,6 +26,7 @@
 #include <dis-asm.h>
 #include "sim-config.h"
 #include <inttypes.h>
+#include <sys/time.h>
 
 #define	VAL(x)	strtoul(x,(char **)NULL,0)
 
@@ -43,7 +44,7 @@ struct irqcell  irqarr[16];
 
 int             ctrl_c = 0;
 int             sis_verbose = 0;
-char           *sis_version = "2.7.5";
+char           *sis_version = "2.8";
 int             nfp = 0;
 int             ift = 0;
 int             wrp = 0;
@@ -58,6 +59,7 @@ uint32		last_load_addr = 0;
 int		nouartrx = 0;
 host_callback 	*sim_callback;
 const struct memsys *ms = &erc32sys;
+int		cputype = 0;		/* 0 = erc32, 3 = leon3 */
 
 #ifdef ERRINJ
 uint32		errcnt = 0;
@@ -469,7 +471,7 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    sregs->pc = len & ~3;
 	    sregs->npc = sregs->pc + 4;
 	    if ((sregs->pc != 0) && (ebase.simtime == 0))
-	        boot_init();
+	        ms->boot_init ();
 	    printf("resuming at 0x%08x\n",sregs->pc);
 	    if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
 		stat = run_sim(sregs, VAL(cmd2), 0);
@@ -517,6 +519,12 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 		len = 64;
 	    disp_mem(daddr, len);
 	    daddr += len;
+	} else if (strncmp(cmd1, "wmem", clen) == 0) {
+	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
+		daddr = VAL(cmd1);
+	    if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL)
+		len = VAL(cmd2);
+	    ms->sis_memory_write (daddr, (char *) &len, 4);
 	} else if (strncmp(cmd1, "perf", clen) == 0) {
 	    cmd1 = strtok(NULL, " \t\n\r");
 	    if ((cmd1 != NULL) &&
@@ -545,6 +553,11 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    ebase.simtime = 0;
 	    reset_all();
 	    reset_stat(sregs);
+            if (last_load_addr != 0) {
+	        sregs->pc = last_load_addr & ~3;
+	        sregs->npc = sregs->pc + 4;
+            }
+	    if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init ();
 	    if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
 		stat = run_sim(sregs, UINT64_MAX, 0);
 	    } else {
@@ -598,6 +611,11 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    ebase.simtime = 0;
 	    reset_all();
 	    reset_stat(sregs);
+            if (last_load_addr != 0) {
+	        sregs->pc = last_load_addr & ~3;
+	        sregs->npc = sregs->pc + 4;
+            }
+	    if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init ();
 	    sregs->tlimit = limcalc(sregs->freq);
 	    stat = run_sim(sregs, UINT64_MAX, 0);
 	    daddr = sregs->pc;
@@ -635,8 +653,8 @@ void
 show_stat(sregs)
     struct pstate  *sregs;
 {
-    uint32          iinst;
-    uint32          stime;
+    uint64          iinst;
+    uint64          stime;
 
     if (sregs->tottime == 0.0)
         sregs->tottime += 1E-6;
@@ -651,37 +669,37 @@ show_stat(sregs)
     printf(" Instructions : %9" PRIu64 "\n", sregs->ninst);
 
 #ifdef STAT
-    printf("   integer    : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
+    printf ("   integer    : %9.2f %%\n", 100.0 * (double) iinst / (double) sregs->ninst);
     printf("   load       : %9.2f %%\n",
-	   100.0 * (float) sregs->nload / (float) sregs->ninst);
+	   100.0 * (double) sregs->nload / (double) sregs->ninst);
     printf("   store      : %9.2f %%\n",
-	   100.0 * (float) sregs->nstore / (float) sregs->ninst);
+	   100.0 * (double) sregs->nstore / (double) sregs->ninst);
     printf("   branch     : %9.2f %%\n",
-	   100.0 * (float) sregs->nbranch / (float) sregs->ninst);
+	   100.0 * (double) sregs->nbranch / (double) sregs->ninst);
     printf("   float      : %9.2f %%\n",
-	   100.0 * (float) sregs->finst / (float) sregs->ninst);
+	   100.0 * (double) sregs->finst / (double) sregs->ninst);
     printf(" Integer CPI  : %9.2f\n",
-	   ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
+	   ((double) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
 	   /
-	   (float) (sregs->ninst - sregs->finst));
+	   (double) (sregs->ninst - sregs->finst));
     printf(" Float CPI    : %9.2f\n",
-	   ((float) sregs->fholdt / (float) sregs->finst) + 1.0);
+	   ((double) sregs->fholdt / (double) sregs->finst) + 1.0);
 #endif
     printf(" Overall CPI  : %9.2f\n",
-	   (float) (stime - sregs->pwdtime) / (float) sregs->ninst);
-    printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
-	   sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime),
-	   sregs->freq * (float) (sregs->ninst - sregs->finst) /
-	   (float) (stime - sregs->pwdtime),
-     sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime));
-    printf(" Simulated ERC32 time        : %.2f s\n",
-        (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
+	  (double) (stime - sregs->pwdtime) / (double) sregs->ninst);
+    printf ("\n CPU performance (%4.1f MHz)  : %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n",
+	  sregs->freq, sregs->freq * (double) sregs->ninst / (double) (stime - sregs->pwdtime),
+	  sregs->freq * (double) (sregs->ninst - sregs->finst) /
+	  (double) (stime - sregs->pwdtime),
+     sregs->freq * (double) sregs->finst / (double) (stime - sregs->pwdtime));
+    printf (" Simulated CPU time          : %.2f s\n",
+	(double) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq);
     printf(" Processor utilisation       : %.2f %%\n",
-        100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
+	100.0 * (1.0 - ((double) sregs->pwdtime / (double) stime)));
     printf(" Real-time performance       : %.2f %%\n",
-        100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
+	100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6))));
     printf(" Simulator performance       : %.2f MIPS\n",
-        (double)(sregs->ninst) / sregs->tottime / 1E6);
+	(double)(sregs->ninst) / sregs->tottime / 1E6);
     printf(" Used time (sys + user)      : %.2f s\n\n", sregs->tottime);
 }
 
@@ -1063,7 +1081,7 @@ bfd_load (const char *fname)
 
 	    section_name = bfd_get_section_name(pbfd, section);
 
-	    section_address = bfd_get_section_vma(pbfd, section);
+	    section_address = bfd_get_section_lma(pbfd, section);
 	    /*
 	     * Adjust sections from a.out files, since they don't carry their
 	     * addresses with.
diff --git a/sim/erc32/grlib.c b/sim/erc32/grlib.c
new file mode 100644
index 0000000..9932360
--- /dev/null
+++ b/sim/erc32/grlib.c
@@ -0,0 +1,106 @@
+/*
+ * This file is part of SIS.
+ *
+ * SIS, SPARC instruction simulator. Copyright (C) 2014 Jiri Gaisler
+ *
+ * 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 "sis.h"
+#include "grlib.h"
+
+
+/* APB PNP */
+
+static uint32 apbppmem[32 * 2];	/* 32-entry APB PP AREA */
+static int apbppindex;
+
+int
+grlib_apbpp_add (uint32 id, uint32 addr)
+{
+  apbppmem[apbppindex++] = id;
+  apbppmem[apbppindex++] = addr;
+  if (apbppindex >= (32 * 2))
+    apbppindex = 0;		/* prevent overflow of area */
+  return apbppindex;
+}
+
+uint32
+grlib_apbpnp_read (uint32 addr)
+{
+  uint32 read_data;
+  addr &= 0xff;
+  read_data = apbppmem[addr >> 2];
+
+  return read_data;
+}
+
+/* AHB PNP */
+
+static uint32 ahbppmem[128 * 8];	/* 128-entry AHB PP AREA */
+static int ahbmppindex;
+static int ahbsppindex = 64 * 8;
+
+int
+grlib_ahbmpp_add (uint32 id)
+{
+  ahbppmem[ahbmppindex] = id;
+  ahbmppindex += 8;
+  if (ahbmppindex >= (64 * 8))
+    ahbmppindex = 0;		/* prevent overflow of area */
+  return ahbmppindex;
+}
+
+int
+grlib_ahbspp_add (uint32 id, uint32 addr1, uint32 addr2,
+		  uint32 addr3, uint32 addr4)
+{
+  ahbppmem[ahbsppindex] = id;
+  ahbsppindex += 4;
+  ahbppmem[ahbsppindex++] = addr1;
+  ahbppmem[ahbsppindex++] = addr2;
+  ahbppmem[ahbsppindex++] = addr3;
+  ahbppmem[ahbsppindex++] = addr4;
+  if (ahbsppindex >= (128 * 8))
+    ahbsppindex = 64 * 8;	/* prevent overflow of area */
+  return ahbsppindex;
+}
+
+uint32
+grlib_ahbpnp_read (uint32 addr)
+{
+  uint32 read_data;
+
+  addr &= 0xfff;
+  read_data = ahbppmem[addr >> 2];
+  return read_data;
+
+}
+
+void
+grlib_init ()
+{
+  /* Add PP records for Leon3, APB bridge and interrupt controller
+     as this is not done elsewhere */
+
+  grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_LEON3, 0, 0));
+  grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBMST, 0, 0),
+		    GRLIB_PP_AHBADDR (0x80000000, 0xFFF, 0, 0, 2), 0, 0, 0);
+
+  grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_IRQMP, 2, 0),
+		   GRLIB_PP_APBADDR (0x80000200, 0xFFF));
+
+}
diff --git a/sim/erc32/grlib.h b/sim/erc32/grlib.h
new file mode 100644
index 0000000..cf38dee
--- /dev/null
+++ b/sim/erc32/grlib.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of SIS.
+ *
+ * SIS, SPARC instruction simulator. Copyright (C) 2014 Jiri Gaisler
+ *
+ * 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/>.
+ *
+ */
+
+
+/* Definitions for AMBA PNP in Gaisler Research GRLIB SOC */
+
+/* Vendors */
+
+#define VENDOR_GAISLER	1
+#define VENDOR_PENDER	2
+#define VENDOR_ESA	4
+#define VENDOR_DLR	10
+
+/* Devices */
+
+#define GAISLER_LEON3	0x003
+#define GAISLER_APBMST	0x006
+#define GAISLER_SRCTRL	0x008
+#define GAISLER_APBUART	0x00C
+#define GAISLER_IRQMP	0x00D
+#define GAISLER_GPTIMER	0x011
+#define ESA_MCTRL	0x00F
+
+/* How to build entries in the plug&play area */
+
+#define GRLIB_PP_ID(v, d, x, i) ((v & 0xff) << 24) | ((d & 0x3ff) << 12) |\
+			((x & 0x1f) << 5) | (i & 0x1f)
+#define GRLIB_PP_AHBADDR(a, m, p, c, t) (a & 0xfff00000) | ((m & 0xfff) << 4) |\
+			((p & 1) << 17) | ((c & 1) << 16) | (t & 0x3)
+#define GRLIB_PP_APBADDR(a, m) ((a & 0xfff00)<< 12) | ((m & 0xfff) << 4) | 1
+
+#define AHBPP_START	0xFFFFF000
+#define AHBPP_END	0xFFFFFFFF
+#define APBPP_START	0x800FF000
+#define APBPP_END	0x800FFFFF
+
+extern int grlib_apbpp_add (uint32 id, uint32 addr);
+extern int grlib_ahbmpp_add (uint32 id);
+extern int grlib_ahbspp_add (uint32 id, uint32 addr1, uint32 addr2,
+			     uint32 addr3, uint32 addr4);
+extern uint32 grlib_ahbpnp_read (uint32 addr);
+extern uint32 grlib_apbpnp_read (uint32 addr);
+extern void grlib_init ();
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index aaaca08..7299a7d 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -50,7 +50,7 @@ run_sim(sregs, icount, dis)
    sregs->starttime = get_time();
    irq = 0;
    if ((sregs->pc != 0) && (ebase.simtime == 0))
-	boot_init();
+	ms->boot_init ();
    while (!sregs->err_mode & (icount > 0)) {
 
 	sregs->fhold = 0;
@@ -171,6 +171,10 @@ sim_open (kind, callback, abfd, argv)
             if (strcmp(argv[stat], "-nouartrx") == 0) {
 		nouartrx = 1;
 	    } else
+            if (strcmp (argv[stat], "-leon3") == 0) {
+		ms = &leon3;
+                cputype = CPU_LEON3;
+            } else
             if (strcmp(argv[stat], "-wrp") == 0) {
                 wrp = 1;
 	    } else
@@ -208,9 +212,21 @@ sim_open (kind, callback, abfd, argv)
 	stat++;
     }
 
+    if (cputype == CPU_LEON3)
+        sregs.freq = freq ? freq : 50;
+    else
+        sregs.freq = freq ? freq : 14;
+
     if (sis_verbose) {
 	(*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
-	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
+	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jiri@gaisler.se)\n\n");
+        switch (cputype) {
+        case CPU_LEON3:
+            (*sim_callback->printf_filtered) (sim_callback, "LEON3 emulation enabled\n");
+            break;
+        default:
+            (*sim_callback->printf_filtered) (sim_callback, "ERC32 emulation enabled\n");
+        }
 	if (nfp)
 	  (*sim_callback->printf_filtered) (sim_callback, "no FPU\n");
 	if (sparclite)
@@ -219,11 +235,9 @@ sim_open (kind, callback, abfd, argv)
 	  (*sim_callback->printf_filtered) (sim_callback, "dumb IO (no input, dumb output)\n");
 	if (sis_gdb_break == 0)
 	  (*sim_callback->printf_filtered) (sim_callback, "disabling GDB trap handling for breakpoints\n");
-	if (freq)
-	  (*sim_callback->printf_filtered) (sim_callback, " ERC32 freq %d Mhz\n", freq);
+	  (*sim_callback->printf_filtered) (sim_callback, "CPU freq %3.1f MHz\n", sregs.freq);
     }
 
-    sregs.freq = freq ? freq : 15;
     termsave = fcntl(0, F_GETFL, 0);
     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
 #ifdef HOST_LITTLE_ENDIAN
@@ -414,7 +428,7 @@ flush_windows ()
 #endif
 
       for (i = 0; i < 16; i++)
-	ms->memory_write (11, sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
+	ms->memory_write (sp + 4 * i, &sregs.r[(win * 16 + 16 + i) & 0x7f], 2,
 		      &ws);
 
       if (win == cwp)
diff --git a/sim/erc32/leon3.c b/sim/erc32/leon3.c
new file mode 100644
index 0000000..4f35386
--- /dev/null
+++ b/sim/erc32/leon3.c
@@ -0,0 +1,1067 @@
+/*
+ * This file is part of SIS.
+ *
+ * SIS, SPARC instruction simulator V2.5 Copyright (C) 1995 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/>.
+ *
+ * Leon3 emulation, loosely based on erc32.c.
+ */
+
+/* The control space devices.  */
+
+#include "config.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include "sis.h"
+#include "grlib.h"
+#include "sim-config.h"
+
+/* APB registers */
+#define APBSTART	0x80000000
+#define APBEND		0x80100000
+
+/* Memory exception waitstates.  */
+#define MEM_EX_WS 	1
+
+#define MOK		0
+
+/* LEON3 APB register addresses.  */
+
+#define IRQMP_IPR		0x204
+#define IRQMP_IMR 	0x240
+#define IRQMP_ICR 	0x20C
+#define IRQMP_IFR 	0x208
+#define GPTIMER_SCALER  0x300
+#define GPTIMER_SCLOAD  0x304
+#define GPTIMER_CONFIG  0x308
+#define GPTIMER_TIMER1 	0x310
+#define GPTIMER_RELOAD1	0x314
+#define GPTIMER_CTRL1 	0x318
+#define GPTIMER_TIMER2 	0x320
+#define GPTIMER_RELOAD2	0x324
+#define GPTIMER_CTRL2 	0x328
+
+#define APBUART_RXTX	0x100
+#define APBUART_STATUS  0x104
+
+/* Size of UART buffers (bytes).  */
+#define UARTBUF	1024
+
+/* Number of simulator ticks between flushing the UARTS.  */
+/* For good performance, keep above 1000.  */
+#define UART_FLUSH_TIME	  3000
+
+/* New uart defines.  */
+#define UART_TX_TIME	1000
+#define UART_RX_TIME	1000
+#define UARTA_DR	0x1
+#define UARTA_SRE	0x2
+#define UARTA_HRE	0x4
+#define UARTA_OR	0x10
+
+/* IRQMP registers.  */
+
+static uint32 irqmp_ipr;
+static uint32 irqmp_imr;
+static uint32 irqmp_ifr;
+
+/* GPTIMER registers.  */
+
+#define NGPTIMERS  2
+#define GPTIMER_IRQ 8
+
+static uint32 gpt_scaler;
+static uint32 gpt_scaler_start;
+static uint32 gpt_counter[NGPTIMERS];
+static uint32 gpt_reload[NGPTIMERS];
+static uint32 gpt_ctrl[NGPTIMERS];
+
+/* ROM size 16 Mbyte.  */
+#define ROM_START 	0x00000000
+#define ROM_MASK 	0x00ffffff
+#define ROM_END 	(ROM_START + ROM_MASK + 1)
+
+/* RAM size 16 Mbyte.  */
+#define RAM_START 	0x40000000
+#define RAM_MASK 	0x00ffffff
+#define RAM_END 	(RAM_START + RAM_MASK + 1)
+
+/* Memory.  */
+static unsigned char romb[ROM_END - ROM_START];
+static unsigned char ramb[RAM_END - RAM_START];
+static uint32 cache_ctrl;
+
+
+/* UART support variables.  */
+
+/* File descriptor for input file.  */
+static int32 fd1, fd2;
+
+/* UART status register */
+static int32 Ucontrol;
+
+static unsigned char aq[UARTBUF], bq[UARTBUF];
+static int32 anum, aind = 0;
+static int32 bnum, bind = 0;
+static char wbufa[UARTBUF], wbufb[UARTBUF];
+static unsigned wnuma;
+static unsigned wnumb;
+static FILE *f1in, *f1out;
+static struct termios ioc1, ioc2, iocold1, iocold2;
+static int f1open = 0;
+
+static char uarta_sreg, uarta_hreg;
+static uint32 uart_stat_reg;
+static uint32 uarta_data;
+
+/* Forward declarations. */
+
+static void mem_init (void);
+static void close_port (void);
+static void leon3_reset (void);
+static void irqmp_intack (int32 level);
+static void chk_irq (void);
+static void set_irq (int32 level);
+static int32 apb_read (uint32 addr, uint32 * data);
+static int apb_write (uint32 addr, uint32 data);
+static void port_init (void);
+static uint32 grlib_read_uart (uint32 addr);
+static void grlib_write_uart (uint32 addr, uint32 data);
+static void flush_uart (void);
+static void uarta_tx (void);
+static void uart_rx (caddr_t arg);
+static void uart_intr (caddr_t arg);
+static void uart_irq_start (void);
+static void gpt_intr (caddr_t arg);
+static void gpt_init (void);
+static void gpt_reset (void);
+static void gpt_scaler_set (uint32 val);
+static void timer_ctrl (uint32 val, int i);
+static unsigned char *get_mem_ptr (uint32 addr, uint32 size);
+static void store_bytes (unsigned char *mem, uint32 waddr,
+			 uint32 * data, int sz, int32 * ws);
+
+static host_callback *callback;
+
+
+/* One-time init. */
+
+static void
+init_sim (void)
+{
+  callback = sim_callback;
+  grlib_init ();
+  mem_init ();
+  port_init ();
+  gpt_init ();
+}
+
+/* Power-on reset init. */
+
+static void
+reset (void)
+{
+  leon3_reset ();
+  uart_irq_start ();
+  gpt_reset ();
+}
+
+/* IU error mode manager. */
+
+static void
+error_mode (uint32 pc)
+{
+
+}
+
+/* Memory init. */
+
+static void
+mem_init (void)
+{
+
+/* Add AMBA P&P record for SRCTRL memory controller */
+
+  grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SRCTRL, 0, 0),
+		    GRLIB_PP_AHBADDR (0x00000000, 0xE00, 1, 1, 2),
+		    GRLIB_PP_AHBADDR (0x40000000, 0xC00, 1, 1, 2),
+		    GRLIB_PP_AHBADDR (0x20000000, 0xE00, 0, 0, 2), 0);
+  if (sis_verbose)
+    printf ("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
+	    RAM_START, (RAM_MASK + 1) / 1024, (ROM_MASK + 1) / 1024);
+}
+
+/* Flush ports when simulator stops. */
+
+static void
+sim_halt (void)
+{
+#ifdef FAST_UART
+  flush_uart ();
+#endif
+}
+
+static void
+close_port (void)
+{
+  if (f1open && f1in != stdin)
+    fclose (f1in);
+}
+
+static void
+exit_sim (void)
+{
+  close_port ();
+}
+
+static void
+leon3_reset (void)
+{
+  int i;
+
+  irqmp_ipr = 0;
+  irqmp_imr = 0;
+  irqmp_ifr = 0;
+
+  wnuma = wnumb = 0;
+  anum = aind = bnum = bind = 0;
+
+  uart_stat_reg = UARTA_SRE | UARTA_HRE;
+
+  gpt_counter[0] = 0xffffffff;
+  gpt_reload[0] = 0xffffffff;
+  gpt_scaler = 0xffff;
+  gpt_ctrl[0] = 0;
+  gpt_ctrl[1] = 0;
+
+}
+
+static void
+irqmp_intack (int32 level)
+{
+  int irq_test;
+
+  if (sis_verbose > 2)
+    printf ("interrupt %d acknowledged\n", level);
+  if (irqmp_ifr & (1 << level))
+    irqmp_ifr &= ~(1 << level);
+  else
+    irqmp_ipr &= ~(1 << level);
+  chk_irq ();
+}
+
+static void
+chk_irq (void)
+{
+  int32 i;
+  uint32 itmp;
+  int old_irl;
+
+  old_irl = ext_irl;
+  itmp = ((irqmp_ipr | irqmp_ifr) & irqmp_imr) & 0x0fffe;
+  ext_irl = 0;
+  if (itmp != 0)
+    {
+      for (i = 15; i > 0; i--)
+	{
+	  if (((itmp >> i) & 1) != 0)
+	    {
+	      if ((sis_verbose > 2) && (i > old_irl))
+		printf ("IU irl: %d\n", i);
+	      ext_irl = i;
+	      set_int (i, irqmp_intack, i);
+	      break;
+	    }
+	}
+    }
+}
+
+static void
+set_irq (int32 level)
+{
+  irqmp_ipr |= (1 << level);
+  chk_irq ();
+}
+
+static int32
+apb_read (uint32 addr, uint32 * data)
+{
+
+  switch (addr & 0xfff)
+    {
+
+    case APBUART_RXTX:		/* 0x100 */
+    case APBUART_STATUS:	/* 0x104 */
+      *data = grlib_read_uart (addr);
+      break;
+
+    case IRQMP_IPR:		/* 0x204 */
+      *data = irqmp_ipr;
+      break;
+
+    case IRQMP_IFR:		/* 0x208 */
+      *data = irqmp_ifr;
+      break;
+
+    case IRQMP_IMR:		/* 0x240 */
+      *data = irqmp_imr;
+      break;
+
+    case GPTIMER_SCALER:	/* 0x300 */
+      *data = gpt_scaler - (now () - gpt_scaler_start);
+      break;
+
+    case GPTIMER_SCLOAD:	/* 0x304 */
+      *data = gpt_scaler;
+      break;
+
+    case GPTIMER_CONFIG:	/* 0x308 */
+      *data = 0x100 | (GPTIMER_IRQ << 3) | NGPTIMERS;
+      break;
+
+    case GPTIMER_TIMER1:	/* 0x310 */
+      *data = gpt_counter[0];
+      break;
+
+    case GPTIMER_RELOAD1:	/* 0x314 */
+      *data = gpt_reload[0];
+      break;
+
+    case GPTIMER_CTRL1:	/* 0x318 */
+      *data = gpt_ctrl[0];
+      break;
+
+    case GPTIMER_TIMER2:	/* 0x320 */
+      *data = gpt_counter[1];
+      break;
+
+    case GPTIMER_RELOAD2:	/* 0x324 */
+      *data = gpt_reload[1];
+      break;
+
+    case GPTIMER_CTRL2:	/* 0x328 */
+      *data = gpt_ctrl[1];
+      break;
+
+    default:
+      *data = 0;
+      break;
+    }
+
+  if (sis_verbose > 1)
+    printf ("APB read  a: %08x, d: %08x\n", addr, *data);
+
+  return MOK;
+}
+
+static int
+apb_write (uint32 addr, uint32 data)
+{
+  if (sis_verbose > 1)
+    printf ("APB write a: %08x, d: %08x\n", addr, data);
+  switch (addr & 0xfff)
+    {
+
+    case APBUART_RXTX:		/* 0x100 */
+    case APBUART_STATUS:	/* 0x104 */
+      grlib_write_uart (addr, data);
+      break;
+
+    case IRQMP_IFR:		/* 0x208 */
+      irqmp_ifr = data & 0xfffe;
+      chk_irq ();
+      break;
+
+    case IRQMP_ICR:		/* 0x20C */
+      irqmp_ipr &= ~data & 0x0fffe;
+      chk_irq ();
+      break;
+
+    case IRQMP_IMR:		/* 0x240 */
+      irqmp_imr = data & 0x7ffe;
+      chk_irq ();
+      break;
+
+    case GPTIMER_SCLOAD:	/* 0x304 */
+      gpt_scaler_set (data);
+      break;
+
+    case GPTIMER_TIMER1:	/* 0x310 */
+      gpt_counter[0] = data;
+      break;
+
+    case GPTIMER_RELOAD1:	/* 0x314 */
+      gpt_reload[0] = data;
+      break;
+
+    case GPTIMER_CTRL1:	/* 0x318 */
+      timer_ctrl (data, 0);
+      break;
+
+    case GPTIMER_TIMER2:	/* 0x320 */
+      gpt_counter[1] = data;
+      break;
+
+    case GPTIMER_RELOAD2:	/* 0x324 */
+      gpt_reload[1] = data;
+      break;
+
+    case GPTIMER_CTRL2:	/* 0x328 */
+      timer_ctrl (data, 1);
+      break;
+
+    default:
+      break;
+    }
+  return MOK;
+}
+
+
+/* APBUART.  */
+
+static int ifd1 = -1, ofd1 = -1;
+
+static void
+init_stdio (void)
+{
+  if (dumbio)
+    return;
+  if (ifd1 == 0 && f1open)
+    {
+      tcsetattr (0, TCSANOW, &ioc1);
+      tcflush (ifd1, TCIFLUSH);
+    }
+}
+
+static void
+restore_stdio (void)
+{
+  if (dumbio)
+    return;
+  if (ifd1 == 0 && f1open && tty_setup)
+    tcsetattr (0, TCSANOW, &iocold1);
+}
+
+#define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
+		( dumbio || nouartrx \
+		? (0) /* no bytes read, no delay */   \
+		: (_fd_) == 1 && callback ? \
+		callback->read_stdin (callback, _buf_, _len_) :  \
+		read( _fd_, _buf_, _len_ ) )
+
+static void
+port_init (void)
+{
+  f1in = stdin;
+  f1out = stdout;
+  if (uart_dev1[0] != 0)
+    if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0)
+      {
+	printf ("Warning, couldn't open output device %s\n", uart_dev1);
+      }
+    else
+      {
+	if (sis_verbose)
+	  printf ("serial port A on %s\n", uart_dev1);
+	f1in = f1out = fdopen (fd1, "r+");
+	setbuf (f1out, NULL);
+	f1open = 1;
+      }
+  if (f1in)
+    ifd1 = fileno (f1in);
+  if (ifd1 == 0)
+    {
+      if (callback && !callback->isatty (callback, ifd1))
+	tty_setup = 0;
+      if (sis_verbose)
+	printf ("serial port A on stdin/stdout\n");
+      if (!dumbio)
+	{
+	  tcgetattr (ifd1, &ioc1);
+	  if (tty_setup)
+	    {
+	      iocold1 = ioc1;
+	      ioc1.c_lflag &= ~(ICANON | ECHO);
+	      ioc1.c_cc[VMIN] = 0;
+	      ioc1.c_cc[VTIME] = 0;
+	    }
+	}
+      f1open = 1;
+    }
+
+  if (f1out)
+    {
+      ofd1 = fileno (f1out);
+      if (!dumbio && tty_setup && ofd1 == 1)
+	setbuf (f1out, NULL);
+    }
+
+  wnuma = 0;
+
+  grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBUART, 1, 3),
+		   GRLIB_PP_APBADDR (0x80000100, 0xFFF));
+}
+
+static uint32
+grlib_read_uart (uint32 addr)
+{
+  unsigned tmp = 0;
+
+  switch (addr & 0xff)
+    {
+
+    case 0x00:			/* UART 1 RX/TX */
+#ifndef _WIN32
+#ifdef FAST_UART
+
+      if (aind < anum)
+	{
+	  if ((aind + 1) < anum)
+	    set_irq (3);
+	  return (uint32) aq[aind++];
+	}
+      else
+	{
+	  if (f1open)
+	    anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
+	  else
+	    anum = 0;
+	  if (anum > 0)
+	    {
+	      aind = 0;
+	      if ((aind + 1) < anum)
+		set_irq (3);
+	      return (uint32) aq[aind++];
+	    }
+	  else
+	    return (uint32) aq[aind];
+	}
+#else
+      tmp = uarta_data;
+      uarta_data &= ~UART_DR;
+      uart_stat_reg &= ~UARTA_DR;
+      return tmp;
+#endif
+#else
+      return 0;
+#endif
+      break;
+
+    case 0x04:			/* UART status register  */
+#ifndef _WIN32
+#ifdef FAST_UART
+
+      Ucontrol = 0;
+      if (aind < anum)
+	{
+	  Ucontrol |= 0x00000001;
+	}
+      else
+	{
+	  if (f1open)
+	    anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
+	  else
+	    anum = 0;
+	  if (anum > 0)
+	    {
+	      Ucontrol |= 0x00000001;
+	      aind = 0;
+	      set_irq (3);
+	    }
+	}
+      Ucontrol |= 0x00000006;
+      return Ucontrol;
+#else
+      return uart_stat_reg;
+#endif
+#else
+      return 0x00060006;
+#endif
+      break;
+    default:
+      if (sis_verbose)
+	printf ("Read from unimplemented UART register (%x)\n", addr);
+    }
+
+  return 0;
+}
+
+static void
+grlib_write_uart (uint32 addr, uint32 data)
+{
+  unsigned char c;
+
+  c = (unsigned char) data;
+  switch (addr & 0xff)
+    {
+
+    case 0x00:			/* UART A */
+#ifdef FAST_UART
+      if (f1open)
+	{
+	  if (wnuma < UARTBUF)
+	    wbufa[wnuma++] = c;
+	  else
+	    {
+	      while (wnuma)
+		{
+		  if (ofd1 == 1 && callback)
+		    wnuma -= callback->write_stdout (callback, wbufa, wnuma);
+		  else
+		    wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+		}
+	      wbufa[wnuma++] = c;
+	    }
+	}
+      set_irq (3);
+#else
+      if (uart_stat_reg & UARTA_SRE)
+	{
+	  uarta_sreg = c;
+	  uart_stat_reg &= ~UARTA_SRE;
+	  event (uarta_tx, 0, UART_TX_TIME);
+	}
+      else
+	{
+	  uarta_hreg = c;
+	  uart_stat_reg &= ~UARTA_HRE;
+	}
+#endif
+      break;
+
+    case 0x04:			/* UART status register */
+#ifndef FAST_UART
+      uart_stat_reg &= 1;
+#endif
+      break;
+    default:
+      if (sis_verbose)
+	printf ("Write to unimplemented UART register (%x)\n", addr);
+    }
+}
+
+static void
+flush_uart (void)
+{
+  while (wnuma && f1open)
+    {
+      if (ofd1 == 1 && callback)
+	{
+	  wnuma -= callback->write_stdout (callback, wbufa, wnuma);
+	  callback->flush_stdout (callback);
+	}
+      else
+	wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+    }
+}
+
+static void
+uarta_tx (void)
+{
+  while (f1open)
+    {
+      if (ofd1 == 1 && callback)
+	while (callback->write_stdout (callback, &uarta_sreg, 1) != 1)
+	  continue;
+      else
+	while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
+	  continue;
+    }
+  if (uart_stat_reg & UARTA_HRE)
+    {
+      uart_stat_reg |= UARTA_SRE;
+    }
+  else
+    {
+      uarta_sreg = uarta_hreg;
+      uart_stat_reg |= UARTA_HRE;
+      event (uarta_tx, 0, UART_TX_TIME);
+    }
+  set_irq (3);
+}
+
+static void
+uart_rx (caddr_t arg)
+{
+  char rxd;
+  int32 rsize = 0;
+
+
+  if (f1open)
+    rsize = DO_STDIO_READ (ifd1, &rxd, 1);
+  else
+    rsize = 0;
+  if (rsize > 0)
+    {
+      uarta_data = rxd;
+      if (uart_stat_reg & UARTA_DR)
+	{
+	  uart_stat_reg |= UARTA_OR;
+	}
+      uart_stat_reg |= UARTA_DR;
+      set_irq (3);
+    }
+  event (uart_rx, 0, UART_RX_TIME);
+}
+
+static void
+uart_intr (caddr_t arg)
+{
+  /* Check for UART interrupts every 1000 clk.  */
+  grlib_read_uart (APBUART_STATUS);
+  flush_uart ();
+  event (uart_intr, 0, UART_FLUSH_TIME);
+}
+
+
+static void
+uart_irq_start (void)
+{
+#ifdef FAST_UART
+  event (uart_intr, 0, UART_FLUSH_TIME);
+#else
+#ifndef _WIN32
+  event (uart_rx, 0, UART_RX_TIME);
+#endif
+#endif
+}
+
+/* GPTIMER.  */
+
+static void
+gpt_intr (caddr_t arg)
+{
+  int i;
+
+  for (i = 0; i < NGPTIMERS; i++)
+    {
+      if (gpt_ctrl[i] & 1)
+	{
+	  gpt_counter[i] -= 1;
+	  if (gpt_counter[i] == -1)
+	    {
+	      if (gpt_ctrl[i] & 8)
+		set_irq (GPTIMER_IRQ + i);
+	      if (gpt_ctrl[i] & 2)
+		gpt_counter[i] = gpt_reload[i];
+	    }
+	}
+    }
+  event (gpt_intr, 0, gpt_scaler + 1);
+  gpt_scaler_start = now ();
+}
+
+static void
+gpt_init (void)
+{
+  if (sis_verbose)
+    printf ("GPT started (period %d)\n\r", gpt_scaler + 1);
+
+  grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GPTIMER, 0, 8),
+		   GRLIB_PP_APBADDR (0x80000300, 0xFFF));
+}
+
+static void
+gpt_reset (void)
+{
+  event (gpt_intr, 0, gpt_scaler + 1);
+  gpt_scaler_start = now ();
+}
+
+static void
+gpt_scaler_set (uint32 val)
+{
+  /* Mask for 16-bit scaler. */
+  gpt_scaler = val & 0x0ffff;
+}
+
+static void
+timer_ctrl (uint32 val, int i)
+{
+  if (val & 4)
+    {
+      /* Reload.  */
+      gpt_counter[i] = gpt_reload[i];
+    }
+  gpt_ctrl[i] = val & 0xb;
+}
+
+/* Store data in host byte order.  MEM points to the beginning of the
+   emulated memory; WADDR contains the index the emulated memory,
+   DATA points to words in host byte order to be stored.  SZ contains log(2)
+   of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
+   2 (one word), or 3 (two words); WS should return the number of wait-states. */
+
+static void
+store_bytes (unsigned char *mem, uint32 waddr, uint32 * data, int32 sz,
+	     int32 * ws)
+{
+  switch (sz)
+    {
+    case 0:
+#ifdef HOST_LITTLE_ENDIAN
+      waddr ^= EBT;
+#endif
+      mem[waddr] = *data & 0x0ff;
+      *ws = 0;
+      break;
+    case 1:
+#ifdef HOST_LITTLE_ENDIAN
+      waddr ^= 2;
+#endif
+      memcpy (&mem[waddr], data, 2);
+      *ws = 0;
+      break;
+    case 2:
+      memcpy (&mem[waddr], data, 4);
+      *ws = 0;
+      break;
+    case 3:
+      memcpy (&mem[waddr], data, 8);
+      *ws = 0;
+      break;
+    }
+}
+
+
+/* Memory emulation.  */
+
+static int
+memory_iread (uint32 addr, uint32 * data, int32 * ws)
+{
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      memcpy (data, &ramb[addr & RAM_MASK], 4);
+      *ws = 0;
+      return 0;
+    }
+  else if (addr < ROM_END)
+    {
+      memcpy (data, &romb[addr], 4);
+      *ws = 0;
+      return 0;
+    }
+
+  if (sis_verbose)
+    printf ("Memory exception at %x (illegal address)\n", addr);
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_read (uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  int32 mexc;
+
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      memcpy (data, &ramb[addr & RAM_MASK & ~3], 4);
+      *ws = 0;
+      return 0;
+    }
+  else if ((addr >= APBPP_START) && (addr <= APBPP_END))
+    {
+      *data = grlib_apbpnp_read (addr);
+      if (sis_verbose > 1)
+	printf ("APB PP read a: %08x, d: %08x\n", addr, *data);
+      *ws = 4;
+      return 0;
+    }
+  else if ((addr >= APBSTART) && (addr < APBEND))
+    {
+      mexc = apb_read (addr, data);
+      if (mexc)
+	*ws = MEM_EX_WS;
+      else
+	*ws = 0;
+      return mexc;
+    }
+  else if ((addr >= AHBPP_START) && (addr <= AHBPP_END))
+    {
+      if (sis_verbose > 1)
+	printf ("AHB PP read a: %08x, d: %08x\n", addr, *data);
+      *data = grlib_ahbpnp_read (addr);
+      *ws = 4;
+      return 0;
+    }
+  else if (addr < ROM_END)
+    {
+      memcpy (data, &romb[addr & ~3], 4);
+      *ws = 0;
+      return 0;
+    }
+
+  if (sis_verbose)
+    printf ("Memory exception at %x (illegal address)\n", addr);
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_read_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  if (asi == 2)
+    {
+      if (addr == 0)
+	*data = cache_ctrl;
+      else
+	*data = 0;
+      return MOK;
+    }
+  else
+    return memory_read (addr, data, sz, ws);
+}
+
+static int
+memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  uint32 byte_addr;
+  uint32 byte_mask;
+  uint32 waddr;
+  uint32 *ram;
+  int32 mexc;
+  int i;
+  int wphit[2];
+
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      waddr = addr & RAM_MASK;
+      store_bytes (ramb, waddr, data, sz, ws);
+      return 0;
+    }
+  else if ((addr >= APBSTART) && (addr < APBEND))
+    {
+      if (sz != 2)
+	{
+	  *ws = MEM_EX_WS;
+	  return 1;
+	}
+      apb_write (addr, *data);
+      *ws = 0;
+      return 0;
+
+    }
+  else if (addr < ROM_END)
+    {
+      *ws = 0;
+      store_bytes (romb, addr, data, sz, ws);
+      return 0;
+    }
+
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_write_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  if (asi == 2)
+    {
+      cache_ctrl = *data & 0x81000f;
+      if (sis_verbose)
+	printf ("cache ctrl reg : 0x%08x\n", cache_ctrl);
+      return MOK;
+    }
+  else
+    return (memory_write (addr, data, sz, ws));
+}
+
+static unsigned char *
+get_mem_ptr (uint32 addr, uint32 size)
+{
+  if ((addr + size) < ROM_END)
+    {
+      return &romb[addr];
+    }
+  else if ((addr >= RAM_START) && ((addr + size) < RAM_END))
+    {
+      return &ramb[addr & RAM_MASK];
+    }
+
+  return (char *) -1;
+}
+
+static int
+sis_memory_write (uint32 addr, const unsigned char *data, uint32 length)
+{
+  char *mem;
+
+  if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
+    return 0;
+
+  memcpy (mem, data, length);
+  return length;
+}
+
+static int
+sis_memory_read (uint32 addr, char *data, uint32 length)
+{
+  char *mem;
+  int ws;
+
+  if (length == 4)
+    {
+      memory_read (addr, (uint32 *) data, length, &ws);
+      return 4;
+    }
+
+  if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
+    return 0;
+
+  memcpy (data, mem, length);
+  return length;
+}
+
+static void
+boot_init (void)
+{
+  /* Generate 1 MHz RTC tick.  */
+  apb_write (GPTIMER_SCALER, sregs.freq - 1);
+  apb_write (GPTIMER_SCLOAD, sregs.freq - 1);
+  apb_write (GPTIMER_TIMER1, -1);
+  apb_write (GPTIMER_RELOAD1, -1);
+  apb_write (GPTIMER_CTRL1, 0x7);
+
+  sregs.wim = 2;
+  sregs.psr = 0xF30010e0;
+  sregs.r[30] = RAM_END;
+  sregs.r[14] = sregs.r[30] - 96 * 4;
+  cache_ctrl = 0x81000f;
+}
+
+const struct memsys leon3 = {
+  init_sim,
+  reset,
+  error_mode,
+  sim_halt,
+  exit_sim,
+  init_stdio,
+  restore_stdio,
+  memory_iread,
+  memory_read,
+  memory_read_asi,
+  memory_write,
+  memory_write_asi,
+  sis_memory_write,
+  sis_memory_read,
+  boot_init
+};
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 935550a..8797956 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -139,7 +139,7 @@ main(argc, argv)
     for (i = 0; i < 64; i++)
 	cmdq[i] = 0;
     printf("\n SIS - SPARC instruction simulator %s,  copyright Jiri Gaisler 1995\n", sis_version);
-    printf(" Bug-reports to jgais@wd.estec.esa.nl\n\n");
+    printf (" Bug-reports to jiri@gaisler.se\n\n");
     while (stat < argc) {
 	if (argv[stat][0] == '-') {
 	    if (strcmp(argv[stat], "-v") == 0) {
@@ -178,6 +178,10 @@ main(argc, argv)
 		dumbio = 1;
 	    } else if (strcmp(argv[stat], "-nouartrx") == 0) {
 		nouartrx = 1;
+	    } else if (strcmp (argv[stat], "-leon3") == 0) {
+		ms = &leon3;
+		if (freq == 14) freq = 50;
+		cputype = CPU_LEON3;
 	    } else {
 		printf("unknown option %s\n", argv[stat]);
 		usage();
@@ -188,13 +192,19 @@ main(argc, argv)
 	}
 	stat++;
     }
+
+    switch (cputype) {
+    case CPU_LEON3:
+	printf (" LEON3 emulation enabled\n");
+	break;
+    default:
+	printf (" ERC32 emulation enabled\n");
+    }
+
     if (nfp)
-	printf("FPU disabled\n");
-#ifdef ERA
-    if (era)
-	printf("ERA ECC emulation enabled\n");
-#endif
+	printf(" FPU disabled\n");
     sregs.freq = freq;
+    printf("\n");
 
     INIT_DISASSEMBLE_INFO(dinfo, stdout, (fprintf_ftype) fprintf);
 #ifdef HOST_LITTLE_ENDIAN
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index c596a8c0..d033266 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -154,6 +154,7 @@ struct irqcell {
 #define BPT_HIT 2
 #define ERROR 3
 #define CTRL_C 4
+#define CPU_LEON3  3
 
 /* Prototypes  */
 
@@ -209,6 +210,7 @@ extern int	nouartrx;
 extern		host_callback *sim_callback;
 extern int	dumbio;
 extern int	tty_setup;
+extern int      cputype;
 
 
 /* exec.c */
@@ -239,14 +241,20 @@ struct memsys {
     void	(*init_stdio) (void);
     void	(*restore_stdio) (void);
     int	        (*memory_iread) (uint32 addr, uint32 *data, int32 *ws);
-    int	        (*memory_read) (int32 asi, uint32 addr, uint32 *data,
+    int	        (*memory_read) (uint32 addr, uint32 *data, int32 sz, int32 *ws);
+    int	        (*memory_read_asi) (int32 asi, uint32 addr, uint32 *data,
+			     int32 sz, int32 *ws);
+    int	        (*memory_write) (uint32 addr, uint32 *data, int32 sz, int32 *ws);
+    int	        (*memory_write_asi) (int32 asi, uint32 addr, uint32 *data,
 			     int32 sz, int32 *ws);
-    int	        (*memory_write) (int32 asi, uint32 addr, uint32 *data,
-			      int32 sz, int32 *ws);
     int	        (*sis_memory_write) (uint32 addr,
 				  const unsigned char *data, uint32 length);
     int	        (*sis_memory_read) (uint32 addr, char *data,
 				 uint32 length);
+    void	(*boot_init) (void);
 };
 
 extern const struct memsys *ms;
+
+/* leon3.c */
+extern const struct memsys leon3;
-- 
2.7.4

From 796df49c4823bd67127c000aff38ab789dc4cd3a Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Tue, 29 Dec 2015 20:57:59 -0500
Subject: [PATCH 05/11] sim/erc32: Add LEON2 processor emulation.

	Added memory and I/O sub-system to emulate a LEON2 processor.
	The cache and MMU are not emulated but enough functionallity
	is provided to run any RTEMS and BCC compiled application.
	The code is based on erc32.c and modified to emulate the
	LEON2 address space and peripheral operations.

	* Makefile.in : Added new object files.
	* exec.c (init_regs): Add leon2 vendor/device ID to %psr.
	* interf.c (sim_open): Add -leon2 to start-up switches.
	(sim_open): Set leon2 default frequency to 50 MHz. Print out current
	emulation mode.
	* leon2.c : New file, emulation of leon2 memory and peripherals.
	* sis.c (main): Add -leon2 switch. Set default leon2 frequency to 50 MHz.
	* sis.h: Add memsys struct for leon2.
---
 sim/erc32/Makefile.in |    2 +-
 sim/erc32/exec.c      |    3 +
 sim/erc32/interf.c    |   11 +-
 sim/erc32/leon2.c     | 1030 +++++++++++++++++++++++++++++++++++++++++++++++++
 sim/erc32/sis.c       |    7 +
 sim/erc32/sis.h       |    4 +
 6 files changed, 1054 insertions(+), 3 deletions(-)
 create mode 100644 sim/erc32/leon2.c

diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
index f062b10..1802788 100644
--- a/sim/erc32/Makefile.in
+++ b/sim/erc32/Makefile.in
@@ -22,7 +22,7 @@ TERMCAP_LIB = @TERMCAP@
 READLINE_LIB = @READLINE@
 
 # `sis' doesn't need interf.o.
-SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
+SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o leon2.o
 
 SIM_OBJS = $(SIS_OFILES) interf.o
 SIM_RUN_OBJS = sis.o
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index 2c3ceaa..3a1a48b 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -2229,6 +2229,9 @@ init_regs(sregs)
     if (cputype == CPU_LEON3)
       sregs->psr |= 0xF3000080;	/* Set supervisor bit */
     else
+    if (cputype == CPU_LEON2)
+      sregs->psr |= 0x00000080;	/* Set supervisor bit */
+    else
       sregs->psr |= 0x11000080;	/* Set supervisor bit */
     sregs->breakpoint = 0;
     sregs->annul = 0;
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 7299a7d..37d67fc 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -171,6 +171,10 @@ sim_open (kind, callback, abfd, argv)
             if (strcmp(argv[stat], "-nouartrx") == 0) {
 		nouartrx = 1;
 	    } else
+	    if (strcmp (argv[stat], "-leon2") == 0) {
+		ms = &leon2;
+		cputype = CPU_LEON2;
+	    } else
             if (strcmp (argv[stat], "-leon3") == 0) {
 		ms = &leon3;
                 cputype = CPU_LEON3;
@@ -212,15 +216,18 @@ sim_open (kind, callback, abfd, argv)
 	stat++;
     }
 
-    if (cputype == CPU_LEON3)
+    if ((cputype == CPU_LEON3) || (cputype == CPU_LEON2))
         sregs.freq = freq ? freq : 50;
     else
         sregs.freq = freq ? freq : 14;
 
     if (sis_verbose) {
 	(*sim_callback->printf_filtered) (sim_callback, "\n SIS - SPARC instruction simulator %s\n", sis_version);
-	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler ESA/ESTEC (jiri@gaisler.se)\n\n");
+	(*sim_callback->printf_filtered) (sim_callback, " Bug-reports to Jiri Gaisler (jiri@gaisler.se)\n\n");
         switch (cputype) {
+        case CPU_LEON2:
+            (*sim_callback->printf_filtered) (sim_callback, "LEON2 emulation enabled\n");
+            break;
         case CPU_LEON3:
             (*sim_callback->printf_filtered) (sim_callback, "LEON3 emulation enabled\n");
             break;
diff --git a/sim/erc32/leon2.c b/sim/erc32/leon2.c
new file mode 100644
index 0000000..87bee6a
--- /dev/null
+++ b/sim/erc32/leon2.c
@@ -0,0 +1,1030 @@
+/*
+ * This file is part of SIS.
+ *
+ * SIS, SPARC instruction simulator V2.8 Copyright (C) 2015 Jiri Gaisler
+ *
+ * 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/>.
+ *
+ * Leon2 emulation, based on leon3.c and erc32.c/
+ */
+
+/* The control space devices.  */
+
+#include "config.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include "sis.h"
+#include "grlib.h"
+#include "sim-config.h"
+
+/* APB registers */
+#define APBSTART	0x80000000
+#define APBEND		0x80000100
+
+/* Memory exception waitstates */
+#define MEM_EX_WS	1
+
+#define MOK		0
+
+/* LEON2 APB register addresses */
+
+#define IRQCTRL_IPR	0x094
+#define IRQCTRL_IMR	0x090
+#define IRQCTRL_ICR	0x09C
+#define IRQCTRL_IFR	0x098
+#define TIMER_SCALER	0x060
+#define TIMER_SCLOAD	0x064
+#define LEON2_CONFIG	0x024
+#define TIMER_TIMER1	0x040
+#define TIMER_RELOAD1	0x044
+#define TIMER_CTRL1	0x048
+#define TIMER_TIMER2	0x050
+#define TIMER_RELOAD2	0x054
+#define TIMER_CTRL2	0x058
+#define CACHE_CTRL	0x014
+#define POWER_DOWN	0x018
+
+#define APBUART_RXTX	0x070
+#define APBUART_STATUS	0x074
+
+/* Size of UART buffers (bytes).  */
+#define UARTBUF	1024
+
+/* Number of simulator ticks between flushing the UARTS.  */
+/* For good performance, keep above 1000.  */
+#define UART_FLUSH_TIME	  3000
+
+/* New uart defines.  */
+#define UART_TX_TIME	1000
+#define UART_RX_TIME	1000
+#define UARTA_DR	0x1
+#define UARTA_SRE	0x2
+#define UARTA_HRE	0x4
+#define UARTA_OR	0x10
+
+/* IRQCTRL registers.  */
+
+static uint32 irqctrl_ipr;
+static uint32 irqctrl_imr;
+static uint32 irqctrl_ifr;
+
+/* TIMER registers.  */
+
+#define NTIMERS		2
+#define TIMER_IRQ	8
+
+static uint32 gpt_scaler;
+static uint32 gpt_scaler_start;
+static uint32 gpt_counter[NTIMERS];
+static uint32 gpt_reload[NTIMERS];
+static uint32 gpt_ctrl[NTIMERS];
+
+/* ROM size 16 Mbyte.  */
+#define ROM_START	0x00000000
+#define ROM_MASK	0x00ffffff
+#define ROM_END		(ROM_START + ROM_MASK + 1)
+
+/* RAM size 16 Mbyte.  */
+#define RAM_START	0x40000000
+#define RAM_MASK	0x00ffffff
+#define RAM_END		(RAM_START + RAM_MASK + 1)
+
+/* Memory.  */
+static unsigned char romb[ROM_END - ROM_START];
+static unsigned char ramb[RAM_END - RAM_START];
+static uint32 cache_ctrl;
+
+
+/* UART support variables.  */
+
+/* File descriptor for input file.  */
+static int32 fd1, fd2;
+
+/* UART status register */
+static int32 Ucontrol;
+
+static unsigned char aq[UARTBUF], bq[UARTBUF];
+static int32 anum, aind = 0;
+static int32 bnum, bind = 0;
+static char wbufa[UARTBUF], wbufb[UARTBUF];
+static unsigned wnuma;
+static unsigned wnumb;
+static FILE *f1in, *f1out;
+static struct termios ioc1, ioc2, iocold1, iocold2;
+static int f1open = 0;
+
+static char uarta_sreg, uarta_hreg;
+static uint32 uart_stat_reg;
+static uint32 uarta_data;
+
+/* Forward declarations. */
+
+static void mem_init (void);
+static void close_port (void);
+static void leon2_reset (void);
+static void irqctrl_intack (int32 level);
+static void chk_irq (void);
+static void set_irq (int32 level);
+static int32 apb_read (uint32 addr, uint32 * data);
+static int apb_write (uint32 addr, uint32 data);
+static void port_init (void);
+static uint32 grlib_read_uart (uint32 addr);
+static void grlib_write_uart (uint32 addr, uint32 data);
+static void flush_uart (void);
+static void uarta_tx (void);
+static void uart_rx (caddr_t arg);
+static void uart_intr (caddr_t arg);
+static void uart_irq_start (void);
+static void gpt_intr (caddr_t arg);
+static void gpt_init (void);
+static void gpt_reset (void);
+static void gpt_scaler_set (uint32 val);
+static void timer_ctrl (uint32 val, int i);
+static unsigned char *get_mem_ptr (uint32 addr, uint32 size);
+static void store_bytes (unsigned char *mem, uint32 waddr,
+			 uint32 * data, int sz, int32 * ws);
+
+static host_callback *callback;
+
+
+/* One-time init. */
+
+static void
+init_sim (void)
+{
+  callback = sim_callback;
+  grlib_init ();
+  mem_init ();
+  port_init ();
+  gpt_init ();
+}
+
+/* Power-on reset init. */
+
+static void
+reset (void)
+{
+  leon2_reset ();
+  uart_irq_start ();
+  gpt_reset ();
+}
+
+/* IU error mode manager. */
+
+static void
+error_mode (uint32 pc)
+{
+
+}
+
+/* Memory init. */
+
+static void
+mem_init (void)
+{
+
+  if (sis_verbose)
+    printf ("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n",
+	    RAM_START, (RAM_MASK + 1) / 1024, (ROM_MASK + 1) / 1024);
+}
+
+/* Flush ports when simulator stops. */
+
+static void
+sim_halt (void)
+{
+#ifdef FAST_UART
+  flush_uart ();
+#endif
+}
+
+static void
+close_port (void)
+{
+  if (f1open && f1in != stdin)
+    fclose (f1in);
+}
+
+static void
+exit_sim (void)
+{
+  close_port ();
+}
+
+static void
+leon2_reset (void)
+{
+  int i;
+
+  irqctrl_ipr = 0;
+  irqctrl_imr = 0;
+  irqctrl_ifr = 0;
+
+  wnuma = wnumb = 0;
+  anum = aind = bnum = bind = 0;
+
+  uart_stat_reg = UARTA_SRE | UARTA_HRE;
+
+  gpt_counter[0] = 0xffffffff;
+  gpt_reload[0] = 0xffffffff;
+  gpt_scaler = 0xffff;
+  gpt_ctrl[0] = 0;
+  gpt_ctrl[1] = 0;
+}
+
+static void
+irqctrl_intack (int32 level)
+{
+  int irq_test;
+
+  if (sis_verbose > 2)
+    printf ("interrupt %d acknowledged\n", level);
+  if (irqctrl_ifr & (1 << level))
+    irqctrl_ifr &= ~(1 << level);
+  else
+    irqctrl_ipr &= ~(1 << level);
+  chk_irq ();
+}
+
+static void
+chk_irq (void)
+{
+  int32 i;
+  uint32 itmp;
+  int old_irl;
+
+  old_irl = ext_irl;
+  itmp = ((irqctrl_ipr | irqctrl_ifr) & irqctrl_imr) & 0x0fffe;
+  ext_irl = 0;
+  if (itmp != 0)
+    {
+      for (i = 15; i > 0; i--)
+	{
+	  if (((itmp >> i) & 1) != 0)
+	    {
+	      if ((sis_verbose > 2) && (i > old_irl))
+		printf ("IU irl: %d\n", i);
+	      ext_irl = i;
+	      set_int (i, irqctrl_intack, i);
+	      break;
+	    }
+	}
+    }
+}
+
+static void
+set_irq (int32 level)
+{
+  irqctrl_ipr |= (1 << level);
+  chk_irq ();
+}
+
+static int32
+apb_read (uint32 addr, uint32 * data)
+{
+
+  switch (addr & 0xfff)
+    {
+
+    case APBUART_RXTX:		/* 0x100 */
+    case APBUART_STATUS:	/* 0x104 */
+      *data = grlib_read_uart (addr);
+      break;
+
+    case IRQCTRL_IPR:		/* 0x204 */
+      *data = irqctrl_ipr;
+      break;
+
+    case IRQCTRL_IFR:		/* 0x208 */
+      *data = irqctrl_ifr;
+      break;
+
+    case IRQCTRL_IMR:		/* 0x240 */
+      *data = irqctrl_imr;
+      break;
+
+    case TIMER_SCALER:		/* 0x300 */
+      *data = gpt_scaler - (now () - gpt_scaler_start);
+      break;
+
+    case TIMER_SCLOAD:		/* 0x304 */
+      *data = gpt_scaler;
+      break;
+
+    case LEON2_CONFIG:		/* 0x308 */
+      *data = 0x700310;
+      break;
+
+    case TIMER_TIMER1:		/* 0x310 */
+      *data = gpt_counter[0];
+      break;
+
+    case TIMER_RELOAD1:	/* 0x314 */
+      *data = gpt_reload[0];
+      break;
+
+    case TIMER_CTRL1:		/* 0x318 */
+      *data = gpt_ctrl[0];
+      break;
+
+    case TIMER_TIMER2:		/* 0x320 */
+      *data = gpt_counter[1];
+      break;
+
+    case TIMER_RELOAD2:	/* 0x324 */
+      *data = gpt_reload[1];
+      break;
+
+    case TIMER_CTRL2:		/* 0x328 */
+      *data = gpt_ctrl[1];
+      break;
+
+    case CACHE_CTRL:		/* 0x328 */
+      *data = cache_ctrl;
+      break;
+
+    default:
+      *data = 0;
+      break;
+    }
+
+  if (sis_verbose > 1)
+    printf ("APB read  a: %08x, d: %08x\n", addr, *data);
+
+  return MOK;
+}
+
+static int
+apb_write (uint32 addr, uint32 data)
+{
+  if (sis_verbose > 1)
+    printf ("APB write a: %08x, d: %08x\n", addr, data);
+  switch (addr & 0xff)
+    {
+
+    case APBUART_RXTX:		/* 0x100 */
+    case APBUART_STATUS:	/* 0x104 */
+      grlib_write_uart (addr, data);
+      break;
+
+    case IRQCTRL_IFR:		/* 0x208 */
+      irqctrl_ifr = data & 0xfffe;
+      chk_irq ();
+      break;
+
+    case IRQCTRL_ICR:		/* 0x20C */
+      irqctrl_ipr &= ~data & 0x0fffe;
+      chk_irq ();
+      break;
+
+    case IRQCTRL_IMR:		/* 0x240 */
+      irqctrl_imr = data & 0x7ffe;
+      chk_irq ();
+      break;
+
+    case TIMER_SCLOAD:		/* 0x304 */
+      gpt_scaler_set (data);
+      break;
+
+    case TIMER_TIMER1:		/* 0x310 */
+      gpt_counter[0] = data;
+      break;
+
+    case TIMER_RELOAD1:	/* 0x314 */
+      gpt_reload[0] = data;
+      break;
+
+    case TIMER_CTRL1:		/* 0x318 */
+      timer_ctrl (data, 0);
+      break;
+
+    case TIMER_TIMER2:		/* 0x320 */
+      gpt_counter[1] = data;
+      break;
+
+    case TIMER_RELOAD2:	/* 0x324 */
+      gpt_reload[1] = data;
+      break;
+
+    case TIMER_CTRL2:		/* 0x328 */
+      timer_ctrl (data, 1);
+      break;
+
+    case POWER_DOWN:		/* 0x328 */
+      wait_for_irq ();
+      break;
+
+    case CACHE_CTRL:		/* 0x328 */
+      cache_ctrl = data & 0x1000f;
+      break;
+
+    default:
+      break;
+    }
+  return MOK;
+}
+
+
+/* APBUART. */
+
+static int ifd1 = -1, ofd1 = -1;
+
+static void
+init_stdio (void)
+{
+  if (dumbio)
+    return;
+  if (ifd1 == 0 && f1open)
+    {
+      tcsetattr (0, TCSANOW, &ioc1);
+      tcflush (ifd1, TCIFLUSH);
+    }
+}
+
+static void
+restore_stdio (void)
+{
+  if (dumbio)
+    return;
+  if (ifd1 == 0 && f1open && tty_setup)
+    tcsetattr (0, TCSANOW, &iocold1);
+}
+
+#define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
+		( dumbio || nouartrx \
+		? (0) /* no bytes read, no delay */   \
+		: (_fd_) == 1 && callback ? \
+		callback->read_stdin (callback, _buf_, _len_) :  \
+		read( _fd_, _buf_, _len_ ) )
+
+static void
+port_init (void)
+{
+  f1in = stdin;
+  f1out = stdout;
+  if (uart_dev1[0] != 0)
+    if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0)
+      printf ("Warning, couldn't open output device %s\n", uart_dev1);
+    else
+      {
+	if (sis_verbose)
+	  printf ("serial port A on %s\n", uart_dev1);
+	f1in = f1out = fdopen (fd1, "r+");
+	setbuf (f1out, NULL);
+	f1open = 1;
+      }
+  if (f1in)
+    ifd1 = fileno (f1in);
+  if (ifd1 == 0)
+    {
+      if (callback && !callback->isatty (callback, ifd1))
+	tty_setup = 0;
+      if (sis_verbose)
+	printf ("serial port A on stdin/stdout\n");
+      if (!dumbio)
+	{
+	  tcgetattr (ifd1, &ioc1);
+	  if (tty_setup)
+	    {
+	      iocold1 = ioc1;
+	      ioc1.c_lflag &= ~(ICANON | ECHO);
+	      ioc1.c_cc[VMIN] = 0;
+	      ioc1.c_cc[VTIME] = 0;
+	    }
+	}
+      f1open = 1;
+    }
+
+  if (f1out)
+    {
+      ofd1 = fileno (f1out);
+      if (!dumbio && tty_setup && ofd1 == 1)
+	setbuf (f1out, NULL);
+    }
+
+  wnuma = 0;
+}
+
+static uint32
+grlib_read_uart (uint32 addr)
+{
+
+  unsigned tmp = 0;
+
+  switch (addr & 0xfff)
+    {
+
+    case 0x070:		/* UART 1 RX/TX */
+#ifndef _WIN32
+#ifdef FAST_UART
+      if (aind < anum)
+	{
+	  if ((aind + 1) < anum)
+	    set_irq (3);
+	  return (uint32) aq[aind++];
+	}
+      else
+	{
+	  if (f1open)
+	    anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
+	  else
+	    anum = 0;
+	  if (anum > 0)
+	    {
+	      aind = 0;
+	      if ((aind + 1) < anum)
+		set_irq (3);
+	      return (uint32) aq[aind++];
+	    }
+	  else
+	    return (uint32) aq[aind];
+	}
+#else
+      tmp = uarta_data;
+      uarta_data &= ~UART_DR;
+      uart_stat_reg &= ~UARTA_DR;
+      return tmp;
+#endif
+#else
+      return 0;
+#endif
+      break;
+
+    case 0x074:		/* UART status register  */
+#ifndef _WIN32
+#ifdef FAST_UART
+
+      Ucontrol = 0;
+      if (aind < anum)
+	Ucontrol |= 0x00000001;
+      else
+	{
+	  if (f1open)
+	    anum = DO_STDIO_READ (ifd1, aq, UARTBUF);
+	  else
+	    anum = 0;
+	  if (anum > 0)
+	    {
+	      Ucontrol |= 0x00000001;
+	      aind = 0;
+	      set_irq (3);
+	    }
+	}
+      Ucontrol |= 0x00000006;
+      return Ucontrol;
+#else
+      return uart_stat_reg;
+#endif
+#else
+      return 0x00060006;
+#endif
+      break;
+    default:
+      if (sis_verbose)
+	printf ("Read from unimplemented LEON2 register (%x)\n", addr);
+
+    }
+  return 0;
+}
+
+static void
+grlib_write_uart (uint32 addr, uint32 data)
+{
+  unsigned char c;
+
+  c = (unsigned char) data;
+  switch (addr & 0xfff)
+    {
+
+    case 0x070:		/* UART A */
+#ifdef FAST_UART
+      if (f1open)
+	{
+	  if (wnuma < UARTBUF)
+	    wbufa[wnuma++] = c;
+	  else
+	    {
+	      while (wnuma)
+		{
+		  if (ofd1 == 1 && callback)
+		    wnuma -= callback->write_stdout (callback, wbufa, wnuma);
+		  else
+		    wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+		}
+	      wbufa[wnuma++] = c;
+	    }
+	}
+      set_irq (3);
+#else
+      if (uart_stat_reg & UARTA_SRE)
+	{
+	  uarta_sreg = c;
+	  uart_stat_reg &= ~UARTA_SRE;
+	  event (uarta_tx, 0, UART_TX_TIME);
+	}
+      else
+	{
+	  uarta_hreg = c;
+	  uart_stat_reg &= ~UARTA_HRE;
+	}
+#endif
+      break;
+
+    case 0x074:		/* UART status register */
+#ifndef FAST_UART
+      uart_stat_reg &= 1;
+#endif
+      break;
+    default:
+      if (sis_verbose)
+	printf ("Write to unimplemented APB register (%x)\n", addr);
+
+    }
+}
+
+static void
+flush_uart (void)
+{
+  while (wnuma && f1open)
+    {
+      if (ofd1 == 1 && callback)
+	{
+	  wnuma -= callback->write_stdout (callback, wbufa, wnuma);
+	  callback->flush_stdout (callback);
+	}
+      else
+	wnuma -= fwrite (wbufa, 1, wnuma, f1out);
+    }
+}
+
+static void
+uarta_tx (void)
+{
+  while (f1open)
+    {
+      if (ofd1 == 1 && callback)
+	while (callback->write_stdout (callback, &uarta_sreg, 1) != 1)
+	  continue;
+      else
+	while (fwrite (&uarta_sreg, 1, 1, f1out) != 1)
+	  continue;
+    }
+  if (uart_stat_reg & UARTA_HRE)
+    {
+      uart_stat_reg |= UARTA_SRE;
+    }
+  else
+    {
+      uarta_sreg = uarta_hreg;
+      uart_stat_reg |= UARTA_HRE;
+      event (uarta_tx, 0, UART_TX_TIME);
+    }
+  set_irq (3);
+}
+
+static void
+uart_rx (caddr_t arg)
+{
+  char rxd;
+  int32 rsize = 0;
+
+  if (f1open)
+    rsize = DO_STDIO_READ (ifd1, &rxd, 1);
+  else
+    rsize = 0;
+  if (rsize > 0)
+    {
+      uarta_data = rxd;
+      if (uart_stat_reg & UARTA_DR)
+	{
+	  uart_stat_reg |= UARTA_OR;
+	}
+      uart_stat_reg |= UARTA_DR;
+      set_irq (3);
+    }
+  event (uart_rx, 0, UART_RX_TIME);
+}
+
+static void
+uart_intr (caddr_t arg)
+{
+  /* Check for UART interrupts every 1000 clk.  */
+  grlib_read_uart (APBUART_STATUS);
+  flush_uart ();
+  event (uart_intr, 0, UART_FLUSH_TIME);
+}
+
+
+static void
+uart_irq_start (void)
+{
+#ifdef FAST_UART
+  event (uart_intr, 0, UART_FLUSH_TIME);
+#else
+#ifndef _WIN32
+  event (uart_rx, 0, UART_RX_TIME);
+#endif
+#endif
+}
+
+/* TIMER */
+
+static void
+gpt_intr (caddr_t arg)
+{
+  int i;
+
+  for (i = 0; i < NTIMERS; i++)
+    {
+      if (gpt_ctrl[i] & 1)
+	{
+	  gpt_counter[i] -= 1;
+	  if (gpt_counter[i] == -1)
+	    {
+	      set_irq (TIMER_IRQ + i);
+	      if (gpt_ctrl[i] & 2)
+		gpt_counter[i] = gpt_reload[i];
+	    }
+	}
+    }
+  event (gpt_intr, 0, gpt_scaler + 1);
+  gpt_scaler_start = now ();
+}
+
+static void
+gpt_init (void)
+{
+  if (sis_verbose)
+    printf ("GPT started (period %d)\n\r", gpt_scaler + 1);
+}
+
+static void
+gpt_reset (void)
+{
+  event (gpt_intr, 0, gpt_scaler + 1);
+  gpt_scaler_start = now ();
+}
+
+static void
+gpt_scaler_set (uint32 val)
+{
+  /* Mask for 16-bit scaler. */
+  gpt_scaler = val & 0x0ffff;
+}
+
+static void
+timer_ctrl (uint32 val, int i)
+{
+  if (val & 4)
+    {
+      /* Reload.  */
+      gpt_counter[i] = gpt_reload[i];
+    }
+  gpt_ctrl[i] = val & 0xb;
+}
+
+/* Store data in host byte order.  MEM points to the beginning of the
+   emulated memory; WADDR contains the index the emulated memory,
+   DATA points to words in host byte order to be stored.  SZ contains log(2)
+   of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word),
+   2 (one word), or 3 (two words); WS should return the number of wait-states. */
+
+static void
+store_bytes (unsigned char *mem, uint32 waddr, uint32 * data, int32 sz,
+	     int32 * ws)
+{
+  switch (sz)
+    {
+    case 0:
+#ifdef HOST_LITTLE_ENDIAN
+      waddr ^= EBT;
+#endif
+      mem[waddr] = *data & 0x0ff;
+      *ws = 0;
+      break;
+    case 1:
+#ifdef HOST_LITTLE_ENDIAN
+      waddr ^= 2;
+#endif
+      memcpy (&mem[waddr], data, 2);
+      *ws = 0;
+      break;
+    case 2:
+      memcpy (&mem[waddr], data, 4);
+      *ws = 0;
+      break;
+    case 3:
+      memcpy (&mem[waddr], data, 8);
+      *ws = 0;
+      break;
+    }
+}
+
+
+/* Memory emulation.  */
+
+static int
+memory_iread (uint32 addr, uint32 * data, int32 * ws)
+{
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      memcpy (data, &ramb[addr & RAM_MASK], 4);
+      *ws = 0;
+      return 0;
+    }
+  else if (addr < ROM_END)
+    {
+      memcpy (data, &romb[addr], 4);
+      *ws = 0;
+      return 0;
+    }
+
+  if (sis_verbose)
+    printf ("Memory exception at %x (illegal address)\n", addr);
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_read (uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  int32 mexc;
+
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      memcpy (data, &ramb[addr & RAM_MASK & ~3], 4);
+      *ws = 0;
+      return 0;
+    }
+  else if ((addr >= APBSTART) && (addr < APBEND))
+    {
+      mexc = apb_read (addr, data);
+      if (mexc)
+	*ws = MEM_EX_WS;
+      else
+	*ws = 0;
+      return mexc;
+    }
+  else if (addr < ROM_END)
+    {
+      memcpy (data, &romb[addr & ~3], 4);
+      *ws = 0;
+      return 0;
+    }
+
+  if (sis_verbose)
+    printf ("Memory exception at %x (illegal address)\n", addr);
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_read_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  return memory_read (addr, data, sz, ws);
+}
+
+static int
+memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  uint32 byte_addr;
+  uint32 byte_mask;
+  uint32 waddr;
+  uint32 *ram;
+  int32 mexc;
+  int i;
+  int wphit[2];
+
+  if ((addr >= RAM_START) && (addr < RAM_END))
+    {
+      waddr = addr & RAM_MASK;
+      store_bytes (ramb, waddr, data, sz, ws);
+      return 0;
+    }
+  else if ((addr >= APBSTART) && (addr < APBEND))
+    {
+      if (sz != 2)
+	{
+	  *ws = MEM_EX_WS;
+	  return 1;
+	}
+      apb_write (addr, *data);
+      *ws = 0;
+      return 0;
+    }
+  else if (addr < ROM_END)
+    {
+      *ws = 0;
+      store_bytes (romb, addr, data, sz, ws);
+      return 0;
+    }
+
+  *ws = MEM_EX_WS;
+  return 1;
+}
+
+static int
+memory_write_asi (int32 asi, uint32 addr, uint32 * data, int32 sz, int32 * ws)
+{
+  return memory_write (addr, data, sz, ws);
+}
+
+static unsigned char *
+get_mem_ptr (uint32 addr, uint32 size)
+{
+  if ((addr + size) < ROM_END)
+    {
+      return &romb[addr];
+    }
+  else if ((addr >= RAM_START) && ((addr + size) < RAM_END))
+    {
+      return &ramb[addr & RAM_MASK];
+    }
+
+  return (char *) -1;
+}
+
+static int
+sis_memory_write (uint32 addr, const unsigned char *data, uint32 length)
+{
+  char *mem;
+
+  if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
+    return 0;
+
+  memcpy (mem, data, length);
+  return length;
+}
+
+static int
+sis_memory_read (uint32 addr, char *data, uint32 length)
+{
+  char *mem;
+  int ws;
+  int w4;
+
+  if (length == 4)
+    {
+      memory_read (addr, &w4, length, &ws);
+      memcpy (data, &w4, length);
+      return 4;
+    }
+
+  if ((mem = get_mem_ptr (addr, length)) == ((char *) -1))
+    return 0;
+
+  memcpy (data, mem, length);
+  return length;
+}
+
+static void
+boot_init (void)
+{
+  /* Generate 1 MHz RTC tick.  */
+  apb_write (TIMER_SCALER, sregs.freq - 1);
+  apb_write (TIMER_SCLOAD, sregs.freq - 1);
+  apb_write (TIMER_TIMER1, -1);
+  apb_write (TIMER_RELOAD1, -1);
+  apb_write (TIMER_CTRL1, 0x7);
+
+  sregs.wim = 2;
+  sregs.psr = 0x000010e0;
+  sregs.r[30] = RAM_END;
+  sregs.r[14] = sregs.r[30] - 96 * 4;
+  cache_ctrl = 0x01000f;
+}
+
+const struct memsys leon2 = {
+  init_sim,
+  reset,
+  error_mode,
+  sim_halt,
+  exit_sim,
+  init_stdio,
+  restore_stdio,
+  memory_iread,
+  memory_read,
+  memory_read_asi,
+  memory_write,
+  memory_write_asi,
+  sis_memory_write,
+  sis_memory_read,
+  boot_init
+};
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 8797956..b60a8e2 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -178,6 +178,10 @@ main(argc, argv)
 		dumbio = 1;
 	    } else if (strcmp(argv[stat], "-nouartrx") == 0) {
 		nouartrx = 1;
+	    } else if (strcmp (argv[stat], "-leon2") == 0) {
+		ms = &leon2;
+		if (freq == 14) freq = 50;
+		cputype = CPU_LEON2;
 	    } else if (strcmp (argv[stat], "-leon3") == 0) {
 		ms = &leon3;
 		if (freq == 14) freq = 50;
@@ -194,6 +198,9 @@ main(argc, argv)
     }
 
     switch (cputype) {
+    case CPU_LEON2:
+	printf (" LEON2 emulation enabled\n");
+	break;
     case CPU_LEON3:
 	printf (" LEON3 emulation enabled\n");
 	break;
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index d033266..ba1c420 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -154,6 +154,7 @@ struct irqcell {
 #define BPT_HIT 2
 #define ERROR 3
 #define CTRL_C 4
+#define CPU_LEON2  2
 #define CPU_LEON3  3
 
 /* Prototypes  */
@@ -256,5 +257,8 @@ struct memsys {
 
 extern const struct memsys *ms;
 
+/* leon2.c */
+extern const struct memsys leon2;
+
 /* leon3.c */
 extern const struct memsys leon3;
-- 
2.7.4

From 535876ec3f4b8ae045672dc4fbe723f477d77668 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Sat, 29 Jul 2017 21:06:26 +0200
Subject: [PATCH 06/11] sim/erc32: Add watchpoint support for sparc simulator.

	Added watchpoint support to break on either data read or writes.
	Watchpoints are controlled through new commands: wp, +wpr, -wpr,
	+wrw, -wpw.

	* exec.c (wpmask): New function to calculate data size.
	(dispatch_instruction): Break simulation on watchpoint hit.

	* func.c (exec_cmd): Implement new watchpoint commands.
	(check_wpr, check_wpw): New functions to match watchpoints.

	* interf.c (run_sim): Watchpoint handling when simulator runs in gdb.

	* sis.h: New variables to hold watchpoint array. New function definitions.
---
 sim/erc32/exec.c   | 56 ++++++++++++++++++++++++++-------
 sim/erc32/func.c   | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sim/erc32/interf.c |  3 +-
 sim/erc32/sis.c    | 32 ++++++++++++++-----
 sim/erc32/sis.h    | 25 +++++++++++++--
 5 files changed, 182 insertions(+), 24 deletions(-)

diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
index 3a1a48b..ce5a729 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -393,6 +393,20 @@ extract_byte_signed (uint32 data, uint32 address)
     return tmp;
 }
 
+/* Decode watchpoint address mask from opcode. Not correct for LDST,
+   SWAP and STFSR but watchpoints will work anyway. */
+
+static unsigned char
+wpmask(uint32 op3)
+{
+    switch (op3 & 3) {
+      case 0: return(3);  /* word */
+      case 1: return(0);  /* byte */
+      case 2: return(1);  /* half-word */
+      case 3: return(7);  /* double word */
+    }
+}
+
 int
 dispatch_instruction(sregs)
     struct pstate  *sregs;
@@ -696,6 +710,12 @@ dispatch_instruction(sregs)
 		}
 		if (eicc & 1) {
 		    sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
+		    if ((sregs->trap == 129) && (sis_gdb_break) &&
+				(sregs->inst == 0x91d02001))
+		    {
+			sregs->trap = WPT_TRAP;
+			sregs->bphit = 1;
+		    }
 		}
 		break;
 
@@ -1201,18 +1221,25 @@ dispatch_instruction(sregs)
 
 	address = rs1 + operand2;
 
-	if (sregs->psr & PSR_S)
-	    asi = 11;
-	 else
-	    asi = 10;
-
 	if (op3 & 4) {
 	    sregs->icnt = T_ST;	/* Set store instruction count */
+	    if (sregs->wpwnum) {
+	       if (sregs->wphit = check_wpw(sregs, address, wpmask(op3))) {
+	           sregs->trap = WPT_TRAP;
+		   break;
+	       }
+	    }
 #ifdef STAT
 	    sregs->nstore++;
 #endif
 	} else {
 	    sregs->icnt = T_LD;	/* Set load instruction count */
+	    if (sregs->wprnum) {
+	       if (sregs->wphit = check_wpr(sregs, address, wpmask(op3))) {
+	           sregs->trap = WPT_TRAP;
+		   break;
+	       }
+	    }
 #ifdef STAT
 	    sregs->nload++;
 #endif
@@ -2155,12 +2182,18 @@ execute_trap(sregs)
 {
     int32           cwp;
 
-    if (sregs->trap == 256) {
-	sregs->pc = 0;
-	sregs->npc = 4;
-	sregs->trap = 0;
-    } else if (sregs->trap == 257) {
-	    return ERROR;
+    if (sregs->trap >= 256) {
+	switch (sregs->trap) {
+	case 256:
+	    sregs->pc = 0;
+	    sregs->npc = 4;
+	    sregs->trap = 0;
+	    break;
+	case ERROR_TRAP:
+	    return (ERROR);
+	case WPT_TRAP:
+	    return (WPT_HIT);
+	}
     } else {
 
 	if ((sregs->psr & PSR_ET) == 0)
@@ -2253,6 +2286,7 @@ init_regs(sregs)
     sregs->fpu_pres = !nfp;
     set_fsr(sregs->fsr);
     sregs->bphit = 0;
+    sregs->wphit = 0;
     sregs->ildreg = 0;
     sregs->ildtime = 0;
 
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index ada4d28..d4fe8ea 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -59,7 +59,8 @@ uint32		last_load_addr = 0;
 int		nouartrx = 0;
 host_callback 	*sim_callback;
 const struct memsys *ms = &erc32sys;
-int		cputype = 0;		/* 0 = erc32, 3 = leon3 */
+int		cputype = 0;		/* 0 = erc32, 2 = leon2,3 = leon3 */
+int             sis_gdb_break;
 
 #ifdef ERRINJ
 uint32		errcnt = 0;
@@ -620,6 +621,53 @@ exec_cmd(struct pstate *sregs, const char *cmd)
 	    stat = run_sim(sregs, UINT64_MAX, 0);
 	    daddr = sregs->pc;
 	    ms->sim_halt ();
+	} else if (strncmp(cmd1, "wp", clen) == 0) {
+	    for (i = 0; i < sregs->wprnum; i++) {
+		printf("  %d : 0x%08x (read)\n", i + 1, sregs->wprs[i]);
+	    }
+	    for (i = 0; i < sregs->wpwnum; i++) {
+		printf("  %d : 0x%08x (write)\n", i + 1, sregs->wpws[i]);
+	    }
+	} else if (strncmp(cmd1, "+wpr", clen) == 0) {
+	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+		sregs->wprs[sregs->wprnum] = VAL(cmd1) & ~0x3;
+		sregs->wprm[sregs->wprnum] = 3;
+		printf("added read watchpoint %d at 0x%08x\n",
+		       sregs->wprnum + 1, sregs->wprs[sregs->wprnum]);
+		sregs->wprnum += 1;
+	    }
+	} else if (strncmp(cmd1, "-wpr", clen) == 0) {
+	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+		i = VAL(cmd1) - 1;
+		if ((i >= 0) && (i < sregs->wprnum)) {
+		    printf("deleted read watchpoint %d at 0x%08x\n", i + 1,
+			   sregs->wprs[i]);
+		    for (; i < sregs->wprnum - 1; i++) {
+			sregs->wprs[i] = sregs->wprs[i + 1];
+		    }
+		    sregs->wprnum -= 1;
+		}
+	    }
+	} else if (strncmp(cmd1, "+wpw", clen) == 0) {
+	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+		sregs->wpws[sregs->wpwnum] = VAL(cmd1) & ~0x3;
+		sregs->wpwm[sregs->wpwnum] = 3;
+		printf("added write watchpoint %d at 0x%08x\n",
+		       sregs->wpwnum + 1, sregs->wpws[sregs->wpwnum]);
+		sregs->wpwnum += 1;
+	    }
+	} else if (strncmp(cmd1, "-wpw", clen) == 0) {
+	    if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+		i = VAL(cmd1) - 1;
+		if ((i >= 0) && (i < sregs->wpwnum)) {
+		    printf("deleted write watchpoint %d at 0x%08x\n", i + 1,
+			   sregs->wpws[i]);
+		    for (; i < sregs->wpwnum - 1; i++) {
+			sregs->wpws[i] = sregs->wpws[i + 1];
+		    }
+		    sregs->wpwnum -= 1;
+		}
+	    }
 	} else
 	    printf("syntax error\n");
     }
@@ -710,6 +758,8 @@ init_bpt(sregs)
     struct pstate  *sregs;
 {
     sregs->bptnum = 0;
+    sregs->wprnum = 0;
+    sregs->wpwnum = 0;
     sregs->histlen = 0;
     sregs->histind = 0;
     sregs->histbuf = NULL;
@@ -1017,6 +1067,44 @@ check_bpt(sregs)
     return 0;
 }
 
+int
+check_wpr(sregs, address, mask)
+    struct pstate  *sregs;
+    int32          address;
+    unsigned char  mask;
+{
+    int32           i, msk;
+
+    for (i = 0; i < sregs->wprnum; i++) {
+	msk = ~(mask | sregs->wprm[i]);
+	if (((address ^ sregs->wprs[i]) & msk) == 0) {
+	    sregs->wpaddress = address;
+            if (sregs->wphit) return (0);
+	    return (WPT_HIT);
+	}
+    }
+    return (0);
+}
+
+int
+check_wpw(sregs, address, mask)
+    struct pstate  *sregs;
+    int32          address;
+    unsigned char  mask;
+{
+    int32           i, msk;
+
+    for (i = 0; i < sregs->wpwnum; i++) {
+	msk = ~(mask | sregs->wpwm[i]);
+	if (((address ^ sregs->wpws[i]) & msk) == 0) {
+	    sregs->wpaddress = address;
+            if (sregs->wphit) return (0);
+	    return (WPT_HIT);
+	}
+    }
+    return (0);
+}
+
 void
 reset_all()
 {
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 37d67fc..fa0ab35 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -33,8 +33,6 @@
 
 #define PSR_CWP 0x7
 
-int             sis_gdb_break = 1;
-
 int
 run_sim(sregs, icount, dis)
     struct pstate  *sregs;
@@ -147,6 +145,7 @@ sim_open (kind, callback, abfd, argv)
 
     sim_callback = callback;
 
+    sis_gdb_break = 1;
     argc = countargv (argv);
     while (stat < argc) {
 	if (argv[stat][0] == '-') {
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index b60a8e2..689d17e 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -72,11 +72,7 @@ run_sim(sregs, icount, dis)
 		    sregs->trap = I_ACC_EXC;
 		} else {
 		    if (deb) {
-			if ((sregs->bphit = check_bpt(sregs)) != 0) {
-			    ms->restore_stdio ();
-			    return BPT_HIT;
-			}
-		        if (sregs->histlen) {
+			if (sregs->histlen) {
 			    sregs->histbuf[sregs->histind].addr = sregs->pc;
 			    sregs->histbuf[sregs->histind].time = ebase.simtime;
 			    sregs->histind++;
@@ -87,14 +83,25 @@ run_sim(sregs, icount, dis)
 			    printf(" %8" PRIu64 " ", ebase.simtime);
 			    dis_mem(sregs->pc, 1, &dinfo);
 			}
+			if ((sregs->bptnum) && (sregs->bphit = check_bpt(sregs)))
+			    icount = 0;
+			else {
+			    dispatch_instruction(sregs);
+			    icount--;
+			}
+		    } else {
+			dispatch_instruction(sregs);
+			icount--;
 		    }
-		    dispatch_instruction(sregs);
-		    icount--;
 		}
 	    }
 	    if (sregs->trap) {
 		irq = 0;
-		sregs->err_mode = execute_trap(sregs);
+		if ((sregs->err_mode = execute_trap(sregs)) == WPT_HIT) {
+		    sregs->err_mode = 0;
+		    sregs->trap = 0;
+		    icount = 0;
+		}
 		if (sregs->err_mode) {
 		    ms->error_mode (sregs->pc);
 		    icount = 0;
@@ -115,6 +122,10 @@ run_sim(sregs, icount, dis)
 	ctrl_c = 0;
 	return CTRL_C;
     }
+    if (sregs->bphit)
+	return (BPT_HIT);
+    if (sregs->wphit)
+	return (WPT_HIT);
     return TIME_OUT;
 }
 
@@ -278,6 +289,11 @@ main(argc, argv)
 	    printf(" %8" PRIu64 " ", ebase.simtime);
 	    dis_mem(sregs.pc, 1, &dinfo);
 	    break;
+	case WPT_HIT:
+	    printf("watchpoint at 0x%08x reached, pc = 0x%08x\n",
+	        sregs.wpaddress, sregs.pc);
+	    sregs.wphit = 1;
+	    break;
 	default:
 	    break;
 	}
diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h
index ba1c420..f046d5c 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -36,8 +36,10 @@
 /* Maximum # of floating point queue */
 #define FPUQN	1
 
-/* Maximum # of breakpoints */
+/* Maximum # of breakpoints and watchpoints */
 #define BPT_MAX	256
+#define WPR_MAX	256
+#define WPW_MAX	256
 
 struct histype {
     unsigned        addr;
@@ -97,6 +99,14 @@ struct pstate {
     uint32          bptnum;
     uint32          bphit;
     uint32          bpts[BPT_MAX];	/* Breakpoints */
+    uint32          wprnum;
+    uint32          wphit;
+    uint32          wprs[WPR_MAX];	/* Read Watchpoints */
+    unsigned char   wprm[WPR_MAX];	/* Read Watchpoint masks*/
+    uint32          wpwnum;
+    uint32          wpws[WPW_MAX];	/* Write Watchpoints */
+    unsigned char   wpwm[WPW_MAX];	/* Write Watchpoint masks */
+    uint32          wpaddress;
 
     uint32          ltime;	/* Load interlock time */
     uint32          hold;	/* IU hold cycles in current inst */
@@ -148,12 +158,19 @@ struct irqcell {
     int32           arg;
 };
 
-
+/* return values for run_sim */
 #define OK 0
 #define TIME_OUT 1
 #define BPT_HIT 2
 #define ERROR 3
 #define CTRL_C 4
+#define WPT_HIT 5
+
+/* special simulator trap types */
+#define ERROR_TRAP 257
+#define WPT_TRAP   258
+
+/* cpu type defines */
 #define CPU_LEON2  2
 #define CPU_LEON3  3
 
@@ -202,6 +219,9 @@ extern void	advance_time (struct pstate  *sregs);
 extern uint32	now (void);
 extern int	wait_for_irq (void);
 extern int	check_bpt (struct pstate *sregs);
+extern int 	check_wpr(struct pstate *sregs, int32 address, unsigned char mask);
+extern int 	check_wpw(struct pstate *sregs, int32 address, unsigned char mask);
+
 extern void	reset_all (void);
 extern void	sys_reset (void);
 extern void	sys_halt (void);
@@ -212,6 +232,7 @@ extern		host_callback *sim_callback;
 extern int	dumbio;
 extern int	tty_setup;
 extern int      cputype;
+extern int	sis_gdb_break;
 
 
 /* exec.c */
-- 
2.7.4

From f13a8fbf74ad31ac23f28aee0d4a3282557d0c66 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Sat, 21 May 2016 22:48:58 +0200
Subject: [PATCH 07/11] Add watchpoint support to gdb simulator interface.

	Currently, only the sparc sim supports watchpoints. Stubs for the
	watchpoint functions were added to all other built-in sims
	to avoid linking errors.
---
 gdb/remote-sim.c              |  69 +++++++++++++
 include/gdb/remote-sim.h      |  24 +++++
 sim/arm/wrapper.c             |  25 +++++
 sim/avr/interp.c              |  25 +++++
 sim/bfin/Makefile.in          |   1 +
 sim/common/sim-watch-remote.c |  27 +++++
 sim/cris/Makefile.in          |   1 +
 sim/erc32/interf.c            | 233 +++++++++++++++++++++++++++++++++---------
 sim/frv/Makefile.in           |   1 +
 sim/ft32/Makefile.in          |   1 +
 sim/h8300/Makefile.in         |   1 +
 sim/iq2000/Makefile.in        |   1 +
 sim/lm32/Makefile.in          |   3 +-
 sim/m32c/gdb-if.c             |  25 +++++
 sim/m32r/Makefile.in          |   1 +
 sim/m68hc11/Makefile.in       |   1 +
 sim/mcore/interp.c            |  25 +++++
 sim/microblaze/Makefile.in    |   1 +
 sim/mips/Makefile.in          |   2 +-
 sim/mn10300/Makefile.in       |   1 +
 sim/moxie/interp.c            |  25 +++++
 sim/msp430/Makefile.in        |   1 +
 sim/ppc/gdb-sim.c             |  25 +++++
 sim/rl78/gdb-if.c             |  25 +++++
 sim/rx/gdb-if.c               |  25 +++++
 sim/sh/interp.c               |  25 +++++
 sim/sh64/Makefile.in          |   1 +
 sim/v850/Makefile.in          |   1 +
 28 files changed, 544 insertions(+), 52 deletions(-)
 create mode 100644 sim/common/sim-watch-remote.c

diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 508e2c2..e22fdbb 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -1317,6 +1317,70 @@ gdbsim_has_memory (struct target_ops *ops)
   return 1;
 }
 
+static int
+gdbsim_insert_watchpoint (struct target_ops *self,
+			CORE_ADDR addr, int len, enum target_hw_bp_type type,
+			struct expression *cond)
+{
+  struct sim_inferior_data *sim_data
+      = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "gdbsim_insert_watchpoint: %d\n", type);
+
+  if (sim_set_watchpoint (sim_data->gdbsim_desc, addr, len, type) != SIM_RC_OK)
+    return -1;
+
+  return 0;
+}
+
+static int
+gdbsim_remove_watchpoint (struct target_ops *self,
+			CORE_ADDR addr, int len, enum target_hw_bp_type type,
+			struct expression *cond)
+{
+  struct sim_inferior_data *sim_data
+      = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "gdbsim_remove_watchpoint: %d\n", type);
+
+  if (sim_clear_watchpoint (sim_data->gdbsim_desc, addr, len, type) != SIM_RC_OK)
+    return -1;
+
+  return 0;
+}
+
+
+static int
+gdbsim_can_use_hw_breakpoint (struct target_ops *self,
+			 enum bptype type, int cnt, int othertype)
+{
+  struct sim_inferior_data *sim_data
+      = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+
+  return (sim_can_use_hw_breakpoint(sim_data->gdbsim_desc, type, cnt, othertype));
+}
+
+static int
+gdbsim_stopped_by_watchpoint (struct target_ops *ops)
+{
+  struct sim_inferior_data *sim_data
+      = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+
+  return (sim_stopped_by_watchpoint(sim_data->gdbsim_desc));;
+}
+
+static int
+gdbsim_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr)
+{
+  struct sim_inferior_data *sim_data
+      = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+
+  *addr = sim_watchpoint_address(sim_data->gdbsim_desc);;
+  return (1);
+}
+
 /* Define the target subroutine names.  */
 
 struct target_ops gdbsim_ops;
@@ -1339,6 +1403,11 @@ init_gdbsim_ops (void)
   gdbsim_ops.to_files_info = gdbsim_files_info;
   gdbsim_ops.to_insert_breakpoint = memory_insert_breakpoint;
   gdbsim_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  gdbsim_ops.to_insert_watchpoint = gdbsim_insert_watchpoint;
+  gdbsim_ops.to_remove_watchpoint = gdbsim_remove_watchpoint;
+  gdbsim_ops.to_stopped_by_watchpoint = gdbsim_stopped_by_watchpoint;
+  gdbsim_ops.to_can_use_hw_breakpoint = gdbsim_can_use_hw_breakpoint;
+  gdbsim_ops.to_stopped_data_address = gdbsim_stopped_data_address;
   gdbsim_ops.to_kill = gdbsim_kill;
   gdbsim_ops.to_load = gdbsim_load;
   gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
diff --git a/include/gdb/remote-sim.h b/include/gdb/remote-sim.h
index 9af0310..2f29569b 100644
--- a/include/gdb/remote-sim.h
+++ b/include/gdb/remote-sim.h
@@ -283,6 +283,30 @@ void sim_do_command (SIM_DESC sd, const char *cmd);
 
 char **sim_complete_command (SIM_DESC sd, const char *text, const char *word);
 
+/* Add hardware watchpoint. See to_insert_watchpoint() in target.h
+   for description of parameters. */
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type);
+
+/* Remove hardware watchpoint. See to_remove_watchpoint() in target.h
+   for description of parameters. */
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type);
+
+/* Returns data address when watchpoint has been hit. See
+   to_stopped_data_address() in target.h for description. */
+
+int sim_watchpoint_address (SIM_DESC sd);
+
+/* Returns 1 if simulator was stopped by watchpoint hit. */
+
+int sim_stopped_by_watchpoint(SIM_DESC sd);
+
+/* Returns non-zero if we can set a hardware watchpoint of type TYPE.
+   See to_can_use_hw_breakpoint() in target.h for details. */
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
index 01f88d1..77b79e6 100644
--- a/sim/arm/wrapper.c
+++ b/sim/arm/wrapper.c
@@ -921,3 +921,28 @@ sim_stop_reason (SIM_DESC sd ATTRIBUTE_UNUSED,
 	*sigrc = 0;
     }
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/avr/interp.c b/sim/avr/interp.c
index 1b7bab7..5e42fa1 100644
--- a/sim/avr/interp.c
+++ b/sim/avr/interp.c
@@ -1774,3 +1774,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
 
   return SIM_RC_OK;
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+	  return 0;
+}
diff --git a/sim/bfin/Makefile.in b/sim/bfin/Makefile.in
index e872e43..0cd37c4 100644
--- a/sim/bfin/Makefile.in
+++ b/sim/bfin/Makefile.in
@@ -27,6 +27,7 @@ SIM_OBJS = \
 	gui.o \
 	interp.o \
 	machs.o \
+	sim-watch-remote.o \
 	sim-resume.o
 
 INCLUDE = bfin-sim.h
diff --git a/sim/common/sim-watch-remote.c b/sim/common/sim-watch-remote.c
new file mode 100644
index 0000000..279bb06
--- /dev/null
+++ b/sim/common/sim-watch-remote.c
@@ -0,0 +1,27 @@
+
+#include "gdb/remote-sim.h"
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/cris/Makefile.in b/sim/cris/Makefile.in
index b2769b8..d73e8c5 100644
--- a/sim/cris/Makefile.in
+++ b/sim/cris/Makefile.in
@@ -24,6 +24,7 @@ CRISV32F_OBJS = crisv32f.o cpuv32.o decodev32.o modelv32.o mloopv32f.o
 
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	cgen-utils.o cgen-trace.o cgen-scache.o \
 	cgen-run.o \
 	sim-if.o arch.o \
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index fa0ab35..ff68259 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -30,6 +30,7 @@
 
 #include "gdb/remote-sim.h"
 #include "gdb/signals.h"
+#include "gdb/common/break-common.h"
 
 #define PSR_CWP 0x7
 
@@ -47,38 +48,15 @@ run_sim(sregs, icount, dis)
    ms->init_stdio ();
    sregs->starttime = get_time();
    irq = 0;
+   if (sregs->err_mode) icount = 0;
    if ((sregs->pc != 0) && (ebase.simtime == 0))
 	ms->boot_init ();
-   while (!sregs->err_mode & (icount > 0)) {
-
+   while (icount > 0) {
 	sregs->fhold = 0;
-	sregs->hold = 0;
 	sregs->icnt = 1;
-
-        if (sregs->psr & 0x080)
-            sregs->asi = 8;
-        else
-            sregs->asi = 9;
-
-#if 0	/* DELETE ME! for debugging purposes only */
-        if (sis_verbose > 1)
-            if (sregs->pc == 0 || sregs->npc == 0)
-                printf ("bogus pc or npc\n");
-#endif
         mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold);
-#if 0	/* DELETE ME! for debugging purposes only */
-        if (sis_verbose > 2)
-            printf("pc %x, np %x, sp %x, fp %x, wm %x, cw %x, i %08x\n",
-                   sregs->pc, sregs->npc,
-                   sregs->r[(((sregs->psr & 7) << 4) + 14) & 0x7f],
-                   sregs->r[(((sregs->psr & 7) << 4) + 30) & 0x7f],
-                   sregs->wim,
-                   sregs->psr & 7,
-                   sregs->inst);
-#endif
         if (sregs->annul) {
             sregs->annul = 0;
-            sregs->icnt = 1;
             sregs->pc = sregs->npc;
             sregs->npc = sregs->npc + 4;
         } else {
@@ -87,47 +65,39 @@ run_sim(sregs, icount, dis)
 		if (mexc) {
 		    sregs->trap = I_ACC_EXC;
 		} else {
-		    if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
-			if (sis_verbose)
-			    (*sim_callback->printf_filtered) (sim_callback,
-							      "SW BP hit at %x\n", sregs->pc);
-                        ms->sim_halt ();
-			ms->restore_stdio ();
-			clearerr(stdin);
-			return BPT_HIT;
-		    } else
-			dispatch_instruction(sregs);
+		    dispatch_instruction(sregs);
+		    icount--;
 		}
-		icount--;
 	    }
 	    if (sregs->trap) {
                 irq = 0;
-		sregs->err_mode = execute_trap(sregs);
+		if ((sregs->err_mode = execute_trap(sregs)) == WPT_HIT) {
+		    sregs->err_mode = 0;
+		    sregs->trap = 0;
+		    icount = 0;
+		}
+		if (sregs->err_mode) icount = 0;
 	    }
 	}
 	advance_time(sregs);
-	if (ctrl_c) {
+	if (ctrl_c)
 	    icount = 0;
-	}
     }
     ms->sim_halt ();
     sregs->tottime += get_time() - sregs->starttime;
     ms->restore_stdio ();
     clearerr(stdin);
-    if (sregs->err_mode)
+    if (sregs->err_mode) {
 	ms->error_mode (sregs->pc);
-    if (sregs->err_mode)
 	return ERROR;
-    if (sregs->bphit) {
-	if (sis_verbose)
-	    (*sim_callback->printf_filtered) (sim_callback,
-					      "HW BP hit at %x\n", sregs->pc);
-	return BPT_HIT;
     }
     if (ctrl_c) {
 	ctrl_c = 0;
+	sregs->wphit = sregs->bphit = 0;
 	return CTRL_C;
     }
+    if ((sregs->bphit) || (sregs->wphit))
+	return (BPT_HIT);
     return TIME_OUT;
 }
 
@@ -144,6 +114,7 @@ sim_open (kind, callback, abfd, argv)
     int             freq = 0;
 
     sim_callback = callback;
+    sis_gdb_break = 1;
 
     sis_gdb_break = 1;
     argc = countargv (argv);
@@ -369,12 +340,15 @@ sim_stop_reason(sd, reason, sigrc)
 {
 
     switch (simstat) {
-	case CTRL_C:
+    case CTRL_C:
 	*reason = sim_stopped;
 	*sigrc = GDB_SIGNAL_INT;
 	break;
     case OK:
     case TIME_OUT:
+	*reason = sim_stopped;
+	*sigrc = 0;
+	break;
     case BPT_HIT:
 	*reason = sim_stopped;
 	*sigrc = GDB_SIGNAL_TRAP;
@@ -383,8 +357,10 @@ sim_stop_reason(sd, reason, sigrc)
 	*sigrc = 0;
 	*reason = sim_exited;
     }
-    ctrl_c = 0;
-    simstat = OK;
+
+    if (sis_verbose)
+	(*sim_callback->printf_filtered) (sim_callback,
+	    "sim_stop_reason %x : %x\n", *reason, *sigrc);
 }
 
 /* Flush all register windows out to the stack.  Starting after the invalid
@@ -445,7 +421,25 @@ flush_windows ()
 void
 sim_resume(SIM_DESC sd, int step, int siggnal)
 {
-    simstat = run_sim(&sregs, UINT64_MAX, 0);
+    if (sis_verbose)
+	(*sim_callback->printf_filtered) (sim_callback,
+	    "sim_resume %x : %x : %x : %x : 0x%08x\n", step, siggnal, sregs.bphit, sregs.wphit, sregs.pc);
+    if (step) {
+	sregs.bphit = 0;
+	sregs.wphit = 1;
+        simstat = run_sim(&sregs, 1, 0);
+	sregs.bphit = 0;
+	sregs.wphit = 0;
+    } else if (sregs.bphit || sregs.wphit) {
+	sregs.bphit = 0;
+	sregs.wphit = 1;
+        simstat = run_sim(&sregs, 1, 0);
+	sregs.bphit = sregs.wphit = 0;
+        simstat = run_sim(&sregs, UINT64_MAX, 0);
+	sregs.bphit = 0;
+    }
+    else
+        simstat = run_sim(&sregs, UINT64_MAX, 0);
 
     if (sis_gdb_break) flush_windows ();
 }
@@ -471,6 +465,145 @@ sim_stop (SIM_DESC sd)
   return 1;
 }
 
+static int
+sis_insert_watchpoint_read(int addr, unsigned char mask)
+{
+    if (sregs.wprnum < WPR_MAX) {
+	sregs.wprs[sregs.wprnum] = addr;
+	sregs.wprm[sregs.wprnum] = mask;
+	sregs.wprnum++;
+	if (sis_verbose)
+	    (*sim_callback->printf_filtered) (sim_callback, "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 < sregs.wprnum) && (sregs.wprs[i] != addr))
+	i++;
+    if (addr == sregs.wprs[i]) {
+	for (; i < sregs.wprnum - 1; i++)
+	    sregs.wprs[i] = sregs.wprs[i + 1];
+	sregs.wprnum -= 1;
+	if (sis_verbose)
+	    (*sim_callback->printf_filtered) (sim_callback, "removed read watchpoint at %x\n", addr);
+	return 0;
+    }
+    return 1;
+}
+
+static int
+sis_insert_watchpoint_write(int32 addr, unsigned char mask)
+{
+    if (sregs.wpwnum < WPR_MAX) {
+	sregs.wpws[sregs.wpwnum] = addr;
+	sregs.wpwm[sregs.wpwnum] = mask;
+	sregs.wpwnum++;
+	if (sis_verbose)
+	    (*sim_callback->printf_filtered) (sim_callback, "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 < sregs.wpwnum) && (sregs.wpws[i] != addr))
+	i++;
+    if (addr == sregs.wpws[i]) {
+	for (; i < sregs.wpwnum - 1; i++)
+	    sregs.wpws[i] = sregs.wpws[i + 1];
+	sregs.wpwnum -= 1;
+	if (sis_verbose)
+	    (*sim_callback->printf_filtered) (sim_callback, "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)
+       (*sim_callback->printf_filtered) (sim_callback, "sim_stopped_by_watchpoint %x\n", sregs.wphit);
+    return((sregs.wphit != 0));
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+    return(sregs.wpaddress);
+}
+
 #if 0 /* FIXME: These shouldn't exist.  */
 
 int
diff --git a/sim/frv/Makefile.in b/sim/frv/Makefile.in
index ff36e1f..013777e 100644
--- a/sim/frv/Makefile.in
+++ b/sim/frv/Makefile.in
@@ -21,6 +21,7 @@ FRV_OBJS = frv.o cpu.o decode.o sem.o model.o mloop.o cgen-par.o
 
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	cgen-utils.o cgen-trace.o cgen-scache.o cgen-fpu.o cgen-accfp.o \
 	cgen-run.o \
 	sim-if.o arch.o \
diff --git a/sim/ft32/Makefile.in b/sim/ft32/Makefile.in
index 7fc9277..ea92e32 100644
--- a/sim/ft32/Makefile.in
+++ b/sim/ft32/Makefile.in
@@ -21,6 +21,7 @@
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
 	interp.o	\
+	sim-watch-remote.o \
 	sim-resume.o
 
 ## COMMON_POST_CONFIG_FRAG
diff --git a/sim/h8300/Makefile.in b/sim/h8300/Makefile.in
index 9d26138..21e5562 100644
--- a/sim/h8300/Makefile.in
+++ b/sim/h8300/Makefile.in
@@ -19,6 +19,7 @@
 
 SIM_OBJS = compile.o \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	sim-resume.o
 
 ## COMMON_POST_CONFIG_FRAG
diff --git a/sim/iq2000/Makefile.in b/sim/iq2000/Makefile.in
index 0c84af6..7e862df 100644
--- a/sim/iq2000/Makefile.in
+++ b/sim/iq2000/Makefile.in
@@ -21,6 +21,7 @@ IQ2000_OBJS = iq2000.o cpu.o decode.o sem.o model.o mloop.o
 
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	cgen-utils.o cgen-trace.o cgen-scache.o \
 	cgen-run.o \
 	sim-if.o arch.o \
diff --git a/sim/lm32/Makefile.in b/sim/lm32/Makefile.in
index 6a71ace..ec97c77 100644
--- a/sim/lm32/Makefile.in
+++ b/sim/lm32/Makefile.in
@@ -9,8 +9,9 @@ SIM_OBJS = \
         cgen-utils.o cgen-trace.o cgen-scache.o \
         cgen-run.o \
         sim-if.o arch.o \
+	sim-watch-remote.o \
         cpu.o decode.o sem.o model.o mloop.o \
-        lm32.o traps.o user.o 
+        lm32.o traps.o user.o
 
 # List of extra dependencies.
 # Generally this consists of simulator specific files included by sim-main.h.
diff --git a/sim/m32c/gdb-if.c b/sim/m32c/gdb-if.c
index 3ead373..883e9fc 100644
--- a/sim/m32c/gdb-if.c
+++ b/sim/m32c/gdb-if.c
@@ -712,3 +712,28 @@ sim_info (SIM_DESC sd, int verbose)
 {
   printf ("The m32c minisim doesn't collect any statistics.\n");
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/m32r/Makefile.in b/sim/m32r/Makefile.in
index 4709e4a..d185171 100644
--- a/sim/m32r/Makefile.in
+++ b/sim/m32r/Makefile.in
@@ -29,6 +29,7 @@ SIM_OBJS = \
 	cgen-utils.o cgen-trace.o cgen-scache.o \
 	cgen-run.o \
 	sim-if.o arch.o \
+	sim-watch-remote.o \
 	$(M32R_OBJS) \
 	$(M32RX_OBJS) \
 	$(M32R2_OBJS) \
diff --git a/sim/m68hc11/Makefile.in b/sim/m68hc11/Makefile.in
index 38e1fc2..bd0356e 100644
--- a/sim/m68hc11/Makefile.in
+++ b/sim/m68hc11/Makefile.in
@@ -22,6 +22,7 @@ M68HC11_OBJS = interp.o m68hc11int.o m68hc12int.o \
 
 SIM_OBJS = $(M68HC11_OBJS) \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	sim-resume.o
 
 SIM_PROFILE= -DPROFILE=1 -DWITH_PROFILE=-1
diff --git a/sim/mcore/interp.c b/sim/mcore/interp.c
index 2ed2670..26b1662 100644
--- a/sim/mcore/interp.c
+++ b/sim/mcore/interp.c
@@ -1529,3 +1529,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
 
   return SIM_RC_OK;
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/microblaze/Makefile.in b/sim/microblaze/Makefile.in
index 6ff284e..eb64dd4 100644
--- a/sim/microblaze/Makefile.in
+++ b/sim/microblaze/Makefile.in
@@ -20,6 +20,7 @@
 SIM_OBJS = \
 	interp.o \
 	$(SIM_NEW_COMMON_OBJS) \
+	sim-watch-remote.o \
 	sim-resume.o
 
 ## COMMON_POST_CONFIG_FRAG
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 7f1c916..e6c943b 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -70,7 +70,7 @@ SIM_OBJS = \
 	dsp.o \
 	sim-main.o \
 	sim-resume.o \
-
+	sim-watch-remote.o
 
 # List of flags to always pass to $(CC).
 SIM_SUBTARGET=@SIM_SUBTARGET@
diff --git a/sim/mn10300/Makefile.in b/sim/mn10300/Makefile.in
index 145eb08..49fa523 100644
--- a/sim/mn10300/Makefile.in
+++ b/sim/mn10300/Makefile.in
@@ -21,6 +21,7 @@ MN10300_OBJS = \
 	itable.o semantics.o idecode.o icache.o engine.o irun.o support.o \
 	$(SIM_NEW_COMMON_OBJS) \
 	op_utils.o \
+	sim-watch-remote.o \
 	sim-resume.o
 
 SIM_OBJS = $(MN10300_OBJS) interp.o
diff --git a/sim/moxie/interp.c b/sim/moxie/interp.c
index c9605d4..f033a14 100644
--- a/sim/moxie/interp.c
+++ b/sim/moxie/interp.c
@@ -1323,3 +1323,28 @@ sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
 
   return SIM_RC_OK;
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/msp430/Makefile.in b/sim/msp430/Makefile.in
index 62c949c..854aa4a 100644
--- a/sim/msp430/Makefile.in
+++ b/sim/msp430/Makefile.in
@@ -27,6 +27,7 @@
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
 	msp430-sim.o \
+	sim-watch-remote.o \
 	sim-resume.o
 
 # List of extra dependencies.
diff --git a/sim/ppc/gdb-sim.c b/sim/ppc/gdb-sim.c
index ca95cff..8086a23 100644
--- a/sim/ppc/gdb-sim.c
+++ b/sim/ppc/gdb-sim.c
@@ -1296,3 +1296,28 @@ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
   return psim_write_register(simulator, MAX_NR_PROCESSORS,
 			     buf, regname, raw_transfer);
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/rl78/gdb-if.c b/sim/rl78/gdb-if.c
index b468687..426a92c 100644
--- a/sim/rl78/gdb-if.c
+++ b/sim/rl78/gdb-if.c
@@ -603,3 +603,28 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
 {
     return NULL;
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/rx/gdb-if.c b/sim/rx/gdb-if.c
index 910962e..b28bc63 100644
--- a/sim/rx/gdb-if.c
+++ b/sim/rx/gdb-if.c
@@ -854,3 +854,28 @@ sim_complete_command (SIM_DESC sd, const char *text, const char *word)
 {
   return NULL;
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/sh/interp.c b/sim/sh/interp.c
index c77cf3b..257985c 100644
--- a/sim/sh/interp.c
+++ b/sim/sh/interp.c
@@ -2511,3 +2511,28 @@ sim_do_command (SIM_DESC sd, const char *cmd)
       sim_io_printf (sd, "Error: \"%s\" is not a valid SH simulator command.\n", cmd);
     }
 }
+
+int sim_set_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_clear_watchpoint (SIM_DESC sd, SIM_ADDR mem, int length, int type)
+{
+  return -1;
+}
+
+int sim_stopped_by_watchpoint (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_watchpoint_address (SIM_DESC sd)
+{
+  return 0;
+}
+
+int sim_can_use_hw_breakpoint (SIM_DESC sd, int type, int cnt, int othertype)
+{
+  return 0;
+}
diff --git a/sim/sh64/Makefile.in b/sim/sh64/Makefile.in
index 15b5a1e..45b579a 100644
--- a/sim/sh64/Makefile.in
+++ b/sim/sh64/Makefile.in
@@ -26,6 +26,7 @@ SIM_OBJS = \
 	cgen-utils.o cgen-trace.o cgen-scache.o \
 	cgen-run.o \
 	sim-if.o arch.o \
+	sim-watch-remote.o \
 	$(SH64_OBJS)
 
 # Extra headers included by sim-main.h.
diff --git a/sim/v850/Makefile.in b/sim/v850/Makefile.in
index 6da9c03..b7c5f20 100644
--- a/sim/v850/Makefile.in
+++ b/sim/v850/Makefile.in
@@ -23,6 +23,7 @@ SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
 	simops.o interp.o \
 	itable.o semantics.o idecode.o icache.o engine.o irun.o support.o \
+	sim-watch-remote.o \
 	sim-resume.o
 
 # List of extra dependencies.
-- 
2.7.4

From e09a9b0686d8a1eb43d3738c7db4155aec6a70f2 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Sun, 5 Jun 2016 23:22:31 +0200
Subject: [PATCH 08/11] sim/erc32: Added back original run.c

	The 'run' utility was removed but is still used by RTEMS project for
	automatic testing. This patch adds it back.

	* New file run.c
	* New file run-sim.h
---
 sim/erc32/Makefile.in |   3 +-
 sim/erc32/run-sim.h   |  93 +++++++++++++
 sim/erc32/run.c       | 354 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 448 insertions(+), 2 deletions(-)
 create mode 100644 sim/erc32/run-sim.h
 create mode 100644 sim/erc32/run.c

diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
index 1802788..d377865 100644
--- a/sim/erc32/Makefile.in
+++ b/sim/erc32/Makefile.in
@@ -25,7 +25,7 @@ READLINE_LIB = @READLINE@
 SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o leon2.o
 
 SIM_OBJS = $(SIS_OFILES) interf.o
-SIM_RUN_OBJS = sis.o
+SIM_RUN_OBJS = run.o
 SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
 SIM_EXTRA_ALL = sis
 SIM_EXTRA_INSTALL = install-sis
@@ -56,4 +56,3 @@ configure:
 	  srcdir=. ; export srcdir ; \
 	else true ; fi ; \
 	(cd $${srcdir}; autoconf --localdir=../common)
-
diff --git a/sim/erc32/run-sim.h b/sim/erc32/run-sim.h
new file mode 100644
index 0000000..8793472
--- /dev/null
+++ b/sim/erc32/run-sim.h
@@ -0,0 +1,93 @@
+/* This file defines the part of the interface between the standalone
+   simaulator program - run - and simulator library - libsim.a - that
+   is not used by GDB.  The GDB part is described in include/remote-sim.h.
+
+   Copyright 2002-2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#ifndef RUN_SIM_H
+#define RUN_SIM_H
+
+#ifdef SIM_TARGET_SWITCHES
+  /* Parse the command line, extracting any target specific switches
+     before the generic simulator code gets a chance to complain
+     about them.  Returns the adjusted value of argc.  */
+int sim_target_parse_command_line (int, char **);
+
+  /* Display a list of target specific switches supported by this
+     target.  */
+void sim_target_display_usage (int help);
+
+#endif
+
+/* Provide simulator with a default (global) host_callback_struct.
+   THIS PROCEDURE IS DEPRECATED.
+   GDB and NRUN do not use this interface.
+   This procedure does not take a SIM_DESC argument as it is
+   used before sim_open. */
+
+void sim_set_callbacks (struct host_callback_struct *);
+
+
+/* Set the size of the simulator memory array.
+   THIS PROCEDURE IS DEPRECATED.
+   GDB and NRUN do not use this interface.
+   This procedure does not take a SIM_DESC argument as it is
+   used before sim_open. */
+
+void sim_size (int i);
+
+
+/* Single-step simulator with tracing enabled.
+   THIS PROCEDURE IS DEPRECATED.
+   THIS PROCEDURE IS EVEN MORE DEPRECATED THAN SIM_SET_TRACE
+   GDB and NRUN do not use this interface.
+   This procedure returns: ``0'' indicating that the simulator should
+   be continued using sim_trace() calls; ``1'' indicating that the
+   simulation has finished. */
+
+int sim_trace (SIM_DESC sd);
+
+
+/* Enable tracing.
+   THIS PROCEDURE IS DEPRECATED.
+   GDB and NRUN do not use this interface.
+   This procedure returns: ``0'' indicating that the simulator should
+   be continued using sim_trace() calls; ``1'' indicating that the
+   simulation has finished. */
+
+void sim_set_trace (void);
+
+
+/* Configure the size of the profile buffer.
+   THIS PROCEDURE IS DEPRECATED.
+   GDB and NRUN do not use this interface.
+   This procedure does not take a SIM_DESC argument as it is
+   used before sim_open. */
+
+void sim_set_profile_size (int n);
+
+
+/* Kill the running program.
+   THIS PROCEDURE IS DEPRECATED.
+   GDB and NRUN do not use this interface.
+   This procedure will be replaced as part of the introduction of
+   multi-cpu simulators. */
+
+void sim_kill (SIM_DESC sd);
+
+#endif
diff --git a/sim/erc32/run.c b/sim/erc32/run.c
new file mode 100644
index 0000000..70ae411
--- /dev/null
+++ b/sim/erc32/run.c
@@ -0,0 +1,354 @@
+/* run front end support for all the simulators.
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
+
+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/>.  */
+
+/* Steve Chamberlain sac@cygnus.com,
+   and others at Cygnus.  */
+
+#include "config.h"
+
+#include <signal.h>
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include "libiberty.h"
+#include "bfd.h"
+#include "gdb/callback.h"
+#include "gdb/remote-sim.h"
+#include "ansidecl.h"
+#include "run-sim.h"
+#include "version.h"
+
+static void usage (int help);
+static void print_version (void);
+extern int optind;
+extern char *optarg;
+
+extern host_callback default_callback;
+
+static char *myname;
+
+extern int getopt ();
+
+#ifdef NEED_UI_LOOP_HOOK
+/* Gdb foolery. This is only needed for gdb using a gui.  */
+int (*deprecated_ui_loop_hook) (int signo);
+#endif
+
+static SIM_DESC sd;
+
+static RETSIGTYPE
+cntrl_c (int sig ATTRIBUTE_UNUSED)
+{
+  if (! sim_stop (sd))
+    {
+      fprintf (stderr, "Quit!\n");
+      exit (1);
+    }
+}
+
+int
+main (ac, av)
+     int ac;
+     char **av;
+{
+  RETSIGTYPE (*prev_sigint) ();
+  bfd *abfd;
+  int i;
+  int verbose = 0;
+  int trace = 0;
+#ifdef SIM_HAVE_ENVIRONMENT
+  int operating_p = 0;
+#endif
+  char *name;
+  static char *no_args[4];
+  char **sim_argv = &no_args[0];
+  char **prog_args;
+  enum sim_stop reason;
+  int sigrc;
+
+  myname = av[0] + strlen (av[0]);
+  while (myname > av[0] && myname[-1] != '/')
+    --myname;
+
+  /* The first element of sim_open's argv is the program name.  */
+  no_args[0] = av[0];
+#ifdef SIM_HAVE_BIENDIAN
+  no_args[1] = "-E";
+  no_args[2] = "set-later";
+#endif
+
+  /* FIXME: This is currently being migrated into sim_open.
+     Simulators that use functions such as sim_size() still require
+     this.  */
+  default_callback.init (&default_callback);
+  //sim_set_callbacks (&default_callback);
+
+#ifdef SIM_TARGET_SWITCHES
+  ac = sim_target_parse_command_line (ac, av);
+#endif
+
+  for (i = 1; av[i]; ++i)
+    {
+      if (strcmp (av[i], "--help") == 0)
+        {
+          usage (1);
+        }
+      else if (strcmp (av[i], "--version") == 0)
+        {
+          print_version ();
+          return 0;
+        }
+    }
+
+  /* FIXME: This is currently being rewritten to have each simulator
+     do all argv processing.  */
+
+  while ((i = getopt (ac, av, "a:c:m:op:s:tv")) != EOF)
+    switch (i)
+      {
+      case 'a':
+	/* FIXME: Temporary hack.  */
+	{
+	  int len = strlen (av[0]) + strlen (optarg);
+	  char *argbuf = (char *) alloca (len + 2 + 50);
+	  sprintf (argbuf, "%s %s", av[0], optarg);
+#ifdef SIM_HAVE_BIENDIAN
+	  /* The desired endianness must be passed to sim_open.
+	     The value for "set-later" is set when we know what it is.
+	     -E support isn't yet part of the published interface.  */
+	  strcat (argbuf, " -E set-later");
+#endif
+	  sim_argv = buildargv (argbuf);
+	}
+	break;
+#ifdef SIM_HAVE_SIMCACHE
+      case 'c':
+	sim_set_simcache_size (atoi (optarg));
+	break;
+#endif
+      case 'm':
+	/* FIXME: Rename to sim_set_mem_size.  */
+	//sim_size (atoi (optarg));
+	break;
+#ifdef SIM_HAVE_ENVIRONMENT
+      case 'o':
+	/* Operating enironment where any signals are delivered to the
+           target.  */
+	operating_p = 1;
+	break;
+#endif
+#ifdef SIM_HAVE_PROFILE
+      case 'p':
+	sim_set_profile (atoi (optarg));
+	break;
+      case 's':
+	sim_set_profile_size (atoi (optarg));
+	break;
+#endif
+      case 't':
+	trace = 1;
+	break;
+      case 'v':
+	/* Things that are printed with -v are the kinds of things that
+	   gcc -v prints.  This is not meant to include detailed tracing
+	   or debugging information, just summaries.  */
+	verbose = 1;
+	/* sim_set_verbose (1); */
+	break;
+	/* FIXME: Quick hack, to be replaced by more general facility.  */
+      default:
+	usage (0);
+      }
+
+  ac -= optind;
+  av += optind;
+  if (ac <= 0)
+    usage (0);
+
+  name = *av;
+  prog_args = av;
+
+  if (verbose)
+    {
+      printf ("%s %s\n", myname, name);
+    }
+
+  abfd = bfd_openr (name, 0);
+  if (!abfd)
+    {
+      fprintf (stderr, "%s: can't open %s: %s\n",
+	       myname, name, bfd_errmsg (bfd_get_error ()));
+      exit (1);
+    }
+
+  if (!bfd_check_format (abfd, bfd_object))
+    {
+      fprintf (stderr, "%s: can't load %s: %s\n",
+	       myname, name, bfd_errmsg (bfd_get_error ()));
+      exit (1);
+    }
+
+#ifdef SIM_HAVE_BIENDIAN
+  /* The endianness must be passed to sim_open because one may wish to
+     examine/set registers before calling sim_load [which is the other
+     place where one can determine endianness].  We previously passed the
+     endianness via global `target_byte_order' but that's not a clean
+     interface.  */
+  for (i = 1; sim_argv[i + 1] != NULL; ++i)
+    continue;
+  if (bfd_big_endian (abfd))
+    sim_argv[i] = "big";
+  else
+    sim_argv[i] = "little";
+#endif
+
+  /* Ensure that any run-time initialisation that needs to be
+     performed by the simulator can occur.  */
+  sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv);
+  if (sd == 0)
+    exit (1);
+
+  if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL)
+    exit (1);
+
+  if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL)
+    exit (1);
+
+#ifdef SIM_HAVE_ENVIRONMENT
+  /* NOTE: An old simulator supporting the operating environment MUST
+     provide sim_set_trace() and not sim_trace(). That way
+     sim_stop_reason() can be used to determine any stop reason.  */
+  if (trace)
+    sim_set_trace ();
+  sigrc = 0;
+  do
+    {
+      prev_sigint = signal (SIGINT, cntrl_c);
+      sim_resume (sd, 0, sigrc);
+      signal (SIGINT, prev_sigint);
+      sim_stop_reason (sd, &reason, &sigrc);
+    }
+  while (operating_p && reason == sim_stopped && sigrc != SIGINT);
+#else
+  if (trace)
+    {
+      int done = 0;
+      prev_sigint = signal (SIGINT, cntrl_c);
+      while (!done)
+	{
+	  // done = sim_trace (sd);
+	}
+      signal (SIGINT, prev_sigint);
+      sim_stop_reason (sd, &reason, &sigrc);
+    }
+  else
+    {
+      prev_sigint = signal (SIGINT, cntrl_c);
+      sigrc = 0;
+      sim_resume (sd, 0, sigrc);
+      signal (SIGINT, prev_sigint);
+      sim_stop_reason (sd, &reason, &sigrc);
+    }
+#endif
+
+  if (verbose)
+    sim_info (sd, 0);
+  sim_close (sd, 0);
+
+  /* If reason is sim_exited, then sigrc holds the exit code which we want
+     to return.  If reason is sim_stopped or sim_signalled, then sigrc holds
+     the signal that the simulator received; we want to return that to
+     indicate failure.  */
+
+  /* Why did we stop? */
+  switch (reason)
+    {
+    case sim_signalled:
+    case sim_stopped:
+      if (sigrc != 0)
+	fprintf (stderr, "program stopped with signal %d.\n", sigrc);
+      break;
+
+    case sim_exited:
+      break;
+
+    case sim_running:
+    case sim_polling: /* These indicate a serious problem.  */
+      abort ();
+      break;
+
+    }
+
+  return sigrc;
+}
+
+static void
+usage (int help)
+{
+  FILE *stream = help ? stdout : stderr;
+
+  fprintf (stream, "Usage: %s [options] program [program args]\n", myname);
+  fprintf (stream, "Options:\n");
+  fprintf (stream, "-a args         Pass `args' to simulator.\n");
+#ifdef SIM_HAVE_SIMCACHE
+  fprintf (stream, "-c size         Set simulator cache size to `size'.\n");
+#endif
+  fprintf (stream, "-m size         Set memory size of simulator, in bytes.\n");
+#ifdef SIM_HAVE_ENVIRONMENT
+  fprintf (stream, "-o              Select operating (kernel) environment.\n");
+#endif
+#ifdef SIM_HAVE_PROFILE
+  fprintf (stream, "-p freq         Set profiling frequency.\n");
+  fprintf (stream, "-s size         Set profiling size.\n");
+#endif
+  fprintf (stream, "-t              Perform instruction tracing.\n");
+  fprintf (stream, "                Note: Very few simulators support tracing.\n");
+  fprintf (stream, "-v              Verbose output.\n");
+  fprintf (stream, "\n");
+  fprintf (stream, "program args    Arguments to pass to simulated program.\n");
+  fprintf (stream, "                Note: Very few simulators support this.\n");
+#ifdef SIM_TARGET_SWITCHES
+  fprintf (stream, "\nTarget specific options:\n");
+  sim_target_display_usage (help);
+#endif
+
+  if (help && REPORT_BUGS_TO[0])
+    printf ("Report bugs to %s\n", REPORT_BUGS_TO);
+
+  exit (help ? 0 : 1);
+}
+
+static void
+print_version ()
+{
+  printf ("GNU simulator %s%s\n", PKGVERSION, version);
+}
-- 
2.7.4

From 7f966d19fd351e99450aea1c050bda358ef626ce Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Thu, 23 Mar 2017 10:23:46 +0100
Subject: [PATCH 09/11] sim/erc32: Add run options to standalone simulator

	The standalone simulator is extend to allow automatic loading and
	running of binaries at start-up. The simulated time can optionally be
	limited to abort a run-away program.

	* sis.c (main): Add -r option to sis to automatically run applications
	 at start-up. Add -tlim option to limit simulated time, e.g. -tlim 200 s.
---
 sim/erc32/func.c | 18 +++++++++---------
 sim/erc32/sis.c  | 35 ++++++++++++++++++++++++++++-------
 2 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index d4fe8ea..a94a0ca 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -75,7 +75,7 @@ uint32		errmec = 0;
 static int	batch (struct pstate *sregs, char *fname);
 static void	set_rega (struct pstate *sregs, char *reg, uint32 rval);
 static void	disp_reg (struct pstate *sregs, char *reg);
-static uint32	limcalc (float32 freq);
+static uint64	limcalc (float32 freq);
 static void	int_handler (int32 sig);
 static void	init_event (void);
 static int	disp_fpu (struct pstate  *sregs);
@@ -350,11 +350,11 @@ errinjstart()
 
 #endif
 
-static uint32
+static uint64
 limcalc (freq)
     float32		freq;
 {
-    uint32          unit, lim;
+    uint64          unit, lim;
     double	    flim;
     char           *cmd1, *cmd2;
 
@@ -363,14 +363,14 @@ limcalc (freq)
     if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
         lim = VAL(cmd1);
         if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
-            if (strcmp(cmd2,"us")==0) unit = 1;
-      	    if (strcmp(cmd2,"ms")==0) unit = 1000;
-            if (strcmp(cmd2,"s")==0)  unit = 1000000;
+	    if (strcmp(cmd2,"us")==0) unit = 1;
+	    if (strcmp(cmd2,"ms")==0) unit = 1000;
+	    if (strcmp(cmd2,"s")==0)  unit = 1000000;
         }
-        flim = (double) lim * (double) unit * (double) freq + 
+        flim = (double) lim * (double) unit * (double) freq +
 	   (double) ebase.simtime;
-        if ((flim > ebase.simtime) && (flim < 4294967296.0)) {
-            lim = (uint32) flim;
+        if (flim > ebase.simtime) {
+            lim = (uint64) flim;
         } else  {
             printf("error in expression\n");
             lim = -1;
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 689d17e..83dd5cf 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -145,6 +145,8 @@ main(argc, argv)
     int             cmdi = 0;
     int             i;
     int             lfile = 0;
+    char	    tlim[64] = "";
+    int		    run = 0;
 
     cfile = 0;
     for (i = 0; i < 64; i++)
@@ -189,6 +191,8 @@ main(argc, argv)
 		dumbio = 1;
 	    } else if (strcmp(argv[stat], "-nouartrx") == 0) {
 		nouartrx = 1;
+	    } else if (strcmp(argv[stat], "-r") == 0) {
+		run = 1;
 	    } else if (strcmp (argv[stat], "-leon2") == 0) {
 		ms = &leon2;
 		if (freq == 14) freq = 50;
@@ -197,6 +201,13 @@ main(argc, argv)
 		ms = &leon3;
 		if (freq == 14) freq = 50;
 		cputype = CPU_LEON3;
+	    } else if (strcmp(argv[stat], "-tlim") == 0) {
+		if ((stat + 2) < argc) {
+		    strcpy(tlim, "tlim ");
+		    strcat(tlim, argv[++stat]);
+		    strcat(tlim, " ");
+		    strcat(tlim, argv[++stat]);
+		}
 	    } else {
 		printf("unknown option %s\n", argv[stat]);
 		usage();
@@ -250,6 +261,10 @@ main(argc, argv)
 	strcat(bacmd, cfile);
 	exec_cmd(&sregs, bacmd);
     }
+    if (tlim[0]) {
+	exec_cmd(&sregs, tlim);
+    }
+
     while (cont) {
 
 	if (cmdq[cmdi] != 0) {
@@ -261,14 +276,20 @@ main(argc, argv)
 	    free(cmdq[cmdi]);
 	    cmdq[cmdi] = 0;
 	}
-	cmdq[cmdi] = readline("sis> ");
-	if (cmdq[cmdi] && *cmdq[cmdi])
-	    add_history(cmdq[cmdi]);
-	if (cmdq[cmdi])
-	    stat = exec_cmd(&sregs, cmdq[cmdi]);
+	if (run) {
+	    stat = exec_cmd(&sregs, "run");
+	    cont = 0;
+	}
 	else {
-	    puts("\n");
-	    exit(0);
+	    cmdq[cmdi] = readline("sis> ");
+	    if (cmdq[cmdi] && *cmdq[cmdi])
+		add_history(cmdq[cmdi]);
+	    if (cmdq[cmdi])
+		stat = exec_cmd(&sregs, cmdq[cmdi]);
+	    else {
+		puts("\n");
+		exit(0);
+	    }
 	}
 	switch (stat) {
 	case OK:
-- 
2.7.4

From b5413e5c202b1b2c79d68ff97f5f49ff43bfce5a Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Wed, 18 Feb 2015 23:10:51 +0100
Subject: [PATCH 10/11] sim/erc32: Updated documentation.

	Cleaned up documentation. Obsolote README files were removed,
	main documentation on operation is now in READMEM.sis.
---
 sim/erc32/NEWS         | 108 --------------------
 sim/erc32/README.erc32 |  88 ++++++++++++----
 sim/erc32/README.gdb   |  67 ------------
 sim/erc32/README.leon2 |  53 ++++++++++
 sim/erc32/README.sis   | 271 ++++++++++++++++++-------------------------------
 sim/erc32/erc32.c      |   2 +-
 sim/erc32/interf.c     |   2 +-
 sim/erc32/leon2.c      |   2 +-
 sim/erc32/leon3.c      |   2 +-
 sim/erc32/sis.c        |   2 +-
 sim/erc32/startsim     |  18 ----
 11 files changed, 225 insertions(+), 390 deletions(-)
 delete mode 100644 sim/erc32/NEWS
 delete mode 100644 sim/erc32/README.gdb
 create mode 100644 sim/erc32/README.leon2
 delete mode 100644 sim/erc32/startsim

diff --git a/sim/erc32/NEWS b/sim/erc32/NEWS
deleted file mode 100644
index dd24b7b..0000000
--- a/sim/erc32/NEWS
+++ /dev/null
@@ -1,108 +0,0 @@
-
-version 2.0 05-02-96
---------------------
-
-* Switched to bfd library. Any supported format (elf, coff, ...) can be used.
-* The UART devices can be set through -uart1 and -uart2 switches.
-* Switched to GNU readline.
-* Added -c option to run batch files at startup
-* 'reg' command can show different register windows (eg 'reg w3').
-* Use 'help' for online help on simulator commands
-
-version 1.8.1 20-01-96
---------------------
-
-* added -mevrev0 switch to simulate MEC rev.0 bugs in timer and uart
-
-* added -iurev0 switch to simulate IU rev.0 jmpl/restore bug
-
-* Added sis command 'batch' to run batch files
-
-
-version 1.8 30-10-95
---------------------
-
-* Added s-record support. Use the '-s' switch with sis or the 'load' command.
-
-* IU load dependencies are now modelled
-
-version 1.7 30-10-95
---------------------
-
-* Power-down mode implemented in erc32.c.
-  
-* Performance display shows the ratio between simulator-time and real-time.
-
-
-version 1.6.2 25-10-95
---------------------
-
-* The UARTs can now be run at a given speed (simulator time) to better
-  simulate the behaviour of interrupt routines. The "true mode" is
-  selected through a compile switch in the makefile.
-
-
-version 1.6 28-09-95
---------------------
-
-* Major reorganisation of the code. mec.c and mem.c merged into erc32.c.
-
-* The load command does NOT longer load the initialised data at an address
-  defined by .bdata. This is done in srt0.s using _environ.
-
-* Additional MEC functionallity added - software reset, memory access
-  protection and waitstate configuration register.
-
-* interf.c - a GDB interface added
-
-* -v switch (verbose) added
-
-version 1.5 14-09-95
---------------------
-
-* Added a instruction trace buffer, enabled through the 'hist' command.
-
-* Added a 'perf' command to display statistics such as instruction mix,
-  CPI, FPU holds etc.
-
-* Added -nfp switch to disable FPU.
-
-* Added -freq switch to set simulated frequency.
-
-version 1.4 22-08-95
---------------------
-
-* A -g is provided for those who have problems with GNU readline(). 
-
-version 1.3 26-07-95
---------------------
-
-* No major news, just a bug fix release ...
-
-
-version 1.2 13-07-95
---------------------
-
-* Added setting of IU registers through the 'reg' command. See README.
-
-* The GNU readline() function is used for command input. However, a
-ctrl-D still kills the simulator ...
-
-
-version 1.1 07-07-95
---------------------
-
-
-* Added a 'go' command
-
-* Added cycle counting for interrupt overhead.
-
-* Function 'get_mem_ptr' takes one more parameter to avoid segmentation 
-   faults if a.out files are loaded outside the simulated memory. See README.
-
-* Added user-defined function sim_stop().
-
-* Added a reset command. See README.
-
-* Implemented buffered output for MEC uarts to improve output speed.
-
diff --git a/sim/erc32/README.erc32 b/sim/erc32/README.erc32
index f413599..831434f 100644
--- a/sim/erc32/README.erc32
+++ b/sim/erc32/README.erc32
@@ -8,26 +8,26 @@ The following paragraphs outline the implemented MEC functions.
 1.1 UARTs
 
 The UARTs are connected to two pseudo-devices, /dev/ttypc and /dev/ttypd.
-The following registers are implemeted:
+The following registers are implemented:
 
 - UART A RX and TX register	(0x01f800e0)
 - UART B RX and TX register	(0x01f800e4)
 - UART status register		(0x01f800e8)
 
-To speed up simulation, the UARTs operate at approximately 115200 baud. 
-The UARTs generate interrupt 4 and 5 after each received or transmitted 
+To speed up simulation, the UARTs operate at approximately 115200 baud.
+The UARTs generate interrupt 4 and 5 after each received or transmitted
 character.  The error interrupt is generated if overflow occurs - other
-errors cannot occure.
+errors cannot occur.
 
-1.2 Real-time clock and general pupose timer A
+1.2 Real-time clock and general purpose timer A
 
-The following registers are implemeted:
+The following registers are implemented:
 
 - Real-time clock timer				(0x01f80080, read-only)
 - Real-time clock scaler program register 	(0x01f80084, write-only)
 - Real-time clock counter program register 	(0x01f80080, write-only)
 
-- Genearl pupose timer 				(0x01f80088, read-only)
+- General purpose timer 				(0x01f80088, read-only)
 - Real-time clock scaler program register 	(0x01f8008c, write-only)
 - General purpose timer counter prog. register 	(0x01f80088, write-only)
 
@@ -42,7 +42,7 @@ only internal interrupts that are generated are the real-time clock,
 the general purpose timer and UARTs. However, all 15 interrupts
 can be tested via the interrupt force register.
 
-The following registers are implemeted:
+The following registers are implemented:
 
 - Interrupt pending register		       (0x01f80048, read-only)
 - Interrupt mask register		       (0x01f8004c, read-write)
@@ -53,13 +53,13 @@ The following registers are implemeted:
 
 The breakpoint and watchpoint functions are implemented as in the MEC
 specification. Traps are correctly generated, and the system fault status
-register is updated accordingly. Implemeted registers are:
+register is updated accordingly. Implemented registers are:
 
 - Debug control register			(0x01f800c0, read-write)
 - Breakpoint register				(0x01f800c4, write-only)
 - Watchpoint register				(0x01f800c8, write-only)
 - System fault status register			(0x01f800a0, read-write)
-- Firts failing address register		(0x01f800a4, read-write)
+- First failing address register		(0x01f800a4, read-write)
 
 
 1.5 Memory interface
@@ -67,29 +67,29 @@ register is updated accordingly. Implemeted registers are:
 The following memory areas are valid for the ERC32 simulator:
 
 0x00000000 - 0x00080000		ROM (512 Kbyte, loaded at start-up)
-0x02000000 - 0x02400000		RAM (4 Mbyte, initialised to 0x0)
+0x02000000 - 0x02400000		RAM (4 Mbyte, initialized to 0x0)
 0x01f80000 - 0x01f800ff		MEC registers
 
 Access to unimplemented MEC registers or non-existing memory will result
 in a memory exception trap. However, access to unimplemented MEC registers
 in the area 0x01f80000 - 0x01f80100 will not cause a memory exception trap.
 The written value will be stored in a register and can be read back. It
-does however not affect the function in any way. 
+does however not affect the function in any way.
 
-The memory configuartion register is used to define available memory
+The memory configuration register is used to define available memory
 in the system. The fields RSIZ and PSIZ are used to set RAM and ROM
-size, the remaining fields are not used.  NOTE: after reset, the MEC 
-is set to decode 4 Kbyte of ROM and 256 Kbyte of RAM. The memory 
-configuration register has to be updated to reflect the available memory. 
+size, the remaining fields are not used.  NOTE: after reset, the MEC
+is set to decode 4 Kbyte of ROM and 256 Kbyte of RAM. The memory
+configuration register has to be updated to reflect the available memory.
 
-The waitstate configuration register is used to generate waitstates. 
-This register must also be updated with the correct configuration after 
+The waitstate configuration register is used to generate waitstates.
+This register must also be updated with the correct configuration after
 reset.
 
 The memory protection scheme is implemented - it is enabled through bit 3
 in the MEC control register.
 
-The following registers are implemeted:
+The following registers are implemented:
 
 - MEC control register (bit 3 only)		(0x01f80000, read-write)
 - Memory control register			(0x01f80010, read-write)
@@ -100,10 +100,10 @@ The following registers are implemeted:
 1.6 Watchdog
 
 The watchdog is implemented as in the specification. The input clock is
-always the system clock regardsless of WDCS bit in mec configuration 
+always the system clock regardless of WDCS bit in mec configuration
 register.
 
-The following registers are implemeted:
+The following registers are implemented:
  
 - Watchdog program and acknowledge register	(0x01f80060, write-only)
 - Watchdog trap door set register		(0x01f80064, write-only)
@@ -128,3 +128,49 @@ Bit	Name	Function
 1	SWR	Soft reset enable
 3	APR	Access protection enable
 
+1.10 IU and FPU instruction timing.
+
+The simulator provides cycle true simulation for ERC32. The following table
+shows the emulated instruction timing for 90C601E & 90C602E:
+
+Instructions	      Cycles
+
+jmpl, rett		2
+load			2
+store			3
+load double		3
+store double		4
+other integer ops	1
+fabs			2
+fadds			4
+faddd			4
+fcmps			4
+fcmpd			4
+fdivs			20
+fdivd			35
+fmovs			2
+fmuls			5
+fmuld			9
+fnegs			2
+fsqrts			37
+fsqrtd			65
+fsubs			4
+fsubd			4
+fdtoi			7
+fdots			3
+fitos			6
+fitod			6
+fstoi			6
+fstod			2
+
+The parallel operation between the IU and FPU is modelled. This means
+that a FPU instruction will execute in parallel with other instructions as
+long as no data or resource dependency is detected. See the 90C602E data
+sheet for the various types of dependencies. Tracing using the 'trace'
+command will display the current simulator time in the left column. This
+time indicates when the instruction is fetched. If a dependency is detected,
+the following fetch will be delayed until the conflict is resolved.
+
+The load dependency in the 90C601E is also modelled - if the destination
+register of a load instruction is used by the following instruction, an
+idle cycle is inserted.
diff --git a/sim/erc32/README.gdb b/sim/erc32/README.gdb
deleted file mode 100644
index 619fcb3..0000000
--- a/sim/erc32/README.gdb
+++ /dev/null
@@ -1,67 +0,0 @@
-How to use SIS with GDB
------------------------
-
-1. Building GDB with SIS
-
-To build GDB with the SIS/ERC32 simulator, configure with option
-'--target sparc-erc32-aout' and build as usual.
-
-2. Attaching the simulator
-
-To attach GDB to the simulator, use:
-
-target sim [options] [files]
-
-The following options are supported:
-
- -nfp		Disable FPU. FPops will cause an FPU disabled trap.
-
- -freq <f>	Set the simulated "system clock" to <f> MHz.
-
- -v		Verbose mode.
-
- -nogdb		Disable GDB breakpoint handling (see below)
-
-The listed [files] are expected to be in aout format and will be
-loaded in the simulator memory prior. This could be used to load
-a boot block at address 0x0 if the application is linked to run
-from RAM (0x2000000).
-
-To start debugging a program type 'load <program>' and debug as
-usual. 
-
-The native simulator commands can be reached using the GDB 'sim'
-command:
-
-sim <sis_command>
-
-Direct simulator commands during a GDB session must be issued
-with care not to disturb GDB's operation ... 
-
-For info on supported ERC32 functionality, see README.sis.
-
-
-3. Loading aout files
-
-The GDB load command loads an aout file into the simulator
-memory with the data section starting directly after the text
-section regardless of wich start address was specified for the data
-at link time! This means that your applications either has to include
-a routine that initialise the data segment at the proper address or
-link with the data placed directly after the text section.
-
-A copying routine is fairly simple, just copy all data between
-_etext and _data to a memory loaction starting at _environ. This
-should be done at the same time as the bss is cleared (in srt0.s).
-
-
-4. GDB breakpoint handling
-
-GDB inserts breakpoint in the form of the 'ta 1' instruction. The
-GDB-integrated simulator will therefore recognize the breakpoint
-instruction and return control to GDB. If the application uses
-'ta 1', the breakpoint detection can be disabled with the -nogdb
-switch. In this case however, GDB breakpoints will not work.
-
-
-Report problems to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)
diff --git a/sim/erc32/README.leon2 b/sim/erc32/README.leon2
new file mode 100644
index 0000000..c79a4e3
--- /dev/null
+++ b/sim/erc32/README.leon2
@@ -0,0 +1,53 @@
+
+1. LEON2 emulation
+
+The file 'leon2.c' contains a model of simple LEON2 sub-system. It
+contains 16 Mbyte ROM and 16 Mbyte RAM. Standard peripherals
+such as interrupt controller, UART and timer are provided.
+The model can execute leon2 binaries that do not require an
+MMU.
+
+To start sis in Leon2 mode, add the -leon2 switch. In gdb,
+use 'target sim -leon2' .
+
+1.1 UART
+
+One LEON2 UART is emulated, and is located at address 0x80000070.
+The following registers are implemented:
+
+- UART RX and TX register	(0x80000070)
+- UART status register		(0x80000074)
+
+The UART generates interrupt 3.
+
+1.2 Timer unit
+
+The LEON2 timer unit is emulated and located at address 0x80000040.
+It is configured with two timers and separate interrupts (8 and 9).
+The scaler is configured to 16 bits, while the counters are 32 bits.
+
+1.3 Interrupt controller
+
+The interrupt controller is implemented as described in the
+LEON2 IP manual, with the exception of the interrupt level register.
+Secondary interrupts are not supported. The registers are located
+at address 0x80000090.
+
+1.5 Memory interface
+
+The following memory areas are valid for the Leon3 simulator:
+
+0x00000000 - 0x01000000		ROM (16 Mbyte, loaded at start-up)
+0x40000000 - 0x41000000		RAM (16 Mbyte, loaded at start-up)
+0x80000000 - 0x81000000		APB bus, including plug&play
+0xFFFFF000 - 0xFFFFFFFF		AHB plug&play area
+
+Access to non-existing memory will result in a memory exception trap.
+
+1.8 Power-down mode
+
+The Leon2 power-down register (0x80000018) is supported. When power-down is
+entered, time is skipped forward until the next event in the event queue.
+However, if the simulator event queue is empty, power-down mode is not
+entered since no interrupt would be generated to exit from the mode. A
+Ctrl-C in the simulator window will exit the power-down mode.
diff --git a/sim/erc32/README.sis b/sim/erc32/README.sis
index 22d998b..bf2f7a7 100644
--- a/sim/erc32/README.sis
+++ b/sim/erc32/README.sis
@@ -1,5 +1,5 @@
 
-SIS - Sparc Instruction Simulator README file  (v2.8, 10-11-2014)
+SIS - Sparc Instruction Simulator README file  (v2.8, 07-29-2017)
 -------------------------------------------------------------------
 
 1. Introduction
@@ -13,11 +13,12 @@ and peripherals.
 
 The simulator is started as follows:
 
-sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
-    [-nfp] [-freq frequency] [-c batch_file] [files]
+sis [-leon2] [-leon3] [-uart1 uart_device1] [-uart2 uart_device2]
+    [-nfp] [-freq frequency] [-c batch_file] [-v] [-r] [-tlim time] [files]
 
-By default, SIS emulates an ERC32 system. The -leon3 switch
-enables emulation of a LEON3 SOC system.
+By default, SIS emulates an ERC32 system. The -leon2 switch enables
+LEON2 emulation, while the -leon3 switch enables emulation of a
+LEON3 SOC system.
 
 The emulated console uart is connected to stdin/stdout. The -uart[1,2]
 switch can be used to connect the uarts to other devices.
@@ -31,14 +32,29 @@ The frequency must be an integer indicating the frequency in MHz.
 The -c option indicates that sis commands should be read from 'batch_file'
 at startup.
 
-Files to be loaded must be in one of the supported formats (elf, a.out, srec),
-and will be loaded into the simulated memory.
+-v sets the debug level to 1, to provide some diagnostic messages.
 
-Below is description of commands  that are recognized by
-the simulator. The command-line is parsed using GNU readline. A command
+-r starts execution immediately without an interactive shell. This is useful
+for automated testing of large number of binaries.
+
+-tlim can be used together with -r to limit the amount of simulated time that
+the simulator runs for before exiting. The following units are recognized:
+us, ms and s. To limit simulated time to 100 seconds, it should thus be
+started with -r -tlim 100s .
+
+Files to be loaded must be in one of the formats supported by the BFD library.
+This inlude elf, a.out, srec and binary. On start-up, the files will be
+loaded into the simulated memory.
+
+3. Internal commands
+
+Below is the description of commands that are recognized by the simulator.
+The command-line is parsed using GNU readline. A command
 history of 64 commands is maintained. Use the up/down arrows to recall
 previous commands. For more details, see the readline documentation.
 
+* List of commands:
+
 batch <file>
 
 Execute a batch file of SIS commands.
@@ -124,7 +140,7 @@ Performs a power-on reset. This command is equal to 'run 0'.
 run [inst_count]
 
 Resets the simulator and starts execution from address 0. If an instruction
-count is given (inst_count), the simulator will stop after the specified 
+count is given (inst_count), the simulator will stop after the specified
 number of instructions. The event queue is emptied but any set breakpoints
 remain.
 
@@ -135,148 +151,97 @@ Equal to 'trace 1'
 tra [inst_count]
 
 Starts the simulator at the present position and prints each instruction
-it executes. If an instruction count is given (inst_count), the simulator 
+it executes. If an instruction count is given (inst_count), the simulator
 will stop after the specified number of instructions.
 
-Typing a 'Ctrl-C' will interrupt a running simulator. 
+wmem [addr] [data]
 
-Short forms of the commands are allowed, e.g 'c' 'co' or 'con' are all
-interpreted as 'cont'. 
+Writes [data] to memory at [addr]. Data is written as a 32-bit word.
 
+wp
 
-3. Simulator core
+Prints all watchpoints
 
-In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E
-sparc IU and FPU from Matra MHS. These are roughly equivalent to the
-Cypress C601 and C602. The simulator is cycle accurate, i.e a simulator
-time is maintained and incremented according the IU and FPU instruction timing.
-The parallel execution between the IU and FPU is modelled, as well as
-stalls due to operand dependencies (FPU).
++wpr <address>
 
-In Leon3 mode, the core emulates the Leon3 SPARC V8 core from
-Gaisler Research. All SPARC V8 instructions are supported but
-emulation is not fully cycle-true as the cache is not emulated.
+Adds an read watchpoint at address <address>.
+
+-wpr <num>
+
+Deletes read watchpoint <num>. Use 'wp' to see which number is assigned to
+the watchpoints.
+
++wpw <address>
 
-The core interacts with the user-defined memory modules through
-a number of functions. The memory module must provide the following
-functions:
-
-int memory_read(asi,addr,data,ws)
-int asi;
-unsigned int addr;
-unsigned int *data;
-int *ws;
-
-int memory_write(asi,addr,data,sz,ws)
-int asi;
-unsigned int addr;
-unsigned int *data;
-int sz;
-int *ws;
-
-int sis_memory_read(addr, data, length)
-unsigned int addr;
-char   *data;
-unsigned int length;
+Adds an write watchpoint at address <address>.
 
-int sis_memory_write(addr, data, length)
-unsigned int addr;
-char    *data;
-unsigned int length;
+-wpw <num>
 
-int init_sim()
+Deletes write watchpoint <num>. Use 'wp' to see which number is assigned to
+the watchpoints.
 
-int reset()
+Typing a 'Ctrl-C' will interrupt a running simulator.
 
-int error_mode(pc)
-unsigned int pc;
+Short forms of the commands are allowed, e.g 'c' 'co' or 'con' are all
+interpreted as 'cont'.
+
+4. Using SIS with GDB
 
-memory_read() is used by the simulator to fetch instructions and
-operands.  The address space identifier (asi) and address is passed as
-parameters. The read data should be assigned to the data pointer
-(*data) and the number of waitstate to *ws. 'memory_read' should return
-0 on success and 1 on failure. A failure will cause a data or
-instruction fetch trap. memory_read() always reads one 32-bit word.
+To attach GDB to the simulator, use:
 
-sis_memory_read() is used by the simulator to display and disassemble
-memory contants. The function should copy 'length' bytes of the simulated
-memory starting at 'addr' to '*data'.
-The sis_memory_read() should return 1 on success and 0 on failure.
-Failure should only be indicated if access to unimplemented memory is attempted.
+target sim [options]
 
-memory_write() is used to write to memory. In addition to the asi
-and address parameters, the size of the written data is given by 'sz'.
-The pointer *data points to the data to be written. The 'sz' is coded
-as follows:
+The following options are supported:
 
-  sz	access type
-  0	  byte
-  1	  halfword
-  2	  word
-  3	  double-word
+ -leon2         Emulate a LEON2 system
 
-If a double word is written, the most significant word is in data[0] and
-the least significant in data[1].
+ -leon3         Emulate a LEON3 system
 
-sis_memory_write() is used by the simulator during loading of programs.
-The function should copy 'length' bytes from *data to the simulated
-memory starting at 'addr'. sis_memory_write() should return 1 on
-success and 0 on failure. Failure should only be indicated if access
-to unimplemented memory is attempted. See erc32.c for more details
-on how to define the memory emulation functions.
+ -nfp           Disable FPU. FPops will cause an FPU disabled trap.
 
-The 'init_sim' is called once when the simulator is started. This function
-should be used to perform initialisations of user defined memory or
-peripherals that only have to be done once, such as opening files etc.
+ -freq <f>      Set the simulated "system clock" to <f> MHz.
 
-The 'reset' is called every time the simulator is reset, i.e. when a
-'run' command is given. This function should be used to simulate a power
-on reset of memory and peripherals.
+ -v             Verbose mode.
 
-error_mode() is called by the simulator when the IU goes into error mode,
-typically if a trap is caused when traps are disabled. The memory module
-can then take actions, such as issue a reset.
+ -nogdb         Disable GDB breakpoint handling (see below)
 
-sys_reset() can be called by the memory module to reset the simulator. A
-reset will empty the event queue and perform a power-on reset.
+To start debugging a program type 'load <program>' and debug as
+usual.
 
-4. Events and interrupts
+The native simulator commands can be reached using the GDB 'sim'
+command:
 
-The simulator supports an event queue and the generation of processor
-interrupts. The following functions are available to the user-defined
-memory module:
+sim <sis_command>
 
-event(cfunc,arg,delta)
-void (*cfunc)();
-int arg;
-unsigned int delta;
+Direct simulator commands during a GDB session must be issued
+with care not to disturb GDB's operation ...
 
-set_int(level,callback,arg)
-int level;
-void (*callback)();
-int arg;
+A program can be restarted in GDB by first issuing the load command,
+followed by run.
 
-clear_int(level)
-int level;
-
-sim_stop()
+4.1 GDB breakpoint handling
 
-The 'event' functions will schedule the execution of the function 'cfunc'
-at time 'now + delta' clock cycles. The parameter 'arg' is passed as a 
-parameter to 'cfunc'.
+GDB inserts breakpoint in the form of the 'ta 1' instruction. The
+GDB-integrated simulator will therefore recognize the breakpoint
+instruction and return control to GDB. If the application uses
+'ta 1', the breakpoint detection can be disabled with the -nogdb
+switch. In this case however, GDB breakpoints will not work.
 
-The 'set_int' function set the processor interrupt 'level'. When the interrupt
-is taken, the function 'callback' is called with the argument 'arg'. This
-will also clear the interrupt. An interrupt can be cleared before it is
-taken by calling 'clear_int' with the appropriate interrupt level.
 
-The sim_stop function is called each time the simulator stops execution.
-It can be used to flush buffered devices to get a clean state during
-single stepping etc.
+5. Simulator core
+
+In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E
+sparc IU and FPU from Matra MHS. These are roughly equivalent to the
+Cypress C601 and C602. The simulator is reasonably cycle accurate, a simulator
+time is maintained and incremented according the IU and FPU instruction timing.
+The parallel execution between the IU and FPU is modelled, as well as
+stalls due to operand dependencies (FPU).
 
-See 'erc32.c' for examples on how to use events and interrupts.
+In Leon2/3 mode, the core emulates the Leon2/3 SPARC V8 core from
+Gaisler Research. All SPARC V8 instructions are supported but
+emulation is not fully cycle-true as the cache is not emulated.
 
-5. Memory module
+6. Memory module
 
 The ERC32 memory module (erc32.c) emulates the functions of memory and
 the MEC asic developed for the 90C601/2. It includes the following functions:
@@ -292,6 +257,19 @@ the MEC asic developed for the 90C601/2. It includes the following functions:
 
 See README.erc32 on how the MEC functions are emulated.
 
+The Leon2 memory module (leon2.c) emulates on-chip peripherals and
+external memory for a simple Leon2 system. The modules includes the
+following functions:
+
+* AHB and APB buses
+* One UART
+* Interrupt controller
+* Timer unit with two timers
+* PROM/SRAM memory controller
+* 16 Mbyte PROM, 16 Mbyte SRAM
+
+See README.leon2 for further details on Leon2 emulation.
+
 The Leon3 memory module (leon3.c) emulates on-chip peripherals and
 external memory for a simple Leon3 system. The modules includes the
 following functions:
@@ -305,57 +283,8 @@ following functions:
 
 See README.leon3 for further details on Leon3 emulation.
 
-6. Compile and linking programs
-
-7. IU and FPU instruction timing.
-
-The simulator provides cycle true simulation for ERC32. The following table
-shows the emulated instruction timing for 90C601E & 90C602E:
-
-Instructions	      Cycles
-
-jmpl, rett		2
-load			2
-store			3
-load double		3
-store double		4
-other integer ops	1
-fabs			2
-fadds			4
-faddd			4
-fcmps			4
-fcmpd			4
-fdivs			20
-fdivd			35
-fmovs			2
-fmuls			5
-fmuld			9
-fnegs			2
-fsqrts			37
-fsqrtd			65
-fsubs			4
-fsubd			4
-fdtoi			7
-fdots			3
-fitos			6
-fitod			6
-fstoi			6
-fstod			2
-
-The parallel operation between the IU and FPU is modelled. This means
-that a FPU instruction will execute in parallel with other instructions as
-long as no data or resource dependency is detected. See the 90C602E data
-sheet for the various types of dependencies. Tracing using the 'trace'
-command will display the current simulator time in the left column. This
-time indicates when the instruction is fetched. If a dependency is detetected,
-the following fetch will be delayed until the conflict is resolved.
-
-The load dependency in the 90C601E is also modelled - if the destination 
-register of a load instruction is used by the following instruction, an 
-idle cycle is inserted.
-
-8. FPU implementation
+7. FPU implementation
 
 The simulator maps floating-point operations on the hosts floating point
-capabilities. This means that accuracy and generation of IEEE exceptions is 
+capabilities. This means that accuracy and generation of IEEE exceptions is
 host dependent.
diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index 3ab70c2..cc74fad 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -24,7 +24,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <termios.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index ff68259..3baf165 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -21,7 +21,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include "sis.h"
 #include "libiberty.h"
 #include "bfd.h"
diff --git a/sim/erc32/leon2.c b/sim/erc32/leon2.c
index 87bee6a..231fa7a 100644
--- a/sim/erc32/leon2.c
+++ b/sim/erc32/leon2.c
@@ -27,7 +27,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <termios.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
diff --git a/sim/erc32/leon3.c b/sim/erc32/leon3.c
index 4f35386..ce2851a 100644
--- a/sim/erc32/leon3.c
+++ b/sim/erc32/leon3.c
@@ -28,7 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <termios.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 83dd5cf..85f105b 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #endif
 #include <stdio.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
 #include "sis.h"
 #include <dis-asm.h>
 #include "sim-config.h"
diff --git a/sim/erc32/startsim b/sim/erc32/startsim
deleted file mode 100644
index 7606c5e..0000000
--- a/sim/erc32/startsim
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
-#
-# 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/>.
-
-xterm -e sis $* &
-xterm -e tip /dev/ttypc &
-
-- 
2.7.4

From 033a639525f9e49668c3efa92705aeb9ef0b7d66 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <jiri@gaisler.se>
Date: Wed, 9 Aug 2017 22:52:45 +0200
Subject: [PATCH 11/11] sim/erc32: Fix to build on mingw64.

	* erc32.c, leon2.c, leon3.c: Remove unecessary include fo fcntl.h.
	Check existens of termios.h before using termios. Check for O_NONBLOCK.
	Change caddr_t to int32 tyoes in event handlers.
	* interf.c: Check for HAVE_FCNTL_H before including fcntl.h. Check
	for F_GETFL and F_SETFL before calling fcntl().
	* sis.c: As above.
	* configure.ac: Check for termios.h
	* config.in: Re-generate.
	* configure.in: Re-generate
---
 sim/erc32/config.in    |  3 +++
 sim/erc32/configure    | 21 ++++++++++++++---
 sim/erc32/configure.ac |  2 ++
 sim/erc32/erc32.c      | 37 ++++++++++++++++++++---------
 sim/erc32/func.c       | 64 ++++++++++++++++++++++++++++++++++++++++++++++++--
 sim/erc32/interf.c     |  6 +++++
 sim/erc32/leon2.c      | 27 +++++++++++++++------
 sim/erc32/leon3.c      | 27 +++++++++++++++------
 sim/erc32/sis.c        |  2 ++
 9 files changed, 159 insertions(+), 30 deletions(-)

diff --git a/sim/erc32/config.in b/sim/erc32/config.in
index aa3e45c..f9ce1d1 100644
--- a/sim/erc32/config.in
+++ b/sim/erc32/config.in
@@ -127,6 +127,9 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
 /* Define to 1 if you have the `time' function. */
 #undef HAVE_TIME
 
diff --git a/sim/erc32/configure b/sim/erc32/configure
index 8f9a558..42dc398 100755
--- a/sim/erc32/configure
+++ b/sim/erc32/configure
@@ -2378,6 +2378,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+
+
 # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
 #
 #   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
@@ -10790,7 +10792,7 @@ _LT_EOF
 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
 	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	else
-	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
 	fi
 	aix_use_runtimelinking=no
 
@@ -12818,7 +12820,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12821 "configure"
+#line 12823 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12924,7 +12926,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12927 "configure"
+#line 12929 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13475,6 +13477,19 @@ _ACEOF
 
 
 
+for ac_header in termios.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default"
+if test "x$ac_cv_header_termios_h" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_TERMIOS_H 1
+_ACEOF
+
+fi
+
+done
+
+
 # In the Cygwin environment, we need some additional flags.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cygwin" >&5
 $as_echo_n "checking for cygwin... " >&6; }
diff --git a/sim/erc32/configure.ac b/sim/erc32/configure.ac
index 8b430d9..6e1ae77 100644
--- a/sim/erc32/configure.ac
+++ b/sim/erc32/configure.ac
@@ -20,6 +20,8 @@ sinclude(../common/acinclude.m4)
 
 SIM_AC_COMMON
 
+AC_CHECK_HEADERS(termios.h)
+
 # In the Cygwin environment, we need some additional flags.
 AC_CACHE_CHECK([for cygwin], sim_cv_os_cygwin,
 [AC_EGREP_CPP(lose, [
diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index cc74fad..d2b9194 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -23,8 +23,9 @@
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
-#include <fcntl.h>
+#endif
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
@@ -226,7 +227,13 @@ static char     wbufa[UARTBUF], wbufb[UARTBUF];
 static unsigned wnuma;
 static unsigned wnumb;
 static FILE    *f1in, *f1out, *f2in, *f2out;
+#ifdef HAVE_TERMIOS_H
 static struct termios ioc1, ioc2, iocold1, iocold2;
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0
+#endif
+
 static int      f1open = 0, f2open = 0;
 
 static char     uarta_sreg, uarta_hreg, uartb_sreg, uartb_hreg;
@@ -263,17 +270,17 @@ static void	write_uart (uint32 addr, uint32 data);
 static void	flush_uart (void);
 static void	uarta_tx (void);
 static void	uartb_tx (void);
-static void	uart_rx (caddr_t arg);
-static void	uart_intr (caddr_t arg);
+static void	uart_rx (int32 arg);
+static void	uart_intr (int32 arg);
 static void	uart_irq_start (void);
-static void	wdog_intr (caddr_t arg);
+static void	wdog_intr (int32 arg);
 static void	wdog_start (void);
-static void	rtc_intr (caddr_t arg);
+static void	rtc_intr (int32 arg);
 static void	rtc_start (void);
 static uint32	rtc_counter_read (void);
 static void	rtc_scaler_set (uint32 val);
 static void	rtc_reload_set (uint32 val);
-static void	gpt_intr (caddr_t arg);
+static void	gpt_intr (int32 arg);
 static void	gpt_start (void);
 static uint32	gpt_counter_read (void);
 static void	gpt_scaler_set (uint32 val);
@@ -919,6 +926,7 @@ init_stdio()
 {
     if (dumbio)
 	return; /* do nothing */
+#ifdef HAVE_TERMIOS_H
     if (ifd1 == 0 && f1open) {
 	tcsetattr(0, TCSANOW, &ioc1);
 	tcflush (ifd1, TCIFLUSH);
@@ -927,6 +935,7 @@ init_stdio()
 	tcsetattr(0, TCSANOW, &ioc2);
 	tcflush (ifd2, TCIFLUSH);
     }
+#endif
 }
 
 static void
@@ -934,10 +943,12 @@ restore_stdio()
 {
     if (dumbio)
 	return; /* do nothing */
+#ifdef HAVE_TERMIOS_H
     if (ifd1 == 0 && f1open && tty_setup)
 	tcsetattr(0, TCSANOW, &iocold1);
     if (ifd2 == 0 && f2open && tty_setup)
 	tcsetattr(0, TCSANOW, &iocold2);
+#endif
 }
 
 #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
@@ -980,6 +991,7 @@ port_init()
 	if (sis_verbose)
 	    printf("serial port A on stdin/stdout\n");
         if (!dumbio) {
+#ifdef HAVE_TERMIOS_H
 	    tcgetattr (ifd1, &ioc1);
 	    if (tty_setup) {
 		iocold1 = ioc1;
@@ -987,6 +999,7 @@ port_init()
 		ioc1.c_cc[VMIN] = 0;
 		ioc1.c_cc[VTIME] = 0;
 	    }
+#endif
         }
 	f1open = 1;
     }
@@ -1012,6 +1025,7 @@ port_init()
 	if (sis_verbose)
 	    printf("serial port B on stdin/stdout\n");
         if (!dumbio) {
+#ifdef HAVE_TERMIOS_H
             tcgetattr(ifd2, &ioc2);
             if (tty_setup) {
 		iocold2 = ioc2;
@@ -1019,6 +1033,7 @@ port_init()
 		ioc2.c_cc[VMIN] = 0;
 		ioc2.c_cc[VTIME] = 0;
 	    }
+#endif
         }
 	f2open = 1;
     }
@@ -1308,7 +1323,7 @@ uartb_tx()
 
 static void
 uart_rx(arg)
-    caddr_t         arg;
+    int32         arg;
 {
     int32           rsize;
     char            rxd;
@@ -1355,7 +1370,7 @@ uart_rx(arg)
 
 static void
 uart_intr(arg)
-    caddr_t         arg;
+    int32         arg;
 {
     read_uart(0xE8);		/* Check for UART interrupts every 1000 clk */
     flush_uart();		/* Flush UART ports      */
@@ -1379,7 +1394,7 @@ uart_irq_start()
 
 static void
 wdog_intr(arg)
-    caddr_t         arg;
+    int32         arg;
 {
     if (wdog_status == disabled) {
 	wdog_status = stopped;
@@ -1418,7 +1433,7 @@ wdog_start()
 
 static void
 rtc_intr(arg)
-    caddr_t         arg;
+    int32         arg;
 {
     if (rtc_counter == 0) {
 
@@ -1472,7 +1487,7 @@ rtc_reload_set(val)
 
 static void
 gpt_intr(arg)
-    caddr_t         arg;
+    int32         arg;
 {
     if (gpt_counter == 0) {
 	mec_irq(12);
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index a94a0ca..1cf7e45 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -82,8 +82,9 @@ static int	disp_fpu (struct pstate  *sregs);
 static void	disp_regs (struct pstate  *sregs, int cwp);
 static void	disp_ctrl (struct pstate *sregs);
 static void	disp_mem (uint32 addr, uint32 len);
+static ssize_t 	mygetline (char **lineptr, size_t *n, FILE *stream);
 
-static int 
+static int
 batch(sregs, fname)
     struct pstate  *sregs;
     char           *fname;
@@ -97,7 +98,7 @@ batch(sregs, fname)
 	fprintf(stderr, "couldn't open batch file %s\n", fname);
 	return 0;
     }
-    while (getline(&lbuf, &len, fp) > -1) {
+    while (mygetline(&lbuf, &len, fp) > -1) {
 	slen = strlen(lbuf);
 	if (slen && (lbuf[slen - 1] == '\n')) {
 	    lbuf[slen - 1] = 0;
@@ -1242,3 +1243,62 @@ double get_time (void)
     usec = ((double) tm.tv_sec) * 1E6 + ((double) tm.tv_usec);
     return usec / 1E6;
 }
+
+/* Local version of getline() since not all systems supports it */
+
+static const int line_size = 128;
+
+static ssize_t
+mygetdelim (char **lineptr, size_t *n, int delim, FILE *stream)
+{
+  int indx = 0;
+  int c;
+
+  /* Sanity checks.  */
+  if (lineptr == NULL || n == NULL || stream == NULL)
+    return -1;
+
+  /* Allocate the line the first time.  */
+  if (*lineptr == NULL)
+    {
+      *lineptr = malloc (line_size);
+      if (*lineptr == NULL)
+        return -1;
+      *n = line_size;
+    }
+
+  /* Clear the line.  */
+  memset (*lineptr, '\0', *n);
+
+  while ((c = getc (stream)) != EOF)
+    {
+      /* Check if more memory is needed.  */
+      if (indx >= *n)
+        {
+          *lineptr = realloc (*lineptr, *n + line_size);
+          if (*lineptr == NULL)
+            {
+              return -1;
+            }
+          /* Clear the rest of the line.  */
+          memset(*lineptr + *n, '\0', line_size);
+          *n += line_size;
+        }
+
+      /* Push the result in the line.  */
+      (*lineptr)[indx++] = c;
+
+      /* Bail out.  */
+      if (c == delim)
+        {
+          break;
+        }
+    }
+  return (c == EOF) ? -1 : indx;
+}
+
+static ssize_t
+mygetline (char **lineptr, size_t *n, FILE *stream)
+{
+  return mygetdelim (lineptr, n, '\n', stream);
+}
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 3baf165..da0e7c3 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -21,7 +21,9 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#endif
 #include "sis.h"
 #include "libiberty.h"
 #include "bfd.h"
@@ -215,7 +217,9 @@ sim_open (kind, callback, abfd, argv)
 	  (*sim_callback->printf_filtered) (sim_callback, "CPU freq %3.1f MHz\n", sregs.freq);
     }
 
+#ifdef F_GETFL
     termsave = fcntl(0, F_GETFL, 0);
+#endif
     INIT_DISASSEMBLE_INFO(dinfo, stdout,(fprintf_ftype)fprintf);
 #ifdef HOST_LITTLE_ENDIAN
     dinfo.endian = BFD_ENDIAN_LITTLE;
@@ -239,7 +243,9 @@ sim_close(sd, quitting)
 {
 
     ms->exit_sim ();
+#if defined(F_GETFL) && defined(F_SETFL)
     fcntl(0, F_SETFL, termsave);
+#endif
 
 };
 
diff --git a/sim/erc32/leon2.c b/sim/erc32/leon2.c
index 231fa7a..09402f7 100644
--- a/sim/erc32/leon2.c
+++ b/sim/erc32/leon2.c
@@ -26,8 +26,9 @@
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
-#include <fcntl.h>
+#endif
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
@@ -127,7 +128,13 @@ static char wbufa[UARTBUF], wbufb[UARTBUF];
 static unsigned wnuma;
 static unsigned wnumb;
 static FILE *f1in, *f1out;
+#ifdef HAVE_TERMIOS_H
 static struct termios ioc1, ioc2, iocold1, iocold2;
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0
+#endif
+
 static int f1open = 0;
 
 static char uarta_sreg, uarta_hreg;
@@ -149,10 +156,10 @@ static uint32 grlib_read_uart (uint32 addr);
 static void grlib_write_uart (uint32 addr, uint32 data);
 static void flush_uart (void);
 static void uarta_tx (void);
-static void uart_rx (caddr_t arg);
-static void uart_intr (caddr_t arg);
+static void uart_rx (int32 arg);
+static void uart_intr (int32 arg);
 static void uart_irq_start (void);
-static void gpt_intr (caddr_t arg);
+static void gpt_intr (int32 arg);
 static void gpt_init (void);
 static void gpt_reset (void);
 static void gpt_scaler_set (uint32 val);
@@ -451,11 +458,13 @@ init_stdio (void)
 {
   if (dumbio)
     return;
+#ifdef HAVE_TERMIOS_H
   if (ifd1 == 0 && f1open)
     {
       tcsetattr (0, TCSANOW, &ioc1);
       tcflush (ifd1, TCIFLUSH);
     }
+#endif
 }
 
 static void
@@ -463,8 +472,10 @@ restore_stdio (void)
 {
   if (dumbio)
     return;
+#ifdef HAVE_TERMIOS_H
   if (ifd1 == 0 && f1open && tty_setup)
     tcsetattr (0, TCSANOW, &iocold1);
+#endif
 }
 
 #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
@@ -500,6 +511,7 @@ port_init (void)
 	printf ("serial port A on stdin/stdout\n");
       if (!dumbio)
 	{
+#ifdef HAVE_TERMIOS_H
 	  tcgetattr (ifd1, &ioc1);
 	  if (tty_setup)
 	    {
@@ -508,6 +520,7 @@ port_init (void)
 	      ioc1.c_cc[VMIN] = 0;
 	      ioc1.c_cc[VTIME] = 0;
 	    }
+#endif
 	}
       f1open = 1;
     }
@@ -700,7 +713,7 @@ uarta_tx (void)
 }
 
 static void
-uart_rx (caddr_t arg)
+uart_rx (int32 arg)
 {
   char rxd;
   int32 rsize = 0;
@@ -723,7 +736,7 @@ uart_rx (caddr_t arg)
 }
 
 static void
-uart_intr (caddr_t arg)
+uart_intr (int32 arg)
 {
   /* Check for UART interrupts every 1000 clk.  */
   grlib_read_uart (APBUART_STATUS);
@@ -747,7 +760,7 @@ uart_irq_start (void)
 /* TIMER */
 
 static void
-gpt_intr (caddr_t arg)
+gpt_intr (int32 arg)
 {
   int i;
 
diff --git a/sim/erc32/leon3.c b/sim/erc32/leon3.c
index ce2851a..0523411 100644
--- a/sim/erc32/leon3.c
+++ b/sim/erc32/leon3.c
@@ -27,8 +27,9 @@
 #include <sys/types.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
-#include <fcntl.h>
+#endif
 #include <sys/file.h>
 #include <unistd.h>
 #include "sis.h"
@@ -126,7 +127,13 @@ static char wbufa[UARTBUF], wbufb[UARTBUF];
 static unsigned wnuma;
 static unsigned wnumb;
 static FILE *f1in, *f1out;
+#ifdef HAVE_TERMIOS_H
 static struct termios ioc1, ioc2, iocold1, iocold2;
+#endif
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0
+#endif
+
 static int f1open = 0;
 
 static char uarta_sreg, uarta_hreg;
@@ -148,10 +155,10 @@ static uint32 grlib_read_uart (uint32 addr);
 static void grlib_write_uart (uint32 addr, uint32 data);
 static void flush_uart (void);
 static void uarta_tx (void);
-static void uart_rx (caddr_t arg);
-static void uart_intr (caddr_t arg);
+static void uart_rx (int32 arg);
+static void uart_intr (int32 arg);
 static void uart_irq_start (void);
-static void gpt_intr (caddr_t arg);
+static void gpt_intr (int32 arg);
 static void gpt_init (void);
 static void gpt_reset (void);
 static void gpt_scaler_set (uint32 val);
@@ -445,11 +452,13 @@ init_stdio (void)
 {
   if (dumbio)
     return;
+#ifdef HAVE_TERMIOS_H
   if (ifd1 == 0 && f1open)
     {
       tcsetattr (0, TCSANOW, &ioc1);
       tcflush (ifd1, TCIFLUSH);
     }
+#endif
 }
 
 static void
@@ -457,8 +466,10 @@ restore_stdio (void)
 {
   if (dumbio)
     return;
+#ifdef HAVE_TERMIOS_H
   if (ifd1 == 0 && f1open && tty_setup)
     tcsetattr (0, TCSANOW, &iocold1);
+#endif
 }
 
 #define DO_STDIO_READ( _fd_, _buf_, _len_ )          \
@@ -496,6 +507,7 @@ port_init (void)
 	printf ("serial port A on stdin/stdout\n");
       if (!dumbio)
 	{
+#ifdef HAVE_TERMIOS_H
 	  tcgetattr (ifd1, &ioc1);
 	  if (tty_setup)
 	    {
@@ -504,6 +516,7 @@ port_init (void)
 	      ioc1.c_cc[VMIN] = 0;
 	      ioc1.c_cc[VTIME] = 0;
 	    }
+#endif
 	}
       f1open = 1;
     }
@@ -700,7 +713,7 @@ uarta_tx (void)
 }
 
 static void
-uart_rx (caddr_t arg)
+uart_rx (int32 arg)
 {
   char rxd;
   int32 rsize = 0;
@@ -724,7 +737,7 @@ uart_rx (caddr_t arg)
 }
 
 static void
-uart_intr (caddr_t arg)
+uart_intr (int32 arg)
 {
   /* Check for UART interrupts every 1000 clk.  */
   grlib_read_uart (APBUART_STATUS);
@@ -748,7 +761,7 @@ uart_irq_start (void)
 /* GPTIMER.  */
 
 static void
-gpt_intr (caddr_t arg)
+gpt_intr (int32 arg)
 {
   int i;
 
diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c
index 85f105b..f78986e 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -242,7 +242,9 @@ main(argc, argv)
     dinfo.endian = BFD_ENDIAN_BIG;
 #endif
 
+#ifdef F_GETFL
     termsave = fcntl(0, F_GETFL, 0);
+#endif
     using_history();
     init_signals();
     ebase.simtime = 0;
-- 
2.7.4

