re PR target/50447 ([avr] Better support of AND, OR, XOR and PLUS with constant integ...
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 22 Sep 2011 09:55:13 +0000 (09:55 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Thu, 22 Sep 2011 09:55:13 +0000 (09:55 +0000)
PR target/50447
PR target/50465
* config/avr/avr-protos.h (avr_out_bitop): New prototype.
(avr_popcount_each_byte): New prototype.
* config/avr/avr.c (avr_popcount): New static function.
(avr_popcount_each_byte): New function.
(avr_out_bitop): New function.
(adjust_insn_length): ADJUST_LEN_OUT_BITOP dispatches to
avr_out_bitop.  Cleanup code.
* config/avr/constraints.md (Ca2, Co2, Cx2): New constraints.
(Ca4, Co4, Cx4): New constraints.
* config/avr/avr.md (adjust_len): Add "out_bitop" insn attribute
alternative.
(andhi3, iorhi3, xorhi3): Rewrite insns using avr_out_bitop.
(andsi3, iorsi3, xorsi3): Ditto.
(*iorhi3_clobber, *iorsi3_clobber): Remove insns.

From-SVN: r179081

gcc/ChangeLog
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.c
gcc/config/avr/avr.md
gcc/config/avr/constraints.md

index 164daa39e67f9f468e7abedb273d894848b6470e..973376c65f3d17065820601b6cde2a3e1444033f 100644 (file)
@@ -1,3 +1,22 @@
+2011-09-22  Georg-Johann Lay  <avr@gjlay.de>
+
+       PR target/50447
+       PR target/50465
+       * config/avr/avr-protos.h (avr_out_bitop): New prototype.
+       (avr_popcount_each_byte): New prototype.
+       * config/avr/avr.c (avr_popcount): New static function.
+       (avr_popcount_each_byte): New function.
+       (avr_out_bitop): New function.
+       (adjust_insn_length): ADJUST_LEN_OUT_BITOP dispatches to
+       avr_out_bitop.  Cleanup code.
+       * config/avr/constraints.md (Ca2, Co2, Cx2): New constraints.
+       (Ca4, Co4, Cx4): New constraints.
+       * config/avr/avr.md (adjust_len): Add "out_bitop" insn attribute
+       alternative.
+       (andhi3, iorhi3, xorhi3): Rewrite insns using avr_out_bitop.
+       (andsi3, iorsi3, xorsi3): Ditto.
+       (*iorhi3_clobber, *iorsi3_clobber): Remove insns.
+
 2011-09-22  Ira Rosen  <ira.rosen@linaro.org>
 
        PR tree-optimization/50451
index 6a0b40cbf7c25646ca78bdd57eda1c44ad397f22..215fd834c3f9447d68fee0a0182ca0f954fac5fd 100644 (file)
@@ -81,6 +81,8 @@ extern int avr_epilogue_uses (int regno);
 extern void avr_output_bld (rtx operands[], int bit_nr);
 extern void avr_output_addr_vec_elt (FILE *stream, int value);
 extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
+extern const char* avr_out_bitop (rtx, rtx*, int*);
+extern bool avr_popcount_each_byte (rtx, int, int);
 
 extern int extra_constraint_Q (rtx x);
 extern int adjust_insn_length (rtx insn, int len);
index 42bc6f3fa352f1309001601f801fbf2cb0e5885b..9c8b43d9a3735a719f2a4ac2d3bb4f8ea3ee3a4b 100644 (file)
@@ -303,6 +303,46 @@ avr_replace_prefix (const char *old_str,
   return (const char*) new_str;
 }
 
+
+/* Custom function to count number of set bits.  */
+
+static inline int
+avr_popcount (unsigned int val)
+{
+  int pop = 0;
+
+  while (val)
+    {
+      val &= val-1;
+      pop++;
+    }
+
+  return pop;
+}
+
+
+/* Constraint helper function.  XVAL is an CONST_INT.  Return true if the least
+   significant N_BYTES bytes of XVAL all have a popcount in POP_MASK and false,
+   otherwise.  POP_MASK represents a subset of integers which contains an
+   integer N iff bit N of POP_MASK is set.  */
+   
+bool
+avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
+{
+  int i;
+
+  for (i = 0; i < n_bytes; i++)
+    {
+      rtx xval8 = simplify_gen_subreg (QImode, xval, SImode, i);
+      unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
+
+      if (0 == (pop_mask & (1 << avr_popcount (val8))))
+        return false;
+    }
+
+  return true;
+}
+
 static void
 avr_option_override (void)
 {
@@ -4462,6 +4502,157 @@ lshrsi3_out (rtx insn, rtx operands[], int *len)
   return "";
 }
 
+
+/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
+   time constant XOP[2]:
+
+      XOP[0] = XOP[0] <op> XOP[2]
+
+   and return "".  If PLEN == NULL, print assembler instructions to perform the
+   operation; otherwise, set *PLEN to the length of the instruction sequence
+   (in words) printed with PLEN == NULL.  XOP[3] is either an 8-bit clobber
+   register or SCRATCH if no clobber register is needed for the operation.  */
+
+const char*
+avr_out_bitop (rtx insn, rtx *xop, int *plen)
+{
+  /* CODE and MODE of the operation.  */
+  enum rtx_code code = GET_CODE (SET_SRC (single_set (insn)));
+  enum machine_mode mode = GET_MODE (xop[0]);
+
+  /* Number of bytes to operate on.  */
+  int i, n_bytes = GET_MODE_SIZE (mode);
+
+  /* Value of T-flag (0 or 1) or -1 if unknow.  */
+  int set_t = -1;
+
+  /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
+  int clobber_val = -1;
+
+  /* op[0]: 8-bit destination register
+     op[1]: 8-bit const int
+     op[2]: 8-bit clobber register or SCRATCH
+     op[3]: 8-bit register containing 0xff or NULL_RTX  */
+  rtx op[4];
+
+  op[2] = xop[3];
+  op[3] = NULL_RTX;
+
+  if (plen)
+    *plen = 0;
+
+  for (i = 0; i < n_bytes; i++)
+    {
+      /* We operate byte-wise on the destination.  */
+      rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
+      rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
+
+      /* 8-bit value to operate with this byte. */
+      unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
+
+      /* Number of bits set in the current byte of the constant.  */
+      int pop8 = avr_popcount (val8);
+
+      /* Registers R16..R31 can operate with immediate.  */
+      bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
+
+      op[0] = reg8;
+      op[1] = GEN_INT (val8);
+    
+      switch (code)
+        {
+        case IOR:
+
+          if (0 == pop8)
+            continue;
+          else if (ld_reg_p)
+            avr_asm_len ("ori %0,%1", op, plen, 1);
+          else if (1 == pop8)
+            {
+              if (set_t != 1)
+                avr_asm_len ("set", op, plen, 1);
+              set_t = 1;
+              
+              op[1] = GEN_INT (exact_log2 (val8));
+              avr_asm_len ("bld %0,%1", op, plen, 1);
+            }
+          else if (8 == pop8)
+            {
+              if (op[3] != NULL_RTX)
+                avr_asm_len ("mov %0,%3", op, plen, 1);
+              else
+                avr_asm_len ("clr %0" CR_TAB
+                             "dec %0", op, plen, 2);
+
+              op[3] = op[0];
+            }
+          else
+            {
+              if (clobber_val != (int) val8)
+                avr_asm_len ("ldi %2,%1", op, plen, 1);
+              clobber_val = (int) val8;
+              
+              avr_asm_len ("or %0,%2", op, plen, 1);
+            }
+
+          continue; /* IOR */
+
+        case AND:
+
+          if (8 == pop8)
+            continue;
+          else if (0 == pop8)
+            avr_asm_len ("clr %0", op, plen, 1);
+          else if (ld_reg_p)
+            avr_asm_len ("andi %0,%1", op, plen, 1);
+          else if (7 == pop8)
+            {
+              if (set_t != 0)
+                avr_asm_len ("clt", op, plen, 1);
+              set_t = 0;
+              
+              op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
+              avr_asm_len ("bld %0,%1", op, plen, 1);
+            }
+          else
+            {
+              if (clobber_val != (int) val8)
+                avr_asm_len ("ldi %2,%1", op, plen, 1);
+              clobber_val = (int) val8;
+              
+              avr_asm_len ("and %0,%2", op, plen, 1);
+            }
+
+          continue; /* AND */
+          
+        case XOR:
+
+          if (0 == pop8)
+            continue;
+          else if (8 == pop8)
+            avr_asm_len ("com %0", op, plen, 1);
+          else if (ld_reg_p && val8 == (1 << 7))
+            avr_asm_len ("subi %0,%1", op, plen, 1);
+          else
+            {
+              if (clobber_val != (int) val8)
+                avr_asm_len ("ldi %2,%1", op, plen, 1);
+              clobber_val = (int) val8;
+              
+              avr_asm_len ("eor %0,%2", op, plen, 1);
+            }
+
+          continue; /* XOR */
+          
+        default:
+          /* Unknown rtx_code */
+          gcc_unreachable();
+        }
+    } /* for all sub-bytes */
+
+  return "";
+}
+
 /* Create RTL split patterns for byte sized rotate expressions.  This
   produces a series of move instructions and considers overlap situations.
   Overlapping non-HImode operands need a scratch register.  */
@@ -4656,6 +4847,10 @@ adjust_insn_length (rtx insn, int len)
           output_reload_insisf (insn, op, op[2], &len);
           break;
           
+        case ADJUST_LEN_OUT_BITOP:
+          avr_out_bitop (insn, op, &len);
+          break;
+
         default:
           gcc_unreachable();
         }
@@ -4700,36 +4895,6 @@ adjust_insn_length (rtx insn, int len)
            default: break;
            }
        }
-      else if (GET_CODE (op[1]) == AND)
-       {
-         if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
-           {
-             HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
-             if (GET_MODE (op[1]) == SImode)
-               len = (((mask & 0xff) != 0xff)
-                      + ((mask & 0xff00) != 0xff00)
-                      + ((mask & 0xff0000L) != 0xff0000L)
-                      + ((mask & 0xff000000L) != 0xff000000L));
-             else if (GET_MODE (op[1]) == HImode)
-               len = (((mask & 0xff) != 0xff)
-                      + ((mask & 0xff00) != 0xff00));
-           }
-       }
-      else if (GET_CODE (op[1]) == IOR)
-       {
-         if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
-           {
-             HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
-             if (GET_MODE (op[1]) == SImode)
-               len = (((mask & 0xff) != 0)
-                      + ((mask & 0xff00) != 0)
-                      + ((mask & 0xff0000L) != 0)
-                      + ((mask & 0xff000000L) != 0));
-             else if (GET_MODE (op[1]) == HImode)
-               len = (((mask & 0xff) != 0)
-                      + ((mask & 0xff00) != 0));
-           }
-       }
     }
   set = single_set (insn);
   if (set)
index a1fcecbb04dcb0194ec3feb7aee63ebef1555a70..ab17104453e8c1ab750e1396f84b692f153945b8 100644 (file)
 ;; Otherwise do special processing depending on the attribute.
 
 (define_attr "adjust_len"
-  "yes,no,reload_in32"
+  "yes,no,reload_in32,out_bitop"
   (const_string "yes"))
 
 ;; Define mode iterators
    (set_attr "cc" "set_zn,set_zn")])
 
 (define_insn "andhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,d,r")
-         (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
-                 (match_operand:HI 2 "nonmemory_operand" "r,i,M")))
-   (clobber (match_scratch:QI 3 "=X,X,&d"))]
+  [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
+        (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
+                (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
+   (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
   ""
-{
-  if (which_alternative==0)
-    return ("and %A0,%A2" CR_TAB
-           "and %B0,%B2");
-  else if (which_alternative==1)
-    {
-      if (GET_CODE (operands[2]) == CONST_INT)
-        {
-         int mask = INTVAL (operands[2]);
-         if ((mask & 0xff) != 0xff)
-           output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
-         if ((mask & 0xff00) != 0xff00)
-           output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
-         return "";
-        }
-        return (AS2 (andi,%A0,lo8(%2)) CR_TAB
-               AS2 (andi,%B0,hi8(%2)));
-     }
-  return (AS2 (ldi,%3,lo8(%2)) CR_TAB
-          "and %A0,%3"         CR_TAB
-          AS1 (clr,%B0));
-}
-  [(set_attr "length" "2,2,3")
-   (set_attr "cc" "set_n,clobber,set_n")])
+  {
+    if (which_alternative == 0)
+      return "and %A0,%A2\;and %B0,%B2";
+    else if (which_alternative == 1)
+      return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
+
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "2,2,2,4,4")
+   (set_attr "adjust_len" "no,no,out_bitop,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
 
 (define_insn "andsi3"
-  [(set (match_operand:SI 0 "register_operand" "=r,d")
-       (and:SI (match_operand:SI 1 "register_operand" "%0,0")
-               (match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
+        (and:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
+                (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
+   (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
   ""
-{
-  if (which_alternative==0)
-    return ("and %0,%2"   CR_TAB
-            "and %B0,%B2" CR_TAB
-            "and %C0,%C2" CR_TAB
-            "and %D0,%D2");
-  else if (which_alternative==1)
-    {
-      if (GET_CODE (operands[2]) == CONST_INT)
-        {
-         HOST_WIDE_INT mask = INTVAL (operands[2]);
-         if ((mask & 0xff) != 0xff)
-           output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
-         if ((mask & 0xff00) != 0xff00)
-           output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
-         if ((mask & 0xff0000L) != 0xff0000L)
-           output_asm_insn (AS2 (andi,%C0,hlo8(%2)), operands);
-         if ((mask & 0xff000000L) != 0xff000000L)
-           output_asm_insn (AS2 (andi,%D0,hhi8(%2)), operands);
-         return "";
-        }
-      return (AS2 (andi, %A0,lo8(%2))  CR_TAB
-              AS2 (andi, %B0,hi8(%2)) CR_TAB
-             AS2 (andi, %C0,hlo8(%2)) CR_TAB
-             AS2 (andi, %D0,hhi8(%2)));
-    }
-  return "bug";
-}
-  [(set_attr "length" "4,4")
-   (set_attr "cc" "set_n,clobber")])
+  {
+    if (which_alternative == 0)
+      return "and %0,%2"   CR_TAB
+             "and %B0,%B2" CR_TAB
+             "and %C0,%C2" CR_TAB
+             "and %D0,%D2";
+
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "4,4,8,8")
+   (set_attr "adjust_len" "no,out_bitop,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,clobber,clobber,clobber")])
 
 (define_peephole2 ; andi
   [(set (match_operand:QI 0 "d_register_operand" "")
    (set_attr "cc" "set_zn,set_zn")])
 
 (define_insn "iorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,d")
-       (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
-               (match_operand:HI 2 "nonmemory_operand" "r,i")))]
+  [(set (match_operand:HI 0 "register_operand"         "=r,d,d,r  ,r")
+        (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0  ,0")
+                (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
+   (clobber (match_scratch:QI 3                        "=X,X,X,X  ,&d"))]
   ""
-{
-  if (which_alternative==0)
-    return ("or %A0,%A2" CR_TAB
-           "or %B0,%B2");
-  if (GET_CODE (operands[2]) == CONST_INT)
-     {
-       int mask = INTVAL (operands[2]);
-       if (mask & 0xff)
-         output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
-       if (mask & 0xff00)
-         output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
-       return "";
-      }
-   return (AS2 (ori,%0,lo8(%2)) CR_TAB
-          AS2 (ori,%B0,hi8(%2)));
-}
-  [(set_attr "length" "2,2")
-   (set_attr "cc" "set_n,clobber")])
+  {
+    if (which_alternative == 0)
+      return "or %A0,%A2\;or %B0,%B2";
+    else if (which_alternative == 1)
+      return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
 
-(define_insn "*iorhi3_clobber"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
-               (match_operand:HI 2 "immediate_operand" "M,i")))
-   (clobber (match_scratch:QI 3 "=&d,&d"))]
-  ""
-  "@
-       ldi %3,lo8(%2)\;or %A0,%3
-       ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3"
-  [(set_attr "length" "2,4")
-   (set_attr "cc" "clobber,set_n")])
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "2,2,2,4,4")
+   (set_attr "adjust_len" "no,no,out_bitop,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
 
 (define_insn "iorsi3"
-  [(set (match_operand:SI 0 "register_operand"        "=r,d")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
-               (match_operand:SI 2 "nonmemory_operand" "r,i")))]
+  [(set (match_operand:SI 0 "register_operand"         "=r,d,r  ,r")
+        (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0  ,0")
+                (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
+   (clobber (match_scratch:QI 3                        "=X,X,X  ,&d"))]
   ""
-{
-  if (which_alternative==0)
-    return ("or %0,%2"   CR_TAB
-           "or %B0,%B2" CR_TAB
-           "or %C0,%C2" CR_TAB
-           "or %D0,%D2");
-  if (GET_CODE (operands[2]) == CONST_INT)
-     {
-       HOST_WIDE_INT mask = INTVAL (operands[2]);
-       if (mask & 0xff)
-         output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
-       if (mask & 0xff00)
-         output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
-       if (mask & 0xff0000L)
-         output_asm_insn (AS2 (ori,%C0,hlo8(%2)), operands);
-       if (mask & 0xff000000L)
-         output_asm_insn (AS2 (ori,%D0,hhi8(%2)), operands);
-       return "";
-      }
-  return (AS2 (ori, %A0,lo8(%2))  CR_TAB
-         AS2 (ori, %B0,hi8(%2)) CR_TAB
-         AS2 (ori, %C0,hlo8(%2)) CR_TAB
-         AS2 (ori, %D0,hhi8(%2)));
-}
-  [(set_attr "length" "4,4")
-   (set_attr "cc" "set_n,clobber")])
+  {
+    if (which_alternative == 0)
+      return "or %0,%2"   CR_TAB
+             "or %B0,%B2" CR_TAB
+             "or %C0,%C2" CR_TAB
+             "or %D0,%D2";
 
-(define_insn "*iorsi3_clobber"
-  [(set (match_operand:SI 0 "register_operand"        "=r,r")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
-               (match_operand:SI 2 "immediate_operand" "M,i")))
-   (clobber (match_scratch:QI 3 "=&d,&d"))]
-  ""
-  "@
-       ldi %3,lo8(%2)\;or %A0,%3
-       ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3\;ldi %3,hlo8(%2)\;or %C0,%3\;ldi %3,hhi8(%2)\;or %D0,%3"
-  [(set_attr "length" "2,8")
-   (set_attr "cc" "clobber,set_n")])
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "4,4,8,8")
+   (set_attr "adjust_len" "no,out_bitop,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,clobber,clobber,clobber")])
 
 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ;; xor
    (set_attr "cc" "set_zn")])
 
 (define_insn "xorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-        (xor:HI (match_operand:HI 1 "register_operand" "%0")
-                (match_operand:HI 2 "register_operand" "r")))]
+  [(set (match_operand:HI 0 "register_operand"         "=r,r  ,r")
+        (xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0")
+                (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
+   (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
   ""
-  "eor %0,%2
-       eor %B0,%B2"
-  [(set_attr "length" "2")
-   (set_attr "cc" "set_n")])
+  {
+    if (which_alternative == 0)
+      return "eor %A0,%A2\;eor %B0,%B2";
+
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "2,2,4")
+   (set_attr "adjust_len" "no,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,clobber,clobber")])
 
 (define_insn "xorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-        (xor:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "register_operand" "r")))]
+  [(set (match_operand:SI 0 "register_operand"         "=r,r  ,r")
+        (xor:SI (match_operand:SI 1 "register_operand" "%0,0  ,0")
+                (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
+   (clobber (match_scratch:QI 3                        "=X,X  ,&d"))]
   ""
-  "eor %0,%2
-       eor %B0,%B2
-       eor %C0,%C2
-       eor %D0,%D2"
-  [(set_attr "length" "4")
-   (set_attr "cc" "set_n")])
+  {
+    if (which_alternative == 0)
+      return "eor %0,%2"   CR_TAB
+             "eor %B0,%B2" CR_TAB
+             "eor %C0,%C2" CR_TAB
+             "eor %D0,%D2";
+
+    return avr_out_bitop (insn, operands, NULL);
+  }
+  [(set_attr "length" "4,8,8")
+   (set_attr "adjust_len" "no,out_bitop,out_bitop")
+   (set_attr "cc" "set_n,clobber,clobber")])
 
 ;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
 ;; swap
index e754c79070bc64f355300a67b2a87834c59a7cdf..d6c172f86e29a46dd1619e9764d836ef97b4b66b 100644 (file)
   "Constant integer 4."
   (and (match_code "const_int")
        (match_test "ival == 4")))
+
+(define_constraint "Ca2"
+  "Constant 2-byte integer that allows AND without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<7) | (1<<8))")))
+
+(define_constraint "Ca4"
+  "Constant 4-byte integer that allows AND without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<7) | (1<<8))")))
+
+(define_constraint "Co2"
+  "Constant 2-byte integer that allows OR without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<1) | (1<<8))")))
+
+(define_constraint "Co4"
+  "Constant 4-byte integer that allows OR without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<1) | (1<<8))")))
+
+(define_constraint "Cx2"
+  "Constant 2-byte integer that allows XOR without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<8))")))
+
+(define_constraint "Cx4"
+  "Constant 4-byte integer that allows XOR without clobber register."
+  (and (match_code "const_int")
+       (match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<8))")))