New sparc simulator from the ESA.

This commit is contained in:
Rob Savoye
1996-05-20 02:46:07 +00:00
parent 41756e56ee
commit f4d2ff34be
20 changed files with 4802 additions and 0 deletions

109
sim/erc32/ChangeLog Normal file
View File

@@ -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)

204
sim/erc32/Makefile.in Normal file
View File

@@ -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

108
sim/erc32/NEWS Normal file
View File

@@ -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.

130
sim/erc32/README.erc32 Normal file
View File

@@ -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

67
sim/erc32/README.gdb Normal file
View File

@@ -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)

356
sim/erc32/README.sis Normal file
View File

@@ -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.

18
sim/erc32/configure.in Normal file
View File

@@ -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)

23
sim/erc32/end.c Normal file
View File

@@ -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);
}

View File

@@ -0,0 +1,4 @@
/* Dummy __main for gccx compiled programs */
__main()
{}

View File

@@ -0,0 +1,8 @@
int clock()
{
volatile int *t_addr;
t_addr = (volatile int * ) 0x01F80080; /* Real-time clock address */
return(*t_addr);
}

7
sim/erc32/examples/gccx Executable file
View File

@@ -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

View File

@@ -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");
}

449
sim/erc32/examples/srt0.S Executable file
View File

@@ -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

1597
sim/erc32/exec.c Normal file

File diff suppressed because it is too large Load Diff

169
sim/erc32/float.c Normal file
View File

@@ -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

968
sim/erc32/func.c Normal file
View File

@@ -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;
{
}

30
sim/erc32/help.c Normal file
View File

@@ -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");
}

372
sim/erc32/interf.c Normal file
View File

@@ -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;
}

92
sim/erc32/run.c Normal file
View File

@@ -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);
}

4
sim/erc32/startsim Normal file
View File

@@ -0,0 +1,4 @@
#
xterm -e sis $* &
xterm -e tip /dev/ttypc &