From 2235ecb8afebeb56baf29eb98de34cfa1b95f697 Mon Sep 17 00:00:00 2001
From: Jan Beulich <jbeulich@suse.com>
Date: Fri, 14 Jan 2022 10:54:21 +0100
Subject: [PATCH] x86: reduce AVX512-FP16 set of insns decoded through
 vex_w_table[]

Like already indicated during review of the original submission, there's
really only very few insns where going through this table is easier /
cheaper than using suitable macros. Utilize %XH more and introduce
similar %XS and %XD (which subsequently can be used for further table
size reduction).

While there also switch to using oappend() in 'XH' macro processing.

diff --git a/opcodes/i386-dis-evex-prefix.h b/opcodes/i386-dis-evex-prefix.h
index 9c8156ac11e..64a43ce02a1 100644
--- a/opcodes/i386-dis-evex-prefix.h
+++ b/opcodes/i386-dis-evex-prefix.h
@@ -375,17 +375,17 @@
     { "vfmsub213s%XW",	{ XMScalar, VexScalar, EXdq, EXxEVexR }, 0 },
     { "v4fnmaddss",	{ XMScalar, VexScalar, Mxmm }, 0 },
   },
-  /* PREFIX_EVEX_0F3A08_W_0 */
+  /* PREFIX_EVEX_0F3A08 */
   {
-    { "vrndscaleph",    { XM, EXxh, EXxEVexS, Ib }, 0 },
+    { "vrndscalep%XH",  { XM, EXxh, EXxEVexS, Ib }, 0 },
     { Bad_Opcode },
-    { "vrndscaleps",    { XM, EXx, EXxEVexS, Ib }, 0 },
+    { "vrndscalep%XS",  { XM, EXx, EXxEVexS, Ib }, 0 },
   },
-  /* PREFIX_EVEX_0F3A0A_W_0 */
+  /* PREFIX_EVEX_0F3A0A */
   {
-    { "vrndscalesh",    { XMScalar, VexScalar, EXw, EXxEVexS, Ib }, 0 },
+    { "vrndscales%XH",  { XMScalar, VexScalar, EXw, EXxEVexS, Ib }, 0 },
     { Bad_Opcode },
-    { "vrndscaless",    { XMScalar, VexScalar, EXd, EXxEVexS, Ib }, 0 },
+    { "vrndscales%XS",  { XMScalar, VexScalar, EXd, EXxEVexS, Ib }, 0 },
   },
   /* PREFIX_EVEX_0F3A26 */
   {
@@ -482,27 +482,18 @@
     { "vmulp%XH", { XM, Vex, EXxh, EXxEVexR }, 0 },
     { "vmuls%XH", { XMM, VexScalar, EXw, EXxEVexR }, 0 },
   },
-  /* PREFIX_EVEX_MAP5_5A_W_0 */
+  /* PREFIX_EVEX_MAP5_5A */
   {
-    { "vcvtph2pd",      { XM, EXxmmqdh, EXxEVexS }, 0 },
-    { "vcvtsh2sd",      { XMM, VexScalar, EXw, EXxEVexS }, 0 },
+    { "vcvtp%XH2pd",    { XM, EXxmmqdh, EXxEVexS }, 0 },
+    { "vcvts%XH2sd",    { XMM, VexScalar, EXw, EXxEVexS }, 0 },
+    { "vcvtp%XD2ph%XZ", { XMM, EXx, EXxEVexR }, 0 },
+    { "vcvts%XD2sh",    { XMM, VexScalar, EXq, EXxEVexR }, 0 },
   },
-  /* PREFIX_EVEX_MAP5_5A_W_1 */
+  /* PREFIX_EVEX_MAP5_5B */
   {
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { "vcvtpd2ph%XZ",   { XMM, EXx, EXxEVexR }, 0 },
-    { "vcvtsd2sh",      { XMM, VexScalar, EXq, EXxEVexR }, 0 },
-  },
-  /* PREFIX_EVEX_MAP5_5B_W_0 */
-  {
-    { "vcvtdq2ph%XY",   { XMxmmq, EXx, EXxEVexR }, 0 },
-    { "vcvttph2dq",     { XM, EXxmmqh, EXxEVexS }, 0 },
-    { "vcvtph2dq",      { XM, EXxmmqh, EXxEVexR }, 0 },
-  },
-  /* PREFIX_EVEX_MAP5_5B_W_1 */
-  {
-    { "vcvtqq2ph%XZ",   { XMM, EXx, EXxEVexR }, 0 },
+    { VEX_W_TABLE (EVEX_W_MAP5_5B_P_0) },
+    { "vcvttp%XH2dq",   { XM, EXxmmqh, EXxEVexS }, 0 },
+    { "vcvtp%XH2dq",    { XM, EXxmmqh, EXxEVexR }, 0 },
   },
   /* PREFIX_EVEX_MAP5_5C */
   {
@@ -526,47 +517,47 @@
   },
   /* PREFIX_EVEX_MAP5_78 */
   {
-    { VEX_W_TABLE (EVEX_W_MAP5_78_P_0) },
+    { "vcvttp%XH2udq",  { XM, EXxmmqh, EXxEVexS }, 0 },
     { "vcvttsh2usi",    { Gdq, EXw, EXxEVexS }, 0 },
-    { VEX_W_TABLE (EVEX_W_MAP5_78_P_2) },
+    { "vcvttp%XH2uqq",  { XM, EXxmmqdh, EXxEVexS }, 0 },
   },
   /* PREFIX_EVEX_MAP5_79 */
   {
-    { VEX_W_TABLE (EVEX_W_MAP5_79_P_0) },
+    { "vcvtp%XH2udq",   { XM, EXxmmqh, EXxEVexR }, 0 },
     { "vcvtsh2usi",     { Gdq, EXw, EXxEVexR }, 0 },
-    { VEX_W_TABLE (EVEX_W_MAP5_79_P_2) },
+    { "vcvtp%XH2uqq",   { XM, EXxmmqdh, EXxEVexR }, 0 },
   },
   /* PREFIX_EVEX_MAP5_7A */
   {
     { Bad_Opcode },
     { Bad_Opcode },
-    { VEX_W_TABLE (EVEX_W_MAP5_7A_P_2) },
+    { "vcvttp%XH2qq",   { XM, EXxmmqdh, EXxEVexS }, 0 },
     { VEX_W_TABLE (EVEX_W_MAP5_7A_P_3) },
   },
   /* PREFIX_EVEX_MAP5_7B */
   {
     { Bad_Opcode },
     { "vcvtusi2sh{%LQ|}",       { XMScalar, VexScalar, EXxEVexR, Edq }, 0 },
-    { VEX_W_TABLE (EVEX_W_MAP5_7B_P_2) },
+    { "vcvtp%XH2qq",    { XM, EXxmmqdh, EXxEVexR }, 0 },
   },
   /* PREFIX_EVEX_MAP5_7C */
   {
-    { VEX_W_TABLE (EVEX_W_MAP5_7C_P_0) },
+    { "vcvttp%XH2uw",   { XM, EXxh, EXxEVexS }, 0 },
     { Bad_Opcode },
-    { VEX_W_TABLE (EVEX_W_MAP5_7C_P_2) },
+    { "vcvttp%XH2w",    { XM, EXxh, EXxEVexS }, 0 },
   },
-  /* PREFIX_EVEX_MAP5_7D_W_0 */
+  /* PREFIX_EVEX_MAP5_7D */
   {
-    { "vcvtph2uw",      { XM, EXxh, EXxEVexR }, 0 },
-    { "vcvtw2ph",       { XM, EXxh, EXxEVexR }, 0 },
-    { "vcvtph2w",       { XM, EXxh, EXxEVexR }, 0 },
-    { "vcvtuw2ph",      { XM, EXxh, EXxEVexR }, 0 },
+    { "vcvtp%XH2uw",    { XM, EXxh, EXxEVexR }, 0 },
+    { "vcvtw2p%XH",     { XM, EXxh, EXxEVexR }, 0 },
+    { "vcvtp%XH2w",     { XM, EXxh, EXxEVexR }, 0 },
+    { "vcvtuw2p%XH",    { XM, EXxh, EXxEVexR }, 0 },
   },
   /* PREFIX_EVEX_MAP6_13 */
   {
-    { VEX_W_TABLE (EVEX_W_MAP6_13_P_0) },
+    { "vcvts%XH2ss",	{ XMM, VexScalar, EXw, EXxEVexS }, 0 },
     { Bad_Opcode },
-    { VEX_W_TABLE (EVEX_W_MAP6_13_P_2) },
+    { "vcvtp%XH2psx",	{ XM, EXxmmqh, EXxEVexS }, 0 },
   },
   /* PREFIX_EVEX_MAP6_56 */
   {
diff --git a/opcodes/i386-dis-evex-w.h b/opcodes/i386-dis-evex-w.h
index 62c3d3b9afb..fc0a0791d1d 100644
--- a/opcodes/i386-dis-evex-w.h
+++ b/opcodes/i386-dis-evex-w.h
@@ -550,19 +550,11 @@
     { Bad_Opcode },
     { "vpermilpd",	{ XM, EXx, Ib }, PREFIX_DATA },
   },
-  /* EVEX_W_0F3A08 */
-  {
-    { PREFIX_TABLE (PREFIX_EVEX_0F3A08_W_0) },
-  },
   /* EVEX_W_0F3A09 */
   {
     { Bad_Opcode },
     { "vrndscalepd",	{ XM, EXx, EXxEVexS, Ib }, PREFIX_DATA },
   },
-  /* EVEX_W_0F3A0A */
-  {
-    { PREFIX_TABLE (PREFIX_EVEX_0F3A0A_W_0) },
-  },
   /* EVEX_W_0F3A0B */
   {
     { Bad_Opcode },
@@ -636,62 +628,13 @@
     { Bad_Opcode },
     { "vpshrdw",   { XM, Vex, EXx, Ib }, 0 },
   },
-  /* EVEX_W_MAP5_5A */
-  {
-    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5A_W_0) },
-    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5A_W_1) },
-  },
-  /* EVEX_W_MAP5_5B */
-  {
-    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5B_W_0) },
-    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5B_W_1) },
-  },
-  /* EVEX_W_MAP5_78_P_0 */
-  {
-    { "vcvttph2udq",	{ XM, EXxmmqh, EXxEVexS }, 0 },
-  },
-  /* EVEX_W_MAP5_78_P_2 */
-  {
-    { "vcvttph2uqq",	{ XM, EXxmmqdh, EXxEVexS }, 0 },
-  },
-  /* EVEX_W_MAP5_79_P_0 */
-  {
-    { "vcvtph2udq",	{ XM, EXxmmqh, EXxEVexR }, 0 },
-  },
-  /* EVEX_W_MAP5_79_P_2 */
+  /* EVEX_W_MAP5_5B_P_0 */
   {
-    { "vcvtph2uqq",	{ XM, EXxmmqdh, EXxEVexR }, 0 },
-  },
-  /* EVEX_W_MAP5_7A_P_2 */
-  {
-    { "vcvttph2qq",	{ XM, EXxmmqdh, EXxEVexS }, 0 },
+    { "vcvtdq2ph%XY",	{ XMxmmq, EXx, EXxEVexR }, 0 },
+    { "vcvtqq2ph%XZ",	{ XMM, EXx, EXxEVexR }, 0 },
   },
   /* EVEX_W_MAP5_7A_P_3 */
   {
     { "vcvtudq2ph%XY",	{ XMxmmq, EXx, EXxEVexR }, 0 },
     { "vcvtuqq2ph%XZ",	{ XMM, EXx, EXxEVexR }, 0 },
   },
-  /* EVEX_W_MAP5_7B_P_2 */
-  {
-    { "vcvtph2qq",	{ XM, EXxmmqdh, EXxEVexR }, 0 },
-  },
-  /* EVEX_W_MAP5_7C_P_0 */
-  {
-    { "vcvttph2uw",	{ XM, EXxh, EXxEVexS }, 0 },
-  },
-  /* EVEX_W_MAP5_7C_P_2 */
-  {
-    { "vcvttph2w",	{ XM, EXxh, EXxEVexS }, 0 },
-  },
-  /* EVEX_W_MAP5_7D */
-  {
-    { PREFIX_TABLE (PREFIX_EVEX_MAP5_7D_W_0) },
-  },
-  /* EVEX_W_MAP6_13_P_0 */
-  {
-    { "vcvtsh2ss",	{ XMM, VexScalar, EXw, EXxEVexS }, 0 },
-  },
-  /* EVEX_W_MAP6_13_P_2 */
-  {
-    { "vcvtph2psx",	{ XM, EXxmmqh, EXxEVexS }, 0 },
-  },
diff --git a/opcodes/i386-dis-evex.h b/opcodes/i386-dis-evex.h
index d79c78c1793..11cc257bb2e 100644
--- a/opcodes/i386-dis-evex.h
+++ b/opcodes/i386-dis-evex.h
@@ -593,9 +593,9 @@ static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     /* 08 */
-    { VEX_W_TABLE (EVEX_W_0F3A08) },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A08) },
     { VEX_W_TABLE (EVEX_W_0F3A09) },
-    { VEX_W_TABLE (EVEX_W_0F3A0A) },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A0A) },
     { VEX_W_TABLE (EVEX_W_0F3A0B) },
     { Bad_Opcode },
     { Bad_Opcode },
@@ -976,8 +976,8 @@ static const struct dis386 evex_table[][256] = {
     /* 58 */
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_58) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_59) },
-    { VEX_W_TABLE (EVEX_W_MAP5_5A) },
-    { VEX_W_TABLE (EVEX_W_MAP5_5B) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5A) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP5_5B) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_5C) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_5D) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_5E) },
@@ -1015,7 +1015,7 @@ static const struct dis386 evex_table[][256] = {
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_7A) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_7B) },
     { PREFIX_TABLE (PREFIX_EVEX_MAP5_7C) },
-    { VEX_W_TABLE (EVEX_W_MAP5_7D) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP5_7D) },
     { "vmovw",	  { Edw, XMScalar }, PREFIX_DATA },
     { Bad_Opcode },
     /* 80 */
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 4e0e1559339..afc3743e4e8 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -1212,8 +1212,8 @@ enum
   PREFIX_EVEX_0F38AA,
   PREFIX_EVEX_0F38AB,
 
-  PREFIX_EVEX_0F3A08_W_0,
-  PREFIX_EVEX_0F3A0A_W_0,
+  PREFIX_EVEX_0F3A08,
+  PREFIX_EVEX_0F3A0A,
   PREFIX_EVEX_0F3A26,
   PREFIX_EVEX_0F3A27,
   PREFIX_EVEX_0F3A56,
@@ -1233,10 +1233,8 @@ enum
   PREFIX_EVEX_MAP5_51,
   PREFIX_EVEX_MAP5_58,
   PREFIX_EVEX_MAP5_59,
-  PREFIX_EVEX_MAP5_5A_W_0,
-  PREFIX_EVEX_MAP5_5A_W_1,
-  PREFIX_EVEX_MAP5_5B_W_0,
-  PREFIX_EVEX_MAP5_5B_W_1,
+  PREFIX_EVEX_MAP5_5A,
+  PREFIX_EVEX_MAP5_5B,
   PREFIX_EVEX_MAP5_5C,
   PREFIX_EVEX_MAP5_5D,
   PREFIX_EVEX_MAP5_5E,
@@ -1246,7 +1244,7 @@ enum
   PREFIX_EVEX_MAP5_7A,
   PREFIX_EVEX_MAP5_7B,
   PREFIX_EVEX_MAP5_7C,
-  PREFIX_EVEX_MAP5_7D_W_0,
+  PREFIX_EVEX_MAP5_7D,
 
   PREFIX_EVEX_MAP6_13,
   PREFIX_EVEX_MAP6_56,
@@ -1746,9 +1744,7 @@ enum
   EVEX_W_0F3883,
 
   EVEX_W_0F3A05,
-  EVEX_W_0F3A08,
   EVEX_W_0F3A09,
-  EVEX_W_0F3A0A,
   EVEX_W_0F3A0B,
   EVEX_W_0F3A18_L_n,
   EVEX_W_0F3A19_L_n,
@@ -1765,21 +1761,8 @@ enum
   EVEX_W_0F3A70,
   EVEX_W_0F3A72,
 
-  EVEX_W_MAP5_5A,
-  EVEX_W_MAP5_5B,
-  EVEX_W_MAP5_78_P_0,
-  EVEX_W_MAP5_78_P_2,
-  EVEX_W_MAP5_79_P_0,
-  EVEX_W_MAP5_79_P_2,
-  EVEX_W_MAP5_7A_P_2,
+  EVEX_W_MAP5_5B_P_0,
   EVEX_W_MAP5_7A_P_3,
-  EVEX_W_MAP5_7B_P_2,
-  EVEX_W_MAP5_7C_P_0,
-  EVEX_W_MAP5_7C_P_2,
-  EVEX_W_MAP5_7D,
-
-  EVEX_W_MAP6_13_P_0,
-  EVEX_W_MAP6_13_P_2,
 };
 
 typedef void (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
@@ -1840,7 +1823,9 @@ struct dis386 {
    "XZ" => print 'x', 'y', or 'z' if suffix_always is true or no
 	   register operands and no broadcast.
    "XW" => print 's', 'd' depending on the VEX.W bit (for FMA)
+   "XD" => print 'd' if EVEX.W=1, EVEX.W=0 is not a valid encoding
    "XH" => print 'h' if EVEX.W=0, EVEX.W=1 is not a valid encoding (for FP16)
+   "XS" => print 's' if EVEX.W=0, EVEX.W=1 is not a valid encoding
    "XV" => print "{vex3}" pseudo prefix
    "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand, cond
 	   being false, or no operand at all in 64bit mode, or if suffix_always
@@ -10496,6 +10481,23 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
 	    }
 	  break;
 	case 'D':
+	  if (l == 1)
+	    {
+	      switch (last[0])
+	      {
+	      case 'X':
+		if (ins->vex.w)
+		  *ins->obufp++ = 'd';
+		else
+		  oappend (ins, "{bad}");
+		break;
+	      default:
+		abort ();
+	      }
+	      break;
+	    }
+	  if (l)
+	    abort ();
 	  if (ins->intel_syntax || !(sizeflag & SUFFIX_ALWAYS))
 	    break;
 	  USED_REX (REX_W);
@@ -10582,13 +10584,7 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
 	      if (ins->vex.w == 0)
 		*ins->obufp++ = 'h';
 	      else
-		{
-		  *ins->obufp++ = '{';
-		  *ins->obufp++ = 'b';
-		  *ins->obufp++ = 'a';
-		  *ins->obufp++ = 'd';
-		  *ins->obufp++ = '}';
-		}
+		oappend (ins, "{bad}");
 	    }
 	  else
 	    abort ();
@@ -10752,9 +10748,13 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
 		      ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
 		    }
 		}
+	      break;
 	    }
-	  else if (l == 1 && last[0] == 'L')
+	  if (l != 1)
+	    abort ();
+	  switch (last[0])
 	    {
+	    case 'L':
 	      if (ins->address_mode == mode_64bit
 		  && !(ins->prefixes & PREFIX_ADDR))
 		{
@@ -10764,9 +10764,15 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
 		}
 
 	      goto case_S;
+	    case 'X':
+	      if (!ins->vex.w)
+		*ins->obufp++ = 's';
+	      else
+		oappend (ins, "{bad}");
+	      break;
+	    default:
+	      abort ();
 	    }
-	  else
-	    abort ();
 	  break;
 	case 'V':
 	  if (l == 0)
-- 
2.33.0

