h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
authorRichard Henderson <rth@cygnus.com>
Thu, 18 May 2000 16:52:10 +0000 (09:52 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 18 May 2000 16:52:10 +0000 (09:52 -0700)
        * config/h8300/h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
        (small_power_of_two): Likewise; use exact_log2.
        (adds_subs_operand, one_insn_adds_subs_operand): Remove.
        (output_adds_subs): Remove.
        (two_insn_adds_subs_operand): New.
        (split_adds_subs): New.
        * config/h8300/h8300-protos.h: Update.
        * config/h8300/h8300.h (CONST_OK_FOR_J): Cast to uns HOST_WIDE_INT.
        (CONST_OK_FOR_L): Match strict adds operands.
        (CONST_OK_FOR_N): Match struct subs operands.
        * config/h8300/h8300.md (adds_subs insns): Remove.
        (addhi patterns): Output adds/subs directly.
        (addsi_h8300h): Likewise.
        (addhi/addsi splitters): New.  Decompose two_insn_adds_subs_operand.

From-SVN: r33985

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

index 66fdc61..0788cdf 100644 (file)
@@ -1,3 +1,20 @@
+2000-05-18  Richard Henderson  <rth@cygnus.com>
+
+       * config/h8300/h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
+       (small_power_of_two): Likewise; use exact_log2.
+       (adds_subs_operand, one_insn_adds_subs_operand): Remove.
+       (output_adds_subs): Remove.
+       (two_insn_adds_subs_operand): New.
+       (split_adds_subs): New.
+       * config/h8300/h8300-protos.h: Update.
+       * config/h8300/h8300.h (CONST_OK_FOR_J): Cast to uns HOST_WIDE_INT.
+       (CONST_OK_FOR_L): Match strict adds operands.
+       (CONST_OK_FOR_N): Match struct subs operands.
+       * config/h8300/h8300.md (adds_subs insns): Remove.
+       (addhi patterns): Output adds/subs directly.
+       (addsi_h8300h): Likewise.
+       (addhi/addsi splitters): New.  Decompose two_insn_adds_subs_operand.
+
 2000-05-18  Zack Weinberg  <zack@wolery.cumb.org>
 
        * cppexp.c (parse_assertion): New.
index 0f4bf78..147e899 100644 (file)
@@ -36,14 +36,14 @@ extern void notice_update_cc PARAMS ((rtx, rtx));
 extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
 extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
 extern int h8300_adjust_insn_length PARAMS ((rtx, int));
+extern void split_adds_subs PARAMS ((enum machine_mode, rtx[]));
 
 extern int general_operand_src PARAMS ((rtx, enum machine_mode));
 extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
 extern int o_operand PARAMS ((rtx, enum machine_mode));
 extern int p_operand PARAMS ((rtx, enum machine_mode));
 extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
-extern int adds_subs_operand PARAMS ((rtx, enum machine_mode));
-extern int one_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
+extern int two_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
 extern int small_call_insn_operand PARAMS ((rtx, enum machine_mode));
 extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
 extern int bit_operand PARAMS ((rtx, enum machine_mode));
@@ -70,6 +70,6 @@ extern void function_prologue PARAMS ((FILE *, int));
 extern void function_epilogue PARAMS ((FILE *, int));
 extern void asm_file_start PARAMS ((FILE *));
 extern void asm_file_end PARAMS ((FILE *));
-extern int ok_for_bclr PARAMS ((int));
-extern int small_power_of_two PARAMS ((int));
+extern int ok_for_bclr PARAMS ((HOST_WIDE_INT));
+extern int small_power_of_two PARAMS ((HOST_WIDE_INT));
 extern int initial_offset PARAMS ((int, int));
index ee4d0ad..9425cbf 100644 (file)
@@ -542,29 +542,10 @@ asm_file_end (file)
 
 int
 small_power_of_two (value)
-     int value;
+     HOST_WIDE_INT value;
 {
-  switch (value)
-    {
-    case 1:
-    case 2:
-    case 4:
-    case 8:
-    case 16:
-    case 32:
-    case 64:
-    case 128:
-    case 256:
-    case 512:
-    case 1024:
-    case 2048:
-    case 4096:
-    case 8192:
-    case 16384:
-    case 32768:
-      return 1;
-    }
-  return 0;
+  int power = exact_log2 (value);
+  return power >= 0 && power <= 15;
 }
 
 /* Return true if VALUE is a valid constant for constraint 'O', which
@@ -573,7 +554,7 @@ small_power_of_two (value)
 
 int
 ok_for_bclr (value)
-     int value;
+     HOST_WIDE_INT value;
 {
   return small_power_of_two ((~value) & 0xff);
 }
@@ -645,107 +626,92 @@ call_insn_operand (op, mode)
 }
 
 int
-adds_subs_operand (op, mode)
+two_insn_adds_subs_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   if (GET_CODE (op) == CONST_INT)
     {
-      if (INTVAL (op) <= 4 && INTVAL (op) >= 0)
-       return 1;
-      if (INTVAL (op) >= -4 && INTVAL (op) <= 0)
-       return 1;
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && INTVAL (op) != 7
-         && (INTVAL (op) <= 8 && INTVAL (op) >= 0))
-       return 1;
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && INTVAL (op) != -7
-         && (INTVAL (op) >= -8 && INTVAL (op) <= 0))
-       return 1;
-    }
-  return 0;
-}
+      HOST_WIDE_INT value = INTVAL (op);
 
-/* Return nonzero if op is an adds/subs operand which only requires
-   one insn to implement.  It is assumed that OP is already an adds/subs
-   operand.  */
-int
-one_insn_adds_subs_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  int val = INTVAL (op);
+      if (TARGET_H8300H || TARGET_H8300S)
+       {
+         if (value >= -8 && value < -4 && value != -7)
+           return 1;
+         if (value > 4 && value <= 8 && value != 7)
+           return 1;
+       }
+      else
+       {
+         if (value == -4 || value == -3 || value == 3 || value == 4)
+           return 1;
+       }
+    }
 
-  if (val == 1 || val == -1
-      || val == 2 || val == -2
-      || ((TARGET_H8300H || TARGET_H8300S)
-         && (val == 4 || val == -4)))
-    return 1;
   return 0;
 }
 
-const char *
-output_adds_subs (operands)
+/* Split an add of a small constant into two adds/subs insns.  */
+
+void
+split_adds_subs (mode, operands)
+     enum machine_mode mode;
      rtx *operands;
 {
-  int val = INTVAL (operands[2]);
+  HOST_WIDE_INT val = INTVAL (operands[1]);
+  rtx reg = operands[0];
+  rtx tmp;
 
-  /* First get the value into the range -4..4 inclusive.
-
-     The only way it can be out of this range is when TARGET_H8300H
-     or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4.  */
-  if (val > 4)
+  /* Take care of +/- 4 for H8300H and H8300S.  */
+  if (TARGET_H8300H || TARGET_H8300S)
     {
-      output_asm_insn ("adds #4,%A0", operands);
-      val -= 4;
-    }
+      /* Get the value in range of +/- 4.  */
+      if (val > 4)
+       {
+         tmp = gen_rtx_PLUS (mode, reg, GEN_INT (4));
+         emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
+         val -= 4;
+       }
+      else if (val < -4)
+       {
+         tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-4));
+         emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
+         val += 4;
+       }
 
-  if (val < -4)
-    {
-      output_asm_insn ("subs #4,%A0", operands);
-      val += 4;
+      if (val == 4 || val == -4)
+       {
+         tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
+         emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
+         return;
+       }
     }
 
-  /* Handle case were val == 4 or val == -4 and we're compiling
-     for TARGET_H8300H or TARGET_H8300S.  */
-  if ((TARGET_H8300H || TARGET_H8300S)
-      && val == 4)
-    return "adds #4,%A0";
-
-  if ((TARGET_H8300H || TARGET_H8300S)
-      && val == -4)
-    return "subs #4,%A0";
-
+  /* Get the value in range of +/- 2.  */
   if (val > 2)
     {
-      output_asm_insn ("adds #2,%A0", operands);
+      tmp = gen_rtx_PLUS (mode, reg, GEN_INT (2));
+      emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
       val -= 2;
     }
-
-  if (val < -2)
+  else if (val < -2)
     {
-      output_asm_insn ("subs #2,%A0", operands);
+      tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-2));
+      emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
       val += 2;
     }
 
-  /* val should be one or two now.  */
-  if (val == 2)
-    return "adds #2,%A0";
-
-  if (val == -2)
-    return "subs #2,%A0";
-
-  /* val should be one now.  */
-  if (val == 1)
-    return "adds #1,%A0";
-
-  if (val == -1)
-    return "subs #1,%A0";
-
   /* If not optimizing, we might be asked to add 0.  */
   if (val == 0)
-    return "";
+    return;
+
+  /* We should have one or two now.  */
+  if (val >= -2 && val <= 2)
+    {
+      tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
+      emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
+      return;
+    }
 
   /* In theory, this can't happen.  */
   abort ();
index 276a3c0..7fdedf8 100644 (file)
@@ -399,11 +399,17 @@ enum reg_class {
    Return 1 if VALUE is in the range specified by C.  */
 
 #define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
-#define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) < 256)
-#define CONST_OK_FOR_K(VALUE) (((VALUE) == 1) || (VALUE) == 2)
-#define CONST_OK_FOR_L(VALUE) (((VALUE) == -1) || (VALUE) == -2)
-#define CONST_OK_FOR_M(VALUE) (((VALUE) == 3) || (VALUE) == 4)
-#define CONST_OK_FOR_N(VALUE) (((VALUE) == -3) || (VALUE) == -4)
+#define CONST_OK_FOR_J(VALUE) ((unsigned HOST_WIDE_INT) (VALUE) < 256)
+#define CONST_OK_FOR_K(VALUE) ((VALUE) == 1 || (VALUE) == 2)
+#define CONST_OK_FOR_L(VALUE) \
+  (TARGET_H8300H || TARGET_H8300S \
+   ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4 \
+   : (VALUE) == 1 || (VALUE) == 2)
+#define CONST_OK_FOR_M(VALUE) ((VALUE) == 3 || (VALUE) == 4)
+#define CONST_OK_FOR_N(VALUE) \
+  (TARGET_H8300H || TARGET_H8300S \
+   ? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4 \
+   : (VALUE) == -1 || (VALUE) == -2)
 #define CONST_OK_FOR_O(VALUE) (ok_for_bclr (VALUE))
 #define CONST_OK_FOR_P(VALUE) (small_power_of_two (VALUE))
 
@@ -415,7 +421,7 @@ enum reg_class {
    (C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
    (C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
    (C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
-   (C) == 'P' ? CONST_OK_FOR_P(VALUE) : \
+   (C) == 'P' ? CONST_OK_FOR_P (VALUE) : \
    0)
 
 /* Similar, but for floating constants, and defining letters G and H.
index fe0cca1..eeabdee 100644 (file)
   ""
   "")
 
-;; Specialized version using adds/subs.  This must come before
-;; the more general patterns below.
 (define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (plus:HI (match_operand:HI 1 "register_operand" "%0")
-                (match_operand:HI 2 "adds_subs_operand" "n")))]
-  ""
-  "* return output_adds_subs (operands);"
-  [(set_attr "cc" "none_0hit")
-   (set (attr "length")
-        (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
-                         (const_int 0))
-                     (const_int 2)
-                     (const_int 4)))])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=&r,r,&r")
-       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,g")
-                (match_operand:HI 2 "nonmemory_operand" "n,r,r")))]
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r")
+       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g")
+                (match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))]
   "TARGET_H8300"
   "@
+   adds        %2,%A0
+   subs        %2,%A0
    add.b       %s2,%s0\;addx   %t2,%t0 
    add.w       %T2,%T0
    mov.w        %T1,%T0\;add.w  %T2,%T0"
-  [(set_attr "length" "4,2,6")
-   (set_attr "cc" "clobber,set_zn,set_zn")])
+  [(set_attr "length" "2,2,4,2,6")
+   (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
 
 (define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
-                (match_operand:HI 2 "nonmemory_operand" "n,r")))]
+  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
+       (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
+                (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
   "TARGET_H8300H || TARGET_H8300S"
   "@
+   adds        %2,%A0
+   subs        %2,%A0
    add.w       %T2,%T0
    add.w       %T2,%T0"
-  [(set_attr "length" "4,2")
-   (set_attr "cc" "set_zn,set_zn")])
+  [(set_attr "length" "2,2,4,2")
+   (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "two_insn_adds_subs_operand" "")))]
+  ""
+  [(const_int 0)]
+  "split_adds_subs (HImode, operands); DONE;")
 
 (define_expand "addsi3"
   [(set (match_operand:SI 0 "register_operand" "")
   ""
   "")
 
-;; Specialized version using adds/subs.  This must come before
-;; the more general patterns below.
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "adds_subs_operand" "n")))]
-  "TARGET_H8300H || TARGET_H8300S"
-  "* return output_adds_subs (operands);"
-  [(set_attr "cc" "none_0hit")
-   (set (attr "length")
-        (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
-                         (const_int 0))
-                     (const_int 2)
-                     (const_int 4)))])
-
 (define_insn "addsi_h8300"
   [(set (match_operand:SI 0 "register_operand" "=r,r,&r")
        (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
    (set_attr "cc" "clobber")])
 
 (define_insn "addsi_h8300h"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
-                (match_operand:SI 2 "nonmemory_operand" "i,r")))]
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+       (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+                (match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
   "TARGET_H8300H || TARGET_H8300S"
   "@
+   adds        %2,%A0
+   subs        %2,%A0
    add.l       %S2,%S0
    add.l       %S2,%S0"
-  [(set_attr "length" "6,2")
-   (set_attr "cc" "set_zn,set_zn")])
+  [(set_attr "length" "2,2,6,2")
+   (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_dup 0)
+                (match_operand:SI 1 "two_insn_adds_subs_operand" "")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(const_int 0)]
+  "split_adds_subs (SImode, operands); DONE;")
 
 ;; ----------------------------------------------------------------------
 ;; SUBTRACT INSTRUCTIONS
   ""
   "")
 
-;; Specialized version using adds/subs.  This must come before
-;; the more general patterns below.  This may not be needed
-;; due to instruction canonicalization.
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (minus:HI (match_operand:HI 1 "register_operand" "r")
-                 (match_operand:HI 2 "adds_subs_operand" "n")))]
-  ""
-  "*
-{
-  operands[2] = GEN_INT (-INTVAL (operands[2]));
-  return output_adds_subs (operands);
-}"
-  [(set_attr "cc" "none_0hit")
-   (set (attr "length")
-        (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
-                         (const_int 0))
-                     (const_int 2)
-                     (const_int 4)))])
-
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r,&r")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
-;; Specialized version using adds/subs.  This must come before
-;; the more general patterns below.  This may not be needed
-;; due to instruction canonicalization.
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (minus:SI (match_operand:SI 1 "general_operand" "0")
-                 (match_operand:SI 2 "adds_subs_operand" "n")))]
-  "TARGET_H8300H || TARGET_H8300S"
-  "*
-{
-  operands[2] = GEN_INT (-INTVAL (operands[2]));
-  return output_adds_subs (operands);
-}"
-  [(set_attr "cc" "none_0hit")
-   (set (attr "length")
-        (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
-                         (const_int 0))
-                     (const_int 2)
-                     (const_int 4)))])
-
 (define_insn "subsi3_h8300h"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (minus:SI (match_operand:SI 1 "general_operand" "0,0")