public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Re: GAS problems
       [not found] <199910171436.LAA01757@sleipnir.valparaiso.cl>
@ 1999-10-17 20:46 ` Alan Modra
  1999-10-18 16:24   ` Horst von Brand
  0 siblings, 1 reply; 7+ messages in thread
From: Alan Modra @ 1999-10-17 20:46 UTC (permalink / raw)
  To: Horst von Brand; +Cc: binutils

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.  Note that older binutils
silently did the same translation we now do (and older gcc emitted this
wrong instruction too)

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 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.

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

* Re: GAS problems
  1999-10-17 20:46 ` GAS problems Alan Modra
@ 1999-10-18 16:24   ` Horst von Brand
  1999-10-18 21:31     ` Alan Modra
  0 siblings, 1 reply; 7+ messages in thread
From: Horst von Brand @ 1999-10-18 16:24 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2742 bytes --]

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

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

* Re: GAS problems
  1999-10-18 16:24   ` Horst von Brand
@ 1999-10-18 21:31     ` Alan Modra
  0 siblings, 0 replies; 7+ messages in thread
From: Alan Modra @ 1999-10-18 21:31 UTC (permalink / raw)
  To: Horst von Brand; +Cc: binutils

On Mon, 18 Oct 1999, Horst von Brand wrote:

> 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).

Well, your imagination is better than mine :-)  Regardless of what we
think the instruction should do, there is no such x86 instruction.  Check
the intel manuals.

> >                                           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.

Can I have a testcase, with lcc's generated asm file?

> > 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".

Are you saying that `fsub %st,%st(3)' should result in st(3) <- st-st(3) ?
That's different to every other subtract instruction.  Consider
subl `%eax,%ebx' and `subl %ebx,%eax'.  In general `op l,r' => r <- r op l
at least in AT&T syntax.

Ian Taylor and I checked gas behaviour vs Unixware fairly exhaustively
back in Jun 1998, when this was all tidied up.

> >    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?

Attached.  Use a fairly old gcc (2.7.2 ?) to show the problem.

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

* Re: Gas Problems
  2002-04-11  3:21 ` Alan Modra
  2002-04-11  3:50   ` Alan Modra
@ 2002-04-11  4:57   ` Alan Modra
  1 sibling, 0 replies; 7+ messages in thread
From: Alan Modra @ 2002-04-11  4:57 UTC (permalink / raw)
  To: Randall Hyde, binutils

On Thu, Apr 11, 2002 at 07:51:07PM +0930, Alan Modra wrote:
> 	* i386.h: Add intel mode cmpsd and movsd.

Hum, now I need another tweak to get "rep movsd" working.

movq.s: Assembler messages:
movq.s:3: Error: expecting string instruction after `rep'

	* i386.h: Add intel mode cmpsd and movsd.
	Put them before SSE2 insns, so that rep prefix works.

Index: include/opcode/i386.h
===================================================================
RCS file: /cvs/src/src/include/opcode/i386.h,v
retrieving revision 1.37
diff -u -p -r1.37 i386.h
--- include/opcode/i386.h	11 Apr 2002 10:21:58 -0000	1.37
+++ include/opcode/i386.h	11 Apr 2002 11:52:12 -0000
@@ -1231,10 +1231,10 @@ static const template i386_optab[] = {
 {"cmpunordpd",2, 0x660fc2,  3, CpuSSE2, FP|Modrm|ImmExt,{ RegXMM|LLongMem, RegXMM, 0 } },
 {"cmpunordsd",2, 0xf20fc2,  3, CpuSSE2, FP|Modrm|ImmExt,{ RegXMM|LongMem, RegXMM, 0 } },
 {"cmppd",     3, 0x660fc2,  X, CpuSSE2, FP|Modrm,	{ Imm8, RegXMM|LLongMem, RegXMM } },
-{"cmpsd",     3, 0xf20fc2,  X, CpuSSE2, FP|Modrm,	{ Imm8, RegXMM|LongMem, RegXMM } },
 /* Intel mode string compare.  */
 {"cmpsd",     0, 0xa7,      X, 0, NoSuf|Size32|IsString, { 0, 0, 0} },
 {"cmpsd",     2, 0xa7,      X, 0, NoSuf|Size32|IsString, { AnyMem, AnyMem|EsSeg, 0} },
+{"cmpsd",     3, 0xf20fc2,  X, CpuSSE2, FP|Modrm,	{ Imm8, RegXMM|LongMem, RegXMM } },
 {"comisd",    2, 0x660f2f,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LongMem, RegXMM, 0 } },
 {"cvtpi2pd",  2, 0x660f2a,  X, CpuSSE2, FP|Modrm,	{ RegMMX|LLongMem, RegXMM, 0 } },
 {"cvtsi2sd",  2, 0xf20f2a,  X, CpuSSE2, lq_Suf|IgnoreSize|Modrm,{ Reg32|Reg64|WordMem|LLongMem, RegXMM, 0 } },
@@ -1252,11 +1252,11 @@ static const template i386_optab[] = {
 {"movlpd",    2, 0x660f13,  X, CpuSSE2, FP|Modrm,	{ RegXMM, LLongMem, 0 } },
 {"movmskpd",  2, 0x660f50,  X, CpuSSE2, lq_Suf|IgnoreSize|Modrm, { RegXMM|InvMem, Reg32|Reg64, 0 } },
 {"movntpd",   2, 0x660f2b,  X, CpuSSE2, FP|Modrm, 	{ RegXMM, LLongMem, 0 } },
-{"movsd",     2, 0xf20f10,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LongMem, RegXMM, 0 } },
-{"movsd",     2, 0xf20f11,  X, CpuSSE2, FP|Modrm,	{ RegXMM, RegXMM|LongMem, 0 } },
 /* Intel mode string move.  */
 {"movsd",     0, 0xa5,      X, 0, NoSuf|Size32|IsString, { 0, 0, 0} },
 {"movsd",     2, 0xa5,      X, 0, NoSuf|Size32|IsString, { AnyMem, AnyMem|EsSeg, 0} },
+{"movsd",     2, 0xf20f10,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LongMem, RegXMM, 0 } },
+{"movsd",     2, 0xf20f11,  X, CpuSSE2, FP|Modrm,	{ RegXMM, RegXMM|LongMem, 0 } },
 {"movupd",    2, 0x660f10,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LLongMem, RegXMM, 0 } },
 {"movupd",    2, 0x660f11,  X, CpuSSE2, FP|Modrm,	{ RegXMM, RegXMM|LLongMem, 0 } },
 {"mulpd",     2, 0x660f59,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LLongMem, RegXMM, 0 } },

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Re: Gas Problems
  2002-04-11  3:21 ` Alan Modra
@ 2002-04-11  3:50   ` Alan Modra
  2002-04-11  4:57   ` Alan Modra
  1 sibling, 0 replies; 7+ messages in thread
From: Alan Modra @ 2002-04-11  3:50 UTC (permalink / raw)
  To: binutils, Jan Hubicka, Andreas Jaeger

On Thu, Apr 11, 2002 at 07:51:07PM +0930, Alan Modra wrote:
> 
> These regressions were introduced with x86_64 support.  I think the
> tc-i386.c:process_suffix patch will fix the problem, but I'd like an
> OK from the x86_64 maintainers.  Frankly, I'd rather have broken
> intel mode support, especially as you can just leave off the
> "qword ptr", rather than having broken x86_64 linux support.
> 
> 	* config/tc-i386.c (process_suffix): Ignore QWORD_MNEM_SUFFIX if
> 	IgnoreSize.

FAIL: x86-64 opcode

Forget that idea..

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Re: Gas Problems
  2002-02-19 16:06 Gas Problems Randall Hyde
@ 2002-04-11  3:21 ` Alan Modra
  2002-04-11  3:50   ` Alan Modra
  2002-04-11  4:57   ` Alan Modra
  0 siblings, 2 replies; 7+ messages in thread
From: Alan Modra @ 2002-04-11  3:21 UTC (permalink / raw)
  To: Randall Hyde; +Cc: binutils, Jan Hubicka, Andreas Jaeger

On Tue, Feb 19, 2002 at 03:27:26PM -0800, Randall Hyde wrote:
> 
> Here are some problems I've found:
> 
> (1) statements like the following get rejected:
> fstp float ptr [eax]
> fstp double ptr [eax]
> fstp tfloat ptr [eax]
> 
> By trial and error I've found appropriate AT&T suffix
> that work, but they are inconsistent, especially on the
> integer FP instructions.

I'm going to leave this problem for someone more familiar with masm
syntax of the modern variety.  My experience with masm dates back to
the early 1980s, so I'm just a little bit out of date.  ;-)

> (2) movq and other MMX ilk that support 64-bit operands
> don't allow "qword ptr" ("must have a 64-bit architecture"
> or some-such error results).

These regressions were introduced with x86_64 support.  I think the
tc-i386.c:process_suffix patch will fix the problem, but I'd like an
OK from the x86_64 maintainers.  Frankly, I'd rather have broken
intel mode support, especially as you can just leave off the
"qword ptr", rather than having broken x86_64 linux support.

	* config/tc-i386.c (process_suffix): Ignore QWORD_MNEM_SUFFIX if
	IgnoreSize.

Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.115
diff -u -p -r1.115 tc-i386.c
--- gas/config/tc-i386.c	10 Apr 2002 13:00:02 -0000	1.115
+++ gas/config/tc-i386.c	11 Apr 2002 10:04:44 -0000
@@ -2253,7 +2253,7 @@ process_suffix ()
 
       /* Set mode64 for an operand.  */
       if (i.suffix == QWORD_MNEM_SUFFIX
-	  && (i.tm.opcode_modifier & NoRex64) == 0)
+	  && (i.tm.opcode_modifier & (NoRex64 | IgnoreSize)) == 0)
 	{
 	  i.rex |= REX_MODE64;
 	  if (flag_code < CODE_64BIT)

> CMPSD and MOVSD don't assemble (the other string
> instructions are fine).

These were broken with SSE2 support, when SSE2 instructions with the
same names were added.  I'm committing the following to fix this.

	* i386.h: Add intel mode cmpsd and movsd.

Index: include/opcode/i386.h
===================================================================
RCS file: /cvs/src/src/include/opcode/i386.h,v
retrieving revision 1.36
diff -u -p -r1.36 i386.h
--- include/opcode/i386.h	18 Feb 2002 16:32:25 -0000	1.36
+++ include/opcode/i386.h	11 Apr 2002 10:04:39 -0000
@@ -1232,6 +1232,9 @@ static const template i386_optab[] = {
 {"cmpunordsd",2, 0xf20fc2,  3, CpuSSE2, FP|Modrm|ImmExt,{ RegXMM|LongMem, RegXMM, 0 } },
 {"cmppd",     3, 0x660fc2,  X, CpuSSE2, FP|Modrm,	{ Imm8, RegXMM|LLongMem, RegXMM } },
 {"cmpsd",     3, 0xf20fc2,  X, CpuSSE2, FP|Modrm,	{ Imm8, RegXMM|LongMem, RegXMM } },
+/* Intel mode string compare.  */
+{"cmpsd",     0, 0xa7,      X, 0, NoSuf|Size32|IsString, { 0, 0, 0} },
+{"cmpsd",     2, 0xa7,      X, 0, NoSuf|Size32|IsString, { AnyMem, AnyMem|EsSeg, 0} },
 {"comisd",    2, 0x660f2f,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LongMem, RegXMM, 0 } },
 {"cvtpi2pd",  2, 0x660f2a,  X, CpuSSE2, FP|Modrm,	{ RegMMX|LLongMem, RegXMM, 0 } },
 {"cvtsi2sd",  2, 0xf20f2a,  X, CpuSSE2, lq_Suf|IgnoreSize|Modrm,{ Reg32|Reg64|WordMem|LLongMem, RegXMM, 0 } },
@@ -1251,6 +1254,9 @@ static const template i386_optab[] = {
 {"movntpd",   2, 0x660f2b,  X, CpuSSE2, FP|Modrm, 	{ RegXMM, LLongMem, 0 } },
 {"movsd",     2, 0xf20f10,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LongMem, RegXMM, 0 } },
 {"movsd",     2, 0xf20f11,  X, CpuSSE2, FP|Modrm,	{ RegXMM, RegXMM|LongMem, 0 } },
+/* Intel mode string move.  */
+{"movsd",     0, 0xa5,      X, 0, NoSuf|Size32|IsString, { 0, 0, 0} },
+{"movsd",     2, 0xa5,      X, 0, NoSuf|Size32|IsString, { AnyMem, AnyMem|EsSeg, 0} },
 {"movupd",    2, 0x660f10,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LLongMem, RegXMM, 0 } },
 {"movupd",    2, 0x660f11,  X, CpuSSE2, FP|Modrm,	{ RegXMM, RegXMM|LLongMem, 0 } },
 {"mulpd",     2, 0x660f59,  X, CpuSSE2, FP|Modrm,	{ RegXMM|LLongMem, RegXMM, 0 } },

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Gas Problems
@ 2002-02-19 16:06 Randall Hyde
  2002-04-11  3:21 ` Alan Modra
  0 siblings, 1 reply; 7+ messages in thread
From: Randall Hyde @ 2002-02-19 16:06 UTC (permalink / raw)
  To: binutils

Hi, I'm having problems with Gas as
follows:

Note: I'm using .intel_syntax in Gas to process the
output of a compiler I've written (which emits MASM
code, porting it to AT&T syntax is too much of a headache).

Here are some problems I've found:

(1) statements like the following get rejected:
fstp float ptr [eax]
fstp double ptr [eax]
fstp tfloat ptr [eax]

By trial and error I've found appropriate AT&T suffix
that work, but they are inconsistent, especially on the
integer FP instructions.

(2) movq and other MMX ilk that support 64-bit operands
don't allow "qword ptr" ("must have a 64-bit architecture"
or some-such error results).

CMPSD and MOVSD don't assemble (the other string
instructions are fine).


Hope this helps,
Randy Hyde





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

end of thread, other threads:[~2002-04-11 11:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <199910171436.LAA01757@sleipnir.valparaiso.cl>
1999-10-17 20:46 ` GAS problems Alan Modra
1999-10-18 16:24   ` Horst von Brand
1999-10-18 21:31     ` Alan Modra
2002-02-19 16:06 Gas Problems Randall Hyde
2002-04-11  3:21 ` Alan Modra
2002-04-11  3:50   ` Alan Modra
2002-04-11  4:57   ` Alan Modra

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).