public inbox for gas2@sourceware.org
 help / color / mirror / Atom feed
* gcc generates invalid i386 fmulp
@ 1998-04-14  0:15 Alan Modra
  1998-04-14  8:19 ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Modra @ 1998-04-14  0:15 UTC (permalink / raw)
  To: gas2, egcs, gcc2

Hello all,
  I've been doing a little work on gas for i386, tidying up a few
things and adding reasonably strict operand/suffix checking.  The new
gas has already found a couple of errors in the linux kernel asm, one
in glibc1, and a problem with gcc.

For anyone who's interested, the gas patches can be found at
ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz
They should apply to binutils-2.9 without problems too.

The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)),
when compiling glibc2 is that gcc will generate instructions like
	`fsubp %st(1),%st'

Now there's no instruction to do %st <- %st - %st(1) and pop, and it
doesn't make sense to pop the result anyway.  Older versions of gas
assemble this instruction to 0xdee9, which does
%st(1) <- %st(1) - %st, pop, ie. `fsubp %st,%st(1)'  (Note!! Because
of the broken UnixWare compatibility requirement for gas, you need to
write `fsubrp %st,%st(1)'  See the comments I put at the top of
binutils/include/opcode/i386.h)


	* config/i386/i386.c (output_387_binary_op): Swap operands
	when popping if the result is st(0), to prevent invalid
	instructions like `fmulp %st(1),%st' and `fsubp %st(1),%st'

--- gcc-2.8.1/config/i386/i386.c	Thu Dec  4 00:31:23 1997
+++ gcc/config/i386/i386.c	Tue Apr 14 00:00:43 1998
@@ -3827,9 +3827,12 @@ output_387_binary_op (insn, operands)
 	  return "";
 	}
 
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
-	return strcat (buf, AS2 (p,%2,%0));
+	if (STACK_TOP_P (operands[0]))
+	  return strcat (buf, AS2 (p,%0,%2));
+	else
+	  return strcat (buf, AS2 (p,%2,%0));
 
       if (STACK_TOP_P (operands[0]))
 	return strcat (buf, AS2C (%y2,%0));
       else
@@ -3858,12 +3861,18 @@ output_387_binary_op (insn, operands)
       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
 	abort ();
 
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
-	return strcat (buf, AS2 (rp,%2,%0));
+	if (STACK_TOP_P (operands[0]))
+	  return strcat (buf, AS2 (p,%0,%2));
+	else
+	  return strcat (buf, AS2 (rp,%2,%0));
 
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
-	return strcat (buf, AS2 (p,%1,%0));
+	if (STACK_TOP_P (operands[0]))
+	  return strcat (buf, AS2 (rp,%0,%1));
+	else
+	  return strcat (buf, AS2 (p,%1,%0));
 
       if (STACK_TOP_P (operands[0]))
 	{
 	  if (STACK_TOP_P (operands[1]))

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14  0:15 gcc generates invalid i386 fmulp Alan Modra
@ 1998-04-14  8:19 ` H.J. Lu
  1998-04-14 16:45   ` Alan Modra
  1998-04-15  7:18   ` Alan Modra
  0 siblings, 2 replies; 10+ messages in thread
From: H.J. Lu @ 1998-04-14  8:19 UTC (permalink / raw)
  To: Alan Modra; +Cc: mikeg, gas2, egcs, gcc2

> 
> Hello all,
>   I've been doing a little work on gas for i386, tidying up a few
> things and adding reasonably strict operand/suffix checking.  The new
> gas has already found a couple of errors in the linux kernel asm, one
> in glibc1, and a problem with gcc.
> 
> For anyone who's interested, the gas patches can be found at
> ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz
> They should apply to binutils-2.9 without problems too.
> 
> The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)),
> when compiling glibc2 is that gcc will generate instructions like
> 	`fsubp %st(1),%st'
> 

Can you show me a small test case please? It is very tricky. Here are
the ChangeLog entries:

Mon Apr 14 14:56:58 1997  Ian Lance Taylor  <ian@cygnus.com>

        * i386.h: Change the opcodes for fsubp, fsubrp, fdivp, and fdivrp       
        with no arguments to match that generated by the UnixWare
        assembler.

Sat Apr  5 13:14:05 1997  Ian Lance Taylor  <ian@cygnus.com>

        * i386.h: Revert last patch for the NON_BROKEN_OPCODES cases.  

Fri Apr  4 14:02:32 1997  Ian Lance Taylor  <ian@cygnus.com>

        * i386.h: Correct opcode values for fsubp, fsubrp, fdivp, and
        fdivrp.

It is very different from Intel and very confusing. But changing it
will break many things.

Thanks.

H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14  8:19 ` H.J. Lu
@ 1998-04-14 16:45   ` Alan Modra
  1998-04-14 20:18     ` Michael L. Galbraith
  1998-04-15  7:18   ` Alan Modra
  1 sibling, 1 reply; 10+ messages in thread
From: Alan Modra @ 1998-04-14 16:45 UTC (permalink / raw)
  To: H.J. Lu; +Cc: mikeg, gas2, egcs, gcc2

>hjl@lucon.org (H.J. Lu):
> > For anyone who's interested, the gas patches can be found at
> > ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz
> > They should apply to binutils-2.9 without problems too.
> > 
> > The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)),
> > when compiling glibc2 is that gcc will generate instructions like
> > 	`fsubp %st(1),%st'
> > 
> 
> Can you show me a small test case please? It is very tricky. Here are
> the ChangeLog entries:
> [deleted]

Yes, I know it's tricky.  Basically, Unixware got their assembler
wrong, and we're stuck with an inconsistent syntax.  A test case for
fmulp is glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c.  I put the
preprocessed file at
ftp://mullet.levels.unisa.edu.au/private/teabag/s_nextafterf.i
Mike Galbraith may be able to give you a .i file for the fsubp case;
I didn't have the right version of glibc.

From the start of binutils/include/opcodes/i386.h:

/* The UnixWare assembler, and possibly other ix86 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
   `fusb %st,%st(3)' results in st(3) <- st - st(3), rather than
   the expected st(3) <- st(3) - st !

   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

> 
> It is very different from Intel and very confusing. But changing it
> will break many things.

I haven't diverged from the UnixWare syntax, even though I'd dearly
like to.  We just put out a warning for the cases where gcc generates
instructions **that won't assemble on UnixWare**.  Ian Taylor was kind
enough to run a number of test cases through a UnixWare assembler for
me.

Regards, Alan Modra

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14 16:45   ` Alan Modra
@ 1998-04-14 20:18     ` Michael L. Galbraith
  1998-04-14 20:30       ` H.J. Lu
  1998-04-14 20:44       ` H.J. Lu
  0 siblings, 2 replies; 10+ messages in thread
From: Michael L. Galbraith @ 1998-04-14 20:18 UTC (permalink / raw)
  To: Alan Modra; +Cc: H.J. Lu, gas2, egcs, gcc2

On Wed, 15 Apr 1998, Alan Modra wrote:

> >hjl@lucon.org (H.J. Lu):
> > > For anyone who's interested, the gas patches can be found at
> > > ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz
> > > They should apply to binutils-2.9 without problems too.
> > > 
> > > The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)),
> > > when compiling glibc2 is that gcc will generate instructions like
> > > 	`fsubp %st(1),%st'
> > > 
> > 
> > Can you show me a small test case please? It is very tricky. Here are
> > the ChangeLog entries:
> > [deleted]
> 
> Yes, I know it's tricky.  Basically, Unixware got their assembler
> wrong, and we're stuck with an inconsistent syntax.  A test case for
> fmulp is glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c.  I put the
> preprocessed file at
> ftp://mullet.levels.unisa.edu.au/private/teabag/s_nextafterf.i
> Mike Galbraith may be able to give you a .i file for the fsubp case;
> I didn't have the right version of glibc.
> 

I can generate a .i file if H.J wants it, but the fsubp %st(1), %st
instances are human generated. (3 .S files)

	-Mike


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14 20:18     ` Michael L. Galbraith
@ 1998-04-14 20:30       ` H.J. Lu
  1998-04-14 21:35         ` Michael L. Galbraith
  1998-04-14 20:44       ` H.J. Lu
  1 sibling, 1 reply; 10+ messages in thread
From: H.J. Lu @ 1998-04-14 20:30 UTC (permalink / raw)
  To: Michael L. Galbraith; +Cc: alan, hjl, gas2, egcs, gcc2

> > 
> 
> I can generate a .i file if H.J wants it, but the fsubp %st(1), %st
> instances are human generated. (3 .S files)
> 

If they are from .S files, it has nothing to do with egcs/gcc. We
need to fix those .S files. But please first get glibc 2.0.7pre3
to see if they are fixed or not.

-- 
H.J. Lu (hjl@gnu.org)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14 20:18     ` Michael L. Galbraith
  1998-04-14 20:30       ` H.J. Lu
@ 1998-04-14 20:44       ` H.J. Lu
  1 sibling, 0 replies; 10+ messages in thread
From: H.J. Lu @ 1998-04-14 20:44 UTC (permalink / raw)
  To: Michael L. Galbraith; +Cc: alan, gas2, egcs, GNU C Library, gcc2

> 
> On Wed, 15 Apr 1998, Alan Modra wrote:
> 
> > >hjl@lucon.org (H.J. Lu):
> > > > For anyone who's interested, the gas patches can be found at
> > > > ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz
> > > > They should apply to binutils-2.9 without problems too.
> > > > 
> > > > The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)),
> > > > when compiling glibc2 is that gcc will generate instructions like
> > > > 	`fsubp %st(1),%st'
> > > > 
> > > 
> > > Can you show me a small test case please? It is very tricky. Here are
> > > the ChangeLog entries:
> > > [deleted]
> > 
> > Yes, I know it's tricky.  Basically, Unixware got their assembler
> > wrong, and we're stuck with an inconsistent syntax.  A test case for
> > fmulp is glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c.  I put the
> > preprocessed file at
> > ftp://mullet.levels.unisa.edu.au/private/teabag/s_nextafterf.i
> > Mike Galbraith may be able to give you a .i file for the fsubp case;
> > I didn't have the right version of glibc.
> > 
> 
> I can generate a .i file if H.J wants it, but the fsubp %st(1), %st
> instances are human generated. (3 .S files)
> 

When you write x86 fp asm code, you have to know what you are doing.
It is very very tricky since the x86 fp asm syntax is very very very
different from Intel and it doesn't make much sense sometimes. But
it is the way how AT&T did it years ago. I don't think it can be easily
fixed. You can use "objdump -d" to check opcode against the Intel
reference manual if you are not familar with the A&T x86 asm syntax.


-- 
H.J. Lu (hjl@gnu.org)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14 20:30       ` H.J. Lu
@ 1998-04-14 21:35         ` Michael L. Galbraith
  0 siblings, 0 replies; 10+ messages in thread
From: Michael L. Galbraith @ 1998-04-14 21:35 UTC (permalink / raw)
  To: H.J. Lu; +Cc: alan, gas2, egcs, gcc2

On Tue, 14 Apr 1998, H.J. Lu wrote:

> > > 
> > 
> > I can generate a .i file if H.J wants it, but the fsubp %st(1), %st
> > instances are human generated. (3 .S files)
> > 
> 
> If they are from .S files, it has nothing to do with egcs/gcc. We
> need to fix those .S files. But please first get glibc 2.0.7pre3
> to see if they are fixed or not.
> 

I've already reported the .S problems.  Unless I'm mistaken, 980319
on ftp.kernel.org is the latest glibc snapshot. (?)

	-Mike


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-14  8:19 ` H.J. Lu
  1998-04-14 16:45   ` Alan Modra
@ 1998-04-15  7:18   ` Alan Modra
  1998-04-15  9:01     ` Robert Lipe
  1 sibling, 1 reply; 10+ messages in thread
From: Alan Modra @ 1998-04-15  7:18 UTC (permalink / raw)
  To: H.J. Lu; +Cc: mikeg, gas2, egcs, gcc2

I fiddled around with the glibc source that generated the invalid
`fmulp %st(1),%st', and came up with the following test case.  It's
not all that small, but reducing the complexity seems to make the
problem go away.

------------------ fop_pop_bug.c ------------------
/*
 * inspired by glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c
 *
 * gcc -O2 -S -DOP=+ gives faddp %st(1),%st
 * gcc -O2 -S -DOP=* gives fmulp %st(1),%st
 * gcc -O2 -S -DOP=- gives fsubrp %st(1),%st
 * gcc -O2 -S -DOP=/ gives fdivrp %st(1),%st
 */

#ifndef OP
#define OP *
#endif

typedef int int32_t __attribute__ ((__mode__ (  __SI__ ))) ;
typedef unsigned int u_int32_t __attribute__ ((__mode__ (  __SI__ ))) ;

typedef union
{
  float value;
  u_int32_t word;
} ieee_float_shape_type;

float __nextafterf(float x, float y)
{
 int32_t hx,hy,ix,iy;

 {
  ieee_float_shape_type gf_u;
  gf_u.value = x;
  hx = gf_u.word;
 }
 {
  ieee_float_shape_type gf_u;
  gf_u.value = y;
  hy = gf_u.word;
 }
 ix = hx&0x7fffffff;
 iy = hy&0x7fffffff;

 if ( ix > 0x7f800000 || iy > 0x7f800000 )
    return x+y;
 if (x == y) return x;
 if (ix == 0)
   {
    {
     ieee_float_shape_type sf_u;
     sf_u.word = (hy&0x80000000) | 1;
     x = sf_u.value;
    }
    y = x*x;
    if (y == x) return y; else return x;
   }
 if (hx >= 0)
   {
    if (hx > hy)
       hx -= 1;
    else
       hx += 1;
   }
 else
   {
    if (hy >= 0 || hx > hy)
       hx -= 1;
    else
       hx += 1;
   }
 hy = hx & 0x7f800000;
 if (hy >= 0x7f800000)
    return x+x;
 if (hy < 0x00800000)
   {
    y = x OP x;
    if (y != x)
      {
       ieee_float_shape_type sf_u;
       sf_u.word = hx;
       y = sf_u.value;
       return y;
      }
   }
 {
  ieee_float_shape_type sf_u;
  sf_u.word = hx;
  x = sf_u.value;
 }
 return x;
}

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-15  7:18   ` Alan Modra
@ 1998-04-15  9:01     ` Robert Lipe
  1998-04-15 10:05       ` Ulrich Drepper
  0 siblings, 1 reply; 10+ messages in thread
From: Robert Lipe @ 1998-04-15  9:01 UTC (permalink / raw)
  To: Alan Modra, H.J. Lu; +Cc: mikeg, gas2, egcs, gcc2

> I fiddled around with the glibc source that generated the invalid
> `fmulp %st(1),%st', and came up with the following test case.  It's
> not all that small, but reducing the complexity seems to make the
> problem go away.

Would anyone like to commit this test case to the testsuite?

It isn't just the Unixware assembler that hurls on the snapshot output
of this.  The OpenServer assemblers (the ELF one is Unixware-derived
since it was licensed from USL, the owner of Unixware at the time, the
COFF one was, I think, developed internally at SCO in the late 80's.)
choke in both COFF and ELF modes.

for m in "-melf " "-mcoff" 
do 
  for o in + - '*' / 
  do 
      ./xgcc $m -B./ -c -O2 -DOP=$o /tmp/am.c 
  done 
done 


/usr/tmp/cca000_7.s:90:invalid operand combination: faddp
/usr/tmp/cca000_B.s:90:invalid operand combination: fsubrp
/usr/tmp/cca000_F.s:90:invalid operand combination: fmulp
/usr/tmp/cca000_J.s:90:invalid operand combination: fdivrp
Assembler: am.c
        aline 89        : Syntax error
Assembler: am.c
        aline 89        : Syntax error
Assembler: am.c
        aline 89        : Syntax error
Assembler: am.c
        aline 89        : Syntax error



> ------------------ fop_pop_bug.c ------------------
> /*
>  * inspired by glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c
>  *
>  * gcc -O2 -S -DOP=+ gives faddp %st(1),%st
>  * gcc -O2 -S -DOP=* gives fmulp %st(1),%st
>  * gcc -O2 -S -DOP=- gives fsubrp %st(1),%st
>  * gcc -O2 -S -DOP=/ gives fdivrp %st(1),%st
>  */
> 
> #ifndef OP
> #define OP *
> #endif
> 
> typedef int int32_t __attribute__ ((__mode__ (  __SI__ ))) ;
> typedef unsigned int u_int32_t __attribute__ ((__mode__ (  __SI__ ))) ;
> 
> typedef union
> {
>   float value;
>   u_int32_t word;
> } ieee_float_shape_type;
> 
> float __nextafterf(float x, float y)
> {
>  int32_t hx,hy,ix,iy;
> 
>  {
>   ieee_float_shape_type gf_u;
>   gf_u.value = x;
>   hx = gf_u.word;
>  }
>  {
>   ieee_float_shape_type gf_u;
>   gf_u.value = y;
>   hy = gf_u.word;
>  }
>  ix = hx&0x7fffffff;
>  iy = hy&0x7fffffff;
> 
>  if ( ix > 0x7f800000 || iy > 0x7f800000 )
>     return x+y;
>  if (x == y) return x;
>  if (ix == 0)
>    {
>     {
>      ieee_float_shape_type sf_u;
>      sf_u.word = (hy&0x80000000) | 1;
>      x = sf_u.value;
>     }
>     y = x*x;
>     if (y == x) return y; else return x;
>    }
>  if (hx >= 0)
>    {
>     if (hx > hy)
>        hx -= 1;
>     else
>        hx += 1;
>    }
>  else
>    {
>     if (hy >= 0 || hx > hy)
>        hx -= 1;
>     else
>        hx += 1;
>    }
>  hy = hx & 0x7f800000;
>  if (hy >= 0x7f800000)
>     return x+x;
>  if (hy < 0x00800000)
>    {
>     y = x OP x;
>     if (y != x)
>       {
>        ieee_float_shape_type sf_u;
>        sf_u.word = hx;
>        y = sf_u.value;
>        return y;
>       }
>    }
>  {
>   ieee_float_shape_type sf_u;
>   sf_u.word = hx;
>   x = sf_u.value;
>  }
>  return x;
> }
> 
> 

-- 
Robert Lipe       http://www.dgii.com/people/robertl       robertl@dgii.com
              (WEB ADDRESS MAY BE TEMPORARILY UNAVAILABLE)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: gcc generates invalid i386 fmulp
  1998-04-15  9:01     ` Robert Lipe
@ 1998-04-15 10:05       ` Ulrich Drepper
  0 siblings, 0 replies; 10+ messages in thread
From: Ulrich Drepper @ 1998-04-15 10:05 UTC (permalink / raw)
  To: Robert Lipe; +Cc: Alan Modra, H.J. Lu, mikeg, gas2, egcs, gcc2

Robert Lipe <robertl@dgii.com> writes:

> Would anyone like to commit this test case to the testsuite?

This is not really necessary if the regular testing of gcc/egcs
finally would include compiling&checking glibc.  Of course we can add
every single file from glibc which exposes a bug to the testsuite but
I think this is pointless.

-- Uli
---------------.      drepper at gnu.org  ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Cygnus Solutions `--' drepper at cygnus.com   `------------------------

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~1998-04-15 10:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-04-14  0:15 gcc generates invalid i386 fmulp Alan Modra
1998-04-14  8:19 ` H.J. Lu
1998-04-14 16:45   ` Alan Modra
1998-04-14 20:18     ` Michael L. Galbraith
1998-04-14 20:30       ` H.J. Lu
1998-04-14 21:35         ` Michael L. Galbraith
1998-04-14 20:44       ` H.J. Lu
1998-04-15  7:18   ` Alan Modra
1998-04-15  9:01     ` Robert Lipe
1998-04-15 10:05       ` Ulrich Drepper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).