* config/tc-mips.h (mips_flush_pending_output): Delete.
(mips_emit_delays): Declare. (md_flush_pending_output): Use mips_emit_delays. * config/tc-mips.c (mips_no_prev_insn): Remove parameter; always forget the previous instructions. (md_begin, append_insn, md_parse_option): Update callers. (mips_emit_delay): Remove parameter. Move INSNS != 0 code to start_noreorder. (mips_align, s_change_sec, s_cons, s_float_cons, s_gpword) (s_gpdword): Update callers. (start_noreorder, end_noreorder): New functions. (macro, macro2, mips16_macro, s_mipsset): Use them instead of manipulating mips_opts or prev_nop_frag directly. (mips_flush_pending_output): Delete.
This commit is contained in:
parent
404a80717c
commit
7d10b47d34
3 changed files with 116 additions and 118 deletions
|
@ -1,3 +1,20 @@
|
|||
2005-03-09 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/tc-mips.h (mips_flush_pending_output): Delete.
|
||||
(mips_emit_delays): Declare.
|
||||
(md_flush_pending_output): Use mips_emit_delays.
|
||||
* config/tc-mips.c (mips_no_prev_insn): Remove parameter; always forget
|
||||
the previous instructions.
|
||||
(md_begin, append_insn, md_parse_option): Update callers.
|
||||
(mips_emit_delay): Remove parameter. Move INSNS != 0 code to
|
||||
start_noreorder.
|
||||
(mips_align, s_change_sec, s_cons, s_float_cons, s_gpword)
|
||||
(s_gpdword): Update callers.
|
||||
(start_noreorder, end_noreorder): New functions.
|
||||
(macro, macro2, mips16_macro, s_mipsset): Use them instead of
|
||||
manipulating mips_opts or prev_nop_frag directly.
|
||||
(mips_flush_pending_output): Delete.
|
||||
|
||||
2005-03-09 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/tc-mips.c (mips_move_labels): New function, taken from...
|
||||
|
|
|
@ -928,7 +928,7 @@ enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
|
|||
|
||||
static void append_insn
|
||||
(struct mips_cl_insn *ip, expressionS *p, bfd_reloc_code_real_type *r);
|
||||
static void mips_no_prev_insn (int);
|
||||
static void mips_no_prev_insn (void);
|
||||
static void mips16_macro_build
|
||||
(expressionS *, const char *, const char *, va_list);
|
||||
static void load_register (int, expressionS *, int);
|
||||
|
@ -1477,7 +1477,7 @@ md_begin (void)
|
|||
&zero_address_frag));
|
||||
}
|
||||
|
||||
mips_no_prev_insn (FALSE);
|
||||
mips_no_prev_insn ();
|
||||
|
||||
mips_gprmask = 0;
|
||||
mips_cprmask[0] = 0;
|
||||
|
@ -2664,7 +2664,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||
/* If that was an unconditional branch, forget the previous
|
||||
insn information. */
|
||||
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
|
||||
mips_no_prev_insn (FALSE);
|
||||
mips_no_prev_insn ();
|
||||
}
|
||||
else if (pinfo & INSN_COND_BRANCH_LIKELY)
|
||||
{
|
||||
|
@ -2685,49 +2685,57 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||
mips_clear_insn_labels ();
|
||||
}
|
||||
|
||||
/* This function forgets that there was any previous instruction or
|
||||
label. If PRESERVE is non-zero, it remembers enough information to
|
||||
know whether nops are needed before a noreorder section. */
|
||||
/* Forget that there was any previous instruction or label. */
|
||||
|
||||
static void
|
||||
mips_no_prev_insn (int preserve)
|
||||
mips_no_prev_insn (void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (! preserve)
|
||||
{
|
||||
prev_nop_frag = NULL;
|
||||
prev_nop_frag_holds = 0;
|
||||
prev_nop_frag_required = 0;
|
||||
prev_nop_frag_since = 0;
|
||||
for (i = 0; i < ARRAY_SIZE (history); i++)
|
||||
history[i] = (mips_opts.mips16 ? mips16_nop_insn : nop_insn);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < ARRAY_SIZE (history); i++)
|
||||
{
|
||||
history[i].fixed_p = 1;
|
||||
history[i].noreorder_p = 0;
|
||||
history[i].mips16_absolute_jump_p = 0;
|
||||
}
|
||||
prev_nop_frag = NULL;
|
||||
insert_into_history (0, ARRAY_SIZE (history), NOP_INSN);
|
||||
mips_clear_insn_labels ();
|
||||
}
|
||||
|
||||
/* This function must be called whenever we turn on noreorder or emit
|
||||
something other than instructions. It inserts any NOPS which might
|
||||
be needed by the previous instruction, and clears the information
|
||||
kept for the previous instructions. The INSNS parameter is true if
|
||||
instructions are to follow. */
|
||||
/* This function must be called before we emit something other than
|
||||
instructions. It is like mips_no_prev_insn except that it inserts
|
||||
any NOPS that might be needed by previous instructions. */
|
||||
|
||||
static void
|
||||
mips_emit_delays (bfd_boolean insns)
|
||||
void
|
||||
mips_emit_delays (void)
|
||||
{
|
||||
if (! mips_opts.noreorder)
|
||||
{
|
||||
int nops = nops_for_insn (history, NULL);
|
||||
if (nops > 0)
|
||||
{
|
||||
if (insns && mips_optimize != 0)
|
||||
while (nops-- > 0)
|
||||
add_fixed_insn (NOP_INSN);
|
||||
mips_move_labels ();
|
||||
}
|
||||
}
|
||||
mips_no_prev_insn ();
|
||||
}
|
||||
|
||||
/* Start a (possibly nested) noreorder block. */
|
||||
|
||||
static void
|
||||
start_noreorder (void)
|
||||
{
|
||||
if (mips_opts.noreorder == 0)
|
||||
{
|
||||
unsigned int i;
|
||||
int nops;
|
||||
|
||||
/* None of the instructions before the .set noreorder can be moved. */
|
||||
for (i = 0; i < ARRAY_SIZE (history); i++)
|
||||
history[i].fixed_p = 1;
|
||||
|
||||
/* Insert any nops that might be needed between the .set noreorder
|
||||
block and the previous instructions. We will later remove any
|
||||
nops that turn out not to be needed. */
|
||||
nops = nops_for_insn (history, NULL);
|
||||
if (nops > 0)
|
||||
{
|
||||
if (mips_optimize != 0)
|
||||
{
|
||||
/* Record the frag which holds the nop instructions, so
|
||||
that we can remove them if we don't need them. */
|
||||
|
@ -2741,23 +2749,35 @@ mips_emit_delays (bfd_boolean insns)
|
|||
for (; nops > 0; --nops)
|
||||
add_fixed_insn (NOP_INSN);
|
||||
|
||||
if (insns)
|
||||
{
|
||||
/* Move on to a new frag, so that it is safe to simply
|
||||
decrease the size of prev_nop_frag. */
|
||||
frag_wane (frag_now);
|
||||
frag_new (0);
|
||||
}
|
||||
|
||||
/* Move on to a new frag, so that it is safe to simply
|
||||
decrease the size of prev_nop_frag. */
|
||||
frag_wane (frag_now);
|
||||
frag_new (0);
|
||||
mips_move_labels ();
|
||||
}
|
||||
mips16_mark_labels ();
|
||||
mips_clear_insn_labels ();
|
||||
}
|
||||
mips_opts.noreorder++;
|
||||
mips_any_noreorder = 1;
|
||||
}
|
||||
|
||||
/* Mark instruction labels in mips16 mode. */
|
||||
if (insns)
|
||||
mips16_mark_labels ();
|
||||
/* End a nested noreorder block. */
|
||||
|
||||
mips_no_prev_insn (insns);
|
||||
static void
|
||||
end_noreorder (void)
|
||||
{
|
||||
mips_opts.noreorder--;
|
||||
if (mips_opts.noreorder == 0 && prev_nop_frag != NULL)
|
||||
{
|
||||
/* Commit to inserting prev_nop_frag_required nops and go back to
|
||||
handling nop insertion the .set reorder way. */
|
||||
prev_nop_frag->fr_fix -= ((prev_nop_frag_holds - prev_nop_frag_required)
|
||||
* (mips_opts.mips16 ? 2 : 4));
|
||||
insert_into_history (prev_nop_frag_since,
|
||||
prev_nop_frag_required, NOP_INSN);
|
||||
prev_nop_frag = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up global variables for the start of a new macro. */
|
||||
|
@ -4061,9 +4081,7 @@ macro (struct mips_cl_insn *ip)
|
|||
sub v0,$zero,$a0
|
||||
*/
|
||||
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
|
||||
expr1.X_add_number = 8;
|
||||
macro_build (&expr1, "bgez", "s,p", sreg);
|
||||
|
@ -4073,7 +4091,7 @@ macro (struct mips_cl_insn *ip)
|
|||
move_register (dreg, sreg);
|
||||
macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg);
|
||||
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
break;
|
||||
|
||||
case M_ADD_I:
|
||||
|
@ -4581,9 +4599,7 @@ macro (struct mips_cl_insn *ip)
|
|||
break;
|
||||
}
|
||||
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
if (mips_trap)
|
||||
{
|
||||
macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
|
||||
|
@ -4617,7 +4633,7 @@ macro (struct mips_cl_insn *ip)
|
|||
macro_build (NULL, "teq", "s,t,q", sreg, AT, 6);
|
||||
/* We want to close the noreorder block as soon as possible, so
|
||||
that later insns are available for delay slot filling. */
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4627,7 +4643,7 @@ macro (struct mips_cl_insn *ip)
|
|||
|
||||
/* We want to close the noreorder block as soon as possible, so
|
||||
that later insns are available for delay slot filling. */
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
|
||||
macro_build (NULL, "break", "c", 6);
|
||||
}
|
||||
|
@ -4722,16 +4738,14 @@ macro (struct mips_cl_insn *ip)
|
|||
s = "ddivu";
|
||||
s2 = "mfhi";
|
||||
do_divu3:
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
if (mips_trap)
|
||||
{
|
||||
macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
|
||||
macro_build (NULL, s, "z,s,t", sreg, treg);
|
||||
/* We want to close the noreorder block as soon as possible, so
|
||||
that later insns are available for delay slot filling. */
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4741,7 +4755,7 @@ macro (struct mips_cl_insn *ip)
|
|||
|
||||
/* We want to close the noreorder block as soon as possible, so
|
||||
that later insns are available for delay slot filling. */
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
macro_build (NULL, "break", "c", 7);
|
||||
}
|
||||
macro_build (NULL, s2, "d", dreg);
|
||||
|
@ -6669,9 +6683,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
dbl = 1;
|
||||
case M_MULO:
|
||||
do_mulo:
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
used_at = 1;
|
||||
if (imm)
|
||||
load_register (AT, &imm_expr, dbl);
|
||||
|
@ -6688,7 +6700,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
macro_build (NULL, "nop", "", 0);
|
||||
macro_build (NULL, "break", "c", 6);
|
||||
}
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
macro_build (NULL, "mflo", "d", dreg);
|
||||
break;
|
||||
|
||||
|
@ -6702,9 +6714,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
dbl = 1;
|
||||
case M_MULOU:
|
||||
do_mulou:
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
used_at = 1;
|
||||
if (imm)
|
||||
load_register (AT, &imm_expr, dbl);
|
||||
|
@ -6721,7 +6731,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
macro_build (NULL, "nop", "", 0);
|
||||
macro_build (NULL, "break", "c", 6);
|
||||
}
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
break;
|
||||
|
||||
case M_DROL:
|
||||
|
@ -7186,9 +7196,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
* Is the double cfc1 instruction a bug in the mips assembler;
|
||||
* or is there a reason for it?
|
||||
*/
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
macro_build (NULL, "cfc1", "t,G", treg, RA);
|
||||
macro_build (NULL, "cfc1", "t,G", treg, RA);
|
||||
macro_build (NULL, "nop", "");
|
||||
|
@ -7202,7 +7210,7 @@ macro2 (struct mips_cl_insn *ip)
|
|||
dreg, sreg);
|
||||
macro_build (NULL, "ctc1", "t,G", treg, RA);
|
||||
macro_build (NULL, "nop", "");
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
break;
|
||||
|
||||
case M_ULH:
|
||||
|
@ -7442,9 +7450,7 @@ mips16_macro (struct mips_cl_insn *ip)
|
|||
case M_REM_3:
|
||||
s = "mfhi";
|
||||
do_div3:
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
macro_build (NULL, dbl ? "ddiv" : "div", "0,x,y", xreg, yreg);
|
||||
expr1.X_add_number = 2;
|
||||
macro_build (&expr1, "bnez", "x,p", yreg);
|
||||
|
@ -7454,7 +7460,7 @@ mips16_macro (struct mips_cl_insn *ip)
|
|||
since that causes an overflow. We should do that as well,
|
||||
but I don't see how to do the comparisons without a temporary
|
||||
register. */
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
macro_build (NULL, s, "x", zreg);
|
||||
break;
|
||||
|
||||
|
@ -7474,14 +7480,12 @@ mips16_macro (struct mips_cl_insn *ip)
|
|||
s = "ddivu";
|
||||
s2 = "mfhi";
|
||||
do_divu3:
|
||||
mips_emit_delays (TRUE);
|
||||
++mips_opts.noreorder;
|
||||
mips_any_noreorder = 1;
|
||||
start_noreorder ();
|
||||
macro_build (NULL, s, "0,x,y", xreg, yreg);
|
||||
expr1.X_add_number = 2;
|
||||
macro_build (&expr1, "bnez", "x,p", yreg);
|
||||
macro_build (NULL, "break", "6", 7);
|
||||
--mips_opts.noreorder;
|
||||
end_noreorder ();
|
||||
macro_build (NULL, s2, "x", zreg);
|
||||
break;
|
||||
|
||||
|
@ -10194,12 +10198,12 @@ md_parse_option (int c, char *arg)
|
|||
|
||||
case OPTION_MIPS16:
|
||||
mips_opts.mips16 = 1;
|
||||
mips_no_prev_insn (FALSE);
|
||||
mips_no_prev_insn ();
|
||||
break;
|
||||
|
||||
case OPTION_NO_MIPS16:
|
||||
mips_opts.mips16 = 0;
|
||||
mips_no_prev_insn (FALSE);
|
||||
mips_no_prev_insn ();
|
||||
break;
|
||||
|
||||
case OPTION_MIPS3D:
|
||||
|
@ -11058,7 +11062,7 @@ get_symbol (void)
|
|||
static void
|
||||
mips_align (int to, int fill, symbolS *label)
|
||||
{
|
||||
mips_emit_delays (FALSE);
|
||||
mips_emit_delays ();
|
||||
frag_align (to, fill, 0);
|
||||
record_alignment (now_seg, to);
|
||||
if (label != NULL)
|
||||
|
@ -11120,13 +11124,6 @@ s_align (int x ATTRIBUTE_UNUSED)
|
|||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
mips_flush_pending_output (void)
|
||||
{
|
||||
mips_emit_delays (FALSE);
|
||||
mips_clear_insn_labels ();
|
||||
}
|
||||
|
||||
static void
|
||||
s_change_sec (int sec)
|
||||
{
|
||||
|
@ -11142,7 +11139,7 @@ s_change_sec (int sec)
|
|||
obj_elf_section_change_hook ();
|
||||
#endif
|
||||
|
||||
mips_emit_delays (FALSE);
|
||||
mips_emit_delays ();
|
||||
switch (sec)
|
||||
{
|
||||
case 't':
|
||||
|
@ -11273,7 +11270,7 @@ s_cons (int log_size)
|
|||
symbolS *label;
|
||||
|
||||
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||
mips_emit_delays (FALSE);
|
||||
mips_emit_delays ();
|
||||
if (log_size > 0 && auto_align)
|
||||
mips_align (log_size, 0, label);
|
||||
mips_clear_insn_labels ();
|
||||
|
@ -11287,7 +11284,7 @@ s_float_cons (int type)
|
|||
|
||||
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||
|
||||
mips_emit_delays (FALSE);
|
||||
mips_emit_delays ();
|
||||
|
||||
if (auto_align)
|
||||
{
|
||||
|
@ -11415,22 +11412,13 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
|
|||
|
||||
if (strcmp (name, "reorder") == 0)
|
||||
{
|
||||
if (mips_opts.noreorder && prev_nop_frag != NULL)
|
||||
{
|
||||
/* If we still have pending nops, we can discard them. The
|
||||
usual nop handling will insert any that are still
|
||||
needed. */
|
||||
prev_nop_frag->fr_fix -= (prev_nop_frag_holds
|
||||
* (mips_opts.mips16 ? 2 : 4));
|
||||
prev_nop_frag = NULL;
|
||||
}
|
||||
mips_opts.noreorder = 0;
|
||||
if (mips_opts.noreorder)
|
||||
end_noreorder ();
|
||||
}
|
||||
else if (strcmp (name, "noreorder") == 0)
|
||||
{
|
||||
mips_emit_delays (TRUE);
|
||||
mips_opts.noreorder = 1;
|
||||
mips_any_noreorder = 1;
|
||||
if (!mips_opts.noreorder)
|
||||
start_noreorder ();
|
||||
}
|
||||
else if (strcmp (name, "at") == 0)
|
||||
{
|
||||
|
@ -11575,16 +11563,9 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
|
|||
/* If we're changing the reorder mode we need to handle
|
||||
delay slots correctly. */
|
||||
if (s->options.noreorder && ! mips_opts.noreorder)
|
||||
mips_emit_delays (TRUE);
|
||||
start_noreorder ();
|
||||
else if (! s->options.noreorder && mips_opts.noreorder)
|
||||
{
|
||||
if (prev_nop_frag != NULL)
|
||||
{
|
||||
prev_nop_frag->fr_fix -= (prev_nop_frag_holds
|
||||
* (mips_opts.mips16 ? 2 : 4));
|
||||
prev_nop_frag = NULL;
|
||||
}
|
||||
}
|
||||
end_noreorder ();
|
||||
|
||||
mips_opts = s->options;
|
||||
mips_opts_stack = s->next;
|
||||
|
@ -11924,7 +11905,7 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
|
|||
}
|
||||
|
||||
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||
mips_emit_delays (TRUE);
|
||||
mips_emit_delays ();
|
||||
if (auto_align)
|
||||
mips_align (2, 0, label);
|
||||
mips_clear_insn_labels ();
|
||||
|
@ -11960,7 +11941,7 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
|
|||
}
|
||||
|
||||
label = insn_labels != NULL ? insn_labels->label : NULL;
|
||||
mips_emit_delays (TRUE);
|
||||
mips_emit_delays ();
|
||||
if (auto_align)
|
||||
mips_align (3, 0, label);
|
||||
mips_clear_insn_labels ();
|
||||
|
|
|
@ -149,8 +149,8 @@ extern void md_mips_end (void);
|
|||
extern void mips_pop_insert (void);
|
||||
#define md_pop_insert() mips_pop_insert()
|
||||
|
||||
extern void mips_flush_pending_output (void);
|
||||
#define md_flush_pending_output mips_flush_pending_output
|
||||
extern void mips_emit_delays (void);
|
||||
#define md_flush_pending_output mips_emit_delays
|
||||
|
||||
extern void mips_enable_auto_align (void);
|
||||
#define md_elf_section_change_hook() mips_enable_auto_align()
|
||||
|
|
Loading…
Reference in a new issue