From 73c4941b23b9c660bb9bc4bb7acf3ea253356c41 Mon Sep 17 00:00:00 2001
From: Michael Meissner <gnu@the-meissners.org>
Date: Wed, 8 Nov 1995 18:57:06 +0000
Subject: first stage in function unit support; add new switches & latest code
 from andrew

---
 sim/ppc/.Sanitize         |   7 +-
 sim/ppc/ChangeLog         | 129 ++++++++++
 sim/ppc/Makefile.in       |  49 ++--
 sim/ppc/configure         | 127 +++++++---
 sim/ppc/configure.in      |  78 ++++--
 sim/ppc/corefile.c        |   1 -
 sim/ppc/cpu.h             |   4 +
 sim/ppc/debug.c           |   3 +-
 sim/ppc/devices.c         |   1 -
 sim/ppc/emul_generic.c    | 230 +++++++++++++++++
 sim/ppc/emul_netbsd.c     |   1 -
 sim/ppc/filter_filename.c |   3 +-
 sim/ppc/function_unit.c   | 611 ++++++++++++++++++++++++++++++++++++++++++++++
 sim/ppc/function_unit.h   |  71 ++++++
 sim/ppc/inline.c          |  16 +-
 sim/ppc/inline.h          | 155 ++++++++++++
 sim/ppc/main.c            |  21 +-
 sim/ppc/mon.c             |  69 ++++--
 sim/ppc/mon.h             |  76 ++++++
 sim/ppc/ppc-endian.c      |  82 -------
 sim/ppc/ppc-endian.h      | 262 --------------------
 sim/ppc/ppc-instructions  |  48 ++--
 sim/ppc/psim.c            |   3 +-
 sim/ppc/sim-endian-n.h    |  65 +++++
 sim/ppc/sim-endian.c      |  79 ++++++
 sim/ppc/sim_calls.c       |  37 ++-
 sim/ppc/std-config.h      |  54 +++-
 sim/ppc/table.c           |   1 +
 sim/ppc/vm.c              |   4 +-
 sim/ppc/vm_n.h            |   1 -
 30 files changed, 1802 insertions(+), 486 deletions(-)
 create mode 100644 sim/ppc/emul_generic.c
 create mode 100644 sim/ppc/function_unit.c
 create mode 100644 sim/ppc/function_unit.h
 create mode 100644 sim/ppc/inline.h
 create mode 100644 sim/ppc/mon.h
 delete mode 100644 sim/ppc/ppc-endian.c
 delete mode 100644 sim/ppc/ppc-endian.h
 create mode 100644 sim/ppc/sim-endian-n.h
 create mode 100644 sim/ppc/sim-endian.c

(limited to 'sim/ppc')

diff --git a/sim/ppc/.Sanitize b/sim/ppc/.Sanitize
index b5b07fa..f72289b 100644
--- a/sim/ppc/.Sanitize
+++ b/sim/ppc/.Sanitize
@@ -59,6 +59,8 @@ events.c
 events.h
 filter_filename.c
 filter_filename.h
+function_unit.c
+function_unit.h
 idecode_branch.h
 idecode_expression.h
 idecode_fields.h
@@ -77,8 +79,6 @@ mon.h
 os_emul.c
 os_emul.h
 ppc-cache-rules
-ppc-endian.c
-ppc-endian.h
 ppc-instructions
 ppc-opcode-complex
 ppc-opcode-simple
@@ -91,6 +91,9 @@ registers.c
 registers.h
 sim_callbacks.h
 sim_calls.c
+sim-endian.c
+sim-endian.h
+sim-endian-n.h
 spa-reporter.c
 spa-system-calls.c
 spa-system-calls.h
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog
index 3a0f385..60decfd 100644
--- a/sim/ppc/ChangeLog
+++ b/sim/ppc/ChangeLog
@@ -1,3 +1,132 @@
+Wed Nov  8 13:19:47 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+	* Makefile.in ({FUNC,MODEL,WARNING}_CFLAGS): New flags set by
+	configure --enable switches.
+	(CONFIG_CFLAGS): Include FUNC_CFLAGS and MODE_CFLAGS.
+	(.c.o): Include WARNING_CFLAGS.
+	(CPU_H): Include function_unit.h.
+	(LIB_OBJ): Include function_unit.o.
+	(BUILT_SRC_WO_CONFIG): Split from BUILT_SRC and do not include
+	config.h or ppc-config.h.
+	(BUILT_SRC): Include BUILT_SRC_WO_CONFIG, config.h and
+	ppc-config.h.
+	(filter_filename.o): Include config.h/ppc-config.h dependencies.
+	(idecode.o, semantics.o): Specify CC line without WARNING_CFLAGS
+	so that we don't get all of the unused variable warnings that are
+	generated.
+	(function_unit.o): Add rule to build.
+	(main.o, sim_calls.o): Add function_unit.h, itable.h dependencies.
+	(mon.o): Include mon.c dependency.
+	(TAGS): Depend on BUILT_SRC.
+	(clean): Don't delete config.h or ppc-config.h
+
+	* basics.h (sim_callbacks.h): Move include after the include of
+	config.h and ppc-config.h.
+
+	* bits.{h,c} (ROTL32,ROTL64): Move these functions to bits.c.  Add
+	support for BITS_INLINE to inline these.  Add declarations to
+	bits.h.
+
+	* configure.in (--enable-sim-warnings): Add new option to specify
+	compiler warnings for all modules except idecode.o and semantics.o
+	which have lots of unused variables because they are machine
+	generated.
+	(--enable-sim-function-unit): New switch to configure whether
+	function unit support is compiled in or not.
+	(--enable-sim-{,default-}mode): New switches to control which cpu
+	model is used.
+	* configure: Regenerate.
+
+	* corefile.c (core_attach_address_callback): Delete unused
+	variable device_address.
+
+	* cpu.c (struct _cpu): Add function unit pointer field func_unit.
+	(cpu_create): If WITH_FUNCTION_UNIT, call function_unit_create.
+	(cpu_init): If WITH_FUNCTION_UNIT, call function_unit_init.
+	(cpu_halt): If WITH_FUNCTION_UNIT, call function_unit_halt.
+	(cpu_function_unit): New function to return func_unit field.
+
+	* cpu.h (function_unit.h): Include new include file.
+	(cpu_function_unit): Declare.
+
+	* debug.c (stdlib.h): Test HAVE_STDLIB_H, not HAVE_STDLIB.
+	(config.h): Include config.h.
+
+	* devices.c (icu_io_write_buffer_callback): Delete unused variable
+	system.
+
+	* emul_generic.c (emul_exit_call): Print out status value.
+
+	* emul_netbsd.c (do_read): Delete unused variable nr_moved.
+
+	* filter_filename.h (includes): Include config.h, ppc-config.h,
+	not basics.h.
+
+	* inline.c: Include bits.c if BITS_INLINE.  Include
+	function_unit.c if FUNCTION_UNIT_INLINE.
+
+	* inline.h (INLINE_BITS): Define if BITS_INLINE.
+	(INLINE_FUNCTION_UNIT): Define if FUNCTION_UNIT_INLINE.
+
+	* interrupts.c (instruction_storage_interrupt): Delete unused
+	variable nia.
+
+	* lf.h (config.h): Include config.h.
+
+	* main.c (includes): Include function_unit.c.  If HAVE_UNISTD_H,
+	include unistd.h.
+	(usage): Update for -m model, -i, and -I options.
+	(main): Delete unused variables stack_pointer and i.  Add support
+	for -i, -m model arguments.  Call psim_print_info with verbose ==
+	1 if -i, and verbose == 2 if -I.
+
+	* mon.c (stdio.h): Include stdio.h to pick up sprintf prototype.
+	(mon_issue): Call function_unit_issue if function units are
+	supported.
+	(mon_print_info): Take psim * argument.  Print out information
+	from function_unit if available.  Move read/write stats to always
+	print, instead of printing if verbose > 1.  Fix up plural
+	vs. singular usage.
+
+	* mon.h (mon_print_info): Update prototype.
+
+	* psim.c (current_ppc_model): Add global variable.
+	(psim_print_info): Pass system argument to mon_print_info.
+
+	* sim_calls.c (function_unit.h): Include.
+	(sim_open): Add support for -i and -m model options.  If -i call
+	psim_print_info with verbose == 1, if -I, with verbose == 2.
+	(sim_resume): Delete unused variable program_counter.
+
+	* std-config.h (WITH_FUNCTION_UNIT): Define.
+	(ppc_model): Add enumeration giving all PowerPC models currently
+	known about.
+	({WITH,CURRENT}_PPC_MODEL): Define.
+	(FUNCTION_UNIT_INLINE): Define.
+
+	* table.c (config.h): Include config.h.
+
+	* vm.c (om_virtual_to_real): Print pte_word_{0,1} so the compiler
+	doesn't complain that they're unused.
+
+	* vm_n.h (vm_data_map_read_N): Delete unused variable rval.
+	
+Mon Nov  6 23:15:54 1995  Andrew Cagney  <cagney@highland.com.au>
+
+	* sim-endian.c (ppc-endian.c), sim-endian.h (ppc-endian.h):
+        renameed.  These files are target independant.
+	* Makefile.in, basics.h: update for new name.
+
+	* sim-endian.h (SWAP_N), sim-endian.c (_SWAP_1): Rename existing
+        SWAP_<N> to _SWAP_<N> so that sim-endian.h can contain SWAP_N
+        macro's as required.
+
+	* sim-endian.c, sim-endian-n.h (new file): Move endian code into a
+        debugable header file.
+
+	* ppc-instructions (Byte-Reverse): Enable byte reverse
+        instructions using SWAP_N macros.
+
 Mon Nov  6 10:39:28 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
 	* Makefile.in (config.status): Remove references to config.make
diff --git a/sim/ppc/Makefile.in b/sim/ppc/Makefile.in
index e233156..0a12ee7 100644
--- a/sim/ppc/Makefile.in
+++ b/sim/ppc/Makefile.in
@@ -81,6 +81,9 @@ FLOAT_CFLAGS = @sim_float@
 TRACE_CFLAGS = @sim_trace@
 ASSERT_CFLAGS = @sim_assert@
 MONITOR_CFLAGS = @sim_monitor@
+FUNC_CFLAGS = @sim_func@
+MODEL_CFLAGS = @sim_model@ @sim_default_model@
+WARNING_CFLAGS = @sim_warnings@
 CONFIG_CFLAGS = $(BSWAP_CFLAGS) \
   $(ENDIAN_CFLAGS) \
   $(HOSTENDIAN_CFLAGS) \
@@ -93,7 +96,9 @@ CONFIG_CFLAGS = $(BSWAP_CFLAGS) \
   $(FLOAT_CFLAGS) \
   $(TRACE_CFLAGS) \
   $(ASSERT_CFLAGS) \
-  $(MONITOR_CFLAGS)
+  $(MONITOR_CFLAGS) \
+  $(FUNC_CFLAGS) \
+  $(MODEL_CFLAGS)
 
 CONFIG_FILE = @sim_config@
 IGEN_OPCODE_RULES = @sim_opcode@
@@ -122,7 +127,7 @@ TARGETLIB	= libsim.a
 all:	run $(TARGETLIB) $(GDB_OBJ)
 
 .c.o:
-	$(CC) -c $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $<
+	$(CC) -c $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $<
 
 
 
@@ -130,7 +135,7 @@ BASICS_H = \
 	config.h \
 	ppc-config.h \
 	words.h \
-	ppc-endian.h \
+	sim-endian.h \
 	debug.h \
 	filter_filename.h \
 	bits.h \
@@ -163,7 +168,8 @@ CPU_H = \
 	psim.h \
 	icache.h \
 	itable.h \
-	mon.h
+	mon.h \
+	function_unit.h
 
 EMUL_GENERIC_H = \
 	$(CPU_H) \
@@ -176,12 +182,15 @@ INLINE = \
 	inline.h \
 	inline.c
 
-BUILT_SRC = \
+BUILT_SRC_WO_CONFIG = \
 	icache.h \
 	idecode.h idecode.c \
 	semantics.h semantics.c \
 	itable.h itable.c \
-	spreg.h spreg.c \
+	spreg.h spreg.c
+
+BUILT_SRC = \
+	$(BUILT_SRC_WO_CONFIG) \
 	config.h \
 	ppc-config.h 
 
@@ -189,9 +198,13 @@ LIB_SRC = \
 	psim.c \
 	bits.c \
 	debug.c \
-	ppc-endian.c \
+	sim-endian.c \
+	sim-endian.h \
+	sim-endian-n.h \
 	vm.c \
+	vm_n.h \
 	corefile.c \
+	function_unit.c \
 	events.c \
 	os_emul.c \
 	emul_generic.c \
@@ -214,13 +227,14 @@ LIB_OBJ = \
 	debug.o \
 	filter_filename.o \
 	bits.o \
-	ppc-endian.o \
+	sim-endian.o \
 	os_emul.o \
 	emul_generic.o \
 	emul_netbsd.o \
 	registers.o \
 	vm.o \
 	corefile.o \
+	function_unit.o \
 	spreg.o \
 	cpu.o \
 	interrupts.o \
@@ -256,10 +270,9 @@ psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC)
 bits.o: bits.c $(BASICS_H)
 
 debug.o: debug.c $(BASICS_H)
-filter_filename.o: filter_filename.c $(BASICS_H)
+filter_filename.o: filter_filename.c config.h ppc-config.h
 
-ppc-endian.o: ppc-endian.c ppc-endian.h \
-	config.h ppc-config.h words.h sim_callbacks.h
+sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
 
 os_emul.o: os_emul.c $(EMUL_GENERIC_H)
 emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
@@ -272,6 +285,7 @@ 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
+	$(CC) -c $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $<
 
 # double.o: double.c dp-bit.c
 
@@ -280,13 +294,15 @@ vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
 
 corefile.o: corefile.c corefile.h $(BASICS_H) device_tree.h
 
+function_unit.o: function_unit.c $(CPU_H)
+
 events.o: events.c events.h $(BASICS_H) 
 
-sim_calls.o: sim_calls.c $(PSIM_H) ../../gdb/tm.h devices.h
+sim_calls.o: sim_calls.c $(PSIM_H) function_unit.h itable.h ../../gdb/tm.h devices.h
 
 spreg.o: spreg.h spreg.c words.h
 
-main.o: main.c $(PSIM_H)
+main.o: main.c $(PSIM_H) function_unit.h itable.h
 
 devices.o: devices.c devices.h $(BASICS_H) \
 	device_tree.h events.h
@@ -294,10 +310,11 @@ devices.o: devices.c devices.h $(BASICS_H) \
 device_tree.o: device_tree.c device_tree.h devices.h $(BASICS_H)
 
 semantics.o: semantics.c semantics.h $(CPU_H) $(IDECODE_H)
+	$(CC) -c $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $<
 
 itable.o: itable.c itable.h
 
-mon.o: $(CPU_H)
+mon.o: mon.c $(CPU_H)
 
 #
 # Rules to create the built c source code files
@@ -359,11 +376,11 @@ misc.o: misc.h filter_filename.h
 
 tags etags: TAGS
 
-TAGS: tmp-igen tmp-dgen config.h ppc-config.h
+TAGS: $(BUILT_SRC)
 	etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
 
 clean mostlyclean:
-	rm -f tmp-* *.[oas] core psim run igen dgen config.log $(BUILT_SRC)
+	rm -f tmp-* *.[oasi] core psim run igen dgen config.log $(BUILT_SRC_WO_CONFIG)
 
 distclean maintainer-clean realclean: clean
 	rm -f TAGS Makefile config.cache config.status config.h stamp-h
diff --git a/sim/ppc/configure b/sim/ppc/configure
index 7eefa07..9c3b40d 100755
--- a/sim/ppc/configure
+++ b/sim/ppc/configure
@@ -12,52 +12,55 @@ 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-cflags=opts		Extra CFLAGS for use in building simulator"
 ac_help="$ac_help
-  --enable-sim-config=file	Override default config file"
+  --enable-sim-warnings=opts		Extra CFLAGS for turning on compiler warnings"
 ac_help="$ac_help
-  --enable-sim-opcode=which	Override default opcode lookup."
+  --enable-sim-config=file		Override default config file"
 ac_help="$ac_help
-  --enable-sim-switch		Use a switch instead of a table for instruction call."
+  --enable-sim-opcode=which		Override default opcode lookup."
 ac_help="$ac_help
-  --enable-sim-duplicate	Expand (duplicate) semantic functions."
+  --enable-sim-switch			Use a switch instead of a table for instruction call."
 ac_help="$ac_help
-  --enable-sim-filter=rule	Specify filter rules."
+  --enable-sim-duplicate		Expand (duplicate) semantic functions."
 ac_help="$ac_help
-  --enable-sim-icache=size	Specify instruction cache size."
+  --enable-sim-filter=rule		Specify filter rules."
 ac_help="$ac_help
-  --enable-sim-inline=inlines	Specify which functions should be inlined."
+  --enable-sim-icache=size		Specify instruction cache size."
 ac_help="$ac_help
-  --enable-sim-bswap		Use the BSWAP instruction on Intel 486s and Pentiums."
+  --enable-sim-inline=inlines		Specify which functions should be inlined."
 ac_help="$ac_help
-  --enable-sim-endian=endian	Specify target byte endian orientation."
+  --enable-sim-bswap			Use the BSWAP instruction on Intel 486s and Pentiums."
 ac_help="$ac_help
-  --enable-sim-hostendain=end	Specify host byte endian orientation."
+  --enable-sim-endian=endian		Specify target byte endian orientation."
 ac_help="$ac_help
-  --enable-sim-smp=n		Specify number of processors to configure for."
+  --enable-sim-hostendain=end		Specify host byte endian orientation."
 ac_help="$ac_help
-  --enable-sim-bitsize=n	Specify target bitsize (32 or 64)."
+  --enable-sim-smp=n			Specify number of processors to configure for."
 ac_help="$ac_help
-  --enable-sim-hostbitsize=n	Specify host bitsize (32 or 64)."
+  --enable-sim-bitsize=n		Specify target bitsize (32 or 64)."
 ac_help="$ac_help
-  --enable-sim-env=env		Specify target environment (operating, virtual, user)."
+  --enable-sim-hostbitsize=n		Specify host bitsize (32 or 64)."
 ac_help="$ac_help
-  --enable-sim-timebase	Specify whether the PPC timebase is supported."
+  --enable-sim-env=env			Specify target environment (operating, virtual, user)."
 ac_help="$ac_help
-  --enable-sim-alignment=align	Specify strict or nonstrict alignment.
-case "${enableval}" in
-  yes | strict | STRICT)	sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
-  no | nonstrict | NONSTRICT)	sim_alignment="-DWITH_ALIGNMENT=NOSTRICT_ALIGNMENT";;
-  *)				sim_alignment="-DWITH_ALIGNMENT=$enableval";;
-esac"
+  --enable-sim-timebase			Specify whether the PPC timebase is supported."
+ac_help="$ac_help
+  --enable-sim-alignment=align		Specify strict or nonstrict alignment."
+ac_help="$ac_help
+  --enable-sim-trace			Specify whether tracing is supported."
+ac_help="$ac_help
+  --enable-sim-assert			Specify whether to perform random assertions."
 ac_help="$ac_help
-  --enable-sim-trace		Specify whether tracing is supported."
+  --enable-sim-float			Specify whether to use host floating point or simulate."
 ac_help="$ac_help
-  --enable-sim-assert		Specify whether to perform random assertions."
+  --enable-sim-monitor=mon		Specify whether to enable monitoring events."
 ac_help="$ac_help
-  --enable-sim-float		Specify whether to use host floating point or simulate."
+  --enable-sim-function-unit		Specify whether detailed functional unit support is built."
 ac_help="$ac_help
-  --enable-sim-monitor=mon	Specify whether to enable monitoring events."
+  --enable-sim-model=which		Specify PowerPC to model."
+ac_help="$ac_help
+  --enable-sim-default-model=which	Specify default PowerPC to model."
 
 # Initialize some variables set by options.
 # The variables have the same names as the options, with
@@ -458,6 +461,18 @@ else
   sim_cflags=""
 fi
 
+# Check whether --enable-sim-warnings or --disable-sim-warnings was given.
+enableval="$enable_sim_warnings"
+if test -n "$enableval"; then
+  case "${enableval}" in
+  yes)	sim_warnings="-Wall";;
+  no)	sim_warnings="-w";;
+  *)	sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac
+else
+  sim_warnings=""
+fi
+
 # Check whether --enable-sim-config or --disable-sim-config was given.
 enableval="$enable_sim_config"
 if test -n "$enableval"; then
@@ -661,6 +676,12 @@ fi
 # Check whether --enable-sim-alignment or --disable-sim-alignment was given.
 enableval="$enable_sim_alignment"
 if test -n "$enableval"; then
+  case "${enableval}" in
+  yes | strict | STRICT)	sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
+  no | nonstrict | NONSTRICT)	sim_alignment="-DWITH_ALIGNMENT=NOSTRICT_ALIGNMENT";;
+  *)				sim_alignment="-DWITH_ALIGNMENT=$enableval";;
+esac
+else
   sim_alignment=""
 fi
 
@@ -714,6 +735,42 @@ else
   sim_float=""
 fi
 
+# Check whether --enable-sim-function-unit or --disable-sim-function-unit was given.
+enableval="$enable_sim_function_unit"
+if test -n "$enableval"; then
+  case "${enableval}" in
+  yes)	sim_func="-DWITH_FUNCTION_UNIT=1";;
+  no)	sim_func="-DWITH_FUNCTION_UNIT=0";;
+  *)	sim_func="";;
+esac
+else
+  sim_func=""
+fi
+
+# Check whether --enable-sim-model or --disable-sim-model was given.
+enableval="$enable_sim_model"
+if test -n "$enableval"; then
+  case "${enableval}" in
+  yes)	sim_model="";;
+  no)	sim_model="";;
+  *)	sim_model="-DWITH_PPC_MODEL=${enableval}";;
+esac
+else
+  sim_model=""
+fi
+
+# Check whether --enable-sim-default-model or --disable-sim-default-model was given.
+enableval="$enable_sim_default_model"
+if test -n "$enableval"; then
+  case "${enableval}" in
+  yes)	sim_default_model="";;
+  no)	sim_default_model="";;
+  *)	sim_default_model="-DWITH_DEFAULT_PPC_MODEL=${enableval}";;
+esac
+else
+  sim_model=""
+fi
+
 
 
 ac_aux_dir=
@@ -968,6 +1025,10 @@ fi
 
 
 
+
+
+
+
 for ac_func in getrusage
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
@@ -975,7 +1036,7 @@ 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 979 "configure"
+#line 1040 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1030,7 +1091,7 @@ else
   ac_cv_c_cross=yes
 else
 cat > conftest.$ac_ext <<EOF
-#line 1034 "configure"
+#line 1095 "configure"
 #include "confdefs.h"
 main(){return(0);}
 EOF
@@ -1068,7 +1129,7 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1072 "configure"
+#line 1133 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -1082,7 +1143,7 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1086 "configure"
+#line 1147 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
@@ -1115,7 +1176,7 @@ 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 1119 "configure"
+#line 1180 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
@@ -1266,6 +1327,7 @@ s%@HDEFINES@%$HDEFINES%g
 s%@AR@%$AR%g
 s%@RANLIB@%$RANLIB%g
 s%@sim_cflags@%$sim_cflags%g
+s%@sim_warnings@%$sim_warnings%g
 s%@sim_config@%$sim_config%g
 s%@sim_opcode@%$sim_opcode%g
 s%@sim_switch@%$sim_switch%g
@@ -1286,6 +1348,9 @@ s%@sim_float@%$sim_float%g
 s%@sim_trace@%$sim_trace%g
 s%@sim_assert@%$sim_assert%g
 s%@sim_monitor@%$sim_monitor%g
+s%@sim_func@%$sim_func%g
+s%@sim_model@%$sim_model%g
+s%@sim_default_model@%$sim_default_model%g
 s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g
 s%@CPP@%$CPP%g
 
diff --git a/sim/ppc/configure.in b/sim/ppc/configure.in
index 43761d8..4ebcefb 100644
--- a/sim/ppc/configure.in
+++ b/sim/ppc/configure.in
@@ -3,15 +3,23 @@ AC_PREREQ(2.3)dnl
 AC_INIT(Makefile.in)
 
 AC_ARG_ENABLE(sim-cflags,
-[  --enable-sim-cflags=opts	Extra CFLAGS for use in building simulator],
+[  --enable-sim-cflags=opts		Extra CFLAGS for use in building simulator],
 [case "${enableval}" in
   yes)	sim_cflags="-O2 -fomit-frame-pointer";;
   no)	sim_cflags="";;
   *)	sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;;
 esac],[sim_cflags=""])dnl
 
+AC_ARG_ENABLE(sim-warnings,
+[  --enable-sim-warnings=opts		Extra CFLAGS for turning on compiler warnings except for idecode.o and semantics.o],
+[case "${enableval}" in
+  yes)	sim_warnings="-Wall";;
+  no)	sim_warnings="-w";;
+  *)	sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
+esac],[sim_warnings=""])dnl
+
 AC_ARG_ENABLE(sim-config,
-[  --enable-sim-config=file	Override default config file],
+[  --enable-sim-config=file		Override default config file],
 [case "${enableval}" in
   yes)	sim_config="std-config.h";;
   no)	sim_config="std-config.h";;
@@ -19,7 +27,7 @@ AC_ARG_ENABLE(sim-config,
 esac],[sim_config="std-config.h]")dnl
 
 AC_ARG_ENABLE(sim-opcode,
-[  --enable-sim-opcode=which	Override default opcode lookup.],
+[  --enable-sim-opcode=which		Override default opcode lookup.],
 [case "${enableval}" in
   yes)	sim_opcode="ppc-opcode-simple";;
   no)	sim_opcode="ppc-opcode-simple";;
@@ -27,35 +35,35 @@ AC_ARG_ENABLE(sim-opcode,
 esac],[sim_opcode="ppc-opcode-simple"])dnl
 
 AC_ARG_ENABLE(sim-switch,
-[  --enable-sim-switch		Use a switch instead of a table for instruction call.],
+[  --enable-sim-switch			Use a switch instead of a table for instruction call.],
 [case "${enableval}" in
   yes)	sim_switch="-s";;
   *)	sim_switch="";;
 esac],[sim_switch=""])dnl
 
 AC_ARG_ENABLE(sim-duplicate,
-[  --enable-sim-duplicate	Expand (duplicate) semantic functions.],
+[  --enable-sim-duplicate		Expand (duplicate) semantic functions.],
 [case "${enableval}" in
    yes)	sim_dup="-e";;
    *)	sim_dup="";;
 esac],[sim_dup=""])dnl
 
 AC_ARG_ENABLE(sim-filter,
-[  --enable-sim-filter=rule	Specify filter rules.],
+[  --enable-sim-filter=rule		Specify filter rules.],
 [case "${enableval}" in
    yes)	sim_filter="";;
    *)	sim_filter="-f $enableval";;
 esac],[sim_filter="-f 64"])dnl
 
 AC_ARG_ENABLE(sim-icache,
-[  --enable-sim-icache=size	Specify instruction cache size.],
+[  --enable-sim-icache=size		Specify instruction cache size.],
 [case "${enableval}" in
    yes)	sim_icache="-r 1024";;
    *)	sim_icache="";;
 esac],[sim_icache=""])dnl
 
 AC_ARG_ENABLE(sim-inline,
-[  --enable-sim-inline=inlines	Specify which functions should be inlined.],
+[  --enable-sim-inline=inlines		Specify which functions should be inlined.],
 [sim_inline=""
 case "$enableval" in
   no)		sim_inline="";;
@@ -79,7 +87,7 @@ case "$enableval" in
 esac],[sim_inline=""])dnl
 
 AC_ARG_ENABLE(sim-bswap,
-[  --enable-sim-bswap		Use the BSWAP instruction on Intel 486s and Pentiums.],
+[  --enable-sim-bswap			Use the BSWAP instruction on Intel 486s and Pentiums.],
 [case "${enableval}" in
   yes)	sim_bswap="-DWITH_BSWAP=1";;
   no)	sim_bswap="-DWITH_BSWAP=0";;
@@ -87,7 +95,7 @@ AC_ARG_ENABLE(sim-bswap,
 esac],[sim_bswap=""])dnl
 
 AC_ARG_ENABLE(sim-endian,
-[  --enable-sim-endian=endian	Specify target byte endian orientation.],
+[  --enable-sim-endian=endian		Specify target byte endian orientation.],
 [case "${enableval}" in
   yes)	case "$target" in
 	  *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
@@ -101,7 +109,7 @@ AC_ARG_ENABLE(sim-endian,
 esac],[sim_endian=""])dnl
 
 AC_ARG_ENABLE(sim-hostendian,
-[  --enable-sim-hostendain=end	Specify host byte endian orientation.],
+[  --enable-sim-hostendain=end		Specify host byte endian orientation.],
 [case "${enableval}" in
   no)	 sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";;
   b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";;
@@ -110,7 +118,7 @@ AC_ARG_ENABLE(sim-hostendian,
 esac],[sim_hostendian=""])dnl
 
 AC_ARG_ENABLE(sim-smp,
-[  --enable-sim-smp=n		Specify number of processors to configure for.],
+[  --enable-sim-smp=n			Specify number of processors to configure for.],
 [case "${enableval}" in
   yes)	sim_smp="-DWITH_SMP=2";;
   no)	sim_smp="-DWITH_SMP=0";;
@@ -118,7 +126,7 @@ AC_ARG_ENABLE(sim-smp,
 esac],[sim_smp=""])dnl
 
 AC_ARG_ENABLE(sim-bitsize,
-[  --enable-sim-bitsize=n	Specify target bitsize (32 or 64).],
+[  --enable-sim-bitsize=n		Specify target bitsize (32 or 64).],
 [case "${enableval}" in
   yes)	sim_bitsize="";;
   no)	sim_bitsize="";;
@@ -126,7 +134,7 @@ AC_ARG_ENABLE(sim-bitsize,
 esac],[sim_bitsize=""])dnl
 
 AC_ARG_ENABLE(sim-hostbitsize,
-[  --enable-sim-hostbitsize=n	Specify host bitsize (32 or 64).],
+[  --enable-sim-hostbitsize=n		Specify host bitsize (32 or 64).],
 [case "${enableval}" in
   yes)	sim_hostbitsize="";;
   no)	sim_hostbitsize="";;
@@ -134,7 +142,7 @@ AC_ARG_ENABLE(sim-hostbitsize,
 esac],[sim_hostbitsize=""])dnl
 
 AC_ARG_ENABLE(sim-env,
-[  --enable-sim-env=env		Specify target environment (operating, virtual, user).],
+[  --enable-sim-env=env			Specify target environment (operating, virtual, user).],
 [case "${enableval}" in
   operating | os | oea)	sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
   virtual | vea)	sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
@@ -143,7 +151,7 @@ AC_ARG_ENABLE(sim-env,
 esac],[sim_env=""])dnl
 
 AC_ARG_ENABLE(sim-timebase,
-[  --enable-sim-timebase	Specify whether the PPC timebase is supported.],
+[  --enable-sim-timebase			Specify whether the PPC timebase is supported.],
 [case "${enableval}" in
   yes)	sim_timebase="-DWITH_TIME_BASE=1";;
   no)	sim_timebase="-DWITH_TIME_BASE=0";;
@@ -151,7 +159,7 @@ AC_ARG_ENABLE(sim-timebase,
 esac],[sim_timebase=""])dnl
 
 AC_ARG_ENABLE(sim-alignment,
-[  --enable-sim-alignment=align	Specify strict or nonstrict alignment.]
+[  --enable-sim-alignment=align		Specify strict or nonstrict alignment.],
 [case "${enableval}" in
   yes | strict | STRICT)	sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
   no | nonstrict | NONSTRICT)	sim_alignment="-DWITH_ALIGNMENT=NOSTRICT_ALIGNMENT";;
@@ -159,7 +167,7 @@ AC_ARG_ENABLE(sim-alignment,
 esac],[sim_alignment=""])dnl
 
 AC_ARG_ENABLE(sim-trace,
-[  --enable-sim-trace		Specify whether tracing is supported.],
+[  --enable-sim-trace			Specify whether tracing is supported.],
 [case "${enableval}" in
   yes)	sim_trace="-DWITH_TRACE=1";;
   no)	sim_trace="-DWITH_TRACE=0";;
@@ -167,7 +175,7 @@ AC_ARG_ENABLE(sim-trace,
 esac],[sim_trace=""])dnl
 
 AC_ARG_ENABLE(sim-assert,
-[  --enable-sim-assert		Specify whether to perform random assertions.],
+[  --enable-sim-assert			Specify whether to perform random assertions.],
 [case "${enableval}" in
   yes)	sim_assert="-DWITH_ASSERT=1";;
   no)	sim_assert="-DWITH_ASSERT=0";;
@@ -175,7 +183,7 @@ AC_ARG_ENABLE(sim-assert,
 esac],[sim_assert=""])dnl
 
 AC_ARG_ENABLE(sim-float,
-[  --enable-sim-float		Specify whether to use host floating point or simulate.],
+[  --enable-sim-float			Specify whether to use host floating point or simulate.],
 [case "${enableval}" in
   yes | hard)	sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
   no | soft)	sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
@@ -183,7 +191,7 @@ AC_ARG_ENABLE(sim-float,
 esac],[sim_float=""])dnl
 
 AC_ARG_ENABLE(sim-monitor,
-[  --enable-sim-monitor=mon	Specify whether to enable monitoring events.],
+[  --enable-sim-monitor=mon		Specify whether to enable monitoring events.],
 [case "${enableval}" in
   yes)		sim_mon="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
   no)		sim_mon="-DWITH_MON=0";;
@@ -192,6 +200,30 @@ AC_ARG_ENABLE(sim-monitor,
   *)		sim_mon="-DWITH_MON='$enableval'";;
 esac],[sim_float=""])dnl
 
+AC_ARG_ENABLE(sim-function-unit,
+[  --enable-sim-function-unit		Specify whether detailed functional unit support is built.],
+[case "${enableval}" in
+  yes)	sim_func="-DWITH_FUNCTION_UNIT=1";;
+  no)	sim_func="-DWITH_FUNCTION_UNIT=0";;
+  *)	sim_func="";;
+esac],[sim_func=""])dnl
+
+AC_ARG_ENABLE(sim-model,
+[  --enable-sim-model=which		Specify PowerPC to model.],
+[case "${enableval}" in
+  yes)	sim_model="";;
+  no)	sim_model="";;
+  *)	sim_model="-DWITH_PPC_MODEL=${enableval}";;
+esac],[sim_model=""])dnl
+
+AC_ARG_ENABLE(sim-default-model,
+[  --enable-sim-default-model=which	Specify default PowerPC to model.],
+[case "${enableval}" in
+  yes)	sim_default_model="";;
+  no)	sim_default_model="";;
+  *)	sim_default_model="-DWITH_DEFAULT_PPC_MODEL=${enableval}";;
+esac],[sim_model=""])dnl
+
 AC_CONFIG_HEADER(config.h:config.in)
 
 AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
@@ -207,6 +239,7 @@ AR=${AR-ar}
 AC_SUBST(AR)
 AC_PROG_RANLIB
 AC_SUBST(sim_cflags)
+AC_SUBST(sim_warnings)
 AC_SUBST(sim_config)
 AC_SUBST(sim_opcode)
 AC_SUBST(sim_switch)
@@ -227,6 +260,9 @@ AC_SUBST(sim_float)
 AC_SUBST(sim_trace)
 AC_SUBST(sim_assert)
 AC_SUBST(sim_monitor)
+AC_SUBST(sim_func)
+AC_SUBST(sim_model)
+AC_SUBST(sim_default_model)
 
 AC_CHECK_FUNCS(getrusage)
 
diff --git a/sim/ppc/corefile.c b/sim/ppc/corefile.c
index 1c67357..c112a63 100644
--- a/sim/ppc/corefile.c
+++ b/sim/ppc/corefile.c
@@ -398,7 +398,6 @@ core_attach_address_callback(const device *me,
 			     const device *who) /*callback/default*/
 {
   core *memory = (core*)me->data;
-  unsigned_word device_address;
   DTRACE_ATTACH_ADDRESS(core);
   if (space != 0)
     error("core_attach_address_callback() invalid address space\n");
diff --git a/sim/ppc/cpu.h b/sim/ppc/cpu.h
index 82290f6..a89f7b9 100644
--- a/sim/ppc/cpu.h
+++ b/sim/ppc/cpu.h
@@ -37,6 +37,7 @@
 #include "icache.h"
 #include "itable.h"
 #include "mon.h"
+#include "function_unit.h"
 
 
 /* typedef struct _cpu cpu;
@@ -176,6 +177,9 @@ INLINE_CPU registers *cpu_registers
 INLINE_CPU void cpu_synchronize_context
 (cpu *processor);
 
+INLINE_CPU function_unit *cpu_function_unit
+(cpu *processor);
+
 #define IS_PROBLEM_STATE(PROCESSOR) \
 (CURRENT_ENVIRONMENT == OPERATING_ENVIRONMENT \
  ? (cpu_registers(PROCESSOR)->msr & msr_problem_state) \
diff --git a/sim/ppc/debug.c b/sim/ppc/debug.c
index e8c054f..c77b51f 100644
--- a/sim/ppc/debug.c
+++ b/sim/ppc/debug.c
@@ -22,9 +22,10 @@
 #ifndef _DEBUG_C_
 #define _DEBUG_C_
 
+#include "config.h"
 #include "basics.h"
 
-#ifdef HAVE_STDLIB
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
diff --git a/sim/ppc/devices.c b/sim/ppc/devices.c
index 46a3eec..b0368d5 100644
--- a/sim/ppc/devices.c
+++ b/sim/ppc/devices.c
@@ -544,7 +544,6 @@ icu_io_write_buffer_callback(const device *me,
 			     cpu *processor,
 			     unsigned_word cia)
 {
-  psim *system = cpu_system(processor);
   unsigned_1 val = H2T_1(*(unsigned_1*)source);
   DTRACE_IO_WRITE_BUFFER(icu);
   /* tell the parent device that the interrupt lines have changed.
diff --git a/sim/ppc/emul_generic.c b/sim/ppc/emul_generic.c
new file mode 100644
index 0000000..f764205
--- /dev/null
+++ b/sim/ppc/emul_generic.c
@@ -0,0 +1,230 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    ----
+
+    Code to output system call traces Copyright (C) 1991 Gordon Irlam.
+    All rights reserved.
+
+    This tool is part of the Spa(7) package.  The Spa(7) package
+    may  be redistributed and/or modified under the terms of the
+    GNU General Public License Version 2 (GPL(7))  as  published
+    by the Free Software Foundation.
+
+    */
+
+
+#ifndef _EMUL_GENERIC_C_
+#define _EMUL_GENERIC_C_
+
+#include "emul_generic.h"
+
+#ifndef STATIC_INLINE_EMUL_GENERIC
+#define STATIC_INLINE_EMUL_GENERIC STATIC_INLINE
+#endif
+
+
+INLINE_EMUL_GENERIC void
+emul_enter_call(emulation *emul,
+		int call,
+		int arg0,
+		cpu *processor,
+		unsigned_word cia)
+{
+  printf_filtered("%d:0x%x:%s(",
+		  cpu_nr(processor) + 1,
+		  cia, 
+		  emul->call_descriptor[call].name);
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_exit_call(emulation *emul,
+	       int call,
+	       int arg0,
+	       cpu *processor,
+	       unsigned_word cia)
+{
+  int status = cpu_registers(processor)->gpr[3];
+  int error = cpu_registers(processor)->gpr[0];
+  printf_filtered(")=%d", status);
+  if (error > 0 && error < emul->nr_error_names)
+    printf_filtered("[%s]",
+		    emul->error_names[cpu_registers(processor)->gpr[0]]);
+  printf_filtered("\n");
+}
+
+
+INLINE_EMUL_GENERIC unsigned64
+emul_read_gpr64(cpu *processor,
+		int g)
+{
+  unsigned32 hi;
+  unsigned32 lo;
+  if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+    hi = cpu_registers(processor)->gpr[g];
+    lo = cpu_registers(processor)->gpr[g+1];
+  }
+  else {
+    lo = cpu_registers(processor)->gpr[g];
+    hi = cpu_registers(processor)->gpr[g+1];
+  }
+  return (INSERTED64(hi, 0, 31) | INSERTED64(lo, 32, 63));
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write_gpr64(cpu *processor,
+		 int g,
+		 unsigned64 val)
+{
+  unsigned32 hi = EXTRACTED64(val, 0, 31);
+  unsigned32 lo = EXTRACTED64(val, 32, 63);
+  if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) {
+    cpu_registers(processor)->gpr[g] = hi;
+    cpu_registers(processor)->gpr[g+1] = lo;
+  }
+  else {
+    cpu_registers(processor)->gpr[g] = lo;
+    cpu_registers(processor)->gpr[g+1] = hi;
+  }
+}
+
+
+INLINE_EMUL_GENERIC char *
+emul_read_string(char *dest,
+		 unsigned_word addr,
+		 unsigned nr_bytes,
+		 cpu *processor,
+		 unsigned_word cia)
+{
+  unsigned nr_moved = 0;
+  if (addr == 0)
+    return NULL;
+  while (1) {
+    if (vm_data_map_read_buffer(cpu_data_map(processor),
+				&dest[nr_moved],
+				addr + nr_moved,
+				sizeof(dest[nr_moved]))
+	!= sizeof(dest[nr_moved]))
+      return NULL;
+    if (dest[nr_moved] == '\0' || nr_moved >= nr_bytes)
+      break;
+    nr_moved++;
+  }
+  dest[nr_moved] = '\0';
+  return dest;
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write_status(cpu *processor,
+		  int status,
+		  int errno)
+{
+  cpu_registers(processor)->gpr[3] = status;
+  if (status < 0)
+    cpu_registers(processor)->gpr[0] = errno;
+  else
+    cpu_registers(processor)->gpr[0] = 0;
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write_word(unsigned_word addr,
+		unsigned_word buf,
+		cpu *processor,
+		unsigned_word cia)
+{
+  int nr_moved;
+  H2T(buf);
+  nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
+				      &buf,
+				      addr,
+				      sizeof(buf),
+				      0/*violate_ro*/);
+  if (nr_moved != sizeof(buf)) {
+    printf_filtered("emul_write_word() write failed, %d out of %d written\n",
+		    nr_moved, sizeof(buf));
+    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+  }
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write_buffer(const void *source,
+		  unsigned_word addr,
+		  unsigned nr_bytes,
+		  cpu *processor,
+		  unsigned_word cia)
+{
+  int nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
+					  source,
+					  addr,
+					  nr_bytes,
+					  0/*violate_ro*/);
+  if (nr_moved != nr_bytes) {
+    printf_filtered("emul_write_buffer() write failed %d out of %d written\n",
+		    nr_moved, nr_bytes);
+    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+  }
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_read_buffer(void *dest,
+		 unsigned_word addr,
+		 unsigned nr_bytes,
+		 cpu *processor,
+		 unsigned_word cia)
+{
+  int nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
+					 dest,
+					 addr,
+					 nr_bytes);
+  if (nr_moved != nr_bytes) {
+    printf_filtered("emul_read_buffer() read failed %d out of %d read\n",
+		    nr_moved, nr_bytes);
+    cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+  }
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_do_call(emulation *emul,
+	     unsigned call,
+	     const int arg0,
+	     cpu *processor,
+	     unsigned_word cia)
+{
+  emul_call_handler *handler = NULL;
+  if (call >= emul->nr_system_calls)
+    error("do_call() os_emul call %d out-of-range\n", call);
+
+  handler = emul->call_descriptor[call].handler;
+  if (handler == NULL)
+    error("do_call() unimplemented call %d\n", call);
+
+  ENTER_CALL;
+  cpu_registers(processor)->gpr[0] = 0; /* default success */
+  handler(emul, call, arg0, processor, cia);
+  EXIT_CALL;
+}
+
+
+#endif /* _SYSTEM_C_ */
diff --git a/sim/ppc/emul_netbsd.c b/sim/ppc/emul_netbsd.c
index 1a05f0a..ac2cd80 100644
--- a/sim/ppc/emul_netbsd.c
+++ b/sim/ppc/emul_netbsd.c
@@ -248,7 +248,6 @@ do_read(emulation *emul,
   unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
   int nbytes = cpu_registers(processor)->gpr[arg0+2];
   int status;
-  int nr_moved;
   SYS(read);
   
   if (WITH_TRACE && ppc_trace[trace_os_emul])
diff --git a/sim/ppc/filter_filename.c b/sim/ppc/filter_filename.c
index 72923b9..ecbde5c 100644
--- a/sim/ppc/filter_filename.c
+++ b/sim/ppc/filter_filename.c
@@ -18,7 +18,8 @@
  
     */
 
-#include "basics.h"
+#include "config.h"
+#include "ppc-config.h"
 
 /* Shorten traces by eliminating the directory component to filenames.  */
 extern char *
diff --git a/sim/ppc/function_unit.c b/sim/ppc/function_unit.c
new file mode 100644
index 0000000..7793c7b
--- /dev/null
+++ b/sim/ppc/function_unit.c
@@ -0,0 +1,611 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+    */
+
+
+#ifndef _FUNCTION_UNIT_C_
+#define _FUNCTION_UNIT_C_
+
+#ifndef STATIC_INLINE_FUNCTION_UNIT
+#define STATIC_INLINE_FUNCTION_UNIT STATIC_INLINE
+#endif
+
+
+#include "basics.h"
+#include "cpu.h"
+#include "function_unit.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+typedef enum _unit_index {
+  UNIT_UNKNOWN,				/* unknown functional unit */
+  UNIT_INT,				/* integer functional unit */
+  UNIT_SINT,				/* integer or SRU functional unit */
+  UNIT_CINT,				/* complex integer functional unit */
+  UNIT_FPU,				/* floating point functional unit */
+  UNIT_MEM,				/* memory functional unit */
+  UNIT_BRANCH,				/* branch functional unit */
+  UNIT_SREG,				/* system register functional unit */
+  NR_UNITS
+} unit_index;
+
+static const char *unit_names[] = {
+  "unknown functional unit instruction",		/* UNIT_UNKNOWN */
+  "int functional unit instruction",			/* UNIT_INT */
+  "int or SRU functional unit instruction",		/* UNIT_SINT */
+  "complex int functional unit instruction",		/* UNIT_CINT */
+  "floating point functional unit instruction",		/* UNIT_FPU */
+  "memory function unit instruction",			/* UNIT_MEM */
+  "branch functional unit instruction",			/* UNIT_BRANCH */
+  "system register functional unit instruction",	/* UNIT_SREG */
+};
+
+typedef struct _timing {
+  itable_index index;					/* instruction # */
+  unit_index unit;					/* functional unit */
+  int cycles;						/* # cycles */
+  unsigned flags;					/* random other flags */
+} timing;
+
+struct _function_unit {
+  unsigned_word old_program_counter;
+  unsigned nr_branches;
+  unsigned nr_stalls;
+  unsigned nr_units[ (int)NR_UNITS ];
+  struct {
+    unit_index unit;
+    int cycles;
+    unsigned flags;
+  } time[ (int)nr_itable_entries ];
+};
+
+/* Flags used in timing info */
+
+#define LOAD	0x00000001				/* this is a load */
+#define	STORE	0x00000002				/* this is a store */
+
+
+/* 603 timings */
+static timing time_603[] = {
+  /* Instruction index							Function unit	Cycles	Flags */
+  { itable_AND,								UNIT_INT,	1,	0 },
+  { itable_AND_Immediate,						UNIT_INT,	1,	0 },
+  { itable_AND_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { itable_AND_with_Complement,						UNIT_INT,	1,	0 },
+  { itable_Add,								UNIT_SINT,	1,	0 },
+  { itable_Add_Carrying,						UNIT_INT,	1,	0 },
+  { itable_Add_Extended,						UNIT_INT,	1,	0 },
+  { itable_Add_Immediate,						UNIT_SINT,	1,	0 },
+  { itable_Add_Immediate_Carrying,					UNIT_INT,	1,	0 },
+  { itable_Add_Immediate_Carrying_and_Record,				UNIT_INT,	1,	0 },
+  { itable_Add_Immediate_Shifted,					UNIT_SINT,	1,	0 },
+  { itable_Add_to_Minus_One_Extended,					UNIT_INT,	1,	0 },
+  { itable_Add_to_Zero_Extended,					UNIT_INT,	1,	0 },
+  { itable_Branch,							UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional,						UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional_to_Count_Register,			UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional_to_Link_Register,				UNIT_BRANCH,	1,	0 },
+  { itable_Compare,							UNIT_SINT,	1,	0 },
+  { itable_Compare_Immediate,						UNIT_SINT,	1,	0 },
+  { itable_Compare_Logical,						UNIT_SINT,	1,	0 },
+  { itable_Compare_Logical_Immediate,					UNIT_SINT,	1,	0 },
+  { itable_Condition_Register_AND,					UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_AND_with_Complement,			UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_Equivalent,				UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_NAND,					UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_NOR,					UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_OR,					UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_OR_with_Complement,			UNIT_SREG,	1,	0 },
+  { itable_Condition_Register_XOR,					UNIT_SREG,	1,	0 },
+  { itable_Count_Leading_Zeros_Word,					UNIT_INT,	1,	0 },
+  { itable_Data_Cache_Block_Flush,					UNIT_MEM,	5,	0 },
+  { itable_Data_Cache_Block_Invalidate,					UNIT_MEM,	2,	0 },
+  { itable_Data_Cache_Block_Store,					UNIT_MEM,	5,	0 },
+  { itable_Data_Cache_Block_Touch,					UNIT_MEM,	2,	0 },
+  { itable_Data_Cache_Block_Touch_for_Store,				UNIT_MEM,	2,	0 },
+  { itable_Data_Cache_Block_set_to_Zero,				UNIT_MEM,	10,	0 },
+  { itable_Divide_Word,							UNIT_INT,	37,	0 },
+  { itable_Divide_Word_Unsigned,					UNIT_INT,	37,	0 },
+  { itable_Enforce_Inorder_Execution_of_IO,				UNIT_SREG,	1,	0 },
+  { itable_Equivalent,							UNIT_INT,	1,	0 },
+  { itable_Extend_Sign_Byte,						UNIT_INT,	1,	0 },
+  { itable_Extend_Sign_Half_Word,					UNIT_INT,	1,	0 },
+  { itable_External_Control_In_Word_Indexed,				UNIT_MEM,	2,	0 },
+  { itable_External_Control_Out_Word_Indexed,				UNIT_MEM,	2,	0 },
+  { itable_Floating_Absolute_Value,					UNIT_FPU,	1,	0 },
+  { itable_Floating_Add,						UNIT_FPU,	1,	0 },
+  { itable_Floating_Add_Single,						UNIT_FPU,	1,	0 },
+  { itable_Floating_Compare_Ordered,					UNIT_FPU,	1,	0 },
+  { itable_Floating_Compare_Unordered,					UNIT_FPU,	1,	0 },
+  { itable_Floating_Convert_To_Integer_Word,				UNIT_FPU,	1,	0 },
+  { itable_Floating_Convert_To_Integer_Word_with_round_towards_Zero,	UNIT_FPU,	1,	0 },
+  { itable_Floating_Divide,						UNIT_FPU,	33,	0 },
+  { itable_Floating_Divide_Single,					UNIT_FPU,	18,	0 },
+  { itable_Floating_Move_Register,					UNIT_FPU,	1,	0 },
+  { itable_Floating_Multiply,						UNIT_FPU,	2,	0 },
+  { itable_Floating_MultiplyAdd,					UNIT_FPU,	2,	0 },
+  { itable_Floating_MultiplyAdd_Single,					UNIT_FPU,	1,	0 },
+  { itable_Floating_MultiplySubtract,					UNIT_FPU,	2,	0 },
+  { itable_Floating_MultiplySubtract_Single,				UNIT_FPU,	1,	0 },
+  { itable_Floating_Multiply_Single,					UNIT_FPU,	1,	0 },
+  { itable_Floating_Negate,						UNIT_FPU,	1,	0 },
+  { itable_Floating_Negative_Absolute_Value,				UNIT_FPU,	1,	0 },
+  { itable_Floating_Negative_MultiplyAdd,				UNIT_FPU,	2,	0 },
+  { itable_Floating_Negative_MultiplyAdd_Single,			UNIT_FPU,	1,	0 },
+  { itable_Floating_Negative_MultiplySubtract,				UNIT_FPU,	2,	0 },
+  { itable_Floating_Negative_MultiplySubtract_Single,			UNIT_FPU,	1,	0 },
+  { itable_Floating_Reciprocal_Estimate_Single,				UNIT_FPU,	18,	0 },
+  { itable_Floating_Reciprocal_Square_Root_Estimate,			UNIT_FPU,	1,	0 },
+  { itable_Floating_Round_to_SinglePrecision,				UNIT_FPU,	1,	0 },
+  { itable_Floating_Select,						UNIT_FPU,	1,	0 },
+  { itable_Floating_Square_Root,					UNIT_UNKNOWN,	0,	0 },
+  { itable_Floating_Square_Root_Single,					UNIT_UNKNOWN,	0,	0 },
+  { itable_Floating_Subtract,						UNIT_FPU,	1,	0 },
+  { itable_Floating_Subtract_Single,					UNIT_FPU,	1,	0 },
+  { itable_Instruction_Cache_Block_Invalidate,				UNIT_MEM,	3,	0 },
+  { itable_Instruction_Synchronize,					UNIT_SREG,	1,	0 },
+  { itable_Load_Byte_and_Zero,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Double,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Double_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Double_with_Update,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Double_with_Update_Indexed,		UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Single,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Single_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Single_with_Update,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Single_with_Update_Indexed,		UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_ByteReverse_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_Multiple_Word,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_String_Word_Immediate,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_String_Word_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_And_Reserve_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_ByteReverse_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Move_Condition_Register_Field,				UNIT_SREG,	1,	0 },
+  { itable_Move_From_Condition_Register,				UNIT_SREG,	1,	0 },
+  { itable_Move_From_FPSCR,						UNIT_FPU,	1,	0 },
+  { itable_Move_From_Machine_State_Register,				UNIT_SREG,	1,	0 },
+  { itable_Move_From_Segment_Register,					UNIT_SREG,	3,	0 },
+  { itable_Move_From_Segment_Register_Indirect,				UNIT_SREG,	1,	0 },
+  { itable_Move_From_Time_Base,						UNIT_SREG,	1,	0 },
+  { itable_Move_To_FPSCR_Bit_0,						UNIT_FPU,	1,	0 },
+  { itable_Move_To_FPSCR_Bit_1,						UNIT_FPU,	1,	0 },
+  { itable_Move_To_FPSCR_Field_Immediate,				UNIT_FPU,	1,	0 },
+  { itable_Move_To_FPSCR_Fields,					UNIT_FPU,	1,	0 },
+  { itable_Move_To_Machine_State_Register,				UNIT_SREG,	2,	0 },
+  { itable_Move_To_Segment_Register,					UNIT_SREG,	2,	0 },
+  { itable_Move_To_Segment_Register_Indirect,				UNIT_SREG,	2,	0 },
+  { itable_Move_from_Special_Purpose_Register,				UNIT_SREG,	1,	0 },
+  { itable_Move_to_Condition_Register_Fields,				UNIT_SREG,	1,	0 },
+  { itable_Move_to_Condition_Register_from_FPSCR,			UNIT_FPU,	1,	0 },
+  { itable_Move_to_Condition_Register_from_XER,				UNIT_SREG,	1,	0 },
+  { itable_Move_to_Special_Purpose_Register,				UNIT_SREG,	1,	0 },
+  { itable_Multiply_High_Word,						UNIT_INT,	5,	0 },
+  { itable_Multiply_High_Word_Unsigned,					UNIT_INT,	6,	0 },
+  { itable_Multiply_Low_Immediate,					UNIT_INT,	3,	0 },
+  { itable_Multiply_Low_Word,						UNIT_INT,	5,	0 },
+  { itable_NAND,							UNIT_INT,	1,	0 },
+  { itable_NOR,								UNIT_INT,	1,	0 },
+  { itable_Negate,							UNIT_INT,	1,	0 },
+  { itable_OR,								UNIT_INT,	1,	0 },
+  { itable_OR_Immediate,						UNIT_INT,	1,	0 },
+  { itable_OR_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { itable_OR_with_Complement,						UNIT_INT,	1,	0 },
+  { itable_Return_From_Interrupt,					UNIT_SREG,	3,	0 },
+  { itable_Rotate_Left_Word_Immediate_then_AND_with_Mask,		UNIT_INT,	1,	0 },
+  { itable_Rotate_Left_Word_Immediate_then_Mask_Insert,			UNIT_INT,	1,	0 },
+  { itable_Rotate_Left_Word_then_AND_with_Mask,				UNIT_INT,	1,	0 },
+  { itable_Shift_Left_Word,						UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Algebraic_Word,					UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Algebraic_Word_Immediate,			UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Word,						UNIT_INT,	1,	0 },
+  { itable_Store_Byte,							UNIT_MEM,	1,	STORE },
+  { itable_Store_Byte_Indexed,						UNIT_MEM,	1,	STORE },
+  { itable_Store_Byte_with_Update,					UNIT_MEM,	1,	STORE },
+  { itable_Store_Byte_with_Update_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Double,					UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Double_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Double_with_Update,			UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Double_with_Update_Indexed,		UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Single,					UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Single_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Single_with_Update,			UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_Single_with_Update_Indexed,		UNIT_MEM,	1,	STORE },
+  { itable_Store_FloatingPoint_as_Integer_Word_Indexed,			UNIT_MEM,	1,	STORE },
+  { itable_Store_Half_Word,						UNIT_MEM,	1,	STORE },
+  { itable_Store_Half_Word_ByteReversed_Indexed,			UNIT_MEM,	1,	STORE },
+  { itable_Store_Half_Word_Indexed,					UNIT_MEM,	1,	STORE },
+  { itable_Store_Half_Word_with_Update,					UNIT_MEM,	1,	STORE },
+  { itable_Store_Half_Word_with_Update_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_Multiple_Word,						UNIT_MEM,	1,	STORE },
+  { itable_Store_String_Word_Immedate,					UNIT_MEM,	1,	STORE },
+  { itable_Store_String_Word_Indexed,					UNIT_MEM,	1,	STORE },
+  { itable_Store_Word,							UNIT_MEM,	1,	STORE },
+  { itable_Store_Word_ByteReversed_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_Word_Conditional_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Store_Word_Indexed,						UNIT_MEM,	1,	STORE },
+  { itable_Store_Word_with_Update,					UNIT_MEM,	1,	STORE },
+  { itable_Store_Word_with_Update_Indexed,				UNIT_MEM,	1,	STORE },
+  { itable_Subtract_From,						UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Carrying,					UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Extended,					UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Immediate_Carrying,				UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Minus_One_Extended,				UNIT_INT,	1,	0 },
+  { itable_Subtract_from_Zero_Extended,					UNIT_INT,	1,	0 },
+  { itable_Synchronize,							UNIT_SREG,	3,	0 },
+  { itable_System_Call,							UNIT_MEM,	3,	0 },
+  { itable_TLB_Invalidate_All,						UNIT_MEM,	3,	0 },
+  { itable_TLB_Invalidate_Entry,					UNIT_MEM,	3,	0 },
+  { itable_TLB_Sychronize,						UNIT_MEM,	3,	0 },
+  { itable_Trap_Word,							UNIT_INT,	2,	0 },
+  { itable_Trap_Word_Immediate,						UNIT_INT,	2,	0 },
+  { itable_XOR,								UNIT_INT,	1,	0 },
+  { itable_XOR_Immediate,						UNIT_INT,	1,	0 },
+  { itable_XOR_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { nr_itable_entries,							UNIT_UNKNOWN,	-1,	0 },
+};
+
+
+/* 604 timings */
+static timing time_604[] = {
+  /* Instruction index							Function unit	Cycles	Flags */
+  { itable_AND,								UNIT_INT,	1,	0 },
+  { itable_AND_Immediate,						UNIT_INT,	1,	0 },
+  { itable_AND_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { itable_AND_with_Complement,						UNIT_INT,	1,	0 },
+  { itable_Add,								UNIT_INT,	1,	0 },
+  { itable_Add_Carrying,						UNIT_INT,	1,	0 },
+  { itable_Add_Extended,						UNIT_INT,	1,	0 },
+  { itable_Add_Immediate,						UNIT_INT,	1,	0 },
+  { itable_Add_Immediate_Carrying,					UNIT_INT,	1,	0 },
+  { itable_Add_Immediate_Carrying_and_Record,				UNIT_INT,	1,	0 },
+  { itable_Add_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { itable_Add_to_Minus_One_Extended,					UNIT_INT,	1,	0 },
+  { itable_Add_to_Zero_Extended,					UNIT_INT,	1,	0 },
+  { itable_Branch,							UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional,						UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional_to_Count_Register,			UNIT_BRANCH,	1,	0 },
+  { itable_Branch_Conditional_to_Link_Register,				UNIT_BRANCH,	1,	0 },
+  { itable_Compare,							UNIT_INT,	1,	0 },
+  { itable_Compare_Immediate,						UNIT_INT,	1,	0 },
+  { itable_Compare_Logical,						UNIT_INT,	1,	0 },
+  { itable_Compare_Logical_Immediate,					UNIT_INT,	1,	0 },
+  { itable_Condition_Register_AND,					UNIT_INT,	1,	0 },
+  { itable_Condition_Register_AND_with_Complement,			UNIT_INT,	1,	0 },
+  { itable_Condition_Register_Equivalent,				UNIT_INT,	1,	0 },
+  { itable_Condition_Register_NAND,					UNIT_INT,	1,	0 },
+  { itable_Condition_Register_NOR,					UNIT_INT,	1,	0 },
+  { itable_Condition_Register_OR,					UNIT_INT,	1,	0 },
+  { itable_Condition_Register_OR_with_Complement,			UNIT_INT,	1,	0 },
+  { itable_Condition_Register_XOR,					UNIT_INT,	1,	0 },
+  { itable_Count_Leading_Zeros_Word,					UNIT_INT,	1,	0 },
+  { itable_Data_Cache_Block_Flush,					UNIT_MEM,	1,	0 },
+  { itable_Data_Cache_Block_Invalidate,					UNIT_MEM,	1,	0 },
+  { itable_Data_Cache_Block_Store,					UNIT_MEM,	1,	0 },
+  { itable_Data_Cache_Block_Touch,					UNIT_MEM,	1,	0 },
+  { itable_Data_Cache_Block_Touch_for_Store,				UNIT_MEM,	1,	0 },
+  { itable_Data_Cache_Block_set_to_Zero,				UNIT_MEM,	3,	0 },
+  { itable_Divide_Word,							UNIT_CINT,	20,	0 },
+  { itable_Divide_Word_Unsigned,					UNIT_CINT,	20,	0 },
+  { itable_Enforce_Inorder_Execution_of_IO,				UNIT_INT,	1,	0 },
+  { itable_Equivalent,							UNIT_INT,	1,	0 },
+  { itable_Extend_Sign_Byte,						UNIT_INT,	1,	0 },
+  { itable_Extend_Sign_Half_Word,					UNIT_INT,	1,	0 },
+  { itable_External_Control_In_Word_Indexed,				UNIT_MEM,	2,	0 },
+  { itable_External_Control_Out_Word_Indexed,				UNIT_MEM,	3,	0 },
+  { itable_Floating_Absolute_Value,					UNIT_FPU,	3,	0 },
+  { itable_Floating_Add,						UNIT_FPU,	3,	0 },
+  { itable_Floating_Add_Single,						UNIT_FPU,	3,	0 },
+  { itable_Floating_Compare_Ordered,					UNIT_FPU,	3,	0 },
+  { itable_Floating_Compare_Unordered,					UNIT_FPU,	3,	0 },
+  { itable_Floating_Convert_To_Integer_Word,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Convert_To_Integer_Word_with_round_towards_Zero,	UNIT_FPU,	3,	0 },
+  { itable_Floating_Divide,						UNIT_FPU,	32,	0 },
+  { itable_Floating_Divide_Single,					UNIT_FPU,	18,	0 },
+  { itable_Floating_Move_Register,					UNIT_FPU,	3,	0 },
+  { itable_Floating_Multiply,						UNIT_FPU,	3,	0 },
+  { itable_Floating_MultiplyAdd,					UNIT_FPU,	3,	0 },
+  { itable_Floating_MultiplyAdd_Single,					UNIT_FPU,	3,	0 },
+  { itable_Floating_MultiplySubtract,					UNIT_FPU,	3,	0 },
+  { itable_Floating_MultiplySubtract_Single,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Multiply_Single,					UNIT_FPU,	3,	0 },
+  { itable_Floating_Negate,						UNIT_FPU,	3,	0 },
+  { itable_Floating_Negative_Absolute_Value,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Negative_MultiplyAdd,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Negative_MultiplyAdd_Single,			UNIT_FPU,	3,	0 },
+  { itable_Floating_Negative_MultiplySubtract,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Negative_MultiplySubtract_Single,			UNIT_FPU,	3,	0 },
+  { itable_Floating_Reciprocal_Estimate_Single,				UNIT_FPU,	18,	0 },
+  { itable_Floating_Reciprocal_Square_Root_Estimate,			UNIT_FPU,	3,	0 },
+  { itable_Floating_Round_to_SinglePrecision,				UNIT_FPU,	3,	0 },
+  { itable_Floating_Select,						UNIT_FPU,	3,	0 },
+  { itable_Floating_Square_Root,					UNIT_UNKNOWN,	0,	0 },
+  { itable_Floating_Square_Root_Single,					UNIT_UNKNOWN,	0,	0 },
+  { itable_Floating_Subtract,						UNIT_FPU,	3,	0 },
+  { itable_Floating_Subtract_Single,					UNIT_FPU,	3,	0 },
+  { itable_Instruction_Cache_Block_Invalidate,				UNIT_MEM,	1,	0 },
+  { itable_Instruction_Synchronize,					UNIT_INT,	1,	0 },
+  { itable_Load_Byte_and_Zero,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Byte_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_FloatingPoint_Double,					UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Double_Indexed,				UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Double_with_Update,			UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Double_with_Update_Indexed,		UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Single,					UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Single_Indexed,				UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Single_with_Update,			UNIT_MEM,	3,	LOAD },
+  { itable_Load_FloatingPoint_Single_with_Update_Indexed,		UNIT_MEM,	3,	LOAD },
+  { itable_Load_Halfword_Algebraic,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_Algebraic_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_ByteReverse_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Halfword_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Load_Multiple_Word,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_String_Word_Immediate,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_String_Word_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_And_Reserve_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_ByteReverse_Indexed,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero,						UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_Indexed,					UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_with_Update,				UNIT_MEM,	2,	LOAD },
+  { itable_Load_Word_and_Zero_with_Update_Indexed,			UNIT_MEM,	2,	LOAD },
+  { itable_Move_Condition_Register_Field,				UNIT_BRANCH,	1,	0 },
+  { itable_Move_From_Condition_Register,				UNIT_CINT,	3,	0 },
+  { itable_Move_From_FPSCR,						UNIT_FPU,	3,	0 },
+  { itable_Move_From_Machine_State_Register,				UNIT_CINT,	3,	0 },
+  { itable_Move_From_Segment_Register,					UNIT_CINT,	3,	0 },
+  { itable_Move_From_Segment_Register_Indirect,				UNIT_CINT,	3,	0 },
+  { itable_Move_From_Time_Base,						UNIT_CINT,	3,	0 },
+  { itable_Move_To_FPSCR_Bit_0,						UNIT_FPU,	3,	0 },
+  { itable_Move_To_FPSCR_Bit_1,						UNIT_FPU,	3,	0 },
+  { itable_Move_To_FPSCR_Field_Immediate,				UNIT_FPU,	3,	0 },
+  { itable_Move_To_FPSCR_Fields,					UNIT_FPU,	3,	0 },
+  { itable_Move_To_Machine_State_Register,				UNIT_CINT,	1,	0 },
+  { itable_Move_To_Segment_Register,					UNIT_CINT,	1,	0 },
+  { itable_Move_To_Segment_Register_Indirect,				UNIT_CINT,	1,	0 },
+  { itable_Move_from_Special_Purpose_Register,				UNIT_CINT,	1,	0 },
+  { itable_Move_to_Condition_Register_Fields,				UNIT_CINT,	1,	0 },
+  { itable_Move_to_Condition_Register_from_FPSCR,			UNIT_FPU,	3,	0 },
+  { itable_Move_to_Condition_Register_from_XER,				UNIT_CINT,	3,	0 },
+  { itable_Move_to_Special_Purpose_Register,				UNIT_CINT,	1,	0 },
+  { itable_Multiply_High_Word,						UNIT_CINT,	4,	0 },
+  { itable_Multiply_High_Word_Unsigned,					UNIT_CINT,	4,	0 },
+  { itable_Multiply_Low_Immediate,					UNIT_CINT,	3,	0 },
+  { itable_Multiply_Low_Word,						UNIT_CINT,	4,	0 },
+  { itable_NAND,							UNIT_INT,	1,	0 },
+  { itable_NOR,								UNIT_INT,	1,	0 },
+  { itable_Negate,							UNIT_INT,	1,	0 },
+  { itable_OR,								UNIT_INT,	1,	0 },
+  { itable_OR_Immediate,						UNIT_INT,	1,	0 },
+  { itable_OR_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { itable_OR_with_Complement,						UNIT_INT,	1,	0 },
+  { itable_Return_From_Interrupt,					UNIT_INT,	3,	0 },
+  { itable_Rotate_Left_Word_Immediate_then_AND_with_Mask,		UNIT_INT,	1,	0 },
+  { itable_Rotate_Left_Word_Immediate_then_Mask_Insert,			UNIT_INT,	1,	0 },
+  { itable_Rotate_Left_Word_then_AND_with_Mask,				UNIT_INT,	1,	0 },
+  { itable_Shift_Left_Word,						UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Algebraic_Word,					UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Algebraic_Word_Immediate,			UNIT_INT,	1,	0 },
+  { itable_Shift_Right_Word,						UNIT_INT,	1,	0 },
+  { itable_Store_Byte,							UNIT_MEM,	3,	STORE },
+  { itable_Store_Byte_Indexed,						UNIT_MEM,	3,	STORE },
+  { itable_Store_Byte_with_Update,					UNIT_MEM,	3,	STORE },
+  { itable_Store_Byte_with_Update_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Double,					UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Double_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Double_with_Update,			UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Double_with_Update_Indexed,		UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Single,					UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Single_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Single_with_Update,			UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_Single_with_Update_Indexed,		UNIT_MEM,	3,	STORE },
+  { itable_Store_FloatingPoint_as_Integer_Word_Indexed,			UNIT_MEM,	3,	STORE },
+  { itable_Store_Half_Word,						UNIT_MEM,	3,	STORE },
+  { itable_Store_Half_Word_ByteReversed_Indexed,			UNIT_MEM,	3,	STORE },
+  { itable_Store_Half_Word_Indexed,					UNIT_MEM,	3,	STORE },
+  { itable_Store_Half_Word_with_Update,					UNIT_MEM,	3,	STORE },
+  { itable_Store_Half_Word_with_Update_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_Multiple_Word,						UNIT_MEM,	3,	STORE },
+  { itable_Store_String_Word_Immedate,					UNIT_MEM,	3,	STORE },
+  { itable_Store_String_Word_Indexed,					UNIT_MEM,	3,	STORE },
+  { itable_Store_Word,							UNIT_MEM,	3,	STORE },
+  { itable_Store_Word_ByteReversed_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_Word_Conditional_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Store_Word_Indexed,						UNIT_MEM,	3,	STORE },
+  { itable_Store_Word_with_Update,					UNIT_MEM,	3,	STORE },
+  { itable_Store_Word_with_Update_Indexed,				UNIT_MEM,	3,	STORE },
+  { itable_Subtract_From,						UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Carrying,					UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Extended,					UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Immediate_Carrying,				UNIT_INT,	1,	0 },
+  { itable_Subtract_From_Minus_One_Extended,				UNIT_INT,	1,	0 },
+  { itable_Subtract_from_Zero_Extended,					UNIT_INT,	1,	0 },
+  { itable_Synchronize,							UNIT_INT,	1,	0 },
+  { itable_System_Call,							UNIT_MEM,	1,	0 },
+  { itable_TLB_Invalidate_All,						UNIT_MEM,	1,	0 },
+  { itable_TLB_Invalidate_Entry,					UNIT_MEM,	1,	0 },
+  { itable_TLB_Sychronize,						UNIT_MEM,	1,	0 },
+  { itable_Trap_Word,							UNIT_INT,	1,	0 },
+  { itable_Trap_Word_Immediate,						UNIT_INT,	1,	0 },
+  { itable_XOR,								UNIT_INT,	1,	0 },
+  { itable_XOR_Immediate,						UNIT_INT,	1,	0 },
+  { itable_XOR_Immediate_Shifted,					UNIT_INT,	1,	0 },
+  { nr_itable_entries,							UNIT_UNKNOWN,	-1,	0 },
+};
+
+
+INLINE_FUNCTION_UNIT function_unit *
+function_unit_create(void)
+{
+  function_unit *new_func;
+  timing *timing_ptr;
+
+  if (!WITH_FUNCTION_UNIT)
+    return (function_unit *)0;
+
+  new_func = ZALLOC(function_unit);
+
+  /* Get the model specific timing information */
+  switch (CURRENT_PPC_MODEL) {
+  default:		timing_ptr = (timing *)0;	break;
+  case PPC_MODEL_603:	timing_ptr = time_603;		break;
+  case PPC_MODEL_603e:	timing_ptr = time_603;		break;
+  case PPC_MODEL_604:	timing_ptr = time_604;		break;
+  }
+
+  /* If we have it, provide model specific timing info */
+  if (timing_ptr) {
+    for (; timing_ptr->cycles >= 0; timing_ptr++) {
+      int i = (int)timing_ptr->index;
+      unit_index unit = timing_ptr->unit;
+
+      /* The 603 as compared to the 603e doesn't support putting add/cmp instructions
+	 in the system register unit, so convert these instructions back to normal
+	 integer instructions.	*/
+      if (CURRENT_PPC_MODEL == PPC_MODEL_603 && unit == UNIT_SINT)
+	unit = UNIT_INT;
+
+      new_func->time[i].unit = unit;
+      new_func->time[i].cycles = timing_ptr->cycles;
+      new_func->time[i].flags = timing_ptr->flags;
+    }
+  }
+
+  return new_func;
+}
+
+INLINE_FUNCTION_UNIT void
+function_unit_init(function_unit *func_unit)
+{
+  func_unit->old_program_counter = 0;
+}
+
+INLINE_FUNCTION_UNIT void
+function_unit_halt(cpu *processor,
+		   function_unit *func_unit)
+{
+}
+
+INLINE_FUNCTION_UNIT function_unit_print *
+function_unit_mon_info(function_unit *func_unit)
+{
+  function_unit_print *head;
+  function_unit_print *tail;
+  int i;
+
+  head = tail = ZALLOC(function_unit_print);
+  tail->count = func_unit->nr_stalls;
+  tail->name = "stall";
+  tail->suffix_plural = "s";
+  tail->suffix_singular = "";
+
+  tail->next = ZALLOC(function_unit_print);
+  tail = tail->next;
+  tail->count = func_unit->nr_branches;
+  tail->name = "branch";
+  tail->suffix_plural = "es";
+  tail->suffix_singular = "";
+
+  for (i = 0; i < (int)NR_UNITS; i++) {
+    if (func_unit->nr_units[i]) {
+      tail->next = ZALLOC(function_unit_print);
+      tail = tail->next;
+      tail->count = func_unit->nr_units[i];
+      tail->name = unit_names[i];
+      tail->suffix_plural = "s";
+      tail->suffix_singular = "";
+    }
+  }
+
+  tail->next = (function_unit_print *)0;
+  return head;
+}
+
+INLINE_FUNCTION_UNIT void
+function_unit_mon_free(function_unit *func_unit,
+		       function_unit_print *ptr)
+{
+  function_unit_print *next;
+
+  while (ptr) {
+    next = ptr->next;
+    free((void *)ptr);
+    ptr = next;
+  }
+}
+
+INLINE_FUNCTION_UNIT void
+function_unit_issue(itable_index index,
+		    function_unit *func_unit,
+		    unsigned_word cia)
+{
+  if (func_unit->old_program_counter+4 != cia)
+    func_unit->nr_branches++;
+
+  func_unit->old_program_counter = cia;
+  func_unit->nr_units[ (int)func_unit->time[ (int)index ].unit ]++;
+}
+
+INLINE_FUNCTION_UNIT void
+function_unit_model(const char *model)
+{
+  if (!strcmp (model, "601"))
+    current_ppc_model = PPC_MODEL_601;
+  else if (!strcmp (model, "602"))
+    current_ppc_model = PPC_MODEL_602;
+  else if (!strcmp (model, "603"))
+    current_ppc_model = PPC_MODEL_603;
+  else if (!strcmp (model, "603e"))
+    current_ppc_model = PPC_MODEL_603e;
+  else if (!strcmp (model, "604"))
+    current_ppc_model = PPC_MODEL_604;
+  else if (!strcmp (model, "403"))
+    current_ppc_model = PPC_MODEL_403;
+  else if (!strcmp (model, "505"))
+    current_ppc_model = PPC_MODEL_505;
+  else if (!strcmp (model, "821"))
+    current_ppc_model = PPC_MODEL_821;
+  else if (!strcmp (model, "860"))
+    current_ppc_model = PPC_MODEL_860;
+  else
+    error ("Unknown PowerPC model %s", model);
+}
+
+#endif /* _FUNCTION_UNIT_C_ */
diff --git a/sim/ppc/function_unit.h b/sim/ppc/function_unit.h
new file mode 100644
index 0000000..904abce
--- /dev/null
+++ b/sim/ppc/function_unit.h
@@ -0,0 +1,71 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _FUNCTION_UNIT_H_
+#define _FUNCTION_UNIT_H_
+
+#include "itable.h"
+
+#ifndef INLINE_FUNCTION_UNIT
+#define INLINE_FUNCTION_UNIT
+#endif
+
+/* basic types */
+
+typedef struct _function_unit function_unit;
+
+typedef struct _function_unit_print function_unit_print;
+struct _function_unit_print {
+  function_unit_print *next;
+  const char *name;
+  const char *suffix_singular;
+  const char *suffix_plural;
+  unsigned count;
+};
+
+/* constructor */
+
+INLINE_FUNCTION_UNIT function_unit *function_unit_create
+(void);
+
+INLINE_FUNCTION_UNIT void function_unit_init
+(function_unit *func_unit);
+
+INLINE_FUNCTION_UNIT void function_unit_halt
+(cpu *processor,
+ function_unit *func_unit);
+
+INLINE_FUNCTION_UNIT function_unit_print *function_unit_mon_info
+(function_unit *func_unit);
+
+INLINE_FUNCTION_UNIT void function_unit_mon_free
+(function_unit *func_unit,
+ function_unit_print *ptr);
+
+INLINE_FUNCTION_UNIT void function_unit_issue
+(itable_index index,
+ function_unit *func_unit,
+ unsigned_word cia);
+
+INLINE_FUNCTION_UNIT void function_unit_model
+(const char *model);
+
+#endif /* _FUNCTION_UNIT_H_ */
diff --git a/sim/ppc/inline.c b/sim/ppc/inline.c
index 4ac048b..715373a 100644
--- a/sim/ppc/inline.c
+++ b/sim/ppc/inline.c
@@ -19,11 +19,15 @@
     */
 
 
-#ifndef _PPC_INLINE_C_
-#define _PPC_INLINE_C_
+#ifndef _INLINE_C_
+#define _INLINE_C_
 
-#if ENDIAN_INLINE
-#include "ppc-endian.c"
+#if BITS_INLINE
+#include "bits.c"
+#endif
+
+#if SIM_ENDIAN_INLINE
+#include "sim-endian.c"
 #endif
 
 #if ICACHE_INLINE
@@ -50,6 +54,10 @@
 #include "mon.c"
 #endif
 
+#if FUNCTION_UNIT_INLINE
+#include "function_unit.c"
+#endif
+
 #if REGISTERS_INLINE
 #include "registers.c"
 #endif
diff --git a/sim/ppc/inline.h b/sim/ppc/inline.h
new file mode 100644
index 0000000..646e696
--- /dev/null
+++ b/sim/ppc/inline.h
@@ -0,0 +1,155 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _INLINE_H_
+#define _INLINE_H_
+
+#if SIM_ENDIAN_INLINE
+#if SIM_ENDIAN_INLINE == 2
+#define INLINE_SIM_ENDIAN static INLINE
+#else
+#define INLINE_SIM_ENDIAN static
+#endif
+#endif
+
+#if ICACHE_INLINE
+#if ICACHE_INLINE == 2
+#define INLINE_ICACHE static INLINE
+#else
+#define INLINE_ICACHE static
+#endif
+#endif
+
+#if CORE_INLINE
+#if CORE_INLINE == 2
+#define INLINE_CORE static INLINE
+#else
+#define INLINE_CORE static
+#endif
+#endif
+
+#if VM_INLINE
+#if VM_INLINE == 2
+#define INLINE_VM static INLINE
+#else
+#define INLINE_VM static
+#endif
+#endif
+
+#if CPU_INLINE
+#if CPU_INLINE == 2
+#define INLINE_CPU static INLINE
+#else
+#define INLINE_CPU static
+#endif
+#endif
+
+#if BITS_INLINE
+#if BITS_INLINE == 2
+#define INLINE_BITS static INLINE
+#else
+#define INLINE_BITS static
+#endif
+#endif
+
+#if EVENTS_INLINE
+#if EVENTS_INLINE == 2
+#define INLINE_EVENTS static INLINE
+#else
+#define INLINE_EVENTS static
+#endif
+#endif
+
+#if MON_INLINE
+#if MON_INLINE == 2
+#define INLINE_MON static INLINE
+#else
+#define INLINE_MON static
+#endif
+#endif
+
+#if REGISTERS_INLINE
+#if REGISTERS_INLINE == 2
+#define INLINE_REGISTERS static INLINE
+#else
+#define INLINE_REGISTERS static
+#endif
+#endif
+
+#if INTERRUPTS_INLINE
+#if INTERRUPTS_INLINE == 2
+#define INLINE_INTERRUPTS static INLINE
+#else
+#define INLINE_INTERRUPTS static
+#endif
+#endif
+
+#if DEVICE_TREE_INLINE
+#if DEVICE_TREE_INLINE == 2
+#define INLINE_DEVICE_TREE static INLINE
+#else
+#define INLINE_DEVICE_TREE static
+#endif
+#endif
+
+#if DEVICES_INLINE
+#if DEVICES_INLINE == 2
+#define INLINE_DEVICES static INLINE
+#else
+#define INLINE_DEVICES static
+#endif
+#define STATIC_DEVICES static
+#endif
+
+#if SPREG_INLINE
+#if SPREG_INLINE == 2
+#define INLINE_SPREG static INLINE
+#else
+#define INLINE_SPREG static
+#endif
+#endif
+
+#if SEMANTICS_INLINE && !defined(_SEMANTICS_C_)
+#if SEMANTICS_INLINE == 2
+#define INLINE_SEMANTICS static INLINE
+#else
+#define INLINE_SEMANTICS static
+#endif
+#endif
+
+#if IDECODE_INLINE
+#if IDECODE_INLINE == 2
+#define INLINE_IDECODE static INLINE
+#else
+#define INLINE_IDECODE static
+#endif
+#endif
+
+#if FUNCTION_UNIT_INLINE
+#if FUNCTION_UNIT_INLINE == 2
+#define INLINE_FUNCTION_UNIT static INLINE
+#else
+#define INLINE_FUNCTION_UNIT static
+#endif
+#endif
+
+
+#endif
diff --git a/sim/ppc/main.c b/sim/ppc/main.c
index 07412be..80b993f 100644
--- a/sim/ppc/main.c
+++ b/sim/ppc/main.c
@@ -23,11 +23,16 @@
 #include <stdio.h>
 
 #include "psim.h"
+#include "function_unit.h"
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #ifdef HAVE_STRING_H
 #include <string.h>
 #else
@@ -80,7 +85,7 @@ zfree(void *chunk)
 static void
 usage(void)
 {
-  printf_filtered("Usage:\n\tpsim [ -t <trace-option> ] <image> [ <image-args> ... ]\n");
+  printf_filtered("Usage:\n\tpsim [ -t <trace-option> ] [-m model] [-i] [-I] <image> [ <image-args> ... ]\n");
   trace_usage();
   error("");
 }
@@ -91,23 +96,27 @@ main(int argc, char **argv)
   psim *system;
   const char *name_of_file;
   char *arg_;
-  unsigned_word stack_pointer;
   psim_status status;
   int letter;
-  int i;
   int print_info = 0;
 
   /* check for arguments -- note sim_calls.c also contains argument processing
      code for the simulator linked within gdb.  */
-  while ((letter = getopt (argc, argv, "It:")) != EOF)
+  while ((letter = getopt (argc, argv, "Iim:t:")) != EOF)
     {
       switch (letter) {
       case 't':
 	trace_option(optarg);
 	break;
-      case 'I':
+      case 'm':
+	function_unit_model(optarg);
+	break;
+      case 'i':
 	print_info = 1;
 	break;
+      case 'I':
+	print_info = 2;
+	break;
       default:
 	usage();
       }
@@ -133,7 +142,7 @@ main(int argc, char **argv)
 
   /* any final clean up */
   if (print_info)
-    psim_print_info (system, 2);
+    psim_print_info (system, print_info);
 
   /* why did we stop */
   status = psim_get_status(system);
diff --git a/sim/ppc/mon.c b/sim/ppc/mon.c
index f086049..0efb1bf 100644
--- a/sim/ppc/mon.c
+++ b/sim/ppc/mon.c
@@ -29,6 +29,7 @@
 #include "basics.h"
 #include "cpu.h"
 #include "mon.h"
+#include <stdio.h>
 
 #ifdef HAVE_STRING_H
 #include <string.h>
@@ -58,6 +59,7 @@ struct _cpu_mon {
   unsigned issue_count[nr_itable_entries];
   unsigned read_count;
   unsigned write_count;
+  function_unit_print *func_unit_print;
 };
 
 struct _mon {
@@ -101,6 +103,9 @@ mon_issue(itable_index index,
   cpu_mon *monitor = cpu_monitor(processor);
   ASSERT(index <= nr_itable_entries);
   monitor->issue_count[index] += 1;
+
+  if (WITH_FUNCTION_UNIT)
+    function_unit_issue(index, cpu_function_unit(processor), cia);
 }
 
 
@@ -127,7 +132,6 @@ mon_write(unsigned_word ea,
   monitor->write_count += 1;
 }
 
-
 STATIC_INLINE_MON unsigned
 mon_get_number_of_insns(cpu_mon *monitor)
 {
@@ -163,7 +167,8 @@ mon_add_commas(char *buf,
 
 
 INLINE_MON void
-mon_print_info(mon *monitor,
+mon_print_info(psim *system,
+	       mon *monitor,
 	       int verbose)
 {
   char buffer[20];
@@ -172,7 +177,7 @@ mon_print_info(mon *monitor,
   int len_num = 0;
   int len;
   long total_insns = 0;
-  long cpu_insns_second;
+  long cpu_insns_second = 0;
   double cpu_time = 0.0;
 
   for (cpu_nr = 0; cpu_nr < monitor->nr_cpus; cpu_nr++) {
@@ -219,26 +224,55 @@ mon_print_info(mon *monitor,
 			  (monitor->cpu_monitor[cpu_nr].issue_count[index] == 1) ? "" : "s");
       }
 
-      if (monitor->cpu_monitor[cpu_nr].read_count)
-	printf_filtered ("CPU #%*d executed %*s data reads.\n",
-			 len_cpu, cpu_nr+1,
-			 len_num, mon_add_commas(buffer,
-						 sizeof(buffer),
-						 monitor->cpu_monitor[cpu_nr].read_count));
-
-      if (monitor->cpu_monitor[cpu_nr].write_count)
-	printf_filtered ("CPU #%*d executed %*s data writes.\n",
-			 len_cpu, cpu_nr+1,
-			 len_num, mon_add_commas(buffer,
-						 sizeof(buffer),
-						 monitor->cpu_monitor[cpu_nr].write_count));
+      printf_filtered ("\n");
     }
+
+    if (WITH_FUNCTION_UNIT)
+      {
+	function_unit *func_unit = cpu_function_unit(psim_cpu(system, cpu_nr));
+	function_unit_print *ptr = function_unit_mon_info(func_unit);
+	function_unit_print *orig_ptr = ptr;
+
+	while (ptr) {
+	  if (ptr->count)
+	    printf_filtered("CPU #%*d executed %*s %s%s.\n",
+			    len_cpu, cpu_nr+1,
+			    len_num, mon_add_commas(buffer,
+						    sizeof(buffer),
+						    ptr->count),
+			    ptr->name,
+			    ((ptr->count == 1)
+			     ? ptr->suffix_singular
+			     : ptr->suffix_plural));
+
+	  ptr = ptr->next;
+	}
+
+	function_unit_mon_free(func_unit, orig_ptr);
+      }
+
+    if (monitor->cpu_monitor[cpu_nr].read_count)
+      printf_filtered ("CPU #%*d executed %*s data read%s.\n",
+		       len_cpu, cpu_nr+1,
+		       len_num, mon_add_commas(buffer,
+					       sizeof(buffer),
+					       monitor->cpu_monitor[cpu_nr].read_count),
+		       (monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s");
+
+    if (monitor->cpu_monitor[cpu_nr].write_count)
+      printf_filtered ("CPU #%*d executed %*s data write%s.\n",
+		       len_cpu, cpu_nr+1,
+		       len_num, mon_add_commas(buffer,
+					       sizeof(buffer),
+					       monitor->cpu_monitor[cpu_nr].write_count),
+		       (monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s");
     
     printf_filtered("CPU #%*d executed %*s instructions in total.\n",
 		    len_cpu, cpu_nr+1,
 		    len_num, mon_add_commas(buffer,
 					    sizeof(buffer),
 					    mon_get_number_of_insns(&monitor->cpu_monitor[cpu_nr])));
+
   }
 
   if (monitor->nr_cpus > 1)
@@ -246,7 +280,8 @@ mon_print_info(mon *monitor,
 		    mon_add_commas(buffer, sizeof(buffer), total_insns));
 
   if (cpu_insns_second)
-    printf_filtered ("\nSimulator speed was %s instructions/second\n",
+    printf_filtered ("%sSimulator speed was %s instructions/second\n",
+		     (monitor->nr_cpus <= 1 && verbose <= 1) ? "" : "\n",
 		     mon_add_commas(buffer, sizeof(buffer), cpu_insns_second));
 }
 
diff --git a/sim/ppc/mon.h b/sim/ppc/mon.h
new file mode 100644
index 0000000..e8ac2e3
--- /dev/null
+++ b/sim/ppc/mon.h
@@ -0,0 +1,76 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _MON_H_
+#define _MON_H_
+
+#ifndef INLINE_MON
+#define INLINE_MON
+#endif
+
+#include "basics.h"
+#include "itable.h"
+
+/* monitor/logger: counts what the simulation is up to */
+
+typedef struct _mon mon;
+typedef struct _cpu_mon cpu_mon;
+
+INLINE_MON mon *mon_create
+(void);
+
+INLINE_MON cpu_mon *mon_cpu
+(mon *monitor,
+ int cpu_nr);
+
+INLINE_MON void mon_init
+(mon *monitor,
+ int nr_cpus);
+
+INLINE_MON void mon_issue
+(itable_index index,
+ cpu *processor, 
+ unsigned_word cia);
+
+/* NOTE - there is no mon_iload - it is made reduntant by mon_issue()
+   and besides when the cpu's have their own cache, the information is
+   wrong */
+
+INLINE_MON void mon_read
+(unsigned_word ea,
+ unsigned_word ra,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_MON void mon_write
+(unsigned_word ea,
+ unsigned_word ra,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_MON void mon_print_info
+(psim *system,
+ mon *monitor,
+ int verbose);
+
+#endif
diff --git a/sim/ppc/ppc-endian.c b/sim/ppc/ppc-endian.c
deleted file mode 100644
index ec90bb7..0000000
--- a/sim/ppc/ppc-endian.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*  This file is part of the program psim.
-
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- 
-    */
-
-
-#ifndef _ENDIAN_C_
-#define _ENDIAN_C_
-
-#ifndef STATIC_INLINE_ENDIAN
-#define STATIC_INLINE_ENDIAN STATIC_INLINE
-#endif
-
-
-#include "config.h"
-#include "ppc-config.h"
-#include "words.h"
-#include "ppc-endian.h"
-#include "sim_callbacks.h"
-
-#if !defined(SWAP_2) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
-#define SWAP_2(SET,RAW) SET htons (RAW)
-#endif
-
-#ifndef	SWAP_2
-#define SWAP_2(SET,RAW) SET (((RAW) >> 8) | ((RAW) << 8))
-#endif
-
-#if !defined(SWAP_4) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
-#define SWAP_4(SET,RAW) SET htonl (RAW)
-#endif
-
-#ifndef SWAP_4
-#define	SWAP_4(SET,RAW) SET (((RAW) << 24) | (((RAW) & 0xff00) << 8) | (((RAW) & 0xff0000) >> 8) | ((RAW) >> 24))
-#endif
-
-#ifndef SWAP_8
-#define SWAP_8(SET,RAW)							\
-  union { unsigned_8 dword; unsigned_4 words[2]; } in, out;		\
-  in.dword = RAW;							\
-  SWAP_4 (out.words[0] =, in.words[1]);					\
-  SWAP_4 (out.words[1] =, in.words[0]);					\
-  SET out.dword;
-#endif
-
-#ifndef ENDIAN_N
-#define ENDIAN_N(NAME,BYTE_SIZE) \
-INLINE unsigned_##BYTE_SIZE \
-endian_##NAME##_##BYTE_SIZE(unsigned_##BYTE_SIZE raw_in) \
-{ \
-  if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) { \
-    return raw_in; \
-  } \
-  else { \
-    SWAP_##BYTE_SIZE(return,raw_in); \
-  } \
-}
-#endif
-
-ENDIAN_N(h2t, 2)
-ENDIAN_N(h2t, 4)
-ENDIAN_N(h2t, 8)
-ENDIAN_N(t2h, 2)
-ENDIAN_N(t2h, 4)
-ENDIAN_N(t2h, 8)
-
-#endif /* _ENDIAN_C_ */
diff --git a/sim/ppc/ppc-endian.h b/sim/ppc/ppc-endian.h
deleted file mode 100644
index 748d2ef..0000000
--- a/sim/ppc/ppc-endian.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*  This file is part of the program psim.
-
-    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- 
-    */
-
-
-#ifndef _ENDIAN_H_
-#define _ENDIAN_H_
-
-/* C byte conversion functions */
-
-extern unsigned_1 endian_h2t_1(unsigned_1 x);
-extern unsigned_2 endian_h2t_2(unsigned_2 x);
-extern unsigned_4 endian_h2t_4(unsigned_4 x);
-extern unsigned_8 endian_h2t_8(unsigned_8 x);
-
-extern unsigned_1 endian_t2h_1(unsigned_1 x);
-extern unsigned_2 endian_t2h_2(unsigned_2 x);
-extern unsigned_4 endian_t2h_4(unsigned_4 x);
-extern unsigned_8 endian_t2h_8(unsigned_8 x);
-
-/* Host dependant:
-
-   The CPP below defines information about the compilation host.  In
-   particular it defines the macro's:
-
-   	WITH_HOST_BYTE_ORDER	The byte order of the host. Could
-				be any of LITTLE_ENDIAN, BIG_ENDIAN
-				or 0 (unknown).  Those macro's also
-				need to be defined.
-
-	WITH_NTOH		Network byte order macros defined.
-				Possible value is 32 or (maybe one
-				day 64 because some 64bit network
-				byte order macro is defined.
- */
-
-
-/* NetBSD:
-
-   NetBSD is easy, everything you could ever want is in a header file
-   (well almost :-) */
-
-#if defined(__NetBSD__)
-# include <machine/endian.h>
-# define WITH_NTOH 32 /* what about alpha? */
-# if (WITH_HOST_BYTE_ORDER == 0)
-#  undef WITH_HOST_BYTE_ORDER
-#  define WITH_HOST_BYTE_ORDER BYTE_ORDER
-# endif
-# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
-#  error "host endian incorrectly configured, check config.h"
-# endif
-#endif
-
-/* Linux is similarly easy.  */
-
-#if defined(__linux__)
-# include <endian.h>
-# include <asm/byteorder.h>
-# if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
-#  define LITTLE_ENDIAN __LITTLE_ENDIAN
-# endif
-# if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
-#  define BIG_ENDIAN __BIG_ENDIAN
-# endif
-# if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
-#  define BYTE_ORDER __BYTE_ORDER
-# endif
-# if !defined(__alpha__)
-#  define WITH_NTOH 32 /* what about alpha? */
-# endif
-# if (WITH_HOST_BYTE_ORDER == 0)
-#  undef WITH_HOST_BYTE_ORDER
-#  define WITH_HOST_BYTE_ORDER BYTE_ORDER
-# endif
-# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
-#  error "host endian incorrectly configured, check config.h"
-# endif
-#endif
-
-/* INSERT HERE - hosts that have available LITTLE_ENDIAN and
-   BIG_ENDIAN macro's */
-
-
-/* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */
-
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-
-/* SunOS on SPARC:
-
-   Big endian last time I looked */
-
-#if defined(sparc) || defined(__sparc__)
-# if (WITH_HOST_BYTE_ORDER == 0)
-#  undef WITH_HOST_BYTE_ORDER
-#  define WITH_HOST_BYTE_ORDER BIG_ENDIAN
-# endif
-# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN)
-#  error "sun was big endian last time I looked ..."
-# endif
-#endif
-
-
-/* Random x86
-
-   Little endian last time I looked */
-
-#if defined(i386) || defined(i486) || defined(i586) || defined(__i386__) || defined(__i486__) || defined(__i586__)
-# if (WITH_HOST_BYTE_ORDER == 0)
-#  undef WITH_HOST_BYTE_ORDER
-#  define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN
-# endif
-# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN)
-#  error "x86 was little endian last time I looked ..."
-# endif
-#endif
-
-
-/* INSERT HERE - additional hosts that do not have LITTLE_ENDIAN and
-   BIG_ENDIAN definitions available.  */
-
-
-/* SWAPPING:
-
-   According to the following table:
-
-                TARG BE   TARG LE   TARG ??
-       HOST BE    ok        s/w      s/w
-       HOST LE   htohl      ok      ok|ntohl
-       HOST ??   ntohl      s/w      s/w
-
-    define host <-> target byte order conversion macro's */
-
-
-/* IN PLACE:
-
-   These macro's given a variable argument swap its value in place if
-   so required */
-
-#define H2T(VARIABLE) \
-do { \
-  switch (sizeof(VARIABLE)) { \
-  case 1: VARIABLE = H2T_1(VARIABLE); break; \
-  case 2: VARIABLE = H2T_2(VARIABLE); break; \
-  case 4: VARIABLE = H2T_4(VARIABLE); break; \
-  case 8: VARIABLE = H2T_8(VARIABLE); break; \
-  } \
-} while (0)
-
-#define T2H(VARIABLE) \
-do { \
-  switch (sizeof(VARIABLE)) { \
-  case 1: VARIABLE = T2H_1(VARIABLE); break; \
-  case 2: VARIABLE = T2H_2(VARIABLE); break; \
-  case 4: VARIABLE = T2H_4(VARIABLE); break; \
-  case 8: VARIABLE = T2H_8(VARIABLE); break; \
-  } \
-} while (0)
-
-
-/* TARGET WORD:
-
-   Byte swap a quantity the size of the targets word */
-
-#if (WITH_TARGET_WORD_BITSIZE == 64)
-#define H2T_word(X) H2T_8(X)
-#define T2H_word(X) T2H_8(X)
-#endif
-#if (WITH_TARGET_WORD_BITSIZE == 32)
-#define H2T_word(X) H2T_4(X)
-#define T2H_word(X) T2H_4(X)
-#endif
-
-
-/* FUNCTIONS:
-
-   Returns the value swapped according to the host/target byte order */
-
-/* no need to swap */
-#if (WITH_HOST_BYTE_ORDER \
-     && WITH_TARGET_BYTE_ORDER \
-     && WITH_HOST_BYTE_ORDER == WITH_TARGET_BYTE_ORDER )
-#define H2T_1(X) (X)
-#define H2T_2(X) (X)
-#define H2T_4(X) (X)
-#define H2T_8(X) (X)
-#define T2H_1(X) (X)
-#define T2H_2(X) (X)
-#define T2H_4(X) (X)
-#define T2H_8(X) (X)
-#endif
-
-/* have ntoh and big endian target */
-#if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN \
-     && WITH_HOST_BYTE_ORDER != BIG_ENDIAN \
-     && WITH_NTOH)
-#define H2T_8(X) endian_h2t_8(X)
-#define H2T_4(X) htonl(X)
-#define H2T_2(X) htons(X)
-#define H2T_1(X) (X)
-#define T2H_8(X) endian_t2h_8(X)
-#define T2H_4(X) htonl(X)
-#define T2H_2(X) htons(X)
-#define T2H_1(X) (X)
-#endif
-
-#if (defined (__i486__) || defined (__i586__)) && defined(__GNUC__) && WITH_BSWAP && WITH_NTOH
-#undef  htonl
-#undef  ntohl
-#define htonl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; })
-#define ntohl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; })
-#endif
-
-/* have ntoh, little host and unknown target */
-#if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN \
-     && WITH_TARGET_BYTE_ORDER == 0 \
-     && WITH_NTOH)
-#define H2T_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : endian_h2t_8(X))
-#define H2T_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htonl(X))
-#define H2T_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htons(X))
-#define H2T_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : (X))
-#define T2H_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : endian_t2h_8(X))
-#define T2H_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htonl(X))
-#define T2H_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htons(X))
-#define T2H_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : (X))
-#endif
-
-/* if all else fails use software */
-#ifndef H2T_1
-#define H2T_1(X) (X)
-#define H2T_2(X) endian_h2t_2(X)
-#define H2T_4(X) endian_h2t_4(X)
-#define H2T_8(X) endian_h2t_8(X)
-#define T2H_1(X) (X)
-#define T2H_2(X) endian_t2h_2(X)
-#define T2H_4(X) endian_t2h_4(X)
-#define T2H_8(X) endian_t2h_8(X)
-#endif
-
-#endif
diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions
index 8d2ca05..67ec1dd 100644
--- a/sim/ppc/ppc-instructions
+++ b/sim/ppc/ppc-instructions
@@ -905,34 +905,34 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 #
 
 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
-#	unsigned_word b;
-#	unsigned_word EA;
-#	if (RA == 0) b = 0;
-#	else         b = *rA;
-#	EA = b + *rB;
-#	*rT = SWAP2(MEM(unsigned, EA, 2));
+	unsigned_word b;
+	unsigned_word EA;
+	if (RA == 0) b = 0;
+	else         b = *rA;
+	EA = b + *rB;
+	*rT = SWAP_2(MEM(unsigned, EA, 2));
 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
-#	unsigned_word b;
-#	unsigned_word EA;
-#	if (RA == 0) b = 0;
-#	else         b = *rA;
-#	EA = b + *rB;
-#	*rT = SWAP4(MEM(unsigned, EA, 4));
+	unsigned_word b;
+	unsigned_word EA;
+	if (RA == 0) b = 0;
+	else         b = *rA;
+	EA = b + *rB;
+	*rT = SWAP_4(MEM(unsigned, EA, 4));
 
 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
-#	unsigned_word b;
-#	unsigned_word EA;
-#	if (RA == 0) b = 0;
-#	else         b = *rA;
-#	EA = b + *rB;
-#	STORE(EA, 2, SWAP2(*rS));
+	unsigned_word b;
+	unsigned_word EA;
+	if (RA == 0) b = 0;
+	else         b = *rA;
+	EA = b + *rB;
+	STORE(EA, 2, SWAP_2(*rS));
 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
-#	unsigned_word b;
-#	unsigned_word EA;
-#	if (RA == 0) b = 0;
-#	else         b = *rA;
-#	EA = b + *rB;
-#	STORE(EA, 4, SWAP4(*rS));
+	unsigned_word b;
+	unsigned_word EA;
+	if (RA == 0) b = 0;
+	else         b = *rA;
+	EA = b + *rB;
+	STORE(EA, 4, SWAP_4(*rS));
 
 
 #
diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c
index 60acc9b..b696ab0 100644
--- a/sim/ppc/psim.c
+++ b/sim/ppc/psim.c
@@ -97,6 +97,7 @@ int current_host_byte_order;
 int current_environment;
 int current_alignment;
 int current_floating_point;
+ppc_model current_ppc_model = WITH_DEFAULT_PPC_MODEL;
 
 
 /* create a device tree from the image */
@@ -1015,7 +1016,7 @@ INLINE_PSIM void
 psim_print_info(psim *system,
 		int verbose)
 {
-  mon_print_info(system->monitor, verbose);
+  mon_print_info(system, system->monitor, verbose);
 }
 
 
diff --git a/sim/ppc/sim-endian-n.h b/sim/ppc/sim-endian-n.h
new file mode 100644
index 0000000..302b088
--- /dev/null
+++ b/sim/ppc/sim-endian-n.h
@@ -0,0 +1,65 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef N
+#error "N must be #defined"
+#endif
+
+#undef unsigned_N
+#define unsigned_N XCONCAT2(unsigned_,N)
+#undef _SWAP_N
+#define _SWAP_N XCONCAT2(_SWAP_,N)
+#undef endian_t2h_N
+#define endian_t2h_N XCONCAT2(endian_t2h_,N)
+#undef endian_h2t_N
+#define endian_h2t_N XCONCAT2(endian_h2t_,N)
+#undef swap_N
+#define swap_N XCONCAT2(swap_,N)
+
+INLINE_SIM_ENDIAN unsigned_N
+endian_t2h_N(unsigned_N raw_in)
+{
+  if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) {
+    return raw_in;
+  }
+  else {
+    _SWAP_N(return,raw_in);
+  }
+}
+
+
+INLINE_SIM_ENDIAN unsigned_N
+endian_h2t_N(unsigned_N raw_in)
+{
+  if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) {
+    return raw_in;
+  }
+  else {
+    _SWAP_N(return,raw_in);
+  }
+}
+
+
+INLINE_SIM_ENDIAN unsigned_N
+swap_N(unsigned_N raw_in)
+{
+  _SWAP_N(return,raw_in);
+}
diff --git a/sim/ppc/sim-endian.c b/sim/ppc/sim-endian.c
new file mode 100644
index 0000000..8edf7a3
--- /dev/null
+++ b/sim/ppc/sim-endian.c
@@ -0,0 +1,79 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _SIM_ENDIAN_C_
+#define _SIM_ENDIAN_C_
+
+#ifndef STATIC_INLINE_ENDIAN
+#define STATIC_INLINE_ENDIAN STATIC_INLINE
+#endif
+
+
+#include "config.h"
+#include "basics.h"
+
+
+#if !defined(_SWAP_1)
+#define _SWAP_1(SET,RAW) SET (RAW)
+#endif
+
+#if !defined(_SWAP_2) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
+#define _SWAP_2(SET,RAW) SET htons (RAW)
+#endif
+
+#ifndef	_SWAP_2
+#define _SWAP_2(SET,RAW) SET (((RAW) >> 8) | ((RAW) << 8))
+#endif
+
+#if !defined(_SWAP_4) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && WITH_NTOH
+#define _SWAP_4(SET,RAW) SET htonl (RAW)
+#endif
+
+#ifndef _SWAP_4
+#define	_SWAP_4(SET,RAW) SET (((RAW) << 24) | (((RAW) & 0xff00) << 8) | (((RAW) & 0xff0000) >> 8) | ((RAW) >> 24))
+#endif
+
+#ifndef _SWAP_8
+#define _SWAP_8(SET,RAW) \
+  union { unsigned_8 dword; unsigned_4 words[2]; } in, out; \
+  in.dword = RAW; \
+  _SWAP_4 (out.words[0] =, in.words[1]); \
+  _SWAP_4 (out.words[1] =, in.words[0]); \
+  SET out.dword;
+#endif
+
+#undef N
+#define N 1
+#include "sim-endian-n.h"
+
+#undef N
+#define N 2
+#include "sim-endian-n.h"
+
+#undef N
+#define N 4
+#include "sim-endian-n.h"
+
+#undef N
+#define N 8
+#include "sim-endian-n.h"
+
+#endif /* _SIM_ENDIAN_C_ */
diff --git a/sim/ppc/sim_calls.c b/sim/ppc/sim_calls.c
index 32bd4f5..5a61e53 100644
--- a/sim/ppc/sim_calls.c
+++ b/sim/ppc/sim_calls.c
@@ -24,6 +24,7 @@
 #include <ctype.h>
 
 #include "basics.h"
+#include "function_unit.h"
 #include "psim.h"
 
 #ifdef HAVE_STDLIB_H
@@ -55,8 +56,6 @@ static int print_info = 0;
 void
 sim_open (char *args)
 {
-  int i;
-
   /* trace the call */
   TRACE(trace_gdb, ("sim_open(args=%s) called\n", args ? args : "(null)"));
 
@@ -77,19 +76,38 @@ sim_open (char *args)
 	while (*p != '\0') {
 	  switch (*p) {
 	  default:
-	    printf_filtered("Usage:\n\ttarget sim [ -t <trace-option> ]\n");
+	    printf_filtered("Usage:\n\ttarget sim [ -t <trace-option> ] [-m model] [-i] [-I]\n");
 	    trace_usage();
 	    error ("");
 	    break;
 	  case 't':
-	    argp += 1;
-	    if (argv[argp] == NULL)
-	      error("Missing <trace> option for -t\n");
-	    trace_option(argv[argp]); /* better fail if NULL */
+	    if (p[1])
+	      trace_option(p+1);
+	    else {
+	      argp += 1;
+	      if (argv[argp] == NULL)
+		error("Missing <trace> option for -t\n");
+	      else
+		trace_option(argv[argp]);
+	    }
 	    break;
-	  case 'I':
+	  case 'm':
+	    if (p[1])
+	      function_unit_model(p+1);
+	    else {
+	      argp += 1;
+	      if (argv[argp] == NULL)
+		error("Missing <trace> option for -t\n");
+	      else
+		function_unit_model(argv[argp]);
+	    }
+	    break;
+	  case 'i':
 	    print_info = 1;
 	    break;
+	  case 'I':
+	    print_info = 2;
+	    break;
 	  }
 	  p += 1;
 	}
@@ -109,7 +127,7 @@ sim_close (int quitting)
 {
   TRACE(trace_gdb, ("sim_close(quitting=%d) called\n", quitting));
   if (print_info)
-    psim_print_info (simulator, 1);
+    psim_print_info (simulator, print_info);
 
   /* nothing to do */
 }
@@ -285,7 +303,6 @@ void
 sim_resume (int step, int siggnal)
 {
   void (*prev) ();
-  unsigned_word program_counter;
 
   TRACE(trace_gdb, ("sim_resume(step=%d, siggnal=%d)\n",
 		    step, siggnal));
diff --git a/sim/ppc/std-config.h b/sim/ppc/std-config.h
index 69359f4..ace2888 100644
--- a/sim/ppc/std-config.h
+++ b/sim/ppc/std-config.h
@@ -246,6 +246,41 @@ extern int current_floating_point;
 #endif
 
 
+/* Include code that simulates function units to model particular
+   machines more closely and provide more detailed information about
+   optimization potential.  */
+
+#ifndef WITH_FUNCTION_UNIT
+#define	WITH_FUNCTION_UNIT		1
+#endif
+
+/* Which specific processor to model */
+typedef enum _ppc_model {
+  PPC_MODEL_UNKNOWN,
+  PPC_MODEL_601,
+  PPC_MODEL_602,
+  PPC_MODEL_603,
+  PPC_MODEL_603e,
+  PPC_MODEL_604,
+  PPC_MODEL_403,
+  PPC_MODEL_505,
+  PPC_MODEL_821,
+  PPC_MODEL_860
+} ppc_model;
+
+#ifndef WITH_DEFAULT_PPC_MODEL
+#define	WITH_DEFAULT_PPC_MODEL PPC_MODEL_603e
+#endif
+
+extern ppc_model current_ppc_model;
+
+#ifndef WITH_PPC_MODEL
+#define	WITH_PPC_MODEL			0
+#endif
+
+#define CURRENT_PPC_MODEL (WITH_PPC_MODEL	\
+			   ? WITH_PPC_MODEL	\
+			   : current_ppc_model)
 
 /* INLINE CODE SELECTION:
 
@@ -309,11 +344,18 @@ extern int current_floating_point;
 #endif
 
 /* Code that converts between hosts and target byte order.  Used on
-   every memory access (instruction and data).  (See ppc-endian.h for
+   every memory access (instruction and data).  (See sim-endian.h for
    additional byte swapping configuration information) */
 
-#ifndef ENDIAN_INLINE
-#define ENDIAN_INLINE			DEFAULT_INLINE
+#ifndef SIM_ENDIAN_INLINE
+#define SIM_ENDIAN_INLINE		DEFAULT_INLINE
+#endif
+
+/* Low level bit manipulation routines used to work around a compiler
+   bug in 2.6.3.  */
+
+#ifndef BITS_INLINE
+#define BITS_INLINE			DEFAULT_INLINE
 #endif
 
 /* Code that gives access to various CPU internals such as registers.
@@ -412,4 +454,10 @@ extern int current_floating_point;
 #define IDECODE_INLINE			DEFAULT_INLINE
 #endif
 
+/* Code to simule functional units of real machines */
+
+#ifndef FUNCTION_UNIT_INLINE
+#define FUNCTION_UNIT_INLINE		DEFAULT_INLINE
+#endif
+
 #endif /* _CONFIG_H */
diff --git a/sim/ppc/table.c b/sim/ppc/table.c
index cc065fc..6bc01d8 100644
--- a/sim/ppc/table.c
+++ b/sim/ppc/table.c
@@ -25,6 +25,7 @@
 #include <fcntl.h>
 #include <ctype.h>
 
+#include "config.h"
 #include "misc.h"
 #include "lf.h"
 #include "table.h"
diff --git a/sim/ppc/vm.c b/sim/ppc/vm.c
index 269f6608d..2feddd5 100644
--- a/sim/ppc/vm.c
+++ b/sim/ppc/vm.c
@@ -485,7 +485,9 @@ om_virtual_to_real(om_map *map,
 	  core_map_read_word(map->physical,
 			     real_address_of_pte + sizeof_pte / 2,
 			     processor, cia);
-	error("fixme - check pte hit\n");
+	error("fixme - check pte hit %ld %ld\n",
+	      (long)pte_word_0,
+	      (long)pte_word_1);
 	if (1) {
 	  error("fixme - update the page_tlb\n");
 	  page_tlb_entry->valid = 1;
diff --git a/sim/ppc/vm_n.h b/sim/ppc/vm_n.h
index 63bd54c..0a9d0a1 100644
--- a/sim/ppc/vm_n.h
+++ b/sim/ppc/vm_n.h
@@ -53,7 +53,6 @@ XCONCAT2(vm_data_map_read_,N)(vm_data_map *map,
       return 0;
     case NONSTRICT_ALIGNMENT:
       {
-	unsigned_N rval;
 	unsigned_N val;
 	if (vm_data_map_read_buffer(map, &val, ea, sizeof(unsigned_N))
 	    != sizeof(unsigned_N))
-- 
cgit v1.1