GAS problems

Horst von Brand vonbrand@sleipnir.valparaiso.cl
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-2.9.5.0.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
> #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                             vonbrand@sleipnir.valparaiso.cl
Casilla 9G, Viña del Mar, Chile                               +56 32 672616



More information about the Binutils mailing list