]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
h8300-protos.h: Add a prototype for emit_logical_op.
authorKazu Hirata <kazu@hxi.com>
Wed, 29 Aug 2001 18:18:15 +0000 (18:18 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Wed, 29 Aug 2001 18:18:15 +0000 (18:18 +0000)
* config/h8300/h8300-protos.h: Add a prototype for
emit_logical_op.
* config/h8300/h8300.c (emit_logical_op): New.
* config/h8300/h8300.md (andhi3): Use emit_logical_op.
(andsi3): Likewise.
(iorhi3): Likewise.
(iorsi3): Likewise.
(xorhi3): Likewise.
(xorsi3): Likewise.

From-SVN: r45272

gcc/ChangeLog
gcc/config/h8300/h8300-protos.h
gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.md

index 2d5043f201c9c330c76f0e6a7bc99ceb1ebd797c..ffc4ad598b90f51c1f30673a7dbf9aaf864f0c08 100644 (file)
@@ -1,3 +1,15 @@
+2001-08-29  Kazu Hirata  <kazu@hxi.com>
+
+       * config/h8300/h8300-protos.h: Add a prototype for
+       emit_logical_op.
+       * config/h8300/h8300.c (emit_logical_op): New.
+       * config/h8300/h8300.md (andhi3): Use emit_logical_op.
+       (andsi3): Likewise.
+       (iorhi3): Likewise.
+       (iorsi3): Likewise.
+       (xorhi3): Likewise.
+       (xorsi3): Likewise.
+
 2001-08-29  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * pa.c (move_operand): Cast GET_MODE_SIZE results to HOST_WIDE_INT for
index 4841d07e2d19a9feae9d3dba54b640cecd0c1cac..36997e1f136f877e133495dc5e9df8ba461a32bf 100644 (file)
@@ -37,6 +37,7 @@ extern void print_operand PARAMS ((FILE *, rtx, int));
 extern void final_prescan_insn PARAMS ((rtx, rtx *, int));
 extern int do_movsi PARAMS ((rtx[]));
 extern void notice_update_cc PARAMS ((rtx, rtx));
+extern const char *output_logical_op PARAMS ((enum machine_mode, int, rtx *));
 extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
 extern int expand_a_rotate PARAMS ((int, rtx[]));
 extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
index 61c255f9cf7e7e7ccc2e4d60e48ba48289e17ce6..3c95e57255a43454b88c31febdd79ee6066bcc2f 100644 (file)
@@ -1601,6 +1601,150 @@ bit_operator (x, mode)
          || code == IOR);
 }
 \f
+const char *
+output_logical_op (mode, code, operands)
+     enum machine_mode mode;
+     int code;
+     rtx *operands;
+{
+  /* Pretend that every byte is affected if both operands are registers.  */
+  unsigned HOST_WIDE_INT intval =
+    (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
+                             ? INTVAL (operands[2]) : 0x55555555);
+  /* The determinant of the algorithm.  If we perform an AND, 0
+     affects a bit.  Otherwise, 1 affects a bit.  */
+  unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
+  /* The name of an insn.  */
+  const char *opname;
+  char insn_buf[100];
+
+  switch (code)
+    {
+    case AND:
+      opname = "and";
+      break;
+    case IOR:
+      opname = "or";
+      break;
+    case XOR:
+      opname = "xor";
+      break;
+    default:
+      abort ();
+    }
+
+  switch (mode)
+    {
+    case HImode:
+      /* First, see if we can finish with one insn.  */
+      if ((TARGET_H8300H || TARGET_H8300S)
+         && ((det & 0x00ff) != 0)
+         && ((det & 0xff00) != 0))
+       {
+         sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
+         output_asm_insn (insn_buf, operands);
+       }
+      else
+       {
+         /* Take care of the lower byte.  */
+         if ((det & 0x00ff) != 0)
+           {
+             sprintf (insn_buf, "%s\t%%s2,%%s0", opname);
+             output_asm_insn (insn_buf, operands);
+           }
+         /* Take care of the upper byte.  */
+         if ((det & 0xff00) != 0)
+           {
+             sprintf (insn_buf, "%s\t%%t2,%%t0", opname);
+             output_asm_insn (insn_buf, operands);
+           }
+       }
+      break;
+    case SImode:
+      /* First, see if we can finish with one insn.
+
+        If code is either AND or XOR, we exclude two special cases,
+        0xffffff00 and 0xffff00ff, because insns like sub.w or neg.w
+        can do a better job.  */
+      if ((TARGET_H8300H || TARGET_H8300S)
+         && ((det & 0x0000ffff) != 0)
+         && ((det & 0xffff0000) != 0)
+         && (code == IOR || det != 0xffffff00)
+         && (code == IOR || det != 0xffff00ff))
+       {
+         sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
+         output_asm_insn (insn_buf, operands);
+       }
+      else
+       {
+         /* Take care of the lower and upper words individually.  For
+            each word, we try different methods in the order of
+
+            1) the special insn (in case of AND or XOR),
+            2) the word-wise insn, and
+            3) The byte-wise insn.  */
+         if ((TARGET_H8300H || TARGET_H8300S)
+             && ((det & 0x0000ffff) == 0x0000ffff)
+             && code != IOR)
+           output_asm_insn ((code == AND)
+                            ? "sub.w\t%f0,%f0" : "neg.w\t%f0",
+                            operands);
+         else if ((TARGET_H8300H || TARGET_H8300S)
+                  && ((det & 0x000000ff) != 0)
+                  && ((det & 0x0000ff00) != 0))
+           {
+             sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname);
+             output_asm_insn (insn_buf, operands);
+           }
+         else
+           {
+             if ((det & 0x000000ff) != 0)
+               {
+                 sprintf (insn_buf, "%s\t%%w2,%%w0", opname);
+                 output_asm_insn (insn_buf, operands);
+               }
+             if ((det & 0x0000ff00) != 0)
+               {
+                 sprintf (insn_buf, "%s\t%%x2,%%x0", opname);
+                 output_asm_insn (insn_buf, operands);
+               }
+           }
+
+         if ((TARGET_H8300H || TARGET_H8300S)
+             && ((det & 0xffff0000) == 0xffff0000)
+             && code != IOR)
+           output_asm_insn ((code == AND)
+                            ? "sub.w\t%e0,%e0" : "neg.w\t%e0",
+                            operands);
+         else if (TARGET_H8300H || TARGET_H8300S)
+           {
+             if ((det & 0xffff0000) != 0)
+               {
+                 sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname);
+                 output_asm_insn (insn_buf, operands);
+               }
+           }
+         else
+           {
+             if ((det & 0x00ff0000) != 0)
+               {
+                 sprintf (insn_buf, "%s\t%%y2,%%y0", opname);
+                 output_asm_insn (insn_buf, operands);
+               }
+             if ((det & 0xff000000) != 0)
+               {
+                 sprintf (insn_buf, "%s\t%%z2,%%z0", opname);
+                 output_asm_insn (insn_buf, operands);
+               }
+           }
+       }
+      break;
+    default:
+      abort ();
+    }
+  return "";
+}
+\f
 /* Shifts.
 
    We devote a fair bit of code to getting efficient shifts since we can only
index b8a9b5e0a9942336ed37de23b5e9133f82ffc042..d9d549673a9ed80810bfaa161dfe08f787c623f8 100644 (file)
     DONE;
 }")
 
-(define_insn "andhi3"
+(define_expand "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (and:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
        (and:HI (match_operand:HI 1 "register_operand" "%0")
                (match_operand:HI 2 "nonmemory_operand" "rn")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
-
-      if ((i & 0x00ff) != 0x00ff)
-       output_asm_insn (\"and  %s2,%s0\", operands);
-      if ((i & 0xff00) != 0xff00)
-       output_asm_insn (\"and  %t2,%t0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"and.w     %T2,%T0\";
-  return \"and %s2,%s0\;and    %t2,%t0;\";
-}"
+  "TARGET_H8300"
+  "* return output_logical_op (HImode, AND, operands);"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
 
-(define_insn "andsi3"
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+       (and:HI (match_operand:HI 1 "register_operand" "%0,0")
+               (match_operand:HI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (HImode, AND, operands);"
+  [(set_attr "length" "2,4")
+   (set_attr "cc" "set_znv,clobber")])
+
+(define_expand "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (and:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (and:SI (match_operand:SI 1 "register_operand" "%0")
                (match_operand:SI 2 "nonmemory_operand" "rn")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
-      int upper_cleared, lower_cleared;
-
-      /* The h8300h can't do byte-wise operations on the
-        upper 16bits of 32bit registers.  However, if
-        those bits aren't going to change, or they're
-        going to be zero'd out, then we can work on the
-        low-order bits.  */
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && ((i & 0xffff0000) != 0xffff0000
-             || (i & 0xffff0000) == 0x00000000))
-        return \"and.l %S2,%S0\";
-
-      lower_cleared = 0;
-      if ((i & 0x0000ffff) == 0x00000000)
-       {
-         output_asm_insn (\"sub.w      %f0,%f0\", operands);
-         lower_cleared = 1;
-       }
-
-      upper_cleared = 0;
-      if ((i & 0xffff0000) == 0x00000000)
-       {
-         output_asm_insn (\"sub.w      %e0,%e0\", operands);
-         upper_cleared = 1;
-       }
-
-      if ((i & 0x000000ff) != 0x000000ff && !lower_cleared)
-       output_asm_insn (\"and  %w2,%w0\", operands);
-      if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared)
-       output_asm_insn (\"and  %x2,%x0\", operands);
-      if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared)
-       output_asm_insn (\"and  %y2,%y0\", operands);
-      if ((i & 0xff000000) != 0xff000000 && !upper_cleared)
-       output_asm_insn (\"and  %z2,%z0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"and.l     %S2,%S0\";
-  return \"and %w2,%w0\;and    %x2,%x0\;and    %y2,%y0\;and    %z2,%z0\";
-}"
+  "TARGET_H8300"
+  "* return output_logical_op (SImode, AND, operands);"
   [(set_attr "length" "8")
    (set_attr "cc" "clobber")])
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+               (match_operand:SI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (SImode, AND, operands);"
+  [(set_attr "length" "4,6")
+   (set_attr "cc" "set_znv,clobber")])
 
 ;; ----------------------------------------------------------------------
 ;; OR INSTRUCTIONS
     DONE;
 }")
 
-(define_insn "iorhi3"
+(define_expand "iorhi3"
   [(set (match_operand:HI 0 "general_operand" "=r,r")
        (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
                (match_operand:HI 2 "general_operand" "J,rn")))]
   ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
+  "")
 
-      if ((i & 0x00ff) != 0)
-       output_asm_insn (\"or   %s2,%s0\", operands);
-      if ((i & 0xff00) != 0)
-       output_asm_insn (\"or   %t2,%t0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"or.w      %T2,%T0\";
-  return \"or  %s2,%s0\;or     %t2,%t0; %2 or2\";
-}"
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r,r")
+       (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+               (match_operand:HI 2 "general_operand" "J,rn")))]
+  "TARGET_H8300"
+  "* return output_logical_op (HImode, IOR, operands);"
   [(set_attr "length" "2,4")
    (set_attr "cc" "clobber,clobber")])
 
-(define_insn "iorsi3"
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r,r,r")
+       (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0")
+               (match_operand:HI 2 "general_operand" "J,r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (HImode, IOR, operands);"
+  [(set_attr "length" "2,2,4")
+   (set_attr "cc" "clobber,set_znv,clobber")])
+
+(define_expand "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ior:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "nonmemory_operand" "J,rn")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
-
-      /* The h8300h can't do byte-wise operations on the
-        upper 16bits of 32bit registers.  However, if
-        those bits aren't going to change, then we can
-        work on the low-order bits.  */
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && (i & 0xffff0000) != 0x00000000)
-        return \"or.l  %S2,%S0\";
-
-      if ((i & 0x000000ff) != 0)
-       output_asm_insn (\"or   %w2,%w0\", operands);
-      if ((i & 0x0000ff00) != 0)
-       output_asm_insn (\"or   %x2,%x0\", operands);
-      if ((i & 0x00ff0000) != 0)
-       output_asm_insn (\"or   %y2,%y0\", operands);
-      if ((i & 0xff000000) != 0)
-       output_asm_insn (\"or   %z2,%z0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"or.l      %S2,%S0\";
-  return \"or  %w2,%w0\;or     %x2,%x0\;or     %y2,%y0\;or     %z2,%z0\";
-}"
+  "TARGET_H8300"
+  "* return output_logical_op (SImode, IOR, operands);"
   [(set_attr "length" "2,8")
    (set_attr "cc" "clobber,clobber")])
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+               (match_operand:SI 2 "nonmemory_operand" "J,r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (SImode, IOR, operands);"
+  [(set_attr "length" "2,4,6")
+   (set_attr "cc" "clobber,set_znv,clobber")])
+
 ;; ----------------------------------------------------------------------
 ;; XOR INSTRUCTIONS
 ;; ----------------------------------------------------------------------
     DONE;
 }")
 
-(define_insn "xorhi3"
+(define_expand "xorhi3"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (xor:HI (match_operand:HI 1 "general_operand" "")
+               (match_operand:HI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
                (match_operand:HI 2 "nonmemory_operand" "J,rn")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
-
-      if ((i & 0x00ff) != 0)
-       output_asm_insn (\"xor  %s2,%s0\", operands);
-      if ((i & 0xff00) != 0)
-       output_asm_insn (\"xor  %t2,%t0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"xor.w     %T2,%T0\";
-  return \"xor %s2,%s0\;xor    %t2,%t0\";
-}"
+  "TARGET_H8300"
+  "* return output_logical_op (HImode, XOR, operands);"
   [(set_attr "length" "2,4")
    (set_attr "cc" "clobber,clobber")])
 
-(define_insn "xorsi3"
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+       (xor:HI (match_operand:HI 1 "general_operand" "%0,0,0")
+               (match_operand:HI 2 "nonmemory_operand" "J,r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (HImode, XOR, operands);"
+  [(set_attr "length" "2,2,4")
+   (set_attr "cc" "clobber,set_znv,clobber")])
+
+(define_expand "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (xor:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "nonmemory_operand" "J,rn")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      int i = INTVAL (operands[2]);
-
-      /* The h8300h can't do byte-wise operations on the
-        upper 16bits of 32bit registers.  However, if
-        those bits aren't going to change, then we can
-        work on the low-order bits.  */
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && (i & 0xffff0000) != 0x00000000)
-        return \"xor.l %S2,%S0\";
-
-      if ((i & 0x000000ff) != 0)
-       output_asm_insn (\"xor  %w2,%w0\", operands);
-      if ((i & 0x0000ff00) != 0)
-       output_asm_insn (\"xor  %x2,%x0\", operands);
-      if ((i & 0x00ff0000) != 0)
-       output_asm_insn (\"xor  %y2,%y0\", operands);
-      if ((i & 0xff000000) != 0)
-       output_asm_insn (\"xor  %z2,%z0\", operands);
-      return \"\";
-    }
-  if (TARGET_H8300H || TARGET_H8300S)
-    return \"xor.l     %S2,%S0\";
-  return \"xor %w2,%w0\;xor    %x2,%x0\;xor    %y2,%y0\;xor    %z2,%z0\";
-}"
+  "TARGET_H8300"
+  "* return output_logical_op (SImode, XOR, operands);"
   [(set_attr "length" "2,8")
    (set_attr "cc" "clobber,clobber")])
+
+(define_insn ""
+  [(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" "J,r,n")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "* return output_logical_op (SImode, XOR, operands);"
+  [(set_attr "length" "2,4,6")
+   (set_attr "cc" "clobber,set_znv,clobber")])
 \f
 ;; ----------------------------------------------------------------------
 ;; NEGATION INSTRUCTIONS