From 4c26037942d435934e3523a6979bff47cae4ef81 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 29 Jun 2011 20:39:00 +0000 Subject: [PATCH] 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. --- gas/ChangeLog | 7 + gas/config/tc-mips.c | 391 ++++++++++++--------------- gas/testsuite/ChangeLog | 10 + gas/testsuite/gas/mips/mips.exp | 2 + gas/testsuite/gas/mips/mips16-e.d | 2 +- gas/testsuite/gas/mips/mips16-f.d | 2 +- gas/testsuite/gas/mips/mipsel16-e.d | 2 +- gas/testsuite/gas/mips/mipsel16-f.d | 2 +- gas/testsuite/gas/mips/reginfo-1.s | 3 + gas/testsuite/gas/mips/reginfo-1a.d | 9 + gas/testsuite/gas/mips/reginfo-1b.d | 9 + gas/testsuite/gas/mips/tmips16-e.d | 2 +- gas/testsuite/gas/mips/tmips16-f.d | 2 +- gas/testsuite/gas/mips/tmipsel16-e.d | 2 +- gas/testsuite/gas/mips/tmipsel16-f.d | 2 +- 15 files changed, 214 insertions(+), 233 deletions(-) create mode 100644 gas/testsuite/gas/mips/reginfo-1.s create mode 100644 gas/testsuite/gas/mips/reginfo-1a.d create mode 100644 gas/testsuite/gas/mips/reginfo-1b.d diff --git a/gas/ChangeLog b/gas/ChangeLog index c450f454cf7..a2ddcda3d2c 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2011-06-29 Richard Sandiford + + * 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 * config/tc-mips.c (md_mips_end): Call mips_emit_delays. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 5f1470be7b9..345d6d0df4c 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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) - { - if (INSN2_USES_REG (EXTRACT_OPERAND (FT, *insn1), MIPS_FP_REG)) - return 1; - } - else if (pinfo1 & INSN_WRITE_FPR_S) + mask = fpr_write_mask (insn1); + if (mask != 0) { - 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) diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index e22630c5904..06941261c35 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2011-06-29 Richard Sandiford + + * 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 * gas/mips/24k-triple-stores-9.d: Add -z to dump options and diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index d51ac43b3ca..e31dbad0a2b 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -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" } diff --git a/gas/testsuite/gas/mips/mips16-e.d b/gas/testsuite/gas/mips/mips16-e.d index b8134dcdf50..656aee7fdc6 100644 --- a/gas/testsuite/gas/mips/mips16-e.d +++ b/gas/testsuite/gas/mips/mips16-e.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/mips16-f.d b/gas/testsuite/gas/mips/mips16-f.d index 84deb36e9f5..9a2ce3bbd38 100644 --- a/gas/testsuite/gas/mips/mips16-f.d +++ b/gas/testsuite/gas/mips/mips16-f.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/mipsel16-e.d b/gas/testsuite/gas/mips/mipsel16-e.d index be84fe38882..838bd260ab8 100644 --- a/gas/testsuite/gas/mips/mipsel16-e.d +++ b/gas/testsuite/gas/mips/mipsel16-e.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/mipsel16-f.d b/gas/testsuite/gas/mips/mipsel16-f.d index 9331f10ad01..8c1e2ea6634 100644 --- a/gas/testsuite/gas/mips/mipsel16-f.d +++ b/gas/testsuite/gas/mips/mipsel16-f.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/reginfo-1.s b/gas/testsuite/gas/mips/reginfo-1.s new file mode 100644 index 00000000000..927c54d6575 --- /dev/null +++ b/gas/testsuite/gas/mips/reginfo-1.s @@ -0,0 +1,3 @@ + ldc1 $f4,($4) + add.s $f10,$f10,$f10 + add.d $f16,$f16,$f16 diff --git a/gas/testsuite/gas/mips/reginfo-1a.d b/gas/testsuite/gas/mips/reginfo-1a.d new file mode 100644 index 00000000000..792d51d20ec --- /dev/null +++ b/gas/testsuite/gas/mips/reginfo-1a.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/reginfo-1b.d b/gas/testsuite/gas/mips/reginfo-1b.d new file mode 100644 index 00000000000..b0d42c206e7 --- /dev/null +++ b/gas/testsuite/gas/mips/reginfo-1b.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/tmips16-e.d b/gas/testsuite/gas/mips/tmips16-e.d index a610dc707fb..dd751738bc5 100644 --- a/gas/testsuite/gas/mips/tmips16-e.d +++ b/gas/testsuite/gas/mips/tmips16-e.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/tmips16-f.d b/gas/testsuite/gas/mips/tmips16-f.d index 8e3304ca9b4..f865d1ddb99 100644 --- a/gas/testsuite/gas/mips/tmips16-f.d +++ b/gas/testsuite/gas/mips/tmips16-f.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/tmipsel16-e.d b/gas/testsuite/gas/mips/tmipsel16-e.d index ecaa8bd1b48..4caf18ba44d 100644 --- a/gas/testsuite/gas/mips/tmipsel16-e.d +++ b/gas/testsuite/gas/mips/tmipsel16-e.d @@ -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 .* diff --git a/gas/testsuite/gas/mips/tmipsel16-f.d b/gas/testsuite/gas/mips/tmipsel16-f.d index 3c21e2d3d75..5daa5931f23 100644 --- a/gas/testsuite/gas/mips/tmipsel16-f.d +++ b/gas/testsuite/gas/mips/tmipsel16-f.d @@ -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 .* -- 2.30.2