Latest changes from Andrew
authorMichael Meissner <gnu@the-meissners.org>
Wed, 10 Jan 1996 20:42:29 +0000 (20:42 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Wed, 10 Jan 1996 20:42:29 +0000 (20:42 +0000)
sim/ppc/.Sanitize
sim/ppc/ChangeLog
sim/ppc/Makefile.in
sim/ppc/PROBLEMS [new file with mode: 0644]
sim/ppc/README.psim
sim/ppc/configure.in
sim/ppc/device_table.c
sim/ppc/emul_bugapi.c
sim/ppc/emul_chirp.c
sim/ppc/emul_generic.c
sim/ppc/emul_generic.h [new file with mode: 0644]

index 9a6c7a7..c0984a4 100644 (file)
@@ -28,6 +28,7 @@ COPYING.LIB
 ChangeLog
 Makefile.in
 README.psim
+PROBLEMS
 basics.h
 bits.c
 bits.h
index 2e62ae6..1e022a8 100644 (file)
@@ -1,3 +1,17 @@
+Tue Jan  9 15:10:27 1996  Andrew Cagney  <cagney@highland.com.au>
+
+       * emul_bugapi.c (emul_bugapi_instruction_call) : Make format type
+       correct.
+       * emul_chirp.c (map_over_chirp_note) : Ditto
+       * emul_chirp.c (chirp_emul_test) : Ditto
+       * device_table.c (register_init): Ditto
+
+Tue Jan  9 14:16:26 1996  Andrew Cagney  <cagney@highland.com.au>
+
+       * configure.in: Make disable-sim-switch default.  Switch only
+       useful if using --enable-sim-opcode=ppc-opcode-stupid and then
+       only marginally so.
+
 Mon Jan  8 12:17:22 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * device_table.c (register_init): Make format type correct.
index e5684bb..9e11058 100644 (file)
@@ -417,7 +417,7 @@ distclean realclean: clean
        rm -f TAGS Makefile config.cache config.status config.h stamp-h
 
 maintainer-clean: distclean
-       rm -f *~ ppc-config.h
+       rm -f *~ *.log ppc-config.h core *.core
 
 Makefile: Makefile.in config.status
        CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/sim/ppc/PROBLEMS b/sim/ppc/PROBLEMS
new file mode 100644 (file)
index 0000000..d88daa4
--- /dev/null
@@ -0,0 +1,34 @@
+       See the ChangeLog file looking for lines taged with the word FIXME.
+
+       COREFILE.C: The implementation of corefile.c (defined by
+       corefile.h) isn't the best.  It is intended to be functionaly
+       correct rather than fast.  One option being considered
+       is to add a data cache to reduce the overhead of the most
+       common case of data read/writes.
+
+       HTAB (page) code for OEA model untested.  Some of the vm code
+       instructions unimplemented.
+
+       Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.  The
+       PowerOpen worked until I added the ELF one.
+
+       Missing VEA system calls.
+
+       Missing or commented out instructions.
+
+       64bit target untested.
+
+       64bit host broken.  For instance use of scanf "%x", &long long.
+
+       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.
+
+
index 55136f9..cb34a37 100644 (file)
@@ -1,5 +1,5 @@
 
-               PSIM - model of a PowerPC platform
+               PSIM - model a PowerPC platform
 
     Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>.
 
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 
-This directory contains the program PSIM that implements a model of a
-PowerPC platform.  PSIM can either be built standalone or as part of
-the debugger GDB.
+This directory contains the source code to the program PSIM that
+implements a model of a PowerPC platform.  PSIM can either be built
+standalone or as part of the debugger GDB.
 
 
 What is PSIM?
 
-       PSIM is an ANSI C program that models a PowerPC platform.
-       The platform it implements can vary from:
+       PSIM is an ANSI C program that can be configured to model
+       various PowerPC platforms.
+
+       The platform that is modeled can vary from:
 
                o       A user program environment (UEA) complete
                        with emulated system calls
@@ -34,7 +36,17 @@ What is PSIM?
        to
 
                o       A hardware platform with several processors
-                       interacting with each other and modeled hardware.
+                       interacting with each other and various
+                       modeled hardware devices.
+
+
+Is the source code available?
+
+       Yes.
+
+       The source code to PSIM is available under the terms of
+       the GNU Public Licence.  This allows you to distribute
+       the source code for free but with certain conditions.
 
 
 What motivated PSIM?
@@ -155,31 +167,40 @@ What features does PSIM have?
                
        ENDIAN SUPORT
 
-               PSIM implements all of Big-endian, little-endian
-               and PowerPC little endian (XOR endian).
+               PSIM implements the PowerPC's big and little (xor
+               endian) modes and correctly simulates code that
+               switches between these two modes.
+
+               In addition, psim can model a true little-endian
+               machine.
 
-       ISA models
+       ISA models (Instruction Set Architecture)
 
-               PSIM includes a model of UEA, VEA and OEA.  This
+               PSIM includes a model of the UEA, VEA and OEA.  This
                inclues the time base registers (VEA) and HTAB
                and BATS (OEA).
 
                In addition, a preliminary model of the 64 bit
-               PowerPC architecture is included.
+               PowerPC architecture is implemented.
 
        Hardware
 
                PSIM's internals are based around the concept
                of a Device Tree.  This tree intentionaly
                resembles that of the Device Tree found in
-               OpenBoot firmware.  Psim is flexable enough
+               OpenBoot firmware.  PSIM is flexable enough
                to allow the user to fully configure the
                actual hardware model from a device tree
-               specification taken from a file.
+               specification that is read in from a file.
+
+               A user can either run a program using one of
+               PSIM's built in hardware models specify a
+               custom hardware model that should be simulated.
+
+               A user is also able to quickly add a model
+               of new hardware devices so that they can be
+               included in a custom hardware model.
 
-               PSIM also contains several built in device
-               trees.
-               
        Emulation
 
                PSIM is able (UEA) to emulate UNIX calls
@@ -187,84 +208,97 @@ What features does PSIM have?
                the ROM rom calls found in common firmware
                (OpenBoot and BUGAPI).
 
-       floating point
+       Floating point
 
                Preliminary suport for floating point is included.
                Real kernels don't need floating point.
 
 
-Can PSIM model a CHRP a.k.a. PowerPC Platform machine?
+Is PSIM CHRP Compliant?
+
+       No.
+
+       However, PSIM does include all the hooks that are needed to
+       construct a model of a CHRP compliant platform.
+
+       That is:
+
+               o       OpenBoot client software
+
+               o       OpenPIC interrupt controller
+
+               o       Hooks to implement a RTAS interface
 
-       No. but that is now one of its main objectives. (Did you notice
-       it was written PowerPC Platform instead of PowerPC platform?).
+               o       the ability to add a model of each of the
+                       hardware devices required by a CHRP compliant
+                       desktop.
 
 
 How do I build PSIM?
 
-       To build PSIM you will need the following:
+       To build PSIM you will need the following files:
+
 
        gdb-4.15.tar.gz         From your favorite GNU ftp site.
                                I've also tested psim-951016 with
-                               gdb-4.15.1.
+                               gdb-4.15.1.  If you would prefer
+                               a graphical development environment
+                               then PSIM can also be built with
+                               gdbtk.
 
 
        ftp://ftp.ci.com.au/pub/clayton/README.pim
 
                                This file.
 
+
        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.
 
+
+       ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.tar.gz
+
+                               This contains the psim files proper.
+
+
        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.
-
-
-       Since PSIM is still being developed, from time to time, to meet
-       a specific analysts needsfurther psim snap shots are occasionally
-       made available.  These snapshots may or may not work with GDB-4.15.
-       Several of the more recent snapshots are:
+                               empty files.  You may want to consider
+                               installing gnu's patch.
 
-       ftp://ftp.ci.com.au/pub/clayton/psim-951218.tar.gz
 
-                               Hopefully merges in Michael stuff
-                               with mine,  adds multiple emulations
-                               (OpenBoot and NetBSD),  revamps
-                               inline stuff, rearanges devices so
-                               that phandls and ihandles can be
-                               implemented.
+       In addition, I'm slowly building up a set of useful patches
+       to gdb-4.15 that are useful.  You will want to also apply
+       these patches:
 
-       ftp://ftp.ci.com.au/pub/clayton/psim-951203.tar.gz
 
-                               A good snapshot
+       ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+attach.diff.gz
 
-                               This includes extensions from Michael
-                               Meissner that add monitoring of the
-                               PowerPC's register and bus architectures.
+                               Patch to gdb that allows the `attach'
+                               command to be used when connecting to a
+                               simulator.
 
+                               See that file for more information.
 
-       ftp://ftp.ci.com.au/pub/clayton/psim-test-951218.tar.gz
+       ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+note.diff.gz
 
-                               Prebuilt test programs for PSIM.
-                               Includes examples of UEA, VEA and
-                               OEA code.
-                               Requires gcc-2.7.2 and binutils-2.6
-                               to rebuild.
+                               Patch to gdb's bfd that adds basic support
+                               for a .note section. OpenBoot makes
+                               use of a .note section when loading a
+                               boot image.
 
 
        Procedure:
@@ -294,6 +328,15 @@ How do I build PSIM?
                $ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar tvf -
                $ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar xvf -
 
+               You may also want to consider applying the `attach' and
+               `note' patches that are available vis:
+
+               $ gunzip < ../gdb-4.15+attach.diff.gz | more
+               $ gunzip < ../gdb-4.15+attach.diff.gz | patch -p
+
+               $ gunzip < ../gdb-4.15+note.diff.gz | more
+               $ gunzip < ../gdb-4.15+note.diff.gz | patch -p
+
 
        3.      Configure gdb
 
@@ -329,24 +372,97 @@ How do I build PSIM?
                $ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
 
 
+Is there a more recent version of PSIM and if so, how would I build it?
+
+       A PSIM is an ongoing development, occasional snapshots
+       (that include new features) are made available.  Several of
+       the more recent snapshots are:
+
+       ftp://ftp.ci.com.au/pub/clayton/psim-951219.tar.gz
+
+                               Hopefully merges in Michael stuff
+                               with mine,  adds multiple emulations
+                               (OpenBoot and NetBSD),  revamps
+                               inline stuff, rearanges devices so
+                               that phandls and ihandles can be
+                               implemented.
+
+       ftp://ftp.ci.com.au/pub/clayton/psim-951203.tar.gz
+
+                               A good snapshot
+
+                               This includes extensions from Michael
+                               Meissner that add monitoring of the
+                               PowerPC's register and bus architectures.
+
+
+       To build/install one of these snapshots, you replace the
+       current gdb/sim/ppc directory with the one in the update,
+       re-configure and rebuild.
+
+       Procedure:
+
+       0.      A starting point
+
+               $ cd gdb-4.15
+
+
+       1.      Remove the old psim directory
+
+               $ mv sim/ppc sim/old.ppc
+
+
+       2.      Unpack the new one
+
+               $ gunzip < ../psim-960105.tar.gz | tar tf -
+               $ gunzip < ../psim-960105.tar.gz | tar tf -
+
+
+       3.      Reconfig/rebuild (as seen above):
+
+               $ CC=gcc ./configure --target=powerpc-unknown-eabisim
+               $ make CC=gcc
+
+
+Are there any example programs that can be run on PSIM?
+
+       Psim has a simple test suite that is used to ensure
+       that fixes do not introduce new bugs.  This test suite
+       like psim is updated:
+
+       ftp://ftp.ci.com.au/pub/clayton/psim-test-951218.tar.gz
+
+                               Prebuilt test programs for PSIM.
+                               Includes examples of UEA, VEA and
+                               OEA code.
+                               Requires gcc-2.7.2 and binutils-2.6
+                               to rebuild.
+
+       ftp://ftp.ci.com.au/pub/clayton/psim-test-951016.tar.gz
+
+                               (Optional) A scattering of pre-compiled
+                               programs that run under the simulator.
+
+
 How do I use the simulator?
 
 
-       (I assume that you've unpacked the psim-test archive).
+       I assume that you've unpacked a psim-test archive.
+
 
        1.      As a standalone program
 
                Print out the users environment:
 
-               $ powerpc-unknown-eabisim-run envp
+               $ powerpc-unknown-eabisim-run psim-test/uea/envp
 
                Print out the arguments:
 
-               $ powerpc-unknown-eabisim-run argv a b c
+               $ powerpc-unknown-eabisim-run psim-test/uea/argv a b c
 
                Check that sbrk works:
 
-               $ powerpc-unknown-eabisim-run break
+               $ powerpc-unknown-eabisim-run psim-test/uea/break
 
 
        2.      Example of running GDB: 
@@ -354,7 +470,7 @@ How do I use the simulator?
                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
+               $ powerpc-unknown-eabisim-gdb psim-test/uea/envp
                (gdb) target sim
                (gdb) load
                (gdb) break main
@@ -364,6 +480,21 @@ How do I use the simulator?
                .
 
 
+       3.      Using a device tree as a description of a machine
+               (I assume that you have applied the attach bug).
+
+               $ cd psim-test/tree
+               $ powerpc-unknown-eabisim-gdb
+               (gdb) target sim
+               (gdb) attach device-tree
+               (gdb) run
+
+               or
+
+               $ cd psim-test/tree
+               $ powerpc-unknown-eabisim-run device-tree
+               
+
 Where do I send bugs or report problems?
 
        There is a mailing list (subscribe through majordomo@ci.com.au) (that
@@ -376,40 +507,10 @@ Where do I send bugs or report problems?
        that e-mail list.
 
 
-Are there any known problems?
-
-       See the ChangeLog file looking for lines taged with the word FIXME.
-
-       COREFILE.C: The implementation of corefile.c (defined by
-       corefile.h) isn't the best.  It is intended to be functionaly
-       correct rather than fast.  One option being considered
-       is to add a data cache to reduce the overhead of the most
-       common case of data read/writes.
-
-       HTAB (page) code for OEA model untested.  Some of the vm code
-       instructions unimplemented.
-
-       Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups.  The
-       PowerOpen worked until I added the ELF one.
-
-       Missing VEA system calls.
-
-       Missing or commented out instructions.
-
-       64bit target untested.
-
-       64bit host broken.  For instance use of scanf "%x", &long long.
-
-       Event code for pending events from within signal handlers not
-       finished/tested.
-
-       Better and more devices.
+Does PSIM have any limitations or problems?
 
-       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.
+       See the file PROBLEMS (included in the distribution) for any
+       outstanding issues.
 
 
 Who helped?
index acdb679..9bf61e2 100644 (file)
@@ -73,7 +73,7 @@ AC_ARG_ENABLE(sim-switch,
 esac
 if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
   echo "Setting switch flags = $sim_switch" 6>&1
-fi],[sim_switch="-s";
+fi],[sim_switch="";
 if test x"$silent" != x"yes"; then
   echo "Setting switch flags = $sim_switch" 6>&1
 fi])dnl
index e723085..15ef95a 100644 (file)
@@ -685,7 +685,7 @@ register_init(device *me,
   if (isdigit(name[0]) && name[1] == '.') {
     processor = atol(name);
     name += 2;
-    DTRACE(register, ("%ld.%s=0x%lx\n", (long)name, processor, (unsigned long)value));
+    DTRACE(register, ("%d.%s=0x%lx\n", processor, name, (unsigned long)value));
   }    
   else {
     processor = -1;
index 252c3ce..f325901 100644 (file)
@@ -156,15 +156,15 @@ emul_bugapi_create(device *root,
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     OEA_SYSTEM_CALL_ADDRESS,
-                                    4, 0x1); /*emul-call*/
+                                    4, emul_call_instruction);
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     OEA_SYSTEM_CALL_ADDRESS + 4,
-                                    4, 0x4c000064); /*rfi*/
+                                    4, emul_rfi_instruction);
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     OEA_STALL_CPU_LOOP_ADDRESS,
-                                    4, 0x48000000); /*b .*/
+                                    4, emul_loop_instruction);
       }
       {
        device *init_stack = device_tree_add_found(init, "", "stack");
@@ -204,7 +204,7 @@ emul_bugapi_instruction_call(cpu *processor,
     return 0;
   switch (call_id) {
   case _OUTCHR:
-    printf_filtered("%c", cpu_registers(processor)->gpr[3]);
+    printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]);
     break;
   case _OUTLN:
     printf_filtered("\n");
index 9c20262..9eb3a4e 100644 (file)
@@ -74,11 +74,135 @@ struct _os_emul_data {
   unsigned_word catching_instruction_ea;
   cap *phandles;
   device *root;
+  chirp_services *services;
 };
 
 
+/* Read in the argument list and make the most basic check that number
+   of argumnets are consistent with what was expected */
+
+static int
+chirp_read_args(void *args,
+               int sizeof_args,
+               int n_args,
+               int n_returns,
+               os_emul_data *data,
+               cpu *processor,
+               unsigned_word cia)
+{
+  struct base_args {
+    unsigned32 service;
+    unsigned32 n_args;
+    unsigned32 n_returns;
+  } *base;
+  emul_read_buffer(args, data->arguments,
+                  sizeof_args,
+                  processor, cia);
+  base = (struct base_args*)args;
+  if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) {
+    TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n",
+                         (long)T2H_4(base->n_args),
+                         (long)T2H_4(base->n_returns)));
+    return -1;
+  }
+  return 0;
+}
+
+
 /* OpenBoot emulation functions */
 
+/* client interface */
+
+static int
+chirp_emul_test(os_emul_data *data,
+               cpu *processor,
+               unsigned_word cia)
+{
+  struct test_args {
+    unsigned32 service;
+    unsigned32 n_args;
+    unsigned32 n_returns;
+    /*in*/
+    unsigned32 name; /*string*/
+    /*out*/
+    unsigned32 missing;
+  } args;
+  char name[32];
+  chirp_services *service = data->services;
+  /* read in the arguments */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+    return -1;
+  emul_read_string(name, T2H_4(args.name), sizeof(name),
+                  processor, cia);
+  TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
+  /* see if we know about the service */
+  while (service->name != NULL && strcmp(service->name, name) != 0) {
+    service++;
+  }
+  if (service->name == NULL)
+    args.missing = -1;
+  else
+    args.missing = 0;
+  /* write the arguments back out */
+  TRACE(trace_os_emul, ("test - out - missing=%ld\n",
+                       (long)args.missing));
+  emul_write_buffer(&args, data->arguments,
+                   sizeof(args),
+                   processor, cia);
+  return 0;
+}
+
+
+/* Device tree */
+
+static int
+chirp_emul_peer(os_emul_data *data,
+               cpu *processor,
+               unsigned_word cia)
+{
+  struct peer_args {
+    unsigned32 service;
+    unsigned32 n_args;
+    unsigned32 n_returns;
+    /*in*/
+    unsigned32 phandle;
+    /*out*/
+    unsigned32 sibling_phandle;
+  } args;
+  device *dev;
+  device *sibling_dev = NULL;
+  /* read in the arguments */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+    return -1;
+  dev = cap_internal(data->phandles, args.phandle);
+  TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)T2H_4(args.phandle),
+                       (unsigned long)dev,
+                       (dev == NULL ? "" : device_name(dev))));
+  /* find the peer */
+  if (dev == NULL && args.phandle != 0)
+    return -1;
+  if (args.phandle == 0)
+    sibling_dev = data->root;
+  else
+    sibling_dev = device_sibling(dev);
+  if (sibling_dev == NULL)
+    args.sibling_phandle = 0;
+  else
+    args.sibling_phandle = cap_external(data->phandles, sibling_dev);
+  /* write the arguments back out */
+  TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)T2H_4(args.sibling_phandle),
+                       (unsigned long)sibling_dev,
+                       (sibling_dev == NULL
+                        ? ""
+                        : device_name(sibling_dev))));
+  emul_write_buffer(&args, data->arguments,
+                   sizeof(args),
+                   processor, cia);
+  return 0;
+}
+
 static int
 chirp_emul_child(os_emul_data *data,
                 cpu *processor,
@@ -95,21 +219,15 @@ chirp_emul_child(os_emul_data *data,
   } args;
   device *dev;
   device *child_dev;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("child - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  /* read the arguments in */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  }
-  /* read in the arguments */
   dev = cap_internal(data->phandles, args.phandle);
   TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
                        (unsigned long)T2H_4(args.phandle),
                        (unsigned long)dev,
                        (dev == NULL ? "" : device_name(dev))));
+  /* find a child */
   if (dev == (device*)0)
     return -1;
   child_dev = device_child(dev);
@@ -117,6 +235,7 @@ chirp_emul_child(os_emul_data *data,
     args.child_phandle = 0;
   else
     args.child_phandle = cap_external(data->phandles, child_dev);
+  /* write the result out */
   TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
                        (unsigned long)T2H_4(args.child_phandle),
                        (unsigned long)child_dev,
@@ -128,55 +247,101 @@ chirp_emul_child(os_emul_data *data,
 }
 
 static int
-chirp_emul_exit(os_emul_data *data,
-            cpu *processor,
-            unsigned_word cia)
+chirp_emul_parent(os_emul_data *data,
+                 cpu *processor,
+                 unsigned_word cia)
 {
-  cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+  struct parent_args {
+    unsigned32 service;
+    unsigned32 n_args;
+    unsigned32 n_returns;
+    /*in*/
+    unsigned32 phandle;
+    /*out*/
+    unsigned32 parent_phandle;
+  } args;
+  device *dev;
+  device *parent_dev;
+  /* read the args in */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+    return -1;
+  dev = cap_internal(data->phandles, args.phandle);
+  TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)T2H_4(args.phandle),
+                       (unsigned long)dev,
+                       (dev == NULL ? "" : device_name(dev))));
+  /* find a parent */
+  if (dev == (device*)0)
+    return -1;
+  parent_dev = device_parent(dev);
+  if (parent_dev == NULL)
+    args.parent_phandle = 0;
+  else
+    args.parent_phandle = cap_external(data->phandles, parent_dev);
+  /* return the result */
+  TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)T2H_4(args.parent_phandle),
+                       (unsigned long)parent_dev,
+                       (parent_dev == NULL ? "" : device_name(parent_dev))));
+  emul_write_buffer(&args, data->arguments,
+                   sizeof(args),
+                   processor, cia);
   return 0;
 }
 
 static int
-chirp_emul_finddevice(os_emul_data *data,
+chirp_emul_instance_to_package(os_emul_data *data,
+                              cpu *processor,
+                              unsigned_word cia)
+{
+  error("chirp: instance-to-package unimplemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_getproplen(os_emul_data *data,
                      cpu *processor,
                      unsigned_word cia)
 {
-  struct finddevice_args {
+  struct getproplen_args {
     unsigned32 service;
     unsigned32 n_args;
     unsigned32 n_returns;
     /*in*/
-    unsigned32 device_specifier;
-    /*out*/
     unsigned32 phandle;
+    unsigned32 name;
+    /*out*/
+    unsigned32 proplen;
   } args;
-  char device_specifier[1024];
+  char name[32];
   device *dev;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("finddevice - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  const device_property *prop;
+  /* read the args in */
+  if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
     return -1;
-  }
-  emul_read_string(device_specifier,
-                  T2H_4(args.device_specifier),
-                  sizeof(device_specifier),
-                  processor, cia);
-  TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
-                       device_specifier));
-  dev = device_tree_find_device(data->root,
-                               device_specifier);
+  dev = cap_internal(data->phandles, args.phandle);
+  /* find our prop and get its length */
   if (dev == (device*)0)
-    args.phandle = -1;
-  else
-    args.phandle = cap_external(data->phandles, dev);
-  TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
+    return -1;
+  emul_read_string(name,
+                  T2H_4(args.name),
+                  sizeof(name),
+                  processor, cia);
+  TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
                        (unsigned long)T2H_4(args.phandle),
                        (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
+                       (dev == NULL ? "" : device_name(dev)),
+                       name));
+  prop = device_find_property(dev, name);
+  if (prop == (device_property*)0) {
+    args.proplen = -1;
+  }
+  else {
+    args.proplen = H2T_4(prop->sizeof_array);
+  }
+  /* return the result */
+  TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
+                       (unsigned long)T2H_4(args.proplen)));
   emul_write_buffer(&args, data->arguments,
                    sizeof(args),
                    processor, cia);
@@ -203,16 +368,9 @@ chirp_emul_getprop(os_emul_data *data,
   char name[32];
   device *dev;
   const device_property *prop;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("getprop - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  /* read in the args */
+  if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
     return -1;
-  }
-  /* read in the arguments */
   dev = cap_internal(data->phandles, args.phandle);
   emul_read_string(name,
                   T2H_4(args.name),
@@ -225,6 +383,7 @@ chirp_emul_getprop(os_emul_data *data,
                        name,
                        (unsigned long)T2H_4(args.buf),
                        (unsigned long)T2H_4(args.buflen)));
+  /* get the property */
   if (dev == (device*)0)
     return -1;
   prop = device_find_property(dev, name);
@@ -248,6 +407,7 @@ chirp_emul_getprop(os_emul_data *data,
   default:
     break;
   }
+  /* write back the result */
   TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
                        (unsigned long)T2H_4(args.size)));
   emul_write_buffer(&args, data->arguments,
@@ -257,54 +417,69 @@ chirp_emul_getprop(os_emul_data *data,
 }
 
 static int
-chirp_emul_getproplen(os_emul_data *data,
+chirp_emul_nextprop(os_emul_data *data,
+                   cpu *processor,
+                   unsigned_word cia)
+{
+  error("chirp: nextprop not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_setprop(os_emul_data *data,
+                  cpu *processor,
+                  unsigned_word cia)
+{
+  error("chirp: setprop not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_canon(os_emul_data *data,
+                 cpu *processor,
+                 unsigned_word cia)
+{
+  error("chirp: canon not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_finddevice(os_emul_data *data,
                      cpu *processor,
                      unsigned_word cia)
 {
-  struct getproplen_args {
+  struct finddevice_args {
     unsigned32 service;
     unsigned32 n_args;
     unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
-    unsigned32 name;
+    unsigned32 device_specifier;
     /*out*/
-    unsigned32 proplen;
+    unsigned32 phandle;
   } args;
-  char name[32];
+  char device_specifier[1024];
   device *dev;
-  const device_property *prop;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 2 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("getproplen - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  /* get the args */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  }
-  /* read in the arguments */
-  dev = cap_internal(data->phandles, args.phandle);
-  if (dev == (device*)0)
-    return -1;
-  emul_read_string(name,
-                  T2H_4(args.name),
-                  sizeof(name),
+  emul_read_string(device_specifier,
+                  T2H_4(args.device_specifier),
+                  sizeof(device_specifier),
                   processor, cia);
-  TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
+  TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
+                       device_specifier));
+  /* find the device */
+  dev = device_tree_find_device(data->root,
+                               device_specifier);
+  if (dev == (device*)0)
+    args.phandle = -1;
+  else
+    args.phandle = cap_external(data->phandles, dev);
+  /* return its phandle */
+  TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
                        (unsigned long)T2H_4(args.phandle),
                        (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev)),
-                       name));
-  prop = device_find_property(dev, name);
-  if (prop == (device_property*)0) {
-    args.proplen = -1;
-  }
-  else {
-    args.proplen = H2T_4(prop->sizeof_array);
-  }
-  TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
-                       (unsigned long)T2H_4(args.proplen)));
+                       (dev == NULL ? "" : device_name(dev))));
   emul_write_buffer(&args, data->arguments,
                    sizeof(args),
                    processor, cia);
@@ -312,6 +487,36 @@ chirp_emul_getproplen(os_emul_data *data,
 }
 
 static int
+chirp_emul_instance_to_path(os_emul_data *data,
+                           cpu *processor,
+                           unsigned_word cia)
+{
+  error("chirp: instance_to_path not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_package_to_path(os_emul_data *data,
+                           cpu *processor,
+                           unsigned_word cia)
+{
+  error("chirp: package_to_path not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_call_method(os_emul_data *data,
+                           cpu *processor,
+                           unsigned_word cia)
+{
+  error("chirp: call-method implemented\n");
+  return 0;
+}
+
+
+/* Device I/O */
+
+static int
 chirp_emul_open(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
@@ -326,24 +531,19 @@ chirp_emul_open(os_emul_data *data,
     unsigned32 ihandle;
   } args;
   char name[1024];
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("open - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  /* read the args */
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  }
-  /* read in the arguments */
   emul_read_string(name,
                   T2H_4(args.device_specifier),
                   sizeof(name),
                   processor, cia);
   TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
                        name));
+  /* open the device */
   printf_filtered("OpenBoot - open unimplemented for %s\n", name);
   args.ihandle = -1;
+  /* return the ihandle result */
   TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
                        (unsigned long)T2H_4(args.ihandle)));
   emul_write_buffer(&args, data->arguments,
@@ -353,98 +553,59 @@ chirp_emul_open(os_emul_data *data,
 }
 
 static int
-chirp_emul_parent(os_emul_data *data,
-                 cpu *processor,
-                 unsigned_word cia)
+chirp_emul_close(os_emul_data *data,
+                cpu *processor,
+                unsigned_word cia)
 {
-  struct parent_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
-    /*in*/
-    unsigned32 phandle;
-    /*out*/
-    unsigned32 parent_phandle;
-  } args;
-  device *dev;
-  device *parent_dev;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("parent - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
-    return -1;
-  }
-  /* read in the arguments */
-  dev = cap_internal(data->phandles, args.phandle);
-  TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
-  if (dev == (device*)0)
-    return -1;
-  parent_dev = device_parent(dev);
-  if (parent_dev == NULL)
-    args.parent_phandle = 0;
-  else
-    args.parent_phandle = cap_external(data->phandles, parent_dev);
-  TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.parent_phandle),
-                       (unsigned long)parent_dev,
-                       (parent_dev == NULL ? "" : device_name(parent_dev))));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+  error("chirp: close not implemented\n");
   return 0;
 }
 
 static int
-chirp_emul_peer(os_emul_data *data,
+chirp_emul_read(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  struct peer_args {
+  struct read_args {
     unsigned32 service;
     unsigned32 n_args;
     unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
+    unsigned32 ihandle;
+    unsigned32 addr;
+    unsigned32 len;
     /*out*/
-    unsigned32 sibling_phandle;
+    unsigned32 actual;
   } args;
-  device *dev;
-  device *sibling_dev = NULL;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("peer - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  char buf[1024];
+  int actual;
+  /* read the args */
+  if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
     return -1;
+  TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)T2H_4(args.addr),
+                       (unsigned long)T2H_4(args.len)));
+  /* do the read */
+  actual = T2H_4(args.len);
+  if (actual >= sizeof(buf))
+    actual = sizeof(buf) - 1;
+  actual = read(BE2H_4(args.ihandle), buf, actual);
+  if (actual >= 0) {
+    emul_write_buffer(buf,
+                     T2H_4(args.addr),
+                     actual,
+                     processor, cia);
+    args.actual = H2T_4(actual);
+    buf[actual] = '\0';
   }
-  /* read in the arguments */
-  dev = cap_internal(data->phandles, args.phandle);
-  TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
-  if (dev == NULL && args.phandle != 0)
-    return -1;
-  if (args.phandle == 0)
-    sibling_dev = data->root;
-  else
-    sibling_dev = device_sibling(dev);
-  if (sibling_dev == NULL)
-    args.sibling_phandle = 0;
-  else
-    args.sibling_phandle = cap_external(data->phandles, sibling_dev);
-  TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.sibling_phandle),
-                       (unsigned long)sibling_dev,
-                       (sibling_dev == NULL ? "" : device_name(sibling_dev))));
+  else {
+    args.actual = 0;
+  }
+  /* return the result */
+  TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
+                       (long)T2H_4(args.actual),
+                       (actual >= 0 ? buf : "")));
   emul_write_buffer(&args, data->arguments,
                    sizeof(args),
                    processor, cia);
@@ -452,11 +613,11 @@ chirp_emul_peer(os_emul_data *data,
 }
 
 static int
-chirp_emul_read(os_emul_data *data,
+chirp_emul_write(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  struct read_args {
+  struct write_args {
     unsigned32 service;
     unsigned32 n_args;
     unsigned32 n_returns;
@@ -469,16 +630,9 @@ chirp_emul_read(os_emul_data *data,
   } args;
   char buf[1024];
   int actual;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("read - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
+  /* get the args */
+  if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
     return -1;
-  }
-  /* read in the arguments */
   actual = T2H_4(args.len);
   if (actual >= sizeof(buf))
     actual = sizeof(buf) - 1;
@@ -487,12 +641,16 @@ chirp_emul_read(os_emul_data *data,
                   actual,
                   processor, cia);
   buf[actual] = '\0';
-  /* read it in */
-  TRACE(trace_os_emul, ("read - in - ihandle=0x%lx `%s' (%ld)\n",
+  TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
                        (unsigned long)args.ihandle, buf, (long)actual));
-  read(BE2H_4(args.ihandle), buf, actual);
-  args.actual = H2T_4(actual);
-  TRACE(trace_os_emul, ("read - out - actual=%ld\n",
+  /* write it out */
+  actual = write(BE2H_4(args.ihandle), buf, actual);
+  if (actual < 0)
+    args.actual = 0;
+  else
+    args.actual = H2T_4(actual);
+  /* return the result */
+  TRACE(trace_os_emul, ("write - out - actual=%ld\n",
                        (long)T2H_4(args.actual)));
   emul_write_buffer(&args, data->arguments,
                    sizeof(args),
@@ -501,48 +659,130 @@ chirp_emul_read(os_emul_data *data,
 }
 
 static int
-chirp_emul_write(os_emul_data *data,
+chirp_emul_seek(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  struct write_args {
+  error("chirp: seek not implemented\n");
+  return 0;
+}
+
+
+/* memory */
+
+static int
+chirp_emul_claim(os_emul_data *data,
+                cpu *processor,
+                unsigned_word cia)
+{
+  error("chirp: claim not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_release(os_emul_data *data,
+                  cpu *processor,
+                  unsigned_word cia)
+{
+  error("chirp: release not implemented\n");
+  return 0;
+}
+
+
+/* Control transfer */
+
+static int
+chirp_emul_boot(os_emul_data *data,
+               cpu *processor,
+               unsigned_word cia)
+{
+  error("chirp: boot not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_enter(os_emul_data *data,
+                cpu *processor,
+                unsigned_word cia)
+{
+  error("chirp: enter not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_exit(os_emul_data *data,
+               cpu *processor,
+               unsigned_word cia)
+{
+  cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+  return 0;
+}
+
+static int
+chirp_emul_chain(os_emul_data *data,
+                cpu *processor,
+                unsigned_word cia)
+{
+  error("chirp: chain not implemented\n");
+  return 0;
+}
+
+
+/* user interface */
+
+static int
+chirp_emul_interpret(os_emul_data *data,
+                    cpu *processor,
+                    unsigned_word cia)
+{
+  error("chirp: interpret not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_set_callback(os_emul_data *data,
+                       cpu *processor,
+                       unsigned_word cia)
+{
+  error("chirp: set_callback not implemented\n");
+  return 0;
+}
+
+static int
+chirp_emul_set_symbol_lookup(os_emul_data *data,
+                            cpu *processor,
+                            unsigned_word cia)
+{
+  error("chirp: set_symbol_lookup not implemented\n");
+  return 0;
+}
+
+
+/* Time */
+
+static int
+chirp_emul_milliseconds(os_emul_data *data,
+                       cpu *processor,
+                       unsigned_word cia)
+{
+  struct test_args {
     unsigned32 service;
     unsigned32 n_args;
     unsigned32 n_returns;
     /*in*/
-    unsigned32 ihandle;
-    unsigned32 addr;
-    unsigned32 len;
     /*out*/
-    unsigned32 actual;
+    unsigned32 ms;
   } args;
-  char buf[1024];
-  int actual;
-  emul_read_buffer(&args, data->arguments,
-                  sizeof(args),
-                  processor, cia);
-  if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
-    TRACE(trace_os_emul, ("write - invalid nr - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(args.n_args),
-                         (long)T2H_4(args.n_returns)));
-    return -1;
-  }
+  unsigned64 time;
   /* read in the arguments */
-  actual = T2H_4(args.len);
-  if (actual >= sizeof(buf))
-    actual = sizeof(buf) - 1;
-  emul_read_buffer(buf,
-                  T2H_4(args.addr),
-                  actual,
-                  processor, cia);
-  buf[actual] = '\0';
-  /* write it out */
-  TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
-                       (unsigned long)args.ihandle, buf, (long)actual));
-  write(BE2H_4(args.ihandle), buf, actual);
-  args.actual = H2T_4(actual);
-  TRACE(trace_os_emul, ("write - out - actual=%ld\n",
-                       (long)T2H_4(args.actual)));
+  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+    return -1;
+  /* make up a number */
+  time = event_queue_time(cpu_event_queue(processor)) / 1000000;
+  args.ms = H2T_4(time);
+  /* write the arguments back out */
+  TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
+                       (unsigned long)T2H_4(args.ms)));
   emul_write_buffer(&args, data->arguments,
                    sizeof(args),
                    processor, cia);
@@ -550,17 +790,54 @@ chirp_emul_write(os_emul_data *data,
 }
 
 
-chirp_services services[] = {
+
+
+static chirp_services services[] = {
+
+  /* client interface */
+  { "test", chirp_emul_test },
+
+  /* device tree */
+  { "peer", chirp_emul_peer },
   { "child", chirp_emul_child },
-  { "exit", chirp_emul_exit },
-  { "finddevice", chirp_emul_finddevice },
-  { "getprop", chirp_emul_getprop },
+  { "parent", chirp_emul_parent },
+  { "instance-to-package", chirp_emul_instance_to_package },
   { "getproplen", chirp_emul_getproplen },
+  { "getprop", chirp_emul_getprop },
+  { "nextprop", chirp_emul_nextprop },
+  { "setprop", chirp_emul_setprop },
+  { "canon", chirp_emul_canon },
+  { "finddevice", chirp_emul_finddevice },
+  { "instance-to-path", chirp_emul_instance_to_path },
+  { "package-to-path", chirp_emul_package_to_path },
+  { "call-method", chirp_emul_call_method },
+
+  /* device I/O */
   { "open", chirp_emul_open },
-  { "parent", chirp_emul_parent },
-  { "peer", chirp_emul_peer },
+  { "close", chirp_emul_close },
   { "read", chirp_emul_read },
   { "write", chirp_emul_write },
+  { "seek", chirp_emul_seek },
+  { "write", chirp_emul_write },
+
+  /* memory */
+  { "claim", chirp_emul_claim },
+  { "release", chirp_emul_release },
+
+  /* control transfer */
+  { "boot", chirp_emul_boot },
+  { "enter", chirp_emul_enter },
+  { "exit", chirp_emul_exit },
+  { "chain", chirp_emul_chain },
+
+  /* user interface */
+  { "interpret", chirp_emul_interpret },
+  { "set_callback", chirp_emul_set_callback },
+  { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
+
+  /* time */
+  { "milliseconds", chirp_emul_milliseconds },
+
   { 0, /* sentinal */ },
 };
 
@@ -613,18 +890,33 @@ map_over_chirp_note(bfd *image,
       return;
     note->found = 1;
     /* check the name field */
-    if (head.namesz > sizeof(name))
+    if (head.namesz > sizeof(name)) {
+      printf_filtered("open-boot warning: note name too long (%ld)\n",
+                     (long)head.namesz);
       return;
+    }
     if (!bfd_get_section_contents(image, sect,
-                                 name, sizeof(head), head.namesz))
+                                 name, sizeof(head), head.namesz)) {
+      printf_filtered("open-boot warning: note name unreadable\n");
       return;
-    if (strcmp(name, "PowerPC") != 0)
+    }
+    if (strcmp(name, "PowerPC") != 0) {
+      printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
+                     name);
       return;
+    }
     /* get the contents */
+    if (head.descsz != sizeof(note->desc)) {
+      printf_filtered("open-boot warning: note descriptor of wrong size\n");
+      return;
+    }
     if (!bfd_get_section_contents(image, sect,
-                                 &note->desc, sizeof(head) + head.namesz,
-                                 head.descsz))
+                                 &note->desc, /* page align start */
+                                 ((sizeof(head) + head.namesz) + 3) & ~3,
+                                 head.descsz)) {
+      printf_filtered("open-boot warning: note descriptor unreadable\n");
       return;
+    }
     note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
     note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
     note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
@@ -753,18 +1045,25 @@ emul_chirp_create(device *root,
        device_add_integer_property(init_register,
                                    "r5",
                                    code_client_va);
+       /* client interface */
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     code_ra + (code_client_va - code_va),
-                                    4, 0x1); /*emul-call*/
+                                    4, emul_call_instruction);
+       device_tree_add_found_uw_u_u(init, "",
+                                    "data",
+                                    code_ra + (code_client_va - code_va) + 4,
+                                    4, emul_blr_instruction);
+       /* callback return address */
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     code_ra + (code_callback_va - code_va),
-                                    4, 0x1); /*emul-call*/
+                                    4, emul_call_instruction);
+       /* loop to keep other processors busy */
        device_tree_add_found_uw_u_u(init, "",
                                     "data",
                                     code_ra + (code_loop_va - code_va),
-                                    4, 0x48000000); /*b .*/
+                                    4, emul_loop_instruction);
        device_add_integer_property(init_register,
                                    "msr",
                                    (msr_machine_check_enable
@@ -843,6 +1142,7 @@ emul_chirp_create(device *root,
     data->catching_instruction_ea = code_callback_va;
     data->phandles = cap_create("chirp");
     data->root = root;
+    data->services = services;
     return data;
   }
 }
@@ -923,9 +1223,7 @@ emul_chirp_instruction_call(cpu *processor,
 
   }
 
-  /* return to caller */
-  cpu_registers(processor)->gpr[3] = result;
-  cpu_restart(processor, emul_data->return_address);
+  /* return to caller - instruction following this is a function return */
   return 1;
 }
 
index f764205..8f8ae09 100644 (file)
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  
-    ----
-
-    Code to output system call traces Copyright (C) 1991 Gordon Irlam.
-    All rights reserved.
-
-    This tool is part of the Spa(7) package.  The Spa(7) package
-    may  be redistributed and/or modified under the terms of the
-    GNU General Public License Version 2 (GPL(7))  as  published
-    by the Free Software Foundation.
-
     */
 
 
 #endif
 
 
-INLINE_EMUL_GENERIC void
-emul_enter_call(emulation *emul,
-               int call,
-               int arg0,
-               cpu *processor,
-               unsigned_word cia)
+STATIC_INLINE_EMUL_GENERIC void
+emul_syscall_enter(emul_syscall *emul,
+                  int call,
+                  int arg0,
+                  cpu *processor,
+                  unsigned_word cia)
 {
-  printf_filtered("%d:0x%x:%s(",
+  printf_filtered("%d:0x%lx:%s(",
                  cpu_nr(processor) + 1,
-                 cia, 
-                 emul->call_descriptor[call].name);
+                 (long)cia, 
+                 emul->syscall_descriptor[call].name);
 }
 
 
-INLINE_EMUL_GENERIC void
-emul_exit_call(emulation *emul,
-              int call,
-              int arg0,
-              cpu *processor,
-              unsigned_word cia)
+STATIC_INLINE_EMUL_GENERIC void
+emul_syscall_exit(emul_syscall *emul,
+                 int call,
+                 int arg0,
+                 cpu *processor,
+                 unsigned_word cia)
 {
   int status = cpu_registers(processor)->gpr[3];
   int error = cpu_registers(processor)->gpr[0];
   printf_filtered(")=%d", status);
   if (error > 0 && error < emul->nr_error_names)
-    printf_filtered("[%s]",
-                   emul->error_names[cpu_registers(processor)->gpr[0]]);
+    printf_filtered("[%s]", emul->error_names[error]);
   printf_filtered("\n");
 }
 
@@ -117,12 +106,9 @@ emul_read_string(char *dest,
   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;
+    dest[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
+                                       addr + nr_moved,
+                                       processor, cia);
     if (dest[nr_moved] == '\0' || nr_moved >= nr_bytes)
       break;
     nr_moved++;
@@ -145,24 +131,27 @@ emul_write_status(cpu *processor,
 }
 
 
+INLINE_EMUL_GENERIC unsigned_word
+emul_read_word(unsigned_word addr,
+              cpu *processor,
+              unsigned_word cia)
+{
+  return vm_data_map_read_word(cpu_data_map(processor),
+                              addr,
+                              processor, cia);
+}
+
+
 INLINE_EMUL_GENERIC void
 emul_write_word(unsigned_word addr,
                unsigned_word buf,
                cpu *processor,
                unsigned_word cia)
 {
-  int nr_moved;
-  H2T(buf);
-  nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
-                                     &buf,
-                                     addr,
-                                     sizeof(buf),
-                                     0/*violate_ro*/);
-  if (nr_moved != sizeof(buf)) {
-    printf_filtered("emul_write_word() write failed, %d out of %d written\n",
-                   nr_moved, sizeof(buf));
-    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
-  }
+  vm_data_map_write_word(cpu_data_map(processor),
+                        addr,
+                        buf,
+                        processor, cia);
 }
 
 
@@ -173,15 +162,12 @@ emul_write_buffer(const void *source,
                  cpu *processor,
                  unsigned_word cia)
 {
-  int nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
-                                         source,
-                                         addr,
-                                         nr_bytes,
-                                         0/*violate_ro*/);
-  if (nr_moved != nr_bytes) {
-    printf_filtered("emul_write_buffer() write failed %d out of %d written\n",
-                   nr_moved, nr_bytes);
-    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+  int nr_moved;
+  for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
+    vm_data_map_write_1(cpu_data_map(processor),
+                       addr + nr_moved,
+                       ((const char*)source)[nr_moved],
+                       processor, cia);
   }
 }
 
@@ -193,38 +179,39 @@ emul_read_buffer(void *dest,
                 cpu *processor,
                 unsigned_word cia)
 {
-  int nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
-                                        dest,
-                                        addr,
-                                        nr_bytes);
-  if (nr_moved != nr_bytes) {
-    printf_filtered("emul_read_buffer() read failed %d out of %d read\n",
-                   nr_moved, nr_bytes);
-    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+  int nr_moved;
+  for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
+    ((char*)dest)[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
+                                                addr + nr_moved,
+                                                processor, cia);
   }
 }
 
 
 INLINE_EMUL_GENERIC void
-emul_do_call(emulation *emul,
-            unsigned call,
-            const int arg0,
-            cpu *processor,
-            unsigned_word cia)
+emul_do_system_call(os_emul_data *emul_data,
+                   emul_syscall *emul,
+                   unsigned call,
+                   const int arg0,
+                   cpu *processor,
+                   unsigned_word cia)
 {
-  emul_call_handler *handler = NULL;
+  emul_syscall_handler *handler = NULL;
   if (call >= emul->nr_system_calls)
     error("do_call() os_emul call %d out-of-range\n", call);
 
-  handler = emul->call_descriptor[call].handler;
+  handler = emul->syscall_descriptor[call].handler;
   if (handler == NULL)
     error("do_call() unimplemented call %d\n", call);
 
-  ENTER_CALL;
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    emul_syscall_enter(emul, call, arg0, processor, cia);
+
   cpu_registers(processor)->gpr[0] = 0; /* default success */
-  handler(emul, call, arg0, processor, cia);
-  EXIT_CALL;
-}
+  handler(emul_data, call, arg0, processor, cia);
 
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    emul_syscall_exit(emul, call, arg0, processor, cia);
+}
 
 #endif /* _SYSTEM_C_ */
diff --git a/sim/ppc/emul_generic.h b/sim/ppc/emul_generic.h
new file mode 100644 (file)
index 0000000..ee8f076
--- /dev/null
@@ -0,0 +1,158 @@
+/*  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 _EMUL_GENERIC_H_
+#define _EMUL_GENERIC_H_
+
+#include "cpu.h"
+#include "idecode.h"
+#include "os_emul.h"
+
+#include "bfd.h"
+
+#ifndef INLINE_EMUL_GENERIC
+#define INLINE_EMUL_GENERIC
+#endif
+
+/* various PowerPC instructions for writing into memory */
+enum {
+  emul_call_instruction = 0x1,
+  emul_loop_instruction = 0x48000000, /* branch to . */
+  emul_rfi_instruction = 0x4c000064,
+  emul_blr_instruction = 0x4e800020,
+};
+
+
+/* emulation specific data */
+
+typedef struct _os_emul_data os_emul_data;
+
+typedef os_emul_data *(os_emul_create_handler)
+     (device *tree,
+      bfd *image,
+      const char *emul_name);
+typedef void (os_emul_init_handler)
+     (os_emul_data *emul_data,
+      int nr_cpus);
+typedef void (os_emul_system_call_handler)
+     (cpu *processor,
+      unsigned_word cia,
+      os_emul_data *emul_data);
+typedef int (os_emul_instruction_call_handler)
+     (cpu *processor,
+      unsigned_word cia,
+      unsigned_word ra,
+      os_emul_data *emul_data);
+
+struct _os_emul {
+  const char *name;
+  os_emul_create_handler *create;
+  os_emul_init_handler *init;
+  os_emul_system_call_handler *system_call;
+  os_emul_instruction_call_handler *instruction_call;
+  os_emul_data *data;
+};
+
+
+/* One class of emulation - system call is pretty general, provide a
+   common template for implementing this */
+
+typedef struct _emul_syscall emul_syscall;
+typedef struct _emul_syscall_descriptor emul_syscall_descriptor;
+
+typedef void (emul_syscall_handler)
+     (os_emul_data *emul_data,
+      unsigned call,
+      const int arg0,
+      cpu *processor,
+      unsigned_word cia);
+
+struct _emul_syscall_descriptor {
+  emul_syscall_handler *handler;
+  const char *name;
+};
+
+struct _emul_syscall {
+  emul_syscall_descriptor *syscall_descriptor;
+  int nr_system_calls;
+  char **error_names;
+  int nr_error_names;
+  char **signal_names;
+  int nr_signal_names;
+};
+
+
+INLINE_EMUL_GENERIC void emul_do_system_call
+(os_emul_data *emul_data,
+ emul_syscall *syscall,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia);
+
+
+INLINE_EMUL_GENERIC unsigned64 emul_read_gpr64
+(cpu *processor,
+ int g);
+
+INLINE_EMUL_GENERIC void emul_write_gpr64
+(cpu *processor,
+ int g,
+ unsigned64 val);
+
+INLINE_EMUL_GENERIC void emul_write_status
+(cpu *processor,
+ int status,
+ int errno);
+
+INLINE_EMUL_GENERIC char *emul_read_string
+(char *dest,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC unsigned_word emul_read_word
+(unsigned_word addr,
+ cpu *processor,
+ unsigned_word cia);
+INLINE_EMUL_GENERIC void emul_write_word
+(unsigned_word addr,
+ unsigned_word buf,
+ cpu *processor,
+ unsigned_word cia);
+INLINE_EMUL_GENERIC void emul_read_buffer
+(void *dest,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC void emul_write_buffer
+(const void *source,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+#endif /* _EMUL_GENERIC_H_ */