New changes from Andrew
authorMichael Meissner <gnu@the-meissners.org>
Tue, 31 Oct 1995 18:29:37 +0000 (18:29 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Tue, 31 Oct 1995 18:29:37 +0000 (18:29 +0000)
26 files changed:
sim/ppc/.Sanitize
sim/ppc/ChangeLog
sim/ppc/Makefile.in
sim/ppc/README.psim
sim/ppc/bits.c [new file with mode: 0644]
sim/ppc/build-psim [new file with mode: 0755]
sim/ppc/core.c
sim/ppc/core_n.h
sim/ppc/device_tree.c
sim/ppc/device_tree.h
sim/ppc/devices.c
sim/ppc/devices.h
sim/ppc/emul_netbsd.h [moved from sim/ppc/system.h with 84% similarity]
sim/ppc/gen.c [deleted file]
sim/ppc/os_emul.c [new file with mode: 0644]
sim/ppc/os_emul.h [new file with mode: 0644]
sim/ppc/ppc-cache-rules [new file with mode: 0644]
sim/ppc/ppc-endian.c
sim/ppc/ppc-opcode-complex [new file with mode: 0644]
sim/ppc/ppc-opcode-simple [new file with mode: 0644]
sim/ppc/spa-reporter.c [new file with mode: 0644]
sim/ppc/spa-system-calls.c [new file with mode: 0644]
sim/ppc/spa-system-calls.h [new file with mode: 0644]
sim/ppc/std-config.h
sim/ppc/system.c [deleted file]
sim/ppc/table.h [new file with mode: 0644]

index c25d589..efa34bd 100644 (file)
@@ -31,6 +31,7 @@ README.psim
 basics.h
 bits.c
 bits.h
+build-psim
 config.in
 configure
 configure.in
@@ -45,22 +46,38 @@ device_tree.c
 device_tree.h
 devices.c
 devices.h
+dgen.c
 double.c
 dp-bit.c
+emul_generic.c
+emul_generic.h
+emul_netbsd.c
+emul_netbsd.h
 events.c
 events.h
-gen.c
 idecode_branch.h
 idecode_expression.h
 idecode_fields.h
+igen.c
 inline.c
 inline.h
 interrupts.c
 interrupts.h
+lf.c
+lf.h
 main.c
+misc.c
+misc.h
+mon.c
+mon.h
+os_emul.c
+os_emul.h
+ppc-cache-rules
 ppc-endian.c
 ppc-endian.h
 ppc-instructions
+ppc-opcode-complex
+ppc-opcode-simple
 ppc-spr-table
 ppc.mt
 psim.c
@@ -69,9 +86,12 @@ registers.c
 registers.h
 sim_callbacks.h
 sim_calls.c
+spa-reporter.c
+spa-system-calls.c
+spa-system-calls.h
 std-config.h
-system.c
-system.h
+table.c
+table.h
 vm.c
 vm.h
 vm_n.h
index 538ef48..14625b1 100644 (file)
@@ -1,3 +1,197 @@
+Fri Oct 27 19:26:27 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * bits.h (ROTL32, ROTL64): Were functions, made them macros, now
+       make them functions again.  Appears 2.6.3 is confused by just a
+       macro.
+
+Thu Oct 26 18:31:58 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * ppc-endian.c (SWAP_8): Fix 8 byte swap!
+
+       * psim.c (psim_create): Not correctly checking that runtime
+       configuration of things like ENDIAN, ENVIRONMENT and ALIGNMENT
+       matched the compiled in ones.
+
+       * debug.h (ITRACE), igen.c: Tidy up more tracing flags -
+       trace_semantics is now different to trace_idecode, the former
+       checks the cache.
+       
+Tue Oct 24 21:54:13 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * ppc-instructions (mtsrin): Missing instruction
+       * ppc-instructions (mfsrin): Missing instruction
+       * ppc-instructions (eieio): Missing instruction
+
+Tue Oct 24 20:55:29 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * build-psim: New shell script - see internals for usage,
+       simplifies the process of building custom simulators.
+
+Mon Oct 23 23:48:59 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * std-config.h (SEMANTICS_INLINE): Tidy up notes on each of the
+        INLINE macros.  Make SEMANTICS_INLINE == 1 if DEFAULT_INLINE == 2.
+        Don't use DEFAULT_INLINE to define REGISTERS_INLINE DEVICES_INLINE
+        DEVICE_TREE_INLINE or INTERRUPTS_INLINE as none of these are on
+        the instruction or data critical paths.
+       
+       * FIXME: need to set up OS_EMUL_INLINE/EMUL_GENERIC_INLINE but
+       not on critical path.
+
+       * FIXME: devices.c/emul_netbsd.c would benefit (slightly) from
+       the inclusion of device_tree.c/emul_generic.c.
+
+Mon Oct 23 00:31:50 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * os_emul.[hc], emul_generic.[hc], emul_netbsd.[hc]: replace
+        system.[hc].  Start of suport for multiple emulations and
+        emulation state (os_emul object).
+
+       * emul_generic.[hc]: Start of code to implement proper system call
+       tracing (from spy).
+
+Sun Oct 22 21:33:51 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * cpu.h, cpu.c (cpu_init): New function, zero the registers before
+        the processor is started. Fixes problem of registers being
+        undefined when restarting from within gdb.
+
+       * cpu.h, cpu.c (cpu_flush_icache): New function, flushes the
+        instruction cache (if present).  Fixes problem of cpu caching gdb
+        breakpoint instructions.
+
+       FIXME: PSIM sometimes aborts calling error(), it should instead
+       call sim_error() say which takes care of housekeeping such as
+       saving the CIA before calling error.
+       
+       * NOTE: cpu_flush_cache() instead of cpu_synchronize_context() is
+       used when restarting a simulation because the latter has the
+       unwanted side effect (well I as a kernel hacker think it is) of
+       performing an isync when the instruction stream doesn't contain
+       one.
+
+Sun Oct 22 19:27:48 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * mon.h (new), mon.c (new), std-config.h (WITH_MON): Performance
+        monitoring module. Counts both instructions issued and
+        load/stores.
+
+       * NOTE: mon does not contain to count instruction loads as this
+       information is already available from the mon_issue() hook.
+
+       * FIXME: mon doesn't have access to register usage information.
+       This is needed if the user wants to monitor things like register
+       stalls.
+
+       * igen.c (lf_print_c_semantic), vm_n.h: Add counting code.
+
+       * psim.h, psim.c (psim_create), cpu.h, cpu.c (cpu_create): Attach
+        a common monitor to each of the cpus. Delete
+        cpu_increment_number_of_insns() and cpu_get_number_of_insns()
+        replaced by copied code in mon.[hc].
+
+Sun Oct 22 18:42:45 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * sim_calls.c, main.c, psim.c (psim_create): always create
+        `WITH_SMP' cpus.  The actual number of CPU's active in a
+        simulation run is taken from the device node: /init/smp (an
+        integer). WITH_SMP changed to 2 (remember to put it back to 0).
+
+Fri Oct 20 17:26:54 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * system.c: More system call emulation.  If code appears NetBSD
+       specific, make conditional to being compiled on a NetBSD system
+       (sigh).
+
+Wed Oct 18 23:02:20 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+       
+       * Makefile.in, gen.c(delete), igen.c(new), dgen.c(new),
+       lf.[ch](new), table.[ch](new): Split into two generators - igen
+       that outputs the instruction tables and dgen that outputs the spr
+       tables.  Add -f (filter out) flag to igen to filter out certain
+       instructions (ex 64 bit ones) from the created tables.  Include
+       $(LIBIBERTY_LIB) in link options in case host lacks some libc
+       functions.
+
+       * NOTE: igen, since it was originally written for the
+       PowerPC/RS6000, things the MSB is 0 and the LSB is 63{31}.
+       
+       * Makefile.in, std-config.h, ppc-cache-rules(new),
+       ppc-opcode-complex(new), ppc-opcode-simple(new): (for igen) Create
+       cache-rule and opcode-rule tables from macros found std-config.h.
+       Delete corresponding macro's from std-config.h.
+       
+       * FIXME: under this new igen scheme, when playing around with igen
+       options, you'll find that depenencies don't work very well.
+
+       * igen.c (gen_itable_c, gen_itable_h), Makefile.in: code to output
+       an table of all the instructions.  Code to output a type
+       enumerating all the instructin names.
+
+       * igen.c(lf_print_c_semantic): Move call to increment instruction
+       counter so that it occures _after_ the instruction has been fully
+       validated, was double counting illegal/invalid instructions.  Add
+       conditional so only compiled in when WITH_PROFILE enabled (enabled
+       by default).
+       
+       * igen.c, cpu.h, cpu.c(cpu_increment_number_of_insns): Include
+       itable.h, count individual instruction types not just total,
+       adjust reporting functions to output this.
+       
+       * ppc-instructions (64 bit Load Doubleword with Update Indexed):
+       Had 32./ instead of 31./
+
+       * ppc-instructions (64 bit Store Double Word Conditional Indexed):
+       bitrot - updated to use newer CR register operators.
+
+       * ppc-instructions (64bit Floating Convert from Integer
+       Doubleword): Correct call to Round_Float().
+
+Mon Oct 16 00:31:20 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * basics.h: #include "sim_callbacks.h" earlier so that its
+       prototypes are declared in all other header files.
+
+       * bits.h, bits.c, idecode_expression.h (ROTL32, ROTL64): Update
+       doc in bits.h, remove dead code in bits.c, move ROTL32/ROTL64 into
+       bits.h.
+
+       * FIXME: the bits.h/bits.c macro's should be replaced with
+       (inline) c functions.
+
+       * cpu.c(cpu_add_commas), device_tree.h, device_tree.c(scand_*):
+       Add size of buffer argument to functions writing a string into a
+       buffer.  Check for buffer overflow.
+       
+Sun Oct 15 22:16:11 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+       * devices.h, devices.c, debug.h, debug.c: add macro's for tracing
+        of each device.  Make parameter names consistent so macros work.
+        Use macro's in device functions.
+
+       * device_tree.c, devices.h, devices.c: include path to device in a
+        devices node when creating it.
+
+       * device_tree.c, debug.h, debug.c: Add tracing of `device-tree'.
+
+       * core.c: add tracing of core-device, adjust parameter names in
+       core functions to be consistent with those in devices*.
+
+Sun Oct 15 20:33:20 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
+
+        * debug.h, debug.c (trace_option): New function. Parses the trace
+        option, updating the trace array.
+
+       * debug.h, debug.c (trace_usage): New function. Outputs the list
+        of all possible trace options.
+
+       * sim_calls.c (sim_open), main.c (main): Use new trace_option() to
+       parse trace options specified with the simpler -t flag.  Adjust
+       usage.
+
+       * FIXME: basic parsing of command line options is still duplicated
+       by main.c and sim_calls.c
+
 Thu Oct 26 10:42:28 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * Makefile.in (clean): Delete *.i and *.out files.
@@ -93,7 +287,7 @@ Thu Oct 12 11:35:53 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
        ({CORE,VM,CPU,EVENTS,REGISTERS,INTERRUPTS}_INLINE): Ditto.
        ({SPREG,IDECODE}_INLINE): Ditto.        
        
-Wed Oct 11 17:13:15 1995  Andrew Cagney  <cagney@kremvax>
+Wed Oct 11 17:13:15 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
         * ppc-instructions: Initial cut of floating point suport added.
        Of note include - use of host IEEE floating point instructions,
@@ -110,7 +304,7 @@ Wed Oct 11 17:13:15 1995  Andrew Cagney  <cagney@kremvax>
        * Makefile.in et.al (sorry): tweek to use new core, core_map and
        core.h.
        
-Wed Oct 11 12:10:26 1995  Andrew Cagney  <cagney@kremvax>
+Wed Oct 11 12:10:26 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * sim_calls.c, main.c: Add -g (trace_gdb) option, add tracing to
        most of the other functions in sim_calls.c.
@@ -121,7 +315,7 @@ Wed Oct 11 12:10:26 1995  Andrew Cagney  <cagney@kremvax>
 
        * vm.c, vm_n.h, Makefile.in: ditto
        
-Tue Oct 10 15:42:59 1995  Andrew Cagney  <cagney@kremvax>
+Tue Oct 10 15:42:59 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * devices.h, devices.c, memory_map.h, memory_map.c: Changed
        callback interface so that there is a read/write buffer but no
@@ -133,12 +327,12 @@ Tue Oct 10 15:42:59 1995  Andrew Cagney  <cagney@kremvax>
        eliminate transfer_mode (raw or cooked) parameter from read/write
        buffer.
        
-Fri Oct  6 20:23:56 1995  Andrew Cagney  <cagney@kremvax>
+Fri Oct  6 20:23:56 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * ppc-instructions (fmul, fmuls): correct instruction format - had
        FRB instead of FRC.
 
-Wed Oct  4 17:31:12 1995  Andrew Cagney  <cagney@kremvax>
+Wed Oct  4 17:31:12 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * psim.c, device_tree.h, device_tree.c, devices.c (printd_*,
        scand_*): new functions to parse/print fields in device names
@@ -152,7 +346,7 @@ Wed Oct  4 17:31:12 1995  Andrew Cagney  <cagney@kremvax>
        variable number of arguments.  This gives greater flexability and
        greater chance of bugs.
 
-Tue Oct  3 22:01:56 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Tue Oct  3 22:01:56 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * main.c (printf_filtered, error): Missing va_end() to close off
         variable argument use.
@@ -275,7 +469,7 @@ Fri Sep  8 09:51:03 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
        * basics.h (sysdep.h): Don't include it.
        * Makefile.in (BASICS_H): Remove sysdep.h.
 
-Wed Sep  6 13:25:42 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Wed Sep  6 13:25:42 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
  
        * core.c (core_add_data): First growth of bss was being put at
         wrong address (0) instead of &end.
@@ -283,7 +477,7 @@ Wed Sep  6 13:25:42 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
        * core.c (core_add_stack, core_add_data): Was not handling case
         where bss/stack is grown across the current end-of-{bss,stack}.
 
-Wed Sep  6 00:46:10 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Wed Sep  6 00:46:10 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * system.c (system_call): Fix SYS_break - was aligning bss to a
         page boundary instead of just an 8 byte one; On first call sbrk(0)
@@ -329,7 +523,7 @@ Tue Aug 22 09:31:18 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
        * configure.in: Clone from other simulator targets.
        * configure: Generate via autoconf from configure.in.
 
-Sat Aug 19 09:05:32 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Sat Aug 19 09:05:32 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * ppc-instructions: fix srawi (was geting XER[CA] real wrong).
 
@@ -340,14 +534,14 @@ Sat Aug 19 09:05:32 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
 
        * main.c (main): really stupid. Wasn't exiting with correct status
 
-Fri Aug 18 00:38:01 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Fri Aug 18 00:38:01 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * system.c (system_call): add system calls kill(2) and getpid(2).
 
        * main.c (main): Check/return exit status when simulation
         finishes.
 
-Thu Aug 17 14:29:18 1995  Andrew Cagney  <cagney@kremvax>
+Thu Aug 17 14:29:18 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * device_tree.c (create_option_device_node): Alignment rules (at
        least for the moment) now are for strict alignment only for LE OEA
@@ -355,7 +549,7 @@ Thu Aug 17 14:29:18 1995  Andrew Cagney  <cagney@kremvax>
 
        * system.c (system_call) SYS_exit: Wasn't exiting with correct status.
 
-Thu Aug 17 01:16:38 1995  Andrew Cagney - aka Noid  <cagney@kremvax>
+Thu Aug 17 01:16:38 1995  Andrew Cagney  <cagney@cagney@highland.com.au>
 
        * vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
         forgot to return.
index c5e9ff4..d92ca56 100644 (file)
@@ -80,7 +80,11 @@ INCLUDES     = -I. -I$(srcdir) $(LIB_INCLUDES) $(BFD_INCLUDES) $(GDB_INCLUDES)
 CONFIG_FILE    = std-config.h
 
 # See inline.h for appropriate flags to set
-INLINE_CFLAGS  = -DDEFAULT_INLINE=2
+INLINE_CFLAGS  =                       # -g0 -DDEFAULT_INLINE=2
+IGEN_FLAGS = -f 64                     # -f 64 -e
+IGEN_OPCODE_RULES = ppc-opcode-simple  # ppc-opcode-complex
+DGEN_FLAGS =                           # # -s
+
 
 LIBIBERTY_LIB  = ../../libiberty/libiberty.a
 BFD_LIB                = ../../bfd/libbfd.a
@@ -128,7 +132,15 @@ CPU_H = \
        events.h \
        interrupts.h \
        psim.h \
-       icache.h
+       icache.h \
+       itable.h \
+       mon.h
+
+EMUL_GENERIC_H = \
+       $(CPU_H) \
+       $(IDECODE_H) \
+       emul_generic.h \
+       os_emul.h
 
 
 INLINE = \
@@ -139,35 +151,43 @@ BUILT_SRC = \
        icache.h \
        idecode.h idecode.c \
        semantics.h semantics.c \
+       itable.h itable.c \
        spreg.h spreg.c \
        config.h \
-       ppc-config.h
+       ppc-config.h 
 
 LIB_SRC = \
        psim.c \
        bits.c \
-       ppc-endian.c \
        debug.c \
+       ppc-endian.c \
        vm.c \
        core.c \
        events.c \
-       system.c \
+       os_emul.c \
+       emul_generic.c \
+       emul_netbsd.c \
        registers.c \
        cpu.c \
        interrupts.c \
        devices.c \
-       device_tree.c
+       device_tree.c \
+       mon.c
 
 MAIN_SRC = \
        main.c \
        sim_calls.c
 
 
+# NOTE: semantics, idecode and psim put last so smaller files are compiled
+#       first
 LIB_OBJ = \
        debug.o \
        bits.o \
        ppc-endian.o \
-       system.o \
+       os_emul.o \
+       emul_generic.o \
+       emul_netbsd.o \
        registers.o \
        vm.o \
        core.o \
@@ -177,6 +197,8 @@ LIB_OBJ = \
        events.o \
        devices.o \
        device_tree.o \
+       itable.o \
+       mon.o \
        semantics.o \
        idecode.o \
        psim.o
@@ -192,7 +214,7 @@ run: psim
        rm -f run
        ln psim run
 
-$(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
+$(TARGETLIB): tmp-igen tmp-dgen $(LIB_OBJ) $(GDB_OBJ)
        rm -f $(TARGETLIB)
        $(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
        $(RANLIB) $(TARGETLIB)
@@ -201,27 +223,29 @@ $(TARGETLIB): tmp-gencode $(LIB_OBJ) $(GDB_OBJ)
 # anything changes.
 psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC)
 
-bits.o: bits.c bits.h
+bits.o: bits.c $(BASICS_H)
 
 debug.o: debug.c $(BASICS_H)
 
 ppc-endian.o: ppc-endian.c ppc-endian.h \
        config.h ppc-config.h words.h sim_callbacks.h
 
-system.o: system.c system.h $(CPU_H) $(IDECODE_H)
+os_emul.o: os_emul.c $(EMUL_GENERIC_H)
+emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
+emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
 
 registers.o: registers.c $(REGISTERS_H) $(BASICS_H) 
 
 cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
 
-interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) system.h
+interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h
 
 idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
 
 # double.o: double.c dp-bit.c
 
 vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
-       device_tree.h core.h interrupts.h
+       device_tree.h core.h interrupts.h itable.h mon.h
 
 core.o: core.c core.h $(BASICS_H) device_tree.h
 
@@ -240,6 +264,9 @@ device_tree.o: device_tree.c device_tree.h devices.h $(BASICS_H)
 
 semantics.o: semantics.c semantics.h $(CPU_H) $(IDECODE_H)
 
+itable.o: itable.c itable.h
+
+mon.o: $(CPU_H)
 
 #
 # Rules to create the built c source code files
@@ -249,47 +276,63 @@ ppc-config.h: $(CONFIG_FILE)
        cp $(srcdir)/$(CONFIG_FILE) ppc-config.h
 
 
-tmp-gencode: gen ppc-instructions ppc-spr-table $(srcdir)/../../move-if-change
-       ./gen   -r $(srcdir)/ppc-spr-table \
-               -i $(srcdir)/ppc-instructions \
+tmp-dgen: dgen ppc-spr-table $(srcdir)/../../move-if-change
+       ./dgen $(DGEN_FLAGS) \
+               -r $(srcdir)/ppc-spr-table \
                -n spreg.h     -P tmp-spreg.h \
-               -n spreg.c     -p tmp-spreg.c \
+               -n spreg.c     -p tmp-spreg.c
+       $(srcdir)/../../move-if-change tmp-spreg.h spreg.h
+       $(srcdir)/../../move-if-change tmp-spreg.c spreg.c
+       touch tmp-dgen
+
+
+tmp-igen: igen ppc-instructions $(IGEN_OPCODE_RULES) ppc-cache-rules $(srcdir)/../../move-if-change
+       ./igen  $(IGEN_FLAGS) \
+               -o $(srcdir)/$(IGEN_OPCODE_RULES) \
+               -k $(srcdir)/ppc-cache-rules \
+               -i $(srcdir)/ppc-instructions \
                -n icache.h    -C tmp-icache.h \
                -n semantics.h -S tmp-semantics.h \
                -n semantics.c -s tmp-semantics.c \
                -n idecode.h   -D tmp-idecode.h \
-               -n idecode.c   -d tmp-idecode.c
+               -n idecode.c   -d tmp-idecode.c \
+               -n itable.h    -T tmp-itable.h \
+               -n itable.c    -t tmp-itable.c
        $(srcdir)/../../move-if-change tmp-icache.h icache.h
        $(srcdir)/../../move-if-change tmp-idecode.h idecode.h
        $(srcdir)/../../move-if-change tmp-idecode.c idecode.c
        $(srcdir)/../../move-if-change tmp-semantics.h semantics.h
        $(srcdir)/../../move-if-change tmp-semantics.c semantics.c
-       $(srcdir)/../../move-if-change tmp-spreg.h spreg.h
-       $(srcdir)/../../move-if-change tmp-spreg.c spreg.c
-       touch tmp-gencode
+       $(srcdir)/../../move-if-change tmp-itable.h itable.h
+       $(srcdir)/../../move-if-change tmp-itable.c itable.c
+       touch tmp-igen
 
 # NOTE: Some versions of make don't handle files created as side-effects
 # uncomment the below if that is the case.
 #
-# $(TARGETLIB): tmp-gencode
-# icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c: tmp-gencode
+# $(TARGETLIB): tmp-igen tmp-dgen
+# itable.h itable.c icache.h idecode.h idecode.c semantics.h semantics.c: tmp-igen
+# spreg.h spreg.c: tmp-dgen
 
-gen.o: gen.c config.h ppc-config.h
-       $(CC_FOR_BUILD) -c $(CFLAGS) $(INLINE_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(srcdir)/gen.c
+dgen: dgen.o table.o lf.o misc.o
+       $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o dgen dgen.o table.o lf.o misc.o $(LIBIBERTY_LIB) $(LIBS)
 
-gen: gen.o config.h ppc-config.h $(LIBIBERTY_LIB) $(LIBS)
-       $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o gen gen.o $(LIBIBERTY_LIB) $(LIBS)
+igen: igen.o table.o lf.o misc.o
+       $(CC_FOR_BUILD) $(CFLAGS) $(LDFLAGS) -o igen igen.o table.o lf.o misc.o $(LIBIBERTY_LIB) $(LIBS)
 
-#
+table.o: misc.h lf.h table.h
+lf.o: misc.h lf.h
+dgen.o igen.o: misc.h lf.h table.h
+misc.o: misc.h
+# With out this #, make thinks that misc.o doesn't have a rule
 
 tags etags: TAGS
 
-TAGS: tmp-gencode config.h ppc-config.h
+TAGS: tmp-igen tmp-dgen config.h ppc-config.h
        etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
 
 clean mostlyclean:
-       rm -f tmp-* *.[ioas] *.out core psim run gen config.log
-       rm -f icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c ppc-config.h
+       rm -f tmp-* *.[oas] core psim run igen dgen config.log
 
 distclean maintainer-clean realclean: clean
        rm -f TAGS $(BUILT_SRC) Makefile config.cache config.status config.h stamp-h
index f9a1486..89bf369 100644 (file)
 
 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
 
-This directory contains the program PSIM that models the PowerPC
-architecture.  It can either be run stand alone (psim or run) or used
-as part of GDB.
+This directory contains the program PSIM that models the PowerPC(tm -
+IBM) architecture.  It can either be run stand alone (psim or run) or
+used as part of GDB.
 
 
-SOURCE:
+KNOWN FEATURES
 
-       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:
+SMP: A Symetric Multi-Processor configuration is suported.  This
+includes modeling of the PowerPC load word and reserve instructions
+(if intending to use this feature you are well advised to read the the
+source code for the reservation instructions so that you are aware of
+any potential limitations in the model).  The number of processors is
+selected during startup.
 
-               ftp.ci.com.au:pub/clayton/psim-sim-*.tar.gz
+DUAL-ENDIAN: Both little and big endian models are suported.  The
+execution of instruction sequences that switch between the two modes,
+however, is not.  The endianess is selected during startup.
 
-       This contains a replacement for the directory sim/ppc.  As
-       these releases prove stable they are merged back into the GDB
-       source tree.
+UIEA, VEA and OEA: The PowerPC architecture defines three levels of
+the PowerPC architecture.  This simulator, to a reasonable degree, is
+capable of modeling all three.  That is the User Instruction Set
+Architecture, the Virtual Environment Architecture and finally the
+Operating Environment Architecture.  The environment is selected
+during startup.  The OEA model is still under development.
 
-       If you find bugs or experience problems, please e-mail them to
-       the alias:
+HARDWARE DEVICE TREE: In the OEA, the model of the target machines
+hardware is built from a tree of devices (bit like Open Boot).
+Included in this is the ability to model bus hierachies and
+runtime-configurable devices (eg PCI).  The device tree used to create
+the hardware model is created during startup.  This device tree is
+still under development.
 
-               powerpc-psim@ci.com.au
+VEA SYSTEM CALLS: In user mode, basic system calls (read, write, open,
+close ...) are emulated.  Under NetBSD (simply because that is what my
+machine at home runs) the list is more extensive.
 
-       It's a majordomo mailing list.
+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.
 
-BUILDING:
+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.
 
-       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.
+FLOATING POINT: Preliminary suport for floating point is included.
+Real kernels don't need floating point.
 
-       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:
+BUILDING PSIM:
 
-               $ CC=gcc ./configure --target=powerpcle-unknown-eabisim
+To build PSIM you will need the following:
 
-         by default (because of its dependency on GCC).
+       gdb-4.15.tar.gz         From your favorite GNU ftp site
 
-       o Build your entire gdb tree as per normal.  Something along the
-         lines of:
+       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
 
-               $ cd gdb-4.15
-               $ make CC=gcc
-               .
-               .
-               .
 
+1.     Unpack gdb
 
+               $ gunzip < gdb-4.15.tar.gz | tar xf -
 
-       o Install it it all as per normal.  Something along the lines of:
+
+2.     Change to the gdb directory, apply the psim patches and unpack
+       the psim files.
 
                $ cd gdb-4.15
-               $ make CC=gcc install
 
+               $ gunzip < ../gdb-4.15+psim-951016.diff.gz | more
+               $ gunzip < ../gdb-4.15+psim-951016.diff.gz | patch -p1
 
-RUNNING:
+               $ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar tvf -
+               $ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar xvf -
 
-       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
+3.     Configure gdb
 
-       contains pre-compiled and linked programs that can be run on
-       PSIM.  The notes below assume that you have unpacked that tar
-       archive.
+               $ more gdb/README
 
-       To rebuild the archive you will need to obtain a working
-       version of an ELF compiler/linker for the PowerPC.
-       
-       Example of running PSIM:
+       then something like (I assume SH):
 
-               Print out the users environment:
+               $ CC=gcc ./configure --target=powerpc-unknown-eabisim
 
-                       $ sim/ppc/psim sim/ppc/test/envp
+       eabisim is needed as by default (because PSIM needs GCC) the
+       simulator is not built.
 
-               Print out the arguments:
 
-                       $ sim/ppc/psim sim/ppc/test/argv a b c
+4.     Build
 
-               Check the OEA model:
+               $ make CC=gcc
 
-                       $ sim/ppc/psim sim/ppc/test/interrupt
+       alternativly, if you are short on disk space or just want the
+       simulator built:
 
-               Check that sbrk works
+               $ ( cd libiberty && make CC=gcc )
+               $ ( cd bfd && make CC=gcc )
+               $ ( cd sim/ppc && make CC=gcc )
 
-                       $ 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.
+5.     Install
 
-                       $ time sim/ppc/sim sim/ppc/test/count 5000000
-                       $ expr 10 \* 1000 \* 1000 / <seconds>
+               $ make CC=gcc install
+       or just
+               $ cp gdb/gdb ~/bin/powerpc-unknown-eabisim-gdb
+               $ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
 
 
-       Example of running GDB: 
+USING THE SIMULATOR:
 
-               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).
+(I assume that you've unpacked the psim-test archive).
 
-                       $ cd sim/ppc/test
-                       $ powerpc-unknown-eabi-gdb count
-                       (gdb) target sim
-                       (gdb) load count
-                       (gdb) break main
-                       (gdb) run
-                       .
-                       .
-                       .
+1.     As a standalone program
 
+       Print out the users environment:
 
-CONFIGURATION:
+               $ powerpc-unknown-eabisim-run envp
 
-       Making it go faster
+       Print out the arguments:
 
-       See the file sim/ppc/config.h (which is copied from
-       sim/ppc/std-config.h) for further information.
+               $ powerpc-unknown-eabisim-run argv a b c
 
+       Check that sbrk works:
 
-KNOWN FEATURES
+               $ powerpc-unknown-eabisim-run break
 
-       SMP: A Symetric Multi-Processor configuration is suported.
-       This includes a model of the PowerPC load word and reserve
-       et.al. instructions (if intending to use this feature you are
-       well advised to read the the source code for the reservation
-       instructions so that you are aware of any potential
-       limitations in the model).
-
-       DUAL-ENDIAN: Both little and big endian modes are suported.
-       Switching between the two modes at run time, however, is not.
-
-       UIEA, VEA and OEA: The PowerPC architecture defines three
-       levels of the PowerPC architecture.  This simulator, to a
-       reasonable degree, is capable of modeling all three of them.
-       That is the User Instruction Set Architecture, the Virtual
-       Environment Architecture and finally the Operating Environment
-       Architecture.
-
-       HARDWARE DEVICES: The OEA model includes facilities that allow
-       a programmer to (I won't say easily) extend this simulator so
-       that a program can interact with models of real devices.
-       Illustrating this is the phony machine clayton that includes
-       console, interrupt control unit and reset register devices.
-
-       PEDANTIC VEA MEMORY MODEL: User programs can not assume that
-       they can stray off the end of valid memory areas.  This model
-       defines valid memory addresses in strict accordance to the
-       executable and does not page allign their values.  At first
-       this was a bug but since then has turned up several bugs in
-       peoples code so I've renamed it `a feature' :-)
-
-       RUNTIME CONFIG OF HARDWARE: In addition to the three builtin
-       models of hardware - VEA, OEA/Hardware and (the start of) OpenBoot,
-       it is possible to load a file containing a specification of a
-       custom device tree.
 
+2.     Example of running GDB: 
 
-KNOWN PROBLEMS:
+       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:
 
-       FLOATING POINT: Need to add suport for non IEEE float
-       machines.  Need to more fully handle exceptions (eg things
-       like divide by zero).
+There is a mailing list (subscribe through majordomo@ci.com.au) (that
+is almost never used) at:
 
-       DEVICE TREE DOC: How to create and use the device tree is not
-       documented at all.
+       powerpc-psim@ci.com.au
 
-       INITIALIZATION: When running from gdb, things are not
-       re-initialzied very well e.g. registers are not rezeroed.
+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.
 
-       HTAB (page) code for OEA model untested.  Some of the vm code
-       instructions unimplemented.
 
-       Flush instruction cache instructions do nothing.  Perhaphs they
-       should (if there is an instruction cache) flush it.
+KNOWN PROBLEMS:
+
+See the ChangeLog file looking for lines taged with the word FIXME.
 
-       Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.
-       The PowerOpen worked until I added the ELF one.
+CORE.C: The implementation of core.c (defined by core.h) isn't the
+best.  It is intended to be functionaly correct rather than fast.
 
-       OpenBoot and PR*P interfaces missing.  Open boot could be
-       implemented by putting special instructions at the address
-       of the OpenBoot callback functions.  Those instructions
-       could than emulate OpenBoot behavour.
+HTAB (page) code for OEA model untested.  Some of the vm code
+instructions unimplemented.
 
-       Missing VEA system calls.
+Flush instruction cache instructions do nothing.  Perhaphs they should
+(if there is an instruction cache) flush it.
 
-       Missing or commented out instructions.
+Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.  The
+PowerOpen worked until I added the ELF one.
 
-       Only basic (hackish) floating point implemented, I would not
-       trust it and it is going to change.
+OpenBoot and PR*P interfaces missing.  Open boot could be implemented
+by putting special instructions at the address of the OpenBoot
+callback functions.  Those instructions could than emulate OpenBoot
+behavour.
 
-       64bit target untested.
+Missing VEA system calls.
 
-       64bit host broken.  For instance use of scanf "%x", &long long.
+Missing or commented out instructions.
 
-       Event code for pending events from within signal handlers not
-       finished/tested.
+64bit target untested.
 
-       Better and more devices.
+64bit host broken.  For instance use of scanf "%x", &long long.
 
-       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.
+Event code for pending events from within signal handlers not
+finished/tested.
+
+Better and more devices.
+
+PORTABILITY (Notes taken from Michael Meissner): Heavy use of the ##
+operator - fix using the clasic X/**/Y hack; Use of the signed
+keyword.  In particular, signed char has no analogue in classic C
+(though most implementations of classic C use signed chars); Use of
+long long which restricts the target compiler to be GCC.
 
-       OPTIONS/FLAGS: Need a function that can parse command line
-       options so that both psim and sim_{load,open,command} can all
-       call it.  Options should be extended to allow the setting of
-       things like floating point support.
 
 THANKS:
 
-       Thanks go to the following who each helped in some way.
+Thanks go to the following who each helped in some way.
 
-               Allen Briggs, Bett Koch, David Edelsohn,
-               Michael Meissner, Bob Mercier, Richard Perini,
-               Richard Stallman, Mitchele Walker
+       Allen Briggs, Bett Koch, David Edelsohn, Gordon Irlam,
+       Michael Meissner, Bob Mercier, Richard Perini,
+       Richard Stallman, Mitchele Walker
 
 
 ----------------------------------------------------------------
@@ -274,7 +293,3 @@ i486DX2/66
        1/270/316 - switch=2/2,expand=0,inline=1,nia=0
        1/271/281 - switch=1/1,expand=0,inline=1,nia=1
        1/267/274 - switch=2/1,expand=0,inline=1,nia=1
-
-----
-
-CFLAGS = -g -Wall -Wno-unused -Wmissing-prototypes -Werror
diff --git a/sim/ppc/bits.c b/sim/ppc/bits.c
new file mode 100644 (file)
index 0000000..2424e85
--- /dev/null
@@ -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_ */
diff --git a/sim/ppc/build-psim b/sim/ppc/build-psim
new file mode 100755 (executable)
index 0000000..ea7318a
--- /dev/null
@@ -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
index a40128e..4acf0a3 100644 (file)
@@ -42,7 +42,7 @@ struct _core_mapping {
   device_io_read_buffer_callback *reader;
   device_io_write_buffer_callback *writer;
   /* common */
-  int address_space;
+  int space;
   unsigned_word base;
   unsigned_word bound;
   unsigned nr_bytes;
@@ -130,12 +130,12 @@ core_executable(core *memory)
 
 STATIC_INLINE_CORE core_mapping *
 new_core_mapping(attach_type attach,
-                  int address_space,
-                  unsigned_word addr,
-                  unsigned nr_bytes,
-                  const device *device,
-                  void *buffer,
-                  int free_buffer)
+                int space,
+                unsigned_word addr,
+                unsigned nr_bytes,
+                const device *device,
+                void *buffer,
+                int free_buffer)
 {
   core_mapping *new_mapping = ZALLOC(core_mapping);
   switch (attach) {
@@ -154,7 +154,7 @@ new_core_mapping(attach_type attach,
          attach);
   }
   /* common */
-  new_mapping->address_space = address_space;
+  new_mapping->space = space;
   new_mapping->base = addr;
   new_mapping->nr_bytes = nr_bytes;
   new_mapping->bound = addr + (nr_bytes - 1);
@@ -164,21 +164,21 @@ new_core_mapping(attach_type attach,
 
 STATIC_INLINE_CORE void
 core_map_attach(core_map *access_map,
-                        attach_type attach,
-                        int address_space,
-                        unsigned_word addr,
-                        unsigned nr_bytes, /* host limited */
-                        const device *device, /*callback/default*/
-                        void *buffer, /*raw_memory*/
-                        int free_buffer) /*raw_memory*/
+               attach_type attach,
+               int space,
+               unsigned_word addr,
+               unsigned nr_bytes, /* host limited */
+               const device *device, /*callback/default*/
+               void *buffer, /*raw_memory*/
+               int free_buffer) /*raw_memory*/
 {
   if (attach == attach_default) {
     if (access_map->default_map != NULL)
       error("core_map_attach() default mapping already in place\n");
     ASSERT(buffer == NULL);
     access_map->default_map = new_core_mapping(attach, 
-                                                address_space, addr, nr_bytes,
-                                                device, buffer, free_buffer);
+                                              space, addr, nr_bytes,
+                                              device, buffer, free_buffer);
   }
   else {
     /* find the insertion point for this additional mapping and insert */
@@ -206,8 +206,8 @@ core_map_attach(core_map *access_map,
 
     /* create/insert the new mapping */
     *last_mapping = new_core_mapping(attach,
-                                      address_space, addr, nr_bytes,
-                                      device, buffer, free_buffer);
+                                    space, addr, nr_bytes,
+                                    device, buffer, free_buffer);
     (*last_mapping)->next = next_mapping;
   }
 }
@@ -216,7 +216,7 @@ core_map_attach(core_map *access_map,
 INLINE_CORE void
 core_attach(core *memory,
            attach_type attach,
-           int address_space,
+           int space,
            access_type access,
            unsigned_word addr,
            unsigned nr_bytes, /* host limited */
@@ -236,7 +236,7 @@ core_attach(core *memory,
       if (access & access_read)
        core_map_attach(memory->map + access_map,
                        attach,
-                       address_space, addr, nr_bytes,
+                       space, addr, nr_bytes,
                        device, buffer, !free_buffer);
       free_buffer ++;
       break;
@@ -244,7 +244,7 @@ core_attach(core *memory,
       if (access & access_write)
        core_map_attach(memory->map + access_map,
                        attach,
-                       address_space, addr, nr_bytes,
+                       space, addr, nr_bytes,
                        device, buffer, !free_buffer);
       free_buffer ++;
       break;
@@ -252,7 +252,7 @@ core_attach(core *memory,
       if (access & access_exec)
        core_map_attach(memory->map + access_map,
                        attach,
-                       address_space, addr, nr_bytes,
+                       space, addr, nr_bytes,
                        device, buffer, !free_buffer);
       free_buffer ++;
       break;
@@ -320,7 +320,7 @@ core_map_read_buffer(core_map *map,
     if (mapping->reader != NULL) {
       if (mapping->reader(mapping->device,
                          &byte,
-                         mapping->address_space,
+                         mapping->space,
                          raddr - mapping->base,
                          1, /* nr_bytes */
                          0, /*processor*/
@@ -357,7 +357,7 @@ core_map_write_buffer(core_map *map,
     if (mapping->writer != NULL) {
       if (mapping->writer(mapping->device,
                          &byte,
-                         mapping->address_space,
+                         mapping->space,
                          raddr - mapping->base,
                          1, /*nr_bytes*/
                          0, /*processor*/
@@ -382,6 +382,7 @@ core_init_callback(const device *me,
                   psim *system)
 {
   core *memory = (core*)me->data;
+  DTRACE_INIT(core);
   core_init(memory);
 }
 
@@ -390,7 +391,7 @@ STATIC_INLINE_CORE void
 core_attach_address_callback(const device *me,
                             const char *name,
                             attach_type attach,
-                            int address_space,
+                            int space,
                             unsigned_word addr,
                             unsigned nr_bytes,
                             access_type access,
@@ -398,11 +399,12 @@ core_attach_address_callback(const device *me,
 {
   core *memory = (core*)me->data;
   unsigned_word device_address;
-  if (address_space != 0)
+  DTRACE_ATTACH_ADDRESS(core);
+  if (space != 0)
     error("core_attach_address_callback() invalid address space\n");
   core_attach(memory,
              attach,
-             address_space,
+             space,
              access,
              addr,
              nr_bytes,
@@ -412,15 +414,16 @@ core_attach_address_callback(const device *me,
 
 STATIC_INLINE_CORE unsigned
 core_dma_read_buffer_callback(const device *me,
-                             void *target,
-                             int address_space,
-                             unsigned_word offset,
+                             void *dest,
+                             int space,
+                             unsigned_word addr,
                              unsigned nr_bytes)
 {
   core *memory = (core*)me->data;
+  DTRACE_DMA_READ_BUFFER(core);
   return core_map_read_buffer(core_readable(memory),
-                             target,
-                             offset,
+                             dest,
+                             addr,
                              nr_bytes);
 }
 
@@ -428,8 +431,8 @@ core_dma_read_buffer_callback(const device *me,
 STATIC_INLINE_CORE unsigned
 core_dma_write_buffer_callback(const device *me,
                               const void *source,
-                              int address_space,
-                              unsigned_word offset,
+                              int space,
+                              unsigned_word addr,
                               unsigned nr_bytes,
                               int violate_read_only_section)
 {
@@ -437,9 +440,10 @@ core_dma_write_buffer_callback(const device *me,
   core_map *map = (violate_read_only_section
                   ? core_readable(memory)
                   : core_writeable(memory));
+  DTRACE_DMA_WRITE_BUFFER(core);
   return core_map_write_buffer(map,
                               source,
-                              offset,
+                              addr,
                               nr_bytes);
 }
 
@@ -463,7 +467,7 @@ static device_callbacks const core_callbacks = {
 INLINE_CORE const device *
 core_device_create(core *memory)
 {
-  return device_create_from("core", memory, &core_callbacks, NULL);
+  return device_create_from("core", "/", memory, &core_callbacks, NULL);
 }
 
 
index d4c54bc..8a80ac8 100644 (file)
@@ -47,7 +47,7 @@ XCONCAT2(core_map_read_,N)(core_map *map,
     unsigned_N data;
     if (mapping->reader(mapping->device,
                        &data,
-                        mapping->address_space,
+                        mapping->space,
                         addr - mapping->base,
                         sizeof(unsigned_N), /* nr_bytes */
                         processor,
@@ -78,7 +78,7 @@ XCONCAT2(core_map_write_,N)(core_map *map,
     unsigned_N data = H2T_N(val);
     if (mapping->writer(mapping->device,
                        &data,
-                        mapping->address_space,
+                        mapping->space,
                        addr - mapping->base,
                        sizeof(unsigned_N), /* nr_bytes */
                        processor,
index 78b6e1b..0d9f768 100644 (file)
@@ -41,6 +41,14 @@ typedef enum {
   node_string
 } node_type;
 
+static char *node_type_names[] = {
+  "any",
+  "device",
+  "integer",
+  "boolean",
+  "string",
+  NULL,
+};
 
 struct _device_tree {
   /* where i am */
@@ -89,6 +97,7 @@ typedef enum {
 STATIC_INLINE_DEVICE_TREE device_tree *
 device_tree_find_node(device_tree *root,
                      const char *path,
+                     const char *full_path,
                      node_type type,
                      device_tree_action action)
 {
@@ -139,13 +148,13 @@ device_tree_find_node(device_tree *root,
        if (path[name_len] == '\0') {
          if (action == device_tree_grow)
            error("device_tree_find_node() node %s already present\n",
-                 path);
+                 full_path);
          if (type != node_any && child->type != type) {
            if (action == device_tree_return_null)
              return NULL;
            else
-             error("device_tree_find_node() node %s does not match type %d\n",
-                   path, type);
+             error("device_tree_find_node() node %s is not of type %s\n",
+                   full_path, node_type_names[type]);
          }
          else
            return child;
@@ -153,6 +162,7 @@ device_tree_find_node(device_tree *root,
        else
          return device_tree_find_node(child,
                                       path + name_len + 1,
+                                      full_path,
                                       type,
                                       action);
       }
@@ -163,10 +173,15 @@ device_tree_find_node(device_tree *root,
   switch (action) {
   case device_tree_grow:
     if (path[name_len] != '\0')
-      error("device_tree_find_node() not a leaf %s\n", path);
+      error("device_tree_find_node() a parent of %s missing\n",
+           full_path);
     return new_device_tree(root, path, type);
   case device_tree_return_null:
     return NULL;
+  case device_tree_abort:
+    error("device_tree_find_node() could not find %s in tree\n",
+         full_path);
+    return NULL;
   default:
     error("device_tree_find_node() invalid default action %d\n", action);
     return NULL;
@@ -180,14 +195,22 @@ INLINE_DEVICE_TREE device_tree *
 device_tree_add_passthrough(device_tree *root,
                            const char *path)
 {
-  device_tree *new_node = device_tree_find_node(root,
-                                               path,
-                                               node_device,
-                                               device_tree_grow);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_passthrough(root=0x%x, path=%s)\n", root, path));
+  new_node = device_tree_find_node(root,
+                                  path,
+                                  path, /*full_path*/
+                                  node_device,
+                                  device_tree_grow);
   new_node->device = device_create_from(new_node->name,
+                                       path,
                                        NULL,
                                        passthrough_device_callbacks(),
                                        new_node->parent->device);
+  
+  TRACE(trace_device_tree,
+       ("device_tree_add_passthrough() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -197,11 +220,18 @@ device_tree_add_device(device_tree *root,
                       const char *path,
                       const device *dev)
 {
-  device_tree *new_node = device_tree_find_node(root,
-                                               path,
-                                               node_device,
-                                               device_tree_grow);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_device(root=0x%x, path=%s, dev=0x%x)\n",
+        root, path, dev));
+  new_node = device_tree_find_node(root,
+                                  path,
+                                  path, /* full-path */
+                                  node_device,
+                                  device_tree_grow);
   new_node->device = dev;
+  TRACE(trace_device_tree,
+       ("device_tree_add_device() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -210,11 +240,18 @@ device_tree_add_integer(device_tree *root,
                        const char *path,
                        signed_word integer)
 {
-  device_tree *new_node = device_tree_find_node(root,
-                                               path,
-                                               node_integer,
-                                               device_tree_grow);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_integer(root=0x%x, path=%s, integer=%d)\n",
+        root, path, integer));
+  new_node = device_tree_find_node(root,
+                                  path,
+                                  path, /* full-name */
+                                  node_integer,
+                                  device_tree_grow);
   new_node->integer = integer;
+  TRACE(trace_device_tree,
+       ("device_tree_add_integer() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -223,11 +260,18 @@ device_tree_add_string(device_tree *root,
                       const char *path,
                       const char *string)
 {
-  device_tree *new_node = device_tree_find_node(root,
-                                               path,
-                                               node_string,
-                                               device_tree_grow);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_device(root=0x%x, path=%s, string=%s)\n",
+        root, path, string));
+  new_node = device_tree_find_node(root,
+                                  path,
+                                  path, /* full-name */
+                                  node_string,
+                                  device_tree_grow);
   new_node->string = string;
+  TRACE(trace_device_tree,
+       ("device_tree_add_string() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -236,11 +280,18 @@ device_tree_add_boolean(device_tree *root,
                        const char *path,
                        int boolean)
 {
-  device_tree *new_node = device_tree_find_node(root,
-                                               path,
-                                               node_boolean,
-                                               device_tree_grow);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_boolean(root=0x%x, path=%s, boolean=%d)\n",
+        root, path, boolean));
+  new_node = device_tree_find_node(root,
+                                  path,
+                                  path, /* full-name */
+                                  node_boolean,
+                                  device_tree_grow);
   new_node->boolean = boolean;
+  TRACE(trace_device_tree,
+       ("device_tree_add_boolean() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -248,9 +299,16 @@ INLINE_DEVICE_TREE device_tree *
 device_tree_add_found_device(device_tree *root,
                             const char *path)
 {
-  device_tree *new_node = device_tree_add_device(root, path, NULL);
+  device_tree *new_node;
+  TRACE(trace_device_tree,
+       ("device_tree_add_found_device(root=0x%x, path=%s)\n",
+        root, path));
+  new_node = device_tree_add_device(root, path, NULL);
   new_node->device = device_create(new_node->name,
+                                  path,
                                   new_node->parent->device);
+  TRACE(trace_device_tree,
+       ("device_tree_add_found_device() = 0x%x\n", new_node));
   return new_node;
 }
 
@@ -261,10 +319,16 @@ INLINE_DEVICE_TREE const device *
 device_tree_find_device(device_tree *root,
                        const char *path)
 {
-  device_tree *node = device_tree_find_node(root,
-                                           path,
-                                           node_device,
-                                           device_tree_abort);
+  device_tree *node;
+  TRACE(trace_device_tree,
+       ("device_tree_find_device(root=0x%x, path=%s)\n", root, path));
+  node = device_tree_find_node(root,
+                              path,
+                              path, /* full-name */
+                              node_device,
+                              device_tree_abort);
+  TRACE(trace_device_tree,
+       ("device_tree_find_device() = 0x%x\n", node->device));
   return node->device;
 }
 
@@ -272,10 +336,16 @@ INLINE_DEVICE_TREE signed_word
 device_tree_find_integer(device_tree *root,
                         const char *path)
 {
-  device_tree *node = device_tree_find_node(root,
-                                           path,
-                                           node_integer,
-                                           device_tree_abort);
+  device_tree *node;
+  TRACE(trace_device_tree,
+       ("device_tree_find_integer(root=0x%x, path=%s)\n", root, path));
+  node = device_tree_find_node(root,
+                              path,
+                              path, /* full-name */
+                              node_integer,
+                              device_tree_abort);
+  TRACE(trace_device_tree,
+       ("device_tree_find_integer() = %d\n", node->integer));
   return node->integer;
 }
 
@@ -283,10 +353,16 @@ INLINE_DEVICE_TREE const char *
 device_tree_find_string(device_tree *root,
                        const char *path)
 {
-  device_tree *node = device_tree_find_node(root,
-                                           path,
-                                           node_string,
-                                           device_tree_abort);
+  device_tree *node;
+  TRACE(trace_device_tree,
+       ("device_tree_find_string(root=0x%x, path=%s)\n", root, path));
+  node = device_tree_find_node(root,
+                              path,
+                              path, /* full-name */
+                              node_string,
+                              device_tree_abort);
+  TRACE(trace_device_tree,
+       ("device_tree_find_string() = 0x%x\n", node->string));
   return node->string;
 }
 
@@ -294,10 +370,16 @@ INLINE_DEVICE_TREE int
 device_tree_find_boolean(device_tree *root,
                         const char *path)
 {
-  device_tree *node = device_tree_find_node(root,
-                                           path,
-                                           node_boolean,
-                                           device_tree_abort);
+  device_tree *node;
+  TRACE(trace_device_tree,
+       ("device_tree_find_boolean(root=0x%x, path=%s)\n", root, path));
+  node = device_tree_find_node(root,
+                              path,
+                              path, /* full-name */
+                              node_boolean,
+                              device_tree_abort);
+  TRACE(trace_device_tree,
+       ("device_tree_find_boolean() = %d\n", node->boolean));
   return node->boolean;
 }
 
@@ -308,9 +390,14 @@ STATIC_INLINE_DEVICE_TREE void
 device_tree_init_device(device_tree *root,
                        void *data)
 {
-  psim *system = (psim*)data;
-  if (root->type == node_device)
+  psim *system;
+  system = (psim*)data;
+  if (root->type == node_device) {
+    TRACE(trace_device_tree,
+         ("device_tree_init() initializing device=0x%x:%s\n",
+          root->device, root->device->full_name));
     root->device->callback->init(root->device, system);
+  }
 }
 
 
@@ -318,7 +405,11 @@ INLINE_DEVICE_TREE void
 device_tree_init(device_tree *root,
                 psim *system)
 {
+  TRACE(trace_device_tree,
+       ("device_tree_init(root=0x%x, system=0x%x)\n", root, system));
   device_tree_traverse(root, device_tree_init_device, NULL, system);
+  TRACE(trace_device_tree,
+       ("device_tree_init() = void\n"));
 }
 
 
@@ -363,10 +454,6 @@ device_tree_dump(device_tree *device,
 
 /* Parse a device name, various formats */
 
-#ifndef __NetBSD__
-#define strtouq strtoul
-#endif
-
 #define SCAN_INIT(START, END, COUNT, NAME) \
   char *START = NULL; \
   char *END = strchr(NAME, '@'); \
@@ -377,7 +464,7 @@ device_tree_dump(device_tree *device,
 
 #define SCAN_U(START, END, COUNT, U) \
 do { \
-  *U = strtouq(START, &END, 0); \
+  *U = strtoul(START, &END, 0); \
   if (START == END) \
     return COUNT; \
   COUNT++; \
@@ -397,7 +484,7 @@ do { \
   START = END + 1; \
 } while (0)
 
-#define SCAN_C(START, END, COUNT, C) \
+#define SCAN_C(START, END, COUNT, C, SIZE) \
 do { \
   char *chp = C; \
   END = START; \
@@ -407,6 +494,8 @@ do { \
     *chp = *END; \
     chp += 1; \
     END += 1; \
+    if ((SIZE) <= ((END) - (START))) \
+      return COUNT; /* overflow */ \
   } \
   *chp = '\0'; \
   if (START == END) \
@@ -465,21 +554,21 @@ scand_uw_uw_u(const char *name,
 
 INLINE_DEVICE_TREE int
 scand_c(const char *name,
-       char *c1)
+       char *c1, int c1size)
 {
   SCAN_INIT(start, end, count, name);
-  SCAN_C(start, end, count, c1);
+  SCAN_C(start, end, count, c1, c1size);
   return count;
 }
 
 INLINE_DEVICE_TREE int
 scand_c_uw_u(const char *name,
-            char *c1,
+            char *c1, int c1size,
             unsigned_word *uw2,
             unsigned *u3)
 {
   SCAN_INIT(start, end, count, name);
-  SCAN_C(start, end, count, c1);
+  SCAN_C(start, end, count, c1, c1size);
   SCAN_U(start, end, count, uw2);
   SCAN_U(start, end, count, u3);
   return count;
index d8e5481..bcd9bea 100644 (file)
@@ -110,7 +110,11 @@ INLINE_DEVICE_TREE void device_tree_dump
  void *ignore_data_argument);
 
 
-/* Parse a device name, various formats */
+/* Parse a device name, various formats:
+
+   uw: unsigned_word
+   u: unsigned
+   c: string */
 
 INLINE_DEVICE_TREE int scand_uw
 (const char *name,
@@ -135,11 +139,11 @@ INLINE_DEVICE_TREE int scand_uw_uw_u
  
 INLINE_DEVICE_TREE int scand_c
 (const char *name,
- char *c1);
+ char *c1, int c1size);
 
 INLINE_DEVICE_TREE int scand_c_uw_u
 (const char *name,
- char *c1,
+ char *c1, int c1size,
  unsigned_word *uw2,
  unsigned *u3);
 
index 6b4d940..c0813d6 100644 (file)
@@ -59,7 +59,7 @@ generic_init_callback(const device *me,
   me->parent->callback->attach_address(me->parent,
                                       me->name,
                                       attach_callback,
-                                      0 /*address_space*/,
+                                      0 /*space*/,
                                       addr,
                                       nr_bytes,
                                       access_read_write,
@@ -81,7 +81,7 @@ INLINE_DEVICES void
 unimp_device_attach_address(const device *me,
                            const char *name,
                            attach_type type,
-                           int address_space,
+                           int space,
                            unsigned_word addr,
                            unsigned nr_bytes,
                            access_type access,
@@ -94,7 +94,7 @@ INLINE_DEVICES void
 unimp_device_detach_address(const device *me,
                            const char *name,
                            attach_type type,
-                           int address_space,
+                           int space,
                            unsigned_word addr,
                            unsigned nr_bytes,
                            access_type access,
@@ -106,7 +106,7 @@ unimp_device_detach_address(const device *me,
 INLINE_DEVICES unsigned
 unimp_device_io_read_buffer(const device *me,
                            void *dest,
-                           int address_space,
+                           int space,
                            unsigned_word addr,
                            unsigned nr_bytes,
                            cpu *processor,
@@ -119,7 +119,7 @@ unimp_device_io_read_buffer(const device *me,
 INLINE_DEVICES unsigned
 unimp_device_io_write_buffer(const device *me,
                             const void *source,
-                            int address_space,
+                            int space,
                             unsigned_word addr,
                             unsigned nr_bytes,
                             cpu *processor,
@@ -132,7 +132,7 @@ unimp_device_io_write_buffer(const device *me,
 INLINE_DEVICES unsigned
 unimp_device_dma_read_buffer(const device *me,
                             void *target,
-                            int address_space,
+                            int space,
                             unsigned_word addr,
                             unsigned nr_bytes)
 {
@@ -143,7 +143,7 @@ unimp_device_dma_read_buffer(const device *me,
 INLINE_DEVICES unsigned
 unimp_device_dma_write_buffer(const device *me,
                              const void *source,
-                             int address_space,
+                             int space,
                              unsigned_word addr,
                              unsigned nr_bytes,
                              int violate_read_only_section)
@@ -213,15 +213,16 @@ ignore_device_init(const device *me,
 INLINE_DEVICES void
 pass_device_attach_address(const device *me,
                           const char *name,
-                          attach_type type,
-                          int address_space,
+                          attach_type attach,
+                          int space,
                           unsigned_word addr,
                           unsigned nr_bytes,
                           access_type access,
                           const device *who) /*callback/default*/
 {
-  me->parent->callback->attach_address(me->parent, name, type,
-                                      address_space, addr, nr_bytes,
+  DTRACE_ATTACH_ADDRESS(pass);
+  me->parent->callback->attach_address(me->parent, name, attach,
+                                      space, addr, nr_bytes,
                                       access,
                                       who);
 }
@@ -229,39 +230,42 @@ pass_device_attach_address(const device *me,
 INLINE_DEVICES void
 pass_device_detach_address(const device *me,
                           const char *name,
-                          attach_type type,
-                          int address_space,
+                          attach_type attach,
+                          int space,
                           unsigned_word addr,
                           unsigned nr_bytes,
                           access_type access,
                           const device *who) /*callback/default*/
 {
-  me->parent->callback->detach_address(me->parent, name, type,
-                                      address_space, addr, nr_bytes, access,
+  DTRACE_DETACH_ADDRESS(pass);
+  me->parent->callback->detach_address(me->parent, name, attach,
+                                      space, addr, nr_bytes, access,
                                       who);
 }
 
 INLINE_DEVICES unsigned
 pass_device_dma_read_buffer(const device *me,
-                           void *target,
-                           int address_space,
+                           void *dest,
+                           int space,
                            unsigned_word addr,
                            unsigned nr_bytes)
 {
-  return me->parent->callback->dma_read_buffer(me->parent, target,
-                                              address_space, addr, nr_bytes);
+  DTRACE_DMA_READ_BUFFER(pass);
+  return me->parent->callback->dma_read_buffer(me->parent, dest,
+                                              space, addr, nr_bytes);
 }
 
 INLINE_DEVICES unsigned
 pass_device_dma_write_buffer(const device *me,
                             const void *source,
-                            int address_space,
+                            int space,
                             unsigned_word addr,
                             unsigned nr_bytes,
                             int violate_read_only_section)
 {
+  DTRACE_DMA_WRITE_BUFFER(pass);
   return me->parent->callback->dma_write_buffer(me->parent, source,
-                                               address_space, addr,
+                                               space, addr,
                                                nr_bytes,
                                                violate_read_only_section);
 }
@@ -341,7 +345,7 @@ typedef enum {
 STATIC_INLINE_DEVICES unsigned
 console_io_read_buffer_callback(const device *me,
                                void *dest,
-                               int address_space,
+                               int space,
                                unsigned_word addr,
                                unsigned nr_bytes,
                                cpu *processor,
@@ -349,9 +353,7 @@ console_io_read_buffer_callback(const device *me,
 {
   console_device *console = (console_device*)me->data;
   unsigned_1 val;
-  TRACE(trace_console_device,
-       ("device=0x%x, addr=0x%x, nr_bytes=%d\n",
-        me, addr, nr_bytes));
+  DTRACE_IO_READ_BUFFER(console);
 
   /* determine what was read */
 
@@ -416,7 +418,7 @@ console_io_read_buffer_callback(const device *me,
 STATIC_INLINE_DEVICES unsigned
 console_io_write_buffer_callback(const device *me,
                                 const void *source,
-                                int address_space,
+                                int space,
                                 unsigned_word addr,
                                 unsigned nr_bytes,
                                 cpu *processor,
@@ -424,10 +426,7 @@ console_io_write_buffer_callback(const device *me,
 {
   console_device *console = (console_device*)me->data;
   unsigned_1 val = *(unsigned8*)source;
-
-  TRACE(trace_console_device,
-       ("device=0x%x, addr=0x%x, nr_bytes=%d, val=%d\n",
-        me, addr, nr_bytes, val));
+  DTRACE_IO_WRITE_BUFFER(console);
 
   switch (addr) {
   case console_read_buffer:
@@ -437,8 +436,7 @@ console_io_write_buffer_callback(const device *me,
     console->input.status = val;
     break;
   case console_write_buffer:
-    TRACE(trace_console_device,
-         ("<%c:%d>", val, val));
+    DTRACE(console, ("<%c:%d>", val, val));
     printf_filtered("%c",val) ;
     console->output.buffer = val;
     console->output.status = 1;
@@ -472,6 +470,7 @@ static device_callbacks const console_callbacks = {
 
 STATIC_INLINE_DEVICES const device *
 console_create(const char *name,
+              const char *full_name,
               const device *parent)
 {
   /* create the descriptor */
@@ -485,6 +484,7 @@ console_create(const char *name,
 
   /* insert into the device tree along with its address info */
   return device_create_from(name,
+                           full_name,
                            console, /* data */
                            &console_callbacks,
                            parent);
@@ -507,16 +507,14 @@ console_create(const char *name,
 STATIC_INLINE_DEVICES unsigned
 icu_io_read_buffer_callback(const device *me,
                            void *dest,
-                           int address_space,
-                           unsigned_word base,
+                           int space,
+                           unsigned_word addr,
                            unsigned nr_bytes,
                            cpu *processor,
                            unsigned_word cia)
 {
   unsigned_1 val;
-  TRACE(trace_icu_device,
-       ("device=0x%x, base=0x%x, nr_bytes=%d\n",
-        me, base, nr_bytes));
+  DTRACE_IO_READ_BUFFER(icu);
   val = cpu_nr(processor);
   bzero(dest, nr_bytes);
   *(unsigned_1*)dest = val;
@@ -527,17 +525,15 @@ icu_io_read_buffer_callback(const device *me,
 STATIC_INLINE_DEVICES unsigned
 icu_io_write_buffer_callback(const device *me,
                             const void *source,
-                            int address_space,
-                            unsigned_word base,
+                            int space,
+                            unsigned_word addr,
                             unsigned nr_bytes,
                             cpu *processor,
                             unsigned_word cia)
 {
   psim *system = cpu_system(processor);
   unsigned_1 val = H2T_1(*(unsigned_1*)source);
-  TRACE(trace_icu_device,
-       ("device=0x%x, base=0x%x, nr_bytes=%d, val=0x%x\n",
-        me, base, nr_bytes, val));
+  DTRACE_IO_WRITE_BUFFER(icu);
   /* tell the parent device that the interrupt lines have changed.
      For this fake ICU.  The interrupt lines just indicate the cpu to
      interrupt next */
@@ -575,12 +571,13 @@ static device_callbacks const icu_callbacks = {
 STATIC_INLINE_DEVICES unsigned
 halt_io_read_buffer_callback(const device *me,
                             void *dest,
-                            int address_space,
-                            unsigned_word base,
+                            int space,
+                            unsigned_word addr,
                             unsigned nr_bytes,
                             cpu *processor,
                             unsigned_word cia)
 {
+  DTRACE_IO_READ_BUFFER(halt);
   cpu_halt(processor, cia, was_exited, 0);
   return 0;
 }
@@ -589,12 +586,13 @@ halt_io_read_buffer_callback(const device *me,
 STATIC_INLINE_DEVICES unsigned
 halt_io_write_buffer_callback(const device *me,
                              const void *source,
-                             int address_space,
+                             int space,
                              unsigned_word addr,
                              unsigned nr_bytes,
                              cpu *processor,
                              unsigned_word cia)
 {
+  DTRACE_IO_WRITE_BUFFER(halt);
   cpu_halt(processor, cia, was_exited, 0);
   return 0;
 }
@@ -630,7 +628,8 @@ register_init_callback(const device *me,
   unsigned_word value;
   unsigned which_cpu;
   int status;
-  status = scand_c_uw_u(me->name, name, &value, &which_cpu);
+  DTRACE_INIT(register);
+  status = scand_c_uw_u(me->name, name, sizeof(name), &value, &which_cpu);
   switch (status) {
   case 2: /* register@<name>,<value> */
     psim_write_register(system, -1, &value, name, cooked_transfer);
@@ -702,6 +701,7 @@ vm_init_callback(const device *me,
                 psim *system)
 {
   vm_device *vm = (vm_device*)me->data;
+  DTRACE_INIT(vm);
 
   /* revert the stack/heap variables to their defaults */
   vm->stack_lower_limit = vm->stack_bound;
@@ -724,14 +724,15 @@ vm_init_callback(const device *me,
 STATIC_INLINE_DEVICES void
 vm_attach_address(const device *me,
                  const char *name,
-                 attach_type type,
-                 int address_space,
+                 attach_type attach,
+                 int space,
                  unsigned_word addr,
                  unsigned nr_bytes,
                  access_type access,
                  const device *who) /*callback/default*/
 {
   vm_device *vm = (vm_device*)me->data;
+  DTRACE_ATTACH_ADDRESS(vm);
   /* update end of bss if necessary */
   if (vm->heap_base < addr + nr_bytes) {
     vm->heap_base = addr + nr_bytes;
@@ -799,12 +800,13 @@ add_vm_space(const device *me,
 STATIC_INLINE_DEVICES unsigned
 vm_io_read_buffer_callback(const device *me,
                           void *dest,
-                          int address_space,
+                          int space,
                           unsigned_word addr,
                           unsigned nr_bytes,
                           cpu *processor,
                           unsigned_word cia)
 {
+  DTRACE_IO_READ_BUFFER(vm);
   if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
     bzero(dest, nr_bytes); /* always initialized to zero */
     return nr_bytes;
@@ -817,15 +819,16 @@ vm_io_read_buffer_callback(const device *me,
 STATIC_INLINE_DEVICES unsigned
 vm_io_write_buffer_callback(const device *me,
                            const void *source,
-                           int address_space,
+                           int space,
                            unsigned_word addr,
                            unsigned nr_bytes,
                            cpu *processor,
                            unsigned_word cia)
 {
+  DTRACE_IO_WRITE_BUFFER(vm);
   if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
     return me->parent->callback->dma_write_buffer(me->parent, source,
-                                                 address_space, addr,
+                                                 space, addr,
                                                  nr_bytes,
                                                  0/*violate_read_only*/);
   }
@@ -873,7 +876,8 @@ static device_callbacks const vm_callbacks = {
 
 STATIC_INLINE_DEVICES const device *
 vea_vm_create(const char *name,
-            const device *parent)
+             const char *full_name,
+             const device *parent)
 {
   vm_device *vm = ZALLOC(vm_device);
   unsigned_word addr;
@@ -887,6 +891,7 @@ vea_vm_create(const char *name,
 
   /* insert in the tree including the buffer */
   return device_create_from(name,
+                           full_name,
                            vm, /* data */
                            &vm_callbacks,
                            parent);
@@ -905,9 +910,20 @@ memory_init_callback(const device *me,
   unsigned_word addr;
   unsigned nr_bytes;
   unsigned access;
+  int nr_args;
+  DTRACE_INIT(memory);
 
-  if (scand_uw_u_u(me->name, &addr, &nr_bytes, &access) != 3)
+  nr_args = scand_uw_u_u(me->name, &addr, &nr_bytes, &access);
+  switch (nr_args) {
+  case 2:
+    access = access_read_write_exec;
+    break;
+  case 3:
+    break;
+  default:
     error("memory_init_callback() invalid memory device %s\n", me->name);
+    break;
+  }
 
   me->parent->callback->attach_address(me->parent,
                                       me->name,
@@ -936,24 +952,6 @@ static device_callbacks const memory_callbacks = {
 };
 
 
-STATIC_INLINE_DEVICES const device *
-memory_create(const char *name,
-             const device *parent)
-{
-  void *buffer;
-  unsigned_word addr;
-  unsigned nr_bytes;
-  if (scand_uw_u(name, &addr, &nr_bytes) != 2)
-    error("memory_create() invalid memory device %s\n");
-
-  /* insert in the tree including the buffer */
-  return device_create_from(name,
-                           buffer, /* data */
-                           &memory_callbacks,
-                           parent);
-}
-
-
 \f
 /* IOBUS device: iobus@<address>
 
@@ -963,7 +961,7 @@ STATIC_INLINE_DEVICES void
 iobus_attach_address_callback(const device *me,
                              const char *name,
                              attach_type type,
-                             int address_space,
+                             int space,
                              unsigned_word addr,
                              unsigned nr_bytes,
                              access_type access,
@@ -974,8 +972,8 @@ iobus_attach_address_callback(const device *me,
   if (type == attach_default)
     error("iobus_attach_address_callback() no default for %s/%s\n",
          me->name, name);
-  if (address_space != 0)
-    error("iobus_attach_address_callback() no address_space for %s/%s\n",
+  if (space != 0)
+    error("iobus_attach_address_callback() no space for %s/%s\n",
          me->name, name);
   /* get the bus address */
   if (scand_uw(me->name, &iobus_addr) != 1)
@@ -984,7 +982,7 @@ iobus_attach_address_callback(const device *me,
   me->parent->callback->attach_address(me->parent,
                                       me->name,
                                       type,
-                                      0 /*address_space*/,
+                                      0 /*space*/,
                                       iobus_addr + addr,
                                       nr_bytes,
                                       access,
@@ -1052,9 +1050,11 @@ file_init_callback(const device *me,
                   psim *system)
 {
   unsigned_word addr;
+  unsigned count;
   char *file_name;
   char buf;
   FILE *image;
+  DTRACE_INIT(file);
 
   if ((file_name = strchr(me->name, ',')) == NULL
       || scand_uw(me->name, &addr) != 1)
@@ -1067,14 +1067,17 @@ file_init_callback(const device *me,
     error("file_init_callback() file open failed for %s\n", me->name);
 
   /* read it in slowly */
+  count = 0;
   while (fread(&buf, 1, 1, image) > 0) {
-    me->parent->callback->dma_write_buffer(me->parent,
-                                          &buf,
-                                          0 /*address-space*/,
-                                          addr,
-                                          1 /*nr-bytes*/,
-                                          1 /*violate ro*/);
-    addr++;
+    if (me->parent->callback->dma_write_buffer(me->parent,
+                                              &buf,
+                                              0 /*address-space*/,
+                                              addr+count,
+                                              1 /*nr-bytes*/,
+                                              1 /*violate ro*/) != 1)
+      error("file_init_callback() failed to write to address 0x%x, offset %d\n",
+           addr+count, count);
+    count++;
   }
 
   /* close down again */
@@ -1115,6 +1118,7 @@ STATIC_INLINE_DEVICES void
 htab_init_callback(const device *me,
                   psim *system)
 {
+  DTRACE_INIT(htab);
   /* only the pte does work */
   if (strncmp(me->name, "pte@", strlen("pte@")) == 0) {
     unsigned_word htab_ra;
@@ -1184,12 +1188,10 @@ static device_callbacks const sim_callbacks = {
    this device loads or maps the relevant text/data segments into
    memory using dma. */
 
-/* create a device tree from the image */
-
 STATIC_INLINE_DEVICES void
-update_device_tree_for_section(bfd *abfd,
-                              asection *the_section,
-                              PTR obj)
+update_for_binary_section(bfd *abfd,
+                         asection *the_section,
+                         PTR obj)
 {
   unsigned_word section_vma;
   unsigned_word section_size;
@@ -1208,17 +1210,17 @@ update_device_tree_for_section(bfd *abfd,
   /* find where it is to go */
   section_vma = bfd_get_section_vma(abfd, the_section);
 
-  TRACE(trace_device_tree,
-       ("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
-        bfd_get_section_name(abfd, the_section),
-        section_vma, section_size,
-        bfd_get_section_flags(abfd, the_section),
-        bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
-        bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
-        bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
-        bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
-        bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
-       ));
+  DTRACE(binary,
+        ("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
+         bfd_get_section_name(abfd, the_section),
+         section_vma, section_size,
+         bfd_get_section_flags(abfd, the_section),
+         bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
+         bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
+         bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
+         bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
+         bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
+         ));
 
   /* determine the devices access */
   access = access_read;
@@ -1251,7 +1253,7 @@ update_device_tree_for_section(bfd *abfd,
     }
     if (me->parent->callback->dma_write_buffer(me->parent,
                                               section_init,
-                                              0 /*address_space*/,
+                                              0 /*space*/,
                                               section_vma,
                                               section_size,
                                               1 /*violate_read_only*/)
@@ -1268,9 +1270,10 @@ binary_init_callback(const device *me,
 {
   char file_name[100];
   bfd *image;
+  DTRACE_INIT(binary);
 
   /* get a file name */
-  if (scand_c(me->name, file_name) != 1)
+  if (scand_c(me->name, file_name, sizeof(file_name)) != 1)
     error("load_binary_init_callback() invalid load-binary device %s\n",
          me->name);
 
@@ -1291,7 +1294,7 @@ binary_init_callback(const device *me,
 
   /* and the data sections */
   bfd_map_over_sections(image,
-                       update_device_tree_for_section,
+                       update_for_binary_section,
                        (PTR)me);
 
   bfd_close(image);
@@ -1371,18 +1374,17 @@ write_stack_arguments(psim *system,
                      unsigned_word start_arg,
                      unsigned_word end_arg)
 {
-  TRACE(trace_create_stack,
-       ("write_stack_arguments() - %s=0x%x %s=0x%x %s=0x%x %s=0x%x\n",
-        "system", system, "arg", arg,
-        "start_block", start_block, "start_arg", start_arg));
+  DTRACE(stack,
+       ("write_stack_arguments(system=0x%x, arg=0x%x, start_block=0x%x, end_block=0x%x, start_arg=0x%x, end_arg=0x%x)\n",
+        system, arg, start_block, end_block, start_arg, end_arg));
   if (arg == NULL)
     error("write_arguments: character array NULL\n");
   /* only copy in arguments, memory is already zero */
   for (; *arg != NULL; arg++) {
     int len = strlen(*arg)+1;
     unsigned_word target_start_block;
-    TRACE(trace_create_stack,
-         ("write_stack_arguments - write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
+    DTRACE(stack,
+         ("write_stack_arguments() write %s=%s at %s=0x%x %s=0x%x %s=0x%x\n",
           "**arg", *arg, "start_block", start_block,
           "len", len, "start_arg", start_arg));
     if (psim_write_memory(system, 0, *arg,
@@ -1402,6 +1404,8 @@ write_stack_arguments(psim *system,
   if (start_block != end_block
       || ALIGN_8(start_arg) != end_arg)
     error("write_stack_arguments - possible corruption\n");
+  DTRACE(stack,
+        ("write_stack_arguments() = void\n"));
 }
 
 STATIC_INLINE_DEVICES void
@@ -1500,10 +1504,16 @@ stack_ioctl_callback(const device *me,
   stack_pointer = va_arg(ap, unsigned_word);
   argv = va_arg(ap, char **);
   envp = va_arg(ap, char **);
+  va_end(ap);
+  DTRACE(stack,
+        ("stack_ioctl_callback(me=0x%x:%s, system=0x%x, processor=0x%x, cia=0x%x, argv=0x%x, envp=0x%x)\n",
+         me, me->full_name, system, processor, cia, argv, envp));
   if (strcmp(me->name, "stack@elf") == 0)
     create_elf_stack_frame(system, stack_pointer, argv, envp);
   else if (strcmp(me->name, "stack@xcoff") == 0)
     create_aix_stack_frame(system, stack_pointer, argv, envp);
+  DTRACE(stack, 
+        ("stack_ioctl_callback() = void\n"));
 }
 
 
@@ -1529,6 +1539,7 @@ static device_callbacks const stack_callbacks = {
 
 typedef const device *(device_creator)
      (const char *name,
+      const char *full_name,
       const device *parent);
 
 typedef struct _device_descriptor device_descriptor;
@@ -1540,7 +1551,7 @@ struct _device_descriptor {
 
 static device_descriptor devices[] = {
   { "console", console_create, NULL },
-  { "memory", memory_create, NULL },
+  { "memory", NULL, &memory_callbacks },
   { "vm", vea_vm_create, NULL },
   { "halt", NULL, &halt_callbacks },
   { "icu", NULL, &icu_callbacks },
@@ -1559,6 +1570,7 @@ static device_descriptor devices[] = {
 
 INLINE_DEVICES const device *
 device_create(const char *name,
+             const char *full_name,
              const device *parent)
 {
   device_descriptor *device;
@@ -1571,9 +1583,10 @@ device_create(const char *name,
        && (device->name[name_len] == '\0'
            || device->name[name_len] == '@'))
       if (device->creator != NULL)
-       return device->creator(name, parent);
+       return device->creator(name, full_name, parent);
       else
        return device_create_from(name,
+                                 full_name,
                                  NULL /* data */,
                                  device->callbacks,
                                  parent);
@@ -1585,12 +1598,14 @@ device_create(const char *name,
 
 INLINE_DEVICES const device *
 device_create_from(const char *name,
+                  const char *full_name,
                   void *data,
                   const device_callbacks *callback,
                   const device *parent)
 {
   device *me = ZALLOC(device);
   me->name = strdup(name);
+  me->full_name = strdup(full_name);
   me->data = data;
   me->callback = callback;
   me->parent = parent;
index df02288..fd22a54 100644 (file)
@@ -79,6 +79,10 @@ typedef void (device_init_callback)
      (const device *me,
       psim *system);
 
+#define DTRACE_INIT(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_init(me=0x%x:%s system=0x%x)\n", \
+            me, me->full_name, system))
 
 /* Data transfers:
 
@@ -160,17 +164,27 @@ typedef void (device_init_callback)
 typedef void (device_config_address_callback)
      (const device *me,
       const char *name,
-      attach_type type,
-      int address_space,
+      attach_type attach,
+      int space,
       unsigned_word addr,
       unsigned nr_bytes,
       access_type access,
       const device *who); /*callback/default*/
 
+#define DTRACE_ATTACH_ADDRESS(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_attach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
+            me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
+#define DTRACE_DETACH_ADDRESS(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_detach_address(me=0x%x:%s, name=%s, attach=%d, space=%d, addr=0x%x, nr_bytes=%d, access=%d, who=0x%x)\n", \
+            me, me->full_name, name, attach, space, addr, nr_bytes, access, who))
+
+
 typedef unsigned (device_io_read_buffer_callback)
      (const device *me,
       void *dest,
-      int address_space,
+      int space,
       unsigned_word addr,
       unsigned nr_bytes,
       cpu *processor,
@@ -179,27 +193,46 @@ typedef unsigned (device_io_read_buffer_callback)
 typedef unsigned (device_io_write_buffer_callback)
      (const device *me,
       const void *source,
-      int address_space,
+      int space,
       unsigned_word addr,
       unsigned nr_bytes,
       cpu *processor,
       unsigned_word cia);
 
+#define DTRACE_IO_READ_BUFFER(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_io_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
+            me, me->full_name, dest, space, addr, nr_bytes, processor, cia))
+#define DTRACE_IO_WRITE_BUFFER(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_io_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d processor=0x%x cia=0x%x)\n", \
+            me, me->full_name, source, space, addr, nr_bytes, processor, cia))
+
+
 typedef unsigned (device_dma_read_buffer_callback)
      (const device *me,
       void *dest,
-      int address_space,
+      int space,
       unsigned_word addr,
       unsigned nr_bytes);
 
 typedef unsigned (device_dma_write_buffer_callback)
      (const device *me,
       const void *source,
-      int address_space,
+      int space,
       unsigned_word addr,
       unsigned nr_bytes,
       int violate_read_only_section);
 
+#define DTRACE_DMA_READ_BUFFER(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_dma_read_buffer(me=0x%x:%s dest=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
+            me, me->full_name, dest, space, addr, nr_bytes))
+#define DTRACE_DMA_WRITE_BUFFER(OBJECT) \
+     DTRACE(OBJECT, \
+           (#OBJECT "_dma_write_buffer(me=0x%x:%s source=0x%x space=%d addr=0x%x nr_bytes=%d)\n", \
+            me, me->full_name, source, space, addr, nr_bytes))
+
 
 /* Interrupts:
 
@@ -282,7 +315,8 @@ typedef struct _device_callbacks {
 
 /* A device */
 struct _device {
-  const char *name; /* eg rom@0x1234, 0x400 */
+  const char *name; /* eg rom@0x1234,0x400 */
+  const char *full_name; /* eg /isa/rom@0x1234,0x400 */
   void *data; /* device specific data */
   const device_callbacks *callback;
   const device *parent;
@@ -293,12 +327,14 @@ struct _device {
 
 INLINE_DEVICES const device *device_create
 (const char *name,
+ const char *full_name,
  const device *parent);
 
 /* create a new device using the parameterized data */
 
 INLINE_DEVICES const device *device_create_from
 (const char *name,
+ const char *full_name,
  void *data,
  const device_callbacks *callback,
  const device *parent);
similarity index 84%
rename from sim/ppc/system.h
rename to sim/ppc/emul_netbsd.h
index 709d5c5..3bdb590 100644 (file)
     */
 
 
-#ifndef _SYSTEM_H_
-#define _SYSTEM_H_
+#ifndef _EMUL_NETBSD_H_
+#define _EMUL_NETBSD_H_
 
-#ifndef INLINE_SYSTEM
-#define INLINE_SYSTEM
-#endif
-
-INLINE_SYSTEM void system_call
-(cpu *processor,
- unsigned_word cia);
+extern emulation emul_netbsd;
 
 #endif
diff --git a/sim/ppc/gen.c b/sim/ppc/gen.c
deleted file mode 100644 (file)
index 76f1bcb..0000000
+++ /dev/null
@@ -1,3323 +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.
-    */
-
-
-/* BUGS:
-
-   Instead of using/abusing macro's the semantic code should be parsed
-   and each `cachable' expression replaced with the corresponding
-   value. */
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "config.h"
-#include "ppc-config.h"
-
-#undef WITH_ASSERT
-#define WITH_ASSERT 1
-
-#include "debug.h"
-
-
-/****************************************************************/
-
-static void
-error (char *msg, ...)
-{
-  va_list ap;
-  va_start(ap, msg);
-  vprintf(msg, ap);
-  va_end(ap);
-  exit (1);
-}
-
-static void *
-zmalloc(long size)
-{
-  void *memory = malloc(size);
-  if (memory == NULL)
-    error("zmalloc failed\n");
-  bzero(memory, size);
-  return memory;
-}
-
-static void
-dumpf (int indent, char *msg, ...)
-{
-  va_list ap;
-  for (; indent > 0; indent--)
-    printf(" ");
-  va_start(ap, msg);
-  vprintf(msg, ap);
-  va_end(ap);
-}
-
-
-/****************************************************************/
-
-int idecode_expand_semantics = WITH_IDECODE_EXPAND_SEMANTICS;
-int idecode_cache = WITH_IDECODE_CACHE;
-int spreg_lookup_table = WITH_SPREG_LOOKUP_TABLE;
-
-/****************************************************************/
-
-typedef struct {
-  int valid;
-  char *old_name;
-  char *new_name;
-  char *type;
-  char *expression;
-} extraction_rules;
-
-extraction_rules cachable_values[] = WITH_IDECODE_CACHE_RULES;
-
-/****************************************************************/
-
-typedef struct _opcode_rules {
-  int valid;
-  int first;
-  int last;
-  int force_first;
-  int force_last;
-  int force_slash;
-  char *force_expansion;
-  int use_switch;
-  unsigned special_mask;
-  unsigned special_value;
-  unsigned special_rule;
-} opcode_rules;
-
-/* FIXME - this should be loaded from a file */
-opcode_rules opcode_table[] = WITH_IDECODE_OPCODE_RULES;
-
-static void
-dump_opcode_rule(opcode_rules *rule,
-                int indent)
-{
-  printf("(opcode_rules*)%p\n", rule);
-  dumpf(indent, "(valid %d)\n", rule->valid);
-  ASSERT(rule != NULL);
-  if (rule->valid) {
-    dumpf(indent, "(first %d)\n", rule->first);
-    dumpf(indent, "(last %d)\n", rule->last);
-    dumpf(indent, "(force_first %d)\n", rule->force_first);
-    dumpf(indent, "(force_last %d)\n", rule->force_last);
-    dumpf(indent, "(force_slash %d)\n", rule->force_slash);
-    dumpf(indent, "(force_expansion %s)\n", rule->force_expansion);
-  }
-}
-
-
-/****************************************************************/
-
-enum gen_constants {
-  insn_size = 32,
-  nr_of_sprs = 1024
-};
-
-char cache_idecode_formal[] = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia,\n idecode_cache *cache_entry";
-char cache_idecode_actual[] = "processor, instruction, cia, cache_entry";
-char cache_insn_formal[] = "cpu *processor,\n idecode_cache *cache_entry,\n unsigned_word cia";
-char cache_insn_actual[] = "processor, entry, cia";
-
-char insn_formal[] = "cpu *processor,\n instruction_word instruction,\n unsigned_word cia";
-char insn_actual[] = "processor, instruction, cia";
-
-char insn_local[] = "unsigned_word nia = cia + 4;";
-
-
-/****************************************************************/
-
-static int
-bin2i(char *bin, int width)
-{
-  int i = 0;
-  while (*bin != '\0' && width != 0) {
-    i = (i << 1) + (*bin - '0');
-    width--;
-    bin++;
-  }
-  return i;
-}
-
-
-static int
-it_is(char *flag,
-      char *flags)
-{
-  int flag_len = strlen(flag);
-  while (*flags != '\0') {
-    if (!strncmp(flags, flag, flag_len)
-       && (flags[flag_len] == ',' || flags[flag_len] == '\0'))
-      return 1;
-    while (*flags != ',') {
-      if (*flags == '\0')
-       return 0;
-      flags++;
-    }
-    flags++;
-  }
-  return 0;
-}
-
-
-/****************************************************************/
-
-typedef struct _lf lf;
-struct _lf {
-  FILE *stream;
-  int line_nr; /* nr complete lines written, curr line is line_nr+1 */
-  int indent;
-  int line_blank;
-  char *file_name;
-};
-
-
-static lf *
-lf_open(char *name,
-       char *real_name)
-{
-  /* create a file object */
-  lf *new_lf = zmalloc(sizeof(lf));
-  ASSERT(new_lf != NULL);
-  new_lf->file_name = (real_name == NULL
-                      ? name
-                      : real_name);
-
-  /* attach to stdout if pipe */
-  if (!strcmp(name, "-")) {
-    new_lf->stream = stdout;
-  }
-  else {
-    /* create a new file */
-    new_lf->stream = fopen(name, "w");
-    ASSERT(new_lf->stream != NULL);
-  }
-  return new_lf;
-}
-
-
-static void
-lf_close(lf *file)
-{
-  if (file->stream != stdout) {
-    if (fclose(file->stream)) {
-      perror("lf_close.fclose");
-      exit(1);
-    }
-    free(file);
-  }
-}
-
-
-static void
-lf_putchr(lf *file,
-         const char chr)
-{
-  if (chr == '\n') {
-    file->line_nr += 1;
-    file->line_blank = 1;
-  }
-  else if (file->line_blank) {
-    int pad;
-    for (pad = file->indent; pad > 0; pad--)
-      putc(' ', file->stream);
-    file->line_blank = 0;
-  }
-  putc(chr, file->stream);
-}
-
-static void
-lf_indent_suppress(lf *file)
-{
-  file->line_blank = 0;
-}
-
-
-static void
-lf_putstr(lf *file,
-         const char *string)
-{
-  const char *chp;
-  if (string != NULL) {
-    for (chp = string; *chp != '\0'; chp++) {
-      lf_putchr(file, *chp);
-    }
-  }
-}
-
-static void
-do_lf_putunsigned(lf *file,
-             unsigned u)
-{
-  if (u > 0) {
-    do_lf_putunsigned(file, u / 10);
-    lf_putchr(file, (u % 10) + '0');
-  }
-}
-
-
-static void
-lf_putint(lf *file,
-         int decimal)
-{
-  if (decimal == 0)
-    lf_putchr(file, '0');
-  else if (decimal < 0) {
-    lf_putchr(file, '-');
-    do_lf_putunsigned(file, -decimal);
-  }
-  else if (decimal > 0) {
-    do_lf_putunsigned(file, decimal);
-  }
-  else
-    ASSERT(0);
-}
-
-static void
-lf_printf(lf *file,
-         const char *fmt,
-         ...)
-{
-  char buf[1024];
-  va_list ap;
-  int nr_chars;
-
-  va_start(ap, fmt);
-  vsprintf(buf, fmt, ap);
-  /* FIXME - this is really stuffed but so is vsprintf() on a sun! */
-  ASSERT(strlen(buf) > 0 && strlen(buf) < sizeof(buf));
-  lf_putstr(file, buf);
-  va_end(ap);
-}
-
-static void
-lf_print_file_line_nr(lf *file)
-{
-#if WITH_LINE_NUMBERS
-  lf_indent_suppress(file);
-  lf_putstr(file, "#line ");
-  lf_putint(file, file->line_nr+2); /*line_nr == last_line, want next */
-  lf_putstr(file, " \"");
-  lf_putstr(file, file->file_name);
-  lf_putstr(file, "\"\n");
-#endif
-}
-
-static void
-lf_indent(lf *file, int delta)
-{
-  file->indent += delta;
-}
-
-
-/****************************************************************/
-
-/* read entries from ppc.instructions */
-
-enum {
-  file_table_max_fields = 6,
-};
-
-typedef struct _file_table file_table;
-struct _file_table {
-  size_t size;
-  char *buffer;
-  char *pos;
-  int line_nr;
-  char *file_name;
-};
-
-typedef struct _file_table_entry file_table_entry;
-struct _file_table_entry {
-  char *fields[file_table_max_fields];
-  int line_nr;
-  char *file_name;
-  char *annex;
-};
-
-
-static file_table *
-file_table_open(char *file_name)
-{
-  int fd;
-  struct stat stat_buf;
-  file_table *file;
-
-  /* create a file descriptor */
-  file = (file_table*)zmalloc(sizeof(file_table));
-  ASSERT(file != NULL);
-
-  /* save the file name */
-  file->file_name = (char*)zmalloc(strlen(file_name) + 1);
-  ASSERT(file->file_name != NULL);
-  strcpy(file->file_name, file_name);
-
-  /* open the file */
-  fd = open(file->file_name, O_RDONLY, 0);
-  ASSERT(fd >= 0);
-
-  /* determine the size */
-  if (fstat(fd, &stat_buf) < 0) {
-    perror("file_table_open.fstat");
-    exit(1);
-  }
-  file->size = stat_buf.st_size;
-
-  /* allocate this much memory */
-  file->buffer = (char*)zmalloc(file->size+1);
-  if(file->buffer == NULL) {
-    perror("file_table_open.calloc.file->size+1");
-    exit(1);
-  }
-  file->pos = file->buffer;
-
-  /* read it in */
-  if (read(fd, file->buffer, file->size) < file->size) {
-    perror("file_table_open.read");
-    exit(1);
-  }
-  file->buffer[file->size] = '\0';
-
-  /* done */
-  close(fd);
-  return file;
-}
-
-
-static file_table_entry *
-file_table_read(file_table *file)
-{
-  int field;
-  file_table_entry *entry;
-
-  /* skip comments/blanks */
-  while(1) {
-    /* leading white space */
-    while (*file->pos != '\0'
-          && *file->pos != '\n'
-          && isspace(*file->pos))
-      file->pos++;
-    /* comment */
-    if (*file->pos == '#') {
-      do {
-       file->pos++;
-      } while (*file->pos != '\0' && *file->pos != '\n');
-    }
-    /* end of line? */
-    if (*file->pos == '\n') {
-      file->pos++;
-      file->line_nr++;
-    }
-    else
-      break;
-  }
-  if (*file->pos == '\0')
-    return NULL;
-
-  /* create this new entry */
-  entry = (file_table_entry*)zmalloc(sizeof(file_table_entry));
-  ASSERT(entry != NULL);
-  entry->file_name = file->file_name;
-
-  /* break the line into its colon delimitered fields */
-  for (field = 0; field < file_table_max_fields-1; field++) {
-    entry->fields[field] = file->pos;
-    while(*file->pos && *file->pos != ':' && *file->pos != '\n')
-      file->pos++;
-    if (*file->pos == ':') {
-      *file->pos = '\0';
-      file->pos++;
-    }
-  }
-
-  /* any trailing stuff not the last field */
-  ASSERT(field == file_table_max_fields-1);
-  entry->fields[field] = file->pos;
-  while (*file->pos && *file->pos != '\n') {
-    file->pos++;
-  }
-  if (*file->pos == '\n') {
-    *file->pos = '\0';
-    file->pos++;
-  }
-  file->line_nr++;
-  entry->line_nr = file->line_nr;
-
-  /* if following lines tab indented, put in the annex */
-  if (*file->pos == '\t') {
-    entry->annex = file->pos;
-    do {
-      do {
-       file->pos++;
-      } while (*file->pos != '\0' && *file->pos != '\n');
-      if (*file->pos == '\n') {
-       file->pos++;
-       file->line_nr++;
-      }
-    } while (*file->pos != '\0' && *file->pos == '\t');
-    if (file->pos[-1] == '\n')
-      file->pos[-1] = '\0';
-  }
-  else
-    entry->annex = NULL;
-
-  /* return it */
-  return entry;
-
-}
-
-
-static void
-dump_file_table_entry(file_table_entry *entry,
-                     int indent)
-{
-  printf("(file_table_entry*)%p\n", entry);
-
-  if (entry != NULL) {
-    int field;
-    char sep;
-
-    sep = ' ';
-    dumpf(indent, "(fields");
-    for (field = 0; field < file_table_max_fields; field++) {
-      printf("%c%s", sep, entry->fields[field]);
-      sep = ':';
-    }
-    printf(")\n");
-
-    dumpf(indent, "(line_nr %d)\n", entry->line_nr);
-
-    dumpf(indent, "(file_name %s)\n", entry->file_name);
-
-    dumpf(indent, "(annex\n%s\n", entry->annex);
-    dumpf(indent, " )\n");
-
-  }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_field insn_field;
-struct _insn_field {
-  int first;
-  int last;
-  int width;
-  int is_int;
-  int is_slash;
-  int is_string;
-  int val_int;
-  char *pos_string;
-  char *val_string;
-  insn_field *next;
-  insn_field *prev;
-};
-
-typedef struct _insn_fields insn_fields;
-struct _insn_fields {
-  insn_field *bits[insn_size];
-  insn_field *first;
-  insn_field *last;
-  unsigned value;
-};
-
-static insn_field *
-insn_field_new()
-{
-  insn_field *new_field = (insn_field*)zmalloc(sizeof(insn_field));
-  ASSERT(new_field != NULL);
-  return new_field;
-}
-
-static insn_fields *
-insn_fields_new()
-{
-  insn_fields *new_fields = (insn_fields*)zmalloc(sizeof(insn_fields));
-  ASSERT(new_fields != NULL);
-  return new_fields;
-}
-
-
-static insn_fields *
-parse_insn_format(file_table_entry *entry,
-                 char *format)
-{
-  char *chp;
-  insn_fields *fields = insn_fields_new();
-
-  /* create a leading sentinal */
-  fields->first = insn_field_new();
-  fields->first->first = -1;
-  fields->first->last = -1;
-  fields->first->width = 0;
-
-  /* and a trailing sentinal */
-  fields->last = insn_field_new();
-  fields->last->first = insn_size;
-  fields->last->last = insn_size;
-  fields->last->width = 0;
-
-  /* link them together */
-  fields->first->next = fields->last;
-  fields->last->prev = fields->first;
-
-  /* now work through the formats */
-  chp = format;
-
-  while (*chp != '\0') {
-    char *start_pos;
-    char *start_val;
-    int strlen_val;
-    int strlen_pos;
-    insn_field *new_field;
-
-    /* sanity check */
-    if (!isdigit(*chp)) {
-      error("%s:%d: missing position field at `%s'\n",
-           entry->file_name, entry->line_nr, chp);
-    }
-
-    /* break out the bit position */
-    start_pos = chp;
-    while (isdigit(*chp))
-      chp++;
-    strlen_pos = chp - start_pos;
-    if (*chp == '.' && strlen_pos > 0)
-      chp++;
-    else {
-      error("%s:%d: missing field value at %s\n",
-           entry->file_name, entry->line_nr, chp);
-      break;
-    }
-
-    /* break out the value */
-    start_val = chp;
-    while ((*start_val == '/' && *chp == '/')
-          || (isdigit(*start_val) && isdigit(*chp))
-          || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
-      chp++;
-    strlen_val = chp - start_val;
-    if (*chp == ',')
-      chp++;
-    else if (*chp != '\0' || strlen_val == 0) {
-      error("%s:%d: missing field terminator at %s\n",
-           entry->file_name, entry->line_nr, chp);
-      break;
-    }
-
-    /* create a new field and insert it */
-    new_field = insn_field_new();
-    new_field->next = fields->last;
-    new_field->prev = fields->last->prev;
-    new_field->next->prev = new_field;
-    new_field->prev->next = new_field;
-
-    /* the value */
-    new_field->val_string = (char*)zmalloc(strlen_val+1);
-    strncpy(new_field->val_string, start_val, strlen_val);
-    if (isdigit(*new_field->val_string)) {
-      new_field->val_int = atoi(new_field->val_string);
-      new_field->is_int = 1;
-    }
-    else if (new_field->val_string[0] == '/') {
-      new_field->is_slash = 1;
-    }
-    else {
-      new_field->is_string = 1;
-    }
-    
-    /* the pos */
-    new_field->pos_string = (char*)zmalloc(strlen_pos+1);
-    strncpy(new_field->pos_string, start_pos, strlen_pos);
-    new_field->first = atoi(new_field->pos_string);
-    new_field->last = new_field->next->first - 1; /* guess */
-    new_field->width = new_field->last - new_field->first + 1; /* guess */
-    new_field->prev->last = new_field->first-1; /*fix*/
-    new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
-  }
-
-  /* fiddle first/last so that the sentinals `disapear' */
-  ASSERT(fields->first->last < 0);
-  ASSERT(fields->last->first >= insn_size);
-  fields->first = fields->first->next;
-  fields->last = fields->last->prev;
-
-  /* now go over this again, pointing each bit position at a field
-     record */
-  {
-    int i;
-    insn_field *field;
-    field = fields->first;
-    for (i = 0; i < insn_size; i++) {
-      while (field->last < i)
-       field = field->next;
-      fields->bits[i] = field;
-    }
-  }
-
-  /* go over each of the fields, and compute a `value' for the insn */
-  {
-    insn_field *field;
-    fields->value = 0;
-    for (field = fields->first;
-        field->last < insn_size;
-        field = field->next) {
-      fields->value <<= field->width;
-      if (field->is_int)
-       fields->value |= field->val_int;
-    }
-  }
-  return fields;
-}
-
-
-typedef enum {
-  field_constant_int = 1,
-  field_constant_slash = 2,
-  field_constant_string = 3
-} constant_field_types;
-
-
-static int
-insn_field_is_constant(insn_field *field,
-                      opcode_rules *rule)
-{
-  /* field is an integer */
-  if (field->is_int)
-    return field_constant_int;
-  /* field is `/' and treating that as a constant */
-  if (field->is_slash && rule->force_slash)
-    return field_constant_slash;
-  /* field, though variable is on the list */
-  if (field->is_string && rule->force_expansion != NULL) {
-    char *forced_fields = rule->force_expansion;
-    while (*forced_fields != '\0') {
-      int field_len;
-      char *end = strchr(forced_fields, ',');
-      if (end == NULL)
-       field_len = strlen(forced_fields);
-      else
-       field_len = end-forced_fields;
-      if (strncmp(forced_fields, field->val_string, field_len) == 0
-         && field->val_string[field_len] == '\0')
-       return field_constant_string;
-      forced_fields += field_len;
-      if (*forced_fields == ',')
-       forced_fields++;
-    }
-  }
-  return 0;
-}
-
-
-static void
-dump_insn_field(insn_field *field,
-               int indent)
-{
-
-  printf("(insn_field*)0x%x\n", (unsigned)field);
-
-  dumpf(indent, "(first %d)\n", field->first);
-
-  dumpf(indent, "(last %d)\n", field->last);
-
-  dumpf(indent, "(width %d)\n", field->width);
-
-  if (field->is_int)
-    dumpf(indent, "(is_int %d)\n", field->val_int);
-
-  if (field->is_slash)
-    dumpf(indent, "(is_slash)\n");
-
-  if (field->is_string)
-    dumpf(indent, "(is_string `%s')\n", field->val_string);
-  
-  dumpf(indent, "(next 0x%x)\n", field->next);
-  
-  dumpf(indent, "(prev 0x%x)\n", field->prev);
-  
-
-}
-
-static void
-dump_insn_fields(insn_fields *fields,
-                int indent)
-{
-  insn_field *field;
-  int i;
-
-  printf("(insn_fields*)%p\n", fields);
-
-  dumpf(indent, "(first 0x%x)\n", fields->first);
-  dumpf(indent, "(last 0x%x)\n", fields->last);
-
-  dumpf(indent, "(value 0x%x)\n", fields->value);
-
-  for (i = 0; i < insn_size; i++) {
-    dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
-    dump_insn_field(fields->bits[i], indent+1);
-    dumpf(indent, " )\n");
-  }
-
-}
-
-
-/****************************************************************/
-
-typedef struct _opcode_field opcode_field;
-struct _opcode_field {
-  int first;
-  int last;
-  int is_boolean;
-  opcode_field *parent;
-};
-
-static opcode_field *
-opcode_field_new()
-{
-  opcode_field *new_field = (opcode_field*)zmalloc(sizeof(opcode_field));
-  ASSERT(new_field != NULL);
-  new_field->first = insn_size;
-  new_field->last = -1;
-  return new_field;
-}
-
-static void
-dump_opcode_field(opcode_field *field, int indent, int levels)
-{
-  printf("(opcode_field*)%p\n", field);
-  if (levels && field != NULL) {
-    dumpf(indent, "(first %d)\n", field->first);
-    dumpf(indent, "(last %d)\n", field->last);
-    dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
-    dumpf(indent, "(parent ");
-    dump_opcode_field(field->parent, indent, levels-1);
-  }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_bits insn_bits;
-struct _insn_bits {
-  int is_expanded;
-  int value;
-  insn_field *field;
-  opcode_field *opcode;
-  insn_bits *last;
-};
-
-static insn_bits *
-insn_bits_new()
-{
-  insn_bits *new_bits = (insn_bits*)zmalloc(sizeof(insn_bits));
-  ASSERT(new_bits);
-  return new_bits;
-}
-
-
-static void
-dump_insn_bits(insn_bits *bits, int indent, int levels)
-{
-  printf("(insn_bits*)%p\n", bits);
-
-  if (levels && bits != NULL) {
-    dumpf(indent, "(value %d)\n", bits->value);
-    dumpf(indent, "(opcode ");
-    dump_opcode_field(bits->opcode, indent+1, 0);
-    dumpf(indent, " )\n");
-    dumpf(indent, "(field ");
-    dump_insn_field(bits->field, indent+1);
-    dumpf(indent, " )\n");
-    dumpf(indent, "(last ");
-    dump_insn_bits(bits->last, indent+1, levels-1);
-  }
-}
-
-
-/****************************************************************/
-
-
-typedef enum {
-  insn_format,
-  insn_form,
-  insn_flags,
-  insn_nmemonic,
-  insn_name,
-  insn_comment,
-  nr_insn_table_fields = file_table_max_fields,
-} insn_table_fields;
-char *insn_field_name[] = {
-  "format", "form", "flags", "nmemonic", "name", "comments"
-};
-
-typedef enum {
-  function_type = insn_format,
-  function_name = insn_name,
-  function_param = insn_comment,
-} function_table_fields;
-
-
-typedef struct _insn insn;
-struct _insn {
-  file_table_entry *file_entry;
-  insn_fields *fields;
-  insn *next;
-};
-
-typedef struct _insn_table insn_table;
-struct _insn_table {
-  int opcode_nr;
-  insn_bits *expanded_bits;
-  int nr_insn;
-  insn *insns;
-  insn *functions;
-  opcode_rules *opcode_rule;
-  opcode_field *opcode;
-  int nr_entries;
-  insn_table *entries;
-  insn_table *sibling;
-  insn_table *parent;
-};
-
-
-
-static insn *
-insn_new()
-{
-  insn *new_entry = ((insn*) zmalloc(sizeof(insn)));
-  ASSERT(new_entry != NULL);
-  return new_entry;
-}
-
-static insn_table *
-insn_table_new()
-{
-  insn_table *new_table = (insn_table*)zmalloc(sizeof(insn_table));
-  ASSERT(new_table != NULL);
-  return new_table;
-}
-
-
-static void
-insn_table_insert_function(insn_table *table,
-                          file_table_entry *file_entry)
-{
-  insn **ptr_to_cur_function = &table->functions;
-
-  /* create a new function */
-  insn *new_function = insn_new();
-  new_function->file_entry = file_entry;
-
-  /* append it to the end of the function list */
-  while (*ptr_to_cur_function != NULL) {
-    ptr_to_cur_function = &(*ptr_to_cur_function)->next;
-  }
-  *ptr_to_cur_function = new_function;
-}
-
-
-static void
-insn_table_insert_insn(insn_table *table,
-                      file_table_entry *file_entry,
-                      insn_fields *fields)
-{
-  insn **ptr_to_cur_insn = &table->insns;
-  insn *cur_insn = *ptr_to_cur_insn;
-
-  /* create a new instruction */
-  insn *new_insn = insn_new();
-  new_insn->file_entry = file_entry;
-  new_insn->fields = fields;
-
-  /* insert it according to the order of the fields */
-  while (cur_insn != NULL
-        && new_insn->fields->value >= cur_insn->fields->value) {
-    ptr_to_cur_insn = &cur_insn->next;
-    cur_insn = *ptr_to_cur_insn;
-  }
-
-  new_insn->next = cur_insn;
-  *ptr_to_cur_insn = new_insn;
-
-  table->nr_insn++;
-}
-
-
-static opcode_field *
-insn_table_find_opcode_field(insn *insns,
-                            opcode_rules *rule,
-                            int string_only)
-{
-  opcode_field *curr_opcode = opcode_field_new();
-  insn *entry;
-
-  ASSERT(rule->valid);
-
-  for (entry = insns; entry != NULL; entry = entry->next) {
-    insn_fields *fields = entry->fields;
-    opcode_field new_opcode;
-
-    /* find a start point for the opcode field */
-    new_opcode.first = rule->first;
-    while (new_opcode.first <= rule->last
-          && (!string_only
-              || insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule) != field_constant_string)
-          && (string_only
-              || !insn_field_is_constant(fields->bits[new_opcode.first],
-                                         rule)))
-      new_opcode.first = fields->bits[new_opcode.first]->last + 1;
-    ASSERT(new_opcode.first > rule->last
-          || (string_only
-              && insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule) == field_constant_string)
-          || (!string_only
-              && insn_field_is_constant(fields->bits[new_opcode.first],
-                                        rule)));
-  
-    /* find the end point for the opcode field */
-    new_opcode.last = rule->last;
-    while (new_opcode.last >= rule->first
-          && (!string_only
-              || insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule) != field_constant_string)
-          && (string_only
-              || !insn_field_is_constant(fields->bits[new_opcode.last],
-                                         rule)))
-      new_opcode.last = fields->bits[new_opcode.last]->first - 1;
-    ASSERT(new_opcode.last < rule->first
-          || (string_only
-              && insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule) == field_constant_string)
-          || (!string_only
-              && insn_field_is_constant(fields->bits[new_opcode.last],
-                                        rule)));
-
-    /* now see if our current opcode needs expanding */
-    if (new_opcode.first <= rule->last
-       && curr_opcode->first > new_opcode.first)
-      curr_opcode->first = new_opcode.first;
-    if (new_opcode.last >= rule->first
-       && curr_opcode->last < new_opcode.last)
-      curr_opcode->last = new_opcode.last;
-    
-  }
-
-  /* was any thing interesting found? */
-  if (curr_opcode->first > rule->last) {
-    ASSERT(curr_opcode->last < rule->first);
-    free(curr_opcode);
-    return NULL;
-  }
-  ASSERT(curr_opcode->last >= rule->first);
-  ASSERT(curr_opcode->first <= rule->last);
-
-  /* if something was found, check it includes the forced field range */
-  if (!string_only
-      && curr_opcode->first > rule->force_first) {
-    curr_opcode->first = rule->force_first;
-  }
-  if (!string_only
-      && curr_opcode->last < rule->force_last) {
-    curr_opcode->last = rule->force_last;
-  }
-  /* handle special case elminating any need to do shift after mask */
-  if (string_only
-      && rule->force_last == insn_size-1) {
-    curr_opcode->last = insn_size-1;
-  }
-
-  /* handle any special cases */
-  switch (rule->special_rule) {
-  case 0: /* let the above apply */
-    break;
-  case 1: /* expand a limited nr of bits, ignoring the rest */
-    curr_opcode->first = rule->force_first;
-    curr_opcode->last = rule->force_last;
-    break;
-  case 2: /* boolean field */
-    curr_opcode->is_boolean = 1;
-    break;
-  }
-
-  return curr_opcode;
-}
-
-
-static void
-insn_table_insert_expanded(insn_table *table,
-                          insn *old_insn,
-                          int new_opcode_nr,
-                          insn_bits *new_bits)
-{
-  insn_table **ptr_to_cur_entry = &table->entries;
-  insn_table *cur_entry = *ptr_to_cur_entry;
-
-  /* find the new table for this entry */
-  while (cur_entry != NULL
-        && cur_entry->opcode_nr < new_opcode_nr) {
-    ptr_to_cur_entry = &cur_entry->sibling;
-    cur_entry = *ptr_to_cur_entry;
-  }
-
-  if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
-    insn_table *new_entry = insn_table_new();
-    new_entry->opcode_nr = new_opcode_nr;
-    new_entry->expanded_bits = new_bits;
-    new_entry->opcode_rule = table->opcode_rule+1;
-    new_entry->sibling = cur_entry;
-    new_entry->parent = table;
-    *ptr_to_cur_entry = new_entry;
-    cur_entry = new_entry;
-    table->nr_entries++;
-  }
-  /* ASSERT new_bits == cur_entry bits */
-  ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
-  insn_table_insert_insn(cur_entry,
-                        old_insn->file_entry,
-                        old_insn->fields);
-}
-
-static void
-insn_table_expand_opcode(insn_table *table,
-                        insn *instruction,
-                        int field_nr,
-                        int opcode_nr,
-                        insn_bits *bits)
-{
-
-  if (field_nr > table->opcode->last) {
-    insn_table_insert_expanded(table, instruction, opcode_nr, bits);
-  }
-  else {
-    insn_field *field = instruction->fields->bits[field_nr];
-    if (field->is_int || field->is_slash) {
-      ASSERT(field->first >= table->opcode->first
-            && field->last <= table->opcode->last);
-      insn_table_expand_opcode(table, instruction, field->last+1,
-                              ((opcode_nr << field->width) + field->val_int),
-                              bits);
-    }
-    else {
-      int val;
-      int last_pos = ((field->last < table->opcode->last)
-                       ? field->last : table->opcode->last);
-      int first_pos = ((field->first > table->opcode->first)
-                        ? field->first : table->opcode->first);
-      int width = last_pos - first_pos + 1;
-      int last_val = (table->opcode->is_boolean
-                     ? 2 : (1 << width));
-      for (val = 0; val < last_val; val++) {
-       insn_bits *new_bits = insn_bits_new();
-       new_bits->field = field;
-       new_bits->value = val;
-       new_bits->last = bits;
-       new_bits->opcode = table->opcode;
-       insn_table_expand_opcode(table, instruction, last_pos+1,
-                                ((opcode_nr << width) | val),
-                                new_bits);
-      }
-    }
-  }
-}
-
-static void
-insn_table_insert_expanding(insn_table *table,
-                           insn *entry)
-{
-  insn_table_expand_opcode(table,
-                          entry,
-                          table->opcode->first,
-                          0,
-                          table->expanded_bits);
-}
-
-
-static void
-insn_table_expand_insns(insn_table *table)
-{
-
-  ASSERT(table->nr_insn >= 1);
-
-  /* determine a valid opcode */
-  while (table->opcode_rule->valid) {
-    /* specials only for single instructions */
-    if ((table->nr_insn > 1
-        && table->opcode_rule->special_mask == 0
-        && table->opcode_rule->special_rule == 0)
-       || (table->nr_insn == 1
-           && table->opcode_rule->special_mask != 0
-           && ((table->insns->fields->value
-                & table->opcode_rule->special_mask)
-               == table->opcode_rule->special_value))
-       || (idecode_expand_semantics
-           && table->opcode_rule->special_mask == 0
-           && table->opcode_rule->special_rule == 0))
-      table->opcode =
-       insn_table_find_opcode_field(table->insns,
-                                    table->opcode_rule,
-                                    table->nr_insn == 1/*string*/
-                                    );
-    if (table->opcode != NULL)
-      break;
-    table->opcode_rule++;
-  }
-
-  /* did we find anything */
-  if (table->opcode == NULL) {
-    return;
-  }
-  ASSERT(table->opcode != NULL);
-
-  /* back link what we found to its parent */
-  if (table->parent != NULL) {
-    ASSERT(table->parent->opcode != NULL);
-    table->opcode->parent = table->parent->opcode;
-  }
-
-  /* expand the raw instructions according to the opcode */
-  {
-    insn *entry;
-    for (entry = table->insns; entry != NULL; entry = entry->next) {
-      insn_table_insert_expanding(table, entry);
-    }
-  }
-
-  /* and do the same for the sub entries */
-  {
-    insn_table *entry;
-    for (entry = table->entries; entry != NULL; entry =  entry->sibling) {
-      insn_table_expand_insns(entry);
-    }
-  }
-}
-
-
-
-static insn_table *
-insn_table_load_insns(char *file_name)
-{
-  file_table *file = file_table_open(file_name);
-  insn_table *table = insn_table_new();
-  file_table_entry *file_entry;
-  table->opcode_rule = opcode_table;
-
-  while ((file_entry = file_table_read(file)) != NULL) {
-    if (it_is("function", file_entry->fields[insn_flags])
-       || it_is("internal", file_entry->fields[insn_flags])) {
-      insn_table_insert_function(table, file_entry);
-    }
-    else {
-      insn_fields *fields;
-      /* skip instructions that aren't relevant to the mode */
-      if ((it_is("64", file_entry->fields[insn_flags])
-          && WITH_TARGET_WORD_BITSIZE != 64)
-         || (it_is("32", file_entry->fields[insn_flags])
-             && WITH_TARGET_WORD_BITSIZE != 32)
-         || (it_is("f", file_entry->fields[insn_flags])
-             && WITH_FLOATING_POINT == SOFT_FLOATING_POINT))
-       continue;
-      /* create/insert the new instruction */
-      fields = parse_insn_format(file_entry, file_entry->fields[insn_format]);
-      insn_table_insert_insn(table, file_entry, fields);
-    }
-  }
-  return table;
-}
-
-
-static void
-dump_insn(insn *entry, int indent, int levels)
-{
-  printf("(insn*)%p\n", entry);
-
-  if (levels && entry != NULL) {
-
-    dumpf(indent, "(file_entry ");
-    dump_file_table_entry(entry->file_entry, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(fields ");
-    dump_insn_fields(entry->fields, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(next ");
-    dump_insn(entry->next, indent+1, levels-1);
-    dumpf(indent, " )\n");
-
-  }
-
-}
-
-
-static void
-dump_insn_table(insn_table *table,
-               int indent, int levels)
-{
-
-  printf("(insn_table*)%p\n", table);
-
-  if (levels && table != NULL) {
-    insn *entry;
-
-    dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
-
-    dumpf(indent, "(expanded_bits ");
-    dump_insn_bits(table->expanded_bits, indent+1, -1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
-
-    dumpf(indent, "(insns ");
-    dump_insn(table->insns, indent+1, table->nr_insn);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(opcode_rule ");
-    dump_opcode_rule(table->opcode_rule, indent+1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(opcode ");
-    dump_opcode_field(table->opcode, indent+1, 1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(nr_entries %d)\n", table->entries);
-    dumpf(indent, "(entries ");
-    dump_insn_table(table->entries, indent+1, table->nr_entries);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(sibling ", table->sibling);
-    dump_insn_table(table->sibling, indent+1, levels-1);
-    dumpf(indent, " )\n");
-
-    dumpf(indent, "(parent ", table->parent);
-    dump_insn_table(table->parent, indent+1, 0);
-    dumpf(indent, " )\n");
-
-  }
-}
-
-
-/****************************************************************/
-
-
-static void
-lf_print_copyleft(lf *file)
-{
-  lf_putstr(file, "\
-/* This file is part of psim (model of the PowerPC(tm) architecture)
-
-   Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License
-   as published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-   This library 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
-   Library General Public License for more details.
-   You should have received a copy of the GNU Library General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   --
-
-   PowerPC is a trademark of International Business Machines Corporation.
-
-   --
-
-   This file was generated by the program gen */
-");
-}
-
-
-static void
-lf_print_c_line_nr(lf *file, file_table_entry *entry)
-{
-#if WITH_LINE_NUMBERS
-  lf_indent_suppress(file);
-  lf_putstr(file, "#line ");
-  lf_putint(file, entry->line_nr);
-  lf_putstr(file, " \"");
-  lf_putstr(file, entry->file_name);
-  lf_putstr(file, "\"\n");
-#endif
-}
-
-
-static void
-lf_print_c_code(lf *file, char *code)
-{
-  char *chp = code;
-  int in_bit_field = 0;
-  while (*chp != '\0') {
-    if (*chp == '\t')
-      chp++;
-    if (*chp == '#')
-      lf_indent_suppress(file);
-    while (*chp != '\0' && *chp != '\n') {
-      if (chp[0] == '{' && !isspace(chp[1])) {
-       in_bit_field = 1;
-       lf_putchr(file, '_');
-      }
-      else if (in_bit_field && chp[0] == ':') {
-       lf_putchr(file, '_');
-      }
-      else if (in_bit_field && *chp == '}') {
-       lf_putchr(file, '_');
-       in_bit_field = 0;
-      }
-      else {
-       lf_putchr(file, *chp);
-      }
-      chp++;
-    }
-    if (in_bit_field)
-      error("bit field paren miss match some where\n");
-    if (*chp == '\n') {
-      lf_putchr(file, '\n');
-      chp++;
-    }
-  }
-  lf_putchr(file, '\n');
-}
-
-
-static void
-lf_print_binary(lf *file, int decimal, int width)
-{
-  int bit;
-  ASSERT(width > 0);
-
-  for (bit = 1 << (width-1); bit != 0; bit >>= 1) {
-    if (decimal & bit)
-      lf_putchr(file, '1');
-    else
-      lf_putchr(file, '0');
-  }
-
-}
-
-
-static void
-lf_print_insn_bits(lf *file, insn_bits *bits)
-{
-  if (bits == NULL)
-    return;
-  lf_print_insn_bits(file, bits->last);
-  lf_putchr(file, '_');
-  lf_putstr(file, bits->field->val_string);
-  if (!bits->opcode->is_boolean || bits->value == 0) {
-    if (bits->opcode->last < bits->field->last)
-      lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
-    else
-      lf_putint(file, bits->value);
-  }
-}
-
-static void
-lf_print_opcodes(lf *file,
-                insn_table *table)
-{
-  if (table != NULL) {
-    while (1) {
-      lf_printf(file, "_%d_%d",
-               table->opcode->first,
-               table->opcode->last);
-      if (table->parent == NULL) break;
-      lf_printf(file, "__%d", table->opcode_nr);
-      table = table->parent;
-    }
-  }
-}
-
-static void
-lf_print_table_name(lf *file,
-                   insn_table *table)
-{
-  lf_printf(file, "idecode_table");
-  lf_print_opcodes(file, table);
-}
-
-
-
-typedef enum {
-  function_name_prefix_semantics,
-  function_name_prefix_idecode,
-  function_name_prefix_none
-} lf_function_name_prefixes;
-
-static void
-lf_print_function_name(lf *file,
-                      char *basename,
-                      insn_bits *expanded_bits,
-                      lf_function_name_prefixes prefix)
-{
-
-  /* the prefix */
-  switch (prefix) {
-  case function_name_prefix_semantics:
-    lf_putstr(file, "semantic_");
-    break;
-  case function_name_prefix_idecode:
-    lf_printf(file, "idecode_");
-    break;
-  default:
-    break;
-  }
-
-  /* the function name */
-  {
-    char *pos;
-    for (pos = basename;
-        *pos != '\0';
-        pos++) {
-      switch (*pos) {
-      case '/':
-      case '-':
-       break;
-      case ' ':
-       lf_putchr(file, '_');
-       break;
-      default:
-       lf_putchr(file, *pos);
-       break;
-      }
-    }
-  }
-
-  /* the suffix */
-  if (idecode_expand_semantics)
-    lf_print_insn_bits(file, expanded_bits);
-}
-
-
-static void
-lf_print_idecode_table(lf *file,
-                      insn_table *entry)
-{
-  int can_assume_leaf;
-  int rule;
-
-  /* have a look at the rule table, if all table rules follow all
-     switch rules, I can assume that all end points are leaves */
-  rule = 0;
-  while (opcode_table[rule].valid
-        && opcode_table[rule].use_switch)
-    rule++;
-  while (opcode_table[rule].valid
-        && !opcode_table[rule].use_switch
-        && !opcode_table[rule].special_rule)
-    rule++;
-  can_assume_leaf = !opcode_table[rule].valid;
-
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  {
-    lf_printf(file, "idecode_table_entry *table = ");
-    lf_print_table_name(file, entry);
-    lf_printf(file, ";\n");
-    lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
-             entry->opcode->first, entry->opcode->last);
-    lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
-    lf_printf(file, "while (1) {\n");
-    lf_indent(file, +2);
-    {
-      lf_printf(file, "while (table_entry->mask != 0) {\n");
-      lf_indent(file, +2);
-      {
-       lf_printf(file, "table = ((idecode_table_entry*)\n");
-       lf_printf(file, "         table_entry->function_or_table);\n");
-       lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
-       lf_printf(file, "          >> table_entry->shift);\n");
-       lf_printf(file, "table_entry = table + opcode;\n");
-      }
-      lf_indent(file, -2);
-      lf_printf(file, "}\n");
-      if (!idecode_cache && can_assume_leaf) {
-       lf_printf(file, "return (((idecode_semantic*)\n");
-       lf_printf(file, "         table_entry->function_or_table)\n");
-       lf_printf(file, "        (%s));\n", insn_actual);
-      }
-      else if (!idecode_cache && !can_assume_leaf) {
-       lf_printf(file, "if (table_entry->shift == 0)");
-       lf_printf(file, "  return (((idecode_semantic*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", insn_actual);
-      }
-      else {
-       lf_printf(file, "if (table_entry->shift == 0)\n");
-       lf_printf(file, "  return (((idecode_crack*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", cache_idecode_actual);
-      }
-      if (!can_assume_leaf) {
-       lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n");
-       lf_printf(file, "table = ((idecode_table_entry*)\n");
-       lf_printf(file, "         table_entry->function_or_table);\n");
-       lf_printf(file, "table_entry = table + opcode;\n");
-      }
-    }
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-  }
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_my_prefix(lf *file,
-                  file_table_entry *file_entry)
-{
-  lf_printf(file, "const char *const my_prefix = \n");
-  lf_printf(file, "  \"%s:%s:%d:cache\";\n",
-           file_entry->file_name,
-           file_entry->fields[insn_name],
-           file_entry->line_nr);
-}
-
-
-static void
-lf_print_ptrace(lf *file)
-{
-  lf_printf(file, "\n");
-  lf_putstr(file, "ITRACE(trace_semantics, (\"cia=0x%x\\n\", cia));\n");
-}
-
-
-/****************************************************************/
-
-typedef void leaf_handler
-(insn_table *entry,
- void *data,
- int depth);
-typedef void padding_handler
-(insn_table *table,
- void *data,
- int depth,
- int opcode_nr);
-
-
-static void
-insn_table_traverse_tree(insn_table *table,
-                        void *data,
-                        int depth,
-                        leaf_handler *start,
-                        leaf_handler *leaf,
-                        leaf_handler *end,
-                        padding_handler *padding)
-{
-  insn_table *entry;
-  int entry_nr;
-  
-  ASSERT(table != NULL
-        && table->opcode != NULL
-        && table->nr_entries > 0
-        && table->entries != 0);
-
-  if (start != NULL && depth >= 0)
-    start(table, data, depth);
-
-  for (entry_nr = 0, entry = table->entries;
-       entry_nr < (table->opcode->is_boolean
-                  ? 2
-                  : (1 << (table->opcode->last - table->opcode->first + 1)));
-       entry_nr ++) {
-    if (entry == NULL
-       || (!table->opcode->is_boolean
-           && entry_nr < entry->opcode_nr)) {
-      if (padding != NULL && depth >= 0)
-       padding(table, data, depth, entry_nr);
-    }
-    else {
-      ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
-                              || table->opcode->is_boolean));
-      if (entry->opcode != NULL && depth != 0) {
-       insn_table_traverse_tree(entry, data, depth+1,
-                                start, leaf, end, padding);
-      }
-      else if (depth >= 0) {
-       if (leaf != NULL)
-         leaf(entry, data, depth);
-      }
-      entry = entry->sibling;
-    }
-  }
-  if (end != NULL && depth >= 0)
-    end(table, data, depth);
-}
-
-
-typedef void function_handler
-(insn_table *table,
- void *data,
- file_table_entry *function);
-
-static void
-insn_table_traverse_function(insn_table *table,
-                            void *data,
-                            function_handler *leaf)
-{
-  insn *function;
-  for (function = table->functions;
-       function != NULL;
-       function = function->next) {
-    leaf(table, data, function->file_entry);
-  }
-}
-
-
-typedef void insn_handler
-(insn_table *table,
- void *data,
- insn *instruction);
-
-static void
-insn_table_traverse_insn(insn_table *table,
-                        void *data,
-                        insn_handler *leaf)
-{
-  insn *instruction;
-  for (instruction = table->insns;
-       instruction != NULL;
-       instruction = instruction->next) {
-    leaf(table, data, instruction);
-  }
-}
-
-
-static void
-update_depth(insn_table *entry,
-            void *data,
-            int depth)
-{
-  int *max_depth = (int*)data;
-  if (*max_depth < depth)
-    *max_depth = depth;
-}
-
-
-static int
-insn_table_depth(insn_table *table)
-{
-  int depth = 0;
-  insn_table_traverse_tree(table,
-                          &depth,
-                          1,
-                          NULL, /*start*/
-                          update_depth,
-                          NULL, /*end*/
-                          NULL); /*padding*/
-  return depth;
-}
-
-
-/****************************************************************/
-
-static void
-dump_traverse_start(insn_table *table,
-                   void *data,
-                   int depth)
-{
-  dumpf(depth*2, "(%d\n", table->opcode_nr);
-}
-
-static void
-dump_traverse_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  ASSERT(entry->nr_entries == 0
-        && entry->nr_insn == 1
-        && entry->opcode == NULL);
-  dumpf(depth*2, ".%d %s\n", entry->opcode_nr,
-       entry->insns->file_entry->fields[insn_format]);
-}
-
-static void
-dump_traverse_end(insn_table *table,
-                 void *data,
-                 int depth)
-{
-  dumpf(depth*2, ")\n");
-}
-
-static void
-dump_traverse_padding(insn_table *table,
-                     void *data,
-                     int depth,
-                     int opcode_nr)
-{
-  dumpf(depth*2, ".<%d>\n", opcode_nr);
-}
-
-
-static void
-dump_traverse(insn_table *table)
-{
-  insn_table_traverse_tree(table, NULL, 1,
-                          dump_traverse_start,
-                          dump_traverse_leaf,
-                          dump_traverse_end,
-                          dump_traverse_padding);
-}
-
-
-/****************************************************************/
-
-
-static void
-semantics_h_print_function(lf *file,
-                          char *basename,
-                          insn_bits *expanded_bits)
-{
-  lf_printf(file, "\n");
-  lf_printf(file, "INLINE_SEMANTICS unsigned_word ");
-  lf_print_function_name(file,
-                        basename,
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, "\n(%s);\n",
-           (idecode_cache ? cache_insn_formal : insn_formal));
-}
-
-
-static void
-semantics_h_leaf(insn_table *entry,
-                void *data,
-                int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1);
-  semantics_h_print_function(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits);
-}
-
-static void
-semantics_h_insn(insn_table *entry,
-                void *data,
-                insn *instruction)
-{
-  lf *file = (lf*)data;
-  semantics_h_print_function(file,
-                            instruction->file_entry->fields[insn_name],
-                            NULL);
-}
-
-static void
-semantics_h_function(insn_table *entry,
-                    void *data,
-                    file_table_entry *function)
-{
-  lf *file = (lf*)data;
-  if (function->fields[function_type] == NULL
-      || function->fields[function_type][0] == '\0') {
-    semantics_h_print_function(file,
-                              function->fields[function_name],
-                              NULL);
-  }
-  else {
-    lf_printf(file, "\n");
-    lf_printf(file, "INLINE_SEMANTICS %s %s\n(%s);\n",
-             function->fields[function_type],
-             function->fields[function_name],
-             function->fields[function_param]);
-  }
-}
-
-
-static void 
-gen_semantics_h(insn_table *table, lf *file)
-{
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SEMANTICS_H_\n");
-  lf_printf(file, "#define _SEMANTICS_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_SEMANTICS\n");
-  lf_printf(file, "#define INLINE_SEMANTICS\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-
-  /* output a declaration for all functions */
-  insn_table_traverse_function(table,
-                              file,
-                              semantics_h_function);
-
-  /* output a declaration for all instructions */
-  if (idecode_expand_semantics)
-    insn_table_traverse_tree(table,
-                            file,
-                            1,
-                            NULL, /* start */
-                            semantics_h_leaf, /* leaf */
-                            NULL, /* end */
-                            NULL); /* padding */
-  else
-    insn_table_traverse_insn(table,
-                            file,
-                            semantics_h_insn);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SEMANTICS_H_ */\n");
-
-}
-
-/****************************************************************/
-
-typedef struct _icache_tree icache_tree;
-struct _icache_tree {
-  char *name;
-  icache_tree *next;
-  icache_tree *children;
-};
-
-static icache_tree *
-icache_tree_new()
-{
-  icache_tree *new_tree = (icache_tree*)zmalloc(sizeof(icache_tree));
-  ASSERT(new_tree != NULL);
-  return new_tree;
-}
-
-static icache_tree *
-icache_tree_insert(icache_tree *tree,
-                  char *name)
-{
-  icache_tree *new_tree;
-  /* find it */
-  icache_tree **ptr_to_cur_tree = &tree->children;
-  icache_tree *cur_tree = *ptr_to_cur_tree;
-  while (cur_tree != NULL
-        && strcmp(cur_tree->name, name) < 0) {
-    ptr_to_cur_tree = &cur_tree->next;
-    cur_tree = *ptr_to_cur_tree;
-  }
-  ASSERT(cur_tree == NULL
-        || strcmp(cur_tree->name, name) >= 0);
-  /* already in the tree */
-  if (cur_tree != NULL
-      && strcmp(cur_tree->name, name) == 0)
-    return cur_tree;
-  /* missing, insert it */
-  ASSERT(cur_tree == NULL
-        || strcmp(cur_tree->name, name) > 0);
-  new_tree = icache_tree_new();
-  new_tree->name = name;
-  new_tree->next = cur_tree;
-  *ptr_to_cur_tree = new_tree;
-  return new_tree;
-}
-
-
-static icache_tree *
-insn_table_cache_fields(insn_table *table)
-{
-  icache_tree *tree = icache_tree_new();
-  insn *instruction;
-  for (instruction = table->insns;
-       instruction != NULL;
-       instruction = instruction->next) {
-    insn_field *field;
-    icache_tree *form =
-      icache_tree_insert(tree,
-                        instruction->file_entry->fields[insn_form]);
-    for (field = instruction->fields->first;
-        field != NULL;
-        field = field->next) {
-      if (field->is_string)
-       icache_tree_insert(form, field->val_string);
-    }
-  }
-  return tree;
-}
-
-
-
-static void
-gen_icache_h(icache_tree *tree,
-            lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _ICACHE_H_\n");
-  lf_printf(file, "#define _ICACHE_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_ICACHE\n");
-  lf_printf(file, "#define INLINE_ICACHE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-
-  /* create an instruction cache if being used */
-  if (idecode_cache) {
-    icache_tree *form;
-    lf_printf(file, "typedef struct _idecode_cache {\n");
-    lf_printf(file, "  unsigned_word address;\n");
-    lf_printf(file, "  void *semantic;\n");
-    lf_printf(file, "  union {\n");
-    for (form = tree->children;
-        form != NULL;
-        form = form->next) {
-      icache_tree *field;
-      lf_printf(file, "    struct {\n");
-      for (field = form->children;
-          field != NULL;
-          field = field->next) {
-       extraction_rules *rule;
-       int found_rule = 0;
-       for (rule = cachable_values;
-            rule->valid;
-            rule++) {
-         if (strcmp(field->name, rule->old_name) == 0) {
-           found_rule = 1;
-           if (rule->new_name != NULL)
-             lf_printf(file, "      %s %s; /* %s */\n",
-                       rule->type == NULL ? "unsigned" : rule->type,
-                       rule->new_name, rule->old_name);
-         }
-       }
-       if (!found_rule)
-         lf_printf(file, "      unsigned %s;\n", field->name);
-      }
-      lf_printf(file, "    } %s;\n", form->name);
-    }
-    lf_printf(file, "  } crack;\n");
-    lf_printf(file, "} idecode_cache;\n");
-  }
-  else {
-    /* alernativly, since no cache, #define the fields to be
-       extractions from the instruction variable */
-    extraction_rules *rule;
-    lf_printf(file, "\n");
-    for (rule = cachable_values;
-        rule->valid;
-        rule++) {
-      if (rule->expression != NULL)
-       lf_printf(file, "#define %s %s\n",
-                 rule->new_name, rule->expression);
-    }
-  }
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _ICACHE_H_ */\n");
-}
-
-
-
-
-/****************************************************************/
-
-
-static void
-lf_print_c_extraction(lf *file,
-                     insn *instruction,
-                     char *field_name,
-                     char *field_type,
-                     char *field_expression,
-                     insn_field *cur_field,
-                     insn_bits *bits,
-                     int get_value_from_cache,
-                     int put_value_in_cache)
-{
-  ASSERT(field_name != NULL);
-  if (bits != NULL
-      && (!bits->opcode->is_boolean || bits->value == 0)
-      && strcmp(field_name, cur_field->val_string) == 0) {
-    ASSERT(bits->field == cur_field);
-    ASSERT(field_type == NULL);
-    lf_print_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "const unsigned %s = ",
-             field_name);
-    if (bits->opcode->last < bits->field->last)
-      lf_printf(file, "%d;\n",
-               bits->value << (bits->field->last - bits->opcode->last));
-    else
-      lf_printf(file, "%d;\n", bits->value);
-  }
-  else {
-    /* put the field in the local variable */
-    lf_print_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "%s const %s = ",
-             field_type == NULL ? "unsigned" : field_type,
-             field_name);
-    /* getting it from the cache */
-    if (get_value_from_cache || put_value_in_cache) {
-      lf_printf(file, "cache_entry->crack.%s.%s",
-               instruction->file_entry->fields[insn_form],
-               field_name);
-      if (put_value_in_cache) /* also put it in the cache? */
-       lf_printf(file, " = ");
-    }
-    if (!get_value_from_cache) {
-      if (strcmp(field_name, cur_field->val_string) == 0)
-       lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
-                 cur_field->first, cur_field->last);
-      else if (field_expression != NULL)
-       lf_printf(file, "%s", field_expression);
-      else
-       lf_printf(file, "eval_%s", field_name);
-    }
-    lf_printf(file, ";\n");
-  }
-}
-
-
-static void
-lf_print_c_extractions(lf *file,
-                      insn *instruction,
-                      insn_bits *expanded_bits,
-                      int get_value_from_cache,
-                      int put_value_in_cache)
-{
-  insn_field *cur_field;
-
-  /* extract instruction fields */
-  lf_printf(file, "/* extraction: %s */\n",
-           instruction->file_entry->fields[insn_format]);
-
-  for (cur_field = instruction->fields->first;
-       cur_field->first < insn_size;
-       cur_field = cur_field->next) {
-    if (cur_field->is_string) {
-      insn_bits *bits;
-      int found_rule = 0;
-      /* find any corresponding value */
-      for (bits = expanded_bits;
-          bits != NULL;
-          bits = bits->last) {
-       if (bits->field == cur_field)
-         break;
-      }
-      /* try the cache rule table for what to do */
-      if (get_value_from_cache || put_value_in_cache) {      
-       extraction_rules *field_rule;
-       for (field_rule = cachable_values;
-            field_rule->valid;
-            field_rule++) {
-         if (strcmp(cur_field->val_string, field_rule->old_name) == 0) {
-           found_rule = 1;
-           if (field_rule->valid > 1 && put_value_in_cache)
-             lf_print_c_extraction(file,
-                                   instruction,
-                                   field_rule->new_name,
-                                   field_rule->type,
-                                   field_rule->expression,
-                                   cur_field,
-                                   bits,
-                                   0,
-                                   0);
-           else if (field_rule->valid == 1)
-             lf_print_c_extraction(file,
-                                   instruction,
-                                   field_rule->new_name,
-                                   field_rule->type,
-                                   field_rule->expression,
-                                   cur_field,
-                                   bits,
-                                   get_value_from_cache,
-                                   put_value_in_cache);
-         }
-       }
-      }
-      if (found_rule == 0)
-       lf_print_c_extraction(file,
-                             instruction,
-                             cur_field->val_string,
-                             0,
-                             0,
-                             cur_field,
-                             bits,
-                             get_value_from_cache,
-                             put_value_in_cache);
-      /* if any (XXX == 0), output a corresponding test */
-      if (instruction->file_entry->annex != NULL) {
-       char *field_name = cur_field->val_string;
-       char *is_0_ptr = instruction->file_entry->annex;
-       int field_len = strlen(field_name);
-       if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
-         is_0_ptr += field_len;
-         while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
-           if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
-               && !isalpha(is_0_ptr[ - field_len - 1])) {
-             lf_print_c_line_nr(file, instruction->file_entry);
-             lf_printf(file, "const unsigned %s_is_0 = (", field_name);
-             if (bits != NULL)
-               lf_printf(file, "%d", bits->value);
-             else
-               lf_printf(file, "%s", field_name);
-             lf_printf(file, " == 0);\n");
-             break;
-           }
-           is_0_ptr += strlen("_is_0");
-         }
-       }
-      }
-      /* any thing else ... */
-    }
-  }
-  lf_print_file_line_nr(file);
-}
-
-
-static void
-lf_print_idecode_illegal(lf *file)
-{
-  if (idecode_cache)
-    lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
-  else
-    lf_printf(file, "return semantic_illegal(%s);\n", insn_actual);
-}
-
-
-static void
-lf_print_idecode_floating_point_unavailable(lf *file)
-{
-  if (idecode_cache)
-    lf_printf(file, "return idecode_floating_point_unavailable(%s);\n",
-             cache_idecode_actual);
-  else
-    lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
-             insn_actual);
-}
-
-
-/* Output code to do any final checks on the decoded instruction.
-   This includes things like verifying any on decoded fields have the
-   correct value and checking that (for floating point) floating point
-   hardware isn't disabled */
-
-static void
-lf_print_c_validate(lf *file,
-                   insn *instruction,
-                   opcode_field *opcodes)
-{
-  /* Validate: unchecked instruction fields
-
-     If any constant fields in the instruction were not checked by the
-     idecode tables, output code to check that they have the correct
-     value here */
-  { 
-    unsigned check_mask = 0;
-    unsigned check_val = 0;
-    insn_field *field;
-    opcode_field *opcode;
-
-    /* form check_mask/check_val containing what needs to be checked
-       in the instruction */
-    for (field = instruction->fields->first;
-        field->first < insn_size;
-        field = field->next) {
-
-      check_mask <<= field->width;
-      check_val <<= field->width;
-
-      /* is it a constant that could need validating? */
-      if (!field->is_int && !field->is_slash)
-       continue;
-
-      /* has it been checked by a table? */
-      for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
-       if (field->first >= opcode->first
-           && field->last <= opcode->last)
-         break;
-      }
-      if (opcode != NULL)
-       continue;
-
-      check_mask |= (1 << field->width)-1;
-      check_val |= field->val_int;
-    }
-
-    /* if any bits not checked by opcode tables, output code to check them */
-    if (check_mask) {
-      lf_printf(file, "\n");
-      lf_printf(file, "/* validate: %s */\n",
-               instruction->file_entry->fields[insn_format]);
-      lf_printf(file, "if ((instruction & 0x%x) != 0x%x)\n",
-               check_mask, check_val);
-      lf_indent(file, +2);
-      lf_print_idecode_illegal(file);
-      lf_indent(file, -2);
-    }
-  }
-
-  /* Validate floating point hardware
-
-     If the simulator is being built with out floating point hardware
-     (different to it being disabled in the MSR) then floating point
-     instructions are invalid */
-  {
-    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
-      lf_printf(file, "\n");
-      lf_printf(file, "/* Validate: FP hardware exists */\n");
-      lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
-      lf_indent(file, +2);
-      lf_print_idecode_illegal(file);
-      lf_indent(file, -2);
-    }
-  }
-
-  /* Validate: Floating Point available
-
-     If floating point is not available, we enter a floating point
-     unavailable interrupt into the cache instead of the instruction
-     proper.
-
-     The PowerPC spec requires a CSI after MSR[FP] is changed and when
-     ever a CSI occures we flush the instruction cache. */
-
-  {
-    if (it_is("f", instruction->file_entry->fields[insn_flags])) {
-      lf_printf(file, "\n");
-      lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
-      lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
-      lf_indent(file, +2);
-      lf_print_idecode_floating_point_unavailable(file);
-      lf_indent(file, -2);
-    }
-  }
-}
-
-
-static void
-lf_print_c_cracker(lf *file,
-                  insn *instruction,
-                  insn_bits *expanded_bits,
-                  opcode_field *opcodes)
-{
-
-  /* function header */
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-
-  lf_print_my_prefix(file,
-                    instruction->file_entry);
-
-  lf_print_ptrace(file);
-
-  lf_print_c_validate(file, instruction, opcodes);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  lf_print_c_extractions(file,
-                        instruction,
-                        expanded_bits,
-                        0/*get_value_from_cache*/,
-                        1/*put_value_in_cache*/);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-
-  /* return the function propper (main sorts this one out) */
-  lf_printf(file, "\n");
-  lf_printf(file, "/* semantic routine */\n");
-  lf_print_c_line_nr(file, instruction->file_entry);
-  lf_printf(file, "return ");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, ";\n");
-
-  lf_print_file_line_nr(file);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_c_semantic(lf *file,
-                   insn *instruction,
-                   insn_bits *expanded_bits,
-                   opcode_field *opcodes)
-{
-
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-
-  lf_print_my_prefix(file,
-                    instruction->file_entry);
-  lf_putstr(file, insn_local);
-  lf_printf(file, "\n");
-
-  lf_printf(file, "\n");
-  lf_print_c_extractions(file,
-                        instruction,
-                        expanded_bits,
-                        idecode_cache/*get_value_from_cache*/,
-                        0/*put_value_in_cache*/);
-
-  lf_print_ptrace(file);
-
-  /* validate the instruction, if a cache this has already been done */
-  if (!idecode_cache)
-    lf_print_c_validate(file, instruction, opcodes);
-
-  /* generate the code (or at least something */
-  if (instruction->file_entry->annex != NULL) {
-    /* true code */
-    lf_printf(file, "\n");
-    lf_print_c_line_nr(file, instruction->file_entry);
-    lf_printf(file, "{\n");
-    lf_indent(file, +2);
-    lf_print_c_code(file, instruction->file_entry->annex);
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-    lf_print_file_line_nr(file);
-  }
-  else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
-    lf_print_file_line_nr(file);
-  }
-  else if (it_is("f", instruction->file_entry->fields[insn_flags])) {
-    /* unimplemented floating point instruction - call for assistance */
-    lf_printf(file, "\n");
-    lf_printf(file, "/* unimplemented floating point instruction - call for assistance */\n");
-    lf_print_c_line_nr(file, instruction->file_entry);
-    lf_putstr(file, "floating_point_assist_interrupt(processor, cia);\n");
-    lf_print_file_line_nr(file);
-  }
-  else {
-    /* abort so it is implemented now */
-    lf_print_c_line_nr(file, instruction->file_entry);
-    lf_putstr(file, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
-    lf_print_file_line_nr(file);
-    lf_printf(file, "\n");
-  }
-
-  /* the function footer */
-  lf_printf(file, "return nia;\n");
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-static void
-lf_print_c_semantic_function_header(lf *file,
-                                   char *basename,
-                                   insn_bits *expanded_bits)
-{
-  lf_printf(file, "\n");
-  lf_printf(file, "INLINE_SEMANTICS unsigned_word\n");
-  lf_print_function_name(file,
-                        basename,
-                        expanded_bits,
-                        function_name_prefix_semantics);
-  lf_printf(file, "\n(%s)\n",
-           (idecode_cache ? cache_insn_formal : insn_formal));
-}
-
-static void
-lf_print_c_semantic_function(lf *file,
-                            insn *instruction,
-                            insn_bits *expanded_bits,
-                            opcode_field *opcodes)
-{
-
-  /* build the semantic routine to execute the instruction */
-  lf_print_c_semantic_function_header(file,
-                                     instruction->file_entry->fields[insn_name],
-                                     expanded_bits);
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  lf_printf(file, "cpu_increment_number_of_insns (processor);\n");
-
-  lf_print_c_semantic(file,
-                     instruction,
-                     expanded_bits,
-                     opcodes);
-
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-}
-
-
-static void
-semantics_c_leaf(insn_table *entry,
-                void *data,
-                int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1
-        && entry->opcode == NULL
-        && entry->parent != NULL
-        && entry->parent->opcode != NULL);
-  lf_print_c_semantic_function(file,
-                              entry->insns,
-                              entry->expanded_bits,
-                              entry->parent->opcode);
-}
-
-static void
-semantics_c_insn(insn_table *table,
-                void *data,
-                insn *instruction)
-{
-  lf *file = (lf*)data;
-  lf_print_c_semantic_function(file, instruction,
-                              NULL, NULL);
-}
-
-static void
-semantics_c_function(insn_table *table,
-                    void *data,
-                    file_table_entry *function)
-{
-  lf *file = (lf*)data;
-  if (function->fields[function_type] == NULL
-      || function->fields[function_type][0] == '\0') {
-    lf_print_c_semantic_function_header(file,
-                                       function->fields[function_name],
-                                       NULL);
-  }
-  else {
-    lf_printf(file, "\n");
-    lf_printf(file, "INLINE_SEMANTICS %s\n%s(%s)\n",
-             function->fields[function_type],
-             function->fields[function_name],
-             function->fields[function_param]);
-  }
-  lf_print_c_line_nr(file, function);
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  lf_print_c_code(file, function->annex);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-  lf_print_file_line_nr(file);
-}
-
-
-
-static void 
-gen_semantics_c(insn_table *table, lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SEMANTICS_C_\n");
-  lf_printf(file, "#define _SEMANTICS_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_SEMANTICS\n");
-  lf_printf(file, "#define STATIC_INLINE_SEMANTICS STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"cpu.h\"\n");
-  lf_printf(file, "#include \"idecode.h\"\n");
-  lf_printf(file, "#include \"semantics.h\"\n");
-  lf_printf(file, "\n");
-
-  /* output a definition (c-code) for all functions */
-  insn_table_traverse_function(table,
-                              file,
-                              semantics_c_function);
-
-  /* output a definition (c-code) for all instructions */
-  if (idecode_expand_semantics)
-    insn_table_traverse_tree(table,
-                            file,
-                            1,
-                            NULL, /* start */
-                            semantics_c_leaf,
-                            NULL, /* end */
-                            NULL); /* padding */
-  else
-    insn_table_traverse_insn(table,
-                            file,
-                            semantics_c_insn);
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
-}
-
-
-/****************************************************************/
-
-static void
-gen_idecode_h(insn_table *table, lf *file)
-{
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _IDECODE_H_\n");
-  lf_printf(file, "#define _IDECODE_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_IDECODE\n");
-  lf_printf(file, "#define INLINE_IDECODE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"idecode_expression.h\"\n");
-  lf_printf(file, "#include \"idecode_fields.h\"\n");
-  lf_printf(file, "#include \"idecode_branch.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"icache.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
-           (idecode_cache ? cache_insn_formal : insn_formal));
-  lf_printf(file, "\n");
-  if (idecode_cache)
-    lf_printf(file, "INLINE_IDECODE idecode_semantic *idecode\n(%s);\n",
-             cache_idecode_formal);
-  else
-    lf_printf(file, "INLINE_IDECODE unsigned_word idecode_issue\n(%s);\n",
-             insn_formal);
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _IDECODE_H_ */\n");
-}
-
-
-/****************************************************************/
-
-
-static void
-idecode_table_start(insn_table *table,
-                   void *data,
-                   int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  /* start of the table */
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "\n");
-    lf_printf(file, "static idecode_table_entry ");
-    lf_print_table_name(file, table);
-    lf_printf(file, "[] = {\n");
-  }
-}
-
-static void
-idecode_table_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->parent != NULL);
-  ASSERT(depth == 0);
-
-  /* add an entry to the table */
-  if (!entry->parent->opcode_rule->use_switch) {
-    if (entry->opcode == NULL) {
-      /* table leaf entry */
-      lf_printf(file, "  /*%d*/ { 0, 0, ", entry->opcode_nr);
-      lf_print_function_name(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits,
-                            (idecode_cache
-                             ? function_name_prefix_idecode
-                             : function_name_prefix_semantics));
-      lf_printf(file, " },\n");
-    }
-    else if (entry->opcode_rule->use_switch) {
-      /* table calling switch statement */
-      lf_printf(file, "  /*%d*/ { -1, 0, ",
-               entry->opcode_nr);
-      lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
-    }
-    else {
-      /* table `calling' another table */
-      lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
-      if (entry->opcode->is_boolean)
-       lf_printf(file, "MASK32(%d,%d), 0, ",
-                 entry->opcode->first, entry->opcode->last);
-      else
-       lf_printf(file, "%d, MASK32(%d,%d), ",
-                 insn_size - entry->opcode->last - 1,
-                 entry->opcode->first, entry->opcode->last);
-      lf_print_table_name(file, entry);
-      lf_printf(file, " },\n");
-    }
-  }
-}
-
-static void
-idecode_table_end(insn_table *table,
-                 void *data,
-                 int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "};\n");
-  }
-}
-
-static void
-idecode_table_padding(insn_table *table,
-                     void *data,
-                     int depth,
-                     int opcode_nr)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-
-  if (!table->opcode_rule->use_switch) {
-    lf_printf(file, "  /*%d*/ { 0, 0, %s_illegal },\n",
-             opcode_nr, (idecode_cache ? "idecode" : "semantic"));
-  }
-}
-
-
-/****************************************************************/
-
-
-void lf_print_idecode_switch
-(lf *file, 
- insn_table *table);
-
-
-static void
-idecode_switch_start(insn_table *table,
-               void *data,
-               int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
-
-  lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
-           table->opcode->first, table->opcode->last);
-}
-
-
-static void
-idecode_switch_leaf(insn_table *entry,
-                   void *data,
-                   int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->parent != NULL);
-  ASSERT(depth == 0);
-  ASSERT(entry->parent->opcode_rule->use_switch);
-
-  lf_printf(file, "case %d:\n", entry->opcode_nr);
-  lf_indent(file, +2);
-  {
-    if (entry->opcode == NULL) {
-      /* switch calling leaf */
-      lf_printf(file, "return ");
-      lf_print_function_name(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits,
-                            (idecode_cache
-                             ? function_name_prefix_idecode
-                             : function_name_prefix_semantics));
-      if (idecode_cache)
-       lf_printf(file, "(%s);\n", cache_idecode_actual);
-      else
-       lf_printf(file, "(%s);\n", insn_actual);
-    }
-    else if (entry->opcode_rule->use_switch) {
-      /* switch calling switch */
-      lf_print_idecode_switch(file, entry);
-    }
-    else {
-      /* switch calling table */
-      lf_printf(file, "return ");
-      lf_print_idecode_table(file, entry);
-    }
-    lf_printf(file, "break;\n");
-  }
-  lf_indent(file, -2);
-}
-
-
-static void
-lf_print_idecode_switch_illegal(lf *file)
-{
-  lf_indent(file, +2);
-  lf_print_idecode_illegal(file);
-  lf_printf(file, "break;\n");
-  lf_indent(file, -2);
-}
-
-static void
-idecode_switch_end(insn_table *table,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
-
-  if (table->opcode_rule->use_switch == 1) {
-    lf_printf(file, "default:\n");
-    lf_print_idecode_switch_illegal(file);
-  }
-  lf_printf(file, "}\n");
-}
-
-static void
-idecode_switch_padding(insn_table *table,
-                      void *data,
-                      int depth,
-                      int opcode_nr)
-{
-  lf *file = (lf*)data;
-
-  ASSERT(depth == 0);
-  ASSERT(table->opcode_rule->use_switch);
-
-  if (table->opcode_rule->use_switch > 1) {
-    lf_printf(file, "case %d:\n", opcode_nr);
-    lf_print_idecode_switch_illegal(file);
-  }
-}
-
-
-void
-lf_print_idecode_switch(lf *file, 
-                       insn_table *table)
-{
-  insn_table_traverse_tree(table,
-                          file,
-                          0,
-                          idecode_switch_start,
-                          idecode_switch_leaf,
-                          idecode_switch_end,
-                          idecode_switch_padding);
-}
-
-
-static void
-idecode_expand_if_switch(insn_table *table,
-                        void *data,
-                        int depth)
-{
-  lf *file = (lf*)data;
-
-  if (table->opcode_rule->use_switch
-      && table->parent != NULL /* don't expand the top one yet */
-      && !table->parent->opcode_rule->use_switch) {
-    lf_printf(file, "\n");
-    lf_printf(file, "STATIC_INLINE_IDECODE void\n");
-    lf_print_table_name(file, table);
-    lf_printf(file, "\n(%s)\n",
-             (idecode_cache ? cache_idecode_formal : insn_formal));
-    lf_printf(file, "{\n");
-    {
-      lf_indent(file, +2);
-      lf_print_idecode_switch(file, table);
-      lf_indent(file, -2);
-    }
-    lf_printf(file, "}\n");
-  }
-}
-
-
-static void
-lf_print_c_cracker_function(lf *file,
-                           insn *instruction,
-                           insn_bits *expanded_bits,
-                           opcode_field *opcodes)
-{
-  /* if needed, generate code to enter this routine into a cache */
-  lf_printf(file, "\n");
-  lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        expanded_bits,
-                        function_name_prefix_idecode);
-  lf_printf(file, "\n(%s)\n", cache_idecode_formal);
-
-  lf_print_c_cracker(file,
-                    instruction,
-                    expanded_bits,
-                    opcodes);
-}
-
-static void
-idecode_crack_leaf(insn_table *entry,
-                  void *data,
-                  int depth)
-{
-  lf *file = (lf*)data;
-  ASSERT(entry->nr_insn == 1
-        && entry->opcode == NULL
-        && entry->parent != NULL
-        && entry->parent->opcode != NULL);
-  lf_print_c_cracker_function(file,
-                             entry->insns,
-                             entry->expanded_bits,
-                             entry->opcode);
-}
-
-static void
-idecode_crack_insn(insn_table *entry,
-                  void *data,
-                  insn *instruction)
-{
-  lf *file = (lf*)data;
-  lf_print_c_cracker_function(file,
-                             instruction,
-                             NULL,
-                             NULL);
-}
-
-static void
-idecode_c_internal_function(insn_table *table,
-                           void *data,
-                           file_table_entry *function)
-{
-  lf *file = (lf*)data;
-  ASSERT(idecode_cache != 0);
-  if (it_is("internal", function->fields[insn_flags])) {
-    lf_printf(file, "\n");
-    lf_printf(file, "STATIC_INLINE_IDECODE idecode_semantic *\n");
-    lf_print_function_name(file,
-                          function->fields[insn_name],
-                          NULL,
-                          function_name_prefix_idecode);
-    lf_printf(file, "\n(%s)\n", cache_idecode_formal);
-    lf_printf(file, "{\n");
-    lf_indent(file, +2);
-    lf_printf(file, "/* semantic routine */\n");
-    lf_print_c_line_nr(file, function);
-    lf_printf(file, "return ");
-    lf_print_function_name(file,
-                          function->fields[insn_name],
-                          NULL,
-                          function_name_prefix_semantics);
-    lf_printf(file, ";\n");
-
-    lf_print_file_line_nr(file);
-    lf_indent(file, -2);
-    lf_printf(file, "}\n");
-  }
-}
-
-
-/****************************************************************/
-
-static void
-gen_idecode_c(insn_table *table, lf *file)
-{
-  int depth;
-
-  /* the intro */
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _IDECODE_C_\n");
-  lf_printf(file, "#define _IDECODE_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef STATIC_INLINE_IDECODE\n");
-  lf_printf(file, "#define STATIC_INLINE_IDECODE STATIC_INLINE\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"cpu.h\"\n");
-  lf_printf(file, "#include \"idecode.h\"\n");
-  lf_printf(file, "#include \"semantics.h\"\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
-           (idecode_cache ? cache_idecode_formal : insn_formal));
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef struct _idecode_table_entry {\n");
-  lf_printf(file, "  unsigned shift;\n");
-  lf_printf(file, "  unsigned mask;\n");
-  lf_printf(file, "  void *function_or_table;\n");
-  lf_printf(file, "} idecode_table_entry;\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "\n");
-
-  /* output `internal' invalid/floating-point unavailable functions
-     where needed */
-  if (idecode_cache) {
-    insn_table_traverse_function(table,
-                                file,
-                                idecode_c_internal_function);
-  }
-
-  /* output cracking functions where needed */
-  if (idecode_cache) {
-    if (idecode_expand_semantics)
-      insn_table_traverse_tree(table,
-                              file,
-                              1,
-                              NULL,
-                              idecode_crack_leaf,
-                              NULL,
-                              NULL);
-    else
-      insn_table_traverse_insn(table,
-                              file,
-                              idecode_crack_insn);
-  }
-
-
-  /* output tables where needed */
-  for (depth = insn_table_depth(table);
-       depth > 0;
-       depth--) {
-    insn_table_traverse_tree(table,
-                            file,
-                            1-depth,
-                            idecode_table_start,
-                            idecode_table_leaf,
-                            idecode_table_end,
-                            idecode_table_padding);
-  }
-
-  /* output switch functions where needed */
-  insn_table_traverse_tree(table,
-                          file,
-                          1,
-                          idecode_expand_if_switch, /* START */
-                          NULL, NULL, NULL);
-
-  /* output the main idecode routine */
-  lf_printf(file, "\n");
-  if (idecode_cache)
-    lf_printf(file, "INLINE_IDECODE idecode_semantic *\nidecode\n(%s)\n",
-             cache_idecode_formal);
-  else
-    lf_printf(file, "INLINE_IDECODE unsigned_word\nidecode_issue\n(%s)\n",
-             insn_formal);
-  lf_printf(file, "{\n");
-  lf_indent(file, +2);
-  if (table->opcode_rule->use_switch)
-    lf_print_idecode_switch(file, table);
-  else
-    lf_print_idecode_table(file, table);
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif\n");
-}
-
-
-/****************************************************************/
-
-
-typedef enum {
-  spreg_name,
-  spreg_reg_nr,
-  spreg_readonly,
-  spreg_length,
-  nr_spreg_registers = file_table_max_fields
-} spreg_fields;
-
-typedef struct _spreg_table_entry spreg_table_entry;
-struct _spreg_table_entry {
-  char *name;
-  int spreg_nr;
-  int is_readonly;
-  int length;
-  file_table_entry *entry;
-  spreg_table_entry *next;
-};
-
-typedef struct _spreg_table spreg_table;
-struct _spreg_table {
-  spreg_table_entry *sprs;
-};
-
-static spreg_table_entry *
-spreg_table_entry_new()
-{
-  spreg_table_entry *new_entry =
-    (spreg_table_entry*)zmalloc(sizeof(spreg_table_entry));
-  ASSERT(new_entry != NULL);
-  return new_entry;
-}
-
-static spreg_table *
-spreg_table_new()
-{
-  spreg_table *new_table = (spreg_table*)zmalloc(sizeof(spreg_table));
-  ASSERT(new_table != NULL);
-  return new_table;
-}
-
-static void
-spreg_table_insert(spreg_table *table, file_table_entry *entry)
-{
-  /* create a new spr entry */
-  spreg_table_entry *new_spr = spreg_table_entry_new();
-  new_spr->next = NULL;
-  new_spr->entry = entry;
-  new_spr->spreg_nr = atoi(entry->fields[spreg_reg_nr]);
-  new_spr->is_readonly = (entry->fields[spreg_readonly]
-                         ? atoi(entry->fields[spreg_readonly])
-                         : 0);
-  new_spr->length = atoi(entry->fields[spreg_length]);
-  new_spr->name = (char*)zmalloc(strlen(entry->fields[spreg_name]) + 1);
-  ASSERT(new_spr->name != NULL);
-  {
-    int i;
-    for (i = 0; entry->fields[spreg_name][i] != '\0'; i++) {
-      if (isupper(entry->fields[spreg_name][i]))
-       new_spr->name[i] = tolower(entry->fields[spreg_name][i]);
-      else
-       new_spr->name[i] = entry->fields[spreg_name][i];
-    }
-  }
-
-  /* insert, by spreg_nr order */
-  {
-    spreg_table_entry **ptr_to_spreg_entry = &table->sprs;
-    spreg_table_entry *spreg_entry = *ptr_to_spreg_entry;
-    while (spreg_entry != NULL && spreg_entry->spreg_nr < new_spr->spreg_nr) {
-      ptr_to_spreg_entry = &spreg_entry->next;
-      spreg_entry = *ptr_to_spreg_entry;
-    }
-    ASSERT(spreg_entry == NULL || spreg_entry->spreg_nr != new_spr->spreg_nr);
-    *ptr_to_spreg_entry = new_spr;
-    new_spr->next = spreg_entry;
-  }
-
-}
-
-
-static spreg_table *
-spreg_table_load(char *file_name)
-{
-  file_table *file = file_table_open(file_name);
-  spreg_table *table = spreg_table_new();
-
-  {
-    file_table_entry *entry;
-    while ((entry = file_table_read(file)) != NULL) {
-      spreg_table_insert(table, entry);
-    }
-  }
-
-  return table;
-}
-
-
-/****************************************************************/
-
-char *spreg_attributes[] = {
-  "is_valid",
-  "is_readonly",
-  "name",
-  "index",
-  "length",
-  0
-};
-
-static void
-gen_spreg_h(spreg_table *table, lf *file)
-{
-  spreg_table_entry *entry;
-  char **attribute;
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SPREG_H_\n");
-  lf_printf(file, "#define _SPREG_H_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef INLINE_SPREG\n");
-  lf_printf(file, "#define INLINE_SPREG\n");
-  lf_printf(file, "#endif\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef unsigned_word spreg;\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef enum {\n");
-
-  for (entry = table->sprs;
-       entry != NULL ;
-       entry = entry->next) {
-    lf_printf(file, "  spr_%s = %d,\n", entry->name, entry->spreg_nr);
-  }
-
-  lf_printf(file, "  nr_of_sprs = %d\n", nr_of_sprs);
-  lf_printf(file, "} sprs;\n");
-  lf_printf(file, "\n");
-  for (attribute = spreg_attributes;
-       *attribute != NULL;
-       attribute++) {
-    if (strcmp(*attribute, "name") == 0)
-      lf_printf(file, "INLINE_SPREG char *spr_%s(sprs spr);\n",
-               *attribute);
-    else
-      lf_printf(file, "INLINE_SPREG int spr_%s(sprs spr);\n",
-               *attribute);
-  }
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SPREG_H_ */\n");
-}
-
-
-static void
-gen_spreg_c(spreg_table *table, lf *file)
-{
-  spreg_table_entry *entry;
-  char **attribute;
-  int spreg_nr;
-
-  lf_print_copyleft(file);
-  lf_printf(file, "\n");
-  lf_printf(file, "#ifndef _SPREG_C_\n");
-  lf_printf(file, "#define _SPREG_C_\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "#include \"words.h\"\n");
-  lf_printf(file, "#include \"spreg.h\"\n");
-
-  lf_printf(file, "\n");
-  lf_printf(file, "typedef struct _spreg_info {\n");
-  lf_printf(file, "  char *name;\n");
-  lf_printf(file, "  int is_valid;\n");
-  lf_printf(file, "  int length;\n");
-  lf_printf(file, "  int is_readonly;\n");
-  lf_printf(file, "  int index;\n");
-  lf_printf(file, "} spreg_info;\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "static spreg_info spr_info[nr_of_sprs+1] = {\n");
-  entry = table->sprs;
-  for (spreg_nr = 0; spreg_nr < nr_of_sprs+1; spreg_nr++) {
-    if (entry == NULL || spreg_nr < entry->spreg_nr)
-      lf_printf(file, "  { 0, 0, 0, 0, %d},\n", spreg_nr);
-    else {
-      lf_printf(file, "  { \"%s\", %d, %d, %d, spr_%s /*%d*/ },\n",
-               entry->name, 1, entry->length, entry->is_readonly,
-               entry->name, entry->spreg_nr);
-      entry = entry->next;
-    }
-  }
-  lf_printf(file, "};\n");
-
-  for (attribute = spreg_attributes;
-       *attribute != NULL;
-       attribute++) {
-    lf_printf(file, "\n");
-    if (strcmp(*attribute, "name") == 0)
-      lf_printf(file, "INLINE_SPREG char *\n");
-    else
-      lf_printf(file, "INLINE_SPREG int\n");
-    lf_printf(file, "spr_%s(sprs spr)\n", *attribute);
-    lf_printf(file, "{\n");
-    if (spreg_lookup_table
-       || strcmp(*attribute, "name") == 0
-       || strcmp(*attribute, "index") == 0)
-      lf_printf(file, "  return spr_info[spr].%s;\n",
-               *attribute);
-    else {
-      spreg_table_entry *entry;
-      lf_printf(file, "  switch (spr) {\n");
-      for (entry = table->sprs; entry != NULL; entry = entry->next) {
-       lf_printf(file, "  case %d:\n", entry->spreg_nr);
-       if (strcmp(*attribute, "is_valid") == 0)
-         lf_printf(file, "    return 1;\n");
-       else if (strcmp(*attribute, "is_readonly") == 0)
-         lf_printf(file, "    return %d;\n", entry->is_readonly);
-       else if (strcmp(*attribute, "length") == 0)
-         lf_printf(file, "    return %d;\n", entry->length);
-       else
-         ASSERT(0);
-      }
-      lf_printf(file, "  default:\n");
-      lf_printf(file, "    return 0;\n");
-      lf_printf(file, "  }\n");
-    }
-    lf_printf(file, "}\n");
-  }
-
-  lf_printf(file, "\n");
-  lf_printf(file, "#endif /* _SPREG_C_ */\n");
-}
-
-
-
-/****************************************************************/
-
-
-int
-main(int argc,
-     char **argv,
-     char **envp)
-{
-  insn_table *instructions = NULL;
-  spreg_table *sprs = NULL;
-  icache_tree *cache_fields = NULL;
-  char *real_file_name = NULL;
-  int ch;
-
-  while ((ch = getopt(argc, argv, "n:i:I:r:S:s:D:d:P:p:C:")) != -1) {
-    fprintf(stderr, "\t-%c %s\n", ch, optarg);
-    switch(ch) {
-    case 'I':
-    case 'i':
-      instructions = insn_table_load_insns(optarg);
-      fprintf(stderr, "\texpanding ...\n");
-      insn_table_expand_insns(instructions);
-      fprintf(stderr, "\tcache fields ...\n");
-      cache_fields = insn_table_cache_fields(instructions);
-      if (ch == 'I') {
-       dump_traverse(instructions);
-       dump_insn_table(instructions, 0, 1);
-      }
-      break;
-    case 'r':
-      sprs = spreg_table_load(optarg);
-      break;
-    case 'n':
-      real_file_name = strdup(optarg);
-      break;
-    default:
-      {
-       lf *file = lf_open(optarg, real_file_name);
-       switch (ch) {
-       case 'S':
-         gen_semantics_h(instructions, file);
-         break;
-       case 's':
-         gen_semantics_c(instructions, file);
-         break;
-       case 'P':
-         gen_spreg_h(sprs, file);
-         break;
-       case 'p':
-         gen_spreg_c(sprs, file);
-         break;
-       case 'D':
-         gen_idecode_h(instructions, file);
-         break;
-       case 'd':
-         gen_idecode_c(instructions, file);
-         break;
-       case 'C':
-         gen_icache_h(cache_fields, file);
-         break;
-       }
-       lf_close(file);
-      }
-      real_file_name = NULL;
-    }
-  }
-  return 0;
-}
diff --git a/sim/ppc/os_emul.c b/sim/ppc/os_emul.c
new file mode 100644 (file)
index 0000000..844b77f
--- /dev/null
@@ -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_ */
diff --git a/sim/ppc/os_emul.h b/sim/ppc/os_emul.h
new file mode 100644 (file)
index 0000000..1febef8
--- /dev/null
@@ -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
diff --git a/sim/ppc/ppc-cache-rules b/sim/ppc/ppc-cache-rules
new file mode 100644 (file)
index 0000000..9dad017
--- /dev/null
@@ -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)
index 1e51bdf..ec90bb7 100644 (file)
@@ -33,7 +33,7 @@
 #include "ppc-endian.h"
 #include "sim_callbacks.h"
 
-#if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
+#if !defined(SWAP_2) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
 #define SWAP_2(SET,RAW) SET htons (RAW)
 #endif
 
@@ -67,7 +67,7 @@ endian_##NAME##_##BYTE_SIZE(unsigned_##BYTE_SIZE raw_in) \
     return raw_in; \
   } \
   else { \
-    SWAP_##BYTE_SIZE(return, raw_in); \
+    SWAP_##BYTE_SIZE(return,raw_in); \
   } \
 }
 #endif
diff --git a/sim/ppc/ppc-opcode-complex b/sim/ppc/ppc-opcode-complex
new file mode 100644 (file)
index 0000000..0435846
--- /dev/null
@@ -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
diff --git a/sim/ppc/ppc-opcode-simple b/sim/ppc/ppc-opcode-simple
new file mode 100644 (file)
index 0000000..b3a1316
--- /dev/null
@@ -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
diff --git a/sim/ppc/spa-reporter.c b/sim/ppc/spa-reporter.c
new file mode 100644 (file)
index 0000000..9a7dd29
--- /dev/null
@@ -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;
+}
diff --git a/sim/ppc/spa-system-calls.c b/sim/ppc/spa-system-calls.c
new file mode 100644 (file)
index 0000000..a344595
--- /dev/null
@@ -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 *);
diff --git a/sim/ppc/spa-system-calls.h b/sim/ppc/spa-system-calls.h
new file mode 100644 (file)
index 0000000..1ee9c1e
--- /dev/null
@@ -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
index 07018bf..9e06267 100644 (file)
    of the host/target it is able to eliminate slower generic endian
    handling code.
 
-   If ENDIAN_OK is true then no byte swapping is required.  If it is
-   false, copy-in / copy-out functions assume that data should be byte
-   reversed as part of the copy. */
+   Possible values are 0 (unknown), LITTLE_ENDIAN, BIG_ENDIAN */
 
+#ifndef WITH_HOST_BYTE_ORDER
 #define WITH_HOST_BYTE_ORDER           0 /*unknown*/
+#endif
+
+#ifndef WITH_TARGET_BYTE_ORDER
 #define WITH_TARGET_BYTE_ORDER         0 /*unknown*/
+#endif
 
 extern int current_host_byte_order;
-extern int current_target_byte_order;
 #define CURRENT_HOST_BYTE_ORDER (WITH_HOST_BYTE_ORDER \
                                 ? WITH_HOST_BYTE_ORDER \
                                 : current_host_byte_order)
+extern int current_target_byte_order;
 #define CURRENT_TARGET_BYTE_ORDER (WITH_TARGET_BYTE_ORDER \
                                   ? WITH_TARGET_BYTE_ORDER \
                                   : current_target_byte_order)
 
 
+/* Intel host BSWAP support:
+
+   Whether to use bswap on the 486 and pentiums rather than the 386
+   sequence that uses xchgb/rorl/xchgb */
+#ifndef WITH_BSWAP
+#define        WITH_BSWAP 0
+#endif
+
+
 /* SMP support:
 
    Sets a limit on the number of processors that can be simulated.  If
    WITH_SMP is set to zero (0), the simulator is restricted to
    suporting only on processor (and as a consequence leaves the SMP
-   code out of the build process). */
+   code out of the build process).
+
+   The actual number of processors is taken from the device
+   /options/smp@<nr-cpu> */
 
 #ifndef WITH_SMP
-#define WITH_SMP                        0
+#define WITH_SMP                        2
+#endif
+#if WITH_SMP
+#define MAX_NR_PROCESSORS              WITH_SMP
+#else
+#define MAX_NR_PROCESSORS              1
 #endif
 
 
@@ -68,6 +88,7 @@ extern int current_target_byte_order;
 #ifndef WITH_TARGET_WORD_BITSIZE
 #define WITH_TARGET_WORD_BITSIZE        32 /* compiled only */
 #endif
+
 #ifndef WITH_HOST_WORD_BITSIZE
 #define WITH_HOST_WORD_BITSIZE         32 /* 64bit ready? */
 #endif
@@ -85,10 +106,13 @@ extern int current_target_byte_order;
    CURRENT_ENVIRONMENT specifies which of vea or oea is required for
    the current runtime. */
 
-#define WITH_ENVIRONMENT               0
 #define VIRTUAL_ENVIRONMENT            1
 #define OPERATING_ENVIRONMENT          2
 
+#ifndef WITH_ENVIRONMENT
+#define WITH_ENVIRONMENT               0
+#endif
+
 extern int current_environment;
 #define CURRENT_ENVIRONMENT (WITH_ENVIRONMENT \
                             ? WITH_ENVIRONMENT \
@@ -170,6 +194,7 @@ extern int current_environment;
 #ifndef WITH_ALIGNMENT
 #define WITH_ALIGNMENT                 0
 #endif
+
 extern int current_alignment;
 #define CURRENT_ALIGNMENT (WITH_ALIGNMENT \
                           ? WITH_ALIGNMENT \
@@ -210,254 +235,16 @@ extern int current_floating_point;
 #define WITH_ASSERT                    1
 #endif
 
-/* include profiling code that doesn't yet exist */
-
-#ifndef WITH_PROFILE
-#define WITH_PROFILE                   1
-#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.
+/* include monitoring code */
 
-   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
+#define MONITOR_INSTRUCTION_ISSUE      1
+#define MONITOR_LOAD_STORE_UNIT                2
+#ifndef WITH_MON
+#define WITH_MON                       (MONITOR_LOAD_STORE_UNIT \
+                                        | MONITOR_INSTRUCTION_ISSUE)
 #endif
 
 
-/* Instruction decode:
-
-   The table that follows is used by gen to construct a decision tree
-   that can identify each possible instruction.  Gen then outputs this
-   decision tree as (according to config) a table or switch statement
-   as the function idecode.
-
-   In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
-   determines of the semantic functions themselves should be expanded
-   in a similar way.
-
-   The table contains the following entries:
-
-   <valid>
-
-   Must be 1 for the entry to be considered.  The last entry must be
-   zero.
-       
-   <first>
-   <last>
-
-   Range of bits (within the instruction) that should be searched for
-   an instruction field.  Within such ranges, gen looks for opcodes
-   (constants), registers (strings) and reserved bits (slash) and
-   according to the rules that follows includes or excludes them from
-   a possible instruction field.
-
-   <force_first>
-   <force_last>
-
-   If an instructioin field was found, enlarge the field size so that
-   it is forced to at least include bits starting from <force_first>
-   (<force_last>).  To stop this occuring, use <force_first> = <last>
-   + 1 and <force_last> = <first> - 1.
-
-   <force_slash>
-
-   Treat `/' fields as a constant instead of variable when looking for
-   an instruction field.
-
-   <force_expansion>
-
-   Treat any contained register (string) fields as constant when
-   determining the instruction field.  For the instruction decode (and
-   controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
-   what would otherwize be non constant bits of an instruction.
-
-   <use_switch>
-
-   Should this table be expanded using a switch statement (val 1) and
-   if so, should it be padded with entries so as to force the compiler
-   to generate a jump table (val 2).
-
-   <special_mask>
-   <special_value>
-   <special_rule>
-
-   Special rule to fine tune how specific (or groups) of instructions
-   are expanded.  The applicability of the rule is determined by
-
-     <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
-
-   Where <instruction> is obtained by looking only at constant fields
-   with in an instructions spec.  When determining an expansion, the
-   rule is only considered when a node contains a single instruction.
-   <special_rule> can be any of:
-
-        0: for this instruction, expand by earlier rules
-       1: expand bits <force_low> .. <force_hi> only
-       2: boolean expansion of only zero/non-zero cases
-
-   Ok? */
-
-
-#define WITH_IDECODE_OPCODE_RULES { \
-  { 1,  0,  5,  0,  5, 0, 0,                1, 0x00000000, 0x00000000, 0 }, \
-  { 1, 21, 31, 32, -1, 0, 0,                1, 0x00000000, 0x00000000, 0 }, \
-  { 0 } \
-}
-
-
-/* Instruction unpacking:
-
-   Once the instruction has been decoded, the register (and other)
-   fields within the instruction need to be extracted.
-
-   The table that follows determines how each field should be treated.
-   Importantly it considers the case where the extracted field is to
-   be used immediatly or stored in an instruction cache.
-
-   <valid>
-
-   Zero marks the end of the table.  More importantly 1. indicates
-   that the entry is valid and can be cached. 2. indicates that that
-   the entry is valid but can not be cached.
-
-   <old_name>
-
-   The field name as given in the instruction spec.
-
-   <new_name>
-
-   A name for <old_name> once it has been extracted from the
-   instructioin (and possibly stored in the instruction cache).
-
-   <type>
-
-   String specifying the storage type for <new_name> (the extracted
-   field>.
-
-   <expression>
-
-   Specifies how to get <new_name> from <old_name>.  If null, old and
-   new name had better be the same. */
-
-#define WITH_IDECODE_CACHE_RULES { \
-  { 1, "RA", "RA", 0, 0 }, \
-  { 1, "RA", "rA", "signed_word *", \
-      "(cpu_registers(processor)->gpr + RA)" }, \
-  { 1, "RT", "RT", 0, 0 }, \
-  { 1, "RT", "rT", "signed_word *", \
-      "(cpu_registers(processor)->gpr + RT)" }, \
-  { 2, "RS", "RS", 0, 0 }, \
-  { 1, "RS", "rS", "signed_word *", \
-      "(cpu_registers(processor)->gpr + RS)" }, \
-  { 2, "RB", "RB", 0, 0 }, \
-  { 1, "RB", "rB", "signed_word *", \
-      "(cpu_registers(processor)->gpr + RB)" }, \
-  { 2, "FRA", "FRA", 0, 0 }, \
-  { 1, "FRA", "frA", "unsigned64 *", \
-      "(cpu_registers(processor)->fpr + FRA)" }, \
-  { 2, "FRB", "FRB", 0, 0 }, \
-  { 1, "FRB", "frB", "unsigned64 *", \
-      "(cpu_registers(processor)->fpr + FRB)" }, \
-  { 2, "FRC", "FRC", 0, 0 }, \
-  { 1, "FRC", "frC", "unsigned64 *", \
-      "(cpu_registers(processor)->fpr + FRC)" }, \
-  { 2, "FRS", "FRS", 0, 0 }, \
-  { 1, "FRS", "frS", "unsigned64 *", \
-      "(cpu_registers(processor)->fpr + FRS)" }, \
-  { 2, "FRT", "FRT", 0, 0 }, \
-  { 1, "FRT", "frT", "unsigned64 *", \
-      "(cpu_registers(processor)->fpr + FRT)" }, \
-  { 1, "SI", "EXTS_SI", "unsigned_word", \
-      "((signed_word)(signed16)instruction)" }, \
-  { 2, "BI", "BI", 0, 0 }, \
-  { 1, "BI", "BIT32_BI", 0, \
-      "BIT32(BI)" }, \
-  { 2, "BA", "BA", 0, 0 }, \
-  { 1, "BA", "BIT32_BA", 0, \
-       "BIT32(BA)" }, \
-  { 2, "BB", "BB", 0, 0 }, \
-  { 1, "BB", "BIT32_BB", 0, \
-      "BIT32(BB)" }, \
-  { 1, "BD", "EXTS_BD_0b00", "unsigned_word", \
-      "(((signed_word)(signed16)instruction) & ~3)" }, \
-/*{ 1, "BD", "CIA_plus_EXTS_BD_0b00", "unsigned_word", */ \
-/*    "CIA + EXTS(BD_0b00)" }, */ \
-  { 1, "LI", "EXTS_LI_0b00", "unsigned_word", \
-      "((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)" }, \
-  { 1, "D", "EXTS_D", "unsigned_word", \
-      "((signed_word)(signed16)(instruction))" }, \
-  { 1, "DS", "EXTS_DS_0b00", "unsigned_word", \
-      "(((signed_word)(signed16)instruction) & ~0x3)" }, \
-  { 0 } \
-};
-
-
 
 /* INLINE CODE SELECTION:
 
@@ -486,12 +273,14 @@ extern int current_floating_point;
    controled by the <module>_INLINE macro's.  Where each can have a
    value:
 
-      0  ppc.c should call external module
+      0  Make a normal external call to functions in the module.
 
-      1  ppc.c should have local copy (and hence possibly facilitate
-         the in lineing of that modules external calls)
+      1  Include the module but to not inline functions within it.
+         This allows functions within the module to inline functions
+        from other modules that have been included.
 
-      2  ppc.c should inline this module
+      2  Both include the module and inline functions contained within
+         it.
 
    Finally, this is not for the faint harted.  I've seen GCC get up to
    200mb trying to compile what this can create */
@@ -512,86 +301,92 @@ extern int current_floating_point;
 #define STATIC_INLINE static INLINE
 #endif
 
-/* Default macro to control several of the inlines */
+/* Default macro to simplify control several of key the inlines */
 
 #ifndef DEFAULT_INLINE
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
+#define        DEFAULT_INLINE                  2
+#else
 #define        DEFAULT_INLINE                  0
 #endif
+#endif
 
-/* Code that does byte swapping used on any memory access */
+/* Code that converts between hosts and target byte order.  Used on
+   every memory access (instruction and data).  (See ppc-endian.h for
+   additional byte swapping configuration information) */
 
 #ifndef ENDIAN_INLINE
 #define ENDIAN_INLINE                  DEFAULT_INLINE
 #endif
 
-/* Instruction cache if in use */
-
-#if 0 /*DNE*/
-#ifndef ICACHE_INLINE
-#define ICACHE_INLINE                  0
-#endif
-#endif
-
-/* Given a translated address, core maps it onto either simulator data
-   or a function call, this is performed once for each
-   data/instruction access */
+/* Code that gives access to various CPU internals such as registers.
+   Used every time an instruction is executed */
 
-
-#ifndef CORE_INLINE
-#define CORE_INLINE                    DEFAULT_INLINE
+#ifndef CPU_INLINE
+#define CPU_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 */
+/* Code that translates between an effective and real address.  Used
+   by every load or store. */
 
 #ifndef VM_INLINE
 #define VM_INLINE                      DEFAULT_INLINE
 #endif
 
-/* Physical memory is implemented using the memory map module */
+/* Code that loads/stores data to/from the memory data structure.
+   Used by every load or store */
 
-#ifndef CPU_INLINE
-#define CPU_INLINE                     DEFAULT_INLINE
+#ifndef CORE_INLINE
+#define CORE_INLINE                    DEFAULT_INLINE
 #endif
 
-/* handle the queue of events to happen in the future */
+/* Code to check for and process any events scheduled in the future.
+   Called once per instruction cycle */
 
 #ifndef EVENTS_INLINE
 #define EVENTS_INLINE                  DEFAULT_INLINE
 #endif
 
-/* not so important register manipulation code.  Most important
-   register operations are performed directly on the register file */
+/* Code monotoring the processors performance.  It counts events on
+   every instruction cycle */
 
-#ifndef REGISTERS_INLINE
-#define REGISTERS_INLINE               DEFAULT_INLINE
+#ifndef MON_INLINE
+#define MON_INLINE                     DEFAULT_INLINE
 #endif
 
-/* interrupt handling code */
+/* Code called on the rare occasions that an interrupt occures. */
 
 #ifndef INTERRUPTS_INLINE
-#define INTERRUPTS_INLINE              DEFAULT_INLINE
+#define INTERRUPTS_INLINE              0
+#endif
+
+/* Code called on the rare occasion that either gdb or the device tree
+   need to manipulate a register within a processor */
+
+#ifndef REGISTERS_INLINE
+#define REGISTERS_INLINE               0
 #endif
 
-/* device code. While possibly important, this isn't as critical as
-   the cpu/memory path
+/* Code called on the rare occasion that a processor is manipulating
+   real hardware instead of RAM.
+
+   Also, most of the functions in devices.c are always called through
+   a jump table.
 
    There seems to be some problem with making either device_tree or
-   devices inline.  It reports the message:
-   device_tree_find_node() not a leaf  */
+   devices inline.  It reports the message: device_tree_find_node()
+   not a leaf */
 
 #ifndef DEVICE_TREE_INLINE
-#define DEVICE_TREE_INLINE             0
+#define DEVICE_TREE_INLINE             DEFAULT_INLINE
 #endif
 
 #ifndef DEVICES_INLINE
 #define DEVICES_INLINE                 0
 #endif
 
-/* Special Purpose Register tables.  Provide information on the
-   attributes of given SPR's. */
+/* Code called whenever information on a Special Purpose Register is
+   required.  Called by the mflr/mtlr pseudo instructions */
 
 #ifndef SPREG_INLINE
 #define SPREG_INLINE                   DEFAULT_INLINE
@@ -610,163 +405,14 @@ extern int current_floating_point;
    inline all of their called functions */
 
 #ifndef SEMANTICS_INLINE
-#define SEMANTICS_INLINE               0
+#define SEMANTICS_INLINE               (DEFAULT_INLINE ? 1 : 0)
 #endif
 
-/* Functions that decode an instruction.  Called by the cpu module.
-   Part of the performance critical fetch - decode - issue sequence */
+/* Code to decode an instruction. Normally called on every instruction
+   cycle */
 
 #ifndef IDECODE_INLINE
 #define IDECODE_INLINE                 DEFAULT_INLINE
 #endif
 
-
-
-/* If you're confused by the above, check out some of the generic
-   configurations below. */
-
-
-#if 0
-/* Allow the expansion of the semantic functions.  That is, if the
-   branch instruction is called with AA=0 and AA=1, generate separate
-   functions for each case */
-
-#undef WITH_IDECODE_EXPAND_SEMANTICS
-#define WITH_IDECODE_EXPAND_SEMANTICS 1
-
-#undef WITH_IDECODE_OPCODE_RULES
-#define WITH_IDECODE_OPCODE_RULES { \
-  { 1,  0,  5,  0,  5, 0, 0,                0, 0x00000000, 0x00000000, 0 }, \
-  { 1, 21, 31, 32, -1, 0, "OE,LR,AA,Rc,LK", 0, 0x00000000, 0x00000000, 0 }, \
-  { 1,  6,  9,  6,  9, 0, "BO",             0, 0xfc000000, 0x40000000, 1 }, \
-  { 1, 11, 15, 11, 15, 0, "RA",             0, 0xfc000000, 0x38000000, 2 }, \
-  { 1, 11, 15, 11, 15, 0, "RA",             0, 0xfc000000, 0x3c000000, 2 }, \
-  { 0 } \
-}
-#endif
-
-
-#if 0
-/* eliminate any debugging noise */
-
-#undef WITH_TRACE
-#define WITH_TRACE 0
-
-#undef WITH_ASSERT
-#define WITH_ASSERT 0
-
-#endif
-
-
-#if 0
-/* A reasonable set of inline macro's that give the compiler a
-   fighting chance at eliminating much of the function call overhead.
-
-   Typically, with the below the -O3 option (to get inline of all
-   functioins) isn't of any greate benefit. */
-
-#undef INLINE
-#define INLINE inline
-
-#undef STATIC_INLINE
-#define STATIC_INLINE static INLINE
-
-#undef ENDIAN_INLINE
-#define ENDIAN_INLINE 2
-
-#if 0 /*DNE*/
-#undef ICACHE_INLINE
-#define ICACHE_INLINE 0
-#endif
-
-#undef CORE_INLINE
-#define CORE_INLINE 2
-
-#undef VM_INLINE
-#define VM_INLINE 2
-
-#undef CPU_INLINE
-#define CPU_INLINE 2
-
-#undef EVENTS_INLINE
-#define EVENTS_INLINE 2
-
-#undef REGISTERS_INLINE
-#define REGISTERS_INLINE 2
-
-#undef INTERRUPTS_INLINE
-#define INTERRUPTS_INLINE 2
-
-#undef DEVICE_TREE_INLINE
-#define DEVICE_TREE_INLINE 0
-
-#undef DEVICES_INLINE
-#define DEVICES_INLINE 0
-
-#undef SPREG_INLINE
-#define SPREG_INLINE 2
-
-#undef SEMANTICS_INLINE
-#define SEMANTICS_INLINE 1 /* not 2! as it blows away the compiler */
-
-#undef IDECODE_INLINE
-#define IDECODE_INLINE 2
-
-#endif
-
-
-#if 0
-/* Enable the full cracking cache.  The cracked instruction cache
-   appears to give best performance if most functions have been lined
-   as well */
-
-#undef WITH_IDECODE_CACHE
-#define WITH_IDECODE_CACHE 2
-
-#endif
-
-
-
-#if 0
-/* With the VEA model, can eliminate some things.  Not least of which
-   is support for the OEA model */
-
-#undef WITH_ENVIRONMENT
-#define WITH_ENVIRONMENT VIRTUAL_ENVIRONMENT
-
-#undef WITH_EVENTS
-#define WITH_EVENTS 0
-
-#undef WITH_SMP
-#define WITH_SMP 0
-
-#undef WITH_TARGET_BYTE_ORDER 
-#define WITH_TARGET_BYTE_ORDER WITH_HOST_BYTE_ORDER
-
-#endif
-
-
-
-
-#if 0
-/* Finally, the expansion rules below are extreemly agressive.  Only
-   consider them if your build machine is VERY VERY VERY VERY VERY
-   well configured */
-
-#undef WITH_IDECODE_EXPAND_SEMANTICS
-#define WITH_IDECODE_EXPAND_SEMANTICS 1
-
-#undef WITH_IDECODE_OPCODE_RULES
-#define WITH_IDECODE_OPCODE_RULES { \
-  { 1,  0,  5,  0,  5, 0, 0,                0, 0x00000000, 0x00000000, 0 }, \
-  { 1, 21, 31, 32, -1, 0, "OE,LR,AA,Rc,LK", 0, 0x00000000, 0x00000000, 0 }, \
-  { 1,  6, 15,  6, 15, 0, "BO,BI",          0, 0xfc000000, 0x40000000, 0 }, \
-  { 1, 11, 15, 11, 15, 0, "RA",             0, 0xfc000000, 0x38000000, 0 }, \
-  { 1, 11, 15, 11, 15, 0, "RA",             0, 0xfc000000, 0x3c000000, 0 }, \
-  { 1, 11, 20, 11, 20, 0, "spr",            0, 0xfc000000, 0x7c000000, 0 }, \
-  { 0 } \
-}
-#endif
-
-
 #endif /* _CONFIG_H */
diff --git a/sim/ppc/system.c b/sim/ppc/system.c
deleted file mode 100644 (file)
index 25ea8eb..0000000
+++ /dev/null
@@ -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_ */
diff --git a/sim/ppc/table.h b/sim/ppc/table.h
new file mode 100644 (file)
index 0000000..1fe29d2
--- /dev/null
@@ -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);