use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McDisasmSyntax {
Att,
Intel,
Annotated,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McProcessorMode {
Mode16,
Mode32,
Mode64,
}
impl McProcessorMode {
pub fn default_operand_size(&self) -> u8 {
match self {
McProcessorMode::Mode16 => 16,
McProcessorMode::Mode32 => 32,
McProcessorMode::Mode64 => 32,
}
}
pub fn default_address_size(&self) -> u8 {
match self {
McProcessorMode::Mode16 => 16,
McProcessorMode::Mode32 => 32,
McProcessorMode::Mode64 => 64,
}
}
pub fn is_64bit(&self) -> bool {
matches!(self, McProcessorMode::Mode64)
}
}
#[derive(Debug, Clone, Default)]
pub struct McLegacyPrefixes {
pub has_lock: bool,
pub has_repne: bool,
pub has_rep: bool,
pub cs_override: bool,
pub ds_override: bool,
pub ss_override: bool,
pub es_override: bool,
pub fs_override: bool,
pub gs_override: bool,
pub has_operand_size_override: bool,
pub has_address_size_override: bool,
pub active_segment_override: Option<McSegmentOverride>,
pub effective_operand_size: u8,
pub effective_address_size: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McSegmentOverride {
CS,
DS,
SS,
ES,
FS,
GS,
}
impl McSegmentOverride {
pub fn name(&self) -> &'static str {
match self {
McSegmentOverride::CS => "cs",
McSegmentOverride::DS => "ds",
McSegmentOverride::SS => "ss",
McSegmentOverride::ES => "es",
McSegmentOverride::FS => "fs",
McSegmentOverride::GS => "gs",
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McRexInfo {
pub present: bool,
pub w: bool,
pub r: bool,
pub x: bool,
pub b: bool,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McVexInfo {
pub present: bool,
pub is_3byte: bool,
pub r: bool,
pub x: bool,
pub b: bool,
pub w: bool,
pub vvvv: u8,
pub l: bool,
pub pp: u8,
pub mmmmm: u8,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McEvexInfo {
pub present: bool,
pub r_prime: bool,
pub x_prime: bool,
pub b_prime: bool,
pub r: bool,
pub x: bool,
pub b: bool,
pub v_prime: bool,
pub w: bool,
pub z: bool,
pub aaa: u8,
pub ll: u8,
pub b_bit: bool,
pub pp: u8,
pub mm: u8,
pub vvvv: u8,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McModRM {
pub raw: u8,
pub mod_field: u8,
pub reg_field: u8,
pub rm_field: u8,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McSIB {
pub raw: u8,
pub scale: u8,
pub index_field: u8,
pub base_field: u8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum McX86Reg {
AL,
CL,
DL,
BL,
AH,
CH,
DH,
BH,
SPL,
BPL,
SIL,
DIL,
R8B,
R9B,
R10B,
R11B,
R12B,
R13B,
R14B,
R15B,
R16B,
R17B,
R18B,
R19B,
R20B,
R21B,
R22B,
R23B,
R24B,
R25B,
R26B,
R27B,
R28B,
R29B,
R30B,
R31B,
AX,
CX,
DX,
BX,
SP,
BP,
SI,
DI,
R8W,
R9W,
R10W,
R11W,
R12W,
R13W,
R14W,
R15W,
R16W,
R17W,
R18W,
R19W,
R20W,
R21W,
R22W,
R23W,
R24W,
R25W,
R26W,
R27W,
R28W,
R29W,
R30W,
R31W,
EAX,
ECX,
EDX,
EBX,
ESP,
EBP,
ESI,
EDI,
R8D,
R9D,
R10D,
R11D,
R12D,
R13D,
R14D,
R15D,
R16D,
R17D,
R18D,
R19D,
R20D,
R21D,
R22D,
R23D,
R24D,
R25D,
R26D,
R27D,
R28D,
R29D,
R30D,
R31D,
RAX,
RCX,
RDX,
RBX,
RSP,
RBP,
RSI,
RDI,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
R16,
R17,
R18,
R19,
R20,
R21,
R22,
R23,
R24,
R25,
R26,
R27,
R28,
R29,
R30,
R31,
SR_ES,
SR_CS,
SR_SS,
SR_DS,
SR_FS,
SR_GS,
CR0,
CR2,
CR3,
CR4,
CR8,
DR0,
DR1,
DR2,
DR3,
DR6,
DR7,
MM0,
MM1,
MM2,
MM3,
MM4,
MM5,
MM6,
MM7,
XMM0,
XMM1,
XMM2,
XMM3,
XMM4,
XMM5,
XMM6,
XMM7,
XMM8,
XMM9,
XMM10,
XMM11,
XMM12,
XMM13,
XMM14,
XMM15,
XMM16,
XMM17,
XMM18,
XMM19,
XMM20,
XMM21,
XMM22,
XMM23,
XMM24,
XMM25,
XMM26,
XMM27,
XMM28,
XMM29,
XMM30,
XMM31,
YMM0,
YMM1,
YMM2,
YMM3,
YMM4,
YMM5,
YMM6,
YMM7,
YMM8,
YMM9,
YMM10,
YMM11,
YMM12,
YMM13,
YMM14,
YMM15,
YMM16,
YMM17,
YMM18,
YMM19,
YMM20,
YMM21,
YMM22,
YMM23,
YMM24,
YMM25,
YMM26,
YMM27,
YMM28,
YMM29,
YMM30,
YMM31,
ZMM0,
ZMM1,
ZMM2,
ZMM3,
ZMM4,
ZMM5,
ZMM6,
ZMM7,
ZMM8,
ZMM9,
ZMM10,
ZMM11,
ZMM12,
ZMM13,
ZMM14,
ZMM15,
ZMM16,
ZMM17,
ZMM18,
ZMM19,
ZMM20,
ZMM21,
ZMM22,
ZMM23,
ZMM24,
ZMM25,
ZMM26,
ZMM27,
ZMM28,
ZMM29,
ZMM30,
ZMM31,
K0,
K1,
K2,
K3,
K4,
K5,
K6,
K7,
ST0,
ST1,
ST2,
ST3,
ST4,
ST5,
ST6,
ST7,
TMM0,
TMM1,
TMM2,
TMM3,
TMM4,
TMM5,
TMM6,
TMM7,
BND0,
BND1,
BND2,
BND3,
}
impl McX86Reg {
pub fn name(&self) -> &'static str {
match self {
McX86Reg::AL => "al",
McX86Reg::CL => "cl",
McX86Reg::DL => "dl",
McX86Reg::BL => "bl",
McX86Reg::AH => "ah",
McX86Reg::CH => "ch",
McX86Reg::DH => "dh",
McX86Reg::BH => "bh",
McX86Reg::SPL => "spl",
McX86Reg::BPL => "bpl",
McX86Reg::SIL => "sil",
McX86Reg::DIL => "dil",
McX86Reg::R8B => "r8b",
McX86Reg::R9B => "r9b",
McX86Reg::R10B => "r10b",
McX86Reg::R11B => "r11b",
McX86Reg::R12B => "r12b",
McX86Reg::R13B => "r13b",
McX86Reg::R14B => "r14b",
McX86Reg::R15B => "r15b",
McX86Reg::R16B => "r16b",
McX86Reg::R17B => "r17b",
McX86Reg::R18B => "r18b",
McX86Reg::R19B => "r19b",
McX86Reg::R20B => "r20b",
McX86Reg::R21B => "r21b",
McX86Reg::R22B => "r22b",
McX86Reg::R23B => "r23b",
McX86Reg::R24B => "r24b",
McX86Reg::R25B => "r25b",
McX86Reg::R26B => "r26b",
McX86Reg::R27B => "r27b",
McX86Reg::R28B => "r28b",
McX86Reg::R29B => "r29b",
McX86Reg::R30B => "r30b",
McX86Reg::R31B => "r31b",
McX86Reg::AX => "ax",
McX86Reg::CX => "cx",
McX86Reg::DX => "dx",
McX86Reg::BX => "bx",
McX86Reg::SP => "sp",
McX86Reg::BP => "bp",
McX86Reg::SI => "si",
McX86Reg::DI => "di",
McX86Reg::R8W => "r8w",
McX86Reg::R9W => "r9w",
McX86Reg::R10W => "r10w",
McX86Reg::R11W => "r11w",
McX86Reg::R12W => "r12w",
McX86Reg::R13W => "r13w",
McX86Reg::R14W => "r14w",
McX86Reg::R15W => "r15w",
McX86Reg::R16W => "r16w",
McX86Reg::R17W => "r17w",
McX86Reg::R18W => "r18w",
McX86Reg::R19W => "r19w",
McX86Reg::R20W => "r20w",
McX86Reg::R21W => "r21w",
McX86Reg::R22W => "r22w",
McX86Reg::R23W => "r23w",
McX86Reg::R24W => "r24w",
McX86Reg::R25W => "r25w",
McX86Reg::R26W => "r26w",
McX86Reg::R27W => "r27w",
McX86Reg::R28W => "r28w",
McX86Reg::R29W => "r29w",
McX86Reg::R30W => "r30w",
McX86Reg::R31W => "r31w",
McX86Reg::EAX => "eax",
McX86Reg::ECX => "ecx",
McX86Reg::EDX => "edx",
McX86Reg::EBX => "ebx",
McX86Reg::ESP => "esp",
McX86Reg::EBP => "ebp",
McX86Reg::ESI => "esi",
McX86Reg::EDI => "edi",
McX86Reg::R8D => "r8d",
McX86Reg::R9D => "r9d",
McX86Reg::R10D => "r10d",
McX86Reg::R11D => "r11d",
McX86Reg::R12D => "r12d",
McX86Reg::R13D => "r13d",
McX86Reg::R14D => "r14d",
McX86Reg::R15D => "r15d",
McX86Reg::R16D => "r16d",
McX86Reg::R17D => "r17d",
McX86Reg::R18D => "r18d",
McX86Reg::R19D => "r19d",
McX86Reg::R20D => "r20d",
McX86Reg::R21D => "r21d",
McX86Reg::R22D => "r22d",
McX86Reg::R23D => "r23d",
McX86Reg::R24D => "r24d",
McX86Reg::R25D => "r25d",
McX86Reg::R26D => "r26d",
McX86Reg::R27D => "r27d",
McX86Reg::R28D => "r28d",
McX86Reg::R29D => "r29d",
McX86Reg::R30D => "r30d",
McX86Reg::R31D => "r31d",
McX86Reg::RAX => "rax",
McX86Reg::RCX => "rcx",
McX86Reg::RDX => "rdx",
McX86Reg::RBX => "rbx",
McX86Reg::RSP => "rsp",
McX86Reg::RBP => "rbp",
McX86Reg::RSI => "rsi",
McX86Reg::RDI => "rdi",
McX86Reg::R8 => "r8",
McX86Reg::R9 => "r9",
McX86Reg::R10 => "r10",
McX86Reg::R11 => "r11",
McX86Reg::R12 => "r12",
McX86Reg::R13 => "r13",
McX86Reg::R14 => "r14",
McX86Reg::R15 => "r15",
McX86Reg::R16 => "r16",
McX86Reg::R17 => "r17",
McX86Reg::R18 => "r18",
McX86Reg::R19 => "r19",
McX86Reg::R20 => "r20",
McX86Reg::R21 => "r21",
McX86Reg::R22 => "r22",
McX86Reg::R23 => "r23",
McX86Reg::R24 => "r24",
McX86Reg::R25 => "r25",
McX86Reg::R26 => "r26",
McX86Reg::R27 => "r27",
McX86Reg::R28 => "r28",
McX86Reg::R29 => "r29",
McX86Reg::R30 => "r30",
McX86Reg::R31 => "r31",
McX86Reg::SR_ES => "es",
McX86Reg::SR_CS => "cs",
McX86Reg::SR_SS => "ss",
McX86Reg::SR_DS => "ds",
McX86Reg::SR_FS => "fs",
McX86Reg::SR_GS => "gs",
McX86Reg::CR0 => "cr0",
McX86Reg::CR2 => "cr2",
McX86Reg::CR3 => "cr3",
McX86Reg::CR4 => "cr4",
McX86Reg::CR8 => "cr8",
McX86Reg::DR0 => "dr0",
McX86Reg::DR1 => "dr1",
McX86Reg::DR2 => "dr2",
McX86Reg::DR3 => "dr3",
McX86Reg::DR6 => "dr6",
McX86Reg::DR7 => "dr7",
McX86Reg::MM0 => "mm0",
McX86Reg::MM1 => "mm1",
McX86Reg::MM2 => "mm2",
McX86Reg::MM3 => "mm3",
McX86Reg::MM4 => "mm4",
McX86Reg::MM5 => "mm5",
McX86Reg::MM6 => "mm6",
McX86Reg::MM7 => "mm7",
McX86Reg::XMM0 => "xmm0",
McX86Reg::XMM1 => "xmm1",
McX86Reg::XMM2 => "xmm2",
McX86Reg::XMM3 => "xmm3",
McX86Reg::XMM4 => "xmm4",
McX86Reg::XMM5 => "xmm5",
McX86Reg::XMM6 => "xmm6",
McX86Reg::XMM7 => "xmm7",
McX86Reg::XMM8 => "xmm8",
McX86Reg::XMM9 => "xmm9",
McX86Reg::XMM10 => "xmm10",
McX86Reg::XMM11 => "xmm11",
McX86Reg::XMM12 => "xmm12",
McX86Reg::XMM13 => "xmm13",
McX86Reg::XMM14 => "xmm14",
McX86Reg::XMM15 => "xmm15",
McX86Reg::XMM16 => "xmm16",
McX86Reg::XMM17 => "xmm17",
McX86Reg::XMM18 => "xmm18",
McX86Reg::XMM19 => "xmm19",
McX86Reg::XMM20 => "xmm20",
McX86Reg::XMM21 => "xmm21",
McX86Reg::XMM22 => "xmm22",
McX86Reg::XMM23 => "xmm23",
McX86Reg::XMM24 => "xmm24",
McX86Reg::XMM25 => "xmm25",
McX86Reg::XMM26 => "xmm26",
McX86Reg::XMM27 => "xmm27",
McX86Reg::XMM28 => "xmm28",
McX86Reg::XMM29 => "xmm29",
McX86Reg::XMM30 => "xmm30",
McX86Reg::XMM31 => "xmm31",
McX86Reg::YMM0 => "ymm0",
McX86Reg::YMM1 => "ymm1",
McX86Reg::YMM2 => "ymm2",
McX86Reg::YMM3 => "ymm3",
McX86Reg::YMM4 => "ymm4",
McX86Reg::YMM5 => "ymm5",
McX86Reg::YMM6 => "ymm6",
McX86Reg::YMM7 => "ymm7",
McX86Reg::YMM8 => "ymm8",
McX86Reg::YMM9 => "ymm9",
McX86Reg::YMM10 => "ymm10",
McX86Reg::YMM11 => "ymm11",
McX86Reg::YMM12 => "ymm12",
McX86Reg::YMM13 => "ymm13",
McX86Reg::YMM14 => "ymm14",
McX86Reg::YMM15 => "ymm15",
McX86Reg::YMM16 => "ymm16",
McX86Reg::YMM17 => "ymm17",
McX86Reg::YMM18 => "ymm18",
McX86Reg::YMM19 => "ymm19",
McX86Reg::YMM20 => "ymm20",
McX86Reg::YMM21 => "ymm21",
McX86Reg::YMM22 => "ymm22",
McX86Reg::YMM23 => "ymm23",
McX86Reg::YMM24 => "ymm24",
McX86Reg::YMM25 => "ymm25",
McX86Reg::YMM26 => "ymm26",
McX86Reg::YMM27 => "ymm27",
McX86Reg::YMM28 => "ymm28",
McX86Reg::YMM29 => "ymm29",
McX86Reg::YMM30 => "ymm30",
McX86Reg::YMM31 => "ymm31",
McX86Reg::ZMM0 => "zmm0",
McX86Reg::ZMM1 => "zmm1",
McX86Reg::ZMM2 => "zmm2",
McX86Reg::ZMM3 => "zmm3",
McX86Reg::ZMM4 => "zmm4",
McX86Reg::ZMM5 => "zmm5",
McX86Reg::ZMM6 => "zmm6",
McX86Reg::ZMM7 => "zmm7",
McX86Reg::ZMM8 => "zmm8",
McX86Reg::ZMM9 => "zmm9",
McX86Reg::ZMM10 => "zmm10",
McX86Reg::ZMM11 => "zmm11",
McX86Reg::ZMM12 => "zmm12",
McX86Reg::ZMM13 => "zmm13",
McX86Reg::ZMM14 => "zmm14",
McX86Reg::ZMM15 => "zmm15",
McX86Reg::ZMM16 => "zmm16",
McX86Reg::ZMM17 => "zmm17",
McX86Reg::ZMM18 => "zmm18",
McX86Reg::ZMM19 => "zmm19",
McX86Reg::ZMM20 => "zmm20",
McX86Reg::ZMM21 => "zmm21",
McX86Reg::ZMM22 => "zmm22",
McX86Reg::ZMM23 => "zmm23",
McX86Reg::ZMM24 => "zmm24",
McX86Reg::ZMM25 => "zmm25",
McX86Reg::ZMM26 => "zmm26",
McX86Reg::ZMM27 => "zmm27",
McX86Reg::ZMM28 => "zmm28",
McX86Reg::ZMM29 => "zmm29",
McX86Reg::ZMM30 => "zmm30",
McX86Reg::ZMM31 => "zmm31",
McX86Reg::K0 => "k0",
McX86Reg::K1 => "k1",
McX86Reg::K2 => "k2",
McX86Reg::K3 => "k3",
McX86Reg::K4 => "k4",
McX86Reg::K5 => "k5",
McX86Reg::K6 => "k6",
McX86Reg::K7 => "k7",
McX86Reg::ST0 => "st(0)",
McX86Reg::ST1 => "st(1)",
McX86Reg::ST2 => "st(2)",
McX86Reg::ST3 => "st(3)",
McX86Reg::ST4 => "st(4)",
McX86Reg::ST5 => "st(5)",
McX86Reg::ST6 => "st(6)",
McX86Reg::ST7 => "st(7)",
McX86Reg::TMM0 => "tmm0",
McX86Reg::TMM1 => "tmm1",
McX86Reg::TMM2 => "tmm2",
McX86Reg::TMM3 => "tmm3",
McX86Reg::TMM4 => "tmm4",
McX86Reg::TMM5 => "tmm5",
McX86Reg::TMM6 => "tmm6",
McX86Reg::TMM7 => "tmm7",
McX86Reg::BND0 => "bnd0",
McX86Reg::BND1 => "bnd1",
McX86Reg::BND2 => "bnd2",
McX86Reg::BND3 => "bnd3",
}
}
pub fn size_suffix(&self) -> &'static str {
match self {
McX86Reg::AL
| McX86Reg::CL
| McX86Reg::DL
| McX86Reg::BL
| McX86Reg::AH
| McX86Reg::CH
| McX86Reg::DH
| McX86Reg::BH
| McX86Reg::SPL
| McX86Reg::BPL
| McX86Reg::SIL
| McX86Reg::DIL
| McX86Reg::R8B
| McX86Reg::R9B
| McX86Reg::R10B
| McX86Reg::R11B
| McX86Reg::R12B
| McX86Reg::R13B
| McX86Reg::R14B
| McX86Reg::R15B
| McX86Reg::R16B
| McX86Reg::R17B
| McX86Reg::R18B
| McX86Reg::R19B
| McX86Reg::R20B
| McX86Reg::R21B
| McX86Reg::R22B
| McX86Reg::R23B
| McX86Reg::R24B
| McX86Reg::R25B
| McX86Reg::R26B
| McX86Reg::R27B
| McX86Reg::R28B
| McX86Reg::R29B
| McX86Reg::R30B
| McX86Reg::R31B => "b",
McX86Reg::AX
| McX86Reg::CX
| McX86Reg::DX
| McX86Reg::BX
| McX86Reg::SP
| McX86Reg::BP
| McX86Reg::SI
| McX86Reg::DI
| McX86Reg::R8W
| McX86Reg::R9W
| McX86Reg::R10W
| McX86Reg::R11W
| McX86Reg::R12W
| McX86Reg::R13W
| McX86Reg::R14W
| McX86Reg::R15W
| McX86Reg::R16W
| McX86Reg::R17W
| McX86Reg::R18W
| McX86Reg::R19W
| McX86Reg::R20W
| McX86Reg::R21W
| McX86Reg::R22W
| McX86Reg::R23W
| McX86Reg::R24W
| McX86Reg::R25W
| McX86Reg::R26W
| McX86Reg::R27W
| McX86Reg::R28W
| McX86Reg::R29W
| McX86Reg::R30W
| McX86Reg::R31W => "w",
McX86Reg::EAX
| McX86Reg::ECX
| McX86Reg::EDX
| McX86Reg::EBX
| McX86Reg::ESP
| McX86Reg::EBP
| McX86Reg::ESI
| McX86Reg::EDI
| McX86Reg::R8D
| McX86Reg::R9D
| McX86Reg::R10D
| McX86Reg::R11D
| McX86Reg::R12D
| McX86Reg::R13D
| McX86Reg::R14D
| McX86Reg::R15D
| McX86Reg::R16D
| McX86Reg::R17D
| McX86Reg::R18D
| McX86Reg::R19D
| McX86Reg::R20D
| McX86Reg::R21D
| McX86Reg::R22D
| McX86Reg::R23D
| McX86Reg::R24D
| McX86Reg::R25D
| McX86Reg::R26D
| McX86Reg::R27D
| McX86Reg::R28D
| McX86Reg::R29D
| McX86Reg::R30D
| McX86Reg::R31D => "l",
McX86Reg::RAX
| McX86Reg::RCX
| McX86Reg::RDX
| McX86Reg::RBX
| McX86Reg::RSP
| McX86Reg::RBP
| McX86Reg::RSI
| McX86Reg::RDI
| McX86Reg::R8
| McX86Reg::R9
| McX86Reg::R10
| McX86Reg::R11
| McX86Reg::R12
| McX86Reg::R13
| McX86Reg::R14
| McX86Reg::R15
| McX86Reg::R16
| McX86Reg::R17
| McX86Reg::R18
| McX86Reg::R19
| McX86Reg::R20
| McX86Reg::R21
| McX86Reg::R22
| McX86Reg::R23
| McX86Reg::R24
| McX86Reg::R25
| McX86Reg::R26
| McX86Reg::R27
| McX86Reg::R28
| McX86Reg::R29
| McX86Reg::R30
| McX86Reg::R31 => "q",
McX86Reg::XMM0
| McX86Reg::XMM1
| McX86Reg::XMM2
| McX86Reg::XMM3
| McX86Reg::XMM4
| McX86Reg::XMM5
| McX86Reg::XMM6
| McX86Reg::XMM7
| McX86Reg::XMM8
| McX86Reg::XMM9
| McX86Reg::XMM10
| McX86Reg::XMM11
| McX86Reg::XMM12
| McX86Reg::XMM13
| McX86Reg::XMM14
| McX86Reg::XMM15
| McX86Reg::XMM16
| McX86Reg::XMM17
| McX86Reg::XMM18
| McX86Reg::XMM19
| McX86Reg::XMM20
| McX86Reg::XMM21
| McX86Reg::XMM22
| McX86Reg::XMM23
| McX86Reg::XMM24
| McX86Reg::XMM25
| McX86Reg::XMM26
| McX86Reg::XMM27
| McX86Reg::XMM28
| McX86Reg::XMM29
| McX86Reg::XMM30
| McX86Reg::XMM31 => "x",
McX86Reg::YMM0
| McX86Reg::YMM1
| McX86Reg::YMM2
| McX86Reg::YMM3
| McX86Reg::YMM4
| McX86Reg::YMM5
| McX86Reg::YMM6
| McX86Reg::YMM7
| McX86Reg::YMM8
| McX86Reg::YMM9
| McX86Reg::YMM10
| McX86Reg::YMM11
| McX86Reg::YMM12
| McX86Reg::YMM13
| McX86Reg::YMM14
| McX86Reg::YMM15
| McX86Reg::YMM16
| McX86Reg::YMM17
| McX86Reg::YMM18
| McX86Reg::YMM19
| McX86Reg::YMM20
| McX86Reg::YMM21
| McX86Reg::YMM22
| McX86Reg::YMM23
| McX86Reg::YMM24
| McX86Reg::YMM25
| McX86Reg::YMM26
| McX86Reg::YMM27
| McX86Reg::YMM28
| McX86Reg::YMM29
| McX86Reg::YMM30
| McX86Reg::YMM31 => "y",
McX86Reg::ZMM0
| McX86Reg::ZMM1
| McX86Reg::ZMM2
| McX86Reg::ZMM3
| McX86Reg::ZMM4
| McX86Reg::ZMM5
| McX86Reg::ZMM6
| McX86Reg::ZMM7
| McX86Reg::ZMM8
| McX86Reg::ZMM9
| McX86Reg::ZMM10
| McX86Reg::ZMM11
| McX86Reg::ZMM12
| McX86Reg::ZMM13
| McX86Reg::ZMM14
| McX86Reg::ZMM15
| McX86Reg::ZMM16
| McX86Reg::ZMM17
| McX86Reg::ZMM18
| McX86Reg::ZMM19
| McX86Reg::ZMM20
| McX86Reg::ZMM21
| McX86Reg::ZMM22
| McX86Reg::ZMM23
| McX86Reg::ZMM24
| McX86Reg::ZMM25
| McX86Reg::ZMM26
| McX86Reg::ZMM27
| McX86Reg::ZMM28
| McX86Reg::ZMM29
| McX86Reg::ZMM30
| McX86Reg::ZMM31 => "z",
_ => "",
}
}
pub fn class(&self) -> McRegClass {
match self {
McX86Reg::AL
| McX86Reg::CL
| McX86Reg::DL
| McX86Reg::BL
| McX86Reg::AH
| McX86Reg::CH
| McX86Reg::DH
| McX86Reg::BH
| McX86Reg::SPL
| McX86Reg::BPL
| McX86Reg::SIL
| McX86Reg::DIL
| McX86Reg::R8B
| McX86Reg::R9B
| McX86Reg::R10B
| McX86Reg::R11B
| McX86Reg::R12B
| McX86Reg::R13B
| McX86Reg::R14B
| McX86Reg::R15B
| McX86Reg::R16B
| McX86Reg::R17B
| McX86Reg::R18B
| McX86Reg::R19B
| McX86Reg::R20B
| McX86Reg::R21B
| McX86Reg::R22B
| McX86Reg::R23B
| McX86Reg::R24B
| McX86Reg::R25B
| McX86Reg::R26B
| McX86Reg::R27B
| McX86Reg::R28B
| McX86Reg::R29B
| McX86Reg::R30B
| McX86Reg::R31B => McRegClass::GPR8,
McX86Reg::AX
| McX86Reg::CX
| McX86Reg::DX
| McX86Reg::BX
| McX86Reg::SP
| McX86Reg::BP
| McX86Reg::SI
| McX86Reg::DI
| McX86Reg::R8W
| McX86Reg::R9W
| McX86Reg::R10W
| McX86Reg::R11W
| McX86Reg::R12W
| McX86Reg::R13W
| McX86Reg::R14W
| McX86Reg::R15W
| McX86Reg::R16W
| McX86Reg::R17W
| McX86Reg::R18W
| McX86Reg::R19W
| McX86Reg::R20W
| McX86Reg::R21W
| McX86Reg::R22W
| McX86Reg::R23W
| McX86Reg::R24W
| McX86Reg::R25W
| McX86Reg::R26W
| McX86Reg::R27W
| McX86Reg::R28W
| McX86Reg::R29W
| McX86Reg::R30W
| McX86Reg::R31W => McRegClass::GPR16,
McX86Reg::EAX
| McX86Reg::ECX
| McX86Reg::EDX
| McX86Reg::EBX
| McX86Reg::ESP
| McX86Reg::EBP
| McX86Reg::ESI
| McX86Reg::EDI
| McX86Reg::R8D
| McX86Reg::R9D
| McX86Reg::R10D
| McX86Reg::R11D
| McX86Reg::R12D
| McX86Reg::R13D
| McX86Reg::R14D
| McX86Reg::R15D
| McX86Reg::R16D
| McX86Reg::R17D
| McX86Reg::R18D
| McX86Reg::R19D
| McX86Reg::R20D
| McX86Reg::R21D
| McX86Reg::R22D
| McX86Reg::R23D
| McX86Reg::R24D
| McX86Reg::R25D
| McX86Reg::R26D
| McX86Reg::R27D
| McX86Reg::R28D
| McX86Reg::R29D
| McX86Reg::R30D
| McX86Reg::R31D => McRegClass::GPR32,
McX86Reg::RAX
| McX86Reg::RCX
| McX86Reg::RDX
| McX86Reg::RBX
| McX86Reg::RSP
| McX86Reg::RBP
| McX86Reg::RSI
| McX86Reg::RDI
| McX86Reg::R8
| McX86Reg::R9
| McX86Reg::R10
| McX86Reg::R11
| McX86Reg::R12
| McX86Reg::R13
| McX86Reg::R14
| McX86Reg::R15
| McX86Reg::R16
| McX86Reg::R17
| McX86Reg::R18
| McX86Reg::R19
| McX86Reg::R20
| McX86Reg::R21
| McX86Reg::R22
| McX86Reg::R23
| McX86Reg::R24
| McX86Reg::R25
| McX86Reg::R26
| McX86Reg::R27
| McX86Reg::R28
| McX86Reg::R29
| McX86Reg::R30
| McX86Reg::R31 => McRegClass::GPR64,
McX86Reg::SR_ES
| McX86Reg::SR_CS
| McX86Reg::SR_SS
| McX86Reg::SR_DS
| McX86Reg::SR_FS
| McX86Reg::SR_GS => McRegClass::Segment,
McX86Reg::CR0 | McX86Reg::CR2 | McX86Reg::CR3 | McX86Reg::CR4 | McX86Reg::CR8 => {
McRegClass::Control
}
McX86Reg::DR0
| McX86Reg::DR1
| McX86Reg::DR2
| McX86Reg::DR3
| McX86Reg::DR6
| McX86Reg::DR7 => McRegClass::Debug,
McX86Reg::MM0
| McX86Reg::MM1
| McX86Reg::MM2
| McX86Reg::MM3
| McX86Reg::MM4
| McX86Reg::MM5
| McX86Reg::MM6
| McX86Reg::MM7 => McRegClass::MMX,
McX86Reg::XMM0
| McX86Reg::XMM1
| McX86Reg::XMM2
| McX86Reg::XMM3
| McX86Reg::XMM4
| McX86Reg::XMM5
| McX86Reg::XMM6
| McX86Reg::XMM7
| McX86Reg::XMM8
| McX86Reg::XMM9
| McX86Reg::XMM10
| McX86Reg::XMM11
| McX86Reg::XMM12
| McX86Reg::XMM13
| McX86Reg::XMM14
| McX86Reg::XMM15
| McX86Reg::XMM16
| McX86Reg::XMM17
| McX86Reg::XMM18
| McX86Reg::XMM19
| McX86Reg::XMM20
| McX86Reg::XMM21
| McX86Reg::XMM22
| McX86Reg::XMM23
| McX86Reg::XMM24
| McX86Reg::XMM25
| McX86Reg::XMM26
| McX86Reg::XMM27
| McX86Reg::XMM28
| McX86Reg::XMM29
| McX86Reg::XMM30
| McX86Reg::XMM31 => McRegClass::XMM,
McX86Reg::YMM0
| McX86Reg::YMM1
| McX86Reg::YMM2
| McX86Reg::YMM3
| McX86Reg::YMM4
| McX86Reg::YMM5
| McX86Reg::YMM6
| McX86Reg::YMM7
| McX86Reg::YMM8
| McX86Reg::YMM9
| McX86Reg::YMM10
| McX86Reg::YMM11
| McX86Reg::YMM12
| McX86Reg::YMM13
| McX86Reg::YMM14
| McX86Reg::YMM15
| McX86Reg::YMM16
| McX86Reg::YMM17
| McX86Reg::YMM18
| McX86Reg::YMM19
| McX86Reg::YMM20
| McX86Reg::YMM21
| McX86Reg::YMM22
| McX86Reg::YMM23
| McX86Reg::YMM24
| McX86Reg::YMM25
| McX86Reg::YMM26
| McX86Reg::YMM27
| McX86Reg::YMM28
| McX86Reg::YMM29
| McX86Reg::YMM30
| McX86Reg::YMM31 => McRegClass::YMM,
McX86Reg::ZMM0
| McX86Reg::ZMM1
| McX86Reg::ZMM2
| McX86Reg::ZMM3
| McX86Reg::ZMM4
| McX86Reg::ZMM5
| McX86Reg::ZMM6
| McX86Reg::ZMM7
| McX86Reg::ZMM8
| McX86Reg::ZMM9
| McX86Reg::ZMM10
| McX86Reg::ZMM11
| McX86Reg::ZMM12
| McX86Reg::ZMM13
| McX86Reg::ZMM14
| McX86Reg::ZMM15
| McX86Reg::ZMM16
| McX86Reg::ZMM17
| McX86Reg::ZMM18
| McX86Reg::ZMM19
| McX86Reg::ZMM20
| McX86Reg::ZMM21
| McX86Reg::ZMM22
| McX86Reg::ZMM23
| McX86Reg::ZMM24
| McX86Reg::ZMM25
| McX86Reg::ZMM26
| McX86Reg::ZMM27
| McX86Reg::ZMM28
| McX86Reg::ZMM29
| McX86Reg::ZMM30
| McX86Reg::ZMM31 => McRegClass::ZMM,
McX86Reg::K0
| McX86Reg::K1
| McX86Reg::K2
| McX86Reg::K3
| McX86Reg::K4
| McX86Reg::K5
| McX86Reg::K6
| McX86Reg::K7 => McRegClass::Opmask,
McX86Reg::ST0
| McX86Reg::ST1
| McX86Reg::ST2
| McX86Reg::ST3
| McX86Reg::ST4
| McX86Reg::ST5
| McX86Reg::ST6
| McX86Reg::ST7 => McRegClass::FPU,
McX86Reg::TMM0
| McX86Reg::TMM1
| McX86Reg::TMM2
| McX86Reg::TMM3
| McX86Reg::TMM4
| McX86Reg::TMM5
| McX86Reg::TMM6
| McX86Reg::TMM7 => McRegClass::TMM,
McX86Reg::BND0 | McX86Reg::BND1 | McX86Reg::BND2 | McX86Reg::BND3 => McRegClass::BND,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McRegClass {
GPR8,
GPR16,
GPR32,
GPR64,
Segment,
Control,
Debug,
MMX,
XMM,
YMM,
ZMM,
Opmask,
FPU,
TMM,
BND,
}
#[derive(Debug, Clone)]
pub struct McDecodedInstruction {
pub mnemonic: String,
pub opcode: u16,
pub opcode_map: McOpcodeMap,
pub operands: Vec<McDecodedOperand>,
pub size: usize,
pub address: u64,
pub prefixes: McLegacyPrefixes,
pub rex: Option<McRexInfo>,
pub vex: Option<McVexInfo>,
pub evex: Option<McEvexInfo>,
pub implicit_operands: Vec<McDecodedOperand>,
pub attributes: McInstrAttributes,
pub opcode_extension: Option<u8>,
pub operand_size: u8,
pub address_size: u8,
pub vector_length: u16,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct McInstrAttributes {
pub has_modrm: bool,
pub has_sib: bool,
pub has_displacement: bool,
pub has_immediate: bool,
pub is_branch: bool,
pub is_call: bool,
pub is_return: bool,
pub is_conditional: bool,
pub is_privileged: bool,
pub is_sse: bool,
pub is_avx: bool,
pub is_avx512: bool,
pub uses_vvvv: bool,
pub uses_opmask: bool,
pub uses_broadcast: bool,
pub uses_zeroing: bool,
pub uses_er: bool,
pub uses_sae: bool,
pub has_lock_prefix: bool,
pub has_rep_prefix: bool,
pub has_repne_prefix: bool,
pub is_64bit_only: bool,
pub is_32bit_only: bool,
pub is_string_instruction: bool,
pub is_group_instruction: bool,
pub opcode_extension_from_3bits: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum McDecodedOperand {
Register {
reg: McX86Reg,
size_hint: McSizeHint,
},
Memory {
segment: Option<McSegmentOverride>,
base: Option<McX86Reg>,
index: Option<(McX86Reg, u8)>,
displacement: i64,
size_hint: McSizeHint,
rip_relative: bool,
},
Immediate {
value: i64,
size: u8,
},
RelativeOffset {
offset: i64,
size: u8,
},
ImplicitRegister {
reg: McX86Reg,
},
OpmaskRegister {
reg: McX86Reg,
zeroing: bool,
},
FPURegister {
index: u8,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McSizeHint {
None,
Byte,
Word,
Dword,
Qword,
Oword,
Yword,
Zword,
Single,
Double,
Fword,
Tbyte,
}
impl McSizeHint {
pub fn att_suffix(&self) -> &'static str {
match self {
McSizeHint::Byte => "b",
McSizeHint::Word => "w",
McSizeHint::Dword => "l",
McSizeHint::Qword => "q",
McSizeHint::Oword => "x",
McSizeHint::Yword => "y",
McSizeHint::Zword => "z",
McSizeHint::Single => "s",
McSizeHint::Double => "d",
McSizeHint::Fword => "f",
McSizeHint::Tbyte => "t",
McSizeHint::None => "",
}
}
pub fn intel_prefix(&self) -> &'static str {
match self {
McSizeHint::Byte => "byte ptr ",
McSizeHint::Word => "word ptr ",
McSizeHint::Dword => "dword ptr ",
McSizeHint::Qword => "qword ptr ",
McSizeHint::Oword => "xmmword ptr ",
McSizeHint::Yword => "ymmword ptr ",
McSizeHint::Zword => "zmmword ptr ",
McSizeHint::Single => "dword ptr ",
McSizeHint::Double => "qword ptr ",
McSizeHint::Fword => "fword ptr ",
McSizeHint::Tbyte => "tbyte ptr ",
McSizeHint::None => "",
}
}
pub fn from_intel_prefix(prefix: &str) -> McSizeHint {
match prefix {
"byte ptr " => McSizeHint::Byte,
"word ptr " => McSizeHint::Word,
"dword ptr " => McSizeHint::Dword,
"qword ptr " => McSizeHint::Qword,
"xmmword ptr " => McSizeHint::Oword,
"ymmword ptr " => McSizeHint::Yword,
"zmmword ptr " => McSizeHint::Zword,
"fword ptr " => McSizeHint::Fword,
"tbyte ptr " => McSizeHint::Tbyte,
_ => McSizeHint::None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McOpcodeMap {
Primary,
Map0F,
Map0F38,
Map0F3A,
VexMap1,
VexMap2,
VexMap3,
EvexMap1,
EvexMap2,
EvexMap3,
EvexMap4,
EvexMap5,
EvexMap6,
XopMap8,
XopMap9,
XopMapA,
ThreeDNow,
Group,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum McEncodingForm {
Implicit,
RegOnly,
RegRM,
OpcodeExtRM,
RmReg,
RmOnly,
RegImm,
RmImm,
RmRegImm,
RmRegImmModRM,
RelBranch,
AccumImm,
AccumMem,
MemAccum,
VexRegVvvvRm,
VexVvvvRmReg,
VexVvvvRmImm,
VexRmReg,
EvexRegKRm,
EvexVvvvKRmReg,
GroupOpcodeExt,
}
#[derive(Debug, Clone)]
pub struct McTableEntry {
pub opcode: u16,
pub mnemonic: &'static str,
pub encoding_form: McEncodingForm,
pub has_modrm: bool,
pub imm_size: u8,
pub attributes: McInstrAttributes,
pub group: Option<u8>,
pub size_hint: McSizeHint,
pub feature_required: FeatureSet,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FeatureSet {
Base, I486, Pentium, P6, MMX, ThreeDNow, SSE, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512F, AVX512BW, AVX512DQ, AVX512VL, AVX512CD, AVX512ER, AVX512PF, AVX512VBMI, AVX512IFMA, AVX512VNNI, AVX512BF16, AVX512FP16, AVX512VPOPCNTDQ,
AVX512BITALG,
AVX512VBMI2,
AVX512GFNI,
AVX512VAES,
AVX512VPCLMULQDQ,
FMA, FMA4, XOP, BMI, BMI2, ADX, AES, CLMUL, SHA, SGX, CET, TSX, VMX, SVM, SMX, XSAVE, RDRAND, RDSEED, MPX, AMX, APX, UINTR, FRED, X86_64, LZCNT, POPCNT, MOVBE, PREFETCHW, PCLMUL, FSGSBASE, RDRAND_Set, RDPID, MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, WAITPKG, SERIALIZE, HRESET, KL, CMPCCXADD, RAOINT, AVXVNNI, AVXIFMA, AVXNECONVERT, AVXVNNIINT8, }
pub struct X86MCDisassemblerFull {
pub mode: McProcessorMode,
pub base_address: u64,
decoder: X86InstructionDecoder,
formatter: X86OperandFormatter,
annotator: X86InstructionAnnotator,
pub syntax: McDisasmSyntax,
pub show_bytes: bool,
pub max_insn_size: usize,
pub validate: bool,
}
impl X86MCDisassemblerFull {
pub fn new(mode: McProcessorMode) -> Self {
X86MCDisassemblerFull {
mode,
base_address: 0,
decoder: X86InstructionDecoder::new(mode),
formatter: X86OperandFormatter::new(McDisasmSyntax::Intel),
annotator: X86InstructionAnnotator::new(),
syntax: McDisasmSyntax::Intel,
show_bytes: false,
max_insn_size: 15,
validate: true,
}
}
pub fn with_address(mut self, addr: u64) -> Self {
self.base_address = addr;
self.decoder.set_base_address(addr);
self
}
pub fn with_syntax(mut self, syntax: McDisasmSyntax) -> Self {
self.syntax = syntax;
self.formatter.set_syntax(syntax);
self
}
pub fn with_show_bytes(mut self, show: bool) -> Self {
self.show_bytes = show;
self
}
pub fn disassemble_one(&mut self, bytes: &[u8]) -> Option<String> {
let inst = self.decoder.decode_one(bytes)?;
self.formatter.format(&inst, self.show_bytes, bytes)
}
pub fn disassemble_all(&mut self, bytes: &[u8]) -> Vec<String> {
let mut results = Vec::new();
let addr = self.base_address;
let mut offset = 0usize;
while offset < bytes.len() {
self.decoder.set_base_address(addr + offset as u64);
if let Some(inst) = self.decoder.decode_one(&bytes[offset..]) {
let insn_size = inst.size;
if insn_size == 0 {
break;
}
let formatted = self.formatter.format(
&inst,
self.show_bytes,
&bytes[offset..offset + insn_size],
);
if let Some(formatted) = formatted {
results.push(formatted);
}
offset += insn_size;
} else {
offset += 1;
}
}
results
}
pub fn decode_one(&mut self, bytes: &[u8]) -> Option<McDecodedInstruction> {
self.decoder.decode_one(bytes)
}
pub fn set_mode(&mut self, mode: McProcessorMode) {
self.mode = mode;
self.decoder.set_mode(mode);
}
pub fn set_base_address(&mut self, addr: u64) {
self.base_address = addr;
self.decoder.set_base_address(addr);
}
pub fn annotate(
&mut self,
inst: &McDecodedInstruction,
symbols: &BTreeMap<u64, String>,
) -> String {
self.annotator.annotate(inst, symbols)
}
}
pub struct X86InstructionDecoder {
pub mode: McProcessorMode,
pub base_address: u64,
pos: usize,
bytes: Vec<u8>,
prefixes: McLegacyPrefixes,
rex: Option<McRexInfo>,
vex: Option<McVexInfo>,
evex: Option<McEvexInfo>,
modrm: Option<McModRM>,
sib: Option<McSIB>,
displacement: i64,
immediates: Vec<i64>,
opcode: u16,
full_opcode: Vec<u8>,
opcode_map: McOpcodeMap,
}
impl X86InstructionDecoder {
pub fn new(mode: McProcessorMode) -> Self {
X86InstructionDecoder {
mode,
base_address: 0,
pos: 0,
bytes: Vec::new(),
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
modrm: None,
sib: None,
displacement: 0,
immediates: Vec::new(),
opcode: 0,
full_opcode: Vec::new(),
opcode_map: McOpcodeMap::Primary,
}
}
pub fn set_base_address(&mut self, addr: u64) {
self.base_address = addr;
}
pub fn set_mode(&mut self, mode: McProcessorMode) {
self.mode = mode;
}
pub fn decode_one(&mut self, bytes: &[u8]) -> Option<McDecodedInstruction> {
self.reset();
self.bytes = bytes.to_vec();
if bytes.is_empty() {
return None;
}
if !self.decode_prefixes() {
return None;
}
if self.pos >= bytes.len() {
return None;
}
let opcode_byte = self.read_byte()?;
self.full_opcode.push(opcode_byte);
let map = self.determine_map(opcode_byte);
let entry = match map {
McOpcodeMap::Primary => {
self.opcode = opcode_byte as u16;
self.lookup_primary(opcode_byte)?
}
McOpcodeMap::Map0F => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
self.opcode = op2 as u16;
self.lookup_0f(op2)?
}
McOpcodeMap::Map0F38 => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
let op3 = self.read_byte()?;
self.full_opcode.push(op3);
self.opcode = op3 as u16;
self.lookup_0f38(op3)?
}
McOpcodeMap::Map0F3A => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
let op3 = self.read_byte()?;
self.full_opcode.push(op3);
self.opcode = op3 as u16;
self.lookup_0f3a(op3)?
}
McOpcodeMap::VexMap1 | McOpcodeMap::VexMap2 | McOpcodeMap::VexMap3 => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
self.opcode = op2 as u16;
self.lookup_vex(op2, &map)?
}
McOpcodeMap::EvexMap1
| McOpcodeMap::EvexMap2
| McOpcodeMap::EvexMap3
| McOpcodeMap::EvexMap4
| McOpcodeMap::EvexMap5
| McOpcodeMap::EvexMap6 => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
self.opcode = op2 as u16;
self.lookup_evex(op2, &map)?
}
McOpcodeMap::XopMap8 | McOpcodeMap::XopMap9 | McOpcodeMap::XopMapA => {
let op2 = self.read_byte()?;
self.full_opcode.push(op2);
self.opcode = op2 as u16;
self.lookup_xop(op2, &map)?
}
_ => return None,
};
if entry.has_modrm {
self.modrm = Some(self.decode_modrm()?);
}
if self.has_sib() {
self.sib = Some(self.decode_sib()?);
}
self.decode_displacement()?;
self.decode_immediates(&entry);
let operands = self.build_operands(&entry);
let size = self.pos;
Some(McDecodedInstruction {
mnemonic: entry.mnemonic.to_string(),
opcode: self.opcode,
opcode_map: self.opcode_map,
operands,
size,
address: self.base_address,
prefixes: self.prefixes.clone(),
rex: self.rex,
vex: self.vex,
evex: self.evex,
implicit_operands: Vec::new(),
attributes: entry.attributes,
opcode_extension: None,
operand_size: self.prefixes.effective_operand_size,
address_size: self.prefixes.effective_address_size,
vector_length: self.determine_vector_length(),
})
}
fn reset(&mut self) {
self.pos = 0;
self.bytes.clear();
self.prefixes = McLegacyPrefixes::default();
self.rex = None;
self.vex = None;
self.evex = None;
self.modrm = None;
self.sib = None;
self.displacement = 0;
self.immediates.clear();
self.opcode = 0;
self.full_opcode.clear();
self.opcode_map = McOpcodeMap::Primary;
}
fn read_byte(&mut self) -> Option<u8> {
if self.pos < self.bytes.len() {
let b = self.bytes[self.pos];
self.pos += 1;
Some(b)
} else {
None
}
}
fn peek_byte(&self) -> Option<u8> {
self.bytes.get(self.pos).copied()
}
fn decode_prefixes(&mut self) -> bool {
let default_op_size = self.mode.default_operand_size();
let default_addr_size = self.mode.default_address_size();
let mut op_override = false;
let mut addr_override = false;
self.prefixes.effective_operand_size = default_op_size;
self.prefixes.effective_address_size = default_addr_size;
loop {
let b = match self.peek_byte() {
Some(b) => b,
None => return false,
};
match b {
0x2E => {
self.prefixes.cs_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::CS);
self.pos += 1;
}
0x3E => {
self.prefixes.ds_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::DS);
self.pos += 1;
}
0x26 => {
self.prefixes.es_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::ES);
self.pos += 1;
}
0x36 => {
self.prefixes.ss_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::SS);
self.pos += 1;
}
0x64 => {
self.prefixes.fs_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::FS);
self.pos += 1;
}
0x65 => {
self.prefixes.gs_override = true;
self.prefixes.active_segment_override = Some(McSegmentOverride::GS);
self.pos += 1;
}
0xF0 => {
self.prefixes.has_lock = true;
self.pos += 1;
}
0xF2 => {
let next = self.bytes.get(self.pos + 1).copied();
if next == Some(0x0F) {
self.prefixes.has_repne = true;
}
self.pos += 1;
}
0xF3 => {
let next = self.bytes.get(self.pos + 1).copied();
if next == Some(0x0F) {
self.prefixes.has_rep = true;
}
self.pos += 1;
}
0x66 => {
op_override = true;
self.pos += 1;
}
0x67 => {
addr_override = true;
self.pos += 1;
}
0x40..=0x4F => {
if self.mode.is_64bit() {
self.decode_rex(b);
self.pos += 1;
} else {
break;
}
}
0xC5 => {
if self.mode.is_64bit()
|| self.bytes.get(self.pos + 1).map_or(false, |&b2| {
(b2 & 0xC0) == 0xC0 || self.prefixes.effective_address_size != 64
})
{
return self.decode_vex_2byte();
}
break;
}
0xC4 => {
if self.mode.is_64bit()
|| self.bytes.get(self.pos + 1).map_or(false, |&b2| {
(b2 & 0xC0) == 0xC0 || self.prefixes.effective_address_size != 64
})
{
return self.decode_vex_3byte();
}
break;
}
0x62 => {
if self.bytes.len() > self.pos + 3 {
let after_evex = self.bytes[self.pos + 3];
if (after_evex & 0x0C) == 0x00 {
return self.decode_evex_full();
}
}
break;
}
0x8F => {
return self.decode_xop();
}
_ => break,
}
}
if op_override {
self.prefixes.has_operand_size_override = true;
self.prefixes.effective_operand_size = match default_op_size {
16 => 32,
32 => 16,
64 => 16,
_ => default_op_size,
};
}
if addr_override {
self.prefixes.has_address_size_override = true;
self.prefixes.effective_address_size = match default_addr_size {
16 => 32,
32 => 16,
64 => 32,
_ => default_addr_size,
};
}
true
}
fn decode_rex(&mut self, byte: u8) {
let rex = McRexInfo {
present: true,
w: (byte & 0x08) != 0,
r: (byte & 0x04) != 0,
x: (byte & 0x02) != 0,
b: (byte & 0x01) != 0,
};
if rex.w {
self.prefixes.effective_operand_size = 64;
}
self.rex = Some(rex);
}
fn decode_vex_2byte(&mut self) -> bool {
self.pos += 1; let p = match self.read_byte() {
Some(b) => b,
None => return false,
};
let r = (p & 0x80) == 0;
let vvvv = (!p >> 3) & 0x0F;
let l = (p & 0x04) != 0;
let pp = p & 0x03;
let vex = McVexInfo {
present: true,
is_3byte: false,
r,
x: true,
b: true,
w: false,
vvvv,
l,
pp,
mmmmm: 1, };
match pp {
0x01 => self.prefixes.effective_operand_size = 16, 0x02 => {} 0x03 => {} _ => {}
}
self.vex = Some(vex);
match self.read_byte() {
Some(op) => {
self.full_opcode.push(op);
self.opcode = op as u16;
self.opcode_map = McOpcodeMap::VexMap1;
true
}
None => false,
}
}
fn decode_vex_3byte(&mut self) -> bool {
self.pos += 1; let p1 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let p2 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let r = (p1 & 0x80) == 0;
let x = (p1 & 0x40) == 0;
let b = (p1 & 0x20) == 0;
let mmmmm = p1 & 0x1F;
let w = (p2 & 0x80) != 0;
let vvvv = (!p2 >> 3) & 0x0F;
let l = (p2 & 0x04) != 0;
let pp = p2 & 0x03;
let vex = McVexInfo {
present: true,
is_3byte: true,
r,
x,
b,
w,
vvvv,
l,
pp,
mmmmm,
};
match pp {
0x01 => self.prefixes.effective_operand_size = 16,
_ => {}
}
if w {
self.prefixes.effective_operand_size = 64;
}
self.vex = Some(vex);
self.opcode_map = match mmmmm {
1 => McOpcodeMap::VexMap1,
2 => McOpcodeMap::VexMap2,
3 => McOpcodeMap::VexMap3,
_ => McOpcodeMap::VexMap1,
};
match self.read_byte() {
Some(op) => {
self.full_opcode.push(op);
self.opcode = op as u16;
true
}
None => false,
}
}
fn decode_evex_full(&mut self) -> bool {
self.pos += 1; let p0 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let p1 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let p2 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let r_prime = (p0 & 0x80) == 0;
let _r = (p0 & 0x10) == 0; let x = (p0 & 0x40) == 0; let b = (p0 & 0x20) == 0; let x_prime = (p0 & 0x08) == 0;
let b_prime = (p0 & 0x04) == 0;
let r = (p0 & 0x10) == 0;
let _r2 = (p0 & 0x01) == 0;
let w = (p1 & 0x80) != 0;
let vvvv = (!p1 >> 3) & 0x0F;
let pp = p1 & 0x03;
let z = (p2 & 0x80) != 0;
let ll = (p2 >> 5) & 0x03;
let b_bit = (p2 & 0x10) != 0;
let v_prime = (p2 & 0x08) != 0;
let aaa = p2 & 0x07;
let mm = (p1 >> 4) & 0x07;
let evex = McEvexInfo {
present: true,
r_prime,
x_prime,
b_prime,
r,
x,
b,
v_prime,
w,
z,
aaa,
ll,
b_bit,
pp,
mm,
vvvv,
};
match pp {
0x01 => self.prefixes.effective_operand_size = 16,
_ => {}
}
if w {
self.prefixes.effective_operand_size = 64;
}
self.evex = Some(evex);
self.opcode_map = match mm {
1 => McOpcodeMap::EvexMap1,
2 => McOpcodeMap::EvexMap2,
3 => McOpcodeMap::EvexMap3,
4 => McOpcodeMap::EvexMap4,
5 => McOpcodeMap::EvexMap5,
6 => McOpcodeMap::EvexMap6,
_ => McOpcodeMap::EvexMap1,
};
match self.read_byte() {
Some(op) => {
self.full_opcode.push(op);
self.opcode = op as u16;
true
}
None => false,
}
}
fn decode_xop(&mut self) -> bool {
self.pos += 1; let p1 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let p2 = match self.read_byte() {
Some(b) => b,
None => return false,
};
let r = (p1 & 0x80) == 0;
let x = (p1 & 0x40) == 0;
let b = (p1 & 0x20) == 0;
let mmmmm = p1 & 0x1F;
let w = (p2 & 0x80) != 0;
let vvvv = (!p2 >> 3) & 0x0F;
let l = (p2 & 0x04) != 0;
let pp = p2 & 0x03;
let vex = McVexInfo {
present: true,
is_3byte: true,
r,
x,
b,
w,
vvvv,
l,
pp,
mmmmm,
};
self.vex = Some(vex);
self.opcode_map = match mmmmm {
8 => McOpcodeMap::XopMap8,
9 => McOpcodeMap::XopMap9,
10 => McOpcodeMap::XopMapA,
_ => McOpcodeMap::XopMap8,
};
match self.read_byte() {
Some(op) => {
self.full_opcode.push(op);
self.opcode = op as u16;
true
}
None => false,
}
}
fn determine_map(&mut self, opcode_byte: u8) -> McOpcodeMap {
if self.vex.is_some() {
match self.vex.as_ref().unwrap().mmmmm {
1 => McOpcodeMap::VexMap1,
2 => McOpcodeMap::VexMap2,
3 => McOpcodeMap::VexMap3,
_ => McOpcodeMap::VexMap1,
}
} else if self.evex.is_some() {
match self.evex.as_ref().unwrap().mm {
1 => McOpcodeMap::EvexMap1,
2 => McOpcodeMap::EvexMap2,
3 => McOpcodeMap::EvexMap3,
4 => McOpcodeMap::EvexMap4,
5 => McOpcodeMap::EvexMap5,
6 => McOpcodeMap::EvexMap6,
_ => McOpcodeMap::EvexMap1,
}
} else if opcode_byte == 0x0F {
let next = self.peek_byte();
match next {
Some(0x38) => {
self.pos += 1;
self.full_opcode.push(0x38);
McOpcodeMap::Map0F38
}
Some(0x3A) => {
self.pos += 1;
self.full_opcode.push(0x3A);
McOpcodeMap::Map0F3A
}
_ => McOpcodeMap::Map0F,
}
} else {
self.opcode_map = McOpcodeMap::Primary;
McOpcodeMap::Primary
}
}
fn decode_modrm(&mut self) -> Option<McModRM> {
let byte = self.read_byte()?;
Some(McModRM {
raw: byte,
mod_field: (byte >> 6) & 0x03,
reg_field: (byte >> 3) & 0x07,
rm_field: byte & 0x07,
})
}
fn has_sib(&self) -> bool {
if let Some(modrm) = self.modrm {
modrm.mod_field != 3
&& modrm.rm_field == 0b100
&& self.prefixes.effective_address_size >= 32
} else {
false
}
}
fn decode_sib(&mut self) -> Option<McSIB> {
let byte = self.read_byte()?;
Some(McSIB {
raw: byte,
scale: (byte >> 6) & 0x03,
index_field: (byte >> 3) & 0x07,
base_field: byte & 0x07,
})
}
fn decode_displacement(&mut self) -> Option<()> {
if let Some(modrm) = self.modrm {
let mod_field = modrm.mod_field;
let rm_field = modrm.rm_field;
let addr_size = self.prefixes.effective_address_size;
if mod_field == 0 && rm_field == 0b101 && addr_size >= 32 {
self.displacement = self.read_i32()? as i64;
} else if mod_field == 1 {
self.displacement = self.read_i8()? as i64;
} else if mod_field == 2 {
self.displacement = match addr_size {
16 => self.read_i16()? as i64,
32 => self.read_i32()? as i64,
64 => self.read_i32()? as i64,
_ => self.read_i32()? as i64,
};
}
}
Some(())
}
fn decode_immediates(&mut self, entry: &McTableEntry) {
if entry.imm_size == 0 {
return;
}
let imm_count = 1; for _ in 0..imm_count {
let val = match entry.imm_size {
1 => self.read_i8().map(|v| v as i64),
2 => self.read_i16().map(|v| v as i64),
4 => self.read_i32().map(|v| v as i64),
8 => {
if self.mode.is_64bit() {
self.read_i64()
} else {
self.read_i32().map(|v| v as i64)
}
}
_ => None,
};
if let Some(v) = val {
self.immediates.push(v);
}
}
}
fn read_i8(&mut self) -> Option<i8> {
let b = self.read_byte()?;
Some(b as i8)
}
fn read_i16(&mut self) -> Option<i16> {
let lo = self.read_byte()? as u16;
let hi = self.read_byte()? as u16;
Some(((hi << 8) | lo) as i16)
}
fn read_i32(&mut self) -> Option<i32> {
let b0 = self.read_byte()? as u32;
let b1 = self.read_byte()? as u32;
let b2 = self.read_byte()? as u32;
let b3 = self.read_byte()? as u32;
Some(((b3 << 24) | (b2 << 16) | (b1 << 8) | b0) as i32)
}
fn read_i64(&mut self) -> Option<i64> {
let lo = self.read_i32()? as u32;
let hi = self.read_i32()? as u32;
Some(((hi as u64) << 32 | lo as u64) as i64)
}
fn build_operands(&self, entry: &McTableEntry) -> Vec<McDecodedOperand> {
let mut operands = Vec::new();
match entry.encoding_form {
McEncodingForm::Implicit => {}
McEncodingForm::RegOnly => {
let reg = self.opcode_reg_from_bits(self.opcode as u8 & 0x07);
operands.push(reg);
}
McEncodingForm::RegRM | McEncodingForm::RmReg => {
if let Some(modrm) = self.modrm {
let reg = self.resolve_reg(modrm.reg_field);
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
if matches!(entry.encoding_form, McEncodingForm::RegRM) {
operands.push(reg);
operands.push(rm);
} else {
operands.push(rm);
operands.push(reg);
}
}
}
McEncodingForm::OpcodeExtRM | McEncodingForm::RmOnly => {
if let Some(modrm) = self.modrm {
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(rm);
}
}
McEncodingForm::RegImm => {
if let Some(modrm) = self.modrm {
let reg = self.resolve_reg(modrm.reg_field);
operands.push(reg);
}
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
McEncodingForm::RmImm => {
if let Some(modrm) = self.modrm {
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(rm);
}
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
McEncodingForm::RmRegImm | McEncodingForm::RmRegImmModRM => {
if let Some(modrm) = self.modrm {
let reg = self.resolve_reg(modrm.reg_field);
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(rm);
operands.push(reg);
}
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
McEncodingForm::RelBranch => {
if let Some(&offset) = self.immediates.first() {
operands.push(McDecodedOperand::RelativeOffset {
offset,
size: entry.imm_size,
});
}
}
McEncodingForm::AccumImm => {
let acc = self.accumulator_reg();
operands.push(acc);
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
McEncodingForm::AccumMem => {
let acc = self.accumulator_reg();
operands.push(acc);
let addr = self.displacement;
operands.push(self.make_absolute_memory(addr, entry.size_hint));
}
McEncodingForm::MemAccum => {
let addr = self.displacement;
operands.push(self.make_absolute_memory(addr, entry.size_hint));
operands.push(self.accumulator_reg());
}
McEncodingForm::VexRegVvvvRm => {
if let Some(modrm) = self.modrm {
let reg = self.resolve_vex_reg(modrm.reg_field);
let vvvv_reg = self.resolve_vvvv_reg();
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(reg);
operands.push(vvvv_reg);
operands.push(rm);
}
}
McEncodingForm::VexVvvvRmReg => {
if let Some(modrm) = self.modrm {
let vvvv_reg = self.resolve_vvvv_reg();
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
let reg = self.resolve_vex_reg(modrm.reg_field);
operands.push(vvvv_reg);
operands.push(rm);
operands.push(reg);
}
}
McEncodingForm::VexVvvvRmImm => {
if let Some(modrm) = self.modrm {
let vvvv_reg = self.resolve_vvvv_reg();
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(vvvv_reg);
operands.push(rm);
}
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
McEncodingForm::VexRmReg => {
if let Some(modrm) = self.modrm {
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
let reg = self.resolve_vex_reg(modrm.reg_field);
operands.push(rm);
operands.push(reg);
}
}
McEncodingForm::EvexRegKRm => {
if let Some(modrm) = self.modrm {
let reg = self.resolve_evex_reg(modrm.reg_field);
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
if let Some(ref evex) = self.evex {
if evex.aaa > 0 {
let kreg = self.opmask_reg_from_bits(evex.aaa);
operands.push(McDecodedOperand::OpmaskRegister {
reg: kreg,
zeroing: evex.z,
});
}
}
operands.push(reg);
operands.push(rm);
}
}
McEncodingForm::EvexVvvvKRmReg => {
if let Some(modrm) = self.modrm {
let vvvv_reg = self.resolve_vvvv_reg();
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
let reg = self.resolve_evex_reg(modrm.reg_field);
if let Some(ref evex) = self.evex {
if evex.aaa > 0 {
let kreg = self.opmask_reg_from_bits(evex.aaa);
operands.push(McDecodedOperand::OpmaskRegister {
reg: kreg,
zeroing: evex.z,
});
}
}
operands.push(vvvv_reg);
operands.push(rm);
operands.push(reg);
}
}
McEncodingForm::GroupOpcodeExt => {
if let Some(modrm) = self.modrm {
let rm = self.resolve_rm_operand(modrm, entry.size_hint);
operands.push(rm);
if let Some(&imm) = self.immediates.first() {
operands.push(McDecodedOperand::Immediate {
value: imm,
size: entry.imm_size,
});
}
}
}
}
operands
}
fn resolve_reg(&self, reg_field: u8) -> McDecodedOperand {
let extended_reg = self.extend_reg(reg_field);
let reg_name = self.gpr_name_for_size(extended_reg);
let size_hint = self.size_hint_for_gpr();
McDecodedOperand::Register {
reg: reg_name,
size_hint,
}
}
fn resolve_vex_reg(&self, reg_field: u8) -> McDecodedOperand {
let extended_reg = self.extend_vex_reg(reg_field);
let reg_name = self.vector_reg_name(extended_reg);
let size_hint = self.vector_size_hint();
McDecodedOperand::Register {
reg: reg_name,
size_hint,
}
}
fn resolve_evex_reg(&self, reg_field: u8) -> McDecodedOperand {
let extended_reg = self.extend_evex_reg(reg_field);
let reg_name = self.vector_reg_name(extended_reg);
let size_hint = self.vector_size_hint();
McDecodedOperand::Register {
reg: reg_name,
size_hint,
}
}
fn resolve_vvvv_reg(&self) -> McDecodedOperand {
let vvvv = if let Some(ref vex) = self.vex {
vex.vvvv
} else if let Some(ref evex) = self.evex {
evex.vvvv
} else {
0
};
let reg_name = self.vector_reg_name(vvvv);
let size_hint = self.vector_size_hint();
McDecodedOperand::Register {
reg: reg_name,
size_hint,
}
}
fn resolve_rm_operand(&self, modrm: McModRM, size_hint: McSizeHint) -> McDecodedOperand {
if modrm.mod_field == 3 {
let extended_rm = self.extend_rm(modrm.rm_field);
let reg_name = self.gpr_name_for_size(extended_rm);
McDecodedOperand::Register {
reg: reg_name,
size_hint,
}
} else {
self.resolve_memory_operand(modrm, size_hint)
}
}
fn resolve_memory_operand(&self, modrm: McModRM, size_hint: McSizeHint) -> McDecodedOperand {
let addr_size = self.prefixes.effective_address_size;
let segment = self.prefixes.active_segment_override;
let disp = self.displacement;
if addr_size == 16 {
let (base, index) = match modrm.rm_field {
0 => (Some(McX86Reg::BX), Some((McX86Reg::SI, 1u8))),
1 => (Some(McX86Reg::BX), Some((McX86Reg::DI, 1u8))),
2 => (Some(McX86Reg::BP), Some((McX86Reg::SI, 1u8))),
3 => (Some(McX86Reg::BP), Some((McX86Reg::DI, 1u8))),
4 => (Some(McX86Reg::SI), None),
5 => (Some(McX86Reg::DI), None),
6 => {
if modrm.mod_field == 0 {
(None, None)
} else {
(Some(McX86Reg::BP), None)
}
}
7 => (Some(McX86Reg::BX), None),
_ => (None, None),
};
McDecodedOperand::Memory {
segment,
base,
index,
displacement: disp,
size_hint,
rip_relative: false,
}
} else {
let mut base_reg: Option<McX86Reg> = None;
let mut index_reg: Option<(McX86Reg, u8)> = None;
let mut rip_rel = false;
if addr_size == 64 && modrm.mod_field == 0 && modrm.rm_field == 0b101 {
rip_rel = true;
} else if modrm.rm_field == 0b100 {
if let Some(sib) = self.sib {
if sib.base_field != 0b101 || modrm.mod_field != 0 {
let base_bits = self.extend_base(sib.base_field);
base_reg = Some(self.base_reg_name(base_bits));
} else if modrm.mod_field == 0 {
base_reg = None;
}
if sib.index_field != 0b100 {
let index_bits = self.extend_index(sib.index_field);
index_reg = Some((self.index_reg_name(index_bits), 1u8 << sib.scale));
}
}
} else {
let base_bits = self.extend_base(modrm.rm_field);
base_reg = Some(self.base_reg_name(base_bits));
}
McDecodedOperand::Memory {
segment,
base: base_reg,
index: index_reg,
displacement: disp,
size_hint,
rip_relative: rip_rel,
}
}
}
fn make_absolute_memory(&self, addr: i64, size_hint: McSizeHint) -> McDecodedOperand {
let segment = self.prefixes.active_segment_override;
McDecodedOperand::Memory {
segment,
base: None,
index: None,
displacement: addr,
size_hint,
rip_relative: false,
}
}
fn extend_reg(&self, reg: u8) -> u8 {
let rex_r = self.rex.map_or(false, |r| r.r);
if rex_r {
reg | 0x08
} else {
reg
}
}
fn extend_rm(&self, rm: u8) -> u8 {
let rex_b = self.rex.map_or(false, |r| r.b);
if rex_b {
rm | 0x08
} else {
rm
}
}
fn extend_base(&self, base: u8) -> u8 {
let rex_b = self.rex.map_or(false, |r| r.b);
if rex_b {
base | 0x08
} else {
base
}
}
fn extend_index(&self, index: u8) -> u8 {
let rex_x = self.rex.map_or(false, |r| r.x);
if rex_x {
index | 0x08
} else {
index
}
}
fn extend_vex_reg(&self, reg: u8) -> u8 {
let vex_r = self.vex.map_or(true, |v| v.r);
let vex_x = self.vex.map_or(true, |v| v.x);
let vex_b = self.vex.map_or(true, |v| v.b);
let mut ext = reg;
if !vex_r {
ext |= 0x08;
}
if !vex_x {
ext |= 0x10;
}
if !vex_b && reg > 7 {
ext |= 0x10;
}
ext
}
fn extend_evex_reg(&self, reg: u8) -> u8 {
let evex_r = self.evex.map_or(true, |e| e.r);
let mut ext = reg;
if !evex_r {
ext |= 0x08;
}
if let Some(ref evex) = self.evex {
if !evex.r_prime {
ext |= 0x10;
}
}
ext
}
fn gpr_name_for_size(&self, reg: u8) -> McX86Reg {
let op_size = self.prefixes.effective_operand_size;
let rex_w = self.rex.map_or(false, |r| r.w);
if rex_w || (op_size == 64 && self.mode.is_64bit()) {
mc_gpr64_name(reg)
} else if op_size == 32 {
mc_gpr32_name(reg)
} else if op_size == 16 {
mc_gpr16_name(reg)
} else {
mc_gpr8_name(reg, self.rex.as_ref())
}
}
fn base_reg_name(&self, base: u8) -> McX86Reg {
let addr_size = self.prefixes.effective_address_size;
if addr_size == 64 {
mc_gpr64_name(base)
} else {
mc_gpr32_name(base)
}
}
fn index_reg_name(&self, index: u8) -> McX86Reg {
let addr_size = self.prefixes.effective_address_size;
if addr_size == 64 {
mc_gpr64_name(index)
} else {
mc_gpr32_name(index)
}
}
fn accumulator_reg(&self) -> McDecodedOperand {
let op_size = self.prefixes.effective_operand_size;
let rex_w = self.rex.map_or(false, |r| r.w);
let reg = if rex_w || (op_size == 64 && self.mode.is_64bit()) {
McX86Reg::RAX
} else if op_size == 32 {
McX86Reg::EAX
} else if op_size == 16 {
McX86Reg::AX
} else {
McX86Reg::AL
};
let size_hint = self.size_hint_for_gpr();
McDecodedOperand::Register { reg, size_hint }
}
fn opcode_reg_from_bits(&self, bits: u8) -> McDecodedOperand {
let op_size = self.prefixes.effective_operand_size;
let rex_b = self.rex.map_or(false, |r| r.b);
let reg_bits = if rex_b { bits | 0x08 } else { bits };
let reg = match op_size {
64 => mc_gpr64_name(reg_bits),
32 => mc_gpr32_name(reg_bits),
16 => mc_gpr16_name(reg_bits),
_ => mc_gpr8_name(reg_bits, self.rex.as_ref()),
};
let size_hint = self.size_hint_for_gpr();
McDecodedOperand::Register { reg, size_hint }
}
fn vector_reg_name(&self, reg: u8) -> McX86Reg {
let vector_len = self.determine_vector_length();
match vector_len {
512 => mc_zmm_name(reg),
256 => mc_ymm_name(reg),
_ => mc_xmm_name(reg),
}
}
fn opmask_reg_from_bits(&self, bits: u8) -> McX86Reg {
match bits & 0x07 {
0 => McX86Reg::K0,
1 => McX86Reg::K1,
2 => McX86Reg::K2,
3 => McX86Reg::K3,
4 => McX86Reg::K4,
5 => McX86Reg::K5,
6 => McX86Reg::K6,
7 => McX86Reg::K7,
_ => McX86Reg::K0,
}
}
fn size_hint_for_gpr(&self) -> McSizeHint {
let op_size = self.prefixes.effective_operand_size;
let rex_w = self.rex.map_or(false, |r| r.w);
if rex_w || (op_size == 64 && self.mode.is_64bit()) {
McSizeHint::Qword
} else {
match op_size {
32 => McSizeHint::Dword,
16 => McSizeHint::Word,
_ => McSizeHint::Byte,
}
}
}
fn vector_size_hint(&self) -> McSizeHint {
match self.determine_vector_length() {
512 => McSizeHint::Zword,
256 => McSizeHint::Yword,
_ => McSizeHint::Oword,
}
}
fn determine_vector_length(&self) -> u16 {
if let Some(ref vex) = self.vex {
if vex.l {
256
} else {
128
}
} else if let Some(ref evex) = self.evex {
match evex.ll {
0 => 128,
1 => 256,
2 => 512,
_ => 128,
}
} else {
0
}
}
fn lookup_primary(&self, opcode: u8) -> Option<McTableEntry> {
let table = primary_opcode_table();
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_0f(&self, opcode: u8) -> Option<McTableEntry> {
let table = opcode_table_0f();
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_0f38(&self, opcode: u8) -> Option<McTableEntry> {
let table = opcode_table_0f38();
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_0f3a(&self, opcode: u8) -> Option<McTableEntry> {
let table = opcode_table_0f3a();
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_vex(&self, opcode: u8, map: &McOpcodeMap) -> Option<McTableEntry> {
let table = match map {
McOpcodeMap::VexMap1 => vex_opcode_table_1(),
McOpcodeMap::VexMap2 => vex_opcode_table_2(),
McOpcodeMap::VexMap3 => vex_opcode_table_3(),
_ => return None,
};
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_evex(&self, opcode: u8, map: &McOpcodeMap) -> Option<McTableEntry> {
let table = match map {
McOpcodeMap::EvexMap1 => evex_opcode_table_1(),
McOpcodeMap::EvexMap2 => evex_opcode_table_2(),
McOpcodeMap::EvexMap3 => evex_opcode_table_3(),
McOpcodeMap::EvexMap4 => evex_opcode_table_4(),
McOpcodeMap::EvexMap5 => evex_opcode_table_5(),
McOpcodeMap::EvexMap6 => evex_opcode_table_6(),
_ => return None,
};
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
fn lookup_xop(&self, opcode: u8, map: &McOpcodeMap) -> Option<McTableEntry> {
let table = match map {
McOpcodeMap::XopMap8 => xop_opcode_table_8(),
McOpcodeMap::XopMap9 => xop_opcode_table_9(),
McOpcodeMap::XopMapA => xop_opcode_table_a(),
_ => return None,
};
table.into_iter().find(|e| e.opcode as u8 == opcode)
}
}
fn mc_gpr8_name(reg: u8, rex: Option<&McRexInfo>) -> McX86Reg {
let has_rex = rex.map_or(false, |r| r.present);
match (reg, has_rex) {
(0, _) => McX86Reg::AL,
(1, _) => McX86Reg::CL,
(2, _) => McX86Reg::DL,
(3, _) => McX86Reg::BL,
(4, false) => McX86Reg::AH,
(5, false) => McX86Reg::CH,
(6, false) => McX86Reg::DH,
(7, false) => McX86Reg::BH,
(4, true) => McX86Reg::SPL,
(5, true) => McX86Reg::BPL,
(6, true) => McX86Reg::SIL,
(7, true) => McX86Reg::DIL,
(8, _) => McX86Reg::R8B,
(9, _) => McX86Reg::R9B,
(10, _) => McX86Reg::R10B,
(11, _) => McX86Reg::R11B,
(12, _) => McX86Reg::R12B,
(13, _) => McX86Reg::R13B,
(14, _) => McX86Reg::R14B,
(15, _) => McX86Reg::R15B,
(16, _) => McX86Reg::R16B,
(17, _) => McX86Reg::R17B,
(18, _) => McX86Reg::R18B,
(19, _) => McX86Reg::R19B,
(20, _) => McX86Reg::R20B,
(21, _) => McX86Reg::R21B,
(22, _) => McX86Reg::R22B,
(23, _) => McX86Reg::R23B,
(24, _) => McX86Reg::R24B,
(25, _) => McX86Reg::R25B,
(26, _) => McX86Reg::R26B,
(27, _) => McX86Reg::R27B,
(28, _) => McX86Reg::R28B,
(29, _) => McX86Reg::R29B,
(30, _) => McX86Reg::R30B,
(31, _) => McX86Reg::R31B,
_ => McX86Reg::AL,
}
}
fn mc_gpr16_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::AX,
1 => McX86Reg::CX,
2 => McX86Reg::DX,
3 => McX86Reg::BX,
4 => McX86Reg::SP,
5 => McX86Reg::BP,
6 => McX86Reg::SI,
7 => McX86Reg::DI,
8 => McX86Reg::R8W,
9 => McX86Reg::R9W,
10 => McX86Reg::R10W,
11 => McX86Reg::R11W,
12 => McX86Reg::R12W,
13 => McX86Reg::R13W,
14 => McX86Reg::R14W,
15 => McX86Reg::R15W,
16 => McX86Reg::R16W,
17 => McX86Reg::R17W,
18 => McX86Reg::R18W,
19 => McX86Reg::R19W,
20 => McX86Reg::R20W,
21 => McX86Reg::R21W,
22 => McX86Reg::R22W,
23 => McX86Reg::R23W,
24 => McX86Reg::R24W,
25 => McX86Reg::R25W,
26 => McX86Reg::R26W,
27 => McX86Reg::R27W,
28 => McX86Reg::R28W,
29 => McX86Reg::R29W,
30 => McX86Reg::R30W,
31 => McX86Reg::R31W,
_ => McX86Reg::AX,
}
}
fn mc_gpr32_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::EAX,
1 => McX86Reg::ECX,
2 => McX86Reg::EDX,
3 => McX86Reg::EBX,
4 => McX86Reg::ESP,
5 => McX86Reg::EBP,
6 => McX86Reg::ESI,
7 => McX86Reg::EDI,
8 => McX86Reg::R8D,
9 => McX86Reg::R9D,
10 => McX86Reg::R10D,
11 => McX86Reg::R11D,
12 => McX86Reg::R12D,
13 => McX86Reg::R13D,
14 => McX86Reg::R14D,
15 => McX86Reg::R15D,
16 => McX86Reg::R16D,
17 => McX86Reg::R17D,
18 => McX86Reg::R18D,
19 => McX86Reg::R19D,
20 => McX86Reg::R20D,
21 => McX86Reg::R21D,
22 => McX86Reg::R22D,
23 => McX86Reg::R23D,
24 => McX86Reg::R24D,
25 => McX86Reg::R25D,
26 => McX86Reg::R26D,
27 => McX86Reg::R27D,
28 => McX86Reg::R28D,
29 => McX86Reg::R29D,
30 => McX86Reg::R30D,
31 => McX86Reg::R31D,
_ => McX86Reg::EAX,
}
}
fn mc_gpr64_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::RAX,
1 => McX86Reg::RCX,
2 => McX86Reg::RDX,
3 => McX86Reg::RBX,
4 => McX86Reg::RSP,
5 => McX86Reg::RBP,
6 => McX86Reg::RSI,
7 => McX86Reg::RDI,
8 => McX86Reg::R8,
9 => McX86Reg::R9,
10 => McX86Reg::R10,
11 => McX86Reg::R11,
12 => McX86Reg::R12,
13 => McX86Reg::R13,
14 => McX86Reg::R14,
15 => McX86Reg::R15,
16 => McX86Reg::R16,
17 => McX86Reg::R17,
18 => McX86Reg::R18,
19 => McX86Reg::R19,
20 => McX86Reg::R20,
21 => McX86Reg::R21,
22 => McX86Reg::R22,
23 => McX86Reg::R23,
24 => McX86Reg::R24,
25 => McX86Reg::R25,
26 => McX86Reg::R26,
27 => McX86Reg::R27,
28 => McX86Reg::R28,
29 => McX86Reg::R29,
30 => McX86Reg::R30,
31 => McX86Reg::R31,
_ => McX86Reg::RAX,
}
}
fn mc_xmm_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::XMM0,
1 => McX86Reg::XMM1,
2 => McX86Reg::XMM2,
3 => McX86Reg::XMM3,
4 => McX86Reg::XMM4,
5 => McX86Reg::XMM5,
6 => McX86Reg::XMM6,
7 => McX86Reg::XMM7,
8 => McX86Reg::XMM8,
9 => McX86Reg::XMM9,
10 => McX86Reg::XMM10,
11 => McX86Reg::XMM11,
12 => McX86Reg::XMM12,
13 => McX86Reg::XMM13,
14 => McX86Reg::XMM14,
15 => McX86Reg::XMM15,
16 => McX86Reg::XMM16,
17 => McX86Reg::XMM17,
18 => McX86Reg::XMM18,
19 => McX86Reg::XMM19,
20 => McX86Reg::XMM20,
21 => McX86Reg::XMM21,
22 => McX86Reg::XMM22,
23 => McX86Reg::XMM23,
24 => McX86Reg::XMM24,
25 => McX86Reg::XMM25,
26 => McX86Reg::XMM26,
27 => McX86Reg::XMM27,
28 => McX86Reg::XMM28,
29 => McX86Reg::XMM29,
30 => McX86Reg::XMM30,
31 => McX86Reg::XMM31,
_ => McX86Reg::XMM0,
}
}
fn mc_ymm_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::YMM0,
1 => McX86Reg::YMM1,
2 => McX86Reg::YMM2,
3 => McX86Reg::YMM3,
4 => McX86Reg::YMM4,
5 => McX86Reg::YMM5,
6 => McX86Reg::YMM6,
7 => McX86Reg::YMM7,
8 => McX86Reg::YMM8,
9 => McX86Reg::YMM9,
10 => McX86Reg::YMM10,
11 => McX86Reg::YMM11,
12 => McX86Reg::YMM12,
13 => McX86Reg::YMM13,
14 => McX86Reg::YMM14,
15 => McX86Reg::YMM15,
16 => McX86Reg::YMM16,
17 => McX86Reg::YMM17,
18 => McX86Reg::YMM18,
19 => McX86Reg::YMM19,
20 => McX86Reg::YMM20,
21 => McX86Reg::YMM21,
22 => McX86Reg::YMM22,
23 => McX86Reg::YMM23,
24 => McX86Reg::YMM24,
25 => McX86Reg::YMM25,
26 => McX86Reg::YMM26,
27 => McX86Reg::YMM27,
28 => McX86Reg::YMM28,
29 => McX86Reg::YMM29,
30 => McX86Reg::YMM30,
31 => McX86Reg::YMM31,
_ => McX86Reg::YMM0,
}
}
fn mc_zmm_name(reg: u8) -> McX86Reg {
match reg {
0 => McX86Reg::ZMM0,
1 => McX86Reg::ZMM1,
2 => McX86Reg::ZMM2,
3 => McX86Reg::ZMM3,
4 => McX86Reg::ZMM4,
5 => McX86Reg::ZMM5,
6 => McX86Reg::ZMM6,
7 => McX86Reg::ZMM7,
8 => McX86Reg::ZMM8,
9 => McX86Reg::ZMM9,
10 => McX86Reg::ZMM10,
11 => McX86Reg::ZMM11,
12 => McX86Reg::ZMM12,
13 => McX86Reg::ZMM13,
14 => McX86Reg::ZMM14,
15 => McX86Reg::ZMM15,
16 => McX86Reg::ZMM16,
17 => McX86Reg::ZMM17,
18 => McX86Reg::ZMM18,
19 => McX86Reg::ZMM19,
20 => McX86Reg::ZMM20,
21 => McX86Reg::ZMM21,
22 => McX86Reg::ZMM22,
23 => McX86Reg::ZMM23,
24 => McX86Reg::ZMM24,
25 => McX86Reg::ZMM25,
26 => McX86Reg::ZMM26,
27 => McX86Reg::ZMM27,
28 => McX86Reg::ZMM28,
29 => McX86Reg::ZMM29,
30 => McX86Reg::ZMM30,
31 => McX86Reg::ZMM31,
_ => McX86Reg::ZMM0,
}
}
fn mc_group1_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("add"),
1 => Some("or"),
2 => Some("adc"),
3 => Some("sbb"),
4 => Some("and"),
5 => Some("sub"),
6 => Some("xor"),
7 => Some("cmp"),
_ => None,
}
}
fn mc_group2_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("rol"),
1 => Some("ror"),
2 => Some("rcl"),
3 => Some("rcr"),
4 => Some("shl"),
5 => Some("shr"),
6 => Some("sal"),
7 => Some("sar"),
_ => None,
}
}
fn mc_group3_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("test"),
1 => Some("test"),
2 => Some("not"),
3 => Some("neg"),
4 => Some("mul"),
5 => Some("imul"),
6 => Some("div"),
7 => Some("idiv"),
_ => None,
}
}
fn mc_group4_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("inc"),
1 => Some("dec"),
_ => None,
}
}
fn mc_group5_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("inc"),
1 => Some("dec"),
2 => Some("call"),
3 => Some("call"),
4 => Some("jmp"),
5 => Some("jmp"),
6 => Some("push"),
_ => None,
}
}
fn mc_group6_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("sldt"),
1 => Some("str"),
2 => Some("lldt"),
3 => Some("ltr"),
4 => Some("verr"),
5 => Some("verw"),
_ => None,
}
}
fn mc_group7_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("sgdt"),
1 => Some("sidt"),
2 => Some("lgdt"),
3 => Some("lidt"),
4 => Some("smsw"),
6 => Some("lmsw"),
7 => Some("invlpg"),
_ => None,
}
}
fn mc_group8_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
4 => Some("bt"),
5 => Some("bts"),
6 => Some("btr"),
7 => Some("btc"),
_ => None,
}
}
fn mc_group9_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
1 => Some("cmpxchg8b"),
3 => Some("xrstors"),
4 => Some("xsavec"),
5 => Some("xsaves"),
6 => Some("vmptrld"),
7 => Some("vmptrst"),
_ => None,
}
}
fn mc_group10_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("ud2"),
_ => None,
}
}
fn mc_group11_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("mov"),
_ => None,
}
}
fn mc_group12_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("cmovo"),
1 => Some("cmovno"),
2 => Some("cmovb"),
3 => Some("cmovae"),
4 => Some("cmove"),
5 => Some("cmovne"),
6 => Some("cmovbe"),
7 => Some("cmova"),
_ => None,
}
}
fn mc_group13_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("cmovs"),
1 => Some("cmovns"),
2 => Some("cmovp"),
3 => Some("cmovnp"),
4 => Some("cmovl"),
5 => Some("cmovge"),
6 => Some("cmovle"),
7 => Some("cmovg"),
_ => None,
}
}
fn mc_group14_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("seto"),
1 => Some("setno"),
2 => Some("setb"),
3 => Some("setae"),
4 => Some("sete"),
5 => Some("setne"),
6 => Some("setbe"),
7 => Some("seta"),
_ => None,
}
}
fn mc_group15_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("sets"),
1 => Some("setns"),
2 => Some("setp"),
3 => Some("setnp"),
4 => Some("setl"),
5 => Some("setge"),
6 => Some("setle"),
7 => Some("setg"),
_ => None,
}
}
fn mc_group16_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("jo"),
1 => Some("jno"),
2 => Some("jb"),
3 => Some("jae"),
4 => Some("je"),
5 => Some("jne"),
6 => Some("jbe"),
7 => Some("ja"),
_ => None,
}
}
fn mc_group17_mnemonic(reg_field: u8) -> Option<&'static str> {
match reg_field {
0 => Some("js"),
1 => Some("jns"),
2 => Some("jp"),
3 => Some("jnp"),
4 => Some("jl"),
5 => Some("jge"),
6 => Some("jle"),
7 => Some("jg"),
_ => None,
}
}
fn mk_mc_entry(
mnemonic: &'static str,
form: McEncodingForm,
has_modrm: bool,
imm_size: u8,
feature: FeatureSet,
) -> McTableEntry {
McTableEntry {
opcode: 0,
mnemonic,
encoding_form: form,
has_modrm,
imm_size,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::None,
feature_required: feature,
}
}
fn mk_mc_entry_attrs(
mnemonic: &'static str,
form: McEncodingForm,
has_modrm: bool,
imm_size: u8,
attrs: McInstrAttributes,
feature: FeatureSet,
) -> McTableEntry {
McTableEntry {
opcode: 0,
mnemonic,
encoding_form: form,
has_modrm,
imm_size,
attributes: attrs,
group: None,
size_hint: McSizeHint::None,
feature_required: feature,
}
}
fn mk_mc_entry_group(opcode: u16, group: u8) -> McTableEntry {
McTableEntry {
opcode,
mnemonic: "",
encoding_form: McEncodingForm::GroupOpcodeExt,
has_modrm: true,
imm_size: 1,
attributes: McInstrAttributes {
has_modrm: true,
is_group_instruction: true,
opcode_extension_from_3bits: true,
..Default::default()
},
group: Some(group),
size_hint: McSizeHint::None,
feature_required: FeatureSet::Base,
}
}
fn primary_opcode_table() -> Vec<McTableEntry> {
vec![
McTableEntry {
opcode: 0x00,
mnemonic: "add",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x01,
mnemonic: "add",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x02,
mnemonic: "add",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x03,
mnemonic: "add",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x04,
mnemonic: "add",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x05,
mnemonic: "add",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), mk_mc_entry("pop", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x08,
mnemonic: "or",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x09,
mnemonic: "or",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x0A,
mnemonic: "or",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x0B,
mnemonic: "or",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x0C,
mnemonic: "or",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x0D,
mnemonic: "or",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), mk_mc_entry("nop", McEncodingForm::Implicit, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x10,
mnemonic: "adc",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x11,
mnemonic: "adc",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x12,
mnemonic: "adc",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x13,
mnemonic: "adc",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x14,
mnemonic: "adc",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x15,
mnemonic: "adc",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), mk_mc_entry("pop", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x18,
mnemonic: "sbb",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x19,
mnemonic: "sbb",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x1A,
mnemonic: "sbb",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x1B,
mnemonic: "sbb",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x1C,
mnemonic: "sbb",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x1D,
mnemonic: "sbb",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), mk_mc_entry("pop", McEncodingForm::RegOnly, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x20,
mnemonic: "and",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x21,
mnemonic: "and",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x22,
mnemonic: "and",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x23,
mnemonic: "and",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x24,
mnemonic: "and",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x25,
mnemonic: "and",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry_group(0x26, 22), mk_mc_entry("daa", McEncodingForm::Implicit, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x28,
mnemonic: "sub",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x29,
mnemonic: "sub",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x2A,
mnemonic: "sub",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x2B,
mnemonic: "sub",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x2C,
mnemonic: "sub",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x2D,
mnemonic: "sub",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry_group(0x2E, 23), mk_mc_entry("das", McEncodingForm::Implicit, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x30,
mnemonic: "xor",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x31,
mnemonic: "xor",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x32,
mnemonic: "xor",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x33,
mnemonic: "xor",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x34,
mnemonic: "xor",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x35,
mnemonic: "xor",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry_group(0x36, 24), mk_mc_entry("aaa", McEncodingForm::Implicit, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x38,
mnemonic: "cmp",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x39,
mnemonic: "cmp",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x3A,
mnemonic: "cmp",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x3B,
mnemonic: "cmp",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x3C,
mnemonic: "cmp",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x3D,
mnemonic: "cmp",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry_group(0x3E, 25), mk_mc_entry("aas", McEncodingForm::Implicit, false, 0, FeatureSet::Base), McTableEntry {
opcode: 0x40,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x41,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x42,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x43,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x44,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x45,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x46,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x47,
mnemonic: "inc",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x48,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x49,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4A,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4B,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4C,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4D,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4E,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x4F,
mnemonic: "dec",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x50,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x51,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x52,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x53,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x54,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x55,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x56,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x57,
mnemonic: "push",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x58,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x59,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5A,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5B,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5C,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5D,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5E,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x5F,
mnemonic: "pop",
encoding_form: McEncodingForm::RegOnly,
has_modrm: false,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Qword,
feature_required: FeatureSet::Base,
},
mk_mc_entry(
"pusha",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
), mk_mc_entry("popa", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("bound", McEncodingForm::RmReg, true, 0, FeatureSet::I486), mk_mc_entry("movsxd", McEncodingForm::RegRM, true, 0, FeatureSet::X86_64),
mk_mc_entry_group(0x64, 26), mk_mc_entry_group(0x65, 27), mk_mc_entry_group(0x66, 28), mk_mc_entry_group(0x67, 29), McTableEntry {
opcode: 0x68,
mnemonic: "push",
encoding_form: McEncodingForm::Implicit,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x69,
mnemonic: "imul",
encoding_form: McEncodingForm::RmRegImm,
has_modrm: true,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::I486,
},
McTableEntry {
opcode: 0x6A,
mnemonic: "push",
encoding_form: McEncodingForm::Implicit,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::I486,
},
McTableEntry {
opcode: 0x6B,
mnemonic: "imul",
encoding_form: McEncodingForm::RmRegImm,
has_modrm: true,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::I486,
},
mk_mc_entry("insb", McEncodingForm::Implicit, false, 0, FeatureSet::I486),
mk_mc_entry("insd", McEncodingForm::Implicit, false, 0, FeatureSet::I486),
mk_mc_entry(
"outsb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::I486,
),
mk_mc_entry(
"outsd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::I486,
),
mk_mc_entry("jo", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jno", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jb", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jae", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("je", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jne", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jbe", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("ja", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("js", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jns", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jp", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jnp", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jl", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jge", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jle", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("jg", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry_group(0x80, 1),
mk_mc_entry_group(0x81, 1),
mk_mc_entry_group(0x82, 1),
mk_mc_entry_group(0x83, 1),
McTableEntry {
opcode: 0x84,
mnemonic: "test",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x85,
mnemonic: "test",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x86,
mnemonic: "xchg",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x87,
mnemonic: "xchg",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x88,
mnemonic: "mov",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x89,
mnemonic: "mov",
encoding_form: McEncodingForm::RmReg,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x8A,
mnemonic: "mov",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0x8B,
mnemonic: "mov",
encoding_form: McEncodingForm::RegRM,
has_modrm: true,
imm_size: 0,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry("mov", McEncodingForm::RmReg, true, 0, FeatureSet::Base), mk_mc_entry("lea", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("mov", McEncodingForm::RmReg, true, 0, FeatureSet::Base), mk_mc_entry_group(0x8F, 30),
mk_mc_entry("nop", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("xchg", McEncodingForm::RegRM, true, 0, FeatureSet::Base), mk_mc_entry("cwde", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("cdq", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry(
"pushf",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
), mk_mc_entry("popf", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("sahf", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("lahf", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("mov", McEncodingForm::AccumMem, false, 0, FeatureSet::Base), mk_mc_entry("mov", McEncodingForm::AccumMem, false, 0, FeatureSet::Base), mk_mc_entry("mov", McEncodingForm::MemAccum, false, 0, FeatureSet::Base), mk_mc_entry("mov", McEncodingForm::MemAccum, false, 0, FeatureSet::Base), mk_mc_entry(
"movsb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"movsd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"cmpsb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"cmpsd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
McTableEntry {
opcode: 0xA8,
mnemonic: "test",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xA9,
mnemonic: "test",
encoding_form: McEncodingForm::AccumImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry(
"stosb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"stosd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"lodsb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"lodsd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"scasb",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
mk_mc_entry(
"scasd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
),
McTableEntry {
opcode: 0xB0,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB1,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB2,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB3,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB4,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB5,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB6,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB7,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 1,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Byte,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB8,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xB9,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBA,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBB,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBC,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBD,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBE,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
McTableEntry {
opcode: 0xBF,
mnemonic: "mov",
encoding_form: McEncodingForm::RegImm,
has_modrm: false,
imm_size: 4,
attributes: McInstrAttributes::default(),
group: None,
size_hint: McSizeHint::Dword,
feature_required: FeatureSet::Base,
},
mk_mc_entry_group(0xC0, 2),
mk_mc_entry_group(0xC1, 2),
mk_mc_entry("ret", McEncodingForm::Implicit, false, 2, FeatureSet::Base), mk_mc_entry("ret", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("les", McEncodingForm::RmReg, true, 0, FeatureSet::Base), mk_mc_entry("lds", McEncodingForm::RmReg, true, 0, FeatureSet::Base), mk_mc_entry_group(0xC6, 11),
mk_mc_entry_group(0xC7, 11),
mk_mc_entry(
"enter",
McEncodingForm::Implicit,
false,
2,
FeatureSet::I486,
),
mk_mc_entry(
"leave",
McEncodingForm::Implicit,
false,
0,
FeatureSet::I486,
),
mk_mc_entry("retf", McEncodingForm::Implicit, false, 2, FeatureSet::Base),
mk_mc_entry("retf", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("int3", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("int", McEncodingForm::Implicit, false, 1, FeatureSet::Base), mk_mc_entry("into", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("iret", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry_group(0xD0, 2),
mk_mc_entry_group(0xD1, 2),
mk_mc_entry_group(0xD2, 2),
mk_mc_entry_group(0xD3, 2),
mk_mc_entry("aam", McEncodingForm::Implicit, false, 1, FeatureSet::Base),
mk_mc_entry("aad", McEncodingForm::Implicit, false, 1, FeatureSet::Base),
mk_mc_entry("salc", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("xlat", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry_group(0xD8, 31),
mk_mc_entry_group(0xD9, 31),
mk_mc_entry_group(0xDA, 31),
mk_mc_entry_group(0xDB, 31),
mk_mc_entry_group(0xDC, 31),
mk_mc_entry_group(0xDD, 31),
mk_mc_entry_group(0xDE, 31),
mk_mc_entry_group(0xDF, 31),
mk_mc_entry(
"loopne",
McEncodingForm::RelBranch,
false,
1,
FeatureSet::Base,
),
mk_mc_entry(
"loope",
McEncodingForm::RelBranch,
false,
1,
FeatureSet::Base,
),
mk_mc_entry(
"loop",
McEncodingForm::RelBranch,
false,
1,
FeatureSet::Base,
),
mk_mc_entry(
"jecxz",
McEncodingForm::RelBranch,
false,
1,
FeatureSet::Base,
),
mk_mc_entry("in", McEncodingForm::AccumImm, false, 1, FeatureSet::Base),
mk_mc_entry("in", McEncodingForm::AccumImm, false, 1, FeatureSet::Base), mk_mc_entry("out", McEncodingForm::AccumImm, false, 1, FeatureSet::Base), mk_mc_entry("out", McEncodingForm::AccumImm, false, 1, FeatureSet::Base), mk_mc_entry(
"call",
McEncodingForm::RelBranch,
false,
4,
FeatureSet::Base,
), mk_mc_entry("jmp", McEncodingForm::RelBranch, false, 4, FeatureSet::Base), mk_mc_entry("jmp", McEncodingForm::RelBranch, false, 4, FeatureSet::Base), mk_mc_entry("jmp", McEncodingForm::RelBranch, false, 1, FeatureSet::Base), mk_mc_entry("in", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("in", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("out", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("out", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry_group(0xF0, 32), mk_mc_entry(
"icebp",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Base,
), mk_mc_entry_group(0xF2, 33), mk_mc_entry_group(0xF3, 34), mk_mc_entry("hlt", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry("cmc", McEncodingForm::Implicit, false, 0, FeatureSet::Base), mk_mc_entry_group(0xF6, 3),
mk_mc_entry_group(0xF7, 3),
mk_mc_entry("clc", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("stc", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("cli", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("sti", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("cld", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry("std", McEncodingForm::Implicit, false, 0, FeatureSet::Base),
mk_mc_entry_group(0xFE, 4),
mk_mc_entry_group(0xFF, 5),
]
}
fn opcode_table_0f() -> Vec<McTableEntry> {
vec![
mk_mc_entry_group(0x00, 6),
mk_mc_entry_group(0x01, 7),
mk_mc_entry("lar", McEncodingForm::RegRM, true, 0, FeatureSet::I486),
mk_mc_entry("lsl", McEncodingForm::RegRM, true, 0, FeatureSet::I486),
mk_mc_entry(
"syscall",
McEncodingForm::Implicit,
false,
0,
FeatureSet::X86_64,
),
mk_mc_entry("clts", McEncodingForm::Implicit, false, 0, FeatureSet::I486),
mk_mc_entry(
"sysret",
McEncodingForm::Implicit,
false,
0,
FeatureSet::X86_64,
),
mk_mc_entry("invd", McEncodingForm::Implicit, false, 0, FeatureSet::I486),
mk_mc_entry(
"wbinvd",
McEncodingForm::Implicit,
false,
0,
FeatureSet::I486,
),
mk_mc_entry("ud2", McEncodingForm::Implicit, false, 0, FeatureSet::I486),
mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6),
mk_mc_entry(
"femms",
McEncodingForm::Implicit,
false,
0,
FeatureSet::ThreeDNow,
),
mk_mc_entry_group(0x0F, 35), mk_mc_entry(
"movups",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movups",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movlps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movlps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"unpcklps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"unpckhps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movhps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movhps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE,
), mk_mc_entry_group(0x18, 36), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("nop", McEncodingForm::RmOnly, true, 0, FeatureSet::P6), mk_mc_entry("mov", McEncodingForm::RmReg, true, 0, FeatureSet::I486), mk_mc_entry("mov", McEncodingForm::RmReg, true, 0, FeatureSet::I486), mk_mc_entry("mov", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("mov", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry(
"movaps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"movaps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"cvtpi2ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"cvtps2pi",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"ucomiss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"comiss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"wrmsr",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"rdtsc",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"rdmsr",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"rdpmc",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"sysenter",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"sysexit",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
),
mk_mc_entry(
"getsec",
McEncodingForm::Implicit,
false,
0,
FeatureSet::SMX,
),
mk_mc_entry_group(0x40, 12),
mk_mc_entry_group(0x41, 12),
mk_mc_entry_group(0x42, 12),
mk_mc_entry_group(0x43, 12),
mk_mc_entry_group(0x44, 12),
mk_mc_entry_group(0x45, 12),
mk_mc_entry_group(0x46, 12),
mk_mc_entry_group(0x47, 12),
mk_mc_entry_group(0x48, 12),
mk_mc_entry_group(0x49, 12),
mk_mc_entry_group(0x4A, 12),
mk_mc_entry_group(0x4B, 12),
mk_mc_entry_group(0x4C, 12),
mk_mc_entry_group(0x4D, 12),
mk_mc_entry_group(0x4E, 12),
mk_mc_entry_group(0x4F, 12),
mk_mc_entry(
"movmskps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"sqrtps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"rsqrtps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"rcpps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"andps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"andnps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"orps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"xorps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"addps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"mulps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"cvtps2pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"cvtdq2ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"subps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"minps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"divps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"maxps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"punpcklbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpcklwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpckldq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"packsswb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pcmpgtb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pcmpgtw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pcmpgtd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"packuswb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpckhbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpckhwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpckhdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"packssdw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"punpcklqdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"punpckhqdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"movd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"movq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pshufw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE,
), mk_mc_entry_group(0x71, 37), mk_mc_entry_group(0x72, 38), mk_mc_entry_group(0x73, 39), mk_mc_entry(
"pcmpeqb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pcmpeqw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry(
"pcmpeqd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::MMX,
), mk_mc_entry("emms", McEncodingForm::Implicit, false, 0, FeatureSet::MMX), mk_mc_entry("vmread", McEncodingForm::RmReg, true, 0, FeatureSet::VMX), mk_mc_entry("vmwrite", McEncodingForm::RmReg, true, 0, FeatureSet::VMX), mk_mc_entry(
"movd",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"movq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry("jo", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jno", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jb", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jae", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("je", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jne", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jbe", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("ja", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("js", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jns", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jp", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jnp", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jl", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jge", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jle", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry("jg", McEncodingForm::RelBranch, false, 4, FeatureSet::I486), mk_mc_entry_group(0x90, 14),
mk_mc_entry_group(0x91, 14),
mk_mc_entry_group(0x92, 14),
mk_mc_entry_group(0x93, 14),
mk_mc_entry_group(0x94, 14),
mk_mc_entry_group(0x95, 14),
mk_mc_entry_group(0x96, 14),
mk_mc_entry_group(0x97, 14),
mk_mc_entry_group(0x98, 14),
mk_mc_entry_group(0x99, 14),
mk_mc_entry_group(0x9A, 14),
mk_mc_entry_group(0x9B, 14),
mk_mc_entry_group(0x9C, 14),
mk_mc_entry_group(0x9D, 14),
mk_mc_entry_group(0x9E, 14),
mk_mc_entry_group(0x9F, 14),
mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("pop", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry(
"cpuid",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
), mk_mc_entry("bt", McEncodingForm::RmRegImm, true, 4, FeatureSet::I486), mk_mc_entry("shld", McEncodingForm::RmRegImm, true, 1, FeatureSet::I486), mk_mc_entry("shld", McEncodingForm::RmRegImm, true, 1, FeatureSet::I486), mk_mc_entry_group(0xA6, 40), mk_mc_entry_group(0xA7, 40), mk_mc_entry("push", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("pop", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry(
"rsm",
McEncodingForm::Implicit,
false,
0,
FeatureSet::Pentium,
), mk_mc_entry("bts", McEncodingForm::RmRegImm, true, 4, FeatureSet::I486), mk_mc_entry("shrd", McEncodingForm::RmRegImm, true, 1, FeatureSet::I486), mk_mc_entry("shrd", McEncodingForm::RmRegImm, true, 1, FeatureSet::I486), mk_mc_entry_group(0xAE, 41), mk_mc_entry("imul", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry(
"cmpxchg",
McEncodingForm::RmReg,
true,
0,
FeatureSet::Pentium,
), mk_mc_entry(
"cmpxchg",
McEncodingForm::RmReg,
true,
0,
FeatureSet::Pentium,
), mk_mc_entry("lss", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("btr", McEncodingForm::RmRegImm, true, 4, FeatureSet::I486), mk_mc_entry("lfs", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("lgs", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("movzx", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("movzx", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry_group(0xB8, 42), mk_mc_entry_group(0xB9, 43), mk_mc_entry_group(0xBA, 8), mk_mc_entry("btc", McEncodingForm::RmRegImm, true, 4, FeatureSet::I486), mk_mc_entry("bsf", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("bsr", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("movsx", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("movsx", McEncodingForm::RegRM, true, 0, FeatureSet::I486), mk_mc_entry("xadd", McEncodingForm::RmReg, true, 0, FeatureSet::I486), mk_mc_entry("xadd", McEncodingForm::RmReg, true, 0, FeatureSet::I486), mk_mc_entry(
"cmpps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE,
), mk_mc_entry("movnti", McEncodingForm::RmReg, true, 0, FeatureSet::SSE2), mk_mc_entry(
"pinsrw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE,
), mk_mc_entry(
"pextrw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE,
), mk_mc_entry(
"shufps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE,
), mk_mc_entry_group(0xC7, 9), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry("bswap", McEncodingForm::RegOnly, false, 0, FeatureSet::I486), mk_mc_entry(
"psrlw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psrld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psrlq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmullw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"movq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmovmskb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubusb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubusw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pminub",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pand",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddusb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddusw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmaxub",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pandn",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pavgb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psraw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psrad",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pavgw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmulhuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmulhw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"cvttpd2dq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"movntdq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pminsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"por",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pmaxsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"pxor",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry_group(0xF0, 44), mk_mc_entry(
"psadbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"maskmovq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"psubb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"psubq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry(
"paddd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE2,
), mk_mc_entry("ud0", McEncodingForm::Implicit, false, 0, FeatureSet::I486), ]
}
fn opcode_table_0f38() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"pshufb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phaddw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phaddd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phaddsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pmaddubsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phsubw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phsubd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"phsubsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"psignb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"psignw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"psignd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pmulhrsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pabsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pabsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pabsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSSE3,
), mk_mc_entry(
"pmuldq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pcmpeqq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"movntdqa",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"packusdw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxbd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxbq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovsxdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxbd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxbq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmovzxdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pminuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pminud",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmaxuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmaxud",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pminsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pminsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmaxsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmaxsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"pmulld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"phminposuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE41,
), mk_mc_entry(
"aesenc",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AES,
), mk_mc_entry(
"aesenclast",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AES,
), mk_mc_entry(
"aesdec",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AES,
), mk_mc_entry(
"aesdeclast",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AES,
), mk_mc_entry(
"pclmulqdq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::PCLMUL,
), mk_mc_entry("crc32", McEncodingForm::RegRM, true, 0, FeatureSet::SSE42), mk_mc_entry("crc32", McEncodingForm::RegRM, true, 0, FeatureSet::SSE42), mk_mc_entry("adcx", McEncodingForm::RegRM, true, 0, FeatureSet::ADX), mk_mc_entry("adox", McEncodingForm::RegRM, true, 0, FeatureSet::ADX), mk_mc_entry(
"sha1nexte",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), mk_mc_entry(
"sha1msg1",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), mk_mc_entry(
"sha1msg2",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), mk_mc_entry(
"sha256rnds2",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), mk_mc_entry(
"sha256msg1",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), mk_mc_entry(
"sha256msg2",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SHA,
), ]
}
fn opcode_table_0f3a() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"roundps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"roundpd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"roundss",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"roundsd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"blendps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"blendpd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pblendw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"palignr",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSSE3,
), mk_mc_entry(
"extractps",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"insertps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pinsrb",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pinsrd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pextrb",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pextrw",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pextrd",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"dpps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"dppd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"mpsadbw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE41,
), mk_mc_entry(
"pcmpestrm",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE42,
), mk_mc_entry(
"pcmpestri",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE42,
), mk_mc_entry(
"pcmpistrm",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE42,
), mk_mc_entry(
"pcmpistri",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SSE42,
), mk_mc_entry(
"aeskeygenassist",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AES,
), mk_mc_entry(
"sha1rnds4",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SHA,
), ]
}
fn vex_opcode_table_1() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vmovups",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovups",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovlps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovlps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vunpcklps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vunpckhps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovhps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovhps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovaps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovaps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovntps",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovntpd",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovntdq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovdqa",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovdqa",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovdqu",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovdqu",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpacksswb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpackssdw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpackuswb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpcklbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpcklwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpckldq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpcklqdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpckhbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpckhwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpckhdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpunpckhqdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpaddb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpaddw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpaddd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpaddq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsubb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsubw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsubd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsubq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmullw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmulhw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmulhuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpand",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpandn",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpor",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpxor",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpavgb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpavgw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsadbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovmskb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpgtb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpgtw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpgtd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpeqb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpeqw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpeqd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminub",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxub",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsrlw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsrld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsrlq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsraw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsrad",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsllw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpslld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsllq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vandps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vandnps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vorps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vxorps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaddps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmulps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vsubps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vminps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vdivps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmaxps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vsqrtps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vrsqrtps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vrcpps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vshufps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vcmpps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vmovmskps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vandpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vandnpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vorpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vxorpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaddpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmulpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vsubpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vminpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vdivpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmaxpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vsqrtpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtps2pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtpd2ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtdq2ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtps2dq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvttps2dq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvttpd2dq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtpd2dq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vlDDQU",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vlddqu",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmaskmovdqu",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::SSE,
), mk_mc_entry(
"vmovd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovd",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovq",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpinsrw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpextrw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vcomiss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vucomiss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcomisd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vucomisd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtss2si",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtsd2si",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtsi2ss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvtsi2sd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvttss2si",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vcvttsd2si",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vptest",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), ]
}
fn vex_opcode_table_2() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vpshufb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphaddw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphaddd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphaddsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaddubsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphsubw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphsubd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphsubsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsignb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsignw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpsignd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmulhrsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpermilps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpermilpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vtestps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vtestpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpabsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpabsw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpabsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxbd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxbq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovsxdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmuldq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpeqq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vmovntdqa",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpackusdw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxbd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxbq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmovzxdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpermd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpcmpgtq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpminud",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxsb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmaxud",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpmulld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vphminposuw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpgtq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpclmulqdq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vperm2i128",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX2,
), mk_mc_entry(
"vpmaskmovd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpmaskmovq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpsllvd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpsllvq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpsrlvd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpsrlvq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpsravd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpbroadcastb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpbroadcastw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpbroadcastd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpbroadcastq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vinserti128",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX2,
), mk_mc_entry(
"vextracti128",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX2,
), mk_mc_entry(
"vgatherdps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vgatherdpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vgatherqps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vgatherqpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpgatherdd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpgatherdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpgatherqd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vpgatherqq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX2,
), mk_mc_entry(
"vaesenc",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaesenclast",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaesdec",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaesdeclast",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaesimc",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaeskeygenassist",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vfmadd132ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd213ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd231ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd132pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd213pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd231pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd132ss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd213ss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd231ss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd132sd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd213sd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmadd231sd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub132ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub213ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub231ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub132pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub213pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfmsub231pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmadd132ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmadd213ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmadd231ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmsub132ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmsub213ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"vfnmsub231ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA,
), mk_mc_entry(
"andn",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI,
), mk_mc_entry(
"bextr",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI,
), mk_mc_entry(
"blsi",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::BMI,
), mk_mc_entry(
"blsmsk",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::BMI,
), mk_mc_entry(
"blsr",
McEncodingForm::VexVvvvRmReg,
true,
0,
FeatureSet::BMI,
), mk_mc_entry(
"bzhi",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI2,
), mk_mc_entry(
"mulx",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI2,
), mk_mc_entry(
"pdep",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI2,
), mk_mc_entry(
"pext",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::BMI2,
), mk_mc_entry(
"rorx",
McEncodingForm::VexVvvvRmImm,
true,
1,
FeatureSet::BMI2,
), ]
}
fn vex_opcode_table_3() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vroundps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vroundpd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vroundss",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vroundsd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vblendps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vblendpd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpblendw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpalignr",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vextractps",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vextractf128",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vinsertf128",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vinsertps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpinsrb",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vinsertps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpinsrd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpinsrq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpextrb",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpextrw",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpextrd",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpextrq",
McEncodingForm::VexVvvvRmReg,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vdpps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vdppd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vmpsadbw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpclmulqdq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vperm2f128",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpermil2ps",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpermil2pd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpestrm",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpestri",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpistrm",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vpcmpistri",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vblendvps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vblendvpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vpblendvb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::AVX,
), mk_mc_entry(
"vaeskeygenassist",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::AVX,
), mk_mc_entry(
"vsha1rnds4",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::SHA,
), ]
}
fn evex_opcode_table_1() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vmovups",
McEncodingForm::EvexRegKRm,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vmovups",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vaddps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vmulps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vsubps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vdivps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vminps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vmaxps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vaddpd",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vmulpd",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), mk_mc_entry(
"vsubpd",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512F,
), ]
}
fn evex_opcode_table_2() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vpshufb",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AVX512BW,
), ]
}
fn evex_opcode_table_3() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vblendps",
McEncodingForm::EvexVvvvKRmReg,
true,
1,
FeatureSet::AVX512F,
), ]
}
fn evex_opcode_table_4() -> Vec<McTableEntry> {
vec![
]
}
fn evex_opcode_table_5() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"tileloadd",
McEncodingForm::EvexRegKRm,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tileloaddt1",
McEncodingForm::EvexRegKRm,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tilestored",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tdpbf16ps",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tdpbssd",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tdpbusd",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tdpbuud",
McEncodingForm::EvexVvvvKRmReg,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tilezero",
McEncodingForm::EvexRegKRm,
true,
0,
FeatureSet::AMX,
), mk_mc_entry(
"tilerelease",
McEncodingForm::Implicit,
false,
0,
FeatureSet::AMX,
), ]
}
fn evex_opcode_table_6() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vfpclassps",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vfpclasspd",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vfpclassss",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vfpclasssd",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vrangeps",
McEncodingForm::EvexVvvvKRmReg,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vrangepd",
McEncodingForm::EvexVvvvKRmReg,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vrangess",
McEncodingForm::EvexVvvvKRmReg,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vrangesd",
McEncodingForm::EvexVvvvKRmReg,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vreduceps",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vreducepd",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vreducess",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), mk_mc_entry(
"vreducesd",
McEncodingForm::EvexRegKRm,
true,
1,
FeatureSet::AVX512DQ,
), ]
}
fn threednow_opcode_table() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"pi2fd",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pi2fw",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pf2id",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pf2iw",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfcmpge",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfcmpgt",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfcmpeq",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfacc",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfadd",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfsub",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfsubr",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfmul",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfmin",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfmax",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfrcp",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfrcpit1",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfrcpit2",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfrsqit1",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfrsqrt",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pavgusb",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pmulhrw",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pmovmskb",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pswapd",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfnacc",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), mk_mc_entry(
"pfpnacc",
McEncodingForm::RmReg,
true,
0,
FeatureSet::ThreeDNow,
), ]
}
fn xop_opcode_table_8() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vpmacsww",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmacssww",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmacsswd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmacssdd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmacssdql",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmacssdqh",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmadcsswd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpmadcswd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddbd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddbq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphadddq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddubw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddubd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddubq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphadduwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphadduwq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphaddudq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphsubbw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphsubwd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vphsubdq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vprotb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vprotw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vprotd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vprotq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshlb",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshlw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshld",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshlq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshab",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshaw",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshad",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpshaq",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpermil2ps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpermil2pd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomb",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomd",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomub",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomuw",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomud",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vpcomuq",
McEncodingForm::VexRegVvvvRm,
true,
1,
FeatureSet::XOP,
), ]
}
fn xop_opcode_table_9() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vfrczps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vfrczpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vfrczss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vfrczsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpcmov",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpcmov",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vpperm",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::XOP,
), mk_mc_entry(
"vprotb",
McEncodingForm::VexVvvvRmImm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vprotw",
McEncodingForm::VexVvvvRmImm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vprotd",
McEncodingForm::VexVvvvRmImm,
true,
1,
FeatureSet::XOP,
), mk_mc_entry(
"vprotq",
McEncodingForm::VexVvvvRmImm,
true,
1,
FeatureSet::XOP,
), ]
}
fn xop_opcode_table_a() -> Vec<McTableEntry> {
vec![
mk_mc_entry(
"vfmaddps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmaddpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmaddss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmaddsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmaddps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmaddpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmaddss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmaddsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmsubps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmsubpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmsubss",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfnmsubsd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmaddsubps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmaddsubpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubaddps",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), mk_mc_entry(
"vfmsubaddpd",
McEncodingForm::VexRegVvvvRm,
true,
0,
FeatureSet::FMA4,
), ]
}
pub struct X86OperandFormatter {
syntax: McDisasmSyntax,
}
impl X86OperandFormatter {
pub fn new(syntax: McDisasmSyntax) -> Self {
X86OperandFormatter { syntax }
}
pub fn set_syntax(&mut self, syntax: McDisasmSyntax) {
self.syntax = syntax;
}
pub fn format(
&self,
inst: &McDecodedInstruction,
show_bytes: bool,
raw_bytes: &[u8],
) -> Option<String> {
let mut result = String::new();
if show_bytes {
result.push_str(&format!("{:08x}: ", inst.address));
for i in 0..inst.size.min(raw_bytes.len()) {
result.push_str(&format!("{:02x} ", raw_bytes[i]));
}
let padding = (15usize.saturating_sub(inst.size)) * 3;
for _ in 0..padding {
result.push(' ');
}
result.push('\t');
} else {
result.push('\t');
}
match self.syntax {
McDisasmSyntax::Intel | McDisasmSyntax::Annotated => {
result.push_str(&self.format_intel(inst));
}
McDisasmSyntax::Att => {
result.push_str(&self.format_att(inst));
}
}
if self.syntax == McDisasmSyntax::Annotated {
result.push_str(&format!(" # 0x{:x}: {}", inst.address, inst.mnemonic));
}
Some(result)
}
pub fn format_operand_intel(
&self,
op: &McDecodedOperand,
inst: &McDecodedInstruction,
) -> String {
match op {
McDecodedOperand::Register { reg, .. } => reg.name().to_string(),
McDecodedOperand::Memory {
base,
index,
displacement,
size_hint,
rip_relative,
..
} => {
let mut s = String::new();
if *rip_relative {
if *displacement < 0 {
s.push_str(&format!("[rip - 0x{:x}]", displacement.unsigned_abs()));
} else if *displacement == 0 {
s.push_str("[rip]");
} else {
s.push_str(&format!("[rip + 0x{:x}]", *displacement as u64));
}
} else {
s.push('[');
let mut parts: Vec<String> = Vec::new();
if let Some(b) = base {
parts.push(b.name().to_string());
}
if let Some((idx, scale)) = index {
if *scale != 1 {
parts.push(format!("{}*{}", idx.name(), scale));
} else {
parts.push(idx.name().to_string());
}
}
if *displacement != 0 || (base.is_none() && index.is_none()) {
let d = *displacement;
if d < 0 {
parts.push(format!("- 0x{:x}", d.unsigned_abs()));
} else {
parts.push(format!("+ 0x{:x}", d as u64));
}
}
s.push_str(&parts.join(" + "));
s.push(']');
}
if base.is_none() && index.is_none() && !rip_relative {
s = format!(
"{}[{}]",
size_hint.intel_prefix(),
s.trim_start_matches('[').trim_end_matches(']')
);
}
s
}
McDecodedOperand::Immediate { value, .. } => {
if value.unsigned_abs() > 9 {
if *value < 0 {
format!("-0x{:x}", value.unsigned_abs())
} else {
format!("0x{:x}", *value as u64)
}
} else {
format!("{}", value)
}
}
McDecodedOperand::RelativeOffset { offset, .. } => {
let target = (inst.address as i64)
.wrapping_add(inst.size as i64)
.wrapping_add(*offset);
format!("0x{:x}", target as u64)
}
McDecodedOperand::ImplicitRegister { reg } => reg.name().to_string(),
McDecodedOperand::OpmaskRegister { reg, zeroing } => {
if *zeroing {
format!("{} {{z}}", reg.name())
} else {
reg.name().to_string()
}
}
McDecodedOperand::FPURegister { index } => format!("st({})", index),
}
}
pub fn format_operand_att(&self, op: &McDecodedOperand, inst: &McDecodedInstruction) -> String {
match op {
McDecodedOperand::Register { reg, .. } => format!("%{}", reg.name()),
McDecodedOperand::Memory {
segment,
base,
index,
displacement,
rip_relative,
..
} => {
let mut s = String::new();
if let Some(seg) = segment {
s.push_str(&format!("%{}:", seg.name()));
}
if *rip_relative {
if *displacement < 0 {
s.push_str(&format!("-0x{:x}(%rip)", displacement.unsigned_abs()));
} else if *displacement == 0 {
s.push_str("(%rip)");
} else {
s.push_str(&format!("0x{:x}(%rip)", *displacement as u64));
}
} else {
let d = *displacement;
let disp_str = if d < 0 {
format!("-0x{:x}", d.unsigned_abs())
} else if d == 0 && (base.is_some() || index.is_some()) {
String::new()
} else {
format!("0x{:x}", d as u64)
};
let base_str = base.map_or(String::new(), |b| format!("%{}", b.name()));
let index_str = match index {
Some((idx, scale)) => {
if *scale != 1 {
format!(", %{}, {}", idx.name(), scale)
} else {
format!(", %{}", idx.name())
}
}
None => String::new(),
};
s.push_str(&format!("{}({}{})", disp_str, base_str, index_str));
}
s
}
McDecodedOperand::Immediate { value, .. } => {
if value.unsigned_abs() > 9 {
if *value < 0 {
format!("$-0x{:x}", value.unsigned_abs())
} else {
format!("$0x{:x}", *value as u64)
}
} else {
format!("${}", value)
}
}
McDecodedOperand::RelativeOffset { offset, .. } => {
let target = (inst.address as i64)
.wrapping_add(inst.size as i64)
.wrapping_add(*offset);
format!("0x{:x}", target as u64)
}
McDecodedOperand::ImplicitRegister { reg } => format!("%{}", reg.name()),
McDecodedOperand::OpmaskRegister { reg, zeroing } => {
if *zeroing {
format!("%{} {{z}}", reg.name())
} else {
format!("%{}", reg.name())
}
}
McDecodedOperand::FPURegister { index } => format!("%st({})", index),
}
}
fn format_intel(&self, inst: &McDecodedInstruction) -> String {
let mut s = inst.mnemonic.clone();
if let Some(ref evex) = inst.evex {
if evex.aaa > 0 && inst.attributes.uses_opmask {
s.push_str(&format!(" {{k{}}}", evex.aaa));
if evex.z {
s.push_str("{z}");
}
}
if evex.b_bit && inst.attributes.uses_broadcast {
s.push_str(" {1toX}");
}
if inst.attributes.uses_er {
match evex.ll {
0 => s.push_str(", {rn-sae}"),
1 => s.push_str(", {rd-sae}"),
2 => s.push_str(", {ru-sae}"),
3 => s.push_str(", {rz-sae}"),
_ => {}
}
}
if inst.attributes.uses_sae {
s.push_str(", {sae}");
}
}
if !inst.operands.is_empty() {
s.push(' ');
let parts: Vec<String> = inst
.operands
.iter()
.map(|op| self.format_operand_intel(op, inst))
.collect();
s.push_str(&parts.join(", "));
}
s
}
fn format_att(&self, inst: &McDecodedInstruction) -> String {
let mut mnem = inst.mnemonic.clone();
let suffix = if let Some(first_op) = inst.operands.first() {
match first_op {
McDecodedOperand::Register { reg, .. } => reg.size_suffix(),
McDecodedOperand::Memory { size_hint, .. } => size_hint.att_suffix(),
McDecodedOperand::Immediate { size, .. } => match size {
1 => "b",
2 => "w",
4 => "l",
8 => "q",
_ => "",
},
_ => "",
}
} else {
""
};
if !mnem.contains('.')
&& !mnem.starts_with('j')
&& !mnem.starts_with("call")
&& !mnem.starts_with("ret")
&& !mnem.starts_with("sys")
&& !mnem.starts_with("loop")
&& !suffix.is_empty()
{
if !mnem.ends_with(suffix) {
mnem.push_str(suffix);
}
}
if let Some(ref evex) = inst.evex {
if evex.aaa > 0 && inst.attributes.uses_opmask {
mnem.push_str(&format!(" {{k{}}}", evex.aaa));
if evex.z {
mnem.push_str("{z}");
}
}
if evex.b_bit && inst.attributes.uses_broadcast {
mnem.push_str(" {1toX}");
}
if inst.attributes.uses_er {
match evex.ll {
0 => mnem.push_str(", {rn-sae}"),
1 => mnem.push_str(", {rd-sae}"),
2 => mnem.push_str(", {ru-sae}"),
3 => mnem.push_str(", {rz-sae}"),
_ => {}
}
}
if inst.attributes.uses_sae {
mnem.push_str(", {sae}");
}
}
if !inst.operands.is_empty() {
let parts: Vec<String> = inst
.operands
.iter()
.map(|op| self.format_operand_att(op, inst))
.collect();
mnem.push(' ');
mnem.push_str(&parts.join(", "));
}
if inst.attributes.has_lock_prefix {
mnem = format!("lock {}", mnem);
}
if inst.attributes.has_rep_prefix {
mnem = format!("rep {}", mnem);
}
if inst.attributes.has_repne_prefix {
mnem = format!("repne {}", mnem);
}
mnem
}
}
pub struct X86InstructionAnnotator {
symbol_prefix: String,
comment_style: String,
}
impl X86InstructionAnnotator {
pub fn new() -> Self {
X86InstructionAnnotator {
symbol_prefix: "# ".to_string(),
comment_style: "; ".to_string(),
}
}
pub fn annotate(&self, inst: &McDecodedInstruction, symbols: &BTreeMap<u64, String>) -> String {
let mut annotations = Vec::new();
for op in &inst.operands {
match op {
McDecodedOperand::RelativeOffset { offset, .. } => {
let target = (inst.address as i64)
.wrapping_add(inst.size as i64)
.wrapping_add(*offset) as u64;
if let Some(name) = symbols.get(&target) {
annotations.push(format!("target: {}", name));
}
}
McDecodedOperand::Memory {
displacement,
base,
index,
rip_relative,
..
} => {
if *rip_relative {
let target = (inst.address as i64)
.wrapping_add(inst.size as i64)
.wrapping_add(*displacement)
as u64;
if let Some(name) = symbols.get(&target) {
annotations.push(format!("ref: {}", name));
}
} else if base.is_none() && index.is_none() {
let addr = *displacement as u64;
if let Some(name) = symbols.get(&addr) {
annotations.push(format!("addr: {}", name));
}
}
}
_ => {}
}
}
let purpose = self.instruction_purpose(inst);
if let Some(p) = purpose {
annotations.push(p);
}
if annotations.is_empty() {
String::new()
} else {
format!("{} {}", self.comment_style, annotations.join(", "))
}
}
pub fn instruction_purpose(&self, inst: &McDecodedInstruction) -> Option<String> {
let m = inst.mnemonic.as_str();
let base_m = if m.starts_with('v')
&& m.len() > 1
&& m.as_bytes()[1].is_ascii_alphabetic()
&& !m.starts_with("vmx")
&& !m.starts_with("ver")
{
&m[1..]
} else {
m
};
match m {
"nop" => Some("no operation".into()),
"ret" | "retf" => Some("return from procedure".into()),
"call" => Some("call procedure".into()),
"jmp" => Some("unconditional jump".into()),
"int3" => Some("breakpoint trap".into()),
"hlt" => Some("halt processor".into()),
"ud2" | "ud0" => Some("undefined instruction".into()),
"syscall" => Some("fast system call (64-bit)".into()),
"sysenter" => Some("fast system call (32-bit)".into()),
"sysexit" => Some("fast return from system call (32-bit)".into()),
"sysret" => Some("fast return from system call (64-bit)".into()),
"cpuid" => Some("CPU identification".into()),
"rdtsc" => Some("read time-stamp counter".into()),
"rdtscp" => Some("read time-stamp counter + processor ID".into()),
"rdmsr" => Some("read model-specific register".into()),
"wrmsr" => Some("write model-specific register".into()),
"rdpmc" => Some("read performance-monitoring counter".into()),
"push" if inst.attributes.has_lock_prefix => Some("locked push (atomic)".into()),
"cli" => Some("clear interrupt flag".into()),
"sti" => Some("set interrupt flag".into()),
"mfence" => Some("memory fence".into()),
"lfence" => Some("load fence".into()),
"sfence" => Some("store fence".into()),
"xchg" => Some("atomic exchange".into()),
"cmpxchg" => Some("atomic compare-and-exchange".into()),
"cmpxchg8b" => Some("atomic 8-byte compare-and-exchange".into()),
"cmpxchg16b" => Some("atomic 16-byte compare-and-exchange".into()),
"pause" => Some("spin-loop hint".into()),
"int" => Some("software interrupt".into()),
"iret" | "iretd" | "iretq" => Some("return from interrupt".into()),
"add" => Some("integer addition".into()),
"sub" => Some("integer subtraction".into()),
"mul" => Some("unsigned multiply".into()),
"imul" => Some("signed multiply".into()),
"div" => Some("unsigned divide".into()),
"idiv" => Some("signed divide".into()),
"and" => Some("bitwise AND".into()),
"or" => Some("bitwise OR".into()),
"xor" => Some("bitwise XOR".into()),
"not" => Some("bitwise NOT".into()),
"neg" => Some("two's complement negation".into()),
"shl" | "sal" => Some("shift left".into()),
"shr" => Some("logical shift right".into()),
"sar" => Some("arithmetic shift right".into()),
"rol" => Some("rotate left".into()),
"ror" => Some("rotate right".into()),
"rcl" => Some("rotate left through carry".into()),
"rcr" => Some("rotate right through carry".into()),
"test" => Some("logical compare (AND)".into()),
"cmp" => Some("arithmetic compare".into()),
"mov" => Some("data move".into()),
"lea" => Some("load effective address".into()),
"movzx" => Some("move with zero extension".into()),
"movsx" | "movsxd" => Some("move with sign extension".into()),
"push" => Some("push onto stack".into()),
"pop" => Some("pop from stack".into()),
"pusha" | "pushad" => Some("push all general-purpose registers".into()),
"popa" | "popad" => Some("pop all general-purpose registers".into()),
"pushf" | "pushfd" | "pushfq" => Some("push flags register".into()),
"popf" | "popfd" | "popfq" => Some("pop flags register".into()),
"leave" => Some("restore stack frame".into()),
"enter" => Some("create stack frame".into()),
"bswap" => Some("byte swap".into()),
"bsf" => Some("bit scan forward".into()),
"bsr" => Some("bit scan reverse".into()),
"bt" => Some("bit test".into()),
"bts" => Some("bit test and set".into()),
"btr" => Some("bit test and reset".into()),
"btc" => Some("bit test and complement".into()),
"movsb" => Some("move string byte".into()),
"movsw" | "movsd" => Some("move string word/dword".into()),
"stosb" => Some("store string byte".into()),
"stosw" | "stosd" => Some("store string word/dword".into()),
"lodsb" => Some("load string byte".into()),
"lodsw" | "lodsd" => Some("load string word/dword".into()),
"scasb" => Some("scan string byte".into()),
"scasw" | "scasd" => Some("scan string word/dword".into()),
"cmpsb" => Some("compare string byte".into()),
"cmpsw" | "cmpsd" => Some("compare string word/dword".into()),
"insb" => Some("input string from port byte".into()),
"insw" | "insd" => Some("input string from port word/dword".into()),
"outsb" => Some("output string to port byte".into()),
"outsw" | "outsd" => Some("output string to port word/dword".into()),
"in" => Some("input from port".into()),
"out" => Some("output to port".into()),
"clc" => Some("clear carry flag".into()),
"stc" => Some("set carry flag".into()),
"cmc" => Some("complement carry flag".into()),
"cld" => Some("clear direction flag".into()),
"std" => Some("set direction flag".into()),
"lahf" => Some("load flags into AH".into()),
"sahf" => Some("store AH into flags".into()),
"adc" => Some("add with carry".into()),
"sbb" => Some("subtract with borrow".into()),
"inc" => Some("increment by 1".into()),
"dec" => Some("decrement by 1".into()),
"daa" => Some("decimal adjust AL after addition".into()),
"das" => Some("decimal adjust AL after subtraction".into()),
"aaa" => Some("ASCII adjust after addition".into()),
"aas" => Some("ASCII adjust after subtraction".into()),
"aam" => Some("ASCII adjust after multiplication".into()),
"aad" => Some("ASCII adjust before division".into()),
"xlat" | "xlatb" => Some("translate byte (table lookup)".into()),
"cwde" | "cbw" | "cwd" | "cdq" | "cdqe" | "cqo" => Some("convert sign-extend".into()),
"aesenc" | "vaesenc" => Some("AES encrypt round".into()),
"aesdec" | "vaesdec" => Some("AES decrypt round".into()),
"aesenclast" | "vaesenclast" => Some("AES encrypt last round".into()),
"aesdeclast" | "vaesdeclast" => Some("AES decrypt last round".into()),
"aesimc" | "vaesimc" => Some("AES inverse mix columns".into()),
"aeskeygenassist" | "vaeskeygenassist" => Some("AES key generation assist".into()),
"pclmulqdq" | "vpclmulqdq" => Some("carry-less multiply quadword".into()),
"crc32" => Some("CRC-32 computation".into()),
"sha1nexte" => Some("SHA-1 schedule update".into()),
"sha1msg1" => Some("SHA-1 message schedule".into()),
"sha1msg2" => Some("SHA-1 message schedule part 2".into()),
"sha1rnds4" => Some("SHA-1 rounds with constant".into()),
"sha256rnds2" => Some("SHA-256 rounds".into()),
"sha256msg1" => Some("SHA-256 message schedule".into()),
"sha256msg2" => Some("SHA-256 message schedule part 2".into()),
"popcnt" => Some("population count".into()),
"lzcnt" => Some("count leading zeros".into()),
"tzcnt" => Some("count trailing zeros".into()),
"rdrand" => Some("read hardware random number".into()),
"rdseed" => Some("read hardware random seed".into()),
"adcx" => Some("unsigned add with carry".into()),
"adox" => Some("unsigned add with overflow".into()),
"movbe" => Some("move data after swapping bytes".into()),
"andn" => Some("bitwise AND NOT".into()),
"bextr" => Some("bit field extract".into()),
"blsi" => Some("extract lowest set isolated bit".into()),
"blsmsk" => Some("get mask up to lowest set bit".into()),
"blsr" => Some("reset lowest set bit".into()),
"bzhi" => Some("zero high bits starting at position".into()),
"mulx" => Some("unsigned multiply without affecting flags".into()),
"pdep" => Some("parallel bits deposit".into()),
"pext" => Some("parallel bits extract".into()),
"rorx" => Some("rotate right without affecting flags".into()),
"sarx" => Some("arithmetic shift right without affecting flags".into()),
"shlx" => Some("shift logical left without affecting flags".into()),
"shrx" => Some("shift logical right without affecting flags".into()),
"prefetch" | "prefetcht0" => Some("prefetch data into all cache levels".into()),
"prefetcht1" => Some("prefetch data into L1 cache".into()),
"prefetcht2" => Some("prefetch data into L2 cache".into()),
"prefetchnta" => Some("prefetch data into non-temporal cache".into()),
"prefetchw" => Some("prefetch with intent to write".into()),
"clflush" => Some("flush cache line".into()),
"clflushopt" => Some("optimized cache line flush".into()),
"clwb" => Some("cache line write back".into()),
"cldemote" => Some("cache line demote".into()),
"invlpg" => Some("invalidate TLB entry".into()),
"wbinvd" => Some("write back and invalidate cache".into()),
"invd" => Some("invalidate internal caches".into()),
"clts" => Some("clear task-switched flag in CR0".into()),
"movaps" | "vmovaps" => Some("move aligned packed singles".into()),
"movups" | "vmovups" => Some("move unaligned packed singles".into()),
"movdqa" | "vmovdqa" => Some("move aligned double quadword".into()),
"movdqu" | "vmovdqu" => Some("move unaligned double quadword".into()),
"movd" | "vmovd" => Some("move doubleword".into()),
"movq" | "vmovq" => Some("move quadword".into()),
"movntps" | "vmovntps" => Some("move non-temporal packed singles".into()),
"movntpd" | "vmovntpd" => Some("move non-temporal packed doubles".into()),
"movntdq" | "vmovntdq" => Some("move non-temporal double quadword".into()),
"movnti" => Some("move non-temporal integer".into()),
"movntdqa" | "vmovntdqa" => Some("load non-temporal aligned double quadword".into()),
"maskmovq" => Some("non-temporal byte mask store".into()),
"maskmovdqu" | "vmaskmovdqu" => Some("non-temporal byte mask store (SSE)".into()),
"addps" | "vaddps" => Some("add packed singles".into()),
"addpd" | "vaddpd" => Some("add packed doubles".into()),
"subps" | "vsubps" => Some("subtract packed singles".into()),
"subpd" | "vsubpd" => Some("subtract packed doubles".into()),
"mulps" | "vmulps" => Some("multiply packed singles".into()),
"mulpd" | "vmulpd" => Some("multiply packed doubles".into()),
"divps" | "vdivps" => Some("divide packed singles".into()),
"divpd" | "vdivpd" => Some("divide packed doubles".into()),
"sqrtps" | "vsqrtps" => Some("square root of packed singles".into()),
"sqrtpd" | "vsqrtpd" => Some("square root of packed doubles".into()),
"rsqrtps" | "vrsqrtps" => Some("reciprocal square root of packed singles".into()),
"rcpps" | "vrcpps" => Some("reciprocal of packed singles".into()),
"minps" | "vminps" => Some("minimum of packed singles".into()),
"maxps" | "vmaxps" => Some("maximum of packed singles".into()),
"minpd" | "vminpd" => Some("minimum of packed doubles".into()),
"maxpd" | "vmaxpd" => Some("maximum of packed doubles".into()),
"andps" | "vandps" => Some("bitwise AND of packed singles".into()),
"andnps" | "vandnps" => Some("bitwise AND NOT of packed singles".into()),
"orps" | "vorps" => Some("bitwise OR of packed singles".into()),
"xorps" | "vxorps" => Some("bitwise XOR of packed singles".into()),
"andpd" | "vandpd" => Some("bitwise AND of packed doubles".into()),
"andnpd" | "vandnpd" => Some("bitwise AND NOT of packed doubles".into()),
"orpd" | "vorpd" => Some("bitwise OR of packed doubles".into()),
"xorpd" | "vxorpd" => Some("bitwise XOR of packed doubles".into()),
"unpcklps" | "vunpcklps" => Some("unpack low packed singles".into()),
"unpckhps" | "vunpckhps" => Some("unpack high packed singles".into()),
"unpcklpd" | "vunpcklpd" => Some("unpack low packed doubles".into()),
"unpckhpd" | "vunpckhpd" => Some("unpack high packed doubles".into()),
"shufps" | "vshufps" => Some("shuffle packed singles".into()),
"shufpd" | "vshufpd" => Some("shuffle packed doubles".into()),
"cmpps" | "vcmpps" => Some("compare packed singles".into()),
"cmppd" | "vcmppd" => Some("compare packed doubles".into()),
"cmpss" | "vcmpss" => Some("compare scalar single".into()),
"cmpsd" | "vcmpsd" => Some("compare scalar double".into()),
"comiss" | "vcomiss" => Some("compare ordered scalar single".into()),
"ucomiss" | "vucomiss" => Some("unordered compare scalar single".into()),
"comisd" | "vcomisd" => Some("compare ordered scalar double".into()),
"ucomisd" | "vucomisd" => Some("unordered compare scalar double".into()),
"cvtps2pd" | "vcvtps2pd" => Some("convert packed singles to packed doubles".into()),
"cvtpd2ps" | "vcvtpd2ps" => Some("convert packed doubles to packed singles".into()),
"cvtdq2ps" | "vcvtdq2ps" => Some("convert packed integers to packed singles".into()),
"cvtps2dq" | "vcvtps2dq" => Some("convert packed singles to packed integers".into()),
"cvttps2dq" | "vcvttps2dq" => {
Some("convert with truncation packed singles to ints".into())
}
"cvttpd2dq" | "vcvttpd2dq" => {
Some("convert with truncation packed doubles to ints".into())
}
"cvtpd2dq" | "vcvtpd2dq" => Some("convert packed doubles to packed integers".into()),
"cvtss2si" | "vcvtss2si" => Some("convert scalar single to integer".into()),
"cvtsd2si" | "vcvtsd2si" => Some("convert scalar double to integer".into()),
"cvtsi2ss" | "vcvtsi2ss" => Some("convert integer to scalar single".into()),
"cvtsi2sd" | "vcvtsi2sd" => Some("convert integer to scalar double".into()),
"cvttss2si" | "vcvttss2si" => {
Some("convert with truncation scalar single to int".into())
}
"cvttsd2si" | "vcvttsd2si" => {
Some("convert with truncation scalar double to int".into())
}
"movmskps" | "vmovmskps" => Some("extract packed single sign mask".into()),
"movmskpd" | "vmovmskpd" => Some("extract packed double sign mask".into()),
"pmovmskb" | "vpmovmskb" => Some("extract byte mask".into()),
"paddb" | "vpaddb" => Some("add packed bytes".into()),
"paddw" | "vpaddw" => Some("add packed words".into()),
"paddd" | "vpaddd" => Some("add packed doublewords".into()),
"paddq" | "vpaddq" => Some("add packed quadwords".into()),
"psubb" | "vpsubb" => Some("subtract packed bytes".into()),
"psubw" | "vpsubw" => Some("subtract packed words".into()),
"psubd" | "vpsubd" => Some("subtract packed doublewords".into()),
"psubq" | "vpsubq" => Some("subtract packed quadwords".into()),
"psllw" | "vpsllw" => Some("shift left logical packed words".into()),
"pslld" | "vpslld" => Some("shift left logical packed doublewords".into()),
"psllq" | "vpsllq" => Some("shift left logical packed quadwords".into()),
"psrlw" | "vpsrlw" => Some("shift right logical packed words".into()),
"psrld" | "vpsrld" => Some("shift right logical packed doublewords".into()),
"psrlq" | "vpsrlq" => Some("shift right logical packed quadwords".into()),
"psraw" | "vpsraw" => Some("shift right arithmetic packed words".into()),
"psrad" | "vpsrad" => Some("shift right arithmetic packed doublewords".into()),
"pand" | "vpand" => Some("bitwise AND of packed integers".into()),
"pandn" | "vpandn" => Some("bitwise AND NOT of packed integers".into()),
"por" | "vpor" => Some("bitwise OR of packed integers".into()),
"pxor" | "vpxor" => Some("bitwise XOR of packed integers".into()),
"fmadd132ps" | "vfmadd132ps" => {
Some("fused multiply-add packed singles (1-3-2)".into())
}
"fmadd213ps" | "vfmadd213ps" => {
Some("fused multiply-add packed singles (2-1-3)".into())
}
"fmadd231ps" | "vfmadd231ps" => {
Some("fused multiply-add packed singles (2-3-1)".into())
}
"fmadd132pd" | "vfmadd132pd" => {
Some("fused multiply-add packed doubles (1-3-2)".into())
}
"fmadd213pd" | "vfmadd213pd" => {
Some("fused multiply-add packed doubles (2-1-3)".into())
}
"fmadd231pd" | "vfmadd231pd" => {
Some("fused multiply-add packed doubles (2-3-1)".into())
}
"tileloadd" => Some("load AMX tile (data)".into()),
"tilestored" => Some("store AMX tile (data)".into()),
"tilezero" => Some("zero AMX tile".into()),
"tdpbf16ps" => Some("AMX dot-product BF16 to single".into()),
"tdpbssd" => Some("AMX dot-product signed byte to dword".into()),
"tdpbusd" => Some("AMX dot-product unsigned byte to dword".into()),
"tdpbuud" => Some("AMX dot-product unsigned byte to unsigned dword".into()),
"tilerelease" => Some("release AMX tile configuration".into()),
"emms" => Some("empty MMX state".into()),
"femms" => Some("fast empty MMX state (3DNow!)".into()),
"vmptrld" => Some("load VMCS pointer".into()),
"vmptrst" => Some("store VMCS pointer".into()),
"vmclear" => Some("clear VMCS".into()),
"vmlaunch" => Some("launch virtual machine".into()),
"vmresume" => Some("resume virtual machine".into()),
"vmread" => Some("read VMCS field".into()),
"vmwrite" => Some("write VMCS field".into()),
"vmxoff" => Some("leave VMX operation".into()),
"vmxon" => Some("enter VMX operation".into()),
"invept" => Some("invalidate EPT-derived translations".into()),
"invvpid" => Some("invalidate VPID-tagged translations".into()),
"getsec" => Some("get SMX capabilities".into()),
"xgetbv" => Some("get extended control register".into()),
"xsetbv" => Some("set extended control register".into()),
"xsave" => Some("save processor extended states".into()),
"xrstor" => Some("restore processor extended states".into()),
"xsavec" => Some("save processor extended states (compacted)".into()),
"xsaves" => Some("save processor extended states (supervisor)".into()),
"xrstors" => Some("restore processor extended states (supervisor)".into()),
"xadd" => Some("exchange and add".into()),
"bound" => Some("check array index against bounds".into()),
"lsl" => Some("load segment limit".into()),
"lar" => Some("load access rights byte".into()),
"lar" => Some("load access rights".into()),
"verr" => Some("verify segment for reading".into()),
"verw" => Some("verify segment for writing".into()),
"sgdt" => Some("store global descriptor table".into()),
"sidt" => Some("store interrupt descriptor table".into()),
"lgdt" => Some("load global descriptor table".into()),
"lidt" => Some("load interrupt descriptor table".into()),
"smsw" => Some("store machine status word".into()),
"lmsw" => Some("load machine status word".into()),
"sldt" => Some("store local descriptor table".into()),
"str" => Some("store task register".into()),
"lldt" => Some("load local descriptor table".into()),
"ltr" => Some("load task register".into()),
m if m.starts_with("cmov") => Some("conditional move".into()),
m if m.starts_with("set") && m.len() > 3 => Some("conditional set byte".into()),
m if m.starts_with('j') && m.len() <= 4 => Some("conditional jump".into()),
m if m.starts_with('v') && m.contains("gather") => Some("vector gather".into()),
m if m.starts_with('v') && m.contains("scatter") => Some("vector scatter".into()),
m if m.starts_with('v') && m.contains("perm") => Some("vector permute".into()),
m if m.starts_with('v') && m.contains("broadcast") => Some("vector broadcast".into()),
m if m.starts_with('v') && m.contains("insert") => Some("vector insert".into()),
m if m.starts_with('v') && m.contains("extract") => Some("vector extract".into()),
m if m.starts_with('v') && m.contains("blend") => Some("vector blend".into()),
_ if inst.mnemonic.starts_with('v') => Some("vector instruction".into()),
_ if inst.attributes.is_sse => Some("SSE instruction".into()),
_ if inst.attributes.is_avx => Some("AVX instruction".into()),
_ if inst.attributes.is_avx512 => Some("AVX-512 instruction".into()),
_ if inst.attributes.is_privileged => Some("privileged instruction".into()),
_ => None,
}
}
}
impl Default for X86InstructionAnnotator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_disassembler(mode: McProcessorMode) -> X86MCDisassemblerFull {
X86MCDisassemblerFull::new(mode)
}
fn make_disassembler64() -> X86MCDisassemblerFull {
X86MCDisassemblerFull::new(McProcessorMode::Mode64)
}
fn make_disassembler32() -> X86MCDisassemblerFull {
X86MCDisassemblerFull::new(McProcessorMode::Mode32)
}
fn make_decoder(mode: McProcessorMode) -> X86InstructionDecoder {
X86InstructionDecoder::new(mode)
}
#[test]
fn test_decode_nop() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x90]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "nop");
}
#[test]
fn test_decode_ret() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xC3]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "ret");
}
#[test]
fn test_decode_push_rax() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x50]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "push");
}
#[test]
fn test_decode_pop_rax() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x58]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "pop");
}
#[test]
fn test_decode_mov_rax_rcx() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x89, 0xC8]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "mov");
}
#[test]
fn test_decode_add_rax_rcx() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x01, 0xC8]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "add");
}
#[test]
fn test_decode_add_rax_imm5() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x83, 0xC0, 0x05]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "add");
}
#[test]
fn test_decode_sub_rax_rdx() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x29, 0xD0]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "sub");
}
#[test]
fn test_decode_xor_rax_rax() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x31, 0xC0]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "xor");
}
#[test]
fn test_decode_cmp_rax_rcx() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x39, 0xC8]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "cmp");
}
#[test]
fn test_decode_jmp_rel8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xEB, 0x04]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("jmp"));
}
#[test]
fn test_decode_call_rel32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xE8, 0x00, 0x00, 0x00, 0x00]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("call"));
}
#[test]
fn test_decode_je_rel8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x74, 0x04]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("je"));
}
#[test]
fn test_decode_jne_rel8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x75, 0xFB]);
assert!(inst.is_some());
}
#[test]
fn test_decode_mov_rax_imm64() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst =
decoder.decode_one(&[0x48, 0xB8, 0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("mov"));
}
#[test]
fn test_decode_mov_eax_imm32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xB8, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("mov"));
}
#[test]
fn test_decode_lea() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x8D, 0x04, 0x51]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("lea"));
}
#[test]
fn test_decode_lock_prefix() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xF0, 0x83, 0x00, 0x01]);
assert!(inst.is_some());
assert!(inst.unwrap().attributes.has_lock_prefix);
}
#[test]
fn test_decode_rep_prefix() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xF3, 0xA4]);
assert!(inst.is_some());
}
#[test]
fn test_decode_operand_size_override() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x66, 0x90]);
assert!(inst.is_some());
}
#[test]
fn test_decode_segment_override_fs() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x64, 0x8B, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_decode_modrm_register_mode() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x89, 0xC8]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "mov");
}
#[test]
fn test_decode_modrm_memory_disp8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x41, 0x08]);
assert!(inst.is_some());
}
#[test]
fn test_decode_modrm_memory_disp32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x81, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
}
#[test]
fn test_decode_sib_base_index_scale() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x8B, 0x04, 0xD1]);
assert!(inst.is_some());
}
#[test]
fn test_decode_sib_disp32_no_base() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x04, 0x95, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
}
#[test]
fn test_decode_rip_relative() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
decoder.set_base_address(0x1000);
let inst = decoder.decode_one(&[0x48, 0x8D, 0x05, 0x00, 0x01, 0x00, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_decode_rex_present() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x4D, 0x89, 0xC8]);
assert!(inst.is_some());
assert!(inst.unwrap().rex.is_some());
}
#[test]
fn test_decode_rex_not_present() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x89, 0xC8]);
assert!(inst.is_some());
assert!(inst.unwrap().rex.is_none());
}
#[test]
fn test_decode_rex_32bit_mode() {
let mut decoder = make_decoder(McProcessorMode::Mode32);
let inst = decoder.decode_one(&[0x40]);
assert!(inst.is_some());
assert!(inst.unwrap().rex.is_none());
}
#[test]
fn test_decode_cmove() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x44, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("cmov"));
}
#[test]
fn test_decode_bswap() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x0F, 0xC8]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("bswap"));
}
#[test]
fn test_decode_cpuid() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0xA2]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "cpuid");
}
#[test]
fn test_decode_syscall() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x05]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "syscall");
}
#[test]
fn test_decode_sete() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x94, 0xC0]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("set"));
}
#[test]
fn test_decode_movzx_rm8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0xB6, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("movzx"));
}
#[test]
fn test_decode_movsx_rm8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0xBE, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("movsx"));
}
#[test]
fn test_decode_imul_reg_rm() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x0F, 0xAF, 0xC1]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "imul");
}
#[test]
fn test_decode_movaps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x28, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("movaps"));
}
#[test]
fn test_decode_addps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x58, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("addps"));
}
#[test]
fn test_decode_mulps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x59, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("mulps"));
}
#[test]
fn test_decode_movdqa() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x66, 0x0F, 0x6F, 0xC1]);
assert!(inst.is_some());
}
#[test]
fn test_decode_group1_add_imm8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x83, 0xC0, 0x01]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("add"));
}
#[test]
fn test_decode_group3_not() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0xF7, 0xD0]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("not"));
}
#[test]
fn test_decode_group3_neg() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0xF7, 0xD8]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("neg"));
}
#[test]
fn test_decode_group5_push() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xFF, 0xF0]);
assert!(inst.is_some());
}
#[test]
fn test_decode_group2_shl_by_cl() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xD3, 0xE0]);
assert!(inst.is_some());
}
#[test]
fn test_decode_vex_2byte_vxorps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xC5, 0xF0, 0x57, 0xC2]);
assert!(inst.is_some());
}
#[test]
fn test_decode_vex_3byte_vaddps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xC5, 0xF4, 0x58, 0xC2]);
assert!(inst.is_some());
}
#[test]
fn test_decode_empty_bytes() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
assert!(decoder.decode_one(&[]).is_none());
}
#[test]
fn test_decode_incomplete_0f() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
assert!(decoder.decode_one(&[0x0F]).is_none());
}
#[test]
fn test_decode_unknown_byte() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xF1]);
assert!(inst.is_some());
}
#[test]
fn test_disassemble_one_nop() {
let mut dis = make_disassembler64();
let result = dis.disassemble_one(&[0x90]);
assert!(result.is_some());
assert!(result.unwrap().contains("nop"));
}
#[test]
fn test_disassemble_one_ret() {
let mut dis = make_disassembler64();
let result = dis.disassemble_one(&[0xC3]);
assert!(result.is_some());
assert!(result.unwrap().contains("ret"));
}
#[test]
fn test_disassemble_all_multiple() {
let mut dis = make_disassembler64();
let results = dis.disassemble_all(&[0x90, 0x90, 0xC3]);
assert_eq!(results.len(), 3);
}
#[test]
fn test_format_intel_mov_reg_reg() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x89, 0xC8]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[0x48, 0x89, 0xC8]).unwrap();
assert!(result.contains("mov"));
assert!(result.contains("rcx"));
assert!(result.contains("rax"));
}
#[test]
fn test_format_att_mov_reg_reg() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x89, 0xC8]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Att);
let result = formatter.format(&inst, false, &[0x48, 0x89, 0xC8]).unwrap();
assert!(result.contains("mov"));
assert!(result.contains("%rcx"));
assert!(result.contains("%rax"));
}
#[test]
fn test_format_memory_operand_intel() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x41, 0x08]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[0x8B, 0x41, 0x08]).unwrap();
assert!(result.contains("["));
}
#[test]
fn test_format_memory_operand_att() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x41, 0x08]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Att);
let result = formatter.format(&inst, false, &[0x8B, 0x41, 0x08]).unwrap();
assert!(result.contains("(%rcx)"));
}
#[test]
fn test_format_rip_relative_intel() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
decoder.set_base_address(0x1000);
let inst = decoder
.decode_one(&[0x48, 0x8D, 0x05, 0x00, 0x01, 0x00, 0x00])
.unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter
.format(&inst, false, &[0x48, 0x8D, 0x05, 0x00, 0x01, 0x00, 0x00])
.unwrap();
assert!(result.contains("rip"));
}
#[test]
fn test_format_show_bytes() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x90]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, true, &[0x90]).unwrap();
assert!(result.contains("90"));
assert!(result.contains("nop"));
}
#[test]
fn test_mode_64bit() {
let dis = make_disassembler64();
assert!(dis.mode.is_64bit());
}
#[test]
fn test_mode_32bit() {
let dis = make_disassembler32();
assert!(!dis.mode.is_64bit());
}
#[test]
fn test_mode_16bit() {
let dis = make_disassembler(McProcessorMode::Mode16);
assert_eq!(dis.mode.default_operand_size(), 16);
assert_eq!(dis.mode.default_address_size(), 16);
}
#[test]
fn test_gpr64_names() {
assert_eq!(McX86Reg::RAX.name(), "rax");
assert_eq!(McX86Reg::R15.name(), "r15");
}
#[test]
fn test_gpr32_names() {
assert_eq!(McX86Reg::EAX.name(), "eax");
assert_eq!(McX86Reg::R15D.name(), "r15d");
}
#[test]
fn test_gpr16_names() {
assert_eq!(McX86Reg::AX.name(), "ax");
assert_eq!(McX86Reg::R15W.name(), "r15w");
}
#[test]
fn test_xmm_names() {
assert_eq!(McX86Reg::XMM0.name(), "xmm0");
assert_eq!(McX86Reg::XMM15.name(), "xmm15");
}
#[test]
fn test_ymm_names() {
assert_eq!(McX86Reg::YMM0.name(), "ymm0");
assert_eq!(McX86Reg::YMM15.name(), "ymm15");
}
#[test]
fn test_zmm_names() {
assert_eq!(McX86Reg::ZMM0.name(), "zmm0");
assert_eq!(McX86Reg::ZMM31.name(), "zmm31");
}
#[test]
fn test_register_class() {
assert_eq!(McX86Reg::RAX.class(), McRegClass::GPR64);
assert_eq!(McX86Reg::XMM0.class(), McRegClass::XMM);
assert_eq!(McX86Reg::K0.class(), McRegClass::Opmask);
assert_eq!(McX86Reg::ST0.class(), McRegClass::FPU);
}
#[test]
fn test_register_size_suffix() {
assert_eq!(McX86Reg::AL.size_suffix(), "b");
assert_eq!(McX86Reg::EAX.size_suffix(), "l");
assert_eq!(McX86Reg::RAX.size_suffix(), "q");
assert_eq!(McX86Reg::XMM0.size_suffix(), "x");
}
#[test]
fn test_size_hint_att_suffix() {
assert_eq!(McSizeHint::Byte.att_suffix(), "b");
assert_eq!(McSizeHint::Dword.att_suffix(), "l");
assert_eq!(McSizeHint::Qword.att_suffix(), "q");
assert_eq!(McSizeHint::Oword.att_suffix(), "x");
assert_eq!(McSizeHint::Zword.att_suffix(), "z");
}
#[test]
fn test_size_hint_intel_prefix() {
assert_eq!(McSizeHint::Byte.intel_prefix(), "byte ptr ");
assert_eq!(McSizeHint::Dword.intel_prefix(), "dword ptr ");
assert_eq!(McSizeHint::Qword.intel_prefix(), "qword ptr ");
assert_eq!(McSizeHint::Zword.intel_prefix(), "zmmword ptr ");
}
#[test]
fn test_legacy_prefix_default() {
let p = McLegacyPrefixes::default();
assert!(!p.has_lock);
assert!(!p.has_rep);
assert!(!p.has_repne);
}
#[test]
fn test_instruction_attributes_default() {
let a = McInstrAttributes::default();
assert!(!a.is_branch);
assert!(!a.is_privileged);
}
#[test]
fn test_modrm_decode_reg_direct() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x89, 0xC8]);
assert!(inst.is_some());
}
#[test]
fn test_modrm_decode_mem_disp8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x41, 0x08]);
assert!(inst.is_some());
}
#[test]
fn test_sib_decode() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x8B, 0x04, 0x51]);
assert!(inst.is_some());
}
#[test]
fn test_segment_override_names() {
assert_eq!(McSegmentOverride::CS.name(), "cs");
assert_eq!(McSegmentOverride::FS.name(), "fs");
assert_eq!(McSegmentOverride::GS.name(), "gs");
}
#[test]
fn test_vex_info_default() {
let v = McVexInfo::default();
assert!(!v.present);
assert!(!v.is_3byte);
}
#[test]
fn test_evex_info_default() {
let e = McEvexInfo::default();
assert!(!e.present);
assert_eq!(e.aaa, 0);
}
#[test]
fn test_syntax_equality() {
assert_ne!(McDisasmSyntax::Att, McDisasmSyntax::Intel);
}
#[test]
fn test_format_opmask_register() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x90]);
let op = McDecodedOperand::OpmaskRegister {
reg: McX86Reg::K1,
zeroing: true,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format_operand_intel(
&op,
&McDecodedInstruction {
mnemonic: "test".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![],
size: 0,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes::default(),
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
},
);
assert!(result.contains("{z}"));
}
#[test]
fn test_primary_table_not_empty() {
assert!(!primary_opcode_table().is_empty());
}
#[test]
fn test_0f_table_not_empty() {
assert!(!opcode_table_0f().is_empty());
}
#[test]
fn test_0f38_table_not_empty() {
assert!(!opcode_table_0f38().is_empty());
}
#[test]
fn test_0f3a_table_not_empty() {
assert!(!opcode_table_0f3a().is_empty());
}
#[test]
fn test_vex_tables_not_empty() {
assert!(!vex_opcode_table_1().is_empty());
assert!(!vex_opcode_table_2().is_empty());
}
#[test]
fn test_evex_tables_have_entries() {
assert!(!evex_opcode_table_1().is_empty());
assert!(!evex_opcode_table_5().is_empty());
}
#[test]
fn test_decode_int3() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xCC]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "int3");
}
#[test]
fn test_decode_leave() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xC9]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "leave");
}
#[test]
fn test_decode_hlt() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xF4]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "hlt");
}
#[test]
fn test_decode_ud2() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x0F, 0x0B]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "ud2");
}
#[test]
fn test_decode_mov_imm32_to_mem() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xC7, 0x00, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
}
#[test]
fn test_disassembler_with_address() {
let dis = make_disassembler64().with_address(0x400000);
assert_eq!(dis.base_address, 0x400000);
}
#[test]
fn test_disassembler_with_syntax() {
let dis = make_disassembler64().with_syntax(McDisasmSyntax::Att);
assert_eq!(dis.syntax, McDisasmSyntax::Att);
}
#[test]
fn test_disassembler_set_mode() {
let mut dis = make_disassembler64();
dis.set_mode(McProcessorMode::Mode32);
assert!(!dis.mode.is_64bit());
}
#[test]
fn test_disassembler_set_base_address() {
let mut dis = make_disassembler64();
dis.set_base_address(0x8000);
assert_eq!(dis.base_address, 0x8000);
}
#[test]
fn test_decode_x87_fld() {
let mut decoder = make_decoder(McProcessorMode::Mode32);
let inst = decoder.decode_one(&[0xD9, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_decode_0f38_pshufb() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x66, 0x0F, 0x38, 0x00, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("pshufb"));
}
#[test]
fn test_decode_0f3a_roundps() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x66, 0x0F, 0x3A, 0x08, 0xC1, 0x00]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("roundps"));
}
#[test]
fn test_decode_aesenc() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x66, 0x0F, 0x38, 0xDC, 0xC1]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("aesenc"));
}
#[test]
fn test_evex_table_5_has_amx() {
let table = evex_opcode_table_5();
assert!(!table.is_empty());
let has_amx = table.iter().any(|e| e.feature_required == FeatureSet::AMX);
assert!(has_amx);
}
#[test]
fn test_format_immediate_hex() {
let op = McDecodedOperand::Immediate {
value: 0xFF,
size: 1,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let inst = McDecodedInstruction {
mnemonic: "test".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![],
size: 0,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes::default(),
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
};
let result = formatter.format_operand_intel(&op, &inst);
assert!(result.contains("0xff"));
}
#[test]
fn test_format_immediate_negative() {
let op = McDecodedOperand::Immediate { value: -1, size: 1 };
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let inst = McDecodedInstruction {
mnemonic: "test".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![],
size: 0,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes::default(),
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
};
let result = formatter.format_operand_intel(&op, &inst);
assert!(result.contains("-0x1"));
}
#[test]
fn test_annotated_output() {
let inst = McDecodedInstruction {
mnemonic: "nop".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![],
size: 1,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes::default(),
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
};
let annotator = X86InstructionAnnotator::new();
let purpose = annotator.instruction_purpose(&inst);
assert_eq!(purpose, Some("no operation".into()));
}
#[test]
fn test_relative_offset_target() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
decoder.set_base_address(0x1000);
let inst = decoder.decode_one(&[0x74, 0x04]).unwrap();
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[0x74, 0x04]).unwrap();
assert!(result.contains("0x1006"));
}
#[test]
fn test_decode_32bit_inc() {
let mut decoder = make_decoder(McProcessorMode::Mode32);
let inst = decoder.decode_one(&[0x40]);
assert!(inst.is_some());
assert!(inst.unwrap().mnemonic.contains("inc"));
}
#[test]
fn test_decoded_operand_constructors() {
let reg_op = McDecodedOperand::Register {
reg: McX86Reg::RAX,
size_hint: McSizeHint::Qword,
};
assert!(matches!(reg_op, McDecodedOperand::Register { .. }));
let imm_op = McDecodedOperand::Immediate { value: 42, size: 4 };
assert!(matches!(imm_op, McDecodedOperand::Immediate { .. }));
let mem_op = McDecodedOperand::Memory {
segment: None,
base: Some(McX86Reg::RAX),
index: None,
displacement: 0,
size_hint: McSizeHint::Dword,
rip_relative: false,
};
assert!(matches!(mem_op, McDecodedOperand::Memory { .. }));
}
#[test]
fn test_feature_set_variants() {
assert_eq!(FeatureSet::Base, FeatureSet::Base);
assert_ne!(FeatureSet::Base, FeatureSet::AVX);
assert_ne!(FeatureSet::AVX, FeatureSet::AVX2);
assert_ne!(FeatureSet::AVX512F, FeatureSet::AMX);
}
#[test]
fn test_opcode_map_variants() {
assert_ne!(McOpcodeMap::Primary, McOpcodeMap::Map0F);
assert_ne!(McOpcodeMap::VexMap1, McOpcodeMap::EvexMap1);
assert_ne!(McOpcodeMap::XopMap8, McOpcodeMap::XopMap9);
}
#[test]
fn test_encoding_form_variants() {
assert_ne!(McEncodingForm::Implicit, McEncodingForm::RegOnly);
assert_ne!(McEncodingForm::RegRM, McEncodingForm::RmReg);
assert_ne!(McEncodingForm::RelBranch, McEncodingForm::AccumImm);
}
#[test]
fn test_decode_16bit_nop() {
let mut decoder = make_decoder(McProcessorMode::Mode16);
let inst = decoder.decode_one(&[0x90]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "nop");
}
#[test]
fn test_annotate_with_symbol() {
let inst = McDecodedInstruction {
mnemonic: "call".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![McDecodedOperand::RelativeOffset {
offset: 16,
size: 4,
}],
size: 5,
address: 0x1000,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes {
is_call: true,
..Default::default()
},
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
};
let mut symbols = BTreeMap::new();
symbols.insert(0x1015, "my_function".to_string());
let annotator = X86InstructionAnnotator::new();
let comment = annotator.annotate(&inst, &symbols);
assert!(comment.contains("my_function"));
}
#[test]
fn test_group1_mnemonics() {
assert_eq!(mc_group1_mnemonic(0), Some("add"));
assert_eq!(mc_group1_mnemonic(7), Some("cmp"));
assert_eq!(mc_group1_mnemonic(8), None);
}
#[test]
fn test_group2_mnemonics() {
assert_eq!(mc_group2_mnemonic(4), Some("shl"));
assert_eq!(mc_group2_mnemonic(5), Some("shr"));
}
#[test]
fn test_xop_table_8_not_empty() {
assert!(!xop_opcode_table_8().is_empty());
}
#[test]
fn test_format_evex_opmask() {
let inst = McDecodedInstruction {
mnemonic: "vaddps".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::OpmaskRegister {
reg: McX86Reg::K1,
zeroing: false,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM0,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM1,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM2,
size_hint: McSizeHint::Zword,
},
],
size: 6,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo {
present: true,
aaa: 1,
z: false,
..Default::default()
}),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_opmask: true,
..Default::default()
},
opcode_extension: None,
operand_size: 64,
address_size: 64,
vector_length: 512,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{k1}"));
assert!(result.contains("zmm"));
}
#[test]
fn test_format_broadcast_decorator() {
let inst = McDecodedInstruction {
mnemonic: "vaddps".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::Register {
reg: McX86Reg::ZMM0,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM1,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Memory {
segment: None,
base: Some(McX86Reg::RAX),
index: None,
displacement: 0,
size_hint: McSizeHint::Zword,
rip_relative: false,
},
],
size: 6,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo {
present: true,
b_bit: true,
..Default::default()
}),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_broadcast: true,
..Default::default()
},
opcode_extension: None,
operand_size: 64,
address_size: 64,
vector_length: 512,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{1toX}"));
}
#[test]
fn test_format_rounding_rn() {
let inst = McDecodedInstruction {
mnemonic: "vaddss".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::Register {
reg: McX86Reg::XMM0,
size_hint: McSizeHint::Oword,
},
McDecodedOperand::Register {
reg: McX86Reg::XMM1,
size_hint: McSizeHint::Oword,
},
McDecodedOperand::Register {
reg: McX86Reg::XMM2,
size_hint: McSizeHint::Oword,
},
],
size: 6,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo {
present: true,
ll: 0,
..Default::default()
}),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_er: true,
..Default::default()
},
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 128,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{rn-sae}"));
}
#[test]
fn test_format_rounding_rd() {
let inst = McDecodedInstruction {
mnemonic: "vaddss".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::Register {
reg: McX86Reg::XMM0,
size_hint: McSizeHint::Oword,
},
McDecodedOperand::Register {
reg: McX86Reg::XMM1,
size_hint: McSizeHint::Oword,
},
McDecodedOperand::Register {
reg: McX86Reg::XMM2,
size_hint: McSizeHint::Oword,
},
],
size: 6,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo {
present: true,
ll: 1,
..Default::default()
}),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_er: true,
..Default::default()
},
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 128,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{rd-sae}"));
}
#[test]
fn test_format_zeroing() {
let inst = McDecodedInstruction {
mnemonic: "vaddps".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::OpmaskRegister {
reg: McX86Reg::K2,
zeroing: true,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM0,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM1,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM2,
size_hint: McSizeHint::Zword,
},
],
size: 6,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo {
present: true,
aaa: 2,
z: true,
..Default::default()
}),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_opmask: true,
uses_zeroing: true,
..Default::default()
},
opcode_extension: None,
operand_size: 64,
address_size: 64,
vector_length: 512,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{k2}"));
assert!(result.contains("{z}"));
}
#[test]
fn test_format_sae() {
let inst = McDecodedInstruction {
mnemonic: "vcmpps".into(),
opcode: 0,
opcode_map: McOpcodeMap::EvexMap1,
operands: vec![
McDecodedOperand::Register {
reg: McX86Reg::K0,
size_hint: McSizeHint::None,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM0,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Register {
reg: McX86Reg::ZMM1,
size_hint: McSizeHint::Zword,
},
McDecodedOperand::Immediate { value: 0, size: 1 },
],
size: 7,
address: 0,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: Some(McEvexInfo::default()),
implicit_operands: vec![],
attributes: McInstrAttributes {
is_avx512: true,
uses_sae: true,
..Default::default()
},
opcode_extension: None,
operand_size: 64,
address_size: 64,
vector_length: 512,
};
let formatter = X86OperandFormatter::new(McDisasmSyntax::Intel);
let result = formatter.format(&inst, false, &[]).unwrap();
assert!(result.contains("{sae}"));
}
#[test]
fn test_roundtrip_nop() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x90]).unwrap();
assert_eq!(inst.size, 1);
assert_eq!(inst.mnemonic, "nop");
}
#[test]
fn test_roundtrip_push_rbp() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x55]).unwrap();
assert_eq!(inst.size, 1);
assert_eq!(inst.mnemonic, "push");
}
#[test]
fn test_roundtrip_mov_eax_imm32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xB8, 0x78, 0x56, 0x34, 0x12]).unwrap();
assert_eq!(inst.size, 5);
assert_eq!(inst.mnemonic, "mov");
}
#[test]
fn test_decoder_mode_switching() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
assert!(decoder.mode.is_64bit());
decoder.set_mode(McProcessorMode::Mode32);
assert!(!decoder.mode.is_64bit());
}
#[test]
fn test_decoder_address_update() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
decoder.set_base_address(0x400000);
assert_eq!(decoder.base_address, 0x400000);
}
#[test]
fn test_legacy_prefix_reset_between_decodes() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let _ = decoder.decode_one(&[0xF0, 0x83, 0x00, 0x01]);
let inst2 = decoder.decode_one(&[0x83, 0x00, 0x01]).unwrap();
assert!(!inst2.attributes.has_lock_prefix);
}
#[test]
fn test_rex_reset_between_decodes() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let _ = decoder.decode_one(&[0x48, 0x89, 0xC8]);
let inst2 = decoder.decode_one(&[0x89, 0xC8]).unwrap();
assert!(inst2.rex.is_none());
}
#[test]
fn test_16bit_addr_bx_si() {
let mut decoder = make_decoder(McProcessorMode::Mode16);
let inst = decoder.decode_one(&[0x67, 0x8B, 0x00]);
decoder.set_mode(McProcessorMode::Mode16);
let inst = decoder.decode_one(&[0x8B, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_accumulator_64bit() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x48, 0x05, 0x05, 0x00, 0x00, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_accumulator_32bit() {
let mut decoder = make_decoder(McProcessorMode::Mode32);
let inst = decoder.decode_one(&[0x05, 0x05, 0x00, 0x00, 0x00]);
assert!(inst.is_some());
}
#[test]
fn test_disp8_positive() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x40, 0x10]);
assert!(inst.is_some());
}
#[test]
fn test_disp8_negative() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x40, 0xF0]);
assert!(inst.is_some());
}
#[test]
fn test_disp32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x8B, 0x80, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
}
#[test]
fn test_imm8() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x04, 0x7F]);
assert!(inst.is_some());
}
#[test]
fn test_imm32() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x05, 0x78, 0x56, 0x34, 0x12]);
assert!(inst.is_some());
}
#[test]
fn test_decode_movsb() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xA4]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "movsb");
}
#[test]
fn test_decode_stosb() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xAA]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "stosb");
}
#[test]
fn test_decode_lodsb() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xAC]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "lodsb");
}
#[test]
fn test_decode_pushfq() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x9C]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "pushf");
}
#[test]
fn test_decode_popfq() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x9D]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "popf");
}
#[test]
fn test_decode_lahf() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0x9F]);
assert!(inst.is_some());
assert_eq!(inst.unwrap().mnemonic, "lahf");
}
#[test]
fn test_decode_fninit() {
let mut decoder = make_decoder(McProcessorMode::Mode64);
let inst = decoder.decode_one(&[0xDB, 0xE3]);
assert!(inst.is_some());
}
#[test]
fn test_3dnow_table_not_empty() {
assert!(!threednow_opcode_table().is_empty());
}
#[test]
fn test_3dnow_has_instructions() {
let table = threednow_opcode_table();
assert!(table.iter().any(|e| e.mnemonic == "pfadd"));
assert!(table.iter().any(|e| e.mnemonic == "pfmul"));
}
#[test]
fn test_xop_table_9_not_empty() {
assert!(!xop_opcode_table_9().is_empty());
}
#[test]
fn test_xop_table_a_not_empty() {
assert!(!xop_opcode_table_a().is_empty());
}
#[test]
fn test_all_feature_sets() {
let sets = [
FeatureSet::Base,
FeatureSet::I486,
FeatureSet::Pentium,
FeatureSet::P6,
FeatureSet::MMX,
FeatureSet::SSE,
FeatureSet::SSE2,
FeatureSet::SSE3,
FeatureSet::SSSE3,
FeatureSet::SSE41,
FeatureSet::SSE42,
FeatureSet::AVX,
FeatureSet::AVX2,
FeatureSet::AVX512F,
FeatureSet::AVX512BW,
FeatureSet::AVX512DQ,
FeatureSet::FMA,
FeatureSet::FMA4,
FeatureSet::XOP,
FeatureSet::AES,
FeatureSet::SHA,
FeatureSet::AMX,
];
for (i, a) in sets.iter().enumerate() {
for (j, b) in sets.iter().enumerate() {
if i == j {
assert_eq!(a, b);
} else {
}
}
}
}
#[test]
fn test_processor_mode_default_sizes() {
assert_eq!(McProcessorMode::Mode16.default_operand_size(), 16);
assert_eq!(McProcessorMode::Mode16.default_address_size(), 16);
assert_eq!(McProcessorMode::Mode32.default_operand_size(), 32);
assert_eq!(McProcessorMode::Mode32.default_address_size(), 32);
assert_eq!(McProcessorMode::Mode64.default_operand_size(), 32);
assert_eq!(McProcessorMode::Mode64.default_address_size(), 64);
}
#[test]
fn test_processor_mode_is_64bit() {
assert!(McProcessorMode::Mode64.is_64bit());
assert!(!McProcessorMode::Mode32.is_64bit());
assert!(!McProcessorMode::Mode16.is_64bit());
}
#[test]
fn test_size_hint_from_intel_prefix() {
assert_eq!(McSizeHint::from_intel_prefix("byte ptr "), McSizeHint::Byte);
assert_eq!(
McSizeHint::from_intel_prefix("dword ptr "),
McSizeHint::Dword
);
assert_eq!(
McSizeHint::from_intel_prefix("qword ptr "),
McSizeHint::Qword
);
assert_eq!(
McSizeHint::from_intel_prefix("xmmword ptr "),
McSizeHint::Oword
);
assert_eq!(
McSizeHint::from_intel_prefix("ymmword ptr "),
McSizeHint::Yword
);
assert_eq!(
McSizeHint::from_intel_prefix("zmmword ptr "),
McSizeHint::Zword
);
assert_eq!(McSizeHint::from_intel_prefix("unknown "), McSizeHint::None);
}
#[test]
fn test_legacy_prefixes_default() {
let p = McLegacyPrefixes::default();
assert!(!p.has_lock);
assert_eq!(p.effective_operand_size, 0);
assert_eq!(p.effective_address_size, 0);
assert!(p.active_segment_override.is_none());
}
#[test]
fn test_rex_info_default() {
let r = McRexInfo::default();
assert!(!r.present);
assert!(!r.w);
}
#[test]
fn test_vex_info_default_v2() {
let v = McVexInfo::default();
assert!(!v.present);
assert_eq!(v.mmmmm, 0);
}
#[test]
fn test_evex_info_default_v2() {
let e = McEvexInfo::default();
assert!(!e.present);
assert_eq!(e.aaa, 0);
assert_eq!(e.ll, 0);
}
#[test]
fn test_annotate_empty_symbols() {
let inst = McDecodedInstruction {
mnemonic: "call".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![McDecodedOperand::RelativeOffset {
offset: 16,
size: 4,
}],
size: 5,
address: 0x1000,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes {
is_call: true,
..Default::default()
},
opcode_extension: None,
operand_size: 32,
address_size: 64,
vector_length: 0,
};
let symbols = BTreeMap::new();
let annotator = X86InstructionAnnotator::new();
let comment = annotator.annotate(&inst, &symbols);
assert!(comment.contains("call procedure") || !comment.is_empty());
}
#[test]
fn test_annotate_rip_relative_symbol() {
let inst = McDecodedInstruction {
mnemonic: "lea".into(),
opcode: 0,
opcode_map: McOpcodeMap::Primary,
operands: vec![
McDecodedOperand::Register {
reg: McX86Reg::RAX,
size_hint: McSizeHint::Qword,
},
McDecodedOperand::Memory {
segment: None,
base: None,
index: None,
displacement: 0x100,
size_hint: McSizeHint::Qword,
rip_relative: true,
},
],
size: 7,
address: 0x1000,
prefixes: McLegacyPrefixes::default(),
rex: None,
vex: None,
evex: None,
implicit_operands: vec![],
attributes: McInstrAttributes::default(),
opcode_extension: None,
operand_size: 64,
address_size: 64,
vector_length: 0,
};
let mut symbols = BTreeMap::new();
symbols.insert(0x1107, "my_data".to_string());
let annotator = X86InstructionAnnotator::new();
let comment = annotator.annotate(&inst, &symbols);
assert!(comment.contains("my_data"));
}
#[test]
fn test_fma_variants_in_table() {
let v2 = vex_opcode_table_2();
let fma_count = v2
.iter()
.filter(|e| matches!(e.feature_required, FeatureSet::FMA))
.count();
assert!(
fma_count > 5,
"Expected at least 6 FMA entries, got {}",
fma_count
);
}
#[test]
fn test_bmi_variants_in_table() {
let v2 = vex_opcode_table_2();
let bmi_count = v2
.iter()
.filter(|e| matches!(e.feature_required, FeatureSet::BMI | FeatureSet::BMI2))
.count();
assert!(bmi_count > 0, "Expected BMI entries, got {}", bmi_count);
}
#[test]
fn test_avx2_entries() {
let v2 = vex_opcode_table_2();
let avx2_count = v2
.iter()
.filter(|e| matches!(e.feature_required, FeatureSet::AVX2))
.count();
assert!(
avx2_count > 3,
"Expected multiple AVX2 entries, got {}",
avx2_count
);
}
#[test]
fn test_gather_entries_in_vex2() {
let v2 = vex_opcode_table_2();
let gather_count = v2
.iter()
.filter(|e| e.mnemonic.starts_with("vgather") || e.mnemonic.starts_with("vpgather"))
.count();
assert!(gather_count > 0, "Expected gather entries");
}
#[test]
fn test_permute_entries() {
let v2 = vex_opcode_table_2();
let perm_count = v2.iter().filter(|e| e.mnemonic.contains("perm")).count();
assert!(
perm_count > 0,
"Expected permute entries, got {}",
perm_count
);
}
}