Teach binutils how to assemble INVPCID and how to disassemble
authorguenther <guenther@openbsd.org>
Sun, 9 Sep 2018 21:59:43 +0000 (21:59 +0000)
committerguenther <guenther@openbsd.org>
Sun, 9 Sep 2018 21:59:43 +0000 (21:59 +0000)
INV{EPT,VPID,PCID}

ok mlarkin@

gnu/usr.bin/binutils-2.17/gas/config/tc-i386.c
gnu/usr.bin/binutils-2.17/include/opcode/i386.h
gnu/usr.bin/binutils-2.17/opcodes/i386-dis.c

index 70422ee..d0f3bb5 100644 (file)
@@ -3464,8 +3464,8 @@ output_insn ()
              goto check_prefix;
            }
        }
-      else if (i.tm.base_opcode == 0x660f3880 || i.tm.base_opcode == 0x660f3881) {
-        /* invept and invvpid are 3 byte instructions with a
+      else if ((i.tm.base_opcode & ~3) == 0x660f3880) {
+        /* INVEPT, INVVPID, and INVPCID are 3 byte instructions with a
            mandatory prefix. */
         prefix = (i.tm.base_opcode >> 24) & 0xff;
         add_prefix (prefix);
@@ -3508,8 +3508,7 @@ check_prefix:
              p = frag_more (3);
              *p++ = (i.tm.base_opcode >> 16) & 0xff;
            }
-          else if (i.tm.base_opcode == 0x660f3880 ||
-                   i.tm.base_opcode == 0x660f3881)
+          else if ((i.tm.base_opcode & ~3) == 0x660f3880)
            {
              p = frag_more (3);
              *p++ = (i.tm.base_opcode >> 16) & 0xff;
index 39155a5..7b31514 100644 (file)
@@ -1530,6 +1530,10 @@ static const template i386_optab[] =
 {"xrstor", 1, 0x0fae, 5, CpuXSAVE, q_Suf|Modrm, { LLongMem, 0, 0 } },
 {"xsaveopt", 1, 0x0fae, 6, CpuXSAVE, q_Suf|Modrm, { LLongMem, 0, 0 } },
 
+/* Intel PCID extension */
+{"invpcid", 2, 0x660f3882, X, CpuNEW|CpuNo64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg32 } },
+{"invpcid", 2, 0x660f3882, X, CpuNEW|Cpu64, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_xSuf|NoRex64, { BaseIndex|Disp8|Disp16|Disp32|Disp32S, Reg64 } },
+
 /* sentinel */
 {NULL, 0, 0, 0, 0, 0, { 0, 0, 0} }
 };
index d27a741..ee34ed3 100644 (file)
@@ -106,6 +106,7 @@ static void VMX_Fixup (int, int);
 static void REP_Fixup (int, int);
 static void OP_0f38 (int, int);
 static void OP_0f3a (int, int);
+static void OP_data (int, int);
 
 struct dis_private {
   /* Points to first byte not fetched.  */
@@ -222,6 +223,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define Ma OP_E, v_mode
 #define M OP_M, 0              /* lea, lgdt, etc. */
 #define Mp OP_M, f_mode                /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Mq OP_M, q_mode                /* 128 bit memory operand for INV{EPT,VPID,PCID} */
 #define Gb OP_G, b_mode
 #define Gv OP_G, v_mode
 #define Gd OP_G, d_mode
@@ -322,6 +324,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
 #define OP0FAE OP_0fae, v_mode
 #define OP0F38 OP_0f38, 0
 #define OP0F3A OP_0f3a, 0
+#define OPDATA OP_data, 0
 
 /* Used handle "rep" prefix for string instructions.  */
 #define Xbr REP_Fixup, eSI_reg
@@ -1910,9 +1913,9 @@ static const struct dis386 three_byte_table[][256] = {
     { "(bad)",         XX, XX, XX },
     { "(bad)",         XX, XX, XX },
     /* 80 */
-    { "(bad)",         XX, XX, XX },
-    { "(bad)",         XX, XX, XX },
-    { "(bad)",         XX, XX, XX },
+    { "invept",                OPDATA, Gm, Mq },
+    { "invvpid",       OPDATA, Gm, Mq },
+    { "invpcid",       OPDATA, Gm, Mq },
     { "(bad)",         XX, XX, XX },
     { "(bad)",         XX, XX, XX },
     { "(bad)",         XX, XX, XX },
@@ -5533,3 +5536,16 @@ OP_0f38 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
   used_prefixes |= (prefixes & PREFIX_DATA);
   USED_REX(rex);
 }
+
+/* suppress/require a mandatory 0x66 data size prefix */
+static void
+OP_data (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  if (prefixes & PREFIX_DATA)
+    used_prefixes |= PREFIX_DATA;
+  else
+    {
+      BadOp();
+      return;
+    }
+}