Foixes for PR16116 and ER15940 - improve parallel insn handling.
authorNick Clifton <nickc@redhat.com>
Tue, 9 Jun 1998 01:33:23 +0000 (01:33 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 9 Jun 1998 01:33:23 +0000 (01:33 +0000)
gas/ChangeLog
gas/config/tc-d30v.c

index 739d6ea6bdbddf0bde76acd5089a07f1d95004e2..29bc25aab83f00e79635ae455526c45235e1e746 100644 (file)
@@ -1,3 +1,13 @@
+Mon Jun  8 18:32:01 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * config/tc-d30v.c (md_assemble): Fix handling of reverse
+       sequential word multiply instructions.
+       
+       (do_assemble): Add extra command line argument, to allow mul32
+       attribute to be preserved across parallel insns.
+       (md_assemble): Insert NOPs between explicitly parallel insns which
+       contain an 32 bit multiply and a 16 multiply.
+
 start-sanitize-sky
 Mon Jun  8 15:41:43 1998  Doug Evans  <devans@canuck.cygnus.com>
 
index d22c2439d9bb5262799cc917c29d5e9dfa9bf2da..dbf657b6ed1c2db7550208776cd6258f75d3324b 100644 (file)
@@ -111,7 +111,7 @@ static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn, Fix
 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,
-                                     int shortp));
+                                     int shortp, int is_parallel));
 static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1, 
                                struct d30v_insn *opcode2, unsigned long insn2,
                                exec_type_enum exec_type));
@@ -159,7 +159,7 @@ reg_name_search (name)
   int cmp;
 
   low = 0;
-  high = reg_name_cnt() - 1;
+  high = reg_name_cnt () - 1;
 
   do
     {
@@ -245,7 +245,7 @@ void
 md_show_usage (stream)
   FILE *stream;
 {
-  fprintf(stream, _("\nD30V options:\n\
+  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"));
@@ -352,7 +352,7 @@ void
 md_begin ()
 {
   struct d30v_opcode *opcode;
-  d30v_hash = hash_new();
+  d30v_hash = hash_new ();
 
   /* Insert opcode names into a hash table. */
   for (opcode = (struct d30v_opcode *)d30v_opcode_table; opcode->name; opcode++)
@@ -409,14 +409,14 @@ get_reloc (op, rel_flag)
       break;
     case 12:
       if (!(op->flags & OPERAND_SHIFT))
-       as_warn(_("unexpected 12-bit reloc type"));
+       as_warn (_("unexpected 12-bit reloc type"));
       if (rel_flag == RELOC_PCREL)
        return BFD_RELOC_D30V_15_PCREL;
       else
        return BFD_RELOC_D30V_15;
     case 18:
       if (!(op->flags & OPERAND_SHIFT))
-       as_warn(_("unexpected 18-bit reloc type"));
+       as_warn (_("unexpected 18-bit reloc type"));
       if (rel_flag == RELOC_PCREL)
        return BFD_RELOC_D30V_21_PCREL;
       else
@@ -585,7 +585,7 @@ build_insn (opcode, opers)
            as_fatal (_("too many fixups"));
 
          fixups->fix[fixups->fc].reloc = 
-           get_reloc((struct d30v_operand *)&d30v_operand_table[form->operands[i]], op->reloc_flag);
+           get_reloc ((struct d30v_operand *)&d30v_operand_table[form->operands[i]], op->reloc_flag);
          fixups->fix[fixups->fc].size = 4;
          fixups->fix[fixups->fc].exp = opers[i];
          fixups->fix[fixups->fc].operand = form->operands[i];
@@ -598,7 +598,7 @@ build_insn (opcode, opers)
 
       /* truncate to the proper number of bits */
       if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
-       as_bad(_("operand out of range: %d"),number);
+       as_bad (_("operand out of range: %d"),number);
       if (bits < 31)
        number &= 0x7FFFFFFF >> (31 - bits);
       if (flags & OPERAND_SHIFT)
@@ -626,7 +626,7 @@ write_long (opcode, insn, fx)
      Fixups *fx;
 {
   int i, where;
-  char *f = frag_more(8);
+  char *f = frag_more (8);
 
   insn |= FM11;
   d30v_number_to_chars (f, insn, 8);
@@ -655,7 +655,7 @@ write_1_short (opcode, insn, fx)
      long long insn;
      Fixups *fx;
 {
-  char *f = frag_more(8);
+  char *f = frag_more (8);
   int i, where;
 
   if (warn_nops == NOP_ALL)
@@ -700,7 +700,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
   char *f;
   int i,j, where;
 
-  if(exec_type != EXEC_PARALLEL &&
+  if (exec_type != EXEC_PARALLEL &&
      ((opcode1->op->flags_used & (FLAG_JSR | FLAG_DELAY)) == FLAG_JSR))
     {
       /* subroutines must be called from 32-bit boundaries */
@@ -782,11 +782,11 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
       break;
 
     default:
-      as_fatal(_("unknown execution type passed to write_2_short()"));
+      as_fatal (_("unknown execution type passed to write_2_short()"));
     }
 
   /*  printf("writing out %llx\n",insn); */
-  f = frag_more(8);
+  f = frag_more (8);
   d30v_number_to_chars (f, insn, 8);
 
   /* If the previous instruction was a 32-bit multiply but it is put into a
@@ -1030,7 +1030,7 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
       mod_reg[0][2] = mod_reg[1][2] = 0;
     }
 
-  for(j = 0; j < 3; j++)
+  for (j = 0; j < 3; j++)
     {
       /* If the second instruction depends on the first, we obviously
         cannot parallelize.  Note, the mod flag implies use, so
@@ -1078,7 +1078,7 @@ md_assemble (str)
 
   if ((prev_insn != -1) && prev_seg
        && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
-    d30v_cleanup();
+    d30v_cleanup ();
 
   if (d30v_current_align < 3)
     d30v_align (3, NULL, d30v_last_label);
@@ -1116,10 +1116,10 @@ md_assemble (str)
          
          /* if two instructions are present and we already have one saved
             then first write it out */
-         d30v_cleanup();
+         d30v_cleanup ();
          
          /* assemble first instruction and save it */
-         prev_insn = do_assemble (str, &prev_opcode, 1);
+         prev_insn = do_assemble (str, &prev_opcode, 1, 0);
          if (prev_insn == -1)
            as_fatal (_("Cannot assemble instruction"));
          if (prev_opcode.form->form >= LONG)
@@ -1132,7 +1132,8 @@ md_assemble (str)
     }
 
   insn = do_assemble (str, &opcode,
-                     (extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN));
+                     (extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN),
+                     extype == EXEC_PARALLEL);
   if (insn == -1)
     {
       if (extype != EXEC_UNKNOWN)
@@ -1151,11 +1152,12 @@ md_assemble (str)
 
   /* Word multiply instructions must not be followed by either a load or a
      16-bit multiply instruction in the next cycle.  */
-  if (prev_mul32_p && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
+  if (   (extype != EXEC_REVSEQ)
+      && prev_mul32_p
+      && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16)))
     {
       /* However, load and multiply should able to be combined in a parallel
         operation, so check for that first.  */
-
       if (prev_insn != -1
          && (opcode.op->flags_used & FLAG_MEM)
          && opcode.form->form < LONG
@@ -1169,14 +1171,47 @@ md_assemble (str)
          prev_insn = -1;
          return;
        }
-
-      /* Can't parallelize, flush current instruction and emit a word of NOPS */
       else
        {
-         char *f;
-         d30v_cleanup();
+         /* 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,
+            as this will generate a word of NOPs for us.  */
 
-         f = frag_more(8);
+         if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0))
+           {
+             d30v_cleanup ();
+           }
+         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 (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;
+       }
+    }
+  else if (   (extype == EXEC_REVSEQ)
+          && 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)
            {
@@ -1185,34 +1220,40 @@ md_assemble (str)
              else
                as_warn (_("word of NOPs added between word multiply and 16-bit multiply"));
            }
-         extype = EXEC_UNKNOWN;
        }
+      
+      /* Make the previous instruction the current one.  */
+      extype = EXEC_UNKNOWN;
+      insn = prev_insn;
+      now_seg = prev_seg;
+      now_subseg = prev_subseg;
+      prev_insn = -1;
+      cur_mul32_p = prev_mul32_p;
+      prev_mul32_p = 0;
     }
 
-  /* if this is a long instruction, write it and any previous short instruction */
+  /* If this is a long instruction, write it and any previous short instruction.  */
   if (opcode.form->form >= LONG) 
     {
-      if (extype) 
-       as_fatal(_("Unable to mix instructions as specified"));
-      d30v_cleanup();
+      if (extype != EXEC_UNKNOWN
+       as_fatal (_("Unable to mix instructions as specified"));
+      d30v_cleanup ();
       write_long (&opcode, insn, fixups);
       prev_insn = -1;
-      return;
     }
-
-  if ((prev_insn != -1) && 
+  else if ((prev_insn != -1) && 
       (write_2_short (&prev_opcode, (long)prev_insn, &opcode, (long)insn, extype, fixups) == 0)) 
     {
-      /* no instructions saved */
+      /* No instructions saved.  */
       prev_insn = -1;
     }
-
   else
     {
-      if (extype) 
-       as_fatal(_("Unable to mix instructions as specified"));
-      /* save off last instruction so it may be packed on next pass */
-      memcpy(&prev_opcode, &opcode, sizeof(prev_opcode));
+      if (extype != EXEC_UNKNOWN) 
+       as_fatal (_("Unable to mix instructions as specified"));
+      
+      /* Save off last instruction so it may be packed on next pass.  */
+      memcpy (&prev_opcode, &opcode, sizeof (prev_opcode));
       prev_insn = insn;
       prev_seg = now_seg;
       prev_subseg = now_subseg;
@@ -1225,10 +1266,11 @@ md_assemble (str)
 /* it returns -1 (an invalid opcode) on error */
 
 static long long
-do_assemble (str, opcode, shortp) 
+do_assemble (str, opcode, shortp, is_parallel
      char *str;
      struct d30v_insn *opcode;
      int shortp;
+     int is_parallel;
 {
   unsigned char *op_start, *save;
   unsigned char *op_end;
@@ -1249,7 +1291,7 @@ do_assemble (str, opcode, shortp)
        && !is_end_of_line[*op_end] && *op_end != ' ';
        op_end++)
     {
-      name[nlen] = tolower(op_start[nlen]);
+      name[nlen] = tolower (op_start[nlen]);
       nlen++;
     }
 
@@ -1262,13 +1304,13 @@ do_assemble (str, opcode, shortp)
   if (*op_end == '/')
     {
       int i = 0;
-      while ( (i < ECC_MAX) && strncasecmp(d30v_ecc_names[i],op_end+1,2))
+      while ( (i < ECC_MAX) && strncasecmp (d30v_ecc_names[i],op_end+1,2))
        i++;
       
       if (i == ECC_MAX)
        {
          char tmp[4];
-         strncpy(tmp,op_end+1,2);
+         strncpy (tmp,op_end+1,2);
          tmp[2] = 0;
          as_fatal (_("unknown condition code: %s"),tmp);
          return -1;
@@ -1282,7 +1324,7 @@ do_assemble (str, opcode, shortp)
   
 
   /* CMP and CMPU change their name based on condition codes */
-  if (!strncmp(name,"cmp",3))
+  if (!strncmp (name,"cmp",3))
     {
       int p,i;
       char **str = (char **)d30v_cc_names;
@@ -1291,7 +1333,7 @@ do_assemble (str, opcode, shortp)
       else
        p = 3;
 
-      for(i=1; *str && strncmp(*str,&name[p],2); i++, str++)
+      for (i=1; *str && strncmp (*str,&name[p],2); i++, str++)
        ;
 
       /* cmpu only supports some condition codes */
@@ -1336,14 +1378,14 @@ do_assemble (str, opcode, shortp)
   /* find the first opcode with the proper name */  
   opcode->op = (struct d30v_opcode *)hash_find (d30v_hash, name);
   if (opcode->op == NULL)
-      as_fatal (_("unknown opcode: %s"),name);
+    as_fatal (_("unknown opcode: %s"),name);
 
   save = input_line_pointer;
   input_line_pointer = op_end;
   while (!(opcode->form = find_format (opcode->op, myops, fsize, cmp_hack)))
     {
       opcode->op++;
-      if (strcmp(opcode->op->name,name))
+      if (strcmp (opcode->op->name,name))
        as_fatal (_("operands for opcode `%s' do not match any valid format"), name);
     }
   input_line_pointer = save;
@@ -1353,8 +1395,13 @@ do_assemble (str, opcode, shortp)
   /* Propigate multiply status */
   if (insn != -1)
     {
-      prev_mul32_p = cur_mul32_p;
-      cur_mul32_p = (opcode->op->flags_used & FLAG_MUL32) != 0;
+      if (is_parallel && prev_mul32_p)
+       cur_mul32_p = 1;
+      else
+       {
+         prev_mul32_p = cur_mul32_p;
+         cur_mul32_p  = (opcode->op->flags_used & FLAG_MUL32) != 0;
+       }
     }
 
   return (insn);
@@ -1460,8 +1507,8 @@ find_format (opcode, myops, fsize, cmp_hack)
                        match = 0;
                    }
                  else if (X_op == O_symbol
-                          && S_IS_DEFINED(myops[j].X_add_symbol)
-                          && S_GET_SEGMENT(myops[j].X_add_symbol) == now_seg
+                          && S_IS_DEFINED (myops[j].X_add_symbol)
+                          && S_GET_SEGMENT (myops[j].X_add_symbol) == now_seg
                           && opcode->reloc_flag == RELOC_PCREL)
                    {
                      /* If the symbol is defined, see if the value will fit
@@ -1474,8 +1521,8 @@ find_format (opcode, myops, fsize, cmp_hack)
                      value = 0;
                      for (f = frchain_now->frch_root; f; f = f->fr_next)
                        value += f->fr_fix + f->fr_offset;
-                     value = (S_GET_VALUE(myops[j].X_add_symbol) - value
-                              - (obstack_next_free(&frchain_now->frch_obstack)
+                     value = (S_GET_VALUE (myops[j].X_add_symbol) - value
+                              - (obstack_next_free (&frchain_now->frch_obstack)
                                  - frag_now->fr_literal));
                      if (check_range (value, bits, flags)) 
                        match = 0;
@@ -1709,15 +1756,15 @@ d30v_number_to_chars (buf, value, n)
 /* then write out any unwritten instructions */
 
 void 
-d30v_start_line()
+d30v_start_line ()
 {
   char *c = input_line_pointer;
 
-  while(isspace(*c))
+  while (isspace (*c))
     c++;
 
-  if (*c == '.') 
-    d30v_cleanup();
+  if (*c == '.')
+    d30v_cleanup ();
 }
 
 static void 
@@ -1749,7 +1796,7 @@ d30v_frob_label (lab)
      symbolS *lab;
 {
   /* Emit any pending instructions.  */
-  d30v_cleanup();
+  d30v_cleanup ();
 
   /* Update the label's address with the current output pointer.  */
   lab->sy_frag = frag_now;
@@ -1797,7 +1844,7 @@ d30v_align (n, pfill, label)
   if (d30v_current_align >= n && !switched_seg_p)
     return;
 
-  d30v_cleanup();
+  d30v_cleanup ();
 
   if (pfill == NULL)
     {
@@ -1833,7 +1880,7 @@ d30v_align (n, pfill, label)
 
       old_frag  = label->sy_frag;
       old_value = S_GET_VALUE (label);
-      new_value = (valueT) frag_now_fix();
+      new_value = (valueT) frag_now_fix ();
       
       /* It is possible to have more than one label at a particular
         address, especially if debugging is enabled, so we must
@@ -1859,7 +1906,7 @@ d30v_align (n, pfill, label)
        }
     }
 
-  record_alignment(now_seg, n);
+  record_alignment (now_seg, n);
 }
 
 /* Handle the .align pseudo-op.  This aligns to a power of two.  We