/* 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. */
/* 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 */
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_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_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));
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));
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));
}
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);
}
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;
}
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;
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
}
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;
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;
*regp = reg - REG_BR;
}
else
- return -1;
- return 1;
+ as_bad ("Operand %d to .%s must be a writable register", n, po);
}
static void
}
static void
-add_unwind_entry (ptr)
+add_unwind_entry (ptr, sep)
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
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
{
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);
+ 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 (psp)
+ 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 (&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
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);
+ 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;
{
- 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;
}
{
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;
}
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, ®))
- {
- 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, ®, po, 1 + pred);
- if (!convert_expr_to_ab_reg (&e2, &ab, ®))
- {
- 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[] =
/* 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. */
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
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;
+ 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;
{
- 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
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
+ 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)
{
- int grmask = e1.X_add_number;
- int frmask = e2.X_add_number;
- add_unwind_entry (output_frgr_mem (grmask, frmask));
+ 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
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, ®))
{
- 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, ®))
- {
- 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;
- }
-
- 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, ®))
{
- as_bad ("Second operand to .spillreg.p must be a preserved register");
- return;
+ sep = parse_operand (&e, ',');
+ qp = 0;
}
+ convert_expr_to_ab_reg (&e, &ab, ®, 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 (&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;
- }
+ 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, ®))
+ 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, ®, 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
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
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
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
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;
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;
+ unwind.prologue_gr = grsave;
unwind.body = 0;
++unwind.prologue_count;
}
{ "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 },
{ "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 },
}
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;
}
{
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;
}
{
expressionS dummy;
- sep = parse_operand (&dummy);
+ sep = parse_operand (&dummy, '=');
if (dummy.X_op == O_absent)
break;
}
/* 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;
void
ia64_start_line ()
{
+ 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");
md.qp.X_op = O_absent;
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");
else
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");
else
&& !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 (ch)
+ int ch;
+{
+ switch (ch)
+ {
+ case '(':
+ expression (&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 '[':
if (name == end_name)
{
as_bad (_("expected symbol name"));
- discard_rest_of_line ();
+ ignore_rest_of_line ();
return;
}
--- /dev/null
+#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\)
+#...
+<psp>: \[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_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