snapshot
authorDoug Evans <dje@google.com>
Mon, 5 Jan 1998 15:53:49 +0000 (15:53 +0000)
committerDoug Evans <dje@google.com>
Mon, 5 Jan 1998 15:53:49 +0000 (15:53 +0000)
gas/config/tc-txvu.c
opcodes/txvu-opc.c

index fbc7344f13afffb735d5aa12647ca263c38a00ed..8d7937b75388c35456f6bf7aa367315522433c4e 100644 (file)
@@ -296,6 +296,8 @@ assemble_insn (str, lower_p)
              if (operand->parse)
                {
                  value = (*operand->parse) (&str, &errmsg);
+                 if (errmsg)
+                   break;
                }
              else
                {
@@ -305,18 +307,13 @@ assemble_insn (str, lower_p)
                  str = input_line_pointer;
                  input_line_pointer = hold;
 
-                 if (exp.X_op == O_illegal)
-                   as_bad ("illegal operand");
-                 else if (exp.X_op == O_absent)
-                   as_bad ("missing operand");
+                 if (exp.X_op == O_illegal
+                     || exp.X_op == O_absent)
+                   break;
                  else if (exp.X_op == O_constant)
-                   {
-                     value = exp.X_add_number;
-                   }
+                   value = exp.X_add_number;
                  else if (exp.X_op == O_register)
-                   {
-                     as_fatal ("got O_register");
-                   }
+                   as_fatal ("got O_register");
                  else
                    {
                      /* We need to generate a fixup for this expression.  */
index a9d0bec9c7737edcb6f99999702e053e99871c75..8a7e12eabb7baa29193519538cf4a5bec134709b 100644 (file)
@@ -50,10 +50,12 @@ static void CONCAT2 (print_,fn) \
      PARAMS ((disassemble_info *, TXVU_INSN, long));
 
 PARSE_FN (dotdest);
+INSERT_FN (dotdest);
+EXTRACT_FN (dotdest);
 PRINT_FN (dotdest);
 
-PARSE_FN (reg);
-PRINT_FN (reg);
+PARSE_FN (vfreg);
+PRINT_FN (vfreg);
 
 /* Various types of ARC operands, including insn suffixes.
 
@@ -73,28 +75,28 @@ const struct txvu_operand txvu_operands[] =
 /* Destination indicator, with leading '.'.  */
 #define DOTDEST (UNUSED + 1)
   { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
-      parse_dotdest, 0, 0, print_dotdest },
+      parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest },
 
 /* ft reg */
 #define FTREG (DOTDEST + 1)
-  { 5, TXVU_SHIFT_FTREG, 0, parse_reg, 0, 0, print_reg },
+  { 5, TXVU_SHIFT_FTREG, 0, parse_vfreg, 0, 0, print_vfreg },
 
 /* fs reg */
 #define FSREG (FTREG + 1)
-  { 5, TXVU_SHIFT_FSREG, 0, parse_reg, 0, 0, print_reg },
+  { 5, TXVU_SHIFT_FSREG, 0, parse_vfreg, 0, 0, print_vfreg },
 
 /* fd reg */
 #define FDREG (FSREG + 1)
-  { 5, TXVU_SHIFT_FDREG, 0, parse_reg, 0, 0, print_reg },
+  { 5, TXVU_SHIFT_FDREG, 0, parse_vfreg, 0, 0, print_vfreg },
 
 /* end of list place holder */
   { 0 }
 };
 \f
 /* Macros to put a field's value into the right place.  */
-#define FT(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FTREG)
-#define FS(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FSREG)
-#define FD(x) (((x) & TXVU_MASK_REG) << TXVU_SHIFT_FDREG)
+#define FT(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FTREG)
+#define FS(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FSREG)
+#define FD(x) (((x) & TXVU_MASK_VFREG) << TXVU_SHIFT_FDREG)
 #define R(x,b,m) (((x) & (m)) << (b))  /* value X, mask M, at bit B */
 
 /* TXVU instructions.
@@ -248,7 +250,7 @@ txvu_lower_opcode_lookup_dis (insn)
 }
 \f
 /* Value of DEST in use.
-   Each of the registers must specify the same value.
+   Each of the registers must specify the same value as the opcode.
    ??? Perhaps remove the duplication?  */
 static int dest;
 \f
@@ -275,20 +277,17 @@ 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.
+   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_dotdest (pstr, errmsg)
+parse_dest (pstr)
      char **pstr;
-     const char **errmsg;
 {
   long dest = 0;
 
-  if (**pstr != '.')
-    {
-      *errmsg = "missing `.'";
-      return 0;
-    }
-
-  ++*pstr;
   while (**pstr)
     {
       switch (**pstr)
@@ -297,22 +296,71 @@ parse_dotdest (pstr, errmsg)
        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 = "unknown dest letter"; return 0;
+       default : return dest;
        }
       ++*pstr;
     }
 
+  return dest;
+}
+
+static long
+parse_dotdest (pstr, errmsg)
+     char **pstr;
+     const char **errmsg;
+{
+  long dest;
+
+  if (**pstr != '.')
+    {
+      *errmsg = "missing `.'";
+      return 0;
+    }
+
+  ++*pstr;
+  dest = parse_dest (pstr);
+  if (dest == 0 || isalnum (**pstr))
+    {
+      *errmsg = "invalid `dest'";
+      return 0;
+    }
   *errmsg = NULL;
   return dest;
 }
 
+static TXVU_INSN
+insert_dotdest (insn, operand, mods, value, errmsg)
+     TXVU_INSN insn;
+     const struct txvu_operand *operand;
+     int mods;
+     long value;
+     const char **errmsg;
+{
+  /* Record the DEST value in use so the register parser can use it.  */
+  dest = value;
+  if (errmsg)
+    *errmsg = NULL;
+  return insn |= value << operand->shift;
+}
+
+static long
+extract_dotdest (insn, operand, mods, pinvalid)
+     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.  */
+  dest = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+  return dest;
+}
+
 static void
-print_dotdest (info, insn, value)
+print_dest (info, insn, value)
      disassemble_info *info;
      TXVU_INSN insn;
      long value;
 {
-  (*info->fprintf_func) (info->stream, ".");
   if (value & TXVU_DEST_X)
     (*info->fprintf_func) (info->stream, "x");
   if (value & TXVU_DEST_Y)
@@ -322,15 +370,26 @@ print_dotdest (info, insn, value)
   if (value & TXVU_DEST_W)
     (*info->fprintf_func) (info->stream, "w");
 }
+
+static void
+print_dotdest (info, insn, value)
+     disassemble_info *info;
+     TXVU_INSN insn;
+     long value;
+{
+  (*info->fprintf_func) (info->stream, ".");
+  print_dest (info, insn, value);
+}
 \f
 static long
-parse_reg (pstr, errmsg)
+parse_vfreg (pstr, errmsg)
      char **pstr;
      const char **errmsg;
 {
   char *str = *pstr;
   char *start;
   long reg;
+  int reg_dest;
 
   if (tolower (str[0]) != 'v'
       || tolower (str[1]) != 'f')
@@ -344,16 +403,28 @@ parse_reg (pstr, errmsg)
   while (*str && isdigit (*str))
     ++str;
   reg = atoi (start);
+  reg_dest = parse_dest (&str);
+  if (reg_dest == 0 || isalnum (*str))
+    {
+      *errmsg = "invalid `dest'";
+      return 0;
+    }
+  if (reg_dest != dest)
+    {
+      *errmsg = "register `dest' does not match instruction `dest'";
+      return 0;
+    }
   *pstr = str;
   *errmsg = NULL;
   return reg;
 }
 
 static void
-print_reg (info, insn, value)
+print_vfreg (info, insn, value)
      disassemble_info *info;
      TXVU_INSN insn;
      long value;
 {
   (*info->fprintf_func) (info->stream, "vf%ld", value);
+  print_dest (info, insn, dest);
 }