Update to 1995-02-20 release
authorMichael Meissner <gnu@the-meissners.org>
Wed, 21 Feb 1996 16:47:06 +0000 (16:47 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Wed, 21 Feb 1996 16:47:06 +0000 (16:47 +0000)
sim/ppc/ChangeLog
sim/ppc/config.in
sim/ppc/cpu.c
sim/ppc/emul_bugapi.c
sim/ppc/emul_generic.c
sim/ppc/emul_netbsd.c
sim/ppc/psim.c

index b9976a1..613eea1 100644 (file)
@@ -1,3 +1,49 @@
+Wed Feb 21 10:39:35 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * emul_bugapi.c (emul_bugapi_create): Make formats type
+       compatible.
+
+Mon Feb 19 22:54:40 1996  Andrew Cagney  <cagney@highland.com.au>
+
+       * ppc-instructions (TLB Invalidate Entry, TLB Invalidate ALL):
+        Implement by passing on request to all processors.
+       * ppc-instructions (TLB Synchronize): Implement as empty, processor
+       tlb's are always in sync.
+
+       * cpu.c (cpu_page_tlb_invalidate_all): New function.  Pass on TLB
+        invalidate request to processors VM sub-system.
+       * cpu.c (cpu_page_tlb_invalidate_entry): Ditto.
+
+       * vm.c (vm_page_tlb_invalidate_all): New function. Mark all page
+        TLB entries as invalid.
+       * vm.c (vm_page_tlb_invalidate_entry): New function. Ditt but only
+       invalidate one TLB entry.
+
+       * psim.c (psim_init): Invalidate TLB's before (re)starting.
+
+Mon Feb 19 21:25:56 1996  Andrew Cagney  <cagney@highland.com.au>
+
+       * emul_generic.c (emul_add_tree_options): Add argument
+        oea_interrupt_prefix (0 or 1) that specifies the prefix MSR[IP]
+        and hence the location of the interrupt vectors.  Add this to the
+        device tree.
+
+       * emul_chirp.c (emul_chirp_create): Allow configuration of
+        floating-point and interrupt prefix (default 0) using the above.
+
+       * emul_netbsd.c (emul_netbsd_create): Pass dummy arg for
+        interrupt-prefix.
+
+       * emul_bugapi.c (emul_bugapi_create): Allow configuration of
+        interrupt prefix (default 1) and configure interrupt table traps
+        accordingly.
+
+       * emul_generic.c (emul_add_tree_hardware): Include a small eeprom
+        in the list of devices.
+
+       * device_table.c: For moment fake eeprom device by a memory
+        device.  In future will need a proper eeprom device.
+
 Tue Feb 20 17:01:26 1996  J.T. Conklin  <jtc@rtl.cygnus.com>
 
        * config.in: Regenerated.
index 7434926..e081c74 100644 (file)
@@ -1,5 +1,8 @@
 /* config.in.  Generated automatically from configure.in by autoheader.  */
 
+#ifndef CONFIG_H
+#define CONFIG_H
+
 /* Define if your processor stores words with the most significant
    byte first (like Motorola and SPARC, unlike Intel and VAX).  */
 #undef WORDS_BIGENDIAN
@@ -45,3 +48,5 @@
 
 /* Define if you have the <unistd.h> header file.  */
 #undef HAVE_UNISTD_H
+
+#endif
index ef8cfeb..9e9e7e7 100644 (file)
 #ifndef _CPU_C_
 #define _CPU_C_
 
-#ifndef STATIC_INLINE_CPU
-#define STATIC_INLINE_CPU STATIC_INLINE
-#endif
-
 #include <setjmp.h>
 
 #include "cpu.h"
@@ -58,6 +54,7 @@ struct _cpu {
 
   /* the system this processor is contained within */
   cpu_mon *monitor;
+  os_emul *os_emulation;
   psim *system;
   event_queue *events;
   int cpu_nr;
@@ -81,12 +78,13 @@ struct _cpu {
 
 };
 
-
-INLINE_CPU cpu *
+INLINE_CPU\
+(cpu *)
 cpu_create(psim *system,
           core *memory,
           event_queue *events,
           cpu_mon *monitor,
+          os_emul *os_emulation,
           int cpu_nr)
 {
   cpu *processor = ZALLOC(cpu);
@@ -105,17 +103,19 @@ cpu_create(psim *system,
   processor->events = events;
   processor->cpu_nr = cpu_nr;
   processor->monitor = monitor;
+  processor->os_emulation = os_emulation;
 
   return processor;
 }
 
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_init(cpu *processor)
 {
   memset(&processor->regs, 0, sizeof(processor->regs));
-  /* FIXME - should any of VM be inited also ? */
-
+  /* vm init is delayed until after the device tree has been init as
+     the devices may further init the cpu */
   if (CURRENT_MODEL_ISSUE > 0)
     model_init (processor->model_ptr);
 }
@@ -123,31 +123,43 @@ cpu_init(cpu *processor)
 
 /* find ones way home */
 
-INLINE_CPU psim *
+INLINE_CPU\
+(psim *)
 cpu_system(cpu *processor)
 {
   return processor->system;
 }
 
-INLINE_CPU int
+INLINE_CPU\
+(int)
 cpu_nr(cpu *processor)
 {
   return processor->cpu_nr;
 }
 
-INLINE_CPU event_queue *
+INLINE_CPU\
+(event_queue *)
 cpu_event_queue(cpu *processor)
 {
   return processor->events;
 }
 
-INLINE_CPU cpu_mon *
+INLINE_CPU\
+(cpu_mon *)
 cpu_monitor(cpu *processor)
 {
   return processor->monitor;
 }
 
-INLINE_CPU model_data *
+INLINE_CPU\
+(os_emul *)
+cpu_os_emulation(cpu *processor)
+{
+  return processor->os_emulation;
+}
+
+INLINE_CPU\
+(model_data *)
 cpu_model(cpu *processor)
 {
   return processor->model_ptr;
@@ -155,14 +167,16 @@ cpu_model(cpu *processor)
 
 /* The processors local concept of time */
 
-INLINE_CPU signed64
+INLINE_CPU\
+(signed64)
 cpu_get_time_base(cpu *processor)
 {
   return (event_queue_time(processor->events)
          - processor->time_base_local_time);
 }
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_set_time_base(cpu *processor,
                  signed64 time_base)
 {
@@ -170,14 +184,16 @@ cpu_set_time_base(cpu *processor,
                                     - time_base);
 }
 
-INLINE_CPU signed32
+INLINE_CPU\
+(signed32)
 cpu_get_decrementer(cpu *processor)
 {
   return (processor->decrementer_local_time
          - event_queue_time(processor->events));
 }
 
-STATIC_INLINE_CPU void
+STATIC_INLINE_CPU\
+(void)
 cpu_decrement_event(event_queue *queue,
                    void *data)
 {
@@ -190,7 +206,8 @@ cpu_decrement_event(event_queue *queue,
   }
 }
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_set_decrementer(cpu *processor,
                    signed32 decrementer)
 {
@@ -216,20 +233,23 @@ cpu_set_decrementer(cpu *processor,
 
 /* program counter manipulation */
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_set_program_counter(cpu *processor,
                        unsigned_word new_program_counter)
 {
   processor->program_counter = new_program_counter;
 }
 
-INLINE_CPU unsigned_word
+INLINE_CPU\
+(unsigned_word)
 cpu_get_program_counter(cpu *processor)
 {
   return processor->program_counter;
 }
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_restart(cpu *processor,
            unsigned_word nia)
 {
@@ -237,7 +257,8 @@ cpu_restart(cpu *processor,
   psim_restart(processor->system, processor->cpu_nr);
 }
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_halt(cpu *processor,
         unsigned_word cia,
         stop_reason reason,
@@ -261,7 +282,8 @@ cpu_halt(cpu *processor,
 
 #if WITH_IDECODE_CACHE_SIZE
 /* allow access to the cpu's instruction cache */
-INLINE_CPU idecode_cache *
+INLINE_CPU\
+(idecode_cache *)
 cpu_icache_entry(cpu *processor,
                 unsigned_word cia)
 {
@@ -269,7 +291,8 @@ cpu_icache_entry(cpu *processor,
 }
 
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_flush_icache(cpu *processor)
 {
   int i;
@@ -282,22 +305,40 @@ cpu_flush_icache(cpu *processor)
 
 /* address map revelation */
 
-INLINE_CPU vm_instruction_map *
+INLINE_CPU\
+(vm_instruction_map *)
 cpu_instruction_map(cpu *processor)
 {
   return processor->instruction_map;
 }
 
-INLINE_CPU vm_data_map *
+INLINE_CPU\
+(vm_data_map *)
 cpu_data_map(cpu *processor)
 {
   return processor->data_map;
 }
 
+INLINE_CPU\
+(void)
+cpu_page_tlb_invalidate_entry(cpu *processor,
+                             unsigned_word ea)
+{
+  vm_page_tlb_invalidate_entry(processor->virtual, ea);
+}
+
+INLINE_CPU\
+(void)
+cpu_page_tlb_invalidate_all(cpu *processor)
+{
+  vm_page_tlb_invalidate_all(processor->virtual);
+}
+
 
 /* reservation access */
 
-INLINE_CPU memory_reservation *
+INLINE_CPU\
+(memory_reservation *)
 cpu_reservation(cpu *processor)
 {
   return &processor->reservation;
@@ -306,13 +347,15 @@ cpu_reservation(cpu *processor)
 
 /* register access */
 
-INLINE_CPU registers *
+INLINE_CPU\
+(registers *)
 cpu_registers(cpu *processor)
 {
   return &processor->regs;
 }
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_synchronize_context(cpu *processor)
 {
 #if (WITH_IDECODE_CACHE)
@@ -330,7 +373,8 @@ cpu_synchronize_context(cpu *processor)
 
 /* might again be useful one day */
 
-INLINE_CPU void
+INLINE_CPU\
+(void)
 cpu_print_info(cpu *processor, int verbose)
 {
 }
index f325901..a202541 100644 (file)
@@ -1,6 +1,6 @@
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright (C) 1994-1996, 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
 #include "emul_generic.h"
 #include "emul_bugapi.h"
 
-/* Any starting address less than this is assumed to be an OEA program
-   rather than VEA.  */
-#ifndef OEA_START_ADDRESS
-#define OEA_START_ADDRESS 0x4000
-#endif
 
-#ifndef OEA_MEMORY_SIZE
-#define OEA_MEMORY_SIZE 0x100000
+#ifndef OEA_START_ADDRESS
+#define OEA_START_ADDRESS 0x100000
 #endif
 
-/* All but CPU 0 are put into an infinate loop, this loop instruction
-   is stored at the address below */
-#ifndef OEA_STALL_CPU_LOOP_ADDRESS
-#define OEA_STALL_CPU_LOOP_ADDRESS 0x00c10
-#endif
 
-/* At initiallization, the system call exception branches to the BUG
-   emulation code */
 
-#ifndef OEA_SYSTEM_CALL_ADDRESS
-#define OEA_SYSTEM_CALL_ADDRESS 0x00c00
-#endif
+struct _os_emul_data {
+  unsigned_word memory_size;
+  unsigned_word top_of_stack;
+  int interrupt_prefix;
+  unsigned_word interrupt_vector_address;
+  unsigned_word system_call_address;
+  unsigned_word stall_cpu_loop_address;
+  int little_endian;
+  int floating_point_available;
+};
 
 
 static os_emul_data *
@@ -79,6 +74,9 @@ emul_bugapi_create(device *root,
                   bfd *image,
                   const char *name)
 {
+  int elf_binary;
+  device *node;
+  os_emul_data *bugapi;
 
   /* check it really is for us */
   if (name != NULL
@@ -90,99 +88,85 @@ emul_bugapi_create(device *root,
       && bfd_get_start_address(image) > OEA_START_ADDRESS)
     return NULL;
 
-  {
-    
-    const memory_size = OEA_MEMORY_SIZE;
-    const elf_binary = (image != NULL 
-                       && image->xvec->flavour == bfd_target_elf_flavour);
-#ifdef bfd_little_endian       /* new bfd */
-    const little_endian = (image != NULL && bfd_little_endian(image));
-#else
-    const little_endian = (image != NULL &&
-                          !image->xvec->byteorder_big_p);
-#endif
-    
-    { /* options */
-      device *options = device_tree_add_found(root, "/", "options");
-      device_add_integer_property(options,
-                                 "smp",
-                                 MAX_NR_PROCESSORS);
-      device_add_boolean_property(options,
-                                 "little-endian?",
-                                 little_endian);
-      device_add_string_property(options,
-                                "env",
-                                "operating");
-      device_add_boolean_property(options,
-                                 "strict-alignment?",
-                                 (WITH_ALIGNMENT == STRICT_ALIGNMENT
-                                  || little_endian));
-      device_add_boolean_property(options,
-                                 "floating-point?",
-                                 WITH_FLOATING_POINT);
-      device_add_string_property(options,
-                                "os-emul",
-                                "bugapi");
-    }
+  bugapi = ZALLOC(os_emul_data);
+
+  /* some defaults */
+  elf_binary = image->xvec->flavour == bfd_target_elf_flavour;
+
+  /* options */
+  emul_add_tree_options(root, image, "bug", "oea",
+                       1 /*oea-interrupt-prefix*/);
+  
+  /* add some real hardware */
+  emul_add_tree_hardware(root);
+
+  bugapi->memory_size
+    = device_find_integer_property(root, "/openprom/options/oea-memory-size");
+  bugapi->interrupt_prefix =
+    device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+  bugapi->interrupt_vector_address = (bugapi->interrupt_prefix
+                                     ? MASK(0, 43)
+                                     : 0);
+  bugapi->system_call_address = (bugapi->interrupt_vector_address + 0x00c00);
+  bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0);
+  bugapi->top_of_stack = bugapi->memory_size - 0x1000;
+  bugapi->little_endian
+    = device_find_boolean_property(root, "/options/little-endian?");
+  bugapi->floating_point_available
+    = device_find_boolean_property(root, "/openprom/options/floating-point?");
+
+  /* initialization */
+  device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
+                        (unsigned long)bfd_get_start_address(image));
+  device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
+                        (unsigned long)bugapi->stall_cpu_loop_address);
+  device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
+                        (unsigned long)(bugapi->top_of_stack - 16));
+  device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
+                        (msr_recoverable_interrupt
+                         | (bugapi->little_endian
+                            ? (msr_little_endian_mode
+                               | msr_interrupt_little_endian_mode)
+                            : 0)
+                         | (bugapi->floating_point_available
+                            ? msr_floating_point_available
+                            : 0)
+                         | (bugapi->interrupt_prefix
+                            ? msr_interrupt_prefix
+                            : 0)
+                         ));
+  
+  /* patch the system call instruction to call this emulation and then
+     do an rfi */
+  node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+                               (long)bugapi->system_call_address);
+  device_tree_add_parsed(node, "./real-address 0x%lx",
+                        (long)bugapi->system_call_address);
+  device_tree_add_parsed(node, "./data 0x%x",
+                        emul_call_instruction);
+  node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+                               (long)(bugapi->system_call_address + 4));
+  device_tree_add_parsed(node, "./real-address 0x%lx",
+                        (long)(bugapi->system_call_address + 4));
+  device_tree_add_parsed(node, "./data 0x%x",
+                        emul_rfi_instruction);
+
+  /* patch the end of the system call instruction so that it contains
+     a loop to self instruction and point all the cpu's at this */
+  node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+                               (unsigned long)bugapi->stall_cpu_loop_address);
+  device_tree_add_parsed(node, "./real-address 0x%lx",
+                        (unsigned long)bugapi->stall_cpu_loop_address);
+  device_tree_add_parsed(node, "./data 0x%lx",
+                        (unsigned long)emul_loop_instruction);
     
-    /* hardware */
-    device_tree_add_found_uw_u_u(root, "/", "memory",
-                                0, memory_size, access_read_write_exec);
-    device_tree_add_found(root, "/", "iobus@0x400000");
-    device_tree_add_found(root, "/iobus", "console@0x000000,16");
-    device_tree_add_found(root, "/iobus", "halt@0x100000,4");
-    device_tree_add_found(root, "/iobus", "icu@0x200000,4");
+  device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
+                        elf_binary ? "elf" : "aix");
     
-    { /* initialization */
-      device *init = device_tree_add_found(root, "/", "init");
-      {
-       device *init_register = device_tree_add_found(init, "", "register");
-       device_add_integer_property(init_register,
-                                   "pc",
-                                   OEA_STALL_CPU_LOOP_ADDRESS);
-       device_add_integer_property(init_register,
-                                   "0.pc",
-                                   bfd_get_start_address(image));
-       device_add_integer_property(init_register,
-                                   "sp",
-                                   memory_size-16);
-       device_add_integer_property(init_register,
-                                   "msr",
-                                   (msr_recoverable_interrupt
-                                    | (little_endian
-                                       ? msr_little_endian_mode
-                                       : 0)
-                                    ));
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    OEA_SYSTEM_CALL_ADDRESS,
-                                    4, emul_call_instruction);
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    OEA_SYSTEM_CALL_ADDRESS + 4,
-                                    4, emul_rfi_instruction);
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    OEA_STALL_CPU_LOOP_ADDRESS,
-                                    4, emul_loop_instruction);
-      }
-      {
-       device *init_stack = device_tree_add_found(init, "", "stack");
-       device_add_null_property(init_stack,
-                                (elf_binary
-                                 ? "elf"
-                                 : "aix"));
-      }
-      {
-       device *init_load_binary = device_tree_add_found(init, "",
-                                                       "load-binary");
-       device_add_null_property(init_load_binary,
-                                bfd_get_filename(image));
-      }
-    }
-  }
-  
-  return (os_emul_data*)-1;
+  device_tree_add_parsed(root, "/openprom/init/load-binary/file-name \"%s",
+                        bfd_get_filename(image));
+
+  return bugapi;
 }
 
 static void
@@ -200,7 +184,7 @@ emul_bugapi_instruction_call(cpu *processor,
 {
   const int call_id = cpu_registers(processor)->gpr[10];
   /* check that this isn't an invalid instruction */
-  if (cia != OEA_SYSTEM_CALL_ADDRESS)
+  if (cia != emul_data->system_call_address)
     return 0;
   switch (call_id) {
   case _OUTCHR:
index 8f8ae09..f45df6c 100644 (file)
@@ -1,6 +1,6 @@
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright (C) 1994-1996, 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
@@ -214,4 +214,82 @@ emul_do_system_call(os_emul_data *emul_data,
     emul_syscall_exit(emul, call, arg0, processor, cia);
 }
 
+
+/* default size for the first bank of memory */
+
+#ifndef OEA_MEMORY_SIZE
+#define OEA_MEMORY_SIZE 0x100000
+#endif
+
+
+/* Add options to the device tree */
+
+INLINE_EMUL_GENERIC void
+emul_add_tree_options(device *tree,
+                     bfd *image,
+                     const char *emul,
+                     const char *env,
+                     int oea_interrupt_prefix)
+{
+  int little_endian = 0;
+
+  /* sort out little endian */
+  if (device_find_property(tree, "/options/little-endian?"))
+    little_endian = device_find_boolean_property(tree, "/options/little-endian?");
+  else {
+#ifdef bfd_little_endian       /* new bfd */
+    little_endian = (image != NULL && bfd_little_endian(image));
+#else
+    little_endian = (image != NULL &&
+                    !image->xvec->byteorder_big_p);
+#endif
+    device_tree_add_parsed(tree, "/options/little-endian? %s",
+                          little_endian ? "true" : "false");
+  }
+
+  /* misc other stuff */
+  device_tree_add_parsed(tree, "/openprom/options/oea-memory-size 0x%x",
+                        OEA_MEMORY_SIZE);
+  device_tree_add_parsed(tree, "/openprom/options/oea-interrupt-prefix %d",
+                        oea_interrupt_prefix);
+  device_tree_add_parsed(tree, "/openprom/options/smp 1");
+  device_tree_add_parsed(tree, "/openprom/options/env %s", env);
+  device_tree_add_parsed(tree, "/openprom/options/os-emul %s", emul);
+  device_tree_add_parsed(tree, "/openprom/options/strict-alignment? %s",
+                        (WITH_ALIGNMENT == STRICT_ALIGNMENT || little_endian)
+                        ? "true" : "false");
+  device_tree_add_parsed(tree, "/openprom/options/floating-point? %s",
+                        WITH_FLOATING_POINT ? "true" : "false");
+  device_tree_add_parsed(tree, "/openprom/options/model \"%s",
+                        model_name[WITH_DEFAULT_MODEL]);
+  device_tree_add_parsed(tree, "/openprom/options/model-issue %d",
+                        MODEL_ISSUE_IGNORE);
+}
+
+INLINE_EMUL_GENERIC void
+emul_add_tree_hardware(device *root)
+{
+  /* add some memory */
+  if (device_tree_find_device(root, "/memory") == NULL) {
+    unsigned_word memory_size =
+      device_find_integer_property(root, "/openprom/options/oea-memory-size");
+    device_tree_add_parsed(root, "/memory@0/reg { 0x0 0x%lx",
+                          (unsigned long)memory_size);
+    /* what about allocated? */
+  }
+  /* an eeprom */
+  device_tree_add_parsed(root, "/openprom/eeprom@0xfff00000/reg { 0xfff00000 0x3000");
+  /* the IO bus */
+  device_tree_add_parsed(root, "/iobus@0x400000/reg { 0x400000 0x400000");
+  device_tree_add_parsed(root, "/iobus/console@0x000000/reg { 0x000000 16");
+  device_tree_add_parsed(root, "/iobus/halt@0x100000/reg    { 0x100000  4");
+  device_tree_add_parsed(root, "/iobus/icu@0x200000/reg     { 0x200000  8");
+  device_tree_add_parsed(root, "/iobus/icu > 0 0 /iobus/icu");
+  device_tree_add_parsed(root, "/iobus/icu > 1 1 /iobus/icu");
+  /* chosen etc */
+  device_tree_add_parsed(root, "/chosen/stdin */iobus/console");
+  device_tree_add_parsed(root, "/chosen/stdout !/chosen/stdin");
+  device_tree_add_parsed(root, "/chosen/memory */memory");
+}
+
 #endif /* _SYSTEM_C_ */
index 6db39a4..27de365 100644 (file)
 #include <sys/errno.h>
 #include <sys/param.h>
 #include <sys/time.h>
+
+#ifdef HAVE_GETRUSAGE
+#ifndef HAVE_SYS_RESOURCE_H
+#undef HAVE_GETRUSAGE
+#endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
 #include <sys/resource.h>
 int getrusage();
+#endif
 
 #include <sys/ioctl.h>
 #include <sys/mount.h>
@@ -224,6 +233,7 @@ write_direntries(unsigned_word addr,
 #endif
 
 
+#ifdef HAVE_GETRUSAGE
 STATIC_INLINE_EMUL_NETBSD void
 write_rusage(unsigned_word addr,
             struct rusage rusage,
@@ -250,7 +260,7 @@ write_rusage(unsigned_word addr,
   H2T(rusage.ru_nivcsw);          /* involuntary context switches */
   emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
 }
-
+#endif
   
 static void
 do_exit(os_emul_data *emul,
@@ -648,6 +658,9 @@ do_gettimeofday(os_emul_data *emul,
 }
 
 
+#ifndef HAVE_GETRUSAGE
+#define do_getrusage 0
+#else
 static void
 do_getrusage(os_emul_data *emul,
             unsigned call,
@@ -670,6 +683,7 @@ do_getrusage(os_emul_data *emul,
       write_rusage(rusage_addr, rusage, processor, cia);
   }
 }
+#endif
 
 
 #if !WITH_NetBSD_HOST
@@ -1277,7 +1291,8 @@ emul_netbsd_create(device *root,
   /* options */
   emul_add_tree_options(root, image, "netbsd",
                        (WITH_ENVIRONMENT == USER_ENVIRONMENT
-                        ? "user" : "virtual"));
+                        ? "user" : "virtual"),
+                       0 /*oea-interrupt-prefix*/);
 
   /* virtual memory - handles growth of stack/heap */
   vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx",
index e12556c..cbdc35e 100644 (file)
@@ -1,6 +1,6 @@
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+    Copyright (C) 1994-1996, 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
 #ifndef _PSIM_C_
 #define _PSIM_C_
 
+#include "inline.c"
+
 #include <stdio.h>
 #include <ctype.h>
 
-#include "config.h"
-#include "ppc-config.h"
-#include "inline.h"
-
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
-#ifndef STATIC_INLINE_PSIM
-#define STATIC_INLINE_PSIM STATIC_INLINE
-#endif
-
 #include <setjmp.h>
 
 #include "cpu.h" /* includes psim.h */
 #include "idecode.h"
+#include "options.h"
 
 #ifdef HAVE_STRING_H
 #include <string.h>
 #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
-
-
 /* system structure, actual size of processor array determined at
    runtime */
 
 struct _psim {
   event_queue *events;
-  device_tree *devices;
+  device *devices;
   mon *monitor;
+  os_emul *os_emulation;
   core *memory;
+
   /* escape routine for inner functions */
   void *path_to_halt;
   void *path_to_restart;
+
   /* 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];
@@ -101,306 +81,207 @@ int current_model_issue = MODEL_ISSUE_IGNORE;
 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/env",
-                        "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 = core_device_create();
+  device_tree_add_parsed(root, "/aliases");
+  device_tree_add_parsed(root, "/options");
+  device_tree_add_parsed(root, "/chosen");
+  device_tree_add_parsed(root, "/packages");
+  device_tree_add_parsed(root, "/cpus");
+  device_tree_add_parsed(root, "/openprom");
+  device_tree_add_parsed(root, "/openprom/init");
+  device_tree_add_parsed(root, "/openprom/trace");
+  device_tree_add_parsed(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)
 {
-  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;
-  }
-  else {
-    elf_binary = 0;
-    top_of_stack = 0x20000000;
-    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-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-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              chirp - OEA + a few OpenBoot calls\n");
+  printf_filtered("\n"); }
+  printf_filtered("\t-i            Print instruction counting statistics\n");
+  if (verbose) { printf_filtered("\n"); }
+  printf_filtered("\t-I            Print execution unit statistics\n");
+  if (verbose) { printf_filtered("\n"); }
+  printf_filtered("\t-r <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("\t-o <spec>     add device <spec> to 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("\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/env",
-                        (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"));
+  error("");
 }
 
-
-/* File device:
-
-   The file contains lines that specify the describe the device tree
-   to be created, read them in and load them into the tree */
-
-STATIC_INLINE_PSIM void
-create_filed_device_tree(const char *file_name,
-                        device_tree *root)
+INLINE_PSIM\
+(char **)
+psim_options(device *root,
+            char **argv)
 {
-  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:
+       psim_usage(0);
+       error ("");
+       break;
+      case 'e':
+       param = find_arg("Missing <emul> option for -e\n", &argp, argv);
+       device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
+       break;
+      case 'h':
+      case '?':
+       psim_usage(1);
+       break;
+      case 'H':
+       psim_usage(2);
+       break;
+      case 'i':
+       device_tree_add_parsed(root, "/openprom/trace/print-info 1");
+       break;
+      case 'I':
+       device_tree_add_parsed(root, "/openprom/trace/print-info 2");
+       device_tree_add_parsed(root, "/openprom/options/model-issue %d",
+                              MODEL_ISSUE_PROCESS);
+       break;
+      case 'm':
+       param = find_arg("Missing <model> option for -m\n", &argp, argv);
+       device_tree_add_parsed(root, "/openprom/options/model %s", param);
+       break;
+      case 'o':
+       param = find_arg("Missing <device> option for -o\n", &argp, argv);
+       current = device_tree_add_parsed(current, "%s", param);
+       break;
+      case 'r':
+       param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
+       device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
+                              atol(param));
+       break;
+      case 't':
+       param = find_arg("Missing <trace> option for -t\n", &argp, argv);
+       if (param[0] == '!')
+         device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
+       else
+         device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
+       break;
       }
+      p += 1;
     }
+    argp += 1;
   }
-  fclose(description);
-}
-
-
-/* Given the file containing the `image', create a device tree that
-   defines the machine to be modeled */
-
-STATIC_INLINE_PSIM device_tree *
-create_device_tree(const char *file_name,
-                  core *memory)
-{
-  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");
-  }
-
-  /* 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;
-  }
-
-  /* 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 {
-    TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
-    create_filed_device_tree(file_name, root);
-  }
-
-  return root;
+  /* force the trace node to (re)process its options */
+  device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
+  /* return where the options end */
+  return argv + argp;
 }
 
 
+/* 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;
+  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 */
-  system->nr_cpus = device_tree_find_integer(system->devices,
-                                            "/options/smp");
+  nr_cpus = device_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 */
-  current_target_byte_order = (device_tree_find_boolean(system->devices,
-                                                       "/options/little-endian?")
-                              ? LITTLE_ENDIAN
-                              : BIG_ENDIAN);
+  current_target_byte_order
+    = (device_find_boolean_property(root, "/options/little-endian?")
+       ? LITTLE_ENDIAN
+       : BIG_ENDIAN);
   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,
@@ -408,11 +289,10 @@ psim_create(const char *file_name)
                              ? 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 */
-  env = device_tree_find_string(system->devices,
-                               "/options/env");
+  env = device_find_string_property(root, "/openprom/options/env");
   current_environment = ((strcmp(env, "user") == 0
                          || strcmp(env, "uea") == 0)
                         ? USER_ENVIRONMENT
@@ -424,25 +304,67 @@ psim_create(const char *file_name)
                         ? OPERATING_ENVIRONMENT
                         : 0);
   if (current_environment == 0)
-    error("unreconized /options/env\n");
+    error("unreconized /options env property\n");
   if (CURRENT_ENVIRONMENT != current_environment)
-    error("target environment conflict\n");
+    error("target and configured environment conflict\n");
 
   /* fill in the missing ALLIGNMENT information */
-  current_alignment = (device_tree_find_boolean(system->devices,
-                                               "/options/strict-alignment?")
-                      ? STRICT_ALIGNMENT
-                      : NONSTRICT_ALIGNMENT);
+  current_alignment
+    = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
+       ? STRICT_ALIGNMENT
+       : NONSTRICT_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 */
-  current_floating_point = (device_tree_find_boolean(system->devices,
-                                                    "/options/floating-point?")
-                           ? HARD_FLOATING_POINT
-                           : SOFT_FLOATING_POINT);
+  current_floating_point
+    = (device_find_boolean_property(root, "/openprom/options/floating-point?")
+       ? HARD_FLOATING_POINT
+       : SOFT_FLOATING_POINT);
   if (CURRENT_FLOATING_POINT != current_floating_point)
-    error("target floating-point conflict\n");
+    error("target and configured floating-point conflict\n");
+
+  /* sort out the level of detail for issue modeling */
+  current_model_issue
+    = device_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(device_find_string_property(root, "/openprom/options/model"));
+
+  /* create things */
+  system = ZALLOC(psim);
+  system->events = event_queue_create();
+  system->memory = core_create(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,
+                                           system->events,
+                                           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])
+    device_tree_traverse(root, device_tree_print_device, NULL, NULL);
+  if (ppc_trace[trace_dump_device_tree])
+    error("");
 
   return system;
 }
@@ -450,7 +372,8 @@ psim_create(const char *file_name)
 
 /* allow the simulation to stop/restart abnormaly */
 
-STATIC_INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
 psim_set_halt_and_restart(psim *system,
                          void *halt_jmp_buf,
                          void *restart_jmp_buf)
@@ -459,14 +382,16 @@ psim_set_halt_and_restart(psim *system,
   system->path_to_restart = restart_jmp_buf;
 }
 
-STATIC_INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
 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)
 {
@@ -475,7 +400,8 @@ psim_restart(psim *system,
 }
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_halt(psim *system,
          int current_cpu,
          unsigned_word cia,
@@ -490,14 +416,16 @@ psim_halt(psim *system,
   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
 }
 
-INLINE_PSIM psim_status
+INLINE_PSIM\
+(psim_status)
 psim_get_status(psim *system)
 {
   return system->halt_status;
 }
 
 
-cpu *
+INLINE_PSIM\
+(cpu *)
 psim_cpu(psim *system,
         int cpu_nr)
 {
@@ -508,7 +436,8 @@ psim_cpu(psim *system,
 }
 
 
-const device *
+INLINE_PSIM\
+(device *)
 psim_device(psim *system,
            const char *path)
 {
@@ -517,43 +446,55 @@ psim_device(psim *system,
 
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_init(psim *system)
 {
   int cpu_nr;
 
   /* scrub the monitor */
   mon_init(system->monitor, system->nr_cpus);
+  os_emul_init(system->os_emulation, system->nr_cpus);
+  event_queue_init(system->events);
 
   /* 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 */
+  /* init all the devices (which updates the cpus) */
   device_tree_init(system->devices, system);
 
+  /* now sync each cpu against the initialized state of its registers */
+  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
+    cpu_synchronize_context(system->processors[cpu_nr]);
+    cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
+  }
+
   /* force loop to restart */
   system->last_cpu = system->nr_cpus - 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 */
-  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);
+  device *stack_device = device_tree_find_device(system->devices,
+                                                "/openprom/init/stack");
+  if (stack_device != (device*)0) {
+    unsigned_word stack_pointer;
+    psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
+    device_ioctl(stack_device,
+                system,
+                NULL, /*cpu*/
+                0, /*cia*/
+                stack_pointer,
+                argv,
+                envp);
+  }
 }
 
 
@@ -566,14 +507,15 @@ psim_stack(psim *system,
 
    Consequently this function is written in multiple different ways */
 
-STATIC_INLINE_PSIM void
+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
+  int cpu_nr;
   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
     cpu_flush_icache(system->processors[cpu_nr]);
 #endif
@@ -655,7 +597,8 @@ run_until_stop(psim *system,
                                                         cia,
                                                         cache_entry);
 
-             mon_event(mon_event_icache_miss, processor, cia);
+             if (WITH_MON != 0)
+               mon_event(mon_event_icache_miss, processor, cia);
              cache_entry->address = cia;
              cache_entry->semantic = semantic;
              cia = semantic(processor, cache_entry, cia);
@@ -750,7 +693,8 @@ run_until_stop(psim *system,
                                                 cia,
                                                 cache_entry);
 
-           mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
+           if (WITH_MON != 0)
+             mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
            cache_entry->address = cia;
            cache_entry->semantic = semantic;
            cpu_set_program_counter(processor,
@@ -771,20 +715,23 @@ run_until_stop(psim *system,
 /* 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;
   run_until_stop(system, &keep_running);
 }
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_run(psim *system)
 {
   run_until_stop(system, NULL);
 }
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_run_until_stop(psim *system,
                    volatile int *keep_running)
 {
@@ -795,7 +742,8 @@ psim_run_until_stop(psim *system,
 
 /* storage manipulation functions */
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_read_register(psim *system,
                   int which_cpu,
                   void *buf,
@@ -884,7 +832,8 @@ psim_read_register(psim *system,
 
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_write_register(psim *system,
                    int which_cpu,
                    const void *buf,
@@ -980,7 +929,8 @@ psim_write_register(psim *system,
 
 
 
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
 psim_read_memory(psim *system,
                 int which_cpu,
                 void *buffer,
@@ -998,7 +948,8 @@ psim_read_memory(psim *system,
 }
 
 
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
 psim_write_memory(psim *system,
                  int which_cpu,
                  const void *buffer,
@@ -1017,7 +968,8 @@ psim_write_memory(psim *system,
 }
 
 
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
 psim_print_info(psim *system,
                int verbose)
 {
@@ -1025,4 +977,30 @@ psim_print_info(psim *system,
 }
 
 
+/* Merge a device tree and a device file. */
+
+INLINE_PSIM\
+(void)
+psim_merge_device_file(device *root,
+                      const char *file_name)
+{
+  FILE *description = fopen(file_name, "r");
+  int line_nr = 0;
+  char device_path[1000];
+  device *current = root;
+  while (fgets(device_path, sizeof(device_path), description)) {
+    /* check all of line was read */
+    if (strchr(device_path, '\n') == NULL) {
+      fclose(description);
+      error("create_filed_device_tree() line %d to long: %s\n",
+           line_nr, device_path);
+    }
+    line_nr++;
+    /* parse this line */
+    current = device_tree_add_parsed(current, "%s", device_path);
+  }
+  fclose(description);
+}
+
+
 #endif /* _PSIM_C_ */