diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2012-11-01 22:49:28 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@linux-mips.org> | 2012-11-01 22:49:28 +0000 |
commit | e64af278469a4101a3fa515bda4d2d977051b8d4 (patch) | |
tree | 608350a29b6a8a7160c399e0f84c405d012bbbe9 /gas/config | |
parent | c2c9fdb45e95aeed8540383f14cad9a85a186b1b (diff) | |
download | gdb-e64af278469a4101a3fa515bda4d2d977051b8d4.zip gdb-e64af278469a4101a3fa515bda4d2d977051b8d4.tar.gz gdb-e64af278469a4101a3fa515bda4d2d977051b8d4.tar.bz2 |
gas/
* config/tc-mips.c (is_delay_slot_valid): Don't accept macros
in 16-bit delay slots.
(macro_build_jalr): Emit 32-bit JALR if placed in a 32-bit delay
slot.
(macro) <M_JAL_2>: Likewise
gas/testsuite/
* gas/mips/micromips-branch-delay.l: Update messages for 16-bit
delay slot changes.
* gas/mips/micromips-warn-branch-delay.d: New test.
* gas/mips/micromips-warn-branch-delay.l: Stderr output for the
new test.
* gas/mips/micromips-warn-branch-delay-1.d: New test.
* gas/mips/micromips-warn-branch-delay.s: New test source.
* gas/mips/micromips-warn-branch-delay-1.s: New test source.
* gas/mips/mips.exp: Run the new tests.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index e866010..dcea7bc 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2301,7 +2301,18 @@ is_size_valid (const struct mips_opcode *mo) } /* Return TRUE if the microMIPS opcode MO is valid for the delay slot - of the preceding instruction. Always TRUE in the standard MIPS mode. */ + of the preceding instruction. Always TRUE in the standard MIPS mode. + + We don't accept macros in 16-bit delay slots to avoid a case where + a macro expansion fails because it relies on a preceding 32-bit real + instruction to have matched and does not handle the operands correctly. + The only macros that may expand to 16-bit instructions are JAL that + cannot be placed in a delay slot anyway, and corner cases of BALIGN + and BGT (that likewise cannot be placed in a delay slot) that decay to + a NOP. In all these cases the macros precede any corresponding real + instruction definitions in the opcode table, so they will match in the + second pass where the size of the delay slot is ignored and therefore + produce correct code. */ static bfd_boolean is_delay_slot_valid (const struct mips_opcode *mo) @@ -2310,7 +2321,8 @@ is_delay_slot_valid (const struct mips_opcode *mo) return TRUE; if (mo->pinfo == INSN_MACRO) - return TRUE; + return ((history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_16BIT) == 0 + ? TRUE : FALSE); if ((history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT) != 0 && micromips_insn_length (mo) != 4) return FALSE; @@ -5328,7 +5340,8 @@ macro_build_jalr (expressionS *ep, int cprestore) if (mips_opts.micromips) { jalr = mips_opts.noreorder && !cprestore ? "jalr" : "jalrs"; - if (MIPS_JALR_HINT_P (ep)) + if (MIPS_JALR_HINT_P (ep) + || (history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT)) macro_build (NULL, jalr, "t,s", RA, PIC_CALL_REG); else macro_build (NULL, jalr, "mj", PIC_CALL_REG); @@ -7768,7 +7781,9 @@ macro (struct mips_cl_insn *ip) if (mips_pic == NO_PIC) { s = jals ? "jalrs" : "jalr"; - if (mips_opts.micromips && dreg == RA) + if (mips_opts.micromips + && dreg == RA + && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT)) macro_build (NULL, s, "mj", sreg); else macro_build (NULL, s, JALR_FMT, dreg, sreg); @@ -7783,7 +7798,9 @@ macro (struct mips_cl_insn *ip) s = (mips_opts.micromips && (!mips_opts.noreorder || cprestore) ? "jalrs" : "jalr"); - if (mips_opts.micromips && dreg == RA) + if (mips_opts.micromips + && dreg == RA + && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT)) macro_build (NULL, s, "mj", sreg); else macro_build (NULL, s, JALR_FMT, dreg, sreg); |