Fix TCL error in gdb.python/py-format-string.exp.
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
index 03b57fea4393ec91bb766ef9a101d9354cf11523..3e322e3820f83830d5076cf46fe7e69ee48804b8 100644 (file)
@@ -1,10 +1,10 @@
 /*  This file is part of the program psim.
 
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
 
     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
 
     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
+    the Free Software Foundation; either version 3 of the License, or
     (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
     (at your option) any later version.
 
     This program is distributed in the hope that it will be useful,
@@ -13,8 +13,7 @@
     GNU General Public License for more details.
  
     You should have received a copy of the GNU General Public License
     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.
+    along with this program; if not, see <http://www.gnu.org/licenses/>.
  
     */
 
  
     */
 
 #ifndef _PSIM_C_
 #define _PSIM_C_
 
 #ifndef _PSIM_C_
 #define _PSIM_C_
 
+#include "cpu.h" /* includes psim.h */
+#include "idecode.h"
+#include "options.h"
+
+#include "tree.h"
+
+#include <signal.h>
+
 #include <stdio.h>
 #include <ctype.h>
 
 #include <stdio.h>
 #include <ctype.h>
 
-#include "config.h"
-#include "ppc-config.h"
-#include "inline.h"
-
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
-#ifndef STATIC_INLINE_PSIM
-#define STATIC_INLINE_PSIM STATIC_INLINE
-#endif
-
 #include <setjmp.h>
 
 #include <setjmp.h>
 
-#include "cpu.h" /* includes psim.h */
-#include "idecode.h"
-
 #ifdef HAVE_STRING_H
 #include <string.h>
 #else
 #ifdef HAVE_STRING_H
 #include <string.h>
 #else
 #endif
 #endif
 
 #endif
 #endif
 
-#include "bfd.h"
-
-
-#include "inline.c"
-
-/* Any starting address less than this is assumed to be an OEA program
-   rather than VEA.  */
-#ifndef OEA_START_ADDRESS
-#define OEA_START_ADDRESS 4096
-#endif
-
-/* Any starting address greater than this is assumed to be an OpenBoot
-   rather than VEA */
-#ifndef OPENBOOT_START_ADDRESS
-#define OPENBOOT_START_ADDRESS 0x80000000
-#endif
-
-#ifndef OEA_MEMORY_SIZE
-#define OEA_MEMORY_SIZE 0x100000
-#endif
 
 
+#include "bfd.h"
+#include "libiberty.h"
+#include "gdb/signals.h"
 
 /* system structure, actual size of processor array determined at
    runtime */
 
 struct _psim {
   event_queue *events;
 
 /* system structure, actual size of processor array determined at
    runtime */
 
 struct _psim {
   event_queue *events;
-  device_tree *devices;
+  device *devices;
   mon *monitor;
   mon *monitor;
+  os_emul *os_emulation;
   core *memory;
   core *memory;
+
   /* escape routine for inner functions */
   void *path_to_halt;
   void *path_to_restart;
   /* escape routine for inner functions */
   void *path_to_halt;
   void *path_to_restart;
+
   /* status from last halt */
   psim_status halt_status;
   /* status from last halt */
   psim_status halt_status;
-  /* the processes proper */
+
+  /* the processors proper */
   int nr_cpus;
   int last_cpu; /* CPU that last (tried to) execute an instruction */
   cpu *processors[MAX_NR_PROCESSORS];
   int nr_cpus;
   int last_cpu; /* CPU that last (tried to) execute an instruction */
   cpu *processors[MAX_NR_PROCESSORS];
@@ -97,308 +80,393 @@ int current_host_byte_order;
 int current_environment;
 int current_alignment;
 int current_floating_point;
 int current_environment;
 int current_alignment;
 int current_floating_point;
+int current_model_issue = MODEL_ISSUE_IGNORE;
+int current_stdio = DO_USE_STDIO;
+model_enum current_model = WITH_DEFAULT_MODEL;
 
 
 
 
-/* create a device tree from the image */
-
-
+/* create the device tree */
 
 
-/* Raw hardware tree:
-
-   A small default set of devices are configured.  Each section of the
-   image is loaded directly into physical memory. */
-
-STATIC_INLINE_PSIM void
-create_hardware_device_tree(bfd *image,
-                           device_tree *root)
+INLINE_PSIM\
+(device *)
+psim_tree(void)
 {
 {
-  char *name;
-  const memory_size = OEA_MEMORY_SIZE;
-
-  /* options */
-  device_tree_add_passthrough(root, "/options");
-  device_tree_add_integer(root, "/options/smp",
-                         MAX_NR_PROCESSORS);
-  device_tree_add_boolean(root, "/options/little-endian?",
-                         !image->xvec->byteorder_big_p);
-  device_tree_add_string(root, "/options/environment-architecture",
-                        "operating");
-  device_tree_add_boolean(root, "/options/strict-alignment?",
-                         (WITH_ALIGNMENT == STRICT_ALIGNMENT
-                          || !image->xvec->byteorder_big_p));
-  device_tree_add_boolean(root, "/options/floating-point?",
-                         WITH_FLOATING_POINT);
-
-  /* hardware */
-  name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  device_tree_add_found_device(root, "/iobus@0x400000");
-  device_tree_add_found_device(root, "/iobus/console@0x000000,16");
-  device_tree_add_found_device(root, "/iobus/halt@0x100000,4");
-  device_tree_add_found_device(root, "/iobus/icu@0x200000,4");
-
-  /* initialization */
-  device_tree_add_passthrough(root, "/init");
-  device_tree_add_found_device(root, "/init/register@pc,0x0");
-  name = printd_c_uw("/init/register", "sp", memory_size);
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  name = printd_c_uw("/init/register", "msr",
-                    (image->xvec->byteorder_big_p
-                     ? 0
-                     : msr_little_endian_mode));
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  /* AJC puts the PC at zero and wants a stack while MM puts it above
-     zero and doesn't. Really there should be no stack *but* this
-     makes testing easier */
-  device_tree_add_found_device(root,
-                              (bfd_get_start_address(image) == 0
-                               ? "/init/stack@elf"
-                               : "/init/stack@none"));
-  name = printd_c("/init/load-binary", bfd_get_filename(image));
-  device_tree_add_found_device(root, name);
-  zfree(name);
+  device *root = tree_parse(NULL, "core");
+  tree_parse(root, "/aliases");
+  tree_parse(root, "/options");
+  tree_parse(root, "/chosen");
+  tree_parse(root, "/packages");
+  tree_parse(root, "/cpus");
+  tree_parse(root, "/openprom");
+  tree_parse(root, "/openprom/init");
+  tree_parse(root, "/openprom/trace");
+  tree_parse(root, "/openprom/options");
+  return root;
 }
 
 }
 
-
-/* Openboot model (under development):
-
-   An extension of the hardware model.  The image is read into memory
-   as a single block.  Sections of the image are then mapped as
-   required using a HTAB. */
-
-STATIC_INLINE_PSIM void
-create_openboot_device_tree(bfd *image,
-                           device_tree *root)
+STATIC_INLINE_PSIM\
+(char *)
+find_arg(char *err_msg,
+        int *ptr_to_argp,
+        char **argv)
 {
 {
-  create_hardware_device_tree(image, root);
+  *ptr_to_argp += 1;
+  if (argv[*ptr_to_argp] == NULL)
+    error(err_msg);
+  return argv[*ptr_to_argp];
 }
 
 }
 
-
-/* User mode model:
-
-   Image sections loaded into virtual addresses as specified.  A
-   (large) stack is reserved (but only allocated as needed). System
-   calls that include suport for heap growth are attached. */
-
-STATIC_INLINE_PSIM void
-create_vea_device_tree(bfd *image,
-                      device_tree *root)
+INLINE_PSIM\
+(void)
+psim_usage (int verbose, int help, SIM_OPEN_KIND kind)
 {
 {
-  unsigned_word top_of_stack;
-  unsigned stack_size;
-  int elf_binary;
-  char *name;
-
-  /* establish a few defaults */
-  if (image->xvec->flavour == bfd_target_elf_flavour) {
-    elf_binary = 1;
-    top_of_stack = 0xe0000000;
-    stack_size =   0x00100000;
+  printf_filtered("Usage:\n");
+  printf_filtered("\n");
+  printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
+  printf_filtered("\n");
+  printf_filtered("Where\n");
+  printf_filtered("\n");
+  printf_filtered("\t<image>         Name of the PowerPC program to run.\n");
+  if (verbose) {
+  printf_filtered("\t                This can either be a PowerPC binary or\n");
+  printf_filtered("\t                a text file containing a device tree\n");
+  printf_filtered("\t                specification.\n");
+  printf_filtered("\t                PSIM will attempt to determine from the\n");
+  printf_filtered("\t                specified <image> the intended emulation\n");
+  printf_filtered("\t                environment.\n");
+  printf_filtered("\t                If PSIM gets it wrong, the emulation\n");
+  printf_filtered("\t                environment can be specified using the\n");
+  printf_filtered("\t                `-e' option (described below).\n");
+  printf_filtered("\n"); }
+  printf_filtered("\t<image-arg>     Argument to be passed to <image>\n");
+  if (verbose) {
+  printf_filtered("\t                These arguments will be passed to\n");
+  printf_filtered("\t                <image> (as standard C argv, argc)\n");
+  printf_filtered("\t                when <image> is started.\n");
+  printf_filtered("\n"); }
+  printf_filtered("\t<psim-option>   See below\n");
+  printf_filtered("\n");
+  printf_filtered("The following are valid <psim-option>s:\n");
+  printf_filtered("\n");
+
+  printf_filtered("\t-c <count>      Limit the simulation to <count> iterations\n");
+  if (verbose) { 
+  printf_filtered("\n");
   }
   }
-  else {
-    elf_binary = 0;
-    top_of_stack = 0x20000000;
-    stack_size =   0x00100000;
+
+  printf_filtered("\t-i or -i2       Print instruction counting statistics\n");
+  if (verbose) { 
+  printf_filtered("\t                Specify -i2 for a more detailed display\n");
+  printf_filtered("\n");
+  }
+
+  printf_filtered("\t-I              Print execution unit statistics\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\t-e <os-emul>    specify an OS or platform to model\n");
+  if (verbose) {
+  printf_filtered("\t                Can be any of the following:\n");
+  printf_filtered("\t                bug - OEA + MOTO BUG ROM calls\n");
+  printf_filtered("\t                netbsd - UEA + NetBSD system calls\n");
+  printf_filtered("\t                solaris - UEA + Solaris system calls\n");
+  printf_filtered("\t                linux - UEA + Linux system calls\n");
+  printf_filtered("\t                chirp - OEA + a few OpenBoot calls\n");
+  printf_filtered("\n"); }
+
+  printf_filtered("\t-E <endian>     Specify the endianness of the target\n");
+  if (verbose) { 
+  printf_filtered("\t                Can be any of the following:\n");
+  printf_filtered("\t                big - big endian target\n");
+  printf_filtered("\t                little - little endian target\n");
+  printf_filtered("\n"); }
+
+  printf_filtered("\t-f <file>       Merge <file> into the device tree\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\t-h -? -H        give more detailed usage\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\t-m <model>      Specify the processor to model (604)\n");
+  if (verbose) {
+  printf_filtered("\t                Selects the processor to use when\n");
+  printf_filtered("\t                modeling execution units.  Includes:\n");
+  printf_filtered("\t                604, 603 and 603e\n");
+  printf_filtered("\n"); }
+
+  printf_filtered("\t-n <nr-smp>     Specify the number of processors in SMP simulations\n");
+  if (verbose) {
+  printf_filtered("\t                Specifies the number of processors that are\n");
+  printf_filtered("\t                to be modeled in a symetric multi-processor (SMP)\n");
+  printf_filtered("\t                simulation\n");
+  printf_filtered("\n"); }
+
+  printf_filtered("\t-o <dev-spec>   Add device <dev-spec> to the device tree\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\t-r <ram-size>   Set RAM size in bytes (OEA environments)\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\t-t [!]<trace>   Enable (disable) <trace> option\n");
+  if (verbose) { printf_filtered("\n"); }
+
+  printf_filtered("\n");
+  trace_usage(verbose);
+  device_usage(verbose);
+  if (verbose > 1) {
+    printf_filtered("\n");
+    print_options();
   }
 
   }
 
-  /* options */
-  device_tree_add_passthrough(root, "/options");
-  device_tree_add_integer(root, "/options/smp", 1); /* always */
-  device_tree_add_boolean(root, "/options/little-endian?",
-                         !image->xvec->byteorder_big_p);
-  device_tree_add_string(root, "/options/environment-architecture",
-                        (WITH_ENVIRONMENT == USER_ENVIRONMENT
-                         ? "user" : "virtual"));
-  device_tree_add_boolean(root, "/options/strict-alignment?",
-                         (WITH_ALIGNMENT == STRICT_ALIGNMENT
-                           || !image->xvec->byteorder_big_p));
-  device_tree_add_boolean(root, "/options/floating-point?",
-                         WITH_FLOATING_POINT);
-
-  /* virtual memory - handles growth of stack/heap */
-  name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size);
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  name = printd_c("/vm/map-binary", bfd_get_filename(image));
-  device_tree_add_found_device(root, name);
-  zfree(name);
-
-  /* finish the init */
-  device_tree_add_passthrough(root, "/init");
-  name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image));
-  device_tree_add_found_device(root, name); /*pc*/
-  zfree(name);
-  name = printd_c_uw("/init/register", "sp", top_of_stack);
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  name = printd_c_uw("/init/register", "msr",
-                    (image->xvec->byteorder_big_p
-                     ? 0
-                     : msr_little_endian_mode));
-  device_tree_add_found_device(root, name);
-  zfree(name);
-  device_tree_add_found_device(root, (elf_binary
-                                     ? "/init/stack@elf"
-                                     : "/init/stack@xcoff"));
+  if (kind == SIM_OPEN_STANDALONE)
+    {
+      if (REPORT_BUGS_TO[0])
+       printf ("Report bugs to %s\n", REPORT_BUGS_TO);
+      exit (help ? 0 : 1);
+    }
 }
 
 }
 
+/* Test "string" for containing a string of digits that form a number
+between "min" and "max".  The return value is the number or "err". */
+static
+int is_num( char *string, int min, int max, int err)
+{
+  int result = 0;
 
 
-/* File device:
+  for ( ; *string; ++string)
+  {
+    if (!isdigit(*string))
+    {
+      result = err;
+      break;
+    }
+    result = result * 10 + (*string - '0');
+  }
+  if (result < min || result > max)
+    result = err;
 
 
-   The file contains lines that specify the describe the device tree
-   to be created, read them in and load them into the tree */
+  return result;
+}
 
 
-STATIC_INLINE_PSIM void
-create_filed_device_tree(const char *file_name,
-                        device_tree *root)
+INLINE_PSIM\
+(char **)
+psim_options(device *root,
+            char **argv,
+            SIM_OPEN_KIND kind)
 {
 {
-  FILE *description = fopen(file_name, "r");
-  int line_nr = 0;
-  char device_path[1000];
-  while (fgets(device_path, sizeof(device_path), description)) {
-    /* check all of line was read */
-    {
-      char *end = strchr(device_path, '\n');
-      if (end == NULL) {
-       fclose(description);
-       error("create_filed_device_tree() line %d to long: %s\n",
-             line_nr, device_path);
-      }
-      line_nr++;
-      *end = '\0';
-    }
-    /* check for leading comment */
-    if (device_path[0] != '/')
-      continue;
-    /* enter it in varying ways */
-    if (strchr(device_path, '@') != NULL) {
-      device_tree_add_found_device(root, device_path);
-    }
-    else {
-      char *space = strchr(device_path, ' ');
-      if (space == NULL) {
-       /* intermediate node */
-       device_tree_add_passthrough(root, device_path);
-      }
-      else if (space[-1] == '?') {
-       /* boolean */
-       *space = '\0';
-       device_tree_add_boolean(root, device_path, space[1] != '0');
-      }
-      else if (isdigit(space[1])) {
-       /* integer */
-       *space = '\0';
-       device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
-      }
-      else if (space[1] == '"') {
-       /* quoted string */
-       char *end = strchr(space+2, '\0');
-       if (end[-1] == '"')
-         end[-1] = '\0';
-       *space = '\0';
-       device_tree_add_string(root, device_path, space + 2);
-      }
-      else {
-       /* any thing else */
-       space = '\0';
-       device_tree_add_string(root, device_path, space + 1);
+  device *current = root;
+  int argp;
+  if (argv == NULL)
+    return NULL;
+  argp = 0;
+  while (argv[argp] != NULL && argv[argp][0] == '-') {
+    char *p = argv[argp] + 1;
+    char *param;
+    while (*p != '\0') {
+      switch (*p) {
+      default:
+       printf_filtered ("Invalid Option: %s\n", argv[argp]);
+       psim_usage (0, 0, kind);
+       return NULL;
+      case 'c':
+       param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
+       tree_parse(root, "/openprom/options/max-iterations %s", param);
+       break;
+      case 'e':
+       param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
+       tree_parse(root, "/openprom/options/os-emul %s", param);
+       break;
+      case 'E':
+       /* endian spec, ignored for now */
+       param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
+       if (strcmp (param, "big") == 0)
+         tree_parse (root, "/options/little-endian? false");
+       else if (strcmp (param, "little") == 0)
+         tree_parse (root, "/options/little-endian? true");
+       else
+         {
+           printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
+           psim_usage (0, 0, kind);
+           return NULL;
+         }
+       break;
+      case 'f':
+       param = find_arg("Missing <file> option for -f\n", &argp, argv);
+       psim_merge_device_file(root, param);
+       break;
+      case 'h':
+      case '?':
+       psim_usage (1, 1, kind);
+       return NULL;
+      case 'H':
+       psim_usage (2, 1, kind);
+       return NULL;
+      case 'i':
+       if (isdigit(p[1])) {
+         tree_parse(root, "/openprom/trace/print-info %c", p[1]);
+         p++;
+       }
+       else {
+         tree_parse(root, "/openprom/trace/print-info 1");
+       }
+       break;
+      case 'I':
+       tree_parse(root, "/openprom/trace/print-info 2");
+       tree_parse(root, "/openprom/options/model-issue %d",
+                  MODEL_ISSUE_PROCESS);
+       break;
+      case 'm':
+       param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
+       tree_parse(root, "/openprom/options/model \"%s", param);
+       break;
+      case 'n':
+       param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
+       tree_parse(root, "/openprom/options/smp %s", param);
+       break;
+      case 'o':
+       param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
+       if (memcmp(param, "mpc860c0", 8) == 0)
+        {
+          if (param[8] == '\0')
+            tree_parse(root, "/options/mpc860c0 5");
+          else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
+          {
+            tree_parse(root, "/options/mpc860c0 %s", param+9);
+          }
+          else error("Invalid mpc860c0 option for -o\n");
+        }
+       else
+          current = tree_parse(current, "%s", param);
+       break;
+      case 'r':
+       param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
+       tree_parse(root, "/openprom/options/oea-memory-size %s",
+                              param);
+       break;
+      case 't':
+       param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
+       if (param[0] == '!')
+         tree_parse(root, "/openprom/trace/%s 0", param+1);
+       else
+         tree_parse(root, "/openprom/trace/%s 1", param);
+       break;
+      case '-':
+       /* it's a long option of the form --optionname=optionvalue.
+          Such options can be passed through if we are invoked by
+          gdb.  */
+       if (strstr(argv[argp], "architecture") != NULL) {
+          /* we must consume the argument here, so that we get out
+             of the loop.  */
+         p = argv[argp] + strlen(argv[argp]) - 1;
+         printf_filtered("Warning - architecture parameter ignored\n");
+        }
+       else if (strcmp (argv[argp], "--help") == 0)
+         {
+           psim_usage (0, 1, kind);
+           return NULL;
+         }
+       else if (strncmp (argv[argp], "--sysroot=",
+                         sizeof ("--sysroot=") - 1) == 0)
+         /* Ignore this option.  */
+         p = argv[argp] + strlen(argv[argp]) - 1;
+       else if (strcmp (argv[argp], "--version") == 0)
+         {
+           extern const char version[];
+           printf ("GNU simulator %s%s\n", PKGVERSION, version);
+           if (kind == SIM_OPEN_STANDALONE)
+             exit (0);
+           else
+             return NULL;
+         }
+       else
+         {
+           printf_filtered ("Invalid option: %s\n", argv[argp]);
+           psim_usage (0, 0, kind);
+           return NULL;
+         }
+       break;
       }
       }
+      p += 1;
     }
     }
+    argp += 1;
+  }
+  /* force the trace node to process its options now *before* the tree
+     initialization occures */
+  device_ioctl(tree_find_device(root, "/openprom/trace"),
+              NULL, 0,
+              device_ioctl_set_trace);
+
+  {
+    void semantic_init(device* root);
+    semantic_init(root);
   }
   }
-  fclose(description);
-}
-
 
 
-/* Given the file containing the `image', create a device tree that
-   defines the machine to be modeled */
+  /* return where the options end */
+  return argv + argp;
+}
 
 
-STATIC_INLINE_PSIM device_tree *
-create_device_tree(const char *file_name,
-                  core *memory)
+INLINE_PSIM\
+(void)
+psim_command(device *root,
+            char **argv)
 {
 {
-  bfd *image;
-  const device *core_device = core_device_create(memory);
-  device_tree *root = device_tree_add_device(NULL, "/", core_device);
-
-  bfd_init(); /* could be redundant but ... */
-
-  /* open the file */
-  image = bfd_openr(file_name, NULL);
-  if (image == NULL) {
-    bfd_perror("open failed:");
-    error("nothing loaded\n");
+  int argp = 0;
+  if (argv[argp] == NULL) {
+    return;
   }
   }
-
-  /* check it is valid */
-  if (!bfd_check_format(image, bfd_object)) {
-    printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
-    printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
-    bfd_close(image);
-    image = NULL;
+  else if (strcmp(argv[argp], "trace") == 0) {
+    const char *opt = find_arg("Missing <trace> option", &argp, argv);
+    if (opt[0] == '!')
+      trace_option(opt + 1, 0);
+    else
+      trace_option(opt, 1);
   }
   }
-
-  /* depending on what was found about the file, load it */
-  if (image != NULL) {
-    if (bfd_get_start_address(image) < OEA_START_ADDRESS) {
-      TRACE(trace_device_tree, ("create_device_tree() - hardware image\n"));
-      create_hardware_device_tree(image, root);
-    }
-    else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) {
-      TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
-      create_vea_device_tree(image, root);
-    }
-    else {
-      TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
-      create_openboot_device_tree(image, root);
-    }
-    bfd_close(image);
+  else if (strcmp(*argv, "change-media") == 0) {
+    char *device = find_arg("Missing device name", &argp, argv);
+    char *media = argv[++argp];
+    device_ioctl(tree_find_device(root, device), NULL, 0,
+                device_ioctl_change_media, media);
   }
   else {
   }
   else {
-    TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
-    create_filed_device_tree(file_name, root);
+    printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
+    printf_filtered("    trace <trace-option>\n");
+    printf_filtered("    change-media <device> [ <new-image> ]\n");
   }
   }
-
-  return root;
 }
 
 
 }
 
 
+/* create the simulator proper from the device tree and executable */
 
 
-INLINE_PSIM psim *
-psim_create(const char *file_name)
+INLINE_PSIM\
+(psim *)
+psim_create(const char *file_name,
+           device *root)
 {
   int cpu_nr;
   const char *env;
   psim *system;
 {
   int cpu_nr;
   const char *env;
   psim *system;
+  os_emul *os_emulation;
+  int nr_cpus;
 
 
-  /* create things */
-  system = ZALLOC(psim);
-  system->events = event_queue_create();
-  system->memory = core_create();
-  system->monitor = mon_create();
-  system->devices = create_device_tree(file_name, system->memory);
-  for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
-    system->processors[cpu_nr] = cpu_create(system,
-                                           system->memory,
-                                           system->events,
-                                           mon_cpu(system->monitor,
-                                                   cpu_nr),
-                                           cpu_nr);
-  }
+  /* given this partially populated device tree, os_emul_create() uses
+     it and file_name to determine the selected emulation and hence
+     further populate the tree with any other required nodes. */
+
+  os_emulation = os_emul_create(file_name, root);
+  if (os_emulation == NULL)
+    error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
 
   /* fill in the missing real number of CPU's */
 
   /* fill in the missing real number of CPU's */
-  system->nr_cpus = device_tree_find_integer(system->devices,
-                                            "/options/smp");
+  nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
+  if (MAX_NR_PROCESSORS < nr_cpus)
+    error("target and configured number of cpus conflict\n");
 
   /* fill in the missing TARGET BYTE ORDER information */
 
   /* fill in the missing TARGET BYTE ORDER information */
-  current_target_byte_order = (device_tree_find_boolean(system->devices,
-                                                       "/options/little-endian?")
-                              ? LITTLE_ENDIAN
-                              : BIG_ENDIAN);
+  current_target_byte_order
+    = (tree_find_boolean_property(root, "/options/little-endian?")
+       ? LITTLE_ENDIAN
+       : BIG_ENDIAN);
   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
-    error("target byte order conflict\n");
+    error("target and configured byte order conflict\n");
 
   /* fill in the missing HOST BYTE ORDER information */
   current_host_byte_order = (current_host_byte_order = 1,
 
   /* fill in the missing HOST BYTE ORDER information */
   current_host_byte_order = (current_host_byte_order = 1,
@@ -406,38 +474,89 @@ psim_create(const char *file_name)
                              ? LITTLE_ENDIAN
                              : BIG_ENDIAN));
   if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
                              ? LITTLE_ENDIAN
                              : BIG_ENDIAN));
   if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
-    error("host byte order conflict\n");
+    error("host and configured byte order conflict\n");
 
   /* fill in the missing OEA/VEA information */
 
   /* fill in the missing OEA/VEA information */
-  env = device_tree_find_string(system->devices,
-                               "/options/environment-architecture");
-  current_environment = (strcmp(env, "user") == 0
+  env = tree_find_string_property(root, "/openprom/options/env");
+  current_environment = ((strcmp(env, "user") == 0
+                         || strcmp(env, "uea") == 0)
                         ? USER_ENVIRONMENT
                         ? USER_ENVIRONMENT
-                        : strcmp(env, "virtual") == 0
+                        : (strcmp(env, "virtual") == 0
+                           || strcmp(env, "vea") == 0)
                         ? VIRTUAL_ENVIRONMENT
                         ? VIRTUAL_ENVIRONMENT
-                        : strcmp(env, "operating") == 0
+                        : (strcmp(env, "operating") == 0
+                           || strcmp(env, "oea") == 0)
                         ? OPERATING_ENVIRONMENT
                         : 0);
   if (current_environment == 0)
                         ? OPERATING_ENVIRONMENT
                         : 0);
   if (current_environment == 0)
-    error("unreconized /options/environment-architecture\n");
+    error("unreconized /options env property\n");
   if (CURRENT_ENVIRONMENT != current_environment)
   if (CURRENT_ENVIRONMENT != current_environment)
-    error("target environment conflict\n");
+    error("target and configured environment conflict\n");
 
   /* fill in the missing ALLIGNMENT information */
 
   /* fill in the missing ALLIGNMENT information */
-  current_alignment = (device_tree_find_boolean(system->devices,
-                                               "/options/strict-alignment?")
-                      ? STRICT_ALIGNMENT
-                      : NONSTRICT_ALIGNMENT);
+  current_alignment
+    = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
+       ? STRICT_ALIGNMENT
+       : NONSTRICT_ALIGNMENT);
   if (CURRENT_ALIGNMENT != current_alignment)
   if (CURRENT_ALIGNMENT != current_alignment)
-    error("target alignment conflict\n");
+    error("target and configured alignment conflict\n");
 
   /* fill in the missing FLOATING POINT information */
 
   /* fill in the missing FLOATING POINT information */
-  current_floating_point = (device_tree_find_boolean(system->devices,
-                                                    "/options/floating-point?")
-                           ? HARD_FLOATING_POINT
-                           : SOFT_FLOATING_POINT);
+  current_floating_point
+    = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
+       ? HARD_FLOATING_POINT
+       : SOFT_FLOATING_POINT);
   if (CURRENT_FLOATING_POINT != current_floating_point)
   if (CURRENT_FLOATING_POINT != current_floating_point)
-    error("target floating-point conflict\n");
+    error("target and configured floating-point conflict\n");
+
+  /* fill in the missing STDIO information */
+  current_stdio
+    = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
+       ? DO_USE_STDIO
+       : DONT_USE_STDIO);
+  if (CURRENT_STDIO != current_stdio)
+    error("target and configured stdio interface conflict\n");
+
+  /* sort out the level of detail for issue modeling */
+  current_model_issue
+    = tree_find_integer_property(root, "/openprom/options/model-issue");
+  if (CURRENT_MODEL_ISSUE != current_model_issue)
+    error("target and configured model-issue conflict\n");
+
+  /* sort out our model architecture - wrong.
+
+     FIXME: this should be obtaining the required information from the
+     device tree via the "/chosen" property "cpu" which is an instance
+     (ihandle) for the only executing processor. By converting that
+     ihandle into the corresponding cpu's phandle and then querying
+     the "name" property, the cpu type can be determined. Ok? */
+
+  model_set(tree_find_string_property(root, "/openprom/options/model"));
+
+  /* create things */
+  system = ZALLOC(psim);
+  system->events = event_queue_create();
+  system->memory = core_from_device(root);
+  system->monitor = mon_create();
+  system->nr_cpus = nr_cpus;
+  system->os_emulation = os_emulation;
+  system->devices = root;
+
+  /* now all the processors attaching to each their per-cpu information */
+  for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
+    system->processors[cpu_nr] = cpu_create(system,
+                                           system->memory,
+                                           mon_cpu(system->monitor,
+                                                   cpu_nr),
+                                           system->os_emulation,
+                                           cpu_nr);
+  }
+
+  /* dump out the contents of the device tree */
+  if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
+    tree_print(root);
+  if (ppc_trace[trace_dump_device_tree])
+    error("");
 
   return system;
 }
 
   return system;
 }
@@ -445,7 +564,8 @@ psim_create(const char *file_name)
 
 /* allow the simulation to stop/restart abnormaly */
 
 
 /* allow the simulation to stop/restart abnormaly */
 
-STATIC_INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_set_halt_and_restart(psim *system,
                          void *halt_jmp_buf,
                          void *restart_jmp_buf)
 psim_set_halt_and_restart(psim *system,
                          void *halt_jmp_buf,
                          void *restart_jmp_buf)
@@ -454,45 +574,96 @@ psim_set_halt_and_restart(psim *system,
   system->path_to_restart = restart_jmp_buf;
 }
 
   system->path_to_restart = restart_jmp_buf;
 }
 
-STATIC_INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_clear_halt_and_restart(psim *system)
 {
   system->path_to_halt = NULL;
   system->path_to_restart = NULL;
 }
 
 psim_clear_halt_and_restart(psim *system)
 {
   system->path_to_halt = NULL;
   system->path_to_restart = NULL;
 }
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_restart(psim *system,
             int current_cpu)
 {
 psim_restart(psim *system,
             int current_cpu)
 {
+  ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
+  ASSERT(system->path_to_restart != NULL);
   system->last_cpu = current_cpu;
   longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
 }
 
 
   system->last_cpu = current_cpu;
   longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
 }
 
 
-INLINE_PSIM void
+static void
+cntrl_c_simulation(void *data)
+{
+  psim *system = data;
+  psim_halt(system,
+           psim_nr_cpus(system),
+           was_continuing,
+           GDB_SIGNAL_INT);
+}
+
+INLINE_PSIM\
+(void)
+psim_stop(psim *system)
+{
+  event_queue_schedule_after_signal(psim_event_queue(system),
+                                   0 /*NOW*/,
+                                   cntrl_c_simulation,
+                                   system);
+}
+
+INLINE_PSIM\
+(void)
 psim_halt(psim *system,
          int current_cpu,
 psim_halt(psim *system,
          int current_cpu,
-         unsigned_word cia,
          stop_reason reason,
          int signal)
 {
          stop_reason reason,
          int signal)
 {
+  ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
+  ASSERT(system->path_to_halt != NULL);
   system->last_cpu = current_cpu;
   system->last_cpu = current_cpu;
-  system->halt_status.cpu_nr = current_cpu;
   system->halt_status.reason = reason;
   system->halt_status.signal = signal;
   system->halt_status.reason = reason;
   system->halt_status.signal = signal;
-  system->halt_status.program_counter = cia;
+  if (current_cpu == system->nr_cpus) {
+    system->halt_status.cpu_nr = 0;
+    system->halt_status.program_counter =
+      cpu_get_program_counter(system->processors[0]);
+  }
+  else {
+    system->halt_status.cpu_nr = current_cpu;
+    system->halt_status.program_counter =
+      cpu_get_program_counter(system->processors[current_cpu]);
+  }
   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
 }
 
   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
 }
 
-INLINE_PSIM psim_status
+
+INLINE_PSIM\
+(int)
+psim_last_cpu(psim *system)
+{
+  return system->last_cpu;
+}
+
+INLINE_PSIM\
+(int)
+psim_nr_cpus(psim *system)
+{
+  return system->nr_cpus;
+}
+
+INLINE_PSIM\
+(psim_status)
 psim_get_status(psim *system)
 {
   return system->halt_status;
 }
 
 
 psim_get_status(psim *system)
 {
   return system->halt_status;
 }
 
 
-cpu *
+INLINE_PSIM\
+(cpu *)
 psim_cpu(psim *system,
         int cpu_nr)
 {
 psim_cpu(psim *system,
         int cpu_nr)
 {
@@ -503,16 +674,37 @@ psim_cpu(psim *system,
 }
 
 
 }
 
 
-const device *
+INLINE_PSIM\
+(device *)
 psim_device(psim *system,
            const char *path)
 {
 psim_device(psim *system,
            const char *path)
 {
-  return device_tree_find_device(system->devices, path);
+  return tree_find_device(system->devices, path);
+}
+
+INLINE_PSIM\
+(event_queue *)
+psim_event_queue(psim *system)
+{
+  return system->events;
 }
 
 
 
 }
 
 
 
-INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
+psim_max_iterations_exceeded(void *data)
+{
+  psim *system = data;
+  psim_halt(system,
+           system->nr_cpus, /* halted during an event */
+           was_signalled,
+           -1);
+}
+
+
+INLINE_PSIM\
+(void)
 psim_init(psim *system)
 {
   int cpu_nr;
 psim_init(psim *system)
 {
   int cpu_nr;
@@ -520,273 +712,92 @@ psim_init(psim *system)
   /* scrub the monitor */
   mon_init(system->monitor, system->nr_cpus);
 
   /* scrub the monitor */
   mon_init(system->monitor, system->nr_cpus);
 
+  /* trash any pending events */
+  event_queue_init(system->events);
+
+  /* if needed, schedule a halt event.  FIXME - In the future this
+     will be replaced by a more generic change to psim_command().  A
+     new command `schedule NNN halt' being added. */
+  if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
+    event_queue_schedule(system->events,
+                        tree_find_integer_property(system->devices,
+                                                   "/openprom/options/max-iterations") - 2,
+                        psim_max_iterations_exceeded,
+                        system);
+  }
+
   /* scrub all the cpus */
   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
     cpu_init(system->processors[cpu_nr]);
 
   /* scrub all the cpus */
   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
     cpu_init(system->processors[cpu_nr]);
 
-  /* init all the devices */
-  device_tree_init(system->devices, system);
+  /* init all the devices (which updates the cpus) */
+  tree_init(system->devices, system);
+
+  /* and the emulation (which needs an initialized device tree) */
+  os_emul_init(system->os_emulation, system->nr_cpus);
 
 
-  /* force loop to restart */
-  system->last_cpu = system->nr_cpus - 1;
+  /* now sync each cpu against the initialized state of its registers */
+  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
+    cpu *processor = system->processors[cpu_nr];
+    cpu_synchronize_context(processor, cpu_get_program_counter(processor));
+    cpu_page_tlb_invalidate_all(processor);
+  }
+
+  /* force loop to start with first cpu */
+  system->last_cpu = -1;
 }
 
 }
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_stack(psim *system,
           char **argv,
           char **envp)
 {
   /* pass the stack device the argv/envp and let it work out what to
      do with it */
 psim_stack(psim *system,
           char **argv,
           char **envp)
 {
   /* pass the stack device the argv/envp and let it work out what to
      do with it */
-  const device *stack_device = device_tree_find_device(system->devices,
-                                                      "/init/stack");
-  unsigned_word stack_pointer;
-  psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
-  stack_device->callback->ioctl(stack_device,
-                               system,
-                               NULL, /*cpu*/
-                               0, /*cia*/
-                               stack_pointer,
-                               argv,
-                               envp);
-}
-
-
-
-/* EXECUTE REAL CODE: 
-
-   Unfortunatly, there are multiple cases to consider vis:
-
-       <icache> X <smp> X <events> X <keep-running-flag> X ...
-
-   Consequently this function is written in multiple different ways */
-
-STATIC_INLINE_PSIM void
-run_until_stop(psim *system,
-              volatile int *keep_running)
-{
-  jmp_buf halt;
-  jmp_buf restart;
-  int cpu_nr;
-#if WITH_IDECODE_CACHE_SIZE
-  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
-    cpu_flush_icache(system->processors[cpu_nr]);
-#endif
-  psim_set_halt_and_restart(system, &halt, &restart);
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
-  /* CASE 1: No instruction cache and no SMP.
-
-     In this case, we can take advantage of the fact that the current
-     instruction address does not need to be returned to the cpu
-     object after every execution of an instruction.  Instead it only
-     needs to be saved when either A. the main loop exits or B. a
-     cpu-{halt,restart} call forces the loop to be re-entered.  The
-     later functions always save the current cpu instruction
-     address. */
-
-  if (!setjmp(halt)) {
-    do {
-      if (!setjmp(restart)) {
-       cpu *const processor = system->processors[0];
-       unsigned_word cia = cpu_get_program_counter(processor);
-       do {
-         if (WITH_EVENTS) {
-           if (event_queue_tick(system->events)) {
-             cpu_set_program_counter(processor, cia);
-             event_queue_process(system->events);
-             cia = cpu_get_program_counter(processor);
-           }
-         }
-         {
-           instruction_word const instruction
-             = vm_instruction_map_read(cpu_instruction_map(processor),
-                                       processor, cia);
-           cia = idecode_issue(processor, instruction, cia);
-         }
-       } while (keep_running == NULL || *keep_running);
-       cpu_set_program_counter(processor, cia);
-      }
-    } while(keep_running == NULL || *keep_running);
-  }
-#endif
-
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
-  /* CASE 2: Instruction case but no SMP
-
-     Here, the additional complexity comes from there being two
-     different cache implementations.  A simple function address cache
-     or a full cracked instruction cache */
-
-  if (!setjmp(halt)) {
-    do {
-      if (!setjmp(restart)) {
-       cpu *const processor = system->processors[0];
-       unsigned_word cia = cpu_get_program_counter(processor);
-       do {
-         if (WITH_EVENTS)
-           if (event_queue_tick(system->events)) {
-             cpu_set_program_counter(processor, cia);
-             event_queue_process(system->events);
-             cia = cpu_get_program_counter(processor);
-           }
-         { 
-           idecode_cache *const cache_entry = cpu_icache_entry(processor,
-                                                               cia);
-           if (cache_entry->address == cia) {
-             idecode_semantic *const semantic = cache_entry->semantic;
-             cia = semantic(processor, cache_entry, cia);
-           }
-           else {
-             instruction_word const instruction
-               = vm_instruction_map_read(cpu_instruction_map(processor),
-                                         processor,
-                                         cia);
-             idecode_semantic *const semantic = idecode(processor,
-                                                        instruction,
-                                                        cia,
-                                                        cache_entry);
-             cache_entry->address = cia;
-             cache_entry->semantic = semantic;
-             cia = semantic(processor, cache_entry, cia);
-           }
-         }
-       } while (keep_running == NULL || *keep_running);
-       cpu_set_program_counter(processor, cia);
-      }
-    } while(keep_running == NULL || *keep_running);
-  }
-#endif
-
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
-  /* CASE 3: No ICACHE but SMP
-
-     The complexity here comes from needing to correctly restart the
-     system when it is aborted.  In particular if cpu0 requests a
-     restart, the next cpu is still cpu1.  Cpu0 being restarted after
-     all the other CPU's and the event queue have been processed */
-
-  if (!setjmp(halt)) {
-    int first_cpu = setjmp(restart);
-    if (first_cpu == 0)
-      first_cpu = system->last_cpu + 1;
-    do {
-      int current_cpu;
-      for (current_cpu = first_cpu, first_cpu = 0;
-          current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
-          current_cpu++) {
-       if (WITH_EVENTS && current_cpu == system->nr_cpus) {
-         if (event_queue_tick(system->events))
-           event_queue_process(system->events);
-       }
-       else {
-         cpu *const processor = system->processors[current_cpu];
-         unsigned_word const cia = cpu_get_program_counter(processor);
-         instruction_word instruction =
-           vm_instruction_map_read(cpu_instruction_map(processor),
-                                   processor,
-                                   cia);
-         cpu_set_program_counter(processor,
-                                 idecode_issue(processor, instruction, cia));
-       }
-       if (!(keep_running == NULL || *keep_running)) {
-         system->last_cpu = current_cpu;
-         break;
-       }
-      }
-    } while (keep_running == NULL || *keep_running);
-  }
-#endif
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
-  /* CASE 4: ICACHE and SMP ...
-
-     This time, everything goes wrong.  Need to restart loops
-     correctly, need to save the program counter and finally need to
-     keep track of each processors current address! */
-
-  if (!setjmp(halt)) {
-    int first_cpu = setjmp(restart);
-    if (!first_cpu)
-      first_cpu = system->last_cpu + 1;
-    do {
-      int current_cpu;
-      for (current_cpu = first_cpu, first_cpu = 0;
-          current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
-          current_cpu++) {
-       if (WITH_EVENTS && current_cpu == system->nr_cpus) {
-         if (event_queue_tick(system->events))
-           event_queue_process(system->events);
-       }
-       else {
-         cpu *processor = system->processors[current_cpu];
-         unsigned_word const cia = cpu_get_program_counter(processor);
-         idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
-         if (cache_entry->address == cia) {
-           idecode_semantic *semantic = cache_entry->semantic;
-           cpu_set_program_counter(processor,
-                                   semantic(processor, cache_entry, cia));
-         }
-         else {
-           instruction_word instruction =
-             vm_instruction_map_read(cpu_instruction_map(processor),
-                                     processor,
-                                     cia);
-           idecode_semantic *semantic = idecode(processor,
-                                                instruction,
-                                                cia,
-                                                cache_entry);
-           cache_entry->address = cia;
-           cache_entry->semantic = semantic;
-           cpu_set_program_counter(processor,
-                                   semantic(processor, cache_entry, cia));
-         }
-       }
-       if (!(keep_running == NULL || *keep_running))
-         break;
-      }
-    } while (keep_running == NULL || *keep_running);
+  device *stack_device = tree_find_device(system->devices,
+                                         "/openprom/init/stack");
+  if (stack_device != (device*)0) {
+    unsigned_word stack_pointer;
+    ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
+                              cooked_transfer) > 0);
+    device_ioctl(stack_device,
+                NULL, /*cpu*/
+                0, /*cia*/
+                device_ioctl_create_stack,
+                stack_pointer,
+                argv,
+                envp);
   }
   }
-#endif
-
-  psim_clear_halt_and_restart(system);
 }
 
 
 }
 
 
+
 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
    thing */
 
 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
    thing */
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_step(psim *system)
 {
   volatile int keep_running = 0;
 psim_step(psim *system)
 {
   volatile int keep_running = 0;
-  run_until_stop(system, &keep_running);
+  idecode_run_until_stop(system, &keep_running,
+                        system->events, system->processors, system->nr_cpus);
 }
 
 }
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_run(psim *system)
 {
 psim_run(psim *system)
 {
-  run_until_stop(system, NULL);
-}
-
-INLINE_PSIM void
-psim_run_until_stop(psim *system,
-                   volatile int *keep_running)
-{
-  run_until_stop(system, keep_running);
+  idecode_run(system,
+             system->events, system->processors, system->nr_cpus);
 }
 
 
 }
 
 
-
 /* storage manipulation functions */
 
 /* storage manipulation functions */
 
-INLINE_PSIM void
+INLINE_PSIM\
+(int)
 psim_read_register(psim *system,
                   int which_cpu,
                   void *buf,
 psim_read_register(psim *system,
                   int which_cpu,
                   void *buf,
@@ -794,20 +805,26 @@ psim_read_register(psim *system,
                   transfer_mode mode)
 {
   register_descriptions description;
                   transfer_mode mode)
 {
   register_descriptions description;
-  char cooked_buf[sizeof(natural_word)];
+  char *cooked_buf;
   cpu *processor;
 
   /* find our processor */
   cpu *processor;
 
   /* find our processor */
-  if (which_cpu == MAX_NR_PROCESSORS)
-    which_cpu = system->last_cpu;
-  if (which_cpu < 0 || which_cpu >= system->nr_cpus)
-    error("psim_read_register() - invalid processor %d\n", which_cpu);
+  if (which_cpu == MAX_NR_PROCESSORS) {
+    if (system->last_cpu == system->nr_cpus
+       || system->last_cpu == -1)
+      which_cpu = 0;
+    else
+      which_cpu = system->last_cpu;
+  }
+  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
+
   processor = system->processors[which_cpu];
 
   /* find the register description */
   description = register_description(reg);
   if (description.type == reg_invalid)
   processor = system->processors[which_cpu];
 
   /* find the register description */
   description = register_description(reg);
   if (description.type == reg_invalid)
-    error("psim_read_register() invalid register name `%s'\n", reg);
+    return 0;
+  cooked_buf = alloca (description.size);
 
   /* get the cooked value */
   switch (description.type) {
 
   /* get the cooked value */
   switch (description.type) {
@@ -840,9 +857,54 @@ psim_read_register(psim *system,
     *(msreg*)cooked_buf = cpu_registers(processor)->msr;
     break;
 
     *(msreg*)cooked_buf = cpu_registers(processor)->msr;
     break;
 
+  case reg_fpscr:
+    *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
+    break;
+
+  case reg_insns:
+    *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
+                                                         which_cpu);
+    break;
+
+  case reg_stalls:
+    if (cpu_model(processor) == NULL)
+      error("$stalls only valid if processor unit model enabled (-I)\n");
+    *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
+    break;
+
+  case reg_cycles:
+    if (cpu_model(processor) == NULL)
+      error("$cycles only valid if processor unit model enabled (-I)\n");
+    *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
+    break;
+
+#ifdef WITH_ALTIVEC
+  case reg_vr:
+    *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
+    break;
+
+  case reg_vscr:
+    *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
+    break;
+#endif
+
+#ifdef WITH_E500
+  case reg_gprh:
+    *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
+    break;
+
+  case reg_evr:
+    *(unsigned64*)cooked_buf = EVR(description.index);
+    break;
+
+  case reg_acc:
+    *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
+    break;
+#endif
+
   default:
   default:
-    printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
-                   processor, buf, reg,
+    printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
+                   (unsigned long)processor, (unsigned long)buf, reg,
                    "read of this register unimplemented");
     break;
 
                    "read of this register unimplemented");
     break;
 
@@ -865,17 +927,34 @@ psim_read_register(psim *system,
     case 8:
       *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
       break;
     case 8:
       *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
       break;
+#ifdef WITH_ALTIVEC
+    case 16:
+      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
+        {
+         union { vreg v; unsigned_8 d[2]; } h, t;
+          memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
+         { _SWAP_8(t.d[0] =, h.d[1]); }
+         { _SWAP_8(t.d[1] =, h.d[0]); }
+          memcpy(buf/*dest*/, &t/*src*/, description.size);
+          break;
+        }
+      else
+        memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
+      break;
+#endif
     }
   }
   else {
     }
   }
   else {
-    bcopy(cooked_buf, buf, description.size);
+    memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
   }
 
   }
 
+  return description.size;
 }
 
 
 
 }
 
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(int)
 psim_write_register(psim *system,
                    int which_cpu,
                    const void *buf,
 psim_write_register(psim *system,
                    int which_cpu,
                    const void *buf,
@@ -884,28 +963,33 @@ psim_write_register(psim *system,
 {
   cpu *processor;
   register_descriptions description;
 {
   cpu *processor;
   register_descriptions description;
-  char cooked_buf[sizeof(natural_word)];
+  char *cooked_buf;
 
   /* find our processor */
 
   /* find our processor */
-  if (which_cpu == MAX_NR_PROCESSORS)
-    which_cpu = system->last_cpu;
+  if (which_cpu == MAX_NR_PROCESSORS) {
+    if (system->last_cpu == system->nr_cpus
+       || system->last_cpu == -1)
+      which_cpu = 0;
+    else
+      which_cpu = system->last_cpu;
+  }
+
+  /* find the description of the register */
+  description = register_description(reg);
+  if (description.type == reg_invalid)
+    return 0;
+  cooked_buf = alloca (description.size);
+
   if (which_cpu == -1) {
     int i;
     for (i = 0; i < system->nr_cpus; i++)
       psim_write_register(system, i, buf, reg, mode);
   if (which_cpu == -1) {
     int i;
     for (i = 0; i < system->nr_cpus; i++)
       psim_write_register(system, i, buf, reg, mode);
-    return;
-  }
-  else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
-    error("psim_read_register() - invalid processor %d\n", which_cpu);
+    return description.size;
   }
   }
+  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
 
   processor = system->processors[which_cpu];
 
 
   processor = system->processors[which_cpu];
 
-  /* find the description of the register */
-  description = register_description(reg);
-  if (description.type == reg_invalid)
-    error("psim_write_register() invalid register name %s\n", reg);
-
   /* If the data is comming in raw (target order), need to cook it
      into host order before putting it into PSIM's internal structures */
   if (mode == raw_transfer) {
   /* If the data is comming in raw (target order), need to cook it
      into host order before putting it into PSIM's internal structures */
   if (mode == raw_transfer) {
@@ -922,10 +1006,24 @@ psim_write_register(psim *system,
     case 8:
       *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
       break;
     case 8:
       *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
       break;
+#ifdef WITH_ALTIVEC
+    case 16:
+      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
+        {
+         union { vreg v; unsigned_8 d[2]; } h, t;
+          memcpy(&t.v/*dest*/, buf/*src*/, description.size);
+         { _SWAP_8(h.d[0] =, t.d[1]); }
+         { _SWAP_8(h.d[1] =, t.d[0]); }
+          memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
+          break;
+        }
+      else
+        memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
+#endif
     }
   }
   else {
     }
   }
   else {
-    bcopy(buf, cooked_buf, description.size);
+    memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
   }
 
   /* put the cooked value into the register */
   }
 
   /* put the cooked value into the register */
@@ -959,19 +1057,54 @@ psim_write_register(psim *system,
     cpu_registers(processor)->msr = *(msreg*)cooked_buf;
     break;
 
     cpu_registers(processor)->msr = *(msreg*)cooked_buf;
     break;
 
+  case reg_fpscr:
+    cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
+    break;
+
+#ifdef WITH_E500
+  case reg_gprh:
+    cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
+    break;
+
+  case reg_evr:
+    {
+      unsigned64 v;
+      v = *(unsigned64*)cooked_buf;
+      cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
+      cpu_registers(processor)->gpr[description.index] = v;
+      break;
+    }
+
+  case reg_acc:
+    cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
+    break;
+#endif
+
+#ifdef WITH_ALTIVEC
+  case reg_vr:
+    cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
+    break;
+
+  case reg_vscr:
+    cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
+    break;
+#endif
+
   default:
   default:
-    printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
-                   processor, cooked_buf, reg,
+    printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
+                   (unsigned long)processor, (unsigned long)cooked_buf, reg,
                    "read of this register unimplemented");
     break;
 
   }
 
                    "read of this register unimplemented");
     break;
 
   }
 
+  return description.size;
 }
 
 
 
 }
 
 
 
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
 psim_read_memory(psim *system,
                 int which_cpu,
                 void *buffer,
 psim_read_memory(psim *system,
                 int which_cpu,
                 void *buffer,
@@ -979,17 +1112,22 @@ psim_read_memory(psim *system,
                 unsigned nr_bytes)
 {
   cpu *processor;
                 unsigned nr_bytes)
 {
   cpu *processor;
-  if (which_cpu == MAX_NR_PROCESSORS)
-    which_cpu = system->last_cpu;
-  if (which_cpu < 0 || which_cpu >= system->nr_cpus)
-    error("psim_read_memory() invalid cpu\n");
+  if (which_cpu == MAX_NR_PROCESSORS) {
+    if (system->last_cpu == system->nr_cpus
+       || system->last_cpu == -1)
+      which_cpu = 0;
+    else
+      which_cpu = system->last_cpu;
+  }
   processor = system->processors[which_cpu];
   return vm_data_map_read_buffer(cpu_data_map(processor),
   processor = system->processors[which_cpu];
   return vm_data_map_read_buffer(cpu_data_map(processor),
-                                buffer, vaddr, nr_bytes);
+                                buffer, vaddr, nr_bytes,
+                                NULL, -1);
 }
 
 
 }
 
 
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
 psim_write_memory(psim *system,
                  int which_cpu,
                  const void *buffer,
 psim_write_memory(psim *system,
                  int which_cpu,
                  const void *buffer,
@@ -998,21 +1136,94 @@ psim_write_memory(psim *system,
                  int violate_read_only_section)
 {
   cpu *processor;
                  int violate_read_only_section)
 {
   cpu *processor;
-  if (which_cpu == MAX_NR_PROCESSORS)
-    which_cpu = system->last_cpu;
-  if (which_cpu < 0 || which_cpu >= system->nr_cpus)
-    error("psim_read_memory() invalid cpu\n");
+  if (which_cpu == MAX_NR_PROCESSORS) {
+    if (system->last_cpu == system->nr_cpus
+       || system->last_cpu == -1)
+      which_cpu = 0;
+    else
+      which_cpu = system->last_cpu;
+  }
+  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
   processor = system->processors[which_cpu];
   return vm_data_map_write_buffer(cpu_data_map(processor),
   processor = system->processors[which_cpu];
   return vm_data_map_write_buffer(cpu_data_map(processor),
-                                 buffer, vaddr, nr_bytes, 1);
+                                 buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
+                                 NULL, -1);
 }
 
 
 }
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_print_info(psim *system,
                int verbose)
 {
 psim_print_info(psim *system,
                int verbose)
 {
-  mon_print_info(system->monitor, verbose);
+  mon_print_info(system, system->monitor, verbose);
+}
+
+
+/* Merge a device tree and a device file. */
+
+INLINE_PSIM\
+(void)
+psim_merge_device_file(device *root,
+                      const char *file_name)
+{
+  FILE *description;
+  int line_nr;
+  char device_path[1000];
+  device *current;
+
+  /* try opening the file */
+  description = fopen(file_name, "r");
+  if (description == NULL) {
+    perror(file_name);
+    error("Invalid file %s specified", file_name);
+  }
+
+  line_nr = 0;
+  current = root;
+  while (fgets(device_path, sizeof(device_path), description)) {
+    char *device;
+    /* check that the full line was read */
+    if (strchr(device_path, '\n') == NULL) {
+      fclose(description);
+      error("%s:%d: line to long - %s",
+           file_name, line_nr, device_path);
+    }
+    else
+      *strchr(device_path, '\n') = '\0';
+    line_nr++;
+    /* skip comments ("#" or ";") and blank lines lines */
+    for (device = device_path;
+        *device != '\0' && isspace(*device);
+        device++);
+    if (device[0] == '#'
+       || device[0] == ';'
+       || device[0] == '\0')
+      continue;
+    /* merge any appended lines */
+    while (device_path[strlen(device_path) - 1] == '\\') {
+      int curlen = strlen(device_path) - 1;
+      /* zap \ */
+      device_path[curlen] = '\0';
+      /* append the next line */
+      if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
+       fclose(description);
+       error("%s:%s: unexpected eof in line continuation - %s",
+             file_name, line_nr, device_path);
+      }
+      if (strchr(device_path, '\n') == NULL) {
+       fclose(description);
+       error("%s:%d: line to long - %s",
+           file_name, line_nr, device_path);
+      }
+      else
+       *strchr(device_path, '\n') = '\0';
+      line_nr++;
+    }
+    /* parse this line */
+    current = tree_parse(current, "%s", device);
+  }
+  fclose(description);
 }
 
 
 }
 
 
This page took 0.041027 seconds and 4 git commands to generate.