rework operand parsing
authorJ.T. Conklin <jtc@acorntoolworks.com>
Fri, 23 Aug 1996 06:33:10 +0000 (06:33 +0000)
committerJ.T. Conklin <jtc@acorntoolworks.com>
Fri, 23 Aug 1996 06:33:10 +0000 (06:33 +0000)
gas/config/tc-v850.c

index c7c420b8969c2be0cb998e25d1246342dc2c9687..ac47152fa6a3c40b92e12c1db1b53366b7aa128d 100644 (file)
@@ -92,19 +92,14 @@ const pseudo_typeS md_pseudo_table[] =
 static struct hash_control *v850_hash;
 
 /* Structure to hold information about predefined registers.  */
-struct pd_reg
+struct reg_name
 {
-  char *name;
+  const char *name;
   int value;
 };
 
-
-/* an expressionS only has one register type, so we fake it */
-/* by setting high bits to indicate type */
-#define REGISTER_MASK          0xFF
-
-/*   The table is sorted. Suitable for searching by a binary search. */
-static const struct pd_reg pre_defined_registers[] =
+/* This table is sorted. Suitable for searching by a binary search. */
+static const struct reg_name pre_defined_registers[] =
 {
   { "ep", 30 },                        /* ep - element ptr */
   { "gp", 4 },                 /* gp - global ptr */
@@ -145,7 +140,42 @@ static const struct pd_reg pre_defined_registers[] =
   { "tp", 5 },                 /* tp - text ptr */
   { "zero", 0 },
 };
-#define REG_NAME_CNT   (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
+#define REG_NAME_CNT   (sizeof(pre_defined_registers) / sizeof(struct reg_name))
+
+
+static const struct reg_name system_registers[] = 
+{
+  { "eipc", 0 },
+  { "eipsw", 1 },
+  { "fepc", 2 },
+  { "fepsw", 3 },
+  { "ecr", 4 },
+  { "psw", 5 },
+};
+
+static const struct reg_name cc_names[] =
+{
+  { "c", 0x1 },
+  { "ge", 0xe },
+  { "gt", 0xf },
+  { "h", 0xb },
+  { "l", 0x1 },
+  { "le", 0x7 },
+  { "lt", 0x6 },
+  { "n", 0x4 },
+  { "nc", 0x9 },
+  { "nh", 0x3 },
+  { "nl", 0x9 },
+  { "ns", 0xc },
+  { "nv", 0x8 },
+  { "nz", 0xa },
+  { "p",  0xc },
+  { "s", 0x4 },
+  { "sa", 0xd },
+  { "t", 0x5 },
+  { "v", 0x0 },
+  { "z", 0x2 },
+};
 
 /* reg_name_search does a binary search of the pre_defined_registers
    array to see if "name" is a valid regiter name.  Returns the register
@@ -343,66 +373,6 @@ get_reloc (op)
 }
 
 
-/* get_operands parses a string of operands and returns and array of
-   expressions. */
-static int
-get_operands (exp)
-     expressionS exp[];
-{
-  char *p = input_line_pointer;
-  int numops = 0;
-  
-  while (*p) 
-    {
-      while (*p == ' ' || *p == '\t' || *p == ',')
-        p++;
-      if (*p==0 || *p=='\n' || *p=='\r')
-        break;
-
-      /* skip trailing parens */
-      if (*p == ')' || *p == ']')
-       {
-         p++;
-         continue;
-       }
-
-      if (*p == '[') 
-       {
-         p++;
-         input_line_pointer = p;
-         register_name(&exp[numops]);
-       }
-      else if (strncmp(p, "lo(", 3) == 0)
-       {
-         p += 3;
-         input_line_pointer = p;
-         expression(&exp[numops]);
-       }
-      else if (strncmp(p, "hi(", 3) == 0)
-       {
-         p += 3;
-         input_line_pointer = p;
-         expression(&exp[numops]);
-       }
-      else
-       {
-         input_line_pointer = p;
-         if (!register_name(&exp[numops]))
-           expression(&exp[numops]);
-       }
-
-      p = input_line_pointer;
-      numops++;
-    }
-
-  input_line_pointer = p;
-
-  exp[numops].X_op = 0;
-  return (numops);
-}
-
-
-
 void
 md_assemble (str) 
      char *str;
@@ -441,65 +411,166 @@ md_assemble (str)
 
   input_line_pointer = str;
 
-  /* get all the operands and save them as expressions */
-  numops = get_operands (myops);
-
-  /* now search the opcode table for one with operands that matches
-     what we've got */
-  match = 0;
-  while (!match) 
+  for(;;)
     {
-      match = 1;
-      for (i = 0; opcode->operands[i]; i++)
+      const char *errmsg = NULL;
+
+      fc = 0;
+      match = 0;
+      next_opindex = 0;
+      for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
        {
-         int flags = v850_operands[opcode->operands[i]].flags;
-         int X_op = myops[i].X_op;
-         int num  = myops[i].X_add_number;
+         const struct v850_operand *operand;
+         char *hold;
+         expressionS ex;
+         char endc;
 
-         if (X_op == 0)
+         if (next_opindex == 0)
            {
-             match = 0;
-             break;
+             operand = &v850_operands[*opindex_ptr];
+           }
+         else
+           {
+             operand = &v850_operands[next_opindex];
+             next_opindex = 0;
            }
 
-         if (flags & OPERAND_REG) 
+         errmsg = NULL;
+
+         while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
+           ++str;
+
+         /* Gather the operand. */
+         hold = input_line_pointer;
+         input_line_pointer = str;
+
+         if ((operand->flags & V850_OPERAND_REG) != 0) 
            {
-             if (X_op != O_register) 
+             if (!register_name(&ex))
                {
-                 match = 0;
-                 break;
+                 errmsg = "invalid register name";
+                 goto error;
                }
            }
-       }
+         else if (strncmp(input_line_pointer, "lo(", 3) == 0) 
+           {
+             input_line_pointer += 3;
+             expression(&ex);
 
-      /* we're only done if the operands matched so far AND there are
-        no more to check. */
-      if (match && myops[i].X_op == 0)
-       break;
-      
-      next_opcode = opcode + 1;
-      if (next_opcode->opcode == 0)
-       break;
-      if (strcmp (next_opcode->name, opcode->name))
-       break;
-      opcode = next_opcode;
-    }
+             if (*input_line_pointer++ != ')')
+               {
+                 errmsg = "syntax error: expected `)'";
+                 goto error;
+               }
+             
+             if (ex.X_op == O_constant) 
+               ex.X_add_number &= 0xffff;
+             else
+               {
+                 if (fc > MAX_INSN_FIXUPS)
+                   as_fatal ("too many fixups");
+                 
+                 fixups[fc].exp = ex;
+                 fixups[fc].opindex = *opindex_ptr;
+                 fixups[fc].reloc = BFD_RELOC_LO16;
+                 fc++;
+               }
+           }
+         else if (strncmp(input_line_pointer, "hi(", 3) == 0) 
+           {
+             input_line_pointer += 3;
+             expression(&ex);
 
-  if (!match) 
-    {
-      as_bad ("Unrecognized operands");
-      return;
-    }
+             if (*input_line_pointer++ != ')')
+               {
+                 errmsg = "syntax error: expected `)'";
+                 goto error;
+               }
+             
+             if (ex.X_op == O_constant)
+               ex.X_add_number = (ex.X_add_number >> 16) & 0xffff;
+             else 
+               {
+                 if (fc > MAX_INSN_FIXUPS)
+                   as_fatal ("too many fixups");
+                 
+                 fixups[fc].exp = ex;
+                 fixups[fc].opindex = *opindex_ptr;
+                 fixups[fc].reloc = BFD_RELOC_HI16;
+                 fc++;
+               }
+           }
+         else
+           {
+               expression(&ex);
+           }
 
-  insn = opcode->opcode;
+         str = input_line_pointer;
+         input_line_pointer = hold;
 
-#if 0
+         switch (ex.X_op) 
+           {
+           case O_illegal:
+             errmsg = "illegal operand";
+             goto error;
+           case O_absent:
+             errmsg = "missing operand";
+             goto error;
+           case O_register:
+             if ((operand->flags & V850_OPERAND_REG) == 0)
+               {
+                 errmsg = "invalid operand";
+                 goto error;
+               }
+               
+             insn = v850_insert_operand (insn, operand, ex.X_add_number,
+                                         (char *) NULL, 0);
+             break;
+
+           case O_constant:
+             insn = v850_insert_operand (insn, operand, ex.X_add_number,
+                                         (char *) NULL, 0);
+             break;
+
+           default:
+             /* We need to generate a fixup for this expression.  */
+             if (fc >= MAX_INSN_FIXUPS)
+               as_fatal ("too many fixups");
+             fixups[fc].exp = ex;
+             fixups[fc].opindex = *opindex_ptr;
+             fixups[fc].reloc = BFD_RELOC_UNUSED;
+             ++fc;
+             break;
+           }
+
+         while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
+           ++str;
+       }
+      match = 1;
+
+    error:
+      if (match == 0)
+        {
+         next_opcode = opcode + 1;
+         if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
+           {
+             opcode = next_opcode;
+             continue;
+           }
+         
+         as_bad ("%s", errmsg);
+         return;
+        }
+      break;
+    }
+      
   while (isspace (*str))
     ++str;
 
   if (*str != '\0')
     as_bad ("junk at end of line: `%s'", str);
-#endif
+
+  input_line_pointer = str;
 
   /* Write out the instruction.  */
   if ((insn & 0x0600) == 0x0600)
@@ -636,18 +707,18 @@ v850_insert_operand (insn, operand, val, file, line)
       long min, max;
       offsetT test;
 
-#if 0
-      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+      if ((operand->flags & V850_OPERAND_SIGNED) != 0)
         {
+#if 0
           if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0
               && ppc_size == PPC_OPCODE_32)
             max = (1 << operand->bits) - 1;
           else
+#endif
             max = (1 << (operand->bits - 1)) - 1;
           min = - (1 << (operand->bits - 1));
         }
       else
-#endif
         {
           max = (1 << operand->bits) - 1;
           min = 0;