]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/config/alpha/alpha.c
flags.h (g_switch_value): Change to an unsigned HOST_WIDE_INT.
[gcc.git] / gcc / config / alpha / alpha.c
index 91cbc12607680d1b66143cc327f70fc4f4df17da..76f399e3c6e15119f1d5eb7ef5893763b50ec392 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on the DEC Alpha.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 /* Subroutines used for code generation on the DEC Alpha.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002 Free Software Foundation, Inc. 
+   2000, 2001, 2002, 2003 Free Software Foundation, Inc. 
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tree.h"
 #include "regs.h"
 #include "rtl.h"
 #include "tree.h"
 #include "regs.h"
@@ -48,6 +50,7 @@ Boston, MA 02111-1307, USA.  */
 #include "target-def.h"
 #include "debug.h"
 #include "langhooks.h"
 #include "target-def.h"
 #include "debug.h"
 #include "langhooks.h"
+#include <splay-tree.h>
 
 /* Specify which cpu to schedule for.  */
 
 
 /* Specify which cpu to schedule for.  */
 
@@ -88,7 +91,7 @@ const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] */
 
 struct alpha_compare alpha_compare;
 
 
 struct alpha_compare alpha_compare;
 
-/* Non-zero if inside of a function, because the Alpha asm can't
+/* Nonzero if inside of a function, because the Alpha asm can't
    handle .files inside of functions.  */
 
 static int inside_function = FALSE;
    handle .files inside of functions.  */
 
 static int inside_function = FALSE;
@@ -103,37 +106,92 @@ static int alpha_function_needs_gp;
 
 /* The alias set for prologue/epilogue register save/restore.  */
 
 
 /* The alias set for prologue/epilogue register save/restore.  */
 
-static int alpha_sr_alias_set;
+static GTY(()) int alpha_sr_alias_set;
 
 /* The assembler name of the current function.  */
 
 static const char *alpha_fnname;
 
 /* The next explicit relocation sequence number.  */
 
 /* The assembler name of the current function.  */
 
 static const char *alpha_fnname;
 
 /* The next explicit relocation sequence number.  */
+extern GTY(()) int alpha_next_sequence_number;
 int alpha_next_sequence_number = 1;
 
 /* The literal and gpdisp sequence numbers for this insn, as printed
    by %# and %* respectively.  */
 int alpha_next_sequence_number = 1;
 
 /* The literal and gpdisp sequence numbers for this insn, as printed
    by %# and %* respectively.  */
+extern GTY(()) int alpha_this_literal_sequence_number;
+extern GTY(()) int alpha_this_gpdisp_sequence_number;
 int alpha_this_literal_sequence_number;
 int alpha_this_gpdisp_sequence_number;
 
 int alpha_this_literal_sequence_number;
 int alpha_this_gpdisp_sequence_number;
 
+/* Costs of various operations on the different architectures.  */
+
+struct alpha_rtx_cost_data
+{
+  unsigned char fp_add;
+  unsigned char fp_mult;
+  unsigned char fp_div_sf;
+  unsigned char fp_div_df;
+  unsigned char int_mult_si;
+  unsigned char int_mult_di;
+  unsigned char int_shift;
+  unsigned char int_cmov;
+};
+
+static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] =
+{
+  { /* EV4 */
+    COSTS_N_INSNS (6),         /* fp_add */
+    COSTS_N_INSNS (6),         /* fp_mult */
+    COSTS_N_INSNS (34),                /* fp_div_sf */
+    COSTS_N_INSNS (63),                /* fp_div_df */
+    COSTS_N_INSNS (23),                /* int_mult_si */
+    COSTS_N_INSNS (23),                /* int_mult_di */
+    COSTS_N_INSNS (2),         /* int_shift */
+    COSTS_N_INSNS (2),         /* int_cmov */
+  },
+  { /* EV5 */
+    COSTS_N_INSNS (4),         /* fp_add */
+    COSTS_N_INSNS (4),         /* fp_mult */
+    COSTS_N_INSNS (15),                /* fp_div_sf */
+    COSTS_N_INSNS (22),                /* fp_div_df */
+    COSTS_N_INSNS (8),         /* int_mult_si */
+    COSTS_N_INSNS (12),                /* int_mult_di */
+    COSTS_N_INSNS (1) + 1,     /* int_shift */
+    COSTS_N_INSNS (1),         /* int_cmov */
+  },
+  { /* EV6 */
+    COSTS_N_INSNS (4),         /* fp_add */
+    COSTS_N_INSNS (4),         /* fp_mult */
+    COSTS_N_INSNS (12),                /* fp_div_sf */
+    COSTS_N_INSNS (15),                /* fp_div_df */
+    COSTS_N_INSNS (7),         /* int_mult_si */
+    COSTS_N_INSNS (7),         /* int_mult_di */
+    COSTS_N_INSNS (1),         /* int_shift */
+    COSTS_N_INSNS (2),         /* int_cmov */
+  },
+};
+
 /* Declarations of static functions.  */
 /* Declarations of static functions.  */
+static bool alpha_function_ok_for_sibcall
+  PARAMS ((tree, tree));
 static int tls_symbolic_operand_1
   PARAMS ((rtx, enum machine_mode, int, int));
 static enum tls_model tls_symbolic_operand_type
   PARAMS ((rtx));
 static int tls_symbolic_operand_1
   PARAMS ((rtx, enum machine_mode, int, int));
 static enum tls_model tls_symbolic_operand_type
   PARAMS ((rtx));
-static bool decl_in_text_section
+static bool decl_has_samegp
   PARAMS ((tree));
 static bool alpha_in_small_data_p
   PARAMS ((tree));
   PARAMS ((tree));
 static bool alpha_in_small_data_p
   PARAMS ((tree));
-static void alpha_encode_section_info
-  PARAMS ((tree, int));
-static const char *alpha_strip_name_encoding
-  PARAMS ((const char *));
+static rtx get_tls_get_addr
+  PARAMS ((void));
 static int some_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
 static int split_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
 static int some_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
 static int split_small_symbolic_operand_1
   PARAMS ((rtx *, void *));
+static bool alpha_cannot_copy_insn_p
+  PARAMS ((rtx));
+static bool alpha_rtx_costs
+  PARAMS ((rtx, int, int, int *));
 static void alpha_set_memflags_1
   PARAMS ((rtx, int, int, int));
 static rtx alpha_emit_set_const_1
 static void alpha_set_memflags_1
   PARAMS ((rtx, int, int, int));
 static rtx alpha_emit_set_const_1
@@ -142,9 +200,13 @@ static void alpha_expand_unaligned_load_words
   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
 static void alpha_expand_unaligned_store_words
   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
 static void alpha_expand_unaligned_store_words
   PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
+static void alpha_init_builtins
+  PARAMS ((void));
+static rtx alpha_expand_builtin
+  PARAMS ((tree, rtx, rtx, enum machine_mode, int));
 static void alpha_sa_mask
   PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
 static void alpha_sa_mask
   PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
-static int find_lo_sum
+static int find_lo_sum_using_gp
   PARAMS ((rtx *, void *));
 static int alpha_does_function_need_gp
   PARAMS ((void));
   PARAMS ((rtx *, void *));
 static int alpha_does_function_need_gp
   PARAMS ((void));
@@ -178,18 +240,30 @@ static int alpha_use_dfa_pipeline_interface
   PARAMS ((void));
 static int alpha_multipass_dfa_lookahead
   PARAMS ((void));
   PARAMS ((void));
 static int alpha_multipass_dfa_lookahead
   PARAMS ((void));
+static void alpha_reorg
+  PARAMS ((void));
 
 #ifdef OBJECT_FORMAT_ELF
 static void alpha_elf_select_rtx_section
   PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
 #endif
 
 
 #ifdef OBJECT_FORMAT_ELF
 static void alpha_elf_select_rtx_section
   PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
 #endif
 
-static void alpha_init_machine_status
-  PARAMS ((struct function *p));
-static void alpha_mark_machine_status
-  PARAMS ((struct function *p));
-static void alpha_free_machine_status
-  PARAMS ((struct function *p));
+#if TARGET_ABI_OPEN_VMS
+static bool alpha_linkage_symbol_p
+  PARAMS ((const char *symname));
+static int alpha_write_one_linkage
+  PARAMS ((splay_tree_node, void *));
+static void alpha_write_linkage
+  PARAMS ((FILE *, const char *, tree));
+#endif
+
+#if TARGET_ABI_OSF
+static void alpha_output_mi_thunk_osf
+  PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+#endif
+
+static struct machine_function * alpha_init_machine_status
+  PARAMS ((void));
 
 static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
 static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
 
 static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
 static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
@@ -221,10 +295,6 @@ static void vms_asm_out_destructor PARAMS ((rtx, int));
 
 #undef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
 
 #undef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding
 
 #if TARGET_ABI_UNICOSMK
 static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
 
 #if TARGET_ABI_UNICOSMK
 static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
@@ -238,6 +308,8 @@ static void unicosmk_unique_section PARAMS ((tree, int));
 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
 # undef TARGET_ASM_UNIQUE_SECTION
 # define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section
 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
 # undef TARGET_ASM_UNIQUE_SECTION
 # define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section
+# undef TARGET_ASM_GLOBALIZE_LABEL
+# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void
 #endif
 
 #undef TARGET_ASM_ALIGNED_HI_OP
 #endif
 
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -278,6 +350,31 @@ static void unicosmk_unique_section PARAMS ((tree, int));
 #undef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS HAVE_AS_TLS
 
 #undef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS HAVE_AS_TLS
 
+#undef  TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS alpha_init_builtins
+#undef  TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN alpha_expand_builtin
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p
+
+#if TARGET_ABI_OSF
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+#endif
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS alpha_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST hook_int_rtx_0
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Parse target option strings.  */
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Parse target option strings.  */
@@ -553,8 +650,14 @@ override_options ()
 
   /* Set up function hooks.  */
   init_machine_status = alpha_init_machine_status;
 
   /* Set up function hooks.  */
   init_machine_status = alpha_init_machine_status;
-  mark_machine_status = alpha_mark_machine_status;
-  free_machine_status = alpha_free_machine_status;
+
+  /* Tell the compiler when we're using VAX floating point.  */
+  if (TARGET_FLOAT_VAX)
+    {
+      real_format_for_mode[SFmode - QFmode] = &vax_f_format;
+      real_format_for_mode[DFmode - QFmode] = &vax_g_format;
+      real_format_for_mode[TFmode - QFmode] = NULL;
+    }
 }
 \f
 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
 }
 \f
 /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
@@ -610,6 +713,16 @@ reg_or_8bit_operand (op, mode)
          || register_operand (op, mode));
 }
 
          || register_operand (op, mode));
 }
 
+/* Return 1 if OP is a constant or any register.  */
+
+int
+reg_or_const_int_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  return GET_CODE (op) == CONST_INT || register_operand (op, mode);
+}
+
 /* Return 1 if OP is an 8-bit constant.  */
 
 int
 /* Return 1 if OP is an 8-bit constant.  */
 
 int
@@ -716,24 +829,26 @@ mode_mask_operand (op, mode)
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-#if HOST_BITS_PER_WIDE_INT == 32
-  if (GET_CODE (op) == CONST_DOUBLE)
-    return (CONST_DOUBLE_LOW (op) == -1
-           && (CONST_DOUBLE_HIGH (op) == -1
-               || CONST_DOUBLE_HIGH (op) == 0));
-#else
-  if (GET_CODE (op) == CONST_DOUBLE)
-    return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
-#endif
+  if (GET_CODE (op) == CONST_INT)
+    {
+      HOST_WIDE_INT value = INTVAL (op);
 
 
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) == 0xff
-             || INTVAL (op) == 0xffff
-             || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
-#if HOST_BITS_PER_WIDE_INT == 64
-             || INTVAL (op) == -1
-#endif
-             ));
+      if (value == 0xff)
+       return 1;
+      if (value == 0xffff)
+       return 1;
+      if (value == 0xffffffff)
+       return 1;
+      if (value == -1)
+       return 1;
+    }
+  else if (HOST_BITS_PER_WIDE_INT == 32 && GET_CODE (op) == CONST_DOUBLE)
+    {
+      if (CONST_DOUBLE_LOW (op) == 0xffffffff && CONST_DOUBLE_HIGH (op) == 0)
+       return 1;
+    }
+
+  return 0;
 }
 
 /* Return 1 if OP is a multiple of 8 less than 64.  */
 }
 
 /* Return 1 if OP is a multiple of 8 less than 64.  */
@@ -813,8 +928,15 @@ some_operand (op, mode)
 
   switch (GET_CODE (op))
     {
 
   switch (GET_CODE (op))
     {
-    case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
-    case SYMBOL_REF:  case CONST:  case HIGH:
+    case REG:
+    case MEM:
+    case CONST_INT:
+    case CONST_DOUBLE:
+    case CONST_VECTOR:
+    case LABEL_REF:
+    case SYMBOL_REF:
+    case CONST:
+    case HIGH:
       return 1;
 
     case SUBREG:
       return 1;
 
     case SUBREG:
@@ -893,7 +1015,8 @@ input_operand (op, mode)
              && general_operand (op, mode));
 
     case CONST_DOUBLE:
              && general_operand (op, mode));
 
     case CONST_DOUBLE:
-      return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
+    case CONST_VECTOR:
+      return op == CONST0_RTX (mode);
 
     case CONST_INT:
       return mode == QImode || mode == HImode || add_operand (op, mode);
 
     case CONST_INT:
       return mode == QImode || mode == HImode || add_operand (op, mode);
@@ -912,25 +1035,32 @@ input_operand (op, mode)
    file, and in the same section as the current function.  */
 
 int
    file, and in the same section as the current function.  */
 
 int
-current_file_function_operand (op, mode)
+samegp_function_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   if (GET_CODE (op) != SYMBOL_REF)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
+    return false;
 
   /* Easy test for recursion.  */
   if (op == XEXP (DECL_RTL (current_function_decl), 0))
 
   /* Easy test for recursion.  */
   if (op == XEXP (DECL_RTL (current_function_decl), 0))
-    return 1;
+    return true;
 
 
-  /* Otherwise, we need the DECL for the SYMBOL_REF, which we can't get.
-     So SYMBOL_REF_FLAG has been declared to imply that the function is
-     in the default text section.  So we must also check that the current
-     function is also in the text section.  */
-  if (SYMBOL_REF_FLAG (op) && decl_in_text_section (current_function_decl))
-    return 1;
+  /* Functions that are not local can be overridden, and thus may
+     not share the same gp.  */
+  if (! SYMBOL_REF_LOCAL_P (op))
+    return false;
 
 
-  return 0;
+  /* If -msmall-data is in effect, assume that there is only one GP
+     for the module, and so any local symbol has this property.  We
+     need explicit relocations to be able to enforce this for symbols
+     not defined in this unit of translation, however.  */
+  if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
+    return true;
+
+  /* Functions that are not external are defined in this UoT,
+     and thus must share the same gp.  */
+  return ! SYMBOL_REF_EXTERNAL_P (op);
 }
 
 /* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr.  */
 }
 
 /* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr.  */
@@ -940,32 +1070,60 @@ direct_call_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
      rtx op;
      enum machine_mode mode;
 {
-  /* Must be defined in this file.  */
-  if (! current_file_function_operand (op, mode))
-    return 0;
+  tree op_decl, cfun_sec, op_sec;
+
+  /* Must share the same GP.  */
+  if (!samegp_function_operand (op, mode))
+    return false;
 
   /* If profiling is implemented via linker tricks, we can't jump
 
   /* If profiling is implemented via linker tricks, we can't jump
-     to the nogp alternate entry point.  */
+     to the nogp alternate entry point.  Note that current_function_profile
+     would not be correct, since that doesn't indicate if the target
+     function uses profiling.  */
   /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
      but is approximately correct for the OSF ABIs.  Don't know
      what to do for VMS, NT, or UMK.  */
   /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
      but is approximately correct for the OSF ABIs.  Don't know
      what to do for VMS, NT, or UMK.  */
-  if (! TARGET_PROFILING_NEEDS_GP
-      && ! current_function_profile)
-    return 0;
+  if (!TARGET_PROFILING_NEEDS_GP && profile_flag)
+    return false;
 
 
-  return 1;
+  /* Must be a function.  In some cases folks create thunks in static
+     data structures and then make calls to them.  If we allow the
+     direct call, we'll get an error from the linker about !samegp reloc
+     against a symbol without a .prologue directive.  */
+  if (!SYMBOL_REF_FUNCTION_P (op))
+    return false;
+  
+  /* Must be "near" so that the branch is assumed to reach.  With
+     -msmall-text, this is assumed true of all local symbols.  Since
+     we've already checked samegp, locality is already assured.  */
+  if (TARGET_SMALL_TEXT)
+    return true;
+
+  /* Otherwise, a decl is "near" if it is defined in the same section.  */
+  if (flag_function_sections)
+    return false;
+
+  op_decl = SYMBOL_REF_DECL (op);
+  if (DECL_ONE_ONLY (current_function_decl)
+      || (op_decl && DECL_ONE_ONLY (op_decl)))
+    return false;
+
+  cfun_sec = DECL_SECTION_NAME (current_function_decl);
+  op_sec = op_decl ? DECL_SECTION_NAME (op_decl) : NULL;
+  return ((!cfun_sec && !op_sec)
+         || (cfun_sec && op_sec
+             && strcmp (TREE_STRING_POINTER (cfun_sec),
+                        TREE_STRING_POINTER (op_sec)) == 0));
 }
 
 /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
 }
 
 /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
-   a variable known to be defined in this file.  */
+   a (non-tls) variable known to be defined in this file.  */
 
 int
 local_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
 
 int
 local_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  const char *str;
-
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -980,26 +1138,7 @@ local_symbolic_operand (op, mode)
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  /* Easy pickings.  */
-  if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op))
-    return 1;
-
-  /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
-     run into problems with the rtl inliner in that the symbol was
-     once external, but is local after inlining, which results in
-     unrecognizable insns.  */
-
-  str = XSTR (op, 0);
-
-  /* If @[VS], then alpha_encode_section_info sez it's local.  */
-  if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S'))
-    return 1;
-
-  /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
-  if (str[0] == '*' && str[1] == '$')
-    return 1;
-
-  return 0;
+  return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
@@ -1010,8 +1149,6 @@ small_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  const char *str;
-
   if (! TARGET_SMALL_DATA)
     return 0;
 
   if (! TARGET_SMALL_DATA)
     return 0;
 
@@ -1026,13 +1163,14 @@ small_symbolic_operand (op, mode)
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
+  /* ??? There's no encode_section_info equivalent for the rtl
+     constant pool, so SYMBOL_FLAG_SMALL never gets set.  */
   if (CONSTANT_POOL_ADDRESS_P (op))
   if (CONSTANT_POOL_ADDRESS_P (op))
-    return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
-  else
-    {
-      str = XSTR (op, 0);
-      return str[0] == '@' && str[1] == 'S';
-    }
+    return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+
+  return (SYMBOL_REF_LOCAL_P (op)
+         && SYMBOL_REF_SMALL_P (op)
+         && SYMBOL_REF_TLS_MODEL (op) == 0);
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
@@ -1043,8 +1181,6 @@ global_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
      rtx op;
      enum machine_mode mode;
 {
-  const char *str;
-
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -1056,12 +1192,7 @@ global_symbolic_operand (op, mode)
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
-  if (local_symbolic_operand (op, mode))
-    return 0;
-
-  /* Also verify that it's not a TLS symbol.  */
-  str = XSTR (op, 0);
-  return str[0] != '%' && str[0] != '@';
+  return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
 }
 
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
 }
 
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
@@ -1122,9 +1253,6 @@ tls_symbolic_operand_1 (op, mode, size, unspec)
      enum machine_mode mode;
      int size, unspec;
 {
      enum machine_mode mode;
      int size, unspec;
 {
-  const char *str;
-  int letter;
-
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -1138,24 +1266,29 @@ tls_symbolic_operand_1 (op, mode, size, unspec)
 
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
 
   if (GET_CODE (op) != SYMBOL_REF)
     return 0;
-  str = XSTR (op, 0);
 
 
-  if (str[0] == '%')
+  if (SYMBOL_REF_LOCAL_P (op))
     {
     {
-      if (size != 64)
+      if (alpha_tls_size > size)
        return 0;
     }
        return 0;
     }
-  else if (str[0] == '@')
+  else
     {
     {
-      if (alpha_tls_size > size)
+      if (size != 64)
        return 0;
     }
        return 0;
     }
-  else
-    return 0;
-
-  letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T');
 
 
-  return str[1] == letter;
+  switch (SYMBOL_REF_TLS_MODEL (op))
+    {
+    case TLS_MODEL_LOCAL_DYNAMIC:
+      return unspec == UNSPEC_DTPREL;
+    case TLS_MODEL_INITIAL_EXEC:
+      return unspec == UNSPEC_TPREL && size == 64;
+    case TLS_MODEL_LOCAL_EXEC:
+      return unspec == UNSPEC_TPREL;
+    default:
+      abort ();
+    }
 }
 
 /* Return true if OP is valid for 16-bit DTP relative relocations.  */
 }
 
 /* Return true if OP is valid for 16-bit DTP relative relocations.  */
@@ -1615,7 +1748,9 @@ alpha_extra_constraint (value, c)
       return GET_CODE (value) == HIGH;
     case 'U':
       return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
       return GET_CODE (value) == HIGH;
     case 'U':
       return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
-
+    case 'W':
+      return (GET_CODE (value) == CONST_VECTOR
+             && value == CONST0_RTX (GET_MODE (value)));
     default:
       return false;
     }
     default:
       return false;
     }
@@ -1695,62 +1830,42 @@ static enum tls_model
 tls_symbolic_operand_type (symbol)
      rtx symbol;
 {
 tls_symbolic_operand_type (symbol)
      rtx symbol;
 {
-  const char *str;
+  enum tls_model model;
 
   if (GET_CODE (symbol) != SYMBOL_REF)
     return 0;
 
   if (GET_CODE (symbol) != SYMBOL_REF)
     return 0;
-  str = XSTR (symbol, 0);
+  model = SYMBOL_REF_TLS_MODEL (symbol);
 
 
-  if (str[0] == '%')
-    {
-      /* ??? Be prepared for -ftls-model=local-dynamic.  Perhaps we shouldn't
-        have separately encoded local-ness.  On well, maybe the user will use
-        attribute visibility next time.  At least we don't crash...  */
-      if (str[1] == 'G' || str[1] == 'D')
-       return TLS_MODEL_GLOBAL_DYNAMIC;
-      if (str[1] == 'T')
-       return TLS_MODEL_INITIAL_EXEC;
-    }
-  else if (str[0] == '@')
-    {
-      if (str[1] == 'D')
-       {
-         /* Local dynamic is a waste if we're not going to combine
-            the __tls_get_addr calls.  So avoid it if not optimizing.  */
-         if (optimize)
-           return TLS_MODEL_LOCAL_DYNAMIC;
-         else
-           return TLS_MODEL_GLOBAL_DYNAMIC;
-       }
-      if (str[1] == 'T')
-       {
-         /* 64-bit local exec is the same as initial exec except without
-            the dynamic relocation.  In either case we use a got entry.  */
-         if (alpha_tls_size == 64)
-           return TLS_MODEL_INITIAL_EXEC;
-         else
-           return TLS_MODEL_LOCAL_EXEC;
-       }
-    }
+  /* Local-exec with a 64-bit size is the same code as initial-exec.  */
+  if (model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64)
+    model = TLS_MODEL_INITIAL_EXEC;
 
 
-  return 0;
+  return model;
 }
 }
-
 \f
 \f
-/* Return true if the function DECL will be placed in the default text
-   section.  */
-/* ??? Ideally we'd be able to always move from a SYMBOL_REF back to the
-   decl, as that would allow us to determine if two functions are in the
-   same section, which is what we really want to know.  */
+/* Return true if the function DECL will share the same GP as any
+   function in the current unit of translation.  */
 
 static bool
 
 static bool
-decl_in_text_section (decl)
+decl_has_samegp (decl)
      tree decl;
 {
      tree decl;
 {
-  return (DECL_SECTION_NAME (decl) == NULL_TREE
-         && ! (flag_function_sections
-               || (targetm.have_named_sections
-                   && DECL_ONE_ONLY (decl))));
+  /* Functions that are not local can be overridden, and thus may
+     not share the same gp.  */
+  if (!(*targetm.binds_local_p) (decl))
+    return false;
+
+  /* If -msmall-data is in effect, assume that there is only one GP
+     for the module, and so any local symbol has this property.  We
+     need explicit relocations to be able to enforce this for symbols
+     not defined in this unit of translation, however.  */
+  if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
+    return true;
+
+  /* Functions that are not external are defined in this UoT.  */
+  /* ??? Irritatingly, static functions not yet emitted are still
+     marked "external".  Apply this to non-static functions only.  */
+  return !TREE_PUBLIC (decl) || !DECL_EXTERNAL (decl);
 }
 
 /* Return true if EXP should be placed in the small data section.  */
 }
 
 /* Return true if EXP should be placed in the small data section.  */
@@ -1776,142 +1891,34 @@ alpha_in_small_data_p (exp)
 
       /* If this is an incomplete type with size 0, then we can't put it
         in sdata because it might be too big when completed.  */
 
       /* If this is an incomplete type with size 0, then we can't put it
         in sdata because it might be too big when completed.  */
-      if (size > 0 && size <= g_switch_value)
+      if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
        return true;
     }
 
   return false;
 }
 
        return true;
     }
 
   return false;
 }
 
-/* If we are referencing a function that is static, make the SYMBOL_REF
-   special.  We use this to see indicate we can branch to this function
-   without setting PV or restoring GP. 
-
-   If this is a variable that is known to be defined locally, add "@v"
-   to the name.  If in addition the variable is to go in .sdata/.sbss,
-   then add "@s" instead.  */
-
-static void
-alpha_encode_section_info (decl, first)
-     tree decl;
-     int first ATTRIBUTE_UNUSED;
+#if TARGET_ABI_OPEN_VMS
+static bool
+alpha_linkage_symbol_p (symname)
+     const char *symname;
 {
 {
-  const char *symbol_str;
-  bool is_local;
-  char encoding = 0;
-  rtx rtl, symbol;
-
-  rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
-
-  /* Careful not to prod global register variables.  */
-  if (GET_CODE (rtl) != MEM)
-    return;
-  symbol = XEXP (rtl, 0);
-  if (GET_CODE (symbol) != SYMBOL_REF)
-    return;
-    
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      /* We mark public functions once they are emitted; otherwise we
-        don't know that they exist in this unit of translation.  */
-      if (TREE_PUBLIC (decl))
-       return;
-
-      /* Do not mark functions that are not in .text; otherwise we
-        don't know that they are near enough for a direct branch.  */
-      if (! decl_in_text_section (decl))
-       return;
-
-      SYMBOL_REF_FLAG (symbol) = 1;
-      return;
-    }
-
-  /* Early out if we're not going to do anything with this data.  */
-  if (! TARGET_EXPLICIT_RELOCS)
-    return;
-
-  symbol_str = XSTR (symbol, 0);
-
-  /* A variable is considered "local" if it is defined in this module.  */
-  is_local = (*targetm.binds_local_p) (decl);
-
-  /* Care for TLS variables.  */
-  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
-    {
-      enum tls_model kind;
-      if (!flag_pic)
-       {
-         if (is_local)
-           kind = TLS_MODEL_LOCAL_EXEC;
-         else
-           kind = TLS_MODEL_INITIAL_EXEC;
-       }
-      else if (is_local)
-       kind = TLS_MODEL_LOCAL_DYNAMIC;
-      else
-       kind = TLS_MODEL_GLOBAL_DYNAMIC;
-      if (kind < flag_tls_default)
-       kind = flag_tls_default;
-
-      switch (kind)
-       {
-       case TLS_MODEL_GLOBAL_DYNAMIC:
-         encoding = 'G';
-         break;
-       case TLS_MODEL_LOCAL_DYNAMIC:
-         encoding = 'D';
-         break;
-       case TLS_MODEL_INITIAL_EXEC:
-       case TLS_MODEL_LOCAL_EXEC:
-         encoding = 'T';
-         break;
-       }
-    }
-  else if (is_local)
-    {
-      /* Determine if DECL will wind up in .sdata/.sbss.  */
-      if (alpha_in_small_data_p (decl))
-       encoding = 'S';
-      else
-       encoding = 'L';
-    }
-
-  /* Finally, encode this into the symbol string.  */
-  if (encoding)
-    {
-      char *newstr;
-      size_t len;
+  int symlen = strlen (symname);
 
 
-      if (symbol_str[0] == (is_local ? '@' : '%'))
-       {
-         if (symbol_str[1] == encoding)
-           return;
-         symbol_str += 2;
-       }
+  if (symlen > 4)
+    return strcmp (&symname [symlen - 4], "..lk") == 0;
 
 
-      len = strlen (symbol_str) + 1;
-      newstr = alloca (len + 2);
-
-      newstr[0] = (is_local ? '@' : '%');
-      newstr[1] = encoding;
-      memcpy (newstr + 2, symbol_str, len);
-         
-      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
-    }
+  return false;
 }
 
 }
 
-/* Undo the effects of the above.  */
-
-static const char *
-alpha_strip_name_encoding (str)
-     const char *str;
-{
-  if (str[0] == '@' || str[0] == '%')
-    str += 2;
-  if (str[0] == '*')
-    str++;
-  return str;
-}
+#define LINKAGE_SYMBOL_REF_P(X) \
+  ((GET_CODE (X) == SYMBOL_REF   \
+    && alpha_linkage_symbol_p (XSTR (X, 0))) \
+   || (GET_CODE (X) == CONST                 \
+       && GET_CODE (XEXP (X, 0)) == PLUS     \
+       && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
+       && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0))))
+#endif
 
 /* legitimate_address_p recognizes an RTL expression that is a valid
    memory address for an instruction.  The MODE argument is the
 
 /* legitimate_address_p recognizes an RTL expression that is a valid
    memory address for an instruction.  The MODE argument is the
@@ -1952,6 +1959,11 @@ alpha_legitimate_address_p (mode, x, strict)
   if (CONSTANT_ADDRESS_P (x))
     return true;
 
   if (CONSTANT_ADDRESS_P (x))
     return true;
 
+#if TARGET_ABI_OPEN_VMS
+  if (LINKAGE_SYMBOL_REF_P (x))
+    return true;
+#endif
+
   /* Register plus a small constant offset is valid.  */
   if (GET_CODE (x) == PLUS)
     {
   /* Register plus a small constant offset is valid.  */
   if (GET_CODE (x) == PLUS)
     {
@@ -2017,6 +2029,18 @@ alpha_legitimate_address_p (mode, x, strict)
   return false;
 }
 
   return false;
 }
 
+/* Build the SYMBOL_REF for __tls_get_addr.  */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr ()
+{
+  if (!tls_get_addr_libfunc)
+    tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+  return tls_get_addr_libfunc;
+}
+
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.  */
 
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.  */
 
@@ -2084,7 +2108,7 @@ alpha_legitimize_address (x, scratch, mode)
 
          r0 = gen_rtx_REG (Pmode, 0);
          r16 = gen_rtx_REG (Pmode, 16);
 
          r0 = gen_rtx_REG (Pmode, 0);
          r16 = gen_rtx_REG (Pmode, 16);
-         tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+         tga = get_tls_get_addr ();
          dest = gen_reg_rtx (Pmode);
          seq = GEN_INT (alpha_next_sequence_number++);
          
          dest = gen_reg_rtx (Pmode);
          seq = GEN_INT (alpha_next_sequence_number++);
          
@@ -2105,7 +2129,7 @@ alpha_legitimize_address (x, scratch, mode)
 
          r0 = gen_rtx_REG (Pmode, 0);
          r16 = gen_rtx_REG (Pmode, 16);
 
          r0 = gen_rtx_REG (Pmode, 0);
          r16 = gen_rtx_REG (Pmode, 16);
-         tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+         tga = get_tls_get_addr ();
          scratch = gen_reg_rtx (Pmode);
          seq = GEN_INT (alpha_next_sequence_number++);
 
          scratch = gen_reg_rtx (Pmode);
          seq = GEN_INT (alpha_next_sequence_number++);
 
@@ -2208,6 +2232,25 @@ alpha_legitimize_address (x, scratch, mode)
   }
 }
 
   }
 }
 
+/* We do not allow indirect calls to be optimized into sibling calls, nor
+   can we allow a call to a function with a different GP to be optimized
+   into a sibcall.  */
+
+static bool
+alpha_function_ok_for_sibcall (decl, exp)
+     tree decl;
+     tree exp ATTRIBUTE_UNUSED;
+{
+  /* Can't do indirect tail calls, since we don't know if the target
+     uses the same GP.  */
+  if (!decl)
+    return false;
+
+  /* Otherwise, we can make a tail call if the target function shares
+     the same GP.  */
+  return decl_has_samegp (decl);
+}
+
 /* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
    small symbolic operand until after reload.  At which point we need
    to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
 /* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a
    small symbolic operand until after reload.  At which point we need
    to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
@@ -2265,6 +2308,49 @@ split_small_symbolic_operand_1 (px, data)
   return 0;
 }
 
   return 0;
 }
 
+/* Indicate that INSN cannot be duplicated.  This is true for any insn
+   that we've marked with gpdisp relocs, since those have to stay in
+   1-1 correspondence with one another.
+
+   Techinically we could copy them if we could set up a mapping from one
+   sequence number to another, across the set of insns to be duplicated.
+   This seems overly complicated and error-prone since interblock motion
+   from sched-ebb could move one of the pair of insns to a different block.  */
+
+static bool
+alpha_cannot_copy_insn_p (insn)
+     rtx insn;
+{
+  rtx pat;
+
+  if (!reload_completed || !TARGET_EXPLICIT_RELOCS)
+    return false;
+
+  if (GET_CODE (insn) != INSN)
+    return false;
+  if (asm_noperands (insn) >= 0)
+    return false;
+
+  pat = PATTERN (insn);
+  if (GET_CODE (pat) != SET)
+    return false;
+  pat = SET_SRC (pat);
+  if (GET_CODE (pat) == UNSPEC_VOLATILE)
+    {
+      if (XINT (pat, 1) == UNSPECV_LDGP1
+         || XINT (pat, 1) == UNSPECV_PLDGP2)
+       return true;
+    }
+  else if (GET_CODE (pat) == UNSPEC)
+    {
+      if (XINT (pat, 1) == UNSPEC_LDGP2)
+       return true;
+    }
+
+  return false;
+}
+
+  
 /* Try a machine-dependent way of reloading an illegitimate address
    operand.  If we find one, push the reload and return the new rtx.  */
    
 /* Try a machine-dependent way of reloading an illegitimate address
    operand.  If we find one, push the reload and return the new rtx.  */
    
@@ -2323,6 +2409,150 @@ alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
   return NULL_RTX;
 }
 \f
   return NULL_RTX;
 }
 \f
+/* Compute a (partial) cost for rtx X.  Return true if the complete
+   cost has been computed, and false if subexpressions should be
+   scanned.  In either case, *TOTAL contains the cost result.  */
+
+static bool
+alpha_rtx_costs (x, code, outer_code, total)
+     rtx x;
+     int code, outer_code;
+     int *total;
+{
+  enum machine_mode mode = GET_MODE (x);
+  bool float_mode_p = FLOAT_MODE_P (mode);
+
+  switch (code)
+    {
+      /* If this is an 8-bit constant, return zero since it can be used
+        nearly anywhere with no cost.  If it is a valid operand for an
+        ADD or AND, likewise return 0 if we know it will be used in that
+        context.  Otherwise, return 2 since it might be used there later.
+        All other constants take at least two insns.  */
+    case CONST_INT:
+      if (INTVAL (x) >= 0 && INTVAL (x) < 256)
+       {
+         *total = 0;
+         return true;
+       }
+      /* FALLTHRU */
+
+    case CONST_DOUBLE:
+      if (x == CONST0_RTX (mode))
+       *total = 0;
+      else if ((outer_code == PLUS && add_operand (x, VOIDmode))
+              || (outer_code == AND && and_operand (x, VOIDmode)))
+       *total = 0;
+      else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode))
+       *total = 2;
+      else
+       *total = COSTS_N_INSNS (2);
+      return true;
+      
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode))
+       *total = COSTS_N_INSNS (outer_code != MEM);
+      else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode))
+       *total = COSTS_N_INSNS (1 + (outer_code != MEM));
+      else if (tls_symbolic_operand_type (x))
+       /* Estimate of cost for call_pal rduniq.  */
+       *total = COSTS_N_INSNS (15);
+      else
+       /* Otherwise we do a load from the GOT.  */
+       *total = COSTS_N_INSNS (alpha_memory_latency);
+      return true;
+    
+    case PLUS:
+    case MINUS:
+      if (float_mode_p)
+       *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+      else if (GET_CODE (XEXP (x, 0)) == MULT
+              && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
+       {
+         *total = (rtx_cost (XEXP (XEXP (x, 0), 0), outer_code)
+                   + rtx_cost (XEXP (x, 1), outer_code) + 2);
+         return true;
+       }
+      return false;
+
+    case MULT:
+      if (float_mode_p)
+       *total = alpha_rtx_cost_data[alpha_cpu].fp_mult;
+      else if (mode == DImode)
+       *total = alpha_rtx_cost_data[alpha_cpu].int_mult_di;
+      else
+       *total = alpha_rtx_cost_data[alpha_cpu].int_mult_si;
+      return false;
+
+    case ASHIFT:
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT
+         && INTVAL (XEXP (x, 1)) <= 3)
+       {
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+      /* FALLTHRU */
+
+    case ASHIFTRT:
+    case LSHIFTRT:
+      *total = alpha_rtx_cost_data[alpha_cpu].int_shift;
+      return false;
+
+    case IF_THEN_ELSE:
+      if (float_mode_p)
+        *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+      else
+        *total = alpha_rtx_cost_data[alpha_cpu].int_cmov;
+      return false;
+
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+      if (!float_mode_p)
+       *total = COSTS_N_INSNS (70);    /* ??? */
+      else if (mode == SFmode)
+        *total = alpha_rtx_cost_data[alpha_cpu].fp_div_sf;
+      else
+        *total = alpha_rtx_cost_data[alpha_cpu].fp_div_df;
+      return false;
+
+    case MEM:
+      *total = COSTS_N_INSNS (alpha_memory_latency);
+      return true;
+
+    case NEG:
+      if (! float_mode_p)
+       {
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+      /* FALLTHRU */
+
+    case ABS:
+      if (! float_mode_p)
+       {
+         *total = COSTS_N_INSNS (1) + alpha_rtx_cost_data[alpha_cpu].int_cmov;
+         return false;
+       }
+      /* FALLTHRU */
+
+    case FLOAT:
+    case UNSIGNED_FLOAT:
+    case FIX:
+    case UNSIGNED_FIX:
+    case FLOAT_EXTEND:
+    case FLOAT_TRUNCATE:
+      *total = alpha_rtx_cost_data[alpha_cpu].fp_add;
+      return false;
+
+    default:
+      return false;
+    }
+}
+\f
 /* REF is an alignable memory location.  Place an aligned SImode
    reference into *PALIGNED_MEM and the number of bits to shift into
    *PBITNUM.  SCRATCH is a free register for use in reloading out
 /* REF is an alignable memory location.  Place an aligned SImode
    reference into *PALIGNED_MEM and the number of bits to shift into
    *PBITNUM.  SCRATCH is a free register for use in reloading out
@@ -2494,6 +2724,8 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
   switch (GET_CODE (x))
     {
     case SEQUENCE:
   switch (GET_CODE (x))
     {
     case SEQUENCE:
+      abort ();
+
     case PARALLEL:
       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
        alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
     case PARALLEL:
       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
        alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
@@ -2528,11 +2760,11 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
     }
 }
 
     }
 }
 
-/* Given INSN, which is either an INSN or a SEQUENCE generated to
-   perform a memory operation, look for any MEMs in either a SET_DEST or
-   a SET_SRC and copy the in-struct, unchanging, and volatile flags from
-   REF into each of the MEMs found.  If REF is not a MEM, don't do
-   anything.  */
+/* Given INSN, which is an INSN list or the PATTERN of a single insn
+   generated to perform a memory operation, look for any MEMs in either
+   a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and
+   volatile flags from REF into each of the MEMs found.  If REF is not
+   a MEM, don't do anything.  */
 
 void
 alpha_set_memflags (insn, ref)
 
 void
 alpha_set_memflags (insn, ref)
@@ -2943,7 +3175,7 @@ alpha_expand_mov (mode, operands)
     }
 
   /* Otherwise we've nothing left but to drop the thing to memory.  */
     }
 
   /* Otherwise we've nothing left but to drop the thing to memory.  */
-  operands[1] = force_const_mem (DImode, operands[1]);
+  operands[1] = force_const_mem (mode, operands[1]);
   if (reload_in_progress)
     {
       emit_move_insn (operands[0], XEXP (operands[1], 0));
   if (reload_in_progress)
     {
       emit_move_insn (operands[0], XEXP (operands[1], 0));
@@ -3247,7 +3479,7 @@ alpha_emit_conditional_branch (code)
        }
       else
        {
        }
       else
        {
-         /* ??? We mark the the branch mode to be CCmode to prevent the
+         /* ??? We mark the branch mode to be CCmode to prevent the
             compare and branch from being combined, since the compare 
             insn follows IEEE rules that the branch does not.  */
          branch_mode = CCmode;
             compare and branch from being combined, since the compare 
             insn follows IEEE rules that the branch does not.  */
          branch_mode = CCmode;
@@ -3415,7 +3647,7 @@ alpha_emit_setcc (code)
 /* Rewrite a comparison against zero CMP of the form
    (CODE (cc0) (const_int 0)) so it can be written validly in
    a conditional move (if_then_else CMP ...).
 /* Rewrite a comparison against zero CMP of the form
    (CODE (cc0) (const_int 0)) so it can be written validly in
    a conditional move (if_then_else CMP ...).
-   If both of the operands that set cc0 are non-zero we must emit
+   If both of the operands that set cc0 are nonzero we must emit
    an insn to perform the compare (it can't be done within
    the conditional move).  */
 rtx
    an insn to perform the compare (it can't be done within
    the conditional move).  */
 rtx
@@ -3447,7 +3679,7 @@ alpha_emit_conditional_move (cmp, mode)
 
       /* If we have fp<->int register move instructions, do a cmov by
         performing the comparison in fp registers, and move the
 
       /* If we have fp<->int register move instructions, do a cmov by
         performing the comparison in fp registers, and move the
-        zero/non-zero value to integer registers, where we can then
+        zero/nonzero value to integer registers, where we can then
         use a normal cmov, or vice-versa.  */
 
       switch (code)
         use a normal cmov, or vice-versa.  */
 
       switch (code)
@@ -3834,7 +4066,7 @@ alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
       abort ();
     }
 
       abort ();
     }
 
-  tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func));
+  tmp = gen_rtx_MEM (QImode, init_one_libfunc (func));
   tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
                                        const0_rtx, const0_rtx));
   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
   tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
                                        const0_rtx, const0_rtx));
   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
@@ -3979,7 +4211,7 @@ alpha_split_tfmode_frobsign (operands, operation)
 
   alpha_split_tfmode_pair (operands);
 
 
   alpha_split_tfmode_pair (operands);
 
-  /* Detect three flavours of operand overlap.  */
+  /* Detect three flavors of operand overlap.  */
   move = 1;
   if (rtx_equal_p (operands[0], operands[2]))
     move = 0;
   move = 1;
   if (rtx_equal_p (operands[0], operands[2]))
     move = 0;
@@ -4225,17 +4457,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
          emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
          break;
        case 4:
          emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
          break;
        case 4:
-         emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr));
-         break;
-       case 8:
          {
          {
-#if HOST_BITS_PER_WIDE_INT == 32
-           rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
-           rtx msk = constm1_rtx;
-#endif
+           rtx msk = immed_double_const (0xffffffff, 0, DImode);
            emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
            emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
+           break;
          }
          }
+       case 8:
+         emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr));
          break;
        }
 
          break;
        }
 
@@ -4272,17 +4500,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
          emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
          break;
        case 4:
          emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
          break;
        case 4:
-         emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr));
-         break;
-       case 8:
          {
          {
-#if HOST_BITS_PER_WIDE_INT == 32
-           rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
-           rtx msk = constm1_rtx;
-#endif
+           rtx msk = immed_double_const (0xffffffff, 0, DImode);
            emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
            emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
+           break;
          }
          }
+       case 8:
+         emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr));
          break;
        }
     }
          break;
        }
     }
@@ -4408,11 +4632,6 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
 {
   rtx const im8 = GEN_INT (-8);
   rtx const i64 = GEN_INT (64);
 {
   rtx const im8 = GEN_INT (-8);
   rtx const i64 = GEN_INT (64);
-#if HOST_BITS_PER_WIDE_INT == 32
-  rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
-  rtx const im1 = constm1_rtx;
-#endif
   rtx ins_tmps[MAX_MOVE_WORDS];
   rtx st_tmp_1, st_tmp_2, dreg;
   rtx st_addr_1, st_addr_2, dmema;
   rtx ins_tmps[MAX_MOVE_WORDS];
   rtx st_tmp_1, st_tmp_2, dreg;
   rtx st_addr_1, st_addr_2, dmema;
@@ -4476,13 +4695,13 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
   /* Split and merge the ends with the destination data.  */
   if (WORDS_BIG_ENDIAN)
     {
   /* Split and merge the ends with the destination data.  */
   if (WORDS_BIG_ENDIAN)
     {
-      emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg));
+      emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, constm1_rtx, dreg));
       emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
     }
   else
     {
       emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
       emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
     }
   else
     {
       emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
-      emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg));
+      emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, constm1_rtx, dreg));
     }
 
   if (data_regs != NULL)
     }
 
   if (data_regs != NULL)
@@ -5147,6 +5366,75 @@ alpha_expand_block_clear (operands)
 
   return 1;
 }
 
   return 1;
 }
+
+/* Returns a mask so that zap(x, value) == x & mask.  */
+
+rtx
+alpha_expand_zap_mask (value)
+     HOST_WIDE_INT value;
+{
+  rtx result;
+  int i;
+
+  if (HOST_BITS_PER_WIDE_INT >= 64)
+    {
+      HOST_WIDE_INT mask = 0;
+
+      for (i = 7; i >= 0; --i)
+       {
+         mask <<= 8;
+         if (!((value >> i) & 1))
+           mask |= 0xff;
+       }
+
+      result = gen_int_mode (mask, DImode);
+    }
+  else if (HOST_BITS_PER_WIDE_INT == 32)
+    {
+      HOST_WIDE_INT mask_lo = 0, mask_hi = 0;
+
+      for (i = 7; i >= 4; --i)
+       {
+         mask_hi <<= 8;
+         if (!((value >> i) & 1))
+           mask_hi |= 0xff;
+       }
+
+      for (i = 3; i >= 0; --i)
+       {
+         mask_lo <<= 8;
+         if (!((value >> i) & 1))
+           mask_lo |= 0xff;
+       }
+
+      result = immed_double_const (mask_lo, mask_hi, DImode);
+    }
+  else
+    abort ();
+
+  return result;
+}
+
+void
+alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2)
+     rtx (*gen) PARAMS ((rtx, rtx, rtx));
+     enum machine_mode mode;
+     rtx op0, op1, op2;
+{
+  op0 = gen_lowpart (mode, op0);
+
+  if (op1 == const0_rtx)
+    op1 = CONST0_RTX (mode);
+  else
+    op1 = gen_lowpart (mode, op1);
+
+  if (op2 == const0_rtx)
+    op2 = CONST0_RTX (mode);
+  else
+    op2 = gen_lowpart (mode, op2);
+
+  emit_insn ((*gen) (op0, op1, op2));
+}
 \f
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
 \f
 /* Adjust the cost of a scheduling dependency.  Return the new cost of
    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
@@ -5214,9 +5502,9 @@ alpha_multipass_dfa_lookahead ()
 \f
 /* Machine-specific function data.  */
 
 \f
 /* Machine-specific function data.  */
 
-struct machine_function
+struct machine_function GTY(())
 {
 {
-#if TARGET_ABI_UNICOSMK
+  /* For unicosmk. */
   /* List of call information words for calls from this function.  */
   struct rtx_def *first_ciw;
   struct rtx_def *last_ciw;
   /* List of call information words for calls from this function.  */
   struct rtx_def *first_ciw;
   struct rtx_def *last_ciw;
@@ -5224,58 +5512,18 @@ struct machine_function
 
   /* List of deferred case vectors.  */
   struct rtx_def *addr_list;
 
   /* List of deferred case vectors.  */
   struct rtx_def *addr_list;
-#else
-#if TARGET_ABI_OSF
+
+  /* For OSF. */
   const char *some_ld_name;
   const char *some_ld_name;
-#else
-  /* Non-empty struct.  */
-  char dummy;
-#endif
-#endif
 };
 
 };
 
-/* Register global variables and machine-specific functions with the
-   garbage collector.  */
+/* How to allocate a 'struct machine_function'.  */
 
 
-static void
-alpha_init_machine_status (p)
-     struct function *p;
+static struct machine_function *
+alpha_init_machine_status ()
 {
 {
-  p->machine =
-    (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
-
-#if TARGET_ABI_UNICOSMK
-  p->machine->first_ciw = NULL_RTX;
-  p->machine->last_ciw = NULL_RTX;
-  p->machine->ciw_count = 0;
-  p->machine->addr_list = NULL_RTX;
-#endif
-#if TARGET_ABI_OSF
-  p->machine->some_ld_name = NULL;
-#endif
-}
-
-static void
-alpha_mark_machine_status (p)
-     struct function *p;
-{
-  struct machine_function *machine = p->machine;
-
-  if (machine)
-    {
-#if TARGET_ABI_UNICOSMK
-      ggc_mark_rtx (machine->first_ciw);
-      ggc_mark_rtx (machine->addr_list);
-#endif
-    }
-}
-
-static void
-alpha_free_machine_status (p)
-     struct function *p;
-{
-  free (p->machine);
-  p->machine = NULL;
+  return ((struct machine_function *) 
+               ggc_alloc_cleared (sizeof (struct machine_function)));
 }
 
 /* Functions to save and restore alpha_return_addr_rtx.  */
 }
 
 /* Functions to save and restore alpha_return_addr_rtx.  */
@@ -5301,7 +5549,7 @@ alpha_gp_save_rtx ()
 {
   rtx r = get_hard_reg_initial_val (DImode, 29);
   if (GET_CODE (r) != MEM)
 {
   rtx r = get_hard_reg_initial_val (DImode, 29);
   if (GET_CODE (r) != MEM)
-    r = gen_mem_addressof (r, NULL_TREE);
+    r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true);
   return r;
 }
 
   return r;
 }
 
@@ -5446,14 +5694,11 @@ get_some_local_dynamic_name_1 (px, data)
 {
   rtx x = *px;
 
 {
   rtx x = *px;
 
-  if (GET_CODE (x) == SYMBOL_REF)
+  if (GET_CODE (x) == SYMBOL_REF
+      && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
     {
     {
-      const char *str = XSTR (x, 0);
-      if (str[0] == '@' && str[1] == 'D')
-       {
-          cfun->machine->some_ld_name = str;
-          return 1;
-       }
+      cfun->machine->some_ld_name = XSTR (x, 0);
+      return 1;
     }
 
   return 0;
     }
 
   return 0;
@@ -5501,6 +5746,13 @@ print_operand (file, x, code)
       fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
       break;
 
       fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
       break;
 
+    case '+':
+      /* Generates a nop after a noreturn call at the very end of the
+        function.  */
+      if (next_real_insn (current_output_insn) == 0)
+       fprintf (file, "\n\tnop");
+      break;
+
     case '#':
       if (alpha_this_literal_sequence_number == 0)
        alpha_this_literal_sequence_number = alpha_next_sequence_number++;
     case '#':
       if (alpha_this_literal_sequence_number == 0)
        alpha_this_literal_sequence_number = alpha_next_sequence_number++;
@@ -5652,31 +5904,40 @@ print_operand (file, x, code)
 
     case 'U':
       /* Similar, except do it from the mask.  */
 
     case 'U':
       /* Similar, except do it from the mask.  */
-      if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
-       fprintf (file, "b");
-      else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
-       fprintf (file, "w");
-      else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
-       fprintf (file, "l");
-#if HOST_BITS_PER_WIDE_INT == 32
-      else if (GET_CODE (x) == CONST_DOUBLE
-              && CONST_DOUBLE_HIGH (x) == 0
-              && CONST_DOUBLE_LOW (x) == -1)
-       fprintf (file, "l");
-      else if (GET_CODE (x) == CONST_DOUBLE
-              && CONST_DOUBLE_HIGH (x) == -1
-              && CONST_DOUBLE_LOW (x) == -1)
-       fprintf (file, "q");
-#else
-      else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
-       fprintf (file, "q");
-      else if (GET_CODE (x) == CONST_DOUBLE
-              && CONST_DOUBLE_HIGH (x) == 0
-              && CONST_DOUBLE_LOW (x) == -1)
-       fprintf (file, "q");
-#endif
-      else
-       output_operand_lossage ("invalid %%U value");
+      if (GET_CODE (x) == CONST_INT)
+       {
+         HOST_WIDE_INT value = INTVAL (x);
+
+         if (value == 0xff)
+           {
+             fputc ('b', file);
+             break;
+           }
+         if (value == 0xffff)
+           {
+             fputc ('w', file);
+             break;
+           }
+         if (value == 0xffffffff)
+           {
+             fputc ('l', file);
+             break;
+           }
+         if (value == -1)
+           {
+             fputc ('q', file);
+             break;
+           }
+       }
+      else if (HOST_BITS_PER_WIDE_INT == 32
+              && GET_CODE (x) == CONST_DOUBLE
+              && CONST_DOUBLE_LOW (x) == 0xffffffff
+              && CONST_DOUBLE_HIGH (x) == 0)
+       {
+         fputc ('l', file);
+         break;
+       }
+      output_operand_lossage ("invalid %%U value");
       break;
 
     case 's':
       break;
 
     case 's':
@@ -5851,10 +6112,7 @@ print_operand_address (file, addr)
        }
 
       if (offset)
        }
 
       if (offset)
-       {
-         fputc ('+', file);
-         fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
-       }
+       fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
       
       addr = XEXP (addr, 0);
       if (GET_CODE (addr) == REG)
       
       addr = XEXP (addr, 0);
       if (GET_CODE (addr) == REG)
@@ -5877,11 +6135,28 @@ print_operand_address (file, addr)
     basereg = subreg_regno (addr);
   else if (GET_CODE (addr) == CONST_INT)
     offset = INTVAL (addr);
     basereg = subreg_regno (addr);
   else if (GET_CODE (addr) == CONST_INT)
     offset = INTVAL (addr);
+
+#if TARGET_ABI_OPEN_VMS
+  else if (GET_CODE (addr) == SYMBOL_REF)
+    {
+      fprintf (file, "%s", XSTR (addr, 0));
+      return;
+    }
+  else if (GET_CODE (addr) == CONST
+          && GET_CODE (XEXP (addr, 0)) == PLUS
+          && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
+    {
+      fprintf (file, "%s+%d",
+              XSTR (XEXP (XEXP (addr, 0), 0), 0),
+              INTVAL (XEXP (XEXP (addr, 0), 1)));
+      return;
+    }
+#endif
+
   else
     abort ();
 
   else
     abort ();
 
-  fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
-  fprintf (file, "($%d)", basereg);
+  fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg);
 }
 \f
 /* Emit RTL insns to initialize the variable parts of a trampoline at
 }
 \f
 /* Emit RTL insns to initialize the variable parts of a trampoline at
@@ -5940,8 +6215,8 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
     }
 
 #ifdef TRANSFER_FROM_TRAMPOLINE
     }
 
 #ifdef TRANSFER_FROM_TRAMPOLINE
-  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
-                    0, VOIDmode, 1, addr, Pmode);
+  emit_library_call (init_one_libfunc ("__enable_execute_stack"),
+                    0, VOIDmode, 1, tramp, Pmode);
 #endif
 
   if (jmpofs >= 0)
 #endif
 
   if (jmpofs >= 0)
@@ -6109,9 +6384,55 @@ alpha_build_va_list ()
   return record;
 }
 
   return record;
 }
 
+/* Perform any needed actions needed for a function that is receiving a
+   variable number of arguments. 
+
+   On the Alpha, we allocate space for all 12 arg registers, but only
+   push those that are remaining.  However, if NO registers need to be
+   saved, don't allocate any space.  This is not only because we won't
+   need the space, but because AP includes the current_pretend_args_size
+   and we don't want to mess up any ap-relative addresses already made.
+
+   If we are not to use the floating-point registers, save the integer
+   registers where we would put the floating-point registers.  This is
+   not the most efficient way to implement varargs with just one register
+   class, but it isn't worth doing anything more efficient in this rare
+   case.  */
+
+void   
+alpha_setup_incoming_varargs(cum, mode, type, pretend_size, no_rtl)
+     CUMULATIVE_ARGS cum;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+     tree type ATTRIBUTE_UNUSED;
+     int *pretend_size;
+     int no_rtl;
+{
+  if (cum >= 6)
+    return;
+
+  if (!no_rtl)
+    {
+      int set = get_varargs_alias_set ();
+      rtx tmp;
+
+      tmp = gen_rtx_MEM (BLKmode,
+                        plus_constant (virtual_incoming_args_rtx,
+                                       (cum + 6) * UNITS_PER_WORD));
+      set_mem_alias_set (tmp, set);
+      move_block_from_reg (16 + cum, tmp, 6 - cum);
+
+      tmp = gen_rtx_MEM (BLKmode,
+                        plus_constant (virtual_incoming_args_rtx,
+                                       cum * UNITS_PER_WORD));
+      set_mem_alias_set (tmp, set);
+      move_block_from_reg (16 + (TARGET_FPREGS ? 32 : 0) + cum, tmp,
+                          6 - cum);
+     }
+  *pretend_size = 12 * UNITS_PER_WORD;
+}
+
 void
 void
-alpha_va_start (stdarg_p, valist, nextarg)
-     int stdarg_p;
+alpha_va_start (valist, nextarg)
      tree valist;
      rtx nextarg ATTRIBUTE_UNUSED;
 {
      tree valist;
      rtx nextarg ATTRIBUTE_UNUSED;
 {
@@ -6122,7 +6443,7 @@ alpha_va_start (stdarg_p, valist, nextarg)
     return;
 
   if (TARGET_ABI_UNICOSMK)
     return;
 
   if (TARGET_ABI_UNICOSMK)
-    std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+    std_expand_builtin_va_start (valist, nextarg);
 
   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
      up by 48, storing fp arg registers in the first 48 bytes, and the
 
   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
      up by 48, storing fp arg registers in the first 48 bytes, and the
@@ -6131,12 +6452,15 @@ alpha_va_start (stdarg_p, valist, nextarg)
 
      If no integer registers need be stored, then we must subtract 48
      in order to account for the integer arg registers which are counted
 
      If no integer registers need be stored, then we must subtract 48
      in order to account for the integer arg registers which are counted
-     in argsize above, but which are not actually stored on the stack.  */
+     in argsize above, but which are not actually stored on the stack.
+     Must further be careful here about structures straddling the last
+     integer argument register; that futzes with pretend_args_size, 
+     which changes the meaning of AP.  */
 
 
-  if (NUM_ARGS <= 5 + stdarg_p)
+  if (NUM_ARGS <= 6)
     offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
   else
     offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
   else
-    offset = -6 * UNITS_PER_WORD;
+    offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size;
 
   if (TARGET_ABI_OPEN_VMS)
     {
 
   if (TARGET_ABI_OPEN_VMS)
     {
@@ -6219,46 +6543,350 @@ alpha_va_arg (valist, type)
   wide_type = make_signed_type (64);
   wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
 
   wide_type = make_signed_type (64);
   wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
 
-  addend = wide_ofs;
+  addend = wide_ofs;
+
+  if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
+    {
+      indirect = 1;
+      rounded_size = size_int (UNITS_PER_WORD);
+    }
+  else if (FLOAT_TYPE_P (type))
+    {
+      tree fpaddend, cond;
+
+      fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
+                             addend, build_int_2 (-6*8, 0)));
+
+      cond = fold (build (LT_EXPR, integer_type_node,
+                         wide_ofs, build_int_2 (6*8, 0)));
+
+      addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
+                           fpaddend, addend));
+    }
+
+  addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
+                    base_field, addend);
+
+  addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
+  addr = copy_to_reg (addr);
+
+  t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
+            build (PLUS_EXPR, TREE_TYPE (offset_field), 
+                   offset_field, rounded_size));
+  TREE_SIDE_EFFECTS (t) = 1;
+  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+  if (indirect)
+    {
+      addr = force_reg (Pmode, addr);
+      addr = gen_rtx_MEM (Pmode, addr);
+    }
+
+  return addr;
+}
+\f
+/* Builtins.  */
+
+enum alpha_builtin
+{
+  ALPHA_BUILTIN_CMPBGE,
+  ALPHA_BUILTIN_EXTBL,
+  ALPHA_BUILTIN_EXTWL,
+  ALPHA_BUILTIN_EXTLL,
+  ALPHA_BUILTIN_EXTQL,
+  ALPHA_BUILTIN_EXTWH,
+  ALPHA_BUILTIN_EXTLH,
+  ALPHA_BUILTIN_EXTQH,
+  ALPHA_BUILTIN_INSBL,
+  ALPHA_BUILTIN_INSWL,
+  ALPHA_BUILTIN_INSLL,
+  ALPHA_BUILTIN_INSQL,
+  ALPHA_BUILTIN_INSWH,
+  ALPHA_BUILTIN_INSLH,
+  ALPHA_BUILTIN_INSQH,
+  ALPHA_BUILTIN_MSKBL,
+  ALPHA_BUILTIN_MSKWL,
+  ALPHA_BUILTIN_MSKLL,
+  ALPHA_BUILTIN_MSKQL,
+  ALPHA_BUILTIN_MSKWH,
+  ALPHA_BUILTIN_MSKLH,
+  ALPHA_BUILTIN_MSKQH,
+  ALPHA_BUILTIN_UMULH,
+  ALPHA_BUILTIN_ZAP,
+  ALPHA_BUILTIN_ZAPNOT,
+  ALPHA_BUILTIN_AMASK,
+  ALPHA_BUILTIN_IMPLVER,
+  ALPHA_BUILTIN_RPCC,
+  ALPHA_BUILTIN_THREAD_POINTER,
+  ALPHA_BUILTIN_SET_THREAD_POINTER,
+
+  /* TARGET_MAX */
+  ALPHA_BUILTIN_MINUB8,
+  ALPHA_BUILTIN_MINSB8,
+  ALPHA_BUILTIN_MINUW4,
+  ALPHA_BUILTIN_MINSW4,
+  ALPHA_BUILTIN_MAXUB8,
+  ALPHA_BUILTIN_MAXSB8,
+  ALPHA_BUILTIN_MAXUW4,
+  ALPHA_BUILTIN_MAXSW4,
+  ALPHA_BUILTIN_PERR,
+  ALPHA_BUILTIN_PKLB,
+  ALPHA_BUILTIN_PKWB,
+  ALPHA_BUILTIN_UNPKBL,
+  ALPHA_BUILTIN_UNPKBW,
+
+  /* TARGET_CIX */
+  ALPHA_BUILTIN_CTTZ,
+  ALPHA_BUILTIN_CTLZ,
+  ALPHA_BUILTIN_CTPOP,
+
+  ALPHA_BUILTIN_max
+};
+
+static unsigned int const code_for_builtin[ALPHA_BUILTIN_max] = {
+  CODE_FOR_builtin_cmpbge,
+  CODE_FOR_builtin_extbl,
+  CODE_FOR_builtin_extwl,
+  CODE_FOR_builtin_extll,
+  CODE_FOR_builtin_extql,
+  CODE_FOR_builtin_extwh,
+  CODE_FOR_builtin_extlh,
+  CODE_FOR_builtin_extqh,
+  CODE_FOR_builtin_insbl,
+  CODE_FOR_builtin_inswl,
+  CODE_FOR_builtin_insll,
+  CODE_FOR_builtin_insql,
+  CODE_FOR_builtin_inswh,
+  CODE_FOR_builtin_inslh,
+  CODE_FOR_builtin_insqh,
+  CODE_FOR_builtin_mskbl,
+  CODE_FOR_builtin_mskwl,
+  CODE_FOR_builtin_mskll,
+  CODE_FOR_builtin_mskql,
+  CODE_FOR_builtin_mskwh,
+  CODE_FOR_builtin_msklh,
+  CODE_FOR_builtin_mskqh,
+  CODE_FOR_umuldi3_highpart,
+  CODE_FOR_builtin_zap,
+  CODE_FOR_builtin_zapnot,
+  CODE_FOR_builtin_amask,
+  CODE_FOR_builtin_implver,
+  CODE_FOR_builtin_rpcc,
+  CODE_FOR_load_tp,
+  CODE_FOR_set_tp,
+
+  /* TARGET_MAX */
+  CODE_FOR_builtin_minub8,
+  CODE_FOR_builtin_minsb8,
+  CODE_FOR_builtin_minuw4,
+  CODE_FOR_builtin_minsw4,
+  CODE_FOR_builtin_maxub8,
+  CODE_FOR_builtin_maxsb8,
+  CODE_FOR_builtin_maxuw4,
+  CODE_FOR_builtin_maxsw4,
+  CODE_FOR_builtin_perr,
+  CODE_FOR_builtin_pklb,
+  CODE_FOR_builtin_pkwb,
+  CODE_FOR_builtin_unpkbl,
+  CODE_FOR_builtin_unpkbw,
+
+  /* TARGET_CIX */
+  CODE_FOR_builtin_cttz,
+  CODE_FOR_builtin_ctlz,
+  CODE_FOR_builtin_ctpop
+};
+
+struct alpha_builtin_def
+{
+  const char *name;
+  enum alpha_builtin code;
+  unsigned int target_mask;
+};
+
+static struct alpha_builtin_def const zero_arg_builtins[] = {
+  { "__builtin_alpha_implver", ALPHA_BUILTIN_IMPLVER,  0 },
+  { "__builtin_alpha_rpcc",    ALPHA_BUILTIN_RPCC,     0 }
+};
+
+static struct alpha_builtin_def const one_arg_builtins[] = {
+  { "__builtin_alpha_amask",   ALPHA_BUILTIN_AMASK,    0 },
+  { "__builtin_alpha_pklb",    ALPHA_BUILTIN_PKLB,     MASK_MAX },
+  { "__builtin_alpha_pkwb",    ALPHA_BUILTIN_PKWB,     MASK_MAX },
+  { "__builtin_alpha_unpkbl",  ALPHA_BUILTIN_UNPKBL,   MASK_MAX },
+  { "__builtin_alpha_unpkbw",  ALPHA_BUILTIN_UNPKBW,   MASK_MAX },
+  { "__builtin_alpha_cttz",    ALPHA_BUILTIN_CTTZ,     MASK_CIX },
+  { "__builtin_alpha_ctlz",    ALPHA_BUILTIN_CTLZ,     MASK_CIX },
+  { "__builtin_alpha_ctpop",   ALPHA_BUILTIN_CTPOP,    MASK_CIX }
+};
+
+static struct alpha_builtin_def const two_arg_builtins[] = {
+  { "__builtin_alpha_cmpbge",  ALPHA_BUILTIN_CMPBGE,   0 },
+  { "__builtin_alpha_extbl",   ALPHA_BUILTIN_EXTBL,    0 },
+  { "__builtin_alpha_extwl",   ALPHA_BUILTIN_EXTWL,    0 },
+  { "__builtin_alpha_extll",   ALPHA_BUILTIN_EXTLL,    0 },
+  { "__builtin_alpha_extql",   ALPHA_BUILTIN_EXTQL,    0 },
+  { "__builtin_alpha_extwh",   ALPHA_BUILTIN_EXTWH,    0 },
+  { "__builtin_alpha_extlh",   ALPHA_BUILTIN_EXTLH,    0 },
+  { "__builtin_alpha_extqh",   ALPHA_BUILTIN_EXTQH,    0 },
+  { "__builtin_alpha_insbl",   ALPHA_BUILTIN_INSBL,    0 },
+  { "__builtin_alpha_inswl",   ALPHA_BUILTIN_INSWL,    0 },
+  { "__builtin_alpha_insll",   ALPHA_BUILTIN_INSLL,    0 },
+  { "__builtin_alpha_insql",   ALPHA_BUILTIN_INSQL,    0 },
+  { "__builtin_alpha_inswh",   ALPHA_BUILTIN_INSWH,    0 },
+  { "__builtin_alpha_inslh",   ALPHA_BUILTIN_INSLH,    0 },
+  { "__builtin_alpha_insqh",   ALPHA_BUILTIN_INSQH,    0 },
+  { "__builtin_alpha_mskbl",   ALPHA_BUILTIN_MSKBL,    0 },
+  { "__builtin_alpha_mskwl",   ALPHA_BUILTIN_MSKWL,    0 },
+  { "__builtin_alpha_mskll",   ALPHA_BUILTIN_MSKLL,    0 },
+  { "__builtin_alpha_mskql",   ALPHA_BUILTIN_MSKQL,    0 },
+  { "__builtin_alpha_mskwh",   ALPHA_BUILTIN_MSKWH,    0 },
+  { "__builtin_alpha_msklh",   ALPHA_BUILTIN_MSKLH,    0 },
+  { "__builtin_alpha_mskqh",   ALPHA_BUILTIN_MSKQH,    0 },
+  { "__builtin_alpha_umulh",   ALPHA_BUILTIN_UMULH,    0 },
+  { "__builtin_alpha_zap",     ALPHA_BUILTIN_ZAP,      0 },
+  { "__builtin_alpha_zapnot",  ALPHA_BUILTIN_ZAPNOT,   0 },
+  { "__builtin_alpha_minub8",  ALPHA_BUILTIN_MINUB8,   MASK_MAX },
+  { "__builtin_alpha_minsb8",  ALPHA_BUILTIN_MINSB8,   MASK_MAX },
+  { "__builtin_alpha_minuw4",  ALPHA_BUILTIN_MINUW4,   MASK_MAX },
+  { "__builtin_alpha_minsw4",  ALPHA_BUILTIN_MINSW4,   MASK_MAX },
+  { "__builtin_alpha_maxub8",  ALPHA_BUILTIN_MAXUB8,   MASK_MAX },
+  { "__builtin_alpha_maxsb8",  ALPHA_BUILTIN_MAXSB8,   MASK_MAX },
+  { "__builtin_alpha_maxuw4",  ALPHA_BUILTIN_MAXUW4,   MASK_MAX },
+  { "__builtin_alpha_maxsw4",  ALPHA_BUILTIN_MAXSW4,   MASK_MAX },
+  { "__builtin_alpha_perr",    ALPHA_BUILTIN_PERR,     MASK_MAX }
+};
+
+static void
+alpha_init_builtins ()
+{
+  const struct alpha_builtin_def *p;
+  tree ftype;
+  size_t i;
+
+  ftype = build_function_type (long_integer_type_node, void_list_node);
+
+  p = zero_arg_builtins;
+  for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
+    if ((target_flags & p->target_mask) == p->target_mask)
+      builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+                       NULL, NULL_TREE);
+
+  ftype = build_function_type_list (long_integer_type_node,
+                                   long_integer_type_node, NULL_TREE);
+
+  p = one_arg_builtins;
+  for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
+    if ((target_flags & p->target_mask) == p->target_mask)
+      builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+                       NULL, NULL_TREE);
+
+  ftype = build_function_type_list (long_integer_type_node,
+                                   long_integer_type_node,
+                                   long_integer_type_node, NULL_TREE);
+
+  p = two_arg_builtins;
+  for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
+    if ((target_flags & p->target_mask) == p->target_mask)
+      builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+                       NULL, NULL_TREE);
+
+  ftype = build_function_type (ptr_type_node, void_list_node);
+  builtin_function ("__builtin_thread_pointer", ftype,
+                   ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+                   NULL, NULL_TREE);
+
+  ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+  builtin_function ("__builtin_set_thread_pointer", ftype,
+                   ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
+                   NULL, NULL_TREE);
+}
+
+/* Expand an expression EXP that calls a built-in function,
+   with result going to TARGET if that's convenient
+   (and in mode MODE if that's convenient).
+   SUBTARGET may be used as the target for computing one of EXP's operands.
+   IGNORE is nonzero if the value is to be ignored.  */
+
+static rtx
+alpha_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;
+{
+#define MAX_ARGS 2
+
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  tree arglist = TREE_OPERAND (exp, 1);
+  enum insn_code icode;
+  rtx op[MAX_ARGS], pat;
+  int arity;
+  bool nonvoid;
+
+  if (fcode >= ALPHA_BUILTIN_max)
+    internal_error ("bad builtin fcode");
+  icode = code_for_builtin[fcode];
+  if (icode == 0)
+    internal_error ("bad builtin fcode");
 
 
-  if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
-    {
-      indirect = 1;
-      rounded_size = size_int (UNITS_PER_WORD);
-    }
-  else if (FLOAT_TYPE_P (type))
-    {
-      tree fpaddend, cond;
+  nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
 
 
-      fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
-                             addend, build_int_2 (-6*8, 0)));
+  for (arglist = TREE_OPERAND (exp, 1), arity = 0;
+       arglist;
+       arglist = TREE_CHAIN (arglist), arity++)
+    {
+      const struct insn_operand_data *insn_op;
 
 
-      cond = fold (build (LT_EXPR, integer_type_node,
-                         wide_ofs, build_int_2 (6*8, 0)));
+      tree arg = TREE_VALUE (arglist);
+      if (arg == error_mark_node)
+       return NULL_RTX;
+      if (arity > MAX_ARGS)
+       return NULL_RTX;
 
 
-      addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
-                           fpaddend, addend));
-    }
+      insn_op = &insn_data[icode].operand[arity + nonvoid];
 
 
-  addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
-                    base_field, addend);
+      op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0);
 
 
-  addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
-  addr = copy_to_reg (addr);
+      if (!(*insn_op->predicate) (op[arity], insn_op->mode))
+       op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
+    }
 
 
-  t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
-            build (PLUS_EXPR, TREE_TYPE (offset_field), 
-                   offset_field, rounded_size));
-  TREE_SIDE_EFFECTS (t) = 1;
-  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+  if (nonvoid)
+    {
+      enum machine_mode tmode = insn_data[icode].operand[0].mode;
+      if (!target
+         || GET_MODE (target) != tmode
+         || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+       target = gen_reg_rtx (tmode);
+    }
 
 
-  if (indirect)
+  switch (arity)
     {
     {
-      addr = force_reg (Pmode, addr);
-      addr = gen_rtx_MEM (Pmode, addr);
+    case 0:
+      pat = GEN_FCN (icode) (target);
+      break;
+    case 1:
+      if (nonvoid)
+        pat = GEN_FCN (icode) (target, op[0]);
+      else
+       pat = GEN_FCN (icode) (op[0]);
+      break;
+    case 2:
+      pat = GEN_FCN (icode) (target, op[0], op[1]);
+      break;
+    default:
+      abort ();
     }
     }
+  if (!pat)
+    return NULL_RTX;
+  emit_insn (pat);
 
 
-  return addr;
+  if (nonvoid)
+    return target;
+  else
+    return const0_rtx;
 }
 \f
 /* This page contains routines that are used to determine what the function
 }
 \f
 /* This page contains routines that are used to determine what the function
@@ -6298,10 +6926,11 @@ alpha_sa_mask (imaskP, fmaskP)
   unsigned int i;
 
   /* Irritatingly, there are two kinds of thunks -- those created with
   unsigned int i;
 
   /* Irritatingly, there are two kinds of thunks -- those created with
-     ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go through
-     the regular part of the compiler.  In the ASM_OUTPUT_MI_THUNK case
-     we don't have valid register life info, but assemble_start_function
-     wants to output .frame and .mask directives.  */
+     TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go
+     through the regular part of the compiler.  In the
+     TARGET_ASM_OUTPUT_MI_THUNK case we don't have valid register life
+     info, but assemble_start_function wants to output .frame and
+     .mask directives.  */
   if (current_function_is_thunk && !no_new_pseudos)
     {
       *imaskP = 0;
   if (current_function_is_thunk && !no_new_pseudos)
     {
       *imaskP = 0;
@@ -6310,7 +6939,7 @@ alpha_sa_mask (imaskP, fmaskP)
     }
 
   if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
     }
 
   if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
-    imask |= (1L << HARD_FRAME_POINTER_REGNUM);
+    imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
 
   /* One for every register we have to save.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 
   /* One for every register we have to save.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -6319,9 +6948,9 @@ alpha_sa_mask (imaskP, fmaskP)
        && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
       {
        if (i < 32)
        && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
       {
        if (i < 32)
-         imask |= (1L << i);
+         imask |= (1UL << i);
        else
        else
-         fmask |= (1L << (i - 32));
+         fmask |= (1UL << (i - 32));
       }
 
   /* We need to restore these for the handler.  */
       }
 
   /* We need to restore these for the handler.  */
@@ -6331,14 +6960,14 @@ alpha_sa_mask (imaskP, fmaskP)
        unsigned regno = EH_RETURN_DATA_REGNO (i);
        if (regno == INVALID_REGNUM)
          break;
        unsigned regno = EH_RETURN_DATA_REGNO (i);
        if (regno == INVALID_REGNUM)
          break;
-       imask |= 1L << regno;
+       imask |= 1UL << regno;
       }
      
   /* If any register spilled, then spill the return address also.  */
   /* ??? This is required by the Digital stack unwind specification
      and isn't needed if we're doing Dwarf2 unwinding.  */
   if (imask || fmask || alpha_ra_ever_killed ())
       }
      
   /* If any register spilled, then spill the return address also.  */
   /* ??? This is required by the Digital stack unwind specification
      and isn't needed if we're doing Dwarf2 unwinding.  */
   if (imask || fmask || alpha_ra_ever_killed ())
-    imask |= (1L << REG_RA);
+    imask |= (1UL << REG_RA);
 
   *imaskP = imask;
   *fmaskP = fmask;
 
   *imaskP = imask;
   *fmaskP = fmask;
@@ -6376,7 +7005,7 @@ alpha_sa_size ()
 
       alpha_procedure_type
        = (sa_size || get_frame_size() != 0
 
       alpha_procedure_type
        = (sa_size || get_frame_size() != 0
-          || current_function_outgoing_args_size || current_function_varargs
+          || current_function_outgoing_args_size
           || current_function_stdarg || current_function_calls_alloca
           || frame_pointer_needed)
          ? PT_STACK : PT_REGISTER;
           || current_function_stdarg || current_function_calls_alloca
           || frame_pointer_needed)
          ? PT_STACK : PT_REGISTER;
@@ -6447,6 +7076,30 @@ alpha_sa_size ()
   return sa_size * 8;
 }
 
   return sa_size * 8;
 }
 
+/* Define the offset between two registers, one to be eliminated,
+   and the other its replacement, at the start of a routine.  */
+
+HOST_WIDE_INT
+alpha_initial_elimination_offset (from, to)
+     unsigned int from, to ATTRIBUTE_UNUSED;
+{
+  HOST_WIDE_INT ret;
+
+  ret = alpha_sa_size ();
+  ret += ALPHA_ROUND (current_function_outgoing_args_size);
+
+  if (from == FRAME_POINTER_REGNUM)
+    ;
+  else if (from == ARG_POINTER_REGNUM)
+    ret += (ALPHA_ROUND (get_frame_size ()
+                        + current_function_pretend_args_size)
+           - current_function_pretend_args_size);
+  else
+    abort ();
+
+  return ret;
+}
+
 int
 alpha_pv_save_size ()
 {
 int
 alpha_pv_save_size ()
 {
@@ -6475,11 +7128,18 @@ const struct attribute_spec vms_attribute_table[] =
 #endif
 
 static int
 #endif
 
 static int
-find_lo_sum (px, data)
+find_lo_sum_using_gp (px, data)
      rtx *px;
      void *data ATTRIBUTE_UNUSED;
 {
      rtx *px;
      void *data ATTRIBUTE_UNUSED;
 {
-  return GET_CODE (*px) == LO_SUM;
+  return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx;
+}
+
+int
+alpha_find_lo_sum_using_gp (insn)
+     rtx insn;
+{
+  return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0;
 }
 
 static int
 }
 
 static int
@@ -6508,15 +7168,9 @@ alpha_does_function_need_gp ()
   for (; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn)
        && GET_CODE (PATTERN (insn)) != USE
   for (; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn)
        && GET_CODE (PATTERN (insn)) != USE
-       && GET_CODE (PATTERN (insn)) != CLOBBER)
-      {
-       enum attr_type type = get_attr_type (insn);
-       if (type == TYPE_LDSYM || type == TYPE_JSR)
-         return 1;
-       if (TARGET_EXPLICIT_RELOCS
-           && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0)
-         return 1;
-      }
+       && GET_CODE (PATTERN (insn)) != CLOBBER
+       && get_attr_usegp (insn))
+      return 1;
 
   return 0;
 }
 
   return 0;
 }
@@ -6543,22 +7197,30 @@ alpha_write_verstamp (file)
 static rtx
 set_frame_related_p ()
 {
 static rtx
 set_frame_related_p ()
 {
-  rtx seq = gen_sequence ();
+  rtx seq = get_insns ();
+  rtx insn;
+
   end_sequence ();
 
   end_sequence ();
 
-  if (GET_CODE (seq) == SEQUENCE)
+  if (!seq)
+    return NULL_RTX;
+
+  if (INSN_P (seq))
     {
     {
-      int i = XVECLEN (seq, 0);
-      while (--i >= 0)
-       RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
-     return emit_insn (seq);
+      insn = seq;
+      while (insn != NULL_RTX)
+       {
+         RTX_FRAME_RELATED_P (insn) = 1;
+         insn = NEXT_INSN (insn);
+       }
+      seq = emit_insn (seq);
     }
   else
     {
       seq = emit_insn (seq);
       RTX_FRAME_RELATED_P (seq) = 1;
     }
   else
     {
       seq = emit_insn (seq);
       RTX_FRAME_RELATED_P (seq) = 1;
-      return seq;
     }
     }
+  return seq;
 }
 
 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
 }
 
 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
@@ -6769,18 +7431,18 @@ alpha_expand_prologue ()
        }
 
       /* Save register RA next.  */
        }
 
       /* Save register RA next.  */
-      if (imask & (1L << REG_RA))
+      if (imask & (1UL << REG_RA))
        {
          mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
          set_mem_alias_set (mem, alpha_sr_alias_set);
          FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
        {
          mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
          set_mem_alias_set (mem, alpha_sr_alias_set);
          FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
-         imask &= ~(1L << REG_RA);
+         imask &= ~(1UL << REG_RA);
          reg_offset += 8;
        }
 
       /* Now save any other registers required to be saved.  */
       for (i = 0; i < 32; i++)
          reg_offset += 8;
        }
 
       /* Now save any other registers required to be saved.  */
       for (i = 0; i < 32; i++)
-       if (imask & (1L << i))
+       if (imask & (1UL << i))
          {
            mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
          {
            mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
@@ -6789,7 +7451,7 @@ alpha_expand_prologue ()
          }
 
       for (i = 0; i < 32; i++)
          }
 
       for (i = 0; i < 32; i++)
-       if (fmask & (1L << i))
+       if (fmask & (1UL << i))
          {
            mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
          {
            mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
@@ -6805,7 +7467,7 @@ alpha_expand_prologue ()
 
       reg_offset = -56;
       for (i = 9; i < 15; i++)
 
       reg_offset = -56;
       for (i = 9; i < 15; i++)
-       if (imask & (1L << i))
+       if (imask & (1UL << i))
          {
            mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
          {
            mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
@@ -6814,7 +7476,7 @@ alpha_expand_prologue ()
            reg_offset -= 8;
          }
       for (i = 2; i < 10; i++)
            reg_offset -= 8;
          }
       for (i = 2; i < 10; i++)
-       if (fmask & (1L << i))
+       if (fmask & (1UL << i))
          {
            mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
                                                      reg_offset));
          {
            mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
                                                      reg_offset));
@@ -6842,11 +7504,31 @@ alpha_expand_prologue ()
 
       /* If we have to allocate space for outgoing args, do it now.  */
       if (current_function_outgoing_args_size != 0)
 
       /* If we have to allocate space for outgoing args, do it now.  */
       if (current_function_outgoing_args_size != 0)
-       FRP (emit_move_insn
-            (stack_pointer_rtx, 
-             plus_constant (hard_frame_pointer_rtx,
-                            - (ALPHA_ROUND
-                               (current_function_outgoing_args_size)))));
+       {
+         rtx seq
+           = emit_move_insn (stack_pointer_rtx, 
+                             plus_constant
+                             (hard_frame_pointer_rtx,
+                              - (ALPHA_ROUND
+                                 (current_function_outgoing_args_size))));
+         
+         /* Only set FRAME_RELATED_P on the stack adjustment we just emitted
+            if ! frame_pointer_needed. Setting the bit will change the CFA
+            computation rule to use sp again, which would be wrong if we had
+            frame_pointer_needed, as this means sp might move unpredictably
+            later on.
+
+            Also, note that
+              frame_pointer_needed
+              => vms_unwind_regno == HARD_FRAME_POINTER_REGNUM
+            and
+              current_function_outgoing_args_size != 0
+              => alpha_procedure_type != PT_NULL,
+
+            so when we are not setting the bit here, we are guaranteed to
+            have emited an FRP frame pointer update just before.  */
+         RTX_FRAME_RELATED_P (seq) = ! frame_pointer_needed;
+       }
     }
   else if (!TARGET_ABI_UNICOSMK)
     {
     }
   else if (!TARGET_ABI_UNICOSMK)
     {
@@ -6890,7 +7572,7 @@ alpha_start_function (file, fnname, decl)
   /* Stack space needed for pushing registers clobbered by us.  */
   HOST_WIDE_INT sa_size;
   /* Complete stack size needed.  */
   /* Stack space needed for pushing registers clobbered by us.  */
   HOST_WIDE_INT sa_size;
   /* Complete stack size needed.  */
-  HOST_WIDE_INT frame_size;
+  unsigned HOST_WIDE_INT frame_size;
   /* Offset from base reg to register save area.  */
   HOST_WIDE_INT reg_offset;
   char *entry_label = (char *) alloca (strlen (fnname) + 6);
   /* Offset from base reg to register save area.  */
   HOST_WIDE_INT reg_offset;
   char *entry_label = (char *) alloca (strlen (fnname) + 6);
@@ -7006,23 +7688,17 @@ alpha_start_function (file, fnname, decl)
   if (TARGET_ABI_UNICOSMK)
     ;
   else if (TARGET_ABI_OPEN_VMS)
   if (TARGET_ABI_UNICOSMK)
     ;
   else if (TARGET_ABI_OPEN_VMS)
-    {
-      fprintf (file, "\t.frame $%d,", vms_unwind_regno);
-      fprintf (file, HOST_WIDE_INT_PRINT_DEC,
-              frame_size >= ((HOST_WIDE_INT) 1 << 31) ? 0 : frame_size);
-      fputs (",$26,", file);
-      fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
-      fputs ("\n", file);
-    }
+    fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
+            HOST_WIDE_INT_PRINT_DEC "\n",
+            vms_unwind_regno,
+            frame_size >= (1UL << 31) ? 0 : frame_size,
+            reg_offset);
   else if (!flag_inhibit_size_directive)
   else if (!flag_inhibit_size_directive)
-    {
-      fprintf (file, "\t.frame $%d,",
-              (frame_pointer_needed
-               ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
-      fprintf (file, HOST_WIDE_INT_PRINT_DEC,
-              frame_size >= (1l << 31) ? 0 : frame_size);
-      fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
-    }
+    fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
+            (frame_pointer_needed
+             ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM),
+            frame_size >= (1UL << 31) ? 0 : frame_size,
+            current_function_pretend_args_size);
 
   /* Describe which registers were spilled.  */
   if (TARGET_ABI_UNICOSMK)
 
   /* Describe which registers were spilled.  */
   if (TARGET_ABI_UNICOSMK)
@@ -7032,7 +7708,7 @@ alpha_start_function (file, fnname, decl)
       if (imask)
         /* ??? Does VMS care if mask contains ra?  The old code didn't
            set it, so I don't here.  */
       if (imask)
         /* ??? Does VMS care if mask contains ra?  The old code didn't
            set it, so I don't here.  */
-       fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
+       fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1UL << REG_RA));
       if (fmask)
        fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
       if (alpha_procedure_type == PT_REGISTER)
       if (fmask)
        fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
       if (alpha_procedure_type == PT_REGISTER)
@@ -7042,23 +7718,17 @@ alpha_start_function (file, fnname, decl)
     {
       if (imask)
        {
     {
       if (imask)
        {
-         fprintf (file, "\t.mask 0x%lx,", imask);
-         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
-                  frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
-         putc ('\n', file);
+         fprintf (file, "\t.mask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", imask,
+                  frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size);
 
          for (i = 0; i < 32; ++i)
 
          for (i = 0; i < 32; ++i)
-           if (imask & (1L << i))
+           if (imask & (1UL << i))
              reg_offset += 8;
        }
 
       if (fmask)
              reg_offset += 8;
        }
 
       if (fmask)
-       {
-         fprintf (file, "\t.fmask 0x%lx,", fmask);
-         fprintf (file, HOST_WIDE_INT_PRINT_DEC,
-                  frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
-         putc ('\n', file);
-       }
+       fprintf (file, "\t.fmask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", fmask,
+                frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size);
     }
 
 #if TARGET_ABI_OPEN_VMS
     }
 
 #if TARGET_ABI_OPEN_VMS
@@ -7069,18 +7739,6 @@ alpha_start_function (file, fnname, decl)
   fputs ("\t.ascii \"", file);
   assemble_name (file, fnname);
   fputs ("\\0\"\n", file);
   fputs ("\t.ascii \"", file);
   assemble_name (file, fnname);
   fputs ("\\0\"\n", file);
-
-  link_section ();
-  fprintf (file, "\t.align 3\n");
-  fputs ("\t.name ", file);
-  assemble_name (file, fnname);
-  fputs ("..na\n", file);
-  ASM_OUTPUT_LABEL (file, fnname);
-  fprintf (file, "\t.pdesc ");
-  assemble_name (file, fnname);
-  fprintf (file, "..en,%s\n",
-          alpha_procedure_type == PT_STACK ? "stack"
-          : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
   alpha_need_linkage (fnname, 1);
   text_section ();
 #endif
   alpha_need_linkage (fnname, 1);
   text_section ();
 #endif
@@ -7204,10 +7862,10 @@ alpha_expand_epilogue ()
       FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
 
       reg_offset += 8;
       FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
 
       reg_offset += 8;
-      imask &= ~(1L << REG_RA);
+      imask &= ~(1UL << REG_RA);
 
       for (i = 0; i < 32; ++i)
 
       for (i = 0; i < 32; ++i)
-       if (imask & (1L << i))
+       if (imask & (1UL << i))
          {
            if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
              fp_offset = reg_offset;
          {
            if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
              fp_offset = reg_offset;
@@ -7221,7 +7879,7 @@ alpha_expand_epilogue ()
          }
 
       for (i = 0; i < 32; ++i)
          }
 
       for (i = 0; i < 32; ++i)
-       if (fmask & (1L << i))
+       if (fmask & (1UL << i))
          {
            mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
          {
            mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
            set_mem_alias_set (mem, alpha_sr_alias_set);
@@ -7236,7 +7894,7 @@ alpha_expand_epilogue ()
       reg_offset = -56;
 
       for (i = 9; i < 15; i++)
       reg_offset = -56;
 
       for (i = 9; i < 15; i++)
-       if (imask & (1L << i))
+       if (imask & (1UL << i))
          {
            mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
          {
            mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
@@ -7246,7 +7904,7 @@ alpha_expand_epilogue ()
          }
 
       for (i = 2; i < 10; i++)
          }
 
       for (i = 2; i < 10; i++)
-       if (fmask & (1L << i))
+       if (fmask & (1UL << i))
          {
            mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
          {
            mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
                                                     reg_offset));
@@ -7366,7 +8024,7 @@ alpha_expand_epilogue ()
         }
     }
 }
         }
     }
 }
-
+\f
 /* Output the rest of the textual info surrounding the epilogue.  */
 
 void
 /* Output the rest of the textual info surrounding the epilogue.  */
 
 void
@@ -7384,20 +8042,9 @@ alpha_end_function (file, fnname, decl)
     }
   inside_function = FALSE;
 
     }
   inside_function = FALSE;
 
-  /* Show that we know this function if it is called again. 
-
-     Don't do this for global functions in object files destined for a
-     shared library because the function may be overridden by the application
-     or other libraries.  Similarly, don't do this for weak functions.
-
-     Don't do this for functions not defined in the .text section, as
-     otherwise it's not unlikely that the destination is out of range
-     for a direct branch.  */
-
-  if (!DECL_WEAK (current_function_decl)
-      && (!flag_pic || !TREE_PUBLIC (current_function_decl))
-      && decl_in_text_section (current_function_decl))
-    SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
+#if TARGET_ABI_OPEN_VMS
+  alpha_write_linkage (file, fnname, decl);
+#endif
 
   /* Output jump tables and the static subroutine information block.  */
   if (TARGET_ABI_UNICOSMK)
 
   /* Output jump tables and the static subroutine information block.  */
   if (TARGET_ABI_UNICOSMK)
@@ -7407,7 +8054,8 @@ alpha_end_function (file, fnname, decl)
     }
 }
 
     }
 }
 
-/* Emit a tail call to FUNCTION after adjusting THIS by DELTA. 
+#if TARGET_ABI_OSF
+/* Emit a tail call to FUNCTION after adjusting THIS by DELTA.
 
    In order to avoid the hordes of differences between generated code
    with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating
 
    In order to avoid the hordes of differences between generated code
    with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating
@@ -7416,11 +8064,12 @@ alpha_end_function (file, fnname, decl)
 
    Not sure why this idea hasn't been explored before...  */
 
 
    Not sure why this idea hasn't been explored before...  */
 
-void
-alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
+static void
+alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function)
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
      FILE *file;
      tree thunk_fndecl ATTRIBUTE_UNUSED;
      HOST_WIDE_INT delta;
+     HOST_WIDE_INT vcall_offset;
      tree function;
 {
   HOST_WIDE_INT hi, lo;
      tree function;
 {
   HOST_WIDE_INT hi, lo;
@@ -7455,6 +8104,37 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
       emit_insn (gen_adddi3 (this, this, tmp));
     }
 
       emit_insn (gen_adddi3 (this, this, tmp));
     }
 
+  /* Add a delta stored in the vtable at VCALL_OFFSET.  */
+  if (vcall_offset)
+    {
+      rtx tmp, tmp2;
+
+      tmp = gen_rtx_REG (Pmode, 0);
+      emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
+
+      lo = ((vcall_offset & 0xffff) ^ 0x8000) - 0x8000;
+      hi = (((vcall_offset - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
+      if (hi + lo == vcall_offset)
+       {
+         if (hi)
+           emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (hi)));
+       }
+      else
+       {
+         tmp2 = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 1),
+                                           vcall_offset, -(vcall_offset < 0));
+          emit_insn (gen_adddi3 (tmp, tmp, tmp2));
+         lo = 0;
+       }
+      if (lo)
+       tmp2 = gen_rtx_PLUS (Pmode, tmp, GEN_INT (lo));
+      else
+       tmp2 = tmp;
+      emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp2));
+
+      emit_insn (gen_adddi3 (this, this, tmp));
+    }
+
   /* Generate a tail call to the target function.  */
   if (! TREE_USED (function))
     {
   /* Generate a tail call to the target function.  */
   if (! TREE_USED (function))
     {
@@ -7476,6 +8156,7 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
   final (insn, file, 1, 0);
   final_end_function ();
 }
   final (insn, file, 1, 0);
   final_end_function ();
 }
+#endif /* TARGET_ABI_OSF */
 \f
 /* Debugging support.  */
 
 \f
 /* Debugging support.  */
 
@@ -7580,7 +8261,7 @@ struct shadow_summary
 };
 
 static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int));
 };
 
 static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int));
-static void alpha_handle_trap_shadows PARAMS ((rtx));
+static void alpha_handle_trap_shadows PARAMS ((void));
 
 /* Summary the effects of expression X on the machine.  Update SUM, a pointer
    to the summary structure.  SET is nonzero if the insn is setting the
 
 /* Summary the effects of expression X on the machine.  Update SUM, a pointer
    to the summary structure.  SET is nonzero if the insn is setting the
@@ -7744,8 +8425,7 @@ summarize_insn (x, sum, set)
    (d) The trap shadow may not include any branch instructions.  */
 
 static void
    (d) The trap shadow may not include any branch instructions.  */
 
 static void
-alpha_handle_trap_shadows (insns)
-     rtx insns;
+alpha_handle_trap_shadows ()
 {
   struct shadow_summary shadow;
   int trap_pending, exception_nesting;
 {
   struct shadow_summary shadow;
   int trap_pending, exception_nesting;
@@ -7758,7 +8438,7 @@ alpha_handle_trap_shadows (insns)
   shadow.used.mem = 0;
   shadow.defd = shadow.used;
   
   shadow.used.mem = 0;
   shadow.defd = shadow.used;
   
-  for (i = insns; i ; i = NEXT_INSN (i))
+  for (i = get_insns (); i ; i = NEXT_INSN (i))
     {
       if (GET_CODE (i) == NOTE)
        {
     {
       if (GET_CODE (i) == NOTE)
        {
@@ -7906,7 +8586,7 @@ static rtx alphaev4_next_nop PARAMS ((int *));
 static rtx alphaev5_next_nop PARAMS ((int *));
 
 static void alpha_align_insns
 static rtx alphaev5_next_nop PARAMS ((int *));
 
 static void alpha_align_insns
-  PARAMS ((rtx, unsigned int, rtx (*)(rtx, int *, int *), rtx (*)(int *)));
+  PARAMS ((unsigned int, rtx (*)(rtx, int *, int *), rtx (*)(int *)));
 
 static enum alphaev4_pipe
 alphaev4_insn_pipe (insn)
 
 static enum alphaev4_pipe
 alphaev4_insn_pipe (insn)
@@ -7938,6 +8618,7 @@ alphaev4_insn_pipe (insn)
     case TYPE_MISC:
     case TYPE_IBR:
     case TYPE_JSR:
     case TYPE_MISC:
     case TYPE_IBR:
     case TYPE_JSR:
+    case TYPE_CALLPAL:
     case TYPE_FCPYS:
     case TYPE_FCMOV:
     case TYPE_FADD:
     case TYPE_FCPYS:
     case TYPE_FCMOV:
     case TYPE_FADD:
@@ -7980,6 +8661,7 @@ alphaev5_insn_pipe (insn)
 
     case TYPE_IBR:
     case TYPE_JSR:
 
     case TYPE_IBR:
     case TYPE_JSR:
+    case TYPE_CALLPAL:
       return EV5_E1;
 
     case TYPE_FCPYS:
       return EV5_E1;
 
     case TYPE_FCPYS:
@@ -8293,8 +8975,7 @@ alphaev5_next_nop (pin_use)
 /* The instruction group alignment main loop.  */
 
 static void
 /* The instruction group alignment main loop.  */
 
 static void
-alpha_align_insns (insns, max_align, next_group, next_nop)
-     rtx insns;
+alpha_align_insns (max_align, next_group, next_nop)
      unsigned int max_align;
      rtx (*next_group) PARAMS ((rtx, int *, int *));
      rtx (*next_nop) PARAMS ((int *));
      unsigned int max_align;
      rtx (*next_group) PARAMS ((rtx, int *, int *));
      rtx (*next_nop) PARAMS ((int *));
@@ -8307,7 +8988,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop)
   rtx i, next;
 
   /* Let shorten branches care for assigning alignments to code labels.  */
   rtx i, next;
 
   /* Let shorten branches care for assigning alignments to code labels.  */
-  shorten_branches (insns);
+  shorten_branches (get_insns ());
 
   if (align_functions < 4)
     align = 4;
 
   if (align_functions < 4)
     align = 4;
@@ -8317,7 +8998,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop)
     align = max_align;
 
   ofs = prev_in_use = 0;
     align = max_align;
 
   ofs = prev_in_use = 0;
-  i = insns;
+  i = get_insns ();
   if (GET_CODE (i) == NOTE)
     i = next_nonnote_insn (i);
 
   if (GET_CODE (i) == NOTE)
     i = next_nonnote_insn (i);
 
@@ -8419,12 +9100,11 @@ alpha_align_insns (insns, max_align, next_group, next_nop)
 \f
 /* Machine dependent reorg pass.  */
 
 \f
 /* Machine dependent reorg pass.  */
 
-void
-alpha_reorg (insns)
-     rtx insns;
+static void
+alpha_reorg ()
 {
   if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
 {
   if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
-    alpha_handle_trap_shadows (insns);
+    alpha_handle_trap_shadows ();
 
   /* Due to the number of extra trapb insns, don't bother fixing up
      alignment when trap precision is instruction.  Moreover, we can
 
   /* Due to the number of extra trapb insns, don't bother fixing up
      alignment when trap precision is instruction.  Moreover, we can
@@ -8434,87 +9114,10 @@ alpha_reorg (insns)
       && flag_schedule_insns_after_reload)
     {
       if (alpha_cpu == PROCESSOR_EV4)
       && flag_schedule_insns_after_reload)
     {
       if (alpha_cpu == PROCESSOR_EV4)
-       alpha_align_insns (insns, 8, alphaev4_next_group, alphaev4_next_nop);
+       alpha_align_insns (8, alphaev4_next_group, alphaev4_next_nop);
       else if (alpha_cpu == PROCESSOR_EV5)
       else if (alpha_cpu == PROCESSOR_EV5)
-       alpha_align_insns (insns, 16, alphaev5_next_group, alphaev5_next_nop);
-    }
-}
-\f
-/* Check a floating-point value for validity for a particular machine mode.  */
-
-static const char * const float_strings[] =
-{
-  /* These are for FLOAT_VAX.  */
-   "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
-  "-1.70141173319264430e+38",
-   "2.93873587705571877e-39", /* 2^-128 */
-  "-2.93873587705571877e-39",
-  /* These are for the default broken IEEE mode, which traps
-     on infinity or denormal numbers.  */
-   "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
-  "-3.402823466385288598117e+38",
-   "1.1754943508222875079687e-38", /* 2^-126 */
-  "-1.1754943508222875079687e-38",
-};
-
-static REAL_VALUE_TYPE float_values[8];
-static int inited_float_values = 0;
-
-int
-check_float_value (mode, d, overflow)
-     enum machine_mode mode;
-     REAL_VALUE_TYPE *d;
-     int overflow ATTRIBUTE_UNUSED;
-{
-
-  if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT)
-    return 0;
-
-  if (inited_float_values == 0)
-    {
-      int i;
-      for (i = 0; i < 8; i++)
-       float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
-
-      inited_float_values = 1;
-    }
-
-  if (mode == SFmode)
-    {
-      REAL_VALUE_TYPE r;
-      REAL_VALUE_TYPE *fvptr;
-
-      if (TARGET_FLOAT_VAX)
-       fvptr = &float_values[0];
-      else
-       fvptr = &float_values[4];
-
-      memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
-      if (REAL_VALUES_LESS (fvptr[0], r))
-       {
-         memcpy (d, &fvptr[0], sizeof (REAL_VALUE_TYPE));
-         return 1;
-       }
-      else if (REAL_VALUES_LESS (r, fvptr[1]))
-       {
-         memcpy (d, &fvptr[1], sizeof (REAL_VALUE_TYPE));
-         return 1;
-       }
-      else if (REAL_VALUES_LESS (dconst0, r)
-               && REAL_VALUES_LESS (r, fvptr[2]))
-       {
-         memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
-         return 1;
-       }
-      else if (REAL_VALUES_LESS (r, dconst0)
-               && REAL_VALUES_LESS (fvptr[3], r))
-       {
-         memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
-         return 1;
-       }
+       alpha_align_insns (16, alphaev5_next_group, alphaev5_next_nop);
     }
     }
-
-  return 0;
 }
 \f
 #ifdef OBJECT_FORMAT_ELF
 }
 \f
 #ifdef OBJECT_FORMAT_ELF
@@ -8537,6 +9140,34 @@ alpha_elf_select_rtx_section (mode, x, align)
 
 #endif /* OBJECT_FORMAT_ELF */
 \f
 
 #endif /* OBJECT_FORMAT_ELF */
 \f
+/* Structure to collect function names for final output in link section.  */
+/* Note that items marked with GTY can't be ifdef'ed out.  */
+
+enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
+
+struct alpha_links GTY(())
+{
+  int num;
+  rtx linkage;
+  enum links_kind lkind;
+  enum reloc_kind rkind;
+};
+
+struct alpha_funcs GTY(())
+{
+  int num;
+  splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+    links;
+};
+
+static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
+  splay_tree alpha_links_tree;
+static GTY ((param1_is (tree), param2_is (struct alpha_funcs *)))
+  splay_tree alpha_funcs_tree;
+
+static GTY(()) int alpha_funcs_num;
+
 #if TARGET_ABI_OPEN_VMS
 
 /* Return the VMS argument type corresponding to MODE.  */
 #if TARGET_ABI_OPEN_VMS
 
 /* Return the VMS argument type corresponding to MODE.  */
@@ -8572,45 +9203,6 @@ alpha_arg_info_reg_val (cum)
   return GEN_INT (regval);
 }
 \f
   return GEN_INT (regval);
 }
 \f
-#include <splay-tree.h>
-
-/* Structure to collect function names for final output
-   in link section.  */
-
-enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
-
-struct alpha_links
-{
-  rtx linkage;
-  enum links_kind kind;
-};
-
-static splay_tree alpha_links;
-
-static int mark_alpha_links_node       PARAMS ((splay_tree_node, void *));
-static void mark_alpha_links           PARAMS ((void *));
-static int alpha_write_one_linkage     PARAMS ((splay_tree_node, void *));
-
-/* Protect alpha_links from garbage collection.  */
-
-static int
-mark_alpha_links_node (node, data)
-     splay_tree_node node;
-     void *data ATTRIBUTE_UNUSED;
-{
-  struct alpha_links *links = (struct alpha_links *) node->value;
-  ggc_mark_rtx (links->linkage);
-  return 0;
-}
-
-static void
-mark_alpha_links (ptr)
-     void *ptr;
-{
-  splay_tree tree = *(splay_tree *) ptr;
-  splay_tree_foreach (tree, mark_alpha_links_node, NULL);
-}
-
 /* Make (or fake) .linkage entry for function call.
 
    IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.
 /* Make (or fake) .linkage entry for function call.
 
    IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.
@@ -8628,42 +9220,55 @@ alpha_need_linkage (name, is_local)
   if (name[0] == '*')
     name++;
 
   if (name[0] == '*')
     name++;
 
-  if (alpha_links)
+  if (is_local)
+    {
+      struct alpha_funcs *cfaf;
+
+      if (!alpha_funcs_tree)
+        alpha_funcs_tree = splay_tree_new_ggc ((splay_tree_compare_fn)
+                                              splay_tree_compare_pointers);
+    
+      cfaf = (struct alpha_funcs *) ggc_alloc (sizeof (struct alpha_funcs));
+
+      cfaf->links = 0;
+      cfaf->num = ++alpha_funcs_num;
+
+      splay_tree_insert (alpha_funcs_tree,
+                        (splay_tree_key) current_function_decl,
+                        (splay_tree_value) cfaf);
+    }
+
+  if (alpha_links_tree)
     {
       /* Is this name already defined?  */
 
     {
       /* Is this name already defined?  */
 
-      node = splay_tree_lookup (alpha_links, (splay_tree_key) name);
+      node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
       if (node)
        {
          al = (struct alpha_links *) node->value;
          if (is_local)
            {
              /* Defined here but external assumed.  */
       if (node)
        {
          al = (struct alpha_links *) node->value;
          if (is_local)
            {
              /* Defined here but external assumed.  */
-             if (al->kind == KIND_EXTERN)
-               al->kind = KIND_LOCAL;
+             if (al->lkind == KIND_EXTERN)
+               al->lkind = KIND_LOCAL;
            }
          else
            {
              /* Used here but unused assumed.  */
            }
          else
            {
              /* Used here but unused assumed.  */
-             if (al->kind == KIND_UNUSED)
-               al->kind = KIND_LOCAL;
+             if (al->lkind == KIND_UNUSED)
+               al->lkind = KIND_LOCAL;
            }
          return al->linkage;
        }
     }
   else
            }
          return al->linkage;
        }
     }
   else
-    {
-      alpha_links = splay_tree_new ((splay_tree_compare_fn) strcmp, 
-                                   (splay_tree_delete_key_fn) free,
-                                   (splay_tree_delete_key_fn) free);
-      ggc_add_root (&alpha_links, 1, 1, mark_alpha_links);
-    }
+    alpha_links_tree = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
 
 
-  al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
-  name = xstrdup (name);
+  al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
+  name = ggc_strdup (name);
 
   /* Assume external if no definition.  */
 
   /* Assume external if no definition.  */
-  al->kind = (is_local ? KIND_UNUSED : KIND_EXTERN);
+  al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
 
   /* Ensure we have an IDENTIFIER so assemble_name can mark it used.  */
   get_identifier (name);
 
   /* Ensure we have an IDENTIFIER so assemble_name can mark it used.  */
   get_identifier (name);
@@ -8679,50 +9284,159 @@ alpha_need_linkage (name, is_local)
                                      ggc_alloc_string (linksym, name_len + 5));
   }
 
                                      ggc_alloc_string (linksym, name_len + 5));
   }
 
-  splay_tree_insert (alpha_links, (splay_tree_key) name,
+  splay_tree_insert (alpha_links_tree, (splay_tree_key) name,
                     (splay_tree_value) al);
 
   return al->linkage;
 }
 
                     (splay_tree_value) al);
 
   return al->linkage;
 }
 
+rtx
+alpha_use_linkage (linkage, cfundecl, lflag, rflag)
+     rtx linkage;
+     tree cfundecl;
+     int lflag;
+     int rflag;
+{
+  splay_tree_node cfunnode;
+  struct alpha_funcs *cfaf;
+  struct alpha_links *al;
+  const char *name = XSTR (linkage, 0);
+
+  cfaf = (struct alpha_funcs *) 0;
+  al = (struct alpha_links *) 0;
+
+  cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl);
+  cfaf = (struct alpha_funcs *) cfunnode->value;
+
+  if (cfaf->links)
+    {
+      splay_tree_node lnode;
+
+      /* Is this name already defined?  */
+
+      lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name);
+      if (lnode)
+       al = (struct alpha_links *) lnode->value;
+    }
+  else
+    cfaf->links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
+
+  if (!al)
+    {
+      size_t name_len;
+      size_t buflen;
+      char buf [512];
+      char *linksym;
+      splay_tree_node node = 0;
+      struct alpha_links *anl;
+
+      if (name[0] == '*')
+       name++;
+
+      name_len = strlen (name);
+
+      al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
+      al->num = cfaf->num;
+
+      node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
+      if (node)
+       {
+         anl = (struct alpha_links *) node->value;
+         al->lkind = anl->lkind;
+       }
+
+      sprintf (buf, "$%d..%s..lk", cfaf->num, name);
+      buflen = strlen (buf);
+      linksym = alloca (buflen + 1);
+      memcpy (linksym, buf, buflen + 1);
+
+      al->linkage = gen_rtx_SYMBOL_REF
+       (Pmode, ggc_alloc_string (linksym, buflen + 1));
+
+      splay_tree_insert (cfaf->links, (splay_tree_key) name,
+                        (splay_tree_value) al);
+    }
+
+  if (rflag)
+    al->rkind = KIND_CODEADDR;
+  else
+    al->rkind = KIND_LINKAGE;
+      
+  if (lflag)
+    return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8));
+  else
+    return al->linkage;
+}
+
 static int
 alpha_write_one_linkage (node, data)
      splay_tree_node node;
      void *data;
 {
   const char *const name = (const char *) node->key;
 static int
 alpha_write_one_linkage (node, data)
      splay_tree_node node;
      void *data;
 {
   const char *const name = (const char *) node->key;
-  struct alpha_links *links = (struct alpha_links *) node->value;
+  struct alpha_links *link = (struct alpha_links *) node->value;
   FILE *stream = (FILE *) data;
 
   FILE *stream = (FILE *) data;
 
-  if (links->kind == KIND_UNUSED
-      || ! TREE_SYMBOL_REFERENCED (get_identifier (name)))
-    return 0;
-
-  fprintf (stream, "$%s..lk:\n", name);
-  if (links->kind == KIND_LOCAL)
+  fprintf (stream, "$%d..%s..lk:\n", link->num, name);
+  if (link->rkind == KIND_CODEADDR)
     {
     {
-      /* Local and used, build linkage pair.  */
-      fprintf (stream, "\t.quad %s..en\n", name);
-      fprintf (stream, "\t.quad %s\n", name);
+      if (link->lkind == KIND_LOCAL)
+       {
+         /* Local and used */
+         fprintf (stream, "\t.quad %s..en\n", name);
+       }
+      else
+       {
+         /* External and used, request code address.  */
+         fprintf (stream, "\t.code_address %s\n", name);
+       }
     }
   else
     {
     }
   else
     {
-      /* External and used, request linkage pair.  */
-      fprintf (stream, "\t.linkage %s\n", name);
+      if (link->lkind == KIND_LOCAL)
+       {
+         /* Local and used, build linkage pair.  */
+         fprintf (stream, "\t.quad %s..en\n", name);
+         fprintf (stream, "\t.quad %s\n", name);
+       }
+      else
+       {
+         /* External and used, request linkage pair.  */
+         fprintf (stream, "\t.linkage %s\n", name);
+       }
     }
 
   return 0;
 }
 
     }
 
   return 0;
 }
 
-void
-alpha_write_linkage (stream)
-    FILE *stream;
+static void
+alpha_write_linkage (stream, funname, fundecl)
+     FILE *stream;
+     const char *funname;
+     tree fundecl;
 {
 {
-  if (alpha_links)
+  splay_tree_node node;
+  struct alpha_funcs *func;
+
+  link_section ();
+  fprintf (stream, "\t.align 3\n");
+  node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl);
+  func = (struct alpha_funcs *) node->value;
+
+  fputs ("\t.name ", stream);
+  assemble_name (stream, funname);
+  fputs ("..na\n", stream);
+  ASM_OUTPUT_LABEL (stream, funname);
+  fprintf (stream, "\t.pdesc ");
+  assemble_name (stream, funname);
+  fprintf (stream, "..en,%s\n",
+          alpha_procedure_type == PT_STACK ? "stack"
+          : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
+
+  if (func->links)
     {
     {
-      readonly_data_section ();
-      fprintf (stream, "\t.align 3\n");
-      splay_tree_foreach (alpha_links, alpha_write_one_linkage, stream);
+      splay_tree_foreach (func->links, alpha_write_one_linkage, stream);
+      /* splay_tree_delete (func->links); */
     }
 }
 
     }
 }
 
@@ -8815,6 +9529,16 @@ alpha_need_linkage (name, is_local)
   return NULL_RTX;
 }
 
   return NULL_RTX;
 }
 
+rtx
+alpha_use_linkage (linkage, cfundecl, lflag, rflag)
+     rtx linkage ATTRIBUTE_UNUSED;
+     tree cfundecl ATTRIBUTE_UNUSED;
+     int lflag ATTRIBUTE_UNUSED;
+     int rflag ATTRIBUTE_UNUSED;
+{
+  return NULL_RTX;
+}
+
 #endif /* TARGET_ABI_OPEN_VMS */
 \f
 #if TARGET_ABI_UNICOSMK
 #endif /* TARGET_ABI_OPEN_VMS */
 \f
 #if TARGET_ABI_UNICOSMK
@@ -9030,7 +9754,7 @@ unicosmk_unique_section (decl, reloc)
     abort ();
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
     abort ();
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  name = alpha_strip_name_encoding (name);
+  name = default_strip_name_encoding (name);
   len = strlen (name);
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
   len = strlen (name);
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -9143,7 +9867,7 @@ unicosmk_output_addr_vec (file, vec)
   int vlen = XVECLEN (body, 0);
   int idx;
 
   int vlen = XVECLEN (body, 0);
   int idx;
 
-  ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (lab));
+  (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (lab));
 
   for (idx = 0; idx < vlen; idx++)
     {
 
   for (idx = 0; idx < vlen; idx++)
     {
@@ -9193,14 +9917,14 @@ unicosmk_gen_dsib (imaskP)
       mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
       set_mem_alias_set (mem, alpha_sr_alias_set);
       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
       mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
       set_mem_alias_set (mem, alpha_sr_alias_set);
       FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
-      (*imaskP) &= ~(1L << REG_RA);
+      (*imaskP) &= ~(1UL << REG_RA);
 
       /* Save the old frame pointer.  */
 
       mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
       set_mem_alias_set (mem, alpha_sr_alias_set);
       FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
 
       /* Save the old frame pointer.  */
 
       mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
       set_mem_alias_set (mem, alpha_sr_alias_set);
       FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
-      (*imaskP) &= ~(1L << HARD_FRAME_POINTER_REGNUM);
+      (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM);
 
       emit_insn (gen_blockage ());
 
 
       emit_insn (gen_blockage ());
 
@@ -9261,7 +9985,7 @@ unicosmk_ssib_name ()
   x = XEXP (x, 0);
   if (GET_CODE (x) != SYMBOL_REF)
     abort ();
   x = XEXP (x, 0);
   if (GET_CODE (x) != SYMBOL_REF)
     abort ();
-  fnname = alpha_strip_name_encoding (XSTR (x, 0));
+  fnname = default_name_encoding (XSTR (x, 0));
 
   len = strlen (fnname);
   if (len + SSIB_PREFIX_LEN > 255)
 
   len = strlen (fnname);
   if (len + SSIB_PREFIX_LEN > 255)
@@ -9327,14 +10051,12 @@ unicosmk_output_ssib (file, fnname)
   for (x = machine->first_ciw; x; x = XEXP (x, 1))
     {
       ciw = XEXP (x, 0);
   for (x = machine->first_ciw; x; x = XEXP (x, 1))
     {
       ciw = XEXP (x, 0);
-      fprintf (file, "\t.quad\t");
 #if HOST_BITS_PER_WIDE_INT == 32
 #if HOST_BITS_PER_WIDE_INT == 32
-      fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+      fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_DOUBLE_HEX "\n",
               CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
 #else
               CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
 #else
-      fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (ciw));
+      fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw));
 #endif
 #endif
-      fprintf (file, "\n");
     }
 }
 
     }
 }
 
@@ -9391,6 +10113,7 @@ unicosmk_data_section ()
 
 /* List of identifiers for which an extern declaration might have to be
    emitted.  */
 
 /* List of identifiers for which an extern declaration might have to be
    emitted.  */
+/* FIXME: needs to use GC, so it can be saved and restored for PCH.  */
 
 struct unicosmk_extern_list
 {
 
 struct unicosmk_extern_list
 {
@@ -9436,7 +10159,7 @@ unicosmk_output_externs (file)
       /* We have to strip the encoding and possibly remove user_label_prefix 
         from the identifier in order to handle -fleading-underscore and
         explicit asm names correctly (cf. gcc.dg/asm-names-1.c).  */
       /* We have to strip the encoding and possibly remove user_label_prefix 
         from the identifier in order to handle -fleading-underscore and
         explicit asm names correctly (cf. gcc.dg/asm-names-1.c).  */
-      real_name = alpha_strip_name_encoding (p->name);
+      real_name = default_strip_name_encoding (p->name);
       if (len && p->name[0] == '*'
          && !memcmp (real_name, user_label_prefix, len))
        real_name += len;
       if (len && p->name[0] == '*'
          && !memcmp (real_name, user_label_prefix, len))
        real_name += len;
@@ -9461,7 +10184,7 @@ unicosmk_add_extern (name)
   struct unicosmk_extern_list *p;
 
   p = (struct unicosmk_extern_list *)
   struct unicosmk_extern_list *p;
 
   p = (struct unicosmk_extern_list *)
-       permalloc (sizeof (struct unicosmk_extern_list));
+       xmalloc (sizeof (struct unicosmk_extern_list));
   p->next = unicosmk_extern_head;
   p->name = name;
   unicosmk_extern_head = p;
   p->next = unicosmk_extern_head;
   p->name = name;
   unicosmk_extern_head = p;
@@ -9473,6 +10196,7 @@ unicosmk_add_extern (name)
 
 /* Structure to collect identifiers which have been replaced by DEX
    expressions.  */
 
 /* Structure to collect identifiers which have been replaced by DEX
    expressions.  */
+/* FIXME: needs to use GC, so it can be saved and restored for PCH.  */
 
 struct unicosmk_dex {
   struct unicosmk_dex *next;
 
 struct unicosmk_dex {
   struct unicosmk_dex *next;
@@ -9543,7 +10267,7 @@ unicosmk_need_dex (x)
       --i;
     }
       
       --i;
     }
       
-  dex = (struct unicosmk_dex *) permalloc (sizeof (struct unicosmk_dex));
+  dex = (struct unicosmk_dex *) xmalloc (sizeof (struct unicosmk_dex));
   dex->name = name;
   dex->next = unicosmk_dex_list;
   unicosmk_dex_list = dex;
   dex->name = name;
   dex->next = unicosmk_dex_list;
   unicosmk_dex_list = dex;
@@ -9611,3 +10335,6 @@ unicosmk_need_dex (x)
 }
 
 #endif /* TARGET_ABI_UNICOSMK */
 }
 
 #endif /* TARGET_ABI_UNICOSMK */
+
+#include "gt-alpha.h"
+
This page took 0.111185 seconds and 5 git commands to generate.