OSDN Git Service

Fix linux kernel miscompilation.
[pf3gnuchains/gcc-fork.git] / gcc / config / ia64 / ia64.c
index 3803033..871c52d 100644 (file)
@@ -1,7 +1,8 @@
 /* Definitions of target machine for GNU compiler.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
    Contributed by James E. Wilson <wilson@cygnus.com> and
-                 David Mosberger <davidm@hpl.hp.com>.
+                 David Mosberger <davidm@hpl.hp.com>.
 
 This file is part of GCC.
 
@@ -50,6 +51,7 @@ Boston, MA 02111-1307, USA.  */
 #include "hashtab.h"
 #include "langhooks.h"
 #include "cfglayout.h"
+#include "tree-gimple.h"
 
 /* This is used for communication between ASM_OUTPUT_LABEL and
    ASM_OUTPUT_LABELREF.  */
@@ -116,6 +118,10 @@ const char *ia64_tune_string;
    avoid the normal second scheduling pass.  */
 static int ia64_flag_schedule_insns2;
 
+/* Determines whether we run variable tracking in machine dependent
+   reorganization.  */
+static int ia64_flag_var_tracking;
+
 /* Variables which are this size or smaller are put in the sdata/sbss
    sections.  */
 
@@ -136,7 +142,7 @@ struct ia64_frame_info
   HOST_WIDE_INT spill_size;    /* size of the gr/br/fr spill area.  */
   HOST_WIDE_INT extra_spill_size;  /* size of spill area for others.  */
   HARD_REG_SET mask;           /* mask of saved registers.  */
-  unsigned int gr_used_mask;   /* mask of registers in use as gr spill 
+  unsigned int gr_used_mask;   /* mask of registers in use as gr spill
                                   registers or long-term scratches.  */
   int n_spilled;               /* number of spilled registers.  */
   int reg_fp;                  /* register for fp.  */
@@ -158,109 +164,119 @@ struct ia64_frame_info
 /* Current frame information calculated by ia64_compute_frame_size.  */
 static struct ia64_frame_info current_frame_info;
 \f
-static int ia64_use_dfa_pipeline_interface PARAMS ((void));
-static int ia64_first_cycle_multipass_dfa_lookahead PARAMS ((void));
-static void ia64_dependencies_evaluation_hook PARAMS ((rtx, rtx));
-static void ia64_init_dfa_pre_cycle_insn PARAMS ((void));
-static rtx ia64_dfa_pre_cycle_insn PARAMS ((void));
-static int ia64_first_cycle_multipass_dfa_lookahead_guard PARAMS ((rtx));
-static int ia64_dfa_new_cycle PARAMS ((FILE *, int, rtx, int, int, int *));
-static rtx gen_tls_get_addr PARAMS ((void));
-static rtx gen_thread_pointer PARAMS ((void));
-static rtx ia64_expand_tls_address PARAMS ((enum tls_model, rtx, rtx));
-static int find_gr_spill PARAMS ((int));
-static int next_scratch_gr_reg PARAMS ((void));
-static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
-static void ia64_compute_frame_size PARAMS ((HOST_WIDE_INT));
-static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT));
-static void finish_spill_pointers PARAMS ((void));
-static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT));
-static void do_spill PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx));
-static void do_restore PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT));
-static rtx gen_movdi_x PARAMS ((rtx, rtx, rtx));
-static rtx gen_fr_spill_x PARAMS ((rtx, rtx, rtx));
-static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
-
-static enum machine_mode hfa_element_mode PARAMS ((tree, int));
-static bool ia64_function_ok_for_sibcall PARAMS ((tree, tree));
-static bool ia64_rtx_costs PARAMS ((rtx, int, int, int *));
-static void fix_range PARAMS ((const char *));
-static struct machine_function * ia64_init_machine_status PARAMS ((void));
-static void emit_insn_group_barriers PARAMS ((FILE *));
-static void emit_all_insn_group_barriers PARAMS ((FILE *));
-static void final_emit_insn_group_barriers PARAMS ((FILE *));
-static void emit_predicate_relation_info PARAMS ((void));
-static void ia64_reorg PARAMS ((void));
-static bool ia64_in_small_data_p PARAMS ((tree));
-static void process_epilogue PARAMS ((void));
-static int process_set PARAMS ((FILE *, rtx));
-
-static rtx ia64_expand_fetch_and_op PARAMS ((optab, enum machine_mode,
-                                            tree, rtx));
-static rtx ia64_expand_op_and_fetch PARAMS ((optab, enum machine_mode,
-                                            tree, rtx));
-static rtx ia64_expand_compare_and_swap PARAMS ((enum machine_mode,
-                                                enum machine_mode,
-                                                int, tree, rtx));
-static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode,
-                                                 tree, rtx));
-static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));
-static bool ia64_assemble_integer PARAMS ((rtx, unsigned int, int));
-static void ia64_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static void ia64_output_function_end_prologue PARAMS ((FILE *));
-
-static int ia64_issue_rate PARAMS ((void));
-static int ia64_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static void ia64_sched_init PARAMS ((FILE *, int, int));
-static void ia64_sched_finish PARAMS ((FILE *, int));
-static int ia64_dfa_sched_reorder PARAMS ((FILE *, int, rtx *, int *,
-                                          int, int));
-static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
-static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));
-static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));
-
-static struct bundle_state *get_free_bundle_state PARAMS ((void));
-static void free_bundle_state PARAMS ((struct bundle_state *));
-static void initiate_bundle_states PARAMS ((void));
-static void finish_bundle_states PARAMS ((void));
-static unsigned bundle_state_hash PARAMS ((const void *));
-static int bundle_state_eq_p PARAMS ((const void *, const void *));
-static int insert_bundle_state PARAMS ((struct bundle_state *));
-static void initiate_bundle_state_table PARAMS ((void));
-static void finish_bundle_state_table PARAMS ((void));
-static int try_issue_nops PARAMS ((struct bundle_state *, int));
-static int try_issue_insn PARAMS ((struct bundle_state *, rtx));
-static void issue_nops_and_insn PARAMS ((struct bundle_state *, int,
-                                        rtx, int, int));
-static int get_max_pos PARAMS ((state_t));
-static int get_template PARAMS ((state_t, int));
-
-static rtx get_next_important_insn PARAMS ((rtx, rtx));
-static void bundling PARAMS ((FILE *, int, rtx, rtx));
-
-static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
-                                         HOST_WIDE_INT, tree));
-static void ia64_file_start PARAMS ((void));
-
-static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx,
-                                            unsigned HOST_WIDE_INT));
-static void ia64_rwreloc_select_section PARAMS ((tree, int,
-                                                unsigned HOST_WIDE_INT))
+static int ia64_first_cycle_multipass_dfa_lookahead (void);
+static void ia64_dependencies_evaluation_hook (rtx, rtx);
+static void ia64_init_dfa_pre_cycle_insn (void);
+static rtx ia64_dfa_pre_cycle_insn (void);
+static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
+static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
+static rtx gen_tls_get_addr (void);
+static rtx gen_thread_pointer (void);
+static rtx ia64_expand_tls_address (enum tls_model, rtx, rtx);
+static int find_gr_spill (int);
+static int next_scratch_gr_reg (void);
+static void mark_reg_gr_used_mask (rtx, void *);
+static void ia64_compute_frame_size (HOST_WIDE_INT);
+static void setup_spill_pointers (int, rtx, HOST_WIDE_INT);
+static void finish_spill_pointers (void);
+static rtx spill_restore_mem (rtx, HOST_WIDE_INT);
+static void do_spill (rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx);
+static void do_restore (rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT);
+static rtx gen_movdi_x (rtx, rtx, rtx);
+static rtx gen_fr_spill_x (rtx, rtx, rtx);
+static rtx gen_fr_restore_x (rtx, rtx, rtx);
+
+static enum machine_mode hfa_element_mode (tree, int);
+static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+                                        tree, int *, int);
+static bool ia64_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+                                   tree, bool);
+static bool ia64_function_ok_for_sibcall (tree, tree);
+static bool ia64_return_in_memory (tree, tree);
+static bool ia64_rtx_costs (rtx, int, int, int *);
+static void fix_range (const char *);
+static struct machine_function * ia64_init_machine_status (void);
+static void emit_insn_group_barriers (FILE *);
+static void emit_all_insn_group_barriers (FILE *);
+static void final_emit_insn_group_barriers (FILE *);
+static void emit_predicate_relation_info (void);
+static void ia64_reorg (void);
+static bool ia64_in_small_data_p (tree);
+static void process_epilogue (void);
+static int process_set (FILE *, rtx);
+
+static rtx ia64_expand_fetch_and_op (optab, enum machine_mode, tree, rtx);
+static rtx ia64_expand_op_and_fetch (optab, enum machine_mode, tree, rtx);
+static rtx ia64_expand_compare_and_swap (enum machine_mode, enum machine_mode,
+                                        int, tree, rtx);
+static rtx ia64_expand_lock_test_and_set (enum machine_mode, tree, rtx);
+static rtx ia64_expand_lock_release (enum machine_mode, tree, rtx);
+static bool ia64_assemble_integer (rtx, unsigned int, int);
+static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
+static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static void ia64_output_function_end_prologue (FILE *);
+
+static int ia64_issue_rate (void);
+static int ia64_adjust_cost (rtx, rtx, rtx, int);
+static void ia64_sched_init (FILE *, int, int);
+static void ia64_sched_finish (FILE *, int);
+static int ia64_dfa_sched_reorder (FILE *, int, rtx *, int *, int, int);
+static int ia64_sched_reorder (FILE *, int, rtx *, int *, int);
+static int ia64_sched_reorder2 (FILE *, int, rtx *, int *, int);
+static int ia64_variable_issue (FILE *, int, rtx, int);
+
+static struct bundle_state *get_free_bundle_state (void);
+static void free_bundle_state (struct bundle_state *);
+static void initiate_bundle_states (void);
+static void finish_bundle_states (void);
+static unsigned bundle_state_hash (const void *);
+static int bundle_state_eq_p (const void *, const void *);
+static int insert_bundle_state (struct bundle_state *);
+static void initiate_bundle_state_table (void);
+static void finish_bundle_state_table (void);
+static int try_issue_nops (struct bundle_state *, int);
+static int try_issue_insn (struct bundle_state *, rtx);
+static void issue_nops_and_insn (struct bundle_state *, int, rtx, int, int);
+static int get_max_pos (state_t);
+static int get_template (state_t, int);
+
+static rtx get_next_important_insn (rtx, rtx);
+static void bundling (FILE *, int, rtx, rtx);
+
+static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
+                                 HOST_WIDE_INT, tree);
+static void ia64_file_start (void);
+
+static void ia64_select_rtx_section (enum machine_mode, rtx,
+                                    unsigned HOST_WIDE_INT);
+static void ia64_rwreloc_select_section (tree, int, unsigned HOST_WIDE_INT)
      ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_unique_section PARAMS ((tree, int))
+static void ia64_rwreloc_unique_section (tree, int)
      ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_select_rtx_section PARAMS ((enum machine_mode, rtx,
-                                                    unsigned HOST_WIDE_INT))
+static void ia64_rwreloc_select_rtx_section (enum machine_mode, rtx,
+                                            unsigned HOST_WIDE_INT)
      ATTRIBUTE_UNUSED;
-static unsigned int ia64_rwreloc_section_type_flags
-     PARAMS ((tree, const char *, int))
+static unsigned int ia64_rwreloc_section_type_flags (tree, const char *, int)
      ATTRIBUTE_UNUSED;
 
-static void ia64_hpux_add_extern_decl PARAMS ((const char *name))
+static void ia64_hpux_add_extern_decl (tree decl)
+     ATTRIBUTE_UNUSED;
+static void ia64_hpux_file_end (void)
+     ATTRIBUTE_UNUSED;
+static void ia64_init_libfuncs (void)
+     ATTRIBUTE_UNUSED;
+static void ia64_hpux_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
-static void ia64_hpux_file_end PARAMS ((void))
+static void ia64_sysv4_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
+static void ia64_vms_init_libfuncs (void)
+     ATTRIBUTE_UNUSED;
+
+static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
+static void ia64_encode_section_info (tree, rtx, int);
+static rtx ia64_struct_value_rtx (tree, int);
+static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
 
 \f
 /* Table of valid machine attributes.  */
@@ -268,7 +284,8 @@ static const struct attribute_spec ia64_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "syscall_linkage", 0, 0, false, true,  true,  NULL },
-  { NULL,              0, 0, false, false, false, NULL }
+  { "model",          1, 1, true, false, false, ia64_handle_model_attribute },
+  { NULL,             0, 0, false, false, false, NULL }
 };
 
 /* Initialize the GCC target structure.  */
@@ -326,9 +343,6 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
 #define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
 
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE ia64_use_dfa_pipeline_interface
-
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
 
@@ -344,13 +358,10 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_SCHED_DFA_NEW_CYCLE
 #define TARGET_SCHED_DFA_NEW_CYCLE ia64_dfa_new_cycle
 
-#ifdef HAVE_AS_TLS
-#undef TARGET_HAVE_TLS
-#define TARGET_HAVE_TLS true
-#endif
-
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE ia64_pass_by_reference
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
@@ -368,683 +379,176 @@ static const struct attribute_spec ia64_attribute_table[] =
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG ia64_reorg
 
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
 
-int
-call_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
-         || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
-}
-
-/* Return 1 if OP refers to a symbol in the sdata section.  */
-
-int
-sdata_symbolic_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  switch (GET_CODE (op))
-    {
-    case CONST:
-      if (GET_CODE (XEXP (op, 0)) != PLUS
-         || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF)
-       break;
-      op = XEXP (XEXP (op, 0), 0);
-      /* FALLTHRU */
-
-    case SYMBOL_REF:
-      if (CONSTANT_POOL_ADDRESS_P (op))
-       return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
-      else
-       return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op);
-
-    default:
-      break;
-    }
-
-  return 0;
-}
-
-/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load.  */
+/* ??? ABI doesn't allow us to define this.  */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#endif
 
-int
-got_symbolic_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  switch (GET_CODE (op))
-    {
-    case CONST:
-      op = XEXP (op, 0);
-      if (GET_CODE (op) != PLUS)
-       return 0;
-      if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
-       return 0;
-      op = XEXP (op, 1);
-      if (GET_CODE (op) != CONST_INT)
-       return 0;
+/* ??? ABI doesn't allow us to define this.  */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#endif
 
-       return 1;
+/* ??? Investigate.  */
+#if 0
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#endif
 
-      /* Ok if we're not using GOT entries at all.  */
-      if (TARGET_NO_PIC || TARGET_AUTO_PIC)
-       return 1;
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY ia64_return_in_memory
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
 
-      /* "Ok" while emitting rtl, since otherwise we won't be provided
-        with the entire offset during emission, which makes it very
-        hard to split the offset into high and low parts.  */
-      if (rtx_equal_function_value_matters)
-       return 1;
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
 
-      /* Force the low 14 bits of the constant to zero so that we do not
-        use up so many GOT entries.  */
-      return (INTVAL (op) & 0x3fff) == 0;
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT process_for_unwind_directive
 
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 1;
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
 
-    default:
-      break;
-    }
-  return 0;
-}
+struct gcc_target targetm = TARGET_INITIALIZER;
+\f
+typedef enum
+  {
+    ADDR_AREA_NORMAL,  /* normal address area */
+    ADDR_AREA_SMALL    /* addressable by "addl" (-2MB < addr < 2MB) */
+  }
+ia64_addr_area;
 
-/* Return 1 if OP refers to a symbol.  */
+static GTY(()) tree small_ident1;
+static GTY(()) tree small_ident2;
 
-int
-symbolic_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+static void
+init_idents (void)
 {
-  switch (GET_CODE (op))
+  if (small_ident1 == 0)
     {
-    case CONST:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 1;
-
-    default:
-      break;
+      small_ident1 = get_identifier ("small");
+      small_ident2 = get_identifier ("__small__");
     }
-  return 0;
-}
-
-/* Return tls_model if OP refers to a TLS symbol.  */
-
-int
-tls_symbolic_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
-  return SYMBOL_REF_TLS_MODEL (op);
-}
-
-
-/* Return 1 if OP refers to a function.  */
-
-int
-function_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op))
-    return 1;
-  else
-    return 0;
 }
 
-/* Return 1 if OP is setjmp or a similar function.  */
+/* Retrieve the address area that has been chosen for the given decl.  */
 
-/* ??? This is an unsatisfying solution.  Should rethink.  */
-
-int
-setjmp_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+static ia64_addr_area
+ia64_get_addr_area (tree decl)
 {
-  const char *name;
-  int retval = 0;
+  tree model_attr;
 
-  if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
-
-  name = XSTR (op, 0);
-
-  /* The following code is borrowed from special_function_p in calls.c.  */
-
-  /* Disregard prefix _, __ or __x.  */
-  if (name[0] == '_')
+  model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
+  if (model_attr)
     {
-      if (name[1] == '_' && name[2] == 'x')
-       name += 3;
-      else if (name[1] == '_')
-       name += 2;
-      else
-       name += 1;
-    }
+      tree id;
 
-  if (name[0] == 's')
-    {
-      retval
-       = ((name[1] == 'e'
-           && (! strcmp (name, "setjmp")
-               || ! strcmp (name, "setjmp_syscall")))
-          || (name[1] == 'i'
-              && ! strcmp (name, "sigsetjmp"))
-          || (name[1] == 'a'
-              && ! strcmp (name, "savectx")));
+      init_idents ();
+      id = TREE_VALUE (TREE_VALUE (model_attr));
+      if (id == small_ident1 || id == small_ident2)
+       return ADDR_AREA_SMALL;
     }
-  else if ((name[0] == 'q' && name[1] == 's'
-           && ! strcmp (name, "qsetjmp"))
-          || (name[0] == 'v' && name[1] == 'f'
-              && ! strcmp (name, "vfork")))
-    retval = 1;
-
-  return retval;
+  return ADDR_AREA_NORMAL;
 }
 
-/* Return 1 if OP is a general operand, excluding tls symbolic operands.  */
-
-int
-move_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+static tree
+ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
 {
-  return general_operand (op, mode) && !tls_symbolic_operand (op, mode);
-}
+  ia64_addr_area addr_area = ADDR_AREA_NORMAL;
+  ia64_addr_area area;
+  tree arg, decl = *node;
 
-/* Return 1 if OP is a register operand that is (or could be) a GR reg.  */
-
-int
-gr_register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! register_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
+  init_idents ();
+  arg = TREE_VALUE (args);
+  if (arg == small_ident1 || arg == small_ident2)
     {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return GENERAL_REGNO_P (regno);
+      addr_area = ADDR_AREA_SMALL;
     }
-  return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) an FR reg.  */
-
-int
-fr_register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! register_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
+  else
     {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return FR_REGNO_P (regno);
+      warning ("invalid argument of `%s' attribute",
+              IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
     }
-  return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg.  */
 
-int
-grfr_register_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! register_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
+  switch (TREE_CODE (decl))
     {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
-    }
-  return 1;
-}
+    case VAR_DECL:
+      if ((DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl))
+          == FUNCTION_DECL)
+         && !TREE_STATIC (decl))
+       {
+         error ("%Jan address area attribute cannot be specified for "
+                "local variables", decl, decl);
+         *no_add_attrs = true;
+       }
+      area = ia64_get_addr_area (decl);
+      if (area != ADDR_AREA_NORMAL && addr_area != area)
+       {
+         error ("%Jaddress area of '%s' conflicts with previous "
+                "declaration", decl, decl);
+         *no_add_attrs = true;
+       }
+      break;
 
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg.  */
+    case FUNCTION_DECL:
+      error ("%Jaddress area attribute cannot be specified for functions",
+            decl, decl);
+      *no_add_attrs = true;
+      break;
 
-int
-gr_nonimmediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! nonimmediate_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
-    {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return GENERAL_REGNO_P (regno);
+    default:
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+      break;
     }
-  return 1;
-}
 
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg.  */
-
-int
-fr_nonimmediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! nonimmediate_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
-    {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return FR_REGNO_P (regno);
-    }
-  return 1;
+  return NULL_TREE;
 }
 
-/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg.  */
-
-int
-grfr_nonimmediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+static void
+ia64_encode_addr_area (tree decl, rtx symbol)
 {
-  if (! nonimmediate_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  if (GET_CODE (op) == REG)
+  int flags;
+
+  flags = SYMBOL_REF_FLAGS (symbol);
+  switch (ia64_get_addr_area (decl))
     {
-      unsigned int regno = REGNO (op);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
+    case ADDR_AREA_NORMAL: break;
+    case ADDR_AREA_SMALL: flags |= SYMBOL_FLAG_SMALL_ADDR; break;
+    default: abort ();
     }
-  return 1;
-}
-
-/* Return 1 if OP is a GR register operand, or zero.  */
-
-int
-gr_reg_or_0_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return (op == const0_rtx || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand.  */
-
-int
-gr_reg_or_5bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand.  */
-
-int
-gr_reg_or_6bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand.  */
-
-int
-gr_reg_or_8bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate.  */
-
-int
-grfr_reg_or_8bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || grfr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate
-   operand.  */
-
-int
-gr_reg_or_8bit_adjusted_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or is valid for both an 8 bit
-   immediate and an 8 bit adjusted immediate operand.  This is necessary
-   because when we emit a compare, we don't know what the condition will be,
-   so we need the union of the immediates accepted by GT and LT.  */
-
-int
-gr_reg_or_8bit_and_adjusted_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
-          && CONST_OK_FOR_L (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 14 bit immediate operand.  */
-
-int
-gr_reg_or_14bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 22 bit immediate operand.  */
-
-int
-gr_reg_or_22bit_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX
-         || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a 6 bit immediate operand.  */
-
-int
-shift_count_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
-         || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 5 bit immediate operand.  */
-
-int
-shift_32bit_count_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return ((GET_CODE (op) == CONST_INT
-          && (INTVAL (op) >= 0 && INTVAL (op) < 32))
-         || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand.  */
-
-int
-shladd_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) == 2 || INTVAL (op) == 4
-             || INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand.  */
-
-int
-fetchadd_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return (GET_CODE (op) == CONST_INT
-          && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
-              INTVAL (op) == -4  || INTVAL (op) == -1 ||
-              INTVAL (op) == 1   || INTVAL (op) == 4  ||
-              INTVAL (op) == 8   || INTVAL (op) == 16));
+  SYMBOL_REF_FLAGS (symbol) = flags;
 }
 
-/* Return 1 if OP is a floating-point constant zero, one, or a register.  */
-
-int
-fr_reg_or_fp01_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
-         || fr_register_operand (op, mode));
-}
-
-/* Like nonimmediate_operand, but don't allow MEMs that try to use a
-   POST_MODIFY with a REG as displacement.  */
-
-int
-destination_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! nonimmediate_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == MEM
-      && GET_CODE (XEXP (op, 0)) == POST_MODIFY
-      && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
-    return 0;
-  return 1;
-}
-
-/* Like memory_operand, but don't allow post-increments.  */
-
-int
-not_postinc_memory_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return (memory_operand (op, mode)
-         && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != 'a');
-}
-
-/* Return 1 if this is a comparison operator, which accepts a normal 8-bit
-   signed immediate operand.  */
-
-int
-normal_comparison_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
-{
-  enum rtx_code code = GET_CODE (op);
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && (code == EQ || code == NE
-             || code == GT || code == LE || code == GTU || code == LEU));
-}
-
-/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit
-   signed immediate operand.  */
-
-int
-adjusted_comparison_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
-{
-  enum rtx_code code = GET_CODE (op);
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && (code == LT || code == GE || code == LTU || code == GEU));
-}
-
-/* Return 1 if this is a signed inequality operator.  */
-
-int
-signed_inequality_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
-{
-  enum rtx_code code = GET_CODE (op);
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && (code == GE || code == GT
-             || code == LE || code == LT));
-}
-
-/* Return 1 if this operator is valid for predication.  */
-
-int
-predicate_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
-{
-  enum rtx_code code = GET_CODE (op);
-  return ((GET_MODE (op) == mode || mode == VOIDmode)
-         && (code == EQ || code == NE));
-}
-
-/* Return 1 if this operator can be used in a conditional operation.  */
-
-int
-condop_operator (op, mode)
-    register rtx op;
-    enum machine_mode mode;
-{
-  enum rtx_code code = GET_CODE (op);
-  return ((GET_MODE (op) == mode || mode == VOIDmode)
-         && (code == PLUS || code == MINUS || code == AND
-             || code == IOR || code == XOR));
-}
-
-/* Return 1 if this is the ar.lc register.  */
-
-int
-ar_lc_reg_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  return (GET_MODE (op) == DImode
-         && (mode == DImode || mode == VOIDmode)
-         && GET_CODE (op) == REG
-         && REGNO (op) == AR_LC_REGNUM);
-}
-
-/* Return 1 if this is the ar.ccv register.  */
-
-int
-ar_ccv_reg_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_MODE (op) == mode || mode == VOIDmode)
-         && GET_CODE (op) == REG
-         && REGNO (op) == AR_CCV_REGNUM);
-}
-
-/* Return 1 if this is the ar.pfs register.  */
-
-int
-ar_pfs_reg_operand (op, mode)
-     register rtx op;
-     enum machine_mode mode;
-{
-  return ((GET_MODE (op) == mode || mode == VOIDmode)
-         && GET_CODE (op) == REG
-         && REGNO (op) == AR_PFS_REGNUM);
-}
-
-/* Like general_operand, but don't allow (mem (addressof)).  */
-
-int
-general_tfmode_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! general_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-    return 0;
-  return 1;
-}
-
-/* Similarly.  */
-
-int
-destination_tfmode_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (! destination_operand (op, mode))
-    return 0;
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-    return 0;
-  return 1;
-}
-
-/* Similarly.  */
-
-int
-tfreg_or_fp01_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  if (GET_CODE (op) == SUBREG)
-    return 0;
-  return fr_reg_or_fp01_operand (op, mode);
-}
-
-/* Return 1 if OP is valid as a base register in a reg + offset address.  */
-
-int
-basereg_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+static void
+ia64_encode_section_info (tree decl, rtx rtl, int first)
 {
-  /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
-     checks from pa.c basereg_operand as well?  Seems to be OK without them
-     in test runs.  */
+  default_encode_section_info (decl, rtl, first);
 
-  return (register_operand (op, mode) &&
-         REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
+  /* Careful not to prod global register variables.  */
+  if (TREE_CODE (decl) == VAR_DECL
+      && GET_CODE (DECL_RTL (decl)) == MEM
+      && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+    ia64_encode_addr_area (decl, XEXP (rtl, 0));
 }
 \f
 /* Return 1 if the operands of a move are ok.  */
 
 int
-ia64_move_ok (dst, src)
-     rtx dst, src;
+ia64_move_ok (rtx dst, rtx src)
 {
   /* If we're under init_recog_no_volatile, we'll not be able to use
      memory_operand.  So check the code directly and don't worry about
@@ -1064,17 +568,9 @@ ia64_move_ok (dst, src)
     return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
 }
 
-/* Return 0 if we are doing C++ code.  This optimization fails with
-   C++ because of GNAT c++/6685.  */
-
 int
-addp4_optimize_ok (op1, op2)
-     rtx op1, op2;
+addp4_optimize_ok (rtx op1, rtx op2)
 {
-
-  if (!strcmp (lang_hooks.name, "GNU C++"))
-    return 0;
-
   return (basereg_operand (op1, GET_MODE(op1)) !=
          basereg_operand (op2, GET_MODE(op2)));
 }
@@ -1083,8 +579,7 @@ addp4_optimize_ok (op1, op2)
    Return the length of the field, or <= 0 on failure.  */
 
 int
-ia64_depz_field_mask (rop, rshift)
-     rtx rop, rshift;
+ia64_depz_field_mask (rtx rop, rtx rshift)
 {
   unsigned HOST_WIDE_INT op = INTVAL (rop);
   unsigned HOST_WIDE_INT shift = INTVAL (rshift);
@@ -1099,10 +594,9 @@ ia64_depz_field_mask (rop, rshift)
 /* Expand a symbolic constant load.  */
 
 void
-ia64_expand_load_address (dest, src)
-      rtx dest, src;
+ia64_expand_load_address (rtx dest, rtx src)
 {
-  if (tls_symbolic_operand (src, VOIDmode))
+  if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (src))
     abort ();
   if (GET_CODE (dest) != REG)
     abort ();
@@ -1114,7 +608,12 @@ ia64_expand_load_address (dest, src)
   if (GET_MODE (dest) != Pmode)
     dest = gen_rtx_REG (Pmode, REGNO (dest));
 
-  if (TARGET_AUTO_PIC)
+  if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (src))
+    {
+      emit_insn (gen_rtx_SET (VOIDmode, dest, src));
+      return;
+    }
+  else if (TARGET_AUTO_PIC)
     {
       emit_insn (gen_load_gprel64 (dest, src));
       return;
@@ -1133,7 +632,7 @@ ia64_expand_load_address (dest, src)
   if (GET_CODE (src) == CONST
       && GET_CODE (XEXP (src, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
-      && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
+      && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x3fff) != 0)
     {
       rtx sym = XEXP (XEXP (src, 0), 0);
       HOST_WIDE_INT ofs, hi, lo;
@@ -1162,7 +661,7 @@ ia64_expand_load_address (dest, src)
 
 static GTY(()) rtx gen_tls_tga;
 static rtx
-gen_tls_get_addr ()
+gen_tls_get_addr (void)
 {
   if (!gen_tls_tga)
     gen_tls_tga = init_one_libfunc ("__tls_get_addr");
@@ -1171,22 +670,18 @@ gen_tls_get_addr ()
 
 static GTY(()) rtx thread_pointer_rtx;
 static rtx
-gen_thread_pointer ()
+gen_thread_pointer (void)
 {
   if (!thread_pointer_rtx)
-    {
-      thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
-      RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
-    }
+    thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
   return thread_pointer_rtx;
 }
 
 static rtx
-ia64_expand_tls_address (tls_kind, op0, op1)
-     enum tls_model tls_kind;
-     rtx op0, op1;
+ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
 {
   rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
+  rtx orig_op0 = op0;
 
   switch (tls_kind)
     {
@@ -1195,14 +690,12 @@ ia64_expand_tls_address (tls_kind, op0, op1)
 
       tga_op1 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
-      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
-      RTX_UNCHANGING_P (tga_op1) = 1;
+      tga_op1 = gen_const_mem (Pmode, tga_op1);
 
       tga_op2 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
-      tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
-      RTX_UNCHANGING_P (tga_op2) = 1;
-             
+      tga_op2 = gen_const_mem (Pmode, tga_op2);
+
       tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
                                         LCT_CONST, Pmode, 2, tga_op1,
                                         Pmode, tga_op2, Pmode);
@@ -1210,8 +703,10 @@ ia64_expand_tls_address (tls_kind, op0, op1)
       insns = get_insns ();
       end_sequence ();
 
+      if (GET_MODE (op0) != Pmode)
+       op0 = tga_ret;
       emit_libcall_block (insns, op0, tga_ret, op1);
-      return NULL_RTX;
+      break;
 
     case TLS_MODEL_LOCAL_DYNAMIC:
       /* ??? This isn't the completely proper way to do local-dynamic
@@ -1222,8 +717,7 @@ ia64_expand_tls_address (tls_kind, op0, op1)
 
       tga_op1 = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
-      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
-      RTX_UNCHANGING_P (tga_op1) = 1;
+      tga_op1 = gen_const_mem (Pmode, tga_op1);
 
       tga_op2 = const0_rtx;
 
@@ -1239,58 +733,53 @@ ia64_expand_tls_address (tls_kind, op0, op1)
       tmp = gen_reg_rtx (Pmode);
       emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
 
-      if (register_operand (op0, Pmode))
-       tga_ret = op0;
-      else
-       tga_ret = gen_reg_rtx (Pmode);
+      if (!register_operand (op0, Pmode))
+       op0 = gen_reg_rtx (Pmode);
       if (TARGET_TLS64)
        {
-         emit_insn (gen_load_dtprel (tga_ret, op1));
-         emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
+         emit_insn (gen_load_dtprel (op0, op1));
+         emit_insn (gen_adddi3 (op0, tmp, op0));
        }
       else
-       emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
-
-      return (tga_ret == op0 ? NULL_RTX : tga_ret);
+       emit_insn (gen_add_dtprel (op0, tmp, op1));
+      break;
 
     case TLS_MODEL_INITIAL_EXEC:
       tmp = gen_reg_rtx (Pmode);
       emit_insn (gen_load_ltoff_tprel (tmp, op1));
-      tmp = gen_rtx_MEM (Pmode, tmp);
-      RTX_UNCHANGING_P (tmp) = 1;
+      tmp = gen_const_mem (Pmode, tmp);
       tmp = force_reg (Pmode, tmp);
 
-      if (register_operand (op0, Pmode))
-       op1 = op0;
-      else
-       op1 = gen_reg_rtx (Pmode);
-      emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
-
-      return (op1 == op0 ? NULL_RTX : op1);
+      if (!register_operand (op0, Pmode))
+       op0 = gen_reg_rtx (Pmode);
+      emit_insn (gen_adddi3 (op0, tmp, gen_thread_pointer ()));
+      break;
 
     case TLS_MODEL_LOCAL_EXEC:
-      if (register_operand (op0, Pmode))
-       tmp = op0;
-      else
-       tmp = gen_reg_rtx (Pmode);
+      if (!register_operand (op0, Pmode))
+       op0 = gen_reg_rtx (Pmode);
       if (TARGET_TLS64)
        {
-         emit_insn (gen_load_tprel (tmp, op1));
-         emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
+         emit_insn (gen_load_tprel (op0, op1));
+         emit_insn (gen_adddi3 (op0, gen_thread_pointer (), op0));
        }
       else
-       emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
-
-      return (tmp == op0 ? NULL_RTX : tmp);
+       emit_insn (gen_add_tprel (op0, gen_thread_pointer (), op1));
+      break;
 
     default:
       abort ();
     }
+
+  if (orig_op0 == op0)
+    return NULL_RTX;
+  if (GET_MODE (orig_op0) == Pmode)
+    return op0;
+  return gen_lowpart (GET_MODE (orig_op0), op0);
 }
 
 rtx
-ia64_expand_move (op0, op1)
-     rtx op0, op1;
+ia64_expand_move (rtx op0, rtx op1)
 {
   enum machine_mode mode = GET_MODE (op0);
 
@@ -1300,7 +789,8 @@ ia64_expand_move (op0, op1)
   if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
     {
       enum tls_model tls_kind;
-      if ((tls_kind = tls_symbolic_operand (op1, VOIDmode)))
+      if (GET_CODE (op1) == SYMBOL_REF
+         && (tls_kind = SYMBOL_REF_TLS_MODEL (op1)))
        return ia64_expand_tls_address (tls_kind, op0, op1);
 
       if (!TARGET_NO_PIC && reload_completed)
@@ -1316,8 +806,7 @@ ia64_expand_move (op0, op1)
 /* Split a move from OP1 to OP0 conditional on COND.  */
 
 void
-ia64_emit_cond_move (op0, op1, cond)
-     rtx op0, op1, cond;
+ia64_emit_cond_move (rtx op0, rtx op1, rtx cond)
 {
   rtx insn, first = get_last_insn ();
 
@@ -1329,102 +818,256 @@ ia64_emit_cond_move (op0, op1, cond)
                                          PATTERN (insn));
 }
 
-/* Split a post-reload TImode reference into two DImode components.  */
+/* Split a post-reload TImode or TFmode reference into two DImode
+   components.  This is made extra difficult by the fact that we do
+   not get any scratch registers to work with, because reload cannot
+   be prevented from giving us a scratch that overlaps the register
+   pair involved.  So instead, when addressing memory, we tweak the
+   pointer register up and back down with POST_INCs.  Or up and not
+   back down when we can get away with it.
 
-rtx
-ia64_split_timode (out, in, scratch)
-     rtx out[2];
-     rtx in, scratch;
+   REVERSED is true when the loads must be done in reversed order
+   (high word first) for correctness.  DEAD is true when the pointer
+   dies with the second insn we generate and therefore the second
+   address must not carry a postmodify.
+
+   May return an insn which is to be emitted after the moves.  */
+
+static rtx
+ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
 {
+  rtx fixup = 0;
+
   switch (GET_CODE (in))
     {
     case REG:
-      out[0] = gen_rtx_REG (DImode, REGNO (in));
-      out[1] = gen_rtx_REG (DImode, REGNO (in) + 1);
-      return NULL_RTX;
+      out[reversed] = gen_rtx_REG (DImode, REGNO (in));
+      out[!reversed] = gen_rtx_REG (DImode, REGNO (in) + 1);
+      break;
+
+    case CONST_INT:
+    case CONST_DOUBLE:
+      /* Cannot occur reversed.  */
+      if (reversed) abort ();
+      
+      if (GET_MODE (in) != TFmode)
+       split_double (in, &out[0], &out[1]);
+      else
+       /* split_double does not understand how to split a TFmode
+          quantity into a pair of DImode constants.  */
+       {
+         REAL_VALUE_TYPE r;
+         unsigned HOST_WIDE_INT p[2];
+         long l[4];  /* TFmode is 128 bits */
+
+         REAL_VALUE_FROM_CONST_DOUBLE (r, in);
+         real_to_target (l, &r, TFmode);
+
+         if (FLOAT_WORDS_BIG_ENDIAN)
+           {
+             p[0] = (((unsigned HOST_WIDE_INT) l[0]) << 32) + l[1];
+             p[1] = (((unsigned HOST_WIDE_INT) l[2]) << 32) + l[3];
+           }
+         else
+           {
+             p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];
+             p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];
+           }
+         out[0] = GEN_INT (p[0]);
+         out[1] = GEN_INT (p[1]);
+       }
+      break;
 
     case MEM:
       {
        rtx base = XEXP (in, 0);
+       rtx offset;
 
        switch (GET_CODE (base))
          {
          case REG:
-           out[0] = adjust_address (in, DImode, 0);
-           break;
-         case POST_MODIFY:
-           base = XEXP (base, 0);
-           out[0] = adjust_address (in, DImode, 0);
+           if (!reversed)
+             {
+               out[0] = adjust_automodify_address
+                 (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
+               out[1] = adjust_automodify_address
+                 (in, DImode, dead ? 0 : gen_rtx_POST_DEC (Pmode, base), 8);
+             }
+           else
+             {
+               /* Reversal requires a pre-increment, which can only
+                  be done as a separate insn.  */
+               emit_insn (gen_adddi3 (base, base, GEN_INT (8)));
+               out[0] = adjust_automodify_address
+                 (in, DImode, gen_rtx_POST_DEC (Pmode, base), 8);
+               out[1] = adjust_address (in, DImode, 0);
+             }
            break;
 
-         /* Since we're changing the mode, we need to change to POST_MODIFY
-            as well to preserve the size of the increment.  Either that or
-            do the update in two steps, but we've already got this scratch
-            register handy so let's use it.  */
          case POST_INC:
-           base = XEXP (base, 0);
-           out[0]
-             = change_address (in, DImode,
-                               gen_rtx_POST_MODIFY
-                               (Pmode, base, plus_constant (base, 16)));
+           if (reversed || dead) abort ();
+           /* Just do the increment in two steps.  */
+           out[0] = adjust_automodify_address (in, DImode, 0, 0);
+           out[1] = adjust_automodify_address (in, DImode, 0, 8);
            break;
+
          case POST_DEC:
+           if (reversed || dead) abort ();
+           /* Add 8, subtract 24.  */
            base = XEXP (base, 0);
-           out[0]
-             = change_address (in, DImode,
-                               gen_rtx_POST_MODIFY
-                               (Pmode, base, plus_constant (base, -16)));
+           out[0] = adjust_automodify_address
+             (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
+           out[1] = adjust_automodify_address
+             (in, DImode,
+              gen_rtx_POST_MODIFY (Pmode, base, plus_constant (base, -24)),
+              8);
+           break;
+
+         case POST_MODIFY:
+           if (reversed || dead) abort ();
+           /* Extract and adjust the modification.  This case is
+              trickier than the others, because we might have an
+              index register, or we might have a combined offset that
+              doesn't fit a signed 9-bit displacement field.  We can
+              assume the incoming expression is already legitimate.  */
+           offset = XEXP (base, 1);
+           base = XEXP (base, 0);
+
+           out[0] = adjust_automodify_address
+             (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
+
+           if (GET_CODE (XEXP (offset, 1)) == REG)
+             {
+               /* Can't adjust the postmodify to match.  Emit the
+                  original, then a separate addition insn.  */
+               out[1] = adjust_automodify_address (in, DImode, 0, 8);
+               fixup = gen_adddi3 (base, base, GEN_INT (-8));
+             }
+           else if (GET_CODE (XEXP (offset, 1)) != CONST_INT)
+             abort ();
+           else if (INTVAL (XEXP (offset, 1)) < -256 + 8)
+             {
+               /* Again the postmodify cannot be made to match, but
+                  in this case it's more efficient to get rid of the
+                  postmodify entirely and fix up with an add insn.  */
+               out[1] = adjust_automodify_address (in, DImode, base, 8);
+               fixup = gen_adddi3 (base, base,
+                                   GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
+             }
+           else
+             {
+               /* Combined offset still fits in the displacement field.
+                  (We cannot overflow it at the high end.)  */
+               out[1] = adjust_automodify_address
+                 (in, DImode,
+                  gen_rtx_POST_MODIFY (Pmode, base,
+                    gen_rtx_PLUS (Pmode, base,
+                                  GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
+                  8);
+             }
            break;
+
          default:
            abort ();
          }
-
-       if (scratch == NULL_RTX)
-         abort ();
-       out[1] = change_address (in, DImode, scratch);
-       return gen_adddi3 (scratch, base, GEN_INT (8));
+       break;
       }
 
-    case CONST_INT:
-    case CONST_DOUBLE:
-      split_double (in, &out[0], &out[1]);
-      return NULL_RTX;
-
     default:
       abort ();
     }
+
+  return fixup;
 }
 
-/* ??? Fixing GR->FR TFmode moves during reload is hard.  You need to go
+/* Split a TImode or TFmode move instruction after reload.
+   This is used by *movtf_internal and *movti_internal.  */
+void
+ia64_split_tmode_move (rtx operands[])
+{
+  rtx in[2], out[2], insn;
+  rtx fixup[2];
+  bool dead = false;
+  bool reversed = false;
+
+  /* It is possible for reload to decide to overwrite a pointer with
+     the value it points to.  In that case we have to do the loads in
+     the appropriate order so that the pointer is not destroyed too
+     early.  Also we must not generate a postmodify for that second
+     load, or rws_access_regno will abort.  */
+  if (GET_CODE (operands[1]) == MEM
+      && reg_overlap_mentioned_p (operands[0], operands[1]))
+    {
+      rtx base = XEXP (operands[1], 0);
+      while (GET_CODE (base) != REG)
+       base = XEXP (base, 0);
+
+      if (REGNO (base) == REGNO (operands[0]))
+       reversed = true;
+      dead = true;
+    }
+  /* Another reason to do the moves in reversed order is if the first
+     element of the target register pair is also the second element of
+     the source register pair.  */
+  if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
+      && REGNO (operands[0]) == REGNO (operands[1]) + 1)
+    reversed = true;
+
+  fixup[0] = ia64_split_tmode (in, operands[1], reversed, dead);
+  fixup[1] = ia64_split_tmode (out, operands[0], reversed, dead);
+
+#define MAYBE_ADD_REG_INC_NOTE(INSN, EXP)                              \
+  if (GET_CODE (EXP) == MEM                                            \
+      && (GET_CODE (XEXP (EXP, 0)) == POST_MODIFY                      \
+         || GET_CODE (XEXP (EXP, 0)) == POST_INC                       \
+         || GET_CODE (XEXP (EXP, 0)) == POST_DEC))                     \
+    REG_NOTES (INSN) = gen_rtx_EXPR_LIST (REG_INC,                     \
+                                         XEXP (XEXP (EXP, 0), 0),      \
+                                         REG_NOTES (INSN))
+
+  insn = emit_insn (gen_rtx_SET (VOIDmode, out[0], in[0]));
+  MAYBE_ADD_REG_INC_NOTE (insn, in[0]);
+  MAYBE_ADD_REG_INC_NOTE (insn, out[0]);
+
+  insn = emit_insn (gen_rtx_SET (VOIDmode, out[1], in[1]));
+  MAYBE_ADD_REG_INC_NOTE (insn, in[1]);
+  MAYBE_ADD_REG_INC_NOTE (insn, out[1]);
+
+  if (fixup[0])
+    emit_insn (fixup[0]);
+  if (fixup[1])
+    emit_insn (fixup[1]);
+
+#undef MAYBE_ADD_REG_INC_NOTE
+}
+
+/* ??? Fixing GR->FR XFmode moves during reload is hard.  You need to go
    through memory plus an extra GR scratch register.  Except that you can
    either get the first from SECONDARY_MEMORY_NEEDED or the second from
    SECONDARY_RELOAD_CLASS, but not both.
 
    We got into problems in the first place by allowing a construct like
-   (subreg:TF (reg:TI)), which we got from a union containing a long double.  
+   (subreg:XF (reg:TI)), which we got from a union containing a long double.
    This solution attempts to prevent this situation from occurring.  When
    we see something like the above, we spill the inner register to memory.  */
 
 rtx
-spill_tfmode_operand (in, force)
-     rtx in;
-     int force;
+spill_xfmode_operand (rtx in, int force)
 {
   if (GET_CODE (in) == SUBREG
       && GET_MODE (SUBREG_REG (in)) == TImode
       && GET_CODE (SUBREG_REG (in)) == REG)
     {
-      rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, /*rescan=*/true);
-      return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
+      rtx memt = assign_stack_temp (TImode, 16, 0);
+      emit_move_insn (memt, SUBREG_REG (in));
+      return adjust_address (memt, XFmode, 0);
     }
   else if (force && GET_CODE (in) == REG)
     {
-      rtx mem = gen_mem_addressof (in, NULL_TREE, /*rescan=*/true);
-      return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
+      rtx memx = assign_stack_temp (XFmode, 16, 0);
+      emit_move_insn (memx, in);
+      return memx;
     }
-  else if (GET_CODE (in) == MEM
-          && GET_CODE (XEXP (in, 0)) == ADDRESSOF)
-    return change_address (in, TFmode, copy_to_reg (XEXP (in, 0)));
   else
     return in;
 }
@@ -1432,10 +1075,10 @@ spill_tfmode_operand (in, force)
 /* Emit comparison instruction if necessary, returning the expression
    that holds the compare result in the proper mode.  */
 
+static GTY(()) rtx cmptf_libfunc;
+
 rtx
-ia64_expand_compare (code, mode)
-     enum rtx_code code;
-     enum machine_mode mode;
+ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
 {
   rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;
   rtx cmp;
@@ -1449,6 +1092,60 @@ ia64_expand_compare (code, mode)
       else
        abort ();
     }
+  /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
+     magic number as its third argument, that indicates what to do.
+     The return value is an integer to be compared against zero.  */
+  else if (GET_MODE (op0) == TFmode)
+    {
+      enum qfcmp_magic {
+       QCMP_INV = 1,   /* Raise FP_INVALID on SNaN as a side effect.  */
+       QCMP_UNORD = 2,
+       QCMP_EQ = 4,
+       QCMP_LT = 8,
+       QCMP_GT = 16
+      } magic;
+      enum rtx_code ncode;
+      rtx ret, insns;
+      if (!cmptf_libfunc || GET_MODE (op1) != TFmode)
+       abort ();
+      switch (code)
+       {
+         /* 1 = equal, 0 = not equal.  Equality operators do
+            not raise FP_INVALID when given an SNaN operand.  */
+       case EQ:        magic = QCMP_EQ;                  ncode = NE; break;
+       case NE:        magic = QCMP_EQ;                  ncode = EQ; break;
+         /* isunordered() from C99.  */
+       case UNORDERED: magic = QCMP_UNORD;               ncode = NE; break;
+       case ORDERED:   magic = QCMP_UNORD;               ncode = EQ; break;
+         /* Relational operators raise FP_INVALID when given
+            an SNaN operand.  */
+       case LT:        magic = QCMP_LT        |QCMP_INV; ncode = NE; break;
+       case LE:        magic = QCMP_LT|QCMP_EQ|QCMP_INV; ncode = NE; break;
+       case GT:        magic = QCMP_GT        |QCMP_INV; ncode = NE; break;
+       case GE:        magic = QCMP_GT|QCMP_EQ|QCMP_INV; ncode = NE; break;
+         /* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT.
+            Expanders for buneq etc. weuld have to be added to ia64.md
+            for this to be useful.  */
+       default: abort ();
+       }
+
+      start_sequence ();
+
+      ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3,
+                                    op0, TFmode, op1, TFmode,
+                                    GEN_INT (magic), DImode);
+      cmp = gen_reg_rtx (BImode);
+      emit_insn (gen_rtx_SET (VOIDmode, cmp,
+                             gen_rtx_fmt_ee (ncode, BImode,
+                                             ret, const0_rtx)));
+
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_libcall_block (insns, cmp, cmp,
+                         gen_rtx_fmt_ee (code, BImode, op0, op1));
+      code = NE;
+    }
   else
     {
       cmp = gen_reg_rtx (BImode);
@@ -1463,15 +1160,13 @@ ia64_expand_compare (code, mode)
 /* Emit the appropriate sequence for a call.  */
 
 void
-ia64_expand_call (retval, addr, nextarg, sibcall_p)
-     rtx retval;
-     rtx addr;
-     rtx nextarg ATTRIBUTE_UNUSED;
-     int sibcall_p;
+ia64_expand_call (rtx retval, rtx addr, rtx nextarg ATTRIBUTE_UNUSED,
+                 int sibcall_p)
 {
   rtx insn, b0;
 
   addr = XEXP (addr, 0);
+  addr = convert_memory_address (DImode, addr);
   b0 = gen_rtx_REG (DImode, R_BR (0));
 
   /* ??? Should do this for functions known to bind local too.  */
@@ -1503,7 +1198,7 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
 }
 
 void
-ia64_reload_gp ()
+ia64_reload_gp (void)
 {
   rtx tmp;
 
@@ -1543,10 +1238,8 @@ ia64_reload_gp ()
 }
 
 void
-ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
-                noreturn_p, sibcall_p)
-     rtx retval, addr, retaddr, scratch_r, scratch_b;
-     int noreturn_p, sibcall_p;
+ia64_split_call (rtx retval, rtx addr, rtx retaddr, rtx scratch_r,
+                rtx scratch_b, int noreturn_p, int sibcall_p)
 {
   rtx insn;
   bool is_desc = false;
@@ -1559,8 +1252,8 @@ ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
       bool addr_dead_p;
 
       /* ??? We are currently constrained to *not* use peep2, because
-        we can legitimiately change the global lifetime of the GP
-        (in the form of killing where previously live).  This is 
+        we can legitimately change the global lifetime of the GP
+        (in the form of killing where previously live).  This is
         because a call through a descriptor doesn't use the previous
         value of the GP, while a direct call does, and we do not
         commit to either form until the split here.
@@ -1609,14 +1302,14 @@ ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
 /* Begin the assembly file.  */
 
 static void
-ia64_file_start ()
+ia64_file_start (void)
 {
   default_file_start ();
   emit_safe_across_calls ();
 }
 
 void
-emit_safe_across_calls ()
+emit_safe_across_calls (void)
 {
   unsigned int rs, re;
   int out_state;
@@ -1654,8 +1347,7 @@ emit_safe_across_calls ()
    TRY_LOCALS is true if we should attempt to locate a local regnum.  */
 
 static int
-find_gr_spill (try_locals)
-     int try_locals;
+find_gr_spill (int try_locals)
 {
   int regno;
 
@@ -1704,7 +1396,7 @@ find_gr_spill (try_locals)
 static int last_scratch_gr_reg;
 
 static int
-next_scratch_gr_reg ()
+next_scratch_gr_reg (void)
 {
   int i, regno;
 
@@ -1729,9 +1421,7 @@ next_scratch_gr_reg ()
    diddle_return_value.  Mark REG in current_frame_info.gr_used_mask.  */
 
 static void
-mark_reg_gr_used_mask (reg, data)
-     rtx reg;
-     void *data ATTRIBUTE_UNUSED;
+mark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int regno = REGNO (reg);
   if (regno < 32)
@@ -1747,8 +1437,7 @@ mark_reg_gr_used_mask (reg, data)
    needed for local variables.  */
 
 static void
-ia64_compute_frame_size (size)
-     HOST_WIDE_INT size;
+ia64_compute_frame_size (HOST_WIDE_INT size)
 {
   HOST_WIDE_INT total_size;
   HOST_WIDE_INT spill_size = 0;
@@ -1821,7 +1510,7 @@ ia64_compute_frame_size (size)
   current_frame_info.n_rotate_regs = 0;
 
   /* Discover which registers need spilling, and how much room that
-     will take.  Begin with floating point and general registers, 
+     will take.  Begin with floating point and general registers,
      which will always wind up on the stack.  */
 
   for (regno = FR_REG (2); regno <= FR_REG (127); regno++)
@@ -1852,7 +1541,7 @@ ia64_compute_frame_size (size)
 
   /* Now come all special registers that might get saved in other
      general registers.  */
-  
+
   if (frame_pointer_needed)
     {
       current_frame_info.reg_fp = find_gr_spill (1);
@@ -2014,8 +1703,7 @@ ia64_compute_frame_size (size)
 /* Compute the initial difference between the specified pair of registers.  */
 
 HOST_WIDE_INT
-ia64_initial_elimination_offset (from, to)
-     int from, to;
+ia64_initial_elimination_offset (int from, int to)
 {
   HOST_WIDE_INT offset;
 
@@ -2054,10 +1742,6 @@ ia64_initial_elimination_offset (from, to)
        abort ();
       break;
 
-    case RETURN_ADDRESS_POINTER_REGNUM:
-      offset = 0;
-      break;
-
     default:
       abort ();
     }
@@ -2091,10 +1775,7 @@ struct spill_fill_data
 static struct spill_fill_data spill_fill_data;
 
 static void
-setup_spill_pointers (n_spills, init_reg, cfa_off)
-     int n_spills;
-     rtx init_reg;
-     HOST_WIDE_INT cfa_off;
+setup_spill_pointers (int n_spills, rtx init_reg, HOST_WIDE_INT cfa_off)
 {
   int i;
 
@@ -2120,15 +1801,13 @@ setup_spill_pointers (n_spills, init_reg, cfa_off)
 }
 
 static void
-finish_spill_pointers ()
+finish_spill_pointers (void)
 {
   current_frame_info.gr_used_mask = spill_fill_data.save_gr_used_mask;
 }
 
 static rtx
-spill_restore_mem (reg, cfa_off)
-     rtx reg;
-     HOST_WIDE_INT cfa_off;
+spill_restore_mem (rtx reg, HOST_WIDE_INT cfa_off)
 {
   int iter = spill_fill_data.next_iter;
   HOST_WIDE_INT disp = spill_fill_data.prev_off[iter] - cfa_off;
@@ -2241,10 +1920,8 @@ spill_restore_mem (reg, cfa_off)
 }
 
 static void
-do_spill (move_fn, reg, cfa_off, frame_reg)
-     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
-     rtx reg, frame_reg;
-     HOST_WIDE_INT cfa_off;
+do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off,
+         rtx frame_reg)
 {
   int iter = spill_fill_data.next_iter;
   rtx mem, insn;
@@ -2260,7 +1937,7 @@ do_spill (move_fn, reg, cfa_off, frame_reg)
 
       RTX_FRAME_RELATED_P (insn) = 1;
 
-      /* Don't even pretend that the unwind code can intuit its way 
+      /* Don't even pretend that the unwind code can intuit its way
         through a pair of interleaved post_modify iterators.  Just
         provide the correct answer.  */
 
@@ -2286,10 +1963,7 @@ do_spill (move_fn, reg, cfa_off, frame_reg)
 }
 
 static void
-do_restore (move_fn, reg, cfa_off)
-     rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
-     rtx reg;
-     HOST_WIDE_INT cfa_off;
+do_restore (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off)
 {
   int iter = spill_fill_data.next_iter;
   rtx insn;
@@ -2304,25 +1978,19 @@ do_restore (move_fn, reg, cfa_off)
    use a consistent function interface.  */
 
 static rtx
-gen_movdi_x (dest, src, offset)
-     rtx dest, src;
-     rtx offset ATTRIBUTE_UNUSED;
+gen_movdi_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
 {
   return gen_movdi (dest, src);
 }
 
 static rtx
-gen_fr_spill_x (dest, src, offset)
-     rtx dest, src;
-     rtx offset ATTRIBUTE_UNUSED;
+gen_fr_spill_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
 {
   return gen_fr_spill (dest, src);
 }
 
 static rtx
-gen_fr_restore_x (dest, src, offset)
-     rtx dest, src;
-     rtx offset ATTRIBUTE_UNUSED;
+gen_fr_restore_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
 {
   return gen_fr_restore (dest, src);
 }
@@ -2350,7 +2018,7 @@ gen_fr_restore_x (dest, src, offset)
    adds instruction.  */
 
 void
-ia64_expand_prologue ()
+ia64_expand_prologue (void)
 {
   rtx insn, ar_pfs_save_reg, ar_unat_save_reg;
   int i, epilogue_p, regno, alt_regno, cfa_off, n_varargs;
@@ -2408,17 +2076,6 @@ ia64_expand_prologue ()
       reg_names[current_frame_info.reg_fp] = tmp;
     }
 
-  /* Fix up the return address placeholder.  */
-  /* ??? We can fail if __builtin_return_address is used, and we didn't
-     allocate a register in which to save b0.  I can't think of a way to
-     eliminate RETURN_ADDRESS_POINTER_REGNUM to a local register and
-     then be sure that I got the right one.  Further, reload doesn't seem
-     to care if an eliminable register isn't used, and "eliminates" it
-     anyway.  */
-  if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM]
-      && current_frame_info.reg_save_b0 != 0)
-    XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0;
-
   /* We don't need an alloc instruction if we've used no outputs or locals.  */
   if (current_frame_info.n_local_regs == 0
       && current_frame_info.n_output_regs == 0
@@ -2440,7 +2097,7 @@ ia64_expand_prologue ()
        regno = next_scratch_gr_reg ();
       ar_pfs_save_reg = gen_rtx_REG (DImode, regno);
 
-      insn = emit_insn (gen_alloc (ar_pfs_save_reg, 
+      insn = emit_insn (gen_alloc (ar_pfs_save_reg,
                                   GEN_INT (current_frame_info.n_input_regs),
                                   GEN_INT (current_frame_info.n_local_regs),
                                   GEN_INT (current_frame_info.n_output_regs),
@@ -2470,7 +2127,7 @@ ia64_expand_prologue ()
       else
        {
          regno = next_scratch_gr_reg ();
-         offset = gen_rtx_REG (DImode, regno);
+         offset = gen_rtx_REG (DImode, regno);
          emit_move_insn (offset, frame_size_rtx);
        }
 
@@ -2688,7 +2345,7 @@ ia64_expand_prologue ()
       {
         if (cfa_off & 15)
          abort ();
-       reg = gen_rtx_REG (TFmode, regno);
+       reg = gen_rtx_REG (XFmode, regno);
        do_spill (gen_fr_spill_x, reg, cfa_off, reg);
        cfa_off -= 16;
       }
@@ -2707,8 +2364,7 @@ ia64_expand_prologue ()
    insn to prevent such scheduling.  */
 
 void
-ia64_expand_epilogue (sibcall_p)
-     int sibcall_p;
+ia64_expand_epilogue (int sibcall_p)
 {
   rtx insn, reg, alt_reg, ar_unat_save_reg;
   int regno, alt_regno, cfa_off;
@@ -2722,7 +2378,7 @@ ia64_expand_epilogue (sibcall_p)
     setup_spill_pointers (current_frame_info.n_spilled,
                          hard_frame_pointer_rtx, 0);
   else
-    setup_spill_pointers (current_frame_info.n_spilled, stack_pointer_rtx, 
+    setup_spill_pointers (current_frame_info.n_spilled, stack_pointer_rtx,
                          current_frame_info.total_size);
 
   if (current_frame_info.total_size != 0)
@@ -2774,7 +2430,7 @@ ia64_expand_epilogue (sibcall_p)
     }
   else
     ar_unat_save_reg = NULL_RTX;
-      
+
   if (current_frame_info.reg_save_ar_pfs != 0)
     {
       alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_pfs);
@@ -2824,7 +2480,7 @@ ia64_expand_epilogue (sibcall_p)
        do_restore (gen_gr_restore, reg, cfa_off);
        cfa_off -= 8;
       }
-  
+
   /* Restore the branch registers.  Handle B0 specially, as it may
      have gotten stored in some GR register.  */
   if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
@@ -2841,7 +2497,7 @@ ia64_expand_epilogue (sibcall_p)
       reg = gen_rtx_REG (DImode, BR_REG (0));
       emit_move_insn (reg, alt_reg);
     }
-    
+
   for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
     if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
       {
@@ -2859,7 +2515,7 @@ ia64_expand_epilogue (sibcall_p)
       {
         if (cfa_off & 15)
          abort ();
-       reg = gen_rtx_REG (TFmode, regno);
+       reg = gen_rtx_REG (XFmode, regno);
        do_restore (gen_fr_restore_x, reg, cfa_off);
        cfa_off -= 16;
       }
@@ -2925,15 +2581,15 @@ ia64_expand_epilogue (sibcall_p)
 
   if (cfun->machine->ia64_eh_epilogue_bsp)
     emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
+
   if (! sibcall_p)
     emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
   else
     {
       int fp = GR_REG (2);
       /* We need a throw away register here, r0 and r1 are reserved, so r2 is the
-        first available call clobbered register.  If there was a frame_pointer 
-        register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM, 
+        first available call clobbered register.  If there was a frame_pointer
+        register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM,
         so we have to make sure we're using the string "r2" when emitting
         the register name for the assembler.  */
       if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2))
@@ -2948,37 +2604,98 @@ ia64_expand_epilogue (sibcall_p)
         It is unclear how to compute that number here.  */
       if (current_frame_info.n_input_regs != 0)
        emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
-                             GEN_INT (0), GEN_INT (0),
+                             const0_rtx, const0_rtx,
                              GEN_INT (current_frame_info.n_input_regs),
-                             GEN_INT (0)));
+                             const0_rtx));
     }
 }
 
 /* Return 1 if br.ret can do all the work required to return from a
    function.  */
 
-int
-ia64_direct_return ()
+int
+ia64_direct_return (void)
+{
+  if (reload_completed && ! frame_pointer_needed)
+    {
+      ia64_compute_frame_size (get_frame_size ());
+
+      return (current_frame_info.total_size == 0
+             && current_frame_info.n_spilled == 0
+             && current_frame_info.reg_save_b0 == 0
+             && current_frame_info.reg_save_pr == 0
+             && current_frame_info.reg_save_ar_pfs == 0
+             && current_frame_info.reg_save_ar_unat == 0
+             && current_frame_info.reg_save_ar_lc == 0);
+    }
+  return 0;
+}
+
+/* Return the magic cookie that we use to hold the return address
+   during early compilation.  */
+
+rtx
+ia64_return_addr_rtx (HOST_WIDE_INT count, rtx frame ATTRIBUTE_UNUSED)
+{
+  if (count != 0)
+    return NULL;
+  return gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_RET_ADDR);
+}
+
+/* Split this value after reload, now that we know where the return
+   address is saved.  */
+
+void
+ia64_split_return_addr_rtx (rtx dest)
 {
-  if (reload_completed && ! frame_pointer_needed)
+  rtx src;
+
+  if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
     {
-      ia64_compute_frame_size (get_frame_size ());
+      if (current_frame_info.reg_save_b0 != 0)
+       src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+      else
+       {
+         HOST_WIDE_INT off;
+         unsigned int regno;
+
+         /* Compute offset from CFA for BR0.  */
+         /* ??? Must be kept in sync with ia64_expand_prologue.  */
+         off = (current_frame_info.spill_cfa_off
+                + current_frame_info.spill_size);
+         for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+           if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
+             off -= 8;
+
+         /* Convert CFA offset to a register based offset.  */
+         if (frame_pointer_needed)
+           src = hard_frame_pointer_rtx;
+         else
+           {
+             src = stack_pointer_rtx;
+             off += current_frame_info.total_size;
+           }
 
-      return (current_frame_info.total_size == 0
-             && current_frame_info.n_spilled == 0
-             && current_frame_info.reg_save_b0 == 0
-             && current_frame_info.reg_save_pr == 0
-             && current_frame_info.reg_save_ar_pfs == 0
-             && current_frame_info.reg_save_ar_unat == 0
-             && current_frame_info.reg_save_ar_lc == 0);
+         /* Load address into scratch register.  */
+         if (CONST_OK_FOR_I (off))
+           emit_insn (gen_adddi3 (dest, src, GEN_INT (off)));
+         else
+           {
+             emit_move_insn (dest, GEN_INT (off));
+             emit_insn (gen_adddi3 (dest, src, dest));
+           }
+
+         src = gen_rtx_MEM (Pmode, dest);
+       }
     }
-  return 0;
+  else
+    src = gen_rtx_REG (DImode, BR_REG (0));
+
+  emit_move_insn (dest, src);
 }
 
 int
-ia64_hard_regno_rename_ok (from, to)
-     int from;
-     int to;
+ia64_hard_regno_rename_ok (int from, int to)
 {
   /* Don't clobber any of the registers we reserved for the prologue.  */
   if (to == current_frame_info.reg_fp
@@ -3012,18 +2729,15 @@ ia64_hard_regno_rename_ok (from, to)
    aligned objects and detect the cases when @fptr is needed.  */
 
 static bool
-ia64_assemble_integer (x, size, aligned_p)
-     rtx x;
-     unsigned int size;
-     int aligned_p;
+ia64_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
-  if (size == (TARGET_ILP32 ? 4 : 8)
+  if (size == POINTER_SIZE / BITS_PER_UNIT
       && aligned_p
       && !(TARGET_NO_PIC || TARGET_AUTO_PIC)
       && GET_CODE (x) == SYMBOL_REF
       && SYMBOL_REF_FUNCTION_P (x))
     {
-      if (TARGET_ILP32)
+      if (POINTER_SIZE == 32)
        fputs ("\tdata4\t@fptr(", asm_out_file);
       else
        fputs ("\tdata8\t@fptr(", asm_out_file);
@@ -3037,9 +2751,7 @@ ia64_assemble_integer (x, size, aligned_p)
 /* Emit the function prologue.  */
 
 static void
-ia64_output_function_prologue (file, size)
-     FILE *file;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+ia64_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   int mask, grsave, grsave_prev;
 
@@ -3089,7 +2801,7 @@ ia64_output_function_prologue (file, size)
        grsave = current_frame_info.reg_save_pr;
     }
 
-  if (mask)
+  if (mask && TARGET_GNU_AS)
     fprintf (file, "\t.prologue %d, %d\n", mask,
             ia64_dbx_register_number (grsave));
   else
@@ -3106,8 +2818,7 @@ ia64_output_function_prologue (file, size)
 /* Emit the .body directive at the scheduled end of the prologue.  */
 
 static void
-ia64_output_function_end_prologue (file)
-     FILE *file;
+ia64_output_function_end_prologue (FILE *file)
 {
   if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
     return;
@@ -3118,15 +2829,11 @@ ia64_output_function_end_prologue (file)
 /* Emit the function epilogue.  */
 
 static void
-ia64_output_function_epilogue (file, size)
-     FILE *file ATTRIBUTE_UNUSED;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+ia64_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
+                              HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {
   int i;
 
-  /* Reset from the function's potential modifications.  */
-  XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM;
-
   if (current_frame_info.reg_fp)
     {
       const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
@@ -3148,8 +2855,7 @@ ia64_output_function_epilogue (file, size)
 }
 
 int
-ia64_dbx_register_number (regno)
-     int regno;
+ia64_dbx_register_number (int regno)
 {
   /* In ia64_expand_prologue we quite literally renamed the frame pointer
      from its home at loc79 to something inside the register frame.  We
@@ -3174,11 +2880,29 @@ ia64_dbx_register_number (regno)
 }
 
 void
-ia64_initialize_trampoline (addr, fnaddr, static_chain)
-     rtx addr, fnaddr, static_chain;
+ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
 {
   rtx addr_reg, eight = GEN_INT (8);
 
+  /* The Intel assembler requires that the global __ia64_trampoline symbol
+     be declared explicitly */
+  if (!TARGET_GNU_AS)
+    {
+      static bool declared_ia64_trampoline = false;
+
+      if (!declared_ia64_trampoline)
+       {
+         declared_ia64_trampoline = true;
+         (*targetm.asm_out.globalize_label) (asm_out_file,
+                                             "__ia64_trampoline");
+       }
+    }
+
+  /* Make sure addresses are Pmode even if we are in ILP32 mode. */
+  addr = convert_memory_address (Pmode, addr);
+  fnaddr = convert_memory_address (Pmode, fnaddr);
+  static_chain = convert_memory_address (Pmode, static_chain);
+
   /* Load up our iterator.  */
   addr_reg = gen_reg_rtx (Pmode);
   emit_move_insn (addr_reg, addr);
@@ -3206,20 +2930,19 @@ ia64_initialize_trampoline (addr, fnaddr, static_chain)
 
    We generate the actual spill instructions during prologue generation.  */
 
-void
-ia64_setup_incoming_varargs (cum, int_mode, type, pretend_size, second_time)
-     CUMULATIVE_ARGS cum;
-     int             int_mode;
-     tree            type;
-     int *           pretend_size;
-     int            second_time ATTRIBUTE_UNUSED;
+static void
+ia64_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                            tree type, int * pretend_size,
+                            int second_time ATTRIBUTE_UNUSED)
 {
+  CUMULATIVE_ARGS next_cum = *cum;
+
   /* Skip the current argument.  */
-  ia64_function_arg_advance (&cum, int_mode, type, 1);
+  ia64_function_arg_advance (&next_cum, mode, type, 1);
 
-  if (cum.words < MAX_ARGUMENT_SLOTS)
+  if (next_cum.words < MAX_ARGUMENT_SLOTS)
     {
-      int n = MAX_ARGUMENT_SLOTS - cum.words;
+      int n = MAX_ARGUMENT_SLOTS - next_cum.words;
       *pretend_size = n * UNITS_PER_WORD;
       cfun->machine->n_varargs = n;
     }
@@ -3234,9 +2957,7 @@ ia64_setup_incoming_varargs (cum, int_mode, type, pretend_size, second_time)
    SFmode).  128-bit quad-precision floats are excluded.  */
 
 static enum machine_mode
-hfa_element_mode (type, nested)
-     tree type;
-     int nested;
+hfa_element_mode (tree type, int nested)
 {
   enum machine_mode element_mode = VOIDmode;
   enum machine_mode mode;
@@ -3258,16 +2979,15 @@ hfa_element_mode (type, nested)
         types though.  */
     case COMPLEX_TYPE:
       if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
-         && (TYPE_MODE (type) != TCmode || INTEL_EXTENDED_IEEE_FORMAT))
-       return mode_for_size (GET_MODE_UNIT_SIZE (TYPE_MODE (type))
-                             * BITS_PER_UNIT, MODE_FLOAT, 0);
+         && TYPE_MODE (type) != TCmode)
+       return GET_MODE_INNER (TYPE_MODE (type));
       else
        return VOIDmode;
 
     case REAL_TYPE:
       /* We want to return VOIDmode for raw REAL_TYPEs, but the actual
         mode if this is contained within an aggregate.  */
-      if (nested && (TYPE_MODE (type) != TFmode || INTEL_EXTENDED_IEEE_FORMAT))
+      if (nested && TYPE_MODE (type) != TFmode)
        return TYPE_MODE (type);
       else
        return VOIDmode;
@@ -3310,40 +3030,62 @@ hfa_element_mode (type, nested)
   return VOIDmode;
 }
 
+/* Return the number of words required to hold a quantity of TYPE and MODE
+   when passed as an argument.  */
+static int
+ia64_function_arg_words (tree type, enum machine_mode mode)
+{
+  int words;
+
+  if (mode == BLKmode)
+    words = int_size_in_bytes (type);
+  else
+    words = GET_MODE_SIZE (mode);
+
+  return (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  /* round up */
+}
+
+/* Return the number of registers that should be skipped so the current
+   argument (described by TYPE and WORDS) will be properly aligned.
+
+   Integer and float arguments larger than 8 bytes start at the next
+   even boundary.  Aggregates larger than 8 bytes start at the next
+   even boundary if the aggregate has 16 byte alignment.  Note that
+   in the 32-bit ABI, TImode and TFmode have only 8-byte alignment
+   but are still to be aligned in registers.
+
+   ??? The ABI does not specify how to handle aggregates with
+   alignment from 9 to 15 bytes, or greater than 16.  We handle them
+   all as if they had 16 byte alignment.  Such aggregates can occur
+   only if gcc extensions are used.  */
+static int
+ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
+{
+  if ((cum->words & 1) == 0)
+    return 0;
+
+  if (type
+      && TREE_CODE (type) != INTEGER_TYPE
+      && TREE_CODE (type) != REAL_TYPE)
+    return TYPE_ALIGN (type) > 8 * BITS_PER_UNIT;
+  else
+    return words > 1;
+}
+
 /* Return rtx for register where argument is passed, or zero if it is passed
    on the stack.  */
-
 /* ??? 128-bit quad-precision floats are always passed in general
    registers.  */
 
 rtx
-ia64_function_arg (cum, mode, type, named, incoming)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
-     int incoming;
+ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
+                  int named, int incoming)
 {
   int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
-  int words = (((mode == BLKmode ? int_size_in_bytes (type)
-                : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
-              / UNITS_PER_WORD);
-  int offset = 0;
+  int words = ia64_function_arg_words (type, mode);
+  int offset = ia64_function_arg_offset (cum, type, words);
   enum machine_mode hfa_mode = VOIDmode;
 
-  /* Integer and float arguments larger than 8 bytes start at the next even
-     boundary.  Aggregates larger than 8 bytes start at the next even boundary
-     if the aggregate has 16 byte alignment.  Net effect is that types with
-     alignment greater than 8 start at the next even boundary.  */
-  /* ??? The ABI does not specify how to handle aggregates with alignment from
-     9 to 15 bytes, or greater than 16.   We handle them all as if they had
-     16 byte alignment.  Such aggregates can occur only if gcc extensions are
-     used.  */
-  if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
-       : (words > 1))
-      && (cum->words & 1))
-    offset = 1;
-
   /* If all argument slots are used, then it must go on the stack.  */
   if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
     return 0;
@@ -3403,6 +3145,7 @@ ia64_function_arg (cum, mode, type, named, incoming)
       for (; offset < byte_size && int_regs < MAX_ARGUMENT_SLOTS; i++)
        {
          enum machine_mode gr_mode = DImode;
+         unsigned int gr_size;
 
          /* If we have an odd 4 byte hunk because we ran out of FR regs,
             then this goes in a GR reg left adjusted/little endian, right
@@ -3416,31 +3159,28 @@ ia64_function_arg (cum, mode, type, named, incoming)
             adjusted/little endian.  */
          else if (byte_size - offset == 4)
            gr_mode = SImode;
-         /* Complex floats need to have float mode.  */
-         if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
-           gr_mode = hfa_mode;
 
          loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
                                      gen_rtx_REG (gr_mode, (basereg
                                                             + int_regs)),
                                      GEN_INT (offset));
-         offset += GET_MODE_SIZE (gr_mode);
-         int_regs += GET_MODE_SIZE (gr_mode) <= UNITS_PER_WORD
-                     ? 1 : GET_MODE_SIZE (gr_mode) / UNITS_PER_WORD;
-       }
 
-      /* If we ended up using just one location, just return that one loc.  */
-      if (i == 1)
-       return XEXP (loc[0], 0);
-      else
-       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+         gr_size = GET_MODE_SIZE (gr_mode);
+         offset += gr_size;
+         if (gr_size == UNITS_PER_WORD
+             || (gr_size < UNITS_PER_WORD && offset % UNITS_PER_WORD == 0))
+           int_regs++;
+         else if (gr_size > UNITS_PER_WORD)
+           int_regs += gr_size / UNITS_PER_WORD;
+       }
+      return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
 
   /* Integral and aggregates go in general registers.  If we have run out of
      FR registers, then FP values must also go in general registers.  This can
      happen when we have a SFmode HFA.  */
-  else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
-          || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
+  else if (mode == TFmode || mode == TCmode
+          || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
     {
       int byte_size = ((mode == BLKmode)
                        ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
@@ -3465,21 +3205,34 @@ ia64_function_arg (cum, mode, type, named, incoming)
      named, and in a GR register when unnamed.  */
   else if (cum->prototype)
     {
-      if (! named)
-       return gen_rtx_REG (mode, basereg + cum->words + offset);
-      else
+      if (named)
        return gen_rtx_REG (mode, FR_ARG_FIRST + cum->fp_regs);
+      /* In big-endian mode, an anonymous SFmode value must be represented
+         as (parallel:SF [(expr_list (reg:DI n) (const_int 0))]) to force
+        the value into the high half of the general register.  */
+      else if (BYTES_BIG_ENDIAN && mode == SFmode)
+       return gen_rtx_PARALLEL (mode,
+                gen_rtvec (1,
+                   gen_rtx_EXPR_LIST (VOIDmode,
+                    gen_rtx_REG (DImode, basereg + cum->words + offset),
+                                     const0_rtx)));
+      else
+       return gen_rtx_REG (mode, basereg + cum->words + offset);
     }
   /* If there is no prototype, then FP values go in both FR and GR
      registers.  */
   else
     {
+      /* See comment above.  */
+      enum machine_mode inner_mode =
+       (BYTES_BIG_ENDIAN && mode == SFmode) ? DImode : mode;
+
       rtx fp_reg = gen_rtx_EXPR_LIST (VOIDmode,
                                      gen_rtx_REG (mode, (FR_ARG_FIRST
                                                          + cum->fp_regs)),
                                      const0_rtx);
       rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
-                                     gen_rtx_REG (mode,
+                                     gen_rtx_REG (inner_mode,
                                                   (basereg + cum->words
                                                    + offset)),
                                      const0_rtx);
@@ -3493,23 +3246,11 @@ ia64_function_arg (cum, mode, type, named, incoming)
    in memory.  */
 
 int
-ia64_function_arg_partial_nregs (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named ATTRIBUTE_UNUSED;
-{
-  int words = (((mode == BLKmode ? int_size_in_bytes (type)
-                : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
-              / UNITS_PER_WORD);
-  int offset = 0;
-
-  /* Arguments with alignment larger than 8 bytes start at the next even
-     boundary.  */
-  if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
-       : (words > 1))
-      && (cum->words & 1))
-    offset = 1;
+ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                                tree type, int named ATTRIBUTE_UNUSED)
+{
+  int words = ia64_function_arg_words (type, mode);
+  int offset = ia64_function_arg_offset (cum, type, words);
 
   /* If all argument slots are used, then it must go on the stack.  */
   if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
@@ -3530,29 +3271,17 @@ ia64_function_arg_partial_nregs (cum, mode, type, named)
    ia64_function_arg.  */
 
 void
-ia64_function_arg_advance (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
-{
-  int words = (((mode == BLKmode ? int_size_in_bytes (type)
-                : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
-              / UNITS_PER_WORD);
-  int offset = 0;
+ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                          tree type, int named)
+{
+  int words = ia64_function_arg_words (type, mode);
+  int offset = ia64_function_arg_offset (cum, type, words);
   enum machine_mode hfa_mode = VOIDmode;
 
   /* If all arg slots are already full, then there is nothing to do.  */
   if (cum->words >= MAX_ARGUMENT_SLOTS)
     return;
 
-  /* Arguments with alignment larger than 8 bytes start at the next even
-     boundary.  */
-  if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
-       : (words > 1))
-      && (cum->words & 1))
-    offset = 1;
-
   cum->words += words + offset;
 
   /* Check for and handle homogeneous FP aggregates.  */
@@ -3614,7 +3343,7 @@ ia64_function_arg_advance (cum, mode, type, named)
   /* If there is no prototype, then FP values go in both FR and GR
      registers.  */
   else
-    { 
+    {
       /* ??? Complex types should not reach here.  */
       cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
       cum->int_regs = cum->words;
@@ -3624,12 +3353,10 @@ ia64_function_arg_advance (cum, mode, type, named)
 /* Variable sized types are passed by reference.  */
 /* ??? At present this is a GCC extension to the IA-64 ABI.  */
 
-int
-ia64_function_arg_pass_by_reference (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     tree type;
-     int named ATTRIBUTE_UNUSED;
+static bool
+ia64_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+                       enum machine_mode mode ATTRIBUTE_UNUSED,
+                       tree type, bool named ATTRIBUTE_UNUSED)
 {
   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
 }
@@ -3638,58 +3365,56 @@ ia64_function_arg_pass_by_reference (cum, mode, type, named)
    call expression EXP.  DECL will be the called function, or NULL if
    this is an indirect call.  */
 static bool
-ia64_function_ok_for_sibcall (decl, exp)
-     tree decl;
-     tree exp ATTRIBUTE_UNUSED;
+ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
 {
-  /* Direct calls are always ok.  */
-  if (decl)
-    return true;
+  /* We can't perform a sibcall if the current function has the syscall_linkage
+     attribute.  */
+  if (lookup_attribute ("syscall_linkage",
+                       TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+    return false;
 
-  /* If TARGET_CONST_GP is in effect, then our caller expects us to
-     return with our current GP.  This means that we'll always have
-     a GP reload after an indirect call.  */
-  return !ia64_epilogue_uses (R_GR (1));
+  /* We must always return with our current GP.  This means we can
+     only sibcall to functions defined in the current module.  */
+  return decl && (*targetm.binds_local_p) (decl);
 }
 \f
 
 /* Implement va_arg.  */
 
-rtx
-ia64_va_arg (valist, type)
-     tree valist, type;
+static tree
+ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
 {
-  tree t;
-
   /* Variable sized types are passed by reference.  */
-  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+  if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
     {
-      rtx addr = std_expand_builtin_va_arg (valist, build_pointer_type (type));
-      return gen_rtx_MEM (ptr_mode, force_reg (Pmode, addr));
+      tree ptrtype = build_pointer_type (type);
+      tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
+      return build_va_arg_indirect_ref (addr);
     }
 
-  /* Arguments with alignment larger than 8 bytes start at the next even
-     boundary.  */
-  if (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
+  /* Aggregate arguments with alignment larger than 8 bytes start at
+     the next even boundary.  Integer and floating point arguments
+     do so if they are larger than 8 bytes, whether or not they are
+     also aligned larger than 8 bytes.  */
+  if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
+      ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
     {
-      t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
-                build_int_2 (2 * UNITS_PER_WORD - 1, 0));
+      tree t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
+                     build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
       t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
-                build_int_2 (-2 * UNITS_PER_WORD, -1));
+                build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
       t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+      gimplify_and_add (t, pre_p);
     }
 
-  return std_expand_builtin_va_arg (valist, type);
+  return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
 }
 \f
 /* Return 1 if function return value returned in memory.  Return 0 if it is
    in a register.  */
 
-int
-ia64_return_in_memory (valtype)
-     tree valtype;
+static bool
+ia64_return_in_memory (tree valtype, tree fntype ATTRIBUTE_UNUSED)
 {
   enum machine_mode mode;
   enum machine_mode hfa_mode;
@@ -3701,7 +3426,7 @@ ia64_return_in_memory (valtype)
     {
       byte_size = int_size_in_bytes (valtype);
       if (byte_size < 0)
-       return 1;
+       return true;
     }
 
   /* Hfa's with up to 8 elements are returned in the FP argument registers.  */
@@ -3712,22 +3437,20 @@ ia64_return_in_memory (valtype)
       int hfa_size = GET_MODE_SIZE (hfa_mode);
 
       if (byte_size / hfa_size > MAX_ARGUMENT_SLOTS)
-       return 1;
+       return true;
       else
-       return 0;
+       return false;
     }
   else if (byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS)
-    return 1;
+    return true;
   else
-    return 0;
+    return false;
 }
 
 /* Return rtx for register that holds the function return value.  */
 
 rtx
-ia64_function_value (valtype, func)
-     tree valtype;
-     tree func ATTRIBUTE_UNUSED;
+ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
 {
   enum machine_mode mode;
   enum machine_mode hfa_mode;
@@ -3754,14 +3477,9 @@ ia64_function_value (valtype, func)
                                      GEN_INT (offset));
          offset += hfa_size;
        }
-
-      if (i == 1)
-       return XEXP (loc[0], 0);
-      else
-       return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+      return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
     }
-  else if (FLOAT_TYPE_P (valtype) &&
-           ((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
+  else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
     return gen_rtx_REG (mode, FR_ARG_FIRST);
   else
     {
@@ -3794,10 +3512,7 @@ ia64_function_value (valtype, func)
    We need to emit DTP-relative relocations.  */
 
 void
-ia64_output_dwarf_dtprel (file, size, x)
-     FILE *file;
-     int size;
-     rtx x;
+ia64_output_dwarf_dtprel (FILE *file, int size, rtx x)
 {
   if (size != 8)
     abort ();
@@ -3812,9 +3527,8 @@ ia64_output_dwarf_dtprel (file, size, x)
    also call this from ia64_print_operand for memory addresses.  */
 
 void
-ia64_print_operand_address (stream, address)
-     FILE * stream ATTRIBUTE_UNUSED;
-     rtx    address ATTRIBUTE_UNUSED;
+ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
+                           rtx address ATTRIBUTE_UNUSED)
 {
 }
 
@@ -3839,10 +3553,7 @@ ia64_print_operand_address (stream, address)
    r   Print register name, or constant 0 as r0.  HP compatibility for
        Linux kernel.  */
 void
-ia64_print_operand (file, x, code)
-     FILE * file;
-     rtx    x;
-     int    code;
+ia64_print_operand (FILE * file, rtx x, int code)
 {
   const char *str;
 
@@ -4001,7 +3712,7 @@ ia64_print_operand (file, x, code)
     case '+':
       {
        const char *which;
-       
+
        /* For conditional branches, returns or calls, substitute
           sptk, dptk, dpnt, or spnt for %s.  */
        x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
@@ -4060,7 +3771,7 @@ ia64_print_operand (file, x, code)
     case MEM:
       {
        rtx addr = XEXP (x, 0);
-       if (GET_RTX_CLASS (GET_CODE (addr)) == 'a')
+       if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
          addr = XEXP (addr, 0);
        fprintf (file, "[%s]", reg_names [REGNO (addr)]);
        break;
@@ -4080,10 +3791,7 @@ ia64_print_operand (file, x, code)
 /* ??? This is incomplete.  */
 
 static bool
-ia64_rtx_costs (x, code, outer_code, total)
-     rtx x;
-     int code, outer_code;
-     int *total;
+ia64_rtx_costs (rtx x, int code, int outer_code, int *total)
 {
   switch (code)
     {
@@ -4157,9 +3865,8 @@ ia64_rtx_costs (x, code, outer_code, total)
    one in class TO, using MODE.  */
 
 int
-ia64_register_move_cost (mode, from, to)
-     enum machine_mode mode;
-     enum reg_class from, to;
+ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
+                        enum reg_class to)
 {
   /* ADDL_REGS is the same as GR_REGS for movement purposes.  */
   if (to == ADDL_REGS)
@@ -4175,11 +3882,11 @@ ia64_register_move_cost (mode, from, to)
       to = from, from = tmp;
     }
 
-  /* Moving from FR<->GR in TFmode must be more expensive than 2,
+  /* Moving from FR<->GR in XFmode must be more expensive than 2,
      so that we get secondary memory reloads.  Between FR_REGS,
      we have to make this at least as expensive as MEMORY_MOVE_COST
      to avoid spectacularly poor register class preferencing.  */
-  if (mode == TFmode)
+  if (mode == XFmode)
     {
       if (to != GR_REGS || from != GR_REGS)
         return MEMORY_MOVE_COST (mode, to, 0);
@@ -4231,10 +3938,8 @@ ia64_register_move_cost (mode, from, to)
    is required.  */
 
 enum reg_class
-ia64_secondary_reload_class (class, mode, x)
-     enum reg_class class;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     rtx x;
+ia64_secondary_reload_class (enum reg_class class,
+                            enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
   int regno = -1;
 
@@ -4268,10 +3973,10 @@ ia64_secondary_reload_class (class, mode, x)
       break;
 
     case FR_REGS:
-      /* Need to go through general regsters to get to other class regs.  */
+      /* Need to go through general registers to get to other class regs.  */
       if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
        return GR_REGS;
+
       /* This can happen when a paradoxical subreg is an operand to the
         muldi3 pattern.  */
       /* ??? This shouldn't be necessary after instruction scheduling is
@@ -4312,13 +4017,6 @@ ia64_secondary_reload_class (class, mode, x)
        return GR_REGS;
       break;
 
-    case GR_REGS:
-      /* Since we have no offsettable memory addresses, we need a temporary
-        to hold the address of the second word.  */
-      if (mode == TImode)
-       return GR_REGS;
-      break;
-
     default:
       break;
     }
@@ -4331,10 +4029,7 @@ ia64_secondary_reload_class (class, mode, x)
    the Intel assembler does not support undefined externals.  */
 
 void
-ia64_asm_output_external (file, decl, name)
-     FILE *file;
-     tree decl;
-     const char *name;
+ia64_asm_output_external (FILE *file, tree decl, const char *name)
 {
   int save_referenced;
 
@@ -4344,7 +4039,7 @@ ia64_asm_output_external (file, decl, name)
   if (TARGET_GNU_AS
       && (!TARGET_HPUX_LD
          || TREE_CODE (decl) != FUNCTION_DECL
-         || strstr(name, "__builtin_") == name))
+         || strstr (name, "__builtin_") == name))
     return;
 
   /* ??? The Intel assembler creates a reference that needs to be satisfied by
@@ -4360,7 +4055,7 @@ ia64_asm_output_external (file, decl, name)
     return;
 
   if (TARGET_HPUX_LD)
-    ia64_hpux_add_extern_decl (name);
+    ia64_hpux_add_extern_decl (decl);
   else
     {
       /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
@@ -4376,8 +4071,7 @@ ia64_asm_output_external (file, decl, name)
 /* Parse the -mfixed-range= option string.  */
 
 static void
-fix_range (const_str)
-     const char *const_str;
+fix_range (const char *const_str)
 {
   int i, first, last;
   char *str, *dash, *comma;
@@ -4440,7 +4134,7 @@ fix_range (const_str)
 }
 
 static struct machine_function *
-ia64_init_machine_status ()
+ia64_init_machine_status (void)
 {
   return ggc_alloc_cleared (sizeof (struct machine_function));
 }
@@ -4448,7 +4142,7 @@ ia64_init_machine_status ()
 /* Handle TARGET_OPTIONS switches.  */
 
 void
-ia64_override_options ()
+ia64_override_options (void)
 {
   static struct pta
     {
@@ -4472,14 +4166,59 @@ ia64_override_options ()
 
   if (TARGET_INLINE_FLOAT_DIV_LAT && TARGET_INLINE_FLOAT_DIV_THR)
     {
-      warning ("cannot optimize floating point division for both latency and throughput");
-      target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
+      if ((target_flags_explicit & MASK_INLINE_FLOAT_DIV_LAT)
+          && (target_flags_explicit & MASK_INLINE_FLOAT_DIV_THR))
+       {
+         warning ("cannot optimize floating point division for both latency and throughput");
+         target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
+       }
+      else 
+       {
+         if (target_flags_explicit & MASK_INLINE_FLOAT_DIV_THR)
+           target_flags &= ~MASK_INLINE_FLOAT_DIV_LAT;
+         else
+           target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
+       }
     }
 
   if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
     {
-      warning ("cannot optimize integer division for both latency and throughput");
-      target_flags &= ~MASK_INLINE_INT_DIV_THR;
+      if ((target_flags_explicit & MASK_INLINE_INT_DIV_LAT)
+          && (target_flags_explicit & MASK_INLINE_INT_DIV_THR))
+       {
+         warning ("cannot optimize integer division for both latency and throughput");
+         target_flags &= ~MASK_INLINE_INT_DIV_THR;
+       }
+      else 
+       {
+         if (target_flags_explicit & MASK_INLINE_INT_DIV_THR)
+           target_flags &= ~MASK_INLINE_INT_DIV_LAT;
+         else
+           target_flags &= ~MASK_INLINE_INT_DIV_THR;
+       }
+    }
+
+  if (TARGET_INLINE_SQRT_LAT && TARGET_INLINE_SQRT_THR)
+    {
+      if ((target_flags_explicit & MASK_INLINE_SQRT_LAT)
+          && (target_flags_explicit & MASK_INLINE_SQRT_THR))
+       {
+         warning ("cannot optimize square root for both latency and throughput");
+         target_flags &= ~MASK_INLINE_SQRT_THR;
+       }
+      else 
+       {
+         if (target_flags_explicit & MASK_INLINE_SQRT_THR)
+           target_flags &= ~MASK_INLINE_SQRT_LAT;
+         else
+           target_flags &= ~MASK_INLINE_SQRT_THR;
+       }
+    }
+
+  if (TARGET_INLINE_SQRT_LAT)
+    {
+      warning ("not yet implemented: latency-optimized inline square root");
+      target_flags &= ~MASK_INLINE_SQRT_LAT;
     }
 
   if (ia64_fixed_range_string)
@@ -4511,21 +4250,21 @@ ia64_override_options ()
   ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
   flag_schedule_insns_after_reload = 0;
 
+  /* Variable tracking should be run after all optimizations which change order
+     of insns.  It also needs a valid CFG.  */
+  ia64_flag_var_tracking = flag_var_tracking;
+  flag_var_tracking = 0;
+
   ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
 
   init_machine_status = ia64_init_machine_status;
-
-  /* Tell the compiler which flavor of TFmode we're using.  */
-  if (INTEL_EXTENDED_IEEE_FORMAT)
-    real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
 }
 \f
-static enum attr_itanium_class ia64_safe_itanium_class PARAMS((rtx));
-static enum attr_type ia64_safe_type PARAMS((rtx));
+static enum attr_itanium_class ia64_safe_itanium_class (rtx);
+static enum attr_type ia64_safe_type (rtx);
 
 static enum attr_itanium_class
-ia64_safe_itanium_class (insn)
-     rtx insn;
+ia64_safe_itanium_class (rtx insn)
 {
   if (recog_memoized (insn) >= 0)
     return get_attr_itanium_class (insn);
@@ -4534,8 +4273,7 @@ ia64_safe_itanium_class (insn)
 }
 
 static enum attr_type
-ia64_safe_type (insn)
-     rtx insn;
+ia64_safe_type (rtx insn)
 {
   if (recog_memoized (insn) >= 0)
     return get_attr_type (insn);
@@ -4552,7 +4290,6 @@ ia64_safe_type (insn)
    never explicitly used in gcc generated code, it seems wasteful to
    do so (plus it would make the call and return patterns needlessly
    complex).  */
-#define REG_GP         (GR_REG (1))
 #define REG_RP         (BR_REG (0))
 #define REG_AR_CFM     (FIRST_PSEUDO_REGISTER + 1)
 /* This is used for volatile asms which may require a stop bit immediately
@@ -4613,26 +4350,21 @@ struct reg_flags
   unsigned int is_sibcall : 1; /* Is this a sibling or normal call?  */
 };
 
-static void rws_update PARAMS ((struct reg_write_state *, int,
-                               struct reg_flags, int));
-static int rws_access_regno PARAMS ((int, struct reg_flags, int));
-static int rws_access_reg PARAMS ((rtx, struct reg_flags, int));
-static void update_set_flags PARAMS ((rtx, struct reg_flags *, int *, rtx *));
-static int set_src_needs_barrier PARAMS ((rtx, struct reg_flags, int, rtx));
-static int rtx_needs_barrier PARAMS ((rtx, struct reg_flags, int));
-static void init_insn_group_barriers PARAMS ((void));
-static int group_barrier_needed_p PARAMS ((rtx));
-static int safe_group_barrier_needed_p PARAMS ((rtx));
+static void rws_update (struct reg_write_state *, int, struct reg_flags, int);
+static int rws_access_regno (int, struct reg_flags, int);
+static int rws_access_reg (rtx, struct reg_flags, int);
+static void update_set_flags (rtx, struct reg_flags *, int *, rtx *);
+static int set_src_needs_barrier (rtx, struct reg_flags, int, rtx);
+static int rtx_needs_barrier (rtx, struct reg_flags, int);
+static void init_insn_group_barriers (void);
+static int group_barrier_needed_p (rtx);
+static int safe_group_barrier_needed_p (rtx);
 
 /* Update *RWS for REGNO, which is being written by the current instruction,
    with predicate PRED, and associated register flags in FLAGS.  */
 
 static void
-rws_update (rws, regno, flags, pred)
-     struct reg_write_state *rws;
-     int regno;
-     struct reg_flags flags;
-     int pred;
+rws_update (struct reg_write_state *rws, int regno, struct reg_flags flags, int pred)
 {
   if (pred)
     rws[regno].write_count++;
@@ -4650,10 +4382,7 @@ rws_update (rws, regno, flags, pred)
    a dependency with an earlier instruction in the same group.  */
 
 static int
-rws_access_regno (regno, flags, pred)
-     int regno;
-     struct reg_flags flags;
-     int pred;
+rws_access_regno (int regno, struct reg_flags flags, int pred)
 {
   int need_barrier = 0;
 
@@ -4688,7 +4417,7 @@ rws_access_regno (regno, flags, pred)
          /* ??? This assumes that P and P+1 are always complementary
             predicates for P even.  */
          if (flags.is_and && rws_sum[regno].written_by_and)
-           ; 
+           ;
          else if (flags.is_or && rws_sum[regno].written_by_or)
            ;
          else if ((rws_sum[regno].first_pred ^ 1) != pred)
@@ -4771,10 +4500,7 @@ rws_access_regno (regno, flags, pred)
 }
 
 static int
-rws_access_reg (reg, flags, pred)
-     rtx reg;
-     struct reg_flags flags;
-     int pred;
+rws_access_reg (rtx reg, struct reg_flags flags, int pred)
 {
   int regno = REGNO (reg);
   int n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
@@ -4794,11 +4520,7 @@ rws_access_reg (reg, flags, pred)
    the condition, stored in *PFLAGS, *PPRED and *PCOND.  */
 
 static void
-update_set_flags (x, pflags, ppred, pcond)
-     rtx x;
-     struct reg_flags *pflags;
-     int *ppred;
-     rtx *pcond;
+update_set_flags (rtx x, struct reg_flags *pflags, int *ppred, rtx *pcond)
 {
   rtx src = SET_SRC (x);
 
@@ -4812,7 +4534,7 @@ update_set_flags (x, pflags, ppred, pcond)
     case IF_THEN_ELSE:
       if (SET_DEST (x) == pc_rtx)
        /* X is a conditional branch.  */
-       return; 
+       return;
       else
        {
          int is_complemented = 0;
@@ -4852,7 +4574,7 @@ update_set_flags (x, pflags, ppred, pcond)
       /* ... fall through ...  */
 
     default:
-      if (GET_RTX_CLASS (GET_CODE (src)) == '<'
+      if (COMPARISON_P (src)
          && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
        /* Set pflags->is_fp to 1 so that we know we're dealing
           with a floating point comparison when processing the
@@ -4875,13 +4597,9 @@ update_set_flags (x, pflags, ppred, pcond)
    source of a given SET rtx found in X needs a barrier.  FLAGS and PRED
    are as in rtx_needs_barrier.  COND is an rtx that holds the condition
    for this insn.  */
-   
+
 static int
-set_src_needs_barrier (x, flags, pred, cond)
-     rtx x;
-     struct reg_flags flags;
-     int pred;
-     rtx cond;
+set_src_needs_barrier (rtx x, struct reg_flags flags, int pred, rtx cond)
 {
   int need_barrier = 0;
   rtx dst;
@@ -4916,15 +4634,12 @@ set_src_needs_barrier (x, flags, pred, cond)
   return need_barrier;
 }
 
-/* Handle an access to rtx X of type FLAGS using predicate register PRED.
-   Return 1 is this access creates a dependency with an earlier instruction
-   in the same group.  */
+/* Handle an access to rtx X of type FLAGS using predicate register
+   PRED.  Return 1 if this access creates a dependency with an earlier
+   instruction in the same group.  */
 
 static int
-rtx_needs_barrier (x, flags, pred)
-     rtx x;
-     struct reg_flags flags;
-     int pred;
+rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
 {
   int i, j;
   int is_complemented = 0;
@@ -4940,7 +4655,7 @@ rtx_needs_barrier (x, flags, pred)
 
   switch (GET_CODE (x))
     {
-    case SET:      
+    case SET:
       update_set_flags (x, &new_flags, &pred, &cond);
       need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
       if (GET_CODE (SET_SRC (x)) != CALL)
@@ -5009,7 +4724,7 @@ rtx_needs_barrier (x, flags, pred)
        }
 
       /* For all ASM_OPERANDS, we must traverse the vector of input operands.
-        We can not just fall through here since then we would be confused
+        We cannot just fall through here since then we would be confused
         by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
         traditional asms unlike their normal usage.  */
 
@@ -5143,11 +4858,13 @@ rtx_needs_barrier (x, flags, pred)
                                              new_flags, pred);
            break;
          }
-         
+
        case UNSPEC_FR_SPILL:
        case UNSPEC_FR_RESTORE:
        case UNSPEC_GETF_EXP:
+       case UNSPEC_SETF_EXP:
         case UNSPEC_ADDP4:
+       case UNSPEC_FR_SQRT_RECIP_APPROX:
          need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
          break;
 
@@ -5245,7 +4962,7 @@ rtx_needs_barrier (x, flags, pred)
    sequence of insns.  */
 
 static void
-init_insn_group_barriers ()
+init_insn_group_barriers (void)
 {
   memset (rws_sum, 0, sizeof (rws_sum));
   first_instruction = 1;
@@ -5256,8 +4973,7 @@ init_insn_group_barriers ()
    Return nonzero if so.  */
 
 static int
-group_barrier_needed_p (insn)
-     rtx insn;
+group_barrier_needed_p (rtx insn)
 {
   rtx pat;
   int need_barrier = 0;
@@ -5368,8 +5084,7 @@ group_barrier_needed_p (insn)
 /* Like group_barrier_needed_p, but do not clobber the current state.  */
 
 static int
-safe_group_barrier_needed_p (insn)
-     rtx insn;
+safe_group_barrier_needed_p (rtx insn)
 {
   struct reg_write_state rws_saved[NUM_REGS];
   int saved_first_instruction;
@@ -5394,8 +5109,7 @@ safe_group_barrier_needed_p (insn)
    invisible to the scheduler.  */
 
 static void
-emit_insn_group_barriers (dump)
-     FILE *dump;
+emit_insn_group_barriers (FILE *dump)
 {
   rtx insn;
   rtx last_label = 0;
@@ -5451,8 +5165,7 @@ emit_insn_group_barriers (dump)
    This function has to emit all necessary group barriers.  */
 
 static void
-emit_all_insn_group_barriers (dump)
-     FILE *dump ATTRIBUTE_UNUSED;
+emit_all_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
 {
   rtx insn;
 
@@ -5489,9 +5202,9 @@ emit_all_insn_group_barriers (dump)
 }
 
 \f
-static int errata_find_address_regs PARAMS ((rtx *, void *));
-static void errata_emit_nops PARAMS ((rtx));
-static void fixup_errata PARAMS ((void));
+static int errata_find_address_regs (rtx *, void *);
+static void errata_emit_nops (rtx);
+static void fixup_errata (void);
 
 /* This structure is used to track some details about the previous insns
    groups so we can determine if it may be necessary to insert NOPs to
@@ -5509,9 +5222,7 @@ static int group_idx;
    conditionally set in the previous group is used as an address register.
    It ensures that for_each_rtx returns 1 in that case.  */
 static int
-errata_find_address_regs (xp, data)
-     rtx *xp;
-     void *data ATTRIBUTE_UNUSED;
+errata_find_address_regs (rtx *xp, void *data ATTRIBUTE_UNUSED)
 {
   rtx x = *xp;
   if (GET_CODE (x) != MEM)
@@ -5534,8 +5245,7 @@ errata_find_address_regs (xp, data)
    last_group and emits additional NOPs if necessary to work around
    an Itanium A/B step erratum.  */
 static void
-errata_emit_nops (insn)
-     rtx insn;
+errata_emit_nops (rtx insn)
 {
   struct group *this_group = last_group + group_idx;
   struct group *prev_group = last_group + (group_idx ^ 1);
@@ -5588,8 +5298,8 @@ errata_emit_nops (insn)
          || GET_CODE (XEXP (SET_SRC (set), 0)) != POST_MODIFY)
       && GENERAL_REGNO_P (REGNO (SET_DEST (set))))
     {
-      if (GET_RTX_CLASS (GET_CODE (cond)) != '<'
-         || ! REG_P (XEXP (cond, 0)))
+      if (!COMPARISON_P (cond)
+         || !REG_P (XEXP (cond, 0)))
        abort ();
 
       if (TEST_HARD_REG_BIT (prev_group->p_reg_set, REGNO (XEXP (cond, 0))))
@@ -5608,7 +5318,7 @@ errata_emit_nops (insn)
 /* Emit extra nops if they are required to work around hardware errata.  */
 
 static void
-fixup_errata ()
+fixup_errata (void)
 {
   rtx insn;
 
@@ -5717,14 +5427,13 @@ static int *clocks;
 
 static int *add_cycles;
 
-static rtx ia64_single_set PARAMS ((rtx));
-static void ia64_emit_insn_before PARAMS ((rtx, rtx));
+static rtx ia64_single_set (rtx);
+static void ia64_emit_insn_before (rtx, rtx);
 
 /* Map a bundle number to its pseudo-op.  */
 
 const char *
-get_bundle_name (b)
-     int b;
+get_bundle_name (int b)
 {
   return bundle_name[b];
 }
@@ -5733,7 +5442,7 @@ get_bundle_name (b)
 /* Return the maximum number of instructions a cpu can issue.  */
 
 static int
-ia64_issue_rate ()
+ia64_issue_rate (void)
 {
   return 6;
 }
@@ -5741,8 +5450,7 @@ ia64_issue_rate ()
 /* Helper function - like single_set, but look inside COND_EXEC.  */
 
 static rtx
-ia64_single_set (insn)
-     rtx insn;
+ia64_single_set (rtx insn)
 {
   rtx x = PATTERN (insn), ret;
   if (GET_CODE (x) == COND_EXEC)
@@ -5772,9 +5480,7 @@ ia64_single_set (insn)
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
 
 static int
-ia64_adjust_cost (insn, link, dep_insn, cost)
-     rtx insn, link, dep_insn;
-     int cost;
+ia64_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 {
   enum attr_itanium_class dep_class;
   enum attr_itanium_class insn_class;
@@ -5795,8 +5501,7 @@ ia64_adjust_cost (insn, link, dep_insn, cost)
    ??? When cycle display notes are implemented, update this.  */
 
 static void
-ia64_emit_insn_before (insn, before)
-     rtx insn, before;
+ia64_emit_insn_before (rtx insn, rtx before)
 {
   emit_insn_before (insn, before);
 }
@@ -5807,11 +5512,10 @@ ia64_emit_insn_before (insn, before)
    `ia64_produce_address_p' and the DFA descriptions).  */
 
 static void
-ia64_dependencies_evaluation_hook (head, tail)
-     rtx head, tail;
+ia64_dependencies_evaluation_hook (rtx head, rtx tail)
 {
   rtx insn, link, next, next_tail;
-  
+
   next_tail = NEXT_INSN (tail);
   for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
     if (INSN_P (insn))
@@ -5840,14 +5544,13 @@ ia64_dependencies_evaluation_hook (head, tail)
 /* We're beginning a new block.  Initialize data structures as necessary.  */
 
 static void
-ia64_sched_init (dump, sched_verbose, max_ready)
-     FILE *dump ATTRIBUTE_UNUSED;
-     int sched_verbose ATTRIBUTE_UNUSED;
-     int max_ready ATTRIBUTE_UNUSED;
+ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
+                int sched_verbose ATTRIBUTE_UNUSED,
+                int max_ready ATTRIBUTE_UNUSED)
 {
 #ifdef ENABLE_CHECKING
   rtx insn;
-  
+
   if (reload_completed)
     for (insn = NEXT_INSN (current_sched_info->prev_head);
         insn != current_sched_info->next_tail;
@@ -5863,14 +5566,9 @@ ia64_sched_init (dump, sched_verbose, max_ready)
    Override the default sort algorithm to better slot instructions.  */
 
 static int
-ia64_dfa_sched_reorder (dump, sched_verbose, ready, pn_ready,
-                       clock_var, reorder_type)
-     FILE *dump;
-     int sched_verbose;
-     rtx *ready;
-     int *pn_ready;
-     int clock_var  ATTRIBUTE_UNUSED;
-     int reorder_type;
+ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
+                       int *pn_ready, int clock_var ATTRIBUTE_UNUSED,
+                       int reorder_type)
 {
   int n_asms;
   int n_ready = *pn_ready;
@@ -5927,7 +5625,7 @@ ia64_dfa_sched_reorder (dump, sched_verbose, ready, pn_ready,
       for (insnp = ready; insnp < e_ready; insnp++)
        if (safe_group_barrier_needed_p (*insnp))
          nr_need_stop++;
-      
+
       if (reorder_type == 1 && n_ready == nr_need_stop)
        return 0;
       if (reorder_type == 0)
@@ -5956,12 +5654,8 @@ ia64_dfa_sched_reorder (dump, sched_verbose, ready, pn_ready,
    the default sort algorithm to better slot instructions.  */
 
 static int
-ia64_sched_reorder (dump, sched_verbose, ready, pn_ready, clock_var)
-     FILE *dump;
-     int sched_verbose;
-     rtx *ready;
-     int *pn_ready;
-     int clock_var;
+ia64_sched_reorder (FILE *dump, int sched_verbose, rtx *ready, int *pn_ready,
+                   int clock_var)
 {
   return ia64_dfa_sched_reorder (dump, sched_verbose, ready,
                                 pn_ready, clock_var, 0);
@@ -5971,12 +5665,9 @@ ia64_sched_reorder (dump, sched_verbose, ready, pn_ready, clock_var)
    Override the default sort algorithm to better slot instructions.  */
 
 static int
-ia64_sched_reorder2 (dump, sched_verbose, ready, pn_ready, clock_var)
-     FILE *dump ATTRIBUTE_UNUSED;
-     int sched_verbose ATTRIBUTE_UNUSED;
-     rtx *ready;
-     int *pn_ready;
-     int clock_var;
+ia64_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
+                    int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
+                    int *pn_ready, int clock_var)
 {
   if (ia64_tune == PROCESSOR_ITANIUM && reload_completed && last_scheduled_insn)
     clocks [INSN_UID (last_scheduled_insn)] = clock_var;
@@ -5988,11 +5679,10 @@ ia64_sched_reorder2 (dump, sched_verbose, ready, pn_ready, clock_var)
    ready queue that can be issued this cycle.  */
 
 static int
-ia64_variable_issue (dump, sched_verbose, insn, can_issue_more)
-     FILE *dump ATTRIBUTE_UNUSED;
-     int sched_verbose ATTRIBUTE_UNUSED;
-     rtx insn ATTRIBUTE_UNUSED;
-     int can_issue_more ATTRIBUTE_UNUSED;
+ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
+                    int sched_verbose ATTRIBUTE_UNUSED,
+                    rtx insn ATTRIBUTE_UNUSED,
+                    int can_issue_more ATTRIBUTE_UNUSED)
 {
   last_scheduled_insn = insn;
   memcpy (prev_cycle_state, curr_state, dfa_state_size);
@@ -6012,8 +5702,7 @@ ia64_variable_issue (dump, sched_verbose, insn, can_issue_more)
    can be chosen.  */
 
 static int
-ia64_first_cycle_multipass_dfa_lookahead_guard (insn)
-     rtx insn;
+ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
 {
   if (insn == NULL_RTX || !INSN_P (insn))
     abort ();
@@ -6027,17 +5716,13 @@ ia64_first_cycle_multipass_dfa_lookahead_guard (insn)
 
 static rtx dfa_pre_cycle_insn;
 
-/* We are about to being issuing INSN.  Return nonzero if we can not
+/* We are about to being issuing INSN.  Return nonzero if we cannot
    issue it on given cycle CLOCK and return zero if we should not sort
    the ready queue on the next clock start.  */
 
 static int
-ia64_dfa_new_cycle (dump, verbose, insn, last_clock, clock, sort_p)
-     FILE *dump;
-     int verbose;
-     rtx insn;
-     int last_clock, clock;
-     int *sort_p;
+ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
+                   int clock, int *sort_p)
 {
   int setup_clocks_p = FALSE;
 
@@ -6066,28 +5751,36 @@ ia64_dfa_new_cycle (dump, verbose, insn, last_clock, clock, sort_p)
        }
       else if (reload_completed)
        setup_clocks_p = TRUE;
-      memcpy (curr_state, prev_cycle_state, dfa_state_size);
-      state_transition (curr_state, dfa_stop_insn);
-      state_transition (curr_state, dfa_pre_cycle_insn);
-      state_transition (curr_state, NULL);
+      if (GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
+         || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)
+       state_reset (curr_state);
+      else
+       {
+         memcpy (curr_state, prev_cycle_state, dfa_state_size);
+         state_transition (curr_state, dfa_stop_insn);
+         state_transition (curr_state, dfa_pre_cycle_insn);
+         state_transition (curr_state, NULL);
+       }
     }
   else if (reload_completed)
     setup_clocks_p = TRUE;
-  if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM)
+  if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM
+      && GET_CODE (PATTERN (insn)) != ASM_INPUT
+      && asm_noperands (PATTERN (insn)) < 0)
     {
       enum attr_itanium_class c = ia64_safe_itanium_class (insn);
-      
+
       if (c != ITANIUM_CLASS_MMMUL && c != ITANIUM_CLASS_MMSHF)
        {
          rtx link;
          int d = -1;
-         
+
          for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
            if (REG_NOTE_KIND (link) == 0)
              {
                enum attr_itanium_class dep_class;
                rtx dep_insn = XEXP (link, 0);
-               
+
                dep_class = ia64_safe_itanium_class (dep_insn);
                if ((dep_class == ITANIUM_CLASS_MMMUL
                     || dep_class == ITANIUM_CLASS_MMSHF)
@@ -6153,7 +5846,7 @@ static struct bundle_state *free_bundle_state_chain;
 /* The following function returns a free bundle state.  */
 
 static struct bundle_state *
-get_free_bundle_state ()
+get_free_bundle_state (void)
 {
   struct bundle_state *result;
 
@@ -6171,14 +5864,13 @@ get_free_bundle_state ()
     }
   result->unique_num = bundle_states_num++;
   return result;
-  
+
 }
 
 /* The following function frees given bundle state.  */
 
 static void
-free_bundle_state (state)
-     struct bundle_state *state;
+free_bundle_state (struct bundle_state *state)
 {
   state->next = free_bundle_state_chain;
   free_bundle_state_chain = state;
@@ -6187,7 +5879,7 @@ free_bundle_state (state)
 /* Start work with abstract data `bundle states'.  */
 
 static void
-initiate_bundle_states ()
+initiate_bundle_states (void)
 {
   bundle_states_num = 0;
   free_bundle_state_chain = NULL;
@@ -6197,7 +5889,7 @@ initiate_bundle_states ()
 /* Finish work with abstract data `bundle states'.  */
 
 static void
-finish_bundle_states ()
+finish_bundle_states (void)
 {
   struct bundle_state *curr_state, *next_state;
 
@@ -6219,8 +5911,7 @@ static htab_t bundle_state_table;
 /* The function returns hash of BUNDLE_STATE.  */
 
 static unsigned
-bundle_state_hash (bundle_state)
-     const void *bundle_state;
+bundle_state_hash (const void *bundle_state)
 {
   const struct bundle_state *state = (struct bundle_state *) bundle_state;
   unsigned result, i;
@@ -6234,9 +5925,7 @@ bundle_state_hash (bundle_state)
 /* The function returns nonzero if the bundle state keys are equal.  */
 
 static int
-bundle_state_eq_p (bundle_state_1, bundle_state_2)
-     const void *bundle_state_1;
-     const void *bundle_state_2;
+bundle_state_eq_p (const void *bundle_state_1, const void *bundle_state_2)
 {
   const struct bundle_state * state1 = (struct bundle_state *) bundle_state_1;
   const struct bundle_state * state2 = (struct bundle_state *) bundle_state_2;
@@ -6251,8 +5940,7 @@ bundle_state_eq_p (bundle_state_1, bundle_state_2)
    table.  The table contains the best bundle state with given key.  */
 
 static int
-insert_bundle_state (bundle_state)
-     struct bundle_state *bundle_state;
+insert_bundle_state (struct bundle_state *bundle_state)
 {
   void **entry_ptr;
 
@@ -6274,7 +5962,7 @@ insert_bundle_state (bundle_state)
                       && ((struct bundle_state *)
                           *entry_ptr)->branch_deviation
                       > bundle_state->branch_deviation))))
-                  
+
     {
       struct bundle_state temp;
 
@@ -6289,7 +5977,7 @@ insert_bundle_state (bundle_state)
 /* Start work with the hash table.  */
 
 static void
-initiate_bundle_state_table ()
+initiate_bundle_state_table (void)
 {
   bundle_state_table = htab_create (50, bundle_state_hash, bundle_state_eq_p,
                                    (htab_del) 0);
@@ -6298,7 +5986,7 @@ initiate_bundle_state_table ()
 /* Finish work with the hash table.  */
 
 static void
-finish_bundle_state_table ()
+finish_bundle_state_table (void)
 {
   htab_delete (bundle_state_table);
 }
@@ -6315,9 +6003,7 @@ static rtx ia64_nop;
    function returns FALSE and frees the current state.  */
 
 static int
-try_issue_nops (curr_state, nops_num)
-     struct bundle_state *curr_state;
-     int nops_num;
+try_issue_nops (struct bundle_state *curr_state, int nops_num)
 {
   int i;
 
@@ -6335,9 +6021,7 @@ try_issue_nops (curr_state, nops_num)
    function returns FALSE and frees the current state.  */
 
 static int
-try_issue_insn (curr_state, insn)
-     struct bundle_state *curr_state;
-     rtx insn;
+try_issue_insn (struct bundle_state *curr_state, rtx insn)
 {
   if (insn && state_transition (curr_state->dfa_state, insn) >= 0)
     {
@@ -6355,12 +6039,8 @@ try_issue_insn (curr_state, insn)
    insert into the hash table and into `index_to_bundle_states'.  */
 
 static void
-issue_nops_and_insn (originator, before_nops_num, insn, try_bundle_end_p,
-                    only_bundle_end_p)
-     struct bundle_state *originator;
-     int before_nops_num;
-     rtx insn;
-     int try_bundle_end_p, only_bundle_end_p;
+issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
+                    rtx insn, int try_bundle_end_p, int only_bundle_end_p)
 {
   struct bundle_state *curr_state;
 
@@ -6466,8 +6146,7 @@ issue_nops_and_insn (originator, before_nops_num, insn, try_bundle_end_p,
    for given STATE.  */
 
 static int
-get_max_pos (state)
-     state_t state;
+get_max_pos (state_t state)
 {
   if (cpu_unit_reservation_p (state, pos_6))
     return 6;
@@ -6490,9 +6169,7 @@ get_max_pos (state)
    position equal to 3 or 6.  */
 
 static int
-get_template (state, pos)
-     state_t state;
-     int pos;
+get_template (state_t state, int pos)
 {
   switch (pos)
     {
@@ -6551,8 +6228,7 @@ get_template (state, pos)
    followed by INSN and before TAIL.  */
 
 static rtx
-get_next_important_insn (insn, tail)
-     rtx insn, tail;
+get_next_important_insn (rtx insn, rtx tail)
 {
   for (; insn && insn != tail; insn = NEXT_INSN (insn))
     if (INSN_P (insn)
@@ -6563,19 +6239,47 @@ get_next_important_insn (insn, tail)
   return NULL_RTX;
 }
 
-/* The following function does insn bundling.  Bundling algorithm is
-   based on dynamic programming.  It tries to insert different number of
-   nop insns before/after the real insns.  At the end of EBB, it chooses the
-   best alternative and then, moving back in EBB, inserts templates for
-   the best alternative.  The algorithm is directed by information
-   (changes of simulated processor cycle) created by the 2nd insn
-   scheduling.  */
+/* The following function does insn bundling.  Bundling means
+   inserting templates and nop insns to fit insn groups into permitted
+   templates.  Instruction scheduling uses NDFA (non-deterministic
+   finite automata) encoding informations about the templates and the
+   inserted nops.  Nondeterminism of the automata permits follows
+   all possible insn sequences very fast.
+
+   Unfortunately it is not possible to get information about inserting
+   nop insns and used templates from the automata states.  The
+   automata only says that we can issue an insn possibly inserting
+   some nops before it and using some template.  Therefore insn
+   bundling in this function is implemented by using DFA
+   (deterministic finite automata).  We follows all possible insn
+   sequences by inserting 0-2 nops (that is what the NDFA describe for
+   insn scheduling) before/after each insn being bundled.  We know the
+   start of simulated processor cycle from insn scheduling (insn
+   starting a new cycle has TImode).
+
+   Simple implementation of insn bundling would create enormous
+   number of possible insn sequences satisfying information about new
+   cycle ticks taken from the insn scheduling.  To make the algorithm
+   practical we use dynamic programming.  Each decision (about
+   inserting nops and implicitly about previous decisions) is described
+   by structure bundle_state (see above).  If we generate the same
+   bundle state (key is automaton state after issuing the insns and
+   nops for it), we reuse already generated one.  As consequence we
+   reject some decisions which cannot improve the solution and
+   reduce memory for the algorithm.
+
+   When we reach the end of EBB (extended basic block), we choose the
+   best sequence and then, moving back in EBB, insert templates for
+   the best alternative.  The templates are taken from querying
+   automaton state for each insn in chosen bundle states.
+
+   So the algorithm makes two (forward and backward) passes through
+   EBB.  There is an additional forward pass through EBB for Itanium1
+   processor.  This pass inserts more nops to make dependency between
+   a producer insn and MMMUL/MMSHF at least 4 cycles long.  */
 
 static void
-bundling (dump, verbose, prev_head_insn, tail)
-     FILE *dump;
-     int verbose;
-     rtx prev_head_insn, tail;
+bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
 {
   struct bundle_state *curr_state, *next_state, *best_state;
   rtx insn, next_insn;
@@ -6587,6 +6291,7 @@ bundling (dump, verbose, prev_head_insn, tail)
   enum attr_type type;
 
   insn_num = 0;
+  /* Count insns in the EBB.  */
   for (insn = NEXT_INSN (prev_head_insn);
        insn && insn != tail;
        insn = NEXT_INSN (insn))
@@ -6599,7 +6304,7 @@ bundling (dump, verbose, prev_head_insn, tail)
   initiate_bundle_state_table ();
   index_to_bundle_states = xmalloc ((insn_num + 2)
                                    * sizeof (struct bundle_state *));
-  /* First (forward) pass -- generates states. */
+  /* First (forward) pass -- generation of bundle states.  */
   curr_state = get_free_bundle_state ();
   curr_state->insn = NULL;
   curr_state->before_nops_num = 0;
@@ -6613,6 +6318,7 @@ bundling (dump, verbose, prev_head_insn, tail)
   state_reset (curr_state->dfa_state);
   index_to_bundle_states [0] = curr_state;
   insn_num = 0;
+  /* Shift cycle mark if it is put on insn which could be ignored.  */
   for (insn = NEXT_INSN (prev_head_insn);
        insn != tail;
        insn = NEXT_INSN (insn))
@@ -6635,6 +6341,7 @@ bundling (dump, verbose, prev_head_insn, tail)
              break;
            }
       }
+  /* Froward pass: generation of bundle states.  */
   for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
        insn != NULL_RTX;
        insn = next_insn)
@@ -6654,20 +6361,27 @@ bundling (dump, verbose, prev_head_insn, tail)
        {
          pos = curr_state->accumulated_insns_num % 3;
          next_state = curr_state->next;
-         /* Finish the current bundle in order to start a subsequent
-            asm insn in a new bundle.  */
+         /* We must fill up the current bundle in order to start a
+            subsequent asm insn in a new bundle.  Asm insn is always
+            placed in a separate bundle.  */
          only_bundle_end_p
            = (next_insn != NULL_RTX
               && INSN_CODE (insn) == CODE_FOR_insn_group_barrier
               && ia64_safe_type (next_insn) == TYPE_UNKNOWN);
+         /* We may fill up the current bundle if it is the cycle end
+            without a group barrier.  */
          bundle_end_p
            = (only_bundle_end_p || next_insn == NULL_RTX
               || (GET_MODE (next_insn) == TImode
                   && INSN_CODE (insn) != CODE_FOR_insn_group_barrier));
          if (type == TYPE_F || type == TYPE_B || type == TYPE_L
              || type == TYPE_S
-             /* We need to insert 2 Nops for cases like M_MII.  */
-             || (type == TYPE_M && ia64_tune == PROCESSOR_ITANIUM
+             /* We need to insert 2 nops for cases like M_MII.  To
+                guarantee issuing all insns on the same cycle for
+                Itanium 1, we need to issue 2 nops after the first M
+                insn (MnnMII where n is a nop insn).  */
+             || ((type == TYPE_M || type == TYPE_A)
+                 && ia64_tune == PROCESSOR_ITANIUM
                  && !bundle_end_p && pos == 1))
            issue_nops_and_insn (curr_state, 2, insn, bundle_end_p,
                                 only_bundle_end_p);
@@ -6683,6 +6397,10 @@ bundling (dump, verbose, prev_head_insn, tail)
           curr_state = curr_state->next)
        if (verbose >= 2 && dump)
          {
+           /* This structure is taken from generated code of the
+              pipeline hazard recognizer (see file insn-attrtab.c).
+              Please don't forget to change the structure if a new
+              automaton is added to .md file.  */
            struct DFA_chip
            {
              unsigned short one_automaton_state;
@@ -6690,7 +6408,7 @@ bundling (dump, verbose, prev_head_insn, tail)
              unsigned short two_automaton_state;
              unsigned short twob_automaton_state;
            };
-           
+
            fprintf
              (dump,
               "//    Bundle state %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
@@ -6707,12 +6425,18 @@ bundling (dump, verbose, prev_head_insn, tail)
          }
     }
   if (index_to_bundle_states [insn_num] == NULL)
+    /* We should find a solution because the 2nd insn scheduling has
+       found one.  */
     abort ();
-  /* Finding state with a minimal cost:  */
+  /* Find a state corresponding to the best insn sequence.  */
   best_state = NULL;
   for (curr_state = index_to_bundle_states [insn_num];
        curr_state != NULL;
        curr_state = curr_state->next)
+    /* We are just looking at the states with fully filled up last
+       bundle.  The first we prefer insn sequences with minimal cost
+       then with minimal inserted nops and finally with branch insns
+       placed in the 3rd slots.  */
     if (curr_state->accumulated_insns_num % 3 == 0
        && (best_state == NULL || best_state->cost > curr_state->cost
            || (best_state->cost == curr_state->cost
@@ -6723,7 +6447,7 @@ bundling (dump, verbose, prev_head_insn, tail)
                        && curr_state->branch_deviation
                        < best_state->branch_deviation)))))
       best_state = curr_state;
-  /* Second (backward) pass: adding nops and templates:  */
+  /* Second (backward) pass: adding nops and templates.  */
   insn_num = best_state->before_nops_num;
   template0 = template1 = -1;
   for (curr_state = best_state;
@@ -6743,7 +6467,7 @@ bundling (dump, verbose, prev_head_insn, tail)
            unsigned short two_automaton_state;
            unsigned short twob_automaton_state;
          };
-         
+
          fprintf
            (dump,
             "//    Best %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
@@ -6758,9 +6482,17 @@ bundling (dump, verbose, prev_head_insn, tail)
              : ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state),
             INSN_UID (insn));
        }
+      /* Find the position in the current bundle window.  The window can
+        contain at most two bundles.  Two bundle window means that
+        the processor will make two bundle rotation.  */
       max_pos = get_max_pos (curr_state->dfa_state);
-      if (max_pos == 6 || (max_pos == 3 && template0 < 0))
+      if (max_pos == 6
+         /* The following (negative template number) means that the
+            processor did one bundle rotation.  */
+         || (max_pos == 3 && template0 < 0))
        {
+         /* We are at the end of the window -- find template(s) for
+            its bundle(s).  */
          pos = max_pos;
          if (max_pos == 3)
            template0 = get_template (curr_state->dfa_state, 3);
@@ -6771,6 +6503,7 @@ bundling (dump, verbose, prev_head_insn, tail)
            }
        }
       if (max_pos > 3 && template1 < 0)
+       /* It may happen when we have the stop inside a bundle.  */
        {
          if (pos > 3)
            abort ();
@@ -6778,6 +6511,7 @@ bundling (dump, verbose, prev_head_insn, tail)
          pos += 3;
        }
       if (!asm_p)
+       /* Emit nops after the current insn.  */
        for (i = 0; i < curr_state->after_nops_num; i++)
          {
            nop = gen_nop ();
@@ -6787,18 +6521,26 @@ bundling (dump, verbose, prev_head_insn, tail)
              abort ();
            if (pos % 3 == 0)
              {
+               /* We are at the start of a bundle: emit the template
+                  (it should be defined).  */
                if (template0 < 0)
                  abort ();
                b = gen_bundle_selector (GEN_INT (template0));
                ia64_emit_insn_before (b, nop);
+               /* If we have two bundle window, we make one bundle
+                  rotation.  Otherwise template0 will be undefined
+                  (negative value).  */
                template0 = template1;
                template1 = -1;
              }
          }
+      /* Move the position backward in the window.  Group barrier has
+        no slot.  Asm insn takes all bundle.  */
       if (INSN_CODE (insn) != CODE_FOR_insn_group_barrier
          && GET_CODE (PATTERN (insn)) != ASM_INPUT
          && asm_noperands (PATTERN (insn)) < 0)
        pos--;
+      /* Long insn takes 2 slots.  */
       if (ia64_safe_type (insn) == TYPE_L)
        pos--;
       if (pos < 0)
@@ -6808,15 +6550,20 @@ bundling (dump, verbose, prev_head_insn, tail)
          && GET_CODE (PATTERN (insn)) != ASM_INPUT
          && asm_noperands (PATTERN (insn)) < 0)
        {
+         /* The current insn is at the bundle start: emit the
+            template.  */
          if (template0 < 0)
            abort ();
          b = gen_bundle_selector (GEN_INT (template0));
          ia64_emit_insn_before (b, insn);
          b = PREV_INSN (insn);
          insn = b;
+         /* See comment above in analogous place for emitting nops
+            after the insn.  */
          template0 = template1;
          template1 = -1;
        }
+      /* Emit nops after the current insn.  */
       for (i = 0; i < curr_state->before_nops_num; i++)
        {
          nop = gen_nop ();
@@ -6828,6 +6575,8 @@ bundling (dump, verbose, prev_head_insn, tail)
            abort ();
          if (pos % 3 == 0)
            {
+             /* See comment above in analogous place for emitting nops
+                after the insn.  */
              if (template0 < 0)
                abort ();
              b = gen_bundle_selector (GEN_INT (template0));
@@ -6840,7 +6589,11 @@ bundling (dump, verbose, prev_head_insn, tail)
        }
     }
   if (ia64_tune == PROCESSOR_ITANIUM)
-    /* Insert additional cycles for MM-insns: */
+    /* Insert additional cycles for MM-insns (MMMUL and MMSHF).
+       Itanium1 has a strange design, if the distance between an insn
+       and dependent MM-insn is less 4 then we have a 6 additional
+       cycles stall.  So we make the distance equal to 4 cycles if it
+       is less.  */
     for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
         insn != NULL_RTX;
         insn = next_insn)
@@ -6852,11 +6605,16 @@ bundling (dump, verbose, prev_head_insn, tail)
          abort ();
        next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
        if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
+         /* We found a MM-insn which needs additional cycles.  */
          {
            rtx last;
            int i, j, n;
            int pred_stop_p;
-           
+
+           /* Now we are searching for a template of the bundle in
+              which the MM-insn is placed and the position of the
+              insn in the bundle (0, 1, 2).  Also we are searching
+              for that there is a stop before the insn.  */
            last = prev_active_insn (insn);
            pred_stop_p = recog_memoized (last) == CODE_FOR_insn_group_barrier;
            if (pred_stop_p)
@@ -6867,17 +6625,29 @@ bundling (dump, verbose, prev_head_insn, tail)
                {
                  template0 = XINT (XVECEXP (PATTERN (last), 0, 0), 0);
                  if (template0 == 9)
+                   /* The insn is in MLX bundle.  Change the template
+                      onto MFI because we will add nops before the
+                      insn.  It simplifies subsequent code a lot.  */
                    PATTERN (last)
-                     = gen_bundle_selector (GEN_INT (2)); /* -> MFI */
+                     = gen_bundle_selector (const2_rtx); /* -> MFI */
                  break;
                }
-             else if (recog_memoized (last) != CODE_FOR_insn_group_barrier)
+             else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
+                      && (ia64_safe_itanium_class (last)
+                          != ITANIUM_CLASS_IGNORE))
                n++;
+           /* Some check of correctness: the stop is not at the
+              bundle start, there are no more 3 insns in the bundle,
+              and the MM-insn is not at the start of bundle with
+              template MLX.  */
            if ((pred_stop_p && n == 0) || n > 2
                || (template0 == 9 && n != 0))
              abort ();
+           /* Put nops after the insn in the bundle.  */
            for (j = 3 - n; j > 0; j --)
              ia64_emit_insn_before (gen_nop (), insn);
+           /* It takes into account that we will add more N nops
+              before the insn lately -- please see code below.  */
            add_cycles [INSN_UID (insn)]--;
            if (!pred_stop_p || add_cycles [INSN_UID (insn)])
              ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
@@ -6886,13 +6656,15 @@ bundling (dump, verbose, prev_head_insn, tail)
              add_cycles [INSN_UID (insn)]--;
            for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
              {
-               /* Insert .MII bundle.  */
-               ia64_emit_insn_before (gen_bundle_selector (GEN_INT (0)),
+               /* Insert "MII;" template.  */
+               ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
                                       insn);
                ia64_emit_insn_before (gen_nop (), insn);
                ia64_emit_insn_before (gen_nop (), insn);
                if (i > 1)
                  {
+                   /* To decrease code size, we use "MI;I;"
+                      template.  */
                    ia64_emit_insn_before
                      (gen_insn_group_barrier (GEN_INT (3)), insn);
                    i--;
@@ -6901,10 +6673,15 @@ bundling (dump, verbose, prev_head_insn, tail)
                ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
                                       insn);
              }
+           /* Put the MM-insn in the same slot of a bundle with the
+              same template as the original one.  */
            ia64_emit_insn_before (gen_bundle_selector (GEN_INT (template0)),
                                   insn);
+           /* To put the insn in the same slot, add necessary number
+              of nops.  */
            for (j = n; j > 0; j --)
              ia64_emit_insn_before (gen_nop (), insn);
+           /* Put the stop if the original bundle had it.  */
            if (pred_stop_p)
              ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
                                     insn);
@@ -6920,9 +6697,7 @@ bundling (dump, verbose, prev_head_insn, tail)
    EBB.  After reload, it inserts stop bits and does insn bundling.  */
 
 static void
-ia64_sched_finish (dump, sched_verbose)
-     FILE *dump;
-     int sched_verbose;
+ia64_sched_finish (FILE *dump, int sched_verbose)
 {
   if (sched_verbose)
     fprintf (dump, "// Finishing schedule.\n");
@@ -6937,7 +6712,7 @@ ia64_sched_finish (dump, sched_verbose)
        fprintf (dump, "//    finishing %d-%d\n",
                 INSN_UID (NEXT_INSN (current_sched_info->prev_head)),
                 INSN_UID (PREV_INSN (current_sched_info->next_tail)));
-      
+
       return;
     }
 }
@@ -6945,8 +6720,7 @@ ia64_sched_finish (dump, sched_verbose)
 /* The following function inserts stop bits in scheduled BB or EBB.  */
 
 static void
-final_emit_insn_group_barriers (dump)
-     FILE *dump ATTRIBUTE_UNUSED;
+final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
 {
   rtx insn;
   int need_barrier_p = 0;
@@ -6987,7 +6761,7 @@ final_emit_insn_group_barriers (dump)
              if (TARGET_EARLY_STOP_BITS)
                {
                  rtx last;
-                 
+
                  for (last = insn;
                       last != current_sched_info->prev_head;
                       last = PREV_INSN (last))
@@ -7032,16 +6806,7 @@ final_emit_insn_group_barriers (dump)
    insn scheduler.  */
 
 static int
-ia64_use_dfa_pipeline_interface ()
-{
-  return 1;
-}
-
-/* If the following function returns TRUE, we will use the the DFA
-   insn scheduler.  */
-
-static int
-ia64_first_cycle_multipass_dfa_lookahead ()
+ia64_first_cycle_multipass_dfa_lookahead (void)
 {
   return (reload_completed ? 6 : 4);
 }
@@ -7049,7 +6814,7 @@ ia64_first_cycle_multipass_dfa_lookahead ()
 /* The following function initiates variable `dfa_pre_cycle_insn'.  */
 
 static void
-ia64_init_dfa_pre_cycle_insn ()
+ia64_init_dfa_pre_cycle_insn (void)
 {
   if (temp_dfa_state == NULL)
     {
@@ -7069,7 +6834,7 @@ ia64_init_dfa_pre_cycle_insn ()
    used by the DFA insn scheduler.  */
 
 static rtx
-ia64_dfa_pre_cycle_insn ()
+ia64_dfa_pre_cycle_insn (void)
 {
   return dfa_pre_cycle_insn;
 }
@@ -7078,9 +6843,7 @@ ia64_dfa_pre_cycle_insn ()
    ld) produces address for CONSUMER (of type st or stf). */
 
 int
-ia64_st_address_bypass_p (producer, consumer)
-     rtx producer;
-     rtx consumer;
+ia64_st_address_bypass_p (rtx producer, rtx consumer)
 {
   rtx dest, reg, mem;
 
@@ -7103,9 +6866,7 @@ ia64_st_address_bypass_p (producer, consumer)
    ld) produces address for CONSUMER (of type ld or fld). */
 
 int
-ia64_ld_address_bypass_p (producer, consumer)
-     rtx producer;
-     rtx consumer;
+ia64_ld_address_bypass_p (rtx producer, rtx consumer)
 {
   rtx dest, src, reg, mem;
 
@@ -7134,11 +6895,10 @@ ia64_ld_address_bypass_p (producer, consumer)
 
 /* The following function returns TRUE if INSN produces address for a
    load/store insn.  We will place such insns into M slot because it
-   decreases its latency time. */
+   decreases its latency time.  */
 
 int
-ia64_produce_address_p (insn)
-     rtx insn;
+ia64_produce_address_p (rtx insn)
 {
   return insn->call;
 }
@@ -7150,14 +6910,14 @@ ia64_produce_address_p (insn)
    straight-line code.  */
 
 static void
-emit_predicate_relation_info ()
+emit_predicate_relation_info (void)
 {
   basic_block bb;
 
   FOR_EACH_BB_REVERSE (bb)
     {
       int r;
-      rtx head = bb->head;
+      rtx head = BB_HEAD (bb);
 
       /* We only need such notes at code labels.  */
       if (GET_CODE (head) != CODE_LABEL)
@@ -7171,8 +6931,8 @@ emit_predicate_relation_info ()
          {
            rtx p = gen_rtx_REG (BImode, r);
            rtx n = emit_insn_after (gen_pred_rel_mutex (p), head);
-           if (head == bb->end)
-             bb->end = n;
+           if (head == BB_END (bb))
+             BB_END (bb) = n;
            head = n;
          }
     }
@@ -7183,8 +6943,8 @@ emit_predicate_relation_info ()
      the call.  */
   FOR_EACH_BB_REVERSE (bb)
     {
-      rtx insn = bb->head;
-      
+      rtx insn = BB_HEAD (bb);
+
       while (1)
        {
          if (GET_CODE (insn) == CALL_INSN
@@ -7193,13 +6953,13 @@ emit_predicate_relation_info ()
            {
              rtx b = emit_insn_before (gen_safe_across_calls_all (), insn);
              rtx a = emit_insn_after (gen_safe_across_calls_normal (), insn);
-             if (bb->head == insn)
-               bb->head = b;
-             if (bb->end == insn)
-               bb->end = a;
+             if (BB_HEAD (bb) == insn)
+               BB_HEAD (bb) = b;
+             if (BB_END (bb) == insn)
+               BB_END (bb) = a;
            }
-         
-         if (insn == bb->end)
+
+         if (insn == BB_END (bb))
            break;
          insn = NEXT_INSN (insn);
        }
@@ -7209,7 +6969,7 @@ emit_predicate_relation_info ()
 /* Perform machine dependent operations on the rtl chain INSNS.  */
 
 static void
-ia64_reorg ()
+ia64_reorg (void)
 {
   /* We are freeing block_for_insn in the toplev to keep compatibility
      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
@@ -7233,14 +6993,11 @@ ia64_reorg ()
       PREV_INSN (ia64_nop) = NEXT_INSN (ia64_nop) = NULL_RTX;
       recog_memoized (ia64_nop);
       clocks_length = get_max_uid () + 1;
-      stops_p = (char *) xmalloc (clocks_length);
-      memset (stops_p, 0, clocks_length);
+      stops_p = xcalloc (1, clocks_length);
       if (ia64_tune == PROCESSOR_ITANIUM)
        {
-         clocks = (int *) xmalloc (clocks_length * sizeof (int));
-         memset (clocks, 0, clocks_length * sizeof (int));
-         add_cycles = (int *) xmalloc (clocks_length * sizeof (int));
-         memset (add_cycles, 0, clocks_length * sizeof (int));
+         clocks = xcalloc (clocks_length, sizeof (int));
+         add_cycles = xcalloc (clocks_length, sizeof (int));
        }
       if (ia64_tune == PROCESSOR_ITANIUM2)
        {
@@ -7300,7 +7057,7 @@ ia64_reorg ()
          _1mfb_ = get_cpu_unit_code ("1b_1mfb.");
          _1mlx_ = get_cpu_unit_code ("1b_1mlx.");
        }
-      schedule_ebbs (rtl_dump_file);
+      schedule_ebbs (dump_file);
       finish_bundle_states ();
       if (ia64_tune == PROCESSOR_ITANIUM)
        {
@@ -7308,13 +7065,13 @@ ia64_reorg ()
          free (clocks);
        }
       free (stops_p);
-      emit_insn_group_barriers (rtl_dump_file);
+      emit_insn_group_barriers (dump_file);
 
       ia64_final_schedule = 0;
       timevar_pop (TV_SCHED2);
     }
   else
-    emit_all_insn_group_barriers (rtl_dump_file);
+    emit_all_insn_group_barriers (dump_file);
 
   /* A call must not be the last instruction in a function, so that the
      return address is still within the function, so that unwinding works
@@ -7327,11 +7084,12 @@ ia64_reorg ()
       insn = get_last_insn ();
       if (! INSN_P (insn))
         insn = prev_active_insn (insn);
-      if (GET_CODE (insn) == INSN
-         && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
-         && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
-       {
-         saw_stop = 1;
+      /* Skip over insns that expand to nothing.  */
+      while (GET_CODE (insn) == INSN && get_attr_empty (insn) == EMPTY_YES)
+        {
+         if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+             && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
+           saw_stop = 1;
          insn = prev_active_insn (insn);
        }
       if (GET_CODE (insn) == CALL_INSN)
@@ -7345,23 +7103,28 @@ ia64_reorg ()
 
   fixup_errata ();
   emit_predicate_relation_info ();
+
+  if (ia64_flag_var_tracking)
+    {
+      timevar_push (TV_VAR_TRACKING);
+      variable_tracking_main ();
+      timevar_pop (TV_VAR_TRACKING);
+    }
 }
 \f
 /* Return true if REGNO is used by the epilogue.  */
 
 int
-ia64_epilogue_uses (regno)
-     int regno;
+ia64_epilogue_uses (int regno)
 {
   switch (regno)
     {
     case R_GR (1):
-      /* When a function makes a call through a function descriptor, we
-         will write a (potentially) new value to "gp".  After returning
-         from such a call, we need to make sure the function restores the
-         original gp-value, even if the function itself does not use the
-         gp anymore.  */
-      return (TARGET_CONST_GP && !(TARGET_AUTO_PIC || TARGET_NO_PIC));
+      /* With a call to a function in another module, we will write a new
+        value to "gp".  After returning from such a call, we need to make
+        sure the function restores the original gp-value, even if the
+        function itself does not use the gp anymore.  */
+      return !(TARGET_AUTO_PIC || TARGET_NO_PIC);
 
     case IN_REG (0): case IN_REG (1): case IN_REG (2): case IN_REG (3):
     case IN_REG (4): case IN_REG (5): case IN_REG (6): case IN_REG (7):
@@ -7391,8 +7154,7 @@ ia64_epilogue_uses (regno)
 /* Return true if REGNO is used by the frame unwinder.  */
 
 int
-ia64_eh_uses (regno)
-     int regno;
+ia64_eh_uses (int regno)
 {
   if (! reload_completed)
     return 0;
@@ -7424,8 +7186,7 @@ ia64_eh_uses (regno)
    types which can't go in sdata/sbss.  */
 
 static bool
-ia64_in_small_data_p (exp)
-     tree exp;
+ia64_in_small_data_p (tree exp)
 {
   if (TARGET_NO_SDATA)
     return false;
@@ -7434,6 +7195,10 @@ ia64_in_small_data_p (exp)
   if (TREE_CODE (exp) == STRING_CST)
     return false;
 
+  /* Functions are never small data.  */
+  if (TREE_CODE (exp) == FUNCTION_DECL)
+    return false;
+
   if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
     {
       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
@@ -7467,7 +7232,7 @@ static bool need_copy_state;
 /* The function emits unwind directives for the start of an epilogue.  */
 
 static void
-process_epilogue ()
+process_epilogue (void)
 {
   /* If this isn't the last block of the function, then we need to label the
      current state, and copy it back in at the start of the next block.  */
@@ -7485,9 +7250,7 @@ process_epilogue ()
    which result in emitting an assembly directive required for unwinding.  */
 
 static int
-process_set (asm_out_file, pat)
-     FILE *asm_out_file;
-     rtx pat;
+process_set (FILE *asm_out_file, rtx pat)
 {
   rtx src = SET_SRC (pat);
   rtx dest = SET_DEST (pat);
@@ -7697,9 +7460,7 @@ process_set (asm_out_file, pat)
 /* This function looks at a single insn and emits any directives
    required to unwind this insn.  */
 void
-process_for_unwind_directive (asm_out_file, insn)
-     FILE *asm_out_file;
-     rtx insn;
+process_for_unwind_directive (FILE *asm_out_file, rtx insn)
 {
   if (flag_unwind_tables
       || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
@@ -7756,7 +7517,7 @@ process_for_unwind_directive (asm_out_file, insn)
 
 \f
 void
-ia64_init_builtins ()
+ia64_init_builtins (void)
 {
   tree psi_type_node = build_pointer_type (integer_type_node);
   tree pdi_type_node = build_pointer_type (long_integer_type_node);
@@ -7800,8 +7561,39 @@ ia64_init_builtins ()
   tree void_ftype_pdi
     = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
 
-#define def_builtin(name, type, code) \
-  builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
+  tree fpreg_type;
+  tree float80_type;
+
+  /* The __fpreg type.  */
+  fpreg_type = make_node (REAL_TYPE);
+  /* ??? The back end should know to load/save __fpreg variables using
+     the ldf.fill and stf.spill instructions.  */
+  TYPE_PRECISION (fpreg_type) = 80;
+  layout_type (fpreg_type);
+  (*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
+
+  /* The __float80 type.  */
+  float80_type = make_node (REAL_TYPE);
+  TYPE_PRECISION (float80_type) = 80;
+  layout_type (float80_type);
+  (*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
+
+  /* The __float128 type.  */
+  if (!TARGET_HPUX)
+    {
+      tree float128_type = make_node (REAL_TYPE);
+      TYPE_PRECISION (float128_type) = 128;
+      layout_type (float128_type);
+      (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
+    }
+  else
+    /* Under HPUX, this is a synonym for "long double".  */
+    (*lang_hooks.types.register_builtin_type) (long_double_type_node,
+                                              "__float128");
+
+#define def_builtin(name, type, code)                                  \
+  lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD,    \
+                              NULL, NULL_TREE)
 
   def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
               IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
@@ -7828,8 +7620,8 @@ ia64_init_builtins ()
               build_function_type (ptr_type_node, void_list_node),
               IA64_BUILTIN_BSP);
 
-  def_builtin ("__builtin_ia64_flushrs", 
-              build_function_type (void_type_node, void_list_node), 
+  def_builtin ("__builtin_ia64_flushrs",
+              build_function_type (void_type_node, void_list_node),
               IA64_BUILTIN_FLUSHRS);
 
   def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
@@ -7900,11 +7692,8 @@ ia64_init_builtins ()
 */
 
 static rtx
-ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
-     optab binoptab;
-     enum machine_mode mode;
-     tree arglist;
-     rtx target;
+ia64_expand_fetch_and_op (optab binoptab, enum machine_mode mode,
+                         tree arglist, rtx target)
 {
   rtx ret, label, tmp, ccv, insn, mem, value;
   tree arg0, arg1;
@@ -7940,13 +7729,14 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
     }
 
   tmp = gen_reg_rtx (mode);
-  ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
+  /* ar.ccv must always be loaded with a zero-extended DImode value.  */
+  ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
   emit_move_insn (tmp, mem);
 
   label = gen_label_rtx ();
   emit_label (label);
   emit_move_insn (ret, tmp);
-  emit_move_insn (ccv, tmp);
+  convert_move (ccv, tmp, /*unsignedp=*/1);
 
   /* Perform the specific operation.  Special case NAND by noticing
      one_cmpl_optab instead.  */
@@ -7981,11 +7771,8 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
 */
 
 static rtx
-ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
-     optab binoptab;
-     enum machine_mode mode;
-     tree arglist;
-     rtx target;
+ia64_expand_op_and_fetch (optab binoptab, enum machine_mode mode,
+                         tree arglist, rtx target)
 {
   rtx old, label, tmp, ret, ccv, insn, mem, value;
   tree arg0, arg1;
@@ -8009,14 +7796,15 @@ ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
   emit_insn (gen_mf ());
   tmp = gen_reg_rtx (mode);
   old = gen_reg_rtx (mode);
-  ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
+  /* ar.ccv must always be loaded with a zero-extended DImode value.  */
+  ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
 
   emit_move_insn (tmp, mem);
 
   label = gen_label_rtx ();
   emit_label (label);
   emit_move_insn (old, tmp);
-  emit_move_insn (ccv, tmp);
+  convert_move (ccv, tmp, /*unsignedp=*/1);
 
   /* Perform the specific operation.  Special case NAND by noticing
      one_cmpl_optab instead.  */
@@ -8049,12 +7837,8 @@ ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
 */
 
 static rtx
-ia64_expand_compare_and_swap (rmode, mode, boolp, arglist, target)
-     enum machine_mode rmode;
-     enum machine_mode mode;
-     int boolp;
-     tree arglist;
-     rtx target;
+ia64_expand_compare_and_swap (enum machine_mode rmode, enum machine_mode mode,
+                             int boolp, tree arglist, rtx target)
 {
   tree arg0, arg1, arg2;
   rtx mem, old, new, ccv, tmp, insn;
@@ -8069,6 +7853,11 @@ ia64_expand_compare_and_swap (rmode, mode, boolp, arglist, target)
   mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
   MEM_VOLATILE_P (mem) = 1;
 
+  if (GET_MODE (old) != mode)
+    old = convert_to_mode (mode, old, /*unsignedp=*/1);
+  if (GET_MODE (new) != mode)
+    new = convert_to_mode (mode, new, /*unsignedp=*/1);
+
   if (! register_operand (old, mode))
     old = copy_to_mode_reg (mode, old);
   if (! register_operand (new, mode))
@@ -8080,14 +7869,7 @@ ia64_expand_compare_and_swap (rmode, mode, boolp, arglist, target)
     tmp = gen_reg_rtx (mode);
 
   ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
-  if (mode == DImode)
-    emit_move_insn (ccv, old);
-  else
-    {
-      rtx ccvtmp = gen_reg_rtx (DImode);
-      emit_insn (gen_zero_extendsidi2 (ccvtmp, old));
-      emit_move_insn (ccv, ccvtmp);
-    }
+  convert_move (ccv, old, /*unsignedp=*/1);
   emit_insn (gen_mf ());
   if (mode == SImode)
     insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
@@ -8108,10 +7890,8 @@ ia64_expand_compare_and_swap (rmode, mode, boolp, arglist, target)
 /* Expand lock_test_and_set.  I.e. `xchgsz ret = [ptr], new'.  */
 
 static rtx
-ia64_expand_lock_test_and_set (mode, arglist, target)
-     enum machine_mode mode;
-     tree arglist;
-     rtx target;
+ia64_expand_lock_test_and_set (enum machine_mode mode, tree arglist,
+                              rtx target)
 {
   tree arg0, arg1;
   rtx mem, new, ret, insn;
@@ -8143,10 +7923,8 @@ ia64_expand_lock_test_and_set (mode, arglist, target)
 /* Expand lock_release.  I.e. `stsz.rel [ptr] = r0'.  */
 
 static rtx
-ia64_expand_lock_release (mode, arglist, target)
-     enum machine_mode mode;
-     tree arglist;
-     rtx target ATTRIBUTE_UNUSED;
+ia64_expand_lock_release (enum machine_mode mode, tree arglist,
+                         rtx target ATTRIBUTE_UNUSED)
 {
   tree arg0;
   rtx mem;
@@ -8163,12 +7941,9 @@ ia64_expand_lock_release (mode, arglist, target)
 }
 
 rtx
-ia64_expand_builtin (exp, target, subtarget, mode, ignore)
-     tree exp;
-     rtx target;
-     rtx subtarget ATTRIBUTE_UNUSED;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     int ignore ATTRIBUTE_UNUSED;
+ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+                    enum machine_mode mode ATTRIBUTE_UNUSED,
+                    int ignore ATTRIBUTE_UNUSED)
 {
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
@@ -8327,9 +8102,7 @@ ia64_expand_builtin (exp, target, subtarget, mode, ignore)
    most significant bits of the stack slot.  */
 
 enum direction
-ia64_hpux_function_arg_padding (mode, type)
-     enum machine_mode mode;
-     tree type;
+ia64_hpux_function_arg_padding (enum machine_mode mode, tree type)
 {
    /* Exception to normal case for structures/unions/etc.  */
 
@@ -8337,35 +8110,28 @@ ia64_hpux_function_arg_padding (mode, type)
        && int_size_in_bytes (type) < UNITS_PER_WORD)
      return upward;
 
-   /* This is the standard FUNCTION_ARG_PADDING with !BYTES_BIG_ENDIAN
-      hardwired to be true.  */
-
-   return((mode == BLKmode
-       ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
-          && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
-       : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
-      ? downward : upward);
+   /* Fall back to the default.  */
+   return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
 }
 
 /* Linked list of all external functions that are to be emitted by GCC.
    We output the name if and only if TREE_SYMBOL_REFERENCED is set in
    order to avoid putting out names that are never really used.  */
 
-struct extern_func_list
+struct extern_func_list GTY(())
 {
-  struct extern_func_list *next; /* next external */
-  char *name;                    /* name of the external */
-} *extern_func_head = 0;
+  struct extern_func_list *next;
+  tree decl;
+};
+
+static GTY(()) struct extern_func_list *extern_func_head;
 
 static void
-ia64_hpux_add_extern_decl (name)
-        const char *name;
+ia64_hpux_add_extern_decl (tree decl)
 {
-  struct extern_func_list *p;
+  struct extern_func_list *p = ggc_alloc (sizeof (struct extern_func_list));
 
-  p = (struct extern_func_list *) xmalloc (sizeof (struct extern_func_list));
-  p->name = xmalloc (strlen (name) + 1);
-  strcpy(p->name, name);
+  p->decl = decl;
   p->next = extern_func_head;
   extern_func_head = p;
 }
@@ -8373,42 +8139,134 @@ ia64_hpux_add_extern_decl (name)
 /* Print out the list of used global functions.  */
 
 static void
-ia64_hpux_file_end ()
+ia64_hpux_file_end (void)
 {
-  while (extern_func_head)
+  struct extern_func_list *p;
+
+  for (p = extern_func_head; p; p = p->next)
     {
-      const char *real_name;
-      tree decl;
+      tree decl = p->decl;
+      tree id = DECL_ASSEMBLER_NAME (decl);
 
-      real_name = (* targetm.strip_name_encoding) (extern_func_head->name);
-      decl = maybe_get_identifier (real_name);
+      if (!id)
+       abort ();
 
-      if (!decl
-         || (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)))
+      if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
         {
-         if (decl)
-           TREE_ASM_WRITTEN (decl) = 1;
-         (*targetm.asm_out.globalize_label) (asm_out_file,
-                                             extern_func_head->name);
+         const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+
+         TREE_ASM_WRITTEN (decl) = 1;
+         (*targetm.asm_out.globalize_label) (asm_out_file, name);
          fputs (TYPE_ASM_OP, asm_out_file);
-         assemble_name (asm_out_file, extern_func_head->name);
-         putc (',', asm_out_file);
-         fprintf (asm_out_file, TYPE_OPERAND_FMT, "function");
-         putc ('\n', asm_out_file);
+         assemble_name (asm_out_file, name);
+         fprintf (asm_out_file, "," TYPE_OPERAND_FMT "\n", "function");
         }
-      extern_func_head = extern_func_head->next;
     }
+
+  extern_func_head = 0;
+}
+
+/* Set SImode div/mod functions, init_integral_libfuncs only initializes
+   modes of word_mode and larger.  Rename the TFmode libfuncs using the
+   HPUX conventions. __divtf3 is used for XFmode. We need to keep it for
+   backward compatibility. */
+
+static void
+ia64_init_libfuncs (void)
+{
+  set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
+  set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
+  set_optab_libfunc (smod_optab, SImode, "__modsi3");
+  set_optab_libfunc (umod_optab, SImode, "__umodsi3");
+
+  set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
+  set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
+  set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
+  set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
+  set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
+
+  set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+  set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+  set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
+  set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+  set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+  set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
+
+  set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
+  set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+  set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
+  set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
+
+  set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+  set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+}
+
+/* Rename all the TFmode libfuncs using the HPUX conventions.  */
+
+static void
+ia64_hpux_init_libfuncs (void)
+{
+  ia64_init_libfuncs ();
+
+  set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
+  set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
+  set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
+
+  /* ia64_expand_compare uses this.  */
+  cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
+
+  /* These should never be used.  */
+  set_optab_libfunc (eq_optab, TFmode, 0);
+  set_optab_libfunc (ne_optab, TFmode, 0);
+  set_optab_libfunc (gt_optab, TFmode, 0);
+  set_optab_libfunc (ge_optab, TFmode, 0);
+  set_optab_libfunc (lt_optab, TFmode, 0);
+  set_optab_libfunc (le_optab, TFmode, 0);
+}
+
+/* Rename the division and modulus functions in VMS.  */
+
+static void
+ia64_vms_init_libfuncs (void)
+{
+  set_optab_libfunc (sdiv_optab, SImode, "OTS$DIV_I");
+  set_optab_libfunc (sdiv_optab, DImode, "OTS$DIV_L");
+  set_optab_libfunc (udiv_optab, SImode, "OTS$DIV_UI");
+  set_optab_libfunc (udiv_optab, DImode, "OTS$DIV_UL");
+  set_optab_libfunc (smod_optab, SImode, "OTS$REM_I");
+  set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
+  set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
+  set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
 }
 
+/* Rename the TFmode libfuncs available from soft-fp in glibc using
+   the HPUX conventions.  */
+
+static void
+ia64_sysv4_init_libfuncs (void)
+{
+  ia64_init_libfuncs ();
+
+  /* These functions are not part of the HPUX TFmode interface.  We
+     use them instead of _U_Qfcmp, which doesn't work the way we
+     expect.  */
+  set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+  set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+  set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+  set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+  set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+  set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
+
+  /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
+     glibc doesn't have them.  */
+}
 \f
 /* Switch to the section to which we should output X.  The only thing
    special we do here is to honor small data.  */
 
 static void
-ia64_select_rtx_section (mode, x, align)
-     enum machine_mode mode;
-     rtx x;
-     unsigned HOST_WIDE_INT align;
+ia64_select_rtx_section (enum machine_mode mode, rtx x,
+                        unsigned HOST_WIDE_INT align)
 {
   if (GET_MODE_SIZE (mode) > 0
       && GET_MODE_SIZE (mode) <= ia64_section_threshold)
@@ -8421,27 +8279,20 @@ ia64_select_rtx_section (mode, x, align)
    Pretend flag_pic is always set.  */
 
 static void
-ia64_rwreloc_select_section (exp, reloc, align)
-     tree exp;
-     int reloc;
-     unsigned HOST_WIDE_INT align;
+ia64_rwreloc_select_section (tree exp, int reloc, unsigned HOST_WIDE_INT align)
 {
   default_elf_select_section_1 (exp, reloc, align, true);
 }
 
 static void
-ia64_rwreloc_unique_section (decl, reloc)
-     tree decl;
-     int reloc;
+ia64_rwreloc_unique_section (tree decl, int reloc)
 {
   default_unique_section_1 (decl, reloc, true);
 }
 
 static void
-ia64_rwreloc_select_rtx_section (mode, x, align)
-     enum machine_mode mode;
-     rtx x;
-     unsigned HOST_WIDE_INT align;
+ia64_rwreloc_select_rtx_section (enum machine_mode mode, rtx x,
+                                unsigned HOST_WIDE_INT align)
 {
   int save_pic = flag_pic;
   flag_pic = 1;
@@ -8450,14 +8301,32 @@ ia64_rwreloc_select_rtx_section (mode, x, align)
 }
 
 static unsigned int
-ia64_rwreloc_section_type_flags (decl, name, reloc)
-     tree decl;
-     const char *name;
-     int reloc;
+ia64_rwreloc_section_type_flags (tree decl, const char *name, int reloc)
 {
   return default_section_type_flags_1 (decl, name, reloc, true);
 }
 
+/* Returns true if FNTYPE (a FUNCTION_TYPE or a METHOD_TYPE) returns a
+   structure type and that the address of that type should be passed
+   in out0, rather than in r8.  */
+
+static bool
+ia64_struct_retval_addr_is_first_parm_p (tree fntype)
+{
+  tree ret_type = TREE_TYPE (fntype);
+
+  /* The Itanium C++ ABI requires that out0, rather than r8, be used
+     as the structure return address parameter, if the return value
+     type has a non-trivial copy constructor or destructor.  It is not
+     clear if this same convention should be used for other
+     programming languages.  Until G++ 3.4, we incorrectly used r8 for
+     these return values.  */
+  return (abi_version_at_least (2)
+         && ret_type
+         && TYPE_MODE (ret_type) == BLKmode 
+         && TREE_ADDRESSABLE (ret_type)
+         && strcmp (lang_hooks.name, "GNU C++") == 0);
+}
 
 /* Output the assembler code for a thunk function.  THUNK_DECL is the
    declaration for the thunk function itself, FUNCTION is the decl for
@@ -8466,18 +8335,18 @@ ia64_rwreloc_section_type_flags (decl, name, reloc)
    *(*this + vcall_offset) should be added to THIS.  */
 
 static void
-ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
-     FILE *file;
-     tree thunk ATTRIBUTE_UNUSED;
-     HOST_WIDE_INT delta;
-     HOST_WIDE_INT vcall_offset;
-     tree function;
+ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+                     HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+                     tree function)
 {
   rtx this, insn, funexp;
+  unsigned int this_parmno;
+  unsigned int this_regno;
 
   reload_completed = 1;
   epilogue_completed = 1;
   no_new_pseudos = 1;
+  reset_block_changes ();
 
   /* Set things up as ia64_expand_prologue might.  */
   last_scratch_gr_reg = 15;
@@ -8487,13 +8356,32 @@ ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
   current_frame_info.n_input_regs = 1;
   current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
 
-  if (!TARGET_REG_NAMES)
-    reg_names[IN_REG (0)] = ia64_reg_numbers[0];
-
   /* Mark the end of the (empty) prologue.  */
-  emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+  emit_note (NOTE_INSN_PROLOGUE_END);
+
+  /* Figure out whether "this" will be the first parameter (the
+     typical case) or the second parameter (as happens when the
+     virtual function returns certain class objects).  */
+  this_parmno
+    = (ia64_struct_retval_addr_is_first_parm_p (TREE_TYPE (thunk))
+       ? 1 : 0);
+  this_regno = IN_REG (this_parmno);
+  if (!TARGET_REG_NAMES)
+    reg_names[this_regno] = ia64_reg_numbers[this_parmno];
 
-  this = gen_rtx_REG (Pmode, IN_REG (0));
+  this = gen_rtx_REG (Pmode, this_regno);
+  if (TARGET_ILP32)
+    {
+      rtx tmp = gen_rtx_REG (ptr_mode, this_regno);
+      REG_POINTER (tmp) = 1;
+      if (delta && CONST_OK_FOR_I (delta))
+       {
+         emit_insn (gen_ptr_extend_plus_imm (this, tmp, GEN_INT (delta)));
+         delta = 0;
+       }
+      else
+       emit_insn (gen_ptr_extend (this, tmp));
+    }
 
   /* Apply the constant offset, if required.  */
   if (delta)
@@ -8515,17 +8403,39 @@ ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
       rtx vcall_offset_rtx = GEN_INT (vcall_offset);
       rtx tmp = gen_rtx_REG (Pmode, 2);
 
-      emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
+      if (TARGET_ILP32)
+       {
+         rtx t = gen_rtx_REG (ptr_mode, 2);
+         REG_POINTER (t) = 1;
+         emit_move_insn (t, gen_rtx_MEM (ptr_mode, this));
+         if (CONST_OK_FOR_I (vcall_offset))
+           {
+             emit_insn (gen_ptr_extend_plus_imm (tmp, t, 
+                                                 vcall_offset_rtx));
+             vcall_offset = 0;
+           }
+         else
+           emit_insn (gen_ptr_extend (tmp, t));
+       }
+      else
+       emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
 
-      if (!CONST_OK_FOR_J (vcall_offset))
+      if (vcall_offset)
        {
-         rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
-         emit_move_insn (tmp2, vcall_offset_rtx);
-         vcall_offset_rtx = tmp2;
+         if (!CONST_OK_FOR_J (vcall_offset))
+           {
+             rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
+             emit_move_insn (tmp2, vcall_offset_rtx);
+             vcall_offset_rtx = tmp2;
+           }
+         emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
        }
-      emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
 
-      emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
+      if (TARGET_ILP32)
+       emit_move_insn (gen_rtx_REG (ptr_mode, 2), 
+                       gen_rtx_MEM (ptr_mode, tmp));
+      else
+       emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
 
       emit_insn (gen_adddi3 (this, this, tmp));
     }
@@ -8567,4 +8477,40 @@ ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
   no_new_pseudos = 0;
 }
 
+/* Worker function for TARGET_STRUCT_VALUE_RTX.  */
+
+static rtx
+ia64_struct_value_rtx (tree fntype,
+                      int incoming ATTRIBUTE_UNUSED)
+{
+  if (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype))
+    return NULL_RTX;
+  return gen_rtx_REG (Pmode, GR_REG (8));
+}
+
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+  switch (mode)
+    {
+    case QImode:
+    case HImode:
+    case SImode:
+    case DImode:
+    case TImode:
+      return true;
+
+    case SFmode:
+    case DFmode:
+    case XFmode:
+      return true;
+
+    case TFmode:
+      return TARGET_HPUX;
+
+    default:
+      return false;
+    }
+}
+
 #include "gt-ia64.h"