Rework MIPS nop-insertion code, add -mfix-vr4130 [5/11]
Richard Sandiford
rsandifo@redhat.com
Tue Mar 8 14:56:00 GMT 2005
This patch introduces a new set of functions for handling mips_cl_insns
and for manipulating the history buffer:
- create_insn
Initialise a mips_cl_insn from an opcode entry
- install_insn
Install a mips_cl_insn's opcode at the position specified
by its frag and where fields.
- move_insn
Change the position of a mips_cl_insn.
- add_fixed_insn
Install a mips_cl_insn at the end of the current frag.
- add_relaxed_insn
Start a variant frag and install a mips_cl_insn at the
start of the variant part.
- insert_into_history
Insert copies of a mips_cl_insn into the history buffer.
- emit_nop
Add a nop to the end of the current frag and record it
in the history buffer.
Most of this is just cleanup, but the new behaviour of emit_nop() is
important. It means that append_insn() now adds nops to the history
buffer at the same time as emitting the nops, not when emitting the
instruction _after_ the nops. This simplified some later changes.
Tested on mips64{,el}-linux-gnu and mipsisa64{,el}-elf. OK to install?
Richard
* config/tc-mips.c (dummy_opcode): Delete.
(nop_insn, mips16_nop_insn): New variables.
(NOP_INSN): New macro.
(insn_length, create_insn, install_insn, move_insn, add_fixed_insn)
(add_relaxed_insn, insert_into_history, emit_nop): New functions.
(md_begin): Initialize nop_insn and mips16_nop_insn.
(append_insn): Use the new emit_nop function to add nops, recording
them in the history buffer. Use add_fixed_insn or add_relaxed_insn
to reserve room for the instruction and install_insn to install the
final form. Use insert_into_history to record the instruction in
the history buffer. Use move_insn to do delay slot filling.
(mips_emit_delays): Use add_fixed_insn instead of the emit_nop macro.
(macro_build, mips16_macro_build, macro_build_lui, mips_ip)
(mips16_ip): Use create_insn to initialize mips_cl_insns.
diff -crpN gas.5/config/tc-mips.c gas/config/tc-mips.c
*** gas.5/config/tc-mips.c 2005-03-08 10:19:44.469831745 +0000
--- gas/config/tc-mips.c 2005-03-08 10:30:43.161925269 +0000
*************** static int mips_debug = 0;
*** 560,568 ****
/* A list of previous instructions, with index 0 being the most recent. */
static struct mips_cl_insn history[2];
! /* If we don't want information for a history[] entry, we
! point the insn_mo field at this dummy integer. */
! static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0, 0 };
/* If this is set, it points to a frag holding nop instructions which
were inserted before the start of a noreorder section. If those
--- 560,570 ----
/* A list of previous instructions, with index 0 being the most recent. */
static struct mips_cl_insn history[2];
! /* Nop instructions used by emit_nop. */
! static struct mips_cl_insn nop_insn, mips16_nop_insn;
!
! /* The appropriate nop for the current mode. */
! #define NOP_INSN (mips_opts.mips16 ? &mips16_nop_insn : &nop_insn)
/* If this is set, it points to a frag holding nop instructions which
were inserted before the start of a noreorder section. If those
*************** mips_target_format (void)
*** 1159,1164 ****
--- 1161,1290 ----
}
}
+ /* Return the length of instruction INSN. */
+
+ static inline unsigned int
+ insn_length (const struct mips_cl_insn *insn)
+ {
+ if (!mips_opts.mips16)
+ return 4;
+ return insn->mips16_absolute_jump_p || insn->use_extend ? 4 : 2;
+ }
+
+ /* Initialise INSN from opcode entry MO. Leave its position unspecified. */
+
+ static void
+ create_insn (struct mips_cl_insn *insn, const struct mips_opcode *mo)
+ {
+ size_t i;
+
+ insn->insn_mo = mo;
+ insn->use_extend = FALSE;
+ insn->extend = 0;
+ insn->insn_opcode = mo->match;
+ insn->frag = NULL;
+ insn->where = 0;
+ for (i = 0; i < ARRAY_SIZE (insn->fixp); i++)
+ insn->fixp[i] = NULL;
+ insn->fixed_p = (mips_opts.noreorder > 0);
+ insn->noreorder_p = (mips_opts.noreorder > 0);
+ insn->mips16_absolute_jump_p = 0;
+ }
+
+ /* Install INSN at the location specified by its "frag" and "where" fields. */
+
+ static void
+ install_insn (const struct mips_cl_insn *insn)
+ {
+ char *f = insn->frag->fr_literal + insn->where;
+ if (!mips_opts.mips16)
+ md_number_to_chars (f, insn->insn_opcode, 4);
+ else if (insn->mips16_absolute_jump_p)
+ {
+ md_number_to_chars (f, insn->insn_opcode >> 16, 2);
+ md_number_to_chars (f + 2, insn->insn_opcode & 0xffff, 2);
+ }
+ else
+ {
+ if (insn->use_extend)
+ {
+ md_number_to_chars (f, 0xf000 | insn->extend, 2);
+ f += 2;
+ }
+ md_number_to_chars (f, insn->insn_opcode, 2);
+ }
+ }
+
+ /* Move INSN to offset WHERE in FRAG. Adjust the fixups accordingly
+ and install the opcode in the new location. */
+
+ static void
+ move_insn (struct mips_cl_insn *insn, fragS *frag, long where)
+ {
+ size_t i;
+
+ insn->frag = frag;
+ insn->where = where;
+ for (i = 0; i < ARRAY_SIZE (insn->fixp); i++)
+ if (insn->fixp[i] != NULL)
+ {
+ insn->fixp[i]->fx_frag = frag;
+ insn->fixp[i]->fx_where = where;
+ }
+ install_insn (insn);
+ }
+
+ /* Add INSN to the end of the output. */
+
+ static void
+ add_fixed_insn (struct mips_cl_insn *insn)
+ {
+ char *f = frag_more (insn_length (insn));
+ move_insn (insn, frag_now, f - frag_now->fr_literal);
+ }
+
+ /* Start a variant frag and move INSN to the start of the variant part,
+ marking it as fixed. The other arguments are as for frag_var. */
+
+ static void
+ add_relaxed_insn (struct mips_cl_insn *insn, int max_chars, int var,
+ relax_substateT subtype, symbolS *symbol, offsetT offset)
+ {
+ frag_grow (max_chars);
+ move_insn (insn, frag_now, frag_more (0) - frag_now->fr_literal);
+ insn->fixed_p = 1;
+ frag_var (rs_machine_dependent, max_chars, var,
+ subtype, symbol, offset, NULL);
+ }
+
+ /* Insert N copies of INSN into the history buffer, starting at
+ position FIRST. Neither FIRST nor N need to be clipped. */
+
+ static void
+ insert_into_history (unsigned int first, unsigned int n,
+ const struct mips_cl_insn *insn)
+ {
+ if (mips_relax.sequence != 2)
+ {
+ unsigned int i;
+
+ for (i = ARRAY_SIZE (history); i-- > first;)
+ if (i >= first + n)
+ history[i] = history[i - n];
+ else
+ history[i] = *insn;
+ }
+ }
+
+ /* Emit a nop instruction, recording it in the history buffer. */
+
+ static void
+ emit_nop (void)
+ {
+ add_fixed_insn (NOP_INSN);
+ insert_into_history (0, 1, NOP_INSN);
+ }
+
/* This function is called once, at assembler startup time. It should
set up all the tables, etc. that the MD part of the assembler will need. */
*************** md_begin (void)
*** 1192,1197 ****
--- 1318,1328 ----
{
if (!validate_mips_insn (&mips_opcodes[i]))
broken = 1;
+ if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
+ {
+ create_insn (&nop_insn, mips_opcodes + i);
+ nop_insn.fixed_p = 1;
+ }
}
++i;
}
*************** md_begin (void)
*** 1219,1224 ****
--- 1350,1360 ----
mips16_opcodes[i].name, mips16_opcodes[i].args);
broken = 1;
}
+ if (mips16_nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
+ {
+ create_insn (&mips16_nop_insn, mips16_opcodes + i);
+ mips16_nop_insn.fixed_p = 1;
+ }
++i;
}
while (i < bfd_mips16_num_opcodes
*************** append_insn (struct mips_cl_insn *ip, ex
*** 1646,1657 ****
bfd_reloc_code_real_type *reloc_type)
{
register unsigned long prev_pinfo, pinfo;
- char *f;
- fixS *fixp[3];
int nops = 0;
relax_stateT prev_insn_frag_type = 0;
bfd_boolean relaxed_branch = FALSE;
- bfd_boolean force_new_frag = FALSE;
/* Mark instruction labels in mips16 mode. */
mips16_mark_labels ();
--- 1782,1790 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 1684,1695 ****
benefit hand written assembly code, and does not seem worth
it. */
- /* This is how a NOP is emitted. */
- #define emit_nop() \
- (mips_opts.mips16 \
- ? md_number_to_chars (frag_more (2), 0x6500, 2) \
- : md_number_to_chars (frag_more (4), 0, 4))
-
/* The previous insn might require a delay slot, depending upon
the contents of the current insn. */
if (! mips_opts.mips16
--- 1817,1822 ----
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2061,2092 ****
&& !mips_opts.mips16)
{
relaxed_branch = TRUE;
! f = frag_var (rs_machine_dependent,
! relaxed_branch_length
! (NULL, NULL,
! (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1
! : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1 : 0), 4,
! RELAX_BRANCH_ENCODE
! (pinfo & INSN_UNCOND_BRANCH_DELAY,
! pinfo & INSN_COND_BRANCH_LIKELY,
! pinfo & INSN_WRITE_GPR_31,
! 0),
! address_expr->X_add_symbol,
! address_expr->X_add_number,
! 0);
*reloc_type = BFD_RELOC_UNUSED;
}
else if (*reloc_type > BFD_RELOC_UNUSED)
{
/* We need to set up a variant frag. */
assert (mips_opts.mips16 && address_expr != NULL);
! f = frag_var (rs_machine_dependent, 4, 0,
! RELAX_MIPS16_ENCODE (*reloc_type - BFD_RELOC_UNUSED,
! mips16_small, mips16_ext,
! (prev_pinfo
! & INSN_UNCOND_BRANCH_DELAY),
! history[0].mips16_absolute_jump_p),
! make_expr_symbol (address_expr), 0, NULL);
}
else if (mips_opts.mips16
&& ! ip->use_extend
--- 2188,2218 ----
&& !mips_opts.mips16)
{
relaxed_branch = TRUE;
! add_relaxed_insn (ip, (relaxed_branch_length
! (NULL, NULL,
! (pinfo & INSN_UNCOND_BRANCH_DELAY) ? -1
! : (pinfo & INSN_COND_BRANCH_LIKELY) ? 1
! : 0)), 4,
! RELAX_BRANCH_ENCODE
! (pinfo & INSN_UNCOND_BRANCH_DELAY,
! pinfo & INSN_COND_BRANCH_LIKELY,
! pinfo & INSN_WRITE_GPR_31,
! 0),
! address_expr->X_add_symbol,
! address_expr->X_add_number);
*reloc_type = BFD_RELOC_UNUSED;
}
else if (*reloc_type > BFD_RELOC_UNUSED)
{
/* We need to set up a variant frag. */
assert (mips_opts.mips16 && address_expr != NULL);
! add_relaxed_insn (ip, 4, 0,
! RELAX_MIPS16_ENCODE
! (*reloc_type - BFD_RELOC_UNUSED,
! mips16_small, mips16_ext,
! prev_pinfo & INSN_UNCOND_BRANCH_DELAY,
! history[0].mips16_absolute_jump_p),
! make_expr_symbol (address_expr), 0);
}
else if (mips_opts.mips16
&& ! ip->use_extend
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2095,2101 ****
/* Make sure there is enough room to swap this instruction with
a following jump instruction. */
frag_grow (6);
! f = frag_more (2);
}
else
{
--- 2221,2227 ----
/* Make sure there is enough room to swap this instruction with
a following jump instruction. */
frag_grow (6);
! add_fixed_insn (ip);
}
else
{
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2119,2128 ****
if (mips_relax.sequence != 1)
mips_macro_warning.sizes[1] += 4;
! f = frag_more (4);
}
- fixp[0] = fixp[1] = fixp[2] = NULL;
if (address_expr != NULL && *reloc_type <= BFD_RELOC_UNUSED)
{
if (address_expr->X_op == O_constant)
--- 2245,2258 ----
if (mips_relax.sequence != 1)
mips_macro_warning.sizes[1] += 4;
! if (mips_opts.mips16)
! {
! ip->fixed_p = 1;
! ip->mips16_absolute_jump_p = (*reloc_type == BFD_RELOC_MIPS16_JMP);
! }
! add_fixed_insn (ip);
}
if (address_expr != NULL && *reloc_type <= BFD_RELOC_UNUSED)
{
if (address_expr->X_op == O_constant)
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2203,2213 ****
break;
howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
! fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
! bfd_get_reloc_size(howto),
! address_expr,
! reloc_type[0] == BFD_RELOC_16_PCREL_S2,
! reloc_type[0]);
/* These relocations can have an addend that won't fit in
4 octets for 64bit assembly. */
--- 2333,2343 ----
break;
howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
! ip->fixp[0] = fix_new_exp (ip->frag, ip->where,
! bfd_get_reloc_size (howto),
! address_expr,
! reloc_type[0] == BFD_RELOC_16_PCREL_S2,
! reloc_type[0]);
/* These relocations can have an addend that won't fit in
4 octets for 64bit assembly. */
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2232,2243 ****
|| reloc_type[0] == BFD_RELOC_MIPS16_GPREL
|| reloc_type[0] == BFD_RELOC_MIPS16_HI16_S
|| reloc_type[0] == BFD_RELOC_MIPS16_LO16))
! fixp[0]->fx_no_overflow = 1;
if (mips_relax.sequence)
{
if (mips_relax.first_fixup == 0)
! mips_relax.first_fixup = fixp[0];
}
else if (reloc_needs_lo_p (*reloc_type))
{
--- 2362,2373 ----
|| reloc_type[0] == BFD_RELOC_MIPS16_GPREL
|| reloc_type[0] == BFD_RELOC_MIPS16_HI16_S
|| reloc_type[0] == BFD_RELOC_MIPS16_LO16))
! ip->fixp[0]->fx_no_overflow = 1;
if (mips_relax.sequence)
{
if (mips_relax.first_fixup == 0)
! mips_relax.first_fixup = ip->fixp[0];
}
else if (reloc_needs_lo_p (*reloc_type))
{
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2253,2259 ****
hi_fixup->next = mips_hi_fixup_list;
mips_hi_fixup_list = hi_fixup;
}
! hi_fixup->fixp = fixp[0];
hi_fixup->seg = now_seg;
}
--- 2383,2389 ----
hi_fixup->next = mips_hi_fixup_list;
mips_hi_fixup_list = hi_fixup;
}
! hi_fixup->fixp = ip->fixp[0];
hi_fixup->seg = now_seg;
}
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2265,2297 ****
for (i = 1; i < 3; i++)
if (reloc_type[i] != BFD_RELOC_UNUSED)
{
! fixp[i] = fix_new (frag_now, fixp[0]->fx_where,
! fixp[0]->fx_size, NULL, 0,
! FALSE, reloc_type[i]);
/* Use fx_tcbit to mark compound relocs. */
! fixp[0]->fx_tcbit = 1;
! fixp[i]->fx_tcbit = 1;
}
}
}
!
! if (! mips_opts.mips16)
! md_number_to_chars (f, ip->insn_opcode, 4);
! else if (*reloc_type == BFD_RELOC_MIPS16_JMP)
! {
! md_number_to_chars (f, ip->insn_opcode >> 16, 2);
! md_number_to_chars (f + 2, ip->insn_opcode & 0xffff, 2);
! }
! else
! {
! if (ip->use_extend)
! {
! md_number_to_chars (f, 0xf000 | ip->extend, 2);
! f += 2;
! }
! md_number_to_chars (f, ip->insn_opcode, 2);
! }
/* Update the register mask information. */
if (! mips_opts.mips16)
--- 2395,2411 ----
for (i = 1; i < 3; i++)
if (reloc_type[i] != BFD_RELOC_UNUSED)
{
! ip->fixp[i] = fix_new (ip->frag, ip->where,
! ip->fixp[0]->fx_size, NULL, 0,
! FALSE, reloc_type[i]);
/* Use fx_tcbit to mark compound relocs. */
! ip->fixp[0]->fx_tcbit = 1;
! ip->fixp[i]->fx_tcbit = 1;
}
}
}
! install_insn (ip);
/* Update the register mask information. */
if (! mips_opts.mips16)
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2534,2696 ****
portions of this object file; we could pick up the
instruction at the destination, put it in the delay
slot, and bump the destination address. */
emit_nop ();
if (mips_relax.sequence)
mips_relax.sizes[mips_relax.sequence - 1] += 4;
- /* Update the previous insn information. */
- history[1].insn_mo = ip->insn_mo;
- history[1].use_extend = ip->use_extend;
- history[1].extend = ip->extend;
- history[1].insn_opcode = ip->insn_opcode;
- history[0].insn_mo = &dummy_opcode;
}
else
{
/* It looks like we can actually do the swap. */
! if (! mips_opts.mips16)
{
! char *prev_f;
! char temp[4];
!
! prev_f = history[0].frag->fr_literal + history[0].where;
! if (!relaxed_branch)
! {
! /* If this is not a relaxed branch, then just
! swap the instructions. */
! memcpy (temp, prev_f, 4);
! memcpy (prev_f, f, 4);
! memcpy (f, temp, 4);
! }
! else
! {
! /* If this is a relaxed branch, then we move the
! instruction to be placed in the delay slot to
! the current frag, shrinking the fixed part of
! the originating frag. If the branch occupies
! the tail of the latter, we move it backwards,
! into the space freed by the moved instruction. */
! f = frag_more (4);
! memcpy (f, prev_f, 4);
! history[0].frag->fr_fix -= 4;
! if (history[0].frag->fr_type == rs_machine_dependent)
! memmove (prev_f, prev_f + 4, history[0].frag->fr_var);
! }
!
! if (history[0].fixp[0])
! {
! history[0].fixp[0]->fx_frag = frag_now;
! history[0].fixp[0]->fx_where = f - frag_now->fr_literal;
! }
! if (history[0].fixp[1])
! {
! history[0].fixp[1]->fx_frag = frag_now;
! history[0].fixp[1]->fx_where = f - frag_now->fr_literal;
! }
! if (history[0].fixp[2])
! {
! history[0].fixp[2]->fx_frag = frag_now;
! history[0].fixp[2]->fx_where = f - frag_now->fr_literal;
! }
! if (history[0].fixp[0] && HAVE_NEWABI
! && history[0].frag != frag_now
! && (history[0].fixp[0]->fx_r_type
! == BFD_RELOC_MIPS_GOT_DISP
! || (history[0].fixp[0]->fx_r_type
! == BFD_RELOC_MIPS_CALL16)))
! {
! /* To avoid confusion in tc_gen_reloc, we must
! ensure that this does not become a variant
! frag. */
! force_new_frag = TRUE;
! }
!
! if (!relaxed_branch)
! {
! if (fixp[0])
! {
! fixp[0]->fx_frag = history[0].frag;
! fixp[0]->fx_where = history[0].where;
! }
! if (fixp[1])
! {
! fixp[1]->fx_frag = history[0].frag;
! fixp[1]->fx_where = history[0].where;
! }
! if (fixp[2])
! {
! fixp[2]->fx_frag = history[0].frag;
! fixp[2]->fx_where = history[0].where;
! }
! }
! else if (history[0].frag->fr_type == rs_machine_dependent)
! {
! if (fixp[0])
! fixp[0]->fx_where -= 4;
! if (fixp[1])
! fixp[1]->fx_where -= 4;
! if (fixp[2])
! fixp[2]->fx_where -= 4;
! }
}
else
{
! char *prev_f;
! char temp[2];
!
! assert (history[0].fixp[0] == NULL);
! assert (history[0].fixp[1] == NULL);
! assert (history[0].fixp[2] == NULL);
! prev_f = history[0].frag->fr_literal + history[0].where;
! memcpy (temp, prev_f, 2);
! memcpy (prev_f, f, 2);
! if (*reloc_type != BFD_RELOC_MIPS16_JMP)
! {
! assert (*reloc_type == BFD_RELOC_UNUSED);
! memcpy (f, temp, 2);
! }
! else
! {
! memcpy (f, f + 2, 2);
! memcpy (f + 2, temp, 2);
! }
! if (fixp[0])
! {
! fixp[0]->fx_frag = history[0].frag;
! fixp[0]->fx_where = history[0].where;
! }
! if (fixp[1])
! {
! fixp[1]->fx_frag = history[0].frag;
! fixp[1]->fx_where = history[0].where;
! }
! if (fixp[2])
! {
! fixp[2]->fx_frag = history[0].frag;
! fixp[2]->fx_where = history[0].where;
! }
}
!
! /* Update the previous insn information; leave history[0]
! unchanged. */
! history[1].insn_mo = ip->insn_mo;
! history[1].use_extend = ip->use_extend;
! history[1].extend = ip->extend;
! history[1].insn_opcode = ip->insn_opcode;
}
- history[0].fixed_p = 1;
/* If that was an unconditional branch, forget the previous
insn information. */
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
! {
! history[1].insn_mo = &dummy_opcode;
! history[0].insn_mo = &dummy_opcode;
! }
!
! history[0].fixp[0] = NULL;
! history[0].fixp[1] = NULL;
! history[0].fixp[2] = NULL;
! history[0].mips16_absolute_jump_p = 0;
}
else if (pinfo & INSN_COND_BRANCH_LIKELY)
{
--- 2648,2693 ----
portions of this object file; we could pick up the
instruction at the destination, put it in the delay
slot, and bump the destination address. */
+ insert_into_history (0, 1, ip);
emit_nop ();
if (mips_relax.sequence)
mips_relax.sizes[mips_relax.sequence - 1] += 4;
}
else
{
/* It looks like we can actually do the swap. */
! struct mips_cl_insn delay = history[0];
! if (mips_opts.mips16)
{
! know (delay.frag == ip->frag);
! move_insn (ip, delay.frag, delay.where);
! move_insn (&delay, ip->frag, ip->where + insn_length (ip));
! }
! else if (relaxed_branch)
! {
! /* Add the delay slot instruction to the end of the
! current frag and shrink the fixed part of the
! original frag. If the branch occupies the tail of
! the latter, move it backwards to cover the gap. */
! delay.frag->fr_fix -= 4;
! if (delay.frag == ip->frag)
! move_insn (ip, ip->frag, ip->where - 4);
! add_fixed_insn (&delay);
}
else
{
! move_insn (&delay, ip->frag, ip->where);
! move_insn (ip, history[0].frag, history[0].where);
}
! history[0] = *ip;
! delay.fixed_p = 1;
! insert_into_history (0, 1, &delay);
}
/* If that was an unconditional branch, forget the previous
insn information. */
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
! mips_no_prev_insn (FALSE);
}
else if (pinfo & INSN_COND_BRANCH_LIKELY)
{
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2698,2766 ****
is look at the target, copy the instruction found there
into the delay slot, and increment the branch to jump to
the next instruction. */
emit_nop ();
- /* Update the previous insn information. */
- history[1].insn_mo = ip->insn_mo;
- history[1].use_extend = ip->use_extend;
- history[1].extend = ip->extend;
- history[1].insn_opcode = ip->insn_opcode;
- history[0].insn_mo = &dummy_opcode;
- history[0].fixp[0] = NULL;
- history[0].fixp[1] = NULL;
- history[0].fixp[2] = NULL;
- history[0].mips16_absolute_jump_p = 0;
- history[0].fixed_p = 1;
}
else
! {
! /* Update the previous insn information. */
! if (nops > 0)
! history[1].insn_mo = &dummy_opcode;
! else
! {
! history[1].insn_mo = history[0].insn_mo;
! history[1].use_extend = history[0].use_extend;
! history[1].extend = history[0].extend;
! history[1].insn_opcode = history[0].insn_opcode;
! }
! history[0].insn_mo = ip->insn_mo;
! history[0].use_extend = ip->use_extend;
! history[0].extend = ip->extend;
! history[0].insn_opcode = ip->insn_opcode;
! history[0].fixed_p = (mips_opts.mips16
! && (ip->use_extend
! || *reloc_type > BFD_RELOC_UNUSED));
! history[0].fixp[0] = fixp[0];
! history[0].fixp[1] = fixp[1];
! history[0].fixp[2] = fixp[2];
! history[0].mips16_absolute_jump_p = (reloc_type[0]
! == BFD_RELOC_MIPS16_JMP);
! }
!
! history[1].noreorder_p = history[0].noreorder_p;
! history[0].noreorder_p = 0;
! history[0].frag = frag_now;
! history[0].where = f - frag_now->fr_literal;
! }
! else if (mips_relax.sequence != 2)
! {
! /* We need to record a bit of information even when we are not
! reordering, in order to determine the base address for mips16
! PC relative relocs. */
! history[1].insn_mo = history[0].insn_mo;
! history[1].use_extend = history[0].use_extend;
! history[1].extend = history[0].extend;
! history[1].insn_opcode = history[0].insn_opcode;
! history[0].insn_mo = ip->insn_mo;
! history[0].use_extend = ip->use_extend;
! history[0].extend = ip->extend;
! history[0].insn_opcode = ip->insn_opcode;
! history[0].mips16_absolute_jump_p = (reloc_type[0]
! == BFD_RELOC_MIPS16_JMP);
! history[1].noreorder_p = history[0].noreorder_p;
! history[0].noreorder_p = 1;
! history[0].fixed_p = 1;
}
/* We just output an insn, so the next one doesn't have a label. */
mips_clear_insn_labels ();
--- 2695,2708 ----
is look at the target, copy the instruction found there
into the delay slot, and increment the branch to jump to
the next instruction. */
+ insert_into_history (0, 1, ip);
emit_nop ();
}
else
! insert_into_history (0, 1, ip);
}
+ else
+ insert_into_history (0, 1, ip);
/* We just output an insn, so the next one doesn't have a label. */
mips_clear_insn_labels ();
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2773,2791 ****
static void
mips_no_prev_insn (int preserve)
{
if (! preserve)
{
- history[0].insn_mo = &dummy_opcode;
- history[1].insn_mo = &dummy_opcode;
prev_nop_frag = NULL;
prev_nop_frag_holds = 0;
prev_nop_frag_required = 0;
prev_nop_frag_since = 0;
}
! history[0].fixed_p = 1;
! history[0].noreorder_p = 0;
! history[0].mips16_absolute_jump_p = 0;
! history[1].noreorder_p = 0;
mips_clear_insn_labels ();
}
--- 2715,2738 ----
static void
mips_no_prev_insn (int preserve)
{
+ 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;
! }
mips_clear_insn_labels ();
}
*************** mips_emit_delays (bfd_boolean insns)
*** 2874,2880 ****
}
for (; nops > 0; --nops)
! emit_nop ();
if (insns)
{
--- 2821,2827 ----
}
for (; nops > 0; --nops)
! add_fixed_insn (NOP_INSN);
if (insns)
{
*************** macro_read_relocs (va_list *args, bfd_re
*** 2997,3002 ****
--- 2944,2950 ----
static void
macro_build (expressionS *ep, const char *name, const char *fmt, ...)
{
+ const struct mips_opcode *mo;
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3];
va_list args;
*************** macro_build (expressionS *ep, const char
*** 3013,3042 ****
r[0] = BFD_RELOC_UNUSED;
r[1] = BFD_RELOC_UNUSED;
r[2] = BFD_RELOC_UNUSED;
! insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
! assert (insn.insn_mo);
! assert (strcmp (name, insn.insn_mo->name) == 0);
!
! /* Search until we get a match for NAME. */
! while (1)
! {
! /* It is assumed here that macros will never generate
! MDMX or MIPS-3D instructions. */
! if (strcmp (fmt, insn.insn_mo->args) == 0
! && insn.insn_mo->pinfo != INSN_MACRO
! && OPCODE_IS_MEMBER (insn.insn_mo,
! (mips_opts.isa
! | (file_ase_mips16 ? INSN_MIPS16 : 0)),
mips_opts.arch)
! && (mips_opts.arch != CPU_R4650 || (insn.insn_mo->pinfo & FP_D) == 0))
! break;
!
! ++insn.insn_mo;
! assert (insn.insn_mo->name);
! assert (strcmp (name, insn.insn_mo->name) == 0);
}
! insn.insn_opcode = insn.insn_mo->match;
for (;;)
{
switch (*fmt++)
--- 2961,2986 ----
r[0] = BFD_RELOC_UNUSED;
r[1] = BFD_RELOC_UNUSED;
r[2] = BFD_RELOC_UNUSED;
! mo = (struct mips_opcode *) hash_find (op_hash, name);
! assert (mo);
! assert (strcmp (name, mo->name) == 0);
!
! /* Search until we get a match for NAME. It is assumed here that
! macros will never generate MDMX or MIPS-3D instructions. */
! while (strcmp (fmt, mo->args) != 0
! || mo->pinfo == INSN_MACRO
! || !OPCODE_IS_MEMBER (mo,
! (mips_opts.isa
! | (file_ase_mips16 ? INSN_MIPS16 : 0)),
mips_opts.arch)
! || (mips_opts.arch == CPU_R4650 && (mo->pinfo & FP_D) != 0))
! {
! ++mo;
! assert (mo->name);
! assert (strcmp (name, mo->name) == 0);
}
! create_insn (&insn, mo);
for (;;)
{
switch (*fmt++)
*************** static void
*** 3219,3243 ****
mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
va_list args)
{
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
! insn.insn_mo = (struct mips_opcode *) hash_find (mips16_op_hash, name);
! assert (insn.insn_mo);
! assert (strcmp (name, insn.insn_mo->name) == 0);
!
! while (strcmp (fmt, insn.insn_mo->args) != 0
! || insn.insn_mo->pinfo == INSN_MACRO)
! {
! ++insn.insn_mo;
! assert (insn.insn_mo->name);
! assert (strcmp (name, insn.insn_mo->name) == 0);
! }
! insn.insn_opcode = insn.insn_mo->match;
! insn.use_extend = FALSE;
for (;;)
{
int c;
--- 3163,3185 ----
mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
va_list args)
{
+ struct mips_opcode *mo;
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
! mo = (struct mips_opcode *) hash_find (mips16_op_hash, name);
! assert (mo);
! assert (strcmp (name, mo->name) == 0);
! while (strcmp (fmt, mo->args) != 0 || mo->pinfo == INSN_MACRO)
! {
! ++mo;
! assert (mo->name);
! assert (strcmp (name, mo->name) == 0);
! }
+ create_insn (&insn, mo);
for (;;)
{
int c;
*************** static void
*** 3363,3368 ****
--- 3305,3311 ----
macro_build_lui (expressionS *ep, int regnum)
{
expressionS high_expr;
+ const struct mips_opcode *mo;
struct mips_cl_insn insn;
bfd_reloc_code_real_type r[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
*************** macro_build_lui (expressionS *ep, int re
*** 3394,3403 ****
*r = BFD_RELOC_HI16_S;
}
! insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
! assert (insn.insn_mo);
! assert (strcmp (name, insn.insn_mo->name) == 0);
! assert (strcmp (fmt, insn.insn_mo->args) == 0);
insn.insn_opcode = insn.insn_mo->match;
INSERT_OPERAND (RT, insn, regnum);
--- 3337,3346 ----
*r = BFD_RELOC_HI16_S;
}
! mo = hash_find (op_hash, name);
! assert (strcmp (name, mo->name) == 0);
! assert (strcmp (fmt, mo->args) == 0);
! create_insn (&insn, mo);
insn.insn_opcode = insn.insn_mo->match;
INSERT_OPERAND (RT, insn, regnum);
*************** mips_ip (char *str, struct mips_cl_insn
*** 8018,8025 ****
}
}
! ip->insn_mo = insn;
! ip->insn_opcode = insn->match;
insn_error = NULL;
for (args = insn->args;; ++args)
{
--- 7961,7967 ----
}
}
! create_insn (ip, insn);
insn_error = NULL;
for (args = insn->args;; ++args)
{
*************** mips16_ip (char *str, struct mips_cl_ins
*** 9123,9131 ****
{
assert (strcmp (insn->name, str) == 0);
! ip->insn_mo = insn;
! ip->insn_opcode = insn->match;
! ip->use_extend = FALSE;
imm_expr.X_op = O_absent;
imm_reloc[0] = BFD_RELOC_UNUSED;
imm_reloc[1] = BFD_RELOC_UNUSED;
--- 9065,9071 ----
{
assert (strcmp (insn->name, str) == 0);
! create_insn (ip, insn);
imm_expr.X_op = O_absent;
imm_reloc[0] = BFD_RELOC_UNUSED;
imm_reloc[1] = BFD_RELOC_UNUSED;
More information about the Binutils
mailing list