aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog9
-rw-r--r--gas/config/obj-ecoff.c290
-rw-r--r--gas/config/tc-mips.c112
-rw-r--r--gas/config/tc-mips.h5
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 <stab.h>
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 <stab.h>
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];