Fix PR 17135 (whilst keeping PR14827 fixed) by prefering register names over
authorNick Clifton <nickc@redhat.com>
Tue, 22 Sep 1998 22:48:42 +0000 (22:48 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 22 Sep 1998 22:48:42 +0000 (22:48 +0000)
symbolic names, except where the register name is unacceptable.

gas/ChangeLog
gas/config/tc-d30v.c

index 2f71e920b940b24f21ef2a31c54480fcb528ffe9..a9bb037c7d0836f98b995967f7a7f3558c047aad 100644 (file)
@@ -1,3 +1,14 @@
+Tue Sep 22 15:44:21 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * config/tc-d30v.c (find_format): Do not accept flag registers as
+       general purpose registers.
+       (find_format): If an immediate value is expected at a given place
+       in a format, but a register name has been provided instead, check
+       to see if that register name matches the name of a predefined
+       symbol and if it does, then use the symbol instead.
+       (reg_name_search): If a register name matches a symbol name,
+       prefer the register name to the symbol name.
+
 start-sanitize-sky
 Mon Sep 21 13:08:01 1998  Doug Evans  <devans@canuck.cygnus.com>
 
index e0b5959b7eaf2bd5ad305a713b72f6088295ad7b..b0f81bc163edb7721a4c53554bb3fcee5637b40e 100644 (file)
@@ -28,7 +28,7 @@
 const char comment_chars[] = ";";
 const char line_comment_chars[] = "#";
 const char line_separator_chars[] = "";
-const char *md_shortopts = "OnN";
+const char *md_shortopts = "OnNcC";
 const char EXP_CHARS[] = "eE";
 const char FLT_CHARS[] = "dD";
 
@@ -36,6 +36,7 @@ const char FLT_CHARS[] = "dD";
 #define NOP_ALL 2
 static int warn_nops = 0;
 static int Optimizing = 0;
+static int warn_register_name_conflicts = 1;
 
 #define FORCE_SHORT    1
 #define FORCE_LONG     2
@@ -112,7 +113,8 @@ static struct d30v_format *find_format PARAMS ((struct d30v_opcode *opcode,
                        expressionS ops[],int fsize, int cmp_hack));
 static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers));
 static void write_long PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));
-static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx));
+static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn,
+                                  Fixups *fx, int use_sequential));
 static int write_2_short PARAMS ((struct d30v_insn *opcode1, long long insn1, 
                   struct d30v_insn *opcode2, long long insn2, exec_type_enum exec_type, Fixups *fx));
 static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode,
@@ -166,6 +168,13 @@ reg_name_search (name)
   low = 0;
   high = reg_name_cnt () - 1;
 
+  if (symbol_find (name) != NULL)
+    {
+      if (warn_register_name_conflicts)
+       as_warn ("Register name %s conflicts with symbol of the same name",
+                name);
+    }
+  
   do
     {
       middle = (low + high) / 2;
@@ -175,9 +184,10 @@ reg_name_search (name)
       else if (cmp > 0)
        low = middle + 1;
       else 
-         return pre_defined_registers[middle].value;
+       return pre_defined_registers[middle].value;
     }
   while (low <= high);
+  
   return -1;
 }
 
@@ -263,8 +273,10 @@ md_show_usage (stream)
   fprintf (stream, _("\nD30V options:\n\
 -O                      Make adjacent short instructions parallel if possible.\n\
 -n                      Warn about all NOPs inserted by the assembler.\n\
--N                     Warn about NOPs inserted after word multiplies.\n"));
-} 
+-N                     Warn about NOPs inserted after word multiplies.\n\
+-c                      Warn about symbols whoes names match register names.\n\
+-C                      Opposite of -C.  -c is the default.\n"));
+}
 
 int
 md_parse_option (c, arg)
@@ -289,6 +301,14 @@ md_parse_option (c, arg)
       warn_nops = NOP_MULTIPLY;
       break;
 
+    case 'c':
+      warn_register_name_conflicts = 1;
+      break;
+
+    case 'C':
+      warn_register_name_conflicts = 0;
+      break;
+      
     default:
       return 0;
     }
@@ -663,26 +683,46 @@ write_long (opcode, insn, fx)
 }
 
 
-/* write out a short form instruction by itself */
+/* Write out a short form instruction by itself.  */
 static void
-write_1_short (opcode, insn, fx) 
+write_1_short (opcode, insn, fx, use_sequential
      struct d30v_insn *opcode;
      long long insn;
      Fixups *fx;
+     int use_sequential;
 {
   char *f = frag_more (8);
   int i, where;
 
   if (warn_nops == NOP_ALL)
-    as_warn (_("NOP inserted"));
+    as_warn (_("%s NOP inserted"), use_sequential ?
+            _("sequential") : _("parallel"));
 
-  /* the other container needs to be NOP */
-  /* according to 4.3.1: for FM=00, sub-instructions performed only
-     by IU cannot be encoded in L-container. */
+  /* The other container needs to be NOP. */
+  if (use_sequential)
+    {
+      /* Use a sequential NOP rather than a parallel one,
+        as the current instruction is a FLAG_MUL32 type one
+        and the next instruction is a load.  */
+      
+      /* According to 4.3.1: for FM=01, sub-instructions performed
+        only by IU cannot be encoded in L-container. */
+      
+      if (opcode->op->unit == IU)
+       insn |= FM10 | NOP_LEFT;        /* right then left */
+      else
+       insn = FM01 | (insn << 32) | NOP_RIGHT; /* left then right */
+    }
+  else
+    {
+      /* According to 4.3.1: for FM=00, sub-instructions performed
+        only by IU cannot be encoded in L-container. */
+      
   if (opcode->op->unit == IU)
     insn |= FM00 | NOP_LEFT;                   /* right container */
   else
     insn = FM00 | (insn << 32) | NOP_RIGHT;    /* left container */
+    }
 
   d30v_number_to_chars (f, insn, 8);
 
@@ -720,8 +760,8 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
     {
       /* subroutines must be called from 32-bit boundaries */
       /* so the return address will be correct */
-      write_1_short (opcode1, insn1, fx->next);
-      return (1);
+      write_1_short (opcode1, insn1, fx->next, false);
+      return 1;
     }
 
   switch (exec_type) 
@@ -1097,7 +1137,7 @@ md_assemble (str)
 
   if ((prev_insn != -1) && prev_seg
        && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
-    d30v_cleanup ();
+    d30v_cleanup (false);
 
   if (d30v_current_align < 3)
     d30v_align (3, NULL, d30v_last_label);
@@ -1135,7 +1175,7 @@ md_assemble (str)
          
          /* if two instructions are present and we already have one saved
             then first write it out */
-         d30v_cleanup ();
+         d30v_cleanup (false);
          
          /* assemble first instruction and save it */
          prev_insn = do_assemble (str, &prev_opcode, 1, 0);
@@ -1193,29 +1233,32 @@ md_assemble (str)
       else
        {
          /* Can't parallelize, flush previous instruction and emit a word of NOPS,
-            unless the previous instruction is a NOP, in whcih case just flush it,
+            unless the previous instruction is a NOP, in which case just flush it,
             as this will generate a word of NOPs for us.  */
 
          if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
-           {
-             d30v_cleanup ();
-           }
+           d30v_cleanup (false);
          else
            {
              char * f;
              
-             d30v_cleanup ();
-
-             f = frag_more (8);
-             d30v_number_to_chars (f, NOP2, 8);
-             if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
+             if (prev_insn != -1)
+               d30v_cleanup (true);
+             else
                {
-                 if (opcode.op->flags_used & FLAG_MEM)
-                   as_warn (_("word of NOPs added between word multiply and load"));
-                 else
-                   as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
+                 f = frag_more (8);
+                 d30v_number_to_chars (f, NOP2, 8);
+                 
+                 if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
+                   {
+                     if (opcode.op->flags_used & FLAG_MEM)
+                       as_warn (_("word of NOPs added between word multiply and load"));
+                     else
+                       as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
+                   }
                }
            }
+         
          extype = EXEC_UNKNOWN;
        }
     }
@@ -1223,23 +1266,8 @@ md_assemble (str)
           && cur_mul32_p
           && (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
     {
-      /* Can't parallelize, flush current instruction and emit a word of NOPS */
-      write_1_short (& opcode, (long) insn, fixups->next->next);
-      
-      if (strcmp (opcode.op->name, "nop") != 0)
-       {
-         char * f;
-                 
-         f = frag_more (8);
-         d30v_number_to_chars (f, NOP2, 8);
-         if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY)
-           {
-             if (opcode.op->flags_used & FLAG_MEM)
-               as_warn (_("word of NOPs added between word multiply and load"));
-             else
-               as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
-           }
-       }
+      /* Can't parallelize, flush current instruction and add a sequential NOP. */
+      write_1_short (& opcode, (long) insn, fixups->next->next, true);
       
       /* Make the previous instruction the current one.  */
       extype = EXEC_UNKNOWN;
@@ -1249,6 +1277,7 @@ md_assemble (str)
       prev_insn = -1;
       cur_mul32_p = prev_mul32_p;
       prev_mul32_p = 0;
+      memcpy (&opcode, &prev_opcode, sizeof (prev_opcode));
     }
 
   /* If this is a long instruction, write it and any previous short instruction.  */
@@ -1256,7 +1285,7 @@ md_assemble (str)
     {
       if (extype != EXEC_UNKNOWN) 
        as_fatal (_("Unable to mix instructions as specified"));
-      d30v_cleanup ();
+      d30v_cleanup (false);
       write_long (&opcode, insn, fixups);
       prev_insn = -1;
     }
@@ -1512,7 +1541,9 @@ find_format (opcode, myops, fsize, cmp_hack)
                {
                  if (X_op != O_register
                      || ((flags & OPERAND_ACC) && !(num & OPERAND_ACC))
+                     || (!(flags & OPERAND_ACC) && (num & OPERAND_ACC))
                      || ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG))
+                     || (!(flags & OPERAND_FLAG) && (num & OPERAND_FLAG))
                      || ((flags & OPERAND_CONTROL)
                          && !(num & (OPERAND_CONTROL | OPERAND_FLAG))))
                    {
@@ -1536,6 +1567,15 @@ find_format (opcode, myops, fsize, cmp_hack)
                {
                  /* A number can be a constant or symbol expression.  */
 
+                 /* If we have found a register name, but that name also
+                    matches a symbol, then re-parse the name as an expression.  */
+                 if (X_op == O_register
+                     && symbol_find ((char *) myops[j].X_op_symbol))
+                   {
+                     input_line_pointer = (char *) myops[j].X_op_symbol;
+                     expression (& myops[j]);
+                   }
+                     
                  /* Turn an expression into a symbol for later resolution.  */
                  if (X_op != O_absent && X_op != O_constant
                      && X_op != O_symbol && X_op != O_register
@@ -1795,7 +1835,8 @@ md_apply_fix3 (fixp, valuep, seg)
    instructions to see if it can package them with the next instruction, there may
    be a short instruction that still needs written.  */
 int
-d30v_cleanup ()
+d30v_cleanup (use_sequential)
+     int use_sequential;
 {
   segT seg;
   subsegT subseg;
@@ -1805,9 +1846,11 @@ d30v_cleanup ()
       seg = now_seg;
       subseg = now_subseg;
       subseg_set (prev_seg, prev_subseg);
-      write_1_short (&prev_opcode, (long)prev_insn, fixups->next);
+      write_1_short (&prev_opcode, (long)prev_insn, fixups->next, use_sequential);
       subseg_set (seg, subseg);
       prev_insn = -1;
+      if (use_sequential)
+       prev_mul32_p = false;
     }
   return 1;
 }
@@ -1840,7 +1883,7 @@ d30v_start_line ()
     c++;
 
   if (*c == '.')
-    d30v_cleanup ();
+    d30v_cleanup (false);
 }
 
 static void 
@@ -1872,7 +1915,7 @@ d30v_frob_label (lab)
      symbolS *lab;
 {
   /* Emit any pending instructions.  */
-  d30v_cleanup ();
+  d30v_cleanup (false);
 
   /* Update the label's address with the current output pointer.  */
   lab->sy_frag = frag_now;
@@ -1923,7 +1966,7 @@ d30v_align (n, pfill, label)
      can be changed under our feet, for example by a .ascii
      directive in the source code.  cf testsuite/gas/d30v/reloc.s  */
 
-  d30v_cleanup ();
+  d30v_cleanup (false);
 
   if (pfill == NULL)
     {