checkpoint
authorDoug Evans <dje@google.com>
Tue, 20 Jan 1998 19:39:54 +0000 (19:39 +0000)
committerDoug Evans <dje@google.com>
Tue, 20 Jan 1998 19:39:54 +0000 (19:39 +0000)
opcodes/txvu-opc.c

index 167aeba6dba618f035140d12fbda7541a640edb9..53e0a8cf7d49fe7090b9745ac94e31bddb0e0b1a 100644 (file)
@@ -54,14 +54,14 @@ INSERT_FN (dotdest);
 EXTRACT_FN (dotdest);
 PRINT_FN (dotdest);
 
-PARSE_FN (dotsdest);
+PARSE_FN (dotdest1);
+
+PARSE_FN (bc);
+PRINT_FN (sdest);
 
 PARSE_FN (vfreg);
 PRINT_FN (vfreg);
 
-PARSE_FN (bc);
-PRINT_FN (bc);
-
 PARSE_FN (bcftreg);
 PRINT_FN (bcftreg);
 
@@ -84,8 +84,8 @@ PRINT_FN (ffstreg);
 PARSE_FN (vi01);
 PRINT_FN (vi01);
 
-INSERT_FN (limm12);
-EXTRACT_FN (limm12);
+INSERT_FN (luimm12);
+EXTRACT_FN (luimm12);
 
 INSERT_FN (luimm15);
 EXTRACT_FN (luimm15);
@@ -106,7 +106,8 @@ const struct txvu_operand txvu_operands[] =
   { 0 },
 
   /* Operands that exist in the same place for essentially the same purpose
-     in both upper and lower instructions.  */
+     in both upper and lower instructions.  These don't have a U or L prefix.
+     Operands specific to the upper or lower instruction are so prefixed.  */
 
   /* Destination indicator attached to mnemonic, with leading '.'.
      After parsing this, the value is stored in global `dest' so that the
@@ -131,7 +132,7 @@ const struct txvu_operand txvu_operands[] =
 
   /* broadcast */
 #define UBC (VFDREG + 1)
-  { 2, 0, 0, parse_bc, 0, 0, print_bc },
+  { 2, 0, 0, parse_bc, 0, 0, print_sdest },
 
   /* ftreg in broadcast case */
 #define UBCFTREG (UBC + 1)
@@ -192,20 +193,20 @@ const struct txvu_operand txvu_operands[] =
 #define LIMM24 (LVI01 + 1)
   { 24, 0, 0, 0, 0, 0, 0 },
 
-  /* 12 bit immediate, split into 1 and 11 bit pieces.  */
-#define LIMM12 (LIMM24 + 1)
-  { 12, 0, 0, 0, insert_limm12, extract_limm12, 0 },
+  /* 12 bit unsigned immediate, split into 1 and 11 bit pieces.  */
+#define LUIMM12 (LIMM24 + 1)
+  { 12, 0, 0, 0, insert_luimm12, extract_luimm12, 0 },
 
   /* 11 bit pc-releative immediate.  */
-#define LPCREL11 (LIMM12 + 1)
+#define LPCREL11 (LUIMM12 + 1)
   { 11, 0, TXVU_OPERAND_RELATIVE_BRANCH, 0, 0, 0, 0 },
 
-  /* Destination indicator, with leading '.'.  */
-#define LDOTSDEST (DOTDEST + 1)
+  /* Destination indicator, single letter only, with leading '.'.  */
+#define LDOTDEST1 (LPCREL11 + 1)
   { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
       /* Note that we borrow the insert/extract/print functions from the
         vector case.  */
-      parse_dotsdest, insert_dotdest, extract_dotdest, print_dotdest },
+      parse_dotdest1, insert_dotdest, extract_dotdest, print_dotdest },
 
 /* end of list place holder */
   { 0 }
@@ -373,6 +374,10 @@ const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_
 #define VLFTF(x) R ((x), 2, 23)
 /* FSF field.  */
 #define VLFSF(x) R ((x), 2, 21)
+/* Upper bit of 12 bit unsigned immediate.  */
+#define VLUIMM12TOP(x) R ((x), 1, 21)
+/* Upper 4 bits of 15 bit unsigned immediate.  */
+#define VLUIMM15TOP(x) VDEST (x)
 
 /* Lower instruction field masks.  */
 #define MLOP6 VLOP6 (~0)
@@ -380,10 +385,12 @@ const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_
 #define MLOP11 VLOP11 (~0)
 #define MLIMM11 VLIMM11 (~0)
 #define MLB24 R (1, 1, 24)
-/* 12 bit immediates are split into two parts, 1 bit and 11 bits.
+#define MLUIMM12TOP VLUIMM12TOP (~0)
+/* 12 bit unsigned immediates are split into two parts, 1 bit and 11 bits.
    The upper 1 bit is part of the `dest' field.  This mask is for the
    other 3 bits of the dest field.  */
-#define MLIMM12TOP R (7, 3, 22)
+#define MLUIMM12UNUSED R (7, 3, 22)
+#define MLUIMM15TOP MDEST
 
 struct txvu_opcode txvu_lower_opcodes[] = {
 
@@ -415,10 +422,10 @@ struct txvu_opcode txvu_lower_opcodes[] = {
   { "fmand", { SP, LITREG, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1a) },
   { "fmeq", { SP, LITREG, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x18) },
   { "fmor", { SP, LITREG, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1b) },
-  { "fsand", { SP, LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MS, VLOP7 (0x16) },
-  { "fseq", { SP, LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MS, VLOP7 (0x14) },
-  { "fsor", { SP, LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MS, VLOP7 (0x17) },
-  { "fsset", { SP, LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MS, VLOP7 (0x15) },
+  { "fsand", { SP, LITREG, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x16) },
+  { "fseq", { SP, LITREG, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x14) },
+  { "fsor", { SP, LITREG, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x17) },
+  { "fsset", { SP, LITREG, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x15) },
   { "iadd", { SP, LIDREG, LISREG, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x30) },
   { "iaddi", { SP, LITREG, LISREG, LIMM5 }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x32) },
   { "iaddiu", { SP, LITREG, LISREG, LUIMM15 }, MLOP7, VLOP7 (0x08) },
@@ -429,26 +436,26 @@ struct txvu_opcode txvu_lower_opcodes[] = {
   { "ibltz", { SP, LISREG, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2c) },
   { "ibne", { SP, LITREG, LISREG, LPCREL11 }, MLOP7 + MDEST, VLOP7 (0x29) },
   /* FIXME: Need to not require commas around parens.  */
-  { "ilw", { LDOTSDEST, SP, LITREG, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x04) },
-  { "ilwr", { LDOTSDEST, SP, LITREG, '(', LISREG, ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x3fe) },
+  { "ilw", { LDOTDEST1, SP, LITREG, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x04) },
+  { "ilwr", { LDOTDEST1, SP, LITREG, '(', LISREG, ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x3fe) },
   { "ior", { SP, LIDREG, LISREG, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x34) },
   { "isub", { SP, LIDREG, LISREG, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x31) },
   { "isubiu", { SP, LITREG, LISREG, LUIMM15 }, MLOP7, VLOP7 (0x09) },
-  { "isw", { LDOTSDEST, SP, LITREG, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x05) },
-  { "iswr", { LDOTSDEST, SP, LITREG, '(', LISREG, ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x3ff) },
+  { "isw", { LDOTDEST1, SP, LITREG, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x05) },
+  { "iswr", { LDOTDEST1, SP, LITREG, '(', LISREG, ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x3ff) },
   { "jalr", { SP, LITREG, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x25) },
   { "jr", { SP, LISREG }, MLOP7 + MDEST + MT + MLIMM11, VLOP7 (0x24) },
   { "lq", { DOTDEST, SP, VFTREG, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x00) },
   /* FIXME: No commas around -/+.  */
   { "lqd", { DOTDEST, SP, VFTREG, LIMM11, '(', '-', '-', LISREG, ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x37e) },
   { "lqi", { DOTDEST, SP, VFTREG, LIMM11, '(', LISREG, '+', '+', ')' }, MLOP7, VLOP7 (0x40) + VLIMM11 (0x37c) },
-  /* Only a single VF reg is allowed here.  We can use VFTREG because LDOTSDEST
+  /* Only a single VF reg is allowed here.  We can use VFTREG because LDOTDEST1
      handles verifying only a single choice of xyzw is present.  */
-  { "mfir", { LDOTSDEST, SP, VFTREG, LISREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fc) },
+  { "mfir", { LDOTDEST1, SP, VFTREG, LISREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fc) },
   { "mfp", { DOTDEST, SP, VFTREG, 'p' }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x67c) },
   { "move", { DOTDEST, SP, VFTREG, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33c) },
   { "mr32", { DOTDEST, SP, VFTREG, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33d) },
-  { "mtir", { LDOTSDEST, SP, LITREG, LFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fd) },
+  { "mtir", { LDOTDEST1, SP, LITREG, LFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fd) },
   { "rget", { DOTDEST, SP, VFTREG, 'r' }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43d) },
   { "rinit", { SP, 'r', LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43e) },
   { "rnext", { DOTDEST, SP, VFTREG, 'r' }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43c) },
@@ -604,13 +611,13 @@ txvu_opcode_init_print ()
    The "dest" string selects any combination of x,y,z,w.
    [The letters are ordered that way to follow the manual's style.]  */
 
-/* Parse a `dest' spec.
+/* Utility to parse a `dest' spec.
    Return the found value.
    *PSTR is set to the character that terminated the parsing.
    It is up to the caller to do any error checking.  */
 
 static long
-parse_dest (pstr)
+_parse_dest (pstr)
      char **pstr;
 {
   long dest = 0;
@@ -645,23 +652,26 @@ parse_dotdest (pstr, errmsg)
     }
 
   ++*pstr;
-  dest = parse_dest (pstr);
+  dest = _parse_dest (pstr);
   if (dest == 0 || isalnum (**pstr))
     {
       *errmsg = "invalid `dest'";
       return 0;
     }
+
   *errmsg = NULL;
   return dest;
 }
 
-/* Parse a `dest' spec where only a single letter is allowed.  */
+/* Parse a `dest' spec where only a single letter is allowed,
+   but the encoding handles all four.  */
 
 static long
-parse_dotsdest (pstr, errmsg)
+parse_dotdest1 (pstr, errmsg)
      char **pstr;
      const char **errmsg;
 {
+  char c;
   long dest;
 
   if (**pstr != '.')
@@ -673,12 +683,25 @@ parse_dotsdest (pstr, errmsg)
   ++*pstr;
   switch (**pstr)
     {
-    case 'x' : case 'X' : dest = TXVU_BC_X; break;
-    case 'y' : case 'Y' : dest = TXVU_BC_Y; break;
-    case 'z' : case 'Z' : dest = TXVU_BC_Z; break;
-    case 'w' : case 'W' : dest = TXVU_BC_W; break;
+    case 'x' : case 'X' : dest |= TXVU_DEST_X; break;
+    case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break;
+    case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break;
+    case 'w' : case 'W' : dest |= TXVU_DEST_W; break;
     default : *errmsg = "invalid `dest'"; return 0;
     }
+  ++*pstr;
+  c == tolower (**pstr);
+  if (c == 'x' || c == 'y' || c == 'z' || c == 'w')
+    {
+      *errmsg = "only one of x,y,z,w can be specified";
+      return 0;
+    }
+  if (isalnum (**pstr))
+    {
+      *errmsg = "invalid `dest'";
+      return 0;
+    }
+
   *errmsg = NULL;
   return dest;
 }
@@ -710,8 +733,10 @@ extract_dotdest (insn, operand, mods, pinvalid)
   return dest;
 }
 
+/* Utility to print a multiple dest spec.  */
+
 static void
-print_dest (info, insn, value)
+_print_dest (info, insn, value)
      disassemble_info *info;
      TXVU_INSN insn;
      long value;
@@ -733,7 +758,91 @@ print_dotdest (info, insn, value)
      long value;
 {
   (*info->fprintf_func) (info->stream, ".");
-  print_dest (info, insn, value);
+  _print_dest (info, insn, value);
+}
+\f
+/* Utilities for single destination choice handling.  */
+
+static long
+_parse_sdest (pstr, errmsg)
+     char **pstr;
+     const char **errmsg;
+{
+  char c;
+  long dest = 0;
+
+  switch (**pstr)
+    {
+    case 'x' : case 'X' : dest = TXVU_SDEST_X; break;
+    case 'y' : case 'Y' : dest = TXVU_SDEST_Y; break;
+    case 'z' : case 'Z' : dest = TXVU_SDEST_Z; break;
+    case 'w' : case 'W' : dest = TXVU_SDEST_W; break;
+    default : *errmsg = "only one of x,y,z,w can be specified"; return 0;
+    }
+  ++*pstr;
+  c == tolower (**pstr);
+  if (c == 'x' || c == 'y' || c == 'z' || c == 'w')
+    {
+      *errmsg = "only one of x,y,z,w can be specified";
+      return 0;
+    }
+  if (isalnum (**pstr))
+    {
+      *errmsg = "invalid `dest'";
+      return 0;
+    }
+
+  *errmsg = NULL;
+  return dest;
+}
+
+static void
+print_sdest (info, insn, value)
+     disassemble_info *info;
+     TXVU_INSN insn;
+     long value;
+{
+  char c;
+
+  switch (value)
+    {
+    case TXVU_SDEST_X : c = 'x'; break;
+    case TXVU_SDEST_Y : c = 'y'; break;
+    case TXVU_SDEST_Z : c = 'z'; break;
+    case TXVU_SDEST_W : c = 'w'; break;
+    }
+
+  (*info->fprintf_func) (info->stream, "%c", c);
+}
+\f
+/* Broadcase field.  */
+
+static long
+parse_bc (pstr, errmsg)
+     char **pstr;
+     const char **errmsg;
+{
+  long value = _parse_sdest (pstr, errmsg);
+
+  if (*errmsg)
+    return 0;
+  /* Save value for later verification in register parsing.  */
+  bc = value;
+  return value;
+}
+
+/* During the extraction process, save the bc field for use in
+   printing the bc register.  */
+
+static long
+extract_bc (insn, operand, mods, pinvalid)
+     TXVU_INSN insn;
+     const struct txvu_operand *operand;
+     int mods;
+     int *pinvalid;
+{
+  bc = insn & 3;
+  return bc;
 }
 \f
 static long
@@ -758,7 +867,12 @@ parse_vfreg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_dest = parse_dest (&str);
+  if (reg < 0 || reg > 31)
+    {
+      *errmsg = "invalid register number";
+      return 0;
+    }
+  reg_dest = _parse_dest (&str);
   if (reg_dest == 0 || isalnum (*str))
     {
       *errmsg = "invalid `dest'";
@@ -781,49 +895,7 @@ print_vfreg (info, insn, value)
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_dest (info, insn, dest);
-}
-\f
-/* Broadcast handling.  */
-
-static long
-parse_bc (pstr, errmsg)
-     char **pstr;
-     const char **errmsg;
-{
-  long dest = 0;
-
-  switch (**pstr)
-    {
-    case 'x' : case 'X' : dest = TXVU_BC_X; break;
-    case 'y' : case 'Y' : dest = TXVU_BC_Y; break;
-    case 'z' : case 'Z' : dest = TXVU_BC_Z; break;
-    case 'w' : case 'W' : dest = TXVU_BC_W; break;
-    default : *errmsg = "invalid `bc'"; return 0;
-    }
-  ++*pstr;
-
-  *errmsg = NULL;
-  return dest;
-}
-
-static void
-print_bc (info, insn, value)
-     disassemble_info *info;
-     TXVU_INSN insn;
-     long value;
-{
-  char c;
-
-  switch (value)
-    {
-    case TXVU_BC_X : c = 'x' ; break;
-    case TXVU_BC_Y : c = 'y' ; break;
-    case TXVU_BC_Z : c = 'z' ; break;
-    case TXVU_BC_W : c = 'w' ; break;
-    }
-
-  (*info->fprintf_func) (info->stream, "%c", c);
+  _print_dest (info, insn, dest);
 }
 \f
 /* FT register in broadcast case.  */
@@ -850,7 +922,12 @@ parse_bcftreg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_bc = parse_bc (&str, errmsg);
+  if (reg < 0 || reg > 31)
+    {
+      *errmsg = "invalid register number";
+      return 0;
+    }
+  reg_bc = _parse_sdest (&str, errmsg);
   if (*errmsg)
     return 0;
   if (reg_bc != bc)
@@ -870,7 +947,7 @@ print_bcftreg (info, insn, value)
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_bc (info, insn, bc);
+  print_sdest (info, insn, bc);
 }
 \f
 /* ACC handling.  */
@@ -889,7 +966,7 @@ parse_accdest (pstr, errmsg)
       return 0;
     }
   str += 3;
-  acc_dest = parse_dest (&str);
+  acc_dest = _parse_dest (&str);
   if (acc_dest == 0 || isalnum (*str))
     {
       *errmsg = "invalid `dest'";
@@ -913,7 +990,7 @@ print_accdest (info, insn, value)
      long value;
 {
   (*info->fprintf_func) (info->stream, "acc");
-  print_dest (info, insn, value);
+  _print_dest (info, insn, value);
 }
 \f
 /* XYZ operand handling.
@@ -933,7 +1010,9 @@ parse_xyz (pstr, errmsg)
   return 0;
 }
 \f
-/* F[ST] register using selector in F[ST]F field.  */
+/* F[ST] register using selector in F[ST]F field.
+   Internally, the value is encoded in 7 bits: the 2 bit xyzw indicator
+   followed by the 5 bit register number.  */
 
 static long
 parse_ffstreg (pstr, errmsg)
@@ -942,8 +1021,7 @@ parse_ffstreg (pstr, errmsg)
 {
   char *str = *pstr;
   char *start;
-  long reg;
-  int reg_bc;
+  int reg, xyzw;
 
   if (tolower (str[0]) != 'v'
       || tolower (str[1]) != 'f')
@@ -957,17 +1035,17 @@ parse_ffstreg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_bc = parse_bc (&str, errmsg);
-  if (*errmsg)
-    return 0;
-  if (reg_bc != bc)
+  if (reg < 0 || reg > 31)
     {
-      *errmsg = "register `bc' does not match instruction `bc'";
+      *errmsg = "invalid register number";
       return 0;
     }
+  xyzw = _parse_sdest (&str, errmsg);
+  if (*errmsg)
+    return 0;
   *pstr = str;
   *errmsg = NULL;
-  return reg;
+  return reg | (xyzw << 5);
 }
 
 static void
@@ -976,19 +1054,10 @@ print_ffstreg (info, insn, value)
      TXVU_INSN insn;
      long value;
 {
-  (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_bc (info, insn, bc);
+  (*info->fprintf_func) (info->stream, "vf%ld", value & TXVU_MASK_REG);
+  print_sdest (info, insn, (value >> 5) & 3);
 }
 
-#define INSERT_FN(fn) \
-static TXVU_INSN 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 *, \
-             int, int *))
-
 static TXVU_INSN
 insert_ffstreg (insn, operand, mods, value, errmsg)
      TXVU_INSN insn;
@@ -997,6 +1066,10 @@ insert_ffstreg (insn, operand, mods, value, errmsg)
      long value;
      const char **errmsg;
 {
+  if (operand->shift == TXVU_SHIFT_SREG)
+    return insn | VLFSF (value >> 5) | VS (value);
+  else
+    return insn | VLFTF (value >> 5) | VT (value);
 }
 
 static long
@@ -1006,6 +1079,10 @@ extract_ffstreg (insn, operand, mods, pinvalid)
      int mods;
      int *pinvalid;
 {
+  if (operand->shift == TXVU_SHIFT_SREG)
+    return (((insn & VLFSF (~0)) >> 21) << 5) | VS (insn);
+  else
+    return (((insn & VLFTF (~0)) >> 21) << 5) | VT (insn);
 }
 \f
 /* F register.  */
@@ -1032,12 +1109,9 @@ parse_freg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_bc = parse_bc (&str, errmsg);
-  if (*errmsg)
-    return 0;
-  if (reg_bc != bc)
+  if (reg < 0 || reg > 31)
     {
-      *errmsg = "register `bc' does not match instruction `bc'";
+      *errmsg = "invalid register number";
       return 0;
     }
   *pstr = str;
@@ -1052,7 +1126,6 @@ print_freg (info, insn, value)
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_bc (info, insn, bc);
 }
 \f
 /* I register.  */
@@ -1068,7 +1141,7 @@ parse_ireg (pstr, errmsg)
   int reg_bc;
 
   if (tolower (str[0]) != 'v'
-      || tolower (str[1]) != 'f')
+      || tolower (str[1]) != 'i')
     {
       *errmsg = "unknown register";
       return 0;
@@ -1079,12 +1152,9 @@ parse_ireg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_bc = parse_bc (&str, errmsg);
-  if (*errmsg)
-    return 0;
-  if (reg_bc != bc)
+  if (reg < 0 || reg > 31)
     {
-      *errmsg = "register `bc' does not match instruction `bc'";
+      *errmsg = "invalid register number";
       return 0;
     }
   *pstr = str;
@@ -1098,8 +1168,7 @@ print_ireg (info, insn, value)
      TXVU_INSN insn;
      long value;
 {
-  (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_bc (info, insn, bc);
+  (*info->fprintf_func) (info->stream, "vi%ld", value);
 }
 \f
 /* VI01 register.  */
@@ -1115,7 +1184,7 @@ parse_vi01 (pstr, errmsg)
   int reg_bc;
 
   if (tolower (str[0]) != 'v'
-      || tolower (str[1]) != 'f')
+      || tolower (str[1]) != 'i')
     {
       *errmsg = "unknown register";
       return 0;
@@ -1126,12 +1195,9 @@ parse_vi01 (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
-  reg_bc = parse_bc (&str, errmsg);
-  if (*errmsg)
-    return 0;
-  if (reg_bc != bc)
+  if (reg != 1)
     {
-      *errmsg = "register `bc' does not match instruction `bc'";
+      *errmsg = "vi01 required here";
       return 0;
     }
   *pstr = str;
@@ -1145,29 +1211,30 @@ print_vi01 (info, insn, value)
      TXVU_INSN insn;
      long value;
 {
-  (*info->fprintf_func) (info->stream, "vf%ld", value);
-  print_bc (info, insn, bc);
+  (*info->fprintf_func) (info->stream, "vi01");
 }
 \f
-/* Lower instruction 12 bit immediate.  */
+/* Lower instruction 12 bit unsigned immediate.  */
 
 static TXVU_INSN
-insert_limm12 (insn, operand, mods, value, errmsg)
+insert_luimm12 (insn, operand, mods, value, errmsg)
      TXVU_INSN insn;
      const struct txvu_operand *operand;
      int mods;
      long value;
      const char **errmsg;
 {
+  return insn | VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value);
 }
 
 static long
-extract_limm12 (insn, operand, mods, pinvalid)
+extract_luimm12 (insn, operand, mods, pinvalid)
      TXVU_INSN insn;
      const struct txvu_operand *operand;
      int mods;
      int *pinvalid;
 {
+  return (((insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (insn);
 }
 \f
 /* Lower instruction 15 bit unsigned immediate.  */
@@ -1180,6 +1247,7 @@ insert_luimm15 (insn, operand, mods, value, errmsg)
      long value;
      const char **errmsg;
 {
+  return insn | VLUIMM15TOP (value >> 11) | VLIMM11 (value);
 }
 
 static long
@@ -1189,4 +1257,5 @@ extract_luimm15 (insn, operand, mods, pinvalid)
      int mods;
      int *pinvalid;
 {
+  return (((insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (insn);
 }