arm.c (arm_legitimate_index_p): Limit iWMMXt addressing modes to LDRD for DImode.
authorPaul Brook <paul@codesourcery.com>
Thu, 1 Mar 2007 22:58:40 +0000 (22:58 +0000)
committerPaul Brook <pbrook@gcc.gnu.org>
Thu, 1 Mar 2007 22:58:40 +0000 (22:58 +0000)
2007-03-01  Paul Brook  <paul@codesourcery.com>

* config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing
modes to LDRD for DImode.
(output_move_double): Fixup out of range ldrd/strd.
(vfp_secondary_reload_class): Rename...
(coproc_secondary_reload_class): ... to this.  Add wb argument.
* config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use
coproc_secondary_reload_class for CLASS_IWMMXT.
(SECONDARY_INPUT_RELOAD_CLASS): Ditto.
* arm-protos.h (coproc_secondary_reload_class): Update prototype.

From-SVN: r122437

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h

index 9c75bc251ed324026b2593a392b845336089b1e4..c3d0a7e3fb9c54f8358095b2f513259eb8aa428b 100644 (file)
@@ -1,3 +1,15 @@
+2007-03-01  Paul Brook  <paul@codesourcery.com>
+
+       * config/arm/arm.c (arm_legitimate_index_p): Limit iWMMXt addressing
+       modes to LDRD for DImode.
+       (output_move_double): Fixup out of range ldrd/strd.
+       (vfp_secondary_reload_class): Rename...
+       (coproc_secondary_reload_class): ... to this.  Add wb argument.
+       * config/arm/arm.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use
+       coproc_secondary_reload_class for CLASS_IWMMXT.
+       (SECONDARY_INPUT_RELOAD_CLASS): Ditto.
+       * arm-protos.h (coproc_secondary_reload_class): Update prototype.
+
 2007-03-01  Zdenek Dvorak  <dvorakz@suse.cz>
 
        * tree-ssa-loop-prefetch.c (determine_unroll_factor):  Bound the unroll
index 6a9a5492c1c3bd40298e1161e2d5c26d37f04954..9d24cd2b8770ab269297b22e71c7dab07d10c5e5 100644 (file)
@@ -68,7 +68,8 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
                                            int);
 extern int arm_const_double_rtx (rtx);
 extern int neg_const_double_rtx_ok_for_fpa (rtx);
-extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
+extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
+                                                    bool);
 extern bool arm_tls_referenced_p (rtx);
 
 extern int cirrus_memory_offset (rtx);
index 6998332a79d7d33beb4202f50b0c7b380758be75..74a9e008ca52d906e08434e877734318a7324b42 100644 (file)
@@ -3922,10 +3922,15 @@ thumb2_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
            && (INTVAL (index) & 3) == 0);
 
   if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
-    return (code == CONST_INT
-           && INTVAL (index) < 1024
-           && INTVAL (index) > -1024
-           && (INTVAL (index) & 3) == 0);
+    {
+      /* For DImode assume values will usually live in core regs
+        and only allow LDRD addressing modes.  */
+      if (!TARGET_LDRD || mode != DImode)
+       return (code == CONST_INT
+               && INTVAL (index) < 1024
+               && INTVAL (index) > -1024
+               && (INTVAL (index) & 3) == 0);
+    }
 
   if (arm_address_register_rtx_p (index, strict_p)
       && (GET_MODE_SIZE (mode) <= 4))
@@ -5764,12 +5769,12 @@ arm_eliminable_register (rtx x)
 }
 
 /* Return GENERAL_REGS if a scratch register required to reload x to/from
-   VFP registers.  Otherwise return NO_REGS.  */
+   coprocessor registers.  Otherwise return NO_REGS.  */
 
 enum reg_class
-vfp_secondary_reload_class (enum machine_mode mode, rtx x)
+coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
 {
-  if (arm_coproc_mem_operand (x, FALSE) || s_register_operand (x, mode))
+  if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
     return NO_REGS;
 
   return GENERAL_REGS;
@@ -9146,12 +9151,37 @@ output_move_double (rtx *operands)
                  output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
                }
              else
-               output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+               {
+                 /* IWMMXT allows offsets larger than ldrd can handle,
+                    fix these up with a pair of ldr.  */
+                 if (GET_CODE (otherops[2]) == CONST_INT
+                     && (INTVAL(otherops[2]) <= -256
+                         || INTVAL(otherops[2]) >= 256))
+                   {
+                     output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+                     otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+                     output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+                   }
+                 else
+                   output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+               }
            }
          else
            {
-             /* We only allow constant increments, so this is safe.  */
-             output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
+             /* IWMMXT allows offsets larger than ldrd can handle,
+                fix these up with a pair of ldr.  */
+             if (GET_CODE (otherops[2]) == CONST_INT
+                 && (INTVAL(otherops[2]) <= -256
+                     || INTVAL(otherops[2]) >= 256))
+               {
+                 otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+                 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+                 otherops[0] = operands[0];
+                 output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+               }
+             else
+               /* We only allow constant increments, so this is safe.  */
+               output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
            }
          break;
 
@@ -9289,7 +9319,29 @@ output_move_double (rtx *operands)
          otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0);
          otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1);
 
-         if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+         /* IWMMXT allows offsets larger than ldrd can handle,
+            fix these up with a pair of ldr.  */
+         if (GET_CODE (otherops[2]) == CONST_INT
+             && (INTVAL(otherops[2]) <= -256
+                 || INTVAL(otherops[2]) >= 256))
+           {
+             rtx reg1;
+             reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
+             if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+               {
+                 output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+                 otherops[0] = reg1;
+                 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+               }
+             else
+               {
+                 otherops[0] = reg1;
+                 output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+                 otherops[0] = operands[1];
+                 output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+               }
+           }
+         else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
            output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
          else
            output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
index 318d4f44624bf3c7a510dc2680678edb22de3ed2..d09bb734e2dcc712e3ee71796a4d6183a52d3bf8 100644 (file)
@@ -1121,10 +1121,12 @@ enum reg_class
    or out of a register in CLASS in MODE.  If it can be done directly,
    NO_REGS is returned.  */
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)          \
-  /* Restrict which direct reloads are allowed for VFP regs.  */ \
+  /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
     && (CLASS) == VFP_REGS)                                    \
-   ? vfp_secondary_reload_class (MODE, X)                      \
+   ? coproc_secondary_reload_class (MODE, X, FALSE)            \
+   : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS)                 \
+   ? coproc_secondary_reload_class (MODE, X, TRUE)             \
    : TARGET_32BIT                                              \
    ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
     ? GENERAL_REGS : NO_REGS)                                  \
@@ -1132,10 +1134,12 @@ enum reg_class
 
 /* If we need to load shorts byte-at-a-time, then we need a scratch.  */
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)           \
-  /* Restrict which direct reloads are allowed for VFP regs.  */ \
+  /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
     && (CLASS) == VFP_REGS)                                    \
-    ? vfp_secondary_reload_class (MODE, X) :                   \
+    ? coproc_secondary_reload_class (MODE, X, FALSE) :         \
+    (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ?                        \
+    coproc_secondary_reload_class (MODE, X, TRUE) :            \
   /* Cannot load constants into Cirrus registers.  */          \
    (TARGET_MAVERICK && TARGET_HARD_FLOAT                       \
      && (CLASS) == CIRRUS_REGS                                 \