OSDN Git Service

2004-07-19 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / pa.c
index e7b0b8a..bd8b0a4 100644 (file)
@@ -1,22 +1,22 @@
 /* Subroutines for insn-output.c for HPPA.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003 Free Software Foundation, Inc.
+   2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
+along with GCC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
@@ -37,11 +37,9 @@ Boston, MA 02111-1307, USA.  */
 #include "except.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "reload.h"
 #include "integrate.h"
 #include "function.h"
-#include "obstack.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "recog.h"
@@ -50,22 +48,10 @@ Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "target-def.h"
 
-static int hppa_use_dfa_pipeline_interface PARAMS ((void));
-
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE 
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hppa_use_dfa_pipeline_interface
-
-static int
-hppa_use_dfa_pipeline_interface ()
-{
-  return 1;
-}
-
 /* Return nonzero if there is a bypass for the output of 
    OUT_INSN and the fp store IN_INSN.  */
 int
-hppa_fpstore_bypass_p (out_insn, in_insn)
-     rtx out_insn, in_insn;
+hppa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
 {
   enum machine_mode store_mode;
   enum machine_mode other_mode;
@@ -96,79 +82,94 @@ hppa_fpstore_bypass_p (out_insn, in_insn)
 #endif
 #endif
 
-static int hppa_address_cost PARAMS ((rtx));
-static bool hppa_rtx_costs PARAMS ((rtx, int, int, int *));
-static inline rtx force_mode PARAMS ((enum machine_mode, rtx));
-static void pa_reorg PARAMS ((void));
-static void pa_combine_instructions PARAMS ((void));
-static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
-static int forward_branch_p PARAMS ((rtx));
-static int shadd_constant_p PARAMS ((int));
-static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
-static int compute_movstrsi_length PARAMS ((rtx));
-static bool pa_assemble_integer PARAMS ((rtx, unsigned int, int));
-static void remove_useless_addtr_insns PARAMS ((int));
-static void store_reg PARAMS ((int, int, int));
-static void store_reg_modify PARAMS ((int, int, int));
-static void load_reg PARAMS ((int, int, int));
-static void set_reg_plus_d PARAMS ((int, int, int, int));
-static void pa_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-static void update_total_code_bytes PARAMS ((int));
-static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static int pa_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static int pa_adjust_priority PARAMS ((rtx, int));
-static int pa_issue_rate PARAMS ((void));
-static void pa_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT))
+static void copy_reg_pointer (rtx, rtx);
+static void fix_range (const char *);
+static int hppa_address_cost (rtx);
+static bool hppa_rtx_costs (rtx, int, int, int *);
+static inline rtx force_mode (enum machine_mode, rtx);
+static void pa_reorg (void);
+static void pa_combine_instructions (void);
+static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx);
+static int forward_branch_p (rtx);
+static int shadd_constant_p (int);
+static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);
+static int compute_movmem_length (rtx);
+static int compute_clrmem_length (rtx);
+static bool pa_assemble_integer (rtx, unsigned int, int);
+static void remove_useless_addtr_insns (int);
+static void store_reg (int, HOST_WIDE_INT, int);
+static void store_reg_modify (int, int, HOST_WIDE_INT);
+static void load_reg (int, HOST_WIDE_INT, int);
+static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
+static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);
+static void update_total_code_bytes (int);
+static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static int pa_adjust_cost (rtx, rtx, rtx, int);
+static int pa_adjust_priority (rtx, int);
+static int pa_issue_rate (void);
+static void pa_select_section (tree, int, unsigned HOST_WIDE_INT)
      ATTRIBUTE_UNUSED;
-static void pa_encode_section_info PARAMS ((tree, rtx, int));
-static const char *pa_strip_name_encoding PARAMS ((const char *));
-static bool pa_function_ok_for_sibcall PARAMS ((tree, tree));
-static void pa_globalize_label PARAMS ((FILE *, const char *))
+static void pa_encode_section_info (tree, rtx, int);
+static const char *pa_strip_name_encoding (const char *);
+static bool pa_function_ok_for_sibcall (tree, tree);
+static void pa_globalize_label (FILE *, const char *)
      ATTRIBUTE_UNUSED;
-static void pa_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                           HOST_WIDE_INT, tree));
+static void pa_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
+                                   HOST_WIDE_INT, tree);
 #if !defined(USE_COLLECT2)
-static void pa_asm_out_constructor PARAMS ((rtx, int));
-static void pa_asm_out_destructor PARAMS ((rtx, int));
+static void pa_asm_out_constructor (rtx, int);
+static void pa_asm_out_destructor (rtx, int);
 #endif
-static void pa_init_builtins PARAMS ((void));
-static void copy_fp_args PARAMS ((rtx)) ATTRIBUTE_UNUSED;
-static int length_fp_args PARAMS ((rtx)) ATTRIBUTE_UNUSED;
-static struct deferred_plabel *get_plabel PARAMS ((const char *))
+static void pa_init_builtins (void);
+static rtx hppa_builtin_saveregs (void);
+static tree hppa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
+static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
+static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
+static struct deferred_plabel *get_plabel (const char *)
      ATTRIBUTE_UNUSED;
-static inline void pa_file_start_level PARAMS ((void)) ATTRIBUTE_UNUSED;
-static inline void pa_file_start_space PARAMS ((int)) ATTRIBUTE_UNUSED;
-static inline void pa_file_start_file PARAMS ((int)) ATTRIBUTE_UNUSED;
-static inline void pa_file_start_mcount PARAMS ((const char*)) ATTRIBUTE_UNUSED;
-static void pa_elf_file_start PARAMS ((void)) ATTRIBUTE_UNUSED;
-static void pa_som_file_start PARAMS ((void)) ATTRIBUTE_UNUSED;
-static void pa_linux_file_start PARAMS ((void)) ATTRIBUTE_UNUSED;
-static void pa_hpux64_gas_file_start PARAMS ((void)) ATTRIBUTE_UNUSED;
-static void pa_hpux64_hpas_file_start PARAMS ((void)) ATTRIBUTE_UNUSED;
-static void output_deferred_plabels PARAMS ((void));
+static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;
+static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED;
+static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED;
+static inline void pa_file_start_mcount (const char*) ATTRIBUTE_UNUSED;
+static void pa_elf_file_start (void) ATTRIBUTE_UNUSED;
+static void pa_som_file_start (void) ATTRIBUTE_UNUSED;
+static void pa_linux_file_start (void) ATTRIBUTE_UNUSED;
+static void pa_hpux64_gas_file_start (void) ATTRIBUTE_UNUSED;
+static void pa_hpux64_hpas_file_start (void) ATTRIBUTE_UNUSED;
+static void output_deferred_plabels (void);
+#ifdef HPUX_LONG_DOUBLE_LIBRARY
+static void pa_hpux_init_libfuncs (void);
+#endif
+static rtx pa_struct_value_rtx (tree, int);
+static bool pa_pass_by_reference (CUMULATIVE_ARGS *ca, enum machine_mode,
+                                 tree, bool);
+
 
 /* Save the operands last given to a compare for use when we
    generate a scc or bcc insn.  */
 rtx hppa_compare_op0, hppa_compare_op1;
 enum cmp_type hppa_branch_type;
 
-/* Which cpu we are scheduling for.  */
-enum processor_type pa_cpu;
-
-/* String to hold which cpu we are scheduling for.  */
-const char *pa_cpu_string;
-
 /* Which architecture we are generating code for.  */
 enum architecture_type pa_arch;
 
 /* String to hold which architecture we are generating code for.  */
 const char *pa_arch_string;
 
+/* String used with the -mfixed-range= option.  */
+const char *pa_fixed_range_string;
+
+/* Which cpu we are scheduling for.  */
+enum processor_type pa_cpu;
+
+/* String to hold which cpu we are scheduling for.  */
+const char *pa_cpu_string;
+
 /* Counts for the number of callee-saved general and floating point
    registers which were saved by the current function's prologue.  */
 static int gr_saved, fr_saved;
 
-static rtx find_addr_reg PARAMS ((rtx));
+static rtx find_addr_reg (rtx);
 
 /* Keep track of the number of bytes we have output in the CODE subspace
    during this compilation so we'll know when to emit inline long-calls.  */
@@ -254,10 +255,107 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG pa_reorg
 
+#ifdef HPUX_LONG_DOUBLE_LIBRARY
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
+#endif
+
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY pa_return_in_memory
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE pa_pass_by_reference
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR hppa_gimplify_va_arg_expr
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
+/* Parse the -mfixed-range= option string.  */
+
+static void
+fix_range (const char *const_str)
+{
+  int i, first, last;
+  char *str, *dash, *comma;
+
+  /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and
+     REG2 are either register names or register numbers.  The effect
+     of this option is to mark the registers in the range from REG1 to
+     REG2 as ``fixed'' so they won't be used by the compiler.  This is
+     used, e.g., to ensure that kernel mode code doesn't use f32-f127.  */
+
+  i = strlen (const_str);
+  str = (char *) alloca (i + 1);
+  memcpy (str, const_str, i + 1);
+
+  while (1)
+    {
+      dash = strchr (str, '-');
+      if (!dash)
+       {
+         warning ("value of -mfixed-range must have form REG1-REG2");
+         return;
+       }
+      *dash = '\0';
+
+      comma = strchr (dash + 1, ',');
+      if (comma)
+       *comma = '\0';
+
+      first = decode_reg_name (str);
+      if (first < 0)
+       {
+         warning ("unknown register name: %s", str);
+         return;
+       }
+
+      last = decode_reg_name (dash + 1);
+      if (last < 0)
+       {
+         warning ("unknown register name: %s", dash + 1);
+         return;
+       }
+
+      *dash = '-';
+
+      if (first > last)
+       {
+         warning ("%s-%s is an empty range", str, dash + 1);
+         return;
+       }
+
+      for (i = first; i <= last; ++i)
+       fixed_regs[i] = call_used_regs[i] = 1;
+
+      if (!comma)
+       break;
+
+      *comma = ',';
+      str = comma + 1;
+    }
+
+  /* Check if all floating point registers have been fixed.  */
+  for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
+    if (!fixed_regs[i])
+      break;
+
+  if (i > FP_REG_LAST)
+    target_flags |= MASK_DISABLE_FPREGS;
+}
+
 void
-override_options ()
+override_options (void)
 {
   if (pa_cpu_string == NULL)
     pa_cpu_string = TARGET_SCHED_DEFAULT;
@@ -297,7 +395,7 @@ override_options ()
       warning ("unknown -mschedule= option (%s).\nValid options are 700, 7100, 7100LC, 7200, 7300, and 8000\n", pa_cpu_string);
     }
 
-  /* Set the instruction set architecture.  */
+  /* Set the instruction architecture.  */
   if (pa_arch_string && ! strcmp (pa_arch_string, "1.0"))
     {
       pa_arch_string = "1.0";
@@ -322,6 +420,9 @@ override_options ()
       warning ("unknown -march= option (%s).\nValid options are 1.0, 1.1, and 2.0\n", pa_arch_string);
     }
 
+  if (pa_fixed_range_string)
+    fix_range (pa_fixed_range_string);
+
   /* Unconditional branches in the delay slot are not compatible with dwarf2
      call frame information.  There is no benefit in using this optimization
      on PA8000 and later processors.  */
@@ -366,7 +467,7 @@ override_options ()
 }
 
 static void
-pa_init_builtins ()
+pa_init_builtins (void)
 {
 #ifdef DONT_HAVE_FPUTC_UNLOCKED
   built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] = NULL_TREE;
@@ -374,12 +475,20 @@ pa_init_builtins ()
 #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
-reg_or_0_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+reg_or_0_operand (rtx op, enum machine_mode mode)
 {
   return (op == CONST0_RTX (mode) || register_operand (op, mode));
 }
@@ -390,9 +499,7 @@ reg_or_0_operand (op, mode)
    For 2.5 try to eliminate either call_operand_address or
    function_label_operand, they perform very similar functions.  */
 int
-call_operand_address (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+call_operand_address (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_MODE (op) == word_mode
          && CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME);
@@ -402,8 +509,7 @@ call_operand_address (op, mode)
    expressions will have one of a few well defined forms, so
    we need only check those forms.  */
 int
-symbolic_expression_p (x)
-     register rtx x;
+symbolic_expression_p (rtx x)
 {
 
   /* Strip off any HIGH.  */
@@ -414,9 +520,7 @@ symbolic_expression_p (x)
 }
 
 int
-symbolic_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   switch (GET_CODE (op))
     {
@@ -437,9 +541,7 @@ symbolic_operand (op, mode)
    operand of mode MODE.  */
 
 int
-symbolic_memory_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
@@ -450,30 +552,11 @@ symbolic_memory_operand (op, mode)
          || 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 (op, mode)
-    register 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.  */
 
 int
-reg_or_0_or_nonsymb_mem_operand (op, mode)
-    register rtx op;
-    enum machine_mode mode;
+reg_or_0_or_nonsymb_mem_operand (rtx op, enum machine_mode mode)
 {
   if (register_operand (op, mode))
     return 1;
@@ -481,10 +564,24 @@ reg_or_0_or_nonsymb_mem_operand (op, 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
@@ -494,9 +591,7 @@ reg_or_0_or_nonsymb_mem_operand (op, mode)
    if reload didn't find a hard register for the operand.  */
 
 int
-reg_before_reload_operand (op, mode)
-    register rtx op;
-    enum machine_mode mode;
+reg_before_reload_operand (rtx op, enum machine_mode mode)
 {
   /* Don't accept a SUBREG since it will need a reload.  */
   if (GET_CODE (op) == SUBREG)
@@ -507,7 +602,7 @@ reg_before_reload_operand (op, mode)
 
   if (reload_completed
       && memory_operand (op, mode)
-      && ! symbolic_memory_operand (op, mode))
+      && !symbolic_memory_operand (op, mode))
     return 1;
 
   return 0;
@@ -516,8 +611,7 @@ reg_before_reload_operand (op, mode)
 /* Accept any constant that can be moved in one instruction into a
    general register.  */
 int
-cint_ok_for_move (intval)
-     HOST_WIDE_INT intval;
+cint_ok_for_move (HOST_WIDE_INT intval)
 {
   /* OK if ldo, ldil, or zdepi, can be used.  */
   return (CONST_OK_FOR_LETTER_P (intval, 'J')
@@ -525,79 +619,117 @@ cint_ok_for_move (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
-move_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+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_CODE (op) == CONSTANT_P_RTX)
+  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_src_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));
 
+  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);
+  /* 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;
 
-  /* 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;
+  return memory_address_p (mode, XEXP (op, 0));
+}
 
-  /* 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;
+/* Accept anything that can be used as the source operand for a prefetch
+   instruction.  */
+int
+prefetch_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) != MEM)
+    return 0;
+
+  /* Until problems with management of the REG_POINTER flag are resolved,
+     we need to delay creating prefetch 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
    general register.  */
 int
-reg_or_cint_move_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+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
-pic_label_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+pic_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (!flag_pic)
     return 0;
@@ -616,9 +748,7 @@ pic_label_operand (op, mode)
 }
 
 int
-fp_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+fp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return reg_renumber && FP_REG_P (op);
 }
@@ -629,9 +759,7 @@ fp_reg_operand (op, mode)
    three operand arithmetic insn that accepts registers of mode MODE
    or 14-bit signed integers.  */
 int
-arith_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
@@ -641,9 +769,7 @@ arith_operand (op, mode)
    three operand arithmetic insn that accepts registers of mode MODE
    or 11-bit signed integers.  */
 int
-arith11_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith11_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
@@ -652,9 +778,7 @@ arith11_operand (op, mode)
 /* Return truth value of whether OP can be used as an operand in a
    adddi3 insn.  */
 int
-adddi3_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+adddi3_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT
@@ -664,9 +788,7 @@ adddi3_operand (op, mode)
 /* A constant integer suitable for use in a PRE_MODIFY memory
    reference.  */
 int
-pre_cint_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+pre_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT
          && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10);
@@ -675,18 +797,14 @@ pre_cint_operand (op, mode)
 /* A constant integer suitable for use in a POST_MODIFY memory
    reference.  */
 int
-post_cint_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+post_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT
          && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10);
 }
 
 int
-arith_double_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_double_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode)
          || (GET_CODE (op) == CONST_DOUBLE
@@ -701,9 +819,7 @@ arith_double_operand (op, mode)
    is an integer register.  */
 
 int
-ireg_or_int5_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+ireg_or_int5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op))
          || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32));
@@ -711,9 +827,7 @@ ireg_or_int5_operand (op, mode)
 
 /* Return nonzero if OP is an integer register, else return zero.  */
 int
-ireg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+ireg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32);
 }
@@ -722,33 +836,25 @@ ireg_operand (op, mode)
    range constraining immediate operands in three-address insns.  */
 
 int
-int5_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+int5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
 }
 
 int
-uint5_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+uint5_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
 }
 
 int
-int11_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+int11_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
 }
 
 int
-uint32_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+uint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
 #if HOST_BITS_PER_WIDE_INT > 32
   /* All allowed constants will fit a CONST_INT.  */
@@ -762,9 +868,7 @@ uint32_operand (op, mode)
 }
 
 int
-arith5_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith5_operand (rtx op, enum machine_mode mode)
 {
   return register_operand (op, mode) || int5_operand (op, mode);
 }
@@ -773,8 +877,7 @@ arith5_operand (op, mode)
    zdepi first sign extends a 5 bit signed number to a given field
    length, then places this field anywhere in a zero.  */
 int
-zdepi_cint_p (x)
-     unsigned HOST_WIDE_INT x;
+zdepi_cint_p (unsigned HOST_WIDE_INT x)
 {
   unsigned HOST_WIDE_INT lsb_mask, t;
 
@@ -792,8 +895,7 @@ zdepi_cint_p (x)
    1....10....0
    1..10..01..1  */
 int
-and_mask_p (mask)
-     unsigned HOST_WIDE_INT mask;
+and_mask_p (unsigned HOST_WIDE_INT mask)
 {
   mask = ~mask;
   mask += mask & -mask;
@@ -802,9 +904,7 @@ and_mask_p (mask)
 
 /* True iff depi or extru can be used to compute (reg & OP).  */
 int
-and_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+and_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode)
          || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op))));
@@ -812,8 +912,7 @@ and_operand (op, mode)
 
 /* True iff depi can be used to compute (reg | MASK).  */
 int
-ior_mask_p (mask)
-     unsigned HOST_WIDE_INT mask;
+ior_mask_p (unsigned HOST_WIDE_INT mask)
 {
   mask += mask & -mask;
   return (mask & (mask - 1)) == 0;
@@ -821,17 +920,13 @@ ior_mask_p (mask)
 
 /* True iff depi can be used to compute (reg | OP).  */
 int
-ior_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+ior_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op)));
 }
 
 int
-lhs_lshift_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+lhs_lshift_operand (rtx op, enum machine_mode mode)
 {
   return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode);
 }
@@ -840,9 +935,7 @@ lhs_lshift_operand (op, mode)
    Such values can be the left hand side x in (x << r), using the zvdepi
    instruction.  */
 int
-lhs_lshift_cint_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+lhs_lshift_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   unsigned HOST_WIDE_INT x;
   if (GET_CODE (op) != CONST_INT)
@@ -852,17 +945,13 @@ lhs_lshift_cint_operand (op, mode)
 }
 
 int
-arith32_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith32_operand (rtx op, enum machine_mode mode)
 {
   return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
 }
 
 int
-pc_or_label_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+pc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
 }
@@ -873,9 +962,7 @@ pc_or_label_operand (op, mode)
    than one register, we lose.  */
 
 rtx
-legitimize_pic_address (orig, mode, reg)
-     rtx orig, reg;
-     enum machine_mode mode;
+legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
 {
   rtx pic_ref = orig;
 
@@ -891,28 +978,43 @@ legitimize_pic_address (orig, mode, 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;
     }
   if (GET_CODE (orig) == SYMBOL_REF)
     {
+      rtx insn, tmp_reg;
+
       if (reg == 0)
        abort ();
 
-      emit_move_insn (reg,
+      /* Before reload, allocate a temporary register for the intermediate
+        result.  This allows the sequence to be deleted when the final
+        result is unused and the insns are trivially dead.  */
+      tmp_reg = ((reload_in_progress || reload_completed)
+                ? reg : gen_reg_rtx (Pmode));
+
+      emit_move_insn (tmp_reg,
                      gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
                                    gen_rtx_HIGH (word_mode, orig)));
       pic_ref
        = gen_rtx_MEM (Pmode,
-                      gen_rtx_LO_SUM (Pmode, reg,
+                      gen_rtx_LO_SUM (Pmode, tmp_reg,
                                       gen_rtx_UNSPEC (Pmode,
                                                       gen_rtvec (1, orig),
-                                                      0)));
+                                                      UNSPEC_DLTIND14R)));
 
       current_function_uses_pic_offset_table = 1;
+      MEM_NOTRAP_P (pic_ref) = 1;
       RTX_UNCHANGING_P (pic_ref) = 1;
-      emit_move_insn (reg, pic_ref);
+      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.  */
+      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn));
+
       return reg;
     }
   else if (GET_CODE (orig) == CONST)
@@ -932,7 +1034,9 @@ legitimize_pic_address (orig, mode, 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))
@@ -942,6 +1046,7 @@ legitimize_pic_address (orig, mode, reg)
       pic_ref = gen_rtx_PLUS (Pmode, base, orig);
       /* Likewise, should we set special REG_NOTEs here?  */
     }
+
   return pic_ref;
 }
 
@@ -997,12 +1102,23 @@ legitimize_pic_address (orig, mode, reg)
    a register.  */
 
 rtx
-hppa_legitimize_address (x, oldx, mode)
-     rtx x, oldx ATTRIBUTE_UNUSED;
-     enum machine_mode mode;
+hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+                        enum machine_mode mode)
 {
   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));
 
@@ -1081,7 +1197,7 @@ hppa_legitimize_address (x, oldx, mode)
   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
       && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
-      && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
+      && (OBJECT_P (XEXP (x, 1))
          || GET_CODE (XEXP (x, 1)) == SUBREG)
       && GET_CODE (XEXP (x, 1)) != CONST)
     {
@@ -1347,8 +1463,7 @@ hppa_legitimize_address (x, oldx, mode)
    as GO_IF_LEGITIMATE_ADDRESS.  */
 
 static int
-hppa_address_cost (X)
-     rtx X;
+hppa_address_cost (rtx X)
 {
   switch (GET_CODE (X))
     {
@@ -1368,10 +1483,7 @@ hppa_address_cost (X)
    scanned.  In either case, *TOTAL contains the cost result.  */
 
 static bool
-hppa_rtx_costs (x, code, outer_code, total)
-     rtx x;
-     int code, outer_code;
-     int *total;
+hppa_rtx_costs (rtx x, int code, int outer_code, int *total)
 {
   switch (code)
     {
@@ -1447,9 +1559,7 @@ hppa_rtx_costs (x, code, outer_code, total)
 /* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a
    new rtx with the correct mode.  */
 static inline rtx
-force_mode (mode, orig)
-     enum machine_mode mode;
-     rtx orig;
+force_mode (enum machine_mode mode, rtx orig)
 {
   if (mode == GET_MODE (orig))
     return orig;
@@ -1467,19 +1577,46 @@ force_mode (mode, orig)
    normally.
 
    Note SCRATCH_REG may not be in the proper mode depending on how it
-   will be used.  This routine is resposible for creating a new copy
+   will be used.  This routine is responsible for creating a new copy
    of SCRATCH_REG in the proper mode.  */
 
 int
-emit_move_sequence (operands, mode, scratch_reg)
-     rtx *operands;
-     enum machine_mode mode;
-     rtx scratch_reg;
+emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
 {
   register rtx operand0 = operands[0];
   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 opportunities 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)
@@ -1518,21 +1655,25 @@ emit_move_sequence (operands, mode, 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)))
     operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
 
   /* Handle secondary reloads for loads/stores of FP registers from
-     REG+D addresses where D does not fit in 5 bits, including
+     REG+D addresses where D does not fit in 5 or 14 bits, including
      (subreg (mem (addr))) cases.  */
-  if (fp_reg_operand (operand0, mode)
+  if (scratch_reg
+      && fp_reg_operand (operand0, mode)
       && ((GET_CODE (operand1) == MEM
-          && ! memory_address_p (DFmode, XEXP (operand1, 0)))
+          && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
+                                XEXP (operand1, 0)))
          || ((GET_CODE (operand1) == SUBREG
               && GET_CODE (XEXP (operand1, 0)) == MEM
-              && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
-      && scratch_reg)
+              && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                     ? SFmode : DFmode),
+                                    XEXP (XEXP (operand1, 0), 0))))))
     {
       if (GET_CODE (operand1) == SUBREG)
        operand1 = XEXP (operand1, 0);
@@ -1547,10 +1688,11 @@ emit_move_sequence (operands, mode, 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));
@@ -1558,13 +1700,17 @@ emit_move_sequence (operands, mode, scratch_reg)
                              gen_rtx_MEM (mode, scratch_reg)));
       return 1;
     }
-  else if (fp_reg_operand (operand1, mode)
+  else if (scratch_reg
+          && fp_reg_operand (operand1, mode)
           && ((GET_CODE (operand0) == MEM
-               && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+               && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                       ? SFmode : DFmode),
+                                      XEXP (operand0, 0)))
               || ((GET_CODE (operand0) == SUBREG)
                   && GET_CODE (XEXP (operand0, 0)) == MEM
-                  && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
-          && scratch_reg)
+                  && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                         ? SFmode : DFmode),
+                                        XEXP (XEXP (operand0, 0), 0)))))
     {
       if (GET_CODE (operand0) == SUBREG)
        operand0 = XEXP (operand0, 0);
@@ -1595,15 +1741,15 @@ emit_move_sequence (operands, mode, scratch_reg)
   /* Handle secondary reloads for loads of FP registers from constant
      expressions by forcing the constant into memory.
 
-     use scratch_reg to hold the address of the memory location.
+     Use scratch_reg to hold the address of the memory location.
 
      The proper fix is to change PREFERRED_RELOAD_CLASS to return
      NO_REGS when presented with a const_int and a register class
      containing only FP registers.  Doing so unfortunately creates
      more problems than it solves.   Fix this for 2.5.  */
-  else if (fp_reg_operand (operand0, mode)
+  else if (scratch_reg
           && CONSTANT_P (operand1)
-          && scratch_reg)
+          && fp_reg_operand (operand0, mode))
     {
       rtx xoperands[2];
 
@@ -1625,14 +1771,14 @@ emit_move_sequence (operands, mode, scratch_reg)
     }
   /* Handle secondary reloads for SAR.  These occur when trying to load
      the SAR from memory, FP register, or with a constant.  */
-  else if (GET_CODE (operand0) == REG
+  else if (scratch_reg
+          && GET_CODE (operand0) == REG
           && REGNO (operand0) < FIRST_PSEUDO_REGISTER
           && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
           && (GET_CODE (operand1) == MEM
               || GET_CODE (operand1) == CONST_INT
               || (GET_CODE (operand1) == REG
-                  && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
-          && scratch_reg)
+                  && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))))
     {
       /* D might not fit in 14 bits either; for such cases load D into
         scratch reg.  */
@@ -1675,7 +1821,7 @@ emit_move_sequence (operands, mode, 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)
@@ -1687,7 +1833,67 @@ emit_move_sequence (operands, mode, 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;
        }
@@ -1829,11 +2035,14 @@ emit_move_sequence (operands, mode, scratch_reg)
                  operands[1] = force_const_mem (mode, operand1);
                  operands[1] = legitimize_pic_address (XEXP (operands[1], 0),
                                                        mode, temp);
+                 operands[1] = gen_rtx_MEM (mode, operands[1]);
                  emit_move_sequence (operands, mode, temp);
                }
              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]));
                }
            }
@@ -1861,9 +2070,10 @@ emit_move_sequence (operands, mode, 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
@@ -1880,16 +2090,22 @@ emit_move_sequence (operands, mode, scratch_reg)
          return 1;
        }
       else if (GET_CODE (operand1) != CONST_INT
-              || ! cint_ok_for_move (INTVAL (operand1)))
+              || !cint_ok_for_move (INTVAL (operand1)))
        {
-         rtx extend = NULL_RTX;
-         rtx temp;
+         rtx insn, temp;
+         rtx op1 = operand1;
+         HOST_WIDE_INT value = 0;
+         HOST_WIDE_INT insv = 0;
+         int insert = 0;
 
-         if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT
+         if (GET_CODE (operand1) == CONST_INT)
+           value = INTVAL (operand1);
+
+         if (TARGET_64BIT
+             && GET_CODE (operand1) == CONST_INT
              && HOST_BITS_PER_WIDE_INT > 32
              && GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)
            {
-             HOST_WIDE_INT val = INTVAL (operand1);
              HOST_WIDE_INT nval;
 
              /* Extract the low order 32 bits of the value and sign extend.
@@ -1897,19 +2113,21 @@ emit_move_sequence (operands, mode, scratch_reg)
                 can use the original value as-is.  If the new value is
                 different, we use it and insert the most-significant 32-bits
                 of the original value into the final result.  */
-             nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))
+             nval = ((value & (((HOST_WIDE_INT) 2 << 31) - 1))
                      ^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
-             if (val != nval)
+             if (value != nval)
                {
 #if HOST_BITS_PER_WIDE_INT > 32
-                 extend = GEN_INT (val >> 32);
+                 insv = value >= 0 ? value >> 32 : ~(~value >> 32);
 #endif
+                 insert = 1;
+                 value = nval;
                  operand1 = GEN_INT (nval);
                }
            }
 
          if (reload_in_progress || reload_completed)
-           temp = operand0;
+           temp = scratch_reg ? scratch_reg : operand0;
          else
            temp = gen_reg_rtx (mode);
 
@@ -1917,7 +2135,8 @@ emit_move_sequence (operands, mode, scratch_reg)
             because PLUS uses an 11-bit immediate and the insn sequence
             generated is not as efficient as the one using HIGH/LO_SUM.  */
          if (GET_CODE (operand1) == CONST_INT
-             && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+             && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+             && !insert)
            {
              /* Directly break constant into high and low parts.  This
                 provides better optimization opportunities because various
@@ -1925,7 +2144,6 @@ emit_move_sequence (operands, mode, scratch_reg)
                 We use a 14-bit signed low part except when the addition
                 of 0x4000 to the high part might change the sign of the
                 high part.  */
-             HOST_WIDE_INT value = INTVAL (operand1);
              HOST_WIDE_INT low = value & 0x3fff;
              HOST_WIDE_INT high = value & ~ 0x3fff;
 
@@ -1949,11 +2167,60 @@ emit_move_sequence (operands, mode, scratch_reg)
              operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
            }
 
-         emit_move_insn (operands[0], operands[1]);
+         insn = emit_move_insn (operands[0], operands[1]);
+
+         /* Now insert the most significant 32 bits of the value
+            into the register.  When we don't have a second register
+            available, it could take up to nine instructions to load
+            a 64-bit integer constant.  Prior to reload, we force
+            constants that would take more than three instructions
+            to load to the constant pool.  During and after reload,
+            we have to handle all possible values.  */
+         if (insert)
+           {
+             /* Use a HIGH/LO_SUM/INSV sequence if we have a second
+                register and the value to be inserted is outside the
+                range that can be loaded with three depdi instructions.  */
+             if (temp != operand0 && (insv >= 16384 || insv < -16384))
+               {
+                 operand1 = GEN_INT (insv);
 
-         if (extend != NULL_RTX)
-           emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
-                                extend));
+                 emit_insn (gen_rtx_SET (VOIDmode, temp,
+                                         gen_rtx_HIGH (mode, operand1)));
+                 emit_move_insn (temp, gen_rtx_LO_SUM (mode, temp, operand1));
+                 emit_insn (gen_insv (operand0, GEN_INT (32),
+                                      const0_rtx, temp));
+               }
+             else
+               {
+                 int len = 5, pos = 27;
+
+                 /* Insert the bits using the depdi instruction.  */
+                 while (pos >= 0)
+                   {
+                     HOST_WIDE_INT v5 = ((insv & 31) ^ 16) - 16;
+                     HOST_WIDE_INT sign = v5 < 0;
+
+                     /* Left extend the insertion.  */
+                     insv = (insv >= 0 ? insv >> len : ~(~insv >> len));
+                     while (pos > 0 && (insv & 1) == sign)
+                       {
+                         insv = (insv >= 0 ? insv >> 1 : ~(~insv >> 1));
+                         len += 1;
+                         pos -= 1;
+                       }
+
+                     emit_insn (gen_insv (operand0, GEN_INT (len),
+                                          GEN_INT (pos), GEN_INT (v5)));
+
+                     len = pos > 0 && pos < 5 ? pos : 5;
+                     pos -= len;
+                   }
+               }
+           }
+
+         REG_NOTES (insn)
+           = gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (insn));
 
          return 1;
        }
@@ -1966,8 +2233,7 @@ emit_move_sequence (operands, mode, scratch_reg)
    it will need a link/runtime reloc).  */
 
 int
-reloc_needed (exp)
-     tree exp;
+reloc_needed (tree exp)
 {
   int reloc = 0;
 
@@ -2011,9 +2277,7 @@ reloc_needed (exp)
    will be true.  */
 
 int
-read_only_operand (operand, mode)
-     rtx operand;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+read_only_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (GET_CODE (operand) == CONST)
     operand = XEXP (XEXP (operand, 0), 0);
@@ -2032,10 +2296,9 @@ read_only_operand (operand, mode)
 
 \f
 /* Return the best assembler insn template
-   for moving operands[1] into operands[0] as a fullword.   */
+   for moving operands[1] into operands[0] as a fullword.  */
 const char *
-singlemove_string (operands)
-     rtx *operands;
+singlemove_string (rtx *operands)
 {
   HOST_WIDE_INT intval;
 
@@ -2080,9 +2343,7 @@ singlemove_string (operands)
    useful for copying IMM to a register using the zdepi
    instructions.  Store the immediate value to insert in OP[0].  */
 static void
-compute_zdepwi_operands (imm, op)
-     unsigned HOST_WIDE_INT imm;
-     unsigned *op;
+compute_zdepwi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
 {
   int lsb, len;
 
@@ -2119,9 +2380,7 @@ compute_zdepwi_operands (imm, op)
    useful for copying IMM to a register using the depdi,z
    instructions.  Store the immediate value to insert in OP[0].  */
 void
-compute_zdepdi_operands (imm, op)
-     unsigned HOST_WIDE_INT imm;
-     unsigned *op;
+compute_zdepdi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
 {
   HOST_WIDE_INT lsb, len;
 
@@ -2159,8 +2418,7 @@ compute_zdepdi_operands (imm, op)
    with operands OPERANDS.  */
 
 const char *
-output_move_double (operands)
-     rtx *operands;
+output_move_double (rtx *operands)
 {
   enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
   rtx latehalf[2];
@@ -2435,8 +2693,7 @@ output_move_double (operands)
 }
 \f
 const char *
-output_fp_move_double (operands)
-     rtx *operands;
+output_fp_move_double (rtx *operands)
 {
   if (FP_REG_P (operands[0]))
     {
@@ -2474,8 +2731,7 @@ output_fp_move_double (operands)
    ADDR can be effectively incremented by incrementing REG.  */
 
 static rtx
-find_addr_reg (addr)
-     rtx addr;
+find_addr_reg (rtx addr)
 {
   while (GET_CODE (addr) == PLUS)
     {
@@ -2500,28 +2756,54 @@ find_addr_reg (addr)
    OPERANDS[0] is the destination pointer as a REG, clobbered.
    OPERANDS[1] is the source pointer as a REG, clobbered.
    OPERANDS[2] is a register for temporary storage.
-   OPERANDS[4] is the size as a CONST_INT
    OPERANDS[3] is a register for temporary storage.
+   OPERANDS[4] is the size as a CONST_INT
    OPERANDS[5] is the alignment safe to use, as a CONST_INT.
-   OPERANDS[6] is another temporary register.   */
+   OPERANDS[6] is another temporary register.  */
 
 const char *
-output_block_move (operands, size_is_constant)
-     rtx *operands;
-     int size_is_constant ATTRIBUTE_UNUSED;
+output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
 {
   int align = INTVAL (operands[5]);
   unsigned long n_bytes = INTVAL (operands[4]);
 
-  /* We can't move more than four bytes at a time because the PA
+  /* We can't move more than a word at a time because the PA
      has no longer integer move insns.  (Could use fp mem ops?)  */
-  if (align > 4)
-    align = 4;
+  if (align > (TARGET_64BIT ? 8 : 4))
+    align = (TARGET_64BIT ? 8 : 4);
 
   /* Note that we know each loop below will execute at least twice
      (else we would have open-coded the copy).  */
   switch (align)
     {
+      case 8:
+       /* Pre-adjust the loop counter.  */
+       operands[4] = GEN_INT (n_bytes - 16);
+       output_asm_insn ("ldi %4,%2", operands);
+
+       /* Copying loop.  */
+       output_asm_insn ("ldd,ma 8(%1),%3", operands);
+       output_asm_insn ("ldd,ma 8(%1),%6", operands);
+       output_asm_insn ("std,ma %3,8(%0)", operands);
+       output_asm_insn ("addib,>= -16,%2,.-12", operands);
+       output_asm_insn ("std,ma %6,8(%0)", operands);
+
+       /* Handle the residual.  There could be up to 7 bytes of
+          residual to copy!  */
+       if (n_bytes % 16 != 0)
+         {
+           operands[4] = GEN_INT (n_bytes % 8);
+           if (n_bytes % 16 >= 8)
+             output_asm_insn ("ldd,ma 8(%1),%3", operands);
+           if (n_bytes % 8 != 0)
+             output_asm_insn ("ldd 0(%1),%6", operands);
+           if (n_bytes % 16 >= 8)
+             output_asm_insn ("std,ma %3,8(%0)", operands);
+           if (n_bytes % 8 != 0)
+             output_asm_insn ("stdby,e %6,%4(%0)", operands);
+         }
+       return "";
+
       case 4:
        /* Pre-adjust the loop counter.  */
        operands[4] = GEN_INT (n_bytes - 8);
@@ -2607,8 +2889,7 @@ output_block_move (operands, size_is_constant)
    count insns rather than emit them.  */
 
 static int
-compute_movstrsi_length (insn)
-     rtx insn;
+compute_movmem_length (rtx insn)
 {
   rtx pat = PATTERN (insn);
   unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 7), 0));
@@ -2617,8 +2898,8 @@ compute_movstrsi_length (insn)
 
   /* We can't move more than four bytes at a time because the PA
      has no longer integer move insns.  (Could use fp mem ops?)  */
-  if (align > 4)
-    align = 4;
+  if (align > (TARGET_64BIT ? 8 : 4))
+    align = (TARGET_64BIT ? 8 : 4);
 
   /* The basic copying loop.  */
   n_insns = 6;
@@ -2636,11 +2917,152 @@ compute_movstrsi_length (insn)
   /* Lengths are expressed in bytes now; each insn is 4 bytes.  */
   return n_insns * 4;
 }
+
+/* Emit code to perform a block clear.
+
+   OPERANDS[0] is the destination pointer as a REG, clobbered.
+   OPERANDS[1] is a register for temporary storage.
+   OPERANDS[2] is the size as a CONST_INT
+   OPERANDS[3] is the alignment safe to use, as a CONST_INT.  */
+
+const char *
+output_block_clear (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
+{
+  int align = INTVAL (operands[3]);
+  unsigned long n_bytes = INTVAL (operands[2]);
+
+  /* We can't clear more than a word at a time because the PA
+     has no longer integer move insns.  */
+  if (align > (TARGET_64BIT ? 8 : 4))
+    align = (TARGET_64BIT ? 8 : 4);
+
+  /* Note that we know each loop below will execute at least twice
+     (else we would have open-coded the copy).  */
+  switch (align)
+    {
+      case 8:
+       /* Pre-adjust the loop counter.  */
+       operands[2] = GEN_INT (n_bytes - 16);
+       output_asm_insn ("ldi %2,%1", operands);
+
+       /* Loop.  */
+       output_asm_insn ("std,ma %%r0,8(%0)", operands);
+       output_asm_insn ("addib,>= -16,%1,.-4", operands);
+       output_asm_insn ("std,ma %%r0,8(%0)", operands);
+
+       /* Handle the residual.  There could be up to 7 bytes of
+          residual to copy!  */
+       if (n_bytes % 16 != 0)
+         {
+           operands[2] = GEN_INT (n_bytes % 8);
+           if (n_bytes % 16 >= 8)
+             output_asm_insn ("std,ma %%r0,8(%0)", operands);
+           if (n_bytes % 8 != 0)
+             output_asm_insn ("stdby,e %%r0,%2(%0)", operands);
+         }
+       return "";
+
+      case 4:
+       /* Pre-adjust the loop counter.  */
+       operands[2] = GEN_INT (n_bytes - 8);
+       output_asm_insn ("ldi %2,%1", operands);
+
+       /* Loop.  */
+       output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
+       output_asm_insn ("addib,>= -8,%1,.-4", operands);
+       output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
+
+       /* Handle the residual.  There could be up to 7 bytes of
+          residual to copy!  */
+       if (n_bytes % 8 != 0)
+         {
+           operands[2] = GEN_INT (n_bytes % 4);
+           if (n_bytes % 8 >= 4)
+             output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
+           if (n_bytes % 4 != 0)
+             output_asm_insn ("{stbys|stby},e %%r0,%2(%0)", operands);
+         }
+       return "";
+
+      case 2:
+       /* Pre-adjust the loop counter.  */
+       operands[2] = GEN_INT (n_bytes - 4);
+       output_asm_insn ("ldi %2,%1", operands);
+
+       /* Loop.  */
+       output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
+       output_asm_insn ("addib,>= -4,%1,.-4", operands);
+       output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
+
+       /* Handle the residual.  */
+       if (n_bytes % 4 != 0)
+         {
+           if (n_bytes % 4 >= 2)
+             output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
+           if (n_bytes % 2 != 0)
+             output_asm_insn ("stb %%r0,0(%0)", operands);
+         }
+       return "";
+
+      case 1:
+       /* Pre-adjust the loop counter.  */
+       operands[2] = GEN_INT (n_bytes - 2);
+       output_asm_insn ("ldi %2,%1", operands);
+
+       /* Loop.  */
+       output_asm_insn ("{stbs|stb},ma %%r0,1(%0)", operands);
+       output_asm_insn ("addib,>= -2,%1,.-4", operands);
+       output_asm_insn ("{stbs|stb},ma %%r0,1(%0)", operands);
+
+       /* Handle the residual.  */
+       if (n_bytes % 2 != 0)
+         output_asm_insn ("stb %%r0,0(%0)", operands);
+
+       return "";
+
+      default:
+       abort ();
+    }
+}
+
+/* Count the number of insns necessary to handle this block move.
+
+   Basic structure is the same as emit_block_move, except that we
+   count insns rather than emit them.  */
+
+static int
+compute_clrmem_length (rtx insn)
+{
+  rtx pat = PATTERN (insn);
+  unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 4), 0));
+  unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 3), 0));
+  unsigned int n_insns = 0;
+
+  /* We can't clear more than a word at a time because the PA
+     has no longer integer move insns.  */
+  if (align > (TARGET_64BIT ? 8 : 4))
+    align = (TARGET_64BIT ? 8 : 4);
+
+  /* The basic loop.  */
+  n_insns = 4;
+
+  /* Residuals.  */
+  if (n_bytes % (2 * align) != 0)
+    {
+      if ((n_bytes % (2 * align)) >= align)
+       n_insns++;
+
+      if ((n_bytes % align) != 0)
+       n_insns++;
+    }
+
+  /* Lengths are expressed in bytes now; each insn is 4 bytes.  */
+  return n_insns * 4;
+}
 \f
 
 const char *
-output_and (operands)
-     rtx *operands;
+output_and (rtx *operands)
 {
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
     {
@@ -2692,8 +3114,7 @@ output_and (operands)
 /* Return a string to perform a bitwise-and of operands[1] with operands[2]
    storing the result in operands[0].  */
 const char *
-output_64bit_and (operands)
-     rtx *operands;
+output_64bit_and (rtx *operands)
 {
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
     {
@@ -2743,8 +3164,7 @@ output_64bit_and (operands)
 }
 
 const char *
-output_ior (operands)
-     rtx *operands;
+output_ior (rtx *operands)
 {
   unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
   int bs0, bs1, p, len;
@@ -2774,8 +3194,7 @@ output_ior (operands)
 /* Return a string to perform a bitwise-and of operands[1] with operands[2]
    storing the result in operands[0].  */
 const char *
-output_64bit_ior (operands)
-     rtx *operands;
+output_64bit_ior (rtx *operands)
 {
   unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
   int bs0, bs1, p, len;
@@ -2808,10 +3227,7 @@ output_64bit_ior (operands)
    be preceded by P%.  */
 
 static bool
-pa_assemble_integer (x, size, aligned_p)
-     rtx x;
-     unsigned int size;
-     int aligned_p;
+pa_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
   if (size == UNITS_PER_WORD && aligned_p
       && function_label_operand (x, VOIDmode))
@@ -2826,14 +3242,11 @@ pa_assemble_integer (x, size, aligned_p)
 \f
 /* Output an ascii string.  */
 void
-output_ascii (file, p, size)
-     FILE *file;
-     const char *p;
-     int size;
+output_ascii (FILE *file, const char *p, int size)
 {
   int i;
   int chars_output;
-  unsigned char partial_output[16];    /* Max space 4 chars can occupy.   */
+  unsigned char partial_output[16];    /* Max space 4 chars can occupy.  */
 
   /* The HP assembler can only take strings of 256 characters at one
      time.  This is a limitation on input line length, *not* the
@@ -2896,8 +3309,7 @@ output_ascii (file, p, size)
    when there's a 1:1 correspondence between fcmp and ftest/fbranch
    instructions.  */
 static void
-remove_useless_addtr_insns (check_notes)
-     int check_notes;
+remove_useless_addtr_insns (int check_notes)
 {
   rtx insn;
   static int pass = 0;
@@ -3098,8 +3510,8 @@ remove_useless_addtr_insns (check_notes)
 /* Global variables set by output_function_prologue().  */
 /* Size of frame.  Need to know this to emit return insns from
    leaf procedures.  */
-static int actual_fsize;
-static int local_fsize, save_fregs;
+static HOST_WIDE_INT actual_fsize, local_fsize;
+static int save_fregs;
 
 /* Emit RTL to store REG at the memory location specified by BASE+DISP.
    Handle case where DISP > 8k by using the add_high_const patterns.
@@ -3108,8 +3520,7 @@ static int local_fsize, save_fregs;
    in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/
 
 static void
-store_reg (reg, disp, base)
-     int reg, disp, base;
+store_reg (int reg, HOST_WIDE_INT disp, int base)
 {
   rtx insn, dest, src, basereg;
 
@@ -3120,11 +3531,33 @@ store_reg (reg, disp, base)
       dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
       insn = emit_move_insn (dest, src);
     }
+  else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
+    {
+      rtx delta = GEN_INT (disp);
+      rtx tmpreg = gen_rtx_REG (Pmode, 1);
+
+      emit_move_insn (tmpreg, delta);
+      emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
+      dest = gen_rtx_MEM (word_mode, tmpreg);
+      insn = emit_move_insn (dest, src);
+      if (DO_FRAME_NOTES)
+       {
+         REG_NOTES (insn)
+           = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+               gen_rtx_SET (VOIDmode,
+                            gen_rtx_MEM (word_mode,
+                                         gen_rtx_PLUS (word_mode, basereg,
+                                                       delta)),
+                             src),
+                REG_NOTES (insn));
+       }
+    }
   else
     {
       rtx delta = GEN_INT (disp);
       rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
       rtx tmpreg = gen_rtx_REG (Pmode, 1);
+
       emit_move_insn (tmpreg, high);
       dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
       insn = emit_move_insn (dest, src);
@@ -3149,12 +3582,11 @@ store_reg (reg, disp, base)
    add MOD to BASE.  MOD must be <= 8k.  */
 
 static void
-store_reg_modify (base, reg, mod)
-     int base, reg, mod;
+store_reg_modify (int base, int reg, HOST_WIDE_INT mod)
 {
   rtx insn, basereg, srcreg, delta;
 
-  if (! VAL_14_BITS_P (mod))
+  if (!VAL_14_BITS_P (mod))
     abort ();
 
   basereg = gen_rtx_REG (Pmode, base);
@@ -3197,8 +3629,7 @@ store_reg_modify (base, reg, mod)
    There is code in expand_hppa_{prologue,epilogue} that knows about this.  */
 
 static void
-set_reg_plus_d (reg, base, disp, note)
-     int reg, base, disp, note;
+set_reg_plus_d (int reg, int base, HOST_WIDE_INT disp, int note)
 {
   rtx insn;
 
@@ -3207,27 +3638,35 @@ set_reg_plus_d (reg, base, disp, note)
       insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
                             plus_constant (gen_rtx_REG (Pmode, base), disp));
     }
+  else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
+    {
+      rtx basereg = gen_rtx_REG (Pmode, base);
+      rtx delta = GEN_INT (disp);
+      rtx tmpreg = gen_rtx_REG (Pmode, 1);
+
+      emit_move_insn (tmpreg, delta);
+      insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
+                            gen_rtx_PLUS (Pmode, tmpreg, basereg));
+    }
   else
     {
       rtx basereg = gen_rtx_REG (Pmode, base);
       rtx delta = GEN_INT (disp);
+      rtx tmpreg = gen_rtx_REG (Pmode, 1);
 
-      emit_move_insn (gen_rtx_REG (Pmode, 1),
+      emit_move_insn (tmpreg,
                      gen_rtx_PLUS (Pmode, basereg,
                                    gen_rtx_HIGH (Pmode, delta)));
       insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
-                            gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
-                                            delta));
+                            gen_rtx_LO_SUM (Pmode, tmpreg, delta));
     }
 
   if (DO_FRAME_NOTES && note)
     RTX_FRAME_RELATED_P (insn) = 1;
 }
 
-int
-compute_frame_size (size, fregs_live)
-     int size;
-     int *fregs_live;
+HOST_WIDE_INT
+compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
 {
   int freg_saved = 0;
   int i, j;
@@ -3320,9 +3759,7 @@ compute_frame_size (size, fregs_live)
    to do this is made in regclass.c.  */
 
 static void
-pa_output_function_prologue (file, size)
-     FILE *file;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   /* The function's label and associated .PROC must never be
      separated and must be output *after* any profiling declarations
@@ -3333,7 +3770,7 @@ pa_output_function_prologue (file, size)
   /* hppa_expand_prologue does the dirty work now.  We just need
      to output the assembler directives which denote the start
      of a function.  */
-  fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
+  fprintf (file, "\t.CALLINFO FRAME=" HOST_WIDE_INT_PRINT_DEC, actual_fsize);
   if (regs_ever_live[2])
     fputs (",CALLS,SAVE_RP", file);
   else
@@ -3371,11 +3808,12 @@ pa_output_function_prologue (file, size)
 }
 
 void
-hppa_expand_prologue ()
+hppa_expand_prologue (void)
 {
   int merge_sp_adjust_with_store = 0;
-  int size = get_frame_size ();
-  int i, offset;
+  HOST_WIDE_INT size = get_frame_size ();
+  HOST_WIDE_INT offset;
+  int i;
   rtx insn, tmpreg;
 
   gr_saved = 0;
@@ -3439,8 +3877,8 @@ hppa_expand_prologue ()
                 So instead use stwm to store at *sp and post-increment the
                 stack pointer as an atomic operation.  Then increment sp to
                 finish allocating the new frame.  */
-             int adjust1 = 8192 - 64;
-             int adjust2 = actual_fsize - adjust1;
+             HOST_WIDE_INT adjust1 = 8192 - 64;
+             HOST_WIDE_INT adjust2 = actual_fsize - adjust1;
 
              store_reg_modify (STACK_POINTER_REGNUM, 1, adjust1);
              set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
@@ -3585,9 +4023,17 @@ hppa_expand_prologue ()
      when generating PIC code.  FIXME:  What is the correct thing
      to do for functions which make no calls and allocate no
      frame?  Do we need to allocate a frame, or can we just omit
-     the save?   For now we'll just omit the save.  */
+     the save?   For now we'll just omit the save.
+     
+     We don't want a note on this insn as the frame marker can
+     move if there is a dynamic stack allocation.  */
   if (flag_pic && actual_fsize != 0 && !TARGET_64BIT)
-    store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
+    {
+      rtx addr = gen_rtx_PLUS (word_mode, stack_pointer_rtx, GEN_INT (-32));
+
+      emit_move_insn (gen_rtx_MEM (word_mode, addr), pic_offset_table_rtx);
+
+    }
 
   /* Align pointer properly (doubleword boundary).  */
   offset = (offset + 7) & ~7;
@@ -3664,37 +4110,48 @@ hppa_expand_prologue ()
    Handle case where DISP > 8k by using the add_high_const patterns.  */
 
 static void
-load_reg (reg, disp, base)
-     int reg, disp, base;
+load_reg (int reg, HOST_WIDE_INT disp, int base)
 {
-  rtx src, dest, basereg;
+  rtx dest = gen_rtx_REG (word_mode, reg);
+  rtx basereg = gen_rtx_REG (Pmode, base);
+  rtx src;
 
-  dest = gen_rtx_REG (word_mode, reg);
-  basereg = gen_rtx_REG (Pmode, base);
   if (VAL_14_BITS_P (disp))
+    src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
+  else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
     {
-      src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
-      emit_move_insn (dest, src);
+      rtx delta = GEN_INT (disp);
+      rtx tmpreg = gen_rtx_REG (Pmode, 1);
+
+      emit_move_insn (tmpreg, delta);
+      if (TARGET_DISABLE_INDEXING)
+       {
+         emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
+         src = gen_rtx_MEM (word_mode, tmpreg);
+       }
+      else
+       src = gen_rtx_MEM (word_mode, gen_rtx_PLUS (Pmode, tmpreg, basereg));
     }
   else
     {
       rtx delta = GEN_INT (disp);
       rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
       rtx tmpreg = gen_rtx_REG (Pmode, 1);
+
       emit_move_insn (tmpreg, high);
       src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
-      emit_move_insn (dest, src);
     }
+
+  emit_move_insn (dest, src);
 }
 
 /* Update the total code bytes output to the text section.  */
 
 static void
-update_total_code_bytes (nbytes)
-     int nbytes;
+update_total_code_bytes (int nbytes)
 {
   if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
-      && in_text_section ())
+      && !IN_NAMED_SECTION_P (cfun->decl))
     {
       if (INSN_ADDRESSES_SET_P ())
        {
@@ -3720,9 +4177,7 @@ update_total_code_bytes (nbytes)
    adjustments before returning.  */
 
 static void
-pa_output_function_epilogue (file, size)
-     FILE *file;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   rtx insn = get_last_insn ();
 
@@ -3770,12 +4225,13 @@ pa_output_function_epilogue (file, size)
 }
 
 void
-hppa_expand_epilogue ()
+hppa_expand_epilogue (void)
 {
   rtx tmpreg;
-  int offset, i;
+  HOST_WIDE_INT offset;
+  HOST_WIDE_INT ret_off = 0;
+  int i;
   int merge_sp_adjust_with_load = 0;
-  int ret_off = 0;
 
   /* We will use this often.  */
   tmpreg = gen_rtx_REG (word_mode, 1);
@@ -3946,21 +4402,25 @@ hppa_expand_epilogue ()
 }
 
 rtx
-hppa_pic_save_rtx ()
+hppa_pic_save_rtx (void)
 {
   return get_hard_reg_initial_val (word_mode, PIC_OFFSET_TABLE_REGNUM);
 }
 
 void
-hppa_profile_hook (label_no)
-     int label_no;
+hppa_profile_hook (int label_no)
 {
+  /* We use SImode for the address of the function in both 32 and
+     64-bit code to avoid having to provide DImode versions of the
+     lcla2 and load_offset_label_address insn patterns.  */
+  rtx reg = gen_reg_rtx (SImode);
+  rtx label_rtx = gen_label_rtx ();
   rtx begin_label_rtx, call_insn;
   char begin_label_name[16];
 
   ASM_GENERATE_INTERNAL_LABEL (begin_label_name, FUNC_BEGIN_PROLOG_LABEL,
                               label_no);
-  begin_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (begin_label_name));
+  begin_label_rtx = gen_rtx_SYMBOL_REF (SImode, ggc_strdup (begin_label_name));
 
   if (TARGET_64BIT)
     emit_move_insn (arg_pointer_rtx,
@@ -3969,6 +4429,18 @@ hppa_profile_hook (label_no)
 
   emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
 
+  /* The address of the function is loaded into %r25 with a instruction-
+     relative sequence that avoids the use of relocations.  The sequence
+     is split so that the load_offset_label_address instruction can
+     occupy the delay slot of the call to _mcount.  */
+  if (TARGET_PA_20)
+    emit_insn (gen_lcla2 (reg, label_rtx));
+  else
+    emit_insn (gen_lcla1 (reg, label_rtx));
+
+  emit_insn (gen_load_offset_label_address (gen_rtx_REG (SImode, 25), 
+                                           reg, begin_label_rtx, label_rtx));
+
 #ifndef NO_PROFILE_COUNTERS
   {
     rtx count_label_rtx, addr, r24;
@@ -3981,35 +4453,31 @@ hppa_profile_hook (label_no)
     r24 = gen_rtx_REG (Pmode, 24);
     emit_move_insn (r24, addr);
 
-    /* %r25 is set from within the output pattern.  */
     call_insn =
-      emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
-                                        GEN_INT (TARGET_64BIT ? 24 : 12),
-                                        begin_label_rtx));
+      emit_call_insn (gen_call (gen_rtx_MEM (Pmode, 
+                                            gen_rtx_SYMBOL_REF (Pmode, 
+                                                                "_mcount")),
+                               GEN_INT (TARGET_64BIT ? 24 : 12)));
 
     use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
   }
 #else
-    /* %r25 is set from within the output pattern.  */
+
   call_insn =
-    emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
-                                      GEN_INT (TARGET_64BIT ? 16 : 8),
-                                      begin_label_rtx));
+    emit_call_insn (gen_call (gen_rtx_MEM (Pmode, 
+                                          gen_rtx_SYMBOL_REF (Pmode, 
+                                                              "_mcount")),
+                             GEN_INT (TARGET_64BIT ? 16 : 8)));
+
 #endif
 
+  use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 25));
+  use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 26));
+
   /* Indicate the _mcount call cannot throw, nor will it execute a
      non-local goto.  */
   REG_NOTES (call_insn)
     = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
-
-  if (flag_pic)
-    {
-      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
-      if (TARGET_64BIT)
-       use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), arg_pointer_rtx);
-
-      emit_move_insn (pic_offset_table_rtx, hppa_pic_save_rtx ());
-    }
 }
 
 /* Fetch the return address for the frame COUNT steps up from
@@ -4039,9 +4507,7 @@ hppa_profile_hook (label_no)
    return location is in a shared library.  */
 
 rtx
-return_addr_rtx (count, frameaddr)
-     int count;
-     rtx frameaddr;
+return_addr_rtx (int count, rtx frameaddr)
 {
   rtx label;
   rtx rp;
@@ -4120,7 +4586,7 @@ return_addr_rtx (count, frameaddr)
    It's only valid if %r2 hasn't been saved into the caller's frame
    (we're not profiling and %r2 isn't live anywhere).  */
 int
-hppa_can_use_return_insn_p ()
+hppa_can_use_return_insn_p (void)
 {
   return (reload_completed
          && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
@@ -4129,9 +4595,7 @@ hppa_can_use_return_insn_p ()
 }
 
 void
-emit_bcond_fp (code, operand0)
-     enum rtx_code code;
-     rtx operand0;
+emit_bcond_fp (enum rtx_code code, rtx operand0)
 {
   emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
                               gen_rtx_IF_THEN_ELSE (VOIDmode,
@@ -4145,9 +4609,7 @@ emit_bcond_fp (code, operand0)
 }
 
 rtx
-gen_cmp_fp (code, operand0, operand1)
-     enum rtx_code code;
-     rtx operand0, operand1;
+gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1)
 {
   return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
                      gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
@@ -4157,11 +4619,7 @@ gen_cmp_fp (code, operand0, operand1)
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
 
 static int
-pa_adjust_cost (insn, link, dep_insn, cost)
-     rtx insn;
-     rtx link;
-     rtx dep_insn;
-     int cost;
+pa_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 {
   enum attr_type attr_type;
 
@@ -4349,9 +4807,7 @@ pa_adjust_cost (insn, link, dep_insn, cost)
 /* Adjust scheduling priorities.  We use this to try and keep addil
    and the next use of %r1 close together.  */
 static int
-pa_adjust_priority (insn, priority)
-     rtx insn;
-     int priority;
+pa_adjust_priority (rtx insn, int priority)
 {
   rtx set = single_set (insn);
   rtx src, dest;
@@ -4383,7 +4839,7 @@ pa_adjust_priority (insn, priority)
    The 7XXX processors can issue two insns at a time.
    The 8000 can issue 4 insns at a time.  */
 static int
-pa_issue_rate ()
+pa_issue_rate (void)
 {
   switch (pa_cpu)
     {
@@ -4411,31 +4867,15 @@ pa_issue_rate ()
    Also compute the length of an inline block move here as it is too
    complicated to express as a length attribute in pa.md.  */
 int
-pa_adjust_insn_length (insn, length)
-    rtx insn;
-    int length;
+pa_adjust_insn_length (rtx insn, int length)
 {
   rtx pat = PATTERN (insn);
 
-  /* Call insns which are *not* indirect and have unfilled delay slots.  */
-  if (GET_CODE (insn) == CALL_INSN)
-    {
-
-      if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL
-         && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF)
-       return 4;
-      else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET
-              && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0))
-                 == SYMBOL_REF)
-       return 4;
-      else
-       return 0;
-    }
-  /* Jumps inside switch tables which have unfilled delay slots
-     also need adjustment.  */
-  else if (GET_CODE (insn) == JUMP_INSN
-          && simplejump_p (insn)
-          && GET_MODE (insn) == SImode)
+  /* Jumps inside switch tables which have unfilled delay slots need
+     adjustment.  */
+  if (GET_CODE (insn) == JUMP_INSN
+      && GET_CODE (pat) == PARALLEL
+      && get_attr_type (insn) == TYPE_BTABLE_BRANCH)
     return 4;
   /* Millicode insn with an unfilled delay slot.  */
   else if (GET_CODE (insn) == INSN
@@ -4452,7 +4892,15 @@ pa_adjust_insn_length (insn, length)
           && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
           && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
           && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
-    return compute_movstrsi_length (insn) - 4;
+    return compute_movmem_length (insn) - 4;
+  /* Block clear pattern.  */
+  else if (GET_CODE (insn) == INSN
+          && GET_CODE (pat) == PARALLEL
+          && GET_CODE (XVECEXP (pat, 0, 0)) == SET
+          && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
+          && XEXP (XVECEXP (pat, 0, 0), 1) == const0_rtx
+          && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode)
+    return compute_clrmem_length (insn) - 4;
   /* Conditional branch with an unfilled delay slot.  */
   else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
     {
@@ -4486,10 +4934,7 @@ pa_adjust_insn_length (insn, length)
    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
 
 void
-print_operand (file, x, code)
-     FILE *file;
-     rtx x;
-     int code;
+print_operand (FILE *file, rtx x, int code)
 {
   switch (code)
     {
@@ -4755,8 +5200,14 @@ print_operand (file, x, 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);
@@ -4831,20 +5282,33 @@ print_operand (file, x, 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
@@ -4854,10 +5318,7 @@ print_operand (file, x, code)
 /* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF.  */
 
 void
-output_global_address (file, x, round_constant)
-     FILE *file;
-     rtx x;
-     int round_constant;
+output_global_address (FILE *file, rtx x, int round_constant)
 {
 
   /* Imagine  (high (const (plus ...))).  */
@@ -4935,7 +5396,7 @@ output_global_address (file, x, round_constant)
    There are several possible versions.  */
 #define aputs(x) fputs(x, asm_out_file)
 static inline void
-pa_file_start_level ()
+pa_file_start_level (void)
 {
   if (TARGET_64BIT)
     aputs ("\t.LEVEL 2.0w\n");
@@ -4948,8 +5409,7 @@ pa_file_start_level ()
 }
 
 static inline void
-pa_file_start_space (sortspace)
-     int sortspace;
+pa_file_start_space (int sortspace)
 {
   aputs ("\t.SPACE $PRIVATE$");
   if (sortspace)
@@ -4964,8 +5424,7 @@ pa_file_start_space (sortspace)
 }
 
 static inline void
-pa_file_start_file (want_version)
-     int want_version;
+pa_file_start_file (int want_version)
 {
   if (write_symbols != NO_DEBUG)
     {
@@ -4976,15 +5435,14 @@ pa_file_start_file (want_version)
 }
 
 static inline void
-pa_file_start_mcount (aswhat)
-     const char *aswhat;
+pa_file_start_mcount (const char *aswhat)
 {
   if (profile_flag)
     fprintf (asm_out_file, "\t.IMPORT _mcount,%s\n", aswhat);
 }
   
 static void
-pa_elf_file_start ()
+pa_elf_file_start (void)
 {
   pa_file_start_level ();
   pa_file_start_mcount ("ENTRY");
@@ -4992,7 +5450,7 @@ pa_elf_file_start ()
 }
 
 static void
-pa_som_file_start ()
+pa_som_file_start (void)
 {
   pa_file_start_level ();
   pa_file_start_space (0);
@@ -5003,7 +5461,7 @@ pa_som_file_start ()
 }
 
 static void
-pa_linux_file_start ()
+pa_linux_file_start (void)
 {
   pa_file_start_file (1);
   pa_file_start_level ();
@@ -5011,7 +5469,7 @@ pa_linux_file_start ()
 }
 
 static void
-pa_hpux64_gas_file_start ()
+pa_hpux64_gas_file_start (void)
 {
   pa_file_start_level ();
 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
@@ -5022,7 +5480,7 @@ pa_hpux64_gas_file_start ()
 }
 
 static void
-pa_hpux64_hpas_file_start ()
+pa_hpux64_hpas_file_start (void)
 {
   pa_file_start_level ();
   pa_file_start_space (1);
@@ -5032,8 +5490,7 @@ pa_hpux64_hpas_file_start ()
 #undef aputs
 
 static struct deferred_plabel *
-get_plabel (fname)
-     const char *fname;
+get_plabel (const char *fname)
 {
   size_t i;
 
@@ -5073,7 +5530,7 @@ get_plabel (fname)
 }
 
 static void
-output_deferred_plabels ()
+output_deferred_plabels (void)
 {
   size_t i;
   /* If we have deferred plabels, then we need to switch into the data
@@ -5095,19 +5552,58 @@ output_deferred_plabels ()
     }
 }
 
+#ifdef HPUX_LONG_DOUBLE_LIBRARY
+/* Initialize optabs to point to HPUX long double emulation routines.  */
+static void
+pa_hpux_init_libfuncs (void)
+{
+  set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
+  set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
+  set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
+  set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
+  set_optab_libfunc (smin_optab, TFmode, "_U_Qmin");
+  set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
+  set_optab_libfunc (sqrt_optab, TFmode, "_U_Qfsqrt");
+  set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
+  set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
+
+  set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+  set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+  set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+  set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+  set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+  set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
+  set_optab_libfunc (unord_optab, TFmode, "_U_Qfunord");
+
+  set_conv_libfunc (sext_optab,   TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+  set_conv_libfunc (sext_optab,   TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+  set_conv_libfunc (trunc_optab,  SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+  set_conv_libfunc (trunc_optab,  DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+
+  set_conv_libfunc (sfix_optab,   SImode, TFmode, TARGET_64BIT
+                                                 ? "__U_Qfcnvfxt_quad_to_sgl"
+                                                 : "_U_Qfcnvfxt_quad_to_sgl");
+  set_conv_libfunc (sfix_optab,   DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+  set_conv_libfunc (ufix_optab,   SImode, TFmode, "_U_Qfcnvfxt_quad_to_usgl");
+  set_conv_libfunc (ufix_optab,   DImode, TFmode, "_U_Qfcnvfxt_quad_to_udbl");
+
+  set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+  set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+}
+#endif
+
 /* HP's millicode routines mean something special to the assembler.
    Keep track of which ones we have used.  */
 
 enum millicodes { remI, remU, divI, divU, mulI, end1000 };
-static void import_milli                       PARAMS ((enum millicodes));
+static void import_milli (enum millicodes);
 static char imported[(int) end1000];
 static const char * const milli_names[] = {"remI", "remU", "divI", "divU", "mulI"};
 static const char import_string[] = ".IMPORT $$....,MILLICODE";
 #define MILLI_START 10
 
 static void
-import_milli (code)
-     enum millicodes code;
+import_milli (enum millicodes code)
 {
   char str[sizeof (import_string)];
 
@@ -5124,9 +5620,7 @@ import_milli (code)
    the proper registers.  */
 
 const char *
-output_mul_insn (unsignedp, insn)
-     int unsignedp ATTRIBUTE_UNUSED;
-     rtx insn;
+output_mul_insn (int unsignedp ATTRIBUTE_UNUSED, rtx insn)
 {
   import_milli (mulI);
   return output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
@@ -5145,9 +5639,7 @@ static const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
 static int div_milli[16][2];
 
 int
-div_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+div_operand (rtx op, enum machine_mode mode)
 {
   return (mode == SImode
          && ((GET_CODE (op) == REG && REGNO (op) == 25)
@@ -5156,9 +5648,7 @@ div_operand (op, mode)
 }
 
 int
-emit_hpdiv_const (operands, unsignedp)
-     rtx *operands;
-     int unsignedp;
+emit_hpdiv_const (rtx *operands, int unsignedp)
 {
   if (GET_CODE (operands[2]) == CONST_INT
       && INTVAL (operands[2]) > 0
@@ -5169,8 +5659,8 @@ emit_hpdiv_const (operands, unsignedp)
 
       emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
       emit
-       (gen_rtx
-        (PARALLEL, VOIDmode,
+       (gen_rtx_PARALLEL
+        (VOIDmode,
          gen_rtvec (6, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29),
                                     gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
                                                     SImode,
@@ -5188,10 +5678,7 @@ emit_hpdiv_const (operands, unsignedp)
 }
 
 const char *
-output_div_insn (operands, unsignedp, insn)
-     rtx *operands;
-     int unsignedp;
-     rtx insn;
+output_div_insn (rtx *operands, int unsignedp, rtx insn)
 {
   int divisor;
 
@@ -5245,9 +5732,7 @@ output_div_insn (operands, unsignedp, insn)
 /* Output a $$rem millicode to do mod.  */
 
 const char *
-output_mod_insn (unsignedp, insn)
-     int unsignedp;
-     rtx insn;
+output_mod_insn (int unsignedp, rtx insn)
 {
   if (unsignedp)
     {
@@ -5264,8 +5749,7 @@ output_mod_insn (unsignedp, insn)
 }
 
 void
-output_arg_descriptor (call_insn)
-     rtx call_insn;
+output_arg_descriptor (rtx call_insn)
 {
   const char *arg_regs[4];
   enum machine_mode arg_mode;
@@ -5349,10 +5833,7 @@ output_arg_descriptor (call_insn)
    It might be worthwhile to try and make this a leaf function too.  */
 
 enum reg_class
-secondary_reload_class (class, mode, in)
-     enum reg_class class;
-     enum machine_mode mode;
-     rtx in;
+secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx in)
 {
   int regno, is_symbolic;
 
@@ -5439,10 +5920,39 @@ secondary_reload_class (class, mode, in)
   return NO_REGS;
 }
 
+/* In the 32-bit runtime, arguments larger than eight bytes are passed
+   by invisible reference.  As a GCC extension, we also pass anything
+   with a zero or variable size by reference.
+
+   The 64-bit runtime does not describe passing any types by invisible
+   reference.  The internals of GCC can't currently handle passing
+   empty structures, and zero or variable length arrays when they are
+   not passed entirely on the stack or by reference.  Thus, as a GCC
+   extension, we pass these types by reference.  The HP compiler doesn't
+   support these types, so hopefully there shouldn't be any compatibility
+   issues.  This may have to be revisited when HP releases a C99 compiler
+   or updates the ABI.  */
+
+static bool
+pa_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+                     enum machine_mode mode, tree type,
+                     bool named ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT size;
+
+  if (type)
+    size = int_size_in_bytes (type);
+  else
+    size = GET_MODE_SIZE (mode);
+
+  if (TARGET_64BIT)
+    return size <= 0;
+  else
+    return size <= 0 || size > 8;
+}
+
 enum direction
-function_arg_padding (mode, type)
-     enum machine_mode mode;
-     tree type;
+function_arg_padding (enum machine_mode mode, tree type)
 {
   if (mode == BLKmode
       || (TARGET_64BIT && type && AGGREGATE_TYPE_P (type)))
@@ -5480,8 +5990,8 @@ function_arg_padding (mode, type)
    to determine if stdargs or varargs is used and fill in an initial
    va_list.  A pointer to this constructor is returned.  */
 
-struct rtx_def *
-hppa_builtin_saveregs ()
+static rtx
+hppa_builtin_saveregs (void)
 {
   rtx offset, dest;
   tree fntype = TREE_TYPE (current_function_decl);
@@ -5550,115 +6060,66 @@ hppa_builtin_saveregs ()
 }
 
 void
-hppa_va_start (valist, nextarg)
-     tree valist;
-     rtx nextarg;
+hppa_va_start (tree valist, rtx nextarg)
 {
   nextarg = expand_builtin_saveregs ();
   std_expand_builtin_va_start (valist, nextarg);
 }
 
-rtx
-hppa_va_arg (valist, type)
-     tree valist, type;
+static tree
+hppa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
 {
-  HOST_WIDE_INT size = int_size_in_bytes (type);
-  HOST_WIDE_INT ofs;
-  tree t, ptr, pptr;
-
   if (TARGET_64BIT)
     {
-      /* Every argument in PA64 is supposed to be passed by value
-        (including large structs).  However, as a GCC extension, we
-        pass zero and variable sized arguments by reference.  Empty
-        structures are a GCC extension not supported by the HP
-        compilers.  Thus, passing them by reference isn't likely
-        to conflict with the ABI.  For variable sized arguments,
-        GCC doesn't have the infrastructure to allocate these to
-        registers.  */
-
-      /* Arguments with a size greater than 8 must be aligned 0 MOD 16.  */
-
-      if (size > UNITS_PER_WORD)
-        {
-          t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                     build_int_2 (2 * UNITS_PER_WORD - 1, 0));
-          t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
-                     build_int_2 (-2 * UNITS_PER_WORD, -1));
-          t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
-          TREE_SIDE_EFFECTS (t) = 1;
-         expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-        }
-
-      if (size > 0)
-       return std_expand_builtin_va_arg (valist, type);
-      else
-       {
-         ptr = build_pointer_type (type);
-
-         /* Args grow upward.  */
-         t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
-                    build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
-         TREE_SIDE_EFFECTS (t) = 1;
-
-         pptr = build_pointer_type (ptr);
-         t = build1 (NOP_EXPR, pptr, t);
-         TREE_SIDE_EFFECTS (t) = 1;
-
-         t = build1 (INDIRECT_REF, ptr, t);
-         TREE_SIDE_EFFECTS (t) = 1;
-       }
+      /* Args grow upward.  We can use the generic routines.  */
+      return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
     }
   else /* !TARGET_64BIT */
     {
-      ptr = build_pointer_type (type);
+      tree ptr = build_pointer_type (type);
+      tree valist_type;
+      tree t, u;
+      unsigned int size, ofs;
+      bool indirect;
 
-      /* "Large" and variable sized types are passed by reference.  */
-      if (size > 8 || size <= 0)
+      indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
+      if (indirect)
        {
-         /* Args grow downward.  */
-         t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
-                    build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
-         TREE_SIDE_EFFECTS (t) = 1;
-
-         pptr = build_pointer_type (ptr);
-         t = build1 (NOP_EXPR, pptr, t);
-         TREE_SIDE_EFFECTS (t) = 1;
-
-         t = build1 (INDIRECT_REF, ptr, t);
-         TREE_SIDE_EFFECTS (t) = 1;
+         type = ptr;
+         ptr = build_pointer_type (type);
        }
-      else
-       {
-         t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                    build_int_2 (-size, -1));
+      size = int_size_in_bytes (type);
+      valist_type = TREE_TYPE (valist);
 
-         /* Copied from va-pa.h, but we probably don't need to align to
-            word size, since we generate and preserve that invariant.  */
-         t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
-                    build_int_2 ((size > 4 ? -8 : -4), -1));
+      /* Args grow down.  Not handled by generic routines.  */
 
-         t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
-         TREE_SIDE_EFFECTS (t) = 1;
+      u = fold_convert (valist_type, size_in_bytes (type));
+      t = build (MINUS_EXPR, valist_type, valist, u);
 
-         ofs = (8 - size) % 4;
-         if (ofs)
-           {
-             t = build (PLUS_EXPR, TREE_TYPE (valist), t,
-                        build_int_2 (ofs, 0));
-             TREE_SIDE_EFFECTS (t) = 1;
-           }
+      /* Copied from va-pa.h, but we probably don't need to align to
+        word size, since we generate and preserve that invariant.  */
+      u = build_int_2 ((size > 4 ? -8 : -4), -1);
+      u = fold_convert (valist_type, u);
+      t = build (BIT_AND_EXPR, valist_type, t, u);
+
+      t = build (MODIFY_EXPR, valist_type, valist, t);
 
-         t = build1 (NOP_EXPR, ptr, t);
-         TREE_SIDE_EFFECTS (t) = 1;
+      ofs = (8 - size) % 4;
+      if (ofs != 0)
+       {
+         u = fold_convert (valist_type, size_int (ofs));
+         t = build (PLUS_EXPR, valist_type, t, u);
        }
-    }
 
-  /* Calculate!  */
-  return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-}
+      t = fold_convert (ptr, t);
+      t = build_fold_indirect_ref (t);
 
+      if (indirect)
+       t = build_fold_indirect_ref (t);
 
+      return t;
+    }
+}
 
 /* This routine handles all the normal conditional branch sequences we
    might need to generate.  It handles compare immediate vs compare
@@ -5668,10 +6129,7 @@ hppa_va_arg (valist, type)
    parameters.  */
 
 const char *
-output_cbranch (operands, nullify, length, negated, insn)
-     rtx *operands;
-     int nullify, length, negated;
-     rtx insn;
+output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
 {
   static char buf[100];
   int useskip = 0;
@@ -5689,6 +6147,12 @@ output_cbranch (operands, nullify, length, negated, insn)
   if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
     return "nop";
 
+  /* The doubleword form of the cmpib instruction doesn't have the LEU
+     and GTU conditions while the cmpb instruction does.  Since we accept
+     zero for cmpb, we must ensure that we use cmpb for the comparison.  */
+  if (GET_MODE (operands[1]) == DImode && operands[2] == const0_rtx)
+    operands[2] = gen_rtx_REG (DImode, 0);
+
   /* If this is a long branch with its delay slot unfilled, set `nullify'
      as it can nullify the delay slot and save a nop.  */
   if (length == 8 && dbr_sequence_length () == 0)
@@ -5856,8 +6320,7 @@ output_cbranch (operands, nullify, length, negated, insn)
    maximum range of a simple branch instruction.  */
 
 const char *
-output_lbranch (dest, insn)
-     rtx dest, insn;
+output_lbranch (rtx dest, rtx insn)
 {
   rtx xoperands[2];
  
@@ -5871,7 +6334,7 @@ output_lbranch (dest, insn)
        abort ();
 
       final_scan_insn (NEXT_INSN (insn), asm_out_file,
-                      optimize, 0, 0);
+                      optimize, 0, 0, NULL);
 
       /* Now delete the delay insn.  */
       PUT_CODE (NEXT_INSN (insn), NOTE);
@@ -5975,11 +6438,8 @@ output_lbranch (dest, insn)
    above.  it returns the appropriate output template to emit the branch.  */
 
 const char *
-output_bb (operands, nullify, length, negated, insn, which)
-     rtx *operands ATTRIBUTE_UNUSED;
-     int nullify, length, negated;
-     rtx insn;
-     int which;
+output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
+          int negated, rtx insn, int which)
 {
   static char buf[100];
   int useskip = 0;
@@ -6123,11 +6583,8 @@ output_bb (operands, nullify, length, negated, insn, which)
    branch.  */
 
 const char *
-output_bvb (operands, nullify, length, negated, insn, which)
-     rtx *operands ATTRIBUTE_UNUSED;
-     int nullify, length, negated;
-     rtx insn;
-     int which;
+output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
+           int negated, rtx insn, int which)
 {
   static char buf[100];
   int useskip = 0;
@@ -6172,7 +6629,7 @@ output_bvb (operands, nullify, length, negated, insn, which)
        else
          strcpy (buf, "{bvb,|bb,}");
        if (useskip && GET_MODE (operands[0]) == DImode)
-         strcpy (buf, "extrd,s,*}");
+         strcpy (buf, "extrd,s,*");
        else if (GET_MODE (operands[0]) == DImode)
          strcpy (buf, "bb,*");
        if ((which == 0 && negated)
@@ -6269,10 +6726,7 @@ output_bvb (operands, nullify, length, negated, insn, which)
    Note it may perform some output operations on its own before
    returning the final output string.  */
 const char *
-output_dbra (operands, insn, which_alternative)
-     rtx *operands;
-     rtx insn;
-     int which_alternative;
+output_dbra (rtx *operands, rtx insn, int which_alternative)
 {
 
   /* A conditional branch to the following instruction (eg the delay slot) is
@@ -6361,7 +6815,7 @@ output_dbra (operands, insn, which_alternative)
   else
     {
       /* Reload loop counter from memory, the store back to memory
-        happens in the branch's delay slot.   */
+        happens in the branch's delay slot.  */
       output_asm_insn ("ldw %0,%4", operands);
       if (get_attr_length (insn) == 12)
        return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
@@ -6375,11 +6829,8 @@ output_dbra (operands, insn, which_alternative)
    Note it may perform some output operations on its own before
    returning the final output string.  */
 const char *
-output_movb (operands, insn, which_alternative, reverse_comparison)
-     rtx *operands;
-     rtx insn;
-     int which_alternative;
-     int reverse_comparison;
+output_movb (rtx *operands, rtx insn, int which_alternative,
+            int reverse_comparison)
 {
 
   /* A conditional branch to the following instruction (eg the delay slot) is
@@ -6467,7 +6918,7 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
   else if (which_alternative == 2)
     {
       /* Reload loop counter from memory, the store back to memory
-        happens in the branch's delay slot.   */
+        happens in the branch's delay slot.  */
       if (get_attr_length (insn) == 8)
        return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
       else
@@ -6485,8 +6936,7 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
 
 /* Copy any FP arguments in INSN into integer registers.  */
 static void
-copy_fp_args (insn)
-     rtx insn;
+copy_fp_args (rtx insn)
 {
   rtx link;
   rtx xoperands[2];
@@ -6529,8 +6979,7 @@ copy_fp_args (insn)
 
 /* Compute length of the FP argument copy sequence for INSN.  */
 static int
-length_fp_args (insn)
-     rtx insn;
+length_fp_args (rtx insn)
 {
   int length = 0;
   rtx link;
@@ -6567,11 +7016,10 @@ length_fp_args (insn)
    over estimate the length than to under estimate it.  */
 
 int
-attr_length_millicode_call (insn)
-     rtx insn;
+attr_length_millicode_call (rtx insn)
 {
   unsigned long distance = -1;
-  unsigned long total = in_text_section () ? total_code_bytes : 0;
+  unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
 
   if (INSN_ADDRESSES_SET_P ())
     {
@@ -6607,9 +7055,7 @@ attr_length_millicode_call (insn)
    CALL_DEST is the routine we are calling.  */
 
 const char *
-output_millicode_call (insn, call_dest)
-     rtx insn;
-     rtx call_dest;
+output_millicode_call (rtx insn, rtx call_dest)
 {
   int attr_length = get_attr_length (insn);
   int seq_length = dbr_sequence_length ();
@@ -6758,73 +7204,93 @@ output_millicode_call (insn, call_dest)
 
 /* Return the attribute length of the call instruction INSN.  The SIBCALL
    flag indicates whether INSN is a regular call or a sibling call.  The
-   length must match the code generated by output_call.  We include the delay
-   slot in the returned length as it is better to over estimate the length
-   than to under estimate it.  */
+   length returned must be longer than the code actually generated by
+   output_call.  Since branch shortening is done before delay branch
+   sequencing, there is no way to determine whether or not the delay
+   slot will be filled during branch shortening.  Even when the delay
+   slot is filled, we may have to add a nop if the delay slot contains
+   a branch that can't reach its target.  Thus, we always have to include
+   the delay slot in the length estimate.  This used to be done in
+   pa_adjust_insn_length but we do it here now as some sequences always
+   fill the delay slot and we can save four bytes in the estimate for
+   these sequences.  */
 
 int
-attr_length_call (insn, sibcall)
-     rtx insn;
-     int sibcall;
+attr_length_call (rtx insn, int sibcall)
 {
+  int local_call;
+  rtx call_dest;
+  tree call_decl;
+  int length = 0;
+  rtx pat = PATTERN (insn);
   unsigned long distance = -1;
-  unsigned long total = in_text_section ()? total_code_bytes : 0;
 
   if (INSN_ADDRESSES_SET_P ())
     {
+      unsigned long total;
+
+      total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
       distance = (total + insn_current_reference_address (insn));
       if (distance < total)
        distance = -1;
     }
 
-  if (TARGET_64BIT)
-    {
-      if (!TARGET_LONG_CALLS
-         && ((!sibcall && distance < 7600000) || distance < 240000))
-       return 8;
-
-      return (sibcall ? 28 : 24);
-    }
+  /* Determine if this is a local call.  */
+  if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL)
+    call_dest = XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0);
   else
-    {
-      if (!TARGET_LONG_CALLS
-         && ((TARGET_PA_20 && !sibcall && distance < 7600000)
-             || distance < 240000))
-       return 8;
+    call_dest = XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0);
 
-      if (TARGET_LONG_ABS_CALL && !flag_pic)
-       return 12;
+  call_decl = SYMBOL_REF_DECL (call_dest);
+  local_call = call_decl && (*targetm.binds_local_p) (call_decl);
 
-      if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
-         || (TARGET_GAS && TARGET_LONG_PIC_PCREL_CALL))
-       {
-         if (TARGET_PA_20)
-           return 20;
+  /* pc-relative branch.  */
+  if (!TARGET_LONG_CALLS
+      && ((TARGET_PA_20 && !sibcall && distance < 7600000)
+         || distance < 240000))
+    length += 8;
 
-         return 28;
-       }
-      else
-       {
-         int length = 0;
+  /* 64-bit plabel sequence.  */
+  else if (TARGET_64BIT && !local_call)
+    length += sibcall ? 28 : 24;
 
-         if (TARGET_SOM)
-           length += length_fp_args (insn);
+  /* non-pic long absolute branch sequence.  */
+  else if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
+    length += 12;
 
-         if (flag_pic)
-           length += 4;
+  /* long pc-relative branch sequence.  */
+  else if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
+          || (TARGET_64BIT && !TARGET_GAS)
+          || (TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call)))
+    {
+      length += 20;
 
-         if (TARGET_PA_20)
-           return (length + 32);
+      if (!TARGET_PA_20 && !TARGET_NO_SPACE_REGS)
+       length += 8;
+    }
 
-         if (!TARGET_NO_SPACE_REGS)
-           length += 8;
+  /* 32-bit plabel sequence.  */
+  else
+    {
+      length += 32;
+
+      if (TARGET_SOM)
+       length += length_fp_args (insn);
 
+      if (flag_pic)
+       length += 4;
+
+      if (!TARGET_PA_20)
+       {
          if (!sibcall)
            length += 8;
 
-         return (length + 32);
+         if (!TARGET_NO_SPACE_REGS)
+           length += 8;
        }
     }
+
+  return length;
 }
 
 /* INSN is a function call.  It may have an unconditional jump
@@ -6833,16 +7299,13 @@ attr_length_call (insn, sibcall)
    CALL_DEST is the routine we are calling.  */
 
 const char *
-output_call (insn, call_dest, sibcall)
-     rtx insn;
-     rtx call_dest;
-     int sibcall;
+output_call (rtx insn, rtx call_dest, int sibcall)
 {
   int delay_insn_deleted = 0;
   int delay_slot_filled = 0;
   int seq_length = dbr_sequence_length ();
   tree call_decl = SYMBOL_REF_DECL (call_dest);
-  int local_call = call_decl && !TREE_PUBLIC (call_decl);
+  int local_call = call_decl && (*targetm.binds_local_p) (call_decl);
   rtx xoperands[2];
 
   xoperands[0] = call_dest;
@@ -6875,7 +7338,7 @@ output_call (insn, call_dest, sibcall)
              && !sibcall)
            {
              final_scan_insn (NEXT_INSN (insn), asm_out_file,
-                              optimize, 0, 0);
+                              optimize, 0, 0, NULL);
 
              /* Now delete the delay insn.  */
              PUT_CODE (NEXT_INSN (insn), NOTE);
@@ -6923,7 +7386,8 @@ output_call (insn, call_dest, sibcall)
              /* A non-jump insn in the delay slot.  By definition we can
                 emit this insn before the call (and in fact before argument
                 relocating.  */
-             final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
+             final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0,
+                              NULL);
 
              /* Now delete the delay insn.  */
              PUT_CODE (NEXT_INSN (insn), NOTE);
@@ -7077,7 +7541,7 @@ output_call (insn, call_dest, sibcall)
        }
     }
 
-  if (seq_length == 0 || (delay_insn_deleted && !delay_slot_filled))
+  if (!delay_slot_filled && (seq_length == 0 || delay_insn_deleted))
     output_asm_insn ("nop", xoperands);
 
   /* We are done if there isn't a jump in the delay slot.  */
@@ -7129,11 +7593,10 @@ output_call (insn, call_dest, sibcall)
    the sequence itself.  */
 
 int
-attr_length_indirect_call (insn)
-     rtx insn;
+attr_length_indirect_call (rtx insn)
 {
   unsigned long distance = -1;
-  unsigned long total = in_text_section () ? total_code_bytes : 0;
+  unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
 
   if (INSN_ADDRESSES_SET_P ())
     {
@@ -7161,9 +7624,7 @@ attr_length_indirect_call (insn)
 }
 
 const char *
-output_indirect_call (insn, call_dest)
-     rtx insn;
-     rtx call_dest;
+output_indirect_call (rtx insn, rtx call_dest)
 {
   rtx xoperands[1];
 
@@ -7185,7 +7646,15 @@ output_indirect_call (insn, call_dest)
      No need to check target flags as the length uniquely identifies
      the remaining cases.  */
   if (attr_length_indirect_call (insn) == 8)
-    return ".CALL\tARGW0=GR\n\t{bl|b,l} $$dyncall,%%r31\n\tcopy %%r31,%%r2";
+    {
+      /* The HP linker substitutes a BLE for millicode calls using
+        the short PIC PCREL form.  Thus, we must use %r31 as the
+        link register when generating PA 1.x code.  */
+      if (TARGET_PA_20)
+       return ".CALL\tARGW0=GR\n\tb,l $$dyncall,%%r2\n\tcopy %%r2,%%r31";
+      else
+       return ".CALL\tARGW0=GR\n\tbl $$dyncall,%%r31\n\tcopy %%r31,%%r2";
+    }
 
   /* Long millicode call, but we are not generating PIC or portable runtime
      code.  */
@@ -7225,8 +7694,7 @@ output_indirect_call (insn, call_dest)
    within the same translation unit.  */
 
 int
-attr_length_save_restore_dltp (insn)
-     rtx insn;
+attr_length_save_restore_dltp (rtx insn)
 {
   if (find_reg_note (insn, REG_NORETURN, NULL_RTX))
     return 0;
@@ -7240,8 +7708,7 @@ attr_length_save_restore_dltp (insn)
    space), and special magic is needed to construct their address.  */
 
 void
-hppa_encode_label (sym)
-     rtx sym;
+hppa_encode_label (rtx sym)
 {
   const char *str = XSTR (sym, 0);
   int len = strlen (str) + 1;
@@ -7255,10 +7722,7 @@ hppa_encode_label (sym)
 }
 
 static void
-pa_encode_section_info (decl, rtl, first)
-     tree decl;
-     rtx rtl;
-     int first;
+pa_encode_section_info (tree decl, rtx rtl, int first)
 {
   if (first && TEXT_SPACE_P (decl))
     {
@@ -7271,8 +7735,7 @@ pa_encode_section_info (decl, rtl, first)
 /* This is sort of inverse to pa_encode_section_info.  */
 
 static const char *
-pa_strip_name_encoding (str)
-     const char *str;
+pa_strip_name_encoding (const char *str)
 {
   str += (*str == '@');
   str += (*str == '*');
@@ -7280,9 +7743,7 @@ pa_strip_name_encoding (str)
 }
 
 int
-function_label_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+function_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
 }
@@ -7291,8 +7752,7 @@ function_label_operand (op, mode)
    with a constant.  Used to keep certain patterns from matching
    during instruction combination.  */
 int
-is_function_label_plus_const (op)
-     rtx op;
+is_function_label_plus_const (rtx op)
 {
   /* Strip off any CONST.  */
   if (GET_CODE (op) == CONST)
@@ -7306,12 +7766,9 @@ is_function_label_plus_const (op)
 /* Output assembly code for a thunk to FUNCTION.  */
 
 static void
-pa_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
-     FILE *file;
-     tree thunk_fndecl;
-     HOST_WIDE_INT delta;
-     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
-     tree function;
+pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
+                       HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+                       tree function)
 {
   const char *fname = XSTR (XEXP (DECL_RTL (function), 0), 0);
   const char *tname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
@@ -7465,7 +7922,7 @@ pa_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
            }
          else
            {
-             fprintf (file, "\tldsid (%%sr0,%%r22),%%r1\n");
+             fprintf (file, "\tldsid (%%sr0,%%r22),%%r21\n");
              fprintf (file, "\tmtsp %%r21,%%sr0\n");
              fprintf (file, "\tbe 0(%%sr0,%%r22)\n\tldo ");
              nbytes += 44;
@@ -7572,9 +8029,7 @@ pa_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
    It is safe to perform a sibcall optimization when the target function
    will never return.  */
 static bool
-pa_function_ok_for_sibcall (decl, exp)
-     tree decl;
-     tree exp ATTRIBUTE_UNUSED;
+pa_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
   /* Sibcalls are ok for TARGET_ELF32 as along as the linker is used in
      single subspace mode and the call is not indirect.  As far as I know,
@@ -7585,7 +8040,7 @@ pa_function_ok_for_sibcall (decl, exp)
     return (decl != NULL_TREE);
 
   /* Sibcalls are not ok because the arg pointer register is not a fixed
-     register.  This prevents the sibcall optimization from occuring.  In
+     register.  This prevents the sibcall optimization from occurring.  In
      addition, there are problems with stub placement using GNU ld.  This
      is because a normal sibcall branch uses a 17-bit relocation while
      a regular call branch uses a 22-bit relocation.  As a result, more
@@ -7601,8 +8056,7 @@ pa_function_ok_for_sibcall (decl, exp)
 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
    use in fmpyadd instructions.  */
 int
-fmpyaddoperands (operands)
-     rtx *operands;
+fmpyaddoperands (rtx *operands)
 {
   enum machine_mode mode = GET_MODE (operands[0]);
 
@@ -7659,9 +8113,7 @@ fmpyaddoperands (operands)
 
 #if !defined(USE_COLLECT2)
 static void
-pa_asm_out_constructor (symbol, priority)
-     rtx symbol;
-     int priority;
+pa_asm_out_constructor (rtx symbol, int priority)
 {
   if (!function_label_operand (symbol, VOIDmode))
     hppa_encode_label (symbol);
@@ -7678,9 +8130,7 @@ pa_asm_out_constructor (symbol, priority)
 }
 
 static void
-pa_asm_out_destructor (symbol, priority)
-     rtx symbol;
-     int priority;
+pa_asm_out_destructor (rtx symbol, int priority)
 {
   if (!function_label_operand (symbol, VOIDmode))
     hppa_encode_label (symbol);
@@ -7700,8 +8150,7 @@ pa_asm_out_destructor (symbol, priority)
 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
    use in fmpysub instructions.  */
 int
-fmpysuboperands (operands)
-     rtx *operands;
+fmpysuboperands (rtx *operands)
 {
   enum machine_mode mode = GET_MODE (operands[0]);
 
@@ -7755,9 +8204,7 @@ fmpysuboperands (operands)
 }
 
 int
-plus_xor_ior_operator (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+plus_xor_ior_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR
          || GET_CODE (op) == IOR);
@@ -7766,8 +8213,7 @@ plus_xor_ior_operator (op, mode)
 /* Return 1 if the given constant is 2, 4, or 8.  These are the valid
    constants for shadd instructions.  */
 static int
-shadd_constant_p (val)
-     int val;
+shadd_constant_p (int val)
 {
   if (val == 2 || val == 4 || val == 8)
     return 1;
@@ -7778,49 +8224,44 @@ shadd_constant_p (val)
 /* Return 1 if OP is a CONST_INT with the value 2, 4, or 8.  These are
    the valid constant for shadd instructions.  */
 int
-shadd_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+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 (op, mode)
-     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)
+borx_reg_operand (rtx op, enum machine_mode mode)
+{
+  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.  */
 
 int
-non_hard_reg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+non_hard_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER);
 }
@@ -7828,8 +8269,7 @@ non_hard_reg_operand (op, mode)
 /* Return 1 if INSN branches forward.  Should be using insn_addresses
    to avoid walking through all the insns...  */
 static int
-forward_branch_p (insn)
-     rtx insn;
+forward_branch_p (rtx insn)
 {
   rtx label = JUMP_LABEL (insn);
 
@@ -7846,18 +8286,14 @@ forward_branch_p (insn)
 
 /* Return 1 if OP is an equality comparison, else return 0.  */
 int
-eq_neq_comparison_operator (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+eq_neq_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
 }
 
 /* Return 1 if OP is an operator suitable for use in a movb instruction.  */
 int
-movb_comparison_operator (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+movb_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == EQ || GET_CODE (op) == NE
          || GET_CODE (op) == LT || GET_CODE (op) == GE);
@@ -7865,8 +8301,7 @@ movb_comparison_operator (op, mode)
 
 /* Return 1 if INSN is in the delay slot of a call instruction.  */
 int
-jump_in_call_delay (insn)
-     rtx insn;
+jump_in_call_delay (rtx insn)
 {
 
   if (GET_CODE (insn) != JUMP_INSN)
@@ -7889,9 +8324,7 @@ jump_in_call_delay (insn)
 /* Output an unconditional move and branch insn.  */
 
 const char *
-output_parallel_movb (operands, length)
-     rtx *operands;
-     int length;
+output_parallel_movb (rtx *operands, int length)
 {
   /* These are the cases in which we win.  */
   if (length == 4)
@@ -7920,9 +8353,7 @@ output_parallel_movb (operands, length)
 /* Output an unconditional add and branch insn.  */
 
 const char *
-output_parallel_addb (operands, length)
-     rtx *operands;
-     int length;
+output_parallel_addb (rtx *operands, int length)
 {
   /* To make life easy we want operand0 to be the shared input/output
      operand and operand1 to be the readonly operand.  */
@@ -7953,8 +8384,7 @@ output_parallel_addb (operands, length)
    the delay slot of the call.  */
 
 int
-following_call (insn)
-     rtx insn;
+following_call (rtx insn)
 {
   if (! TARGET_JUMP_IN_DELAY)
     return 0;
@@ -8002,7 +8432,8 @@ following_call (insn)
    The jump instructions within the table are special; we must be able
    to identify them during assembly output (if the jumps don't get filled
    we need to emit a nop rather than nullifying the delay slot)).  We
-   identify jumps in switch tables by marking the SET with DImode.
+   identify jumps in switch tables by using insns with the attribute
+   type TYPE_BTABLE_BRANCH.
 
    We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB
    insns.  This serves two purposes, first it prevents jump.c from
@@ -8012,7 +8443,7 @@ following_call (insn)
    when using GAS (allows for better link time optimizations).  */
 
 static void
-pa_reorg ()
+pa_reorg (void)
 {
   rtx insn;
 
@@ -8028,7 +8459,7 @@ pa_reorg ()
       /* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns.  */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
        {
-         rtx pattern, tmp, location;
+         rtx pattern, tmp, location, label;
          unsigned int length, i;
 
          /* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode.  */
@@ -8054,57 +8485,17 @@ pa_reorg ()
              location = NEXT_INSN (location);
 
              if (GET_CODE (pattern) == ADDR_VEC)
-               {
-                 /* Emit the jump itself.  */
-                 tmp = gen_jump (XEXP (XVECEXP (pattern, 0, i), 0));
-                 tmp = emit_jump_insn_after (tmp, location);
-                 JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
-                 /* It is easy to rely on the branch table markers
-                    during assembly output to trigger the correct code
-                    for a switch table jump with an unfilled delay slot,
-
-                    However, that requires state and assumes that we look
-                    at insns in order.
-
-                    We can't make such assumptions when computing the length
-                    of instructions.  Ugh.  We could walk the insn chain to
-                    determine if this instruction is in a branch table, but
-                    that can get rather expensive, particularly during the
-                    branch shortening phase of the compiler.
-
-                    So instead we mark this jump as being special.  This is
-                    far from ideal and knows that no code after this will
-                    muck around with the mode of the JUMP_INSN itself.  */
-                 PUT_MODE (tmp, SImode);
-                 LABEL_NUSES (JUMP_LABEL (tmp))++;
-                 location = NEXT_INSN (location);
-               }
+               label = XEXP (XVECEXP (pattern, 0, i), 0);
              else
-               {
-                 /* Emit the jump itself.  */
-                 tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0));
-                 tmp = emit_jump_insn_after (tmp, location);
-                 JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0);
-                 /* It is easy to rely on the branch table markers
-                    during assembly output to trigger the correct code
-                    for a switch table jump with an unfilled delay slot,
-
-                    However, that requires state and assumes that we look
-                    at insns in order.
-
-                    We can't make such assumptions when computing the length
-                    of instructions.  Ugh.  We could walk the insn chain to
-                    determine if this instruction is in a branch table, but
-                    that can get rather expensive, particularly during the
-                    branch shortening phase of the compiler.
-
-                    So instead we mark this jump as being special.  This is
-                    far from ideal and knows that no code after this will
-                    muck around with the mode of the JUMP_INSN itself.  */
-                 PUT_MODE (tmp, SImode);
-                 LABEL_NUSES (JUMP_LABEL (tmp))++;
-                 location = NEXT_INSN (location);
-               }
+               label = XEXP (XVECEXP (pattern, 1, i), 0);
+
+             tmp = gen_short_jump (label);
+
+             /* Emit the jump itself.  */
+             tmp = emit_jump_insn_after (tmp, location);
+             JUMP_LABEL (tmp) = label;
+             LABEL_NUSES (label)++;
+             location = NEXT_INSN (location);
 
              /* Emit a BARRIER after the jump.  */
              emit_barrier_after (location);
@@ -8122,7 +8513,12 @@ pa_reorg ()
     }
   else
     {
-      /* Sill need an end_brtab insn.  */
+      /* Still need brtab marker insns.  FIXME: the presence of these
+        markers disables output of the branch table to readonly memory,
+        and any alignment directives that might be needed.  Possibly,
+        the begin_brtab insn should be output before the label for the
+        table.  This doesn't matter at the moment since the tables are
+        always output in the text section.  */
       for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
        {
          /* Find an ADDR_VEC insn.  */
@@ -8183,7 +8579,7 @@ pa_reorg ()
       branch length restrictions.  */
 
 static void
-pa_combine_instructions ()
+pa_combine_instructions (void)
 {
   rtx anchor, new;
 
@@ -8379,10 +8775,8 @@ pa_combine_instructions ()
 }
 
 static int
-pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2)
-     rtx new, anchor, floater;
-     int reversed;
-     rtx dest, src1, src2;
+pa_can_combine_p (rtx new, rtx anchor, rtx floater, int reversed, rtx dest,
+                 rtx src1, rtx src2)
 {
   int insn_code_number;
   rtx start, end;
@@ -8457,8 +8851,7 @@ pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2)
    filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns
    in particular.  */
 int
-insn_refs_are_delayed (insn)
-     rtx insn;
+insn_refs_are_delayed (rtx insn)
 {
   return ((GET_CODE (insn) == INSN
           && GET_CODE (PATTERN (insn)) != SEQUENCE
@@ -8471,15 +8864,13 @@ insn_refs_are_delayed (insn)
    the mode is SF or DF. Then the value is returned in fr4 (32).
 
    This must perform the same promotions as PROMOTE_MODE, else
-   PROMOTE_FUNCTION_RETURN will not work correctly.
+   TARGET_PROMOTE_FUNCTION_RETURN will not work correctly.
 
    Small structures must be returned in a PARALLEL on PA64 in order
    to match the HP Compiler ABI.  */
 
 rtx
-function_value (valtype, func)
-    tree valtype;
-    tree func ATTRIBUTE_UNUSED;
+function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
 {
   enum machine_mode valmode;
 
@@ -8527,11 +8918,8 @@ function_value (valtype, func)
    ??? We might want to restructure this so that it looks more like other
    ports.  */
 rtx
-function_arg (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named ATTRIBUTE_UNUSED;
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
+             int named ATTRIBUTE_UNUSED)
 {
   int max_arg_words = (TARGET_64BIT ? 8 : 4);
   int alignment = 0;
@@ -8636,21 +9024,9 @@ function_arg (cum, mode, type, named)
          /* Structures 5 to 8 bytes in size are passed in the general
             registers in the same manner as other non floating-point
             objects.  The data is right-justified and zero-extended
-            to 64 bits.
-
-            This is magic.  Normally, using a PARALLEL results in left
-            justified data on a big-endian target.  However, using a
-            single double-word register provides the required right
-            justication for 5 to 8 byte structures.  This has nothing
-            to do with the direction of padding specified for the argument.
-            It has to do with how the data is widened and shifted into
-            and from the register.
-
-            Aside from adding load_multiple and store_multiple patterns,
-            this is the only way that I have found to obtain right
-            justification of BLKmode data when it has a size greater
-            than one word.  Splitting the operation into two SImode loads
-            or returning a DImode REG results in left justified data.  */
+            to 64 bits.  This is opposite to the normal justification
+            used on big endian targets and requires special treatment.
+            We now define BLOCK_REG_PADDING to pad these objects.  */
          if (mode == BLKmode)
            {
              rtx loc = gen_rtx_EXPR_LIST (VOIDmode,
@@ -8730,11 +9106,8 @@ function_arg (cum, mode, type, named)
    then this routine should return zero. It is currently called only for
    the 64-bit target.  */
 int
-function_arg_partial_nregs (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named ATTRIBUTE_UNUSED;
+function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                           tree type, int named ATTRIBUTE_UNUSED)
 {
   unsigned int max_arg_words = 8;
   unsigned int offset = 0;
@@ -8758,9 +9131,7 @@ function_arg_partial_nregs (cum, mode, type, named)
    MATCH_OPERATOR to recognize all the branch insns.  */
 
 int
-cmpib_comparison_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
+cmpib_comparison_operator (rtx op, enum machine_mode mode)
 {
   return ((mode == VOIDmode || GET_MODE (op) == mode)
           && (GET_CODE (op) == EQ
@@ -8779,10 +9150,8 @@ cmpib_comparison_operator (op, mode)
    not be placed in the read-only data section.  */
 
 static void
-pa_select_section (exp, reloc, align)
-     tree exp;
-     int reloc;
-     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+pa_select_section (tree exp, int reloc,
+                  unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (exp) == VAR_DECL
       && TREE_READONLY (exp)
@@ -8793,7 +9162,6 @@ pa_select_section (exp, reloc, align)
       && !reloc)
     readonly_data_section ();
   else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
-          && !(TREE_CODE (exp) == STRING_CST && flag_writable_strings)
           && !reloc)
     readonly_data_section ();
   else
@@ -8801,9 +9169,7 @@ pa_select_section (exp, reloc, align)
 }
 
 static void
-pa_globalize_label (stream, name)
-     FILE *stream;
-     const char *name;
+pa_globalize_label (FILE *stream, const char *name)
 {
   /* We only handle DATA objects here, functions are globalized in
      ASM_DECLARE_FUNCTION_NAME.  */
@@ -8814,4 +9180,31 @@ pa_globalize_label (stream, name)
     fputs (",DATA\n", stream);
   }
 }
+
+/* Worker function for TARGET_STRUCT_VALUE_RTX.  */
+
+static rtx
+pa_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
+                    int incoming ATTRIBUTE_UNUSED)
+{
+  return gen_rtx_REG (Pmode, PA_STRUCT_VALUE_REGNUM);
+}
+
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+bool
+pa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+  /* SOM ABI says that objects larger than 64 bits are returned in memory.
+     PA64 ABI says that objects larger than 128 bits are returned in memory.
+     Note, int_size_in_bytes can return -1 if the size of the object is
+     variable or larger than the maximum value that can be expressed as
+     a HOST_WIDE_INT.   It can also return zero for an empty type.  The
+     simplest way to handle variable and empty types is to pass them in
+     memory.  This avoids problems in defining the boundaries of argument
+     slots, allocating registers, etc.  */
+  return (int_size_in_bytes (type) > (TARGET_64BIT ? 16 : 8)
+         || int_size_in_bytes (type) <= 0);
+}
+
 #include "gt-pa.h"