x86: re-work operand handling for 5-operand XOP insns
authorJan Beulich <jbeulich@suse.com>
Wed, 8 Jul 2020 09:02:40 +0000 (11:02 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 8 Jul 2020 09:02:40 +0000 (11:02 +0200)
There's no need for custom operand handling here, except for the VEX.W
controlled operand swapping and the printing of the remaining 4-bit
immediate. VEX.W can be handled just like 4-operand insns.

Also take the opportunity and drop the stray indirection through
vex_w_table[].

opcodes/ChangeLog
opcodes/i386-dis.c

index 5b6949cc2050b868e1dfeeef6e89443fd4f265e4..18605c849bb9ec492330c1e5dfac7e767c91779a 100644 (file)
@@ -1,3 +1,13 @@
+2020-07-08  Jan Beulich  <jbeulich@suse.com>
+
+       * i386-dis.c (OP_EX_VexImmW, OP_XMM_VexW, EXVexImmW, XMVexW,
+       VEX_W_0F3A48_P_2, VEX_W_0F3A49_P_2, vex_w_done, get_vex_imm8,
+       OP_EX_VexReg): Delete.
+       (OP_VexI4, VexI4): New.
+       (vex_w_table): Move vpermil2ps and vpermil2pd entries ...
+       (prefix_table): ... here.
+       (print_insn): Drop setting of vex_w_done.
+
 2020-07-08  Jan Beulich  <jbeulich@suse.com>
 
        * i386-dis.c (OP_EX_VexW, EXVexW, EXdVexW, EXqVexW): Delete.
index eb1157b6ba2eecc2eb1e6f91b8e2abdc3049e8a6..1e4c75cdc5fa0351867f0a692877872bf6664501 100644 (file)
@@ -89,11 +89,10 @@ static void OP_XS (int, int);
 static void OP_M (int, int);
 static void OP_VEX (int, int);
 static void OP_EX_Vex (int, int);
-static void OP_EX_VexImmW (int, int);
 static void OP_XMM_Vex (int, int);
-static void OP_XMM_VexW (int, int);
 static void OP_Rounding (int, int);
 static void OP_REG_VexI4 (int, int);
+static void OP_VexI4 (int, int);
 static void PCLMUL_Fixup (int, int);
 static void VCMP_Fixup (int, int);
 static void VPCMP_Fixup (int, int);
@@ -422,10 +421,9 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define VexGdq { OP_VEX, dq_mode }
 #define EXdVexScalarS { OP_EX_Vex, d_scalar_swap_mode }
 #define EXqVexScalarS { OP_EX_Vex, q_scalar_swap_mode }
-#define EXVexImmW { OP_EX_VexImmW, x_mode }
 #define XMVexScalar { OP_XMM_Vex, scalar_mode }
-#define XMVexW { OP_XMM_VexW, 0 }
 #define XMVexI4 { OP_REG_VexI4, x_mode }
+#define VexI4 { OP_VexI4, 0 }
 #define PCLMUL { PCLMUL_Fixup, 0 }
 #define VCMP { VCMP_Fixup, 0 }
 #define VPCMP { VPCMP_Fixup, 0 }
@@ -1944,8 +1942,6 @@ enum
   VEX_W_0F3A38_P_2,
   VEX_W_0F3A39_P_2,
   VEX_W_0F3A46_P_2,
-  VEX_W_0F3A48_P_2,
-  VEX_W_0F3A49_P_2,
   VEX_W_0F3A4A_P_2,
   VEX_W_0F3A4B_P_2,
   VEX_W_0F3A4C_P_2,
@@ -2877,7 +2873,6 @@ static struct
 vex;
 static unsigned char need_vex;
 static unsigned char need_vex_reg;
-static unsigned char vex_w_done;
 
 struct op
   {
@@ -6413,14 +6408,14 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_W_TABLE (VEX_W_0F3A48_P_2) },
+    { "vpermil2ps",    { XM, Vex, EXx, XMVexI4, VexI4 }, 0 },
   },
 
   /* PREFIX_VEX_0F3A49 */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_W_TABLE (VEX_W_0F3A49_P_2) },
+    { "vpermil2pd",    { XM, Vex, EXx, XMVexI4, VexI4 }, 0 },
   },
 
   /* PREFIX_VEX_0F3A4A */
@@ -10020,16 +10015,6 @@ static const struct dis386 vex_w_table[][2] = {
     /* VEX_W_0F3A46_P_2 */
     { "vperm2i128",    { XM, Vex256, EXx, Ib }, 0 },
   },
-  {
-    /* VEX_W_0F3A48_P_2 */
-    { "vpermil2ps",    { XMVexW, Vex, EXVexImmW, EXVexImmW, EXVexImmW }, 0 },
-    { "vpermil2ps",    { XMVexW, Vex, EXVexImmW, EXVexImmW, EXVexImmW }, 0 },
-  },
-  {
-    /* VEX_W_0F3A49_P_2 */
-    { "vpermil2pd",    { XMVexW, Vex, EXVexImmW, EXVexImmW, EXVexImmW }, 0 },
-    { "vpermil2pd",    { XMVexW, Vex, EXVexImmW, EXVexImmW, EXVexImmW }, 0 },
-  },
   {
     /* VEX_W_0F3A4A_P_2 */
     { "vblendvps",     { XM, Vex, EXx, XMVexI4 }, 0 },
@@ -11992,7 +11977,6 @@ print_insn (bfd_vma pc, disassemble_info *info)
 
   need_vex = 0;
   need_vex_reg = 0;
-  vex_w_done = 0;
   memset (&vex, 0, sizeof (vex));
 
   if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE)
@@ -15865,175 +15849,6 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
   oappend (names[reg]);
 }
 
-/* Get the VEX immediate byte without moving codep.  */
-
-static unsigned char
-get_vex_imm8 (int sizeflag, int opnum)
-{
-  int bytes_before_imm = 0;
-
-  if (modrm.mod != 3)
-    {
-      /* There are SIB/displacement bytes.  */
-      if ((sizeflag & AFLAG) || address_mode == mode_64bit)
-       {
-         /* 32/64 bit address mode */
-         int base = modrm.rm;
-
-         /* Check SIB byte.  */
-         if (base == 4)
-           {
-             FETCH_DATA (the_info, codep + 1);
-             base = *codep & 7;
-             /* When decoding the third source, don't increase
-                bytes_before_imm as this has already been incremented
-                by one in OP_E_memory while decoding the second
-                source operand.  */
-             if (opnum == 0)
-               bytes_before_imm++;
-           }
-
-         /* Don't increase bytes_before_imm when decoding the third source,
-            it has already been incremented by OP_E_memory while decoding
-            the second source operand.  */
-         if (opnum == 0)
-           {
-             switch (modrm.mod)
-               {
-                 case 0:
-                   /* When modrm.rm == 5 or modrm.rm == 4 and base in
-                      SIB == 5, there is a 4 byte displacement.  */
-                   if (base != 5)
-                     /* No displacement. */
-                     break;
-                   /* Fall through.  */
-                 case 2:
-                   /* 4 byte displacement.  */
-                   bytes_before_imm += 4;
-                   break;
-                 case 1:
-                   /* 1 byte displacement.  */
-                   bytes_before_imm++;
-                   break;
-               }
-           }
-       }
-      else
-       {
-         /* 16 bit address mode */
-         /* Don't increase bytes_before_imm when decoding the third source,
-            it has already been incremented by OP_E_memory while decoding
-            the second source operand.  */
-         if (opnum == 0)
-           {
-             switch (modrm.mod)
-               {
-               case 0:
-                 /* When modrm.rm == 6, there is a 2 byte displacement.  */
-                 if (modrm.rm != 6)
-                   /* No displacement. */
-                   break;
-                 /* Fall through.  */
-               case 2:
-                 /* 2 byte displacement.  */
-                 bytes_before_imm += 2;
-                 break;
-               case 1:
-                 /* 1 byte displacement: when decoding the third source,
-                    don't increase bytes_before_imm as this has already
-                    been incremented by one in OP_E_memory while decoding
-                    the second source operand.  */
-                 if (opnum == 0)
-                   bytes_before_imm++;
-
-                 break;
-               }
-           }
-       }
-    }
-
-  FETCH_DATA (the_info, codep + bytes_before_imm + 1);
-  return codep [bytes_before_imm];
-}
-
-static void
-OP_EX_VexReg (int bytemode, int sizeflag, int reg)
-{
-  const char **names;
-
-  if (reg == -1 && modrm.mod != 3)
-    {
-      OP_E_memory (bytemode, sizeflag);
-      return;
-    }
-  else
-    {
-      if (reg == -1)
-       {
-         reg = modrm.rm;
-         USED_REX (REX_B);
-         if (rex & REX_B)
-           reg += 8;
-       }
-      if (address_mode != mode_64bit)
-       reg &= 7;
-    }
-
-  switch (vex.length)
-    {
-    case 128:
-      names = names_xmm;
-      break;
-    case 256:
-      names = names_ymm;
-      break;
-    default:
-      abort ();
-    }
-  oappend (names[reg]);
-}
-
-static void
-OP_EX_VexImmW (int bytemode, int sizeflag)
-{
-  int reg = -1;
-  static unsigned char vex_imm8;
-
-  if (vex_w_done == 0)
-    {
-      vex_w_done = 1;
-
-      /* Skip mod/rm byte.  */
-      MODRM_CHECK;
-      codep++;
-
-      vex_imm8 = get_vex_imm8 (sizeflag, 0);
-
-      if (vex.w)
-         reg = vex_imm8 >> 4;
-
-      OP_EX_VexReg (bytemode, sizeflag, reg);
-    }
-  else if (vex_w_done == 1)
-    {
-      vex_w_done = 2;
-
-      if (!vex.w)
-         reg = vex_imm8 >> 4;
-
-      OP_EX_VexReg (bytemode, sizeflag, reg);
-    }
-  else
-    {
-      /* Output the imm8 directly.  */
-      scratchbuf[0] = '$';
-      print_operand_value (scratchbuf + 1, 1, vex_imm8 & 0xf);
-      oappend_maybe_intel (scratchbuf);
-      scratchbuf[0] = '\0';
-      codep++;
-    }
-}
-
 static void
 OP_Vex_2src (int bytemode, int sizeflag)
 {
@@ -16135,12 +15950,12 @@ OP_REG_VexI4 (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 }
 
 static void
-OP_XMM_VexW (int bytemode, int sizeflag)
+OP_VexI4 (int bytemode ATTRIBUTE_UNUSED,
+         int sizeflag ATTRIBUTE_UNUSED)
 {
-  /* Turn off the REX.W bit since it is used for swapping operands
-     now.  */
-  rex &= ~REX_W;
-  OP_XMM (bytemode, sizeflag);
+  scratchbuf[0] = '$';
+  print_operand_value (scratchbuf + 1, 1, codep[-1] & 0xf);
+  oappend_maybe_intel (scratchbuf);
 }
 
 static void