Horst von Brand
Mon Oct 18 16:24:00 GMT 1999
Alan Modra <alan@SPRI.Levels.UniSA.Edu.Au> said:
> On Sun, 17 Oct 1999, Horst von Brand wrote:
> > The lcc C compiler on ia32 generates "fxxxp %st(1),%st" instructions to
> > handle floating point operations. This is handled wrong by H.J.Lu's
> > binutils-22.214.171.124.16. Note that now it translates "fsubp %st(1),%st" into
> > "fsubp %st,%st(1)", which does something very different. Also, the
> > instructions are legal AFAIK (they used to work before), so either no
> > warning is needed or you could use f.ex. "fsubrp %st,%st(1)" if there is a
> > penalty of some sort. In any case, I would prefer you left them alone.
> These floating point operations are a real pain, but in this case lcc is
> doing something wrong. There is no such x86 instruction. What should
> "fsubp %st(1),%st" do? I'd imagine it should do st <- st - st(1), then
> pop off the result, which is a bit silly.
No, it would do st(0) - st(1), pop both and push the result. Note that this
is _not_ st(1) - st(0).
> Note that older binutils
> silently did the same translation we now do (and older gcc emitted this
> wrong instruction too)
They did not: lcc used to work.
> FYI, here's a comment I added to binutils/include/opcode/i386.h, just to
> make you aware of a horrible kludge.
> /* The UnixWare assembler, and probably other AT&T derived ix86 Unix
> assemblers, generate floating point instructions with reversed
> source and destination registers in certain cases. Unfortunately,
> gcc and possibly many other programs use this reversed syntax, so
> we're stuck with it.
> eg. `fsub %st(3),%st' results in st <- st - st(3) as expected, but
> `fsub %st,%st(3)' results in st(3) <- st - st(3), rather than
> the expected st(3) <- st(3) - st !
This is _not_ expected behaviour! It gets the operation backwards. If you
do that, use fsubr in the "translation".
> This happens with all the non-commutative arithmetic floating point
> operations with two register operands, where the source register is
> %st, and destination register is %st(i). Look for FloatDR below. */
> #ifndef UNIXWARE_COMPAT
> /* Set non-zero for broken, compatible instructions. Set to zero for
> non-broken opcodes at your peril. gcc generates UnixWare
> compatible instructions. */
> #define UNIXWARE_COMPAT 1
> I would love to get rid of this stupidity, but that needs a
> synchronised update of both gcc and binutils.
Strange. gcc and lcc used to work for me. Any specific testcase that shows
gcc generating garbage?
Horst von Brand firstname.lastname@example.org
Casilla 9G, ViÃÂ±a del Mar, Chile +56 32 672616
More information about the Binutils