use std::collections::HashMap;
use super::x86_full_instr_info::{
EncodingForm, InstrEncodingInfo, X86FullInstrInfo, X86FullOpcode,
};
use super::x86_instr_info::{OperandType, X86MemOperand, X86Operand};
use super::x86_mc_encoder::{mod_field, prefixes, X86MCEncoder, X86Mode};
use super::x86_register_info::RegClass;
use super::x86_subtarget::X86Subtarget;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OpcodeOperandClass {
NoModRM,
ModRMReg,
ModRMDigit(u8),
ModRMOpcodeExtension,
OpcodeReg(u8),
ImplicitReg(u8),
}
#[derive(Debug, Clone)]
pub struct OpcodeEncodingEntry {
pub opcode_byte: u8,
pub opcode_map: u8,
pub mnemonic: &'static str,
pub intel_mnemonic: &'static str,
pub operand_class: OpcodeOperandClass,
pub has_modrm: bool,
pub can_have_sib: bool,
pub imm_size: u8,
pub has_disp: bool,
pub mandatory_prefix: u8,
pub requires_rex_w: bool,
pub valid_64: bool,
pub valid_32: bool,
pub valid_16: bool,
pub encoding_form: EncodingForm,
}
impl Default for OpcodeEncodingEntry {
fn default() -> Self {
OpcodeEncodingEntry {
opcode_byte: 0,
opcode_map: 0,
mnemonic: "invalid",
intel_mnemonic: "INVALID",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
can_have_sib: false,
imm_size: 0,
has_disp: false,
mandatory_prefix: 0,
requires_rex_w: false,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
}
}
}
pub fn build_primary_opcode_map() -> [OpcodeEncodingEntry; 256] {
let mut map: [OpcodeEncodingEntry; 256] =
std::array::from_fn(|_| OpcodeEncodingEntry::default());
map[0x00] = OpcodeEncodingEntry {
opcode_byte: 0x00,
opcode_map: 0,
mnemonic: "addb",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 0,
has_disp: true,
..Default::default()
};
map[0x01] = OpcodeEncodingEntry {
opcode_byte: 0x01,
opcode_map: 0,
mnemonic: "addl",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 0,
has_disp: true,
..Default::default()
};
map[0x02] = OpcodeEncodingEntry {
opcode_byte: 0x02,
opcode_map: 0,
mnemonic: "addb",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 0,
has_disp: true,
..Default::default()
};
map[0x03] = OpcodeEncodingEntry {
opcode_byte: 0x03,
opcode_map: 0,
mnemonic: "addl",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 0,
has_disp: true,
..Default::default()
};
map[0x04] = OpcodeEncodingEntry {
opcode_byte: 0x04,
opcode_map: 0,
mnemonic: "addb",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x05] = OpcodeEncodingEntry {
opcode_byte: 0x05,
opcode_map: 0,
mnemonic: "addl",
intel_mnemonic: "ADD",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x06] = OpcodeEncodingEntry {
opcode_byte: 0x06,
opcode_map: 0,
mnemonic: "pushw",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x07] = OpcodeEncodingEntry {
opcode_byte: 0x07,
opcode_map: 0,
mnemonic: "popw",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x08] = OpcodeEncodingEntry {
opcode_byte: 0x08,
opcode_map: 0,
mnemonic: "orb",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x09] = OpcodeEncodingEntry {
opcode_byte: 0x09,
opcode_map: 0,
mnemonic: "orl",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x0A] = OpcodeEncodingEntry {
opcode_byte: 0x0A,
opcode_map: 0,
mnemonic: "orb",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x0B] = OpcodeEncodingEntry {
opcode_byte: 0x0B,
opcode_map: 0,
mnemonic: "orl",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x0C] = OpcodeEncodingEntry {
opcode_byte: 0x0C,
opcode_map: 0,
mnemonic: "orb",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x0D] = OpcodeEncodingEntry {
opcode_byte: 0x0D,
opcode_map: 0,
mnemonic: "orl",
intel_mnemonic: "OR",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x0E] = OpcodeEncodingEntry {
opcode_byte: 0x0E,
opcode_map: 0,
mnemonic: "pushw",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x0F] = OpcodeEncodingEntry {
opcode_byte: 0x0F,
opcode_map: 0,
mnemonic: "escape_0f",
intel_mnemonic: "ESCAPE",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x10] = OpcodeEncodingEntry {
opcode_byte: 0x10,
opcode_map: 0,
mnemonic: "adcb",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x11] = OpcodeEncodingEntry {
opcode_byte: 0x11,
opcode_map: 0,
mnemonic: "adcl",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x12] = OpcodeEncodingEntry {
opcode_byte: 0x12,
opcode_map: 0,
mnemonic: "adcb",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x13] = OpcodeEncodingEntry {
opcode_byte: 0x13,
opcode_map: 0,
mnemonic: "adcl",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x14] = OpcodeEncodingEntry {
opcode_byte: 0x14,
opcode_map: 0,
mnemonic: "adcb",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x15] = OpcodeEncodingEntry {
opcode_byte: 0x15,
opcode_map: 0,
mnemonic: "adcl",
intel_mnemonic: "ADC",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x16] = OpcodeEncodingEntry {
opcode_byte: 0x16,
opcode_map: 0,
mnemonic: "pushw",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x17] = OpcodeEncodingEntry {
opcode_byte: 0x17,
opcode_map: 0,
mnemonic: "popw",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x18] = OpcodeEncodingEntry {
opcode_byte: 0x18,
opcode_map: 0,
mnemonic: "sbbb",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x19] = OpcodeEncodingEntry {
opcode_byte: 0x19,
opcode_map: 0,
mnemonic: "sbbl",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x1A] = OpcodeEncodingEntry {
opcode_byte: 0x1A,
opcode_map: 0,
mnemonic: "sbbb",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x1B] = OpcodeEncodingEntry {
opcode_byte: 0x1B,
opcode_map: 0,
mnemonic: "sbbl",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x1C] = OpcodeEncodingEntry {
opcode_byte: 0x1C,
opcode_map: 0,
mnemonic: "sbbb",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x1D] = OpcodeEncodingEntry {
opcode_byte: 0x1D,
opcode_map: 0,
mnemonic: "sbbl",
intel_mnemonic: "SBB",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x1E] = OpcodeEncodingEntry {
opcode_byte: 0x1E,
opcode_map: 0,
mnemonic: "pushw",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x1F] = OpcodeEncodingEntry {
opcode_byte: 0x1F,
opcode_map: 0,
mnemonic: "popw",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x20] = OpcodeEncodingEntry {
opcode_byte: 0x20,
opcode_map: 0,
mnemonic: "andb",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x21] = OpcodeEncodingEntry {
opcode_byte: 0x21,
opcode_map: 0,
mnemonic: "andl",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x22] = OpcodeEncodingEntry {
opcode_byte: 0x22,
opcode_map: 0,
mnemonic: "andb",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x23] = OpcodeEncodingEntry {
opcode_byte: 0x23,
opcode_map: 0,
mnemonic: "andl",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x24] = OpcodeEncodingEntry {
opcode_byte: 0x24,
opcode_map: 0,
mnemonic: "andb",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x25] = OpcodeEncodingEntry {
opcode_byte: 0x25,
opcode_map: 0,
mnemonic: "andl",
intel_mnemonic: "AND",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x26] = OpcodeEncodingEntry {
opcode_byte: 0x26,
opcode_map: 0,
mnemonic: "es",
intel_mnemonic: "ES",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x27] = OpcodeEncodingEntry {
opcode_byte: 0x27,
opcode_map: 0,
mnemonic: "daa",
intel_mnemonic: "DAA",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x28] = OpcodeEncodingEntry {
opcode_byte: 0x28,
opcode_map: 0,
mnemonic: "subb",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x29] = OpcodeEncodingEntry {
opcode_byte: 0x29,
opcode_map: 0,
mnemonic: "subl",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x2A] = OpcodeEncodingEntry {
opcode_byte: 0x2A,
opcode_map: 0,
mnemonic: "subb",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x2B] = OpcodeEncodingEntry {
opcode_byte: 0x2B,
opcode_map: 0,
mnemonic: "subl",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x2C] = OpcodeEncodingEntry {
opcode_byte: 0x2C,
opcode_map: 0,
mnemonic: "subb",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x2D] = OpcodeEncodingEntry {
opcode_byte: 0x2D,
opcode_map: 0,
mnemonic: "subl",
intel_mnemonic: "SUB",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x2E] = OpcodeEncodingEntry {
opcode_byte: 0x2E,
opcode_map: 0,
mnemonic: "cs",
intel_mnemonic: "CS",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x2F] = OpcodeEncodingEntry {
opcode_byte: 0x2F,
opcode_map: 0,
mnemonic: "das",
intel_mnemonic: "DAS",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x30] = OpcodeEncodingEntry {
opcode_byte: 0x30,
opcode_map: 0,
mnemonic: "xorb",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x31] = OpcodeEncodingEntry {
opcode_byte: 0x31,
opcode_map: 0,
mnemonic: "xorl",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x32] = OpcodeEncodingEntry {
opcode_byte: 0x32,
opcode_map: 0,
mnemonic: "xorb",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x33] = OpcodeEncodingEntry {
opcode_byte: 0x33,
opcode_map: 0,
mnemonic: "xorl",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x34] = OpcodeEncodingEntry {
opcode_byte: 0x34,
opcode_map: 0,
mnemonic: "xorb",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x35] = OpcodeEncodingEntry {
opcode_byte: 0x35,
opcode_map: 0,
mnemonic: "xorl",
intel_mnemonic: "XOR",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x36] = OpcodeEncodingEntry {
opcode_byte: 0x36,
opcode_map: 0,
mnemonic: "ss",
intel_mnemonic: "SS",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x37] = OpcodeEncodingEntry {
opcode_byte: 0x37,
opcode_map: 0,
mnemonic: "aaa",
intel_mnemonic: "AAA",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x38] = OpcodeEncodingEntry {
opcode_byte: 0x38,
opcode_map: 0,
mnemonic: "cmpb",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x39] = OpcodeEncodingEntry {
opcode_byte: 0x39,
opcode_map: 0,
mnemonic: "cmpl",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x3A] = OpcodeEncodingEntry {
opcode_byte: 0x3A,
opcode_map: 0,
mnemonic: "cmpb",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x3B] = OpcodeEncodingEntry {
opcode_byte: 0x3B,
opcode_map: 0,
mnemonic: "cmpl",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x3C] = OpcodeEncodingEntry {
opcode_byte: 0x3C,
opcode_map: 0,
mnemonic: "cmpb",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x3D] = OpcodeEncodingEntry {
opcode_byte: 0x3D,
opcode_map: 0,
mnemonic: "cmpl",
intel_mnemonic: "CMP",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x3E] = OpcodeEncodingEntry {
opcode_byte: 0x3E,
opcode_map: 0,
mnemonic: "ds",
intel_mnemonic: "DS",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x3F] = OpcodeEncodingEntry {
opcode_byte: 0x3F,
opcode_map: 0,
mnemonic: "aas",
intel_mnemonic: "AAS",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
for i in 0x40u8..0x48u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "rex",
intel_mnemonic: "REX",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
..Default::default()
};
}
for i in 0x48u8..0x50u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "rex_w",
intel_mnemonic: "REX.W",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
requires_rex_w: true,
..Default::default()
};
}
for i in 0x50u8..0x58u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "push",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
..Default::default()
};
}
for i in 0x58u8..0x60u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "pop",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
..Default::default()
};
}
map[0x60] = OpcodeEncodingEntry {
opcode_byte: 0x60,
opcode_map: 0,
mnemonic: "pusha",
intel_mnemonic: "PUSHA",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x61] = OpcodeEncodingEntry {
opcode_byte: 0x61,
opcode_map: 0,
mnemonic: "popa",
intel_mnemonic: "POPA",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0x62] = OpcodeEncodingEntry {
opcode_byte: 0x62,
opcode_map: 0,
mnemonic: "bound",
intel_mnemonic: "BOUND",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: false,
..Default::default()
};
map[0x63] = OpcodeEncodingEntry {
opcode_byte: 0x63,
opcode_map: 0,
mnemonic: "movsxd",
intel_mnemonic: "MOVSXD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
requires_rex_w: true,
..Default::default()
};
map[0x64] = OpcodeEncodingEntry {
opcode_byte: 0x64,
opcode_map: 0,
mnemonic: "fs",
intel_mnemonic: "FS",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x65] = OpcodeEncodingEntry {
opcode_byte: 0x65,
opcode_map: 0,
mnemonic: "gs",
intel_mnemonic: "GS",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x66] = OpcodeEncodingEntry {
opcode_byte: 0x66,
opcode_map: 0,
mnemonic: "data16",
intel_mnemonic: "DATA16",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x67] = OpcodeEncodingEntry {
opcode_byte: 0x67,
opcode_map: 0,
mnemonic: "addr32",
intel_mnemonic: "ADDR32",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x68] = OpcodeEncodingEntry {
opcode_byte: 0x68,
opcode_map: 0,
mnemonic: "push",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0x69] = OpcodeEncodingEntry {
opcode_byte: 0x69,
opcode_map: 0,
mnemonic: "imul",
intel_mnemonic: "IMUL",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 4,
has_disp: true,
..Default::default()
};
map[0x6A] = OpcodeEncodingEntry {
opcode_byte: 0x6A,
opcode_map: 0,
mnemonic: "push",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0x6B] = OpcodeEncodingEntry {
opcode_byte: 0x6B,
opcode_map: 0,
mnemonic: "imul",
intel_mnemonic: "IMUL",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0x6C] = OpcodeEncodingEntry {
opcode_byte: 0x6C,
opcode_map: 0,
mnemonic: "insb",
intel_mnemonic: "INSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x6D] = OpcodeEncodingEntry {
opcode_byte: 0x6D,
opcode_map: 0,
mnemonic: "insl",
intel_mnemonic: "INSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x6E] = OpcodeEncodingEntry {
opcode_byte: 0x6E,
opcode_map: 0,
mnemonic: "outsb",
intel_mnemonic: "OUTSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x6F] = OpcodeEncodingEntry {
opcode_byte: 0x6F,
opcode_map: 0,
mnemonic: "outsl",
intel_mnemonic: "OUTSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
let jcc_mnemonics = [
"jo", "jno", "jb", "jae", "je", "jne", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge",
"jle", "jg",
];
let jcc_intel = [
"JO", "JNO", "JB", "JAE", "JE", "JNE", "JBE", "JA", "JS", "JNS", "JP", "JNP", "JL", "JGE",
"JLE", "JG",
];
for i in 0..16u8 {
let idx = (i & 0x0F) as usize;
map[(0x70 + i) as usize] = OpcodeEncodingEntry {
opcode_byte: 0x70 + i,
opcode_map: 0,
mnemonic: jcc_mnemonics[idx],
intel_mnemonic: jcc_intel[idx],
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
}
map[0x80] = OpcodeEncodingEntry {
opcode_byte: 0x80,
opcode_map: 0,
mnemonic: "grp1_8",
intel_mnemonic: "GRP1",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0x81] = OpcodeEncodingEntry {
opcode_byte: 0x81,
opcode_map: 0,
mnemonic: "grp1_32",
intel_mnemonic: "GRP1",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 4,
has_disp: true,
..Default::default()
};
map[0x82] = OpcodeEncodingEntry {
opcode_byte: 0x82,
opcode_map: 0,
mnemonic: "grp1_8_alt",
intel_mnemonic: "GRP1",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
valid_64: false,
..Default::default()
};
map[0x83] = OpcodeEncodingEntry {
opcode_byte: 0x83,
opcode_map: 0,
mnemonic: "grp1_sx",
intel_mnemonic: "GRP1",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0x84] = OpcodeEncodingEntry {
opcode_byte: 0x84,
opcode_map: 0,
mnemonic: "testb",
intel_mnemonic: "TEST",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x85] = OpcodeEncodingEntry {
opcode_byte: 0x85,
opcode_map: 0,
mnemonic: "testl",
intel_mnemonic: "TEST",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x86] = OpcodeEncodingEntry {
opcode_byte: 0x86,
opcode_map: 0,
mnemonic: "xchgb",
intel_mnemonic: "XCHG",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x87] = OpcodeEncodingEntry {
opcode_byte: 0x87,
opcode_map: 0,
mnemonic: "xchgl",
intel_mnemonic: "XCHG",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x88] = OpcodeEncodingEntry {
opcode_byte: 0x88,
opcode_map: 0,
mnemonic: "movb",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x89] = OpcodeEncodingEntry {
opcode_byte: 0x89,
opcode_map: 0,
mnemonic: "movl",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8A] = OpcodeEncodingEntry {
opcode_byte: 0x8A,
opcode_map: 0,
mnemonic: "movb",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8B] = OpcodeEncodingEntry {
opcode_byte: 0x8B,
opcode_map: 0,
mnemonic: "movl",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8C] = OpcodeEncodingEntry {
opcode_byte: 0x8C,
opcode_map: 0,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8D] = OpcodeEncodingEntry {
opcode_byte: 0x8D,
opcode_map: 0,
mnemonic: "lea",
intel_mnemonic: "LEA",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8E] = OpcodeEncodingEntry {
opcode_byte: 0x8E,
opcode_map: 0,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x8F] = OpcodeEncodingEntry {
opcode_byte: 0x8F,
opcode_map: 0,
mnemonic: "pop",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0x90] = OpcodeEncodingEntry {
opcode_byte: 0x90,
opcode_map: 0,
mnemonic: "nop",
intel_mnemonic: "NOP",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
for i in 0x91u8..0x98u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "xchg",
intel_mnemonic: "XCHG",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
..Default::default()
};
}
map[0x98] = OpcodeEncodingEntry {
opcode_byte: 0x98,
opcode_map: 0,
mnemonic: "cbtw",
intel_mnemonic: "CBW/CWDE/CDQE",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x99] = OpcodeEncodingEntry {
opcode_byte: 0x99,
opcode_map: 0,
mnemonic: "cwtd",
intel_mnemonic: "CWD/CDQ/CQO",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x9A] = OpcodeEncodingEntry {
opcode_byte: 0x9A,
opcode_map: 0,
mnemonic: "lcall",
intel_mnemonic: "CALLF",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
has_disp: false,
valid_64: false,
..Default::default()
};
map[0x9B] = OpcodeEncodingEntry {
opcode_byte: 0x9B,
opcode_map: 0,
mnemonic: "fwait",
intel_mnemonic: "WAIT",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x9C] = OpcodeEncodingEntry {
opcode_byte: 0x9C,
opcode_map: 0,
mnemonic: "pushf",
intel_mnemonic: "PUSHF",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x9D] = OpcodeEncodingEntry {
opcode_byte: 0x9D,
opcode_map: 0,
mnemonic: "popf",
intel_mnemonic: "POPF",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x9E] = OpcodeEncodingEntry {
opcode_byte: 0x9E,
opcode_map: 0,
mnemonic: "sahf",
intel_mnemonic: "SAHF",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0x9F] = OpcodeEncodingEntry {
opcode_byte: 0x9F,
opcode_map: 0,
mnemonic: "lahf",
intel_mnemonic: "LAHF",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xA0] = OpcodeEncodingEntry {
opcode_byte: 0xA0,
opcode_map: 0,
mnemonic: "movb",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
has_disp: true,
..Default::default()
};
map[0xA1] = OpcodeEncodingEntry {
opcode_byte: 0xA1,
opcode_map: 0,
mnemonic: "movl",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
has_disp: true,
..Default::default()
};
map[0xA2] = OpcodeEncodingEntry {
opcode_byte: 0xA2,
opcode_map: 0,
mnemonic: "movb",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
has_disp: true,
..Default::default()
};
map[0xA3] = OpcodeEncodingEntry {
opcode_byte: 0xA3,
opcode_map: 0,
mnemonic: "movl",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
has_disp: true,
..Default::default()
};
map[0xA4] = OpcodeEncodingEntry {
opcode_byte: 0xA4,
opcode_map: 0,
mnemonic: "movsb",
intel_mnemonic: "MOVSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xA5] = OpcodeEncodingEntry {
opcode_byte: 0xA5,
opcode_map: 0,
mnemonic: "movsl",
intel_mnemonic: "MOVSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xA6] = OpcodeEncodingEntry {
opcode_byte: 0xA6,
opcode_map: 0,
mnemonic: "cmpsb",
intel_mnemonic: "CMPSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xA7] = OpcodeEncodingEntry {
opcode_byte: 0xA7,
opcode_map: 0,
mnemonic: "cmpsl",
intel_mnemonic: "CMPSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xA8] = OpcodeEncodingEntry {
opcode_byte: 0xA8,
opcode_map: 0,
mnemonic: "testb",
intel_mnemonic: "TEST",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xA9] = OpcodeEncodingEntry {
opcode_byte: 0xA9,
opcode_map: 0,
mnemonic: "testl",
intel_mnemonic: "TEST",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0xAA] = OpcodeEncodingEntry {
opcode_byte: 0xAA,
opcode_map: 0,
mnemonic: "stosb",
intel_mnemonic: "STOSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xAB] = OpcodeEncodingEntry {
opcode_byte: 0xAB,
opcode_map: 0,
mnemonic: "stosl",
intel_mnemonic: "STOSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xAC] = OpcodeEncodingEntry {
opcode_byte: 0xAC,
opcode_map: 0,
mnemonic: "lodsb",
intel_mnemonic: "LODSB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xAD] = OpcodeEncodingEntry {
opcode_byte: 0xAD,
opcode_map: 0,
mnemonic: "lodsl",
intel_mnemonic: "LODSD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xAE] = OpcodeEncodingEntry {
opcode_byte: 0xAE,
opcode_map: 0,
mnemonic: "scasb",
intel_mnemonic: "SCASB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xAF] = OpcodeEncodingEntry {
opcode_byte: 0xAF,
opcode_map: 0,
mnemonic: "scasl",
intel_mnemonic: "SCASD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
for i in 0xB0u8..0xB8u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "movb",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
has_modrm: false,
imm_size: 1,
..Default::default()
};
}
for i in 0xB8u8..0xC0u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 0,
mnemonic: "movl",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
has_modrm: false,
imm_size: 4,
..Default::default()
};
}
map[0xC0] = OpcodeEncodingEntry {
opcode_byte: 0xC0,
opcode_map: 0,
mnemonic: "grp2_8",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0xC1] = OpcodeEncodingEntry {
opcode_byte: 0xC1,
opcode_map: 0,
mnemonic: "grp2_32",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0xC2] = OpcodeEncodingEntry {
opcode_byte: 0xC2,
opcode_map: 0,
mnemonic: "ret",
intel_mnemonic: "RET",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 2,
..Default::default()
};
map[0xC3] = OpcodeEncodingEntry {
opcode_byte: 0xC3,
opcode_map: 0,
mnemonic: "ret",
intel_mnemonic: "RET",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xC4] = OpcodeEncodingEntry {
opcode_byte: 0xC4,
opcode_map: 0,
mnemonic: "les",
intel_mnemonic: "LES",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: false,
..Default::default()
};
map[0xC5] = OpcodeEncodingEntry {
opcode_byte: 0xC5,
opcode_map: 0,
mnemonic: "lds",
intel_mnemonic: "LDS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: false,
..Default::default()
};
map[0xC6] = OpcodeEncodingEntry {
opcode_byte: 0xC6,
opcode_map: 0,
mnemonic: "grp11_8",
intel_mnemonic: "GRP11",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 1,
has_disp: true,
..Default::default()
};
map[0xC7] = OpcodeEncodingEntry {
opcode_byte: 0xC7,
opcode_map: 0,
mnemonic: "grp11_32",
intel_mnemonic: "GRP11",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
imm_size: 4,
has_disp: true,
..Default::default()
};
map[0xC8] = OpcodeEncodingEntry {
opcode_byte: 0xC8,
opcode_map: 0,
mnemonic: "enter",
intel_mnemonic: "ENTER",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 3,
..Default::default()
};
map[0xC9] = OpcodeEncodingEntry {
opcode_byte: 0xC9,
opcode_map: 0,
mnemonic: "leave",
intel_mnemonic: "LEAVE",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xCA] = OpcodeEncodingEntry {
opcode_byte: 0xCA,
opcode_map: 0,
mnemonic: "lret",
intel_mnemonic: "RETF",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 2,
..Default::default()
};
map[0xCB] = OpcodeEncodingEntry {
opcode_byte: 0xCB,
opcode_map: 0,
mnemonic: "lret",
intel_mnemonic: "RETF",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xCC] = OpcodeEncodingEntry {
opcode_byte: 0xCC,
opcode_map: 0,
mnemonic: "int3",
intel_mnemonic: "INT3",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xCD] = OpcodeEncodingEntry {
opcode_byte: 0xCD,
opcode_map: 0,
mnemonic: "int",
intel_mnemonic: "INT",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xCE] = OpcodeEncodingEntry {
opcode_byte: 0xCE,
opcode_map: 0,
mnemonic: "into",
intel_mnemonic: "INTO",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0xCF] = OpcodeEncodingEntry {
opcode_byte: 0xCF,
opcode_map: 0,
mnemonic: "iret",
intel_mnemonic: "IRET",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xD0] = OpcodeEncodingEntry {
opcode_byte: 0xD0,
opcode_map: 0,
mnemonic: "grp2_8_cl",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xD1] = OpcodeEncodingEntry {
opcode_byte: 0xD1,
opcode_map: 0,
mnemonic: "grp2_32_cl",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xD2] = OpcodeEncodingEntry {
opcode_byte: 0xD2,
opcode_map: 0,
mnemonic: "grp2_8_cl",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xD3] = OpcodeEncodingEntry {
opcode_byte: 0xD3,
opcode_map: 0,
mnemonic: "grp2_32_cl",
intel_mnemonic: "GRP2",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xD4] = OpcodeEncodingEntry {
opcode_byte: 0xD4,
opcode_map: 0,
mnemonic: "aam",
intel_mnemonic: "AAM",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
valid_64: false,
..Default::default()
};
map[0xD5] = OpcodeEncodingEntry {
opcode_byte: 0xD5,
opcode_map: 0,
mnemonic: "aad",
intel_mnemonic: "AAD",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
valid_64: false,
..Default::default()
};
map[0xD6] = OpcodeEncodingEntry {
opcode_byte: 0xD6,
opcode_map: 0,
mnemonic: "salc",
intel_mnemonic: "SALC",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0xD7] = OpcodeEncodingEntry {
opcode_byte: 0xD7,
opcode_map: 0,
mnemonic: "xlatb",
intel_mnemonic: "XLATB",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
let fpu_entries = [
(0xD8, "fadd", "FADD"),
(0xD9, "fld", "FLD"),
(0xDA, "fiadd", "FIADD"),
(0xDB, "fild", "FILD"),
(0xDC, "fadd", "FADD"),
(0xDD, "fld", "FLD"),
(0xDE, "fiadd", "FIADD"),
(0xDF, "fild", "FILD"),
];
for &(op, mn, intel) in &fpu_entries {
map[op as usize] = OpcodeEncodingEntry {
opcode_byte: op,
opcode_map: 0,
mnemonic: mn,
intel_mnemonic: intel,
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
}
map[0xE0] = OpcodeEncodingEntry {
opcode_byte: 0xE0,
opcode_map: 0,
mnemonic: "loopne",
intel_mnemonic: "LOOPNE",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE1] = OpcodeEncodingEntry {
opcode_byte: 0xE1,
opcode_map: 0,
mnemonic: "loope",
intel_mnemonic: "LOOPE",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE2] = OpcodeEncodingEntry {
opcode_byte: 0xE2,
opcode_map: 0,
mnemonic: "loop",
intel_mnemonic: "LOOP",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE3] = OpcodeEncodingEntry {
opcode_byte: 0xE3,
opcode_map: 0,
mnemonic: "jecxz",
intel_mnemonic: "JECXZ",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE4] = OpcodeEncodingEntry {
opcode_byte: 0xE4,
opcode_map: 0,
mnemonic: "inb",
intel_mnemonic: "IN",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE5] = OpcodeEncodingEntry {
opcode_byte: 0xE5,
opcode_map: 0,
mnemonic: "inl",
intel_mnemonic: "IN",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE6] = OpcodeEncodingEntry {
opcode_byte: 0xE6,
opcode_map: 0,
mnemonic: "outb",
intel_mnemonic: "OUT",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE7] = OpcodeEncodingEntry {
opcode_byte: 0xE7,
opcode_map: 0,
mnemonic: "outl",
intel_mnemonic: "OUT",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xE8] = OpcodeEncodingEntry {
opcode_byte: 0xE8,
opcode_map: 0,
mnemonic: "call",
intel_mnemonic: "CALL",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0xE9] = OpcodeEncodingEntry {
opcode_byte: 0xE9,
opcode_map: 0,
mnemonic: "jmp",
intel_mnemonic: "JMP",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
..Default::default()
};
map[0xEA] = OpcodeEncodingEntry {
opcode_byte: 0xEA,
opcode_map: 0,
mnemonic: "ljmp",
intel_mnemonic: "JMPF",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: false,
..Default::default()
};
map[0xEB] = OpcodeEncodingEntry {
opcode_byte: 0xEB,
opcode_map: 0,
mnemonic: "jmp",
intel_mnemonic: "JMP",
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 1,
..Default::default()
};
map[0xEC] = OpcodeEncodingEntry {
opcode_byte: 0xEC,
opcode_map: 0,
mnemonic: "inb",
intel_mnemonic: "IN",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xED] = OpcodeEncodingEntry {
opcode_byte: 0xED,
opcode_map: 0,
mnemonic: "inl",
intel_mnemonic: "IN",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xEE] = OpcodeEncodingEntry {
opcode_byte: 0xEE,
opcode_map: 0,
mnemonic: "outb",
intel_mnemonic: "OUT",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xEF] = OpcodeEncodingEntry {
opcode_byte: 0xEF,
opcode_map: 0,
mnemonic: "outl",
intel_mnemonic: "OUT",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF0] = OpcodeEncodingEntry {
opcode_byte: 0xF0,
opcode_map: 0,
mnemonic: "lock",
intel_mnemonic: "LOCK",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF1] = OpcodeEncodingEntry {
opcode_byte: 0xF1,
opcode_map: 0,
mnemonic: "int1",
intel_mnemonic: "INT1",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF2] = OpcodeEncodingEntry {
opcode_byte: 0xF2,
opcode_map: 0,
mnemonic: "repne",
intel_mnemonic: "REPNE",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF3] = OpcodeEncodingEntry {
opcode_byte: 0xF3,
opcode_map: 0,
mnemonic: "rep",
intel_mnemonic: "REP",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF4] = OpcodeEncodingEntry {
opcode_byte: 0xF4,
opcode_map: 0,
mnemonic: "hlt",
intel_mnemonic: "HLT",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF5] = OpcodeEncodingEntry {
opcode_byte: 0xF5,
opcode_map: 0,
mnemonic: "cmc",
intel_mnemonic: "CMC",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF6] = OpcodeEncodingEntry {
opcode_byte: 0xF6,
opcode_map: 0,
mnemonic: "grp3_8",
intel_mnemonic: "GRP3",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xF7] = OpcodeEncodingEntry {
opcode_byte: 0xF7,
opcode_map: 0,
mnemonic: "grp3_32",
intel_mnemonic: "GRP3",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xF8] = OpcodeEncodingEntry {
opcode_byte: 0xF8,
opcode_map: 0,
mnemonic: "clc",
intel_mnemonic: "CLC",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xF9] = OpcodeEncodingEntry {
opcode_byte: 0xF9,
opcode_map: 0,
mnemonic: "stc",
intel_mnemonic: "STC",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xFA] = OpcodeEncodingEntry {
opcode_byte: 0xFA,
opcode_map: 0,
mnemonic: "cli",
intel_mnemonic: "CLI",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xFB] = OpcodeEncodingEntry {
opcode_byte: 0xFB,
opcode_map: 0,
mnemonic: "sti",
intel_mnemonic: "STI",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xFC] = OpcodeEncodingEntry {
opcode_byte: 0xFC,
opcode_map: 0,
mnemonic: "cld",
intel_mnemonic: "CLD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xFD] = OpcodeEncodingEntry {
opcode_byte: 0xFD,
opcode_map: 0,
mnemonic: "std",
intel_mnemonic: "STD",
operand_class: OpcodeOperandClass::NoModRM,
..Default::default()
};
map[0xFE] = OpcodeEncodingEntry {
opcode_byte: 0xFE,
opcode_map: 0,
mnemonic: "grp4_8",
intel_mnemonic: "GRP4",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map[0xFF] = OpcodeEncodingEntry {
opcode_byte: 0xFF,
opcode_map: 0,
mnemonic: "grp5",
intel_mnemonic: "GRP5",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
..Default::default()
};
map
}
pub fn build_two_byte_opcode_map() -> [OpcodeEncodingEntry; 256] {
let mut map: [OpcodeEncodingEntry; 256] =
std::array::from_fn(|_| OpcodeEncodingEntry::default());
for entry in &mut map {
entry.opcode_map = 1; entry.valid_64 = true;
entry.valid_32 = true;
}
map[0x00] = OpcodeEncodingEntry {
opcode_byte: 0x00,
opcode_map: 1,
mnemonic: "grp6",
intel_mnemonic: "GRP6",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x01] = OpcodeEncodingEntry {
opcode_byte: 0x01,
opcode_map: 1,
mnemonic: "grp7",
intel_mnemonic: "GRP7",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x02] = OpcodeEncodingEntry {
opcode_byte: 0x02,
opcode_map: 1,
mnemonic: "lar",
intel_mnemonic: "LAR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x03] = OpcodeEncodingEntry {
opcode_byte: 0x03,
opcode_map: 1,
mnemonic: "lsl",
intel_mnemonic: "LSL",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x04] = OpcodeEncodingEntry {
opcode_byte: 0x04,
opcode_map: 1,
mnemonic: "invalid",
intel_mnemonic: "INVALID",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x05] = OpcodeEncodingEntry {
opcode_byte: 0x05,
opcode_map: 1,
mnemonic: "syscall",
intel_mnemonic: "SYSCALL",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x06] = OpcodeEncodingEntry {
opcode_byte: 0x06,
opcode_map: 1,
mnemonic: "clts",
intel_mnemonic: "CLTS",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x07] = OpcodeEncodingEntry {
opcode_byte: 0x07,
opcode_map: 1,
mnemonic: "sysret",
intel_mnemonic: "SYSRET",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x08] = OpcodeEncodingEntry {
opcode_byte: 0x08,
opcode_map: 1,
mnemonic: "invd",
intel_mnemonic: "INVD",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x09] = OpcodeEncodingEntry {
opcode_byte: 0x09,
opcode_map: 1,
mnemonic: "wbinvd",
intel_mnemonic: "WBINVD",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x0B] = OpcodeEncodingEntry {
opcode_byte: 0x0B,
opcode_map: 1,
mnemonic: "ud2",
intel_mnemonic: "UD2",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
let prefix10_mnemonics = [
"movups", "movups", "movlps", "movlps", "unpcklps", "unpckhps", "movhps", "movhps",
];
let prefix10_intel = [
"MOVUPS", "MOVUPS", "MOVLPS", "MOVLPS", "UNPCKLPS", "UNPCKHPS", "MOVHPS", "MOVHPS",
];
for i in 0..8u8 {
let idx = i as usize;
map[(0x10 + i) as usize] = OpcodeEncodingEntry {
opcode_byte: 0x10 + i,
opcode_map: 1,
mnemonic: prefix10_mnemonics[idx],
intel_mnemonic: prefix10_intel[idx],
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x18..0x20u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "prefetch",
intel_mnemonic: "PREFETCH",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map[0x20] = OpcodeEncodingEntry {
opcode_byte: 0x20,
opcode_map: 1,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x21] = OpcodeEncodingEntry {
opcode_byte: 0x21,
opcode_map: 1,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x22] = OpcodeEncodingEntry {
opcode_byte: 0x22,
opcode_map: 1,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x23] = OpcodeEncodingEntry {
opcode_byte: 0x23,
opcode_map: 1,
mnemonic: "mov",
intel_mnemonic: "MOV",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
for i in 0x28u8..0x30u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "movaps",
intel_mnemonic: "MOVAPS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map[0x30] = OpcodeEncodingEntry {
opcode_byte: 0x30,
opcode_map: 1,
mnemonic: "wrmsr",
intel_mnemonic: "WRMSR",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x31] = OpcodeEncodingEntry {
opcode_byte: 0x31,
opcode_map: 1,
mnemonic: "rdtsc",
intel_mnemonic: "RDTSC",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x32] = OpcodeEncodingEntry {
opcode_byte: 0x32,
opcode_map: 1,
mnemonic: "rdmsr",
intel_mnemonic: "RDMSR",
operand_class: OpcodeOperandClass::NoModRM,
valid_64: true,
valid_32: true,
valid_16: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x33] = OpcodeEncodingEntry {
opcode_byte: 0x33,
opcode_map: 1,
mnemonic: "rdpmc",
intel_mnemonic: "RDPMC",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x34] = OpcodeEncodingEntry {
opcode_byte: 0x34,
opcode_map: 1,
mnemonic: "sysenter",
intel_mnemonic: "SYSENTER",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0x35] = OpcodeEncodingEntry {
opcode_byte: 0x35,
opcode_map: 1,
mnemonic: "sysexit",
intel_mnemonic: "SYSEXIT",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
let cmov_mnemonics = [
"cmovo", "cmovno", "cmovb", "cmovae", "cmove", "cmovne", "cmovbe", "cmova", "cmovs",
"cmovns", "cmovp", "cmovnp", "cmovl", "cmovge", "cmovle", "cmovg",
];
let cmov_intel = [
"CMOVO", "CMOVNO", "CMOVB", "CMOVAE", "CMOVE", "CMOVNE", "CMOVBE", "CMOVA", "CMOVS",
"CMOVNS", "CMOVP", "CMOVNP", "CMOVL", "CMOVGE", "CMOVLE", "CMOVG",
];
for i in 0..16u8 {
map[(0x40 + i) as usize] = OpcodeEncodingEntry {
opcode_byte: 0x40 + i,
opcode_map: 1,
mnemonic: cmov_mnemonics[i as usize],
intel_mnemonic: cmov_intel[i as usize],
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x50u8..0x60u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "sse_misc",
intel_mnemonic: "SSE",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x60u8..0x70u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "mmx_sse2",
intel_mnemonic: "MMX/SSE2",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x70u8..0x80u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "sse2_shuf",
intel_mnemonic: "SSE2",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
let jcc_mnemonics = [
"jo", "jno", "jb", "jae", "je", "jne", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge",
"jle", "jg",
];
let jcc_intel = [
"JO", "JNO", "JB", "JAE", "JE", "JNE", "JBE", "JA", "JS", "JNS", "JP", "JNP", "JL", "JGE",
"JLE", "JG",
];
for i in 0..16u8 {
map[(0x80 + i) as usize] = OpcodeEncodingEntry {
opcode_byte: 0x80 + i,
opcode_map: 1,
mnemonic: jcc_mnemonics[i as usize],
intel_mnemonic: jcc_intel[i as usize],
operand_class: OpcodeOperandClass::NoModRM,
has_modrm: false,
imm_size: 4,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
let set_mnemonics = [
"seto", "setno", "setb", "setae", "sete", "setne", "setbe", "seta", "sets", "setns",
"setp", "setnp", "setl", "setge", "setle", "setg",
];
let set_intel = [
"SETO", "SETNO", "SETB", "SETAE", "SETE", "SETNE", "SETBE", "SETA", "SETS", "SETNS",
"SETP", "SETNP", "SETL", "SETGE", "SETLE", "SETG",
];
for i in 0..16u8 {
map[(0x90 + i) as usize] = OpcodeEncodingEntry {
opcode_byte: 0x90 + i,
opcode_map: 1,
mnemonic: set_mnemonics[i as usize],
intel_mnemonic: set_intel[i as usize],
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: false,
has_disp: false,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map[0xA0] = OpcodeEncodingEntry {
opcode_byte: 0xA0,
opcode_map: 1,
mnemonic: "push",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA1] = OpcodeEncodingEntry {
opcode_byte: 0xA1,
opcode_map: 1,
mnemonic: "pop",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA2] = OpcodeEncodingEntry {
opcode_byte: 0xA2,
opcode_map: 1,
mnemonic: "cpuid",
intel_mnemonic: "CPUID",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA3] = OpcodeEncodingEntry {
opcode_byte: 0xA3,
opcode_map: 1,
mnemonic: "bt",
intel_mnemonic: "BT",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA4] = OpcodeEncodingEntry {
opcode_byte: 0xA4,
opcode_map: 1,
mnemonic: "shld",
intel_mnemonic: "SHLD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA5] = OpcodeEncodingEntry {
opcode_byte: 0xA5,
opcode_map: 1,
mnemonic: "shld",
intel_mnemonic: "SHLD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA8] = OpcodeEncodingEntry {
opcode_byte: 0xA8,
opcode_map: 1,
mnemonic: "push",
intel_mnemonic: "PUSH",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xA9] = OpcodeEncodingEntry {
opcode_byte: 0xA9,
opcode_map: 1,
mnemonic: "pop",
intel_mnemonic: "POP",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAA] = OpcodeEncodingEntry {
opcode_byte: 0xAA,
opcode_map: 1,
mnemonic: "rsm",
intel_mnemonic: "RSM",
operand_class: OpcodeOperandClass::NoModRM,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAB] = OpcodeEncodingEntry {
opcode_byte: 0xAB,
opcode_map: 1,
mnemonic: "bts",
intel_mnemonic: "BTS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAC] = OpcodeEncodingEntry {
opcode_byte: 0xAC,
opcode_map: 1,
mnemonic: "shrd",
intel_mnemonic: "SHRD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAD] = OpcodeEncodingEntry {
opcode_byte: 0xAD,
opcode_map: 1,
mnemonic: "shrd",
intel_mnemonic: "SHRD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAE] = OpcodeEncodingEntry {
opcode_byte: 0xAE,
opcode_map: 1,
mnemonic: "grp15",
intel_mnemonic: "GRP15",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xAF] = OpcodeEncodingEntry {
opcode_byte: 0xAF,
opcode_map: 1,
mnemonic: "imul",
intel_mnemonic: "IMUL",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB0] = OpcodeEncodingEntry {
opcode_byte: 0xB0,
opcode_map: 1,
mnemonic: "cmpxchgb",
intel_mnemonic: "CMPXCHG",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB1] = OpcodeEncodingEntry {
opcode_byte: 0xB1,
opcode_map: 1,
mnemonic: "cmpxchgl",
intel_mnemonic: "CMPXCHG",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB2] = OpcodeEncodingEntry {
opcode_byte: 0xB2,
opcode_map: 1,
mnemonic: "lss",
intel_mnemonic: "LSS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB3] = OpcodeEncodingEntry {
opcode_byte: 0xB3,
opcode_map: 1,
mnemonic: "btr",
intel_mnemonic: "BTR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB4] = OpcodeEncodingEntry {
opcode_byte: 0xB4,
opcode_map: 1,
mnemonic: "lfs",
intel_mnemonic: "LFS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB5] = OpcodeEncodingEntry {
opcode_byte: 0xB5,
opcode_map: 1,
mnemonic: "lgs",
intel_mnemonic: "LGS",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB6] = OpcodeEncodingEntry {
opcode_byte: 0xB6,
opcode_map: 1,
mnemonic: "movzxb",
intel_mnemonic: "MOVZX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xB7] = OpcodeEncodingEntry {
opcode_byte: 0xB7,
opcode_map: 1,
mnemonic: "movzxw",
intel_mnemonic: "MOVZX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBA] = OpcodeEncodingEntry {
opcode_byte: 0xBA,
opcode_map: 1,
mnemonic: "grp8",
intel_mnemonic: "GRP8",
operand_class: OpcodeOperandClass::ModRMDigit(0),
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBB] = OpcodeEncodingEntry {
opcode_byte: 0xBB,
opcode_map: 1,
mnemonic: "btc",
intel_mnemonic: "BTC",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBC] = OpcodeEncodingEntry {
opcode_byte: 0xBC,
opcode_map: 1,
mnemonic: "bsf",
intel_mnemonic: "BSF",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBD] = OpcodeEncodingEntry {
opcode_byte: 0xBD,
opcode_map: 1,
mnemonic: "bsr",
intel_mnemonic: "BSR",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBE] = OpcodeEncodingEntry {
opcode_byte: 0xBE,
opcode_map: 1,
mnemonic: "movsxb",
intel_mnemonic: "MOVSX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xBF] = OpcodeEncodingEntry {
opcode_byte: 0xBF,
opcode_map: 1,
mnemonic: "movsxw",
intel_mnemonic: "MOVSX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xC0] = OpcodeEncodingEntry {
opcode_byte: 0xC0,
opcode_map: 1,
mnemonic: "xaddb",
intel_mnemonic: "XADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xC1] = OpcodeEncodingEntry {
opcode_byte: 0xC1,
opcode_map: 1,
mnemonic: "xaddl",
intel_mnemonic: "XADD",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
for i in 0xC2u8..0xC8u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "sse_cmp",
intel_mnemonic: "SSE",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0xC8u8..0xD0u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "bswap",
intel_mnemonic: "BSWAP",
operand_class: OpcodeOperandClass::OpcodeReg(i & 0x07),
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0xD0u8..0xF0u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "sse3_mmx",
intel_mnemonic: "SSE3/MMX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0xF0u8..0xF8u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "mmx_shift",
intel_mnemonic: "MMX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0xF8u16..0x100u16 {
let i = i as u8;
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 1,
mnemonic: "mmx_arith",
intel_mnemonic: "MMX",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map
}
pub fn build_0f38_opcode_map() -> [OpcodeEncodingEntry; 256] {
let mut map: [OpcodeEncodingEntry; 256] =
std::array::from_fn(|_| OpcodeEncodingEntry::default());
for entry in &mut map {
entry.opcode_map = 2;
}
for i in 0x00u8..0x10u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 2,
mnemonic: "ssse3",
intel_mnemonic: "SSSE3",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x10u8..0x18u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 2,
mnemonic: "sse41_blend",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x20u8..0x30u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 2,
mnemonic: "sse41_pmov",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x30u8..0x40u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 2,
mnemonic: "sse41_int",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x40u8..0x50u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 2,
mnemonic: "sse41_dpps",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map[0xF0] = OpcodeEncodingEntry {
opcode_byte: 0xF0,
opcode_map: 2,
mnemonic: "movbe",
intel_mnemonic: "MOVBE",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map[0xF1] = OpcodeEncodingEntry {
opcode_byte: 0xF1,
opcode_map: 2,
mnemonic: "crc32",
intel_mnemonic: "CRC32",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map
}
pub fn build_0f3a_opcode_map() -> [OpcodeEncodingEntry; 256] {
let mut map: [OpcodeEncodingEntry; 256] =
std::array::from_fn(|_| OpcodeEncodingEntry::default());
for entry in &mut map {
entry.opcode_map = 3;
}
for i in 0x08u8..0x10u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 3,
mnemonic: "sse41_round",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x14u8..0x18u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 3,
mnemonic: "sse41_extract",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x20u8..0x23u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 3,
mnemonic: "sse41_insert",
intel_mnemonic: "SSE4.1",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
for i in 0x60u8..0x64u8 {
map[i as usize] = OpcodeEncodingEntry {
opcode_byte: i,
opcode_map: 3,
mnemonic: "sse42_cmpstr",
intel_mnemonic: "SSE4.2",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
}
map[0xDF] = OpcodeEncodingEntry {
opcode_byte: 0xDF,
opcode_map: 3,
mnemonic: "aeskeygenassist",
intel_mnemonic: "AESKEYGENASSIST",
operand_class: OpcodeOperandClass::ModRMReg,
has_modrm: true,
can_have_sib: true,
has_disp: true,
imm_size: 1,
encoding_form: EncodingForm::Legacy,
..Default::default()
};
map
}
#[derive(Debug, Clone)]
pub struct VexEncodingEntry {
pub opcode_byte: u8,
pub vex_map: u8,
pub mnemonic: &'static str,
pub intel_mnemonic: &'static str,
pub w_bit: u8,
pub l_bit: u8,
pub pp: u8,
pub is_2byte_vex: bool,
}
pub fn get_vex_instructions() -> Vec<VexEncodingEntry> {
vec![
VexEncodingEntry {
opcode_byte: 0x10,
vex_map: 1,
mnemonic: "vmovups",
intel_mnemonic: "VMOVUPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x11,
vex_map: 1,
mnemonic: "vmovups",
intel_mnemonic: "VMOVUPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x12,
vex_map: 1,
mnemonic: "vmovlps",
intel_mnemonic: "VMOVLPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x14,
vex_map: 1,
mnemonic: "vunpcklps",
intel_mnemonic: "VUNPCKLPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x15,
vex_map: 1,
mnemonic: "vunpckhps",
intel_mnemonic: "VUNPCKHPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x16,
vex_map: 1,
mnemonic: "vmovhps",
intel_mnemonic: "VMOVHPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x28,
vex_map: 1,
mnemonic: "vmovaps",
intel_mnemonic: "VMOVAPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x29,
vex_map: 1,
mnemonic: "vmovaps",
intel_mnemonic: "VMOVAPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x50,
vex_map: 1,
mnemonic: "vmovmskps",
intel_mnemonic: "VMOVMSKPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x51,
vex_map: 1,
mnemonic: "vsqrtps",
intel_mnemonic: "VSQRTPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x52,
vex_map: 1,
mnemonic: "vrsqrtps",
intel_mnemonic: "VRSQRTPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x53,
vex_map: 1,
mnemonic: "vrcpps",
intel_mnemonic: "VRCPPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x54,
vex_map: 1,
mnemonic: "vandps",
intel_mnemonic: "VANDPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x55,
vex_map: 1,
mnemonic: "vandnps",
intel_mnemonic: "VANDNPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x56,
vex_map: 1,
mnemonic: "vorps",
intel_mnemonic: "VORPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x57,
vex_map: 1,
mnemonic: "vxorps",
intel_mnemonic: "VXORPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x58,
vex_map: 1,
mnemonic: "vaddps",
intel_mnemonic: "VADDPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x59,
vex_map: 1,
mnemonic: "vmulps",
intel_mnemonic: "VMULPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5A,
vex_map: 1,
mnemonic: "vcvtps2pd",
intel_mnemonic: "VCVTPS2PD",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5B,
vex_map: 1,
mnemonic: "vcvtdq2ps",
intel_mnemonic: "VCVTDQ2PS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5C,
vex_map: 1,
mnemonic: "vsubps",
intel_mnemonic: "VSUBPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5D,
vex_map: 1,
mnemonic: "vminps",
intel_mnemonic: "VMINPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5E,
vex_map: 1,
mnemonic: "vdivps",
intel_mnemonic: "VDIVPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5F,
vex_map: 1,
mnemonic: "vmaxps",
intel_mnemonic: "VMAXPS",
w_bit: 0,
l_bit: 0,
pp: 0,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x10,
vex_map: 1,
mnemonic: "vmovupd",
intel_mnemonic: "VMOVUPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x14,
vex_map: 1,
mnemonic: "vunpcklpd",
intel_mnemonic: "VUNPCKLPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x15,
vex_map: 1,
mnemonic: "vunpckhpd",
intel_mnemonic: "VUNPCKHPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x28,
vex_map: 1,
mnemonic: "vmovapd",
intel_mnemonic: "VMOVAPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x54,
vex_map: 1,
mnemonic: "vandpd",
intel_mnemonic: "VANDPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x58,
vex_map: 1,
mnemonic: "vaddpd",
intel_mnemonic: "VADDPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x59,
vex_map: 1,
mnemonic: "vmulpd",
intel_mnemonic: "VMULPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5C,
vex_map: 1,
mnemonic: "vsubpd",
intel_mnemonic: "VSUBPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5E,
vex_map: 1,
mnemonic: "vdivpd",
intel_mnemonic: "VDIVPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x10,
vex_map: 1,
mnemonic: "vmovss",
intel_mnemonic: "VMOVSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x51,
vex_map: 1,
mnemonic: "vsqrtss",
intel_mnemonic: "VSQRTSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x58,
vex_map: 1,
mnemonic: "vaddss",
intel_mnemonic: "VADDSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x59,
vex_map: 1,
mnemonic: "vmulss",
intel_mnemonic: "VMULSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5C,
vex_map: 1,
mnemonic: "vsubss",
intel_mnemonic: "VSUBSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5E,
vex_map: 1,
mnemonic: "vdivss",
intel_mnemonic: "VDIVSS",
w_bit: 0,
l_bit: 0,
pp: 2,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x10,
vex_map: 1,
mnemonic: "vmovsd",
intel_mnemonic: "VMOVSD",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x51,
vex_map: 1,
mnemonic: "vsqrtsd",
intel_mnemonic: "VSQRTSD",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x58,
vex_map: 1,
mnemonic: "vaddsd",
intel_mnemonic: "VADDSD",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x59,
vex_map: 1,
mnemonic: "vmulsd",
intel_mnemonic: "VMULSD",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x5C,
vex_map: 1,
mnemonic: "vsubsd",
intel_mnemonic: "VSUBSD",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: true,
},
VexEncodingEntry {
opcode_byte: 0x00,
vex_map: 2,
mnemonic: "vpshufb",
intel_mnemonic: "VPSHUFB",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x01,
vex_map: 2,
mnemonic: "vphaddw",
intel_mnemonic: "VPHADDW",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x02,
vex_map: 2,
mnemonic: "vphaddd",
intel_mnemonic: "VPHADDD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x10,
vex_map: 2,
mnemonic: "vpblendvb",
intel_mnemonic: "VPBLENDVB",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x13,
vex_map: 2,
mnemonic: "vcvtph2ps",
intel_mnemonic: "VCVTPH2PS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x17,
vex_map: 2,
mnemonic: "vptest",
intel_mnemonic: "VPTEST",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x20,
vex_map: 2,
mnemonic: "vpmovsxbw",
intel_mnemonic: "VPMOVSXBW",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x28,
vex_map: 2,
mnemonic: "vpmuldq",
intel_mnemonic: "VPMULDQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x29,
vex_map: 2,
mnemonic: "vpcmpeqq",
intel_mnemonic: "VPCMPEQQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x37,
vex_map: 2,
mnemonic: "vpcmpgtq",
intel_mnemonic: "VPCMPGTQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x40,
vex_map: 2,
mnemonic: "vpmulld",
intel_mnemonic: "VPMULLD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x58,
vex_map: 2,
mnemonic: "vpbroadcastd",
intel_mnemonic: "VPBROADCASTD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x59,
vex_map: 2,
mnemonic: "vpbroadcastq",
intel_mnemonic: "VPBROADCASTQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x78,
vex_map: 2,
mnemonic: "vpbroadcastb",
intel_mnemonic: "VPBROADCASTB",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x79,
vex_map: 2,
mnemonic: "vpbroadcastw",
intel_mnemonic: "VPBROADCASTW",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x8C,
vex_map: 2,
mnemonic: "vpmaskmovd",
intel_mnemonic: "VPMASKMOVD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x90,
vex_map: 2,
mnemonic: "vpgatherdd",
intel_mnemonic: "VPGATHERDD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x91,
vex_map: 2,
mnemonic: "vpgatherdq",
intel_mnemonic: "VPGATHERDQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x92,
vex_map: 2,
mnemonic: "vpgatherqd",
intel_mnemonic: "VPGATHERQD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x96,
vex_map: 2,
mnemonic: "vfmaddsub132ps",
intel_mnemonic: "VFMADDSUB132PS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x98,
vex_map: 2,
mnemonic: "vfmadd132ps",
intel_mnemonic: "VFMADD132PS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xA6,
vex_map: 2,
mnemonic: "vfmaddsub213ps",
intel_mnemonic: "VFMADDSUB213PS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xB6,
vex_map: 2,
mnemonic: "vfmaddsub231ps",
intel_mnemonic: "VFMADDSUB231PS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDB,
vex_map: 2,
mnemonic: "vaesimc",
intel_mnemonic: "VAESIMC",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDC,
vex_map: 2,
mnemonic: "vaesenc",
intel_mnemonic: "VAESENC",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDD,
vex_map: 2,
mnemonic: "vaesenclast",
intel_mnemonic: "VAESENCLAST",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDE,
vex_map: 2,
mnemonic: "vaesdec",
intel_mnemonic: "VAESDEC",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDF,
vex_map: 2,
mnemonic: "vaesdeclast",
intel_mnemonic: "VAESDECLAST",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x98,
vex_map: 2,
mnemonic: "vfmadd132ps",
intel_mnemonic: "VFMADD132PS",
w_bit: 0,
l_bit: 0,
pp: 3,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x08,
vex_map: 3,
mnemonic: "vroundps",
intel_mnemonic: "VROUNDPS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x09,
vex_map: 3,
mnemonic: "vroundpd",
intel_mnemonic: "VROUNDPD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x0A,
vex_map: 3,
mnemonic: "vroundss",
intel_mnemonic: "VROUNDSS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x0B,
vex_map: 3,
mnemonic: "vroundsd",
intel_mnemonic: "VROUNDSD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x14,
vex_map: 3,
mnemonic: "vpextrb",
intel_mnemonic: "VPEXTRB",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x16,
vex_map: 3,
mnemonic: "vpextrd",
intel_mnemonic: "VPEXTRD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x20,
vex_map: 3,
mnemonic: "vpinsrb",
intel_mnemonic: "VPINSRB",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x22,
vex_map: 3,
mnemonic: "vpinsrd",
intel_mnemonic: "VPINSRD",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x40,
vex_map: 3,
mnemonic: "vdpps",
intel_mnemonic: "VDPPS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x44,
vex_map: 3,
mnemonic: "vpclmulqdq",
intel_mnemonic: "VPCLMULQDQ",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x4A,
vex_map: 3,
mnemonic: "vblendvps",
intel_mnemonic: "VBLENDVPS",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x60,
vex_map: 3,
mnemonic: "vpcmpestrm",
intel_mnemonic: "VPCMPESTRM",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0x62,
vex_map: 3,
mnemonic: "vpcmpistrm",
intel_mnemonic: "VPCMPISTRM",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
VexEncodingEntry {
opcode_byte: 0xDF,
vex_map: 3,
mnemonic: "vaeskeygenassist",
intel_mnemonic: "VAESKEYGENASSIST",
w_bit: 0,
l_bit: 0,
pp: 1,
is_2byte_vex: false,
},
]
}
#[derive(Debug, Clone)]
pub struct EvexEncodingEntry {
pub opcode_byte: u8,
pub evex_map: u8,
pub mnemonic: &'static str,
pub intel_mnemonic: &'static str,
pub w_bit: u8,
pub ll: u8,
pub pp: u8,
pub has_mask: bool,
pub has_zeroing: bool,
}
pub fn get_evex_instructions() -> Vec<EvexEncodingEntry> {
vec![
EvexEncodingEntry {
opcode_byte: 0x10,
evex_map: 1,
mnemonic: "vmovups",
intel_mnemonic: "VMOVUPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x28,
evex_map: 1,
mnemonic: "vmovaps",
intel_mnemonic: "VMOVAPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x54,
evex_map: 1,
mnemonic: "vandps",
intel_mnemonic: "VANDPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x55,
evex_map: 1,
mnemonic: "vandnps",
intel_mnemonic: "VANDNPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x56,
evex_map: 1,
mnemonic: "vorps",
intel_mnemonic: "VORPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x57,
evex_map: 1,
mnemonic: "vxorps",
intel_mnemonic: "VXORPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x58,
evex_map: 1,
mnemonic: "vaddps",
intel_mnemonic: "VADDPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x59,
evex_map: 1,
mnemonic: "vmulps",
intel_mnemonic: "VMULPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x5C,
evex_map: 1,
mnemonic: "vsubps",
intel_mnemonic: "VSUBPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x5E,
evex_map: 1,
mnemonic: "vdivps",
intel_mnemonic: "VDIVPS",
w_bit: 0,
ll: 0,
pp: 0,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x6E,
evex_map: 1,
mnemonic: "vmovd",
intel_mnemonic: "VMOVD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: false,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x7E,
evex_map: 1,
mnemonic: "vmovq",
intel_mnemonic: "VMOVQ",
w_bit: 0,
ll: 0,
pp: 2,
has_mask: false,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x00,
evex_map: 2,
mnemonic: "vpshufb",
intel_mnemonic: "VPSHUFB",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x13,
evex_map: 2,
mnemonic: "vcvtph2ps",
intel_mnemonic: "VCVTPH2PS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x1D,
evex_map: 2,
mnemonic: "vcvtps2ph",
intel_mnemonic: "VCVTPS2PH",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x26,
evex_map: 2,
mnemonic: "vptestmb",
intel_mnemonic: "VPTESTMB",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x27,
evex_map: 2,
mnemonic: "vptestmw",
intel_mnemonic: "VPTESTMW",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x40,
evex_map: 2,
mnemonic: "vpmulld",
intel_mnemonic: "VPMULLD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x47,
evex_map: 2,
mnemonic: "vpsllvd",
intel_mnemonic: "VPSLLVD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x4C,
evex_map: 2,
mnemonic: "vrcp14ps",
intel_mnemonic: "VRCP14PS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x55,
evex_map: 2,
mnemonic: "vpopcntd",
intel_mnemonic: "VPOPCNTD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x58,
evex_map: 2,
mnemonic: "vpbroadcastd",
intel_mnemonic: "VPBROADCASTD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x64,
evex_map: 2,
mnemonic: "vpblendmd",
intel_mnemonic: "VPBLENDMD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x65,
evex_map: 2,
mnemonic: "vpblendmq",
intel_mnemonic: "VPBLENDMQ",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x75,
evex_map: 2,
mnemonic: "vpermi2b",
intel_mnemonic: "VPERMI2B",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x76,
evex_map: 2,
mnemonic: "vpermi2w",
intel_mnemonic: "VPERMI2W",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x7D,
evex_map: 2,
mnemonic: "vpermt2b",
intel_mnemonic: "VPERMT2B",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x83,
evex_map: 2,
mnemonic: "vpmultishiftqb",
intel_mnemonic: "VPMULTISHIFTQB",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x8C,
evex_map: 2,
mnemonic: "vpmaskmovd",
intel_mnemonic: "VPMASKMOVD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: false,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x90,
evex_map: 2,
mnemonic: "vpgatherdd",
intel_mnemonic: "VPGATHERDD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0xA6,
evex_map: 2,
mnemonic: "vfmaddsub213ps",
intel_mnemonic: "VFMADDSUB213PS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0xB4,
evex_map: 2,
mnemonic: "vpmadd52luq",
intel_mnemonic: "VPMADD52LUQ",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0xC6,
evex_map: 2,
mnemonic: "vpexpandd",
intel_mnemonic: "VPEXPANDD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0xC8,
evex_map: 2,
mnemonic: "vexpandps",
intel_mnemonic: "VEXPANDPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0xCA,
evex_map: 2,
mnemonic: "vcompressps",
intel_mnemonic: "VCOMPRESSPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0xCB,
evex_map: 2,
mnemonic: "vrcp28ps",
intel_mnemonic: "VRCP28PS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0xCC,
evex_map: 2,
mnemonic: "vrsqrt28ps",
intel_mnemonic: "VRSQRT28PS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x08,
evex_map: 3,
mnemonic: "vrndscaleps",
intel_mnemonic: "VRNDSCALEPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x09,
evex_map: 3,
mnemonic: "vrndscalepd",
intel_mnemonic: "VRNDSCALEPD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x14,
evex_map: 3,
mnemonic: "vpextrb",
intel_mnemonic: "VPEXTRB",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: false,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x18,
evex_map: 3,
mnemonic: "vinsertf32x4",
intel_mnemonic: "VINSERTF32X4",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x1A,
evex_map: 3,
mnemonic: "vinsertf64x2",
intel_mnemonic: "VINSERTF64X2",
w_bit: 1,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x1D,
evex_map: 3,
mnemonic: "vcvtps2ph",
intel_mnemonic: "VCVTPS2PH",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x20,
evex_map: 3,
mnemonic: "vpinsrb",
intel_mnemonic: "VPINSRB",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: false,
has_zeroing: false,
},
EvexEncodingEntry {
opcode_byte: 0x25,
evex_map: 3,
mnemonic: "vpternlogd",
intel_mnemonic: "VPTERNLOGD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x26,
evex_map: 3,
mnemonic: "vgetmantps",
intel_mnemonic: "VGETMANTPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x27,
evex_map: 3,
mnemonic: "vgetmantpd",
intel_mnemonic: "VGETMANTPD",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x38,
evex_map: 3,
mnemonic: "vinserti64x2",
intel_mnemonic: "VINSERTI64X2",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x42,
evex_map: 3,
mnemonic: "vdbpsadbw",
intel_mnemonic: "VDBPSADBW",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x43,
evex_map: 3,
mnemonic: "vshuff32x4",
intel_mnemonic: "VSHUFF32X4",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x44,
evex_map: 3,
mnemonic: "vpclmulqdq",
intel_mnemonic: "VPCLMULQDQ",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x50,
evex_map: 3,
mnemonic: "vrangeps",
intel_mnemonic: "VRANGEPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x54,
evex_map: 3,
mnemonic: "vfixupimmps",
intel_mnemonic: "VFIXUPIMMPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
EvexEncodingEntry {
opcode_byte: 0x56,
evex_map: 3,
mnemonic: "vreduceps",
intel_mnemonic: "VREDUCEPS",
w_bit: 0,
ll: 0,
pp: 1,
has_mask: true,
has_zeroing: true,
},
]
}
#[derive(Debug, Clone)]
pub struct XopEncodingEntry {
pub opcode_byte: u8,
pub xop_map: u8, pub mnemonic: &'static str,
pub intel_mnemonic: &'static str,
pub pp: u8,
}
pub fn get_xop_instructions() -> Vec<XopEncodingEntry> {
vec![
XopEncodingEntry {
opcode_byte: 0x90,
xop_map: 8,
mnemonic: "vpmacsdd",
intel_mnemonic: "VPMACSDD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x91,
xop_map: 8,
mnemonic: "vpmacssdd",
intel_mnemonic: "VPMACSSDD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x92,
xop_map: 8,
mnemonic: "vpmacsdqh",
intel_mnemonic: "VPMACSDQH",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x94,
xop_map: 8,
mnemonic: "vpmacswd",
intel_mnemonic: "VPMACSWD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x95,
xop_map: 8,
mnemonic: "vpmacsswd",
intel_mnemonic: "VPMACSSWD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x96,
xop_map: 8,
mnemonic: "vpmadcsswd",
intel_mnemonic: "VPMADCSSWD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x9E,
xop_map: 8,
mnemonic: "vpmadcswd",
intel_mnemonic: "VPMADCSWD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0xA6,
xop_map: 8,
mnemonic: "vphaddbw",
intel_mnemonic: "VPHADDBW",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0xC0,
xop_map: 8,
mnemonic: "vprotb",
intel_mnemonic: "VPROTB",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0xC2,
xop_map: 8,
mnemonic: "vprotd",
intel_mnemonic: "VPROTD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0xCC,
xop_map: 8,
mnemonic: "vpcomb",
intel_mnemonic: "VPCOMB",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x01,
xop_map: 9,
mnemonic: "vpermil2ps",
intel_mnemonic: "VPERMIL2PS",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x02,
xop_map: 9,
mnemonic: "vpermil2pd",
intel_mnemonic: "VPERMIL2PD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x80,
xop_map: 9,
mnemonic: "vfrczps",
intel_mnemonic: "VFRCZPS",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x81,
xop_map: 9,
mnemonic: "vfrczpd",
intel_mnemonic: "VFRCZPD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x82,
xop_map: 9,
mnemonic: "vfrczss",
intel_mnemonic: "VFRCZSS",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x90,
xop_map: 9,
mnemonic: "vprotb_imm",
intel_mnemonic: "VPROTB",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x92,
xop_map: 9,
mnemonic: "vprotd_imm",
intel_mnemonic: "VPROTD",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x93,
xop_map: 9,
mnemonic: "vprotq_imm",
intel_mnemonic: "VPROTQ",
pp: 0,
},
XopEncodingEntry {
opcode_byte: 0x12,
xop_map: 10,
mnemonic: "vphaddbd",
intel_mnemonic: "VPHADDBD",
pp: 0,
},
]
}
#[derive(Debug, Clone)]
pub struct ThreeDNowEntry {
pub opcode_byte: u8,
pub mnemonic: &'static str,
pub intel_mnemonic: &'static str,
}
pub fn get_3dnow_instructions() -> Vec<ThreeDNowEntry> {
vec![
ThreeDNowEntry {
opcode_byte: 0x0C,
mnemonic: "pi2fw",
intel_mnemonic: "PI2FW",
},
ThreeDNowEntry {
opcode_byte: 0x0D,
mnemonic: "pi2fd",
intel_mnemonic: "PI2FD",
},
ThreeDNowEntry {
opcode_byte: 0x1C,
mnemonic: "pf2iw",
intel_mnemonic: "PF2IW",
},
ThreeDNowEntry {
opcode_byte: 0x1D,
mnemonic: "pf2id",
intel_mnemonic: "PF2ID",
},
ThreeDNowEntry {
opcode_byte: 0x8A,
mnemonic: "pfnacc",
intel_mnemonic: "PFNACC",
},
ThreeDNowEntry {
opcode_byte: 0x8E,
mnemonic: "pfpnacc",
intel_mnemonic: "PFPNACC",
},
ThreeDNowEntry {
opcode_byte: 0x90,
mnemonic: "pfcmpge",
intel_mnemonic: "PFCMPGE",
},
ThreeDNowEntry {
opcode_byte: 0x94,
mnemonic: "pfmin",
intel_mnemonic: "PFMIN",
},
ThreeDNowEntry {
opcode_byte: 0x96,
mnemonic: "pfrcp",
intel_mnemonic: "PFRCP",
},
ThreeDNowEntry {
opcode_byte: 0x97,
mnemonic: "pfrsqrt",
intel_mnemonic: "PFRSQRT",
},
ThreeDNowEntry {
opcode_byte: 0x9A,
mnemonic: "pfsub",
intel_mnemonic: "PFSUB",
},
ThreeDNowEntry {
opcode_byte: 0x9E,
mnemonic: "pfadd",
intel_mnemonic: "PFADD",
},
ThreeDNowEntry {
opcode_byte: 0xA0,
mnemonic: "pfcmpgt",
intel_mnemonic: "PFCMPGT",
},
ThreeDNowEntry {
opcode_byte: 0xA4,
mnemonic: "pfmax",
intel_mnemonic: "PFMAX",
},
ThreeDNowEntry {
opcode_byte: 0xA6,
mnemonic: "pfrcpit1",
intel_mnemonic: "PFRCPIT1",
},
ThreeDNowEntry {
opcode_byte: 0xA7,
mnemonic: "pfrsqit1",
intel_mnemonic: "PFRSQIT1",
},
ThreeDNowEntry {
opcode_byte: 0xAA,
mnemonic: "pfsubr",
intel_mnemonic: "PFSUBR",
},
ThreeDNowEntry {
opcode_byte: 0xAE,
mnemonic: "pfacc",
intel_mnemonic: "PFACC",
},
ThreeDNowEntry {
opcode_byte: 0xB0,
mnemonic: "pfcmpeq",
intel_mnemonic: "PFCMPEQ",
},
ThreeDNowEntry {
opcode_byte: 0xB4,
mnemonic: "pfmul",
intel_mnemonic: "PFMUL",
},
ThreeDNowEntry {
opcode_byte: 0xB6,
mnemonic: "pfrcpit2",
intel_mnemonic: "PFRCPIT2",
},
ThreeDNowEntry {
opcode_byte: 0xB7,
mnemonic: "pmulhrw",
intel_mnemonic: "PMULHRW",
},
]
}
pub fn build_modrm(mod_field: u8, reg: u8, rm: u8) -> u8 {
((mod_field & 0x03) << 6) | ((reg & 0x07) << 3) | (rm & 0x07)
}
pub fn build_sib(scale: u8, index: u8, base: u8) -> u8 {
((scale & 0x03) << 6) | ((index & 0x07) << 3) | (base & 0x07)
}
pub fn encode_displacement(disp: i64, size: u8) -> Vec<u8> {
match size {
0 => vec![],
1 => vec![disp as u8],
2 => (disp as i16).to_le_bytes().to_vec(),
4 => (disp as i32).to_le_bytes().to_vec(),
8 => disp.to_le_bytes().to_vec(),
_ => vec![],
}
}
pub fn encode_immediate(imm: i64, size: u8) -> Vec<u8> {
match size {
0 => vec![],
1 => vec![imm as u8],
2 => (imm as i16).to_le_bytes().to_vec(),
3 => {
let bytes = (imm as i32).to_le_bytes();
vec![bytes[0], bytes[1], bytes[2]]
}
4 => (imm as i32).to_le_bytes().to_vec(),
8 => imm.to_le_bytes().to_vec(),
_ => vec![],
}
}
pub fn disp_size_bytes(disp: i64) -> u8 {
if disp == 0 {
return 0;
}
if disp >= i8::MIN as i64 && disp <= i8::MAX as i64 {
return 1;
}
4
}
pub fn mod_for_disp(disp: i64) -> u8 {
if disp == 0 {
0 } else if disp >= i8::MIN as i64 && disp <= i8::MAX as i64 {
1 } else {
2 }
}
pub fn compute_instruction_length(
entry: &OpcodeEncodingEntry,
mode: X86Mode,
use_rex: bool,
use_sib: bool,
disp_size: u8,
imm_size: u8,
) -> u32 {
let mut length: u32 = 0;
if entry.mandatory_prefix != 0 {
length += 1; }
if use_rex {
length += 1;
}
match entry.opcode_map {
0 => length += 1, 1 => length += 2, 2 | 3 => length += 3, _ => length += 1,
}
if entry.has_modrm {
length += 1;
}
if use_sib {
length += 1;
}
if disp_size > 0 {
length += disp_size as u32;
}
if imm_size > 0 {
length += imm_size as u32;
}
length
}
pub fn compute_vex_length(
entry: &VexEncodingEntry,
use_sib: bool,
disp_size: u8,
imm_size: u8,
) -> u32 {
let mut length: u32 = 0;
if entry.is_2byte_vex {
length += 2;
} else {
length += 3;
}
length += 1;
length += 1;
if use_sib {
length += 1;
}
if disp_size > 0 {
length += disp_size as u32;
}
if imm_size > 0 {
length += imm_size as u32;
}
length
}
pub fn compute_evex_length(
_entry: &EvexEncodingEntry,
use_sib: bool,
disp_size: u8,
imm_size: u8,
) -> u32 {
let mut length: u32 = 0;
length += 4;
length += 1;
length += 1;
if use_sib {
length += 1;
}
if disp_size > 0 {
length += disp_size as u32;
}
if imm_size > 0 {
length += imm_size as u32;
}
length
}
#[derive(Debug, Clone)]
pub struct EncodeValidation {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub computed_length: u32,
}
impl EncodeValidation {
pub fn new() -> Self {
EncodeValidation {
is_valid: true,
errors: Vec::new(),
warnings: Vec::new(),
computed_length: 0,
}
}
pub fn add_error(&mut self, msg: &str) {
self.is_valid = false;
self.errors.push(msg.to_string());
}
pub fn add_warning(&mut self, msg: &str) {
self.warnings.push(msg.to_string());
}
}
pub fn validate_encoded_bytes(
bytes: &[u8],
entry: &OpcodeEncodingEntry,
mode: X86Mode,
) -> EncodeValidation {
let mut result = EncodeValidation::new();
result.computed_length = bytes.len() as u32;
if bytes.is_empty() {
result.add_error("empty byte sequence");
return result;
}
if bytes.len() < entry.opcode_map as usize + 1 {
result.add_error("byte sequence too short for opcode map");
return result;
}
if entry.opcode_map > 0 && entry.mandatory_prefix != 0 {
let prefix_byte = match entry.mandatory_prefix {
1 => 0x66u8,
2 => 0xF3u8,
3 => 0xF2u8,
_ => 0x00,
};
if prefix_byte != 0 {
let has_prefix = bytes.iter().any(|&b| b == prefix_byte);
if !has_prefix {
result.add_warning(&format!(
"expected mandatory prefix 0x{:02X} not found",
prefix_byte
));
}
}
}
if mode.is_64bit() {
for &byte in bytes.iter() {
if byte >= 0x40 && byte <= 0x4F {
if byte & 0xF0 != 0x40 {
result.add_warning("invalid REX prefix format");
}
break;
}
}
}
if entry.has_modrm && bytes.len() >= 1 {
let min_len = compute_instruction_length(entry, mode, false, false, 0, entry.imm_size);
if bytes.len() < min_len as usize {
result.add_warning(&format!(
"instruction length {} less than minimum expected {}",
bytes.len(),
min_len
));
}
}
if entry.mnemonic == "invalid" || entry.mnemonic == "ud2" {
result.add_warning("encoding intentionally invalid or undefined instruction");
}
result
}
pub fn validate_vex_bytes(bytes: &[u8], entry: &VexEncodingEntry) -> EncodeValidation {
let mut result = EncodeValidation::new();
result.computed_length = bytes.len() as u32;
if bytes.len() < 4 {
result.add_error("VEX instruction too short");
return result;
}
let first_byte = bytes[0];
if first_byte != 0xC4 && first_byte != 0xC5 {
result.add_error(&format!(
"invalid VEX prefix byte 0x{:02X} (expected C4 or C5)",
first_byte
));
}
if entry.is_2byte_vex && first_byte != 0xC5 {
result.add_warning("expected 2-byte VEX prefix C5 but got C4");
}
if !entry.is_2byte_vex && first_byte != 0xC4 {
result.add_warning("expected 3-byte VEX prefix C4 but got C5");
}
result
}
pub fn validate_evex_bytes(bytes: &[u8], _entry: &EvexEncodingEntry) -> EncodeValidation {
let mut result = EncodeValidation::new();
result.computed_length = bytes.len() as u32;
if bytes.len() < 6 {
result.add_error("EVEX instruction too short");
return result;
}
if bytes[0] != 0x62 {
result.add_error(&format!(
"invalid EVEX prefix byte 0x{:02X} (expected 62)",
bytes[0]
));
}
if bytes.len() >= 3 {
let p1 = bytes[2];
if (p1 & 0x04) == 0 {
result.add_error("EVEX P1 bit 2 must be set to 1");
}
}
result
}
pub struct X86FullMCEncoderFull {
pub primary_map: [OpcodeEncodingEntry; 256],
pub two_byte_map: [OpcodeEncodingEntry; 256],
pub of38_map: [OpcodeEncodingEntry; 256],
pub of3a_map: [OpcodeEncodingEntry; 256],
pub vex_instructions: Vec<VexEncodingEntry>,
pub evex_instructions: Vec<EvexEncodingEntry>,
pub xop_instructions: Vec<XopEncodingEntry>,
pub three_dnow_instructions: Vec<ThreeDNowEntry>,
pub mode: X86Mode,
}
impl X86FullMCEncoderFull {
pub fn new(mode: X86Mode) -> Self {
X86FullMCEncoderFull {
primary_map: build_primary_opcode_map(),
two_byte_map: build_two_byte_opcode_map(),
of38_map: build_0f38_opcode_map(),
of3a_map: build_0f3a_opcode_map(),
vex_instructions: get_vex_instructions(),
evex_instructions: get_evex_instructions(),
xop_instructions: get_xop_instructions(),
three_dnow_instructions: get_3dnow_instructions(),
mode,
}
}
pub fn lookup_primary(&self, opcode: u8) -> &OpcodeEncodingEntry {
&self.primary_map[opcode as usize]
}
pub fn lookup_two_byte(&self, opcode: u8) -> &OpcodeEncodingEntry {
&self.two_byte_map[opcode as usize]
}
pub fn lookup_0f38(&self, opcode: u8) -> &OpcodeEncodingEntry {
&self.of38_map[opcode as usize]
}
pub fn lookup_0f3a(&self, opcode: u8) -> &OpcodeEncodingEntry {
&self.of3a_map[opcode as usize]
}
pub fn encode_reg_reg(
&self,
opcode_byte: u8,
dst_reg: u8,
src_reg: u8,
rex_w: bool,
) -> Vec<u8> {
let mut bytes = Vec::new();
let entry = self.lookup_primary(opcode_byte);
if self.mode.is_64bit() {
let rex = 0x40
| if rex_w { 0x08 } else { 0 }
| if dst_reg >= 8 { 0x04 } else { 0 }
| if src_reg >= 8 { 0x01 } else { 0 };
if rex != 0x40 || rex_w {
bytes.push(rex);
}
}
bytes.push(opcode_byte);
let modrm = build_modrm(0b11, src_reg & 0x07, dst_reg & 0x07);
bytes.push(modrm);
bytes
}
pub fn encode_modrm_imm(
&self,
opcode_byte: u8,
reg_op: u8,
rm_op: u8,
mod_bits: u8,
imm: i64,
imm_size: u8,
rex_w: bool,
) -> Vec<u8> {
let mut bytes = Vec::new();
if self.mode.is_64bit() {
let rex = 0x40
| if rex_w { 0x08 } else { 0 }
| if reg_op >= 8 { 0x04 } else { 0 }
| if rm_op >= 8 { 0x01 } else { 0 };
if rex != 0x40 || rex_w {
bytes.push(rex);
}
}
bytes.push(opcode_byte);
let modrm = build_modrm(mod_bits, reg_op & 0x07, rm_op & 0x07);
bytes.push(modrm);
let imm_bytes = encode_immediate(imm, imm_size);
bytes.extend_from_slice(&imm_bytes);
bytes
}
pub fn encode_legacy_instruction(
&self,
entry: &OpcodeEncodingEntry,
reg: u8,
rm: u8,
mod_bits: u8,
disp: i64,
imm: i64,
rex: bool,
) -> Vec<u8> {
let mut bytes = Vec::new();
if entry.mandatory_prefix != 0 {
let prefix = match entry.mandatory_prefix {
1 => 0x66,
2 => 0xF3,
3 => 0xF2,
_ => 0x00,
};
if prefix != 0 {
bytes.push(prefix);
}
}
if rex || self.mode.is_64bit() {
let rex_byte = 0x40
| if entry.requires_rex_w { 0x08 } else { 0 }
| if reg >= 8 { 0x04 } else { 0 }
| if rm >= 8 { 0x01 } else { 0 };
if rex_byte != 0x40 || entry.requires_rex_w {
bytes.push(rex_byte);
}
}
match entry.opcode_map {
0 => bytes.push(entry.opcode_byte),
1 => {
bytes.push(0x0F);
bytes.push(entry.opcode_byte);
}
2 => {
bytes.push(0x0F);
bytes.push(0x38);
bytes.push(entry.opcode_byte);
}
3 => {
bytes.push(0x0F);
bytes.push(0x3A);
bytes.push(entry.opcode_byte);
}
_ => bytes.push(entry.opcode_byte),
}
if entry.has_modrm {
let modrm = match entry.operand_class {
OpcodeOperandClass::ModRMReg => build_modrm(mod_bits, reg & 0x07, rm & 0x07),
OpcodeOperandClass::ModRMDigit(digit) => build_modrm(mod_bits, digit, rm & 0x07),
_ => build_modrm(mod_bits, 0, rm & 0x07),
};
bytes.push(modrm);
}
let disp_size = if entry.has_disp {
disp_size_bytes(disp)
} else {
0
};
let disp_bytes = encode_displacement(disp, disp_size);
bytes.extend_from_slice(&disp_bytes);
let imm_bytes = encode_immediate(imm, entry.imm_size);
bytes.extend_from_slice(&imm_bytes);
bytes
}
pub fn encode_vex_instruction(
&self,
entry: &VexEncodingEntry,
vvvv: u8,
reg: u8,
rm: u8,
mod_bits: u8,
disp: i64,
imm: i64,
imm_size: u8,
l_bit: bool,
) -> Vec<u8> {
let mut bytes = Vec::new();
let w_bit = entry.w_bit != 0;
let r_bit = reg >= 8;
let x_bit = false; let b_bit = rm >= 8;
if entry.is_2byte_vex && !x_bit && !b_bit && !w_bit {
let vex1 = 0xC5;
let vex2 = ((!r_bit as u8) << 7)
| ((!vvvv & 0x0F) << 3)
| ((l_bit as u8) << 2)
| (entry.pp & 0x03);
bytes.push(vex1);
bytes.push(vex2);
} else {
let vex1 = 0xC4;
let vex2 = ((!r_bit as u8) << 7)
| ((!x_bit as u8) << 6)
| ((!b_bit as u8) << 5)
| (entry.vex_map & 0x1F);
let vex3 = ((w_bit as u8) << 7)
| ((!vvvv & 0x0F) << 3)
| ((l_bit as u8) << 2)
| (entry.pp & 0x03);
bytes.push(vex1);
bytes.push(vex2);
bytes.push(vex3);
}
bytes.push(entry.opcode_byte);
let modrm = build_modrm(mod_bits, reg & 0x07, rm & 0x07);
bytes.push(modrm);
if mod_bits != 0b11 {
let disp_size = disp_size_bytes(disp);
let disp_bytes = encode_displacement(disp, disp_size);
bytes.extend_from_slice(&disp_bytes);
}
if imm_size > 0 {
let imm_bytes = encode_immediate(imm, imm_size);
bytes.extend_from_slice(&imm_bytes);
}
bytes
}
pub fn encode_evex_instruction(
&self,
entry: &EvexEncodingEntry,
vvvv: u8,
reg: u8,
rm: u8,
mod_bits: u8,
disp: i64,
imm: i64,
imm_size: u8,
aaa: u8,
z_bit: bool,
) -> Vec<u8> {
let mut bytes = Vec::new();
let w_bit = entry.w_bit != 0;
let r_bit = reg >= 8;
let x_bit = false;
let b_bit = rm >= 8;
let r_prime = false;
let b_prime = false;
bytes.push(0x62);
let p0 = ((!r_bit as u8) << 7)
| ((!x_bit as u8) << 6)
| ((!b_bit as u8) << 5)
| ((!r_prime as u8) << 4)
| (entry.evex_map & 0x07);
bytes.push(p0);
let p1 = ((w_bit as u8) << 7)
| ((!vvvv & 0x0F) << 3)
| 0x04 | (entry.pp & 0x03);
bytes.push(p1);
let p2 = ((z_bit as u8) << 7)
| ((entry.ll & 0x03) << 5)
| ((b_prime as u8) << 4)
| 0x08 | (aaa & 0x07);
bytes.push(p2);
bytes.push(entry.opcode_byte);
let modrm = build_modrm(mod_bits, reg & 0x07, rm & 0x07);
bytes.push(modrm);
if mod_bits != 0b11 {
let disp_size = disp_size_bytes(disp);
let disp_bytes = encode_displacement(disp, disp_size);
bytes.extend_from_slice(&disp_bytes);
}
if imm_size > 0 {
let imm_bytes = encode_immediate(imm, imm_size);
bytes.extend_from_slice(&imm_bytes);
}
bytes
}
pub fn encode_xop_instruction(
&self,
entry: &XopEncodingEntry,
vvvv: u8,
reg: u8,
rm: u8,
mod_bits: u8,
) -> Vec<u8> {
let mut bytes = Vec::new();
let r_bit = reg >= 8;
let x_bit = false;
let b_bit = rm >= 8;
let w_bit = false;
bytes.push(0x8F);
let p0 = ((!r_bit as u8) << 7)
| ((!x_bit as u8) << 6)
| ((!b_bit as u8) << 5)
| (entry.xop_map & 0x1F);
bytes.push(p0);
let p1 = ((w_bit as u8) << 7)
| ((!vvvv & 0x0F) << 3)
| 0x00 | (entry.pp & 0x03);
bytes.push(p1);
bytes.push(entry.opcode_byte);
let modrm = build_modrm(mod_bits, reg & 0x07, rm & 0x07);
bytes.push(modrm);
bytes
}
pub fn encode_3dnow(&self, imm_opcode: u8, mm_reg: u8, rm: u8) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(0x0F);
bytes.push(0x0F);
let modrm = build_modrm(0b11, mm_reg & 0x07, rm & 0x07);
bytes.push(modrm);
bytes.push(imm_opcode);
bytes
}
pub fn encode_opcode_reg(&self, base_opcode: u8, reg: u8, rex_w: bool) -> Vec<u8> {
let mut bytes = Vec::new();
if self.mode.is_64bit() {
let rex = 0x40 | if rex_w { 0x08 } else { 0 } | if reg >= 8 { 0x01 } else { 0 };
if rex != 0x40 || rex_w {
bytes.push(rex);
}
}
bytes.push(base_opcode | (reg & 0x07));
bytes
}
pub fn encode_branch_rel(&self, opcode: u8, offset: i64, size: u8) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.push(opcode);
let off_bytes = encode_immediate(offset, size);
bytes.extend_from_slice(&off_bytes);
bytes
}
pub fn validate(&self, bytes: &[u8], entry: &OpcodeEncodingEntry) -> EncodeValidation {
validate_encoded_bytes(bytes, entry, self.mode)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_primary_opcode_map_built() {
let map = build_primary_opcode_map();
assert_eq!(map.len(), 256);
assert_eq!(map[0x00].mnemonic, "addb");
assert_eq!(map[0x90].mnemonic, "nop");
assert_eq!(map[0xC3].mnemonic, "ret");
assert_eq!(map[0xCC].mnemonic, "int3");
assert_eq!(map[0xE8].mnemonic, "call");
assert_eq!(map[0xE9].mnemonic, "jmp");
assert_eq!(map[0x0F].mnemonic, "escape_0f");
}
#[test]
fn test_two_byte_opcode_map_built() {
let map = build_two_byte_opcode_map();
assert_eq!(map.len(), 256);
assert_eq!(map[0x0B].mnemonic, "ud2");
assert_eq!(map[0xAF].mnemonic, "imul");
assert_eq!(map[0xB6].mnemonic, "movzxb");
}
#[test]
fn test_0f38_opcode_map_built() {
let map = build_0f38_opcode_map();
assert_eq!(map.len(), 256);
assert_eq!(map[0xF0].mnemonic, "movbe");
}
#[test]
fn test_0f3a_opcode_map_built() {
let map = build_0f3a_opcode_map();
assert_eq!(map.len(), 256);
assert_eq!(map[0xDF].mnemonic, "aeskeygenassist");
}
#[test]
fn test_build_modrm() {
assert_eq!(build_modrm(0b11, 0, 0), 0xC0); assert_eq!(build_modrm(0b00, 0, 5), 0x05); assert_eq!(build_modrm(0b01, 3, 4), 0x5C); }
#[test]
fn test_build_sib() {
assert_eq!(build_sib(0, 4, 4), 0x24); assert_eq!(build_sib(2, 0, 5), 0x85); }
#[test]
fn test_encode_displacement() {
assert!(encode_displacement(0, 0).is_empty());
assert_eq!(encode_displacement(0x7F, 1), vec![0x7F]);
assert_eq!(encode_displacement(-128i64, 1), vec![0x80u8]);
assert_eq!(
encode_displacement(0x12345678, 4),
vec![0x78, 0x56, 0x34, 0x12]
);
}
#[test]
fn test_encode_immediate() {
assert_eq!(encode_immediate(0x42, 1), vec![0x42]);
assert_eq!(encode_immediate(0x1234, 2), vec![0x34, 0x12]);
assert_eq!(
encode_immediate(0xDEADBEEFi64, 4),
vec![0xEF, 0xBE, 0xAD, 0xDE]
);
}
#[test]
fn test_disp_size() {
assert_eq!(disp_size_bytes(0), 0);
assert_eq!(disp_size_bytes(127), 1);
assert_eq!(disp_size_bytes(-128), 1);
assert_eq!(disp_size_bytes(128), 4);
assert_eq!(disp_size_bytes(0x10000), 4);
}
#[test]
fn test_mod_for_disp() {
assert_eq!(mod_for_disp(0), 0);
assert_eq!(mod_for_disp(100), 1);
assert_eq!(mod_for_disp(200), 2);
}
#[test]
fn test_encoder_creation() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
assert_eq!(encoder.primary_map.len(), 256);
assert_eq!(encoder.two_byte_map.len(), 256);
assert!(!encoder.vex_instructions.is_empty());
assert!(!encoder.evex_instructions.is_empty());
}
#[test]
fn test_encode_simple_reg_reg() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let bytes = encoder.encode_reg_reg(0x01, 0, 1, false);
assert_eq!(bytes, vec![0x01, 0xC8]);
}
#[test]
fn test_encode_with_rex() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let bytes = encoder.encode_reg_reg(0x01, 1, 0, false);
assert_eq!(bytes, vec![0x45, 0x01, 0xC8]);
}
#[test]
fn test_encode_push_opcode_reg() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let bytes = encoder.encode_opcode_reg(0x50, 0, false);
assert_eq!(bytes, vec![0x50]);
let bytes = encoder.encode_opcode_reg(0x50, 8, false);
assert_eq!(bytes, vec![0x41, 0x50]);
}
#[test]
fn test_encode_nop() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let entry = encoder.lookup_primary(0x90);
assert_eq!(entry.mnemonic, "nop");
}
#[test]
fn test_vex_instruction_count() {
let vex = get_vex_instructions();
assert!(vex.len() >= 40);
}
#[test]
fn test_evex_instruction_count() {
let evex = get_evex_instructions();
assert!(evex.len() >= 20);
}
#[test]
fn test_xop_instruction_count() {
let xop = get_xop_instructions();
assert!(xop.len() >= 5);
}
#[test]
fn test_3dnow_instruction_count() {
let dnow = get_3dnow_instructions();
assert!(dnow.len() >= 10);
}
#[test]
fn test_validate_good_bytes() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let entry = encoder.lookup_primary(0x01);
let bytes = vec![0x01, 0xC8]; let result = validate_encoded_bytes(&bytes, entry, X86Mode::Mode64);
assert!(result.is_valid);
assert_eq!(result.computed_length, 2);
}
#[test]
fn test_validate_empty_bytes() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let entry = encoder.lookup_primary(0x01);
let result = validate_encoded_bytes(&[], entry, X86Mode::Mode64);
assert!(!result.is_valid);
}
#[test]
fn test_encode_3dnow() {
let encoder = X86FullMCEncoderFull::new(X86Mode::Mode64);
let bytes = encoder.encode_3dnow(0x90, 0, 1); assert_eq!(bytes.len(), 5);
assert_eq!(bytes[0], 0x0F);
assert_eq!(bytes[1], 0x0F);
assert_eq!(bytes[2], 0xC1);
assert_eq!(bytes[3], 0x90);
}
}