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]

PATCH: PR binutils/4218: objdump on AMD64 fails to decode prefixed 0x90 opcode properly.


The assembler doesn't use the shorter 0x90 opcode for xchg in 64bit
mode and the disassembler fails to proper decode the REX byte before
0x90. Also nop (0f 1f) takes both register and memory operand.

This patch fixes those.

H.J.
-----
gas/

2003-03-21  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/4218
	* config/tc-i386.c (match_template): Properly handle 64bit mode
	"xchg %eax, %eax".

gas/testsuite/

2003-03-21  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/4218
	* gas/i386/nops.s: Add testcases for nop r/m.
	* gas/i386/x86-64-nops.s: Likewise.

	* gas/i386/x86-64-opcode.s: Add testcases for xchg with %ax,
	%eax and %rax.

	* gas/i386/nops.d: Updated.
	* gas/i386/x86-64-nops.d: Likewise.
	* gas/i386/x86-64-opcode.d: Likewise.

opcodes/

2003-03-21  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/4218
	* i386-dis.c (PREGRP38): New.
	(dis386): Use PREGRP38 for 0x90.
	(prefix_user_table): Add PREGRP38.
	(print_insn): Set uses_REPZ_prefix to 1 for pause.
	(NOP_Fixup1): Properly handle REX bits.
	(NOP_Fixup2): Likewise.

	* i386-opc.c (i386_optab): Allow %eax with xchg in 64bit.
	Allow register with nop.

--- binutils/gas/config/tc-i386.c.nop	2007-03-21 08:53:36.000000000 -0700
+++ binutils/gas/config/tc-i386.c	2007-03-21 10:45:27.000000000 -0700
@@ -2621,6 +2621,15 @@ match_template (void)
 	    continue;
 	  break;
 	case 2:
+	  /* xchg %eax, %eax is a special case. It is an aliase for nop
+	     only in 32bit mode and we can use opcode 0x90.  In 64bit
+	     mode, we can't use 0x90 for xchg %eax, %eax since it should
+	     zero-extend %eax to %rax.  */
+	  if (flag_code == CODE_64BIT
+	      && t->base_opcode == 0x90
+	      && i.types [0] == (Acc | Reg32)
+	      && i.types [1] == (Acc | Reg32))
+	    continue;
 	case 3:
 	case 4:
 	  overlap1 = i.types[1] & operand_types[1];
--- binutils/gas/testsuite/gas/i386/nops.d.nop	2006-06-12 11:59:35.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/nops.d	2007-03-21 09:16:58.000000000 -0700
@@ -14,4 +14,11 @@ Disassembly of section .text:
 [	 ]*19:[	 ]+0f 1f 84 00 00 00 00 00[	 ]+nopl[ 	]+0x0\(%eax,%eax,1\)
 [	 ]*21:[	 ]+66 0f 1f 84 00 00 00 00 00[	 ]+nopw[ 	]+0x0\(%eax,%eax,1\)
 [	 ]*2a:[	 ]+66 2e 0f 1f 84 00 00 00 00 00[	 ]+nopw[ 	]+%cs:0x0\(%eax,%eax,1\)
+[	 ]*34:[	 ]+0f 1f 00[	 ]+nopl[ 	]+\(%eax\)
+[	 ]*37:[	 ]+0f 1f c0[	 ]+nop[ 	]+%eax
+[	 ]*3a:[	 ]+66 0f 1f c0[	 ]+nop[ 	]+%ax
+[	 ]*3e:[	 ]+0f 1f 00[	 ]+nopl[ 	]+\(%eax\)
+[	 ]*41:[	 ]+66 0f 1f 00[	 ]+nopw[ 	]+\(%eax\)
+[	 ]*45:[	 ]+0f 1f c0[	 ]+nop[ 	]+%eax
+[	 ]*48:[	 ]+66 0f 1f c0[	 ]+nop[ 	]+%ax
 #pass
--- binutils/gas/testsuite/gas/i386/nops.s.nop	2006-06-12 11:59:35.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/nops.s	2007-03-21 09:10:52.000000000 -0700
@@ -9,4 +9,12 @@
 	.byte 0x66, 0x0f, 0x1f, 0x84, 0x0,  0x0, 0x0, 0x0, 0x0
 	.byte 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0
 
+	nop (%eax) 
+	nop %eax
+	nop %ax
+	nopl (%eax) 
+	nopw (%eax) 
+	nopl %eax
+	nopw %ax
+
 	.p2align 4
--- binutils/gas/testsuite/gas/i386/x86-64-nops.d.nop	2006-06-12 11:59:35.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-nops.d	2007-03-21 11:31:17.000000000 -0700
@@ -14,4 +14,24 @@ Disassembly of section .text:
 [	 ]*19:[	 ]+0f 1f 84 00 00 00 00 00[	 ]+nopl[ 	]+0x0\(%rax,%rax,1\)
 [	 ]*21:[	 ]+66 0f 1f 84 00 00 00 00 00[	 ]+nopw[ 	]+0x0\(%rax,%rax,1\)
 [	 ]*2a:[	 ]+66 2e 0f 1f 84 00 00 00 00 00[	 ]+nopw[ 	]+%cs:0x0\(%rax,%rax,1\)
+[	 ]*34:[	 ]+0f 1f 00[	 ]+nopl[ 	]+\(%rax\)
+[	 ]*37:[	 ]+48 0f 1f c0[	 ]+nop[ 	]+%rax
+[	 ]*3b:[	 ]+0f 1f c0[	 ]+nop[ 	]+%eax
+[	 ]*3e:[	 ]+66 0f 1f c0[	 ]+nop[ 	]+%ax
+[	 ]*42:[	 ]+48 0f 1f 00[	 ]+nopq[ 	]+\(%rax\)
+[	 ]*46:[	 ]+0f 1f 00[	 ]+nopl[ 	]+\(%rax\)
+[	 ]*49:[	 ]+66 0f 1f 00[	 ]+nopw[ 	]+\(%rax\)
+[	 ]*4d:[	 ]+48 0f 1f c0[	 ]+nop[ 	]+%rax
+[	 ]*51:[	 ]+0f 1f c0[	 ]+nop[ 	]+%eax
+[	 ]*54:[	 ]+66 0f 1f c0[	 ]+nop[ 	]+%ax
+[	 ]*58:[	 ]+41 0f 1f 02[	 ]+nopl[ 	]+\(%r10\)
+[	 ]*5c:[	 ]+49 0f 1f c2[	 ]+nop[ 	]+%r10
+[	 ]*60:[	 ]+41 0f 1f c2[	 ]+nop[ 	]+%r10d
+[	 ]*64:[	 ]+66 41 0f 1f c2[	 ]+nop[ 	]+%r10w
+[	 ]*69:[	 ]+49 0f 1f 02[	 ]+nopq[ 	]+\(%r10\)
+[	 ]*6d:[	 ]+41 0f 1f 02[	 ]+nopl[ 	]+\(%r10\)
+[	 ]*71:[	 ]+66 41 0f 1f 02[	 ]+nopw[ 	]+\(%r10\)
+[	 ]*76:[	 ]+49 0f 1f c2[	 ]+nop[ 	]+%r10
+[	 ]*7a:[	 ]+41 0f 1f c2[	 ]+nop[ 	]+%r10d
+[	 ]*7e:[	 ]+66 41 0f 1f c2[	 ]+nop[ 	]+%r10w
 #pass
--- binutils/gas/testsuite/gas/i386/x86-64-nops.s.nop	2006-06-12 11:59:35.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-nops.s	2007-03-21 09:12:36.000000000 -0700
@@ -9,4 +9,25 @@
 	.byte 0x66, 0x0f, 0x1f, 0x84, 0x0,  0x0, 0x0, 0x0, 0x0
 	.byte 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0
 
+	nop (%rax) 
+	nop %rax
+	nop %eax
+	nop %ax
+	nopq (%rax) 
+	nopl (%rax) 
+	nopw (%rax) 
+	nopq %rax
+	nopl %eax
+	nopw %ax
+	nop (%r10) 
+	nop %r10
+	nop %r10d
+	nop %r10w
+	nopq (%r10) 
+	nopl (%r10) 
+	nopw (%r10) 
+	nopq %r10
+	nopl %r10d
+	nopw %r10w
+
 	.p2align 4
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.d.nop	2006-09-20 04:35:11.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.d	2007-03-21 12:06:10.000000000 -0700
@@ -274,6 +274,16 @@ Disassembly of section .text:
 [	 ]*[0-9a-f]+:[	 ]+90[	 ]+nop[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+48 90[	 ]+rex64 nop[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+49 90[	 ]+xchg[	 ]+%rax,%r8[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+41 90[	 ]+xchg[	 ]+%eax,%r8d[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+41 90[	 ]+xchg[	 ]+%eax,%r8d[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+41 91[	 ]+xchg[	 ]+%eax,%r9d[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+41 91[	 ]+xchg[	 ]+%eax,%r9d[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+93[	 ]+xchg[	 ]+%eax,%ebx[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+93[	 ]+xchg[	 ]+%eax,%ebx[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+66 41 90[	 ]+xchg[	 ]+%ax,%r8w[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+66 41 90[	 ]+xchg[	 ]+%ax,%r8w[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+66 41 91[	 ]+xchg[	 ]+%ax,%r9w[	 ]*(#.*)*
+[	 ]*[0-9a-f]+:[	 ]+66 41 91[	 ]+xchg[	 ]+%ax,%r9w[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+48 0f 01 e0[	 ]+smsw[	 ]+%rax[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+0f 01 e0[	 ]+smsw[	 ]+%eax[	 ]*(#.*)*
 [	 ]*[0-9a-f]+:[	 ]+66 0f 01 e0[	 ]+smsw[	 ]+%ax[	 ]*(#.*)*
--- binutils/gas/testsuite/gas/i386/x86-64-opcode.s.nop	2006-07-18 13:25:40.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/x86-64-opcode.s	2007-03-21 12:04:51.000000000 -0700
@@ -397,6 +397,16 @@
 	xchg %rax,%rax		      # --  --	 -- --	 90
 	rex64 xchg %rax,%rax	      # --  --	 -- 48	 90
 	xchg %rax,%r8		      # --  --	 -- 49	 90
+	xchg %eax,%r8d		      # --  --	 -- 41	 90
+	xchg %r8d,%eax		      # --  --	 -- 41	 90
+	xchg %eax,%r9d		      # --  --	 -- 41	 91
+	xchg %r9d,%eax		      # --  --	 -- 41	 91
+	xchg %ebx,%eax		      # --  --	 -- 93
+	xchg %eax,%ebx		      # --  --	 -- 93
+	xchg %ax,%r8w		      # --  --	 -- 66 41 90
+	xchg %r8w,%ax		      # --  --	 -- 66 41 90
+	xchg %ax,%r9w		      # --  --	 -- 66 41 91
+	xchg %r9w,%ax		      # --  --	 -- 66 41 91
 
         smsw %rax	              #  --  --	 -- 48	 0F 01 e0
         smsw %eax	              #  --  --	 -- --	 0F 01 e0
--- binutils/opcodes/i386-dis.c.nop	2007-03-15 07:46:25.000000000 -0700
+++ binutils/opcodes/i386-dis.c	2007-03-21 11:36:00.000000000 -0700
@@ -467,6 +467,7 @@ fetch_data (struct disassemble_info *inf
 #define PREGRP35  NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 35 } }
 #define PREGRP36  NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 36 } }
 #define PREGRP37  NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 37 } }
+#define PREGRP38  NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 38 } }
 
 
 #define X86_64_0  NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } }
@@ -692,7 +693,7 @@ static const struct dis386 dis386[] = {
   { "movD",		{ Sw, Sv } },
   { "popU",		{ stackEv } },
   /* 90 */
-  { "xchgS",		{ { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } },
+  { PREGRP38 },
   { "xchgS",		{ RMeCX, eAX } },
   { "xchgS",		{ RMeDX, eAX } },
   { "xchgS",		{ RMeBX, eAX } },
@@ -2017,6 +2018,14 @@ static const struct dis386 prefix_user_t
     { "(bad)", { XX } },
     { "(bad)", { XX } },    
   },
+
+  /* PREGRP38 */
+  {
+    { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } },
+    { "pause", { XX } },
+    { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } },
+    { "(bad)", { XX } },    
+  },
 };
 
 static const struct dis386 x86_64_table[][2] = {
@@ -3091,7 +3100,8 @@ print_insn (bfd_vma pc, disassemble_info
       need_modrm = onebyte_has_modrm[*codep];
       uses_DATA_prefix = 0;
       uses_REPNZ_prefix = 0;
-      uses_REPZ_prefix = 0;
+      /* pause is 0xf3 0x90.  */
+      uses_REPZ_prefix = *codep == 0x90;
       uses_LOCK_prefix = 0;
       codep++;
     }
@@ -5284,17 +5294,15 @@ OP_0fae (int bytemode, int 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".
- */
+   32bit mode and "xchg %rax,%rax" in 64bit mode.  */  
 
 static void
 NOP_Fixup1 (int bytemode, int sizeflag)
 {
-  if (prefixes == PREFIX_REPZ)
-    strcpy (obuf, "pause");
-  else if (prefixes == PREFIX_DATA
-	   || ((rex & REX_MODE64) && rex != 0x48))
+  if ((prefixes & PREFIX_DATA) != 0
+      || (rex != 0
+	  && rex != 0x48
+	  && address_mode == mode_64bit))
     OP_REG (bytemode, sizeflag);
   else
     strcpy (obuf, "nop");
@@ -5303,8 +5311,10 @@ NOP_Fixup1 (int bytemode, int sizeflag)
 static void
 NOP_Fixup2 (int bytemode, int sizeflag)
 {
-  if (prefixes == PREFIX_DATA
-      || ((rex & REX_MODE64) && rex != 0x48))
+  if ((prefixes & PREFIX_DATA) != 0
+      || (rex != 0
+	  && rex != 0x48
+	  && address_mode == mode_64bit))
     OP_IMREG (bytemode, sizeflag);
 }
 
--- binutils/opcodes/i386-opc.c.nop	2007-03-15 10:32:27.000000000 -0700
+++ binutils/opcodes/i386-opc.c	2007-03-21 10:26:30.000000000 -0700
@@ -144,12 +144,10 @@ const template i386_optab[] =
    xchg commutes:  we allow both operand orders.
  
    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 } },
-{"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 } },
+{"xchg",   2,	0x90, X, 0,	wlq_Suf|ShortForm,	{ WordReg, Acc, 0 } },
+{"xchg",   2,	0x90, X, 0,	wlq_Suf|ShortForm,	{ Acc, WordReg, 0 } },
+{"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 } },
 
 /* In/out from ports.  */
 /* XXX should reject %rax */
@@ -517,7 +515,7 @@ const template i386_optab[] =
 
 {"hlt",	   0,	0xf4, X, 0,	 NoSuf,			{ 0, 0, 0} },
 
-{"nop",    1, 0x0f1f, X, Cpu686, wl_Suf|Modrm,		{ WordMem, 0, 0} },
+{"nop",    1, 0x0f1f, 0, Cpu686, wlq_Suf|Modrm,		{ WordReg|WordMem, 0, 0} },
 
 /* nop is actually "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
    32bit mode and "xchg %rax,%rax" in 64bit mode.  */


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