OSDN Git Service

PR target/13054
authordanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Dec 2003 07:26:19 +0000 (07:26 +0000)
committerdanglin <danglin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Dec 2003 07:26:19 +0000 (07:26 +0000)
* pa-protos.h (indexed_memory_operand, borx_reg_operand,
move_dest_operand, move_src_operand): New protypes.
(basereg_operand, move_operand, reg_or_nonsymb_mem_operand): Deleted.
* pa.c (copy_reg_pointer, indexed_memory_operand, move_dest_operand,
move_src_operand): New functions.
(basereg_operand, reg_or_nonsymb_mem_operand, move_operand): Delete.
(reg_or_0_or_nonsymb_mem_operand): Return false for unscaled indexed
address until cse is not expected on targets with non-equivalent
space registers.
(hppa_legitimize_address): Canonicalize unscaled indexed addresses
on targets non-equivalent space registers.
(emit_move_sequence): Break out indexed addresses from destination
operand.  Similarly, break out unscaled indexed addresses from
source operand on targets with non-equivalent space registers.  Fix
REG_POINTER flag when possible.  Mark register pointer when creating
new pointers.
(print_operand): Handle unscaled index addresses.
* pa.h (IS_INDEX_ADDR_P, IS_LO_SUM_DLT_ADDR_P): New macro subroutines
for EXTRA_CONSTRAINT.
(EXTRA_CONSTRAINT): Rework to make more readable.
(MODE_OK_FOR_SCALED_INDEXING_P, MODE_OK_FOR_UNSCALED_INDEXING_P): New
subroutines for GO_IF_LEGITIMATE_ADDRESS.
(GO_IF_LEGITIMATE_ADDRESS): Rework using new subroutines.  Allow scaled
and unscaled addresses.  Canonicalize unscaled indexed addresses on
targets with non-equivalent space registers.  Document issues in
handling indexed address modes on PA-RISC.
(PREDICATE_CODES): Update for new and deleted predicates.
* pa.md (move_dest_operand, move_src_operand, indexed_memory_operand):
Use new predicates in move patterns.
Add peephole2 patterns to optimize floating point stores.  Fix
constrain preferencing in move patterns.  Delete patterns for handling
unscaled indexed memory loads.  Add missing load and store with
base-register modification patterns.  Correct SFmode floating point
store pattern.  Add missing zero extension loads.

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

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

index 34234a8..f43d14b 100644 (file)
@@ -1,3 +1,41 @@
+2003-12-14  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       PR target/13054
+       * pa-protos.h (indexed_memory_operand, borx_reg_operand,
+       move_dest_operand, move_src_operand): New protypes.
+       (basereg_operand, move_operand, reg_or_nonsymb_mem_operand): Deleted.
+       * pa.c (copy_reg_pointer, indexed_memory_operand, move_dest_operand,
+       move_src_operand): New functions.
+       (basereg_operand, reg_or_nonsymb_mem_operand, move_operand): Delete.
+       (reg_or_0_or_nonsymb_mem_operand): Return false for unscaled indexed
+       address until cse is not expected on targets with non-equivalent
+       space registers.
+       (hppa_legitimize_address): Canonicalize unscaled indexed addresses
+       on targets non-equivalent space registers.
+       (emit_move_sequence): Break out indexed addresses from destination
+       operand.  Similarly, break out unscaled indexed addresses from
+       source operand on targets with non-equivalent space registers.  Fix
+       REG_POINTER flag when possible.  Mark register pointer when creating
+       new pointers.
+       (print_operand): Handle unscaled index addresses.
+       * pa.h (IS_INDEX_ADDR_P, IS_LO_SUM_DLT_ADDR_P): New macro subroutines
+       for EXTRA_CONSTRAINT.
+       (EXTRA_CONSTRAINT): Rework to make more readable.
+       (MODE_OK_FOR_SCALED_INDEXING_P, MODE_OK_FOR_UNSCALED_INDEXING_P): New
+       subroutines for GO_IF_LEGITIMATE_ADDRESS.
+       (GO_IF_LEGITIMATE_ADDRESS): Rework using new subroutines.  Allow scaled
+       and unscaled addresses.  Canonicalize unscaled indexed addresses on
+       targets with non-equivalent space registers.  Document issues in
+       handling indexed address modes on PA-RISC.
+       (PREDICATE_CODES): Update for new and deleted predicates.
+       * pa.md (move_dest_operand, move_src_operand, indexed_memory_operand):
+       Use new predicates in move patterns.
+       Add peephole2 patterns to optimize floating point stores.  Fix
+       constrain preferencing in move patterns.  Delete patterns for handling
+       unscaled indexed memory loads.  Add missing load and store with
+       base-register modification patterns.  Correct SFmode floating point
+       store pattern.  Add missing zero extension loads.
+
 2003-12-13  Steven Bosscher  <stevenb@suse.de>
 
        * ggc-zone.c (struct alloc_zone): Don't pre-declare, it already
index 4d5ce69..9bf5e97 100644 (file)
@@ -64,6 +64,7 @@ extern struct rtx_def *gen_cmp_fp (enum rtx_code, rtx, rtx);
 extern void hppa_encode_label (rtx);
 extern int arith11_operand (rtx, enum machine_mode);
 extern int adddi3_operand (rtx, enum machine_mode);
+extern int indexed_memory_operand (rtx, enum machine_mode);
 extern int symbolic_expression_p (rtx);
 extern int symbolic_memory_operand (rtx, enum machine_mode);
 extern int pa_adjust_insn_length (rtx, int);
@@ -73,16 +74,16 @@ extern int arith5_operand (rtx, enum machine_mode);
 extern int uint5_operand (rtx, enum machine_mode);
 extern int pic_label_operand (rtx, enum machine_mode);
 extern int plus_xor_ior_operator (rtx, enum machine_mode);
-extern int basereg_operand (rtx, enum machine_mode);
+extern int borx_reg_operand (rtx, enum machine_mode);
 extern int shadd_operand (rtx, enum machine_mode);
 extern int arith_operand (rtx, enum machine_mode);
 extern int read_only_operand (rtx, enum machine_mode);
-extern int move_operand (rtx, enum machine_mode);
+extern int move_dest_operand (rtx, enum machine_mode);
+extern int move_src_operand (rtx, enum machine_mode);
 extern int and_operand (rtx, enum machine_mode);
 extern int ior_operand (rtx, enum machine_mode);
 extern int arith32_operand (rtx, enum machine_mode);
 extern int uint32_operand (rtx, enum machine_mode);
-extern int reg_or_nonsymb_mem_operand (rtx, enum machine_mode);
 extern int reg_before_reload_operand (rtx, enum machine_mode);
 extern int reg_or_0_operand (rtx, enum machine_mode);
 extern int reg_or_0_or_nonsymb_mem_operand (rtx, enum machine_mode);
index f724c43..6cc3deb 100644 (file)
@@ -94,6 +94,7 @@ hppa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
 #endif
 #endif
 
+static void copy_reg_pointer (rtx, rtx);
 static int hppa_address_cost (rtx);
 static bool hppa_rtx_costs (rtx, int, int, int *);
 static inline rtx force_mode (enum machine_mode, rtx);
@@ -381,6 +382,16 @@ pa_init_builtins (void)
 #endif
 }
 
+/* If FROM is a probable pointer register, mark TO as a probable
+   pointer register with the same pointer alignment as FROM.  */
+
+static void
+copy_reg_pointer (rtx to, rtx from)
+{
+  if (REG_POINTER (from))
+    mark_reg_pointer (to, REGNO_POINTER_ALIGN (REGNO (from)));
+}
+
 /* Return nonzero only if OP is a register of mode MODE,
    or CONST0_RTX.  */
 int
@@ -448,21 +459,6 @@ symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
          || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
 }
 
-/* Return 1 if the operand is either a register or a memory operand that is
-   not symbolic.  */
-
-int
-reg_or_nonsymb_mem_operand (rtx op, enum machine_mode mode)
-{
-  if (register_operand (op, mode))
-    return 1;
-
-  if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
-    return 1;
-
-  return 0;
-}
-
 /* Return 1 if the operand is either a register, zero, or a memory operand
    that is not symbolic.  */
 
@@ -475,10 +471,24 @@ reg_or_0_or_nonsymb_mem_operand (rtx op, enum machine_mode mode)
   if (op == CONST0_RTX (mode))
     return 1;
 
-  if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
-    return 1;
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
 
-  return 0;
+  if (GET_CODE (op) != MEM)
+    return 0;
+
+  /* Until problems with management of the REG_POINTER flag are resolved,
+     we need to delay creating move insns with unscaled indexed addresses
+     until CSE is not expected.  */
+  if (!TARGET_NO_SPACE_REGS
+      && !cse_not_expected
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && REG_P (XEXP (XEXP (op, 0), 0))
+      && REG_P (XEXP (XEXP (op, 0), 1)))
+    return 0;
+
+  return (!symbolic_memory_operand (op, mode)
+         && memory_address_p (mode, XEXP (op, 0)));
 }
 
 /* Return 1 if the operand is a register operand or a non-symbolic memory
@@ -499,7 +509,7 @@ reg_before_reload_operand (rtx op, enum machine_mode mode)
 
   if (reload_completed
       && memory_operand (op, mode)
-      && ! symbolic_memory_operand (op, mode))
+      && !symbolic_memory_operand (op, mode))
     return 1;
 
   return 0;
@@ -516,10 +526,54 @@ cint_ok_for_move (HOST_WIDE_INT intval)
          || CONST_OK_FOR_LETTER_P (intval, 'K'));
 }
 
-/* Accept anything that can be moved in one instruction into a general
-   register.  */
+/* Return 1 iff OP is an indexed memory operand.  */
+int
+indexed_memory_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+
+  /* Before reload, a (SUBREG (MEM...)) forces reloading into a register.  */
+  if (reload_completed && GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode))
+    return 0;
+
+  op = XEXP (op, 0);
+
+  return (memory_address_p (mode, op) && IS_INDEX_ADDR_P (op));
+}
+
+/* Accept anything that can be used as a destination operand for a
+   move instruction.  We don't accept indexed memory operands since
+   they are supported only for floating point stores.  */
+int
+move_dest_operand (rtx op, enum machine_mode mode)
+{
+  if (register_operand (op, mode))
+    return 1;
+
+  if (GET_MODE (op) != mode)
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode))
+    return 0;
+
+  op = XEXP (op, 0);
+
+  return (memory_address_p (mode, op)
+         && !IS_INDEX_ADDR_P (op)
+         && !IS_LO_SUM_DLT_ADDR_P (op));
+}
+
+/* Accept anything that can be used as a source operand for a move
+   instruction.  */
 int
-move_operand (rtx op, enum machine_mode mode)
+move_src_operand (rtx op, enum machine_mode mode)
 {
   if (register_operand (op, mode))
     return 1;
@@ -530,41 +584,26 @@ move_operand (rtx op, enum machine_mode mode)
   if (GET_CODE (op) == CONST_INT)
     return cint_ok_for_move (INTVAL (op));
 
+  if (GET_MODE (op) != mode)
+    return 0;
+
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
+
   if (GET_CODE (op) != MEM)
     return 0;
 
-  op = XEXP (op, 0);
-
-  /* We consider a LO_SUM DLT reference a move_operand now since it has
-     been merged into the normal movsi/movdi patterns.  */
-  if (GET_CODE (op) == LO_SUM
-      && GET_CODE (XEXP (op, 0)) == REG
-      && REG_OK_FOR_BASE_P (XEXP (op, 0))
-      && GET_CODE (XEXP (op, 1)) == UNSPEC
-      && GET_MODE (op) == Pmode)
-    return 1;
-
-  /* Since move_operand is only used for source operands, we can always
-     allow scaled indexing!  */
-  if (! TARGET_DISABLE_INDEXING
-      && GET_CODE (op) == PLUS
-      && ((GET_CODE (XEXP (op, 0)) == MULT
-          && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
-          && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
-          && INTVAL (XEXP (XEXP (op, 0), 1))
-             == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
-          && GET_CODE (XEXP (op, 1)) == REG)
-         || (GET_CODE (XEXP (op, 1)) == MULT
-             &&GET_CODE (XEXP (XEXP (op, 1), 0)) == REG
-             && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT
-             && INTVAL (XEXP (XEXP (op, 1), 1))
-                == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
-             && GET_CODE (XEXP (op, 0)) == REG)))
-    return 1;
+  /* Until problems with management of the REG_POINTER flag are resolved,
+     we need to delay creating move insns with unscaled indexed addresses
+     until CSE is not expected.  */
+  if (!TARGET_NO_SPACE_REGS
+      && !cse_not_expected
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && REG_P (XEXP (XEXP (op, 0), 0))
+      && REG_P (XEXP (XEXP (op, 0), 1)))
+    return 0;
 
-  return memory_address_p (mode, op);
+  return memory_address_p (mode, XEXP (op, 0));
 }
 
 /* Accept REG and any CONST_INT that can be moved in one instruction into a
@@ -575,10 +614,7 @@ reg_or_cint_move_operand (rtx op, enum machine_mode mode)
   if (register_operand (op, mode))
     return 1;
 
-  if (GET_CODE (op) == CONST_INT)
-    return cint_ok_for_move (INTVAL (op));
-
-  return 0;
+  return (GET_CODE (op) == CONST_INT && cint_ok_for_move (INTVAL (op)));
 }
 
 int
@@ -831,6 +867,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 
         So instead we just emit the raw set, which avoids the movXX
         expanders completely.  */
+      mark_reg_pointer (reg, BITS_PER_UNIT);
       emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
       current_function_uses_pic_offset_table = 1;
       return reg;
@@ -861,6 +898,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
       current_function_uses_pic_offset_table = 1;
       MEM_NOTRAP_P (pic_ref) = 1;
       RTX_UNCHANGING_P (pic_ref) = 1;
+      mark_reg_pointer (reg, BITS_PER_UNIT);
       insn = emit_move_insn (reg, pic_ref);
 
       /* Put a REG_EQUAL note on this insn, so that it can be optimized.  */
@@ -885,7 +923,9 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
          orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
                                         base == reg ? 0 : reg);
        }
-      else abort ();
+      else
+       abort ();
+
       if (GET_CODE (orig) == CONST_INT)
        {
          if (INT_14_BITS (orig))
@@ -895,6 +935,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
       pic_ref = gen_rtx_PLUS (Pmode, base, orig);
       /* Likewise, should we set special REG_NOTEs here?  */
     }
+
   return pic_ref;
 }
 
@@ -955,6 +996,18 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 {
   rtx orig = x;
 
+  /* We need to canonicalize the order of operands in unscaled indexed
+     addresses since the code that checks if an address is valid doesn't
+     always try both orders.  */
+  if (!TARGET_NO_SPACE_REGS
+      && GET_CODE (x) == PLUS
+      && GET_MODE (x) == Pmode
+      && REG_P (XEXP (x, 0))
+      && REG_P (XEXP (x, 1))
+      && REG_POINTER (XEXP (x, 0))
+      && !REG_POINTER (XEXP (x, 1)))
+    return gen_rtx_PLUS (Pmode, XEXP (x, 1), XEXP (x, 0));
+
   if (flag_pic)
     return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
 
@@ -1423,6 +1476,36 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
   register rtx operand1 = operands[1];
   register rtx tem;
 
+  /* We can only handle indexed addresses in the destination operand
+     of floating point stores.  Thus, we need to break out indexed
+     addresses from the destination operand.  */
+  if (GET_CODE (operand0) == MEM && IS_INDEX_ADDR_P (XEXP (operand0, 0)))
+    {
+      /* This is only safe up to the beginning of life analysis.  */
+      if (no_new_pseudos)
+       abort ();
+
+      tem = copy_to_mode_reg (Pmode, XEXP (operand0, 0));
+      operand0 = replace_equiv_address (operand0, tem);
+    }
+
+  /* On targets with non-equivalent space registers, break out unscaled
+     indexed addresses from the source operand before the final CSE.
+     We have to do this because the REG_POINTER flag is not correctly
+     carried through various optimization passes and CSE may substitute
+     a pseudo without the pointer set for one with the pointer set.  As
+     a result, we loose various opportunites to create insns with
+     unscaled indexed addresses.  */
+  if (!TARGET_NO_SPACE_REGS
+      && !cse_not_expected
+      && GET_CODE (operand1) == MEM
+      && GET_CODE (XEXP (operand1, 0)) == PLUS
+      && REG_P (XEXP (XEXP (operand1, 0), 0))
+      && REG_P (XEXP (XEXP (operand1, 0), 1)))
+    operand1
+      = replace_equiv_address (operand1,
+                              copy_to_mode_reg (Pmode, XEXP (operand1, 0)));
+
   if (scratch_reg
       && reload_in_progress && GET_CODE (operand0) == REG
       && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
@@ -1461,6 +1544,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
       && ((tem = find_replacement (&XEXP (operand0, 0)))
          != XEXP (operand0, 0)))
     operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
+
   if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
       && ((tem = find_replacement (&XEXP (operand1, 0)))
          != XEXP (operand1, 0)))
@@ -1471,7 +1555,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
      (subreg (mem (addr))) cases.  */
   if (fp_reg_operand (operand0, mode)
       && ((GET_CODE (operand1) == MEM
-          && ! memory_address_p (DFmode, XEXP (operand1, 0)))
+          && !memory_address_p (DFmode, XEXP (operand1, 0)))
          || ((GET_CODE (operand1) == SUBREG
               && GET_CODE (XEXP (operand1, 0)) == MEM
               && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
@@ -1490,10 +1574,11 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
       if (!memory_address_p (Pmode, XEXP (operand1, 0)))
        {
          emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
-         emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
-                                                      Pmode,
-                                                      XEXP (XEXP (operand1, 0), 0),
-                                                      scratch_reg));
+         emit_move_insn (scratch_reg,
+                         gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
+                                         Pmode,
+                                         XEXP (XEXP (operand1, 0), 0),
+                                         scratch_reg));
        }
       else
        emit_move_insn (scratch_reg, XEXP (operand1, 0));
@@ -1506,7 +1591,8 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
                && ! memory_address_p (DFmode, XEXP (operand0, 0)))
               || ((GET_CODE (operand0) == SUBREG)
                   && GET_CODE (XEXP (operand0, 0)) == MEM
-                  && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
+                  && !memory_address_p (DFmode,
+                                        XEXP (XEXP (operand0, 0), 0))))
           && scratch_reg)
     {
       if (GET_CODE (operand0) == SUBREG)
@@ -1618,7 +1704,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
       emit_move_insn (operand0, scratch_reg);
       return 1;
     }
-  /* Handle most common case: storing into a register.  */
+  /* Handle the most common case: storing into a register.  */
   else if (register_operand (operand0, mode))
     {
       if (register_operand (operand1, mode)
@@ -1630,7 +1716,67 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
          /* Only `general_operands' can come here, so MEM is ok.  */
          || GET_CODE (operand1) == MEM)
        {
-         /* Run this case quickly.  */
+         /* Various sets are created during RTL generation which don't
+            have the REG_POINTER flag correctly set.  After the CSE pass,
+            instruction recognition can fail if we don't consistently
+            set this flag when performing register copies.  This should
+            also improve the opportunities for creating insns that use
+            unscaled indexing.  */
+         if (REG_P (operand0) && REG_P (operand1))
+           {
+             if (REG_POINTER (operand1)
+                 && !REG_POINTER (operand0)
+                 && !HARD_REGISTER_P (operand0))
+               copy_reg_pointer (operand0, operand1);
+             else if (REG_POINTER (operand0)
+                      && !REG_POINTER (operand1)
+                      && !HARD_REGISTER_P (operand1))
+               copy_reg_pointer (operand1, operand0);
+           }
+         
+         /* When MEMs are broken out, the REG_POINTER flag doesn't
+            get set.  In some cases, we can set the REG_POINTER flag
+            from the declaration for the MEM.  */
+         if (REG_P (operand0)
+             && GET_CODE (operand1) == MEM
+             && !REG_POINTER (operand0))
+           {
+             tree decl = MEM_EXPR (operand1);
+
+             /* Set the register pointer flag and register alignment
+                if the declaration for this memory reference is a
+                pointer type.  Fortran indirect argument references
+                are ignored.  */
+             if (decl
+                 && !(flag_argument_noalias > 1
+                      && TREE_CODE (decl) == INDIRECT_REF
+                      && TREE_CODE (TREE_OPERAND (decl, 0)) == PARM_DECL))
+               {
+                 tree type;
+
+                 /* If this is a COMPONENT_REF, use the FIELD_DECL from
+                    tree operand 1.  */
+                 if (TREE_CODE (decl) == COMPONENT_REF)
+                   decl = TREE_OPERAND (decl, 1);
+
+                 type = TREE_TYPE (decl);
+                 if (TREE_CODE (type) == ARRAY_TYPE)
+                   type = get_inner_array_type (type);
+
+                 if (POINTER_TYPE_P (type))
+                   {
+                     int align;
+
+                     type = TREE_TYPE (type);
+                     /* Using TYPE_ALIGN_OK is rather conservative as
+                        only the ada frontend actually sets it.  */
+                     align = (TYPE_ALIGN_OK (type) ? TYPE_ALIGN (type)
+                              : BITS_PER_UNIT);
+                     mark_reg_pointer (operand0, align);
+                   }
+               }
+           }
+
          emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
          return 1;
        }
@@ -1777,6 +1923,8 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
              else
                {
                  operands[1] = legitimize_pic_address (operand1, mode, temp);
+                 if (REG_P (operand0) && REG_P (operands[1]))
+                   copy_reg_pointer (operand0, operands[1]);
                  emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1]));
                }
            }
@@ -1804,9 +1952,10 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
                 Don't mark hard registers though.  That loses.  */
              if (GET_CODE (operand0) == REG
                  && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
-               REG_POINTER (operand0) = 1;
+               mark_reg_pointer (operand0, BITS_PER_UNIT);
              if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)
-               REG_POINTER (temp) = 1;
+               mark_reg_pointer (temp, BITS_PER_UNIT);
+
              if (ishighonly)
                set = gen_rtx_SET (mode, operand0, temp);
              else
@@ -4829,8 +4978,14 @@ print_operand (FILE *file, rtx x, int code)
            fputs (",ma", file);
          break;
        case PLUS:
-         if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
-             || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
+         if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+             && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
+           {
+             if (ASSEMBLER_DIALECT == 0)
+               fputs ("x", file);
+           }
+         else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+                  || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
            {
              if (ASSEMBLER_DIALECT == 0)
                fputs ("x,s", file);
@@ -4905,20 +5060,33 @@ print_operand (FILE *file, rtx x, int code)
           base = XEXP (XEXP (x, 0), 0);
          fprintf (file, "%d(%s)", size, reg_names [REGNO (base)]);
          break;
-       default:
-         if (GET_CODE (XEXP (x, 0)) == PLUS
-             && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
+       case PLUS:
+         if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
            fprintf (file, "%s(%s)",
                     reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))],
                     reg_names [REGNO (XEXP (XEXP (x, 0), 1))]);
-         else if (GET_CODE (XEXP (x, 0)) == PLUS
-                  && GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
+         else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
            fprintf (file, "%s(%s)",
                     reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))],
                     reg_names [REGNO (XEXP (XEXP (x, 0), 0))]);
+         else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+                  && 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
+                index and base registers in the combined move patterns.  */
+             rtx base = XEXP (XEXP (x, 0), 1);
+             rtx index = XEXP (XEXP (x, 0), 0);
+
+             fprintf (file, "%s(%s)",
+                      reg_names [REGNO (index)], reg_names [REGNO (base)]);
+           }
          else
            output_address (XEXP (x, 0));
          break;
+       default:
+         output_address (XEXP (x, 0));
+         break;
        }
     }
   else
@@ -7844,32 +8012,33 @@ shadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
   return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op)));
 }
 
-/* Return 1 if OP is valid as a base register in a reg + reg address.  */
+/* Return 1 if OP is valid as a base or index register in a
+   REG+REG address.  */
 
 int
-basereg_operand (rtx op, enum machine_mode mode)
+borx_reg_operand (rtx op, enum machine_mode mode)
 {
-  /* cse will create some unscaled indexed addresses, however; it
-     generally isn't a win on the PA, so avoid creating unscaled
-     indexed addresses until after cse is finished.  */
-  if (!cse_not_expected)
+  if (GET_CODE (op) != REG)
     return 0;
 
-  /* Allow any register when TARGET_NO_SPACE_REGS is in effect since
-     we don't have to worry about the braindamaged implicit space
-     register selection from the basereg.  */
-  if (TARGET_NO_SPACE_REGS)
-    return (GET_CODE (op) == REG);
+  /* We must reject virtual registers as the only expressions that
+     can be instantiated are REG and REG+CONST.  */
+  if (op == virtual_incoming_args_rtx
+      || op == virtual_stack_vars_rtx
+      || op == virtual_stack_dynamic_rtx
+      || op == virtual_outgoing_args_rtx
+      || op == virtual_cfa_rtx)
+    return 0;
 
   /* While it's always safe to index off the frame pointer, it's not
-     always profitable, particularly when the frame pointer is being
-     eliminated.  */
-  if (! flag_omit_frame_pointer && op == frame_pointer_rtx)
-    return 1;
+     profitable to do so when the frame pointer is being eliminated.  */
+  if (!reload_completed
+      && flag_omit_frame_pointer
+      && !current_function_calls_alloca
+      && op == frame_pointer_rtx)
+    return 0;
 
-  return (GET_CODE (op) == REG
-          && REG_POINTER (op)
-          && register_operand (op, mode));
+  return register_operand (op, mode);
 }
 
 /* Return 1 if this operand is anything other than a hard register.  */
index ab15e79..5c33a3b 100644 (file)
@@ -641,9 +641,9 @@ extern struct rtx_def *hppa_pic_save_rtx (void);
    in some cases it is preferable to use a more restrictive class.  */
 #define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
 
-/* Return the register class of a scratch register needed to copy IN into
-   or out of a register in CLASS in MODE.  If it can be done directly
-   NO_REGS is returned. 
+/* Return the register class of a scratch register needed to copy
+   IN into a register in CLASS in MODE, or a register in CLASS in MODE
+   to IN.  If it can be done directly NO_REGS is returned. 
 
   Avoid doing any work for the common case calls.  */
 
@@ -1199,83 +1199,87 @@ extern int may_call_alloca;
             || cint_ok_for_move (INTVAL (X))))                 \
    && !function_label_operand (X, VOIDmode))
 
-/* Subroutine for EXTRA_CONSTRAINT.
+/* Subroutines for EXTRA_CONSTRAINT.
 
    Return 1 iff OP is a pseudo which did not get a hard register and
    we are running the reload pass.  */
-
 #define IS_RELOADING_PSEUDO_P(OP) \
   ((reload_in_progress                                 \
     && GET_CODE (OP) == REG                            \
     && REGNO (OP) >= FIRST_PSEUDO_REGISTER             \
     && reg_renumber [REGNO (OP)] < 0))
 
+/* Return 1 iff OP is a scaled or unscaled index address.  */
+#define IS_INDEX_ADDR_P(OP) \
+  (GET_CODE (OP) == PLUS                               \
+   && GET_MODE (OP) == Pmode                           \
+   && (GET_CODE (XEXP (OP, 0)) == MULT                 \
+       || GET_CODE (XEXP (OP, 1)) == MULT              \
+       || (REG_P (XEXP (OP, 0))                                \
+          && REG_P (XEXP (OP, 1)))))
+
+/* Return 1 iff OP is a LO_SUM DLT address.  */
+#define IS_LO_SUM_DLT_ADDR_P(OP) \
+  (GET_CODE (OP) == LO_SUM                             \
+   && GET_MODE (OP) == Pmode                           \
+   && REG_P (XEXP (OP, 0))                             \
+   && REG_OK_FOR_BASE_P (XEXP (OP, 0))                 \
+   && GET_CODE (XEXP (OP, 1)) == UNSPEC)
+
 /* Optional extra constraints for this machine. Borrowed from sparc.h.
 
-   For the HPPA, `Q' means that this is a memory operand but not a
-   symbolic memory operand.  Note that an unassigned pseudo register
-   is such a memory operand.  Needed because reload will generate
-   these things in insns and then not re-recognize the insns, causing
-   constrain_operands to fail.
+   `A' is a LO_SUM DLT memory operand.
+
+   `Q' is any memory operand that isn't a symbolic, indexed or lo_sum
+       memory operand.  Note that an unassigned pseudo register is such a
+       memory operand.  Needed because reload will generate these things
+       and then not re-recognize the insn, causing constrain_operands to
+       fail.
 
-   `R' is used for scaled indexed addresses.
+   `R' is a scaled/unscaled indexed memory operand.
 
    `S' is the constant 31.
 
-   `T' is for fp loads and stores.  */
-#define EXTRA_CONSTRAINT(OP, C)                                \
-  ((C) == 'Q' ?                                                \
-   (IS_RELOADING_PSEUDO_P (OP)                         \
-    || (GET_CODE (OP) == MEM                           \
-       && (memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
-           || reload_in_progress)                      \
-       && ! symbolic_memory_operand (OP, VOIDmode)     \
-        && !(GET_CODE (XEXP (OP, 0)) == PLUS           \
-            && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
-                || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))))\
-   : ((C) == 'R' ?                                     \
-     (GET_CODE (OP) == MEM                             \
-      && GET_CODE (XEXP (OP, 0)) == PLUS               \
-      && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT    \
-         || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT) \
-      && (move_operand (OP, GET_MODE (OP))             \
-         || memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
-         || reload_in_progress))                       \
-   : ((C) == 'T' ?                                     \
-      (GET_CODE (OP) == MEM                            \
-       /* Using DFmode forces only short displacements \
-         to be recognized as valid in reg+d addresses. \
-         However, this is not necessary for PA2.0 since\
-         it has long FP loads/stores.                  \
-                                                       \
-         FIXME: the ELF32 linker clobbers the LSB of   \
-         the FP register number in {fldw,fstw} insns.  \
-         Thus, we only allow long FP loads/stores on   \
-         TARGET_64BIT.  */                             \
-       && memory_address_p ((TARGET_PA_20              \
-                            && !TARGET_ELF32           \
-                            ? GET_MODE (OP)            \
-                            : DFmode),                 \
-                           XEXP (OP, 0))               \
-       && !(GET_CODE (XEXP (OP, 0)) == LO_SUM          \
-           && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG \
-           && REG_OK_FOR_BASE_P (XEXP (XEXP (OP, 0), 0))\
-           && GET_CODE (XEXP (XEXP (OP, 0), 1)) == UNSPEC\
-           && GET_MODE (XEXP (OP, 0)) == Pmode)        \
-       && !(GET_CODE (XEXP (OP, 0)) == PLUS            \
-           && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
-               || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT)))\
-   : ((C) == 'U' ?                                     \
-      (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63)        \
-   : ((C) == 'A' ?                                     \
-      (GET_CODE (OP) == MEM                            \
-       && GET_CODE (XEXP (OP, 0)) == LO_SUM            \
-       && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG     \
-       && REG_OK_FOR_BASE_P (XEXP (XEXP (OP, 0), 0))   \
-       && GET_CODE (XEXP (XEXP (OP, 0), 1)) == UNSPEC          \
-       && GET_MODE (XEXP (OP, 0)) == Pmode)                    \
-   : ((C) == 'S' ?                                     \
-      (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) : 0))))))
+   `T' is for fp loads and stores.
+
+   `U' is the constant 63.  */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+  ((C) == 'Q' ?                                                                \
+   (IS_RELOADING_PSEUDO_P (OP)                                         \
+    || (GET_CODE (OP) == MEM                                           \
+       && (reload_in_progress                                          \
+           || memory_address_p (GET_MODE (OP), XEXP (OP, 0)))          \
+       && !symbolic_memory_operand (OP, VOIDmode)                      \
+       && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))                         \
+       && !IS_INDEX_ADDR_P (XEXP (OP, 0))))                            \
+   : ((C) == 'A' ?                                                     \
+      (GET_CODE (OP) == MEM                                            \
+       && IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)))                         \
+   : ((C) == 'R' ?                                                     \
+      (GET_CODE (OP) == MEM                                            \
+       && IS_INDEX_ADDR_P (XEXP (OP, 0)))                              \
+   : ((C) == 'T' ?                                                     \
+      (GET_CODE (OP) == MEM                                            \
+       && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))                         \
+       && !IS_INDEX_ADDR_P (XEXP (OP, 0))                              \
+       /* Using DFmode forces only short displacements                 \
+         to be recognized as valid in reg+d addresses.                 \
+         However, this is not necessary for PA2.0 since                \
+         it has long FP loads/stores.                                  \
+                                                                       \
+         FIXME: the ELF32 linker clobbers the LSB of                   \
+         the FP register number in {fldw,fstw} insns.                  \
+         Thus, we only allow long FP loads/stores on                   \
+         TARGET_64BIT.  */                                             \
+       && memory_address_p ((TARGET_PA_20 && !TARGET_ELF32             \
+                            ? GET_MODE (OP)                            \
+                            : DFmode),                                 \
+                           XEXP (OP, 0)))                              \
+   : ((C) == 'S' ?                                                     \
+      (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31)                        \
+   : ((C) == 'U' ?                                                     \
+      (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63) : 0))))))
        
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
@@ -1311,16 +1315,53 @@ extern int may_call_alloca;
 
 #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 the HP-PA, the actual legitimate addresses must be
-   REG+REG, REG+(REG*SCALE) or REG+SMALLINT.
-   But we can treat a SYMBOL_REF as legitimate if it is part of this
-   function's constant-pool, because such addresses can actually
-   be output as REG+SMALLINT. 
+/* 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 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. 
 
    Note we only allow 5 bit immediates for access to a constant address;
    doing so avoids losing for loading/storing a FP register at an address
@@ -1338,87 +1379,114 @@ extern int may_call_alloca;
 #define VAL_14_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x2000 < 0x4000)
 #define INT_14_BITS(X) VAL_14_BITS_P (INTVAL (X))
 
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)  \
-{                                                      \
-  if ((REG_P (X) && REG_OK_FOR_BASE_P (X))             \
+/* These are the modes that we allow for scaled indexing.  */
+#define MODE_OK_FOR_SCALED_INDEXING_P(MODE) \
+  ((TARGET_64BIT && (MODE) == DImode)                                  \
+   || (MODE) == SImode                                                 \
+   || (MODE) == HImode                                                 \
+   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+
+/* These are the modes that we allow for unscaled indexing.  */
+#define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \
+  ((TARGET_64BIT && (MODE) == DImode)                                  \
+   || (MODE) == SImode                                                 \
+   || (MODE) == HImode                                                 \
+   || (MODE) == QImode                                                 \
+   || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode)))
+
+#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, 0))                          \
-         && REG_OK_FOR_BASE_P (XEXP (X, 0)))           \
-       base = XEXP (X, 0), index = XEXP (X, 1);        \
-      else if (REG_P (XEXP (X, 1))                     \
-              && REG_OK_FOR_BASE_P (XEXP (X, 1)))      \
-       base = XEXP (X, 1), index = XEXP (X, 0);        \
-      if (base != 0)                                   \
-       if (GET_CODE (index) == CONST_INT               \
-           && ((INT_14_BITS (index)                    \
-                && (TARGET_SOFT_FLOAT                  \
-                    || (TARGET_PA_20                   \
-                        && ((MODE == SFmode            \
-                             && (INTVAL (index) % 4) == 0)\
-                            || (MODE == DFmode         \
-                                && (INTVAL (index) % 8) == 0)))\
-                    || ((MODE) != SFmode && (MODE) != DFmode))) \
-               || INT_5_BITS (index)))                 \
-         goto ADDR;                                    \
-      if (! TARGET_SOFT_FLOAT                          \
-         && ! TARGET_DISABLE_INDEXING                  \
-         && base                                       \
-         && ((MODE) == SFmode || (MODE) == DFmode)     \
-         && GET_CODE (index) == MULT                   \
-         && GET_CODE (XEXP (index, 0)) == REG          \
-         && REG_OK_FOR_BASE_P (XEXP (index, 0))        \
-         && GET_CODE (XEXP (index, 1)) == CONST_INT    \
-         && INTVAL (XEXP (index, 1)) == ((MODE) == SFmode ? 4 : 8))\
-       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) == LABEL_REF                   \
-          || (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;                                         \
+         && 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)                                      \
+              && (TARGET_SOFT_FLOAT                                    \
+                  || (TARGET_PA_20                                     \
+                      && ((MODE == SFmode                              \
+                           && (INTVAL (index) % 4) == 0)               \
+                          || (MODE == DFmode                           \
+                              && (INTVAL (index) % 8) == 0)))          \
+                  || ((MODE) != SFmode && (MODE) != DFmode)))          \
+              || 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)                   \
+                && REG_POINTER (base) && !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) == LABEL_REF                                   \
+          || (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
@@ -1872,16 +1940,17 @@ do {                                                                    \
 #define JMP_BUF_SIZE 50
 
 #define PREDICATE_CODES                                                        \
-  {"reg_or_0_operand", {SUBREG, REG, CONST_INT}},                      \
+  {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},                \
   {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT,          \
                            CONST_DOUBLE, CONST, HIGH, CONSTANT_P_RTX}}, \
+  {"indexed_memory_operand", {SUBREG, MEM}},                           \
   {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
   {"symbolic_memory_operand", {SUBREG, MEM}},                          \
   {"reg_before_reload_operand", {REG, MEM}},                           \
-  {"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}},                  \
   {"reg_or_0_or_nonsymb_mem_operand", {SUBREG, REG, MEM, CONST_INT,    \
                                       CONST_DOUBLE}},                  \
-  {"move_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}},     \
+  {"move_dest_operand", {SUBREG, REG, MEM}},                           \
+  {"move_src_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}}, \
   {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}},              \
   {"pic_label_operand", {LABEL_REF, CONST}},                           \
   {"fp_reg_operand", {REG}},                                           \
@@ -1905,7 +1974,6 @@ do {                                                                      \
   {"pc_or_label_operand", {PC, LABEL_REF}},                            \
   {"plus_xor_ior_operator", {PLUS, XOR, IOR}},                         \
   {"shadd_operand", {CONST_INT}},                                      \
-  {"basereg_operand", {REG}},                                          \
   {"div_operand", {REG, CONST_INT}},                                   \
   {"ireg_operand", {REG}},                                             \
   {"cmpib_comparison_operator", {EQ, NE, LT, LE, LEU,                  \
index 6f0cdcf..310a248 100644 (file)
 }")
 
 (define_insn ""
-  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
-                               "=r,r,r,r,r,r,Q,!*q,!f,f,*TR")
-       (match_operand:SI 1 "move_operand"
-                               "A,r,J,N,K,RQ,rM,!rM,!fM,*RT,f"))]
+  [(set (match_operand:SI 0 "move_dest_operand"
+                         "=r,r,r,r,r,r,Q,!*q,!*f,*f,T")
+       (match_operand:SI 1 "move_src_operand"
+                         "A,r,J,N,K,RQ,rM,!rM,!*fM,RT,*f"))]
   "(register_operand (operands[0], SImode)
     || reg_or_0_operand (operands[1], SImode))
-   && ! TARGET_SOFT_FLOAT"
+   && !TARGET_SOFT_FLOAT"
   "@
    ldw RT'%A1,%0
    copy %1,%0
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4")])
 
 (define_insn ""
-  [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
-                               "=r,r,r,r,r,r,Q,!*q")
-       (match_operand:SI 1 "move_operand"
-                               "A,r,J,N,K,RQ,rM,!rM"))]
+  [(set (match_operand:SI 0 "indexed_memory_operand" "=R")
+       (match_operand:SI 1 "register_operand" "f"))]
+  "!TARGET_SOFT_FLOAT
+   && !TARGET_DISABLE_INDEXING
+   && reload_completed"
+  "fstw%F0 %1,%0"
+  [(set_attr "type" "fpstore")
+   (set_attr "pa_combine_type" "addmove")
+   (set_attr "length" "4")])
+
+; Rewrite RTL using an indexed store.  This will allow the insn that
+; computes the address to be deleted if the register it sets is dead.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 4))
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "reg_or_0_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 2 "register_operand" "")
+                (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 4))))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 4))
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 2 "register_operand" "")
+                (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 4))))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:SI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:SI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:DI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SI (match_dup 0))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SI (plus:DI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "move_dest_operand"
+                         "=r,r,r,r,r,r,Q,!*q")
+       (match_operand:SI 1 "move_src_operand"
+                         "A,r,J,N,K,RQ,rM,!rM"))]
   "(register_operand (operands[0], SImode)
     || reg_or_0_operand (operands[1], SImode))
    && TARGET_SOFT_FLOAT"
    (set_attr "pa_combine_type" "addmove")
    (set_attr "length" "4,4,4,4,4,4,4,4")])
 
+;; Load or store with base-register modification.
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (mem:SI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldwx|ldw} %2(%1),%0"
+       (mem:SI (plus:DI (match_operand:DI 1 "register_operand" "+r")
+                        (match_operand:DI 2 "int5_operand" "L"))))
+   (set (match_dup 1)
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldw,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
+; And a zero extended variant.
 (define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldwx|ldw} %1(%2),%0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (mem:SI
+                         (plus:DI
+                           (match_operand:DI 1 "register_operand" "+r")
+                           (match_operand:DI 2 "int5_operand" "L")))))
+   (set (match_dup 1)
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldw,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-;; Load or store with base-register modification.
-
 (define_expand "pre_load"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
              (mem (plus (match_operand 1 "register_operand" "")
 }")
 
 (define_insn ""
-  [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,!*q,!*f")
-       (match_operand:HI 1 "move_operand" "r,J,N,K,RQ,rM,!rM,!*fM"))]
+  [(set (match_operand:HI 0 "move_dest_operand"
+                         "=r,r,r,r,r,Q,!*q,!*f")
+       (match_operand:HI 1 "move_src_operand"
+                         "r,J,N,K,RQ,rM,!rM,!*fM"))]
   "register_operand (operands[0], HImode)
    || reg_or_0_operand (operands[1], HImode)"
   "@
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (mem:HI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldhx|ldh} %2(%1),%0"
+       (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "+r")
+                        (match_operand:SI 2 "int5_operand" "L"))))
+   (set (match_dup 1)
+       (plus:SI (match_dup 1) (match_dup 2)))]
+  ""
+  "{ldhs|ldh},mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-       (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldhx|ldh} %1(%2),%0"
+       (mem:HI (plus:DI (match_operand:DI 1 "register_operand" "+r")
+                        (match_operand:DI 2 "int5_operand" "L"))))
+   (set (match_dup 1)
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldh,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-; Now zero extended variants.
+; And a zero extended variant.
 (define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (zero_extend:SI (mem:HI
-                         (plus:SI
-                           (match_operand:SI 1 "basereg_operand" "r")
-                           (match_operand:SI 2 "register_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldhx|ldh} %2(%1),%0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (mem:HI
+                         (plus:DI
+                           (match_operand:DI 1 "register_operand" "+r")
+                           (match_operand:DI 2 "int5_operand" "L")))))
+   (set (match_dup 1)
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldh,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (mem:HI
                          (plus:SI
-                            (match_operand:SI 1 "register_operand" "r")
-                            (match_operand:SI 2 "basereg_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldhx|ldh} %1(%2),%0"
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "+r")
-                        (match_operand:SI 2 "int5_operand" "L"))))
+                           (match_operand:SI 1 "register_operand" "+r")
+                           (match_operand:SI 2 "int5_operand" "L")))))
    (set (match_dup 1)
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-; And a zero extended variant.
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (mem:HI
-                         (plus:SI
-                           (match_operand:SI 1 "register_operand" "+r")
-                           (match_operand:SI 2 "int5_operand" "L")))))
+                         (plus:DI
+                           (match_operand:DI 1 "register_operand" "+r")
+                           (match_operand:DI 2 "int5_operand" "L")))))
    (set (match_dup 1)
-       (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
-  "{ldhs|ldh},mb %2(%1),%0"
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldh,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
    (set_attr "length" "4")])
 
 (define_insn ""
+  [(set (mem:HI (plus:DI (match_operand:DI 0 "register_operand" "+r")
+                        (match_operand:DI 1 "int5_operand" "L")))
+       (match_operand:HI 2 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:DI (match_dup 0) (match_dup 1)))]
+  "TARGET_64BIT"
+  "sth,mb %r2,%1(%0)"
+  [(set_attr "type" "store")
+   (set_attr "length" "4")])
+
+(define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
        (plus:HI (match_operand:HI 1 "register_operand" "r")
                 (match_operand 2 "const_int_operand" "J")))]
 }")
 
 (define_insn ""
-  [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,!*q,!*f")
-       (match_operand:QI 1 "move_operand" "r,J,N,K,RQ,rM,!rM,!*fM"))]
+  [(set (match_operand:QI 0 "move_dest_operand"
+                         "=r,r,r,r,r,Q,!*q,!*f")
+       (match_operand:QI 1 "move_src_operand"
+                         "r,J,N,K,RQ,rM,!rM,!*fM"))]
   "register_operand (operands[0], QImode)
    || reg_or_0_operand (operands[1], QImode)"
   "@
 
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (mem:QI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %2(%1),%0"
+       (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "+r")
+                        (match_operand:SI 2 "int5_operand" "L"))))
+   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
+  ""
+  "{ldbs|ldb},mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn ""
   [(set (match_operand:QI 0 "register_operand" "=r")
-       (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %1(%2),%0"
+       (mem:QI (plus:DI (match_operand:DI 1 "register_operand" "+r")
+                        (match_operand:DI 2 "int5_operand" "L"))))
+   (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldb,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-; Indexed byte load with zero extension to SImode or HImode.
+; Now the same thing with zero extensions.
 (define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (zero_extend:SI (mem:QI
-                         (plus:SI
-                           (match_operand:SI 1 "basereg_operand" "r")
-                           (match_operand:SI 2 "register_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %2(%1),%0"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (mem:QI (plus:DI
+                                 (match_operand:DI 1 "register_operand" "+r")
+                                 (match_operand:DI 2 "int5_operand" "L")))))
+   (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldb,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (zero_extend:SI (mem:QI
-                         (plus:SI
-                           (match_operand:SI 1 "register_operand" "r")
-                           (match_operand:SI 2 "basereg_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %1(%2),%0"
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (zero_extend:HI (mem:QI
-                         (plus:SI
-                           (match_operand:SI 1 "basereg_operand" "r")
-                           (match_operand:SI 2 "register_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %2(%1),%0"
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:HI 0 "register_operand" "=r")
-       (zero_extend:HI (mem:QI
-                         (plus:SI
-                           (match_operand:SI 1 "register_operand" "r")
-                           (match_operand:SI 2 "basereg_operand" "r")))))]
-  "! TARGET_DISABLE_INDEXING"
-  "{ldbx|ldb} %1(%2),%0"
-  [(set_attr "type" "load")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:QI 0 "register_operand" "=r")
-       (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "+r")
-                        (match_operand:SI 2 "int5_operand" "L"))))
+       (zero_extend:SI (mem:QI (plus:SI
+                                 (match_operand:SI 1 "register_operand" "+r")
+                                 (match_operand:SI 2 "int5_operand" "L")))))
    (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
   ""
   "{ldbs|ldb},mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
-; Now the same thing with zero extensions.
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (zero_extend:SI (mem:QI (plus:SI
-                                 (match_operand:SI 1 "register_operand" "+r")
-                                 (match_operand:SI 2 "int5_operand" "L")))))
-   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
-  ""
-  "{ldbs|ldb},mb %2(%1),%0"
+       (zero_extend:SI (mem:QI (plus:DI
+                                 (match_operand:DI 1 "register_operand" "+r")
+                                 (match_operand:DI 2 "int5_operand" "L")))))
+   (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldb,mb %2(%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
    (set_attr "length" "4")])
 
 (define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (zero_extend:HI (mem:QI (plus:DI
+                                 (match_operand:DI 1 "register_operand" "+r")
+                                 (match_operand:DI 2 "int5_operand" "L")))))
+   (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT"
+  "ldb,mb %2(%1),%0"
+  [(set_attr "type" "load")
+   (set_attr "length" "4")])
+
+(define_insn ""
   [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "+r")
                         (match_operand:SI 1 "int5_operand" "L")))
        (match_operand:QI 2 "reg_or_0_operand" "rM"))
   [(set_attr "type" "store")
    (set_attr "length" "4")])
 
+(define_insn ""
+  [(set (mem:QI (plus:DI (match_operand:DI 0 "register_operand" "+r")
+                        (match_operand:DI 1 "int5_operand" "L")))
+       (match_operand:QI 2 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:DI (match_dup 0) (match_dup 1)))]
+  "TARGET_64BIT"
+  "stb,mb %r2,%1(%0)"
+  [(set_attr "type" "store")
+   (set_attr "length" "4")])
+
 ;; The definition of this insn does not really explain what it does,
 ;; but it should suffice that anything generated as this insn will be
 ;; recognized as a movstrsi operation, and that it will not successfully
   "GET_CODE (operands[1]) == CONST_DOUBLE
    && operands[1] != CONST0_RTX (DFmode)
    && !TARGET_64BIT
-   && ! TARGET_SOFT_FLOAT"
+   && !TARGET_SOFT_FLOAT"
   "* return (which_alternative == 0 ? output_move_double (operands)
                                    : \"fldd%F1 %1,%0\");"
   [(set_attr "type" "move,fpload")
   "
 {
   if (GET_CODE (operands[1]) == CONST_DOUBLE && TARGET_64BIT)
-      operands[1] = force_const_mem (DFmode, operands[1]);
+    operands[1] = force_const_mem (DFmode, operands[1]);
 
   if (emit_move_sequence (operands, DFmode, 0))
     DONE;
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
-                         "=f,*r,RQ,?o,?Q,f,*r,*r")
+  [(set (match_operand:DF 0 "move_dest_operand"
+                         "=f,*r,Q,?o,?Q,f,*r,*r")
        (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
                          "fG,*rG,f,*r,*r,RQ,o,RQ"))]
   "(register_operand (operands[0], DFmode)
     || reg_or_0_operand (operands[1], DFmode))
-   && ! (GET_CODE (operands[1]) == CONST_DOUBLE
-        && GET_CODE (operands[0]) == MEM)
-   && ! TARGET_64BIT
-   && ! TARGET_SOFT_FLOAT"
+   && !(GET_CODE (operands[1]) == CONST_DOUBLE
+       && GET_CODE (operands[0]) == MEM)
+   && !TARGET_64BIT
+   && !TARGET_SOFT_FLOAT"
   "*
 {
   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])
    (set_attr "length" "4,8,4,8,16,4,8,16")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
+  [(set (match_operand:DF 0 "indexed_memory_operand" "=R")
+       (match_operand:DF 1 "reg_or_0_operand" "f"))]
+  "!TARGET_SOFT_FLOAT
+   && !TARGET_DISABLE_INDEXING
+   && reload_completed"
+  "fstd%F0 %1,%0"
+  [(set_attr "type" "fpstore")
+   (set_attr "pa_combine_type" "addmove")
+   (set_attr "length" "4")])
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 8))
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 2 "register_operand" "")
+                (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 8))))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:SI (mult:SI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 8))
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 2 "register_operand" "")
+                (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 8))))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:SI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:SI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:DI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DF (match_dup 0))
+        (match_operand:DF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DF (plus:DI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:DF 0 "move_dest_operand"
                          "=r,?o,?Q,r,r")
        (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "rG,r,r,o,Q"))]
+                         "rG,r,r,o,RQ"))]
   "(register_operand (operands[0], DFmode)
     || reg_or_0_operand (operands[1], DFmode))
-   && ! TARGET_64BIT
+   && !TARGET_64BIT
    && TARGET_SOFT_FLOAT"
   "*
 {
    (set_attr "length" "8,8,16,8,16")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
-                               "=r,r,r,r,r,Q,!*q,!f,f,*TR")
-       (match_operand:DF 1 "move_operand"
-                               "r,J,N,K,RQ,rM,!rM,!fM,*RT,f"))]
+  [(set (match_operand:DF 0 "move_dest_operand"
+                         "=!*r,*r,*r,*r,*r,Q,!*q,f,f,T")
+       (match_operand:DF 1 "move_src_operand"
+                         "!*r,J,N,K,RQ,*rM,!*rM,fM,RT,f"))]
   "(register_operand (operands[0], DFmode)
     || reg_or_0_operand (operands[1], DFmode))
-   && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
+   && !TARGET_SOFT_FLOAT && TARGET_64BIT"
   "@
    copy %1,%0
    ldi %1,%0
    (set_attr "pa_combine_type" "addmove")
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=fx")
-       (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{flddx|fldd} %2(%1),%0"
-  [(set_attr "type" "fpload")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:DF 0 "register_operand" "=fx")
-       (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{flddx|fldd} %1(%2),%0"
-  [(set_attr "type" "fpload")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r")))
-       (match_operand:DF 0 "register_operand" "fx"))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fstdx|fstd} %0,%2(%1)"
-  [(set_attr "type" "fpstore")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r")))
-       (match_operand:DF 0 "register_operand" "fx"))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fstdx|fstd} %0,%1(%2)"
-  [(set_attr "type" "fpstore")
-   (set_attr "length" "4")])
-
+\f
 (define_expand "movdi"
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
+  [(set (match_operand:DI 0 "general_operand" "")
        (match_operand:DI 1 "general_operand" ""))]
   ""
   "
 {
   if (GET_CODE (operands[1]) == CONST_DOUBLE && TARGET_64BIT)
-      operands[1] = force_const_mem (DImode, operands[1]);
+    operands[1] = force_const_mem (DImode, operands[1]);
 
   if (emit_move_sequence (operands, DImode, 0))
     DONE;
    (set_attr "length" "8")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
-                         "=r,o,Q,r,r,r,f,f,*TR")
+  [(set (match_operand:DI 0 "move_dest_operand"
+                         "=r,o,Q,r,r,r,*f,*f,T")
        (match_operand:DI 1 "general_operand"
-                         "rM,r,r,o*R,Q,i,fM,*TR,f"))]
+                         "rM,r,r,o*R,Q,i,*fM,RT,*f"))]
   "(register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))
-   && ! TARGET_64BIT
-   && ! TARGET_SOFT_FLOAT"
+   && !TARGET_64BIT
+   && !TARGET_SOFT_FLOAT"
   "*
 {
   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])
    (set_attr "length" "8,8,16,8,16,16,4,4,4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
-                               "=r,r,r,r,r,r,Q,!*q,!f,f,*TR")
-       (match_operand:DI 1 "move_operand"
-                               "A,r,J,N,K,RQ,rM,!rM,!fM,*RT,f"))]
+  [(set (match_operand:DI 0 "move_dest_operand"
+                         "=r,r,r,r,r,r,Q,!*q,!*f,*f,T")
+       (match_operand:DI 1 "move_src_operand"
+                         "A,r,J,N,K,RQ,rM,!rM,!*fM,RT,*f"))]
   "(register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))
-   && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
+   && !TARGET_SOFT_FLOAT && TARGET_64BIT"
   "@
    ldd RT'%A1,%0
    copy %1,%0
    (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
+  [(set (match_operand:DI 0 "indexed_memory_operand" "=R")
+       (match_operand:DI 1 "register_operand" "f"))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && !TARGET_DISABLE_INDEXING
+   && reload_completed"
+  "fstd%F0 %1,%0"
+  [(set_attr "type" "fpstore")
+   (set_attr "pa_combine_type" "addmove")
+   (set_attr "length" "4")])
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 8))
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DI (match_dup 0))
+        (match_operand:DI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 2 "register_operand" "")
+                (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 8))))
+   (set (mem:DI (match_dup 0))
+        (match_operand:DI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DI (plus:DI (mult:DI (match_dup 1) (const_int 8)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 8))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DI (match_dup 0))
+        (match_operand:DI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DI (plus:DI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:DI (match_dup 0))
+        (match_operand:DI 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:DI (plus:DI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "move_dest_operand"
                          "=r,o,Q,r,r,r")
        (match_operand:DI 1 "general_operand"
                          "rM,r,r,o,Q,i"))]
   "(register_operand (operands[0], DImode)
     || reg_or_0_operand (operands[1], DImode))
-   && ! TARGET_64BIT
+   && !TARGET_64BIT
    && TARGET_SOFT_FLOAT"
   "*
 {
 }")
 
 (define_insn ""
-  [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand"
-                         "=f,r,f,r,RQ,Q")
+  [(set (match_operand:SF 0 "move_dest_operand"
+                         "=f,!*r,f,*r,Q,Q")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
-                         "fG,rG,RQ,RQ,f,rG"))]
+                         "fG,!*rG,RQ,RQ,f,*rG"))]
   "(register_operand (operands[0], SFmode)
     || reg_or_0_operand (operands[1], SFmode))
-   && ! TARGET_SOFT_FLOAT"
+   && !TARGET_SOFT_FLOAT"
   "@
    fcpy,sgl %f1,%0
    copy %r1,%0
    fldw%F1 %1,%0
    ldw%M1 %1,%0
-   fstw%F0 %r1,%0
+   fstw%F0 %1,%0
    stw%M0 %r1,%0"
   [(set_attr "type" "fpalu,move,fpload,load,fpstore,store")
    (set_attr "pa_combine_type" "addmove")
    (set_attr "length" "4,4,4,4,4,4")])
 
 (define_insn ""
-  [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand"
+  [(set (match_operand:SF 0 "indexed_memory_operand" "=R")
+       (match_operand:SF 1 "register_operand" "f"))]
+  "!TARGET_SOFT_FLOAT
+   && !TARGET_DISABLE_INDEXING
+   && reload_completed"
+  "fstw%F0 %1,%0"
+  [(set_attr "type" "fpstore")
+   (set_attr "pa_combine_type" "addmove")
+   (set_attr "length" "4")])
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 4))
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 2 "register_operand" "")
+                (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (const_int 4))))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:SI (mult:SI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 4))
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 2 "register_operand" "")
+                (mult:DI (match_operand:DI 1 "register_operand" "")
+                         (const_int 4))))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:DI (mult:DI (match_dup 1) (const_int 4)) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (const_int 4))
+                              (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:SI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_operand:SI 1 "register_operand" "")
+                (match_operand:SI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:SI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[1])
+   && (TARGET_NO_SPACE_REGS
+       || (!REG_POINTER (operands[1]) && REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:DI (match_dup 1) (match_dup 2)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+  "")
+
+(define_peephole2
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "register_operand" "")))
+   (set (mem:SF (match_dup 0))
+        (match_operand:SF 3 "register_operand" ""))]
+  "!TARGET_SOFT_FLOAT
+   && TARGET_64BIT
+   && REG_OK_FOR_BASE_P (operands[2])
+   && (TARGET_NO_SPACE_REGS
+       || (REG_POINTER (operands[1]) && !REG_POINTER (operands[2])))
+   && FP_REGNO_P (REGNO (operands[3]))"
+  [(set (mem:SF (plus:DI (match_dup 2) (match_dup 1)))
+       (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 2) (match_dup 1)))]
+  "")
+
+(define_insn ""
+  [(set (match_operand:SF 0 "move_dest_operand"
                          "=r,r,Q")
        (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
                          "rG,RQ,rG"))]
    (set_attr "pa_combine_type" "addmove")
    (set_attr "length" "4,4,4")])
 
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=fx")
-       (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fldwx|fldw} %2(%1),%0"
-  [(set_attr "type" "fpload")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (match_operand:SF 0 "register_operand" "=fx")
-       (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r"))))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fldwx|fldw} %1(%2),%0"
-  [(set_attr "type" "fpload")
-   (set_attr "length" "4")])
-
-(define_insn ""
-  [(set (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
-                        (match_operand:SI 2 "register_operand" "r")))
-      (match_operand:SF 0 "register_operand" "fx"))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fstwx|fstw} %0,%2(%1)"
-  [(set_attr "type" "fpstore")
-   (set_attr "length" "4")])
-\f
-(define_insn ""
-  [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r")
-                        (match_operand:SI 2 "basereg_operand" "r")))
-      (match_operand:SF 0 "register_operand" "fx"))]
-  "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
-  "{fstwx|fstw} %0,%1(%2)"
-  [(set_attr "type" "fpstore")
-   (set_attr "length" "4")])
 \f
 
 ;;- zero extension instructions
 ;; memory operands.  This gives us better overall code than just
 ;; having a pattern that does or does not accept memory operands.
 
-(define_expand "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "")
-       (zero_extend:SI
-        (match_operand:HI 1 "register_operand" "")))]
-  ""
-  "")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (zero_extend:SI
-        (match_operand:HI 1 "move_operand" "r,RQ")))]
-  "GET_CODE (operands[1]) != CONST_INT"
-  "@
-   {extru|extrw,u} %1,31,16,%0
-   ldh%M1 %1,%0"
-  [(set_attr "type" "shift,load")
-   (set_attr "length" "4,4")])
-
 (define_expand "zero_extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "")
        (zero_extend:HI
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (zero_extend:HI
-        (match_operand:QI 1 "move_operand" "r,RQ")))]
+        (match_operand:QI 1 "move_src_operand" "r,RQ")))]
   "GET_CODE (operands[1]) != CONST_INT"
   "@
    {extru|extrw,u} %1,31,8,%0
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (zero_extend:SI
-        (match_operand:QI 1 "move_operand" "r,RQ")))]
+        (match_operand:QI 1 "move_src_operand" "r,RQ")))]
   "GET_CODE (operands[1]) != CONST_INT"
   "@
    {extru|extrw,u} %1,31,8,%0
   [(set_attr "type" "shift,load")
    (set_attr "length" "4,4")])
 
-(define_insn "zero_extendqidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))]
+(define_expand "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (zero_extend:SI
+        (match_operand:HI 1 "register_operand" "")))]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (zero_extend:SI
+        (match_operand:HI 1 "move_src_operand" "r,RQ")))]
+  "GET_CODE (operands[1]) != CONST_INT"
+  "@
+   {extru|extrw,u} %1,31,16,%0
+   ldh%M1 %1,%0"
+  [(set_attr "type" "shift,load")
+   (set_attr "length" "4,4")])
+
+(define_expand "zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI
+        (match_operand:QI 1 "register_operand" "")))]
   "TARGET_64BIT"
-  "extrd,u %1,63,8,%0"
-  [(set_attr "type" "shift") 
-  (set_attr "length" "4")])
+  "")
 
-(define_insn "zero_extendhidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+        (match_operand:QI 1 "move_src_operand" "r,RQ")))]
+  "TARGET_64BIT && GET_CODE (operands[1]) != CONST_INT"
+  "@
+   extrd,u %1,63,8,%0
+   ldb%M1 %1,%0"
+  [(set_attr "type" "shift,load")
+   (set_attr "length" "4,4")])
+
+(define_expand "zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI
+        (match_operand:HI 1 "register_operand" "")))]
   "TARGET_64BIT"
-  "extrd,u %1,63,16,%0"
-  [(set_attr "type" "shift") 
-  (set_attr "length" "4")])
+  "")
 
-(define_insn "zero_extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+        (match_operand:HI 1 "move_src_operand" "r,RQ")))]
+  "TARGET_64BIT && GET_CODE (operands[1]) != CONST_INT"
+  "@
+   extrd,u %1,63,16,%0
+   ldh%M1 %1,%0"
+  [(set_attr "type" "shift,load")
+   (set_attr "length" "4,4")])
+
+(define_expand "zero_extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI
+        (match_operand:SI 1 "register_operand" "")))]
   "TARGET_64BIT"
-  "extrd,u %1,63,32,%0"
-  [(set_attr "type" "shift") 
-  (set_attr "length" "4")])
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+        (match_operand:SI 1 "move_src_operand" "r,RQ")))]
+  "TARGET_64BIT && GET_CODE (operands[1]) != CONST_INT"
+  "@
+   extrd,u %1,63,32,%0
+   ldw%M1 %1,%0"
+  [(set_attr "type" "shift,load")
+   (set_attr "length" "4,4")])
 
 ;;- sign extension instructions
 
                 (match_operand:DI 2 "arith_operand" "r,J")))]
   "TARGET_64BIT"
   "@
-   {addl|add,l} %1,%2,%0
+   add,l %1,%2,%0
    ldo %2(%1),%0"
   [(set_attr "type" "binary,binary")
    (set_attr "pa_combine_type" "addmove")
 
 ;; The mulsi3 insns set up registers for the millicode call.
 (define_expand "mulsi3"
-  [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
-   (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
+  [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
+   (set (reg:SI 25) (match_operand:SI 2 "move_src_operand" ""))
    (parallel [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25)))
              (clobber (match_dup 3))
              (clobber (reg:SI 26))
   "
 {
   operands[4] = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
-  if (TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT)
+  if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
     {
       rtx scratch = gen_reg_rtx (DImode);
       operands[1] = force_reg (SImode, operands[1]);
       operands[2] = force_reg (SImode, operands[2]);
       emit_insn (gen_umulsidi3 (scratch, operands[1], operands[2]));
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-                             gen_rtx_SUBREG (SImode, scratch, GET_MODE_SIZE (SImode))));
+      emit_insn (gen_movsi (operands[0],
+                           gen_rtx_SUBREG (SImode, scratch,
+                                           GET_MODE_SIZE (SImode))));
       DONE;
     }
   operands[3] = gen_reg_rtx (SImode);
 
 ;;; Division and mod.
 (define_expand "divsi3"
-  [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
-   (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
+  [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
+   (set (reg:SI 25) (match_operand:SI 2 "move_src_operand" ""))
    (parallel [(set (reg:SI 29) (div:SI (reg:SI 26) (reg:SI 25)))
              (clobber (match_dup 3))
              (clobber (match_dup 4))
    (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
 
 (define_expand "udivsi3"
-  [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
-   (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
+  [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
+   (set (reg:SI 25) (match_operand:SI 2 "move_src_operand" ""))
    (parallel [(set (reg:SI 29) (udiv:SI (reg:SI 26) (reg:SI 25)))
              (clobber (match_dup 3))
              (clobber (match_dup 4))
    (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
 
 (define_expand "modsi3"
-  [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
-   (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
+  [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
+   (set (reg:SI 25) (match_operand:SI 2 "move_src_operand" ""))
    (parallel [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25)))
              (clobber (match_dup 3))
              (clobber (match_dup 4))
    (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
 
 (define_expand "umodsi3"
-  [(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
-   (set (reg:SI 25) (match_operand:SI 2 "move_operand" ""))
+  [(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
+   (set (reg:SI 25) (match_operand:SI 2 "move_src_operand" ""))
    (parallel [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25)))
              (clobber (match_dup 3))
              (clobber (match_dup 4))
@@ -8274,11 +8754,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
 ;; Clean up turds left by reload.
 (define_peephole
-  [(set (match_operand 0 "reg_or_nonsymb_mem_operand" "")
+  [(set (match_operand 0 "move_dest_operand" "")
        (match_operand 1 "register_operand" "fr"))
    (set (match_operand 2 "register_operand" "fr")
        (match_dup 0))]
-  "! TARGET_SOFT_FLOAT
+  "!TARGET_SOFT_FLOAT
    && GET_CODE (operands[0]) == MEM
    && ! MEM_VOLATILE_P (operands[0])
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
@@ -8314,10 +8794,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 
 (define_peephole
   [(set (match_operand 0 "register_operand" "fr")
-       (match_operand 1 "reg_or_nonsymb_mem_operand" ""))
+       (match_operand 1 "move_src_operand" ""))
    (set (match_operand 2 "register_operand" "fr")
        (match_dup 1))]
-  "! TARGET_SOFT_FLOAT
+  "!TARGET_SOFT_FLOAT
    && GET_CODE (operands[1]) == MEM
    && ! MEM_VOLATILE_P (operands[1])
    && GET_MODE (operands[0]) == GET_MODE (operands[1])