forked from Imagelibrary/binutils-gdb
New sparc simulator from the ESA.
This commit is contained in:
109
sim/erc32/ChangeLog
Normal file
109
sim/erc32/ChangeLog
Normal 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
204
sim/erc32/Makefile.in
Normal 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
108
sim/erc32/NEWS
Normal 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
130
sim/erc32/README.erc32
Normal 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
67
sim/erc32/README.gdb
Normal 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
356
sim/erc32/README.sis
Normal 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
18
sim/erc32/configure.in
Normal 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
23
sim/erc32/end.c
Normal 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);
|
||||
}
|
||||
4
sim/erc32/examples/__main.c
Normal file
4
sim/erc32/examples/__main.c
Normal file
@@ -0,0 +1,4 @@
|
||||
/* Dummy __main for gccx compiled programs */
|
||||
|
||||
__main()
|
||||
{}
|
||||
8
sim/erc32/examples/clock.c
Normal file
8
sim/erc32/examples/clock.c
Normal 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
7
sim/erc32/examples/gccx
Executable 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
|
||||
87
sim/erc32/examples/hello.c
Normal file
87
sim/erc32/examples/hello.c
Normal 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
449
sim/erc32/examples/srt0.S
Executable 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
1597
sim/erc32/exec.c
Normal file
File diff suppressed because it is too large
Load Diff
169
sim/erc32/float.c
Normal file
169
sim/erc32/float.c
Normal 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
968
sim/erc32/func.c
Normal 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(®[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
30
sim/erc32/help.c
Normal 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
372
sim/erc32/interf.c
Normal 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
92
sim/erc32/run.c
Normal 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
4
sim/erc32/startsim
Normal file
@@ -0,0 +1,4 @@
|
||||
#
|
||||
xterm -e sis $* &
|
||||
xterm -e tip /dev/ttypc &
|
||||
|
||||
Reference in New Issue
Block a user