January 23rd merge
authorMichael Meissner <gnu@the-meissners.org>
Mon, 27 Jan 1997 21:34:50 +0000 (21:34 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Mon, 27 Jan 1997 21:34:50 +0000 (21:34 +0000)
18 files changed:
sim/ppc/BUGS [new file with mode: 0644]
sim/ppc/ChangeLog
sim/ppc/Makefile.in
sim/ppc/configure
sim/ppc/configure.in
sim/ppc/device.c
sim/ppc/device.h
sim/ppc/emul_chirp.c
sim/ppc/gen-icache.c
sim/ppc/gen-idecode.c
sim/ppc/igen.c
sim/ppc/main.c
sim/ppc/ppc-cache-rules
sim/ppc/ppc-instructions
sim/ppc/ppc-opcode-complex
sim/ppc/psim.c
sim/ppc/sim_calls.c
sim/ppc/tree.c [new file with mode: 0644]

diff --git a/sim/ppc/BUGS b/sim/ppc/BUGS
new file mode 100644 (file)
index 0000000..81e7870
--- /dev/null
@@ -0,0 +1,47 @@
+ChangeLog
+
+See the ChangeLog file looking for lines taged with the word FIXME.
+
+COREFILE.C:
+
+The implementation of corefile.c (defined by corefile.h) isn't the
+best.  It is intended to be functionaly correct rather than fast.  One
+option being considered is to add a data cache to reduce the overhead
+of the most common case of data read/writes.
+
+VEA
+
+Missing VEA system calls.
+
+ppc-instructions:
+
+Missing or commented out instructions.
+
+64bit:
+
+64bit target untested. 64bit host broken.  For instance use of scanf
+"%x", &long long.
+
+events.c:
+
+Event code for pending events from within signal handlers not
+finished/tested.
+
+hw_*.c:
+
+Better and more devices.
+
+PORTABILITY:
+
+(Notes taken from Michael Meissner): Heavy use of the ## operator -
+fix using the clasic X/**/Y hack; Use of the signed keyword.  In
+particular, signed char has no analogue in classic C (though most
+implementations of classic C use signed chars); Use of long long which
+restricts the target compiler to be GCC.
+
+
+device_ioctl():
+
+Should have an extra argument (unsigned request) as standard.
+
+
index 4bf6282..d7f31be 100644 (file)
+Thu Jan 23 09:07:26 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * hw_trace.c (hw_trace_init_data): Delete.  The trace options need
+       to be initialized independant of the rest of the simulation
+       initalization.  Otherwize a trace option explictly set from gdb
+       could be overridden by hw_trace.
+
+       * psim.c (psim_options): Clarify reason why the trace ioctl occures.
+
+       * FIXME: The trace code is too scattered - hw_trace.c, psim.c,
+       debug.c.  It could be much simpler.
+
+Thu Jan 23 09:07:26 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+       
+       * Some devices support removable media.  Add hooks to the disk
+       device so that it supports this.
+       
+       * device.c (device_add_string_array_property,
+       device_find_string_array_property): New functions, manipulate
+       properties containing an array of strings.
+       (device_find_string_property): Allow a string array.
+       (device_init_static_properties): Update.
+       (device_init_runtime_properties): Update.
+
+       * hw_disk.c (hw_disk_ioctl): Add ioctl for changing the disk
+       media.  If no file image is specified, use the next one in the
+       image property list.
+       (hw_disk_init_address): Change the file property so that it is a
+       string array - use the first entry for the initial file image.
+
+       * tree.c (print_string_aray_property): New function - print a
+       string array.
+       (print_properties): Adjust.
+       (print_string): Write a string, handling double quotes.
+
+       * device.h: Define an ioctl to `change-media' with an optional new
+       media image.
+       
+       * hw_disk.c: Allow floppy disk devices to be specified.
+
+       * psim.c (psim_command): New function, parse more complex psim
+       commands such as "change-media" and "trace".
+       * sim_calls.c (sim_do_command): Use.
+
+Wed Jan 22 09:38:33 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * For expressions like (RA == 0) that are entered in to the cache
+       as RA_is_0. If possible generate the result of the expression so
+       that the compiler gets a better chance of eliminating dead
+       branches.
+
+       * gen-icache.c (print_icache_extraction): For a cache entry of
+       the form <name>_is_<const> where it is a boolean field, generate
+       the result of the expression instead of the expression its self.
+       (print_icache_body): Remove code that was looking for *_is_0 and
+       then generating corresponding definitions.
+
+       * gen-icache.c (print_icache_struct): If there is no cache, do not
+       output expressions in idecode.h file.
+       
+       * gen-icache.c (print_icache_body): Output them here.
+       
+       * ppc-opcode-complex: Clarify constant values for SPR==LR register
+       expansion.
+
+       * ppc-cache-rules (RA_is_0, SPR_is_256): Two new cache entries.
+
+Wed Jan 22 12:24:52 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * The code that put values in and extracted values from the cache
+       was too compilicated.  The cache table did not allow values to be
+       computed from cache entries.  #defines could only be used when a
+       cache was present, remove the restriction.
+
+       * ld-cache.h, ld-cache.c: Add a new cache entry type - SCRATCH.  A
+       scratch variable is defined when a cache entry is beinf
+       filled. Change the definition of a COMPUTE variable to be defined
+       when the cache entry is being used.
+       * gen-icache.c: Update.
+       
+       * ld-cache.h, ld-cache.c: Change field names so that their meaning
+       is more obvious.  old_name->field_name, new_name->derived_name.
+       * gen-icache.c: Update
+       
+       * gen-icache.h, gen-icache.c (print_icache_body): Make the three
+       different types of cache code - put into cache, extract from
+       cache, no cache - an explicit argument to print_icache_body.
+       * gen-icache.c (print_icache_extraction): Ditto.
+       
+       * gen-semantics.c (print_c_semantic): Update use.
+       * gen-idecode.c (print_jump_insn): Update use.
+       * gen-icache.c (print_icache_function): Update use.
+
+       * igen.c (main): Change 'R' option so that it does not force the
+       cache.
+
+       * configure.in (enable-sim-icache): Clarify description.  Make
+       #define one of the defaults regardless of the cache.  Probably
+       should revamp and add a separate option.
+
+Tue Jan 21 13:26:10 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * pk_disklabel.c (block_is_fdisk): Tidy up traces - use dos
+       partition numbering.
+       (pk_disklabel_create_instance): Partition 1..4 are valid - not
+       1..3.
+       (is_iso9660): New function, verify a CD9660 File system.
+       (pk_disklabel_create_instance): Start expanding so that active
+       partition selection is supported.
+
+Mon Jan 20 11:20:15 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * The cap object was retaining a reference to the instance of a
+       device after it was deleted. Instead add and remove cap's from the
+       cap db as they are created and deleted.  This ensuring that a
+       capibility is only used during the lifetime of the corresponding
+       object.
+       
+       * cap.h, cap.c: Correct cap type - was signed32 should be
+       signed_cell.
+       
+       * cap.c (cap_add, cap_remove): New methods for cap object that
+       allow the explicit addition and removal of internal objects that
+       the cap knows about.
+       
+       * cap.c (cap_init): Rewrite.  Verify that the only objects
+       remaining in the cap data base are those that were entered first.
+       Thse objects will be the permenant ones.
+       * device.c (device_init_address): Remember to initialize the cap
+       database.
+       
+       * device.c (device_create_instance_from): Explicitly add device
+       instances to the cap database.  Simplify create code.
+       (device_instance_delete): Explicitly remove device instances from
+       the cap database.
+       
+       * device.c (device_create_from): Explicitly add a device to the
+       cap data base.
+       
+       * device.c (device_create_from): Always set the cap members.
+
+       * hw_disk.c: Output the instance when tracing.
+       
+Sun Jan 19 16:44:29 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * tree.c (split_device_specifier): Add support for aliases when
+       looking up a device. Now needs a device as an argument.
+       (split_property_specifier): Ditto.
+
+Sun Jan 19 15:28:23 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * The memory "claim" and "release" methods take an address and
+       size as arguments.  These may be multi cell values. Initially fix
+       the memory code so that they check/detect this.  Leave the
+       adjustment of any clients to later.
+       
+       * hw_memory.c (hw_memory_instance_claim,
+       hw_memory_instance_release): Handle multi-cell memory devices.
+       
+       * hw_memory.c (hw_memory_instance_claim): Be tolerant towards the
+       release of memory regions that were not claimed.
+
+Fri Jan 17 12:01:07 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * device.h, device.c (device_instance_call_method): Correct return
+       type - can return either 0 or -1, hence should be a signed type.
+       * device_table.h: Ditto.
+       
+       * hw_memory.c (hw_memory_instance_claim,
+       hw_memory_instance_release): Update.
+       * hw_disk.c (hw_disk_max_transfer, hw_disk_block_size,
+       hw_disk_nr_blocks): Ditto.
+       
+Fri Jan 17 11:50:13 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * emul_chirp.c (chirp_emul_claim): Implement using the "claim"
+       method belonging to "/chosen/memory".
+       (chirm_emul_release): Ditto.
+       
+       * Makefile.in (LIB_INLINE_SRC): Remove emul_* from list of files
+       that are inlined.  These modules are called via a table and are
+       not made inline.
+
+       * hw_init.c (update_for_binary_section): Fix failure to allocate
+       memory used by the binary in real-mode executions. If "claim"
+       property is present, allocate memory from the "/chosen/memory"
+       device.
+
+       * emul_chirp.c (emul_chirp_create): Specify that memory should be
+       claimed when loading a real image.
+
+       * hw_memory.c (hw_memory_instance_claim): Don't page align memory
+       allocations.
+
+       * hw_memory.c (hw_memory_instance_release): Avoid infinite loop
+       when merging adjacent memory chunks.
+
+Thu Jan 16 08:51:25 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * vm.h (vm_data_map_read_buffer, vm_data_map_write_buffer): Add
+       optional PROCESSOR & CIA args so that this routine also abort an
+       access.
+
+       * vm_n.h (vm_data_map_read_N, vm_data_map_write_N): For a
+       miss-aligned access when a transfer fails abort.
+       
+       * emul_bugapi.c (emul_bugapi_do_write): Use emul_read_buffer
+       instead of the vm_read_buffer.
+       * emul_netbsd.c (do_write): Ditto.
+       * emul_unix.c (do_unix_write): Ditto.
+
+Wed Jan 15 14:38:25 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * configure.in (--enable-sim-jump): Default is NULL and not -E.
+       * configure: Regenerate.
+       
+       * basics.h (__attribute__): Enable attributes if GCC >= 2.6.
+       (UNUSED): Only enable UNUSED if GCC >= 2.7.
+       
+       * gen-icache.c (print_icache_extraction): Print UNUSED macro
+       instead of explicit __unused__ attribute.
+       (print_icache_body): Ditto.
+       * idecode_expression.h (FPSCR_BEGIN): Use UNUSED.
+
+Wed Jan 15 13:54:50 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * cpu.h, cpu.c (cpu_synchronize_context): Add CIA argument as
+       reference point.
+
+       * vm.c (vm_synchronize_context): Add PROCESSOR and CIA as
+       arguments so that there is a reference point for recovery.
+       (vm_synchronize_context): Pass processor+cia for errors.
+       (om_unpack_sr): Ditto.
+       (om_unpack_srs): Ditto.
+       * vm.c (vm_create): Review error messages.
+
+       * vm.c: Include "cpu.h" so that cpu_error is visible.
+
+       * ppc-instructions (Return From Interrupt): Pass CIA.
+       (Instruction Synchronize): Ditto.
+       * psim.c (psim_init): Ditto.
+
+Wed Jan 15 12:25:11 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * cpu.h, cpu.c (cpu_error): Aborts simulation with error message,
+       but also saves current processor state.
+       
+       * basics.h: Move #include <stdarg.h> to here from device_table.h.
+
+       * interrupts.c (perform_oea_interrupt): Use.  No longer loose CIA
+       when simulation aborted.
+       (program_interrupt): Ditto.
+       (floating_point_unavailable_interrupt): Ditto.
+       (alignment_interrupt): Ditto.
+       (floating_point_assist_interrupt): Ditto.
+       (perform_oea_interrupt): Ditto.
+       (machine_check_interrupt): Ditto.
+
+Tue Jan 14 12:19:10 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * ppc-instructions (Move from Special Purpose Register): Support
+       move from DEC.
+
+Mon Jan 13 16:58:12 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * debug.h, debug.c: Add "interrupts" trace option.
+
+       * interrupts.c (data_storage_interrupt): Add tracing.
+       (machine_check_interrupt): Ditto.
+       (instruction_storage_interrupt): Ditto.
+       (alignment_interrupt): Ditto.
+       (program_interrupt): Ditto.
+       (floating_point_unavailable_interrupt): Ditto.
+       (system_call_interrupt): Ditto.
+       (floating_point_assist_interrupt): Ditto.
+       (deliver_hardware_interrupt): Ditto.
+       
+       * interrupts.c (program_interrupt): For UEA mode, halt the
+       processor - so that the current state is saved - instead of
+       aborting.
+       (floating_point_unavailable_interrupt): Ditto.
+       (floating_point_assist_interrupt): Ditto.
+
+Thu Jan  2 09:10:41 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * interrupts.c (perform_oea_interrupt): Halt rather than abort on
+       a double interrupt.
+
+Wed Jan  1 22:54:52 1997  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * ppc-instructions (Store Multiple Word, Load Multiple Word):
+       Enable.
+
+       * tree.c (print_properties): For an array consider printing it out
+       as an integer array.
+
+       * hw_memory.c (hw_memory_init_address): If an "available" property
+       is present, use that to initialize the available memory instead of
+       using the reg property.
+
+       * emul_generic.c (emul_add_tree_hardware): Add "available"
+       property to memory device.
+
+Fri Dec 20 13:19:07 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * ppc-instructions (Rotate Left Word then AND with Mask): Enable.
+
+       * device.c (device_instance_call_method): Was only looking at the
+       first method.
+
+       * hw_disk.c (hw_disk_nr_blocks): Implement #blocks method.
+       (hw_disk_block_size): Implement block-size method.
+       (hw_disk_max_transfer): Implement max-transfer method.
+
+       * hw_phb.c (hw_phb_init_address): Reinit the rest of the PHB.
+
+       * emul_chirp.c (chirp_emul_instance_to_path): Recover from an
+       invalid ihandle.
+       (chirp_emul_instance_to_package): Ditto.
+       (chirp_emul_method): Ditto.
+       (chirp_emul_read): Ditto.
+       (chirp_emul_write): Ditto.
+       (chirp_emul_close): Ditto.
+       (chirp_emul_seek): Ditto.
+       (chirp_emul_package_to_path): Ditto (for phandle).
+       (chirp_emul_package_to_path): Return the length.
+
+       * psim.c (psim_merge_device_file): Allow continuation lines.
+
+Thu Dec 19 11:09:43 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * emul_chirp.c (chirp_emul_boot): Implement. Well report the new
+       string and exit.
+       
+       * emul_chirp.c (chirp_emul_exit): Correct type of args struct
+       members - *_cell not host dependant int.
+
+Wed Dec 18 17:49:59 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * interrupts.c (perform_oea_interrupt): Print additional
+       information if a double interrupt is encountered.
+
+Wed Dec 18 17:49:59 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+       
+       * psim.c (psim_merge_device_file): Tolerate an incorrect file-name
+       being specified with the -f option.
+       (psim_merge_device_file): Correct check for end of string.
+
+Wed Dec 18 17:49:59 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+       
+       * emul_chirp.c (chirp_emul_peer): Was falling off the end of the
+       list of devices. Return zero to the client instead.
+       * emul_chirp.c (chirp_emul_child): Ditto
+       * emul_chirp.c (chirp_emul_parent): Ditto
+
+       * device.c (device_root): Assert assumption about the device being
+       valid.
+
+Tue Dec 17 15:12:38 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * emul_chirp.c (emul_chirp_create): Add description property to
+       each significant node in the device tree.
+       * emul_bugapi.c (emul_bugapi_create): Ditto.
+
+Fri Dec 13 14:30:31 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * main.c (sim_io_read_stdin): For a single byte STDIO read, use a
+       tempoary two byte buffer.  Single byte read with fgets will not
+       work.
+       * main.c: Include errno.h.
+       (sim_io_read_stdin): For non-STDIO, make it work.
+
+       * emul_chirp.c (chirp_emul_read): Return the correct error status.
+
+Fri Dec 13 14:30:31 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * std-config.h (WITH_STDIO): Don't hard-wire the STDIO mechanism.
+       Instead have each emulation default it to DO_USE_STDIO.
+
+       * emul_generic.c (emul_add_tree_options): Select the STDIO I/O
+       mechanism as the default if enabled or if nothing selected.
+
+       * sim_calls.c (sim_io_read_stdin): Passify GCC's desire for a
+       return value.
+       (sim_io_write_stdout): Ditto.
+       (sim_io_write_stderr): Ditto.
+       * main.c (sim_io_write_stdout): Ditto.
+       (sim_io_write_stderr): Ditto.
+       (sim_io_read_stdin): Ditto.
+
+Tue Dec 10 10:31:48 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * emul_chirp.c (emul_chirp_instruction_call): Make *printf calls
+       type correct.
+       * vm.c (om_effective_to_virtual): Ditto.
+       * events.c (event_queue_schedule{,_after_signal}): Ditto.
+       (event_queue_{deschedule,process}): Ditto.
+       * hw_htab.c (htab_decode_hash_table): Ditto.
+       (htab_map_{page,binary}): Ditto.
+       * hw_opic.c (hw_opic_init_data): Ditto.
+       (handle_interrupt): Ditto.
+       (do_processor_init_register_{read,write}): Ditto.
+       (write_vector_priority_register): Ditto.
+       ({read,write}_destination_register): Ditto.
+       (do_suprious_vector_register_{read,write}): Ditto.
+       (do_current_task_priority_register_N_{read,write}): Ditto.
+       (do_timer_frequency_reporting_register_{read,write}): Ditto.
+       (do_timer_N_{current,base}_count_register_{read,write}): Ditto.
+       (do_ipi_N_dispatch_register_write): Ditto.
+       (do_vendor_identification_register_read): Ditto.
+       (do_feature_reporting_register_N_read): Ditto.
+       (do_global_configuration_register_N_{read,write}): Ditto.
+       * hw_phb.c (hw_phb_attach_address): Ditto.
+       (hw_phb_unit_decode): Ditto.
+       (hw_phb_address_to_attach_address): Ditto.
+       (hw_phb_io_{read,write}_buffer): Ditto.
+       * hw_ide.c (setup_fifo): Ditto.
+
+       * sim_calls.c ({defs,callback,remote-sim}.h): Find gdb include
+       files via -I<dir> instead of using "../../gdb/" prefixes.
+
+Tue Dec 10 10:12:44 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * debug.h: Add tracing for the pal device.
+       * hw_pal.c: Update.
+
+       * emul_chirp.c (chirp_emul_getprop): More tracing.
+
+Tue Dec 10 10:12:44 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * device.h, device.c (device_find_ihandle_runtime_property): New
+       function. Reverse of add_ihandle_runtime property.
+       (device_init_runtime_properties): Use it.
+       
+       * device.c (find_property_entry): New function returns the
+       internal property spec.
+       (device_set_property): Use.
+       (device_find_property): Use.
+
+Tue Dec 10 10:12:44 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * psim.c (psim_merge_device_file): Strip newline from device
+       specs.
+       
+Tue Dec 10 10:12:44 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * hw_htab.c (htab_map_binary): For overlapping text / data maps
+       merge the two.  Also check that the merge is safe.
+
+       * emul_chirp.c (emul_chirp_create): Add a description property to
+       the pte's so that they are easier to identify.
+       
+       (emul_chirp_create): Don't specify a load address for the CHRP
+       image.  Always use the values specified by the executable.
+
+       * hw_htab.c (htab_map_page): Abort if a duplicate map is
+       encountered.
+
+Mon Dec  9 12:08:46 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * hw_htab.c (htab_map_page): Formatting.
+
+       * emul_chirp.c (emul_chirp_instruction_call): Check for a NULL
+       method name when handling the client call. Also check for other
+       bad call arguments.
+       
+       * emul_chirp.c (emul_chirp_create): Allow real-mode?, real-base,
+       etc to be overriden.
+
+Mon Dec  9 12:08:46 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * os_emul.c (os_emul_create): Use tree find property instead of
+       device find property - sigh.
+
+Thu Dec  5 10:46:42 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * 961205: Release snapshot 961205.
+       
+Thu Dec  5 10:46:42 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * configure.in (hostbitsize, bitsize): Fix typo in error message -
+       cannot contain a comma.
+       (sim-warnings): Check for more potential errors.
+
+       * psim.c (psim_usage): Add -f <file> option.  Specifies a file
+       containing device tree specifications that should be merged into
+       the device tree.
+
+       * configure.in: Sort options.
+       * configure: Rebuild
+       
+Wed Dec  4 13:57:31 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * psim.c (psim_usage): Add -n option - specify number of
+       processors.
+
+       * emul_chirp.c: Add description.
+       * emul_bugapi.c: Ditto.
+       * emul_unix.c: Ditto.
+       * emul_netbsd.c: Ditto.
+
+Fri Nov 29 11:12:22 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * hw_pal.c (hw_pal_attach_address): New function, if an attach is
+       encountered, assume that it is the single disk.
+       * hw_pal.c: Add generic device/size decode methods.
+       
+       * hw_nvram.c (hw_nvram_init_address): Use the first nonzero reg
+       property entry when determining the nvram size.
+
+       * hw_core.c: Add generic address/size decode methods.
+
+       * emul_chirp.c (emul_chirp_instruction_call): Return and trace
+       nonzero status from client functions.
+
+       * main.c (error): Always include a cariage return when writing out
+       errors.
+
 Wed Nov 20 00:36:55 1996  Doug Evans  <dje@canuck.cygnus.com>
 
-       * Makefile.in (LIBCOMMON): Define.
-       ($(TARGETLIB)): Add files from $(LIBCOMMON).
+       * sim_calls.c (sim_resume): Reset sim_should_run if single
+       stepping.
+
+Thu Nov 28 13:19:46 1996  Andrew Cagney  <cagney@kremvax.tpgi.com.au>
+
+       * emul_bugapi.c (emul_bugapi_do_diskio): Add support for multiple
+       optional disks.
+
+       * emul_generic.c (emul_add_tree_hardware): Drop the dummy eeprom.
+       Attach the pal - for I/O - as a pseudo device haning from the
+       firmware sub tree.
+
+       * emul_bugapi.c (emul_bugapi_create): Add a small memory device to
+       the device tree at the address of the hi-mem interrupt vector
+       addreses.  Used by bugapi to establish its trap instructions.
+       
+       * debug.h: Add a new macro DITRACE for tracing device instances.
+       
+       * debug.h: Extend the DTRACE macro so that it can also tests for
+       device specific tracint.
+       
+       * device.h, device.c (device_trace): Add method to determine
+       device specific tracing.
+       (device_init_address): Set the devices tracing level.
+       
+Thu Nov 21 12:05:32 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * tree.h, tree.c (tree_device): New files - separate out the
+       device parser and other tree operations from the device.
+       
+       * inline.h, inline.c (INLINE_TREE): Add.
+       * device.h, device.c (device_tree_add_parsed): Delete.
+       * Makefile.in (tree.c): Add rules for new file.
+       * Makefile.in: Better order the emul_* files.
+       
+       * emul_generic.c (emul_add_tree_hardware): Update.
+       * emul_netbsd.c (emul_netbsd_create): Update.
+       * emul_unix.c (emul_unix_create): Ditto.
+       * emul_chirp.c (emul_chirp_create): Ditto.
+       * emul_bugapi.c (emul_bugapi_create): Ditto.
+       * psim.c (psim_tree): Ditto.
+       * hw_init.c: Ditto.
+       
+       * emul_generic.h: Include tree.h
+       * Makefile.in: Add to EMUL_GENERIC_H dependencies.
+       
+       * device.h, device.c (device_root): New function - returns the
+       root of the tree.
+       * corefile.c: Use.
+       
+       * device.h, device.c (device_clean): New function, clean up device
+       ready for next simulation run. This includes things like deleting
+       interrupt edges and properties created during the simulation and
+       also scrubbing any pre-defined properties.
+       * tree.c (tree_init): Use.
+       
+       * device.h, device.c (device_init_static_properties): New
+       function.  Initialize any static predefined properties.  By static
+       we mean those that have values that can be determined before the
+       device tree initialization has started.
+       * tree.c (tree_init): Use.
+
+       * device.h, device.c (device_init_address): Add code to
+       check/verify the devices #address-cells and #size-cells.
+       (device_add_integer_property): Delete corresponding code.
+       (device_nr_address_cells, device_nr_data_cells): Check for
+       property when returning value.
+       
+       * device.h, device.c (device_init_runtime_properties): New
+       function.  Initialize those properties that are not `static'.  At
+       present the only such property is the ihandle.
+       * tree.c (tree_init): Use.
+       
+       * device.h, device.c (reg, ranges): Rework these so that they use
+       an array of the fundamental type - single reg or single range
+       entry.
+       
+       * device.h, device.c (device_add_ihandle_runtime_property):
+       Re-implement the adding of an ihandle during tree construction so
+       that it better fits in with device initialization.
+       
+Thu Nov 21 12:05:32 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.h, device.c (device_ioctl): Add additional argument -
+       request - so that the caller must always specify the type of
+       the ioctl request.
+
+       * device_table.h: Update.
+       * hw_trace.c (hw_trace_ioctl): Ditto.
+       * hw_vm.c (hw_vm_ioctl_callback): Ditto.
+       * hw_init.c (hw_stack_ioctl_callback): Ditto.
+       * psim.c (psim_options): Ditto.
+       
+Thu Nov 21 12:05:32 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+       
+       * BUGS: Updated a bit.
+
+Wed Nov 20 14:06:37 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_opic.c: Finish - third round.
 
-       * sim_calls.c (sim_resume): Reset sim_should_run if single stepping.
+Wed Nov 20 12:02:08 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
 
+       * hw_glue.c (hw_glue_io_read_buffer_callback): Fix miscalc of glue
+       reg index.
+       (hw_glue_io_write_buffer_callback): Ditto.
+
+Tue Nov 19 21:17:08 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * events.c (event_queue_process): Was incorrectly consuming future
+       events on the queue when they should be left alone.
+
+       * debug.h, debug.c (events): Add support for event queue tracing.
+       * events.c: Add event tracing.
+       
+       * debug.h, debug.c: Order device trace options.
+       
 Fri Nov 15 15:23:39 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * pk_disklabel.c (pk_disklabel_create_instance): Fix up some
        warnings generated by GCC.
 
+Sun Nov 17 17:59:14 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * sim-endian.h: Add LE versions of byte swap macros.  Needed for
+       PCI devices which are little-endian.
+       
+       * sim-endian-n.h (endian_le2h_N, endian_h2le_N): Ditto
+
+Sun Nov 17 17:59:14 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_iobus.c (hw_iobus_attach_address_callback): Change the iobus
+       so that it is implementing a 1-1 address map.
+       
+       * emul_generic.c (emul_add_tree_hardware): Adjust.
+
+       * emul_generic.c (emul_add_tree_hardware): Don't add the nvram as
+       a default.
+
+Sun Nov 17 17:59:14 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+       
+       * device.c (split_find_device): Be tolerant of missing unit
+       addresses.
+
+Fri Nov 15 16:49:49 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * basics.h (port_direction): New type, specify the direction of
+       any `port'.
+       
+       * device.h, device.c (device_interrupt_decode): Include
+       specification of port direction in operations.
+       (device_interrupt_encode): Ditto.
+       
+       * device_table.h: Add a direction field to the interrupt port
+       table.
+
+       * device.c (device_tree_add_parsed): Specify port direction.
+       
+Thu Nov 14 21:38:13 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_opic.c: Finish - second round.
+
+Thu Nov  7 00:18:59 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_htab.c (htab_init_data_callback): Allow the virtual-address
+       to be specified as an array which allows 64bit addresses.
+
+       * device.c (device_find_integer_array_property): New function.
+       Simplify the querying of elements of an integer array.
+       (device_add_integer_property, device_find_integer_property):
+       Update to correctly use the cell type.
+
+       * vm.c (om_unpack_sr): Clarify shifting comment.
+       (om_pte_0_masked_vsid): Ditto. Add 64bit version.
+
+       * emul_chirp.c (emul_chirp_create): Initialize the segment
+       registers.
+
+       * vm.c (om_effective_to_virtual): Trace segment register use.
+
+       * hw_htab.c (htab_map_page): Print out the pteg base address to
+       simplify cross checking between vm and the htab.
+       (htab_decode_hash_table): Use device_error instead of error.
+       (htab_map_page): Ditto.
+       (htab_dma_binary): Ditto.
+       (htab_map_binary): Ditto.
+       (htab_init_data_callback): Ditto.
+
+Wed Nov  6 20:20:58 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * interrupts.h: Clarify what the optional instruction program
+       interrupt is - a subset of illegal instruction program interrupt.
+
+       * interrupts.c (program_interrupt): For UEA mode, clarify what an
+       optional instruction program interrupt is.
+       (program_interrupt): For OEA mode, as per spec, generate an
+       illegal instruction program interrupt when an optional instruction
+       is encountered.
+       
+       * gen-semantics.c (print_semantic_body): Delete code
+       differentiating between an unimplemented floating point and normal
+       instruction.  Instead, such a case can be handled explicitly.
+
+       * ppc-instructions (store floating-point as integer word indexed):
+       Mark as optional.
+       (Floating Convert to Integer Doubleword): Make the floating point
+       assist interrupt explicit.
+       (Floating Convert To Integer Doubleword with round towards Zero):
+       Ditto.
+       (Floating Convert To Integer Word): Ditto
+       (Move From FPSCR): Ditto.
+       (Move to Condition Register from FPSCR): Ditto.
+       (Move To FPSCR Fields): Ditto.
+       (Move To FPSCR Field Immediate): Ditto.
+       (Move To FPSCR Bit 0): Ditto.
+       (Move To FPSCR Bit 1): Ditto.
+       
+Mon Nov  4 12:49:13 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * corefile.c (core_map_read_buffer, core_map_write_buffer): Avoid
+       breaking up transfers.
+
+       * corefile.c: Adjust arguments so that the client server
+       relationship is clarified.
+       
+       * hw_glue.c (hw_glue_init_address): Update so it can be attached
+       to a PCI bus.
+
+       * hw_disk.c (hw_disk_instance_write): Add more checks to disk IO -
+       looking for things like overflow/underflow.
+
+Sun Nov  3 18:45:20 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * emul_generic.c (emul_add_tree_hardware): Hang the disk off the
+       PAL device instead of the IOBUS.  The disk must be attached to a
+       logical bus.
+
+       * hw_disk.c (hw_disk_init_address): Just use the unit address
+       directly in the attach - the rest isn't relevant.
+
+Sat Nov  2 21:48:57 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * configure.in (sim-hardware, sim-packages): Allow additional
+       hardware and packages to be prefixed as well as appended.
+
+       * Makefile.in (tmp-hw, tmp-pk): Retain the user specified order of
+       packages when building them.  Consequently, a user can override a
+       standard device by prefixing their own version.
+       
+       * Makefile.in (hw_opic.o, hw_pci.o, hw_ide.o): Add dependencies.
+
 Fri Nov  1 14:42:57 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * mon.c (_cpu_mon): Add fields for counting 1, 2, 4, and 8 byte
@@ -29,6 +788,139 @@ Tue Oct 29 17:55:43 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
        (solaris_descriptors): Make sigaltstack and sigaction nops.
        ({solaris,linux}_descriptors): Add support for access.
 
+Tue, 8 Oct 18:42:26 1996  Jason Molenda <crash@cygnus.co.jp>
+        
+       * Makefile.in (clean): Move config.log to distclean.
+
+Fri Nov  1 16:44:28 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * corefile-n.h (core_map_write_N): Improve abort messages.
+
+       * device.h, device.c (device_attach_address): Remove unused name
+       parameter.
+       (device_detach_address): Ditto.
+       * device_table.h, device_table.c: Update.
+       * hw_iobus.c (hw_iobus_attach_address_callback): Ditto.
+       * hw_nvram.c (hw_nvram_init_address): Ditto.
+       * hw_memory.c (hw_memory_init_address): Ditto.
+       * hw_vm.c (hw_vm_init_address_callback): Ditto.
+       (hw_vm_attach_address): Ditto.
+       (hw_vm_add_space): Ditto.
+       * hw_init.c (update_for_binary_section): Ditto.
+       * hw_core.c (hw_core_attach_address_callback): Ditto.
+
+       * hw_iobus.c (hw_iobus_attach_address_callback): Rewrite to handle
+       configurable parent busses.
+
+Wed Oct 30 18:46:32 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device_table.c (generic_device_size_to_attach_size): Provide
+       limited support for multi-cell sizes.
+       (generic_device_address_to_attach_address): Ditto for addresses.
+
+Tue Oct 29 02:01:29 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.c (device_add_integer_property): Check for setting of
+       #address-cells and #size-cells properties.  For these, update the
+       corresponding device values.
+       (device_nr_address_cells, device_nr_size_cells): Use the value
+       from the device instead of the property.
+
+       * hw_core.c: Use generic address and size conversions for the top
+       bus.
+
+       * hw_memory.c (hw_memory_init_address): Tolerate case where
+       #address and #size cells is greater than 1.
+
+       * device.c (device_tree_print_device): Clean out printing of
+       properties.
+       
+       * device.c (split_device_specifier): Don't detect comments here -
+       "#" can be a valid prefix - eg #size-cells.
+
+       * psim.c (psim_merge_device_file): Suppress comments and blank
+       lines here.
+
+       * emul_generic.c (emul_add_tree_hardware): Fix typo of incorrect
+       pal unit address.  Add the property /#address-cells to the root of
+       the tree.
+
+       * device.c (device_template_create_device): Check that the unit
+       address was successfully parsed.
+
+       * device_table.c (generic_device_unit_decode): Rewrite to better
+       handle multi-cell addresses.
+       (generic_device_unit_encode): Ditto.
+
+       * emul_generic.c (emul_add_tree_hardware): "reg" properties no
+       longer need the explicit array type - the parser takes care of it.
+
+       * pk_disklabel.c (pk_disklabel_create_instance): Add NULL return
+       to keep GCC happy.
+
+Mon Oct 28 22:55:48 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_ide.c: New file.  Model of a basic IDE interface attached to
+       a PCI bus.
+       
+       * configure.in (hardware): Add the ide device to the default
+       configuration.
+       * configure: Regenerate.
+       
+       * debug.h, debug.c: Add tracing option for the IDE device.
+       
+Fri Oct 25 21:28:25 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_phb.c, hw_phb.h: New files - implement a PHB.
+
+       * configure.in (hardware): Add the phb to the list of devices to
+       build by default.
+
+Fri Oct 25 21:28:25 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_com.c: Review description.
+       * hw_disk.c: Ditto.
+       * hw_htab.c: Ditto.
+       * hw_eeprom.c: Ditto.
+       * hw_init.c: Ditto.
+       * hw_cpu.c: Ditto.
+       
+       * hw_com.c: Update event handling.
+
+       * hw_disk.c: Implement tracing.
+       
+Fri Oct 25 21:28:25 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device_table.c (generic_device_init_address): Use
+       assigned-addresses property in preference to any other reg
+       property.
+
+Fri Oct 25 21:28:25 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.h, device.c (device_find_ranges_property): New function.
+       Simplify the manipulation of "ranges" properties.
+       
+       * device.c (device_add_parsed): Extend to include support for the
+       ranges property.
+
+       * device.c (device_add_parsed): Add assigned-addresses to the list
+       of reg type properties.
+       
+       * device.c (device_tree_print_device): Add code to format and
+       print a ranges property.
+       
+       * device.h, device.c (device_nr_address_cells,
+       device_nr_size_cells): New functions. Determine the values of the
+       standard properties #address-cells and #size-cells.  Both of which
+       are optional and have default values of two and one respectfuly.
+       Previously, code that determined #address-cells was incorrectly
+       using a value of one.
+
+Fri Oct 25 21:28:25 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * debug.h, debug.c: Sort debug options, Add entries for the
+       comming PHB device.
+       
 Fri Oct 18 12:12:21 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * ppc-instructions (Floating Select): Add support for fsel unless
@@ -52,9 +944,108 @@ Fri Oct 18 12:12:21 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
        information on program interrupts, particularly in user mode.  Add
        support for optional_instruction_program_interrupt.
 
-Thu Oct  3 16:15:20 1996  Jason Molenda  (crash@godzilla.cygnus.co.jp)
+Wed Sep 25 10:20:29 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
 
-       * Makefile.in (clean): Move config.log to distclean.
+       * hw_glue.c: New device.  Hooks for manipulating interrupt ports.
+
+       * debug.h, debug.c (trace_glue_device): Add tracing support for
+        the interrupt glue logic device.
+
+       * configure.in (hardware): Add glue device.
+       * configure: Regenerate.
+
+Tue Sep 24 20:55:38 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.c (device_tree_parse_integer_property): New function,
+        parse a list of integers as an array property.
+       (device_tree_add_parsed): Call it.
+
+       * device.c (device_tree_parse_string_property): New function,
+        parse a list of strings as a string property (with embeded
+        null's).  For moment, don't try to implement a complext string
+        parser.
+       (device_tree_add_parsed): Call it.
+
+Tue Sep 24 16:30:48 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_opic.c: New file.  OpenPIC interrupt controller.
+
+       * configure.in (hardware): Add opic device.
+       * configure: re-generate.
+
+       * hw_pic.c: Delete, replaced with hw_opic.c.
+
+       * debug.h, debug.c: Add debug option for OpenPIC device. -
+        opic-device.
+
+Tue Sep 24 16:30:48 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * Makefile.in (psim.o, idecode.o): Since idecode and not psim is
+        now the file that does all the inlining.
+
+       * Makefile.in (LIB_SRC, LIB_INLINE_SRC, idecode.o): Break out the
+        library source code that could be involved in an inlining.  Make
+        idecode.o only dependant on the inlined library source code.
+
+       * Makefile.in (LIB_OBJ): Put options last on the list so that it
+        is compiled last.
+
+       * std-config.h (DEVICE_INLINE): Only inline locals when the
+        default is to inline.
+
+Mon Sep 23 00:37:49 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * hw_htab.c (htab_sum_binary): Determine the real-base for the
+        binary.
+
+       * hw_htab.c (htab_map_binary): Depending on the value of the
+        load-base, either map the program in as a contiguous section or as
+        separate sections controled by th binaries lma values.
+       (htab_init_data_callback): Ditto.
+
+Sun Sep 22 15:56:22 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * emul_generic.c (emul_add_tree_options): Remove load-base option.
+
+       * emul_chirp.c (map_over_chirp_note): Add load_base field to note
+        struct.  Don't require the load_base field to be present - just
+        issue warning - it is a recent addition.
+       (emul_chirp_create): Support both virtual and physical modes.
+
+       * emul_chirp.c (emul_chirp_create): Add a stack initialization
+        property so that any arguments specified on the command line can
+        be passed on to user programs.
+
+       * hw_init.c (create_ppc_chirp_bootargs): Add support for chirp
+        argument passing to the pseudo device stack.
+
+Sat Sep 21 19:39:56 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.c (device_error): Make it more tolerant to incomplete
+        devices.
+
+       * hw_init.c (hw_data_init_data_callback): Extend the data device
+        so that it can perform initialization operations either dma or a
+        more complex instance open, seek, write operation.
+       * hw_init.c: Update the description of the data device to reflect
+        this.
+
+Sat Sep 21 00:13:02 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * device.c (device_event_queue_schedule,
+        device_event_queue_deschedule, device_event_queue_time): Have the
+        device object export the event operations.  Making these available
+        from the device object should hopefully simplify writing device
+        models.
+
+Fri Sep 20 14:04:40 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
+
+       * configure.in (sim-hardware): Add eeprom device to default build.
+
+       * hw_eeprom.c: Rewrite so it works.
+
+       * debug.h, debug.c: Add tracing support for the eeprom and com
+        devices.
 
 Thu Sep 19 14:40:40 1996  Andrew Cagney  <cagney@kremvax.highland.com.au>
 
index 1d36f65..b14084e 100644 (file)
@@ -196,12 +196,14 @@ DEVICE_TABLE_H = \
        $(BASICS_H) \
        device_table.h \
        device.h \
+       tree.h \
        hw.h
 
 EMUL_GENERIC_H = \
        $(CPU_H) \
        $(IDECODE_H) \
        emul_generic.h \
+       tree.h \
        os_emul.h
 
 
@@ -227,7 +229,7 @@ BUILT_SRC = \
        config.h \
        ppc-config.h 
 
-LIB_SRC = \
+LIB_INLINE_SRC = \
        psim.c \
        bits.c \
        debug.c \
@@ -239,21 +241,20 @@ LIB_SRC = \
        corefile.c \
        events.c \
        os_emul.c \
-       emul_generic.c \
-       emul_netbsd.c \
-       emul_unix.c \
-       emul_chirp.c \
-       emul_bugapi.c \
        registers.c \
        cpu.c \
        interrupts.c \
        device.c \
+       tree.c \
        device_table.c \
        cap.c \
        mon.c \
-       options.c \
+       options.c
+
+LIB_SRC = \
        $(PACKAGE_SRC) \
-       $(HW_SRC)
+       $(HW_SRC) \
+       $(LIB_INLINE_SRC)
 
 MAIN_SRC = \
        main.c \
@@ -269,10 +270,10 @@ LIB_OBJ = \
        sim-endian.o \
        os_emul.o \
        emul_generic.o \
+       emul_bugapi.o \
+       emul_chirp.o \
        emul_netbsd.o \
        emul_unix.o \
-       emul_chirp.o \
-       emul_bugapi.o \
        registers.o \
        vm.o \
        corefile.o \
@@ -283,6 +284,7 @@ LIB_OBJ = \
        events.o \
        cap.o \
        device.o \
+       tree.o \
        device_table.o \
        itable.o \
        mon.o \
@@ -291,9 +293,9 @@ LIB_OBJ = \
        idecode.o \
        support.o \
        psim.o \
-       options.o \
        $(PACKAGE_OBJ) \
-       $(HW_OBJ)
+       $(HW_OBJ) \
+       options.o
 
 
 GDB_OBJ = sim_calls.o 
@@ -317,9 +319,7 @@ $(TARGETLIB): tmp-igen tmp-dgen tmp-hw tmp-pk $(LIB_OBJ) $(GDB_OBJ)
        $(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
        $(RANLIB) $(TARGETLIB)
 
-# Given that inlines are turned on now, rebuild psim whenever
-# anything changes.
-psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC)
+psim.o: psim.c psim.h tree.h $(CPU_H) $(IDECODE_H)
 
 bits.o: bits.c $(BASICS_H)
 
@@ -331,10 +331,10 @@ sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
 os_emul.o: os_emul.c emul_netbsd.h emul_unix.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
 emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
 
+emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
+emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
 emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
 emul_unix.o: emul_unix.c emul_unix.h $(EMUL_GENERIC_H)
-emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
-emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
 
 registers.o: registers.c $(REGISTERS_H) $(BASICS_H) 
 
@@ -342,13 +342,14 @@ cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
 
 interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h
 
-idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
+# Given that inlines are turned on now, rebuild idecode whenever
+# anything changes.
+idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h $(LIB_INLINE_SRC) $(BUILT_SRC)
        $(CC) -c $(NOWARN_CFLAGS) $<
 
 # double.o: double.c dp-bit.c
 
-vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
-       device.h corefile.h interrupts.h itable.h mon.h
+vm.o: vm.c vm.h vm_n.h $(CPU_H)
 
 corefile.o: corefile.c corefile.h corefile-n.h $(BASICS_H) $(DEVICE_TABLE_H)
 
@@ -364,6 +365,8 @@ main.o: main.c $(PSIM_H) itable.h options.h
 
 device.o: device.c $(DEVICE_TABLE_H) cap.h
 
+tree.o: tree.c tree.h device.h $(DEVICE_TABLE_H)
+
 device_table.o: device_table.c $(DEVICE_TABLE_H) events.h hw.c
 
 cap.o: cap.c cap.h $(BASICS_H)
@@ -381,9 +384,12 @@ itable.o: itable.c itable.h
 mon.o: mon.c $(CPU_H)
 
 # Rebuild options whenever something changes so the date/time is up to date.
-options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile
+options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile defines.h
        $(CC) -c $(STD_CFLAGS) '-DOPCODE_RULES="@sim_opcode@"' '-DIGEN_FLAGS="$(IGEN_FLAGS)"' '-DDGEN_FLAGS="$(DGEN_FLAGS)"' $<
 
+defines.h: config.h Makefile
+       rm -f defines.h
+       sed -n -e '/^#define HAVE_/s/ 1$$/",/' -e '/^#define HAVE_/s//"HAVE_/p' < config.h > defines.h
 #
 # Rules to create the built c source code files
 #
@@ -510,13 +516,13 @@ misc.o: misc.c misc.h filter_filename.h
 # real hardware
 tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change
        for hw in $(HW_SRC) ; do echo $$hw ; done \
-       | sort -u \
+       | cat -n | sort +1 -u | sort -n \
        | sed -e 's/^.*\(hw_.*\)\.c/\1/' \
                -e 's/^/extern const device_descriptor /' \
                -e 's/$$/_device_descriptor\[\];/' \
                > tmp-hw.h
        for hw in $(HW_SRC) ; do echo $$hw ; done \
-       | sort -u \
+       | cat -n | sort +1 -u | sort -n \
        | sed -e 's/^.*\(hw_.*\)\.c/\1/' \
                -e 's/^/    /' \
                -e 's/$$/_device_descriptor,/' \
@@ -526,17 +532,21 @@ tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change
        touch tmp-hw
 
 hw_cpu.o: hw_cpu.c $(DEVICE_TABLE_H)
+hw_core.o: hw_core.c $(DEVICE_TABLE_H)
+hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h
+hw_glue.o: hw_glue.c $(DEVICE_TABLE_H)
+hw_htab.o: hw_htab.c $(DEVICE_TABLE_H)
+hw_ide.o: hw_ide.c $(DEVICE_TABLE_H)
+hw_init.o: hw_init.c $(DEVICE_TABLE_H)
+hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H)
 hw_memory.o: hw_memory.c $(DEVICE_TABLE_H)
 hw_nvram.o: hw_nvram.c $(DEVICE_TABLE_H)
-hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H)
-hw_core.o: hw_core.c $(DEVICE_TABLE_H)
+hw_opic.o: hw_opic.c $(DEVICE_TABLE_H)
 hw_pal.o: hw_pal.c $(DEVICE_TABLE_H)
-hw_htab.o: hw_htab.c $(DEVICE_TABLE_H)
-hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h
-hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
+hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) hw_phb.h
 hw_register.o: hw_register.c $(DEVICE_TABLE_H)
+hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
 hw_vm.o: hw_vm.c $(DEVICE_TABLE_H)
-hw_init.o: hw_init.c $(DEVICE_TABLE_H)
 # ignore this line, it stops make from getting confused
 
 
@@ -544,8 +554,8 @@ hw_init.o: hw_init.c $(DEVICE_TABLE_H)
 # real packages
 tmp-pk: Makefile $(PACKAGE_SRC) $(srcdir)/../../move-if-change
        for pk in $(PACKAGE_SRC) ; do echo $$pk ; done \
-       | sort -u \
-       | sed -e 's/^pk_\(.*\)\.c/\1/' \
+       | cat -n | sort +1 -u | sort -n \
+       | sed -e 's/^.*pk_\(.*\)\.c/\1/' \
                -e 's/^/extern package_create_instance_callback pk_/' \
                -e 's/$$/_create_instance;/' \
                > tmp-pk.h
@@ -563,10 +573,10 @@ TAGS: $(BUILT_SRC)
        etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
 
 clean mostlyclean:
-       rm -f tmp-* *.[oasi] core psim run igen dgen config.log $(BUILT_SRC_WO_CONFIG)
+       rm -f tmp-* *.[oasi] core psim run igen dgen $(BUILT_SRC_WO_CONFIG)
 
 distclean realclean: clean
-       rm -f TAGS Makefile config.cache config.status config.h stamp-h
+       rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log
 
 maintainer-clean: distclean
        rm -f *~ *.log ppc-config.h core *.core
index c405a57..5dd42c8 100755 (executable)
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 # Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.10 
+# Generated automatically using autoconf version 2.12 
 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
 #
 # This configure script is free software; the Free Software Foundation
@@ -12,73 +12,73 @@ ac_help=
 ac_default_prefix=/usr/local
 # Any additions from configure.in:
 ac_help="$ac_help
-  --enable-sim-cflags=opts             Extra CFLAGS for use in building simulator"
+  --enable-sim-alignment=align         Specify strict or nonstrict alignment."
 ac_help="$ac_help
-  --enable-sim-warnings=opts           Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o"
+  --enable-sim-assert                  Specify whether to perform random assertions."
 ac_help="$ac_help
-  --enable-sim-line-nr=opts            Generate extra CPP code that references source rather than generated code"
+  --enable-sim-bitsize=n               Specify target bitsize (32 or 64)."
 ac_help="$ac_help
-  --enable-sim-config=file             Override default config file"
+  --enable-sim-bswap                   Use the BSWAP instruction on Intel 486s and Pentiums."
 ac_help="$ac_help
-  --enable-sim-opcode=which            Override default opcode lookup."
+  --enable-sim-cflags=opts             Extra CFLAGS for use in building simulator"
 ac_help="$ac_help
-  --enable-sim-switch                  Use a switch instead of a table for instruction call."
+  --enable-sim-config=file             Override default config file"
+ac_help="$ac_help
+  --enable-sim-default-model=which     Specify default PowerPC to model."
 ac_help="$ac_help
   --enable-sim-duplicate               Expand (duplicate) semantic functions."
 ac_help="$ac_help
-  --enable-sim-jump            Jump between semantic code (instead of call/return)."
+  --enable-sim-endian=endian           Specify target byte endian orientation."
+ac_help="$ac_help
+  --enable-sim-env=env                 Specify target environment (operating, virtual, user)."
 ac_help="$ac_help
   --enable-sim-filter=rule             Specify filter rules."
 ac_help="$ac_help
-  --enable-sim-icache=size             Specify instruction cache size."
+  --enable-sim-float                   Specify whether to use host floating point or simulate."
 ac_help="$ac_help
   --enable-sim-hardware=list           Specify the hardware to be included in the build."
 ac_help="$ac_help
-  --enable-sim-packages=list           Specify the packages to be included in the build."
-ac_help="$ac_help
-  --enable-sim-inline=inlines          Specify which functions should be inlined."
-ac_help="$ac_help
-  --enable-sim-bswap                   Use the BSWAP instruction on Intel 486s and Pentiums."
+  --enable-sim-hostbitsize=32|64       Specify host bitsize (32 or 64)."
 ac_help="$ac_help
-  --enable-sim-endian=endian           Specify target byte endian orientation."
+  --enable-sim-hostendain=end          Specify host byte endian orientation."
 ac_help="$ac_help
-  --enable-sim-regparm=nr-parm         Pass parameters in registers instead of on the stack - x86/GCC specific."
+  --enable-sim-icache=size             Specify instruction-decode cache size and type."
 ac_help="$ac_help
-  --enable-sim-stdcall=type            Use an alternative function call/return mechanism - x86/GCC specific."
+  --enable-sim-inline=inlines          Specify which functions should be inlined."
 ac_help="$ac_help
-  --enable-sim-hostendain=end          Specify host byte endian orientation."
+  --enable-sim-jump            Jump between semantic code (instead of call/return)."
 ac_help="$ac_help
-  --enable-sim-smp=n                   Specify number of processors to configure for."
+  --enable-sim-line-nr=opts            Generate extra CPP code that references source rather than generated code"
 ac_help="$ac_help
-  --enable-sim-xor-endian=n            Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)."
+  --enable-sim-model=which             Specify PowerPC to model."
 ac_help="$ac_help
-  --enable-sim-bitsize=n               Specify target bitsize (32 or 64)."
+  --enable-sim-model-issue             Specify whether to simulate model specific actions"
 ac_help="$ac_help
-  --enable-sim-hostbitsize=32|64       Specify host bitsize (32 or 64)."
+  --enable-sim-monitor=mon             Specify whether to enable monitoring events."
 ac_help="$ac_help
-  --enable-sim-env=env                 Specify target environment (operating, virtual, user)."
+  --enable-sim-opcode=which            Override default opcode lookup."
 ac_help="$ac_help
-  --enable-sim-timebase                        Specify whether the PPC timebase is supported."
+  --enable-sim-packages=list           Specify the packages to be included in the build."
 ac_help="$ac_help
-  --enable-sim-alignment=align         Specify strict or nonstrict alignment."
+  --enable-sim-regparm=nr-parm         Pass parameters in registers instead of on the stack - x86/GCC specific."
 ac_help="$ac_help
-  --enable-sim-trace                   Specify whether tracing is supported."
+  --enable-sim-reserved-bits           Specify whether to check reserved bits in instruction."
 ac_help="$ac_help
-  --enable-sim-assert                  Specify whether to perform random assertions."
+  --enable-sim-smp=n                   Specify number of processors to configure for."
 ac_help="$ac_help
-  --enable-sim-reserved-bits           Specify whether to check reserved bits in instruction."
+  --enable-sim-stdcall=type            Use an alternative function call/return mechanism - x86/GCC specific."
 ac_help="$ac_help
-  --enable-sim-float                   Specify whether to use host floating point or simulate."
+  --enable-sim-stdio                   Specify whether to use stdio for console input/output."
 ac_help="$ac_help
-  --enable-sim-monitor=mon             Specify whether to enable monitoring events."
+  --enable-sim-switch                  Use a switch instead of a table for instruction call."
 ac_help="$ac_help
-  --enable-sim-model=which             Specify PowerPC to model."
+  --enable-sim-timebase                        Specify whether the PPC timebase is supported."
 ac_help="$ac_help
-  --enable-sim-default-model=which     Specify default PowerPC to model."
+  --enable-sim-trace                   Specify whether tracing is supported."
 ac_help="$ac_help
-  --enable-sim-model-issue             Specify whether to simulate model specific actions"
+  --enable-sim-warnings=opts           Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o"
 ac_help="$ac_help
-  --enable-sim-stdio                   Specify whether to use stdio for console input/output."
+  --enable-sim-xor-endian=n            Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)."
 
 # Initialize some variables set by options.
 # The variables have the same names as the options, with
@@ -117,6 +117,8 @@ mandir='${prefix}/man'
 # Initialize some other variables.
 subdirs=
 MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
 
 ac_prev=
 for ac_option
@@ -398,7 +400,7 @@ EOF
     verbose=yes ;;
 
   -version | --version | --versio | --versi | --vers)
-    echo "configure generated by autoconf version 2.10"
+    echo "configure generated by autoconf version 2.12"
     exit 0 ;;
 
   -with-* | --with-*)
@@ -500,11 +502,14 @@ do
 done
 
 # NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
 if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
 
 # confdefs.h avoids OS command line length limits that DEFS can exceed.
 rm -rf conftest* confdefs.h
@@ -566,6 +571,7 @@ ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
 ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
 
 if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
   # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
@@ -611,11 +617,12 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:621: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
   for ac_dir in $PATH; do
     # Account for people who put trailing slashes in PATH elements.
     case "$ac_dir/" in
@@ -638,7 +645,7 @@ else
       ;;
     esac
   done
-  IFS="$ac_save_ifs"
+  IFS="$ac_save_IFS"
 
 fi
   if test "${ac_cv_path_install+set}" = set; then
@@ -662,6 +669,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:673: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -690,6 +698,7 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:702: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -736,7 +745,47 @@ fi
   test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
 fi
 
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:750: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 760 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:784: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:789: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -745,7 +794,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -753,29 +802,34 @@ fi
 fi
 
 echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
 if test $ac_cv_prog_gcc = yes; then
   GCC=yes
-  if test "${CFLAGS+set}" != set; then
-    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+  ac_test_CFLAGS="${CFLAGS+set}"
+  ac_save_CFLAGS="$CFLAGS"
+  CFLAGS=
+  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:813: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   echo 'void f(){}' > conftest.c
 if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
-  ac_cv_prog_gcc_g=yes
+  ac_cv_prog_cc_g=yes
 else
-  ac_cv_prog_gcc_g=no
+  ac_cv_prog_cc_g=no
 fi
 rm -f conftest*
 
 fi
 
-echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
-    if test $ac_cv_prog_gcc_g = yes; then
-      CFLAGS="-g -O"
-    else
-      CFLAGS="-O"
-    fi
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+  if test "$ac_test_CFLAGS" = set; then
+    CFLAGS="$ac_save_CFLAGS"
+  elif test $ac_cv_prog_cc_g = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-O2"
   fi
 else
   GCC=
@@ -784,83 +838,94 @@ fi
 
 
 # Put a plausible default for CC_FOR_BUILD in Makefile.
-# If we cannot run a trivial program, we must be cross compiling.
-echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-  ac_cv_c_cross=yes
-else
-cat > conftest.$ac_ext <<EOF
-#line 797 "configure"
-#include "confdefs.h"
-main(){return(0);}
-EOF
-{ (eval echo configure:801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
-  ac_cv_c_cross=no
+
+if test "x$cross_compiling" = "xno"; then
+  CC_FOR_BUILD='$(CC)'
 else
-  ac_cv_c_cross=yes
+  CC_FOR_BUILD=gcc
 fi
+
+
+# Check whether --enable-sim-alignment or --disable-sim-alignment was given.
+if test "${enable_sim_alignment+set}" = set; then
+  enableval="$enable_sim_alignment"
+  case "${enableval}" in
+  yes | strict | STRICT)       sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
+  no | nonstrict | NONSTRICT)  sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+  0 | default | DEFAULT)       sim_alignment="-DWITH_ALIGNMENT=0";;
+  *)                           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
+  echo "Setting alignment flags = $sim_alignment" 6>&1
 fi
-rm -fr conftest*
+else
+  sim_alignment=""
 fi
 
-echo "$ac_t""$ac_cv_c_cross" 1>&6
-cross_compiling=$ac_cv_c_cross
 
-if test "x$cross_compiling" = "xno"; then
-  CC_FOR_BUILD='$(CC)'
+# Check whether --enable-sim-assert or --disable-sim-assert was given.
+if test "${enable_sim_assert+set}" = set; then
+  enableval="$enable_sim_assert"
+  case "${enableval}" in
+  yes) sim_assert="-DWITH_ASSERT=1";;
+  no)  sim_assert="-DWITH_ASSERT=0";;
+  *)   { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
+  echo "Setting assert flags = $sim_assert" 6>&1
+fi
 else
-  CC_FOR_BUILD=gcc
+  sim_assert=""
 fi
 
-# Check whether --enable-sim-cflags or --disable-sim-cflags was given.
-if test "${enable_sim_cflags+set}" = set; then
-  enableval="$enable_sim_cflags"
+
+# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given.
+if test "${enable_sim_bitsize+set}" = set; then
+  enableval="$enable_sim_bitsize"
   case "${enableval}" in
-  yes) sim_cflags="-O2 -fomit-frame-pointer";;
-  no)  sim_cflags="";;
-  *)   sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+  32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
+  *)    { echo "configure: error: "--enable-sim-bitsize was given $enableval.  Expected 32 or 64"" 1>&2; exit 1; }; sim_bitsize="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then
-  echo "Setting sim cflags = $sim_cflags" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
+  echo "Setting bitsize flags = $sim_bitsize" 6>&1
 fi
 else
-  sim_cflags=""
+  sim_bitsize=""
 fi
 
-# Check whether --enable-sim-warnings or --disable-sim-warnings was given.
-if test "${enable_sim_warnings+set}" = set; then
-  enableval="$enable_sim_warnings"
+
+# Check whether --enable-sim-bswap or --disable-sim-bswap was given.
+if test "${enable_sim_bswap+set}" = set; then
+  enableval="$enable_sim_bswap"
   case "${enableval}" in
-  yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";;
-  no)  sim_warnings="-w";;
-  *)   sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+  yes) sim_bswap="-DWITH_BSWAP=1";;
+  no)  sim_bswap="-DWITH_BSWAP=0";;
+  *)   { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
-  echo "Setting warning flags = $sim_warnings" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then
+  echo "Setting bswap flags = $sim_bswap" 6>&1
 fi
 else
-  sim_warnings=""
+  sim_bswap=""
 fi
 
-# Check whether --enable-sim-line-nr or --disable-sim-line-nr was given.
-if test "${enable_sim_line_nr+set}" = set; then
-  enableval="$enable_sim_line_nr"
+
+# Check whether --enable-sim-cflags or --disable-sim-cflags was given.
+if test "${enable_sim_cflags+set}" = set; then
+  enableval="$enable_sim_cflags"
   case "${enableval}" in
-  yes) sim_line_nr="";;
-  no)  sim_line_nr="-L";;
-  *)   { echo "configure: error: "--enable-sim-line-nr does not take a value"" 1>&2; exit 1; }; sim_line_nr="";;
+  yes) sim_cflags="-O2 -fomit-frame-pointer";;
+  no)  sim_cflags="";;
+  *)   sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;;
 esac
-if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
-  echo "Setting warning flags = $sim_line_nr" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then
+  echo "Setting sim cflags = $sim_cflags" 6>&1
 fi
 else
-  sim_line_nr=""
+  sim_cflags=""
 fi
 
+
 # Check whether --enable-sim-config or --disable-sim-config was given.
 if test "${enable_sim_config+set}" = set; then
   enableval="$enable_sim_config"
@@ -885,48 +950,22 @@ if test x"$silent" != x"yes"; then
 fi
 fi
 
-# Check whether --enable-sim-opcode or --disable-sim-opcode was given.
-if test "${enable_sim_opcode+set}" = set; then
-  enableval="$enable_sim_opcode"
-  case "${enableval}" in
-  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };;
-  *)           if test -f "${srcdir}/${enableval}"; then
-                 sim_opcode="${enableval}"
-               elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
-                 sim_opcode="ppc-opcode-${enableval}"
-               else
-                 { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; };
-                 sim_opcode="ppc-opcode-complex"
-               fi;;
-esac
-if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
-  echo "Setting opcode flags = $sim_opcode" 6>&1
-fi
-else
-  sim_opcode="ppc-opcode-complex"
-if test x"$silent" != x"yes"; then
-  echo "Setting opcode flags = $sim_opcode"
-fi
-fi
 
-# Check whether --enable-sim-switch or --disable-sim-switch was given.
-if test "${enable_sim_switch+set}" = set; then
-  enableval="$enable_sim_switch"
+# Check whether --enable-sim-default-model or --disable-sim-default-model was given.
+if test "${enable_sim_default_model+set}" = set; then
+  enableval="$enable_sim_default_model"
   case "${enableval}" in
-  yes) sim_switch="-s";;
-  no)  sim_switch="";;
-  *)   { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";;
+  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };;
+  *)           sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
-  echo "Setting switch flags = $sim_switch" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
+  echo "Setting default-model flags = $sim_default_model" 6>&1
 fi
 else
-  sim_switch="";
-if test x"$silent" != x"yes"; then
-  echo "Setting switch flags = $sim_switch" 6>&1
-fi
+  sim_model=""
 fi
 
+
 # Check whether --enable-sim-duplicate or --disable-sim-duplicate was given.
 if test "${enable_sim_duplicate+set}" = set; then
   enableval="$enable_sim_duplicate"
@@ -945,23 +984,46 @@ if test x"$silent" != x"yes"; then
 fi
 fi
 
-# Check whether --enable-sim-jump or --disable-sim-jump was given.
-if test "${enable_sim_jump+set}" = set; then
-  enableval="$enable_sim_jump"
+
+# Check whether --enable-sim-endian or --disable-sim-endian was given.
+if test "${enable_sim_endian+set}" = set; then
+  enableval="$enable_sim_endian"
   case "${enableval}" in
-  yes) sim_jump="-J";;
-  no)  sim_jump="";;
-  *)   { echo "configure: error: "--enable-sim-jump does not take a value"" 1>&2; exit 1; }; sim_jump="";;
+  yes) case "$target" in
+         *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+         *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+         *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+       esac;;
+  no)   sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+  b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+  l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+  *)    { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
-  echo "Setting jump flag = $sim_jump" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
+  echo "Setting endian flags = $sim_endian" 6>&1
 fi
 else
-  sim_jump="-E"
-if test x"$silent" != x"yes"; then
-  echo "Setting jump flag = $sim_jump" 6>&1
+  sim_endian=""
 fi
+
+
+# Check whether --enable-sim-env or --disable-sim-env was given.
+if test "${enable_sim_env+set}" = set; then
+  enableval="$enable_sim_env"
+  case "${enableval}" in
+  operating | os | oea)        sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
+  virtual | vea)       sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
+  user | uea)          sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
+  no)                  sim_env="-DWITH_ENVIRONMENT=0";;
+  *)                   { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
+  echo "Setting env flags = $sim_env" 6>&1
 fi
+else
+  sim_env=""
+fi
+
 
 # Check whether --enable-sim-filter or --disable-sim-filter was given.
 if test "${enable_sim_filter+set}" = set; then
@@ -975,51 +1037,39 @@ if test x"$silent" != x"yes" && test x"$sim_filter" != x""; then
   echo "Setting filter flags = $sim_filter" 6>&1
 fi
 else
-  sim_filter="-F 32,f"
+  sim_filter="-F 32,f,o"
 if test x"$silent" != x"yes"; then
   echo "Setting filter flags = $sim_filter" 6>&1
 fi
 fi
 
-# Check whether --enable-sim-icache or --disable-sim-icache was given.
-if test "${enable_sim_icache+set}" = set; then
-  enableval="$enable_sim_icache"
-  icache=""
- case "${enableval}" in
-  yes)         icache="1024"; sim_icache="-I $icache";;
-  no)          sim_icache="";;
-  *) icache=1024
-     sim_icache="-"
-     for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
-       case "$x" in
-         define)       sim_icache="${sim_icache}R";;
-         semantic)     sim_icache="${sim_icache}C";;
-        insn)          sim_icache="${sim_icache}S";;
-        0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;;
-         *)            { echo "configure: error: "Unknown value $x for --enable-sim-icache"" 1>&2; exit 1; }; sim_icache="";;
-       esac
-     done
-     sim_icache="${sim_icache}I $icache";;
+
+# Check whether --enable-sim-float or --disable-sim-float was given.
+if test "${enable_sim_float+set}" = set; then
+  enableval="$enable_sim_float"
+  case "${enableval}" in
+  yes | hard)  sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
+  no | soft)   sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
+  *)           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";;
 esac
-if test x"$silent" != x"yes" && test x"$icache" != x""; then
-  echo "Setting instruction cache size to $icache ($sim_icache)"
+if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
+  echo "Setting float flags = $sim_float" 6>&1
 fi
 else
-  sim_icache="-CSI 1024"
-if test x"$silent" != x"yes"; then
-  echo "Setting instruction cache size to 1024 ($sim_icache)"
-fi
+  sim_float=""
 fi
 
+
 # Check whether --enable-sim-hardware or --disable-sim-hardware was given.
 if test "${enable_sim_hardware+set}" = set; then
   enableval="$enable_sim_hardware"
-  hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal"
+  hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
 case "${enableval}" in
   yes) ;;
   no)  { echo "configure: error: "List of hardware must be specified for --enable-sim-hardware"" 1>&2; exit 1; }; hardware="";;
   ,*)   hardware="${hardware}${enableval}";;
-  *)   hardware="${enableval}";;
+  *,)   hardware="${enableval}${hardware}";;
+  *)   hardware="${enableval}"'';;
 esac
 sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
 sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
@@ -1027,7 +1077,7 @@ if test x"$silent" != x"yes" && test x"$hardware" != x""; then
   echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
 fi
 else
-  hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal"
+  hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
 sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
 sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
 if test x"$silent" != x"yes"; then
 fi
 
 
-# Check whether --enable-sim-packages or --disable-sim-packages was given.
-if test "${enable_sim_packages+set}" = set; then
-  enableval="$enable_sim_packages"
-  packages=disklabel
-case "${enableval}" in
-  yes) ;;
-  no)  { echo "configure: error: "List of packages must be specified for --enable-sim-packages"" 1>&2; exit 1; }; packages="";;
-  ,*)   packages="${packages}${enableval}";;
-  *)   packages="${enableval}"''
-esac
-sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
-sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
-if test x"$silent" != x"yes" && test x"$packages" != x""; then
-  echo "Setting packages to $sim_pk_src, $sim_pk_obj"
-fi
-else
-  packages=disklabel
-sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
-sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
-if test x"$silent" != x"yes"; then
-  echo "Setting packages to $sim_pk_src, $sim_pk_obj"
-fi
-fi
-
-# Check whether --enable-sim-inline or --disable-sim-inline was given.
-if test "${enable_sim_inline+set}" = set; then
-  enableval="$enable_sim_inline"
-  sim_inline=""
-case "$enableval" in
-  no)          sim_inline="-DDEFAULT_INLINE=0";;
-  0)           sim_inline="-DDEFAULT_INLINE=0";;
-  yes | 2)     sim_inline="-DDEFAULT_INLINE=ALL_INLINE";;
-  1)           sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";;
-  *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do
-       new_flag=""
-       case "$x" in
-        *_INLINE=*)    new_flag="-D$x";;
-        *=*)           new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;;
-        *_INLINE)      new_flag="-D$x=ALL_INLINE";;
-        *)             new_flag="-D$x""_INLINE=ALL_INLINE";;
-       esac
-       if test x"$sim_inline" = x""; then
-        sim_inline="$new_flag"
-       else
-        sim_inline="$sim_inline $new_flag"
-       fi
-     done;;
-esac
-if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then
-  echo "Setting inline flags = $sim_inline" 6>&1
-fi
-else
-  if test x"$GCC" != ""; then
-  sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS"
-  if test x"$silent" != x"yes"; then
-    echo "Setting inline flags = $sim_inline" 6>&1
-  fi
-else
-  sim_inline=""
-fi
-fi
-
-# Check whether --enable-sim-bswap or --disable-sim-bswap was given.
-if test "${enable_sim_bswap+set}" = set; then
-  enableval="$enable_sim_bswap"
-  case "${enableval}" in
-  yes) sim_bswap="-DWITH_BSWAP=1";;
-  no)  sim_bswap="-DWITH_BSWAP=0";;
-  *)   { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then
-  echo "Setting bswap flags = $sim_bswap" 6>&1
-fi
-else
-  sim_bswap=""
-fi
-
-# Check whether --enable-sim-endian or --disable-sim-endian was given.
-if test "${enable_sim_endian+set}" = set; then
-  enableval="$enable_sim_endian"
+# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given.
+if test "${enable_sim_hostbitsize+set}" = set; then
+  enableval="$enable_sim_hostbitsize"
   case "${enableval}" in
-  yes) case "$target" in
-         *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
-         *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
-         *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
-       esac;;
-  no)   sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
-  b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
-  l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
-  *)    { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";;
+  32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
+  *)    { echo "configure: error: "--enable-sim-hostbitsize was given $enableval.  Expected 32 or 64"" 1>&2; exit 1; }; sim_hostbitsize="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
-  echo "Setting endian flags = $sim_endian" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
+  echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
 fi
 else
-  sim_endian=""
+  sim_hostbitsize=""
 fi
 
-# Check whether --enable-sim-regparm or --disable-sim-regparm was given.
-if test "${enable_sim_regparm+set}" = set; then
-  enableval="$enable_sim_regparm"
-  case "${enableval}" in
-  0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";;
-  no)                            sim_regparm="" ;;
-  yes)                           sim_regparm="-DWITH_REGPARM=3";;
-  *)   { echo "configure: error: "Unknown value $enableval for --enable-sim-regparm"" 1>&2; exit 1; }; sim_regparm="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then
-  echo "Setting regparm flags = $sim_regparm" 6>&1
-fi
-else
-  sim_regparm=""
-fi
-
-# Check whether --enable-sim-stdcall or --disable-sim-stdcall was given.
-if test "${enable_sim_stdcall+set}" = set; then
-  enableval="$enable_sim_stdcall"
-  case "${enableval}" in
-  no)          sim_stdcall="" ;;
-  std*)                sim_stdcall="-DWITH_STDCALL=1";;
-  yes)         sim_stdcall="-DWITH_STDCALL=1";;
-  *)   { echo "configure: error: "Unknown value $enableval for --enable-sim-stdcall"" 1>&2; exit 1; }; sim_stdcall="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then
-  echo "Setting function call flags = $sim_stdcall" 6>&1
-fi
-else
-  sim_stdcall=""
-fi
 
 # Check whether --enable-sim-hostendian or --disable-sim-hostendian was given.
 if test "${enable_sim_hostendian+set}" = set; then
@@ -1182,58 +1117,60 @@ else
   
 if test "x$cross_compiling" = "xno"; then
   echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:1121: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 1192 "configure"
+#line 1128 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
-int main() { return 0; }
-int t() {
+int main() {
 
 #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
  bogus endian macros
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:1204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1139: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 1208 "configure"
+#line 1143 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
-int main() { return 0; }
-int t() {
+int main() {
 
 #if BYTE_ORDER != BIG_ENDIAN
  not big endian
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:1220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1154: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_c_bigendian=no
 fi
 rm -f conftest*
-
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
 fi
 rm -f conftest*
-
 if test $ac_cv_c_bigendian = unknown; then
 if test "$cross_compiling" = yes; then
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
-cat > conftest.$ac_ext <<EOF
-#line 1237 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 1174 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -1246,15 +1183,19 @@ main () {
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-{ (eval echo configure:1250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
+if { (eval echo configure:1187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
   ac_cv_c_bigendian=no
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_c_bigendian=yes
 fi
-fi
 rm -fr conftest*
 fi
+
+fi
 fi
 
 echo "$ac_t""$ac_cv_c_bigendian" 1>&6
@@ -1275,6 +1216,245 @@ else
 fi
 fi
 
+
+# Check whether --enable-sim-icache or --disable-sim-icache was given.
+if test "${enable_sim_icache+set}" = set; then
+  enableval="$enable_sim_icache"
+  icache="-R"
+ case "${enableval}" in
+  yes)         icache="1024"; sim_icache="-I $icache";;
+  no)          sim_icache="-R";;
+  *) icache=1024
+     sim_icache="-"
+     for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
+       case "$x" in
+         define)       sim_icache="${sim_icache}R";;
+         semantic)     sim_icache="${sim_icache}C";;
+        insn)          sim_icache="${sim_icache}S";;
+        0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;;
+         *)            { echo "configure: error: "Unknown value $x for --enable-sim-icache"" 1>&2; exit 1; }; sim_icache="";;
+       esac
+     done
+     sim_icache="${sim_icache}I $icache";;
+esac
+if test x"$silent" != x"yes" && test x"$icache" != x""; then
+  echo "Setting instruction cache size to $icache ($sim_icache)"
+fi
+else
+  sim_icache="-CSRI 1024"
+if test x"$silent" != x"yes"; then
+  echo "Setting instruction cache size to 1024 ($sim_icache)"
+fi
+fi
+
+
+# Check whether --enable-sim-inline or --disable-sim-inline was given.
+if test "${enable_sim_inline+set}" = set; then
+  enableval="$enable_sim_inline"
+  sim_inline=""
+case "$enableval" in
+  no)          sim_inline="-DDEFAULT_INLINE=0";;
+  0)           sim_inline="-DDEFAULT_INLINE=0";;
+  yes | 2)     sim_inline="-DDEFAULT_INLINE=ALL_INLINE";;
+  1)           sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";;
+  *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do
+       new_flag=""
+       case "$x" in
+        *_INLINE=*)    new_flag="-D$x";;
+        *=*)           new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;;
+        *_INLINE)      new_flag="-D$x=ALL_INLINE";;
+        *)             new_flag="-D$x""_INLINE=ALL_INLINE";;
+       esac
+       if test x"$sim_inline" = x""; then
+        sim_inline="$new_flag"
+       else
+        sim_inline="$sim_inline $new_flag"
+       fi
+     done;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then
+  echo "Setting inline flags = $sim_inline" 6>&1
+fi
+else
+  if test x"$GCC" != ""; then
+  sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS"
+  if test x"$silent" != x"yes"; then
+    echo "Setting inline flags = $sim_inline" 6>&1
+  fi
+else
+  sim_inline=""
+fi
+fi
+
+
+# Check whether --enable-sim-jump or --disable-sim-jump was given.
+if test "${enable_sim_jump+set}" = set; then
+  enableval="$enable_sim_jump"
+  case "${enableval}" in
+  yes) sim_jump="-J";;
+  no)  sim_jump="";;
+  *)   { echo "configure: error: "--enable-sim-jump does not take a value"" 1>&2; exit 1; }; sim_jump="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
+  echo "Setting jump flag = $sim_jump" 6>&1
+fi
+else
+  sim_jump=""
+if test x"$silent" != x"yes"; then
+  echo "Setting jump flag = $sim_jump" 6>&1
+fi
+fi
+
+
+# Check whether --enable-sim-line-nr or --disable-sim-line-nr was given.
+if test "${enable_sim_line_nr+set}" = set; then
+  enableval="$enable_sim_line_nr"
+  case "${enableval}" in
+  yes) sim_line_nr="";;
+  no)  sim_line_nr="-L";;
+  *)   { echo "configure: error: "--enable-sim-line-nr does not take a value"" 1>&2; exit 1; }; sim_line_nr="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
+  echo "Setting warning flags = $sim_line_nr" 6>&1
+fi
+else
+  sim_line_nr=""
+fi
+
+
+# Check whether --enable-sim-model or --disable-sim-model was given.
+if test "${enable_sim_model+set}" = set; then
+  enableval="$enable_sim_model"
+  case "${enableval}" in
+  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };;
+  *)           sim_model="-DWITH_MODEL=${enableval}";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
+  echo "Setting model flags = $sim_model" 6>&1
+fi
+else
+  sim_model=""
+fi
+
+
+# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given.
+if test "${enable_sim_model_issue+set}" = set; then
+  enableval="$enable_sim_model_issue"
+  case "${enableval}" in
+  yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
+  no)  sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
+  *)   { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";;
+esac
+if test x"$silent" != x"yes"; then
+  echo "Setting model-issue flags = $sim_model_issue" 6>&1
+fi
+else
+  sim_model_issue=""
+fi
+
+
+# Check whether --enable-sim-monitor or --disable-sim-monitor was given.
+if test "${enable_sim_monitor+set}" = set; then
+  enableval="$enable_sim_monitor"
+  case "${enableval}" in
+  yes)         sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
+  no)          sim_monitor="-DWITH_MON=0";;
+  instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
+  memory)      sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
+  *)           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
+  echo "Setting monitor flags = $sim_monitor" 6>&1
+fi
+else
+  sim_monitor=""
+fi
+
+
+# Check whether --enable-sim-opcode or --disable-sim-opcode was given.
+if test "${enable_sim_opcode+set}" = set; then
+  enableval="$enable_sim_opcode"
+  case "${enableval}" in
+  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };;
+  *)           if test -f "${srcdir}/${enableval}"; then
+                 sim_opcode="${enableval}"
+               elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
+                 sim_opcode="ppc-opcode-${enableval}"
+               else
+                 { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; };
+                 sim_opcode="ppc-opcode-complex"
+               fi;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
+  echo "Setting opcode flags = $sim_opcode" 6>&1
+fi
+else
+  sim_opcode="ppc-opcode-complex"
+if test x"$silent" != x"yes"; then
+  echo "Setting opcode flags = $sim_opcode"
+fi
+fi
+
+
+# Check whether --enable-sim-packages or --disable-sim-packages was given.
+if test "${enable_sim_packages+set}" = set; then
+  enableval="$enable_sim_packages"
+  packages=disklabel
+case "${enableval}" in
+  yes) ;;
+  no)  { echo "configure: error: "List of packages must be specified for --enable-sim-packages"" 1>&2; exit 1; }; packages="";;
+  ,*)   packages="${packages}${enableval}";;
+  *,)   packages="${enableval}${packages}";;
+  *)   packages="${enableval}"'';;
+esac
+sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
+sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes" && test x"$packages" != x""; then
+  echo "Setting packages to $sim_pk_src, $sim_pk_obj"
+fi
+else
+  packages=disklabel
+sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'`
+sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes"; then
+  echo "Setting packages to $sim_pk_src, $sim_pk_obj"
+fi
+fi
+
+
+# Check whether --enable-sim-regparm or --disable-sim-regparm was given.
+if test "${enable_sim_regparm+set}" = set; then
+  enableval="$enable_sim_regparm"
+  case "${enableval}" in
+  0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";;
+  no)                            sim_regparm="" ;;
+  yes)                           sim_regparm="-DWITH_REGPARM=3";;
+  *)   { echo "configure: error: "Unknown value $enableval for --enable-sim-regparm"" 1>&2; exit 1; }; sim_regparm="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then
+  echo "Setting regparm flags = $sim_regparm" 6>&1
+fi
+else
+  sim_regparm=""
+fi
+
+
+# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given.
+if test "${enable_sim_reserved_bits+set}" = set; then
+  enableval="$enable_sim_reserved_bits"
+  case "${enableval}" in
+  yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
+  no)  sim_reserved="-DWITH_RESERVED_BITS=0";;
+  *)   { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
+  echo "Setting reserved flags = $sim_reserved" 6>&1
+fi
+else
+  sim_reserved=""
+fi
+
+
 # Check whether --enable-sim-smp or --disable-sim-smp was given.
 if test "${enable_sim_smp+set}" = set; then
   enableval="$enable_sim_smp"
@@ -1293,66 +1473,59 @@ if test x"$silent" != x"yes"; then
 fi
 fi
 
-# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given.
-if test "${enable_sim_xor_endian+set}" = set; then
-  enableval="$enable_sim_xor_endian"
-  case "${enableval}" in
-  yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";;
-  no)  sim_xor_endian="-DWITH_XOR_ENDIAN=0";;
-  *)   sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
-  echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
-fi
-else
-  sim_xor_endian=""
-fi
 
-# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given.
-if test "${enable_sim_bitsize+set}" = set; then
-  enableval="$enable_sim_bitsize"
+# Check whether --enable-sim-stdcall or --disable-sim-stdcall was given.
+if test "${enable_sim_stdcall+set}" = set; then
+  enableval="$enable_sim_stdcall"
   case "${enableval}" in
-  32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
-  *)    { echo "configure: error: "--enable-sim-bitsize was given $enableval" 1>&2; exit 1; }; sim_bitsize="";;
+  no)          sim_stdcall="" ;;
+  std*)                sim_stdcall="-DWITH_STDCALL=1";;
+  yes)         sim_stdcall="-DWITH_STDCALL=1";;
+  *)   { echo "configure: error: "Unknown value $enableval for --enable-sim-stdcall"" 1>&2; exit 1; }; sim_stdcall="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
-  echo "Setting bitsize flags = $sim_bitsize" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then
+  echo "Setting function call flags = $sim_stdcall" 6>&1
 fi
 else
-  sim_bitsize=""
+  sim_stdcall=""
 fi
 
-# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given.
-if test "${enable_sim_hostbitsize+set}" = set; then
-  enableval="$enable_sim_hostbitsize"
+
+# Check whether --enable-sim-stdio or --disable-sim-stdio was given.
+if test "${enable_sim_stdio+set}" = set; then
+  enableval="$enable_sim_stdio"
   case "${enableval}" in
-  32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
-  *)    { echo "configure: error: "--enable-sim-hostbitsize was given $enableval" 1>&2; exit 1; }; sim_hostbitsize="";;
+  yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";;
+  no)  sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";;
+  *)   { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
-  echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
+  echo "Setting stdio flags = $sim_stdio" 6>&1
 fi
 else
-  sim_hostbitsize=""
+  sim_stdio=""
 fi
 
-# Check whether --enable-sim-env or --disable-sim-env was given.
-if test "${enable_sim_env+set}" = set; then
-  enableval="$enable_sim_env"
+
+# Check whether --enable-sim-switch or --disable-sim-switch was given.
+if test "${enable_sim_switch+set}" = set; then
+  enableval="$enable_sim_switch"
   case "${enableval}" in
-  operating | os | oea)        sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
-  virtual | vea)       sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
-  user | uea)          sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
-  no)                  sim_env="-DWITH_ENVIRONMENT=0";;
-  *)                   { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";;
+  yes) sim_switch="-s";;
+  no)  sim_switch="";;
+  *)   { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";;
 esac
-if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
-  echo "Setting env flags = $sim_env" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
+  echo "Setting switch flags = $sim_switch" 6>&1
 fi
 else
-  sim_env=""
+  sim_switch="";
+if test x"$silent" != x"yes"; then
+  echo "Setting switch flags = $sim_switch" 6>&1
+fi
 fi
 
+
 # Check whether --enable-sim-timebase or --disable-sim-timebase was given.
 if test "${enable_sim_timebase+set}" = set; then
   enableval="$enable_sim_timebase"
@@ -1368,21 +1541,6 @@ else
   sim_timebase=""
 fi
 
-# Check whether --enable-sim-alignment or --disable-sim-alignment was given.
-if test "${enable_sim_alignment+set}" = set; then
-  enableval="$enable_sim_alignment"
-  case "${enableval}" in
-  yes | strict | STRICT)       sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
-  no | nonstrict | NONSTRICT)  sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
-  0 | default | DEFAULT)       sim_alignment="-DWITH_ALIGNMENT=0";;
-  *)                           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
-  echo "Setting alignment flags = $sim_alignment" 6>&1
-fi
-else
-  sim_alignment=""
-fi
 
 # Check whether --enable-sim-trace or --disable-sim-trace was given.
 if test "${enable_sim_trace+set}" = set; then
@@ -1399,125 +1557,38 @@ else
   sim_trace=""
 fi
 
-# Check whether --enable-sim-assert or --disable-sim-assert was given.
-if test "${enable_sim_assert+set}" = set; then
-  enableval="$enable_sim_assert"
-  case "${enableval}" in
-  yes) sim_assert="-DWITH_ASSERT=1";;
-  no)  sim_assert="-DWITH_ASSERT=0";;
-  *)   { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
-  echo "Setting assert flags = $sim_assert" 6>&1
-fi
-else
-  sim_assert=""
-fi
-
-# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given.
-if test "${enable_sim_reserved_bits+set}" = set; then
-  enableval="$enable_sim_reserved_bits"
-  case "${enableval}" in
-  yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
-  no)  sim_reserved="-DWITH_RESERVED_BITS=0";;
-  *)   { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
-  echo "Setting reserved flags = $sim_reserved" 6>&1
-fi
-else
-  sim_reserved=""
-fi
-
-# Check whether --enable-sim-float or --disable-sim-float was given.
-if test "${enable_sim_float+set}" = set; then
-  enableval="$enable_sim_float"
-  case "${enableval}" in
-  yes | hard)  sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
-  no | soft)   sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
-  *)           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
-  echo "Setting float flags = $sim_float" 6>&1
-fi
-else
-  sim_float=""
-fi
-
-# Check whether --enable-sim-monitor or --disable-sim-monitor was given.
-if test "${enable_sim_monitor+set}" = set; then
-  enableval="$enable_sim_monitor"
-  case "${enableval}" in
-  yes)         sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
-  no)          sim_monitor="-DWITH_MON=0";;
-  instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
-  memory)      sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
-  *)           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
-  echo "Setting monitor flags = $sim_monitor" 6>&1
-fi
-else
-  sim_monitor=""
-fi
 
-# Check whether --enable-sim-model or --disable-sim-model was given.
-if test "${enable_sim_model+set}" = set; then
-  enableval="$enable_sim_model"
+# Check whether --enable-sim-warnings or --disable-sim-warnings was given.
+if test "${enable_sim_warnings+set}" = set; then
+  enableval="$enable_sim_warnings"
   case "${enableval}" in
-  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };;
-  *)           sim_model="-DWITH_MODEL=${enableval}";;
+  yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";;
+  no)  sim_warnings="-w";;
+  *)   sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
 esac
-if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
-  echo "Setting model flags = $sim_model" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
+  echo "Setting warning flags = $sim_warnings" 6>&1
 fi
 else
-  sim_model=""
+  sim_warnings=""
 fi
 
-# Check whether --enable-sim-default-model or --disable-sim-default-model was given.
-if test "${enable_sim_default_model+set}" = set; then
-  enableval="$enable_sim_default_model"
-  case "${enableval}" in
-  yes|no)      { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };;
-  *)           sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
-  echo "Setting default-model flags = $sim_default_model" 6>&1
-fi
-else
-  sim_model=""
-fi
 
-# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given.
-if test "${enable_sim_model_issue+set}" = set; then
-  enableval="$enable_sim_model_issue"
+# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given.
+if test "${enable_sim_xor_endian+set}" = set; then
+  enableval="$enable_sim_xor_endian"
   case "${enableval}" in
-  yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
-  no)  sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
-  *)   { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";;
+  yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";;
+  no)  sim_xor_endian="-DWITH_XOR_ENDIAN=0";;
+  *)   sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";;
 esac
-if test x"$silent" != x"yes"; then
-  echo "Setting model-issue flags = $sim_model_issue" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
+  echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
 fi
 else
-  sim_model_issue=""
+  sim_xor_endian=""
 fi
 
-# Check whether --enable-sim-stdio or --disable-sim-stdio was given.
-if test "${enable_sim_stdio+set}" = set; then
-  enableval="$enable_sim_stdio"
-  case "${enableval}" in
-  yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";;
-  no)  sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";;
-  *)   { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
-  echo "Setting stdio flags = $sim_stdio" 6>&1
-fi
-else
-  sim_stdio=""
-fi
 
 ac_aux_dir=
 for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do
@@ -1566,6 +1637,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
 fi
 
 echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:1641: checking host system type" >&5
 
 host_alias=$host
 case "$host_alias" in
@@ -1580,12 +1652,13 @@ NONE)
 esac
 
 host=`$ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$host" 1>&6
 
 echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:1662: checking target system type" >&5
 
 target_alias=$target
 case "$target_alias" in
@@ -1597,12 +1670,13 @@ NONE)
 esac
 
 target=`$ac_config_sub $target_alias`
-target_cpu=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
-target_vendor=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
-target_os=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$target" 1>&6
 
 echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:1680: checking build system type" >&5
 
 build_alias=$build
 case "$build_alias" in
@@ -1614,9 +1688,9 @@ NONE)
 esac
 
 build=`$ac_config_sub $build_alias`
-build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
-build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
-build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$build" 1>&6
 
 test "$host_alias" != "$target_alias" &&
@@ -1649,28 +1723,29 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
 
 
 echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:1727: checking for st_blksize in struct stat" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1657 "configure"
+#line 1732 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
-int main() { return 0; }
-int t() {
+int main() {
 struct stat s; s.st_blksize;
 ; return 0; }
 EOF
-if { (eval echo configure:1666: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1740: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_blksize=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_struct_st_blksize=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
@@ -1682,28 +1757,29 @@ EOF
 fi
 
 echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
+echo "configure:1761: checking for st_blocks in struct stat" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1690 "configure"
+#line 1766 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
-int main() { return 0; }
-int t() {
+int main() {
 struct stat s; s.st_blocks;
 ; return 0; }
 EOF
-if { (eval echo configure:1699: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_blocks=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_struct_st_blocks=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_struct_st_blocks" 1>&6
@@ -1717,28 +1793,29 @@ else
 fi
 
 echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
+echo "configure:1797: checking for st_rdev in struct stat" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1725 "configure"
+#line 1802 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
-int main() { return 0; }
-int t() {
+int main() {
 struct stat s; s.st_rdev;
 ; return 0; }
 EOF
-if { (eval echo configure:1734: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1810: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_rdev=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_struct_st_rdev=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6
@@ -1750,28 +1827,29 @@ EOF
 fi
 
 echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:1831: checking whether struct tm is in sys/time.h or time.h" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1758 "configure"
+#line 1836 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <time.h>
-int main() { return 0; }
-int t() {
+int main() {
 struct tm *tp; tp->tm_sec;
 ; return 0; }
 EOF
-if { (eval echo configure:1767: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm=time.h
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_struct_tm=sys/time.h
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_struct_tm" 1>&6
@@ -1783,28 +1861,29 @@ EOF
 fi
 
 echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
+echo "configure:1865: checking for tm_zone in struct tm" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1791 "configure"
+#line 1870 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_cv_struct_tm>
-int main() { return 0; }
-int t() {
+int main() {
 struct tm tm; tm.tm_zone;
 ; return 0; }
 EOF
-if { (eval echo configure:1800: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1878: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm_zone=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_struct_tm_zone=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6
@@ -1815,30 +1894,31 @@ EOF
 
 else
   echo $ac_n "checking for tzname""... $ac_c" 1>&6
+echo "configure:1898: checking for tzname" >&5
 if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1823 "configure"
+#line 1903 "configure"
 #include "confdefs.h"
 #include <time.h>
 #ifndef tzname /* For SGI.  */
 extern char *tzname[]; /* RS6000 and others reject char **tzname.  */
 #endif
-int main() { return 0; }
-int t() {
+int main() {
 atoi(*tzname);
 ; return 0; }
 EOF
-if { (eval echo configure:1834: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_var_tzname=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_var_tzname=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_var_tzname" 1>&6
@@ -1852,6 +1932,7 @@ fi
 
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1936: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -1866,33 +1947,37 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1870 "configure"
+#line 1951 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1885 "configure"
+#line 1968 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1891: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1974: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP=/lib/cpp
 fi
@@ -1908,11 +1993,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:1997: checking for uid_t in sys/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1916 "configure"
+#line 2002 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -1941,14 +2027,15 @@ EOF
 fi
 
 echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
+echo "configure:2031: checking type of array argument to getgroups" >&5
 if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   if test "$cross_compiling" = yes; then
   ac_cv_type_getgroups=cross
 else
-cat > conftest.$ac_ext <<EOF
-#line 1952 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 2039 "configure"
 #include "confdefs.h"
 
 /* Thanks to Mike Rendell for this test.  */
@@ -1973,17 +2060,21 @@ main()
 }
 
 EOF
-{ (eval echo configure:1977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
+if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
     ac_cv_type_getgroups=gid_t
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_type_getgroups=int
 fi
-fi
 rm -fr conftest*
+fi
+
 if test $ac_cv_type_getgroups = cross; then
         cat > conftest.$ac_ext <<EOF
-#line 1987 "configure"
+#line 2078 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 EOF
@@ -2007,11 +2098,12 @@ EOF
 
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2102: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2015 "configure"
+#line 2107 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2019,13 +2111,15 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
   ac_cv_header_stdc=yes
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_header_stdc=no
 fi
@@ -2034,7 +2128,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2038 "configure"
+#line 2132 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2052,7 +2146,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2056 "configure"
+#line 2150 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2072,8 +2166,8 @@ if test $ac_cv_header_stdc = yes; then
 if test "$cross_compiling" = yes; then
   :
 else
-cat > conftest.$ac_ext <<EOF
-#line 2077 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 2171 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2084,15 +2178,19 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-{ (eval echo configure:2088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
+if { (eval echo configure:2182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
   :
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_header_stdc=no
 fi
-fi
 rm -fr conftest*
 fi
+
+fi
 fi
 
 echo "$ac_t""$ac_cv_header_stdc" 1>&6
@@ -2104,19 +2202,21 @@ EOF
 fi
 
 echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+echo "configure:2206: checking for mode_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2112 "configure"
+#line 2211 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "mode_t" >/dev/null 2>&1; then
+  egrep "mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_mode_t=yes
 else
@@ -2135,19 +2235,21 @@ EOF
 fi
 
 echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:2239: checking for off_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2143 "configure"
+#line 2244 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "off_t" >/dev/null 2>&1; then
+  egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_off_t=yes
 else
@@ -2166,19 +2268,21 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:2272: checking for pid_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2174 "configure"
+#line 2277 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "pid_t" >/dev/null 2>&1; then
+  egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_pid_t=yes
 else
@@ -2197,11 +2301,12 @@ EOF
 fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:2305: checking return type of signal handlers" >&5
 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2205 "configure"
+#line 2310 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -2214,20 +2319,20 @@ extern "C" void (*signal (int, void (*)(int)))(int);
 void (*signal ()) ();
 #endif
 
-int main() { return 0; }
-int t() {
+int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:2223: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2327: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_type_signal=int
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_type_signal" 1>&6
@@ -2237,19 +2342,21 @@ EOF
 
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:2346: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2245 "configure"
+#line 2351 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "size_t" >/dev/null 2>&1; then
+  egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_size_t=yes
 else
@@ -2268,11 +2375,12 @@ EOF
 fi
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:2379: checking for uid_t in sys/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2276 "configure"
+#line 2384 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -2301,14 +2409,15 @@ EOF
 fi
 
 
-for ac_func in cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink
+for ac_func in access cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2416: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2312 "configure"
+#line 2421 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2318,8 +2427,7 @@ else
     builtin and then its argument prototype would still apply.  */
 char $ac_func();
 
-int main() { return 0; }
-int t() {
+int main() {
 
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
@@ -2332,16 +2440,18 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=no"
 fi
 rm -f conftest*
-
 fi
+
 if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
   echo "$ac_t""yes" 1>&6
     ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
@@ -2357,24 +2467,27 @@ done
 
 for ac_hdr in fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h
 do
-ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2473: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2367 "configure"
+#line 2478 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2372: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2483: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
   eval "ac_cv_header_$ac_safe=yes"
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_header_$ac_safe=no"
 fi
@@ -2382,7 +2495,7 @@ rm -f conftest*
 fi
 if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-    ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
@@ -2395,34 +2508,35 @@ done
 ac_header_dirent=no
 for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
 do
-ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:2514: checking for $ac_hdr that defines DIR" >&5
 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2405 "configure"
+#line 2519 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_hdr>
-int main() { return 0; }
-int t() {
+int main() {
 DIR *dirp = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:2414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2527: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_header_dirent_$ac_safe=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_header_dirent_$ac_safe=no"
 fi
 rm -f conftest*
-
 fi
 if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-    ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'`
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
   cat >> confdefs.h <<EOF
 #define $ac_tr_hdr 1
 EOF
@@ -2433,30 +2547,32 @@ fi
 done
 # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
 if test $ac_header_dirent = dirent.h; then
-echo $ac_n "checking for -ldir""... $ac_c" 1>&6
-ac_lib_var=`echo dir'_'opendir | tr './+\055' '__p_'`
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:2552: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-ldir  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2445 "configure"
+#line 2560 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char opendir();
 
-int main() { return 0; }
-int t() {
+int main() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:2457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -2472,30 +2588,32 @@ else
 fi
 
 else
-echo $ac_n "checking for -lx""... $ac_c" 1>&6
-ac_lib_var=`echo x'_'opendir | tr './+\055' '__p_'`
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:2593: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-lx  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2484 "configure"
+#line 2601 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
 char opendir();
 
-int main() { return 0; }
-int t() {
+int main() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:2496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -2515,16 +2633,16 @@ fi
 
 sim_termio=""
 echo $ac_n "checking for struct termios""... $ac_c" 1>&6
+echo "configure:2637: checking for struct termios" >&5
 if eval "test \"`echo '$''{'ac_cv_termios_struct'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2523 "configure"
+#line 2642 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/termios.h>
-int main() { return 0; }
-int t() {
+int main() {
 static struct termios x;
  x.c_iflag = 0;
  x.c_oflag = 0;
@@ -2533,15 +2651,16 @@ static struct termios x;
  x.c_cc[NCCS] = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:2537: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2655: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_termios_struct=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_termios_struct=no
 fi
 rm -f conftest*
-
 fi
 
 echo "$ac_t""$ac_cv_termios_struct" 1>&6
@@ -2551,28 +2670,29 @@ fi
 
 if test "$ac_cv_termios_struct" = "yes"; then
   echo $ac_n "checking for c_line field in struct termios""... $ac_c" 1>&6
+echo "configure:2674: checking for c_line field in struct termios" >&5
   if eval "test \"`echo '$''{'ac_cv_termios_cline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2559 "configure"
+#line 2679 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/termios.h>
-int main() { return 0; }
-int t() {
+int main() {
 static struct termios x; x.c_line = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:2568: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2687: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_termios_cline=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_termios_cline=no
 fi
 rm -f conftest*
-
 fi
 
 
@@ -2586,16 +2706,16 @@ fi
 
 if test "$ac_cv_termios_struct" != "yes"; then
   echo $ac_n "checking for struct termio""... $ac_c" 1>&6
+echo "configure:2710: checking for struct termio" >&5
   if eval "test \"`echo '$''{'ac_cv_termio_struct'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2594 "configure"
+#line 2715 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/termio.h>
-int main() { return 0; }
-int t() {
+int main() {
 static struct termio x;
  x.c_iflag = 0;
  x.c_oflag = 0;
@@ -2604,15 +2724,16 @@ static struct termio x;
  x.c_cc[NCC] = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:2608: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_termio_struct=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_termio_struct=no
 fi
 rm -f conftest*
-
 fi
 
   echo "$ac_t""$ac_cv_termio_struct" 1>&6
@@ -2625,28 +2746,29 @@ fi
 
 if test "$ac_cv_termio_struct" = "yes"; then
   echo $ac_n "checking for c_line field in struct termio""... $ac_c" 1>&6
+echo "configure:2750: checking for c_line field in struct termio" >&5
   if eval "test \"`echo '$''{'ac_cv_termio_cline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2633 "configure"
+#line 2755 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/termio.h>
-int main() { return 0; }
-int t() {
+int main() {
 static struct termio x; x.c_line = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:2642: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2763: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_termio_cline=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_termio_cline=no
 fi
 rm -f conftest*
-
 fi
 
 
@@ -2658,6 +2780,56 @@ else
   ac_cv_termio_cline=no
 fi
 
+sim_devzero=""
+echo $ac_n "checking for /dev/zero""... $ac_c" 1>&6
+echo "configure:2786: checking for /dev/zero" >&5
+if eval "test \"`echo '$''{'ac_cv_devzero'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_devzero=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2794 "configure"
+#include "confdefs.h"
+#include <fcntl.h>
+main () {
+  char buf[2048];
+  int i;
+  int fd = open ("/dev/zero", O_RDONLY);
+  if (fd < 0)
+    return 1;
+  for (i = 0; i < sizeof (buf); i++)
+    buf[i] = 1;
+  if (read (fd, buf, sizeof (buf)) != sizeof (buf))
+    return 1;
+  for (i = 0; i < sizeof (buf); i++)
+    if (buf[i])
+      return 1;
+  return 0;
+}
+EOF
+if { (eval echo configure:2813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_devzero=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_devzero=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_devzero" 1>&6
+if test $ac_cv_devzero = yes; then
+  sim_devzero="-DHAVE_DEVZERO"
+else
+  sim_devzero=""
+fi
+
 
 
 
@@ -2666,6 +2838,7 @@ AR=${AR-ar}
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2842: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2730,6 +2903,7 @@ fi
 
 
 
+
 trap '' 1 2 15
 cat > confcache <<\EOF
 # This file is a shell script that caches the results of configure
@@ -2747,11 +2921,25 @@ cat > confcache <<\EOF
 # --recheck option to rerun configure.
 #
 EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
 (set) 2>&1 |
-  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
-  >> confcache
+  case `(ac_space=' '; set) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
 if cmp -s $cache_file confcache; then
   :
 else
@@ -2806,7 +2994,7 @@ do
     echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
     exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
   -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
-    echo "$CONFIG_STATUS generated by autoconf version 2.10"
+    echo "$CONFIG_STATUS generated by autoconf version 2.12"
     exit 0 ;;
   -help | --help | --hel | --he | --h)
     echo "\$ac_cs_usage"; exit 0 ;;
@@ -2909,23 +3097,60 @@ s%@sim_default_model@%$sim_default_model%g
 s%@sim_model_issue@%$sim_model_issue%g
 s%@sim_stdio@%$sim_stdio%g
 s%@sim_termio@%$sim_termio%g
+s%@sim_devzero@%$sim_devzero%g
 
 CEOF
 EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
 cat >> $CONFIG_STATUS <<EOF
 
 CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
 for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
-  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
   case "$ac_file" in
-  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
        ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
   *) ac_file_in="${ac_file}.in" ;;
   esac
 
-  # Adjust relative srcdir, etc. for subdirectories.
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
 
   # Remove last slash and all that follows it.  Not all systems have dirname.
   ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
@@ -2953,6 +3178,7 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
   [/$]*) INSTALL="$ac_given_INSTALL" ;;
   *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
   esac
+
   echo creating "$ac_file"
   rm -f "$ac_file"
   configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
@@ -2961,14 +3187,16 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
 # $configure_input" ;;
   *) ac_comsub= ;;
   esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
   sed -e "$ac_comsub
 s%@configure_input@%$configure_input%g
 s%@srcdir@%$srcdir%g
 s%@top_srcdir@%$top_srcdir%g
 s%@INSTALL@%$INSTALL%g
-" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
 fi; done
-rm -f conftest.subs
+rm -f conftest.s*
 
 # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
 # NAME is the cpp macro being defined and VALUE is the value it is being given.
@@ -2989,11 +3217,17 @@ ac_eB='$%\1#\2define\3'
 ac_eC=' '
 ac_eD='%g'
 
-CONFIG_HEADERS=${CONFIG_HEADERS-"config.h:config.in"}
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h:config.in"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
 for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
-  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
   case "$ac_file" in
-  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
        ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
   *) ac_file_in="${ac_file}.in" ;;
   esac
@@ -3001,7 +3235,8 @@ for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
   echo creating $ac_file
 
   rm -f conftest.frag conftest.in conftest.out
-  cp $ac_given_srcdir/$ac_file_in conftest.in
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
 
 EOF
 
@@ -3029,8 +3264,6 @@ EOF
 
 # Break up conftest.vals because some shells have a limit on
 # the size of here documents, and old seds have small limits too.
-# Maximum number of lines to put in a single here document.
-ac_max_here_lines=12
 
 rm -f conftest.tail
 while :
@@ -3072,7 +3305,11 @@ cat >> $CONFIG_STATUS <<\EOF
   fi
 fi; done
 
+EOF
+cat >> $CONFIG_STATUS <<EOF
 
+EOF
+cat >> $CONFIG_STATUS <<\EOF
 case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac
 exit 0
 EOF
index fa6ae13..1d34ab4 100644 (file)
@@ -237,11 +237,11 @@ fi])dnl
 
 
 AC_ARG_ENABLE(sim-icache,
-[  --enable-sim-icache=size            Specify instruction cache size.],
-[icache=""
+[  --enable-sim-icache=size            Specify instruction-decode cache size and type.],
+[icache="-R"
  case "${enableval}" in
   yes)         icache="1024"; sim_icache="-I $icache";;
-  no)          sim_icache="";;
+  no)          sim_icache="-R";;
   *) icache=1024
      sim_icache="-"
      for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
@@ -257,7 +257,7 @@ AC_ARG_ENABLE(sim-icache,
 esac
 if test x"$silent" != x"yes" && test x"$icache" != x""; then
   echo "Setting instruction cache size to $icache ($sim_icache)"
-fi],[sim_icache="-CSI 1024"
+fi],[sim_icache="-CSRI 1024"
 if test x"$silent" != x"yes"; then
   echo "Setting instruction cache size to 1024 ($sim_icache)"
 fi])dnl
@@ -307,7 +307,7 @@ AC_ARG_ENABLE(sim-jump,
 esac
 if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
   echo "Setting jump flag = $sim_jump" 6>&1
-fi],[sim_jump="-E"
+fi],[sim_jump=""
 if test x"$silent" != x"yes"; then
   echo "Setting jump flag = $sim_jump" 6>&1
 fi])dnl
index 83d9e3f..7d69c3f 100644 (file)
@@ -27,6 +27,9 @@
 #include "device_table.h"
 #include "cap.h"
 
+#include "events.h"
+#include "psim.h"
+
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -42,7 +45,6 @@
 #include <ctype.h>
 
 STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
-STATIC_INLINE_DEVICE (void) init_device_properties(device *, void*);
 
 /* property entries */
 
@@ -97,13 +99,13 @@ detach_device_interrupt_edge(device *me,
        && old_edge->dest_port == dest_port
        && old_edge->my_port == my_port) {
       if (old_edge->disposition == permenant_object)
-       device_error(me, "attempt to delete permenant interrupt\n");
+       device_error(me, "attempt to delete permenant interrupt");
       *list = old_edge->next;
       zfree(old_edge);
       return;
     }
   }
-  device_error(me, "attempt to delete unattached interrupt\n");
+  device_error(me, "attempt to delete unattached interrupt");
 }
 
 STATIC_INLINE_DEVICE\
@@ -133,6 +135,8 @@ struct _device {
   const char *name;
   device_unit unit_address;
   const char *path;
+  int nr_address_cells;
+  int nr_size_cells;
 
   /* device tree */
   device *parent;
@@ -156,6 +160,9 @@ struct _device {
   cap *ihandles;
   cap *phandles;
   psim *system;
+
+  /* debugging */
+  int trace;
 };
 
 
@@ -175,76 +182,13 @@ struct _device_instance {
 
 
 \f
-/* Device node: */
-
-INLINE_DEVICE\
-(device *)
-device_parent(device *me)
-{
-  return me->parent;
-}
-
-INLINE_DEVICE\
-(device *)
-device_sibling(device *me)
-{
-  return me->sibling;
-}
-
-INLINE_DEVICE\
-(device *)
-device_child(device *me)
-{
-  return me->children;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_name(device *me)
-{
-  return me->name;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_path(device *me)
-{
-  return me->path;
-}
-
-INLINE_DEVICE\
-(void *)
-device_data(device *me)
-{
-  return me->data;
-}
-
-INLINE_DEVICE\
-(psim *)
-device_system(device *me)
-{
-  return me->system;
-}
-
-INLINE_DEVICE\
-(const device_unit *)
-device_unit_address(device *me)
-{
-  return &me->unit_address;
-}
-
-
-\f
-/* device template: */
-
-/* determine the full name of the device.  If buf is specified it is
-   stored in there.  Failing that, a safe area of memory is allocated */
+/* creation */
 
 STATIC_INLINE_DEVICE\
 (const char *)
 device_full_name(device *leaf,
-                char *buf,
-                unsigned sizeof_buf)
+                 char *buf,
+                 unsigned sizeof_buf)
 {
   /* get a buffer */
   char full_name[1024];
@@ -256,23 +200,23 @@ device_full_name(device *leaf,
   /* construct a name */
   if (leaf->parent == NULL) {
     if (sizeof_buf < 1)
-      error("device_full_name: buffer overflow\n");
+      error("device_full_name: buffer overflow");
     *buf = '\0';
   }
   else {
     char unit[1024];
     device_full_name(leaf->parent, buf, sizeof_buf);
     if (leaf->parent != NULL
-       && leaf->parent->callback->convert.encode_unit(leaf->parent,
-                                                      &leaf->unit_address,
-                                                      unit+1,
-                                                      sizeof(unit)-1) > 0)
+        && device_encode_unit(leaf->parent,
+                              &leaf->unit_address,
+                              unit+1,
+                              sizeof(unit)-1) > 0)
       unit[0] = '@';
     else
       unit[0] = '\0';
     if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
-       >= sizeof_buf)
-      error("device_full_name: buffer overflow\n");
+        >= sizeof_buf)
+      error("device_full_name: buffer overflow");
     strcat(buf, "/");
     strcat(buf, leaf->name);
     strcat (buf, unit);
@@ -280,271 +224,10 @@ device_full_name(device *leaf,
   
   /* return it usefully */
   if (buf == full_name)
-    buf = strdup(full_name);
+    buf = (char *) strdup(full_name);
   return buf;
 }
 
-/* manipulate/lookup device names */
-
-typedef struct _name_specifier {
-  /* components in the full length name */
-  char *path;
-  char *property;
-  char *value;
-  /* current device */
-  char *name;
-  char *unit;
-  char *args;
-  /* previous device */
-  char *last_name;
-  char *last_unit;
-  char *last_args;
-  /* work area */
-  char buf[1024];
-} name_specifier;
-
-/* Given a device specifier, break it up into its main components:
-   path (and if present) property name and property value. */
-STATIC_INLINE_DEVICE\
-(int)
-split_device_specifier(const char *device_specifier,
-                      name_specifier *spec)
-{
-  char *chp;
-  if (strlen(device_specifier) >= sizeof(spec->buf))
-    error("split_device_specifier: buffer overflow\n");
-
-  /* expand aliases (later) */
-  strcpy(spec->buf, device_specifier);
-
-  /* strip the leading spaces and check that remainder isn't a comment */
-  chp = spec->buf;
-  while (*chp != '\0' && isspace(*chp))
-    chp++;
-  if (*chp == '\0' || *chp == '#')
-    return 0;
-
-  /* find the path and terminate it with null */
-  spec->path = chp;
-  while (*chp != '\0' && !isspace(*chp))
-    chp++;
-  if (*chp != '\0') {
-    *chp = '\0';
-    chp++;
-  }
-
-  /* and any value */
-  while (*chp != '\0' && isspace(*chp))
-    chp++;
-  spec->value = chp;
-
-  /* now go back and chop the property off of the path */
-  if (spec->value[0] == '\0') {
-    spec->property = NULL; /*not a property*/
-    spec->value = NULL;
-  }
-  else if (spec->value[0] == '>'
-          || spec->value[0] == '<') {
-    /* an interrupt spec */
-    spec->property = NULL;
-  }
-  else {
-    chp = strrchr(spec->path, '/');
-    if (chp == NULL) {
-      spec->property = spec->path;
-      spec->path = strchr(spec->property, '\0');
-    }
-    else {
-      *chp = '\0';
-      spec->property = chp+1;
-    }
-  }
-
-  /* and mark the rest as invalid */
-  spec->name = NULL;
-  spec->unit = NULL;
-  spec->args = NULL;
-  spec->last_name = NULL;
-  spec->last_unit = NULL;
-  spec->last_args = NULL;
-
-  return 1;
-}
-
-/* given a device specifier break it up into its main components -
-   path and property name - assuming that the last `device' is a
-   property name. */
-STATIC_INLINE_DEVICE\
-(int)
-split_property_specifier(const char *property_specifier,
-                        name_specifier *spec)
-{
-  if (split_device_specifier(property_specifier, spec)) {
-    if (spec->property == NULL) {
-      /* force the last name to be a property name */
-      char *chp = strrchr(spec->path, '/');
-      if (chp == NULL) {
-       spec->property = spec->path;
-       spec->path = strrchr(spec->property, '\0');;
-      }
-      else {
-       *chp = '\0';
-       spec->property = chp+1;
-      }
-    }
-    return 1;
-  }
-  else
-    return 0;
-}
-
-/* parse the next device name and split it up, return 0 when no more
-   names to parse */
-STATIC_INLINE_DEVICE\
-(int)
-split_device_name(name_specifier *spec)
-{
-  char *chp;
-  /* remember what came before */
-  spec->last_name = spec->name;
-  spec->last_unit = spec->unit;
-  spec->last_args = spec->args;
-  /* finished? */
-  if (spec->path[0] == '\0') {
-    spec->name = NULL;
-    spec->unit = NULL;
-    spec->args = NULL;
-    return 0;
-  }
-  /* break the device name from the path */
-  spec->name = spec->path;
-  chp = strchr(spec->name, '/');
-  if (chp == NULL)
-    spec->path = strchr(spec->name, '\0');
-  else {
-    spec->path = chp+1;
-    *chp = '\0';
-  }
-  /* now break out the unit */
-  chp = strchr(spec->name, '@');
-  if (chp == NULL) {
-    spec->unit = NULL;
-    chp = spec->name;
-  }
-  else {
-    *chp = '\0';
-    chp += 1;
-    spec->unit = chp;
-  }
-  /* finally any args */
-  chp = strchr(chp, ':');
-  if (chp == NULL)
-    spec->args = NULL;
-  else {
-    *chp = '\0';
-    spec->args = chp+1;
-  }
-  return 1;
-}
-
-/* parse the value, returning the next non-space token */
-
-STATIC_INLINE_DEVICE\
-(char *)
-split_value(name_specifier *spec)
-{
-  char *token;
-  if (spec->value == NULL)
-    return NULL;
-  /* skip leading white space */
-  while (isspace(spec->value[0]))
-    spec->value++;
-  if (spec->value[0] == '\0') {
-    spec->value = NULL;
-    return NULL;
-  }
-  token = spec->value;
-  /* find trailing space */
-  while (spec->value[0] != '\0' && !isspace(spec->value[0]))
-    spec->value++;
-  /* chop this value out */
-  if (spec->value[0] != '\0') {
-    spec->value[0] = '\0';
-    spec->value++;
-  }
-  return token;
-}
-
-
-
-/* traverse the path specified by spec starting at current */
-
-STATIC_INLINE_DEVICE\
-(device *)
-split_find_device(device *current,
-                 name_specifier *spec)
-{
-  /* strip off (and process) any leading ., .., ./ and / */
-  while (1) {
-    if (strncmp(spec->path, "/", strlen("/")) == 0) {
-      /* cd /... */
-      while (current != NULL && current->parent != NULL)
-       current = current->parent;
-      spec->path += strlen("/");
-    }
-    else if (strncmp(spec->path, "./", strlen("./")) == 0) {
-      /* cd ./... */
-      current = current;
-      spec->path += strlen("./");
-    }
-    else if (strncmp(spec->path, "../", strlen("../")) == 0) {
-      /* cd ../... */
-      if (current != NULL && current->parent != NULL)
-       current = current->parent;
-      spec->path += strlen("../");
-    }
-    else if (strcmp(spec->path, ".") == 0) {
-      /* cd . */
-      current = current;
-      spec->path += strlen(".");
-    }
-    else if (strcmp(spec->path, "..") == 0) {
-      /* cd . */
-      if (current != NULL && current->parent != NULL)
-       current = current->parent;
-      spec->path += strlen("..");
-    }
-    else
-      break;
-  }
-
-  /* now go through the path proper */
-
-  if (current == NULL) {
-    split_device_name(spec);
-    return current;
-  }
-
-  while (split_device_name(spec)) {
-    device_unit phys;
-    device *child;
-    current->callback->convert.decode_unit(current, spec->unit, &phys);
-    for (child = current->children; child != NULL; child = child->sibling) {
-      if (strcmp(spec->name, child->name) == 0) {
-       if (phys.nr_cells == 0
-           || memcmp(&phys, &child->unit_address, sizeof(device_unit)) == 0)
-         break;
-      }
-    }
-    if (child == NULL)
-      return current; /* search failed */
-    current = child;
-  }
-
-  return current;
-}
-
-
 STATIC_INLINE_DEVICE\
 (device *)
 device_create_from(const char *name,
@@ -566,7 +249,7 @@ device_create_from(const char *name,
   }
 
   /* give it a name */
-  new_device->name = strdup(name);
+  new_device->name = (char *) strdup(name);
   new_device->unit_address = *unit_address;
   new_device->path = device_full_name(new_device, NULL, 0);
 
@@ -582,35 +265,36 @@ device_create_from(const char *name,
     new_device->ihandles = cap_create(name);
     new_device->phandles = cap_create(name);
   }
+  else {
+    new_device->ihandles = device_root(parent)->ihandles;
+    new_device->phandles = device_root(parent)->phandles;
+  }
 
+  cap_add(new_device->phandles, new_device);
   return new_device;
 }
 
 
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
 (device *)
-device_template_create_device(device *parent,
-                             const char *name,
-                             const char *unit_address,
-                             const char *args)
+device_create(device *parent,
+             const char *base,
+             const char *name,
+             const char *unit_address,
+             const char *args)
 {
   const device_descriptor *const *table;
-  int name_len;
-  char *chp;
-  chp = strchr(name, '@');
-  name_len = (chp == NULL ? strlen(name) : chp - name);
   for (table = device_table; *table != NULL; table++) {
     const device_descriptor *descr;
     for (descr = *table; descr->name != NULL; descr++) {
-      if (strncmp(name, descr->name, name_len) == 0
-         && (descr->name[name_len] == '\0'
-             || descr->name[name_len] == '@')) {
+      if (strcmp(base, descr->name) == 0) {
        device_unit address = { 0 };
        void *data = NULL;
-       if (parent != NULL && parent->callback->convert.decode_unit != NULL)
-         parent->callback->convert.decode_unit(parent, 
-                                               unit_address,
-                                               &address);
+       if (parent != NULL)
+         if (device_decode_unit(parent, unit_address, &address) < 0)
+           device_error(parent, "invalid address %s for device %s",
+                        unit_address, name);
        if (descr->creator != NULL)
          data = descr->creator(name, &address, args);
        return device_create_from(name, &address, data,
@@ -618,10 +302,207 @@ device_template_create_device(device *parent,
       }
     }
   }
-  device_error(parent, "attempt to attach unknown device %s\n", name);
-  return NULL;
+  device_error(parent, "attempt to attach unknown device %s", name);
+  return NULL;
+}
+
+
+
+INLINE_DEVICE\
+(void)
+device_usage(int verbose)
+{
+  const device_descriptor *const *table;
+  if (verbose == 1) {
+    int pos = 0;
+    for (table = device_table; *table != NULL; table++) {
+      const device_descriptor *descr;
+      for (descr = *table; descr->name != NULL; descr++) {
+       pos += strlen(descr->name) + 2;
+       if (pos > 75) {
+         pos = strlen(descr->name) + 2;
+         printf_filtered("\n");
+       }
+       printf_filtered("  %s", descr->name);
+      }
+      printf_filtered("\n");
+    }
+  }
+  if (verbose > 1) {
+    for (table = device_table; *table != NULL; table++) {
+      const device_descriptor *descr;
+      for (descr = *table; descr->name != NULL; descr++) {
+       printf_filtered("  %s:\n", descr->name);
+       /* interrupt ports */
+       if (descr->callbacks->interrupt.ports != NULL) {
+         const device_interrupt_port_descriptor *ports =
+           descr->callbacks->interrupt.ports;
+         printf_filtered("    interrupt ports:");
+         while (ports->name != NULL) {
+           printf_filtered(" %s", ports->name);
+           ports++;
+         }
+         printf_filtered("\n");
+       }
+       /* general info */
+       if (descr->callbacks->usage != NULL)
+         descr->callbacks->usage(verbose);
+      }
+    }
+  }
+}
+
+
+
+\f
+/* Device node: */
+
+INLINE_DEVICE\
+(device *)
+device_parent(device *me)
+{
+  return me->parent;
+}
+
+INLINE_DEVICE\
+(device *)
+device_root(device *me)
+{
+  ASSERT(me != NULL);
+  while (me->parent != NULL)
+    me = me->parent;
+  return me;
+}
+
+INLINE_DEVICE\
+(device *)
+device_sibling(device *me)
+{
+  return me->sibling;
+}
+
+INLINE_DEVICE\
+(device *)
+device_child(device *me)
+{
+  return me->children;
+}
+
+INLINE_DEVICE\
+(const char *)
+device_name(device *me)
+{
+  return me->name;
+}
+
+INLINE_DEVICE\
+(const char *)
+device_path(device *me)
+{
+  return me->path;
+}
+
+INLINE_DEVICE\
+(void *)
+device_data(device *me)
+{
+  return me->data;
+}
+
+INLINE_DEVICE\
+(psim *)
+device_system(device *me)
+{
+  return me->system;
+}
+
+INLINE_DEVICE\
+(const device_unit *)
+device_unit_address(device *me)
+{
+  return &me->unit_address;
+}
+
+
+INLINE_DEVICE\
+(int)
+device_address_to_attach_address(device *me,
+                                const device_unit *address,
+                                int *attach_space,
+                                unsigned_word *attach_address,
+                                device *client)
+{
+  if (me->callback->convert.address_to_attach_address == NULL)
+    device_error(me, "no convert.address_to_attach_address method");
+  return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_size_to_attach_size(device *me,
+                          const device_unit *size,
+                          unsigned *nr_bytes,
+                          device *client)
+{
+  if (me->callback->convert.size_to_attach_size == NULL)
+    device_error(me, "no convert.size_to_attach_size method");
+  return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_decode_unit(device *bus,
+                  const char *unit,
+                  device_unit *address)
+{
+  if (bus->callback->convert.decode_unit == NULL)
+    device_error(bus, "no convert.decode_unit method");
+  return bus->callback->convert.decode_unit(bus, unit, address);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_encode_unit(device *bus,
+                  const device_unit *unit_address,
+                  char *buf,
+                  int sizeof_buf)
+{
+  if (bus->callback->convert.encode_unit == NULL)
+    device_error(bus, "no convert.encode_unit method");
+  return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
+}
+
+INLINE_DEVICE\
+(unsigned)
+device_nr_address_cells(device *me)
+{
+  if (me->nr_address_cells == 0) {
+    if (device_find_property(me, "#address-cells") != NULL)
+      me->nr_address_cells = device_find_integer_property(me, "#address-cells");
+    else
+      me->nr_address_cells = 2;
+  }
+  return me->nr_address_cells;
+}
+
+INLINE_DEVICE\
+(unsigned)
+device_nr_size_cells(device *me)
+{
+  if (me->nr_size_cells == 0) {
+    if (device_find_property(me, "#size-cells") != NULL)
+      me->nr_size_cells = device_find_integer_property(me, "#size-cells");
+    else
+      me->nr_size_cells = 1;
+  }
+  return me->nr_size_cells;
 }
 
+
 \f
 /* device-instance: */
 
@@ -636,29 +517,40 @@ device_create_instance_from(device *me,
 {
   device_instance *instance = ZALLOC(device_instance);
   if ((me == NULL) == (parent == NULL))
-    device_error(me, "can't have both parent instance and parent device\n");
-  instance->owner = me;
-  instance->parent = parent;
-  instance->data = data;
-  instance->args = (args == NULL ? NULL : strdup(args));
-  instance->path = (path == NULL ? NULL : strdup(path));
-  instance->callback = callbacks;
+    device_error(me, "can't have both parent instance and parent device");
   /*instance->unit*/
+  /* link this instance into the devices list */
   if (me != NULL) {
+    ASSERT(parent == NULL);
+    instance->owner = me;
+    instance->parent = NULL;
+    /* link this instance into the front of the devices instance list */
     instance->next = me->instances;
     me->instances = instance;
   }
   if (parent != NULL) {
     device_instance **previous;
+    ASSERT(parent->child == NULL);
     parent->child = instance;
+    ASSERT(me == NULL);
     instance->owner = parent->owner;
+    instance->parent = parent;
+    /* in the devices instance list replace the parent instance with
+       this one */
     instance->next = parent->next;
     /* replace parent with this new node */
     previous = &instance->owner->instances;
-    while (*previous != parent)
+    while (*previous != parent) {
+      ASSERT(*previous != NULL);
       previous = &(*previous)->next;
+    }
     *previous = instance;
   }
+  instance->data = data;
+  instance->args = (args == NULL ? NULL : (char *) strdup(args));
+  instance->path = (path == NULL ? NULL : (char *) strdup(path));
+  instance->callback = callbacks;
+  cap_add(instance->owner->ihandles, instance);
   return instance;
 }
 
@@ -666,22 +558,16 @@ device_create_instance_from(device *me,
 INLINE_DEVICE\
 (device_instance *)
 device_create_instance(device *me,
-                      const char *device_specifier)
+                      const char *path,
+                      const char *args)
 {
-  /* find the device node */
-  name_specifier spec;
-  if (!split_device_specifier(device_specifier, &spec))
-    return NULL;
-  me = split_find_device(me, &spec);
-  if (spec.name != NULL)
-    return NULL;
   /* create the instance */
   if (me->callback->instance_create == NULL)
-    device_error(me, "no instance_create method\n");
-  return me->callback->instance_create(me,
-                                      device_specifier, spec.last_args);
+    device_error(me, "no instance_create method");
+  return me->callback->instance_create(me, path, args);
 }
 
+
 STATIC_INLINE_DEVICE\
 (void)
 clean_device_instances(device *me)
@@ -694,24 +580,40 @@ clean_device_instances(device *me)
   }
 }
 
+
 INLINE_DEVICE\
 (void)
 device_instance_delete(device_instance *instance)
 {
   device *me = instance->owner;
-  device_instance **curr;
   if (instance->callback->delete == NULL)
-    device_error(me, "no delete method\n");
+    device_error(me, "no delete method");
   instance->callback->delete(instance);
   if (instance->args != NULL)
     zfree(instance->args);
   if (instance->path != NULL)
     zfree(instance->path);
-  curr = &me->instances;
-  while (*curr != NULL && *curr != instance)
-    curr = &(*curr)->next;
-  ASSERT(*curr != NULL);
-  *curr = instance->next;
+  if (instance->child == NULL) {
+    /* only remove leaf nodes */
+    device_instance **curr = &me->instances;
+    while (*curr != instance) {
+      ASSERT(*curr != NULL);
+      curr = &(*curr)->next;
+    }
+    *curr = instance->next;
+  }
+  else {
+    /* check it isn't in the instance list */
+    device_instance *curr = me->instances;
+    while (curr != NULL) {
+      ASSERT(curr != instance);
+      curr = curr->next;
+    }
+    /* unlink the child */
+    ASSERT(instance->child->parent == instance);
+    instance->child->parent = NULL;
+  }
+  cap_remove(me->ihandles, instance);
   zfree(instance);
 }
 
@@ -723,7 +625,7 @@ device_instance_read(device_instance *instance,
 {
   device *me = instance->owner;
   if (instance->callback->read == NULL)
-    device_error(me, "no read method\n");
+    device_error(me, "no read method");
   return instance->callback->read(instance, addr, len);
 }
 
@@ -735,7 +637,7 @@ device_instance_write(device_instance *instance,
 {
   device *me = instance->owner;
   if (instance->callback->write == NULL)
-    device_error(me, "no write method\n");
+    device_error(me, "no write method");
   return instance->callback->write(instance, addr, len);
 }
 
@@ -747,34 +649,36 @@ device_instance_seek(device_instance *instance,
 {
   device *me = instance->owner;
   if (instance->callback->seek == NULL)
-    device_error(me, "no seek method\n");
+    device_error(me, "no seek method");
   return instance->callback->seek(instance, pos_hi, pos_lo);
 }
 
 INLINE_DEVICE\
-(unsigned_word)
-device_instance_claim(device_instance *instance,
-                     unsigned_word address,
-                     unsigned_word length,
-                     unsigned_word alignment)
+(int)
+device_instance_call_method(device_instance *instance,
+                           const char *method_name,
+                           int n_stack_args,
+                           unsigned_cell stack_args[/*n_stack_args*/], 
+                           int n_stack_returns,
+                           unsigned_cell stack_returns[/*n_stack_args*/])
 {
   device *me = instance->owner;
-  if (instance->callback->claim == NULL)
-    device_error(me, "no claim method\n");
-  return instance->callback->claim(instance, address, length, alignment);
+  const device_instance_methods *method = instance->callback->methods;
+  if (method == NULL) {
+    device_error(me, "no methods (want %s)", method_name);
+  }
+  while (method->name != NULL) {
+    if (strcmp(method->name, method_name) == 0) {
+      return method->method(instance,
+                           n_stack_args, stack_args,
+                           n_stack_returns, stack_returns);
+    }
+    method++;
+  }
+  device_error(me, "no %s method", method_name);
+  return 0;
 }
 
-INLINE_DEVICE\
-(void)
-device_instance_release(device_instance *instance,
-                       unsigned_word address,
-                       unsigned_word length)
-{
-  device *me = instance->owner;
-  if (instance->callback->release == NULL)
-    device_error(me, "no release method\n");
-  instance->callback->release(instance, address, length);
-}
 
 INLINE_DEVICE\
 (device *)
@@ -799,64 +703,24 @@ device_instance_data(device_instance *instance)
 
 
 \f
-/* Device initialization: */
-
-STATIC_INLINE_DEVICE\
-(void)
-clean_device(device *root,
-            void *data)
-{
-  psim *system;
-  system = (psim*)data;
-  clean_device_interrupt_edges(&root->interrupt_destinations);
-  clean_device_instances(root);
-  clean_device_properties(root);
-}
-
-STATIC_INLINE_DEVICE\
-(void)
-init_device_address(device *me,
-                   void *data)
-{
-  psim *system = (psim*)data;
-  TRACE(trace_device_init, ("init_device_address() initializing %s\n", me->path));
-  me->system = system; /* misc things not known until now */
-  if (me->callback->init.address != NULL)
-    me->callback->init.address(me);
-}
+/* Device Properties: */
 
 STATIC_INLINE_DEVICE\
-(void)
-init_device_data(device *me,
-                void *data)
-{
-  TRACE(trace_device_init, ("device_init_data() initializing %s\n", me->path));
-  if (me->callback->init.data != NULL)
-    me->callback->init.data(me);
-}
-
-INLINE_DEVICE\
-(void)
-device_tree_init(device *root,
-                psim *system)
+(device_property_entry *)
+find_property_entry(device *me,
+                    const char *property)
 {
-  TRACE(trace_device_tree, ("device_tree_init(root=0x%lx, system=0x%lx)\n",
-                           (long)root,
-                           (long)system));
-  /* remove the old, rebuild the new */
-  device_tree_traverse(root, clean_device, NULL, system);
-  TRACE(trace_tbd, ("Need to dump the device tree here\n"));
-  device_tree_traverse(root, init_device_address, NULL, system);
-  device_tree_traverse(root, init_device_properties, NULL, system);
-  device_tree_traverse(root, init_device_data, NULL, system);
-  TRACE(trace_device_tree, ("device_tree_init() = void\n"));
+  device_property_entry *entry;
+  ASSERT(property != NULL);
+  entry = me->properties;
+  while (entry != NULL) {
+    if (strcmp(entry->value->name, property) == 0)
+      return entry;
+    entry = entry->next;
+  }
+  return NULL;
 }
 
-
-\f
-/* Device Properties: */
-
-/* local - not available externally */
 STATIC_INLINE_DEVICE\
 (void)
 device_add_property(device *me,
@@ -871,8 +735,6 @@ device_add_property(device *me,
 {
   device_property_entry *new_entry = NULL;
   device_property *new_value = NULL;
-  void *new_array = NULL;
-  void *new_init_array = NULL;
 
   /* find the list end */
   device_property_entry **insertion_point = &me->properties;
@@ -884,26 +746,28 @@ device_add_property(device *me,
 
   /* create a new value */
   new_value = ZALLOC(device_property);
-  new_value->name = strdup(property);
+  new_value->name = (char *) strdup(property);
   new_value->type = type;
-  new_value->sizeof_array = sizeof_array;
-  new_array = (sizeof_array > 0 ? zalloc(sizeof_array) : NULL);
-  new_value->array = new_array;
+  if (sizeof_array > 0) {
+    void *new_array = zalloc(sizeof_array);
+    memcpy(new_array, array, sizeof_array);
+    new_value->array = new_array;
+    new_value->sizeof_array = sizeof_array;
+  }
   new_value->owner = me;
   new_value->original = original;
   new_value->disposition = disposition;
-  if (sizeof_array > 0)
-    memcpy(new_array, array, sizeof_array);
 
   /* insert the value into the list */
   new_entry = ZALLOC(device_property_entry);
   *insertion_point = new_entry;
-  new_entry->sizeof_init_array = sizeof_init_array;
-  new_init_array = (sizeof_init_array > 0 ? zalloc(sizeof_init_array) : NULL);
-  new_entry->init_array = new_init_array;
-  new_entry->value = new_value;
-  if (sizeof_init_array > 0)
+  if (sizeof_init_array > 0) {
+    void *new_init_array = zalloc(sizeof_init_array);
     memcpy(new_init_array, init_array, sizeof_init_array);
+    new_entry->init_array = new_init_array;
+    new_entry->sizeof_init_array = sizeof_init_array;
+  }
+  new_entry->value = new_value;
 
 }
 
@@ -915,35 +779,35 @@ device_set_property(device *me,
                    const char *property,
                    device_property_type type,
                    const void *array,
-                   int sizeof_array,
-                   const device_property *original)
+                   int sizeof_array)
 {
   /* find the property */
-  device_property_entry *entry = me->properties;
-  while (entry != NULL) {
-    if (strcmp(entry->value->name, property) == 0) {
-      void *new_array = 0;
-      device_property *value = entry->value;
-      /* check the type matches */
-      if (value->type != type)
-       device_error(me, "conflict between type of new and old value for property %s\n", property);
-      /* replace its value */
-      if (value->array != NULL)
-       zfree((void*)value->array);
-      new_array = (sizeof_array > 0
-                  ? zalloc(sizeof_array)
-                  : (void*)0);
-      value->array = new_array;
-      value->sizeof_array = sizeof_array;
-      if (sizeof_array > 0)
-       memcpy(new_array, array, sizeof_array);
-      return;
-    }
-    entry = entry->next;
+  device_property_entry *entry = find_property_entry(me, property);
+  if (entry != NULL) {
+    /* existing property - update it */
+    void *new_array = 0;
+    device_property *value = entry->value;
+    /* check the type matches */
+    if (value->type != type)
+      device_error(me, "conflict between type of new and old value for property %s", property);
+    /* replace its value */
+    if (value->array != NULL)
+      zfree((void*)value->array);
+    new_array = (sizeof_array > 0
+                ? zalloc(sizeof_array)
+                : (void*)0);
+    value->array = new_array;
+    value->sizeof_array = sizeof_array;
+    if (sizeof_array > 0)
+      memcpy(new_array, array, sizeof_array);
+    return;
+  }
+  else {
+    /* new property - create it */
+    device_add_property(me, property, type,
+                       NULL, 0, array, sizeof_array,
+                       NULL, tempoary_object);
   }
-  device_add_property(me, property, type,
-                     NULL, 0, array, sizeof_array,
-                     original, tempoary_object);
 }
 
 
@@ -954,70 +818,105 @@ clean_device_properties(device *me)
   device_property_entry **delete_point = &me->properties;
   while (*delete_point != NULL) {
     device_property_entry *current = *delete_point;
-    device_property *property = current->value;
     switch (current->value->disposition) {
     case permenant_object:
-      {
-       /* delete the property, and replace it with the original */
-       ASSERT(((property->array == NULL) == (current->init_array == NULL))
-              || property->type == ihandle_property);
-       if (current->init_array != NULL) {
-         zfree((void*)current->value->array);
-         current->value->array = NULL;
-         if (property->type != ihandle_property) {
-           device_set_property(me, property->name,
-                               property->type,
-                               current->init_array, current->sizeof_init_array,
-                               NULL);
-         }
-       }
-       delete_point = &(*delete_point)->next;
+      /* zap the current value, will be initialized later */
+      ASSERT(current->init_array != NULL);
+      if (current->value->array != NULL) {
+       zfree((void*)current->value->array);
+       current->value->array = NULL;
       }
+      delete_point = &(*delete_point)->next;
       break;
     case tempoary_object:
-      {
-       /* zap the actual property, was created during simulation run */
-       *delete_point = current->next;
-       if (current->value->array != NULL)
-         zfree((void*)current->value->array);
-       zfree(current->value);
-       zfree(current);
-      }
+      /* zap the actual property, was created during simulation run */
+      ASSERT(current->init_array == NULL);
+      *delete_point = current->next;
+      if (current->value->array != NULL)
+       zfree((void*)current->value->array);
+      zfree(current->value);
+      zfree(current);
       break;
     }
   }
 }
 
 
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
+(void)
+device_init_static_properties(device *me,
+                             void *data)
+{
+  device_property_entry *property;
+  for (property = me->properties;
+       property != NULL;
+       property = property->next) {
+    ASSERT(property->init_array != NULL);
+    ASSERT(property->value->array == NULL);
+    ASSERT(property->value->disposition == permenant_object);
+    switch (property->value->type) {
+    case array_property:
+    case boolean_property:
+    case range_array_property:
+    case reg_array_property:
+    case string_property:
+    case string_array_property:
+    case integer_property:
+      /* delete the property, and replace it with the original */
+      device_set_property(me, property->value->name,
+                         property->value->type,
+                         property->init_array,
+                         property->sizeof_init_array);
+      break;
+    case ihandle_property:
+      break;
+    }
+  }
+}
+
+
+INLINE_DEVICE\
 (void)
-init_device_properties(device *me,
-                      void *data)
-{
-  device_property_entry *property = me->properties;
-  while (property != NULL) {
-    /* now do the phandles */
-    if (property->value->type == ihandle_property) {
-      if (property->value->original != NULL) {
-       const device_property *original = property->value->original;
-       if (original->array == NULL) {
-         init_device_properties(original->owner, data);
+device_init_runtime_properties(device *me,
+                              void *data)
+{
+  device_property_entry *property;
+  for (property = me->properties;
+       property != NULL;
+       property = property->next) {
+    switch (property->value->disposition) {
+    case permenant_object:
+      switch (property->value->type) {
+      case ihandle_property:
+       {
+         device_instance *ihandle;
+         ihandle_runtime_property_spec spec;
+         ASSERT(property->init_array != NULL);
+         ASSERT(property->value->array == NULL);
+         device_find_ihandle_runtime_property(me, property->value->name, &spec);
+         ihandle = device_create_instance(spec.phandle, 
+                                          spec.full_path,
+                                          spec.args);
+         device_set_ihandle_property(me, property->value->name, ihandle);
+         break;
        }
-       ASSERT(original->array != NULL);
-       device_set_property(me, property->value->name,
-                           ihandle_property,
-                           original->array, original->sizeof_array, NULL);
-      }
-      else {
-       device_instance *instance =
-         device_create_instance(me, (char*)property->init_array);
-       unsigned32 ihandle = H2BE_4(device_instance_to_external(instance));
-       device_set_property(me, property->value->name,
-                           ihandle_property,
-                           &ihandle, sizeof(ihandle), NULL);
+      case array_property:
+      case boolean_property:
+      case range_array_property:
+      case integer_property:
+      case reg_array_property:
+      case string_property:
+      case string_array_property:
+       ASSERT(property->init_array != NULL);
+       ASSERT(property->value->array != NULL);
+       break;
       }
+      break;
+    case tempoary_object:
+      ASSERT(property->init_array == NULL);
+      ASSERT(property->value->array != NULL);
+      break;
     }
-    property = property->next;
   }
 }
 
@@ -1039,12 +938,12 @@ device_next_property(const device_property *property)
     return NULL;
 }
 
+
 INLINE_DEVICE\
 (const device_property *)
 device_find_property(device *me,
                     const char *property)
 {
-  name_specifier spec;
   if (me == NULL) {
     return NULL;
   }
@@ -1054,33 +953,25 @@ device_find_property(device *me,
     else
       return me->properties->value;
   }
-  else if (split_property_specifier(property, &spec)) {
-    me = split_find_device(me, &spec);
-    if (spec.name == NULL) { /*got to root*/
-      device_property_entry *entry = me->properties;
-      while (entry != NULL) {
-       if (strcmp(entry->value->name, spec.property) == 0)
-         return entry->value;
-       entry = entry->next;
-      }
-    }
+  else {
+    device_property_entry *entry = find_property_entry(me, property);
+    if (entry != NULL)
+      return entry->value;
   }
   return NULL;
 }
 
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
 (void)
 device_add_array_property(device *me,
-                         const char *property,
-                         const void *array,
-                         int sizeof_array)
+                          const char *property,
+                          const void *array,
+                          int sizeof_array)
 {
-  TRACE(trace_devices,
-       ("device_add_array_property(me=0x%lx, property=%s, ...)\n",
-        (long)me, property));
   device_add_property(me, property, array_property,
-                     array, sizeof_array, array, sizeof_array,
-                     NULL, permenant_object);
+                      array, sizeof_array, array, sizeof_array,
+                      NULL, permenant_object);
 }
 
 INLINE_DEVICE\
@@ -1090,10 +981,7 @@ device_set_array_property(device *me,
                          const void *array,
                          int sizeof_array)
 {
-  TRACE(trace_devices,
-       ("device_set_array_property(me=0x%lx, property=%s, ...)\n",
-        (long)me, property));
-  device_set_property(me, property, array_property, array, sizeof_array, NULL);
+  device_set_property(me, property, array_property, array, sizeof_array);
 }
 
 INLINE_DEVICE\
@@ -1102,31 +990,25 @@ device_find_array_property(device *me,
                           const char *property)
 {
   const device_property *node;
-  TRACE(trace_devices,
-       ("device_find_integer(me=0x%lx, property=%s)\n",
-        (long)me, property));
   node = device_find_property(me, property);
   if (node == (device_property*)0
       || node->type != array_property)
-    device_error(me, "property %s not found or of wrong type\n", property);
+    device_error(me, "property %s not found or of wrong type", property);
   return node;
 }
 
 
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
 (void)
 device_add_boolean_property(device *me,
-                           const char *property,
-                           int boolean)
+                            const char *property,
+                            int boolean)
 {
   signed32 new_boolean = (boolean ? -1 : 0);
-  TRACE(trace_devices,
-       ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n",
-        (long)me, property, boolean));
   device_add_property(me, property, boolean_property,
-                     &new_boolean, sizeof(new_boolean),
-                     &new_boolean, sizeof(new_boolean),
-                     NULL, permenant_object);
+                      &new_boolean, sizeof(new_boolean),
+                      &new_boolean, sizeof(new_boolean),
+                      NULL, permenant_object);
 }
 
 INLINE_DEVICE\
@@ -1135,108 +1017,427 @@ device_find_boolean_property(device *me,
                             const char *property)
 {
   const device_property *node;
-  unsigned32 boolean;
-  TRACE(trace_devices,
-       ("device_find_boolean(me=0x%lx, property=%s)\n",
-        (long)me, property));
+  unsigned_cell boolean;
   node = device_find_property(me, property);
   if (node == (device_property*)0
       || node->type != boolean_property)
-    device_error(me, "property %s not found or of wrong type\n", property);
+    device_error(me, "property %s not found or of wrong type", property);
   ASSERT(sizeof(boolean) == node->sizeof_array);
   memcpy(&boolean, node->array, sizeof(boolean));
   return boolean;
 }
 
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
 (void)
-device_add_ihandle_property(device *me,
-                           const char *property,
-                           const char *path)
+device_add_ihandle_runtime_property(device *me,
+                                   const char *property,
+                                   const ihandle_runtime_property_spec *ihandle)
 {
-  TRACE(trace_devices,
-       ("device_add_ihandle_property(me=0x%lx, property=%s, path=%s)\n",
-        (long)me, property, path));
+  unsigned_cell *cells;
+  char *chp;
+  unsigned sizeof_cells = (sizeof(unsigned_cell) * 3
+                          + (strlen(ihandle->full_path) + 1)
+                          + (ihandle->args != NULL
+                             ? (strlen(ihandle->args) + 1)
+                             : 0));
+
+  /* the basics */
+  cells = zalloc(sizeof_cells);
+  cells[0] = H2BE_cell(device_to_external(ihandle->phandle));
+  cells[1] = (ihandle->full_path == NULL ? 0 : -1);
+  cells[2] = (ihandle->args == NULL ? 0 : -1);
+  chp = (char*)&cells[3];
+
+  /* the full path (if present) */
+  if (ihandle->full_path != NULL) {
+    strcpy(chp, ihandle->full_path);
+    chp += strlen(ihandle->full_path) + 1;
+  }
+
+  /* the args (if present) */
+  if (ihandle->args != NULL) {
+    strcpy(chp, ihandle->args);
+    chp += strlen(ihandle->args) + 1;
+  }
+
+  /* add it */
+  ASSERT(sizeof_cells == (chp - (char*)cells));
   device_add_property(me, property, ihandle_property,
-                     path, strlen(path) + 1,
+                     cells, sizeof_cells,
                      NULL, 0,
                      NULL, permenant_object);
 }
 
 INLINE_DEVICE\
+(void)
+device_find_ihandle_runtime_property(device *me,
+                                    const char *property,
+                                    ihandle_runtime_property_spec *ihandle)
+{
+  const unsigned_cell *cells;
+  const char *chp;
+  device_property_entry *entry = find_property_entry(me, property);
+  TRACE(trace_devices,
+       ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
+        (long)me, property));
+  if (entry == NULL
+      || entry->value->type != ihandle_property
+      || entry->value->disposition != permenant_object)
+    device_error(me, "property %s not found or of wrong type", property);
+  cells = entry->init_array;
+  chp = (char*)&cells[3];
+  ASSERT(entry->init_array != NULL);
+  /* the device to be opened */
+  ihandle->phandle = external_to_device(me, BE2H_cell(cells[0]));
+  /* the full path */
+  if (cells[1] != 0) {
+    ihandle->full_path = chp;
+    chp += strlen(ihandle->full_path) + 1;
+  }
+  else
+    ihandle->full_path = NULL;
+  /* the args */
+  if (cells[2] != 0) {
+    ihandle->args = chp;
+    chp += strlen(ihandle->args) + 1;
+  }
+  else
+    ihandle->args = NULL;
+  /* reached the end? */
+  ASSERT(entry->sizeof_init_array
+        == (chp - (char*)cells));
+  return;
+}
+
+
+
+INLINE_DEVICE\
+(void)
+device_set_ihandle_property(device *me,
+                           const char *property,
+                           device_instance *ihandle)
+{
+  unsigned_cell cells;
+  cells = H2BE_cell(device_instance_to_external(ihandle));
+  device_set_property(me, property, ihandle_property,
+                     &cells, sizeof(cells));
+                     
+}
+
+INLINE_DEVICE\
 (device_instance *)
 device_find_ihandle_property(device *me,
                             const char *property)
 {
   const device_property *node;
-  unsigned32 ihandle;
+  unsigned_cell ihandle;
   device_instance *instance;
-  TRACE(trace_devices,
-       ("device_find_ihandle_property(me=0x%lx, property=%s)\n",
-        (long)me, property));
+
   node = device_find_property(me, property);
   if (node == NULL || node->type != ihandle_property)
-    device_error(me, "property %s not found or of wrong type\n", property);
+    device_error(me, "property %s not found or of wrong type", property);
   if (node->array == NULL)
-    device_error(me, "property %s not yet initialized\n", property);
+    device_error(me, "runtime property %s not yet initialized", property);
+
   ASSERT(sizeof(ihandle) == node->sizeof_array);
   memcpy(&ihandle, node->array, sizeof(ihandle));
-  BE2H(ihandle);
-  instance = external_to_device_instance(me, ihandle);
+  instance = external_to_device_instance(me, BE2H_cell(ihandle));
   ASSERT(instance != NULL);
   return instance;
 }
 
+
+INLINE_DEVICE\
+(void)
+device_add_integer_property(device *me,
+                           const char *property,
+                           signed_cell integer)
+{
+  H2BE(integer);
+  device_add_property(me, property, integer_property,
+                      &integer, sizeof(integer),
+                      &integer, sizeof(integer),
+                      NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(signed_cell)
+device_find_integer_property(device *me,
+                            const char *property)
+{
+  const device_property *node;
+  signed_cell integer;
+  TRACE(trace_devices,
+       ("device_find_integer(me=0x%lx, property=%s)\n",
+        (long)me, property));
+  node = device_find_property(me, property);
+  if (node == (device_property*)0
+      || node->type != integer_property)
+    device_error(me, "property %s not found or of wrong type", property);
+  ASSERT(sizeof(integer) == node->sizeof_array);
+  memcpy(&integer, node->array, sizeof(integer));
+  return BE2H_cell(integer);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_integer_array_property(device *me,
+                                  const char *property,
+                                  unsigned index,
+                                  signed_cell *integer)
+{
+  const device_property *node;
+  int sizeof_integer = sizeof(*integer);
+  signed_cell *cell;
+  TRACE(trace_devices,
+       ("device_find_integer(me=0x%lx, property=%s)\n",
+        (long)me, property));
+
+  /* check things sane */
+  node = device_find_property(me, property);
+  if (node == (device_property*)0
+      || (node->type != integer_property
+         && node->type != array_property))
+    device_error(me, "property %s not found or of wrong type", property);
+  if ((node->sizeof_array % sizeof_integer) != 0)
+    device_error(me, "property %s contains an incomplete number of cells", property);
+  if (node->sizeof_array <= sizeof_integer * index)
+    return 0;
+
+  /* Find and convert the value */
+  cell = ((signed_cell*)node->array) + index;
+  *integer = BE2H_cell(*cell);
+
+  return node->sizeof_array / sizeof_integer;
+}
+
+
+STATIC_INLINE_DEVICE\
+(unsigned_cell *)
+unit_address_to_cells(const device_unit *unit,
+                     unsigned_cell *cell,
+                     int nr_cells)
+{
+  int i;
+  ASSERT(nr_cells == unit->nr_cells);
+  for (i = 0; i < unit->nr_cells; i++) {
+    *cell = H2BE_cell(unit->cells[i]);
+    cell += 1;
+  }
+  return cell;
+}
+
+
+STATIC_INLINE_DEVICE\
+(const unsigned_cell *)
+cells_to_unit_address(const unsigned_cell *cell,
+                     device_unit *unit,
+                     int nr_cells)
+{
+  int i;
+  memset(unit, 0, sizeof(*unit));
+  unit->nr_cells = nr_cells;
+  for (i = 0; i < unit->nr_cells; i++) {
+    unit->cells[i] = BE2H_cell(*cell);
+    cell += 1;
+  }
+  return cell;
+}
+
+
+STATIC_INLINE_DEVICE\
+(unsigned)
+nr_range_property_cells(device *me,
+                       int nr_ranges)
+{
+  return ((device_nr_address_cells(me)
+          + device_nr_address_cells(device_parent(me))
+          + device_nr_size_cells(me))
+         ) * nr_ranges;
+}
+
+INLINE_DEVICE\
+(void)
+device_add_range_array_property(device *me,
+                               const char *property,
+                               const range_property_spec *ranges,
+                               unsigned nr_ranges)
+{
+  unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges)
+                          * sizeof(unsigned_cell));
+  unsigned_cell *cells = zalloc(sizeof_cells);
+  unsigned_cell *cell;
+  int i;
+
+  /* copy the property elements over */
+  cell = cells;
+  for (i = 0; i < nr_ranges; i++) {
+    const range_property_spec *range = &ranges[i];
+    /* copy the child address */
+    cell = unit_address_to_cells(&range->child_address, cell,
+                                device_nr_address_cells(me));
+    /* copy the parent address */
+    cell = unit_address_to_cells(&range->parent_address, cell, 
+                                device_nr_address_cells(device_parent(me)));
+    /* copy the size */
+    cell = unit_address_to_cells(&range->size, cell, 
+                                device_nr_size_cells(me));
+  }
+  ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
+
+  /* add it */
+  device_add_property(me, property, range_array_property,
+                     cells, sizeof_cells,
+                     cells, sizeof_cells,
+                     NULL, permenant_object);
+
+  zfree(cells);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_range_array_property(device *me,
+                                const char *property,
+                                unsigned index,
+                                range_property_spec *range)
+{
+  const device_property *node;
+  unsigned sizeof_entry = (nr_range_property_cells(me, 1)
+                          * sizeof(unsigned_cell));
+  const unsigned_cell *cells;
+
+  /* locate the property */
+  node = device_find_property(me, property);
+  if (node == (device_property*)0
+      || node->type != range_array_property)
+    device_error(me, "property %s not found or of wrong type", property);
+
+  /* aligned ? */
+  if ((node->sizeof_array % sizeof_entry) != 0)
+    device_error(me, "property %s contains an incomplete number of entries",
+                property);
+
+  /* within bounds? */
+  if (node->sizeof_array < sizeof_entry * (index + 1))
+    return 0;
+
+  /* find the range of interest */
+  cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
+
+  /* copy the child address out - converting as we go */
+  cells = cells_to_unit_address(cells, &range->child_address,
+                               device_nr_address_cells(me));
+
+  /* copy the parent address out - converting as we go */
+  cells = cells_to_unit_address(cells, &range->parent_address,
+                               device_nr_address_cells(device_parent(me)));
+
+  /* copy the size - converting as we go */
+  cells = cells_to_unit_address(cells, &range->size,
+                               device_nr_size_cells(me));
+
+  return node->sizeof_array / sizeof_entry;
+}
+
+
 STATIC_INLINE_DEVICE\
-(void)
-device_add_integer_property(device *me,
-                           const char *property,
-                           signed32 integer)
+(unsigned)
+nr_reg_property_cells(device *me,
+                     int nr_regs)
 {
-  TRACE(trace_devices,
-       ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n",
-        (long)me, property, (long)integer));
-  H2BE(integer);
-  device_add_property(me, property, integer_property,
-                     &integer, sizeof(integer),
-                     &integer, sizeof(integer),
+  return (device_nr_address_cells(device_parent(me))
+         + device_nr_size_cells(device_parent(me))
+         ) * nr_regs;
+}
+
+INLINE_DEVICE\
+(void)
+device_add_reg_array_property(device *me,
+                             const char *property,
+                             const reg_property_spec *regs,
+                             unsigned nr_regs)
+{
+  unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
+                          * sizeof(unsigned_cell));
+  unsigned_cell *cells = zalloc(sizeof_cells);
+  unsigned_cell *cell;
+  int i;
+
+  /* copy the property elements over */
+  cell = cells;
+  for (i = 0; i < nr_regs; i++) {
+    const reg_property_spec *reg = &regs[i];
+    /* copy the address */
+    cell = unit_address_to_cells(&reg->address, cell,
+                                device_nr_address_cells(device_parent(me)));
+    /* copy the size */
+    cell = unit_address_to_cells(&reg->size, cell,
+                                device_nr_size_cells(device_parent(me)));
+  }
+  ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
+
+  /* add it */
+  device_add_property(me, property, reg_array_property,
+                     cells, sizeof_cells,
+                     cells, sizeof_cells,
                      NULL, permenant_object);
+
+  zfree(cells);
 }
 
 INLINE_DEVICE\
-(signed_word)
-device_find_integer_property(device *me,
-                            const char *property)
+(int)
+device_find_reg_array_property(device *me,
+                              const char *property,
+                              unsigned index,
+                              reg_property_spec *reg)
 {
   const device_property *node;
-  signed32 integer;
-  TRACE(trace_devices,
-       ("device_find_integer(me=0x%lx, property=%s)\n",
-        (long)me, property));
+  unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
+                          * sizeof(unsigned_cell));
+  const unsigned_cell *cells;
+
+  /* locate the property */
   node = device_find_property(me, property);
   if (node == (device_property*)0
-      || node->type != integer_property)
-    device_error(me, "property %s not found or of wrong type\n", property);
-  ASSERT(sizeof(integer) == node->sizeof_array);
-  memcpy(&integer, node->array, sizeof(integer));
-  BE2H(integer);
-  return integer;
+      || node->type != reg_array_property)
+    device_error(me, "property %s not found or of wrong type", property);
+
+  /* aligned ? */
+  if ((node->sizeof_array % sizeof_entry) != 0)
+    device_error(me, "property %s contains an incomplete number of entries",
+                property);
+
+  /* within bounds? */
+  if (node->sizeof_array < sizeof_entry * (index + 1))
+    return 0;
+
+  /* find the range of interest */
+  cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
+
+  /* copy the address out - converting as we go */
+  cells = cells_to_unit_address(cells, &reg->address,
+                               device_nr_address_cells(device_parent(me)));
+
+  /* copy the size out - converting as we go */
+  cells = cells_to_unit_address(cells, &reg->size,
+                               device_nr_size_cells(device_parent(me)));
+
+  return node->sizeof_array / sizeof_entry;
 }
 
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
 (void)
 device_add_string_property(device *me,
-                          const char *property,
-                          const char *string)
+                           const char *property,
+                           const char *string)
 {
-
-  TRACE(trace_devices,
-       ("device_add_property(me=0x%lx, property=%s, string=%s)\n",
-        (long)me, property, string));
   device_add_property(me, property, string_property,
-                     string, strlen(string) + 1,
-                     string, strlen(string) + 1,
-                     NULL, permenant_object);
+                      string, strlen(string) + 1,
+                      string, strlen(string) + 1,
+                      NULL, permenant_object);
 }
 
 INLINE_DEVICE\
@@ -1246,32 +1447,133 @@ device_find_string_property(device *me,
 {
   const device_property *node;
   const char *string;
-  TRACE(trace_devices,
-       ("device_find_string(me=0x%lx, property=%s)\n",
-        (long)me, property));
   node = device_find_property(me, property);
   if (node == (device_property*)0
       || node->type != string_property)
-    device_error(me, "property %s not found or of wrong type\n", property);
+    device_error(me, "property %s not found or of wrong type", property);
   string = node->array;
   ASSERT(strlen(string) + 1 == node->sizeof_array);
   return string;
 }
 
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
+(void)
+device_add_string_array_property(device *me,
+                                const char *property,
+                                const string_property_spec *strings,
+                                unsigned nr_strings)
+{
+  int sizeof_array;
+  int string_nr;
+  char *array;
+  char *chp;
+  if (nr_strings == 0)
+    device_error(me, "property %s must be non-null", property);
+  /* total up the size of the needed array */
+  for (sizeof_array = 0, string_nr = 0;
+       string_nr < nr_strings;
+       string_nr ++) {
+    sizeof_array += strlen(strings[string_nr]) + 1;
+  }
+  /* create the array */
+  array = (char*)zalloc(sizeof_array);
+  chp = array;
+  for (string_nr = 0;
+       string_nr < nr_strings;
+       string_nr++) {
+    strcpy(chp, strings[string_nr]);
+    chp += strlen(chp) + 1;
+  }
+  ASSERT(chp == array + sizeof_array);
+  /* now enter it */
+  device_add_property(me, property, string_array_property,
+                     array, sizeof_array,
+                     array, sizeof_array,
+                     NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_string_array_property(device *me,
+                                 const char *property,
+                                 unsigned index,
+                                 string_property_spec *string)
+{
+  const device_property *node;
+  node = device_find_property(me, property);
+  if (node == (device_property*)0)
+    device_error(me, "property %s not found", property);
+  switch (node->type) {
+  default:
+    device_error(me, "property %s of wrong type", property);
+    break;
+  case string_property:
+    if (index == 0) {
+      *string = node->array;
+      ASSERT(strlen(*string) + 1 == node->sizeof_array);
+      return 1;
+    }
+    break;
+  case array_property:
+    if (node->sizeof_array == 0
+       || ((char*)node->array)[node->sizeof_array - 1] != '\0')
+      device_error(me, "property %s invalid for string array", property);
+    /* FALL THROUGH */
+  case string_array_property:
+    ASSERT(node->sizeof_array > 0);
+    ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0');
+    {
+      const char *chp = node->array;
+      int nr_entries = 0;
+      /* count the number of strings, keeping an eye out for the one
+         we're looking for */
+      *string = chp;
+      do {
+       if (*chp == '\0') {
+         /* next string */
+         nr_entries++;
+         chp++;
+         if (nr_entries == index)
+           *string = chp;
+       }
+       else {
+         chp++;
+       }
+      } while (chp < (char*)node->array + node->sizeof_array);
+      if (index < nr_entries)
+       return nr_entries;
+      else {
+       *string = NULL;
+       return 0;
+      }
+    }
+    break;
+  }
+  return 0;
+}
+
+INLINE_DEVICE\
 (void)
 device_add_duplicate_property(device *me,
                              const char *property,
                              const device_property *original)
 {
+  device_property_entry *master;
   TRACE(trace_devices,
        ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
         (long)me, property));
   if (original->disposition != permenant_object)
-    device_error(me, "Can only duplicate permenant objects\n");
+    device_error(me, "Can only duplicate permenant objects");
+  /* find the original's master */
+  master = original->owner->properties;
+  while (master->value != original) {
+    master = master->next;
+    ASSERT(master != NULL);
+  }
+  /* now duplicate it */
   device_add_property(me, property,
                      original->type,
-                     original->array, original->sizeof_array,
+                     master->init_array, master->sizeof_init_array,
                      original->array, original->sizeof_array,
                      original, permenant_object);
 }
@@ -1291,7 +1593,7 @@ device_io_read_buffer(device *me,
                      unsigned_word cia)
 {
   if (me->callback->io.read_buffer == NULL)
-    device_error(me, "no io_read_buffer method\n");
+    device_error(me, "no io.read_buffer method");
   return me->callback->io.read_buffer(me, dest, space,
                                      addr, nr_bytes,
                                      processor, cia);
@@ -1308,7 +1610,7 @@ device_io_write_buffer(device *me,
                       unsigned_word cia)
 {
   if (me->callback->io.write_buffer == NULL)
-    device_error(me, "no io_write_buffer method\n");
+    device_error(me, "no io.write_buffer method");
   return me->callback->io.write_buffer(me, source, space,
                                       addr, nr_bytes,
                                       processor, cia);
@@ -1323,7 +1625,7 @@ device_dma_read_buffer(device *me,
                       unsigned nr_bytes)
 {
   if (me->callback->dma.read_buffer == NULL)
-    device_error(me, "no dma_read_buffer method\n");
+    device_error(me, "no dma.read_buffer method");
   return me->callback->dma.read_buffer(me, dest, space,
                                       addr, nr_bytes);
 }
@@ -1338,7 +1640,7 @@ device_dma_write_buffer(device *me,
                        int violate_read_only_section)
 {
   if (me->callback->dma.write_buffer == NULL)
-    device_error(me, "no dma_write_buffer method\n");
+    device_error(me, "no dma.write_buffer method");
   return me->callback->dma.write_buffer(me, source, space,
                                        addr, nr_bytes,
                                        violate_read_only_section);
@@ -1347,35 +1649,33 @@ device_dma_write_buffer(device *me,
 INLINE_DEVICE\
 (void)
 device_attach_address(device *me,
-                     const char *name,
                      attach_type attach,
                      int space,
                      unsigned_word addr,
                      unsigned nr_bytes,
                      access_type access,
-                     device *who) /*callback/default*/
+                     device *client) /*callback/default*/
 {
   if (me->callback->address.attach == NULL)
-    device_error(me, "no address_attach method\n");
-  me->callback->address.attach(me, name, attach, space,
-                              addr, nr_bytes, access, who);
+    device_error(me, "no address.attach method");
+  me->callback->address.attach(me, attach, space,
+                              addr, nr_bytes, access, client);
 }
 
 INLINE_DEVICE\
 (void)
 device_detach_address(device *me,
-                     const char *name,
                      attach_type attach,
                      int space,
                      unsigned_word addr,
                      unsigned nr_bytes,
                      access_type access,
-                     device *who) /*callback/default*/
+                     device *client) /*callback/default*/
 {
   if (me->callback->address.detach == NULL)
-    device_error(me, "no address_detach method\n");
-  me->callback->address.detach(me, name, attach, space,
-                              addr, nr_bytes, access, who);
+    device_error(me, "no address.detach method");
+  me->callback->address.detach(me, attach, space,
+                              addr, nr_bytes, access, client);
 }
 
 
@@ -1397,7 +1697,7 @@ device_interrupt_event(device *me,
        edge = edge->next) {
     if (edge->my_port == my_port) {
       if (edge->dest->callback->interrupt.event == NULL)
-       device_error(me, "no interrupt method\n");
+       device_error(me, "no interrupt method");
       edge->dest->callback->interrupt.event(edge->dest,
                                            edge->dest_port,
                                            me,
@@ -1408,7 +1708,7 @@ device_interrupt_event(device *me,
     }
   }
   if (!found_an_edge) {
-    device_error(me, "No interrupt edge for port %d\n", my_port);
+    device_error(me, "No interrupt edge for port %d", my_port);
   }
 }
 
@@ -1442,9 +1742,26 @@ device_interrupt_detach(device *me,
 }
 
 INLINE_DEVICE\
+(void)
+device_interrupt_traverse(device *me,
+                         device_interrupt_traverse_function *handler,
+                         void *data)
+{
+  device_interrupt_edge *interrupt_edge;
+  for (interrupt_edge = me->interrupt_destinations;
+       interrupt_edge != NULL;
+       interrupt_edge = interrupt_edge->next) {
+    handler(me, interrupt_edge->my_port,
+           interrupt_edge->dest, interrupt_edge->dest_port,
+           data);
+  }
+}
+
+INLINE_DEVICE\
 (int)
 device_interrupt_decode(device *me,
-                       const char *port_name)
+                       const char *port_name,
+                       port_direction direction)
 {
   if (port_name == NULL || port_name[0] == '\0')
     return 0;
@@ -1456,27 +1773,30 @@ device_interrupt_decode(device *me,
       me->callback->interrupt.ports;
     if (ports != NULL) {
       while (ports->name != NULL) {
-       if (ports->bound > ports->number) {
-         int len = strlen(ports->name);
-         if (strncmp(port_name, ports->name, len) == 0) {
-           if (port_name[len] == '\0')
-             return ports->number;
-           else if(isdigit(port_name[len])) {
-             int port = ports->number + strtoul(&port_name[len], NULL, 0);
-             if (port >= ports->bound)
-               device_error(me, "Interrupt port %s out of range\n",
-                            port_name);
-             return port;
+       if (ports->direction == bidirect_port
+           || ports->direction == direction) {
+         if (ports->nr_ports > 0) {
+           int len = strlen(ports->name);
+           if (strncmp(port_name, ports->name, len) == 0) {
+             if (port_name[len] == '\0')
+               return ports->number;
+             else if(isdigit(port_name[len])) {
+               int port = ports->number + strtoul(&port_name[len], NULL, 0);
+               if (port >= ports->number + ports->nr_ports)
+                 device_error(me, "Interrupt port %s out of range",
+                              port_name);
+               return port;
+             }
            }
          }
+         else if (strcmp(port_name, ports->name) == 0)
+           return ports->number;
        }
-       else if (strcmp(port_name, ports->name) == 0)
-         return ports->number;
        ports++;
       }
     }
   }
-  device_error(me, "Unreconized interrupt port %s\n", port_name);
+  device_error(me, "Unreconized interrupt port %s", port_name);
   return 0;
 }
 
@@ -1485,28 +1805,32 @@ INLINE_DEVICE\
 device_interrupt_encode(device *me,
                        int port_number,
                        char *buf,
-                       int sizeof_buf)
+                       int sizeof_buf,
+                       port_direction direction)
 {
   const device_interrupt_port_descriptor *ports = NULL;
   ports = me->callback->interrupt.ports;
   if (ports != NULL) {
     while (ports->name != NULL) {
-      if (ports->bound > ports->number) {
-       if (port_number >= ports->number
-           && port_number < ports->bound) {
-         strcpy(buf, ports->name);
-         sprintf(buf + strlen(buf), "%d", port_number - ports->number);
-         if (strlen(buf) >= sizeof_buf)
-           error("device_interrupt_encode:buffer overflow\n");
-         return strlen(buf);
+      if (ports->direction == bidirect_port
+         || ports->direction == direction) {
+       if (ports->nr_ports > 0) {
+         if (port_number >= ports->number
+             && port_number < ports->number + ports->nr_ports) {
+           strcpy(buf, ports->name);
+           sprintf(buf + strlen(buf), "%d", port_number - ports->number);
+           if (strlen(buf) >= sizeof_buf)
+             error("device_interrupt_encode: buffer overflow");
+           return strlen(buf);
+         }
        }
-      }
-      else {
-       if (ports->number == port_number) {
-         if (strlen(ports->name) >= sizeof_buf)
-           error("device_interrupt_encode: buffer overflow\n");
-         strcpy(buf, ports->name);
-         return strlen(buf);
+       else {
+         if (ports->number == port_number) {
+           if (strlen(ports->name) >= sizeof_buf)
+             error("device_interrupt_encode: buffer overflow");
+           strcpy(buf, ports->name);
+           return strlen(buf);
+         }
        }
       }
       ports++;
@@ -1514,7 +1838,7 @@ device_interrupt_encode(device *me,
   }
   sprintf(buf, "%d", port_number);
   if (strlen(buf) >= sizeof_buf)
-    error("device_interrupt_encode: buffer overflow\n");
+    error("device_interrupt_encode: buffer overflow");
   return strlen(buf);
 }
 
@@ -1527,14 +1851,15 @@ EXTERN_DEVICE\
 device_ioctl(device *me,
             cpu *processor,
             unsigned_word cia,
+            device_ioctl_request request,
             ...)
 {
   int status;
   va_list ap;
-  va_start(ap, cia);
+  va_start(ap, request);
   if (me->callback->ioctl == NULL)
-    device_error(me, "no ioctl method\n");
-  status = me->callback->ioctl(me, processor, cia, ap);
+    device_error(me, "no ioctl method");
+  status = me->callback->ioctl(me, processor, cia, request, ap);
   va_end(ap);
   return status;
 }
@@ -1557,413 +1882,170 @@ device_error(device *me,
   va_end(ap);
   /* sanity check */
   if (strlen(message) >= sizeof(message))
-    error("device_error: buffer overflow\n");
+    error("device_error: buffer overflow");
   if (me == NULL)
-    error("device: %s\n", message);
+    error("device: %s", message);
+  else if (me->path != NULL && me->path[0] != '\0')
+    error("%s: %s", me->path, message);
+  else if (me->name != NULL && me->name[0] != '\0')
+    error("%s: %s", me->name, message);
   else
-    error("%s: %s\n", me->path, message);
+    error("device: %s", message);
   while(1);
 }
 
+INLINE_DEVICE\
+(int)
+device_trace(device *me)
+{
+  return me->trace;
+}
+
 \f
-/* Tree utilities: */
+/* External representation */
 
-EXTERN_DEVICE\
+INLINE_DEVICE\
 (device *)
-device_tree_add_parsed(device *current,
-                      const char *fmt,
-                      ...)
-{
-  char device_specifier[1024];
-  name_specifier spec;
-
-  /* format the path */
-  {
-    va_list ap;
-    va_start(ap, fmt);
-    vsprintf(device_specifier, fmt, ap);
-    va_end(ap);
-    if (strlen(device_specifier) >= sizeof(device_specifier))
-      error("device_tree_add_parsed: buffer overflow\n");
-  }
-
-  /* break it up */
-  if (!split_device_specifier(device_specifier, &spec))
-    device_error(current, "error parsing %s\n", device_specifier);
-
-  /* fill our tree with its contents */
-  current = split_find_device(current, &spec);
-
-  /* add any additional devices as needed */
-  if (spec.name != NULL) {
-    do {
-      current =
-       device_template_create_device(current, spec.name, spec.unit, spec.args);
-    } while (split_device_name(&spec));
-  }
-
-  /* is there an interrupt spec */
-  if (spec.property == NULL
-      && spec.value != NULL) {
-    char *op = split_value(&spec);
-    switch (op[0]) {
-    case '>':
-      {
-       char *my_port_name = split_value(&spec);
-       char *dest_port_name = split_value(&spec);
-       device *dest = device_tree_find_device(current, split_value(&spec));
-       int my_port = device_interrupt_decode(current, my_port_name);
-       int dest_port  = device_interrupt_decode(dest, dest_port_name);
-       device_interrupt_attach(current,
-                               my_port,
-                               dest,
-                               dest_port,
-                               permenant_object);
-      }
-      break;
-    default:
-      device_error(current, "unreconised interrupt spec %s\n", spec.value);
-      break;
-    }
-  }
-
-  /* is there a property */
-  if (spec.property != NULL) {
-    if (strcmp(spec.value, "true") == 0)
-      device_add_boolean_property(current, spec.property, 1);
-    else if (strcmp(spec.value, "false") == 0)
-      device_add_boolean_property(current, spec.property, 0);
-    else {
-      const device_property *property;
-      switch (spec.value[0]) {
-      case '*':
-       {
-         spec.value++;
-         device_add_ihandle_property(current, spec.property, spec.value);
-       }
-       break;
-      case '-': case '+':
-      case '0': case '1': case '2': case '3': case '4':
-      case '5': case '6': case '7': case '8': case '9':
-       {
-         unsigned long ul = strtoul(spec.value, &spec.value, 0);
-         device_add_integer_property(current, spec.property, ul);
-       }
-       break;
-      case '[':
-       {
-         unsigned8 words[1024];
-         char *curr = spec.value + 1;
-         int nr_words = 0;
-         while (1) {
-           char *next;
-           words[nr_words] = H2BE_1(strtoul(curr, &next, 0));
-           if (curr == next)
-             break;
-           curr = next;
-           nr_words += 1;
-         }
-         device_add_array_property(current, spec.property,
-                                   words, sizeof(words[0]) * nr_words);
-       }
-       break;
-      case '{':
-       {
-         unsigned32 words[1024];
-         char *curr = spec.value + 1;
-         int nr_words = 0;
-         while (1) {
-           char *next;
-           words[nr_words] = H2BE_4(strtoul(curr, &next, 0));
-           if (curr == next)
-             break;
-           curr = next;
-           nr_words += 1;
-         }
-         device_add_array_property(current, spec.property,
-                                   words, sizeof(words[0]) * nr_words);
-       }
-       break;
-      case '"':
-       spec.value++;
-      default:
-       device_add_string_property(current, spec.property, spec.value);
-       break;
-      case '!':
-       spec.value++;
-       property = device_find_property(current, spec.value);
-       if (property == NULL)
-         device_error(current, "property %s not found\n", spec.value);
-       device_add_duplicate_property(current,
-                                     spec.property,
-                                     property);
-       break;
-      }
-    }
-  }
-  return current;
+external_to_device(device *tree_member,
+                  unsigned_cell phandle)
+{
+  device *me = cap_internal(tree_member->phandles, phandle);
+  return me;
 }
 
 INLINE_DEVICE\
-(void)
-device_tree_traverse(device *root,
-                    device_tree_traverse_function *prefix,
-                    device_tree_traverse_function *postfix,
-                    void *data)
-{
-  device *child;
-  if (prefix != NULL)
-    prefix(root, data);
-  for (child = root->children; child != NULL; child = child->sibling) {
-    device_tree_traverse(child, prefix, postfix, data);
-  }
-  if (postfix != NULL)
-    postfix(root, data);
+(unsigned_cell)
+device_to_external(device *me)
+{
+  unsigned_cell phandle = cap_external(me->phandles, me);
+  return phandle;
 }
 
 INLINE_DEVICE\
-(void)
-device_tree_print_device(device *me,
-                        void *ignore_or_null)
+(device_instance *)
+external_to_device_instance(device *tree_member,
+                           unsigned_cell ihandle)
 {
-  const device_property *property;
-  device_interrupt_edge *interrupt_edge;
-  /* output my name */
-  printf_filtered("%s\n", me->path);
-  /* properties */
-  for (property = device_find_property(me, NULL);
-       property != NULL;
-       property = device_next_property(property)) {
-    printf_filtered("%s/%s", me->path, property->name);
-    if (property->original != NULL) {
-      printf_filtered(" !");
-      printf_filtered("%s/%s\n", property->original->owner->path,
-                     property->original->name);
-    }
-    else {
-      switch (property->type) {
-      case array_property:
-       {
-         if ((property->sizeof_array % sizeof(unsigned32)) == 0) {
-           unsigned32 *w = (unsigned32*)property->array;
-           printf_filtered(" {");
-           while ((char*)w - (char*)property->array < property->sizeof_array) {
-             printf_filtered(" 0x%lx", BE2H_4(*w));
-             w++;
-           }
-         }
-         else {
-           unsigned8 *w = (unsigned8*)property->array;
-           printf_filtered(" [");
-           while ((char*)w - (char*)property->array < property->sizeof_array) {
-             printf_filtered(" 0x%2x", BE2H_1(*w));
-             w++;
-           }
-         }
-         printf_filtered("\n");
-       }
-       break;
-      case boolean_property:
-       {
-         int b = device_find_boolean_property(me, property->name);
-         printf_filtered(" %s\n", b ? "true"  : "false");
-       }
-       break;
-      case ihandle_property:
-       {
-         if (property->array != NULL) {
-           device_instance *i = device_find_ihandle_property(me, property->name);
-           printf_filtered(" *%s\n", i->path);
-         }
-         else {
-           /* drats, the instance hasn't yet been created.  Grub
-               around and find the path that will be used to create
-               the ihandle */
-           device_property_entry *entry = me->properties;
-           while (entry->value != property) {
-             entry = entry->next;
-             ASSERT(entry != NULL);
-           }
-           ASSERT(entry->init_array != NULL);
-           printf_filtered(" *%s\n", (char*)entry->init_array);
-         }
-       }
-       break;
-      case integer_property:
-       {
-         unsigned_word w = device_find_integer_property(me, property->name);
-         printf_filtered(" 0x%lx\n", (unsigned long)w);
-       }
-       break;
-      case string_property:
-       {
-         const char *s = device_find_string_property(me, property->name);
-         printf_filtered(" \"%s\n", s);
-       }
-       break;
-      }
-    }
-  }
-  /* interrupts */
-  for (interrupt_edge = me->interrupt_destinations;
-       interrupt_edge != NULL;
-       interrupt_edge = interrupt_edge->next) {
-    char src[32];
-    char dst[32];
-    device_interrupt_encode(me, interrupt_edge->my_port, src, sizeof(src));
-    device_interrupt_encode(interrupt_edge->dest,
-                           interrupt_edge->dest_port, dst, sizeof(dst));
-    printf_filtered("%s > %s %s %s\n",
-                   me->path,
-                   src, dst,
-                   interrupt_edge->dest->path);
-  }
+  device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
+  return instance;
 }
 
 INLINE_DEVICE\
-(device *)
-device_tree_find_device(device *root,
-                       const char *path)
-{
-  device *node;
-  name_specifier spec;
-  TRACE(trace_device_tree,
-       ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
-        (long)root, path));
-  /* parse the path */
-  split_device_specifier(path, &spec);
-  if (spec.value != NULL)
-    return NULL; /* something wierd */
-
-  /* now find it */
-  node = split_find_device(root, &spec);
-  if (spec.name != NULL)
-    return NULL; /* not a leaf */
+(unsigned_cell)
+device_instance_to_external(device_instance *instance)
+{
+  unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
+  return ihandle;
+}
 
-  return node;
+
+/* Map onto the event functions */
+
+INLINE_DEVICE\
+(event_entry_tag)
+device_event_queue_schedule(device *me,
+                           signed64 delta_time,
+                           device_event_handler *handler,
+                           void *data)
+{
+  return event_queue_schedule(psim_event_queue(me->system),
+                             delta_time,
+                             handler,
+                             data);
 }
 
 INLINE_DEVICE\
 (void)
-device_usage(int verbose)
+device_event_queue_deschedule(device *me,
+                             event_entry_tag event_to_remove)
 {
-  if (verbose == 1) {
-    const device_descriptor *const *table;
-    int pos;
-    printf_filtered("\n");
-    printf_filtered("A device/property specifier has the form:\n");
-    printf_filtered("\n");
-    printf_filtered("  /path/to/a/device [ property-value ]\n");
-    printf_filtered("\n");
-    printf_filtered("and a possible device is\n");
-    printf_filtered("\n");
-    pos = 0;
-    for (table = device_table; *table != NULL; table++) {
-      const device_descriptor *descr;
-      for (descr = *table; descr->name != NULL; descr++) {
-       pos += strlen(descr->name) + 2;
-       if (pos > 75) {
-         pos = strlen(descr->name) + 2;
-         printf_filtered("\n");
-       }
-       printf_filtered("  %s", descr->name);
-      }
-      printf_filtered("\n");
-    }
-  }
-  if (verbose > 1) {
-    const device_descriptor *const *table;
-    printf_filtered("\n");
-    printf_filtered("A device/property specifier (<spec>) has the format:\n");
-    printf_filtered("\n");
-    printf_filtered("  <spec> ::= <path> [ <value> ] ;\n");
-    printf_filtered("  <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
-    printf_filtered("  <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
-    printf_filtered("  <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
-    printf_filtered("  <unit> ::= <number> { \",\" <number> } ;\n");
-    printf_filtered("\n");
-    printf_filtered("Where:\n");
-    printf_filtered("\n");
-    printf_filtered("  <name>  is the name of a device (list below)\n");
-    printf_filtered("  <unit>  is the unit-address relative to the parent bus\n");
-    printf_filtered("  <args>  additional arguments used when creating the device\n");
-    printf_filtered("  <value> ::= ( <number> # integer property\n");
-    printf_filtered("              | \"[\" { <number> } # array property (byte)\n");
-    printf_filtered("              | \"{\" { <number> } # array property (cell)\n");
-    printf_filtered("              | [ \"true\" | \"false\" ] # boolean property\n");
-    printf_filtered("              | \"*\" <path> # ihandle property\n");
-    printf_filtered("              | \"!\" <path> # copy property\n");
-    printf_filtered("              | \">\" [ <number> ] <path> # attach interrupt\n");
-    printf_filtered("              | \"<\" <path> # attach child interrupt\n");
-    printf_filtered("              | \"\\\"\" <text> # string property\n");
-    printf_filtered("              | <text> # string property\n");
-    printf_filtered("              ) ;\n");
-    printf_filtered("\n");
-    printf_filtered("And the following are valid device names:\n");
-    printf_filtered("\n");
-    for (table = device_table; *table != NULL; table++) {
-      const device_descriptor *descr;
-      for (descr = *table; descr->name != NULL; descr++) {
-       printf_filtered("  %s:\n", descr->name);
-       /* interrupt ports */
-       if (descr->callbacks->interrupt.ports != NULL) {
-         const device_interrupt_port_descriptor *ports =
-           descr->callbacks->interrupt.ports;
-         printf_filtered("    interrupt ports:");
-         while (ports->name != NULL) {
-           printf_filtered(" %s", ports->name);
-           ports++;
-         }
-         printf_filtered("\n");
-       }
-       /* general info */
-       if (descr->callbacks->usage != NULL)
-         descr->callbacks->usage(verbose);
-      }
-    }
-  }
+  event_queue_deschedule(psim_event_queue(me->system),
+                        event_to_remove);
 }
 
-
-\f
-/* External representation */
-
 INLINE_DEVICE\
-(device *)
-external_to_device(device *tree_member,
-                  unsigned32 phandle)
+(signed64)
+device_event_queue_time(device *me)
 {
-  device *root = device_tree_find_device(tree_member, "/");
-  device *me = cap_internal(root->phandles, phandle);
-  return me;
+  return event_queue_time(psim_event_queue(me->system));
 }
 
+
+/* Initialization: */
+
+
 INLINE_DEVICE\
-(unsigned32)
-device_to_external(device *me)
+(void)
+device_clean(device *me,
+            void *data)
 {
-  device *root = device_tree_find_device(me, "/");
-  unsigned32 phandle = cap_external(root->phandles, me);
-  return phandle;
+  psim *system;
+  system = (psim*)data;
+  TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
+  clean_device_interrupt_edges(&me->interrupt_destinations);
+  clean_device_instances(me);
+  clean_device_properties(me);
 }
 
+/* Device initialization: */
+
 INLINE_DEVICE\
-(device_instance *)
-external_to_device_instance(device *tree_member,
-                           unsigned32 ihandle)
+(void)
+device_init_address(device *me,
+                   void *data)
 {
-  device *root = device_tree_find_device(tree_member, "/");
-  device_instance *instance = cap_internal(root->ihandles, ihandle);
-  return instance;
+  psim *system = (psim*)data;
+  int nr_address_cells;
+  int nr_size_cells;
+  TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
+
+  /* ensure the cap database is valid */
+  if (me->parent == NULL) {
+    cap_init(me->ihandles);
+    cap_init(me->phandles);
+  }
+
+  /* some basics */
+  me->system = system; /* misc things not known until now */
+  me->trace = (device_find_property(me, "trace")
+              ? device_find_integer_property(me, "trace")
+              : 0);
+
+  /* Ensure that the first address found in the reg property matches
+     anything that was specified as part of the devices name */
+  if (device_find_property(me, "reg") != NULL) {
+    reg_property_spec unit;
+    device_find_reg_array_property(me, "reg", 0, &unit);
+    if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
+       != 0)
+      device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
+  }
+
+  /* ensure that the devices #address/size-cells is consistent */
+  nr_address_cells = device_nr_address_cells(me);
+  if (device_find_property(me, "#address-cells") != NULL
+      && (nr_address_cells
+         != device_find_integer_property(me, "#address-cells")))
+    device_error(me, "#address-cells property used before defined");
+  nr_size_cells = device_nr_size_cells(me);
+  if (device_find_property(me, "#size-cells") != NULL
+      && (nr_size_cells
+         != device_find_integer_property(me, "#size-cells")))
+    device_error(me, "#size-cells property used before defined");
+
+  /* now init it */
+  if (me->callback->init.address != NULL)
+    me->callback->init.address(me);
 }
 
 INLINE_DEVICE\
-(unsigned32)
-device_instance_to_external(device_instance *instance)
+(void)
+device_init_data(device *me,
+                   void *data)
 {
-  device *root = device_tree_find_device(instance->owner, "/");
-  unsigned32 ihandle = cap_external(root->ihandles, instance);
-  return ihandle;
+  TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
+  if (me->callback->init.data != NULL)
+    me->callback->init.data(me);
 }
 
 #endif /* _DEVICE_C_ */
index 4fa5a9d..cb2e8c8 100644 (file)
    */
 
 
-/* Constructing the device tree:
+/* Device creation: */
 
-   The initial device tree populated with devices and basic properties
-   is created using the function <<device_tree_add_parsed()>>.  This
-   function parses a PSIM device specification and uses it to populate
-   the tree accordingly.
+INLINE_DEVICE\
+(device *) device_create
+(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args);
 
-   This function accepts a printf style formatted string as the
-   argument that describes the entry.  Any properties or interrupt
-   connections added to a device tree using this function are marked
-   as having a permenant disposition.  When the tree is (re)
-   initialized they will be restored to their initial value.
+INLINE_DEVICE\
+(void) device_usage
+(int verbose);
 
-   */
 
-EXTERN_DEVICE\
-(device *) device_tree_add_parsed
-(device *current,
- const char *fmt,
- ...) __attribute__ ((format (printf, 2, 3)));
+/* Device initialization: */
 
+INLINE_DEVICE\
+(void) device_clean
+(device *root,
+ void *data);
 
-/* Initializing the created tree:
+INLINE_DEVICE\
+(void) device_init_static_properties
+(device *me,
+ void *data);
 
-   Once a device tree has been created the <<device_tree_init()>>
-   function is used to initialize it.  The exact sequence of events
-   that occure during initialization are described separatly.
+INLINE_DEVICE\
+(void) device_init_address
+(device *me,
+ void *data);
 
-   */
+INLINE_DEVICE\
+(void) device_init_runtime_properties
+(device *me,
+ void *data);
 
 INLINE_DEVICE\
-(void) device_tree_init
-(device *root,
psim *system);
+(void) device_init_data
+(device *me,
void *data);
 
 
 /* Relationships:
@@ -91,6 +98,10 @@ INLINE_DEVICE\
 (device *me);
 
 INLINE_DEVICE\
+(device *) device_root
+(device *me);
+
+INLINE_DEVICE\
 (device *) device_sibling
 (device *me);
 
@@ -103,6 +114,10 @@ INLINE_DEVICE\
 (device *me);
 
 INLINE_DEVICE\
+(const char *) device_base
+(device *me);
+
+INLINE_DEVICE\
 (const char *) device_path
 (device *me);
 
@@ -116,13 +131,63 @@ INLINE_DEVICE\
 
 typedef struct _device_unit {
   int nr_cells;
-  unsigned32 cells[4]; /* unused cells are zero */
+  unsigned_cell cells[4]; /* unused cells are zero */
 } device_unit;
 
 INLINE_DEVICE\
 (const device_unit *) device_unit_address
 (device *me);
 
+INLINE_DEVICE\
+(int) device_decode_unit
+(device *bus,
+ const char *unit,
+ device_unit *address);
+
+INLINE_DEVICE\
+(int) device_encode_unit
+(device *bus,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf);
+
+
+/* Convert an Open Firmware size into a form suitable for attach
+   address calls.
+
+   Return a zero result if the address should be ignored when looking
+   for attach addresses */
+
+INLINE_DEVICE\
+(int) device_address_to_attach_address
+(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client);
+
+
+/* Convert an Open Firmware size into a form suitable for attach
+   address calls
+
+   Return a zero result if the address should be ignored */
+
+INLINE_DEVICE\
+(int) device_size_to_attach_size
+(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client);
+
+
+INLINE_DEVICE\
+(unsigned) device_nr_address_cells
+(device *me);
+
+INLINE_DEVICE\
+(unsigned) device_nr_size_cells
+(device *me);
+
 
 /* Properties:
 
@@ -132,15 +197,18 @@ INLINE_DEVICE\
 
    */
 
-/* The following are valid property types.  The property `array' is a
+/* The following are valid property types.  The property `array' is
    for generic untyped data. */
 
 typedef enum {
   array_property,
   boolean_property,
-  ihandle_property,
+  ihandle_property, /*runtime*/
   integer_property,
+  range_array_property,
+  reg_array_property,
   string_property,
+  string_array_property,
 } device_property_type;
 
 typedef struct _device_property device_property;
@@ -176,10 +244,26 @@ INLINE_DEVICE\
    FIND returns the specified properties value, aborting the
    simulation if the property is missing.  Code locating a property
    should first check its type (using device_find_property above) and
-   then obtain its value using the below. */
+   then obtain its value using the below.
+
+   void device_add_<type>_property(device *, const char *, <type>)
+   void device_add_*_array_property(device *, const char *, const <type>*, int)
+   void device_set_*_property(device *, const char *, <type>)
+   void device_set_*_array_property(device *, const char *, const <type>*, int)
+   <type> device_find_*_property(device *, const char *)
+   int device_find_*_array_property(device *, const char *, int, <type>*)
+
+   */
 
 
 INLINE_DEVICE\
+(void) device_add_array_property
+(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array);
+
+INLINE_DEVICE\
 (void) device_set_array_property
 (device *me,
  const char *property,
@@ -192,13 +276,12 @@ INLINE_DEVICE\
  const char *property);
 
 
-#if 0
+
 INLINE_DEVICE\
-(void) device_set_boolean_property
+(void) device_add_boolean_property
 (device *me,
  const char *property,
  int bool);
-#endif
 
 INLINE_DEVICE\
 (int) device_find_boolean_property
@@ -206,13 +289,30 @@ INLINE_DEVICE\
  const char *property);
 
 
-#if 0
+
+typedef struct _ihandle_runtime_property_spec {
+  device *phandle;
+  const char *full_path;
+  const char *args;
+} ihandle_runtime_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_ihandle_runtime_property
+(device *me,
+ const char *property,
+ const ihandle_runtime_property_spec *ihandle);
+
+INLINE_DEVICE\
+(void) device_find_ihandle_runtime_property
+(device *me,
+ const char *property,
+ ihandle_runtime_property_spec *ihandle);
+
 INLINE_DEVICE\
 (void) device_set_ihandle_property
 (device *me,
  const char *property,
  device_instance *ihandle);
-#endif
 
 INLINE_DEVICE\
 (device_instance *) device_find_ihandle_property
@@ -220,27 +320,75 @@ INLINE_DEVICE\
  const char *property);
 
 
-#if 0
+
 INLINE_DEVICE\
-(void) device_set_integer_property
+(void) device_add_integer_property
 (device *me,
  const char *property,
- signed_word integer);
-#endif
+ signed_cell integer);
 
 INLINE_DEVICE\
-(signed_word) device_find_integer_property
+(signed_cell) device_find_integer_property
 (device *me,
  const char *property);
 
+INLINE_DEVICE\
+(int) device_find_integer_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ signed_word *integer);
+
+
+
+typedef struct _range_property_spec {
+  device_unit child_address;
+  device_unit parent_address;
+  device_unit size;
+} range_property_spec;
 
-#if 0
 INLINE_DEVICE\
-(void) device_set_string_property
+(void) device_add_range_array_property
+(device *me,
+ const char *property,
+ const range_property_spec *ranges,
+ unsigned nr_ranges);
+
+INLINE_DEVICE\
+(int) device_find_range_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ range_property_spec *range);
+
+
+
+typedef struct _reg_property_spec {
+  device_unit address;
+  device_unit size;
+} reg_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_reg_array_property
+(device *me,
+ const char *property,
+ const reg_property_spec *reg,
+ unsigned nr_regs);
+
+INLINE_DEVICE\
+(int) device_find_reg_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg);
+
+
+
+INLINE_DEVICE\
+(void) device_add_string_property
 (device *me,
  const char *property,
  const char *string);
-#endif
 
 INLINE_DEVICE\
 (const char *) device_find_string_property
@@ -248,6 +396,33 @@ INLINE_DEVICE\
  const char *property);
 
 
+
+typedef const char *string_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_string_array_property
+(device *me,
+ const char *property,
+ const string_property_spec *strings,
+ unsigned nr_strings);
+
+INLINE_DEVICE\
+(int) device_find_string_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ string_property_spec *string);
+
+
+
+INLINE_DEVICE\
+(void) device_add_duplicate_property
+(device *me,
+ const char *property,
+ const device_property *original);
+
+
+
 /* Instances:
 
    As with IEEE1275, a device can be opened, creating an instance.
@@ -277,7 +452,8 @@ INLINE_DEVICE\
 INLINE_DEVICE\
 (device_instance *) device_create_instance
 (device *me,
- const char *device_specifier);
+ const char *full_path,
+ const char *args);
 
 INLINE_DEVICE\
 (void) device_instance_delete
@@ -302,17 +478,13 @@ INLINE_DEVICE\
  unsigned_word pos_lo);
 
 INLINE_DEVICE\
-(unsigned_word) device_instance_claim
+(int) device_instance_call_method
 (device_instance *instance,
- unsigned_word address,
- unsigned_word length,
- unsigned_word alignment);
-
-INLINE_DEVICE\
-(void) device_instance_release
-(device_instance *instance,
- unsigned_word address,
- unsigned_word length);
+ const char *method,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/]);
 
 INLINE_DEVICE\
 (device *) device_instance_device
@@ -378,6 +550,20 @@ INLINE_DEVICE\
  device *dest,
  int dest_port);
 
+typedef void (device_interrupt_traverse_function)
+     (device *me,
+      int my_port,
+      device *dest,
+      int my_dest,
+      void *data);
+
+INLINE_DEVICE\
+(void) device_interrupt_traverse
+(device *me,
+ device_interrupt_traverse_function *handler,
+ void *data);
+
 /* DESTINATION is attached (detached) to LINE of the device ME
 
 
@@ -393,14 +579,16 @@ INLINE_DEVICE\
 INLINE_DEVICE\
 (int) device_interrupt_decode
 (device *me,
- const char *symbolic_name);
+ const char *symbolic_name,
+ port_direction direction);
 
 INLINE_DEVICE\
 (int) device_interrupt_encode
 (device *me,
  int port_number,
  char *buf,
- int sizeof_buf);
+ int sizeof_buf,
+ port_direction direction);
  
 
 /* Hardware operations:
@@ -480,24 +668,22 @@ typedef enum _attach_type {
 INLINE_DEVICE\
 (void) device_attach_address
 (device *me,
- const char *name,
  attach_type attach,
  int space,
  unsigned_word addr,
  unsigned nr_bytes,
  access_type access,
- device *who); /*callback/default*/
+ device *client); /*callback/default*/
 
 INLINE_DEVICE\
 (void) device_detach_address
 (device *me,
- const char *name,
  attach_type attach,
  int space,
  unsigned_word addr,
  unsigned nr_bytes,
  access_type access,
- device *who); /*callback/default*/
+ device *client); /*callback/default*/
 
 /* Utilities:
 
@@ -513,11 +699,20 @@ INLINE_DEVICE\
 
    */
 
+typedef enum {
+  device_ioctl_break, /* unsigned_word requested_break */
+  device_ioctl_set_trace, /* void */
+  device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */
+  device_ioctl_change_media, /* const char *new_image (possibly NULL) */
+  nr_device_ioctl_requests,
+} device_ioctl_request;
+
 EXTERN_DEVICE\
 (int) device_ioctl
 (device *me,
  cpu *processor,
  unsigned_word cia,
+ device_ioctl_request request,
  ...);
 
 
@@ -539,60 +734,10 @@ EXTERN_DEVICE\
  const char *fmt,
  ...) __attribute__ ((format (printf, 2, 3)));
 
-/* Tree traversal::
-
-   The entire device tree can be traversed using the
-   <<device_tree_traverse()>> function.  The traversal can be in
-   either pre- or postfix order.
-
-   */
-
-typedef void (device_tree_traverse_function)
-     (device *device,
-      void *data);
-
-INLINE_DEVICE\
-(void) device_tree_traverse
-(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data);
-
-/* Device description::
-
-   */
-
-INLINE_DEVICE\
-(void) device_tree_print_device
-(device *device,
- void *ignore_data_argument);
-
-
-/* Tree lookup::
-
-   The function <<device_tree_find_device()>> will attempt to locate
-   the specified device within the tree.  If the device is not found a
-   NULL device is returned.
-
-   */
-
 INLINE_DEVICE\
-(device *) device_tree_find_device
-(device *root,
- const char *path);
-
-
-/* Device list or usage::
-
-   The <<device_usage()>> function outputs a list of all the devices
-   compiled into PSIM.  The verbose option will result in additional
-   information being printed (for instance, the interrupt ports).
-
-   */
+(int) device_trace
+(device *me);
 
-INLINE_DEVICE\
-(void) device_usage
-(int verbose);
 
 
 /* External representation:
@@ -612,19 +757,43 @@ INLINE_DEVICE\
 INLINE_DEVICE\
 (device *) external_to_device
 (device *tree_member,
- unsigned32 phandle);
+ unsigned_cell phandle);
 
 INLINE_DEVICE\
-(unsigned32) device_to_external
+(unsigned_cell) device_to_external
 (device *me);
 
 INLINE_DEVICE\
 (device_instance *) external_to_device_instance
 (device *tree_member,
- unsigned32 ihandle);
+ unsigned_cell ihandle);
 
 INLINE_DEVICE\
-(unsigned32) device_instance_to_external
+(unsigned_cell) device_instance_to_external
 (device_instance *me);
 
+
+/* Event queue:
+
+   The device inherets certain event queue operations from the main
+   simulation. */
+
+typedef void device_event_handler(void *data);
+
+INLINE_DEVICE\
+(event_entry_tag) device_event_queue_schedule
+(device *me,
+ signed64 delta_time,
+ device_event_handler *handler,
+ void *data);
+
+INLINE_EVENTS\
+(void) device_event_queue_deschedule
+(device *me,
+ event_entry_tag event_to_remove);
+
+INLINE_EVENTS\
+(signed64) device_event_queue_time
+(device *me);
+
 #endif /* _DEVICE_H_ */
index 9eb3a4e..e569dd7 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
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
+
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
     */
 
 
@@ -28,8 +28,6 @@
 #include "emul_generic.h"
 #include "emul_chirp.h"
 
-#include "cap.h"
-
 #ifdef HAVE_STRING_H
 #include <string.h>
 #else
 #endif
 
 
+/* EMULATION
+
+
+   OpenFirmware - IEEE Standard for Boot (Initialization
+   Configuration) Firmware.
+
+
+   DESCRIPTION
+
+
+   BUGS
+
+   
+   This code assumes that the memory node has #address-cells and
+   #size-cells set to one.  For future implementations, this may not
+   be the case.
+
+   */
+
+
+
+
 /* Descriptor of the open boot services being emulated */
 
 typedef int (chirp_handler)
      (os_emul_data *data,
       cpu *processor,
       unsigned_word cia);
+
 typedef struct _chirp_services {
   const char *name;
   chirp_handler *handler;
@@ -61,53 +82,127 @@ typedef struct _chirp_services {
    request or waiting on a client callback */
 typedef enum {
   serving,
+  emulating,
   faulting,
-  catching,
 } chirp_emul_state;
 
 struct _os_emul_data {
   chirp_emul_state state;
   unsigned_word return_address;
   unsigned_word arguments;
+  unsigned_word n_args;
+  unsigned_word n_returns;
   chirp_services *service;
-  unsigned_word serving_instruction_ea;
-  unsigned_word catching_instruction_ea;
-  cap *phandles;
   device *root;
   chirp_services *services;
+  /* configuration */
+  unsigned_word memory_size;
+  unsigned_word real_base;
+  unsigned_word real_size;
+  unsigned_word virt_base;
+  unsigned_word virt_size;
+  int real_mode;
+  int little_endian;
+  int floating_point_available;
+  int interrupt_prefix;
+  unsigned_word load_base;
+  /* hash table */
+  unsigned_word nr_page_table_entry_groups;
+  unsigned_word htab_offset;
+  unsigned_word htab_ra;
+  unsigned_word htab_va;
+  unsigned_word sizeof_htab;
+  /* virtual address of htab */
+  unsigned_word stack_offset;
+  unsigned_word stack_ra;
+  unsigned_word stack_va;
+  unsigned_word sizeof_stack;
+  /* addresses of emulation instructions virtual/real */
+  unsigned_word code_offset;
+  unsigned_word code_va;
+  unsigned_word code_ra;
+  unsigned_word sizeof_code;
+  unsigned_word code_client_va;
+  unsigned_word code_client_ra;
+  unsigned_word code_callback_va;
+  unsigned_word code_callback_ra;
+  unsigned_word code_loop_va;
+  unsigned_word code_loop_ra;
 };
 
 
-/* Read in the argument list and make the most basic check that number
-   of argumnets are consistent with what was expected */
+/* returns the name of the corresponding Ihandle */
+static const char *
+ihandle_name(device_instance *ihandle)
+{
+  if (ihandle == NULL)
+    return "";
+  else
+    return device_name(device_instance_device(ihandle));
+}
+
+
+
+/* Read/write the argument list making certain that all values are
+   converted to/from host byte order.
+
+   In the below only n_args+n_returns is read/written */
 
 static int
-chirp_read_args(void *args,
-               int sizeof_args,
-               int n_args,
-               int n_returns,
-               os_emul_data *data,
-               cpu *processor,
-               unsigned_word cia)
+chirp_read_t2h_args(void *args,
+                   int sizeof_args,
+                   int n_args,
+                   int n_returns,
+                   os_emul_data *data,
+                   cpu *processor,
+                   unsigned_word cia)
 {
-  struct base_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
-  } *base;
-  emul_read_buffer(args, data->arguments,
-                  sizeof_args,
-                  processor, cia);
-  base = (struct base_args*)args;
-  if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) {
-    TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n",
-                         (long)T2H_4(base->n_args),
-                         (long)T2H_4(base->n_returns)));
+  unsigned_cell *words;
+  int i;
+  /* check against the number of arguments specified by the client
+     program */
+  if ((n_args >= 0 && data->n_args != n_args)
+      || (n_returns >= 0 && data->n_returns != n_returns)) {
+    TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
+                         data->service->name,
+                         (long)data->n_args,
+                         (long)data->n_returns));
     return -1;
   }
+  /* check that there is enough space */
+  if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args)
+    return -1;
+  /* bring in the data */
+  memset(args, 0, sizeof_args);
+  emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
+                  sizeof(unsigned_cell) * (data->n_args + data->n_returns),
+                  processor, cia);
+  /* convert all words to host format */
+  words = args;
+  for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
+    words[i] = T2H_cell(words[i]);
   return 0;
 }
 
+static void
+chirp_write_h2t_args(void *args,
+                    int sizeof_args,
+                    os_emul_data *data,
+                    cpu *processor,
+                    unsigned_word cia)
+{
+  int i;
+  unsigned_cell *words;
+  /* convert to target everything */
+  words = args;
+  for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
+    words[i] = H2T_cell(words[i]);
+  /* bring in the data */
+  emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
+                   sizeof(unsigned_cell) * (data->n_args + data->n_returns),
+                   processor, cia);
+}
+
 
 /* OpenBoot emulation functions */
 
@@ -119,23 +214,21 @@ chirp_emul_test(os_emul_data *data,
                unsigned_word cia)
 {
   struct test_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 name; /*string*/
+    unsigned_cell name; /*string*/
     /*out*/
-    unsigned32 missing;
+    unsigned_cell missing;
   } args;
   char name[32];
-  chirp_services *service = data->services;
+  chirp_services *service = NULL;
   /* read in the arguments */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  emul_read_string(name, T2H_4(args.name), sizeof(name),
+  emul_read_string(name, args.name, sizeof(name),
                   processor, cia);
   TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
   /* see if we know about the service */
+  service = data->services;
   while (service->name != NULL && strcmp(service->name, name) != 0) {
     service++;
   }
@@ -146,9 +239,10 @@ chirp_emul_test(os_emul_data *data,
   /* write the arguments back out */
   TRACE(trace_os_emul, ("test - out - missing=%ld\n",
                        (long)args.missing));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -161,45 +255,46 @@ chirp_emul_peer(os_emul_data *data,
                unsigned_word cia)
 {
   struct peer_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
+    unsigned_cell phandle;
     /*out*/
-    unsigned32 sibling_phandle;
+    unsigned_cell sibling_phandle;
   } args;
-  device *dev;
-  device *sibling_dev = NULL;
+  device *phandle;
+  device *sibling_phandle = NULL;
   /* read in the arguments */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  dev = cap_internal(data->phandles, args.phandle);
+  phandle = external_to_device(data->root, args.phandle);
   TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle))));
   /* find the peer */
-  if (dev == NULL && args.phandle != 0)
-    return -1;
-  if (args.phandle == 0)
-    sibling_dev = data->root;
-  else
-    sibling_dev = device_sibling(dev);
-  if (sibling_dev == NULL)
-    args.sibling_phandle = 0;
-  else
-    args.sibling_phandle = cap_external(data->phandles, sibling_dev);
+  if (args.phandle == 0) {
+    sibling_phandle = data->root;
+    args.sibling_phandle = device_to_external(sibling_phandle);
+  }
+  else if (phandle == NULL) {
+    sibling_phandle = NULL;
+    args.sibling_phandle = -1;
+  }
+  else {
+    sibling_phandle = device_sibling(phandle);
+    if (sibling_phandle == NULL)
+      args.sibling_phandle = 0;
+    else
+      args.sibling_phandle = device_to_external(sibling_phandle);
+  }
   /* write the arguments back out */
   TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.sibling_phandle),
-                       (unsigned long)sibling_dev,
-                       (sibling_dev == NULL
-                        ? ""
-                        : device_name(sibling_dev))));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.sibling_phandle,
+                       (unsigned long)sibling_phandle,
+                       (sibling_phandle == NULL ? "" : device_name(sibling_phandle))));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -209,40 +304,43 @@ chirp_emul_child(os_emul_data *data,
                 unsigned_word cia)
 {
   struct child_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
+    unsigned_cell phandle;
     /*out*/
-    unsigned32 child_phandle;
+    unsigned_cell child_phandle;
   } args;
-  device *dev;
-  device *child_dev;
+  device *phandle;
+  device *child_phandle;
   /* read the arguments in */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  dev = cap_internal(data->phandles, args.phandle);
+  phandle = external_to_device(data->root, args.phandle);
   TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle))));
   /* find a child */
-  if (dev == (device*)0)
-    return -1;
-  child_dev = device_child(dev);
-  if (child_dev == NULL)
-    args.child_phandle = 0;
-  else
-    args.child_phandle = cap_external(data->phandles, child_dev);
+  if (args.phandle == 0
+      || phandle == NULL) {
+    child_phandle = NULL;
+    args.child_phandle = -1;
+  }
+  else {
+    child_phandle = device_child(phandle);
+    if (child_phandle == NULL)
+      args.child_phandle = 0;
+    else
+      args.child_phandle = device_to_external(child_phandle);
+  }
   /* write the result out */
   TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.child_phandle),
-                       (unsigned long)child_dev,
-                       (child_dev == NULL ? "" : device_name(child_dev))));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.child_phandle,
+                       (unsigned long)child_phandle,
+                       (child_phandle == NULL ? "" : device_name(child_phandle))));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -252,40 +350,43 @@ chirp_emul_parent(os_emul_data *data,
                  unsigned_word cia)
 {
   struct parent_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
+    unsigned_cell phandle;
     /*out*/
-    unsigned32 parent_phandle;
+    unsigned_cell parent_phandle;
   } args;
-  device *dev;
-  device *parent_dev;
+  device *phandle;
+  device *parent_phandle;
   /* read the args in */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  dev = cap_internal(data->phandles, args.phandle);
+  phandle = external_to_device(data->root, args.phandle);
   TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle))));
   /* find a parent */
-  if (dev == (device*)0)
-    return -1;
-  parent_dev = device_parent(dev);
-  if (parent_dev == NULL)
-    args.parent_phandle = 0;
-  else
-    args.parent_phandle = cap_external(data->phandles, parent_dev);
+  if (args.phandle == 0
+      || phandle == NULL) {
+    parent_phandle = NULL;
+    args.parent_phandle = -1;
+  }
+  else {
+    parent_phandle = device_parent(phandle);
+    if (parent_phandle == NULL)
+      args.parent_phandle = 0;
+    else
+      args.parent_phandle = device_to_external(parent_phandle);
+  }
   /* return the result */
   TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.parent_phandle),
-                       (unsigned long)parent_dev,
-                       (parent_dev == NULL ? "" : device_name(parent_dev))));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.parent_phandle,
+                       (unsigned long)parent_phandle,
+                       (parent_phandle == NULL ? "" : device_name(parent_phandle))));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -294,7 +395,40 @@ chirp_emul_instance_to_package(os_emul_data *data,
                               cpu *processor,
                               unsigned_word cia)
 {
-  error("chirp: instance-to-package unimplemented\n");
+  struct instance_to_package_args {
+    /*in*/
+    unsigned_cell ihandle;
+    /*out*/
+    unsigned_cell phandle;
+  } args;
+  device_instance *ihandle;
+  device *phandle = NULL;
+  /* read the args in */
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
+    return -1;
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle)));
+  /* find the corresponding phandle */
+  if (ihandle == NULL) {
+    phandle = NULL;
+    args.phandle = -1;
+  }
+  else {
+    phandle = device_instance_device(ihandle);
+    args.phandle = device_to_external(phandle);
+  }
+  /* return the result */
+  TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle))));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -304,47 +438,48 @@ chirp_emul_getproplen(os_emul_data *data,
                      unsigned_word cia)
 {
   struct getproplen_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
-    unsigned32 name;
+    unsigned_cell phandle;
+    unsigned_cell name;
     /*out*/
-    unsigned32 proplen;
+    unsigned_cell proplen;
   } args;
   char name[32];
-  device *dev;
-  const device_property *prop;
+  device *phandle;
   /* read the args in */
-  if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
-    return -1;
-  dev = cap_internal(data->phandles, args.phandle);
-  /* find our prop and get its length */
-  if (dev == (device*)0)
+  if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia))
     return -1;
+  phandle = external_to_device(data->root, args.phandle);
   emul_read_string(name,
-                  T2H_4(args.name),
+                  args.name,
                   sizeof(name),
                   processor, cia);
   TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev)),
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle)),
                        name));
-  prop = device_find_property(dev, name);
-  if (prop == (device_property*)0) {
+  /* find our prop and get its length */
+  if (args.phandle == 0
+      || phandle == NULL) {
     args.proplen = -1;
   }
   else {
-    args.proplen = H2T_4(prop->sizeof_array);
+    const device_property *prop = device_find_property(phandle, name);
+    if (prop == (device_property*)0) {
+      args.proplen = -1;
+    }
+    else {
+      args.proplen = prop->sizeof_array;
+    }
   }
   /* return the result */
   TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
-                       (unsigned long)T2H_4(args.proplen)));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.proplen));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -354,65 +489,77 @@ chirp_emul_getprop(os_emul_data *data,
                   unsigned_word cia)
 {
   struct getprop_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 phandle;
-    unsigned32 name;
-    unsigned32 buf;
-    unsigned32 buflen;
+    unsigned_cell phandle;
+    unsigned_cell name;
+    unsigned_cell buf;
+    unsigned_cell buflen;
     /*out*/
-    unsigned32 size;
+    unsigned_cell size;
   } args;
   char name[32];
-  device *dev;
-  const device_property *prop;
-  /* read in the args */
-  if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
+  device *phandle;
+  /* read in the args, the return is optional */
+  if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia))
     return -1;
-  dev = cap_internal(data->phandles, args.phandle);
+  phandle = external_to_device(data->root, args.phandle);
   emul_read_string(name,
-                  T2H_4(args.name),
+                  args.name,
                   sizeof(name),
                   processor, cia);
   TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev)),
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle)),
                        name,
-                       (unsigned long)T2H_4(args.buf),
-                       (unsigned long)T2H_4(args.buflen)));
+                       (unsigned long)args.buf,
+                       (unsigned long)args.buflen));
   /* get the property */
-  if (dev == (device*)0)
-    return -1;
-  prop = device_find_property(dev, name);
-  if (prop == (device_property*)0) {
+  if (args.phandle == 0
+      || phandle == NULL) {
     args.size = -1;
   }
   else {
-    int size = T2H_4(args.buflen);
-    if (size > prop->sizeof_array)
-      size = prop->sizeof_array;
-    emul_write_buffer(prop->array, T2H_4(args.buf),
-                     size,
-                     processor, cia);
-    args.size = H2T_4(size);
-  }
-  switch (prop->type) {
-  case string_property:
-    TRACE(trace_os_emul, ("getprop - value=`%s' (string)\n",
-                         (char*)prop->array));
-    break;
-  default:
-    break;
+    const device_property *prop = device_find_property(phandle, name);
+    if (prop == NULL) {
+      args.size = -1;
+    }
+    else {
+      int size = args.buflen;
+      if (size > prop->sizeof_array)
+       size = prop->sizeof_array;
+      emul_write_buffer(prop->array, args.buf,
+                       size,
+                       processor, cia);
+      args.size = size;
+      switch (prop->type) {
+      case string_property:
+       TRACE(trace_os_emul, ("getprop - string `%s'\n",
+                             device_find_string_property(phandle, name)));
+       break;
+      case ihandle_property:
+       TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
+                             BE2H_cell(*(unsigned_cell*)prop->array),
+                             (unsigned long)device_find_ihandle_property(phandle, name),
+                             ihandle_name(device_find_ihandle_property(phandle, name))));
+       break;
+      default:
+       break;
+      }
+    }
   }
   /* write back the result */
-  TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
-                       (unsigned long)T2H_4(args.size)));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+  if (data->n_returns == 0)
+    TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n",
+                         (unsigned long)args.size));
+  else {
+    TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
+                         (unsigned long)args.size));
+    chirp_write_h2t_args(&args,
+                        sizeof(args),
+                        data,
+                        processor, cia);
+  }
   return 0;
 }
 
@@ -421,25 +568,127 @@ chirp_emul_nextprop(os_emul_data *data,
                    cpu *processor,
                    unsigned_word cia)
 {
-  error("chirp: nextprop not implemented\n");
+  struct nextprop_args {
+    /*in*/
+    unsigned_cell phandle;
+    unsigned_cell previous;
+    unsigned_cell buf;
+    /*out*/
+    unsigned_cell flag;
+  } args;
+  char previous[32];
+  device *phandle;
+  /* read in the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
+    return -1;
+  phandle = external_to_device(data->root, args.phandle);
+  emul_read_string(previous,
+                  args.previous,
+                  sizeof(previous),
+                  processor, cia);
+  TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle)),
+                       previous,
+                       (unsigned long)args.buf));
+  /* find the next property */
+  if (args.phandle == 0
+      || phandle == NULL) {
+    args.flag = -1;
+  }
+  else {
+    const device_property *prev_prop = device_find_property(phandle, previous);
+    if (prev_prop == NULL) {
+      args.flag = -1; /* name invalid */
+    }
+    else {
+      const device_property *next_prop;
+      next_prop = device_next_property(prev_prop);
+      if (next_prop == NULL) {
+       args.flag = 0; /* last property */
+      }
+      else {
+       emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name),
+                         processor, cia);
+       TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name));
+       args.flag = 1; /* worked ok */
+      }
+    }
+  }
+  /* write back the result */
+  TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n",
+                       (unsigned long)args.flag));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
+#if 0
 static int
 chirp_emul_setprop(os_emul_data *data,
                   cpu *processor,
                   unsigned_word cia)
 {
-  error("chirp: setprop not implemented\n");
+  error("chirp: setprop method not implemented\n");
   return 0;
 }
+#endif
 
 static int
 chirp_emul_canon(os_emul_data *data,
-                 cpu *processor,
-                 unsigned_word cia)
+                cpu *processor,
+                unsigned_word cia)
 {
-  error("chirp: canon not implemented\n");
+  struct canon_args {
+    /*in*/
+    unsigned_cell device_specifier;
+    unsigned_cell buf;
+    unsigned_cell buflen;
+    /*out*/
+    unsigned_cell length;
+  } args;
+  char device_specifier[1024];
+  device *phandle;
+  const char *path;
+  int length;
+  /* read in the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
+    return -1;
+  emul_read_string(device_specifier,
+                  args.device_specifier,
+                  sizeof(device_specifier),
+                  processor, cia);
+  TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
+                       device_specifier,
+                       (unsigned long)args.buf,
+                       (unsigned long)args.buflen));
+  /* canon the name */
+  phandle = tree_find_device(data->root, device_specifier);
+  if (phandle == NULL) {
+    length = -1;
+    path = "";
+    args.length = -1;
+  }
+  else {
+    path = device_path(phandle);
+    length = strlen(path);
+    if (length >= args.buflen)
+      length = args.buflen - 1;
+    emul_write_buffer(path, args.buf, length,
+                     processor, cia);
+    args.length = length;
+  }
+  /* write back the result */
+  TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n",
+                       (unsigned long)args.length,
+                       path));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -449,40 +698,37 @@ chirp_emul_finddevice(os_emul_data *data,
                      unsigned_word cia)
 {
   struct finddevice_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 device_specifier;
+    unsigned_cell device_specifier;
     /*out*/
-    unsigned32 phandle;
+    unsigned_cell phandle;
   } args;
   char device_specifier[1024];
-  device *dev;
+  device *phandle;
   /* get the args */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
   emul_read_string(device_specifier,
-                  T2H_4(args.device_specifier),
+                  args.device_specifier,
                   sizeof(device_specifier),
                   processor, cia);
   TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
                        device_specifier));
   /* find the device */
-  dev = device_tree_find_device(data->root,
-                               device_specifier);
-  if (dev == (device*)0)
+  phandle = tree_find_device(data->root, device_specifier);
+  if (phandle == NULL)
     args.phandle = -1;
   else
-    args.phandle = cap_external(data->phandles, dev);
+    args.phandle = device_to_external(phandle);
   /* return its phandle */
   TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
-                       (unsigned long)T2H_4(args.phandle),
-                       (unsigned long)dev,
-                       (dev == NULL ? "" : device_name(dev))));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle))));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -491,25 +737,162 @@ chirp_emul_instance_to_path(os_emul_data *data,
                            cpu *processor,
                            unsigned_word cia)
 {
-  error("chirp: instance_to_path not implemented\n");
+  struct instance_to_path_args {
+    /*in*/
+    unsigned_cell ihandle;
+    unsigned_cell buf;
+    unsigned_cell buflen;
+    /*out*/
+    unsigned_cell length;
+  } args;
+  device_instance *ihandle;
+  const char *path;
+  int length;
+  /* get the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
+    return -1;
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle),
+                       (unsigned long)args.buf,
+                       (unsigned long)args.buflen));
+  /* get the devices name */
+  if (ihandle == NULL) {
+    args.length = -1;
+    path = "(null)";
+  }
+  else {
+    path = device_instance_path(ihandle);
+    length = strlen(path);
+    if (length >= args.buflen)
+      length = args.buflen - 1;
+    emul_write_buffer(path, args.buf, length,
+                     processor, cia);
+    args.length = length;
+  }
+  /* return its phandle */
+  TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n",
+                       (unsigned long)args.length,
+                       path));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
 static int
 chirp_emul_package_to_path(os_emul_data *data,
-                           cpu *processor,
-                           unsigned_word cia)
+                          cpu *processor,
+                          unsigned_word cia)
 {
-  error("chirp: package_to_path not implemented\n");
+  struct package_to_path_args {
+    /*in*/
+    unsigned_cell phandle;
+    unsigned_cell buf;
+    unsigned_cell buflen;
+    /*out*/
+    unsigned_cell length;
+  } args;
+  device *phandle;
+  const char *path;
+  /* get the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
+    return -1;
+  phandle = external_to_device(data->root, args.phandle);
+  TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
+                       (unsigned long)args.phandle,
+                       (unsigned long)phandle,
+                       (phandle == NULL ? "" : device_name(phandle)),
+                       (unsigned long)args.buf,
+                       (unsigned long)args.buflen));
+  /* get the devices name */
+  if (phandle == NULL) {
+    args.length = -1;
+    path = "(null)";
+  }
+  else {
+    int length;
+    path = device_path(phandle);
+    length = strlen(path);
+    if (length >= args.buflen)
+      length = args.buflen - 1;
+    emul_write_buffer(path, args.buf, length,
+                     processor, cia);
+    args.length = length;
+  }
+  /* return its phandle */
+  TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n",
+                       (unsigned long)args.length,
+                       path));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
 static int
 chirp_emul_call_method(os_emul_data *data,
-                           cpu *processor,
-                           unsigned_word cia)
+                      cpu *processor,
+                      unsigned_word cia)
 {
-  error("chirp: call-method implemented\n");
+  struct call_method_args {
+    /*in*/
+    unsigned_cell method;
+    unsigned_cell ihandle;
+    /*in/out*/
+    unsigned_cell stack[13]; /*6in + 6out + catch */
+  } args;
+  char method[32];
+  device_instance *ihandle;
+  /* some useful info about our mini stack */
+  int n_stack_args;
+  int n_stack_returns;
+  int stack_catch_result;
+  int stack_returns;
+  /* read the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia))
+    return -1;
+  emul_read_string(method,
+                  args.method,
+                  sizeof(method),
+                  processor, cia);
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  n_stack_args = data->n_args - 2;
+  n_stack_returns = data->n_returns - 1;
+  stack_catch_result = n_stack_args;
+  stack_returns = stack_catch_result + 1;
+  TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)data->n_args,
+                       (unsigned long)data->n_returns,
+                       method,
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle)));
+  /* see if we can emulate this method */
+  if (ihandle == NULL) {
+    /* OpenFirmware doesn't define this error */
+    error("chirp: invalid ihandle passed to call-method method");
+  }
+  else {
+    args.stack[stack_catch_result] =
+      device_instance_call_method(ihandle,
+                                 method,
+                                 n_stack_args,
+                                 &args.stack[0],
+                                 n_stack_returns,
+                                 &args.stack[stack_returns]);
+  }
+  /* finished */
+  TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n",
+                       (unsigned long)args.stack[stack_catch_result]));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -522,33 +905,37 @@ chirp_emul_open(os_emul_data *data,
                unsigned_word cia)
 {
   struct open_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 device_specifier;
+    unsigned_cell device_specifier;
     /*out*/
-    unsigned32 ihandle;
+    unsigned_cell ihandle;
   } args;
-  char name[1024];
+  char device_specifier[1024];
+  device_instance *ihandle;
   /* read the args */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
-  emul_read_string(name,
-                  T2H_4(args.device_specifier),
-                  sizeof(name),
+  emul_read_string(device_specifier,
+                  args.device_specifier,
+                  sizeof(device_specifier),
                   processor, cia);
   TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
-                       name));
+                       device_specifier));
   /* open the device */
-  printf_filtered("OpenBoot - open unimplemented for %s\n", name);
-  args.ihandle = -1;
+  ihandle = tree_instance(data->root, device_specifier);
+  if (ihandle == NULL)
+    args.ihandle = -1;
+  else
+    args.ihandle = device_instance_to_external(ihandle);
   /* return the ihandle result */
-  TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
-                       (unsigned long)T2H_4(args.ihandle)));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+  TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle)));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -557,7 +944,34 @@ chirp_emul_close(os_emul_data *data,
                 cpu *processor,
                 unsigned_word cia)
 {
-  error("chirp: close not implemented\n");
+  struct close_args {
+    /*in*/
+    unsigned_cell ihandle;
+    /*out*/
+  } args;
+  device_instance *ihandle;
+  /* read the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia))
+    return -1;
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle)));
+  /* close the device */
+  if (ihandle == NULL) {
+    /* OpenFirmware doesn't define this error */
+    error("chirp: invalid ihandle passed to close method");
+  }
+  else {
+    device_instance_delete(ihandle);
+  }
+  /* return the ihandle result */
+  TRACE(trace_os_emul, ("close - out\n"));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -567,94 +981,135 @@ chirp_emul_read(os_emul_data *data,
                unsigned_word cia)
 {
   struct read_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 ihandle;
-    unsigned32 addr;
-    unsigned32 len;
+    unsigned_cell ihandle;
+    unsigned_cell addr;
+    unsigned_cell len;
     /*out*/
-    unsigned32 actual;
+    unsigned_cell actual;
   } args;
   char buf[1024];
-  int actual;
+  device_instance *ihandle;
   /* read the args */
-  if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
     return -1;
-  TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n",
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
                        (unsigned long)args.ihandle,
-                       (unsigned long)T2H_4(args.addr),
-                       (unsigned long)T2H_4(args.len)));
-  /* do the read */
-  actual = T2H_4(args.len);
-  if (actual >= sizeof(buf))
-    actual = sizeof(buf) - 1;
-  actual = read(BE2H_4(args.ihandle), buf, actual);
-  if (actual >= 0) {
-    emul_write_buffer(buf,
-                     T2H_4(args.addr),
-                     actual,
-                     processor, cia);
-    args.actual = H2T_4(actual);
-    buf[actual] = '\0';
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle),
+                       (unsigned long)args.addr,
+                       (unsigned long)args.len));
+  if (ihandle == NULL) {
+    /* OpenFirmware doesn't define this error */
+    error("chirp: invalid ihandle passed to read method");
   }
   else {
-    args.actual = 0;
+    /* do the reads */
+    int actual = 0;
+    while (actual < args.len) {
+      int remaining = args.len - actual;
+      int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf));
+      int nr_read = device_instance_read(ihandle, buf, to_read);
+      if (nr_read < 0) {
+       actual = nr_read; /* the error */
+       break;
+      }
+      else if (nr_read == 0) {
+       break;
+      }
+      emul_write_buffer(buf,
+                       args.addr + actual,
+                       nr_read,
+                       processor, cia);
+      actual += nr_read;
+    }
+    if (actual >= 0) {
+      args.actual = actual;
+      if (actual < sizeof(buf))
+       buf[actual] = '\0';
+      else
+       buf[sizeof(buf) - 1] = '\0';
+    }
+    else {
+      switch (actual) {
+      case sim_io_eof:
+       args.actual = 0;
+       break;
+      case sim_io_not_ready:
+       ASSERT(sim_io_not_ready == -2);
+       args.actual = sim_io_not_ready;
+       break;
+      default:
+       error("Bad error value %ld", (long)actual);
+       break;
+      }
+    }
   }
   /* return the result */
   TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
-                       (long)T2H_4(args.actual),
-                       (actual >= 0 ? buf : "")));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (long)args.actual,
+                       ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "")
+                       ));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
 static int
 chirp_emul_write(os_emul_data *data,
-               cpu *processor,
-               unsigned_word cia)
+                cpu *processor,
+                unsigned_word cia)
 {
   struct write_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
-    unsigned32 ihandle;
-    unsigned32 addr;
-    unsigned32 len;
+    unsigned_cell ihandle;
+    unsigned_cell addr;
+    unsigned_cell len;
     /*out*/
-    unsigned32 actual;
+    unsigned_cell actual;
   } args;
   char buf[1024];
+  device_instance *ihandle;
   int actual;
   /* get the args */
-  if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
     return -1;
-  actual = T2H_4(args.len);
+  actual = args.len;
   if (actual >= sizeof(buf))
     actual = sizeof(buf) - 1;
   emul_read_buffer(buf,
-                  T2H_4(args.addr),
+                  args.addr,
                   actual,
                   processor, cia);
   buf[actual] = '\0';
-  TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
-                       (unsigned long)args.ihandle, buf, (long)actual));
-  /* write it out */
-  actual = write(BE2H_4(args.ihandle), buf, actual);
-  if (actual < 0)
-    args.actual = 0;
-  else
-    args.actual = H2T_4(actual);
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle),
+                       buf, (long)actual));
+  if (ihandle == NULL) {
+    /* OpenFirmware doesn't define this error */
+    error("chirp: invalid ihandle passed to write method");
+  }
+  else {
+    /* write it out */
+    actual = device_instance_write(ihandle, buf, actual);
+    if (actual < 0)
+      args.actual = 0;
+    else
+      args.actual = actual;
+  }
   /* return the result */
   TRACE(trace_os_emul, ("write - out - actual=%ld\n",
-                       (long)T2H_4(args.actual)));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (long)args.actual));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -663,7 +1118,41 @@ chirp_emul_seek(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  error("chirp: seek not implemented\n");
+  struct seek_args {
+    /*in*/
+    unsigned_cell ihandle;
+    unsigned_cell pos_hi;
+    unsigned_cell pos_lo;
+    /*out*/
+    unsigned_cell status;
+  } args;
+  int status;
+  device_instance *ihandle;
+  /* get the args */
+  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
+    return -1;
+  ihandle = external_to_device_instance(data->root, args.ihandle);
+  TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
+                       (unsigned long)args.ihandle,
+                       (unsigned long)ihandle,
+                       ihandle_name(ihandle),
+                       args.pos_hi, args.pos_lo));
+  if (ihandle == NULL) {
+    /* OpenFirmware doesn't define this error */
+    error("chirp: invalid ihandle passed to seek method");
+  }
+  else {
+    /* seek it out */
+    status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
+    args.status = status;
+  }
+  /* return the result */
+  TRACE(trace_os_emul, ("seek - out - status=%ld\n",
+                       (long)args.status));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -675,7 +1164,55 @@ chirp_emul_claim(os_emul_data *data,
                 cpu *processor,
                 unsigned_word cia)
 {
-  error("chirp: claim not implemented\n");
+  /* NOTE: the client interface claim routine is *very* different to
+     the "claim" method described in IEEE-1275 appendix A.  The latter
+     uses real addresses while this uses virtual (effective)
+     addresses. */
+  struct claim_args {
+    /* in */
+    unsigned_cell virt;
+    unsigned_cell size;
+    unsigned_cell align;
+    /* out */
+    unsigned_cell baseaddr;
+  } args;
+  /* read the args */
+  if (chirp_read_t2h_args(&args, sizeof(args),
+                         3 /*n_args*/, 1 /*n_returns*/,
+                         data, processor, cia))
+    return -1;
+  TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n",
+                       (unsigned long)args.virt,
+                       (long int)args.size,
+                       (int)args.align));
+  /* use the memory device to allocate (real) memory at the requested
+     address */
+  {
+    device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
+    unsigned_cell mem_in[3];
+    unsigned_cell mem_out[1];
+    mem_in[0] = args.align; /*top-of-stack*/
+    mem_in[1] = args.size;
+    mem_in[2] = args.virt;
+    if (device_instance_call_method(memory, "claim",
+                                   3, mem_in, 1, mem_out) < 0)
+      error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
+           (unsigned long)args.virt,
+           (long int)args.size,
+           (int)args.align);
+    args.baseaddr = mem_out[0];
+  }
+  /* if using virtual addresses, create a 1-1 map of this address space */
+  if (!data->real_mode) {
+    error("chirp: claim method does not support virtual mode");
+  }
+  /* return the base address */
+  TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n",
+                       (unsigned long)args.baseaddr));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -684,7 +1221,47 @@ chirp_emul_release(os_emul_data *data,
                   cpu *processor,
                   unsigned_word cia)
 {
-  error("chirp: release not implemented\n");
+  /* NOTE: the client interface release routine is *very* different to
+     the "claim" method described in IEEE-1275 appendix A.  The latter
+     uses real addresses while this uses virtual (effective)
+     addresses. */
+  struct claim_args {
+    /* in */
+    unsigned_cell virt;
+    unsigned_cell size;
+    /* out */
+  } args;
+  /* read the args */
+  if (chirp_read_t2h_args(&args, sizeof(args),
+                         2 /*n_args*/, 0 /*n_returns*/,
+                         data, processor, cia))
+    return -1;
+  TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n",
+                       (unsigned long)args.virt,
+                       (long int)args.size));
+  /* use the memory device to release (real) memory at the requested
+     address */
+  {
+    device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
+    unsigned_cell mem_in[2];
+    mem_in[0] = args.size;
+    mem_in[1] = args.virt;
+    if (device_instance_call_method(memory, "release",
+                                   2, mem_in, 0, NULL) < 0)
+      error("chirp: claim failed to release memory virt=0x%lx size=%ld",
+           (unsigned long)args.virt,
+           (long int)args.size);
+  }
+  /* if using virtual addresses, remove the 1-1 map of this address space */
+  if (!data->real_mode) {
+    error("chirp: release method does not support virtual mode");
+  }
+  /* return the base address */
+  TRACE(trace_os_emul, ("release - out\n"));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -696,7 +1273,25 @@ chirp_emul_boot(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  error("chirp: boot not implemented\n");
+  /* unlike OpenFirmware this one can take an argument */
+  struct boot_args {
+    /*in*/
+    unsigned_cell bootspec;
+    /*out*/
+  } args;
+  char bootspec[1024];
+  /* read in the arguments */
+  if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
+    cpu_halt(processor, cia, was_exited, -1);
+  if (args.bootspec != 0)
+    emul_read_string(bootspec, args.bootspec, sizeof(bootspec),
+                    processor, cia);
+  else
+    strcpy(bootspec, "(null)");
+  TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec));
+  /* just report this and exit */
+  printf_filtered("chrp: boot %s called, exiting.\n", bootspec);
+  cpu_halt(processor, cia, was_exited, 0);
   return 0;
 }
 
@@ -705,7 +1300,7 @@ chirp_emul_enter(os_emul_data *data,
                 cpu *processor,
                 unsigned_word cia)
 {
-  error("chirp: enter not implemented\n");
+  error("chirp: enter method not implemented\n");
   return 0;
 }
 
@@ -714,7 +1309,15 @@ chirp_emul_exit(os_emul_data *data,
                cpu *processor,
                unsigned_word cia)
 {
-  cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+  /* unlike OpenBoot this one can take an argument */
+  struct exit_args {
+    /*in*/
+    signed_cell status;
+    /*out*/
+  } args;
+  if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
+    cpu_halt(processor, cia, was_exited, -1);
+  cpu_halt(processor, cia, was_exited, args.status);
   return 0;
 }
 
@@ -723,7 +1326,7 @@ chirp_emul_chain(os_emul_data *data,
                 cpu *processor,
                 unsigned_word cia)
 {
-  error("chirp: chain not implemented\n");
+  error("chirp: chain method not implemented\n");
   return 0;
 }
 
@@ -735,7 +1338,7 @@ chirp_emul_interpret(os_emul_data *data,
                     cpu *processor,
                     unsigned_word cia)
 {
-  error("chirp: interpret not implemented\n");
+  error("chirp: interpret method not implemented\n");
   return 0;
 }
 
@@ -744,7 +1347,7 @@ chirp_emul_set_callback(os_emul_data *data,
                        cpu *processor,
                        unsigned_word cia)
 {
-  error("chirp: set_callback not implemented\n");
+  error("chirp: set_callback method not implemented\n");
   return 0;
 }
 
@@ -753,7 +1356,7 @@ chirp_emul_set_symbol_lookup(os_emul_data *data,
                             cpu *processor,
                             unsigned_word cia)
 {
-  error("chirp: set_symbol_lookup not implemented\n");
+  error("chirp: set_symbol_lookup method not implemented\n");
   return 0;
 }
 
@@ -766,26 +1369,24 @@ chirp_emul_milliseconds(os_emul_data *data,
                        unsigned_word cia)
 {
   struct test_args {
-    unsigned32 service;
-    unsigned32 n_args;
-    unsigned32 n_returns;
     /*in*/
     /*out*/
-    unsigned32 ms;
+    unsigned_cell ms;
   } args;
   unsigned64 time;
   /* read in the arguments */
-  if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
     return -1;
   /* make up a number */
-  time = event_queue_time(cpu_event_queue(processor)) / 1000000;
-  args.ms = H2T_4(time);
+  time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000;
+  args.ms = time;
   /* write the arguments back out */
   TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
-                       (unsigned long)T2H_4(args.ms)));
-  emul_write_buffer(&args, data->arguments,
-                   sizeof(args),
-                   processor, cia);
+                       (unsigned long)args.ms));
+  chirp_write_h2t_args(&args,
+                      sizeof(args),
+                      data,
+                      processor, cia);
   return 0;
 }
 
@@ -805,7 +1406,7 @@ static chirp_services services[] = {
   { "getproplen", chirp_emul_getproplen },
   { "getprop", chirp_emul_getprop },
   { "nextprop", chirp_emul_nextprop },
-  { "setprop", chirp_emul_setprop },
+  /* { "setprop", chirp_emul_setprop }, */
   { "canon", chirp_emul_canon },
   { "finddevice", chirp_emul_finddevice },
   { "instance-to-path", chirp_emul_instance_to_path },
@@ -850,6 +1451,10 @@ static chirp_services services[] = {
 #ifndef CHIRP_START_ADDRESS
 #define CHIRP_START_ADDRESS 0x80000000
 #endif
+#ifndef CHIRP_LOAD_BASE
+#define CHIRP_LOAD_BASE -1
+#endif
+
 
 typedef struct _chirp_note_desc {
   signed32 real_mode;
@@ -857,11 +1462,17 @@ typedef struct _chirp_note_desc {
   signed32 real_size;
   signed32 virt_base;
   signed32 virt_size;
+  signed32 load_base;
 } chirp_note_desc;
 
+typedef enum {
+  note_missing,
+  note_found,
+  note_correct,
+} note_found_status;
 typedef struct _chirp_note {
   chirp_note_desc desc;
-  int found;
+  note_found_status found;
 } chirp_note;
 
 typedef struct _chirp_note_head {
@@ -888,41 +1499,43 @@ map_over_chirp_note(bfd *image,
     head.type = bfd_get_32(image, (void*)&head.type);
     if (head.type != 0x1275)
       return;
-    note->found = 1;
     /* check the name field */
     if (head.namesz > sizeof(name)) {
-      printf_filtered("open-boot warning: note name too long (%ld)\n",
-                     (long)head.namesz);
-      return;
+      error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name));
     }
     if (!bfd_get_section_contents(image, sect,
                                  name, sizeof(head), head.namesz)) {
-      printf_filtered("open-boot warning: note name unreadable\n");
-      return;
+      error("chirp: note name unreadable\n");
     }
     if (strcmp(name, "PowerPC") != 0) {
-      printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
-                     name);
-      return;
+      printf_filtered("chirp: note name (%s) not `PowerPC'\n", name);
     }
-    /* get the contents */
-    if (head.descsz != sizeof(note->desc)) {
-      printf_filtered("open-boot warning: note descriptor of wrong size\n");
+    /* check the size */
+    if (head.descsz == sizeof(note->desc) - sizeof(signed32)) {
+      sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
+    }
+    else if (head.descsz != sizeof(note->desc)) {
+      sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
+      note->found = note_found;
       return;
     }
+    note->found = note_correct;
+    /* get the contents */
     if (!bfd_get_section_contents(image, sect,
                                  &note->desc, /* page align start */
                                  ((sizeof(head) + head.namesz) + 3) & ~3,
                                  head.descsz)) {
-      printf_filtered("open-boot warning: note descriptor unreadable\n");
-      return;
+      error("chirp: note descriptor unreadable\n");
     }
     note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
     note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
     note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
     note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
     note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
-    note->found = 2;
+    if (head.descsz == sizeof(note->desc))
+      note->desc.load_base = bfd_get_32(image, (void*)&note->desc.load_base);
+    else
+      note->desc.load_base = CHIRP_LOAD_BASE;
   }
 }
 
@@ -932,9 +1545,10 @@ emul_chirp_create(device *root,
                  bfd *image,
                  const char *name)
 {
-  os_emul_data *data;
+  os_emul_data *chirp;
+  device *node;
   chirp_note note;
-  int big_endian;
+  int i;
 
   /* Sanity check that this really is the chosen emulation */
   if (name == NULL && image == NULL)
@@ -947,204 +1561,347 @@ emul_chirp_create(device *root,
       && strcmp(name, "openboot") != 0)
     return NULL;
 
-  /* look for an elf note section */
+  /* look for an elf note section, enter its values into the device tree */
   memset(&note, 0, sizeof(note));
   if (image != NULL)
     bfd_map_over_sections(image, map_over_chirp_note, &note);
-  if (name == NULL && image != NULL && !note.found)
+  if (name == NULL && image != NULL && note.found == note_missing)
     return NULL;
 
+  /* Assume that it is a chirp emulation */
+
+  chirp = ZALLOC(os_emul_data);
+  chirp->root = root;
+  chirp->services = services;
+
   /* the root node */
-  device_add_string_property(root,
-                            "name",
-                            "gpl,clayton");
+  tree_parse(root, "/name \"gpl,clayton");
 
-  {
-    const unsigned_word memory_size = 0x200000;
-    
-    /* the hash table */
-    const unsigned nr_page_table_entry_groups = (memory_size < 0x800000
-                                                ? 1024 /* min allowed */
-                                                : (memory_size / 4096 / 2));
-    const unsigned sizeof_htab = nr_page_table_entry_groups * 64;
-    const unsigned_word htab_ra = memory_size - sizeof_htab;
-    
-    /* a page for firmware calls */
-    const unsigned_word sizeof_code = 4096;
-    const unsigned_word code_ra = htab_ra - sizeof_code;
-
-    /* the stack */
-    const unsigned sizeof_stack = 32 * 1024;
-    const unsigned_word stack_ra = code_ra - sizeof_stack;
-    
-    /* the firmware's home */
-    const int real_mode = 0;
-    /*  const unsigned_word real_base = stack_ra; */
-    /*  const unsigned real_size = memory_size - real_base; */
-    const unsigned_word virt_base = CHIRP_START_ADDRESS;
-    /*  const unsigned virt_size = real_size;*/
-    
-    /* the virtual addresses */
-    const unsigned_word stack_va = virt_base;
-    const unsigned_word code_va = stack_va + sizeof_stack;
-    const unsigned_word code_client_va = code_va;
-    const unsigned_word code_callback_va = code_client_va + 16;
-    const unsigned_word code_loop_va = code_callback_va + 16;
-    const unsigned_word htab_va = code_va + sizeof_code;
-
-#ifdef bfd_big_endian  /* new bfd */
-    big_endian = bfd_big_endian(image);
-#else
-    big_endian = image->xvec->byteorder_big_p;
-#endif
+  /* default options */
+  emul_add_tree_options(root, image, "chirp", "oea",
+                       0 /*oea-interrupt-prefix*/);
 
-    /* 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?",
-                                 !big_endian);
-      device_add_string_property(options, 
-                                "env",
-                                "operating");
-      device_add_boolean_property(options,
-                                 "strict-alignment?",
-                                 (WITH_ALIGNMENT == STRICT_ALIGNMENT
-                                  || !big_endian));
-      device_add_boolean_property(options,
-                                 "floating-point?",
-                                 WITH_FLOATING_POINT);
-      device_add_string_property(options,
-                                "os-emul",
-                                "chirp");
-    }
-    
-    /* hardware */
-    device_tree_add_found_uw_u_u(root, "/", "memory",
-                                0, memory_size, access_read_write_exec);
-    
-    /* 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",
-                                   code_loop_va);
-       device_add_integer_property(init_register,
-                                   "0.pc",
-                                   bfd_get_start_address(image));
-       device_add_integer_property(init_register,
-                                   "sp",
-                                   stack_va + sizeof_stack - 16);
-       
-       /* init the code callback along with a loop for the unused cpu's */
-       device_add_integer_property(init_register,
-                                   "r5",
-                                   code_client_va);
-       /* client interface */
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    code_ra + (code_client_va - code_va),
-                                    4, emul_call_instruction);
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    code_ra + (code_client_va - code_va) + 4,
-                                    4, emul_blr_instruction);
-       /* callback return address */
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    code_ra + (code_callback_va - code_va),
-                                    4, emul_call_instruction);
-       /* loop to keep other processors busy */
-       device_tree_add_found_uw_u_u(init, "",
-                                    "data",
-                                    code_ra + (code_loop_va - code_va),
-                                    4, emul_loop_instruction);
-       device_add_integer_property(init_register,
-                                   "msr",
-                                   (msr_machine_check_enable
-                                    | (real_mode
-                                       ? 0 
-                                       : (msr_instruction_relocate
-                                          | msr_data_relocate))
-                                    | (big_endian
-                                       ? 0
-                                       : (msr_little_endian_mode
-                                          | msr_interrupt_little_endian_mode
-                                          ))));
-       device_add_integer_property(init_register,
-                                   "sdr1",
-                                   (htab_ra
-                                    | MASK32(16, 22)
-                                    | ((sizeof_htab - 1) >> 16)));
-       /* FIXME */
-       device_add_integer_property(init_register,
-                                   "sr8",
-                                   0x00fffff8);
-       device_add_integer_property(init_register,
-                                   "sr9",
-                                   0x00fffff9);
-       
-       { /* hash table and vm */
-         device *htab_root = device_tree_add_found_uw_u(init, "", "htab",
-                                                        htab_ra, sizeof_htab);
-         device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
-                                           stack_ra, stack_va, sizeof_stack,
-                                           0x7/*wimg*/, 0x2/*pp*/);
-         device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
-                                           code_ra, code_va, sizeof_code,
-                                           0x7/*wimg*/, 0x2/*pp*/);
-         device_tree_add_found_uw_uw_u_u_u(htab_root, "", "pte",
-                                           htab_ra, htab_va, sizeof_htab,
-                                           0x7/*wimg*/, 0x2/*pp*/);
-         device_tree_add_found_uw_u_u_c(htab_root, "", "pte",
-                                        0x4000, /*magic*/
-                                        0x7/*wimg*/, 0x2/*pp*/,
-                                        bfd_get_filename (image));
-       }
-      }
-    }
-    
-    { /* chosen options */
-      device *chosen = device_tree_add_found(root, "/", "chosen");
-      device_add_string_property(chosen,
-                                "name",
-                                "chosen");
-      device_add_integer_property(chosen,
-                                 "stdin",
-                                 0); /* FIXME: ihandle of stdin */
-      device_add_integer_property(chosen,
-                                 "stdout",
-                                 1); /* FIXME: ihandle of stdout */
-      device_add_string_property(chosen,
-                                "bootpath",
-                                "/disk@0:\\boot");
-      device_add_string_property(chosen,
-                                "bootargs",
-                                "");
-#if 0
-      device_add_integer_property(chosen,
-                                 "memory",
-                                 0); /* FIXME: ihandle of memory */
-      device_add_integer_property(chosen,
-                                 "mmu",
-                                 0);
-#endif
-    }
-    
-    /* FIXME - should come from the device tree */
-    data = ZALLOC(os_emul_data);
-    data->serving_instruction_ea = code_client_va;
-    data->catching_instruction_ea = code_callback_va;
-    data->phandles = cap_create("chirp");
-    data->root = root;
-    data->services = services;
-    return data;
+  /* hardware */
+  emul_add_tree_hardware(root);
+
+  /* basic information */
+  chirp->memory_size
+    = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
+  chirp->little_endian
+    = tree_find_boolean_property(root, "/options/little-endian?");
+  chirp->floating_point_available
+    = tree_find_boolean_property(root, "/openprom/options/floating-point?");
+  chirp->interrupt_prefix =
+    tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+
+
+  /* Perform an interum layout of the openboot firmware in memory */
+
+
+  /* a page for firmware calls */
+  chirp->sizeof_code = 4096;
+  chirp->code_offset = 0x4000; /* possible space for interrupt table */
+
+  /* the stack */
+  chirp->sizeof_stack = 32 * 1024;
+  chirp->stack_offset = chirp->code_offset + chirp->sizeof_code;
+
+  /* the hash table */
+  if (!note.desc.real_mode) {
+    chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
+                                        ? 1024 /* min allowed */
+                                        : (chirp->memory_size / 4096 / 2));
+    chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
+  }
+  chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack;
+
+  /* the actual amount of space needed */
+  chirp->real_size = chirp->htab_offset + chirp->sizeof_htab;
+
+
+  /* now go through and see if it fits in what is available */
+
+
+  /* resolve real-mode? */
+  if (note.found == note_correct)
+    chirp->real_mode = note.desc.real_mode;
+  else if (tree_find_property(root, "/options/real-mode?") != NULL)
+    chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?");
+  else
+    chirp->real_mode = 0;
+  if (tree_find_property(root, "/options/real-mode?") != NULL) {
+    if (!chirp->real_mode
+       != !tree_find_boolean_property(root, "/options/real-mode?"))
+      error("chirp: /options/real-mode? conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/real-mode? %s",
+              chirp->real_mode ? "true" : "false");
+
+  /* resolve real-base */
+  if (note.found == note_correct
+      && note.desc.real_base != (signed32)-1)
+    chirp->real_base = note.desc.real_base;
+  else if (tree_find_property(root, "/options/real-base") != NULL)
+    chirp->real_base = tree_find_integer_property(root, "/options/real-base");
+  else
+    chirp->real_base = chirp->memory_size - chirp->real_size;
+  if (tree_find_property(root, "/options/real-base") != NULL) {
+    if (chirp->real_base != tree_find_integer_property(root, "/options/real-base"))
+      error("chirp: /options/real-base conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/real-base 0x%lx",
+              (unsigned long)chirp->real_base);
+
+  /* resolve real-size */
+  if (note.found == note_correct
+      && note.desc.real_size != (signed32)-1
+      && note.desc.real_size != 0
+      && chirp->real_size > note.desc.real_size)
+    error("chirp: insufficient physical memory for firmware\n");
+  if (tree_find_property(root, "/options/real-size") != NULL) {
+    if (chirp->real_size > tree_find_integer_property(root, "/options/real-size"))
+      error("chirp: /options/real-size conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/real-size 0x%lx",
+              (unsigned long)chirp->real_size);
+
+  /* resolve virt-base */
+  if (chirp->real_mode)
+    chirp->virt_base = chirp->real_base;
+  else if (note.found == note_correct && note.desc.virt_base != (signed32)-1)
+    chirp->virt_base = note.desc.virt_base;
+  else if (tree_find_property(root, "/options/virt-base") != NULL)
+    chirp->virt_base = tree_find_integer_property(root, "/options/virt-base");
+  else
+    chirp->virt_base = CHIRP_START_ADDRESS;
+  if (tree_find_property(root, "/options/virt-base") != NULL) {
+    if (chirp->virt_base != tree_find_integer_property(root, "/options/virt-base"))
+      error("chirp: /options/virt-base conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/virt-base 0x%lx",
+              chirp->real_mode ? -1 : (unsigned long)chirp->virt_base);
+
+  /* resolve virt-size */
+  chirp->virt_size = chirp->real_size;
+  if (note.found == note_correct
+     && note.desc.virt_size != (signed32)-1
+      && note.desc.virt_size != 0
+      && !chirp->real_mode
+      && chirp->virt_size > note.desc.virt_size)
+    error("chirp: insufficent virtual memory for firmware\n");
+  if (tree_find_property(root, "/options/virt-size") != NULL) {
+    if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size"))
+      error("chirp: /options/virt-size conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/virt-size 0x%lx",
+              chirp->real_mode ? -1 : (unsigned long)chirp->virt_size);
+
+  /* resolve load-base */
+  if (note.found == note_correct
+      && note.desc.load_base != (signed32)-1)
+    chirp->load_base = note.desc.load_base;
+  else if (tree_find_property(root, "/options/load-base") != NULL)
+    chirp->load_base = tree_find_integer_property(root, "/options/load-base");
+  else
+    chirp->load_base = CHIRP_LOAD_BASE;
+  if (tree_find_property(root, "/options/load-base") != NULL) {
+    if (chirp->load_base != tree_find_integer_property(root, "/options/load-base"))
+      error("chirp: /options/load-base conflicts with note section\n");
+  }
+  else
+    tree_parse(root, "/options/load-base 0x%lx",
+              (unsigned long)chirp->load_base);
+
+  /* now adjust the preliminary firmware addresses to final values */
+  chirp->code_ra = chirp->code_offset + chirp->real_base;
+  chirp->stack_ra = chirp->stack_offset + chirp->real_base;
+  chirp->htab_ra = chirp->htab_offset + chirp->real_base;
+
+  /* the virtual addresses.  In real mode these are real addresses. */
+
+  chirp->code_va = chirp->code_offset + chirp->virt_base;
+  chirp->stack_va = chirp->stack_offset + chirp->virt_base;
+  chirp->htab_va = chirp->htab_offset + chirp->virt_base;
+
+  chirp->code_client_va = chirp->code_va;
+  chirp->code_client_ra = chirp->code_ra;
+
+  chirp->code_callback_va = chirp->code_client_va + 16;
+  chirp->code_callback_ra = chirp->code_client_ra + 16;
+
+  chirp->code_loop_va = chirp->code_callback_va + 16;
+  chirp->code_loop_ra = chirp->code_callback_ra + 16;
+
+  /* initialization */
+
+  tree_parse(root, "/openprom/init");
+  tree_parse(root, "/openprom/init/register");
+  tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
+            (unsigned long)bfd_get_start_address(image));
+  tree_parse(root, "/openprom/init/register/pc 0x%lx",
+            (unsigned long)chirp->code_loop_va);
+  tree_parse(root, "/openprom/init/register/msr 0x%x",
+            (msr_machine_check_enable
+             | (chirp->real_mode
+                ? 0
+                : (msr_instruction_relocate
+                   | msr_data_relocate))
+             | (chirp->little_endian
+                ? (msr_little_endian_mode
+                   | msr_interrupt_little_endian_mode)
+                : 0)
+             | (chirp->floating_point_available
+                ? msr_floating_point_available
+                : 0)
+             | (chirp->interrupt_prefix
+                ? msr_interrupt_prefix
+                : 0)
+             ));
+  tree_parse(root, "/openprom/init/register/sdr1 0x%lx",
+            (unsigned long)(chirp->htab_ra
+                            | MASK32(16, 22)
+                            | ((chirp->sizeof_htab - 1) >> 16)));
+  /* make certain that the segment registers map straight through */
+  for (i = 0; i < 16; i++) {
+    tree_parse(root, "/openprom/init/register/sr%d 0x%lx",
+              i, (unsigned long)i);
+  }
+
+  /* establish an initial state for all processors */
+
+
+  /* the client interface address */
+  tree_parse(root, "/openprom/init/register/r5 0x%lx",
+            (unsigned long)chirp->code_client_va);
+  /* a stack */
+  tree_parse(root, "/openprom/init/register/sp 0x%lx",
+            (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
+  /* in chrp mode any arguments end up being concatinated */
+  tree_parse(root, "/openprom/init/stack/stack-type chirp");
+
+
+  /* client interface - emul-call followed by return instruction */
+
+
+  node = tree_parse(root, "/openprom/init/data@0x%lx",
+                   (unsigned long)chirp->code_client_ra);
+  tree_parse(node, "./psim,description \"client-interface instruction");
+  tree_parse(node, "./real-address 0x%lx",
+            (unsigned long)chirp->code_client_ra);
+  tree_parse(node, "./data 0x%lx",
+            (unsigned long)emul_call_instruction);
+
+  node = tree_parse(root, "/openprom/init/data@0x%lx",
+                   (unsigned long)(chirp->code_client_ra + 4));
+  tree_parse(node, "./psim,description \"client-interface return instruction");
+  tree_parse(node, "./real-address 0x%lx",
+            (unsigned long)(chirp->code_client_ra + 4));
+  tree_parse(node, "./data 0x%lx",
+            (unsigned long)emul_blr_instruction);
+
+
+  /* return address for client callbacks - an emul-call instruction
+     that is again followed by a return instruction */
+
+
+  node = tree_parse(root, "/openprom/init/data@0x%lx",
+                   (unsigned long)chirp->code_callback_ra);
+  tree_parse(node, "./psim,description \"client-callback instruction");
+  tree_parse(node, "./real-address 0x%lx",
+            (unsigned long)chirp->code_callback_ra);
+  tree_parse(node, "./data 0x%lx",
+            (unsigned long)emul_call_instruction);
+
+  node = tree_parse(root, "/openprom/init/data@0x%lx",
+                   (unsigned long)(chirp->code_callback_ra + 4));
+  tree_parse(node, "./psim,description \"client-callback return instruction");
+  tree_parse(node, "./real-address 0x%lx",
+            (unsigned long)(chirp->code_callback_ra + 4));
+  tree_parse(node, "./data 0x%lx",
+            (unsigned long)emul_blr_instruction);
+
+  /* loop to keep other processors busy */
+
+  node = tree_parse(root, "/openprom/init/data@0x%lx",
+                   (unsigned long)chirp->code_loop_ra);
+  tree_parse(node, "./psim,description \"processor busy loop");
+  tree_parse(node, "./real-address 0x%lx",
+            (unsigned long)chirp->code_loop_ra);
+  tree_parse(node, "./data 0x%lx",
+            (unsigned long)emul_loop_instruction);
+
+  /* hash table */
+
+  /* create a hash table */
+
+  if (!chirp->real_mode) {
+    node = tree_parse(root, "/openprom/init/htab@0x%lx",
+                     (unsigned long)chirp->htab_ra);
+    tree_parse(node, "./claim 0");
+    tree_parse(node, "./real-address 0x%lx",
+              (unsigned long)chirp->htab_ra);
+    tree_parse(node, "./nr-bytes 0x%lx",
+              (unsigned long)chirp->sizeof_htab);
+  }
+
+  /* map in the stack */
+
+  if (!chirp->real_mode) {
+    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+                     (unsigned long)chirp->stack_ra);
+    tree_parse(node, "./psim,description \"map in the stack");
+    tree_parse(node, "./claim 1");
+    tree_parse(node, "./virtual-address 0x%lx",
+              (unsigned long)chirp->stack_va);
+    tree_parse(node, "./real-address 0x%lx",
+              (unsigned long)chirp->stack_ra);
+    tree_parse(node, "./nr-bytes 0x%lx",
+              (unsigned long)chirp->sizeof_stack);
+    tree_parse(node, "./wimg %d", 0x7);
+    tree_parse(node, "./pp %d", 0x2);
+  }
+
+  /* map in the chrp openboot callback code */
+
+  if (!chirp->real_mode) {
+    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+                     (unsigned long)chirp->code_ra);
+    tree_parse(node, "./psim,description \"map in chrp openboot callback code");
+    tree_parse(node, "./claim 1");
+    tree_parse(node, "./virtual-address 0x%lx",
+              (unsigned long)chirp->code_va);
+    tree_parse(node, "./real-address 0x%lx",
+              (unsigned long)chirp->code_ra);
+    tree_parse(node, "./nr-bytes 0x%lx",
+              (unsigned long)chirp->sizeof_code);
+    tree_parse(node, "./wimg %d", 0x7);
+    tree_parse(node, "./pp %d", 0x2);
   }
+
+  /* map in the program to run */
+
+  if (chirp->real_mode) {
+    node = tree_parse(node, "/openprom/init/load-binary");
+    tree_parse(node, "./psim,description \"load the binary");
+    tree_parse(node, "./file-name %s", bfd_get_filename(image));
+    tree_parse(node, "./claim 1");
+  }
+  else {
+    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+                     (unsigned long)chirp->load_base);
+    tree_parse(node, "./psim,description \"load & map the binary");
+    tree_parse(node, "./claim 1");
+    tree_parse(node, "./file-name \"%s", bfd_get_filename(image));
+    tree_parse(node, "./wimg %d", 0x7);
+    tree_parse(node, "./pp %d", 0x2);
+  }
+
+  return chirp;
 }
 
 static void
@@ -1152,7 +1909,6 @@ emul_chirp_init(os_emul_data *emul_data,
                int nr_cpus)
 {
   emul_data->state = serving;
-  cap_init(emul_data->phandles);
 }
 
 static int
@@ -1172,7 +1928,7 @@ emul_chirp_instruction_call(cpu *processor,
   case serving:
     /* we are waiting on an OpenBoot request from the client program
        via the client interface */
-    if (cia != emul_data->serving_instruction_ea)
+    if (cia != emul_data->code_client_va)
       return 0;
     emul_data->return_address = LR;
     emul_data->arguments = cpu_registers(processor)->gpr[3];
@@ -1181,39 +1937,51 @@ emul_chirp_instruction_call(cpu *processor,
                                       processor, cia);
     service_name = emul_read_string(service_buf, service_name_addr,
                                    sizeof(service_buf), processor, cia);
+    emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell),
+                                      processor, cia);
+    emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell),
+                                         processor, cia);
+    /* verify what was passed */
+    if (service_name_addr == 0
+       || service_name == NULL) {
+      error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
+           (unsigned long)emul_data->return_address,
+           (unsigned long)emul_data->arguments);
+    }
+    if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */
+      error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
+           (unsigned long)emul_data->return_address,
+           (unsigned long)emul_data->arguments,
+           emul_data->n_returns);
+    }
+    if (emul_data->n_returns > 6) {
+      error("OpenFirmware service %s called from 0x%lx with args 0x%lx,  with too many returns (%d)\n",
+           (unsigned long)emul_data->return_address,
+           (unsigned long)emul_data->arguments,
+           emul_data->n_args);
+    }
+    /* look it up */
     TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
                          service_name,
                          (unsigned long)emul_data->return_address,
                          (unsigned long)emul_data->arguments));
-    /* look it up */
     service = services;
     while (service->name != NULL && strcmp(service->name, service_name) != 0)
       service++;
+    /* found or not? */
     if (service->name == NULL) {
       error("OpenBoot service `%s' not found\n", service_name);
       TRACE(trace_os_emul, ("%s not found\n", service_name));
-      cpu_registers(processor)->gpr[3] = 0;
-      cpu_restart(processor, emul_data->return_address);
+      cpu_registers(processor)->gpr[3] = -1;
+    }
+    else {
+      emul_data->service = service;
+      /* call upon it */
+      result = service->handler(emul_data, processor, cia);
+      if (result != 0)
+       TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result));
+      cpu_registers(processor)->gpr[3] = result;
     }
-    emul_data->service = service;
-    /* call upon it */
-    result = service->handler(emul_data, processor, cia);
-    break;
-
-  case faulting:
-    /* We were handling a client request but encountered a page fault
-       (or other exception).  The fault needs to be passed back to the
-       client using the the client suplied call back interface */
-    error("emul_chirp_instruction_call() faulting unimplemented\n");
-    result = -1;
-    break;
-
-  case catching:
-    /* Have called the client (via the callback interface) because
-       some fault (hash table miss) occured.  The client has finished
-       handling this and is now returning */
-    error("emul_chirp_instruction_call() catching unimplemented\n");
-    result = -1;
     break;
 
   default:
index 7f5e5e1..bd585a6 100644 (file)
@@ -83,45 +83,51 @@ print_icache_declaration(insn_table *entry,
 static void
 print_icache_extraction(lf *file,
                        insn *instruction,
-                       char *field_name,
-                       char *field_type,
-                       char *field_expression,
+                       const char *entry_name,
+                       const char *entry_type,
+                       const char *entry_expression,
+                       const char *original_name,
                        const char *file_name,
                        int line_nr,
                        insn_field *cur_field,
                        insn_bits *bits,
-                       int use_defines,
-                       int get_value_from_cache,
-                       int put_value_in_cache)
+                       icache_decl_type what_to_declare,
+                       icache_body_type what_to_do)
 {
-  ASSERT(field_name != NULL);
-  if (use_defines && put_value_in_cache) {
+  ASSERT(entry_name != NULL);
+
+  /* Define a storage area for the cache element */
+  if (what_to_declare == undef_variables) {
     /* We've finished with the value - destory it */
     lf_indent_suppress(file);
-    lf_printf(file, "#undef %s\n", field_name);
+    lf_printf(file, "#undef %s\n", entry_name);
     return;
   }
-  else if (use_defines && get_value_from_cache) {
-      lf_indent_suppress(file);
-      lf_printf(file, "#define %s ", field_name);
+  else if (what_to_declare == define_variables) {
+    lf_indent_suppress(file);
+    lf_printf(file, "#define %s ", entry_name);
   }
   else {
-    lf_print__external_reference(file, line_nr, file_name);
-    lf_printf(file, "%s const %s __attribute__((__unused__)) = ",
-             field_type == NULL ? "unsigned" : field_type,
-             field_name);
+    if (file_name != NULL)
+      lf_print__external_reference(file, line_nr, file_name);
+    lf_printf(file, "%s const %s UNUSED = ",
+             entry_type == NULL ? "unsigned" : entry_type,
+             entry_name);
   }
 
+  /* define a value for that storage area as determined by what is in
+     the cache */
   if (bits != NULL
-      && ((bits->opcode->is_boolean
-          && bits->value == 0)
-         || !bits->opcode->is_boolean)
-      && strcmp(field_name, cur_field->val_string) == 0) {
+      && strcmp(entry_name, cur_field->val_string) == 0
+      && ((bits->opcode->is_boolean && bits->value == 0)
+         || (!bits->opcode->is_boolean))) {
     /* The field has been made constant (as a result of expanding
-       instructions or similar) - define a constant variable with the
-       corresponding value. */
+       instructions or similar).  Remember that for a boolean field,
+       value is either 0 (implying the required boolean_constant) or
+       nonzero (implying some other value) - Define the variable
+       accordingly */
     ASSERT(bits->field == cur_field);
-    ASSERT(field_type == NULL);
+    ASSERT(entry_type == NULL);
     if (bits->opcode->is_boolean)
       lf_printf(file, "%d", bits->opcode->boolean_constant);
     else if (bits->opcode->last < bits->field->last)
@@ -130,30 +136,48 @@ print_icache_extraction(lf *file,
     else
       lf_printf(file, "%d", bits->value);
   }
+  else if (bits != NULL
+          && bits->opcode->is_boolean
+          && original_name != NULL
+          && strncmp(entry_name,
+                     original_name, strlen(original_name)) == 0
+          && strncmp(entry_name + strlen(original_name),
+                     "_is_", strlen("_is_")) == 0
+          && (atol(entry_name + strlen(original_name) + strlen("_is_"))
+              == bits->opcode->boolean_constant)) {
+    /* An entry, derived from ORIGINAL_NAME, is testing to see of the
+       ORIGINAL_NAME has a specific constant value.  That value
+       matching a boolean bit field */
+    lf_printf(file, "%d /* %s == %d */",
+             bits->value == 0, original_name, bits->opcode->boolean_constant);
+  }
   else {
     /* put the field in the local variable, possibly also enter it
        into the cache */
-    /* getting it from the cache */
-    if (get_value_from_cache || put_value_in_cache) {
+    /* handle the cache */
+    if ((what_to_do & get_values_from_icache)
+       || (what_to_do & put_values_in_icache)) {
       lf_printf(file, "cache_entry->crack.%s.%s",
                instruction->file_entry->fields[insn_form],
-               field_name);
-      if (put_value_in_cache) /* also put it in the cache? */
+               entry_name);
+      if (what_to_do & put_values_in_icache) /* also put it in the cache? */
        lf_printf(file, " = ");
     }
-    if (!get_value_from_cache) {
-      if (strcmp(field_name, cur_field->val_string) == 0)
+    if ((what_to_do & put_values_in_icache)
+       || what_to_do == do_not_use_icache) {
+      if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
        lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
                  i2target(hi_bit_nr, cur_field->first),
                  i2target(hi_bit_nr, cur_field->last));
-      else if (field_expression != NULL)
-       lf_printf(file, "%s", field_expression);
+      else if (entry_expression != NULL)
+       lf_printf(file, "%s", entry_expression);
       else
-       lf_printf(file, "eval_%s", field_name);
+       lf_printf(file, "eval_%s", entry_name);
     }
   }
 
-  if (use_defines && get_value_from_cache)
+  if ((what_to_declare == define_variables)
+      || (what_to_declare == undef_variables))
     lf_printf(file, "\n");
   else
     lf_printf(file, ";\n");
@@ -165,16 +189,41 @@ print_icache_body(lf *file,
                  insn *instruction,
                  insn_bits *expanded_bits,
                  cache_table *cache_rules,
-                 int use_defines,
-                 int get_value_from_cache,
-                 int put_value_in_cache)
+                 icache_decl_type what_to_declare,
+                 icache_body_type what_to_do)
 {
   insn_field *cur_field;
   
   /* extract instruction fields */
-  lf_printf(file, "/* extraction: %s defines=%d get-value=%d put-value=%d */\n",
-           instruction->file_entry->fields[insn_format],
-           use_defines, get_value_from_cache, put_value_in_cache);
+  lf_printf(file, "/* extraction: %s ",
+           instruction->file_entry->fields[insn_format]);
+  switch (what_to_declare) {
+  case define_variables:
+    lf_printf(file, "#define");
+    break;
+  case declare_variables:
+    lf_printf(file, "declare");
+    break;
+  case undef_variables:
+    lf_printf(file, "#undef");
+    break;
+  }
+  lf_printf(file, " ");
+  switch (what_to_do) {
+  case get_values_from_icache:
+    lf_printf(file, "get-values-from-icache");
+    break;
+  case put_values_in_icache:
+    lf_printf(file, "put-values-in-icache");
+    break;
+  case both_values_and_icache:
+    lf_printf(file, "get-values-from-icache|put-values-in-icache");
+    break;
+  case do_not_use_icache:
+    lf_printf(file, "do-not-use-icache");
+    break;
+  }
+  lf_printf(file, " */\n");
   
   for (cur_field = instruction->fields->first;
        cur_field->first < insn_bit_size;
@@ -190,100 +239,98 @@ print_icache_body(lf *file,
          break;
       }
       /* try the cache rule table for what to do */
-      if (get_value_from_cache || put_value_in_cache) {      
+      {
        cache_table *cache_rule;
        for (cache_rule = cache_rules;
             cache_rule != NULL;
             cache_rule = cache_rule->next) {
-         if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
+         if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
            found_rule = 1;
-           if (cache_rule->type == compute_value
-               && put_value_in_cache
-               && !use_defines)
+           if (cache_rule->type == scratch_value
+               && ((what_to_do & put_values_in_icache)
+                   || what_to_do == do_not_use_icache))
+             print_icache_extraction(file,
+                                     instruction,
+                                     cache_rule->derived_name,
+                                     cache_rule->type_def,
+                                     cache_rule->expression,
+                                     cache_rule->field_name,
+                                     cache_rule->file_entry->file_name,
+                                     cache_rule->file_entry->line_nr,
+                                     cur_field,
+                                     bits,
+                                     what_to_declare,
+                                     do_not_use_icache);
+           else if (cache_rule->type == compute_value
+                    && ((what_to_do & get_values_from_icache)
+                        || what_to_do == do_not_use_icache))
              print_icache_extraction(file,
                                      instruction,
-                                     cache_rule->new_name,
+                                     cache_rule->derived_name,
                                      cache_rule->type_def,
                                      cache_rule->expression,
+                                     cache_rule->field_name,
                                      cache_rule->file_entry->file_name,
                                      cache_rule->file_entry->line_nr,
                                      cur_field,
                                      bits,
-                                     0 /*use_defines*/,
-                                     0 /*get-value-from-cache*/,
-                                     0 /*put-value-in-cache*/);
-           else if (cache_rule->type == cache_value)
+                                     what_to_declare,
+                                     do_not_use_icache);
+           else if (cache_rule->type == cache_value
+                    && ((what_to_declare != undef_variables)
+                        || !(what_to_do & put_values_in_icache)))
              print_icache_extraction(file,
                                      instruction,
-                                     cache_rule->new_name,
+                                     cache_rule->derived_name,
                                      cache_rule->type_def,
                                      cache_rule->expression,
+                                     cache_rule->field_name,
                                      cache_rule->file_entry->file_name,
                                      cache_rule->file_entry->line_nr,
                                      cur_field,
                                      bits,
-                                     use_defines,
-                                     get_value_from_cache,
-                                     put_value_in_cache);
+                                     ((what_to_do & put_values_in_icache)
+                                      ? declare_variables
+                                      : what_to_declare),
+                                     what_to_do);
          }
        }
       }
-      if (found_rule == 0)
+      /* No rule at all, assume that it should go into the cache */
+      if (found_rule == 0
+         && ((what_to_declare != undef_variables)
+             || !(what_to_do & put_values_in_icache)))
        print_icache_extraction(file,
                                instruction,
                                cur_field->val_string,
-                               0,
-                               0,
+                               NULL, NULL, NULL, /* type, exp, orig */
                                instruction->file_entry->file_name,
                                instruction->file_entry->line_nr,
                                cur_field,
                                bits,
-                               use_defines,
-                               get_value_from_cache,
-                               put_value_in_cache);
-      /* if any (XXX == 0), output a corresponding test */
-      if (instruction->file_entry->annex != NULL) {
-       char *field_name = cur_field->val_string;
-       char *is_0_ptr = instruction->file_entry->annex;
-       int field_len = strlen(field_name);
-       if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
-         is_0_ptr += field_len;
-         while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
-           if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
-               && !isalpha(is_0_ptr[ - field_len - 1])) {
-             if (!use_defines || (use_defines && get_value_from_cache)) {
-               if (use_defines) {
-                 lf_indent_suppress(file);
-                 lf_printf(file, "#define %s_is_0 ", field_name);
-               }
-               else {
-                 table_entry_print_cpp_line_nr(file, instruction->file_entry);
-                 lf_printf(file, "const unsigned %s_is_0 __attribute__((__unused__)) = ",
-                           field_name);
-               }
-               if (bits != NULL)
-                 lf_printf(file, "(%d == 0)", bits->value);
-               else
-                 lf_printf(file, "(%s == 0)", field_name);
-               if (use_defines)
-                 lf_printf(file, "\n");
-               else
-                 lf_printf(file, ";\n");
-             }
-             else if (use_defines && put_value_in_cache) {
-               lf_indent_suppress(file);
-               lf_printf(file, "#undef %s_is_0\n", field_name);
-             }
-             break;
-           }
-           is_0_ptr += strlen("_is_0");
-         }
-       }
-      }
+                               ((what_to_do & put_values_in_icache)
+                                ? declare_variables
+                                : what_to_declare),
+                               what_to_do);
       /* any thing else ... */
     }
   }
+
   lf_print__internal_reference(file);
+
+  if ((code & generate_with_insn_in_icache)) {
+    lf_printf(file, "\n");
+    print_icache_extraction(file,
+                           instruction,
+                           "insn",
+                           "instruction_word",
+                           "instruction",
+                           NULL, /* origin */
+                           NULL, 0, /* file_name & line_nr */
+                           NULL, NULL,
+                           what_to_declare,
+                           what_to_do);
+  }
 }
 
 
@@ -356,6 +403,7 @@ print_icache_struct(insn_table *instructions,
 {
   icache_tree *tree = insn_table_cache_fields(instructions);
   
+  lf_printf(file, "\n");
   lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
            (code & generate_with_icache) ? icache_size : 0);
   lf_printf(file, "\n");
@@ -372,6 +420,8 @@ print_icache_struct(insn_table *instructions,
         form = form->next) {
       icache_tree *field;
       lf_printf(file, "    struct {\n");
+      if (code & generate_with_insn_in_icache)
+       lf_printf(file, "      instruction_word insn;\n");
       for (field = form->children;
           field != NULL;
           field = field->next) {
@@ -380,15 +430,15 @@ print_icache_struct(insn_table *instructions,
        for (cache_rule = cache_rules;
             cache_rule != NULL;
             cache_rule = cache_rule->next) {
-         if (strcmp(field->name, cache_rule->old_name) == 0) {
+         if (strcmp(field->name, cache_rule->field_name) == 0) {
            found_rule = 1;
-           if (cache_rule->new_name != NULL)
+           if (cache_rule->derived_name != NULL)
              lf_printf(file, "      %s %s; /* %s */\n",
                        (cache_rule->type_def == NULL
                         ? "unsigned" 
                         : cache_rule->type_def),
-                       cache_rule->new_name,
-                       cache_rule->old_name);
+                       cache_rule->derived_name,
+                       cache_rule->field_name);
          }
        }
        if (!found_rule)
@@ -400,23 +450,11 @@ print_icache_struct(insn_table *instructions,
     lf_printf(file, "} idecode_cache;\n");
   }
   else {
-    /* alernativly, since no cache, #define the fields to be
-       extractions from the instruction variable.  Emit a dummy
-       definition for idecode_cache to allow model_issue to not
-       be #ifdefed at the call level */
-    cache_table *cache_rule;
-    lf_printf(file, "\n");
+    /* alernativly, since no cache, emit a dummy definition for
+       idecode_cache so that code refering to the type can still compile */
     lf_printf(file, "typedef void idecode_cache;\n");
-    lf_printf(file, "\n");
-    for (cache_rule = cache_rules;
-        cache_rule != NULL;
-        cache_rule = cache_rule->next) {
-      if (cache_rule->expression != NULL
-         && strlen(cache_rule->expression) > 0)
-       lf_printf(file, "#define %s %s\n",
-                 cache_rule->new_name, cache_rule->expression);
-    }
   }
+  lf_printf(file, "\n");
 }
 
 
@@ -445,7 +483,7 @@ print_icache_function(lf *file,
   lf_printf(file, "{\n");
   lf_indent(file, +2);
   
-  print_define_my_index(file, instruction->file_entry);
+  print_my_defines(file, expanded_bits, instruction->file_entry);
   print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
   
   print_idecode_validate(file, instruction, opcodes);
@@ -453,47 +491,60 @@ print_icache_function(lf *file,
   lf_printf(file, "\n");
   lf_printf(file, "{\n");
   lf_indent(file, +2);
+  if ((code & generate_with_semantic_icache))
+    lf_printf(file, "unsigned_word nia;\n");
   print_icache_body(file,
                    instruction,
                    expanded_bits,
                    cache_rules,
-                   0/*use_defines*/,
-                   0/*get_value_from_cache*/,
-                   1/*put_value_in_cache*/);
+                   ((code & generate_with_direct_access)
+                    ? define_variables
+                    : declare_variables),
+                   ((code & generate_with_semantic_icache)
+                    ? both_values_and_icache
+                    : put_values_in_icache));
   
+  lf_printf(file, "\n");
+  lf_printf(file, "cache_entry->address = cia;\n");
+  lf_printf(file, "cache_entry->semantic = ");
+  print_function_name(file,
+                     instruction->file_entry->fields[insn_name],
+                     expanded_bits,
+                     function_name_prefix_semantics);
+  lf_printf(file, ";\n");
+  lf_printf(file, "\n");
+
   if ((code & generate_with_semantic_icache)) {
-    lf_printf(file, "unsigned_word nia;\n");
-    lf_printf(file, "cache_entry->address = cia;\n");
-    lf_printf(file, "cache_entry->semantic = ");
-    print_function_name(file,
-                       instruction->file_entry->fields[insn_name],
-                       expanded_bits,
-                       function_name_prefix_semantics);
-    lf_printf(file, ";\n");
+    lf_printf(file, "/* semantic routine */\n");
     print_semantic_body(file,
                        instruction,
                        expanded_bits,
                        opcodes);
-    lf_printf(file, "\n");
     lf_printf(file, "return nia;\n");
   }
-  lf_indent(file, -2);
-  lf_printf(file, "}\n");
   
   if (!(code & generate_with_semantic_icache)) {
-    /* return the function propper (main sorts this one out) */
-    lf_printf(file, "\n");
-    lf_printf(file, "/* semantic routine */\n");
-    table_entry_print_cpp_line_nr(file, instruction->file_entry);
+    lf_printf(file, "/* return the function proper */\n");
     lf_printf(file, "return ");
     print_function_name(file,
                        instruction->file_entry->fields[insn_name],
                        expanded_bits,
                        function_name_prefix_semantics);
     lf_printf(file, ";\n");
-    lf_print__internal_reference(file);
   }
   
+  if ((code & generate_with_direct_access))
+    print_icache_body(file,
+                     instruction,
+                     expanded_bits,
+                     cache_rules,
+                     undef_variables,
+                     ((code & generate_with_semantic_icache)
+                      ? both_values_and_icache
+                      : put_values_in_icache));
+
+  lf_indent(file, -2);
+  lf_printf(file, "}\n");
   lf_indent(file, -2);
   lf_printf(file, "}\n");
 }
index 1c4c6bf..d5a805c 100644 (file)
@@ -42,6 +42,7 @@ lf_print_opcodes(lf *file,
 {
   if (table != NULL) {
     while (1) {
+      ASSERT(table->opcode != NULL);
       lf_printf(file, "_%d_%d",
                table->opcode->first,
                table->opcode->last);
@@ -70,9 +71,10 @@ print_idecode_table(lf *file,
                    insn_table *entry,
                    const char *result)
 {
-  /* int can_assume_leaf; */
+#if 0
+  /* FIXME: I don't think the second part of this is correct! */
+  int can_assume_leaf;
   decode_table *opcode_rule;
-
   /* have a look at the rule table, if all table rules follow all
      switch rules, I can assume that all end points are leaves */
   opcode_rule = entry->opcode_rule;
@@ -80,9 +82,6 @@ print_idecode_table(lf *file,
         && (opcode_rule->gen == switch_gen
             || opcode_rule->gen == padded_switch_gen))
     opcode_rule = opcode_rule->next;
-
-#if 0
-  /* FIXME: I don't get this bit! */
   while (opcode_rule != NULL
         && (opcode_rule->gen == switch_gen
             || opcode_rule->gen == padded_switch_gen)
@@ -189,6 +188,7 @@ print_idecode_table_leaf(insn_table *entry,
       lf_printf(file, " },\n");
     }
     else if (entry->opcode_rule->gen == switch_gen
+            || entry->opcode_rule->gen == goto_switch_gen
             || entry->opcode_rule->gen == padded_switch_gen) {
       /* table calling switch statement */
       lf_printf(file, "  /*%d*/ { table_function_entry, 0, 0, 0, ",
@@ -250,12 +250,89 @@ print_idecode_table_padding(insn_table *table,
 /****************************************************************/
 
 
+static void
+print_goto_switch_name(lf *file,
+                      insn_table *entry)
+{
+  lf_printf(file, "case_");
+  if (entry->opcode == NULL)
+    print_function_name(file,
+                       entry->insns->file_entry->fields[insn_name],
+                       entry->expanded_bits,
+                       ((code & generate_with_icache)
+                        ? function_name_prefix_icache
+                        : function_name_prefix_semantics));
+  else
+    lf_print_table_name(file, entry);
+}
+
+static void
+print_goto_switch_table_leaf(insn_table *entry,
+                            lf *file,
+                            void *data,
+                            insn *instruction,
+                            int depth)
+{
+  ASSERT(entry->parent != NULL);
+  ASSERT(depth == 0);
+  ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
+  ASSERT(entry->parent->opcode);
+
+  lf_printf(file, "&&");
+  print_goto_switch_name(file, entry);
+  lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_table_padding(insn_table *table,
+                               lf *file,
+                               void *data,
+                               int depth,
+                               int opcode_nr)
+{
+  ASSERT(depth == 0);
+  ASSERT(table->opcode_rule->gen == goto_switch_gen);
+
+  lf_printf(file, "&&illegal_");
+  lf_print_table_name(file, table);
+  lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_break(lf *file,
+                       insn_table *entry)
+{
+  lf_printf(file, "goto break_");
+  lf_print_table_name(file, entry->parent);
+  lf_printf(file, ";\n");
+}
+
+
+static void
+print_goto_switch_table(lf *file,
+                       insn_table *table)
+{
+  lf_printf(file, "const static void *");
+  lf_print_table_name(file, table);
+  lf_printf(file, "[] = {\n");
+  lf_indent(file, +2);
+  insn_table_traverse_tree(table,
+                          file, NULL/*data*/,
+                          0,
+                          NULL/*start*/,
+                          print_goto_switch_table_leaf,
+                          NULL/*end*/,
+                          print_goto_switch_table_padding);
+  lf_indent(file, -2);
+  lf_printf(file, "};\n");
+}
+
+
 void print_idecode_switch
 (lf *file, 
  insn_table *table,
  const char *result);
 
-
 static void
 idecode_switch_start(insn_table *table,
                     lf *file,
@@ -265,15 +342,39 @@ idecode_switch_start(insn_table *table,
   /* const char *result = data; */
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
-        || table->opcode_rule->gen == padded_switch_gen
-        || table->opcode_rule->gen == goto_gen);
+        || table->opcode_rule->gen == goto_switch_gen
+        || table->opcode_rule->gen == padded_switch_gen);
 
-  switch (table->opcode_rule->gen) {
-  default:
+  if (table->opcode->is_boolean
+      || table->opcode_rule->gen == switch_gen
+        || table->opcode_rule->gen == padded_switch_gen) {
     lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
              i2target(hi_bit_nr, table->opcode->first),
              i2target(hi_bit_nr, table->opcode->last));
-    break;
+  }
+  else if (table->opcode_rule->gen == goto_switch_gen) {
+    if (table->parent != NULL
+       && (table->parent->opcode_rule->gen == switch_gen
+           || table->parent->opcode_rule->gen == goto_switch_gen
+           || table->parent->opcode_rule->gen == padded_switch_gen)) {
+      lf_printf(file, "{\n");
+      lf_indent(file, +2);
+    }
+    print_goto_switch_table(file, table);
+    lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
+             i2target(hi_bit_nr, table->opcode->first),
+             i2target(hi_bit_nr, table->opcode->last));
+    lf_printf(file, "       < (sizeof(");
+    lf_print_table_name(file, table);
+    lf_printf(file, ") / sizeof(void*)));\n");
+    lf_printf(file, "goto *");
+    lf_print_table_name(file, table);
+    lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
+             i2target(hi_bit_nr, table->opcode->first),
+             i2target(hi_bit_nr, table->opcode->last));
+  }
+  else {
+    ASSERT("bad switch" == NULL);
   }
 }
 
@@ -289,16 +390,34 @@ idecode_switch_leaf(insn_table *entry,
   ASSERT(entry->parent != NULL);
   ASSERT(depth == 0);
   ASSERT(entry->parent->opcode_rule->gen == switch_gen
+        || entry->parent->opcode_rule->gen == goto_switch_gen
         || entry->parent->opcode_rule->gen == padded_switch_gen);
   ASSERT(entry->parent->opcode);
 
   if (entry->parent->opcode->is_boolean
-      && entry->opcode_nr == 0)
+      && entry->opcode_nr == 0) {
+    /* boolean false target */
     lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
-  else if (!entry->parent->opcode->is_boolean)
-    lf_printf(file, "case %d:\n", entry->opcode_nr);
-  else
+  }
+  else if (entry->parent->opcode->is_boolean
+          && entry->opcode_nr != 0) {
+    /* boolean true case */
     lf_printf(file, "default:\n");
+  }
+  else if (entry->parent->opcode_rule->gen == switch_gen
+          || entry->parent->opcode_rule->gen == padded_switch_gen) {
+    /* normal goto */
+    lf_printf(file, "case %d:\n", entry->opcode_nr);
+  }
+  else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+    /* lf_indent(file, -1); */
+    print_goto_switch_name(file, entry);
+    lf_printf(file, ":\n");
+    /* lf_indent(file, +1); */
+  }
+  else {
+    ASSERT("bad switch" == NULL);
+  }
   lf_indent(file, +2);
   {
     if (entry->opcode == NULL) {
@@ -318,6 +437,7 @@ idecode_switch_leaf(insn_table *entry,
       lf_printf(file, ";\n");
     }
     else if (entry->opcode_rule->gen == switch_gen
+            || entry->opcode_rule->gen == goto_switch_gen
             || entry->opcode_rule->gen == padded_switch_gen) {
       /* switch calling switch */
       print_idecode_switch(file, entry, result);
@@ -330,7 +450,17 @@ idecode_switch_leaf(insn_table *entry,
       lf_indent(file, -2);
       lf_printf(file, "}\n");
     }
-    lf_printf(file, "break;\n");
+    if (entry->parent->opcode->is_boolean
+       || entry->parent->opcode_rule->gen == switch_gen
+       || entry->parent->opcode_rule->gen == padded_switch_gen) {
+      lf_printf(file, "break;\n");
+    }
+    else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+      print_goto_switch_break(file, entry);
+    }
+    else {
+      ASSERT("bad switch" == NULL);
+    }
   }
   lf_indent(file, -2);
 }
@@ -342,7 +472,7 @@ print_idecode_switch_illegal(lf *file,
 {
   lf_indent(file, +2);
   print_idecode_illegal(file, result);
-  /*lf_printf(file, "break;\n");*/
+  lf_printf(file, "break;\n");
   lf_indent(file, -2);
 }
 
@@ -355,11 +485,15 @@ idecode_switch_end(insn_table *table,
   const char *result = data;
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
-        || table->opcode_rule->gen == padded_switch_gen
-        || table->opcode_rule->gen == goto_gen);
+        || table->opcode_rule->gen == goto_switch_gen
+        || table->opcode_rule->gen == padded_switch_gen);
   ASSERT(table->opcode);
 
-  if (!table->opcode->is_boolean) {
+  if (table->opcode->is_boolean) {
+    lf_printf(file, "}\n");
+  }
+  else if (table->opcode_rule->gen == switch_gen
+          || table->opcode_rule->gen == padded_switch_gen) {
     lf_printf(file, "default:\n");
     switch (table->opcode_rule->gen) {
     case switch_gen:
@@ -370,10 +504,29 @@ idecode_switch_end(insn_table *table,
       lf_printf(file, "  break;\n");
       break;
     default:
-      error("idecode_switch_end - unknown switch type\n");
+      ASSERT("bad switch" == NULL);
     }
+    lf_printf(file, "}\n");
+  }
+  else if (table->opcode_rule->gen == goto_switch_gen) {
+    lf_printf(file, "illegal_");
+    lf_print_table_name(file, table);
+    lf_printf(file, ":\n");
+    print_idecode_illegal(file, result);
+    lf_printf(file, "break_");
+    lf_print_table_name(file, table);
+    lf_printf(file, ":;\n");
+    if (table->parent != NULL
+       && (table->parent->opcode_rule->gen == switch_gen
+           || table->parent->opcode_rule->gen == goto_switch_gen
+           || table->parent->opcode_rule->gen == padded_switch_gen)) {
+      lf_indent(file, -2);
+      lf_printf(file, "}\n");
+    }
+  }
+  else {
+    ASSERT("bad switch" == NULL);
   }
-  lf_printf(file, "}\n");
 }
 
 static void
@@ -386,15 +539,21 @@ idecode_switch_padding(insn_table *table,
   const char *result = data;
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->gen == switch_gen
+        || table->opcode_rule->gen == goto_switch_gen
         || table->opcode_rule->gen == padded_switch_gen);
 
-  if (table->opcode_rule->gen == padded_switch_gen) {
+  switch (table->opcode_rule->gen) {
+  case switch_gen:
+    break;
+  case padded_switch_gen:
     lf_printf(file, "case %d:\n", opcode_nr);
     print_idecode_switch_illegal(file, result);
-  }
-  else if (table->opcode_rule->gen == goto_gen) {
-    lf_printf(file, "goto_%d:\n", opcode_nr);
-    print_idecode_switch_illegal(file, result);
+    break;
+  case goto_switch_gen:
+    /* no padding needed */
+    break;
+  default:
+    ASSERT("bad switch" != NULL);
   }
 }
 
@@ -452,12 +611,13 @@ idecode_declare_if_switch(insn_table *table,
                          int depth)
 {
   if ((table->opcode_rule->gen == switch_gen
+       || table->opcode_rule->gen == goto_switch_gen
        || table->opcode_rule->gen == padded_switch_gen)
       && table->parent != NULL /* don't declare the top one yet */
       && table->parent->opcode_rule->gen == array_gen) {
     print_idecode_switch_function_header(file,
-                                           table,
-                                           0/*isnt function definition*/);
+                                        table,
+                                        0/*isnt function definition*/);
   }
 }
 
@@ -469,6 +629,7 @@ idecode_expand_if_switch(insn_table *table,
                         int depth)
 {
   if ((table->opcode_rule->gen == switch_gen
+       || table->opcode_rule->gen == goto_switch_gen
        || table->opcode_rule->gen == padded_switch_gen)
       && table->parent != NULL /* don't expand the top one yet */
       && table->parent->opcode_rule->gen == array_gen) {
@@ -537,6 +698,7 @@ print_idecode_body(lf *file,
   lf_putstr(file, "{\n");
   lf_indent(file, +2);
   if (table->opcode_rule->gen == switch_gen
+      || table->opcode_rule->gen == goto_switch_gen
       || table->opcode_rule->gen == padded_switch_gen)
     print_idecode_switch(file, table, result);
   else
@@ -565,8 +727,6 @@ print_run_until_stop_body(lf *file,
 
   lf_putstr(file, "{\n");
   lf_indent(file, +2);
-  if (!can_stop)
-    lf_putstr(file, "int *keep_running = NULL;\n");
   lf_putstr(file, "jmp_buf halt;\n");
   lf_putstr(file, "jmp_buf restart;\n");
   lf_putstr(file, "cpu *processor = NULL;\n");
@@ -630,6 +790,11 @@ print_run_until_stop_body(lf *file,
     if (!(code & generate_with_icache)) {
       lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
       print_idecode_body(file, table, "cia =", "");
+      /* tail */
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
     }
 
     if ((code & generate_with_icache)) {
@@ -638,6 +803,12 @@ print_run_until_stop_body(lf *file,
       lf_putstr(file, "  /* cache hit */\n");
       lf_putstr(file, "  idecode_semantic *const semantic = cache_entry->semantic;\n");
       lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
+      /* tail */
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
+      lf_putstr(file, "  continue;\n");
       lf_putstr(file, "}\n");
       lf_putstr(file, "else {\n");
       lf_putstr(file, "  /* cache miss */\n");
@@ -656,11 +827,15 @@ print_run_until_stop_body(lf *file,
        print_idecode_body(file, table, "semantic =", "  ");
        lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
       }
+      /* tail */
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
+      lf_putstr(file, "  continue;\n");
       lf_putstr(file, "}\n");
     }
 
-    lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
-    lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
     lf_indent(file, -2);
     lf_putstr(file, "}\n");
   }
@@ -698,41 +873,63 @@ print_run_until_stop_body(lf *file,
     if (!(code & generate_with_icache)) {
       lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
       print_idecode_body(file, table, "cia =", "");
+      if (can_stop) {
+       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+      }
+      lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+      lf_putstr(file, "continue;\n");
     }
 
     if ((code & generate_with_icache)) {
       lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
       lf_putstr(file, "if (cache_entry->address == cia) {\n");
-      lf_putstr(file, "  /* cache hit */\n");
-      lf_putstr(file, "  idecode_semantic *semantic = cache_entry->semantic;\n");
-      lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
-      lf_putstr(file, "}\n");
-      lf_putstr(file, "else {\n");
-      lf_putstr(file, "  /* cache miss */\n");
-      if (!(code & generate_with_semantic_icache)) {
+      {
        lf_indent(file, +2);
-       lf_putstr(file, "  idecode_semantic *semantic;\n");
+       lf_putstr(file, "/* cache hit */\n");
+       lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
+       lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+       /* tail */
+       if (can_stop) {
+         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+       }
+       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+       lf_putstr(file, "continue;\n");
        lf_indent(file, -2);
       }
-      lf_putstr(file, "  instruction =\n");
-      lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
-      lf_putstr(file, "  if (WITH_MON != 0)\n");
-      lf_putstr(file, "    mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
-      if ((code & generate_with_semantic_icache)) {
-       print_idecode_body(file, table, "cia =", "  ");
-      }
-      else {
-       print_idecode_body(file, table, "semantic = ", "  ");
+      lf_putstr(file, "}\n");
+      lf_putstr(file, "else {\n");
+      {
        lf_indent(file, +2);
-       lf_putstr(file, "cia = semantic(processor, cache_entry, cia));\n");
+       lf_putstr(file, "/* cache miss */\n");
+       if (!(code & generate_with_semantic_icache)) {
+         lf_putstr(file, "idecode_semantic *semantic;\n");
+       }
+       lf_putstr(file, "instruction =\n");
+       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+       lf_putstr(file, "if (WITH_MON != 0)\n");
+       lf_putstr(file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
+       if ((code & generate_with_semantic_icache)) {
+         print_idecode_body(file, table, "cia =", "");
+       }
+       else {
+         print_idecode_body(file, table, "semantic = ", "  ");
+         lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+       }
+       /* tail */
+       if (can_stop) {
+         lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+         lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+       }
+       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+       lf_putstr(file, "continue;\n");
        lf_indent(file, -2);
       }
       lf_putstr(file, "}\n");
     }
 
-    lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
-    lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
-    lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+    /* tail */
     lf_indent(file, -2);
     lf_putstr(file, "}\n");
   }
@@ -765,10 +962,11 @@ print_jump(lf *file,
   }
 
   if (generate_smp) {
-    lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
+    if (is_tail)
+      lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
     lf_putstr(file, "if (WITH_EVENTS) {\n");
     lf_putstr(file, "  current_cpu += 1;\n");
-    lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
+    lf_putstr(file, "  if (current_cpu >= nr_cpus) {\n");
     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
     lf_putstr(file, "      event_queue_process(events);\n");
     lf_putstr(file, "    }\n");
@@ -793,7 +991,7 @@ print_jump(lf *file,
     }
   }
 
-  if (!(code & generate_with_icache)) {
+  if (!(code & generate_with_icache) && is_tail) {
     lf_printf(file, "goto idecode;\n");
   }
 
@@ -813,7 +1011,7 @@ print_jump_insn(lf *file,
 
   /* what we are for the moment */
   lf_printf(file, "\n");
-  print_define_my_index(file, instruction->file_entry);
+  print_my_defines(file, expanded_bits, instruction->file_entry);
 
   /* output the icache entry */
   if ((code & generate_with_icache)) {
@@ -837,9 +1035,8 @@ print_jump_insn(lf *file,
                      instruction,
                      expanded_bits,
                      cache_rules,
-                     0,
-                     0/*get_value_from_cache*/,
-                     1/*put_value_in_cache*/);
+                     0, /*use_defines*/
+                     put_values_in_icache);
     lf_printf(file, "cache_entry->address = nia;\n");
     lf_printf(file, "cache_entry->semantic = &&");
     print_function_name(file,
@@ -884,13 +1081,25 @@ print_jump_insn(lf *file,
                    instruction,
                    expanded_bits,
                    cache_rules,
-                   (code & generate_with_direct_access_icache),
-                   (code & generate_with_icache)/*get_value_from_cache*/,
-                   0/*put_value_in_cache*/);
+                   ((code & generate_with_direct_access)
+                    ? define_variables
+                    : declare_variables),
+                   ((code & generate_with_icache)
+                    ? get_values_from_icache
+                    : do_not_use_icache));
   print_semantic_body(file,
                      instruction,
                      expanded_bits,
                      opcodes);
+  if (code & generate_with_direct_access)
+    print_icache_body(file,
+                     instruction,
+                     expanded_bits,
+                     cache_rules,
+                     undef_variables,
+                     ((code & generate_with_icache)
+                      ? get_values_from_icache
+                      : do_not_use_icache));
   print_jump(file, 1/*is tail*/);
   lf_indent(file, -2);
   lf_printf(file, "}\n");
index 471c97b..4b9ae36 100644 (file)
@@ -48,7 +48,7 @@ int insn_bit_size = max_insn_bit_size;
 igen_code code = generate_calls;
 
 int generate_expanded_instructions;
-int icache_size;
+int icache_size = 1024;
 int generate_smp;
 
 /****************************************************************/
@@ -127,9 +127,11 @@ print_function_name(lf *file,
 
 
 void
-print_define_my_index(lf *file,
-                     table_entry *file_entry)
+print_my_defines(lf *file,
+                insn_bits *expanded_bits,
+                table_entry *file_entry)
 {
+  /* #define MY_INDEX xxxxx */
   lf_indent_suppress(file);
   lf_printf(file, "#undef MY_INDEX\n");
   lf_indent_suppress(file);
@@ -139,6 +141,16 @@ print_define_my_index(lf *file,
                       NULL,
                       function_name_prefix_itable);
   lf_printf(file, "\n");
+  /* #define MY_PREFIX xxxxxx */
+  lf_indent_suppress(file);
+  lf_printf(file, "#undef MY_PREFIX\n");
+  lf_indent_suppress(file);
+  lf_printf(file, "#define MY_PREFIX ");
+  print_function_name(file,
+                     file_entry->fields[insn_name],
+                     expanded_bits,
+                     function_name_prefix_none);
+  lf_printf(file, "\n");
 }
 
 
@@ -321,9 +333,10 @@ main(int argc,
     printf("  igen <config-opts> ... <input-opts>... <output-opts>...\n");
     printf("Config options:\n");
     printf("  -F <filter-out-flag>  eg -F 64 to skip 64bit instructions\n");
-    printf("  -C                    Include semantics in cache functions\n");
     printf("  -E                    Expand (duplicate) semantic functions\n");
     printf("  -I <icache-size>      Generate cracking cache version\n");
+    printf("  -C                    Include semantics in cache functions\n");
+    printf("  -S                    Include insn (instruction) in icache\n");
     printf("  -R                    Use defines to reference cache vars\n");
     printf("  -L                    Supress line numbering in output files\n");
     printf("  -B <bit-size>         Set the number of bits in an instruction\n");
@@ -348,15 +361,17 @@ main(int argc,
   }
 
   while ((ch = getopt(argc, argv,
-                     "F:EI:RLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
+                     "F:EI:RSLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
         != -1) {
     fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
     switch(ch) {
     case 'C':
       code |= generate_with_icache;
       code |= generate_with_semantic_icache;
-      if (icache_size == 0)
-       icache_size = 1024;
+      break;
+    case 'S':
+      code |= generate_with_icache;
+      code |= generate_with_insn_in_icache;
       break;
     case 'L':
       file_references = lf_omit_references;
@@ -372,10 +387,7 @@ main(int argc,
       generate_smp = a2i(optarg);
       break;
     case 'R':
-      code |= generate_with_icache;
-      code |= generate_with_direct_access_icache;
-      if (icache_size == 0)
-       icache_size = 1024;
+      code |= generate_with_direct_access;
       break;
     case 'B':
       insn_bit_size = a2i(optarg);
index 99201db..454efed 100644 (file)
@@ -43,6 +43,8 @@
 #endif
 #endif
 
+#include <errno.h>
+
 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
 #undef WITH_STDIO
 #define WITH_STDIO DO_USE_STDIO
@@ -69,6 +71,7 @@ error (char *msg, ...)
   va_list ap;
   va_start(ap, msg);
   vprintf(msg, ap);
+  printf("\n");
   va_end(ap);
 
   /* any final clean up */
@@ -98,6 +101,7 @@ sim_io_write_stdout(const char *buf,
   default:
     error("sim_io_write_stdout: invalid switch\n");
   }
+  return 0;
 }
 
 int
@@ -120,6 +124,7 @@ sim_io_write_stderr(const char *buf,
   default:
     error("sim_io_write_stdout: invalid switch\n");
   }
+  return 0;
 }
 
 int
@@ -128,10 +133,20 @@ sim_io_read_stdin(char *buf,
 {
   switch (CURRENT_STDIO) {
   case DO_USE_STDIO:
-    if (fgets(buf, sizeof_buf, stdin) == NULL)
-      return sim_io_eof;
-    else
-      return strlen(buf);
+    if (sizeof_buf > 1) {
+      if (fgets(buf, sizeof_buf, stdin) != NULL)
+       return strlen(buf);
+    }
+    else if (sizeof_buf == 1) {
+      char b[2];
+      if (fgets(b, sizeof(b), stdin) != NULL) {
+       memcpy(buf, b, strlen(b));
+       return strlen(b);
+      }
+    }
+    else if (sizeof_buf == 0)
+      return 0;
+    return sim_io_eof;
     break;
   case DONT_USE_STDIO:
     {
@@ -139,6 +154,7 @@ sim_io_read_stdin(char *buf,
       int flags;
       int status;
       int nr_read;
+      int result;
       /* get the old status */
       flags = fcntl(0, F_GETFL, 0);
       if (flags == -1) {
@@ -152,25 +168,32 @@ sim_io_read_stdin(char *buf,
        return sim_io_eof;
       }
       /* try for input */
-      nr_read = read(0, &buf, sizeof_buf);
+      nr_read = read(0, buf, sizeof_buf);
+      if (nr_read > 0
+         || (nr_read == 0 && sizeof_buf == 0))
+       result = nr_read;
+      else if (nr_read == 0)
+       result = sim_io_eof;
+      else { /* nr_read < 0 */
+       if (errno == EAGAIN)
+         result = sim_io_not_ready;
+       else 
+         result = sim_io_eof;
+      }
       /* return to regular vewing */
       status = fcntl(0, F_SETFL, flags);
       if (status == -1) {
        perror("sim_io_read_stdin");
        return sim_io_eof;
       }
-      if (status > 0)
-       return 1;
-      else if (status < 0)
-       return sim_io_eof;
-      else
-       return sim_io_not_ready;
+      return result;
     }
     break;
   default:
     error("sim_io_read_stdin: invalid switch\n");
     break;
   }
+  return 0;
 }
 
 void
@@ -215,8 +238,14 @@ main(int argc, char **argv)
 
   /* parse the arguments */
   argv = psim_options(root, argv + 1);
-  if (argv[0] == NULL)
-    psim_usage(0);
+  if (argv[0] == NULL) {
+    if (ppc_trace[trace_opts]) {
+      print_options ();
+      return 0;
+    } else {
+      psim_usage(0);
+    }
+  }
   name_of_file = argv[0];
 
   if (ppc_trace[trace_opts])
index 270fb4a..2b5f472 100644 (file)
@@ -20,6 +20,7 @@
 cache:RA:RA::
 cache:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA)
 cache:RA:RA_BITMASK:unsigned32:(1 << RA)
+compute:RA:RA_is_0:int:(RA == 0)
 cache:RT:RT::
 cache:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT)
 cache:RT:RT_BITMASK:unsigned32:(1 << RT)
@@ -29,30 +30,30 @@ cache:RS:RS_BITMASK:unsigned32:(1 << RS)
 cache:RB:RB::
 cache:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB)
 cache:RB:RB_BITMASK:unsigned32:(1 << RB)
-compute:FRA:FRA::
+scratch:FRA:FRA::
 cache:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA)
 cache:FRA:FRA_BITMASK:unsigned32:(1 << FRA)
-compute:FRB:FRB::
+scratch:FRB:FRB::
 cache:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB)
 cache:FRB:FRB_BITMASK:unsigned32:(1 << FRB)
-compute:FRC:FRC::
+scratch:FRC:FRC::
 cache:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC)
 cache:FRC:FRC_BITMASK:unsigned32:(1 << FRC)
-compute:FRS:FRS::
+scratch:FRS:FRS::
 cache:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS)
 cache:FRS:FRS_BITMASK:unsigned32:(1 << FRS)
-compute:FRT:FRT::
+scratch:FRT:FRT::
 cache:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT)
 cache:FRT:FRT_BITMASK:unsigned32:(1 << FRT)
 cache:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction)
-compute:BI:BI::
+scratch:BI:BI::
 cache:BI:BIT32_BI::BIT32(BI)
 cache:BF:BF::
 cache:BF:BF_BITMASK:unsigned32:(1 << BF)
-compute:BA:BA::
+scratch:BA:BA::
 cache:BA:BIT32_BA::BIT32(BA)
 cache:BA:BA_BITMASK:unsigned32:(1 << BA)
-compute:BB:BB::
+scratch:BB:BB::
 cache:BB:BIT32_BB::BIT32(BB)
 cache:BB:BB_BITMASK:unsigned32:(1 << BB)
 cache:BT:BT::
@@ -61,3 +62,4 @@ cache:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3)
 cache:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
 cache:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction))
 cache:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3)
+#compute:SPR:SPR_is_256:int:(SPR == 256)
index be62655..54df704 100644 (file)
@@ -1109,18 +1109,14 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
        int rbit = 0;
        int xbit = 0;
        int sign = EXTRACTED64(frb, 0, 0);
-       enum { start, finish, Infinity_Operand, SNaN_Operand, QNaN_Operand, Large_Operand, Done } label = start;
-       while (label != finish) switch (label) {
-       case finish:
-         error("Unhandled switch\n");
-       case start:
+       /***/
          if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
-           { label = Infinity_Operand; break; }
+           GOTO(Infinity_Operand);
          if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
-           { label = SNaN_Operand; break; }
+           GOTO(SNaN_Operand);
          if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
-           { label = QNaN_Operand; break; }
-         if (EXTRACTED64(frb, 1, 11) > 1086) { label = Large_Operand; break; }
+           GOTO(QNaN_Operand);
+         if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
          if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
          if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
          if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
@@ -1148,25 +1144,25 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
          }
          if (tgt_precision == 32 /* can ignore frac64 in compare */
              && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
-           { label = Large_Operand; break; }
+           GOTO(Large_Operand);
          if (tgt_precision == 64 /* can ignore frac64 in compare */
              && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
-           { label = Large_Operand; break; }
+           GOTO(Large_Operand);
          if (tgt_precision == 32 /* can ignore frac64 in compare */
              && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
-           { label = Large_Operand; break; }
+           GOTO(Large_Operand);
          if (tgt_precision == 64 /* can ignore frac64 in compare */
              && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
-           { label = Large_Operand; break; }
+           GOTO(Large_Operand);
          FPSCR_SET_XX(FPSCR & fpscr_fi);
          if (tgt_precision == 32)
            *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
          if (tgt_precision == 64)
            *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
          /*FPSCR[fprf] = undefined */
-         { label = Done; break; }
+         GOTO(Done);
          /**/
-       case Infinity_Operand:
+       LABEL(Infinity_Operand):
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
          FPSCR_OR_VX(fpscr_vxcvi);
@@ -1181,9 +1177,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
            }
            /* FPSCR[FPRF] = undefined */
          }
-         { label = Done; break; }
+         GOTO(Done);
        /**/
-       case SNaN_Operand:
+       LABEL(SNaN_Operand):
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
          FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
@@ -1192,9 +1188,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
            if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
            /* FPSCR[fprf] = undefined */
          }
-         { label = Done; break; }
+         GOTO(Done);
        /**/
-       case QNaN_Operand:
+       LABEL(QNaN_Operand):
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
          FPSCR_OR_VX(fpscr_vxcvi);
@@ -1203,9 +1199,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
            if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
            /* FPSCR[fprf] = undefined */
          }
-         { label = Done; break; }
+         GOTO(Done);
        /**/
-       case Large_Operand:
+       LABEL(Large_Operand):
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
          FPSCR_OR_VX(fpscr_vxcvi);
@@ -1221,9 +1217,7 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
            /* FPSCR[fprf] = undefined */
          }
        /**/
-       case Done:
-         { label = finish; break; }
-       }
+       LABEL(Done):
 
 
 # extract out raw fields of a FP number
@@ -2126,8 +2120,40 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 #
 
 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
+       unsigned_word EA;
+       unsigned_word b;
+       int r;
+       if (RA == 0) b = 0;
+       else         b = *rA;
+       EA = b + EXTS(D);
+       r = RT;
+       if (RA >= r)
+         program_interrupt(processor, cia,
+                         illegal_instruction_program_interrupt);
+       if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
+         alignment_interrupt(processor, cia, EA);
+       while (r <= 31) {
+         GPR(r) = MEM(unsigned, EA, 4);
+         r = r + 1;
+         EA = EA + 4;
+       }
 
 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
+       unsigned_word EA;
+       unsigned_word b;
+       int r;
+       if (RA == 0) b = 0;
+       else         b = *rA;
+       EA = b + EXTS(D);
+       if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
+           || (EA % 4 != 0))
+         alignment_interrupt(processor, cia, EA);
+       r = RS;
+       while (r <= 31) {
+         STORE(EA, 4, GPR(r));
+         r = r + 1;
+         EA = EA + 4;
+       }
 
 
 #
@@ -2135,12 +2161,116 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 #
 
 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
+#      unsigned_word EA;
+#      int n;
+#      int r;
+#      int i;
+#      int nr;
+#      if (RA == 0) EA = 0;
+#      else         EA = *rA;
+#      if (NB == 0) n = 32;
+#      else         n = NB;
+#      r = RT - 1;
+#      i = 32;
+#      nr = (n + 3) / 4;
+#      if ((RT + nr >= 32)
+#          ? (RA >= RT && RA < RT + nr)
+#          : (RA >= RT || RA < (RT + nr) % 32))
+#        program_interrupt(processor, cia,
+#                          illegal_instruction_program_interrupt);
+#      if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+#        alignment_interrupt(processor, cia, EA);
+#      while (n > 0) {
+#        if (i == 32) {
+#          r = (r + 1) % 32;
+#          GPR(r) = 0;
+#        }
+#        GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
+#        if (i == 64) i = 32;
+#        EA = EA + 1;
+#        n = n - 1;
+#      }
 
 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
+#      unsigned_word EA;
+#      unsigned_word b;
+#      int n;
+#      int r;
+#      int i;
+#      int nr;
+#      if (RA == 0) b = 0;
+#      else         b = *rA;
+#      EA = b + *rB;
+#      n = EXTRACTED32(XER, 25, 31);
+#      r = RT - 1;
+#      i = 32;
+#      nr = (n + 3) / 4;
+#      if (((RT + n >= 32)
+#           ? ((RA >= RT && RA < RT + n)
+#              || (RB >= RT && RB < RT + n))
+#           : ((RA >= RT || RA < (RT + n) % 32)
+#              || (RB >= RT || RB < (RT + n) % 32)))
+#          || (RT == RA || RT == RB))
+#        program_interrupt(processor, cia,
+#                        illegal_instruction_program_interrupt);
+#      if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+#        alignment_interrupt(processor, cia, EA);
+#      while (n > 0) {
+#        if (i == 32) {
+#          r = (r + 1) % 32;
+#          GPR(i) = 0;
+#        }
+#        GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
+#        i = i + 8;
+#        if (i == 64) i = 32;
+#        EA = EA + 1;
+#        n = n - 1;
+#      }
 
 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
+#      unsigned_word EA;
+#      int n;
+#      int r;
+#      int i;
+#      if (RA == 0) EA = 0;
+#      else         EA = *rA;
+#      if (NB == 0) n = 32;
+#      else         n = NB;
+#      r = RS - 1;
+#      i = 32;
+#      if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+#        alignment_interrupt(processor, cia, EA);
+#      while (n > 0) {
+#        if (i == 32) r = (r + 1) % 32;
+#        STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
+#        i = i + 8;
+#        if (i == 64) i = 32;
+#        EA = EA + 1;
+#        n = n - 1;
+#      }
 
 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
+#      unsigned_word EA;
+#      unsigned_word b;
+#      int n;
+#      int r;
+#      int i;
+#      if (RA == 0) b = 0;
+#      else         b = *rA;
+#      EA = b + *rB;
+#      if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+#        alignment_interrupt(processor, cia, EA);
+#      n = EXTRACTED32(XER, 25, 31);
+#      r = RS - 1;
+#      i = 32;
+#      while (n > 0) {
+#        if (i == 32) r = (r + 1) % 32;
+#        STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
+#        i = i + 8;
+#        if (i == 64) i = 32;
+#        EA = EA + 1;
+#        n = n - 1;
+#      }
 
 
 #
@@ -2944,12 +3074,12 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 #      CR0_COMPARE(result, 0, Rc);
 
 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
-#      long n = MASKED(*rB, 59, 63);
-#      unsigned32 r = ROTL32(*rS, n);
-#      unsigned32 m = MASK(MB+32, ME+32);
-#      signed_word result = r & m;
-#      *rA = result;
-#      CR0_COMPARE(result, 0, Rc);
+       long n = MASKED(*rB, 59, 63);
+       unsigned32 r = ROTL32(*rS, n);
+       unsigned32 m = MASK(MB+32, ME+32);
+       signed_word result = r & m;
+       *rA = result;
+       CR0_COMPARE(result, 0, Rc);
 
 0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert
 #      long n = (sh_5 << 4) | sh_0_4;
@@ -3124,8 +3254,23 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          program_interrupt(processor, cia,
                            illegal_instruction_program_interrupt);
        else {
-         /* HACK - some SPR's need to get their value extracted specially */
-         *rT = SPREG(n);
+         /* HACK - time base registers need to be calculated */
+         if (WITH_TIME_BASE) {
+           switch (n) {
+           case spr_dec:
+             *rT = cpu_get_decrementer(processor);
+             break;
+           case spr_tbu:
+           case spr_tbl:
+             /* NOTE - these SPR's are not readable. Use mftb[ul] */
+           default:
+             *rT = SPREG(n);
+             break;
+           }
+         }
+         else {
+           *rT = SPREG(n);
+         }
        }
        PPC_INSN_FROM_SPR(RT_BITMASK, n);
 
@@ -3149,6 +3294,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        PPC_INSN_MTCR(RS_BITMASK, FXM);
 
 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
+#      CR_SET(BF, EXTRACTED32(XER, 0, 3));
+#      MBLIT32(XER, 0, 3, 0);
 
 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -4010,32 +4157,29 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        int sign;
        int exp;
        unsigned64 frac_grx;
-       enum { start, finish, Disabled_Exponent_Underflow, Enabled_Exponent_Underflow, Disabled_Exponent_Overflow, Enabled_Exponent_Overflow, Normal_Operand, Zero_Operand, Infinity_Operand, QNaN_Operand, SNaN_Operand, Enabled_Overflow, Done } label = start;
-       while (label != finish) switch (label) {
-       case finish:
-         error("Unhandled switch\n");
-       case start:
+       /***/
          /* split off cases for what to do */
          if (EXTRACTED64(*frB, 1, 11) < 897
              && EXTRACTED64(*frB, 1, 63) > 0) {
-             if ((FPSCR & fpscr_ue) == 0) { label = Disabled_Exponent_Underflow; break; }
-             if ((FPSCR & fpscr_ue) != 0) { label = Enabled_Exponent_Underflow; break; }
+             if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
+             if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
          }
          if (EXTRACTED64(*frB, 1, 11) > 1150
              && EXTRACTED64(*frB, 1, 11) < 2047) {
-             if ((FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
-             if ((FPSCR & fpscr_oe) != 0) { label = Enabled_Exponent_Overflow; break; }
+             if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
+             if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
          }
          if (EXTRACTED64(*frB, 1, 11) > 896
-             && EXTRACTED64(*frB, 1, 11) < 1151) { label = Normal_Operand; break; }
-         if (EXTRACTED64(*frB, 1, 63) == 0) { label = Zero_Operand; break; }
+             && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
+         if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
          if (EXTRACTED64(*frB, 1, 11) == 2047) {
-           if (EXTRACTED64(*frB, 12, 63) == 0) { label = Infinity_Operand; break; }
-           if (EXTRACTED64(*frB, 12, 12) == 1) { label = QNaN_Operand; break; }
+           if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
+           if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
            if (EXTRACTED64(*frB, 12, 12) == 0
-               && EXTRACTED64(*frB, 13, 63) > 0) { label = SNaN_Operand; break; }
+               && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
          }
-       case Disabled_Exponent_Underflow:
+       /**/
+       LABEL(Disabled_Exponent_Underflow):
          sign = EXTRACTED64(*frB, 0, 0);
          if (EXTRACTED64(*frB, 1, 11) == 0) {
            exp = -1022;
@@ -4077,8 +4221,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
                    | INSERTED64(exp + 1023, 1, 11)
                    | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
          }
-         { label = Done; break; }
-       case Enabled_Exponent_Underflow:
+         GOTO(Done);
+       /**/
+       LABEL(Enabled_Exponent_Underflow):
          FPSCR_SET_UX(1);
          sign = EXTRACTED64(*frB, 0, 0);
          if (EXTRACTED64(*frB, 1, 11) == 0) {
@@ -4103,8 +4248,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
                  | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
          if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
          if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
-         { label = Done; break; }
-       case Disabled_Exponent_Overflow:
+         GOTO(Done);
+       /**/
+       LABEL(Disabled_Exponent_Overflow):
          FPSCR_SET_OX(1);
          if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
            if (EXTRACTED64(*frB, 0, 0) == 0) {
@@ -4149,14 +4295,16 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          /* FPSCR[FR] <- undefined */
          FPSCR_SET_FI(1);
          FPSCR_SET_XX(1);
-         { label = Done; break; }
-       case Enabled_Exponent_Overflow:
+         GOTO(Done);
+       /**/
+       LABEL(Enabled_Exponent_Overflow):
          sign = EXTRACTED64(*frB, 0, 0);
          exp = EXTRACTED64(*frB, 1, 11) - 1023;
          frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
          Round_Single(processor, sign, &exp, &frac_grx);
          FPSCR_SET_XX(FPSCR & fpscr_fi);
-       case Enabled_Overflow:
+       /**/
+       LABEL(Enabled_Overflow):
          FPSCR_SET_OX(1);
          exp = exp - 192;
          *frT = (INSERTED64(sign, 0, 0)
@@ -4164,28 +4312,32 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
                  | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
          if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
          if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
-         { label = Done; break; }
-       case Zero_Operand:
+         GOTO(Done);
+       /**/
+       LABEL(Zero_Operand):
          *frT = *frB;
          if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
          if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
-         { label = Done; break; }
-       case Infinity_Operand:
+         GOTO(Done);
+       /**/
+       LABEL(Infinity_Operand):
          *frT = *frB;
          if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
          if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
-         { label = Done; break; }
-       case QNaN_Operand:
+         GOTO(Done);
+       /**/
+       LABEL(QNaN_Operand):
          *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
          FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
-         { label = Done; break; }
-       case SNaN_Operand:
+         GOTO(Done);
+       /**/
+       LABEL(SNaN_Operand):
          FPSCR_OR_VX(fpscr_vxsnan);
          if ((FPSCR & fpscr_ve) == 0) {
            *frT = (MASKED64(*frB, 0, 11)
@@ -4195,31 +4347,35 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          }
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
-         { label = Done; break; }
-       case Normal_Operand:
+         GOTO(Done);
+       /**/
+       LABEL(Normal_Operand):
          sign = EXTRACTED64(*frB, 0, 0);
          exp = EXTRACTED64(*frB, 1, 11) - 1023;
          frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
          Round_Single(processor, sign, &exp, &frac_grx);
          FPSCR_SET_XX(FPSCR & fpscr_fi);
-         if (exp > 127 && (FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
-         if (exp > 127 && (FPSCR & fpscr_oe) != 0) { label = Enabled_Overflow; break; }
+         if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
+         if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
          *frT = (INSERTED64(sign, 0, 0)
                  | INSERTED64(exp + 1023, 1, 11)
                  | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
          if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
          if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
-         { label = Done; break; }
-       case Done:
+         GOTO(Done);
+       /**/
+       LABEL(Done):
          PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
-         { label = finish; break; }
-       }
+
 
 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
+       floating_point_assist_interrupt(processor, cia);
 
 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
+       floating_point_assist_interrupt(processor, cia);
 
 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
+       floating_point_assist_interrupt(processor, cia);
 
 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -4237,12 +4393,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        int sign = EXTRACTED64(*frB, 0, 0);
        int exp = 63;
        unsigned64 frac = *frB;
-       enum { start, finish, Zero_Operand, Done } label = start;
-       while (label != finish) switch (label) {
-       case finish:
-         error("Unhandled switch\n");
-       case start:
-         if (frac == 0) { label = Zero_Operand; break; }
+       /***/
+         if (frac == 0) GOTO(Zero_Operand);
          if (sign == 1) frac = ~frac + 1;
          while (EXTRACTED64(frac, 0, 0) == 0) {
            /*??? do the loop 0 times if (FRB) = max negative integer */
@@ -4255,19 +4407,18 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *frT = (INSERTED64(sign, 0, 0)
                  | INSERTED64(exp + 1023, 1, 11)
                  | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
-         { label = Done; break; }
+         GOTO(Done);
        /**/
-       case Zero_Operand:
+       LABEL(Zero_Operand):
          FPSCR_SET_FR(0);
          FPSCR_SET_FI(0);
          FPSCR_SET_FPRF(fpscr_rf_pos_zero);
          *frT = 0;
-         { label = Done; break; }
+         GOTO(Done);
        /**/
-       case Done:
+       LABEL(Done):
          PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
-         { label = finish; break; }
-       }
+
 
 #
 # I.4.6.7 Floating-Point Compare Instructions
@@ -4329,41 +4480,115 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 #
 
 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
+       floating_point_assist_interrupt(processor, cia);
+#      FPSCR_BEGIN;
+#      *frT = FPSCR;
+#      FPSCR_END(Rc);
 
 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
+       floating_point_assist_interrupt(processor, cia);
+#      FPSCR_BEGIN;
+#      unsigned field = FPSCR_FIELD(BFA);
+#      CR_SET(BF, field);
+#      switch (BFA) {
+#      case 0:
+#        FPSCR &= ~(fpscr_fx | fpscr_ox);
+#        break;
+#      case 1:
+#        FPSCR &= ~(fpscr_ux | fpscr_zx | fpscr_xx | fpscr_vxsnan);
+#        break;
+#      case 2:
+#        FPSCR &= ~(fpscr_vxisi | fpscr_vxidi | fpscr_vxzdz | fpscr_vximz);
+#        break;
+#      case 3:
+#        FPSCR &= ~(fpscr_vxvc);
+#        break;
+#      case 5:
+#        FPSCR &= ~(fpscr_vxsoft | fpscr_vxsqrt | fpscr_vxcvi);
+#        break;
+#      }
+#      FPSCR_END(0);
 
 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
+       floating_point_assist_interrupt(processor, cia);
+#      FPSCR_BEGIN;
+#      FPSCR_SET(BF, U);
+#      /* FIXME - what about the effect this has on exception bits */
+#      FPSCR_END(Rc);
 
 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
+       FPSCR_BEGIN;
+       int i;
+       for (i = 0; i < 8; i++) {
+         if ((FLM & BIT8(i))) {
+           FPSCR &= ~MASK32(i*4, i*4+3);
+           FPSCR |= MASKED32(*frB, i*4, i*4+3);
+         }
+       }
+       FPSCR_END(Rc);
 
 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
+       floating_point_assist_interrupt(processor, cia);
+#      FPSCR_BEGIN;
+#      unsigned32 mask = ~BIT32(BT) | (fpscr_fex | fpscr_vx);
+#      FPSCR &= mask;
+#      /* FIXME - what about the effect this has on exception bits */
+#      FPSCR_END(Rc);
 
 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
+       floating_point_assist_interrupt(processor, cia);
+#      FPSCR_BEGIN;
+#      unsigned32 bit = BIT32(BT) & ~(fpscr_fex | fpscr_vx);
+#      FPSCR |= bit;
+#      /* FIXME - need to take care of when and why FX is set */
+#      /* FIXME - if FX (or another exception bit is set) shall
+#                 an exception occure */
+#      /* FPSCR |= fpscr_fx; */
+#      /* FIXME - what about the effect this has on exception bits */
+#      FPSCR_END(Rc);
 
 
 #
 # I.A.1.1 Floating-Point Store Instruction
 #
-0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
+0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
+       program_interrupt(processor, cia, optional_instruction_program_interrupt);
 
 #
 # I.A.1.2 Floating-Point Arithmetic Instructions
 #
 
-0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
+0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
+       program_interrupt(processor, cia, optional_instruction_program_interrupt);
 
-0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
+0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
+       program_interrupt(processor, cia, optional_instruction_program_interrupt);
 
-0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
+0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
+       program_interrupt(processor, cia, optional_instruction_program_interrupt);
 
-0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
+0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
+       program_interrupt(processor, cia, optional_instruction_program_interrupt);
 
 #
 # I.A.1.3 Floating-Point Select Instruction
 #
 
-0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
-
+0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
+*601: PPC_UNIT_BAD,   PPC_UNIT_BAD,   0,  0,  0
+*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       if (CURRENT_MODEL == MODEL_ppc601) {
+         program_interrupt(processor, cia, optional_instruction_program_interrupt);
+       } else {
+         unsigned64 zero = 0;
+         FPSCR_BEGIN;
+         if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
+         else                                              *frT = *frC;
+         FPSCR_END(Rc);
+         PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
+       }
 
 #
 # II.3.2 Cache Management Instructions
@@ -4385,7 +4610,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
-       cpu_synchronize_context(processor);
+       cpu_synchronize_context(processor, cia);
        PPC_INSN_INT(0, 0, 0);
 
 
@@ -4481,7 +4706,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
                 | MASKED(SRR1, 37, 41)
                 | MASKED(SRR1, 48, 63));
          NIA = MASKED(SRR0, 0, 61);
-         cpu_synchronize_context(processor);
+         cpu_synchronize_context(processor, cia);
          check_masked_interrupts(processor);
        }
 
index 333c6ae..78fac6a 100644 (file)
@@ -22,6 +22,6 @@ array,normal:       21:31:32:-1:OE,LR,AA,Rc,LK:
 array,expand-forced: 6: 9: 6: 9:BO:            0xfc000000:0x40000000
 array,boolean:      11:15:11:15:0RA:           0xfc000000:0x38000000:0
 array,boolean:      11:15:11:15:RA:            0xfc000000:0x3c000000:0
-# BLR instruction - LR=8 is munged into 0x100
-array,boolean:      11:20:11:20:SPR:           0xfc0007ff:0x7c0003a6:0x100
-array,boolean:      11:20:11:20:SPR:           0xfc0007ff:0x7c0002a6:0x100
+# BLR instruction - LR=8 is munged into 0x100 == 256
+array,boolean:      11:20:11:20:SPR:           0xfc0007ff:0x7c0003a6:256
+array,boolean:      11:20:11:20:SPR:           0xfc0007ff:0x7c0002a6:256
index 0c7024e..c2d3a60 100644 (file)
@@ -26,6 +26,7 @@
 #include "idecode.h"
 #include "options.h"
 
+#include "tree.h"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -78,6 +79,7 @@ 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;
 
 
@@ -87,16 +89,16 @@ INLINE_PSIM\
 (device *)
 psim_tree(void)
 {
-  device *root = device_tree_add_parsed(NULL, "core");
-  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");
+  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;
 }
 
@@ -122,55 +124,74 @@ psim_usage(int verbose)
   printf_filtered("\n");
   printf_filtered("Where\n");
   printf_filtered("\n");
-  printf_filtered("\t<image>       Name of the PowerPC program to run.\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("\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");
+  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("\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("\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");
+
+  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-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("\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-i            Print instruction counting statistics\n");
-  if (verbose) { printf_filtered("\n"); }
-  printf_filtered("\t-I            Print execution unit statistics\n");
+
+  printf_filtered("\t-f <file>       Merge <file> into the device tree\n");
   if (verbose) { printf_filtered("\n"); }
-  printf_filtered("\t-r <size>     Set RAM size in bytes (OEA environments)\n");
+
+  printf_filtered("\t-h -? -H        give more detailed usage\n");
   if (verbose) { printf_filtered("\n"); }
-  printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\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-o <spec>     add device <spec> to the device tree\n");
+
+  printf_filtered("\t-r <ram-size>   Set RAM size in bytes (OEA environments)\n");
   if (verbose) { printf_filtered("\n"); }
-  printf_filtered("\t-h -? -H      give more detailed usage\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);
@@ -202,7 +223,11 @@ psim_options(device *root,
        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);
+       tree_parse(root, "/openprom/options/os-emul %s", param);
+       break;
+      case 'f':
+       param = find_arg("Missing <file> option for -f\n", &argp, argv);
+       psim_merge_device_file(root, param);
        break;
       case 'h':
       case '?':
@@ -212,45 +237,81 @@ psim_options(device *root,
        psim_usage(2);
        break;
       case 'i':
-       device_tree_add_parsed(root, "/openprom/trace/print-info 1");
+       tree_parse(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);
+       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\n", &argp, argv);
-       device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
+       tree_parse(root, "/openprom/options/model \"%s", param);
+       break;
+      case 'n':
+       param = find_arg("Missing <nr-smp> option for -n\n", &argp, argv);
+       tree_parse(root, "/openprom/options/smp %s", param);
        break;
       case 'o':
-       param = find_arg("Missing <device> option for -o\n", &argp, argv);
-       current = device_tree_add_parsed(current, "%s", param);
+       param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
+       current = tree_parse(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));
+       tree_parse(root, "/openprom/options/oea-memory-size %s",
+                              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);
+         tree_parse(root, "/openprom/trace/%s 0", param+1);
        else
-         device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
+         tree_parse(root, "/openprom/trace/%s 1", param);
        break;
       }
       p += 1;
     }
     argp += 1;
   }
-  /* force the trace node to (re)process its options */
-  device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0);
+  /* 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);
 
   /* return where the options end */
   return argv + argp;
 }
 
+INLINE_PSIM\
+(void)
+psim_command(device *root,
+            char **argv)
+{
+  int argp = 0;
+  if (argv[argp] == NULL) {
+    return;
+  }
+  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);
+  }
+  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 {
+    printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
+    printf_filtered("    trace <trace-option>\n");
+    printf_filtered("    change-media <device> [ <new-image> ]\n");
+  }
+}
+
 
 /* create the simulator proper from the device tree and executable */
 
@@ -274,13 +335,13 @@ psim_create(const char *file_name,
     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 */
-  nr_cpus = device_find_integer_property(root, "/openprom/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 */
   current_target_byte_order
-    = (device_find_boolean_property(root, "/options/little-endian?")
+    = (tree_find_boolean_property(root, "/options/little-endian?")
        ? LITTLE_ENDIAN
        : BIG_ENDIAN);
   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
@@ -295,7 +356,7 @@ psim_create(const char *file_name,
     error("host and configured byte order conflict\n");
 
   /* fill in the missing OEA/VEA information */
-  env = device_find_string_property(root, "/openprom/options/env");
+  env = tree_find_string_property(root, "/openprom/options/env");
   current_environment = ((strcmp(env, "user") == 0
                          || strcmp(env, "uea") == 0)
                         ? USER_ENVIRONMENT
@@ -313,7 +374,7 @@ psim_create(const char *file_name,
 
   /* fill in the missing ALLIGNMENT information */
   current_alignment
-    = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
+    = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
        ? STRICT_ALIGNMENT
        : NONSTRICT_ALIGNMENT);
   if (CURRENT_ALIGNMENT != current_alignment)
@@ -321,15 +382,23 @@ psim_create(const char *file_name,
 
   /* fill in the missing FLOATING POINT information */
   current_floating_point
-    = (device_find_boolean_property(root, "/openprom/options/floating-point?")
+    = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
        ? HARD_FLOATING_POINT
        : SOFT_FLOATING_POINT);
   if (CURRENT_FLOATING_POINT != current_floating_point)
     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
-    = device_find_integer_property(root, "/openprom/options/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");
 
@@ -341,7 +410,7 @@ psim_create(const char *file_name,
      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"));
+  model_set(tree_find_string_property(root, "/openprom/options/model"));
 
   /* create things */
   system = ZALLOC(psim);
@@ -364,7 +433,7 @@ psim_create(const char *file_name,
 
   /* 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);
+    tree_print(root);
   if (ppc_trace[trace_dump_device_tree])
     error("");
 
@@ -419,6 +488,7 @@ psim_halt(psim *system,
   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
 }
 
+
 INLINE_PSIM\
 (int)
 psim_last_cpu(psim *system)
@@ -458,7 +528,7 @@ INLINE_PSIM\
 psim_device(psim *system,
            const char *path)
 {
-  return device_tree_find_device(system->devices, path);
+  return tree_find_device(system->devices, path);
 }
 
 INLINE_PSIM\
@@ -487,19 +557,20 @@ psim_init(psim *system)
     cpu_init(system->processors[cpu_nr]);
 
   /* init all the devices (which updates the cpus) */
-  device_tree_init(system->devices, system);
+  tree_init(system->devices, system);
 
   /* and the emulation (which needs an initialized device tree) */
   os_emul_init(system->os_emulation, system->nr_cpus);
 
   /* 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]);
+    cpu *processor = system->processors[cpu_nr];
+    cpu_synchronize_context(processor, cpu_get_program_counter(processor));
+    cpu_page_tlb_invalidate_all(processor);
   }
 
-  /* force loop to restart */
-  system->last_cpu = -1; /* when incremented will become 0 - first CPU */
+  /* force loop to start with first cpu (after processing events) */
+  system->last_cpu = system->nr_cpus - 1;
 }
 
 INLINE_PSIM\
@@ -510,14 +581,15 @@ psim_stack(psim *system,
 {
   /* pass the stack device the argv/envp and let it work out what to
      do with it */
-  device *stack_device = device_tree_find_device(system->devices,
-                                                "/openprom/init/stack");
+  device *stack_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,
                 NULL, /*cpu*/
                 0, /*cia*/
+                device_ioctl_create_stack,
                 stack_pointer,
                 argv,
                 envp);
@@ -778,7 +850,8 @@ psim_read_memory(psim *system,
     error("psim_read_memory() invalid cpu\n");
   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);
 }
 
 
@@ -798,7 +871,8 @@ psim_write_memory(psim *system,
     error("psim_read_memory() invalid cpu\n");
   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);
 }
 
 
@@ -818,20 +892,61 @@ INLINE_PSIM\
 psim_merge_device_file(device *root,
                       const char *file_name)
 {
-  FILE *description = fopen(file_name, "r");
-  int line_nr = 0;
+  FILE *description;
+  int line_nr;
   char device_path[1000];
-  device *current = root;
+  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)) {
-    /* check all of line was read */
+    char *device;
+    /* check that the full 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);
+      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 = device_tree_add_parsed(current, "%s", device_path);
+    current = tree_parse(current, "%s", device);
   }
   fclose(description);
 }
index e1889f6..35a9212 100644 (file)
 #endif
 #endif
 
-#include "../../gdb/defs.h"
-
-#include "../../gdb/remote-sim.h"
-#include "../../gdb/callback.h"
+#include "defs.h"
+#include "callback.h"
+#include "remote-sim.h"
 
 
 /* Structures used by the simulator, for gdb just have static structures */
@@ -280,9 +279,9 @@ sim_do_command (char *cmd)
 {
   TRACE(trace_gdb, ("sim_do_commands(cmd=%s) called\n",
                    cmd ? cmd : "(null)"));
-  if (cmd) {
+  if (cmd != NULL) {
     char **argv = buildargv(cmd);
-    psim_options(root_device, argv);
+    psim_command(root_device, argv);
     freeargv(argv);
   }
 }
@@ -312,6 +311,7 @@ sim_io_read_stdin(char *buf,
     error("sim_io_read_stdin: unaccounted switch\n");
     break;
   }
+  return 0;
 }
 
 int
@@ -329,6 +329,7 @@ sim_io_write_stdout(const char *buf,
     error("sim_io_write_stdout: unaccounted switch\n");
     break;
   }
+  return 0;
 }
 
 int
@@ -347,6 +348,7 @@ sim_io_write_stderr(const char *buf,
     error("sim_io_write_stderr: unaccounted switch\n");
     break;
   }
+  return 0;
 }
 
 
diff --git a/sim/ppc/tree.c b/sim/ppc/tree.c
new file mode 100644 (file)
index 0000000..856e90b
--- /dev/null
@@ -0,0 +1,1273 @@
+/*  This file is part of the program psim.
+
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    */
+
+
+#ifndef _PARSE_C_
+#define _PARSE_C_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "basics.h"
+
+#include "device.h"
+#include "tree.h"
+
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include <ctype.h>
+
+
+/* manipulate/lookup device names */
+
+typedef struct _name_specifier {
+  /* components in the full length name */
+  char *path;
+  char *property;
+  char *value;
+  /* current device */
+  char *name;
+  char *base;
+  char *unit;
+  char *args;
+  /* previous device */
+  char *last_name;
+  char *last_base;
+  char *last_unit;
+  char *last_args;
+  /* work area */
+  char buf[1024];
+} name_specifier;
+
+
+
+/* Given a device specifier, break it up into its main components:
+   path (and if present) property name and property value. */
+
+STATIC_INLINE_TREE\
+(int)
+split_device_specifier(device *current,
+                      const char *device_specifier,
+                      name_specifier *spec)
+{
+  char *chp = NULL;
+
+  /* expand any leading alias if present */
+  if (current != NULL
+      && *device_specifier != '\0'
+      && *device_specifier != '.'
+      && *device_specifier != '/') {
+    device *aliases = tree_find_device(current, "/aliases");
+    char alias[32];
+    int len = 0;
+    while (device_specifier[len] != '\0'
+          && device_specifier[len] != '/'
+          && device_specifier[len] != ':'
+          && !isspace(device_specifier[len])) {
+      alias[len] = device_specifier[len];
+      len++;
+      if (len >= sizeof(alias))
+       error("split_device_specifier: buffer overflow");
+    }
+    alias[len] = '\0';
+    if (aliases != NULL
+       && device_find_property(aliases, alias)) {
+      strcpy(spec->buf, device_find_string_property(aliases, alias));
+      strcat(spec->buf, device_specifier + len);
+    }
+    else {
+      strcpy(spec->buf, device_specifier);
+    }
+  }
+  else {
+    strcpy(spec->buf, device_specifier);
+  }
+
+  /* check no overflow */
+  if (strlen(spec->buf) >= sizeof(spec->buf))
+    error("split_device_specifier: buffer overflow\n");
+
+  /* strip leading spaces */
+  chp = spec->buf;
+  while (*chp != '\0' && isspace(*chp))
+    chp++;
+  if (*chp == '\0')
+    return 0;
+
+  /* find the path and terminate it with null */
+  spec->path = chp;
+  while (*chp != '\0' && !isspace(*chp))
+    chp++;
+  if (*chp != '\0') {
+    *chp = '\0';
+    chp++;
+  }
+
+  /* and any value */
+  while (*chp != '\0' && isspace(*chp))
+    chp++;
+  spec->value = chp;
+
+  /* now go back and chop the property off of the path */
+  if (spec->value[0] == '\0') {
+    spec->property = NULL; /*not a property*/
+    spec->value = NULL;
+  }
+  else if (spec->value[0] == '>'
+          || spec->value[0] == '<') {
+    /* an interrupt spec */
+    spec->property = NULL;
+  }
+  else {
+    chp = strrchr(spec->path, '/');
+    if (chp == NULL) {
+      spec->property = spec->path;
+      spec->path = strchr(spec->property, '\0');
+    }
+    else {
+      *chp = '\0';
+      spec->property = chp+1;
+    }
+  }
+
+  /* and mark the rest as invalid */
+  spec->name = NULL;
+  spec->base = NULL;
+  spec->unit = NULL;
+  spec->args = NULL;
+  spec->last_name = NULL;
+  spec->last_base = NULL;
+  spec->last_unit = NULL;
+  spec->last_args = NULL;
+
+  return 1;
+}
+
+
+/* given a device specifier break it up into its main components -
+   path and property name - assuming that the last `device' is a
+   property name. */
+
+STATIC_INLINE_DEVICE\
+(int)
+split_property_specifier(device *current,
+                        const char *property_specifier,
+                        name_specifier *spec)
+{
+  if (split_device_specifier(current, property_specifier, spec)) {
+    if (spec->property == NULL) {
+      /* force the last name to be a property name */
+      char *chp = strrchr(spec->path, '/');
+      if (chp == NULL) {
+       spec->property = spec->path;
+       spec->path = strrchr(spec->property, '\0');;
+      }
+      else {
+       *chp = '\0';
+       spec->property = chp+1;
+      }
+    }
+    return 1;
+  }
+  else
+    return 0;
+}
+
+
+/* device the next device name and split it up, return 0 when no more
+   names to device */
+
+STATIC_INLINE_TREE\
+(int)
+split_device_name(name_specifier *spec)
+{
+  char *chp;
+  /* remember what came before */
+  spec->last_name = spec->name;
+  spec->last_base = spec->base;
+  spec->last_unit = spec->unit;
+  spec->last_args = spec->args;
+  /* finished? */
+  if (spec->path[0] == '\0') {
+    spec->name = NULL;
+    spec->base = NULL;
+    spec->unit = NULL;
+    spec->args = NULL;
+    return 0;
+  }
+  /* break the current device spec from the path */
+  spec->name = spec->path;
+  chp = strchr(spec->name, '/');
+  if (chp == NULL)
+    spec->path = strchr(spec->name, '\0');
+  else {
+    spec->path = chp+1;
+    *chp = '\0';
+  }
+  /* break out the base */
+  if (spec->name[0] == '(') {
+    chp = strchr(spec->name, ')');
+    if (chp == NULL) {
+      spec->base = spec->name;
+    }
+    else {
+      *chp = '\0';
+      spec->base = spec->name + 1;
+      spec->name = chp + 1;
+    }
+  }
+  else {
+    spec->base = spec->name;
+  }
+  /* now break out the unit */
+  chp = strchr(spec->name, '@');
+  if (chp == NULL) {
+    spec->unit = NULL;
+    chp = spec->name;
+  }
+  else {
+    *chp = '\0';
+    chp += 1;
+    spec->unit = chp;
+  }
+  /* finally any args */
+  chp = strchr(chp, ':');
+  if (chp == NULL)
+    spec->args = NULL;
+  else {
+    *chp = '\0';
+    spec->args = chp+1;
+  }
+  return 1;
+}
+
+
+/* device the value, returning the next non-space token */
+
+STATIC_INLINE_TREE\
+(char *)
+split_value(name_specifier *spec)
+{
+  char *token;
+  if (spec->value == NULL)
+    return NULL;
+  /* skip leading white space */
+  while (isspace(spec->value[0]))
+    spec->value++;
+  if (spec->value[0] == '\0') {
+    spec->value = NULL;
+    return NULL;
+  }
+  token = spec->value;
+  /* find trailing space */
+  while (spec->value[0] != '\0' && !isspace(spec->value[0]))
+    spec->value++;
+  /* chop this value out */
+  if (spec->value[0] != '\0') {
+    spec->value[0] = '\0';
+    spec->value++;
+  }
+  return token;
+}
+
+
+
+/* traverse the path specified by spec starting at current */
+
+STATIC_INLINE_TREE\
+(device *)
+split_find_device(device *current,
+                 name_specifier *spec)
+{
+  /* strip off (and process) any leading ., .., ./ and / */
+  while (1) {
+    if (strncmp(spec->path, "/", strlen("/")) == 0) {
+      /* cd /... */
+      while (current != NULL && device_parent(current) != NULL)
+       current = device_parent(current);
+      spec->path += strlen("/");
+    }
+    else if (strncmp(spec->path, "./", strlen("./")) == 0) {
+      /* cd ./... */
+      current = current;
+      spec->path += strlen("./");
+    }
+    else if (strncmp(spec->path, "../", strlen("../")) == 0) {
+      /* cd ../... */
+      if (current != NULL && device_parent(current) != NULL)
+       current = device_parent(current);
+      spec->path += strlen("../");
+    }
+    else if (strcmp(spec->path, ".") == 0) {
+      /* cd . */
+      current = current;
+      spec->path += strlen(".");
+    }
+    else if (strcmp(spec->path, "..") == 0) {
+      /* cd . */
+      if (current != NULL && device_parent(current) != NULL)
+       current = device_parent(current);
+      spec->path += strlen("..");
+    }
+    else
+      break;
+  }
+
+  /* now go through the path proper */
+
+  if (current == NULL) {
+    split_device_name(spec);
+    return NULL;
+  }
+
+  while (split_device_name(spec)) {
+    device *child;
+    for (child = device_child(current);
+        child != NULL; child = device_sibling(child)) {
+      if (strcmp(spec->name, device_name(child)) == 0) {
+       if (spec->unit == NULL)
+         break;
+       else {
+         device_unit phys;
+         device_decode_unit(current, spec->unit, &phys);
+         if (memcmp(&phys, device_unit_address(child),
+                    sizeof(device_unit)) == 0)
+           break;
+       }
+      }
+    }
+    if (child == NULL)
+      return current; /* search failed */
+    current = child;
+  }
+
+  return current;
+}
+
+
+STATIC_INLINE_TREE\
+(device *)
+split_fill_path(device *current,
+               const char *device_specifier,
+               name_specifier *spec)
+{
+  /* break it up */
+  if (!split_device_specifier(current, device_specifier, spec))
+    device_error(current, "error parsing %s\n", device_specifier);
+
+  /* fill our tree with its contents */
+  current = split_find_device(current, spec);
+
+  /* add any additional devices as needed */
+  if (spec->name != NULL) {
+    do {
+      current = device_create(current, spec->base, spec->name,
+                             spec->unit, spec->args);
+    } while (split_device_name(spec));
+  }
+
+  return current;
+}
+
+
+INLINE_TREE\
+(void)
+tree_init(device *root,
+         psim *system)
+{
+  TRACE(trace_device_tree, ("tree_init(root=0x%lx, system=0x%lx)\n",
+                           (long)root,
+                           (long)system));
+  /* remove the old, rebuild the new */
+  tree_traverse(root, device_clean, NULL, system);
+  tree_traverse(root, device_init_static_properties, NULL, system);
+  tree_traverse(root, device_init_address, NULL, system);
+  tree_traverse(root, device_init_runtime_properties, NULL, system);
+  tree_traverse(root, device_init_data, NULL, system);
+}
+
+
+\f
+/* <non-white-space> */
+
+STATIC_INLINE_TREE\
+(const char *)
+skip_token(const char *chp)
+{
+  while (!isspace(*chp) && *chp != '\0')
+    chp++;
+  while (isspace(*chp) && *chp != '\0')
+    chp++;
+  return chp;
+}
+
+
+/* count the number of entries */
+
+STATIC_INLINE_TREE\
+(int)
+count_entries(device *current,
+             const char *property_name,
+             const char *property_value,
+             int modulo)
+{
+  const char *chp = property_value;
+  int nr_entries = 0;
+  while (*chp != '\0') {
+    nr_entries += 1;
+    chp = skip_token(chp);
+  }
+  if ((nr_entries % modulo) != 0) {
+    device_error(current, "incorrect number of entries for %s property %s, should be multiple of %d",
+                property_name, property_value, modulo);
+  }
+  return nr_entries / modulo;
+}
+
+
+
+/* parse: <address> ::= <token> ; device dependant */
+
+STATIC_INLINE_TREE\
+(const char *)
+parse_address(device *current,
+             device *bus,
+             const char *chp,
+             device_unit *address)
+{
+  if (device_decode_unit(bus, chp, address) < 0)
+    device_error(current, "invalid unit address in %s", chp);
+  return skip_token(chp);
+}
+
+
+/* parse: <size> ::= <number> { "," <number> } ; */
+
+STATIC_INLINE_TREE\
+(const char *)
+parse_size(device *current,
+          device *bus,
+          const char *chp,
+          device_unit *size)
+{
+  int i;
+  int nr;
+  const char *curr = chp;
+  memset(size, 0, sizeof(*size));
+  /* parse the numeric list */
+  size->nr_cells = device_nr_size_cells(bus);
+  nr = 0;
+  while (1) {
+    char *next;
+    size->cells[nr] = strtoul(curr, &next, 0);
+    if (curr == next)
+      device_error(current, "Problem parsing <size> %s", chp);
+    nr += 1;
+    if (next[0] != ',')
+      break;
+    if (nr == size->nr_cells)
+      device_error(current, "Too many values in <size> %s", chp);
+    curr = next + 1;
+  }
+  ASSERT(nr > 0 && nr <= size->nr_cells);
+  /* right align the numbers */
+  for (i = 1; i <= size->nr_cells; i++) {
+    if (i <= nr)
+      size->cells[size->nr_cells - i] = size->cells[nr - i];
+    else
+      size->cells[size->nr_cells - i] = 0;
+  }
+  return skip_token(chp);
+}
+
+
+/* parse: <reg> ::= { <address> <size> } ; */
+
+STATIC_INLINE_TREE\
+(void)
+parse_reg_property(device *current,
+                  const char *property_name,
+                  const char *property_value)
+{
+  int nr_regs;
+  int reg_nr;
+  reg_property_spec *regs;
+  const char *chp;
+
+  /* determine the number of reg entries by counting tokens */
+  nr_regs = count_entries(current, property_name, property_value, 2);
+
+  /* create working space */
+  regs = zalloc(nr_regs * sizeof(*regs));
+
+  /* fill it in */
+  chp = property_value;
+  for (reg_nr = 0; reg_nr < nr_regs; reg_nr++) {
+    chp = parse_address(current, device_parent(current),
+                       chp, &regs[reg_nr].address);
+    chp = parse_size(current, device_parent(current),
+                    chp, &regs[reg_nr].size);
+  }
+
+  /* create it */
+  device_add_reg_array_property(current, property_name,
+                               regs, nr_regs);
+
+  zfree(regs);
+}
+
+
+/* { <child-address> <parent-address> <child-size> }* */
+
+STATIC_INLINE_TREE\
+(void)
+parse_ranges_property(device *current,
+                     const char *property_name,
+                     const char *property_value)
+{
+  int nr_ranges;
+  int range_nr;
+  range_property_spec *ranges;
+  const char *chp;
+  
+  /* determine the number of ranges specified */
+  nr_ranges = count_entries(current, property_name, property_value, 3);
+
+  /* create a property of that size */
+  ranges = zalloc(nr_ranges * sizeof(*ranges));
+
+  /* fill it in */
+  chp = property_value;
+  for (range_nr = 0; range_nr < nr_ranges; range_nr++) {
+    chp = parse_address(current, current,
+                       chp, &ranges[range_nr].child_address);
+    chp = parse_address(current, device_parent(current),
+                       chp, &ranges[range_nr].parent_address);
+    chp = parse_size(current, current,
+                    chp, &ranges[range_nr].size);
+  }
+
+  /* create it */
+  device_add_range_array_property(current, property_name, ranges, nr_ranges);
+
+  zfree(ranges);
+}
+
+
+/* <integer> ... */
+
+STATIC_INLINE_TREE\
+(void)
+parse_integer_property(device *current,
+                      const char *property_name,
+                      const char *property_value)
+{
+  int nr_entries;
+  unsigned_cell words[1024];
+  /* integer or integer array? */
+  nr_entries = 0;
+  while (1) {
+    char *end;
+    words[nr_entries] = strtoul(property_value, &end, 0);
+    if (property_value == end)
+      break;
+    nr_entries += 1;
+    if (nr_entries * sizeof(words[0]) >= sizeof(words))
+      device_error(current, "buffer overflow");
+    property_value = end;
+  }
+  if (nr_entries == 0)
+    device_error(current, "error parsing integer property %s (%s)",
+                 property_name, property_value);
+  else if (nr_entries == 1)
+    device_add_integer_property(current, property_name, words[0]);
+  else {
+    int i;
+    for (i = 0; i < nr_entries; i++) {
+      H2BE(words[i]);
+    }
+    /* perhaphs integer array property is better */
+    device_add_array_property(current, property_name, words,
+                              sizeof(words[0]) * nr_entries);
+  }
+}
+
+
+/* <string> ... */
+
+STATIC_INLINE_TREE\
+(void)
+parse_string_property(device *current,
+                     const char *property_name,
+                     const char *property_value)
+{
+  char **strings;
+  const char *chp;
+  int nr_strings;
+  int approx_nr_strings;
+
+  /* get an estimate as to the number of strings by counting double
+     quotes */
+  approx_nr_strings = 2;
+  for (chp = property_value; *chp; chp++) {
+    if (*chp == '"')
+      approx_nr_strings++;
+  }
+  approx_nr_strings = (approx_nr_strings) / 2;
+
+  /* create a string buffer for that many (plus a null) */
+  strings = (char**)zalloc((approx_nr_strings + 1) * sizeof(char*));
+
+  /* now find all the strings */
+  chp = property_value;
+  nr_strings = 0;
+  while (1) {
+
+    /* skip leading space */
+    while (*chp != '\0' && isspace(*chp))
+      chp += 1;
+    if (*chp == '\0')
+      break;
+
+    /* copy it in */
+    if (*chp == '"') {
+      /* a quoted string - watch for '\' et.al. */
+      /* estimate the size and allocate space for it */
+      int pos;
+      chp++;
+      pos = 0;
+      while (chp[pos] != '\0' && chp[pos] != '"') {
+       if (chp[pos] == '\\' && chp[pos+1] != '\0')
+         pos += 2;
+       else
+         pos += 1;
+      }
+      strings[nr_strings] = zalloc(pos + 1);
+      /* copy the string over */
+      pos = 0;
+      while (*chp != '\0' && *chp != '"') {
+       if (*chp == '\\' && *(chp+1) != '\0') {
+         strings[nr_strings][pos] = *(chp+1);
+         chp += 2;
+         pos++;
+       }
+       else {
+         strings[nr_strings][pos] = *chp;
+         chp += 1;
+         pos++;
+       }
+      }
+      if (*chp != '\0')
+       chp++;
+      strings[nr_strings][pos] = '\0';
+    }
+    else {
+      /* copy over a single unquoted token */
+      int len = 0;
+      while (chp[len] != '\0' && !isspace(chp[len]))
+       len++;
+      strings[nr_strings] = zalloc(len + 1);
+      strncpy(strings[nr_strings], chp, len);
+      strings[nr_strings][len] = '\0';
+      chp += len;
+    }
+    nr_strings++;
+    if (nr_strings > approx_nr_strings)
+      device_error(current, "String property %s badly formatted",
+                  property_name);
+  }
+  ASSERT(strings[nr_strings] == NULL); /* from zalloc */
+
+  /* install it */
+  if (nr_strings == 0)
+    device_add_string_property(current, property_name, "");
+  else if (nr_strings == 1)
+    device_add_string_property(current, property_name, strings[0]);
+  else {
+    const char **specs = (const char**)strings; /* stop a bogus error */
+    device_add_string_array_property(current, property_name,
+                                    specs, nr_strings);
+  }
+
+  /* flush the created string */
+  while (nr_strings > 0) {
+    nr_strings--;
+    zfree(strings[nr_strings]);
+  }
+  zfree(strings);
+}
+
+
+/* <path-to-ihandle-device> */
+
+STATIC_INLINE_TREE\
+(void)
+parse_ihandle_property(device *current,
+                      const char *property,
+                      const char *value)
+{
+  ihandle_runtime_property_spec ihandle;
+  const char *chp;
+  name_specifier ihandle_spec;
+
+  /* copy over the full path */
+  ihandle.full_path = value;
+
+  /* copy over the args (if present) */
+  chp = strchr(value, '\0');
+  while (chp > value && *chp != '/' && *chp != ':')
+    chp--;
+  if (*chp == ':') {
+    chp += 1;
+    ihandle.args = chp;
+  }
+  else {
+    ihandle.args = NULL;
+  }
+  
+  /* save this ready for the ihandle create */
+  ihandle.phandle = split_fill_path(current, ihandle.full_path, &ihandle_spec);
+  device_add_ihandle_runtime_property(current, property,
+                                     &ihandle);
+}
+
+
+
+EXTERN_TREE\
+(device *)
+tree_parse(device *current,
+          const char *fmt,
+          ...)
+{
+  char device_specifier[1024];
+  name_specifier spec;
+
+  /* format the path */
+  {
+    va_list ap;
+    va_start(ap, fmt);
+    vsprintf(device_specifier, fmt, ap);
+    va_end(ap);
+    if (strlen(device_specifier) >= sizeof(device_specifier))
+      error("device_tree_add_deviced: buffer overflow\n");
+  }
+
+  /* construct the tree down to the final device */
+  current = split_fill_path(current, device_specifier, &spec);
+
+  /* is there an interrupt spec */
+  if (spec.property == NULL
+      && spec.value != NULL) {
+    char *op = split_value(&spec);
+    switch (op[0]) {
+    case '>':
+      {
+       char *my_port_name = split_value(&spec);
+       int my_port;
+       char *dest_port_name = split_value(&spec);
+       int dest_port;
+       name_specifier dest_spec;
+       char *dest_device_name = split_value(&spec);
+       device *dest;
+       /* find my name */
+       my_port = device_interrupt_decode(current, my_port_name,
+                                         output_port);
+       /* find the dest device and port */
+       dest = split_fill_path(current, dest_device_name, &dest_spec);
+       dest_port = device_interrupt_decode(dest, dest_port_name,
+                                           input_port);
+       /* connect the two */
+       device_interrupt_attach(current,
+                               my_port,
+                               dest,
+                               dest_port,
+                               permenant_object);
+      }
+      break;
+    default:
+      device_error(current, "unreconised interrupt spec %s\n", spec.value);
+      break;
+    }
+  }
+
+  /* is there a property */
+  if (spec.property != NULL) {
+    if (strcmp(spec.value, "true") == 0)
+      device_add_boolean_property(current, spec.property, 1);
+    else if (strcmp(spec.value, "false") == 0)
+      device_add_boolean_property(current, spec.property, 0);
+    else {
+      const device_property *property;
+      switch (spec.value[0]) {
+      case '*':
+       parse_ihandle_property(current, spec.property, spec.value + 1);
+       break;
+      case '[':
+       {
+         unsigned8 words[1024];
+         char *curr = spec.value + 1;
+         int nr_words = 0;
+         while (1) {
+           char *next;
+           words[nr_words] = H2BE_1(strtoul(curr, &next, 0));
+           if (curr == next)
+             break;
+           curr = next;
+           nr_words += 1;
+         }
+         device_add_array_property(current, spec.property,
+                                   words, sizeof(words[0]) * nr_words);
+       }
+       break;
+      case '"':
+       parse_string_property(current, spec.property, spec.value);
+       break;
+      case '!':
+       spec.value++;
+       property = tree_find_property(current, spec.value);
+       if (property == NULL)
+         device_error(current, "property %s not found\n", spec.value);
+       device_add_duplicate_property(current,
+                                     spec.property,
+                                     property);
+       break;
+      default:
+       if (strcmp(spec.property, "reg") == 0
+           || strcmp(spec.property, "assigned-addresses") == 0
+           || strcmp(spec.property, "alternate-reg") == 0){
+         parse_reg_property(current, spec.property, spec.value);
+       }
+       else if (strcmp(spec.property, "ranges") == 0) {
+         parse_ranges_property(current, spec.property, spec.value);
+       }
+       else if (isdigit(spec.value[0])
+                || (spec.value[0] == '-' && isdigit(spec.value[1]))
+                || (spec.value[0] == '+' && isdigit(spec.value[1]))) {
+         parse_integer_property(current, spec.property, spec.value);
+       }
+       else
+         parse_string_property(current, spec.property, spec.value);
+       break;
+      }
+    }
+  }
+  return current;
+}
+
+
+INLINE_TREE\
+(void)
+tree_traverse(device *root,
+             tree_traverse_function *prefix,
+             tree_traverse_function *postfix,
+             void *data)
+{
+  device *child;
+  if (prefix != NULL)
+    prefix(root, data);
+  for (child = device_child(root);
+       child != NULL;
+       child = device_sibling(child)) {
+    tree_traverse(child, prefix, postfix, data);
+  }
+  if (postfix != NULL)
+    postfix(root, data);
+}
+
+
+STATIC_INLINE_TREE\
+(void)
+print_address(device *bus,
+             const device_unit *phys)
+{
+  char unit[32];
+  device_encode_unit(bus, phys, unit, sizeof(unit));
+  printf_filtered(" %s", unit);
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_size(device *bus,
+          const device_unit *size)
+{
+  int i;
+  for (i = 0; i < size->nr_cells; i++)
+    if (size->cells[i] != 0)
+      break;
+  if (i < size->nr_cells) {
+    printf_filtered(" 0x%lx", (unsigned long)size->cells[i]);
+    i++;
+    for (; i < size->nr_cells; i++)
+      printf_filtered(",0x%lx", (unsigned long)size->cells[i]);
+  }
+  else
+    printf_filtered(" 0");
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_reg_property(device *me,
+                  const device_property *property)
+{
+  int reg_nr;
+  reg_property_spec reg;
+  for (reg_nr = 0;
+       device_find_reg_array_property(me, property->name, reg_nr, &reg);
+       reg_nr++) {
+    print_address(device_parent(me), &reg.address);
+    print_size(me, &reg.size);
+  }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_ranges_property(device *me,
+                     const device_property *property)
+{
+  int range_nr;
+  range_property_spec range;
+  for (range_nr = 0;
+       device_find_range_array_property(me, property->name, range_nr, &range);
+       range_nr++) {
+    print_address(me, &range.child_address);
+    print_address(device_parent(me), &range.parent_address);
+    print_size(me, &range.size);
+  }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_string(const char *string)
+{
+  printf_filtered(" \"");
+  while (*string != '\0') {
+    switch (*string) {
+    case '"':
+      printf_filtered("\\\"");
+      break;
+    case '\\':
+      printf_filtered("\\\\");
+      break;
+    default:
+      printf_filtered("%c", *string);
+      break;
+    }
+    string++;
+  }
+  printf_filtered("\"");
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_string_array_property(device *me,
+                           const device_property *property)
+{
+  int nr;
+  string_property_spec string;
+  for (nr = 0;
+       device_find_string_array_property(me, property->name, nr, &string);
+       nr++) {
+    print_string(string);
+  }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_properties(device *me)
+{
+  const device_property *property;
+  for (property = device_find_property(me, NULL);
+       property != NULL;
+       property = device_next_property(property)) {
+    printf_filtered("%s/%s", device_path(me), property->name);
+    if (property->original != NULL) {
+      printf_filtered(" !");
+      printf_filtered("%s/%s", 
+                     device_path(property->original->owner),
+                     property->original->name);
+    }
+    else {
+      switch (property->type) {
+      case array_property:
+       if ((property->sizeof_array % sizeof(signed_cell)) == 0) {
+         unsigned_cell *w = (unsigned_cell*)property->array;
+         int cell_nr;
+         for (cell_nr = 0;
+              cell_nr < (property->sizeof_array / sizeof(unsigned_cell));
+              cell_nr++) {
+           printf_filtered(" 0x%lx", (unsigned long)BE2H_cell(w[cell_nr]));
+         }
+       }
+       else {
+         unsigned8 *w = (unsigned8*)property->array;
+         printf_filtered(" [");
+         while ((char*)w - (char*)property->array < property->sizeof_array) {
+           printf_filtered(" 0x%2x", BE2H_1(*w));
+           w++;
+         }
+       }
+       break;
+      case boolean_property:
+       {
+         int b = device_find_boolean_property(me, property->name);
+         printf_filtered(" %s", b ? "true"  : "false");
+       }
+       break;
+      case ihandle_property:
+       {
+         if (property->array != NULL) {
+           device_instance *instance = device_find_ihandle_property(me, property->name);
+           printf_filtered(" *%s", device_instance_path(instance));
+         }
+         else {
+           /* not yet initialized, ask the device for the path */
+           ihandle_runtime_property_spec spec;
+           device_find_ihandle_runtime_property(me, property->name, &spec);
+           printf_filtered(" *%s", spec.full_path);
+           if (spec.args != NULL)
+             printf_filtered(":%s", spec.args);
+         }
+       }
+       break;
+      case integer_property:
+       {
+         unsigned_word w = device_find_integer_property(me, property->name);
+         printf_filtered(" 0x%lx", (unsigned long)w);
+       }
+       break;
+      case range_array_property:
+       print_ranges_property(me, property);
+       break;
+      case reg_array_property:
+       print_reg_property(me, property);
+       break;
+      case string_property:
+       {
+         const char *s = device_find_string_property(me, property->name);
+         print_string(s);
+       }
+       break;
+      case string_array_property:
+       print_string_array_property(me, property);
+       break;
+      }
+    }
+    printf_filtered("\n");
+  }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_interrupts(device *me,
+                int my_port,
+                device *dest,
+                int dest_port,
+                void *ignore_or_null)
+{
+  char src[32];
+  char dst[32];
+  device_interrupt_encode(me, my_port, src, sizeof(src), output_port);
+  device_interrupt_encode(dest, dest_port, dst, sizeof(dst), input_port);
+  printf_filtered("%s > %s %s %s\n",
+                 device_path(me),
+                 src, dst,
+                 device_path(dest));
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_device(device *me,
+            void *ignore_or_null)
+{
+  printf_filtered("%s\n", device_path(me));
+  print_properties(me);
+  device_interrupt_traverse(me, print_interrupts, NULL);
+}
+
+INLINE_TREE\
+(void)
+tree_print(device *root)
+{
+  tree_traverse(root,
+               print_device, NULL,
+               NULL);
+}
+
+
+INLINE_TREE\
+(void)
+tree_usage(int verbose)
+{
+  if (verbose == 1) {
+    printf_filtered("\n");
+    printf_filtered("A device/property specifier has the form:\n");
+    printf_filtered("\n");
+    printf_filtered("  /path/to/a/device [ property-value ]\n");
+    printf_filtered("\n");
+    printf_filtered("and a possible device is\n");
+    printf_filtered("\n");
+  }
+  if (verbose > 1) {
+    printf_filtered("\n");
+    printf_filtered("A device/property specifier (<spec>) has the format:\n");
+    printf_filtered("\n");
+    printf_filtered("  <spec> ::= <path> [ <value> ] ;\n");
+    printf_filtered("  <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
+    printf_filtered("  <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
+    printf_filtered("  <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
+    printf_filtered("  <unit> ::= <number> { \",\" <number> } ;\n");
+    printf_filtered("\n");
+    printf_filtered("Where:\n");
+    printf_filtered("\n");
+    printf_filtered("  <name>  is the name of a device (list below)\n");
+    printf_filtered("  <unit>  is the unit-address relative to the parent bus\n");
+    printf_filtered("  <args>  additional arguments used when creating the device\n");
+    printf_filtered("  <value> ::= ( <number> # integer property\n");
+    printf_filtered("              | \"[\" { <number> } # array property (byte)\n");
+    printf_filtered("              | \"{\" { <number> } # array property (cell)\n");
+    printf_filtered("              | [ \"true\" | \"false\" ] # boolean property\n");
+    printf_filtered("              | \"*\" <path> # ihandle property\n");
+    printf_filtered("              | \"!\" <path> # copy property\n");
+    printf_filtered("              | \">\" [ <number> ] <path> # attach interrupt\n");
+    printf_filtered("              | \"<\" <path> # attach child interrupt\n");
+    printf_filtered("              | \"\\\"\" <text> # string property\n");
+    printf_filtered("              | <text> # string property\n");
+    printf_filtered("              ) ;\n");
+    printf_filtered("\n");
+    printf_filtered("And the following are valid device names:\n");
+    printf_filtered("\n");
+  }
+}
+
+
+
+INLINE_TREE\
+(device_instance *)
+tree_instance(device *root,
+             const char *device_specifier)
+{
+  /* find the device node */
+  device *me;
+  name_specifier spec;
+  if (!split_device_specifier(root, device_specifier, &spec))
+    return NULL;
+  me = split_find_device(root, &spec);
+  if (spec.name != NULL)
+    return NULL;
+  /* create the instance */
+  return device_create_instance(me, device_specifier, spec.last_args);
+}
+
+
+INLINE_TREE\
+(device *)
+tree_find_device(device *root,
+                const char *path_to_device)
+{
+  device *node;
+  name_specifier spec;
+
+  /* parse the path */
+  split_device_specifier(root, path_to_device, &spec);
+  if (spec.value != NULL)
+    return NULL; /* something wierd */
+
+  /* now find it */
+  node = split_find_device(root, &spec);
+  if (spec.name != NULL)
+    return NULL; /* not a leaf */
+
+  return node;
+}
+
+
+INLINE_TREE\
+(const device_property *)
+tree_find_property(device *root,
+                  const char *path_to_property)
+{
+  name_specifier spec;
+  if (!split_property_specifier(root, path_to_property, &spec))
+    device_error(root, "Invalid property path %s", path_to_property);
+  root = split_find_device(root, &spec);
+  return device_find_property(root, spec.property);
+}
+
+INLINE_TREE\
+(int)
+tree_find_boolean_property(device *root,
+                          const char *path_to_property)
+{
+  name_specifier spec;
+  if (!split_property_specifier(root, path_to_property, &spec))
+    device_error(root, "Invalid property path %s", path_to_property);
+  root = split_find_device(root, &spec);
+  return device_find_boolean_property(root, spec.property);
+}
+
+INLINE_TREE\
+(signed_cell)
+tree_find_integer_property(device *root,
+                          const char *path_to_property)
+{
+  name_specifier spec;
+  if (!split_property_specifier(root, path_to_property, &spec))
+    device_error(root, "Invalid property path %s", path_to_property);
+  root = split_find_device(root, &spec);
+  return device_find_integer_property(root, spec.property);
+}
+
+INLINE_TREE\
+(device_instance *)
+tree_find_ihandle_property(device *root,
+                          const char *path_to_property)
+{
+  name_specifier spec;
+  if (!split_property_specifier(root, path_to_property, &spec))
+    device_error(root, "Invalid property path %s", path_to_property);
+  root = split_find_device(root, &spec);
+  return device_find_ihandle_property(root, spec.property);
+}
+
+INLINE_TREE\
+(const char *)
+tree_find_string_property(device *root,
+                         const char *path_to_property)
+{
+  name_specifier spec;
+  if (!split_property_specifier(root, path_to_property, &spec))
+    device_error(root, "Invalid property path %s", path_to_property);
+  root = split_find_device(root, &spec);
+  return device_find_string_property(root, spec.property);
+}
+
+
+#endif /* _PARSE_C_ */