Patchwork [committed] Delete GO_IF_LEGITIMATE_ADDRESS on PA target

login
register
mail settings
Submitter John David Anglin
Date Feb. 3, 2013, 8:28 p.m.
Message ID <BLU0-SMTP77149B3E6427022D03FA2997020@phx.gbl>
Download mbox | patch
Permalink /patch/217802/
State New
Headers show

Comments

John David Anglin - Feb. 3, 2013, 8:28 p.m.
On 3-Feb-13, at 3:25 PM, John David Anglin wrote:

> Committed to trunk.

Oops, forgot to attach change.

Dave
--
John David Anglin	dave.anglin@bell.net
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.

Patch

Index: config/pa/constraints.md
===================================================================
--- config/pa/constraints.md	(revision 195696)
+++ config/pa/constraints.md	(working copy)
@@ -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"
@@ -124,12 +124,7 @@ 
 
 (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: config/pa/predicates.md
===================================================================
--- config/pa/predicates.md	(revision 195696)
+++ config/pa/predicates.md	(working copy)
@@ -234,26 +234,136 @@ 
   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.
 
 (define_predicate "ireg_operand"
@@ -302,7 +412,7 @@ 
   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);
@@ -484,7 +594,10 @@ 
     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.
@@ -507,9 +620,9 @@ 
 		  || 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.
Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 195696)
+++ config/pa/pa.md	(working copy)
@@ -3772,52 +3772,32 @@ 
 
 ;; 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"
@@ -3854,9 +3834,9 @@ 
 
 (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
@@ -4071,18 +4051,6 @@ 
   ""
   "
 {
-  /* 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;
 }")
@@ -4190,7 +4158,7 @@ 
 (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))
@@ -4355,44 +4323,32 @@ 
   [(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"
@@ -4429,9 +4385,9 @@ 
 
 (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
@@ -4451,9 +4407,9 @@ 
 
 (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
@@ -5408,7 +5364,7 @@ 
 }")
 
 (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"
@@ -5417,7 +5373,7 @@ 
    (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"
@@ -5426,7 +5382,7 @@ 
    (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: config/pa/pa-protos.h
===================================================================
--- config/pa/pa-protos.h	(revision 195696)
+++ config/pa/pa-protos.h	(working copy)
@@ -67,6 +67,8 @@ 
 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: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 195696)
+++ config/pa/pa.c	(working copy)
@@ -187,6 +187,7 @@ 
 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 @@ 
 #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;
 
@@ -685,7 +688,7 @@ 
   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 @@ 
       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 @@ 
    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 @@ 
      (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 @@ 
 
       /* 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 @@ 
     }
   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 @@ 
 
       /* 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 @@ 
       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 @@ 
 		   && 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 @@ 
   fputc ('\n', asm_out_file);
 }
 
-/* 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 @@ 
     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 @@ 
 
       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 @@ 
   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 @@ 
 	      || 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 @@ 
   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: config/pa/pa.h
===================================================================
--- config/pa/pa.h	(revision 195696)
+++ config/pa/pa.h	(working copy)
@@ -846,9 +846,9 @@ 
 /* 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 @@ 
    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 @@ 
    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,64 +887,12 @@ 
    || 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))
+#define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
-#endif
-
-/* 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 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 @@ 
    || (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;								\
-}
+/* 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.  */
 
-/* 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;							\
-	}								\
-    }									\
+#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)
 
-
 
 #define TARGET_ASM_SELECT_SECTION  pa_select_section