x86: Add {rex} pseudo prefix

Message ID 20180222122003.GA10022@gmail.com
State New
Headers show
Series
  • x86: Add {rex} pseudo prefix
Related show

Commit Message

H.J. Lu Feb. 22, 2018, 12:20 p.m.
Add {rex} pseudo prefix to generate a REX byte for integer and legacy
vector instructions if possible.

Any comments?

H.J.
---
gas/

	* config/tc-i386.c (_i386_insn): Add rex_encoding.
	(md_assemble): When i.rex_encoding is true, generate a REX byte
	if possible.
	(parse_insn): Set i.rex_encoding for {rex}.
	* doc/c-i386.texi: Document {rex}.
	* testsuite/gas/i386/x86-64-pseudos.s: Add {rex} tests.
	* testsuite/gas/i386/x86-64-pseudos.d: Updated

opcodes/

	* i386-opc.tbl: Add {rex},
	* i386-tbl.h: Regenerated.
---
 gas/config/tc-i386.c                    | 27 +++++++++++++++++++++++++++
 gas/doc/c-i386.texi                     |  4 ++++
 gas/testsuite/gas/i386/x86-64-pseudos.d | 26 ++++++++++++++++++++++++++
 gas/testsuite/gas/i386/x86-64-pseudos.s | 26 ++++++++++++++++++++++++++
 opcodes/i386-opc.tbl                    |  1 +
 opcodes/i386-tbl.h                      | 14 ++++++++++++++
 6 files changed, 98 insertions(+)

-- 
2.14.3

Comments

Jan Beulich Feb. 22, 2018, 12:28 p.m. | #1
>>> On 22.02.18 at 13:20, <hjl.tools@gmail.com> wrote:

> Add {rex} pseudo prefix to generate a REX byte for integer and legacy

> vector instructions if possible.

> 

> Any comments?


Would you mind adding a sentence as to the difference to the
plain (without the braces) prefix, both above and in the doc entry?

Jan
H.J. Lu Feb. 22, 2018, 12:40 p.m. | #2
On Thu, Feb 22, 2018 at 4:28 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 22.02.18 at 13:20, <hjl.tools@gmail.com> wrote:

>> Add {rex} pseudo prefix to generate a REX byte for integer and legacy

>> vector instructions if possible.

>>

>> Any comments?

>

> Would you mind adding a sentence as to the difference to the

> plain (without the braces) prefix, both above and in the doc entry?

>


Sure.  Here it is.


-- 
H.J.
From 197f79711c7f9fb4246c051561c0bd0eeb82eaed Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 21 Feb 2018 16:04:44 -0800
Subject: [PATCH] x86: Add {rex} pseudo prefix

Add {rex} pseudo prefix to generate a REX byte for integer and legacy
vector instructions if possible.  Note that this differs from the rex
prefix which generates REX prefix unconditionally.

gas/

	* config/tc-i386.c (_i386_insn): Add rex_encoding.
	(md_assemble): When i.rex_encoding is true, generate a REX byte
	if possible.
	(parse_insn): Set i.rex_encoding for {rex}.
	* doc/c-i386.texi: Document {rex}.
	* testsuite/gas/i386/x86-64-pseudos.s: Add {rex} tests.
	* testsuite/gas/i386/x86-64-pseudos.d: Updated

opcodes/

	* i386-opc.tbl: Add {rex},
	* i386-tbl.h: Regenerated.
---
 gas/config/tc-i386.c                    | 27 +++++++++++++++++++++++++++
 gas/doc/c-i386.texi                     |  5 +++++
 gas/testsuite/gas/i386/x86-64-pseudos.d | 26 ++++++++++++++++++++++++++
 gas/testsuite/gas/i386/x86-64-pseudos.s | 26 ++++++++++++++++++++++++++
 opcodes/i386-opc.tbl                    |  1 +
 opcodes/i386-tbl.h                      | 14 ++++++++++++++
 6 files changed, 99 insertions(+)

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c67ea1f224..dff42bdb91 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -369,6 +369,9 @@ struct _i386_insn
 	disp_encoding_32bit
       } disp_encoding;
 
+    /* Prefer the REX byte in encoding.  */
+    bfd_boolean rex_encoding;
+
     /* How to encode vector instructions.  */
     enum
       {
@@ -3992,6 +3995,26 @@ md_assemble (char *line)
 	}
     }
 
+  if (i.rex == 0 && i.rex_encoding)
+    {
+      /* Check if we can add a REX_OPCODE byte.  Look for 8 bit operand
+         that uses legacy register.  If it is "hi" register, don't add
+	 the REX_OPCODE byte.  */
+      int x;
+      for (x = 0; x < 2; x++)
+	if (i.types[x].bitfield.reg
+	    && i.types[x].bitfield.byte
+	    && (i.op[x].regs->reg_flags & RegRex64) == 0
+	    && i.op[x].regs->reg_num > 3)
+	  {
+	    i.rex_encoding = FALSE;
+	    break;
+	  }
+
+      if (i.rex_encoding)
+	i.rex = REX_OPCODE;
+    }
+
   if (i.rex != 0)
     add_prefix (REX_OPCODE | i.rex);
 
@@ -4104,6 +4127,10 @@ parse_insn (char *line, char *mnemonic)
 		  /* {evex} */
 		  i.vec_encoding = vex_encoding_evex;
 		  break;
+		case 0x7:
+		  /* {rex} */
+		  i.rex_encoding = TRUE;
+		  break;
 		default:
 		  abort ();
 		}
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index e669c5f34f..6b2def0457 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -642,6 +642,11 @@ Different encoding options can be specified via pseudo prefixes:
 
 @item
 @samp{@{evex@}} --  encode with EVEX prefix.
+
+@item
+@samp{@{rex@}} -- prefer REX prefix for integer and legacy vector
+instructions (x86-64 only).  Note that this differs from the @samp{rex}
+prefix which generates REX prefix unconditionally.
 @end itemize
 
 @cindex conversion instructions, i386
diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.d b/gas/testsuite/gas/i386/x86-64-pseudos.d
index c63a0a1150..de8c8eb46c 100644
--- a/gas/testsuite/gas/i386/x86-64-pseudos.d
+++ b/gas/testsuite/gas/i386/x86-64-pseudos.d
@@ -35,6 +35,19 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
+ +[a-f0-9]+:	88 c4                	mov    %al,%ah
+ +[a-f0-9]+:	40 89 c3             	rex mov %eax,%ebx
+ +[a-f0-9]+:	41 89 c6             	mov    %eax,%r14d
+ +[a-f0-9]+:	41 89 00             	mov    %eax,\(%r8\)
+ +[a-f0-9]+:	40 0f 28 d7          	rex movaps %xmm7,%xmm2
+ +[a-f0-9]+:	44 0f 28 e7          	movaps %xmm7,%xmm12
+ +[a-f0-9]+:	40 0f 28 11          	rex movaps \(%rcx\),%xmm2
+ +[a-f0-9]+:	41 0f 28 10          	movaps \(%r8\),%xmm2
+ +[a-f0-9]+:	40 0f 38 01 01       	rex phaddw \(%rcx\),%mm0
+ +[a-f0-9]+:	41 0f 38 01 00       	phaddw \(%r8\),%mm0
+ +[a-f0-9]+:	c5 f8 28 d7          	vmovaps %xmm7,%xmm2
+ +[a-f0-9]+:	62 b1 7c 08 28 d1    	vmovaps %xmm17,%xmm2
+ +[a-f0-9]+:	c4 e3 7b f0 d8 07    	rorx   \$0x7,%eax,%ebx
  +[a-f0-9]+:	c4 e1 78 28 d7       	vmovaps %xmm7,%xmm2
  +[a-f0-9]+:	c4 e1 78 28 d7       	vmovaps %xmm7,%xmm2
  +[a-f0-9]+:	c4 e1 78 29 fa       	vmovaps %xmm7,%xmm2
@@ -63,4 +76,17 @@ Disassembly of section .text:
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
+ +[a-f0-9]+:	88 c4                	mov    %al,%ah
+ +[a-f0-9]+:	40 89 c3             	rex mov %eax,%ebx
+ +[a-f0-9]+:	41 89 c6             	mov    %eax,%r14d
+ +[a-f0-9]+:	41 89 00             	mov    %eax,\(%r8\)
+ +[a-f0-9]+:	40 0f 28 d7          	rex movaps %xmm7,%xmm2
+ +[a-f0-9]+:	44 0f 28 e7          	movaps %xmm7,%xmm12
+ +[a-f0-9]+:	40 0f 28 11          	rex movaps \(%rcx\),%xmm2
+ +[a-f0-9]+:	41 0f 28 10          	movaps \(%r8\),%xmm2
+ +[a-f0-9]+:	40 0f 38 01 01       	rex phaddw \(%rcx\),%mm0
+ +[a-f0-9]+:	41 0f 38 01 00       	phaddw \(%r8\),%mm0
+ +[a-f0-9]+:	c5 f8 28 d7          	vmovaps %xmm7,%xmm2
+ +[a-f0-9]+:	62 b1 7c 08 28 d1    	vmovaps %xmm17,%xmm2
+ +[a-f0-9]+:	c4 e3 7b f0 d8 07    	rorx   \$0x7,%eax,%ebx
 #pass
diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.s b/gas/testsuite/gas/i386/x86-64-pseudos.s
index c0ee8dcab9..c2137698ad 100644
--- a/gas/testsuite/gas/i386/x86-64-pseudos.s
+++ b/gas/testsuite/gas/i386/x86-64-pseudos.s
@@ -30,6 +30,19 @@ _start:
 	movaps 128(%rax),%xmm2
 	{disp8} movaps 128(%rax),%xmm2
 	{disp32} movaps 128(%rax),%xmm2
+	{rex} mov %al,%ah
+	{rex} movl %eax,%ebx
+	{rex} movl %eax,%r14d
+	{rex} movl %eax,(%r8)
+	{rex} movaps %xmm7,%xmm2
+	{rex} movaps %xmm7,%xmm12
+	{rex} movaps (%rcx),%xmm2
+	{rex} movaps (%r8),%xmm2
+	{rex} phaddw (%rcx),%mm0
+	{rex} phaddw (%r8),%mm0
+	{rex} vmovaps %xmm7,%xmm2
+	{rex} vmovaps %xmm17,%xmm2
+	{rex} rorx $7,%eax,%ebx
 
 	.intel_syntax noprefix
 	{vex3} vmovaps xmm2,xmm7
@@ -60,3 +73,16 @@ _start:
 	movaps xmm2,XMMWORD PTR [rax+128]
 	{disp8} movaps xmm2,XMMWORD PTR [rax+128]
 	{disp32} movaps xmm2,XMMWORD PTR [rax+128]
+	{rex} mov ah,al
+	{rex} mov ebx,eax
+	{rex} mov r14d,eax
+	{rex} mov DWORD PTR [r8],eax
+	{rex} movaps xmm2,xmm7
+	{rex} movaps xmm12,xmm7
+	{rex} movaps xmm2,XMMWORD PTR [rcx]
+	{rex} movaps xmm2,XMMWORD PTR [r8]
+	{rex} phaddw mm0,QWORD PTR [rcx]
+	{rex} phaddw mm0,QWORD PTR [r8]
+	{rex} vmovaps xmm2,xmm7
+	{rex} vmovaps xmm2,xmm17
+	{rex} rorx ebx,eax,0x7
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 481e99f097..450350556f 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -829,6 +829,7 @@ rex.wrxb, 0, 0x4f, None, 1, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ld
 {vex2}, 0, 0x4, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 {vex3}, 0, 0x5, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 {evex}, 0, 0x6, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
+{rex}, 0, 0x7, None, 0, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 
 // 486 extensions.
 
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index f0b9241581..edb32fdaef 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -9293,6 +9293,20 @@ 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 } } } },
+  { "{rex}", 0, 0x7, None, 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, 0, 0, 0, 0, 0, 0, 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, 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, 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 } } } },
   { "bswap", 1, 0xfc8, None, 2,
     { { 0, 0, 0, 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,
Jan Beulich Feb. 22, 2018, 1:31 p.m. | #3
>>> On 22.02.18 at 13:40, <hjl.tools@gmail.com> wrote:

> On Thu, Feb 22, 2018 at 4:28 AM, Jan Beulich <JBeulich@suse.com> wrote:

>>>>> On 22.02.18 at 13:20, <hjl.tools@gmail.com> wrote:

>>> Add {rex} pseudo prefix to generate a REX byte for integer and legacy

>>> vector instructions if possible.

>>>

>>> Any comments?

>>

>> Would you mind adding a sentence as to the difference to the

>> plain (without the braces) prefix, both above and in the doc entry?

>>

> 

> Sure.  Here it is.


Thanks, LGTM FWIW.

Jan
H.J. Lu Feb. 22, 2018, 2:16 p.m. | #4
On Thu, Feb 22, 2018 at 5:31 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 22.02.18 at 13:40, <hjl.tools@gmail.com> wrote:

>> On Thu, Feb 22, 2018 at 4:28 AM, Jan Beulich <JBeulich@suse.com> wrote:

>>>>>> On 22.02.18 at 13:20, <hjl.tools@gmail.com> wrote:

>>>> Add {rex} pseudo prefix to generate a REX byte for integer and legacy

>>>> vector instructions if possible.

>>>>

>>>> Any comments?

>>>

>>> Would you mind adding a sentence as to the difference to the

>>> plain (without the braces) prefix, both above and in the doc entry?

>>>

>>

>> Sure.  Here it is.

>

> Thanks, LGTM FWIW.

>


I am checking it in.


-- 
H.J.

Patch

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c67ea1f224..dff42bdb91 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -369,6 +369,9 @@  struct _i386_insn
 	disp_encoding_32bit
       } disp_encoding;
 
+    /* Prefer the REX byte in encoding.  */
+    bfd_boolean rex_encoding;
+
     /* How to encode vector instructions.  */
     enum
       {
@@ -3992,6 +3995,26 @@  md_assemble (char *line)
 	}
     }
 
+  if (i.rex == 0 && i.rex_encoding)
+    {
+      /* Check if we can add a REX_OPCODE byte.  Look for 8 bit operand
+         that uses legacy register.  If it is "hi" register, don't add
+	 the REX_OPCODE byte.  */
+      int x;
+      for (x = 0; x < 2; x++)
+	if (i.types[x].bitfield.reg
+	    && i.types[x].bitfield.byte
+	    && (i.op[x].regs->reg_flags & RegRex64) == 0
+	    && i.op[x].regs->reg_num > 3)
+	  {
+	    i.rex_encoding = FALSE;
+	    break;
+	  }
+
+      if (i.rex_encoding)
+	i.rex = REX_OPCODE;
+    }
+
   if (i.rex != 0)
     add_prefix (REX_OPCODE | i.rex);
 
@@ -4104,6 +4127,10 @@  parse_insn (char *line, char *mnemonic)
 		  /* {evex} */
 		  i.vec_encoding = vex_encoding_evex;
 		  break;
+		case 0x7:
+		  /* {rex} */
+		  i.rex_encoding = TRUE;
+		  break;
 		default:
 		  abort ();
 		}
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index e669c5f34f..dbbe61346c 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -642,6 +642,10 @@  Different encoding options can be specified via pseudo prefixes:
 
 @item
 @samp{@{evex@}} --  encode with EVEX prefix.
+
+@item
+@samp{@{rex@}} -- prefer REX prefix for integer and legacy vector
+instructions (x86-64 only).
 @end itemize
 
 @cindex conversion instructions, i386
diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.d b/gas/testsuite/gas/i386/x86-64-pseudos.d
index c63a0a1150..de8c8eb46c 100644
--- a/gas/testsuite/gas/i386/x86-64-pseudos.d
+++ b/gas/testsuite/gas/i386/x86-64-pseudos.d
@@ -35,6 +35,19 @@  Disassembly of section .text:
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
+ +[a-f0-9]+:	88 c4                	mov    %al,%ah
+ +[a-f0-9]+:	40 89 c3             	rex mov %eax,%ebx
+ +[a-f0-9]+:	41 89 c6             	mov    %eax,%r14d
+ +[a-f0-9]+:	41 89 00             	mov    %eax,\(%r8\)
+ +[a-f0-9]+:	40 0f 28 d7          	rex movaps %xmm7,%xmm2
+ +[a-f0-9]+:	44 0f 28 e7          	movaps %xmm7,%xmm12
+ +[a-f0-9]+:	40 0f 28 11          	rex movaps \(%rcx\),%xmm2
+ +[a-f0-9]+:	41 0f 28 10          	movaps \(%r8\),%xmm2
+ +[a-f0-9]+:	40 0f 38 01 01       	rex phaddw \(%rcx\),%mm0
+ +[a-f0-9]+:	41 0f 38 01 00       	phaddw \(%r8\),%mm0
+ +[a-f0-9]+:	c5 f8 28 d7          	vmovaps %xmm7,%xmm2
+ +[a-f0-9]+:	62 b1 7c 08 28 d1    	vmovaps %xmm17,%xmm2
+ +[a-f0-9]+:	c4 e3 7b f0 d8 07    	rorx   \$0x7,%eax,%ebx
  +[a-f0-9]+:	c4 e1 78 28 d7       	vmovaps %xmm7,%xmm2
  +[a-f0-9]+:	c4 e1 78 28 d7       	vmovaps %xmm7,%xmm2
  +[a-f0-9]+:	c4 e1 78 29 fa       	vmovaps %xmm7,%xmm2
@@ -63,4 +76,17 @@  Disassembly of section .text:
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
  +[a-f0-9]+:	0f 28 90 80 00 00 00 	movaps 0x80\(%rax\),%xmm2
+ +[a-f0-9]+:	88 c4                	mov    %al,%ah
+ +[a-f0-9]+:	40 89 c3             	rex mov %eax,%ebx
+ +[a-f0-9]+:	41 89 c6             	mov    %eax,%r14d
+ +[a-f0-9]+:	41 89 00             	mov    %eax,\(%r8\)
+ +[a-f0-9]+:	40 0f 28 d7          	rex movaps %xmm7,%xmm2
+ +[a-f0-9]+:	44 0f 28 e7          	movaps %xmm7,%xmm12
+ +[a-f0-9]+:	40 0f 28 11          	rex movaps \(%rcx\),%xmm2
+ +[a-f0-9]+:	41 0f 28 10          	movaps \(%r8\),%xmm2
+ +[a-f0-9]+:	40 0f 38 01 01       	rex phaddw \(%rcx\),%mm0
+ +[a-f0-9]+:	41 0f 38 01 00       	phaddw \(%r8\),%mm0
+ +[a-f0-9]+:	c5 f8 28 d7          	vmovaps %xmm7,%xmm2
+ +[a-f0-9]+:	62 b1 7c 08 28 d1    	vmovaps %xmm17,%xmm2
+ +[a-f0-9]+:	c4 e3 7b f0 d8 07    	rorx   \$0x7,%eax,%ebx
 #pass
diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.s b/gas/testsuite/gas/i386/x86-64-pseudos.s
index c0ee8dcab9..c2137698ad 100644
--- a/gas/testsuite/gas/i386/x86-64-pseudos.s
+++ b/gas/testsuite/gas/i386/x86-64-pseudos.s
@@ -30,6 +30,19 @@  _start:
 	movaps 128(%rax),%xmm2
 	{disp8} movaps 128(%rax),%xmm2
 	{disp32} movaps 128(%rax),%xmm2
+	{rex} mov %al,%ah
+	{rex} movl %eax,%ebx
+	{rex} movl %eax,%r14d
+	{rex} movl %eax,(%r8)
+	{rex} movaps %xmm7,%xmm2
+	{rex} movaps %xmm7,%xmm12
+	{rex} movaps (%rcx),%xmm2
+	{rex} movaps (%r8),%xmm2
+	{rex} phaddw (%rcx),%mm0
+	{rex} phaddw (%r8),%mm0
+	{rex} vmovaps %xmm7,%xmm2
+	{rex} vmovaps %xmm17,%xmm2
+	{rex} rorx $7,%eax,%ebx
 
 	.intel_syntax noprefix
 	{vex3} vmovaps xmm2,xmm7
@@ -60,3 +73,16 @@  _start:
 	movaps xmm2,XMMWORD PTR [rax+128]
 	{disp8} movaps xmm2,XMMWORD PTR [rax+128]
 	{disp32} movaps xmm2,XMMWORD PTR [rax+128]
+	{rex} mov ah,al
+	{rex} mov ebx,eax
+	{rex} mov r14d,eax
+	{rex} mov DWORD PTR [r8],eax
+	{rex} movaps xmm2,xmm7
+	{rex} movaps xmm12,xmm7
+	{rex} movaps xmm2,XMMWORD PTR [rcx]
+	{rex} movaps xmm2,XMMWORD PTR [r8]
+	{rex} phaddw mm0,QWORD PTR [rcx]
+	{rex} phaddw mm0,QWORD PTR [r8]
+	{rex} vmovaps xmm2,xmm7
+	{rex} vmovaps xmm2,xmm17
+	{rex} rorx ebx,eax,0x7
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 481e99f097..450350556f 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -829,6 +829,7 @@  rex.wrxb, 0, 0x4f, None, 1, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ld
 {vex2}, 0, 0x4, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 {vex3}, 0, 0x5, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 {evex}, 0, 0x6, None, 0, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
+{rex}, 0, 0x7, None, 0, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
 
 // 486 extensions.
 
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index f0b9241581..edb32fdaef 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -9293,6 +9293,20 @@  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 } } } },
+  { "{rex}", 0, 0x7, None, 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, 0, 0, 0, 0, 0, 0, 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, 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, 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 } } } },
   { "bswap", 1, 0xfc8, None, 2,
     { { 0, 0, 0, 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,