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] x86-64: fix port I/O disassembly


Port I/O cannot be 64-bits wide on x86-64.

Built and tested on i686-pc-linux-gnu, x86_64-unknown-linux-gnu, and a few
cross x86 targets.

opcodes/
2006-11-30  Jan Beulich  <jbeulich@novell.com>

	* i386-dis.c (zAX): New.
	(Xz): New.
	(Yzr): New.
	(z_mode): New.
	(z_mode_ax_reg): New.
	(putop): New suffix character 'G'.
	(dis386): Use it for in, out, ins, and outs.
	(intel_operand_size): Handle z_mode.
	(OP_REG): Delete unreachable case indir_dx_reg.
	(OP_IMREG): Fix Intel syntax output for case indir_dx_reg. Handle
	z_mode_ax_reg.
	(OP_ESreg): Fix Intel syntax operand size handling.
	(OP_DSreg): Likewise.

gas/testsuite/
2006-11-30  Jan Beulich  <jbeulich@novell.com>

	* gas/i386/x86-64-io.[sd]: New.
	* gas/i386/x86-64-io-intel.d: New.
	* gas/i386/x86-64-io-suffix.d: New.
	* gas/i386/i386.exp: Run new tests.

--- 2006-11-30/gas/testsuite/gas/i386/i386.exp	2006-11-13 15:22:00.000000000 +0100
+++ 2006-11-30/gas/testsuite/gas/i386/i386.exp	2006-11-20 17:59:55.000000000 +0100
@@ -155,6 +155,9 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "x86-64-merom"
     run_dump_test "x86-64-rep"
     run_dump_test "x86-64-rep-suffix"
+    run_dump_test "x86-64-io"
+    run_dump_test "x86-64-io-intel"
+    run_dump_test "x86-64-io-suffix"
     run_dump_test "x86-64-gidt"
     run_dump_test "x86-64-nops"
     if ![istarget "*-*-mingw64*"] then {
--- 2006-11-30/gas/testsuite/gas/i386/x86-64-io-intel.d	1970-01-01 01:00:00.000000000 +0100
+++ 2006-11-30/gas/testsuite/gas/i386/x86-64-io-intel.d	2006-11-20 16:21:38.000000000 +0100
@@ -0,0 +1,28 @@
+#source: x86-64-io.s
+#objdump: -dwMintel
+#name: x86-64 rex64 in/out (Intel disassembly)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <_in>:
+   0:	48 ed                	rex64 in     eax,dx
+   2:	66                   	data16
+   3:	48 ed                	rex64 in     eax,dx
+
+0+005 <_out>:
+   5:	48 ef                	rex64 out    dx,eax
+   7:	66                   	data16
+   8:	48 ef                	rex64 out    dx,eax
+
+0+00a <_ins>:
+   a:	48 6d                	rex64 ins    DWORD PTR es:\[rdi\],dx
+   c:	66                   	data16
+   d:	48 6d                	rex64 ins    DWORD PTR es:\[rdi\],dx
+
+0+00f <_outs>:
+   f:	48 6f                	rex64 outs   dx,DWORD PTR ds:\[rsi\]
+  11:	66                   	data16
+  12:	48 6f                	rex64 outs   dx,DWORD PTR ds:\[rsi\]
+#pass
--- 2006-11-30/gas/testsuite/gas/i386/x86-64-io-suffix.d	1970-01-01 01:00:00.000000000 +0100
+++ 2006-11-30/gas/testsuite/gas/i386/x86-64-io-suffix.d	2006-11-20 16:21:40.000000000 +0100
@@ -0,0 +1,28 @@
+#source: x86-64-io.s
+#objdump: -dwMsuffix
+#name: x86-64 rex64 in/out w/ suffix
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <_in>:
+   0:	48 ed                	rex64 inl    \(%dx\),%eax
+   2:	66                   	data16
+   3:	48 ed                	rex64 inl    \(%dx\),%eax
+
+0+005 <_out>:
+   5:	48 ef                	rex64 outl   %eax,\(%dx\)
+   7:	66                   	data16
+   8:	48 ef                	rex64 outl   %eax,\(%dx\)
+
+0+00a <_ins>:
+   a:	48 6d                	rex64 insl   \(%dx\),%es:\(%rdi\)
+   c:	66                   	data16
+   d:	48 6d                	rex64 insl   \(%dx\),%es:\(%rdi\)
+
+0+00f <_outs>:
+   f:	48 6f                	rex64 outsl  %ds:\(%rsi\),\(%dx\)
+  11:	66                   	data16
+  12:	48 6f                	rex64 outsl  %ds:\(%rsi\),\(%dx\)
+#pass
--- 2006-11-30/gas/testsuite/gas/i386/x86-64-io.d	1970-01-01 01:00:00.000000000 +0100
+++ 2006-11-30/gas/testsuite/gas/i386/x86-64-io.d	2006-11-20 16:21:35.000000000 +0100
@@ -0,0 +1,27 @@
+#objdump: -dw
+#name: x86-64 rex64 in/out
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <_in>:
+   0:	48 ed                	rex64 in     \(%dx\),%eax
+   2:	66                   	data16
+   3:	48 ed                	rex64 in     \(%dx\),%eax
+
+0+005 <_out>:
+   5:	48 ef                	rex64 out    %eax,\(%dx\)
+   7:	66                   	data16
+   8:	48 ef                	rex64 out    %eax,\(%dx\)
+
+0+00a <_ins>:
+   a:	48 6d                	rex64 insl   \(%dx\),%es:\(%rdi\)
+   c:	66                   	data16
+   d:	48 6d                	rex64 insl   \(%dx\),%es:\(%rdi\)
+
+0+00f <_outs>:
+   f:	48 6f                	rex64 outsl  %ds:\(%rsi\),\(%dx\)
+  11:	66                   	data16
+  12:	48 6f                	rex64 outsl  %ds:\(%rsi\),\(%dx\)
+#pass
\ No newline at end of file
--- 2006-11-30/gas/testsuite/gas/i386/x86-64-io.s	1970-01-01 01:00:00.000000000 +0100
+++ 2006-11-30/gas/testsuite/gas/i386/x86-64-io.s	2006-11-20 16:22:35.000000000 +0100
@@ -0,0 +1,16 @@
+ .intel_syntax noprefix
+ .text
+_in:
+	rex64 in eax,dx
+	rex64 in ax,dx
+_out:
+	rex64 out dx,eax
+	rex64 out dx,ax
+_ins:
+	rex64 insd
+	rex64 insw
+_outs:
+	rex64 outsd
+	rex64 outsw
+
+	.p2align	4,0
--- 2006-11-30/opcodes/i386-dis.c	2006-11-13 15:22:14.000000000 +0100
+++ 2006-11-30/opcodes/i386-dis.c	2006-11-21 09:43:56.000000000 +0100
@@ -289,6 +289,7 @@ fetch_data (struct disassemble_info *inf
 #define BH OP_IMREG, bh_reg
 #define AX OP_IMREG, ax_reg
 #define DX OP_IMREG, dx_reg
+#define zAX OP_IMREG, z_mode_ax_reg
 #define indirDX OP_IMREG, indir_dx_reg
 
 #define Sw OP_SEG, w_mode
@@ -297,6 +298,7 @@ fetch_data (struct disassemble_info *inf
 #define Ov OP_OFF64, v_mode
 #define Xb OP_DSreg, eSI_reg
 #define Xv OP_DSreg, eSI_reg
+#define Xz OP_DSreg, eSI_reg
 #define Yb OP_ESreg, eDI_reg
 #define Yv OP_ESreg, eDI_reg
 #define DSBX OP_DSreg, eBX_reg
@@ -325,6 +327,7 @@ fetch_data (struct disassemble_info *inf
 #define Xvr REP_Fixup, eSI_reg
 #define Ybr REP_Fixup, eDI_reg
 #define Yvr REP_Fixup, eDI_reg
+#define Yzr REP_Fixup, eDI_reg
 #define indirDXr REP_Fixup, indir_dx_reg
 #define ALr REP_Fixup, al_reg
 #define eAXr REP_Fixup, eAX_reg
@@ -352,6 +355,7 @@ fetch_data (struct disassemble_info *inf
 #define f_mode 13 /* 4- or 6-byte pointer operand */
 #define const_1_mode 14
 #define stack_v_mode 15 /* v_mode for stack-related opcodes.  */
+#define z_mode 16 /* non-quad operand size depends on prefixes */
 
 #define es_reg 100
 #define cs_reg 101
@@ -396,6 +400,7 @@ fetch_data (struct disassemble_info *inf
 #define rSI_reg 138
 #define rDI_reg 139
 
+#define z_mode_ax_reg 149
 #define indir_dx_reg 150
 
 #define FLOATCODE 1
@@ -500,6 +505,7 @@ struct dis386 {
    .      size prefix
    'E' => print 'e' if 32-bit form of jcxz
    'F' => print 'w' or 'l' depending on address size prefix (loop insns)
+   'G' => print 'w' or 'l' depending on operand size prefix (i/o insns)
    'H' => print ",pt" or ",pn" branch hint
    'I' => honor following macro letter even in Intel mode (implemented only
    .      for some of the macro letters)
@@ -654,9 +660,9 @@ static const struct dis386 dis386[] = {
   { "pushT",		sIb, XX, XX, XX },
   { "imulS",		Gv, Ev, sIb, XX },
   { "ins{b||b|}",	Ybr, indirDX, XX, XX },
-  { "ins{R||R|}",	Yvr, indirDX, XX, XX },
+  { "ins{R||G|}",	Yzr, indirDX, XX, XX },
   { "outs{b||b|}",	indirDXr, Xb, XX, XX },
-  { "outs{R||R|}",	indirDXr, Xv, XX, XX },
+  { "outs{R||G|}",	indirDXr, Xz, XX, XX },
   /* 70 */
   { "joH",		Jb, XX, cond_jump_flag, XX },
   { "jnoH",		Jb, XX, cond_jump_flag, XX },
@@ -789,18 +795,18 @@ static const struct dis386 dis386[] = {
   { "loopFH",		Jb, XX, loop_jcxz_flag, XX },
   { "jEcxzH",		Jb, XX, loop_jcxz_flag, XX },
   { "inB",		AL, Ib, XX, XX },
-  { "inS",		eAX, Ib, XX, XX },
+  { "inG",		zAX, Ib, XX, XX },
   { "outB",		Ib, AL, XX, XX },
-  { "outS",		Ib, eAX, XX, XX },
+  { "outG",		Ib, zAX, XX, XX },
   /* e8 */
   { "callT",		Jv, XX, XX, XX },
   { "jmpT",		Jv, XX, XX, XX },
   { "Jjmp{T|}",		Ap, XX, XX, XX },
   { "jmp",		Jb, XX, XX, XX },
   { "inB",		AL, indirDX, XX, XX },
-  { "inS",		eAX, indirDX, XX, XX },
+  { "inG",		zAX, indirDX, XX, XX },
   { "outB",		indirDX, AL, XX, XX },
-  { "outS",		indirDX, eAX, XX, XX },
+  { "outG",		indirDX, zAX, XX, XX },
   /* f0 */
   { "(bad)",		XX, XX, XX, XX },	/* lock prefix */
   { "icebp",		XX, XX, XX, XX },
@@ -3767,6 +3773,16 @@ putop (const char *template, int sizefla
 	      used_prefixes |= (prefixes & PREFIX_ADDR);
 	    }
 	  break;
+	case 'G':
+	  if (intel_syntax || (obufp[-1] != 's' && !(sizeflag & SUFFIX_ALWAYS)))
+	    break;
+	  if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+	    *obufp++ = 'l';
+	  else
+	    *obufp++ = 'w';
+	  if (!(rex & REX_MODE64))
+	    used_prefixes |= (prefixes & PREFIX_DATA);
+	  break;
 	case 'H':
 	  if (intel_syntax)
 	    break;
@@ -4122,6 +4138,13 @@ intel_operand_size (int bytemode, int si
 	oappend ("WORD PTR ");
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
+    case z_mode:
+      if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+	*obufp++ = 'D';
+      oappend ("WORD PTR ");
+      if (!(rex & REX_MODE64))
+	used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     case d_mode:
       oappend ("DWORD PTR ");
       break;
@@ -4572,12 +4595,6 @@ OP_REG (int code, int sizeflag)
 
   switch (code)
     {
-    case indir_dx_reg:
-      if (intel_syntax)
-	s = "[dx]";
-      else
-	s = "(%dx)";
-      break;
     case ax_reg: case cx_reg: case dx_reg: case bx_reg:
     case sp_reg: case bp_reg: case si_reg: case di_reg:
       s = names16[code - ax_reg + add];
@@ -4630,7 +4647,7 @@ OP_IMREG (int code, int sizeflag)
     {
     case indir_dx_reg:
       if (intel_syntax)
-	s = "[dx]";
+	s = "dx";
       else
 	s = "(%dx)";
       break;
@@ -4661,6 +4678,14 @@ OP_IMREG (int code, int sizeflag)
 	s = names16[code - eAX_reg];
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
+    case z_mode_ax_reg:
+      if ((rex & REX_MODE64) || (sizeflag & DFLAG))
+	s = *names32;
+      else
+	s = *names16;
+      if (!(rex & REX_MODE64))
+	used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     default:
       s = INTERNAL_DISASSEMBLER_ERROR;
       break;
@@ -4974,7 +4999,22 @@ static void
 OP_ESreg (int code, int sizeflag)
 {
   if (intel_syntax)
-    intel_operand_size (codep[-1] & 1 ? v_mode : b_mode, sizeflag);
+    {
+      switch (codep[-1])
+	{
+	case 0x6d:	/* insw/insl */
+	  intel_operand_size (z_mode, sizeflag);
+	  break;
+	case 0xa5:	/* movsw/movsl/movsq */
+	case 0xa7:	/* cmpsw/cmpsl/cmpsq */
+	case 0xab:	/* stosw/stosl */
+	case 0xaf:	/* scasw/scasl */
+	  intel_operand_size (v_mode, sizeflag);
+	  break;
+	default:
+	  intel_operand_size (b_mode, sizeflag);
+	}
+    }
   oappend ("%es:" + intel_syntax);
   ptr_reg (code, sizeflag);
 }
@@ -4983,10 +5023,21 @@ static void
 OP_DSreg (int code, int sizeflag)
 {
   if (intel_syntax)
-    intel_operand_size (codep[-1] != 0xd7 && (codep[-1] & 1)
-			? v_mode
-			: b_mode,
-			sizeflag);
+    {
+      switch (codep[-1])
+	{
+	case 0x6f:	/* outsw/outsl */
+	  intel_operand_size (z_mode, sizeflag);
+	  break;
+	case 0xa5:	/* movsw/movsl/movsq */
+	case 0xa7:	/* cmpsw/cmpsl/cmpsq */
+	case 0xad:	/* lodsw/lodsl/lodsq */
+	  intel_operand_size (v_mode, sizeflag);
+	  break;
+	default:
+	  intel_operand_size (b_mode, sizeflag);
+	}
+    }
   if ((prefixes
        & (PREFIX_CS
 	  | PREFIX_DS



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