OSDN Git Service

* pa.h (TARGET_LONG_PIC_SDIFF_CALL): Conditionalize define on
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / pa.c
index 0eeb163..8076c40 100644 (file)
@@ -1,13 +1,13 @@
 /* Subroutines for insn-output.c for HPPA.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
 
 This file is part of GCC.
 
 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +16,8 @@ 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 GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -47,6 +46,7 @@ Boston, MA 02110-1301, USA.  */
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
 
 /* Return nonzero if there is a bypass for the output of 
    OUT_INSN and the fp store IN_INSN.  */
@@ -58,7 +58,8 @@ hppa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
   rtx set;
 
   if (recog_memoized (in_insn) < 0
-      || get_attr_type (in_insn) != TYPE_FPSTORE
+      || (get_attr_type (in_insn) != TYPE_FPSTORE
+         && get_attr_type (in_insn) != TYPE_FPSTORE_LOAD)
       || recog_memoized (out_insn) < 0)
     return 0;
 
@@ -107,7 +108,8 @@ 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)
+static void pa_som_asm_init_sections (void) ATTRIBUTE_UNUSED;
+static section *pa_select_section (tree, int, unsigned HOST_WIDE_INT)
      ATTRIBUTE_UNUSED;
 static void pa_encode_section_info (tree, rtx, int);
 static const char *pa_strip_name_encoding (const char *);
@@ -122,9 +124,10 @@ static void pa_asm_out_destructor (rtx, int);
 #endif
 static void pa_init_builtins (void);
 static rtx hppa_builtin_saveregs (void);
+static void hppa_va_start (tree, rtx);
 static tree hppa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 static bool pa_scalar_mode_supported_p (enum machine_mode);
-static bool pa_commutative_p (rtx x, int outer_code);
+static bool pa_commutative_p (const_rtx x, int outer_code);
 static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
 static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
 static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;
@@ -146,11 +149,19 @@ static void pa_hpux_init_libfuncs (void);
 #endif
 static rtx pa_struct_value_rtx (tree, int);
 static bool pa_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
-                                 tree, bool);
+                                 const_tree, bool);
 static int pa_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                 tree, bool);
 static struct machine_function * pa_init_machine_status (void);
+static enum reg_class pa_secondary_reload (bool, rtx, enum reg_class,
+                                          enum machine_mode,
+                                          secondary_reload_info *);
+static void pa_extra_live_on_entry (bitmap);
 
+/* The following extra sections are only used for SOM.  */
+static GTY(()) section *som_readonly_data_section;
+static GTY(()) section *som_one_only_readonly_data_section;
+static GTY(()) section *som_one_only_data_section;
 
 /* Save the operands last given to a compare for use when we
    generate a scc or bcc insn.  */
@@ -167,6 +178,10 @@ int flag_pa_unix = TARGET_HPUX_11_11 ? 1998 : TARGET_HPUX_10_10 ? 1995 : 1993;
    registers which were saved by the current function's prologue.  */
 static int gr_saved, fr_saved;
 
+/* Boolean indicating whether the return pointer was saved by the
+   current function's prologue.  */
+static bool rp_saved;
+
 static rtx find_addr_reg (rtx);
 
 /* Keep track of the number of bytes we have output in the CODE subspace
@@ -271,9 +286,9 @@ static size_t n_deferred_plabels = 0;
 #endif
 
 #undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
 #undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
 #undef TARGET_STRUCT_VALUE_RTX
 #define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx
@@ -290,6 +305,8 @@ static size_t n_deferred_plabels = 0;
 
 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
 #define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs
+#undef TARGET_EXPAND_BUILTIN_VA_START
+#define TARGET_EXPAND_BUILTIN_VA_START hppa_va_start
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR hppa_gimplify_va_arg_expr
 
@@ -299,6 +316,12 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_CANNOT_FORCE_CONST_MEM
 #define TARGET_CANNOT_FORCE_CONST_MEM pa_tls_referenced_p
 
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD pa_secondary_reload
+
+#undef TARGET_EXTRA_LIVE_ON_ENTRY
+#define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Parse the -mfixed-range= option string.  */
@@ -495,8 +518,16 @@ static void
 pa_init_builtins (void)
 {
 #ifdef DONT_HAVE_FPUTC_UNLOCKED
-  built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] = NULL_TREE;
-  implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] = NULL_TREE;
+  built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] =
+    built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
+  implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED]
+    = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
+#endif
+#if TARGET_HPUX_11
+  if (built_in_decls [BUILT_IN_FINITE])
+    set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], "_Isfinite");
+  if (built_in_decls [BUILT_IN_FINITEF])
+    set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef");
 #endif
 }
 
@@ -537,12 +568,12 @@ symbolic_expression_p (rtx x)
 /* Accept any constant that can be moved in one instruction into a
    general register.  */
 int
-cint_ok_for_move (HOST_WIDE_INT intval)
+cint_ok_for_move (HOST_WIDE_INT ival)
 {
   /* OK if ldo, ldil, or zdepi, can be used.  */
-  return (CONST_OK_FOR_LETTER_P (intval, 'J')
-         || CONST_OK_FOR_LETTER_P (intval, 'N')
-         || CONST_OK_FOR_LETTER_P (intval, 'K'));
+  return (VAL_14_BITS_P (ival)
+         || ldil_cint_p (ival)
+         || zdepi_cint_p (ival));
 }
 \f
 /* Return truth value of whether OP can be used as an operand in a
@@ -555,8 +586,38 @@ adddi3_operand (rtx op, enum machine_mode mode)
              && (TARGET_64BIT ? INT_14_BITS (op) : INT_11_BITS (op))));
 }
 
+/* True iff the operand OP can be used as the destination operand of
+   an integer store.  This also implies the operand could be used as
+   the source operand of an integer load.  Symbolic, lo_sum and indexed
+   memory operands are not allowed.  We accept reloading pseudos and
+   other memory operands.  */
+int
+integer_store_memory_operand (rtx op, enum machine_mode mode)
+{
+  return ((reload_in_progress
+          && REG_P (op)
+          && REGNO (op) >= FIRST_PSEUDO_REGISTER
+          && reg_renumber [REGNO (op)] < 0)
+         || (GET_CODE (op) == MEM
+             && (reload_in_progress || memory_address_p (mode, XEXP (op, 0)))
+             && !symbolic_memory_operand (op, VOIDmode)
+             && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0))
+             && !IS_INDEX_ADDR_P (XEXP (op, 0))));
+}
+
+/* True iff ldil can be used to load this CONST_INT.  The least
+   significant 11 bits of the value must be zero and the value must
+   not change sign when extended from 32 to 64 bits.  */
+int
+ldil_cint_p (HOST_WIDE_INT ival)
+{
+  HOST_WIDE_INT x = ival & (((HOST_WIDE_INT) -1 << 31) | 0x7ff);
+
+  return x == 0 || x == ((HOST_WIDE_INT) -1 << 31);
+}
+
 /* True iff zdepi can be used to generate this CONST_INT.
-   zdepi first sign extends a 5 bit signed number to a given field
+   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 (unsigned HOST_WIDE_INT x)
@@ -607,6 +668,8 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
   /* Labels need special handling.  */
   if (pic_label_operand (orig, mode))
     {
+      rtx insn;
+
       /* We do not want to go through the movXX expanders here since that
         would create recursion.
 
@@ -617,7 +680,24 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
         So instead we just emit the raw set, which avoids the movXX
         expanders completely.  */
       mark_reg_pointer (reg, BITS_PER_UNIT);
-      emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
+      insn = emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
+
+      /* 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));
+
+      /* During and after reload, we need to generate a REG_LABEL_OPERAND note
+        and update LABEL_NUSES because this is not done automatically.  */
+      if (reload_in_progress || reload_completed)
+       {
+         /* Extract LABEL_REF.  */
+         if (GET_CODE (orig) == CONST)
+           orig = XEXP (XEXP (orig, 0), 0);
+         /* Extract CODE_LABEL.  */
+         orig = XEXP (orig, 0);
+         REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, orig,
+                                               REG_NOTES (insn));
+         LABEL_NUSES (orig)++;
+       }
       current_function_uses_pic_offset_table = 1;
       return reg;
     }
@@ -633,22 +713,44 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
       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_const_mem (Pmode,
-                        gen_rtx_LO_SUM (Pmode, tmp_reg,
-                                        gen_rtx_UNSPEC (Pmode,
+      if (function_label_operand (orig, mode))
+       {
+         /* Force function label into memory.  */
+         orig = XEXP (force_const_mem (mode, orig), 0);
+         /* Load plabel address from DLT.  */
+         emit_move_insn (tmp_reg,
+                         gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
+                                       gen_rtx_HIGH (word_mode, orig)));
+         pic_ref
+           = gen_const_mem (Pmode,
+                            gen_rtx_LO_SUM (Pmode, tmp_reg,
+                                            gen_rtx_UNSPEC (Pmode,
                                                         gen_rtvec (1, orig),
                                                         UNSPEC_DLTIND14R)));
+         emit_move_insn (reg, pic_ref);
+         /* Now load address of function descriptor.  */
+         pic_ref = gen_rtx_MEM (Pmode, reg);
+       }
+      else
+       {
+         /* Load symbol reference from DLT.  */
+         emit_move_insn (tmp_reg,
+                         gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
+                                       gen_rtx_HIGH (word_mode, orig)));
+         pic_ref
+           = gen_const_mem (Pmode,
+                            gen_rtx_LO_SUM (Pmode, tmp_reg,
+                                            gen_rtx_UNSPEC (Pmode,
+                                                        gen_rtvec (1, orig),
+                                                        UNSPEC_DLTIND14R)));
+       }
 
       current_function_uses_pic_offset_table = 1;
       mark_reg_pointer (reg, BITS_PER_UNIT);
       insn = emit_move_insn (reg, pic_ref);
 
       /* Put a REG_EQUAL note on this insn, so that it can be optimized.  */
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn));
+      set_unique_reg_note (insn, REG_EQUAL, orig);
 
       return reg;
     }
@@ -712,7 +814,10 @@ legitimize_tls_address (rtx addr)
     {
       case TLS_MODEL_GLOBAL_DYNAMIC:
        tmp = gen_reg_rtx (Pmode);
-       emit_insn (gen_tgd_load (tmp, addr));
+       if (flag_pic)
+         emit_insn (gen_tgd_load_pic (tmp, addr));
+       else
+         emit_insn (gen_tgd_load (tmp, addr));
        ret = hppa_tls_call (tmp);
        break;
 
@@ -720,7 +825,10 @@ legitimize_tls_address (rtx addr)
        ret = gen_reg_rtx (Pmode);
        tmp = gen_reg_rtx (Pmode);
        start_sequence ();
-       emit_insn (gen_tld_load (tmp, addr));
+       if (flag_pic)
+         emit_insn (gen_tld_load_pic (tmp, addr));
+       else
+         emit_insn (gen_tld_load (tmp, addr));
        t1 = hppa_tls_call (tmp);
        insn = get_insns ();
        end_sequence ();
@@ -736,7 +844,10 @@ legitimize_tls_address (rtx addr)
        tmp = gen_reg_rtx (Pmode);
        ret = gen_reg_rtx (Pmode);
        emit_insn (gen_tp_load (tp));
-       emit_insn (gen_tie_load (tmp, addr));
+       if (flag_pic)
+         emit_insn (gen_tie_load_pic (tmp, addr));
+       else
+         emit_insn (gen_tie_load (tmp, addr));
        emit_move_insn (ret, gen_rtx_PLUS (Pmode, tp, tmp));
        break;
 
@@ -856,7 +967,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       int mask;
 
       mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
-             ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff);
+             ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff);
 
       /* Choose which way to round the offset.  Round up if we
         are >= halfway to the next boundary.  */
@@ -1316,8 +1427,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
      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.  */
-      gcc_assert (!no_new_pseudos);
+      gcc_assert (can_create_pseudo_p ());
 
       tem = copy_to_mode_reg (Pmode, XEXP (operand0, 0));
       operand0 = replace_equiv_address (operand0, tem);
@@ -1879,6 +1989,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx 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) <= BITS_PER_WORD
              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
              && !insert)
            {
@@ -1963,8 +2074,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
                }
            }
 
-         REG_NOTES (insn)
-           = gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (insn));
+         set_unique_reg_note (insn, REG_EQUAL, op1);
 
          return 1;
        }
@@ -1986,6 +2096,7 @@ reloc_needed (tree exp)
     case ADDR_EXPR:
       return 1;
 
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
     case MINUS_EXPR:
       reloc = reloc_needed (TREE_OPERAND (exp, 0));
@@ -2195,6 +2306,25 @@ output_move_double (rtx *operands)
      supposed to allow to happen.  */
   gcc_assert (optype0 == REGOP || optype1 == REGOP);
 
+  /* Handle copies between general and floating registers.  */
+
+  if (optype0 == REGOP && optype1 == REGOP
+      && FP_REG_P (operands[0]) ^ FP_REG_P (operands[1]))
+    {
+      if (FP_REG_P (operands[0]))
+       {
+         output_asm_insn ("{stws|stw} %1,-16(%%sp)", operands);
+         output_asm_insn ("{stws|stw} %R1,-12(%%sp)", operands);
+         return "{fldds|fldd} -16(%%sp),%0";
+       }
+      else
+       {
+         output_asm_insn ("{fstds|fstd} %1,-16(%%sp)", operands);
+         output_asm_insn ("{ldws|ldw} -16(%%sp),%0", operands);
+         return "{ldws|ldw} -12(%%sp),%R0";
+       }
+    }
+
    /* Handle auto decrementing and incrementing loads and stores
      specifically, since the structure of the function doesn't work
      for them without major modification.  Do it better when we learn
@@ -2304,12 +2434,11 @@ output_move_double (rtx *operands)
       else if (GET_CODE (addr) == PLUS
               && GET_CODE (XEXP (addr, 0)) == MULT)
        {
+         rtx xoperands[4];
          rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
 
          if (!reg_overlap_mentioned_p (high_reg, addr))
            {
-             rtx xoperands[3];
-
              xoperands[0] = high_reg;
              xoperands[1] = XEXP (addr, 1);
              xoperands[2] = XEXP (XEXP (addr, 0), 0);
@@ -2320,8 +2449,6 @@ output_move_double (rtx *operands)
            }
          else
            {
-             rtx xoperands[3];
-
              xoperands[0] = high_reg;
              xoperands[1] = XEXP (addr, 1);
              xoperands[2] = XEXP (XEXP (addr, 0), 0);
@@ -3415,13 +3542,13 @@ compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
 
   /* Account for space used by the callee general register saves.  */
   for (i = 18, j = frame_pointer_needed ? 4 : 3; i >= j; i--)
-    if (regs_ever_live[i])
+    if (df_regs_ever_live_p (i))
       size += UNITS_PER_WORD;
 
   /* Account for space used by the callee floating point register saves.  */
   for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
-    if (regs_ever_live[i]
-       || (!TARGET_64BIT && regs_ever_live[i + 1]))
+    if (df_regs_ever_live_p (i)
+       || (!TARGET_64BIT && df_regs_ever_live_p (i + 1)))
       {
        freg_saved = 1;
 
@@ -3486,10 +3613,12 @@ pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
      to output the assembler directives which denote the start
      of a function.  */
   fprintf (file, "\t.CALLINFO FRAME=" HOST_WIDE_INT_PRINT_DEC, actual_fsize);
-  if (regs_ever_live[2])
-    fputs (",CALLS,SAVE_RP", file);
-  else
+  if (current_function_is_leaf)
     fputs (",NO_CALLS", file);
+  else
+    fputs (",CALLS", file);
+  if (rp_saved)
+    fputs (",SAVE_RP", file);
 
   /* The SAVE_SP flag is used to indicate that register %r3 is stored
      at the beginning of the frame and that it is used as the frame
@@ -3550,8 +3679,13 @@ hppa_expand_prologue (void)
   /* Save RP first.  The calling conventions manual states RP will
      always be stored into the caller's frame at sp - 20 or sp - 16
      depending on which ABI is in use.  */
-  if (regs_ever_live[2] || current_function_calls_eh_return)
-    store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
+  if (df_regs_ever_live_p (2) || current_function_calls_eh_return)
+    {
+      store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
+      rp_saved = true;
+    }
+  else
+    rp_saved = false;
 
   /* Allocate the local frame and set up the frame pointer if needed.  */
   if (actual_fsize != 0)
@@ -3661,7 +3795,7 @@ hppa_expand_prologue (void)
        }
 
       for (i = 18; i >= 4; i--)
-       if (regs_ever_live[i] && ! call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ! call_used_regs[i])
          {
            store_reg (i, offset, FRAME_POINTER_REGNUM);
            offset += UNITS_PER_WORD;
@@ -3701,7 +3835,7 @@ hppa_expand_prologue (void)
        }
 
       for (i = 18; i >= 3; i--)
-       if (regs_ever_live[i] && ! call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ! call_used_regs[i])
          {
            /* If merge_sp_adjust_with_store is nonzero, then we can
               optimize the first GR save.  */
@@ -3764,8 +3898,8 @@ hppa_expand_prologue (void)
       /* Now actually save the FP registers.  */
       for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
        {
-         if (regs_ever_live[i]
-             || (! TARGET_64BIT && regs_ever_live[i + 1]))
+         if (df_regs_ever_live_p (i)
+             || (! TARGET_64BIT && df_regs_ever_live_p (i + 1)))
            {
              rtx addr, insn, reg;
              addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
@@ -3920,7 +4054,8 @@ pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
       /* We done with this subspace except possibly for some additional
         debug information.  Forget that we are in this subspace to ensure
         that the next function is output in its own subspace.  */
-      forget_section ();
+      in_section = NULL;
+      cfun->machine->in_nsubspa = 2;
     }
 
   if (INSN_ADDRESSES_SET_P ())
@@ -3952,7 +4087,7 @@ hppa_expand_epilogue (void)
   /* Try to restore RP early to avoid load/use interlocks when
      RP gets used in the return (bv) instruction.  This appears to still
      be necessary even when we schedule the prologue and epilogue.  */
-  if (regs_ever_live [2] || current_function_calls_eh_return)
+  if (rp_saved)
     {
       ret_off = TARGET_64BIT ? -16 : -20;
       if (frame_pointer_needed)
@@ -3994,7 +4129,7 @@ hppa_expand_epilogue (void)
        }
 
       for (i = 18; i >= 4; i--)
-       if (regs_ever_live[i] && ! call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ! call_used_regs[i])
          {
            load_reg (i, offset, FRAME_POINTER_REGNUM);
            offset += UNITS_PER_WORD;
@@ -4031,7 +4166,7 @@ hppa_expand_epilogue (void)
 
       for (i = 18; i >= 3; i--)
        {
-         if (regs_ever_live[i] && ! call_used_regs[i])
+         if (df_regs_ever_live_p (i) && ! call_used_regs[i])
            {
              /* Only for the first load.
                 merge_sp_adjust_with_load holds the register load
@@ -4061,8 +4196,8 @@ hppa_expand_epilogue (void)
 
       /* Actually do the restores now.  */
       for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
-       if (regs_ever_live[i]
-           || (! TARGET_64BIT && regs_ever_live[i + 1]))
+       if (df_regs_ever_live_p (i)
+           || (! TARGET_64BIT && df_regs_ever_live_p (i + 1)))
          {
            rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
            rtx dest = gen_rtx_REG (DFmode, i);
@@ -4124,9 +4259,6 @@ hppa_pic_save_rtx (void)
 #define NO_DEFERRED_PROFILE_COUNTERS 0
 #endif
 
-/* Define heap vector type for funcdef numbers.  */
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int,heap);
 
 /* Vector of funcdef numbers.  */
 static VEC(int,heap) *funcdef_nos;
@@ -4141,7 +4273,7 @@ output_deferred_profile_counters (void)
   if (VEC_empty (int, funcdef_nos))
    return;
 
-  data_section ();
+  switch_to_section (data_section);
   align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
   ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
 
@@ -4176,7 +4308,7 @@ hppa_profile_hook (int 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-
+  /* The address of the function is loaded into %r25 with an 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.  */
@@ -4303,8 +4435,10 @@ return_addr_rtx (int count, rtx frameaddr)
                 GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
   emit_jump_insn (gen_bne (label));
 
+  /* 0xe0400002 must be specified as -532676606 so that it won't be
+     rejected as an invalid immediate operand on 64-bit hosts.  */
   emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
-                GEN_INT (0xe0400002), NE, NULL_RTX, SImode, 1);
+                GEN_INT (-532676606), NE, NULL_RTX, SImode, 1);
 
   /* If there is no export stub then just use the value saved from
      the return pointer register.  */
@@ -4326,22 +4460,6 @@ return_addr_rtx (int count, rtx frameaddr)
   return saved_rp;
 }
 
-/* This is only valid once reload has completed because it depends on
-   knowing exactly how much (if any) frame there is and...
-
-   It's only valid if there is no frame marker to de-allocate and...
-
-   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 (void)
-{
-  return (reload_completed
-         && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
-         && ! regs_ever_live[2]
-         && ! frame_pointer_needed);
-}
-
 void
 emit_bcond_fp (enum rtx_code code, rtx operand0)
 {
@@ -5286,19 +5404,20 @@ static void
 output_deferred_plabels (void)
 {
   size_t i;
-  /* If we have deferred plabels, then we need to switch into the data
-     section and align it to a 4 byte boundary before we output the
-     deferred plabels.  */
+
+  /* If we have some deferred plabels, then we need to switch into the
+     data or readonly data section, and align it to a 4 byte boundary
+     before outputting the deferred plabels.  */
   if (n_deferred_plabels)
     {
-      data_section ();
+      switch_to_section (flag_pic ? data_section : readonly_data_section);
       ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2);
     }
 
   /* Now output the deferred plabels.  */
   for (i = 0; i < n_deferred_plabels; i++)
     {
-      (*targetm.asm_out.internal_label) (asm_out_file, "L",
+      targetm.asm_out.internal_label (asm_out_file, "L",
                 CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
       assemble_integer (deferred_plabels[i].symbol,
                        TARGET_64BIT ? 8 : 4, TARGET_64BIT ? 64 : 32, 1);
@@ -5342,6 +5461,8 @@ pa_hpux_init_libfuncs (void)
 
   set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
   set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+  set_conv_libfunc (ufloat_optab, TFmode, SImode, "_U_Qfcnvxf_usgl_to_quad");
+  set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxf_udbl_to_quad");
 }
 #endif
 
@@ -5565,104 +5686,174 @@ output_arg_descriptor (rtx call_insn)
   fputc ('\n', asm_out_file);
 }
 \f
-/* Return the class of any secondary reload register that is needed to
-   move IN into a register in class CLASS using mode MODE.
-
-   Profiling has showed this routine and its descendants account for
-   a significant amount of compile time (~7%).  So it has been
-   optimized to reduce redundant computations and eliminate useless
-   function calls.
-
-   It might be worthwhile to try and make this a leaf function too.  */
-
-enum reg_class
-pa_secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx in)
+static enum reg_class
+pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
+                    enum machine_mode mode, secondary_reload_info *sri)
 {
-  int regno, is_symbolic;
+  int is_symbolic, regno;
 
-  /* Trying to load a constant into a FP register during PIC code
-     generation will require %r1 as a scratch register.  */
-  if (flag_pic
-      && GET_MODE_CLASS (mode) == MODE_INT
-      && FP_REG_CLASS_P (class)
-      && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
-    return R1_REGS;
-
-  /* Profiling showed the PA port spends about 1.3% of its compilation
-     time in true_regnum from calls inside pa_secondary_reload_class.  */
+  /* Handle the easy stuff first.  */
+  if (class == R1_REGS)
+    return NO_REGS;
 
-  if (GET_CODE (in) == REG)
+  if (REG_P (x))
     {
-      regno = REGNO (in);
-      if (regno >= FIRST_PSEUDO_REGISTER)
-       regno = true_regnum (in);
+      regno = REGNO (x);
+      if (class == BASE_REG_CLASS && regno < FIRST_PSEUDO_REGISTER)
+       return NO_REGS;
     }
-  else if (GET_CODE (in) == SUBREG)
-    regno = true_regnum (in);
   else
     regno = -1;
 
   /* If we have something like (mem (mem (...)), we can safely assume the
      inner MEM will end up in a general register after reloading, so there's
      no need for a secondary reload.  */
-  if (GET_CODE (in) == MEM
-      && GET_CODE (XEXP (in, 0)) == MEM)
+  if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == MEM)
     return NO_REGS;
 
-  /* Handle out of range displacement for integer mode loads/stores of
-     FP registers.  */
-  if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
-       && GET_MODE_CLASS (mode) == MODE_INT
-       && FP_REG_CLASS_P (class))
-      || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
-    return GENERAL_REGS;
+  /* Trying to load a constant into a FP register during PIC code
+     generation requires %r1 as a scratch register.  */
+  if (flag_pic
+      && (mode == SImode || mode == DImode)
+      && FP_REG_CLASS_P (class)
+      && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
+    {
+      sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
+                   : CODE_FOR_reload_indi_r1);
+      return NO_REGS;
+    }
+
+  /* Profiling showed the PA port spends about 1.3% of its compilation
+     time in true_regnum from calls inside pa_secondary_reload_class.  */
+  if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
+    regno = true_regnum (x);
+
+  /* In order to allow 14-bit displacements in integer loads and stores,
+     we need to prevent reload from generating out of range integer mode
+     loads and stores to the floating point registers.  Previously, we
+     used to call for a secondary reload and have emit_move_sequence()
+     fix the instruction sequence.  However, reload occasionally wouldn't
+     generate the reload and we would end up with an invalid REG+D memory
+     address.  So, now we use an intermediate general register for most
+     memory loads and stores.  */
+  if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && FP_REG_CLASS_P (class))
+    {
+      /* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check
+        the secondary reload needed for a pseudo.  It never passes a
+        REG+D address.  */
+      if (GET_CODE (x) == MEM)
+       {
+         x = XEXP (x, 0);
+
+         /* We don't need an intermediate for indexed and LO_SUM DLT
+            memory addresses.  When INT14_OK_STRICT is true, it might
+            appear that we could directly allow register indirect
+            memory addresses.  However, this doesn't work because we
+            don't support SUBREGs in floating-point register copies
+            and reload doesn't tell us when it's going to use a SUBREG.  */
+         if (IS_INDEX_ADDR_P (x)
+             || IS_LO_SUM_DLT_ADDR_P (x))
+           return NO_REGS;
+
+         /* Otherwise, we need an intermediate general register.  */
+         return GENERAL_REGS;
+       }
+
+      /* Request a secondary reload with a general scratch register
+        for everthing else.  ??? Could symbolic operands be handled
+        directly when generating non-pic PA 2.0 code?  */
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
+
+  /* We need a secondary register (GPR) for copies between the SAR
+     and anything other than a general register.  */
+  if (class == SHIFT_REGS && (regno <= 0 || regno >= 32))
+    {
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
 
   /* A SAR<->FP register copy requires a secondary register (GPR) as
      well as secondary memory.  */
   if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
-      && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
-         || (class == SHIFT_REGS && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
-    return GENERAL_REGS;
+      && (REGNO_REG_CLASS (regno) == SHIFT_REGS
+      && FP_REG_CLASS_P (class)))
+    {
+      sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
+      return NO_REGS;
+    }
 
-  if (GET_CODE (in) == HIGH)
-    in = XEXP (in, 0);
+  /* Secondary reloads of symbolic operands require %r1 as a scratch
+     register when we're generating PIC code and when the operand isn't
+     readonly.  */
+  if (GET_CODE (x) == HIGH)
+    x = XEXP (x, 0);
 
   /* Profiling has showed GCC spends about 2.6% of its compilation
      time in symbolic_operand from calls inside pa_secondary_reload_class.
-
-     We use an inline copy and only compute its return value once to avoid
-     useless work.  */
-  switch (GET_CODE (in))
+     So, we use an inline copy to avoid useless work.  */
+  switch (GET_CODE (x))
     {
-      rtx tmp;
+      rtx op;
 
       case SYMBOL_REF:
+        is_symbolic = !SYMBOL_REF_TLS_MODEL (x);
+        break;
       case LABEL_REF:
         is_symbolic = 1;
         break;
       case CONST:
-       tmp = XEXP (in, 0);
-       is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
-                       || GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
-                      && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
+       op = XEXP (x, 0);
+       is_symbolic = (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+                        && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+                       || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+                      && GET_CODE (XEXP (op, 1)) == CONST_INT);
         break;
-
       default:
         is_symbolic = 0;
         break;
     }
 
-  if (!flag_pic
-      && is_symbolic
-      && read_only_operand (in, VOIDmode))
-    return NO_REGS;
-
-  if (class != R1_REGS && is_symbolic)
-    return R1_REGS;
+  if (is_symbolic && (flag_pic || !read_only_operand (x, VOIDmode)))
+    {
+      gcc_assert (mode == SImode || mode == DImode);
+      sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
+                   : CODE_FOR_reload_indi_r1);
+    }
 
   return NO_REGS;
 }
 
+/* Implement TARGET_EXTRA_LIVE_ON_ENTRY.  The argument pointer
+   is only marked as live on entry by df-scan when it is a fixed
+   register.  It isn't a fixed register in the 64-bit runtime,
+   so we need to mark it here.  */
+
+static void
+pa_extra_live_on_entry (bitmap regs)
+{
+  if (TARGET_64BIT)
+    bitmap_set_bit (regs, ARG_POINTER_REGNUM);
+}
+
+/* Implement EH_RETURN_HANDLER_RTX.  The MEM needs to be volatile
+   to prevent it from being deleted.  */
+
+rtx
+pa_eh_return_handler_rtx (void)
+{
+  rtx tmp;
+
+  tmp = gen_rtx_PLUS (word_mode, frame_pointer_rtx,
+                     TARGET_64BIT ? GEN_INT (-16) : GEN_INT (-20));
+  tmp = gen_rtx_MEM (word_mode, tmp);
+  tmp->volatil = 1;
+  return tmp;
+}
+
 /* 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.
@@ -5678,7 +5869,7 @@ pa_secondary_reload_class (enum reg_class class, enum machine_mode mode, rtx in)
 
 static bool
 pa_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-                     enum machine_mode mode, tree type,
+                     enum machine_mode mode, const_tree type,
                      bool named ATTRIBUTE_UNUSED)
 {
   HOST_WIDE_INT size;
@@ -5695,7 +5886,7 @@ pa_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
 }
 
 enum direction
-function_arg_padding (enum machine_mode mode, tree type)
+function_arg_padding (enum machine_mode mode, const_tree type)
 {
   if (mode == BLKmode
       || (TARGET_64BIT && type && AGGREGATE_TYPE_P (type)))
@@ -5802,7 +5993,7 @@ hppa_builtin_saveregs (void)
                                    offset, 0, 0, OPTAB_LIB_WIDEN));
 }
 
-void
+static void
 hppa_va_start (tree valist, rtx nextarg)
 {
   nextarg = expand_builtin_saveregs ();
@@ -5836,21 +6027,24 @@ hppa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
 
       /* Args grow down.  Not handled by generic routines.  */
 
-      u = fold_convert (valist_type, size_in_bytes (type));
-      t = build (MINUS_EXPR, valist_type, valist, u);
+      u = fold_convert (sizetype, size_in_bytes (type));
+      u = fold_build1 (NEGATE_EXPR, sizetype, u);
+      t = build2 (POINTER_PLUS_EXPR, valist_type, valist, u);
 
       /* 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_cst (valist_type, (size > 4 ? -8 : -4));
-      t = build (BIT_AND_EXPR, valist_type, t, u);
+      u = size_int (size > 4 ? -8 : -4);
+      t = fold_convert (sizetype, t);
+      t = build2 (BIT_AND_EXPR, sizetype, t, u);
+      t = fold_convert (valist_type, t);
 
-      t = build (MODIFY_EXPR, valist_type, valist, t);
+      t = build2 (MODIFY_EXPR, valist_type, valist, t);
 
       ofs = (8 - size) % 4;
       if (ofs != 0)
        {
-         u = fold_convert (valist_type, size_int (ofs));
-         t = build (PLUS_EXPR, valist_type, t, u);
+         u = size_int (ofs);
+         t = build2 (POINTER_PLUS_EXPR, valist_type, t, u);
        }
 
       t = fold_convert (ptr, t);
@@ -5902,6 +6096,9 @@ pa_scalar_mode_supported_p (enum machine_mode mode)
        return true;
       return false;
 
+    case MODE_DECIMAL_FLOAT:
+      return false;
+
     default:
       gcc_unreachable ();
     }
@@ -5915,11 +6112,13 @@ pa_scalar_mode_supported_p (enum machine_mode mode)
    parameters.  */
 
 const char *
-output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
+output_cbranch (rtx *operands, int negated, rtx insn)
 {
   static char buf[100];
   int useskip = 0;
-  rtx xoperands[5];
+  int nullify = INSN_ANNULLED_BRANCH_P (insn);
+  int length = get_attr_length (insn);
+  int xdelay;
 
   /* A conditional branch to the following instruction (e.g. the delay slot)
      is asking for a disaster.  This can happen when not optimizing and
@@ -5989,7 +6188,7 @@ output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
        with an unfilled delay slot.  */
       case 8:
        /* Handle weird backwards branch with a filled delay slot
-          with is nullified.  */
+          which is nullified.  */
        if (dbr_sequence_length () != 0
            && ! forward_branch_p (insn)
            && nullify)
@@ -6036,19 +6235,24 @@ output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
          }
        break;
 
-      case 20:
-      case 28:
-       xoperands[0] = operands[0];
-       xoperands[1] = operands[1];
-       xoperands[2] = operands[2];
-       xoperands[3] = operands[3];
-
+      default:
        /* The reversed conditional branch must branch over one additional
-          instruction if the delay slot is filled.  If the delay slot
-          is empty, the instruction after the reversed condition branch
-          must be nullified.  */
-       nullify = dbr_sequence_length () == 0;
-       xoperands[4] = nullify ? GEN_INT (length) : GEN_INT (length + 4);
+          instruction if the delay slot is filled and needs to be extracted
+          by output_lbranch.  If the delay slot is empty or this is a
+          nullified forward branch, the instruction after the reversed
+          condition branch must be nullified.  */
+       if (dbr_sequence_length () == 0
+           || (nullify && forward_branch_p (insn)))
+         {
+           nullify = 1;
+           xdelay = 0;
+           operands[4] = GEN_INT (length);
+         }
+       else
+         {
+           xdelay = 1;
+           operands[4] = GEN_INT (length + 4);
+         }
 
        /* Create a reversed conditional branch which branches around
           the following insns.  */
@@ -6095,27 +6299,38 @@ output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
              }
          }
 
-       output_asm_insn (buf, xoperands);
-       return output_lbranch (operands[0], insn);
-
-      default:
-       gcc_unreachable ();
+       output_asm_insn (buf, operands);
+       return output_lbranch (operands[0], insn, xdelay);
     }
   return buf;
 }
 
-/* This routine handles long unconditional branches that exceed the
-   maximum range of a simple branch instruction.  */
+/* This routine handles output of long unconditional branches that
+   exceed the maximum range of a simple branch instruction.  Since
+   we don't have a register available for the branch, we save register
+   %r1 in the frame marker, load the branch destination DEST into %r1,
+   execute the branch, and restore %r1 in the delay slot of the branch.
+
+   Since long branches may have an insn in the delay slot and the
+   delay slot is used to restore %r1, we in general need to extract
+   this insn and execute it before the branch.  However, to facilitate
+   use of this function by conditional branches, we also provide an
+   option to not extract the delay insn so that it will be emitted
+   after the long branch.  So, if there is an insn in the delay slot,
+   it is extracted if XDELAY is nonzero.
+
+   The lengths of the various long-branch sequences are 20, 16 and 24
+   bytes for the portable runtime, non-PIC and PIC cases, respectively.  */
 
 const char *
-output_lbranch (rtx dest, rtx insn)
+output_lbranch (rtx dest, rtx insn, int xdelay)
 {
   rtx xoperands[2];
  
   xoperands[0] = dest;
 
   /* First, free up the delay slot.  */
-  if (dbr_sequence_length () != 0)
+  if (xdelay && dbr_sequence_length () != 0)
     {
       /* We can't handle a jump in the delay slot.  */
       gcc_assert (GET_CODE (NEXT_INSN (insn)) != JUMP_INSN);
@@ -6124,9 +6339,7 @@ output_lbranch (rtx dest, rtx insn)
                       optimize, 0, NULL);
 
       /* Now delete the delay insn.  */
-      PUT_CODE (NEXT_INSN (insn), NOTE);
-      NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
-      NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+      SET_INSN_DELETED (NEXT_INSN (insn));
     }
 
   /* Output an insn to save %r1.  The runtime documentation doesn't
@@ -6151,7 +6364,7 @@ output_lbranch (rtx dest, rtx insn)
      for other purposes.  */
   if (TARGET_64BIT)
     {
-      if (actual_fsize == 0 && !regs_ever_live[2])
+      if (actual_fsize == 0 && !df_regs_ever_live_p (2))
        /* Use the return pointer slot in the frame marker.  */
        output_asm_insn ("std %%r1,-16(%%r30)", xoperands);
       else
@@ -6161,7 +6374,7 @@ output_lbranch (rtx dest, rtx insn)
     }
   else
     {
-      if (actual_fsize == 0 && !regs_ever_live[2])
+      if (actual_fsize == 0 && !df_regs_ever_live_p (2))
        /* Use the return pointer slot in the frame marker.  */
        output_asm_insn ("stw %%r1,-20(%%r30)", xoperands);
       else
@@ -6187,8 +6400,8 @@ output_lbranch (rtx dest, rtx insn)
        {
          xoperands[1] = gen_label_rtx ();
          output_asm_insn ("addil L'%l0-%l1,%%r1", xoperands);
-         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                            CODE_LABEL_NUMBER (xoperands[1]));
+         targetm.asm_out.internal_label (asm_out_file, "L",
+                                         CODE_LABEL_NUMBER (xoperands[1]));
          output_asm_insn ("ldo R'%l0-%l1(%%r1),%%r1", xoperands);
        }
       else
@@ -6205,14 +6418,14 @@ output_lbranch (rtx dest, rtx insn)
   /* Now restore the value of %r1 in the delay slot.  */
   if (TARGET_64BIT)
     {
-      if (actual_fsize == 0 && !regs_ever_live[2])
+      if (actual_fsize == 0 && !df_regs_ever_live_p (2))
        return "ldd -16(%%r30),%%r1";
       else
        return "ldd -40(%%r30),%%r1";
     }
   else
     {
-      if (actual_fsize == 0 && !regs_ever_live[2])
+      if (actual_fsize == 0 && !df_regs_ever_live_p (2))
        return "ldw -20(%%r30),%%r1";
       else
        return "ldw -12(%%r30),%%r1";
@@ -6225,11 +6438,13 @@ output_lbranch (rtx dest, rtx insn)
    above.  it returns the appropriate output template to emit the branch.  */
 
 const char *
-output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
-          int negated, rtx insn, int which)
+output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
 {
   static char buf[100];
   int useskip = 0;
+  int nullify = INSN_ANNULLED_BRANCH_P (insn);
+  int length = get_attr_length (insn);
+  int xdelay;
 
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  I do not think this can happen as this pattern
@@ -6296,7 +6511,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
        with an unfilled delay slot.  */
       case 8:
        /* Handle weird backwards branch with a filled delay slot
-          with is nullified.  */
+          which is nullified.  */
        if (dbr_sequence_length () != 0
            && ! forward_branch_p (insn)
            && nullify)
@@ -6338,9 +6553,10 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
          }
        else
          {
-           strcpy (buf, "{extrs,|extrw,s,}");
            if (GET_MODE (operands[0]) == DImode)
              strcpy (buf, "extrd,s,*");
+           else
+             strcpy (buf, "{extrs,|extrw,s,}");
            if ((which == 0 && negated)
                || (which == 1 && ! negated))
              strcat (buf, "<");
@@ -6358,7 +6574,40 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
        break;
 
       default:
-       gcc_unreachable ();
+       /* The reversed conditional branch must branch over one additional
+          instruction if the delay slot is filled and needs to be extracted
+          by output_lbranch.  If the delay slot is empty or this is a
+          nullified forward branch, the instruction after the reversed
+          condition branch must be nullified.  */
+       if (dbr_sequence_length () == 0
+           || (nullify && forward_branch_p (insn)))
+         {
+           nullify = 1;
+           xdelay = 0;
+           operands[4] = GEN_INT (length);
+         }
+       else
+         {
+           xdelay = 1;
+           operands[4] = GEN_INT (length + 4);
+         }
+
+       if (GET_MODE (operands[0]) == DImode)
+         strcpy (buf, "bb,*");
+       else
+         strcpy (buf, "bb,");
+       if ((which == 0 && negated)
+           || (which == 1 && !negated))
+         strcat (buf, "<");
+       else
+         strcat (buf, ">=");
+       if (nullify)
+         strcat (buf, ",n %0,%1,.+%4");
+       else
+         strcat (buf, " %0,%1,.+%4");
+       output_asm_insn (buf, operands);
+       return output_lbranch (negated ? operands[3] : operands[2],
+                              insn, xdelay);
     }
   return buf;
 }
@@ -6370,11 +6619,13 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
    branch.  */
 
 const char *
-output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
-           int negated, rtx insn, int which)
+output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
 {
   static char buf[100];
   int useskip = 0;
+  int nullify = INSN_ANNULLED_BRANCH_P (insn);
+  int length = get_attr_length (insn);
+  int xdelay;
 
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  I do not think this can happen as this pattern
@@ -6441,7 +6692,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
        with an unfilled delay slot.  */
       case 8:
        /* Handle weird backwards branch with a filled delay slot
-          with is nullified.  */
+          which is nullified.  */
        if (dbr_sequence_length () != 0
            && ! forward_branch_p (insn)
            && nullify)
@@ -6503,7 +6754,40 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
        break;
 
       default:
-       gcc_unreachable ();
+       /* The reversed conditional branch must branch over one additional
+          instruction if the delay slot is filled and needs to be extracted
+          by output_lbranch.  If the delay slot is empty or this is a
+          nullified forward branch, the instruction after the reversed
+          condition branch must be nullified.  */
+       if (dbr_sequence_length () == 0
+           || (nullify && forward_branch_p (insn)))
+         {
+           nullify = 1;
+           xdelay = 0;
+           operands[4] = GEN_INT (length);
+         }
+       else
+         {
+           xdelay = 1;
+           operands[4] = GEN_INT (length + 4);
+         }
+
+       if (GET_MODE (operands[0]) == DImode)
+         strcpy (buf, "bb,*");
+       else
+         strcpy (buf, "{bvb,|bb,}");
+       if ((which == 0 && negated)
+           || (which == 1 && !negated))
+         strcat (buf, "<");
+       else
+         strcat (buf, ">=");
+       if (nullify)
+         strcat (buf, ",n {%0,.+%4|%0,%%sar,.+%4}");
+       else
+         strcat (buf, " {%0,.+%4|%0,%%sar,.+%4}");
+       output_asm_insn (buf, operands);
+       return output_lbranch (negated ? operands[3] : operands[2],
+                              insn, xdelay);
     }
   return buf;
 }
@@ -6515,6 +6799,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
 const char *
 output_dbra (rtx *operands, rtx insn, int which_alternative)
 {
+  int length = get_attr_length (insn);
 
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  Be prepared!  */
@@ -6540,7 +6825,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
   if (which_alternative == 0)
     {
       int nullify = INSN_ANNULLED_BRANCH_P (insn);
-      int length = get_attr_length (insn);
+      int xdelay;
 
       /* If this is a long branch with its delay slot unfilled, set `nullify'
         as it can nullify the delay slot and save a nop.  */
@@ -6584,7 +6869,30 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
            return "addi,%N2 %1,%0,%0\n\tb %3";
 
        default:
-         gcc_unreachable ();
+         /* The reversed conditional branch must branch over one additional
+            instruction if the delay slot is filled and needs to be extracted
+            by output_lbranch.  If the delay slot is empty or this is a
+            nullified forward branch, the instruction after the reversed
+            condition branch must be nullified.  */
+         if (dbr_sequence_length () == 0
+             || (nullify && forward_branch_p (insn)))
+           {
+             nullify = 1;
+             xdelay = 0;
+             operands[4] = GEN_INT (length);
+           }
+         else
+           {
+             xdelay = 1;
+             operands[4] = GEN_INT (length + 4);
+           }
+
+         if (nullify)
+           output_asm_insn ("addib,%N2,n %1,%0,.+%4", operands);
+         else
+           output_asm_insn ("addib,%N2 %1,%0,.+%4", operands);
+
+         return output_lbranch (operands[3], insn, xdelay);
        }
       
     }
@@ -6597,10 +6905,17 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
       output_asm_insn ("{fstws|fstw} %0,-16(%%r30)\n\tldw -16(%%r30),%4",
                       operands);
       output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
-      if (get_attr_length (insn) == 24)
+      if (length == 24)
        return "{comb|cmpb},%S2 %%r0,%4,%3\n\t{fldws|fldw} -16(%%r30),%0";
-      else
+      else if (length == 28)
        return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
+      else
+       {
+         operands[5] = GEN_INT (length - 16);
+         output_asm_insn ("{comb|cmpb},%B2 %%r0,%4,.+%5", operands);
+         output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
+         return output_lbranch (operands[3], insn, 0);
+       }
     }
   /* Deal with gross reload from memory case.  */
   else
@@ -6608,14 +6923,20 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
       /* Reload loop counter from memory, the store back to memory
         happens in the branch's delay slot.  */
       output_asm_insn ("ldw %0,%4", operands);
-      if (get_attr_length (insn) == 12)
+      if (length == 12)
        return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
-      else
+      else if (length == 16)
        return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
+      else
+       {
+         operands[5] = GEN_INT (length - 4);
+         output_asm_insn ("addib,%N2 %1,%4,.+%5\n\tstw %4,%0", operands);
+         return output_lbranch (operands[3], insn, 0);
+       }
     }
 }
 
-/* Return the output template for emitting a dbra type insn.
+/* Return the output template for emitting a movb type insn.
 
    Note it may perform some output operations on its own before
    returning the final output string.  */
@@ -6623,6 +6944,7 @@ const char *
 output_movb (rtx *operands, rtx insn, int which_alternative,
             int reverse_comparison)
 {
+  int length = get_attr_length (insn);
 
   /* A conditional branch to the following instruction (e.g. the delay slot) is
      asking for a disaster.  Be prepared!  */
@@ -6649,7 +6971,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
   if (which_alternative == 0)
     {
       int nullify = INSN_ANNULLED_BRANCH_P (insn);
-      int length = get_attr_length (insn);
+      int xdelay;
 
       /* If this is a long branch with its delay slot unfilled, set `nullify'
         as it can nullify the delay slot and save a nop.  */
@@ -6693,38 +7015,82 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
            return "or,%N2 %1,%%r0,%0\n\tb %3";
 
        default:
-         gcc_unreachable ();
+         /* The reversed conditional branch must branch over one additional
+            instruction if the delay slot is filled and needs to be extracted
+            by output_lbranch.  If the delay slot is empty or this is a
+            nullified forward branch, the instruction after the reversed
+            condition branch must be nullified.  */
+         if (dbr_sequence_length () == 0
+             || (nullify && forward_branch_p (insn)))
+           {
+             nullify = 1;
+             xdelay = 0;
+             operands[4] = GEN_INT (length);
+           }
+         else
+           {
+             xdelay = 1;
+             operands[4] = GEN_INT (length + 4);
+           }
+
+         if (nullify)
+           output_asm_insn ("movb,%N2,n %1,%0,.+%4", operands);
+         else
+           output_asm_insn ("movb,%N2 %1,%0,.+%4", operands);
+
+         return output_lbranch (operands[3], insn, xdelay);
        }
     }
-  /* Deal with gross reload from FP register case.  */
+  /* Deal with gross reload for FP destination register case.  */
   else if (which_alternative == 1)
     {
-      /* Move loop counter from FP register to MEM then into a GR,
-        increment the GR, store the GR into MEM, and finally reload
-        the FP register from MEM from within the branch's delay slot.  */
+      /* Move source register to MEM, perform the branch test, then
+        finally load the FP register from MEM from within the branch's
+        delay slot.  */
       output_asm_insn ("stw %1,-16(%%r30)", operands);
-      if (get_attr_length (insn) == 12)
+      if (length == 12)
        return "{comb|cmpb},%S2 %%r0,%1,%3\n\t{fldws|fldw} -16(%%r30),%0";
-      else
+      else if (length == 16)
        return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
+      else
+       {
+         operands[4] = GEN_INT (length - 4);
+         output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4", operands);
+         output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
+         return output_lbranch (operands[3], insn, 0);
+       }
     }
   /* Deal with gross reload from memory case.  */
   else if (which_alternative == 2)
     {
       /* Reload loop counter from memory, the store back to memory
         happens in the branch's delay slot.  */
-      if (get_attr_length (insn) == 8)
+      if (length == 8)
        return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
-      else
+      else if (length == 12)
        return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
+      else
+       {
+         operands[4] = GEN_INT (length);
+         output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tstw %1,%0",
+                          operands);
+         return output_lbranch (operands[3], insn, 0);
+       }
     }
   /* Handle SAR as a destination.  */
   else
     {
-      if (get_attr_length (insn) == 8)
+      if (length == 8)
        return "{comb|cmpb},%S2 %%r0,%1,%3\n\tmtsar %r1";
-      else
+      else if (length == 12)
        return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tmtsar %r1";
+      else
+       {
+         operands[4] = GEN_INT (length);
+         output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tmtsar %r1",
+                          operands);
+         return output_lbranch (operands[3], insn, 0);
+       }
     }
 }
 
@@ -6894,7 +7260,7 @@ output_millicode_call (rtx insn, rtx call_dest)
            {
              xoperands[1] = gen_label_rtx ();
              output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
-             (*targetm.asm_out.internal_label) (asm_out_file, "L",
+             targetm.asm_out.internal_label (asm_out_file, "L",
                                         CODE_LABEL_NUMBER (xoperands[1]));
              output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
            }
@@ -6938,7 +7304,7 @@ output_millicode_call (rtx insn, rtx call_dest)
                 millicode symbol but not an arbitrary external
                 symbol when generating SOM output.  */
              xoperands[1] = gen_label_rtx ();
-             (*targetm.asm_out.internal_label) (asm_out_file, "L",
+             targetm.asm_out.internal_label (asm_out_file, "L",
                                         CODE_LABEL_NUMBER (xoperands[1]));
              output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
              output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
@@ -6977,8 +7343,8 @@ output_millicode_call (rtx insn, rtx call_dest)
        {
          xoperands[1] = gen_label_rtx ();
          output_asm_insn ("ldo %0-%1(%2),%2", xoperands);
-         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                            CODE_LABEL_NUMBER (xoperands[1]));
+         targetm.asm_out.internal_label (asm_out_file, "L",
+                                         CODE_LABEL_NUMBER (xoperands[1]));
        }
       else
        /* ??? This branch may not reach its target.  */
@@ -6989,9 +7355,7 @@ output_millicode_call (rtx insn, rtx call_dest)
     output_asm_insn ("nop\n\tb,n %0", xoperands);
 
   /* Delete the jump.  */
-  PUT_CODE (NEXT_INSN (insn), NOTE);
-  NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
-  NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+  SET_INSN_DELETED (NEXT_INSN (insn));
 
   return "";
 }
@@ -7036,7 +7400,7 @@ attr_length_call (rtx insn, int sibcall)
     call_dest = XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0);
 
   call_decl = SYMBOL_REF_DECL (call_dest);
-  local_call = call_decl && (*targetm.binds_local_p) (call_decl);
+  local_call = call_decl && targetm.binds_local_p (call_decl);
 
   /* pc-relative branch.  */
   if (!TARGET_LONG_CALLS
@@ -7053,13 +7417,13 @@ attr_length_call (rtx insn, int sibcall)
     length += 12;
 
   /* 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)))
+  else if (TARGET_LONG_PIC_SDIFF_CALL
+          || (TARGET_GAS && !TARGET_SOM
+              && (TARGET_LONG_PIC_PCREL_CALL || local_call)))
     {
       length += 20;
 
-      if (!TARGET_PA_20 && !TARGET_NO_SPACE_REGS)
+      if (!TARGET_PA_20 && !TARGET_NO_SPACE_REGS && flag_pic)
        length += 8;
     }
 
@@ -7079,7 +7443,7 @@ attr_length_call (rtx insn, int sibcall)
          if (!sibcall)
            length += 8;
 
-         if (!TARGET_NO_SPACE_REGS)
+         if (!TARGET_NO_SPACE_REGS && flag_pic)
            length += 8;
        }
     }
@@ -7099,7 +7463,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
   int delay_slot_filled = 0;
   int seq_length = dbr_sequence_length ();
   tree call_decl = SYMBOL_REF_DECL (call_dest);
-  int local_call = call_decl && (*targetm.binds_local_p) (call_decl);
+  int local_call = call_decl && targetm.binds_local_p (call_decl);
   rtx xoperands[2];
 
   xoperands[0] = call_dest;
@@ -7133,9 +7497,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
                               optimize, 0, NULL);
 
              /* Now delete the delay insn.  */
-             PUT_CODE (NEXT_INSN (insn), NOTE);
-             NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+             SET_INSN_DELETED (NEXT_INSN (insn));
              delay_insn_deleted = 1;
            }
 
@@ -7165,8 +7527,9 @@ output_call (rtx insn, rtx call_dest, int sibcall)
             of increasing length and complexity.  In most cases,
              they don't allow an instruction in the delay slot.  */
          if (!((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
-             && !(TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
-             && !(TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call))
+             && !TARGET_LONG_PIC_SDIFF_CALL
+             && !(TARGET_GAS && !TARGET_SOM
+                  && (TARGET_LONG_PIC_PCREL_CALL || local_call))
              && !TARGET_64BIT)
            indirect_call = 1;
 
@@ -7182,9 +7545,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
                               NULL);
 
              /* Now delete the delay insn.  */
-             PUT_CODE (NEXT_INSN (insn), NOTE);
-             NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+             SET_INSN_DELETED (NEXT_INSN (insn));
              delay_insn_deleted = 1;
            }
 
@@ -7212,21 +7573,21 @@ output_call (rtx insn, rtx call_dest, int sibcall)
            }
          else
            {
-             if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
-                 || (TARGET_64BIT && !TARGET_GAS))
+             if (TARGET_LONG_PIC_SDIFF_CALL)
                {
                  /* The HP assembler and linker can handle relocations
-                    for the difference of two symbols.  GAS and the HP
-                    linker can't do this when one of the symbols is
-                    external.  */
+                    for the difference of two symbols.  The HP assembler
+                    recognizes the sequence as a pc-relative call and
+                    the linker provides stubs when needed.  */
                  xoperands[1] = gen_label_rtx ();
                  output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
                  output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
-                 (*targetm.asm_out.internal_label) (asm_out_file, "L",
+                 targetm.asm_out.internal_label (asm_out_file, "L",
                                             CODE_LABEL_NUMBER (xoperands[1]));
                  output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
                }
-             else if (TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call))
+             else if (TARGET_GAS && !TARGET_SOM
+                      && (TARGET_LONG_PIC_PCREL_CALL || local_call))
                {
                  /*  GAS currently can't generate the relocations that
                      are needed for the SOM linker under HP-UX using this
@@ -7302,20 +7663,20 @@ output_call (rtx insn, rtx call_dest, int sibcall)
                }
              else
                {
-                 if (!TARGET_NO_SPACE_REGS)
+                 if (!TARGET_NO_SPACE_REGS && flag_pic)
                    output_asm_insn ("ldsid (%%r1),%%r31\n\tmtsp %%r31,%%sr0",
                                     xoperands);
 
                  if (sibcall)
                    {
-                     if (TARGET_NO_SPACE_REGS)
+                     if (TARGET_NO_SPACE_REGS || !flag_pic)
                        output_asm_insn ("be 0(%%sr4,%%r1)", xoperands);
                      else
                        output_asm_insn ("be 0(%%sr0,%%r1)", xoperands);
                    }
                  else
                    {
-                     if (TARGET_NO_SPACE_REGS)
+                     if (TARGET_NO_SPACE_REGS || !flag_pic)
                        output_asm_insn ("ble 0(%%sr4,%%r1)", xoperands);
                      else
                        output_asm_insn ("ble 0(%%sr0,%%r1)", xoperands);
@@ -7358,8 +7719,8 @@ output_call (rtx insn, rtx call_dest, int sibcall)
        {
          xoperands[1] = gen_label_rtx ();
          output_asm_insn ("ldo %0-%1(%%r2),%%r2", xoperands);
-         (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                            CODE_LABEL_NUMBER (xoperands[1]));
+         targetm.asm_out.internal_label (asm_out_file, "L",
+                                         CODE_LABEL_NUMBER (xoperands[1]));
        }
       else
        output_asm_insn ("nop\n\tb,n %0", xoperands);
@@ -7368,9 +7729,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
     output_asm_insn ("b,n %0", xoperands);
 
   /* Delete the jump.  */
-  PUT_CODE (NEXT_INSN (insn), NOTE);
-  NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
-  NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+  SET_INSN_DELETED (NEXT_INSN (insn));
 
   return "";
 }
@@ -7399,7 +7758,8 @@ attr_length_indirect_call (rtx insn)
 
   if (TARGET_FAST_INDIRECT_CALLS
       || (!TARGET_PORTABLE_RUNTIME
-         && ((TARGET_PA_20 && distance < 7600000) || distance < 240000)))
+         && ((TARGET_PA_20 && !TARGET_SOM && distance < 7600000)
+             || distance < 240000)))
     return 8;
 
   if (flag_pic)
@@ -7436,10 +7796,10 @@ output_indirect_call (rtx insn, rtx call_dest)
      the remaining cases.  */
   if (attr_length_indirect_call (insn) == 8)
     {
-      /* 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)
+      /* The HP linker sometimes substitutes a BLE for BL/B,L calls to
+        $$dyncall.  Since BLE uses %r31 as the link register, the 22-bit
+        variant of the B,L instruction can't be used on the SOM target.  */
+      if (TARGET_PA_20 && !TARGET_SOM)
        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";
@@ -7461,8 +7821,8 @@ output_indirect_call (rtx insn, rtx call_dest)
     {
       xoperands[0] = gen_label_rtx ();
       output_asm_insn ("addil L'$$dyncall-%0,%%r1", xoperands);
-      (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                        CODE_LABEL_NUMBER (xoperands[0]));
+      targetm.asm_out.internal_label (asm_out_file, "L",
+                                     CODE_LABEL_NUMBER (xoperands[0]));
       output_asm_insn ("ldo R'$$dyncall-%0(%%r1),%%r1", xoperands);
     }
   else
@@ -7513,6 +7873,12 @@ hppa_encode_label (rtx sym)
 static void
 pa_encode_section_info (tree decl, rtx rtl, int first)
 {
+  int old_referenced = 0;
+
+  if (!first && MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF)
+    old_referenced
+      = SYMBOL_REF_FLAGS (XEXP (rtl, 0)) & SYMBOL_FLAG_REFERENCED;
+
   default_encode_section_info (decl, rtl, first);
 
   if (first && TEXT_SPACE_P (decl))
@@ -7521,6 +7887,8 @@ pa_encode_section_info (tree decl, rtx rtl, int first)
       if (TREE_CODE (decl) == FUNCTION_DECL)
        hppa_encode_label (XEXP (rtl, 0));
     }
+  else if (old_referenced)
+    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= old_referenced;
 }
 
 /* This is sort of inverse to pa_encode_section_info.  */
@@ -7775,15 +8143,22 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
 
   fprintf (file, "\t.EXIT\n\t.PROCEND\n");
 
+  if (TARGET_SOM && TARGET_GAS)
+    {
+      /* We done with this subspace except possibly for some additional
+        debug information.  Forget that we are in this subspace to ensure
+        that the next function is output in its own subspace.  */
+      in_section = NULL;
+      cfun->machine->in_nsubspa = 2;
+    }
+
   if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
     {
-      data_section ();
+      switch_to_section (data_section);
       output_asm_insn (".align 4", xoperands);
       ASM_OUTPUT_LABEL (file, label);
       output_asm_insn (".word P'%0", xoperands);
     }
-  else if (TARGET_SOM && TARGET_GAS)
-    forget_section ();
 
   current_thunk_number++;
   nbytes = ((nbytes + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)
@@ -7846,7 +8221,7 @@ pa_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
    space register selection rules for memory addresses.  Therefore, we
    don't consider a + b == b + a, as this might be inside a MEM.  */
 static bool
-pa_commutative_p (rtx x, int outer_code)
+pa_commutative_p (const_rtx x, int outer_code)
 {
   return (COMMUTATIVE_P (x)
          && (TARGET_NO_SPACE_REGS
@@ -7959,7 +8334,7 @@ pa_asm_output_aligned_bss (FILE *stream,
                           unsigned HOST_WIDE_INT size,
                           unsigned int align)
 {
-  bss_section ();
+  switch_to_section (bss_section);
   fprintf (stream, "\t.align %u\n", align / BITS_PER_UNIT);
 
 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
@@ -7999,7 +8374,7 @@ pa_asm_output_aligned_common (FILE *stream,
       align = max_common_align;
     }
 
-  bss_section ();
+  switch_to_section (bss_section);
 
   assemble_name (stream, name);
   fprintf (stream, "\t.comm "HOST_WIDE_INT_PRINT_UNSIGNED"\n",
@@ -8019,7 +8394,7 @@ pa_asm_output_aligned_local (FILE *stream,
                             unsigned HOST_WIDE_INT size,
                             unsigned int align)
 {
-  bss_section ();
+  switch_to_section (bss_section);
   fprintf (stream, "\t.align %u\n", align / BITS_PER_UNIT);
 
 #ifdef LOCAL_ASM_OP
@@ -8186,37 +8561,50 @@ jump_in_call_delay (rtx insn)
 /* Output an unconditional move and branch insn.  */
 
 const char *
-output_parallel_movb (rtx *operands, int length)
+output_parallel_movb (rtx *operands, rtx insn)
 {
+  int length = get_attr_length (insn);
+
   /* These are the cases in which we win.  */
   if (length == 4)
     return "mov%I1b,tr %1,%0,%2";
 
-  /* None of these cases wins, but they don't lose either.  */
-  if (dbr_sequence_length () == 0)
+  /* None of the following cases win, but they don't lose either.  */
+  if (length == 8)
     {
-      /* Nothing in the delay slot, fake it by putting the combined
-        insn (the copy or add) in the delay slot of a bl.  */
-      if (GET_CODE (operands[1]) == CONST_INT)
-       return "b %2\n\tldi %1,%0";
+      if (dbr_sequence_length () == 0)
+       {
+         /* Nothing in the delay slot, fake it by putting the combined
+            insn (the copy or add) in the delay slot of a bl.  */
+         if (GET_CODE (operands[1]) == CONST_INT)
+           return "b %2\n\tldi %1,%0";
+         else
+           return "b %2\n\tcopy %1,%0";
+       }
       else
-       return "b %2\n\tcopy %1,%0";
+       {
+         /* Something in the delay slot, but we've got a long branch.  */
+         if (GET_CODE (operands[1]) == CONST_INT)
+           return "ldi %1,%0\n\tb %2";
+         else
+           return "copy %1,%0\n\tb %2";
+       }
     }
+
+  if (GET_CODE (operands[1]) == CONST_INT)
+    output_asm_insn ("ldi %1,%0", operands);
   else
-    {
-      /* Something in the delay slot, but we've got a long branch.  */
-      if (GET_CODE (operands[1]) == CONST_INT)
-       return "ldi %1,%0\n\tb %2";
-      else
-       return "copy %1,%0\n\tb %2";
-    }
+    output_asm_insn ("copy %1,%0", operands);
+  return output_lbranch (operands[2], insn, 1);
 }
 
 /* Output an unconditional add and branch insn.  */
 
 const char *
-output_parallel_addb (rtx *operands, int length)
+output_parallel_addb (rtx *operands, rtx insn)
 {
+  int length = get_attr_length (insn);
+
   /* To make life easy we want operand0 to be the shared input/output
      operand and operand1 to be the readonly operand.  */
   if (operands[0] == operands[1])
@@ -8226,18 +8614,20 @@ output_parallel_addb (rtx *operands, int length)
   if (length == 4)
     return "add%I1b,tr %1,%0,%3";
 
-  /* None of these cases win, but they don't lose either.  */
-  if (dbr_sequence_length () == 0)
+  /* None of the following cases win, but they don't lose either.  */
+  if (length == 8)
     {
-      /* Nothing in the delay slot, fake it by putting the combined
-        insn (the copy or add) in the delay slot of a bl.  */
-      return "b %3\n\tadd%I1 %1,%0,%0";
-    }
-  else
-    {
-      /* Something in the delay slot, but we've got a long branch.  */
-      return "add%I1 %1,%0,%0\n\tb %3";
+      if (dbr_sequence_length () == 0)
+       /* Nothing in the delay slot, fake it by putting the combined
+          insn (the copy or add) in the delay slot of a bl.  */
+       return "b %3\n\tadd%I1 %1,%0,%0";
+      else
+       /* Something in the delay slot, but we've got a long branch.  */
+       return "add%I1 %1,%0,%0\n\tb %3";
     }
+
+  output_asm_insn ("add%I1 %1,%0,%0", operands);
+  return output_lbranch (operands[3], insn, 1);
 }
 
 /* Return nonzero if INSN (a jump insn) immediately follows a call
@@ -8598,9 +8988,7 @@ pa_combine_instructions (void)
                                            PATTERN (floater))),
                                anchor);
 
-             PUT_CODE (anchor, NOTE);
-             NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (anchor) = 0;
+             SET_INSN_DELETED (anchor);
 
              /* Emit a special USE insn for FLOATER, then delete
                 the floating insn.  */
@@ -8622,9 +9010,7 @@ pa_combine_instructions (void)
                                         anchor);
 
              JUMP_LABEL (temp) = JUMP_LABEL (anchor);
-             PUT_CODE (anchor, NOTE);
-             NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
-             NOTE_SOURCE_FILE (anchor) = 0;
+             SET_INSN_DELETED (anchor);
 
              /* Emit a special USE insn for FLOATER, then delete
                 the floating insn.  */
@@ -8732,11 +9118,13 @@ insn_refs_are_delayed (rtx insn)
    to match the HP Compiler ABI.  */
 
 rtx
-function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
+function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
 {
   enum machine_mode valmode;
 
-  if (AGGREGATE_TYPE_P (valtype))
+  if (AGGREGATE_TYPE_P (valtype)
+      || TREE_CODE (valtype) == COMPLEX_TYPE
+      || TREE_CODE (valtype) == VECTOR_TYPE)
     {
       if (TARGET_64BIT)
        {
@@ -8773,7 +9161,7 @@ function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
     }
 
   if ((INTEGRAL_TYPE_P (valtype)
-       && TYPE_PRECISION (valtype) < BITS_PER_WORD)
+       && GET_MODE_BITSIZE (TYPE_MODE (valtype)) < BITS_PER_WORD)
       || POINTER_TYPE_P (valtype))
     valmode = word_mode;
   else
@@ -8816,7 +9204,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
      this routine should return zero.  pa_arg_partial_bytes will
      handle arguments which are split between regs and stack slots if
      the ABI mandates split arguments.  */
-  if (! TARGET_64BIT)
+  if (!TARGET_64BIT)
     {
       /* The 32-bit ABI does not split arguments.  */
       if (cum->words + arg_size > max_arg_words)
@@ -8851,7 +9239,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
         treatment.  */
       if (arg_size > 1
          || mode == BLKmode
-         || (type && AGGREGATE_TYPE_P (type)))
+         || (type && (AGGREGATE_TYPE_P (type)
+                      || TREE_CODE (type) == COMPLEX_TYPE
+                      || TREE_CODE (type) == VECTOR_TYPE)))
        {
          /* Double-extended precision (80-bit), quad-precision (128-bit)
             and aggregates including complex numbers are aligned on
@@ -8905,8 +9295,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
             objects.  The data is right-justified and zero-extended
             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 || (type && AGGREGATE_TYPE_P (type)))
+            We now define BLOCK_REG_PADDING to pad these objects.
+            Aggregates, complex and vector types are passed in the same
+            manner as structures.  */
+         if (mode == BLKmode
+             || (type && (AGGREGATE_TYPE_P (type)
+                          || TREE_CODE (type) == COMPLEX_TYPE
+                          || TREE_CODE (type) == VECTOR_TYPE)))
            {
              rtx loc = gen_rtx_EXPR_LIST (VOIDmode,
                                           gen_rtx_REG (DImode, gpr_reg_base),
@@ -8929,9 +9324,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
        /* If we are doing soft-float with portable runtime, then there
          is no need to worry about FP regs.  */
        && !TARGET_SOFT_FLOAT
-       /* The parameter must be some kind of float, else we can just
+       /* The parameter must be some kind of scalar float, else we just
          pass it in integer registers.  */
-       && FLOAT_MODE_P (mode)
+       && GET_MODE_CLASS (mode) == MODE_FLOAT
        /* The target function must not have a prototype.  */
        && cum->nargs_prototype <= 0
        /* libcalls do not need to pass items in both FP and general
@@ -8947,7 +9342,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
          && !TARGET_GAS
          && !cum->incoming
          && cum->indirect
-         && FLOAT_MODE_P (mode)))
+         && GET_MODE_CLASS (mode) == MODE_FLOAT))
     {
       retval
        = gen_rtx_PARALLEL
@@ -8970,9 +9365,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
              && !TARGET_64BIT
              && !TARGET_ELF32
              && cum->indirect)
-         /* If the parameter is not a floating point parameter, then
-            it belongs in GPRs.  */
-         || !FLOAT_MODE_P (mode)
+         /* If the parameter is not a scalar floating-point parameter,
+            then it belongs in GPRs.  */
+         || GET_MODE_CLASS (mode) != MODE_FLOAT
          /* Structure with single SFmode field belongs in GPR.  */
          || (type && AGGREGATE_TYPE_P (type)))
        retval = gen_rtx_REG (mode, gpr_reg_base);
@@ -9011,20 +9406,19 @@ pa_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 }
 
 
-/* Return a string to output before text in the current function.
+/* A get_unnamed_section callback for switching to the text section.
 
    This function is only used with SOM.  Because we don't support
    named subspaces, we can only create a new subspace or switch back
    to the default text subspace.  */
-const char *
-som_text_section_asm_op (void)
-{
-  if (!TARGET_SOM)
-    return "";
 
+static void
+som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+{
+  gcc_assert (TARGET_SOM);
   if (TARGET_GAS)
     {
-      if (cfun && !cfun->machine->in_nsubspa)
+      if (cfun && cfun->machine && !cfun->machine->in_nsubspa)
        {
          /* We only want to emit a .nsubspa directive once at the
             start of the function.  */
@@ -9035,24 +9429,93 @@ som_text_section_asm_op (void)
          if (cfun->decl
              && DECL_ONE_ONLY (cfun->decl)
              && !DECL_WEAK (cfun->decl))
-           return
- "\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=24,COMDAT";
-
-         return "\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$";
+           {
+             output_section_asm_op ("\t.SPACE $TEXT$\n"
+                                    "\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,"
+                                    "ACCESS=44,SORT=24,COMDAT");
+             return;
+           }
        }
       else
        {
          /* There isn't a current function or the body of the current
             function has been completed.  So, we are changing to the
-            text section to output debugging information.  Do this in
-            the default text section.  We need to forget that we are
-            in the text section so that the function text_section in
-            varasm.c will call us the next time around.  */
-         forget_section ();
-       }
+            text section to output debugging information.  Thus, we
+            need to forget that we are in the text section so that
+            varasm.c will call us when text_section is selected again.  */
+         gcc_assert (!cfun || !cfun->machine
+                     || cfun->machine->in_nsubspa == 2);
+         in_section = NULL;
+       }
+      output_section_asm_op ("\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$");
+      return;
     }
+  output_section_asm_op ("\t.SPACE $TEXT$\n\t.SUBSPA $CODE$");
+}
+
+/* A get_unnamed_section callback for switching to comdat data
+   sections.  This function is only used with SOM.  */
 
-  return "\t.SPACE $TEXT$\n\t.SUBSPA $CODE$";
+static void
+som_output_comdat_data_section_asm_op (const void *data)
+{
+  in_section = NULL;
+  output_section_asm_op (data);
+}
+
+/* Implement TARGET_ASM_INITIALIZE_SECTIONS  */
+
+static void
+pa_som_asm_init_sections (void)
+{
+  text_section
+    = get_unnamed_section (0, som_output_text_section_asm_op, NULL);
+
+  /* SOM puts readonly data in the default $LIT$ subspace when PIC code
+     is not being generated.  */
+  som_readonly_data_section
+    = get_unnamed_section (0, output_section_asm_op,
+                          "\t.SPACE $TEXT$\n\t.SUBSPA $LIT$");
+
+  /* When secondary definitions are not supported, SOM makes readonly
+     data one-only by creating a new $LIT$ subspace in $TEXT$ with
+     the comdat flag.  */
+  som_one_only_readonly_data_section
+    = get_unnamed_section (0, som_output_comdat_data_section_asm_op,
+                          "\t.SPACE $TEXT$\n"
+                          "\t.NSUBSPA $LIT$,QUAD=0,ALIGN=8,"
+                          "ACCESS=0x2c,SORT=16,COMDAT");
+
+
+  /* When secondary definitions are not supported, SOM makes data one-only
+     by creating a new $DATA$ subspace in $PRIVATE$ with the comdat flag.  */
+  som_one_only_data_section
+    = get_unnamed_section (SECTION_WRITE,
+                          som_output_comdat_data_section_asm_op,
+                          "\t.SPACE $PRIVATE$\n"
+                          "\t.NSUBSPA $DATA$,QUAD=1,ALIGN=8,"
+                          "ACCESS=31,SORT=24,COMDAT");
+
+  /* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
+     which reference data within the $TEXT$ space (for example constant
+     strings in the $LIT$ subspace).
+
+     The assemblers (GAS and HP as) both have problems with handling
+     the difference of two symbols which is the other correct way to
+     reference constant data during PIC code generation.
+
+     So, there's no way to reference constant data which is in the
+     $TEXT$ space during PIC generation.  Instead place all constant
+     data into the $PRIVATE$ subspace (this reduces sharing, but it
+     works correctly).  */
+  readonly_data_section = flag_pic ? data_section : som_readonly_data_section;
+
+  /* We must not have a reference to an external symbol defined in a
+     shared library in a readonly section, else the SOM linker will
+     complain.
+
+     So, we force exception information into the data section.  */
+  exception_section = data_section;
 }
 
 /* On hpux10, the linker will give an error if we have a reference
@@ -9060,7 +9523,7 @@ som_text_section_asm_op (void)
    library.  Therefore, expressions that might require a reloc can
    not be placed in the read-only data section.  */
 
-static void
+static section *
 pa_select_section (tree exp, int reloc,
                   unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
 {
@@ -9075,19 +9538,19 @@ pa_select_section (tree exp, int reloc,
       if (TARGET_SOM
          && DECL_ONE_ONLY (exp)
          && !DECL_WEAK (exp))
-       som_one_only_readonly_data_section ();
+       return som_one_only_readonly_data_section;
       else
-       readonly_data_section ();
+       return readonly_data_section;
     }
   else if (CONSTANT_CLASS_P (exp) && !reloc)
-    readonly_data_section ();
+    return readonly_data_section;
   else if (TARGET_SOM
           && TREE_CODE (exp) == VAR_DECL
           && DECL_ONE_ONLY (exp)
           && !DECL_WEAK (exp))
-    som_one_only_data_section ();
+    return som_one_only_data_section;
   else
-    data_section ();
+    return data_section;
 }
 
 static void
@@ -9115,7 +9578,7 @@ pa_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
 
 bool
-pa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+pa_return_in_memory (const_tree type, const_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.
@@ -9190,4 +9653,62 @@ pa_hpux_file_end (void)
 }
 #endif
 
+/* Return true if a change from mode FROM to mode TO for a register
+   in register class CLASS is invalid.  */
+
+bool
+pa_cannot_change_mode_class (enum machine_mode from, enum machine_mode to,
+                            enum reg_class class)
+{
+  if (from == to)
+    return false;
+
+  /* Reject changes to/from complex and vector modes.  */
+  if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from)
+      || COMPLEX_MODE_P (to) || VECTOR_MODE_P (to))
+    return true;
+      
+  if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to))
+    return false;
+
+  /* There is no way to load QImode or HImode values directly from
+     memory.  SImode loads to the FP registers are not zero extended.
+     On the 64-bit target, this conflicts with the definition of
+     LOAD_EXTEND_OP.  Thus, we can't allow changing between modes
+     with different sizes in the floating-point registers.  */
+  if (MAYBE_FP_REG_CLASS_P (class))
+    return true;
+
+  /* HARD_REGNO_MODE_OK places modes with sizes larger than a word
+     in specific sets of registers.  Thus, we cannot allow changing
+     to a larger mode when it's larger than a word.  */
+  if (GET_MODE_SIZE (to) > UNITS_PER_WORD
+      && GET_MODE_SIZE (to) > GET_MODE_SIZE (from))
+    return true;
+
+  return false;
+}
+
+/* Returns TRUE if it is a good idea to tie two pseudo registers
+   when one has mode MODE1 and one has mode MODE2.
+   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+   for any hard reg, then this must be FALSE for correct output.
+   
+   We should return FALSE for QImode and HImode because these modes
+   are not ok in the floating-point registers.  However, this prevents
+   tieing these modes to SImode and DImode in the general registers.
+   So, this isn't a good idea.  We rely on HARD_REGNO_MODE_OK and
+   CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used
+   in the floating-point registers.  */
+
+bool
+pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+  /* Don't tie modes in different classes.  */
+  if (GET_MODE_CLASS (mode1) != GET_MODE_CLASS (mode2))
+    return false;
+
+  return true;
+}
+
 #include "gt-pa.h"