the Intel manual for details. */
#include "sysdep.h"
-#include "dis-asm.h"
+#include "disassemble.h"
#include "opintl.h"
#include "opcode/i386.h"
#include "libiberty.h"
static void BadOp (void);
static void REP_Fixup (int, int);
static void BND_Fixup (int, int);
+static void NOTRACK_Fixup (int, int);
static void HLE_Fixup1 (int, int);
static void HLE_Fixup2 (int, int);
static void HLE_Fixup3 (int, int);
#define EMS { OP_EM, v_swap_mode }
#define EMd { OP_EM, d_mode }
#define EMx { OP_EM, x_mode }
+#define EXbScalar { OP_EX, b_scalar_mode }
#define EXw { OP_EX, w_mode }
+#define EXwScalar { OP_EX, w_scalar_mode }
#define EXd { OP_EX, d_mode }
#define EXdScalar { OP_EX, d_scalar_mode }
#define EXdS { OP_EX, d_swap_mode }
#define Evh3 { HLE_Fixup3, v_mode }
#define BND { BND_Fixup, 0 }
+#define NOTRACK { NOTRACK_Fixup, 0 }
#define cond_jump_flag { NULL, cond_jump_mode }
#define loop_jcxz_flag { NULL, loop_jcxz_mode }
/* scalar, ignore vector length. */
scalar_mode,
+ /* like b_mode, ignore vector length. */
+ b_scalar_mode,
+ /* like w_mode, ignore vector length. */
+ w_scalar_mode,
/* like d_mode, ignore vector length. */
d_scalar_mode,
/* like d_swap_mode, ignore vector length. */
RM_0F01_REG_5,
RM_0F01_REG_7,
RM_0F1E_MOD_3_REG_7,
- RM_0FAE_REG_5,
RM_0FAE_REG_6,
RM_0FAE_REG_7
};
{
PREFIX_90 = 0,
PREFIX_MOD_0_0F01_REG_5,
- PREFIX_MOD_3_0F01_REG_5_RM_1,
+ PREFIX_MOD_3_0F01_REG_5_RM_0,
PREFIX_MOD_3_0F01_REG_5_RM_2,
PREFIX_0F10,
PREFIX_0F11,
PREFIX_MOD_0_0FAE_REG_4,
PREFIX_MOD_3_0FAE_REG_4,
PREFIX_MOD_0_0FAE_REG_5,
+ PREFIX_MOD_3_0FAE_REG_5,
PREFIX_0FAE_REG_6,
PREFIX_0FAE_REG_7,
PREFIX_0FB8,
PREFIX_0F38CB,
PREFIX_0F38CC,
PREFIX_0F38CD,
+ PREFIX_0F38CF,
PREFIX_0F38DB,
PREFIX_0F38DC,
PREFIX_0F38DD,
PREFIX_0F3A62,
PREFIX_0F3A63,
PREFIX_0F3ACC,
+ PREFIX_0F3ACE,
+ PREFIX_0F3ACF,
PREFIX_0F3ADF,
PREFIX_VEX_0F10,
PREFIX_VEX_0F11,
PREFIX_VEX_0F38BD,
PREFIX_VEX_0F38BE,
PREFIX_VEX_0F38BF,
+ PREFIX_VEX_0F38CF,
PREFIX_VEX_0F38DB,
PREFIX_VEX_0F38DC,
PREFIX_VEX_0F38DD,
PREFIX_VEX_0F3A7D,
PREFIX_VEX_0F3A7E,
PREFIX_VEX_0F3A7F,
+ PREFIX_VEX_0F3ACE,
+ PREFIX_VEX_0F3ACF,
PREFIX_VEX_0F3ADF,
PREFIX_VEX_0F3AF0,
PREFIX_EVEX_0F3859,
PREFIX_EVEX_0F385A,
PREFIX_EVEX_0F385B,
+ PREFIX_EVEX_0F3862,
+ PREFIX_EVEX_0F3863,
PREFIX_EVEX_0F3864,
PREFIX_EVEX_0F3865,
PREFIX_EVEX_0F3866,
+ PREFIX_EVEX_0F3870,
+ PREFIX_EVEX_0F3871,
+ PREFIX_EVEX_0F3872,
+ PREFIX_EVEX_0F3873,
PREFIX_EVEX_0F3875,
PREFIX_EVEX_0F3876,
PREFIX_EVEX_0F3877,
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,
PREFIX_EVEX_0F3A56,
PREFIX_EVEX_0F3A57,
PREFIX_EVEX_0F3A66,
- PREFIX_EVEX_0F3A67
+ PREFIX_EVEX_0F3A67,
+ PREFIX_EVEX_0F3A70,
+ PREFIX_EVEX_0F3A71,
+ PREFIX_EVEX_0F3A72,
+ PREFIX_EVEX_0F3A73,
+ PREFIX_EVEX_0F3ACE,
+ PREFIX_EVEX_0F3ACF
};
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,
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,
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,
EVEX_W_0F3859_P_2,
EVEX_W_0F385A_P_2,
EVEX_W_0F385B_P_2,
+ EVEX_W_0F3862_P_2,
+ EVEX_W_0F3863_P_2,
EVEX_W_0F3866_P_2,
+ EVEX_W_0F3870_P_2,
+ EVEX_W_0F3871_P_2,
+ EVEX_W_0F3872_P_2,
+ EVEX_W_0F3873_P_2,
EVEX_W_0F3875_P_2,
EVEX_W_0F3878_P_2,
EVEX_W_0F3879_P_2,
EVEX_W_0F3A56_P_2,
EVEX_W_0F3A57_P_2,
EVEX_W_0F3A66_P_2,
- EVEX_W_0F3A67_P_2
+ EVEX_W_0F3A67_P_2,
+ EVEX_W_0F3A70_P_2,
+ EVEX_W_0F3A71_P_2,
+ EVEX_W_0F3A72_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);
{ "rcrA", { Eb, Ib }, 0 },
{ "shlA", { Eb, Ib }, 0 },
{ "shrA", { Eb, Ib }, 0 },
- { Bad_Opcode },
+ { "shlA", { Eb, Ib }, 0 },
{ "sarA", { Eb, Ib }, 0 },
},
/* REG_C1 */
{ "rcrQ", { Ev, Ib }, 0 },
{ "shlQ", { Ev, Ib }, 0 },
{ "shrQ", { Ev, Ib }, 0 },
- { Bad_Opcode },
+ { "shlQ", { Ev, Ib }, 0 },
{ "sarQ", { Ev, Ib }, 0 },
},
/* REG_C6 */
{ "rcrA", { Eb, I1 }, 0 },
{ "shlA", { Eb, I1 }, 0 },
{ "shrA", { Eb, I1 }, 0 },
- { Bad_Opcode },
+ { "shlA", { Eb, I1 }, 0 },
{ "sarA", { Eb, I1 }, 0 },
},
/* REG_D1 */
{ "rcrQ", { Ev, I1 }, 0 },
{ "shlQ", { Ev, I1 }, 0 },
{ "shrQ", { Ev, I1 }, 0 },
- { Bad_Opcode },
+ { "shlQ", { Ev, I1 }, 0 },
{ "sarQ", { Ev, I1 }, 0 },
},
/* REG_D2 */
{ "rcrA", { Eb, CL }, 0 },
{ "shlA", { Eb, CL }, 0 },
{ "shrA", { Eb, CL }, 0 },
- { Bad_Opcode },
+ { "shlA", { Eb, CL }, 0 },
{ "sarA", { Eb, CL }, 0 },
},
/* REG_D3 */
{ "rcrQ", { Ev, CL }, 0 },
{ "shlQ", { Ev, CL }, 0 },
{ "shrQ", { Ev, CL }, 0 },
- { Bad_Opcode },
+ { "shlQ", { Ev, CL }, 0 },
{ "sarQ", { Ev, CL }, 0 },
},
/* REG_F6 */
{
{ "incQ", { Evh1 }, 0 },
{ "decQ", { Evh1 }, 0 },
- { "call{&|}", { indirEv, BND }, 0 },
+ { "call{&|}", { NOTRACK, indirEv, BND }, 0 },
{ MOD_TABLE (MOD_FF_REG_3) },
- { "jmp{&|}", { indirEv, BND }, 0 },
+ { "jmp{&|}", { NOTRACK, indirEv, BND }, 0 },
{ MOD_TABLE (MOD_FF_REG_5) },
{ "pushU", { stackEv }, 0 },
{ Bad_Opcode },
{ "rstorssp", { Mq }, PREFIX_OPCODE },
},
- /* PREFIX_MOD_3_0F01_REG_5_RM_1 */
+ /* PREFIX_MOD_3_0F01_REG_5_RM_0 */
{
{ Bad_Opcode },
- { "incsspK", { Skip_MODRM }, PREFIX_OPCODE },
+ { "setssbsy", { Skip_MODRM }, PREFIX_OPCODE },
},
/* PREFIX_MOD_3_0F01_REG_5_RM_2 */
{
{ Bad_Opcode },
- { "savessp", { Skip_MODRM }, PREFIX_OPCODE },
+ { "saveprevssp", { Skip_MODRM }, PREFIX_OPCODE },
},
/* PREFIX_0F10 */
/* PREFIX_MOD_0_0FAE_REG_5 */
{
{ "xrstor", { FXSAVE }, PREFIX_OPCODE },
- { "setssbsy", { Mq }, PREFIX_OPCODE },
+ },
+
+ /* PREFIX_MOD_3_0FAE_REG_5 */
+ {
+ { "lfence", { Skip_MODRM }, 0 },
+ { "incsspK", { Rdq }, PREFIX_OPCODE },
},
/* PREFIX_0FAE_REG_6 */
{ "sha256msg2", { XM, EXxmm }, PREFIX_OPCODE },
},
+ /* PREFIX_0F38CF */
+ {
+ { Bad_Opcode },
+ { Bad_Opcode },
+ { "gf2p8mulb", { XM, EXxmm }, PREFIX_OPCODE },
+ },
+
/* PREFIX_0F38DB */
{
{ Bad_Opcode },
{ "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 },
{ "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 },
{
{ 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 */
{ 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 },
/* X86_64_82 */
{
- /* Opcode 0x82 is an alias of of opcode 0x80 in 32-bit mode. */
+ /* Opcode 0x82 is an alias of opcode 0x80 in 32-bit mode. */
{ REG_TABLE (REG_80) },
},
{ PREFIX_TABLE (PREFIX_0F38CC) },
{ PREFIX_TABLE (PREFIX_0F38CD) },
{ Bad_Opcode },
- { Bad_Opcode },
+ { PREFIX_TABLE (PREFIX_0F38CF) },
/* d0 */
{ Bad_Opcode },
{ Bad_Opcode },
{ 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 },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
- { Bad_Opcode },
+ { PREFIX_TABLE (PREFIX_VEX_0F38CF) },
/* d0 */
{ Bad_Opcode },
{ Bad_Opcode },
{ 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 },
{ 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 },
{ "vpbroadcastw", { XM, EXxmm_mw }, 0 },
},
{
- /* VEX_W_0F38DB_P_2 */
- { "vaesimc", { XM, 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_0F38CF_P_2 */
+ { "vgf2p8mulb", { XM, Vex, 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 */
/* VEX_W_0F3A63_P_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 },
{
/* MOD_0FAE_REG_5 */
{ PREFIX_TABLE (PREFIX_MOD_0_0FAE_REG_5) },
- { RM_TABLE (RM_0FAE_REG_5) },
+ { PREFIX_TABLE (PREFIX_MOD_3_0FAE_REG_5) },
},
{
/* MOD_0FAE_REG_6 */
},
{
/* RM_0F01_REG_5 */
+ { PREFIX_TABLE (PREFIX_MOD_3_0F01_REG_5_RM_0) },
{ Bad_Opcode },
- { PREFIX_TABLE (PREFIX_MOD_3_0F01_REG_5_RM_1) },
{ PREFIX_TABLE (PREFIX_MOD_3_0F01_REG_5_RM_2) },
{ Bad_Opcode },
{ Bad_Opcode },
{ "nopQ", { Ev }, 0 },
{ "nopQ", { Ev }, 0 },
},
- {
- /* RM_0FAE_REG_5 */
- { "lfence", { Skip_MODRM }, 0 },
- },
{
/* RM_0FAE_REG_6 */
{ "mfence", { Skip_MODRM }, 0 },
#define XACQUIRE_PREFIX (0xf2 | 0x200)
#define XRELEASE_PREFIX (0xf3 | 0x400)
#define BND_PREFIX (0xf2 | 0x400)
+#define NOTRACK_PREFIX (0x3e | 0x100)
static int
ckprefix (void)
return "xrelease";
case BND_PREFIX:
return "bnd";
+ case NOTRACK_PREFIX:
+ return "notrack";
default:
return NULL;
}
case x_swap_mode:
case evex_x_gscat_mode:
case evex_x_nobcst_mode:
+ case b_scalar_mode:
+ case w_scalar_mode:
if (need_vex)
{
switch (vex.length)
names = address_mode == mode_64bit ? names64 : names32;
break;
case bnd_mode:
+ if (reg > 0x3)
+ {
+ oappend ("(bad)");
+ return;
+ }
names = names_bnd;
break;
case indir_v_mode:
case d_scalar_swap_mode:
shift = 2;
break;
+ case w_scalar_mode:
case xmm_mw_mode:
shift = 1;
break;
+ case b_scalar_mode:
case xmm_mb_mode:
shift = 0;
break;
oappend (names64[modrm.reg + add]);
break;
case bnd_mode:
+ if (modrm.reg > 0x3)
+ {
+ oappend ("(bad)");
+ return;
+ }
oappend (names_bnd[modrm.reg]);
break;
case v_mode:
all_prefixes[last_repnz_prefix] = BND_PREFIX;
}
+/* For NOTRACK-prefixed instructions, 0x3E prefix should be displayed as
+ "notrack". */
+
+static void
+NOTRACK_Fixup (int bytemode ATTRIBUTE_UNUSED,
+ int sizeflag ATTRIBUTE_UNUSED)
+{
+ if (active_seg_prefix == PREFIX_DS
+ && (address_mode != mode_64bit || last_data_prefix < 0))
+ {
+ /* NOTRACK prefix is only valid on indirect branch instructions.
+ NB: DATA prefix is unsupported for Intel64. */
+ active_seg_prefix = 0;
+ all_prefixes[last_seg_prefix] = NOTRACK_PREFIX;
+ }
+}
+
/* Similar to OP_E. But the 0xf2/0xf3 prefixes should be displayed as
"xacquire"/"xrelease" for memory operand if there is a LOCK prefix.
*/