aboutsummaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
authorRob Savoye <rob@cygnus>1996-05-20 02:46:07 +0000
committerRob Savoye <rob@cygnus>1996-05-20 02:46:07 +0000
commitf4d2ff34bef1789eef9bed93572993ee023270e2 (patch)
tree8627672c208e2f884decca146c9aefdcfd5bbb99 /sim
parent41756e56ee00510ee7044119d0b033ea536dae5b (diff)
downloadgdb-f4d2ff34bef1789eef9bed93572993ee023270e2.zip
gdb-f4d2ff34bef1789eef9bed93572993ee023270e2.tar.gz
gdb-f4d2ff34bef1789eef9bed93572993ee023270e2.tar.bz2
New sparc simulator from the ESA.
Diffstat (limited to 'sim')
-rw-r--r--sim/erc32/ChangeLog109
-rw-r--r--sim/erc32/Makefile.in204
-rw-r--r--sim/erc32/NEWS108
-rw-r--r--sim/erc32/README.erc32130
-rw-r--r--sim/erc32/README.gdb67
-rw-r--r--sim/erc32/README.sis356
-rw-r--r--sim/erc32/configure.in18
-rw-r--r--sim/erc32/end.c23
-rw-r--r--sim/erc32/examples/__main.c4
-rw-r--r--sim/erc32/examples/clock.c8
-rwxr-xr-xsim/erc32/examples/gccx7
-rw-r--r--sim/erc32/examples/hello.c87
-rwxr-xr-xsim/erc32/examples/srt0.S449
-rw-r--r--sim/erc32/exec.c1597
-rw-r--r--sim/erc32/float.c169
-rw-r--r--sim/erc32/func.c968
-rw-r--r--sim/erc32/help.c30
-rw-r--r--sim/erc32/interf.c372
-rw-r--r--sim/erc32/run.c92
-rw-r--r--sim/erc32/startsim4
20 files changed, 4802 insertions, 0 deletions
diff --git a/sim/erc32/ChangeLog b/sim/erc32/ChangeLog
new file mode 100644
index 0000000..ed56438
--- /dev/null
+++ b/sim/erc32/ChangeLog
@@ -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
index 0000000..5ee6db3
--- /dev/null
+++ b/sim/erc32/Makefile.in
@@ -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
index 0000000..dd24b7b
--- /dev/null
+++ b/sim/erc32/NEWS
@@ -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
index 0000000..f413599
--- /dev/null
+++ b/sim/erc32/README.erc32
@@ -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
index 0000000..619fcb3
--- /dev/null
+++ b/sim/erc32/README.gdb
@@ -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
index 0000000..b119f03
--- /dev/null
+++ b/sim/erc32/README.sis
@@ -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
index 0000000..0eb7b73
--- /dev/null
+++ b/sim/erc32/configure.in
@@ -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
index 0000000..5cd454a
--- /dev/null
+++ b/sim/erc32/end.c
@@ -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
index 0000000..73c52cd
--- /dev/null
+++ b/sim/erc32/examples/__main.c
@@ -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
index 0000000..ec23037
--- /dev/null
+++ b/sim/erc32/examples/clock.c
@@ -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
index 0000000..5fec6ec
--- /dev/null
+++ b/sim/erc32/examples/gccx
@@ -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
index 0000000..02903cf
--- /dev/null
+++ b/sim/erc32/examples/hello.c
@@ -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
index 0000000..1e68951
--- /dev/null
+++ b/sim/erc32/examples/srt0.S
@@ -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
index 0000000..8690cea
--- /dev/null
+++ b/sim/erc32/exec.c
@@ -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
index 0000000..30ffffa
--- /dev/null
+++ b/sim/erc32/float.c
@@ -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
index 0000000..2cd9bf2
--- /dev/null
+++ b/sim/erc32/func.c
@@ -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
index 0000000..8f57d8e
--- /dev/null
+++ b/sim/erc32/help.c
@@ -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
index 0000000..e81fbf3
--- /dev/null
+++ b/sim/erc32/interf.c
@@ -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
index 0000000..a571c4a
--- /dev/null
+++ b/sim/erc32/run.c
@@ -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
index 0000000..1b9b41c
--- /dev/null
+++ b/sim/erc32/startsim
@@ -0,0 +1,4 @@
+#
+xterm -e sis $* &
+xterm -e tip /dev/ttypc &
+