OSDN Git Service

Add setjmp/longjmp exception handling.
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / pa.h
index 5fe9319..30a070b 100644 (file)
@@ -1,6 +1,6 @@
 /* Definitions of target machine for GNU compiler, for the HP Spectrum.
 /* Definitions of target machine for GNU compiler, for the HP Spectrum.
-   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-   Contributed by Michael Tiemann (tiemann@mcc.com)
+   Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Contributed by Michael Tiemann (tiemann@cygnus.com) of Cygnus Support
    and Tim Moore (moore@defmacro.cs.utah.edu) of the Center for
    Software Science at the University of Utah.
 
    and Tim Moore (moore@defmacro.cs.utah.edu) of the Center for
    Software Science at the University of Utah.
 
@@ -18,7 +18,8 @@ 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
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 enum cmp_type                          /* comparison type */
 {
 
 enum cmp_type                          /* comparison type */
 {
@@ -48,7 +49,7 @@ extern enum processor_type pa_cpu;
 
 /* Print subsidiary information on the compiler version in use.  */
 
 
 /* Print subsidiary information on the compiler version in use.  */
 
-#define TARGET_VERSION fprintf (stderr, " (hppa)");
+#define TARGET_VERSION fputs (" (hppa)", stderr);
 
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
 
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
@@ -69,24 +70,17 @@ extern int target_flags;
    never cross a space boundary.  Such assumptions are generally safe for
    building kernels and statically linked executables.  Code compiled with
    this option will fail miserably if the executable is dynamically linked
    never cross a space boundary.  Such assumptions are generally safe for
    building kernels and statically linked executables.  Code compiled with
    this option will fail miserably if the executable is dynamically linked
-   or uses nested functions!  */
-#define TARGET_FAST_INDIRECT_CALLS (target_flags & 4)
+   or uses nested functions!
+
+   This is also used to trigger agressive unscaled index addressing.  */
+#define TARGET_NO_SPACE_REGS (target_flags & 4)
 
 /* Allow unconditional jumps in the delay slots of call instructions.  */
 #define TARGET_JUMP_IN_DELAY (target_flags & 8)
 
 
 /* Allow unconditional jumps in the delay slots of call instructions.  */
 #define TARGET_JUMP_IN_DELAY (target_flags & 8)
 
-/* In rare cases, a millicode call via "bl" can not be turned into
-   a millicode call using "ble" (when SHLIB_INFO subspace is very large).
-
-   This option forces just millicode calls to use inline long-calls
-   This is far more efficient than the old long-call option which forced
-   every function to be called indirectly (as is still the case for
-   TARGET_PORTABLE_RUNTIME).
-
-   ??? What about simple jumps, they can suffer from the same problem.
-   Would require significant surgery in pa.md.  */
-
-#define TARGET_MILLICODE_LONG_CALLS (target_flags & 16)
+/* Optimize for space.  Currently this only turns on out of line
+   prologues and epilogues.  */
+#define TARGET_SPACE (target_flags & 16)
 
 /* Disable indexed addressing modes.  */
 
 
 /* Disable indexed addressing modes.  */
 
@@ -111,6 +105,13 @@ extern int target_flags;
 
 #define TARGET_SOFT_FLOAT (target_flags & 256)
 
 
 #define TARGET_SOFT_FLOAT (target_flags & 256)
 
+/* Use 3-insn load/store sequences for access to large data segments
+   in shared libraries on hpux10.  */
+#define TARGET_LONG_LOAD_STORE (target_flags & 512)
+
+/* Use a faster sequence for indirect calls.  */
+#define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -123,27 +124,36 @@ extern int target_flags;
    {"pa-risc-1-0", -1},                \
    {"pa-risc-1-1", 1},         \
    {"disable-fpregs", 2},      \
    {"pa-risc-1-0", -1},                \
    {"pa-risc-1-1", 1},         \
    {"disable-fpregs", 2},      \
-   {"no-disable-fpregs", 2},   \
-   {"fast-indirect-calls", 4}, \
-   {"no-fast-indirect-calls", -4},\
+   {"no-disable-fpregs", -2},  \
+   {"no-space-regs", 4},       \
+   {"space-regs", -4},         \
    {"jump-in-delay", 8},       \
    {"no-jump-in-delay", -8},   \
    {"jump-in-delay", 8},       \
    {"no-jump-in-delay", -8},   \
-   {"millicode-long-calls", 16},\
-   {"no-millicode-long-calls", -16},\
+   {"space", 16},              \
+   {"no-space", -16},          \
    {"disable-indexing", 32},   \
    {"no-disable-indexing", -32},\
    {"disable-indexing", 32},   \
    {"no-disable-indexing", -32},\
-   {"portable-runtime", 64+16},\
-   {"no-portable-runtime", -(64+16)},\
+   {"portable-runtime", 64},   \
+   {"no-portable-runtime", -64},\
    {"gas", 128},               \
    {"no-gas", -128},           \
    {"soft-float", 256},                \
    {"no-soft-float", -256},    \
    {"gas", 128},               \
    {"no-gas", -128},           \
    {"soft-float", 256},                \
    {"no-soft-float", -256},    \
-   { "", TARGET_DEFAULT}}
+   {"long-load-store", 512},   \
+   {"no-long-load-store", -512},\
+   {"fast-indirect-calls", 1024},\
+   {"no-fast-indirect-calls", -1024},\
+   {"linker-opt", 0},          \
+   { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
 
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT 0x88            /* TARGET_GAS + TARGET_JUMP_IN_DELAY */
 #endif
 
 
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT 0x88            /* TARGET_GAS + TARGET_JUMP_IN_DELAY */
 #endif
 
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT 0
+#endif
+
 #define TARGET_OPTIONS                 \
 {                                      \
   { "schedule=",       &pa_cpu_string }\
 #define TARGET_OPTIONS                 \
 {                                      \
   { "schedule=",       &pa_cpu_string }\
@@ -155,7 +165,7 @@ extern int target_flags;
 #define DEFAULT_GDB_EXTENSIONS 1
 
 /* This is the way other stabs-in-XXX tools do things.  We will be
 #define DEFAULT_GDB_EXTENSIONS 1
 
 /* This is the way other stabs-in-XXX tools do things.  We will be
-   compatable.  */
+   compatible.  */
 #define DBX_BLOCKS_FUNCTION_RELATIVE 1
 
 /* Likewise for linenos.
 #define DBX_BLOCKS_FUNCTION_RELATIVE 1
 
 /* Likewise for linenos.
@@ -180,7 +190,7 @@ extern int target_flags;
    name *first*...  */
 #define DBX_FUNCTION_FIRST
 
    name *first*...  */
 #define DBX_FUNCTION_FIRST
 
-/* Only lables should ever begin in colunm zero.  */
+/* Only labels should ever begin in column zero.  */
 #define ASM_STABS_OP "\t.stabs"
 #define ASM_STABN_OP "\t.stabn"
 
 #define ASM_STABS_OP "\t.stabs"
 #define ASM_STABN_OP "\t.stabn"
 
@@ -208,26 +218,33 @@ extern int target_flags;
 /* gdb needs a null N_SO at the end of each file for scattered loading. */
 
 #undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
 /* gdb needs a null N_SO at the end of each file for scattered loading. */
 
 #undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME)                        \
+#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
+  text_section (); \
+  if (!TARGET_PORTABLE_RUNTIME) \
+    fputs ("\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \
+  else \
+    fprintf (FILE, "%s\n", TEXT_SECTION_ASM_OP); \
   fprintf (FILE,                                                       \
   fprintf (FILE,                                                       \
-          "%s\n\t.stabs \"%s\",%d,0,0,L$text_end\nL$text_end:\n",\
-          TEXT_SECTION_ASM_OP, "" , N_SO)
+          "\t.stabs \"\",%d,0,0,L$text_end0000\nL$text_end0000:\n", N_SO)
 
 
-#if (TARGET_DEFAULT & 1) == 0
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0
 #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
 #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
- %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}"
+ %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
+ %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
 #else
 #else
-#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}}"
+#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
 #endif
 
 /* Defines for a K&R CC */
 
 #define CC1_SPEC "%{pg:} %{p:}"
 
 #endif
 
 /* Defines for a K&R CC */
 
 #define CC1_SPEC "%{pg:} %{p:}"
 
-#define LINK_SPEC "%{!shared:-u main} %{shared:-b}"
+#define LINK_SPEC "%{mlinker-opt:-O} %{!shared:-u main} %{shared:-b}"
 
 
-/* Allow $ in identifiers.  */
-#define DOLLARS_IN_IDENTIFIERS 2
+/* We don't want -lg.  */
+#ifndef LIB_SPEC
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+#endif
 
 /* Make gcc agree with <machine/ansi.h> */
 
 
 /* Make gcc agree with <machine/ansi.h> */
 
@@ -239,34 +256,79 @@ extern int target_flags;
 /* Show we can debug even without a frame pointer.  */
 #define CAN_DEBUG_WITHOUT_FP
 
 /* Show we can debug even without a frame pointer.  */
 #define CAN_DEBUG_WITHOUT_FP
 
+/* Machine dependent reorg pass.  */
+#define MACHINE_DEPENDENT_REORG(X) pa_reorg(X)
+
 /* Names to predefine in the preprocessor for this target machine.  */
 
 /* Names to predefine in the preprocessor for this target machine.  */
 
-#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -D_HPUX_SOURCE -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
+#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
 
 /* HPUX has a program 'chatr' to list the dependencies of dynamically
    linked executables and shared libraries.  */
 #define LDD_SUFFIX "chatr"
 
 /* HPUX has a program 'chatr' to list the dependencies of dynamically
    linked executables and shared libraries.  */
 #define LDD_SUFFIX "chatr"
-/* look for lines like "dynamic   /usr/lib/X11R5/libX11.sl".  */
+/* Look for lines like "dynamic   /usr/lib/X11R5/libX11.sl"
+   or "static    /usr/lib/X11R5/libX11.sl". 
+
+   HPUX 10.20 also has lines like "static branch prediction ..."
+   so we filter that out explcitly.
+
+   We also try to bound our search for libraries with marker
+   lines.  What a pain.  */
 #define PARSE_LDD_OUTPUT(PTR)                                  \
 do {                                                           \
 #define PARSE_LDD_OUTPUT(PTR)                                  \
 do {                                                           \
+  static int in_shlib_list = 0;                                        \
   while (*PTR == ' ') PTR++;                                   \
   while (*PTR == ' ') PTR++;                                   \
-  if (strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0)   \
+  if (strncmp (PTR, "shared library list:",                    \
+              sizeof ("shared library list:") - 1) == 0)       \
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 1;                                       \
+    }                                                          \
+  else if (strncmp (PTR, "shared library binding:",            \
+                   sizeof ("shared library binding:") - 1) == 0)\
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 0;                                       \
+    }                                                          \
+  else if (strncmp (PTR, "static branch prediction disabled",  \
+                   sizeof ("static branch prediction disabled") - 1) == 0)\
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 0;                                       \
+    }                                                          \
+  else if (in_shlib_list                                       \
+          &&  strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0) \
     {                                                          \
       PTR += sizeof ("dynamic") - 1;                           \
       while (*p == ' ') PTR++;                                 \
     }                                                          \
     {                                                          \
       PTR += sizeof ("dynamic") - 1;                           \
       while (*p == ' ') PTR++;                                 \
     }                                                          \
+  else if (in_shlib_list                                       \
+          && strncmp (PTR, "static", sizeof ("static") - 1) == 0) \
+    {                                                          \
+      PTR += sizeof ("static") - 1;                            \
+      while (*p == ' ') PTR++;                                 \
+    }                                                          \
   else                                                         \
     PTR = 0;                                                   \
 } while (0)
   else                                                         \
     PTR = 0;                                                   \
 } while (0)
-
-#define LD_INIT_SWITCH "+I"
 \f
 /* target machine storage layout */
 
 /* Define for cross-compilation from a host with a different float format
 \f
 /* target machine storage layout */
 
 /* Define for cross-compilation from a host with a different float format
-   or endianess (e.g. VAX, x86).  */
+   or endianness (e.g. VAX, x86).  */
 #define REAL_ARITHMETIC
 
 #define REAL_ARITHMETIC
 
+/* Define this macro if it is advisable to hold scalars in registers
+   in a wider mode than that declared by the program.  In such cases, 
+   the value is constrained to be within the bounds of the declared
+   type, but kept valid in the wider mode.  The signedness of the
+   extension may differ from that of the type.  */
+
+#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE)  \
+  if (GET_MODE_CLASS (MODE) == MODE_INT        \
+      && GET_MODE_SIZE (MODE) < 4)     \
+    (MODE) = SImode;
+
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
 #define BITS_BIG_ENDIAN 1
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
 #define BITS_BIG_ENDIAN 1
@@ -302,8 +364,12 @@ do {                                                               \
    Don't define this if it is equal to PARM_BOUNDARY */
 #define MAX_PARM_BOUNDARY 64
 
    Don't define this if it is equal to PARM_BOUNDARY */
 #define MAX_PARM_BOUNDARY 64
 
-/* Boundary (in *bits*) on which stack pointer should be aligned.  */
-#define STACK_BOUNDARY 512
+/* Boundary (in *bits*) on which stack pointer is always aligned;
+   certain optimizations in combine depend on this.
+
+   GCC for the PA always rounds its stacks to a 512bit boundary,
+   but that happens late in the compilation process.  */
+#define STACK_BOUNDARY 64
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY 32
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY 32
@@ -447,14 +513,16 @@ do {                                                              \
       for (i = 33; i < 88; i += 2)             \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
       for (i = 33; i < 88; i += 2)             \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
-  else if (TARGET_DISABLE_FPREGS               \
-          || TARGET_SOFT_FLOAT)                \
+  if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)\
     {                                          \
       for (i = 32; i < 88; i++)                \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
   if (flag_pic)                                        \
     {                                          \
       for (i = 32; i < 88; i++)                \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
   if (flag_pic)                                        \
-    fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;   \
+    {                                          \
+      fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+      fixed_regs[PIC_OFFSET_TABLE_REGNUM_SAVED] = 1;\
+    }                                          \
 }
 
 /* Allocate the call used registers first.  This should minimize
 }
 
 /* Allocate the call used registers first.  This should minimize
@@ -467,10 +535,10 @@ do {                                                              \
 #define REG_ALLOC_ORDER \
  {                                     \
   /* caller-saved fp regs.  */         \
 #define REG_ALLOC_ORDER \
  {                                     \
   /* caller-saved fp regs.  */         \
-  40, 41, 42, 43, 44, 45, 46, 47,      \
   68, 69, 70, 71, 72, 73, 74, 75,      \
   76, 77, 78, 79, 80, 81, 82, 83,      \
   84, 85, 86, 87,                      \
   68, 69, 70, 71, 72, 73, 74, 75,      \
   76, 77, 78, 79, 80, 81, 82, 83,      \
   84, 85, 86, 87,                      \
+  40, 41, 42, 43, 44, 45, 46, 47,      \
   32, 33, 34, 35, 36, 37, 38, 39,      \
   /* caller-saved general regs.  */    \
   19, 20, 21, 22, 23, 24, 25, 26,      \
   32, 33, 34, 35, 36, 37, 38, 39,      \
   /* caller-saved general regs.  */    \
   19, 20, 21, 22, 23, 24, 25, 26,      \
@@ -531,9 +599,9 @@ do {                                                                \
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM 3
 
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM 3
 
-/* Value should be nonzero if functions must have frame pointers. */
-#define FRAME_POINTER_REQUIRED (current_function_calls_alloca)
-
+/* Value should be nonzero if functions must have frame pointers.  */
+#define FRAME_POINTER_REQUIRED \
+  (current_function_calls_alloca)
 
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.
 
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.
@@ -557,15 +625,14 @@ do {                                                              \
 #define PIC_OFFSET_TABLE_REGNUM 19
 #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 1
 
 #define PIC_OFFSET_TABLE_REGNUM 19
 #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 1
 
-/* Initialize hppa_save_pic_table_rtx before RTL generation for
-   each function.  We used to do this in FINALIZE_PIC, but FINALIZE_PIC
-   isn't always called for static inline functions.  */
-#define INIT_EXPANDERS hppa_save_pic_table_rtx = 0;
+/* Register into which we save the PIC_OFFEST_TABLE_REGNUM so that it
+   can be restore across function calls.  */
+#define PIC_OFFSET_TABLE_REGNUM_SAVED 4
 
 /* SOM ABI says that objects larger than 64 bits are returned in memory.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 #define RETURN_IN_MEMORY(TYPE) \
 
 /* SOM ABI says that objects larger than 64 bits are returned in memory.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 #define RETURN_IN_MEMORY(TYPE) \
-  (int_size_in_bytes (TYPE) > 8 || TREE_ADDRESSABLE (TYPE))
+  (int_size_in_bytes (TYPE) > 8)
 
 /* Register in which address to store a structure value
    is passed to a function.  */
 
 /* Register in which address to store a structure value
    is passed to a function.  */
@@ -691,11 +758,15 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
 #define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
 
 /* Return the register class of a scratch register needed to copy IN into
 #define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
 
 /* Return the register class of a scratch register needed to copy IN into
-   or out of a register in CLASS in MODE.  If it can be done directly,
-   NO_REGS is returned.  */
+   or out of a register in CLASS in MODE.  If it can be done directly
+   NO_REGS is returned. 
+
+  Avoid doing any work for the common case calls.  */
 
 #define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
 
 #define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
-  secondary_reload_class (CLASS, MODE, IN)
+  ((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG            \
+    && REGNO (IN) < FIRST_PSEUDO_REGISTER)                     \
+   ? NO_REGS : secondary_reload_class (CLASS, MODE, IN))
 
 /* On the PA it is not possible to directly move data between
    GENERAL_REGS and FP_REGS.  */
 
 /* On the PA it is not possible to directly move data between
    GENERAL_REGS and FP_REGS.  */
@@ -780,10 +851,11 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
 
 /* Value is 1 if returning from a function call automatically
    pops the arguments described by the number-of-args field in the call.
 
 /* Value is 1 if returning from a function call automatically
    pops the arguments described by the number-of-args field in the call.
+   FUNDECL is the declaration node of the function (as a tree),
    FUNTYPE is the data type of the function (as a tree),
    or for a library call it is an identifier node for the subroutine name.  */
 
    FUNTYPE is the data type of the function (as a tree),
    or for a library call it is an identifier node for the subroutine name.  */
 
-#define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
 
 /* Define how to find the value returned by a function.
    VALTYPE is the data type of the value (as a tree).
 
 /* Define how to find the value returned by a function.
    VALTYPE is the data type of the value (as a tree).
@@ -830,7 +902,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
    if any, which holds the structure-value-address).
    Thus 4 or more means all following args should go on the stack.  */
 
    if any, which holds the structure-value-address).
    Thus 4 or more means all following args should go on the stack.  */
 
-struct hppa_args {int words, nargs_prototype; };
+struct hppa_args {int words, nargs_prototype, indirect; };
 
 #define CUMULATIVE_ARGS struct hppa_args
 
 
 #define CUMULATIVE_ARGS struct hppa_args
 
@@ -838,8 +910,9 @@ struct hppa_args {int words, nargs_prototype; };
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
 
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
 
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
   (CUM).words = 0,                                                     \
   (CUM).words = 0,                                                     \
+  (CUM).indirect = INDIRECT,                                           \
   (CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE)           \
                           ? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1 \
                              + (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \
   (CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE)           \
                           ? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1 \
                              + (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \
@@ -849,10 +922,11 @@ struct hppa_args {int words, nargs_prototype; };
 
 
 /* Similar, but when scanning the definition of a procedure.  We always
 
 
 /* Similar, but when scanning the definition of a procedure.  We always
-   set NARGS_PROTOTYPE large so we never return an EXPR_LIST.  */
+   set NARGS_PROTOTYPE large so we never return a PARALLEL.  */
 
 #define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
   (CUM).words = 0,                             \
 
 #define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
   (CUM).words = 0,                             \
+  (CUM).indirect = 0,                          \
   (CUM).nargs_prototype = 1000
 
 /* Figure out the size in words of the function argument. */
   (CUM).nargs_prototype = 1000
 
 /* Figure out the size in words of the function argument. */
@@ -930,13 +1004,13 @@ struct hppa_args {int words, nargs_prototype; };
       || (CUM).nargs_prototype > 0)                                    \
       ? gen_rtx (REG, (MODE),                                          \
                 (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1                \
       || (CUM).nargs_prototype > 0)                                    \
       ? gen_rtx (REG, (MODE),                                          \
                 (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1                \
-                 ? (((!current_call_is_indirect                        \
+                 ? (((!(CUM).indirect                                  \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == DFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
                     ? ((CUM).words ? 38 : 34)                          \
                     : ((CUM).words ? 23 : 25))                         \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == DFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
                     ? ((CUM).words ? 38 : 34)                          \
                     : ((CUM).words ? 23 : 25))                         \
-                 : (((!current_call_is_indirect                        \
+                 : (((!(CUM).indirect                                  \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == SFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == SFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
@@ -945,16 +1019,23 @@ struct hppa_args {int words, nargs_prototype; };
                                                              (TYPE))))))\
    /* We are calling a non-prototyped function with floating point     \
       arguments using the portable conventions.  */                    \
                                                              (TYPE))))))\
    /* We are calling a non-prototyped function with floating point     \
       arguments using the portable conventions.  */                    \
-   : gen_rtx (EXPR_LIST, VOIDmode,                                     \
-             gen_rtx (REG, (MODE),                                     \
-                      (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1          \
-                       ? ((CUM).words ? 38 : 34)                       \
-                       : (32 + 2 * (CUM).words))),                     \
-             gen_rtx (REG, (MODE),                                     \
-                      (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1          \
-                       ? ((CUM).words ? 23 : 25)                       \
-                       : (27 - (CUM).words - FUNCTION_ARG_SIZE ((MODE),\
-                                                                (TYPE)))))) \
+   : gen_rtx (PARALLEL, (MODE),                                                \
+             gen_rtvec                                                 \
+             (2,                                                       \
+              gen_rtx (EXPR_LIST, VOIDmode,                            \
+                       gen_rtx (REG, (MODE),                           \
+                                (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \
+                                 ? ((CUM).words ? 38 : 34)             \
+                                 : (32 + 2 * (CUM).words))),           \
+                       const0_rtx),                                    \
+              gen_rtx (EXPR_LIST, VOIDmode,                            \
+                       gen_rtx (REG, (MODE),                           \
+                                (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \
+                                 ? ((CUM).words ? 23 : 25)             \
+                                 : (27 - (CUM).words -                 \
+                                    FUNCTION_ARG_SIZE ((MODE),         \
+                                                       (TYPE))))),     \
+                       const0_rtx)))                                   \
   /* Pass this parameter in the stack.  */                             \
   : 0)
 
   /* Pass this parameter in the stack.  */                             \
   : 0)
 
@@ -979,6 +1060,10 @@ struct hppa_args {int words, nargs_prototype; };
 
 #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)         \
   ((TYPE) && int_size_in_bytes (TYPE) > 8)
 
 #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)         \
   ((TYPE) && int_size_in_bytes (TYPE) > 8)
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
+  ((TYPE) && int_size_in_bytes (TYPE) > 8)
+
 \f
 extern struct rtx_def *hppa_compare_op0, *hppa_compare_op1;
 extern enum cmp_type hppa_branch_type;
 \f
 extern struct rtx_def *hppa_compare_op0, *hppa_compare_op1;
 extern enum cmp_type hppa_branch_type;
@@ -994,6 +1079,29 @@ extern enum cmp_type hppa_branch_type;
        fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0)
 #endif
 
        fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0)
 #endif
 
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+{ char *my_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (THUNK_FNDECL)); \
+  char *target_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)); \
+  output_function_prologue (FILE, 0); \
+  if (VAL_14_BITS_P (DELTA)) \
+    fprintf (FILE, "\tb %s\n\tldo %d(%%r26),%%r26\n", target_name, DELTA); \
+  else \
+    fprintf (FILE, "\taddil L%%%d,%r26\n\tb %s\n\tldo R%%%d(%%r1),%%r26\n", \
+            DELTA, target_name, DELTA); \
+  fprintf (FILE, "\n\t.EXIT\n\t.PROCEND\n"); \
+}
+
+#define ASM_OUTPUT_FUNCTION_PREFIX(FILE, NAME) \
+  {                                                                    \
+    char *name;                                                                \
+    STRIP_NAME_ENCODING (name, NAME);                                  \
+    if (!TARGET_PORTABLE_RUNTIME && TARGET_GAS && in_section == in_text) \
+      fputs ("\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \
+    else if (! TARGET_PORTABLE_RUNTIME && TARGET_GAS)                  \
+      fprintf (FILE,                                                   \
+              "\t.SUBSPA %s\n", name);                         \
+  }
+    
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
     do { tree fntype = TREE_TYPE (TREE_TYPE (DECL));                   \
         tree tree_type = TREE_TYPE (DECL);                             \
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
     do { tree fntype = TREE_TYPE (TREE_TYPE (DECL));                   \
         tree tree_type = TREE_TYPE (DECL);                             \
@@ -1040,6 +1148,11 @@ extern enum cmp_type hppa_branch_type;
                     int arg_size =                                     \
                       FUNCTION_ARG_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)),\
                                          DECL_ARG_TYPE (parm));        \
                     int arg_size =                                     \
                       FUNCTION_ARG_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)),\
                                          DECL_ARG_TYPE (parm));        \
+                    /* Passing structs by invisible reference uses     \
+                       one general register.  */                       \
+                    if (arg_size > 2                                   \
+                        || TREE_ADDRESSABLE (DECL_ARG_TYPE (parm)))    \
+                      arg_size = 1;                                    \
                     if (arg_size == 2 && i <= 2)                       \
                       {                                                \
                         if (i == 1) i++;                               \
                     if (arg_size == 2 && i <= 2)                       \
                       {                                                \
                         if (i == 1) i++;                               \
@@ -1062,11 +1175,11 @@ extern enum cmp_type hppa_branch_type;
                   fprintf (FILE, ",ARGW%d=GR", i);                     \
               }                                                        \
             if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT)   \
                   fprintf (FILE, ",ARGW%d=GR", i);                     \
               }                                                        \
             if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT)   \
-              fprintf (FILE, ",RTNVAL=FR");                            \
+              fputs (",RTNVAL=FR", FILE);                              \
             else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \
             else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \
-              fprintf (FILE, ",RTNVAL=FU");                            \
+              fputs (",RTNVAL=FU", FILE);                              \
             else if (fntype != void_type_node)                         \
             else if (fntype != void_type_node)                         \
-              fprintf (FILE, ",RTNVAL=GR");                            \
+              fputs (",RTNVAL=GR", FILE);                              \
             fputs ("\n", FILE);                                        \
           }} while (0)
 
             fputs ("\n", FILE);                                        \
           }} while (0)
 
@@ -1146,17 +1259,17 @@ extern union tree_node *current_function_decl;
 
 #define TRAMPOLINE_TEMPLATE(FILE) \
   {                                                    \
 
 #define TRAMPOLINE_TEMPLATE(FILE) \
   {                                                    \
-    fprintf (FILE, "\tldw      36(0,%%r22),%%r21\n");  \
-    fprintf (FILE, "\tbb,>=,n  %%r21,30,.+16\n");      \
-    fprintf (FILE, "\tdepi     0,31,2,%%r21\n");       \
-    fprintf (FILE, "\tldw      4(0,%%r21),%%r19\n");   \
-    fprintf (FILE, "\tldw      0(0,%%r21),%%r21\n");   \
-    fprintf (FILE, "\tldsid    (0,%%r21),%%r1\n");     \
-    fprintf (FILE, "\tmtsp     %%r1,%%sr0\n");         \
-    fprintf (FILE, "\tbe       0(%%sr0,%%r21)\n");     \
-    fprintf (FILE, "\tldw      40(0,%%r22),%%r29\n");  \
-    fprintf (FILE, "\t.word    0\n");                  \
-    fprintf (FILE, "\t.word    0\n");                  \
+    fputs ("\tldw      36(0,%r22),%r21\n", FILE);      \
+    fputs ("\tbb,>=,n  %r21,30,.+16\n", FILE); \
+    fputs ("\tdepi     0,31,2,%r21\n", FILE);          \
+    fputs ("\tldw      4(0,%r21),%r19\n", FILE);       \
+    fputs ("\tldw      0(0,%r21),%r21\n", FILE);       \
+    fputs ("\tldsid    (0,%r21),%r1\n", FILE); \
+    fputs ("\tmtsp     %r1,%sr0\n", FILE);             \
+    fputs ("\tbe       0(%sr0,%r21)\n", FILE); \
+    fputs ("\tldw      40(0,%r22),%r29\n", FILE);      \
+    fputs ("\t.word    0\n", FILE);                    \
+    fputs ("\t.word    0\n", FILE);                    \
   }
 
 /* Length in units of the trampoline for entering a nested function.
   }
 
 /* Length in units of the trampoline for entering a nested function.
@@ -1200,7 +1313,8 @@ extern union tree_node *current_function_decl;
    Ordinarily they are not call used registers, but they are for
    _builtin_saveregs, so we must make this explicit.  */
 
    Ordinarily they are not call used registers, but they are for
    _builtin_saveregs, so we must make this explicit.  */
 
-#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) (rtx)hppa_builtin_saveregs (ARGLIST)
+extern struct rtx_def *hppa_builtin_saveregs ();
+#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) hppa_builtin_saveregs (ARGLIST)
 
 \f
 /* Addressing modes, and classification of registers for them.  */
 
 \f
 /* Addressing modes, and classification of registers for them.  */
@@ -1279,10 +1393,6 @@ extern union tree_node *current_function_decl;
    these things in insns and then not re-recognize the insns, causing
    constrain_operands to fail.
 
    these things in insns and then not re-recognize the insns, causing
    constrain_operands to fail.
 
-   Also note `Q' accepts any memory operand during the reload pass.
-   This includes out-of-range displacements in reg+d addressing.
-   This makes for better code.  (??? For 2.5 address this issue).
-
    `R' is unused.
 
    `S' is unused.
    `R' is unused.
 
    `S' is unused.
@@ -1291,16 +1401,29 @@ extern union tree_node *current_function_decl;
 #define EXTRA_CONSTRAINT(OP, C)                                \
   ((C) == 'Q' ?                                                \
    (IS_RELOADING_PSEUDO_P (OP)                         \
 #define EXTRA_CONSTRAINT(OP, C)                                \
   ((C) == 'Q' ?                                                \
    (IS_RELOADING_PSEUDO_P (OP)                         \
-    || (GET_CODE (OP) == MEM                           \
-       && reload_in_progress)                          \
     || (GET_CODE (OP) == MEM                           \
     || (GET_CODE (OP) == MEM                           \
-       && memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
-       && ! symbolic_memory_operand (OP, VOIDmode)))   \
+       && (memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+           || reload_in_progress)                      \
+       && ! symbolic_memory_operand (OP, VOIDmode)     \
+        && !(GET_CODE (XEXP (OP, 0)) == PLUS           \
+            && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
+                || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))))\
+   : ((C) == 'R' ?                                     \
+     (GET_CODE (OP) == MEM                             \
+      && GET_CODE (XEXP (OP, 0)) == PLUS               \
+      && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT    \
+         || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT) \
+      && (move_operand (OP, GET_MODE (OP))             \
+         || memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+         || reload_in_progress))                       \
    : ((C) == 'T' ?                                     \
       (GET_CODE (OP) == MEM                            \
        /* Using DFmode forces only short displacements \
          to be recognized as valid in reg+d addresses.  */\
    : ((C) == 'T' ?                                     \
       (GET_CODE (OP) == MEM                            \
        /* Using DFmode forces only short displacements \
          to be recognized as valid in reg+d addresses.  */\
-       && memory_address_p (DFmode, XEXP (OP, 0))) : 0))
+       && memory_address_p (DFmode, XEXP (OP, 0))      \
+       && !(GET_CODE (XEXP (OP, 0)) == PLUS            \
+           && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
+               || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))) : 0)))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1395,6 +1518,15 @@ extern union tree_node *current_function_decl;
                     || ((MODE) != SFmode && (MODE) != DFmode))) \
                || INT_5_BITS (index)))                 \
          goto ADDR;                                    \
                     || ((MODE) != SFmode && (MODE) != DFmode))) \
                || INT_5_BITS (index)))                 \
          goto ADDR;                                    \
+      if (! TARGET_SOFT_FLOAT                          \
+         && base                                       \
+         && (mode == SFmode || mode == DFmode)         \
+         && GET_CODE (index) == MULT                   \
+         && GET_CODE (XEXP (index, 0)) == REG          \
+         && REG_OK_FOR_BASE_P (XEXP (index, 0))        \
+         && GET_CODE (XEXP (index, 1)) == CONST_INT    \
+         && INTVAL (XEXP (index, 1)) == (mode == SFmode ? 4 : 8))\
+       goto ADDR;                                      \
     }                                                  \
   else if (GET_CODE (X) == LO_SUM                      \
           && GET_CODE (XEXP (X, 0)) == REG             \
     }                                                  \
   else if (GET_CODE (X) == LO_SUM                      \
           && GET_CODE (XEXP (X, 0)) == REG             \
@@ -1476,6 +1608,7 @@ extern struct rtx_def *hppa_legitimize_address ();
   (TREE_CODE (DECL) == FUNCTION_DECL                                   \
    || (TREE_CODE (DECL) == VAR_DECL                                    \
        && TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL)           \
   (TREE_CODE (DECL) == FUNCTION_DECL                                   \
    || (TREE_CODE (DECL) == VAR_DECL                                    \
        && TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL)           \
+       && (! DECL_INITIAL (DECL) || ! reloc_needed (DECL_INITIAL (DECL))) \
        && !flag_pic)                                                   \
    || (*tree_code_type[(int) TREE_CODE (DECL)] == 'c'                  \
        && !(TREE_CODE (DECL) == STRING_CST && flag_writable_strings)))
        && !flag_pic)                                                   \
    || (*tree_code_type[(int) TREE_CODE (DECL)] == 'c'                  \
        && !(TREE_CODE (DECL) == STRING_CST && flag_writable_strings)))
@@ -1494,7 +1627,7 @@ do                                                        \
          _rtl = TREE_CST_RTL (DECL);                   \
        SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1;           \
        if (TREE_CODE (DECL) == FUNCTION_DECL)          \
          _rtl = TREE_CST_RTL (DECL);                   \
        SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1;           \
        if (TREE_CODE (DECL) == FUNCTION_DECL)          \
-         hppa_encode_label (XEXP (DECL_RTL (DECL), 0));\
+         hppa_encode_label (XEXP (DECL_RTL (DECL), 0), 0);\
       }                                                        \
   }                                                    \
 while (0)
       }                                                        \
   }                                                    \
 while (0)
@@ -1507,9 +1640,29 @@ while (0)
                             1 + (SYMBOL_NAME)[1] == '@'\
                             : (SYMBOL_NAME)[0] == '@'))
 
                             1 + (SYMBOL_NAME)[1] == '@'\
                             : (SYMBOL_NAME)[0] == '@'))
 
+/* On hpux10, the linker will give an error if we have a reference
+   in the read-only data section to a symbol defined in a shared
+   library.  Therefore, expressions that might require a reloc can
+   not be placed in the read-only data section.  */
+#define SELECT_SECTION(EXP,RELOC) \
+  if (TREE_CODE (EXP) == VAR_DECL \
+      && TREE_READONLY (EXP) \
+      && !TREE_THIS_VOLATILE (EXP) \
+      && DECL_INITIAL (EXP) \
+      && (DECL_INITIAL (EXP) == error_mark_node \
+          || TREE_CONSTANT (DECL_INITIAL (EXP))) \
+      && !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 \
+    data_section ();
+   
 /* Arghh.  This is used for stuff in the constant pool; this may include
    function addresses on the PA, which during PIC code generation must
 /* Arghh.  This is used for stuff in the constant pool; this may include
    function addresses on the PA, which during PIC code generation must
-   reside in the data space.  Unfortuantely, there's no way to determine
+   reside in the data space.  Unfortunately, there's no way to determine
    if a particular label in the constant pool refers to a function address.
    So just force everything into the data space during PIC generation.  */
 #define SELECT_RTX_SECTION(RTX,MODE)   \
    if a particular label in the constant pool refers to a function address.
    So just force everything into the data space during PIC generation.  */
 #define SELECT_RTX_SECTION(RTX,MODE)   \
@@ -1541,6 +1694,11 @@ while (0)
    in one reasonably fast instruction.  */
 #define MOVE_MAX 8
 
    in one reasonably fast instruction.  */
 #define MOVE_MAX 8
 
+/* Higher than the default as we prefer to use simple move insns
+   (better scheduling and delay slot filling) and because our
+   built-in block move is really a 2X unrolled loop.  */
+#define MOVE_RATIO 4
+
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
 #define WORD_REGISTER_OPERATIONS
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
 #define WORD_REGISTER_OPERATIONS
@@ -1555,7 +1713,7 @@ while (0)
 #define SLOW_BYTE_ACCESS 1
 
 /* Do not break .stabs pseudos into continuations.  */
 #define SLOW_BYTE_ACCESS 1
 
 /* Do not break .stabs pseudos into continuations.  */
-#define DBX_CONTIN_LENGTH 0
+#define DBX_CONTIN_LENGTH 4000
 
 /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
    is done just by pretending it is already truncated.  */
 
 /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
    is done just by pretending it is already truncated.  */
@@ -1655,28 +1813,61 @@ while (0)
    switch on CODE.  The purpose for the cost of MULT is to encourage
    `synth_mult' to find a synthetic multiply when reasonable.  */
 
    switch on CODE.  The purpose for the cost of MULT is to encourage
    `synth_mult' to find a synthetic multiply when reasonable.  */
 
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
-  case MULT:                                                   \
-    return (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS            \
-           && ! TARGET_SOFT_FLOAT                              \
-           ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20));          \
-  case DIV:                                                    \
-  case UDIV:                                                   \
-  case MOD:                                                    \
-  case UMOD:                                                   \
-    return COSTS_N_INSNS (60);                                 \
-  case PLUS:                                                   \
-    if (GET_CODE (XEXP (X, 0)) == MULT                         \
-       && shadd_operand (XEXP (XEXP (X, 0), 1), VOIDmode))     \
-      return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \
-             + rtx_cost (XEXP (X, 1), OUTER_CODE));            \
-    break;
+#define RTX_COSTS(X,CODE,OUTER_CODE)                                   \
+  case MULT:                                                           \
+    if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT)                   \
+      return COSTS_N_INSNS (3);                                                \
+    return (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) \
+           ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20);   \
+  case DIV:                                                            \
+    if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT)                   \
+      return COSTS_N_INSNS (14);                                       \
+  case UDIV:                                                           \
+  case MOD:                                                            \
+  case UMOD:                                                           \
+    return COSTS_N_INSNS (60);                                         \
+  case PLUS: /* this includes shNadd insns */                          \
+  case MINUS:                                                          \
+    if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT)                   \
+      return COSTS_N_INSNS (3);                                                \
+    return COSTS_N_INSNS (1);                                          \
+  case ASHIFT:                                                         \
+  case ASHIFTRT:                                                       \
+  case LSHIFTRT:                                                       \
+    return COSTS_N_INSNS (1);
 
 /* Adjust the cost of dependencies.  */
 
 #define ADJUST_COST(INSN,LINK,DEP,COST) \
   (COST) = pa_adjust_cost (INSN, LINK, DEP, COST)
 
 
 /* Adjust the cost of dependencies.  */
 
 #define ADJUST_COST(INSN,LINK,DEP,COST) \
   (COST) = pa_adjust_cost (INSN, LINK, DEP, COST)
 
+/* Adjust scheduling priorities.  We use this to try and keep addil
+   and the next use of %r1 close together.  */
+#define ADJUST_PRIORITY(PREV) \
+  {                                                            \
+    rtx set = single_set (PREV);                               \
+    rtx src, dest;                                             \
+    if (set)                                                   \
+      {                                                                \
+        src = SET_SRC (set);                                   \
+       dest = SET_DEST (set);                                  \
+       if (GET_CODE (src) == LO_SUM                            \
+           && symbolic_operand (XEXP (src, 1), VOIDmode)       \
+           && ! read_only_operand (XEXP (src, 1), VOIDmode))   \
+         INSN_PRIORITY (PREV) >>= 3;                           \
+        else if (GET_CODE (src) == MEM                         \
+                && GET_CODE (XEXP (src, 0)) == LO_SUM          \
+                && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)\
+                && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))\
+         INSN_PRIORITY (PREV) >>= 1;                           \
+       else if (GET_CODE (dest) == MEM                         \
+                && GET_CODE (XEXP (dest, 0)) == LO_SUM         \
+                && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)\
+                && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))\
+         INSN_PRIORITY (PREV) >>= 3;                           \
+      }                                                                \
+  }
+
 /* Handling the special cases is going to get too complicated for a macro,
    just call `pa_adjust_insn_length' to do the real work.  */
 #define ADJUST_INSN_LENGTH(INSN, LENGTH)       \
 /* Handling the special cases is going to get too complicated for a macro,
    just call `pa_adjust_insn_length' to do the real work.  */
 #define ADJUST_INSN_LENGTH(INSN, LENGTH)       \
@@ -1722,14 +1913,14 @@ while (0)
 /* Output at beginning of assembler file.  */
 
 #define ASM_FILE_START(FILE) \
 /* Output at beginning of assembler file.  */
 
 #define ASM_FILE_START(FILE) \
-do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
+do { fputs ("\t.SPACE $PRIVATE$\n\
 \t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\
 \t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\
 \t.SPACE $TEXT$\n\
 \t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\
 \t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\
 \t.IMPORT $global$,DATA\n\
 \t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\
 \t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\
 \t.SPACE $TEXT$\n\
 \t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\
 \t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\
 \t.IMPORT $global$,DATA\n\
-\t.IMPORT $$dyncall,MILLICODE\n");\
+\t.IMPORT $$dyncall,MILLICODE\n", FILE);\
      if (profile_flag)\
        fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\
      if (write_symbols != NO_DEBUG) \
      if (profile_flag)\
        fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\
      if (write_symbols != NO_DEBUG) \
@@ -1747,7 +1938,7 @@ do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
 #define ASM_APP_OFF ""
 
 /* We don't yet know how to identify GCC to HP-PA machines.  */
 #define ASM_APP_OFF ""
 
 /* We don't yet know how to identify GCC to HP-PA machines.  */
-#define ASM_IDENTIFY_GCC(FILE) fprintf (FILE, "; gcc_compiled.:\n")
+#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc_compiled.:\n", FILE)
 
 /* Output before code.  */
 
 
 /* Output before code.  */
 
@@ -1772,7 +1963,41 @@ do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
 
 /* Define the .bss section for ASM_OUTPUT_LOCAL to use. */
 
 
 /* Define the .bss section for ASM_OUTPUT_LOCAL to use. */
 
-#define EXTRA_SECTIONS in_bss, in_readonly_data
+#ifndef CTORS_SECTION_FUNCTION
+#define EXTRA_SECTIONS in_readonly_data
+#define CTORS_SECTION_FUNCTION
+#define DTORS_SECTION_FUNCTION
+#else
+#define EXTRA_SECTIONS in_readonly_data, in_ctors, in_dtors
+#endif
+
+/* Switch into a generic section.
+   This is currently only used to support section attributes.
+
+   We make the section read-only and executable for a function decl,
+   read-only for a const data decl, and writable for a non-const data decl.  */
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+  if (DECL && TREE_CODE (DECL) == FUNCTION_DECL)               \
+    {                                                          \
+      fputs ("\t.SPACE $TEXT$\n", FILE);                       \
+      fprintf (FILE,                                           \
+              "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY,SORT=24\n",\
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
+    }                                                          \
+  else if (DECL && TREE_READONLY (DECL))                       \
+    {                                                          \
+      fputs ("\t.SPACE $TEXT$\n", FILE);                       \
+      fprintf (FILE,                                           \
+              "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,SORT=16\n", \
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      fputs ("\t.SPACE $PRIVATE$\n", FILE);                    \
+      fprintf (FILE,                                           \
+              "\t.SUBSPA %s,QUAD=1,ALIGN=8,ACCESS=31,SORT=16\n", \
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
+    }
 
 /* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
    which reference data within the $TEXT$ space (for example constant
 
 /* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
    which reference data within the $TEXT$ space (for example constant
@@ -1789,15 +2014,6 @@ do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
 
 #define EXTRA_SECTION_FUNCTIONS                                                \
 void                                                                   \
 
 #define EXTRA_SECTION_FUNCTIONS                                                \
 void                                                                   \
-bss_section ()                                                         \
-{                                                                      \
-  if (in_section != in_bss)                                            \
-    {                                                                  \
-      fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP);              \
-      in_section = in_bss;                                             \
-    }                                                                  \
-}                                                                      \
-void                                                                   \
 readonly_data ()                                                       \
 {                                                                      \
   if (in_section != in_readonly_data)                                  \
 readonly_data ()                                                       \
 {                                                                      \
   if (in_section != in_readonly_data)                                  \
@@ -1808,7 +2024,9 @@ readonly_data ()                                                  \
        fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP);           \
       in_section = in_readonly_data;                                   \
     }                                                                  \
        fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP);           \
       in_section = in_readonly_data;                                   \
     }                                                                  \
-}
+}                                                                      \
+CTORS_SECTION_FUNCTION                                                 \
+DTORS_SECTION_FUNCTION
 
 
 /* How to refer to registers in assembler output.
 
 
 /* How to refer to registers in assembler output.
@@ -1858,23 +2076,36 @@ readonly_data ()                                                        \
        fputc ('\n', FILE); } while (0)
 
 /* This is how to output a command to make the user-level label named NAME
        fputc ('\n', FILE); } while (0)
 
 /* This is how to output a command to make the user-level label named NAME
-   defined for reference from other files.  */
+   defined for reference from other files.
+
+   We call assemble_name, which in turn sets TREE_SYMBOL_REFERENCED.  This
+   macro will restore the original value of TREE_SYMBOL_REFERENCED to avoid
+   placing useless function definitions in the output file.  */
 
 #define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)  \
 
 #define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)  \
-  do { fputs ("\t.IMPORT ", FILE);                             \
+  do { int save_referenced;                                    \
+       save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)); \
+       fputs ("\t.IMPORT ", FILE);                                     \
         assemble_name (FILE, NAME);                            \
        if (FUNCTION_NAME_P (NAME))                                     \
         fputs (",CODE\n", FILE);                               \
        else                                                    \
         fputs (",DATA\n", FILE);                               \
         assemble_name (FILE, NAME);                            \
        if (FUNCTION_NAME_P (NAME))                                     \
         fputs (",CODE\n", FILE);                               \
        else                                                    \
         fputs (",DATA\n", FILE);                               \
+       TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)) = save_referenced; \
      } while (0)
 
 /* The bogus HP assembler requires ALL external references to be
    "imported", even library calls. They look a bit different, so
      } while (0)
 
 /* The bogus HP assembler requires ALL external references to be
    "imported", even library calls. They look a bit different, so
-   here's this macro. */
+   here's this macro.
+
+   Also note not all libcall names are passed to ENCODE_SECTION_INFO
+   (__main for example).  To make sure all libcall names have section
+   info recorded in them, we do it here.  */
 
 #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
   do { fputs ("\t.IMPORT ", FILE);                                     \
 
 #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
   do { fputs ("\t.IMPORT ", FILE);                                     \
+       if (!function_label_operand (RTL, VOIDmode))                    \
+        hppa_encode_label (RTL, 1);                                    \
        assemble_name (FILE, XSTR ((RTL), 0));                          \
        fputs (",CODE\n", FILE);                                                \
      } while (0)
        assemble_name (FILE, XSTR ((RTL), 0));                          \
        fputs (",CODE\n", FILE);                                                \
      } while (0)
@@ -1927,27 +2158,31 @@ readonly_data ()                                                        \
        fprintf (FILE, "\t.word 0x%lx\n", l);                           \
      } while (0)
 
        fprintf (FILE, "\t.word 0x%lx\n", l);                           \
      } while (0)
 
-/* This is how to output an assembler line defining an `int' constant.  */
+/* This is how to output an assembler line defining an `int' constant. 
+
+   This is made more complicated by the fact that functions must be
+   prefixed by a P% as well as code label references for the exception
+   table -- otherwise the linker chokes.  */
 
 #define ASM_OUTPUT_INT(FILE,VALUE)  \
 
 #define ASM_OUTPUT_INT(FILE,VALUE)  \
-{ fprintf (FILE, "\t.word ");                  \
+{ fputs ("\t.word ", FILE);                    \
   if (function_label_operand (VALUE, VOIDmode) \
       && !TARGET_PORTABLE_RUNTIME)             \
   if (function_label_operand (VALUE, VOIDmode) \
       && !TARGET_PORTABLE_RUNTIME)             \
-    fprintf (FILE, "P%%");                     \
+    fputs ("P%", FILE);                                \
   output_addr_const (FILE, (VALUE));           \
   output_addr_const (FILE, (VALUE));           \
-  fprintf (FILE, "\n");}
+  fputs ("\n", FILE);}
 
 /* Likewise for `short' and `char' constants.  */
 
 #define ASM_OUTPUT_SHORT(FILE,VALUE)  \
 
 /* Likewise for `short' and `char' constants.  */
 
 #define ASM_OUTPUT_SHORT(FILE,VALUE)  \
-( fprintf (FILE, "\t.half "),                  \
+( fputs ("\t.half ", FILE),                    \
   output_addr_const (FILE, (VALUE)),           \
   output_addr_const (FILE, (VALUE)),           \
-  fprintf (FILE, "\n"))
+  fputs ("\n", FILE))
 
 #define ASM_OUTPUT_CHAR(FILE,VALUE)  \
 
 #define ASM_OUTPUT_CHAR(FILE,VALUE)  \
-( fprintf (FILE, "\t.byte "),                  \
+( fputs ("\t.byte ", FILE),                    \
   output_addr_const (FILE, (VALUE)),           \
   output_addr_const (FILE, (VALUE)),           \
-  fprintf (FILE, "\n"))
+  fputs ("\n", FILE))
 
 /* This is how to output an assembler line for a numeric constant byte.  */
 
 
 /* This is how to output an assembler line for a numeric constant byte.  */
 
@@ -1972,7 +2207,7 @@ readonly_data ()                                                  \
 /* This is how to output an element of a case-vector that is relative.
    This must be defined correctly as it is used when generating PIC code.
 
 /* This is how to output an element of a case-vector that is relative.
    This must be defined correctly as it is used when generating PIC code.
 
-   I belive it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT
+   I believe it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT
    on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions
    rather than a table of absolute addresses.  */
 
    on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions
    rather than a table of absolute addresses.  */
 
@@ -2074,13 +2309,15 @@ readonly_data ()                                                        \
       fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]);    \
       break;                                                           \
     case LO_SUM:                                                       \
       fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]);    \
       break;                                                           \
     case LO_SUM:                                                       \
-      if (flag_pic == 0 || !symbolic_operand (XEXP (addr, 1)))         \
+      if (!symbolic_operand (XEXP (addr, 1)))                          \
        fputs ("R'", FILE);                                             \
        fputs ("R'", FILE);                                             \
+      else if (flag_pic == 0)                                          \
+       fputs ("RR'", FILE);                                            \
       else if (flag_pic == 1)                                          \
        abort ();                                                       \
       else if (flag_pic == 2)                                          \
        fputs ("RT'", FILE);                                            \
       else if (flag_pic == 1)                                          \
        abort ();                                                       \
       else if (flag_pic == 2)                                          \
        fputs ("RT'", FILE);                                            \
-      output_global_address (FILE, XEXP (addr, 1));                    \
+      output_global_address (FILE, XEXP (addr, 1), 0);                 \
       fputs ("(", FILE);                                               \
       output_operand (XEXP (addr, 0), 0);                              \
       fputs (")", FILE);                                               \
       fputs ("(", FILE);                                               \
       output_operand (XEXP (addr, 0), 0);                              \
       fputs (")", FILE);                                               \
@@ -2102,10 +2339,14 @@ extern char *output_fp_move_double ();
 extern char *output_block_move ();
 extern char *output_cbranch ();
 extern char *output_bb ();
 extern char *output_block_move ();
 extern char *output_cbranch ();
 extern char *output_bb ();
+extern char *output_bvb ();
 extern char *output_dbra ();
 extern char *output_movb ();
 extern char *output_dbra ();
 extern char *output_movb ();
+extern char *output_parallel_movb ();
+extern char *output_parallel_addb ();
 extern char *output_return ();
 extern char *output_call ();
 extern char *output_return ();
 extern char *output_call ();
+extern char *output_millicode_call ();
 extern char *output_mul_insn ();
 extern char *output_div_insn ();
 extern char *output_mod_insn ();
 extern char *output_mul_insn ();
 extern char *output_div_insn ();
 extern char *output_mod_insn ();
@@ -2116,49 +2357,37 @@ extern struct rtx_def *legitimize_pic_address ();
 extern struct rtx_def *gen_cmp_fp ();
 extern void hppa_encode_label ();
 
 extern struct rtx_def *gen_cmp_fp ();
 extern void hppa_encode_label ();
 
-extern struct rtx_def *hppa_save_pic_table_rtx;
-
-#if 0
-#define PREDICATE_CODES \
-  {"reg_or_0_operand", {SUBREG, REG, CONST_INT}},                      \
-  {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}},              \
-  {"arith_operand", {SUBREG, REG, CONST_INT}},                         \
-  {"arith32_operand", {SUBREG, REG, CONST_INT}},                       \
-  {"arith11_operand", {SUBREG, REG, CONST_INT}},                       \
-  {"arith5_operand", {SUBREG, REG, CONST_INT}},                                \
-  {"pre_cint_operand", {CONST_INT}},                                   \
-  {"post_cint_operand", {CONST_INT}},                                  \
-  {"int5_operand", {CONST_INT}},                                       \
-  {"uint5_operand", {CONST_INT}},                                      \
-  {"uint32_operand", {CONST_INT}},                                     \
-  {"int11_operand", {CONST_INT}},                                      \
-  {"and_operand", {SUBREG, REG, CONST_INT}},                           \
-  {"ior_operand", {CONST_INT}},                                                \
-  {"lhs_lshift_operand", {SUBREG, REG, CONST_INT}},                    \
-  {"lhs_lshift_cint_operand", {CONST_INT}},                            \
-  {"plus_xor_ior_operator", {PLUS, XOR, IOR}},                         \
-  {"shadd_operand", {CONST_INT}},                                      \
-  {"eq_neq_comparison_operator", {EQ, NE}},                            \
-  {"movb_comparison_operator", {EQ, NE, LT, GE}},                      \
-  {"pc_or_label_operand", {LABEL_REF, PC}},                            \
-  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
-  {"reg_or_nonsymb_mem_operand", {REG, SUBREG, MEM}},                  \
-  {"move_operand", {REG, SUBREG, CONST_INT, MEM}},                     \
-  {"pic_operand", {REG, SUBREG, CONST_INT, SYMBOL_REF, LABEL_REF,      \
-                  CONST, HIGH, PC}},   /* No clue */                   \
-  {"function_label_operand", {SYMBOL_REF}},                            \
-  {"reg_or_0_or_nonsymb_mem_operand", {REG, SUBREG, CONST_INT, MEM}},  \
-  {"div_operand", {REG, CONST_INT}},                                   \
-  {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT,          \
-                           CONST, HIGH}},
-#endif
+/* Declare functions defined in pa.c and used in templates.  */
 
 
-#define DO_GLOBAL_DTORS_BODY \
-do { \
-  extern void __gcc_plt_call (); \
-  volatile int reference = &__gcc_plt_call; \
-  func_ptr *p; \
-  for (p = __DTOR_LIST__ + 1; *p; ) \
-    (*p++) (); \
+extern struct rtx_def *return_addr_rtx ();
+
+/* We want __gcc_plt_call to appear in every program built by
+   gcc, so we make a reference to it out of __main.
+   We use the asm statement to fool the optimizer into not
+   removing the dead (but important) initialization of
+   REFERENCE.  */
+
+#define DO_GLOBAL_DTORS_BODY                   \
+do {                                           \
+  extern void __gcc_plt_call ();               \
+  void (*reference)() = &__gcc_plt_call;       \
+  func_ptr *p;                                 \
+  __asm__ ("" : : "r" (reference));            \
+  for (p = __DTOR_LIST__ + 1; *p; )            \
+    (*p++) ();                                 \
 } while (0)
 
 } while (0)
 
+/* Find the return address associated with the frame given by
+   FRAMEADDR.  */
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR)                               \
+  (return_addr_rtx (COUNT, FRAMEADDR))
+
+/* Used to mask out junk bits from the return address, such as
+   processor state, interrupt status, condition codes and the like.  */
+#define MASK_RETURN_ADDR                                               \
+  /* The privilege level is in the two low order bits, mask em out     \
+     of the return address.  */                                                \
+  (GEN_INT (0xfffffffc))
+
+/* The number of Pmode words for the setjmp buffer.  */
+#define JMP_BUF_SIZE 50