* config/h8300/h8300-protos.h: Add a prototype for
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Mar 2002 17:20:01 +0000 (17:20 +0000)
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 2 Mar 2002 17:20:01 +0000 (17:20 +0000)
compute_a_shift_length.
* config/h8300/h8300.c (h8300_asm_insn_count): New.
(compute_a_shift_length): Likewise.
(h8300_adjust_insn_length): Do not adjust insn length of shift
insns.
* config/h8300/h8300.md (anonymous shift patterns): Use
compute_a_shift_length.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50227 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 2b395d3..3ebfedb 100644 (file)
@@ -1,3 +1,14 @@
+2002-03-02  Kazu Hirata  <kazu@hxi.com>
+
+       * config/h8300/h8300-protos.h: Add a prototype for
+       compute_a_shift_length.
+       * config/h8300/h8300.c (h8300_asm_insn_count): New.
+       (compute_a_shift_length): Likewise.
+       (h8300_adjust_insn_length): Do not adjust insn length of shift
+       insns.
+       * config/h8300/h8300.md (anonymous shift patterns): Use
+       compute_a_shift_length.
+
 Sat Mar  2 06:30:14 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * config/sparc/sparc.c (sparc_initialize_trampoline): Use
index ff31530..c864842 100644 (file)
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 /* Declarations for functions used in insn-output.c.  */
 #ifdef RTX_CODE
 extern const char *output_a_shift PARAMS ((rtx *));
+extern unsigned int compute_a_shift_length PARAMS ((rtx, rtx *));
 extern const char *emit_a_rotate PARAMS ((enum rtx_code, rtx *));
 extern const char *output_simode_bld PARAMS ((int, rtx[]));
 extern void print_operand_address PARAMS ((FILE *, rtx));
index aa31531..456577a 100644 (file)
@@ -54,6 +54,7 @@ static unsigned int compute_saved_regs PARAMS ((void));
 static void push PARAMS ((FILE *, int));
 static void pop PARAMS ((FILE *, int));
 static const char *cond_string PARAMS ((enum rtx_code));
+static unsigned int h8300_asm_insn_count PARAMS ((const char *));
 const struct attribute_spec h8300_attribute_table[];
 static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
@@ -2863,6 +2864,160 @@ output_a_shift (operands)
        }
     }
 }
+
+static unsigned int
+h8300_asm_insn_count (const char *template)
+{
+  unsigned int count = 1;
+
+  for (; *template; template++)
+    if (*template == '\n')
+      count++;
+
+  return count;
+}
+
+unsigned int
+compute_a_shift_length (insn, operands)
+     rtx insn ATTRIBUTE_UNUSED;
+     rtx *operands;
+{
+  rtx shift = operands[3];
+  enum machine_mode mode = GET_MODE (shift);
+  enum rtx_code code = GET_CODE (shift);
+  enum shift_type shift_type;
+  enum shift_mode shift_mode;
+  struct shift_info info;
+  unsigned int wlength = 0;
+
+  switch (mode)
+    {
+    case QImode:
+      shift_mode = QIshift;
+      break;
+    case HImode:
+      shift_mode = HIshift;
+      break;
+    case SImode:
+      shift_mode = SIshift;
+      break;
+    default:
+      abort ();
+    }
+
+  switch (code)
+    {
+    case ASHIFTRT:
+      shift_type = SHIFT_ASHIFTRT;
+      break;
+    case LSHIFTRT:
+      shift_type = SHIFT_LSHIFTRT;
+      break;
+    case ASHIFT:
+      shift_type = SHIFT_ASHIFT;
+      break;
+    default:
+      abort ();
+    }
+
+  if (GET_CODE (operands[2]) != CONST_INT)
+    {
+      /* Get the assembler code to do one shift.  */
+      get_shift_alg (shift_type, shift_mode, 1, &info);
+
+      return (4 + h8300_asm_insn_count (info.shift1)) * 2;
+    }
+  else
+    {
+      int n = INTVAL (operands[2]);
+
+      /* If the count is negative, make it 0.  */
+      if (n < 0)
+       n = 0;
+      /* If the count is too big, truncate it.
+         ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
+        do the intuitive thing.  */
+      else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
+       n = GET_MODE_BITSIZE (mode);
+
+      get_shift_alg (shift_type, shift_mode, n, &info);
+
+      switch (info.alg)
+       {
+       case SHIFT_SPECIAL:
+         wlength += h8300_asm_insn_count (info.special);
+         /* Fall through.  */
+
+       case SHIFT_INLINE:
+         n = info.remainder;
+
+         if (info.shift2 != NULL)
+           {
+             wlength += h8300_asm_insn_count (info.shift2) * (n / 2);
+             n = n % 2;
+           }
+
+         wlength += h8300_asm_insn_count (info.shift1) * n;
+           
+         return 2 * wlength;
+
+       case SHIFT_ROT_AND:
+         {
+           int m = GET_MODE_BITSIZE (mode) - n;
+
+           /* Not all possibilities of rotate are supported.  They shouldn't
+              be generated, but let's watch for 'em.  */
+           if (info.shift1 == 0)
+             abort ();
+
+           if (info.shift2 != NULL)
+             {
+               wlength += h8300_asm_insn_count (info.shift2) * (m / 2);
+               m = m % 2;
+             }
+
+           wlength += h8300_asm_insn_count (info.shift1) * m;
+           
+           /* Now mask off the high bits.  */
+           switch (mode)
+             {
+             case QImode:
+               wlength += 1;
+               break;
+             case HImode:
+               wlength += 2;
+               break;
+             case SImode:
+               if (TARGET_H8300)
+                 abort ();
+               wlength += 3;
+               break;
+             default:
+               abort ();
+             }
+           return 2 * wlength;
+         }
+
+       case SHIFT_LOOP:
+         /* A loop to shift by a "large" constant value.
+            If we have shift-by-2 insns, use them.  */
+         if (info.shift2 != NULL)
+           {
+             wlength += 3 + h8300_asm_insn_count (info.shift2);
+             if (n % 2)
+               wlength += h8300_asm_insn_count (info.shift1);
+           }
+         else
+           {
+             wlength += 3 + h8300_asm_insn_count (info.shift1);
+           }
+         return 2 * wlength;
+
+       default:
+         abort ();
+       }
+    }
+}
 \f
 /* A rotation by a non-constant will cause a loop to be generated, in
    which a rotation by one bit is used.  A rotation by a constant,
@@ -3436,50 +3591,6 @@ h8300_adjust_insn_length (insn, length)
        }
     }
 
-  /* Shifts need various adjustments.  */
-  if (GET_CODE (pat) == PARALLEL
-      && GET_CODE (XVECEXP (pat, 0, 0)) == SET
-      && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT
-         || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT
-         || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT))
-    {
-      rtx src = SET_SRC (XVECEXP (pat, 0, 0));
-      enum machine_mode mode = GET_MODE (src);
-      int shift;
-
-      if (GET_CODE (XEXP (src, 1)) != CONST_INT)
-       return 0;
-
-      shift = INTVAL (XEXP (src, 1));
-      /* According to ANSI, negative shift is undefined.  It is
-         considered to be zero in this case (see function
-         output_a_shift above).  */
-      if (shift < 0)
-       shift = 0;
-
-      /* QImode shifts by small constants take one insn
-        per shift.  So the adjustment is 20 (md length) -
-        # shifts * 2.  */
-      if (mode == QImode && shift <= 4)
-       return -(20 - shift * 2);
-
-      /* Similarly for HImode and SImode shifts by small constants on
-        the H8/300H and H8/S.  */
-      if ((TARGET_H8300H || TARGET_H8300S)
-         && (mode == HImode || mode == SImode) && shift <= 4)
-       return -(20 - shift * 2);
-
-      /* HImode shifts by small constants for the H8/300.  */
-      if (mode == HImode && shift <= 4)
-       return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 2 : 4)));
-
-      /* SImode shifts by small constants for the H8/300.  */
-      if (mode == SImode && shift <= 2)
-       return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 6 : 8)));
-
-      /* XXX ??? Could check for more shift/rotate cases here.  */
-    }
-
   /* Rotations need various adjustments.  */
   if (GET_CODE (pat) == SET
       && (GET_CODE (SET_SRC (pat)) == ROTATE
index b17d555..a3c445a 100644 (file)
    (clobber (match_scratch:QI 4 "=X,&r"))]
   ""
   "* return output_a_shift (operands);"
-  [(set_attr "length" "20")
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (insn, operands)"))
    (set_attr "cc" "clobber")])
 
 ;; HI BIT SHIFTS
    (clobber (match_scratch:QI 4 "=X,&r"))]
   ""
   "* return output_a_shift (operands);"
-  [(set_attr "length" "20")
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (insn, operands)"))
    (set_attr "cc" "clobber")])
 
 ;;  SI BIT SHIFTS
    (clobber (match_scratch:QI 4 "=X,&r"))]
   ""
   "* return output_a_shift (operands);"
-  [(set_attr "length" "20")
+  [(set (attr "length")
+       (symbol_ref "compute_a_shift_length (insn, operands)"))
    (set_attr "cc" "clobber")])
 \f
 ;; ----------------------------------------------------------------------