New changes from Andrew
This commit is contained in:
parent
5666490bee
commit
5b4d72dd73
|
@ -31,6 +31,7 @@ README.psim
|
||||||
basics.h
|
basics.h
|
||||||
bits.c
|
bits.c
|
||||||
bits.h
|
bits.h
|
||||||
|
build-psim
|
||||||
config.in
|
config.in
|
||||||
configure
|
configure
|
||||||
configure.in
|
configure.in
|
||||||
|
@ -45,22 +46,38 @@ device_tree.c
|
||||||
device_tree.h
|
device_tree.h
|
||||||
devices.c
|
devices.c
|
||||||
devices.h
|
devices.h
|
||||||
|
dgen.c
|
||||||
double.c
|
double.c
|
||||||
dp-bit.c
|
dp-bit.c
|
||||||
|
emul_generic.c
|
||||||
|
emul_generic.h
|
||||||
|
emul_netbsd.c
|
||||||
|
emul_netbsd.h
|
||||||
events.c
|
events.c
|
||||||
events.h
|
events.h
|
||||||
gen.c
|
|
||||||
idecode_branch.h
|
idecode_branch.h
|
||||||
idecode_expression.h
|
idecode_expression.h
|
||||||
idecode_fields.h
|
idecode_fields.h
|
||||||
|
igen.c
|
||||||
inline.c
|
inline.c
|
||||||
inline.h
|
inline.h
|
||||||
interrupts.c
|
interrupts.c
|
||||||
interrupts.h
|
interrupts.h
|
||||||
|
lf.c
|
||||||
|
lf.h
|
||||||
main.c
|
main.c
|
||||||
|
misc.c
|
||||||
|
misc.h
|
||||||
|
mon.c
|
||||||
|
mon.h
|
||||||
|
os_emul.c
|
||||||
|
os_emul.h
|
||||||
|
ppc-cache-rules
|
||||||
ppc-endian.c
|
ppc-endian.c
|
||||||
ppc-endian.h
|
ppc-endian.h
|
||||||
ppc-instructions
|
ppc-instructions
|
||||||
|
ppc-opcode-complex
|
||||||
|
ppc-opcode-simple
|
||||||
ppc-spr-table
|
ppc-spr-table
|
||||||
ppc.mt
|
ppc.mt
|
||||||
psim.c
|
psim.c
|
||||||
|
@ -69,9 +86,12 @@ registers.c
|
||||||
registers.h
|
registers.h
|
||||||
sim_callbacks.h
|
sim_callbacks.h
|
||||||
sim_calls.c
|
sim_calls.c
|
||||||
|
spa-reporter.c
|
||||||
|
spa-system-calls.c
|
||||||
|
spa-system-calls.h
|
||||||
std-config.h
|
std-config.h
|
||||||
system.c
|
table.c
|
||||||
system.h
|
table.h
|
||||||
vm.c
|
vm.c
|
||||||
vm.h
|
vm.h
|
||||||
vm_n.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>
|
Thu Oct 26 10:42:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||||
|
|
||||||
* Makefile.in (clean): Delete *.i and *.out files.
|
* 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.
|
({CORE,VM,CPU,EVENTS,REGISTERS,INTERRUPTS}_INLINE): Ditto.
|
||||||
({SPREG,IDECODE}_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.
|
* ppc-instructions: Initial cut of floating point suport added.
|
||||||
Of note include - use of host IEEE floating point instructions,
|
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
|
* Makefile.in et.al (sorry): tweek to use new core, core_map and
|
||||||
core.h.
|
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
|
* sim_calls.c, main.c: Add -g (trace_gdb) option, add tracing to
|
||||||
most of the other functions in sim_calls.c.
|
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
|
* 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
|
* devices.h, devices.c, memory_map.h, memory_map.c: Changed
|
||||||
callback interface so that there is a read/write buffer but no
|
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
|
eliminate transfer_mode (raw or cooked) parameter from read/write
|
||||||
buffer.
|
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
|
* ppc-instructions (fmul, fmuls): correct instruction format - had
|
||||||
FRB instead of FRC.
|
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_*,
|
* psim.c, device_tree.h, device_tree.c, devices.c (printd_*,
|
||||||
scand_*): new functions to parse/print fields in device names
|
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
|
variable number of arguments. This gives greater flexability and
|
||||||
greater chance of bugs.
|
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
|
* main.c (printf_filtered, error): Missing va_end() to close off
|
||||||
variable argument use.
|
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.
|
* basics.h (sysdep.h): Don't include it.
|
||||||
* Makefile.in (BASICS_H): Remove sysdep.h.
|
* 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
|
* core.c (core_add_data): First growth of bss was being put at
|
||||||
wrong address (0) instead of &end.
|
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
|
* core.c (core_add_stack, core_add_data): Was not handling case
|
||||||
where bss/stack is grown across the current end-of-{bss,stack}.
|
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
|
* 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)
|
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.in: Clone from other simulator targets.
|
||||||
* configure: Generate via autoconf from configure.in.
|
* 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).
|
* 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
|
* 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).
|
* system.c (system_call): add system calls kill(2) and getpid(2).
|
||||||
|
|
||||||
* main.c (main): Check/return exit status when simulation
|
* main.c (main): Check/return exit status when simulation
|
||||||
finishes.
|
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
|
* device_tree.c (create_option_device_node): Alignment rules (at
|
||||||
least for the moment) now are for strict alignment only for LE OEA
|
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.
|
* 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
|
* vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
|
||||||
forgot to return.
|
forgot to return.
|
||||||
|
|
|
@ -80,7 +80,11 @@ INCLUDES = -I. -I$(srcdir) $(LIB_INCLUDES) $(BFD_INCLUDES) $(GDB_INCLUDES)
|
||||||
CONFIG_FILE = std-config.h
|
CONFIG_FILE = std-config.h
|
||||||
|
|
||||||
# See inline.h for appropriate flags to set
|
# 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
|
LIBIBERTY_LIB = ../../libiberty/libiberty.a
|
||||||
BFD_LIB = ../../bfd/libbfd.a
|
BFD_LIB = ../../bfd/libbfd.a
|
||||||
|
@ -128,7 +132,15 @@ CPU_H = \
|
||||||
events.h \
|
events.h \
|
||||||
interrupts.h \
|
interrupts.h \
|
||||||
psim.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 = \
|
INLINE = \
|
||||||
|
@ -139,35 +151,43 @@ BUILT_SRC = \
|
||||||
icache.h \
|
icache.h \
|
||||||
idecode.h idecode.c \
|
idecode.h idecode.c \
|
||||||
semantics.h semantics.c \
|
semantics.h semantics.c \
|
||||||
|
itable.h itable.c \
|
||||||
spreg.h spreg.c \
|
spreg.h spreg.c \
|
||||||
config.h \
|
config.h \
|
||||||
ppc-config.h
|
ppc-config.h
|
||||||
|
|
||||||
LIB_SRC = \
|
LIB_SRC = \
|
||||||
psim.c \
|
psim.c \
|
||||||
bits.c \
|
bits.c \
|
||||||
ppc-endian.c \
|
|
||||||
debug.c \
|
debug.c \
|
||||||
|
ppc-endian.c \
|
||||||
vm.c \
|
vm.c \
|
||||||
core.c \
|
core.c \
|
||||||
events.c \
|
events.c \
|
||||||
system.c \
|
os_emul.c \
|
||||||
|
emul_generic.c \
|
||||||
|
emul_netbsd.c \
|
||||||
registers.c \
|
registers.c \
|
||||||
cpu.c \
|
cpu.c \
|
||||||
interrupts.c \
|
interrupts.c \
|
||||||
devices.c \
|
devices.c \
|
||||||
device_tree.c
|
device_tree.c \
|
||||||
|
mon.c
|
||||||
|
|
||||||
MAIN_SRC = \
|
MAIN_SRC = \
|
||||||
main.c \
|
main.c \
|
||||||
sim_calls.c
|
sim_calls.c
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: semantics, idecode and psim put last so smaller files are compiled
|
||||||
|
# first
|
||||||
LIB_OBJ = \
|
LIB_OBJ = \
|
||||||
debug.o \
|
debug.o \
|
||||||
bits.o \
|
bits.o \
|
||||||
ppc-endian.o \
|
ppc-endian.o \
|
||||||
system.o \
|
os_emul.o \
|
||||||
|
emul_generic.o \
|
||||||
|
emul_netbsd.o \
|
||||||
registers.o \
|
registers.o \
|
||||||
vm.o \
|
vm.o \
|
||||||
core.o \
|
core.o \
|
||||||
|
@ -177,6 +197,8 @@ LIB_OBJ = \
|
||||||
events.o \
|
events.o \
|
||||||
devices.o \
|
devices.o \
|
||||||
device_tree.o \
|
device_tree.o \
|
||||||
|
itable.o \
|
||||||
|
mon.o \
|
||||||
semantics.o \
|
semantics.o \
|
||||||
idecode.o \
|
idecode.o \
|
||||||
psim.o
|
psim.o
|
||||||
|
@ -192,7 +214,7 @@ run: psim
|
||||||
rm -f run
|
rm -f run
|
||||||
ln psim run
|
ln psim run
|
||||||
|
|
||||||
$(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
|
$(TARGETLIB): tmp-igen tmp-dgen $(LIB_OBJ) $(GDB_OBJ)
|
||||||
rm -f $(TARGETLIB)
|
rm -f $(TARGETLIB)
|
||||||
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
|
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
|
||||||
$(RANLIB) $(TARGETLIB)
|
$(RANLIB) $(TARGETLIB)
|
||||||
|
@ -201,27 +223,29 @@ $(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
|
||||||
# anything changes.
|
# anything changes.
|
||||||
psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC)
|
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)
|
debug.o: debug.c $(BASICS_H)
|
||||||
|
|
||||||
ppc-endian.o: ppc-endian.c ppc-endian.h \
|
ppc-endian.o: ppc-endian.c ppc-endian.h \
|
||||||
config.h ppc-config.h words.h sim_callbacks.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)
|
registers.o: registers.c $(REGISTERS_H) $(BASICS_H)
|
||||||
|
|
||||||
cpu.o: cpu.c $(CPU_H) $(IDECODE_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
|
idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
|
||||||
|
|
||||||
# double.o: double.c dp-bit.c
|
# double.o: double.c dp-bit.c
|
||||||
|
|
||||||
vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
|
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
|
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)
|
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
|
# 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
|
cp $(srcdir)/$(CONFIG_FILE) ppc-config.h
|
||||||
|
|
||||||
|
|
||||||
tmp-gencode: gen ppc-instructions ppc-spr-table $(srcdir)/../../move-if-change
|
tmp-dgen: dgen ppc-spr-table $(srcdir)/../../move-if-change
|
||||||
./gen -r $(srcdir)/ppc-spr-table \
|
./dgen $(DGEN_FLAGS) \
|
||||||
-i $(srcdir)/ppc-instructions \
|
-r $(srcdir)/ppc-spr-table \
|
||||||
-n spreg.h -P tmp-spreg.h \
|
-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 icache.h -C tmp-icache.h \
|
||||||
-n semantics.h -S tmp-semantics.h \
|
-n semantics.h -S tmp-semantics.h \
|
||||||
-n semantics.c -s tmp-semantics.c \
|
-n semantics.c -s tmp-semantics.c \
|
||||||
-n idecode.h -D tmp-idecode.h \
|
-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-icache.h icache.h
|
||||||
$(srcdir)/../../move-if-change tmp-idecode.h idecode.h
|
$(srcdir)/../../move-if-change tmp-idecode.h idecode.h
|
||||||
$(srcdir)/../../move-if-change tmp-idecode.c idecode.c
|
$(srcdir)/../../move-if-change tmp-idecode.c idecode.c
|
||||||
$(srcdir)/../../move-if-change tmp-semantics.h semantics.h
|
$(srcdir)/../../move-if-change tmp-semantics.h semantics.h
|
||||||
$(srcdir)/../../move-if-change tmp-semantics.c semantics.c
|
$(srcdir)/../../move-if-change tmp-semantics.c semantics.c
|
||||||
$(srcdir)/../../move-if-change tmp-spreg.h spreg.h
|
$(srcdir)/../../move-if-change tmp-itable.h itable.h
|
||||||
$(srcdir)/../../move-if-change tmp-spreg.c spreg.c
|
$(srcdir)/../../move-if-change tmp-itable.c itable.c
|
||||||
touch tmp-gencode
|
touch tmp-igen
|
||||||
|
|
||||||
# NOTE: Some versions of make don't handle files created as side-effects
|
# NOTE: Some versions of make don't handle files created as side-effects
|
||||||
# uncomment the below if that is the case.
|
# uncomment the below if that is the case.
|
||||||
#
|
#
|
||||||
# $(TARGETLIB): tmp-gencode
|
# $(TARGETLIB): tmp-igen tmp-dgen
|
||||||
# icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c: tmp-gencode
|
# 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
|
dgen: dgen.o table.o lf.o misc.o
|
||||||
$(CC_FOR_BUILD) -c $(CFLAGS) $(INLINE_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(srcdir)/gen.c
|
$(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)
|
igen: igen.o table.o lf.o misc.o
|
||||||
$(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o gen gen.o $(LIBIBERTY_LIB) $(LIBS)
|
$(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 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)
|
etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
|
||||||
|
|
||||||
clean mostlyclean:
|
clean mostlyclean:
|
||||||
rm -f tmp-* *.[ioas] *.out core psim run gen config.log
|
rm -f tmp-* *.[oas] core psim run igen dgen config.log
|
||||||
rm -f icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c ppc-config.h
|
|
||||||
|
|
||||||
distclean maintainer-clean realclean: clean
|
distclean maintainer-clean realclean: clean
|
||||||
rm -f TAGS $(BUILT_SRC) Makefile config.cache config.status config.h stamp-h
|
rm -f TAGS $(BUILT_SRC) Makefile config.cache config.status config.h stamp-h
|
||||||
|
|
|
@ -3,231 +3,250 @@
|
||||||
|
|
||||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||||
|
|
||||||
This directory contains the program PSIM that models the PowerPC
|
This directory contains the program PSIM that models the PowerPC(tm -
|
||||||
architecture. It can either be run stand alone (psim or run) or used
|
IBM) architecture. It can either be run stand alone (psim or run) or
|
||||||
as part of GDB.
|
used as part of GDB.
|
||||||
|
|
||||||
|
|
||||||
SOURCE:
|
|
||||||
|
|
||||||
PSIM is now part of the Cygnus GDB source tree (hopefully it
|
|
||||||
will in turn become part of the next FSF release of GDB).
|
|
||||||
|
|
||||||
If you're looking for a more `cutting' edge version of this
|
|
||||||
program then it can be found in:
|
|
||||||
|
|
||||||
ftp.ci.com.au:pub/clayton/psim-sim-*.tar.gz
|
|
||||||
|
|
||||||
This contains a replacement for the directory sim/ppc. As
|
|
||||||
these releases prove stable they are merged back into the GDB
|
|
||||||
source tree.
|
|
||||||
|
|
||||||
If you find bugs or experience problems, please e-mail them to
|
|
||||||
the alias:
|
|
||||||
|
|
||||||
powerpc-psim@ci.com.au
|
|
||||||
|
|
||||||
It's a majordomo mailing list.
|
|
||||||
|
|
||||||
|
|
||||||
BUILDING:
|
|
||||||
|
|
||||||
o At present PSIM can only be built using the compiler GCC
|
|
||||||
(yes that is bug). This is because, among other things the
|
|
||||||
code exploits GCC's suport of long ongs.
|
|
||||||
|
|
||||||
o I also suggest that you install: flex, bision, gnu-make and
|
|
||||||
byacc. Doing this just makes builds easier.
|
|
||||||
|
|
||||||
o Configure almost as per normal, specifing the special target
|
|
||||||
eabisim vis:
|
|
||||||
|
|
||||||
$ CC=gcc ./configure --target=powerpcle-unknown-eabisim
|
|
||||||
|
|
||||||
by default (because of its dependency on GCC).
|
|
||||||
|
|
||||||
o Build your entire gdb tree as per normal. Something along the
|
|
||||||
lines of:
|
|
||||||
|
|
||||||
$ cd gdb-4.15
|
|
||||||
$ make CC=gcc
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
o Install it it all as per normal. Something along the lines of:
|
|
||||||
|
|
||||||
$ cd gdb-4.15
|
|
||||||
$ make CC=gcc install
|
|
||||||
|
|
||||||
|
|
||||||
RUNNING:
|
|
||||||
|
|
||||||
PSIM can either be run as a stand alone program or as part
|
|
||||||
of gdb. The psim-test archive (found in:
|
|
||||||
|
|
||||||
ftp.ci.com.au:pub/clayton
|
|
||||||
|
|
||||||
contains pre-compiled and linked programs that can be run on
|
|
||||||
PSIM. The notes below assume that you have unpacked that tar
|
|
||||||
archive.
|
|
||||||
|
|
||||||
To rebuild the archive you will need to obtain a working
|
|
||||||
version of an ELF compiler/linker for the PowerPC.
|
|
||||||
|
|
||||||
Example of running PSIM:
|
|
||||||
|
|
||||||
Print out the users environment:
|
|
||||||
|
|
||||||
$ sim/ppc/psim sim/ppc/test/envp
|
|
||||||
|
|
||||||
Print out the arguments:
|
|
||||||
|
|
||||||
$ sim/ppc/psim sim/ppc/test/argv a b c
|
|
||||||
|
|
||||||
Check the OEA model:
|
|
||||||
|
|
||||||
$ sim/ppc/psim sim/ppc/test/interrupt
|
|
||||||
|
|
||||||
Check that sbrk works
|
|
||||||
|
|
||||||
$ sim/ppc/psim sim/ppc/test/break
|
|
||||||
|
|
||||||
Try for speed. The program count contains a loop
|
|
||||||
of two instructions which is looped <arg> times.
|
|
||||||
See later for how to make PSIM run 10-100 times
|
|
||||||
faster.
|
|
||||||
|
|
||||||
$ time sim/ppc/sim sim/ppc/test/count 5000000
|
|
||||||
$ expr 10 \* 1000 \* 1000 / <seconds>
|
|
||||||
|
|
||||||
|
|
||||||
Example of running GDB:
|
|
||||||
|
|
||||||
The most important thing to be aware of is the fact
|
|
||||||
that before the simulator is used, the user must attach
|
|
||||||
to it (target sim) and than load the executable (load count).
|
|
||||||
|
|
||||||
$ cd sim/ppc/test
|
|
||||||
$ powerpc-unknown-eabi-gdb count
|
|
||||||
(gdb) target sim
|
|
||||||
(gdb) load count
|
|
||||||
(gdb) break main
|
|
||||||
(gdb) run
|
|
||||||
.
|
|
||||||
.
|
|
||||||
.
|
|
||||||
|
|
||||||
|
|
||||||
CONFIGURATION:
|
|
||||||
|
|
||||||
Making it go faster
|
|
||||||
|
|
||||||
See the file sim/ppc/config.h (which is copied from
|
|
||||||
sim/ppc/std-config.h) for further information.
|
|
||||||
|
|
||||||
|
|
||||||
KNOWN FEATURES
|
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.
|
SMP: A Symetric Multi-Processor configuration is suported. This
|
||||||
Switching between the two modes at run time, however, is not.
|
includes modeling of the PowerPC load word and reserve instructions
|
||||||
|
(if intending to use this feature you are well advised to read the the
|
||||||
|
source code for the reservation instructions so that you are aware of
|
||||||
|
any potential limitations in the model). The number of processors is
|
||||||
|
selected during startup.
|
||||||
|
|
||||||
UIEA, VEA and OEA: The PowerPC architecture defines three
|
DUAL-ENDIAN: Both little and big endian models are suported. The
|
||||||
levels of the PowerPC architecture. This simulator, to a
|
execution of instruction sequences that switch between the two modes,
|
||||||
reasonable degree, is capable of modeling all three of them.
|
however, is not. The endianess is selected during startup.
|
||||||
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
|
UIEA, VEA and OEA: The PowerPC architecture defines three levels of
|
||||||
a programmer to (I won't say easily) extend this simulator so
|
the PowerPC architecture. This simulator, to a reasonable degree, is
|
||||||
that a program can interact with models of real devices.
|
capable of modeling all three. That is the User Instruction Set
|
||||||
Illustrating this is the phony machine clayton that includes
|
Architecture, the Virtual Environment Architecture and finally the
|
||||||
console, interrupt control unit and reset register devices.
|
Operating Environment Architecture. The environment is selected
|
||||||
|
during startup. The OEA model is still under development.
|
||||||
|
|
||||||
PEDANTIC VEA MEMORY MODEL: User programs can not assume that
|
HARDWARE DEVICE TREE: In the OEA, the model of the target machines
|
||||||
they can stray off the end of valid memory areas. This model
|
hardware is built from a tree of devices (bit like Open Boot).
|
||||||
defines valid memory addresses in strict accordance to the
|
Included in this is the ability to model bus hierachies and
|
||||||
executable and does not page allign their values. At first
|
runtime-configurable devices (eg PCI). The device tree used to create
|
||||||
this was a bug but since then has turned up several bugs in
|
the hardware model is created during startup. This device tree is
|
||||||
peoples code so I've renamed it `a feature' :-)
|
still under development.
|
||||||
|
|
||||||
RUNTIME CONFIG OF HARDWARE: In addition to the three builtin
|
VEA SYSTEM CALLS: In user mode, basic system calls (read, write, open,
|
||||||
models of hardware - VEA, OEA/Hardware and (the start of) OpenBoot,
|
close ...) are emulated. Under NetBSD (simply because that is what my
|
||||||
it is possible to load a file containing a specification of a
|
machine at home runs) the list is more extensive.
|
||||||
custom device tree.
|
|
||||||
|
PEDANTIC VEA MEMORY MODEL: This model implements the break (brk, sbrk)
|
||||||
|
system calls. Further, the user model has very strict memory access
|
||||||
|
controls. User programs can not assume that they can stray off the
|
||||||
|
end of valid memory areas. This model defines valid memory addresses
|
||||||
|
in strict accordance to the executable and does not page allign their
|
||||||
|
values. At first this was a bug but since then has turned up several
|
||||||
|
problems in user code so it is now described as a feature.
|
||||||
|
|
||||||
|
PROFILING: The simulation is able to count the number and type of
|
||||||
|
instructions issued and the number of loads and stores. This feature
|
||||||
|
is still under development.
|
||||||
|
|
||||||
|
PERFORMANCE: In its default configuration PSIM is constructed so that
|
||||||
|
it will compile fast and run slow. Through the enabling of more
|
||||||
|
agressive compile options (and the disabling of unwanted features) the
|
||||||
|
build can be changed to compile slow and run fast.
|
||||||
|
|
||||||
|
FLOATING POINT: Preliminary suport for floating point is included.
|
||||||
|
Real kernels don't need floating point.
|
||||||
|
|
||||||
|
|
||||||
|
BUILDING PSIM:
|
||||||
|
|
||||||
|
To build PSIM you will need the following:
|
||||||
|
|
||||||
|
gdb-4.15.tar.gz From your favorite GNU ftp site
|
||||||
|
|
||||||
|
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.diff.gz
|
||||||
|
|
||||||
|
This contains a few minor patches to
|
||||||
|
gdb-4.15 so that will include psim
|
||||||
|
when it is built.
|
||||||
|
|
||||||
|
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.tar.gz
|
||||||
|
|
||||||
|
This contains the psim files propper.
|
||||||
|
|
||||||
|
ftp://ftp.ci.com.au/pub/clayton/psim-test-951016.tar.gz
|
||||||
|
|
||||||
|
(Optional) A scattering of pre-compiled
|
||||||
|
programs that run under the simulator.
|
||||||
|
|
||||||
|
gcc Again available from your favorite
|
||||||
|
GNU ftp site.
|
||||||
|
|
||||||
|
patch Sun's patch behaves a little wierd
|
||||||
|
and doesn't appear to like creating
|
||||||
|
empty files.
|
||||||
|
|
||||||
|
|
||||||
|
In the directory ftp.ci.com.au:pub/clayton you will also notice files
|
||||||
|
named psim-NNNNNN.tar.gz. Those, more recent snapshots, may or may
|
||||||
|
not work with gdb.
|
||||||
|
|
||||||
|
|
||||||
|
0. A starting point
|
||||||
|
|
||||||
|
$ ls -1
|
||||||
|
gdb-4.15+psim-951016.diff.gz
|
||||||
|
gdb-4.15+psim-951016.tar.gz
|
||||||
|
gdb-4.15.tar.gz
|
||||||
|
psim-test-951016.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
1. Unpack gdb
|
||||||
|
|
||||||
|
$ gunzip < gdb-4.15.tar.gz | tar xf -
|
||||||
|
|
||||||
|
|
||||||
|
2. Change to the gdb directory, apply the psim patches and unpack
|
||||||
|
the psim files.
|
||||||
|
|
||||||
|
$ cd gdb-4.15
|
||||||
|
|
||||||
|
$ gunzip < ../gdb-4.15+psim-951016.diff.gz | more
|
||||||
|
$ gunzip < ../gdb-4.15+psim-951016.diff.gz | patch -p1
|
||||||
|
|
||||||
|
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar tvf -
|
||||||
|
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar xvf -
|
||||||
|
|
||||||
|
|
||||||
|
3. Configure gdb
|
||||||
|
|
||||||
|
$ more gdb/README
|
||||||
|
|
||||||
|
then something like (I assume SH):
|
||||||
|
|
||||||
|
$ CC=gcc ./configure --target=powerpc-unknown-eabisim
|
||||||
|
|
||||||
|
eabisim is needed as by default (because PSIM needs GCC) the
|
||||||
|
simulator is not built.
|
||||||
|
|
||||||
|
|
||||||
|
4. Build
|
||||||
|
|
||||||
|
$ make CC=gcc
|
||||||
|
|
||||||
|
alternativly, if you are short on disk space or just want the
|
||||||
|
simulator built:
|
||||||
|
|
||||||
|
$ ( cd libiberty && make CC=gcc )
|
||||||
|
$ ( cd bfd && make CC=gcc )
|
||||||
|
$ ( cd sim/ppc && make CC=gcc )
|
||||||
|
|
||||||
|
|
||||||
|
5. Install
|
||||||
|
|
||||||
|
$ make CC=gcc install
|
||||||
|
or just
|
||||||
|
$ cp gdb/gdb ~/bin/powerpc-unknown-eabisim-gdb
|
||||||
|
$ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
|
||||||
|
|
||||||
|
|
||||||
|
USING THE SIMULATOR:
|
||||||
|
|
||||||
|
(I assume that you've unpacked the psim-test archive).
|
||||||
|
|
||||||
|
1. As a standalone program
|
||||||
|
|
||||||
|
Print out the users environment:
|
||||||
|
|
||||||
|
$ powerpc-unknown-eabisim-run envp
|
||||||
|
|
||||||
|
Print out the arguments:
|
||||||
|
|
||||||
|
$ powerpc-unknown-eabisim-run argv a b c
|
||||||
|
|
||||||
|
Check that sbrk works:
|
||||||
|
|
||||||
|
$ powerpc-unknown-eabisim-run break
|
||||||
|
|
||||||
|
|
||||||
|
2. Example of running GDB:
|
||||||
|
|
||||||
|
The main thing to note is that before you can run the simulator
|
||||||
|
you must enable it. The example below illustrates this:
|
||||||
|
|
||||||
|
$ powerpc-unknown-eabisim-gdb envp
|
||||||
|
(gdb) target sim
|
||||||
|
(gdb) load
|
||||||
|
(gdb) break main
|
||||||
|
(gdb) run
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
BUGS AND PROBLEMS:
|
||||||
|
|
||||||
|
There is a mailing list (subscribe through majordomo@ci.com.au) (that
|
||||||
|
is almost never used) at:
|
||||||
|
|
||||||
|
powerpc-psim@ci.com.au
|
||||||
|
|
||||||
|
If I get the ftp archive updated I post a note to that news group. In
|
||||||
|
addition your welcome to send bugs or problems either to me or to that
|
||||||
|
e-mail list.
|
||||||
|
|
||||||
|
|
||||||
KNOWN PROBLEMS:
|
KNOWN PROBLEMS:
|
||||||
|
|
||||||
FLOATING POINT: Need to add suport for non IEEE float
|
See the ChangeLog file looking for lines taged with the word FIXME.
|
||||||
machines. Need to more fully handle exceptions (eg things
|
|
||||||
like divide by zero).
|
|
||||||
|
|
||||||
DEVICE TREE DOC: How to create and use the device tree is not
|
CORE.C: The implementation of core.c (defined by core.h) isn't the
|
||||||
documented at all.
|
best. It is intended to be functionaly correct rather than fast.
|
||||||
|
|
||||||
INITIALIZATION: When running from gdb, things are not
|
HTAB (page) code for OEA model untested. Some of the vm code
|
||||||
re-initialzied very well e.g. registers are not rezeroed.
|
instructions unimplemented.
|
||||||
|
|
||||||
HTAB (page) code for OEA model untested. Some of the vm code
|
Flush instruction cache instructions do nothing. Perhaphs they should
|
||||||
instructions unimplemented.
|
(if there is an instruction cache) flush it.
|
||||||
|
|
||||||
Flush instruction cache instructions do nothing. Perhaphs they
|
Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups. The
|
||||||
should (if there is an instruction cache) flush it.
|
PowerOpen worked until I added the ELF one.
|
||||||
|
|
||||||
Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.
|
OpenBoot and PR*P interfaces missing. Open boot could be implemented
|
||||||
The PowerOpen worked until I added the ELF one.
|
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
|
Missing VEA system calls.
|
||||||
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 or commented out instructions.
|
||||||
|
|
||||||
Missing or commented out instructions.
|
64bit target untested.
|
||||||
|
|
||||||
Only basic (hackish) floating point implemented, I would not
|
64bit host broken. For instance use of scanf "%x", &long long.
|
||||||
trust it and it is going to change.
|
|
||||||
|
|
||||||
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
|
PORTABILITY (Notes taken from Michael Meissner): Heavy use of the ##
|
||||||
finished/tested.
|
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:
|
||||||
|
|
||||||
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,
|
Michael Meissner, Bob Mercier, Richard Perini,
|
||||||
Richard Stallman, Mitchele Walker
|
Richard Stallman, Mitchele Walker
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@ -274,7 +293,3 @@ i486DX2/66
|
||||||
1/270/316 - switch=2/2,expand=0,inline=1,nia=0
|
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/271/281 - switch=1/1,expand=0,inline=1,nia=1
|
||||||
1/267/274 - switch=2/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_read_buffer_callback *reader;
|
||||||
device_io_write_buffer_callback *writer;
|
device_io_write_buffer_callback *writer;
|
||||||
/* common */
|
/* common */
|
||||||
int address_space;
|
int space;
|
||||||
unsigned_word base;
|
unsigned_word base;
|
||||||
unsigned_word bound;
|
unsigned_word bound;
|
||||||
unsigned nr_bytes;
|
unsigned nr_bytes;
|
||||||
|
@ -130,12 +130,12 @@ core_executable(core *memory)
|
||||||
|
|
||||||
STATIC_INLINE_CORE core_mapping *
|
STATIC_INLINE_CORE core_mapping *
|
||||||
new_core_mapping(attach_type attach,
|
new_core_mapping(attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
const device *device,
|
const device *device,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
int free_buffer)
|
int free_buffer)
|
||||||
{
|
{
|
||||||
core_mapping *new_mapping = ZALLOC(core_mapping);
|
core_mapping *new_mapping = ZALLOC(core_mapping);
|
||||||
switch (attach) {
|
switch (attach) {
|
||||||
|
@ -154,7 +154,7 @@ new_core_mapping(attach_type attach,
|
||||||
attach);
|
attach);
|
||||||
}
|
}
|
||||||
/* common */
|
/* common */
|
||||||
new_mapping->address_space = address_space;
|
new_mapping->space = space;
|
||||||
new_mapping->base = addr;
|
new_mapping->base = addr;
|
||||||
new_mapping->nr_bytes = nr_bytes;
|
new_mapping->nr_bytes = nr_bytes;
|
||||||
new_mapping->bound = addr + (nr_bytes - 1);
|
new_mapping->bound = addr + (nr_bytes - 1);
|
||||||
|
@ -164,21 +164,21 @@ new_core_mapping(attach_type attach,
|
||||||
|
|
||||||
STATIC_INLINE_CORE void
|
STATIC_INLINE_CORE void
|
||||||
core_map_attach(core_map *access_map,
|
core_map_attach(core_map *access_map,
|
||||||
attach_type attach,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes, /* host limited */
|
unsigned nr_bytes, /* host limited */
|
||||||
const device *device, /*callback/default*/
|
const device *device, /*callback/default*/
|
||||||
void *buffer, /*raw_memory*/
|
void *buffer, /*raw_memory*/
|
||||||
int free_buffer) /*raw_memory*/
|
int free_buffer) /*raw_memory*/
|
||||||
{
|
{
|
||||||
if (attach == attach_default) {
|
if (attach == attach_default) {
|
||||||
if (access_map->default_map != NULL)
|
if (access_map->default_map != NULL)
|
||||||
error("core_map_attach() default mapping already in place\n");
|
error("core_map_attach() default mapping already in place\n");
|
||||||
ASSERT(buffer == NULL);
|
ASSERT(buffer == NULL);
|
||||||
access_map->default_map = new_core_mapping(attach,
|
access_map->default_map = new_core_mapping(attach,
|
||||||
address_space, addr, nr_bytes,
|
space, addr, nr_bytes,
|
||||||
device, buffer, free_buffer);
|
device, buffer, free_buffer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* find the insertion point for this additional mapping and insert */
|
/* find the insertion point for this additional mapping and insert */
|
||||||
|
@ -206,8 +206,8 @@ core_map_attach(core_map *access_map,
|
||||||
|
|
||||||
/* create/insert the new mapping */
|
/* create/insert the new mapping */
|
||||||
*last_mapping = new_core_mapping(attach,
|
*last_mapping = new_core_mapping(attach,
|
||||||
address_space, addr, nr_bytes,
|
space, addr, nr_bytes,
|
||||||
device, buffer, free_buffer);
|
device, buffer, free_buffer);
|
||||||
(*last_mapping)->next = next_mapping;
|
(*last_mapping)->next = next_mapping;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ core_map_attach(core_map *access_map,
|
||||||
INLINE_CORE void
|
INLINE_CORE void
|
||||||
core_attach(core *memory,
|
core_attach(core *memory,
|
||||||
attach_type attach,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
access_type access,
|
access_type access,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes, /* host limited */
|
unsigned nr_bytes, /* host limited */
|
||||||
|
@ -236,7 +236,7 @@ core_attach(core *memory,
|
||||||
if (access & access_read)
|
if (access & access_read)
|
||||||
core_map_attach(memory->map + access_map,
|
core_map_attach(memory->map + access_map,
|
||||||
attach,
|
attach,
|
||||||
address_space, addr, nr_bytes,
|
space, addr, nr_bytes,
|
||||||
device, buffer, !free_buffer);
|
device, buffer, !free_buffer);
|
||||||
free_buffer ++;
|
free_buffer ++;
|
||||||
break;
|
break;
|
||||||
|
@ -244,7 +244,7 @@ core_attach(core *memory,
|
||||||
if (access & access_write)
|
if (access & access_write)
|
||||||
core_map_attach(memory->map + access_map,
|
core_map_attach(memory->map + access_map,
|
||||||
attach,
|
attach,
|
||||||
address_space, addr, nr_bytes,
|
space, addr, nr_bytes,
|
||||||
device, buffer, !free_buffer);
|
device, buffer, !free_buffer);
|
||||||
free_buffer ++;
|
free_buffer ++;
|
||||||
break;
|
break;
|
||||||
|
@ -252,7 +252,7 @@ core_attach(core *memory,
|
||||||
if (access & access_exec)
|
if (access & access_exec)
|
||||||
core_map_attach(memory->map + access_map,
|
core_map_attach(memory->map + access_map,
|
||||||
attach,
|
attach,
|
||||||
address_space, addr, nr_bytes,
|
space, addr, nr_bytes,
|
||||||
device, buffer, !free_buffer);
|
device, buffer, !free_buffer);
|
||||||
free_buffer ++;
|
free_buffer ++;
|
||||||
break;
|
break;
|
||||||
|
@ -320,7 +320,7 @@ core_map_read_buffer(core_map *map,
|
||||||
if (mapping->reader != NULL) {
|
if (mapping->reader != NULL) {
|
||||||
if (mapping->reader(mapping->device,
|
if (mapping->reader(mapping->device,
|
||||||
&byte,
|
&byte,
|
||||||
mapping->address_space,
|
mapping->space,
|
||||||
raddr - mapping->base,
|
raddr - mapping->base,
|
||||||
1, /* nr_bytes */
|
1, /* nr_bytes */
|
||||||
0, /*processor*/
|
0, /*processor*/
|
||||||
|
@ -357,7 +357,7 @@ core_map_write_buffer(core_map *map,
|
||||||
if (mapping->writer != NULL) {
|
if (mapping->writer != NULL) {
|
||||||
if (mapping->writer(mapping->device,
|
if (mapping->writer(mapping->device,
|
||||||
&byte,
|
&byte,
|
||||||
mapping->address_space,
|
mapping->space,
|
||||||
raddr - mapping->base,
|
raddr - mapping->base,
|
||||||
1, /*nr_bytes*/
|
1, /*nr_bytes*/
|
||||||
0, /*processor*/
|
0, /*processor*/
|
||||||
|
@ -382,6 +382,7 @@ core_init_callback(const device *me,
|
||||||
psim *system)
|
psim *system)
|
||||||
{
|
{
|
||||||
core *memory = (core*)me->data;
|
core *memory = (core*)me->data;
|
||||||
|
DTRACE_INIT(core);
|
||||||
core_init(memory);
|
core_init(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,7 +391,7 @@ STATIC_INLINE_CORE void
|
||||||
core_attach_address_callback(const device *me,
|
core_attach_address_callback(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type attach,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
|
@ -398,11 +399,12 @@ core_attach_address_callback(const device *me,
|
||||||
{
|
{
|
||||||
core *memory = (core*)me->data;
|
core *memory = (core*)me->data;
|
||||||
unsigned_word device_address;
|
unsigned_word device_address;
|
||||||
if (address_space != 0)
|
DTRACE_ATTACH_ADDRESS(core);
|
||||||
|
if (space != 0)
|
||||||
error("core_attach_address_callback() invalid address space\n");
|
error("core_attach_address_callback() invalid address space\n");
|
||||||
core_attach(memory,
|
core_attach(memory,
|
||||||
attach,
|
attach,
|
||||||
address_space,
|
space,
|
||||||
access,
|
access,
|
||||||
addr,
|
addr,
|
||||||
nr_bytes,
|
nr_bytes,
|
||||||
|
@ -412,15 +414,16 @@ core_attach_address_callback(const device *me,
|
||||||
|
|
||||||
STATIC_INLINE_CORE unsigned
|
STATIC_INLINE_CORE unsigned
|
||||||
core_dma_read_buffer_callback(const device *me,
|
core_dma_read_buffer_callback(const device *me,
|
||||||
void *target,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word offset,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes)
|
unsigned nr_bytes)
|
||||||
{
|
{
|
||||||
core *memory = (core*)me->data;
|
core *memory = (core*)me->data;
|
||||||
|
DTRACE_DMA_READ_BUFFER(core);
|
||||||
return core_map_read_buffer(core_readable(memory),
|
return core_map_read_buffer(core_readable(memory),
|
||||||
target,
|
dest,
|
||||||
offset,
|
addr,
|
||||||
nr_bytes);
|
nr_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,8 +431,8 @@ core_dma_read_buffer_callback(const device *me,
|
||||||
STATIC_INLINE_CORE unsigned
|
STATIC_INLINE_CORE unsigned
|
||||||
core_dma_write_buffer_callback(const device *me,
|
core_dma_write_buffer_callback(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word offset,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
int violate_read_only_section)
|
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_map *map = (violate_read_only_section
|
||||||
? core_readable(memory)
|
? core_readable(memory)
|
||||||
: core_writeable(memory));
|
: core_writeable(memory));
|
||||||
|
DTRACE_DMA_WRITE_BUFFER(core);
|
||||||
return core_map_write_buffer(map,
|
return core_map_write_buffer(map,
|
||||||
source,
|
source,
|
||||||
offset,
|
addr,
|
||||||
nr_bytes);
|
nr_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +467,7 @@ static device_callbacks const core_callbacks = {
|
||||||
INLINE_CORE const device *
|
INLINE_CORE const device *
|
||||||
core_device_create(core *memory)
|
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;
|
unsigned_N data;
|
||||||
if (mapping->reader(mapping->device,
|
if (mapping->reader(mapping->device,
|
||||||
&data,
|
&data,
|
||||||
mapping->address_space,
|
mapping->space,
|
||||||
addr - mapping->base,
|
addr - mapping->base,
|
||||||
sizeof(unsigned_N), /* nr_bytes */
|
sizeof(unsigned_N), /* nr_bytes */
|
||||||
processor,
|
processor,
|
||||||
|
@ -78,7 +78,7 @@ XCONCAT2(core_map_write_,N)(core_map *map,
|
||||||
unsigned_N data = H2T_N(val);
|
unsigned_N data = H2T_N(val);
|
||||||
if (mapping->writer(mapping->device,
|
if (mapping->writer(mapping->device,
|
||||||
&data,
|
&data,
|
||||||
mapping->address_space,
|
mapping->space,
|
||||||
addr - mapping->base,
|
addr - mapping->base,
|
||||||
sizeof(unsigned_N), /* nr_bytes */
|
sizeof(unsigned_N), /* nr_bytes */
|
||||||
processor,
|
processor,
|
||||||
|
|
|
@ -41,6 +41,14 @@ typedef enum {
|
||||||
node_string
|
node_string
|
||||||
} node_type;
|
} node_type;
|
||||||
|
|
||||||
|
static char *node_type_names[] = {
|
||||||
|
"any",
|
||||||
|
"device",
|
||||||
|
"integer",
|
||||||
|
"boolean",
|
||||||
|
"string",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct _device_tree {
|
struct _device_tree {
|
||||||
/* where i am */
|
/* where i am */
|
||||||
|
@ -89,6 +97,7 @@ typedef enum {
|
||||||
STATIC_INLINE_DEVICE_TREE device_tree *
|
STATIC_INLINE_DEVICE_TREE device_tree *
|
||||||
device_tree_find_node(device_tree *root,
|
device_tree_find_node(device_tree *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
|
const char *full_path,
|
||||||
node_type type,
|
node_type type,
|
||||||
device_tree_action action)
|
device_tree_action action)
|
||||||
{
|
{
|
||||||
|
@ -139,13 +148,13 @@ device_tree_find_node(device_tree *root,
|
||||||
if (path[name_len] == '\0') {
|
if (path[name_len] == '\0') {
|
||||||
if (action == device_tree_grow)
|
if (action == device_tree_grow)
|
||||||
error("device_tree_find_node() node %s already present\n",
|
error("device_tree_find_node() node %s already present\n",
|
||||||
path);
|
full_path);
|
||||||
if (type != node_any && child->type != type) {
|
if (type != node_any && child->type != type) {
|
||||||
if (action == device_tree_return_null)
|
if (action == device_tree_return_null)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
error("device_tree_find_node() node %s does not match type %d\n",
|
error("device_tree_find_node() node %s is not of type %s\n",
|
||||||
path, type);
|
full_path, node_type_names[type]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return child;
|
return child;
|
||||||
|
@ -153,6 +162,7 @@ device_tree_find_node(device_tree *root,
|
||||||
else
|
else
|
||||||
return device_tree_find_node(child,
|
return device_tree_find_node(child,
|
||||||
path + name_len + 1,
|
path + name_len + 1,
|
||||||
|
full_path,
|
||||||
type,
|
type,
|
||||||
action);
|
action);
|
||||||
}
|
}
|
||||||
|
@ -163,10 +173,15 @@ device_tree_find_node(device_tree *root,
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case device_tree_grow:
|
case device_tree_grow:
|
||||||
if (path[name_len] != '\0')
|
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);
|
return new_device_tree(root, path, type);
|
||||||
case device_tree_return_null:
|
case device_tree_return_null:
|
||||||
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:
|
default:
|
||||||
error("device_tree_find_node() invalid default action %d\n", action);
|
error("device_tree_find_node() invalid default action %d\n", action);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -180,14 +195,22 @@ INLINE_DEVICE_TREE device_tree *
|
||||||
device_tree_add_passthrough(device_tree *root,
|
device_tree_add_passthrough(device_tree *root,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
device_tree *new_node = device_tree_find_node(root,
|
device_tree *new_node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_device,
|
("device_tree_add_passthrough(root=0x%x, path=%s)\n", root, path));
|
||||||
device_tree_grow);
|
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,
|
new_node->device = device_create_from(new_node->name,
|
||||||
|
path,
|
||||||
NULL,
|
NULL,
|
||||||
passthrough_device_callbacks(),
|
passthrough_device_callbacks(),
|
||||||
new_node->parent->device);
|
new_node->parent->device);
|
||||||
|
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_passthrough() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,11 +220,18 @@ device_tree_add_device(device_tree *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
const device *dev)
|
const device *dev)
|
||||||
{
|
{
|
||||||
device_tree *new_node = device_tree_find_node(root,
|
device_tree *new_node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_device,
|
("device_tree_add_device(root=0x%x, path=%s, dev=0x%x)\n",
|
||||||
device_tree_grow);
|
root, path, dev));
|
||||||
|
new_node = device_tree_find_node(root,
|
||||||
|
path,
|
||||||
|
path, /* full-path */
|
||||||
|
node_device,
|
||||||
|
device_tree_grow);
|
||||||
new_node->device = dev;
|
new_node->device = dev;
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_device() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,11 +240,18 @@ device_tree_add_integer(device_tree *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
signed_word integer)
|
signed_word integer)
|
||||||
{
|
{
|
||||||
device_tree *new_node = device_tree_find_node(root,
|
device_tree *new_node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_integer,
|
("device_tree_add_integer(root=0x%x, path=%s, integer=%d)\n",
|
||||||
device_tree_grow);
|
root, path, integer));
|
||||||
|
new_node = device_tree_find_node(root,
|
||||||
|
path,
|
||||||
|
path, /* full-name */
|
||||||
|
node_integer,
|
||||||
|
device_tree_grow);
|
||||||
new_node->integer = integer;
|
new_node->integer = integer;
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_integer() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,11 +260,18 @@ device_tree_add_string(device_tree *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
const char *string)
|
const char *string)
|
||||||
{
|
{
|
||||||
device_tree *new_node = device_tree_find_node(root,
|
device_tree *new_node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_string,
|
("device_tree_add_device(root=0x%x, path=%s, string=%s)\n",
|
||||||
device_tree_grow);
|
root, path, string));
|
||||||
|
new_node = device_tree_find_node(root,
|
||||||
|
path,
|
||||||
|
path, /* full-name */
|
||||||
|
node_string,
|
||||||
|
device_tree_grow);
|
||||||
new_node->string = string;
|
new_node->string = string;
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_string() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,11 +280,18 @@ device_tree_add_boolean(device_tree *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
int boolean)
|
int boolean)
|
||||||
{
|
{
|
||||||
device_tree *new_node = device_tree_find_node(root,
|
device_tree *new_node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_boolean,
|
("device_tree_add_boolean(root=0x%x, path=%s, boolean=%d)\n",
|
||||||
device_tree_grow);
|
root, path, boolean));
|
||||||
|
new_node = device_tree_find_node(root,
|
||||||
|
path,
|
||||||
|
path, /* full-name */
|
||||||
|
node_boolean,
|
||||||
|
device_tree_grow);
|
||||||
new_node->boolean = boolean;
|
new_node->boolean = boolean;
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_boolean() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +299,16 @@ INLINE_DEVICE_TREE device_tree *
|
||||||
device_tree_add_found_device(device_tree *root,
|
device_tree_add_found_device(device_tree *root,
|
||||||
const char *path)
|
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,
|
new_node->device = device_create(new_node->name,
|
||||||
|
path,
|
||||||
new_node->parent->device);
|
new_node->parent->device);
|
||||||
|
TRACE(trace_device_tree,
|
||||||
|
("device_tree_add_found_device() = 0x%x\n", new_node));
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,10 +319,16 @@ INLINE_DEVICE_TREE const device *
|
||||||
device_tree_find_device(device_tree *root,
|
device_tree_find_device(device_tree *root,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
device_tree *node = device_tree_find_node(root,
|
device_tree *node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_device,
|
("device_tree_find_device(root=0x%x, path=%s)\n", root, path));
|
||||||
device_tree_abort);
|
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;
|
return node->device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,10 +336,16 @@ INLINE_DEVICE_TREE signed_word
|
||||||
device_tree_find_integer(device_tree *root,
|
device_tree_find_integer(device_tree *root,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
device_tree *node = device_tree_find_node(root,
|
device_tree *node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_integer,
|
("device_tree_find_integer(root=0x%x, path=%s)\n", root, path));
|
||||||
device_tree_abort);
|
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;
|
return node->integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,10 +353,16 @@ INLINE_DEVICE_TREE const char *
|
||||||
device_tree_find_string(device_tree *root,
|
device_tree_find_string(device_tree *root,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
device_tree *node = device_tree_find_node(root,
|
device_tree *node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_string,
|
("device_tree_find_string(root=0x%x, path=%s)\n", root, path));
|
||||||
device_tree_abort);
|
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;
|
return node->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,10 +370,16 @@ INLINE_DEVICE_TREE int
|
||||||
device_tree_find_boolean(device_tree *root,
|
device_tree_find_boolean(device_tree *root,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
device_tree *node = device_tree_find_node(root,
|
device_tree *node;
|
||||||
path,
|
TRACE(trace_device_tree,
|
||||||
node_boolean,
|
("device_tree_find_boolean(root=0x%x, path=%s)\n", root, path));
|
||||||
device_tree_abort);
|
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;
|
return node->boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,9 +390,14 @@ STATIC_INLINE_DEVICE_TREE void
|
||||||
device_tree_init_device(device_tree *root,
|
device_tree_init_device(device_tree *root,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
psim *system = (psim*)data;
|
psim *system;
|
||||||
if (root->type == node_device)
|
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);
|
root->device->callback->init(root->device, system);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,7 +405,11 @@ INLINE_DEVICE_TREE void
|
||||||
device_tree_init(device_tree *root,
|
device_tree_init(device_tree *root,
|
||||||
psim *system)
|
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);
|
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 */
|
/* Parse a device name, various formats */
|
||||||
|
|
||||||
#ifndef __NetBSD__
|
|
||||||
#define strtouq strtoul
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SCAN_INIT(START, END, COUNT, NAME) \
|
#define SCAN_INIT(START, END, COUNT, NAME) \
|
||||||
char *START = NULL; \
|
char *START = NULL; \
|
||||||
char *END = strchr(NAME, '@'); \
|
char *END = strchr(NAME, '@'); \
|
||||||
|
@ -377,7 +464,7 @@ device_tree_dump(device_tree *device,
|
||||||
|
|
||||||
#define SCAN_U(START, END, COUNT, U) \
|
#define SCAN_U(START, END, COUNT, U) \
|
||||||
do { \
|
do { \
|
||||||
*U = strtouq(START, &END, 0); \
|
*U = strtoul(START, &END, 0); \
|
||||||
if (START == END) \
|
if (START == END) \
|
||||||
return COUNT; \
|
return COUNT; \
|
||||||
COUNT++; \
|
COUNT++; \
|
||||||
|
@ -397,7 +484,7 @@ do { \
|
||||||
START = END + 1; \
|
START = END + 1; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SCAN_C(START, END, COUNT, C) \
|
#define SCAN_C(START, END, COUNT, C, SIZE) \
|
||||||
do { \
|
do { \
|
||||||
char *chp = C; \
|
char *chp = C; \
|
||||||
END = START; \
|
END = START; \
|
||||||
|
@ -407,6 +494,8 @@ do { \
|
||||||
*chp = *END; \
|
*chp = *END; \
|
||||||
chp += 1; \
|
chp += 1; \
|
||||||
END += 1; \
|
END += 1; \
|
||||||
|
if ((SIZE) <= ((END) - (START))) \
|
||||||
|
return COUNT; /* overflow */ \
|
||||||
} \
|
} \
|
||||||
*chp = '\0'; \
|
*chp = '\0'; \
|
||||||
if (START == END) \
|
if (START == END) \
|
||||||
|
@ -465,21 +554,21 @@ scand_uw_uw_u(const char *name,
|
||||||
|
|
||||||
INLINE_DEVICE_TREE int
|
INLINE_DEVICE_TREE int
|
||||||
scand_c(const char *name,
|
scand_c(const char *name,
|
||||||
char *c1)
|
char *c1, int c1size)
|
||||||
{
|
{
|
||||||
SCAN_INIT(start, end, count, name);
|
SCAN_INIT(start, end, count, name);
|
||||||
SCAN_C(start, end, count, c1);
|
SCAN_C(start, end, count, c1, c1size);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE_DEVICE_TREE int
|
INLINE_DEVICE_TREE int
|
||||||
scand_c_uw_u(const char *name,
|
scand_c_uw_u(const char *name,
|
||||||
char *c1,
|
char *c1, int c1size,
|
||||||
unsigned_word *uw2,
|
unsigned_word *uw2,
|
||||||
unsigned *u3)
|
unsigned *u3)
|
||||||
{
|
{
|
||||||
SCAN_INIT(start, end, count, name);
|
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, uw2);
|
||||||
SCAN_U(start, end, count, u3);
|
SCAN_U(start, end, count, u3);
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -110,7 +110,11 @@ INLINE_DEVICE_TREE void device_tree_dump
|
||||||
void *ignore_data_argument);
|
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
|
INLINE_DEVICE_TREE int scand_uw
|
||||||
(const char *name,
|
(const char *name,
|
||||||
|
@ -135,11 +139,11 @@ INLINE_DEVICE_TREE int scand_uw_uw_u
|
||||||
|
|
||||||
INLINE_DEVICE_TREE int scand_c
|
INLINE_DEVICE_TREE int scand_c
|
||||||
(const char *name,
|
(const char *name,
|
||||||
char *c1);
|
char *c1, int c1size);
|
||||||
|
|
||||||
INLINE_DEVICE_TREE int scand_c_uw_u
|
INLINE_DEVICE_TREE int scand_c_uw_u
|
||||||
(const char *name,
|
(const char *name,
|
||||||
char *c1,
|
char *c1, int c1size,
|
||||||
unsigned_word *uw2,
|
unsigned_word *uw2,
|
||||||
unsigned *u3);
|
unsigned *u3);
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ generic_init_callback(const device *me,
|
||||||
me->parent->callback->attach_address(me->parent,
|
me->parent->callback->attach_address(me->parent,
|
||||||
me->name,
|
me->name,
|
||||||
attach_callback,
|
attach_callback,
|
||||||
0 /*address_space*/,
|
0 /*space*/,
|
||||||
addr,
|
addr,
|
||||||
nr_bytes,
|
nr_bytes,
|
||||||
access_read_write,
|
access_read_write,
|
||||||
|
@ -81,7 +81,7 @@ INLINE_DEVICES void
|
||||||
unimp_device_attach_address(const device *me,
|
unimp_device_attach_address(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type type,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
|
@ -94,7 +94,7 @@ INLINE_DEVICES void
|
||||||
unimp_device_detach_address(const device *me,
|
unimp_device_detach_address(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type type,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
|
@ -106,7 +106,7 @@ unimp_device_detach_address(const device *me,
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
unimp_device_io_read_buffer(const device *me,
|
unimp_device_io_read_buffer(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
|
@ -119,7 +119,7 @@ unimp_device_io_read_buffer(const device *me,
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
unimp_device_io_write_buffer(const device *me,
|
unimp_device_io_write_buffer(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
|
@ -132,7 +132,7 @@ unimp_device_io_write_buffer(const device *me,
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
unimp_device_dma_read_buffer(const device *me,
|
unimp_device_dma_read_buffer(const device *me,
|
||||||
void *target,
|
void *target,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes)
|
unsigned nr_bytes)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +143,7 @@ unimp_device_dma_read_buffer(const device *me,
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
unimp_device_dma_write_buffer(const device *me,
|
unimp_device_dma_write_buffer(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
int violate_read_only_section)
|
int violate_read_only_section)
|
||||||
|
@ -213,15 +213,16 @@ ignore_device_init(const device *me,
|
||||||
INLINE_DEVICES void
|
INLINE_DEVICES void
|
||||||
pass_device_attach_address(const device *me,
|
pass_device_attach_address(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
const device *who) /*callback/default*/
|
const device *who) /*callback/default*/
|
||||||
{
|
{
|
||||||
me->parent->callback->attach_address(me->parent, name, type,
|
DTRACE_ATTACH_ADDRESS(pass);
|
||||||
address_space, addr, nr_bytes,
|
me->parent->callback->attach_address(me->parent, name, attach,
|
||||||
|
space, addr, nr_bytes,
|
||||||
access,
|
access,
|
||||||
who);
|
who);
|
||||||
}
|
}
|
||||||
|
@ -229,39 +230,42 @@ pass_device_attach_address(const device *me,
|
||||||
INLINE_DEVICES void
|
INLINE_DEVICES void
|
||||||
pass_device_detach_address(const device *me,
|
pass_device_detach_address(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
const device *who) /*callback/default*/
|
const device *who) /*callback/default*/
|
||||||
{
|
{
|
||||||
me->parent->callback->detach_address(me->parent, name, type,
|
DTRACE_DETACH_ADDRESS(pass);
|
||||||
address_space, addr, nr_bytes, access,
|
me->parent->callback->detach_address(me->parent, name, attach,
|
||||||
|
space, addr, nr_bytes, access,
|
||||||
who);
|
who);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
pass_device_dma_read_buffer(const device *me,
|
pass_device_dma_read_buffer(const device *me,
|
||||||
void *target,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes)
|
unsigned nr_bytes)
|
||||||
{
|
{
|
||||||
return me->parent->callback->dma_read_buffer(me->parent, target,
|
DTRACE_DMA_READ_BUFFER(pass);
|
||||||
address_space, addr, nr_bytes);
|
return me->parent->callback->dma_read_buffer(me->parent, dest,
|
||||||
|
space, addr, nr_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE_DEVICES unsigned
|
INLINE_DEVICES unsigned
|
||||||
pass_device_dma_write_buffer(const device *me,
|
pass_device_dma_write_buffer(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
int violate_read_only_section)
|
int violate_read_only_section)
|
||||||
{
|
{
|
||||||
|
DTRACE_DMA_WRITE_BUFFER(pass);
|
||||||
return me->parent->callback->dma_write_buffer(me->parent, source,
|
return me->parent->callback->dma_write_buffer(me->parent, source,
|
||||||
address_space, addr,
|
space, addr,
|
||||||
nr_bytes,
|
nr_bytes,
|
||||||
violate_read_only_section);
|
violate_read_only_section);
|
||||||
}
|
}
|
||||||
|
@ -341,7 +345,7 @@ typedef enum {
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
console_io_read_buffer_callback(const device *me,
|
console_io_read_buffer_callback(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
|
@ -349,9 +353,7 @@ console_io_read_buffer_callback(const device *me,
|
||||||
{
|
{
|
||||||
console_device *console = (console_device*)me->data;
|
console_device *console = (console_device*)me->data;
|
||||||
unsigned_1 val;
|
unsigned_1 val;
|
||||||
TRACE(trace_console_device,
|
DTRACE_IO_READ_BUFFER(console);
|
||||||
("device=0x%x, addr=0x%x, nr_bytes=%d\n",
|
|
||||||
me, addr, nr_bytes));
|
|
||||||
|
|
||||||
/* determine what was read */
|
/* determine what was read */
|
||||||
|
|
||||||
|
@ -416,7 +418,7 @@ console_io_read_buffer_callback(const device *me,
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
console_io_write_buffer_callback(const device *me,
|
console_io_write_buffer_callback(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
|
@ -424,10 +426,7 @@ console_io_write_buffer_callback(const device *me,
|
||||||
{
|
{
|
||||||
console_device *console = (console_device*)me->data;
|
console_device *console = (console_device*)me->data;
|
||||||
unsigned_1 val = *(unsigned8*)source;
|
unsigned_1 val = *(unsigned8*)source;
|
||||||
|
DTRACE_IO_WRITE_BUFFER(console);
|
||||||
TRACE(trace_console_device,
|
|
||||||
("device=0x%x, addr=0x%x, nr_bytes=%d, val=%d\n",
|
|
||||||
me, addr, nr_bytes, val));
|
|
||||||
|
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case console_read_buffer:
|
case console_read_buffer:
|
||||||
|
@ -437,8 +436,7 @@ console_io_write_buffer_callback(const device *me,
|
||||||
console->input.status = val;
|
console->input.status = val;
|
||||||
break;
|
break;
|
||||||
case console_write_buffer:
|
case console_write_buffer:
|
||||||
TRACE(trace_console_device,
|
DTRACE(console, ("<%c:%d>", val, val));
|
||||||
("<%c:%d>", val, val));
|
|
||||||
printf_filtered("%c",val) ;
|
printf_filtered("%c",val) ;
|
||||||
console->output.buffer = val;
|
console->output.buffer = val;
|
||||||
console->output.status = 1;
|
console->output.status = 1;
|
||||||
|
@ -472,6 +470,7 @@ static device_callbacks const console_callbacks = {
|
||||||
|
|
||||||
STATIC_INLINE_DEVICES const device *
|
STATIC_INLINE_DEVICES const device *
|
||||||
console_create(const char *name,
|
console_create(const char *name,
|
||||||
|
const char *full_name,
|
||||||
const device *parent)
|
const device *parent)
|
||||||
{
|
{
|
||||||
/* create the descriptor */
|
/* create the descriptor */
|
||||||
|
@ -485,6 +484,7 @@ console_create(const char *name,
|
||||||
|
|
||||||
/* insert into the device tree along with its address info */
|
/* insert into the device tree along with its address info */
|
||||||
return device_create_from(name,
|
return device_create_from(name,
|
||||||
|
full_name,
|
||||||
console, /* data */
|
console, /* data */
|
||||||
&console_callbacks,
|
&console_callbacks,
|
||||||
parent);
|
parent);
|
||||||
|
@ -507,16 +507,14 @@ console_create(const char *name,
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
icu_io_read_buffer_callback(const device *me,
|
icu_io_read_buffer_callback(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word base,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
unsigned_1 val;
|
unsigned_1 val;
|
||||||
TRACE(trace_icu_device,
|
DTRACE_IO_READ_BUFFER(icu);
|
||||||
("device=0x%x, base=0x%x, nr_bytes=%d\n",
|
|
||||||
me, base, nr_bytes));
|
|
||||||
val = cpu_nr(processor);
|
val = cpu_nr(processor);
|
||||||
bzero(dest, nr_bytes);
|
bzero(dest, nr_bytes);
|
||||||
*(unsigned_1*)dest = val;
|
*(unsigned_1*)dest = val;
|
||||||
|
@ -527,17 +525,15 @@ icu_io_read_buffer_callback(const device *me,
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
icu_io_write_buffer_callback(const device *me,
|
icu_io_write_buffer_callback(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word base,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
psim *system = cpu_system(processor);
|
psim *system = cpu_system(processor);
|
||||||
unsigned_1 val = H2T_1(*(unsigned_1*)source);
|
unsigned_1 val = H2T_1(*(unsigned_1*)source);
|
||||||
TRACE(trace_icu_device,
|
DTRACE_IO_WRITE_BUFFER(icu);
|
||||||
("device=0x%x, base=0x%x, nr_bytes=%d, val=0x%x\n",
|
|
||||||
me, base, nr_bytes, val));
|
|
||||||
/* tell the parent device that the interrupt lines have changed.
|
/* tell the parent device that the interrupt lines have changed.
|
||||||
For this fake ICU. The interrupt lines just indicate the cpu to
|
For this fake ICU. The interrupt lines just indicate the cpu to
|
||||||
interrupt next */
|
interrupt next */
|
||||||
|
@ -575,12 +571,13 @@ static device_callbacks const icu_callbacks = {
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
halt_io_read_buffer_callback(const device *me,
|
halt_io_read_buffer_callback(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word base,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
|
DTRACE_IO_READ_BUFFER(halt);
|
||||||
cpu_halt(processor, cia, was_exited, 0);
|
cpu_halt(processor, cia, was_exited, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -589,12 +586,13 @@ halt_io_read_buffer_callback(const device *me,
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
halt_io_write_buffer_callback(const device *me,
|
halt_io_write_buffer_callback(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
|
DTRACE_IO_WRITE_BUFFER(halt);
|
||||||
cpu_halt(processor, cia, was_exited, 0);
|
cpu_halt(processor, cia, was_exited, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -630,7 +628,8 @@ register_init_callback(const device *me,
|
||||||
unsigned_word value;
|
unsigned_word value;
|
||||||
unsigned which_cpu;
|
unsigned which_cpu;
|
||||||
int status;
|
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) {
|
switch (status) {
|
||||||
case 2: /* register@<name>,<value> */
|
case 2: /* register@<name>,<value> */
|
||||||
psim_write_register(system, -1, &value, name, cooked_transfer);
|
psim_write_register(system, -1, &value, name, cooked_transfer);
|
||||||
|
@ -702,6 +701,7 @@ vm_init_callback(const device *me,
|
||||||
psim *system)
|
psim *system)
|
||||||
{
|
{
|
||||||
vm_device *vm = (vm_device*)me->data;
|
vm_device *vm = (vm_device*)me->data;
|
||||||
|
DTRACE_INIT(vm);
|
||||||
|
|
||||||
/* revert the stack/heap variables to their defaults */
|
/* revert the stack/heap variables to their defaults */
|
||||||
vm->stack_lower_limit = vm->stack_bound;
|
vm->stack_lower_limit = vm->stack_bound;
|
||||||
|
@ -724,14 +724,15 @@ vm_init_callback(const device *me,
|
||||||
STATIC_INLINE_DEVICES void
|
STATIC_INLINE_DEVICES void
|
||||||
vm_attach_address(const device *me,
|
vm_attach_address(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
const device *who) /*callback/default*/
|
const device *who) /*callback/default*/
|
||||||
{
|
{
|
||||||
vm_device *vm = (vm_device*)me->data;
|
vm_device *vm = (vm_device*)me->data;
|
||||||
|
DTRACE_ATTACH_ADDRESS(vm);
|
||||||
/* update end of bss if necessary */
|
/* update end of bss if necessary */
|
||||||
if (vm->heap_base < addr + nr_bytes) {
|
if (vm->heap_base < addr + nr_bytes) {
|
||||||
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
|
STATIC_INLINE_DEVICES unsigned
|
||||||
vm_io_read_buffer_callback(const device *me,
|
vm_io_read_buffer_callback(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
|
DTRACE_IO_READ_BUFFER(vm);
|
||||||
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
|
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
|
||||||
bzero(dest, nr_bytes); /* always initialized to zero */
|
bzero(dest, nr_bytes); /* always initialized to zero */
|
||||||
return nr_bytes;
|
return nr_bytes;
|
||||||
|
@ -817,15 +819,16 @@ vm_io_read_buffer_callback(const device *me,
|
||||||
STATIC_INLINE_DEVICES unsigned
|
STATIC_INLINE_DEVICES unsigned
|
||||||
vm_io_write_buffer_callback(const device *me,
|
vm_io_write_buffer_callback(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia)
|
unsigned_word cia)
|
||||||
{
|
{
|
||||||
|
DTRACE_IO_WRITE_BUFFER(vm);
|
||||||
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
|
if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
|
||||||
return me->parent->callback->dma_write_buffer(me->parent, source,
|
return me->parent->callback->dma_write_buffer(me->parent, source,
|
||||||
address_space, addr,
|
space, addr,
|
||||||
nr_bytes,
|
nr_bytes,
|
||||||
0/*violate_read_only*/);
|
0/*violate_read_only*/);
|
||||||
}
|
}
|
||||||
|
@ -873,7 +876,8 @@ static device_callbacks const vm_callbacks = {
|
||||||
|
|
||||||
STATIC_INLINE_DEVICES const device *
|
STATIC_INLINE_DEVICES const device *
|
||||||
vea_vm_create(const char *name,
|
vea_vm_create(const char *name,
|
||||||
const device *parent)
|
const char *full_name,
|
||||||
|
const device *parent)
|
||||||
{
|
{
|
||||||
vm_device *vm = ZALLOC(vm_device);
|
vm_device *vm = ZALLOC(vm_device);
|
||||||
unsigned_word addr;
|
unsigned_word addr;
|
||||||
|
@ -887,6 +891,7 @@ vea_vm_create(const char *name,
|
||||||
|
|
||||||
/* insert in the tree including the buffer */
|
/* insert in the tree including the buffer */
|
||||||
return device_create_from(name,
|
return device_create_from(name,
|
||||||
|
full_name,
|
||||||
vm, /* data */
|
vm, /* data */
|
||||||
&vm_callbacks,
|
&vm_callbacks,
|
||||||
parent);
|
parent);
|
||||||
|
@ -905,9 +910,20 @@ memory_init_callback(const device *me,
|
||||||
unsigned_word addr;
|
unsigned_word addr;
|
||||||
unsigned nr_bytes;
|
unsigned nr_bytes;
|
||||||
unsigned access;
|
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);
|
error("memory_init_callback() invalid memory device %s\n", me->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
me->parent->callback->attach_address(me->parent,
|
me->parent->callback->attach_address(me->parent,
|
||||||
me->name,
|
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>
|
/* IOBUS device: iobus@<address>
|
||||||
|
|
||||||
|
@ -963,7 +961,7 @@ STATIC_INLINE_DEVICES void
|
||||||
iobus_attach_address_callback(const device *me,
|
iobus_attach_address_callback(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type type,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
|
@ -974,8 +972,8 @@ iobus_attach_address_callback(const device *me,
|
||||||
if (type == attach_default)
|
if (type == attach_default)
|
||||||
error("iobus_attach_address_callback() no default for %s/%s\n",
|
error("iobus_attach_address_callback() no default for %s/%s\n",
|
||||||
me->name, name);
|
me->name, name);
|
||||||
if (address_space != 0)
|
if (space != 0)
|
||||||
error("iobus_attach_address_callback() no address_space for %s/%s\n",
|
error("iobus_attach_address_callback() no space for %s/%s\n",
|
||||||
me->name, name);
|
me->name, name);
|
||||||
/* get the bus address */
|
/* get the bus address */
|
||||||
if (scand_uw(me->name, &iobus_addr) != 1)
|
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->parent->callback->attach_address(me->parent,
|
||||||
me->name,
|
me->name,
|
||||||
type,
|
type,
|
||||||
0 /*address_space*/,
|
0 /*space*/,
|
||||||
iobus_addr + addr,
|
iobus_addr + addr,
|
||||||
nr_bytes,
|
nr_bytes,
|
||||||
access,
|
access,
|
||||||
|
@ -1052,9 +1050,11 @@ file_init_callback(const device *me,
|
||||||
psim *system)
|
psim *system)
|
||||||
{
|
{
|
||||||
unsigned_word addr;
|
unsigned_word addr;
|
||||||
|
unsigned count;
|
||||||
char *file_name;
|
char *file_name;
|
||||||
char buf;
|
char buf;
|
||||||
FILE *image;
|
FILE *image;
|
||||||
|
DTRACE_INIT(file);
|
||||||
|
|
||||||
if ((file_name = strchr(me->name, ',')) == NULL
|
if ((file_name = strchr(me->name, ',')) == NULL
|
||||||
|| scand_uw(me->name, &addr) != 1)
|
|| 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);
|
error("file_init_callback() file open failed for %s\n", me->name);
|
||||||
|
|
||||||
/* read it in slowly */
|
/* read it in slowly */
|
||||||
|
count = 0;
|
||||||
while (fread(&buf, 1, 1, image) > 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,
|
&buf,
|
||||||
0 /*address-space*/,
|
0 /*address-space*/,
|
||||||
addr,
|
addr+count,
|
||||||
1 /*nr-bytes*/,
|
1 /*nr-bytes*/,
|
||||||
1 /*violate ro*/);
|
1 /*violate ro*/) != 1)
|
||||||
addr++;
|
error("file_init_callback() failed to write to address 0x%x, offset %d\n",
|
||||||
|
addr+count, count);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close down again */
|
/* close down again */
|
||||||
|
@ -1115,6 +1118,7 @@ STATIC_INLINE_DEVICES void
|
||||||
htab_init_callback(const device *me,
|
htab_init_callback(const device *me,
|
||||||
psim *system)
|
psim *system)
|
||||||
{
|
{
|
||||||
|
DTRACE_INIT(htab);
|
||||||
/* only the pte does work */
|
/* only the pte does work */
|
||||||
if (strncmp(me->name, "pte@", strlen("pte@")) == 0) {
|
if (strncmp(me->name, "pte@", strlen("pte@")) == 0) {
|
||||||
unsigned_word htab_ra;
|
unsigned_word htab_ra;
|
||||||
|
@ -1184,12 +1188,10 @@ static device_callbacks const sim_callbacks = {
|
||||||
this device loads or maps the relevant text/data segments into
|
this device loads or maps the relevant text/data segments into
|
||||||
memory using dma. */
|
memory using dma. */
|
||||||
|
|
||||||
/* create a device tree from the image */
|
|
||||||
|
|
||||||
STATIC_INLINE_DEVICES void
|
STATIC_INLINE_DEVICES void
|
||||||
update_device_tree_for_section(bfd *abfd,
|
update_for_binary_section(bfd *abfd,
|
||||||
asection *the_section,
|
asection *the_section,
|
||||||
PTR obj)
|
PTR obj)
|
||||||
{
|
{
|
||||||
unsigned_word section_vma;
|
unsigned_word section_vma;
|
||||||
unsigned_word section_size;
|
unsigned_word section_size;
|
||||||
|
@ -1208,17 +1210,17 @@ update_device_tree_for_section(bfd *abfd,
|
||||||
/* find where it is to go */
|
/* find where it is to go */
|
||||||
section_vma = bfd_get_section_vma(abfd, the_section);
|
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",
|
("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
|
||||||
bfd_get_section_name(abfd, the_section),
|
bfd_get_section_name(abfd, the_section),
|
||||||
section_vma, section_size,
|
section_vma, section_size,
|
||||||
bfd_get_section_flags(abfd, the_section),
|
bfd_get_section_flags(abfd, the_section),
|
||||||
bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
|
bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
|
||||||
bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
|
bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
|
||||||
bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
|
bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
|
||||||
bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
|
bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
|
||||||
bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
|
bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
|
||||||
));
|
));
|
||||||
|
|
||||||
/* determine the devices access */
|
/* determine the devices access */
|
||||||
access = access_read;
|
access = access_read;
|
||||||
|
@ -1251,7 +1253,7 @@ update_device_tree_for_section(bfd *abfd,
|
||||||
}
|
}
|
||||||
if (me->parent->callback->dma_write_buffer(me->parent,
|
if (me->parent->callback->dma_write_buffer(me->parent,
|
||||||
section_init,
|
section_init,
|
||||||
0 /*address_space*/,
|
0 /*space*/,
|
||||||
section_vma,
|
section_vma,
|
||||||
section_size,
|
section_size,
|
||||||
1 /*violate_read_only*/)
|
1 /*violate_read_only*/)
|
||||||
|
@ -1268,9 +1270,10 @@ binary_init_callback(const device *me,
|
||||||
{
|
{
|
||||||
char file_name[100];
|
char file_name[100];
|
||||||
bfd *image;
|
bfd *image;
|
||||||
|
DTRACE_INIT(binary);
|
||||||
|
|
||||||
/* get a file name */
|
/* 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",
|
error("load_binary_init_callback() invalid load-binary device %s\n",
|
||||||
me->name);
|
me->name);
|
||||||
|
|
||||||
|
@ -1291,7 +1294,7 @@ binary_init_callback(const device *me,
|
||||||
|
|
||||||
/* and the data sections */
|
/* and the data sections */
|
||||||
bfd_map_over_sections(image,
|
bfd_map_over_sections(image,
|
||||||
update_device_tree_for_section,
|
update_for_binary_section,
|
||||||
(PTR)me);
|
(PTR)me);
|
||||||
|
|
||||||
bfd_close(image);
|
bfd_close(image);
|
||||||
|
@ -1371,18 +1374,17 @@ write_stack_arguments(psim *system,
|
||||||
unsigned_word start_arg,
|
unsigned_word start_arg,
|
||||||
unsigned_word end_arg)
|
unsigned_word end_arg)
|
||||||
{
|
{
|
||||||
TRACE(trace_create_stack,
|
DTRACE(stack,
|
||||||
("write_stack_arguments() - %s=0x%x %s=0x%x %s=0x%x %s=0x%x\n",
|
("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", system, "arg", arg,
|
system, arg, start_block, end_block, start_arg, end_arg));
|
||||||
"start_block", start_block, "start_arg", start_arg));
|
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
error("write_arguments: character array NULL\n");
|
error("write_arguments: character array NULL\n");
|
||||||
/* only copy in arguments, memory is already zero */
|
/* only copy in arguments, memory is already zero */
|
||||||
for (; *arg != NULL; arg++) {
|
for (; *arg != NULL; arg++) {
|
||||||
int len = strlen(*arg)+1;
|
int len = strlen(*arg)+1;
|
||||||
unsigned_word target_start_block;
|
unsigned_word target_start_block;
|
||||||
TRACE(trace_create_stack,
|
DTRACE(stack,
|
||||||
("write_stack_arguments - write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
|
("write_stack_arguments() write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
|
||||||
"**arg", *arg, "start_block", start_block,
|
"**arg", *arg, "start_block", start_block,
|
||||||
"len", len, "start_arg", start_arg));
|
"len", len, "start_arg", start_arg));
|
||||||
if (psim_write_memory(system, 0, *arg,
|
if (psim_write_memory(system, 0, *arg,
|
||||||
|
@ -1402,6 +1404,8 @@ write_stack_arguments(psim *system,
|
||||||
if (start_block != end_block
|
if (start_block != end_block
|
||||||
|| ALIGN_8(start_arg) != end_arg)
|
|| ALIGN_8(start_arg) != end_arg)
|
||||||
error("write_stack_arguments - possible corruption\n");
|
error("write_stack_arguments - possible corruption\n");
|
||||||
|
DTRACE(stack,
|
||||||
|
("write_stack_arguments() = void\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC_INLINE_DEVICES void
|
STATIC_INLINE_DEVICES void
|
||||||
|
@ -1500,10 +1504,16 @@ stack_ioctl_callback(const device *me,
|
||||||
stack_pointer = va_arg(ap, unsigned_word);
|
stack_pointer = va_arg(ap, unsigned_word);
|
||||||
argv = va_arg(ap, char **);
|
argv = va_arg(ap, char **);
|
||||||
envp = 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)
|
if (strcmp(me->name, "stack@elf") == 0)
|
||||||
create_elf_stack_frame(system, stack_pointer, argv, envp);
|
create_elf_stack_frame(system, stack_pointer, argv, envp);
|
||||||
else if (strcmp(me->name, "stack@xcoff") == 0)
|
else if (strcmp(me->name, "stack@xcoff") == 0)
|
||||||
create_aix_stack_frame(system, stack_pointer, argv, envp);
|
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)
|
typedef const device *(device_creator)
|
||||||
(const char *name,
|
(const char *name,
|
||||||
|
const char *full_name,
|
||||||
const device *parent);
|
const device *parent);
|
||||||
|
|
||||||
typedef struct _device_descriptor device_descriptor;
|
typedef struct _device_descriptor device_descriptor;
|
||||||
|
@ -1540,7 +1551,7 @@ struct _device_descriptor {
|
||||||
|
|
||||||
static device_descriptor devices[] = {
|
static device_descriptor devices[] = {
|
||||||
{ "console", console_create, NULL },
|
{ "console", console_create, NULL },
|
||||||
{ "memory", memory_create, NULL },
|
{ "memory", NULL, &memory_callbacks },
|
||||||
{ "vm", vea_vm_create, NULL },
|
{ "vm", vea_vm_create, NULL },
|
||||||
{ "halt", NULL, &halt_callbacks },
|
{ "halt", NULL, &halt_callbacks },
|
||||||
{ "icu", NULL, &icu_callbacks },
|
{ "icu", NULL, &icu_callbacks },
|
||||||
|
@ -1559,6 +1570,7 @@ static device_descriptor devices[] = {
|
||||||
|
|
||||||
INLINE_DEVICES const device *
|
INLINE_DEVICES const device *
|
||||||
device_create(const char *name,
|
device_create(const char *name,
|
||||||
|
const char *full_name,
|
||||||
const device *parent)
|
const device *parent)
|
||||||
{
|
{
|
||||||
device_descriptor *device;
|
device_descriptor *device;
|
||||||
|
@ -1571,9 +1583,10 @@ device_create(const char *name,
|
||||||
&& (device->name[name_len] == '\0'
|
&& (device->name[name_len] == '\0'
|
||||||
|| device->name[name_len] == '@'))
|
|| device->name[name_len] == '@'))
|
||||||
if (device->creator != NULL)
|
if (device->creator != NULL)
|
||||||
return device->creator(name, parent);
|
return device->creator(name, full_name, parent);
|
||||||
else
|
else
|
||||||
return device_create_from(name,
|
return device_create_from(name,
|
||||||
|
full_name,
|
||||||
NULL /* data */,
|
NULL /* data */,
|
||||||
device->callbacks,
|
device->callbacks,
|
||||||
parent);
|
parent);
|
||||||
|
@ -1585,12 +1598,14 @@ device_create(const char *name,
|
||||||
|
|
||||||
INLINE_DEVICES const device *
|
INLINE_DEVICES const device *
|
||||||
device_create_from(const char *name,
|
device_create_from(const char *name,
|
||||||
|
const char *full_name,
|
||||||
void *data,
|
void *data,
|
||||||
const device_callbacks *callback,
|
const device_callbacks *callback,
|
||||||
const device *parent)
|
const device *parent)
|
||||||
{
|
{
|
||||||
device *me = ZALLOC(device);
|
device *me = ZALLOC(device);
|
||||||
me->name = strdup(name);
|
me->name = strdup(name);
|
||||||
|
me->full_name = strdup(full_name);
|
||||||
me->data = data;
|
me->data = data;
|
||||||
me->callback = callback;
|
me->callback = callback;
|
||||||
me->parent = parent;
|
me->parent = parent;
|
||||||
|
|
|
@ -79,6 +79,10 @@ typedef void (device_init_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
psim *system);
|
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:
|
/* Data transfers:
|
||||||
|
|
||||||
|
@ -160,17 +164,27 @@ typedef void (device_init_callback)
|
||||||
typedef void (device_config_address_callback)
|
typedef void (device_config_address_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
const char *name,
|
const char *name,
|
||||||
attach_type type,
|
attach_type attach,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
access_type access,
|
access_type access,
|
||||||
const device *who); /*callback/default*/
|
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)
|
typedef unsigned (device_io_read_buffer_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
|
@ -179,27 +193,46 @@ typedef unsigned (device_io_read_buffer_callback)
|
||||||
typedef unsigned (device_io_write_buffer_callback)
|
typedef unsigned (device_io_write_buffer_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
cpu *processor,
|
cpu *processor,
|
||||||
unsigned_word cia);
|
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)
|
typedef unsigned (device_dma_read_buffer_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
void *dest,
|
void *dest,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes);
|
unsigned nr_bytes);
|
||||||
|
|
||||||
typedef unsigned (device_dma_write_buffer_callback)
|
typedef unsigned (device_dma_write_buffer_callback)
|
||||||
(const device *me,
|
(const device *me,
|
||||||
const void *source,
|
const void *source,
|
||||||
int address_space,
|
int space,
|
||||||
unsigned_word addr,
|
unsigned_word addr,
|
||||||
unsigned nr_bytes,
|
unsigned nr_bytes,
|
||||||
int violate_read_only_section);
|
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:
|
/* Interrupts:
|
||||||
|
|
||||||
|
@ -282,7 +315,8 @@ typedef struct _device_callbacks {
|
||||||
|
|
||||||
/* A device */
|
/* A device */
|
||||||
struct _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 */
|
void *data; /* device specific data */
|
||||||
const device_callbacks *callback;
|
const device_callbacks *callback;
|
||||||
const device *parent;
|
const device *parent;
|
||||||
|
@ -293,12 +327,14 @@ struct _device {
|
||||||
|
|
||||||
INLINE_DEVICES const device *device_create
|
INLINE_DEVICES const device *device_create
|
||||||
(const char *name,
|
(const char *name,
|
||||||
|
const char *full_name,
|
||||||
const device *parent);
|
const device *parent);
|
||||||
|
|
||||||
/* create a new device using the parameterized data */
|
/* create a new device using the parameterized data */
|
||||||
|
|
||||||
INLINE_DEVICES const device *device_create_from
|
INLINE_DEVICES const device *device_create_from
|
||||||
(const char *name,
|
(const char *name,
|
||||||
|
const char *full_name,
|
||||||
void *data,
|
void *data,
|
||||||
const device_callbacks *callback,
|
const device_callbacks *callback,
|
||||||
const device *parent);
|
const device *parent);
|
||||||
|
|
|
@ -19,15 +19,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef _SYSTEM_H_
|
#ifndef _EMUL_NETBSD_H_
|
||||||
#define _SYSTEM_H_
|
#define _EMUL_NETBSD_H_
|
||||||
|
|
||||||
#ifndef INLINE_SYSTEM
|
extern emulation emul_netbsd;
|
||||||
#define INLINE_SYSTEM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INLINE_SYSTEM void system_call
|
|
||||||
(cpu *processor,
|
|
||||||
unsigned_word cia);
|
|
||||||
|
|
||||||
#endif
|
#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 "ppc-endian.h"
|
||||||
#include "sim_callbacks.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)
|
#define SWAP_2(SET,RAW) SET htons (RAW)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ endian_##NAME##_##BYTE_SIZE(unsigned_##BYTE_SIZE raw_in) \
|
||||||
return raw_in; \
|
return raw_in; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
SWAP_##BYTE_SIZE(return, raw_in); \
|
SWAP_##BYTE_SIZE(return,raw_in); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
of the host/target it is able to eliminate slower generic endian
|
||||||
handling code.
|
handling code.
|
||||||
|
|
||||||
If ENDIAN_OK is true then no byte swapping is required. If it is
|
Possible values are 0 (unknown), LITTLE_ENDIAN, BIG_ENDIAN */
|
||||||
false, copy-in / copy-out functions assume that data should be byte
|
|
||||||
reversed as part of the copy. */
|
|
||||||
|
|
||||||
|
#ifndef WITH_HOST_BYTE_ORDER
|
||||||
#define WITH_HOST_BYTE_ORDER 0 /*unknown*/
|
#define WITH_HOST_BYTE_ORDER 0 /*unknown*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WITH_TARGET_BYTE_ORDER
|
||||||
#define WITH_TARGET_BYTE_ORDER 0 /*unknown*/
|
#define WITH_TARGET_BYTE_ORDER 0 /*unknown*/
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int current_host_byte_order;
|
extern int current_host_byte_order;
|
||||||
extern int current_target_byte_order;
|
|
||||||
#define CURRENT_HOST_BYTE_ORDER (WITH_HOST_BYTE_ORDER \
|
#define CURRENT_HOST_BYTE_ORDER (WITH_HOST_BYTE_ORDER \
|
||||||
? WITH_HOST_BYTE_ORDER \
|
? WITH_HOST_BYTE_ORDER \
|
||||||
: current_host_byte_order)
|
: current_host_byte_order)
|
||||||
|
extern int current_target_byte_order;
|
||||||
#define CURRENT_TARGET_BYTE_ORDER (WITH_TARGET_BYTE_ORDER \
|
#define CURRENT_TARGET_BYTE_ORDER (WITH_TARGET_BYTE_ORDER \
|
||||||
? WITH_TARGET_BYTE_ORDER \
|
? WITH_TARGET_BYTE_ORDER \
|
||||||
: current_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:
|
/* SMP support:
|
||||||
|
|
||||||
Sets a limit on the number of processors that can be simulated. If
|
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
|
WITH_SMP is set to zero (0), the simulator is restricted to
|
||||||
suporting only on processor (and as a consequence leaves the SMP
|
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
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,6 +88,7 @@ extern int current_target_byte_order;
|
||||||
#ifndef WITH_TARGET_WORD_BITSIZE
|
#ifndef WITH_TARGET_WORD_BITSIZE
|
||||||
#define WITH_TARGET_WORD_BITSIZE 32 /* compiled only */
|
#define WITH_TARGET_WORD_BITSIZE 32 /* compiled only */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WITH_HOST_WORD_BITSIZE
|
#ifndef WITH_HOST_WORD_BITSIZE
|
||||||
#define WITH_HOST_WORD_BITSIZE 32 /* 64bit ready? */
|
#define WITH_HOST_WORD_BITSIZE 32 /* 64bit ready? */
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,10 +106,13 @@ extern int current_target_byte_order;
|
||||||
CURRENT_ENVIRONMENT specifies which of vea or oea is required for
|
CURRENT_ENVIRONMENT specifies which of vea or oea is required for
|
||||||
the current runtime. */
|
the current runtime. */
|
||||||
|
|
||||||
#define WITH_ENVIRONMENT 0
|
|
||||||
#define VIRTUAL_ENVIRONMENT 1
|
#define VIRTUAL_ENVIRONMENT 1
|
||||||
#define OPERATING_ENVIRONMENT 2
|
#define OPERATING_ENVIRONMENT 2
|
||||||
|
|
||||||
|
#ifndef WITH_ENVIRONMENT
|
||||||
|
#define WITH_ENVIRONMENT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int current_environment;
|
extern int current_environment;
|
||||||
#define CURRENT_ENVIRONMENT (WITH_ENVIRONMENT \
|
#define CURRENT_ENVIRONMENT (WITH_ENVIRONMENT \
|
||||||
? WITH_ENVIRONMENT \
|
? WITH_ENVIRONMENT \
|
||||||
|
@ -170,6 +194,7 @@ extern int current_environment;
|
||||||
#ifndef WITH_ALIGNMENT
|
#ifndef WITH_ALIGNMENT
|
||||||
#define WITH_ALIGNMENT 0
|
#define WITH_ALIGNMENT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int current_alignment;
|
extern int current_alignment;
|
||||||
#define CURRENT_ALIGNMENT (WITH_ALIGNMENT \
|
#define CURRENT_ALIGNMENT (WITH_ALIGNMENT \
|
||||||
? WITH_ALIGNMENT \
|
? WITH_ALIGNMENT \
|
||||||
|
@ -210,254 +235,16 @@ extern int current_floating_point;
|
||||||
#define WITH_ASSERT 1
|
#define WITH_ASSERT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* include profiling code that doesn't yet exist */
|
/* include monitoring code */
|
||||||
|
|
||||||
#ifndef WITH_PROFILE
|
#define MONITOR_INSTRUCTION_ISSUE 1
|
||||||
#define WITH_PROFILE 1
|
#define MONITOR_LOAD_STORE_UNIT 2
|
||||||
|
#ifndef WITH_MON
|
||||||
|
#define WITH_MON (MONITOR_LOAD_STORE_UNIT \
|
||||||
|
| MONITOR_INSTRUCTION_ISSUE)
|
||||||
#endif
|
#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:
|
/* INLINE CODE SELECTION:
|
||||||
|
|
||||||
|
@ -486,12 +273,14 @@ extern int current_floating_point;
|
||||||
controled by the <module>_INLINE macro's. Where each can have a
|
controled by the <module>_INLINE macro's. Where each can have a
|
||||||
value:
|
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
|
1 Include the module but to not inline functions within it.
|
||||||
the in lineing of that modules external calls)
|
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
|
Finally, this is not for the faint harted. I've seen GCC get up to
|
||||||
200mb trying to compile what this can create */
|
200mb trying to compile what this can create */
|
||||||
|
@ -512,86 +301,92 @@ extern int current_floating_point;
|
||||||
#define STATIC_INLINE static INLINE
|
#define STATIC_INLINE static INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Default macro to control several of the inlines */
|
/* Default macro to simplify control several of key the inlines */
|
||||||
|
|
||||||
#ifndef DEFAULT_INLINE
|
#ifndef DEFAULT_INLINE
|
||||||
|
#if defined(__GNUC__) && defined(__OPTIMIZE__)
|
||||||
|
#define DEFAULT_INLINE 2
|
||||||
|
#else
|
||||||
#define DEFAULT_INLINE 0
|
#define DEFAULT_INLINE 0
|
||||||
#endif
|
#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
|
#ifndef ENDIAN_INLINE
|
||||||
#define ENDIAN_INLINE DEFAULT_INLINE
|
#define ENDIAN_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Instruction cache if in use */
|
/* Code that gives access to various CPU internals such as registers.
|
||||||
|
Used every time an instruction is executed */
|
||||||
#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 */
|
|
||||||
|
|
||||||
#ifndef CPU_INLINE
|
#ifndef CPU_INLINE
|
||||||
#define CPU_INLINE DEFAULT_INLINE
|
#define CPU_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#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
|
#ifndef EVENTS_INLINE
|
||||||
#define EVENTS_INLINE DEFAULT_INLINE
|
#define EVENTS_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* not so important register manipulation code. Most important
|
/* Code monotoring the processors performance. It counts events on
|
||||||
register operations are performed directly on the register file */
|
every instruction cycle */
|
||||||
|
|
||||||
#ifndef REGISTERS_INLINE
|
#ifndef MON_INLINE
|
||||||
#define REGISTERS_INLINE DEFAULT_INLINE
|
#define MON_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* interrupt handling code */
|
/* Code called on the rare occasions that an interrupt occures. */
|
||||||
|
|
||||||
#ifndef INTERRUPTS_INLINE
|
#ifndef INTERRUPTS_INLINE
|
||||||
#define INTERRUPTS_INLINE DEFAULT_INLINE
|
#define INTERRUPTS_INLINE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* device code. While possibly important, this isn't as critical as
|
/* Code called on the rare occasion that either gdb or the device tree
|
||||||
the cpu/memory path
|
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
|
There seems to be some problem with making either device_tree or
|
||||||
devices inline. It reports the message:
|
devices inline. It reports the message: device_tree_find_node()
|
||||||
device_tree_find_node() not a leaf */
|
not a leaf */
|
||||||
|
|
||||||
#ifndef DEVICE_TREE_INLINE
|
#ifndef DEVICE_TREE_INLINE
|
||||||
#define DEVICE_TREE_INLINE 0
|
#define DEVICE_TREE_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEVICES_INLINE
|
#ifndef DEVICES_INLINE
|
||||||
#define DEVICES_INLINE 0
|
#define DEVICES_INLINE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Special Purpose Register tables. Provide information on the
|
/* Code called whenever information on a Special Purpose Register is
|
||||||
attributes of given SPR's. */
|
required. Called by the mflr/mtlr pseudo instructions */
|
||||||
|
|
||||||
#ifndef SPREG_INLINE
|
#ifndef SPREG_INLINE
|
||||||
#define SPREG_INLINE DEFAULT_INLINE
|
#define SPREG_INLINE DEFAULT_INLINE
|
||||||
|
@ -610,163 +405,14 @@ extern int current_floating_point;
|
||||||
inline all of their called functions */
|
inline all of their called functions */
|
||||||
|
|
||||||
#ifndef SEMANTICS_INLINE
|
#ifndef SEMANTICS_INLINE
|
||||||
#define SEMANTICS_INLINE 0
|
#define SEMANTICS_INLINE (DEFAULT_INLINE ? 1 : 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Functions that decode an instruction. Called by the cpu module.
|
/* Code to decode an instruction. Normally called on every instruction
|
||||||
Part of the performance critical fetch - decode - issue sequence */
|
cycle */
|
||||||
|
|
||||||
#ifndef IDECODE_INLINE
|
#ifndef IDECODE_INLINE
|
||||||
#define IDECODE_INLINE DEFAULT_INLINE
|
#define IDECODE_INLINE DEFAULT_INLINE
|
||||||
#endif
|
#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 */
|
#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