checkpoint
authorMichael Meissner <gnu@the-meissners.org>
Mon, 13 Nov 1995 16:07:30 +0000 (16:07 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Mon, 13 Nov 1995 16:07:30 +0000 (16:07 +0000)
sim/ppc/ChangeLog
sim/ppc/Makefile.in
sim/ppc/configure.in
sim/ppc/device_tree.c
sim/ppc/device_tree.h
sim/ppc/devices.c
sim/ppc/igen.c
sim/ppc/main.c

index d3e2ab4..aae1bc2 100644 (file)
@@ -1,3 +1,179 @@
+Mon Nov 13 09:14:13 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * igen.c ({insn,model}_table_fields): Spell mnemonic correctly.
+       (gen_itable_h,itable_c_insn): Ditto.
+       (model support): Move model support around, add support for
+       model-data, model-internal.  Use annex field for model-macros
+       now.
+
+       * configure.in (--enable-sim-inline): If --enable-sim-inline=no,
+       also define INLINE as nothing.
+       * configure: Regenerate.
+
+       * std-config.h (INLINE): Rather than nuking INLINE, only define it
+       as __inline__ if any of the INLINE flags are non-zero.
+
+       * options.c (print_options): Print out WITH_XOR_ENDAIN.
+
+Mon Nov 13 23:03:45 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * ppc-instructions (rfi): Add missing code.
+
+       * cpu.c (cpu_get_time_base): Fix calculation of current value of
+        time base register.
+
+       * ppc-spr-table (TBL, TBU): Fix TBL/TBU entries - was confusing
+        m[tf]tb with m[tf]spr.
+
+       * ppc-instructions (mtspr, mfspr): Fix mttbl - wasn't storing
+        lower word.
+
+Mon Nov 13 21:35:37 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * std-config.h (INLINE, STATIC_INLINE): Was being set to static
+        inline..  Only problem being that with ppc-opcode-simple this gave
+        it the chance to inline all the idecode functions with potentially
+        disasterous results on a 16mb PC.  For moment hobble INLINE.
+
+       * configure.in, std-config.h (WITH_SMP): Make that 5 processors by
+        default ...
+
+       * configure.in: Tweek flags passed to gcc for --with-sim-warnings.
+        Firstly make them errors and secondly remove the options gcc-245
+        doesn't reconize.
+
+Mon Nov 13 17:57:24 1995  Andrew Cagney  <cagney@highland.com.au>
+
+       * misc.c (zalloc), cpu.c (cpu_init), devices
+       (console_io_read_buffer_callback, icu_io_read_buffer_callback,
+       vm_io_read_buffer_callback), main.c (zalloc), mon.c (memset),
+       sim_calls.c (zalloc) : replace bzero() with memset().
+
+       * emul_netbsd.c (write_direntries), psim.c (psim_read_register,
+       psim_write_register): replace bcopy() with memcpy().
+       
+Sun Nov 12 20:55:41 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * configure.in: for --disable-sim-inline (--enable-sim-inline=no),
+        force DEFAULT_INLINE to 0 rather then trusting the std
+        configuration.
+
+Sun Nov 12 20:55:41 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * igen.c (lf_print_idecode_table, idecode_table_leaf): Fix
+        generation of switch entries in tables - treat the same as
+        cracking/semantic functions.
+
+       * igen.c (idecode_switch_end, idecode_switch_leaf): Fix generation
+        of a boolean switch statement (field zero or non-zero).
+
+       * ppc-opcode-test-1, ppc-opcode-test-2: New files.  These test the
+        switch/table generation ability of igen.
+
+       * igen.c (idecode_switch_leaf): Fix code output when a switch
+        statement needs to look up a table.
+
+       * igen.c (idecode_declare_if_switch): New function called from
+        gen_idecode_c - need to declare any idecode switch functions
+        before they are used in idecode tables.
+
+       * igen.c (lf_print_c_cracker_function, idecode_crack_leaf,
+        idecode_crack_insn): Add is_inline_function argument to code
+        printing cracker functions which indicates if STATIC_IDECODE or
+        STATIC_INLINE_IDECODE should be used for definition.  For
+        idecode_crack_insn (which implies not duplicating/expanding) don't
+        declare function as inline - we assume that the only time this is
+        code is generated is when things are being tested.  For
+        idecode_crack_leaf, make static (instead of INLINE) if the
+        instructions parent is a table as function will always be called
+        via a table.
+
+       * igen.c (idecode_expand_if_switch): Declare as STATIC_IDECODE not
+        STATIC_INLINE_IDECODE. Only the outermost idecode switch will be
+        called directly, all others are called via a table.
+
+       * igen.c (lf_print_semantic_function_header, semantics_h_leaf,
+        semantics_h_insn, semantics_h_function,
+        lf_print_c_semantic_function, semantics_c_function): Add
+        is_inline_function argument to lf_print_semantic_function_header
+        to indicate if an inline or static function declaration/definition
+        should be output.  Depending on situtation call accordingly:
+        functions (not instruction semantic routines) are always inline;
+        Semantic routines are made inline when there is no icache (cache
+        will contain the function address) and are duplicating (see above)
+        and the parent of the instruction is a switch statement.
+
+       * igen.c (opcode_field_new): Delete.  Code changed to use ZALLOC
+        and moved to insn_table_find_opcode_field.
+
+       * table.c (table_open): Fix typo (nr_model_fields vs nr_fields).
+
+       * igen.c (model_c_insn): Suggestion - document the name of the
+        instruction on each line of the instruction model table.
+
+Fri Nov 10 00:44:38 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * emul_netbsd.c (do_ioctl): Cleanup compilation.
+
+       * sim_callbacks.h (__attribute__): Only define if not defined (was
+        already defined on NetBSD host).
+
+Wed Nov  8 21:49:52 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * std-config.h (WITH_XOR_ENDIAN), configure.in, Makefile.in: New
+        macro, indicates if the PowerPC's horrible XOR endian mode should
+        be suported.  Add to configure and make.
+
+       * vm_n.h (vm_data_map_read_N, vm_data_map_write_N), vm.c
+        (vm_instruction_map_read): If XOR endian, xor the address
+       with a value from an xor table (indexed by size of access).
+
+       * vm.c (vm_synchronize_context), cpu.c (cpu_synchronize_context):
+        set up xor table to xor if there is a conflict between the
+        CURRENT_TARGET_ENDIAN and the endian indicated in the MSR.  Move
+        check of suported change of endian mode from cpu.c to vm.c.
+
+       * vm.c (vm_data_map_write_buffer, vm_data_map_read_buffer):
+        Hopefully added correct hack to handle XOR endian mode.
+
+       FIXME: If NONSTRICT alignment and XOR ENDIAN and MSR indicates
+        little endian mode, the model accepts miss aligned transfers.
+
+       FIXME: Need to create an `init' device that, during
+        initializatioin for XOR mode, it mushes (XOR address) all the dma
+        data before passing it on to the core for storage. Just like the
+        real thing really.
+
+Wed Nov  8 21:49:52 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * devices.c (halt_io_write_buffer_callback): Use value written to
+        halt device to determine exit status.  Thus allowing
+        success/failure of OEA tests.
+
+Wed Nov  8 00:10:38 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * ppc-instructions (icbi): If icache present flush it.
+
+Tue Nov  7 23:36:31 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * devices.c (htab_init_callback): Add code to create htab/pte.
+
+       * devices.c (dma_file, file_init_callback, htab_init_callback):
+        New function - Dma the named file into memory at the specified
+        address.  Use.
+
+       * device_tree.h, device_tree.c (scand_*): New functions.
+
+Tue Nov  7 23:36:31 1995  Andrew Cagney   <cagneyhighland.com.au>
+
+       * filter_filename.c, Makefile.in: Change so that only dependant on
+        a very limited nr of files.  Stops an unnecessary dependency.
+
+Tue Nov  7 15:44:33 1995  Andrew Cagney  <cagney@highland.com.au>
+
+       * core.c (core_map_find_mapping): Use cpu_halt rather than error
+       to abort an access to an undefined address.
+
 Sun Nov 12 07:58:09 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * igen.c (model_table_insert_{macro,function}): New functions.
@@ -439,7 +615,7 @@ Thu Nov  2 08:54:04 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
        * configure.in: Add support for --enable-sim-opcode=stupid.
        * configure: Regenerate.
 
-Wed Nov  1 23:46:59 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Wed Nov  1 23:46:59 1995  Andrew Cagney   <cagney@highland.com.au>
 
        * std-config (INLINE_DEVICE_TREE): Don't inline either of
         device_tree.c or devices.c.  There is no significant gain.
@@ -447,7 +623,7 @@ Wed Nov  1 23:46:59 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
        * configure.in, Makefile.in: add --enable-sim-icache=[0-9]* and
        IGEN_ICACHE macro.
        
-Wed Nov  1 23:46:59 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Wed Nov  1 23:46:59 1995  Andrew Cagney   <cagney@highland.com.au>
 
        * igen.c (main), misc.h (target_a2i, i2target), misc.c: Add
         functions to convert between target and igen internal bit numbers.
@@ -455,17 +631,17 @@ Wed Nov  1 23:46:59 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
         bit nr) options to igen.  Typical usage would be: ./igen -b 16 -h
         15 for a 16 bit instruction format with the msb given a number 15.
 
-Wed Nov  1 22:17:32 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Wed Nov  1 22:17:32 1995  Andrew Cagney   <cagney@highland.com.au>
 
        * dgen.c (main): Was outputting optarg even when it was NULL.
 
-Tue Oct 31 23:48:33 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Tue Oct 31 23:48:33 1995  Andrew Cagney   <cagney@highland.com.au>
 
        * vm_n.h (vm_data_map_load_N, vm_data_map_store_n), debug.h,
         debug.c: Add tracing of load/store unit (virtual) with -t
         load-store.
 
-Tue Oct 31 21:44:01 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Tue Oct 31 21:44:01 1995  Andrew Cagney   <cagney@highland.com.au>
 
         * std-config.h (WITH_ENVIRONMENT): Add USER_ENVIRONMENT which does
         not include things such as the time base and events.
@@ -477,7 +653,7 @@ Tue Oct 31 21:44:01 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
         /options/environment-architecture with values user, virtual and
         operating.
 
-Tue Oct 31 21:31:32 1995  Andrew Cagney - aka Noid  <cagney@highland.com.au>
+Tue Oct 31 21:31:32 1995  Andrew Cagney   <cagney@highland.com.au>
 
        * ppc-opcode-stupid: Third example of use of opcode table - this
         one expands all mtspr/mfspr and branch instructions.  Appears to
index 48d9452..ccf0ab2 100644 (file)
@@ -72,6 +72,7 @@ BSWAP_CFLAGS = @sim_bswap@
 ENDIAN_CFLAGS = @sim_endian@
 HOSTENDIAN_CFLAGS = @sim_hostendian@
 SMP_CFLAGS = @sim_smp@
+XOR_ENDIAN_CFLAGS = @sim_xor_endian@
 BITSIZE_CFLAGS = @sim_bitsize@
 HOSTBITSIZE_CFLAGS = @sim_hostbitsize@
 ENV_CFLAGS = @sim_env@
@@ -89,6 +90,7 @@ CONFIG_CFLAGS = $(BSWAP_CFLAGS) \
   $(ENDIAN_CFLAGS) \
   $(HOSTENDIAN_CFLAGS) \
   $(SMP_CFLAGS) \
+  $(XOR_ENDIAN_CFLAGS) \
   $(BITSIZE_CFLAGS) \
   $(HOSTBITSIZE_CFLAGS) \
   $(ENV_CFLAGS) \
@@ -281,7 +283,7 @@ 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 config.h ppc-config.h
+filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h
 
 sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
 
index b2a0ee4..acb0442 100644 (file)
@@ -16,7 +16,7 @@ fi],[sim_cflags=""])dnl
 AC_ARG_ENABLE(sim-warnings,
 [  --enable-sim-warnings=opts          Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o],
 [case "${enableval}" in
-  yes) sim_warnings="-Wall -Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wmissing-declarations";;
+  yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";;
   no)  sim_warnings="-w";;
   *)   sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
 esac
@@ -125,7 +125,7 @@ AC_ARG_ENABLE(sim-inline,
 [  --enable-sim-inline=inlines         Specify which functions should be inlined.],
 [sim_inline=""
 case "$enableval" in
-  no)          sim_inline="";;
+  no)          sim_inline="-DDEFAULT_INLINE=0 -DINLINE=";;
   0)           sim_inline="-DDEFAULT_INLINE=0";;
   yes | 2)     sim_inline="-DDEFAULT_INLINE=2";;
   1)           sim_inline="-DDEFAULT_INLINE=1";;
@@ -198,7 +198,7 @@ fi],[sim_hostendian=""])dnl
 AC_ARG_ENABLE(sim-smp,
 [  --enable-sim-smp=n                  Specify number of processors to configure for.],
 [case "${enableval}" in
-  yes) sim_smp="-DWITH_SMP=2";;
+  yes) sim_smp="-DWITH_SMP=5";;
   no)  sim_smp="-DWITH_SMP=0";;
   *)   sim_smp="-DWITH_SMP=$enableval";;
 esac
@@ -209,6 +209,14 @@ if test x"$silent" != x"yes"; then
   echo "Setting smp flags = $sim_smp" 6>&1
 fi])dnl
 
+AC_ARG_ENABLE(sim-xor-endian,
+[  --enable-sim-xor-endian=n           Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).],
+[case "${enableval}" in
+  yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";;
+  no)  sim_xor_endian="-DWITH_XOR_ENDIAN=0";;
+  *)   sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";;
+esac],[sim_xor_endian=""])dnl
+
 AC_ARG_ENABLE(sim-bitsize,
 [  --enable-sim-bitsize=n              Specify target bitsize (32 or 64).],
 [case "${enableval}" in
@@ -377,6 +385,7 @@ AC_SUBST(sim_icache)
 AC_SUBST(sim_inline)
 AC_SUBST(sim_bswap)
 AC_SUBST(sim_endian)
+AC_SUBST(sim_xor_endian)
 AC_SUBST(sim_hostendian)
 AC_SUBST(sim_smp)
 AC_SUBST(sim_bitsize)
index 0fb019b..51d828c 100644 (file)
@@ -464,43 +464,49 @@ device_tree_dump(device_tree *device,
 
 /* Parse a device name, various formats */
 
-#define SCAN_INIT(START, END, COUNT, NAME) \
-  char *START = NULL; \
-  char *END = strchr(NAME, '@'); \
-  int COUNT = 0; \
-  if (END == NULL) \
-    return 0; \
+#define SCAN_INIT(NAME) \
+  char *START = (char*)0; \
+  char *END = (char*)0; \
+  int COUNT = -1; \
+  /* find the first element */ \
+  END = strchr(NAME, '@'); \
+  if (END == (char*)0) \
+    return COUNT; \
+  COUNT += 1; \
   START = END + 1
 
-#define SCAN_U(START, END, COUNT, U) \
+#define SCAN_END \
+  return COUNT
+
+#define SCAN_U(U) \
 do { \
   *U = strtoul(START, &END, 0); \
   if (START == END) \
     return COUNT; \
-  COUNT++; \
+  COUNT += 1; \
   if (*END != ',') \
     return COUNT; \
   START = END + 1; \
 } while (0)
 
-#define SCAN_P(START, END, COUNT, P) \
+#define SCAN_P(P) \
 do { \
-  *P = (void*)(unsigned)strtouq(START, &END, 0); \
+  *P = (void*)(unsigned)strtouq(START, END, 0); \
   if (START == END) \
     return COUNT; \
-  COUNT++; \
+  COUNT += 1; \
   if (*END != ',') \
     return COUNT; \
   START = END + 1; \
 } while (0)
 
-#define SCAN_C(START, END, COUNT, C, SIZE) \
+#define SCAN_C(C, SIZE) \
 do { \
   char *chp = C; \
   END = START; \
   while (*END != '\0' && *END != ',') { \
     if (*END == '\\') \
-      END++; \
+      END += 1; \
     *chp = *END; \
     chp += 1; \
     END += 1; \
@@ -510,19 +516,55 @@ do { \
   *chp = '\0'; \
   if (START == END) \
     return COUNT; \
-  COUNT++; \
+  COUNT += 1; \
   if (*END != ',') \
     return COUNT; \
   START = END + 1; \
 } while (0)
 
 INLINE_DEVICE_TREE int
+scand_c(const char *name,
+       char *c1,
+       unsigned c1size)
+{
+  SCAN_INIT(name);
+  SCAN_C(c1, c1size);
+  SCAN_END;
+}
+
+INLINE_DEVICE_TREE int
+scand_c_uw_u(const char *name,
+            char *c1,
+            unsigned c1size,
+            unsigned_word *uw2,
+            unsigned *u3)
+{
+  SCAN_INIT(name);
+  SCAN_C(c1, c1size);
+  SCAN_U(uw2);
+  SCAN_U(u3);
+  SCAN_END;
+}
+
+INLINE_DEVICE_TREE int
 scand_uw(const char *name,
         unsigned_word *uw1)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_U(start, end, count, uw1);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_END;
+}
+
+INLINE_DEVICE_TREE int
+scand_uw_c(const char *name,
+          unsigned_word *uw1,
+          char *c2,
+          unsigned c2size)
+{
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_C(c2, c2size);
+  SCAN_END;
 }
 
 INLINE_DEVICE_TREE int
@@ -530,10 +572,10 @@ scand_uw_u(const char *name,
           unsigned_word *uw1,
           unsigned *u2)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_U(start, end, count, uw1);
-  SCAN_U(start, end, count, u2);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(u2);
+  SCAN_END;
 }
 
 INLINE_DEVICE_TREE int
@@ -542,11 +584,22 @@ scand_uw_u_u(const char *name,
             unsigned *u2,
             unsigned *u3)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_U(start, end, count, uw1);
-  SCAN_U(start, end, count, u2);
-  SCAN_U(start, end, count, u3);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(u2);
+  SCAN_U(u3);
+  SCAN_END;
+}
+
+INLINE_DEVICE_TREE int
+scand_uw_uw(const char *name,
+           unsigned_word *uw1,
+           unsigned_word *uw2)
+{
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(uw2);
+  SCAN_END;
 }
 
 INLINE_DEVICE_TREE int
@@ -555,33 +608,46 @@ scand_uw_uw_u(const char *name,
              unsigned_word *uw2,
              unsigned *u3)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_U(start, end, count, uw1);
-  SCAN_U(start, end, count, uw2);
-  SCAN_U(start, end, count, u3);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(uw2);
+  SCAN_U(u3);
+  SCAN_END;
 }
 
 INLINE_DEVICE_TREE int
-scand_c(const char *name,
-       char *c1, int c1size)
+scand_uw_uw_u_u_c(const char *name,
+                 unsigned_word *uw1,
+                 unsigned_word *uw2,
+                 unsigned *u3,
+                 unsigned *u4,
+                 char *c5,
+                 unsigned c5size)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_C(start, end, count, c1, c1size);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(uw2);
+  SCAN_U(u3);
+  SCAN_U(u4);
+  SCAN_C(c5, c5size);
+  SCAN_END;
 }
 
 INLINE_DEVICE_TREE int
-scand_c_uw_u(const char *name,
-            char *c1, int c1size,
-            unsigned_word *uw2,
-            unsigned *u3)
+scand_uw_uw_u_u_u(const char *name,
+                 unsigned_word *uw1,
+                 unsigned_word *uw2,
+                 unsigned *u3,
+                 unsigned *u4,
+                 unsigned *u5)
 {
-  SCAN_INIT(start, end, count, name);
-  SCAN_C(start, end, count, c1, c1size);
-  SCAN_U(start, end, count, uw2);
-  SCAN_U(start, end, count, u3);
-  return count;
+  SCAN_INIT(name);
+  SCAN_U(uw1);
+  SCAN_U(uw2);
+  SCAN_U(u3);
+  SCAN_U(u4);
+  SCAN_U(u5);
+  SCAN_END;
 }
 
 
@@ -634,6 +700,43 @@ enum {
 };
 
 INLINE_DEVICE_TREE char *
+printd_c(const char *name,
+        const char *c1)
+{
+  int sizeof_buf = (strlen(name)
+                   + strlen("@")
+                   + c_strlen(c1)
+                   + 1);
+  char *buf = (char*)zalloc(sizeof_buf);
+  strcpy(buf, name);
+  strcat(buf, "@");
+  c_strcat(buf, c1);
+  ASSERT(strlen(buf) < sizeof_buf);
+  return buf;
+}
+
+INLINE_DEVICE_TREE char *
+printd_c_uw(const char *name,
+           const char *c1,
+           unsigned_word uw2)
+{
+  int sizeof_buf = (strlen(name)
+                   + strlen("@")
+                   + c_strlen(c1)
+                   + strlen(",")
+                   + strlen_unsigned_word
+                   + 1);
+  char *buf = (char*)zalloc(sizeof_buf);
+  strcpy(buf, name);
+  strcat(buf, "@");
+  c_strcat(buf, c1);
+  strcat(buf, ",");
+  u_strcat(buf, uw2);
+  ASSERT(strlen(buf) < sizeof_buf);
+  return buf;
+}
+
+INLINE_DEVICE_TREE char *
 printd_uw_u(const char *name,
            unsigned_word uw1,
            unsigned u2)
@@ -711,41 +814,4 @@ printd_uw_u_u_c(const char *name,
   return buf;
 }
 
-INLINE_DEVICE_TREE char *
-printd_c(const char *name,
-        const char *c1)
-{
-  int sizeof_buf = (strlen(name)
-                   + strlen("@")
-                   + c_strlen(c1)
-                   + 1);
-  char *buf = (char*)zalloc(sizeof_buf);
-  strcpy(buf, name);
-  strcat(buf, "@");
-  c_strcat(buf, c1);
-  ASSERT(strlen(buf) < sizeof_buf);
-  return buf;
-}
-
-INLINE_DEVICE_TREE char *
-printd_c_uw(const char *name,
-           const char *c1,
-           unsigned_word uw2)
-{
-  int sizeof_buf = (strlen(name)
-                   + strlen("@")
-                   + c_strlen(c1)
-                   + strlen(",")
-                   + strlen_unsigned_word
-                   + 1);
-  char *buf = (char*)zalloc(sizeof_buf);
-  strcpy(buf, name);
-  strcat(buf, "@");
-  c_strcat(buf, c1);
-  strcat(buf, ",");
-  u_strcat(buf, uw2);
-  ASSERT(strlen(buf) < sizeof_buf);
-  return buf;
-}
-
 #endif /* _DEVICE_TREE_C_ */
index bcd9bea..765c20e 100644 (file)
@@ -116,10 +116,28 @@ INLINE_DEVICE_TREE void device_tree_dump
    u: unsigned
    c: string */
 
+INLINE_DEVICE_TREE int scand_c
+(const char *name,
+ char *c1,
+ unsigned c1size);
+
+INLINE_DEVICE_TREE int scand_c_uw_u
+(const char *name,
+ char *c1,
+ unsigned c1size,
+ unsigned_word *uw2,
+ unsigned *u3);
 INLINE_DEVICE_TREE int scand_uw
 (const char *name,
  unsigned_word *uw1);
  
+INLINE_DEVICE_TREE int scand_uw_c
+(const char *name,
+ unsigned_word *uw1,
+ char *c2,
+ unsigned c2size);
 INLINE_DEVICE_TREE int scand_uw_u
 (const char *name,
  unsigned_word *uw1,
@@ -131,21 +149,42 @@ INLINE_DEVICE_TREE int scand_uw_u_u
  unsigned *u2,
  unsigned *u3);
  
+INLINE_DEVICE_TREE int scand_uw_uw
+(const char *name,
+ unsigned_word *uw1,
+ unsigned_word *uw2);
+
 INLINE_DEVICE_TREE int scand_uw_uw_u
 (const char *name,
  unsigned_word *uw1,
  unsigned_word *uw2,
  unsigned *u3);
  
-INLINE_DEVICE_TREE int scand_c
+INLINE_DEVICE_TREE int scand_uw_uw_u_u_c
 (const char *name,
- char *c1, int c1size);
-
-INLINE_DEVICE_TREE int scand_c_uw_u
+ unsigned_word *uw1,
+ unsigned_word *uw2,
+ unsigned *u3,
+ unsigned *u4,
+ char *c5,
+ unsigned c5size);
+INLINE_DEVICE_TREE int scand_uw_uw_u_u_u
 (const char *name,
char *c1, int c1size,
unsigned_word *uw1,
  unsigned_word *uw2,
- unsigned *u3);
+ unsigned *u3,
+ unsigned *u4,
+ unsigned *u5);
+INLINE_DEVICE_TREE char *printd_c
+(const char *name,
+ const char *c1);
+
+INLINE_DEVICE_TREE char *printd_c_uw
+(const char *name,
+ const char *c1,
+ unsigned_word uw2);
 
 INLINE_DEVICE_TREE char *printd_uw_u
 (const char *name,
@@ -165,13 +204,4 @@ INLINE_DEVICE_TREE char *printd_uw_u_u_c
  unsigned u3,
  const char *c4);
 
-INLINE_DEVICE_TREE char *printd_c
-(const char *name,
- const char *c1);
-
-INLINE_DEVICE_TREE char *printd_c_uw
-(const char *name,
- const char *c1,
- unsigned_word uw2);
-
 #endif /* _DEVICE_TREE_H_ */
index 257b8eb..39f6103 100644 (file)
@@ -80,6 +80,47 @@ generic_init_callback(const device *me,
 }
 
 
+/* DMA a file into memory */
+STATIC_INLINE_DEVICES int
+dma_file(const device *me,
+        const char *file_name,
+        unsigned_word addr)
+{
+  int count;
+  int inc;
+  FILE *image;
+  char buf[1024];
+
+  /* get it open */
+  image = fopen(file_name, "r");
+  if (image == NULL)
+    return -1;
+
+  /* read it in slowly */
+  count = 0;
+  while (1) {
+    inc = fread(buf, sizeof(buf), 1, image);
+    if (inc <= 0)
+      break;
+    if (me->parent->callback->dma_write_buffer(me->parent,
+                                              buf,
+                                              0 /*address-space*/,
+                                              addr+count,
+                                              inc /*nr-bytes*/,
+                                              1 /*violate ro*/) != inc) {
+      fclose(image);
+      return -1;
+    }
+    count += inc;
+  }
+
+  /* close down again */
+  fclose(image);
+
+  return count;
+}
+
+
 \f
 /* inimplemented versions of each function */
 
@@ -319,7 +360,7 @@ pass_device_interrupt(const device *me,
 
 
 \f
-/* Simple console device: console@)x<address>,16
+/* Simple console device: console@<address>,16
 
    Input characters are taken from the keyboard, output characters
    sent to the terminal.  Echoing of characters is not disabled.
@@ -423,7 +464,7 @@ console_io_read_buffer_callback(const device *me,
 
   }
 
-  bzero(dest, nr_bytes);
+  memset(dest, 0, nr_bytes);
   *(unsigned_1*)dest = val;
   return nr_bytes;
 }
@@ -438,7 +479,7 @@ console_io_write_buffer_callback(const device *me,
                                 unsigned_word cia)
 {
   console_device *console = (console_device*)me->data;
-  unsigned_1 val = *(unsigned8*)source;
+  unsigned_1 val = *(unsigned_1*)source;
   DTRACE_IO_WRITE_BUFFER(console);
 
   switch ((int)addr) {
@@ -529,7 +570,7 @@ icu_io_read_buffer_callback(const device *me,
   unsigned_1 val;
   DTRACE_IO_READ_BUFFER(icu);
   val = cpu_nr(processor);
-  bzero(dest, nr_bytes);
+  memset(dest, 0, nr_bytes);
   *(unsigned_1*)dest = val;
   return nr_bytes;
 }
@@ -605,7 +646,7 @@ halt_io_write_buffer_callback(const device *me,
                              unsigned_word cia)
 {
   DTRACE_IO_WRITE_BUFFER(halt);
-  cpu_halt(processor, cia, was_exited, 0);
+  cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
   return 0;
 }
 
@@ -820,7 +861,7 @@ vm_io_read_buffer_callback(const device *me,
 {
   DTRACE_IO_READ_BUFFER(vm);
   if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
-    bzero(dest, nr_bytes); /* always initialized to zero */
+    memset(dest, 0, nr_bytes); /* always initialized to zero */
     return nr_bytes;
   }
   else 
@@ -1062,38 +1103,17 @@ file_init_callback(const device *me,
                   psim *system)
 {
   unsigned_word addr;
-  unsigned count;
-  char *file_name;
-  char buf;
-  FILE *image;
+  int count;
+  char file_name[1024];
   DTRACE_INIT(file);
 
-  if ((file_name = strchr(me->name, ',')) == NULL
-      || scand_uw(me->name, &addr) != 1)
-    error("file_init_callback() invalid file device %s\n", me->name);
-
-  /* open the file to load */
-  file_name++; /* skip the `,' */
-  image = fopen(file_name, "r");
-  if (image == NULL)
-    error("file_init_callback() file open failed for %s\n", me->name);
-
-  /* read it in slowly */
-  count = 0;
-  while (fread(&buf, 1, 1, image) > 0) {
-    if (me->parent->callback->dma_write_buffer(me->parent,
-                                              &buf,
-                                              0 /*address-space*/,
-                                              addr+count,
-                                              1 /*nr-bytes*/,
-                                              1 /*violate ro*/) != 1)
-      error("file_init_callback() failed to write to address 0x%x, offset %d\n",
-           addr+count, count);
-    count++;
-  }
-
-  /* close down again */
-  fclose(image);
+  if (scand_uw_c(me->name, &addr, file_name, sizeof(file_name)) != 2)
+    error("devices/file - Usage: file@<address>,<file-name>\n");
+  /* load the file */
+  count = dma_file(me, file_name, addr);
+  if (count < 0)
+    error("devices/%s - Problem loading file %s\n", me->name, file_name);
 }
 
 
@@ -1114,8 +1134,9 @@ static device_callbacks const file_callbacks = {
 
 
 \f
-/* HTAB: htab@0x<address>,<nr_bytes>
-   PTE: pte@0x<effective-address>,0x<real-address>,<nr_bytes>
+/* HTAB: htab@<address>,<nr_bytes>
+   PTE: pte@<virtual-address>,<real-address>,<wimg>,<pp>,<nr_bytes>
+   PTE: pte@<virtual-address>,<real-address>,<wimg>,<pp>,<file>
 
    HTAB defines the location (in physical memory) of a HASH table.
    PTE (as a child of HTAB) defines a mapping that is to be entered
@@ -1131,22 +1152,115 @@ htab_init_callback(const device *me,
                   psim *system)
 {
   DTRACE_INIT(htab);
+  if (WITH_TARGET_WORD_BITSIZE != 32)
+    error("devices/htab: only 32bit targets currently suported\n");
   /* only the pte does work */
   if (strncmp(me->name, "pte@", strlen("pte@")) == 0) {
-    unsigned_word htab_ra;
+    unsigned32 htab_ra;
     unsigned htab_nr_bytes;
-    unsigned_word pte_ea;
-    unsigned_word pte_ra;
+    signed32 pte_va; /* so that 0xff...0 is make 0xffffff00 */
+    unsigned32 pte_ra;
     unsigned pte_nr_bytes;
+    unsigned pte_wimg;
+    unsigned pte_pp;
+    unsigned32 ra;
+    unsigned64 va;
+    unsigned32 htaborg;
+    unsigned32 htabmask;
+    unsigned32 n;
+
     /* determine the location/size of the hash table */
+    if (me->parent == NULL
+       || strncmp(me->parent->name, "htab@", strlen("htab@")) != 0)
+      error("devices/%s - Parent is not a htab device\n", me->name);
     if (scand_uw_u(me->parent->name, &htab_ra, &htab_nr_bytes) != 2)
-      error("htab_init_callback() htab entry %s invalid\n",
+      error("devices/%s - Usage: htab@<real-addr>,<nr_bytes>\n",
            me->parent->name);
+    htabmask = EXTRACTED32(htab_nr_bytes - 1, 7, 15);
+    for (n = htab_nr_bytes; n > 1; n = n / 2) {
+      if (n % 2 != 0)
+       error("devices/%s - htabmask 0x%x (size 0x%x) not a power of two\n",
+             me->parent->name, htabmask, htab_nr_bytes);
+    }
+    htaborg = htab_ra;
+    if ((htaborg & INSERTED32(htabmask, 7, 15)) != 0) {
+      error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
+           me->parent->name, htaborg, htabmask);
+    }
+
     /* determine the location/size of the mapping */
-    if (scand_uw_uw_u(me->name, &pte_ea, &pte_ra, &pte_nr_bytes) != 3)
-      error("htab_init_callback() pte entry %s invalid\n", me->name);
-    error("Map ea=0x%x, ra=0x%x, nr_bytes=%d using htab=0x%x, nr_bytes=%d\n",
-         pte_ea, pte_ra, pte_nr_bytes, htab_ra, htab_nr_bytes);
+    if (scand_uw_uw_u_u_u(me->name, &pte_va, &pte_ra,
+                         &pte_wimg, &pte_pp, &pte_nr_bytes) != 5) {
+      int nr_bytes;
+      char file_name[1024];
+      if (scand_uw_uw_u_u_c(me->name, &pte_va, &pte_ra, &pte_wimg, &pte_pp,
+                           file_name, sizeof(file_name)) != 5)
+       error("devices/%s - Usage: %s\nor\t%s\n",
+             me->name,
+             "pte@<virtual-addr>,<real-addr>,<wimg>,<pp>,<nr-bytes>",
+             "pte@<virtual-addr>,<real-addr>,<wimg>,<pp>,<file>");
+      /* load/validate it */
+      nr_bytes = dma_file(me, file_name, pte_ra);
+      if (nr_bytes < 0)
+       error("devices/%s - problem loading file %s\n", me->name, file_name);
+      pte_nr_bytes = nr_bytes;
+    }
+
+    /* go through all pages and create a pte for each */
+    for (ra = pte_ra, va = (signed32)pte_va;
+        ra < pte_ra + pte_nr_bytes;
+        ra += 1024, va += 1024) {
+      unsigned64 vpn = va << 12;
+      unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
+      unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
+      unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
+                                  ^ EXTRACTED32(page, 0, 15),
+                                  0, 18);
+      int h;
+      for (h = 0; h < 2; h++) {
+       unsigned32 pteg = (htaborg
+                          | INSERTED32(EXTRACTED32(hash, 0, 8) & htabmask, 7, 15)
+                          | INSERTED32(EXTRACTED32(hash, 9, 18), 16, 25));
+       int pti;
+       for (pti = 0; pti < 8; pti++, pteg += 8) {
+         unsigned32 pte0;
+         if (me->parent->callback->dma_read_buffer(me->parent,
+                                                   &pte0,
+                                                   0, /*space*/
+                                                   pteg,
+                                                   sizeof(pte0)) != 4)
+           error("htab_init_callback() failed to read a pte at 0x%x\n",
+                 pteg);
+         if (!MASKED32(pte0, 0, 0)) {
+           /* empty pte fill it */
+           unsigned32 pte0 = (MASK32(0, 0)
+                              | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
+                              | INSERTED32(h, 25, 25)
+                              | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
+           unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
+                              | INSERTED32(pte_wimg, 25, 28)
+                              | INSERTED32(pte_pp, 30, 31));
+           if (me->parent->callback->dma_write_buffer(me->parent,
+                                                      &pte0,
+                                                      0, /*space*/
+                                                      pteg,
+                                                      sizeof(pte0),
+                                                      1/*ro?*/) != 4
+               || me->parent->callback->dma_write_buffer(me->parent,
+                                                         &pte1,
+                                                         0, /*space*/
+                                                         pteg + 4,
+                                                         sizeof(pte1),
+                                                         1/*ro?*/) != 4)
+             error("htab_init_callback() failed to write a pte a 0x%x\n",
+                   pteg);
+           return;
+         }
+       }
+       /* re-hash */
+       hash = MASKED32(~hash, 0, 18);
+      }
+    }
   }
 }
 
@@ -1194,7 +1308,7 @@ static device_callbacks const sim_callbacks = {
 
 
 \f
-/* Load device: *binary@<file-name>
+/* Load device: binary@<file-name>
 
    Assuming that <file-name> is an executable file understood by BFD,
    this device loads or maps the relevant text/data segments into
@@ -1281,20 +1395,19 @@ STATIC_INLINE_DEVICES void
 binary_init_callback(const device *me,
                     psim *system)
 {
-  char file_name[100];
+  char file_name[1024];
   bfd *image;
   DTRACE_INIT(binary);
 
   /* get a file name */
   if (scand_c(me->name, file_name, sizeof(file_name)) != 1)
-    error("load_binary_init_callback() invalid load-binary device %s\n",
-         me->name);
+    error("devices/binary - Usage: binary@<file-name>\n");
 
   /* open the file */
   image = bfd_openr(file_name, NULL);
   if (image == NULL) {
-    bfd_perror("open failed:");
-    error("nothing loaded\n");
+    bfd_perror("devices/binary");
+    error("devices/%s - the file %s not loaded\n", me->name, file_name);
   }
 
   /* check it is valid */
index c1ec541..4eb2310 100644 (file)
@@ -513,16 +513,6 @@ struct _opcode_field {
   opcode_field *parent;
 };
 
-static opcode_field *
-opcode_field_new(void)
-{
-  opcode_field *new_field = (opcode_field*)zalloc(sizeof(opcode_field));
-  ASSERT(new_field != NULL);
-  new_field->first = insn_size;
-  new_field->last = -1;
-  return new_field;
-}
-
 static void
 dump_opcode_field(opcode_field *field, int indent, int levels)
 {
@@ -575,7 +565,7 @@ typedef enum {
   insn_format,
   insn_form,
   insn_flags,
-  insn_nmemonic,
+  insn_mnemonic,
   insn_name,
   insn_comment,
   nr_insn_table_fields
@@ -588,7 +578,8 @@ typedef enum {
 } function_table_fields;
 
 typedef enum {
-  model_name = insn_nmemonic,
+  model_default = insn_form,
+  model_name = insn_mnemonic,
   model_identifer = insn_name,
   model_func = insn_comment,
 } model_table_fields;
@@ -654,6 +645,12 @@ static insn *last_model_macro;
 static insn *model_functions;
 static insn *last_model_function;
 
+static insn *model_internal;
+static insn *last_model_internal;
+
+static insn *model_data;
+static insn *last_model_data;
+
 static void
 insn_table_insert_function(insn_table *table,
                           table_entry *file_entry)
@@ -670,159 +667,6 @@ insn_table_insert_function(insn_table *table,
   table->last_function = new_function;
 }
 
-
-static void
-model_table_insert(insn_table *table,
-                  table_entry *file_entry)
-{
-  /* create a new model */
-  model *new_model = ZALLOC(model);
-  model_func_unit *func_unit;
-  char *ptr, *end, *end_name, *comment, *name;
-  int ch;
-  int name_len;
-  int func_name_len;
-  unsigned unit, mask;
-  int number;
-
-  new_model->name = file_entry->fields[model_identifer];
-  new_model->printable_name = file_entry->fields[model_name];
-  name_len = strlen(new_model->name);
-
-  /* append it to the end of the model list */
-  if (last_model)
-    last_model->next = new_model;
-  else
-    models = new_model;
-  last_model = new_model;
-
-  /* Parse the function units separated by commas */
-  unit = 1;
-  for (ptr = file_entry->fields[model_func];
-       ((ch = *ptr) != '\0') && (ch != '\n');
-       ptr = (*end == ',') ? end+1 : end) {
-
-    while (ch == ' ' || ch == '\t')
-      ch = *++ptr;
-
-    if (!ch || ch == '\n')
-      break;
-
-    /* Search for comma or newline ending field */
-    end = ptr;
-    end_name = (char *)0;
-
-    if (ch == ',')
-      continue;
-
-    while (ch != '\0' && ch != ',' && ch != '\n') {
-      if (end_name == (char *)0 && (ch == '=' || isspace(ch)))
-       end_name = end;
-
-      ch = *++end;
-    }
-    if (!end_name)
-      end_name = end;
-
-    func_unit = ZALLOC(model_func_unit);
-    if (new_model->func_unit_end)
-      new_model->func_unit_end->next = func_unit;
-    else
-      new_model->func_unit_start = func_unit;
-
-    new_model->func_unit_end = func_unit;
-
-    /* Record function unit name as model name _ unit name */
-    func_name_len = name_len + end_name - ptr + 2;
-    if (table->max_func_unit_name_len < func_name_len)
-      table->max_func_unit_name_len = func_name_len;
-
-    func_unit->name = name = (char *)zalloc(func_name_len);
-    memcpy(name, new_model->name, name_len);
-    name[name_len] = '_';
-    memcpy(name + name_len + 1, ptr, end_name - ptr);
-
-    /* See if there are multiple functional units */
-    if (*end_name == '=') {
-      number = 0;
-      for(end_name++; end_name < end && isdigit(*end_name); end_name++)
-       number = number * 10 + (*end_name - '0');
-    } else {
-      number = 1;
-    }
-
-    /* Now figure out the mask for these unit(s) */
-    func_unit->number = number;
-    mask = 0;
-    while (number--) {
-      ASSERT(unit != 0);
-      mask |= unit;
-      unit <<= 1;
-    }
-    func_unit->mask = mask;
-    table->max_func_unit_mask |= mask;
-
-    /* Now figure out comments */
-    for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++)
-      ;
-
-    if (comment < end) {
-      func_unit->comment = (char *)zalloc(end - comment + 1);
-      memcpy(func_unit->comment, comment, end - comment);
-    }
-  }
-
-  /* Add an 'sentinel' function unit at the end to simpify the loop */
-  func_unit = ZALLOC(model_func_unit);
-  if (new_model->func_unit_end)
-    new_model->func_unit_end->next = func_unit;
-  else
-    new_model->func_unit_start = func_unit;
-
-  new_model->func_unit_end = func_unit;
-
-  /* Record function unit name as model name _ unit name */
-  func_name_len = name_len + sizeof("_SENTINEL");
-  if (table->max_func_unit_name_len < func_name_len)
-    table->max_func_unit_name_len = func_name_len;
-
-  func_unit->name = name = (char *)zalloc(func_name_len);
-  func_unit->number = 0;
-  func_unit->mask = unit;
-  func_unit->comment = "dummy";
-  table->max_func_unit_mask |= unit;
-
-  memcpy(name, new_model->name, name_len);
-  strcpy(name + name_len, "_SENTINEL");
-}
-
-static void
-model_table_insert_macro(insn_table *table,
-                        table_entry *file_entry)
-{
-  insn *macro = ZALLOC(insn);
-  macro->file_entry = file_entry;
-  if (last_model_macro)
-    last_model_macro->next = macro;
-  else
-    model_macros = macro;
-  last_model_macro = macro;
-}
-
-static void
-model_table_insert_function(insn_table *table,
-                           table_entry *file_entry)
-{
-  insn *func = ZALLOC(insn);
-  func->file_entry = file_entry;
-  if (last_model_function)
-    last_model_function->next = func;
-  else
-    model_functions = func;
-  last_model_function = func;
-}
-
-
 static void
 insn_table_insert_insn(insn_table *table,
                       table_entry *file_entry,
@@ -877,11 +721,12 @@ insn_table_find_opcode_field(insn *insns,
                             opcode_rules *rule,
                             int string_only)
 {
-  opcode_field *curr_opcode = opcode_field_new();
+  opcode_field *curr_opcode = ZALLOC(opcode_field);
   insn *entry;
-
   ASSERT(rule);
 
+  curr_opcode->first = insn_size;
+  curr_opcode->last = -1;
   for (entry = insns; entry != NULL; entry = entry->next) {
     insn_fields *fields = entry->fields;
     opcode_field new_opcode;
@@ -1121,6 +966,147 @@ insn_table_expand_insns(insn_table *table)
 }
 
 
+static void
+model_table_insert(insn_table *table,
+                  table_entry *file_entry)
+{
+  /* create a new model */
+  model *new_model = ZALLOC(model);
+  model_func_unit *func_unit;
+  char *ptr, *end, *end_name, *comment, *name;
+  int ch;
+  int name_len;
+  int func_name_len;
+  unsigned unit, mask;
+  int number;
+
+  new_model->name = file_entry->fields[model_identifer];
+  new_model->printable_name = file_entry->fields[model_name];
+  name_len = strlen(new_model->name);
+
+  /* append it to the end of the model list */
+  if (last_model)
+    last_model->next = new_model;
+  else
+    models = new_model;
+  last_model = new_model;
+
+  /* Parse the function units separated by commas */
+  unit = 1;
+  for (ptr = file_entry->fields[model_func];
+       ((ch = *ptr) != '\0') && (ch != '\n');
+       ptr = (*end == ',') ? end+1 : end) {
+
+    while (ch == ' ' || ch == '\t')
+      ch = *++ptr;
+
+    if (!ch || ch == '\n')
+      break;
+
+    /* Search for comma or newline ending field */
+    end = ptr;
+    end_name = (char *)0;
+
+    if (ch == ',')
+      continue;
+
+    while (ch != '\0' && ch != ',' && ch != '\n') {
+      if (end_name == (char *)0 && (ch == '=' || isspace(ch)))
+       end_name = end;
+
+      ch = *++end;
+    }
+    if (!end_name)
+      end_name = end;
+
+    func_unit = ZALLOC(model_func_unit);
+    if (new_model->func_unit_end)
+      new_model->func_unit_end->next = func_unit;
+    else
+      new_model->func_unit_start = func_unit;
+
+    new_model->func_unit_end = func_unit;
+
+    /* Record function unit name as model name _ unit name */
+    func_name_len = name_len + end_name - ptr + 2;
+    if (table->max_func_unit_name_len < func_name_len)
+      table->max_func_unit_name_len = func_name_len;
+
+    func_unit->name = name = (char *)zalloc(func_name_len);
+    memcpy(name, new_model->name, name_len);
+    name[name_len] = '_';
+    memcpy(name + name_len + 1, ptr, end_name - ptr);
+
+    /* See if there are multiple functional units */
+    if (*end_name == '=') {
+      number = 0;
+      for(end_name++; end_name < end && isdigit(*end_name); end_name++)
+       number = number * 10 + (*end_name - '0');
+    } else {
+      number = 1;
+    }
+
+    /* Now figure out the mask for these unit(s) */
+    func_unit->number = number;
+    mask = 0;
+    while (number--) {
+      ASSERT(unit != 0);
+      mask |= unit;
+      unit <<= 1;
+    }
+    func_unit->mask = mask;
+    table->max_func_unit_mask |= mask;
+
+    /* Now figure out comments */
+    for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++)
+      ;
+
+    if (comment < end) {
+      func_unit->comment = (char *)zalloc(end - comment + 1);
+      memcpy(func_unit->comment, comment, end - comment);
+    }
+  }
+
+  /* Add an 'sentinel' function unit at the end to simpify the loop */
+  func_unit = ZALLOC(model_func_unit);
+  if (new_model->func_unit_end)
+    new_model->func_unit_end->next = func_unit;
+  else
+    new_model->func_unit_start = func_unit;
+
+  new_model->func_unit_end = func_unit;
+
+  /* Record function unit name as model name _ unit name */
+  func_name_len = name_len + sizeof("_SENTINEL");
+  if (table->max_func_unit_name_len < func_name_len)
+    table->max_func_unit_name_len = func_name_len;
+
+  func_unit->name = name = (char *)zalloc(func_name_len);
+  func_unit->number = 0;
+  func_unit->mask = unit;
+  func_unit->comment = "dummy";
+  table->max_func_unit_mask |= unit;
+
+  memcpy(name, new_model->name, name_len);
+  strcpy(name + name_len, "_SENTINEL");
+}
+
+static void
+model_table_insert_specific(insn_table *table,
+                           table_entry *file_entry,
+                           insn **start_ptr,
+                           insn **end_ptr)
+{
+  insn *ptr = ZALLOC(insn);
+  ptr->file_entry = file_entry;
+  if (*end_ptr)
+    (*end_ptr)->next = ptr;
+  else
+    (*start_ptr) = ptr;
+  (*end_ptr) = ptr;
+}
+
+
 
 static insn_table *
 insn_table_load_insns(char *file_name)
@@ -1139,10 +1125,16 @@ insn_table_load_insns(char *file_name)
       model_table_insert(table, file_entry);
     }
     else if (it_is("model-macro", file_entry->fields[insn_flags])) {
-      model_table_insert_macro(table, file_entry);
+      model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
     }
     else if (it_is("model-function", file_entry->fields[insn_flags])) {
-      model_table_insert_function(table, file_entry);
+      model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
+    }
+    else if (it_is("model-internal", file_entry->fields[insn_flags])) {
+      model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
+    }
+    else if (it_is("model-data", file_entry->fields[insn_flags])) {
+      model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
     }
     else {
       insn_fields *fields;
@@ -1367,6 +1359,7 @@ lf_print_idecode_table(lf *file,
     lf_printf(file, "while (1) {\n");
     lf_indent(file, +2);
     {
+      lf_printf(file, "/* nonzero mask -> another table */\n");
       lf_printf(file, "while (table_entry->mask != 0) {\n");
       lf_indent(file, +2);
       {
@@ -1378,24 +1371,26 @@ lf_print_idecode_table(lf *file,
       }
       lf_indent(file, -2);
       lf_printf(file, "}\n");
-      if (!idecode_cache && can_assume_leaf) {
-       lf_printf(file, "return (((idecode_semantic*)\n");
-       lf_printf(file, "         table_entry->function_or_table)\n");
-       lf_printf(file, "        (%s));\n", semantic_actual);
+      lf_printf(file, "ASSERT(table_entry->mask == 0);\n");
+      if (can_assume_leaf)
+       lf_printf(file, "ASSERT(table_entry->shift == 0);\n");
+      else {
+       lf_printf(file, "if (table_entry->shift == 0)\n");
+       lf_indent(file, +2);
       }
-      else if (!idecode_cache && !can_assume_leaf) {
-       lf_printf(file, "if (table_entry->shift == 0)");
-       lf_printf(file, "  return (((idecode_semantic*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", semantic_actual);
+      if (idecode_cache) {
+       lf_printf(file, "return (((idecode_crack*)\n");
+       lf_printf(file, "         table_entry->function_or_table)\n");
+       lf_printf(file, "        (%s));\n", cache_idecode_actual);
       }
       else {
-       lf_printf(file, "if (table_entry->shift == 0)\n");
-       lf_printf(file, "  return (((idecode_crack*)\n");
-       lf_printf(file, "           table_entry->function_or_table)\n");
-       lf_printf(file, "          (%s));\n", cache_idecode_actual);
+       lf_printf(file, "return (((idecode_semantic*)\n");
+       lf_printf(file, "         table_entry->function_or_table)\n");
+       lf_printf(file, "        (%s));\n", semantic_actual);
       }
       if (!can_assume_leaf) {
+       lf_indent(file, -2);
+       lf_printf(file, "/* must be a boolean */\n");
        lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n");
        lf_printf(file, "table = ((idecode_table_entry*)\n");
        lf_printf(file, "         table_entry->function_or_table);\n");
@@ -1616,9 +1611,11 @@ dump_traverse(insn_table *table)
 
 
 static void
-semantics_h_print_function(lf *file,
-                          char *basename,
-                          insn_bits *expanded_bits)
+lf_print_semantic_function_header(lf *file,
+                                 char *basename,
+                                 insn_bits *expanded_bits,
+                                 int is_function_definition,
+                                 int is_inline_function)
 {
   lf_printf(file, "\n");
   lf_printf(file, "STATIC_SEMANTICS unsigned_word ");
@@ -1626,8 +1623,11 @@ semantics_h_print_function(lf *file,
                         basename,
                         expanded_bits,
                         function_name_prefix_semantics);
-  lf_printf(file, "\n(%s);\n", 
+  lf_printf(file, "\n(%s)", 
            (idecode_cache ? cache_semantic_formal : semantic_formal));
+  if (!is_function_definition)
+    lf_printf(file, ";");
+  lf_printf(file, "\n");
 }
 
 
@@ -1638,9 +1638,11 @@ semantics_h_leaf(insn_table *entry,
 {
   lf *file = (lf*)data;
   ASSERT(entry->nr_insn == 1);
-  semantics_h_print_function(file,
-                            entry->insns->file_entry->fields[insn_name],
-                            entry->expanded_bits);
+  lf_print_semantic_function_header(file,
+                                   entry->insns->file_entry->fields[insn_name],
+                                   entry->expanded_bits,
+                                   0/* isnt function definition*/,
+                                   !idecode_cache && entry->parent->opcode_rule->use_switch);
 }
 
 static void
@@ -1649,9 +1651,11 @@ semantics_h_insn(insn_table *entry,
                 insn *instruction)
 {
   lf *file = (lf*)data;
-  semantics_h_print_function(file,
-                            instruction->file_entry->fields[insn_name],
-                            NULL);
+  lf_print_semantic_function_header(file,
+                                   instruction->file_entry->fields[insn_name],
+                                   NULL,
+                                   0/*isnt function definition*/,
+                                   0/*isnt inline function*/);
 }
 
 static void
@@ -1662,9 +1666,11 @@ semantics_h_function(insn_table *entry,
   lf *file = (lf*)data;
   if (function->fields[function_type] == NULL
       || function->fields[function_type][0] == '\0') {
-    semantics_h_print_function(file,
-                              function->fields[function_name],
-                              NULL);
+    lf_print_semantic_function_header(file,
+                                     function->fields[function_name],
+                                     NULL,
+                                     0/*isnt function definition*/,
+                                     1/*is inline function*/);
   }
   else {
     lf_printf(file, "\n");
@@ -2280,13 +2286,16 @@ static void
 lf_print_c_semantic_function(lf *file,
                             insn *instruction,
                             insn_bits *expanded_bits,
-                            opcode_field *opcodes)
+                            opcode_field *opcodes,
+                            int is_inline_function)
 {
 
   /* build the semantic routine to execute the instruction */
-  lf_print_c_semantic_function_header(file,
-                                     instruction->file_entry->fields[insn_name],
-                                     expanded_bits);
+  lf_print_semantic_function_header(file,
+                                   instruction->file_entry->fields[insn_name],
+                                   expanded_bits,
+                                   1/*is-function-definition*/,
+                                   is_inline_function);
   lf_print_c_semantic(file,
                      instruction,
                      expanded_bits,
@@ -2307,7 +2316,8 @@ semantics_c_leaf(insn_table *entry,
   lf_print_c_semantic_function(file,
                               entry->insns,
                               entry->expanded_bits,
-                              entry->parent->opcode);
+                              entry->parent->opcode,
+                              !idecode_cache && entry->parent->opcode_rule->use_switch);
 }
 
 static void
@@ -2317,7 +2327,8 @@ semantics_c_insn(insn_table *table,
 {
   lf *file = (lf*)data;
   lf_print_c_semantic_function(file, instruction,
-                              NULL, NULL);
+                              NULL, NULL,
+                              0/*isnt_inline_function*/);
 }
 
 static void
@@ -2328,9 +2339,11 @@ semantics_c_function(insn_table *table,
   lf *file = (lf*)data;
   if (function->fields[function_type] == NULL
       || function->fields[function_type][0] == '\0') {
-    lf_print_c_semantic_function_header(file,
-                                       function->fields[function_name],
-                                       NULL);
+    lf_print_semantic_function_header(file,
+                                     function->fields[function_name],
+                                     NULL,
+                                     1/*is function definition*/,
+                                     1/*is inline function*/);
   }
   else {
     lf_printf(file, "\n");
@@ -2468,7 +2481,7 @@ idecode_table_leaf(insn_table *entry,
     }
     else if (entry->opcode_rule->use_switch) {
       /* table calling switch statement */
-      lf_printf(file, "  /*%d*/ { -1, 0, ",
+      lf_printf(file, "  /*%d*/ { 0, 0, ",
                entry->opcode_nr);
       lf_print_table_name(file, entry);
       lf_printf(file, " },\n");
@@ -2552,8 +2565,13 @@ idecode_switch_leaf(insn_table *entry,
   ASSERT(entry->parent != NULL);
   ASSERT(depth == 0);
   ASSERT(entry->parent->opcode_rule->use_switch);
+  ASSERT(entry->parent->opcode);
 
-  lf_printf(file, "case %d:\n", entry->opcode_nr);
+  if (!entry->parent->opcode->is_boolean
+      || entry->opcode_nr == 0)
+    lf_printf(file, "case %d:\n", entry->opcode_nr);
+  else
+    lf_printf(file, "default:\n");
   lf_indent(file, +2);
   {
     if (entry->opcode == NULL) {
@@ -2575,8 +2593,7 @@ idecode_switch_leaf(insn_table *entry,
       lf_print_idecode_switch(file, entry);
     }
     else {
-      /* switch calling table */
-      lf_printf(file, "return ");
+      /* switch looking up a table */
       lf_print_idecode_table(file, entry);
     }
     lf_printf(file, "break;\n");
@@ -2602,8 +2619,10 @@ idecode_switch_end(insn_table *table,
   lf *file = (lf*)data;
   ASSERT(depth == 0);
   ASSERT(table->opcode_rule->use_switch);
+  ASSERT(table->opcode);
 
-  if (table->opcode_rule->use_switch == 1) {
+  if (table->opcode_rule->use_switch == 1
+      && !table->opcode->is_boolean) {
     lf_printf(file, "default:\n");
     lf_print_idecode_switch_illegal(file);
   }
@@ -2643,6 +2662,47 @@ lf_print_idecode_switch(lf *file,
 
 
 static void
+lf_print_idecode_switch_function_header(lf *file,
+                                       insn_table *table,
+                                       int is_function_definition)
+{
+  lf_printf(file, "\n");
+  lf_printf(file, "static ");
+  if (idecode_cache)
+    lf_printf(file, "idecode_semantic *");
+  else
+    lf_printf(file, "unsigned_word");
+  if (is_function_definition)
+    lf_printf(file, "\n");
+  else
+    lf_printf(file, " ");
+  lf_print_table_name(file, table);
+  lf_printf(file, "\n(%s)",
+           (idecode_cache ? cache_idecode_formal : semantic_formal));
+  if (!is_function_definition)
+    lf_printf(file, ";");
+  lf_printf(file, "\n");
+}
+
+
+static void
+idecode_declare_if_switch(insn_table *table,
+                         void *data,
+                         int depth)
+{
+  lf *file = (lf*)data;
+
+  if (table->opcode_rule->use_switch
+      && table->parent != NULL /* don't declare the top one yet */
+      && !table->parent->opcode_rule->use_switch) {
+    lf_print_idecode_switch_function_header(file,
+                                           table,
+                                           0/*isnt function definition*/);
+  }
+}
+
+
+static void
 idecode_expand_if_switch(insn_table *table,
                         void *data,
                         int depth)
@@ -2652,11 +2712,9 @@ idecode_expand_if_switch(insn_table *table,
   if (table->opcode_rule->use_switch
       && table->parent != NULL /* don't expand the top one yet */
       && !table->parent->opcode_rule->use_switch) {
-    lf_printf(file, "\n");
-    lf_printf(file, "STATIC_INLINE_IDECODE void\n");
-    lf_print_table_name(file, table);
-    lf_printf(file, "\n(%s)\n",
-             (idecode_cache ? cache_idecode_formal : semantic_formal));
+    lf_print_idecode_switch_function_header(file,
+                                           table,
+                                           1/*is function definition*/);
     lf_printf(file, "{\n");
     {
       lf_indent(file, +2);
@@ -2672,7 +2730,8 @@ static void
 lf_print_c_cracker_function(lf *file,
                            insn *instruction,
                            insn_bits *expanded_bits,
-                           opcode_field *opcodes)
+                           opcode_field *opcodes,
+                           int is_inline_function)
 {
   /* if needed, generate code to enter this routine into a cache */
   lf_printf(file, "\n");
@@ -2698,11 +2757,13 @@ idecode_crack_leaf(insn_table *entry,
   ASSERT(entry->nr_insn == 1
         && entry->opcode == NULL
         && entry->parent != NULL
-        && entry->parent->opcode != NULL);
+        && entry->parent->opcode != NULL
+        && entry->parent->opcode_rule != NULL);
   lf_print_c_cracker_function(file,
                              entry->insns,
                              entry->expanded_bits,
-                             entry->opcode);
+                             entry->opcode,
+                             entry->parent->opcode_rule->use_switch);
 }
 
 static void
@@ -2714,7 +2775,8 @@ idecode_crack_insn(insn_table *entry,
   lf_print_c_cracker_function(file,
                              instruction,
                              NULL,
-                             NULL);
+                             NULL,
+                             0/*isnt inline function*/);
 }
 
 static void
@@ -2812,6 +2874,12 @@ gen_idecode_c(insn_table *table, lf *file)
                               idecode_crack_insn);
   }
 
+  /* output switch function declarations where needed by tables */
+  insn_table_traverse_tree(table,
+                          file,
+                          1,
+                          idecode_declare_if_switch, /* START */
+                          NULL, NULL, NULL);
 
   /* output tables where needed */
   for (depth = insn_table_depth(table);
@@ -2850,7 +2918,7 @@ gen_idecode_c(insn_table *table, lf *file)
   lf_indent(file, -2);
   lf_printf(file, "}\n");
   lf_printf(file, "\n");
-  lf_printf(file, "#endif\n");
+  lf_printf(file, "#endif /* _IDECODE_C_ */\n");
 }
 
 
@@ -2901,7 +2969,7 @@ gen_itable_h(insn_table *table, lf *file)
   lf_printf(file, "  char *format;\n");
   lf_printf(file, "  char *form;\n");
   lf_printf(file, "  char *flags;\n");
-  lf_printf(file, "  char *nmemonic;\n");
+  lf_printf(file, "  char *mnemonic;\n");
   lf_printf(file, "  char *name;\n");
   lf_printf(file, "} itable_info;\n");
   lf_printf(file, "\n");
@@ -2930,7 +2998,7 @@ itable_c_insn(insn_table *entry,
   lf_printf(file, "    \"%s\",\n", fields[insn_format]);
   lf_printf(file, "    \"%s\",\n", fields[insn_form]);
   lf_printf(file, "    \"%s\",\n", fields[insn_flags]);
-  lf_printf(file, "    \"%s\",\n", fields[insn_nmemonic]);
+  lf_printf(file, "    \"%s\",\n", fields[insn_mnemonic]);
   lf_printf(file, "    \"%s\",\n", fields[insn_name]);
   lf_printf(file, "    },\n");
 }
@@ -2967,23 +3035,37 @@ gen_itable_c(insn_table *table, lf *file)
 /****************************************************************/
 
 static void
-model_h_function(insn_table *entry,
-                lf *file,
-                table_entry *function)
+model_c_or_h_data(insn_table *table,
+                 lf *file,
+                 table_entry *data)
+{
+  if (data->annex) {
+    table_entry_lf_c_line_nr(file, data);
+    lf_print_c_code(file, data->annex);
+    lf_print_lf_c_line_nr(file);
+    lf_printf(file, "\n");
+  }
+}
+
+static void
+model_c_or_h_function(insn_table *entry,
+                     lf *file,
+                     table_entry *function,
+                     char *prefix)
 {
   if (function->fields[function_type] == NULL
       || function->fields[function_type][0] == '\0') {
-    semantics_h_print_function(file,
-                              function->fields[function_name],
-                              NULL);
+    error("Model function type not specified for %s", function->fields[function_name]);
   }
   else {
     lf_printf(file, "\n");
-    lf_printf(file, "INLINE_MODEL %s %s\n(%s);\n",
+    lf_printf(file, "%s %s %s\n(%s);\n",
+             prefix,
              function->fields[function_type],
              function->fields[function_name],
              function->fields[function_param]);
   }
+  lf_printf(file, "\n");
 }
 
 static void 
@@ -3001,10 +3083,8 @@ gen_model_h(insn_table *table, lf *file)
   lf_printf(file, "#define _MODEL_H_\n");
   lf_printf(file, "\n");
 
-  if (model_macros) {
-    for(macro = model_macros; macro; macro = macro->next)
-      lf_printf(file, "%s\n", macro->file_entry->fields[insn_comment]);
-    lf_printf(file, "\n");
+  for(macro = model_macros; macro; macro = macro->next) {
+    model_c_or_h_data(table, file, insn_ptr->file_entry);
   }
 
   lf_printf(file, "#ifndef INLINE_MODEL\n");
@@ -3090,7 +3170,7 @@ gen_model_h(insn_table *table, lf *file)
   lf_printf(file, "(const char *name);\n");
 
   for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
-    model_h_function(table, file, insn_ptr->file_entry);
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
     lf_printf(file, "\n");
   }
 
@@ -3100,8 +3180,8 @@ gen_model_h(insn_table *table, lf *file)
 
 /****************************************************************/
 
-typedef struct _model_c_data model_c_data;
-struct _model_c_data {
+typedef struct _model_c_passed_data model_c_passed_data;
+struct _model_c_passed_data {
   lf *file;
   model *model_ptr;
 };
@@ -3111,7 +3191,7 @@ model_c_insn(insn_table *entry,
              void *data,
              insn *instruction)
 {
-  model_c_data *data_ptr = (model_c_data *)data;
+  model_c_passed_data *data_ptr = (model_c_passed_data *)data;
   lf *file = data_ptr->file;
   char *current_name = data_ptr->model_ptr->name;
   table_model_entry *model_ptr = instruction->file_entry->model_first;
@@ -3123,7 +3203,7 @@ model_c_insn(insn_table *entry,
       for(i = insn_model_unit; i < nr_insn_model_table_fields; i++) {
        lf_printf(file, " %s,", model_ptr->fields[i]);
       }
-      lf_printf(file, " },\n");
+      lf_printf(file, " }, /* %s */\n", instruction->file_entry->fields[insn_name]);
       return;
     }
 
@@ -3136,17 +3216,17 @@ model_c_insn(insn_table *entry,
 static void
 model_c_function(insn_table *table,
                 lf *file,
-                table_entry *function)
+                table_entry *function,
+                const char *prefix)
 {
   if (function->fields[function_type] == NULL
       || function->fields[function_type][0] == '\0') {
-    lf_print_c_semantic_function_header(file,
-                                       function->fields[function_name],
-                                       NULL);
+    error("Model function return type not specified for %s", function->fields[function_name]);
   }
   else {
     lf_printf(file, "\n");
-    lf_printf(file, "INLINE_MODEL %s\n%s(%s)\n",
+    lf_printf(file, "%s %s\n%s(%s)\n",
+             prefix,
              function->fields[function_type],
              function->fields[function_name],
              function->fields[function_param]);
@@ -3160,6 +3240,7 @@ model_c_function(insn_table *table,
   }
   lf_printf(file, "}\n");
   lf_print_lf_c_line_nr(file);
+  lf_printf(file, "\n");
 }
 
 static void 
@@ -3178,6 +3259,14 @@ gen_model_c(insn_table *table, lf *file)
   lf_printf(file, "#include \"cpu.h\"\n");
   lf_printf(file, "\n");
 
+  for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_data(table, file, insn_ptr->file_entry);
+  }
+
+  for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+  }
+
   lf_printf(file, "/* map model enumeration into printable string */\n");
   lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
   lf_printf(file, "  \"NONE\",\n");
@@ -3230,7 +3319,7 @@ gen_model_c(insn_table *table, lf *file)
 
   lf_printf(file, "/* Insn functional unit info */\n");
   for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
-    model_c_data data;
+    model_c_passed_data data;
 
     lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
     data.file = file;
@@ -3252,9 +3341,12 @@ gen_model_c(insn_table *table, lf *file)
   lf_printf(file, "};\n");
   lf_printf(file, "\n");
 
+  for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+  }
+
   for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
-    model_c_function(table, file, insn_ptr->file_entry);
-    lf_printf(file, "\n");
+    model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
   }
 
   lf_printf(file, "INLINE_MODEL void\n");
index 0b3ad07..8df9276 100644 (file)
@@ -73,7 +73,7 @@ zalloc(long size)
   void *memory = malloc(size);
   if (memory == NULL)
     error("zmalloc failed\n");
-  bzero(memory, size);
+  memset(memory, 0, size);
   return memory;
 }