]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
constraints.md: Adjust unused letters.
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>
Sun, 3 Feb 2013 19:52:37 +0000 (19:52 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Sun, 3 Feb 2013 19:52:37 +0000 (19:52 +0000)
* config/pa/constraints.md: Adjust unused letters.  Change "T"
constraint to match_test floating_point_store_memory_operand().
* config/pa/predicates.md (reg_plus_base_memory_operand): New.
(base14_operand): New.
(floating_point_store_memory_operand): New.
(integer_store_memory_operand): Revise to use base14_operand and
reg_plus_base_memory_operand.
(move_dest_operand): Allow symbolic_memory_operands.
(symbolic_memory_operand): Check for LO_SOM.
(symbolic_operand): Change default case to break.
* config/pa/pa.md: Remove unamed DFmode and SFmode patterns to force
CONST_DOUBLE values to be reloaded by putting them into memory when
the destination is a floating point register.
(movdf): Remove code to handle CONST_DOUBLE.
(movsf): Likewise.
(reload_indf_r1): New.
(reload_insf_r1): New.
Consistently use "Q" and "T" constraints with integer and floating
point move instructions, respectively.
(movdi): Remove FAIL.
Change predicate for source operand unamed DImode move from
general_operand to move_src_operand.
(umulsidi3): Change predicate for destination operand to
register_operand.
Likewise for similar unamed patterns.
* config/pa/pa-protos.h (pa_legitimize_reload_address): Declare.
* config/pa/pa.c (pa_symbolic_expression_p): Remove extra parenthesis.
(hppa_legitimize_address): Simplify mask calculation.
(pa_emit_move_sequence): Revised handling of secondary reloads from
REG+D addresses for floating point loads and stores.  Directly handle
loading CONST0_RTX (mode) to a floating point register.
(pa_secondary_reload): Handle reloading DF and SFmode constant values
to floating point registers.  Don't restrict secondary reloads to
floating point registers to integer modes.  Revise some comments and
cleanup some code.
(TARGET_LEGITIMATE_ADDRESS_P): Define.
(pa_legitimate_address_p): New.
(pa_legitimize_reload_address): New.
* config/pa/pa.h (STRICT_REG_OK_FOR_INDEX_P): New.
(STRICT_REG_OK_FOR_BASE_P): New.
(GO_IF_LEGITIMATE_ADDRESS): Delete.  Update some related comments.
(LEGITIMIZE_RELOAD_ADDRESS): Revise to use pa_legitimize_reload_address.

From-SVN: r195702

gcc/ChangeLog
gcc/config/pa/constraints.md
gcc/config/pa/pa-protos.h
gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/pa.md
gcc/config/pa/predicates.md

index 95a808c36eefc4e52670707ffec9fa72c2d69076..103976fc83304b8bb312dc26c3827c26a5f09278 100644 (file)
@@ -1,3 +1,48 @@
+2013-02-03  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * config/pa/constraints.md: Adjust unused letters.  Change "T"
+       constraint to match_test floating_point_store_memory_operand().
+       * config/pa/predicates.md (reg_plus_base_memory_operand): New.
+       (base14_operand): New.
+       (floating_point_store_memory_operand): New.
+       (integer_store_memory_operand): Revise to use base14_operand and
+       reg_plus_base_memory_operand.
+       (move_dest_operand): Allow symbolic_memory_operands.
+       (symbolic_memory_operand): Check for LO_SOM.
+       (symbolic_operand): Change default case to break.
+       * config/pa/pa.md: Remove unamed DFmode and SFmode patterns to force
+       CONST_DOUBLE values to be reloaded by putting them into memory when
+       the destination is a floating point register.
+       (movdf): Remove code to handle CONST_DOUBLE.
+       (movsf): Likewise.
+       (reload_indf_r1): New.
+       (reload_insf_r1): New.
+       Consistently use "Q" and "T" constraints with integer and floating
+       point move instructions, respectively.
+       (movdi): Remove FAIL.
+       Change predicate for source operand unamed DImode move from
+       general_operand to move_src_operand.
+       (umulsidi3): Change predicate for destination operand to
+       register_operand.
+       Likewise for similar unamed patterns.
+       * config/pa/pa-protos.h (pa_legitimize_reload_address): Declare.
+       * config/pa/pa.c (pa_symbolic_expression_p): Remove extra parenthesis.
+       (hppa_legitimize_address): Simplify mask calculation.
+       (pa_emit_move_sequence): Revised handling of secondary reloads from
+       REG+D addresses for floating point loads and stores.  Directly handle
+       loading CONST0_RTX (mode) to a floating point register.
+       (pa_secondary_reload): Handle reloading DF and SFmode constant values
+       to floating point registers.  Don't restrict secondary reloads to
+       floating point registers to integer modes.  Revise some comments and
+       cleanup some code.
+       (TARGET_LEGITIMATE_ADDRESS_P): Define.
+       (pa_legitimate_address_p): New.
+       (pa_legitimize_reload_address): New.
+       * config/pa/pa.h (STRICT_REG_OK_FOR_INDEX_P): New.
+       (STRICT_REG_OK_FOR_BASE_P): New.
+       (GO_IF_LEGITIMATE_ADDRESS): Delete.  Update some related comments.
+       (LEGITIMIZE_RELOAD_ADDRESS): Revise to use pa_legitimize_reload_address.
+
 2013-02-03  David Edelsohn  <dje.gcc@gmail.com>
            Andrew Dixie  <andrewd@gentrack.com>
 
index 899e59139da217cfd9a4f610ab941eebc6492bda..bdc119e4d31b1a55ff2a551c0382c1e7647448bc 100644 (file)
@@ -18,8 +18,8 @@
 ;; <http://www.gnu.org/licenses/>.
 
 ;;; Unused letters:
-;;;    ABCDEF H             V  Y 
-;;;     bcde ghijklmnop  stuvw  z
+;;;    ABCD   H                Y 
+;;;     bcde  h jkl       tuvw  z
 
 ;; Register constraints.
 (define_register_constraint "a" "R1_REGS"
 
 (define_constraint "T"
   "A memory operand for floating-point loads and stores."
-  (and (match_code "mem")
-       (match_test "!IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
-                   && !IS_INDEX_ADDR_P (XEXP (op, 0))
-                   && memory_address_p ((GET_MODE_SIZE (mode) == 4
-                                         ? SFmode : DFmode),
-                                        XEXP (op, 0))")))
+  (match_test "floating_point_store_memory_operand (op, mode)"))
 
 ;; We could allow short displacements but TARGET_LEGITIMATE_ADDRESS_P
 ;; can't tell when a long displacement is valid.
index e3d65279b0b17f0ae5dd957840ad52f2b4fbfa63..ab1763a5d19b56324a11040f61aa37127b9404bd 100644 (file)
@@ -67,6 +67,8 @@ extern int pa_fpstore_bypass_p (rtx, rtx);
 extern int pa_attr_length_millicode_call (rtx);
 extern int pa_attr_length_call (rtx, int);
 extern int pa_attr_length_indirect_call (rtx);
+extern rtx pa_legitimize_reload_address (rtx, enum machine_mode,
+                                        int, int, int);
 
 /* Declare functions defined in pa.c and used in templates.  */
 
index 429711ec5d83e0ce2a559591f12f1ebeda611010..36eba24d6234aa020140b01cd47b7f413f00f6e2 100644 (file)
@@ -187,6 +187,7 @@ static section *pa_function_section (tree, enum node_frequency, bool, bool);
 static bool pa_cannot_force_const_mem (enum machine_mode, rtx);
 static bool pa_legitimate_constant_p (enum machine_mode, rtx);
 static unsigned int pa_section_type_flags (tree, const char *, int);
+static bool pa_legitimate_address_p (enum machine_mode, rtx, bool);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -384,6 +385,8 @@ static size_t n_deferred_plabels = 0;
 #define TARGET_LEGITIMATE_CONSTANT_P pa_legitimate_constant_p
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS pa_section_type_flags
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P pa_legitimate_address_p
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
@@ -685,7 +688,7 @@ pa_symbolic_expression_p (rtx x)
   if (GET_CODE (x) == HIGH)
     x = XEXP (x, 0);
 
-  return (symbolic_operand (x, VOIDmode));
+  return symbolic_operand (x, VOIDmode);
 }
 
 /* Accept any constant that can be moved in one instruction into a
@@ -1057,7 +1060,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       int mask;
 
       mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
-             ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff);
+             && !INT14_OK_STRICT ? 0x1f : 0x3fff);
 
       /* Choose which way to round the offset.  Round up if we
         are >= halfway to the next boundary.  */
@@ -1393,7 +1396,7 @@ hppa_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
    PIC addresses are very expensive.
 
    It is no coincidence that this has the same structure
-   as GO_IF_LEGITIMATE_ADDRESS.  */
+   as pa_legitimate_address_p.  */
 
 static int
 hppa_address_cost (rtx X, enum machine_mode mode ATTRIBUTE_UNUSED,
@@ -1650,14 +1653,10 @@ pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
      (subreg (mem (addr))) cases.  */
   if (scratch_reg
       && fp_reg_operand (operand0, mode)
-      && ((GET_CODE (operand1) == MEM
-          && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
-                                XEXP (operand1, 0)))
-         || ((GET_CODE (operand1) == SUBREG
-              && GET_CODE (XEXP (operand1, 0)) == MEM
-              && !memory_address_p ((GET_MODE_SIZE (mode) == 4
-                                     ? SFmode : DFmode),
-                                    XEXP (XEXP (operand1, 0), 0))))))
+      && (MEM_P (operand1)
+         || (GET_CODE (operand1) == SUBREG
+             && MEM_P (XEXP (operand1, 0))))
+      && !floating_point_store_memory_operand (operand1, mode))
     {
       if (GET_CODE (operand1) == SUBREG)
        operand1 = XEXP (operand1, 0);
@@ -1669,7 +1668,10 @@ pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
 
       /* D might not fit in 14 bits either; for such cases load D into
         scratch reg.  */
-      if (!memory_address_p (Pmode, XEXP (operand1, 0)))
+      if (reg_plus_base_memory_operand (operand1, mode)
+         && !(TARGET_PA_20
+              && !TARGET_ELF32
+              && INT_14_BITS (XEXP (XEXP (operand1, 0), 1))))
        {
          emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
          emit_move_insn (scratch_reg,
@@ -1686,15 +1688,10 @@ pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
     }
   else if (scratch_reg
           && fp_reg_operand (operand1, mode)
-          && ((GET_CODE (operand0) == MEM
-               && !memory_address_p ((GET_MODE_SIZE (mode) == 4
-                                       ? SFmode : DFmode),
-                                      XEXP (operand0, 0)))
-              || ((GET_CODE (operand0) == SUBREG)
-                  && GET_CODE (XEXP (operand0, 0)) == MEM
-                  && !memory_address_p ((GET_MODE_SIZE (mode) == 4
-                                         ? SFmode : DFmode),
-                                        XEXP (XEXP (operand0, 0), 0)))))
+          && (MEM_P (operand0)
+              || (GET_CODE (operand0) == SUBREG
+                  && MEM_P (XEXP (operand0, 0))))
+          && !floating_point_store_memory_operand (operand0, mode))
     {
       if (GET_CODE (operand0) == SUBREG)
        operand0 = XEXP (operand0, 0);
@@ -1706,7 +1703,10 @@ pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
 
       /* D might not fit in 14 bits either; for such cases load D into
         scratch reg.  */
-      if (!memory_address_p (Pmode, XEXP (operand0, 0)))
+      if (reg_plus_base_memory_operand (operand0, mode)
+         && !(TARGET_PA_20
+              && !TARGET_ELF32
+              && INT_14_BITS (XEXP (XEXP (operand0, 0), 1))))
        {
          emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
          emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
@@ -1724,20 +1724,22 @@ pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
       return 1;
     }
   /* Handle secondary reloads for loads of FP registers from constant
-     expressions by forcing the constant into memory.
+     expressions by forcing the constant into memory.  For the most part,
+     this is only necessary for SImode and DImode.
 
-     Use scratch_reg to hold the address of the memory location.
-
-     The proper fix is to change TARGET_PREFERRED_RELOAD_CLASS to return
-     NO_REGS when presented with a const_int and a register class
-     containing only FP registers.  Doing so unfortunately creates
-     more problems than it solves.   Fix this for 2.5.  */
+     Use scratch_reg to hold the address of the memory location.  */
   else if (scratch_reg
           && CONSTANT_P (operand1)
           && fp_reg_operand (operand0, mode))
     {
       rtx const_mem, xoperands[2];
 
+      if (operand1 == CONST0_RTX (mode))
+       {
+         emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
+         return 1;
+       }
+
       /* SCRATCH_REG will hold an address and maybe the actual data.  We want
         it in WORD_MODE regardless of what mode it was originally given
         to us.  */
@@ -5341,7 +5343,7 @@ pa_print_operand (FILE *file, rtx x, int code)
                   && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
            {
              /* Because the REG_POINTER flag can get lost during reload,
-                GO_IF_LEGITIMATE_ADDRESS canonicalizes the order of the
+                pa_legitimate_address_p canonicalizes the order of the
                 index and base registers in the combined move patterns.  */
              rtx base = XEXP (XEXP (x, 0), 1);
              rtx index = XEXP (XEXP (x, 0), 0);
@@ -5892,9 +5894,9 @@ pa_output_arg_descriptor (rtx call_insn)
   fputc ('\n', asm_out_file);
 }
 \f
-/* Inform reload about cases where moving X with a mode MODE to a register in
-   RCLASS requires an extra scratch or immediate register.  Return the class
-   needed for the immediate register.  */
+/* Inform reload about cases where moving X with a mode MODE to or from
+   a register in RCLASS requires an extra scratch or immediate register.
+   Return the class needed for the immediate register.  */
 
 static reg_class_t
 pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
@@ -5923,19 +5925,39 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
     return NO_REGS;
 
   /* Trying to load a constant into a FP register during PIC code
-     generation requires %r1 as a scratch register.  */
+     generation requires %r1 as a scratch register.  For float modes,
+     the only legitimate constant is CONST0_RTX.  However, there are
+     a few patterns that accept constant double operands.  */
   if (flag_pic
-      && (mode == SImode || mode == DImode)
       && FP_REG_CLASS_P (rclass)
       && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
     {
-      sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
-                   : CODE_FOR_reload_indi_r1);
+      switch (mode)
+       {
+       case SImode:
+         sri->icode = CODE_FOR_reload_insi_r1;
+         break;
+
+       case DImode:
+         sri->icode = CODE_FOR_reload_indi_r1;
+         break;
+
+       case SFmode:
+         sri->icode = CODE_FOR_reload_insf_r1;
+         break;
+
+       case DFmode:
+         sri->icode = CODE_FOR_reload_indf_r1;
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
       return NO_REGS;
     }
 
-  /* Secondary reloads of symbolic operands require %r1 as a scratch
-     register when we're generating PIC code and when the operand isn't
+  /* Secondary reloads of symbolic expressions require %r1 as a scratch
+     register when we're generating PIC code or when the operand isn't
      readonly.  */
   if (pa_symbolic_expression_p (x))
     {
@@ -5944,9 +5966,19 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
 
       if (flag_pic || !read_only_operand (x, VOIDmode))
        {
-         gcc_assert (mode == SImode || mode == DImode);
-         sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
-                       : CODE_FOR_reload_indi_r1);
+         switch (mode)
+           {
+           case SImode:
+             sri->icode = CODE_FOR_reload_insi_r1;
+             break;
+
+           case DImode:
+             sri->icode = CODE_FOR_reload_indi_r1;
+             break;
+
+           default:
+             gcc_unreachable ();
+           }
          return NO_REGS;
        }
     }
@@ -5956,22 +5988,11 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
     regno = true_regnum (x);
 
-  /* In order to allow 14-bit displacements in integer loads and stores,
-     we need to prevent reload from generating out of range integer mode
-     loads and stores to the floating point registers.  Previously, we
-     used to call for a secondary reload and have pa_emit_move_sequence()
-     fix the instruction sequence.  However, reload occasionally wouldn't
-     generate the reload and we would end up with an invalid REG+D memory
-     address.  So, now we use an intermediate general register for most
-     memory loads and stores.  */
+  /* Handle reloads for floating point loads and stores.  */
   if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
-      && GET_MODE_CLASS (mode) == MODE_INT
       && FP_REG_CLASS_P (rclass))
     {
-      /* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check
-        the secondary reload needed for a pseudo.  It never passes a
-        REG+D address.  */
-      if (GET_CODE (x) == MEM)
+      if (MEM_P (x))
        {
          x = XEXP (x, 0);
 
@@ -5985,7 +6006,7 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
              || IS_LO_SUM_DLT_ADDR_P (x))
            return NO_REGS;
 
-         /* Otherwise, we need an intermediate general register.  */
+         /* Request intermediate general register.  */
          return GENERAL_REGS;
        }
 
@@ -10406,4 +10427,253 @@ pa_section_type_flags (tree decl, const char *name, int reloc)
   return flags;
 }
 
+/* pa_legitimate_address_p recognizes an RTL expression that is a
+   valid memory address for an instruction.  The MODE argument is the
+   machine mode for the MEM expression that wants to use this address.
+
+   On HP PA-RISC, the legitimate address forms are REG+SMALLINT,
+   REG+REG, and REG+(REG*SCALE).  The indexed address forms are only
+   available with floating point loads and stores, and integer loads.
+   We get better code by allowing indexed addresses in the initial
+   RTL generation.
+
+   The acceptance of indexed addresses as legitimate implies that we
+   must provide patterns for doing indexed integer stores, or the move
+   expanders must force the address of an indexed store to a register.
+   We have adopted the latter approach.
+   
+   Another function of pa_legitimate_address_p is to ensure that
+   the base register is a valid pointer for indexed instructions.
+   On targets that have non-equivalent space registers, we have to
+   know at the time of assembler output which register in a REG+REG
+   pair is the base register.  The REG_POINTER flag is sometimes lost
+   in reload and the following passes, so it can't be relied on during
+   code generation.  Thus, we either have to canonicalize the order
+   of the registers in REG+REG indexed addresses, or treat REG+REG
+   addresses separately and provide patterns for both permutations.
+
+   The latter approach requires several hundred additional lines of
+   code in pa.md.  The downside to canonicalizing is that a PLUS
+   in the wrong order can't combine to form to make a scaled indexed
+   memory operand.  As we won't need to canonicalize the operands if
+   the REG_POINTER lossage can be fixed, it seems better canonicalize.
+
+   We initially break out scaled indexed addresses in canonical order
+   in pa_emit_move_sequence.  LEGITIMIZE_ADDRESS also canonicalizes
+   scaled indexed addresses during RTL generation.  However, fold_rtx
+   has its own opinion on how the operands of a PLUS should be ordered.
+   If one of the operands is equivalent to a constant, it will make
+   that operand the second operand.  As the base register is likely to
+   be equivalent to a SYMBOL_REF, we have made it the second operand.
+
+   pa_legitimate_address_p accepts REG+REG as legitimate when the
+   operands are in the order INDEX+BASE on targets with non-equivalent
+   space registers, and in any order on targets with equivalent space
+   registers.  It accepts both MULT+BASE and BASE+MULT for scaled indexing.
+
+   We treat a SYMBOL_REF as legitimate if it is part of the current
+   function's constant-pool, because such addresses can actually be
+   output as REG+SMALLINT.  */
+
+static bool
+pa_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+  if ((REG_P (x)
+       && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
+                 : REG_OK_FOR_BASE_P (x)))
+      || ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_DEC
+          || GET_CODE (x) == PRE_INC || GET_CODE (x) == POST_INC)
+         && REG_P (XEXP (x, 0))
+         && (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))
+                    : REG_OK_FOR_BASE_P (XEXP (x, 0)))))
+    return true;
+
+  if (GET_CODE (x) == PLUS)
+    {
+      rtx base, index;
+
+      /* For REG+REG, the base register should be in XEXP (x, 1),
+        so check it first.  */
+      if (REG_P (XEXP (x, 1))
+         && (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 1))
+                    : REG_OK_FOR_BASE_P (XEXP (x, 1))))
+       base = XEXP (x, 1), index = XEXP (x, 0);
+      else if (REG_P (XEXP (x, 0))
+              && (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))
+                         : REG_OK_FOR_BASE_P (XEXP (x, 0))))
+       base = XEXP (x, 0), index = XEXP (x, 1);
+      else
+       return false;
+
+      if (GET_CODE (index) == CONST_INT)
+       {
+         if (INT_5_BITS (index))
+           return true;
+
+         /* When INT14_OK_STRICT is false, a secondary reload is needed
+            to adjust the displacement of SImode and DImode floating point
+            instructions.  So, we return false when STRICT is true.  We
+            also reject long displacements for float mode addresses since
+            the majority of accesses will use floating point instructions
+            that don't support 14-bit offsets.  */
+         if (!INT14_OK_STRICT
+             && (GET_MODE_CLASS (mode) == MODE_FLOAT
+                 || (reload_in_progress
+                     && strict
+                     && (mode == SImode || mode == DImode))))
+          return false;
+
+         if (INT_14_BITS (index)
+             && (mode == BLKmode
+                 || mode == QImode
+                 || mode == HImode
+                 /* Displacement must be a multiple of its size.  */
+                 || (INTVAL (index) % GET_MODE_SIZE (mode)) == 0))
+           return true;
+
+         return false;
+       }
+
+      if (!TARGET_DISABLE_INDEXING
+         /* Only accept the "canonical" INDEX+BASE operand order
+            on targets with non-equivalent space registers.  */
+         && (TARGET_NO_SPACE_REGS
+             ? REG_P (index)
+             : (base == XEXP (x, 1) && REG_P (index)
+                && (reload_completed
+                    || (reload_in_progress && HARD_REGISTER_P (base))
+                    || REG_POINTER (base))
+                && (reload_completed
+                    || (reload_in_progress && HARD_REGISTER_P (index))
+                    || !REG_POINTER (index))))
+         && MODE_OK_FOR_UNSCALED_INDEXING_P (mode)
+         && (strict ? STRICT_REG_OK_FOR_INDEX_P (index)
+                    : REG_OK_FOR_INDEX_P (index))
+         && borx_reg_operand (base, Pmode)
+         && borx_reg_operand (index, Pmode))
+       return true;
+
+      if (!TARGET_DISABLE_INDEXING
+         && GET_CODE (index) == MULT
+         && MODE_OK_FOR_SCALED_INDEXING_P (mode)
+         && REG_P (XEXP (index, 0))
+         && GET_MODE (XEXP (index, 0)) == Pmode
+         && (strict ? STRICT_REG_OK_FOR_INDEX_P (XEXP (index, 0))
+                    : REG_OK_FOR_INDEX_P (XEXP (index, 0)))
+         && GET_CODE (XEXP (index, 1)) == CONST_INT
+         && INTVAL (XEXP (index, 1))
+            == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
+         && borx_reg_operand (base, Pmode))
+       return true;
+
+      return false;
+    }
+
+  if (GET_CODE (x) == LO_SUM)
+    {
+      rtx y = XEXP (x, 0);
+
+      if (GET_CODE (y) == SUBREG)
+       y = SUBREG_REG (y);
+
+      if (REG_P (y)
+         && (strict ? STRICT_REG_OK_FOR_BASE_P (y)
+                    : REG_OK_FOR_BASE_P (y)))
+       {
+         /* Needed for -fPIC */
+         if (mode == Pmode
+             && GET_CODE (XEXP (x, 1)) == UNSPEC)
+           return true;
+
+         if (!INT14_OK_STRICT
+             && (GET_MODE_CLASS (mode) == MODE_FLOAT
+                 || (reload_in_progress
+                     && strict
+                     && (mode == SImode || mode == DImode))))
+          return false;
+
+         if (CONSTANT_P (XEXP (x, 1)))
+           return true;
+       }
+      return false;
+    }
+
+  if (GET_CODE (x) == CONST_INT && INT_5_BITS (x))
+    return true;
+
+  return false;
+}
+
+/* Look for machine dependent ways to make the invalid address AD a
+   valid address.
+
+   For the PA, transform:
+
+        memory(X + <large int>)
+
+   into:
+
+        if (<large int> & mask) >= 16
+          Y = (<large int> & ~mask) + mask + 1  Round up.
+        else
+          Y = (<large int> & ~mask)             Round down.
+        Z = X + Y
+        memory (Z + (<large int> - Y));
+
+   This makes reload inheritance and reload_cse work better since Z
+   can be reused.
+
+   There may be more opportunities to improve code with this hook.  */
+
+rtx
+pa_legitimize_reload_address (rtx ad, enum machine_mode mode,
+                             int opnum, int type,
+                             int ind_levels ATTRIBUTE_UNUSED)
+{
+  long offset, newoffset, mask;
+  rtx new_rtx, temp = NULL_RTX;
+
+  mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
+         && !INT14_OK_STRICT ? 0x1f : 0x3fff);
+
+  if (optimize && GET_CODE (ad) == PLUS)
+    temp = simplify_binary_operation (PLUS, Pmode,
+                                     XEXP (ad, 0), XEXP (ad, 1));
+
+  new_rtx = temp ? temp : ad;
+
+  if (optimize
+      && GET_CODE (new_rtx) == PLUS
+      && GET_CODE (XEXP (new_rtx, 0)) == REG
+      && GET_CODE (XEXP (new_rtx, 1)) == CONST_INT)
+    {
+      offset = INTVAL (XEXP ((new_rtx), 1));
+
+      /* Choose rounding direction.  Round up if we are >= halfway.  */
+      if ((offset & mask) >= ((mask + 1) / 2))
+       newoffset = (offset & ~mask) + mask + 1;
+      else
+       newoffset = offset & ~mask;
+
+      /* Ensure that long displacements are aligned.  */
+      if (mask == 0x3fff
+         && (GET_MODE_CLASS (mode) == MODE_FLOAT
+             || (TARGET_64BIT && (mode) == DImode)))
+       newoffset &= ~(GET_MODE_SIZE (mode) - 1);
+
+      if (newoffset != 0 && VAL_14_BITS_P (newoffset))
+       {
+         temp = gen_rtx_PLUS (Pmode, XEXP (new_rtx, 0),
+                              GEN_INT (newoffset));
+         ad = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - newoffset));
+         push_reload (XEXP (ad, 0), 0, &XEXP (ad, 0), 0,
+                      BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+                      opnum, (enum reload_type) type);
+         return ad;
+       }
+    }
+
+  return NULL_RTX;
+}
+
 #include "gt-pa.h"
index 216f7372c9daf1b50facbf80e52dfdb3751515e1..620768fb04d5b37eba209e43b601f0c4881354f8 100644 (file)
@@ -846,9 +846,9 @@ extern int may_call_alloca;
 /* Nonzero if 14-bit offsets can be used for all loads and stores.
    This is not possible when generating PA 1.x code as floating point
    loads and stores only support 5-bit offsets.  Note that we do not
-   forbid the use of 14-bit offsets in GO_IF_LEGITIMATE_ADDRESS.
-   Instead, we use pa_secondary_reload() to reload integer mode
-   REG+D memory addresses used in floating point loads and stores.
+   forbid the use of 14-bit offsets for integer modes.  Instead, we
+   use secondary reloads to fix REG+D memory addresses for integer
+   mode floating-point loads and stores.
 
    FIXME: the ELF32 linker clobbers the LSB of the FP register number
    in PA 2.0 floating-point insns with long displacements.  This is
@@ -866,7 +866,6 @@ extern int may_call_alloca;
    We have two alternate definitions for each of them.
    The usual definition accepts all pseudo regs; the other rejects
    them unless they have been allocated suitable hard regs.
-   The symbol REG_OK_STRICT causes the latter definition to be used.
 
    Most source files want to accept pseudo regs in the hope that
    they will get allocated to the class that the insn wants them to be in.
@@ -874,8 +873,6 @@ extern int may_call_alloca;
    After reload, it makes no difference, since pseudo regs have
    been eliminated by then.  */
 
-#ifndef REG_OK_STRICT
-
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
@@ -890,63 +887,11 @@ extern int may_call_alloca;
    || REGNO (X) == FRAME_POINTER_REGNUM                                \
    || REGNO (X) >= FIRST_PSEUDO_REGISTER))
 
-#else
-
 /* Nonzero if X is a hard reg that can be used as an index.  */
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+#define STRICT_REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
 
 /* Nonzero if X is a hard reg that can be used as a base reg.  */
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#endif
-\f
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a
-   valid memory address for an instruction.  The MODE argument is the
-   machine mode for the MEM expression that wants to use this address.
-
-   On HP PA-RISC, the legitimate address forms are REG+SMALLINT,
-   REG+REG, and REG+(REG*SCALE).  The indexed address forms are only
-   available with floating point loads and stores, and integer loads.
-   We get better code by allowing indexed addresses in the initial
-   RTL generation.
-
-   The acceptance of indexed addresses as legitimate implies that we
-   must provide patterns for doing indexed integer stores, or the move
-   expanders must force the address of an indexed store to a register.
-   We have adopted the latter approach.
-   
-   Another function of GO_IF_LEGITIMATE_ADDRESS is to ensure that
-   the base register is a valid pointer for indexed instructions.
-   On targets that have non-equivalent space registers, we have to
-   know at the time of assembler output which register in a REG+REG
-   pair is the base register.  The REG_POINTER flag is sometimes lost
-   in reload and the following passes, so it can't be relied on during
-   code generation.  Thus, we either have to canonicalize the order
-   of the registers in REG+REG indexed addresses, or treat REG+REG
-   addresses separately and provide patterns for both permutations.
-
-   The latter approach requires several hundred additional lines of
-   code in pa.md.  The downside to canonicalizing is that a PLUS
-   in the wrong order can't combine to form to make a scaled indexed
-   memory operand.  As we won't need to canonicalize the operands if
-   the REG_POINTER lossage can be fixed, it seems better canonicalize.
-
-   We initially break out scaled indexed addresses in canonical order
-   in pa_emit_move_sequence.  LEGITIMIZE_ADDRESS also canonicalizes
-   scaled indexed addresses during RTL generation.  However, fold_rtx
-   has its own opinion on how the operands of a PLUS should be ordered.
-   If one of the operands is equivalent to a constant, it will make
-   that operand the second operand.  As the base register is likely to
-   be equivalent to a SYMBOL_REF, we have made it the second operand.
-
-   GO_IF_LEGITIMATE_ADDRESS accepts REG+REG as legitimate when the
-   operands are in the order INDEX+BASE on targets with non-equivalent
-   space registers, and in any order on targets with equivalent space
-   registers.  It accepts both MULT+BASE and BASE+MULT for scaled indexing.
-
-   We treat a SYMBOL_REF as legitimate if it is part of the current
-   function's constant-pool, because such addresses can actually be
-   output as REG+SMALLINT.  */
+#define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
 #define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20)
 #define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X))
@@ -989,180 +934,20 @@ extern int may_call_alloca;
    || (MODE) == SFmode                                                 \
    || (MODE) == DFmode)
 
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{                                                                      \
-  if ((REG_P (X) && REG_OK_FOR_BASE_P (X))                             \
-      || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_DEC         \
-          || GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_INC)      \
-         && REG_P (XEXP (X, 0))                                        \
-         && REG_OK_FOR_BASE_P (XEXP (X, 0))))                          \
-    goto ADDR;                                                         \
-  else if (GET_CODE (X) == PLUS)                                       \
-    {                                                                  \
-      rtx base = 0, index = 0;                                         \
-      if (REG_P (XEXP (X, 1))                                          \
-         && REG_OK_FOR_BASE_P (XEXP (X, 1)))                           \
-       base = XEXP (X, 1), index = XEXP (X, 0);                        \
-      else if (REG_P (XEXP (X, 0))                                     \
-              && REG_OK_FOR_BASE_P (XEXP (X, 0)))                      \
-       base = XEXP (X, 0), index = XEXP (X, 1);                        \
-      if (base                                                         \
-         && GET_CODE (index) == CONST_INT                              \
-         && ((INT_14_BITS (index)                                      \
-              && (((MODE) != DImode                                    \
-                   && (MODE) != SFmode                                 \
-                   && (MODE) != DFmode)                                \
-                  /* The base register for DImode loads and stores     \
-                     with long displacements must be aligned because   \
-                     the lower three bits in the displacement are      \
-                     assumed to be zero.  */                           \
-                  || ((MODE) == DImode                                 \
-                      && (!TARGET_64BIT                                \
-                          || (INTVAL (index) % 8) == 0))               \
-                  /* Similarly, the base register for SFmode/DFmode    \
-                     loads and stores with long displacements must     \
-                     be aligned.  */                                   \
-                  || (((MODE) == SFmode || (MODE) == DFmode)           \
-                      && INT14_OK_STRICT                               \
-                      && (INTVAL (index) % GET_MODE_SIZE (MODE)) == 0))) \
-              || INT_5_BITS (index)))                                  \
-       goto ADDR;                                                      \
-      if (!TARGET_DISABLE_INDEXING                                     \
-         /* Only accept the "canonical" INDEX+BASE operand order       \
-            on targets with non-equivalent space registers.  */        \
-         && (TARGET_NO_SPACE_REGS                                      \
-             ? (base && REG_P (index))                                 \
-             : (base == XEXP (X, 1) && REG_P (index)                   \
-                && (reload_completed                                   \
-                    || (reload_in_progress && HARD_REGISTER_P (base))  \
-                    || REG_POINTER (base))                             \
-                && (reload_completed                                   \
-                    || (reload_in_progress && HARD_REGISTER_P (index)) \
-                    || !REG_POINTER (index))))                         \
-         && MODE_OK_FOR_UNSCALED_INDEXING_P (MODE)                     \
-         && REG_OK_FOR_INDEX_P (index)                                 \
-         && borx_reg_operand (base, Pmode)                             \
-         && borx_reg_operand (index, Pmode))                           \
-       goto ADDR;                                                      \
-      if (!TARGET_DISABLE_INDEXING                                     \
-         && base                                                       \
-         && GET_CODE (index) == MULT                                   \
-         && MODE_OK_FOR_SCALED_INDEXING_P (MODE)                       \
-         && REG_P (XEXP (index, 0))                                    \
-         && GET_MODE (XEXP (index, 0)) == Pmode                        \
-         && REG_OK_FOR_INDEX_P (XEXP (index, 0))                       \
-         && GET_CODE (XEXP (index, 1)) == CONST_INT                    \
-         && INTVAL (XEXP (index, 1))                                   \
-            == (HOST_WIDE_INT) GET_MODE_SIZE (MODE)                    \
-         && borx_reg_operand (base, Pmode))                            \
-       goto ADDR;                                                      \
-    }                                                                  \
-  else if (GET_CODE (X) == LO_SUM                                      \
-          && GET_CODE (XEXP (X, 0)) == REG                             \
-          && REG_OK_FOR_BASE_P (XEXP (X, 0))                           \
-          && CONSTANT_P (XEXP (X, 1))                                  \
-          && (TARGET_SOFT_FLOAT                                        \
-              /* We can allow symbolic LO_SUM addresses for PA2.0.  */ \
-              || (TARGET_PA_20                                         \
-                  && !TARGET_ELF32                                     \
-                  && GET_CODE (XEXP (X, 1)) != CONST_INT)              \
-              || ((MODE) != SFmode                                     \
-                  && (MODE) != DFmode)))                               \
-    goto ADDR;                                                         \
-  else if (GET_CODE (X) == LO_SUM                                      \
-          && GET_CODE (XEXP (X, 0)) == SUBREG                          \
-          && GET_CODE (SUBREG_REG (XEXP (X, 0))) == REG                \
-          && REG_OK_FOR_BASE_P (SUBREG_REG (XEXP (X, 0)))              \
-          && CONSTANT_P (XEXP (X, 1))                                  \
-          && (TARGET_SOFT_FLOAT                                        \
-              /* We can allow symbolic LO_SUM addresses for PA2.0.  */ \
-              || (TARGET_PA_20                                         \
-                  && !TARGET_ELF32                                     \
-                  && GET_CODE (XEXP (X, 1)) != CONST_INT)              \
-              || ((MODE) != SFmode                                     \
-                  && (MODE) != DFmode)))                               \
-    goto ADDR;                                                         \
-  else if (GET_CODE (X) == CONST_INT && INT_5_BITS (X))                        \
-    goto ADDR;                                                         \
-  /* Needed for -fPIC */                                               \
-  else if (GET_CODE (X) == LO_SUM                                      \
-          && GET_CODE (XEXP (X, 0)) == REG                             \
-          && REG_OK_FOR_BASE_P (XEXP (X, 0))                           \
-          && GET_CODE (XEXP (X, 1)) == UNSPEC                          \
-          && (TARGET_SOFT_FLOAT                                        \
-              || (TARGET_PA_20 && !TARGET_ELF32)                       \
-              || ((MODE) != SFmode                                     \
-                  && (MODE) != DFmode)))                               \
-    goto ADDR;                                                         \
-}
-
-/* Look for machine dependent ways to make the invalid address AD a
-   valid address.
-
-   For the PA, transform:
-
-        memory(X + <large int>)
-
-   into:
-
-        if (<large int> & mask) >= 16
-          Y = (<large int> & ~mask) + mask + 1  Round up.
-        else
-          Y = (<large int> & ~mask)             Round down.
-        Z = X + Y
-        memory (Z + (<large int> - Y));
-
-   This makes reload inheritance and reload_cse work better since Z
-   can be reused.
-
-   There may be more opportunities to improve code with this hook.  */
-#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN)     \
-do {                                                                   \
-  long offset, newoffset, mask;                                                \
-  rtx new_rtx, temp = NULL_RTX;                                                \
-                                                                       \
-  mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT                          \
-         ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff);                \
-                                                                       \
-  if (optimize && GET_CODE (AD) == PLUS)                               \
-    temp = simplify_binary_operation (PLUS, Pmode,                     \
-                                     XEXP (AD, 0), XEXP (AD, 1));      \
-                                                                       \
-  new_rtx = temp ? temp : AD;                                          \
-                                                                       \
-  if (optimize                                                         \
-      && GET_CODE (new_rtx) == PLUS                                            \
-      && GET_CODE (XEXP (new_rtx, 0)) == REG                           \
-      && GET_CODE (XEXP (new_rtx, 1)) == CONST_INT)                            \
-    {                                                                  \
-      offset = INTVAL (XEXP ((new_rtx), 1));                           \
-                                                                       \
-      /* Choose rounding direction.  Round up if we are >= halfway.  */        \
-      if ((offset & mask) >= ((mask + 1) / 2))                         \
-       newoffset = (offset & ~mask) + mask + 1;                        \
-      else                                                             \
-       newoffset = offset & ~mask;                                     \
-                                                                       \
-      /* Ensure that long displacements are aligned.  */               \
-      if (mask == 0x3fff                                               \
-         && (GET_MODE_CLASS (MODE) == MODE_FLOAT                       \
-             || (TARGET_64BIT && (MODE) == DImode)))                   \
-       newoffset &= ~(GET_MODE_SIZE (MODE) - 1);                       \
-                                                                       \
-      if (newoffset != 0 && VAL_14_BITS_P (newoffset))                 \
-       {                                                               \
-         temp = gen_rtx_PLUS (Pmode, XEXP (new_rtx, 0),                        \
-                              GEN_INT (newoffset));                    \
-         AD = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - newoffset));\
-         push_reload (XEXP (AD, 0), 0, &XEXP (AD, 0), 0,               \
-                      BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,           \
-                      (OPNUM), (TYPE));                                \
-         goto WIN;                                                     \
-       }                                                               \
-    }                                                                  \
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.  */
+
+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND_L, WIN)        \
+do {                                                                        \
+  rtx new_ad = pa_legitimize_reload_address (AD, MODE, OPNUM, TYPE, IND_L);  \
+  if (new_ad)                                                               \
+    {                                                                       \
+      AD = new_ad;                                                          \
+      goto WIN;                                                                     \
+    }                                                                       \
 } while (0)
 
-
 \f
 #define TARGET_ASM_SELECT_SECTION  pa_select_section
 
index de2eb3aa8d132744b7c8d4953cb3cf53491ac653..d5696e908e080e0a876519e36a2c6a6dd416459b 100644 (file)
 \f
 ;; Floating point move insns
 
-;; This pattern forces (set (reg:DF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movdf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=?r,f")
-       (match_operand:DF 1 "" "?F,m"))]
-  "GET_CODE (operands[1]) == CONST_DOUBLE
-   && operands[1] != CONST0_RTX (DFmode)
-   && !TARGET_64BIT
-   && !TARGET_SOFT_FLOAT"
-  "* return (which_alternative == 0 ? pa_output_move_double (operands)
-                                   : \"fldd%F1 %1,%0\");"
-  [(set_attr "type" "move,fpload")
-   (set_attr "length" "16,4")])
-
 (define_expand "movdf"
   [(set (match_operand:DF 0 "general_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
   ""
   "
 {
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-      && operands[1] != CONST0_RTX (DFmode))
-    {
-      /* Reject CONST_DOUBLE loads to all hard registers when
-        generating 64-bit code and to floating point registers
-        when generating 32-bit code.  */
-      if (REG_P (operands[0])
-         && HARD_REGISTER_P (operands[0])
-         && (TARGET_64BIT || REGNO (operands[0]) >= 32))
-       FAIL;
-
-      if (TARGET_64BIT)
-       operands[1] = force_const_mem (DFmode, operands[1]);
-    }
-
   if (pa_emit_move_sequence (operands, DFmode, 0))
     DONE;
 }")
 
+;; Handle DFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_indf_r1"
+  [(set (match_operand:DF 0 "register_operand" "=Z")
+       (match_operand:DF 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (pa_emit_move_sequence (operands, DFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+
 ;; Handle DFmode input reloads requiring a general register as a
 ;; scratch register.
 (define_expand "reload_indf"
 
 (define_insn ""
   [(set (match_operand:DF 0 "move_dest_operand"
-                         "=f,*r,Q,?o,?Q,f,*r,*r,?*r,?f")
+                         "=f,*r,T,?o,?Q,f,*r,*r,?*r,?f")
        (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,*rG,f,*r,*r,RQ,o,RQ,f,*r"))]
+                         "fG,*rG,f,*r,*r,RT,o,RQ,f,*r"))]
   "(register_operand (operands[0], DFmode)
     || reg_or_0_operand (operands[1], DFmode))
    && !(GET_CODE (operands[1]) == CONST_DOUBLE
   ""
   "
 {
-  /* Except for zero, we don't support loading a CONST_INT directly
-     to a hard floating-point register since a scratch register is
-     needed for the operation.  While the operation could be handled
-     before register allocation, the simplest solution is to fail.  */
-  if (TARGET_64BIT
-      && GET_CODE (operands[1]) == CONST_INT
-      && operands[1] != CONST0_RTX (DImode)
-      && REG_P (operands[0])
-      && HARD_REGISTER_P (operands[0])
-      && REGNO (operands[0]) >= 32)
-    FAIL;
-
   if (pa_emit_move_sequence (operands, DImode, 0))
     DONE;
 }")
 (define_insn ""
   [(set (match_operand:DI 0 "move_dest_operand"
                          "=r,o,Q,r,r,r,*f,*f,T,?r,?*f")
-       (match_operand:DI 1 "general_operand"
+       (match_operand:DI 1 "move_src_operand"
                          "rM,r,r,o*R,Q,i,*fM,RT,*f,*f,r"))]
   "(register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))
   [(set_attr "type" "move,move")
    (set_attr "length" "4,8")])
 
-;; This pattern forces (set (reg:SF ...) (const_double ...))
-;; to be reloaded by putting the constant into memory when
-;; reg is a floating point register.
-;;
-;; For integer registers we use ldil;ldo to set the appropriate
-;; value.
-;;
-;; This must come before the movsf pattern, and it must be present
-;; to handle obscure reloading cases.
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=?r,f")
-       (match_operand:SF 1 "" "?F,m"))]
-  "GET_CODE (operands[1]) == CONST_DOUBLE
-   && operands[1] != CONST0_RTX (SFmode)
-   && ! TARGET_SOFT_FLOAT"
-  "* return (which_alternative == 0 ? pa_singlemove_string (operands)
-                                   : \" fldw%F1 %1,%0\");"
-  [(set_attr "type" "move,fpload")
-   (set_attr "length" "8,4")])
-
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_operand" "")
        (match_operand:SF 1 "general_operand" ""))]
   ""
   "
 {
-  /* Reject CONST_DOUBLE loads to floating point registers.  */
-  if (GET_CODE (operands[1]) == CONST_DOUBLE
-      && operands[1] != CONST0_RTX (SFmode)
-      && REG_P (operands[0])
-      && HARD_REGISTER_P (operands[0])
-      && REGNO (operands[0]) >= 32)
-    FAIL;
-
   if (pa_emit_move_sequence (operands, SFmode, 0))
     DONE;
 }")
 
+;; Handle SFmode input reloads requiring %r1 as a scratch register.
+(define_expand "reload_insf_r1"
+  [(set (match_operand:SF 0 "register_operand" "=Z")
+       (match_operand:SF 1 "non_hard_reg_operand" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=&a"))]
+  ""
+  "
+{
+  if (pa_emit_move_sequence (operands, SFmode, operands[2]))
+    DONE;
+
+  /* We don't want the clobber emitted, so handle this ourselves.  */
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+
 ;; Handle SFmode input reloads requiring a general register as a
 ;; scratch register.
 (define_expand "reload_insf"
 
 (define_insn ""
   [(set (match_operand:SF 0 "move_dest_operand"
-                         "=f,!*r,f,*r,Q,Q,?*r,?f")
+                         "=f,!*r,f,*r,T,Q,?*r,?f")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,!*rG,RQ,RQ,f,*rG,f,*r"))]
+                         "fG,!*rG,RT,RQ,f,*rG,f,*r"))]
   "(register_operand (operands[0], SFmode)
     || reg_or_0_operand (operands[1], SFmode))
    && !TARGET_SOFT_FLOAT
 
 (define_insn ""
   [(set (match_operand:SF 0 "move_dest_operand"
-                         "=f,!*r,f,*r,Q,Q")
+                         "=f,!*r,f,*r,T,Q")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,!*rG,RQ,RQ,f,*rG"))]
+                         "fG,!*rG,RT,RQ,f,*rG"))]
   "(register_operand (operands[0], SFmode)
     || reg_or_0_operand (operands[1], SFmode))
    && !TARGET_SOFT_FLOAT
 }")
 
 (define_insn "umulsidi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
+  [(set (match_operand:DI 0 "register_operand" "=f")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
                 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT"
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
+  [(set (match_operand:DI 0 "register_operand" "=f")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
                 (match_operand:DI 2 "uint32_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && !TARGET_64BIT"
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=f")
+  [(set (match_operand:DI 0 "register_operand" "=f")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
                 (match_operand:DI 2 "uint32_operand" "f")))]
   "TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
index d59530cbe3d3543dc0c7a9d66369999d9551beb3..8823706026b70e51adc95bf0b1fee3cfc3b9adea 100644 (file)
   return IS_INDEX_ADDR_P (op) && memory_address_p (mode, op);
 })
 
+;; True iff OP is a register plus base memory operand.
+
+(define_predicate "reg_plus_base_memory_operand"
+  (match_code "subreg,mem")
+{
+  if (GET_MODE (op) != mode)
+    return false;
+
+  /* Before reload, a (SUBREG (MEM...)) forces reloading into a register.  */
+  if (reload_completed && GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (! MEM_P (op))
+    return false;
+
+  op = XEXP (op, 0);
+  if (GET_CODE (op) != PLUS)
+    return false;
+
+  if (REG_P (XEXP (op, 0)) && REG_OK_FOR_BASE_P (XEXP (op, 0)))
+    return GET_CODE (XEXP (op, 1)) == CONST_INT;
+
+  return false;
+})
+
+;; True iff OP is a base14 operand.
+
+(define_predicate "base14_operand"
+  (match_code "const_int")
+{
+  if (!INT_14_BITS (op))
+    return false;
+
+  /* Although this may not be necessary, we require that the
+     base value is correctly aligned for its mode as this is
+     assumed in the instruction encoding.  */
+  switch (mode)
+    {
+    case QImode:
+    case HImode:
+      return true;
+
+    case SImode:
+    case SFmode:
+    case SCmode:
+      return (INTVAL (op) % 4) == 0;
+
+    case DImode:
+    case DFmode:
+    case DCmode:
+      return (INTVAL (op) % 8) == 0;
+
+    default:
+      break;
+    }
+
+  return false;
+})
+
 ;; True iff the operand OP can be used as the destination operand of
 ;; an integer store.  This also implies the operand could be used as
-;; the source operand of an integer load.  Symbolic, lo_sum and indexed
+;; the source operand of an integer load.  LO_SUM DLT and indexed
 ;; memory operands are not allowed.  We accept reloading pseudos and
 ;; other memory operands.
 
 (define_predicate "integer_store_memory_operand"
   (match_code "reg,mem")
 {
-  return ((reload_in_progress
-           && REG_P (op)
-           && REGNO (op) >= FIRST_PSEUDO_REGISTER
-           && reg_renumber [REGNO (op)] < 0)
-          || (MEM_P (op)
-              && (reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
-              && !symbolic_memory_operand (op, VOIDmode)
-              && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
-              && !IS_INDEX_ADDR_P (XEXP (op, 0))));
+  if (reload_in_progress
+      && REG_P (op)
+      && REGNO (op) >= FIRST_PSEUDO_REGISTER
+      && reg_renumber [REGNO (op)] < 0)
+    return true;
+
+  if (reg_plus_base_memory_operand (op, mode))
+    {
+      /* Extract CONST_INT operand.  */
+      if (GET_CODE (op) == SUBREG)
+       op = SUBREG_REG (op);
+      op = XEXP (op, 0);
+      op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
+      return base14_operand (op, mode) || INT_5_BITS (op);
+    }
+
+  if (!MEM_P (op))
+    return false;
+
+  return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
+         && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
+         && !IS_INDEX_ADDR_P (XEXP (op, 0)));
+})
+
+;; True iff the operand OP can be used as the destination operand of
+;; a floating point store.  This also implies the operand could be used as
+;; the source operand of a floating point load.  LO_SUM DLT and indexed
+;; memory operands are not allowed.  Symbolic operands are accepted if
+;; INT14_OK_STRICT is true.  We accept reloading pseudos and other memory
+;; operands.
+
+(define_predicate "floating_point_store_memory_operand"
+  (match_code "reg,mem")
+{
+  if (reload_in_progress
+      && REG_P (op)
+      && REGNO (op) >= FIRST_PSEUDO_REGISTER
+      && reg_renumber [REGNO (op)] < 0)
+    return true;
+
+  if (reg_plus_base_memory_operand (op, mode))
+    {
+      /* Extract CONST_INT operand.  */
+      if (GET_CODE (op) == SUBREG)
+       op = SUBREG_REG (op);
+      op = XEXP (op, 0);
+      op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
+      return ((TARGET_PA_20
+              && !TARGET_ELF32
+              && base14_operand (op, mode))
+             || INT_5_BITS (op));
+    }
+
+  if (!MEM_P (op))
+    return false;
+
+  return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
+         && (INT14_OK_STRICT || !symbolic_memory_operand (op, VOIDmode))
+         && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
+         && !IS_INDEX_ADDR_P (XEXP (op, 0)));
 })
 
 ;; Return true iff OP is an integer register.
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
 
-  if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode))
+  if (! MEM_P (op))
     return false;
 
   op = XEXP (op, 0);
     op = SUBREG_REG (op);
   if (!MEM_P (op))
     return false;
-  return pa_symbolic_expression_p (XEXP (op, 0));
+  op = XEXP (op, 0);
+  if (GET_CODE (op) == LO_SUM)
+    op = XEXP (op, 1);
+  return pa_symbolic_expression_p (op);
 })
 
 ;; True iff OP is a symbolic operand.
                  || GET_CODE (XEXP (op, 0)) == LABEL_REF)
              && GET_CODE (XEXP (op, 1)) == CONST_INT);
     default:
-      gcc_unreachable ();
+      break;
     }
-  return true;
+  return false;
 })
 
 ;; Return true if OP is a symbolic operand for the TLS Global Dynamic model.