* config/tc-mips.h (mips_cl_insn): Move definition to...
* config/tc-mips.c (mips_cl_insn): ...here. Add new fields: frag, where, fixp, reloc_type, valid_p, noreorder_p, delay_slot_p and extended_p. (history): New variable. (prev_insn, prev_prev_insn, prev_insn_valid, prev_insn_frag) (prev_insn_where, prev_insn_reloc_type, prev_insn_fixp) (prev_insn_is_delay_slot, prev_insn_unreordered, prev_insn_extended) (prev_prev_insn_unreordered): Delete. (reg_needs_delay, append_insn, mips_no_prev_insn, mips_emit_delays) (macro_start): Replace uses of prev_insn* with the equivalent history[] field.
This commit is contained in:
parent
5b5464adf1
commit
47e39b9d3f
|
@ -1,3 +1,18 @@
|
||||||
|
2005-03-09 Richard Sandiford <rsandifo@redhat.com>
|
||||||
|
|
||||||
|
* config/tc-mips.h (mips_cl_insn): Move definition to...
|
||||||
|
* config/tc-mips.c (mips_cl_insn): ...here. Add new fields:
|
||||||
|
frag, where, fixp, reloc_type, valid_p, noreorder_p, delay_slot_p
|
||||||
|
and extended_p.
|
||||||
|
(history): New variable.
|
||||||
|
(prev_insn, prev_prev_insn, prev_insn_valid, prev_insn_frag)
|
||||||
|
(prev_insn_where, prev_insn_reloc_type, prev_insn_fixp)
|
||||||
|
(prev_insn_is_delay_slot, prev_insn_unreordered, prev_insn_extended)
|
||||||
|
(prev_prev_insn_unreordered): Delete.
|
||||||
|
(reg_needs_delay, append_insn, mips_no_prev_insn, mips_emit_delays)
|
||||||
|
(macro_start): Replace uses of prev_insn* with the equivalent history[]
|
||||||
|
field.
|
||||||
|
|
||||||
2005-03-08 Daniel Jacobowitz <dan@codesourcery.com>
|
2005-03-08 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* doc/Makefile.am: Update as.info dependencies.
|
* doc/Makefile.am: Update as.info dependencies.
|
||||||
|
|
|
@ -119,6 +119,50 @@ extern int target_big_endian;
|
||||||
? ".rodata" \
|
? ".rodata" \
|
||||||
: (abort (), ""))
|
: (abort (), ""))
|
||||||
|
|
||||||
|
/* Information about an instruction, including its format, operands
|
||||||
|
and fixups. */
|
||||||
|
struct mips_cl_insn
|
||||||
|
{
|
||||||
|
/* The opcode's entry in mips_opcodes or mips16_opcodes. */
|
||||||
|
const struct mips_opcode *insn_mo;
|
||||||
|
|
||||||
|
/* True if this is a mips16 instruction and if we want the extended
|
||||||
|
form of INSN_MO. */
|
||||||
|
bfd_boolean use_extend;
|
||||||
|
|
||||||
|
/* The 16-bit extension instruction to use when USE_EXTEND is true. */
|
||||||
|
unsigned short extend;
|
||||||
|
|
||||||
|
/* The 16-bit or 32-bit bitstring of the instruction itself. This is
|
||||||
|
a copy of INSN_MO->match with the operands filled in. */
|
||||||
|
unsigned long insn_opcode;
|
||||||
|
|
||||||
|
/* The frag that contains the instruction. */
|
||||||
|
struct frag *frag;
|
||||||
|
|
||||||
|
/* The offset into FRAG of the first instruction byte. */
|
||||||
|
long where;
|
||||||
|
|
||||||
|
/* The relocs associated with the instruction, if any. */
|
||||||
|
fixS *fixp[3];
|
||||||
|
|
||||||
|
/* The reloc types associated with the instruction. */
|
||||||
|
bfd_reloc_code_real_type reloc_type[3];
|
||||||
|
|
||||||
|
/* True if this entry describes a real instruction. */
|
||||||
|
unsigned int valid_p : 1;
|
||||||
|
|
||||||
|
/* True if this instruction occured in a .set noreorder block. */
|
||||||
|
unsigned int noreorder_p : 1;
|
||||||
|
|
||||||
|
/* True if this instruction corresponds to an assembler-filled
|
||||||
|
delay slot. Always false if noreorder_p. */
|
||||||
|
unsigned int delay_slot_p : 1;
|
||||||
|
|
||||||
|
/* True for extended mips16 instructions. */
|
||||||
|
unsigned int extended_p : 1;
|
||||||
|
};
|
||||||
|
|
||||||
/* The ABI to use. */
|
/* The ABI to use. */
|
||||||
enum mips_abi_level
|
enum mips_abi_level
|
||||||
{
|
{
|
||||||
|
@ -520,45 +564,13 @@ static int mips_optimize = 2;
|
||||||
equivalent to seeing no -g option at all. */
|
equivalent to seeing no -g option at all. */
|
||||||
static int mips_debug = 0;
|
static int mips_debug = 0;
|
||||||
|
|
||||||
/* The previous instruction. */
|
/* A list of previous instructions, with index 0 being the most recent. */
|
||||||
static struct mips_cl_insn prev_insn;
|
static struct mips_cl_insn history[2];
|
||||||
|
|
||||||
/* The instruction before prev_insn. */
|
/* If we don't want information for a history[] entry, we
|
||||||
static struct mips_cl_insn prev_prev_insn;
|
|
||||||
|
|
||||||
/* If we don't want information for prev_insn or prev_prev_insn, we
|
|
||||||
point the insn_mo field at this dummy integer. */
|
point the insn_mo field at this dummy integer. */
|
||||||
static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0, 0 };
|
static const struct mips_opcode dummy_opcode = { NULL, NULL, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
/* Non-zero if prev_insn is valid. */
|
|
||||||
static int prev_insn_valid;
|
|
||||||
|
|
||||||
/* The frag for the previous instruction. */
|
|
||||||
static struct frag *prev_insn_frag;
|
|
||||||
|
|
||||||
/* The offset into prev_insn_frag for the previous instruction. */
|
|
||||||
static long prev_insn_where;
|
|
||||||
|
|
||||||
/* The reloc type for the previous instruction, if any. */
|
|
||||||
static bfd_reloc_code_real_type prev_insn_reloc_type[3];
|
|
||||||
|
|
||||||
/* The reloc for the previous instruction, if any. */
|
|
||||||
static fixS *prev_insn_fixp[3];
|
|
||||||
|
|
||||||
/* Non-zero if the previous instruction was in a delay slot. */
|
|
||||||
static int prev_insn_is_delay_slot;
|
|
||||||
|
|
||||||
/* Non-zero if the previous instruction was in a .set noreorder. */
|
|
||||||
static int prev_insn_unreordered;
|
|
||||||
|
|
||||||
/* Non-zero if the previous instruction uses an extend opcode (if
|
|
||||||
mips16). */
|
|
||||||
static int prev_insn_extended;
|
|
||||||
|
|
||||||
/* Non-zero if the previous previous instruction was in a .set
|
|
||||||
noreorder. */
|
|
||||||
static int prev_prev_insn_unreordered;
|
|
||||||
|
|
||||||
/* If this is set, it points to a frag holding nop instructions which
|
/* If this is set, it points to a frag holding nop instructions which
|
||||||
were inserted before the start of a noreorder section. If those
|
were inserted before the start of a noreorder section. If those
|
||||||
nops turn out to be unnecessary, the size of the frag can be
|
nops turn out to be unnecessary, the size of the frag can be
|
||||||
|
@ -1515,7 +1527,7 @@ reg_needs_delay (unsigned int reg)
|
||||||
{
|
{
|
||||||
unsigned long prev_pinfo;
|
unsigned long prev_pinfo;
|
||||||
|
|
||||||
prev_pinfo = prev_insn.insn_mo->pinfo;
|
prev_pinfo = history[0].insn_mo->pinfo;
|
||||||
if (! mips_opts.noreorder
|
if (! mips_opts.noreorder
|
||||||
&& (((prev_pinfo & INSN_LOAD_MEMORY_DELAY)
|
&& (((prev_pinfo & INSN_LOAD_MEMORY_DELAY)
|
||||||
&& ! gpr_interlocks)
|
&& ! gpr_interlocks)
|
||||||
|
@ -1526,7 +1538,7 @@ reg_needs_delay (unsigned int reg)
|
||||||
delay the use of general register rt for one instruction. */
|
delay the use of general register rt for one instruction. */
|
||||||
/* Itbl support may require additional care here. */
|
/* Itbl support may require additional care here. */
|
||||||
know (prev_pinfo & INSN_WRITE_GPR_T);
|
know (prev_pinfo & INSN_WRITE_GPR_T);
|
||||||
if (reg == ((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT))
|
if (reg == ((history[0].insn_opcode >> OP_SH_RT) & OP_MASK_RT))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1627,7 +1639,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
/* Mark instruction labels in mips16 mode. */
|
/* Mark instruction labels in mips16 mode. */
|
||||||
mips16_mark_labels ();
|
mips16_mark_labels ();
|
||||||
|
|
||||||
prev_pinfo = prev_insn.insn_mo->pinfo;
|
prev_pinfo = history[0].insn_mo->pinfo;
|
||||||
pinfo = ip->insn_mo->pinfo;
|
pinfo = ip->insn_mo->pinfo;
|
||||||
|
|
||||||
if (mips_relax.sequence != 2
|
if (mips_relax.sequence != 2
|
||||||
|
@ -1676,7 +1688,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
know (prev_pinfo & INSN_WRITE_GPR_T);
|
know (prev_pinfo & INSN_WRITE_GPR_T);
|
||||||
if (mips_optimize == 0
|
if (mips_optimize == 0
|
||||||
|| insn_uses_reg (ip,
|
|| insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode >> OP_SH_RT)
|
((history[0].insn_opcode >> OP_SH_RT)
|
||||||
& OP_MASK_RT),
|
& OP_MASK_RT),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
++nops;
|
++nops;
|
||||||
|
@ -1705,7 +1717,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
{
|
{
|
||||||
if (mips_optimize == 0
|
if (mips_optimize == 0
|
||||||
|| insn_uses_reg (ip,
|
|| insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode >> OP_SH_FT)
|
((history[0].insn_opcode >> OP_SH_FT)
|
||||||
& OP_MASK_FT),
|
& OP_MASK_FT),
|
||||||
MIPS_FP_REG))
|
MIPS_FP_REG))
|
||||||
++nops;
|
++nops;
|
||||||
|
@ -1714,7 +1726,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
{
|
{
|
||||||
if (mips_optimize == 0
|
if (mips_optimize == 0
|
||||||
|| insn_uses_reg (ip,
|
|| insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode >> OP_SH_FS)
|
((history[0].insn_opcode >> OP_SH_FS)
|
||||||
& OP_MASK_FS),
|
& OP_MASK_FS),
|
||||||
MIPS_FP_REG))
|
MIPS_FP_REG))
|
||||||
++nops;
|
++nops;
|
||||||
|
@ -1758,7 +1770,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
|
|
||||||
else if (mips_7000_hilo_fix
|
else if (mips_7000_hilo_fix
|
||||||
&& MF_HILO_INSN (prev_pinfo)
|
&& MF_HILO_INSN (prev_pinfo)
|
||||||
&& insn_uses_reg (ip, ((prev_insn.insn_opcode >> OP_SH_RD)
|
&& insn_uses_reg (ip, ((history[0].insn_opcode >> OP_SH_RD)
|
||||||
& OP_MASK_RD),
|
& OP_MASK_RD),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
{
|
{
|
||||||
|
@ -1771,8 +1783,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
insert one nop. */
|
insert one nop. */
|
||||||
|
|
||||||
else if (mips_7000_hilo_fix
|
else if (mips_7000_hilo_fix
|
||||||
&& MF_HILO_INSN (prev_prev_insn.insn_opcode)
|
&& MF_HILO_INSN (history[1].insn_opcode)
|
||||||
&& insn_uses_reg (ip, ((prev_prev_insn.insn_opcode >> OP_SH_RD)
|
&& insn_uses_reg (ip, ((history[1].insn_opcode >> OP_SH_RD)
|
||||||
& OP_MASK_RD),
|
& OP_MASK_RD),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
|
|
||||||
|
@ -1805,7 +1817,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
|| (pinfo & MIPS16_INSN_BRANCH)))
|
|| (pinfo & MIPS16_INSN_BRANCH)))
|
||||||
++nops;
|
++nops;
|
||||||
}
|
}
|
||||||
else if (prev_insn.insn_mo->pinfo & INSN_READ_HI)
|
else if (history[0].insn_mo->pinfo & INSN_READ_HI)
|
||||||
{
|
{
|
||||||
/* The previous instruction reads the HI register; if the
|
/* The previous instruction reads the HI register; if the
|
||||||
current instruction writes to the HI register, we must
|
current instruction writes to the HI register, we must
|
||||||
|
@ -1831,7 +1843,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
/* If the previous instruction was in a noreorder section, then
|
/* If the previous instruction was in a noreorder section, then
|
||||||
we don't want to insert the nop after all. */
|
we don't want to insert the nop after all. */
|
||||||
/* Itbl support may require additional care here. */
|
/* Itbl support may require additional care here. */
|
||||||
if (prev_insn_unreordered)
|
if (history[0].noreorder_p)
|
||||||
nops = 0;
|
nops = 0;
|
||||||
|
|
||||||
/* There are two cases which require two intervening
|
/* There are two cases which require two intervening
|
||||||
|
@ -1843,15 +1855,15 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
instruction, we must check for these cases compared to the
|
instruction, we must check for these cases compared to the
|
||||||
instruction previous to the previous instruction. */
|
instruction previous to the previous instruction. */
|
||||||
if ((! mips_opts.mips16
|
if ((! mips_opts.mips16
|
||||||
&& (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
|
&& (history[1].insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
|
||||||
&& (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
&& (history[1].insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
||||||
&& (pinfo & INSN_READ_COND_CODE)
|
&& (pinfo & INSN_READ_COND_CODE)
|
||||||
&& ! cop_interlocks)
|
&& ! cop_interlocks)
|
||||||
|| ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)
|
|| ((history[1].insn_mo->pinfo & INSN_READ_LO)
|
||||||
&& (pinfo & INSN_WRITE_LO)
|
&& (pinfo & INSN_WRITE_LO)
|
||||||
&& ! (hilo_interlocks
|
&& ! (hilo_interlocks
|
||||||
|| (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))))
|
|| (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT))))
|
||||||
|| ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|
|| ((history[1].insn_mo->pinfo & INSN_READ_HI)
|
||||||
&& (pinfo & INSN_WRITE_HI)
|
&& (pinfo & INSN_WRITE_HI)
|
||||||
&& ! (hilo_interlocks
|
&& ! (hilo_interlocks
|
||||||
|| (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT)))))
|
|| (mips_opts.arch == CPU_R3900 && (pinfo & INSN_MULT)))))
|
||||||
|
@ -1859,19 +1871,19 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
else
|
else
|
||||||
prev_prev_nop = 0;
|
prev_prev_nop = 0;
|
||||||
|
|
||||||
if (prev_prev_insn_unreordered)
|
if (history[1].noreorder_p)
|
||||||
prev_prev_nop = 0;
|
prev_prev_nop = 0;
|
||||||
|
|
||||||
if (prev_prev_nop && nops == 0)
|
if (prev_prev_nop && nops == 0)
|
||||||
++nops;
|
++nops;
|
||||||
|
|
||||||
if (mips_fix_vr4120 && prev_insn.insn_mo->name)
|
if (mips_fix_vr4120 && history[0].insn_mo->name)
|
||||||
{
|
{
|
||||||
/* We're out of bits in pinfo, so we must resort to string
|
/* We're out of bits in pinfo, so we must resort to string
|
||||||
ops here. Shortcuts are selected based on opcodes being
|
ops here. Shortcuts are selected based on opcodes being
|
||||||
limited to the VR4120 instruction set. */
|
limited to the VR4120 instruction set. */
|
||||||
int min_nops = 0;
|
int min_nops = 0;
|
||||||
const char *pn = prev_insn.insn_mo->name;
|
const char *pn = history[0].insn_mo->name;
|
||||||
const char *tn = ip->insn_mo->name;
|
const char *tn = ip->insn_mo->name;
|
||||||
if (strncmp (pn, "macc", 4) == 0
|
if (strncmp (pn, "macc", 4) == 0
|
||||||
|| strncmp (pn, "dmacc", 5) == 0)
|
|| strncmp (pn, "dmacc", 5) == 0)
|
||||||
|
@ -2024,8 +2036,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Record the frag type before frag_var. */
|
/* Record the frag type before frag_var. */
|
||||||
if (prev_insn_frag)
|
if (history[0].frag)
|
||||||
prev_insn_frag_type = prev_insn_frag->fr_type;
|
prev_insn_frag_type = history[0].frag->fr_type;
|
||||||
|
|
||||||
if (address_expr
|
if (address_expr
|
||||||
&& *reloc_type == BFD_RELOC_16_PCREL_S2
|
&& *reloc_type == BFD_RELOC_16_PCREL_S2
|
||||||
|
@ -2064,7 +2076,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
mips16_small, mips16_ext,
|
mips16_small, mips16_ext,
|
||||||
(prev_pinfo
|
(prev_pinfo
|
||||||
& INSN_UNCOND_BRANCH_DELAY),
|
& INSN_UNCOND_BRANCH_DELAY),
|
||||||
(*prev_insn_reloc_type
|
(*history[0].reloc_type
|
||||||
== BFD_RELOC_MIPS16_JMP)),
|
== BFD_RELOC_MIPS16_JMP)),
|
||||||
make_expr_symbol (address_expr), 0, NULL);
|
make_expr_symbol (address_expr), 0, NULL);
|
||||||
}
|
}
|
||||||
|
@ -2348,10 +2360,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
|| nops != 0
|
|| nops != 0
|
||||||
/* If we don't even know the previous insn, we can not
|
/* If we don't even know the previous insn, we can not
|
||||||
swap. */
|
swap. */
|
||||||
|| ! prev_insn_valid
|
|| ! history[0].valid_p
|
||||||
/* If the previous insn is already in a branch delay
|
/* If the previous insn is already in a branch delay
|
||||||
slot, then we can not swap. */
|
slot, then we can not swap. */
|
||||||
|| prev_insn_is_delay_slot
|
|| history[0].delay_slot_p
|
||||||
/* If the previous previous insn was in a .set
|
/* If the previous previous insn was in a .set
|
||||||
noreorder, we can't swap. Actually, the MIPS
|
noreorder, we can't swap. Actually, the MIPS
|
||||||
assembler will swap in this situation. However, gcc
|
assembler will swap in this situation. However, gcc
|
||||||
|
@ -2364,11 +2376,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
in which we can not swap the bne and INSN. If gcc is
|
in which we can not swap the bne and INSN. If gcc is
|
||||||
not configured -with-gnu-as, it does not output the
|
not configured -with-gnu-as, it does not output the
|
||||||
.set pseudo-ops. We don't have to check
|
.set pseudo-ops. We don't have to check
|
||||||
prev_insn_unreordered, because prev_insn_valid will
|
history[0].noreorder_p, because history[0].valid_p will
|
||||||
be 0 in that case. We don't want to use
|
be 0 in that case. We don't want to use
|
||||||
prev_prev_insn_valid, because we do want to be able
|
history[1].valid_p, because we do want to be able
|
||||||
to swap at the start of a function. */
|
to swap at the start of a function. */
|
||||||
|| prev_prev_insn_unreordered
|
|| history[1].noreorder_p
|
||||||
/* If the branch is itself the target of a branch, we
|
/* If the branch is itself the target of a branch, we
|
||||||
can not swap. We cheat on this; all we check for is
|
can not swap. We cheat on this; all we check for is
|
||||||
whether there is a label on this instruction. If
|
whether there is a label on this instruction. If
|
||||||
|
@ -2428,31 +2440,31 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode >> OP_SH_RT)
|
((history[0].insn_opcode >> OP_SH_RT)
|
||||||
& OP_MASK_RT),
|
& OP_MASK_RT),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode >> OP_SH_RD)
|
((history[0].insn_opcode >> OP_SH_RD)
|
||||||
& OP_MASK_RD),
|
& OP_MASK_RD),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
|| (mips_opts.mips16
|
|| (mips_opts.mips16
|
||||||
&& (((prev_pinfo & MIPS16_INSN_WRITE_X)
|
&& (((prev_pinfo & MIPS16_INSN_WRITE_X)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode
|
((history[0].insn_opcode
|
||||||
>> MIPS16OP_SH_RX)
|
>> MIPS16OP_SH_RX)
|
||||||
& MIPS16OP_MASK_RX),
|
& MIPS16OP_MASK_RX),
|
||||||
MIPS16_REG))
|
MIPS16_REG))
|
||||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_Y)
|
|| ((prev_pinfo & MIPS16_INSN_WRITE_Y)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode
|
((history[0].insn_opcode
|
||||||
>> MIPS16OP_SH_RY)
|
>> MIPS16OP_SH_RY)
|
||||||
& MIPS16OP_MASK_RY),
|
& MIPS16OP_MASK_RY),
|
||||||
MIPS16_REG))
|
MIPS16_REG))
|
||||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_Z)
|
|| ((prev_pinfo & MIPS16_INSN_WRITE_Z)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_insn.insn_opcode
|
((history[0].insn_opcode
|
||||||
>> MIPS16OP_SH_RZ)
|
>> MIPS16OP_SH_RZ)
|
||||||
& MIPS16OP_MASK_RZ),
|
& MIPS16OP_MASK_RZ),
|
||||||
MIPS16_REG))
|
MIPS16_REG))
|
||||||
|
@ -2462,8 +2474,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
&& insn_uses_reg (ip, RA, MIPS_GR_REG))
|
&& insn_uses_reg (ip, RA, MIPS_GR_REG))
|
||||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
MIPS16OP_EXTRACT_REG32R (prev_insn.
|
MIPS16OP_EXTRACT_REG32R
|
||||||
insn_opcode),
|
(history[0].insn_opcode),
|
||||||
MIPS_GR_REG))))
|
MIPS_GR_REG))))
|
||||||
/* If the branch writes a register that the previous
|
/* If the branch writes a register that the previous
|
||||||
instruction sets, we can not swap (we know that
|
instruction sets, we can not swap (we know that
|
||||||
|
@ -2471,54 +2483,54 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
||||||
&& (((pinfo & INSN_WRITE_GPR_D)
|
&& (((pinfo & INSN_WRITE_GPR_D)
|
||||||
&& (((prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT)
|
&& (((history[0].insn_opcode >> OP_SH_RT) & OP_MASK_RT)
|
||||||
== ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
|
== ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
|
||||||
|| ((pinfo & INSN_WRITE_GPR_31)
|
|| ((pinfo & INSN_WRITE_GPR_31)
|
||||||
&& (((prev_insn.insn_opcode >> OP_SH_RT)
|
&& (((history[0].insn_opcode >> OP_SH_RT)
|
||||||
& OP_MASK_RT)
|
& OP_MASK_RT)
|
||||||
== RA))))
|
== RA))))
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
||||||
&& (((pinfo & INSN_WRITE_GPR_D)
|
&& (((pinfo & INSN_WRITE_GPR_D)
|
||||||
&& (((prev_insn.insn_opcode >> OP_SH_RD) & OP_MASK_RD)
|
&& (((history[0].insn_opcode >> OP_SH_RD) & OP_MASK_RD)
|
||||||
== ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
|
== ((ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD)))
|
||||||
|| ((pinfo & INSN_WRITE_GPR_31)
|
|| ((pinfo & INSN_WRITE_GPR_31)
|
||||||
&& (((prev_insn.insn_opcode >> OP_SH_RD)
|
&& (((history[0].insn_opcode >> OP_SH_RD)
|
||||||
& OP_MASK_RD)
|
& OP_MASK_RD)
|
||||||
== RA))))
|
== RA))))
|
||||||
|| (mips_opts.mips16
|
|| (mips_opts.mips16
|
||||||
&& (pinfo & MIPS16_INSN_WRITE_31)
|
&& (pinfo & MIPS16_INSN_WRITE_31)
|
||||||
&& ((prev_pinfo & MIPS16_INSN_WRITE_31)
|
&& ((prev_pinfo & MIPS16_INSN_WRITE_31)
|
||||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||||
&& (MIPS16OP_EXTRACT_REG32R (prev_insn.insn_opcode)
|
&& (MIPS16OP_EXTRACT_REG32R (history[0].insn_opcode)
|
||||||
== RA))))
|
== RA))))
|
||||||
/* If the branch writes a register that the previous
|
/* If the branch writes a register that the previous
|
||||||
instruction reads, we can not swap (we know that
|
instruction reads, we can not swap (we know that
|
||||||
branches only write to RD or to $31). */
|
branches only write to RD or to $31). */
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (pinfo & INSN_WRITE_GPR_D)
|
&& (pinfo & INSN_WRITE_GPR_D)
|
||||||
&& insn_uses_reg (&prev_insn,
|
&& insn_uses_reg (&history[0],
|
||||||
((ip->insn_opcode >> OP_SH_RD)
|
((ip->insn_opcode >> OP_SH_RD)
|
||||||
& OP_MASK_RD),
|
& OP_MASK_RD),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (pinfo & INSN_WRITE_GPR_31)
|
&& (pinfo & INSN_WRITE_GPR_31)
|
||||||
&& insn_uses_reg (&prev_insn, RA, MIPS_GR_REG))
|
&& insn_uses_reg (&history[0], RA, MIPS_GR_REG))
|
||||||
|| (mips_opts.mips16
|
|| (mips_opts.mips16
|
||||||
&& (pinfo & MIPS16_INSN_WRITE_31)
|
&& (pinfo & MIPS16_INSN_WRITE_31)
|
||||||
&& insn_uses_reg (&prev_insn, RA, MIPS_GR_REG))
|
&& insn_uses_reg (&history[0], RA, MIPS_GR_REG))
|
||||||
/* If the previous previous instruction has a load
|
/* If the previous previous instruction has a load
|
||||||
delay, and sets a register that the branch reads, we
|
delay, and sets a register that the branch reads, we
|
||||||
can not swap. */
|
can not swap. */
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
/* Itbl support may require additional care here. */
|
/* Itbl support may require additional care here. */
|
||||||
&& (((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
|
&& (((history[1].insn_mo->pinfo & INSN_LOAD_COPROC_DELAY)
|
||||||
&& ! cop_interlocks)
|
&& ! cop_interlocks)
|
||||||
|| ((prev_prev_insn.insn_mo->pinfo
|
|| ((history[1].insn_mo->pinfo
|
||||||
& INSN_LOAD_MEMORY_DELAY)
|
& INSN_LOAD_MEMORY_DELAY)
|
||||||
&& ! gpr_interlocks))
|
&& ! gpr_interlocks))
|
||||||
&& insn_uses_reg (ip,
|
&& insn_uses_reg (ip,
|
||||||
((prev_prev_insn.insn_opcode >> OP_SH_RT)
|
((history[1].insn_opcode >> OP_SH_RT)
|
||||||
& OP_MASK_RT),
|
& OP_MASK_RT),
|
||||||
MIPS_GR_REG))
|
MIPS_GR_REG))
|
||||||
/* If one instruction sets a condition code and the
|
/* If one instruction sets a condition code and the
|
||||||
|
@ -2533,11 +2545,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
&& (prev_pinfo & MIPS16_INSN_READ_PC))
|
&& (prev_pinfo & MIPS16_INSN_READ_PC))
|
||||||
/* If the previous instruction was extended, we can not
|
/* If the previous instruction was extended, we can not
|
||||||
swap. */
|
swap. */
|
||||||
|| (mips_opts.mips16 && prev_insn_extended)
|
|| (mips_opts.mips16 && history[0].extended_p)
|
||||||
/* If the previous instruction had a fixup in mips16
|
/* If the previous instruction had a fixup in mips16
|
||||||
mode, we can not swap. This normally means that the
|
mode, we can not swap. This normally means that the
|
||||||
previous instruction was a 4 byte branch anyhow. */
|
previous instruction was a 4 byte branch anyhow. */
|
||||||
|| (mips_opts.mips16 && prev_insn_fixp[0])
|
|| (mips_opts.mips16 && history[0].fixp[0])
|
||||||
/* If the previous instruction is a sync, sync.l, or
|
/* If the previous instruction is a sync, sync.l, or
|
||||||
sync.p, we can not swap. */
|
sync.p, we can not swap. */
|
||||||
|| (prev_pinfo & INSN_SYNC))
|
|| (prev_pinfo & INSN_SYNC))
|
||||||
|
@ -2550,8 +2562,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
if (mips_relax.sequence)
|
if (mips_relax.sequence)
|
||||||
mips_relax.sizes[mips_relax.sequence - 1] += 4;
|
mips_relax.sizes[mips_relax.sequence - 1] += 4;
|
||||||
/* Update the previous insn information. */
|
/* Update the previous insn information. */
|
||||||
prev_prev_insn = *ip;
|
history[1].insn_mo = ip->insn_mo;
|
||||||
prev_insn.insn_mo = &dummy_opcode;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -2561,7 +2576,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
char *prev_f;
|
char *prev_f;
|
||||||
char temp[4];
|
char temp[4];
|
||||||
|
|
||||||
prev_f = prev_insn_frag->fr_literal + prev_insn_where;
|
prev_f = history[0].frag->fr_literal + history[0].where;
|
||||||
if (!relaxed_branch)
|
if (!relaxed_branch)
|
||||||
{
|
{
|
||||||
/* If this is not a relaxed branch, then just
|
/* If this is not a relaxed branch, then just
|
||||||
|
@ -2580,31 +2595,31 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
into the space freed by the moved instruction. */
|
into the space freed by the moved instruction. */
|
||||||
f = frag_more (4);
|
f = frag_more (4);
|
||||||
memcpy (f, prev_f, 4);
|
memcpy (f, prev_f, 4);
|
||||||
prev_insn_frag->fr_fix -= 4;
|
history[0].frag->fr_fix -= 4;
|
||||||
if (prev_insn_frag->fr_type == rs_machine_dependent)
|
if (history[0].frag->fr_type == rs_machine_dependent)
|
||||||
memmove (prev_f, prev_f + 4, prev_insn_frag->fr_var);
|
memmove (prev_f, prev_f + 4, history[0].frag->fr_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_insn_fixp[0])
|
if (history[0].fixp[0])
|
||||||
{
|
{
|
||||||
prev_insn_fixp[0]->fx_frag = frag_now;
|
history[0].fixp[0]->fx_frag = frag_now;
|
||||||
prev_insn_fixp[0]->fx_where = f - frag_now->fr_literal;
|
history[0].fixp[0]->fx_where = f - frag_now->fr_literal;
|
||||||
}
|
}
|
||||||
if (prev_insn_fixp[1])
|
if (history[0].fixp[1])
|
||||||
{
|
{
|
||||||
prev_insn_fixp[1]->fx_frag = frag_now;
|
history[0].fixp[1]->fx_frag = frag_now;
|
||||||
prev_insn_fixp[1]->fx_where = f - frag_now->fr_literal;
|
history[0].fixp[1]->fx_where = f - frag_now->fr_literal;
|
||||||
}
|
}
|
||||||
if (prev_insn_fixp[2])
|
if (history[0].fixp[2])
|
||||||
{
|
{
|
||||||
prev_insn_fixp[2]->fx_frag = frag_now;
|
history[0].fixp[2]->fx_frag = frag_now;
|
||||||
prev_insn_fixp[2]->fx_where = f - frag_now->fr_literal;
|
history[0].fixp[2]->fx_where = f - frag_now->fr_literal;
|
||||||
}
|
}
|
||||||
if (prev_insn_fixp[0] && HAVE_NEWABI
|
if (history[0].fixp[0] && HAVE_NEWABI
|
||||||
&& prev_insn_frag != frag_now
|
&& history[0].frag != frag_now
|
||||||
&& (prev_insn_fixp[0]->fx_r_type
|
&& (history[0].fixp[0]->fx_r_type
|
||||||
== BFD_RELOC_MIPS_GOT_DISP
|
== BFD_RELOC_MIPS_GOT_DISP
|
||||||
|| (prev_insn_fixp[0]->fx_r_type
|
|| (history[0].fixp[0]->fx_r_type
|
||||||
== BFD_RELOC_MIPS_CALL16)))
|
== BFD_RELOC_MIPS_CALL16)))
|
||||||
{
|
{
|
||||||
/* To avoid confusion in tc_gen_reloc, we must
|
/* To avoid confusion in tc_gen_reloc, we must
|
||||||
|
@ -2617,21 +2632,21 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
{
|
{
|
||||||
if (fixp[0])
|
if (fixp[0])
|
||||||
{
|
{
|
||||||
fixp[0]->fx_frag = prev_insn_frag;
|
fixp[0]->fx_frag = history[0].frag;
|
||||||
fixp[0]->fx_where = prev_insn_where;
|
fixp[0]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
if (fixp[1])
|
if (fixp[1])
|
||||||
{
|
{
|
||||||
fixp[1]->fx_frag = prev_insn_frag;
|
fixp[1]->fx_frag = history[0].frag;
|
||||||
fixp[1]->fx_where = prev_insn_where;
|
fixp[1]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
if (fixp[2])
|
if (fixp[2])
|
||||||
{
|
{
|
||||||
fixp[2]->fx_frag = prev_insn_frag;
|
fixp[2]->fx_frag = history[0].frag;
|
||||||
fixp[2]->fx_where = prev_insn_where;
|
fixp[2]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (prev_insn_frag->fr_type == rs_machine_dependent)
|
else if (history[0].frag->fr_type == rs_machine_dependent)
|
||||||
{
|
{
|
||||||
if (fixp[0])
|
if (fixp[0])
|
||||||
fixp[0]->fx_where -= 4;
|
fixp[0]->fx_where -= 4;
|
||||||
|
@ -2646,10 +2661,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
char *prev_f;
|
char *prev_f;
|
||||||
char temp[2];
|
char temp[2];
|
||||||
|
|
||||||
assert (prev_insn_fixp[0] == NULL);
|
assert (history[0].fixp[0] == NULL);
|
||||||
assert (prev_insn_fixp[1] == NULL);
|
assert (history[0].fixp[1] == NULL);
|
||||||
assert (prev_insn_fixp[2] == NULL);
|
assert (history[0].fixp[2] == NULL);
|
||||||
prev_f = prev_insn_frag->fr_literal + prev_insn_where;
|
prev_f = history[0].frag->fr_literal + history[0].where;
|
||||||
memcpy (temp, prev_f, 2);
|
memcpy (temp, prev_f, 2);
|
||||||
memcpy (prev_f, f, 2);
|
memcpy (prev_f, f, 2);
|
||||||
if (*reloc_type != BFD_RELOC_MIPS16_JMP)
|
if (*reloc_type != BFD_RELOC_MIPS16_JMP)
|
||||||
|
@ -2664,42 +2679,45 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
}
|
}
|
||||||
if (fixp[0])
|
if (fixp[0])
|
||||||
{
|
{
|
||||||
fixp[0]->fx_frag = prev_insn_frag;
|
fixp[0]->fx_frag = history[0].frag;
|
||||||
fixp[0]->fx_where = prev_insn_where;
|
fixp[0]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
if (fixp[1])
|
if (fixp[1])
|
||||||
{
|
{
|
||||||
fixp[1]->fx_frag = prev_insn_frag;
|
fixp[1]->fx_frag = history[0].frag;
|
||||||
fixp[1]->fx_where = prev_insn_where;
|
fixp[1]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
if (fixp[2])
|
if (fixp[2])
|
||||||
{
|
{
|
||||||
fixp[2]->fx_frag = prev_insn_frag;
|
fixp[2]->fx_frag = history[0].frag;
|
||||||
fixp[2]->fx_where = prev_insn_where;
|
fixp[2]->fx_where = history[0].where;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the previous insn information; leave prev_insn
|
/* Update the previous insn information; leave history[0]
|
||||||
unchanged. */
|
unchanged. */
|
||||||
prev_prev_insn = *ip;
|
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;
|
||||||
}
|
}
|
||||||
prev_insn_is_delay_slot = 1;
|
history[0].delay_slot_p = 1;
|
||||||
|
|
||||||
/* If that was an unconditional branch, forget the previous
|
/* If that was an unconditional branch, forget the previous
|
||||||
insn information. */
|
insn information. */
|
||||||
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
|
if (pinfo & INSN_UNCOND_BRANCH_DELAY)
|
||||||
{
|
{
|
||||||
prev_prev_insn.insn_mo = &dummy_opcode;
|
history[1].insn_mo = &dummy_opcode;
|
||||||
prev_insn.insn_mo = &dummy_opcode;
|
history[0].insn_mo = &dummy_opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_insn_fixp[0] = NULL;
|
history[0].fixp[0] = NULL;
|
||||||
prev_insn_fixp[1] = NULL;
|
history[0].fixp[1] = NULL;
|
||||||
prev_insn_fixp[2] = NULL;
|
history[0].fixp[2] = NULL;
|
||||||
prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[0] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[1] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[2] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_extended = 0;
|
history[0].extended_p = 0;
|
||||||
}
|
}
|
||||||
else if (pinfo & INSN_COND_BRANCH_LIKELY)
|
else if (pinfo & INSN_COND_BRANCH_LIKELY)
|
||||||
{
|
{
|
||||||
|
@ -2709,60 +2727,77 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
||||||
the next instruction. */
|
the next instruction. */
|
||||||
emit_nop ();
|
emit_nop ();
|
||||||
/* Update the previous insn information. */
|
/* Update the previous insn information. */
|
||||||
prev_prev_insn = *ip;
|
history[1].insn_mo = ip->insn_mo;
|
||||||
prev_insn.insn_mo = &dummy_opcode;
|
history[1].use_extend = ip->use_extend;
|
||||||
prev_insn_fixp[0] = NULL;
|
history[1].extend = ip->extend;
|
||||||
prev_insn_fixp[1] = NULL;
|
history[1].insn_opcode = ip->insn_opcode;
|
||||||
prev_insn_fixp[2] = NULL;
|
history[0].insn_mo = &dummy_opcode;
|
||||||
prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
|
history[0].fixp[0] = NULL;
|
||||||
prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
|
history[0].fixp[1] = NULL;
|
||||||
prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
|
history[0].fixp[2] = NULL;
|
||||||
prev_insn_extended = 0;
|
history[0].reloc_type[0] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_is_delay_slot = 1;
|
history[0].reloc_type[1] = BFD_RELOC_UNUSED;
|
||||||
|
history[0].reloc_type[2] = BFD_RELOC_UNUSED;
|
||||||
|
history[0].extended_p = 0;
|
||||||
|
history[0].delay_slot_p = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Update the previous insn information. */
|
/* Update the previous insn information. */
|
||||||
if (nops > 0)
|
if (nops > 0)
|
||||||
prev_prev_insn.insn_mo = &dummy_opcode;
|
history[1].insn_mo = &dummy_opcode;
|
||||||
else
|
else
|
||||||
prev_prev_insn = prev_insn;
|
{
|
||||||
prev_insn = *ip;
|
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;
|
||||||
|
|
||||||
/* Any time we see a branch, we always fill the delay slot
|
/* Any time we see a branch, we always fill the delay slot
|
||||||
immediately; since this insn is not a branch, we know it
|
immediately; since this insn is not a branch, we know it
|
||||||
is not in a delay slot. */
|
is not in a delay slot. */
|
||||||
prev_insn_is_delay_slot = 0;
|
history[0].delay_slot_p = 0;
|
||||||
|
|
||||||
prev_insn_fixp[0] = fixp[0];
|
history[0].fixp[0] = fixp[0];
|
||||||
prev_insn_fixp[1] = fixp[1];
|
history[0].fixp[1] = fixp[1];
|
||||||
prev_insn_fixp[2] = fixp[2];
|
history[0].fixp[2] = fixp[2];
|
||||||
prev_insn_reloc_type[0] = reloc_type[0];
|
history[0].reloc_type[0] = reloc_type[0];
|
||||||
prev_insn_reloc_type[1] = reloc_type[1];
|
history[0].reloc_type[1] = reloc_type[1];
|
||||||
prev_insn_reloc_type[2] = reloc_type[2];
|
history[0].reloc_type[2] = reloc_type[2];
|
||||||
if (mips_opts.mips16)
|
if (mips_opts.mips16)
|
||||||
prev_insn_extended = (ip->use_extend
|
history[0].extended_p = (ip->use_extend
|
||||||
|| *reloc_type > BFD_RELOC_UNUSED);
|
|| *reloc_type > BFD_RELOC_UNUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_prev_insn_unreordered = prev_insn_unreordered;
|
history[1].noreorder_p = history[0].noreorder_p;
|
||||||
prev_insn_unreordered = 0;
|
history[0].noreorder_p = 0;
|
||||||
prev_insn_frag = frag_now;
|
history[0].frag = frag_now;
|
||||||
prev_insn_where = f - frag_now->fr_literal;
|
history[0].where = f - frag_now->fr_literal;
|
||||||
prev_insn_valid = 1;
|
history[0].valid_p = 1;
|
||||||
}
|
}
|
||||||
else if (mips_relax.sequence != 2)
|
else if (mips_relax.sequence != 2)
|
||||||
{
|
{
|
||||||
/* We need to record a bit of information even when we are not
|
/* We need to record a bit of information even when we are not
|
||||||
reordering, in order to determine the base address for mips16
|
reordering, in order to determine the base address for mips16
|
||||||
PC relative relocs. */
|
PC relative relocs. */
|
||||||
prev_prev_insn = prev_insn;
|
history[1].insn_mo = history[0].insn_mo;
|
||||||
prev_insn = *ip;
|
history[1].use_extend = history[0].use_extend;
|
||||||
prev_insn_reloc_type[0] = reloc_type[0];
|
history[1].extend = history[0].extend;
|
||||||
prev_insn_reloc_type[1] = reloc_type[1];
|
history[1].insn_opcode = history[0].insn_opcode;
|
||||||
prev_insn_reloc_type[2] = reloc_type[2];
|
history[0].insn_mo = ip->insn_mo;
|
||||||
prev_prev_insn_unreordered = prev_insn_unreordered;
|
history[0].use_extend = ip->use_extend;
|
||||||
prev_insn_unreordered = 1;
|
history[0].extend = ip->extend;
|
||||||
|
history[0].insn_opcode = ip->insn_opcode;
|
||||||
|
history[0].reloc_type[0] = reloc_type[0];
|
||||||
|
history[0].reloc_type[1] = reloc_type[1];
|
||||||
|
history[0].reloc_type[2] = reloc_type[2];
|
||||||
|
history[1].noreorder_p = history[0].noreorder_p;
|
||||||
|
history[0].noreorder_p = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We just output an insn, so the next one doesn't have a label. */
|
/* We just output an insn, so the next one doesn't have a label. */
|
||||||
|
@ -2778,21 +2813,21 @@ mips_no_prev_insn (int preserve)
|
||||||
{
|
{
|
||||||
if (! preserve)
|
if (! preserve)
|
||||||
{
|
{
|
||||||
prev_insn.insn_mo = &dummy_opcode;
|
history[0].insn_mo = &dummy_opcode;
|
||||||
prev_prev_insn.insn_mo = &dummy_opcode;
|
history[1].insn_mo = &dummy_opcode;
|
||||||
prev_nop_frag = NULL;
|
prev_nop_frag = NULL;
|
||||||
prev_nop_frag_holds = 0;
|
prev_nop_frag_holds = 0;
|
||||||
prev_nop_frag_required = 0;
|
prev_nop_frag_required = 0;
|
||||||
prev_nop_frag_since = 0;
|
prev_nop_frag_since = 0;
|
||||||
}
|
}
|
||||||
prev_insn_valid = 0;
|
history[0].valid_p = 0;
|
||||||
prev_insn_is_delay_slot = 0;
|
history[0].delay_slot_p = 0;
|
||||||
prev_insn_unreordered = 0;
|
history[0].noreorder_p = 0;
|
||||||
prev_insn_extended = 0;
|
history[0].extended_p = 0;
|
||||||
prev_insn_reloc_type[0] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[0] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_reloc_type[1] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[1] = BFD_RELOC_UNUSED;
|
||||||
prev_insn_reloc_type[2] = BFD_RELOC_UNUSED;
|
history[0].reloc_type[2] = BFD_RELOC_UNUSED;
|
||||||
prev_prev_insn_unreordered = 0;
|
history[1].noreorder_p = 0;
|
||||||
mips_clear_insn_labels ();
|
mips_clear_insn_labels ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2811,51 +2846,51 @@ mips_emit_delays (bfd_boolean insns)
|
||||||
|
|
||||||
nops = 0;
|
nops = 0;
|
||||||
if ((! mips_opts.mips16
|
if ((! mips_opts.mips16
|
||||||
&& ((prev_insn.insn_mo->pinfo
|
&& ((history[0].insn_mo->pinfo
|
||||||
& (INSN_LOAD_COPROC_DELAY
|
& (INSN_LOAD_COPROC_DELAY
|
||||||
| INSN_COPROC_MOVE_DELAY
|
| INSN_COPROC_MOVE_DELAY
|
||||||
| INSN_WRITE_COND_CODE))
|
| INSN_WRITE_COND_CODE))
|
||||||
&& ! cop_interlocks))
|
&& ! cop_interlocks))
|
||||||
|| (! hilo_interlocks
|
|| (! hilo_interlocks
|
||||||
&& (prev_insn.insn_mo->pinfo
|
&& (history[0].insn_mo->pinfo
|
||||||
& (INSN_READ_LO
|
& (INSN_READ_LO
|
||||||
| INSN_READ_HI)))
|
| INSN_READ_HI)))
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_insn.insn_mo->pinfo & INSN_LOAD_MEMORY_DELAY)
|
&& (history[0].insn_mo->pinfo & INSN_LOAD_MEMORY_DELAY)
|
||||||
&& ! gpr_interlocks)
|
&& ! gpr_interlocks)
|
||||||
|| (! mips_opts.mips16
|
|| (! mips_opts.mips16
|
||||||
&& (prev_insn.insn_mo->pinfo & INSN_COPROC_MEMORY_DELAY)
|
&& (history[0].insn_mo->pinfo & INSN_COPROC_MEMORY_DELAY)
|
||||||
&& ! cop_mem_interlocks))
|
&& ! cop_mem_interlocks))
|
||||||
{
|
{
|
||||||
/* Itbl support may require additional care here. */
|
/* Itbl support may require additional care here. */
|
||||||
++nops;
|
++nops;
|
||||||
if ((! mips_opts.mips16
|
if ((! mips_opts.mips16
|
||||||
&& ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
&& ((history[0].insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
||||||
&& ! cop_interlocks))
|
&& ! cop_interlocks))
|
||||||
|| (! hilo_interlocks
|
|| (! hilo_interlocks
|
||||||
&& ((prev_insn.insn_mo->pinfo & INSN_READ_HI)
|
&& ((history[0].insn_mo->pinfo & INSN_READ_HI)
|
||||||
|| (prev_insn.insn_mo->pinfo & INSN_READ_LO))))
|
|| (history[0].insn_mo->pinfo & INSN_READ_LO))))
|
||||||
++nops;
|
++nops;
|
||||||
|
|
||||||
if (prev_insn_unreordered)
|
if (history[0].noreorder_p)
|
||||||
nops = 0;
|
nops = 0;
|
||||||
}
|
}
|
||||||
else if ((! mips_opts.mips16
|
else if ((! mips_opts.mips16
|
||||||
&& ((prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
&& ((history[1].insn_mo->pinfo & INSN_WRITE_COND_CODE)
|
||||||
&& ! cop_interlocks))
|
&& ! cop_interlocks))
|
||||||
|| (! hilo_interlocks
|
|| (! hilo_interlocks
|
||||||
&& ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|
&& ((history[1].insn_mo->pinfo & INSN_READ_HI)
|
||||||
|| (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
|
|| (history[1].insn_mo->pinfo & INSN_READ_LO))))
|
||||||
{
|
{
|
||||||
/* Itbl support may require additional care here. */
|
/* Itbl support may require additional care here. */
|
||||||
if (! prev_prev_insn_unreordered)
|
if (! history[1].noreorder_p)
|
||||||
++nops;
|
++nops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mips_fix_vr4120 && prev_insn.insn_mo->name)
|
if (mips_fix_vr4120 && history[0].insn_mo->name)
|
||||||
{
|
{
|
||||||
int min_nops = 0;
|
int min_nops = 0;
|
||||||
const char *pn = prev_insn.insn_mo->name;
|
const char *pn = history[0].insn_mo->name;
|
||||||
if (strncmp (pn, "macc", 4) == 0
|
if (strncmp (pn, "macc", 4) == 0
|
||||||
|| strncmp (pn, "dmacc", 5) == 0
|
|| strncmp (pn, "dmacc", 5) == 0
|
||||||
|| strncmp (pn, "dmult", 5) == 0
|
|| strncmp (pn, "dmult", 5) == 0
|
||||||
|
@ -2920,7 +2955,7 @@ macro_start (void)
|
||||||
{
|
{
|
||||||
memset (&mips_macro_warning.sizes, 0, sizeof (mips_macro_warning.sizes));
|
memset (&mips_macro_warning.sizes, 0, sizeof (mips_macro_warning.sizes));
|
||||||
mips_macro_warning.delay_slot_p = (mips_opts.noreorder
|
mips_macro_warning.delay_slot_p = (mips_opts.noreorder
|
||||||
&& (prev_insn.insn_mo->pinfo
|
&& (history[0].insn_mo->pinfo
|
||||||
& (INSN_UNCOND_BRANCH_DELAY
|
& (INSN_UNCOND_BRANCH_DELAY
|
||||||
| INSN_COND_BRANCH_DELAY
|
| INSN_COND_BRANCH_DELAY
|
||||||
| INSN_COND_BRANCH_LIKELY)) != 0);
|
| INSN_COND_BRANCH_LIKELY)) != 0);
|
||||||
|
|
|
@ -79,15 +79,6 @@ enum mips_pic_level
|
||||||
|
|
||||||
extern enum mips_pic_level mips_pic;
|
extern enum mips_pic_level mips_pic;
|
||||||
|
|
||||||
struct mips_cl_insn
|
|
||||||
{
|
|
||||||
unsigned long insn_opcode;
|
|
||||||
const struct mips_opcode *insn_mo;
|
|
||||||
/* The next two fields are used when generating mips16 code. */
|
|
||||||
bfd_boolean use_extend;
|
|
||||||
unsigned short extend;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int tc_get_register (int frame);
|
extern int tc_get_register (int frame);
|
||||||
|
|
||||||
#define md_after_parse_args() mips_after_parse_args()
|
#define md_after_parse_args() mips_after_parse_args()
|
||||||
|
|
Loading…
Reference in New Issue