This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 18/23] sim/erc32: Add support for 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.ZZ
---
 sim/erc32/Makefile.in  |    6 +-
 sim/erc32/README.leon3 |   53 +++
 sim/erc32/README.sis   |   79 ++--
 sim/erc32/erc32.c      |   48 ++-
 sim/erc32/exec.c       |  228 +++++++++--
 sim/erc32/func.c       |   51 ++-
 sim/erc32/grlib.c      |   98 +++++
 sim/erc32/grlib.h      |   57 +++
 sim/erc32/interf.c     |   26 +-
 sim/erc32/leon3.c      | 1066 ++++++++++++++++++++++++++++++++++++++++++++++++
 sim/erc32/sis.c        |   22 +-
 sim/erc32/sis.h        |   49 ++-
 12 files changed, 1658 insertions(+), 125 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 7dfc7da..63b0f0b 100644
--- a/sim/erc32/Makefile.in
+++ b/sim/erc32/Makefile.in
@@ -21,7 +21,7 @@
 TERMCAP_LIB = @TERMCAP@
 READLINE_LIB = @READLINE@
 
-SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
+SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o leon3.o grlib.o
 SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
 SIM_EXTRA_ALL = sis
 SIM_EXTRA_INSTALL = install-sis
@@ -35,7 +35,7 @@ SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcdir)/../..
 ## COMMON_POST_CONFIG_FRAG
 
 # `sis' doesn't need interf.o.
-SIS_OFILES = exec.o erc32.o func.o help.o float.o
+SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o
 
 sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
 	$(CC) $(ALL_CFLAGS) -o sis \
@@ -64,3 +64,5 @@ func.o: func.c sis.h
 help.o: help.c sis.h
 interf.o: interf.c sis.h
 sis.o: sis.c sis.h
+grlib.o: grlib.c sis.h grlib.h
+leon3.o: leon3.c sis.h grlib.h
diff --git a/sim/erc32/README.leon3 b/sim/erc32/README.leon3
new file mode 100644
index 0000000..00ab14a
--- /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 implemeted:
+
+- 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..eb4a683 100644
--- a/sim/erc32/README.sis
+++ b/sim/erc32/README.sis
@@ -1,10 +1,10 @@
 
-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. 
@@ -13,28 +13,28 @@ and peripherals.
 
 The simulator is started as follows: 
 
-sis [-uart1 uart_device1] [-uart2 uart_device2] 
+sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2] 
     [-nfp] [-freq frequency] [-c batch_file] [files] 
 
-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.
+By default, SIS emaultes an ERC32 system. The -leon3 switch
+enables emulation of a LEON3 SOC system.
+
+The emulated console uart is connected stdin/stdout. The -uart[1,2]
+switch can be used to connect the uarts to other devices.
+
 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' 
 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
 
@@ -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
+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 true, i.e a simulator time is
 maintained and inremented 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
+emaultion 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;
@@ -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 1c55579..0846bab 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -1636,19 +1636,20 @@ memory_iread(addr, data, ws)
 }
 
 static int
-memory_read(asi, addr, data, sz, ws)
-    int32           asi;
+memory_read(addr, data, sz, ws)
     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);
+        if (sregs.psr & 0x080) asi = 11; else asi = 10;
 	set_sfsr(errmec, addr, asi, 1);
 	if (errmec == 5) mecparerror();
 	if (errmec == 6) iucomperr();
@@ -1662,6 +1663,7 @@ memory_read(asi, addr, data, sz, ws)
 	*ws = mem_ramr_ws;
 	return (0);
     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+        if (sregs.psr & 0x080) asi = 11; else asi = 10;
 	mexc = mec_read(addr, asi, data);
 	if (mexc) {
 	    set_sfsr(MEC_ACC, addr, asi, 1);
@@ -1701,19 +1703,30 @@ memory_read(asi, addr, data, sz, ws)
     }
 
     printf("Memory exception at %x (illegal address)\n", addr);
+    if (sregs.psr & 0x080) asi = 11; else asi = 10;
     set_sfsr(UIMP_ACC, addr, asi, 1);
     *ws = MEM_EX_WS;
     return (1);
 }
 
 static int
-memory_write(asi, addr, data, sz, ws)
+memory_read_asi(asi, addr, data, sz, ws)
     int32           asi;
     uint32          addr;
     uint32         *data;
     int32           sz;
     int32          *ws;
 {
+    return(memory_read(addr, data, sz, ws));
+}
+
+static int
+memory_write(addr, data, sz, ws)
+    uint32          addr;
+    uint32         *data;
+    int32           sz;
+    int32          *ws;
+{
     uint32          byte_addr;
     uint32          byte_mask;
     uint32          waddr;
@@ -1721,11 +1734,13 @@ memory_write(asi, addr, data, sz, ws)
     int32           mexc;
     int             i;
     int             wphit[2];
+    int32           asi;
 
 #ifdef ERRINJ
     if (errmec) {
 	if (sis_verbose)
 	    printf("Inserted MEC error %d\n",errmec);
+        if (sregs.psr & 0x080) asi = 11; else asi = 10;
 	set_sfsr(errmec, addr, asi, 0);
 	if (errmec == 5) mecparerror();
 	if (errmec == 6) iucomperr();
@@ -1738,6 +1753,7 @@ memory_write(asi, addr, data, sz, ws)
 	if (mem_accprot) {
 
 	    waddr = (addr & 0x7fffff) >> 2;
+            if (sregs.psr & 0x080) asi = 11; else asi = 10;
 	    for (i = 0; i < 2; i++)
 		wphit[i] =
 		    (((asi == 0xa) && (mec_wpr[i] & 1)) ||
@@ -1761,6 +1777,7 @@ memory_write(asi, addr, data, sz, ws)
 	return (0);
 
     } else if ((addr >= MEC_START) && (addr < MEC_END)) {
+        if (sregs.psr & 0x080) asi = 11; else asi = 10;
 	if ((sz != 2) || (asi != 0xb)) {
 	    set_sfsr(MEC_ACC, addr, asi, 0);
 	    *ws = MEM_EX_WS;
@@ -1817,10 +1834,22 @@ memory_write(asi, addr, data, sz, ws)
     }
 	
     *ws = MEM_EX_WS;
+    if (sregs.psr & 0x080) asi = 11; else asi = 10;
     set_sfsr(UIMP_ACC, addr, asi, 0);
     return (1);
 }
 
+static int
+memory_write_asi(asi, addr, data, sz, ws)
+    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;
@@ -1864,6 +1893,12 @@ sis_memory_read(addr, data, length)
     uint32          length;
 {
     char           *mem;
+    int            ws;
+
+    if (length == 4) {
+      memory_read(addr, data, length, &ws);
+      return(4);
+    }
 
     if ((mem = get_mem_ptr(addr, length)) == ((char *) -1))
 	return (0);
@@ -1872,7 +1907,7 @@ sis_memory_read(addr, data, length)
     return (length);
 }
 
-void
+static void
 boot_init ()
 {
     mec_write(MEC_WCR, 0);	/* zero waitstates */
@@ -1896,7 +1931,10 @@ 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 6d80306..13d5805 100644
--- a/sim/erc32/exec.c
+++ b/sim/erc32/exec.c
@@ -1065,17 +1065,17 @@ dispatch_instruction(sregs)
 		*rdd = sregs->psr;
 		break;
 	    case RDY:
-                if (!sparclite)
+                if ((!sparclite) && (cputype != CPU_LEON3))
                     *rdd = sregs->y;
                 else {
                     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;
@@ -1121,13 +1121,19 @@ 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 if ( 17 == rd ) {
+                        if (sparclite)
+                            sregs->asr17 = (rs1 ^ operand2);
+                    }
+                    else if ( 19 == rd ) {
+                        if (cputype == CPU_LEON3)
+                            wait_for_irq();
+                    }
                     else {
                         sregs->trap = TRAP_UNIMP;
                         break;
@@ -1227,6 +1233,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;
@@ -1239,9 +1271,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) {
@@ -1257,12 +1289,24 @@ 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;
@@ -1272,8 +1316,27 @@ 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) {
@@ -1283,7 +1346,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;
@@ -1295,9 +1358,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;
@@ -1312,13 +1387,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;
@@ -1344,7 +1435,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 +
@@ -1370,9 +1461,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) {
@@ -1401,7 +1492,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;
@@ -1423,7 +1514,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;
@@ -1432,12 +1523,22 @@ 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;
@@ -1445,8 +1546,14 @@ 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;
@@ -1454,6 +1561,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;
@@ -1466,7 +1595,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
@@ -1495,7 +1624,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
@@ -1511,12 +1640,22 @@ 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;
@@ -1535,7 +1674,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;
@@ -1555,7 +1694,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
@@ -1567,18 +1706,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) {
@@ -1814,7 +1975,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;
@@ -1996,7 +2157,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;
@@ -2043,7 +2204,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;
@@ -2072,4 +2236,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 26cf5ef..6f985a1 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -45,7 +45,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;
@@ -60,6 +60,7 @@ uint32		last_load_addr = 0;
 int		nouartrx = 0;
 host_callback 	*sim_callback;
 struct memsys *ms = &erc32sys;
+int		cputype = 0;		/* 0 = erc32, 3 = leon3 */
 
 #ifdef ERRINJ
 uint32		errcnt = 0;
@@ -477,7 +478,7 @@ exec_cmd(sregs, cmd)
 	    }
 	    sregs->pc = len & ~3;
 	    sregs->npc = sregs->pc + 4;
-	    if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
+	    if ((sregs->pc != 0) && (ebase.simtime == 0)) 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);
@@ -553,6 +554,11 @@ exec_cmd(sregs, 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 {
@@ -604,6 +610,11 @@ exec_cmd(sregs, 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;
@@ -639,8 +650,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;
     stime = ebase.simtime - sregs->simstart;	/* Total simulated time */
@@ -654,31 +665,31 @@ show_stat(sregs)
     printf(" Instructions : %9llu\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);
-    printf(" Processor utilisation       : %.2f %%\n", 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
+	   (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 - ((double) sregs->pwdtime / (double) stime)));
     printf(" Real-time performance       : %.2f %%\n", 100.0/
       ((sregs->tottime) / ((double) (stime) / (sregs->freq * 1.0E6))));
     printf(" Simulator performance       : %.2f MIPS\n",(double)(sregs->ninst)/sregs->tottime/1E6);
diff --git a/sim/erc32/grlib.c b/sim/erc32/grlib.c
new file mode 100644
index 0000000..42a3ed0
--- /dev/null
+++ b/sim/erc32/grlib.c
@@ -0,0 +1,98 @@
+/*
+ * 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..4d52211
--- /dev/null
+++ b/sim/erc32/grlib.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+int grlib_apbpp_add(uint32 id, uint32 addr);
+int grlib_ahbmpp_add(uint32 id);
+int grlib_ahbspp_add(uint32 id, uint32 addr1, uint32 addr2,
+                     uint32 addr3, uint32 addr4);
+uint32 grlib_ahbpnp_read(uint32 addr);
+uint32 grlib_apbpnp_read(uint32 addr);
+void grlib_init();
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 2fab99f..6a406ba 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -52,7 +52,7 @@ run_sim(sregs, icount, dis)
    ms->init_stdio();
    sregs->starttime = get_time();
    irq = 0;
-   if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
+   if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init();
    while (!sregs->err_mode & (icount > 0)) {
 
 	sregs->fhold = 0;
@@ -187,6 +187,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
@@ -224,9 +228,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)
@@ -235,11 +251,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
@@ -457,7 +471,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..e79169e
--- /dev/null
+++ b/sim/erc32/leon3.c
@@ -0,0 +1,1066 @@
+/*
+ * 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"
+
+static int tty_setup = 1; /* default setup if not a tty */
+
+/* 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 */
+
+static int32    fd1, fd2;	/* file descriptor for input file */
+static int32    Ucontrol;	/* UART status register */
+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()
+{
+    callback = sim_callback;
+    grlib_init();
+    mem_init();
+    port_init();
+    gpt_init();
+}
+
+/* Power-on reset init */
+
+static void
+reset()
+{
+    leon3_reset();
+    uart_irq_start();
+    gpt_reset();
+}
+
+/* IU error mode manager */
+
+static void
+error_mode(pc)
+    uint32          pc;
+{
+
+}
+
+
+/* Memory init */
+
+static void
+mem_init()
+{
+
+/* 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()
+{
+#ifdef FAST_UART
+    flush_uart();
+#endif
+}
+
+static void
+close_port()
+{
+    if (f1open && f1in != stdin)
+	fclose(f1in);
+}
+
+static void
+exit_sim()
+{
+    close_port();
+}
+
+static void
+leon3_reset()
+{
+    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(level)
+    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()
+{
+    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(level)
+    int32           level;
+{
+    irqmp_ipr |= (1 << level);
+    chk_irq();
+}
+
+static int32
+apb_read(addr, data)
+    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(addr, data)
+    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()
+{
+    if (dumbio)
+        return; /* do nothing */
+    if (ifd1 == 0 && f1open) {
+	tcsetattr(0, TCSANOW, &ioc1);
+        tcflush(ifd1, TCIFLUSH);
+    }
+}
+
+static void
+restore_stdio()
+{
+    if (dumbio)
+        return; /* do nothing */
+    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()
+{
+
+    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(addr)
+    uint32          addr;
+{
+
+    unsigned        tmp;
+
+    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 MEC register (%x)\n", addr);
+
+    }
+    return (0);
+}
+
+static void
+grlib_write_uart(addr, data)
+    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 APB register (%x)\n", addr);
+
+    }
+}
+
+static void
+flush_uart()
+{
+    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()
+{
+    while (f1open) {
+        if (ofd1 == 1 && callback) {
+            while (callback->write_stdout(callback, &uarta_sreg, 1) != 1);
+        }
+        else {
+            while (fwrite(&uarta_sreg, 1, 1, f1out) != 1);
+        }
+    }
+    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(arg)
+    caddr_t         arg;
+{
+    int32           rsize;
+    char            rxd;
+
+
+    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(arg)
+    caddr_t         arg;
+{
+    grlib_read_uart(APBUART_STATUS); /* Check for UART interrupts every 1000 clk */
+    flush_uart();		/* Flush UART ports      */
+    event(uart_intr, 0, UART_FLUSH_TIME);
+}
+
+
+static void
+uart_irq_start()
+{
+#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(arg)
+    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()
+{
+    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()
+{
+    event(gpt_intr, 0, gpt_scaler + 1);
+    gpt_scaler_start = now();
+}
+
+static void
+gpt_scaler_set(val)
+    uint32          val;
+{
+    gpt_scaler = val & 0x0ffff;	/* 16-bit scaler */
+}
+
+static void
+timer_ctrl(val, i)
+    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 (mem, waddr, data, sz, ws)
+    unsigned char  *mem;
+    uint32	   waddr;
+    uint32	   *data;
+    int32	    sz;
+    int32	   *ws;
+{
+    switch (sz) {
+	case 0:
+#ifdef HOST_LITTLE_ENDIAN
+	    waddr ^= 3;
+#endif
+	    mem[waddr] = *data & 0x0ff;
+	    *ws = 0;
+	    break;
+	case 1:
+#ifdef HOST_LITTLE_ENDIAN
+	    waddr ^= 2;
+#endif
+	    *((unsigned short *) &(mem[waddr])) = *data & 0x0ffff;
+	    *ws = 0;
+	    break;
+	case 2:
+	    *((uint32 *) &(mem[waddr])) = *data;
+	    *ws = 0;
+	    break;
+	case 3:
+	    *((uint32 *) &(mem[waddr])) = data[0];
+	    *((uint32 *) &(mem[waddr + 4])) = data[1];
+	    *ws = 0;
+	    break;
+    }
+}
+
+
+/* Memory emulation */
+
+static int
+memory_iread(addr, data, ws)
+    uint32          addr;
+    uint32         *data;
+    int32          *ws;
+{
+    if ((addr >= RAM_START) && (addr < RAM_END)) {
+        *data = *((uint32 *) & (ramb[addr & RAM_MASK]));
+	*ws = 0;
+	return (0);
+    } else if (addr < ROM_END) {
+        *data = *((uint32 *) & (romb[addr]));
+	*ws = 0;
+	return (0);
+    }
+
+    printf("Memory exception at %x (illegal address)\n", addr);
+    *ws = MEM_EX_WS;
+    return (1);
+}
+
+static int
+memory_read(addr, data, sz, ws)
+    uint32          addr;
+    uint32         *data;
+    int32           sz;
+    int32          *ws;
+{
+    int32           mexc;
+
+    if ((addr >= RAM_START) && (addr < RAM_END)) {
+        *data = *((uint32 *) & (ramb[addr & RAM_MASK & ~3]));
+	*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) {
+        *data = *((uint32 *) & (romb[addr & ~3]));
+	*ws = 0;
+	return (0);
+    }
+
+    printf("Memory exception at %x (illegal address)\n", addr);
+    *ws = MEM_EX_WS;
+    return (1);
+}
+
+static int
+memory_read_asi(asi, addr, data, sz, ws)
+    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(addr, data, sz, ws)
+    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) {
+//        return (1);
+	*ws = 0;
+	store_bytes (romb, addr, data, sz, ws);
+        return (0);
+    }
+	
+    *ws = MEM_EX_WS;
+    return (1);
+}
+
+static int
+memory_write_asi(asi, addr, data, sz, ws)
+    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(addr, size)
+    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(addr, data, length)
+    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(addr, data, length)
+    uint32          addr;
+    char           *data;
+    uint32          length;
+{
+    char           *mem;
+    int            ws;
+
+    if (length == 4) {
+      memory_read(addr, 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 ()
+{
+//    mec_write(MEC_WCR, 0);	/* zero waitstates */
+//    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
+    apb_write(GPTIMER_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
+    apb_write(GPTIMER_SCLOAD, sregs.freq-1);
+    apb_write(GPTIMER_TIMER1, -1);
+    apb_write(GPTIMER_RELOAD1, -1);
+    apb_write(GPTIMER_CTRL1, 0x7);
+//    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
+    sregs.wim = 2;
+    sregs.psr = 0xF30010e0;
+    sregs.r[30] = RAM_END;
+    sregs.r[14] = sregs.r[30] - 96*4;
+    cache_ctrl = 0x81000f;
+}
+
+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 efd8a63..68ec319 100644
--- a/sim/erc32/sis.c
+++ b/sim/erc32/sis.c
@@ -141,7 +141,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) {
@@ -180,6 +180,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 if (strcmp(argv[stat], "-v") == 0) {
 		sis_verbose = 1;
             } else if (strcmp(argv[stat], "-vv") == 0) {
@@ -194,13 +198,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 a7bb39a..98e0e38 100644
--- a/sim/erc32/sis.h
+++ b/sim/erc32/sis.h
@@ -153,6 +153,30 @@ struct irqcell {
     int32           arg;
 };
 
+struct memsys {
+    void	(*init_sim) ();
+    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) (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	        (*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);
+};
+
 
 #define OK 0
 #define TIME_OUT 1
@@ -160,6 +184,8 @@ struct irqcell {
 #define ERROR 3
 #define CTRL_C 4
 
+#define CPU_LEON3  3
+
 /* Prototypes  */
 
 /* erc32.c */
@@ -215,6 +241,7 @@ extern int	nouartrx;
 extern          host_callback *sim_callback;
 extern int	current_target_byte_order;
 extern int      dumbio;
+extern int      cputype;
 
 /* exec.c */
 extern int	dispatch_instruction (struct pstate *sregs);
@@ -235,23 +262,7 @@ extern void	set_fsr (uint32 fsr);
 extern void	usage (void);
 extern void	gen_help (void);
 
-struct memsys {
-    void	(*init_sim) ();
-    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 struct memsys *ms;
+
+/* leon3.c */
+extern struct memsys leon3;
-- 
2.1.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]