]> 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,
-   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.
@@ -23,6 +23,8 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.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 <splay-tree.h>
 
 /* 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;
 
-/* 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;
@@ -103,37 +106,92 @@ static int alpha_function_needs_gp;
 
 /* 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.  */
+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.  */
+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;
 
+/* 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.  */
+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 bool decl_in_text_section
+static bool decl_has_samegp
   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 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
@@ -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));
+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 int find_lo_sum
+static int find_lo_sum_using_gp
   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));
+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
 
-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));
@@ -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_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));
@@ -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
+# undef TARGET_ASM_GLOBALIZE_LABEL
+# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void
 #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_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.  */
@@ -553,8 +650,14 @@ override_options ()
 
   /* 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.  */
@@ -610,6 +713,16 @@ reg_or_8bit_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
@@ -716,24 +829,26 @@ mode_mask_operand (op, mode)
      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.  */
@@ -813,8 +928,15 @@ some_operand (op, mode)
 
   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:
@@ -893,7 +1015,8 @@ input_operand (op, mode)
              && 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);
@@ -912,25 +1035,32 @@ input_operand (op, mode)
    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)
-    return 0;
+    return false;
 
   /* 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.  */
@@ -940,32 +1070,60 @@ direct_call_operand (op, 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
-     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.  */
-  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
-   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;
 {
-  const char *str;
-
   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;
 
-  /* 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
@@ -1010,8 +1149,6 @@ small_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  const char *str;
-
   if (! TARGET_SMALL_DATA)
     return 0;
 
@@ -1026,13 +1163,14 @@ small_symbolic_operand (op, mode)
   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))
-    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
@@ -1043,8 +1181,6 @@ global_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;
 
@@ -1056,12 +1192,7 @@ global_symbolic_operand (op, mode)
   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.  */
@@ -1122,9 +1253,6 @@ tls_symbolic_operand_1 (op, mode, 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;
 
@@ -1138,24 +1266,29 @@ tls_symbolic_operand_1 (op, mode, size, unspec)
 
   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;
     }
-  else if (str[0] == '@')
+  else
     {
-      if (alpha_tls_size > size)
+      if (size != 64)
        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.  */
@@ -1615,7 +1748,9 @@ alpha_extra_constraint (value, c)
       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;
     }
@@ -1695,62 +1830,42 @@ static enum tls_model
 tls_symbolic_operand_type (symbol)
      rtx symbol;
 {
-  const char *str;
+  enum tls_model model;
 
   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
-/* 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
-decl_in_text_section (decl)
+decl_has_samegp (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.  */
@@ -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 (size > 0 && size <= g_switch_value)
+      if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
        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
@@ -1952,6 +1959,11 @@ alpha_legitimate_address_p (mode, x, strict)
   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)
     {
@@ -2017,6 +2029,18 @@ alpha_legitimate_address_p (mode, x, strict)
   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.  */
 
@@ -2084,7 +2108,7 @@ alpha_legitimize_address (x, scratch, mode)
 
          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++);
          
@@ -2105,7 +2129,7 @@ alpha_legitimize_address (x, scratch, mode)
 
          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++);
 
@@ -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))
@@ -2265,6 +2308,49 @@ split_small_symbolic_operand_1 (px, data)
   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.  */
    
@@ -2323,6 +2409,150 @@ alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
   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
@@ -2494,6 +2724,8 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
   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,
@@ -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)
@@ -2943,7 +3175,7 @@ alpha_expand_mov (mode, operands)
     }
 
   /* 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));
@@ -3247,7 +3479,7 @@ alpha_emit_conditional_branch (code)
        }
       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;
@@ -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 ...).
-   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
@@ -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
-        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)
@@ -3834,7 +4066,7 @@ alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
       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;
@@ -3979,7 +4211,7 @@ alpha_split_tfmode_frobsign (operands, operation)
 
   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;
@@ -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 (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));
+           break;
          }
+       case 8:
+         emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr));
          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 (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));
+           break;
          }
+       case 8:
+         emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr));
          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);
-#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;
@@ -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)
     {
-      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_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)
@@ -5147,6 +5366,75 @@ alpha_expand_block_clear (operands)
 
   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.  */
@@ -5214,9 +5502,9 @@ alpha_multipass_dfa_lookahead ()
 \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;
@@ -5224,58 +5512,18 @@ struct machine_function
 
   /* List of deferred case vectors.  */
   struct rtx_def *addr_list;
-#else
-#if TARGET_ABI_OSF
+
+  /* For OSF. */
   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.  */
@@ -5301,7 +5549,7 @@ alpha_gp_save_rtx ()
 {
   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;
 }
 
@@ -5446,14 +5694,11 @@ get_some_local_dynamic_name_1 (px, data)
 {
   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;
@@ -5501,6 +5746,13 @@ print_operand (file, x, code)
       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++;
@@ -5652,31 +5904,40 @@ print_operand (file, x, code)
 
     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':
@@ -5851,10 +6112,7 @@ print_operand_address (file, addr)
        }
 
       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)
@@ -5877,11 +6135,28 @@ print_operand_address (file, 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 ();
 
-  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
@@ -5940,8 +6215,8 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
     }
 
 #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)
@@ -6109,9 +6384,55 @@ alpha_build_va_list ()
   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
-alpha_va_start (stdarg_p, valist, nextarg)
-     int stdarg_p;
+alpha_va_start (valist, nextarg)
      tree valist;
      rtx nextarg ATTRIBUTE_UNUSED;
 {
@@ -6122,7 +6443,7 @@ alpha_va_start (stdarg_p, valist, nextarg)
     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
@@ -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
-     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 = -6 * UNITS_PER_WORD;
+    offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size;
 
   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));
 
-  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
@@ -6298,10 +6926,11 @@ alpha_sa_mask (imaskP, fmaskP)
   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;
@@ -6310,7 +6939,7 @@ alpha_sa_mask (imaskP, fmaskP)
     }
 
   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++)
@@ -6319,9 +6948,9 @@ alpha_sa_mask (imaskP, fmaskP)
        && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
       {
        if (i < 32)
-         imask |= (1L << i);
+         imask |= (1UL << i);
        else
-         fmask |= (1L << (i - 32));
+         fmask |= (1UL << (i - 32));
       }
 
   /* 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;
-       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 ())
-    imask |= (1L << REG_RA);
+    imask |= (1UL << REG_RA);
 
   *imaskP = imask;
   *fmaskP = fmask;
@@ -6376,7 +7005,7 @@ alpha_sa_size ()
 
       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;
@@ -6447,6 +7076,30 @@ alpha_sa_size ()
   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 ()
 {
@@ -6475,11 +7128,18 @@ const struct attribute_spec vms_attribute_table[] =
 #endif
 
 static int
-find_lo_sum (px, data)
+find_lo_sum_using_gp (px, data)
      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
@@ -6508,15 +7168,9 @@ alpha_does_function_need_gp ()
   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;
 }
@@ -6543,22 +7197,30 @@ alpha_write_verstamp (file)
 static rtx
 set_frame_related_p ()
 {
-  rtx seq = gen_sequence ();
+  rtx seq = get_insns ();
+  rtx insn;
+
   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;
-      return seq;
     }
+  return seq;
 }
 
 #define FRP(exp)  (start_sequence (), exp, set_frame_related_p ())
@@ -6769,18 +7431,18 @@ alpha_expand_prologue ()
        }
 
       /* 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)));
-         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++)
-       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);
@@ -6789,7 +7451,7 @@ alpha_expand_prologue ()
          }
 
       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);
@@ -6805,7 +7467,7 @@ alpha_expand_prologue ()
 
       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));
@@ -6814,7 +7476,7 @@ alpha_expand_prologue ()
            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));
@@ -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)
-       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)
     {
@@ -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.  */
-  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);
@@ -7006,23 +7688,17 @@ alpha_start_function (file, fnname, decl)
   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)
-    {
-      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)
@@ -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.  */
-       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)
@@ -7042,23 +7718,17 @@ alpha_start_function (file, fnname, decl)
     {
       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)
-           if (imask & (1L << i))
+           if (imask & (1UL << i))
              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
@@ -7069,18 +7739,6 @@ alpha_start_function (file, fnname, decl)
   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
@@ -7204,10 +7862,10 @@ alpha_expand_epilogue ()
       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)
-       if (imask & (1L << i))
+       if (imask & (1UL << i))
          {
            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)
-       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);
@@ -7236,7 +7894,7 @@ alpha_expand_epilogue ()
       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));
@@ -7246,7 +7904,7 @@ alpha_expand_epilogue ()
          }
 
       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));
@@ -7366,7 +8024,7 @@ alpha_expand_epilogue ()
         }
     }
 }
-
+\f
 /* Output the rest of the textual info surrounding the epilogue.  */
 
 void
@@ -7384,20 +8042,9 @@ alpha_end_function (file, fnname, decl)
     }
   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)
@@ -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
@@ -7416,11 +8064,12 @@ alpha_end_function (file, fnname, decl)
 
    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;
+     HOST_WIDE_INT vcall_offset;
      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));
     }
 
+  /* 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))
     {
@@ -7476,6 +8156,7 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
   final (insn, file, 1, 0);
   final_end_function ();
 }
+#endif /* TARGET_ABI_OSF */
 \f
 /* Debugging support.  */
 
@@ -7580,7 +8261,7 @@ struct shadow_summary
 };
 
 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
@@ -7744,8 +8425,7 @@ summarize_insn (x, sum, set)
    (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;
@@ -7758,7 +8438,7 @@ alpha_handle_trap_shadows (insns)
   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)
        {
@@ -7906,7 +8586,7 @@ static rtx alphaev4_next_nop PARAMS ((int *));
 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)
@@ -7938,6 +8618,7 @@ alphaev4_insn_pipe (insn)
     case TYPE_MISC:
     case TYPE_IBR:
     case TYPE_JSR:
+    case TYPE_CALLPAL:
     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_CALLPAL:
       return EV5_E1;
 
     case TYPE_FCPYS:
@@ -8293,8 +8975,7 @@ alphaev5_next_nop (pin_use)
 /* 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 *));
@@ -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.  */
-  shorten_branches (insns);
+  shorten_branches (get_insns ());
 
   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;
-  i = insns;
+  i = get_insns ();
   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.  */
 
-void
-alpha_reorg (insns)
-     rtx insns;
+static void
+alpha_reorg ()
 {
   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
@@ -8434,87 +9114,10 @@ alpha_reorg (insns)
       && 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)
-       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
@@ -8537,6 +9140,34 @@ alpha_elf_select_rtx_section (mode, x, align)
 
 #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.  */
@@ -8572,45 +9203,6 @@ alpha_arg_info_reg_val (cum)
   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.
@@ -8628,42 +9220,55 @@ alpha_need_linkage (name, is_local)
   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?  */
 
-      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 (al->kind == KIND_EXTERN)
-               al->kind = KIND_LOCAL;
+             if (al->lkind == KIND_EXTERN)
+               al->lkind = KIND_LOCAL;
            }
          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
-    {
-      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.  */
-  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);
@@ -8679,50 +9284,159 @@ alpha_need_linkage (name, is_local)
                                      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;
 }
 
+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;
-  struct alpha_links *links = (struct alpha_links *) node->value;
+  struct alpha_links *link = (struct alpha_links *) node->value;
   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
     {
-      /* 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;
 }
 
-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;
 }
 
+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
@@ -9030,7 +9754,7 @@ unicosmk_unique_section (decl, reloc)
     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)
@@ -9143,7 +9867,7 @@ unicosmk_output_addr_vec (file, vec)
   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++)
     {
@@ -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)));
-      (*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));
-      (*imaskP) &= ~(1L << HARD_FRAME_POINTER_REGNUM);
+      (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM);
 
       emit_insn (gen_blockage ());
 
@@ -9261,7 +9985,7 @@ unicosmk_ssib_name ()
   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)
@@ -9327,14 +10051,12 @@ unicosmk_output_ssib (file, fnname)
   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
-      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
-      fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (ciw));
+      fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw));
 #endif
-      fprintf (file, "\n");
     }
 }
 
@@ -9391,6 +10113,7 @@ unicosmk_data_section ()
 
 /* 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
 {
@@ -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).  */
-      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;
@@ -9461,7 +10184,7 @@ unicosmk_add_extern (name)
   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;
@@ -9473,6 +10196,7 @@ unicosmk_add_extern (name)
 
 /* 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;
@@ -9543,7 +10267,7 @@ unicosmk_need_dex (x)
       --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;
@@ -9611,3 +10335,6 @@ unicosmk_need_dex (x)
 }
 
 #endif /* TARGET_ABI_UNICOSMK */
+
+#include "gt-alpha.h"
+
This page took 0.115093 seconds and 5 git commands to generate.