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 v2] x86: ignore high register select bit(s) in 32- and 16-bit modes


While commits 9889cbb14e ("Check invalid mask registers") and
abfcb414b9 ("X86: Ignore REX_B bit for 32-bit XOP instructions") went a
bit into the right direction, this wasn't quite enough:
- VEX.vvvv has its high bit ignored
- EVEX.vvvv has its high bit ignored together with EVEX.v'
- the high bits of {,E}VEX.vvvv should not be prematurely zapped, to
  allow proper checking of them when the fields has to hold al ones
- when the high bits of an immediate specify a register, bit 7 is
  ignored
---
v2: Parts of the test were moved to earlier, already approved (and
    committed) patches.

gas/
2017-11-15  Jan Beulich  <jbeulich@suse.com>

	* testsuite/gas/i386/noextreg.s: Add tests with register index
	bit 3 set.
	* testsuite/gas/i386/noextreg.d: Adjust expectations.

opcodes/
2017-11-15  Jan Beulich  <jbeulich@suse.com>

	(get_valid_dis386): Never flag bad opcode when
	vex.register_specifier is beyond 7. Always store all four
	bits of it. Move 16-/32-bit override in EVEX handling after
	all to be overridden bits have been set.
	(OP_VEX): Mask vex.register_specifier outside of 64-bit mode.
	Use rex to determine GPR register set.
	(OP_EX_VexReg, OP_Vex_2src_1, OP_Vex_2src_2, OP_REG_VexI4,
	OP_LWP_E): Mask vex.register_specifier outside of 64-bit mode.

--- a/gas/testsuite/gas/i386/noextreg.d
+++ b/gas/testsuite/gas/i386/noextreg.d
@@ -6,13 +6,48 @@
 Disassembly of section .text:
 
 0+ <ix86>:
+[ 	]*[a-f0-9]+:	c5 f9 db c0          	vpand  %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 c1 79 db c0       	vpand  %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 c1 39 db c0       	vpand  %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	62 f1 7d 08 db c0    	vpandd %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	62 d1 7d 08 db c0    	vpandd %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	62 f1 3d 08 db c0    	vpandd %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	62 f1 7d 00 db c0    	vpandd %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 79 4c c0 00    	vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 c3 79 4c c0 00    	vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 39 4c c0 00    	vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 79 4c c0 80    	vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	62 f2 7d 0f 90 0c 00 	vpgatherdd \(%eax,%xmm0(,1)?\),%xmm1\{%k7\}
+[ 	]*[a-f0-9]+:	62 d2 7d 0f 90 0c 00 	vpgatherdd \(%eax,%xmm0(,1)?\),%xmm1\{%k7\}
+[ 	]*[a-f0-9]+:	62 f2 7d 07 90 0c 00 	vpgatherdd \(%eax,%xmm0(,1)?\),%xmm1\{%k7\}
 [ 	]*[a-f0-9]+:	c4 e2 78 f2 00       	andn   \(%eax\),%eax,%eax
+[ 	]*[a-f0-9]+:	c4 e2 38 f2 00       	andn   \(%eax\),%eax,%eax
+[ 	]*[a-f0-9]+:	c4 c2 78 f2 00       	andn   \(%eax\),%eax,%eax
 [ 	]*[a-f0-9]+:	c4 e2 f8 f2 00       	andn   \(%eax\),%eax,%eax
 [ 	]*[a-f0-9]+:	8f e9 78 01 20       	tzmsk  \(%eax\),%eax
+[ 	]*[a-f0-9]+:	8f c9 78 01 20       	tzmsk  \(%eax\),%eax
+[ 	]*[a-f0-9]+:	8f e9 38 01 20       	tzmsk  \(%eax\),%eax
 [ 	]*[a-f0-9]+:	8f e9 f8 01 20       	tzmsk  \(%eax\),%eax
 [ 	]*[a-f0-9]+:	8f e9 78 12 c0       	llwpcb %eax
+[ 	]*[a-f0-9]+:	8f c9 78 12 c0       	llwpcb %eax
 [ 	]*[a-f0-9]+:	8f e9 f8 12 c0       	llwpcb %eax
+[ 	]*[a-f0-9]+:	8f e8 78 c0 c0 01    	vprotb \$(0x)?1,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f e8 78 c0 00 01    	vprotb \$(0x)?1,\(%eax\),%xmm0
+[ 	]*[a-f0-9]+:	8f e9 78 90 c0       	vprotb %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f e9 78 90 00       	vprotb %xmm0,\(%eax\),%xmm0
+[ 	]*[a-f0-9]+:	8f e9 f8 90 00       	vprotb \(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f c8 78 c0 c0 01    	vprotb \$(0x)?1,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f c8 78 c0 00 01    	vprotb \$(0x)?1,\(%eax\),%xmm0
+[ 	]*[a-f0-9]+:	8f c9 b8 90 c0       	vprotb %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f c9 78 90 00       	vprotb %xmm0,\(%eax\),%xmm0
+[ 	]*[a-f0-9]+:	8f e9 38 90 c0       	vprotb %xmm0,%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	8f c9 f8 90 00       	vprotb \(%eax\),%xmm0,%xmm0
 [ 	]*[a-f0-9]+:	c4 e3 79 68 00 00    	vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 39 68 00 00    	vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 79 68 00 80    	vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
 [ 	]*[a-f0-9]+:	c4 e3 79 68 00 0f    	vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 79 48 00 00    	vpermil2ps \$(0x)?0,%xmm0,\(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 39 48 00 00    	vpermil2ps \$(0x)?0,%xmm0,\(%eax\),%xmm0,%xmm0
+[ 	]*[a-f0-9]+:	c4 e3 79 48 00 80    	vpermil2ps \$(0x)?0,%xmm0,\(%eax\),%xmm0,%xmm0
 [ 	]*[a-f0-9]+:	c3                   	ret[ 	]*
 #pass
--- a/gas/testsuite/gas/i386/noextreg.s
+++ b/gas/testsuite/gas/i386/noextreg.s
@@ -1,24 +1,79 @@
 	.intel_syntax noprefix
 	.text
 ix86:
+	vpand	xmm0, xmm0, xmm0
+	.code64
+	vpand	xmm0, xmm0, xmm8
+	vpand	xmm0, xmm8, xmm8
+	.code32
+
+	vpandd	xmm0, xmm0, xmm0
+	.code64
+	vpandd	xmm0, xmm0, xmm8
+	vpandd	xmm0, xmm8, xmm0
+	vpandd	xmm0, xmm16, xmm0
+	.code32
+
+	vpblendvb xmm0, xmm0, xmm0, xmm0
+	.code64
+	vpblendvb xmm0, xmm0, xmm8, xmm0
+	vpblendvb xmm0, xmm8, xmm0, xmm0
+	vpblendvb xmm0, xmm0, xmm0, xmm8
+	.code32
+
+	vpgatherdd xmm1{k7}, [eax+xmm0]
+	.code64
+	vpgatherdd xmm1{k7}, [r8+xmm0]
+	vpgatherdd xmm1{k7}, [rax+xmm16]
+	.code32
+
 	andn	eax, eax, [eax]
 	.code64
+	andn	eax, r8d, [rax]
+	andn	eax, eax, [r8]
 	andn	rax, rax, [rax]
 	.code32
 
 	tzmsk	eax, [eax]
 	.code64
+	tzmsk	eax, [r8]
+	tzmsk	r8d, [rax]
 	tzmsk	rax, [rax]
 	.code32
 
 	llwpcb	eax
 	.code64
+	llwpcb	r8d
 	llwpcb	rax
 	.code32
 
+	vprotb	xmm0, xmm0, 1
+	vprotb	xmm0, [eax], 1
+	vprotb	xmm0, xmm0, xmm0
+	vprotb	xmm0, [eax], xmm0
+	vprotb	xmm0, xmm0, [eax]
+	.code64
+	vprotb	xmm0, xmm8, 1
+	vprotb	xmm0, [r8], 1
+	.byte	0x8f, 0xc9, 0xb8, 0x90, 0xc0		 # vprotb xmm0, xmm8, xmm0
+	vprotb	xmm0, [r8], xmm0
+	vprotb	xmm0, xmm0, xmm8
+	vprotb	xmm0, xmm0, [r8]
+	.code32
+
 	vfmaddps xmm0, xmm0, [eax], xmm0
+	.code64
+	vfmaddps xmm0, xmm8, [rax], xmm0
+	vfmaddps xmm0, xmm0, [rax], xmm8
+	.code32
 	.byte	0xc4, 0xe3, 0x79, 0x68, 0x00, 0x0f	# vfmaddps xmm0, xmm0, [eax], xmm0
 
+	vpermil2ps xmm0, xmm0, [eax], xmm0, 0
+	.code64
+	vpermil2ps xmm0, xmm8, [rax], xmm0, 0
+	vpermil2ps xmm0, xmm0, [rax], xmm8, 0
+	.code32
+
 	ret
 
 	.type ix86, @function
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -12809,11 +12809,6 @@ get_valid_dis386 (const struct dis386 *d
 	{
 	  /* In 16/32-bit mode REX_B is silently ignored.  */
 	  rex &= ~REX_B;
-	  if (vex.register_specifier > 0x7)
-	    {
-	      dp = &bad_opcode;
-	      return dp;
-	    }
 	}
 
       vex.length = (*codep & 0x4) ? 256 : 128;
@@ -12872,16 +12867,15 @@ get_valid_dis386 (const struct dis386 *d
 	{
 	  if (vex.w)
 	    rex |= REX_W;
-	  vex.register_specifier = (~(*codep >> 3)) & 0xf;
 	}
       else
 	{
 	  /* For the 3-byte VEX prefix in 32-bit mode, the REX_B bit
 	     is ignored, other REX bits are 0 and the highest bit in
-	     VEX.vvvv is also ignored.  */
+	     VEX.vvvv is also ignored (but we mustn't clear it here).  */
 	  rex = 0;
-	  vex.register_specifier = (~(*codep >> 3)) & 0x7;
 	}
+      vex.register_specifier = (~(*codep >> 3)) & 0xf;
       vex.length = (*codep & 0x4) ? 256 : 128;
       switch ((*codep & 0x3))
 	{
@@ -12996,14 +12990,6 @@ get_valid_dis386 (const struct dis386 *d
 	rex |= REX_W;
 
       vex.register_specifier = (~(*codep >> 3)) & 0xf;
-      if (address_mode != mode_64bit)
-	{
-	  /* In 16/32-bit mode silently ignore following bits.  */
-	  rex &= ~REX_B;
-	  vex.r = 1;
-	  vex.v = 1;
-	  vex.register_specifier &= 0x7;
-	}
 
       /* The U bit.  */
       if (!(*codep & 0x4))
@@ -13036,6 +13022,14 @@ get_valid_dis386 (const struct dis386 *d
       vex.mask_register_specifier = *codep & 0x7;
       vex.zeroing = *codep & 0x80;
 
+      if (address_mode != mode_64bit)
+	{
+	  /* In 16/32-bit mode silently ignore following bits.  */
+	  rex &= ~REX_B;
+	  vex.r = 1;
+	  vex.v = 1;
+	}
+
       need_vex = 1;
       need_vex_reg = 1;
       codep++;
@@ -17098,11 +17092,10 @@ OP_VEX (int bytemode, int sizeflag ATTRI
     return;
 
   reg = vex.register_specifier;
-  if (vex.evex)
-    {
-      if (!vex.v)
-	reg += 16;
-    }
+  if (address_mode != mode_64bit)
+    reg &= 7;
+  else if (vex.evex && !vex.v)
+    reg += 16;
 
   if (bytemode == vex_scalar_mode)
     {
@@ -17287,8 +17280,8 @@ OP_EX_VexReg (int bytemode, int sizeflag
 	  if (rex & REX_B)
 	    reg += 8;
 	}
-      else if (reg > 7 && address_mode != mode_64bit)
-	BadOp ();
+      if (address_mode != mode_64bit)
+	reg &= 7;
     }
 
   switch (vex.length)
@@ -17380,7 +17373,13 @@ OP_Vex_2src_1 (int bytemode, int sizefla
     }
 
   if (vex.w)
-    oappend (names_xmm[vex.register_specifier]);
+    {
+      unsigned int reg = vex.register_specifier;
+
+      if (address_mode != mode_64bit)
+	reg &= 7;
+      oappend (names_xmm[reg]);
+    }
   else
     OP_Vex_2src (bytemode, sizeflag);
 }
@@ -17391,7 +17390,13 @@ OP_Vex_2src_2 (int bytemode, int sizefla
   if (vex.w)
     OP_Vex_2src (bytemode, sizeflag);
   else
-    oappend (names_xmm[vex.register_specifier]);
+    {
+      unsigned int reg = vex.register_specifier;
+
+      if (address_mode != mode_64bit)
+	reg &= 7;
+      oappend (names_xmm[reg]);
+    }
 }
 
 static void
@@ -17434,8 +17439,8 @@ OP_REG_VexI4 (int bytemode, int sizeflag
     abort ();
 
   reg >>= 4;
-  if (reg > 7 && address_mode != mode_64bit)
-    BadOp ();
+  if (address_mode != mode_64bit)
+    reg &= 7;
 
   switch (vex.length)
     {
@@ -17775,13 +17780,16 @@ static void
 OP_LWP_E (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
 {
   const char **names;
+  unsigned int reg = vex.register_specifier;
 
   if (rex & REX_W)
     names = names64;
   else
     names = names32;
 
-  oappend (names[vex.register_specifier]);
+  if (address_mode != mode_64bit)
+    reg &= 7;
+  oappend (names[reg]);
 }
 
 static void



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