From 1aa6938eb37f89db944795a21aadb98af7e44399 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 8 Oct 1993 20:01:10 +0000 Subject: [PATCH] * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to hold register masks. (md_begin): Initialize them to zero. (append_insn): Update mips_gprmask and mips_cprmask. Also add register variables pinfo and prev_pinfo. * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare. * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask and cprmask from mips_gprmask and mips_cprmask. --- gas/ChangeLog | 9 ++ gas/config/obj-ecoff.c | 290 +++++++++++++++++++++---------------------------- gas/config/tc-mips.c | 112 ++++++++++++------- gas/config/tc-mips.h | 5 + 4 files changed, 215 insertions(+), 201 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index cdca726..dcd4506 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,14 @@ Fri Oct 8 14:09:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to + hold register masks. + (md_begin): Initialize them to zero. + (append_insn): Update mips_gprmask and mips_cprmask. Also add + register variables pinfo and prev_pinfo. + * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare. + * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask + and cprmask from mips_gprmask and mips_cprmask. + * config/tc-mips.h: Define TARGET_FORMAT if OBJ_ELF. * config/tc-mips.c (GPOPT): Define if OBJ_ECOFF or OBJ_ELF. (various): Change all references to GP references to apply if diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c index 0006c2d..5e66e3a 100644 --- a/gas/config/obj-ecoff.c +++ b/gas/config/obj-ecoff.c @@ -1449,7 +1449,6 @@ static void obj_ecoff_size PARAMS ((int)); static void obj_ecoff_tag PARAMS ((int)); static void obj_ecoff_type PARAMS ((int)); static void obj_ecoff_val PARAMS ((int)); -static void obj_ecoff_stab PARAMS ((int)); static void obj_ecoff_ent PARAMS ((int)); static void obj_ecoff_begin PARAMS ((int)); static void obj_ecoff_bend PARAMS ((int)); @@ -1460,28 +1459,32 @@ static void obj_ecoff_loc PARAMS ((int)); static void obj_ecoff_mask PARAMS ((int)); static void mark_stabs PARAMS ((int)); static char *ecoff_add_bytes PARAMS ((char **buf, char **bufend, - char *bufptr, long need)); -static long ecoff_padding_adjust PARAMS ((char **buf, char **bufend, - long offset, char **bufptrptr)); -static long ecoff_build_lineno PARAMS ((char **buf, char **bufend, - long offset, long *linecntptr)); -static long ecoff_build_symbols PARAMS ((char **buf, char **bufend, - long offset, - char **extbuf, char **extbufend, - long *extoffset, - varray_t *ext_strings, - struct hash_control *ext_str_hash)); -static long ecoff_build_procs PARAMS ((char **buf, char **bufend, - long offset)); -static long ecoff_build_aux PARAMS ((char **buf, char **bufend, - long offset)); -static long ecoff_build_strings PARAMS ((char **buf, char **bufend, - long offset, - varray_t *vp)); -static long ecoff_build_ss PARAMS ((char **buf, char **bufend, - long offset)); -static long ecoff_build_fdr PARAMS ((char **buf, char **bufend, - long offset)); + char *bufptr, unsigned long need)); +static unsigned long ecoff_padding_adjust PARAMS ((char **buf, + char **bufend, + unsigned long offset, + char **bufptrptr)); +static unsigned long ecoff_build_lineno PARAMS ((char **buf, char **bufend, + unsigned long offset, + long *linecntptr)); +static unsigned long ecoff_build_symbols PARAMS ((char **buf, char **bufend, + unsigned long offset, + char **extbuf, + char **extbufend, + unsigned long *extoffset, + varray_t *ext_strings, + struct hash_control *)); +static unsigned long ecoff_build_procs PARAMS ((char **buf, char **bufend, + unsigned long offset)); +static unsigned long ecoff_build_aux PARAMS ((char **buf, char **bufend, + unsigned long offset)); +static unsigned long ecoff_build_strings PARAMS ((char **buf, char **bufend, + unsigned long offset, + varray_t *vp)); +static unsigned long ecoff_build_ss PARAMS ((char **buf, char **bufend, + unsigned long offset)); +static unsigned long ecoff_build_fdr PARAMS ((char **buf, char **bufend, + unsigned long offset)); static page_t *allocate_cluster PARAMS ((unsigned long npages)); static page_t *allocate_page PARAMS ((void)); static scope_t *allocate_scope PARAMS ((void)); @@ -1540,11 +1543,6 @@ const pseudo_typeS obj_pseudo_table[] = { "type", obj_ecoff_type, 0 }, { "val", obj_ecoff_val, 0 }, - /* stabs debugging information. */ - { "stabd", obj_ecoff_stab, 'd' }, - { "stabn", obj_ecoff_stab, 'n' }, - { "stabs", obj_ecoff_stab, 's' }, - /* ECOFF specific debugging information. */ { "begin", obj_ecoff_begin, 0 }, { "bend", obj_ecoff_bend, 0 }, @@ -1634,7 +1632,7 @@ add_string (vp, hash_tbl, str, ret_hash) hash_ptr = (shash_t *) hash_find (hash_tbl, str); if (hash_ptr == (shash_t *) NULL) { - register char *err; + register const char *err; if (vp->objects_last_page + len >= PAGE_USIZE) { @@ -1654,7 +1652,7 @@ add_string (vp, hash_tbl, str, ret_hash) strcpy (hash_ptr->string, str); err = hash_insert (hash_tbl, str, (char *) hash_ptr); - if (*err != '\0') + if (err) as_fatal ("Inserting \"%s\" into string hash table: %s", str, err); } @@ -2085,7 +2083,7 @@ get_tag (tag, sym, basic_type) bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ { shash_t *hash_ptr; - char *err; + const char *err; tag_t *tag_ptr; if (cur_file_ptr == (efdr_t *) NULL) @@ -2110,11 +2108,11 @@ get_tag (tag, sym, basic_type) { char *perm; - perm = xmalloc (strlen (tag) + 1); + perm = xmalloc ((unsigned long) (strlen (tag) + 1)); strcpy (perm, tag); hash_ptr = allocate_shash (); err = hash_insert (tag_hash, perm, (char *) hash_ptr); - if (*err != '\0') + if (err) as_fatal ("Inserting \"%s\" into tag hash table: %s", tag, err); hash_ptr->string = perm; @@ -2127,7 +2125,7 @@ get_tag (tag, sym, basic_type) tag_ptr->basic_type = basic_type; tag_ptr->sym = sym; tag_ptr->ifd = ((sym == (localsym_t *) NULL) - ? -1 + ? (symint_t) -1 : cur_file_ptr->file_index); tag_ptr->same_block = cur_tag_head->first_tag; @@ -2284,7 +2282,8 @@ add_file (file_name, indx) { (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil, symbol_new ("L0\001", now_seg, - frag_now_fix (), frag_now), + (valueT) frag_now_fix (), + frag_now), 0, ECOFF_MARK_STAB (N_SOL)); return; } @@ -2525,7 +2524,7 @@ static sc_t coff_storage_class; static st_t coff_symbol_typ; static int coff_is_function; static char *coff_tag; -static long coff_value; /* FIXME: Might be 64 bits. */ +static valueT coff_value; symbolS *coff_sym_value; static int coff_inside_enumeration; @@ -2553,7 +2552,7 @@ obj_ecoff_def (ignore) free (coff_sym_name); if (coff_tag != (char *) NULL) free (coff_tag); - coff_sym_name = (char *) xmalloc (strlen (name) + 1); + coff_sym_name = (char *) xmalloc ((unsigned long) (strlen (name) + 1)); strcpy (coff_sym_name, name); coff_type = type_info_init; coff_storage_class = sc_Nil; @@ -2781,7 +2780,7 @@ obj_ecoff_tag (ignore) name = input_line_pointer; name_end = get_symbol_end (); - coff_tag = (char *) xmalloc (strlen (name) + 1); + coff_tag = (char *) xmalloc ((unsigned long) (strlen (name) + 1)); strcpy (coff_tag, name); *input_line_pointer = name_end; @@ -2984,7 +2983,7 @@ obj_ecoff_endef (ignore) coff_symbol_typ, coff_storage_class, coff_sym_value, - coff_value, + (symint_t) coff_value, indx); /* deal with struct, union, and enum tags. */ @@ -3053,7 +3052,8 @@ obj_ecoff_end (ignore) else (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, symbol_new ("L0\001", now_seg, - frag_now_fix (), frag_now), + (valueT) frag_now_fix (), + frag_now), (symint_t) 0, (symint_t) 0); cur_proc_ptr = (proc_t *) NULL; @@ -3226,7 +3226,7 @@ obj_ecoff_loc (ignore) int ignore; { lineno_list_t *list; - int lineno; + symint_t lineno; if (cur_file_ptr == (efdr_t *) NULL) { @@ -3260,7 +3260,8 @@ obj_ecoff_loc (ignore) { (void) add_ecoff_symbol ((char *) NULL, st_Label, sc_Text, symbol_new ("L0\001", now_seg, - frag_now_fix (), frag_now), + (valueT) frag_now_fix (), + frag_now), 0, lineno); return; } @@ -3309,13 +3310,16 @@ mark_stabs (ignore) } } -/* Parse .stabs directives. +/* Handle .stabs directives. The actual parsing routine is done by a + generic routine. This routine is called via OBJ_PROCESS_STAB. + When this is called, input_line_pointer will be pointing at the + value field of the stab. .stabs directives have five fields: "string" a string, encoding the type information. code a numeric code, defined in 0 a zero - 0 a zero or line number + desc a zero or line number value a numeric value or an address. If the value is relocatable, we transform this into: @@ -3335,111 +3339,76 @@ mark_stabs (ignore) .stabn directives have four fields (string is null): code a numeric code, defined in 0 a zero - 0 a zero or a line number + desc a zero or a line number value a numeric value or an address. */ -static void -obj_ecoff_stab (type) +void +ecoff_stab (what, string, type, other, desc) + int what; + const char *string; int type; + int other; + int desc; { - char *string; efdr_t *save_file_ptr = cur_file_ptr; - symint_t code; - symint_t value; symbolS *sym; + symint_t value; st_t st; sc_t sc; + symint_t indx; - if (cur_file_ptr == (efdr_t *) NULL) + /* We don't handle .stabd. */ + if (what != 's' && what != 'n') { - add_file ((const char *) NULL, 0); - save_file_ptr = cur_file_ptr; + as_bad (".stab%c is not supported", what); + return; } - if (stabs_seen == 0) - mark_stabs (0); + /* A .stabn uses a null name, not an empty string. */ + if (what == 'n') + string = NULL; - if (type != 's') - string = (char *) NULL; - else - { - int len; + /* We ignore the other field. */ + if (other != 0) + as_warn (".stab%c: ignoring non-zero other field", what); - string = demand_copy_C_string (&len); - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - input_line_pointer++; - else - { - as_warn ("Bad .stab%c directive", type); - demand_empty_rest_of_line (); - return; - } - } - - code = (symint_t) get_absolute_expression (); - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') + /* Make sure we have a current file. */ + if (cur_file_ptr == (efdr_t *) NULL) { - as_warn ("Bad .stab%c directive", type); - --input_line_pointer; - demand_empty_rest_of_line (); - return; + add_file ((const char *) NULL, 0); + save_file_ptr = cur_file_ptr; } - if (get_absolute_expression () != 0) - { - as_warn ("Bad .stab%c directive (expected 0)", type); - demand_empty_rest_of_line (); - return; - } - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') - { - as_warn ("Bad .stab%c directive", type); - --input_line_pointer; - demand_empty_rest_of_line (); - return; - } + /* For stabs in ECOFF, the first symbol must be @stabs. This is a + signal to gdb. */ + if (stabs_seen == 0) + mark_stabs (0); - /* Line number stabs are handled differently, since they have two values, - the line number and the address of the label. We use the index field - (aka code) to hold the line number, and the value field to hold the - address. The symbol type is st_Label, which should be different from - the other stabs, so that gdb can recognize it. */ - if (code == N_SLINE) + /* Line number stabs are handled differently, since they have two + values, the line number and the address of the label. We use the + index field (aka desc) to hold the line number, and the value + field to hold the address. The symbol type is st_Label, which + should be different from the other stabs, so that gdb can + recognize it. */ + if (type == N_SLINE) { SYMR dummy_symr; char *name; char name_end; - code = (symint_t) get_absolute_expression (); - #ifndef NO_LISTING if (listing) - listing_source_line (code); + listing_source_line ((unsigned int) desc); #endif - if (*input_line_pointer++ != ',') - { - as_warn ("Bad .stab%c directive", type); - --input_line_pointer; - demand_empty_rest_of_line (); - return; - } - - dummy_symr.index = code; - if (dummy_symr.index != code) + dummy_symr.index = desc; + if (dummy_symr.index != desc) { - as_warn ("Line number (%lu) for .stab%c directive cannot fit in index field (20 bits)", - code, type); - demand_empty_rest_of_line (); + as_warn ("Line number (%d) for .stab%c directive cannot fit in index field (20 bits)", + desc, what); return; } - SKIP_WHITESPACE (); name = input_line_pointer; name_end = get_symbol_end (); @@ -3449,29 +3418,15 @@ obj_ecoff_stab (type) value = 0; st = st_Label; sc = sc_Text; + indx = desc; } else { #ifndef NO_LISTING - if (listing && (code == N_SO || code == N_SOL)) + if (listing && (type == N_SO || type == N_SOL)) listing_source_file (string); #endif - /* The next number is sometimes the line number of the - declaration. We have nowhere to put it, so we just ignore - it. */ - (void) get_absolute_expression (); - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') - { - as_warn ("Bad .stab%c directive", type); - --input_line_pointer; - demand_empty_rest_of_line (); - return; - } - - SKIP_WHITESPACE (); if (isdigit (*input_line_pointer) || *input_line_pointer == '-' || *input_line_pointer == '+') @@ -3483,8 +3438,7 @@ obj_ecoff_stab (type) } else if (! is_name_beginner ((unsigned char) *input_line_pointer)) { - as_warn ("Illegal .stab%c directive, bad character", type); - demand_empty_rest_of_line (); + as_warn ("Illegal .stab%c directive, bad character", what); return; } else @@ -3511,10 +3465,10 @@ obj_ecoff_stab (type) } } - code = ECOFF_MARK_STAB (code); + indx = ECOFF_MARK_STAB (type); } - (void) add_ecoff_symbol (string, st, sc, sym, value, code); + (void) add_ecoff_symbol (string, st, sc, sym, value, indx); /* Restore normal file type. */ cur_file_ptr = save_file_ptr; @@ -3527,7 +3481,7 @@ ecoff_add_bytes (buf, bufend, bufptr, need) char **buf; char **bufend; char *bufptr; - long need; + unsigned long need; { unsigned long at; unsigned long want; @@ -3545,11 +3499,11 @@ ecoff_add_bytes (buf, bufend, bufptr, need) /* Adjust the symbolic information buffer to the alignment required for the ECOFF target debugging information. */ -static long +static unsigned long ecoff_padding_adjust (buf, bufend, offset, bufptrptr) char **buf; char **bufend; - long offset; + unsigned long offset; char **bufptrptr; { bfd_size_type align; @@ -3557,7 +3511,7 @@ ecoff_padding_adjust (buf, bufend, offset, bufptrptr) align = ecoff_backend (stdoutput)->debug_align; if ((offset & (align - 1)) != 0) { - long add; + unsigned long add; add = align - (offset & (align - 1)); if (*bufend - (*buf + offset) < add) @@ -3573,11 +3527,11 @@ ecoff_padding_adjust (buf, bufend, offset, bufptrptr) /* Build the line number information. */ -static long +static unsigned long ecoff_build_lineno (buf, bufend, offset, linecntptr) char **buf; char **bufend; - long offset; + unsigned long offset; long *linecntptr; { char *bufptr; @@ -3585,7 +3539,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) lineno_list_t *last; efdr_t *file; proc_t *proc; - long c; + unsigned long c; long iline; long totcount; @@ -3764,7 +3718,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr) /* Build and swap out the symbols. */ -static long +static unsigned long ecoff_build_symbols (buf, bufend, offset, @@ -3775,10 +3729,10 @@ ecoff_build_symbols (buf, ext_str_hash) char **buf; char **bufend; - long offset; + unsigned long offset; char **extbuf; char **extbufend; - long *extoffset; + unsigned long *extoffset; varray_t *ext_strings; struct hash_control *ext_str_hash; { @@ -4120,11 +4074,11 @@ ecoff_build_symbols (buf, /* Swap out the procedure information. */ -static long +static unsigned long ecoff_build_procs (buf, bufend, offset) char **buf; char **bufend; - long offset; + unsigned long offset; { const bfd_size_type external_pdr_size = ecoff_backend (stdoutput)->external_pdr_size; @@ -4212,11 +4166,11 @@ ecoff_build_procs (buf, bufend, offset) /* Swap out the aux information. */ -static long +static unsigned long ecoff_build_aux (buf, bufend, offset) char **buf; char **bufend; - long offset; + unsigned long offset; { int bigendian; union aux_ext *aux_out; @@ -4321,14 +4275,14 @@ ecoff_build_aux (buf, bufend, offset) /* Copy out the strings from a varray_t. This returns the number of bytes copied, rather than the new offset. */ -static long +static unsigned long ecoff_build_strings (buf, bufend, offset, vp) char **buf; char **bufend; - long offset; + unsigned long offset; varray_t *vp; { - long istr; + unsigned long istr; char *str_out; vlinks_t *str_link; @@ -4340,7 +4294,7 @@ ecoff_build_strings (buf, bufend, offset, vp) str_link != (vlinks_t *) NULL; str_link = str_link->next) { - long str_cnt; + unsigned long str_cnt; if (str_link->next == (vlinks_t *) NULL) str_cnt = vp->objects_last_page; @@ -4360,11 +4314,11 @@ ecoff_build_strings (buf, bufend, offset, vp) /* Dump out the local strings. */ -static long +static unsigned long ecoff_build_ss (buf, bufend, offset) char **buf; char **bufend; - long offset; + unsigned long offset; { long iss; vlinks_t *file_link; @@ -4402,11 +4356,11 @@ ecoff_build_ss (buf, bufend, offset) /* Swap out the file descriptors. */ -static long +static unsigned long ecoff_build_fdr (buf, bufend, offset) char **buf; char **bufend; - long offset; + unsigned long offset; { const bfd_size_type external_fdr_size = ecoff_backend (stdoutput)->external_fdr_size; @@ -4467,10 +4421,10 @@ ecoff_frob_file () HDRR *hdr; char *buf; char *bufend; - long offset; + unsigned long offset; char *extbuf; char *extbufend; - long extoffset; + unsigned long extoffset; varray_t ext_strings; static varray_t init_ext_strings = INIT_VARRAY (char); struct hash_control *ext_str_hash; @@ -4651,7 +4605,15 @@ ecoff_frob_file () #undef SET - /* FIXME: set the register masks. */ +#ifdef TC_MIPS + /* Get the MIPS register masks. It's probably not worth setting up + a generic interface for this. */ + ecoff_data (stdoutput)->gprmask = mips_gprmask; + ecoff_data (stdoutput)->cprmask[0] = mips_cprmask[0]; + ecoff_data (stdoutput)->cprmask[1] = mips_cprmask[1]; + ecoff_data (stdoutput)->cprmask[2] = mips_cprmask[2]; + ecoff_data (stdoutput)->cprmask[3] = mips_cprmask[3]; +#endif ecoff_data (stdoutput)->raw_size = offset; ecoff_data (stdoutput)->raw_syments = buf; @@ -4660,7 +4622,7 @@ ecoff_frob_file () /* FIXME: what should hdr->vstamp be? */ bfd_set_symtab (stdoutput, bfd_get_outsymbols (stdoutput), - hdr->isymMax + hdr->iextMax); + (unsigned int) (hdr->isymMax + hdr->iextMax)); } /* Allocate a cluster of pages. */ diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index f7b1947..e03a4bc 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -56,6 +56,12 @@ #define GPOPT #endif +/* These variables are filled in with the masks of registers used. + The object format code reads them and puts them in the appropriate + place. */ +unsigned long mips_gprmask; +unsigned long mips_cprmask[4]; + /* MIPS ISA (Instruction Set Architecture) level. */ static int mips_isa = -1; @@ -367,6 +373,12 @@ md_begin () mips_no_prev_insn (); + mips_gprmask = 0; + mips_cprmask[0] = 0; + mips_cprmask[1] = 0; + mips_cprmask[2] = 0; + mips_cprmask[3] = 0; + /* set the default alignment for the text section (2**2) */ record_alignment (text_section, 2); @@ -477,10 +489,14 @@ append_insn (ip, address_expr, reloc_type) expressionS *address_expr; bfd_reloc_code_real_type reloc_type; { + register unsigned long prev_pinfo, pinfo; char *f; fixS *fixp; int nops = 0; + prev_pinfo = prev_insn.insn_mo->pinfo; + pinfo = ip->insn_mo->pinfo; + if (! mips_noreorder) { /* If the previous insn required any delay slots, see if we need @@ -508,15 +524,15 @@ append_insn (ip, address_expr, reloc_type) /* The previous insn might require a delay slot, depending upon the contents of the current insn. */ - if ((prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY) + if ((prev_pinfo & INSN_LOAD_COPROC_DELAY) || (mips_isa < 2 - && (prev_insn.insn_mo->pinfo & INSN_LOAD_MEMORY_DELAY))) + && (prev_pinfo & INSN_LOAD_MEMORY_DELAY))) { /* A load from a coprocessor or from memory. All load delays delay the use of general register rt for one instruction on the r3000. The r6000 and r4000 use interlocks. */ - know (prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T); + know (prev_pinfo & INSN_WRITE_GPR_T); if (mips_optimize == 0 || insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RT) @@ -524,9 +540,9 @@ append_insn (ip, address_expr, reloc_type) 0)) ++nops; } - else if ((prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY) + else if ((prev_pinfo & INSN_COPROC_MOVE_DELAY) || (mips_isa < 2 - && (prev_insn.insn_mo->pinfo & INSN_COPROC_MEMORY_DELAY))) + && (prev_pinfo & INSN_COPROC_MEMORY_DELAY))) { /* A generic coprocessor delay. The previous instruction modified a coprocessor general or control register. If @@ -542,7 +558,7 @@ append_insn (ip, address_expr, reloc_type) knowledge of CP0 handling, and the coprocessors other than the floating point unit are not distinguished at all. */ - if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_T) + if (prev_pinfo & INSN_WRITE_FPR_T) { if (mips_optimize == 0 || insn_uses_reg (ip, @@ -551,7 +567,7 @@ append_insn (ip, address_expr, reloc_type) 1)) ++nops; } - else if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_S) + else if (prev_pinfo & INSN_WRITE_FPR_S) { if (mips_optimize == 0 || insn_uses_reg (ip, @@ -569,14 +585,14 @@ append_insn (ip, address_expr, reloc_type) current instruction uses them, we must insert two NOPS. */ if (mips_optimize == 0 - || ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) - && (ip->insn_mo->pinfo & INSN_READ_COND_CODE))) + || ((prev_pinfo & INSN_WRITE_COND_CODE) + && (pinfo & INSN_READ_COND_CODE))) nops += 2; - else if (ip->insn_mo->pinfo & INSN_COP) + else if (pinfo & INSN_COP) ++nops; } } - else if (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) + else if (prev_pinfo & INSN_WRITE_COND_CODE) { /* The previous instruction sets the coprocessor condition codes, but does not require a general coprocessor delay @@ -584,16 +600,16 @@ append_insn (ip, address_expr, reloc_type) instruction). If this instruction uses the condition codes, we need to insert a single NOP. */ if (mips_optimize == 0 - || ip->insn_mo->pinfo & INSN_READ_COND_CODE) + || (pinfo & INSN_READ_COND_CODE)) ++nops; } - else if (prev_insn.insn_mo->pinfo & INSN_READ_LO) + else if (prev_pinfo & INSN_READ_LO) { /* The previous instruction reads the LO register; if the current instruction writes to the LO register, we must insert two NOPS. */ if (mips_optimize == 0 - || ip->insn_mo->pinfo & INSN_WRITE_LO) + || (pinfo & INSN_WRITE_LO)) nops += 2; } else if (prev_insn.insn_mo->pinfo & INSN_READ_HI) @@ -602,7 +618,7 @@ append_insn (ip, address_expr, reloc_type) current instruction writes to the HI register, we must insert a NOP. */ if (mips_optimize == 0 - || ip->insn_mo->pinfo & INSN_WRITE_HI) + || (pinfo & INSN_WRITE_HI)) nops += 2; } @@ -617,11 +633,11 @@ append_insn (ip, address_expr, reloc_type) if (nops == 0 && (((prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY) && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE) - && (ip->insn_mo->pinfo & INSN_READ_COND_CODE)) + && (pinfo & INSN_READ_COND_CODE)) || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO) - && (ip->insn_mo->pinfo & INSN_WRITE_LO)) + && (pinfo & INSN_WRITE_LO)) || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI) - && (ip->insn_mo->pinfo & INSN_WRITE_HI)))) + && (pinfo & INSN_WRITE_HI)))) ++nops; /* Now emit the right number of NOP instructions. */ @@ -685,6 +701,28 @@ append_insn (ip, address_expr, reloc_type) md_number_to_chars (f, ip->insn_opcode, 4); + /* Update the register mask information. */ + if (pinfo & INSN_WRITE_GPR_D) + mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD); + if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0) + mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT); + if (pinfo & INSN_READ_GPR_S) + mips_gprmask |= 1 << ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS); + if (pinfo & INSN_WRITE_GPR_31) + mips_gprmask |= 1 << 31; + if (pinfo & INSN_WRITE_FPR_D) + mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FD) & OP_MASK_FD); + if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0) + mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS); + if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0) + mips_cprmask[1] |= 1 << ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT); + if (pinfo & INSN_COP) + { + /* We don't keep enough information to sort these cases out. */ + } + /* Never set the bit for $0, which is always zero. */ + mips_gprmask &=~ 1 << 0; + if (! mips_noreorder) { /* Filling the branch delay slot is more complex. We try to @@ -692,8 +730,8 @@ append_insn (ip, address_expr, reloc_type) do if the previous instruction does not set up a condition that the branch tests and if the branch is not itself the target of any branch. */ - if ((ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY) - || (ip->insn_mo->pinfo & INSN_COND_BRANCH_DELAY)) + if ((pinfo & INSN_UNCOND_BRANCH_DELAY) + || (pinfo & INSN_COND_BRANCH_DELAY)) { if (mips_optimize < 2 /* If we have seen .set nobopt, don't optimize. */ @@ -741,37 +779,37 @@ append_insn (ip, address_expr, reloc_type) bc1t LABEL we can not swap, and I don't feel like handling that case. */ - || (ip->insn_mo->pinfo & INSN_READ_COND_CODE) + || (pinfo & INSN_READ_COND_CODE) /* We can not swap with an instruction that requires a delay slot, becase the target of the branch might interfere with that instruction. */ - || (prev_insn.insn_mo->pinfo + || (prev_pinfo & (INSN_LOAD_COPROC_DELAY | INSN_COPROC_MOVE_DELAY | INSN_WRITE_COND_CODE | INSN_READ_LO | INSN_READ_HI)) || (mips_isa < 2 - && (prev_insn.insn_mo->pinfo + && (prev_pinfo & (INSN_LOAD_MEMORY_DELAY | INSN_COPROC_MEMORY_DELAY))) /* We can not swap with a branch instruction. */ - || (prev_insn.insn_mo->pinfo + || (prev_pinfo & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY | INSN_COND_BRANCH_LIKELY)) /* We do not swap with a trap instruction, since it complicates trap handlers to have the trap instruction be in a delay slot. */ - || (prev_insn.insn_mo->pinfo & INSN_TRAP) + || (prev_pinfo & INSN_TRAP) /* If the branch reads a register that the previous instruction sets, we can not swap. */ - || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T) + || ((prev_pinfo & INSN_WRITE_GPR_T) && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT), 0)) - || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D) + || ((prev_pinfo & INSN_WRITE_GPR_D) && insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD), @@ -779,31 +817,31 @@ append_insn (ip, address_expr, reloc_type) /* If the branch writes a register that the previous instruction sets, we can not swap (we know that branches write only to RD or to $31). */ - || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T) - && (((ip->insn_mo->pinfo & INSN_WRITE_GPR_D) + || ((prev_pinfo & INSN_WRITE_GPR_T) + && (((pinfo & INSN_WRITE_GPR_D) && (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT) == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD))) - || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31) + || ((pinfo & INSN_WRITE_GPR_31) && (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT) == 31)))) - || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D) - && (((ip->insn_mo->pinfo & INSN_WRITE_GPR_D) + || ((prev_pinfo & INSN_WRITE_GPR_D) + && (((pinfo & INSN_WRITE_GPR_D) && (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD) == ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD))) - || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31) + || ((pinfo & INSN_WRITE_GPR_31) && (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD) == 31)))) /* If the branch writes a register that the previous instruction reads, we can not swap (we know that branches only write to RD or to $31). */ - || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_D) + || ((pinfo & INSN_WRITE_GPR_D) && insn_uses_reg (&prev_insn, ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD), 0)) - || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31) + || ((pinfo & INSN_WRITE_GPR_31) && insn_uses_reg (&prev_insn, 31, 0)) /* If the previous previous instruction has a load delay, and sets a register that the branch reads, we @@ -854,13 +892,13 @@ append_insn (ip, address_expr, reloc_type) /* If that was an unconditional branch, forget the previous insn information. */ - if (ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY) + if (pinfo & INSN_UNCOND_BRANCH_DELAY) { prev_prev_insn.insn_mo = &dummy_opcode; prev_insn.insn_mo = &dummy_opcode; } } - else if (ip->insn_mo->pinfo & INSN_COND_BRANCH_LIKELY) + else if (pinfo & INSN_COND_BRANCH_LIKELY) { /* We don't yet optimize a branch likely. What we should do is look at the target, copy the instruction found there diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h index dca09a8..4aba744 100644 --- a/gas/config/tc-mips.h +++ b/gas/config/tc-mips.h @@ -95,3 +95,8 @@ extern void mips_define_label PARAMS ((struct symbol *)); #define TC_CONS_FIX_NEW cons_fix_new_mips extern void cons_fix_new_mips (); + +/* Register mask variables. These are set by the MIPS assembly code + and used by ECOFF and possibly other object file formats. */ +extern unsigned long mips_gprmask; +extern unsigned long mips_cprmask[4]; -- 2.7.4