* txvu-dis.c (print_insn): Extract/print fns take pointer to
authorDoug Evans <dje@google.com>
Tue, 27 Jan 1998 00:27:54 +0000 (00:27 +0000)
committerDoug Evans <dje@google.com>
Tue, 27 Jan 1998 00:27:54 +0000 (00:27 +0000)
insn now and not insn itself.
* txvu-opc.c: insert/extract/print fns take pointer to
insn now and not insn itself.  Add initial dma,pke,gpuif support.
Parse fn no longer needs to set errmsg = NULL for success.

opcodes/ChangeLog
opcodes/txvu-dis.c
opcodes/txvu-opc.c

index cfb0601314d6a8f7c48d32fae02b084adace6462..89eba09f8ef6fa0645125d4824b2ce9dc03007e7 100644 (file)
@@ -1,4 +1,12 @@
 start-sanitize-sky
+Mon Jan 26 16:25:51 1998  Doug Evans  <devans@seba.cygnus.com>
+
+       * txvu-dis.c (print_insn): Extract/print fns take pointer to
+       insn now and not insn itself.
+       * txvu-opc.c: insert/extract/print fns take pointer to
+       insn now and not insn itself.  Add initial dma,pke,gpuif support.
+       Parse fn no longer needs to set errmsg = NULL for success.
+
 Fri Jan 23 01:49:24 1998  Doug Evans  <devans@seba.cygnus.com>
 
        * txvu-opc.c (txvu_operands, UBC): Add extract entry.
index db1ed0addeca7c43cb868f1ff3dadb876d70433b..e8f801e12c70c569b0c1398b4a1dbd52d14fafa7 100644 (file)
@@ -125,7 +125,7 @@ print_insn (pc, info, insn, lower_p)
            }
          operand = txvu_operands + index;
          if (operand->extract)
-           (*operand->extract) (insn, operand, mods, &invalid);
+           (*operand->extract) (&insn, operand, mods, &invalid);
        }
       if (invalid)
        continue;
@@ -158,7 +158,7 @@ print_insn (pc, info, insn, lower_p)
          /* Extract the value from the instruction.  */
          if (operand->extract)
            {
-             value = (*operand->extract) (insn, operand, mods, (int *) NULL);
+             value = (*operand->extract) (&insn, operand, mods, (int *) NULL);
            }
          else
            {
@@ -176,7 +176,7 @@ print_insn (pc, info, insn, lower_p)
 
          /* Print the operand as directed by the flags.  */
          if (operand->print)
-           (*operand->print) (info, insn, value);
+           (*operand->print) (info, &insn, value);
          else if (operand->flags & TXVU_OPERAND_FAKE)
            ; /* nothing to do (??? at least not yet) */
          else if (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH)
index 881da9bea9b703befc9ed316c60fbf27395b475e..2eab05fbdac76b2a73a61855ed0ddd697e9eed13 100644 (file)
 static long CONCAT2 (parse_,fn) \
      PARAMS ((char **, const char **));
 #define INSERT_FN(fn) \
-static TXVU_INSN CONCAT2 (insert_,fn) \
-     PARAMS ((TXVU_INSN, const struct txvu_operand *, \
+static void CONCAT2 (insert_,fn) \
+     PARAMS ((TXVU_INSN *, const struct txvu_operand *, \
              int, long, const char **))
 #define EXTRACT_FN(fn) \
 static long CONCAT2 (extract_,fn) \
-     PARAMS ((TXVU_INSN, const struct txvu_operand *, \
+     PARAMS ((TXVU_INSN *, const struct txvu_operand *, \
              int, int *))
 #define PRINT_FN(fn) \
 static void CONCAT2 (print_,fn) \
-     PARAMS ((disassemble_info *, TXVU_INSN, long));
+     PARAMS ((disassemble_info *, TXVU_INSN *, long));
 
 PARSE_FN (dotdest);
 INSERT_FN (dotdest);
@@ -495,108 +495,6 @@ struct txvu_opcode txvu_lower_opcodes[] =
 };
 const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_lower_opcodes[0]);
 \f
-/* Indexed by first letter of opcode.  Points to chain of opcodes with same
-   first letter.  */
-/* ??? One can certainly use a better hash.  Later.  */
-static struct txvu_opcode *upper_opcode_map[26 + 1];
-static struct txvu_opcode *lower_opcode_map[26 + 1];
-
-/* Indexed by insn code.  Points to chain of opcodes with same insn code.  */
-static struct txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
-static struct txvu_opcode *lower_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
-\f
-/* Initialize any tables that need it.
-   Must be called once at start up (or when first needed).
-
-   FLAGS is currently unused but is intended to control initialization.  */
-
-void
-txvu_opcode_init_tables (flags)
-     int flags;
-{
-  static int init_p = 0;
-
-  /* We may be intentionally called more than once (for example gdb will call
-     us each time the user switches cpu).  These tables only need to be init'd
-     once though.  */
-  /* ??? We can remove the need for txvu_opcode_supported by taking it into
-     account here, but I'm not sure I want to do that yet (if ever).  */
-  if (!init_p)
-    {
-      int i,n;
-
-      memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
-      memset (upper_icode_map, 0, sizeof (upper_icode_map));
-
-      /* Scan the table backwards so macros appear at the front.  */
-      for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
-       {
-         int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
-         int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
-
-         txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
-         upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
-
-         txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
-         upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
-       }
-
-      memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
-      memset (lower_icode_map, 0, sizeof (lower_icode_map));
-
-      /* Scan the table backwards so macros appear at the front.  */
-      for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
-       {
-         int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
-         int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
-
-         txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
-         lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
-
-         txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
-         lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
-       }
-
-      init_p = 1;
-    }
-}
-
-/* Return the first insn in the chain for assembling upper INSN.  */
-
-const struct txvu_opcode *
-txvu_upper_opcode_lookup_asm (insn)
-     const char *insn;
-{
-  return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
-}
-
-/* Return the first insn in the chain for assembling lower INSN.  */
-
-const struct txvu_opcode *
-txvu_lower_opcode_lookup_asm (insn)
-     const char *insn;
-{
-  return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
-}
-
-/* Return the first insn in the chain for disassembling upper INSN.  */
-
-const struct txvu_opcode *
-txvu_upper_opcode_lookup_dis (insn)
-     TXVU_INSN insn;
-{
-  return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
-}
-
-/* Return the first insn in the chain for disassembling lower INSN.  */
-
-const struct txvu_opcode *
-txvu_lower_opcode_lookup_dis (insn)
-     TXVU_INSN insn;
-{
-  return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
-}
-\f
 /* Value of DEST in use.
    Each of the registers must specify the same value as the opcode.
    ??? Perhaps remove the duplication?  */
@@ -607,27 +505,6 @@ static int mnemonic_dest;
    specified in the opcode.  */
 static int mnemonic_bc;
 \f
-/* Init fns.
-   These are called before doing each of the respective activities.  */
-
-/* Called by the assembler before parsing an instruction.  */
-
-void
-txvu_opcode_init_parse ()
-{
-  mnemonic_dest = -1;
-  mnemonic_bc = -1;
-}
-
-/* Called by the disassembler before printing an instruction.  */
-
-void
-txvu_opcode_init_print ()
-{
-  mnemonic_dest = -1;
-  mnemonic_bc = -1;
-}
-\f
 /* Multiple destination choice support.
    The "dest" string selects any combination of x,y,z,w.
    [The letters are ordered that way to follow the manual's style.]  */
@@ -680,7 +557,6 @@ parse_dotdest (pstr, errmsg)
       return 0;
     }
 
-  *errmsg = NULL;
   return dest;
 }
 
@@ -723,7 +599,6 @@ parse_dotdest1 (pstr, errmsg)
       return 0;
     }
 
-  *errmsg = NULL;
   return dest;
 }
 
@@ -755,13 +630,12 @@ parse_dest1 (pstr, errmsg)
       return 0;
     }
 
-  *errmsg = NULL;
   return dest;
 }
 
-static TXVU_INSN
+static void
 insert_dotdest (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
@@ -769,18 +643,18 @@ insert_dotdest (insn, operand, mods, value, errmsg)
 {
   /* Record the DEST value in use so the register parser can use it.  */
   mnemonic_dest = value;
-  return insn |= value << operand->shift;
+  *insn |= value << operand->shift;
 }
 
 static long
 extract_dotdest (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
   /* Record the DEST value in use so the register printer can use it.  */
-  mnemonic_dest = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+  mnemonic_dest = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
   return mnemonic_dest;
 }
 
@@ -789,7 +663,7 @@ extract_dotdest (insn, operand, mods, pinvalid)
 static void
 _print_dest (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   if (value & TXVU_DEST_X)
@@ -805,7 +679,7 @@ _print_dest (info, insn, value)
 static void
 print_dotdest (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, ".");
@@ -815,7 +689,7 @@ print_dotdest (info, insn, value)
 static void
 print_dest1 (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   _print_dest (info, insn, mnemonic_dest);
@@ -852,14 +726,13 @@ _parse_sdest (pstr, errmsg)
       return 0;
     }
 
-  *errmsg = NULL;
   return dest;
 }
 
 static void
 print_sdest (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   char c;
@@ -896,12 +769,12 @@ parse_bc (pstr, errmsg)
 
 static long
 extract_bc (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
-  mnemonic_bc = insn & 3;
+  mnemonic_bc = *insn & 3;
   return mnemonic_bc;
 }
 \f
@@ -944,14 +817,13 @@ parse_vfreg (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   return reg;
 }
 
 static void
 print_vfreg (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%02ld", value);
@@ -996,14 +868,13 @@ parse_bcftreg (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   return reg;
 }
 
 static void
 print_bcftreg (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%02ld", value);
@@ -1038,7 +909,6 @@ parse_accdest (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   /* Value isn't used, but we must return something.  */
   return 0;
 }
@@ -1046,7 +916,7 @@ parse_accdest (pstr, errmsg)
 static void
 print_accdest (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "acc");
@@ -1057,20 +927,16 @@ print_accdest (info, insn, value)
    This simplifies the opmula,opmsub entries by keeping them equivalent to
    the others.  */
 
-static TXVU_INSN
+static void
 insert_xyz (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
   if (mnemonic_dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z))
-    {
-      *errmsg = "expecting `xyz' for `dest' value";
-      return insn;
-    }
-  return insn;
+    *errmsg = "expecting `xyz' for `dest' value";
 }
 \f
 /* F[ST] register using selector in F[ST]F field.
@@ -1107,45 +973,44 @@ parse_ffstreg (pstr, errmsg)
   if (*errmsg)
     return 0;
   *pstr = str;
-  *errmsg = NULL;
   return reg | (xyzw << 5);
 }
 
 static void
 print_ffstreg (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%02ld", value & TXVU_MASK_REG);
   print_sdest (info, insn, (value >> 5) & 3);
 }
 
-static TXVU_INSN
+static void
 insert_ffstreg (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
   if (operand->shift == TXVU_SHIFT_SREG)
-    return insn | VLFSF (value >> 5) | VS (value);
+    *insn |= VLFSF (value >> 5) | VS (value);
   else
-    return insn | VLFTF (value >> 5) | VT (value);
+    *insn |= VLFTF (value >> 5) | VT (value);
 }
 
 static long
 extract_ffstreg (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
   if (operand->shift == TXVU_SHIFT_SREG)
-    return (((insn & VLFSF (~0)) >> 21) << 5) | VS (insn);
+    return (((*insn & VLFSF (~0)) >> 21) << 5) | VS (*insn);
   else
-    return (((insn & VLFTF (~0)) >> 21) << 5) | VT (insn);
+    return (((*insn & VLFTF (~0)) >> 21) << 5) | VT (*insn);
 }
 \f
 /* F register.  */
@@ -1177,14 +1042,13 @@ parse_freg (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   return reg;
 }
 
 static void
 print_freg (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%02ld", value);
@@ -1219,14 +1083,13 @@ parse_ireg (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   return reg;
 }
 
 static void
 print_ireg (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vi%02ld", value);
@@ -1261,14 +1124,13 @@ parse_vi01 (pstr, errmsg)
       return 0;
     }
   *pstr = str;
-  *errmsg = NULL;
   return reg;
 }
 
 static void
 print_vi01 (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vi01");
@@ -1276,61 +1138,61 @@ print_vi01 (info, insn, value)
 \f
 /* Lower instruction 12 bit unsigned immediate.  */
 
-static TXVU_INSN
+static void
 insert_luimm12 (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return insn | VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value);
+  *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value);
 }
 
 static long
 extract_luimm12 (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
-  return (((insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (insn);
+  return (((*insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (*insn);
 }
 
 /* Lower instruction 12 bit unsigned immediate, upper 6 bits.  */
 
-static TXVU_INSN
+static void
 insert_luimm12up6 (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return insn | VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0);
+  *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0);
 }
 \f
 /* Lower instruction 15 bit unsigned immediate.  */
 
-static TXVU_INSN
+static void
 insert_luimm15 (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return insn | VLUIMM15TOP (value >> 11) | VLIMM11 (value);
+  *insn |= VLUIMM15TOP (value >> 11) | VLIMM11 (value);
 }
 
 static long
 extract_luimm15 (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
-  return (((insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (insn);
+  return (((*insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (*insn);
 }
 \f
 /* PKE support.  */
@@ -1356,7 +1218,7 @@ PRINT_FN (pke_unpacktype);
 
 PARSE_FN (pke_unpackaddr);
 
-const struct txvu_operand txvu_pke_operands[] =
+const struct txvu_operand pke_operands[] =
 {
   /* place holder (??? not sure if needed) */
 #define PKE_UNUSED 128
@@ -1427,7 +1289,7 @@ const struct txvu_operand txvu_pke_operands[] =
 #define VPKECMD(x) V ((x), 7, 24)
 #define VPKEUNPACK V (0x60, 8, 24)
 
-struct txvu_opcode txvu_pke_opcodes[] =
+struct txvu_opcode pke_opcodes[] =
 {
   { "pkenop", { PKE_IBIT }, 0x7fffffff, 0 },
   { "stcycle", { PKE_IBIT, SP, PKE_UIMM8UP, C, PKE_UIMM8LO }, MPKECMD, VPKECMD (1) },
@@ -1457,7 +1319,7 @@ struct txvu_opcode txvu_pke_opcodes[] =
   { "directhl", { PKE_IBIT, SP, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x51), PKE_OPCODE_LENVAR + PKE_OPCODE_DIRECT },
   { "unpack", { PKE_IMRBITS, SP, PKE_UNPACKTYPE, C, PKE_UNPACKADDR, C, PKE_VARLENDATA }, MPKEUNPACK, VPKEUNPACK, PKE_OPCODE_LENVAR + PKE_OPCODE_UNPACK },
 };
-const int txvu_pke_opcodes_count = sizeof (txvu_pke_opcodes) / sizeof (txvu_pke_opcodes[0]);
+const int pke_opcodes_count = sizeof (pke_opcodes) / sizeof (pke_opcodes[0]);
 \f
 /* PKE parse,insert,extract,print helper fns.  */
 
@@ -1471,7 +1333,7 @@ parse_pke_ibit (pstr, errmsg)
 static void
 print_pke_ibit (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1487,7 +1349,7 @@ parse_pke_mode (pstr, errmsg)
 static void
 print_pke_mode (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1503,7 +1365,7 @@ parse_pke_ability (pstr, errmsg)
 static void
 print_pke_ability (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1535,7 +1397,7 @@ parse_pke_imrbits (pstr, errmsg)
 static void
 print_pke_imrbits (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1551,7 +1413,7 @@ parse_pke_unpacktype (pstr, errmsg)
 static void
 print_pke_unpacktype (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1581,7 +1443,7 @@ INSERT_FN (dma_next);
 EXTRACT_FN (dma_next);
 PRINT_FN (dma_next);
 
-const struct txvu_operand txvu_dma_operands[] =
+const struct txvu_operand dma_operands[] =
 {
   /* place holder (??? not sure if needed) */
 #define DMA_UNUSED 128
@@ -1606,7 +1468,7 @@ const struct txvu_operand txvu_dma_operands[] =
   { 0 }
 };
 
-struct txvu_opcode txvu_dma_opcodes[] =
+struct txvu_opcode dma_opcodes[] =
 {
   { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 1 },
   { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 2 },
@@ -1616,7 +1478,7 @@ struct txvu_opcode txvu_dma_opcodes[] =
   { "dmareg", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 6 },
   { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 7 }
 };
-const int txvu_dma_opcodes_count = sizeof (txvu_dma_opcodes) / sizeof (txvu_dma_opcodes[0]);
+const int dma_opcodes_count = sizeof (dma_opcodes) / sizeof (dma_opcodes[0]);
 \f
 /* DMA parse,insert,extract,print helper fns.  */
 
@@ -1625,22 +1487,42 @@ parse_dma_flags (pstr, errmsg)
      char **pstr;
      const char **errmsg;
 {
+  char *str = *pstr;
+  int flags = 0;
+
+  if (*str != '[')
+    return 0;
+
+  for (str = str + 1; *str != ']'; ++str)
+    {
+      switch (tolower (*str))
+       {
+       case '0' : flags |= DMA_FLAG_PCE0; break;
+       case '1' : flags |= DMA_FLAG_PCE1; break;
+       case 'i' : flags |= DMA_FLAG_INT; break;
+       case 's' : flags |= DMA_FLAG_SPR; break;
+       default : *errmsg = "unknown dma flag"; return 0;
+       }
+    }
+
+  *errmsg = NULL;
+  *pstr = str + 1;
+  return flags;
 }
 
-static TXVU_INSN
+static void
 insert_dma_flags (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_dma_flags (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1651,10 +1533,22 @@ extract_dma_flags (insn, operand, mods, pinvalid)
 static void
 print_dma_flags (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
-  (*info->fprintf_func) (info->stream, "???");
+  if (value)
+    {
+      (*info->fprintf_func) (info->stream, "[");
+      if (value & DMA_FLAG_PCE0)
+       (*info->fprintf_func) (info->stream, "0");
+      if (value & DMA_FLAG_PCE1)
+       (*info->fprintf_func) (info->stream, "1");
+      if (value & DMA_FLAG_INT)
+       (*info->fprintf_func) (info->stream, "i");
+      if (value & DMA_FLAG_SPR)
+       (*info->fprintf_func) (info->stream, "s");
+      (*info->fprintf_func) (info->stream, "]");
+    }
 }
 
 static long
@@ -1664,20 +1558,19 @@ parse_dma_data (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_dma_data (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_dma_data (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1688,7 +1581,7 @@ extract_dma_data (insn, operand, mods, pinvalid)
 static void
 print_dma_data (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1701,20 +1594,19 @@ parse_dma_next (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_dma_next (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_dma_next (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1725,7 +1617,7 @@ extract_dma_next (insn, operand, mods, pinvalid)
 static void
 print_dma_next (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1753,7 +1645,7 @@ INSERT_FN (gpuif_eop);
 EXTRACT_FN (gpuif_eop);
 PRINT_FN (gpuif_eop);
 
-const struct txvu_operand txvu_gpuif_operands[] =
+const struct txvu_operand gpuif_operands[] =
 {
   /* place holder (??? not sure if needed) */
 #define GPUIF_UNUSED 128
@@ -1779,13 +1671,13 @@ const struct txvu_operand txvu_gpuif_operands[] =
   { 0 }
 };
 
-struct txvu_opcode txvu_gpuif_opcodes[] =
+struct txvu_opcode gpuif_opcodes[] =
 {
   { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 1 },
   { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 2 },
   { "gpuifimage", { SP, GPUIF_NLOOP }, 0, 3 },
 };
-const int txvu_gpuif_opcodes_count = sizeof (txvu_gpuif_opcodes) / sizeof (txvu_gpuif_opcodes[0]);
+const int gpuif_opcodes_count = sizeof (gpuif_opcodes) / sizeof (gpuif_opcodes[0]);
 \f
 /* GPUIF parse,insert,extract,print helper fns.  */
 
@@ -1796,20 +1688,19 @@ parse_gpuif_prim (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_gpuif_prim (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_gpuif_prim (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1820,7 +1711,7 @@ extract_gpuif_prim (insn, operand, mods, pinvalid)
 static void
 print_gpuif_prim (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1833,20 +1724,19 @@ parse_gpuif_regs (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_gpuif_regs (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_gpuif_regs (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1857,7 +1747,7 @@ extract_gpuif_regs (insn, operand, mods, pinvalid)
 static void
 print_gpuif_regs (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1870,20 +1760,19 @@ parse_gpuif_nloop (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_gpuif_nloop (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_gpuif_nloop (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1894,7 +1783,7 @@ extract_gpuif_nloop (insn, operand, mods, pinvalid)
 static void
 print_gpuif_nloop (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
@@ -1907,20 +1796,19 @@ parse_gpuif_eop (pstr, errmsg)
 {
 }
 
-static TXVU_INSN
+static void
 insert_gpuif_eop (insn, operand, mods, value, errmsg)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
-  return 0;
 }
 
 static long
 extract_gpuif_eop (insn, operand, mods, pinvalid)
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
@@ -1931,8 +1819,211 @@ extract_gpuif_eop (insn, operand, mods, pinvalid)
 static void
 print_gpuif_eop (info, insn, value)
      disassemble_info *info;
-     TXVU_INSN insn;
+     TXVU_INSN *insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "???");
 }
+\f
+/* Init fns.
+   These are called before doing each of the respective activities.  */
+
+/* Called by the assembler before parsing an instruction.  */
+
+void
+txvu_opcode_init_parse ()
+{
+  mnemonic_dest = -1;
+  mnemonic_bc = -1;
+}
+
+/* Called by the disassembler before printing an instruction.  */
+
+void
+txvu_opcode_init_print ()
+{
+  mnemonic_dest = -1;
+  mnemonic_bc = -1;
+}
+\f
+/* Indexed by first letter of opcode.  Points to chain of opcodes with same
+   first letter.  */
+/* ??? One can certainly use a better hash.  Later.  */
+static struct txvu_opcode *upper_opcode_map[26 + 1];
+static struct txvu_opcode *lower_opcode_map[26 + 1];
+
+/* Indexed by insn code.  Points to chain of opcodes with same insn code.  */
+static struct txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
+static struct txvu_opcode *lower_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
+\f
+/* Initialize any tables that need it.
+   Must be called once at start up (or when first needed).
+
+   FLAGS is currently unused but is intended to control initialization.  */
+
+void
+txvu_opcode_init_tables (flags)
+     int flags;
+{
+  static int init_p = 0;
+
+  /* We may be intentionally called more than once (for example gdb will call
+     us each time the user switches cpu).  These tables only need to be init'd
+     once though.  */
+  /* ??? We can remove the need for txvu_opcode_supported by taking it into
+     account here, but I'm not sure I want to do that yet (if ever).  */
+  if (!init_p)
+    {
+      int i,n;
+
+      /* Upper VU table.  */
+
+      memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
+      memset (upper_icode_map, 0, sizeof (upper_icode_map));
+      /* Scan the table backwards so macros appear at the front.  */
+      for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
+       {
+         int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
+         int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
+
+         txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
+         upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
+
+         txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
+         upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
+       }
+
+      /* Lower VU table.  */
+
+      memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
+      memset (lower_icode_map, 0, sizeof (lower_icode_map));
+      /* Scan the table backwards so macros appear at the front.  */
+      for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
+       {
+         int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
+         int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
+
+         txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
+         lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
+
+         txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
+         lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
+       }
+
+      /* PKE table.  */
+
+      for (i = pke_opcodes_count - 2; i >= 0; --i)
+       {
+         pke_opcodes[i].next_asm = & pke_opcodes[i+1];
+         pke_opcodes[i].next_dis = & pke_opcodes[i+1];
+       }
+
+      /* DMA table.  */
+
+      for (i = dma_opcodes_count - 2; i >= 0; --i)
+       {
+         dma_opcodes[i].next_asm = & dma_opcodes[i+1];
+         dma_opcodes[i].next_dis = & dma_opcodes[i+1];
+       }
+
+      /* GPUIF table.  */
+
+      for (i = gpuif_opcodes_count - 2; i >= 0; --i)
+       {
+         gpuif_opcodes[i].next_asm = & gpuif_opcodes[i+1];
+         gpuif_opcodes[i].next_dis = & gpuif_opcodes[i+1];
+       }
+
+      init_p = 1;
+    }
+}
+
+/* Return the first insn in the chain for assembling upper INSN.  */
+
+const struct txvu_opcode *
+txvu_upper_opcode_lookup_asm (insn)
+     const char *insn;
+{
+  return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
+}
+
+/* Return the first insn in the chain for disassembling upper INSN.  */
+
+const struct txvu_opcode *
+txvu_upper_opcode_lookup_dis (insn)
+     TXVU_INSN insn;
+{
+  return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
+}
+
+/* Return the first insn in the chain for assembling lower INSN.  */
+
+const struct txvu_opcode *
+txvu_lower_opcode_lookup_asm (insn)
+     const char *insn;
+{
+  return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
+}
+
+/* Return the first insn in the chain for disassembling lower INSN.  */
+
+const struct txvu_opcode *
+txvu_lower_opcode_lookup_dis (insn)
+     TXVU_INSN insn;
+{
+  return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
+}
+
+/* Return the first insn in the chain for assembling lower INSN.  */
+
+const struct txvu_opcode *
+pke_opcode_lookup_asm (insn)
+     const char *insn;
+{
+  return &pke_opcodes[0];
+}
+
+/* Return the first insn in the chain for disassembling lower INSN.  */
+
+const struct txvu_opcode *
+pke_opcode_lookup_dis (insn)
+     TXVU_INSN insn;
+{
+  return &pke_opcodes[0];
+}
+
+/* Return the first insn in the chain for assembling lower INSN.  */
+
+const struct txvu_opcode *
+dma_opcode_lookup_asm (insn)
+     const char *insn;
+{
+  return &dma_opcodes[0];
+}
+
+/* Return the first insn in the chain for disassembling lower INSN.  */
+
+const struct txvu_opcode *
+dma_opcode_lookup_dis (insn)
+     TXVU_INSN insn;
+{
+  return &dma_opcodes[0];
+}
+
+/* Return the first insn in the chain for assembling lower INSN.  */
+
+const struct txvu_opcode *
+gpuif_opcode_lookup_asm (insn)
+     const char *insn;
+{
+  return &gpuif_opcodes[0];
+}
+
+/* Return the first insn in the chain for disassembling lower INSN.  */
+
+const struct txvu_opcode *
+gpuif_opcode_lookup_dis (insn)
+     TXVU_INSN insn;
+{
+  return &gpuif_opcodes[0];
+}