This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: Display "xchg %ax,%ax" and "xchg %rax,%rax"


On Fri, Jun 09, 2006 at 12:27:39PM -0700, H. J. Lu wrote:
> On Fri, Jun 09, 2006 at 09:48:23AM +0200, Jan Beulich wrote:
> > >+  else if (prefixes == PREFIX_DATA)
> > >+    {
> > >+      /* We display "xchg %ax,%ax" instead of "data16 nop".  */
> > >+      prefixes = 0;
> > >+      if (intel_syntax)
> > >+	strcpy (obuf, "xchg   ax,ax");
> > >+      else
> > >+	strcpy (obuf, "xchg   %ax,%ax");
> > >+    }
> > 
> > This is wrong in 16-bit mode. It might be better to call appropriate functions than to use hard-coded strings here.
> > 
> > +  else if (rex == 0x48)
> > +    {
> > +      /* We display "xchg %rax,%rax" instead of "rex64 nop".  */
> > +      rex = 0;
> > +      if (intel_syntax)
> > +	strcpy (obuf, "xchg   rax,rax");
> > +      else
> > +	strcpy (obuf, "xchg   %rax,%rax");
> > +    }
> > 
> > This doesn't account for the rex bits that are ignored by this instruction. You should consume only rex.w here.
> 
> 
> Here is the updated patch. It also fixes "xchg %rax,%r8".
> 

There is another bug. 64bit NOP is "xchg %rax,%rax". This patch
optimizes "xchg %rax,%rax" as NOP and removes the erroneous comments.


H.J.
----
gas/

2006-06-09  H.J. Lu  <hongjiu.lu@intel.com>

	* config/tc-i386.c (process_suffix): Don't add rex64 for
	"xchg %rax,%rax".

gas/testsuite/

2006-06-09  H.J. Lu  <hongjiu.lu@intel.com>

	* gas/i386/opcode.s: Add "xchg %ax,%ax".
	* gas/i386/opcode.d: Updated.

	* gas/i386/x86-64-opcode.s: Add xchg %ax,%ax, xchg %eax,%eax,
	xchg %rax,%rax, rex64 xchg %rax,%rax and xchg %rax,%r8.
	* gas/i386/x86-64-opcode.d: Updated.

include/opcode/

2006-06-09  H.J. Lu  <hongjiu.lu@intel.com>

	* i386.h (i386_optab): Update comment for 64bit NOP.

opcodes/

2006-06-09  H.J. Lu  <hongjiu.lu@intel.com>

	* i386-dis.c (NOP_Fixup): Removed.
	(NOP_Fixup1): New.
	(NOP_Fixup2): Likewise.
	(dis386): Use NOP_Fixup1 and NOP_Fixup2 on 0x90.

--- binutils/gas/config/tc-i386.c.xchg	2006-05-19 06:31:21.000000000 -0700
+++ binutils/gas/config/tc-i386.c	2006-06-09 13:48:27.000000000 -0700
@@ -2615,7 +2615,15 @@ process_suffix (void)
       if (i.suffix == QWORD_MNEM_SUFFIX
 	  && flag_code == CODE_64BIT
 	  && (i.tm.opcode_modifier & NoRex64) == 0)
-	i.rex |= REX_MODE64;
+	{
+	  /* Special case for xchg %rax,%rax.  It is NOP and doesn't
+	     need rex64.  */
+	  if (i.operands != 2
+	      || i.types [0] != (Acc | Reg64)
+	      || i.types [1] != (Acc | Reg64)
+	      || strcmp (i.tm.name, "xchg") != 0)
+	  i.rex |= REX_MODE64;
+	}
 
       /* Size floating point instruction.  */
       if (i.suffix == LONG_MNEM_SUFFIX)
--- binutils/gas/testsuite/gas/i386/opcode.d.xchg	2005-03-29 12:09:20.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/opcode.d	2006-06-09 12:06:15.000000000 -0700
@@ -572,4 +572,5 @@ Disassembly of section .text:
  9b7:	66 0f bd 90 90 90 90 90 [ 	]*bsr    0x90909090\(%eax\),%dx
  9bf:	66 0f be 90 90 90 90 90 [ 	]*movsbw 0x90909090\(%eax\),%dx
  9c7:	66 0f c1 90 90 90 90 90 [ 	]*xadd   %dx,0x90909090\(%eax\)
+ 9cf:	66 90 [ 	]*xchg   %ax,%ax
 	\.\.\.
--- binutils/gas/testsuite/gas/i386/opcode.s.xchg	2005-03-29 12:09:20.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/opcode.s	2006-06-08 23:27:00.000000000 -0700
@@ -566,5 +566,7 @@ foo:
  movsbw 0x90909090(%eax),%dx
  xadd   %dx,0x90909090(%eax)
 
+ xchg   %ax,%ax
+
 # Force a good alignment.
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.d.xchg	2005-03-29 12:09:20.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.d	2006-06-09 13:45:23.000000000 -0700
@@ -266,6 +266,9 @@ Disassembly of section .text:
 [	 ]*[0-9a-f]+:[	 ]+e6 00[	 ]+out[	 ]+%al,\$0[x0]*[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+66 e7 00[	 ]+out[	 ]+%ax,\$0[x0]*[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+e7 00[	 ]+out[	 ]+%eax,\$0[x0]*[	 ]*(#.*)*
-[	 ]*[0-9a-f]+:[	 ]+00 00[	 ]+.*
-[	 ]*[0-9a-f]+:[	 ]+00 00[	 ]+.*
-[	 *]...
+[	 ]*[0-9a-f]+:[	 ]+66 90[	 ]+xchg[	 ]+%ax,%ax[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+87 c0[	 ]+xchg[	 ]+%eax,%eax[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+90[	 ]+nop[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+48 90[	 ]+rex64 nop[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+49 90[	 ]+xchg[	 ]+%rax,%r8[	 ]*(#.*)*
+#pass
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.s.xchg	2005-03-29 12:09:20.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.s	2006-06-09 13:45:02.000000000 -0700
@@ -387,4 +387,12 @@
 
 	# IN
 
+
+
+	xchg %ax,%ax		      # 66  --	 -- --	 90
+	xchg %eax,%eax		      # --  --	 -- --	 87 C0
+	xchg %rax,%rax		      # --  --	 -- --	 90
+	rex64 xchg %rax,%rax	      # 48  --	 -- --	 90
+	xchg %rax,%r8		      # --  --	 -- 49	 90
+
  .p2align 4,0
--- binutils/include/opcode/i386.h.xchg	2006-02-27 15:50:54.000000000 -0800
+++ binutils/include/opcode/i386.h	2006-06-09 13:29:04.000000000 -0700
@@ -179,19 +179,11 @@ static const template i386_optab[] =
 /* Exchange instructions.
    xchg commutes  we allow both operand orders.
  
-   In the 64bit code, xchg eax, eax is reused for new nop instruction.  */
-#if 0 /* While the two entries that are disabled generate shorter code
-         for xchg eax, reg (on x86_64), the special case xchg eax, eax
-         does not get handled correctly - it degenerates into nop, but
-         that way the side effect of zero-extending eax to rax is lost.  */
-{"xchg",   2,	0x90, X, 0,	 wlq_Suf|ShortForm,	{ WordReg, Acc, 0 } },
-{"xchg",   2,	0x90, X, 0,	 wlq_Suf|ShortForm,	{ Acc, WordReg, 0 } },
-#else
+   In the 64bit code, xchg rax, rax is reused for new nop instruction.  */
 {"xchg",   2,	0x90, X, CpuNo64, wl_Suf|ShortForm,	{ WordReg, Acc, 0 } },
 {"xchg",   2,	0x90, X, CpuNo64, wl_Suf|ShortForm,	{ Acc, WordReg, 0 } },
 {"xchg",   2,	0x90, X, Cpu64, wq_Suf|ShortForm,	{ Reg16|Reg64, Acc, 0 } },
 {"xchg",   2,	0x90, X, Cpu64, wq_Suf|ShortForm,	{ Acc, Reg16|Reg64, 0 } },
-#endif
 {"xchg",   2,	0x86, X, 0,	 bwlq_Suf|W|Modrm,	{ Reg, Reg|AnyMem, 0 } },
 {"xchg",   2,	0x86, X, 0,	 bwlq_Suf|W|Modrm,	{ Reg|AnyMem, Reg, 0 } },
 
--- binutils/opcodes/i386-dis.c.xchg	2006-05-11 08:52:55.000000000 -0700
+++ binutils/opcodes/i386-dis.c	2006-06-09 13:13:49.000000000 -0700
@@ -91,7 +91,8 @@ static void OP_M (int, int);
 static void OP_VMX (int, int);
 static void OP_0fae (int, int);
 static void OP_0f07 (int, int);
-static void NOP_Fixup (int, int);
+static void NOP_Fixup1 (int, int);
+static void NOP_Fixup2 (int, int);
 static void OP_3DNowSuffix (int, int);
 static void OP_SIMD_Suffix (int, int);
 static void SIMD_Fixup (int, int);
@@ -679,7 +680,7 @@ static const struct dis386 dis386[] = {
   { "movQ",		Sw, Sv, XX },
   { "popU",		stackEv, XX, XX },
   /* 90 */
-  { "nop",		NOP_Fixup, 0, XX, XX },
+  { "xchgS",		NOP_Fixup1, eAX_reg, NOP_Fixup2, eAX_reg, XX },
   { "xchgS",		RMeCX, eAX, XX },
   { "xchgS",		RMeDX, eAX, XX },
   { "xchgS",		RMeBX, eAX, XX },
@@ -4360,12 +4361,29 @@ OP_0fae (int bytemode, int sizeflag)
   OP_E (bytemode, sizeflag);
 }
 
+/* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
+   32bit mode and "xchg %rax,%rax" in 64bit mode.  NOP with REPZ prefix
+   is called PAUSE.  We display "xchg %ax,%ax" instead of "data16 nop".
+ */
+
 static void
-NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+NOP_Fixup1 (int bytemode, int sizeflag)
 {
-  /* NOP with REPZ prefix is called PAUSE.  */
   if (prefixes == PREFIX_REPZ)
     strcpy (obuf, "pause");
+  else if (prefixes == PREFIX_DATA
+	   || ((rex & REX_MODE64) && rex != 0x48))
+    OP_REG (bytemode, sizeflag);
+  else
+    strcpy (obuf, "nop");
+}
+
+static void
+NOP_Fixup2 (int bytemode, int sizeflag)
+{
+  if (prefixes == PREFIX_DATA
+      || ((rex & REX_MODE64) && rex != 0x48))
+    OP_IMREG (bytemode, sizeflag);
 }
 
 static const char *const Suffix3DNow[] = {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]