New changes from Andrew

This commit is contained in:
Michael Meissner 1995-10-31 18:29:37 +00:00
parent 5666490bee
commit 5b4d72dd73
26 changed files with 2945 additions and 4959 deletions

View File

@ -31,6 +31,7 @@ README.psim
basics.h
bits.c
bits.h
build-psim
config.in
configure
configure.in
@ -45,22 +46,38 @@ device_tree.c
device_tree.h
devices.c
devices.h
dgen.c
double.c
dp-bit.c
emul_generic.c
emul_generic.h
emul_netbsd.c
emul_netbsd.h
events.c
events.h
gen.c
idecode_branch.h
idecode_expression.h
idecode_fields.h
igen.c
inline.c
inline.h
interrupts.c
interrupts.h
lf.c
lf.h
main.c
misc.c
misc.h
mon.c
mon.h
os_emul.c
os_emul.h
ppc-cache-rules
ppc-endian.c
ppc-endian.h
ppc-instructions
ppc-opcode-complex
ppc-opcode-simple
ppc-spr-table
ppc.mt
psim.c
@ -69,9 +86,12 @@ registers.c
registers.h
sim_callbacks.h
sim_calls.c
spa-reporter.c
spa-system-calls.c
spa-system-calls.h
std-config.h
system.c
system.h
table.c
table.h
vm.c
vm.h
vm_n.h

View File

@ -1,3 +1,197 @@
Fri Oct 27 19:26:27 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* bits.h (ROTL32, ROTL64): Were functions, made them macros, now
make them functions again. Appears 2.6.3 is confused by just a
macro.
Thu Oct 26 18:31:58 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* ppc-endian.c (SWAP_8): Fix 8 byte swap!
* psim.c (psim_create): Not correctly checking that runtime
configuration of things like ENDIAN, ENVIRONMENT and ALIGNMENT
matched the compiled in ones.
* debug.h (ITRACE), igen.c: Tidy up more tracing flags -
trace_semantics is now different to trace_idecode, the former
checks the cache.
Tue Oct 24 21:54:13 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* ppc-instructions (mtsrin): Missing instruction
* ppc-instructions (mfsrin): Missing instruction
* ppc-instructions (eieio): Missing instruction
Tue Oct 24 20:55:29 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* build-psim: New shell script - see internals for usage,
simplifies the process of building custom simulators.
Mon Oct 23 23:48:59 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* std-config.h (SEMANTICS_INLINE): Tidy up notes on each of the
INLINE macros. Make SEMANTICS_INLINE == 1 if DEFAULT_INLINE == 2.
Don't use DEFAULT_INLINE to define REGISTERS_INLINE DEVICES_INLINE
DEVICE_TREE_INLINE or INTERRUPTS_INLINE as none of these are on
the instruction or data critical paths.
* FIXME: need to set up OS_EMUL_INLINE/EMUL_GENERIC_INLINE but
not on critical path.
* FIXME: devices.c/emul_netbsd.c would benefit (slightly) from
the inclusion of device_tree.c/emul_generic.c.
Mon Oct 23 00:31:50 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* os_emul.[hc], emul_generic.[hc], emul_netbsd.[hc]: replace
system.[hc]. Start of suport for multiple emulations and
emulation state (os_emul object).
* emul_generic.[hc]: Start of code to implement proper system call
tracing (from spy).
Sun Oct 22 21:33:51 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* cpu.h, cpu.c (cpu_init): New function, zero the registers before
the processor is started. Fixes problem of registers being
undefined when restarting from within gdb.
* cpu.h, cpu.c (cpu_flush_icache): New function, flushes the
instruction cache (if present). Fixes problem of cpu caching gdb
breakpoint instructions.
FIXME: PSIM sometimes aborts calling error(), it should instead
call sim_error() say which takes care of housekeeping such as
saving the CIA before calling error.
* NOTE: cpu_flush_cache() instead of cpu_synchronize_context() is
used when restarting a simulation because the latter has the
unwanted side effect (well I as a kernel hacker think it is) of
performing an isync when the instruction stream doesn't contain
one.
Sun Oct 22 19:27:48 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* mon.h (new), mon.c (new), std-config.h (WITH_MON): Performance
monitoring module. Counts both instructions issued and
load/stores.
* NOTE: mon does not contain to count instruction loads as this
information is already available from the mon_issue() hook.
* FIXME: mon doesn't have access to register usage information.
This is needed if the user wants to monitor things like register
stalls.
* igen.c (lf_print_c_semantic), vm_n.h: Add counting code.
* psim.h, psim.c (psim_create), cpu.h, cpu.c (cpu_create): Attach
a common monitor to each of the cpus. Delete
cpu_increment_number_of_insns() and cpu_get_number_of_insns()
replaced by copied code in mon.[hc].
Sun Oct 22 18:42:45 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* sim_calls.c, main.c, psim.c (psim_create): always create
`WITH_SMP' cpus. The actual number of CPU's active in a
simulation run is taken from the device node: /init/smp (an
integer). WITH_SMP changed to 2 (remember to put it back to 0).
Fri Oct 20 17:26:54 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* system.c: More system call emulation. If code appears NetBSD
specific, make conditional to being compiled on a NetBSD system
(sigh).
Wed Oct 18 23:02:20 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* Makefile.in, gen.c(delete), igen.c(new), dgen.c(new),
lf.[ch](new), table.[ch](new): Split into two generators - igen
that outputs the instruction tables and dgen that outputs the spr
tables. Add -f (filter out) flag to igen to filter out certain
instructions (ex 64 bit ones) from the created tables. Include
$(LIBIBERTY_LIB) in link options in case host lacks some libc
functions.
* NOTE: igen, since it was originally written for the
PowerPC/RS6000, things the MSB is 0 and the LSB is 63{31}.
* Makefile.in, std-config.h, ppc-cache-rules(new),
ppc-opcode-complex(new), ppc-opcode-simple(new): (for igen) Create
cache-rule and opcode-rule tables from macros found std-config.h.
Delete corresponding macro's from std-config.h.
* FIXME: under this new igen scheme, when playing around with igen
options, you'll find that depenencies don't work very well.
* igen.c (gen_itable_c, gen_itable_h), Makefile.in: code to output
an table of all the instructions. Code to output a type
enumerating all the instructin names.
* igen.c(lf_print_c_semantic): Move call to increment instruction
counter so that it occures _after_ the instruction has been fully
validated, was double counting illegal/invalid instructions. Add
conditional so only compiled in when WITH_PROFILE enabled (enabled
by default).
* igen.c, cpu.h, cpu.c(cpu_increment_number_of_insns): Include
itable.h, count individual instruction types not just total,
adjust reporting functions to output this.
* ppc-instructions (64 bit Load Doubleword with Update Indexed):
Had 32./ instead of 31./
* ppc-instructions (64 bit Store Double Word Conditional Indexed):
bitrot - updated to use newer CR register operators.
* ppc-instructions (64bit Floating Convert from Integer
Doubleword): Correct call to Round_Float().
Mon Oct 16 00:31:20 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* basics.h: #include "sim_callbacks.h" earlier so that its
prototypes are declared in all other header files.
* bits.h, bits.c, idecode_expression.h (ROTL32, ROTL64): Update
doc in bits.h, remove dead code in bits.c, move ROTL32/ROTL64 into
bits.h.
* FIXME: the bits.h/bits.c macro's should be replaced with
(inline) c functions.
* cpu.c(cpu_add_commas), device_tree.h, device_tree.c(scand_*):
Add size of buffer argument to functions writing a string into a
buffer. Check for buffer overflow.
Sun Oct 15 22:16:11 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* devices.h, devices.c, debug.h, debug.c: add macro's for tracing
of each device. Make parameter names consistent so macros work.
Use macro's in device functions.
* device_tree.c, devices.h, devices.c: include path to device in a
devices node when creating it.
* device_tree.c, debug.h, debug.c: Add tracing of `device-tree'.
* core.c: add tracing of core-device, adjust parameter names in
core functions to be consistent with those in devices*.
Sun Oct 15 20:33:20 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* debug.h, debug.c (trace_option): New function. Parses the trace
option, updating the trace array.
* debug.h, debug.c (trace_usage): New function. Outputs the list
of all possible trace options.
* sim_calls.c (sim_open), main.c (main): Use new trace_option() to
parse trace options specified with the simpler -t flag. Adjust
usage.
* FIXME: basic parsing of command line options is still duplicated
by main.c and sim_calls.c
Thu Oct 26 10:42:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* Makefile.in (clean): Delete *.i and *.out files.
@ -93,7 +287,7 @@ Thu Oct 12 11:35:53 1995 Michael Meissner <meissner@tiktok.cygnus.com>
({CORE,VM,CPU,EVENTS,REGISTERS,INTERRUPTS}_INLINE): Ditto.
({SPREG,IDECODE}_INLINE): Ditto.
Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@kremvax>
Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* ppc-instructions: Initial cut of floating point suport added.
Of note include - use of host IEEE floating point instructions,
@ -110,7 +304,7 @@ Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@kremvax>
* Makefile.in et.al (sorry): tweek to use new core, core_map and
core.h.
Wed Oct 11 12:10:26 1995 Andrew Cagney <cagney@kremvax>
Wed Oct 11 12:10:26 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* sim_calls.c, main.c: Add -g (trace_gdb) option, add tracing to
most of the other functions in sim_calls.c.
@ -121,7 +315,7 @@ Wed Oct 11 12:10:26 1995 Andrew Cagney <cagney@kremvax>
* vm.c, vm_n.h, Makefile.in: ditto
Tue Oct 10 15:42:59 1995 Andrew Cagney <cagney@kremvax>
Tue Oct 10 15:42:59 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* devices.h, devices.c, memory_map.h, memory_map.c: Changed
callback interface so that there is a read/write buffer but no
@ -133,12 +327,12 @@ Tue Oct 10 15:42:59 1995 Andrew Cagney <cagney@kremvax>
eliminate transfer_mode (raw or cooked) parameter from read/write
buffer.
Fri Oct 6 20:23:56 1995 Andrew Cagney <cagney@kremvax>
Fri Oct 6 20:23:56 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* ppc-instructions (fmul, fmuls): correct instruction format - had
FRB instead of FRC.
Wed Oct 4 17:31:12 1995 Andrew Cagney <cagney@kremvax>
Wed Oct 4 17:31:12 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* psim.c, device_tree.h, device_tree.c, devices.c (printd_*,
scand_*): new functions to parse/print fields in device names
@ -152,7 +346,7 @@ Wed Oct 4 17:31:12 1995 Andrew Cagney <cagney@kremvax>
variable number of arguments. This gives greater flexability and
greater chance of bugs.
Tue Oct 3 22:01:56 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Tue Oct 3 22:01:56 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* main.c (printf_filtered, error): Missing va_end() to close off
variable argument use.
@ -275,7 +469,7 @@ Fri Sep 8 09:51:03 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* basics.h (sysdep.h): Don't include it.
* Makefile.in (BASICS_H): Remove sysdep.h.
Wed Sep 6 13:25:42 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Wed Sep 6 13:25:42 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* core.c (core_add_data): First growth of bss was being put at
wrong address (0) instead of &end.
@ -283,7 +477,7 @@ Wed Sep 6 13:25:42 1995 Andrew Cagney - aka Noid <cagney@kremvax>
* core.c (core_add_stack, core_add_data): Was not handling case
where bss/stack is grown across the current end-of-{bss,stack}.
Wed Sep 6 00:46:10 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Wed Sep 6 00:46:10 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* system.c (system_call): Fix SYS_break - was aligning bss to a
page boundary instead of just an 8 byte one; On first call sbrk(0)
@ -329,7 +523,7 @@ Tue Aug 22 09:31:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* configure.in: Clone from other simulator targets.
* configure: Generate via autoconf from configure.in.
Sat Aug 19 09:05:32 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Sat Aug 19 09:05:32 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* ppc-instructions: fix srawi (was geting XER[CA] real wrong).
@ -340,14 +534,14 @@ Sat Aug 19 09:05:32 1995 Andrew Cagney - aka Noid <cagney@kremvax>
* main.c (main): really stupid. Wasn't exiting with correct status
Fri Aug 18 00:38:01 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Fri Aug 18 00:38:01 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* system.c (system_call): add system calls kill(2) and getpid(2).
* main.c (main): Check/return exit status when simulation
finishes.
Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@kremvax>
Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* device_tree.c (create_option_device_node): Alignment rules (at
least for the moment) now are for strict alignment only for LE OEA
@ -355,7 +549,7 @@ Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@kremvax>
* system.c (system_call) SYS_exit: Wasn't exiting with correct status.
Thu Aug 17 01:16:38 1995 Andrew Cagney - aka Noid <cagney@kremvax>
Thu Aug 17 01:16:38 1995 Andrew Cagney <cagney@cagney@highland.com.au>
* vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
forgot to return.

View File

@ -80,7 +80,11 @@ INCLUDES = -I. -I$(srcdir) $(LIB_INCLUDES) $(BFD_INCLUDES) $(GDB_INCLUDES)
CONFIG_FILE = std-config.h
# See inline.h for appropriate flags to set
INLINE_CFLAGS = -DDEFAULT_INLINE=2
INLINE_CFLAGS = # -g0 -DDEFAULT_INLINE=2
IGEN_FLAGS = -f 64 # -f 64 -e
IGEN_OPCODE_RULES = ppc-opcode-simple # ppc-opcode-complex
DGEN_FLAGS = # # -s
LIBIBERTY_LIB = ../../libiberty/libiberty.a
BFD_LIB = ../../bfd/libbfd.a
@ -128,7 +132,15 @@ CPU_H = \
events.h \
interrupts.h \
psim.h \
icache.h
icache.h \
itable.h \
mon.h
EMUL_GENERIC_H = \
$(CPU_H) \
$(IDECODE_H) \
emul_generic.h \
os_emul.h
INLINE = \
@ -139,35 +151,43 @@ BUILT_SRC = \
icache.h \
idecode.h idecode.c \
semantics.h semantics.c \
itable.h itable.c \
spreg.h spreg.c \
config.h \
ppc-config.h
ppc-config.h
LIB_SRC = \
psim.c \
bits.c \
ppc-endian.c \
debug.c \
ppc-endian.c \
vm.c \
core.c \
events.c \
system.c \
os_emul.c \
emul_generic.c \
emul_netbsd.c \
registers.c \
cpu.c \
interrupts.c \
devices.c \
device_tree.c
device_tree.c \
mon.c
MAIN_SRC = \
main.c \
sim_calls.c
# NOTE: semantics, idecode and psim put last so smaller files are compiled
# first
LIB_OBJ = \
debug.o \
bits.o \
ppc-endian.o \
system.o \
os_emul.o \
emul_generic.o \
emul_netbsd.o \
registers.o \
vm.o \
core.o \
@ -177,6 +197,8 @@ LIB_OBJ = \
events.o \
devices.o \
device_tree.o \
itable.o \
mon.o \
semantics.o \
idecode.o \
psim.o
@ -192,7 +214,7 @@ run: psim
rm -f run
ln psim run
$(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
$(TARGETLIB): tmp-igen tmp-dgen $(LIB_OBJ) $(GDB_OBJ)
rm -f $(TARGETLIB)
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
$(RANLIB) $(TARGETLIB)
@ -201,27 +223,29 @@ $(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
# anything changes.
psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC)
bits.o: bits.c bits.h
bits.o: bits.c $(BASICS_H)
debug.o: debug.c $(BASICS_H)
ppc-endian.o: ppc-endian.c ppc-endian.h \
config.h ppc-config.h words.h sim_callbacks.h
system.o: system.c system.h $(CPU_H) $(IDECODE_H)
os_emul.o: os_emul.c $(EMUL_GENERIC_H)
emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
registers.o: registers.c $(REGISTERS_H) $(BASICS_H)
cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) system.h
interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h
idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
# double.o: double.c dp-bit.c
vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
device_tree.h core.h interrupts.h
device_tree.h core.h interrupts.h itable.h mon.h
core.o: core.c core.h $(BASICS_H) device_tree.h
@ -240,6 +264,9 @@ device_tree.o: device_tree.c device_tree.h devices.h $(BASICS_H)
semantics.o: semantics.c semantics.h $(CPU_H) $(IDECODE_H)
itable.o: itable.c itable.h
mon.o: $(CPU_H)
#
# Rules to create the built c source code files
@ -249,47 +276,63 @@ ppc-config.h: $(CONFIG_FILE)
cp $(srcdir)/$(CONFIG_FILE) ppc-config.h
tmp-gencode: gen ppc-instructions ppc-spr-table $(srcdir)/../../move-if-change
./gen -r $(srcdir)/ppc-spr-table \
-i $(srcdir)/ppc-instructions \
tmp-dgen: dgen ppc-spr-table $(srcdir)/../../move-if-change
./dgen $(DGEN_FLAGS) \
-r $(srcdir)/ppc-spr-table \
-n spreg.h -P tmp-spreg.h \
-n spreg.c -p tmp-spreg.c \
-n spreg.c -p tmp-spreg.c
$(srcdir)/../../move-if-change tmp-spreg.h spreg.h
$(srcdir)/../../move-if-change tmp-spreg.c spreg.c
touch tmp-dgen
tmp-igen: igen ppc-instructions $(IGEN_OPCODE_RULES) ppc-cache-rules $(srcdir)/../../move-if-change
./igen $(IGEN_FLAGS) \
-o $(srcdir)/$(IGEN_OPCODE_RULES) \
-k $(srcdir)/ppc-cache-rules \
-i $(srcdir)/ppc-instructions \
-n icache.h -C tmp-icache.h \
-n semantics.h -S tmp-semantics.h \
-n semantics.c -s tmp-semantics.c \
-n idecode.h -D tmp-idecode.h \
-n idecode.c -d tmp-idecode.c
-n idecode.c -d tmp-idecode.c \
-n itable.h -T tmp-itable.h \
-n itable.c -t tmp-itable.c
$(srcdir)/../../move-if-change tmp-icache.h icache.h
$(srcdir)/../../move-if-change tmp-idecode.h idecode.h
$(srcdir)/../../move-if-change tmp-idecode.c idecode.c
$(srcdir)/../../move-if-change tmp-semantics.h semantics.h
$(srcdir)/../../move-if-change tmp-semantics.c semantics.c
$(srcdir)/../../move-if-change tmp-spreg.h spreg.h
$(srcdir)/../../move-if-change tmp-spreg.c spreg.c
touch tmp-gencode
$(srcdir)/../../move-if-change tmp-itable.h itable.h
$(srcdir)/../../move-if-change tmp-itable.c itable.c
touch tmp-igen
# NOTE: Some versions of make don't handle files created as side-effects
# uncomment the below if that is the case.
#
# $(TARGETLIB): tmp-gencode
# icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c: tmp-gencode
# $(TARGETLIB): tmp-igen tmp-dgen
# itable.h itable.c icache.h idecode.h idecode.c semantics.h semantics.c: tmp-igen
# spreg.h spreg.c: tmp-dgen
gen.o: gen.c config.h ppc-config.h
$(CC_FOR_BUILD) -c $(CFLAGS) $(INLINE_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(srcdir)/gen.c
dgen: dgen.o table.o lf.o misc.o
$(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o dgen dgen.o table.o lf.o misc.o $(LIBIBERTY_LIB) $(LIBS)
gen: gen.o config.h ppc-config.h $(LIBIBERTY_LIB) $(LIBS)
$(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o gen gen.o $(LIBIBERTY_LIB) $(LIBS)
igen: igen.o table.o lf.o misc.o
$(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o igen igen.o table.o lf.o misc.o $(LIBIBERTY_LIB) $(LIBS)
#
table.o: misc.h lf.h table.h
lf.o: misc.h lf.h
dgen.o igen.o: misc.h lf.h table.h
misc.o: misc.h
# With out this #, make thinks that misc.o doesn't have a rule
tags etags: TAGS
TAGS: tmp-gencode config.h ppc-config.h
TAGS: tmp-igen tmp-dgen config.h ppc-config.h
etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
clean mostlyclean:
rm -f tmp-* *.[ioas] *.out core psim run gen config.log
rm -f icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c ppc-config.h
rm -f tmp-* *.[oas] core psim run igen dgen config.log
distclean maintainer-clean realclean: clean
rm -f TAGS $(BUILT_SRC) Makefile config.cache config.status config.h stamp-h

View File

@ -3,231 +3,250 @@
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
This directory contains the program PSIM that models the PowerPC
architecture. It can either be run stand alone (psim or run) or used
as part of GDB.
SOURCE:
PSIM is now part of the Cygnus GDB source tree (hopefully it
will in turn become part of the next FSF release of GDB).
If you're looking for a more `cutting' edge version of this
program then it can be found in:
ftp.ci.com.au:pub/clayton/psim-sim-*.tar.gz
This contains a replacement for the directory sim/ppc. As
these releases prove stable they are merged back into the GDB
source tree.
If you find bugs or experience problems, please e-mail them to
the alias:
powerpc-psim@ci.com.au
It's a majordomo mailing list.
BUILDING:
o At present PSIM can only be built using the compiler GCC
(yes that is bug). This is because, among other things the
code exploits GCC's suport of long ongs.
o I also suggest that you install: flex, bision, gnu-make and
byacc. Doing this just makes builds easier.
o Configure almost as per normal, specifing the special target
eabisim vis:
$ CC=gcc ./configure --target=powerpcle-unknown-eabisim
by default (because of its dependency on GCC).
o Build your entire gdb tree as per normal. Something along the
lines of:
$ cd gdb-4.15
$ make CC=gcc
.
.
.
o Install it it all as per normal. Something along the lines of:
$ cd gdb-4.15
$ make CC=gcc install
RUNNING:
PSIM can either be run as a stand alone program or as part
of gdb. The psim-test archive (found in:
ftp.ci.com.au:pub/clayton
contains pre-compiled and linked programs that can be run on
PSIM. The notes below assume that you have unpacked that tar
archive.
To rebuild the archive you will need to obtain a working
version of an ELF compiler/linker for the PowerPC.
Example of running PSIM:
Print out the users environment:
$ sim/ppc/psim sim/ppc/test/envp
Print out the arguments:
$ sim/ppc/psim sim/ppc/test/argv a b c
Check the OEA model:
$ sim/ppc/psim sim/ppc/test/interrupt
Check that sbrk works
$ sim/ppc/psim sim/ppc/test/break
Try for speed. The program count contains a loop
of two instructions which is looped <arg> times.
See later for how to make PSIM run 10-100 times
faster.
$ time sim/ppc/sim sim/ppc/test/count 5000000
$ expr 10 \* 1000 \* 1000 / <seconds>
Example of running GDB:
The most important thing to be aware of is the fact
that before the simulator is used, the user must attach
to it (target sim) and than load the executable (load count).
$ cd sim/ppc/test
$ powerpc-unknown-eabi-gdb count
(gdb) target sim
(gdb) load count
(gdb) break main
(gdb) run
.
.
.
CONFIGURATION:
Making it go faster
See the file sim/ppc/config.h (which is copied from
sim/ppc/std-config.h) for further information.
This directory contains the program PSIM that models the PowerPC(tm -
IBM) architecture. It can either be run stand alone (psim or run) or
used as part of GDB.
KNOWN FEATURES
SMP: A Symetric Multi-Processor configuration is suported.
This includes a model of the PowerPC load word and reserve
et.al. instructions (if intending to use this feature you are
well advised to read the the source code for the reservation
instructions so that you are aware of any potential
limitations in the model).
DUAL-ENDIAN: Both little and big endian modes are suported.
Switching between the two modes at run time, however, is not.
SMP: A Symetric Multi-Processor configuration is suported. This
includes modeling of the PowerPC load word and reserve instructions
(if intending to use this feature you are well advised to read the the
source code for the reservation instructions so that you are aware of
any potential limitations in the model). The number of processors is
selected during startup.
UIEA, VEA and OEA: The PowerPC architecture defines three
levels of the PowerPC architecture. This simulator, to a
reasonable degree, is capable of modeling all three of them.
That is the User Instruction Set Architecture, the Virtual
Environment Architecture and finally the Operating Environment
Architecture.
DUAL-ENDIAN: Both little and big endian models are suported. The
execution of instruction sequences that switch between the two modes,
however, is not. The endianess is selected during startup.
HARDWARE DEVICES: The OEA model includes facilities that allow
a programmer to (I won't say easily) extend this simulator so
that a program can interact with models of real devices.
Illustrating this is the phony machine clayton that includes
console, interrupt control unit and reset register devices.
UIEA, VEA and OEA: The PowerPC architecture defines three levels of
the PowerPC architecture. This simulator, to a reasonable degree, is
capable of modeling all three. That is the User Instruction Set
Architecture, the Virtual Environment Architecture and finally the
Operating Environment Architecture. The environment is selected
during startup. The OEA model is still under development.
PEDANTIC VEA MEMORY MODEL: User programs can not assume that
they can stray off the end of valid memory areas. This model
defines valid memory addresses in strict accordance to the
executable and does not page allign their values. At first
this was a bug but since then has turned up several bugs in
peoples code so I've renamed it `a feature' :-)
HARDWARE DEVICE TREE: In the OEA, the model of the target machines
hardware is built from a tree of devices (bit like Open Boot).
Included in this is the ability to model bus hierachies and
runtime-configurable devices (eg PCI). The device tree used to create
the hardware model is created during startup. This device tree is
still under development.
RUNTIME CONFIG OF HARDWARE: In addition to the three builtin
models of hardware - VEA, OEA/Hardware and (the start of) OpenBoot,
it is possible to load a file containing a specification of a
custom device tree.
VEA SYSTEM CALLS: In user mode, basic system calls (read, write, open,
close ...) are emulated. Under NetBSD (simply because that is what my
machine at home runs) the list is more extensive.
PEDANTIC VEA MEMORY MODEL: This model implements the break (brk, sbrk)
system calls. Further, the user model has very strict memory access
controls. User programs can not assume that they can stray off the
end of valid memory areas. This model defines valid memory addresses
in strict accordance to the executable and does not page allign their
values. At first this was a bug but since then has turned up several
problems in user code so it is now described as a feature.
PROFILING: The simulation is able to count the number and type of
instructions issued and the number of loads and stores. This feature
is still under development.
PERFORMANCE: In its default configuration PSIM is constructed so that
it will compile fast and run slow. Through the enabling of more
agressive compile options (and the disabling of unwanted features) the
build can be changed to compile slow and run fast.
FLOATING POINT: Preliminary suport for floating point is included.
Real kernels don't need floating point.
BUILDING PSIM:
To build PSIM you will need the following:
gdb-4.15.tar.gz From your favorite GNU ftp site
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.diff.gz
This contains a few minor patches to
gdb-4.15 so that will include psim
when it is built.
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.tar.gz
This contains the psim files propper.
ftp://ftp.ci.com.au/pub/clayton/psim-test-951016.tar.gz
(Optional) A scattering of pre-compiled
programs that run under the simulator.
gcc Again available from your favorite
GNU ftp site.
patch Sun's patch behaves a little wierd
and doesn't appear to like creating
empty files.
In the directory ftp.ci.com.au:pub/clayton you will also notice files
named psim-NNNNNN.tar.gz. Those, more recent snapshots, may or may
not work with gdb.
0. A starting point
$ ls -1
gdb-4.15+psim-951016.diff.gz
gdb-4.15+psim-951016.tar.gz
gdb-4.15.tar.gz
psim-test-951016.tar.gz
1. Unpack gdb
$ gunzip < gdb-4.15.tar.gz | tar xf -
2. Change to the gdb directory, apply the psim patches and unpack
the psim files.
$ cd gdb-4.15
$ gunzip < ../gdb-4.15+psim-951016.diff.gz | more
$ gunzip < ../gdb-4.15+psim-951016.diff.gz | patch -p1
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar tvf -
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar xvf -
3. Configure gdb
$ more gdb/README
then something like (I assume SH):
$ CC=gcc ./configure --target=powerpc-unknown-eabisim
eabisim is needed as by default (because PSIM needs GCC) the
simulator is not built.
4. Build
$ make CC=gcc
alternativly, if you are short on disk space or just want the
simulator built:
$ ( cd libiberty && make CC=gcc )
$ ( cd bfd && make CC=gcc )
$ ( cd sim/ppc && make CC=gcc )
5. Install
$ make CC=gcc install
or just
$ cp gdb/gdb ~/bin/powerpc-unknown-eabisim-gdb
$ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
USING THE SIMULATOR:
(I assume that you've unpacked the psim-test archive).
1. As a standalone program
Print out the users environment:
$ powerpc-unknown-eabisim-run envp
Print out the arguments:
$ powerpc-unknown-eabisim-run argv a b c
Check that sbrk works:
$ powerpc-unknown-eabisim-run break
2. Example of running GDB:
The main thing to note is that before you can run the simulator
you must enable it. The example below illustrates this:
$ powerpc-unknown-eabisim-gdb envp
(gdb) target sim
(gdb) load
(gdb) break main
(gdb) run
.
.
.
BUGS AND PROBLEMS:
There is a mailing list (subscribe through majordomo@ci.com.au) (that
is almost never used) at:
powerpc-psim@ci.com.au
If I get the ftp archive updated I post a note to that news group. In
addition your welcome to send bugs or problems either to me or to that
e-mail list.
KNOWN PROBLEMS:
FLOATING POINT: Need to add suport for non IEEE float
machines. Need to more fully handle exceptions (eg things
like divide by zero).
See the ChangeLog file looking for lines taged with the word FIXME.
DEVICE TREE DOC: How to create and use the device tree is not
documented at all.
CORE.C: The implementation of core.c (defined by core.h) isn't the
best. It is intended to be functionaly correct rather than fast.
INITIALIZATION: When running from gdb, things are not
re-initialzied very well e.g. registers are not rezeroed.
HTAB (page) code for OEA model untested. Some of the vm code
instructions unimplemented.
HTAB (page) code for OEA model untested. Some of the vm code
instructions unimplemented.
Flush instruction cache instructions do nothing. Perhaphs they should
(if there is an instruction cache) flush it.
Flush instruction cache instructions do nothing. Perhaphs they
should (if there is an instruction cache) flush it.
Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups. The
PowerOpen worked until I added the ELF one.
Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.
The PowerOpen worked until I added the ELF one.
OpenBoot and PR*P interfaces missing. Open boot could be implemented
by putting special instructions at the address of the OpenBoot
callback functions. Those instructions could than emulate OpenBoot
behavour.
OpenBoot and PR*P interfaces missing. Open boot could be
implemented by putting special instructions at the address
of the OpenBoot callback functions. Those instructions
could than emulate OpenBoot behavour.
Missing VEA system calls.
Missing VEA system calls.
Missing or commented out instructions.
Missing or commented out instructions.
64bit target untested.
Only basic (hackish) floating point implemented, I would not
trust it and it is going to change.
64bit host broken. For instance use of scanf "%x", &long long.
64bit target untested.
Event code for pending events from within signal handlers not
finished/tested.
64bit host broken. For instance use of scanf "%x", &long long.
Better and more devices.
Event code for pending events from within signal handlers not
finished/tested.
PORTABILITY (Notes taken from Michael Meissner): Heavy use of the ##
operator - fix using the clasic X/**/Y hack; Use of the signed
keyword. In particular, signed char has no analogue in classic C
(though most implementations of classic C use signed chars); Use of
long long which restricts the target compiler to be GCC.
Better and more devices.
PORTABILITY (Notes taken from Michael Meissner): Heavy use of
the ## operator - fix using the clasic X/**/Y hack; Use of the
signed keyword. In particular, signed char has no analogue in
classic C (though most implementations of classic C use signed
chars); Use of long long which restricts the target compiler
to be GCC.
OPTIONS/FLAGS: Need a function that can parse command line
options so that both psim and sim_{load,open,command} can all
call it. Options should be extended to allow the setting of
things like floating point support.
THANKS:
Thanks go to the following who each helped in some way.
Thanks go to the following who each helped in some way.
Allen Briggs, Bett Koch, David Edelsohn,
Michael Meissner, Bob Mercier, Richard Perini,
Richard Stallman, Mitchele Walker
Allen Briggs, Bett Koch, David Edelsohn, Gordon Irlam,
Michael Meissner, Bob Mercier, Richard Perini,
Richard Stallman, Mitchele Walker
----------------------------------------------------------------
@ -274,7 +293,3 @@ i486DX2/66
1/270/316 - switch=2/2,expand=0,inline=1,nia=0
1/271/281 - switch=1/1,expand=0,inline=1,nia=1
1/267/274 - switch=2/1,expand=0,inline=1,nia=1
----
CFLAGS = -g -Wall -Wno-unused -Wmissing-prototypes -Werror

27
sim/ppc/bits.c Normal file
View File

@ -0,0 +1,27 @@
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _BITS_C_
#define _BITS_C_
#include "basics.h"
#endif /* _BITS_C_ */

155
sim/ppc/build-psim Executable file
View File

@ -0,0 +1,155 @@
#!/bin/sh
case "`uname -s`-`uname -r`" in
NetBSD* )
cflags="-Wall -Wno-unused -Wmissing-prototypes -Werror"
;;
SunOS-5* )
cflags="-gstabs+"
;;
SunOS-4* )
cflags="-Werror"
;;
esac
for target in "$@"
do
echo ""
echo "$target"
echo ""
if [ $# -gt 1 ]
then
make clean
fi
case $target in
*unsafe* )
with_trace="-DWITH_TRACE=0"
with_assert="-DWITH_ASSERT=0"
unsafe_flags="-g0 -fomit-frame-pointer -fno-strength-reduce"
;;
*safe* )
with_trace=
with_assert=
unsafe_flags="-g0"
;;
* )
with_trace=
with_assert=
unsafe_flags=
;;
esac
case $target in
*little* )
with_target_byte_order="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN"
;;
*big* )
with_target_byte_order="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN"
;;
* )
with_target_byte_order=
;;
esac
case $target in
*vea* )
with_environment="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT"
with_smp="-DWITH_SMP=0"
;;
*oea* )
with_environment="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT"
with_smp="-DWITH_SMP=2"
;;
* )
with_environment=
with_smp=
;;
esac
case $target in
*complex* )
igen_opcode_rules="IGEN_OPCODE_RULES=ppc-opcode-complex"
igen_flags="-e -r 1024"
opt_flags="-O2"
;;
*simple* )
igen_opcode_rules="IGEN_OPCODE_RULES=ppc-opcode-simple"
igen_flags="-e"
opt_flags="-O2"
;;
* )
igen_opcode_rules=
igen_flags=
opt_flags=
;;
esac
case $target in
*64* )
with_target_word_bitsize="-DWITH_TARGET_WORD_BITSIZE=64"
igen_flags="$igen_flags -f 32"
;;
*32* )
with_target_word_bitsize="-DWITH_TARGET_WORD_BITSIZE=32"
igen_flags="$igen_flags -f 64"
;;
* )
with_target_word_bitsize=
igen_flags="$igen_flags -f 64"
;;
esac
case $target in
*inline* )
default_inline="-DDEFAULT_INLINE=2"
;;
* )
default_inline=
;;
esac
case $target in
*nomon* )
with_mon="-DWITH_MON=0"
;;
* )
with_mon=
;;
esac
case $target in
*bswap* )
with_bswap="-DWITH_BSWAP=1"
;;
* )
with_bswap=
;;
esac
if ( set -x ; make \
$igen_opcode_rules \
IGEN_FLAGS="$igen_flags" \
INLINE_CFLAGS=" \
$cflags \
$unsafe_flags \
$opt_flags \
$with_bswap \
$with_target_byte_order \
$with_environment \
$with_smp \
$default_inline \
$with_target_word_bitsize \
$with_trace \
$with_assert \
$with_mon \
" )
then
rm -f psim-${target}-failed
( set -x ; cp psim psim-$target )
else
( set -x ; touch psim-${target}-failed )
fi
done

View File

@ -42,7 +42,7 @@ struct _core_mapping {
device_io_read_buffer_callback *reader;
device_io_write_buffer_callback *writer;
/* common */
int address_space;
int space;
unsigned_word base;
unsigned_word bound;
unsigned nr_bytes;
@ -130,12 +130,12 @@ core_executable(core *memory)
STATIC_INLINE_CORE core_mapping *
new_core_mapping(attach_type attach,
int address_space,
unsigned_word addr,
unsigned nr_bytes,
const device *device,
void *buffer,
int free_buffer)
int space,
unsigned_word addr,
unsigned nr_bytes,
const device *device,
void *buffer,
int free_buffer)
{
core_mapping *new_mapping = ZALLOC(core_mapping);
switch (attach) {
@ -154,7 +154,7 @@ new_core_mapping(attach_type attach,
attach);
}
/* common */
new_mapping->address_space = address_space;
new_mapping->space = space;
new_mapping->base = addr;
new_mapping->nr_bytes = nr_bytes;
new_mapping->bound = addr + (nr_bytes - 1);
@ -164,21 +164,21 @@ new_core_mapping(attach_type attach,
STATIC_INLINE_CORE void
core_map_attach(core_map *access_map,
attach_type attach,
int address_space,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
const device *device, /*callback/default*/
void *buffer, /*raw_memory*/
int free_buffer) /*raw_memory*/
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
const device *device, /*callback/default*/
void *buffer, /*raw_memory*/
int free_buffer) /*raw_memory*/
{
if (attach == attach_default) {
if (access_map->default_map != NULL)
error("core_map_attach() default mapping already in place\n");
ASSERT(buffer == NULL);
access_map->default_map = new_core_mapping(attach,
address_space, addr, nr_bytes,
device, buffer, free_buffer);
space, addr, nr_bytes,
device, buffer, free_buffer);
}
else {
/* find the insertion point for this additional mapping and insert */
@ -206,8 +206,8 @@ core_map_attach(core_map *access_map,
/* create/insert the new mapping */
*last_mapping = new_core_mapping(attach,
address_space, addr, nr_bytes,
device, buffer, free_buffer);
space, addr, nr_bytes,
device, buffer, free_buffer);
(*last_mapping)->next = next_mapping;
}
}
@ -216,7 +216,7 @@ core_map_attach(core_map *access_map,
INLINE_CORE void
core_attach(core *memory,
attach_type attach,
int address_space,
int space,
access_type access,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
@ -236,7 +236,7 @@ core_attach(core *memory,
if (access & access_read)
core_map_attach(memory->map + access_map,
attach,
address_space, addr, nr_bytes,
space, addr, nr_bytes,
device, buffer, !free_buffer);
free_buffer ++;
break;
@ -244,7 +244,7 @@ core_attach(core *memory,
if (access & access_write)
core_map_attach(memory->map + access_map,
attach,
address_space, addr, nr_bytes,
space, addr, nr_bytes,
device, buffer, !free_buffer);
free_buffer ++;
break;
@ -252,7 +252,7 @@ core_attach(core *memory,
if (access & access_exec)
core_map_attach(memory->map + access_map,
attach,
address_space, addr, nr_bytes,
space, addr, nr_bytes,
device, buffer, !free_buffer);
free_buffer ++;
break;
@ -320,7 +320,7 @@ core_map_read_buffer(core_map *map,
if (mapping->reader != NULL) {
if (mapping->reader(mapping->device,
&byte,
mapping->address_space,
mapping->space,
raddr - mapping->base,
1, /* nr_bytes */
0, /*processor*/
@ -357,7 +357,7 @@ core_map_write_buffer(core_map *map,
if (mapping->writer != NULL) {
if (mapping->writer(mapping->device,
&byte,
mapping->address_space,
mapping->space,
raddr - mapping->base,
1, /*nr_bytes*/
0, /*processor*/
@ -382,6 +382,7 @@ core_init_callback(const device *me,
psim *system)
{
core *memory = (core*)me->data;
DTRACE_INIT(core);
core_init(memory);
}
@ -390,7 +391,7 @@ STATIC_INLINE_CORE void
core_attach_address_callback(const device *me,
const char *name,
attach_type attach,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
@ -398,11 +399,12 @@ core_attach_address_callback(const device *me,
{
core *memory = (core*)me->data;
unsigned_word device_address;
if (address_space != 0)
DTRACE_ATTACH_ADDRESS(core);
if (space != 0)
error("core_attach_address_callback() invalid address space\n");
core_attach(memory,
attach,
address_space,
space,
access,
addr,
nr_bytes,
@ -412,15 +414,16 @@ core_attach_address_callback(const device *me,
STATIC_INLINE_CORE unsigned
core_dma_read_buffer_callback(const device *me,
void *target,
int address_space,
unsigned_word offset,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes)
{
core *memory = (core*)me->data;
DTRACE_DMA_READ_BUFFER(core);
return core_map_read_buffer(core_readable(memory),
target,
offset,
dest,
addr,
nr_bytes);
}
@ -428,8 +431,8 @@ core_dma_read_buffer_callback(const device *me,
STATIC_INLINE_CORE unsigned
core_dma_write_buffer_callback(const device *me,
const void *source,
int address_space,
unsigned_word offset,
int space,
unsigned_word addr,
unsigned nr_bytes,
int violate_read_only_section)
{
@ -437,9 +440,10 @@ core_dma_write_buffer_callback(const device *me,
core_map *map = (violate_read_only_section
? core_readable(memory)
: core_writeable(memory));
DTRACE_DMA_WRITE_BUFFER(core);
return core_map_write_buffer(map,
source,
offset,
addr,
nr_bytes);
}
@ -463,7 +467,7 @@ static device_callbacks const core_callbacks = {
INLINE_CORE const device *
core_device_create(core *memory)
{
return device_create_from("core", memory, &core_callbacks, NULL);
return device_create_from("core", "/", memory, &core_callbacks, NULL);
}

View File

@ -47,7 +47,7 @@ XCONCAT2(core_map_read_,N)(core_map *map,
unsigned_N data;
if (mapping->reader(mapping->device,
&data,
mapping->address_space,
mapping->space,
addr - mapping->base,
sizeof(unsigned_N), /* nr_bytes */
processor,
@ -78,7 +78,7 @@ XCONCAT2(core_map_write_,N)(core_map *map,
unsigned_N data = H2T_N(val);
if (mapping->writer(mapping->device,
&data,
mapping->address_space,
mapping->space,
addr - mapping->base,
sizeof(unsigned_N), /* nr_bytes */
processor,

View File

@ -41,6 +41,14 @@ typedef enum {
node_string
} node_type;
static char *node_type_names[] = {
"any",
"device",
"integer",
"boolean",
"string",
NULL,
};
struct _device_tree {
/* where i am */
@ -89,6 +97,7 @@ typedef enum {
STATIC_INLINE_DEVICE_TREE device_tree *
device_tree_find_node(device_tree *root,
const char *path,
const char *full_path,
node_type type,
device_tree_action action)
{
@ -139,13 +148,13 @@ device_tree_find_node(device_tree *root,
if (path[name_len] == '\0') {
if (action == device_tree_grow)
error("device_tree_find_node() node %s already present\n",
path);
full_path);
if (type != node_any && child->type != type) {
if (action == device_tree_return_null)
return NULL;
else
error("device_tree_find_node() node %s does not match type %d\n",
path, type);
error("device_tree_find_node() node %s is not of type %s\n",
full_path, node_type_names[type]);
}
else
return child;
@ -153,6 +162,7 @@ device_tree_find_node(device_tree *root,
else
return device_tree_find_node(child,
path + name_len + 1,
full_path,
type,
action);
}
@ -163,10 +173,15 @@ device_tree_find_node(device_tree *root,
switch (action) {
case device_tree_grow:
if (path[name_len] != '\0')
error("device_tree_find_node() not a leaf %s\n", path);
error("device_tree_find_node() a parent of %s missing\n",
full_path);
return new_device_tree(root, path, type);
case device_tree_return_null:
return NULL;
case device_tree_abort:
error("device_tree_find_node() could not find %s in tree\n",
full_path);
return NULL;
default:
error("device_tree_find_node() invalid default action %d\n", action);
return NULL;
@ -180,14 +195,22 @@ INLINE_DEVICE_TREE device_tree *
device_tree_add_passthrough(device_tree *root,
const char *path)
{
device_tree *new_node = device_tree_find_node(root,
path,
node_device,
device_tree_grow);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_passthrough(root=0x%x, path=%s)\n", root, path));
new_node = device_tree_find_node(root,
path,
path, /*full_path*/
node_device,
device_tree_grow);
new_node->device = device_create_from(new_node->name,
path,
NULL,
passthrough_device_callbacks(),
new_node->parent->device);
TRACE(trace_device_tree,
("device_tree_add_passthrough() = 0x%x\n", new_node));
return new_node;
}
@ -197,11 +220,18 @@ device_tree_add_device(device_tree *root,
const char *path,
const device *dev)
{
device_tree *new_node = device_tree_find_node(root,
path,
node_device,
device_tree_grow);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_device(root=0x%x, path=%s, dev=0x%x)\n",
root, path, dev));
new_node = device_tree_find_node(root,
path,
path, /* full-path */
node_device,
device_tree_grow);
new_node->device = dev;
TRACE(trace_device_tree,
("device_tree_add_device() = 0x%x\n", new_node));
return new_node;
}
@ -210,11 +240,18 @@ device_tree_add_integer(device_tree *root,
const char *path,
signed_word integer)
{
device_tree *new_node = device_tree_find_node(root,
path,
node_integer,
device_tree_grow);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_integer(root=0x%x, path=%s, integer=%d)\n",
root, path, integer));
new_node = device_tree_find_node(root,
path,
path, /* full-name */
node_integer,
device_tree_grow);
new_node->integer = integer;
TRACE(trace_device_tree,
("device_tree_add_integer() = 0x%x\n", new_node));
return new_node;
}
@ -223,11 +260,18 @@ device_tree_add_string(device_tree *root,
const char *path,
const char *string)
{
device_tree *new_node = device_tree_find_node(root,
path,
node_string,
device_tree_grow);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_device(root=0x%x, path=%s, string=%s)\n",
root, path, string));
new_node = device_tree_find_node(root,
path,
path, /* full-name */
node_string,
device_tree_grow);
new_node->string = string;
TRACE(trace_device_tree,
("device_tree_add_string() = 0x%x\n", new_node));
return new_node;
}
@ -236,11 +280,18 @@ device_tree_add_boolean(device_tree *root,
const char *path,
int boolean)
{
device_tree *new_node = device_tree_find_node(root,
path,
node_boolean,
device_tree_grow);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_boolean(root=0x%x, path=%s, boolean=%d)\n",
root, path, boolean));
new_node = device_tree_find_node(root,
path,
path, /* full-name */
node_boolean,
device_tree_grow);
new_node->boolean = boolean;
TRACE(trace_device_tree,
("device_tree_add_boolean() = 0x%x\n", new_node));
return new_node;
}
@ -248,9 +299,16 @@ INLINE_DEVICE_TREE device_tree *
device_tree_add_found_device(device_tree *root,
const char *path)
{
device_tree *new_node = device_tree_add_device(root, path, NULL);
device_tree *new_node;
TRACE(trace_device_tree,
("device_tree_add_found_device(root=0x%x, path=%s)\n",
root, path));
new_node = device_tree_add_device(root, path, NULL);
new_node->device = device_create(new_node->name,
path,
new_node->parent->device);
TRACE(trace_device_tree,
("device_tree_add_found_device() = 0x%x\n", new_node));
return new_node;
}
@ -261,10 +319,16 @@ INLINE_DEVICE_TREE const device *
device_tree_find_device(device_tree *root,
const char *path)
{
device_tree *node = device_tree_find_node(root,
path,
node_device,
device_tree_abort);
device_tree *node;
TRACE(trace_device_tree,
("device_tree_find_device(root=0x%x, path=%s)\n", root, path));
node = device_tree_find_node(root,
path,
path, /* full-name */
node_device,
device_tree_abort);
TRACE(trace_device_tree,
("device_tree_find_device() = 0x%x\n", node->device));
return node->device;
}
@ -272,10 +336,16 @@ INLINE_DEVICE_TREE signed_word
device_tree_find_integer(device_tree *root,
const char *path)
{
device_tree *node = device_tree_find_node(root,
path,
node_integer,
device_tree_abort);
device_tree *node;
TRACE(trace_device_tree,
("device_tree_find_integer(root=0x%x, path=%s)\n", root, path));
node = device_tree_find_node(root,
path,
path, /* full-name */
node_integer,
device_tree_abort);
TRACE(trace_device_tree,
("device_tree_find_integer() = %d\n", node->integer));
return node->integer;
}
@ -283,10 +353,16 @@ INLINE_DEVICE_TREE const char *
device_tree_find_string(device_tree *root,
const char *path)
{
device_tree *node = device_tree_find_node(root,
path,
node_string,
device_tree_abort);
device_tree *node;
TRACE(trace_device_tree,
("device_tree_find_string(root=0x%x, path=%s)\n", root, path));
node = device_tree_find_node(root,
path,
path, /* full-name */
node_string,
device_tree_abort);
TRACE(trace_device_tree,
("device_tree_find_string() = 0x%x\n", node->string));
return node->string;
}
@ -294,10 +370,16 @@ INLINE_DEVICE_TREE int
device_tree_find_boolean(device_tree *root,
const char *path)
{
device_tree *node = device_tree_find_node(root,
path,
node_boolean,
device_tree_abort);
device_tree *node;
TRACE(trace_device_tree,
("device_tree_find_boolean(root=0x%x, path=%s)\n", root, path));
node = device_tree_find_node(root,
path,
path, /* full-name */
node_boolean,
device_tree_abort);
TRACE(trace_device_tree,
("device_tree_find_boolean() = %d\n", node->boolean));
return node->boolean;
}
@ -308,9 +390,14 @@ STATIC_INLINE_DEVICE_TREE void
device_tree_init_device(device_tree *root,
void *data)
{
psim *system = (psim*)data;
if (root->type == node_device)
psim *system;
system = (psim*)data;
if (root->type == node_device) {
TRACE(trace_device_tree,
("device_tree_init() initializing device=0x%x:%s\n",
root->device, root->device->full_name));
root->device->callback->init(root->device, system);
}
}
@ -318,7 +405,11 @@ INLINE_DEVICE_TREE void
device_tree_init(device_tree *root,
psim *system)
{
TRACE(trace_device_tree,
("device_tree_init(root=0x%x, system=0x%x)\n", root, system));
device_tree_traverse(root, device_tree_init_device, NULL, system);
TRACE(trace_device_tree,
("device_tree_init() = void\n"));
}
@ -363,10 +454,6 @@ device_tree_dump(device_tree *device,
/* Parse a device name, various formats */
#ifndef __NetBSD__
#define strtouq strtoul
#endif
#define SCAN_INIT(START, END, COUNT, NAME) \
char *START = NULL; \
char *END = strchr(NAME, '@'); \
@ -377,7 +464,7 @@ device_tree_dump(device_tree *device,
#define SCAN_U(START, END, COUNT, U) \
do { \
*U = strtouq(START, &END, 0); \
*U = strtoul(START, &END, 0); \
if (START == END) \
return COUNT; \
COUNT++; \
@ -397,7 +484,7 @@ do { \
START = END + 1; \
} while (0)
#define SCAN_C(START, END, COUNT, C) \
#define SCAN_C(START, END, COUNT, C, SIZE) \
do { \
char *chp = C; \
END = START; \
@ -407,6 +494,8 @@ do { \
*chp = *END; \
chp += 1; \
END += 1; \
if ((SIZE) <= ((END) - (START))) \
return COUNT; /* overflow */ \
} \
*chp = '\0'; \
if (START == END) \
@ -465,21 +554,21 @@ scand_uw_uw_u(const char *name,
INLINE_DEVICE_TREE int
scand_c(const char *name,
char *c1)
char *c1, int c1size)
{
SCAN_INIT(start, end, count, name);
SCAN_C(start, end, count, c1);
SCAN_C(start, end, count, c1, c1size);
return count;
}
INLINE_DEVICE_TREE int
scand_c_uw_u(const char *name,
char *c1,
char *c1, int c1size,
unsigned_word *uw2,
unsigned *u3)
{
SCAN_INIT(start, end, count, name);
SCAN_C(start, end, count, c1);
SCAN_C(start, end, count, c1, c1size);
SCAN_U(start, end, count, uw2);
SCAN_U(start, end, count, u3);
return count;

View File

@ -110,7 +110,11 @@ INLINE_DEVICE_TREE void device_tree_dump
void *ignore_data_argument);
/* Parse a device name, various formats */
/* Parse a device name, various formats:
uw: unsigned_word
u: unsigned
c: string */
INLINE_DEVICE_TREE int scand_uw
(const char *name,
@ -135,11 +139,11 @@ INLINE_DEVICE_TREE int scand_uw_uw_u
INLINE_DEVICE_TREE int scand_c
(const char *name,
char *c1);
char *c1, int c1size);
INLINE_DEVICE_TREE int scand_c_uw_u
(const char *name,
char *c1,
char *c1, int c1size,
unsigned_word *uw2,
unsigned *u3);

View File

@ -59,7 +59,7 @@ generic_init_callback(const device *me,
me->parent->callback->attach_address(me->parent,
me->name,
attach_callback,
0 /*address_space*/,
0 /*space*/,
addr,
nr_bytes,
access_read_write,
@ -81,7 +81,7 @@ INLINE_DEVICES void
unimp_device_attach_address(const device *me,
const char *name,
attach_type type,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
@ -94,7 +94,7 @@ INLINE_DEVICES void
unimp_device_detach_address(const device *me,
const char *name,
attach_type type,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
@ -106,7 +106,7 @@ unimp_device_detach_address(const device *me,
INLINE_DEVICES unsigned
unimp_device_io_read_buffer(const device *me,
void *dest,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
@ -119,7 +119,7 @@ unimp_device_io_read_buffer(const device *me,
INLINE_DEVICES unsigned
unimp_device_io_write_buffer(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
@ -132,7 +132,7 @@ unimp_device_io_write_buffer(const device *me,
INLINE_DEVICES unsigned
unimp_device_dma_read_buffer(const device *me,
void *target,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes)
{
@ -143,7 +143,7 @@ unimp_device_dma_read_buffer(const device *me,
INLINE_DEVICES unsigned
unimp_device_dma_write_buffer(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
int violate_read_only_section)
@ -213,15 +213,16 @@ ignore_device_init(const device *me,
INLINE_DEVICES void
pass_device_attach_address(const device *me,
const char *name,
attach_type type,
int address_space,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
const device *who) /*callback/default*/
{
me->parent->callback->attach_address(me->parent, name, type,
address_space, addr, nr_bytes,
DTRACE_ATTACH_ADDRESS(pass);
me->parent->callback->attach_address(me->parent, name, attach,
space, addr, nr_bytes,
access,
who);
}
@ -229,39 +230,42 @@ pass_device_attach_address(const device *me,
INLINE_DEVICES void
pass_device_detach_address(const device *me,
const char *name,
attach_type type,
int address_space,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
const device *who) /*callback/default*/
{
me->parent->callback->detach_address(me->parent, name, type,
address_space, addr, nr_bytes, access,
DTRACE_DETACH_ADDRESS(pass);
me->parent->callback->detach_address(me->parent, name, attach,
space, addr, nr_bytes, access,
who);
}
INLINE_DEVICES unsigned
pass_device_dma_read_buffer(const device *me,
void *target,
int address_space,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes)
{
return me->parent->callback->dma_read_buffer(me->parent, target,
address_space, addr, nr_bytes);
DTRACE_DMA_READ_BUFFER(pass);
return me->parent->callback->dma_read_buffer(me->parent, dest,
space, addr, nr_bytes);
}
INLINE_DEVICES unsigned
pass_device_dma_write_buffer(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
int violate_read_only_section)
{
DTRACE_DMA_WRITE_BUFFER(pass);
return me->parent->callback->dma_write_buffer(me->parent, source,
address_space, addr,
space, addr,
nr_bytes,
violate_read_only_section);
}
@ -341,7 +345,7 @@ typedef enum {
STATIC_INLINE_DEVICES unsigned
console_io_read_buffer_callback(const device *me,
void *dest,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
@ -349,9 +353,7 @@ console_io_read_buffer_callback(const device *me,
{
console_device *console = (console_device*)me->data;
unsigned_1 val;
TRACE(trace_console_device,
("device=0x%x, addr=0x%x, nr_bytes=%d\n",
me, addr, nr_bytes));
DTRACE_IO_READ_BUFFER(console);
/* determine what was read */
@ -416,7 +418,7 @@ console_io_read_buffer_callback(const device *me,
STATIC_INLINE_DEVICES unsigned
console_io_write_buffer_callback(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
@ -424,10 +426,7 @@ console_io_write_buffer_callback(const device *me,
{
console_device *console = (console_device*)me->data;
unsigned_1 val = *(unsigned8*)source;
TRACE(trace_console_device,
("device=0x%x, addr=0x%x, nr_bytes=%d, val=%d\n",
me, addr, nr_bytes, val));
DTRACE_IO_WRITE_BUFFER(console);
switch (addr) {
case console_read_buffer:
@ -437,8 +436,7 @@ console_io_write_buffer_callback(const device *me,
console->input.status = val;
break;
case console_write_buffer:
TRACE(trace_console_device,
("<%c:%d>", val, val));
DTRACE(console, ("<%c:%d>", val, val));
printf_filtered("%c",val) ;
console->output.buffer = val;
console->output.status = 1;
@ -472,6 +470,7 @@ static device_callbacks const console_callbacks = {
STATIC_INLINE_DEVICES const device *
console_create(const char *name,
const char *full_name,
const device *parent)
{
/* create the descriptor */
@ -485,6 +484,7 @@ console_create(const char *name,
/* insert into the device tree along with its address info */
return device_create_from(name,
full_name,
console, /* data */
&console_callbacks,
parent);
@ -507,16 +507,14 @@ console_create(const char *name,
STATIC_INLINE_DEVICES unsigned
icu_io_read_buffer_callback(const device *me,
void *dest,
int address_space,
unsigned_word base,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
unsigned_1 val;
TRACE(trace_icu_device,
("device=0x%x, base=0x%x, nr_bytes=%d\n",
me, base, nr_bytes));
DTRACE_IO_READ_BUFFER(icu);
val = cpu_nr(processor);
bzero(dest, nr_bytes);
*(unsigned_1*)dest = val;
@ -527,17 +525,15 @@ icu_io_read_buffer_callback(const device *me,
STATIC_INLINE_DEVICES unsigned
icu_io_write_buffer_callback(const device *me,
const void *source,
int address_space,
unsigned_word base,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
psim *system = cpu_system(processor);
unsigned_1 val = H2T_1(*(unsigned_1*)source);
TRACE(trace_icu_device,
("device=0x%x, base=0x%x, nr_bytes=%d, val=0x%x\n",
me, base, nr_bytes, val));
DTRACE_IO_WRITE_BUFFER(icu);
/* tell the parent device that the interrupt lines have changed.
For this fake ICU. The interrupt lines just indicate the cpu to
interrupt next */
@ -575,12 +571,13 @@ static device_callbacks const icu_callbacks = {
STATIC_INLINE_DEVICES unsigned
halt_io_read_buffer_callback(const device *me,
void *dest,
int address_space,
unsigned_word base,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
DTRACE_IO_READ_BUFFER(halt);
cpu_halt(processor, cia, was_exited, 0);
return 0;
}
@ -589,12 +586,13 @@ halt_io_read_buffer_callback(const device *me,
STATIC_INLINE_DEVICES unsigned
halt_io_write_buffer_callback(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
DTRACE_IO_WRITE_BUFFER(halt);
cpu_halt(processor, cia, was_exited, 0);
return 0;
}
@ -630,7 +628,8 @@ register_init_callback(const device *me,
unsigned_word value;
unsigned which_cpu;
int status;
status = scand_c_uw_u(me->name, name, &value, &which_cpu);
DTRACE_INIT(register);
status = scand_c_uw_u(me->name, name, sizeof(name), &value, &which_cpu);
switch (status) {
case 2: /* register@<name>,<value> */
psim_write_register(system, -1, &value, name, cooked_transfer);
@ -702,6 +701,7 @@ vm_init_callback(const device *me,
psim *system)
{
vm_device *vm = (vm_device*)me->data;
DTRACE_INIT(vm);
/* revert the stack/heap variables to their defaults */
vm->stack_lower_limit = vm->stack_bound;
@ -724,14 +724,15 @@ vm_init_callback(const device *me,
STATIC_INLINE_DEVICES void
vm_attach_address(const device *me,
const char *name,
attach_type type,
int address_space,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
const device *who) /*callback/default*/
{
vm_device *vm = (vm_device*)me->data;
DTRACE_ATTACH_ADDRESS(vm);
/* update end of bss if necessary */
if (vm->heap_base < addr + nr_bytes) {
vm->heap_base = addr + nr_bytes;
@ -799,12 +800,13 @@ add_vm_space(const device *me,
STATIC_INLINE_DEVICES unsigned
vm_io_read_buffer_callback(const device *me,
void *dest,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
DTRACE_IO_READ_BUFFER(vm);
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
bzero(dest, nr_bytes); /* always initialized to zero */
return nr_bytes;
@ -817,15 +819,16 @@ vm_io_read_buffer_callback(const device *me,
STATIC_INLINE_DEVICES unsigned
vm_io_write_buffer_callback(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
DTRACE_IO_WRITE_BUFFER(vm);
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
return me->parent->callback->dma_write_buffer(me->parent, source,
address_space, addr,
space, addr,
nr_bytes,
0/*violate_read_only*/);
}
@ -873,7 +876,8 @@ static device_callbacks const vm_callbacks = {
STATIC_INLINE_DEVICES const device *
vea_vm_create(const char *name,
const device *parent)
const char *full_name,
const device *parent)
{
vm_device *vm = ZALLOC(vm_device);
unsigned_word addr;
@ -887,6 +891,7 @@ vea_vm_create(const char *name,
/* insert in the tree including the buffer */
return device_create_from(name,
full_name,
vm, /* data */
&vm_callbacks,
parent);
@ -905,9 +910,20 @@ memory_init_callback(const device *me,
unsigned_word addr;
unsigned nr_bytes;
unsigned access;
int nr_args;
DTRACE_INIT(memory);
if (scand_uw_u_u(me->name, &addr, &nr_bytes, &access) != 3)
nr_args = scand_uw_u_u(me->name, &addr, &nr_bytes, &access);
switch (nr_args) {
case 2:
access = access_read_write_exec;
break;
case 3:
break;
default:
error("memory_init_callback() invalid memory device %s\n", me->name);
break;
}
me->parent->callback->attach_address(me->parent,
me->name,
@ -936,24 +952,6 @@ static device_callbacks const memory_callbacks = {
};
STATIC_INLINE_DEVICES const device *
memory_create(const char *name,
const device *parent)
{
void *buffer;
unsigned_word addr;
unsigned nr_bytes;
if (scand_uw_u(name, &addr, &nr_bytes) != 2)
error("memory_create() invalid memory device %s\n");
/* insert in the tree including the buffer */
return device_create_from(name,
buffer, /* data */
&memory_callbacks,
parent);
}
/* IOBUS device: iobus@<address>
@ -963,7 +961,7 @@ STATIC_INLINE_DEVICES void
iobus_attach_address_callback(const device *me,
const char *name,
attach_type type,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
@ -974,8 +972,8 @@ iobus_attach_address_callback(const device *me,
if (type == attach_default)
error("iobus_attach_address_callback() no default for %s/%s\n",
me->name, name);
if (address_space != 0)
error("iobus_attach_address_callback() no address_space for %s/%s\n",
if (space != 0)
error("iobus_attach_address_callback() no space for %s/%s\n",
me->name, name);
/* get the bus address */
if (scand_uw(me->name, &iobus_addr) != 1)
@ -984,7 +982,7 @@ iobus_attach_address_callback(const device *me,
me->parent->callback->attach_address(me->parent,
me->name,
type,
0 /*address_space*/,
0 /*space*/,
iobus_addr + addr,
nr_bytes,
access,
@ -1052,9 +1050,11 @@ file_init_callback(const device *me,
psim *system)
{
unsigned_word addr;
unsigned count;
char *file_name;
char buf;
FILE *image;
DTRACE_INIT(file);
if ((file_name = strchr(me->name, ',')) == NULL
|| scand_uw(me->name, &addr) != 1)
@ -1067,14 +1067,17 @@ file_init_callback(const device *me,
error("file_init_callback() file open failed for %s\n", me->name);
/* read it in slowly */
count = 0;
while (fread(&buf, 1, 1, image) > 0) {
me->parent->callback->dma_write_buffer(me->parent,
&buf,
0 /*address-space*/,
addr,
1 /*nr-bytes*/,
1 /*violate ro*/);
addr++;
if (me->parent->callback->dma_write_buffer(me->parent,
&buf,
0 /*address-space*/,
addr+count,
1 /*nr-bytes*/,
1 /*violate ro*/) != 1)
error("file_init_callback() failed to write to address 0x%x, offset %d\n",
addr+count, count);
count++;
}
/* close down again */
@ -1115,6 +1118,7 @@ STATIC_INLINE_DEVICES void
htab_init_callback(const device *me,
psim *system)
{
DTRACE_INIT(htab);
/* only the pte does work */
if (strncmp(me->name, "pte@", strlen("pte@")) == 0) {
unsigned_word htab_ra;
@ -1184,12 +1188,10 @@ static device_callbacks const sim_callbacks = {
this device loads or maps the relevant text/data segments into
memory using dma. */
/* create a device tree from the image */
STATIC_INLINE_DEVICES void
update_device_tree_for_section(bfd *abfd,
asection *the_section,
PTR obj)
update_for_binary_section(bfd *abfd,
asection *the_section,
PTR obj)
{
unsigned_word section_vma;
unsigned_word section_size;
@ -1208,17 +1210,17 @@ update_device_tree_for_section(bfd *abfd,
/* find where it is to go */
section_vma = bfd_get_section_vma(abfd, the_section);
TRACE(trace_device_tree,
("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
bfd_get_section_name(abfd, the_section),
section_vma, section_size,
bfd_get_section_flags(abfd, the_section),
bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
));
DTRACE(binary,
("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
bfd_get_section_name(abfd, the_section),
section_vma, section_size,
bfd_get_section_flags(abfd, the_section),
bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
));
/* determine the devices access */
access = access_read;
@ -1251,7 +1253,7 @@ update_device_tree_for_section(bfd *abfd,
}
if (me->parent->callback->dma_write_buffer(me->parent,
section_init,
0 /*address_space*/,
0 /*space*/,
section_vma,
section_size,
1 /*violate_read_only*/)
@ -1268,9 +1270,10 @@ binary_init_callback(const device *me,
{
char file_name[100];
bfd *image;
DTRACE_INIT(binary);
/* get a file name */
if (scand_c(me->name, file_name) != 1)
if (scand_c(me->name, file_name, sizeof(file_name)) != 1)
error("load_binary_init_callback() invalid load-binary device %s\n",
me->name);
@ -1291,7 +1294,7 @@ binary_init_callback(const device *me,
/* and the data sections */
bfd_map_over_sections(image,
update_device_tree_for_section,
update_for_binary_section,
(PTR)me);
bfd_close(image);
@ -1371,18 +1374,17 @@ write_stack_arguments(psim *system,
unsigned_word start_arg,
unsigned_word end_arg)
{
TRACE(trace_create_stack,
("write_stack_arguments() - %s=0x%x %s=0x%x %s=0x%x %s=0x%x\n",
"system", system, "arg", arg,
"start_block", start_block, "start_arg", start_arg));
DTRACE(stack,
("write_stack_arguments(system=0x%x, arg=0x%x, start_block=0x%x, end_block=0x%x, start_arg=0x%x, end_arg=0x%x)\n",
system, arg, start_block, end_block, start_arg, end_arg));
if (arg == NULL)
error("write_arguments: character array NULL\n");
/* only copy in arguments, memory is already zero */
for (; *arg != NULL; arg++) {
int len = strlen(*arg)+1;
unsigned_word target_start_block;
TRACE(trace_create_stack,
("write_stack_arguments - write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
DTRACE(stack,
("write_stack_arguments() write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
"**arg", *arg, "start_block", start_block,
"len", len, "start_arg", start_arg));
if (psim_write_memory(system, 0, *arg,
@ -1402,6 +1404,8 @@ write_stack_arguments(psim *system,
if (start_block != end_block
|| ALIGN_8(start_arg) != end_arg)
error("write_stack_arguments - possible corruption\n");
DTRACE(stack,
("write_stack_arguments() = void\n"));
}
STATIC_INLINE_DEVICES void
@ -1500,10 +1504,16 @@ stack_ioctl_callback(const device *me,
stack_pointer = va_arg(ap, unsigned_word);
argv = va_arg(ap, char **);
envp = va_arg(ap, char **);
va_end(ap);
DTRACE(stack,
("stack_ioctl_callback(me=0x%x:%s, system=0x%x, processor=0x%x, cia=0x%x, argv=0x%x, envp=0x%x)\n",
me, me->full_name, system, processor, cia, argv, envp));
if (strcmp(me->name, "stack@elf") == 0)
create_elf_stack_frame(system, stack_pointer, argv, envp);
else if (strcmp(me->name, "stack@xcoff") == 0)
create_aix_stack_frame(system, stack_pointer, argv, envp);
DTRACE(stack,
("stack_ioctl_callback() = void\n"));
}
@ -1529,6 +1539,7 @@ static device_callbacks const stack_callbacks = {
typedef const device *(device_creator)
(const char *name,
const char *full_name,
const device *parent);
typedef struct _device_descriptor device_descriptor;
@ -1540,7 +1551,7 @@ struct _device_descriptor {
static device_descriptor devices[] = {
{ "console", console_create, NULL },
{ "memory", memory_create, NULL },
{ "memory", NULL, &memory_callbacks },
{ "vm", vea_vm_create, NULL },
{ "halt", NULL, &halt_callbacks },
{ "icu", NULL, &icu_callbacks },
@ -1559,6 +1570,7 @@ static device_descriptor devices[] = {
INLINE_DEVICES const device *
device_create(const char *name,
const char *full_name,
const device *parent)
{
device_descriptor *device;
@ -1571,9 +1583,10 @@ device_create(const char *name,
&& (device->name[name_len] == '\0'
|| device->name[name_len] == '@'))
if (device->creator != NULL)
return device->creator(name, parent);
return device->creator(name, full_name, parent);
else
return device_create_from(name,
full_name,
NULL /* data */,
device->callbacks,
parent);
@ -1585,12 +1598,14 @@ device_create(const char *name,
INLINE_DEVICES const device *
device_create_from(const char *name,
const char *full_name,
void *data,
const device_callbacks *callback,
const device *parent)
{
device *me = ZALLOC(device);
me->name = strdup(name);
me->full_name = strdup(full_name);
me->data = data;
me->callback = callback;
me->parent = parent;

View File

@ -79,6 +79,10 @@ typedef void (device_init_callback)
(const device *me,
psim *system);
#define DTRACE_INIT(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_init(me=0x%x:%s system=0x%x)\n", \
me, me->full_name, system))
/* Data transfers:
@ -160,17 +164,27 @@ typedef void (device_init_callback)
typedef void (device_config_address_callback)
(const device *me,
const char *name,
attach_type type,
int address_space,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
const device *who); /*callback/default*/
#define DTRACE_ATTACH_ADDRESS(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_attach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
#define DTRACE_DETACH_ADDRESS(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_detach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
typedef unsigned (device_io_read_buffer_callback)
(const device *me,
void *dest,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
@ -179,27 +193,46 @@ typedef unsigned (device_io_read_buffer_callback)
typedef unsigned (device_io_write_buffer_callback)
(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia);
#define DTRACE_IO_READ_BUFFER(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_io_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
me, me->full_name, dest, space, addr, nr_bytes, processor, cia))
#define DTRACE_IO_WRITE_BUFFER(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_io_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
me, me->full_name, source, space, addr, nr_bytes, processor, cia))
typedef unsigned (device_dma_read_buffer_callback)
(const device *me,
void *dest,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes);
typedef unsigned (device_dma_write_buffer_callback)
(const device *me,
const void *source,
int address_space,
int space,
unsigned_word addr,
unsigned nr_bytes,
int violate_read_only_section);
#define DTRACE_DMA_READ_BUFFER(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_dma_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
me, me->full_name, dest, space, addr, nr_bytes))
#define DTRACE_DMA_WRITE_BUFFER(OBJECT) \
DTRACE(OBJECT, \
(#OBJECT "_dma_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
me, me->full_name, source, space, addr, nr_bytes))
/* Interrupts:
@ -282,7 +315,8 @@ typedef struct _device_callbacks {
/* A device */
struct _device {
const char *name; /* eg rom@0x1234, 0x400 */
const char *name; /* eg rom@0x1234,0x400 */
const char *full_name; /* eg /isa/rom@0x1234,0x400 */
void *data; /* device specific data */
const device_callbacks *callback;
const device *parent;
@ -293,12 +327,14 @@ struct _device {
INLINE_DEVICES const device *device_create
(const char *name,
const char *full_name,
const device *parent);
/* create a new device using the parameterized data */
INLINE_DEVICES const device *device_create_from
(const char *name,
const char *full_name,
void *data,
const device_callbacks *callback,
const device *parent);

View File

@ -19,15 +19,9 @@
*/
#ifndef _SYSTEM_H_
#define _SYSTEM_H_
#ifndef _EMUL_NETBSD_H_
#define _EMUL_NETBSD_H_
#ifndef INLINE_SYSTEM
#define INLINE_SYSTEM
#endif
INLINE_SYSTEM void system_call
(cpu *processor,
unsigned_word cia);
extern emulation emul_netbsd;
#endif

File diff suppressed because it is too large Load Diff

49
sim/ppc/os_emul.c Normal file
View File

@ -0,0 +1,49 @@
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _OS_EMUL_C_
#define _OS_EMUL_C_
#include "cpu.h"
#include "idecode.h"
#include "os_emul.h"
#include "emul_generic.h"
#include "emul_netbsd.h"
#ifndef STATIC_INLINE_OS_EMUL
#define STATIC_INLINE_OS_EMUL STATIC_INLINE
#endif
INLINE_OS_EMUL void
os_emul_call(cpu *processor,
unsigned_word cia)
{
emulation *emul = &emul_netbsd;
emul_do_call(emul,
cpu_registers(processor)->gpr[0],
3, /*r3 contains arg0*/
processor,
cia);
}
#endif /* _OS_EMUL_C_ */

41
sim/ppc/os_emul.h Normal file
View File

@ -0,0 +1,41 @@
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _OS_EMUL_H_
#define _OS_EMUL_H_
#ifndef INLINE_OS_EMUL
#define INLINE_OS_EMUL
#endif
typedef struct _os_emul *os_emul;
INLINE_OS_EMUL os_emul *os_emul_create
(char *emulation_name);
INLINE_OS_EMUL void os_emul_init
(os_emul *emulation);
INLINE_OS_EMUL void os_emul_call
(cpu *processor,
unsigned_word cia);
#endif

85
sim/ppc/ppc-cache-rules Normal file
View File

@ -0,0 +1,85 @@
#
# This file is part of the program psim.
#
# Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# Instruction unpacking:
#
# Once the instruction has been decoded, the register (and other)
# fields within the instruction need to be extracted.
#
# The table that follows determines how each field should be treated.
# Importantly it considers the case where the extracted field is to
# be used immediatly or stored in an instruction cache.
#
# <valid>
#
# Zero marks the end of the table. More importantly 1. indicates
# that the entry is valid and can be cached. 2. indicates that that
# the entry is valid but can not be cached.
#
# <old_name>
#
# The field name as given in the instruction spec.
#
# <new_name>
#
# A name for <old_name> once it has been extracted from the
# instructioin (and possibly stored in the instruction cache).
#
# <type>
#
# String specifying the storage type for <new_name> (the extracted
# field>.
#
# <expression>
#
# Specifies how to get <new_name> from <old_name>. If null, old and
# new name had better be the same. */
#
#
1:RA:RA::
1:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA)
1:RT:RT::
1:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT)
2:RS:RS::
1:RS:rS:signed_word *:(cpu_registers(processor)->gpr + RS)
2:RB:RB::
1:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB)
2:FRA:FRA::
1:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA)
2:FRB:FRB::
1:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB)
2:FRC:FRC::
1:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC)
2:FRS:FRS::
1:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS)
2:FRT:FRT::
1:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT)
1:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction)
2:BI:BI::
1:BI:BIT32_BI::BIT32(BI)
2:BA:BA::
1:BA:BIT32_BA::BIT32(BA)
2:BB:BB::
1:BB:BIT32_BB::BIT32(BB)
1:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3)
#1:BD:CIA_plus_EXTS_BD_0b00:unsigned_word:CIA + EXTS(BD_0b00)
1:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
1:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction))
1:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3)

View File

@ -33,7 +33,7 @@
#include "ppc-endian.h"
#include "sim_callbacks.h"
#if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
#if !defined(SWAP_2) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
#define SWAP_2(SET,RAW) SET htons (RAW)
#endif
@ -67,7 +67,7 @@ endian_##NAME##_##BYTE_SIZE(unsigned_##BYTE_SIZE raw_in) \
return raw_in; \
} \
else { \
SWAP_##BYTE_SIZE(return, raw_in); \
SWAP_##BYTE_SIZE(return,raw_in); \
} \
}
#endif

View File

@ -0,0 +1,95 @@
#
# This file is part of the program psim.
#
# Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Instruction decode:
#
# The table that follows is used by gen to construct a decision tree
# that can identify each possible instruction. Gen then outputs this
# decision tree as (according to config) a table or switch statement
# as the function idecode.
#
# In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
# determines of the semantic functions themselves should be expanded
# in a similar way.
#
# The table contains the following entries:
#
# <valid>
#
# Must be 1 for the entry to be considered. The last entry must be
# zero.
#
# <first>
# <last>
#
# Range of bits (within the instruction) that should be searched for
# an instruction field. Within such ranges, gen looks for opcodes
# (constants), registers (strings) and reserved bits (slash) and
# according to the rules that follows includes or excludes them from
# a possible instruction field.
#
# <force_first>
# <force_last>
#
# If an instructioin field was found, enlarge the field size so that
# it is forced to at least include bits starting from <force_first>
# (<force_last>). To stop this occuring, use <force_first> = <last>
# + 1 and <force_last> = <first> - 1.
#
# <force_slash>
#
# Treat `/' fields as a constant instead of variable when looking for
# an instruction field.
#
# <force_expansion>
#
# Treat any contained register (string) fields as constant when
# determining the instruction field. For the instruction decode (and
# controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
# what would otherwize be non constant bits of an instruction.
#
# <use_switch>
#
# Should this table be expanded using a switch statement (val 1) and
# if so, should it be padded with entries so as to force the compiler
# to generate a jump table (val 2).
#
# <special_mask>
# <special_value>
# <special_rule>
#
# Special rule to fine tune how specific (or groups) of instructions
# are expanded. The applicability of the rule is determined by
#
# <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
#
# Where <instruction> is obtained by looking only at constant fields
# with in an instructions spec. When determining an expansion, the
# rule is only considered when a node contains a single instruction.
# <special_rule> can be any of:
#
# 0: for this instruction, expand by earlier rules
# 1: expand bits <force_low> .. <force_hi> only
# 2: boolean expansion of only zero/non-zero cases
#
0: 5: 0: 5:0:: 0:0x00000000:0x00000000:0
21:31:32:-1:0:OE,LR,AA,Rc,LK:0:0x00000000:0x00000000:0
6: 9: 6: 9:0:BO: 0:0xfc000000:0x40000000:1
11:15:11:15:0:RA: 0:0xfc000000:0x38000000:2
11:15:11:15:0:RA: 0:0xfc000000:0x3c000000:2

92
sim/ppc/ppc-opcode-simple Normal file
View File

@ -0,0 +1,92 @@
#
# This file is part of the program psim.
#
# Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Instruction decode:
#
# The table that follows is used by gen to construct a decision tree
# that can identify each possible instruction. Gen then outputs this
# decision tree as (according to config) a table or switch statement
# as the function idecode.
#
# In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
# determines of the semantic functions themselves should be expanded
# in a similar way.
#
# The table contains the following entries:
#
# <valid>
#
# Must be 1 for the entry to be considered. The last entry must be
# zero.
#
# <first>
# <last>
#
# Range of bits (within the instruction) that should be searched for
# an instruction field. Within such ranges, gen looks for opcodes
# (constants), registers (strings) and reserved bits (slash) and
# according to the rules that follows includes or excludes them from
# a possible instruction field.
#
# <force_first>
# <force_last>
#
# If an instructioin field was found, enlarge the field size so that
# it is forced to at least include bits starting from <force_first>
# (<force_last>). To stop this occuring, use <force_first> = <last>
# + 1 and <force_last> = <first> - 1.
#
# <force_slash>
#
# Treat `/' fields as a constant instead of variable when looking for
# an instruction field.
#
# <force_expansion>
#
# Treat any contained register (string) fields as constant when
# determining the instruction field. For the instruction decode (and
# controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
# what would otherwize be non constant bits of an instruction.
#
# <use_switch>
#
# Should this table be expanded using a switch statement (val 1) and
# if so, should it be padded with entries so as to force the compiler
# to generate a jump table (val 2).
#
# <special_mask>
# <special_value>
# <special_rule>
#
# Special rule to fine tune how specific (or groups) of instructions
# are expanded. The applicability of the rule is determined by
#
# <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
#
# Where <instruction> is obtained by looking only at constant fields
# with in an instructions spec. When determining an expansion, the
# rule is only considered when a node contains a single instruction.
# <special_rule> can be any of:
#
# 0: for this instruction, expand by earlier rules
# 1: expand bits <force_low> .. <force_hi> only
# 2: boolean expansion of only zero/non-zero cases
#
0: 5: 0: 5:0:: 1:0x00000000:0x00000000:0
21:31:32:-1:0:: 1:0x00000000:0x00000000:0

758
sim/ppc/spa-reporter.c Normal file
View File

@ -0,0 +1,758 @@
/*
* Copyright (C) 1991 Gordon Irlam. All rights reserved.
*/
/*
* Sparc trace generator.
*
* Generate a Sparc address trace.
*
* Report system calls.
*
* We want to display the system call and the return value at the same time
* (so that other output does not appear between the two) but also want to
* identify system calls that block without having to wait for them to
* return. Whenever a system call is performed we store the name of the
* call and the parameters. If we don't see a return within a certain time
* period we display the call regardless, and assume it has blocked.
*/
/*
* Imported declarations.
*/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <malloc.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <machine/trap.h>
/*
* sigcleanup is not defined in a system header file.
*/
#define SYS_sigcleanup 139
#include "prototype.h"
#include "error.h"
#include "spy.h"
#include "system_calls.h"
/*
* Forward declarations.
*/
PROTOTYPE(void report_trap,
(int pid, void *addr, int trap, int g1, syscall_params *params));
PROTOTYPE(void report_trap_result, (int pid, int error, int o0, int o1));
PROTOTYPE(void display_trap_msg, (void));
PROTOTYPE(void delayed_trap_msg, (void));
PROTOTYPE(void discard_trap_msg, (void));
PROTOTYPE(int copy_memory, (int pid, void *addr, int size, char *data));
PROTOTYPE(char *snarf_string, (int pid, void *addr));
PROTOTYPE(char *snarf_data, (int pid, void *addr, int size));
PROTOTYPE(char *format_value,
(int pid, fmt_type format, unsigned long value, int opt));
PROTOTYPE(int printable_data, (char *data, int size));
PROTOTYPE(char *print_string, (char *data, int size));
/*
* Global definitions.
*/
static char *trap_msg = NULL;
static fmt_type result_format;
static int no_return;
static fmt_type post_fmt;
static unsigned long post_value;
static int post_size;
/*
* Report the occurence of the specified trap.
*/
void report_trap(pid, addr, trap, g1, params_addr)
int pid;
void *addr;
int trap;
int g1;
syscall_params *params_addr;
{
syscall_params params;
call_desc *call;
int i;
fmt_type arg_format;
char *arg_str;
/*
* Display any previous trap message that is still pending (it might have
* been a trap that did not return a value, and so has not yet been
* displayed).
*/
display_trap_msg();
/*
* Read the parameters, and construct a string describing the system call.
*/
ensure(ptrace(PTRACE_READDATA, pid,
(char *) params_addr, sizeof(syscall_params),
(char *) params) != -1);
no_return = 0;
if (trap != T_SOFTWARE_TRAP) {
/*
* Not a system call trap.
*/
no_return = 1;
ensure((trap_msg = malloc(17 + 20 + 1)) != NULL);
sprintf(trap_msg, "0x%08lx: trap %d", (unsigned long) addr, trap);
result_format = fmt_unknown;
} if ((g1 < 0) || (g1 >= no_system_calls)) {
/*
* An unknown system call.
*/
ensure((trap_msg = malloc(21 + 20 + 1)) != NULL);
sprintf(trap_msg, "0x%08lx: _unknown_%d(",
(unsigned long) addr, g1);
arg_str = format_value(pid, fmt_unknown, params[0], 0);
ensure((trap_msg = realloc(trap_msg, strlen(trap_msg)
+ strlen(arg_str) + 1 + 1))
!= NULL);
sprintf(trap_msg + sizeof(trap_msg), "%s)", arg_str);
free(arg_str);
result_format = fmt_unknown;
} else {
/*
* A known system call.
*/
call = &system_calls[g1];
switch (g1) {
case SYS_open :
if (!(params[1] & O_CREAT)) {
call = &system_call_open_simple;
}
break;
case SYS_exit :
case SYS_execve :
case SYS_sigcleanup :
no_return = 1;
break;
default :
break;
}
ensure((trap_msg = malloc(13 + strlen(call->name) + 1 + 1))
!= NULL);
sprintf(trap_msg, "0x%08lx: %s(",
(unsigned long) addr, call->name);
/*
* Display each of the arguments.
*/
for (i = 0; i < NO_PARAMS; i++) {
if ((arg_format = call->arg[i]) == fmt_none) {
break;
}
if (i > 0) {
strcat(trap_msg, ", ");
}
if (arg_format == fmt_data) {
assert(((i + 1) < NO_PARAMS) &&
(call->arg[i + 1] == fmt_data_size));
arg_str = format_value(pid, arg_format,
params[i], (int) params[i + 1]);
} else {
arg_str = format_value(pid, arg_format, params[i], 0);
}
ensure((trap_msg = realloc(trap_msg, strlen(trap_msg) +
strlen(arg_str) + 2 + 1))
!= NULL);
strcat(trap_msg, arg_str);
free(arg_str);
}
strcat(trap_msg, ")");
result_format = call->result;
}
/*
* Set alarm so that name of call will be displayed even if it blocks.
*/
alarm((unsigned int) 1);
}
/*
* Report the value returned as a result of the most recent trap.
*/
void report_trap_result(pid, error, o0, o1)
int pid;
int error;
int o0;
int o1;
{
char *result, *eno, *emsg, *addr;
/*
* Turn off alarm used to ensure we print the call promptly - we are about
* to print it now.
*/
alarm((unsigned int) 0);
/*
* See if previous call blocked.
*/
if (trap_msg == NULL) {
ensure((trap_msg = strdup(" [previous call]")) != NULL);
}
/*
* Work out error message (if any) to be printed following return value.
*/
if (error) {
eno = format_value(pid, fmt_error, o0, 0);
ensure((emsg = malloc(9 + strlen(eno) + 1)) != NULL);
sprintf(emsg, " [error %s]", eno);
free(eno);
o0 = -1;
post_fmt = fmt_none;
} else {
ensure((emsg = strdup("")) != NULL);
}
/*
* Print out all the details of the system call.
*/
if (result_format == fmt_none) {
ensure(fprintf(msgfile, "%s: %s%s\n", trace_progname, trap_msg, emsg)
!= EOF);
} else {
result = format_value(pid, result_format, o0, 0);
ensure(fprintf(msgfile, "%s: %s -> %s%s\n",
trace_progname, trap_msg, result, emsg) != EOF);
free(result);
}
free(emsg);
/*
* Display any string or buffer modified by the system call if required.
* And providing it can be displayed as a (non-null) string.
*/
if (post_fmt != fmt_none) {
result = format_value(pid, post_fmt, post_value, post_size);
if ((result[0] == '"') && (strlen(result) > 2)) {
addr = format_value(pid, fmt_ptr, post_value, 0);
ensure(fprintf(msgfile, "%s: %s: %s\n",
trace_progname, addr, result) != EOF);
free(addr);
}
free(result);
post_fmt = fmt_none;
}
free(trap_msg);
trap_msg = NULL;
}
/*
* Report any trap messages that haven't been reported yet.
*/
void display_trap_msg() {
/*
* Clear the alarm - we are about to print the message.
*/
alarm((unsigned int) 0);
if (trap_msg != NULL) {
ensure(fprintf(msgfile, "%s: %s\n", trace_progname, trap_msg) != EOF);
free(trap_msg);
trap_msg = NULL;
}
}
/*
* Report the completion of a trap message as being delayed.
*
* This routine is invoked when a SIGALRM is received.
*/
void delayed_trap_msg() {
assert(trap_msg != NULL);
/*
* If the call was not expected to return a value, think nothing of it,
* otherwise assume the call has blocked.
*/
ensure(fprintf(msgfile, "%s: %s%s\n",
trace_progname, trap_msg, (no_return ? "" : " [pending]"))
!= EOF);
free(trap_msg);
trap_msg = NULL;
}
/*
* Discard any pending trap messages.
*
* This routine is used by the child of a fork to discard the fork system call
* record.
*/
void discard_trap_msg() {
trap_msg = NULL;
}
/*
* Attempt to copy size bytes from the target process to data. The number of
* bytes successfully copied is returned.
*/
int copy_memory(pid, addr, size, data)
int pid;
void *addr;
int size;
char *data;
{
int lo, hi, try;
assert(size >= 0);
/*
* Common cases first.
*/
if (ptrace(PTRACE_READDATA, pid, (char *) addr, size, data) != -1) {
return size;
} else if (ptrace(PTRACE_READDATA, pid, (char *) addr, 1, data) == -1) {
return 0;
}
/*
* Binary search.
*/
lo = 1;
hi = size - 1;
while (lo < hi) {
try = (lo + hi + 1) / 2;
if (ptrace(PTRACE_READDATA, pid, (char *) addr, try, data) != -1) {
lo = try;
} else {
hi = try - 1;
}
}
ensure(ptrace(PTRACE_READDATA, pid, (char *) addr, lo, data) != -1);
return lo;
}
/*
* Create a string representing the contents of the indicated null termintated
* region of memory.
*/
char *snarf_string(pid, addr)
int pid;
void *addr;
{
char data[STRING_SIZE_LIMIT + 1];
int size, len;
char *result = NULL;
int too_long = 0;
size = copy_memory(pid, addr, STRING_SIZE_LIMIT, data);
data[size] = '\0';
len = strlen(data);
too_long = (len == STRING_SIZE_LIMIT);
if ((len < size) || too_long) {
if (printable_data(data, len)) {
result = print_string(data, len);
if (too_long) {
ensure((result = realloc(result, strlen(result) + 2 + 1))
!= NULL);
strcat(result, "..");
}
}
}
return result;
}
/*
* Create a string representing the contents of the indicated length delimited
* region of memory.
*/
char *snarf_data(pid, addr, size)
int pid;
void *addr;
int size;
{
char data[DATA_SIZE_LIMIT];
char *result = NULL;
int too_long = 0;
if (size > DATA_SIZE_LIMIT) {
size = DATA_SIZE_LIMIT;
too_long = 1;
}
if ((size >= 0) && (copy_memory(pid, addr, size, data) == size)) {
if (printable_data(data, size)) {
result = print_string(data, size);
if (too_long) {
ensure((result = realloc(result, strlen(result) + 2 + 1))
!= NULL);
strcat(result, "..");
}
}
}
return result;
}
/*
* Create a string representing the contents of the indicated null termintated
* array of pointers to null terminated regions of memory.
*/
char *snarf_string_array(pid, addr)
int pid;
void *addr;
{
char *data[ARRAY_SIZE_LIMIT + 1];
int size, len, i;
char *result = NULL;
char *s;
int too_long = 0;
size = copy_memory(pid, addr, ARRAY_SIZE_LIMIT * sizeof(char *),
(char *) data) / sizeof(char *);
data[size] = NULL;
for (len = 0; data[len] != NULL; len++) {
}
too_long = (len == ARRAY_SIZE_LIMIT);
if ((len < size) || too_long) {
ensure((result = strdup("{")) != NULL);
for (i = 0; i < len; i++) {
if (i > 0) {
strcat(result, ", ");
}
s = format_value(pid, fmt_string, (unsigned long) data[i], 0);
ensure((result = realloc(result,
strlen(result) + strlen(s) + 2 + 5 + 1))
!= NULL);
strcat(result, s);
}
if (too_long) {
strcat(result, ", ..");
}
strcat(result, "}");
}
return result;
}
/*
* Return a string containing a value printed in a specific format. Opt is a
* second optional parameter currently only used to contain the size to be used
* with fmt_data.
*/
char *format_value(pid, format, value, opt)
int pid;
fmt_type format;
unsigned long value;
int opt;
{
char *str;
int sig, error;
/*
* See if we are meant to hang on to the value for later use.
*/
switch (format) {
case fmt_post_string :
post_fmt = fmt_string ;
post_value = value;
format = fmt_ptr;
break;
case fmt_post_data :
post_fmt = fmt_data;
post_value = value;
format = fmt_ptr;
break;
case fmt_data_size :
format = FMT_SIZE;
break;
case fmt_post_data_size :
post_size = (int) value;
format = FMT_SIZE;
break;
default :
break;
}
/*
* Display the value.
*/
switch (format) {
case fmt_dec :
ensure((str = malloc(20 + 1)) != NULL);
sprintf(str, "%d", (int) value);
break;
case fmt_hex :
ensure((str = malloc(2 + 20 + 1)) != NULL);
sprintf(str, "0x%lx", value);
break;
case fmt_ptr :
if (value == 0) {
ensure((str = strdup("NULL")) != NULL);
} else {
ensure((str = malloc(10 + 1)) != NULL);
sprintf(str, "0x%08lx", value);
}
break;
case fmt_fd :
ensure((str = malloc(2 + 20 + 1)) != NULL);
sprintf(str, "fd%d", (int) value);
break;
case fmt_signal :
sig = (int) value;
if ((sig < 0) || (sig >= no_signal_names)) {
ensure((str = malloc(20 + 1)) != NULL);
sprintf(str, "%d", sig);
} else {
ensure((str = strdup(signal_names[sig])) != NULL);
}
break;
case fmt_error :
error = (int) value;
if ((error < 0) || (error >= no_error_names)) {
ensure((str = malloc(20 + 1)) != NULL);
sprintf(str, "%d", error);
} else {
ensure((str = strdup(error_names[error])) != NULL);
}
break;
case fmt_open_flags :
ensure((str = malloc(8 + 3 + 20 + 1)) != NULL);
switch (value & 3) {
case O_RDONLY :
sprintf(str, "O_RDONLY");
value -= O_RDONLY;
break;
case O_WRONLY :
sprintf(str, "O_WRONLY");
value -= O_WRONLY;
break;
case O_RDWR :
sprintf(str, "O_RDWR");
value -= O_RDWR;
break;
default :
sprintf(str, "0x%lx", value);
value = 0;
break;
}
if (value != 0) {
sprintf(str + strlen(str), "|0x%lx", value);
}
break;
case fmt_unknown :
ensure((str = strdup("..")) != NULL);
break;
case fmt_string :
if ((str = snarf_string(pid, (void *) value)) == NULL) {
str = format_value(pid, fmt_ptr, value, 0);
}
break;
case fmt_data :
if ((str = snarf_data(pid, (void *) value, opt)) == NULL) {
str = format_value(pid, fmt_ptr, value, 0);
}
break;
case fmt_string_array :
if ((str = snarf_string_array(pid, (void *) value)) == NULL) {
str = format_value(pid, fmt_ptr, value, 0);
}
break;
default :
diagnose("Unexpected display format");
break;
}
return str;
}
/*
* Determine whether size bytes of data are printable.
*/
int printable_data(data, size)
char *data;
int size;
{
int i;
for (i = 0; i < size; i++) {
if (!(isprint(data[i]))) {
switch (data[i]) {
case '\0' :
case '\t' :
case '\n' :
case '\f' :
case '\r' :
break;
default :
return 0;
break;
}
}
}
return 1;
}
/*
* Create a string representing size bytes of data.
*/
char *print_string(data, size)
char *data;
int size;
{
char *str, *s;
int i;
assert(size >= 0);
ensure((str = malloc(1 + size * 2 + 1 + 1)) != NULL);
s = str;
*(s++) = '"';
for (i = 0; i < size; i++) {
if ((!(isprint(data[i]))) || (data[i] == '"') || (data[i] == '\\')) {
*(s++) = '\\';
switch (data[i]) {
case '\0' :
*(s++) = '0';
break;
case '\t' :
*(s++) = 't';
break;
case '\n' :
*(s++) = 'n';
break;
case '\f' :
*(s++) = 'f';
break;
case '\r' :
*(s++) = 'r';
break;
case '"' :
case '\\' :
*(s++) = data[i];
break;
default :
diagnose("Attempted to display illegal character");
}
} else {
*(s++) = data[i];
}
}
*(s++) = '"';
*s = '\0';
return str;
}

499
sim/ppc/spa-system-calls.c Normal file
View File

@ -0,0 +1,499 @@
/*
* Copyright (C) 1991 Gordon Irlam. All rights reserved.
*/
/*
* Definition of system calls for sparc trace generator.
*/
/*
* Imported declarations.
*/
#include "system_calls.h"
/*
* Table containing system calls, and their parameter profile.
*/
call_desc system_calls[] = {
/* 0 */ {"syscall", {fmt_dec, fmt_unknown}, fmt_dec},
/* 1 */ {"_exit", {fmt_dec}, fmt_none},
/* 2 */ {"fork", {fmt_none}, fmt_dec},
/* 3 */ {"read", {fmt_fd, fmt_post_data, FMT_SIZE}, fmt_post_data_size},
/* 4 */ {"write", {fmt_fd, fmt_data, fmt_data_size}, FMT_SIZE},
/* 5 */ {"open", {fmt_string, fmt_open_flags, FMT_FLAGS}, fmt_fd},
/* 6 */ {"close", {fmt_fd}, FMT_STATUS},
/* 7 */ {"wait4", {fmt_dec, fmt_ptr, FMT_FLAGS, fmt_ptr}, fmt_dec},
/* 8 */ {"creat", {fmt_string, FMT_FLAGS}, fmt_fd},
/* 9 */ {"link", {fmt_string, fmt_string}, FMT_STATUS},
/* 10 */ {"unlink", {fmt_string}, FMT_STATUS},
/* 11 */ {"_unknown_11[\"old execv\"]", {fmt_unknown}, fmt_unknown},
/*
* execv is now a library routine which calls execve, although
* Sun have not officially declared execv obsolete.
*/
/* 12 */ {"chdir", {fmt_string}, FMT_STATUS},
/* 13 */ {"_unknown_13[\"old time\"]", {fmt_unknown}, fmt_unknown},
/* 14 */ {"mknod", {fmt_string, FMT_FLAGS, FMT_FLAGS}, FMT_STATUS},
/* 15 */ {"chmod", {fmt_string, FMT_FLAGS}, FMT_STATUS},
/* 16 */ {"chown", {fmt_string, fmt_dec, fmt_dec}, FMT_STATUS},
/* 17 */ {"_brk", {fmt_ptr}, FMT_STATUS},
/* 18 */ {"_unknown_18[\"old stat\"]", {fmt_unknown}, fmt_unknown},
/* 19 */ {"lseek", {fmt_fd, FMT_SIZE, fmt_dec}, FMT_SIZE},
/* 20 */ {"getpid", {fmt_none}, fmt_dec},
/* 21 */ {"_unknown_21", {fmt_unknown}, fmt_unknown},
/* 22 */ {"umount[\"System V\"]", {fmt_string}, FMT_STATUS},
/* 23 */ {"_unknown_23[\"old setuid\"]", {fmt_unknown}, fmt_unknown},
/* 24 */ {"getuid", {fmt_none}, fmt_dec},
/* 25 */ {"_unknown_25[\"old System V stime\"]",
{fmt_unknown},
fmt_unknown},
/* 26 */ {"ptrace",
{fmt_dec, fmt_dec, fmt_ptr, fmt_dec, fmt_ptr},
fmt_dec},
/* 27 */ {"_unknown_27[\"old alarm\"]", {fmt_unknown}, fmt_unknown},
/* 28 */ {"_unknown_28[\"old fstat\"]", {fmt_unknown}, fmt_unknown},
/* 29 */ {"_unknown_29[\"old pause\"]", {fmt_unknown}, fmt_unknown},
/* 30 */ {"_unknown_30[\"old utime\"]", {fmt_unknown}, fmt_unknown},
/* 31 */ {"_unknown_31", {fmt_unknown}, fmt_unknown},
/* 32 */ {"_unknown_32", {fmt_unknown}, fmt_unknown},
/* 33 */ {"access", {fmt_string, FMT_FLAGS}, FMT_STATUS},
/* 34 */ {"_unknown_34[\"old nice\"]", {fmt_unknown}, fmt_unknown},
/* 35 */ {"_unknown_35[\"old ftime\"]", {fmt_unknown}, fmt_unknown},
/* 36 */ {"sync", {fmt_none}, fmt_none},
/* 37 */ {"kill", {fmt_dec, fmt_signal}, FMT_STATUS},
/* 38 */ {"stat", {fmt_string, fmt_ptr}, FMT_STATUS},
/* 39 */ {"_unknown_39[\"old setpgrp\"]", {fmt_unknown}, fmt_unknown},
/* 40 */ {"lstat", {fmt_string, fmt_ptr}, FMT_STATUS},
/* 41 */ {"dup", {fmt_fd}, fmt_fd},
/*
* Sun sometimes claim dup has 2 parameters.
*/
/* 42 */ {"pipe", {fmt_ptr}, FMT_STATUS},
/* 43 */ {"_unknown_43[\"old times\"]", {fmt_unknown}, fmt_unknown},
/* 44 */ {"profil", {fmt_ptr, FMT_SIZE, fmt_ptr, fmt_dec}, FMT_STATUS},
/* 45 */ {"_unknown_45", {fmt_unknown}, fmt_unknown},
/* 46 */ {"_unknown_46[\"old setgid\"]", {fmt_unknown}, fmt_unknown},
/* 47 */ {"getgid", {fmt_none}, fmt_dec},
/* 48 */ {"_unknown_48[\"old signal\"]", {fmt_unknown}, fmt_unknown},
/* 49 */ {"_unknown_49", {fmt_unknown}, fmt_unknown},
/* 50 */ {"_unknown_50", {fmt_unknown}, fmt_unknown},
/* 51 */ {"acct", {fmt_string}, FMT_STATUS},
/* 52 */ {"_unknown_52", {fmt_unknown}, fmt_unknown},
/* 53 */ {"mctl", {fmt_ptr, FMT_SIZE, fmt_dec, FMT_FLAGS}, FMT_STATUS},
/* 54 */ {"ioctl", {fmt_fd, FMT_FLAGS, fmt_ptr}, fmt_dec},
/* 55 */ {"reboot", {FMT_FLAGS, fmt_string}, FMT_STATUS},
/* 56 */ {"_unknown_56[\"old wait3\"]", {fmt_unknown}, fmt_unknown},
/* 57 */ {"symlink", {fmt_string, fmt_string}, FMT_STATUS},
/* 58 */ {"readlink",
{fmt_string, fmt_post_data, FMT_SIZE},
fmt_post_data_size},
/* 59 */ {"execve",
{fmt_string, fmt_string_array, fmt_string_array},
FMT_STATUS},
/* 60 */ {"umask", {FMT_FLAGS}, FMT_FLAGS},
/* 61 */ {"chroot", {fmt_string}, FMT_STATUS},
/* 62 */ {"fstat", {fmt_fd, fmt_ptr}, FMT_STATUS},
/* 63 */ {"_unknown_63", {fmt_unknown}, fmt_unknown},
/* 64 */ {"getpagesize", {fmt_none}, FMT_SIZE},
/* 65 */ {"_unknown_65[\"old msync\"]", {fmt_unknown}, fmt_unknown},
/*
* msync is now a library routine which calls mctl, although
* Sun have not officially declared msync obsolete.
*/
/* 66 */ {"vfork", {fmt_none}, fmt_dec},
/* 67 */ {"_unknown_67[\"old vread\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think vread can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 68 */ {"_unknown_68[\"old vwrite\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think vwrite can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 69 */ {"_unknown_69[\"old brk\"]", {fmt_unknown}, fmt_unknown},
/*
* Also referred to as sbrk. I don't think it can be generated
* by the standard libararies, although Sun have not officially
* declared it obsolete.
*/
/* 70 */ {"_unknown_70[\"old sstk\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think sstk can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 71 */ {"mmap",
{fmt_ptr, fmt_post_data_size, FMT_FLAGS, FMT_FLAGS, fmt_fd,
FMT_SIZE},
fmt_post_data},
/* 72 */ {"vadvise", {fmt_dec}, FMT_STATUS},
/*
* vadvise is currently still a valid system call, although Sun
* have said it is likely to disappear in the future.
*/
/* 73 */ {"munmap", {fmt_ptr, FMT_SIZE}, FMT_STATUS},
/* 74 */ {"mprotect", {fmt_ptr, FMT_SIZE, FMT_FLAGS}, FMT_STATUS},
/* 75 */ {"_unknown_75[\"old madvise\"]", {fmt_unknown}, fmt_unknown},
/*
* madvise is now a library routine which calls mctl, although
* Sun have not officially declared madvise obsolete.
*/
/* 76 */ {"vhangup", {fmt_none}, FMT_STATUS},
/*
* Sun sometimes claim vhangup has 1 parameter.
*/
/* 77 */ {"_unknown_77[\"old vlimit\"]", {fmt_unknown}, fmt_unknown},
/* 78 */ {"mincore", {fmt_ptr, FMT_SIZE, fmt_ptr}, FMT_STATUS},
/* 79 */ {"getgroups", {fmt_dec, fmt_ptr}, fmt_dec},
/* 80 */ {"setgroups", {fmt_dec, fmt_ptr}, FMT_STATUS},
/* 81 */ {"getpgrp", {fmt_dec}, fmt_dec},
/* 82 */ {"setpgrp", {fmt_dec, fmt_dec}, FMT_STATUS},
/* 83 */ {"setitimer", {fmt_dec, fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 84 */ {"_unknown_84[\"old wait\"]", {fmt_unknown}, fmt_unknown},
/*
* wait is now a library routine which calls wait4, although Sun
* have not officially declared wait obsolete.
*/
/* 85 */ {"swapon", {fmt_string}, FMT_STATUS},
/* 86 */ {"getitimer", {fmt_dec, fmt_ptr}, FMT_STATUS},
/* 87 */ {"gethostname", {fmt_post_string, FMT_SIZE}, FMT_STATUS},
/* 88 */ {"sethostname", {fmt_data, fmt_data_size}, FMT_STATUS},
/* 89 */ {"getdtablesize", {fmt_none}, fmt_dec},
/* 90 */ {"dup2", {fmt_fd, fmt_dec}, fmt_fd},
/* 91 */ {"_unknown_91[\"old getdopt\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think getdopt can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 92 */ {"fcntl", {fmt_fd, fmt_dec, fmt_dec}, fmt_dec},
/* 93 */ {"select",
{fmt_dec, fmt_ptr, fmt_ptr, fmt_ptr, fmt_ptr},
fmt_dec},
/* 94 */ {"_unknown_94[\"old setdopt\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think setdopt can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 95 */ {"fsync", {fmt_fd}, FMT_STATUS},
/* 96 */ {"setpriority", {fmt_dec, fmt_dec, fmt_dec}, FMT_STATUS},
/* 97 */ {"socket", {fmt_dec, fmt_dec, fmt_dec}, fmt_fd},
/* 98 */ {"connect", {fmt_fd, fmt_ptr, FMT_SIZE}, FMT_STATUS},
/* 99 */ {"accept", {fmt_fd, fmt_ptr, fmt_ptr}, fmt_fd},
/* 100 */ {"getpriority", {fmt_dec, fmt_dec}, fmt_dec},
/* 101 */ {"send", {fmt_fd, fmt_data, fmt_data_size, FMT_FLAGS}, FMT_SIZE},
/* 102 */ {"recv",
{fmt_fd, fmt_post_data, FMT_SIZE, FMT_FLAGS},
fmt_post_data_size},
/* 103 */ {"_unknown_103", {fmt_unknown}, fmt_unknown},
/* 104 */ {"bind", {fmt_fd, fmt_ptr, FMT_SIZE}, FMT_STATUS},
/* 105 */ {"setsockopt",
{fmt_fd, fmt_dec, fmt_dec, fmt_ptr, FMT_SIZE},
FMT_STATUS},
/* 106 */ {"listen", {fmt_fd, fmt_dec}, FMT_STATUS},
/* 107 */ {"_unknown_107[\"old vtimes\"]", {fmt_unknown}, fmt_unknown},
/* 108 */ {"_sigvec", {fmt_signal, fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 109 */ {"sigblock", {fmt_hex}, fmt_hex},
/* 110 */ {"sigsetmask", {fmt_hex}, fmt_hex},
/* 111 */ {"sigpause", {fmt_hex}, FMT_STATUS},
/* 112 */ {"sigstack", {fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 113 */ {"recvmsg", {fmt_fd, fmt_ptr, FMT_FLAGS}, FMT_SIZE},
/* 114 */ {"sendmsg", {fmt_fd, fmt_ptr, FMT_FLAGS}, FMT_SIZE},
/* 115 */ {"_unknown_115[\"vtrace\"]",
{fmt_dec, fmt_hex, fmt_hex},
fmt_unknown},
/*
* I am unsure of the parameters for vtrace.
*/
/* 116 */ {"gettimeofday", {fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 117 */ {"getrusage", {fmt_dec, fmt_ptr}, FMT_STATUS},
/* 118 */ {"getsockopt",
{fmt_fd, fmt_dec, fmt_dec, fmt_ptr, fmt_ptr},
FMT_STATUS},
/* 119 */ {"_unknown_119", {fmt_unknown}, fmt_unknown},
/* 120 */ {"readv", {fmt_fd, fmt_ptr, fmt_dec}, FMT_SIZE},
/* 121 */ {"writev", {fmt_fd, fmt_ptr, fmt_dec}, FMT_SIZE},
/* 122 */ {"settimeofday", {fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 123 */ {"fchown", {fmt_fd, fmt_dec, fmt_dec}, FMT_STATUS},
/* 124 */ {"fchmod", {fmt_fd, FMT_FLAGS}, FMT_STATUS},
/* 125 */ {"recvfrom",
{fmt_fd, fmt_post_data, FMT_SIZE, FMT_FLAGS, fmt_ptr, fmt_ptr},
fmt_post_data_size},
/* 126 */ {"setreuid", {fmt_dec, fmt_dec}, FMT_STATUS},
/* 127 */ {"setregid", {fmt_dec, fmt_dec}, FMT_STATUS},
/* 128 */ {"rename", {fmt_string, fmt_string}, FMT_STATUS},
/* 129 */ {"truncate", {fmt_string, FMT_SIZE}, FMT_STATUS},
/* 130 */ {"ftruncate", {fmt_fd, FMT_SIZE}, FMT_STATUS},
/* 131 */ {"flock", {fmt_fd, FMT_FLAGS}, FMT_STATUS},
/* 132 */ {"_unknown_132", {fmt_unknown}, fmt_unknown},
/* 133 */ {"sendto",
{fmt_fd, fmt_data, fmt_data_size, FMT_FLAGS, fmt_ptr, FMT_SIZE},
FMT_SIZE},
/* 134 */ {"shutdown", {fmt_fd, fmt_dec}, FMT_STATUS},
/* 135 */ {"socketpair", {fmt_dec, fmt_dec, fmt_dec, fmt_ptr}, FMT_STATUS},
/*
* Sun sometimes claim socketpair has 5 parameters.
*/
/* 136 */ {"mkdir", {fmt_string, FMT_FLAGS}, FMT_STATUS},
/* 137 */ {"rmdir", {fmt_string}, FMT_STATUS},
/* 138 */ {"utimes", {fmt_string, fmt_ptr}, FMT_STATUS},
/* 139 */ {"_sigcleanup", {fmt_ptr}, FMT_STATUS},
/* 140 */ {"adjtime", {fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 141 */ {"getpeername", {fmt_fd, fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 142 */ {"gethostid", {fmt_none}, fmt_hex},
/*
* Sun sometimes claim gethostid has 2 parameters.
*/
/* 143 */ {"_unknown_143", {fmt_unknown}, fmt_unknown},
/* 144 */ {"getrlimit", {fmt_dec, fmt_ptr}, FMT_STATUS},
/* 145 */ {"setrlimit", {fmt_dec, fmt_ptr}, FMT_STATUS},
/* 146 */ {"killpg", {fmt_dec, fmt_signal}, FMT_STATUS},
/* 147 */ {"_unknown_147", {fmt_unknown}, fmt_unknown},
/* 148 */ {"_unknown_148[\"old quota\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think quota can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 149 */ {"_unknown_149[\"old qquota\"]", {fmt_unknown}, fmt_unknown},
/*
* I don't think qquota can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 150 */ {"getsockname", {fmt_fd, fmt_ptr, fmt_ptr}, FMT_STATUS},
/* 151 */ {"getmsg", {fmt_fd, fmt_ptr, fmt_ptr, fmt_ptr}, fmt_dec},
/* 152 */ {"putmsg", {fmt_fd, fmt_ptr, fmt_ptr, FMT_FLAGS}, FMT_STATUS},
/* 153 */ {"poll", {fmt_ptr, fmt_dec, fmt_dec}, fmt_dec},
/* 154 */ {"_unknown_154", {fmt_unknown}, fmt_unknown},
/* 155 */ {"nfssvc", {fmt_fd}, FMT_STATUS},
/* 156 */ {"_unknown_156[\"old getdirentries\"]",
{fmt_unknown},
fmt_unknown},
/*
* I don't think getdirentries can be generated by the standard
* libararies, although Sun have not officially declared it
* obsolete.
*/
/* 157 */ {"statfs", {fmt_string, fmt_ptr}, FMT_STATUS},
/* 158 */ {"fstatfs", {fmt_fd, fmt_ptr}, FMT_STATUS},
/* 159 */ {"unmount", {fmt_string}, FMT_STATUS},
/* 160 */ {"async_daemon", {fmt_none}, fmt_none},
/* 161 */ {"nfs_getfh", {fmt_hex, fmt_hex}, fmt_unknown},
/*
* I am unsure of the parameters for nfs_getfh.
*/
/* 162 */ {"getdomainname", {fmt_post_string, FMT_SIZE}, FMT_STATUS},
/* 163 */ {"setdomainname", {fmt_data, fmt_data_size}, FMT_STATUS},
/* 164 */ {"rtschedule",
{fmt_hex, fmt_hex, fmt_hex, fmt_hex, fmt_hex},
fmt_unknown},
/*
* I am unsure of the parameters for rtschedule.
*/
/* 165 */ {"quotactl",
{fmt_dec, fmt_string, fmt_dec, fmt_ptr},
FMT_STATUS},
/* 166 */ {"_exportfs", {fmt_string, fmt_ptr}, FMT_STATUS},
/* 167 */ {"mount",
{fmt_string, fmt_string, FMT_FLAGS, fmt_ptr},
FMT_STATUS},
/* 168 */ {"ustat", {fmt_hex, fmt_ptr}, FMT_STATUS},
/* 169 */ {"_semsys",
{fmt_dec, fmt_hex, fmt_hex, fmt_hex, fmt_hex},
fmt_dec},
/* 170 */ {"_msgsys",
{fmt_dec, fmt_hex, fmt_hex, fmt_hex, fmt_hex, fmt_hex},
fmt_dec},
/* 171 */ {"_shmsys", {fmt_dec, fmt_hex, fmt_hex, fmt_hex}, fmt_dec},
/* 172 */ {"_auditsys", {fmt_dec, fmt_hex, fmt_hex, fmt_hex}, fmt_dec},
/* 173 */ {"_rfssys",
{fmt_dec, fmt_hex, fmt_hex, fmt_hex, fmt_hex},
fmt_dec},
/* 174 */ {"getdents",
{fmt_fd, fmt_post_data, FMT_SIZE},
fmt_post_data_size},
/* 175 */ {"_setsid", {fmt_dec}, fmt_dec},
/* 176 */ {"fchdir", {fmt_fd}, FMT_STATUS},
/* 177 */ {"fchroot", {fmt_fd}, FMT_STATUS},
/* 178 */ {"vpixsys", {fmt_hex, fmt_hex}, fmt_unknown},
/*
* I am unsure of the parameters for vpixsys.
*/
/* 179 */ {"aioread",
{fmt_fd, fmt_ptr, FMT_SIZE, FMT_SIZE, fmt_dec, fmt_ptr},
FMT_STATUS},
/* 180 */ {"aiowrite",
{fmt_fd, fmt_data, fmt_data_size, FMT_SIZE, fmt_dec, fmt_ptr},
FMT_STATUS},
/* 181 */ {"aiowait", {fmt_ptr}, fmt_ptr},
/* 182 */ {"aiocancel", {fmt_ptr}, FMT_STATUS},
/* 183 */ {"sigpending", {fmt_ptr}, FMT_STATUS},
/* 184 */ {"_unknown_184", {fmt_unknown}, fmt_unknown},
/* 185 */ {"setpgid", {fmt_dec, fmt_dec}, FMT_STATUS},
/* 186 */ {"_pathconf", {fmt_string, fmt_dec}, fmt_dec},
/* 187 */ {"fpathconf", {fmt_fd, fmt_dec}, fmt_dec},
/* 188 */ {"sysconf", {fmt_dec}, fmt_dec},
/* 189 */ {"uname", {fmt_ptr}, FMT_STATUS}
/*
* Next 8 system calls are for loadable system calls. Not declared since
* they are likely to change from one O/S release to the next.
*/
};
int no_system_calls = sizeof(system_calls) / sizeof(call_desc);
call_desc system_call_open_simple =
/* 5 */ {"open", {fmt_string, fmt_open_flags}, fmt_fd};
/*
* Table containing signal names.
*/
char *signal_names[] = {
/* 0 */ "0",
/* 1 */ "SIGHUP",
/* 2 */ "SIGINT",
/* 3 */ "SIGQUIT",
/* 4 */ "SIGILL",
/* 5 */ "SIGTRAP",
/* 6 */ "SIGABRT",
/* 7 */ "SIGEMT",
/* 8 */ "SIGFPE",
/* 9 */ "SIGKILL",
/* 10 */ "SIGBUS",
/* 11 */ "SIGSEGV",
/* 12 */ "SIGSYS",
/* 13 */ "SIGPIPE",
/* 14 */ "SIGALRM",
/* 15 */ "SIGTERM",
/* 16 */ "SIGURG",
/* 17 */ "SIGSTOP",
/* 18 */ "SIGTSTP",
/* 19 */ "SIGCONT",
/* 20 */ "SIGCHLD",
/* 21 */ "SIGTTIN",
/* 22 */ "SIGTTOU",
/* 23 */ "SIGIO",
/* 24 */ "SIGXCPU",
/* 25 */ "SIGXFSZ",
/* 26 */ "SIGVTALRM",
/* 27 */ "SIGPROF",
/* 28 */ "SIGWINCH",
/* 29 */ "SIGLOST",
/* 30 */ "SIGUSR1",
/* 31 */ "SIGUSR2"
};
int no_signal_names = sizeof(signal_names) / sizeof(char *);
/*
* Table containing error messages.
*/
char *error_names[] = {
/* 0 */ "0",
/* 1 */ "EPERM",
/* 2 */ "ENOENT",
/* 3 */ "ESRCH",
/* 4 */ "EINTR",
/* 5 */ "EIO",
/* 6 */ "ENXIO",
/* 7 */ "E2BIG",
/* 8 */ "ENOEXEC",
/* 9 */ "EBADF",
/* 10 */ "ECHILD",
/* 11 */ "EAGAIN",
/* 12 */ "ENOMEM",
/* 13 */ "EACCES",
/* 14 */ "EFAULT",
/* 15 */ "ENOTBLK",
/* 16 */ "EBUSY",
/* 17 */ "EEXIST",
/* 18 */ "EXDEV",
/* 19 */ "ENODEV",
/* 20 */ "ENOTDIR",
/* 21 */ "EISDIR",
/* 22 */ "EINVAL",
/* 23 */ "ENFILE",
/* 24 */ "EMFILE",
/* 25 */ "ENOTTY",
/* 26 */ "ETXTBSY",
/* 27 */ "EFBIG",
/* 28 */ "ENOSPC",
/* 29 */ "ESPIPE",
/* 30 */ "EROFS",
/* 31 */ "EMLINK",
/* 32 */ "EPIPE",
/* 33 */ "EDOM",
/* 34 */ "ERANGE",
/* 35 */ "EWOULDBLOCK",
/* 36 */ "EINPROGRESS",
/* 37 */ "EALREADY",
/* 38 */ "ENOTSOCK",
/* 39 */ "EDESTADDRREQ",
/* 40 */ "EMSGSIZE",
/* 41 */ "EPROTOTYPE",
/* 42 */ "ENOPROTOOPT",
/* 43 */ "EPROTONOSUPPORT",
/* 44 */ "ESOCKTNOSUPPORT",
/* 45 */ "EOPNOTSUPP",
/* 46 */ "EPFNOSUPPORT",
/* 47 */ "EAFNOSUPPORT",
/* 48 */ "EADDRINUSE",
/* 49 */ "EADDRNOTAVAIL",
/* 50 */ "ENETDOWN",
/* 51 */ "ENETUNREACH",
/* 52 */ "ENETRESET",
/* 53 */ "ECONNABORTED",
/* 54 */ "ECONNRESET",
/* 55 */ "ENOBUFS",
/* 56 */ "EISCONN",
/* 57 */ "ENOTCONN",
/* 58 */ "ESHUTDOWN",
/* 59 */ "ETOOMANYREFS",
/* 60 */ "ETIMEDOUT",
/* 61 */ "ECONNREFUSED",
/* 62 */ "ELOOP",
/* 63 */ "ENAMETOOLONG",
/* 64 */ "EHOSTDOWN",
/* 65 */ "EHOSTUNREACH",
/* 66 */ "ENOTEMPTY",
/* 67 */ "EPROCLIM",
/* 68 */ "EUSERS",
/* 69 */ "EDQUOT",
/* 70 */ "ESTALE",
/* 71 */ "EREMOTE",
/* 72 */ "ENOSTR",
/* 73 */ "ETIME",
/* 74 */ "ENOSR",
/* 75 */ "ENOMSG",
/* 76 */ "EBADMSG",
/* 77 */ "EIDRM",
/* 78 */ "EDEADLK",
/* 79 */ "ENOLCK",
/* 80 */ "ENONET",
/* 81 */ "ERREMOTE",
/* 82 */ "ENOLINK",
/* 83 */ "EADV",
/* 84 */ "ESRMNT",
/* 85 */ "ECOMM",
/* 86 */ "EPROTO",
/* 87 */ "EMULTIHOP",
/* 88 */ "EDOTDOT",
/* 89 */ "EREMCHG",
/* 90 */ "ENOSYS"
};
int no_error_names = sizeof(error_names) / sizeof(char *);

119
sim/ppc/spa-system-calls.h Normal file
View File

@ -0,0 +1,119 @@
/*
* Copyright (C) 1991 Gordon Irlam. All rights reserved.
*/
/*
* Declaration of system calls for sparc trace generator.
*/
#if !defined(SYSCALLS_H)
#define SYSCALLS_H 1
/*
* Imported declarations.
*/
#include "agent_msg.h"
/*
* Declaration of table containing system calls, and their parameter profile.
*/
/*
* Words, such as the parameters and results of system calls, are capable of
* being displayed in a number of different formats.
*
* fmt_none - indicates the absense of further arguments, functions that don't
* return a value, etc.
*
* The function format_value(..) can be used to display a word in one of the
* following formats.
*
* fmt_dec - a signed decimal number : 0, 21, -1
* fmt_hex - a unsigned hex number : 0x0, 0x15, 0xffffffff
* fmt_ptr - a pointer : NULL, 0x00000015, 0xffffffff
* fmt_fd - a file descriptor : fd0, fd15, fd-1
* fmt_signal - the name of a signal : 0, SIGTTIN, -1
* fmt_error - the name of an error : 0, EISDIR, -1
* fmt_open_flags - the flags to open : O_RDONLY, O_WRONLY|0x14, 0xffffffff
* fmt_unknown - representation unknown : .., .., ..
* fmt_string - if the null termintated string at word is printable displays
* the string within quotes, otherwise displays like fmt_ptr
* fmt_post_string - displays like fmt_ptr, value of word is also saved,
* following the system call a printable string exists at
* address word the address and the string will be displayed
* fmt_data - only permitted in argument lists, next argument must be
* format_data_size, if printable data exists at word having length
* specified by the next argument it is printed, otherwise displays
* like fmt_ptr
* fmt_data_size - displays like FMT_SIZE
* fmt_post_data - displays like fmt_ptr, value of word is also saved,
* following call if a printable length delimited string exists
* it will be displayed
* fmt_post_data_size - displays like FMT_SIZE, value is saved for use as
* length for fmt_post_data display format
* fmt_string_array - word is the address of a null terminted array of strings
* to be printed if possible
*
* Unlike the string formats which typically represent filenames it is not so
* important that length delimited data be fully displayed. When printable,
* it will be truncate much more harshly than the string formats.
*
* Only one item can be pending for display at the end of a system call.
*
* At a later date this program may be extended to display length delimited
* data as a hex dump if it is not printable.
*
* The following macros are employed to make it easy to alter how a whole
* class of values is displayed by changing their definition.
*
* FMT_STATUS - function calls that return 0 on success and -1 on error
* FMT_FLAGS - bit field objects
* FMT_SIZE - length of an object in bytes
*/
typedef enum fmt_type {fmt_none = 0, fmt_dec, fmt_hex, fmt_ptr, fmt_fd,
fmt_signal, fmt_error, fmt_open_flags, fmt_unknown, fmt_string,
fmt_post_string, fmt_data, fmt_post_data, fmt_data_size,
fmt_post_data_size, fmt_string_array} fmt_type;
#define FMT_STATUS fmt_none
#define FMT_FLAGS fmt_hex
#define FMT_SIZE fmt_dec
typedef struct _spa_call_desc {
char *name;
fmt_type arg[NO_PARAMS];
fmt_type result;
} spa_call_desc;
extern spa_call_desc spa_system_calls[];
extern int no_system_calls;
extern spa_call_desc spa_system_call_open_simple;
#define SPA_DATA_SIZE_LIMIT 20
#define SPA_STRING_SIZE_LIMIT 201
#define SPA_ARRAY_SIZE_LIMIT 21
/*
* Declaration of table containing signal names.
*/
extern char *spa_signal_names[];
extern int spa_no_signal_names;
/*
* Declaration of table containing error messages.
*/
char *spa_error_names[];
extern int spa_no_error_names;
#endif

View File

@ -29,32 +29,52 @@
of the host/target it is able to eliminate slower generic endian
handling code.
If ENDIAN_OK is true then no byte swapping is required. If it is
false, copy-in / copy-out functions assume that data should be byte
reversed as part of the copy. */
Possible values are 0 (unknown), LITTLE_ENDIAN, BIG_ENDIAN */
#ifndef WITH_HOST_BYTE_ORDER
#define WITH_HOST_BYTE_ORDER 0 /*unknown*/
#endif
#ifndef WITH_TARGET_BYTE_ORDER
#define WITH_TARGET_BYTE_ORDER 0 /*unknown*/
#endif
extern int current_host_byte_order;
extern int current_target_byte_order;
#define CURRENT_HOST_BYTE_ORDER (WITH_HOST_BYTE_ORDER \
? WITH_HOST_BYTE_ORDER \
: current_host_byte_order)
extern int current_target_byte_order;
#define CURRENT_TARGET_BYTE_ORDER (WITH_TARGET_BYTE_ORDER \
? WITH_TARGET_BYTE_ORDER \
: current_target_byte_order)
/* Intel host BSWAP support:
Whether to use bswap on the 486 and pentiums rather than the 386
sequence that uses xchgb/rorl/xchgb */
#ifndef WITH_BSWAP
#define WITH_BSWAP 0
#endif
/* SMP support:
Sets a limit on the number of processors that can be simulated. If
WITH_SMP is set to zero (0), the simulator is restricted to
suporting only on processor (and as a consequence leaves the SMP
code out of the build process). */
code out of the build process).
The actual number of processors is taken from the device
/options/smp@<nr-cpu> */
#ifndef WITH_SMP
#define WITH_SMP 0
#define WITH_SMP 2
#endif
#if WITH_SMP
#define MAX_NR_PROCESSORS WITH_SMP
#else
#define MAX_NR_PROCESSORS 1
#endif
@ -68,6 +88,7 @@ extern int current_target_byte_order;
#ifndef WITH_TARGET_WORD_BITSIZE
#define WITH_TARGET_WORD_BITSIZE 32 /* compiled only */
#endif
#ifndef WITH_HOST_WORD_BITSIZE
#define WITH_HOST_WORD_BITSIZE 32 /* 64bit ready? */
#endif
@ -85,10 +106,13 @@ extern int current_target_byte_order;
CURRENT_ENVIRONMENT specifies which of vea or oea is required for
the current runtime. */
#define WITH_ENVIRONMENT 0
#define VIRTUAL_ENVIRONMENT 1
#define OPERATING_ENVIRONMENT 2
#ifndef WITH_ENVIRONMENT
#define WITH_ENVIRONMENT 0
#endif
extern int current_environment;
#define CURRENT_ENVIRONMENT (WITH_ENVIRONMENT \
? WITH_ENVIRONMENT \
@ -170,6 +194,7 @@ extern int current_environment;
#ifndef WITH_ALIGNMENT
#define WITH_ALIGNMENT 0
#endif
extern int current_alignment;
#define CURRENT_ALIGNMENT (WITH_ALIGNMENT \
? WITH_ALIGNMENT \
@ -210,254 +235,16 @@ extern int current_floating_point;
#define WITH_ASSERT 1
#endif
/* include profiling code that doesn't yet exist */
/* include monitoring code */
#ifndef WITH_PROFILE
#define WITH_PROFILE 1
#define MONITOR_INSTRUCTION_ISSUE 1
#define MONITOR_LOAD_STORE_UNIT 2
#ifndef WITH_MON
#define WITH_MON (MONITOR_LOAD_STORE_UNIT \
| MONITOR_INSTRUCTION_ISSUE)
#endif
/* INSTRUCTION TABLE CODE GENERATION:
The program gen takes the files ppc.instructions and spr.table and
creates from them code that provides:
o instruction decode and issue
o spr information
The program gen does this according to the configuration
information that follows. */
/* Line numbering of generated code:
When generating the semantic and idecode files, gen can also output
line number information (w.r.t. ppc.instructions). It may be
useful to disable this if you suspect that gen.c is incorrectly
generating itermediate code files. */
#ifndef WITH_LINE_NUMBERS
#define WITH_LINE_NUMBERS 1
#endif
/* Instruction cache:
Instead of the idecode routine calling the semantic function
directly, idecode can instead return a descriptor of the
instruction (cache entry).
With level one caching, idecode just returns the address of the
semantic function. With level two caching, in addition to this,
the idecode routine decodes key fields within the instruction and
also enters them into the cache. The table IDECODE_CACHE_RULES
controls what goes into the cache.*/
#ifndef WITH_IDECODE_CACHE
#define WITH_IDECODE_CACHE 0
#endif
#ifndef IDECODE_CACHE_SIZE
#define IDECODE_CACHE_SIZE 1024
#endif
/* Semantic code expansion:
For a given instruction there is the potential to improve
performance bo creating copies of the instructions code for one or
more of its possible variations. Eg branch being relative. This
macro determines of semantic functions should be expanded. How
well they are expanded is determined by the table
WITH_IDECODE_OPCODE_RULES. */
#ifndef WITH_IDECODE_EXPAND_SEMANTICS
#define WITH_IDECODE_EXPAND_SEMANTICS 0
#endif
/* SPR database:
The attributes of the SPR's are kept in a `lookup table'. This
table can be implemented as either a true table or a switch
statement.
A swith statement may be a performance advantage if the SPR's are
known at compile time. The compiler is then able to eliminate the
switch. */
#ifndef WITH_SPREG_LOOKUP_TABLE
#define WITH_SPREG_LOOKUP_TABLE 1
#endif
/* Instruction decode:
The table that follows is used by gen to construct a decision tree
that can identify each possible instruction. Gen then outputs this
decision tree as (according to config) a table or switch statement
as the function idecode.
In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
determines of the semantic functions themselves should be expanded
in a similar way.
The table contains the following entries:
<valid>
Must be 1 for the entry to be considered. The last entry must be
zero.
<first>
<last>
Range of bits (within the instruction) that should be searched for
an instruction field. Within such ranges, gen looks for opcodes
(constants), registers (strings) and reserved bits (slash) and
according to the rules that follows includes or excludes them from
a possible instruction field.
<force_first>
<force_last>
If an instructioin field was found, enlarge the field size so that
it is forced to at least include bits starting from <force_first>
(<force_last>). To stop this occuring, use <force_first> = <last>
+ 1 and <force_last> = <first> - 1.
<force_slash>
Treat `/' fields as a constant instead of variable when looking for
an instruction field.
<force_expansion>
Treat any contained register (string) fields as constant when
determining the instruction field. For the instruction decode (and
controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
what would otherwize be non constant bits of an instruction.
<use_switch>
Should this table be expanded using a switch statement (val 1) and
if so, should it be padded with entries so as to force the compiler
to generate a jump table (val 2).
<special_mask>
<special_value>
<special_rule>
Special rule to fine tune how specific (or groups) of instructions
are expanded. The applicability of the rule is determined by
<special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
Where <instruction> is obtained by looking only at constant fields
with in an instructions spec. When determining an expansion, the
rule is only considered when a node contains a single instruction.
<special_rule> can be any of:
0: for this instruction, expand by earlier rules
1: expand bits <force_low> .. <force_hi> only
2: boolean expansion of only zero/non-zero cases
Ok? */
#define WITH_IDECODE_OPCODE_RULES { \
{ 1, 0, 5, 0, 5, 0, 0, 1, 0x00000000, 0x00000000, 0 }, \
{ 1, 21, 31, 32, -1, 0, 0, 1, 0x00000000, 0x00000000, 0 }, \
{ 0 } \
}
/* Instruction unpacking:
Once the instruction has been decoded, the register (and other)
fields within the instruction need to be extracted.
The table that follows determines how each field should be treated.
Importantly it considers the case where the extracted field is to
be used immediatly or stored in an instruction cache.
<valid>
Zero marks the end of the table. More importantly 1. indicates
that the entry is valid and can be cached. 2. indicates that that
the entry is valid but can not be cached.
<old_name>
The field name as given in the instruction spec.
<new_name>
A name for <old_name> once it has been extracted from the
instructioin (and possibly stored in the instruction cache).
<type>
String specifying the storage type for <new_name> (the extracted
field>.
<expression>
Specifies how to get <new_name> from <old_name>. If null, old and
new name had better be the same. */
#define WITH_IDECODE_CACHE_RULES { \
{ 1, "RA", "RA", 0, 0 }, \
{ 1, "RA", "rA", "signed_word *", \
"(cpu_registers(processor)->gpr + RA)" }, \
{ 1, "RT", "RT", 0, 0 }, \
{ 1, "RT", "rT", "signed_word *", \
"(cpu_registers(processor)->gpr + RT)" }, \
{ 2, "RS", "RS", 0, 0 }, \
{ 1, "RS", "rS", "signed_word *", \
"(cpu_registers(processor)->gpr + RS)" }, \
{ 2, "RB", "RB", 0, 0 }, \
{ 1, "RB", "rB", "signed_word *", \
"(cpu_registers(processor)->gpr + RB)" }, \
{ 2, "FRA", "FRA", 0, 0 }, \
{ 1, "FRA", "frA", "unsigned64 *", \
"(cpu_registers(processor)->fpr + FRA)" }, \
{ 2, "FRB", "FRB", 0, 0 }, \
{ 1, "FRB", "frB", "unsigned64 *", \
"(cpu_registers(processor)->fpr + FRB)" }, \
{ 2, "FRC", "FRC", 0, 0 }, \
{ 1, "FRC", "frC", "unsigned64 *", \
"(cpu_registers(processor)->fpr + FRC)" }, \
{ 2, "FRS", "FRS", 0, 0 }, \
{ 1, "FRS", "frS", "unsigned64 *", \
"(cpu_registers(processor)->fpr + FRS)" }, \
{ 2, "FRT", "FRT", 0, 0 }, \
{ 1, "FRT", "frT", "unsigned64 *", \
"(cpu_registers(processor)->fpr + FRT)" }, \
{ 1, "SI", "EXTS_SI", "unsigned_word", \
"((signed_word)(signed16)instruction)" }, \
{ 2, "BI", "BI", 0, 0 }, \
{ 1, "BI", "BIT32_BI", 0, \
"BIT32(BI)" }, \
{ 2, "BA", "BA", 0, 0 }, \
{ 1, "BA", "BIT32_BA", 0, \
"BIT32(BA)" }, \
{ 2, "BB", "BB", 0, 0 }, \
{ 1, "BB", "BIT32_BB", 0, \
"BIT32(BB)" }, \
{ 1, "BD", "EXTS_BD_0b00", "unsigned_word", \
"(((signed_word)(signed16)instruction) & ~3)" }, \
/*{ 1, "BD", "CIA_plus_EXTS_BD_0b00", "unsigned_word", */ \
/* "CIA + EXTS(BD_0b00)" }, */ \
{ 1, "LI", "EXTS_LI_0b00", "unsigned_word", \
"((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)" }, \
{ 1, "D", "EXTS_D", "unsigned_word", \
"((signed_word)(signed16)(instruction))" }, \
{ 1, "DS", "EXTS_DS_0b00", "unsigned_word", \
"(((signed_word)(signed16)instruction) & ~0x3)" }, \
{ 0 } \
};
/* INLINE CODE SELECTION:
@ -486,12 +273,14 @@ extern int current_floating_point;
controled by the <module>_INLINE macro's. Where each can have a
value:
0 ppc.c should call external module
0 Make a normal external call to functions in the module.
1 ppc.c should have local copy (and hence possibly facilitate
the in lineing of that modules external calls)
1 Include the module but to not inline functions within it.
This allows functions within the module to inline functions
from other modules that have been included.
2 ppc.c should inline this module
2 Both include the module and inline functions contained within
it.
Finally, this is not for the faint harted. I've seen GCC get up to
200mb trying to compile what this can create */
@ -512,86 +301,92 @@ extern int current_floating_point;
#define STATIC_INLINE static INLINE
#endif
/* Default macro to control several of the inlines */
/* Default macro to simplify control several of key the inlines */
#ifndef DEFAULT_INLINE
#if defined(__GNUC__) && defined(__OPTIMIZE__)
#define DEFAULT_INLINE 2
#else
#define DEFAULT_INLINE 0
#endif
#endif
/* Code that does byte swapping used on any memory access */
/* Code that converts between hosts and target byte order. Used on
every memory access (instruction and data). (See ppc-endian.h for
additional byte swapping configuration information) */
#ifndef ENDIAN_INLINE
#define ENDIAN_INLINE DEFAULT_INLINE
#endif
/* Instruction cache if in use */
#if 0 /*DNE*/
#ifndef ICACHE_INLINE
#define ICACHE_INLINE 0
#endif
#endif
/* Given a translated address, core maps it onto either simulator data
or a function call, this is performed once for each
data/instruction access */
#ifndef CORE_INLINE
#define CORE_INLINE DEFAULT_INLINE
#endif
/* The cpu object. May things call upon this module to manipulate
each cpu object for instance register updates (from semantics) or
instruction execution from psim */
#ifndef VM_INLINE
#define VM_INLINE DEFAULT_INLINE
#endif
/* Physical memory is implemented using the memory map module */
/* Code that gives access to various CPU internals such as registers.
Used every time an instruction is executed */
#ifndef CPU_INLINE
#define CPU_INLINE DEFAULT_INLINE
#endif
/* handle the queue of events to happen in the future */
/* Code that translates between an effective and real address. Used
by every load or store. */
#ifndef VM_INLINE
#define VM_INLINE DEFAULT_INLINE
#endif
/* Code that loads/stores data to/from the memory data structure.
Used by every load or store */
#ifndef CORE_INLINE
#define CORE_INLINE DEFAULT_INLINE
#endif
/* Code to check for and process any events scheduled in the future.
Called once per instruction cycle */
#ifndef EVENTS_INLINE
#define EVENTS_INLINE DEFAULT_INLINE
#endif
/* not so important register manipulation code. Most important
register operations are performed directly on the register file */
/* Code monotoring the processors performance. It counts events on
every instruction cycle */
#ifndef REGISTERS_INLINE
#define REGISTERS_INLINE DEFAULT_INLINE
#ifndef MON_INLINE
#define MON_INLINE DEFAULT_INLINE
#endif
/* interrupt handling code */
/* Code called on the rare occasions that an interrupt occures. */
#ifndef INTERRUPTS_INLINE
#define INTERRUPTS_INLINE DEFAULT_INLINE
#define INTERRUPTS_INLINE 0
#endif
/* device code. While possibly important, this isn't as critical as
the cpu/memory path
/* Code called on the rare occasion that either gdb or the device tree
need to manipulate a register within a processor */
#ifndef REGISTERS_INLINE
#define REGISTERS_INLINE 0
#endif
/* Code called on the rare occasion that a processor is manipulating
real hardware instead of RAM.
Also, most of the functions in devices.c are always called through
a jump table.
There seems to be some problem with making either device_tree or
devices inline. It reports the message:
device_tree_find_node() not a leaf */
devices inline. It reports the message: device_tree_find_node()
not a leaf */
#ifndef DEVICE_TREE_INLINE
#define DEVICE_TREE_INLINE 0
#define DEVICE_TREE_INLINE DEFAULT_INLINE
#endif
#ifndef DEVICES_INLINE
#define DEVICES_INLINE 0
#endif
/* Special Purpose Register tables. Provide information on the
attributes of given SPR's. */
/* Code called whenever information on a Special Purpose Register is
required. Called by the mflr/mtlr pseudo instructions */
#ifndef SPREG_INLINE
#define SPREG_INLINE DEFAULT_INLINE
@ -610,163 +405,14 @@ extern int current_floating_point;
inline all of their called functions */
#ifndef SEMANTICS_INLINE
#define SEMANTICS_INLINE 0
#define SEMANTICS_INLINE (DEFAULT_INLINE ? 1 : 0)
#endif
/* Functions that decode an instruction. Called by the cpu module.
Part of the performance critical fetch - decode - issue sequence */
/* Code to decode an instruction. Normally called on every instruction
cycle */
#ifndef IDECODE_INLINE
#define IDECODE_INLINE DEFAULT_INLINE
#endif
/* If you're confused by the above, check out some of the generic
configurations below. */
#if 0
/* Allow the expansion of the semantic functions. That is, if the
branch instruction is called with AA=0 and AA=1, generate separate
functions for each case */
#undef WITH_IDECODE_EXPAND_SEMANTICS
#define WITH_IDECODE_EXPAND_SEMANTICS 1
#undef WITH_IDECODE_OPCODE_RULES
#define WITH_IDECODE_OPCODE_RULES { \
{ 1, 0, 5, 0, 5, 0, 0, 0, 0x00000000, 0x00000000, 0 }, \
{ 1, 21, 31, 32, -1, 0, "OE,LR,AA,Rc,LK", 0, 0x00000000, 0x00000000, 0 }, \
{ 1, 6, 9, 6, 9, 0, "BO", 0, 0xfc000000, 0x40000000, 1 }, \
{ 1, 11, 15, 11, 15, 0, "RA", 0, 0xfc000000, 0x38000000, 2 }, \
{ 1, 11, 15, 11, 15, 0, "RA", 0, 0xfc000000, 0x3c000000, 2 }, \
{ 0 } \
}
#endif
#if 0
/* eliminate any debugging noise */
#undef WITH_TRACE
#define WITH_TRACE 0
#undef WITH_ASSERT
#define WITH_ASSERT 0
#endif
#if 0
/* A reasonable set of inline macro's that give the compiler a
fighting chance at eliminating much of the function call overhead.
Typically, with the below the -O3 option (to get inline of all
functioins) isn't of any greate benefit. */
#undef INLINE
#define INLINE inline
#undef STATIC_INLINE
#define STATIC_INLINE static INLINE
#undef ENDIAN_INLINE
#define ENDIAN_INLINE 2
#if 0 /*DNE*/
#undef ICACHE_INLINE
#define ICACHE_INLINE 0
#endif
#undef CORE_INLINE
#define CORE_INLINE 2
#undef VM_INLINE
#define VM_INLINE 2
#undef CPU_INLINE
#define CPU_INLINE 2
#undef EVENTS_INLINE
#define EVENTS_INLINE 2
#undef REGISTERS_INLINE
#define REGISTERS_INLINE 2
#undef INTERRUPTS_INLINE
#define INTERRUPTS_INLINE 2
#undef DEVICE_TREE_INLINE
#define DEVICE_TREE_INLINE 0
#undef DEVICES_INLINE
#define DEVICES_INLINE 0
#undef SPREG_INLINE
#define SPREG_INLINE 2
#undef SEMANTICS_INLINE
#define SEMANTICS_INLINE 1 /* not 2! as it blows away the compiler */
#undef IDECODE_INLINE
#define IDECODE_INLINE 2
#endif
#if 0
/* Enable the full cracking cache. The cracked instruction cache
appears to give best performance if most functions have been lined
as well */
#undef WITH_IDECODE_CACHE
#define WITH_IDECODE_CACHE 2
#endif
#if 0
/* With the VEA model, can eliminate some things. Not least of which
is support for the OEA model */
#undef WITH_ENVIRONMENT
#define WITH_ENVIRONMENT VIRTUAL_ENVIRONMENT
#undef WITH_EVENTS
#define WITH_EVENTS 0
#undef WITH_SMP
#define WITH_SMP 0
#undef WITH_TARGET_BYTE_ORDER
#define WITH_TARGET_BYTE_ORDER WITH_HOST_BYTE_ORDER
#endif
#if 0
/* Finally, the expansion rules below are extreemly agressive. Only
consider them if your build machine is VERY VERY VERY VERY VERY
well configured */
#undef WITH_IDECODE_EXPAND_SEMANTICS
#define WITH_IDECODE_EXPAND_SEMANTICS 1
#undef WITH_IDECODE_OPCODE_RULES
#define WITH_IDECODE_OPCODE_RULES { \
{ 1, 0, 5, 0, 5, 0, 0, 0, 0x00000000, 0x00000000, 0 }, \
{ 1, 21, 31, 32, -1, 0, "OE,LR,AA,Rc,LK", 0, 0x00000000, 0x00000000, 0 }, \
{ 1, 6, 15, 6, 15, 0, "BO,BI", 0, 0xfc000000, 0x40000000, 0 }, \
{ 1, 11, 15, 11, 15, 0, "RA", 0, 0xfc000000, 0x38000000, 0 }, \
{ 1, 11, 15, 11, 15, 0, "RA", 0, 0xfc000000, 0x3c000000, 0 }, \
{ 1, 11, 20, 11, 20, 0, "spr", 0, 0xfc000000, 0x7c000000, 0 }, \
{ 0 } \
}
#endif
#endif /* _CONFIG_H */

View File

@ -1,720 +0,0 @@
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _SYSTEM_C_
#define _SYSTEM_C_
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <fcntl.h>
#if (NetBSD >= 199306) /* here NetBSD as that is what we're emulating */
#include <sys/syscall.h> /* FIXME - should not be including this one */
#include <sys/sysctl.h>
#endif
#if (BSD < 199306) /* here BSD as just a bug */
extern int errno;
#endif
#include "cpu.h"
#include "idecode.h"
#include "system.h"
#ifndef STATIC_INLINE_SYSTEM
#define STATIC_INLINE_SYSTEM STATIC_INLINE
#endif
#if (NetBSD >= 199306)
#define SYS(X) ASSERT(call == (SYS_##X))
#else
#define SYS(X)
#endif
#if (NetBSD >= 199306 && PATH_MAX != 1024)
#error "PATH_MAX not 1024"
#elif !defined(PATH_MAX)
#define PATH_MAX 1024
#endif
STATIC_INLINE_SYSTEM char *
read_string(cpu *processor,
char *dest,
unsigned_word addr,
unsigned nr_bytes)
{
unsigned nr_moved = 0;
if (addr == 0)
return NULL;
while (1) {
if (vm_data_map_read_buffer(cpu_data_map(processor),
&dest[nr_moved],
addr + nr_moved,
sizeof(dest[nr_moved]))
!= sizeof(dest[nr_moved]))
return NULL;
if (dest[nr_moved] == '\0' || nr_moved >= nr_bytes)
break;
nr_moved++;
}
dest[nr_moved] = '\0';
return dest;
}
STATIC_INLINE_SYSTEM void
write_status(cpu *processor,
int status)
{
cpu_registers(processor)->gpr[3] = status;
if (status < 0)
cpu_registers(processor)->gpr[0] = errno;
else
cpu_registers(processor)->gpr[0] = 0;
}
STATIC_INLINE_SYSTEM void
write_stat(cpu *processor,
unsigned_word addr,
struct stat buf)
{
int nr_moved;
H2T(buf.st_dev);
H2T(buf.st_ino);
H2T(buf.st_mode);
H2T(buf.st_nlink);
H2T(buf.st_uid);
H2T(buf.st_gid);
H2T(buf.st_rdev);
H2T(buf.st_size);
H2T(buf.st_atime);
/* H2T(buf.st_spare1); */
H2T(buf.st_mtime);
/* H2T(buf.st_spare2); */
H2T(buf.st_ctime);
/* H2T(buf.st_spare3); */
H2T(buf.st_blksize);
H2T(buf.st_blocks);
#if (NetBSD >= 199306)
H2T(buf.st_flags);
H2T(buf.st_gen);
#endif
nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
&buf,
addr,
sizeof(buf),
0/*violate_ro*/);
if (nr_moved != sizeof(buf))
error("write_stat() write failed\n");
}
STATIC_INLINE_SYSTEM void
do_exit(unsigned call,
cpu *processor,
unsigned_word cia)
{
int status = (int)cpu_registers(processor)->gpr[3];
SYS(exit);
cpu_halt(processor, cia, was_exited, status);
}
STATIC_INLINE_SYSTEM void
do_read(unsigned call,
cpu *processor,
unsigned_word cia)
{
void *scratch_buffer;
int d = (int)cpu_registers(processor)->gpr[3];
unsigned_word buf = cpu_registers(processor)->gpr[4];
int nbytes = cpu_registers(processor)->gpr[5];
int status;
int nr_moved;
SYS(read);
/* get a tempoary bufer */
scratch_buffer = zalloc(nbytes);
/* check if buffer exists by reading it */
nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
scratch_buffer,
buf,
nbytes);
if (nr_moved != nbytes)
error("system_call()read - check on buffer failed\n");
/* read */
#if 0
if (d == 0) {
status = fread (scratch_buffer, 1, nbytes, stdin);
if (status == 0 && ferror (stdin))
status = -1;
}
#endif
status = read (d, scratch_buffer, nbytes);
if (status == -1) {
cpu_registers(processor)->gpr[0] = errno;
} else {
cpu_registers(processor)->gpr[3] = status;
if (status > 0) {
nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
scratch_buffer,
buf,
status,
0/*violate_ro*/);
if (nr_moved != status)
error("system_call()read - write to buffer failed\n");
}
}
zfree(scratch_buffer);
}
STATIC_INLINE_SYSTEM void
do_write(unsigned call,
cpu *processor,
unsigned_word cia)
{
void *scratch_buffer = NULL;
int nr_moved;
int d = (int)cpu_registers(processor)->gpr[3];
unsigned_word buf = cpu_registers(processor)->gpr[4];
int nbytes = cpu_registers(processor)->gpr[5];
int status;
SYS(write);
/* get a tempoary bufer */
scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
/* copy in */
nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
scratch_buffer,
buf,
nbytes);
if (nr_moved != nbytes) {
/* FIXME - should handle better */
error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
nr_moved, nbytes);
}
/* write */
status = write(d, scratch_buffer, nbytes);
if (status == -1) {
cpu_registers(processor)->gpr[0] = errno;
}
cpu_registers(processor)->gpr[3] = status;
zfree(scratch_buffer);
}
STATIC_INLINE_SYSTEM void
do_open(unsigned call,
cpu *processor,
unsigned_word cia)
{
unsigned_word path_addr = cpu_registers(processor)->gpr[3];
char path_buf[PATH_MAX];
char *path = read_string(processor, path_buf, path_addr, PATH_MAX);
int flags = (int)cpu_registers(processor)->gpr[4];
int mode = (int)cpu_registers(processor)->gpr[4];
SYS(open);
write_status(processor, open(path, flags, mode));
}
STATIC_INLINE_SYSTEM void
do_close(unsigned call,
cpu *processor,
unsigned_word cia)
{
int d = (int)cpu_registers(processor)->gpr[3];
SYS(close);
write_status(processor, close(d));
}
STATIC_INLINE_SYSTEM void
do_break(unsigned call,
cpu *processor,
unsigned_word cia)
/* just pass this onto the `vm' device */
{
psim *system = cpu_system(processor);
const device *vm = psim_device(system, "/vm");
SYS(break);
vm->callback->ioctl(vm,
system,
processor,
cia,
0, /*ioctl*/
NULL); /*ioctl-data*/
}
STATIC_INLINE_SYSTEM void
do_getpid(unsigned call,
cpu *processor,
unsigned_word cia)
{
SYS(getpid);
cpu_registers(processor)->gpr[3] = (int)getpid();
}
STATIC_INLINE_SYSTEM void
do_getuid(unsigned call,
cpu *processor,
unsigned_word cia)
{
SYS(getuid);
cpu_registers(processor)->gpr[3] = (int)getuid();
}
STATIC_INLINE_SYSTEM void
do_geteuid(unsigned call,
cpu *processor,
unsigned_word cia)
{
SYS(geteuid);
cpu_registers(processor)->gpr[3] = (int)geteuid();
}
STATIC_INLINE_SYSTEM void
do_kill(unsigned call,
cpu *processor,
unsigned_word cia)
{
pid_t pid = cpu_registers(processor)->gpr[3];
int sig = cpu_registers(processor)->gpr[4];
SYS(kill);
error("SYS_kill - more to this than just a kill\n");
cpu_halt(processor, cia, was_signalled, sig);
}
STATIC_INLINE_SYSTEM void
do_sigprocmask(unsigned call,
cpu *processor,
unsigned_word cia)
{
natural_word how = cpu_registers(processor)->gpr[3];
unsigned_word set = cpu_registers(processor)->gpr[4];
unsigned_word oset = cpu_registers(processor)->gpr[5];
SYS(sigprocmask);
TRACE(trace_system, ("SYS_sigprocmask: how=%d, set=0x%x, oset=0x%x\n",
how, set, oset));
cpu_registers(processor)->gpr[3] = 0;
cpu_registers(processor)->gpr[4] = set;
}
STATIC_INLINE_SYSTEM void
do_ioctl(unsigned call,
cpu *processor,
unsigned_word cia)
{
SYS(ioctl);
TRACE(trace_system, ("SYS_ioctl: d=%d, request=0x%x, argp=0x%x\n",
cpu_registers(processor)->gpr[3], cpu_registers(processor)->gpr[4], cpu_registers(processor)->gpr[5]));
cpu_registers(processor)->gpr[3] = 0;
}
STATIC_INLINE_SYSTEM void
do_umask(unsigned call,
cpu *processor,
unsigned_word cia)
{
SYS(umask);
cpu_registers(processor)->gpr[3] = umask(cpu_registers(processor)->gpr[3]);
}
STATIC_INLINE_SYSTEM void
do_stat(unsigned call,
cpu *processor,
unsigned_word cia)
{
char path_buf[PATH_MAX];
unsigned_word path_addr = cpu_registers(processor)->gpr[3];
unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[4];
char *path = read_string(processor, path_buf, path_addr, PATH_MAX);
struct stat buf;
SYS(stat);
write_status(processor, stat(path, &buf));
write_stat(processor, stat_buf_addr, buf);
}
STATIC_INLINE_SYSTEM void
do_fstat(unsigned call,
cpu *processor,
unsigned_word cia)
{
int fd = cpu_registers(processor)->gpr[3];
unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[4];
struct stat buf;
SYS(fstat);
write_status(processor, fstat(fd, &buf));
write_stat(processor, stat_buf_addr, buf);
}
STATIC_INLINE_SYSTEM void
do_lstat(unsigned call,
cpu *processor,
unsigned_word cia)
{
char path_buf[PATH_MAX];
unsigned_word path_addr = cpu_registers(processor)->gpr[3];
char *path = read_string(processor, path_buf, path_addr, PATH_MAX);
unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[4];
struct stat buf;
SYS(lstat);
write_status(processor, stat(path, &buf));
write_stat(processor, stat_buf_addr, buf);
}
STATIC_INLINE_SYSTEM void
do___sysctl(unsigned call,
cpu *processor,
unsigned_word cia)
{
/* call the arguments by their real name */
unsigned_word name = cpu_registers(processor)->gpr[3];
natural_word namelen = cpu_registers(processor)->gpr[4];
unsigned_word oldp = cpu_registers(processor)->gpr[5];
unsigned_word oldlenp = cpu_registers(processor)->gpr[6];
natural_word oldlen;
natural_word mib;
natural_word int_val;
SYS(__sysctl);
/* pluck out the management information base id */
if (namelen < 1)
error("system_call()SYS___sysctl bad name[0]\n");
mib = vm_data_map_read_word(cpu_data_map(processor),
name,
processor,
cia);
name += sizeof(mib);
/* see what to do with it ... */
switch (mib) {
case 6/*CTL_HW*/:
#if (NetBSD >= 199306) && (CTL_HW != 6)
# error "CTL_HW"
#endif
if (namelen < 2)
error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
mib = vm_data_map_read_word(cpu_data_map(processor),
name,
processor,
cia);
name += sizeof(mib);
switch (mib) {
case 7/*HW_PAGESIZE*/:
#if (NetBSD >= 199306) && (HW_PAGESIZE != 7)
# error "HW_PAGESIZE"
#endif
oldlen = vm_data_map_read_word(cpu_data_map(processor),
oldlenp,
processor,
cia);
if (sizeof(natural_word) > oldlen)
error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
int_val = 8192;
oldlen = sizeof(int_val);
vm_data_map_write_word(cpu_data_map(processor),
oldp,
int_val,
processor,
cia);
vm_data_map_write_word(cpu_data_map(processor),
oldlenp,
oldlen,
processor,
cia);
break;
default:
error("sysctl() CTL_HW.%d unknown\n", mib);
break;
}
break;
default:
error("sysctl() name[0]=%s unknown\n", (int)mib);
break;
}
cpu_registers(processor)->gpr[3] = 0;
}
STATIC_INLINE_SYSTEM void
unimp(unsigned call,
cpu *processor,
unsigned_word cia)
{
error("unimplemented system call %d, cia=0x%x\n", call, cia);
}
typedef void (sys_handler)
(unsigned call,
cpu *processor,
unsigned_word cia);
static sys_handler *(handlers[]) = {
unimp, /* SYS_syscall 0 */
do_exit, /* 1*/
unimp, /* SYS_fork 2 */
do_read, /* 3 */
do_write, /* 4 */
do_open, /* 5 */
do_close, /* 6 */
unimp, /* SYS_wait4 7 */
unimp, /* 8 is old creat */
unimp, /* SYS_link 9 */
unimp, /* SYS_unlink 10 */
unimp, /* 11 is obsolete execv */
unimp, /* SYS_chdir 12 */
unimp, /* SYS_fchdir 13 */
unimp, /* SYS_mknod 14 */
unimp, /* SYS_chmod 15 */
unimp, /* SYS_chown 16 */
do_break, /* 17 */
unimp, /* SYS_getfsstat 18 */
unimp, /* 19 is old lseek */
do_getpid, /* 20 */
unimp, /* SYS_mount 21 */
unimp, /* SYS_unmount 22 */
unimp, /* SYS_setuid 23 */
do_getuid, /* 24 */
do_geteuid, /* 25 */
unimp, /* SYS_ptrace 26 */
unimp, /* SYS_recvmsg 27 */
unimp, /* SYS_sendmsg 28 */
unimp, /* SYS_recvfrom 29 */
unimp, /* SYS_accept 30 */
unimp, /* SYS_getpeername 31 */
unimp, /* SYS_getsockname 32 */
unimp, /* SYS_access 33 */
unimp, /* SYS_chflags 34 */
unimp, /* SYS_fchflags 35 */
unimp, /* SYS_sync 36 */
do_kill, /* 37 */
unimp, /* 38 is old stat */
unimp, /* SYS_getppid 39 */
unimp, /* 40 is old lstat */
unimp, /* SYS_dup 41 */
unimp, /* SYS_pipe 42 */
unimp, /* SYS_getegid 43 */
unimp, /* SYS_profil 44 */
unimp, /* SYS_ktrace 45 */
unimp, /* SYS_sigaction 46 */
unimp, /* SYS_getgid 47 */
do_sigprocmask, /* 48 */
unimp, /* SYS_getlogin 49 */
unimp, /* SYS_setlogin 50 */
unimp, /* SYS_acct 51 */
unimp, /* SYS_sigpending 52 */
unimp, /* SYS_sigaltstack 53 */
do_ioctl, /* 54 */
unimp, /* SYS_reboot 55 */
unimp, /* SYS_revoke 56 */
unimp, /* SYS_symlink 57 */
unimp, /* SYS_readlink 58 */
unimp, /* SYS_execve 59 */
do_umask, /* 60 */
unimp, /* SYS_chroot 61 */
unimp, /* 62 is old fstat */
unimp, /* 63 is old getkerninfo */
unimp, /* 64 is old getpagesize */
unimp, /* SYS_msync 65 */
unimp, /* SYS_vfork 66 */
unimp, /* 67 is obsolete vread */
unimp, /* 68 is obsolete vwrite */
unimp, /* SYS_sbrk 69 */
unimp, /* SYS_sstk 70 */
unimp, /* 71 is old mmap */
unimp, /* SYS_vadvise 72 */
unimp, /* SYS_munmap 73 */
unimp, /* SYS_mprotect 74 */
unimp, /* SYS_madvise 75 */
unimp, /* 76 is obsolete vhangup */
unimp, /* 77 is obsolete vlimit */
unimp, /* SYS_mincore 78 */
unimp, /* SYS_getgroups 79 */
unimp, /* SYS_setgroups 80 */
unimp, /* SYS_getpgrp 81 */
unimp, /* SYS_setpgid 82 */
unimp, /* SYS_setitimer 83 */
unimp, /* 84 is old wait */
unimp, /* SYS_swapon 85 */
unimp, /* SYS_getitimer 86 */
unimp, /* 87 is old gethostname */
unimp, /* 88 is old sethostname */
unimp, /* 89 is old getdtablesize */
unimp, /* SYS_dup2 90 */
unimp, /* 91 */
unimp, /* SYS_fcntl 92 */
unimp, /* SYS_select 93 */
unimp, /* 94 */
unimp, /* SYS_fsync 95 */
unimp, /* SYS_setpriority 96 */
unimp, /* SYS_socket 97 */
unimp, /* SYS_connect 98 */
unimp, /* 99 is old accept */
unimp, /* SYS_getpriority 100 */
unimp, /* 101 is old send */
unimp, /* 102 is old recv */
unimp, /* SYS_sigreturn 103 */
unimp, /* SYS_bind 104 */
unimp, /* SYS_setsockopt 105 */
unimp, /* SYS_listen 106 */
unimp, /* 107 is obsolete vtimes */
unimp, /* 108 is old sigvec */
unimp, /* 109 is old sigblock */
unimp, /* 110 is old sigsetmask */
unimp, /* SYS_sigsuspend 111 */
unimp, /* 112 is old sigstack */
unimp, /* 113 is old recvmsg */
unimp, /* 114 is old sendmsg */
unimp, /* SYS_vtrace 115 - is obsolete vtrace */
unimp, /* SYS_gettimeofday 116 */
unimp, /* SYS_getrusage 117 */
unimp, /* SYS_getsockopt 118 */
unimp, /* SYS_resuba 119 */
unimp, /* SYS_readv 120 */
unimp, /* SYS_writev 121 */
unimp, /* SYS_settimeofday 122 */
unimp, /* SYS_fchown 123 */
unimp, /* SYS_fchmod 124 */
unimp, /* 125 is old recvfrom */
unimp, /* 126 is old setreuid */
unimp, /* 127 is old setregid */
unimp, /* SYS_rename 128 */
unimp, /* 129 is old truncate */
unimp, /* 130 is old ftruncate */
unimp, /* SYS_flock 131 */
unimp, /* SYS_mkfifo 132 */
unimp, /* SYS_sendto 133 */
unimp, /* SYS_shutdown 134 */
unimp, /* SYS_socketpair 135 */
unimp, /* SYS_mkdir 136 */
unimp, /* SYS_rmdir 137 */
unimp, /* SYS_utimes 138 */
unimp, /* 139 is obsolete 4.2 sigreturn */
unimp, /* SYS_adjtime 140 */
unimp, /* 141 is old getpeername */
unimp, /* 142 is old gethostid */
unimp, /* 143 is old sethostid */
unimp, /* 144 is old getrlimit */
unimp, /* 145 is old setrlimit */
unimp, /* 146 is old killpg */
unimp, /* SYS_setsid 147 */
unimp, /* SYS_quotactl 148 */
unimp, /* 149 is old quota */
unimp, /* 150 is old getsockname */
unimp, /* 151 */
unimp, /* 152 */
unimp, /* 153 */
unimp, /* 154 */
unimp, /* SYS_nfssvc 155 */
unimp, /* 156 is old getdirentries */
unimp, /* SYS_statfs 157 */
unimp, /* SYS_fstatfs 158 */
unimp, /* 159 */
unimp, /* 160 */
unimp, /* SYS_getfh 161 */
unimp, /* 162 is old getdomainname */
unimp, /* 163 is old setdomainname */
unimp, /* 164 is old uname */
unimp, /* SYS_sysarch 165 */
unimp, /* 166 */
unimp, /* 167 */
unimp, /* 168 */
unimp, /* SYS_semsys 169 */
unimp, /* SYS_msgsys 170 */
unimp, /* SYS_shmsys 171 */
unimp, /* 172 */
unimp, /* 173 */
unimp, /* 174 */
unimp, /* 175 */
unimp, /* 176 */
unimp, /* 177 */
unimp, /* 178 */
unimp, /* 179 */
unimp, /* 180 */
unimp, /* SYS_setgid 181 */
unimp, /* SYS_setegid 182 */
unimp, /* SYS_seteuid 183 */
unimp, /* SYS_lfs_bmapv 184 */
unimp, /* SYS_lfs_markv 185 */
unimp, /* SYS_lfs_segclean 186 */
unimp, /* SYS_lfs_segwait 187 */
do_stat, /* 188 */
do_fstat, /* 189 */
do_lstat, /* 190 */
unimp, /* SYS_pathconf 191 */
unimp, /* SYS_fpathconf 192 */
unimp, /* 193 */
unimp, /* SYS_getrlimit 194 */
unimp, /* SYS_setrlimit 195 */
unimp, /* SYS_getdirentries 196 */
unimp, /* SYS_mmap 197 */
unimp, /* SYS___syscall 198 */
unimp, /* SYS_lseek 199 */
unimp, /* SYS_truncate 200 */
unimp, /* SYS_ftruncate 201 */
do___sysctl, /* 202 */
unimp, /* SYS_mlock 203 */
unimp, /* SYS_munlock 204 */
};
INLINE_SYSTEM void
system_call(cpu *processor,
unsigned_word cia)
{
unsigned call = cpu_registers(processor)->gpr[0];
if (call >= sizeof(handlers)/sizeof(handlers[0]))
error("system call %d out-of-range\n", call);
cpu_registers(processor)->gpr[0] = 0; /* default success */
handlers[call](call, processor, cia);
}
#endif /* _SYSTEM_C_ */

49
sim/ppc/table.h Normal file
View File

@ -0,0 +1,49 @@
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* load a table into memory */
typedef struct _table table;
typedef struct _table_entry table_entry;
struct _table_entry {
int line_nr;
int nr_fields;
char *file_name;
char *annex;
char *fields[0]; /* User defined */
};
extern table *table_open
(char *file_name,
int max_nr_fields);
extern table_entry *table_entry_read
(table *file);
extern void dump_table_entry
(table_entry *entry,
int indent);
extern void table_entry_lf_c_line_nr
(lf *file,
table_entry *entry);