This is the mail archive of the
mailing list for the binutils project.
Re: [PATC] MIPS16/GAS: Permit branch swapping with PC-relative insns
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: binutils at sourceware dot org, Chao-ying Fu <fu at mips dot com>, Rich Fuhler <rich at mips dot com>, David Lau <davidlau at mips dot com>, Kevin Mills <kevinm at mips dot com>, Ilie Garbacea <ilie at mips dot com>, Catherine Moore <clm at codesourcery dot com>, Nathan Sidwell <nathan at codesourcery dot com>, Joseph Myers <joseph at codesourcery dot com>
- Date: Wed, 10 Aug 2011 23:55:54 +0100 (BST)
- Subject: Re: [PATC] MIPS16/GAS: Permit branch swapping with PC-relative insns
- References: <alpine.DEB.firstname.lastname@example.org> <email@example.com>
On Sat, 6 Aug 2011, Richard Sandiford wrote:
> > While at microMIPS branch swapping, I believe it is safe to swap MIPS16
> > basic instructions that use the PC-relative addressing mode too with a
> > subsequent jump instruction to fill its delay slot. There are four such
> > instructions, namely: ADDIU, DADDIU, LD and LW. There are two arguments
> > standing both at a time that make me think so:
> > 1. The use of any complex expression (one that evaluates to but a plain
> > number) as the immediate argument of any of these instructions causes
> > relaxation to trigger (even if the basic form of the instruction is
> > forced with .set noautoxtend or .t suffix) that marks the instruction
> > fixed and inhibits branch swapping.
> > 2. All these instructions, if placed in a jump delay slot, use the value
> > of the PC of the preceding jump rather than that of the delay slot
> > itself for calculation -- the value of the PC retrieved therefore
> > remains the same after the swap (note that, contrariwise, this is not
> > the case with the microMIPS ADDIUPC instruction).
> I agree the calculated address remains the same. The problem is that
> swapping the instructions would change the contents of that address.
> Of course, it's vanishingly unlikely that anyone would write a
> constant addiupc in a reorder block and follow it with an unfilled
> delayed branch. Perhaps it could even be called user error. But given
> that we have deliberately not swapped until now, changing the behaviour
> for this one case (and for this one case only) would just be a gratutious
> break in backwards compatibility.
> So, not ok. However...
Hmm, I have troubles buying that -- that can be true about any address
calculation that gets swapped into a branch delay slot. And about the
only use of such calculation, requiring the resulting address to point to
the instruction doing it, is to patch it with something else in
self-modifying code, which sounds useless, but let it be that I may be
overlooking something here.
What I do not overlook, and neither you do, is that such code requires a
noreorder block, or otherwise GAS is essentially *by definition* free to
shuffle code around, transform instructions, add NOPs and do all kinds of
weird stuff, so I fail to see why we should be refraining from making this
Have you got any historical records that back up your position and
explain why this statement has originally been placed in? Otherwise I'd
just expect a misunderstanding of how unusually the addition is calculated
-- which would be unsurprising to me, as I've seen similar mistakes
elsewhere, e.g. up until recently (I believe) QEMU used to get the result
of these instructions in delay slots wrong -- hopefully this piece of GAS
code is not a workaround for that!
> > While at it I have adjusted a comment about MIPS16 mode fixups that I
> > believe is no longer accurate -- these days we support MIPS16 mode
> > relocations on instructions other than branches (hmm, was it jumps that
> > were meant here instead? -- or relaxed branches that are otherwise fixed
> > as noted above anyway?) too (but then they are extended instructions).
> ...I agree this comment needs a bit of TLC.
> > @@ -3679,8 +3679,8 @@ can_swap_branch_p (struct mips_cl_insn *
> > return FALSE;
> > /* If the previous instruction had a fixup in mips16 mode, we can not
> > - swap. This normally means that the previous instruction was a 4
> > - byte branch anyhow. */
> > + swap. This normally means that the previous instruction was
> > + a 4-byte extended instruction anyhow. */
> > if (mips_opts.mips16 && history.fixp)
> > return FALSE;
> It always means that the previous instruction was a 4-byte instruction.
> I'm not sure adding "extended" is a good idea though, since JAL can have
> a fixup but doesn't use EXTEND.
Indeed, it's a notable exception (as is JALX).
> A patch that changes the comment to:
> /* If the previous instruction had a fixup in mips16 mode, we can not swap.
> This means that the previous instruction was a 4-byte one anyhow. */
> (and does nothing else) is OK.
2011-08-10 Maciej W. Rozycki <firstname.lastname@example.org>
* config/tc-mips.c (can_swap_branch_p): Update the comment on
--- binutils-fsf-trunk-quilt.orig/gas/config/tc-mips.c 2011-08-10 22:42:21.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/config/tc-mips.c 2011-08-10 22:52:20.000000000 +0100
@@ -3715,9 +3715,8 @@ can_swap_branch_p (struct mips_cl_insn *
- /* If the previous instruction had a fixup in mips16 mode, we can not
- swap. This normally means that the previous instruction was a 4
- byte branch anyhow. */
+ /* If the previous instruction had a fixup in mips16 mode, we can not swap.
+ This means that the previous instruction was a 4-byte one anyhow. */
if (mips_opts.mips16 && history.fixp)