(adddi3, subdi3): Allow constant operand.
authorRichard Kenner <kenner@gcc.gnu.org>
Mon, 14 Jul 1997 11:41:09 +0000 (07:41 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Mon, 14 Jul 1997 11:41:09 +0000 (07:41 -0400)
(anddi3, iordi3, xordi3): New patterns.
({and,ior,xor}si3_internal): Use corresponding output_???si3 function.

From-SVN: r14430

gcc/config/m68k/m68k.md

index dec5ff67153c8cc91e700de40c92ca72917bd226..40e59a0532af0e9b7c7b21bbbd341789af1ca9fa 100644 (file)
 (define_insn "adddi3"
   [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
        (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
-                (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+                (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
    (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
        }
       else
        {
-         /* TODO : this should work also for CONST operands[2] */
          if (GET_CODE (operands[2]) == REG)
            operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+         else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+           {
+             operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+             operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+           }
+         else if (GET_CODE (operands[2]) == CONST_INT)
+           {
+             operands[1] = operands[2];
+             operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+           }
          else
            operands[1] = adj_offsettable_operand (operands[2], 4);
+         /* TODO : for consts, optimize move and add */
          return \"move%.l %2,%3\;add%.l %1,%R0\;addx%.l %3,%0\";
        }
     }
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
        (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
-                (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+                (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
    (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
   ""
   "*
        }
       else
        {
-         /* TODO : this should work also for CONST operands[2] */
          if (GET_CODE (operands[2]) == REG)
            operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+         else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+           {
+             operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+             operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+           }
+         else if (GET_CODE (operands[2]) == CONST_INT)
+           {
+             operands[1] = operands[2];
+             operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+           }
          else
            operands[1] = adj_offsettable_operand (operands[2], 4);
+         /* TODO : for consts, optimize move and sub */
          return \"move%.l %2,%3\;sub%.l %1,%R0\;subx%.l %3,%0\";
        }
     }
   "*
 {
 #ifdef MOTOROLA
-  output_asm_insn(\"ext%.l %0\;divs%.w %2,%0\", operands);
+  output_asm_insn (\"ext%.l %0\;divs%.w %2,%0\", operands);
 #else
-  output_asm_insn(\"extl %0\;divs %2,%0\", operands);
+  output_asm_insn (\"extl %0\;divs %2,%0\", operands);
 #endif
   if (!find_reg_note(insn, REG_UNUSED, operands[3]))
     {
   "*
 {
 #ifdef MOTOROLA
-  output_asm_insn(\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
+  output_asm_insn (\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
 #else
-  output_asm_insn(\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
+  output_asm_insn (\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
 #endif
   if (!find_reg_note(insn, REG_UNUSED, operands[3]))
     {
 \f
 ;; logical-and instructions
 
+;; "anddi3" is mainly here to help combine().
+(define_insn "anddi3"
+  [(set (match_operand:DI 0 "general_operand" "=o,d")
+       (and:DI (match_operand:DI 1 "general_operand" "%0,0")
+               (match_operand:DI 2 "general_operand" "dn,don")))]
+  ""
+  "*
+{
+  CC_STATUS_INIT;
+  /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+  if (GET_CODE (operands[2]) == CONST_DOUBLE
+     || GET_CODE (operands[2]) == CONST_INT)
+    {
+      rtx hi, lo;
+
+      if (GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+       }
+      else
+       {
+         lo = operands[2];
+         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+       }
+      switch (INTVAL (hi))
+       {
+         case 0 :
+           output_asm_insn (\"clr%.l %0\", operands);
+           break;
+         case -1 :
+           break;
+         default :
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = hi;
+           output_asm_insn (output_andsi3 (xoperands), xoperands);
+           }
+       }
+      if (GET_CODE (operands[0]) == REG)
+       operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      else
+       operands[0] = adj_offsettable_operand (operands[0], 4);
+      switch (INTVAL (lo))
+       {
+         case 0 :
+           output_asm_insn (\"clr%.l %0\", operands);
+           break;
+         case -1 :
+           break;
+         default :
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = lo;
+           output_asm_insn (output_andsi3 (xoperands), xoperands);
+           }
+       }
+      return \"\";
+    }
+  if (GET_CODE (operands[0]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[0], 4);
+      return \"and%.l %2,%0\;and%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 4);
+      return \"and%.l %2,%0\;and%.l %1,%R0\";
+    }
+  return \"and%.l %2,%0\;and%.l %R2,%R0\";
+}")
+
 ;; Prevent AND from being made with sp.  This doesn't exist in the machine
 ;; and reload will cause inefficient code.  Since sp is a FIXED_REG, we
 ;; can't allocate pseudos into it.
   "!TARGET_5200"
   "*
 {
-  int logval;
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (GET_CODE (operands[0]) != REG)
-        operands[0] = adj_offsettable_operand (operands[0], 2);
-      operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                            INTVAL (operands[2]) & 0xffff);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      if (operands[2] == const0_rtx)
-        return \"clr%.w %0\";
-      return \"and%.w %2,%0\";
-    }
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
-      && (DATA_REG_P (operands[0])
-          || offsettable_memref_p (operands[0])))
-    {
-      if (DATA_REG_P (operands[0]))
-        {
-          operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
-        }
-      else
-        {
-         operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
-        }
-      /* This does not set condition codes in a standard way.  */
-      CC_STATUS_INIT;
-      return \"bclr %1,%0\";
-    }
-  return \"and%.l %2,%0\";
+  return output_andsi3 (operands);
 }")
 
 (define_insn "andsi3_5200"
 \f
 ;; inclusive-or instructions
 
+;; "iordi3" is mainly here to help combine().
+(define_insn "iordi3"
+  [(set (match_operand:DI 0 "general_operand" "=o,d")
+       (ior:DI (match_operand:DI 1 "general_operand" "%0,0")
+               (match_operand:DI 2 "general_operand" "dn,don")))]
+  "!TARGET_5200"
+  "*
+{
+  CC_STATUS_INIT;
+  /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+  if (GET_CODE (operands[2]) == CONST_DOUBLE
+     || GET_CODE (operands[2]) == CONST_INT)
+    {
+      rtx hi, lo;
+
+      if (GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+       }
+      else
+       {
+         lo = operands[2];
+         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+       }
+      switch (INTVAL (hi))
+       {
+         case 0 :
+           break;
+         case -1 :
+           /* FIXME : a scratch register would be welcome here if operand[0]
+              is not a register */
+           output_asm_insn (\"move%.l %#-1,%0\", operands);
+           break;
+         default :
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = hi;
+           output_asm_insn (output_iorsi3 (xoperands), xoperands);
+           }
+       }
+      if (GET_CODE (operands[0]) == REG)
+       operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      else
+       operands[0] = adj_offsettable_operand (operands[0], 4);
+      switch (INTVAL (lo))
+       {
+         case 0 :
+           break;
+         case -1 :
+           /* FIXME : a scratch register would be welcome here if operand[0]
+              is not a register */
+           output_asm_insn (\"move%.l %#-1,%R0\", operands);
+           break;
+         default :
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = lo;
+           output_asm_insn (output_iorsi3 (xoperands), xoperands);
+           }
+       }
+      return \"\";
+    }
+  if (GET_CODE (operands[0]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[0], 4);
+      return \"or%.l %2,%0\;or%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 4);
+      return \"or%.l %2,%0\;or%.l %1,%R0\";
+    }
+  return \"or%.l %2,%0\;or%.l %R2,%R0\";
+}")
+
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (ior:SI (match_operand:SI 1 "general_operand" "")
   [(set (match_operand:SI 0 "general_operand" "=m,d")
        (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
-  "!TARGET_5200"
+  ""
   "*
 {
-  register int logval;
-  if (GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) >> 16 == 0
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (GET_CODE (operands[0]) != REG)
-        operands[0] = adj_offsettable_operand (operands[0], 2);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      return \"or%.w %2,%0\";
-    }
-  if (GET_CODE (operands[2]) == CONST_INT
-      && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
-      && (DATA_REG_P (operands[0])
-         || offsettable_memref_p (operands[0])))
-    {
-      if (DATA_REG_P (operands[0]))
-       {
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
-       }
-      else
-        {
-         operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
-       }
-      CC_STATUS_INIT;
-      return \"bset %1,%0\";
-    }
-  return \"or%.l %2,%0\";
+  return output_iorsi3 (operands);
 }")
 
 (define_insn "iorsi3_5200"
 \f
 ;; xor instructions
 
+;; "xordi3" is mainly here to help combine().
+(define_insn "xordi3"
+  [(set (match_operand:DI 0 "general_operand" "=od")
+       (xor:DI (match_operand:DI 1 "general_operand" "%0")
+               (match_operand:DI 2 "general_operand" "dn")))]
+  ""
+  "*
+{
+  CC_STATUS_INIT;
+  /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+  if (GET_CODE (operands[2]) == CONST_DOUBLE
+     || GET_CODE (operands[2]) == CONST_INT)
+    {
+      rtx hi, lo;
+
+      if (GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+         hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+         lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+       }
+      else
+       {
+         lo = operands[2];
+         hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+       }
+      switch (INTVAL (hi))
+       {
+         case 0 :
+           break;
+         case -1 :
+           output_asm_insn (\"not%.l %0\", operands);
+           break;
+         default :
+           /* FIXME : a scratch register would be welcome here if
+              -128 <= INTVAL (hi) < -1 */
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = hi;
+           output_asm_insn (output_xorsi3 (xoperands), xoperands);
+           }
+       }
+      if (GET_CODE (operands[0]) == REG)
+       operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      else
+       operands[0] = adj_offsettable_operand (operands[0], 4);
+      switch (INTVAL (lo))
+       {
+         case 0 :
+           break;
+         case -1 :
+           output_asm_insn (\"not%.l %0\", operands);
+           break;
+         default :
+           /* FIXME : a scratch register would be welcome here if
+              -128 <= INTVAL (lo) < -1 */
+           operands[2] = lo;
+           /* FIXME : this should be merged with xorsi3 */
+           {
+           rtx xoperands[3];
+
+           xoperands[0] = operands[0];
+           xoperands[2] = lo;
+           output_asm_insn (output_xorsi3 (xoperands), xoperands);
+           }
+       }
+      return \"\";
+    }
+  if (GET_CODE (operands[0]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[0], 4);
+      return \"eor%.l %2,%0\;eor%.l %R2,%1\";
+    }
+  if (GET_CODE (operands[2]) != REG)
+    {
+      operands[1] = adj_offsettable_operand (operands[2], 4);
+      return \"eor%.l %2,%0\;eor%.l %1,%R0\";
+    }
+  return \"eor%.l %2,%0\;eor%.l %R2,%R0\";
+}")
+
 (define_expand "xorsi3"
   [(set (match_operand:SI 0 "general_operand" "")
        (xor:SI (match_operand:SI 1 "general_operand" "")
   "!TARGET_5200"
   "*
 {
-  if (GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) >> 16 == 0
-      && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
-    {
-      if (! DATA_REG_P (operands[0]))
-       operands[0] = adj_offsettable_operand (operands[0], 2);
-      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
-      CC_STATUS_INIT;
-      return \"eor%.w %2,%0\";
-    }
-  return \"eor%.l %2,%0\";
+  return output_xorsi3 (operands);
 }")
 
 (define_insn "xorsi3_5200"
 \f
 ;; one complement instructions
 
-;; "one_cmpldi2" is only here to help combine().
+;; "one_cmpldi2" is mainly here to help combine().
 (define_insn "one_cmpldi2"
   [(set (match_operand:DI 0 "general_operand" "=dm")
        (not:DI (match_operand:DI 1 "general_operand" "0")))]