New sparc simulator from the ESA.
authorRob Savoye <rob@cygnus>
Mon, 20 May 1996 02:46:07 +0000 (02:46 +0000)
committerRob Savoye <rob@cygnus>
Mon, 20 May 1996 02:46:07 +0000 (02:46 +0000)
20 files changed:
sim/erc32/ChangeLog [new file with mode: 0644]
sim/erc32/Makefile.in [new file with mode: 0644]
sim/erc32/NEWS [new file with mode: 0644]
sim/erc32/README.erc32 [new file with mode: 0644]
sim/erc32/README.gdb [new file with mode: 0644]
sim/erc32/README.sis [new file with mode: 0644]
sim/erc32/configure.in [new file with mode: 0644]
sim/erc32/end.c [new file with mode: 0644]
sim/erc32/examples/__main.c [new file with mode: 0644]
sim/erc32/examples/clock.c [new file with mode: 0644]
sim/erc32/examples/gccx [new file with mode: 0755]
sim/erc32/examples/hello.c [new file with mode: 0644]
sim/erc32/examples/srt0.S [new file with mode: 0755]
sim/erc32/exec.c [new file with mode: 0644]
sim/erc32/float.c [new file with mode: 0644]
sim/erc32/func.c [new file with mode: 0644]
sim/erc32/help.c [new file with mode: 0644]
sim/erc32/interf.c [new file with mode: 0644]
sim/erc32/run.c [new file with mode: 0644]
sim/erc32/startsim [new file with mode: 0644]

diff --git a/sim/erc32/ChangeLog b/sim/erc32/ChangeLog
new file mode 100644 (file)
index 0000000..ed56438
--- /dev/null
@@ -0,0 +1,109 @@
+version 2.1 26-02-96
+--------------------
+* Fixed bug in "go" command.
+version 2.0 05-02-96
+--------------------
+
+* Fixed bug in interrupt force register (erc32.c).
+
+* Change file load function to use bfd_openr.
+
+* SIS should now be endian independent.
+
+version 1.8 24-11-95
+--------------------
+
+* Fixed FPU timing - some sequences of FPU instructions did not calculate
+  the resource dependencies right.
+
+* Corrected STDFQ when qne = 0 (again!). The ftt is set to sequence_error
+  but no FPU trap is generated.
+
+version 1.7.1 31-10-95
+--------------------
+
+* Corrected STDFQ when qne = 0. Now, a trap is immidiately generated but
+  the FPU stays in execute mode.
+
+* Corrected JMPL and RETT timing (these instructions takes two cycles).
+
+
+version 1.7 25-10-95
+--------------------
+
+* Interrupt during annuled instruction corrupted return address - fixed.
+
+
+version 1.6.2 25-10-95
+--------------------
+
+* Added -DFAST_UART to Makefile
+
+version 1.6.1 24-10-95
+--------------------
+* Fixed bug in STDFQ which caused bus error
+
+
+version 1.6 02-10-95
+--------------------
+* Modified srt0.s to include code that initiates registers in IU and FPU
+  and initializes the data segment. The simulator 'load' command does not
+  longer initialize the data segment!
+
+* Corrected MEC timer operation; scalers now divide the frequency by 
+  (scaler_value + 1).
+
+* MEC breakpoints are not checked during store operation
+
+
+version 1.5 14-09-95
+--------------------
+
+* Fixed some bugs in the cycle counting for IU & FPU instructions.
+
+* Fixed bug that allowed an annuled instruction to cause memory exception.
+
+* The *ws parameter in mem.c should now contain the number of waitstates
+  required by the memory access (was total number of cycles).
+
+* The supplied srt0.s now clears the BSS (thanks Joel).
+
+version 1.4 22-08-95
+--------------------
+
+* Added a '-g' switch to enable/disable the GNU readline(), which cause
+some problems on solaris 2.x machines.
+
+* Enabled MEC watchpoint and breakpoint function to mem.c. Performance 
+may suffer a bit ...
+
+NOTE: The UARTs are now connected to /dev/ttypc and /dev/ttypd.
+
+version 1.3 26-07-95
+--------------------
+
+* Fixed bug in mulscc instruction (how could that ever have worked?)
+
+* Fixed bug in UART B (flushed characters on UART A), thanks Paul.
+
+version 1.2 13-07-95
+--------------------
+
+* Fixed bug in interrupt handling (wrong interrupt selected when more that
+one interrupt pending)
+
+* Fixed updating of condition codes during logical instructions (carry and
+overflow were not reset)
+
+* Fixed bug in WRTBR (tt field was wrongly over-written)
+
+version 1.1 07-07-95
+--------------------
+
+* Fixed several bugs in the interrupt handler and callback routines.
+(reported by Paul Warren, Alsys)
diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in
new file mode 100644 (file)
index 0000000..5ee6db3
--- /dev/null
@@ -0,0 +1,204 @@
+#    Makefile template for Configure for the erc32sim library.
+#    Copyright (C) 1993 Free Software Foundation, Inc.
+#    Written by Cygnus Support
+#    Modified by J.Gaisler ESA/ESTEC
+# 
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+srcroot = $(srcdir)/../../
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(exec_prefix)/$(target_alias)
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+oldincludedir =
+docdir = $(srcdir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = $${srcroot}/install.sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
+INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
+
+AR = @AR@
+AR_FLAGS = rc
+CC = @CC@
+CFLAGS = @CFLAGS@
+MAKEINFO = makeinfo
+RANLIB = @RANLIB@
+
+#
+# UARTS run at about 115200 baud (simulator time). Add -DFAST_UART to
+# CFLAGS if faster (infinite) UART speed is desired. Might affect the
+# behaviour of UART interrupt routines ...
+#
+
+AR = ar
+AR_FLAGS = rc
+CFLAGS2 = -g -O3 -DSTAT -DFAST_UART -DIUREV0 -DMECREV0
+BISON = bison
+MAKEINFO = makeinfo
+RANLIB = ranlib
+CC = gcc
+
+INCDIR = $(srcdir)/../../include
+CSEARCH = -I. -I$(srcdir) -I$(INCDIR) -I../../bfd -I$(srcdir)/../../bfd \
+               -I$(srcdir)/../../gdb -I$(srcdir)/../../gdb/config
+DEP = mkdep
+
+
+TARGETLIB = libsim.a
+
+CFILES = sis.c exec.c erc32.c interf.c run.c help.c float.c
+OFILES =  exec.o erc32.o func.o help.o float.o
+
+
+all: end.h sis run $(TARGETLIB)
+
+end : $(srcdir)/end.c
+       $(CC) $(srcdir)/end.c -o end
+
+end.h : end
+       end > end.h
+
+sis: sis.o $(OFILES)
+       $(CC) $(CFLAGS) $(CLAGS2) -o sis sis.o $(OFILES) \
+       ../../opcodes/libopcodes.a ../../readline/libreadline.a \
+       ../../bfd/libbfd.a ../../libiberty/libiberty.a \
+       -ltermcap -lm
+
+run: run.o interf.o $(OFILES)
+       $(CC) $(CFLAGS) $(CLAGS2) -o run run.o interf.o $(OFILES) \
+       ../../opcodes/libopcodes.a ../../readline/libreadline.a \
+       ../../bfd/libbfd.a ../../libiberty/libiberty.a \
+       -ltermcap -lm
+
+clean:
+       rm -f *.o libsim.a sis run end end.h
+
+distclean: clean
+       rm -rf Makefile config.status sysdep.h
+
+#### host and target dependent Makefile fragments come in here.
+###
+
+FLAGS_TO_PASS = \
+       "against=$(against)" \
+       "AR=$(AR)" \
+       "AR_FLAGS=$(AR_FLAGS)" \
+       "CC=$(CC)" \
+       "CFLAGS=$(CFLAGS)" \
+       "RANLIB=$(RANLIB)" \
+       "MAKEINFO=$(MAKEINFO)" \
+       "INSTALL=$(INSTALL)" \
+       "INSTALL_DATA=$(INSTALL_DATA)" \
+       "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+       "BISON=$(BISON)"
+
+$(OFILES) sis.o interf.o : end.h sis.h
+
+.c.o:
+       $(CC) -c $(CFLAGS) $(CFLAGS2) $(HDEFINES) $(TDEFINES) $(CSEARCH) $(CSWITCHES) $<
+
+
+# C source files that correspond to .o's.
+
+STAGESTUFF = $(TARGETLIB) $(OFILES)
+
+all: $(TARGETLIB) 
+
+
+.NOEXPORT:
+
+check:
+
+info:
+clean-info:
+install-info:
+
+# HDEPFILES comes from the host config; TDEPFILES from the target config.
+
+
+$(TARGETLIB): $(OFILES) interf.o
+        rm -f $(TARGETLIB)
+        $(AR) $(AR_FLAGS) $(TARGETLIB) $(OFILES) interf.o
+        $(RANLIB) $(TARGETLIB)
+
+# Circumvent Sun Make bug with VPATH.
+sparc-opc.o: sparc-opc.c
+
+tags etags: TAGS
+
+TAGS: force
+       etags $(INCDIR)/*.h $(srcdir)/*.h $(srcdir)/*.c
+
+
+sis.o: sis.c sis.h end.h
+exec.o: exec.c sis.h end.h
+erc32.o: erc32.c sis.h end.h
+interf.o: interf.c sis.h end.h 
+run.o: run.c
+help.o: help.c
+float.o: float.c sis.h end.h
+
+# Mark everything as depending on config.status, since the timestamp on
+# sysdep.h might actually move backwards if we reconfig and relink it
+# to a different hosts/h-xxx.h file.  This will force a recompile anyway.
+RECONFIG = config.status
+
+# Dummy target to force execution of dependent targets.
+#
+force:
+
+# Copy the files into directories where they will be run.
+install:
+       srcroot=`cd $(srcroot); pwd`; export srcroot; \
+       $(INSTALL_XFORM) sis $(bindir)/sis ;  \
+       n=`echo sis | sed '$(program_transform_name)'`; \
+       if [ -d $(tooldir) ] ; then \
+         if [ -d $(tooldir)/bin ] ; then true ; else mkdir $(tooldir)/bin ; fi; \
+         rm -f $(tooldir)/bin/sis;  \
+         ln $(bindir)/$$n $(bindir)/sis \
+           || $(INSTALL_PROGRAM) sis $(bindir)/sis; \
+         ln $(bindir)/$$n $(tooldir)/bin/sis \
+           || $(INSTALL_PROGRAM) sis $(tooldir)/bin/sis; \
+       true; fi
+
+
+Makefile: $(srcdir)/Makefile.in
+       $(SHELL) ./config.status
diff --git a/sim/erc32/NEWS b/sim/erc32/NEWS
new file mode 100644 (file)
index 0000000..dd24b7b
--- /dev/null
@@ -0,0 +1,108 @@
+
+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
new file mode 100644 (file)
index 0000000..f413599
--- /dev/null
@@ -0,0 +1,130 @@
+
+1. MEC and ERC32 emulation
+
+The file 'erc32.c' contains a model of the MEC, 512 K rom and 4 M ram.
+
+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:
+
+- 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 
+character.  The error interrupt is generated if overflow occurs - other
+errors cannot occure.
+
+1.2 Real-time clock and general pupose timer A
+
+The following registers are implemeted:
+
+- 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)
+- Real-time clock scaler program register      (0x01f8008c, write-only)
+- General purpose timer counter prog. register         (0x01f80088, write-only)
+
+- Timer control register                       (0x01f80098, write-only)
+
+1.3 Interrupt controller
+
+The interrupt controller is implemented as in the MEC specification with
+the exception of the interrupt shape register. Since external interrupts
+are not possible, the interrupt shape register is not implemented. The
+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:
+
+- Interrupt pending register                  (0x01f80048, read-only)
+- Interrupt mask register                     (0x01f8004c, read-write)
+- Interrupt clear register                    (0x01f80050, write-only)
+- Interrupt force register                    (0x01f80054, read-write)
+
+1.4 Breakpoint and watchpoint register
+
+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:
+
+- 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)
+
+
+1.5 Memory interface
+
+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)
+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. 
+
+The memory configuartion 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. 
+
+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:
+
+- MEC control register (bit 3 only)            (0x01f80000, read-write)
+- Memory control register                      (0x01f80010, read-write)
+- Waitstate configuration register             (0x01f80018, read-write)
+- Memory access register 0                     (0x01f80020, read-write)
+- Memory access register 1                     (0x01f80024, read-write)
+
+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 
+register.
+
+The following registers are implemeted:
+- Watchdog program and acknowledge register    (0x01f80060, write-only)
+- Watchdog trap door set register              (0x01f80064, write-only)
+
+1.7 Software reset register
+
+Implemented as in the specification (0x01f800004, write-only).
+
+1.8 Power-down mode
+
+The power-down register (0x01f800008) is implemented as in the specification.
+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.
+
+1.9 MEC control register
+
+The following bits are implemented in the MEC control register:
+
+Bit    Name    Function
+0      PRD     Power-down mode enable
+1      SWR     Soft reset enable
+3      APR     Access protection enable
+
diff --git a/sim/erc32/README.gdb b/sim/erc32/README.gdb
new file mode 100644 (file)
index 0000000..619fcb3
--- /dev/null
@@ -0,0 +1,67 @@
+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.sis b/sim/erc32/README.sis
new file mode 100644 (file)
index 0000000..b119f03
--- /dev/null
@@ -0,0 +1,356 @@
+
+SIS - Sparc Instruction Simulator README file  (v2.0, 05-02-1996)
+-------------------------------------------------------------------
+
+1. Introduction
+
+The SIS is a SPARC V7 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. 
+
+2. Usage
+
+The simulator is started as follows: 
+
+sis [-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.
+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 -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.
+
+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 
+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.
+
+batch <file>
+
+Execute a batch file of SIS commands.
+
++bp <address>
+
+Adds an breakpoint at address <address>.
+
+bp
+
+Prints all breakpoints
+
+-bp <num>
+
+Deletes breakpoint <num>. Use 'bp' to see which number is assigned to the 
+breakpoints.
+
+cont [inst_count]
+
+Continue execution at present position, optionally for [inst_count] 
+instructions.
+
+dis [addr] [count]
+
+Disassemble [count] instructions at address [addr]. Default values for
+count is 16 and addr is the present address.
+
+echo <string>
+
+Print <string> to the simulator window.
+
+float
+
+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.
+
+help
+
+Print a small help menu for the SIS commands.
+
+hist [trace_length]
+
+Enable the instruction trace buffer. The 'trace_length' last executed 
+instructions will be placed in the trace buffer. A 'hist' command without 
+a trace_length will display the trace buffer. Specifying a zero trace 
+length will disable the trace buffer.
+
+load  <file_name>
+
+Loads a file into simulator memory. 
+
+mem [addr] [count]
+
+Display memory at [addr] for [count] bytes. Same default values as above.
+
+quit
+
+Exits the simulator.
+
+perf [reset]
+
+The 'perf' command will display various execution statistics. A 'perf reset' 
+command will reset the statistics. This can be used if statistics shall 
+be calculated only over a part of the program. The 'run' and 'reset' 
+command also resets the statistic information.
+
+reg [reg_name] [value]
+
+Prints and sets the IU regiters. '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.
+
+reset
+
+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 
+number of instructions. The event queue is emptied but any set breakpoints
+remain.
+
+step
+
+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 
+will stop after the specified number of instructions.
+
+Typing a 'Ctrl-C' will interrupt a running simulator. 
+
+Short forms of the commands are allowed, e.g 'c' 'co' or 'con' are all
+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.
+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:
+
+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;
+
+int sis_memory_write(addr, data, length)
+unsigned int addr;
+char    *data;
+unsigned int length;
+
+int init_sim()
+
+int reset()
+
+int error_mode(pc)
+unsigned int pc;
+
+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.
+
+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.
+
+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:
+
+  sz   access type
+  0      byte
+  1      halfword
+  2      word
+  3      double-word
+
+If a double word is written, the most significant word is in data[0] and
+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 
+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 
+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
+'run' command is given. This function should be used to simulate a power
+on reset of memory and peripherals.
+
+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.
+
+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.
+
+4. Events and interrupts
+
+The simulator supports an event queue and the generation of processor
+interrupts. The following functions are available to the user-defined
+memory module:
+
+event(cfunc,arg,delta)
+void (*cfunc)();
+int arg;
+unsigned int delta;
+
+set_int(level,callback,arg)
+int level;
+void (*callback)();
+int arg;
+
+clear_int(level)
+int level;
+
+sim_stop()
+
+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'.
+
+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.
+
+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 MEC asic developed for the 90C601/2. It includes the following functions:
+
+* UART A & B
+* Real-time clock
+* General purpose timer
+* Interrupt controller
+* Breakpoint register
+* Watchpoint register
+* 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:
+
+http://www.estec.esa.nl/wsmwww/erc32
+
+6. Compile and linking programs
+
+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. 
+
+The programs are linked with a start-up file, srt0.S. This file includes
+the traptable and window underflow/overflow trap routines.
+
+7. IU and FPU instruction timing.
+
+The simulator provides cycle true simulation. 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
+
+The simulator maps floating-point operations on the hosts floating point
+capabilities. This means that accuracy and generation of IEEE exceptions is 
+host dependent.
diff --git a/sim/erc32/configure.in b/sim/erc32/configure.in
new file mode 100644 (file)
index 0000000..0eb7b73
--- /dev/null
@@ -0,0 +1,18 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.3)dnl
+AC_INIT(Makefile.in)
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+. ${srcdir}/../../bfd/configure.host
+
+AC_PROG_CC
+AC_SUBST(CFLAGS)
+AC_SUBST(HDEFINES)
+AR=${AR-ar}
+AC_SUBST(AR)
+AC_PROG_RANLIB
+
+AC_OUTPUT(Makefile)
diff --git a/sim/erc32/end.c b/sim/erc32/end.c
new file mode 100644 (file)
index 0000000..5cd454a
--- /dev/null
@@ -0,0 +1,23 @@
+main()
+{
+
+    unsigned int    u1;
+    char           *c;
+    double          d1;
+    float          *f1;
+
+    c = (char *) &u1;
+    u1 = 0x0F;
+    if (c[0] == 0x0F)
+       puts("#define HOST_LITTLE_ENDIAN\n");
+    else
+       puts("#define HOST_BIG_ENDIAN\n");
+
+    d1 = 1.0;
+    f1 = (float *) &d1;
+    if (*((int *) f1) != 0x3ff00000)
+       puts("#define HOST_LITTLE_ENDIAN_FLOAT\n");
+    else
+       puts("#define HOST_BIG_ENDIAN_FLOAT\n");
+    exit(0);
+}
diff --git a/sim/erc32/examples/__main.c b/sim/erc32/examples/__main.c
new file mode 100644 (file)
index 0000000..73c52cd
--- /dev/null
@@ -0,0 +1,4 @@
+/* Dummy __main for gccx compiled programs */
+
+__main()
+{}
diff --git a/sim/erc32/examples/clock.c b/sim/erc32/examples/clock.c
new file mode 100644 (file)
index 0000000..ec23037
--- /dev/null
@@ -0,0 +1,8 @@
+
+int clock()
+{
+       volatile int *t_addr;
+
+       t_addr = (volatile int * ) 0x01F80080;  /* Real-time clock address */
+       return(*t_addr);
+}
diff --git a/sim/erc32/examples/gccx b/sim/erc32/examples/gccx
new file mode 100755 (executable)
index 0000000..5fec6ec
--- /dev/null
@@ -0,0 +1,7 @@
+#
+sparclite-aout-gcc -g \
+-Xlinker -Bstatic -Xlinker -N -Xlinker -Ttext -Xlinker 0 \
+-Xlinker -Tdata -Xlinker 02000000 -Xlinker -e -Xlinker _trap_table -Xlinker -X \
+-o $1:r -nostartfiles -nostdlib \
+srt0.S __main.c $* 
+size $1:r
diff --git a/sim/erc32/examples/hello.c b/sim/erc32/examples/hello.c
new file mode 100644 (file)
index 0000000..02903cf
--- /dev/null
@@ -0,0 +1,87 @@
+/* A small test program to demonstrate use of UARTs and clock */
+
+
+#define RXADATA (int *) 0x01F800E0
+#define RXBDATA (int *) 0x01F800E4
+#define RXSTAT (int *) 0x01F800E8
+
+int write (fd, buf, nbyte)
+int fd;
+char *buf;
+int nbyte;
+{
+
+        int *rxadata;
+        int rxmask;
+       int nsave;
+       volatile *rxstat;
+
+       nsave = nbyte;
+
+       switch (fd) {
+               case 0 : 
+                       rxadata = RXADATA;
+                       rxmask = 6;
+                       break;
+               case 1 : 
+                       rxadata = RXBDATA;
+                       rxmask = 0x60000;
+                       break;
+               default:
+                       return (-1);
+       }
+       rxstat = RXSTAT;
+        while (nbyte > 0) {
+               while ((*rxstat & rxmask) == 0);
+               *rxadata = *buf;
+               buf++;
+               nbyte--;
+       }
+       return (nsave);
+}
+
+int read (fd, buf, nbyte)
+int fd;
+char *buf;
+int nbyte;
+{
+
+        int rxmask,*rxadata;
+       int nsave;
+       volatile *rxstat;
+
+       nsave = nbyte;
+       switch (fd) {
+               case 0 : 
+                       rxadata = RXADATA;
+                       rxmask = 1;
+                       break;
+               case 1 : 
+                       rxadata = RXBDATA;
+                       rxmask = 0x10000;
+                       break;
+               default:
+                       return (-1);
+       }
+       rxstat = RXSTAT;
+        while (nbyte > 0) {
+               while ((*rxstat & rxmask) == 0);
+               *buf =  *rxadata;
+               buf++;
+                nbyte--;
+       }
+       return (nsave);
+}
+
+char *
+puts(s)
+char *s;
+{
+    while (*s) write(0,s++,1);
+}
+
+main()
+{
+    puts("Hello world!\n");
+}
+
diff --git a/sim/erc32/examples/srt0.S b/sim/erc32/examples/srt0.S
new file mode 100755 (executable)
index 0000000..1e68951
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * srt0.s for ERC32. This file is part of ERC32SIM.
+ *
+ * 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 2 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, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+/* The traptable has to be the first code in a boot PROM. */
+
+/* Entry for traps which jump to a programmer-specified trap handler.  */
+#define TRAP(H)  mov %psr, %l0; sethi %hi(H), %l4; jmp %l4+%lo(H); nop;
+
+/* Unexcpected trap will halt the processor by forcing it to error state */
+#define BAD_TRAP ta 0; nop; nop; nop;
+
+/* Software trap. Treat as BAD_TRAP for the time being... */
+#define SOFT_TRAP BAD_TRAP
+
+#define PSR_INIT   0x10c0      /* Disable traps, set s and ps */
+#define WIM_INIT   2
+#define SP_INIT           0x02100000
+
+WINDOWSIZE = (16 * 4)
+ARGPUSHSIZE = (6 * 4)
+ARGPUSH = (WINDOWSIZE + 4)
+MINFRAME = (WINDOWSIZE + ARGPUSHSIZE + 4)
+#define STACK_ALIGN    8
+#define SA(X)  (((X)+(STACK_ALIGN-1)) & ~(STACK_ALIGN-1))
+
+  .seg    "text"
+  .global _trap_table, _mecini, start
+
+  /* Hardware traps */
+_trap_table:
+  TRAP(_mecini);                       ! 00 reset trap 
+  BAD_TRAP;                    ! 01 instruction_access_exception
+  BAD_TRAP;                    ! 02 illegal_instruction
+  BAD_TRAP;                    ! 03 priveleged_instruction
+  BAD_TRAP;                    ! 04 fp_disabled
+  TRAP(_window_overflow);      ! 05 window_overflow
+  TRAP(_window_underflow);     ! 06 window_underflow
+  BAD_TRAP;                    ! 07 memory_address_not_aligned
+  BAD_TRAP;                    ! 08 fp_exception
+  BAD_TRAP;                    ! 09 data_access_exception
+  BAD_TRAP;                    ! 0A tag_overflow
+
+  /* Trap levels from 0B to 0x10 are not defined (used for MEC init) */
+
+_mecini:
+  sethi                %hi(0x01f80000), %g1    ! 0B
+  sethi                %hi(0x001C1000), %g2
+  or           %g1,%lo(0x001C1000),%g1
+  st           %g2, [%g1 + 0x10]
+
+  st           %g0, [%g1 + 0x18]       ! 0C
+  nop
+  nop
+  nop
+
+  TRAP(_hardreset);                    ! 0D
+
+  BAD_TRAP;                    ! 0E undefined
+  BAD_TRAP;                    ! 0F undefined
+  BAD_TRAP;                    ! 10 undefined
+
+  /* Interrupt entries */
+  BAD_TRAP;                    ! 11 interrupt level 1
+  BAD_TRAP;                    ! 12 interrupt level 2
+  BAD_TRAP;                    ! 13 interrupt level 3
+  BAD_TRAP;                    ! 14 interrupt level 4
+  BAD_TRAP;                    ! 15 interrupt level 5
+  BAD_TRAP;                    ! 16 interrupt level 6
+  BAD_TRAP;                    ! 17 interrupt level 7
+  BAD_TRAP;                    ! 18 interrupt level 8
+  BAD_TRAP;                    ! 19 interrupt level 9
+  BAD_TRAP;                    ! 1A interrupt level 1
+  BAD_TRAP;                    ! 1B interrupt level 11
+  BAD_TRAP;                    ! 1C interrupt level 12
+  BAD_TRAP;                    ! 1D interrupt level 13
+  BAD_TRAP;                    ! 1E interrupt level 14
+  BAD_TRAP;                    ! 1F interrupt level 15
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 20 - 23 undefined
+  BAD_TRAP;                                    ! 24 cp_disabled
+           BAD_TRAP; BAD_TRAP; BAD_TRAP;       ! 25 - 27 undefined
+  BAD_TRAP;                                    ! 28 cp_exception
+           BAD_TRAP; BAD_TRAP; BAD_TRAP;       ! 29 - 2B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 2C - 2F undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 30 - 33 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 34 - 37 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 38 - 3B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 3C - 3F undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 40 - 43 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 44 - 47 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 48 - 4B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 4C - 4F undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 50 - 53 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 54 - 57 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 58 - 5B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 5C - 5F undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 60 - 63 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 64 - 67 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 68 - 6B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 6C - 6F undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 70 - 73 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 74 - 77 undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 78 - 7B undefined
+  BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP;      ! 7C - 7F undefined
+
+  /* Software traps */
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;             ! 80 - 82
+  TRAP(_flush_windows)                         ! 83
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 84 - 87
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 88 - 8B
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 8C - 8F
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 90 - 93
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 94 - 97
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 98 - 9B
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! 9C - 9F
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! A0 - A3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! A4 - A7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! A8 - AB
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! AC - AF
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! B0 - B3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! B4 - B7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! B8 - BB
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! BC - BF
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! C0 - C3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! C4 - C7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! C8 - CB
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! CC - CF
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! D0 - D3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! D4 - D7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! D8 - DB
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! DC - DF
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! E0 - E3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! E4 - E7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! E8 - EB
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! EC - EF
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! F0 - F3
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! F4 - F7
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! F8 - FB 
+  SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP;  ! FC - FF
+
+
+!
+! Startup code for standalone system. Wash IU and FPU (if present) registers.
+! The registers have to be written to initiate the parity bits.
+!
+
+_hardreset:
+
+        sethi %hi(0x01FE0),%o0
+        or %o0,%lo(0x01FE0),%o0
+       wr      %o0, %psr               ! Set valid PSR
+       nop
+
+       wr      %g0, %wim               ! Set window invalid mask register
+       wr      %g0, %y                 ! Init Y-register
+       nop
+       set     _hardreset, %g1
+
+       wr      %g1, %tbr               ! Set TBR
+       sethi %hi(SP_INIT),%sp
+       or      %g0, 1, %o0
+       ld      [%g0], %f0              ! Check if FPU is present
+
+       tst     %o0
+       bz      fixiu
+       nop
+       ba      fixfpu
+
+! FPU disabled trap address
+
+       clr     %i0
+       jmpl    %l2, %g0
+       rett    %l2 + 4
+       nop
+       
+
+! Wash register files (fix for 90C601E & 90C602E)
+
+fixfpu:
+
+       ld      [%g0], %f0
+       ld      [%g0], %f1
+       ld      [%g0], %f2
+       ld      [%g0], %f3
+       ld      [%g0], %f4
+       ld      [%g0], %f5
+       ld      [%g0], %f6
+       ld      [%g0], %f7
+       ld      [%g0], %f8
+       ld      [%g0], %f9
+       ld      [%g0], %f10
+       ld      [%g0], %f11
+       ld      [%g0], %f12
+       ld      [%g0], %f13
+       ld      [%g0], %f14
+       ld      [%g0], %f15
+       ld      [%g0], %f16
+       ld      [%g0], %f17
+       ld      [%g0], %f18
+       ld      [%g0], %f19
+       ld      [%g0], %f20
+       ld      [%g0], %f21
+       ld      [%g0], %f22
+       ld      [%g0], %f23
+       ld      [%g0], %f24
+       ld      [%g0], %f25
+       ld      [%g0], %f26
+       ld      [%g0], %f27
+       ld      [%g0], %f28
+       ld      [%g0], %f29
+       ld      [%g0], %f30
+       ld      [%g0], %f31
+
+fixiu:
+       clr     %g1
+       clr     %g2
+       clr     %g3
+       clr     %g4
+       clr     %g5
+       clr     %g6
+       clr     %g7
+       set     8,%g1
+wl0:
+       clr     %i0
+       clr     %i1
+       clr     %i2
+       clr     %i3
+       clr     %i4
+       clr     %i5
+       clr     %i6
+       clr     %i7
+       clr     %l0
+       clr     %l1
+       clr     %l2
+       clr     %l3
+       clr     %l4
+       clr     %l5
+       clr     %l6
+       clr     %l7
+       save
+       subcc   %g1, 1, %g1
+       bne     wl0
+       nop
+
+!
+! Start the real-time clock with a tick of 150 clocks
+!
+
+rtc:
+
+       set     0x1f80000, %l0          ! MEC register base
+       set     149, %l1
+       st      %l1, [%l0 + 0x84]       ! RTC scaler = 149
+       set     0x0d00, %l1
+       st      %l1, [%l0 + 0x98]       ! Start RTC
+
+       st      %g0, [%l0 + 0x64]       ! Disable watchdog for now
+       ld      [%l0], %g1
+       or      %g1, 1, %g1
+       st      %g1, [%l0]              ! Enable power-down mode
+
+! Initialise some registers
+
+_init:
+        set     PSR_INIT, %g1          ! Initialize psr
+        wr      %g1, %psr
+        set     WIM_INIT, %g1          ! Initialize WIM
+        wr      %g1, %wim               
+        set     _trap_table, %g1               ! Initialize TBR
+        wr      %g1, %tbr
+        nop;nop;nop                     
+
+        set     PSR_INIT, %g1
+        wr      %g1, 0x20, %psr                ! enable traps
+        nop; nop; nop;
+        set     0x02100000, %sp         ! Set stack pointer
+        mov     %sp, %fp
+        nop
+
+start:
+        /* clear the bss */
+        sethi %hi(_edata),%g2
+        or    %g2,%lo(_edata),%g2  ! g2 = start of bss
+        sethi %hi(_end),%g3
+        or    %g3,%lo(_end),%g3         ! g3 = end of bss
+        mov   %g0,%g1                   ! so std has two zeros
+zerobss:
+        std    %g0,[%g2]
+        add    %g2,8,%g2
+        cmp    %g2,%g3
+        bleu,a zerobss
+        nop
+
+        /* move data segment to proper location */
+relocd:
+        set (_etext),%g2               ! g2 = start of data in aout file
+        set (_environ),%g4             ! g4 = start of where data should go
+        set (_edata),%g3               ! g3 = end of where data should go
+       subcc   %g3, %g4, %g5           ! g5 = length of data
+
+       subcc   %g4, %g2, %g0           ! need to relocate data ?
+       ble     initok
+mvdata:
+       subcc   %g5, 8, %g5
+       ldd     [%g2 + %g5], %g6
+       bg      mvdata
+        std            %g6, [%g4 + %g5]
+
+initok:
+
+        call    _main
+        sub     %sp, 0x40, %sp         ! room for main to save args
+        nop
+
+       ta      0                       ! Halt if _main would return ...
+       nop
+
+
+
+/* Number of register windows */
+#define NWINDOWS       8
+
+                       !Window overflow trap handler.
+       .global _window_overflow
+
+_window_overflow:
+
+       mov  %wim, %l3                  ! Calculate next WIM
+       mov  %g1, %l7           
+       srl  %l3, 1, %g1        
+       sll  %l3, NWINDOWS-1 , %l4
+       or   %l4, %g1, %g1
+
+       save                              ! Get into window to be saved.
+       mov  %g1, %wim
+       nop; nop; nop
+        st   %l0, [%sp + 0];
+        st   %l1, [%sp + 4];
+        st   %l2, [%sp + 8];
+        st   %l3, [%sp + 12];
+        st   %l4, [%sp + 16]; 
+        st   %l5, [%sp + 20];
+        st   %l6, [%sp + 24]; 
+        st   %l7, [%sp + 28]; 
+        st   %i0, [%sp + 32]; 
+        st   %i1, [%sp + 36]; 
+        st   %i2, [%sp + 40]; 
+        st   %i3, [%sp + 44]; 
+        st   %i4, [%sp + 48]; 
+        st   %i5, [%sp + 52]; 
+        st   %i6, [%sp + 56]; 
+        st   %i7, [%sp + 60];
+       restore                         ! Go back to trap window.
+       mov  %l7, %g1
+       jmp  %l1                        ! Re-execute save.
+       rett %l2
+
+  /* Window underflow trap handler.  */
+
+       .global  _window_underflow
+
+_window_underflow:
+
+       mov  %wim, %l3                  ! Calculate next WIM
+       sll  %l3, 1, %l4
+       srl  %l3, NWINDOWS-1, %l5
+       or   %l5, %l4, %l5
+       mov  %l5, %wim
+       nop; nop; nop
+       restore                         ! Two restores to get into the
+       restore                         ! window to restore
+        ld   [%sp + 0], %l0;           ! Restore window from the stack
+        ld   [%sp + 4], %l1; 
+        ld   [%sp + 8], %l2; 
+        ld   [%sp + 12], %l3; 
+        ld   [%sp + 16], %l4; 
+        ld   [%sp + 20], %l5; 
+        ld   [%sp + 24], %l6; 
+        ld   [%sp + 28], %l7; 
+        ld   [%sp + 32], %i0; 
+        ld   [%sp + 36], %i1; 
+        ld   [%sp + 40], %i2; 
+        ld   [%sp + 44], %i3; 
+        ld   [%sp + 48], %i4; 
+        ld   [%sp + 52], %i5; 
+        ld   [%sp + 56], %i6; 
+        ld   [%sp + 60], %i7;
+       save                            ! Get back to the trap window.
+       save
+       jmp  %l1                        ! Re-execute restore.
+       rett  %l2
+
+       .global _flush_windows  
+_flush_windows:                
+
+       mov     %psr, %g1
+       or      %g1, 0x0f00, %g2
+       restore                         ! enter previous frame (cannot trap)
+        wr      %g2, 0x20, %psr                ! enable traps, disable interrupts
+       nop; nop; nop
+       save                            ! 6 save to flush all windows
+       save
+       save
+       save
+       save
+       save
+       restore                         ! 5 restore to enter trapped frame
+       restore
+       restore
+       restore
+       restore
+       wr      %g1, %psr               ! restore %psr
+       nop; nop; nop
+       jmp  %l2                        ! Jump to nPC
+       rett  %l2 + 4
+
+
+
+
+        .seg    "data"
+        .global .bdata
+.bdata:
+        .align  8
+        .global _environ                ! first symbol in sdata
+_environ:
+        .word   0
+        .global _errno                  ! not defined elsewhere ..?
+_errno:
+        .word   0
+
+
diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c
new file mode 100644 (file)
index 0000000..8690cea
--- /dev/null
@@ -0,0 +1,1597 @@
+/*
+ * This file is part of SIS.
+ * 
+ * SIS, SPARC instruction simulator V1.8 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 2 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, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ */
+
+#include "sis.h"
+#include "end.h"
+#include <math.h>
+#include <stdio.h>
+
+extern int32    ext_irl, irqpend, iurev0, sis_verbose;
+
+/* Load/store interlock delay */
+#define FLSTHOLD 1
+
+/* Load delay (delete if unwanted - speeds up simulation) */
+#define LOAD_DEL 1
+
+#define T_LD   2
+#define T_LDD  3
+#define T_ST   3
+#define T_STD  4
+#define T_LDST 4
+#define T_JMPL 2
+#define T_RETT 2
+
+#define FSR_QNE        0x2000
+#define FP_EXE_MODE 0
+#define        FP_EXC_PE   1
+#define FP_EXC_MODE 2
+
+#define        FBA     8
+#define        FBN     0
+#define        FBNE    1
+#define        FBLG    2
+#define        FBUL    3
+#define        FBL     4
+#define        FBUG    5
+#define        FBG     6
+#define        FBU     7
+
+#define        FCC_E   0
+#define        FCC_L   1
+#define        FCC_G   2
+#define        FCC_U   3
+
+#define PSR_ET 0x20
+#define PSR_EF 0x1000
+#define PSR_PS 0x40
+#define PSR_S  0x80
+#define PSR_N  0x0800000
+#define PSR_Z  0x0400000
+#define PSR_V  0x0200000
+#define PSR_C  0x0100000
+#define PSR_CC 0x0F00000
+#define PSR_CWP 0x7
+#define PSR_PIL 0x0f00
+
+#define ICC_N  sregs->psr
+#define ICC_Z  (sregs->psr << 1)
+#define ICC_V  (sregs->psr << 2)
+#define ICC_C  (sregs->psr << 3)
+
+#define TRAP_IEXC 1
+#define TRAP_UNIMP 2
+#define TRAP_PRIVI 3
+#define TRAP_FPDIS 4
+#define TRAP_WOFL 5
+#define TRAP_WUFL 6
+#define TRAP_UNALI 7
+#define TRAP_FPEXC 8
+#define TRAP_DEXC 9
+#define TRAP_TAG 10
+
+#define FSR_TT         0x1C000
+#define FP_IEEE                0x04000
+#define FP_UNIMP       0x0C000
+#define FP_SEQ_ERR     0x10000
+
+#define        BICC_BN         0
+#define        BICC_BE         1
+#define        BICC_BLE        2
+#define        BICC_BL         3
+#define        BICC_BLEU       4
+#define        BICC_BCS        5
+#define        BICC_NEG        6
+#define        BICC_BVS        7
+#define        BICC_BA         8
+
+#define INST_SIMM13 0x1fff
+#define INST_RS2    0x1f
+#define INST_I     0x2000
+#define ADD    0x00
+#define ADDCC  0x10
+#define ADDX   0x08
+#define ADDXCC         0x18
+#define TADDCC         0x20
+#define TADDCCTV       0x22
+#define IAND   0x01
+#define IANDCC         0x11
+#define IANDN  0x05
+#define IANDNCC        0x15
+#define MULScc         0x24
+#define IOR    0x02
+#define IORCC  0x12
+#define IORN   0x06
+#define IORNCC         0x16
+#define SLL    0x25
+#define SRA    0x27
+#define SRL    0x26
+#define SUB    0x04
+#define SUBCC  0x14
+#define SUBX   0x0C
+#define SUBXCC         0x1C
+#define IXNOR  0x07
+#define IXNORCC        0x17
+#define IXOR   0x03
+#define IXORCC         0x13
+#define SETHI  0x04
+#define BICC   0x02
+#define FPBCC  0x06
+#define RDY    0x28
+#define RDPSR  0x29
+#define RDWIM  0x2A
+#define RDTBR  0x2B
+#define WRY    0x30
+#define WRPSR  0x31
+#define WRWIM  0x32
+#define WRTBR  0x33
+#define JMPL   0x38
+#define RETT   0x39
+#define TICC   0x3A
+#define SAVE   0x3C
+#define RESTORE 0x3D
+#define LDD    0x03
+#define LDDA   0x13
+#define LD     0x00
+#define LDA    0x10
+#define LDF    0x20
+#define LDDF   0x23
+#define LDSTUB 0x0D
+#define LDSTUBA        0x1D
+#define LDUB   0x01
+#define LDUBA  0x11
+#define LDSB   0x09
+#define LDSBA  0x19
+#define LDUH   0x02
+#define LDUHA  0x12
+#define LDSH   0x0A
+#define LDSHA  0x1A
+#define LDFSR  0x21
+#define ST     0x04
+#define STA    0x14
+#define STB    0x05
+#define STBA   0x15
+#define STD    0x07
+#define STDA   0x17
+#define STF    0x24
+#define STDFQ  0x26
+#define STDF   0x27
+#define STFSR  0x25
+#define STH    0x06
+#define STHA   0x16
+#define SWAP   0x0F
+#define SWAPA  0x1F
+
+/* # of cycles overhead when a trap is taken */
+#define TRAP_C  3
+
+int32           fpexec();
+extern struct estate ebase;
+extern int32    nfp;
+
+sub_cc(operand1, operand2, result, sregs)
+    int32           operand1;
+    int32           operand2;
+    int32           result;
+    struct pstate  *sregs;
+{
+    sregs->psr = ((sregs->psr & ~PSR_N) | ((result >> 8) & PSR_N));
+    if (result)
+       sregs->psr &= ~PSR_Z;
+    else
+       sregs->psr |= PSR_Z;
+    sregs->psr = (sregs->psr & ~PSR_V) | ((
+                                        ((operand1 & ~operand2 & ~result) |
+                          (~operand1 & operand2 & result)) >> 10) & PSR_V);
+    sregs->psr = (sregs->psr & ~PSR_C) | ((
+                                          ((~operand1 & operand2) |
+                        ((~operand1 | operand2) & result)) >> 11) & PSR_C);
+}
+
+add_cc(operand1, operand2, result, psr)
+    int32           operand1;
+    int32           operand2;
+    int32           result;
+    uint32         *psr;
+{
+    *psr = ((*psr & ~PSR_N) | ((result >> 8) & PSR_N));
+    if (result)
+       *psr &= ~PSR_Z;
+    else
+       *psr |= PSR_Z;
+    *psr = (*psr & ~PSR_V) | ((
+                              ((operand1 & operand2 & ~result) |
+                         (~operand1 & ~operand2 & result)) >> 10) & PSR_V);
+    *psr = (*psr & ~PSR_C) | ((
+                              ((operand1 & operand2) |
+                        ((operand1 | operand2) & ~result)) >> 11) & PSR_C);
+}
+
+log_cc(result, sregs)
+    int32           result;
+    struct pstate  *sregs;
+{
+    sregs->psr &= ~(PSR_CC);   /* Zero CC bits */
+    sregs->psr = (sregs->psr | ((result >> 8) & PSR_N));
+    if (result == 0)
+       sregs->psr |= PSR_Z;
+}
+
+int
+dispatch_instruction(sregs)
+    struct pstate  *sregs;
+{
+
+    uint32          cwp, op, op2, op3, opf, opc, asi, a, rd, cond, rs1,
+                    rs2;
+    uint32          ldep;
+    int32           operand1, operand2, *rdd, result, i, disp22, eicc,
+                    new_cwp;
+    int32           pc, npc, data, address, ws, mexc, fcc;
+
+    sregs->ninst++;
+    sregs->icnt = 1;
+    cwp = ((sregs->psr & PSR_CWP) << 4);
+    op = sregs->inst >> 30;
+    pc = sregs->npc;
+    npc = sregs->npc + 4;
+    if (op > 1) {
+
+       op3 = (sregs->inst >> 19) & 0x3f;
+       rs1 = (sregs->inst >> 14) & 0x1f;
+       rd = (sregs->inst >> 25) & 0x1f;
+
+#ifdef LOAD_DEL
+
+       /* Check if load dependecy is possible */
+       ldep = ((ebase.simtime <= sregs->ildtime) && ((op3 & 0x38) != 0x28) &&
+               ((op3 & 0x3e) != 0x34) && (sregs->ildreg != 0));
+       if (sregs->inst & INST_I) {
+           if (ldep && (sregs->ildreg == rs1))
+               sregs->hold++;
+           operand2 = sregs->inst & INST_SIMM13;
+           if (operand2 > 0x0fff)
+               operand2 |= 0xfffff000;
+       } else {
+           rs2 = sregs->inst & INST_RS2;
+           if (rs2 > 7)
+               operand2 = sregs->r[(cwp + rs2) & 0x7f];
+           else
+               operand2 = sregs->g[rs2];
+           if (ldep && ((sregs->ildreg == rs1) || (sregs->ildreg == rs2)))
+               sregs->hold++;
+       }
+#else
+       if (sregs->inst & INST_I) {
+           operand2 = sregs->inst & INST_SIMM13;
+           if (operand2 > 0x0fff)
+               operand2 |= 0xfffff000;
+       } else {
+           rs2 = sregs->inst & INST_RS2;
+           if (rs2 > 7)
+               operand2 = sregs->r[(cwp + rs2) & 0x7f];
+           else
+               operand2 = sregs->g[rs2];
+       }
+#endif
+
+       if (rd > 7)
+           rdd = &(sregs->r[(cwp + rd) & 0x7f]);
+       else
+           rdd = &(sregs->g[rd]);
+       if (rs1 > 7)
+           rs1 = sregs->r[(cwp + rs1) & 0x7f];
+       else
+           rs1 = sregs->g[rs1];
+    }
+    switch (op) {
+    case 0:
+       op2 = (sregs->inst >> 22) & 0x7;
+       switch (op2) {
+       case SETHI:
+           rd = (sregs->inst >> 25) & 0x1f;
+           if (rd > 7)
+               rdd = &(sregs->r[(cwp + rd) & 0x7f]);
+           else
+               rdd = &(sregs->g[rd]);
+           *rdd = sregs->inst << 10;
+           break;
+       case BICC:
+#ifdef STAT
+           sregs->nbranch++;
+#endif
+           cond = ((sregs->inst >> 25) & 0x0f);
+           switch (cond & 0x7) {
+           case BICC_BN:
+               eicc = 0;
+               break;
+           case BICC_BE:
+               eicc = ICC_Z;
+               break;
+           case BICC_BLE:
+               eicc = ICC_Z | (ICC_N ^ ICC_V);
+               break;
+           case BICC_BL:
+               eicc = (ICC_N ^ ICC_V);
+               break;
+           case BICC_BLEU:
+               eicc = ICC_C | ICC_Z;
+               break;
+           case BICC_BCS:
+               eicc = ICC_C;
+               break;
+           case BICC_NEG:
+               eicc = ICC_N;
+               break;
+           case BICC_BVS:
+               eicc = ICC_V;
+               break;
+           }
+           eicc &= PSR_N;
+           if (sregs->inst & 0x10000000)
+               eicc = !eicc;
+           a = sregs->inst & 0x20000000;
+           if (eicc) {
+               operand1 = sregs->inst & 0x3fffff;
+               if (sregs->inst & 0x200000)
+                   operand1 |= 0xffc00000;
+               npc = sregs->pc + (operand1 << 2);
+               if ((cond == BICC_BA) && (a))
+                   sregs->annul = 1;
+           } else {
+               if (a)
+                   sregs->annul = 1;
+           }
+           break;
+       case FPBCC:
+#ifdef STAT
+           sregs->nbranch++;
+#endif
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (ebase.simtime < sregs->ftime) {
+               sregs->ftime = ebase.simtime + sregs->hold;
+           }
+           cond = ((sregs->inst >> 25) & 0x0f);
+           fcc = (sregs->fsr >> 10) & 0x3;
+           switch (cond & 0x7) {
+           case FBN:
+               eicc = 0;
+               break;
+           case FBNE:
+               eicc = (fcc != FCC_E);
+               break;
+           case FBLG:
+               eicc = (fcc == FCC_L) || (fcc == FCC_G);
+               break;
+           case FBUL:
+               eicc = (fcc == FCC_L) || (fcc == FCC_U);
+               break;
+           case FBL:
+               eicc = (fcc == FCC_L);
+               break;
+           case FBUG:
+               eicc = (fcc == FCC_G) || (fcc == FCC_U);
+               break;
+           case FBG:
+               eicc = (fcc == FCC_G);
+               break;
+           case FBU:
+               eicc = (fcc == FCC_U);
+               break;
+           }
+           if (sregs->inst & 0x10000000)
+               eicc = !eicc;
+           a = sregs->inst & 0x20000000;
+           if (eicc) {
+               operand1 = sregs->inst & 0x3fffff;
+               if (sregs->inst & 0x200000)
+                   operand1 |= 0xffc00000;
+               npc = sregs->pc + (operand1 << 2);
+               if ((cond == FBA) && (a))
+                   sregs->annul = 1;
+           } else {
+               if (a)
+                   sregs->annul = 1;
+           }
+           break;
+
+       default:
+           sregs->trap = TRAP_UNIMP;
+           break;
+       }
+       break;
+    case 1:                    /* CALL */
+#ifdef STAT
+       sregs->nbranch++;
+#endif
+       sregs->r[(cwp + 15) & 0x7f] = sregs->pc;
+       npc = sregs->pc + (sregs->inst << 2);
+       break;
+
+    case 2:
+       if ((op3 >> 1) == 0x1a) {
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+           } else {
+               rs1 = (sregs->inst >> 14) & 0x1f;
+               rs2 = sregs->inst & 0x1f;
+               sregs->trap = fpexec(op3, rd, rs1, rs2, sregs);
+           }
+       } else {
+
+           switch (op3) {
+           case TICC:
+               cond = ((sregs->inst >> 25) & 0x0f);
+               switch (cond & 0x7) {
+               case BICC_BN:
+                   eicc = 0;
+                   break;
+               case BICC_BE:
+                   eicc = ICC_Z;
+                   break;
+               case BICC_BLE:
+                   eicc = ICC_Z | (ICC_N ^ ICC_V);
+                   break;
+               case BICC_BL:
+                   eicc = (ICC_N ^ ICC_V);
+                   break;
+               case BICC_BLEU:
+                   eicc = ICC_C | ICC_Z;
+                   break;
+               case BICC_BCS:
+                   eicc = ICC_C;
+                   break;
+               case BICC_NEG:
+                   eicc = ICC_N;
+                   break;
+               case BICC_BVS:
+                   eicc = ICC_V;
+                   break;
+               }
+               eicc &= PSR_N;
+               if (sregs->inst & 0x10000000)
+                   eicc = !eicc;
+               if (eicc) {
+                   sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f));
+               }
+               break;
+
+           case MULScc:
+               operand1 =
+                   (((sregs->psr & PSR_V) ^ ((sregs->psr & PSR_N) >> 2))
+                    << 10) | (rs1 >> 1);
+               if ((sregs->y & 1) == 0)
+                   operand2 = 0;
+               *rdd = operand1 + operand2;
+               sregs->y = (rs1 << 31) | (sregs->y >> 1);
+               add_cc(operand1, operand2, *rdd, &sregs->psr);
+               break;
+           case IXNOR:
+               *rdd = rs1 ^ ~operand2;
+               break;
+           case IXNORCC:
+               *rdd = rs1 ^ ~operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case IXOR:
+               *rdd = rs1 ^ operand2;
+               break;
+           case IXORCC:
+               *rdd = rs1 ^ operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case IOR:
+               *rdd = rs1 | operand2;
+               break;
+           case IORCC:
+               *rdd = rs1 | operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case IORN:
+               *rdd = rs1 | ~operand2;
+               break;
+           case IORNCC:
+               *rdd = rs1 | ~operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case IANDNCC:
+               *rdd = rs1 & ~operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case IANDN:
+               *rdd = rs1 & ~operand2;
+               break;
+           case IAND:
+               *rdd = rs1 & operand2;
+               break;
+           case IANDCC:
+               *rdd = rs1 & operand2;
+               log_cc(*rdd, sregs);
+               break;
+           case SUB:
+               *rdd = rs1 - operand2;
+               break;
+           case SUBCC:
+               *rdd = rs1 - operand2;
+               sub_cc(rs1, operand2, *rdd, sregs);
+               break;
+           case SUBX:
+               *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
+               break;
+           case SUBXCC:
+               *rdd = rs1 - operand2 - ((sregs->psr >> 20) & 1);
+               sub_cc(rs1, operand2, *rdd, sregs);
+               break;
+           case ADD:
+               *rdd = rs1 + operand2;
+               break;
+           case ADDCC:
+               *rdd = rs1 + operand2;
+               add_cc(rs1, operand2, *rdd, &sregs->psr);
+               break;
+           case ADDX:
+               *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
+               break;
+           case ADDXCC:
+               *rdd = rs1 + operand2 + ((sregs->psr >> 20) & 1);
+               add_cc(rs1, operand2, *rdd, &sregs->psr);
+               break;
+           case TADDCC:
+               *rdd = rs1 + operand2;
+               add_cc(rs1, operand2, *rdd, &sregs->psr);
+               if ((rs1 | operand2) & 0x3)
+                   sregs->psr |= PSR_V;
+               break;
+           case TADDCCTV:
+               *rdd = rs1 + operand2;
+               result = 0;
+               add_cc(rs1, operand2, *rdd, &result);
+               if ((rs1 | operand2) & 0x3)
+                   result |= PSR_V;
+               if (result & PSR_V) {
+                   sregs->trap = TRAP_TAG;
+               } else {
+                   sregs->psr = (sregs->psr & PSR_CC) | result;
+               }
+               break;
+           case SLL:
+               *rdd = rs1 << (operand2 & 0x1f);
+               break;
+           case SRL:
+               *rdd = rs1 >> (operand2 & 0x1f);
+               break;
+           case SRA:
+               *rdd = ((int) rs1) >> (operand2 & 0x1f);
+               break;
+           case SAVE:
+               new_cwp = ((sregs->psr & PSR_CWP) - 1) & PSR_CWP;
+               if (sregs->wim & (1 << new_cwp)) {
+                   sregs->trap = TRAP_WOFL;
+                   break;
+               }
+               if (rd > 7)
+                   rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
+               *rdd = rs1 + operand2;
+               sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
+               break;
+           case RESTORE:
+
+#ifdef IUREV0
+               if ((iurev0) && ((sregs->jmpltime + 1) == sregs->ninst)) {
+                   if (!(sregs->rett_err)) {
+                       sregs->rett_err = 1;
+                       if (sis_verbose)
+                           printf("IU rev.0 bug mode entered\n");
+                   }
+               }
+#endif
+
+               new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
+               if (sregs->wim & (1 << new_cwp)) {
+                   sregs->trap = TRAP_WUFL;
+                   break;
+               }
+               if (rd > 7)
+                   rdd = &(sregs->r[((new_cwp << 4) + rd) & 0x7f]);
+               *rdd = rs1 + operand2;
+               sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp;
+               break;
+           case RDPSR:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               *rdd = sregs->psr;
+#ifdef IUREV0
+
+               if (iurev0 & sregs->rett_err) {
+                   operand2 = sregs->psr;
+                   *rdd |= PSR_ET;
+                   *rdd &= ~(PSR_S);
+                   *rdd |= ((*rdd & PSR_PS) << 1);
+                   if (sis_verbose) {
+                       if (operand2 != *rdd)
+                           printf("rdpsr failed: %08X -> %08X\n", operand2, *rdd);
+                   }
+               }
+#endif
+               break;
+           case RDY:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               *rdd = sregs->y;
+               break;
+           case RDWIM:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               *rdd = sregs->wim;
+               break;
+           case RDTBR:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               *rdd = sregs->tbr;
+               break;
+           case WRPSR:
+               if ((sregs->psr & 0x1f) > 7) {
+                   sregs->trap = TRAP_UNIMP;
+                   break;
+               }
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               sregs->psr = (rs1 ^ operand2) & 0x00f03fff;
+               break;
+           case WRWIM:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               sregs->wim = (rs1 ^ operand2) & 0x0ff;
+               break;
+           case WRTBR:
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               sregs->tbr = (sregs->tbr & 0x00000ff0) |
+                   ((rs1 ^ operand2) & 0xfffff000);
+               break;
+           case WRY:
+               sregs->y = (rs1 ^ operand2);
+               break;
+           case JMPL:
+
+#ifdef IUREV0
+               if (iurev0)
+                   sregs->jmpltime = sregs->ninst;
+#endif
+#ifdef STAT
+               sregs->nbranch++;
+#endif
+               sregs->icnt = T_JMPL;   /* JMPL takes two cycles */
+               if (rs1 & 0x3) {
+                   sregs->trap = TRAP_UNALI;
+                   break;
+               }
+               *rdd = sregs->pc;
+               npc = rs1 + operand2;
+               break;
+           case RETT:
+#ifdef IUREV0
+               if (iurev0 && sregs->rett_err) {
+                   sregs->rett_err = 0;
+                   if (sis_verbose)
+                       printf("IU rev.0 bug mode reset\n");
+               }
+#endif
+
+               address = rs1 + operand2;
+               new_cwp = ((sregs->psr & PSR_CWP) + 1) & PSR_CWP;
+               sregs->icnt = T_RETT;   /* RETT takes two cycles */
+               if (sregs->psr & PSR_ET) {
+                   sregs->trap = TRAP_UNIMP;
+                   break;
+               }
+               if (!(sregs->psr & PSR_S)) {
+                   sregs->trap = TRAP_PRIVI;
+                   break;
+               }
+               if (sregs->wim & (1 << new_cwp)) {
+                   sregs->trap = TRAP_WUFL;
+                   break;
+               }
+               if (address & 0x3) {
+                   sregs->trap = TRAP_UNALI;
+                   break;
+               }
+               sregs->psr = (sregs->psr & ~PSR_CWP) | new_cwp | PSR_ET;
+               sregs->psr =
+                   (sregs->psr & ~PSR_S) | ((sregs->psr & PSR_PS) << 1);
+               npc = address;
+               break;
+
+           default:
+               sregs->trap = TRAP_UNIMP;
+               break;
+           }
+       }
+       break;
+    case 3:                    /* Load/store instructions */
+
+       address = rs1 + operand2;
+
+       /* Check for load/store to alternate address space */
+
+       if ((op3 >> 4) == 1) {
+           if (!(sregs->psr & PSR_S)) {
+               sregs->trap = TRAP_PRIVI;
+               break;
+           } else if (sregs->inst & INST_I) {
+               sregs->trap = TRAP_UNIMP;
+               break;
+           } else
+               asi = (sregs->inst >> 5) & 0x0ff;
+       } else {
+           if (sregs->psr & PSR_S)
+               asi = 11;
+           else
+               asi = 10;
+#ifdef IUREV0
+           if (iurev0 && sregs->rett_err) {
+               asi &= ~0x1;
+               asi |= ((sregs->psr & PSR_PS) >> 6);
+           }
+#endif
+       }
+
+       if (op3 & 4) {
+           sregs->icnt = T_ST; /* Set store instruction count */
+#ifdef STAT
+           sregs->nstore++;
+#endif
+       } else {
+           sregs->icnt = T_LD; /* Set load instruction count */
+#ifdef STAT
+           sregs->nload++;
+#endif
+       }
+
+       /* Decode load/store instructions */
+
+       switch (op3) {
+       case LDDA:
+       case LDD:
+           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 = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           sregs->icnt = T_LDD;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           } else {
+               rdd[0] = data;
+               address += 4;
+               mexc = memory_read(asi, address, &data, &ws);
+               sregs->hold += ws;
+#ifdef STAT
+               sregs->nload++; /* Double load counts twice */
+#endif
+               if (mexc) {
+                   sregs->trap = TRAP_DEXC;
+               } else {
+                   rdd[1] = data;
+               }
+           }
+           break;
+
+       case LDA:
+       case LD:
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           } else {
+               *rdd = data;
+           }
+           break;
+       case LDSTUB:
+       case LDSTUBA:
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           sregs->icnt = T_LDST;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+               break;
+           }
+           data = (data >> ((3 - (address & 0x3)) << 3)) & 0x0ff;
+           *rdd = data;
+           data = 0x0ff;
+           mexc = memory_write(asi, address, &data, 0, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+#ifdef STAT
+           sregs->nload++;
+#endif
+           break;
+       case LDSBA:
+       case LDUBA:
+       case LDSB:
+       case LDUB:
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+               break;
+           }
+           data = (data >> ((3 - (address & 0x3)) << 3)) & 0x0ff;
+           if ((op3 == LDSB) && (data >> 7))
+               data |= 0xffffff00;
+           *rdd = data;
+           break;
+       case LDSHA:
+       case LDUHA:
+       case LDSH:
+       case LDUH:
+           if (address & 0x1) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+               break;
+           }
+           if (!(address & 0x2))
+               data >>= 16;
+           data &= 0x0ffff;
+           if ((op3 == LDSH) && (data >> 15))
+               data |= 0xffff0000;
+           *rdd = data;
+           break;
+       case LDF:
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           if (ebase.simtime < sregs->ftime) {
+               if ((sregs->frd == rd) || (sregs->frs1 == rd) ||
+                   (sregs->frs2 == rd))
+                   sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           sregs->flrd = rd;
+           sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
+               sregs->hold + sregs->fhold;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           } else {
+               sregs->fs[rd] = *((float32 *) & data);
+           }
+           break;
+       case LDDF:
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x7) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           if (ebase.simtime < sregs->ftime) {
+               if (((sregs->frd >> 1) == (rd >> 1)) ||
+                   ((sregs->frs1 >> 1) == (rd >> 1)) ||
+                   ((sregs->frs2 >> 1) == (rd >> 1)))
+                   sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           sregs->icnt = T_LDD;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           } else {
+               rd &= 0x1E;
+               sregs->flrd = rd;
+               sregs->fs[rd] = *((float32 *) & data);
+               mexc = memory_read(asi, address + 4, &data, &ws);
+               sregs->hold += ws;
+#ifdef STAT
+               sregs->nload++; /* Double load counts twice */
+#endif
+               if (mexc) {
+                   sregs->trap = TRAP_DEXC;
+               } else {
+                   sregs->fs[rd + 1] = *((float32 *) & data);
+                   sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD +
+                       sregs->hold + sregs->fhold;
+               }
+           }
+           break;
+       case LDFSR:
+           if (ebase.simtime < sregs->ftime) {
+               sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           } else {
+               sregs->fsr =
+                   (sregs->fsr & 0x7FF000) | (data & ~0x7FF000);
+               set_fsr(sregs->fsr);
+           }
+           break;
+       case STFSR:
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           if (ebase.simtime < sregs->ftime) {
+               sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           mexc = memory_write(asi, address, &sregs->fsr, 2, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+           break;
+
+       case ST:
+       case STA:
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_write(asi, address, rdd, 2, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+           break;
+       case STB:
+       case STBA:
+           mexc = memory_write(asi, address, rdd, 0, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+           break;
+       case STD:
+       case STDA:
+           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 = memory_write(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 STDFQ:
+           if ((sregs->psr & 0x1f) > 7) {
+               sregs->trap = TRAP_UNIMP;
+               break;
+           }
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x7) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           if (!(sregs->fsr & FSR_QNE)) {
+               sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
+               break;
+           }
+           rdd = &(sregs->fpq[0]);
+           mexc = memory_write(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;
+           } else {
+               sregs->fsr &= ~FSR_QNE;
+               sregs->fpstate = FP_EXE_MODE;
+           }
+           break;
+       case STHA:
+       case STH:
+           if (address & 0x1) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_write(asi, address, rdd, 1, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+           break;
+       case STF:
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           if (ebase.simtime < sregs->ftime) {
+               if (sregs->frd == rd)
+                   sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           mexc = memory_write(asi, address, &sregs->fsi[rd], 2, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+           }
+           break;
+       case STDF:
+           if (!((sregs->psr & PSR_EF) && chk_fp(sregs))) {
+               sregs->trap = TRAP_FPDIS;
+               break;
+           }
+           if (address & 0x7) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           rd &= 0x1E;
+           if (ebase.simtime < sregs->ftime) {
+               if ((sregs->frd == rd) || (sregs->frd + 1 == rd))
+                   sregs->fhold += (sregs->ftime - ebase.simtime);
+           }
+           mexc = memory_write(asi, address, &sregs->fsi[rd], 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;
+       case SWAP:
+       case SWAPA:
+           if (address & 0x3) {
+               sregs->trap = TRAP_UNALI;
+               break;
+           }
+           mexc = memory_read(asi, address, &data, &ws);
+           sregs->hold += ws;
+           if (mexc) {
+               sregs->trap = TRAP_DEXC;
+               break;
+           }
+           mexc = memory_write(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;
+
+
+       default:
+           sregs->trap = TRAP_UNIMP;
+           break;
+       }
+
+#ifdef LOAD_DEL
+
+       if (!(op3 & 4)) {
+           sregs->ildtime = ebase.simtime + sregs->hold + sregs->icnt;
+           sregs->ildreg = rd;
+           if ((op3 | 0x10) == 0x13)
+               sregs->ildreg |= 1;     /* Double load, odd register loaded
+                                        * last */
+       }
+#endif
+       break;
+
+    default:
+       sregs->trap = TRAP_UNIMP;
+       break;
+    }
+    sregs->g[0] = 0;
+    if (!sregs->trap) {
+       sregs->pc = pc;
+       sregs->npc = npc;
+    }
+    return (0);
+}
+
+#define T_FABSs                2
+#define T_FADDs                4
+#define T_FADDd                4
+#define T_FCMPs                4
+#define T_FCMPd                4
+#define T_FDIVs                20
+#define T_FDIVd                35
+#define T_FMOVs                2
+#define T_FMULs                5
+#define T_FMULd                9
+#define T_FNEGs                2
+#define T_FSQRTs       37
+#define T_FSQRTd       65
+#define T_FSUBs                4
+#define T_FSUBd                4
+#define T_FdTOi                7
+#define T_FdTOs                3
+#define T_FiTOs                6
+#define T_FiTOd                6
+#define T_FsTOi                6
+#define T_FsTOd                2
+
+#define FABSs  0x09
+#define FADDs  0x41
+#define FADDd  0x42
+#define FCMPs  0x51
+#define FCMPd  0x52
+#define FCMPEs 0x55
+#define FCMPEd 0x56
+#define FDIVs  0x4D
+#define FDIVd  0x4E
+#define FMOVs  0x01
+#define FMULs  0x49
+#define FMULd  0x4A
+#define FNEGs  0x05
+#define FSQRTs 0x29
+#define FSQRTd 0x2A
+#define FSUBs  0x45
+#define FSUBd  0x46
+#define FdTOi  0xD2
+#define FdTOs  0xC6
+#define FiTOs  0xC4
+#define FiTOd  0xC8
+#define FsTOi  0xD1
+#define FsTOd  0xC9
+
+
+int
+fpexec(op3, rd, rs1, rs2, sregs)
+    uint32          op3, rd, rs1, rs2;
+    struct pstate  *sregs;
+{
+    uint32          opf, tem, accex;
+    float32         ftmps;
+    float64         ftmpd;
+    int32           fcc;
+    char           *res;
+    uint32          ldadj;
+
+    if (sregs->fpstate == FP_EXC_MODE) {
+       sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_SEQ_ERR;
+       sregs->fpstate == FP_EXC_PE;
+       return (0);
+    }
+    if (sregs->fpstate == FP_EXC_PE) {
+       sregs->fpstate = FP_EXC_MODE;
+       return (TRAP_FPEXC);
+    }
+    opf = (sregs->inst >> 5) & 0x1ff;
+
+    /*
+     * Check if we already have an FPop in the pipe. If so, halt until it is
+     * finished by incrementing fhold with the remaining execution time
+     */
+
+    if (ebase.simtime < sregs->ftime) {
+       sregs->fhold = (sregs->ftime - ebase.simtime);
+    } else {
+       sregs->fhold = 0;
+
+       /* Check load dependencies. */
+
+       if (ebase.simtime < sregs->ltime) {
+
+           /* Don't check rs1 if single operand instructions */
+
+           if (((opf >> 6) == 0) || ((opf >> 6) == 3))
+               rs1 = 32;
+
+           /* Adjust for double floats */
+
+           ldadj = opf & 1;
+           if (!(((sregs->flrd - rs1) >> ldadj) && ((sregs->flrd - rs2) >> ldadj)))
+               sregs->fhold++;
+       }
+    }
+
+    sregs->finst++;
+
+    sregs->frs1 = rs1;         /* Store src and dst for dependecy check */
+    sregs->frs2 = rs2;
+    sregs->frd = rd;
+
+    sregs->ftime = ebase.simtime + sregs->hold + sregs->fhold;
+
+    /* SPARC is big-endian - swap double floats if host is little-endian */
+    /* This is ugly - I know ... */
+#ifdef HOST_LITTLE_ENDIAN_FLOAT
+    rs1 &= 0x1f;
+    switch (opf) {
+       case FADDd:
+       case FDIVd:
+       case FMULd:
+       case FSQRTd:
+       case FSUBd:
+        case FCMPd:
+        case FCMPEd:
+       case FdTOi:
+       case FdTOs:
+           sregs->fdp[rs1 | 1] = sregs->fs[rs1 & ~1];
+           sregs->fdp[rs1 & ~1] = sregs->fs[rs1 | 1];
+           sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
+           sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
+    default:
+    }
+#endif
+
+    clear_accex();
+
+    switch (opf) {
+    case FABSs:
+       sregs->fs[rd] = fabs(sregs->fs[rs2]);
+       sregs->ftime += T_FABSs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FADDs:
+       sregs->fs[rd] = sregs->fs[rs1] + sregs->fs[rs2];
+       sregs->ftime += T_FADDs;
+       break;
+    case FADDd:
+       sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] + sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FADDd;
+       break;
+    case FCMPs:
+    case FCMPEs:
+       if (sregs->fs[rs1] == sregs->fs[rs2])
+           fcc = 3;
+       else if (sregs->fs[rs1] < sregs->fs[rs2])
+           fcc = 2;
+       else if (sregs->fs[rs1] > sregs->fs[rs2])
+           fcc = 1;
+       else
+           fcc = 0;
+       sregs->fsr |= 0x0C00;
+       sregs->fsr &= ~(fcc << 10);
+       sregs->ftime += T_FCMPs;
+       sregs->frd = 32;        /* rd ignored */
+       if ((fcc == 0) && (opf == FCMPEs)) {
+           sregs->fpstate == FP_EXC_PE;
+           sregs->fsr = (sregs->fsr & ~0x1C000) | (1 << 14);
+       }
+       break;
+    case FCMPd:
+    case FCMPEd:
+       if (sregs->fd[rs1 >> 1] == sregs->fd[rs2 >> 1])
+           fcc = 3;
+       else if (sregs->fd[rs1 >> 1] < sregs->fd[rs2 >> 1])
+           fcc = 2;
+       else if (sregs->fd[rs1 >> 1] > sregs->fd[rs2 >> 1])
+           fcc = 1;
+       else
+           fcc = 0;
+       sregs->fsr |= 0x0C00;
+       sregs->fsr &= ~(fcc << 10);
+       sregs->ftime += T_FCMPd;
+       sregs->frd = 32;        /* rd ignored */
+       if ((fcc == 0) && (opf == FCMPEd)) {
+           sregs->fpstate == FP_EXC_PE;
+           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
+       }
+       break;
+    case FDIVs:
+       sregs->fs[rd] = sregs->fs[rs1] / sregs->fs[rs2];
+       sregs->ftime += T_FDIVs;
+       break;
+    case FDIVd:
+       sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] / sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FDIVd;
+       break;
+    case FMOVs:
+       sregs->fs[rd] = sregs->fs[rs2];
+       sregs->ftime += T_FMOVs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FMULs:
+       sregs->fs[rd] = sregs->fs[rs1] * sregs->fs[rs2];
+       sregs->ftime += T_FMULs;
+       break;
+    case FMULd:
+       sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] * sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FMULd;
+       break;
+    case FNEGs:
+       sregs->fs[rd] = -sregs->fs[rs2];
+       sregs->ftime += T_FNEGs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FSQRTs:
+       if (sregs->fs[rs2] < 0.0) {
+           sregs->fpstate == FP_EXC_PE;
+           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
+           sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
+           break;
+       }
+       sregs->fs[rd] = sqrt(sregs->fs[rs2]);
+       sregs->ftime += T_FSQRTs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FSQRTd:
+       if (sregs->fd[rs2 >> 1] < 0.0) {
+           sregs->fpstate == FP_EXC_PE;
+           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
+           sregs->fsr = (sregs->fsr & 0x1f) | 0x10;
+           break;
+       }
+       sregs->fd[rd >> 1] = sqrt(sregs->fd[rs2 >> 1]);
+       sregs->ftime += T_FSQRTd;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FSUBs:
+       sregs->fs[rd] = sregs->fs[rs1] - sregs->fs[rs2];
+       sregs->ftime += T_FSUBs;
+       break;
+    case FSUBd:
+       sregs->fd[rd >> 1] = sregs->fd[rs1 >> 1] - sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FSUBd;
+       break;
+    case FdTOi:
+       sregs->fsi[rd] = (int) sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FdTOi;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FdTOs:
+       sregs->fs[rd] = (float32) sregs->fd[rs2 >> 1];
+       sregs->ftime += T_FdTOs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FiTOs:
+       sregs->fs[rd] = (float32) sregs->fsi[rs2];
+       sregs->ftime += T_FiTOs;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FiTOd:
+       sregs->fd[rd >> 1] = (float64) sregs->fsi[rs2];
+       sregs->ftime += T_FiTOd;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FsTOi:
+       sregs->fsi[rd] = (int) sregs->fs[rs2];
+       sregs->ftime += T_FsTOi;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+    case FsTOd:
+       sregs->fd[rd >> 1] = sregs->fs[rs2];
+       sregs->ftime += T_FsTOd;
+       sregs->frs1 = 32;       /* rs1 ignored */
+       break;
+
+    default:
+       sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_UNIMP;
+       sregs->fpstate == FP_EXC_PE;
+    }
+
+    accex = get_accex();
+
+#ifdef HOST_LITTLE_ENDIAN_FLOAT
+    switch (opf) {
+    case FADDd:
+    case FDIVd:
+    case FMULd:
+    case FSQRTd:
+    case FSUBd:
+    case FiTOd:
+    case FsTOd:
+       sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
+       sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
+    default:
+    }
+#endif
+    if (sregs->fpstate == FP_EXC_PE) {
+       sregs->fpq[0] = sregs->pc;
+       sregs->fpq[1] = sregs->inst;
+       sregs->fsr |= FSR_QNE;
+    } else {
+       tem = (sregs->fsr >> 23) & 0x1f;
+       if (tem & accex) {
+           sregs->fpstate = FP_EXC_PE;
+           sregs->fsr = (sregs->fsr & ~FSR_TT) | FP_IEEE;
+           sregs->fsr = ((sregs->fsr & ~0x1f) | accex);
+       } else {
+           sregs->fsr = ((((sregs->fsr >> 5) | accex) << 5) | accex);
+       }
+       if (sregs->fpstate == FP_EXC_PE) {
+           sregs->fpq[0] = sregs->pc;
+           sregs->fpq[1] = sregs->inst;
+           sregs->fsr |= FSR_QNE;
+       }
+    }
+    clear_accex();
+
+    return (0);
+
+
+}
+
+int
+execute_trap(sregs)
+    struct pstate  *sregs;
+{
+    int32           cwp;
+
+    if (sregs->trap == 256) {
+       sregs->pc = 0;
+       sregs->npc = 4;
+       sregs->trap = 0;
+    } else {
+
+       if ((sregs->psr & PSR_ET) == 0)
+           return (ERROR);
+
+       sregs->tbr = (sregs->tbr & 0xfffff000) | (sregs->trap << 4);
+       sregs->trap = 0;
+       sregs->psr &= ~PSR_ET;
+       sregs->psr |= ((sregs->psr & PSR_S) >> 1);
+       sregs->annul = 0;
+       sregs->psr = (((sregs->psr & PSR_CWP) - 1) & 0x7) | (sregs->psr & ~PSR_CWP);
+       cwp = ((sregs->psr & PSR_CWP) << 4);
+       sregs->r[(cwp + 17) & 0x7f] = sregs->pc;
+       sregs->r[(cwp + 18) & 0x7f] = sregs->npc;
+       sregs->psr |= PSR_S;
+       sregs->pc = sregs->tbr;
+       sregs->npc = sregs->tbr + 4;
+
+       /* Increase simulator time */
+       sregs->icnt = TRAP_C;
+
+    }
+
+
+    return (0);
+
+}
+
+extern struct irqcell irqarr[16];
+
+void
+check_interrupts(sregs)
+    struct pstate  *sregs;
+{
+    if ((ext_irl) && (sregs->psr & PSR_ET) &&
+       ((ext_irl == 15) || (ext_irl > ((sregs->psr & PSR_PIL) >> 8)))) {
+       if (sregs->trap == 0) {
+           sregs->trap = 16 + ext_irl;
+           irqarr[ext_irl & 0x0f].callback(irqarr[ext_irl & 0x0f].arg);
+           clear_int(ext_irl);
+       }
+    }
+}
+
+init_regs(sregs)
+    struct pstate  *sregs;
+{
+    int32           i;
+
+    sregs->pc = 0;
+    sregs->npc = 4;
+    sregs->trap = 0;
+    sregs->psr &= 0x00f03fdf;
+    sregs->psr |= 0x080;       /* Set supervisor bit */
+    sregs->breakpoint = 0;
+    sregs->annul = 0;
+    sregs->fpstate = FP_EXE_MODE;
+    sregs->fpqn = 0;
+    sregs->ftime = 0;
+    sregs->ltime = 0;
+    sregs->err_mode = 0;
+    ext_irl = 0;
+    irqpend = 0;
+    sregs->g[0] = 0;
+#ifdef HOST_LITTLE_ENDIAN_FLOAT
+    sregs->fdp = (float32 *) sregs->fd;
+    sregs->fsi = (int32 *) sregs->fs;
+#else
+    sregs->fs = (float32 *) sregs->fd;
+    sregs->fsi = (int32 *) sregs->fd;
+#endif
+    sregs->fsr = 0;
+    sregs->fpu_pres = !nfp;
+    set_fsr(sregs->fsr);
+    sregs->bphit = 0;
+    sregs->ildreg = 0;
+    sregs->ildtime = 0;
+
+    sregs->rett_err = 0;
+    sregs->jmpltime = 0;
+}
+
+chk_fp(sregs)
+    struct pstate  *sregs;
+{
+    return (sregs->fpu_pres);
+}
diff --git a/sim/erc32/float.c b/sim/erc32/float.c
new file mode 100644 (file)
index 0000000..30ffffa
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * This file is part of SIS.
+ *
+ * SIS, SPARC instruction simulator. 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 2 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, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This file implements the interface between the host and the simulated
+ * FPU. IEEE trap handling is done as follows: 
+ * 1. In the host, all IEEE traps are masked
+ * 2. After each simulated FPU instruction, check if any exception occured 
+ *    by reading the exception bits from the host FPU status register 
+ *    (get_accex()).
+ * 3. Propagate any exceptions to the simulated FSR.
+ * 4. Clear host exception bits
+ *
+ *
+ * This can also be done using ieee_flags() library routine on sun.
+ */
+
+#include "sis.h"
+
+/* This host dependent routine should return the accrued exceptions */
+int
+get_accex()
+{
+#ifdef sparc
+    return ((_get_fsr_raw() >> 5) & 0x1F);
+#elif i386
+    uint32 accx;
+
+    accx = _get_sw() & 0x3f;
+    accx = ((accx & 1) << 4) | ((accx & 2) >> 1) | ((accx & 4) >> 1) |
+          (accx & 8) | ((accx & 16) >> 2) | ((accx & 32) >> 5);
+    return(accx);
+#else
+    return(0);
+#warning no fpu trap support for this target
+#endif
+
+}
+
+/* How to clear the accrued exceptions */
+int
+clear_accex()
+{
+#ifdef sparc
+    set_fsr((_get_fsr_raw() & ~0x3e0));
+#elif i386
+    asm("
+.text
+       fnclex
+
+    ");
+#else
+#warning no fpu trap support for this target
+#endif
+}
+
+/* How to map SPARC FSR onto the host */
+int
+set_fsr(fsr)
+uint32 fsr;
+{
+#ifdef sparc
+       _set_fsr_raw(fsr & ~0x0f800000);
+#elif i386
+     uint32 rawfsr;
+
+     fsr >>= 30;
+     switch (fsr) {
+       case 0: 
+       case 2: break;
+       case 1: fsr = 3;
+       case 3: fsr = 1;
+    }
+    rawfsr = _get_cw();
+    rawfsr |= (fsr << 10) | 0x3ff;
+    __setfpucw(rawfsr);
+#else
+#warning no fpu trap support for this target
+#endif
+}
+
+
+/* Host dependent support functions */
+
+#ifdef sparc
+
+    asm("
+
+.text
+        .align 4
+        .global __set_fsr_raw,_set_fsr_raw
+__set_fsr_raw:
+_set_fsr_raw:
+        save %sp,-104,%sp
+        st %i0,[%fp+68]
+        ld [%fp+68], %fsr
+        mov 0,%i0
+        ret
+        restore
+        .align 4
+        .global __get_fsr_raw
+        .global _get_fsr_raw
+__get_fsr_raw:
+_get_fsr_raw:
+        save %sp,-104,%sp
+        st %fsr,[%fp+68]
+        ld [%fp+68], %i0
+        ret
+        restore
+    ");
+
+#elif i386
+       /* both these align statements were 16, not 8 */
+
+    asm("
+
+.text
+        .align 8
+.globl _get_sw,__get_sw
+__get_sw:
+_get_sw:
+        pushl %ebp
+        movl %esp,%ebp
+        movl $0,%eax
+        fnstsw %ax
+        movl %ebp,%esp
+        popl %ebp
+        ret
+
+        .align 8
+.globl _get_cw,__get_cw
+__get_cw:
+_get_cw:
+        pushl %ebp
+        movl %esp,%ebp
+        subw $2,%esp
+        fnstcw -2(%ebp)
+        movw -2(%ebp),%eax
+        movl %ebp,%esp
+        popl %ebp
+        ret
+
+
+    ");
+
+
+#else
+#warning no fpu trap support for this target
+#endif
+
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
new file mode 100644 (file)
index 0000000..2cd9bf2
--- /dev/null
@@ -0,0 +1,968 @@
+/*
+ * func.c, misc simulator functions. This file is part of SIS.
+ * 
+ * SIS, SPARC instruction simulator V1.8 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 2 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, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ */
+
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include "sis.h"
+#include "end.h"
+#include <dis-asm.h>
+
+
+#define        VAL(x)  strtol(x,(char *)NULL,0)
+
+extern char    *readline(char *prompt);        /* GNU readline function */
+
+struct disassemble_info dinfo;
+struct pstate   sregs;
+extern struct estate ebase;
+int             ctrl_c = 0;
+int             sis_verbose = 0;
+char           *sis_version = "2.1";
+int             nfp = 0;
+char            uart_dev1[128] = "/dev/ptypc";
+char            uart_dev2[128] = "/dev/ptypd";
+
+#ifdef IUREV0
+int             iurev0 = 0;
+#endif
+#ifdef MECREV0
+int             mecrev0 = 0;
+#endif
+
+int 
+batch(sregs, fname)
+    struct pstate  *sregs;
+    char           *fname;
+{
+    FILE           *fp;
+    char            lbuf[1024];
+
+    if ((fp = fopen(fname, "r")) == NULL) {
+       fprintf(stderr, "couldn't open batch file %s\n", fname);
+       return (0);
+    }
+    while (!feof(fp)) {
+       lbuf[0] = 0;
+       fgets(lbuf, 1023, fp);
+       if ((strlen(lbuf) > 0) && (lbuf[strlen(lbuf) - 1] == '\n'))
+           lbuf[strlen(lbuf) - 1] = 0;
+       printf("sis> %s\n", lbuf);
+       exec_cmd(sregs, lbuf);
+    }
+    fclose(fp);
+    return (1);
+}
+
+set_regi(sregs, reg, rval)
+    struct pstate  *sregs;
+    int32           reg;
+    uint32          rval;
+{
+    uint32          cwp;
+    int32           err = 0;
+
+    cwp = ((sregs->psr & 0x7) << 4);
+    if ((reg > 0) && (reg < 8)) {
+       sregs->g[reg] = rval;
+    } else if ((reg >= 8) && (reg < 32)) {
+       sregs->r[(cwp + reg) & 0x7f] = rval;
+    } else if ((reg >= 32) && (reg < 64)) {
+       sregs->fsi[reg - 32] = rval;
+    } else {
+       switch (reg) {
+       case 64:
+           sregs->y = rval;
+           break;
+       case 65:
+           sregs->psr = rval;
+           break;
+       case 66:
+           sregs->wim = rval;
+           break;
+       case 67:
+           sregs->tbr = rval;
+           break;
+       case 68:
+           sregs->pc = rval;
+           break;
+       case 69:
+           sregs->npc = rval;
+           break;
+       case 70:
+           sregs->fsr = rval;
+           set_fsr(rval);
+           break;
+    defualt:break;
+       }
+    }
+}
+
+void
+get_regi(struct pstate * sregs, int32 reg, char *buf)
+{
+    uint32          cwp;
+    uint32          rval = 0;
+
+    cwp = ((sregs->psr & 0x7) << 4);
+    if ((reg >= 0) && (reg < 8)) {
+       rval = sregs->g[reg];
+    } else if ((reg >= 8) && (reg < 32)) {
+       rval = sregs->r[(cwp + reg) & 0x7f];
+    } else if ((reg >= 32) && (reg < 64)) {
+       rval = sregs->fsi[reg - 32];
+    } else {
+       switch (reg) {
+       case 64:
+           rval = sregs->y;
+           break;
+       case 65:
+           rval = sregs->psr;
+           break;
+       case 66:
+           rval = sregs->wim;
+           break;
+       case 67:
+           rval = sregs->tbr;
+           break;
+       case 68:
+           rval = sregs->pc;
+           break;
+       case 69:
+           rval = sregs->npc;
+           break;
+       case 70:
+           rval = sregs->fsr;
+           break;
+    defualt:break;
+       }
+    }
+    buf[0] = (rval >> 24) & 0x0ff;
+    buf[1] = (rval >> 16) & 0x0ff;
+    buf[2] = (rval >> 8) & 0x0ff;
+    buf[3] = rval & 0x0ff;
+}
+
+
+set_rega(sregs, reg, rval)
+    struct pstate  *sregs;
+    char           *reg;
+    uint32          rval;
+{
+    uint32          cwp;
+    int32           err = 0;
+
+    cwp = ((sregs->psr & 0x7) << 4);
+    if (strcmp(reg, "psr") == 0)
+       sregs->psr = (rval = (rval & 0x00f03fff));
+    else if (strcmp(reg, "tbr") == 0)
+       sregs->tbr = (rval = (rval & 0xfffffff0));
+    else if (strcmp(reg, "wim") == 0)
+       sregs->wim = (rval = (rval & 0x0ff));
+    else if (strcmp(reg, "y") == 0)
+       sregs->y = rval;
+    else if (strcmp(reg, "pc") == 0)
+       sregs->pc = rval;
+    else if (strcmp(reg, "npc") == 0)
+       sregs->npc = rval;
+    else if (strcmp(reg, "fsr") == 0) {
+       sregs->fsr = rval;
+       set_fsr(rval);
+    } else if (strcmp(reg, "g0") == 0)
+       err = 2;
+    else if (strcmp(reg, "g1") == 0)
+       sregs->g[1] = rval;
+    else if (strcmp(reg, "g2") == 0)
+       sregs->g[2] = rval;
+    else if (strcmp(reg, "g3") == 0)
+       sregs->g[3] = rval;
+    else if (strcmp(reg, "g4") == 0)
+       sregs->g[4] = rval;
+    else if (strcmp(reg, "g5") == 0)
+       sregs->g[5] = rval;
+    else if (strcmp(reg, "g6") == 0)
+       sregs->g[6] = rval;
+    else if (strcmp(reg, "g7") == 0)
+       sregs->g[7] = rval;
+    else if (strcmp(reg, "o0") == 0)
+       sregs->r[(cwp + 8) & 0x7f] = rval;
+    else if (strcmp(reg, "o1") == 0)
+       sregs->r[(cwp + 9) & 0x7f] = rval;
+    else if (strcmp(reg, "o2") == 0)
+       sregs->r[(cwp + 10) & 0x7f] = rval;
+    else if (strcmp(reg, "o3") == 0)
+       sregs->r[(cwp + 11) & 0x7f] = rval;
+    else if (strcmp(reg, "o4") == 0)
+       sregs->r[(cwp + 12) & 0x7f] = rval;
+    else if (strcmp(reg, "o5") == 0)
+       sregs->r[(cwp + 13) & 0x7f] = rval;
+    else if (strcmp(reg, "o6") == 0)
+       sregs->r[(cwp + 14) & 0x7f] = rval;
+    else if (strcmp(reg, "o7") == 0)
+       sregs->r[(cwp + 15) & 0x7f] = rval;
+    else if (strcmp(reg, "l0") == 0)
+       sregs->r[(cwp + 16) & 0x7f] = rval;
+    else if (strcmp(reg, "l1") == 0)
+       sregs->r[(cwp + 17) & 0x7f] = rval;
+    else if (strcmp(reg, "l2") == 0)
+       sregs->r[(cwp + 18) & 0x7f] = rval;
+    else if (strcmp(reg, "l3") == 0)
+       sregs->r[(cwp + 19) & 0x7f] = rval;
+    else if (strcmp(reg, "l4") == 0)
+       sregs->r[(cwp + 20) & 0x7f] = rval;
+    else if (strcmp(reg, "l5") == 0)
+       sregs->r[(cwp + 21) & 0x7f] = rval;
+    else if (strcmp(reg, "l6") == 0)
+       sregs->r[(cwp + 22) & 0x7f] = rval;
+    else if (strcmp(reg, "l7") == 0)
+       sregs->r[(cwp + 23) & 0x7f] = rval;
+    else if (strcmp(reg, "i0") == 0)
+       sregs->r[(cwp + 24) & 0x7f] = rval;
+    else if (strcmp(reg, "i1") == 0)
+       sregs->r[(cwp + 25) & 0x7f] = rval;
+    else if (strcmp(reg, "i2") == 0)
+       sregs->r[(cwp + 26) & 0x7f] = rval;
+    else if (strcmp(reg, "i3") == 0)
+       sregs->r[(cwp + 27) & 0x7f] = rval;
+    else if (strcmp(reg, "i4") == 0)
+       sregs->r[(cwp + 28) & 0x7f] = rval;
+    else if (strcmp(reg, "i5") == 0)
+       sregs->r[(cwp + 29) & 0x7f] = rval;
+    else if (strcmp(reg, "i6") == 0)
+       sregs->r[(cwp + 30) & 0x7f] = rval;
+    else if (strcmp(reg, "i7") == 0)
+       sregs->r[(cwp + 31) & 0x7f] = rval;
+    else
+       err = 1;
+    switch (err) {
+    case 0:
+       printf("%s = %d (0x%08x)\n", reg, rval, rval);
+       break;
+    case 1:
+       printf("no such regiser: %s\n", reg);
+       break;
+    case 2:
+       printf("cannot set g0\n");
+       break;
+    default:
+       break;
+    }
+
+}
+
+disp_reg(sregs, reg)
+    struct pstate  *sregs;
+    char           *reg;
+{
+    if (strncmp(reg, "w",1) == 0)
+       disp_regs(sregs, VAL(&reg[1]));
+}
+
+exec_cmd(sregs, cmd)
+    char           *cmd;
+    struct pstate  *sregs;
+{
+    char           *cmd1, *cmd2;
+    int32           ws, stat;
+    int32           len, i, clen, j;
+    static          daddr = 0;
+    char           *cmdsave;
+
+    stat = OK;
+    cmdsave = strdup(cmd);
+    if ((cmd1 = strtok(cmd, " \t")) != NULL) {
+       clen = strlen(cmd1);
+       if (strncmp(cmd1, "bp", clen) == 0) {
+           for (i = 0; i < sregs->bptnum; i++) {
+               printf("  %d : 0x%08x\n", i + 1, sregs->bpts[i]);
+           }
+       } else if (strncmp(cmd1, "+bp", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               sregs->bpts[sregs->bptnum] = VAL(cmd1) & ~0x3;
+               printf("added breakpoint %d at 0x%08x\n",
+                      sregs->bptnum + 1, sregs->bpts[sregs->bptnum]);
+               sregs->bptnum += 1;
+           }
+       } else if (strncmp(cmd1, "-bp", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               i = VAL(cmd1) - 1;
+               if ((i >= 0) && (i < sregs->bptnum)) {
+                   printf("deleted breakpoint %d at 0x%08x\n", i + 1,
+                          sregs->bpts[i]);
+                   for (; i < sregs->bptnum - 1; i++) {
+                       sregs->bpts[i] = sregs->bpts[i + 1];
+                   }
+                   sregs->bptnum -= 1;
+               }
+           }
+       } else if (strncmp(cmd1, "batch", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+               printf("no file specified\n");
+           } else {
+               batch(sregs, cmd1);
+           }
+       } else if (strncmp(cmd1, "cont", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+               stat = run_sim(sregs, 1, 0, 0);
+           } else {
+               stat = run_sim(sregs, 0, VAL(cmd1), 0);
+           }
+           daddr = sregs->pc;
+           sim_stop();
+       } else if (strncmp(cmd1, "dis", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               daddr = VAL(cmd1);
+           }
+           if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
+               len = VAL(cmd2);
+           } else
+               len = 16;
+           printf("\n");
+           dis_mem(daddr, len, &dinfo);
+           printf("\n");
+           daddr += len * 4;
+       } else if (strncmp(cmd1, "echo", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               printf("%s\n", (&cmdsave[clen+1]));
+           }
+       } else if (strncmp(cmd1, "float", clen) == 0) {
+           stat = disp_fpu(sregs);
+       } else if (strncmp(cmd1, "go", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+               printf("wrong syntax: go <address> [inst_count]\n");
+           } else {
+               len = VAL(cmd1);
+               sregs->pc = len & ~3;
+               sregs->npc = sregs->pc + 4;
+               if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
+                   stat = run_sim(sregs, 0, VAL(cmd2), 0);
+               } else {
+                   stat = run_sim(sregs, 1, 0, 0);
+               }
+           }
+           daddr = sregs->pc;
+           sim_stop();
+       } else if (strncmp(cmd1, "help", clen) == 0) {
+           gen_help();
+       } else if (strncmp(cmd1, "history", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               sregs->histlen = VAL(cmd1);
+               if (sregs->histbuf != NULL)
+                   free(sregs->histbuf);
+               sregs->histbuf = (struct histype *) calloc(sregs->histlen, sizeof(struct histype));
+               printf("trace history length = %d\n\r", sregs->histlen);
+               sregs->histind = 0;
+
+           } else {
+               j = sregs->histind;
+               for (i = 0; i < sregs->histlen; i++) {
+                   if (j >= sregs->histlen)
+                       j = 0;
+                   printf(" %8d ", sregs->histbuf[j].time);
+                   dis_mem(sregs->histbuf[j].addr, 1, &dinfo);
+                   j++;
+               }
+           }
+
+       } else if (strncmp(cmd1, "load", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               bfd_load(cmd1);
+           } else {
+               printf("load: no file specified\n");
+           }
+       } else if (strncmp(cmd1, "mem", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL)
+               daddr = VAL(cmd1);
+           if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL)
+               len = VAL(cmd2);
+           else
+               len = 64;
+           disp_mem(daddr, len);
+           daddr += len;
+       } else if (strncmp(cmd1, "perf", clen) == 0) {
+           cmd1 = strtok(NULL, " \t\n\r");
+           if ((cmd1 != NULL) &&
+               (strncmp(cmd1, "reset", strlen(cmd1)) == 0)) {
+               reset_stat(sregs);
+           } else
+               show_stat(sregs);
+       } else if (strncmp(cmd1, "quit", clen) == 0) {
+           exit(0);
+       } else if (strncmp(cmd1, "reg", clen) == 0) {
+           cmd1 = strtok(NULL, " \t\n\r");
+           cmd2 = strtok(NULL, " \t\n\r");
+           if (cmd2 != NULL)
+               set_rega(sregs, cmd1, VAL(cmd2));
+           else if (cmd1 != NULL)
+               disp_reg(sregs, cmd1);
+           else {
+               disp_regs(sregs,sregs->psr);
+               disp_ctrl(sregs);
+           }
+       } else if (strncmp(cmd1, "reset", clen) == 0) {
+           ebase.simtime = 0;
+           reset_all();
+           reset_stat(sregs);
+       } else if (strncmp(cmd1, "run", clen) == 0) {
+           ebase.simtime = 0;
+           reset_all();
+           reset_stat(sregs);
+           if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+               stat = run_sim(sregs, 1, 0, 0);
+           } else {
+               stat = run_sim(sregs, 0, VAL(cmd1), 0);
+           }
+           daddr = sregs->pc;
+           sim_stop();
+       } else if (strncmp(cmd1, "shell", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) {
+               system(&cmdsave[clen]);
+           }
+       } else if (strncmp(cmd1, "step", clen) == 0) {
+           stat = run_sim(sregs, 0, 1, 1);
+           daddr = sregs->pc;
+           sim_stop();
+       } else if (strncmp(cmd1, "tra", clen) == 0) {
+           if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) {
+               stat = run_sim(sregs, 1, 0, 1);
+           } else {
+               stat = run_sim(sregs, 0, VAL(cmd1), 1);
+           }
+           printf("\n");
+           daddr = sregs->pc;
+           sim_stop();
+       } else
+           printf("syntax error\n");
+    }
+    if (cmdsave != NULL)
+       free(cmdsave);
+    return (stat);
+}
+
+
+reset_stat(sregs)
+    struct pstate  *sregs;
+{
+    sregs->tottime = 0;
+    sregs->pwdtime = 0;
+    sregs->ninst = 0;
+    sregs->fholdt = 0;
+    sregs->holdt = 0;
+    sregs->icntt = 0;
+    sregs->finst = 0;
+    sregs->nstore = 0;
+    sregs->nload = 0;
+    sregs->nbranch = 0;
+    sregs->simstart = ebase.simtime;
+
+}
+
+show_stat(sregs)
+    struct pstate  *sregs;
+{
+    int32           simperf = 0;
+    uint32          iinst;
+    uint32          stime;
+
+    stime = ebase.simtime - sregs->simstart;   /* Total simulated time */
+#ifdef STAT
+
+    iinst = sregs->ninst - sregs->finst - sregs->nload - sregs->nstore -
+       sregs->nbranch;
+#endif
+
+    printf("\n Cycles       : %9d\n\r", ebase.simtime - sregs->simstart);
+    printf(" Instructions : %9d\n", sregs->ninst);
+
+#ifdef STAT
+    printf("   integer    : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst);
+    printf("   load       : %9.2f %%\n",
+          100.0 * (float) sregs->nload / (float) sregs->ninst);
+    printf("   store      : %9.2f %%\n",
+          100.0 * (float) sregs->nstore / (float) sregs->ninst);
+    printf("   branch     : %9.2f %%\n",
+          100.0 * (float) sregs->nbranch / (float) sregs->ninst);
+    printf("   float      : %9.2f %%\n",
+          100.0 * (float) sregs->finst / (float) sregs->ninst);
+    printf(" Integer CPI  : %9.2f\n",
+          ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst))
+          /
+          (float) (sregs->ninst - sregs->finst));
+    printf(" Float CPI    : %9.2f\n",
+          ((float) sregs->fholdt / (float) 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        : %5.2f ms\n", (float) (ebase.simtime - sregs->simstart) / 1000.0 / sregs->freq);
+    printf(" Processor utilisation       : %5.2f %%\n", 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime)));
+    printf(" Real-time / simulator-time  : %5.2f \n",
+      ((float) sregs->tottime) / ((float) (stime) / (sregs->freq * 1.0E6)));
+    printf(" Used time (sys + user)      : %3d s\n\n", sregs->tottime);
+}
+
+
+
+init_bpt(sregs)
+    struct pstate  *sregs;
+{
+    sregs->bptnum = 0;
+    sregs->histlen = 0;
+    sregs->histind = 0;
+    sregs->histbuf = NULL;
+
+}
+
+void
+int_handler(sig)
+    int32           sig;
+{
+    if (sig != 2)
+       printf("\n\n Signal handler error  (%d)\n\n", sig);
+    ctrl_c = 1;
+}
+
+init_signals()
+{
+    typedef void    (*PFI) ();
+    static PFI      int_tab[2];
+
+    int_tab[0] = signal(SIGTERM, int_handler);
+    int_tab[1] = signal(SIGINT, int_handler);
+}
+
+
+extern struct disassemble_info dinfo;
+
+struct estate   ebase;
+struct evcell   evbuf[EVENT_MAX];
+struct irqcell  irqarr[16];
+int32           irqpend, ext_irl = 0;
+
+disp_fpu(sregs)
+    struct pstate  *sregs;
+{
+
+    int           i, j;
+    float      t;
+
+    printf("\n fsr: %08X\n\n", sregs->fsr);
+
+#ifdef HOST_LITTLE_ENDIAN_FLOAT
+    for (i = 0; i < 32; i++) {
+       sregs->fdp[i ^ 1] = sregs->fs[i];
+    }
+#endif
+
+    for (i = 0; i < 32; i++) {
+       t = sregs->fs[i];
+       printf(" f%02d  %08x  %14e  ", i, sregs->fsi[i], sregs->fs[i]);
+       if (!(i & 1))
+           printf("%14e\n", sregs->fd[i >> 1]);
+       else
+           printf("\n");
+    }
+    printf("\n");
+    return (OK);
+}
+
+disp_regs(sregs,cwp)
+    struct pstate  *sregs;
+    int cwp;
+{
+
+    int           i;
+
+    cwp = ((cwp & 0x7) << 4);
+    printf("\n\t  INS       LOCALS      OUTS     GLOBALS\n");
+    for (i = 0; i < 8; i++) {
+       printf("   %d:  %08X   %08X   %08X   %08X\n", i,
+              sregs->r[(cwp + i + 24) & 0x7f],
+           sregs->r[(cwp + i + 16) & 0x7f], sregs->r[(cwp + i + 8) & 0x7f],
+              sregs->g[i]);
+    }
+}
+
+disp_ctrl(sregs)
+    struct pstate  *sregs;
+{
+
+    uint32           i;
+
+    printf("\n psr: %08X   wim: %08X   tbr: %08X   y: %08X\n",
+          sregs->psr, sregs->wim, sregs->tbr, sregs->y);
+    sis_memory_read(sregs->pc, &i, 4);
+    printf("\n  pc: %08X = %08X    ", sregs->pc, i);
+    print_insn_sparc(sregs->pc, &dinfo);
+    sis_memory_read(sregs->npc, &i, 4);
+    printf("\n npc: %08X = %08X    ", sregs->npc, i);
+    print_insn_sparc(sregs->npc, &dinfo);
+    if (sregs->err_mode)
+       printf("\n IU in error mode");
+    printf("\n\n");
+}
+
+disp_mem(addr, len)
+    uint32          addr;
+    uint32          len;
+{
+
+    int32           i, data, ws;
+    int32           mem[4], j;
+    char           *p;
+
+    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, 4);
+           printf("%08x  ", data);
+           mem[j] = data;
+       }
+       printf("  ");
+       p = (char *) mem;
+       for (j = 0; j < 16; j++) {
+           if (isprint(p[j]))
+               putchar(p[j]);
+           else
+               putchar('.');
+       }
+    }
+    printf("\n\n");
+}
+dis_mem(addr, len, info)
+    uint32          addr;
+    uint32          len;
+    struct disassemble_info *info;
+{
+    int32           i, data, ws;
+
+    for (i = addr & -3; i < ((addr & -3) + (len << 2)); i += 4) {
+       sis_memory_read(i, &data, 4);
+       printf(" %08x  %08x  ", i, data);
+       print_insn_sparc(i, info);
+       printf("\n");
+    }
+    return (OK);
+}
+
+int
+buffer_read_memory(addr, buffer, size, info)
+    bfd_vma         addr;
+    bfd_byte       *buffer;
+    int32           size;
+    struct disassemble_info *info;
+{
+    if (size == sis_memory_read(addr, buffer, size))
+       return (0);
+    else
+       return (1);
+}
+
+void
+perror_memory(status, addr, info)
+    int32           status;
+    bfd_vma         addr;
+    struct disassemble_info *info;
+{
+
+    printf("Could not read address 0x%08x\n", addr);
+}
+
+void
+generic_print_address(addr, info)
+    bfd_vma         addr;
+    struct disassemble_info *info;
+{
+
+    printf("0x%x", addr);
+}
+
+/* Add event to event queue */
+
+event(cfunc, arg, delta)
+    void            (*cfunc) ();
+    int32           arg;
+    uint32          delta;
+{
+    struct evcell  *ev1, *evins;
+
+    if (ebase.freeq == NULL) {
+       printf("Error, too many events in event queue\n");
+       return (0);
+    }
+    ev1 = &ebase.eq;
+    delta += ebase.simtime;
+    while ((ev1->nxt != NULL) && (ev1->nxt->time <= delta)) {
+       ev1 = ev1->nxt;
+    }
+    if (ev1->nxt == NULL) {
+       ev1->nxt = ebase.freeq;
+       ebase.freeq = ebase.freeq->nxt;
+       ev1->nxt->nxt = NULL;
+    } else {
+       evins = ebase.freeq;
+       ebase.freeq = ebase.freeq->nxt;
+       evins->nxt = ev1->nxt;
+       ev1->nxt = evins;
+    }
+    ev1->nxt->time = delta;
+    ev1->nxt->cfunc = cfunc;
+    ev1->nxt->arg = arg;
+}
+
+stop_event()
+{
+}
+
+init_event()
+{
+    int32           i;
+
+    ebase.eq.nxt = NULL;
+    ebase.freeq = evbuf;
+    for (i = 0; i < EVENT_MAX; i++) {
+       evbuf[i].nxt = &evbuf[i + 1];
+    }
+    evbuf[EVENT_MAX - 1].nxt = NULL;
+}
+
+set_int(level, callback, arg)
+    int32           level;
+    void            (*callback) ();
+    int32           arg;
+{
+    irqarr[level & 0x0f].callback = callback;
+    irqarr[level & 0x0f].arg = arg;
+    irqpend |= (1 << level);
+    if (level > ext_irl)
+       ext_irl = level;
+
+}
+
+clear_int(level)
+    int32           level;
+{
+    int32           tmpirq = irqpend;
+
+    irqpend &= ~(1 << level);
+    ext_irl = 0;
+    if (irqpend) {
+       tmpirq >>= 1;
+       while (tmpirq) {
+           ext_irl++;
+           tmpirq >>= 1;
+       }
+    }
+}
+
+/* Advance simulator time */
+
+advance_time(sregs)
+    struct pstate  *sregs;
+{
+
+    struct evcell  *evrem;
+    void            (*cfunc) ();
+    uint32          arg, endtime, ws;
+
+    ws = sregs->icnt + sregs->hold + sregs->fhold;
+
+#ifdef STAT
+    sregs->fholdt += sregs->fhold;
+    sregs->holdt += sregs->hold;
+    sregs->icntt += sregs->icnt;
+#endif
+
+    endtime = ebase.simtime += ws;
+    while ((ebase.eq.nxt != NULL) && (ebase.eq.nxt->time <= (endtime))) {
+       ebase.simtime = ebase.eq.nxt->time;
+       cfunc = ebase.eq.nxt->cfunc;
+       arg = ebase.eq.nxt->arg;
+       evrem = ebase.eq.nxt;
+       ebase.eq.nxt = ebase.eq.nxt->nxt;
+       evrem->nxt = ebase.freeq;
+       ebase.freeq = evrem;
+       cfunc(arg);
+    }
+    ebase.simtime = endtime;
+
+}
+
+/* Advance time until an external interrupt is seen */
+
+int
+wait_for_irq()
+{
+    struct evcell  *evrem;
+    void            (*cfunc) ();
+    int32           arg, endtime;
+
+    if (ebase.eq.nxt == NULL)
+       printf("Warning: event queue empty - power-down mode not entered\n");
+    endtime = ebase.simtime;
+    while (!ext_irl && (ebase.eq.nxt != NULL)) {
+       ebase.simtime = ebase.eq.nxt->time;
+       cfunc = ebase.eq.nxt->cfunc;
+       arg = ebase.eq.nxt->arg;
+       evrem = ebase.eq.nxt;
+       ebase.eq.nxt = ebase.eq.nxt->nxt;
+       evrem->nxt = ebase.freeq;
+       ebase.freeq = evrem;
+       cfunc(arg);
+       if (ctrl_c) {
+           printf("\bwarning: power-down mode interrupted\n");
+           break;
+       }
+    }
+    sregs.pwdtime += ebase.simtime - endtime;
+    return (ebase.simtime - endtime);
+}
+
+int
+check_bpt(sregs)
+    struct pstate  *sregs;
+{
+    int32           i;
+
+    if ((sregs->bphit) || (sregs->annul))
+       return (0);
+    for (i = 0; i < sregs->bptnum; i++) {
+       if (sregs->pc == sregs->bpts[i])
+           return (BPT_HIT);
+    }
+    return (0);
+}
+
+reset_all()
+{
+    init_event();              /* Clear event queue */
+    init_regs(&sregs);
+    reset();
+}
+
+sys_reset()
+{
+    reset_all();
+    sregs.trap = 256;          /* Force fake reset trap */
+}
+
+#include "ansidecl.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "libiberty.h"
+#include "bfd.h"
+
+#define min(A, B) (((A) < (B)) ? (A) : (B))
+#define LOAD_ADDRESS 0
+
+int
+bfd_load(fname)
+    char           *fname;
+{
+    int             cc, c;
+    unsigned char   buf[10];
+    asection       *section;
+    bfd            *pbfd;
+    unsigned long   entry;
+
+    pbfd = bfd_openr(fname, 0);
+
+    if (pbfd == NULL) {
+       printf("open of %s failed\n", fname);
+       return (0);
+    }
+    if (!bfd_check_format(pbfd, bfd_object)) {
+       printf("file %s  doesn't seem to be an object file\n", fname);
+       return (0);
+    }
+    printf("loading %s:", fname);
+    for (section = pbfd->sections; section; section = section->next) {
+       if (bfd_get_section_flags(pbfd, section) & SEC_ALLOC) {
+           bfd_vma         section_address;
+           unsigned long   section_size;
+           const char     *section_name;
+
+           section_name = bfd_get_section_name(pbfd, section);
+
+           section_address = bfd_get_section_vma(pbfd, section);
+           /*
+            * Adjust sections from a.out files, since they don't carry their
+            * addresses with.
+            */
+           if (bfd_get_flavour(pbfd) == bfd_target_aout_flavour)
+               section_address += bfd_get_start_address (pbfd);
+           section_size = bfd_section_size(pbfd, section);
+
+           printf("\nsection %s at 0x%08lx (%ld bytes)",
+                  section_name, section_address, section_size);
+
+           /* Text, data or lit */
+           if (bfd_get_section_flags(pbfd, section) & SEC_LOAD) {
+               file_ptr        fptr;
+
+               fptr = 0;
+
+               while (section_size > 0) {
+                   char            buffer[1024];
+                   int             count;
+
+                   count = min(section_size, 1024);
+
+                   bfd_get_section_contents(pbfd, section, buffer, fptr, count);
+
+                   sis_memory_write(section_address, buffer, count);
+
+                   section_address += count;
+                   fptr += count;
+                   section_size -= count;
+               }
+           } else              /* BSS */
+               printf("(not loaded)");
+       }
+    }
+    printf("\n");
+
+    /*
+     * entry = bfd_get_start_address (pbfd);
+     * 
+     * printf ("[Starting %s at 0x%lx]\n", fname, entry);
+     */
+
+    return (1);
+}
+
+void
+sim_set_callbacks (ptr)
+struct host_callback_struct *ptr;
+{
+
+}
+
diff --git a/sim/erc32/help.c b/sim/erc32/help.c
new file mode 100644 (file)
index 0000000..8f57d8e
--- /dev/null
@@ -0,0 +1,30 @@
+usage()
+{
+
+    printf("usage: sis [-uart1 uart_device1] [-uart2 uart_device2]\n");
+    printf("[-nfp] [-freq frequency] [-c batch_file] [files]\n");
+}
+
+gen_help()
+{
+
+  printf("\n batch <file>          execute a batch file of SIS commands\n");
+    printf(" +bp <addr>            add a breakpoint at <addr>\n");
+    printf(" -bp <num>             delete breakpoint <num>\n");
+    printf(" bp                    print all breakpoints\n");
+    printf(" cont [icnt]           continue execution for [icnt] instructions\n");
+    printf(" dis [addr] [count]    disassemble [count] instructions at address [addr]\n");
+    printf(" echo <string>         print <string> to the simulator window\n");
+    printf(" float                 print the FPU registers\n");
+    printf(" go <addr> [icnt]      start execution at <addr> for [icnt] instructions\n");
+    printf(" hist [trace_length]   enable/show trace history\n");
+    printf(" load  <file_name>     load a file into simulator memory\n");
+    printf(" mem [addr] [count]    display memory at [addr] for [count] bytes\n");
+    printf(" quit                  exit the simulator\n");
+    printf(" perf [reset]          show/reset performance statistics\n");
+    printf(" reg [w<0-7>]          show integer registers (or windows, eg 're w2')\n");
+    printf(" run [inst_count]      reset and start execution for [icnt] instruction\n");
+    printf(" step                  single step\n");
+    printf(" tra [inst_count]      trace [inst_count] instructions\n");
+    printf("\n type Ctrl-C to interrupt execution\n\n");
+}
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
new file mode 100644 (file)
index 0000000..e81fbf3
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * This file is part of SIS.
+ * 
+ * SIS, SPARC instruction simulator V1.6 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 2 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, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ */
+
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include "sis.h"
+#include "bfd.h"
+#include <dis-asm.h>
+
+#ifndef fprintf
+extern          fprintf();
+#endif
+
+#define        VAL(x)  strtol(x,(char *)NULL,0)
+
+extern char   **buildargv(char *input);
+
+extern struct disassemble_info dinfo;
+extern struct pstate sregs;
+extern struct estate ebase;
+
+extern int      ctrl_c;
+extern int      nfp;
+extern int      sis_verbose;
+extern char    *sis_version;
+extern struct estate ebase;
+extern struct evcell evbuf[];
+extern struct irqcell irqarr[];
+extern int      irqpend, ext_irl;
+extern char    uart_dev1[], uart_dev2[];
+
+int             sis_gdb_break = 1;
+
+#ifdef IUREV0
+extern int      iurev0;
+#endif
+
+#ifdef MECREV0
+extern int      mecrev0;
+#endif
+
+run_sim(sregs, go, icount, dis)
+    struct pstate  *sregs;
+    int             go;
+    unsigned int    icount;
+    int             dis;
+{
+    int             mexc, ws;
+
+    if (sis_verbose)
+       printf_filtered("resuming at %x\n", sregs->pc);
+    sregs->starttime = time(NULL);
+    while ((!sregs->err_mode & (go || (icount > 0))) &&
+          ((sregs->bptnum == 0) || !(sregs->bphit = check_bpt(sregs)))) {
+
+       sregs->fhold = 0;
+       sregs->hold = 0;
+       sregs->icnt = 0;
+
+       check_interrupts(sregs);
+       if (sregs->trap) {
+           sregs->err_mode = execute_trap(sregs);
+       } else {
+           if (sregs->psr & 0x080)
+               sregs->asi = 8;
+           else
+               sregs->asi = 9;
+#ifdef IUREV0
+           if (iurev0 && sregs->rett_err) {
+               sregs->asi &= ~0x1;
+               sregs->asi |= ((sregs->psr & 0x040) >> 6);
+           }
+#endif
+
+           mexc = memory_read(sregs->asi, sregs->pc, &sregs->inst, &sregs->hold);
+           if (sregs->annul) {
+               sregs->annul = 0;
+               sregs->icnt = 1;
+               sregs->pc = sregs->npc;
+               sregs->npc = sregs->npc + 4;
+           } else {
+               if (mexc) {
+                   sregs->trap = I_ACC_EXC;
+               } else {
+                   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) {
+                       printf(" %8d ", ebase.simtime);
+                       dis_mem(sregs->pc, 1, &dinfo);
+                   }
+                   if ((sis_gdb_break) && (sregs->inst == 0x91d02001)) {
+                       if (sis_verbose)
+                           printf_filtered("SW BP hit at %x\n", sregs->pc);
+                       return (BPT_HIT);
+                   } else
+                       dispatch_instruction(sregs);
+               }
+               icount--;
+           }
+           if (sregs->trap) {
+               sregs->err_mode = execute_trap(sregs);
+           }
+       }
+       advance_time(sregs);
+       if (ctrl_c) {
+           go = icount = 0;
+       }
+    }
+    sregs->tottime += time(NULL) - sregs->starttime;
+    if (sregs->err_mode)
+       error_mode(sregs->pc);
+    if (sregs->err_mode)
+       return (ERROR);
+    if (sregs->bphit) {
+       if (sis_verbose)
+           printf_filtered("HW BP hit at %x\n", sregs->pc);
+       return (BPT_HIT);
+    }
+    if (ctrl_c) {
+       ctrl_c = 0;
+       return (CTRL_C);
+    }
+    return (TIME_OUT);
+}
+
+
+void
+sim_open(char *args)
+{
+
+    int             argc = 0;
+    char          **argv;
+    int             cont = 1;
+    int             stat = 0;
+    int             grdl = 0;
+    int             freq = 15;
+
+    printf_filtered("\n SIS - SPARC instruction simulator %s\n", sis_version);
+    printf_filtered(" Bug-reports to Jiri Gaisler ESA/ESTEC (jgais@wd.estec.esa.nl)\n");
+    argv = buildargv(args);
+    if (argv != NULL)
+       while (argv[argc])
+           argc++;
+    while (stat < argc) {
+       if (argv[stat][0] == '-') {
+           if (strcmp(argv[stat], "-v") == 0) {
+               sis_verbose = 1;
+           }
+#ifdef IUREV0
+           if (strcmp(argv[stat], "-iurev0") == 0) {
+               iurev0 = 1;
+               printf_filtered(" simulating IU rev.0 jmpl/restore bug\n");
+           }
+#endif
+#ifdef MECREV0
+           if (strcmp(argv[stat], "-mecrev0") == 0) {
+               mecrev0 = 1;
+               printf_filtered(" simulating MEC rev.0 timer and uart interrupt bug\n");
+           }
+#endif
+           if (strcmp(argv[stat], "-nfp") == 0) {
+               printf_filtered("no FPU\n");
+               nfp = 1;
+           }
+            if (strcmp(argv[stat], "-uart1") == 0) {
+                if ((stat + 1) < argc)
+                    strcpy(uart_dev1, argv[++stat]);
+           }
+            if (strcmp(argv[stat], "-uart2") == 0) {
+                if ((stat + 1) < argc)
+                    strcpy(uart_dev2, argv[++stat]);
+           }
+           if (strcmp(argv[stat], "-nogdb") == 0) {
+               printf_filtered("disabling GDB trap handling for breakpoints\n");
+               sis_gdb_break = 0;
+           }
+           if (strcmp(argv[stat], "-freq") == 0)
+               if ((stat + 1) < argc) {
+                   freq = VAL(argv[++stat]);
+                   printf_filtered(" ERC32 freq %d Mhz\n", freq);
+               }
+       } else
+           bfd_load(argv[stat]);
+       stat++;
+    }
+    freeargv(argv);
+    sregs.freq = freq;
+
+    INIT_DISASSEMBLE_INFO(dinfo, stdout, fprintf);
+    init_signals();
+    reset_all();
+    ebase.simtime = 0;
+    init_sim();
+    init_bpt(&sregs);
+    reset_stat(&sregs);
+}
+
+void
+sim_close(int quitting)
+{
+
+    exit_sim();
+
+};
+
+int
+sim_load(char *prog, int from_tty)
+{
+    bfd_load(*prog);
+    return (0);
+}
+
+void
+sim_create_inferior(int start_address, char **argv, char **env)
+{
+    ebase.simtime = 0;
+    reset_all();
+    reset_stat(&sregs);
+    sregs.pc = start_address & ~3;
+    sregs.npc = sregs.pc + 4;
+
+}
+
+void
+sim_store_register(regno, value)
+    int             regno;
+    unsigned char  *value;
+{
+    /* FIXME: Review the computation of regval.  */
+    int             regval = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
+    set_regi(&sregs, regno, regval);
+}
+
+
+void
+sim_fetch_register(regno, buf)
+    int             regno;
+    unsigned char  *buf;
+{
+    get_regi(&sregs, regno, buf);
+}
+
+int
+sim_write(mem, buf, length)
+    int             mem;
+    unsigned char  *buf;
+    int             length;
+{
+    return (sis_memory_write(mem, buf, length));
+}
+
+int
+sim_read(int mem, unsigned char *buf, int length)
+{
+    return (sis_memory_read(mem, buf, length));
+}
+
+void
+sim_info(int verbose)
+{
+    show_stat(&sregs);
+
+
+}
+
+int             simstat = OK;
+
+enum sim_stop {
+    sim_exited, sim_stopped, sim_signalled
+};
+
+void
+sim_stop_reason(enum sim_stop * reason, int *sigrc)
+{
+
+    switch (simstat) {
+       case CTRL_C:
+       *reason = sim_stopped;
+       *sigrc = SIGINT;
+       break;
+    case OK:
+    case TIME_OUT:
+    case BPT_HIT:
+       *reason = sim_stopped;
+       *sigrc = SIGTRAP;
+       break;
+    case ERROR:
+       *sigrc = 0;
+       *reason = sim_exited;
+    }
+    ctrl_c = 0;
+    simstat = OK;
+}
+
+
+void
+sim_resume(int step, int siggnal)
+{
+    simstat = run_sim(&sregs, 1, 0, 0);
+}
+
+void
+sim_kill(void)
+{
+};
+
+
+
+void
+sim_do_command(cmd)
+    char           *cmd;
+{
+    exec_cmd(&sregs, cmd);
+}
+
+
+
+int
+sim_insert_breakpoint(int addr)
+{
+    if (sregs.bptnum < BPT_MAX) {
+       sregs.bpts[sregs.bptnum] = addr & ~0x3;
+       sregs.bptnum++;
+       if (sis_verbose)
+           printf_filtered("inserted HW BP at %x\n", addr);
+       return 0;
+    } else
+       return 1;
+}
+
+int
+sim_remove_breakpoint(int addr)
+{
+    int             i = 0;
+
+    while ((i < sregs.bptnum) && (sregs.bpts[i] != addr))
+       i++;
+    if (addr == sregs.bpts[i]) {
+       for (; i < sregs.bptnum - 1; i++)
+           sregs.bpts[i] = sregs.bpts[i + 1];
+       sregs.bptnum -= 1;
+       if (sis_verbose)
+           printf_filtered("removed HW BP at %x\n", addr);
+       return 0;
+    }
+    return 1;
+}
diff --git a/sim/erc32/run.c b/sim/erc32/run.c
new file mode 100644 (file)
index 0000000..a571c4a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * run front end support for ERC32SIM Copyright (C) 1987, 1992 Free Software
+ * Foundation, Inc.
+ * 
+ * This file is part of ERC32SIM
+ * 
+ * ERC32SIM 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 2, or (at your option) any later version.
+ * 
+ * ERC32SIM 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
+ * ERC32SIM; see the file COPYING.  If not, write to the Free Software
+ * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <varargs.h>
+#include <stdio.h>
+#include "bfd.h"
+
+main(ac, av)
+    int             ac;
+    char          **av;
+{
+    bfd            *abfd;
+    bfd_vma         start_address;
+    asection       *s;
+    int             i;
+    int             verbose = 0;
+    int             trace = 0;
+    char           *name = "";
+    for (i = 1; i < ac; i++) {
+       if (strcmp(av[i], "-v") == 0) {
+           verbose = 1;
+       } else if (strcmp(av[i], "-t") == 0) {
+           trace = 1;
+       } else {
+           name = av[i];
+       }
+    }
+    if (verbose) {
+       printf("run %s\n", name);
+    }
+    sim_open(0);
+    abfd = bfd_openr(name, "a.out-sunos-big");
+
+    if (abfd) {
+
+       if (bfd_check_format(abfd, bfd_object)) {
+           for (s = abfd->sections; s; s = s->next) {
+               char           *buffer = malloc(bfd_section_size(abfd, s));
+               bfd_get_section_contents(abfd, s, buffer, 0, bfd_section_size(abfd, s));
+               sim_write(s->vma, buffer, bfd_section_size(abfd, s));
+           }
+
+           start_address = bfd_get_start_address(abfd);
+           sim_create_inferior(start_address, NULL, NULL);
+           if (trace) {
+               int             done = 0;
+               while (!done) {
+                   /*
+                    * done = sim_trace();
+                    */
+               }
+           } else {
+               sim_resume(0, 0);
+           }
+           if (verbose) {
+               sim_info(0);
+           }
+           return 0;
+       }
+    }
+    return 1;
+}
+
+void
+printf_filtered(va_alist)
+va_dcl
+{
+    char           *msg;
+    va_list         args;
+
+    va_start(args);
+    msg = va_arg(args, char *);
+    vfprintf(stdout, msg, args);
+    va_end(args);
+}
diff --git a/sim/erc32/startsim b/sim/erc32/startsim
new file mode 100644 (file)
index 0000000..1b9b41c
--- /dev/null
@@ -0,0 +1,4 @@
+#
+xterm -e sis $* &
+xterm -e tip /dev/ttypc &
+