Add -Wshadow to the gcc command line options used when compiling the binutils.
[deliverable/binutils-gdb.git] / gas / config / tc-ia64.c
index c7a6b07884627e0b5cdb2778e0849e9f9a50c71f..dcaa416178b36562ae334477cd39d808c41fdd36 100644 (file)
@@ -1,13 +1,13 @@
 /* tc-ia64.c -- Assembler for the HP/Intel IA-64 architecture.
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008, 2009   Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /*
   TODO:
 #include "opcode/ia64.h"
 
 #include "elf/ia64.h"
+#include "bfdver.h"
+#include <time.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 #define NELEMS(a)      ((int) (sizeof (a)/sizeof ((a)[0])))
+
+/* Some systems define MIN in, e.g., param.h.  */
+#undef MIN
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
 
 #define NUM_SLOTS      4
@@ -117,7 +126,6 @@ enum reg_symbol
     IND_DTR,
     IND_ITR,
     IND_IBR,
-    IND_MEM,
     IND_MSR,
     IND_PKR,
     IND_PMC,
@@ -152,6 +160,7 @@ struct label_fix
 {
   struct label_fix *next;
   struct symbol *sym;
+  bfd_boolean dw2_mark_labels;
 };
 
 /* This is the endianness of the current section.  */
@@ -160,14 +169,12 @@ extern int target_big_endian;
 /* This is the default endianness.  */
 static int default_big_endian = TARGET_BYTES_BIG_ENDIAN;
 
-void (*ia64_number_to_chars) PARAMS ((char *, valueT, int));
+void (*ia64_number_to_chars) (char *, valueT, int);
+
+static void ia64_float_to_chars_bigendian (char *, LITTLENUM_TYPE *, int);
+static void ia64_float_to_chars_littleendian (char *, LITTLENUM_TYPE *, int);
 
-static void ia64_float_to_chars_bigendian
-  PARAMS ((char *, LITTLENUM_TYPE *, int));
-static void ia64_float_to_chars_littleendian
-  PARAMS ((char *, LITTLENUM_TYPE *, int));
-static void (*ia64_float_to_chars)
-  PARAMS ((char *, LITTLENUM_TYPE *, int));
+static void (*ia64_float_to_chars) (char *, LITTLENUM_TYPE *, int);
 
 static struct hash_control *alias_hash;
 static struct hash_control *alias_name_hash;
@@ -186,7 +193,7 @@ const char line_comment_chars[] = "#";
 
 /* Characters which may be used to separate multiple commands on a
    single line.  */
-const char line_separator_chars[] = ";";
+const char line_separator_chars[] = ";{}";
 
 /* Characters which are used to indicate an exponent in a floating
    point number.  */
@@ -218,13 +225,26 @@ static struct
     struct hash_control *const_hash;   /* constant hash table */
     struct hash_control *entry_hash;    /* code entry hint hash table */
 
-    symbolS *regsym[REG_NUM];
-
     /* If X_op is != O_absent, the registername for the instruction's
        qualifying predicate.  If NULL, p0 is assumed for instructions
-       that are predicatable.  */
+       that are predictable.  */
     expressionS qp;
 
+    /* Optimize for which CPU.  */
+    enum
+      {
+       itanium1,
+       itanium2
+      } tune;
+
+    /* What to do when hint.b is used.  */
+    enum
+      {
+       hint_b_error,
+       hint_b_warning,
+       hint_b_ok
+      } hint_b;
+
     unsigned int
       manual_bundling : 1,
       debug_dv: 1,
@@ -306,9 +326,26 @@ static struct
 
     int pointer_size;       /* size in bytes of a pointer */
     int pointer_size_shift; /* shift size of a pointer for alignment */
+
+    symbolS *indregsym[IND_RR - IND_CPUID + 1];
   }
 md;
 
+/* These are not const, because they are modified to MMI for non-itanium1
+   targets below.  */
+/* MFI bundle of nops.  */
+static unsigned char le_nop[16] =
+{
+  0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
+};
+/* MFI bundle of nops with stop-bit.  */
+static unsigned char le_nop_stop[16] =
+{
+  0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
+};
+
 /* application registers:  */
 
 #define AR_K0          0
@@ -317,33 +354,53 @@ md;
 #define AR_BSP         17
 #define AR_BSPSTORE    18
 #define AR_RNAT                19
+#define AR_FCR         21
+#define AR_EFLAG       24
+#define AR_CSD         25
+#define AR_SSD         26
+#define AR_CFLG                27
+#define AR_FSR         28
+#define AR_FIR         29
+#define AR_FDR         30
+#define AR_CCV         32
 #define AR_UNAT                36
 #define AR_FPSR                40
 #define AR_ITC         44
+#define AR_RUC         45
 #define AR_PFS         64
 #define AR_LC          65
+#define AR_EC          66
 
 static const struct
   {
     const char *name;
-    int regnum;
+    unsigned int regnum;
   }
 ar[] =
   {
-    {"ar.k0", 0}, {"ar.k1", 1}, {"ar.k2", 2}, {"ar.k3", 3},
-    {"ar.k4", 4}, {"ar.k5", 5}, {"ar.k6", 6}, {"ar.k7", 7},
-    {"ar.rsc",         16}, {"ar.bsp",         17},
-    {"ar.bspstore",    18}, {"ar.rnat",        19},
-    {"ar.fcr",         21}, {"ar.eflag",       24},
-    {"ar.csd",         25}, {"ar.ssd",         26},
-    {"ar.cflg",                27}, {"ar.fsr",         28},
-    {"ar.fir",         29}, {"ar.fdr",         30},
-    {"ar.ccv",         32}, {"ar.unat",        36},
-    {"ar.fpsr",                40}, {"ar.itc",         44},
-    {"ar.pfs",         64}, {"ar.lc",          65},
-    {"ar.ec",          66},
+    {"ar.k0",          AR_K0},         {"ar.k1",       AR_K0 + 1},
+    {"ar.k2",          AR_K0 + 2},     {"ar.k3",       AR_K0 + 3},
+    {"ar.k4",          AR_K0 + 4},     {"ar.k5",       AR_K0 + 5},
+    {"ar.k6",          AR_K0 + 6},     {"ar.k7",       AR_K7},
+    {"ar.rsc",         AR_RSC},        {"ar.bsp",      AR_BSP},
+    {"ar.bspstore",    AR_BSPSTORE},   {"ar.rnat",     AR_RNAT},
+    {"ar.fcr",         AR_FCR},        {"ar.eflag",    AR_EFLAG},
+    {"ar.csd",         AR_CSD},        {"ar.ssd",      AR_SSD},
+    {"ar.cflg",                AR_CFLG},       {"ar.fsr",      AR_FSR},
+    {"ar.fir",         AR_FIR},        {"ar.fdr",      AR_FDR},
+    {"ar.ccv",         AR_CCV},        {"ar.unat",     AR_UNAT},
+    {"ar.fpsr",                AR_FPSR},       {"ar.itc",      AR_ITC},
+    {"ar.ruc",         AR_RUC},        {"ar.pfs",      AR_PFS},
+    {"ar.lc",          AR_LC},         {"ar.ec",       AR_EC},
   };
 
+/* control registers:  */
+
+#define CR_DCR           0
+#define CR_ITM           1
+#define CR_IVA           2
+#define CR_PTA           8
+#define CR_GPTA          9
 #define CR_IPSR         16
 #define CR_ISR          17
 #define CR_IIP          19
@@ -353,49 +410,56 @@ ar[] =
 #define CR_IFS          23
 #define CR_IIM          24
 #define CR_IHA          25
+#define CR_IIB0         26
+#define CR_IIB1         27
+#define CR_LID          64
 #define CR_IVR          65
 #define CR_TPR          66
 #define CR_EOI          67
 #define CR_IRR0         68
 #define CR_IRR3         71
+#define CR_ITV          72
+#define CR_PMV          73
+#define CR_CMCV         74
 #define CR_LRR0         80
 #define CR_LRR1         81
 
-/* control registers:  */
 static const struct
   {
     const char *name;
-    int regnum;
+    unsigned int regnum;
   }
 cr[] =
   {
-    {"cr.dcr",  0},
-    {"cr.itm",  1},
-    {"cr.iva",  2},
-    {"cr.pta",  8},
-    {"cr.gpta",         9},
-    {"cr.ipsr",        16},
-    {"cr.isr", 17},
-    {"cr.iip", 19},
-    {"cr.ifa", 20},
-    {"cr.itir",        21},
-    {"cr.iipa",        22},
-    {"cr.ifs", 23},
-    {"cr.iim", 24},
-    {"cr.iha", 25},
-    {"cr.lid", 64},
-    {"cr.ivr", 65},
-    {"cr.tpr", 66},
-    {"cr.eoi", 67},
-    {"cr.irr0",        68},
-    {"cr.irr1",        69},
-    {"cr.irr2",        70},
-    {"cr.irr3",        71},
-    {"cr.itv", 72},
-    {"cr.pmv", 73},
-    {"cr.cmcv",        74},
-    {"cr.lrr0",        80},
-    {"cr.lrr1",        81}
+    {"cr.dcr", CR_DCR},
+    {"cr.itm", CR_ITM},
+    {"cr.iva", CR_IVA},
+    {"cr.pta", CR_PTA},
+    {"cr.gpta",        CR_GPTA},
+    {"cr.ipsr",        CR_IPSR},
+    {"cr.isr", CR_ISR},
+    {"cr.iip", CR_IIP},
+    {"cr.ifa", CR_IFA},
+    {"cr.itir",        CR_ITIR},
+    {"cr.iipa",        CR_IIPA},
+    {"cr.ifs", CR_IFS},
+    {"cr.iim", CR_IIM},
+    {"cr.iha", CR_IHA},
+    {"cr.iib0",        CR_IIB0},
+    {"cr.iib1",        CR_IIB1},
+    {"cr.lid", CR_LID},
+    {"cr.ivr", CR_IVR},
+    {"cr.tpr", CR_TPR},
+    {"cr.eoi", CR_EOI},
+    {"cr.irr0",        CR_IRR0},
+    {"cr.irr1",        CR_IRR0 + 1},
+    {"cr.irr2",        CR_IRR0 + 2},
+    {"cr.irr3",        CR_IRR3},
+    {"cr.itv", CR_ITV},
+    {"cr.pmv", CR_PMV},
+    {"cr.cmcv",        CR_CMCV},
+    {"cr.lrr0",        CR_LRR0},
+    {"cr.lrr1",        CR_LRR1}
   };
 
 #define PSR_MFL         4
@@ -453,7 +517,7 @@ const_bits[] =
 static const struct
   {
     const char *name;
-    int regnum;
+    unsigned int regnum;
   }
 indirect_reg[] =
   {
@@ -556,7 +620,7 @@ static const bfd_vma nop[IA64_NUM_UNITS] =
     0x0008000000LL,    /* M-unit nop */
     0x4000000000LL,    /* B-unit nop */
     0x0008000000LL,    /* F-unit nop */
-    0x0008000000LL,    /* L-"unit" nop */
+    0x0000000000LL,    /* L-"unit" nop immediate */
     0x0008000000LL,    /* X-unit nop */
   };
 
@@ -627,7 +691,17 @@ static struct gr {
   unsigned known:1;
   int path;
   valueT value;
-} gr_values[128] = {{ 1, 0, 0 }};
+} gr_values[128] = {
+  {
+    1,
+#ifdef INT_MAX
+    INT_MAX,
+#else
+    (((1 << (8 * sizeof(gr_values->path) - 2)) - 1) << 1) + 1,
+#endif
+    0
+  }
+};
 
 /* Remember the alignment frag.  */
 static fragS *align_frag;
@@ -648,8 +722,6 @@ typedef struct unw_rec_list {
   unwind_record r;
   unsigned long slot_number;
   fragS *slot_frag;
-  unsigned long next_slot_number;
-  fragS *next_slot_frag;
   struct unw_rec_list *next;
 } unw_rec_list;
 
@@ -664,18 +736,24 @@ typedef struct label_prologue_count
   unsigned int prologue_count;
 } label_prologue_count;
 
+typedef struct proc_pending
+{
+  symbolS *sym;
+  struct proc_pending *next;
+} proc_pending;
+
 static struct
 {
   /* Maintain a list of unwind entries for the current function.  */
   unw_rec_list *list;
   unw_rec_list *tail;
 
-  /* Any unwind entires that should be attached to the current slot
+  /* Any unwind entries that should be attached to the current slot
      that an insn is being constructed for.  */
   unw_rec_list *current_entry;
 
   /* These are used to create the unwind table entry for this function.  */
-  symbolS *proc_start;
+  proc_pending proc_pending;
   symbolS *info;               /* pointer to unwind info */
   symbolS *personality_routine;
   segT saved_text_seg;
@@ -685,11 +763,15 @@ static struct
   /* TRUE if processing unwind directives in a prologue region.  */
   unsigned int prologue : 1;
   unsigned int prologue_mask : 4;
+  unsigned int prologue_gr : 7;
   unsigned int body : 1;
   unsigned int insn : 1;
   unsigned int prologue_count; /* number of .prologues seen so far */
   /* Prologue counts at previous .label_state directives.  */
   struct label_prologue_count * saved_prologue_counts;
+
+  /* List of split up .save-s.  */
+  unw_p_record *pending_saves;
 } unwind;
 
 /* The input value is a negated offset from psp, and specifies an address
@@ -698,218 +780,26 @@ static struct
 
 #define ENCODED_PSP_OFFSET(OFFSET) (((OFFSET) + 16) / 4)
 
-typedef void (*vbyte_func) PARAMS ((int, char *, char *));
+typedef void (*vbyte_func) (int, char *, char *);
 
 /* Forward declarations:  */
-static void set_section PARAMS ((char *name));
-static unsigned int set_regstack PARAMS ((unsigned int, unsigned int,
-                                         unsigned int, unsigned int));
-static void dot_align (int);
-static void dot_radix PARAMS ((int));
-static void dot_special_section PARAMS ((int));
-static void dot_proc PARAMS ((int));
-static void dot_fframe PARAMS ((int));
-static void dot_vframe PARAMS ((int));
-static void dot_vframesp PARAMS ((int));
-static void dot_vframepsp PARAMS ((int));
-static void dot_save PARAMS ((int));
-static void dot_restore PARAMS ((int));
-static void dot_restorereg PARAMS ((int));
-static void dot_restorereg_p PARAMS ((int));
-static void dot_handlerdata  PARAMS ((int));
-static void dot_unwentry PARAMS ((int));
-static void dot_altrp PARAMS ((int));
-static void dot_savemem PARAMS ((int));
-static void dot_saveg PARAMS ((int));
-static void dot_savef PARAMS ((int));
-static void dot_saveb PARAMS ((int));
-static void dot_savegf PARAMS ((int));
-static void dot_spill PARAMS ((int));
-static void dot_spillreg PARAMS ((int));
-static void dot_spillmem PARAMS ((int));
-static void dot_spillreg_p PARAMS ((int));
-static void dot_spillmem_p PARAMS ((int));
-static void dot_label_state PARAMS ((int));
-static void dot_copy_state PARAMS ((int));
-static void dot_unwabi PARAMS ((int));
-static void dot_personality PARAMS ((int));
-static void dot_body PARAMS ((int));
-static void dot_prologue PARAMS ((int));
-static void dot_endp PARAMS ((int));
-static void dot_template PARAMS ((int));
-static void dot_regstk PARAMS ((int));
-static void dot_rot PARAMS ((int));
-static void dot_byteorder PARAMS ((int));
-static void dot_psr PARAMS ((int));
-static void dot_alias PARAMS ((int));
-static void dot_ln PARAMS ((int));
-static char *parse_section_name PARAMS ((void));
-static void dot_xdata PARAMS ((int));
-static void stmt_float_cons PARAMS ((int));
-static void stmt_cons_ua PARAMS ((int));
-static void dot_xfloat_cons PARAMS ((int));
-static void dot_xstringer PARAMS ((int));
-static void dot_xdata_ua PARAMS ((int));
-static void dot_xfloat_cons_ua PARAMS ((int));
-static void print_prmask PARAMS ((valueT mask));
-static void dot_pred_rel PARAMS ((int));
-static void dot_reg_val PARAMS ((int));
-static void dot_serialize PARAMS ((int));
-static void dot_dv_mode PARAMS ((int));
-static void dot_entry PARAMS ((int));
-static void dot_mem_offset PARAMS ((int));
-static void add_unwind_entry PARAMS((unw_rec_list *ptr));
-static symbolS *declare_register PARAMS ((const char *name, int regnum));
-static void declare_register_set PARAMS ((const char *, int, int));
-static unsigned int operand_width PARAMS ((enum ia64_opnd));
-static enum operand_match_result operand_match PARAMS ((const struct ia64_opcode *idesc,
-                                                       int index,
-                                                       expressionS *e));
-static int parse_operand PARAMS ((expressionS *e));
-static struct ia64_opcode * parse_operands PARAMS ((struct ia64_opcode *));
-static void build_insn PARAMS ((struct slot *, bfd_vma *));
-static void emit_one_bundle PARAMS ((void));
-static void fix_insn PARAMS ((fixS *, const struct ia64_operand *, valueT));
-static bfd_reloc_code_real_type ia64_gen_real_reloc_type PARAMS ((struct symbol *sym,
-                                                                 bfd_reloc_code_real_type r_type));
-static void insn_group_break PARAMS ((int, int, int));
-static void mark_resource PARAMS ((struct ia64_opcode *, const struct ia64_dependency *,
-                                  struct rsrc *, int depind, int path));
-static void add_qp_mutex PARAMS((valueT mask));
-static void add_qp_imply PARAMS((int p1, int p2));
-static void clear_qp_branch_flag PARAMS((valueT mask));
-static void clear_qp_mutex PARAMS((valueT mask));
-static void clear_qp_implies PARAMS((valueT p1_mask, valueT p2_mask));
-static int has_suffix_p PARAMS((const char *, const char *));
-static void clear_register_values PARAMS ((void));
-static void print_dependency PARAMS ((const char *action, int depind));
-static void instruction_serialization PARAMS ((void));
-static void data_serialization PARAMS ((void));
-static void remove_marked_resource PARAMS ((struct rsrc *));
-static int is_conditional_branch PARAMS ((struct ia64_opcode *));
-static int is_taken_branch PARAMS ((struct ia64_opcode *));
-static int is_interruption_or_rfi PARAMS ((struct ia64_opcode *));
-static int depends_on PARAMS ((int, struct ia64_opcode *));
-static int specify_resource PARAMS ((const struct ia64_dependency *,
-                                    struct ia64_opcode *, int, struct rsrc [], int, int));
-static int check_dv PARAMS((struct ia64_opcode *idesc));
-static void check_dependencies PARAMS((struct ia64_opcode *));
-static void mark_resources PARAMS((struct ia64_opcode *));
-static void update_dependencies PARAMS((struct ia64_opcode *));
-static void note_register_values PARAMS((struct ia64_opcode *));
-static int qp_mutex PARAMS ((int, int, int));
-static int resources_match PARAMS ((struct rsrc *, struct ia64_opcode *, int, int, int));
-static void output_vbyte_mem PARAMS ((int, char *, char *));
-static void count_output PARAMS ((int, char *, char *));
-static void output_R1_format PARAMS ((vbyte_func, unw_record_type, int));
-static void output_R2_format PARAMS ((vbyte_func, int, int, unsigned long));
-static void output_R3_format PARAMS ((vbyte_func, unw_record_type, unsigned long));
-static void output_P1_format PARAMS ((vbyte_func, int));
-static void output_P2_format PARAMS ((vbyte_func, int, int));
-static void output_P3_format PARAMS ((vbyte_func, unw_record_type, int));
-static void output_P4_format PARAMS ((vbyte_func, unsigned char *, unsigned long));
-static void output_P5_format PARAMS ((vbyte_func, int, unsigned long));
-static void output_P6_format PARAMS ((vbyte_func, unw_record_type, int));
-static void output_P7_format PARAMS ((vbyte_func, unw_record_type, unsigned long, unsigned long));
-static void output_P8_format PARAMS ((vbyte_func, unw_record_type, unsigned long));
-static void output_P9_format PARAMS ((vbyte_func, int, int));
-static void output_P10_format PARAMS ((vbyte_func, int, int));
-static void output_B1_format PARAMS ((vbyte_func, unw_record_type, unsigned long));
-static void output_B2_format PARAMS ((vbyte_func, unsigned long, unsigned long));
-static void output_B3_format PARAMS ((vbyte_func, unsigned long, unsigned long));
-static void output_B4_format PARAMS ((vbyte_func, unw_record_type, unsigned long));
-static char format_ab_reg PARAMS ((int, int));
-static void output_X1_format PARAMS ((vbyte_func, unw_record_type, int, int, unsigned long,
-                                     unsigned long));
-static void output_X2_format PARAMS ((vbyte_func, int, int, int, int, int, unsigned long));
-static void output_X3_format PARAMS ((vbyte_func, unw_record_type, int, int, int, unsigned long,
-                                     unsigned long));
-static void output_X4_format PARAMS ((vbyte_func, int, int, int, int, int, int, unsigned long));
-static unw_rec_list *output_endp PARAMS ((void));
-static unw_rec_list *output_prologue PARAMS ((void));
-static unw_rec_list *output_prologue_gr PARAMS ((unsigned int, unsigned int));
-static unw_rec_list *output_body PARAMS ((void));
-static unw_rec_list *output_mem_stack_f PARAMS ((unsigned int));
-static unw_rec_list *output_mem_stack_v PARAMS ((void));
-static unw_rec_list *output_psp_gr PARAMS ((unsigned int));
-static unw_rec_list *output_psp_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_rp_when PARAMS ((void));
-static unw_rec_list *output_rp_gr PARAMS ((unsigned int));
-static unw_rec_list *output_rp_br PARAMS ((unsigned int));
-static unw_rec_list *output_rp_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_rp_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_pfs_when PARAMS ((void));
-static unw_rec_list *output_pfs_gr PARAMS ((unsigned int));
-static unw_rec_list *output_pfs_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_pfs_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_preds_when PARAMS ((void));
-static unw_rec_list *output_preds_gr PARAMS ((unsigned int));
-static unw_rec_list *output_preds_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_preds_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_fr_mem PARAMS ((unsigned int));
-static unw_rec_list *output_frgr_mem PARAMS ((unsigned int, unsigned int));
-static unw_rec_list *output_gr_gr PARAMS ((unsigned int, unsigned int));
-static unw_rec_list *output_gr_mem PARAMS ((unsigned int));
-static unw_rec_list *output_br_mem PARAMS ((unsigned int));
-static unw_rec_list *output_br_gr PARAMS ((unsigned int, unsigned int));
-static unw_rec_list *output_spill_base PARAMS ((unsigned int));
-static unw_rec_list *output_unat_when PARAMS ((void));
-static unw_rec_list *output_unat_gr PARAMS ((unsigned int));
-static unw_rec_list *output_unat_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_unat_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_lc_when PARAMS ((void));
-static unw_rec_list *output_lc_gr PARAMS ((unsigned int));
-static unw_rec_list *output_lc_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_lc_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_fpsr_when PARAMS ((void));
-static unw_rec_list *output_fpsr_gr PARAMS ((unsigned int));
-static unw_rec_list *output_fpsr_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_fpsr_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_priunat_when_gr PARAMS ((void));
-static unw_rec_list *output_priunat_when_mem PARAMS ((void));
-static unw_rec_list *output_priunat_gr PARAMS ((unsigned int));
-static unw_rec_list *output_priunat_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_priunat_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_bsp_when PARAMS ((void));
-static unw_rec_list *output_bsp_gr PARAMS ((unsigned int));
-static unw_rec_list *output_bsp_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_bsp_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_bspstore_when PARAMS ((void));
-static unw_rec_list *output_bspstore_gr PARAMS ((unsigned int));
-static unw_rec_list *output_bspstore_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_bspstore_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_rnat_when PARAMS ((void));
-static unw_rec_list *output_rnat_gr PARAMS ((unsigned int));
-static unw_rec_list *output_rnat_psprel PARAMS ((unsigned int));
-static unw_rec_list *output_rnat_sprel PARAMS ((unsigned int));
-static unw_rec_list *output_unwabi PARAMS ((unsigned long, unsigned long));
-static unw_rec_list *output_epilogue PARAMS ((unsigned long));
-static unw_rec_list *output_label_state PARAMS ((unsigned long));
-static unw_rec_list *output_copy_state PARAMS ((unsigned long));
-static unw_rec_list *output_spill_psprel PARAMS ((unsigned int, unsigned int, unsigned int));
-static unw_rec_list *output_spill_sprel PARAMS ((unsigned int, unsigned int, unsigned int));
-static unw_rec_list *output_spill_psprel_p PARAMS ((unsigned int, unsigned int, unsigned int,
-                                                   unsigned int));
-static unw_rec_list *output_spill_sprel_p PARAMS ((unsigned int, unsigned int, unsigned int,
-                                                  unsigned int));
-static unw_rec_list *output_spill_reg PARAMS ((unsigned int, unsigned int, unsigned int,
-                                              unsigned int));
-static unw_rec_list *output_spill_reg_p PARAMS ((unsigned int, unsigned int, unsigned int,
-                                                unsigned int, unsigned int));
-static void process_one_record PARAMS ((unw_rec_list *, vbyte_func));
-static void process_unw_records PARAMS ((unw_rec_list *, vbyte_func));
-static int calc_record_size PARAMS ((unw_rec_list *));
-static void set_imask PARAMS ((unw_rec_list *, unsigned long, unsigned long, unsigned int));
-static unsigned long slot_index PARAMS ((unsigned long, fragS *,
-                                        unsigned long, fragS *,
-                                        int));
-static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
-static void fixup_unw_records PARAMS ((unw_rec_list *, int));
-static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
-static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
-static unsigned int get_saved_prologue_count PARAMS ((unsigned long));
-static void save_prologue_count PARAMS ((unsigned long, unsigned int));
-static void free_saved_prologue_counts PARAMS ((void));
+static void dot_alias (int);
+static int parse_operand_and_eval (expressionS *, int);
+static void emit_one_bundle (void);
+static bfd_reloc_code_real_type ia64_gen_real_reloc_type (struct symbol *,
+                                                         bfd_reloc_code_real_type);
+static void insn_group_break (int, int, int);
+static void add_qp_mutex (valueT);
+static void add_qp_imply (int, int);
+static void clear_qp_mutex (valueT);
+static void clear_qp_implies (valueT, valueT);
+static void print_dependency (const char *, int);
+static void instruction_serialization (void);
+static void data_serialization (void);
+static void output_R3_format (vbyte_func, unw_record_type, unsigned long);
+static void output_B3_format (vbyte_func, unsigned long, unsigned long);
+static void output_B4_format (vbyte_func, unw_record_type, unsigned long);
+static void free_saved_prologue_counts (void);
 
 /* Determine if application register REGNUM resides only in the integer
    unit (as opposed to the memory unit).  */
@@ -934,8 +824,7 @@ ar_is_only_in_memory_unit (int reg)
    don't see any other way to accomplish the same thing without
    changing obj-elf.c (which may be the Right Thing, in the end).  */
 static void
-set_section (name)
-     char *name;
+set_section (char *name)
 {
   char *saved_input_line_pointer;
 
@@ -947,15 +836,19 @@ set_section (name)
 
 /* Map 's' to SHF_IA_64_SHORT.  */
 
-int
-ia64_elf_section_letter (letter, ptr_msg)
-     int letter;
-     char **ptr_msg;
+bfd_vma
+ia64_elf_section_letter (int letter, char **ptr_msg)
 {
   if (letter == 's')
     return SHF_IA_64_SHORT;
   else if (letter == 'o')
     return SHF_LINK_ORDER;
+#ifdef TE_VMS
+  else if (letter == 'O')
+    return SHF_IA_64_VMS_OVERLAID;
+  else if (letter == 'g')
+    return SHF_IA_64_VMS_GLOBAL;
+#endif
 
   *ptr_msg = _("Bad .section directive: want a,o,s,w,x,M,S,G,T in string");
   return -1;
@@ -964,9 +857,9 @@ ia64_elf_section_letter (letter, ptr_msg)
 /* Map SHF_IA_64_SHORT to SEC_SMALL_DATA.  */
 
 flagword
-ia64_elf_section_flags (flags, attr, type)
-     flagword flags;
-     int attr, type ATTRIBUTE_UNUSED;
+ia64_elf_section_flags (flagword flags,
+                       bfd_vma attr,
+                       int type ATTRIBUTE_UNUSED)
 {
   if (attr & SHF_IA_64_SHORT)
     flags |= SEC_SMALL_DATA;
@@ -974,9 +867,7 @@ ia64_elf_section_flags (flags, attr, type)
 }
 
 int
-ia64_elf_section_type (str, len)
-     const char *str;
-     size_t len;
+ia64_elf_section_type (const char *str, size_t len)
 {
 #define STREQ(s) ((len == sizeof (s) - 1) && (strncmp (str, s, sizeof (s) - 1) == 0))
 
@@ -1000,8 +891,10 @@ ia64_elf_section_type (str, len)
 }
 
 static unsigned int
-set_regstack (ins, locs, outs, rots)
-     unsigned int ins, locs, outs, rots;
+set_regstack (unsigned int ins,
+             unsigned int locs,
+             unsigned int outs,
+             unsigned int rots)
 {
   /* Size of frame.  */
   unsigned int sof;
@@ -1009,12 +902,12 @@ set_regstack (ins, locs, outs, rots)
   sof = ins + locs + outs;
   if (sof > 96)
     {
-      as_bad ("Size of frame exceeds maximum of 96 registers");
+      as_bad (_("Size of frame exceeds maximum of 96 registers"));
       return 0;
     }
   if (rots > sof)
     {
-      as_warn ("Size of rotating registers exceeds frame size");
+      as_warn (_("Size of rotating registers exceeds frame size"));
       return 0;
     }
   md.in.base = REG_GR + 32;
@@ -1029,12 +922,13 @@ set_regstack (ins, locs, outs, rots)
 }
 
 void
-ia64_flush_insns ()
+ia64_flush_insns (void)
 {
   struct label_fix *lfix;
   segT saved_seg;
   subsegT saved_subseg;
   unw_rec_list *ptr;
+  bfd_boolean mark;
 
   if (!md.last_text_seg)
     return;
@@ -1048,18 +942,24 @@ ia64_flush_insns ()
     emit_one_bundle ();                /* force out queued instructions */
 
   /* In case there are labels following the last instruction, resolve
-     those now:  */
+     those now.  */
+  mark = FALSE;
   for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      symbol_set_value_now (lfix->sym);
+      mark |= lfix->dw2_mark_labels;
     }
-  CURR_SLOT.label_fixups = 0;
-  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+  if (mark)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      dwarf2_where (&CURR_SLOT.debug_line);
+      CURR_SLOT.debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+      dwarf2_gen_line_info (frag_now_fix (), &CURR_SLOT.debug_line);
+      dwarf2_consume_line_info ();
     }
+  CURR_SLOT.label_fixups = 0;
+
+  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+    symbol_set_value_now (lfix->sym);
   CURR_SLOT.tag_fixups = 0;
 
   /* In case there are unwind directives following the last instruction,
@@ -1103,7 +1003,7 @@ ia64_flush_insns ()
   subseg_set (saved_seg, saved_subseg);
 
   if (md.qp.X_op == O_register)
-    as_bad ("qualifying predicate not followed by instruction");
+    as_bad (_("qualifying predicate not followed by instruction"));
 }
 
 static void
@@ -1117,8 +1017,7 @@ ia64_do_align (int nbytes)
 }
 
 void
-ia64_cons_align (nbytes)
-     int nbytes;
+ia64_cons_align (int nbytes)
 {
   if (md.auto_align)
     {
@@ -1130,13 +1029,10 @@ ia64_cons_align (nbytes)
 }
 
 /* Output COUNT bytes to a memory location.  */
-static unsigned char *vbyte_mem_ptr = NULL;
+static char *vbyte_mem_ptr = NULL;
 
-void
-output_vbyte_mem (count, ptr, comment)
-     int count;
-     char *ptr;
-     char *comment ATTRIBUTE_UNUSED;
+static void
+output_vbyte_mem (int count, char *ptr, char *comment ATTRIBUTE_UNUSED)
 {
   int x;
   if (vbyte_mem_ptr == NULL)
@@ -1150,20 +1046,16 @@ output_vbyte_mem (count, ptr, comment)
 
 /* Count the number of bytes required for records.  */
 static int vbyte_count = 0;
-void
-count_output (count, ptr, comment)
-     int count;
-     char *ptr ATTRIBUTE_UNUSED;
-     char *comment ATTRIBUTE_UNUSED;
+static void
+count_output (int count,
+             char *ptr ATTRIBUTE_UNUSED,
+             char *comment ATTRIBUTE_UNUSED)
 {
   vbyte_count += count;
 }
 
 static void
-output_R1_format (f, rtype, rlen)
-     vbyte_func f;
-     unw_record_type rtype;
-     int rlen;
+output_R1_format (vbyte_func f, unw_record_type rtype, int rlen)
 {
   int r = 0;
   char byte;
@@ -1176,17 +1068,14 @@ output_R1_format (f, rtype, rlen)
   if (rtype == body)
     r = 1;
   else if (rtype != prologue)
-    as_bad ("record type is not valid");
+    as_bad (_("record type is not valid"));
 
   byte = UNW_R1 | (r << 5) | (rlen & 0x1f);
   (*f) (1, &byte, NULL);
 }
 
 static void
-output_R2_format (f, mask, grsave, rlen)
-     vbyte_func f;
-     int mask, grsave;
-     unsigned long rlen;
+output_R2_format (vbyte_func f, int mask, int grsave, unsigned long rlen)
 {
   char bytes[20];
   int count = 2;
@@ -1200,10 +1089,7 @@ output_R2_format (f, mask, grsave, rlen)
 }
 
 static void
-output_R3_format (f, rtype, rlen)
-     vbyte_func f;
-     unw_record_type rtype;
-     unsigned long rlen;
+output_R3_format (vbyte_func f, unw_record_type rtype, unsigned long rlen)
 {
   int r = 0, count;
   char bytes[20];
@@ -1216,16 +1102,14 @@ output_R3_format (f, rtype, rlen)
   if (rtype == body)
     r = 1;
   else if (rtype != prologue)
-    as_bad ("record type is not valid");
+    as_bad (_("record type is not valid"));
   bytes[0] = (UNW_R3 | r);
   count = output_leb128 (bytes + 1, rlen, 0);
   (*f) (count + 1, bytes, NULL);
 }
 
 static void
-output_P1_format (f, brmask)
-     vbyte_func f;
-     int brmask;
+output_P1_format (vbyte_func f, int brmask)
 {
   char byte;
   byte = UNW_P1 | (brmask & 0x1f);
@@ -1233,10 +1117,7 @@ output_P1_format (f, brmask)
 }
 
 static void
-output_P2_format (f, brmask, gr)
-     vbyte_func f;
-     int brmask;
-     int gr;
+output_P2_format (vbyte_func f, int brmask, int gr)
 {
   char bytes[2];
   brmask = (brmask & 0x1f);
@@ -1246,10 +1127,7 @@ output_P2_format (f, brmask, gr)
 }
 
 static void
-output_P3_format (f, rtype, reg)
-     vbyte_func f;
-     unw_record_type rtype;
-     int reg;
+output_P3_format (vbyte_func f, unw_record_type rtype, int reg)
 {
   char bytes[2];
   int r = 0;
@@ -1293,7 +1171,7 @@ output_P3_format (f, rtype, reg)
       r = 11;
       break;
     default:
-      as_bad ("Invalid record type for P3 format.");
+      as_bad (_("Invalid record type for P3 format."));
     }
   bytes[0] = (UNW_P3 | (r >> 1));
   bytes[1] = (((r & 1) << 7) | reg);
@@ -1301,20 +1179,14 @@ output_P3_format (f, rtype, reg)
 }
 
 static void
-output_P4_format (f, imask, imask_size)
-     vbyte_func f;
-     unsigned char *imask;
-     unsigned long imask_size;
+output_P4_format (vbyte_func f, unsigned char *imask, unsigned long imask_size)
 {
   imask[0] = UNW_P4;
-  (*f) (imask_size, imask, NULL);
+  (*f) (imask_size, (char *) imask, NULL);
 }
 
 static void
-output_P5_format (f, grmask, frmask)
-     vbyte_func f;
-     int grmask;
-     unsigned long frmask;
+output_P5_format (vbyte_func f, int grmask, unsigned long frmask)
 {
   char bytes[4];
   grmask = (grmask & 0x0f);
@@ -1327,10 +1199,7 @@ output_P5_format (f, grmask, frmask)
 }
 
 static void
-output_P6_format (f, rtype, rmask)
-     vbyte_func f;
-     unw_record_type rtype;
-     int rmask;
+output_P6_format (vbyte_func f, unw_record_type rtype, int rmask)
 {
   char byte;
   int r = 0;
@@ -1338,17 +1207,16 @@ output_P6_format (f, rtype, rmask)
   if (rtype == gr_mem)
     r = 1;
   else if (rtype != fr_mem)
-    as_bad ("Invalid record type for format P6");
+    as_bad (_("Invalid record type for format P6"));
   byte = (UNW_P6 | (r << 4) | (rmask & 0x0f));
   (*f) (1, &byte, NULL);
 }
 
 static void
-output_P7_format (f, rtype, w1, w2)
-     vbyte_func f;
-     unw_record_type rtype;
-     unsigned long w1;
-     unsigned long w2;
+output_P7_format (vbyte_func f,
+                 unw_record_type rtype,
+                 unsigned long w1,
+                 unsigned long w2)
 {
   char bytes[20];
   int count = 1;
@@ -1413,10 +1281,7 @@ output_P7_format (f, rtype, w1, w2)
 }
 
 static void
-output_P8_format (f, rtype, t)
-     vbyte_func f;
-     unw_record_type rtype;
-     unsigned long t;
+output_P8_format (vbyte_func f, unw_record_type rtype, unsigned long t)
 {
   char bytes[20];
   int r = 0;
@@ -1490,10 +1355,7 @@ output_P8_format (f, rtype, t)
 }
 
 static void
-output_P9_format (f, grmask, gr)
-     vbyte_func f;
-     int grmask;
-     int gr;
+output_P9_format (vbyte_func f, int grmask, int gr)
 {
   char bytes[3];
   bytes[0] = UNW_P9;
@@ -1503,10 +1365,7 @@ output_P9_format (f, grmask, gr)
 }
 
 static void
-output_P10_format (f, abi, context)
-     vbyte_func f;
-     int abi;
-     int context;
+output_P10_format (vbyte_func f, int abi, int context)
 {
   char bytes[3];
   bytes[0] = UNW_P10;
@@ -1516,10 +1375,7 @@ output_P10_format (f, abi, context)
 }
 
 static void
-output_B1_format (f, rtype, label)
-     vbyte_func f;
-     unw_record_type rtype;
-     unsigned long label;
+output_B1_format (vbyte_func f, unw_record_type rtype, unsigned long label)
 {
   char byte;
   int r = 0;
@@ -1531,17 +1387,14 @@ output_B1_format (f, rtype, label)
   if (rtype == copy_state)
     r = 1;
   else if (rtype != label_state)
-    as_bad ("Invalid record type for format B1");
+    as_bad (_("Invalid record type for format B1"));
 
   byte = (UNW_B1 | (r << 5) | (label & 0x1f));
   (*f) (1, &byte, NULL);
 }
 
 static void
-output_B2_format (f, ecount, t)
-     vbyte_func f;
-     unsigned long ecount;
-     unsigned long t;
+output_B2_format (vbyte_func f, unsigned long ecount, unsigned long t)
 {
   char bytes[20];
   int count = 1;
@@ -1556,10 +1409,7 @@ output_B2_format (f, ecount, t)
 }
 
 static void
-output_B3_format (f, ecount, t)
-     vbyte_func f;
-     unsigned long ecount;
-     unsigned long t;
+output_B3_format (vbyte_func f, unsigned long ecount, unsigned long t)
 {
   char bytes[20];
   int count = 1;
@@ -1575,10 +1425,7 @@ output_B3_format (f, ecount, t)
 }
 
 static void
-output_B4_format (f, rtype, label)
-     vbyte_func f;
-     unw_record_type rtype;
-     unsigned long label;
+output_B4_format (vbyte_func f, unw_record_type rtype, unsigned long label)
 {
   char bytes[20];
   int r = 0;
@@ -1592,7 +1439,7 @@ output_B4_format (f, rtype, label)
   if (rtype == copy_state)
     r = 1;
   else if (rtype != label_state)
-    as_bad ("Invalid record type for format B1");
+    as_bad (_("Invalid record type for format B1"));
 
   bytes[0] = (UNW_B4 | (r << 3));
   count += output_leb128 (bytes + 1, label, 0);
@@ -1600,9 +1447,7 @@ output_B4_format (f, rtype, label)
 }
 
 static char
-format_ab_reg (ab, reg)
-     int ab;
-     int reg;
+format_ab_reg (int ab, int reg)
 {
   int ret;
   ab = (ab & 3);
@@ -1612,12 +1457,12 @@ format_ab_reg (ab, reg)
 }
 
 static void
-output_X1_format (f, rtype, ab, reg, t, w1)
-     vbyte_func f;
-     unw_record_type rtype;
-     int ab, reg;
-     unsigned long t;
-     unsigned long w1;
+output_X1_format (vbyte_func f,
+                 unw_record_type rtype,
+                 int ab,
+                 int reg,
+                 unsigned long t,
+                 unsigned long w1)
 {
   char bytes[20];
   int r = 0;
@@ -1627,7 +1472,7 @@ output_X1_format (f, rtype, ab, reg, t, w1)
   if (rtype == spill_sprel)
     r = 1;
   else if (rtype != spill_psprel)
-    as_bad ("Invalid record type for format X1");
+    as_bad (_("Invalid record type for format X1"));
   bytes[1] = ((r << 7) | format_ab_reg (ab, reg));
   count += output_leb128 (bytes + 2, t, 0);
   count += output_leb128 (bytes + count, w1, 0);
@@ -1635,11 +1480,13 @@ output_X1_format (f, rtype, ab, reg, t, w1)
 }
 
 static void
-output_X2_format (f, ab, reg, x, y, treg, t)
-     vbyte_func f;
-     int ab, reg;
-     int x, y, treg;
-     unsigned long t;
+output_X2_format (vbyte_func f,
+                 int ab,
+                 int reg,
+                 int x,
+                 int y,
+                 int treg,
+                 unsigned long t)
 {
   char bytes[20];
   int count = 3;
@@ -1651,13 +1498,13 @@ output_X2_format (f, ab, reg, x, y, treg, t)
 }
 
 static void
-output_X3_format (f, rtype, qp, ab, reg, t, w1)
-     vbyte_func f;
-     unw_record_type rtype;
-     int qp;
-     int ab, reg;
-     unsigned long t;
-     unsigned long w1;
+output_X3_format (vbyte_func f,
+                 unw_record_type rtype,
+                 int qp,
+                 int ab,
+                 int reg,
+                 unsigned long t,
+                 unsigned long w1)
 {
   char bytes[20];
   int r = 0;
@@ -1667,7 +1514,7 @@ output_X3_format (f, rtype, qp, ab, reg, t, w1)
   if (rtype == spill_sprel_p)
     r = 1;
   else if (rtype != spill_psprel_p)
-    as_bad ("Invalid record type for format X3");
+    as_bad (_("Invalid record type for format X3"));
   bytes[1] = ((r << 7) | (qp & 0x3f));
   bytes[2] = format_ab_reg (ab, reg);
   count += output_leb128 (bytes + 3, t, 0);
@@ -1676,12 +1523,14 @@ output_X3_format (f, rtype, qp, ab, reg, t, w1)
 }
 
 static void
-output_X4_format (f, qp, ab, reg, x, y, treg, t)
-     vbyte_func f;
-     int qp;
-     int ab, reg;
-     int x, y, treg;
-     unsigned long t;
+output_X4_format (vbyte_func f,
+                 int qp,
+                 int ab,
+                 int reg,
+                 int x,
+                 int y,
+                 int treg,
+                 unsigned long t)
 {
   char bytes[20];
   int count = 4;
@@ -1693,6 +1542,55 @@ output_X4_format (f, qp, ab, reg, x, y, treg, t)
   (*f) (count, bytes, NULL);
 }
 
+/* This function checks whether there are any outstanding .save-s and
+   discards them if so.  */
+
+static void
+check_pending_save (void)
+{
+  if (unwind.pending_saves)
+    {
+      unw_rec_list *cur, *prev;
+
+      as_warn (_("Previous .save incomplete"));
+      for (cur = unwind.list, prev = NULL; cur; )
+       if (&cur->r.record.p == unwind.pending_saves)
+         {
+           if (prev)
+             prev->next = cur->next;
+           else
+             unwind.list = cur->next;
+           if (cur == unwind.tail)
+             unwind.tail = prev;
+           if (cur == unwind.current_entry)
+             unwind.current_entry = cur->next;
+           /* Don't free the first discarded record, it's being used as
+              terminator for (currently) br_gr and gr_gr processing, and
+              also prevents leaving a dangling pointer to it in its
+              predecessor.  */
+           cur->r.record.p.grmask = 0;
+           cur->r.record.p.brmask = 0;
+           cur->r.record.p.frmask = 0;
+           prev = cur->r.record.p.next;
+           cur->r.record.p.next = NULL;
+           cur = prev;
+           break;
+         }
+       else
+         {
+           prev = cur;
+           cur = cur->next;
+         }
+      while (cur)
+       {
+         prev = cur;
+         cur = cur->r.record.p.next;
+         free (prev);
+       }
+      unwind.pending_saves = NULL;
+    }
+}
+
 /* This function allocates a record list structure, and initializes fields.  */
 
 static unw_rec_list *
@@ -1700,11 +1598,9 @@ alloc_record (unw_record_type t)
 {
   unw_rec_list *ptr;
   ptr = xmalloc (sizeof (*ptr));
-  ptr->next = NULL;
+  memset (ptr, 0, sizeof (*ptr));
   ptr->slot_number = SLOT_NUM_NOT_SET;
   ptr->r.type = t;
-  ptr->next_slot_number = 0;
-  ptr->next_slot_frag = 0;
   return ptr;
 }
 
@@ -1712,14 +1608,14 @@ alloc_record (unw_record_type t)
    body region.  */
 
 static unw_rec_list *
-output_endp ()
+output_endp (void)
 {
   unw_rec_list *ptr = alloc_record (endp);
   return ptr;
 }
 
 static unw_rec_list *
-output_prologue ()
+output_prologue (void)
 {
   unw_rec_list *ptr = alloc_record (prologue);
   memset (&ptr->r.record.r.mask, 0, sizeof (ptr->r.record.r.mask));
@@ -1727,9 +1623,7 @@ output_prologue ()
 }
 
 static unw_rec_list *
-output_prologue_gr (saved_mask, reg)
-     unsigned int saved_mask;
-     unsigned int reg;
+output_prologue_gr (unsigned int saved_mask, unsigned int reg)
 {
   unw_rec_list *ptr = alloc_record (prologue_gr);
   memset (&ptr->r.record.r.mask, 0, sizeof (ptr->r.record.r.mask));
@@ -1739,15 +1633,14 @@ output_prologue_gr (saved_mask, reg)
 }
 
 static unw_rec_list *
-output_body ()
+output_body (void)
 {
   unw_rec_list *ptr = alloc_record (body);
   return ptr;
 }
 
 static unw_rec_list *
-output_mem_stack_f (size)
-     unsigned int size;
+output_mem_stack_f (unsigned int size)
 {
   unw_rec_list *ptr = alloc_record (mem_stack_f);
   ptr->r.record.p.size = size;
@@ -1755,458 +1648,528 @@ output_mem_stack_f (size)
 }
 
 static unw_rec_list *
-output_mem_stack_v ()
+output_mem_stack_v (void)
 {
   unw_rec_list *ptr = alloc_record (mem_stack_v);
   return ptr;
 }
 
 static unw_rec_list *
-output_psp_gr (gr)
-     unsigned int gr;
+output_psp_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (psp_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_psp_sprel (offset)
-     unsigned int offset;
+output_psp_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (psp_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_rp_when ()
+output_rp_when (void)
 {
   unw_rec_list *ptr = alloc_record (rp_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_rp_gr (gr)
-     unsigned int gr;
+output_rp_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (rp_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_rp_br (br)
-     unsigned int br;
+output_rp_br (unsigned int br)
 {
   unw_rec_list *ptr = alloc_record (rp_br);
-  ptr->r.record.p.br = br;
+  ptr->r.record.p.r.br = br;
   return ptr;
 }
 
 static unw_rec_list *
-output_rp_psprel (offset)
-     unsigned int offset;
+output_rp_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (rp_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_rp_sprel (offset)
-     unsigned int offset;
+output_rp_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (rp_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_pfs_when ()
+output_pfs_when (void)
 {
   unw_rec_list *ptr = alloc_record (pfs_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_pfs_gr (gr)
-     unsigned int gr;
+output_pfs_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (pfs_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_pfs_psprel (offset)
-     unsigned int offset;
+output_pfs_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (pfs_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_pfs_sprel (offset)
-     unsigned int offset;
+output_pfs_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (pfs_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_preds_when ()
+output_preds_when (void)
 {
   unw_rec_list *ptr = alloc_record (preds_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_preds_gr (gr)
-     unsigned int gr;
+output_preds_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (preds_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_preds_psprel (offset)
-     unsigned int offset;
+output_preds_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (preds_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_preds_sprel (offset)
-     unsigned int offset;
+output_preds_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (preds_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_fr_mem (mask)
-     unsigned int mask;
+output_fr_mem (unsigned int mask)
 {
   unw_rec_list *ptr = alloc_record (fr_mem);
-  ptr->r.record.p.rmask = mask;
-  return ptr;
+  unw_rec_list *cur = ptr;
+
+  ptr->r.record.p.frmask = mask;
+  unwind.pending_saves = &ptr->r.record.p;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+       return ptr;
+      cur = alloc_record (fr_mem);
+      cur->r.record.p.frmask = mask;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.frmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
-output_frgr_mem (gr_mask, fr_mask)
-     unsigned int gr_mask;
-     unsigned int fr_mask;
+output_frgr_mem (unsigned int gr_mask, unsigned int fr_mask)
 {
   unw_rec_list *ptr = alloc_record (frgr_mem);
-  ptr->r.record.p.grmask = gr_mask;
-  ptr->r.record.p.frmask = fr_mask;
-  return ptr;
+  unw_rec_list *cur = ptr;
+
+  unwind.pending_saves = &cur->r.record.p;
+  cur->r.record.p.frmask = fr_mask;
+  while (fr_mask)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      fr_mask &= ~(fr_mask & (~fr_mask + 1));
+      if (!gr_mask && !fr_mask)
+       return ptr;
+      cur = alloc_record (frgr_mem);
+      cur->r.record.p.frmask = fr_mask;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.frmask ^= fr_mask;
+      prev->r.record.p.next = cur;
+    }
+  cur->r.record.p.grmask = gr_mask;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      gr_mask &= ~(gr_mask & (~gr_mask + 1));
+      if (!gr_mask)
+       return ptr;
+      cur = alloc_record (frgr_mem);
+      cur->r.record.p.grmask = gr_mask;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.grmask ^= gr_mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
-output_gr_gr (mask, reg)
-     unsigned int mask;
-     unsigned int reg;
+output_gr_gr (unsigned int mask, unsigned int reg)
 {
   unw_rec_list *ptr = alloc_record (gr_gr);
+  unw_rec_list *cur = ptr;
+
   ptr->r.record.p.grmask = mask;
-  ptr->r.record.p.gr = reg;
-  return ptr;
+  ptr->r.record.p.r.gr = reg;
+  unwind.pending_saves = &ptr->r.record.p;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+       return ptr;
+      cur = alloc_record (gr_gr);
+      cur->r.record.p.grmask = mask;
+      /* Indicate this record shouldn't be output.  */
+      cur->r.record.p.r.gr = REG_NUM;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.grmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
-output_gr_mem (mask)
-     unsigned int mask;
+output_gr_mem (unsigned int mask)
 {
   unw_rec_list *ptr = alloc_record (gr_mem);
-  ptr->r.record.p.rmask = mask;
-  return ptr;
+  unw_rec_list *cur = ptr;
+
+  ptr->r.record.p.grmask = mask;
+  unwind.pending_saves = &ptr->r.record.p;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+       return ptr;
+      cur = alloc_record (gr_mem);
+      cur->r.record.p.grmask = mask;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.grmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
 output_br_mem (unsigned int mask)
 {
   unw_rec_list *ptr = alloc_record (br_mem);
+  unw_rec_list *cur = ptr;
+
   ptr->r.record.p.brmask = mask;
-  return ptr;
+  unwind.pending_saves = &ptr->r.record.p;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+       return ptr;
+      cur = alloc_record (br_mem);
+      cur->r.record.p.brmask = mask;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.brmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
-output_br_gr (save_mask, reg)
-     unsigned int save_mask;
-     unsigned int reg;
+output_br_gr (unsigned int mask, unsigned int reg)
 {
   unw_rec_list *ptr = alloc_record (br_gr);
-  ptr->r.record.p.brmask = save_mask;
-  ptr->r.record.p.gr = reg;
-  return ptr;
+  unw_rec_list *cur = ptr;
+
+  ptr->r.record.p.brmask = mask;
+  ptr->r.record.p.r.gr = reg;
+  unwind.pending_saves = &ptr->r.record.p;
+  for (;;)
+    {
+      unw_rec_list *prev = cur;
+
+      /* Clear least significant set bit.  */
+      mask &= ~(mask & (~mask + 1));
+      if (!mask)
+       return ptr;
+      cur = alloc_record (br_gr);
+      cur->r.record.p.brmask = mask;
+      /* Indicate this record shouldn't be output.  */
+      cur->r.record.p.r.gr = REG_NUM;
+      /* Retain only least significant bit.  */
+      prev->r.record.p.brmask ^= mask;
+      prev->r.record.p.next = cur;
+    }
 }
 
 static unw_rec_list *
-output_spill_base (offset)
-     unsigned int offset;
+output_spill_base (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (spill_base);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_unat_when ()
+output_unat_when (void)
 {
   unw_rec_list *ptr = alloc_record (unat_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_unat_gr (gr)
-     unsigned int gr;
+output_unat_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (unat_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_unat_psprel (offset)
-     unsigned int offset;
+output_unat_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (unat_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_unat_sprel (offset)
-     unsigned int offset;
+output_unat_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (unat_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_lc_when ()
+output_lc_when (void)
 {
   unw_rec_list *ptr = alloc_record (lc_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_lc_gr (gr)
-     unsigned int gr;
+output_lc_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (lc_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_lc_psprel (offset)
-     unsigned int offset;
+output_lc_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (lc_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_lc_sprel (offset)
-     unsigned int offset;
+output_lc_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (lc_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_fpsr_when ()
+output_fpsr_when (void)
 {
   unw_rec_list *ptr = alloc_record (fpsr_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_fpsr_gr (gr)
-     unsigned int gr;
+output_fpsr_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (fpsr_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_fpsr_psprel (offset)
-     unsigned int offset;
+output_fpsr_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (fpsr_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_fpsr_sprel (offset)
-     unsigned int offset;
+output_fpsr_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (fpsr_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_priunat_when_gr ()
+output_priunat_when_gr (void)
 {
   unw_rec_list *ptr = alloc_record (priunat_when_gr);
   return ptr;
 }
 
 static unw_rec_list *
-output_priunat_when_mem ()
+output_priunat_when_mem (void)
 {
   unw_rec_list *ptr = alloc_record (priunat_when_mem);
   return ptr;
 }
 
 static unw_rec_list *
-output_priunat_gr (gr)
-     unsigned int gr;
+output_priunat_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (priunat_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_priunat_psprel (offset)
-     unsigned int offset;
+output_priunat_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (priunat_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_priunat_sprel (offset)
-     unsigned int offset;
+output_priunat_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (priunat_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_bsp_when ()
+output_bsp_when (void)
 {
   unw_rec_list *ptr = alloc_record (bsp_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_bsp_gr (gr)
-     unsigned int gr;
+output_bsp_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (bsp_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_bsp_psprel (offset)
-     unsigned int offset;
+output_bsp_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (bsp_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_bsp_sprel (offset)
-     unsigned int offset;
+output_bsp_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (bsp_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_bspstore_when ()
+output_bspstore_when (void)
 {
   unw_rec_list *ptr = alloc_record (bspstore_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_bspstore_gr (gr)
-     unsigned int gr;
+output_bspstore_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (bspstore_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_bspstore_psprel (offset)
-     unsigned int offset;
+output_bspstore_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (bspstore_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_bspstore_sprel (offset)
-     unsigned int offset;
+output_bspstore_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (bspstore_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_rnat_when ()
+output_rnat_when (void)
 {
   unw_rec_list *ptr = alloc_record (rnat_when);
   return ptr;
 }
 
 static unw_rec_list *
-output_rnat_gr (gr)
-     unsigned int gr;
+output_rnat_gr (unsigned int gr)
 {
   unw_rec_list *ptr = alloc_record (rnat_gr);
-  ptr->r.record.p.gr = gr;
+  ptr->r.record.p.r.gr = gr;
   return ptr;
 }
 
 static unw_rec_list *
-output_rnat_psprel (offset)
-     unsigned int offset;
+output_rnat_psprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (rnat_psprel);
-  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset);
   return ptr;
 }
 
 static unw_rec_list *
-output_rnat_sprel (offset)
-     unsigned int offset;
+output_rnat_sprel (unsigned int offset)
 {
   unw_rec_list *ptr = alloc_record (rnat_sprel);
-  ptr->r.record.p.spoff = offset / 4;
+  ptr->r.record.p.off.sp = offset / 4;
   return ptr;
 }
 
 static unw_rec_list *
-output_unwabi (abi, context)
-     unsigned long abi;
-     unsigned long context;
+output_unwabi (unsigned long abi, unsigned long context)
 {
   unw_rec_list *ptr = alloc_record (unwabi);
   ptr->r.record.p.abi = abi;
@@ -2239,88 +2202,44 @@ output_copy_state (unsigned long label)
 }
 
 static unw_rec_list *
-output_spill_psprel (ab, reg, offset)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int offset;
-{
-  unw_rec_list *ptr = alloc_record (spill_psprel);
-  ptr->r.record.x.ab = ab;
-  ptr->r.record.x.reg = reg;
-  ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset);
-  return ptr;
-}
-
-static unw_rec_list *
-output_spill_sprel (ab, reg, offset)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int offset;
-{
-  unw_rec_list *ptr = alloc_record (spill_sprel);
-  ptr->r.record.x.ab = ab;
-  ptr->r.record.x.reg = reg;
-  ptr->r.record.x.spoff = offset / 4;
-  return ptr;
-}
-
-static unw_rec_list *
-output_spill_psprel_p (ab, reg, offset, predicate)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int offset;
-     unsigned int predicate;
+output_spill_psprel (unsigned int ab,
+                    unsigned int reg,
+                    unsigned int offset,
+                    unsigned int predicate)
 {
-  unw_rec_list *ptr = alloc_record (spill_psprel_p);
+  unw_rec_list *ptr = alloc_record (predicate ? spill_psprel_p : spill_psprel);
   ptr->r.record.x.ab = ab;
   ptr->r.record.x.reg = reg;
-  ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset);
+  ptr->r.record.x.where.pspoff = ENCODED_PSP_OFFSET (offset);
   ptr->r.record.x.qp = predicate;
   return ptr;
 }
 
 static unw_rec_list *
-output_spill_sprel_p (ab, reg, offset, predicate)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int offset;
-     unsigned int predicate;
+output_spill_sprel (unsigned int ab,
+                   unsigned int reg,
+                   unsigned int offset,
+                   unsigned int predicate)
 {
-  unw_rec_list *ptr = alloc_record (spill_sprel_p);
+  unw_rec_list *ptr = alloc_record (predicate ? spill_sprel_p : spill_sprel);
   ptr->r.record.x.ab = ab;
   ptr->r.record.x.reg = reg;
-  ptr->r.record.x.spoff = offset / 4;
+  ptr->r.record.x.where.spoff = offset / 4;
   ptr->r.record.x.qp = predicate;
   return ptr;
 }
 
 static unw_rec_list *
-output_spill_reg (ab, reg, targ_reg, xy)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int targ_reg;
-     unsigned int xy;
+output_spill_reg (unsigned int ab,
+                 unsigned int reg,
+                 unsigned int targ_reg,
+                 unsigned int xy,
+                 unsigned int predicate)
 {
-  unw_rec_list *ptr = alloc_record (spill_reg);
-  ptr->r.record.x.ab = ab;
-  ptr->r.record.x.reg = reg;
-  ptr->r.record.x.treg = targ_reg;
-  ptr->r.record.x.xy = xy;
-  return ptr;
-}
-
-static unw_rec_list *
-output_spill_reg_p (ab, reg, targ_reg, xy, predicate)
-     unsigned int ab;
-     unsigned int reg;
-     unsigned int targ_reg;
-     unsigned int xy;
-     unsigned int predicate;
-{
-  unw_rec_list *ptr = alloc_record (spill_reg_p);
+  unw_rec_list *ptr = alloc_record (predicate ? spill_reg_p : spill_reg);
   ptr->r.record.x.ab = ab;
   ptr->r.record.x.reg = reg;
-  ptr->r.record.x.treg = targ_reg;
+  ptr->r.record.x.where.reg = targ_reg;
   ptr->r.record.x.xy = xy;
   ptr->r.record.x.qp = predicate;
   return ptr;
@@ -2330,11 +2249,9 @@ output_spill_reg_p (ab, reg, targ_reg, xy, predicate)
    specified function.  */
 
 static void
-process_one_record (ptr, f)
-     unw_rec_list *ptr;
-     vbyte_func f;
+process_one_record (unw_rec_list *ptr, vbyte_func f)
 {
-  unsigned long fr_mask, gr_mask;
+  unsigned int fr_mask, gr_mask;
 
   switch (ptr->r.type)
     {
@@ -2400,13 +2317,13 @@ process_one_record (ptr, f)
     case bsp_gr:
     case bspstore_gr:
     case rnat_gr:
-      output_P3_format (f, ptr->r.type, ptr->r.record.p.gr);
+      output_P3_format (f, ptr->r.type, ptr->r.record.p.r.gr);
       break;
     case rp_br:
-      output_P3_format (f, rp_br, ptr->r.record.p.br);
+      output_P3_format (f, rp_br, ptr->r.record.p.r.br);
       break;
     case psp_sprel:
-      output_P7_format (f, psp_sprel, ptr->r.record.p.spoff, 0);
+      output_P7_format (f, psp_sprel, ptr->r.record.p.off.sp, 0);
       break;
     case rp_when:
     case pfs_when:
@@ -2423,7 +2340,7 @@ process_one_record (ptr, f)
     case lc_psprel:
     case fpsr_psprel:
     case spill_base:
-      output_P7_format (f, ptr->r.type, ptr->r.record.p.pspoff, 0);
+      output_P7_format (f, ptr->r.type, ptr->r.record.p.off.psp, 0);
       break;
     case rp_sprel:
     case pfs_sprel:
@@ -2435,16 +2352,32 @@ process_one_record (ptr, f)
     case bsp_sprel:
     case bspstore_sprel:
     case rnat_sprel:
-      output_P8_format (f, ptr->r.type, ptr->r.record.p.spoff);
+      output_P8_format (f, ptr->r.type, ptr->r.record.p.off.sp);
       break;
     case gr_gr:
-      output_P9_format (f, ptr->r.record.p.grmask, ptr->r.record.p.gr);
+      if (ptr->r.record.p.r.gr < REG_NUM)
+       {
+         const unw_rec_list *cur = ptr;
+
+         gr_mask = cur->r.record.p.grmask;
+         while ((cur = cur->r.record.p.next) != NULL)
+           gr_mask |= cur->r.record.p.grmask;
+         output_P9_format (f, gr_mask, ptr->r.record.p.r.gr);
+       }
       break;
     case br_gr:
-      output_P2_format (f, ptr->r.record.p.brmask, ptr->r.record.p.gr);
+      if (ptr->r.record.p.r.gr < REG_NUM)
+       {
+         const unw_rec_list *cur = ptr;
+
+         gr_mask = cur->r.record.p.brmask;
+         while ((cur = cur->r.record.p.next) != NULL)
+           gr_mask |= cur->r.record.p.brmask;
+         output_P2_format (f, gr_mask, ptr->r.record.p.r.gr);
+       }
       break;
     case spill_mask:
-      as_bad ("spill_mask record unimplemented.");
+      as_bad (_("spill_mask record unimplemented."));
       break;
     case priunat_when_gr:
     case priunat_when_mem:
@@ -2457,7 +2390,7 @@ process_one_record (ptr, f)
     case bsp_psprel:
     case bspstore_psprel:
     case rnat_psprel:
-      output_P8_format (f, ptr->r.type, ptr->r.record.p.pspoff);
+      output_P8_format (f, ptr->r.type, ptr->r.record.p.off.psp);
       break;
     case unwabi:
       output_P10_format (f, ptr->r.record.p.abi, ptr->r.record.p.context);
@@ -2472,36 +2405,36 @@ process_one_record (ptr, f)
     case spill_psprel:
       output_X1_format (f, ptr->r.type, ptr->r.record.x.ab,
                        ptr->r.record.x.reg, ptr->r.record.x.t,
-                       ptr->r.record.x.pspoff);
+                       ptr->r.record.x.where.pspoff);
       break;
     case spill_sprel:
       output_X1_format (f, ptr->r.type, ptr->r.record.x.ab,
                        ptr->r.record.x.reg, ptr->r.record.x.t,
-                       ptr->r.record.x.spoff);
+                       ptr->r.record.x.where.spoff);
       break;
     case spill_reg:
       output_X2_format (f, ptr->r.record.x.ab, ptr->r.record.x.reg,
                        ptr->r.record.x.xy >> 1, ptr->r.record.x.xy,
-                       ptr->r.record.x.treg, ptr->r.record.x.t);
+                       ptr->r.record.x.where.reg, ptr->r.record.x.t);
       break;
     case spill_psprel_p:
       output_X3_format (f, ptr->r.type, ptr->r.record.x.qp,
                        ptr->r.record.x.ab, ptr->r.record.x.reg,
-                       ptr->r.record.x.t, ptr->r.record.x.pspoff);
+                       ptr->r.record.x.t, ptr->r.record.x.where.pspoff);
       break;
     case spill_sprel_p:
       output_X3_format (f, ptr->r.type, ptr->r.record.x.qp,
                        ptr->r.record.x.ab, ptr->r.record.x.reg,
-                       ptr->r.record.x.t, ptr->r.record.x.spoff);
+                       ptr->r.record.x.t, ptr->r.record.x.where.spoff);
       break;
     case spill_reg_p:
       output_X4_format (f, ptr->r.record.x.qp, ptr->r.record.x.ab,
                        ptr->r.record.x.reg, ptr->r.record.x.xy >> 1,
-                       ptr->r.record.x.xy, ptr->r.record.x.treg,
+                       ptr->r.record.x.xy, ptr->r.record.x.where.reg,
                        ptr->r.record.x.t);
       break;
     default:
-      as_bad ("record_type_not_valid");
+      as_bad (_("record_type_not_valid"));
       break;
     }
 }
@@ -2509,9 +2442,7 @@ process_one_record (ptr, f)
 /* Given a unw_rec_list list, process all the records with
    the specified function.  */
 static void
-process_unw_records (list, f)
-     unw_rec_list *list;
-     vbyte_func f;
+process_unw_records (unw_rec_list *list, vbyte_func f)
 {
   unw_rec_list *ptr;
   for (ptr = list; ptr; ptr = ptr->next)
@@ -2520,14 +2451,35 @@ process_unw_records (list, f)
 
 /* Determine the size of a record list in bytes.  */
 static int
-calc_record_size (list)
-     unw_rec_list *list;
+calc_record_size (unw_rec_list *list)
 {
   vbyte_count = 0;
   process_unw_records (list, count_output);
   return vbyte_count;
 }
 
+/* Return the number of bits set in the input value.
+   Perhaps this has a better place...  */
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# define popcount __builtin_popcount
+#else
+static int
+popcount (unsigned x)
+{
+  static const unsigned char popcnt[16] =
+    {
+      0, 1, 1, 2,
+      1, 2, 2, 3,
+      1, 2, 2, 3,
+      2, 3, 3, 4
+    };
+
+  if (x < NELEMS (popcnt))
+    return popcnt[x];
+  return popcnt[x % NELEMS (popcnt)] + popcount (x / NELEMS (popcnt));
+}
+#endif
+
 /* Update IMASK bitmask to reflect the fact that one or more registers
    of type TYPE are saved starting at instruction with index T.  If N
    bits are set in REGMASK, it is assumed that instructions T through
@@ -2539,11 +2491,10 @@ calc_record_size (list)
        2: instruction saves next general reg
        3: instruction saves next branch reg */
 static void
-set_imask (region, regmask, t, type)
-     unw_rec_list *region;
-     unsigned long regmask;
-     unsigned long t;
-     unsigned int type;
+set_imask (unw_rec_list *region,
+          unsigned long regmask,
+          unsigned long t,
+          unsigned int type)
 {
   unsigned char *imask;
   unsigned long imask_size;
@@ -2568,7 +2519,7 @@ set_imask (region, regmask, t, type)
     {
       if (i >= imask_size)
        {
-         as_bad ("Ignoring attempt to spill beyond end of region");
+         as_bad (_("Ignoring attempt to spill beyond end of region"));
          return;
        }
 
@@ -2589,15 +2540,14 @@ set_imask (region, regmask, t, type)
    containing FIRST_ADDR.  If BEFORE_RELAX, then we use worst-case estimates
    for frag sizes.  */
 
-unsigned long
-slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
-     unsigned long slot_addr;
-     fragS *slot_frag;
-     unsigned long first_addr;
-     fragS *first_frag;
-     int before_relax;
+static unsigned long
+slot_index (unsigned long slot_addr,
+           fragS *slot_frag,
+           unsigned long first_addr,
+           fragS *first_frag,
+           int before_relax)
 {
-  unsigned long index = 0;
+  unsigned long s_index = 0;
 
   /* First time we are called, the initial address and frag are invalid.  */
   if (first_addr == 0)
@@ -2615,7 +2565,7 @@ slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
          /* We can get the final addresses only during and after
             relaxation.  */
          if (first_frag->fr_next && first_frag->fr_next->fr_address)
-           index += 3 * ((first_frag->fr_next->fr_address
+           s_index += 3 * ((first_frag->fr_next->fr_address
                           - first_frag->fr_address
                             - first_frag->fr_fix) >> 4);
        }
@@ -2628,7 +2578,7 @@ slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
            break;
 
          case rs_space:
-           as_fatal ("only constant space allocation is supported");
+           as_fatal (_("Only constant space allocation is supported"));
            break;
 
          case rs_align:
@@ -2636,42 +2586,48 @@ slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax)
          case rs_align_test:
            /* Take alignment into account.  Assume the worst case
               before relaxation.  */
-           index += 3 * ((1 << first_frag->fr_offset) >> 4);
+           s_index += 3 * ((1 << first_frag->fr_offset) >> 4);
            break;
 
          case rs_org:
            if (first_frag->fr_symbol)
              {
-               as_fatal ("only constant offsets are supported");
+               as_fatal (_("Only constant offsets are supported"));
                break;
              }
          case rs_fill:
-           index += 3 * (first_frag->fr_offset >> 4);
+           s_index += 3 * (first_frag->fr_offset >> 4);
            break;
          }
 
       /* Add in the full size of the frag converted to instruction slots.  */
-      index += 3 * (first_frag->fr_fix >> 4);
+      s_index += 3 * (first_frag->fr_fix >> 4);
       /* Subtract away the initial part before first_addr.  */
-      index -= (3 * ((first_addr >> 4) - (start_addr >> 4))
+      s_index -= (3 * ((first_addr >> 4) - (start_addr >> 4))
                + ((first_addr & 0x3) - (start_addr & 0x3)));
 
       /* Move to the beginning of the next frag.  */
       first_frag = first_frag->fr_next;
       first_addr = (unsigned long) &first_frag->fr_literal;
+
+      /* This can happen if there is section switching in the middle of a
+        function, causing the frag chain for the function to be broken.
+        It is too difficult to recover safely from this problem, so we just
+        exit with an error.  */
+      if (first_frag == NULL)
+       as_fatal (_("Section switching in code is not supported."));
     }
 
   /* Add in the used part of the last frag.  */
-  index += (3 * ((slot_addr >> 4) - (first_addr >> 4))
+  s_index += (3 * ((slot_addr >> 4) - (first_addr >> 4))
            + ((slot_addr & 0x3) - (first_addr & 0x3)));
-  return index;
+  return s_index;
 }
 
 /* Optimize unwind record directives.  */
 
 static unw_rec_list *
-optimize_unw_records (list)
-     unw_rec_list *list;
+optimize_unw_records (unw_rec_list *list)
 {
   if (!list)
     return NULL;
@@ -2692,9 +2648,7 @@ optimize_unw_records (list)
    within each record to generate an image.  */
 
 static void
-fixup_unw_records (list, before_relax)
-     unw_rec_list *list;
-     int before_relax;
+fixup_unw_records (unw_rec_list *list, int before_relax)
 {
   unw_rec_list *ptr, *region = 0;
   unsigned long first_addr = 0, rlen = 0, t;
@@ -2703,7 +2657,7 @@ fixup_unw_records (list, before_relax)
   for (ptr = list; ptr; ptr = ptr->next)
     {
       if (ptr->slot_number == SLOT_NUM_NOT_SET)
-       as_bad (" Insn slot not set in unwind record.");
+       as_bad (_(" Insn slot not set in unwind record."));
       t = slot_index (ptr->slot_number, ptr->slot_frag,
                      first_addr, first_frag, before_relax);
       switch (ptr->r.type)
@@ -2777,7 +2731,7 @@ fixup_unw_records (list, before_relax)
        case frgr_mem:
          if (!region)
            {
-             as_bad ("frgr_mem record before region record!");
+             as_bad (_("frgr_mem record before region record!"));
              return;
            }
          region->r.record.r.mask.fr_mem |= ptr->r.record.p.frmask;
@@ -2788,25 +2742,25 @@ fixup_unw_records (list, before_relax)
        case fr_mem:
          if (!region)
            {
-             as_bad ("fr_mem record before region record!");
+             as_bad (_("fr_mem record before region record!"));
              return;
            }
-         region->r.record.r.mask.fr_mem |= ptr->r.record.p.rmask;
-         set_imask (region, ptr->r.record.p.rmask, t, 1);
+         region->r.record.r.mask.fr_mem |= ptr->r.record.p.frmask;
+         set_imask (region, ptr->r.record.p.frmask, t, 1);
          break;
        case gr_mem:
          if (!region)
            {
-             as_bad ("gr_mem record before region record!");
+             as_bad (_("gr_mem record before region record!"));
              return;
            }
-         region->r.record.r.mask.gr_mem |= ptr->r.record.p.rmask;
-         set_imask (region, ptr->r.record.p.rmask, t, 2);
+         region->r.record.r.mask.gr_mem |= ptr->r.record.p.grmask;
+         set_imask (region, ptr->r.record.p.grmask, t, 2);
          break;
        case br_mem:
          if (!region)
            {
-             as_bad ("br_mem record before region record!");
+             as_bad (_("br_mem record before region record!"));
              return;
            }
          region->r.record.r.mask.br_mem |= ptr->r.record.p.brmask;
@@ -2816,7 +2770,7 @@ fixup_unw_records (list, before_relax)
        case gr_gr:
          if (!region)
            {
-             as_bad ("gr_gr record before region record!");
+             as_bad (_("gr_gr record before region record!"));
              return;
            }
          set_imask (region, ptr->r.record.p.grmask, t, 2);
@@ -2824,7 +2778,7 @@ fixup_unw_records (list, before_relax)
        case br_gr:
          if (!region)
            {
-             as_bad ("br_gr record before region record!");
+             as_bad (_("br_gr record before region record!"));
              return;
            }
          set_imask (region, ptr->r.record.p.brmask, t, 3);
@@ -2863,7 +2817,7 @@ ia64_estimate_size_before_relax (fragS *frag,
 
   /* fr_var carries the max_chars that we created the fragment with.
      We must, of course, have allocated enough memory earlier.  */
-  assert (frag->fr_var >= size);
+  gas_assert (frag->fr_var >= size);
 
   return frag->fr_fix + size;
 }
@@ -2894,7 +2848,7 @@ ia64_convert_frag (fragS *frag)
 
   /* fr_var carries the max_chars that we created the fragment with.
      We must, of course, have allocated enough memory earlier.  */
-  assert (frag->fr_var >= size);
+  gas_assert (frag->fr_var >= size);
 
   /* Initialize the header area. fr_offset is initialized with
      unwind.personality_routine.  */
@@ -2923,6 +2877,10 @@ ia64_convert_frag (fragS *frag)
   if (pad != 0)
     md_number_to_chars (frag->fr_literal + len + 8 - md.pointer_size + pad, 0,
                        md.pointer_size - pad);
+  /* Fill the unwind personality with zeros.  */
+  if (frag->fr_offset)
+    md_number_to_chars (frag->fr_literal + size - md.pointer_size, 0,
+                       md.pointer_size);
 
   frag->fr_fix += size;
   frag->fr_type = rs_fill;
@@ -2931,17 +2889,39 @@ ia64_convert_frag (fragS *frag)
 }
 
 static int
-convert_expr_to_ab_reg (e, ab, regp)
-     expressionS *e;
-     unsigned int *ab;
-     unsigned int *regp;
+parse_predicate_and_operand (expressionS *e, unsigned *qp, const char *po)
+{
+  int sep = parse_operand_and_eval (e, ',');
+
+  *qp = e->X_add_number - REG_P;
+  if (e->X_op != O_register || *qp > 63)
+    {
+      as_bad (_("First operand to .%s must be a predicate"), po);
+      *qp = 0;
+    }
+  else if (*qp == 0)
+    as_warn (_("Pointless use of p0 as first operand to .%s"), po);
+  if (sep == ',')
+    sep = parse_operand_and_eval (e, ',');
+  else
+    e->X_op = O_absent;
+  return sep;
+}
+
+static void
+convert_expr_to_ab_reg (const expressionS *e,
+                       unsigned int *ab,
+                       unsigned int *regp,
+                       const char *po,
+                       int n)
 {
-  unsigned int reg;
+  unsigned int reg = e->X_add_number;
+
+  *ab = *regp = 0; /* Anything valid is good here.  */
 
   if (e->X_op != O_register)
-    return 0;
+    reg = REG_GR; /* Anything invalid is good here.  */
 
-  reg = e->X_add_number;
   if (reg >= (REG_GR + 4) && reg <= (REG_GR + 7))
     {
       *ab = 0;
@@ -2976,31 +2956,32 @@ convert_expr_to_ab_reg (e, ab, regp)
        case REG_AR + AR_LC:    *regp = 10; break;
 
        default:
-         return 0;
+         as_bad (_("Operand %d to .%s must be a preserved register"), n, po);
+         break;
        }
     }
-  return 1;
 }
 
-static int
-convert_expr_to_xy_reg (e, xy, regp)
-     expressionS *e;
-     unsigned int *xy;
-     unsigned int *regp;
+static void
+convert_expr_to_xy_reg (const expressionS *e,
+                       unsigned int *xy,
+                       unsigned int *regp,
+                       const char *po,
+                       int n)
 {
-  unsigned int reg;
+  unsigned int reg = e->X_add_number;
 
-  if (e->X_op != O_register)
-    return 0;
+  *xy = *regp = 0; /* Anything valid is good here.  */
 
-  reg = e->X_add_number;
+  if (e->X_op != O_register)
+    reg = REG_GR; /* Anything invalid is good here.  */
 
-  if (/* reg >= REG_GR && */ reg <= (REG_GR + 127))
+  if (reg >= (REG_GR + 1) && reg <= (REG_GR + 127))
     {
       *xy = 0;
       *regp = reg - REG_GR;
     }
-  else if (reg >= REG_FR && reg <= (REG_FR + 127))
+  else if (reg >= (REG_FR + 2) && reg <= (REG_FR + 127))
     {
       *xy = 1;
       *regp = reg - REG_FR;
@@ -3011,8 +2992,7 @@ convert_expr_to_xy_reg (e, xy, regp)
       *regp = reg - REG_BR;
     }
   else
-    return -1;
-  return 1;
+    as_bad (_("Operand %d to .%s must be a writable register"), n, po);
 }
 
 static void
@@ -3024,20 +3004,22 @@ dot_align (int arg)
 }
 
 static void
-dot_radix (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_radix (int dummy ATTRIBUTE_UNUSED)
 {
-  int radix;
+  char *radix;
+  int ch;
 
   SKIP_WHITESPACE ();
-  radix = *input_line_pointer++;
 
-  if (radix != 'C' && !is_end_of_line[(unsigned char) radix])
-    {
-      as_bad ("Radix `%c' unsupported", *input_line_pointer);
-      ignore_rest_of_line ();
-      return;
-    }
+  if (is_it_end_of_statement ())
+    return;
+  radix = input_line_pointer;
+  ch = get_symbol_end ();
+  ia64_canonicalize_symbol_name (radix);
+  if (strcasecmp (radix, "C"))
+    as_bad (_("Radix `%s' unsupported or invalid"), radix);
+  *input_line_pointer = ch;
+  demand_empty_rest_of_line ();
 }
 
 /* Helper function for .loc directives.  If the assembler is not generating
@@ -3053,8 +3035,7 @@ dot_loc (int x)
 
 /* .sbss, .bss etc. are macros that expand into ".section SECNAME".  */
 static void
-dot_special_section (which)
-     int which;
+dot_special_section (int which)
 {
   set_section ((char *) special_section_name[which]);
 }
@@ -3066,12 +3047,12 @@ unwind_diagnostic (const char * region, const char *directive)
 {
   if (md.unwind_check == unwind_check_warning)
     {
-      as_warn (".%s outside of %s", directive, region);
+      as_warn (_(".%s outside of %s"), directive, region);
       return -1;
     }
   else
     {
-      as_bad (".%s outside of %s", directive, region);
+      as_bad (_(".%s outside of %s"), directive, region);
       ignore_rest_of_line ();
       return 0;
     }
@@ -3085,7 +3066,7 @@ unwind_diagnostic (const char * region, const char *directive)
 static int
 in_procedure (const char *directive)
 {
-  if (unwind.proc_start
+  if (unwind.proc_pending.sym
       && (!unwind.saved_text_seg || strcmp (directive, "endp") == 0))
     return 1;
   return unwind_diagnostic ("procedure", directive);
@@ -3100,18 +3081,11 @@ static int
 in_prologue (const char *directive)
 {
   int in = in_procedure (directive);
-  if (in)
-    {
-      /* We are in a procedure. Check if we are in a prologue.  */
-      if (unwind.prologue)
-       return 1;
-      /* We only want to issue one message.  */
-      if (in == 1)
-       return unwind_diagnostic ("prologue", directive);
-      else
-       return -1;
-    }
-  return 0;
+
+  if (in > 0 && !unwind.prologue)
+    in = unwind_diagnostic ("prologue", directive);
+  check_pending_save ();
+  return in;
 }
 
 /* Return 1 if a directive is in a body, -1 if a directive isn't in
@@ -3123,217 +3097,233 @@ static int
 in_body (const char *directive)
 {
   int in = in_procedure (directive);
-  if (in)
-    {
-      /* We are in a procedure. Check if we are in a body.  */
-      if (unwind.body)
-       return 1;
-      /* We only want to issue one message.  */
-      if (in == 1)
-       return unwind_diagnostic ("body region", directive);
-      else
-       return -1;
-    }
-  return 0;
+
+  if (in > 0 && !unwind.body)
+    in = unwind_diagnostic ("body region", directive);
+  return in;
 }
 
 static void
-add_unwind_entry (ptr)
-     unw_rec_list *ptr;
+add_unwind_entry (unw_rec_list *ptr, int sep)
 {
-  if (unwind.tail)
-    unwind.tail->next = ptr;
-  else
-    unwind.list = ptr;
-  unwind.tail = ptr;
+  if (ptr)
+    {
+      if (unwind.tail)
+       unwind.tail->next = ptr;
+      else
+       unwind.list = ptr;
+      unwind.tail = ptr;
+
+      /* The current entry can in fact be a chain of unwind entries.  */
+      if (unwind.current_entry == NULL)
+       unwind.current_entry = ptr;
+    }
 
   /* The current entry can in fact be a chain of unwind entries.  */
   if (unwind.current_entry == NULL)
     unwind.current_entry = ptr;
+
+  if (sep == ',')
+    {
+      /* Parse a tag permitted for the current directive.  */
+      int ch;
+
+      SKIP_WHITESPACE ();
+      ch = get_symbol_end ();
+      /* FIXME: For now, just issue a warning that this isn't implemented.  */
+      {
+       static int warned;
+
+       if (!warned)
+         {
+           warned = 1;
+           as_warn (_("Tags on unwind pseudo-ops aren't supported, yet"));
+         }
+      }
+      *input_line_pointer = ch;
+    }
+  if (sep != NOT_A_CHAR)
+    demand_empty_rest_of_line ();
 }
 
 static void
-dot_fframe (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_fframe (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
+  int sep;
 
   if (!in_prologue ("fframe"))
     return;
 
-  parse_operand (&e);
+  sep = parse_operand_and_eval (&e, ',');
 
   if (e.X_op != O_constant)
-    as_bad ("Operand to .fframe must be a constant");
-  else
-    add_unwind_entry (output_mem_stack_f (e.X_add_number));
+    {
+      as_bad (_("First operand to .fframe must be a constant"));
+      e.X_add_number = 0;
+    }
+  add_unwind_entry (output_mem_stack_f (e.X_add_number), sep);
 }
 
 static void
-dot_vframe (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_vframe (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
   unsigned reg;
+  int sep;
 
   if (!in_prologue ("vframe"))
     return;
 
-  parse_operand (&e);
+  sep = parse_operand_and_eval (&e, ',');
   reg = e.X_add_number - REG_GR;
-  if (e.X_op == O_register && reg < 128)
+  if (e.X_op != O_register || reg > 127)
     {
-      add_unwind_entry (output_mem_stack_v ());
-      if (! (unwind.prologue_mask & 2))
-       add_unwind_entry (output_psp_gr (reg));
+      as_bad (_("First operand to .vframe must be a general register"));
+      reg = 0;
     }
-  else
-    as_bad ("First operand to .vframe must be a general register");
+  add_unwind_entry (output_mem_stack_v (), sep);
+  if (! (unwind.prologue_mask & 2))
+    add_unwind_entry (output_psp_gr (reg), NOT_A_CHAR);
+  else if (reg != unwind.prologue_gr
+                 + (unsigned) popcount (unwind.prologue_mask & (-2 << 1)))
+    as_warn (_("Operand of .vframe contradicts .prologue"));
 }
 
 static void
-dot_vframesp (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_vframesp (int psp)
 {
   expressionS e;
+  int sep;
 
-  if (!in_prologue ("vframesp"))
-    return;
-
-  parse_operand (&e);
-  if (e.X_op == O_constant)
-    {
-      add_unwind_entry (output_mem_stack_v ());
-      add_unwind_entry (output_psp_sprel (e.X_add_number));
-    }
-  else
-    as_bad ("Operand to .vframesp must be a constant (sp-relative offset)");
-}
-
-static void
-dot_vframepsp (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  expressionS e;
+  if (psp)
+    as_warn (_(".vframepsp is meaningless, assuming .vframesp was meant"));
 
-  if (!in_prologue ("vframepsp"))
+  if (!in_prologue ("vframesp"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op == O_constant)
+  sep = parse_operand_and_eval (&e, ',');
+  if (e.X_op != O_constant)
     {
-      add_unwind_entry (output_mem_stack_v ());
-      add_unwind_entry (output_psp_sprel (e.X_add_number));
+      as_bad (_("Operand to .vframesp must be a constant (sp-relative offset)"));
+      e.X_add_number = 0;
     }
-  else
-    as_bad ("Operand to .vframepsp must be a constant (psp-relative offset)");
+  add_unwind_entry (output_mem_stack_v (), sep);
+  add_unwind_entry (output_psp_sprel (e.X_add_number), NOT_A_CHAR);
 }
 
 static void
-dot_save (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_save (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e1, e2;
+  unsigned reg1, reg2;
   int sep;
-  int reg1, reg2;
 
   if (!in_prologue ("save"))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    as_bad ("No second operand to .save");
-  sep = parse_operand (&e2);
+  sep = parse_operand_and_eval (&e1, ',');
+  if (sep == ',')
+    sep = parse_operand_and_eval (&e2, ',');
+  else
+    e2.X_op = O_absent;
 
   reg1 = e1.X_add_number;
-  reg2 = e2.X_add_number - REG_GR;
-
   /* Make sure its a valid ar.xxx reg, OR its br0, aka 'rp'.  */
-  if (e1.X_op == O_register)
+  if (e1.X_op != O_register)
     {
-      if (e2.X_op == O_register && reg2 >= 0 && reg2 < 128)
-       {
-         switch (reg1)
-           {
-           case REG_AR + AR_BSP:
-             add_unwind_entry (output_bsp_when ());
-             add_unwind_entry (output_bsp_gr (reg2));
-             break;
-           case REG_AR + AR_BSPSTORE:
-             add_unwind_entry (output_bspstore_when ());
-             add_unwind_entry (output_bspstore_gr (reg2));
-             break;
-           case REG_AR + AR_RNAT:
-             add_unwind_entry (output_rnat_when ());
-             add_unwind_entry (output_rnat_gr (reg2));
-             break;
-           case REG_AR + AR_UNAT:
-             add_unwind_entry (output_unat_when ());
-             add_unwind_entry (output_unat_gr (reg2));
-             break;
-           case REG_AR + AR_FPSR:
-             add_unwind_entry (output_fpsr_when ());
-             add_unwind_entry (output_fpsr_gr (reg2));
-             break;
-           case REG_AR + AR_PFS:
-             add_unwind_entry (output_pfs_when ());
-             if (! (unwind.prologue_mask & 4))
-               add_unwind_entry (output_pfs_gr (reg2));
-             break;
-           case REG_AR + AR_LC:
-             add_unwind_entry (output_lc_when ());
-             add_unwind_entry (output_lc_gr (reg2));
-             break;
-           case REG_BR:
-             add_unwind_entry (output_rp_when ());
-             if (! (unwind.prologue_mask & 8))
-               add_unwind_entry (output_rp_gr (reg2));
-             break;
-           case REG_PR:
-             add_unwind_entry (output_preds_when ());
-             if (! (unwind.prologue_mask & 1))
-               add_unwind_entry (output_preds_gr (reg2));
-             break;
-           case REG_PRIUNAT:
-             add_unwind_entry (output_priunat_when_gr ());
-             add_unwind_entry (output_priunat_gr (reg2));
-             break;
-           default:
-             as_bad ("First operand not a valid register");
-           }
-       }
-      else
-       as_bad (" Second operand not a valid register");
+      as_bad (_("First operand to .save not a register"));
+      reg1 = REG_PR; /* Anything valid is good here.  */
+    }
+  reg2 = e2.X_add_number - REG_GR;
+  if (e2.X_op != O_register || reg2 > 127)
+    {
+      as_bad (_("Second operand to .save not a valid register"));
+      reg2 = 0;
+    }
+  switch (reg1)
+    {
+    case REG_AR + AR_BSP:
+      add_unwind_entry (output_bsp_when (), sep);
+      add_unwind_entry (output_bsp_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_BSPSTORE:
+      add_unwind_entry (output_bspstore_when (), sep);
+      add_unwind_entry (output_bspstore_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_RNAT:
+      add_unwind_entry (output_rnat_when (), sep);
+      add_unwind_entry (output_rnat_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_UNAT:
+      add_unwind_entry (output_unat_when (), sep);
+      add_unwind_entry (output_unat_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_FPSR:
+      add_unwind_entry (output_fpsr_when (), sep);
+      add_unwind_entry (output_fpsr_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_PFS:
+      add_unwind_entry (output_pfs_when (), sep);
+      if (! (unwind.prologue_mask & 4))
+       add_unwind_entry (output_pfs_gr (reg2), NOT_A_CHAR);
+      else if (reg2 != unwind.prologue_gr
+                      + (unsigned) popcount (unwind.prologue_mask & (-4 << 1)))
+       as_warn (_("Second operand of .save contradicts .prologue"));
+      break;
+    case REG_AR + AR_LC:
+      add_unwind_entry (output_lc_when (), sep);
+      add_unwind_entry (output_lc_gr (reg2), NOT_A_CHAR);
+      break;
+    case REG_BR:
+      add_unwind_entry (output_rp_when (), sep);
+      if (! (unwind.prologue_mask & 8))
+       add_unwind_entry (output_rp_gr (reg2), NOT_A_CHAR);
+      else if (reg2 != unwind.prologue_gr)
+       as_warn (_("Second operand of .save contradicts .prologue"));
+      break;
+    case REG_PR:
+      add_unwind_entry (output_preds_when (), sep);
+      if (! (unwind.prologue_mask & 1))
+       add_unwind_entry (output_preds_gr (reg2), NOT_A_CHAR);
+      else if (reg2 != unwind.prologue_gr
+                      + (unsigned) popcount (unwind.prologue_mask & (-1 << 1)))
+       as_warn (_("Second operand of .save contradicts .prologue"));
+      break;
+    case REG_PRIUNAT:
+      add_unwind_entry (output_priunat_when_gr (), sep);
+      add_unwind_entry (output_priunat_gr (reg2), NOT_A_CHAR);
+      break;
+    default:
+      as_bad (_("First operand to .save not a valid register"));
+      add_unwind_entry (NULL, sep);
+      break;
     }
-  else
-    as_bad ("First operand not a register");
 }
 
 static void
-dot_restore (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_restore (int dummy ATTRIBUTE_UNUSED)
 {
-  expressionS e1, e2;
+  expressionS e1;
   unsigned long ecount;        /* # of _additional_ regions to pop */
   int sep;
 
   if (!in_body ("restore"))
     return;
 
-  sep = parse_operand (&e1);
+  sep = parse_operand_and_eval (&e1, ',');
   if (e1.X_op != O_register || e1.X_add_number != REG_GR + 12)
-    {
-      as_bad ("First operand to .restore must be stack pointer (sp)");
-      return;
-    }
+    as_bad (_("First operand to .restore must be stack pointer (sp)"));
 
   if (sep == ',')
     {
-      parse_operand (&e2);
+      expressionS e2;
+
+      sep = parse_operand_and_eval (&e2, ',');
       if (e2.X_op != O_constant || e2.X_add_number < 0)
        {
-         as_bad ("Second operand to .restore must be a constant >= 0");
-         return;
+         as_bad (_("Second operand to .restore must be a constant >= 0"));
+         e2.X_add_number = 0;
        }
       ecount = e2.X_add_number;
     }
@@ -3342,12 +3332,12 @@ dot_restore (dummy)
 
   if (ecount >= unwind.prologue_count)
     {
-      as_bad ("Epilogue count of %lu exceeds number of nested prologues (%u)",
+      as_bad (_("Epilogue count of %lu exceeds number of nested prologues (%u)"),
              ecount + 1, unwind.prologue_count);
-      return;
+      ecount = 0;
     }
 
-  add_unwind_entry (output_epilogue (ecount));
+  add_unwind_entry (output_epilogue (ecount), sep);
 
   if (ecount < unwind.prologue_count)
     unwind.prologue_count -= ecount + 1;
@@ -3356,58 +3346,26 @@ dot_restore (dummy)
 }
 
 static void
-dot_restorereg (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_restorereg (int pred)
 {
-  unsigned int ab, reg;
+  unsigned int qp, ab, reg;
   expressionS e;
-
-  if (!in_procedure ("restorereg"))
-    return;
-
-  parse_operand (&e);
-
-  if (!convert_expr_to_ab_reg (&e, &ab, &reg))
-    {
-      as_bad ("First operand to .restorereg must be a preserved register");
-      return;
-    }
-  add_unwind_entry (output_spill_reg (ab, reg, 0, 0));
-}
-
-static void
-dot_restorereg_p (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  unsigned int qp, ab, reg;
-  expressionS e1, e2;
   int sep;
+  const char * const po = pred ? "restorereg.p" : "restorereg";
 
-  if (!in_procedure ("restorereg.p"))
+  if (!in_procedure (po))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("No second operand to .restorereg.p");
-      return;
-    }
-
-  parse_operand (&e2);
-
-  qp = e1.X_add_number - REG_P;
-  if (e1.X_op != O_register || qp > 63)
+  if (pred)
+    sep = parse_predicate_and_operand (&e, &qp, po);
+  else
     {
-      as_bad ("First operand to .restorereg.p must be a predicate");
-      return;
+      sep = parse_operand_and_eval (&e, ',');
+      qp = 0;
     }
+  convert_expr_to_ab_reg (&e, &ab, &reg, po, 1 + pred);
 
-  if (!convert_expr_to_ab_reg (&e2, &ab, &reg))
-    {
-      as_bad ("Second operand to .restorereg.p must be a preserved register");
-      return;
-    }
-  add_unwind_entry (output_spill_reg_p (ab, reg, 0, 0, qp));
+  add_unwind_entry (output_spill_reg (ab, reg, 0, 0, qp), sep);
 }
 
 static char *special_linkonce_name[] =
@@ -3416,7 +3374,7 @@ static char *special_linkonce_name[] =
   };
 
 static void
-start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
+start_unwind_section (const segT text_seg, int sec_index)
 {
   /*
     Use a slightly ugly scheme to derive the unwind section names from
@@ -3461,7 +3419,7 @@ start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
   text_name = sec_text_name;
   if (strncmp (text_name, "_info", 5) == 0)
     {
-      as_bad ("Illegal section name `%s' (causes unwind section name clash)",
+      as_bad (_("Illegal section name `%s' (causes unwind section name clash)"),
              text_name);
       ignore_rest_of_line ();
       return;
@@ -3478,8 +3436,6 @@ start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
       prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
       suffix += sizeof (".gnu.linkonce.t.") - 1;
     }
-  else if (linkonce_empty)
-    return;
 
   prefix_len = strlen (prefix);
   suffix_len = strlen (suffix);
@@ -3490,7 +3446,8 @@ start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
   sec_name [sec_name_len] = '\0';
 
   /* Handle COMDAT group.  */
-  if (suffix == text_name && (text_seg->flags & SEC_LINK_ONCE) != 0)
+  if ((text_seg->flags & SEC_LINK_ONCE) != 0
+      && (elf_section_flags (text_seg) & SHF_GROUP) != 0)
     {
       char *section;
       size_t len, group_name_len;
@@ -3498,7 +3455,7 @@ start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
 
       if (group_name == NULL)
        {
-         as_bad ("Group section `%s' has no group signature",
+         as_bad (_("Group section `%s' has no group signature"),
                  sec_text_name);
          ignore_rest_of_line ();
          return;
@@ -3536,7 +3493,7 @@ generate_unwind_image (const segT text_seg)
 
   /* Mark the end of the unwind info, so that we can compute the size of the
      last unwind region.  */
-  add_unwind_entry (output_endp ());
+  add_unwind_entry (output_endp (), NOT_A_CHAR);
 
   /* Force out pending instructions, to make sure all unwind records have
      a valid slot_number field.  */
@@ -3567,7 +3524,7 @@ generate_unwind_image (const segT text_seg)
       expressionS exp;
       bfd_reloc_code_real_type reloc;
 
-      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 0);
+      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
 
       /* Make sure the section has 4 byte alignment for ILP32 and
         8 byte alignment for LP64.  */
@@ -3608,16 +3565,13 @@ generate_unwind_image (const segT text_seg)
          unwind.personality_routine = 0;
        }
     }
-  else
-    start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 1);
 
   free_saved_prologue_counts ();
   unwind.list = unwind.tail = unwind.current_entry = NULL;
 }
 
 static void
-dot_handlerdata (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_handlerdata (int dummy ATTRIBUTE_UNUSED)
 {
   if (!in_procedure ("handlerdata"))
     return;
@@ -3635,8 +3589,7 @@ dot_handlerdata (dummy)
 }
 
 static void
-dot_unwentry (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_unwentry (int dummy ATTRIBUTE_UNUSED)
 {
   if (!in_procedure ("unwentry"))
     return;
@@ -3645,8 +3598,7 @@ dot_unwentry (dummy)
 }
 
 static void
-dot_altrp (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_altrp (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
   unsigned reg;
@@ -3654,424 +3606,356 @@ dot_altrp (dummy)
   if (!in_prologue ("altrp"))
     return;
 
-  parse_operand (&e);
+  parse_operand_and_eval (&e, 0);
   reg = e.X_add_number - REG_BR;
-  if (e.X_op == O_register && reg < 8)
-    add_unwind_entry (output_rp_br (reg));
-  else
-    as_bad ("First operand not a valid branch register");
+  if (e.X_op != O_register || reg > 7)
+    {
+      as_bad (_("First operand to .altrp not a valid branch register"));
+      reg = 0;
+    }
+  add_unwind_entry (output_rp_br (reg), 0);
 }
 
 static void
-dot_savemem (psprel)
-     int psprel;
+dot_savemem (int psprel)
 {
   expressionS e1, e2;
   int sep;
   int reg1, val;
+  const char * const po = psprel ? "savepsp" : "savesp";
 
-  if (!in_prologue (psprel ? "savepsp" : "savesp"))
+  if (!in_prologue (po))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    as_bad ("No second operand to .save%ssp", psprel ? "p" : "");
-  sep = parse_operand (&e2);
+  sep = parse_operand_and_eval (&e1, ',');
+  if (sep == ',')
+    sep = parse_operand_and_eval (&e2, ',');
+  else
+    e2.X_op = O_absent;
 
   reg1 = e1.X_add_number;
   val = e2.X_add_number;
 
   /* Make sure its a valid ar.xxx reg, OR its br0, aka 'rp'.  */
-  if (e1.X_op == O_register)
+  if (e1.X_op != O_register)
     {
-      if (e2.X_op == O_constant)
-       {
-         switch (reg1)
-           {
-           case REG_AR + AR_BSP:
-             add_unwind_entry (output_bsp_when ());
-             add_unwind_entry ((psprel
-                                ? output_bsp_psprel
-                                : output_bsp_sprel) (val));
-             break;
-           case REG_AR + AR_BSPSTORE:
-             add_unwind_entry (output_bspstore_when ());
-             add_unwind_entry ((psprel
-                                ? output_bspstore_psprel
-                                : output_bspstore_sprel) (val));
-             break;
-           case REG_AR + AR_RNAT:
-             add_unwind_entry (output_rnat_when ());
-             add_unwind_entry ((psprel
-                                ? output_rnat_psprel
-                                : output_rnat_sprel) (val));
-             break;
-           case REG_AR + AR_UNAT:
-             add_unwind_entry (output_unat_when ());
-             add_unwind_entry ((psprel
-                                ? output_unat_psprel
-                                : output_unat_sprel) (val));
-             break;
-           case REG_AR + AR_FPSR:
-             add_unwind_entry (output_fpsr_when ());
-             add_unwind_entry ((psprel
-                                ? output_fpsr_psprel
-                                : output_fpsr_sprel) (val));
-             break;
-           case REG_AR + AR_PFS:
-             add_unwind_entry (output_pfs_when ());
-             add_unwind_entry ((psprel
-                                ? output_pfs_psprel
-                                : output_pfs_sprel) (val));
-             break;
-           case REG_AR + AR_LC:
-             add_unwind_entry (output_lc_when ());
-             add_unwind_entry ((psprel
-                                ? output_lc_psprel
-                                : output_lc_sprel) (val));
-             break;
-           case REG_BR:
-             add_unwind_entry (output_rp_when ());
-             add_unwind_entry ((psprel
-                                ? output_rp_psprel
-                                : output_rp_sprel) (val));
-             break;
-           case REG_PR:
-             add_unwind_entry (output_preds_when ());
-             add_unwind_entry ((psprel
-                                ? output_preds_psprel
-                                : output_preds_sprel) (val));
-             break;
-           case REG_PRIUNAT:
-             add_unwind_entry (output_priunat_when_mem ());
-             add_unwind_entry ((psprel
-                                ? output_priunat_psprel
-                                : output_priunat_sprel) (val));
-             break;
-           default:
-             as_bad ("First operand not a valid register");
-           }
-       }
-      else
-       as_bad (" Second operand not a valid constant");
+      as_bad (_("First operand to .%s not a register"), po);
+      reg1 = REG_PR; /* Anything valid is good here.  */
+    }
+  if (e2.X_op != O_constant)
+    {
+      as_bad (_("Second operand to .%s not a constant"), po);
+      val = 0;
+    }
+
+  switch (reg1)
+    {
+    case REG_AR + AR_BSP:
+      add_unwind_entry (output_bsp_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_bsp_psprel
+                        : output_bsp_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_BSPSTORE:
+      add_unwind_entry (output_bspstore_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_bspstore_psprel
+                        : output_bspstore_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_RNAT:
+      add_unwind_entry (output_rnat_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_rnat_psprel
+                        : output_rnat_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_UNAT:
+      add_unwind_entry (output_unat_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_unat_psprel
+                        : output_unat_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_FPSR:
+      add_unwind_entry (output_fpsr_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_fpsr_psprel
+                        : output_fpsr_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_PFS:
+      add_unwind_entry (output_pfs_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_pfs_psprel
+                        : output_pfs_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_AR + AR_LC:
+      add_unwind_entry (output_lc_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_lc_psprel
+                        : output_lc_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_BR:
+      add_unwind_entry (output_rp_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_rp_psprel
+                        : output_rp_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_PR:
+      add_unwind_entry (output_preds_when (), sep);
+      add_unwind_entry ((psprel
+                        ? output_preds_psprel
+                        : output_preds_sprel) (val), NOT_A_CHAR);
+      break;
+    case REG_PRIUNAT:
+      add_unwind_entry (output_priunat_when_mem (), sep);
+      add_unwind_entry ((psprel
+                        ? output_priunat_psprel
+                        : output_priunat_sprel) (val), NOT_A_CHAR);
+      break;
+    default:
+      as_bad (_("First operand to .%s not a valid register"), po);
+      add_unwind_entry (NULL, sep);
+      break;
     }
-  else
-    as_bad ("First operand not a register");
 }
 
 static void
-dot_saveg (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_saveg (int dummy ATTRIBUTE_UNUSED)
 {
-  expressionS e1, e2;
+  expressionS e;
+  unsigned grmask;
   int sep;
 
   if (!in_prologue ("save.g"))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep == ',')
-    parse_operand (&e2);
+  sep = parse_operand_and_eval (&e, ',');
 
-  if (e1.X_op != O_constant)
-    as_bad ("First operand to .save.g must be a constant.");
-  else
+  grmask = e.X_add_number;
+  if (e.X_op != O_constant
+      || e.X_add_number <= 0
+      || e.X_add_number > 0xf)
     {
-      int grmask = e1.X_add_number;
-      if (sep != ',')
-       add_unwind_entry (output_gr_mem (grmask));
-      else
+      as_bad (_("First operand to .save.g must be a positive 4-bit constant"));
+      grmask = 0;
+    }
+
+  if (sep == ',')
+    {
+      unsigned reg;
+      int n = popcount (grmask);
+
+      parse_operand_and_eval (&e, 0);
+      reg = e.X_add_number - REG_GR;
+      if (e.X_op != O_register || reg > 127)
        {
-         int reg = e2.X_add_number - REG_GR;
-         if (e2.X_op == O_register && reg >= 0 && reg < 128)
-           add_unwind_entry (output_gr_gr (grmask, reg));
-         else
-           as_bad ("Second operand is an invalid register.");
+         as_bad (_("Second operand to .save.g must be a general register"));
+         reg = 0;
+       }
+      else if (reg > 128U - n)
+       {
+         as_bad (_("Second operand to .save.g must be the first of %d general registers"), n);
+         reg = 0;
        }
+      add_unwind_entry (output_gr_gr (grmask, reg), 0);
     }
+  else
+    add_unwind_entry (output_gr_mem (grmask), 0);
 }
 
 static void
-dot_savef (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_savef (int dummy ATTRIBUTE_UNUSED)
 {
-  expressionS e1;
-  int sep;
+  expressionS e;
 
   if (!in_prologue ("save.f"))
     return;
 
-  sep = parse_operand (&e1);
+  parse_operand_and_eval (&e, 0);
 
-  if (e1.X_op != O_constant)
-    as_bad ("Operand to .save.f must be a constant.");
-  else
-    add_unwind_entry (output_fr_mem (e1.X_add_number));
+  if (e.X_op != O_constant
+      || e.X_add_number <= 0
+      || e.X_add_number > 0xfffff)
+    {
+      as_bad (_("Operand to .save.f must be a positive 20-bit constant"));
+      e.X_add_number = 0;
+    }
+  add_unwind_entry (output_fr_mem (e.X_add_number), 0);
 }
 
 static void
-dot_saveb (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_saveb (int dummy ATTRIBUTE_UNUSED)
 {
-  expressionS e1, e2;
-  unsigned int reg;
-  unsigned char sep;
-  int brmask;
+  expressionS e;
+  unsigned brmask;
+  int sep;
 
   if (!in_prologue ("save.b"))
     return;
 
-  sep = parse_operand (&e1);
-  if (e1.X_op != O_constant)
+  sep = parse_operand_and_eval (&e, ',');
+
+  brmask = e.X_add_number;
+  if (e.X_op != O_constant
+      || e.X_add_number <= 0
+      || e.X_add_number > 0x1f)
     {
-      as_bad ("First operand to .save.b must be a constant.");
-      return;
+      as_bad (_("First operand to .save.b must be a positive 5-bit constant"));
+      brmask = 0;
     }
-  brmask = e1.X_add_number;
 
   if (sep == ',')
     {
-      sep = parse_operand (&e2);
-      reg = e2.X_add_number - REG_GR;
-      if (e2.X_op != O_register || reg > 127)
+      unsigned reg;
+      int n = popcount (brmask);
+
+      parse_operand_and_eval (&e, 0);
+      reg = e.X_add_number - REG_GR;
+      if (e.X_op != O_register || reg > 127)
        {
-         as_bad ("Second operand to .save.b must be a general register.");
-         return;
+         as_bad (_("Second operand to .save.b must be a general register"));
+         reg = 0;
+       }
+      else if (reg > 128U - n)
+       {
+         as_bad (_("Second operand to .save.b must be the first of %d general registers"), n);
+         reg = 0;
        }
-      add_unwind_entry (output_br_gr (brmask, e2.X_add_number));
+      add_unwind_entry (output_br_gr (brmask, reg), 0);
     }
   else
-    add_unwind_entry (output_br_mem (brmask));
-
-  if (!is_end_of_line[sep] && !is_it_end_of_statement ())
-    demand_empty_rest_of_line ();
+    add_unwind_entry (output_br_mem (brmask), 0);
 }
 
 static void
-dot_savegf (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_savegf (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e1, e2;
-  int sep;
 
   if (!in_prologue ("save.gf"))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep == ',')
-    parse_operand (&e2);
-
-  if (e1.X_op != O_constant || sep != ',' || e2.X_op != O_constant)
-    as_bad ("Both operands of .save.gf must be constants.");
-  else
-    {
-      int grmask = e1.X_add_number;
-      int frmask = e2.X_add_number;
-      add_unwind_entry (output_frgr_mem (grmask, frmask));
-    }
-}
-
-static void
-dot_spill (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  expressionS e;
-  unsigned char sep;
-
-  if (!in_prologue ("spill"))
-    return;
-
-  sep = parse_operand (&e);
-  if (!is_end_of_line[sep] && !is_it_end_of_statement ())
-    demand_empty_rest_of_line ();
-
-  if (e.X_op != O_constant)
-    as_bad ("Operand to .spill must be a constant");
+  if (parse_operand_and_eval (&e1, ',') == ',')
+    parse_operand_and_eval (&e2, 0);
   else
-    add_unwind_entry (output_spill_base (e.X_add_number));
-}
+    e2.X_op = O_absent;
 
-static void
-dot_spillreg (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  int sep, ab, xy, reg, treg;
-  expressionS e1, e2;
-
-  if (!in_procedure ("spillreg"))
-    return;
-
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("No second operand to .spillreg");
-      return;
-    }
-
-  parse_operand (&e2);
-
-  if (!convert_expr_to_ab_reg (&e1, &ab, &reg))
+  if (e1.X_op != O_constant
+      || e1.X_add_number < 0
+      || e1.X_add_number > 0xf)
     {
-      as_bad ("First operand to .spillreg must be a preserved register");
-      return;
+      as_bad (_("First operand to .save.gf must be a non-negative 4-bit constant"));
+      e1.X_op = O_absent;
+      e1.X_add_number = 0;
     }
-
-  if (!convert_expr_to_xy_reg (&e2, &xy, &treg))
+  if (e2.X_op != O_constant
+      || e2.X_add_number < 0
+      || e2.X_add_number > 0xfffff)
     {
-      as_bad ("Second operand to .spillreg must be a register");
-      return;
+      as_bad (_("Second operand to .save.gf must be a non-negative 20-bit constant"));
+      e2.X_op = O_absent;
+      e2.X_add_number = 0;
     }
+  if (e1.X_op == O_constant
+      && e2.X_op == O_constant
+      && e1.X_add_number == 0
+      && e2.X_add_number == 0)
+    as_bad (_("Operands to .save.gf may not be both zero"));
 
-  add_unwind_entry (output_spill_reg (ab, reg, treg, xy));
+  add_unwind_entry (output_frgr_mem (e1.X_add_number, e2.X_add_number), 0);
 }
 
 static void
-dot_spillmem (psprel)
-     int psprel;
+dot_spill (int dummy ATTRIBUTE_UNUSED)
 {
-  expressionS e1, e2;
-  int sep, ab, reg;
+  expressionS e;
 
-  if (!in_procedure ("spillmem"))
+  if (!in_prologue ("spill"))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("Second operand missing");
-      return;
-    }
-
-  parse_operand (&e2);
-
-  if (!convert_expr_to_ab_reg (&e1, &ab, &reg))
-    {
-      as_bad ("First operand to .spill%s must be a preserved register",
-             psprel ? "psp" : "sp");
-      return;
-    }
+  parse_operand_and_eval (&e, 0);
 
-  if (e2.X_op != O_constant)
+  if (e.X_op != O_constant)
     {
-      as_bad ("Second operand to .spill%s must be a constant",
-             psprel ? "psp" : "sp");
-      return;
+      as_bad (_("Operand to .spill must be a constant"));
+      e.X_add_number = 0;
     }
-
-  if (psprel)
-    add_unwind_entry (output_spill_psprel (ab, reg, e2.X_add_number));
-  else
-    add_unwind_entry (output_spill_sprel (ab, reg, e2.X_add_number));
+  add_unwind_entry (output_spill_base (e.X_add_number), 0);
 }
 
 static void
-dot_spillreg_p (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_spillreg (int pred)
 {
-  int sep, ab, xy, reg, treg;
-  expressionS e1, e2, e3;
-  unsigned int qp;
+  int sep;
+  unsigned int qp, ab, xy, reg, treg;
+  expressionS e;
+  const char * const po = pred ? "spillreg.p" : "spillreg";
 
-  if (!in_procedure ("spillreg.p"))
+  if (!in_procedure (po))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("No second and third operand to .spillreg.p");
-      return;
-    }
-
-  sep = parse_operand (&e2);
-  if (sep != ',')
-    {
-      as_bad ("No third operand to .spillreg.p");
-      return;
-    }
-
-  parse_operand (&e3);
-
-  qp = e1.X_add_number - REG_P;
-
-  if (e1.X_op != O_register || qp > 63)
-    {
-      as_bad ("First operand to .spillreg.p must be a predicate");
-      return;
-    }
-
-  if (!convert_expr_to_ab_reg (&e2, &ab, &reg))
+  if (pred)
+    sep = parse_predicate_and_operand (&e, &qp, po);
+  else
     {
-      as_bad ("Second operand to .spillreg.p must be a preserved register");
-      return;
+      sep = parse_operand_and_eval (&e, ',');
+      qp = 0;
     }
+  convert_expr_to_ab_reg (&e, &ab, &reg, po, 1 + pred);
 
-  if (!convert_expr_to_xy_reg (&e3, &xy, &treg))
-    {
-      as_bad ("Third operand to .spillreg.p must be a register");
-      return;
-    }
+  if (sep == ',')
+    sep = parse_operand_and_eval (&e, ',');
+  else
+    e.X_op = O_absent;
+  convert_expr_to_xy_reg (&e, &xy, &treg, po, 2 + pred);
 
-  add_unwind_entry (output_spill_reg_p (ab, reg, treg, xy, qp));
+  add_unwind_entry (output_spill_reg (ab, reg, treg, xy, qp), sep);
 }
 
 static void
-dot_spillmem_p (psprel)
-     int psprel;
+dot_spillmem (int psprel)
 {
-  expressionS e1, e2, e3;
-  int sep, ab, reg;
-  unsigned int qp;
-
-  if (!in_procedure ("spillmem.p"))
-    return;
-
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("Second operand missing");
-      return;
-    }
+  expressionS e;
+  int pred = (psprel < 0), sep;
+  unsigned int qp, ab, reg;
+  const char * po;
 
-  parse_operand (&e2);
-  if (sep != ',')
+  if (pred)
     {
-      as_bad ("Second operand missing");
-      return;
+      psprel = ~psprel;
+      po = psprel ? "spillpsp.p" : "spillsp.p";
     }
+  else
+    po = psprel ? "spillpsp" : "spillsp";
 
-  parse_operand (&e3);
-
-  qp = e1.X_add_number - REG_P;
-  if (e1.X_op != O_register || qp > 63)
-    {
-      as_bad ("First operand to .spill%s_p must be a predicate",
-             psprel ? "psp" : "sp");
-      return;
-    }
+  if (!in_procedure (po))
+    return;
 
-  if (!convert_expr_to_ab_reg (&e2, &ab, &reg))
+  if (pred)
+    sep = parse_predicate_and_operand (&e, &qp, po);
+  else
     {
-      as_bad ("Second operand to .spill%s_p must be a preserved register",
-             psprel ? "psp" : "sp");
-      return;
+      sep = parse_operand_and_eval (&e, ',');
+      qp = 0;
     }
+  convert_expr_to_ab_reg (&e, &ab, &reg, po, 1 + pred);
 
-  if (e3.X_op != O_constant)
+  if (sep == ',')
+    sep = parse_operand_and_eval (&e, ',');
+  else
+    e.X_op = O_absent;
+  if (e.X_op != O_constant)
     {
-      as_bad ("Third operand to .spill%s_p must be a constant",
-             psprel ? "psp" : "sp");
-      return;
+      as_bad (_("Operand %d to .%s must be a constant"), 2 + pred, po);
+      e.X_add_number = 0;
     }
 
   if (psprel)
-    add_unwind_entry (output_spill_psprel_p (ab, reg, e3.X_add_number, qp));
+    add_unwind_entry (output_spill_psprel (ab, reg, e.X_add_number, qp), sep);
   else
-    add_unwind_entry (output_spill_sprel_p (ab, reg, e3.X_add_number, qp));
+    add_unwind_entry (output_spill_sprel (ab, reg, e.X_add_number, qp), sep);
 }
 
 static unsigned int
-get_saved_prologue_count (lbl)
-     unsigned long lbl;
+get_saved_prologue_count (unsigned long lbl)
 {
   label_prologue_count *lpc = unwind.saved_prologue_counts;
 
@@ -4081,14 +3965,12 @@ get_saved_prologue_count (lbl)
   if (lpc != NULL)
     return lpc->prologue_count;
 
-  as_bad ("Missing .label_state %ld", lbl);
+  as_bad (_("Missing .label_state %ld"), lbl);
   return 1;
 }
 
 static void
-save_prologue_count (lbl, count)
-     unsigned long lbl;
-     unsigned int count;
+save_prologue_count (unsigned long lbl, unsigned int count)
 {
   label_prologue_count *lpc = unwind.saved_prologue_counts;
 
@@ -4125,81 +4007,75 @@ free_saved_prologue_counts ()
 }
 
 static void
-dot_label_state (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_label_state (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
 
   if (!in_body ("label_state"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op != O_constant)
+  parse_operand_and_eval (&e, 0);
+  if (e.X_op == O_constant)
+    save_prologue_count (e.X_add_number, unwind.prologue_count);
+  else
     {
-      as_bad ("Operand to .label_state must be a constant");
-      return;
+      as_bad (_("Operand to .label_state must be a constant"));
+      e.X_add_number = 0;
     }
-  add_unwind_entry (output_label_state (e.X_add_number));
-  save_prologue_count (e.X_add_number, unwind.prologue_count);
+  add_unwind_entry (output_label_state (e.X_add_number), 0);
 }
 
 static void
-dot_copy_state (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_copy_state (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
 
   if (!in_body ("copy_state"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op != O_constant)
+  parse_operand_and_eval (&e, 0);
+  if (e.X_op == O_constant)
+    unwind.prologue_count = get_saved_prologue_count (e.X_add_number);
+  else
     {
-      as_bad ("Operand to .copy_state must be a constant");
-      return;
+      as_bad (_("Operand to .copy_state must be a constant"));
+      e.X_add_number = 0;
     }
-  add_unwind_entry (output_copy_state (e.X_add_number));
-  unwind.prologue_count = get_saved_prologue_count (e.X_add_number);
+  add_unwind_entry (output_copy_state (e.X_add_number), 0);
 }
 
 static void
-dot_unwabi (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_unwabi (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e1, e2;
   unsigned char sep;
 
-  if (!in_procedure ("unwabi"))
+  if (!in_prologue ("unwabi"))
     return;
 
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("Second operand to .unwabi missing");
-      return;
-    }
-  sep = parse_operand (&e2);
-  if (!is_end_of_line[sep] && !is_it_end_of_statement ())
-    demand_empty_rest_of_line ();
+  sep = parse_operand_and_eval (&e1, ',');
+  if (sep == ',')
+    parse_operand_and_eval (&e2, 0);
+  else
+    e2.X_op = O_absent;
 
   if (e1.X_op != O_constant)
     {
-      as_bad ("First operand to .unwabi must be a constant");
-      return;
+      as_bad (_("First operand to .unwabi must be a constant"));
+      e1.X_add_number = 0;
     }
 
   if (e2.X_op != O_constant)
     {
-      as_bad ("Second operand to .unwabi must be a constant");
-      return;
+      as_bad (_("Second operand to .unwabi must be a constant"));
+      e2.X_add_number = 0;
     }
 
-  add_unwind_entry (output_unwabi (e1.X_add_number, e2.X_add_number));
+  add_unwind_entry (output_unwabi (e1.X_add_number, e2.X_add_number), 0);
 }
 
 static void
-dot_personality (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_personality (int dummy ATTRIBUTE_UNUSED)
 {
   char *name, *p, c;
   if (!in_procedure ("personality"))
@@ -4216,13 +4092,26 @@ dot_personality (dummy)
 }
 
 static void
-dot_proc (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_proc (int dummy ATTRIBUTE_UNUSED)
 {
   char *name, *p, c;
   symbolS *sym;
+  proc_pending *pending, *last_pending;
+
+  if (unwind.proc_pending.sym)
+    {
+      (md.unwind_check == unwind_check_warning
+       ? as_warn
+       : as_bad) (_("Missing .endp after previous .proc"));
+      while (unwind.proc_pending.next)
+       {
+         pending = unwind.proc_pending.next;
+         unwind.proc_pending.next = pending->next;
+         free (pending);
+       }
+    }
+  last_pending = NULL;
 
-  unwind.proc_start = 0;
   /* Parse names of main and alternate entry points and mark them as
      function symbols:  */
   while (1)
@@ -4232,15 +4121,22 @@ dot_proc (dummy)
       c = get_symbol_end ();
       p = input_line_pointer;
       if (!*name)
-       as_bad ("Empty argument of .proc");
+       as_bad (_("Empty argument of .proc"));
       else
        {
          sym = symbol_find_or_make (name);
          if (S_IS_DEFINED (sym))
-           as_bad ("`%s' was already defined", name);
-         else if (unwind.proc_start == 0)
+           as_bad (_("`%s' was already defined"), name);
+         else if (!last_pending)
+           {
+             unwind.proc_pending.sym = sym;
+             last_pending = &unwind.proc_pending;
+           }
+         else
            {
-             unwind.proc_start = sym;
+             pending = xmalloc (sizeof (*pending));
+             pending->sym = sym;
+             last_pending = last_pending->next = pending;
            }
          symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
        }
@@ -4250,8 +4146,12 @@ dot_proc (dummy)
        break;
       ++input_line_pointer;
     }
-  if (unwind.proc_start == 0)
-    unwind.proc_start = expr_build_dot ();
+  if (!last_pending)
+    {
+      unwind.proc_pending.sym = expr_build_dot ();
+      last_pending = &unwind.proc_pending;
+    }
+  last_pending->next = NULL;
   demand_empty_rest_of_line ();
   ia64_do_align (16);
 
@@ -4264,88 +4164,99 @@ dot_proc (dummy)
 }
 
 static void
-dot_body (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_body (int dummy ATTRIBUTE_UNUSED)
 {
   if (!in_procedure ("body"))
     return;
   if (!unwind.prologue && !unwind.body && unwind.insn)
-    as_warn ("Initial .body should precede any instructions");
+    as_warn (_("Initial .body should precede any instructions"));
+  check_pending_save ();
 
   unwind.prologue = 0;
   unwind.prologue_mask = 0;
   unwind.body = 1;
 
-  add_unwind_entry (output_body ());
-  demand_empty_rest_of_line ();
+  add_unwind_entry (output_body (), 0);
 }
 
 static void
-dot_prologue (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_prologue (int dummy ATTRIBUTE_UNUSED)
 {
-  unsigned char sep;
-  int mask = 0, grsave = 0;
+  unsigned mask = 0, grsave = 0;
 
   if (!in_procedure ("prologue"))
     return;
   if (unwind.prologue)
     {
-      as_bad (".prologue within prologue");
+      as_bad (_(".prologue within prologue"));
       ignore_rest_of_line ();
       return;
     }
   if (!unwind.body && unwind.insn)
-    as_warn ("Initial .prologue should precede any instructions");
+    as_warn (_("Initial .prologue should precede any instructions"));
 
   if (!is_it_end_of_statement ())
     {
-      expressionS e1, e2;
-      sep = parse_operand (&e1);
-      if (sep != ',')
-       as_bad ("No second operand to .prologue");
-      sep = parse_operand (&e2);
-      if (!is_end_of_line[sep] && !is_it_end_of_statement ())
-       demand_empty_rest_of_line ();
+      expressionS e;
+      int n, sep = parse_operand_and_eval (&e, ',');
 
-      if (e1.X_op == O_constant)
-       {
-         mask = e1.X_add_number;
-
-         if (e2.X_op == O_constant)
-           grsave = e2.X_add_number;
-         else if (e2.X_op == O_register
-                  && (grsave = e2.X_add_number - REG_GR) < 128)
-           ;
-         else
-           as_bad ("Second operand not a constant or general register");
+      if (e.X_op != O_constant
+         || e.X_add_number < 0
+         || e.X_add_number > 0xf)
+       as_bad (_("First operand to .prologue must be a positive 4-bit constant"));
+      else if (e.X_add_number == 0)
+       as_warn (_("Pointless use of zero first operand to .prologue"));
+      else
+       mask = e.X_add_number;
+       n = popcount (mask);
 
-         add_unwind_entry (output_prologue_gr (mask, grsave));
-       }
+      if (sep == ',')
+       parse_operand_and_eval (&e, 0);
       else
-       as_bad ("First operand not a constant");
+       e.X_op = O_absent;
+      if (e.X_op == O_constant
+         && e.X_add_number >= 0
+         && e.X_add_number < 128)
+       {
+         if (md.unwind_check == unwind_check_error)
+           as_warn (_("Using a constant as second operand to .prologue is deprecated"));
+         grsave = e.X_add_number;
+       }
+      else if (e.X_op != O_register
+              || (grsave = e.X_add_number - REG_GR) > 127)
+       {
+         as_bad (_("Second operand to .prologue must be a general register"));
+         grsave = 0;
+       }
+      else if (grsave > 128U - n)
+       {
+         as_bad (_("Second operand to .prologue must be the first of %d general registers"), n);
+         grsave = 0;
+       }
+
     }
+
+  if (mask)
+    add_unwind_entry (output_prologue_gr (mask, grsave), 0);
   else
-    add_unwind_entry (output_prologue ());
+    add_unwind_entry (output_prologue (), 0);
 
   unwind.prologue = 1;
   unwind.prologue_mask = mask;
+  unwind.prologue_gr = grsave;
   unwind.body = 0;
   ++unwind.prologue_count;
 }
 
 static void
-dot_endp (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_endp (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS e;
-  unsigned char *ptr;
   int bytes_per_address;
   long where;
   segT saved_seg;
   subsegT saved_subseg;
-  char *name, *default_name, *p, c;
-  symbolS *sym;
+  proc_pending *pending;
   int unwind_check = md.unwind_check;
 
   md.unwind_check = unwind_check_error;
@@ -4378,7 +4289,7 @@ dot_endp (dummy)
       subseg_set (md.last_text_seg, 0);
       proc_end = expr_build_dot ();
 
-      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 0);
+      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
 
       /* Make sure that section has 4 byte alignment for ILP32 and
          8 byte alignment for LP64.  */
@@ -4386,7 +4297,7 @@ dot_endp (dummy)
 
       /* Need space for 3 pointers for procedure start, procedure end,
         and unwind info.  */
-      ptr = frag_more (3 * md.pointer_size);
+      memset (frag_more (3 * md.pointer_size), 0, 3 * md.pointer_size);
       where = frag_now_fix () - (3 * md.pointer_size);
       bytes_per_address = bfd_arch_bits_per_address (stdoutput) / 8;
 
@@ -4394,7 +4305,13 @@ dot_endp (dummy)
       e.X_op = O_pseudo_fixup;
       e.X_op_symbol = pseudo_func[FUNC_SEG_RELATIVE].u.sym;
       e.X_add_number = 0;
-      e.X_add_symbol = unwind.proc_start;
+      if (!S_IS_LOCAL (unwind.proc_pending.sym)
+         && S_IS_DEFINED (unwind.proc_pending.sym))
+       e.X_add_symbol = symbol_temp_new (S_GET_SEGMENT (unwind.proc_pending.sym),
+                                         S_GET_VALUE (unwind.proc_pending.sym),
+                                         symbol_get_frag (unwind.proc_pending.sym));
+      else
+       e.X_add_symbol = unwind.proc_pending.sym;
       ia64_cons_fix_new (frag_now, where, bytes_per_address, &e);
 
       e.X_op = O_pseudo_fixup;
@@ -4413,72 +4330,25 @@ dot_endp (dummy)
          ia64_cons_fix_new (frag_now, where + (bytes_per_address * 2),
                             bytes_per_address, &e);
        }
-      else
-       md_number_to_chars (ptr + (bytes_per_address * 2), 0,
-                           bytes_per_address);
-
     }
-  else
-    start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 1);
-
   subseg_set (saved_seg, saved_subseg);
 
-  if (unwind.proc_start)
-    default_name = (char *) S_GET_NAME (unwind.proc_start);
-  else
-    default_name = NULL;
-
-  /* Parse names of main and alternate entry points and set symbol sizes.  */
-  while (1)
+  /* Set symbol sizes.  */
+  pending = &unwind.proc_pending;
+  if (S_GET_NAME (pending->sym))
     {
-      SKIP_WHITESPACE ();
-      name = input_line_pointer;
-      c = get_symbol_end ();
-      p = input_line_pointer;
-      if (!*name)
-       {
-         if (md.unwind_check == unwind_check_warning)
-           {
-             if (default_name)
-               {
-                 as_warn ("Empty argument of .endp. Use the default name `%s'",
-                          default_name);
-                 name = default_name;
-               }
-             else
-               as_warn ("Empty argument of .endp");
-           }
-         else
-           as_bad ("Empty argument of .endp");
-       }
-      if (*name)
+      do
        {
-         sym = symbol_find (name);
-         if (!sym
-             && md.unwind_check == unwind_check_warning
-             && default_name
-             && default_name != name)
-           {
-             /* We have a bad name. Try the default one if needed.  */
-             as_warn ("`%s' was not defined within procedure. Use the default name `%s'",
-                      name, default_name);
-             name = default_name;
-             sym = symbol_find (name);
-           }
-         if (!sym || !S_IS_DEFINED (sym))
-           as_bad ("`%s' was not defined within procedure", name);
-         else if (unwind.proc_start
-             && (symbol_get_bfdsym (sym)->flags & BSF_FUNCTION)
-             && S_GET_SIZE (sym) == 0 && symbol_get_obj (sym)->size == NULL)
+         symbolS *sym = pending->sym;
+
+         if (!S_IS_DEFINED (sym))
+           as_bad (_("`%s' was not defined within procedure"), S_GET_NAME (sym));
+         else if (S_GET_SIZE (sym) == 0
+                  && symbol_get_obj (sym)->size == NULL)
            {
-             fragS *fr = symbol_get_frag (unwind.proc_start);
              fragS *frag = symbol_get_frag (sym);
 
-             /* Check whether the function label is at or beyond last
-                .proc directive.  */
-             while (fr && fr != frag)
-               fr = fr->fr_next;
-             if (fr)
+             if (frag)
                {
                  if (frag == frag_now && SEG_NORMAL (now_seg))
                    S_SET_SIZE (sym, frag_now_fix () - S_GET_VALUE (sym));
@@ -4495,6 +4365,36 @@ dot_endp (dummy)
                    }
                }
            }
+       } while ((pending = pending->next) != NULL);
+    }
+
+  /* Parse names of main and alternate entry points.  */
+  while (1)
+    {
+      char *name, *p, c;
+
+      SKIP_WHITESPACE ();
+      name = input_line_pointer;
+      c = get_symbol_end ();
+      p = input_line_pointer;
+      if (!*name)
+       (md.unwind_check == unwind_check_warning
+        ? as_warn
+        : as_bad) (_("Empty argument of .endp"));
+      else
+       {
+         symbolS *sym = symbol_find (name);
+
+         for (pending = &unwind.proc_pending; pending; pending = pending->next)
+           {
+             if (sym == pending->sym)
+               {
+                 pending->sym = NULL;
+                 break;
+               }
+           }
+         if (!sym || !pending)
+           as_warn (_("`%s' was not specified with previous .proc"), name);
        }
       *p = c;
       SKIP_WHITESPACE ();
@@ -4503,19 +4403,31 @@ dot_endp (dummy)
       ++input_line_pointer;
     }
   demand_empty_rest_of_line ();
-  unwind.proc_start = unwind.info = 0;
+
+  /* Deliberately only checking for the main entry point here; the
+     language spec even says all arguments to .endp are ignored.  */
+  if (unwind.proc_pending.sym
+      && S_GET_NAME (unwind.proc_pending.sym)
+      && strcmp (S_GET_NAME (unwind.proc_pending.sym), FAKE_LABEL_NAME))
+    as_warn (_("`%s' should be an operand to this .endp"),
+            S_GET_NAME (unwind.proc_pending.sym));
+  while (unwind.proc_pending.next)
+    {
+      pending = unwind.proc_pending.next;
+      unwind.proc_pending.next = pending->next;
+      free (pending);
+    }
+  unwind.proc_pending.sym = unwind.info = NULL;
 }
 
 static void
-dot_template (template)
-     int template;
+dot_template (int template_val)
 {
-  CURR_SLOT.user_template = template;
+  CURR_SLOT.user_template = template_val;
 }
 
 static void
-dot_regstk (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_regstk (int dummy ATTRIBUTE_UNUSED)
 {
   int ins, locs, outs, rots;
 
@@ -4538,15 +4450,15 @@ dot_regstk (dummy)
   return;
 
  err:
-  as_bad ("Comma expected");
+  as_bad (_("Comma expected"));
   ignore_rest_of_line ();
 }
 
 static void
-dot_rot (type)
-     int type;
+dot_rot (int type)
 {
-  unsigned num_regs, num_alloced = 0;
+  offsetT num_regs;
+  valueT num_alloced = 0;
   struct dynreg **drpp, *dr;
   int ch, base_reg = 0;
   char *name, *start;
@@ -4563,7 +4475,7 @@ dot_rot (type)
   /* First, remove existing names from hash table.  */
   for (dr = md.dynreg[type]; dr && dr->num_regs; dr = dr->next)
     {
-      hash_delete (md.dynreg_hash, dr->name);
+      hash_delete (md.dynreg_hash, dr->name, FALSE);
       /* FIXME: Free dr->name.  */
       dr->num_regs = 0;
     }
@@ -4579,7 +4491,7 @@ dot_rot (type)
       SKIP_WHITESPACE ();
       if (*input_line_pointer != '[')
        {
-         as_bad ("Expected '['");
+         as_bad (_("Expected '['"));
          goto err;
        }
       ++input_line_pointer;    /* skip '[' */
@@ -4588,7 +4500,12 @@ dot_rot (type)
 
       if (*input_line_pointer++ != ']')
        {
-         as_bad ("Expected ']'");
+         as_bad (_("Expected ']'"));
+         goto err;
+       }
+      if (num_regs <= 0)
+       {
+         as_bad (_("Number of elements must be positive"));
          goto err;
        }
       SKIP_WHITESPACE ();
@@ -4599,7 +4516,7 @@ dot_rot (type)
        case DYNREG_GR:
          if (num_alloced > md.rot.num_regs)
            {
-             as_bad ("Used more than the declared %d rotating registers",
+             as_bad (_("Used more than the declared %d rotating registers"),
                      md.rot.num_regs);
              goto err;
            }
@@ -4607,14 +4524,14 @@ dot_rot (type)
        case DYNREG_FR:
          if (num_alloced > 96)
            {
-             as_bad ("Used more than the available 96 rotating registers");
+             as_bad (_("Used more than the available 96 rotating registers"));
              goto err;
            }
          break;
        case DYNREG_PR:
          if (num_alloced > 48)
            {
-             as_bad ("Used more than the available 48 rotating registers");
+             as_bad (_("Used more than the available 48 rotating registers"));
              goto err;
            }
          break;
@@ -4642,7 +4559,7 @@ dot_rot (type)
 
       if (hash_insert (md.dynreg_hash, name, dr))
        {
-         as_bad ("Attempt to redefine register set `%s'", name);
+         as_bad (_("Attempt to redefine register set `%s'"), name);
          obstack_free (&notes, name);
          goto err;
        }
@@ -4660,8 +4577,7 @@ dot_rot (type)
 }
 
 static void
-dot_byteorder (byteorder)
-     int byteorder;
+dot_byteorder (int byteorder)
 {
   segment_info_type *seginfo = seg_info (now_seg);
 
@@ -4691,8 +4607,7 @@ dot_byteorder (byteorder)
 }
 
 static void
-dot_psr (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_psr (int dummy ATTRIBUTE_UNUSED)
 {
   char *option;
   int ch;
@@ -4710,7 +4625,7 @@ dot_psr (dummy)
       else if (strcmp (option, "abi64") == 0)
        md.flags |= EF_IA_64_ABI64;
       else
-       as_bad ("Unknown psr option `%s'", option);
+       as_bad (_("Unknown psr option `%s'"), option);
       *input_line_pointer = ch;
 
       SKIP_WHITESPACE ();
@@ -4724,72 +4639,83 @@ dot_psr (dummy)
 }
 
 static void
-dot_ln (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_ln (int dummy ATTRIBUTE_UNUSED)
 {
   new_logical_line (0, get_absolute_expression ());
   demand_empty_rest_of_line ();
 }
 
-static char *
-parse_section_name ()
+static void
+cross_section (int ref, void (*builder) (int), int ua)
 {
-  char *name;
-  int len;
+  char *start, *end;
+  int saved_auto_align;
+  unsigned int section_count;
 
   SKIP_WHITESPACE ();
-  if (*input_line_pointer == '"')
+  start = input_line_pointer;
+  if (*start == '"')
+    {
+      int len;
+      char *name;
+
       name = demand_copy_C_string (&len);
+      obstack_free(&notes, name);
+      if (!name)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
+    }
   else
     {
-      char *start = input_line_pointer;
       char c = get_symbol_end ();
 
       if (input_line_pointer == start)
        {
-         as_bad ("Missing section name");
+         as_bad (_("Missing section name"));
          ignore_rest_of_line ();
-         return 0;
+         return;
        }
-      name = obstack_copy (&notes, start, input_line_pointer - start + 1);
       *input_line_pointer = c;
     }
-  if (!name)
-    {
-      ignore_rest_of_line ();
-      return 0;
-    }
+  end = input_line_pointer;
   SKIP_WHITESPACE ();
   if (*input_line_pointer != ',')
     {
-      as_bad ("Comma expected after section name");
+      as_bad (_("Comma expected after section name"));
       ignore_rest_of_line ();
-      return 0;
+      return;
     }
-  ++input_line_pointer;                /* skip comma */
-  return name;
+  *end = '\0';
+  end = input_line_pointer + 1;                /* skip comma */
+  input_line_pointer = start;
+  md.keep_pending_output = 1;
+  section_count = bfd_count_sections (stdoutput);
+  obj_elf_section (0);
+  if (section_count != bfd_count_sections (stdoutput))
+    as_warn (_("Creating sections with .xdataN/.xrealN/.xstringZ is deprecated."));
+  input_line_pointer = end;
+  saved_auto_align = md.auto_align;
+  if (ua)
+    md.auto_align = 0;
+  (*builder) (ref);
+  if (ua)
+    md.auto_align = saved_auto_align;
+  obj_elf_previous (0);
+  md.keep_pending_output = 0;
 }
 
 static void
-dot_xdata (size)
-     int size;
+dot_xdata (int size)
 {
-  char *name = parse_section_name ();
-  if (!name)
-    return;
-
-  md.keep_pending_output = 1;
-  set_section (name);
-  cons (size);
-  obj_elf_previous (0);
-  md.keep_pending_output = 0;
+  cross_section (size, cons, 0);
 }
 
 /* Why doesn't float_cons() call md_cons_align() the way cons() does?  */
 
 static void
-stmt_float_cons (kind)
-     int kind;
+stmt_float_cons (int kind)
 {
   size_t alignment;
 
@@ -4814,8 +4740,7 @@ stmt_float_cons (kind)
 }
 
 static void
-stmt_cons_ua (size)
-     int size;
+stmt_cons_ua (int size)
 {
   int saved_auto_align = md.auto_align;
 
@@ -4825,80 +4750,37 @@ stmt_cons_ua (size)
 }
 
 static void
-dot_xfloat_cons (kind)
-     int kind;
+dot_xfloat_cons (int kind)
 {
-  char *name = parse_section_name ();
-  if (!name)
-    return;
-
-  md.keep_pending_output = 1;
-  set_section (name);
-  stmt_float_cons (kind);
-  obj_elf_previous (0);
-  md.keep_pending_output = 0;
+  cross_section (kind, stmt_float_cons, 0);
 }
 
 static void
-dot_xstringer (zero)
-     int zero;
+dot_xstringer (int zero)
 {
-  char *name = parse_section_name ();
-  if (!name)
-    return;
-
-  md.keep_pending_output = 1;
-  set_section (name);
-  stringer (zero);
-  obj_elf_previous (0);
-  md.keep_pending_output = 0;
+  cross_section (zero, stringer, 0);
 }
 
 static void
-dot_xdata_ua (size)
-     int size;
+dot_xdata_ua (int size)
 {
-  int saved_auto_align = md.auto_align;
-  char *name = parse_section_name ();
-  if (!name)
-    return;
-
-  md.keep_pending_output = 1;
-  set_section (name);
-  md.auto_align = 0;
-  cons (size);
-  md.auto_align = saved_auto_align;
-  obj_elf_previous (0);
-  md.keep_pending_output = 0;
+  cross_section (size, cons, 1);
 }
 
 static void
-dot_xfloat_cons_ua (kind)
-     int kind;
+dot_xfloat_cons_ua (int kind)
 {
-  int saved_auto_align = md.auto_align;
-  char *name = parse_section_name ();
-  if (!name)
-    return;
-
-  md.keep_pending_output = 1;
-  set_section (name);
-  md.auto_align = 0;
-  stmt_float_cons (kind);
-  md.auto_align = saved_auto_align;
-  obj_elf_previous (0);
-  md.keep_pending_output = 0;
+  cross_section (kind, float_cons, 1);
 }
 
 /* .reg.val <regname>,value */
 
 static void
-dot_reg_val (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_reg_val (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS reg;
 
-  expression (&reg);
+  expression_and_evaluate (&reg);
   if (reg.X_op != O_register)
     {
       as_bad (_("Register name expected"));
@@ -4913,7 +4795,7 @@ dot_reg_val (dummy)
     {
       valueT value = get_absolute_expression ();
       int regno = reg.X_add_number;
-      if (regno < REG_GR || regno > REG_GR + 128)
+      if (regno <= REG_GR || regno > REG_GR + 127)
        as_warn (_("Register value annotation ignored"));
       else
        {
@@ -4930,8 +4812,7 @@ dot_reg_val (dummy)
   .serialize.instruction
  */
 static void
-dot_serialize (type)
-     int type;
+dot_serialize (int type)
 {
   insn_group_break (0, 0, 0);
   if (type)
@@ -4951,8 +4832,7 @@ dot_serialize (type)
  */
 
 static void
-dot_dv_mode (type)
-     int type;
+dot_dv_mode (int type)
 {
   if (md.manual_bundling)
     as_warn (_("Directive invalid within a bundle"));
@@ -4988,8 +4868,7 @@ dot_dv_mode (type)
 }
 
 static void
-print_prmask (mask)
-     valueT mask;
+print_prmask (valueT mask)
 {
   int regno;
   char *comma = "";
@@ -5011,8 +4890,7 @@ print_prmask (mask)
  */
 
 static void
-dot_pred_rel (type)
-     int type;
+dot_pred_rel (int type)
 {
   valueT mask = 0;
   int count = 0;
@@ -5063,14 +4941,13 @@ dot_pred_rel (type)
       SKIP_WHITESPACE ();
     }
 
-  SKIP_WHITESPACE ();
   while (1)
     {
       valueT bits = 1;
-      int regno;
+      int sep, regno;
       expressionS pr, *pr1, *pr2;
 
-      expression (&pr);
+      sep = parse_operand_and_eval (&pr, ',');
       if (pr.X_op == O_register
          && pr.X_add_number >= REG_P
          && pr.X_add_number <= REG_P + 63)
@@ -5117,10 +4994,8 @@ dot_pred_rel (type)
       if (mask & bits)
        as_warn (_("Duplicate predicate register ignored"));
       mask |= bits;
-      if (*input_line_pointer != ',')
+      if (sep != ',')
        break;
-      ++input_line_pointer;
-      SKIP_WHITESPACE ();
     }
 
   switch (type)
@@ -5176,8 +5051,7 @@ dot_pred_rel (type)
    Otherwise, only global labels are considered entry points.  */
 
 static void
-dot_entry (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+dot_entry (int dummy ATTRIBUTE_UNUSED)
 {
   const char *err;
   char *name;
@@ -5190,7 +5064,7 @@ dot_entry (dummy)
       c = get_symbol_end ();
       symbolP = symbol_find_or_make (name);
 
-      err = hash_insert (md.entry_hash, S_GET_NAME (symbolP), (PTR) symbolP);
+      err = hash_insert (md.entry_hash, S_GET_NAME (symbolP), (void *) symbolP);
       if (err)
        as_fatal (_("Inserting \"%s\" into entry hint table failed: %s"),
                  name, err);
@@ -5215,8 +5089,7 @@ dot_entry (dummy)
    "base" is used to distinguish between offsets from a different base.  */
 
 static void
-dot_mem_offset (dummy)
-  int dummy ATTRIBUTE_UNUSED;
+dot_mem_offset (int dummy ATTRIBUTE_UNUSED)
 {
   md.mem_offset.hint = 1;
   md.mem_offset.offset = get_absolute_expression ();
@@ -5254,11 +5127,11 @@ const pseudo_typeS md_pseudo_table[] =
     { "fframe", dot_fframe, 0 },
     { "vframe", dot_vframe, 0 },
     { "vframesp", dot_vframesp, 0 },
-    { "vframepsp", dot_vframepsp, 0 },
+    { "vframepsp", dot_vframesp, 1 },
     { "save", dot_save, 0 },
     { "restore", dot_restore, 0 },
     { "restorereg", dot_restorereg, 0 },
-    { "restorereg.p", dot_restorereg_p, 0 },
+    { "restorereg.p", dot_restorereg, 1 },
     { "handlerdata", dot_handlerdata, 0 },
     { "unwentry", dot_unwentry, 0 },
     { "altrp", dot_altrp, 0 },
@@ -5272,9 +5145,9 @@ const pseudo_typeS md_pseudo_table[] =
     { "spillreg", dot_spillreg, 0 },
     { "spillsp", dot_spillmem, 0 },
     { "spillpsp", dot_spillmem, 1 },
-    { "spillreg.p", dot_spillreg_p, 0 },
-    { "spillsp.p", dot_spillmem_p, 0 },
-    { "spillpsp.p", dot_spillmem_p, 1 },
+    { "spillreg.p", dot_spillreg, 1 },
+    { "spillsp.p", dot_spillmem, ~0 },
+    { "spillpsp.p", dot_spillmem, ~1 },
     { "label_state", dot_label_state, 0 },
     { "copy_state", dot_copy_state, 0 },
     { "unwabi", dot_unwabi, 0 },
@@ -5311,8 +5184,8 @@ const pseudo_typeS md_pseudo_table[] =
     { "xreal8", dot_xfloat_cons, 'd' },
     { "xreal10", dot_xfloat_cons, 'x' },
     { "xreal16", dot_xfloat_cons, 'X' },
-    { "xstring", dot_xstringer, 0 },
-    { "xstringz", dot_xstringer, 1 },
+    { "xstring", dot_xstringer, 8 + 0 },
+    { "xstringz", dot_xstringer, 8 + 1 },
 
     /* unaligned versions:  */
     { "xdata2.ua", dot_xdata_ua, 2 },
@@ -5369,8 +5242,8 @@ pseudo_opcode[] =
     { "real8", stmt_float_cons, 'd' },
     { "real10", stmt_float_cons, 'x' },
     { "real16", stmt_float_cons, 'X' },
-    { "string", stringer, 0 },
-    { "stringz", stringer, 1 },
+    { "string", stringer, 8 + 0 },
+    { "stringz", stringer, 8 + 1 },
 
     /* unaligned versions:  */
     { "data2.ua", stmt_cons_ua, 2 },
@@ -5387,16 +5260,14 @@ pseudo_opcode[] =
    the symbol table.  */
 
 static symbolS *
-declare_register (name, regnum)
-     const char *name;
-     int regnum;
+declare_register (const char *name, unsigned int regnum)
 {
   const char *err;
   symbolS *sym;
 
-  sym = symbol_new (name, reg_section, regnum, &zero_address_frag);
+  sym = symbol_create (name, reg_section, regnum, &zero_address_frag);
 
-  err = hash_insert (md.reg_hash, S_GET_NAME (sym), (PTR) sym);
+  err = hash_insert (md.reg_hash, S_GET_NAME (sym), (void *) sym);
   if (err)
     as_fatal ("Inserting \"%s\" into register table failed: %s",
              name, err);
@@ -5405,24 +5276,22 @@ declare_register (name, regnum)
 }
 
 static void
-declare_register_set (prefix, num_regs, base_regnum)
-     const char *prefix;
-     int num_regs;
-     int base_regnum;
+declare_register_set (const char *prefix,
+                     unsigned int num_regs,
+                     unsigned int base_regnum)
 {
   char name[8];
-  int i;
+  unsigned int i;
 
   for (i = 0; i < num_regs; ++i)
     {
-      sprintf (name, "%s%u", prefix, i);
+      snprintf (name, sizeof (name), "%s%u", prefix, i);
       declare_register (name, base_regnum + i);
     }
 }
 
 static unsigned int
-operand_width (opnd)
-     enum ia64_opnd opnd;
+operand_width (enum ia64_opnd opnd)
 {
   const struct ia64_operand *odesc = &elf64_ia64_operands[opnd];
   unsigned int bits = 0;
@@ -5436,12 +5305,9 @@ operand_width (opnd)
 }
 
 static enum operand_match_result
-operand_match (idesc, index, e)
-     const struct ia64_opcode *idesc;
-     int index;
-     expressionS *e;
+operand_match (const struct ia64_opcode *idesc, int res_index, expressionS *e)
 {
-  enum ia64_opnd opnd = idesc->operands[index];
+  enum ia64_opnd opnd = idesc->operands[res_index];
   int bits, relocatable = 0;
   struct insn_fix *fix;
   bfd_signed_vma val;
@@ -5611,7 +5477,7 @@ operand_match (idesc, index, e)
     case IA64_OPND_CNT2a:
     case IA64_OPND_LEN4:
     case IA64_OPND_LEN6:
-      bits = operand_width (idesc->operands[index]);
+      bits = operand_width (idesc->operands[res_index]);
       if (e->X_op == O_constant)
        {
          if ((bfd_vma) (e->X_add_number - 1) < ((bfd_vma) 1 << bits))
@@ -5685,7 +5551,7 @@ operand_match (idesc, index, e)
                e->X_op = O_symbol;
            }
 
-         fix->opnd = idesc->operands[index];
+         fix->opnd = idesc->operands[res_index];
          fix->expr = *e;
          fix->is_pcrel = 0;
          ++CURR_SLOT.num_fixups;
@@ -5695,6 +5561,17 @@ operand_match (idesc, index, e)
        return OPERAND_MATCH;
       break;
 
+    case IA64_OPND_IMMU5b:
+      if (e->X_op == O_constant)
+       {
+         val = e->X_add_number;
+         if (val >= 32 && val <= 63)
+           return OPERAND_MATCH;
+         else
+           return OPERAND_OUT_OF_RANGE;
+       }
+      break;
+
     case IA64_OPND_CCNT5:
     case IA64_OPND_CNT5:
     case IA64_OPND_CNT6:
@@ -5709,7 +5586,7 @@ operand_match (idesc, index, e)
     case IA64_OPND_MBTYPE4:
     case IA64_OPND_MHTYPE8:
     case IA64_OPND_POS6:
-      bits = operand_width (idesc->operands[index]);
+      bits = operand_width (idesc->operands[res_index]);
       if (e->X_op == O_constant)
        {
          if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits))
@@ -5720,7 +5597,7 @@ operand_match (idesc, index, e)
       break;
 
     case IA64_OPND_IMMU9:
-      bits = operand_width (idesc->operands[index]);
+      bits = operand_width (idesc->operands[res_index]);
       if (e->X_op == O_constant)
        {
          if ((bfd_vma) e->X_add_number < ((bfd_vma) 1 << bits))
@@ -5796,14 +5673,14 @@ operand_match (idesc, index, e)
     case IA64_OPND_IMM8M1U8:
     case IA64_OPND_IMM9a:
     case IA64_OPND_IMM9b:
-      bits = operand_width (idesc->operands[index]);
+      bits = operand_width (idesc->operands[res_index]);
       if (relocatable && (e->X_op == O_symbol
                          || e->X_op == O_subtract
                          || e->X_op == O_pseudo_fixup))
        {
          fix = CURR_SLOT.fixup + CURR_SLOT.num_fixups;
 
-         if (idesc->operands[index] == IA64_OPND_IMM14)
+         if (idesc->operands[res_index] == IA64_OPND_IMM14)
            fix->code = BFD_RELOC_IA64_IMM14;
          else
            fix->code = BFD_RELOC_IA64_IMM22;
@@ -5815,7 +5692,7 @@ operand_match (idesc, index, e)
                e->X_op = O_symbol;
            }
 
-         fix->opnd = idesc->operands[index];
+         fix->opnd = idesc->operands[res_index];
          fix->expr = *e;
          fix->is_pcrel = 0;
          ++CURR_SLOT.num_fixups;
@@ -5921,7 +5798,7 @@ operand_match (idesc, index, e)
            abort ();
 
          fix->code = ia64_gen_real_reloc_type (e->X_op_symbol, fix->code);
-         fix->opnd = idesc->operands[index];
+         fix->opnd = idesc->operands[res_index];
          fix->expr = *e;
          fix->is_pcrel = 1;
          ++CURR_SLOT.num_fixups;
@@ -5937,10 +5814,10 @@ operand_match (idesc, index, e)
        case O_symbol:
          fix = CURR_SLOT.fixup + CURR_SLOT.num_fixups;
          /* There are no external relocs for TAG13/TAG13b fields, so we
-            create a dummy reloc.  This will not live past md_apply_fix3.  */
+            create a dummy reloc.  This will not live past md_apply_fix.  */
          fix->code = BFD_RELOC_UNUSED;
          fix->code = ia64_gen_real_reloc_type (e->X_op_symbol, fix->code);
-         fix->opnd = idesc->operands[index];
+         fix->opnd = idesc->operands[res_index];
          fix->expr = *e;
          fix->is_pcrel = 1;
          ++CURR_SLOT.num_fixups;
@@ -5954,7 +5831,7 @@ operand_match (idesc, index, e)
     case IA64_OPND_LDXMOV:
       fix = CURR_SLOT.fixup + CURR_SLOT.num_fixups;
       fix->code = BFD_RELOC_IA64_LDXMOV;
-      fix->opnd = idesc->operands[index];
+      fix->opnd = idesc->operands[res_index];
       fix->expr = *e;
       fix->is_pcrel = 0;
       ++CURR_SLOT.num_fixups;
@@ -5967,26 +5844,48 @@ operand_match (idesc, index, e)
 }
 
 static int
-parse_operand (e)
-     expressionS *e;
+parse_operand (expressionS *e, int more)
 {
   int sep = '\0';
 
   memset (e, 0, sizeof (*e));
   e->X_op = O_absent;
   SKIP_WHITESPACE ();
-  if (*input_line_pointer != '}')
-    expression (e);
-  sep = *input_line_pointer++;
+  expression (e);
+  sep = *input_line_pointer;
+  if (more && (sep == ',' || sep == more))
+    ++input_line_pointer;
+  return sep;
+}
+
+static int
+parse_operand_and_eval (expressionS *e, int more)
+{
+  int sep = parse_operand (e, more);
+  resolve_expression (e);
+  return sep;
+}
 
-  if (sep == '}')
+static int
+parse_operand_maybe_eval (expressionS *e, int more, enum ia64_opnd op)
+{
+  int sep = parse_operand (e, more);
+  switch (op)
     {
-      if (!md.manual_bundling)
-       as_warn ("Found '}' when manual bundling is off");
-      else
-       CURR_SLOT.manual_bundling_off = 1;
-      md.manual_bundling = 0;
-      sep = '\0';
+    case IA64_OPND_IMM14:
+    case IA64_OPND_IMM22:
+    case IA64_OPND_IMMU64:
+    case IA64_OPND_TGT25:
+    case IA64_OPND_TGT25b:
+    case IA64_OPND_TGT25c:
+    case IA64_OPND_TGT64:
+    case IA64_OPND_TAG13:
+    case IA64_OPND_TAG13b:
+    case IA64_OPND_LDXMOV:
+      break;
+    default:
+      resolve_expression (e);
+      break;
     }
   return sep;
 }
@@ -6007,8 +5906,7 @@ get_next_opcode (struct ia64_opcode *idesc)
    matches the specified operands, or NULL if no match is possible.  */
 
 static struct ia64_opcode *
-parse_operands (idesc)
-     struct ia64_opcode *idesc;
+parse_operands (struct ia64_opcode *idesc)
 {
   int i = 0, highest_unmatched_operand, num_operands = 0, num_outputs = 0;
   int error_pos, out_of_range_pos, curr_out_of_range_pos, sep = 0;
@@ -6020,7 +5918,7 @@ parse_operands (idesc)
   char *first_arg = 0, *end, *saved_input_pointer;
   unsigned int sof;
 
-  assert (strlen (idesc->name) <= 128);
+  gas_assert (strlen (idesc->name) <= 128);
 
   strcpy (mnemonic, idesc->name);
   if (idesc->operands[2] == IA64_OPND_SOF
@@ -6034,7 +5932,7 @@ parse_operands (idesc)
       end = strchr (input_line_pointer, '=');
       if (!end)
        {
-         as_bad ("Expected separator `='");
+         as_bad (_("Expected separator `='"));
          return 0;
        }
       input_line_pointer = end + 1;
@@ -6046,7 +5944,8 @@ parse_operands (idesc)
     {
       if (i < NELEMS (CURR_SLOT.opnd)) 
        {
-         sep = parse_operand (CURR_SLOT.opnd + i);
+         sep = parse_operand_maybe_eval (CURR_SLOT.opnd + i, '=',
+                                         idesc->operands[i]);
          if (CURR_SLOT.opnd[i].X_op == O_absent)
            break;
        }
@@ -6054,7 +5953,7 @@ parse_operands (idesc)
        {
          expressionS dummy;
 
-         sep = parse_operand (&dummy);
+         sep = parse_operand (&dummy, '=');
          if (dummy.X_op == O_absent)
            break;
        }
@@ -6067,48 +5966,53 @@ parse_operands (idesc)
       if (sep == '=')
        {
          if (num_outputs > 0)
-           as_bad ("Duplicate equal sign (=) in instruction");
+           as_bad (_("Duplicate equal sign (=) in instruction"));
          else
            num_outputs = i + 1;
        }
     }
   if (sep != '\0')
     {
-      as_bad ("Illegal operand separator `%c'", sep);
+      as_bad (_("Illegal operand separator `%c'"), sep);
       return 0;
     }
 
   if (idesc->operands[2] == IA64_OPND_SOF
       || idesc->operands[1] == IA64_OPND_SOF)
     {
-      /* map alloc r1=ar.pfs,i,l,o,r to alloc r1=ar.pfs,(i+l+o),(i+l),r */
+      /* Map alloc r1=ar.pfs,i,l,o,r to alloc r1=ar.pfs,(i+l+o),(i+l),r.
+        Note, however, that due to that mapping operand numbers in error
+        messages for any of the constant operands will not be correct.  */
       know (strcmp (idesc->name, "alloc") == 0);
-      i = (CURR_SLOT.opnd[1].X_op == O_register
-          && CURR_SLOT.opnd[1].X_add_number == REG_AR + AR_PFS) ? 2 : 1;
-      if (num_operands == i + 3 /* first_arg not included in this count! */
-         && CURR_SLOT.opnd[i].X_op == O_constant
-         && CURR_SLOT.opnd[i + 1].X_op == O_constant
-         && CURR_SLOT.opnd[i + 2].X_op == O_constant
-         && CURR_SLOT.opnd[i + 3].X_op == O_constant)
-       {
-         sof = set_regstack (CURR_SLOT.opnd[i].X_add_number,
-                             CURR_SLOT.opnd[i + 1].X_add_number,
-                             CURR_SLOT.opnd[i + 2].X_add_number,
-                             CURR_SLOT.opnd[i + 3].X_add_number);
-
-         /* now we can parse the first arg:  */
-         saved_input_pointer = input_line_pointer;
-         input_line_pointer = first_arg;
-         sep = parse_operand (CURR_SLOT.opnd + 0);
-         if (sep != '=')
-           --num_outputs;      /* force error */
-         input_line_pointer = saved_input_pointer;
-
-         CURR_SLOT.opnd[i].X_add_number = sof;
-         CURR_SLOT.opnd[i + 1].X_add_number
-           = sof - CURR_SLOT.opnd[i + 2].X_add_number;
-         CURR_SLOT.opnd[i + 2] = CURR_SLOT.opnd[i + 3];
-       }
+      /* The first operand hasn't been parsed/initialized, yet (but
+        num_operands intentionally doesn't account for that).  */
+      i = num_operands > 4 ? 2 : 1;
+#define FORCE_CONST(n) (CURR_SLOT.opnd[n].X_op == O_constant \
+                       ? CURR_SLOT.opnd[n].X_add_number \
+                       : 0)
+      sof = set_regstack (FORCE_CONST(i),
+                         FORCE_CONST(i + 1),
+                         FORCE_CONST(i + 2),
+                         FORCE_CONST(i + 3));
+#undef FORCE_CONST
+
+      /* now we can parse the first arg:  */
+      saved_input_pointer = input_line_pointer;
+      input_line_pointer = first_arg;
+      sep = parse_operand_maybe_eval (CURR_SLOT.opnd + 0, '=',
+                                     idesc->operands[0]);
+      if (sep != '=')
+       --num_outputs;  /* force error */
+      input_line_pointer = saved_input_pointer;
+
+      CURR_SLOT.opnd[i].X_add_number = sof;
+      if (CURR_SLOT.opnd[i + 1].X_op == O_constant
+         && CURR_SLOT.opnd[i + 2].X_op == O_constant)
+       CURR_SLOT.opnd[i + 1].X_add_number
+         = sof - CURR_SLOT.opnd[i + 2].X_add_number;
+      else
+       CURR_SLOT.opnd[i + 1].X_op = O_illegal;
+      CURR_SLOT.opnd[i + 2] = CURR_SLOT.opnd[i + 3];
     }
 
   highest_unmatched_operand = -4;
@@ -6184,15 +6088,15 @@ parse_operands (idesc)
   if (!idesc)
     {
       if (expected_operand)
-       as_bad ("Operand %u of `%s' should be %s",
+       as_bad (_("Operand %u of `%s' should be %s"),
                error_pos + 1, mnemonic,
                elf64_ia64_operands[expected_operand].desc);
       else if (highest_unmatched_operand < 0 && !(highest_unmatched_operand & 1))
-       as_bad ("Wrong number of output operands");
+       as_bad (_("Wrong number of output operands"));
       else if (highest_unmatched_operand < 0 && !(highest_unmatched_operand & 2))
-       as_bad ("Wrong number of input operands");
+       as_bad (_("Wrong number of input operands"));
       else
-       as_bad ("Operand mismatch");
+       as_bad (_("Operand mismatch"));
       return 0;
     }
 
@@ -6274,10 +6178,10 @@ parse_operands (idesc)
        case 0:
          break;
        default:
-         as_warn ("Invalid use of `%c%d' as output operand", reg_class, regno);
+         as_warn (_("Invalid use of `%c%d' as output operand"), reg_class, regno);
          break;
        case 'm':
-         as_warn ("Invalid use of `r%d' as base update address operand", regno);
+         as_warn (_("Invalid use of `r%d' as base update address operand"), regno);
          break;
        }
     }
@@ -6301,32 +6205,31 @@ parse_operands (idesc)
       else
        reg_class = 0;
       if (reg_class)
-       as_warn ("Invalid duplicate use of `%c%d'", reg_class, reg1);
+       as_warn (_("Invalid duplicate use of `%c%d'"), reg_class, reg1);
     }
   else if (((reg1 >= REG_FR && reg1 <= REG_FR + 31
             && reg2 >= REG_FR && reg2 <= REG_FR + 31)
            || (reg1 >= REG_FR + 32 && reg1 <= REG_FR + 127
             && reg2 >= REG_FR + 32 && reg2 <= REG_FR + 127))
           && ! ((reg1 ^ reg2) & 1))
-    as_warn ("Invalid simultaneous use of `f%d' and `f%d'",
+    as_warn (_("Invalid simultaneous use of `f%d' and `f%d'"),
             reg1 - REG_FR, reg2 - REG_FR);
   else if ((reg1 >= REG_FR && reg1 <= REG_FR + 31
            && reg2 >= REG_FR + 32 && reg2 <= REG_FR + 127)
           || (reg1 >= REG_FR + 32 && reg1 <= REG_FR + 127
            && reg2 >= REG_FR && reg2 <= REG_FR + 31))
-    as_warn ("Dangerous simultaneous use of `f%d' and `f%d'",
+    as_warn (_("Dangerous simultaneous use of `f%d' and `f%d'"),
             reg1 - REG_FR, reg2 - REG_FR);
   return idesc;
 }
 
 static void
-build_insn (slot, insnp)
-     struct slot *slot;
-     bfd_vma *insnp;
+build_insn (struct slot *slot, bfd_vma *insnp)
 {
   const struct ia64_operand *odesc, *o2desc;
   struct ia64_opcode *idesc = slot->idesc;
-  bfd_signed_vma insn, val;
+  bfd_vma insn;
+  bfd_signed_vma val;
   const char *err;
   int i;
 
@@ -6341,7 +6244,7 @@ build_insn (slot, insnp)
       else if (slot->opnd[i].X_op == O_big)
        {
          /* This must be the value 0x10000000000000000.  */
-         assert (idesc->operands[i] == IA64_OPND_IMM8M1U8);
+         gas_assert (idesc->operands[i] == IA64_OPND_IMM8M1U8);
          val = 0;
        }
       else
@@ -6422,7 +6325,7 @@ build_insn (slot, insnp)
       err = (*odesc->insert) (odesc, val, &insn);
       if (err)
        as_bad_where (slot->src_file, slot->src_line,
-                     "Bad operand value: %s", err);
+                     _("Bad operand value: %s"), err);
       if (idesc->flags & IA64_OPCODE_PSEUDO)
        {
          if ((idesc->flags & IA64_OPCODE_F2_EQ_F3)
@@ -6444,19 +6347,19 @@ build_insn (slot, insnp)
 }
 
 static void
-emit_one_bundle ()
+emit_one_bundle (void)
 {
   int manual_bundling_off = 0, manual_bundling = 0;
   enum ia64_unit required_unit, insn_unit = 0;
   enum ia64_insn_type type[3], insn_type;
-  unsigned int template, orig_template;
+  unsigned int template_val, orig_template;
   bfd_vma insn[3] = { -1, -1, -1 };
   struct ia64_opcode *idesc;
   int end_of_insn_group = 0, user_template = -1;
-  int n, i, j, first, curr;
-  unw_rec_list *ptr, *last_ptr, *end_ptr;
+  int n, i, j, first, curr, last_slot;
   bfd_vma t0 = 0, t1 = 0;
   struct label_fix *lfix;
+  bfd_boolean mark_label;
   struct insn_fix *ifix;
   char mnemonic[16];
   fixS *fix;
@@ -6464,14 +6367,14 @@ emit_one_bundle ()
   int addr_mod;
 
   first = (md.curr_slot + NUM_SLOTS - md.num_slots_in_use) % NUM_SLOTS;
-  know (first >= 0 & first < NUM_SLOTS);
+  know (first >= 0 && first < NUM_SLOTS);
   n = MIN (3, md.num_slots_in_use);
 
   /* Determine template: user user_template if specified, best match
      otherwise:  */
 
   if (md.slot[first].user_template >= 0)
-    user_template = template = md.slot[first].user_template;
+    user_template = template_val = md.slot[first].user_template;
   else
     {
       /* Auto select appropriate template.  */
@@ -6484,12 +6387,12 @@ emit_one_bundle ()
          type[i] = md.slot[curr].idesc->type;
          curr = (curr + 1) % NUM_SLOTS;
        }
-      template = best_template[type[0]][type[1]][type[2]];
+      template_val = best_template[type[0]][type[1]][type[2]];
     }
 
   /* initialize instructions with appropriate nops:  */
   for (i = 0; i < 3; ++i)
-    insn[i] = nop[ia64_templ_desc[template].exec_unit[i]];
+    insn[i] = nop[ia64_templ_desc[template_val].exec_unit[i]];
 
   f = frag_more (16);
 
@@ -6505,10 +6408,13 @@ emit_one_bundle ()
   curr = first;
   idesc = md.slot[curr].idesc;
   end_of_insn_group = 0;
+  last_slot = -1;
   for (i = 0; i < 3 && md.num_slots_in_use > 0; ++i)
     {
       /* If we have unwind records, we may need to update some now.  */
-      ptr = md.slot[curr].unwind_record;
+      unw_rec_list *ptr = md.slot[curr].unwind_record;
+      unw_rec_list *end_ptr = NULL;
+
       if (ptr)
        {
          /* Find the last prologue/body record in the list for the current
@@ -6518,9 +6424,11 @@ emit_one_bundle ()
             issued.  This matters because there may have been nops emitted
             meanwhile.  Any non-prologue non-body record followed by a
             prologue/body record must also refer to the current point.  */
-         last_ptr = NULL;
-         end_ptr = md.slot[(curr + 1) % NUM_SLOTS].unwind_record;
-         for (; ptr != end_ptr; ptr = ptr->next)
+         unw_rec_list *last_ptr;
+
+         for (j = 1; end_ptr == NULL && j < md.num_slots_in_use; ++j)
+           end_ptr = md.slot[(curr + j) % NUM_SLOTS].unwind_record;
+         for (last_ptr = NULL; ptr != end_ptr; ptr = ptr->next)
            if (ptr->r.type == prologue || ptr->r.type == prologue_gr
                || ptr->r.type == body)
              last_ptr = ptr;
@@ -6550,12 +6458,17 @@ emit_one_bundle ()
          break; /* Need to start a new bundle.  */
        }
 
+      /* If this instruction specifies a template, then it must be the first
+        instruction of a bundle.  */
+      if (curr != first && md.slot[curr].user_template >= 0)
+       break;
+
       if (idesc->flags & IA64_OPCODE_SLOT2)
        {
          if (manual_bundling && !manual_bundling_off)
            {
              as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                           "`%s' must be last in bundle", idesc->name);
+                           _("`%s' must be last in bundle"), idesc->name);
              if (i < 2)
                manual_bundling = -1; /* Suppress meaningless post-loop errors.  */
            }
@@ -6573,7 +6486,7 @@ emit_one_bundle ()
             MBB, BBB, MMB, and MFB.  We don't handle anything other
             than M and B slots because these are the only kind of
             instructions that can have the IA64_OPCODE_LAST bit set.  */
-         required_template = template;
+         required_template = template_val;
          switch (idesc->type)
            {
            case IA64_TYPE_M:
@@ -6587,8 +6500,8 @@ emit_one_bundle ()
 
            default:
              as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                           "Internal error: don't know how to force %s to end"
-                           "of instruction group", idesc->name);
+                           _("Internal error: don't know how to force %s to end of instruction group"),
+                           idesc->name);
              required_slot = i;
              break;
            }
@@ -6597,10 +6510,10 @@ emit_one_bundle ()
                  || (required_slot == 2 && !manual_bundling_off)
                  || (user_template >= 0
                      /* Changing from MMI to M;MI is OK.  */
-                     && (template ^ required_template) > 1)))
+                     && (template_val ^ required_template) > 1)))
            {
              as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                           "`%s' must be last in instruction group",
+                           _("`%s' must be last in instruction group"),
                            idesc->name);
              if (i < 2 && required_slot == 2 && !manual_bundling_off)
                manual_bundling = -1; /* Suppress meaningless post-loop errors.  */
@@ -6610,7 +6523,7 @@ emit_one_bundle ()
            break;
 
          i = required_slot;
-         if (required_template != template)
+         if (required_template != template_val)
            {
              /* If we switch the template, we need to reset the NOPs
                 after slot i.  The slot-types of the instructions ahead
@@ -6618,15 +6531,19 @@ emit_one_bundle ()
                 changing NOPs in front of this slot.  */
              for (j = i; j < 3; ++j)
                insn[j] = nop[ia64_templ_desc[required_template].exec_unit[j]];
+
+             /* We just picked a template that includes the stop bit in the
+                middle, so we don't need another one emitted later.  */
+             md.slot[curr].end_of_insn_group = 0;
            }
-         template = required_template;
+         template_val = required_template;
        }
       if (curr != first && md.slot[curr].label_fixups)
        {
          if (manual_bundling)
            {
              as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                         "Label must be first in a bundle");
+                           _("Label must be first in a bundle"));
              manual_bundling = -1; /* Suppress meaningless post-loop errors.  */
            }
          /* This insn must go into the first slot of a bundle.  */
@@ -6639,18 +6556,18 @@ emit_one_bundle ()
             bundle.  See if we can switch to an other template with
             an appropriate boundary.  */
 
-         orig_template = template;
+         orig_template = template_val;
          if (i == 1 && (user_template == 4
                         || (user_template < 0
-                            && (ia64_templ_desc[template].exec_unit[0]
+                            && (ia64_templ_desc[template_val].exec_unit[0]
                                 == IA64_UNIT_M))))
            {
-             template = 5;
+             template_val = 5;
              end_of_insn_group = 0;
            }
          else if (i == 2 && (user_template == 0
                              || (user_template < 0
-                                 && (ia64_templ_desc[template].exec_unit[1]
+                                 && (ia64_templ_desc[template_val].exec_unit[1]
                                      == IA64_UNIT_I)))
                   /* This test makes sure we don't switch the template if
                      the next instruction is one that needs to be first in
@@ -6663,7 +6580,7 @@ emit_one_bundle ()
                      first in the group! --davidm 99/12/16  */
                   && (idesc->flags & IA64_OPCODE_FIRST) == 0)
            {
-             template = 1;
+             template_val = 1;
              end_of_insn_group = 0;
            }
          else if (i == 1
@@ -6675,15 +6592,15 @@ emit_one_bundle ()
            /* can't fit this insn */
            break;
 
-         if (template != orig_template)
+         if (template_val != orig_template)
            /* if we switch the template, we need to reset the NOPs
               after slot i.  The slot-types of the instructions ahead
               of i never change, so we don't need to worry about
               changing NOPs in front of this slot.  */
            for (j = i; j < 3; ++j)
-             insn[j] = nop[ia64_templ_desc[template].exec_unit[j]];
+             insn[j] = nop[ia64_templ_desc[template_val].exec_unit[j]];
        }
-      required_unit = ia64_templ_desc[template].exec_unit[i];
+      required_unit = ia64_templ_desc[template_val].exec_unit[i];
 
       /* resolve dynamic opcodes such as "break", "hint", and "nop":  */
       if (idesc->type == IA64_TYPE_DYN)
@@ -6691,21 +6608,47 @@ emit_one_bundle ()
          enum ia64_opnd opnd1, opnd2;
 
          if ((strcmp (idesc->name, "nop") == 0)
-             || (strcmp (idesc->name, "hint") == 0)
              || (strcmp (idesc->name, "break") == 0))
            insn_unit = required_unit;
+         else if (strcmp (idesc->name, "hint") == 0)
+           {
+             insn_unit = required_unit;
+             if (required_unit == IA64_UNIT_B)
+               {
+                 switch (md.hint_b)
+                   {
+                   case hint_b_ok:
+                     break;
+                   case hint_b_warning:
+                     as_warn (_("hint in B unit may be treated as nop"));
+                     break;
+                   case hint_b_error:
+                     /* When manual bundling is off and there is no
+                        user template, we choose a different unit so
+                        that hint won't go into the current slot. We
+                        will fill the current bundle with nops and
+                        try to put hint into the next bundle.  */
+                     if (!manual_bundling && user_template < 0)
+                       insn_unit = IA64_UNIT_I;
+                     else
+                       as_bad (_("hint in B unit can't be used"));
+                     break;
+                   }
+               }
+           }
          else if (strcmp (idesc->name, "chk.s") == 0
              || strcmp (idesc->name, "mov") == 0)
            {
              insn_unit = IA64_UNIT_M;
              if (required_unit == IA64_UNIT_I
-                 || (required_unit == IA64_UNIT_F && template == 6))
+                 || (required_unit == IA64_UNIT_F && template_val == 6))
                insn_unit = IA64_UNIT_I;
            }
          else
-           as_fatal ("emit_one_bundle: unexpected dynamic op");
+           as_fatal (_("emit_one_bundle: unexpected dynamic op"));
 
-         sprintf (mnemonic, "%s.%c", idesc->name, "?imbfxx"[insn_unit]);
+         snprintf (mnemonic, sizeof (mnemonic), "%s.%c",
+                   idesc->name, "?imbfxx"[insn_unit]);
          opnd1 = idesc->operands[0];
          opnd2 = idesc->operands[1];
          ia64_free_opcode (idesc);
@@ -6740,33 +6683,32 @@ emit_one_bundle ()
        }
 
       if (insn_unit != required_unit)
+       continue;               /* Try next slot.  */
+
+      /* Now is a good time to fix up the labels for this insn.  */
+      mark_label = FALSE;
+      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
        {
-         if (required_unit == IA64_UNIT_L
-             && insn_unit == IA64_UNIT_I
-             && !(idesc->flags & IA64_OPCODE_X_IN_MLX))
-           {
-             /* we got ourselves an MLX template but the current
-                instruction isn't an X-unit, or an I-unit instruction
-                that can go into the X slot of an MLX template.  Duh.  */
-             if (md.num_slots_in_use >= NUM_SLOTS)
-               {
-                 as_bad_where (md.slot[curr].src_file,
-                               md.slot[curr].src_line,
-                               "`%s' can't go in X slot of "
-                               "MLX template", idesc->name);
-                 /* drop this insn so we don't livelock:  */
-                 --md.num_slots_in_use;
-               }
-             break;
-           }
-         continue;             /* try next slot */
+         S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
+         symbol_set_frag (lfix->sym, frag_now);
+         mark_label |= lfix->dw2_mark_labels;
+       }
+      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
+       {
+         S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
+         symbol_set_frag (lfix->sym, frag_now);
        }
 
-      if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen)
+      if (debug_type == DEBUG_DWARF2
+         || md.slot[curr].loc_directive_seen
+         || mark_label)
        {
          bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i;
 
          md.slot[curr].loc_directive_seen = 0;
+         if (mark_label)
+           md.slot[curr].debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+
          dwarf2_gen_line_info (addr, &md.slot[curr].debug_line);
        }
 
@@ -6778,7 +6720,6 @@ emit_one_bundle ()
          /* Set slot numbers for all remaining unwind records belonging to the
             current insn.  There can not be any prologue/body unwind records
             here.  */
-         end_ptr = md.slot[(curr + 1) % NUM_SLOTS].unwind_record;
          for (; ptr != end_ptr; ptr = ptr->next)
            {
              ptr->slot_number = (unsigned long) f + i;
@@ -6794,19 +6735,7 @@ emit_one_bundle ()
          ++i;
        }
       --md.num_slots_in_use;
-
-      /* now is a good time to fix up the labels for this insn:  */
-      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
-       {
-         S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
-         symbol_set_frag (lfix->sym, frag_now);
-       }
-      /* and fix up the tags also.  */
-      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
-       {
-         S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
-         symbol_set_frag (lfix->sym, frag_now);
-       }
+      last_slot = i;
 
       for (j = 0; j < md.slot[curr].num_fixups; ++j)
        {
@@ -6814,7 +6743,6 @@ emit_one_bundle ()
          fix = fix_new_exp (frag_now, frag_now_fix () - 16 + i, 8,
                             &ifix->expr, ifix->is_pcrel, ifix->code);
          fix->tc_fix_data.opnd = ifix->opnd;
-         fix->fx_plt = (fix->fx_r_type == BFD_RELOC_IA64_PLTOFF22);
          fix->fx_file = md.slot[curr].src_file;
          fix->fx_line = md.slot[curr].src_line;
        }
@@ -6834,38 +6762,59 @@ emit_one_bundle ()
       curr = (curr + 1) % NUM_SLOTS;
       idesc = md.slot[curr].idesc;
     }
-  if (manual_bundling > 0)
+
+  /* A user template was specified, but the first following instruction did
+     not fit.  This can happen with or without manual bundling.  */
+  if (md.num_slots_in_use > 0 && last_slot < 0)
+    {
+      as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                   _("`%s' does not fit into %s template"),
+                   idesc->name, ia64_templ_desc[template_val].name);
+      /* Drop first insn so we don't livelock.  */
+      --md.num_slots_in_use;
+      know (curr == first);
+      ia64_free_opcode (md.slot[curr].idesc);
+      memset (md.slot + curr, 0, sizeof (md.slot[curr]));
+      md.slot[curr].user_template = -1;
+    }
+  else if (manual_bundling > 0)
     {
       if (md.num_slots_in_use > 0)
        {
-         as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                       "`%s' does not fit into %s template",
-                       idesc->name, ia64_templ_desc[template].name);
-         --md.num_slots_in_use;
+         if (last_slot >= 2)
+           as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                         _("`%s' does not fit into bundle"), idesc->name);
+         else
+           {
+             const char *where;
+
+             if (template_val == 2)
+               where = "X slot";
+             else if (last_slot == 0)
+               where = "slots 2 or 3";
+             else
+               where = "slot 3";
+             as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                           _("`%s' can't go in %s of %s template"),
+                           idesc->name, where, ia64_templ_desc[template_val].name);
+           }
        }
       else
        as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                     "Missing '}' at end of file");
+                     _("Missing '}' at end of file"));
     }
+       
   know (md.num_slots_in_use < NUM_SLOTS);
 
-  t0 = end_of_insn_group | (template << 1) | (insn[0] << 5) | (insn[1] << 46);
+  t0 = end_of_insn_group | (template_val << 1) | (insn[0] << 5) | (insn[1] << 46);
   t1 = ((insn[1] >> 18) & 0x7fffff) | (insn[2] << 23);
 
   number_to_chars_littleendian (f + 0, t0, 8);
   number_to_chars_littleendian (f + 8, t1, 8);
-
-  if (unwind.list)
-    {
-      unwind.list->next_slot_number = (unsigned long) f + 16;
-      unwind.list->next_slot_frag = frag_now;
-    }
 }
 
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg;
+md_parse_option (int c, char *arg)
 {
 
   switch (c)
@@ -6894,11 +6843,33 @@ md_parse_option (c, arg)
        }
       else if (strncmp (arg, "unwind-check=", 13) == 0)
        {
-         arg += 13;
-         if (strcmp (arg, "warning") == 0)
-           md.unwind_check = unwind_check_warning;
+         arg += 13;
+         if (strcmp (arg, "warning") == 0)
+           md.unwind_check = unwind_check_warning;
+         else if (strcmp (arg, "error") == 0)
+           md.unwind_check = unwind_check_error;
+         else
+           return 0;
+       }
+      else if (strncmp (arg, "hint.b=", 7) == 0)
+       {
+         arg += 7;
+         if (strcmp (arg, "ok") == 0)
+           md.hint_b = hint_b_ok;
+         else if (strcmp (arg, "warning") == 0)
+           md.hint_b = hint_b_warning;
          else if (strcmp (arg, "error") == 0)
-           md.unwind_check = unwind_check_error;
+           md.hint_b = hint_b_error;
+         else
+           return 0;
+       }
+      else if (strncmp (arg, "tune=", 5) == 0)
+       {
+         arg += 5;
+         if (strcmp (arg, "itanium1") == 0)
+           md.tune = itanium1;
+         else if (strcmp (arg, "itanium2") == 0)
+           md.tune = itanium2;
          else
            return 0;
        }
@@ -7002,8 +6973,7 @@ md_parse_option (c, arg)
 }
 
 void
-md_show_usage (stream)
-     FILE *stream;
+md_show_usage (FILE *stream)
 {
   fputs (_("\
 IA-64 options:\n\
@@ -7014,8 +6984,12 @@ IA-64 options:\n\
                          EF_IA_64_NOFUNCDESC_CONS_GP)\n\
   -milp32|-milp64|-mlp64|-mp64 select data model (default -mlp64)\n\
   -mle | -mbe            select little- or big-endian byte order (default -mle)\n\
+  -mtune=[itanium1|itanium2]\n\
+                         tune for a specific CPU (default -mtune=itanium2)\n\
   -munwind-check=[warning|error]\n\
                          unwind directive check (default -munwind-check=warning)\n\
+  -mhint.b=[ok|warning|error]\n\
+                         hint.b check (default -mhint.b=error)\n\
   -x | -xexplicit        turn on dependency violation checking\n\
   -xauto                 automagically remove dependency violations (default)\n\
   -xnone                 turn off dependency violation checking\n\
@@ -7028,7 +7002,7 @@ IA-64 options:\n\
 }
 
 void
-ia64_after_parse_args ()
+ia64_after_parse_args (void)
 {
   if (debug_type == DEBUG_STABS)
     as_fatal (_("--gstabs is not supported for ia64"));
@@ -7059,26 +7033,46 @@ match (int templ, int type, int slot)
   return result;
 }
 
-/* Add a bit of extra goodness if a nop of type F or B would fit
-   in TEMPL at SLOT.  */
+/* For Itanium 1, add a bit of extra goodness if a nop of type F or B would fit
+   in TEMPL at SLOT.  For Itanium 2, add a bit of extra goodness if a nop of
+   type M or I would fit in TEMPL at SLOT.  */
 
 static inline int
 extra_goodness (int templ, int slot)
 {
-  if (slot == 1 && match (templ, IA64_TYPE_F, slot))
-    return 2;
-  if (slot == 2 && match (templ, IA64_TYPE_B, slot))
-    return 1;
-  return 0;
+  switch (md.tune)
+    {
+    case itanium1:
+      if (slot == 1 && match (templ, IA64_TYPE_F, slot))
+       return 2;
+      else if (slot == 2 && match (templ, IA64_TYPE_B, slot))
+       return 1;
+      else
+       return 0;
+      break;
+    case itanium2:
+      if (match (templ, IA64_TYPE_M, slot)
+         || match (templ, IA64_TYPE_I, slot))
+       /* Favor M- and I-unit NOPs.  We definitely want to avoid
+          F-unit and B-unit may cause split-issue or less-than-optimal
+          branch-prediction.  */
+       return 2;
+      else
+       return 0;
+      break;
+    default:
+      abort ();
+      return 0;
+    }
 }
 
 /* This function is called once, at assembler startup time.  It sets
    up all the tables, etc. that the MD part of the assembler will need
    that can be determined before arguments are parsed.  */
 void
-md_begin ()
+md_begin (void)
 {
-  int i, j, k, t, total, ar_base, cr_base, goodness, best, regnum, ok;
+  int i, j, k, t, goodness, best, ok;
   const char *err;
   char name[8];
 
@@ -7164,11 +7158,17 @@ md_begin ()
     symbol_new (".<iplt>", undefined_section, FUNC_IPLT_RELOC,
                &zero_address_frag);
 
+ if (md.tune != itanium1)
+   {
+     /* Convert MFI NOPs bundles into MMI NOPs bundles.  */
+     le_nop[0] = 0x8;
+     le_nop_stop[0] = 0x9;
+   }
+
   /* Compute the table of best templates.  We compute goodness as a
-     base 4 value, in which each match counts for 3, each F counts
-     for 2, each B counts for 1.  This should maximize the number of
-     F and B nops in the chosen bundles, which is good because these
-     pipelines are least likely to be overcommitted.  */
+     base 4 value, in which each match counts for 3.  Match-failures
+     result in NOPs and we use extra_goodness() to pick the execution
+     units that are best suited for issuing the NOP.  */
   for (i = 0; i < IA64_NUM_TYPES; ++i)
     for (j = 0; j < IA64_NUM_TYPES; ++j)
       for (k = 0; k < IA64_NUM_TYPES; ++k)
@@ -7181,7 +7181,7 @@ md_begin ()
                {
                  if (match (t, j, 1))
                    {
-                     if (match (t, k, 2))
+                     if ((t == 2 && j == IA64_TYPE_X) || match (t, k, 2))
                        goodness = 3 + 3 + 3;
                      else
                        goodness = 3 + 3 + extra_goodness (t, 2);
@@ -7197,7 +7197,7 @@ md_begin ()
                }
              else if (match (t, i, 1))
                {
-                 if (match (t, j, 2))
+                 if ((t == 2 && i == IA64_TYPE_X) || match (t, j, 2))
                    goodness = 3 + 3;
                  else
                    goodness = 3 + extra_goodness (t, 2);
@@ -7213,6 +7213,21 @@ md_begin ()
            }
        }
 
+#ifdef DEBUG_TEMPLATES
+  /* For debugging changes to the best_template calculations.  We don't care
+     about combinations with invalid instructions, so start the loops at 1.  */
+  for (i = 0; i < IA64_NUM_TYPES; ++i)
+    for (j = 0; j < IA64_NUM_TYPES; ++j)
+      for (k = 0; k < IA64_NUM_TYPES; ++k)
+       {
+         char type_letter[IA64_NUM_TYPES] = { 'n', 'a', 'i', 'm', 'b', 'f',
+                                              'x', 'd' };
+         fprintf (stderr, "%c%c%c %s\n", type_letter[i], type_letter[j],
+                  type_letter[k],
+                  ia64_templ_desc[best_template[i][j][k]].name);
+       }
+#endif
+
   for (i = 0; i < NUM_SLOTS; ++i)
     md.slot[i].user_template = -1;
 
@@ -7222,7 +7237,7 @@ md_begin ()
       err = hash_insert (md.pseudo_hash, pseudo_opcode[i].name,
                         (void *) (pseudo_opcode + i));
       if (err)
-       as_fatal ("ia64.md_begin: can't hash `%s': %s",
+       as_fatal (_("ia64.md_begin: can't hash `%s': %s"),
                  pseudo_opcode[i].name, err);
     }
 
@@ -7232,97 +7247,58 @@ md_begin ()
   md.entry_hash = hash_new ();
 
   /* general registers:  */
-
-  total = 128;
-  for (i = 0; i < total; ++i)
-    {
-      sprintf (name, "r%d", i - REG_GR);
-      md.regsym[i] = declare_register (name, i);
-    }
+  declare_register_set ("r", 128, REG_GR);
+  declare_register ("gp", REG_GR +  1);
+  declare_register ("sp", REG_GR + 12);
+  declare_register ("tp", REG_GR + 13);
+  declare_register_set ("ret", 4, REG_GR + 8);
 
   /* floating point registers:  */
-  total += 128;
-  for (; i < total; ++i)
-    {
-      sprintf (name, "f%d", i - REG_FR);
-      md.regsym[i] = declare_register (name, i);
-    }
-
-  /* application registers:  */
-  total += 128;
-  ar_base = i;
-  for (; i < total; ++i)
-    {
-      sprintf (name, "ar%d", i - REG_AR);
-      md.regsym[i] = declare_register (name, i);
-    }
+  declare_register_set ("f", 128, REG_FR);
+  declare_register_set ("farg", 8, REG_FR + 8);
+  declare_register_set ("fret", 8, REG_FR + 8);
 
-  /* control registers:  */
-  total += 128;
-  cr_base = i;
-  for (; i < total; ++i)
-    {
-      sprintf (name, "cr%d", i - REG_CR);
-      md.regsym[i] = declare_register (name, i);
-    }
+  /* branch registers:  */
+  declare_register_set ("b", 8, REG_BR);
+  declare_register ("rp", REG_BR + 0);
 
   /* predicate registers:  */
-  total += 64;
-  for (; i < total; ++i)
-    {
-      sprintf (name, "p%d", i - REG_P);
-      md.regsym[i] = declare_register (name, i);
-    }
+  declare_register_set ("p", 64, REG_P);
+  declare_register ("pr", REG_PR);
+  declare_register ("pr.rot", REG_PR_ROT);
 
-  /* branch registers:  */
-  total += 8;
-  for (; i < total; ++i)
-    {
-      sprintf (name, "b%d", i - REG_BR);
-      md.regsym[i] = declare_register (name, i);
-    }
+  /* application registers:  */
+  declare_register_set ("ar", 128, REG_AR);
+  for (i = 0; i < NELEMS (ar); ++i)
+    declare_register (ar[i].name, REG_AR + ar[i].regnum);
 
-  md.regsym[REG_IP] = declare_register ("ip", REG_IP);
-  md.regsym[REG_CFM] = declare_register ("cfm", REG_CFM);
-  md.regsym[REG_PR] = declare_register ("pr", REG_PR);
-  md.regsym[REG_PR_ROT] = declare_register ("pr.rot", REG_PR_ROT);
-  md.regsym[REG_PSR] = declare_register ("psr", REG_PSR);
-  md.regsym[REG_PSR_L] = declare_register ("psr.l", REG_PSR_L);
-  md.regsym[REG_PSR_UM] = declare_register ("psr.um", REG_PSR_UM);
+  /* control registers:  */
+  declare_register_set ("cr", 128, REG_CR);
+  for (i = 0; i < NELEMS (cr); ++i)
+    declare_register (cr[i].name, REG_CR + cr[i].regnum);
+
+  declare_register ("ip", REG_IP);
+  declare_register ("cfm", REG_CFM);
+  declare_register ("psr", REG_PSR);
+  declare_register ("psr.l", REG_PSR_L);
+  declare_register ("psr.um", REG_PSR_UM);
 
   for (i = 0; i < NELEMS (indirect_reg); ++i)
     {
-      regnum = indirect_reg[i].regnum;
-      md.regsym[regnum] = declare_register (indirect_reg[i].name, regnum);
-    }
-
-  /* define synonyms for application registers:  */
-  for (i = REG_AR; i < REG_AR + NELEMS (ar); ++i)
-    md.regsym[i] = declare_register (ar[i - REG_AR].name,
-                                    REG_AR + ar[i - REG_AR].regnum);
+      unsigned int regnum = indirect_reg[i].regnum;
 
-  /* define synonyms for control registers:  */
-  for (i = REG_CR; i < REG_CR + NELEMS (cr); ++i)
-    md.regsym[i] = declare_register (cr[i - REG_CR].name,
-                                    REG_CR + cr[i - REG_CR].regnum);
-
-  declare_register ("gp", REG_GR +  1);
-  declare_register ("sp", REG_GR + 12);
-  declare_register ("rp", REG_BR +  0);
+      md.indregsym[regnum - IND_CPUID] = declare_register (indirect_reg[i].name, regnum);
+    }
 
   /* pseudo-registers used to specify unwind info:  */
   declare_register ("psp", REG_PSP);
 
-  declare_register_set ("ret", 4, REG_GR + 8);
-  declare_register_set ("farg", 8, REG_FR + 8);
-  declare_register_set ("fret", 8, REG_FR + 8);
-
   for (i = 0; i < NELEMS (const_bits); ++i)
     {
       err = hash_insert (md.const_hash, const_bits[i].name,
-                        (PTR) (const_bits + i));
+                        (void *) (const_bits + i));
       if (err)
-       as_fatal ("Inserting \"%s\" into constant hash table failed: %s",
+       as_fatal (_("Inserting \"%s\" into constant hash table failed: %s"),
                  name, err);
     }
 
@@ -7360,20 +7336,23 @@ md_begin ()
    options in md based on command line options.  */
 
 void
-ia64_init (argc, argv)
-     int argc ATTRIBUTE_UNUSED;
-     char **argv ATTRIBUTE_UNUSED;
+ia64_init (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
 {
   md.flags = MD_FLAGS_DEFAULT;
+#ifndef TE_VMS
+  /* Don't turn on dependency checking for VMS, doesn't work.  */
   md.detect_dv = 1;
+#endif
   /* FIXME: We should change it to unwind_check_error someday.  */
   md.unwind_check = unwind_check_warning;
+  md.hint_b = hint_b_error;
+  md.tune = itanium2;
 }
 
 /* Return a string for the target object file format.  */
 
 const char *
-ia64_target_format ()
+ia64_target_format (void)
 {
   if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
     {
@@ -7399,8 +7378,13 @@ ia64_target_format ()
       else
        {
          if (md.flags & EF_IA_64_ABI64)
-#ifdef TE_AIX50
+#if defined (TE_AIX50)
            return "elf64-ia64-aix-little";
+#elif defined (TE_VMS)
+         {
+           md.flags |= EF_IA_64_ARCHVER_1;
+           return "elf64-ia64-vms";
+         }
 #else
            return "elf64-ia64-little";
 #endif
@@ -7417,7 +7401,7 @@ ia64_target_format ()
 }
 
 void
-ia64_end_of_source ()
+ia64_end_of_source (void)
 {
   /* terminate insn group upon reaching end of file:  */
   insn_group_break (1, 0, 0);
@@ -7431,10 +7415,19 @@ ia64_end_of_source ()
 }
 
 void
-ia64_start_line ()
+ia64_start_line (void)
 {
+  static int first;
+
+  if (!first) {
+    /* Make sure we don't reference input_line_pointer[-1] when that's
+       not valid.  */
+    first = 1;
+    return;
+  }
+
   if (md.qp.X_op == O_register)
-    as_bad ("qualifying predicate not followed by instruction");
+    as_bad (_("qualifying predicate not followed by instruction"));
   md.qp.X_op = O_absent;
 
   if (ignore_input ())
@@ -7455,40 +7448,10 @@ ia64_start_line ()
       else
        insn_group_break (1, 0, 0);
     }
-}
-
-/* This is a hook for ia64_frob_label, so that it can distinguish tags from
-   labels.  */
-static int defining_tag = 0;
-
-int
-ia64_unrecognized_line (ch)
-     int ch;
-{
-  switch (ch)
+  else if (input_line_pointer[-1] == '{')
     {
-    case '(':
-      expression (&md.qp);
-      if (*input_line_pointer++ != ')')
-       {
-         as_bad ("Expected ')'");
-         return 0;
-       }
-      if (md.qp.X_op != O_register)
-       {
-         as_bad ("Qualifying predicate expected");
-         return 0;
-       }
-      if (md.qp.X_add_number < REG_P || md.qp.X_add_number >= REG_P + 64)
-       {
-         as_bad ("Predicate register expected");
-         return 0;
-       }
-      return 1;
-
-    case '{':
       if (md.manual_bundling)
-       as_warn ("Found '{' when manual bundling is already turned on");
+       as_warn (_("Found '{' when manual bundling is already turned on"));
       else
        CURR_SLOT.manual_bundling_on = 1;
       md.manual_bundling = 1;
@@ -7503,11 +7466,11 @@ ia64_unrecognized_line (ch)
          else
            as_warn (_("Found '{' after explicit switch to automatic mode"));
        }
-      return 1;
-
-    case '}':
+    }
+  else if (input_line_pointer[-1] == '}')
+    {
       if (!md.manual_bundling)
-       as_warn ("Found '}' when manual bundling is off");
+       as_warn (_("Found '}' when manual bundling is off"));
       else
        PREV_SLOT.manual_bundling_off = 1;
       md.manual_bundling = 0;
@@ -7518,17 +7481,35 @@ ia64_unrecognized_line (ch)
          && !md.mode_explicitly_set
          && !md.default_explicit_mode)
        dot_dv_mode ('A');
+    }
+}
 
-      /* Allow '{' to follow on the same line.  We also allow ";;", but that
-        happens automatically because ';' is an end of line marker.  */
-      SKIP_WHITESPACE ();
-      if (input_line_pointer[0] == '{')
+/* This is a hook for ia64_frob_label, so that it can distinguish tags from
+   labels.  */
+static int defining_tag = 0;
+
+int
+ia64_unrecognized_line (int ch)
+{
+  switch (ch)
+    {
+    case '(':
+      expression_and_evaluate (&md.qp);
+      if (*input_line_pointer++ != ')')
        {
-         input_line_pointer++;
-         return ia64_unrecognized_line ('{');
+         as_bad (_("Expected ')'"));
+         return 0;
+       }
+      if (md.qp.X_op != O_register)
+       {
+         as_bad (_("Qualifying predicate expected"));
+         return 0;
+       }
+      if (md.qp.X_add_number < REG_P || md.qp.X_add_number >= REG_P + 64)
+       {
+         as_bad (_("Predicate register expected"));
+         return 0;
        }
-
-      demand_empty_rest_of_line ();
       return 1;
 
     case '[':
@@ -7540,7 +7521,7 @@ ia64_unrecognized_line (ch)
 
        if (md.qp.X_op == O_register)
          {
-           as_bad ("Tag must come before qualifying predicate.");
+           as_bad (_("Tag must come before qualifying predicate."));
            return 0;
          }
 
@@ -7570,7 +7551,7 @@ ia64_unrecognized_line (ch)
          {
            /* Put ':' back for error messages' sake.  */
            *input_line_pointer++ = ':';
-           as_bad ("Expected ':'");
+           as_bad (_("Expected ':'"));
            return 0;
          }
 
@@ -7581,12 +7562,12 @@ ia64_unrecognized_line (ch)
        *input_line_pointer++ = ':';
        if (*input_line_pointer++ != ']')
          {
-           as_bad ("Expected ']'");
+           as_bad (_("Expected ']'"));
            return 0;
          }
        if (! tag)
          {
-           as_bad ("Tag name expected");
+           as_bad (_("Tag name expected"));
            return 0;
          }
        return 1;
@@ -7601,8 +7582,7 @@ ia64_unrecognized_line (ch)
 }
 
 void
-ia64_frob_label (sym)
-     struct symbol *sym;
+ia64_frob_label (struct symbol *sym)
 {
   struct label_fix *fix;
 
@@ -7613,6 +7593,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.tag_fixups;
+      fix->dw2_mark_labels = FALSE;
       CURR_SLOT.tag_fixups = fix;
 
       return;
@@ -7624,6 +7605,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.label_fixups;
+      fix->dw2_mark_labels = dwarf2_loc_mark_labels;
       CURR_SLOT.label_fixups = fix;
 
       /* Keep track of how many code entry points we've seen.  */
@@ -7643,8 +7625,7 @@ ia64_frob_label (sym)
    that are declared but unused.  This routine removes declared,
    unused symbols from an object.  */
 int
-ia64_frob_symbol (sym)
-     struct symbol *sym;
+ia64_frob_symbol (struct symbol *sym)
 {
   if ((S_GET_SEGMENT (sym) == &bfd_und_section && ! symbol_used_p (sym) &&
        ELF_ST_VISIBILITY (S_GET_OTHER (sym)) == STV_DEFAULT)
@@ -7656,7 +7637,7 @@ ia64_frob_symbol (sym)
 #endif
 
 void
-ia64_flush_pending_output ()
+ia64_flush_pending_output (void)
 {
   if (!md.keep_pending_output
       && bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)
@@ -7673,55 +7654,60 @@ ia64_flush_pending_output ()
    of rotating registers or due to the indexing of indirect register
    sets.  */
 int
-ia64_optimize_expr (l, op, r)
-     expressionS *l;
-     operatorT op;
-     expressionS *r;
+ia64_optimize_expr (expressionS *l, operatorT op, expressionS *r)
 {
-  unsigned num_regs;
-
-  if (op == O_index)
+  if (op != O_index)
+    return 0;
+  resolve_expression (l);
+  if (l->X_op == O_register)
     {
-      if (l->X_op == O_register && r->X_op == O_constant)
+      unsigned num_regs = l->X_add_number >> 16;
+
+      resolve_expression (r);
+      if (num_regs)
        {
-         num_regs = (l->X_add_number >> 16);
-         if ((unsigned) r->X_add_number >= num_regs)
+         /* Left side is a .rotX-allocated register.  */
+         if (r->X_op != O_constant)
            {
-             if (!num_regs)
-               as_bad ("No current frame");
-             else
-               as_bad ("Index out of range 0..%u", num_regs - 1);
+             as_bad (_("Rotating register index must be a non-negative constant"));
+             r->X_add_number = 0;
+           }
+         else if ((valueT) r->X_add_number >= num_regs)
+           {
+             as_bad (_("Index out of range 0..%u"), num_regs - 1);
              r->X_add_number = 0;
            }
          l->X_add_number = (l->X_add_number & 0xffff) + r->X_add_number;
          return 1;
        }
-      else if (l->X_op == O_register && r->X_op == O_register)
+      else if (l->X_add_number >= IND_CPUID && l->X_add_number <= IND_RR)
        {
-         if (l->X_add_number < IND_CPUID || l->X_add_number > IND_RR
-             || l->X_add_number == IND_MEM)
+         if (r->X_op != O_register
+             || r->X_add_number < REG_GR
+             || r->X_add_number > REG_GR + 127)
            {
-             as_bad ("Indirect register set name expected");
-             l->X_add_number = IND_CPUID;
+             as_bad (_("Indirect register index must be a general register"));
+             r->X_add_number = REG_GR;
            }
          l->X_op = O_index;
-         l->X_op_symbol = md.regsym[l->X_add_number];
+         l->X_op_symbol = md.indregsym[l->X_add_number - IND_CPUID];
          l->X_add_number = r->X_add_number;
          return 1;
        }
     }
-  return 0;
+  as_bad (_("Index can only be applied to rotating or indirect registers"));
+  /* Fall back to some register use of which has as little as possible
+     side effects, to minimize subsequent error messages.  */
+  l->X_op = O_register;
+  l->X_add_number = REG_GR + 3;
+  return 1;
 }
 
 int
-ia64_parse_name (name, e, nextcharP)
-     char *name;
-     expressionS *e;
-     char *nextcharP;
+ia64_parse_name (char *name, expressionS *e, char *nextcharP)
 {
   struct const_desc *cdesc;
   struct dynreg *dr = 0;
-  unsigned int regnum;
   unsigned int idx;
   struct symbol *sym;
   char *end;
@@ -7745,7 +7731,7 @@ ia64_parse_name (name, e, nextcharP)
          end = input_line_pointer;
          if (*nextcharP != '(')
            {
-             as_bad ("Expected '('");
+             as_bad (_("Expected '('"));
              break;
            }
          /* Skip '('.  */
@@ -7753,7 +7739,7 @@ ia64_parse_name (name, e, nextcharP)
          expression (e);
          if (*input_line_pointer != ')')
            {
-             as_bad ("Missing ')'");
+             as_bad (_("Missing ')'"));
              goto done;
            }
          /* Skip ')'.  */
@@ -7762,12 +7748,12 @@ ia64_parse_name (name, e, nextcharP)
            {
              if (e->X_op != O_pseudo_fixup)
                {
-                 as_bad ("Not a symbolic expression");
+                 as_bad (_("Not a symbolic expression"));
                  goto done;
                }
              if (idx != FUNC_LT_RELATIVE)
                {
-                 as_bad ("Illegal combination of relocation functions");
+                 as_bad (_("Illegal combination of relocation functions"));
                  goto done;
                }
              switch (S_GET_VALUE (e->X_op_symbol))
@@ -7781,7 +7767,7 @@ ia64_parse_name (name, e, nextcharP)
                case FUNC_TP_RELATIVE:
                  idx = FUNC_LT_TP_RELATIVE; break;
                default:
-                 as_bad ("Illegal combination of relocation functions");
+                 as_bad (_("Illegal combination of relocation functions"));
                  goto done;
                }
            }
@@ -7827,13 +7813,14 @@ ia64_parse_name (name, e, nextcharP)
     }
 
   /* check for inN, locN, or outN:  */
+  idx = 0;
   switch (name[0])
     {
     case 'i':
       if (name[1] == 'n' && ISDIGIT (name[2]))
        {
          dr = &md.in;
-         name += 2;
+         idx = 2;
        }
       break;
 
@@ -7841,7 +7828,7 @@ ia64_parse_name (name, e, nextcharP)
       if (name[1] == 'o' && name[2] == 'c' && ISDIGIT (name[3]))
        {
          dr = &md.loc;
-         name += 3;
+         idx = 3;
        }
       break;
 
@@ -7849,7 +7836,7 @@ ia64_parse_name (name, e, nextcharP)
       if (name[1] == 'u' && name[2] == 't' && ISDIGIT (name[3]))
        {
          dr = &md.out;
-         name += 3;
+         idx = 3;
        }
       break;
 
@@ -7857,18 +7844,21 @@ ia64_parse_name (name, e, nextcharP)
       break;
     }
 
-  if (dr)
+  /* Ignore register numbers with leading zeroes, except zero itself.  */
+  if (dr && (name[idx] != '0' || name[idx + 1] == '\0'))
     {
+      unsigned long regnum;
+
       /* The name is inN, locN, or outN; parse the register number.  */
-      regnum = strtoul (name, &end, 10);
-      if (end > name && *end == '\0')
+      regnum = strtoul (name + idx, &end, 10);
+      if (end > name + idx && *end == '\0' && regnum < 96)
        {
-         if ((unsigned) regnum >= dr->num_regs)
+         if (regnum >= dr->num_regs)
            {
              if (!dr->num_regs)
-               as_bad ("No current frame");
+               as_bad (_("No current frame"));
              else
-               as_bad ("Register number out of range 0..%u",
+               as_bad (_("Register number out of range 0..%u"),
                        dr->num_regs - 1);
              regnum = 0;
            }
@@ -7897,8 +7887,7 @@ ia64_parse_name (name, e, nextcharP)
 /* Remove the '#' suffix that indicates a symbol as opposed to a register.  */
 
 char *
-ia64_canonicalize_symbol_name (name)
-     char *name;
+ia64_canonicalize_symbol_name (char *name)
 {
   size_t len = strlen (name), full = len;
 
@@ -7907,12 +7896,10 @@ ia64_canonicalize_symbol_name (name)
   if (len <= 0)
     {
       if (full > 0)
-       as_bad ("Standalone `#' is illegal");
-      else
-       as_bad ("Zero-length symbol is illegal");
+       as_bad (_("Standalone `#' is illegal"));
     }
   else if (len < full - 1)
-    as_warn ("Redundant `#' suffix operators");
+    as_warn (_("Redundant `#' suffix operators"));
   name[len] = '\0';
   return name;
 }
@@ -7925,8 +7912,7 @@ ia64_canonicalize_symbol_name (name)
    through, and which use no resources if they do fall through.  */
 
 static int
-is_conditional_branch (idesc)
-     struct ia64_opcode *idesc;
+is_conditional_branch (struct ia64_opcode *idesc)
 {
   /* br is a conditional branch.  Everything that starts with br. except
      br.ia, br.c{loop,top,exit}, and br.w{top,exit} is a conditional branch.
@@ -7946,8 +7932,7 @@ is_conditional_branch (idesc)
    returns zero.  */
 
 static int
-is_taken_branch (idesc)
-     struct ia64_opcode *idesc;
+is_taken_branch (struct ia64_opcode *idesc)
 {
   return ((is_conditional_branch (idesc) && CURR_SLOT.qp_regno == 0)
          || strncmp (idesc->name, "br.ia", 5) == 0);
@@ -7957,8 +7942,7 @@ is_taken_branch (idesc)
    doubt, returns zero.  */
 
 static int
-is_interruption_or_rfi (idesc)
-     struct ia64_opcode *idesc;
+is_interruption_or_rfi (struct ia64_opcode *idesc)
 {
   if (strcmp (idesc->name, "rfi") == 0)
     return 1;
@@ -7969,9 +7953,7 @@ is_interruption_or_rfi (idesc)
    -1 if there is no dependency.  */
 
 static int
-depends_on (depind, idesc)
-     int depind;
-     struct ia64_opcode *idesc;
+depends_on (int depind, struct ia64_opcode *idesc)
 {
   int i;
   const struct ia64_opcode_dependency *dep = idesc->dependencies;
@@ -8015,7 +7997,7 @@ depends_on (depind, idesc)
    cannot statically be determined, all source registers are marked used.
    12) This insn only reads the specified predicate register when that
    register is the PR[qp].
-   13) This reference to ld-c only applies to teh GR whose value is loaded
+   13) This reference to ld-c only applies to the GR whose value is loaded
    with data returned from memory, not the post-incremented address register.
    14) The RSE resource includes the implementation-specific RSE internal
    state resources.  At least one (and possibly more) of these resources are
@@ -8024,6 +8006,8 @@ depends_on (depind, idesc)
    IC:rse-writers.
    15+16) Represents reserved instructions, which the assembler does not
    generate.
+   17) CR[TPR] has a RAW dependency only between mov-to-CR-TPR and
+   mov-to-PSR-l or ssm instructions that set PSR.i, PSR.pp or PSR.up.
 
    Memory resources (i.e. locations in memory) are *not* marked or tracked by
    this code; there are no dependency violations based on memory access.
@@ -8034,13 +8018,16 @@ depends_on (depind, idesc)
 #define DV_REG 0
 
 static int
-specify_resource (dep, idesc, type, specs, note, path)
-     const struct ia64_dependency *dep;
-     struct ia64_opcode *idesc;
-     int type;                         /* is this a DV chk or a DV reg? */
-     struct rsrc specs[MAX_SPECS];     /* returned specific resources */
-     int note;                         /* resource note for this insn's usage */
-     int path;                         /* which execution path to examine */
+specify_resource (const struct ia64_dependency *dep,
+                 struct ia64_opcode *idesc,
+                 /* is this a DV chk or a DV reg? */
+                 int type,
+                 /* returned specific resources */
+                 struct rsrc specs[MAX_SPECS],
+                 /* resource note for this insn's usage */
+                 int note,
+                 /* which execution path to examine */
+                 int path)
 {
   int count = 0;
   int i;
@@ -8059,9 +8046,15 @@ specify_resource (dep, idesc, type, specs, note, path)
   tmpl.qp_regno = CURR_SLOT.qp_regno;
   tmpl.link_to_qp_branch = 1;
   tmpl.mem_offset.hint = 0;
+  tmpl.mem_offset.offset = 0;
+  tmpl.mem_offset.base = 0;
   tmpl.specific = 1;
-  tmpl.index = 0;
+  tmpl.index = -1;
   tmpl.cmp_type = CMP_NONE;
+  tmpl.depind = 0;
+  tmpl.file = NULL;
+  tmpl.line = 0;
+  tmpl.path = 0;
 
 #define UNHANDLED \
 as_warn (_("Unhandled dependency %s for %s (%s), note %d"), \
@@ -8368,9 +8361,9 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
              || (!rsrc_write && idesc->operands[1] == IA64_OPND_PMD_R3))
 
            {
-             int index = ((idesc->operands[1] == IA64_OPND_R3 && !rsrc_write)
-                          ? 1 : !rsrc_write);
-             int regno = CURR_SLOT.opnd[index].X_add_number - REG_GR;
+             int reg_index = ((idesc->operands[1] == IA64_OPND_R3 && !rsrc_write)
+                              ? 1 : !rsrc_write);
+             int regno = CURR_SLOT.opnd[reg_index].X_add_number - REG_GR;
              if (regno >= 0 && regno < NELEMS (gr_values)
                  && KNOWN (regno))
                {
@@ -8478,6 +8471,23 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
        }
       break;
 
+    case IA64_RS_CR_IIB:
+      if (note != 0)
+       {
+         UNHANDLED;
+       }
+      else
+       {
+         int regno = CURR_SLOT.opnd[!rsrc_write].X_add_number - REG_CR;
+         if (idesc->operands[!rsrc_write] == IA64_OPND_CR3
+             && (regno == CR_IIB0 || regno == CR_IIB1))
+           {
+             specs[count] = tmpl;
+             specs[count++].index = regno;
+           }
+       }
+      break;
+
     case IA64_RS_CR_LRR:
       if (note != 1)
        {
@@ -8891,11 +8901,11 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
                      if (idesc->operands[0] == IA64_OPND_CR3
                          || idesc->operands[1] == IA64_OPND_CR3)
                        {
-                         int index =
+                         int reg_index =
                            ((idesc->operands[0] == IA64_OPND_CR3)
                             ? 0 : 1);
                          int regno =
-                           CURR_SLOT.opnd[index].X_add_number - REG_CR;
+                           CURR_SLOT.opnd[reg_index].X_add_number - REG_CR;
 
                          switch (regno)
                            {
@@ -8909,6 +8919,8 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
                            case CR_ISR:
                            case CR_IFA:
                            case CR_IHA:
+                           case CR_IIB0:
+                           case CR_IIB1:
                            case CR_IIPA:
                              specs[count++] = tmpl;
                              break;
@@ -8927,16 +8939,16 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
                      if (idesc->operands[0] == IA64_OPND_AR3
                          || idesc->operands[1] == IA64_OPND_AR3)
                        {
-                         int index =
+                         int reg_index =
                            ((idesc->operands[0] == IA64_OPND_AR3)
                             ? 0 : 1);
                          int regno =
-                           CURR_SLOT.opnd[index].X_add_number - REG_AR;
+                           CURR_SLOT.opnd[reg_index].X_add_number - REG_AR;
 
                          if (regno == AR_ITC
-                             || (index == 0
-                                 && (regno == AR_ITC
-                                     || regno == AR_RSC
+                             || regno == AR_RUC
+                             || (reg_index == 0
+                                 && (regno == AR_RSC
                                      || (regno >= AR_K0
                                          && regno <= AR_K7))))
                            {
@@ -9106,8 +9118,9 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
       break;
 
     case IA64_RS_CRX:
-      /* Handle all CR[REG] resources */
-      if (note == 0 || note == 1)
+      /* Handle all CR[REG] resources.
+        ??? FIXME: The rule 17 isn't really handled correctly.   */
+      if (note == 0 || note == 1 || note == 17)
        {
          if (idesc->operands[!rsrc_write] == IA64_OPND_CR3)
            {
@@ -9303,8 +9316,7 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
              if (idesc->operands[0] == IA64_OPND_AR3
                  && CURR_SLOT.opnd[0].X_add_number - REG_AR == AR_BSPSTORE)
                {
-                 specs[count] = tmpl;
-                 specs[count++].index = 0; /* IA64_RSE_BSPLOAD/RNATBITINDEX */
+                 specs[count++] = tmpl;
                }
            }
          else
@@ -9351,8 +9363,7 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
    QP of the marking instruction and a subsequent branch on the same QP.  */
 
 static void
-clear_qp_branch_flag (mask)
-     valueT mask;
+clear_qp_branch_flag (valueT mask)
 {
   int i;
   for (i = 0; i < regdepslen; i++)
@@ -9441,8 +9452,7 @@ update_qp_mutex (valueT mask)
    Any changes to a PR clears the mutex relations which include that PR.  */
 
 static void
-clear_qp_mutex (mask)
-     valueT mask;
+clear_qp_mutex (valueT mask)
 {
   int i;
 
@@ -9469,9 +9479,7 @@ clear_qp_mutex (mask)
    indicates the implied PR.  */
 
 static void
-clear_qp_implies (p1_mask, p2_mask)
-     valueT p1_mask;
-     valueT p2_mask;
+clear_qp_implies (valueT p1_mask, valueT p2_mask)
 {
   int i;
 
@@ -9494,8 +9502,7 @@ clear_qp_implies (p1_mask, p2_mask)
 /* Add the PRs specified to the list of implied relations.  */
 
 static void
-add_qp_imply (p1, p2)
-     int p1, p2;
+add_qp_imply (int p1, int p2)
 {
   valueT mask;
   valueT bit;
@@ -9558,8 +9565,7 @@ add_qp_imply (p1, p2)
    the mask.  */
 
 static void
-add_qp_mutex (mask)
-     valueT mask;
+add_qp_mutex (valueT mask)
 {
   if (mask & 0x1)
     abort ();
@@ -9582,9 +9588,7 @@ add_qp_mutex (mask)
 }
 
 static int
-has_suffix_p (name, suffix)
-     const char *name;
-     const char *suffix;
+has_suffix_p (const char *name, const char *suffix)
 {
   size_t namelen = strlen (name);
   size_t sufflen = strlen (suffix);
@@ -9595,7 +9599,7 @@ has_suffix_p (name, suffix)
 }
 
 static void
-clear_register_values ()
+clear_register_values (void)
 {
   int i;
   if (md.debug_dv)
@@ -9610,8 +9614,7 @@ clear_register_values ()
    have to examine a group of strings to identify them.  */
 
 static void
-note_register_values (idesc)
-     struct ia64_opcode *idesc;
+note_register_values (struct ia64_opcode *idesc)
 {
   valueT qp_changemask = 0;
   int i;
@@ -9758,6 +9761,7 @@ note_register_values (idesc)
   else if (idesc->operands[0] == IA64_OPND_R1
           && (idesc->operands[1] == IA64_OPND_IMM22
               || idesc->operands[1] == IA64_OPND_IMMU64)
+          && CURR_SLOT.opnd[1].X_op == O_constant
           && (strcmp (idesc->name, "mov") == 0
               || strcmp (idesc->name, "movl") == 0))
     {
@@ -9775,6 +9779,30 @@ note_register_values (idesc)
            }
        }
     }
+  /* Look for dep.z imm insns.  */
+  else if (idesc->operands[0] == IA64_OPND_R1
+          && idesc->operands[1] == IA64_OPND_IMM8
+          && strcmp (idesc->name, "dep.z") == 0)
+    {
+      int regno = CURR_SLOT.opnd[0].X_add_number - REG_GR;
+      if (regno > 0 && regno < NELEMS (gr_values))
+       {
+         valueT value = CURR_SLOT.opnd[1].X_add_number;
+
+         if (CURR_SLOT.opnd[3].X_add_number < 64)
+           value &= ((valueT)1 << CURR_SLOT.opnd[3].X_add_number) - 1;
+         value <<= CURR_SLOT.opnd[2].X_add_number;
+         gr_values[regno].known = 1;
+         gr_values[regno].value = value;
+         gr_values[regno].path = md.path;
+         if (md.debug_dv)
+           {
+             fprintf (stderr, "  Know gr%d = ", regno);
+             fprintf_vma (stderr, gr_values[regno].value);
+             fputs ("\n", stderr);
+           }
+       }
+    }
   else
     {
       clear_qp_mutex (qp_changemask);
@@ -9785,10 +9813,7 @@ note_register_values (idesc)
 /* Return whether the given predicate registers are currently mutex.  */
 
 static int
-qp_mutex (p1, p2, path)
-     int p1;
-     int p2;
-     int path;
+qp_mutex (int p1, int p2, int path)
 {
   int i;
   valueT mask;
@@ -9811,12 +9836,11 @@ qp_mutex (p1, p2, path)
    conflict.  */
 
 static int
-resources_match (rs, idesc, note, qp_regno, path)
-     struct rsrc *rs;
-     struct ia64_opcode *idesc;
-     int note;
-     int qp_regno;
-     int path;
+resources_match (struct rsrc *rs,
+                struct ia64_opcode *idesc,
+                int note,
+                int qp_regno,
+                int path)
 {
   struct rsrc specs[MAX_SPECS];
   int count;
@@ -9892,10 +9916,7 @@ resources_match (rs, idesc, note, qp_regno, path)
    instruction.  */
 
 static void
-insn_group_break (insert_stop, qp_regno, save_current)
-     int insert_stop;
-     int qp_regno;
-     int save_current;
+insn_group_break (int insert_stop, int qp_regno, int save_current)
 {
   int i;
 
@@ -9959,12 +9980,11 @@ insn_group_break (insert_stop, qp_regno, save_current)
 /* Add the given resource usage spec to the list of active dependencies.  */
 
 static void
-mark_resource (idesc, dep, spec, depind, path)
-     struct ia64_opcode *idesc ATTRIBUTE_UNUSED;
-     const struct ia64_dependency *dep ATTRIBUTE_UNUSED;
-     struct rsrc *spec;
-     int depind;
-     int path;
+mark_resource (struct ia64_opcode *idesc ATTRIBUTE_UNUSED,
+              const struct ia64_dependency *dep ATTRIBUTE_UNUSED,
+              struct rsrc *spec,
+              int depind,
+              int path)
 {
   if (regdepslen == regdepstotlen)
     {
@@ -9986,16 +10006,14 @@ mark_resource (idesc, dep, spec, depind, path)
 }
 
 static void
-print_dependency (action, depind)
-     const char *action;
-     int depind;
+print_dependency (const char *action, int depind)
 {
   if (md.debug_dv)
     {
       fprintf (stderr, "  %s %s '%s'",
               action, dv_mode[(regdeps[depind].dependency)->mode],
               (regdeps[depind].dependency)->name);
-      if (regdeps[depind].specific && regdeps[depind].index != 0)
+      if (regdeps[depind].specific && regdeps[depind].index >= 0)
        fprintf (stderr, " (%d)", regdeps[depind].index);
       if (regdeps[depind].mem_offset.hint)
        {
@@ -10009,7 +10027,7 @@ print_dependency (action, depind)
 }
 
 static void
-instruction_serialization ()
+instruction_serialization (void)
 {
   int i;
   if (md.debug_dv)
@@ -10020,7 +10038,7 @@ instruction_serialization ()
 }
 
 static void
-data_serialization ()
+data_serialization (void)
 {
   int i = 0;
   if (md.debug_dv)
@@ -10043,8 +10061,7 @@ data_serialization ()
 /* Insert stops and serializations as needed to avoid DVs.  */
 
 static void
-remove_marked_resource (rs)
-     struct rsrc *rs;
+remove_marked_resource (struct rsrc *rs)
 {
   switch (rs->dependency->semantics)
     {
@@ -10062,6 +10079,7 @@ remove_marked_resource (rs)
          struct slot oldslot = CURR_SLOT;
          /* Manually jam a srlz.i insn into the stream */
          memset (&CURR_SLOT, 0, sizeof (CURR_SLOT));
+         CURR_SLOT.user_template = -1;
          CURR_SLOT.idesc = ia64_find_opcode ("srlz.i");
          instruction_serialization ();
          md.curr_slot = (md.curr_slot + 1) % NUM_SLOTS;
@@ -10083,6 +10101,7 @@ remove_marked_resource (rs)
        struct slot oldslot = CURR_SLOT;
        /* Manually jam a srlz.d insn into the stream */
        memset (&CURR_SLOT, 0, sizeof (CURR_SLOT));
+       CURR_SLOT.user_template = -1;
        CURR_SLOT.idesc = ia64_find_opcode ("srlz.d");
        data_serialization ();
        md.curr_slot = (md.curr_slot + 1) % NUM_SLOTS;
@@ -10117,8 +10136,7 @@ remove_marked_resource (rs)
 */
 
 static void
-check_dependencies (idesc)
-     struct ia64_opcode *idesc;
+check_dependencies (struct ia64_opcode *idesc)
 {
   const struct ia64_opcode_dependency *opdeps = idesc->dependencies;
   int path;
@@ -10191,12 +10209,15 @@ check_dependencies (idesc)
              int certain = (matchtype == 1 && CURR_SLOT.qp_regno == 0);
 
              if (path != 0)
-               sprintf (pathmsg, " when entry is at label '%s'",
+               snprintf (pathmsg, sizeof (pathmsg),
+                         " when entry is at label '%s'",
                         md.entry_labels[path - 1]);
-             if (rs->specific && rs->index != 0)
-               sprintf (indexmsg, ", specific resource number is %d",
+             if (matchtype == 1 && rs->index >= 0)
+               snprintf (indexmsg, sizeof (indexmsg),
+                         ", specific resource number is %d",
                         rs->index);
-             sprintf (msg, "Use of '%s' %s %s dependency '%s' (%s)%s%s",
+             snprintf (msg, sizeof (msg),
+                       "Use of '%s' %s %s dependency '%s' (%s)%s%s",
                       idesc->name,
                       (certain ? "violates" : "may violate"),
                       dv_mode[dep->mode], dep->name,
@@ -10207,11 +10228,9 @@ check_dependencies (idesc)
                {
                  as_warn ("%s", msg);
                  if (path < md.path)
-                   as_warn (_("Only the first path encountering the conflict "
-                              "is reported"));
+                   as_warn (_("Only the first path encountering the conflict is reported"));
                  as_warn_where (rs->file, rs->line,
-                                _("This is the location of the "
-                                  "conflicting usage"));
+                                _("This is the location of the conflicting usage"));
                  /* Don't bother checking other paths, to avoid duplicating
                     the same warning */
                  break;
@@ -10241,8 +10260,7 @@ check_dependencies (idesc)
 /* Register new dependencies based on the given opcode.  */
 
 static void
-mark_resources (idesc)
-     struct ia64_opcode *idesc;
+mark_resources (struct ia64_opcode *idesc)
 {
   int i;
   const struct ia64_opcode_dependency *opdeps = idesc->dependencies;
@@ -10315,8 +10333,7 @@ mark_resources (idesc)
 /* Remove dependencies when they no longer apply.  */
 
 static void
-update_dependencies (idesc)
-     struct ia64_opcode *idesc;
+update_dependencies (struct ia64_opcode *idesc)
 {
   int i;
 
@@ -10396,8 +10413,7 @@ update_dependencies (idesc)
 /* Examine the current instruction for dependency violations.  */
 
 static int
-check_dv (idesc)
-     struct ia64_opcode *idesc;
+check_dv (struct ia64_opcode *idesc)
 {
   if (md.debug_dv)
     {
@@ -10445,8 +10461,7 @@ check_dv (idesc)
 /* Translate one line of assembly.  Pseudo ops and labels do not show
    here.  */
 void
-md_assemble (str)
-     char *str;
+md_assemble (char *str)
 {
   char *saved_input_line_pointer, *mnemonic;
   const struct pseudo_opcode *pdesc;
@@ -10476,7 +10491,7 @@ md_assemble (str)
   *input_line_pointer = ch;
   if (!idesc)
     {
-      as_bad ("Unknown opcode `%s'", mnemonic);
+      as_bad (_("Unknown opcode `%s'"), mnemonic);
       goto done;
     }
 
@@ -10554,11 +10569,25 @@ md_assemble (str)
          else if (ar_is_only_in_memory_unit (CURR_SLOT.opnd[rop].X_add_number))
            unit = 'm';
          if (unit != 'a' && unit != idesc->name [4])
-           as_bad ("AR %d cannot be accessed by %c-unit",
+           as_bad (_("AR %d can only be accessed by %c-unit"),
                    (int) (CURR_SLOT.opnd[rop].X_add_number - REG_AR),
                    TOUPPER (unit));
        }
     }
+  else if (strcmp (idesc->name, "hint.b") == 0)
+    {
+      switch (md.hint_b)
+       {
+       case hint_b_ok:
+         break;
+       case hint_b_warning:
+         as_warn (_("hint.b may be treated as nop"));
+         break;
+       case hint_b_error:
+         as_bad (_("hint.b shouldn't be used"));
+         break;
+       }
+    }
 
   qp_regno = 0;
   if (md.qp.X_op == O_register)
@@ -10594,7 +10623,7 @@ md_assemble (str)
 
   if ((flags & IA64_OPCODE_NO_PRED) != 0 && qp_regno != 0)
     {
-      as_bad ("`%s' cannot be predicated", idesc->name);
+      as_bad (_("`%s' cannot be predicated"), idesc->name);
       goto done;
     }
 
@@ -10603,14 +10632,27 @@ md_assemble (str)
   CURR_SLOT.idesc = idesc;
   as_where (&CURR_SLOT.src_file, &CURR_SLOT.src_line);
   dwarf2_where (&CURR_SLOT.debug_line);
+  dwarf2_consume_line_info ();
 
-  /* Add unwind entry, if there is one.  */
+  /* Add unwind entries, if there are any.  */
   if (unwind.current_entry)
     {
       CURR_SLOT.unwind_record = unwind.current_entry;
       unwind.current_entry = NULL;
     }
-  if (unwind.proc_start && S_IS_DEFINED (unwind.proc_start))
+  if (unwind.pending_saves)
+    {
+      if (unwind.pending_saves->next)
+       {
+         /* Attach the next pending save to the next slot so that its
+            slot number will get set correctly.  */
+         add_unwind_entry (unwind.pending_saves->next, NOT_A_CHAR);
+         unwind.pending_saves = &unwind.pending_saves->next->r.record.p;
+       }
+      else
+       unwind.pending_saves = NULL;
+    }
+  if (unwind.proc_pending.sym && S_IS_DEFINED (unwind.proc_pending.sym))
     unwind.insn = 1;
 
   /* Check for dependency violations.  */
@@ -10634,8 +10676,7 @@ md_assemble (str)
    Should be used for dynamic valued symbols only.  */
 
 symbolS *
-md_undefined_symbol (name)
-     char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
 {
   return 0;
 }
@@ -10645,23 +10686,27 @@ md_undefined_symbol (name)
    the expression.  */
 
 void
-md_operand (e)
-     expressionS *e;
+md_operand (expressionS *e)
 {
   switch (*input_line_pointer)
     {
     case '[':
       ++input_line_pointer;
-      expression (e);
+      expression_and_evaluate (e);
       if (*input_line_pointer != ']')
        {
-         as_bad ("Closing bracket missing");
+         as_bad (_("Closing bracket missing"));
          goto err;
        }
       else
        {
-         if (e->X_op != O_register)
-           as_bad ("Register expected as index");
+         if (e->X_op != O_register
+             || e->X_add_number < REG_GR
+             || e->X_add_number > REG_GR + 127)
+           {
+             as_bad (_("Index must be a general register"));
+             e->X_add_number = REG_GR;
+           }
 
          ++input_line_pointer;
          e->X_op = O_index;
@@ -10682,11 +10727,10 @@ md_operand (e)
    directives we don't want such adjustments since we need to have the
    original symbol's name in the reloc.  */
 int
-ia64_fix_adjustable (fix)
-     fixS *fix;
+ia64_fix_adjustable (fixS *fix)
 {
   /* Prevent all adjustments to global symbols */
-  if (S_IS_EXTERN (fix->fx_addsy) || S_IS_WEAK (fix->fx_addsy))
+  if (S_IS_EXTERNAL (fix->fx_addsy) || S_IS_WEAK (fix->fx_addsy))
     return 0;
 
   switch (fix->fx_r_type)
@@ -10707,8 +10751,7 @@ ia64_fix_adjustable (fix)
 }
 
 int
-ia64_force_relocation (fix)
-     fixS *fix;
+ia64_force_relocation (fixS *fix)
 {
   switch (fix->fx_r_type)
     {
@@ -10741,9 +10784,7 @@ ia64_force_relocation (fix)
 /* Decide from what point a pc-relative relocation is relative to,
    relative to the pc-relative fixup.  Er, relatively speaking.  */
 long
-ia64_pcrel_from_section (fix, sec)
-     fixS *fix;
-     segT sec;
+ia64_pcrel_from_section (fixS *fix, segT sec)
 {
   unsigned long off = fix->fx_frag->fr_address + fix->fx_where;
 
@@ -10758,24 +10799,20 @@ ia64_pcrel_from_section (fix, sec)
 void
 ia64_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 {
-  expressionS expr;
+  expressionS exp;
 
-  expr.X_op = O_pseudo_fixup;
-  expr.X_op_symbol = pseudo_func[FUNC_SEC_RELATIVE].u.sym;
-  expr.X_add_number = 0;
-  expr.X_add_symbol = symbol;
-  emit_expr (&expr, size);
+  exp.X_op = O_pseudo_fixup;
+  exp.X_op_symbol = pseudo_func[FUNC_SEC_RELATIVE].u.sym;
+  exp.X_add_number = 0;
+  exp.X_add_symbol = symbol;
+  emit_expr (&exp, size);
 }
 
 /* This is called whenever some data item (not an instruction) needs a
    fixup.  We pick the right reloc code depending on the byteorder
    currently in effect.  */
 void
-ia64_cons_fix_new (f, where, nbytes, exp)
-     fragS *f;
-     int where;
-     int nbytes;
-     expressionS *exp;
+ia64_cons_fix_new (fragS *f, int where, int nbytes, expressionS *exp)
 {
   bfd_reloc_code_real_type code;
   fixS *fix;
@@ -10832,7 +10869,7 @@ ia64_cons_fix_new (f, where, nbytes, exp)
       /* FALLTHRU */
 
     default:
-      as_bad ("Unsupported fixup size %d", nbytes);
+      as_bad (_("Unsupported fixup size %d"), nbytes);
       ignore_rest_of_line ();
       return;
     }
@@ -10847,7 +10884,7 @@ ia64_cons_fix_new (f, where, nbytes, exp)
   fix = fix_new_exp (f, where, nbytes, exp, 0, code);
   /* We need to store the byte order in effect in case we're going
      to fix an 8 or 16 bit relocation (for which there no real
-     relocs available).  See md_apply_fix3().  */
+     relocs available).  See md_apply_fix().  */
   fix->tc_fix_data.bigendian = target_big_endian;
 }
 
@@ -10856,11 +10893,9 @@ ia64_cons_fix_new (f, where, nbytes, exp)
    symbols in the pseudo_func array, or NULL.  */
 
 static bfd_reloc_code_real_type
-ia64_gen_real_reloc_type (sym, r_type)
-     struct symbol *sym;
-     bfd_reloc_code_real_type r_type;
+ia64_gen_real_reloc_type (struct symbol *sym, bfd_reloc_code_real_type r_type)
 {
-  bfd_reloc_code_real_type new = 0;
+  bfd_reloc_code_real_type newr = 0;
   const char *type = NULL, *suffix = "";
 
   if (sym == NULL)
@@ -10873,11 +10908,11 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_FPTR_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_FPTR64I; break;
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_FPTR32MSB; break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_FPTR32LSB; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_FPTR64MSB; break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_FPTR64LSB; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_FPTR64I; break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_FPTR32MSB; break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_FPTR32LSB; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_FPTR64MSB; break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_FPTR64LSB; break;
        default:                        type = "FPTR"; break;
        }
       break;
@@ -10885,12 +10920,12 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_GP_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_GPREL22; break;
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_GPREL64I; break;
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_GPREL32MSB; break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_GPREL32LSB; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_GPREL64MSB; break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_GPREL64LSB; break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_GPREL22; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_GPREL64I; break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_GPREL32MSB; break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_GPREL32LSB; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_GPREL64MSB; break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_GPREL64LSB; break;
        default:                        type = "GPREL"; break;
        }
       break;
@@ -10898,8 +10933,8 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_LT_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_LTOFF22; break;
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_LTOFF64I; break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_LTOFF22; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_LTOFF64I; break;
        default:                        type = "LTOFF"; break;
        }
       break;
@@ -10907,7 +10942,7 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_LT_RELATIVE_X:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_LTOFF22X; break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_LTOFF22X; break;
        default:                        type = "LTOFF"; suffix = "X"; break;
        }
       break;
@@ -10915,12 +10950,12 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_PC_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_PCREL22; break;
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_PCREL64I; break;
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_PCREL32MSB; break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_PCREL32LSB; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_PCREL64MSB; break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_PCREL64LSB; break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_PCREL22; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_PCREL64I; break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_PCREL32MSB; break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_PCREL32LSB; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_PCREL64MSB; break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_PCREL64LSB; break;
        default:                        type = "PCREL"; break;
        }
       break;
@@ -10928,10 +10963,10 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_PLT_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_PLTOFF22; break;
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_PLTOFF64I; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_PLTOFF64MSB;break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_PLTOFF64LSB;break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_PLTOFF22; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_PLTOFF64I; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_PLTOFF64MSB;break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_PLTOFF64LSB;break;
        default:                        type = "PLTOFF"; break;
        }
       break;
@@ -10939,10 +10974,10 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_SEC_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_SECREL32MSB;break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_SECREL32LSB;break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_SECREL64MSB;break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_SECREL64LSB;break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_SECREL32MSB;break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_SECREL32LSB;break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_SECREL64MSB;break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_SECREL64LSB;break;
        default:                        type = "SECREL"; break;
        }
       break;
@@ -10950,10 +10985,10 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_SEG_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_SEGREL32MSB;break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_SEGREL32LSB;break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_SEGREL64MSB;break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_SEGREL64LSB;break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_SEGREL32MSB;break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_SEGREL32LSB;break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_SEGREL64MSB;break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_SEGREL64LSB;break;
        default:                        type = "SEGREL"; break;
        }
       break;
@@ -10961,10 +10996,10 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_LTV_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_DIR32MSB:   new = BFD_RELOC_IA64_LTV32MSB; break;
-       case BFD_RELOC_IA64_DIR32LSB:   new = BFD_RELOC_IA64_LTV32LSB; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_LTV64MSB; break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_LTV64LSB; break;
+       case BFD_RELOC_IA64_DIR32MSB:   newr = BFD_RELOC_IA64_LTV32MSB; break;
+       case BFD_RELOC_IA64_DIR32LSB:   newr = BFD_RELOC_IA64_LTV32LSB; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_LTV64MSB; break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_LTV64LSB; break;
        default:                        type = "LTV"; break;
        }
       break;
@@ -10973,17 +11008,17 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_IMM22:
-         new = BFD_RELOC_IA64_LTOFF_FPTR22; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR22; break;
        case BFD_RELOC_IA64_IMM64:
-         new = BFD_RELOC_IA64_LTOFF_FPTR64I; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR64I; break;
        case BFD_RELOC_IA64_DIR32MSB:
-         new = BFD_RELOC_IA64_LTOFF_FPTR32MSB; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR32MSB; break;
        case BFD_RELOC_IA64_DIR32LSB:
-         new = BFD_RELOC_IA64_LTOFF_FPTR32LSB; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR32LSB; break;
        case BFD_RELOC_IA64_DIR64MSB:
-         new = BFD_RELOC_IA64_LTOFF_FPTR64MSB; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR64MSB; break;
        case BFD_RELOC_IA64_DIR64LSB:
-         new = BFD_RELOC_IA64_LTOFF_FPTR64LSB; break;
+         newr = BFD_RELOC_IA64_LTOFF_FPTR64LSB; break;
        default:
          type = "LTOFF_FPTR"; break;
        }
@@ -10992,11 +11027,11 @@ ia64_gen_real_reloc_type (sym, r_type)
     case FUNC_TP_RELATIVE:
       switch (r_type)
        {
-       case BFD_RELOC_IA64_IMM14:      new = BFD_RELOC_IA64_TPREL14; break;
-       case BFD_RELOC_IA64_IMM22:      new = BFD_RELOC_IA64_TPREL22; break;
-       case BFD_RELOC_IA64_IMM64:      new = BFD_RELOC_IA64_TPREL64I; break;
-       case BFD_RELOC_IA64_DIR64MSB:   new = BFD_RELOC_IA64_TPREL64MSB; break;
-       case BFD_RELOC_IA64_DIR64LSB:   new = BFD_RELOC_IA64_TPREL64LSB; break;
+       case BFD_RELOC_IA64_IMM14:      newr = BFD_RELOC_IA64_TPREL14; break;
+       case BFD_RELOC_IA64_IMM22:      newr = BFD_RELOC_IA64_TPREL22; break;
+       case BFD_RELOC_IA64_IMM64:      newr = BFD_RELOC_IA64_TPREL64I; break;
+       case BFD_RELOC_IA64_DIR64MSB:   newr = BFD_RELOC_IA64_TPREL64MSB; break;
+       case BFD_RELOC_IA64_DIR64LSB:   newr = BFD_RELOC_IA64_TPREL64LSB; break;
        default:                        type = "TPREL"; break;
        }
       break;
@@ -11005,7 +11040,7 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_IMM22:
-         new = BFD_RELOC_IA64_LTOFF_TPREL22; break;
+         newr = BFD_RELOC_IA64_LTOFF_TPREL22; break;
        default:
          type = "LTOFF_TPREL"; break;
        }
@@ -11015,9 +11050,9 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_DIR64MSB:
-         new = BFD_RELOC_IA64_DTPMOD64MSB; break;
+         newr = BFD_RELOC_IA64_DTPMOD64MSB; break;
        case BFD_RELOC_IA64_DIR64LSB:
-         new = BFD_RELOC_IA64_DTPMOD64LSB; break;
+         newr = BFD_RELOC_IA64_DTPMOD64LSB; break;
        default:
          type = "DTPMOD"; break;
        }
@@ -11027,7 +11062,7 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_IMM22:
-         new = BFD_RELOC_IA64_LTOFF_DTPMOD22; break;
+         newr = BFD_RELOC_IA64_LTOFF_DTPMOD22; break;
        default:
          type = "LTOFF_DTPMOD"; break;
        }
@@ -11037,19 +11072,19 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_DIR32MSB:
-         new = BFD_RELOC_IA64_DTPREL32MSB; break;
+         newr = BFD_RELOC_IA64_DTPREL32MSB; break;
        case BFD_RELOC_IA64_DIR32LSB:
-         new = BFD_RELOC_IA64_DTPREL32LSB; break;
+         newr = BFD_RELOC_IA64_DTPREL32LSB; break;
        case BFD_RELOC_IA64_DIR64MSB:
-         new = BFD_RELOC_IA64_DTPREL64MSB; break;
+         newr = BFD_RELOC_IA64_DTPREL64MSB; break;
        case BFD_RELOC_IA64_DIR64LSB:
-         new = BFD_RELOC_IA64_DTPREL64LSB; break;
+         newr = BFD_RELOC_IA64_DTPREL64LSB; break;
        case BFD_RELOC_IA64_IMM14:
-         new = BFD_RELOC_IA64_DTPREL14; break;
+         newr = BFD_RELOC_IA64_DTPREL14; break;
        case BFD_RELOC_IA64_IMM22:
-         new = BFD_RELOC_IA64_DTPREL22; break;
+         newr = BFD_RELOC_IA64_DTPREL22; break;
        case BFD_RELOC_IA64_IMM64:
-         new = BFD_RELOC_IA64_DTPREL64I; break;
+         newr = BFD_RELOC_IA64_DTPREL64I; break;
        default:
          type = "DTPREL"; break;
        }
@@ -11059,7 +11094,7 @@ ia64_gen_real_reloc_type (sym, r_type)
       switch (r_type)
        {
        case BFD_RELOC_IA64_IMM22:
-         new = BFD_RELOC_IA64_LTOFF_DTPREL22; break;
+         newr = BFD_RELOC_IA64_LTOFF_DTPREL22; break;
        default:
          type = "LTOFF_DTPREL"; break;
        }
@@ -11078,8 +11113,8 @@ ia64_gen_real_reloc_type (sym, r_type)
       abort ();
     }
 
-  if (new)
-    return new;
+  if (newr)
+    return newr;
   else
     {
       int width;
@@ -11092,6 +11127,7 @@ ia64_gen_real_reloc_type (sym, r_type)
        case BFD_RELOC_IA64_DIR32LSB: width = 32; suffix = "LSB"; break;
        case BFD_RELOC_IA64_DIR64MSB: width = 64; suffix = "MSB"; break;
        case BFD_RELOC_IA64_DIR64LSB: width = 64; suffix = "LSB"; break;
+       case BFD_RELOC_UNUSED:        width = 13; break;
        case BFD_RELOC_IA64_IMM14:    width = 14; break;
        case BFD_RELOC_IA64_IMM22:    width = 22; break;
        case BFD_RELOC_IA64_IMM64:    width = 64; suffix = "I"; break;
@@ -11099,8 +11135,8 @@ ia64_gen_real_reloc_type (sym, r_type)
        }
 
       /* This should be an error, but since previously there wasn't any
-        diagnostic here, dont't make it fail because of this for now.  */
-      as_warn ("Cannot express %s%d%s relocation", type, width, suffix);
+        diagnostic here, don't make it fail because of this for now.  */
+      as_warn (_("Cannot express %s%d%s relocation"), type, width, suffix);
       return r_type;
     }
 }
@@ -11108,8 +11144,7 @@ ia64_gen_real_reloc_type (sym, r_type)
 /* Here is where generate the appropriate reloc for pseudo relocation
    functions.  */
 void
-ia64_validate_fix (fix)
-     fixS *fix;
+ia64_validate_fix (fixS *fix)
 {
   switch (fix->fx_r_type)
     {
@@ -11120,7 +11155,7 @@ ia64_validate_fix (fix)
     case BFD_RELOC_IA64_LTOFF_FPTR64I:
       if (fix->fx_offset != 0)
        as_bad_where (fix->fx_file, fix->fx_line,
-                     "No addend allowed in @fptr() relocation");
+                     _("No addend allowed in @fptr() relocation"));
       break;
     default:
       break;
@@ -11128,10 +11163,7 @@ ia64_validate_fix (fix)
 }
 
 static void
-fix_insn (fix, odesc, value)
-     fixS *fix;
-     const struct ia64_operand *odesc;
-     valueT value;
+fix_insn (fixS *fix, const struct ia64_operand *odesc, valueT value)
 {
   bfd_vma insn[3], t0, t1, control_bits;
   const char *err;
@@ -11162,7 +11194,7 @@ fix_insn (fix, odesc, value)
   else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
     {
       if (value & ~0x3fffffffffffffffULL)
-       err = "integer operand out of range";
+       err = _("integer operand out of range");
       insn[1] = (value >> 21) & 0x1ffffffffffLL;
       insn[2] |= (((value & 0xfffff) << 6) | (((value >> 20) & 0x1) << 36));
     }
@@ -11177,7 +11209,7 @@ fix_insn (fix, odesc, value)
     err = (*odesc->insert) (odesc, value, insn + slot);
 
   if (err)
-    as_bad_where (fix->fx_file, fix->fx_line, err);
+    as_bad_where (fix->fx_file, fix->fx_line, "%s", err);
 
   t0 = control_bits | (insn[0] << 5) | (insn[1] << 46);
   t1 = ((insn[1] >> 18) & 0x7fffff) | (insn[2] << 23);
@@ -11193,10 +11225,7 @@ fix_insn (fix, odesc, value)
    (if possible).  */
 
 void
-md_apply_fix3 (fix, valP, seg)
-     fixS *fix;
-     valueT *valP;
-     segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fix, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   char *fixpos;
   valueT value = *valP;
@@ -11205,27 +11234,24 @@ md_apply_fix3 (fix, valP, seg)
 
   if (fix->fx_pcrel)
     {
-      switch (fix->fx_r_type)
-       {
-       case BFD_RELOC_IA64_DIR32MSB:
-         fix->fx_r_type = BFD_RELOC_IA64_PCREL32MSB;
-         break;
-
-       case BFD_RELOC_IA64_DIR32LSB:
-         fix->fx_r_type = BFD_RELOC_IA64_PCREL32LSB;
-         break;
-
-       case BFD_RELOC_IA64_DIR64MSB:
-         fix->fx_r_type = BFD_RELOC_IA64_PCREL64MSB;
-         break;
-
-       case BFD_RELOC_IA64_DIR64LSB:
-         fix->fx_r_type = BFD_RELOC_IA64_PCREL64LSB;
-         break;
-
-       default:
-         break;
-       }
+    switch (fix->fx_r_type)
+      {
+      case BFD_RELOC_IA64_PCREL21B: break;
+      case BFD_RELOC_IA64_PCREL21BI: break;
+      case BFD_RELOC_IA64_PCREL21F: break;
+      case BFD_RELOC_IA64_PCREL21M: break;
+      case BFD_RELOC_IA64_PCREL60B: break;
+      case BFD_RELOC_IA64_PCREL22: break;
+      case BFD_RELOC_IA64_PCREL64I: break;
+      case BFD_RELOC_IA64_PCREL32MSB: break;
+      case BFD_RELOC_IA64_PCREL32LSB: break;
+      case BFD_RELOC_IA64_PCREL64MSB: break;
+      case BFD_RELOC_IA64_PCREL64LSB: break;
+      default:
+       fix->fx_r_type = ia64_gen_real_reloc_type (pseudo_func[FUNC_PC_RELATIVE].u.sym,
+                                              fix->fx_r_type);
+       break;
+      }
     }
   if (fix->fx_addsy)
     {
@@ -11235,7 +11261,7 @@ md_apply_fix3 (fix, valP, seg)
          /* This must be a TAG13 or TAG13b operand.  There are no external
             relocs defined for them, so we must give an error.  */
          as_bad_where (fix->fx_file, fix->fx_line,
-                       "%s must have a constant value",
+                       _("%s must have a constant value"),
                        elf64_ia64_operands[fix->tc_fix_data.opnd].desc);
          fix->fx_done = 1;
          return;
@@ -11275,9 +11301,7 @@ md_apply_fix3 (fix, valP, seg)
    fixup used internally in the assembler.  */
 
 arelent *
-tc_gen_reloc (sec, fixp)
-     asection *sec ATTRIBUTE_UNUSED;
-     fixS *fixp;
+tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
 
@@ -11291,8 +11315,10 @@ tc_gen_reloc (sec, fixp)
   if (!reloc->howto)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
-                   "Cannot represent %s relocation in object file",
+                   _("Cannot represent %s relocation in object file"),
                    bfd_get_reloc_code_name (fixp->fx_r_type));
+      free (reloc);
+      return NULL;
     }
   return reloc;
 }
@@ -11305,10 +11331,7 @@ tc_gen_reloc (sec, fixp)
 #define MAX_LITTLENUMS 5
 
 char *
-md_atof (type, lit, size)
-     int type;
-     char *lit;
-     int *size;
+md_atof (int type, char *lit, int *size)
 {
   LITTLENUM_TYPE words[MAX_LITTLENUMS];
   char *t;
@@ -11340,7 +11363,7 @@ md_atof (type, lit, size)
 
     default:
       *size = 0;
-      return "Bad call to MD_ATOF()";
+      return _("Unrecognized or unsupported floating point constant");
     }
   t = atof_ieee (input_line_pointer, type, words);
   if (t)
@@ -11357,17 +11380,16 @@ md_atof (type, lit, size)
   else
     *size = prec * sizeof (LITTLENUM_TYPE);
 
-  return 0;
+  return NULL;
 }
 
 /* Handle ia64 specific semantics of the align directive.  */
 
 void
-ia64_md_do_align (n, fill, len, max)
-     int n ATTRIBUTE_UNUSED;
-     const char *fill ATTRIBUTE_UNUSED;
-     int len ATTRIBUTE_UNUSED;
-     int max ATTRIBUTE_UNUSED;
+ia64_md_do_align (int n ATTRIBUTE_UNUSED,
+                 const char *fill ATTRIBUTE_UNUSED,
+                 int len ATTRIBUTE_UNUSED,
+                 int max ATTRIBUTE_UNUSED)
 {
   if (subseg_text_p (now_seg))
     ia64_flush_insns ();
@@ -11377,26 +11399,17 @@ ia64_md_do_align (n, fill, len, max)
    of an rs_align_code fragment.  */
 
 void
-ia64_handle_align (fragp)
-     fragS *fragp;
+ia64_handle_align (fragS *fragp)
 {
-  /* Use mfi bundle of nops with no stop bits.  */
-  static const unsigned char le_nop[]
-    = { 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
-  static const unsigned char le_nop_stop[]
-    = { 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
-
   int bytes;
   char *p;
-  const unsigned char *nop;
+  const unsigned char *nop_type;
 
   if (fragp->fr_type != rs_align_code)
     return;
 
   /* Check if this frag has to end with a stop bit.  */
-  nop = fragp->tc_frag_data ? le_nop_stop : le_nop;
+  nop_type = fragp->tc_frag_data ? le_nop_stop : le_nop;
 
   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
   p = fragp->fr_literal + fragp->fr_fix;
@@ -11433,7 +11446,7 @@ ia64_handle_align (fragp)
     }
 
   /* Instruction bundles are always little-endian.  */
-  memcpy (p, nop, 16);
+  memcpy (p, nop_type, 16);
   fragp->fr_var = 16;
 }
 
@@ -11462,7 +11475,7 @@ ia64_float_to_chars_littleendian (char *lit, LITTLENUM_TYPE *words,
 }
 
 void
-ia64_elf_section_change_hook  (void)
+ia64_elf_section_change_hook (void)
 {
   if (elf_section_type (now_seg) == SHT_IA_64_UNWIND
       && elf_linked_to_section (now_seg) == NULL)
@@ -11488,7 +11501,7 @@ struct alias
 {
   char *file;          /* The file where the directive is seen.  */
   unsigned int line;   /* The line number the directive is at.  */
-  const char *name;    /* The orignale name of the symbol.  */
+  const char *name;    /* The original name of the symbol.  */
 };
 
 /* Called for .alias and .secalias directives. If SECTION is 1, it is
@@ -11514,7 +11527,7 @@ dot_alias (int section)
   if (name == end_name)
     {
       as_bad (_("expected symbol name"));
-      discard_rest_of_line ();
+      ignore_rest_of_line ();
       return;
     }
 
@@ -11583,7 +11596,7 @@ dot_alias (int section)
   as_where (&h->file, &h->line);
   h->name = name;
   
-  error_string = hash_jam (ahash, alias, (PTR) h);
+  error_string = hash_jam (ahash, alias, (void *) h);
   if (error_string)
     {
       as_fatal (_("inserting \"%s\" into %s alias hash table failed: %s"),
@@ -11591,7 +11604,7 @@ dot_alias (int section)
       goto out;
     }
 
-  error_string = hash_jam (nhash, name, (PTR) alias);
+  error_string = hash_jam (nhash, name, (void *) alias);
   if (error_string)
     {
       as_fatal (_("inserting \"%s\" into %s name hash table failed: %s"),
@@ -11606,15 +11619,23 @@ out:
 
 /* It renames the original symbol name to its alias.  */
 static void
-do_alias (const char *alias, PTR value)
+do_alias (const char *alias, void *value)
 {
   struct alias *h = (struct alias *) value;
   symbolS *sym = symbol_find (h->name);
 
   if (sym == NULL)
-    as_warn_where (h->file, h->line,
-                  _("symbol `%s' aliased to `%s' is not used"),
-                  h->name, alias);
+    {
+#ifdef TE_VMS
+      /* Uses .alias extensively to alias CRTL functions to same with
+        decc$ prefix. Sometimes function gets optimized away and a
+        warning results, which should be suppressed.  */
+      if (strncmp (alias, "decc$", 5) != 0)
+#endif
+       as_warn_where (h->file, h->line,
+                      _("symbol `%s' aliased to `%s' is not used"),
+                      h->name, alias);
+    }
     else
       S_SET_NAME (sym, (char *) alias);
 }
@@ -11628,7 +11649,7 @@ ia64_adjust_symtab (void)
 
 /* It renames the original section name to its alias.  */
 static void
-do_secalias (const char *alias, PTR value)
+do_secalias (const char *alias, void *value)
 {
   struct alias *h = (struct alias *) value;
   segT sec = bfd_get_section_by_name (stdoutput, h->name);
@@ -11647,3 +11668,138 @@ ia64_frob_file (void)
 {
   hash_traverse (secalias_hash, do_secalias);
 }
+
+#ifdef TE_VMS
+#define NT_VMS_MHD 1
+#define NT_VMS_LNM 2
+
+/* Integrity VMS 8.x identifies it's ELF modules with a standard ELF
+   .note section.  */
+
+/* Manufacture a VMS-like time string.  */
+static void
+get_vms_time (char *Now)
+{
+  char *pnt;
+  time_t timeb;
+
+  time (&timeb);
+  pnt = ctime (&timeb);
+  pnt[3] = 0;
+  pnt[7] = 0;
+  pnt[10] = 0;
+  pnt[16] = 0;
+  pnt[24] = 0;
+  sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
+}
+
+void
+ia64_vms_note (void)
+{
+  char *p;
+  asection *seg = now_seg;
+  subsegT subseg = now_subseg;
+  Elf_Internal_Note i_note;
+  asection *secp = NULL;
+  char *bname;
+  char buf [256];
+  symbolS *sym;
+
+  /* Create the .note section.  */
+
+  secp = subseg_new (".note", 0);
+  bfd_set_section_flags (stdoutput,
+                        secp,
+                        SEC_HAS_CONTENTS | SEC_READONLY);
+
+  /* Module header note.  */
+  bname = xstrdup (lbasename (out_file_name));
+  if ((p = strrchr (bname, '.')))
+    *p = '\0';
+
+  i_note.namesz = 8;
+  i_note.descsz = 40 + strlen (bname);
+  i_note.type = NT_VMS_MHD;
+
+  p = frag_more (sizeof (i_note.namesz));
+  number_to_chars_littleendian (p, i_note.namesz, 8);
+
+  p = frag_more (sizeof (i_note.descsz));
+  number_to_chars_littleendian (p, i_note.descsz, 8);
+
+  p = frag_more (sizeof (i_note.type));
+  number_to_chars_littleendian (p, i_note.type, 8);
+
+  p = frag_more (8);
+  strcpy (p, "IPF/VMS");
+
+  get_vms_time (buf);
+  p = frag_more (17);
+  strcpy (p, buf);
+
+  p = frag_more (17);
+  strcpy (p, "24-FEB-2005 15:00");
+
+  p = frag_more (strlen (bname) + 1);
+  strcpy (p, bname);
+  free (bname);
+
+  p = frag_more (5);
+  strcpy (p, "V1.0");
+
+  frag_align (3, 0, 0);
+
+  /* Language processor name note.  */
+  sprintf (buf, "GNU assembler version %s (%s) using BFD version %s",
+          VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
+
+  i_note.namesz = 8;
+  i_note.descsz = 1 + strlen (buf);
+  i_note.type = NT_VMS_LNM;
+
+  p = frag_more (sizeof (i_note.namesz));
+  number_to_chars_littleendian (p, i_note.namesz, 8);
+
+  p = frag_more (sizeof (i_note.descsz));
+  number_to_chars_littleendian (p, i_note.descsz, 8);
+
+  p = frag_more (sizeof (i_note.type));
+  number_to_chars_littleendian (p, i_note.type, 8);
+
+  p = frag_more (8);
+  strcpy (p, "IPF/VMS");
+
+  p = frag_more (strlen (buf) + 1);
+  strcpy (p, buf);
+
+  frag_align (3, 0, 0);
+
+  secp = subseg_new (".vms_display_name_info", 0);
+  bfd_set_section_flags (stdoutput,
+                        secp,
+                        SEC_HAS_CONTENTS | SEC_READONLY);
+
+  /* This symbol should be passed on the command line and be variable
+     according to language.  */
+  sym = symbol_new ("__gnat_vms_display_name@gnat_demangler_rtl",
+                   absolute_section, 0, &zero_address_frag);
+  symbol_table_insert (sym);
+  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING | BSF_DYNAMIC;
+
+  p = frag_more (4);
+  /* Format 3 of VMS demangler Spec.  */
+  number_to_chars_littleendian (p, 3, 4);
+
+  p = frag_more (4);
+  /* Place holder for symbol table index of above symbol.  */
+  number_to_chars_littleendian (p, -1, 4);
+
+  frag_align (3, 0, 0);
+
+  /* We probably can't restore the current segment, for there likely
+     isn't one yet...  */
+  if (seg && subseg)
+    subseg_set (seg, subseg);
+}
+
+#endif /* TE_VMS */
This page took 0.12653 seconds and 4 git commands to generate.