h8300-protos.h: Add a prototype for compute_mov_length.
authorKazu Hirata <kazu@cs.umass.edu>
Wed, 25 Jun 2003 03:47:31 +0000 (03:47 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Wed, 25 Jun 2003 03:47:31 +0000 (03:47 +0000)
* config/h8300/h8300-protos.h: Add a prototype for
compute_mov_length.
* config/h8300/h8300.c (compute_mov_length): New.
* config/h8300/h8300.md (*movqi_h8300): Use it.
(*movqi_h8300hs): Likewise.
(movstrictqi): Likewise.
(*movhi_h8300): Likewise.
(*movhi_h8300hs): Likewise.
(movstricthi): Likewise.
(*movsi_h8300): Likewise.
(*movsf_h8300): Likewise.
(*movsi_h8300hs): Likewise.
(*movsf_h8300hs): Likewise.

From-SVN: r68454

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

index f30e83542c92e5f9ccec36b6e4e4f1b45f887c32..d443295007892df8403732bc46a442eab3f67069 100644 (file)
@@ -1,3 +1,19 @@
+2003-06-24  Kazu Hirata  <kazu@cs.umass.edu>
+
+       * config/h8300/h8300-protos.h: Add a prototype for
+       compute_mov_length.
+       * config/h8300/h8300.c (compute_mov_length): New.
+       * config/h8300/h8300.md (*movqi_h8300): Use it.
+       (*movqi_h8300hs): Likewise.
+       (movstrictqi): Likewise.
+       (*movhi_h8300): Likewise.
+       (*movhi_h8300hs): Likewise.
+       (movstricthi): Likewise.
+       (*movsi_h8300): Likewise.
+       (*movsf_h8300): Likewise.
+       (*movsi_h8300hs): Likewise.
+       (*movsf_h8300hs): Likewise.
+
 2003-06-24  Kazu Hirata  <kazu@cs.umass.edu>
 
        * jump.c (next_nondeleted_insn): Remove.
index d1708698bb2f0eb7bbc09ea7d55cbb261a9193f4..e7ddff8f1c32e745fb36459b8e1a1d6ce3574a51 100644 (file)
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA.  */
 
 /* Declarations for functions used in insn-output.c.  */
 #ifdef RTX_CODE
+extern unsigned int compute_mov_length (rtx *);
 extern const char *output_plussi (rtx *);
 extern unsigned int compute_plussi_length (rtx *);
 extern int compute_plussi_cc (rtx *);
index e82ee9552b3372b7eee76393722ed932dea87e18..3a5334bf42c17debaa240aa4139777bbd70d1ed1 100644 (file)
@@ -1806,6 +1806,255 @@ bit_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
          || code == IOR);
 }
 \f
+/* Return the length of mov instruction.  */
+
+unsigned int
+compute_mov_length (rtx *operands)
+{
+  /* If the mov instruction involves a memory operand, we compute the
+     length, assuming the largest addressing mode is used, and then
+     adjust later in the function.  Otherwise, we compute and return
+     the exact length in one step.  */
+  enum machine_mode mode = GET_MODE (operands[0]);
+  rtx dest = operands[0];
+  rtx src = operands[1];
+  rtx addr;
+
+  if (GET_CODE (src) == MEM)
+    addr = XEXP (src, 0);
+  else if (GET_CODE (dest) == MEM)
+    addr = XEXP (dest, 0);
+  else
+    addr = NULL_RTX;
+
+  if (TARGET_H8300)
+    {
+      unsigned int base_length;
+
+      switch (mode)
+       {
+       case QImode:
+         if (addr == NULL_RTX)
+           return 2;
+
+         /* The eightbit addressing is available only in QImode, so
+            go ahead and take care of it.  */
+         if (h8300_eightbit_constant_address_p (addr))
+           return 2;
+
+         base_length = 4;
+         break;
+
+       case HImode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               return 2;
+
+             if (src == const0_rtx)
+               return 2;
+
+             return 4;
+           }
+
+         base_length = 4;
+         break;
+
+       case SImode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               return 4;
+
+             if (GET_CODE (src) == CONST_INT)
+               {
+                 if (src == const0_rtx)
+                   return 4;
+
+                 if ((INTVAL (src) & 0xffff) == 0)
+                   return 6;
+
+                 if ((INTVAL (src) & 0xffff) == 0)
+                   return 6;
+               }
+             return 8;
+           }
+
+         base_length = 8;
+         break;
+
+       case SFmode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               return 4;
+
+             if (src == const0_rtx)
+               return 2;
+
+             return 6;
+           }
+
+         base_length = 8;
+         break;
+
+       default:
+         abort ();
+       }
+
+      /* Adjust the length based on the addressing mode used.
+        Specifically, we subtract the difference between the actual
+        length and the longest one, which is @(d:16,Rs).  For SImode
+        and SFmode, we double the adjustment because two mov.w are
+        used to do the job.  */
+
+      /* @Rs+ and @-Rd are 2 bytes shorter than the longest.  */
+      if (GET_CODE (addr) == PRE_DEC
+         || GET_CODE (addr) == POST_INC)
+       {
+         if (mode == QImode || mode == HImode)
+           return base_length - 2;
+         else
+           /* In SImode and SFmode, we use two mov.w instructions, so
+              double the adustment.  */
+           return base_length - 4;
+       }
+
+      /* @Rs and @Rd are 2 bytes shorter than the longest.  Note that
+        in SImode and SFmode, the second mov.w involves an address
+        with displacement, namely @(2,Rs) or @(2,Rd), so we subtract
+        only 2 bytes.  */
+      if (GET_CODE (addr) == REG)
+       return base_length - 2;
+
+      return base_length;
+    }
+  else
+    {
+      unsigned int base_length;
+
+      switch (mode)
+       {
+       case QImode:
+         if (addr == NULL_RTX)
+           return 2;
+
+         /* The eightbit addressing is available only in QImode, so
+            go ahead and take care of it.  */
+         if (h8300_eightbit_constant_address_p (addr))
+           return 2;
+
+         base_length = 8;
+         break;
+
+       case HImode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               return 2;
+
+             if (src == const0_rtx)
+               return 2;
+
+             return 4;
+           }
+
+         base_length = 8;
+         break;
+
+       case SImode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               {
+                 if (REGNO (src) == MAC_REG || REGNO (dest) == MAC_REG)
+                   return 4;
+                 else
+                   return 2;
+               }
+
+             if (GET_CODE (src) == CONST_INT)
+               {
+                 int val = INTVAL (src);
+
+                 if (val == 0)
+                   return 2;
+
+                 if (val == (val & 0x00ff) || val == (val & 0xff00))
+                   return 4;
+                 
+                 switch (val & 0xffffffff)
+                   {
+                   case 0xffffffff:
+                   case 0xfffffffe:
+                   case 0xfffffffc:
+                   case 0x0000ffff:
+                   case 0x0000fffe:
+                   case 0xffff0000:
+                   case 0xfffe0000:
+                   case 0x00010000:
+                   case 0x00020000:
+                     return 4;
+                   }
+               }
+             return 6;
+           }
+
+         base_length = 10;
+         break;
+
+       case SFmode:
+         if (addr == NULL_RTX)
+           {
+             if (REG_P (src))
+               return 2;
+
+             if (src == const0_rtx)
+               return 2;
+             return 6;
+           }
+
+         base_length = 10;
+         break;
+
+       default:
+         abort ();
+       }
+
+      /* Adjust the length based on the addressing mode used.
+        Specifically, we subtract the difference between the actual
+        length and the longest one, which is @(d:24,ERs).  */
+
+      /* @ERs+ and @-ERd are 6 bytes shorter than the longest.  */
+      if (GET_CODE (addr) == PRE_DEC
+         || GET_CODE (addr) == POST_INC)
+       return base_length - 6;
+
+      /* @ERs and @ERd are 6 bytes shorter than the longest.  */
+      if (GET_CODE (addr) == REG)
+       return base_length - 6;
+
+      /* @(d:16,ERs) and @(d:16,ERd) are 4 bytes shorter than the
+        longest.  */
+      if (GET_CODE (addr) == PLUS
+         && GET_CODE (XEXP (addr, 0)) == REG
+         && GET_CODE (XEXP (addr, 1)) == CONST_INT
+         && INTVAL (XEXP (addr, 1)) > -32768
+         && INTVAL (XEXP (addr, 1)) < 32767)
+       return base_length - 4;
+
+      /* @aa:16 is 4 bytes shorter than the longest.  */
+      if (h8300_tiny_constant_address_p (addr))
+       return base_length - 4;
+
+      /* @aa:24 is 2 bytes shorter than the longest.  */
+      if (CONSTANT_P (addr))
+       return base_length - 2;
+
+      return base_length;
+    }
+}
+\f
 const char *
 output_plussi (rtx *operands)
 {
@@ -4067,101 +4316,6 @@ h8300_adjust_insn_length (rtx insn, int length ATTRIBUTE_UNUSED)
   if (get_attr_adjust_length (insn) == ADJUST_LENGTH_NO)
     return 0;
 
-  /* Adjust length for reg->mem and mem->reg copies.  */
-  if (GET_CODE (pat) == SET
-      && (GET_CODE (SET_SRC (pat)) == MEM
-         || GET_CODE (SET_DEST (pat)) == MEM))
-    {
-      /* This insn might need a length adjustment.  */
-      rtx addr;
-
-      if (GET_CODE (SET_SRC (pat)) == MEM)
-       addr = XEXP (SET_SRC (pat), 0);
-      else
-       addr = XEXP (SET_DEST (pat), 0);
-
-      if (TARGET_H8300)
-       {
-         /* On the H8/300, we subtract the difference between the
-             actual length and the longest one, which is @(d:16,ERs).  */
-
-         /* @Rs is 2 bytes shorter than the longest.  */
-         if (GET_CODE (addr) == REG)
-           return -2;
-
-         /* @aa:8 is 2 bytes shorter than the longest.  */
-         if (GET_MODE (SET_SRC (pat)) == QImode
-             && h8300_eightbit_constant_address_p (addr))
-           return -2;
-       }
-      else
-       {
-         /* On the H8/300H and H8S, we subtract the difference
-             between the actual length and the longest one, which is
-             @(d:24,ERs).  */
-
-         /* @ERs is 6 bytes shorter than the longest.  */
-         if (GET_CODE (addr) == REG)
-           return -6;
-
-         /* @(d:16,ERs) is 6 bytes shorter than the longest.  */
-         if (GET_CODE (addr) == PLUS
-             && GET_CODE (XEXP (addr, 0)) == REG
-             && GET_CODE (XEXP (addr, 1)) == CONST_INT
-             && INTVAL (XEXP (addr, 1)) > -32768
-             && INTVAL (XEXP (addr, 1)) < 32767)
-           return -4;
-
-         /* @aa:8 is 6 bytes shorter than the longest.  */
-         if (GET_MODE (SET_SRC (pat)) == QImode
-             && h8300_eightbit_constant_address_p (addr))
-           return -6;
-
-         /* @aa:16 is 4 bytes shorter than the longest.  */
-         if (h8300_tiny_constant_address_p (addr))
-           return -4;
-
-         /* @aa:24 is 2 bytes shorter than the longest.  */
-         if (GET_CODE (addr) == CONST_INT)
-           return -2;
-       }
-    }
-
-  /* Loading some constants needs adjustment.  */
-  if (GET_CODE (pat) == SET
-      && GET_CODE (SET_SRC (pat)) == CONST_INT
-      && GET_MODE (SET_DEST (pat)) == SImode
-      && INTVAL (SET_SRC (pat)) != 0)
-    {
-      int val = INTVAL (SET_SRC (pat));
-
-      if (TARGET_H8300
-         && ((val & 0xffff) == 0
-             || ((val >> 16) & 0xffff) == 0))
-       return -2;
-
-      if (TARGET_H8300H || TARGET_H8300S)
-       {
-         if (val == (val & 0xff)
-             || val == (val & 0xff00))
-           return 4 - 6;
-
-         switch (val & 0xffffffff)
-           {
-           case 0xffffffff:
-           case 0xfffffffe:
-           case 0xfffffffc:
-           case 0x0000ffff:
-           case 0x0000fffe:
-           case 0xffff0000:
-           case 0xfffe0000:
-           case 0x00010000:
-           case 0x00020000:
-             return 4 - 6;
-           }
-       }
-    }
-
   /* Rotations need various adjustments.  */
   if (GET_CODE (pat) == SET
       && (GET_CODE (SET_SRC (pat)) == ROTATE
index 5533cd8ecdb8f8e3088eb116a08f9ba7d8281cd0..ec9f1c6876f5f50933651bc2d31bc2ce0c6c0d5c 100644 (file)
    mov.b       %R1,%X0
    mov.b       %R1,%X0
    mov.b       %X1,%R0"
-  [(set_attr "length" "2,2,2,2,8,8")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,clobber,set_znv,set_znv")])
 
 (define_expand "movqi"
    mov.b       %X1,%X0
    mov.b       %R1,%X0
    mov.b       %R1,%X0"
-  [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2) (const_int 2)
-      (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")])
 
 ;; movhi
    mov.w       %T1,%T0
    mov.w       %T1,%T0
    mov.w       %T1,%T0"
-  [(set_attr "length" "2,2,2,4,4,4")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
 
 (define_insn "*movhi_h8300hs"
    mov.w       %T1,%T0
    mov.w       %T1,%T0
    mov.w       %T1,%T0"
-  [(set_attr "length" "2,2,2,4,8,8")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
 
 (define_expand "movhi"
    mov.w       %T1,%T0
    mov.w       %T1,%T0
    mov.w       %T1,%T0"
-  [(set_attr_alternative "length"
-     [(const_int 2) (const_int 2) (const_int 4)
-      (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")])
 
 ;; movsi
       abort ();
     }
 }"
-  [(set_attr "length" "4,4,8,8,4,4")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "clobber")])
 
 (define_insn "*movsf_h8300"
       abort ();
     }
 }"
-  [(set_attr "length" "4,4,8,8,4,4")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "clobber")])
 
 (define_insn "*movsi_h8300hs"
     }
    return \"mov.l      %S1,%S0\";
 }"
-  [(set_attr "length" "2,2,6,4,4,10,10,2,6,4")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
 
 (define_insn "*movsf_h8300h"
    mov.l       %S1,%S0
    mov.l       %S1,%S0
    mov.l       %S1,%S0"
-  [(set_attr "length" "2,2,10,10,4,4")
+  [(set (attr "length")
+       (symbol_ref "compute_mov_length (operands)"))
    (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
 \f
 ;; ----------------------------------------------------------------------