X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ia64.c;h=426b60f589aa33a2a68ba64b2b2f854a1840b875;hb=53022e4a53d0f3c2408b598f25662efe713db8c3;hp=fe0f9a00b2f2b50bf983474ec513b91f33a763de;hpb=e4e8248d79d8461adf8b0cf22086e85a4c9ee0a4;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index fe0f9a00b2..426b60f589 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -1,5 +1,5 @@ /* tc-ia64.c -- Assembler for the HP/Intel IA-64 architecture. - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by David Mosberger-Tang @@ -124,7 +124,6 @@ enum reg_symbol IND_DTR, IND_ITR, IND_IBR, - IND_MEM, IND_MSR, IND_PKR, IND_PMC, @@ -159,6 +158,7 @@ struct label_fix { struct label_fix *next; struct symbol *sym; + bfd_boolean dw2_mark_labels; }; /* This is the endianness of the current section. */ @@ -225,8 +225,6 @@ static struct struct hash_control *const_hash; /* constant hash table */ struct hash_control *entry_hash; /* code entry hint hash table */ - symbolS *regsym[REG_NUM]; - /* If X_op is != O_absent, the registername for the instruction's qualifying predicate. If NULL, p0 is assumed for instructions that are predicatable. */ @@ -328,6 +326,8 @@ static struct int pointer_size; /* size in bytes of a pointer */ int pointer_size_shift; /* shift size of a pointer for alignment */ + + symbolS *indregsym[IND_RR - IND_CPUID + 1]; } md; @@ -354,33 +354,52 @@ static unsigned char le_nop_stop[16] = #define AR_BSP 17 #define AR_BSPSTORE 18 #define AR_RNAT 19 +#define AR_FCR 21 +#define AR_EFLAG 24 +#define AR_CSD 25 +#define AR_SSD 26 +#define AR_CFLG 27 +#define AR_FSR 28 +#define AR_FIR 29 +#define AR_FDR 30 +#define AR_CCV 32 #define AR_UNAT 36 #define AR_FPSR 40 #define AR_ITC 44 #define AR_PFS 64 #define AR_LC 65 +#define AR_EC 66 static const struct { const char *name; - int regnum; + unsigned int regnum; } ar[] = { - {"ar.k0", 0}, {"ar.k1", 1}, {"ar.k2", 2}, {"ar.k3", 3}, - {"ar.k4", 4}, {"ar.k5", 5}, {"ar.k6", 6}, {"ar.k7", 7}, - {"ar.rsc", 16}, {"ar.bsp", 17}, - {"ar.bspstore", 18}, {"ar.rnat", 19}, - {"ar.fcr", 21}, {"ar.eflag", 24}, - {"ar.csd", 25}, {"ar.ssd", 26}, - {"ar.cflg", 27}, {"ar.fsr", 28}, - {"ar.fir", 29}, {"ar.fdr", 30}, - {"ar.ccv", 32}, {"ar.unat", 36}, - {"ar.fpsr", 40}, {"ar.itc", 44}, - {"ar.pfs", 64}, {"ar.lc", 65}, - {"ar.ec", 66}, + {"ar.k0", AR_K0}, {"ar.k1", AR_K0 + 1}, + {"ar.k2", AR_K0 + 2}, {"ar.k3", AR_K0 + 3}, + {"ar.k4", AR_K0 + 4}, {"ar.k5", AR_K0 + 5}, + {"ar.k6", AR_K0 + 6}, {"ar.k7", AR_K7}, + {"ar.rsc", AR_RSC}, {"ar.bsp", AR_BSP}, + {"ar.bspstore", AR_BSPSTORE}, {"ar.rnat", AR_RNAT}, + {"ar.fcr", AR_FCR}, {"ar.eflag", AR_EFLAG}, + {"ar.csd", AR_CSD}, {"ar.ssd", AR_SSD}, + {"ar.cflg", AR_CFLG}, {"ar.fsr", AR_FSR}, + {"ar.fir", AR_FIR}, {"ar.fdr", AR_FDR}, + {"ar.ccv", AR_CCV}, {"ar.unat", AR_UNAT}, + {"ar.fpsr", AR_FPSR}, {"ar.itc", AR_ITC}, + {"ar.pfs", AR_PFS}, {"ar.lc", AR_LC}, + {"ar.ec", AR_EC}, }; +/* control registers: */ + +#define CR_DCR 0 +#define CR_ITM 1 +#define CR_IVA 2 +#define CR_PTA 8 +#define CR_GPTA 9 #define CR_IPSR 16 #define CR_ISR 17 #define CR_IIP 19 @@ -390,49 +409,52 @@ ar[] = #define CR_IFS 23 #define CR_IIM 24 #define CR_IHA 25 +#define CR_LID 64 #define CR_IVR 65 #define CR_TPR 66 #define CR_EOI 67 #define CR_IRR0 68 #define CR_IRR3 71 +#define CR_ITV 72 +#define CR_PMV 73 +#define CR_CMCV 74 #define CR_LRR0 80 #define CR_LRR1 81 -/* control registers: */ static const struct { const char *name; - int regnum; + unsigned int regnum; } cr[] = { - {"cr.dcr", 0}, - {"cr.itm", 1}, - {"cr.iva", 2}, - {"cr.pta", 8}, - {"cr.gpta", 9}, - {"cr.ipsr", 16}, - {"cr.isr", 17}, - {"cr.iip", 19}, - {"cr.ifa", 20}, - {"cr.itir", 21}, - {"cr.iipa", 22}, - {"cr.ifs", 23}, - {"cr.iim", 24}, - {"cr.iha", 25}, - {"cr.lid", 64}, - {"cr.ivr", 65}, - {"cr.tpr", 66}, - {"cr.eoi", 67}, - {"cr.irr0", 68}, - {"cr.irr1", 69}, - {"cr.irr2", 70}, - {"cr.irr3", 71}, - {"cr.itv", 72}, - {"cr.pmv", 73}, - {"cr.cmcv", 74}, - {"cr.lrr0", 80}, - {"cr.lrr1", 81} + {"cr.dcr", CR_DCR}, + {"cr.itm", CR_ITM}, + {"cr.iva", CR_IVA}, + {"cr.pta", CR_PTA}, + {"cr.gpta", CR_GPTA}, + {"cr.ipsr", CR_IPSR}, + {"cr.isr", CR_ISR}, + {"cr.iip", CR_IIP}, + {"cr.ifa", CR_IFA}, + {"cr.itir", CR_ITIR}, + {"cr.iipa", CR_IIPA}, + {"cr.ifs", CR_IFS}, + {"cr.iim", CR_IIM}, + {"cr.iha", CR_IHA}, + {"cr.lid", CR_LID}, + {"cr.ivr", CR_IVR}, + {"cr.tpr", CR_TPR}, + {"cr.eoi", CR_EOI}, + {"cr.irr0", CR_IRR0}, + {"cr.irr1", CR_IRR0 + 1}, + {"cr.irr2", CR_IRR0 + 2}, + {"cr.irr3", CR_IRR3}, + {"cr.itv", CR_ITV}, + {"cr.pmv", CR_PMV}, + {"cr.cmcv", CR_CMCV}, + {"cr.lrr0", CR_LRR0}, + {"cr.lrr1", CR_LRR1} }; #define PSR_MFL 4 @@ -490,7 +512,7 @@ const_bits[] = static const struct { const char *name; - int regnum; + unsigned int regnum; } indirect_reg[] = { @@ -593,7 +615,7 @@ static const bfd_vma nop[IA64_NUM_UNITS] = 0x0008000000LL, /* M-unit nop */ 0x4000000000LL, /* B-unit nop */ 0x0008000000LL, /* F-unit nop */ - 0x0008000000LL, /* L-"unit" nop */ + 0x0000000000LL, /* L-"unit" nop immediate */ 0x0008000000LL, /* X-unit nop */ }; @@ -742,6 +764,9 @@ static struct unsigned int prologue_count; /* number of .prologues seen so far */ /* Prologue counts at previous .label_state directives. */ struct label_prologue_count * saved_prologue_counts; + + /* List of split up .save-s. */ + unw_p_record *pending_saves; } unwind; /* The input value is a negated offset from psp, and specifies an address @@ -807,8 +832,8 @@ 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 *, int)); -static symbolS *declare_register PARAMS ((const char *name, int regnum)); -static void declare_register_set PARAMS ((const char *, int, int)); +static symbolS *declare_register PARAMS ((const char *name, unsigned int regnum)); +static void declare_register_set PARAMS ((const char *, unsigned int, unsigned 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, @@ -1080,6 +1105,7 @@ ia64_flush_insns () segT saved_seg; subsegT saved_subseg; unw_rec_list *ptr; + bfd_boolean mark; if (!md.last_text_seg) return; @@ -1093,18 +1119,23 @@ ia64_flush_insns () emit_one_bundle (); /* force out queued instructions */ /* In case there are labels following the last instruction, resolve - those now: */ + those now. */ + mark = FALSE; for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next) { - S_SET_VALUE (lfix->sym, frag_now_fix ()); - symbol_set_frag (lfix->sym, frag_now); + symbol_set_value_now (lfix->sym); + mark |= lfix->dw2_mark_labels; } - CURR_SLOT.label_fixups = 0; - for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next) + if (mark) { - S_SET_VALUE (lfix->sym, frag_now_fix ()); - symbol_set_frag (lfix->sym, frag_now); + dwarf2_where (&CURR_SLOT.debug_line); + CURR_SLOT.debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK; + dwarf2_gen_line_info (frag_now_fix (), &CURR_SLOT.debug_line); } + CURR_SLOT.label_fixups = 0; + + for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next) + symbol_set_value_now (lfix->sym); CURR_SLOT.tag_fixups = 0; /* In case there are unwind directives following the last instruction, @@ -1738,6 +1769,55 @@ output_X4_format (f, qp, ab, reg, x, y, treg, t) (*f) (count, bytes, NULL); } +/* This function checks whether there are any outstanding .save-s and + discards them if so. */ + +static void +check_pending_save (void) +{ + if (unwind.pending_saves) + { + unw_rec_list *cur, *prev; + + as_warn ("Previous .save incomplete"); + for (cur = unwind.list, prev = NULL; cur; ) + if (&cur->r.record.p == unwind.pending_saves) + { + if (prev) + prev->next = cur->next; + else + unwind.list = cur->next; + if (cur == unwind.tail) + unwind.tail = prev; + if (cur == unwind.current_entry) + unwind.current_entry = cur->next; + /* Don't free the first discarded record, it's being used as + terminator for (currently) br_gr and gr_gr processing, and + also prevents leaving a dangling pointer to it in its + predecessor. */ + cur->r.record.p.grmask = 0; + cur->r.record.p.brmask = 0; + cur->r.record.p.frmask = 0; + prev = cur->r.record.p.next; + cur->r.record.p.next = NULL; + cur = prev; + break; + } + else + { + prev = cur; + cur = cur->next; + } + while (cur) + { + prev = cur; + cur = cur->r.record.p.next; + free (prev); + } + unwind.pending_saves = NULL; + } +} + /* This function allocates a record list structure, and initializes fields. */ static unw_rec_list * @@ -1745,7 +1825,7 @@ alloc_record (unw_record_type t) { unw_rec_list *ptr; ptr = xmalloc (sizeof (*ptr)); - ptr->next = NULL; + memset (ptr, 0, sizeof (*ptr)); ptr->slot_number = SLOT_NUM_NOT_SET; ptr->r.type = t; return ptr; @@ -1809,7 +1889,7 @@ output_psp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (psp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1818,7 +1898,7 @@ output_psp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (psp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1834,7 +1914,7 @@ output_rp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (rp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1843,7 +1923,7 @@ output_rp_br (br) unsigned int br; { unw_rec_list *ptr = alloc_record (rp_br); - ptr->r.record.p.br = br; + ptr->r.record.p.r.br = br; return ptr; } @@ -1852,7 +1932,7 @@ output_rp_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rp_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1861,7 +1941,7 @@ output_rp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1877,7 +1957,7 @@ output_pfs_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (pfs_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1886,7 +1966,7 @@ output_pfs_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (pfs_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1895,7 +1975,7 @@ output_pfs_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (pfs_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1911,7 +1991,7 @@ output_preds_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (preds_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -1920,7 +2000,7 @@ output_preds_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (preds_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -1929,7 +2009,7 @@ output_preds_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (preds_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -1938,8 +2018,24 @@ output_fr_mem (mask) unsigned int mask; { unw_rec_list *ptr = alloc_record (fr_mem); - ptr->r.record.p.rmask = mask; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.frmask = mask; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (fr_mem); + cur->r.record.p.frmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.frmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1948,9 +2044,39 @@ output_frgr_mem (gr_mask, fr_mask) unsigned int fr_mask; { unw_rec_list *ptr = alloc_record (frgr_mem); - ptr->r.record.p.grmask = gr_mask; - ptr->r.record.p.frmask = fr_mask; - return ptr; + unw_rec_list *cur = ptr; + + unwind.pending_saves = &cur->r.record.p; + cur->r.record.p.frmask = fr_mask; + while (fr_mask) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + fr_mask &= ~(fr_mask & (~fr_mask + 1)); + if (!gr_mask && !fr_mask) + return ptr; + cur = alloc_record (frgr_mem); + cur->r.record.p.frmask = fr_mask; + /* Retain only least significant bit. */ + prev->r.record.p.frmask ^= fr_mask; + prev->r.record.p.next = cur; + } + cur->r.record.p.grmask = gr_mask; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + gr_mask &= ~(gr_mask & (~gr_mask + 1)); + if (!gr_mask) + return ptr; + cur = alloc_record (frgr_mem); + cur->r.record.p.grmask = gr_mask; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= gr_mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1959,9 +2085,27 @@ output_gr_gr (mask, reg) unsigned int reg; { unw_rec_list *ptr = alloc_record (gr_gr); + unw_rec_list *cur = ptr; + ptr->r.record.p.grmask = mask; - ptr->r.record.p.gr = reg; - return ptr; + ptr->r.record.p.r.gr = reg; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (gr_gr); + cur->r.record.p.grmask = mask; + /* Indicate this record shouldn't be output. */ + cur->r.record.p.r.gr = REG_NUM; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1969,27 +2113,77 @@ output_gr_mem (mask) unsigned int mask; { unw_rec_list *ptr = alloc_record (gr_mem); - ptr->r.record.p.rmask = mask; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.grmask = mask; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (gr_mem); + cur->r.record.p.grmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.grmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * output_br_mem (unsigned int mask) { unw_rec_list *ptr = alloc_record (br_mem); + unw_rec_list *cur = ptr; + ptr->r.record.p.brmask = mask; - return ptr; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (br_mem); + cur->r.record.p.brmask = mask; + /* Retain only least significant bit. */ + prev->r.record.p.brmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * -output_br_gr (save_mask, reg) - unsigned int save_mask; +output_br_gr (mask, reg) + unsigned int mask; unsigned int reg; { unw_rec_list *ptr = alloc_record (br_gr); - ptr->r.record.p.brmask = save_mask; - ptr->r.record.p.gr = reg; - return ptr; + unw_rec_list *cur = ptr; + + ptr->r.record.p.brmask = mask; + ptr->r.record.p.r.gr = reg; + unwind.pending_saves = &ptr->r.record.p; + for (;;) + { + unw_rec_list *prev = cur; + + /* Clear least significant set bit. */ + mask &= ~(mask & (~mask + 1)); + if (!mask) + return ptr; + cur = alloc_record (br_gr); + cur->r.record.p.brmask = mask; + /* Indicate this record shouldn't be output. */ + cur->r.record.p.r.gr = REG_NUM; + /* Retain only least significant bit. */ + prev->r.record.p.brmask ^= mask; + prev->r.record.p.next = cur; + } } static unw_rec_list * @@ -1997,7 +2191,7 @@ output_spill_base (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (spill_base); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2013,7 +2207,7 @@ output_unat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (unat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2022,7 +2216,7 @@ output_unat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (unat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2031,7 +2225,7 @@ output_unat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (unat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2047,7 +2241,7 @@ output_lc_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (lc_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2056,7 +2250,7 @@ output_lc_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (lc_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2065,7 +2259,7 @@ output_lc_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (lc_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2081,7 +2275,7 @@ output_fpsr_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (fpsr_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2090,7 +2284,7 @@ output_fpsr_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (fpsr_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2099,7 +2293,7 @@ output_fpsr_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (fpsr_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2122,7 +2316,7 @@ output_priunat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (priunat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2131,7 +2325,7 @@ output_priunat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (priunat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2140,7 +2334,7 @@ output_priunat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (priunat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2156,7 +2350,7 @@ output_bsp_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (bsp_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2165,7 +2359,7 @@ output_bsp_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bsp_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2174,7 +2368,7 @@ output_bsp_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bsp_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2190,7 +2384,7 @@ output_bspstore_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (bspstore_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2199,7 +2393,7 @@ output_bspstore_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bspstore_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2208,7 +2402,7 @@ output_bspstore_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (bspstore_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2224,7 +2418,7 @@ output_rnat_gr (gr) unsigned int gr; { unw_rec_list *ptr = alloc_record (rnat_gr); - ptr->r.record.p.gr = gr; + ptr->r.record.p.r.gr = gr; return ptr; } @@ -2233,7 +2427,7 @@ output_rnat_psprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rnat_psprel); - ptr->r.record.p.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.p.off.psp = ENCODED_PSP_OFFSET (offset); return ptr; } @@ -2242,7 +2436,7 @@ output_rnat_sprel (offset) unsigned int offset; { unw_rec_list *ptr = alloc_record (rnat_sprel); - ptr->r.record.p.spoff = offset / 4; + ptr->r.record.p.off.sp = offset / 4; return ptr; } @@ -2291,7 +2485,7 @@ output_spill_psprel (ab, reg, offset, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_psprel_p : spill_psprel); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.pspoff = ENCODED_PSP_OFFSET (offset); + ptr->r.record.x.where.pspoff = ENCODED_PSP_OFFSET (offset); ptr->r.record.x.qp = predicate; return ptr; } @@ -2306,7 +2500,7 @@ output_spill_sprel (ab, reg, offset, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_sprel_p : spill_sprel); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.spoff = offset / 4; + ptr->r.record.x.where.spoff = offset / 4; ptr->r.record.x.qp = predicate; return ptr; } @@ -2322,7 +2516,7 @@ output_spill_reg (ab, reg, targ_reg, xy, predicate) unw_rec_list *ptr = alloc_record (predicate ? spill_reg_p : spill_reg); ptr->r.record.x.ab = ab; ptr->r.record.x.reg = reg; - ptr->r.record.x.treg = targ_reg; + ptr->r.record.x.where.reg = targ_reg; ptr->r.record.x.xy = xy; ptr->r.record.x.qp = predicate; return ptr; @@ -2336,7 +2530,7 @@ process_one_record (ptr, f) unw_rec_list *ptr; vbyte_func f; { - unsigned long fr_mask, gr_mask; + unsigned int fr_mask, gr_mask; switch (ptr->r.type) { @@ -2402,13 +2596,13 @@ process_one_record (ptr, f) case bsp_gr: case bspstore_gr: case rnat_gr: - output_P3_format (f, ptr->r.type, ptr->r.record.p.gr); + output_P3_format (f, ptr->r.type, ptr->r.record.p.r.gr); break; case rp_br: - output_P3_format (f, rp_br, ptr->r.record.p.br); + output_P3_format (f, rp_br, ptr->r.record.p.r.br); break; case psp_sprel: - output_P7_format (f, psp_sprel, ptr->r.record.p.spoff, 0); + output_P7_format (f, psp_sprel, ptr->r.record.p.off.sp, 0); break; case rp_when: case pfs_when: @@ -2425,7 +2619,7 @@ process_one_record (ptr, f) case lc_psprel: case fpsr_psprel: case spill_base: - output_P7_format (f, ptr->r.type, ptr->r.record.p.pspoff, 0); + output_P7_format (f, ptr->r.type, ptr->r.record.p.off.psp, 0); break; case rp_sprel: case pfs_sprel: @@ -2437,13 +2631,29 @@ process_one_record (ptr, f) case bsp_sprel: case bspstore_sprel: case rnat_sprel: - output_P8_format (f, ptr->r.type, ptr->r.record.p.spoff); + output_P8_format (f, ptr->r.type, ptr->r.record.p.off.sp); break; case gr_gr: - output_P9_format (f, ptr->r.record.p.grmask, ptr->r.record.p.gr); + if (ptr->r.record.p.r.gr < REG_NUM) + { + const unw_rec_list *cur = ptr; + + gr_mask = cur->r.record.p.grmask; + while ((cur = cur->r.record.p.next) != NULL) + gr_mask |= cur->r.record.p.grmask; + output_P9_format (f, gr_mask, ptr->r.record.p.r.gr); + } break; case br_gr: - output_P2_format (f, ptr->r.record.p.brmask, ptr->r.record.p.gr); + if (ptr->r.record.p.r.gr < REG_NUM) + { + const unw_rec_list *cur = ptr; + + gr_mask = cur->r.record.p.brmask; + while ((cur = cur->r.record.p.next) != NULL) + gr_mask |= cur->r.record.p.brmask; + output_P2_format (f, gr_mask, ptr->r.record.p.r.gr); + } break; case spill_mask: as_bad ("spill_mask record unimplemented."); @@ -2459,7 +2669,7 @@ process_one_record (ptr, f) case bsp_psprel: case bspstore_psprel: case rnat_psprel: - output_P8_format (f, ptr->r.type, ptr->r.record.p.pspoff); + output_P8_format (f, ptr->r.type, ptr->r.record.p.off.psp); break; case unwabi: output_P10_format (f, ptr->r.record.p.abi, ptr->r.record.p.context); @@ -2474,32 +2684,32 @@ process_one_record (ptr, f) case spill_psprel: output_X1_format (f, ptr->r.type, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.t, - ptr->r.record.x.pspoff); + ptr->r.record.x.where.pspoff); break; case spill_sprel: output_X1_format (f, ptr->r.type, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.t, - ptr->r.record.x.spoff); + ptr->r.record.x.where.spoff); break; case spill_reg: output_X2_format (f, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.xy >> 1, ptr->r.record.x.xy, - ptr->r.record.x.treg, ptr->r.record.x.t); + ptr->r.record.x.where.reg, ptr->r.record.x.t); break; case spill_psprel_p: output_X3_format (f, ptr->r.type, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, - ptr->r.record.x.t, ptr->r.record.x.pspoff); + ptr->r.record.x.t, ptr->r.record.x.where.pspoff); break; case spill_sprel_p: output_X3_format (f, ptr->r.type, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, - ptr->r.record.x.t, ptr->r.record.x.spoff); + ptr->r.record.x.t, ptr->r.record.x.where.spoff); break; case spill_reg_p: output_X4_format (f, ptr->r.record.x.qp, ptr->r.record.x.ab, ptr->r.record.x.reg, ptr->r.record.x.xy >> 1, - ptr->r.record.x.xy, ptr->r.record.x.treg, + ptr->r.record.x.xy, ptr->r.record.x.where.reg, ptr->r.record.x.t); break; default: @@ -2685,24 +2895,11 @@ slot_index (slot_addr, slot_frag, first_addr, first_frag, before_relax) first_addr = (unsigned long) &first_frag->fr_literal; /* This can happen if there is section switching in the middle of a - function, causing the frag chain for the function to be broken. */ + function, causing the frag chain for the function to be broken. + It is too difficult to recover safely from this problem, so we just + exit with an error. */ if (first_frag == NULL) - { - /* We get six warnings for one problem, because of the loop in - fixup_unw_records, and because fixup_unw_records is called 3 - times: once before creating the variant frag, once to estimate - its size, and once to relax it. This is unreasonable, so we use - a static var to make sure we only emit the warning once. */ - static int warned = 0; - - if (!warned) - { - as_warn ("Corrupted unwind info due to unsupported section switching"); - warned = 1; - } - - return index; - } + as_fatal ("Section switching in code is not supported."); } /* Add in the used part of the last frag. */ @@ -2835,8 +3032,8 @@ fixup_unw_records (list, before_relax) as_bad ("fr_mem record before region record!"); return; } - region->r.record.r.mask.fr_mem |= ptr->r.record.p.rmask; - set_imask (region, ptr->r.record.p.rmask, t, 1); + region->r.record.r.mask.fr_mem |= ptr->r.record.p.frmask; + set_imask (region, ptr->r.record.p.frmask, t, 1); break; case gr_mem: if (!region) @@ -2844,8 +3041,8 @@ fixup_unw_records (list, before_relax) as_bad ("gr_mem record before region record!"); return; } - region->r.record.r.mask.gr_mem |= ptr->r.record.p.rmask; - set_imask (region, ptr->r.record.p.rmask, t, 2); + region->r.record.r.mask.gr_mem |= ptr->r.record.p.grmask; + set_imask (region, ptr->r.record.p.grmask, t, 2); break; case br_mem: if (!region) @@ -3174,18 +3371,11 @@ static int in_prologue (const char *directive) { int in = in_procedure (directive); - if (in) - { - /* We are in a procedure. Check if we are in a prologue. */ - if (unwind.prologue) - return 1; - /* We only want to issue one message. */ - if (in == 1) - return unwind_diagnostic ("prologue", directive); - else - return -1; - } - return 0; + + if (in > 0 && !unwind.prologue) + in = unwind_diagnostic ("prologue", directive); + check_pending_save (); + return in; } /* Return 1 if a directive is in a body, -1 if a directive isn't in @@ -3197,18 +3387,10 @@ static int in_body (const char *directive) { int in = in_procedure (directive); - if (in) - { - /* We are in a procedure. Check if we are in a body. */ - if (unwind.body) - return 1; - /* We only want to issue one message. */ - if (in == 1) - return unwind_diagnostic ("body region", directive); - else - return -1; - } - return 0; + + if (in > 0 && !unwind.body) + in = unwind_diagnostic ("body region", directive); + return in; } static void @@ -4306,6 +4488,7 @@ dot_body (dummy) return; if (!unwind.prologue && !unwind.body && unwind.insn) as_warn ("Initial .body should precede any instructions"); + check_pending_save (); unwind.prologue = 0; unwind.prologue_mask = 0; @@ -4597,7 +4780,8 @@ static void dot_rot (type) int type; { - unsigned num_regs, num_alloced = 0; + offsetT num_regs; + valueT num_alloced = 0; struct dynreg **drpp, *dr; int ch, base_reg = 0; char *name, *start; @@ -4642,6 +4826,11 @@ dot_rot (type) as_bad ("Expected ']'"); goto err; } + if (num_regs <= 0) + { + as_bad ("Number of elements must be positive"); + goto err; + } SKIP_WHITESPACE (); num_alloced += num_regs; @@ -4928,7 +5117,7 @@ dot_reg_val (dummy) { expressionS reg; - expression (®); + expression_and_evaluate (®); if (reg.X_op != O_register) { as_bad (_("Register name expected")); @@ -5100,7 +5289,7 @@ dot_pred_rel (type) int regno; expressionS pr, *pr1, *pr2; - expression (&pr); + expression_and_evaluate (&pr); if (pr.X_op == O_register && pr.X_add_number >= REG_P && pr.X_add_number <= REG_P + 63) @@ -5419,12 +5608,12 @@ pseudo_opcode[] = static symbolS * declare_register (name, regnum) const char *name; - int regnum; + unsigned int regnum; { const char *err; symbolS *sym; - sym = symbol_new (name, reg_section, regnum, &zero_address_frag); + sym = symbol_create (name, reg_section, regnum, &zero_address_frag); err = hash_insert (md.reg_hash, S_GET_NAME (sym), (PTR) sym); if (err) @@ -5437,11 +5626,11 @@ declare_register (name, regnum) static void declare_register_set (prefix, num_regs, base_regnum) const char *prefix; - int num_regs; - int base_regnum; + unsigned int num_regs; + unsigned int base_regnum; { char name[8]; - int i; + unsigned int i; for (i = 0; i < num_regs; ++i) { @@ -5725,6 +5914,17 @@ operand_match (idesc, index, e) return OPERAND_MATCH; break; + case IA64_OPND_IMMU5b: + if (e->X_op == O_constant) + { + val = e->X_add_number; + if (val >= 32 && val <= 63) + return OPERAND_MATCH; + else + return OPERAND_OUT_OF_RANGE; + } + break; + case IA64_OPND_CCNT5: case IA64_OPND_CNT5: case IA64_OPND_CNT6: @@ -6006,7 +6206,7 @@ parse_operand (e, more) memset (e, 0, sizeof (*e)); e->X_op = O_absent; SKIP_WHITESPACE (); - expression (e); + expression_and_evaluate (e); sep = *input_line_pointer; if (more && (sep == ',' || sep == more)) ++input_line_pointer; @@ -6103,34 +6303,38 @@ parse_operands (idesc) if (idesc->operands[2] == IA64_OPND_SOF || idesc->operands[1] == IA64_OPND_SOF) { - /* map alloc r1=ar.pfs,i,l,o,r to alloc r1=ar.pfs,(i+l+o),(i+l),r */ + /* Map alloc r1=ar.pfs,i,l,o,r to alloc r1=ar.pfs,(i+l+o),(i+l),r. + Note, however, that due to that mapping operand numbers in error + messages for any of the constant operands will not be correct. */ know (strcmp (idesc->name, "alloc") == 0); - i = (CURR_SLOT.opnd[1].X_op == O_register - && CURR_SLOT.opnd[1].X_add_number == REG_AR + AR_PFS) ? 2 : 1; - if (num_operands == i + 3 /* first_arg not included in this count! */ - && CURR_SLOT.opnd[i].X_op == O_constant - && CURR_SLOT.opnd[i + 1].X_op == O_constant - && CURR_SLOT.opnd[i + 2].X_op == O_constant - && CURR_SLOT.opnd[i + 3].X_op == O_constant) - { - sof = set_regstack (CURR_SLOT.opnd[i].X_add_number, - CURR_SLOT.opnd[i + 1].X_add_number, - CURR_SLOT.opnd[i + 2].X_add_number, - CURR_SLOT.opnd[i + 3].X_add_number); - - /* now we can parse the first arg: */ - saved_input_pointer = input_line_pointer; - input_line_pointer = first_arg; - sep = parse_operand (CURR_SLOT.opnd + 0, '='); - if (sep != '=') - --num_outputs; /* force error */ - input_line_pointer = saved_input_pointer; - - CURR_SLOT.opnd[i].X_add_number = sof; - CURR_SLOT.opnd[i + 1].X_add_number - = sof - CURR_SLOT.opnd[i + 2].X_add_number; - CURR_SLOT.opnd[i + 2] = CURR_SLOT.opnd[i + 3]; - } + /* The first operand hasn't been parsed/initialized, yet (but + num_operands intentionally doesn't account for that). */ + i = num_operands > 4 ? 2 : 1; +#define FORCE_CONST(n) (CURR_SLOT.opnd[n].X_op == O_constant \ + ? CURR_SLOT.opnd[n].X_add_number \ + : 0) + sof = set_regstack (FORCE_CONST(i), + FORCE_CONST(i + 1), + FORCE_CONST(i + 2), + FORCE_CONST(i + 3)); +#undef FORCE_CONST + + /* now we can parse the first arg: */ + saved_input_pointer = input_line_pointer; + input_line_pointer = first_arg; + sep = parse_operand (CURR_SLOT.opnd + 0, '='); + if (sep != '=') + --num_outputs; /* force error */ + input_line_pointer = saved_input_pointer; + + CURR_SLOT.opnd[i].X_add_number = sof; + if (CURR_SLOT.opnd[i + 1].X_op == O_constant + && CURR_SLOT.opnd[i + 2].X_op == O_constant) + CURR_SLOT.opnd[i + 1].X_add_number + = sof - CURR_SLOT.opnd[i + 2].X_add_number; + else + CURR_SLOT.opnd[i + 1].X_op = O_illegal; + CURR_SLOT.opnd[i + 2] = CURR_SLOT.opnd[i + 3]; } highest_unmatched_operand = -4; @@ -6479,6 +6683,7 @@ emit_one_bundle () int n, i, j, first, curr, last_slot; bfd_vma t0 = 0, t1 = 0; struct label_fix *lfix; + bfd_boolean mark_label; struct insn_fix *ifix; char mnemonic[16]; fixS *fix; @@ -6650,6 +6855,10 @@ emit_one_bundle () changing NOPs in front of this slot. */ for (j = i; j < 3; ++j) insn[j] = nop[ia64_templ_desc[required_template].exec_unit[j]]; + + /* We just picked a template that includes the stop bit in the + middle, so we don't need another one emitted later. */ + md.slot[curr].end_of_insn_group = 0; } template = required_template; } @@ -6799,11 +7008,30 @@ emit_one_bundle () if (insn_unit != required_unit) continue; /* Try next slot. */ - if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen) + /* Now is a good time to fix up the labels for this insn. */ + mark_label = FALSE; + for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next) + { + S_SET_VALUE (lfix->sym, frag_now_fix () - 16); + symbol_set_frag (lfix->sym, frag_now); + mark_label |= lfix->dw2_mark_labels; + } + for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next) + { + S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i); + symbol_set_frag (lfix->sym, frag_now); + } + + if (debug_type == DEBUG_DWARF2 + || md.slot[curr].loc_directive_seen + || mark_label) { bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i; md.slot[curr].loc_directive_seen = 0; + if (mark_label) + md.slot[curr].debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK; + dwarf2_gen_line_info (addr, &md.slot[curr].debug_line); } @@ -6832,19 +7060,6 @@ emit_one_bundle () --md.num_slots_in_use; last_slot = i; - /* now is a good time to fix up the labels for this insn: */ - for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next) - { - S_SET_VALUE (lfix->sym, frag_now_fix () - 16); - symbol_set_frag (lfix->sym, frag_now); - } - /* and fix up the tags also. */ - for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next) - { - S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i); - symbol_set_frag (lfix->sym, frag_now); - } - for (j = 0; j < md.slot[curr].num_fixups; ++j) { ifix = md.slot[curr].fixup + j; @@ -6871,25 +7086,28 @@ emit_one_bundle () curr = (curr + 1) % NUM_SLOTS; idesc = md.slot[curr].idesc; } - if (manual_bundling > 0) + + /* A user template was specified, but the first following instruction did + not fit. This can happen with or without manual bundling. */ + if (md.num_slots_in_use > 0 && last_slot < 0) + { + as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, + "`%s' does not fit into %s template", + idesc->name, ia64_templ_desc[template].name); + /* Drop first insn so we don't livelock. */ + --md.num_slots_in_use; + know (curr == first); + ia64_free_opcode (md.slot[curr].idesc); + memset (md.slot + curr, 0, sizeof (md.slot[curr])); + md.slot[curr].user_template = -1; + } + else if (manual_bundling > 0) { if (md.num_slots_in_use > 0) { if (last_slot >= 2) as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, "`%s' does not fit into bundle", idesc->name); - else if (last_slot < 0) - { - as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, - "`%s' does not fit into %s template", - idesc->name, ia64_templ_desc[template].name); - /* Drop first insn so we don't livelock. */ - --md.num_slots_in_use; - know (curr == first); - ia64_free_opcode (md.slot[curr].idesc); - memset (md.slot + curr, 0, sizeof (md.slot[curr])); - md.slot[curr].user_template = -1; - } else { const char *where; @@ -6909,6 +7127,7 @@ emit_one_bundle () as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line, "Missing '}' at end of file"); } + know (md.num_slots_in_use < NUM_SLOTS); t0 = end_of_insn_group | (template << 1) | (insn[0] << 5) | (insn[1] << 46); @@ -7180,7 +7399,7 @@ extra_goodness (int templ, int slot) void md_begin () { - int i, j, k, t, total, ar_base, cr_base, goodness, best, regnum, ok; + int i, j, k, t, goodness, best, ok; const char *err; char name[8]; @@ -7355,91 +7574,52 @@ md_begin () md.entry_hash = hash_new (); /* general registers: */ - - total = 128; - for (i = 0; i < total; ++i) - { - sprintf (name, "r%d", i - REG_GR); - md.regsym[i] = declare_register (name, i); - } + declare_register_set ("r", 128, REG_GR); + declare_register ("gp", REG_GR + 1); + declare_register ("sp", REG_GR + 12); + declare_register ("tp", REG_GR + 13); + declare_register_set ("ret", 4, REG_GR + 8); /* floating point registers: */ - total += 128; - for (; i < total; ++i) - { - sprintf (name, "f%d", i - REG_FR); - md.regsym[i] = declare_register (name, i); - } - - /* application registers: */ - total += 128; - ar_base = i; - for (; i < total; ++i) - { - sprintf (name, "ar%d", i - REG_AR); - md.regsym[i] = declare_register (name, i); - } + declare_register_set ("f", 128, REG_FR); + declare_register_set ("farg", 8, REG_FR + 8); + declare_register_set ("fret", 8, REG_FR + 8); - /* control registers: */ - total += 128; - cr_base = i; - for (; i < total; ++i) - { - sprintf (name, "cr%d", i - REG_CR); - md.regsym[i] = declare_register (name, i); - } + /* branch registers: */ + declare_register_set ("b", 8, REG_BR); + declare_register ("rp", REG_BR + 0); /* predicate registers: */ - total += 64; - for (; i < total; ++i) - { - sprintf (name, "p%d", i - REG_P); - md.regsym[i] = declare_register (name, i); - } + declare_register_set ("p", 64, REG_P); + declare_register ("pr", REG_PR); + declare_register ("pr.rot", REG_PR_ROT); - /* branch registers: */ - total += 8; - for (; i < total; ++i) - { - sprintf (name, "b%d", i - REG_BR); - md.regsym[i] = declare_register (name, i); - } + /* application registers: */ + declare_register_set ("ar", 128, REG_AR); + for (i = 0; i < NELEMS (ar); ++i) + declare_register (ar[i].name, REG_AR + ar[i].regnum); - md.regsym[REG_IP] = declare_register ("ip", REG_IP); - md.regsym[REG_CFM] = declare_register ("cfm", REG_CFM); - md.regsym[REG_PR] = declare_register ("pr", REG_PR); - md.regsym[REG_PR_ROT] = declare_register ("pr.rot", REG_PR_ROT); - md.regsym[REG_PSR] = declare_register ("psr", REG_PSR); - md.regsym[REG_PSR_L] = declare_register ("psr.l", REG_PSR_L); - md.regsym[REG_PSR_UM] = declare_register ("psr.um", REG_PSR_UM); + /* control registers: */ + declare_register_set ("cr", 128, REG_CR); + for (i = 0; i < NELEMS (cr); ++i) + declare_register (cr[i].name, REG_CR + cr[i].regnum); + + declare_register ("ip", REG_IP); + declare_register ("cfm", REG_CFM); + declare_register ("psr", REG_PSR); + declare_register ("psr.l", REG_PSR_L); + declare_register ("psr.um", REG_PSR_UM); for (i = 0; i < NELEMS (indirect_reg); ++i) { - regnum = indirect_reg[i].regnum; - md.regsym[regnum] = declare_register (indirect_reg[i].name, regnum); - } + unsigned int regnum = indirect_reg[i].regnum; - /* define synonyms for application registers: */ - for (i = REG_AR; i < REG_AR + NELEMS (ar); ++i) - md.regsym[i] = declare_register (ar[i - REG_AR].name, - REG_AR + ar[i - REG_AR].regnum); - - /* define synonyms for control registers: */ - for (i = REG_CR; i < REG_CR + NELEMS (cr); ++i) - md.regsym[i] = declare_register (cr[i - REG_CR].name, - REG_CR + cr[i - REG_CR].regnum); - - declare_register ("gp", REG_GR + 1); - declare_register ("sp", REG_GR + 12); - declare_register ("rp", REG_BR + 0); + md.indregsym[regnum - IND_CPUID] = declare_register (indirect_reg[i].name, regnum); + } /* pseudo-registers used to specify unwind info: */ declare_register ("psp", REG_PSP); - declare_register_set ("ret", 4, REG_GR + 8); - declare_register_set ("farg", 8, REG_FR + 8); - declare_register_set ("fret", 8, REG_FR + 8); - for (i = 0; i < NELEMS (const_bits); ++i) { err = hash_insert (md.const_hash, const_bits[i].name, @@ -7636,7 +7816,7 @@ ia64_unrecognized_line (ch) switch (ch) { case '(': - expression (&md.qp); + expression_and_evaluate (&md.qp); if (*input_line_pointer++ != ')') { as_bad ("Expected ')'"); @@ -7736,6 +7916,7 @@ ia64_frob_label (sym) fix = obstack_alloc (¬es, sizeof (*fix)); fix->sym = sym; fix->next = CURR_SLOT.tag_fixups; + fix->dw2_mark_labels = FALSE; CURR_SLOT.tag_fixups = fix; return; @@ -7747,6 +7928,7 @@ ia64_frob_label (sym) fix = obstack_alloc (¬es, sizeof (*fix)); fix->sym = sym; fix->next = CURR_SLOT.label_fixups; + fix->dw2_mark_labels = dwarf2_loc_mark_labels; CURR_SLOT.label_fixups = fix; /* Keep track of how many code entry points we've seen. */ @@ -7801,39 +7983,51 @@ ia64_optimize_expr (l, op, r) operatorT op; expressionS *r; { - unsigned num_regs; - - if (op == O_index) + if (op != O_index) + return 0; + resolve_expression (l); + if (l->X_op == O_register) { - if (l->X_op == O_register && r->X_op == O_constant) + unsigned num_regs = l->X_add_number >> 16; + + resolve_expression (r); + if (num_regs) { - num_regs = (l->X_add_number >> 16); - if ((unsigned) r->X_add_number >= num_regs) + /* Left side is a .rotX-allocated register. */ + if (r->X_op != O_constant) { - if (!num_regs) - as_bad ("No current frame"); - else - as_bad ("Index out of range 0..%u", num_regs - 1); + as_bad ("Rotating register index must be a non-negative constant"); + r->X_add_number = 0; + } + else if ((valueT) r->X_add_number >= num_regs) + { + as_bad ("Index out of range 0..%u", num_regs - 1); r->X_add_number = 0; } l->X_add_number = (l->X_add_number & 0xffff) + r->X_add_number; return 1; } - else if (l->X_op == O_register && r->X_op == O_register) + else if (l->X_add_number >= IND_CPUID && l->X_add_number <= IND_RR) { - if (l->X_add_number < IND_CPUID || l->X_add_number > IND_RR - || l->X_add_number == IND_MEM) + if (r->X_op != O_register + || r->X_add_number < REG_GR + || r->X_add_number > REG_GR + 127) { - as_bad ("Indirect register set name expected"); - l->X_add_number = IND_CPUID; + as_bad ("Indirect register index must be a general register"); + r->X_add_number = REG_GR; } l->X_op = O_index; - l->X_op_symbol = md.regsym[l->X_add_number]; + l->X_op_symbol = md.indregsym[l->X_add_number - IND_CPUID]; l->X_add_number = r->X_add_number; return 1; } } - return 0; + as_bad ("Index can only be applied to rotating or indirect registers"); + /* Fall back to some register use of which has as little as possible + side effects, to minimize subsequent error messages. */ + l->X_op = O_register; + l->X_add_number = REG_GR + 3; + return 1; } int @@ -8148,6 +8342,8 @@ depends_on (depind, idesc) IC:rse-writers. 15+16) Represents reserved instructions, which the assembler does not generate. + 17) CR[TPR] has a RAW dependency only between mov-to-CR-TPR and + mov-to-PSR-l or ssm instructions that set PSR.i, PSR.pp or PSR.up. Memory resources (i.e. locations in memory) are *not* marked or tracked by this code; there are no dependency violations based on memory access. @@ -9236,8 +9432,9 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note) break; case IA64_RS_CRX: - /* Handle all CR[REG] resources */ - if (note == 0 || note == 1) + /* Handle all CR[REG] resources. + ??? FIXME: The rule 17 isn't really handled correctly. */ + if (note == 0 || note == 1 || note == 17) { if (idesc->operands[!rsrc_write] == IA64_OPND_CR3) { @@ -10774,12 +10971,24 @@ md_assemble (str) as_where (&CURR_SLOT.src_file, &CURR_SLOT.src_line); dwarf2_where (&CURR_SLOT.debug_line); - /* Add unwind entry, if there is one. */ + /* Add unwind entries, if there are any. */ if (unwind.current_entry) { CURR_SLOT.unwind_record = unwind.current_entry; unwind.current_entry = NULL; } + if (unwind.pending_saves) + { + if (unwind.pending_saves->next) + { + /* Attach the next pending save to the next slot so that its + slot number will get set correctly. */ + add_unwind_entry (unwind.pending_saves->next, NOT_A_CHAR); + unwind.pending_saves = &unwind.pending_saves->next->r.record.p; + } + else + unwind.pending_saves = NULL; + } if (unwind.proc_pending.sym && S_IS_DEFINED (unwind.proc_pending.sym)) unwind.insn = 1; @@ -10822,7 +11031,7 @@ md_operand (e) { case '[': ++input_line_pointer; - expression (e); + expression_and_evaluate (e); if (*input_line_pointer != ']') { as_bad ("Closing bracket missing"); @@ -10830,8 +11039,13 @@ md_operand (e) } else { - if (e->X_op != O_register) - as_bad ("Register expected as index"); + if (e->X_op != O_register + || e->X_add_number < REG_GR + || e->X_add_number > REG_GR + 127) + { + as_bad ("Index must be a general register"); + e->X_add_number = REG_GR; + } ++input_line_pointer; e->X_op = O_index;