[v5,3/5] x86: replace adhoc (partly wrong) ambiguous operand checking for MOVSX/MOVZX

Message ID 51743857-5b6b-d687-2174-7658d712e123@suse.com
State Superseded
Headers show
Series
  • x86: operand size handling improvements
Related show

Commit Message

Jan Beulich Feb. 11, 2020, 10:25 a.m.
For these to get treatment consistent with other operand size checking
the special logic shouldn't live in md_assemble(), but process_suffix().
And there's more logic involved than simply zapping the suffix, in
particular to enforce the general "suffix trumps register size" rule in
AT&T mode. The cases where behavior is being corrected can be seen from
the testcase adjustments (as mentioned in the commit introducing these
tests some cases had wrong expectations at that point, but it seemed
better to separate testcase introduction from actual code changes).

Note however that MOVS[BW]* and MOVZ[BW]* still won't be fully
consistent, due to the objection to fold MOVS* templates just like was
done for MOVZ* in c07315e0c6 ("x86: allow suffix-less movzw and 64-bit
movzb").

Note further that the assembler change points out (and this patch fixes)
a wrong Intel syntax test introduced by bc31405ebb2c ("x86-64: Properly
encode and decode movsxd"): When source code specifies a 16-bit
destination register, disassembly expectations shouldn't have been to
find a 32-bit one.

gas/
2020-02-XX  Jan Beulich  <jbeulich@suse.com>

	PR gas/25438
	* config/tc-i386.c (md_assemble): Move movsx/movzx special
	casing ...
	(process_suffix): ... here. Consider just the first operand
	initially.
	(check_long_reg): Drop opcode 0x63 special case again.
	* testsuite/gas/i386/movx16.l, testsuite/gas/i386/movx32.l,
	testsuite/gas/i386/movx64.l, testsuite/gas/i386/noreg16.l,
	testsuite/gas/i386/noreg32.l, testsuite/gas/i386/noreg64.l,
	testsuite/gas/i386/x86-64-movsxd-intel.d,
	testsuite/gas/i386/x86-64-movsxd.d: Adjust expectations.

opcodes/
2020-02-XX  Jan Beulich  <jbeulich@suse.com>

	PR gas/25438
	* i386-opc.tbl (movsx): Fold patterns. Also allow Reg32 as
	destination for Cpu64-only variant.
	(movsxd): Also allow Reg32 as destination. Drop Rex64.
	(movzx): Fold patterns.
	* i386-tbl.h: Re-generate.
---
v5: Re-base.
v4: Re-base.
v3: Re-base.
v2: Undo No_lSuf addition to MOVSXD template. Drop bogus / pointless
    !i.tm.opcode_modifier.rex64 part of conditional in md_assemble().
    Re-base over changes earlier in the series.

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4378,22 +4378,6 @@  md_assemble (char *line)
        : as_bad) (_("SSE instruction `%s' is used"), i.tm.name);
     }
 
-  /* Zap movzx and movsx suffix.  The suffix has been set from
-     "word ptr" or "byte ptr" on the source operand in Intel syntax
-     or extracted from mnemonic in AT&T syntax.  But we'll use
-     the destination register to choose the suffix for encoding.  */
-  if ((i.tm.base_opcode & ~9) == 0x0fb6)
-    {
-      /* In Intel syntax, there must be a suffix.  In AT&T syntax, if
-	 there is no suffix, the default will be byte extension.  */
-      if (i.reg_operands != 2
-	  && !i.suffix
-	  && intel_syntax)
-	as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
-
-      i.suffix = 0;
-    }
-
   if (i.tm.opcode_modifier.fwait)
     if (!add_prefix (FWAIT_OPCODE))
       return;
@@ -6311,6 +6295,15 @@  process_suffix (void)
   else if (i.reg_operands
 	   && (i.operands > 1 || i.types[0].bitfield.class == Reg))
     {
+      unsigned int numop = i.operands;
+
+      /* movsx/movzx want only their source operand considered here, for the
+	 ambiguity checking below.  The suffix will be replaced afterwards
+	 to represent the destination (register).  */
+      if (((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w)
+	  || (i.tm.base_opcode == 0x63 && i.tm.cpu_flags.bitfield.cpu64))
+	--i.operands;
+
       /* If there's no instruction mnemonic suffix we try to invent one
 	 based on GPR operands.  */
       if (!i.suffix)
@@ -6339,6 +6332,13 @@  process_suffix (void)
 		  continue;
 		break;
 	      }
+
+	  /* As an exception, movsx/movzx with a word register destination
+	     silently default to a byte source in AT&T mode, as their word
+	     memory source case isn't really useful.  */
+	  if ((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w
+	      && !i.suffix && !intel_syntax && i.types[1].bitfield.word)
+	    i.suffix = BYTE_MNEM_SUFFIX;
 	}
       else if (i.suffix == BYTE_MNEM_SUFFIX)
 	{
@@ -6385,6 +6385,9 @@  process_suffix (void)
 	;
       else
 	abort ();
+
+      /* Undo the movsx/movzx change done above.  */
+      i.operands = numop;
     }
   else if (i.tm.opcode_modifier.defaultsize && !i.suffix)
     {
@@ -6484,6 +6487,10 @@  process_suffix (void)
 
 	  if (i.tm.opcode_modifier.floatmf)
 	    i.suffix = SHORT_MNEM_SUFFIX;
+	  else if ((i.tm.base_opcode | 8) == 0xfbe
+		   || (i.tm.base_opcode == 0x63
+		       && i.tm.cpu_flags.bitfield.cpu64))
+	    /* handled below */;
 	  else if (flag_code == CODE_16BIT)
 	    i.suffix = WORD_MNEM_SUFFIX;
 	  else if (!i.tm.opcode_modifier.no_lsuf)
@@ -6493,6 +6500,32 @@  process_suffix (void)
 	}
     }
 
+  if ((i.tm.base_opcode | 8) == 0xfbe
+      || (i.tm.base_opcode == 0x63 && i.tm.cpu_flags.bitfield.cpu64))
+    {
+      /* In Intel syntax, movsx/movzx must have a "suffix" (checked above).
+	 In AT&T syntax, if there is no suffix (warned about above), the default
+	 will be byte extension.  */
+      if (i.tm.opcode_modifier.w && i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
+	i.tm.base_opcode |= 1;
+
+      /* For further processing, the suffix should represent the destination
+	 (register).  This is already the case when one was used with
+	 mov[sz][bw]*, but we need to replace it for mov[sz]x, or if there was
+	 no suffix to begin with.  */
+      if (i.tm.opcode_modifier.w || i.tm.base_opcode == 0x63 || !i.suffix)
+	{
+	  if (i.types[1].bitfield.word)
+	    i.suffix = WORD_MNEM_SUFFIX;
+	  else if (i.types[1].bitfield.qword)
+	    i.suffix = QWORD_MNEM_SUFFIX;
+	  else
+	    i.suffix = LONG_MNEM_SUFFIX;
+
+	  i.tm.opcode_modifier.w = 0;
+	}
+    }
+
   if (!i.tm.opcode_modifier.modrm && i.reg_operands && i.tm.operands < 3)
     i.short_form = (i.tm.operand_types[0].bitfield.class == Reg)
 		   != (i.tm.operand_types[1].bitfield.class == Reg);
@@ -6699,9 +6732,7 @@  check_long_reg (void)
 	     && i.tm.operand_types[op].bitfield.dword)
       {
 	if (intel_syntax
-	    && (i.tm.opcode_modifier.toqword
-		/* Also convert to QWORD for MOVSXD.  */
-		|| i.tm.base_opcode == 0x63)
+	    && i.tm.opcode_modifier.toqword
 	    && i.types[0].bitfield.class != RegSIMD)
 	  {
 	    /* Convert to QWORD.  We want REX byte. */
--- a/gas/testsuite/gas/i386/movx16.l
+++ b/gas/testsuite/gas/i386/movx16.l
@@ -6,7 +6,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 0FBEC8[ 	]+movsx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 0FBFC8[ 	]+movsx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FBEC8[ 	]+movsx	%al, %ecx
@@ -30,7 +30,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 0FBFC8[ 	]+movsxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%al, %ecx
@@ -103,7 +103,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzx	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 0FB7C8[ 	]+movzx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzx	%al, %ecx
@@ -127,7 +127,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 0FB7C8[ 	]+movzxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%al, %ecx
@@ -154,7 +154,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzbw	%al, %ecx
+[ 	]*[1-9][0-9]*[ 	]+movzbw	%al, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -162,7 +162,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %cl
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzbl	%al, %cx
+[ 	]*[1-9][0-9]*[ 	]+movzbl	%al, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
--- a/gas/testsuite/gas/i386/movx32.l
+++ b/gas/testsuite/gas/i386/movx32.l
@@ -6,7 +6,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FBEC8[ 	]+movsx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FBFC8[ 	]+movsx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 0FBEC8[ 	]+movsx	%al, %ecx
@@ -30,7 +30,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FBFC8[ 	]+movsxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%al, %ecx
@@ -103,7 +103,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzx	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FB7C8[ 	]+movzx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzx	%al, %ecx
@@ -127,7 +127,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FB7C8[ 	]+movzxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%al, %ecx
@@ -154,7 +154,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzbw	%al, %ecx
+[ 	]*[1-9][0-9]*[ 	]+movzbw	%al, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -162,7 +162,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %cl
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzbl	%al, %cx
+[ 	]*[1-9][0-9]*[ 	]+movzbl	%al, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
--- a/gas/testsuite/gas/i386/movx64.l
+++ b/gas/testsuite/gas/i386/movx64.l
@@ -7,13 +7,13 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsx	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FBEC8[ 	]+movsx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FBFC8[ 	]+movsx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsx	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 0FBEC8[ 	]+movsx	%al, %ecx
 [ 	]*[1-9][0-9]* \?\?\?\? 0FBFC8[ 	]+movsx	%ax, %ecx
-[ 	]*[1-9][0-9]*[ 	]+movsx	%eax, %ecx
+[ 	]*[1-9][0-9]* \?\?\?\? 63C8[ 	]+movsx	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movsx	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 480FBEC8[ 	]+movsx	%al, %rcx
@@ -47,7 +47,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movsxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FBFC8[ 	]+movsxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movsxw	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -73,7 +73,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxl	%al, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movsxl	%ax, %ecx
-[ 	]*[1-9][0-9]*[ 	]+movsxl	%eax, %ecx
+[ 	]*[1-9][0-9]* \?\?\?\? 63C8[ 	]+movsxl	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movsxl	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movsxl	%al, %rcx
@@ -248,7 +248,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzx	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzx	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzx	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FB7C8[ 	]+movzx	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzx	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzx	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -288,7 +288,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%al, %cx
-[ 	]*[1-9][0-9]*[ 	]+movzxw	%ax, %cx
+[ 	]*[1-9][0-9]* \?\?\?\? 660FB7C8[ 	]+movzxw	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzxw	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -372,12 +372,12 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzbw	%al, %ecx
+[ 	]*[1-9][0-9]*[ 	]+movzbw	%al, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 480FB6C8[ 	]+movzbw	%al, %rcx
+[ 	]*[1-9][0-9]*[ 	]+movzbw	%al, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%ax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%eax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbw	%rax, %rcx
@@ -387,7 +387,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzbl	%al, %cx
+[ 	]*[1-9][0-9]*[ 	]+movzbl	%al, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%rax, %cx
@@ -397,7 +397,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 480FB6C8[ 	]+movzbl	%al, %rcx
+[ 	]*[1-9][0-9]*[ 	]+movzbl	%al, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%ax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%eax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzbl	%rax, %rcx
@@ -407,12 +407,12 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%eax, %cl
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%rax, %cl
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 660FB6C8[ 	]+movzbq	%al, %cx
+[ 	]*[1-9][0-9]*[ 	]+movzbq	%al, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%ax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%eax, %cx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
-[ 	]*[1-9][0-9]* \?\?\?\? 0FB6C8[ 	]+movzbq	%al, %ecx
+[ 	]*[1-9][0-9]*[ 	]+movzbq	%al, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%ax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzbq	%rax, %ecx
@@ -458,7 +458,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzwl	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzwl	%al, %rcx
-[ 	]*[1-9][0-9]* \?\?\?\? 480FB7C8[ 	]+movzwl	%ax, %rcx
+[ 	]*[1-9][0-9]*[ 	]+movzwl	%ax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzwl	%eax, %rcx
 [ 	]*[1-9][0-9]*[ 	]+movzwl	%rax, %rcx
 [ 	]*[1-9][0-9]*[ 	]*
@@ -473,7 +473,7 @@ 
 [ 	]*[1-9][0-9]*[ 	]+movzwq	%rax, %cx
 [ 	]*[1-9][0-9]*[ 	]*
 [ 	]*[1-9][0-9]*[ 	]+movzwq	%al, %ecx
-[ 	]*[1-9][0-9]* \?\?\?\? 0FB7C8[ 	]+movzwq	%ax, %ecx
+[ 	]*[1-9][0-9]*[ 	]+movzwq	%ax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzwq	%eax, %ecx
 [ 	]*[1-9][0-9]*[ 	]+movzwq	%rax, %ecx
 [ 	]*[1-9][0-9]*[ 	]*
--- a/gas/testsuite/gas/i386/noreg16.l
+++ b/gas/testsuite/gas/i386/noreg16.l
@@ -56,6 +56,8 @@ 
 .*:[1-9][0-9]*: Warning: .* `mov'
 .*:[1-9][0-9]*: Warning: .* `movs'
 .*:[1-9][0-9]*: Warning: .* `movs'
+.*:[1-9][0-9]*: Warning: .* `movsx'
+.*:[1-9][0-9]*: Warning: .* `movzx'
 .*:[1-9][0-9]*: Warning: .* `mul'
 .*:[1-9][0-9]*: Warning: .* `neg'
 .*:[1-9][0-9]*: Warning: .* `nop'
--- a/gas/testsuite/gas/i386/noreg32.l
+++ b/gas/testsuite/gas/i386/noreg32.l
@@ -61,6 +61,8 @@ 
 .*:[1-9][0-9]*: Warning: .* `mov'
 .*:[1-9][0-9]*: Warning: .* `movs'
 .*:[1-9][0-9]*: Warning: .* `movs'
+.*:[1-9][0-9]*: Warning: .* `movsx'
+.*:[1-9][0-9]*: Warning: .* `movzx'
 .*:[1-9][0-9]*: Warning: .* `mul'
 .*:[1-9][0-9]*: Warning: .* `neg'
 .*:[1-9][0-9]*: Warning: .* `nop'
--- a/gas/testsuite/gas/i386/noreg64.l
+++ b/gas/testsuite/gas/i386/noreg64.l
@@ -67,6 +67,10 @@ 
 .*:[1-9][0-9]*: Warning: .* `mov'
 .*:[1-9][0-9]*: Warning: .* `movs'
 .*:[1-9][0-9]*: Warning: .* `movs'
+.*:[1-9][0-9]*: Warning: .* `movsx'
+.*:[1-9][0-9]*: Warning: .* `movsx'
+.*:[1-9][0-9]*: Warning: .* `movzx'
+.*:[1-9][0-9]*: Warning: .* `movzx'
 .*:[1-9][0-9]*: Warning: .* `mul'
 .*:[1-9][0-9]*: Warning: .* `neg'
 .*:[1-9][0-9]*: Warning: .* `nop'
--- a/gas/testsuite/gas/i386/x86-64-movsxd-intel.d
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel.d
@@ -21,6 +21,6 @@  Disassembly of section .text:
  +[a-f0-9]+:	63 08                	movsxd ecx,DWORD PTR \[rax\]
  +[a-f0-9]+:	63 08                	movsxd ecx,DWORD PTR \[rax\]
  +[a-f0-9]+:	66 63 c8             	movsxd cx,eax
- +[a-f0-9]+:	63 08                	movsxd ecx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	66 63 08             	movsxd cx,DWORD PTR \[rax\]
  +[a-f0-9]+:	66 63 08             	movsxd cx,DWORD PTR \[rax\]
 #pass
--- a/gas/testsuite/gas/i386/x86-64-movsxd.d
+++ b/gas/testsuite/gas/i386/x86-64-movsxd.d
@@ -20,6 +20,6 @@  Disassembly of section .text:
  +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
  +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
  +[a-f0-9]+:	66 63 c8             	movsxd %eax,%cx
- +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
+ +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
  +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
 #pass
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -132,13 +132,9 @@  movswl, 2, 0xfbf, None, 2, Cpu386, Modrm
 movsbq, 2, 0xfbe, None, 2, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64, { Reg8|Byte|Unspecified|BaseIndex, Reg64 }
 movswq, 2, 0xfbf, None, 2, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64, { Reg16|Word|Unspecified|BaseIndex, Reg64 }
 movslq, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64, { Reg32|Dword|Unspecified|BaseIndex, Reg64 }
-// Intel Syntax next 3 insns
-movsx, 2, 0xfbe, None, 2, Cpu386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ATTSyntax, { Reg8|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-movsx, 2, 0xfbf, None, 2, Cpu386, Modrm|No_bSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ATTSyntax, { Reg16|Unspecified|BaseIndex, Reg32|Reg64 }
-movsx, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64|ATTSyntax, { Reg32|Unspecified|BaseIndex, Reg64 }
-movsx, 2, 0xfbe, None, 2, Cpu386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IntelSyntax, { Reg8|Byte|BaseIndex, Reg16|Reg32|Reg64 }
-movsx, 2, 0xfbf, None, 2, Cpu386, Modrm|No_bSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IntelSyntax, { Reg16|Word|BaseIndex, Reg32|Reg64 }
-movsx, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64|IntelSyntax, { Reg32|Dword|BaseIndex, Reg64 }
+// Intel Syntax next 2 insns
+movsx, 2, 0xfbe, None, 2, Cpu386, W|Modrm|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg8|Reg16|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+movsx, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, Reg32|Reg64 }
 movsxd, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, Reg32|Reg64 }
 movsxd, 2, 0x63, None, 1, Cpu64, Amd64|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, Reg16 }
 movsxd, 2, 0x63, None, 1, Cpu64, Intel64|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Unspecified|BaseIndex, Reg16 }
@@ -146,12 +142,9 @@  movsxd, 2, 0x63, None, 1, Cpu64, Intel64
 // Move with zero extend.
 movzb, 2, 0xfb6, None, 2, Cpu386, Modrm|No_bSuf|No_sSuf|No_ldSuf, { Reg8|Byte|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
 movzw, 2, 0xfb7, None, 2, Cpu386, Modrm|No_bSuf|No_wSuf|No_sSuf|No_ldSuf, { Reg16|Word|Unspecified|BaseIndex, Reg32|Reg64 }
-// Intel Syntax next 2 insns (the 64-bit variants are not particulary
+// Intel Syntax next insn (the 64-bit variant is not particulary
 // useful since the zero extend 32->64 is implicit, but we can encode them).
-movzx, 2, 0xfb6, None, 2, Cpu386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ATTSyntax, { Reg8|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-movzx, 2, 0xfb7, None, 2, Cpu386, Modrm|No_bSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ATTSyntax, { Reg16|Unspecified|BaseIndex, Reg32|Reg64 }
-movzx, 2, 0xfb6, None, 2, Cpu386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IntelSyntax, { Reg8|Byte|BaseIndex, Reg16|Reg32|Reg64 }
-movzx, 2, 0xfb7, None, 2, Cpu386, Modrm|No_bSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IntelSyntax, { Reg16|Word|BaseIndex, Reg32|Reg64 }
+movzx, 2, 0xfb6, None, 2, Cpu386, W|Modrm|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg8|Reg16|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
 
 // Push instructions.
 push, 1, 0x50, None, 1, CpuNo64, No_bSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Reg32 }