public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: "Jan Beulich" <JBeulich@novell.com>
To: <binutils@sources.redhat.com>
Subject: [PATCH] ia64: unwind directive handling
Date: Mon, 23 May 2005 10:19:00 -0000	[thread overview]
Message-ID: <s291b7db.099@emea1-mh.id2.novell.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 4470 bytes --]

The main purpose of this patch is to add parser level support for the
optional tags various of the unwind directives permit and to make '}' a
statement separator as is done in ias. Along with that it consolidates
some redundant functionality, tightens operand checking for many unwind
directives, and fixes some other bugs.

Separating these into distinct patches would be very cumbersome, so I hope
applying this in one piece is acceptable (various pieces have already been
broken out and submitted previously).

There is one slightly odd thing in here: .prologue doesn't (as per the Intel
spec) allow an immediate as the second operand, but gcc for whatever reason
uses exactly that non-standard form. Thus the warning of this form being
deprecated had to be masked by an option not on by default; I chose 
unwind_check_error here rather than adding yet another controlling command
line option.

The actual handling of tags used with unwind directives still needs to be
implemented. Similarly, proper handling of .save.x directives with more
than one bit set in their operands needs to be done.

Built and tested on ia64-unknown-linux-gnu.

Jan

binutils/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* unwind-ia64.c (unw_decode_p7_p10): Add psp_psprel to P8 handling.

gas/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* config/tc-ia64.h (unw_record_type): Add psp_psprel.
	* config/tc-ia64.c (line_separator_chars): Add '}'.
	(output_P8_format): Handle psp_psprel.
	(output_psp_psprel): New.
	(output_spill_psprel, output_spill_psprel_p): Combine.
	(output_spill_sprel, output_spill_sprel_p): Combine.
	(output_spill_reg, output_spill_regp_p): Combine.
	(process_one_record): Handle psp_psprel.
	(parse_predicate_and_operand): New.
	(convert_expr_to_ab_reg): Two new parameters. Return void. Always
	initialize output values. Emit diagnostic case here.
	(convert_expr_to_xy_reg): Likewise. Don't allow r0, f0, and f1.
	(add_unwind_entry): New second parameter. Parse optional tag, emit
	warning about further support for it otherwise being missing. Check
	end-of-line when requested.
	(dot_fframe): Clear operand when wrong. Allow tag.
	(dot_vframe): Likewise.
	(dot_vframesp): Likewise.
	(dot_vframepsp): Likewise.
	(dot_altrp): Likewise.
	(dot_save): Likewise. Let default case fall through to also go
	through add_unwind_entry.
	(dot_savemem): Likewise.
	(dot_restore): Don't return when wrong operand. Allow tag.
	(dot_spillreg, dot_spillreg_p): Combine. Simplify by using
	parse_predicate_and_operand and the new arguments to
	convert_expr_to_ab_reg and convert_expr_to_xy_reg. Don't return
	when wrong operand. Allow tag.
	(dot_restorereg, dot_restorereg_p): Likewise.
	(dot_spillmem, dot_spillmem_p): Likewise.
	(dot_saveg): Clear operand when wrong. Perform tighter operand
	checks. Allow tag.
	(dot_savef): Likewise.
	(dot_saveb): Likewise.
	(dot_savegf): Likewise.
	(dot_spill): Remove end-of-line check. 	Combine. Simplify by using
	parse_predicate_and_operand and the new arguments to
	convert_expr_to_ab_reg and convert_expr_to_xy_reg. Don't return
	when wrong operand. Allow tag.
	(popcount): New.
	(dot_label_state): Don't return when wrong operand.
	(dot_copy_state): Likewise.
	(dot_unwabi): Likewise. Check if in prologue.
	(dot_body): Don't call demand_empty_rest_of_line.
	(dot_prologue): Type of mask and grsave is unsigned. Perform tighter
	operand checks.
	(md_pseudo_table): Also use dot_restorereg for .restorereg.p. Also
	use dot_spillreg for .spillreg.p. Also use dot_spillmem for
	.spillpsp.p and .spillsp.p.
	(parse_operand): New second parameter. Don't deal with '}' here
	anymore. Don't advance past end-of-line.
	(parse_operands): Pass second argument to parse_operand.
	(ia64_start_line): Prevent out-of-bounds access through
	input_line_pointer. Deal with '}' here.
	(ia64_unrecognized_line): Don't deal with '}' here.
	(dot_alias): Use ignore_rest_of_line not its deprecated alias
	discard_rest_of_line.

gas/testsuite/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* gas/ia64/group-2.s: Use register as second operand of .prologue.
	* gas/ia64/unwind-err.s: Add check for .vframesp and .vframepsp.
	* gas/ia64/unwind-err.l: Adjust.
	* gas/ia64/strange.[sd]: New.
	* gas/ia64/unwind-bad.[sl]: New.
	* gas/ia64/unwind-ok.[sd]: New.
	* gas/ia64/ia64.exp: Run new tests.

(actual patch too large for inlining; attached)

[-- Attachment #2: binutils-mainline-ia64-unwind.patch --]
[-- Type: text/plain, Size: 78451 bytes --]

The main purpose of this patch is to add parser level support for the
optional tags various of the unwind directives permit and to make '}' a
statement separator as is done in ias. Along with that it consolidates
some redundant functionality, tightens operand checking for many unwind
directives, and fixes some other bugs.

Separating these into distinct patches would be very cumbersome, so I hope
applying this in one piece is acceptable (various pieces have already been
broken out and submitted previously).

There is one slightly odd thing in here: .prologue doesn't (as per the Intel
spec) allow an immediate as the second operand, but gcc for whatever reason
uses exactly that non-standard form. Thus the warning of this form being
deprecated had to be masked by an option not on by default; I chose 
unwind_check_error here rather than adding yet another controlling command
line option.

The actual handling of tags used with unwind directives still needs to be
implemented. Similarly, proper handling of .save.x directives with more
than one bit set in their operands needs to be done.

Built and tested on ia64-unknown-linux-gnu.

Jan

binutils/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* unwind-ia64.c (unw_decode_p7_p10): Add psp_psprel to P8 handling.

gas/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* config/tc-ia64.h (unw_record_type): Add psp_psprel.
	* config/tc-ia64.c (line_separator_chars): Add '}'.
	(output_P8_format): Handle psp_psprel.
	(output_psp_psprel): New.
	(output_spill_psprel, output_spill_psprel_p): Combine.
	(output_spill_sprel, output_spill_sprel_p): Combine.
	(output_spill_reg, output_spill_regp_p): Combine.
	(process_one_record): Handle psp_psprel.
	(parse_predicate_and_operand): New.
	(convert_expr_to_ab_reg): Two new parameters. Return void. Always
	initialize output values. Emit diagnostic case here.
	(convert_expr_to_xy_reg): Likewise. Don't allow r0, f0, and f1.
	(add_unwind_entry): New second parameter. Parse optional tag, emit
	warning about further support for it otherwise being missing. Check
	end-of-line when requested.
	(dot_fframe): Clear operand when wrong. Allow tag.
	(dot_vframe): Likewise.
	(dot_vframesp): Likewise.
	(dot_vframepsp): Likewise.
	(dot_altrp): Likewise.
	(dot_save): Likewise. Let default case fall through to also go
	through add_unwind_entry.
	(dot_savemem): Likewise.
	(dot_restore): Don't return when wrong operand. Allow tag.
	(dot_spillreg, dot_spillreg_p): Combine. Simplify by using
	parse_predicate_and_operand and the new arguments to
	convert_expr_to_ab_reg and convert_expr_to_xy_reg. Don't return
	when wrong operand. Allow tag.
	(dot_restorereg, dot_restorereg_p): Likewise.
	(dot_spillmem, dot_spillmem_p): Likewise.
	(dot_saveg): Clear operand when wrong. Perform tighter operand
	checks. Allow tag.
	(dot_savef): Likewise.
	(dot_saveb): Likewise.
	(dot_savegf): Likewise.
	(dot_spill): Remove end-of-line check. 	Combine. Simplify by using
	parse_predicate_and_operand and the new arguments to
	convert_expr_to_ab_reg and convert_expr_to_xy_reg. Don't return
	when wrong operand. Allow tag.
	(popcount): New.
	(dot_label_state): Don't return when wrong operand.
	(dot_copy_state): Likewise.
	(dot_unwabi): Likewise. Check if in prologue.
	(dot_body): Don't call demand_empty_rest_of_line.
	(dot_prologue): Type of mask and grsave is unsigned. Perform tighter
	operand checks.
	(md_pseudo_table): Also use dot_restorereg for .restorereg.p. Also
	use dot_spillreg for .spillreg.p. Also use dot_spillmem for
	.spillpsp.p and .spillsp.p.
	(parse_operand): New second parameter. Don't deal with '}' here
	anymore. Don't advance past end-of-line.
	(parse_operands): Pass second argument to parse_operand.
	(ia64_start_line): Prevent out-of-bounds access through
	input_line_pointer. Deal with '}' here.
	(ia64_unrecognized_line): Don't deal with '}' here.
	(dot_alias): Use ignore_rest_of_line not its deprecated alias
	discard_rest_of_line.

gas/testsuite/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* gas/ia64/group-2.s: Use register as second operand of .prologue.
	* gas/ia64/unwind-err.s: Add check for .vframesp and .vframepsp.
	* gas/ia64/unwind-err.l: Adjust.
	* gas/ia64/strange.[sd]: New.
	* gas/ia64/unwind-bad.[sl]: New.
	* gas/ia64/unwind-ok.[sd]: New.
	* gas/ia64/ia64.exp: Run new tests.

--- /home/jbeulich/src/binutils/mainline/2005-05-18/binutils/unwind-ia64.c	2005-05-09 08:31:30.000000000 +0200
+++ 2005-05-18/binutils/unwind-ia64.c	2005-05-20 16:41:30.000000000 +0200
@@ -883,6 +883,9 @@ unw_decode_p7_p10 (const unsigned char *
 	    t = unw_decode_uleb128 (&dp);
 	    switch (r)
 	      {
+	      case 0:
+		UNW_DEC_REG_PSPREL ("P8", UNW_REG_PSP, t, arg);
+		break;
 	      case 1:
 		UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
 		break;
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/config/tc-ia64.c	2005-05-09 08:31:38.000000000 +0200
+++ 2005-05-18/gas/config/tc-ia64.c	2005-05-23 11:47:24.643235655 +0200
@@ -193,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.  */
@@ -762,7 +760,6 @@ 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));
@@ -774,8 +771,6 @@ 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));
@@ -805,14 +800,14 @@ 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 void add_unwind_entry PARAMS((unw_rec_list *, int));
 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 int parse_operand PARAMS ((expressionS *, int));
 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));
@@ -879,6 +874,7 @@ static unw_rec_list *output_body PARAMS 
 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_psprel 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));
@@ -933,15 +929,11 @@ static unw_rec_list *output_unwabi PARAM
 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,
+static unw_rec_list *output_spill_psprel PARAMS ((unsigned int, unsigned int, unsigned int,
 						    unsigned int));
-static unw_rec_list *output_spill_sprel_p PARAMS ((unsigned int, unsigned int, unsigned int,
+static unw_rec_list *output_spill_sprel 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));
@@ -952,8 +944,9 @@ static unsigned long slot_index PARAMS (
 					 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 int parse_predicate_and_operand PARAMS ((expressionS *, unsigned *, const char *));
+static void convert_expr_to_ab_reg PARAMS ((const expressionS *, unsigned int *, unsigned int *, const char *, int));
+static void convert_expr_to_xy_reg PARAMS ((const expressionS *, unsigned int *, unsigned int *, const char *, 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));
@@ -1471,6 +1464,9 @@ output_P8_format (f, rtype, t)
   bytes[0] = UNW_P8;
   switch (rtype)
     {
+    case psp_psprel:
+      r = 0;
+      break;
     case rp_sprel:
       r = 1;
       break;
@@ -1818,6 +1812,15 @@ output_psp_gr (gr)
 }
 
 static unw_rec_list *
+output_psp_psprel (offset)
+     unsigned int offset;
+{
+  unw_rec_list *ptr = alloc_record (psp_psprel);
+  ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset);
+  return ptr;
+}
+
+static unw_rec_list *
 output_psp_sprel (offset)
      unsigned int offset;
 {
@@ -2286,39 +2289,13 @@ 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)
+output_spill_psprel (ab, reg, offset, predicate)
      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);
@@ -2327,13 +2304,13 @@ output_spill_psprel_p (ab, reg, offset, 
 }
 
 static unw_rec_list *
-output_spill_sprel_p (ab, reg, offset, predicate)
+output_spill_sprel (ab, reg, offset, predicate)
      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;
@@ -2342,29 +2319,14 @@ output_spill_sprel_p (ab, reg, offset, p
 }
 
 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;
-{
-  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)
+output_spill_reg (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;
@@ -2472,6 +2434,9 @@ process_one_record (ptr, f)
     case spill_base:
       output_P7_format (f, ptr->r.type, ptr->r.record.p.pspoff, 0);
       break;
+    case psp_psprel:
+      output_P8_format (f, ptr->r.type, ptr->r.record.p.pspoff);
+      break;
     case rp_sprel:
     case pfs_sprel:
     case preds_sprel:
@@ -2978,17 +2943,43 @@ ia64_convert_frag (fragS *frag)
 }
 
 static int
-convert_expr_to_ab_reg (e, ab, regp)
-     expressionS *e;
+parse_predicate_and_operand (e, qp, po)
+     expressionS * e;
+     unsigned * qp;
+     const char * po;
+{
+  int sep = parse_operand (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 (e, ',');
+  else
+    e->X_op = O_absent;
+  return sep;
+}
+
+static void
+convert_expr_to_ab_reg (e, ab, regp, po, n)
+     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;
@@ -3023,31 +3014,33 @@ 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;
+static void
+convert_expr_to_xy_reg (e, xy, regp, po, n)
+     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;
@@ -3058,8 +3051,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
@@ -3185,8 +3180,9 @@ in_body (const char *directive)
 }
 
 static void
-add_unwind_entry (ptr)
+add_unwind_entry (ptr, sep)
      unw_rec_list *ptr;
+     int sep;
 {
   if (unwind.tail)
     unwind.tail->next = ptr;
@@ -3197,6 +3193,28 @@ add_unwind_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
@@ -3204,16 +3222,19 @@ dot_fframe (dummy)
      int dummy ATTRIBUTE_UNUSED;
 {
   expressionS e;
+  int sep;
 
   if (!in_prologue ("fframe"))
     return;
 
-  parse_operand (&e);
+  sep = parse_operand (&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
@@ -3222,20 +3243,21 @@ dot_vframe (dummy)
 {
   expressionS e;
   unsigned reg;
+  int sep;
 
   if (!in_prologue ("vframe"))
     return;
 
-  parse_operand (&e);
+  sep = parse_operand (&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);
 }
 
 static void
@@ -3243,18 +3265,19 @@ dot_vframesp (dummy)
      int dummy ATTRIBUTE_UNUSED;
 {
   expressionS e;
+  int sep;
 
   if (!in_prologue ("vframesp"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op == O_constant)
+  sep = 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));
+      as_bad ("Operand to .vframesp must be a constant (sp-relative offset)");
+      e.X_add_number = 0;
     }
-  else
-    as_bad ("Operand to .vframesp must be a constant (sp-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
@@ -3262,18 +3285,19 @@ dot_vframepsp (dummy)
      int dummy ATTRIBUTE_UNUSED;
 {
   expressionS e;
+  int sep;
 
   if (!in_prologue ("vframepsp"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op == O_constant)
+  sep = 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));
+      as_bad ("Operand to .vframepsp must be a constant (psp-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_psprel (e.X_add_number), NOT_A_CHAR);
 }
 
 static void
@@ -3281,106 +3305,105 @@ dot_save (dummy)
      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 (&e1, ',');
+  if (sep == ',')
+    sep = parse_operand (&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);
+      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);
+      break;
+    default:
+      as_bad ("First operand to .save not a valid register");
+    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);
+      break;
+    case REG_PRIUNAT:
+      add_unwind_entry (output_priunat_when_gr (), sep);
+      add_unwind_entry (output_priunat_gr (reg2), NOT_A_CHAR);
+      break;
     }
-  else
-    as_bad ("First operand not a register");
 }
 
 static void
 dot_restore (dummy)
      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 (&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 (&e2, ',');
       if (e2.X_op != O_constant || e2.X_add_number < 0)
 	{
 	  as_bad ("Second operand to .restore must be a constant >= 0");
-	  return;
+	  e2.X_add_number = 0;
 	}
       ecount = e2.X_add_number;
     }
@@ -3391,10 +3414,10 @@ dot_restore (dummy)
     {
       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;
@@ -3403,58 +3426,27 @@ dot_restore (dummy)
 }
 
 static void
-dot_restorereg (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  unsigned int 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;
+dot_restorereg (pred)
+     int pred;
 {
   unsigned int qp, ab, reg;
-  expressionS e1, e2;
+  expressionS e;
   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 (&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[] =
@@ -3582,7 +3574,7 @@ generate_unwind_image (const segT text_s
 
   /* 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.  */
@@ -3698,12 +3690,14 @@ dot_altrp (dummy)
   if (!in_prologue ("altrp"))
     return;
 
-  parse_operand (&e);
+  parse_operand (&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
@@ -3713,182 +3707,229 @@ dot_savemem (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 (&e1, ',');
+  if (sep == ',')
+    sep = parse_operand (&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;
+    default:
+      as_bad ("First operand to .%s not a valid register", po);
+    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;
     }
-  else
-    as_bad ("First operand not a register");
 }
 
+/* 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
+
 static void
 dot_saveg (dummy)
      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 (&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 (&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;
 {
-  expressionS e1;
-  int sep;
+  expressionS e;
 
   if (!in_prologue ("save.f"))
     return;
 
-  sep = parse_operand (&e1);
+  parse_operand (&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;
 {
-  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 (&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 (&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;
 	}
-      add_unwind_entry (output_br_gr (brmask, e2.X_add_number));
+      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, 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
@@ -3896,23 +3937,38 @@ dot_savegf (dummy)
      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.");
+  if (parse_operand (&e1, ',') == ',')
+    parse_operand (&e2, 0);
   else
-    {
-      int grmask = e1.X_add_number;
-      int frmask = e2.X_add_number;
-      add_unwind_entry (output_frgr_mem (grmask, frmask));
-    }
+    e2.X_op = O_absent;
+
+  if (e1.X_op != O_constant
+      || e1.X_add_number < 0
+      || e1.X_add_number > 0xf)
+    {
+      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 (e2.X_op != O_constant
+      || e2.X_add_number < 0
+      || e2.X_add_number > 0xfffff)
+    {
+      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_frgr_mem (e1.X_add_number, e2.X_add_number), 0);
 }
 
 static void
@@ -3920,201 +3976,90 @@ 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 ();
+  parse_operand (&e, 0);
 
   if (e.X_op != O_constant)
-    as_bad ("Operand to .spill must be a constant");
-  else
-    add_unwind_entry (output_spill_base (e.X_add_number));
-}
-
-static void
-dot_spillreg (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  int sep;
-  unsigned int 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))
-    {
-      as_bad ("First operand to .spillreg must be a preserved register");
-      return;
-    }
-
-  if (!convert_expr_to_xy_reg (&e2, &xy, &treg))
     {
-      as_bad ("Second operand to .spillreg must be a register");
-      return;
+      as_bad ("Operand to .spill must be a constant");
+      e.X_add_number = 0;
     }
-
-  add_unwind_entry (output_spill_reg (ab, reg, treg, xy));
+  add_unwind_entry (output_spill_base (e.X_add_number), 0);
 }
 
 static void
-dot_spillmem (psprel)
-     int psprel;
+dot_spillreg (pred)
+     int pred;
 {
-  expressionS e1, e2;
   int sep;
-  unsigned int ab, reg;
+  unsigned int qp, ab, xy, reg, treg;
+  expressionS e;
+  const char * const po = pred ? "spillreg.p" : "spillreg";
 
-  if (!in_procedure ("spillmem"))
+  if (!in_procedure (po))
     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;
-    }
-
-  if (e2.X_op != O_constant)
-    {
-      as_bad ("Second operand to .spill%s must be a constant",
-	      psprel ? "psp" : "sp");
-      return;
-    }
-
-  if (psprel)
-    add_unwind_entry (output_spill_psprel (ab, reg, e2.X_add_number));
+  if (pred)
+    sep = parse_predicate_and_operand (&e, &qp, po);
   else
-    add_unwind_entry (output_spill_sprel (ab, reg, e2.X_add_number));
-}
-
-static void
-dot_spillreg_p (dummy)
-     int dummy ATTRIBUTE_UNUSED;
-{
-  int sep;
-  unsigned int ab, xy, reg, treg;
-  expressionS e1, e2, e3;
-  unsigned int qp;
-
-  if (!in_procedure ("spillreg.p"))
-    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;
+      sep = parse_operand (&e, ',');
+      qp = 0;
     }
+  convert_expr_to_ab_reg (&e, &ab, &reg, po, 1 + pred);
 
-  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))
-    {
-      as_bad ("Second operand to .spillreg.p must be a preserved register");
-      return;
-    }
-
-  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 (&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)
+dot_spillmem (psprel)
      int psprel;
 {
-  expressionS e1, e2, e3;
-  int sep;
-  unsigned int ab, reg;
-  unsigned int qp;
-
-  if (!in_procedure ("spillmem.p"))
-    return;
-
-  sep = parse_operand (&e1);
-  if (sep != ',')
-    {
-      as_bad ("Second operand missing");
-      return;
-    }
-
-  parse_operand (&e2);
-  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 (&e3);
+  if (pred)
+    po = (psprel = ~psprel) ? "spillpsp.p" : "spillsp.p";
+  else
+    po = psprel ? "spillpsp" : "spillsp";
 
-  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 (&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 (&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
@@ -4181,14 +4126,15 @@ dot_label_state (dummy)
   if (!in_body ("label_state"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op != O_constant)
+  parse_operand (&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;
+      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
@@ -4200,14 +4146,15 @@ dot_copy_state (dummy)
   if (!in_body ("copy_state"))
     return;
 
-  parse_operand (&e);
-  if (e.X_op != O_constant)
+  parse_operand (&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;
+      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
@@ -4217,32 +4164,28 @@ dot_unwabi (dummy)
   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 (&e1, ',');
+  if (sep == ',')
+    parse_operand (&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;
+      e1.X_add_number = 0;
     }
 
   if (e2.X_op != O_constant)
     {
       as_bad ("Second operand to .unwabi must be a constant");
-      return;
+      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
@@ -4324,16 +4267,14 @@ dot_body (dummy)
   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;
 {
-  unsigned char sep;
-  int mask = 0, grsave = 0;
+  unsigned mask = 0, grsave = 0;
 
   if (!in_procedure ("prologue"))
     return;
@@ -4348,33 +4289,49 @@ dot_prologue (dummy)
 
   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 ();
-
-      if (e1.X_op == O_constant)
-	{
-	  mask = e1.X_add_number;
+      expressionS e;
+      int n, sep = parse_operand (&e, ',');
 
-	  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 (&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;
@@ -5282,7 +5234,7 @@ const pseudo_typeS md_pseudo_table[] =
     { "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 },
@@ -5296,9 +5248,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 },
@@ -5991,27 +5943,19 @@ operand_match (idesc, index, e)
 }
 
 static int
-parse_operand (e)
+parse_operand (e, more)
      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++;
-
-  if (sep == '}')
-    {
-      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';
-    }
+  expression (e);
+  sep = *input_line_pointer;
+  if (more && (sep == ',' || sep == more))
+    ++input_line_pointer;
   return sep;
 }
 
@@ -6070,7 +6014,7 @@ parse_operands (idesc)
     {
       if (i < NELEMS (CURR_SLOT.opnd)) 
 	{
-	  sep = parse_operand (CURR_SLOT.opnd + i);
+	  sep = parse_operand (CURR_SLOT.opnd + i, '=');
 	  if (CURR_SLOT.opnd[i].X_op == O_absent)
 	    break;
 	}
@@ -6078,7 +6022,7 @@ parse_operands (idesc)
 	{
 	  expressionS dummy;
 
-	  sep = parse_operand (&dummy);
+	  sep = parse_operand (&dummy, '=');
 	  if (dummy.X_op == O_absent)
 	    break;
 	}
@@ -6123,7 +6067,7 @@ parse_operands (idesc)
 	  /* 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);
+	  sep = parse_operand (CURR_SLOT.opnd + 0, '=');
 	  if (sep != '=')
 	    --num_outputs;	/* force error */
 	  input_line_pointer = saved_input_pointer;
@@ -7548,10 +7487,17 @@ ia64_end_of_source ()
 void
 ia64_start_line ()
 {
+  static int first;
+
   if (md.qp.X_op == O_register)
     as_bad ("qualifying predicate not followed by instruction");
   md.qp.X_op = O_absent;
 
+  if (!first) {
+    first = 1;
+    return;
+  }
+
   if (ignore_input ())
     return;
 
@@ -7570,6 +7516,21 @@ ia64_start_line ()
       else
 	insn_group_break (1, 0, 0);
     }
+  else if (input_line_pointer[-1] == '}')
+    {
+      if (!md.manual_bundling)
+	as_warn ("Found '}' when manual bundling is off");
+      else
+	PREV_SLOT.manual_bundling_off = 1;
+      md.manual_bundling = 0;
+
+      /* switch back to automatic mode, if applicable */
+      if (md.detect_dv
+	  && md.explicit_mode
+	  && !md.mode_explicitly_set
+	  && !md.default_explicit_mode)
+	dot_dv_mode ('A');
+    }
 }
 
 /* This is a hook for ia64_frob_label, so that it can distinguish tags from
@@ -7620,32 +7581,6 @@ ia64_unrecognized_line (ch)
 	}
       return 1;
 
-    case '}':
-      if (!md.manual_bundling)
-	as_warn ("Found '}' when manual bundling is off");
-      else
-	PREV_SLOT.manual_bundling_off = 1;
-      md.manual_bundling = 0;
-
-      /* switch back to automatic mode, if applicable */
-      if (md.detect_dv
-	  && md.explicit_mode
-	  && !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] == '{')
-	{
-	  input_line_pointer++;
-	  return ia64_unrecognized_line ('{');
-	}
-
-      demand_empty_rest_of_line ();
-      return 1;
-
     case '[':
       {
 	char *s;
@@ -11665,7 +11601,7 @@ dot_alias (int section)
   if (name == end_name)
     {
       as_bad (_("expected symbol name"));
-      discard_rest_of_line ();
+      ignore_rest_of_line ();
       return;
     }
 
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/config/tc-ia64.h	2005-05-06 08:24:28.000000000 +0200
+++ 2005-05-18/gas/config/tc-ia64.h	2005-05-20 16:41:30.000000000 +0200
@@ -213,9 +213,9 @@ extern void ia64_convert_frag (fragS *);
 
 typedef enum
 {
-  prologue, prologue_gr, body, mem_stack_f, mem_stack_v, psp_gr, psp_sprel,
-  rp_when, rp_gr, rp_br, rp_psprel, rp_sprel, pfs_when, pfs_gr, pfs_psprel,
-  pfs_sprel, preds_when, preds_gr, preds_psprel, preds_sprel,
+  prologue, prologue_gr, body, mem_stack_f, mem_stack_v, psp_gr, psp_psprel,
+  psp_sprel, rp_when, rp_gr, rp_br, rp_psprel, rp_sprel, pfs_when, pfs_gr,
+  pfs_psprel, pfs_sprel, preds_when, preds_gr, preds_psprel, preds_sprel,
   fr_mem, frgr_mem, gr_gr, gr_mem, br_mem, br_gr, spill_base, spill_mask,
   unat_when, unat_gr, unat_psprel, unat_sprel, lc_when, lc_gr, lc_psprel,
   lc_sprel, fpsr_when, fpsr_gr, fpsr_psprel, fpsr_sprel,
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/group-2.s	2005-05-08 00:19:37.000000000 +0200
+++ 2005-05-18/gas/testsuite/gas/ia64/group-2.s	2005-05-20 16:53:54.000000000 +0200
@@ -1,6 +1,6 @@
 	.section	.gnu.linkonce.t.foo,"axG",@progbits,foo,comdat
 	.proc foo#
 foo:
-	.prologue 12, 33
+	.prologue 12, r33
 	;;
 	.endp foo#
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/ia64.exp	2005-05-09 08:31:39.000000000 +0200
+++ 2005-05-18/gas/testsuite/gas/ia64/ia64.exp	2005-05-23 11:46:47.236009550 +0200
@@ -81,7 +81,10 @@ if [istarget "ia64-*"] then {
     run_list_test "pound" "-al"
     run_list_test "proc" "-munwind-check=error"
     run_list_test "slot2" ""
+    run_dump_test "strange"
+    run_list_test "unwind-bad" ""
     run_list_test "unwind-err" "-munwind-check=error"
+    run_dump_test "unwind-ok"
     run_dump_test "operand-or"
     run_list_test "hint.b-err" ""
     run_list_test "hint.b-warn" "-mhint.b=warning"
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/strange.d	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/strange.d	2005-05-19 16:37:51.000000000 +0200
@@ -0,0 +1,13 @@
+#objdump: -s
+#name: ia64 strange
+
+.*: +file format .*
+
+Contents of section .text:
+ 0000 0c000000 01001000 00020000 00000400  .*
+ 0010 04000000 01000000 00000020 00000400  .*
+ 0020 0c000000 01002000 00020000 00000400  .*
+ 0030 04000000 01000000 00000040 00000400  .*
+ 0040 1d000000 01003000 00020080 00008400  .*
+Contents of section .data:
+ 0000 ffff                                 .*              
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/strange.s	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/strange.s	2005-05-19 16:35:55.000000000 +0200
@@ -0,0 +1,12 @@
+.explicit
+.text
+_start:
+{.mfi
+	nop.f		1 } nop.x 1
+{.mfi
+	nop.f		2
+}	nop.x		2
+{.mfb
+	nop.f		3
+	br.ret.sptk	rp
+.xdata1 .data, -1 } .xdata1 .data, -1
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-bad.l	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-bad.l	2005-05-20 16:34:10.000000000 +0200
@@ -0,0 +1,51 @@
+.*: Assembler messages:
+.*:8: Error: First operand to \.save\.g must be a positive 4-bit constant
+.*:10: Error: First operand to \.save\.g must be a positive 4-bit constant
+.*:12: Error: First operand to \.save\.g must be a positive 4-bit constant
+#FIXME .*:16: Error: Previous spill incomplete
+#FIXME .*:18: Error: Register r4 was already saved
+.*:20: Error: Operand to \.save\.f must be a positive 20-bit constant
+.*:22: Error: Operand to \.save\.f must be a positive 20-bit constant
+.*:24: Error: Operand to \.save\.f must be a positive 20-bit constant
+#FIXME .*:28: Error: Previous spill incomplete
+#FIXME .*:30: Error: Register f2 was already saved
+.*:32: Error: First operand to \.save\.b must be a positive 5-bit constant
+.*:34: Error: First operand to \.save\.b must be a positive 5-bit constant
+.*:36: Error: First operand to \.save\.b must be a positive 5-bit constant
+#FIXME .*:40: Error: Previous spill incomplete
+#FIXME .*:42: Error: Register b1 was already saved
+.*:44: Error: Operand 2 to \.spillreg must be a writable register
+.*:46: Error: Operand 1 to \.spillreg must be a preserved register
+.*:48: Error: Operand 1 to \.spillreg must be a preserved register
+.*:50: Error: Operand 1 to \.spillreg must be a preserved register
+.*:52: Error: Operand 2 to \.spillreg must be a writable register
+.*:54: Error: Operand 2 to \.spillreg must be a writable register
+.*:56: Error: Operand 1 to \.spillreg must be a preserved register
+#FIXME .*:58: Error: Floating point register cannot be spilled to general register
+#FIXME .*:60: Error: Floating point register cannot be spilled to branch register
+.*:62: Warning: Pointless use of p0 as first operand to \.spillreg\.p
+.*:64: Error: Operand 3 to \.spillreg.p must be a writable register
+.*:66: Error: Operand 3 to \.spillreg.p must be a writable register
+.*:68: Warning: Pointless use of p0 as first operand to \.restorereg\.p
+.*:78: Error: Operands to \.save\.gf may not be both zero
+.*:80: Error: First operand to \.save\.gf must be a non-negative 4-bit constant
+.*:82: Error: Second operand to \.save\.gf must be a non-negative 20-bit constant
+.*:84: Error: First operand to \.save\.gf must be a non-negative 4-bit constant
+.*:86: Error: Second operand to \.save\.gf must be a non-negative 20-bit constant
+#FIXME .*:90: Error: Previous spill incomplete
+#FIXME .*:92: Error: Register r4 was already saved
+#FIXME .*:94: Error: Register f2 was already saved
+.*:98: Error: Epilogue count of 2 exceeds number of nested prologues \(1\)
+.*:100: Error: Missing \.label_state 2
+.*:108: Error: First operand to \.save\.g must be a positive 4-bit constant
+#FIXME .*:110: Error: Second operand to \.save\.g must be a writable general registers
+.*:112: Error: Second operand to \.save\.g must be the first of 2 general registers
+.*:115: Error: First operand to \.save\.b must be a positive 5-bit constant
+#FIXME .*:117: Error: Second operand to \.save\.b must be a writable general registers
+.*:119: Error: Second operand to \.save\.b must be the first of 2 general registers
+.*:128: Error: First operand to \.prologue must be a positive 4-bit constant
+.*:134: Warning: Pointless use of zero first operand to \.prologue
+.*:140: Error: First operand to \.prologue must be a positive 4-bit constant
+#FIXME .*:141: Error: Operand to \.vframe must be a writable general registers
+#FIXME .*:147: Error: Second operand to \.prologue must be a writable general registers
+.*:153: Error: Second operand to \.prologue must be the first of 2 general registers
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-bad.s	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-bad.s	2005-05-20 16:23:42.000000000 +0200
@@ -0,0 +1,155 @@
+.text
+
+.proc full1
+full1:
+
+.prologue
+.spill 0
+.save.g 0
+	nop		0
+.save.g 0x10
+	nop		0
+.save.g -1
+	nop		0
+.save.g 0x3
+	nop		0
+.save.g 0x4
+	nop		0
+.save.g 0x1
+	nop		0
+.save.f 0
+	nop		0
+.save.f 0x100000
+	nop		0
+.save.f -1
+	nop		0
+.save.f 0x3
+	nop		0
+.save.f 0x4
+	nop		0
+.save.f 0x1
+	nop		0
+.save.b 0
+	nop		0
+.save.b 0x20
+	nop		0
+.save.b -1
+	nop		0
+.save.b 0x3
+	nop		0
+.save.b 0x4
+	nop		0
+.save.b 0x1
+	nop		0
+.spillreg r4, r0
+	nop		0
+.spillreg r3, r2
+	nop		0
+.spillreg r8, r9
+	nop		0
+.spillreg b6, r10
+	nop		0
+.spillreg f2, f0
+	nop		0
+.spillreg f3, f1
+	nop		0
+.spillreg f6, f7
+	nop		0
+.spillreg f4, r11
+	nop		0
+.spillreg f5, b0
+	nop		0
+.spillreg.p p0, r4, r3
+	nop		0
+.spillreg.p p1, r4, r0
+	nop		0
+.spillreg.p p1, f16, f0
+	nop		0
+.restorereg.p p0, r4
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp full1
+
+.proc full2
+full2:
+.prologue
+.spill 0
+.save.gf 0, 0
+	nop		0
+.save.gf 0x10, 0
+	nop		0
+.save.gf 0, 0x100000
+	nop		0
+.save.gf ~0, 0
+	nop		0
+.save.gf 0, ~0
+	nop		0
+.save.gf 1, 1
+	nop		0
+.save.gf 2, 0
+	nop		0
+.save.gf 1, 0
+	nop		0
+.save.gf 0, 1
+	nop		0
+.body
+.label_state 1
+.restore sp, 1
+	nop.x		0
+.copy_state 2
+	br.ret.sptk	rp
+.endp full2
+
+.proc full3
+full3:
+.prologue
+.spill 0
+.save.g 0x10, r16
+	nop		0
+.save.g 0x01, r0
+	nop		0
+.save.g 0x06, r127
+	nop		0
+	nop		0
+.save.b 0x20, r16
+	nop		0
+.save.b 0x01, r0
+	nop		0
+.save.b 0x18, r127
+	nop		0
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp full3
+
+.proc simple1
+simple1:
+.prologue 0x10, r2
+	br.ret.sptk	rp
+.endp simple1
+
+.proc simple2
+simple2:
+.prologue 0, r2
+	br.ret.sptk	rp
+.endp simple2
+
+.proc simple3
+simple3:
+.prologue -1, r2
+.vframe r0
+	br.ret.sptk	rp
+.endp simple3
+
+.proc simple4
+simple4:
+.prologue 0x1, r0
+	br.ret.sptk	rp
+.endp simple4
+
+.proc simple5
+simple5:
+.prologue 0xc, r127
+	br.ret.sptk	rp
+.endp simple5
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-err.l	2005-02-08 10:38:38.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-err.l	2005-05-20 16:41:30.000000000 +0200
@@ -8,27 +8,29 @@
 .*:7: Error: .body outside of procedure
 .*:8: Error: .spillreg outside of procedure
 .*:9: Error: .spillreg.p outside of procedure
-.*:10: Error: .spillmem outside of procedure
-.*:11: Error: .spillmem.p outside of procedure
-.*:12: Error: .spillmem outside of procedure
-.*:13: Error: .spillmem.p outside of procedure
+.*:10: Error: .spillsp outside of procedure
+.*:11: Error: .spillsp.p outside of procedure
+.*:12: Error: .spillpsp outside of procedure
+.*:13: Error: .spillpsp.p outside of procedure
 .*:14: Error: .restorereg outside of procedure
 .*:15: Error: .restorereg.p outside of procedure
 .*:24: Error: .label_state outside of body region
 .*:25: Error: .copy_state outside of body region
 .*:26: Error: .fframe outside of prologue
 .*:27: Error: .vframe outside of prologue
-.*:28: Error: .spill outside of prologue
-.*:29: Error: .restore outside of body region
-.*:30: Error: .save outside of prologue
-.*:31: Error: .savesp outside of prologue
-.*:32: Error: .savepsp outside of prologue
-.*:33: Error: .save.g outside of prologue
-.*:34: Error: .save.gf outside of prologue
-.*:35: Error: .save.f outside of prologue
-.*:36: Error: .save.b outside of prologue
-.*:37: Error: .altrp outside of prologue
-.*:42: Error: .prologue within prologue
-.*:50: Error: .body outside of procedure
-.*:57: Warning: Initial .prologue.*
-.*:64: Warning: Initial .body.*
+.*:28: Error: .vframesp outside of prologue
+.*:29: Error: .vframepsp outside of prologue
+.*:30: Error: .spill outside of prologue
+.*:31: Error: .restore outside of body region
+.*:32: Error: .save outside of prologue
+.*:33: Error: .savesp outside of prologue
+.*:34: Error: .savepsp outside of prologue
+.*:35: Error: .save.g outside of prologue
+.*:36: Error: .save.gf outside of prologue
+.*:37: Error: .save.f outside of prologue
+.*:38: Error: .save.b outside of prologue
+.*:39: Error: .altrp outside of prologue
+.*:44: Error: .prologue within prologue
+.*:52: Error: .body outside of procedure
+.*:59: Warning: Initial .prologue.*
+.*:66: Warning: Initial .body.*
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-err.s	2005-02-08 10:36:18.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-err.s	2005-05-20 16:41:30.000000000 +0200
@@ -25,6 +25,8 @@ start:
 .copy_state 1
 .fframe 0
 .vframe r0
+.vframesp 0
+.vframepsp 0
 .spill 0
 .restore sp
 .save rp, r0
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-ok.d	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-ok.d	2005-05-20 17:03:06.000000000 +0200
@@ -0,0 +1,224 @@
+#readelf: -u
+#name: ia64 unwind descriptors
+
+Unwind section '\.IA_64\.unwind' at offset 0x[[:xdigit:]]+ contains 8 entries:
+
+<full1>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x3 \( ?ehandler uhandler\), len=[[:digit:]]+ bytes
+[[:space:]]*R1:prologue\(rlen=8\)
+[[:space:]]*P6:fr_mem\(frmask=\[f2,f5\]\)
+[[:space:]]*P6:gr_mem\(grmask=\[r4,r7\]\)
+[[:space:]]*P1:br_mem\(brmask=\[b1,b5\]\)
+[[:space:]]*P4:spill_mask\(imask=\[rfb,rfb,--\]\)
+[[:space:]]*P7:spill_base\(pspoff=0x10-0x10\)
+[[:space:]]*P3:rp_br\(reg=b7\)
+[[:space:]]*P10:unwabi\(abi=@svr4,context=0x00\)
+[[:space:]]*R1:body\(rlen=[[:digit:]]+\)
+[[:space:]]*X2:spill_reg\(t=0,reg=r4,treg=r2\)
+[[:space:]]*X4:spill_reg_p\(qp=p1,t=1,reg=r7,treg=r31\)
+[[:space:]]*X1:spill_sprel\(reg=b1,t=2,spoff=0x8\)
+[[:space:]]*X3:spill_sprel_p\(qp=p2,t=3,reg=b5,spoff=0x10\)
+[[:space:]]*X1:spill_psprel\(reg=f2,t=4,pspoff=0x10-0x28\)
+[[:space:]]*X3:spill_psprel_p\(qp=p4,t=5,reg=f5,pspoff=0x10-0x30\)
+[[:space:]]*X2:restore\(t=6,reg=f16\)
+[[:space:]]*X4:restore_p\(qp=p8,t=7,reg=f31\)
+[[:space:]]*X2:spill_reg\(t=8,reg=ar\.bsp,treg=r16\)
+[[:space:]]*X2:spill_reg\(t=9,reg=ar\.bspstore,treg=r17\)
+[[:space:]]*X2:spill_reg\(t=10,reg=ar\.fpsr,treg=r18\)
+[[:space:]]*X2:spill_reg\(t=11,reg=ar\.lc,treg=r19\)
+[[:space:]]*X2:spill_reg\(t=12,reg=ar\.pfs,treg=r20\)
+[[:space:]]*X2:spill_reg\(t=13,reg=ar\.rnat,treg=r21\)
+[[:space:]]*X2:spill_reg\(t=14,reg=ar\.unat,treg=r22\)
+[[:space:]]*X2:spill_reg\(t=15,reg=psp,treg=r23\)
+[[:space:]]*X2:spill_reg\(t=16,reg=pr,treg=r24\)
+[[:space:]]*X2:spill_reg\(t=17,reg=rp,treg=r25\)
+[[:space:]]*X2:spill_reg\(t=18,reg=@priunat,treg=r26\)
+[[:space:]]*B1:label_state\(label=1\)
+[[:space:]]*B2:epilogue\(t=4,ecount=0\)
+[[:space:]]*B1:copy_state\(label=1\)
+#...
+<full2>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R2:prologue_gr\(mask=\[rp,psp,pr\],grsave=r8,rlen=14\)
+[[:space:]]*P5:frgr_mem\(grmask=\[r4,r7\],frmask=\[f2,f31\]\)
+[[:space:]]*P4:spill_mask\(imask=\[b-b,bb-,---,---,--\]\)
+[[:space:]]*P7:spill_base\(pspoff=0x10-0x10\)
+[[:space:]]*P2:br_gr\(brmask=\[b1,b5\],gr=r32\)
+[[:space:]]*X2:spill_reg\(t=6,reg=f31,treg=f31\)
+[[:space:]]*X4:spill_reg_p\(qp=p63,t=7,reg=f16,treg=f0\)
+[[:space:]]*X1:spill_sprel\(reg=f5,t=8,spoff=0x20\)
+[[:space:]]*X3:spill_sprel_p\(qp=p31,t=9,reg=f2,spoff=0x18\)
+[[:space:]]*X1:spill_psprel\(reg=b5,t=10,pspoff=0x10-0x20\)
+[[:space:]]*X3:spill_psprel_p\(qp=p15,t=11,reg=b1,pspoff=0x10-0x18\)
+[[:space:]]*X2:restore\(t=12,reg=r7\)
+[[:space:]]*X4:restore_p\(qp=p7,t=13,reg=r4\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=0\)
+[[:space:]]*R1:prologue\(rlen=0\)
+[[:space:]]*R1:body\(rlen=7\)
+[[:space:]]*B4:label_state\(label=32\)
+[[:space:]]*B3:epilogue\(t=4,ecount=32\)
+[[:space:]]*B4:copy_state\(label=32\)
+#...
+<full3>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R3:prologue\(rlen=33\)
+[[:space:]]*P4:spill_mask\(imask=\[rrb,brr,bb-,---,---,---,---,---,---,---,---\]\)
+[[:space:]]*P7:spill_base\(pspoff=0x10-0x10\)
+[[:space:]]*P9:gr_gr\(grmask=\[r4,r5\],r32\)
+[[:space:]]*P2:br_gr\(brmask=\[b1,b2\],gr=r34\)
+[[:space:]]*P9:gr_gr\(grmask=\[r6,r7\],r124\)
+[[:space:]]*P2:br_gr\(brmask=\[b4,b5\],gr=r126\)
+[[:space:]]*R3:body\(rlen=33\)
+#...
+<fframe>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R1:prologue\(rlen=1\)
+[[:space:]]*P7:mem_stack_f\(t=0,size=0\)
+[[:space:]]*R1:body\(rlen=2\)
+#...
+<vframe>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R1:prologue\(rlen=11\)
+[[:space:]]*P7:mem_stack_v\(t=0\)
+[[:space:]]*P3:psp_gr\(reg=r16\)
+[[:space:]]*P8:bsp_when\(t=1\)
+[[:space:]]*P3:bsp_gr\(reg=r17\)
+[[:space:]]*P8:bspstore_when\(t=2\)
+[[:space:]]*P3:bspstore_gr\(reg=r18\)
+[[:space:]]*P7:fpsr_when\(t=3\)
+[[:space:]]*P3:fpsr_gr\(reg=r19\)
+[[:space:]]*P7:lc_when\(t=4\)
+[[:space:]]*P3:lc_gr\(reg=r20\)
+[[:space:]]*P7:pfs_when\(t=5\)
+[[:space:]]*P3:pfs_gr\(reg=r21\)
+[[:space:]]*P8:rnat_when\(t=6\)
+[[:space:]]*P3:rnat_gr\(reg=r22\)
+[[:space:]]*P7:unat_when\(t=7\)
+[[:space:]]*P3:unat_gr\(reg=r23\)
+[[:space:]]*P7:pr_when\(t=8\)
+[[:space:]]*P3:pr_gr\(reg=r24\)
+[[:space:]]*P8:priunat_when_gr\(t=9\)
+[[:space:]]*P3:priunat_gr\(reg=r25\)
+[[:space:]]*P7:rp_when\(t=10\)
+[[:space:]]*P3:rp_gr\(reg=r26\)
+[[:space:]]*R1:body\(rlen=1\)
+#...
+<vframesp>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R1:prologue\(rlen=11\)
+[[:space:]]*P7:mem_stack_v\(t=0\)
+[[:space:]]*P7:psp_sprel\(spoff=0x0\)
+[[:space:]]*P8:bsp_when\(t=1\)
+[[:space:]]*P8:bsp_sprel\(spoff=0x8\)
+[[:space:]]*P8:bspstore_when\(t=2\)
+[[:space:]]*P8:bspstore_sprel\(spoff=0x10\)
+[[:space:]]*P7:fpsr_when\(t=3\)
+[[:space:]]*P8:fpsr_sprel\(spoff=0x18\)
+[[:space:]]*P7:lc_when\(t=4\)
+[[:space:]]*P8:lc_sprel\(spoff=0x20\)
+[[:space:]]*P7:pfs_when\(t=5\)
+[[:space:]]*P8:pfs_sprel\(spoff=0x28\)
+[[:space:]]*P8:rnat_when\(t=6\)
+[[:space:]]*P8:rnat_sprel\(spoff=0x30\)
+[[:space:]]*P7:unat_when\(t=7\)
+[[:space:]]*P8:unat_sprel\(spoff=0x38\)
+[[:space:]]*P7:pr_when\(t=8\)
+[[:space:]]*P8:pr_sprel\(spoff=0x40\)
+[[:space:]]*P8:priunat_when_mem\(t=9\)
+[[:space:]]*P8:priunat_sprel\(spoff=0x48\)
+[[:space:]]*P7:rp_when\(t=10\)
+[[:space:]]*P8:rp_sprel\(spoff=0x50\)
+[[:space:]]*R1:body\(rlen=1\)
+#...
+<vframepsp>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+[[:space:]]*R1:prologue\(rlen=11\)
+[[:space:]]*P7:mem_stack_v\(t=0\)
+[[:space:]]*P8:psp_psprel\(pspoff=0x10-0x10\)
+[[:space:]]*P8:bsp_when\(t=1\)
+[[:space:]]*P8:bsp_psprel\(pspoff=0x10-0x18\)
+[[:space:]]*P8:bspstore_when\(t=2\)
+[[:space:]]*P8:bspstore_psprel\(pspoff=0x10-0x20\)
+[[:space:]]*P7:fpsr_when\(t=3\)
+[[:space:]]*P7:fpsr_psprel\(pspoff=0x10-0x28\)
+[[:space:]]*P7:lc_when\(t=4\)
+[[:space:]]*P7:lc_psprel\(pspoff=0x10-0x30\)
+[[:space:]]*P7:pfs_when\(t=5\)
+[[:space:]]*P7:pfs_psprel\(pspoff=0x10-0x38\)
+[[:space:]]*P8:rnat_when\(t=6\)
+[[:space:]]*P8:rnat_psprel\(pspoff=0x10-0x40\)
+[[:space:]]*P7:unat_when\(t=7\)
+[[:space:]]*P7:unat_psprel\(pspoff=0x10-0x48\)
+[[:space:]]*P7:pr_when\(t=8\)
+[[:space:]]*P7:pr_psprel\(pspoff=0x10-0x50\)
+[[:space:]]*P8:priunat_when_mem\(t=9\)
+[[:space:]]*P8:priunat_psprel\(pspoff=0x10-0x58\)
+[[:space:]]*P7:rp_when\(t=10\)
+[[:space:]]*P7:rp_psprel\(pspoff=0x10-0x60\)
+[[:space:]]*R1:body\(rlen=1\)
+#...
+<simple>: \[0x[[:xdigit:]]*0-0x[[:xdigit:]]*0\], info at \+0x[[:xdigit:]]*[08]
+[[:space:]]*v[[:digit:]]+, flags=0x0( \(\))?, len=[[:digit:]]+ bytes
+#pass
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/unwind-ok.s	1970-01-01 01:00:00.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/unwind-ok.s	2005-05-20 11:02:35.000000000 +0200
@@ -0,0 +1,272 @@
+.text
+.proc personality
+personality:
+	br.ret.sptk	rp
+.endp personality
+
+.proc full1
+full1:
+
+.prologue
+.spill 0
+.save.g 0x1
+	nop		0
+.save.f 0x1
+	nop		0
+.save.b 0x01
+	nop		0
+.save.g 0x8
+	nop		0
+.save.f 0x8
+	nop		0
+.save.b 0x10
+	nop		0
+.altrp b7
+	nop		0
+.unwabi @svr4, 0
+	nop		0
+
+.body
+.spillreg r4, r2
+	nop		0
+.spillreg.p p1, r7, r127
+	nop		0
+.spillsp b1, 0x08
+	nop		0
+.spillsp.p p2, b5, 0x10
+	nop		0
+.spillpsp f2, 0x18
+	nop		0
+.spillpsp.p p4, f5, 0x20
+	nop		0
+.restorereg f16
+	nop		0
+.restorereg.p p8, f31
+	nop		0
+
+.spillreg ar.bsp, r16
+	nop		0
+.spillreg ar.bspstore, r17
+	nop		0
+.spillreg ar.fpsr, r18
+	nop		0
+.spillreg ar.lc, r19
+	nop		0
+.spillreg ar.pfs, r20
+	nop		0
+.spillreg ar.rnat, r21
+	nop		0
+.spillreg ar.unat, r22
+	nop		0
+.spillreg psp, r23
+	nop		0
+.spillreg pr, r24
+	nop		0
+.spillreg rp, r25
+	nop		0
+.spillreg @priunat, r26
+	nop		0
+
+.label_state 1
+	nop		0
+.restore sp
+	nop.x		0
+.copy_state 1
+	br.ret.sptk	rp
+
+.personality personality
+.handlerdata
+	data4		-1
+	data4		0
+
+.endp full1
+
+.proc full2
+full2:
+
+.prologue 0xb, r8
+.spill 0
+.save.gf 0x1, 0x00001
+	nop		0
+	nop		0
+.save.b 0x11, r32
+	nop		0
+	nop		0
+.save.gf 0x8, 0x80000
+	nop		0
+	nop		0
+.spillreg f31, f127
+	nop		0
+.spillreg.p p63, f16, f32
+	nop		0
+.spillsp f5, 0x20
+	nop		0
+.spillsp.p p31, f2, 0x18
+	nop		0
+.spillpsp b5, 0x10
+	nop		0
+.spillpsp.p p15, b1, 0x08
+	nop		0
+.restorereg r7
+	nop		0
+.restorereg.p p7, r4
+	nop		0
+
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+.body; .prologue; .body; .prologue; .body; .prologue; .body; .prologue
+
+.body
+.label_state 32
+	nop		0
+.restore sp, 32
+	nop.x		0
+.copy_state 32
+	br.ret.sptk	rp
+.endp full2
+
+.proc full3
+full3:
+
+.prologue
+.spill 0
+.save.g 0x3, r32
+	nop		0
+	nop		0
+.save.b 0x03, r34
+	nop		0
+	nop		0
+.save.g 0xc, r124
+	nop		0
+	nop		0
+.save.b 0x18, r126
+	nop		0
+	nop		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+.body
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	nop.x		0
+	br.ret.sptk	rp
+.endp full3
+
+.proc fframe
+fframe:
+.prologue
+.fframe 0
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp fframe
+
+.proc vframe
+vframe:
+.prologue
+.vframe r16
+	nop		0
+.save ar.bsp, r17
+	nop		0
+.save ar.bspstore, r18
+	nop		0
+.save ar.fpsr, r19
+	nop		0
+.save ar.lc, r20
+	nop		0
+.save ar.pfs, r21
+	nop		0
+.save ar.rnat, r22
+	nop		0
+.save ar.unat, r23
+	nop		0
+.save pr, r24
+	nop		0
+.save @priunat, r25
+	nop		0
+.save rp, r26
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp vframe
+
+.proc vframesp
+vframesp:
+.prologue
+.vframesp 0
+	nop		0
+.savesp ar.bsp, 0x08
+	nop		0
+.savesp ar.bspstore, 0x10
+	nop		0
+.savesp ar.fpsr, 0x18
+	nop		0
+.savesp ar.lc, 0x20
+	nop		0
+.savesp ar.pfs, 0x28
+	nop		0
+.savesp ar.rnat, 0x30
+	nop		0
+.savesp ar.unat, 0x38
+	nop		0
+.savesp pr, 0x40
+	nop		0
+.savesp @priunat, 0x48
+	nop		0
+.savesp rp, 0x50
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp vframesp
+
+.proc vframepsp
+vframepsp:
+.prologue
+.vframepsp 0
+	nop		0
+.savepsp ar.bsp, 0x08
+	nop		0
+.savepsp ar.bspstore, 0x10
+	nop		0
+.savepsp ar.fpsr, 0x18
+	nop		0
+.savepsp ar.lc, 0x20
+	nop		0
+.savepsp ar.pfs, 0x28
+	nop		0
+.savepsp ar.rnat, 0x30
+	nop		0
+.savepsp ar.unat, 0x38
+	nop		0
+.savepsp pr, 0x40
+	nop		0
+.savepsp @priunat, 0x48
+	nop		0
+.savepsp rp, 0x50
+	nop		0
+.body
+	br.ret.sptk	rp
+.endp vframepsp
+
+.proc simple
+simple:
+.unwentry
+	br.ret.sptk	rp
+.endp simple

             reply	other threads:[~2005-05-23 10:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-05-23 10:19 Jan Beulich [this message]
2005-06-10  0:07 ` James E Wilson
2005-06-10 13:21 Jan Beulich
2005-06-10 21:52 Cary Coutant
2005-06-13  7:07 Jan Beulich
2005-06-15 15:31 Jan Beulich
2005-06-27 10:31 Jan Beulich
2005-07-01  3:10 ` James E Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s291b7db.099@emea1-mh.id2.novell.com \
    --to=jbeulich@novell.com \
    --cc=binutils@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).