* config/tc-d30v.c (parallel_ok): For the explicitly parallel
authorFred Fish <fnf@specifix.com>
Fri, 20 Feb 1998 05:47:40 +0000 (05:47 +0000)
committerFred Fish <fnf@specifix.com>
Fri, 20 Feb 1998 05:47:40 +0000 (05:47 +0000)
  case, allow the parallel instructions to modify the same flag
  bits.
PR 14883

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

index 5b1cad6a0f03de932f38e8f55263a6e071472d33..095b10f5438f1aaa98d8eb21c07c86ac2ea16894 100644 (file)
@@ -1,3 +1,11 @@
+start-sanitize-d30v
+Tue Feb 17 17:02:15 1998  Fred Fish  <fnf@cygnus.com>
+
+       * config/tc-d30v.c (parallel_ok): For the explicitly parallel
+       case, allow the parallel instructions to modify the same flag
+       bits.
+
+end-sanitize-d30v
 Thu Feb 19 16:08:15 1998  Richard Henderson  <rth@cygnus.com>
 
        * listing.c (list_symbol_table): Categorize symbols by
index f37ae4dd713c8ab16ac8fa924b5d99c66ddd238e..1b217b97ba3340e20d72354992005df78722f99a 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-d30v.c -- Assembler code for the Mitsubishi D30V
 
-   Copyright (C) 1997 Free Software Foundation.
+   Copyright (C) 1997, 1998 Free Software Foundation.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -44,9 +44,9 @@ static int Optimizing = 0;
 typedef enum _exec_type
 {
   EXEC_UNKNOWN,                        /* no order specified */
-  EXEC_PARALLEL,               /* done in parallel */
-  EXEC_SEQ,                    /* sequential */
-  EXEC_REVSEQ                  /* reverse sequential */
+  EXEC_PARALLEL,               /* done in parallel (FM=00) */
+  EXEC_SEQ,                    /* sequential (FM=01) */
+  EXEC_REVSEQ                  /* reverse sequential (FM=10) */
 } exec_type_enum;
 
 /* fixups */
@@ -74,6 +74,15 @@ static Fixups *fixups;
 int cur_mul32_p = 0;
 int prev_mul32_p = 0;
 
+/*  The flag_explicitly_parallel is true iff the instruction being assembled
+    has been explicitly written as a parallel short-instruction pair by the
+    human programmer.  It is used in parallel_ok() to distinguish between
+    those dangerous parallelizations attempted by the human, which are to be
+    allowed, and those attempted by the assembler, which are not.  It is set
+    from md_assemble().  */
+static int flag_explicitly_parallel = 0; 
+static int flag_xp_state = 0;
+
 /* Two nops */
 #define NOP_LEFT ((long long)NOP << 32)
 #define NOP_RIGHT ((long long)NOP)
@@ -709,6 +718,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
       break;
 
     case EXEC_PARALLEL:        /* parallel */
+      flag_explicitly_parallel = flag_xp_state;
       if (! parallel_ok (opcode1, insn1, opcode2, insn2, exec_type))
        as_fatal ("Instructions may not be executed in parallel");
       else if (opcode1->op->unit == IU)
@@ -730,6 +740,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
          insn = FM00 | (insn1 << 32) | insn2;  
          fx = fx->next;
        }
+      flag_explicitly_parallel = 0;
       break;
 
     case EXEC_SEQ:     /* sequential */
@@ -1000,8 +1011,20 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
       /* If the second instruction depends on the first, we obviously
         cannot parallelize.  Note, the mod flag implies use, so
         check that as well.  */
-      if ((mod_reg[0][j] & (mod_reg[1][j] | used_reg[1][j])) != 0)
-       return 0;
+      /* If flag_explicitly_parallel is set, then the case of the 
+        second instruction using a register the first instruction
+        modifies is assumed to be okay; we trust the human.  We
+        don't trust the human if both instructions modify the same
+        register but we do trust the human if they modify the same
+        flags. */
+      if (flag_explicitly_parallel)
+       {
+         if ((j < 2) && (mod_reg[0][j] & mod_reg[1][j]) != 0)
+           return 0;
+       }
+      else
+        if ((mod_reg[0][j] & (mod_reg[1][j] | used_reg[1][j])) != 0)
+         return 0;
     }
 
   return 1;
@@ -1032,12 +1055,17 @@ md_assemble (str)
   if ( (prev_insn != -1) && prev_seg && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
     d30v_cleanup();
 
+  flag_explicitly_parallel = 0;
+  flag_xp_state = 0;
   if (etype == EXEC_UNKNOWN)
     {
       /* look for the special multiple instruction separators */
       str2 = strstr (str, "||");
       if (str2) 
-       extype = EXEC_PARALLEL;
+       {
+         extype = EXEC_PARALLEL;
+         flag_xp_state = 1;
+       }
       else
        {
          str2 = strstr (str, "->");
@@ -1262,7 +1290,7 @@ do_assemble (str, opcode)
          break;
        case 'l':
          fsize = FORCE_LONG;
-       default:
+         break;
        }
       name[nlen-2] = 0;
     }