From d276ec695e8954330e922807d6886b8212d6323b Mon Sep 17 00:00:00 2001
From: Jan Beulich <jbeulich@novell.com>
Date: Thu, 13 Sep 2018 11:03:35 +0200
Subject: [PATCH] x86-64: bndmk, bndldx, and bndstx don't allow RIP-relative
 addressing

---
 gas/ChangeLog                       |  6 ++++++
 gas/testsuite/gas/i386/x86-64-mpx.d |  1 +
 gas/testsuite/gas/i386/x86-64-mpx.s |  7 +++++++
 opcodes/ChangeLog                   |  7 +++++++
 opcodes/i386-dis.c                  | 17 ++++++++++++++---
 5 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 84895bec800..8675e2fe75a 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2018-09-13  Jan Beulich  <jbeulich@suse.com>
+
+	* testsuite/gas/i386/x86-64-mpx.s: And BNDMK case with RIP-
+	relative memory operand.
+	* testsuite/gas/i386/x86-64-mpx.d: Adjust expectations.
+
 2018-09-13  Nick Clifton  <nickc@redhat.com>
 
 	* dwarf2dbg.c (generic_dwarf2_emit_offset): Use memset to
diff --git a/gas/testsuite/gas/i386/x86-64-mpx.d b/gas/testsuite/gas/i386/x86-64-mpx.d
index e2a7828b69d..bb83adcbf51 100644
--- a/gas/testsuite/gas/i386/x86-64-mpx.d
+++ b/gas/testsuite/gas/i386/x86-64-mpx.d
@@ -186,4 +186,5 @@ Disassembly of section .text:
 [a-f0-9]+ <bad>:
 [ 	]*[a-f0-9]+:	0f 1a 30             	bndldx \(%rax\),\(bad\)
 [ 	]*[a-f0-9]+:	66 0f 1a c4          	bndmov \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	f3 0f 1b 05 90 90 90 90 	bndmk  \(bad\),%bnd0
 #pass
diff --git a/gas/testsuite/gas/i386/x86-64-mpx.s b/gas/testsuite/gas/i386/x86-64-mpx.s
index 1263408f3d9..726e35ab354 100644
--- a/gas/testsuite/gas/i386/x86-64-mpx.s
+++ b/gas/testsuite/gas/i386/x86-64-mpx.s
@@ -221,3 +221,10 @@ bad:
 	.byte 0x0f
 	.byte 0x1a
 	.byte 0xc4
+
+	# bndmk (bad),%bnd0
+	.byte 0xf3
+	.byte 0x0f
+	.byte 0x1b
+	.byte 0x05
+	.long 0x90909090
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 1e59d0093b7..870e8fcc320 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,10 @@
+2018-09-13  Jan Beulich  <jbeulich@suse.com>
+
+	* i386-dis.c (Mv_bnd, v_bndmk_mode): New.
+	(mod_table): Use Mv_bnd for bndldx, bndstx, and bndmk.
+	(intel_operand_size): Handle v_bndmk_mode.
+	(OP_E_memory): Likewise. Produce (bad) when also riprel.
+
 2018-09-08  John Darrington  <john@darrington.wattle.id.au>
 
 	* disassemble.c (ARCH_s12z): Define if ARCH_all.
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 77f2e2a3d37..930569e0f73 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -273,6 +273,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Mo { OP_M, o_mode }
 #define Mp { OP_M, f_mode }		/* 32 or 48 bit memory operand for LDS, LES etc */
 #define Mq { OP_M, q_mode }
+#define Mv_bnd { OP_M, v_bndmk_mode }
 #define Mx { OP_M, x_mode }
 #define Mxmm { OP_M, xmm_mode }
 #define Gb { OP_G, b_mode }
@@ -561,6 +562,8 @@ enum
   cond_jump_mode,
   loop_jcxz_mode,
   v_bnd_mode,
+  /* like v_bnd_mode in 32bit, no RIP-rel in 64bit mode.  */
+  v_bndmk_mode,
   /* operand size depends on REX prefixes.  */
   dq_mode,
   /* registers like dq_mode, memory like w_mode.  */
@@ -11646,17 +11649,17 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_0F1A_PREFIX_0 */
-    { "bndldx",		{ Gbnd, Ev_bnd }, 0 },
+    { "bndldx",		{ Gbnd, Mv_bnd }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
   {
     /* MOD_0F1B_PREFIX_0 */
-    { "bndstx",		{ Ev_bnd, Gbnd }, 0 },
+    { "bndstx",		{ Mv_bnd, Gbnd }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
   {
     /* MOD_0F1B_PREFIX_1 */
-    { "bndmk",		{ Gbnd, Ev_bnd }, 0 },
+    { "bndmk",		{ Gbnd, Mv_bnd }, 0 },
     { "nopQ",		{ Ev }, 0 },
   },
   {
@@ -15083,6 +15086,7 @@ intel_operand_size (int bytemode, int sizeflag)
 	oappend ("WORD PTR ");
       break;
     case v_bnd_mode:
+    case v_bndmk_mode:
     default:
       break;
     }
@@ -15343,6 +15347,7 @@ OP_E_memory (int bytemode, int sizeflag)
       int scale = 0;
       int addr32flag = !((sizeflag & AFLAG)
 			 || bytemode == v_bnd_mode
+			 || bytemode == v_bndmk_mode
 			 || bytemode == bnd_mode
 			 || bytemode == bnd_swap_mode);
       const char **indexes64 = names64;
@@ -15419,6 +15424,11 @@ OP_E_memory (int bytemode, int sizeflag)
 	      if (address_mode == mode_64bit && !havesib)
 		riprel = 1;
 	      disp = get32s ();
+	      if (riprel && bytemode == v_bndmk_mode)
+		{
+		  oappend ("(bad)");
+		  return;
+		}
 	    }
 	  break;
 	case 1:
@@ -15476,6 +15486,7 @@ OP_E_memory (int bytemode, int sizeflag)
 
       if ((havebase || haveindex || needaddr32 || riprel)
 	  && (bytemode != v_bnd_mode)
+	  && (bytemode != v_bndmk_mode)
 	  && (bytemode != bnd_mode)
 	  && (bytemode != bnd_swap_mode))
 	used_prefixes |= PREFIX_ADDR;