[PATCH] x86-64: Properly encode and decode movsxd

H.J. Lu hjl.tools@gmail.com
Thu Jan 23 20:25:00 GMT 2020


movsxd is a 64-bit only instruction.  It supports both 16-bit and 32-bit
destination registers.  Its AT&T mnemonic is movslq which only supports
64-bit destination register.  There is also a discrepancy between AMD64
and Intel64 on movsxd with 16-bit destination register.  AMD64 supports
32-bit source operand and Intel64 supports 16-bit source operand.

This patch updates movsxd encoding and decoding to alow 16-bit and 32-bit
destination registers.  It also handles movsxd with 16-bit destination
register for AMD64 and Intel 64.

gas/

	PR binutils/25445
	* config/tc-i386.c (check_long_reg): Also convert to QWORD for
	movsxd.
	* doc/c-i386.texi: Add a node for AMD64 vs. Intel64 ISA
	differences.  Document movslq and movsxd.
	* testsuite/gas/i386/i386.exp: Run PR binutils/25445 tests.
	* testsuite/gas/i386/x86-64-movsxd-intel.d: New file.
	* testsuite/gas/i386/x86-64-movsxd-intel64-intel.d: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-intel64-inval.l: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-intel64-inval.s: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-intel64.d: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-intel64.s: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-inval.l: Likewise.
	* testsuite/gas/i386/x86-64-movsxd-inval.s: Likewise.
	* testsuite/gas/i386/x86-64-movsxd.d: Likewise.
	* testsuite/gas/i386/x86-64-movsxd.s: Likewise.

opcodes/

	PR binutils/25445
	* i386-dis.c (MOVSXD_Fixup): New.
	(movsxd_mode): New enum.
	(x86_64_table): Use MOVSXD_Fixup and movsxd_mode on movsxd.
	(intel_operand_size): Handle movsxd_mode.
	(OP_E_register): Likewise.
	(OP_G): Likewise.
	* i386-opc.tbl: Remove Rex64 and allow 32-bit destination
	register on movsxd.  Add movsxd with 16-bit destination register
	for AMD64 and Intel64 ISAs.
	* i386-tbl.h: Regenerated.
---
 gas/config/tc-i386.c                          |  4 +-
 gas/doc/c-i386.texi                           | 18 ++++++
 gas/testsuite/gas/i386/i386.exp               |  6 ++
 gas/testsuite/gas/i386/x86-64-movsxd-intel.d  | 26 ++++++++
 .../gas/i386/x86-64-movsxd-intel64-intel.d    | 26 ++++++++
 .../gas/i386/x86-64-movsxd-intel64-inval.l    | 27 ++++++++
 .../gas/i386/x86-64-movsxd-intel64-inval.s    | 14 +++++
 .../gas/i386/x86-64-movsxd-intel64.d          | 25 ++++++++
 .../gas/i386/x86-64-movsxd-intel64.s          | 20 ++++++
 gas/testsuite/gas/i386/x86-64-movsxd-inval.l  | 27 ++++++++
 gas/testsuite/gas/i386/x86-64-movsxd-inval.s  | 14 +++++
 gas/testsuite/gas/i386/x86-64-movsxd.d        | 25 ++++++++
 gas/testsuite/gas/i386/x86-64-movsxd.s        | 20 ++++++
 opcodes/i386-dis.c                            | 61 ++++++++++++++++++-
 opcodes/i386-opc.tbl                          |  4 +-
 opcodes/i386-tbl.h                            | 34 ++++++++++-
 16 files changed, 344 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel64-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel64.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-intel64.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-inval.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd-inval.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-movsxd.s

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 34778ae7605..e3c971ca499 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -6690,7 +6690,9 @@ check_long_reg (void)
 	     && i.tm.operand_types[op].bitfield.dword)
       {
 	if (intel_syntax
-	    && i.tm.opcode_modifier.toqword
+	    && (i.tm.opcode_modifier.toqword
+		/* Also convert to QWORD for MOVSXD.  */
+		|| i.tm.base_opcode == 0x63)
 	    && i.types[0].bitfield.class != RegSIMD)
 	  {
 	    /* Convert to QWORD.  We want REX byte. */
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index 6d556a01a10..9fb681e8729 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -37,6 +37,7 @@ extending the Intel architecture to 64-bits.
 * i386-TBM::                    AMD's Trailing Bit Manipulation Instructions
 * i386-16bit::                  Writing 16-bit Code
 * i386-Arch::                   Specifying an x86 CPU architecture
+* i386-ISA::                    AMD64 ISA vs. Intel64 ISA
 * i386-Bugs::                   AT&T Syntax bugs
 * i386-Notes::                  Notes
 @end menu
@@ -856,6 +857,12 @@ Several x87 instructions, @samp{fadd}, @samp{fdiv}, @samp{fdivp},
 assembler with different mnemonics from those in Intel IA32 specification.
 @code{@value{GCC}} generates those instructions with AT&T mnemonic.
 
+@itemize @bullet
+@item @samp{movslq} with AT&T mnemonic only accepts 64-bit destination
+register.  @samp{movsxd} should be used to encode 16-bit or 32-bit
+destination register with both AT&T and Intel mnemonics.
+@end itemize
+
 @node i386-Regs
 @section Register Naming
 
@@ -1438,6 +1445,17 @@ For example
  .arch i8086,nojumps
 @end smallexample
 
+@node i386-ISA
+@section AMD64 ISA vs. Intel64 ISA
+
+There are some discrepancies between AMD64 and Intel64 ISAs.
+
+@itemize @bullet
+@item For @samp{movsxd} with 16-bit destination register, AMD64
+supports 32-bit source operand and Intel64 supports 16-bit source
+operand.
+@end itemize
+
 @node i386-Bugs
 @section AT&T Syntax bugs
 
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index aedcf147380..feab8c2be95 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -1050,6 +1050,12 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
     run_dump_test "x86-64-movd-intel"
     run_dump_test "x86-64-nop-1"
     run_dump_test "x86-64-nop-2"
+    run_dump_test "x86-64-movsxd"
+    run_dump_test "x86-64-movsxd-intel"
+    run_list_test "x86-64-movsxd-inval" "-al"
+    run_dump_test "x86-64-movsxd-intel64"
+    run_dump_test "x86-64-movsxd-intel64-intel"
+    run_list_test "x86-64-movsxd-intel64-inval" "-mintel64 -al"
     run_dump_test "x86-64-optimize-1"
     run_dump_test "x86-64-optimize-2"
     run_dump_test "x86-64-optimize-2a"
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel.d b/gas/testsuite/gas/i386/x86-64-movsxd-intel.d
new file mode 100644
index 00000000000..b7f55d41681
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel.d
@@ -0,0 +1,26 @@
+#source: x86-64-movsxd.s
+#as:
+#objdump: -dw -Mintel
+#name: x86-64 movsxd (AMD64) (Intel mode)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:	48 63 c8             	movsxd rcx,eax
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	63 c8                	movsxd ecx,eax
+ +[a-f0-9]+:	63 08                	movsxd ecx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	66 63 c8             	movsxd cx,eax
+ +[a-f0-9]+:	66 63 08             	movsxd cx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	48 63 c8             	movsxd rcx,eax
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	63 c8                	movsxd ecx,eax
+ +[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\]
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel64-intel.d b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-intel.d
new file mode 100644
index 00000000000..1145df2971f
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-intel.d
@@ -0,0 +1,26 @@
+#source: x86-64-movsxd-intel64.s
+#as: -mintel64
+#objdump: -dw -Mintel -Mintel64
+#name: x86-64 movsxd (Intel64) (Intel mode)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:	48 63 c8             	movsxd rcx,eax
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	63 c8                	movsxd ecx,eax
+ +[a-f0-9]+:	63 08                	movsxd ecx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	66 63 c8             	movsxd cx,ax
+ +[a-f0-9]+:	66 63 08             	movsxd cx,WORD PTR \[rax\]
+ +[a-f0-9]+:	48 63 c8             	movsxd rcx,eax
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	48 63 08             	movsxd rcx,DWORD PTR \[rax\]
+ +[a-f0-9]+:	63 c8                	movsxd ecx,eax
+ +[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,ax
+ +[a-f0-9]+:	66 63 08             	movsxd cx,WORD PTR \[rax\]
+ +[a-f0-9]+:	66 63 08             	movsxd cx,WORD PTR \[rax\]
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.l b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.l
new file mode 100644
index 00000000000..b3219e0c671
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.l
@@ -0,0 +1,27 @@
+.*: Assembler messages:
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+.*:7: Error: .*
+.*:10: Error: .*
+.*:11: Error: .*
+.*:12: Error: .*
+.*:13: Error: .*
+.*:14: Error: .*
+GAS LISTING .*
+
+
+[ 	]*1[ 	]+\# 64-bit only invalid MOVSXD with Intel64 ISA
+[ 	]*2[ 	]+\.text
+[ 	]*3[ 	]+_start:
+[ 	]*4[ 	]+movslq	%eax, %cx
+[ 	]*5[ 	]+movslq	%eax, %ecx
+[ 	]*6[ 	]+movslq	\(%rax\), %ecx
+[ 	]*7[ 	]+movsxd	%ax, %ecx
+[ 	]*8[ 	]+
+[ 	]*9[ 	]+\.intel_syntax noprefix
+[ 	]*10[ 	]+movslq	cx, ax
+[ 	]*11[ 	]+movslq	ecx, eax
+[ 	]*12[ 	]+movslq	ecx, \[rax\]
+[ 	]*13[ 	]+movsxd	cx, eax
+[ 	]*14[ 	]+movsxd	cx, DWORD PTR \[rax\]
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.s b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.s
new file mode 100644
index 00000000000..2edcaf83302
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel64-inval.s
@@ -0,0 +1,14 @@
+# 64-bit only invalid MOVSXD with Intel64 ISA
+	.text
+_start:
+	movslq	%eax, %cx
+	movslq	%eax, %ecx
+	movslq	(%rax), %ecx
+	movsxd	%ax, %ecx
+
+	.intel_syntax noprefix
+	movslq	cx, ax
+	movslq	ecx, eax
+	movslq	ecx, [rax]
+	movsxd	cx, eax
+	movsxd	cx, DWORD PTR [rax]
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel64.d b/gas/testsuite/gas/i386/x86-64-movsxd-intel64.d
new file mode 100644
index 00000000000..afd26d93a51
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel64.d
@@ -0,0 +1,25 @@
+#as: -mintel64
+#objdump: -dw -Mintel64
+#name: x86-64 movsxd (Intel64)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:	48 63 c8             	movslq %eax,%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	63 c8                	movsxd %eax,%ecx
+ +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
+ +[a-f0-9]+:	66 63 c8             	movsxd %ax,%cx
+ +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
+ +[a-f0-9]+:	48 63 c8             	movslq %eax,%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	63 c8                	movsxd %eax,%ecx
+ +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
+ +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
+ +[a-f0-9]+:	66 63 c8             	movsxd %ax,%cx
+ +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
+ +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-intel64.s b/gas/testsuite/gas/i386/x86-64-movsxd-intel64.s
new file mode 100644
index 00000000000..842cdef42f5
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-intel64.s
@@ -0,0 +1,20 @@
+# 64-bit only MOVSXD with Intel64 ISA
+	.text
+_start:
+	movslq	%eax, %rcx
+	movslq	(%rax), %rcx
+	movsxd	%eax, %ecx
+	movsxd	(%rax), %ecx
+	movsxd	%ax, %cx
+	movsxd	(%rax), %cx
+
+	.intel_syntax noprefix
+	movsxd	rcx, eax
+	movsxd	rcx, DWORD PTR [rax]
+	movsxd	rcx, [rax]
+	movsxd	ecx, eax
+	movsxd	ecx, DWORD PTR [rax]
+	movsxd	ecx, [rax]
+	movsxd	cx, ax
+	movsxd	cx, WORD PTR [rax]
+	movsxd	cx, [rax]
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-inval.l b/gas/testsuite/gas/i386/x86-64-movsxd-inval.l
new file mode 100644
index 00000000000..7db46d6af39
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-inval.l
@@ -0,0 +1,27 @@
+.*: Assembler messages:
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+.*:7: Error: .*
+.*:10: Error: .*
+.*:11: Error: .*
+.*:12: Error: .*
+.*:13: Error: .*
+.*:14: Error: .*
+GAS LISTING .*
+
+
+[ 	]*1[ 	]+\# 64-bit only invalid MOVSXD with AMD64 ISA
+[ 	]*2[ 	]+\.text
+[ 	]*3[ 	]+_start:
+[ 	]*4[ 	]+movslq	%ax, %cx
+[ 	]*5[ 	]+movslq	%eax, %ecx
+[ 	]*6[ 	]+movslq	\(%rax\), %ecx
+[ 	]*7[ 	]+movsxd	%ax, %cx
+[ 	]*8[ 	]+
+[ 	]*9[ 	]+\.intel_syntax noprefix
+[ 	]*10[ 	]+movslq	cx, eax
+[ 	]*11[ 	]+movslq	ecx, eax
+[ 	]*12[ 	]+movslq	ecx, \[rax\]
+[ 	]*13[ 	]+movsxd	cx, ax
+[ 	]*14[ 	]+movsxd	cx, WORD PTR \[rax\]
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd-inval.s b/gas/testsuite/gas/i386/x86-64-movsxd-inval.s
new file mode 100644
index 00000000000..84bf5209057
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd-inval.s
@@ -0,0 +1,14 @@
+# 64-bit only invalid MOVSXD with AMD64 ISA
+	.text
+_start:
+	movslq	%ax, %cx
+	movslq	%eax, %ecx
+	movslq	(%rax), %ecx
+	movsxd	%ax, %cx
+
+	.intel_syntax noprefix
+	movslq	cx, eax
+	movslq	ecx, eax
+	movslq	ecx, [rax]
+	movsxd	cx, ax
+	movsxd	cx, WORD PTR [rax]
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd.d b/gas/testsuite/gas/i386/x86-64-movsxd.d
new file mode 100644
index 00000000000..1881fe2e313
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd.d
@@ -0,0 +1,25 @@
+#as:
+#objdump: -dw
+#name: x86-64 movsxd (AMD64)
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:	48 63 c8             	movslq %eax,%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	63 c8                	movsxd %eax,%ecx
+ +[a-f0-9]+:	63 08                	movsxd \(%rax\),%ecx
+ +[a-f0-9]+:	66 63 c8             	movsxd %eax,%cx
+ +[a-f0-9]+:	66 63 08             	movsxd \(%rax\),%cx
+ +[a-f0-9]+:	48 63 c8             	movslq %eax,%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	48 63 08             	movslq \(%rax\),%rcx
+ +[a-f0-9]+:	63 c8                	movsxd %eax,%ecx
+ +[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
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-movsxd.s b/gas/testsuite/gas/i386/x86-64-movsxd.s
new file mode 100644
index 00000000000..f0efd59319a
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-movsxd.s
@@ -0,0 +1,20 @@
+# 64-bit only MOVSXD with AMD64 ISA
+	.text
+_start:
+	movslq	%eax, %rcx
+	movslq	(%rax), %rcx
+	movsxd	%eax, %ecx
+	movsxd	(%rax), %ecx
+	movsxd	%eax, %cx
+	movsxd	(%rax), %cx
+
+	.intel_syntax noprefix
+	movsxd	rcx, eax
+	movsxd	rcx, DWORD PTR [rax]
+	movsxd	rcx, [rax]
+	movsxd	ecx, eax
+	movsxd	ecx, DWORD PTR [rax]
+	movsxd	ecx, [rax]
+	movsxd	cx, eax
+	movsxd	cx, DWORD PTR [rax]
+	movsxd	cx, [rax]
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index c73e964b546..e6f73bff206 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -124,6 +124,7 @@ static void OP_Vex_2src_1 (int, int);
 static void OP_Vex_2src_2 (int, int);
 
 static void MOVBE_Fixup (int, int);
+static void MOVSXD_Fixup (int, int);
 
 static void OP_Mask (int, int);
 
@@ -556,6 +557,7 @@ enum
   a_mode,
   cond_jump_mode,
   loop_jcxz_mode,
+  movsxd_mode,
   v_bnd_mode,
   /* like v_bnd_mode in 32bit, no RIP-rel in 64bit mode.  */
   v_bndmk_mode,
@@ -6873,7 +6875,7 @@ static const struct dis386 x86_64_table[][2] = {
   /* X86_64_63 */
   {
     { "arpl", { Ew, Gw }, 0 },
-    { "movs{lq|xd}", { Gv, Ed }, 0 },
+    { "movs", { { OP_G, movsxd_mode }, { MOVSXD_Fixup, movsxd_mode } }, 0 },
   },
 
   /* X86_64_6D */
@@ -13536,6 +13538,13 @@ intel_operand_size (int bytemode, int sizeflag)
 	oappend ("DWORD PTR ");
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
+    case movsxd_mode:
+      if (!(sizeflag & DFLAG) && isa64 == intel64)
+	oappend ("WORD PTR ");
+      else
+	oappend ("DWORD PTR ");
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     case d_mode:
     case d_scalar_mode:
     case d_scalar_swap_mode:
@@ -13921,6 +13930,13 @@ OP_E_register (int bytemode, int sizeflag)
 	  used_prefixes |= (prefixes & PREFIX_DATA);
 	}
       break;
+    case movsxd_mode:
+      if (!(sizeflag & DFLAG) && isa64 == intel64)
+	names = names16;
+      else
+	names = names32;
+      used_prefixes |= (prefixes & PREFIX_DATA);
+      break;
     case va_mode:
       names = (address_mode == mode_64bit
 	       ? names64 : names32);
@@ -14492,12 +14508,14 @@ OP_G (int bytemode, int sizeflag)
     case dqb_mode:
     case dqd_mode:
     case dqw_mode:
+    case movsxd_mode:
       USED_REX (REX_W);
       if (rex & REX_W)
 	oappend (names64[modrm.reg + add]);
       else
 	{
-	  if ((sizeflag & DFLAG) || bytemode != v_mode)
+	  if ((sizeflag & DFLAG)
+	      || (bytemode != v_mode && bytemode != movsxd_mode))
 	    oappend (names32[modrm.reg + add]);
 	  else
 	    oappend (names16[modrm.reg + add]);
@@ -16563,6 +16581,45 @@ skip:
   OP_M (bytemode, sizeflag);
 }
 
+static void
+MOVSXD_Fixup (int bytemode, int sizeflag)
+{
+  /* Add proper suffix to "movsxd".  */
+  char *p = mnemonicendp;
+
+  switch (bytemode)
+    {
+    case movsxd_mode:
+      if (intel_syntax)
+	{
+	  *p++ = 'x';
+	  *p++ = 'd';
+	  goto skip;
+	}
+
+      USED_REX (REX_W);
+      if (rex & REX_W)
+	{
+	  *p++ = 'l';
+	  *p++ = 'q';
+	}
+      else
+	{
+	  *p++ = 'x';
+	  *p++ = 'd';
+	}
+      break;
+    default:
+      oappend (INTERNAL_DISASSEMBLER_ERROR);
+      break;
+    }
+
+skip:
+  mnemonicendp = p;
+  *p = '\0';
+  OP_E (bytemode, sizeflag);
+}
+
 static void
 OP_LWPCB_E (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 2acb76bfa15..19793fdcd45 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -135,7 +135,9 @@ movsx, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf|R
 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 }
-movsxd, 2, 0x63, None, 1, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf|Rex64, { Reg32|Dword|Unspecified|BaseIndex, 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 }
 
 // Move with zero extend.
 movzb, 2, 0xfb6, None, 2, Cpu386, Modrm|No_bSuf|No_sSuf|No_ldSuf, { Reg8|Byte|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index c8fa7e95a00..d1a6c0915a9 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -435,12 +435,40 @@ const insn_template i386_optab[] =
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
-    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
-      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
     { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0,
 	  0, 0, 0, 0, 1, 0 } },
-      { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+      { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+	  0, 0, 0, 0, 0, 0 } } } },
+  { "movsxd", 0x63, None, 1, 2,
+    { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
+    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
+    { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0,
+	  0, 0, 0, 0, 1, 0 } },
+      { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+	  0, 0, 0, 0, 0, 0 } } } },
+  { "movsxd", 0x63, None, 1, 2,
+    { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } },
+    { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+    { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
+	  0, 0, 0, 0, 1, 0 } },
+      { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
 	  0, 0, 0, 0, 0, 0 } } } },
   { "movzb", 0xfb6, None, 2, 2,
     { { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-- 
2.24.1



More information about the Binutils mailing list