gas/
* config/tc-mips.c (insn_uses_reg): Delete. (gpr_read_mask, gpr_write_mask): New functions. (fpr_read_mask, fpr_write_mask): Likewise. (insns_between, nops_for_vr4130, append_insn): Use them. gas/testsuite/ * gas/mips/mips16-e.d, gas/mips/mips16-f.d, gas/mips/mipsel16-e.d, gas/mips/mipsel16-f.d, gas/mips/tmips16-e.d, gas/mips/tmips16-f.d, gas/mips/tmipsel16-e.d, gas/mips/tmipsel16-f.d: Fix GPR mask. * gas/mips/reginfo-1.s, gas/mips/reginfo-1a.d, gas/mips/reginfo-1b.d: New tests. * gas/mips/mips.exp: Run them.
This commit is contained in:
parent
02b1ab82d7
commit
4c26037942
15 changed files with 214 additions and 233 deletions
|
@ -1,3 +1,10 @@
|
|||
2011-06-29 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* config/tc-mips.c (insn_uses_reg): Delete.
|
||||
(gpr_read_mask, gpr_write_mask): New functions.
|
||||
(fpr_read_mask, fpr_write_mask): Likewise.
|
||||
(insns_between, nops_for_vr4130, append_insn): Use them.
|
||||
|
||||
2011-06-29 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* config/tc-mips.c (md_mips_end): Call mips_emit_delays.
|
||||
|
|
|
@ -2243,88 +2243,6 @@ fixup_has_matching_lo_p (fixS *fixp)
|
|||
&& fixp->fx_offset == fixp->fx_next->fx_offset);
|
||||
}
|
||||
|
||||
/* See whether instruction IP reads register REG. CLASS is the type
|
||||
of register. */
|
||||
|
||||
static int
|
||||
insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg,
|
||||
enum mips_regclass regclass)
|
||||
{
|
||||
if (regclass == MIPS16_REG)
|
||||
{
|
||||
gas_assert (mips_opts.mips16);
|
||||
reg = mips16_to_32_reg_map[reg];
|
||||
regclass = MIPS_GR_REG;
|
||||
}
|
||||
|
||||
/* Don't report on general register ZERO, since it never changes. */
|
||||
if (regclass == MIPS_GR_REG && reg == ZERO)
|
||||
return 0;
|
||||
|
||||
if (regclass == MIPS_FP_REG)
|
||||
{
|
||||
gas_assert (! mips_opts.mips16);
|
||||
/* If we are called with either $f0 or $f1, we must check $f0.
|
||||
This is not optimal, because it will introduce an unnecessary
|
||||
NOP between "lwc1 $f0" and "swc1 $f1". To fix this we would
|
||||
need to distinguish reading both $f0 and $f1 or just one of
|
||||
them. Note that we don't have to check the other way,
|
||||
because there is no instruction that sets both $f0 and $f1
|
||||
and requires a delay. */
|
||||
if ((ip->insn_mo->pinfo & INSN_READ_FPR_S)
|
||||
&& ((EXTRACT_OPERAND (FS, *ip) & ~(unsigned) 1)
|
||||
== (reg &~ (unsigned) 1)))
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)
|
||||
&& ((EXTRACT_OPERAND (FT, *ip) & ~(unsigned) 1)
|
||||
== (reg &~ (unsigned) 1)))
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo2 & INSN2_READ_FPR_Z)
|
||||
&& ((EXTRACT_OPERAND (FZ, *ip) & ~(unsigned) 1)
|
||||
== (reg &~ (unsigned) 1)))
|
||||
return 1;
|
||||
}
|
||||
else if (! mips_opts.mips16)
|
||||
{
|
||||
if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)
|
||||
&& EXTRACT_OPERAND (RS, *ip) == reg)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
|
||||
&& EXTRACT_OPERAND (RT, *ip) == reg)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_D)
|
||||
&& EXTRACT_OPERAND (RD, *ip) == reg)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_Z)
|
||||
&& EXTRACT_OPERAND (RZ, *ip) == reg)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_X)
|
||||
&& mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)] == reg)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Y)
|
||||
&& mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)] == reg)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Z)
|
||||
&& (mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip)]
|
||||
== reg))
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_T) && reg == TREG)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_SP) && reg == SP)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_31) && reg == RA)
|
||||
return 1;
|
||||
if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_GPR_X)
|
||||
&& MIPS16_EXTRACT_OPERAND (REGR32, *ip) == reg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function returns true if modifying a register requires a
|
||||
delay. */
|
||||
|
||||
|
@ -2477,6 +2395,149 @@ relax_end (void)
|
|||
mips_relax.sequence = 0;
|
||||
}
|
||||
|
||||
/* Return the mask of core registers that IP reads. */
|
||||
|
||||
static unsigned int
|
||||
gpr_read_mask (const struct mips_cl_insn *ip)
|
||||
{
|
||||
unsigned long pinfo, pinfo2;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
pinfo = ip->insn_mo->pinfo;
|
||||
pinfo2 = ip->insn_mo->pinfo2;
|
||||
if (mips_opts.mips16)
|
||||
{
|
||||
if (pinfo & MIPS16_INSN_READ_X)
|
||||
mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)];
|
||||
if (pinfo & MIPS16_INSN_READ_Y)
|
||||
mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)];
|
||||
if (pinfo & MIPS16_INSN_READ_T)
|
||||
mask |= 1 << TREG;
|
||||
if (pinfo & MIPS16_INSN_READ_SP)
|
||||
mask |= 1 << SP;
|
||||
if (pinfo & MIPS16_INSN_READ_31)
|
||||
mask |= 1 << RA;
|
||||
if (pinfo & MIPS16_INSN_READ_Z)
|
||||
mask |= 1 << (mips16_to_32_reg_map
|
||||
[MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip)]);
|
||||
if (pinfo & MIPS16_INSN_READ_GPR_X)
|
||||
mask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinfo2 & INSN2_READ_GPR_D)
|
||||
mask |= 1 << EXTRACT_OPERAND (RD, *ip);
|
||||
if (pinfo & INSN_READ_GPR_T)
|
||||
mask |= 1 << EXTRACT_OPERAND (RT, *ip);
|
||||
if (pinfo & INSN_READ_GPR_S)
|
||||
mask |= 1 << EXTRACT_OPERAND (RS, *ip);
|
||||
if (pinfo2 & INSN2_READ_GPR_Z)
|
||||
mask |= 1 << EXTRACT_OPERAND (RZ, *ip);
|
||||
}
|
||||
return mask & ~0;
|
||||
}
|
||||
|
||||
/* Return the mask of core registers that IP writes. */
|
||||
|
||||
static unsigned int
|
||||
gpr_write_mask (const struct mips_cl_insn *ip)
|
||||
{
|
||||
unsigned long pinfo, pinfo2;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
pinfo = ip->insn_mo->pinfo;
|
||||
pinfo2 = ip->insn_mo->pinfo2;
|
||||
if (mips_opts.mips16)
|
||||
{
|
||||
if (pinfo & MIPS16_INSN_WRITE_X)
|
||||
mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)];
|
||||
if (pinfo & MIPS16_INSN_WRITE_Y)
|
||||
mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)];
|
||||
if (pinfo & MIPS16_INSN_WRITE_Z)
|
||||
mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RZ, *ip)];
|
||||
if (pinfo & MIPS16_INSN_WRITE_T)
|
||||
mask |= 1 << TREG;
|
||||
if (pinfo & MIPS16_INSN_WRITE_SP)
|
||||
mask |= 1 << SP;
|
||||
if (pinfo & MIPS16_INSN_WRITE_31)
|
||||
mask |= 1 << RA;
|
||||
if (pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||
mask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinfo & INSN_WRITE_GPR_D)
|
||||
mask |= 1 << EXTRACT_OPERAND (RD, *ip);
|
||||
if (pinfo & INSN_WRITE_GPR_T)
|
||||
mask |= 1 << EXTRACT_OPERAND (RT, *ip);
|
||||
if (pinfo & INSN_WRITE_GPR_31)
|
||||
mask |= 1 << RA;
|
||||
if (pinfo2 & INSN2_WRITE_GPR_Z)
|
||||
mask |= 1 << EXTRACT_OPERAND (RZ, *ip);
|
||||
}
|
||||
return mask & ~0;
|
||||
}
|
||||
|
||||
/* Return the mask of floating-point registers that IP reads. */
|
||||
|
||||
static unsigned int
|
||||
fpr_read_mask (const struct mips_cl_insn *ip)
|
||||
{
|
||||
unsigned long pinfo, pinfo2;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
pinfo = ip->insn_mo->pinfo;
|
||||
pinfo2 = ip->insn_mo->pinfo2;
|
||||
if (!mips_opts.mips16)
|
||||
{
|
||||
if (pinfo & INSN_READ_FPR_S)
|
||||
mask |= 1 << EXTRACT_OPERAND (FS, *ip);
|
||||
if (pinfo & INSN_READ_FPR_T)
|
||||
mask |= 1 << EXTRACT_OPERAND (FT, *ip);
|
||||
if (pinfo & INSN_READ_FPR_R)
|
||||
mask |= 1 << EXTRACT_OPERAND (FR, *ip);
|
||||
if (pinfo2 & INSN2_READ_FPR_Z)
|
||||
mask |= 1 << EXTRACT_OPERAND (FZ, *ip);
|
||||
}
|
||||
/* Conservatively treat all operands to an FP_D instruction are doubles.
|
||||
(This is overly pessimistic for things like cvt.d.s.) */
|
||||
if (HAVE_32BIT_FPRS && (pinfo & FP_D))
|
||||
mask |= mask << 1;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* Return the mask of floating-point registers that IP writes. */
|
||||
|
||||
static unsigned int
|
||||
fpr_write_mask (const struct mips_cl_insn *ip)
|
||||
{
|
||||
unsigned long pinfo, pinfo2;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
pinfo = ip->insn_mo->pinfo;
|
||||
pinfo2 = ip->insn_mo->pinfo2;
|
||||
if (!mips_opts.mips16)
|
||||
{
|
||||
if (pinfo & INSN_WRITE_FPR_D)
|
||||
mask |= 1 << EXTRACT_OPERAND (FD, *ip);
|
||||
if (pinfo & INSN_WRITE_FPR_S)
|
||||
mask |= 1 << EXTRACT_OPERAND (FS, *ip);
|
||||
if (pinfo & INSN_WRITE_FPR_T)
|
||||
mask |= 1 << EXTRACT_OPERAND (FT, *ip);
|
||||
if (pinfo2 & INSN2_WRITE_FPR_Z)
|
||||
mask |= 1 << EXTRACT_OPERAND (FZ, *ip);
|
||||
}
|
||||
/* Conservatively treat all operands to an FP_D instruction are doubles.
|
||||
(This is overly pessimistic for things like cvt.s.d.) */
|
||||
if (HAVE_32BIT_FPRS && (pinfo & FP_D))
|
||||
mask |= mask << 1;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* Classify an instruction according to the FIX_VR4120_* enumeration.
|
||||
Return NUM_FIX_VR4120_CLASSES if the instruction isn't affected
|
||||
by VR4120 errata. */
|
||||
|
@ -2511,16 +2572,17 @@ insns_between (const struct mips_cl_insn *insn1,
|
|||
const struct mips_cl_insn *insn2)
|
||||
{
|
||||
unsigned long pinfo1, pinfo2;
|
||||
unsigned int mask;
|
||||
|
||||
/* This function needs to know which pinfo flags are set for INSN2
|
||||
and which registers INSN2 uses. The former is stored in PINFO2 and
|
||||
the latter is tested via INSN2_USES_REG. If INSN2 is null, PINFO2
|
||||
will have every flag set and INSN2_USES_REG will always return true. */
|
||||
the latter is tested via INSN2_USES_GPR. If INSN2 is null, PINFO2
|
||||
will have every flag set and INSN2_USES_GPR will always return true. */
|
||||
pinfo1 = insn1->insn_mo->pinfo;
|
||||
pinfo2 = insn2 ? insn2->insn_mo->pinfo : ~0U;
|
||||
|
||||
#define INSN2_USES_REG(REG, CLASS) \
|
||||
(insn2 == NULL || insn_uses_reg (insn2, REG, CLASS))
|
||||
#define INSN2_USES_GPR(REG) \
|
||||
(insn2 == NULL || (gpr_read_mask (insn2) & (1U << (REG))) != 0)
|
||||
|
||||
/* For most targets, write-after-read dependencies on the HI and LO
|
||||
registers must be separated by at least two instructions. */
|
||||
|
@ -2536,7 +2598,7 @@ insns_between (const struct mips_cl_insn *insn1,
|
|||
between an mfhi or mflo and any instruction that uses the result. */
|
||||
if (mips_7000_hilo_fix
|
||||
&& MF_HILO_INSN (pinfo1)
|
||||
&& INSN2_USES_REG (EXTRACT_OPERAND (RD, *insn1), MIPS_GR_REG))
|
||||
&& INSN2_USES_GPR (EXTRACT_OPERAND (RD, *insn1)))
|
||||
return 2;
|
||||
|
||||
/* If we're working around 24K errata, one instruction is required
|
||||
|
@ -2583,7 +2645,7 @@ insns_between (const struct mips_cl_insn *insn1,
|
|||
|| (!cop_interlocks && (pinfo1 & INSN_LOAD_COPROC_DELAY)))
|
||||
{
|
||||
know (pinfo1 & INSN_WRITE_GPR_T);
|
||||
if (INSN2_USES_REG (EXTRACT_OPERAND (RT, *insn1), MIPS_GR_REG))
|
||||
if (INSN2_USES_GPR (EXTRACT_OPERAND (RT, *insn1)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2601,14 +2663,10 @@ insns_between (const struct mips_cl_insn *insn1,
|
|||
/* Handle cases where INSN1 writes to a known general coprocessor
|
||||
register. There must be a one instruction delay before INSN2
|
||||
if INSN2 reads that register, otherwise no delay is needed. */
|
||||
if (pinfo1 & INSN_WRITE_FPR_T)
|
||||
mask = fpr_write_mask (insn1);
|
||||
if (mask != 0)
|
||||
{
|
||||
if (INSN2_USES_REG (EXTRACT_OPERAND (FT, *insn1), MIPS_FP_REG))
|
||||
return 1;
|
||||
}
|
||||
else if (pinfo1 & INSN_WRITE_FPR_S)
|
||||
{
|
||||
if (INSN2_USES_REG (EXTRACT_OPERAND (FS, *insn1), MIPS_FP_REG))
|
||||
if (!insn2 || (mask & fpr_read_mask (insn2)) != 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -2638,7 +2696,7 @@ insns_between (const struct mips_cl_insn *insn1,
|
|||
return 1;
|
||||
}
|
||||
|
||||
#undef INSN2_USES_REG
|
||||
#undef INSN2_USES_GPR
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2652,7 +2710,8 @@ static int
|
|||
nops_for_vr4130 (int ignore, const struct mips_cl_insn *hist,
|
||||
const struct mips_cl_insn *insn)
|
||||
{
|
||||
int i, j, reg;
|
||||
int i, j;
|
||||
unsigned int mask;
|
||||
|
||||
/* Check if the instruction writes to HI or LO. MTHI and MTLO
|
||||
are not affected by the errata. */
|
||||
|
@ -2667,18 +2726,15 @@ nops_for_vr4130 (int ignore, const struct mips_cl_insn *hist,
|
|||
if (MF_HILO_INSN (hist[i].insn_mo->pinfo))
|
||||
{
|
||||
/* Extract the destination register. */
|
||||
if (mips_opts.mips16)
|
||||
reg = mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, hist[i])];
|
||||
else
|
||||
reg = EXTRACT_OPERAND (RD, hist[i]);
|
||||
mask = gpr_write_mask (&hist[i]);
|
||||
|
||||
/* No nops are needed if INSN reads that register. */
|
||||
if (insn != NULL && insn_uses_reg (insn, reg, MIPS_GR_REG))
|
||||
if (insn != NULL && (gpr_read_mask (insn) & mask) != 0)
|
||||
return 0;
|
||||
|
||||
/* ...or if any of the intervening instructions do. */
|
||||
for (j = 0; j < i; j++)
|
||||
if (insn_uses_reg (&hist[j], reg, MIPS_GR_REG))
|
||||
if (gpr_read_mask (&hist[j]) & mask)
|
||||
return 0;
|
||||
|
||||
if (i >= ignore)
|
||||
|
@ -3396,59 +3452,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||
install_insn (ip);
|
||||
|
||||
/* Update the register mask information. */
|
||||
if (! mips_opts.mips16)
|
||||
{
|
||||
if ((pinfo & INSN_WRITE_GPR_D) || (pinfo2 & INSN2_READ_GPR_D))
|
||||
mips_gprmask |= 1 << EXTRACT_OPERAND (RD, *ip);
|
||||
if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0)
|
||||
mips_gprmask |= 1 << EXTRACT_OPERAND (RT, *ip);
|
||||
if (pinfo & INSN_READ_GPR_S)
|
||||
mips_gprmask |= 1 << EXTRACT_OPERAND (RS, *ip);
|
||||
if (pinfo & INSN_WRITE_GPR_31)
|
||||
mips_gprmask |= 1 << RA;
|
||||
if (pinfo2 & (INSN2_WRITE_GPR_Z | INSN2_READ_GPR_Z))
|
||||
mips_gprmask |= 1 << EXTRACT_OPERAND (RZ, *ip);
|
||||
if (pinfo & INSN_WRITE_FPR_D)
|
||||
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FD, *ip);
|
||||
if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0)
|
||||
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FS, *ip);
|
||||
if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0)
|
||||
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FT, *ip);
|
||||
if ((pinfo & INSN_READ_FPR_R) != 0)
|
||||
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FR, *ip);
|
||||
if (pinfo2 & (INSN2_WRITE_FPR_Z | INSN2_READ_FPR_Z))
|
||||
mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FZ, *ip);
|
||||
if (pinfo & INSN_COP)
|
||||
{
|
||||
/* We don't keep enough information to sort these cases out.
|
||||
The itbl support does keep this information however, although
|
||||
we currently don't support itbl fprmats as part of the cop
|
||||
instruction. May want to add this support in the future. */
|
||||
}
|
||||
/* Never set the bit for $0, which is always zero. */
|
||||
mips_gprmask &= ~1 << 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pinfo & (MIPS16_INSN_WRITE_X | MIPS16_INSN_READ_X))
|
||||
mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RX, *ip);
|
||||
if (pinfo & (MIPS16_INSN_WRITE_Y | MIPS16_INSN_READ_Y))
|
||||
mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RY, *ip);
|
||||
if (pinfo & MIPS16_INSN_WRITE_Z)
|
||||
mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RZ, *ip);
|
||||
if (pinfo & (MIPS16_INSN_WRITE_T | MIPS16_INSN_READ_T))
|
||||
mips_gprmask |= 1 << TREG;
|
||||
if (pinfo & (MIPS16_INSN_WRITE_SP | MIPS16_INSN_READ_SP))
|
||||
mips_gprmask |= 1 << SP;
|
||||
if (pinfo & (MIPS16_INSN_WRITE_31 | MIPS16_INSN_READ_31))
|
||||
mips_gprmask |= 1 << RA;
|
||||
if (pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||
mips_gprmask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode);
|
||||
if (pinfo & MIPS16_INSN_READ_Z)
|
||||
mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip);
|
||||
if (pinfo & MIPS16_INSN_READ_GPR_X)
|
||||
mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip);
|
||||
}
|
||||
mips_gprmask |= gpr_read_mask (ip) | gpr_write_mask (ip);
|
||||
mips_cprmask[1] |= fpr_read_mask (ip) | fpr_write_mask (ip);
|
||||
|
||||
if (mips_relax.sequence != 2 && !mips_opts.noreorder)
|
||||
{
|
||||
|
@ -3504,77 +3509,13 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
|
|||
|| (prev_pinfo & INSN_TRAP)
|
||||
/* If the branch reads a register that the previous
|
||||
instruction sets, we can not swap. */
|
||||
|| (! mips_opts.mips16
|
||||
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
||||
&& insn_uses_reg (ip, EXTRACT_OPERAND (RT, history[0]),
|
||||
MIPS_GR_REG))
|
||||
|| (! mips_opts.mips16
|
||||
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
||||
&& insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]),
|
||||
MIPS_GR_REG))
|
||||
|| (! mips_opts.mips16
|
||||
&& (prev_pinfo2 & INSN2_WRITE_GPR_Z)
|
||||
&& insn_uses_reg (ip, EXTRACT_OPERAND (RZ, history[0]),
|
||||
MIPS_GR_REG))
|
||||
|| (mips_opts.mips16
|
||||
&& (((prev_pinfo & MIPS16_INSN_WRITE_X)
|
||||
&& (insn_uses_reg
|
||||
(ip, MIPS16_EXTRACT_OPERAND (RX, history[0]),
|
||||
MIPS16_REG)))
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_Y)
|
||||
&& (insn_uses_reg
|
||||
(ip, MIPS16_EXTRACT_OPERAND (RY, history[0]),
|
||||
MIPS16_REG)))
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_Z)
|
||||
&& (insn_uses_reg
|
||||
(ip, MIPS16_EXTRACT_OPERAND (RZ, history[0]),
|
||||
MIPS16_REG)))
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_T)
|
||||
&& insn_uses_reg (ip, TREG, MIPS_GR_REG))
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_31)
|
||||
&& insn_uses_reg (ip, RA, MIPS_GR_REG))
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||
&& insn_uses_reg (ip,
|
||||
MIPS16OP_EXTRACT_REG32R
|
||||
(history[0].insn_opcode),
|
||||
MIPS_GR_REG))))
|
||||
|| (gpr_read_mask (ip) & gpr_write_mask (&history[0])) != 0
|
||||
/* 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). */
|
||||
|| (! mips_opts.mips16
|
||||
&& (prev_pinfo & INSN_WRITE_GPR_T)
|
||||
&& (((pinfo & INSN_WRITE_GPR_D)
|
||||
&& (EXTRACT_OPERAND (RT, history[0])
|
||||
== EXTRACT_OPERAND (RD, *ip)))
|
||||
|| ((pinfo & INSN_WRITE_GPR_31)
|
||||
&& EXTRACT_OPERAND (RT, history[0]) == RA)))
|
||||
|| (! mips_opts.mips16
|
||||
&& (prev_pinfo & INSN_WRITE_GPR_D)
|
||||
&& (((pinfo & INSN_WRITE_GPR_D)
|
||||
&& (EXTRACT_OPERAND (RD, history[0])
|
||||
== EXTRACT_OPERAND (RD, *ip)))
|
||||
|| ((pinfo & INSN_WRITE_GPR_31)
|
||||
&& EXTRACT_OPERAND (RD, history[0]) == RA)))
|
||||
|| (mips_opts.mips16
|
||||
&& (pinfo & MIPS16_INSN_WRITE_31)
|
||||
&& ((prev_pinfo & MIPS16_INSN_WRITE_31)
|
||||
|| ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
|
||||
&& (MIPS16OP_EXTRACT_REG32R (history[0].insn_opcode)
|
||||
== RA))))
|
||||
instruction sets, we can not swap. */
|
||||
|| (gpr_write_mask (ip) & gpr_write_mask (&history[0])) != 0
|
||||
/* 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). */
|
||||
|| (! mips_opts.mips16
|
||||
&& (pinfo & INSN_WRITE_GPR_D)
|
||||
&& insn_uses_reg (&history[0],
|
||||
EXTRACT_OPERAND (RD, *ip),
|
||||
MIPS_GR_REG))
|
||||
|| (! mips_opts.mips16
|
||||
&& (pinfo & INSN_WRITE_GPR_31)
|
||||
&& insn_uses_reg (&history[0], RA, MIPS_GR_REG))
|
||||
|| (mips_opts.mips16
|
||||
&& (pinfo & MIPS16_INSN_WRITE_31)
|
||||
&& insn_uses_reg (&history[0], RA, MIPS_GR_REG))
|
||||
instruction reads, we can not swap. */
|
||||
|| (gpr_write_mask (ip) & gpr_read_mask (&history[0])) != 0
|
||||
/* If one instruction sets a condition code and the
|
||||
other one uses a condition code, we can not swap. */
|
||||
|| ((pinfo & INSN_READ_COND_CODE)
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2011-06-29 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* gas/mips/mips16-e.d, gas/mips/mips16-f.d,
|
||||
gas/mips/mipsel16-e.d, gas/mips/mipsel16-f.d,
|
||||
gas/mips/tmips16-e.d, gas/mips/tmips16-f.d,
|
||||
gas/mips/tmipsel16-e.d, gas/mips/tmipsel16-f.d: Fix GPR mask.
|
||||
* gas/mips/reginfo-1.s, gas/mips/reginfo-1a.d,
|
||||
gas/mips/reginfo-1b.d: New tests.
|
||||
* gas/mips/mips.exp: Run them.
|
||||
|
||||
2011-06-29 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* gas/mips/24k-triple-stores-9.d: Add -z to dump options and
|
||||
|
|
|
@ -1002,4 +1002,6 @@ if { [istarget mips*-*-vxworks*] } {
|
|||
if $has_newabi { run_dump_test "cfi-n64-1" }
|
||||
|
||||
run_dump_test "pr12915"
|
||||
run_dump_test "reginfo-1a"
|
||||
run_dump_test "reginfo-1b"
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 65006500 65006500 65006500 65006500 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 00000001 00000000 00000000 00000000 .*
|
||||
0000 00010000 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000000 00000008 00000000 00000003 .*
|
||||
|
|
|
@ -24,7 +24,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 65006500 65006500 65006500 65006500 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 00000001 00000000 00000000 00000000 .*
|
||||
0000 00010000 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000003 00000000 00000000 00000000 .*
|
||||
|
|
|
@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 00650065 00650065 00650065 00650065 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 01000000 00000000 00000000 00000000 .*
|
||||
0000 00000100 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000000 08000000 00000000 03000000 .*
|
||||
|
|
|
@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 00650065 00650065 00650065 00650065 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 01000000 00000000 00000000 00000000 .*
|
||||
0000 00000100 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 03000000 00000000 00000000 00000000 .*
|
||||
|
|
3
gas/testsuite/gas/mips/reginfo-1.s
Normal file
3
gas/testsuite/gas/mips/reginfo-1.s
Normal file
|
@ -0,0 +1,3 @@
|
|||
ldc1 $f4,($4)
|
||||
add.s $f10,$f10,$f10
|
||||
add.d $f16,$f16,$f16
|
9
gas/testsuite/gas/mips/reginfo-1a.d
Normal file
9
gas/testsuite/gas/mips/reginfo-1a.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
#source: reginfo-1.s
|
||||
#as: -32 -EL -mips4
|
||||
#objdump: -sj.reginfo
|
||||
|
||||
.*
|
||||
|
||||
Contents of section \.reginfo:
|
||||
0000 10000000 00000000 30040300 00000000 .*
|
||||
0010 00000000 00000000 .*
|
9
gas/testsuite/gas/mips/reginfo-1b.d
Normal file
9
gas/testsuite/gas/mips/reginfo-1b.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
#source: reginfo-1.s
|
||||
#as: -mabi=o64 -EB -mips4
|
||||
#objdump: -sj.reginfo
|
||||
|
||||
.*
|
||||
|
||||
Contents of section \.reginfo:
|
||||
0000 00000010 00000000 00010410 00000000 .*
|
||||
0010 00000000 00000000 .*
|
|
@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 65006500 65006500 65006500 65006500 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 00000001 00000000 00000000 00000000 .*
|
||||
0000 00010000 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000000 00000008 00000000 00000003 .*
|
||||
|
|
|
@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 65006500 65006500 65006500 65006500 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 00000001 00000000 00000000 00000000 .*
|
||||
0000 00010000 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000003 00000000 00000000 00000000 .*
|
||||
|
|
|
@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 00650065 00650065 00650065 00650065 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 01000000 00000000 00000000 00000000 .*
|
||||
0000 00000100 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 00000000 08000000 00000000 03000000 .*
|
||||
|
|
|
@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE VALUE
|
|||
Contents of section \.text:
|
||||
0000 00650065 00650065 00650065 00650065 .*
|
||||
Contents of section \.reginfo:
|
||||
0000 01000000 00000000 00000000 00000000 .*
|
||||
0000 00000100 00000000 00000000 00000000 .*
|
||||
0010 00000000 00000000 .*
|
||||
Contents of section foo:
|
||||
0000 03000000 00000000 00000000 00000000 .*
|
||||
|
|
Loading…
Reference in a new issue