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);
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;
{"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} }
};
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. */
#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
#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
{ "(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 },
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;
+ }
+}