x86: ignore high register select bit(s) in 32- and 16-bit modes
[external/binutils.git] / opcodes / i386-dis.c
index 8d5bd27..64b4702 100644 (file)
@@ -95,10 +95,10 @@ static void OP_XMM_VexW (int, int);
 static void OP_Rounding (int, int);
 static void OP_REG_VexI4 (int, int);
 static void PCLMUL_Fixup (int, int);
-static void VEXI4_Fixup (int, int);
 static void VZERO_Fixup (int, int);
 static void VCMP_Fixup (int, int);
 static void VPCMP_Fixup (int, int);
+static void VPCOM_Fixup (int, int);
 static void OP_0f07 (int, int);
 static void OP_Monitor (int, int);
 static void OP_Mwait (int, int);
@@ -422,7 +422,6 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Vex128 { OP_VEX, vex128_mode }
 #define Vex256 { OP_VEX, vex256_mode }
 #define VexGdq { OP_VEX, dq_mode }
-#define VexI4 { VEXI4_Fixup, 0}
 #define EXdVex { OP_EX_Vex, d_mode }
 #define EXdVexS { OP_EX_Vex, d_swap_mode }
 #define EXdVexScalarS { OP_EX_Vex, d_scalar_swap_mode }
@@ -441,6 +440,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define VZERO { VZERO_Fixup, 0 }
 #define VCMP { VCMP_Fixup, 0 }
 #define VPCMP { VPCMP_Fixup, 0 }
+#define VPCOM { VPCOM_Fixup, 0 }
 
 #define EXxEVexR { OP_Rounding, evex_rounding_mode }
 #define EXxEVexS { OP_Rounding, evex_sae_mode }
@@ -1059,6 +1059,7 @@ enum
   PREFIX_0F38CB,
   PREFIX_0F38CC,
   PREFIX_0F38CD,
+  PREFIX_0F38CF,
   PREFIX_0F38DB,
   PREFIX_0F38DC,
   PREFIX_0F38DD,
@@ -1091,6 +1092,8 @@ enum
   PREFIX_0F3A62,
   PREFIX_0F3A63,
   PREFIX_0F3ACC,
+  PREFIX_0F3ACE,
+  PREFIX_0F3ACF,
   PREFIX_0F3ADF,
   PREFIX_VEX_0F10,
   PREFIX_VEX_0F11,
@@ -1312,6 +1315,7 @@ enum
   PREFIX_VEX_0F38BD,
   PREFIX_VEX_0F38BE,
   PREFIX_VEX_0F38BF,
+  PREFIX_VEX_0F38CF,
   PREFIX_VEX_0F38DB,
   PREFIX_VEX_0F38DC,
   PREFIX_VEX_0F38DD,
@@ -1388,6 +1392,8 @@ enum
   PREFIX_VEX_0F3A7D,
   PREFIX_VEX_0F3A7E,
   PREFIX_VEX_0F3A7F,
+  PREFIX_VEX_0F3ACE,
+  PREFIX_VEX_0F3ACF,
   PREFIX_VEX_0F3ADF,
   PREFIX_VEX_0F3AF0,
 
@@ -1566,8 +1572,11 @@ enum
   PREFIX_EVEX_0F384D,
   PREFIX_EVEX_0F384E,
   PREFIX_EVEX_0F384F,
+  PREFIX_EVEX_0F3850,
+  PREFIX_EVEX_0F3851,
   PREFIX_EVEX_0F3852,
   PREFIX_EVEX_0F3853,
+  PREFIX_EVEX_0F3854,
   PREFIX_EVEX_0F3855,
   PREFIX_EVEX_0F3858,
   PREFIX_EVEX_0F3859,
@@ -1599,6 +1608,7 @@ enum
   PREFIX_EVEX_0F388A,
   PREFIX_EVEX_0F388B,
   PREFIX_EVEX_0F388D,
+  PREFIX_EVEX_0F388F,
   PREFIX_EVEX_0F3890,
   PREFIX_EVEX_0F3891,
   PREFIX_EVEX_0F3892,
@@ -1653,6 +1663,11 @@ enum
   PREFIX_EVEX_0F38CB,
   PREFIX_EVEX_0F38CC,
   PREFIX_EVEX_0F38CD,
+  PREFIX_EVEX_0F38CF,
+  PREFIX_EVEX_0F38DC,
+  PREFIX_EVEX_0F38DD,
+  PREFIX_EVEX_0F38DE,
+  PREFIX_EVEX_0F38DF,
 
   PREFIX_EVEX_0F3A00,
   PREFIX_EVEX_0F3A01,
@@ -1690,6 +1705,7 @@ enum
   PREFIX_EVEX_0F3A3F,
   PREFIX_EVEX_0F3A42,
   PREFIX_EVEX_0F3A43,
+  PREFIX_EVEX_0F3A44,
   PREFIX_EVEX_0F3A50,
   PREFIX_EVEX_0F3A51,
   PREFIX_EVEX_0F3A54,
@@ -1701,7 +1717,9 @@ enum
   PREFIX_EVEX_0F3A70,
   PREFIX_EVEX_0F3A71,
   PREFIX_EVEX_0F3A72,
-  PREFIX_EVEX_0F3A73
+  PREFIX_EVEX_0F3A73,
+  PREFIX_EVEX_0F3ACE,
+  PREFIX_EVEX_0F3ACF
 };
 
 enum
@@ -1856,10 +1874,6 @@ enum
   VEX_LEN_0F3841_P_2,
   VEX_LEN_0F385A_P_2_M_0,
   VEX_LEN_0F38DB_P_2,
-  VEX_LEN_0F38DC_P_2,
-  VEX_LEN_0F38DD_P_2,
-  VEX_LEN_0F38DE_P_2,
-  VEX_LEN_0F38DF_P_2,
   VEX_LEN_0F38F2_P_0,
   VEX_LEN_0F38F3_R_1_P_0,
   VEX_LEN_0F38F3_R_2_P_0,
@@ -1893,7 +1907,6 @@ enum
   VEX_LEN_0F3A38_P_2,
   VEX_LEN_0F3A39_P_2,
   VEX_LEN_0F3A41_P_2,
-  VEX_LEN_0F3A44_P_2,
   VEX_LEN_0F3A46_P_2,
   VEX_LEN_0F3A60_P_2,
   VEX_LEN_0F3A61_P_2,
@@ -2180,11 +2193,8 @@ enum
   VEX_W_0F385A_P_2_M_0,
   VEX_W_0F3878_P_2,
   VEX_W_0F3879_P_2,
+  VEX_W_0F38CF_P_2,
   VEX_W_0F38DB_P_2,
-  VEX_W_0F38DC_P_2,
-  VEX_W_0F38DD_P_2,
-  VEX_W_0F38DE_P_2,
-  VEX_W_0F38DF_P_2,
   VEX_W_0F3A00_P_2,
   VEX_W_0F3A01_P_2,
   VEX_W_0F3A02_P_2,
@@ -2214,7 +2224,6 @@ enum
   VEX_W_0F3A40_P_2,
   VEX_W_0F3A41_P_2,
   VEX_W_0F3A42_P_2,
-  VEX_W_0F3A44_P_2,
   VEX_W_0F3A46_P_2,
   VEX_W_0F3A48_P_2,
   VEX_W_0F3A49_P_2,
@@ -2223,6 +2232,8 @@ enum
   VEX_W_0F3A4C_P_2,
   VEX_W_0F3A62_P_2,
   VEX_W_0F3A63_P_2,
+  VEX_W_0F3ACE_P_2,
+  VEX_W_0F3ACF_P_2,
   VEX_W_0F3ADF_P_2,
 
   EVEX_W_0F10_P_0,
@@ -2406,6 +2417,7 @@ enum
   EVEX_W_0F3839_P_1,
   EVEX_W_0F383A_P_1,
   EVEX_W_0F3840_P_2,
+  EVEX_W_0F3854_P_2,
   EVEX_W_0F3855_P_2,
   EVEX_W_0F3858_P_2,
   EVEX_W_0F3859_P_2,
@@ -2469,7 +2481,9 @@ enum
   EVEX_W_0F3A70_P_2,
   EVEX_W_0F3A71_P_2,
   EVEX_W_0F3A72_P_2,
-  EVEX_W_0F3A73_P_2
+  EVEX_W_0F3A73_P_2,
+  EVEX_W_0F3ACE_P_2,
+  EVEX_W_0F3ACF_P_2
 };
 
 typedef void (*op_rtn) (int bytemode, int sizeflag);
@@ -4549,6 +4563,13 @@ static const struct dis386 prefix_table[][4] = {
     { "sha256msg2", { XM, EXxmm }, PREFIX_OPCODE },
   },
 
+  /* PREFIX_0F38CF */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "gf2p8mulb", { XM, EXxmm }, PREFIX_OPCODE },
+  },
+
   /* PREFIX_0F38DB */
   {
     { Bad_Opcode },
@@ -4774,6 +4795,20 @@ static const struct dis386 prefix_table[][4] = {
     { "sha1rnds4", { XM, EXxmm, Ib }, PREFIX_OPCODE },
   },
 
+  /* PREFIX_0F3ACE */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "gf2p8affineqb", { XM, EXxmm, Ib }, PREFIX_OPCODE },
+  },
+
+  /* PREFIX_0F3ACF */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "gf2p8affineinvqb", { XM, EXxmm, Ib }, PREFIX_OPCODE },
+  },
+
   /* PREFIX_0F3ADF */
   {
     { Bad_Opcode },
@@ -6341,6 +6376,13 @@ static const struct dis386 prefix_table[][4] = {
     { "vfnmsub231s%XW", { XMScalar, VexScalar, EXVexWdqScalar }, 0 },
   },
 
+  /* PREFIX_VEX_0F38CF */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F38CF_P_2) },
+  },
+
   /* PREFIX_VEX_0F38DB */
   {
     { Bad_Opcode },
@@ -6352,28 +6394,28 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_LEN_TABLE (VEX_LEN_0F38DC_P_2) },
+    { "vaesenc",       { XM, Vex, EXx }, 0 },
   },
 
   /* PREFIX_VEX_0F38DD */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_LEN_TABLE (VEX_LEN_0F38DD_P_2) },
+    { "vaesenclast",   { XM, Vex, EXx }, 0 },
   },
 
   /* PREFIX_VEX_0F38DE */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_LEN_TABLE (VEX_LEN_0F38DE_P_2) },
+    { "vaesdec",       { XM, Vex, EXx }, 0 },
   },
 
   /* PREFIX_VEX_0F38DF */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_LEN_TABLE (VEX_LEN_0F38DF_P_2) },
+    { "vaesdeclast",   { XM, Vex, EXx }, 0 },
   },
 
   /* PREFIX_VEX_0F38F2 */
@@ -6655,7 +6697,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_LEN_TABLE (VEX_LEN_0F3A44_P_2) },
+    { "vpclmulqdq",    { XM, Vex, EXx, PCLMUL }, 0 },
   },
 
   /* PREFIX_VEX_0F3A46 */
@@ -6704,28 +6746,28 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmaddsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmaddsubps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A5D */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmaddsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmaddsubpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A5E */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmsubaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmsubaddps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A5F */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmsubaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmsubaddpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A60 */
@@ -6761,14 +6803,14 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmaddps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A69 */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmaddpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A6A */
@@ -6789,14 +6831,14 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmsubps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A6D */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfmsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfmsubpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A6E */
@@ -6817,14 +6859,14 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfnmaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfnmaddps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A79 */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfnmaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfnmaddpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A7A */
@@ -6845,7 +6887,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfnmsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfnmsubps", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     { Bad_Opcode },
   },
 
@@ -6853,7 +6895,7 @@ static const struct dis386 prefix_table[][4] = {
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vfnmsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vfnmsubpd", { XMVexW, Vex, EXVexW, EXVexW }, 0 },
   },
 
   /* PREFIX_VEX_0F3A7E */
@@ -6870,6 +6912,20 @@ static const struct dis386 prefix_table[][4] = {
     { VEX_LEN_TABLE (VEX_LEN_0F3A7F_P_2) },
   },
 
+  /* PREFIX_VEX_0F3ACE */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F3ACE_P_2) },
+  },
+
+  /* PREFIX_VEX_0F3ACF */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { VEX_W_TABLE (VEX_W_0F3ACF_P_2) },
+  },
+
   /* PREFIX_VEX_0F3ADF */
   {
     { Bad_Opcode },
@@ -7297,7 +7353,7 @@ static const struct dis386 three_byte_table[][256] = {
     { PREFIX_TABLE (PREFIX_0F38CC) },
     { PREFIX_TABLE (PREFIX_0F38CD) },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_0F38CF) },
     /* d0 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -7587,8 +7643,8 @@ static const struct dis386 three_byte_table[][256] = {
     { Bad_Opcode },
     { PREFIX_TABLE (PREFIX_0F3ACC) },
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_0F3ACE) },
+    { PREFIX_TABLE (PREFIX_0F3ACF) },
     /* d0 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -7799,9 +7855,9 @@ static const struct dis386 xop_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmacssww",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacsswd",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacssdql",    { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmacssww",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacsswd",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacssdql",    { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     /* 88 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -7809,17 +7865,17 @@ static const struct dis386 xop_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmacssdd",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacssdqh",    { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmacssdd",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacssdqh",    { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     /* 90 */
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmacsww",      { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacswd",      { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacsdql",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmacsww",      { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacswd",      { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacsdql",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     /* 98 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -7827,16 +7883,16 @@ static const struct dis386 xop_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmacsdd",      { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpmacsdqh",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmacsdd",      { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpmacsdqh",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     /* a0 */
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpcmov",        { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
-    { "vpperm",        { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpcmov",        { XMVexW, Vex, EXVexW, EXVexW }, 0 },
+    { "vpperm",        { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmadcsswd",    { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmadcsswd",    { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     { Bad_Opcode },
     /* a8 */
     { Bad_Opcode },
@@ -7854,7 +7910,7 @@ static const struct dis386 xop_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { "vpmadcswd",     { XMVexW, Vex, EXVexW, EXVexW, VexI4 }, 0 },
+    { "vpmadcswd",     { XMVexW, Vex, EXVexW, EXVexW }, 0 },
     { Bad_Opcode },
     /* b8 */
     { Bad_Opcode },
@@ -9049,7 +9105,7 @@ static const struct dis386 vex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_VEX_0F38CF) },
     /* d0 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -9339,8 +9395,8 @@ static const struct dis386 vex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE(PREFIX_VEX_0F3ACE) },
+    { PREFIX_TABLE(PREFIX_VEX_0F3ACF) },
     /* d0 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -9884,26 +9940,6 @@ static const struct dis386 vex_len_table[][2] = {
     { VEX_W_TABLE (VEX_W_0F38DB_P_2) },
   },
 
-  /* VEX_LEN_0F38DC_P_2 */
-  {
-    { VEX_W_TABLE (VEX_W_0F38DC_P_2) },
-  },
-
-  /* VEX_LEN_0F38DD_P_2 */
-  {
-    { VEX_W_TABLE (VEX_W_0F38DD_P_2) },
-  },
-
-  /* VEX_LEN_0F38DE_P_2 */
-  {
-    { VEX_W_TABLE (VEX_W_0F38DE_P_2) },
-  },
-
-  /* VEX_LEN_0F38DF_P_2 */
-  {
-    { VEX_W_TABLE (VEX_W_0F38DF_P_2) },
-  },
-
   /* VEX_LEN_0F38F2_P_0 */
   {
     { "andnS",         { Gdq, VexGdq, Edq }, 0 },
@@ -10078,11 +10114,6 @@ static const struct dis386 vex_len_table[][2] = {
     { VEX_W_TABLE (VEX_W_0F3A41_P_2) },
   },
 
-  /* VEX_LEN_0F3A44_P_2 */
-  {
-    { VEX_W_TABLE (VEX_W_0F3A44_P_2) },
-  },
-
   /* VEX_LEN_0F3A46_P_2 */
   {
     { Bad_Opcode },
@@ -10111,42 +10142,42 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0F3A6A_P_2 */
   {
-    { "vfmaddss",      { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 }, 0 },
+    { "vfmaddss",      { XMVexW, Vex128, EXdVexW, EXdVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A6B_P_2 */
   {
-    { "vfmaddsd",      { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 }, 0 },
+    { "vfmaddsd",      { XMVexW, Vex128, EXqVexW, EXqVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A6E_P_2 */
   {
-    { "vfmsubss",      { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 }, 0 },
+    { "vfmsubss",      { XMVexW, Vex128, EXdVexW, EXdVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A6F_P_2 */
   {
-    { "vfmsubsd",      { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 }, 0 },
+    { "vfmsubsd",      { XMVexW, Vex128, EXqVexW, EXqVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A7A_P_2 */
   {
-    { "vfnmaddss",     { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 }, 0 },
+    { "vfnmaddss",     { XMVexW, Vex128, EXdVexW, EXdVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A7B_P_2 */
   {
-    { "vfnmaddsd",     { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 }, 0 },
+    { "vfnmaddsd",     { XMVexW, Vex128, EXqVexW, EXqVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A7E_P_2 */
   {
-    { "vfnmsubss",     { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 }, 0 },
+    { "vfnmsubss",     { XMVexW, Vex128, EXdVexW, EXdVexW }, 0 },
   },
 
   /* VEX_LEN_0F3A7F_P_2 */
   {
-    { "vfnmsubsd",     { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 }, 0 },
+    { "vfnmsubsd",     { XMVexW, Vex128, EXqVexW, EXqVexW }, 0 },
   },
 
   /* VEX_LEN_0F3ADF_P_2 */
@@ -10161,42 +10192,42 @@ static const struct dis386 vex_len_table[][2] = {
 
   /* VEX_LEN_0FXOP_08_CC */
   {
-     { "vpcomb",       { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomb",       { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_CD */
   {
-     { "vpcomw",       { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomw",       { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_CE */
   {
-     { "vpcomd",       { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomd",       { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_CF */
   {
-     { "vpcomq",       { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomq",       { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_EC */
   {
-     { "vpcomub",      { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomub",      { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_ED */
   {
-     { "vpcomuw",      { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomuw",      { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_EE */
   {
-     { "vpcomud",      { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomud",      { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_08_EF */
   {
-     { "vpcomuq",      { XM, Vex128, EXx, Ib }, 0 },
+     { "vpcomuq",      { XM, Vex128, EXx, VPCOM }, 0 },
   },
 
   /* VEX_LEN_0FXOP_09_80 */
@@ -11267,24 +11298,12 @@ static const struct dis386 vex_w_table[][2] = {
     { "vpbroadcastw",  { XM, EXxmm_mw }, 0 },
   },
   {
-    /* VEX_W_0F38DB_P_2 */
-    { "vaesimc",       { XM, EXx }, 0 },
+    /* VEX_W_0F38CF_P_2 */
+    { "vgf2p8mulb", { XM, Vex, EXx }, 0 },
   },
   {
-    /* VEX_W_0F38DC_P_2 */
-    { "vaesenc",       { XM, Vex128, EXx }, 0 },
-  },
-  {
-    /* VEX_W_0F38DD_P_2 */
-    { "vaesenclast",   { XM, Vex128, EXx }, 0 },
-  },
-  {
-    /* VEX_W_0F38DE_P_2 */
-    { "vaesdec",       { XM, Vex128, EXx }, 0 },
-  },
-  {
-    /* VEX_W_0F38DF_P_2 */
-    { "vaesdeclast",   { XM, Vex128, EXx }, 0 },
+    /* VEX_W_0F38DB_P_2 */
+    { "vaesimc",       { XM, EXx }, 0 },
   },
   {
     /* VEX_W_0F3A00_P_2 */
@@ -11409,10 +11428,6 @@ static const struct dis386 vex_w_table[][2] = {
     { "vmpsadbw",      { XM, Vex, EXx, Ib }, 0 },
   },
   {
-    /* VEX_W_0F3A44_P_2 */
-    { "vpclmulqdq",    { XM, Vex128, EXx, PCLMUL }, 0 },
-  },
-  {
     /* VEX_W_0F3A46_P_2 */
     { "vperm2i128",    { XM, Vex256, EXx, Ib }, 0 },
   },
@@ -11447,6 +11462,16 @@ static const struct dis386 vex_w_table[][2] = {
     { "vpcmpistri",    { XM, EXx, Ib }, 0 },
   },
   {
+    /* VEX_W_0F3ACE_P_2 */
+    { Bad_Opcode },
+    { "vgf2p8affineqb", { XM, Vex, EXx, Ib }, 0 },
+  },
+  {
+    /* VEX_W_0F3ACF_P_2 */
+    { Bad_Opcode },
+    { "vgf2p8affineinvqb",  { XM, Vex, EXx, Ib }, 0 },
+  },
+  {
     /* VEX_W_0F3ADF_P_2 */
     { "vaeskeygenassist", { XM, EXx, Ib }, 0 },
   },
@@ -12784,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;
@@ -12847,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))
        {
@@ -12971,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))
@@ -13011,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++;
@@ -17073,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)
     {
@@ -17097,7 +17115,7 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
          names = names_xmm;
          break;
        case dq_mode:
-         if (vex.w)
+         if (rex & REX_W)
            names = names64;
          else
            names = names32;
@@ -17262,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)
@@ -17355,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);
 }
@@ -17366,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
@@ -17376,8 +17406,6 @@ OP_EX_VexW (int bytemode, int sizeflag)
 
   if (!vex_w_done)
     {
-      vex_w_done = 1;
-
       /* Skip mod/rm byte.  */
       MODRM_CHECK;
       codep++;
@@ -17392,16 +17420,10 @@ OP_EX_VexW (int bytemode, int sizeflag)
     }
 
   OP_EX_VexReg (bytemode, sizeflag, reg);
-}
 
-static void
-VEXI4_Fixup (int bytemode ATTRIBUTE_UNUSED,
-            int sizeflag ATTRIBUTE_UNUSED)
-{
-  /* Skip the immediate byte and check for invalid bits.  */
-  FETCH_DATA (the_info, codep + 1);
-  if (*codep++ & 0xf)
-    BadOp ();
+  if (vex_w_done)
+    codep++;
+  vex_w_done = 1;
 }
 
 static void
@@ -17416,12 +17438,9 @@ OP_REG_VexI4 (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
   if (bytemode != x_mode)
     abort ();
 
-  if (reg & 0xf)
-      BadOp ();
-
   reg >>= 4;
-  if (reg > 7 && address_mode != mode_64bit)
-    BadOp ();
+  if (address_mode != mode_64bit)
+    reg &= 7;
 
   switch (vex.length)
     {
@@ -17596,6 +17615,58 @@ VPCMP_Fixup (int bytemode ATTRIBUTE_UNUSED,
     }
 }
 
+static const struct op xop_cmp_op[] =
+{
+  { STRING_COMMA_LEN ("lt") },
+  { STRING_COMMA_LEN ("le") },
+  { STRING_COMMA_LEN ("gt") },
+  { STRING_COMMA_LEN ("ge") },
+  { STRING_COMMA_LEN ("eq") },
+  { STRING_COMMA_LEN ("neq") },
+  { STRING_COMMA_LEN ("false") },
+  { STRING_COMMA_LEN ("true") }
+};
+
+static void
+VPCOM_Fixup (int bytemode ATTRIBUTE_UNUSED,
+            int sizeflag ATTRIBUTE_UNUSED)
+{
+  unsigned int cmp_type;
+
+  FETCH_DATA (the_info, codep + 1);
+  cmp_type = *codep++ & 0xff;
+  if (cmp_type < ARRAY_SIZE (xop_cmp_op))
+    {
+      char suffix[3];
+      char *p = mnemonicendp - 2;
+
+      /* vpcom* can have both one- and two-lettered suffix.  */
+      if (p[0] == 'm')
+       {
+         p++;
+         suffix[0] = p[0];
+         suffix[1] = '\0';
+       }
+      else
+       {
+         suffix[0] = p[0];
+         suffix[1] = p[1];
+         suffix[2] = '\0';
+       }
+
+      sprintf (p, "%s%s", xop_cmp_op[cmp_type].name, suffix);
+      mnemonicendp += xop_cmp_op[cmp_type].len;
+    }
+  else
+    {
+      /* We have a reserved extension byte.  Output it directly.  */
+      scratchbuf[0] = '$';
+      print_operand_value (scratchbuf + 1, 1, cmp_type);
+      oappend_maybe_intel (scratchbuf);
+      scratchbuf[0] = '\0';
+    }
+}
+
 static const struct op pclmul_op[] =
 {
   { STRING_COMMA_LEN ("lql") },
@@ -17692,7 +17763,7 @@ OP_LWPCB_E (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
   MODRM_CHECK;
   codep++;
 
-  if (vex.w)
+  if (rex & REX_W)
     names = names64;
   else
     names = names32;
@@ -17709,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 (vex.w)
+  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