x86: ignore high register select bit(s) in 32- and 16-bit modes
authorJan Beulich <jbeulich@novell.com>
Thu, 16 Nov 2017 12:56:45 +0000 (13:56 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 16 Nov 2017 12:56:45 +0000 (13:56 +0100)
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

gas/ChangeLog
gas/testsuite/gas/i386/noextreg.d
gas/testsuite/gas/i386/noextreg.s
opcodes/ChangeLog
opcodes/i386-dis.c

index e1aacffd964059390a30b17d38b013df6f700b08..de1b63d46b42a377da4ba0255da40968349e2595 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-16  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.
+
 2017-11-16  Jan Beulich  <jbeulich@suse.com>
 
        * config/tc-i386.c (process_suffix): Ignore .no_qsuf outside of
index 4b7f45d46ed6fc2f1aebbdb636184129f4226985..99579c9c677730ec1ab7aa0d50227609d4d01611 100644 (file)
@@ -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 \$0x1,%xmm0,%xmm0
+[      ]*[a-f0-9]+:    8f c8 78 c0 c0 01       vprotb \$0x1,%xmm0,%xmm0
+[      ]*[a-f0-9]+:    8f e8 78 c0 00 01       vprotb \$0x1,\(%eax\),%xmm0
+[      ]*[a-f0-9]+:    8f c8 78 c0 00 01       vprotb \$0x1,\(%eax\),%xmm0
+[      ]*[a-f0-9]+:    8f e9 78 90 c0          vprotb %xmm0,%xmm0,%xmm0
+[      ]*[a-f0-9]+:    8f c9 b8 90 c0          vprotb %xmm0,%xmm0,%xmm0
+[      ]*[a-f0-9]+:    8f e9 38 90 c0          vprotb %xmm0,%xmm0,%xmm0
+[      ]*[a-f0-9]+:    8f e9 78 90 00          vprotb %xmm0,\(%eax\),%xmm0
+[      ]*[a-f0-9]+:    8f c9 78 90 00          vprotb %xmm0,\(%eax\),%xmm0
+[      ]*[a-f0-9]+:    8f e9 f8 90 00          vprotb \(%eax\),%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 \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
+[      ]*[a-f0-9]+:    c4 e3 39 48 00 00       vpermil2ps \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
+[      ]*[a-f0-9]+:    c4 e3 79 48 00 80       vpermil2ps \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
 [      ]*[a-f0-9]+:    c3                      ret[    ]*
 #pass
index f1205acf2279cced2f8f87b081dea981467e64b0..85fd26ed5a46c19f40dbd563af1bd127749dc25d 100644 (file)
@@ -1,20 +1,57 @@
        .intel_syntax noprefix
        .text
 ix86:
+       vpand   xmm0, xmm0, xmm0
+       .byte   0xc4, 0xc1, 0x79, 0xdb, 0xc0
+       .byte   0xc4, 0xc1, 0x39, 0xdb, 0xc0
+
+       vpandd  xmm0, xmm0, xmm0
+       .byte   0x62, 0xd1, 0x7d, 0x08, 0xdb, 0xc0
+       .byte   0x62, 0xf1, 0x3d, 0x08, 0xdb, 0xc0
+       .byte   0x62, 0xf1, 0x7d, 0x00, 0xdb, 0xc0
+
+       vpblendvb xmm0, xmm0, xmm0, xmm0
+       .byte   0xc4, 0xc3, 0x79, 0x4c, 0xc0, 0x00
+       .byte   0xc4, 0xe3, 0x39, 0x4c, 0xc0, 0x00
+       .byte   0xc4, 0xe3, 0x79, 0x4c, 0xc0, 0x80
+
+       vpgatherdd xmm1{k7}, [eax+xmm0]
+       .byte   0x62, 0xd2, 0x7d, 0x0f, 0x90, 0x0c, 0x00
+       .byte   0x62, 0xf2, 0x7d, 0x07, 0x90, 0x0c, 0x00
+
        andn    eax, eax, [eax]
-       # andn rax, rax, [rax]
+       .byte   0xc4, 0xe2, 0x38, 0xf2, 0x00
+       .byte   0xc4, 0xc2, 0x78, 0xf2, 0x00
        .byte   0xc4, 0xe2, 0xf8, 0xf2, 0x00
 
        tzmsk   eax, [eax]
-       # tzmsk rax, [rax]
+       .byte   0x8f, 0xc9, 0x78, 0x01, 0x20
+       .byte   0x8f, 0xe9, 0x38, 0x01, 0x20
        .byte   0x8f, 0xe9, 0xf8, 0x01, 0x20
 
        llwpcb  eax
-       # llwpcb rax
+       .byte   0x8f, 0xc9, 0x78, 0x12, 0xc0
        .byte   0x8f, 0xe9, 0xf8, 0x12, 0xc0
 
+       vprotb  xmm0, xmm0, 1
+       .byte   0x8f, 0xc8, 0x78, 0xc0, 0xc0, 0x01
+       vprotb  xmm0, [eax], 1
+       .byte   0x8f, 0xc8, 0x78, 0xc0, 0x00, 0x01
+       vprotb  xmm0, xmm0, xmm0
+       .byte   0x8f, 0xc9, 0xb8, 0x90, 0xc0
+       .byte   0x8f, 0xe9, 0x38, 0x90, 0xc0
+       vprotb  xmm0, [eax], xmm0
+       .byte   0x8f, 0xc9, 0x78, 0x90, 0x00
+       vprotb  xmm0, xmm0, [eax]
+       .byte   0x8f, 0xc9, 0xf8, 0x90, 0x00
+
        vfmaddps xmm0, xmm0, [eax], xmm0
-       # vfmaddps xmm0, xmm0, [eax], xmm0
+       .byte   0xc4, 0xe3, 0x39, 0x68, 0x00, 0x00
+       .byte   0xc4, 0xe3, 0x79, 0x68, 0x00, 0x80
        .byte   0xc4, 0xe3, 0x79, 0x68, 0x00, 0x0f
 
+       vpermil2ps xmm0, xmm0, [eax], xmm0, 0
+       .byte   0xc4, 0xe3, 0x39, 0x48, 0x00, 0x00
+       .byte   0xc4, 0xe3, 0x79, 0x48, 0x00, 0x80
+
        ret
index 2cc35947bd954a9a481e3e644dec209ce33b6cce..6ea9c100bfb903f65b56e31ae85fd41960e89ab6 100644 (file)
@@ -1,3 +1,14 @@
+2017-11-16  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.
+
 2017-11-15  Jan Beulich  <jbeulich@suse.com>
 
        * i386-dis.c (OP_VEX, OP_LWPCB_E, OP_LWP_E): Use rex to
index 78a685ee47167ebc7d37114af9affe1ec3e626bc..64b47028fd4e34d68cc78de529847b1057fa5535 100644 (file)
@@ -12809,11 +12809,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
        {
          /* 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 *dp, disassemble_info *info)
        {
          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 *dp, disassemble_info *info)
        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 *dp, disassemble_info *info)
       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 ATTRIBUTE_UNUSED)
     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, int reg)
          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 sizeflag)
     }
 
   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 sizeflag)
   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 ATTRIBUTE_UNUSED)
     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