GAS problems

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- 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.  */
> /* Set non-zero for broken, compatible instructions.  Set to zero for
>    non-broken opcodes at your peril.  gcc generates UnixWare
>    compatible instructions.  */
> #endif
> 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                   
Casilla 9G, Viña del Mar, Chile                               +56 32 672616

More information about the Binutils mailing list