New changes from Andrew
This commit is contained in:
parent
5666490bee
commit
5b4d72dd73
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,6 +151,7 @@ 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
|
||||
|
@ -146,28 +159,35 @@ BUILT_SRC = \
|
|||
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
|
||||
|
|
|
@ -3,117 +3,183 @@
|
|||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
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.
|
||||
KNOWN FEATURES
|
||||
|
||||
|
||||
BUILDING:
|
||||
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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
o I also suggest that you install: flex, bision, gnu-make and
|
||||
byacc. Doing this just makes builds easier.
|
||||
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.
|
||||
|
||||
o Configure almost as per normal, specifing the special target
|
||||
eabisim vis:
|
||||
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.
|
||||
|
||||
$ CC=gcc ./configure --target=powerpcle-unknown-eabisim
|
||||
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.
|
||||
|
||||
by default (because of its dependency on GCC).
|
||||
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.
|
||||
|
||||
o Build your entire gdb tree as per normal. Something along the
|
||||
lines of:
|
||||
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
|
||||
|
||||
o Install it it all as per normal. Something along the lines of:
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ make CC=gcc install
|
||||
or just
|
||||
$ cp gdb/gdb ~/bin/powerpc-unknown-eabisim-gdb
|
||||
$ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
|
||||
|
||||
|
||||
RUNNING:
|
||||
USING THE SIMULATOR:
|
||||
|
||||
PSIM can either be run as a stand alone program or as part
|
||||
of gdb. The psim-test archive (found in:
|
||||
(I assume that you've unpacked the psim-test archive).
|
||||
|
||||
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:
|
||||
1. As a standalone program
|
||||
|
||||
Print out the users environment:
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/envp
|
||||
$ powerpc-unknown-eabisim-run envp
|
||||
|
||||
Print out the arguments:
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/argv a b c
|
||||
$ powerpc-unknown-eabisim-run argv a b c
|
||||
|
||||
Check the OEA model:
|
||||
Check that sbrk works:
|
||||
|
||||
$ 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>
|
||||
$ powerpc-unknown-eabisim-run break
|
||||
|
||||
|
||||
Example of running GDB:
|
||||
2. 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).
|
||||
The main thing to note is that before you can run the simulator
|
||||
you must enable it. The example below illustrates this:
|
||||
|
||||
$ cd sim/ppc/test
|
||||
$ powerpc-unknown-eabi-gdb count
|
||||
$ powerpc-unknown-eabisim-gdb envp
|
||||
(gdb) target sim
|
||||
(gdb) load count
|
||||
(gdb) load
|
||||
(gdb) break main
|
||||
(gdb) run
|
||||
.
|
||||
|
@ -121,111 +187,64 @@ RUNNING:
|
|||
.
|
||||
|
||||
|
||||
CONFIGURATION:
|
||||
BUGS AND PROBLEMS:
|
||||
|
||||
Making it go faster
|
||||
There is a mailing list (subscribe through majordomo@ci.com.au) (that
|
||||
is almost never used) at:
|
||||
|
||||
See the file sim/ppc/config.h (which is copied from
|
||||
sim/ppc/std-config.h) for further information.
|
||||
powerpc-psim@ci.com.au
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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' :-)
|
||||
|
||||
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.
|
||||
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,
|
||||
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
|
||||
|
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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,7 +130,7 @@ core_executable(core *memory)
|
|||
|
||||
STATIC_INLINE_CORE core_mapping *
|
||||
new_core_mapping(attach_type attach,
|
||||
int address_space,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
const device *device,
|
||||
|
@ -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);
|
||||
|
@ -165,7 +165,7 @@ new_core_mapping(attach_type attach,
|
|||
STATIC_INLINE_CORE void
|
||||
core_map_attach(core_map *access_map,
|
||||
attach_type attach,
|
||||
int address_space,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes, /* host limited */
|
||||
const device *device, /*callback/default*/
|
||||
|
@ -177,7 +177,7 @@ core_map_attach(core_map *access_map,
|
|||
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,
|
||||
space, addr, nr_bytes,
|
||||
device, buffer, free_buffer);
|
||||
}
|
||||
else {
|
||||
|
@ -206,7 +206,7 @@ core_map_attach(core_map *access_map,
|
|||
|
||||
/* create/insert the new mapping */
|
||||
*last_mapping = new_core_mapping(attach,
|
||||
address_space, addr, nr_bytes,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,6 +876,7 @@ static device_callbacks const vm_callbacks = {
|
|||
|
||||
STATIC_INLINE_DEVICES const device *
|
||||
vea_vm_create(const char *name,
|
||||
const char *full_name,
|
||||
const device *parent)
|
||||
{
|
||||
vm_device *vm = ZALLOC(vm_device);
|
||||
|
@ -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,
|
||||
if (me->parent->callback->dma_write_buffer(me->parent,
|
||||
&buf,
|
||||
0 /*address-space*/,
|
||||
addr,
|
||||
addr+count,
|
||||
1 /*nr-bytes*/,
|
||||
1 /*violate ro*/);
|
||||
addr++;
|
||||
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,10 +1188,8 @@ 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,
|
||||
update_for_binary_section(bfd *abfd,
|
||||
asection *the_section,
|
||||
PTR obj)
|
||||
{
|
||||
|
@ -1208,7 +1210,7 @@ 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,
|
||||
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,
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
3323
sim/ppc/gen.c
3323
sim/ppc/gen.c
File diff suppressed because it is too large
Load Diff
|
@ -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_ */
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 *);
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
720
sim/ppc/system.c
720
sim/ppc/system.c
|
@ -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_ */
|
|
@ -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);
|
Loading…
Reference in New Issue