From 5ebc7fdd0bb9131aea3c388e6ab7ebd7ce9ebc00 Mon Sep 17 00:00:00 2001 From: iximeow Date: Wed, 15 Jan 2020 23:22:18 -0800 Subject: make space for non-64bit modes --- Cargo.toml | 4 +- src/display.rs | 2068 --------------- src/lib.rs | 6215 +-------------------------------------------- src/long_mode/display.rs | 2068 +++++++++++++++ src/long_mode/mod.rs | 6209 ++++++++++++++++++++++++++++++++++++++++++++ src/long_mode/vex.rs | 2363 +++++++++++++++++ src/protected_mode/mod.rs | 1 + src/real_mode/mod.rs | 1 + src/vex.rs | 2363 ----------------- test/test.rs | 4 +- 10 files changed, 10652 insertions(+), 10644 deletions(-) delete mode 100644 src/display.rs create mode 100644 src/long_mode/display.rs create mode 100644 src/long_mode/mod.rs create mode 100644 src/long_mode/vex.rs create mode 100644 src/protected_mode/mod.rs create mode 100644 src/real_mode/mod.rs delete mode 100644 src/vex.rs diff --git a/Cargo.toml b/Cargo.toml index 295428f..65fcb55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ repository = "http://git.iximeow.net/yaxpeax-x86/" description = "x86 decoders for the yaxpeax project" [dependencies] -yaxpeax-arch = { path = "../../yaxpeax-arch", default-features = false, features = []} +yaxpeax-arch = { path = "../../yaxpeax-arch", default-features = false, features = [] } "num-traits" = { version = "0.2", default-features = false } "termion" = { version = "1.4.0", optional = true } "serde" = { version = "1.0", optional = true } @@ -37,7 +37,7 @@ default = ["std", "colors", "use-serde"] # opt-in for some apis that are really much nicer with String std = [] -use-serde = ["yaxpeax-arch/use-serde"] +use-serde = ["yaxpeax-arch/use-serde", "serde", "serde_derive"] colors = ["yaxpeax-arch/colors"] diff --git a/src/display.rs b/src/display.rs deleted file mode 100644 index 4e5e0cf..0000000 --- a/src/display.rs +++ /dev/null @@ -1,2068 +0,0 @@ -extern crate yaxpeax_arch; - -use core::fmt; - -use yaxpeax_arch::{Colorize, ShowContextual, NoColors, YaxColors}; -use yaxpeax_arch::display::*; - -use ::{RegSpec, RegisterBank, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixRex, OperandSpec, DecodeError}; - -impl fmt::Display for DecodeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - DecodeError::ExhaustedInput => { write!(f, "exhausted input") }, - DecodeError::InvalidOpcode => { write!(f, "invalid opcode") }, - DecodeError::InvalidOperand => { write!(f, "invalid operand") }, - DecodeError::InvalidPrefixes => { write!(f, "invalid prefixes") }, - DecodeError::TooLong => { write!(f, "too long") }, - DecodeError::IncompleteDecoder => { write!(f, "the decoder is incomplete") }, - } - } -} - -impl fmt::Display for InstDecoder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self == &InstDecoder::default() { - return write!(f, ""); - } else if self == &InstDecoder::minimal() { - return write!(f, ""); - } - if self.sse3() { write!(f, "sse3 ")? } - if self.ssse3() { write!(f, "ssse3 ")? } - if self.monitor() { write!(f, "monitor ")? } - if self.vmx() { write!(f, "vmx ")? } - if self.fma3() { write!(f, "fma3 ")? } - if self.cmpxchg16b() { write!(f, "cmpxchg16b ")? } - if self.sse4_1() { write!(f, "sse4_1 ")? } - if self.sse4_2() { write!(f, "sse4_2 ")? } - if self.movbe() { write!(f, "movbe ")? } - if self.popcnt() { write!(f, "popcnt ")? } - if self.aesni() { write!(f, "aesni ")? } - if self.xsave() { write!(f, "xsave ")? } - if self.rdrand() { write!(f, "rdrand ")? } - if self.sgx() { write!(f, "sgx ")? } - if self.bmi1() { write!(f, "bmi1 ")? } - if self.avx2() { write!(f, "avx2 ")? } - if self.bmi2() { write!(f, "bmi2 ")? } - if self.invpcid() { write!(f, "invpcid ")? } - if self.mpx() { write!(f, "mpx ")? } - if self.avx512_f() { write!(f, "avx512_f ")? } - if self.avx512_dq() { write!(f, "avx512_dq ")? } - if self.rdseed() { write!(f, "rdseed ")? } - if self.adx() { write!(f, "adx ")? } - if self.avx512_fma() { write!(f, "avx512_fma ")? } - if self.pcommit() { write!(f, "pcommit ")? } - if self.clflushopt() { write!(f, "clflushopt ")? } - if self.clwb() { write!(f, "clwb ")? } - if self.avx512_pf() { write!(f, "avx512_pf ")? } - if self.avx512_er() { write!(f, "avx512_er ")? } - if self.avx512_cd() { write!(f, "avx512_cd ")? } - if self.sha() { write!(f, "sha ")? } - if self.avx512_bw() { write!(f, "avx512_bw ")? } - if self.avx512_vl() { write!(f, "avx512_vl ")? } - if self.prefetchwt1() { write!(f, "prefetchwt1 ")? } - if self.avx512_vbmi() { write!(f, "avx512_vbmi ")? } - if self.avx512_vbmi2() { write!(f, "avx512_vbmi2 ")? } - if self.gfni() { write!(f, "gfni ")? } - if self.vaes() { write!(f, "vaes ")? } - if self.pclmulqdq() { write!(f, "pclmulqdq ")? } - if self.avx_vnni() { write!(f, "avx_vnni ")? } - if self.avx512_bitalg() { write!(f, "avx512_bitalg ")? } - if self.avx512_vpopcntdq() { write!(f, "avx512_vpopcntdq ")? } - if self.avx512_4vnniw() { write!(f, "avx512_4vnniw ")? } - if self.avx512_4fmaps() { write!(f, "avx512_4fmaps ")? } - if self.cx8() { write!(f, "cx8 ")? } - if self.syscall() { write!(f, "syscall ")? } - if self.rdtscp() { write!(f, "rdtscp ")? } - if self.abm() { write!(f, "abm ")? } - if self.sse4a() { write!(f, "sse4a ")? } - if self._3dnowprefetch() { write!(f, "_3dnowprefetch ")? } - if self.xop() { write!(f, "xop ")? } - if self.skinit() { write!(f, "skinit ")? } - if self.tbm() { write!(f, "tbm ")? } - if self.intel_quirks() { write!(f, "intel_quirks ")? } - if self.amd_quirks() { write!(f, "amd_quirks ")? } - if self.avx() { write!(f, "avx ")? } - Ok(()) - } -} - -impl fmt::Display for PrefixRex { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.present() { - write!(f, "rex:{}{}{}{}", - if self.w() { "w" } else { "-" }, - if self.r() { "r" } else { "-" }, - if self.x() { "x" } else { "-" }, - if self.b() { "b" } else { "-" }, - ) - } else { - write!(f, "rex:none") - } - } -} - -impl fmt::Display for Segment { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Segment::CS => write!(f, "cs"), - Segment::DS => write!(f, "ds"), - Segment::ES => write!(f, "es"), - Segment::FS => write!(f, "fs"), - Segment::GS => write!(f, "gs"), - Segment::SS => write!(f, "ss"), - } - } -} - -impl fmt::Display for RegSpec { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let name = match self.bank { - RegisterBank::Q => { - ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"][self.num as usize] - }, - RegisterBank::D => { - ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"][self.num as usize] - }, - RegisterBank::W => { - ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"][self.num as usize] - }, - RegisterBank::B => { - ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"][self.num as usize] - }, - RegisterBank::rB => { - ["al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"][self.num as usize] - }, - RegisterBank::EIP => { "eip" }, - RegisterBank::RIP => { "rip" }, - RegisterBank::EFlags => { "eflags" }, - RegisterBank::RFlags => { "rflags" }, - RegisterBank::CR => { - ["cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15"][self.num as usize] - } - RegisterBank::DR => { - ["dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"][self.num as usize] - } - RegisterBank::X => { - ["xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"][self.num as usize] - }, - RegisterBank::Y => { - ["ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"][self.num as usize] - }, - RegisterBank::Z => { - ["zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31"][self.num as usize] - }, - RegisterBank::ST => { - ["st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"][self.num as usize] - }, - RegisterBank::MM => { - ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"][self.num as usize] - } - RegisterBank::S => { - ["cs", "ds", "es", "fs", "gs", "ss"][self.num as usize] - } - RegisterBank::K => { - ["k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"][self.num as usize] - } - }; - write!(f, "{}", name) - } -} - -impl fmt::Display for Operand { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.colorize(&NoColors, fmt) - } -} - -impl > Colorize for Operand { - fn colorize(&self, colors: &Y, f: &mut T) -> fmt::Result { - match self { - &Operand::ImmediateU8(imm) => { - write!(f, "{}", colors.number(u8_hex(imm))) - } - &Operand::ImmediateI8(imm) => { - write!(f, "{}", - colors.number(signed_i8_hex(imm))) - }, - &Operand::ImmediateU16(imm) => { - write!(f, "{}", colors.number(u16_hex(imm))) - } - &Operand::ImmediateI16(imm) => { - write!(f, "{}", - colors.number(signed_i16_hex(imm))) - }, - &Operand::ImmediateU32(imm) => { - write!(f, "{}", colors.number(u32_hex(imm))) - } - &Operand::ImmediateI32(imm) => { - write!(f, "{}", - colors.number(signed_i32_hex(imm))) - }, - &Operand::ImmediateU64(imm) => { - write!(f, "{}", colors.number(u64_hex(imm))) - } - &Operand::ImmediateI64(imm) => { - write!(f, "{}", - colors.number(signed_i64_hex(imm))) - }, - &Operand::Register(ref spec) => { - write!(f, "{}", colors.register(spec)) - } - &Operand::DisplacementU32(imm) => { - write!(f, "[{}]", colors.address(u32_hex(imm))) - } - &Operand::DisplacementU64(imm) => { - write!(f, "[{}]", colors.address(u64_hex(imm))) - } - &Operand::RegDisp(ref spec, disp) => { - write!(f, "[{} ", colors.register(spec))?; - format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; - write!(f, "]") - }, - &Operand::RegDeref(ref spec) => { - write!(f, "[{}]", colors.register(spec)) - }, - &Operand::RegScale(ref spec, scale) => { - write!(f, "[{} * {}]", - colors.register(spec), - colors.number(scale) - ) - }, - &Operand::RegScaleDisp(ref spec, scale, disp) => { - write!(f, "[{} * {} ", - colors.register(spec), - colors.number(scale), - )?; - format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; - write!(f, "]") - }, - &Operand::RegIndexBase(ref base, ref index) => { - write!(f, "[{} + {}]", - colors.register(base), - colors.register(index) - ) - } - &Operand::RegIndexBaseDisp(ref base, ref index, disp) => { - write!(f, "[{} + {} ", - colors.register(base), - colors.register(index), - )?; - format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; - write!(f, "]") - }, - &Operand::RegIndexBaseScale(ref base, ref index, scale) => { - write!(f, "[{} + {} * {}]", - colors.register(base), - colors.register(index), - colors.number(scale) - ) - } - &Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => { - write!(f, "[{} + {} * {} ", - colors.register(base), - colors.register(index), - colors.number(scale), - )?; - format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; - write!(f, "]") - }, - &Operand::Nothing => { Ok(()) }, - } - } -} - -impl fmt::Display for Opcode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Opcode::POPCNT => write!(f, "popcnt"), - &Opcode::MOVDQU => write!(f, "movdqu"), - &Opcode::MOVDQA => write!(f, "movdqa"), - &Opcode::MOVQ => write!(f, "movq"), - &Opcode::CMPSS => write!(f, "cmpss"), - &Opcode::CMPSD => write!(f, "cmpsd"), - &Opcode::UNPCKLPS => write!(f, "unpcklps"), - &Opcode::UNPCKHPS => write!(f, "unpckhps"), - &Opcode::MOVUPS => write!(f, "movups"), - &Opcode::MOVQ2DQ => write!(f, "movq2dq"), - &Opcode::MOVDQ2Q => write!(f, "movdq2q"), - &Opcode::RSQRTSS => write!(f, "rsqrtss"), - &Opcode::MOVSHDUP => write!(f, "movshdup"), - &Opcode::CVTTPS2DQ => write!(f, "cvttps2dq"), - &Opcode::CVTPD2DQ => write!(f, "cvtpd2dq"), - &Opcode::RCPSS => write!(f, "rcpss"), - &Opcode::CVTDQ2PD => write!(f, "cvtdq2pd"), - &Opcode::PSHUFHW => write!(f, "pshufhw"), - &Opcode::PSHUFLW => write!(f, "pshuflw"), - &Opcode::XADD => write!(f, "xadd"), - &Opcode::BT => write!(f, "bt"), - &Opcode::BTS => write!(f, "bts"), - &Opcode::BTR => write!(f, "btr"), - &Opcode::BTC => write!(f, "btc"), - &Opcode::BSF => write!(f, "bsf"), - &Opcode::BSR => write!(f, "bsr"), - &Opcode::TZCNT => write!(f, "tzcnt"), - &Opcode::MOVSS => write!(f, "movss"), - &Opcode::SQRTSS => write!(f, "sqrtss"), - &Opcode::ADDSS => write!(f, "addss"), - &Opcode::SUBSS => write!(f, "subss"), - &Opcode::MULSS => write!(f, "mulss"), - &Opcode::DIVSS => write!(f, "divss"), - &Opcode::MINSS => write!(f, "minss"), - &Opcode::MAXSS => write!(f, "maxss"), - &Opcode::MOVSD => write!(f, "movsd"), - &Opcode::SQRTSD => write!(f, "sqrtsd"), - &Opcode::ADDSD => write!(f, "addsd"), - &Opcode::SUBSD => write!(f, "subsd"), - &Opcode::MULSD => write!(f, "mulsd"), - &Opcode::DIVSD => write!(f, "divsd"), - &Opcode::MINSD => write!(f, "minsd"), - &Opcode::MAXSD => write!(f, "maxsd"), - &Opcode::MOVDDUP => write!(f, "movddup"), - &Opcode::MOVSLDUP => write!(f, "movsldup"), - &Opcode::HADDPS => write!(f, "haddps"), - &Opcode::HSUBPS => write!(f, "hsubps"), - &Opcode::ADDSUBPS => write!(f, "addsubps"), - &Opcode::CVTSI2SS => write!(f, "cvtsi2ss"), - &Opcode::CVTSI2SD => write!(f, "cvtsi2sd"), - &Opcode::CVTTSD2SI => write!(f, "cvttsd2si"), - &Opcode::CVTSD2SI => write!(f, "cvtsd2si"), - &Opcode::CVTSD2SS => write!(f, "cvtsd2ss"), - &Opcode::CVTTSS2SI => write!(f, "cvttss2si"), - &Opcode::CVTSS2SI => write!(f, "cvtss2si"), - &Opcode::CVTSS2SD => write!(f, "cvtss2sd"), - &Opcode::LDDQU => write!(f, "lddqu"), - &Opcode::STI => write!(f, "sti"), - &Opcode::STD => write!(f, "std"), - &Opcode::STC => write!(f, "stc"), - &Opcode::CLI => write!(f, "cli"), - &Opcode::CLD => write!(f, "cld"), - &Opcode::CLC => write!(f, "clc"), - &Opcode::SLDT => write!(f, "sldt"), - &Opcode::STR => write!(f, "str"), - &Opcode::LLDT => write!(f, "lldt"), - &Opcode::LTR => write!(f, "ltr"), - &Opcode::VERR => write!(f, "verr"), - &Opcode::VERW => write!(f, "verw"), - &Opcode::JMPE => write!(f, "jmpe"), - &Opcode::WRMSR => write!(f, "wrmsr"), - &Opcode::RDMSR => write!(f, "rdmsr"), - &Opcode::RDTSC => write!(f, "rdtsc"), - &Opcode::RDPMC => write!(f, "rdpmc"), - &Opcode::FXSAVE => write!(f, "fxsave"), - &Opcode::FXRSTOR => write!(f, "fxrstor"), - &Opcode::LDMXCSR => write!(f, "ldmxcsr"), - &Opcode::STMXCSR => write!(f, "stmxcsr"), - &Opcode::XSAVE => write!(f, "xsave"), - &Opcode::XRSTOR => write!(f, "xrstor"), - &Opcode::XSAVEOPT => write!(f, "xsaveopt"), - &Opcode::LFENCE => write!(f, "lfence"), - &Opcode::MFENCE => write!(f, "mfence"), - &Opcode::SFENCE => write!(f, "sfence"), - &Opcode::CLFLUSH => write!(f, "clflush"), - &Opcode::SGDT => write!(f, "sgdt"), - &Opcode::SIDT => write!(f, "sidt"), - &Opcode::LGDT => write!(f, "lgdt"), - &Opcode::LIDT => write!(f, "lidt"), - &Opcode::SMSW => write!(f, "smsw"), - &Opcode::LMSW => write!(f, "lmsw"), - &Opcode::SWAPGS => write!(f, "swapgs"), - &Opcode::RDTSCP => write!(f, "rdtscp"), - &Opcode::INVLPG => write!(f, "invlpg"), - &Opcode::CPUID => write!(f, "cpuid"), - &Opcode::UD2 => write!(f, "ud2"), - &Opcode::WBINVD => write!(f, "wbinvd"), - &Opcode::INVD => write!(f, "invd"), - &Opcode::SYSRET => write!(f, "sysret"), - &Opcode::CLTS => write!(f, "clts"), - &Opcode::SYSCALL => write!(f, "syscall"), - &Opcode::LSL => write!(f, "lsl"), - &Opcode::LAR => write!(f, "lar"), - &Opcode::INC => write!(f, "inc"), - &Opcode::DEC => write!(f, "dec"), - &Opcode::HLT => write!(f, "hlt"), - &Opcode::SBB => write!(f, "sbb"), - &Opcode::AND => write!(f, "and"), - &Opcode::XOR => write!(f, "xor"), - &Opcode::OR => write!(f, "or"), - &Opcode::PUSH => write!(f, "push"), - &Opcode::POP => write!(f, "pop"), - &Opcode::LEA => write!(f, "lea"), - &Opcode::NOP => write!(f, "nop"), - &Opcode::PREFETCHNTA => write!(f, "prefetchnta"), - &Opcode::PREFETCH0 => write!(f, "prefetch0"), - &Opcode::PREFETCH1 => write!(f, "prefetch1"), - &Opcode::PREFETCH2 => write!(f, "prefetch2"), - &Opcode::XCHG => write!(f, "xchg"), - &Opcode::POPF => write!(f, "popf"), - &Opcode::ADD => write!(f, "add"), - &Opcode::ADC => write!(f, "adc"), - &Opcode::SUB => write!(f, "sub"), - &Opcode::INT => write!(f, "int"), - &Opcode::INTO => write!(f, "into"), - &Opcode::IRET => write!(f, "iret"), - &Opcode::RETF => write!(f, "retf"), - &Opcode::ENTER => write!(f, "enter"), - &Opcode::LEAVE => write!(f, "leave"), - &Opcode::MOV => write!(f, "mov"), - &Opcode::RETURN => write!(f, "ret"), - &Opcode::PUSHF => write!(f, "pushf"), - &Opcode::WAIT => write!(f, "wait"), - &Opcode::LODS => write!(f, "lods"), - &Opcode::STOS => write!(f, "stos"), - &Opcode::LAHF => write!(f, "lahf"), - &Opcode::SAHF => write!(f, "sahf"), - &Opcode::CMPS => write!(f, "cmps"), - &Opcode::SCAS => write!(f, "scas"), - &Opcode::MOVS => write!(f, "movs"), - &Opcode::TEST => write!(f, "test"), - &Opcode::CMP => write!(f, "cmp"), - &Opcode::INS => write!(f, "ins"), - &Opcode::OUTS => write!(f, "outs"), - &Opcode::IMUL => write!(f, "imul"), - &Opcode::JO => write!(f, "jo"), - &Opcode::JNO => write!(f, "jno"), - &Opcode::JB => write!(f, "jb"), - &Opcode::JNB => write!(f, "jnb"), - &Opcode::JZ => write!(f, "jz"), - &Opcode::JNZ => write!(f, "jnz"), - &Opcode::JA => write!(f, "ja"), - &Opcode::JNA => write!(f, "jna"), - &Opcode::JS => write!(f, "js"), - &Opcode::JNS => write!(f, "jns"), - &Opcode::JP => write!(f, "jp"), - &Opcode::JNP => write!(f, "jnp"), - &Opcode::JL => write!(f, "jl"), - &Opcode::JGE => write!(f, "jge"), - &Opcode::JLE => write!(f, "jle"), - &Opcode::JG => write!(f, "jg"), - &Opcode::CALL => write!(f, "call"), - &Opcode::JMP => write!(f, "jmp"), - &Opcode::CALLF => write!(f, "callf"), - &Opcode::JMPF => write!(f, "jmpf"), - &Opcode::SAR => write!(f, "sar"), - &Opcode::SAL => write!(f, "sal"), - &Opcode::SHR => write!(f, "shr"), - &Opcode::SHRD => write!(f, "shrd"), - &Opcode::SHL => write!(f, "shl"), - &Opcode::RCR => write!(f, "rcr"), - &Opcode::RCL => write!(f, "rcl"), - &Opcode::ROR => write!(f, "ror"), - &Opcode::ROL => write!(f, "rol"), - &Opcode::CMOVA => write!(f, "cmova"), - &Opcode::CMOVB => write!(f, "cmovb"), - &Opcode::CMOVG => write!(f, "cmovg"), - &Opcode::CMOVGE => write!(f, "cmovge"), - &Opcode::CMOVL => write!(f, "cmovl"), - &Opcode::CMOVLE => write!(f, "cmovle"), - &Opcode::CMOVNA => write!(f, "cmovna"), - &Opcode::CMOVNB => write!(f, "cmovnb"), - &Opcode::CMOVNO => write!(f, "cmovno"), - &Opcode::CMOVNP => write!(f, "cmovnp"), - &Opcode::CMOVNS => write!(f, "cmovns"), - &Opcode::CMOVNZ => write!(f, "cmovnz"), - &Opcode::CMOVO => write!(f, "cmovo"), - &Opcode::CMOVP => write!(f, "cmovp"), - &Opcode::CMOVS => write!(f, "cmovs"), - &Opcode::CMOVZ => write!(f, "cmovz"), - &Opcode::NEG => write!(f, "neg"), - &Opcode::NOT => write!(f, "not"), - &Opcode::MUL => write!(f, "mul"), - &Opcode::DIV => write!(f, "div"), - &Opcode::IDIV => write!(f, "idiv"), - &Opcode::CMPXCHG => write!(f, "cmpxchg"), - &Opcode::MOVSX_b => write!(f, "movsx"), - &Opcode::MOVSX_w => write!(f, "movsx"), - &Opcode::MOVZX_b => write!(f, "movzx"), - &Opcode::MOVZX_w => write!(f, "movzx"), - &Opcode::MOVSXD => write!(f, "movsxd"), - &Opcode::MOVSX => write!(f, "movsx"), - &Opcode::SETO => write!(f, "seto"), - &Opcode::SETNO => write!(f, "setno"), - &Opcode::SETB => write!(f, "setb"), - &Opcode::SETAE => write!(f, "setae"), - &Opcode::SETZ => write!(f, "setz"), - &Opcode::SETNZ => write!(f, "setnz"), - &Opcode::SETBE => write!(f, "setbe"), - &Opcode::SETA => write!(f, "seta"), - &Opcode::SETS => write!(f, "sets"), - &Opcode::SETNS => write!(f, "setns"), - &Opcode::SETP => write!(f, "setp"), - &Opcode::SETNP => write!(f, "setnp"), - &Opcode::SETL => write!(f, "setl"), - &Opcode::SETGE => write!(f, "setge"), - &Opcode::SETLE => write!(f, "setle"), - &Opcode::SETG => write!(f, "setg"), - &Opcode::ADDPS => write!(f, "addps"), - &Opcode::ANDNPS => write!(f, "andnps"), - &Opcode::ANDPS => write!(f, "andps"), - &Opcode::BSWAP => write!(f, "bswap"), - &Opcode::CMPPS => write!(f, "cmpps"), - &Opcode::COMISS => write!(f, "comiss"), - &Opcode::CVTDQ2PS => write!(f, "cvtdq2ps"), - &Opcode::CVTPI2PS => write!(f, "cvtpi2ps"), - &Opcode::CVTPI2PD => write!(f, "cvtpi2pd"), - &Opcode::CVTPS2PD => write!(f, "cvtps2pd"), - &Opcode::CVTPS2PI => write!(f, "cvtps2pi"), - &Opcode::CVTTPS2PI => write!(f, "cvttps2pi"), - &Opcode::DIVPS => write!(f, "divps"), - &Opcode::EMMS => write!(f, "emms"), - &Opcode::GETSEC => write!(f, "getsec"), - &Opcode::LFS => write!(f, "lfs"), - &Opcode::LGS => write!(f, "lgs"), - &Opcode::LSS => write!(f, "lss"), - &Opcode::MASKMOVQ => write!(f, "maskmovq"), - &Opcode::MAXPS => write!(f, "maxps"), - &Opcode::MINPS => write!(f, "minps"), - &Opcode::MOVAPS => write!(f, "movaps"), - &Opcode::MOVAPD => write!(f, "movapd"), - &Opcode::MOVD => write!(f, "movd"), - &Opcode::MOVLPS => write!(f, "movlps"), - &Opcode::MOVLHPS => write!(f, "movlhps"), - &Opcode::MOVHPS => write!(f, "movhps"), - &Opcode::MOVHLPS => write!(f, "movhlps"), - &Opcode::MOVUPD => write!(f, "movupd"), - &Opcode::MOVMSKPS => write!(f, "movmskps"), - &Opcode::MOVNTI => write!(f, "movnti"), - &Opcode::MOVNTPS => write!(f, "movntps"), - &Opcode::MOVNTQ => write!(f, "movntq"), - &Opcode::MULPS => write!(f, "mulps"), - &Opcode::ORPS => write!(f, "orps"), - &Opcode::PACKSSDW => write!(f, "packssdw"), - &Opcode::PACKSSWB => write!(f, "packsswb"), - &Opcode::PACKUSWB => write!(f, "packuswb"), - &Opcode::PADDB => write!(f, "paddb"), - &Opcode::PADDD => write!(f, "paddd"), - &Opcode::PADDQ => write!(f, "paddq"), - &Opcode::PADDSB => write!(f, "paddsb"), - &Opcode::PADDSW => write!(f, "paddsw"), - &Opcode::PADDUSB => write!(f, "paddusb"), - &Opcode::PADDUSW => write!(f, "paddusw"), - &Opcode::PADDW => write!(f, "paddw"), - &Opcode::PAND => write!(f, "pand"), - &Opcode::PANDN => write!(f, "pandn"), - &Opcode::PAVGB => write!(f, "pavgb"), - &Opcode::PAVGW => write!(f, "pavgw"), - &Opcode::PCMPEQB => write!(f, "pcmpeqb"), - &Opcode::PCMPEQD => write!(f, "pcmpeqd"), - &Opcode::PCMPEQW => write!(f, "pcmpeqw"), - &Opcode::PCMPGTB => write!(f, "pcmpgtb"), - &Opcode::PCMPGTD => write!(f, "pcmpgtd"), - &Opcode::PCMPGTW => write!(f, "pcmpgtw"), - &Opcode::PEXTRW => write!(f, "pextrw"), - &Opcode::PINSRW => write!(f, "pinsrw"), - &Opcode::PMADDWD => write!(f, "pmaddwd"), - &Opcode::PMAXSW => write!(f, "pmaxsw"), - &Opcode::PMAXUB => write!(f, "pmaxub"), - &Opcode::PMINSW => write!(f, "pminsw"), - &Opcode::PMINUB => write!(f, "pminub"), - &Opcode::PMOVMSKB => write!(f, "pmovmskb"), - &Opcode::PMULHUW => write!(f, "pmulhuw"), - &Opcode::PMULHW => write!(f, "pmulhw"), - &Opcode::PMULLW => write!(f, "pmullw"), - &Opcode::PMULUDQ => write!(f, "pmuludq"), - &Opcode::POR => write!(f, "por"), - &Opcode::PSADBW => write!(f, "psadbw"), - &Opcode::PSHUFW => write!(f, "pshufw"), - &Opcode::PSHUFD => write!(f, "pshufd"), - &Opcode::PSLLD => write!(f, "pslld"), - &Opcode::PSLLDQ => write!(f, "pslldq"), - &Opcode::PSLLQ => write!(f, "psllq"), - &Opcode::PSLLW => write!(f, "psllw"), - &Opcode::PSRAD => write!(f, "psrad"), - &Opcode::PSRAW => write!(f, "psraw"), - &Opcode::PSRLD => write!(f, "psrld"), - &Opcode::PSRLDQ => write!(f, "psrldq"), - &Opcode::PSRLQ => write!(f, "psrlq"), - &Opcode::PSRLW => write!(f, "psrlw"), - &Opcode::PSUBB => write!(f, "psubb"), - &Opcode::PSUBD => write!(f, "psubd"), - &Opcode::PSUBQ => write!(f, "psubq"), - &Opcode::PSUBSB => write!(f, "psubsb"), - &Opcode::PSUBSW => write!(f, "psubsw"), - &Opcode::PSUBUSB => write!(f, "psubusb"), - &Opcode::PSUBUSW => write!(f, "psubusw"), - &Opcode::PSUBW => write!(f, "psubw"), - &Opcode::PUNPCKHBW => write!(f, "punpckhbw"), - &Opcode::PUNPCKHDQ => write!(f, "punpckhdq"), - &Opcode::PUNPCKHWD => write!(f, "punpckhwd"), - &Opcode::PUNPCKLBW => write!(f, "punpcklbw"), - &Opcode::PUNPCKLDQ => write!(f, "punpckldq"), - &Opcode::PUNPCKLWD => write!(f, "punpcklwd"), - &Opcode::PUNPCKLQDQ => write!(f, "punpcklqdq"), - &Opcode::PUNPCKHQDQ => write!(f, "punpckhqdq"), - &Opcode::PXOR => write!(f, "pxor"), - &Opcode::RCPPS => write!(f, "rcpps"), - &Opcode::RSM => write!(f, "rsm"), - &Opcode::RSQRTPS => write!(f, "rsqrtps"), - &Opcode::SHLD => write!(f, "shld"), - &Opcode::SHUFPS => write!(f, "shufps"), - &Opcode::SLHD => write!(f, "slhd"), - &Opcode::SQRTPS => write!(f, "sqrtps"), - &Opcode::SUBPS => write!(f, "subps"), - &Opcode::SYSENTER => write!(f, "sysenter"), - &Opcode::SYSEXIT => write!(f, "sysexit"), - &Opcode::UCOMISS => write!(f, "ucomiss"), - &Opcode::UD2E => write!(f, "ud2e"), - &Opcode::VMREAD => write!(f, "vmread"), - &Opcode::VMWRITE => write!(f, "vmwrite"), - &Opcode::XORPS => write!(f, "xorps"), - &Opcode::CBW => write!(f, "cbw"), - &Opcode::CWDE => write!(f, "cwde"), - &Opcode::CDQE => write!(f, "cdqe"), - &Opcode::CBD => write!(f, "cbd"), - &Opcode::CDQ => write!(f, "cdq"), - &Opcode::CQO => write!(f, "cqo"), - &Opcode::ANDN => write!(f, "andn"), - &Opcode::BEXTR => write!(f, "bextr"), - &Opcode::BLSI => write!(f, "blsi"), - &Opcode::BLSMSK => write!(f, "blsmsk"), - &Opcode::BLSR => write!(f, "blsr"), - &Opcode::VMCALL => write!(f, "vmcall"), - &Opcode::VMLAUNCH => write!(f, "vmlaunch"), - &Opcode::VMRESUME => write!(f, "vmresume"), - &Opcode::VMXOFF => write!(f, "vmxoff"), - &Opcode::MONITOR => write!(f, "monitor"), - &Opcode::MWAIT => write!(f, "mwait"), - &Opcode::CLAC => write!(f, "clac"), - &Opcode::STAC => write!(f, "stac"), - &Opcode::ENCLS => write!(f, "encls"), - &Opcode::ENCLV => write!(f, "enclv"), - &Opcode::XGETBV => write!(f, "xgetbv"), - &Opcode::XSETBV => write!(f, "xsetbv"), - &Opcode::VMFUNC => write!(f, "vmfunc"), - &Opcode::XEND => write!(f, "xend"), - &Opcode::XTEST => write!(f, "xtest"), - &Opcode::ENCLU => write!(f, "enclu"), - &Opcode::RDPKRU => write!(f, "rdpkru"), - &Opcode::WRPKRU => write!(f, "wrpkru"), - &Opcode::VADDPD => write!(f, "vaddpd"), - &Opcode::VADDPS => write!(f, "vaddps"), - &Opcode::VADDSUBPD => write!(f, "vaddsubpd"), - &Opcode::VAESDEC => write!(f, "vaesdec"), - &Opcode::VAESDECLAST => write!(f, "vaesdeclast"), - &Opcode::VAESENC => write!(f, "vaesenc"), - &Opcode::VAESENCLAST => write!(f, "vaesenclast"), - &Opcode::VAESIMC => write!(f, "vaesimc"), - &Opcode::VAESKEYGENASSIST => write!(f, "vaeskeygenassist"), - &Opcode::VBLENDPD => write!(f, "vblendpd"), - &Opcode::VBLENDPS => write!(f, "vblendps"), - &Opcode::VBLENDVPD => write!(f, "vblendvpd"), - &Opcode::VBLENDVPS => write!(f, "vblendvps"), - &Opcode::VBROADCASTF128 => write!(f, "vbroadcastf128"), - &Opcode::VBROADCASTI128 => write!(f, "vbroadcasti128"), - &Opcode::VBROADCASTSD => write!(f, "vbroadcastsd"), - &Opcode::VBROADCASTSS => write!(f, "vbroadcastss"), - &Opcode::VCMPPD => write!(f, "vcmppd"), - &Opcode::VCMPPS => write!(f, "vcmpps"), - &Opcode::VCVTDQ2PD => write!(f, "vcvtdq2pd"), - &Opcode::VCVTDQ2PS => write!(f, "vcvtdq2ps"), - &Opcode::VCVTPD2PS => write!(f, "vcvtpd2ps"), - &Opcode::VCVTPH2PS => write!(f, "vcvtph2ps"), - &Opcode::VCVTPS2DQ => write!(f, "vcvtps2dq"), - &Opcode::VCVTPS2PD => write!(f, "vcvtps2pd"), - &Opcode::VCVTPS2PH => write!(f, "vcvtps2ph"), - &Opcode::VCVTTPD2DQ => write!(f, "vcvttpd2dq"), - &Opcode::VCVTTPS2DQ => write!(f, "vcvttps2dq"), - &Opcode::VDIVPD => write!(f, "vdivpd"), - &Opcode::VDIVPS => write!(f, "vdivps"), - &Opcode::VDPPD => write!(f, "vdppd"), - &Opcode::VDPPS => write!(f, "vdpps"), - &Opcode::VEXTRACTF128 => write!(f, "vextractf128"), - &Opcode::VEXTRACTI128 => write!(f, "vextracti128"), - &Opcode::VEXTRACTPS => write!(f, "vextractps"), - &Opcode::VFMADD132PD => write!(f, "vfmadd132pd"), - &Opcode::VFMADD132PS => write!(f, "vfmadd132ps"), - &Opcode::VFMADD213PD => write!(f, "vfmadd213pd"), - &Opcode::VFMADD213PS => write!(f, "vfmadd213ps"), - &Opcode::VFMADD231PD => write!(f, "vfmadd231pd"), - &Opcode::VFMADD231PS => write!(f, "vfmadd231ps"), - &Opcode::VFMADDSUB132PD => write!(f, "vfmaddsub132pd"), - &Opcode::VFMADDSUB132PS => write!(f, "vfmaddsub132ps"), - &Opcode::VFMADDSUB213PD => write!(f, "vfmaddsub213pd"), - &Opcode::VFMADDSUB213PS => write!(f, "vfmaddsub213ps"), - &Opcode::VFMADDSUB231PD => write!(f, "vfmaddsub231pd"), - &Opcode::VFMADDSUB231PS => write!(f, "vfmaddsub231ps"), - &Opcode::VFMSUB132PD => write!(f, "vfmsub132pd"), - &Opcode::VFMSUB132PS => write!(f, "vfmsub132ps"), - &Opcode::VFMSUB213PD => write!(f, "vfmsub213pd"), - &Opcode::VFMSUB213PS => write!(f, "vfmsub213ps"), - &Opcode::VFMSUB231PD => write!(f, "vfmsub231pd"), - &Opcode::VFMSUB231PS => write!(f, "vfmsub231ps"), - &Opcode::VFMSUBADD132PD => write!(f, "vfmsubadd132pd"), - &Opcode::VFMSUBADD132PS => write!(f, "vfmsubadd132ps"), - &Opcode::VFMSUBADD213PD => write!(f, "vfmsubadd213pd"), - &Opcode::VFMSUBADD213PS => write!(f, "vfmsubadd213ps"), - &Opcode::VFMSUBADD231PD => write!(f, "vfmsubadd231pd"), - &Opcode::VFMSUBADD231PS => write!(f, "vfmsubadd231ps"), - &Opcode::VFNMADD132PD => write!(f, "vfnmadd132pd"), - &Opcode::VFNMADD132PS => write!(f, "vfnmadd132ps"), - &Opcode::VFNMADD213PD => write!(f, "vfnmadd213pd"), - &Opcode::VFNMADD213PS => write!(f, "vfnmadd213ps"), - &Opcode::VFNMADD231PD => write!(f, "vfnmadd231pd"), - &Opcode::VFNMADD231PS => write!(f, "vfnmadd231ps"), - &Opcode::VFNMSUB132PD => write!(f, "vfnmsub132pd"), - &Opcode::VFNMSUB132PS => write!(f, "vfnmsub132ps"), - &Opcode::VFNMSUB213PD => write!(f, "vfnmsub213pd"), - &Opcode::VFNMSUB213PS => write!(f, "vfnmsub213ps"), - &Opcode::VFNMSUB231PD => write!(f, "vfnmsub231pd"), - &Opcode::VFNMSUB231PS => write!(f, "vfnmsub231ps"), - &Opcode::VGATHERDPD => write!(f, "vgatherdpd"), - &Opcode::VGATHERDPS => write!(f, "vgatherdps"), - &Opcode::VGATHERQPD => write!(f, "vgatherqpd"), - &Opcode::VGATHERQPS => write!(f, "vgatherqps"), - &Opcode::VHADDPD => write!(f, "vhaddpd"), - &Opcode::VHSUBPD => write!(f, "vhsubpd"), - &Opcode::VINSERTF128 => write!(f, "vinsertf128"), - &Opcode::VINSERTI128 => write!(f, "vinserti128"), - &Opcode::VINSERTPS => write!(f, "vinsertps"), - &Opcode::VMASKMOVDQU => write!(f, "vmaskmovdqu"), - &Opcode::VMASKMOVPD => write!(f, "vmaskmovpd"), - &Opcode::VMASKMOVPS => write!(f, "vmaskmovps"), - &Opcode::VMAXPD => write!(f, "vmaxpd"), - &Opcode::VMAXPS => write!(f, "vmaxps"), - &Opcode::VMINPD => write!(f, "vminpd"), - &Opcode::VMINPS => write!(f, "vminps"), - &Opcode::VMOVAPD => write!(f, "vmovapd"), - &Opcode::VMOVAPS => write!(f, "vmovaps"), - &Opcode::VMOVD => write!(f, "vmovd"), - &Opcode::VMOVDQA => write!(f, "vmovdqa"), - &Opcode::VMOVDQU => write!(f, "vmovdqu"), - &Opcode::VMOVHLPS => write!(f, "vmovhlps"), - &Opcode::VMOVHPD => write!(f, "vmovhpd"), - &Opcode::VMOVHPS => write!(f, "vmovhps"), - &Opcode::VMOVLHPS => write!(f, "vmovlhps"), - &Opcode::VMOVLPD => write!(f, "vmovlpd"), - &Opcode::VMOVLPS => write!(f, "vmovlps"), - &Opcode::VMOVMSKPD => write!(f, "vmovmskpd"), - &Opcode::VMOVMSKPS => write!(f, "vmovmskps"), - &Opcode::VMOVNTDQ => write!(f, "vmovntdq"), - &Opcode::VMOVNTDQA => write!(f, "vmovntdqa"), - &Opcode::VMOVNTPD => write!(f, "vmovntpd"), - &Opcode::VMOVNTPS => write!(f, "vmovntps"), - &Opcode::VMOVQ => write!(f, "vmovq"), - &Opcode::VMOVSHDUP => write!(f, "vmovshdup"), - &Opcode::VMOVSLDUP => write!(f, "vmovsldup"), - &Opcode::VMOVUPD => write!(f, "vmovupd"), - &Opcode::VMOVUPS => write!(f, "vmovups"), - &Opcode::VMPSADBW => write!(f, "vmpsadbw"), - &Opcode::VMULPD => write!(f, "vmulpd"), - &Opcode::VMULPS => write!(f, "vmulps"), - &Opcode::VPABSB => write!(f, "vpabsb"), - &Opcode::VPABSD => write!(f, "vpabsd"), - &Opcode::VPABSW => write!(f, "vpabsw"), - &Opcode::VPACKSSDW => write!(f, "vpackssdw"), - &Opcode::VPACKSSWB => write!(f, "vpacksswb"), - &Opcode::VPACKUSWB => write!(f, "vpackuswb"), - &Opcode::VPADDB => write!(f, "vpaddb"), - &Opcode::VPADDD => write!(f, "vpaddd"), - &Opcode::VPADDQ => write!(f, "vpaddq"), - &Opcode::VPADDSB => write!(f, "vpaddsb"), - &Opcode::VPADDSW => write!(f, "vpaddsw"), - &Opcode::VPADDUSB => write!(f, "vpaddusb"), - &Opcode::VPADDUSW => write!(f, "vpaddusw"), - &Opcode::VPADDW => write!(f, "vpaddw"), - &Opcode::VPALIGNR => write!(f, "vpalignr"), - &Opcode::VPAND => write!(f, "vpand"), - &Opcode::VPANDN => write!(f, "vpandn"), - &Opcode::VPAVGB => write!(f, "vpavgb"), - &Opcode::VPAVGW => write!(f, "vpavgw"), - &Opcode::VPBLENDD => write!(f, "vpblendd"), - &Opcode::VPBLENDVB => write!(f, "vpblendvb"), - &Opcode::VPBLENDW => write!(f, "vpblendw"), - &Opcode::VPBROADCASTB => write!(f, "vpbroadcastb"), - &Opcode::VPBROADCASTD => write!(f, "vpbroadcastd"), - &Opcode::VPBROADCASTQ => write!(f, "vpbroadcastq"), - &Opcode::VPBROADCASTW => write!(f, "vpbroadcastw"), - &Opcode::VPCLMULQDQ => write!(f, "vpclmulqdq"), - &Opcode::VPCMPEQB => write!(f, "vpcmpeqb"), - &Opcode::VPCMPEQD => write!(f, "vpcmpeqd"), - &Opcode::VPCMPEQQ => write!(f, "vpcmpeqq"), - &Opcode::VPCMPEQW => write!(f, "vpcmpeqw"), - &Opcode::VPCMPGTB => write!(f, "vpcmpgtb"), - &Opcode::VPCMPGTD => write!(f, "vpcmpgtd"), - &Opcode::VPCMPGTQ => write!(f, "vpcmpgtq"), - &Opcode::VPCMPGTW => write!(f, "vpcmpgtw"), - &Opcode::VPCMPISTRI => write!(f, "vpcmpistri"), - &Opcode::VPCMPISTRM => write!(f, "vpcmpistrm"), - &Opcode::VPERM2F128 => write!(f, "vperm2f128"), - &Opcode::VPERM2I128 => write!(f, "vperm2i128"), - &Opcode::VPERMD => write!(f, "vpermd"), - &Opcode::VPERMILPD => write!(f, "vpermilpd"), - &Opcode::VPERMILPS => write!(f, "vpermilps"), - &Opcode::VPERMPD => write!(f, "vpermpd"), - &Opcode::VPERMPS => write!(f, "vpermps"), - &Opcode::VPERMQ => write!(f, "vpermq"), - &Opcode::VPEXTRB => write!(f, "vpextrb"), - &Opcode::VPEXTRD => write!(f, "vpextrd"), - &Opcode::VPEXTRQ => write!(f, "vpextrq"), - &Opcode::VPEXTRW => write!(f, "vpextrw"), - &Opcode::VPGATHERDD => write!(f, "vpgatherdd"), - &Opcode::VPGATHERDQ => write!(f, "vpgatherdq"), - &Opcode::VPGATHERQD => write!(f, "vpgatherqd"), - &Opcode::VPGATHERQQ => write!(f, "vpgatherqq"), - &Opcode::VPHADDD => write!(f, "vphaddd"), - &Opcode::VPHADDSW => write!(f, "vphaddsw"), - &Opcode::VPHADDUBSW => write!(f, "vphaddubsw"), - &Opcode::VPHADDW => write!(f, "vphaddw"), - &Opcode::VPHMINPOSUW => write!(f, "vphminposuw"), - &Opcode::VPHSUBD => write!(f, "vphsubd"), - &Opcode::VPHSUBSW => write!(f, "vphsubsw"), - &Opcode::VPHSUBW => write!(f, "vphsubw"), - &Opcode::VPINSRB => write!(f, "vpinsrb"), - &Opcode::VPINSRD => write!(f, "vpinsrd"), - &Opcode::VPINSRQ => write!(f, "vpinsrq"), - &Opcode::VPINSRW => write!(f, "vpinsrw"), - &Opcode::VPMADDWD => write!(f, "vpmaddwd"), - &Opcode::VPMASKMOVD => write!(f, "vpmaskmovd"), - &Opcode::VPMASKMOVQ => write!(f, "vpmaskmovq"), - &Opcode::VPMAXSB => write!(f, "vpmaxsb"), - &Opcode::VPMAXSD => write!(f, "vpmaxsd"), - &Opcode::VPMAXSW => write!(f, "vpmaxsw"), - &Opcode::VPMAXUD => write!(f, "vpmaxud"), - &Opcode::VPMINSD => write!(f, "vpminsd"), - &Opcode::VPMINUD => write!(f, "vpminud"), - &Opcode::VPMOVMSKB => write!(f, "vpmovmskb"), - &Opcode::VPMOVSXBD => write!(f, "vpmovsxbd"), - &Opcode::VPMOVSXBQ => write!(f, "vpmovsxbq"), - &Opcode::VPMOVSXBW => write!(f, "vpmovsxbw"), - &Opcode::VPMOVSXDQ => write!(f, "vpmovsxdq"), - &Opcode::VPMOVSXWD => write!(f, "vpmovsxwd"), - &Opcode::VPMOVSXWQ => write!(f, "vpmovsxwq"), - &Opcode::VPMOVZXBD => write!(f, "vpmovzxbd"), - &Opcode::VPMOVZXBQ => write!(f, "vpmovzxbq"), - &Opcode::VPMOVZXBW => write!(f, "vpmovzxbw"), - &Opcode::VPMOVZXDQ => write!(f, "vpmovzxdq"), - &Opcode::VPMOVZXWD => write!(f, "vpmovzxwd"), - &Opcode::VPMOVZXWQ => write!(f, "vpmovzxwq"), - &Opcode::VPMULDQ => write!(f, "vpmuldq"), - &Opcode::VPMULHRSW => write!(f, "vpmulhrsw"), - &Opcode::VPMULHUW => write!(f, "vpmulhuw"), - &Opcode::VPMULHW => write!(f, "vpmulhw"), - &Opcode::VPMULLD => write!(f, "vpmulld"), - &Opcode::VPMULLW => write!(f, "vpmullw"), - &Opcode::VPMULUDQ => write!(f, "vpmuludq"), - &Opcode::VPOR => write!(f, "vpor"), - &Opcode::VPSADBW => write!(f, "vpsadbw"), - &Opcode::VPSHUFB => write!(f, "vpshufb"), - &Opcode::VPSHUFD => write!(f, "vpshufd"), - &Opcode::VPSIGNB => write!(f, "vpsignb"), - &Opcode::VPSIGND => write!(f, "vpsignd"), - &Opcode::VPSIGNW => write!(f, "vpsignw"), - &Opcode::VPSLLD => write!(f, "vpslld"), - &Opcode::VPSLLDQ => write!(f, "vpslldq"), - &Opcode::VPSLLQ => write!(f, "vpsllq"), - &Opcode::VPSLLVD => write!(f, "vpsllvd"), - &Opcode::VPSLLVQ => write!(f, "vpsllvq"), - &Opcode::VPSLLW => write!(f, "vpsllw"), - &Opcode::VPSRAD => write!(f, "vpsrad"), - &Opcode::VPSRAVD => write!(f, "vpsravd"), - &Opcode::VPSRAW => write!(f, "vpsraw"), - &Opcode::VPSRLD => write!(f, "vpsrld"), - &Opcode::VPSRLDQ => write!(f, "vpsrldq"), - &Opcode::VPSRLQ => write!(f, "vpsrlq"), - &Opcode::VPSRLVD => write!(f, "vpsrlvd"), - &Opcode::VPSRLVQ => write!(f, "vpsrlvq"), - &Opcode::VPSRLW => write!(f, "vpsrlw"), - &Opcode::VPSUBB => write!(f, "vpsubb"), - &Opcode::VPSUBD => write!(f, "vpsubd"), - &Opcode::VPSUBQ => write!(f, "vpsubq"), - &Opcode::VPSUBSB => write!(f, "vpsubsb"), - &Opcode::VPSUBSW => write!(f, "vpsubsw"), - &Opcode::VPSUBUSB => write!(f, "vpsubusb"), - &Opcode::VPSUBUSW => write!(f, "vpsubusw"), - &Opcode::VPSUBW => write!(f, "vpsubw"), - &Opcode::VPTEST => write!(f, "vptest"), - &Opcode::VPUNPCKHBW => write!(f, "vpunpckhbw"), - &Opcode::VPUNPCKHDQ => write!(f, "vpunpckhdq"), - &Opcode::VPUNPCKHQDQ => write!(f, "vpunpckhqdq"), - &Opcode::VPUNPCKHWD => write!(f, "vpunpckhwd"), - &Opcode::VPUNPCKLBW => write!(f, "vpunpcklbw"), - &Opcode::VPUNPCKLDQ => write!(f, "vpunpckldq"), - &Opcode::VPUNPCKLQDQ => write!(f, "vpunpcklqdq"), - &Opcode::VPUNPCKLWD => write!(f, "vpunpcklwd"), - &Opcode::VPXOR => write!(f, "vpxor"), - &Opcode::VRCPPS => write!(f, "vrcpps"), - &Opcode::VROUNDPD => write!(f, "vroundpd"), - &Opcode::VROUNDPS => write!(f, "vroundps"), - &Opcode::VRSQRTPS => write!(f, "vrsqrtps"), - &Opcode::VSHUFPD => write!(f, "vshufpd"), - &Opcode::VSHUFPS => write!(f, "vshufps"), - &Opcode::VSQRTPD => write!(f, "vsqrtpd"), - &Opcode::VSQRTPS => write!(f, "vsqrtps"), - &Opcode::VSUBPD => write!(f, "vsubpd"), - &Opcode::VSUBPS => write!(f, "vsubps"), - &Opcode::VTESTPD => write!(f, "vtestpd"), - &Opcode::VTESTPS => write!(f, "vtestps"), - &Opcode::VUNPCKHPD => write!(f, "vunpckhpd"), - &Opcode::VUNPCKHPS => write!(f, "vunpckhps"), - &Opcode::VUNPCKLPD => write!(f, "vunpcklpd"), - &Opcode::VUNPCKLPS => write!(f, "vunpcklps"), - &Opcode::VXORPD => write!(f, "vxorpd"), - &Opcode::VXORPS => write!(f, "vxorps"), - &Opcode::VZEROUPPER => write!(f, "vzeroupper"), - &Opcode::VMOVDDUP => write!(f, "vmovddup"), - &Opcode::VPSHUFLW => write!(f, "vpshuflw"), - &Opcode::VHADDPS => write!(f, "vhaddps"), - &Opcode::VHSUBPS => write!(f, "vhsubps"), - &Opcode::VADDSUBPS => write!(f, "vaddsubps"), - &Opcode::VCVTPD2DQ => write!(f, "vcvtpd2dq"), - &Opcode::VLDDQU => write!(f, "vlddqu"), - &Opcode::VADDSD => write!(f, "vaddsd"), - &Opcode::VADDSS => write!(f, "vaddss"), - &Opcode::VCMPSD => write!(f, "vcmpsd"), - &Opcode::VCMPSS => write!(f, "vcmpss"), - &Opcode::VCOMISD => write!(f, "vcomisd"), - &Opcode::VCOMISS => write!(f, "vcomiss"), - &Opcode::VCVTSD2SI => write!(f, "vcvtsd2si"), - &Opcode::VCVTSD2SS => write!(f, "vcvtsd2ss"), - &Opcode::VCVTSI2SD => write!(f, "vcvtsi2sd"), - &Opcode::VCVTSI2SS => write!(f, "vcvtsi2ss"), - &Opcode::VCVTSS2SD => write!(f, "vcvtss2sd"), - &Opcode::VCVTSS2SI => write!(f, "vcvtss2si"), - &Opcode::VCVTTSD2SI => write!(f, "vcvttsd2si"), - &Opcode::VCVTTSS2SI => write!(f, "vcvttss2si"), - &Opcode::VDIVSD => write!(f, "vdivsd"), - &Opcode::VDIVSS => write!(f, "vdivss"), - &Opcode::VFMADD132SD => write!(f, "vfmadd132sd"), - &Opcode::VFMADD132SS => write!(f, "vfmadd132ss"), - &Opcode::VFMADD213SD => write!(f, "vfmadd213sd"), - &Opcode::VFMADD213SS => write!(f, "vfmadd213ss"), - &Opcode::VFMADD231SD => write!(f, "vfmadd231sd"), - &Opcode::VFMADD231SS => write!(f, "vfmadd231ss"), - &Opcode::VFMSUB132SD => write!(f, "vfmsub132sd"), - &Opcode::VFMSUB132SS => write!(f, "vfmsub132ss"), - &Opcode::VFMSUB213SD => write!(f, "vfmsub213sd"), - &Opcode::VFMSUB213SS => write!(f, "vfmsub213ss"), - &Opcode::VFMSUB231SD => write!(f, "vfmsub231sd"), - &Opcode::VFMSUB231SS => write!(f, "vfmsub231ss"), - &Opcode::VFNMADD132SD => write!(f, "vfnmadd132sd"), - &Opcode::VFNMADD132SS => write!(f, "vfnmadd132ss"), - &Opcode::VFNMADD213SD => write!(f, "vfnmadd213sd"), - &Opcode::VFNMADD213SS => write!(f, "vfnmadd213ss"), - &Opcode::VFNMADD231SD => write!(f, "vfnmadd231sd"), - &Opcode::VFNMADD231SS => write!(f, "vfnmadd231ss"), - &Opcode::VFNMSUB132SD => write!(f, "vfnmsub132sd"), - &Opcode::VFNMSUB132SS => write!(f, "vfnmsub132ss"), - &Opcode::VFNMSUB213SD => write!(f, "vfnmsub213sd"), - &Opcode::VFNMSUB213SS => write!(f, "vfnmsub213ss"), - &Opcode::VFNMSUB231SD => write!(f, "vfnmsub231sd"), - &Opcode::VFNMSUB231SS => write!(f, "vfnmsub231ss"), - &Opcode::VMAXSD => write!(f, "vmaxsd"), - &Opcode::VMAXSS => write!(f, "vmaxss"), - &Opcode::VMINSD => write!(f, "vminsd"), - &Opcode::VMINSS => write!(f, "vminss"), - &Opcode::VMOVSD => write!(f, "vmovsd"), - &Opcode::VMOVSS => write!(f, "vmovss"), - &Opcode::VMULSD => write!(f, "vmulsd"), - &Opcode::VMULSS => write!(f, "vmulss"), - &Opcode::VRCPSS => write!(f, "vrcpss"), - &Opcode::VROUNDSD => write!(f, "vroundsd"), - &Opcode::VROUNDSS => write!(f, "vroundss"), - &Opcode::VRSQRTSS => write!(f, "vrsqrtss"), - &Opcode::VSQRTSD => write!(f, "vsqrtsd"), - &Opcode::VSQRTSS => write!(f, "vsqrtss"), - &Opcode::VSUBSD => write!(f, "vsubsd"), - &Opcode::VSUBSS => write!(f, "vsubss"), - &Opcode::VUCOMISD => write!(f, "vucomisd"), - &Opcode::VUCOMISS => write!(f, "vucomiss"), - &Opcode::PCLMULQDQ => write!(f, "pclmulqdq"), - &Opcode::AESKEYGENASSIST => write!(f, "aeskeygenassist"), - &Opcode::AESIMC => write!(f, "aesimc"), - &Opcode::AESENC => write!(f, "aesenc"), - &Opcode::AESENCLAST => write!(f, "aesenclast"), - &Opcode::AESDEC => write!(f, "aesdec"), - &Opcode::AESDECLAST => write!(f, "aesdeclast"), - &Opcode::PCMPGTQ => write!(f, "pcmpgtq"), - &Opcode::PCMPISTRM => write!(f, "pcmpistrm"), - &Opcode::PCMPISTRI => write!(f, "pcmpistri"), - &Opcode::PCMPESTRI => write!(f, "pcmpestri"), - &Opcode::PACKUSDW => write!(f, "packusdw"), - &Opcode::PCMPESTRM => write!(f, "pcmpestrm"), - &Opcode::PCMPEQQ => write!(f, "pcmpeqq"), - &Opcode::PTEST => write!(f, "ptest"), - &Opcode::PHMINPOSUW => write!(f, "phminposuw"), - &Opcode::MPSADBW => write!(f, "mpsadbw"), - &Opcode::PMOVZXDQ => write!(f, "pmovzxdq"), - &Opcode::PMOVSXDQ => write!(f, "pmovsxdq"), - &Opcode::PMOVZXBD => write!(f, "pmovzxbd"), - &Opcode::PMOVSXBD => write!(f, "pmovsxbd"), - &Opcode::PMOVZXWQ => write!(f, "pmovzxwq"), - &Opcode::PMOVSXWQ => write!(f, "pmovsxwq"), - &Opcode::PMOVZXBQ => write!(f, "pmovzxbq"), - &Opcode::PMOVSXBQ => write!(f, "pmovsxbq"), - &Opcode::PMOVSXWD => write!(f, "pmovsxwd"), - &Opcode::PMOVZXWD => write!(f, "pmovzxwd"), - &Opcode::PEXTRQ => write!(f, "pextrq"), - &Opcode::PEXTRB => write!(f, "pextrb"), - &Opcode::PMOVSXBW => write!(f, "pmovsxbw"), - &Opcode::PMOVZXBW => write!(f, "pmovzxbw"), - &Opcode::PINSRQ => write!(f, "pinsrq"), - &Opcode::PINSRD => write!(f, "pinsrd"), - &Opcode::PINSRB => write!(f, "pinsrb"), - &Opcode::EXTRACTPS => write!(f, "extractps"), - &Opcode::INSERTPS => write!(f, "insertps"), - &Opcode::ROUNDSS => write!(f, "roundss"), - &Opcode::ROUNDSD => write!(f, "roundsd"), - &Opcode::ROUNDPS => write!(f, "roundps"), - &Opcode::ROUNDPD => write!(f, "roundpd"), - &Opcode::PMAXSB => write!(f, "pmaxsb"), - &Opcode::PMAXUW => write!(f, "pmaxuw"), - &Opcode::PMAXUD => write!(f, "pmaxud"), - &Opcode::PMINSD => write!(f, "pminsd"), - &Opcode::PMINSB => write!(f, "pminsb"), - &Opcode::PMINUD => write!(f, "pminud"), - &Opcode::PMINUW => write!(f, "pminuw"), - &Opcode::BLENDW => write!(f, "blendw"), - &Opcode::BLENDDVB => write!(f, "blenddvb"), - &Opcode::BLENDVPS => write!(f, "blendvps"), - &Opcode::BLENDVPD => write!(f, "blendvpd"), - &Opcode::BLENDPS => write!(f, "blendps"), - &Opcode::BLENDPD => write!(f, "blendpd"), - &Opcode::PMULDQ => write!(f, "pmuldq"), - &Opcode::MOVNTDQA => write!(f, "movntdqa"), - &Opcode::PMULLD => write!(f, "pmulld"), - &Opcode::PALIGNR => write!(f, "palignr"), - &Opcode::PSIGNW => write!(f, "psignw"), - &Opcode::PSIGND => write!(f, "psignd"), - &Opcode::PSIGNB => write!(f, "psignb"), - &Opcode::PSHUFB => write!(f, "pshufb"), - &Opcode::PMULHRSU => write!(f, "pmulhrsu"), - &Opcode::PMADDUBSW => write!(f, "pmaddubsw"), - &Opcode::PABSD => write!(f, "pabsd"), - &Opcode::PABSW => write!(f, "pabsw"), - &Opcode::PABSB => write!(f, "pabsb"), - &Opcode::PHSUBSW => write!(f, "phsubsw"), - &Opcode::PHSUBW => write!(f, "phsubw"), - &Opcode::PHSUBD => write!(f, "phsubd"), - &Opcode::PHADDD => write!(f, "phaddd"), - &Opcode::PHADDSW => write!(f, "phaddsw"), - &Opcode::PHADDW => write!(f, "phaddw"), - &Opcode::HSUBPD => write!(f, "hsubpd"), - &Opcode::HADDPD => write!(f, "haddpd"), - &Opcode::ADDSUBPD => write!(f, "addsubpd"), - &Opcode::Invalid => write!(f, "invalid"), - } - } -} - -impl > Colorize for Opcode { - fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { - match self { - Opcode::VHADDPS | - Opcode::VHSUBPS | - Opcode::VADDSUBPS | - Opcode::VADDPD | - Opcode::VADDPS | - Opcode::VADDSD | - Opcode::VADDSS | - Opcode::VADDSUBPD | - Opcode::VFMADD132PD | - Opcode::VFMADD132PS | - Opcode::VFMADD132SD | - Opcode::VFMADD132SS | - Opcode::VFMADD213PD | - Opcode::VFMADD213PS | - Opcode::VFMADD213SD | - Opcode::VFMADD213SS | - Opcode::VFMADD231PD | - Opcode::VFMADD231PS | - Opcode::VFMADD231SD | - Opcode::VFMADD231SS | - Opcode::VFMADDSUB132PD | - Opcode::VFMADDSUB132PS | - Opcode::VFMADDSUB213PD | - Opcode::VFMADDSUB213PS | - Opcode::VFMADDSUB231PD | - Opcode::VFMADDSUB231PS | - Opcode::VFMSUB132PD | - Opcode::VFMSUB132PS | - Opcode::VFMSUB132SD | - Opcode::VFMSUB132SS | - Opcode::VFMSUB213PD | - Opcode::VFMSUB213PS | - Opcode::VFMSUB213SD | - Opcode::VFMSUB213SS | - Opcode::VFMSUB231PD | - Opcode::VFMSUB231PS | - Opcode::VFMSUB231SD | - Opcode::VFMSUB231SS | - Opcode::VFMSUBADD132PD | - Opcode::VFMSUBADD132PS | - Opcode::VFMSUBADD213PD | - Opcode::VFMSUBADD213PS | - Opcode::VFMSUBADD231PD | - Opcode::VFMSUBADD231PS | - Opcode::VFNMADD132PD | - Opcode::VFNMADD132PS | - Opcode::VFNMADD132SD | - Opcode::VFNMADD132SS | - Opcode::VFNMADD213PD | - Opcode::VFNMADD213PS | - Opcode::VFNMADD213SD | - Opcode::VFNMADD213SS | - Opcode::VFNMADD231PD | - Opcode::VFNMADD231PS | - Opcode::VFNMADD231SD | - Opcode::VFNMADD231SS | - Opcode::VFNMSUB132PD | - Opcode::VFNMSUB132PS | - Opcode::VFNMSUB132SD | - Opcode::VFNMSUB132SS | - Opcode::VFNMSUB213PD | - Opcode::VFNMSUB213PS | - Opcode::VFNMSUB213SD | - Opcode::VFNMSUB213SS | - Opcode::VFNMSUB231PD | - Opcode::VFNMSUB231PS | - Opcode::VFNMSUB231SD | - Opcode::VFNMSUB231SS | - Opcode::VDIVPD | - Opcode::VDIVPS | - Opcode::VDIVSD | - Opcode::VDIVSS | - Opcode::VHADDPD | - Opcode::VHSUBPD | - Opcode::HADDPD | - Opcode::HSUBPD | - Opcode::VMULPD | - Opcode::VMULPS | - Opcode::VMULSD | - Opcode::VMULSS | - Opcode::VPABSB | - Opcode::VPABSD | - Opcode::VPABSW | - Opcode::PABSB | - Opcode::PABSD | - Opcode::PABSW | - Opcode::VPSIGNB | - Opcode::VPSIGND | - Opcode::VPSIGNW | - Opcode::PSIGNB | - Opcode::PSIGND | - Opcode::PSIGNW | - Opcode::VPADDB | - Opcode::VPADDD | - Opcode::VPADDQ | - Opcode::VPADDSB | - Opcode::VPADDSW | - Opcode::VPADDUSB | - Opcode::VPADDUSW | - Opcode::VPADDW | - Opcode::VPAVGB | - Opcode::VPAVGW | - Opcode::VPMULDQ | - Opcode::VPMULHRSW | - Opcode::VPMULHUW | - Opcode::VPMULHW | - Opcode::VPMULLD | - Opcode::VPMULLW | - Opcode::VPMULUDQ | - Opcode::PCLMULQDQ | - Opcode::PMULDQ | - Opcode::PMULHRSU | - Opcode::PMULLD | - Opcode::VPSUBB | - Opcode::VPSUBD | - Opcode::VPSUBQ | - Opcode::VPSUBSB | - Opcode::VPSUBSW | - Opcode::VPSUBUSB | - Opcode::VPSUBUSW | - Opcode::VPSUBW | - Opcode::VROUNDPD | - Opcode::VROUNDPS | - Opcode::VRSQRTPS | - Opcode::VSQRTPD | - Opcode::VSQRTPS | - Opcode::VSUBPD | - Opcode::VSUBPS | - Opcode::VSUBSD | - Opcode::VSUBSS | - Opcode::VRCPSS | - Opcode::VROUNDSD | - Opcode::VROUNDSS | - Opcode::ROUNDPD | - Opcode::ROUNDPS | - Opcode::ROUNDSD | - Opcode::ROUNDSS | - Opcode::VRSQRTSS | - Opcode::VSQRTSD | - Opcode::VSQRTSS | - Opcode::VPSADBW | - Opcode::VMPSADBW | - Opcode::VPHADDD | - Opcode::VPHADDSW | - Opcode::VPHADDW | - Opcode::VPHSUBD | - Opcode::VPHSUBSW | - Opcode::VPHSUBW | - Opcode::VPHADDUBSW | - Opcode::VPMADDWD | - Opcode::VDPPD | - Opcode::VDPPS | - Opcode::VRCPPS | - Opcode::VPAND | - Opcode::VPANDN | - Opcode::VPOR | - Opcode::VPXOR | - Opcode::VXORPD | - Opcode::VXORPS | - Opcode::VPSLLD | - Opcode::VPSLLDQ | - Opcode::VPSLLQ | - Opcode::VPSLLVD | - Opcode::VPSLLVQ | - Opcode::VPSLLW | - Opcode::VPSRAD | - Opcode::VPSRAVD | - Opcode::VPSRAW | - Opcode::VPSRLD | - Opcode::VPSRLDQ | - Opcode::VPSRLQ | - Opcode::VPSRLVD | - Opcode::VPSRLVQ | - Opcode::VPSRLW | - Opcode::PHADDD | - Opcode::PHADDSW | - Opcode::PHADDW | - Opcode::PHSUBD | - Opcode::PHSUBSW | - Opcode::PHSUBW | - Opcode::PMADDUBSW | - Opcode::ADDSUBPD | - Opcode::MPSADBW | - Opcode::RCPSS | - Opcode::RSQRTSS | - Opcode::SQRTSD | - Opcode::ADDSD | - Opcode::SUBSD | - Opcode::MULSD | - Opcode::DIVSD | - Opcode::SQRTSS | - Opcode::ADDSS | - Opcode::SUBSS | - Opcode::MULSS | - Opcode::DIVSS | - Opcode::HADDPS | - Opcode::HSUBPS | - Opcode::ADDSUBPS | - Opcode::XADD| - Opcode::DIV | - Opcode::IDIV | - Opcode::MUL | - Opcode::NEG | - Opcode::NOT | - Opcode::SAR | - Opcode::SAL | - Opcode::SHR | - Opcode::SHRD | - Opcode::SHL | - Opcode::RCR | - Opcode::RCL | - Opcode::ROR | - Opcode::ROL | - Opcode::INC | - Opcode::DEC | - Opcode::SBB | - Opcode::AND | - Opcode::XOR | - Opcode::OR | - Opcode::LEA | - Opcode::ADD | - Opcode::ADC | - Opcode::SUB | - Opcode::POPCNT | - Opcode::BT | - Opcode::BTS | - Opcode::BTR | - Opcode::BTC | - Opcode::BSF | - Opcode::BSR | - Opcode::TZCNT | - Opcode::ANDN | - Opcode::BEXTR | - Opcode::BLSI | - Opcode::BLSMSK | - Opcode::BLSR | - Opcode::ADDPS | - Opcode::ANDNPS | - Opcode::ANDPS | - Opcode::COMISS | - Opcode::DIVPS | - Opcode::MULPS | - Opcode::ORPS | - Opcode::PADDB | - Opcode::PADDD | - Opcode::PADDQ | - Opcode::PADDSB | - Opcode::PADDSW | - Opcode::PADDUSB | - Opcode::PADDUSW | - Opcode::PADDW | - Opcode::PAND | - Opcode::PANDN | - Opcode::PAVGB | - Opcode::PAVGW | - Opcode::PMADDWD | - Opcode::PMULHUW | - Opcode::PMULHW | - Opcode::PMULLW | - Opcode::PMULUDQ | - Opcode::POR | - Opcode::PSADBW | - Opcode::PSHUFD | - Opcode::PSHUFW | - Opcode::PSHUFB | - Opcode::PSLLD | - Opcode::PSLLDQ | - Opcode::PSLLQ | - Opcode::PSLLW | - Opcode::PSRAD | - Opcode::PSRAW | - Opcode::PSRLD | - Opcode::PSRLDQ | - Opcode::PSRLQ | - Opcode::PSRLW | - Opcode::PSUBB | - Opcode::PSUBD | - Opcode::PSUBQ | - Opcode::PSUBSB | - Opcode::PSUBSW | - Opcode::PSUBUSB | - Opcode::PSUBUSW | - Opcode::PSUBW | - Opcode::PXOR | - Opcode::RSQRTPS | - Opcode::SQRTPS | - Opcode::SUBPS | - Opcode::XORPS | - Opcode::RCPPS | - Opcode::SHLD | - Opcode::SLHD | - Opcode::UCOMISS | - Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) } - Opcode::POPF | - Opcode::PUSHF | - Opcode::ENTER | - Opcode::LEAVE | - Opcode::PUSH | - Opcode::POP => { write!(out, "{}", colors.stack_op(self)) } - Opcode::WAIT | - Opcode::PREFETCHNTA | - Opcode::PREFETCH0 | - Opcode::PREFETCH1 | - Opcode::PREFETCH2 | - Opcode::NOP => { write!(out, "{}", colors.nop_op(self)) } - - /* Control flow */ - Opcode::HLT | - Opcode::INT | - Opcode::INTO | - Opcode::IRET | - Opcode::RETF | - Opcode::RETURN => { write!(out, "{}", colors.stop_op(self)) } - Opcode::CALL | - Opcode::CALLF | - Opcode::JMP | - Opcode::JMPF | - Opcode::JO | - Opcode::JNO | - Opcode::JB | - Opcode::JNB | - Opcode::JZ | - Opcode::JNZ | - Opcode::JA | - Opcode::JNA | - Opcode::JS | - Opcode::JNS | - Opcode::JP | - Opcode::JNP | - Opcode::JL | - Opcode::JGE | - Opcode::JLE | - Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) } - - /* Data transfer */ - Opcode::VCVTDQ2PD | - Opcode::VCVTDQ2PS | - Opcode::VCVTPD2DQ | - Opcode::VCVTPD2PS | - Opcode::VCVTPH2PS | - Opcode::VCVTPS2DQ | - Opcode::VCVTPS2PD | - Opcode::VCVTPS2PH | - Opcode::VCVTTPD2DQ | - Opcode::VCVTTPS2DQ | - Opcode::VCVTSD2SI | - Opcode::VCVTSD2SS | - Opcode::VCVTSI2SD | - Opcode::VCVTSI2SS | - Opcode::VCVTSS2SD | - Opcode::VCVTSS2SI | - Opcode::VCVTTSD2SI | - Opcode::VCVTTSS2SI | - Opcode::VMOVDDUP | - Opcode::VPSHUFLW | - Opcode::VBLENDPD | - Opcode::VBLENDPS | - Opcode::VBLENDVPD | - Opcode::VBLENDVPS | - Opcode::BLENDDVB | - Opcode::BLENDPD | - Opcode::BLENDPS | - Opcode::BLENDVPD | - Opcode::BLENDVPS | - Opcode::BLENDW | - Opcode::VBROADCASTF128 | - Opcode::VBROADCASTI128 | - Opcode::VBROADCASTSD | - Opcode::VBROADCASTSS | - Opcode::VEXTRACTF128 | - Opcode::VEXTRACTI128 | - Opcode::VEXTRACTPS | - Opcode::EXTRACTPS | - Opcode::VGATHERDPD | - Opcode::VGATHERDPS | - Opcode::VGATHERQPD | - Opcode::VGATHERQPS | - Opcode::VINSERTF128 | - Opcode::VINSERTI128 | - Opcode::VINSERTPS | - Opcode::INSERTPS | - Opcode::VMASKMOVDQU | - Opcode::VMASKMOVPD | - Opcode::VMASKMOVPS | - Opcode::VMOVAPD | - Opcode::VMOVAPS | - Opcode::VMOVD | - Opcode::VMOVDQA | - Opcode::VMOVDQU | - Opcode::VMOVHLPS | - Opcode::VMOVHPD | - Opcode::VMOVHPS | - Opcode::VMOVLHPS | - Opcode::VMOVLPD | - Opcode::VMOVLPS | - Opcode::VMOVMSKPD | - Opcode::VMOVMSKPS | - Opcode::VMOVNTDQ | - Opcode::VMOVNTDQA | - Opcode::VMOVNTPD | - Opcode::VMOVNTPS | - Opcode::MOVNTDQA | - Opcode::VMOVQ | - Opcode::VMOVSHDUP | - Opcode::VMOVSLDUP | - Opcode::VMOVUPD | - Opcode::VMOVUPS | - Opcode::VMOVSD | - Opcode::VMOVSS | - - Opcode::VPBLENDD | - Opcode::VPBLENDVB | - Opcode::VPBLENDW | - Opcode::VPBROADCASTB | - Opcode::VPBROADCASTD | - Opcode::VPBROADCASTQ | - Opcode::VPBROADCASTW | - Opcode::VPGATHERDD | - Opcode::VPGATHERDQ | - Opcode::VPGATHERQD | - Opcode::VPGATHERQQ | - Opcode::VPCLMULQDQ | - Opcode::VPMOVMSKB | - Opcode::VPMOVSXBD | - Opcode::VPMOVSXBQ | - Opcode::VPMOVSXBW | - Opcode::VPMOVSXDQ | - Opcode::VPMOVSXWD | - Opcode::VPMOVSXWQ | - Opcode::VPMOVZXBD | - Opcode::VPMOVZXBQ | - Opcode::VPMOVZXBW | - Opcode::VPMOVZXDQ | - Opcode::VPMOVZXWD | - Opcode::VPMOVZXWQ | - Opcode::PMOVSXBD | - Opcode::PMOVSXBQ | - Opcode::PMOVSXBW | - Opcode::PMOVSXDQ | - Opcode::PMOVSXWD | - Opcode::PMOVSXWQ | - Opcode::PMOVZXBD | - Opcode::PMOVZXBQ | - Opcode::PMOVZXBW | - Opcode::PMOVZXDQ | - Opcode::PMOVZXWD | - Opcode::PMOVZXWQ | - Opcode::VUNPCKHPD | - Opcode::VUNPCKHPS | - Opcode::VUNPCKLPD | - Opcode::VUNPCKLPS | - Opcode::VPUNPCKHBW | - Opcode::VPUNPCKHDQ | - Opcode::VPUNPCKHQDQ | - Opcode::VPUNPCKHWD | - Opcode::VPUNPCKLBW | - Opcode::VPUNPCKLDQ | - Opcode::VPUNPCKLQDQ | - Opcode::VPUNPCKLWD | - Opcode::VSHUFPD | - Opcode::VSHUFPS | - Opcode::VPACKSSDW | - Opcode::PACKUSDW | - Opcode::VPACKSSWB | - Opcode::VPACKUSWB | - Opcode::VPALIGNR | - Opcode::PALIGNR | - Opcode::VPERM2F128 | - Opcode::VPERM2I128 | - Opcode::VPERMD | - Opcode::VPERMILPD | - Opcode::VPERMILPS | - Opcode::VPERMPD | - Opcode::VPERMPS | - Opcode::VPERMQ | - Opcode::VPEXTRB | - Opcode::VPEXTRD | - Opcode::VPEXTRQ | - Opcode::VPEXTRW | - Opcode::PEXTRB | - Opcode::PEXTRQ | - Opcode::PINSRB | - Opcode::PINSRD | - Opcode::PINSRQ | - Opcode::VPINSRB | - Opcode::VPINSRD | - Opcode::VPINSRQ | - Opcode::VPINSRW | - Opcode::VPMASKMOVD | - Opcode::VPMASKMOVQ | - Opcode::VPSHUFB | - Opcode::VPSHUFD | - Opcode::VPHMINPOSUW | - Opcode::PHMINPOSUW | - Opcode::VZEROUPPER | - Opcode::VLDDQU | - Opcode::BSWAP | - Opcode::CVTDQ2PD | - Opcode::CVTDQ2PS | - Opcode::CVTPD2DQ | - Opcode::CVTPI2PS | - Opcode::CVTPI2PD | - Opcode::CVTPS2PD | - Opcode::CVTPS2PI | - Opcode::CVTSD2SI | - Opcode::CVTSD2SS | - Opcode::CVTSI2SD | - Opcode::CVTSI2SS | - Opcode::CVTSS2SD | - Opcode::CVTSS2SI | - Opcode::CVTTPS2DQ | - Opcode::CVTTPS2PI | - Opcode::CVTTSD2SI | - Opcode::CVTTSS2SI | - Opcode::MASKMOVQ | - Opcode::MOVAPS | - Opcode::MOVAPD | - Opcode::MOVD | - Opcode::MOVHPS | - Opcode::MOVHLPS | - Opcode::MOVLPS | - Opcode::MOVLHPS | - Opcode::MOVMSKPS | - Opcode::MOVNTI | - Opcode::MOVNTPS | - Opcode::MOVNTQ | - Opcode::MOVSD | - Opcode::MOVSS | - Opcode::MOVUPD | - Opcode::PSHUFHW | - Opcode::PSHUFLW | - Opcode::PUNPCKHBW | - Opcode::PUNPCKHDQ | - Opcode::PUNPCKHWD | - Opcode::PUNPCKLBW | - Opcode::PUNPCKLDQ | - Opcode::PUNPCKLWD | - Opcode::PUNPCKLQDQ | - Opcode::PUNPCKHQDQ | - Opcode::PACKSSDW | - Opcode::PACKSSWB | - Opcode::PACKUSWB | - Opcode::UNPCKHPS | - Opcode::UNPCKLPS | - Opcode::SHUFPS | - Opcode::PMOVMSKB | - Opcode::LDDQU | - Opcode::CLC | - Opcode::CLI | - Opcode::CLD | - Opcode::STC | - Opcode::STI | - Opcode::STD | - Opcode::CBW | - Opcode::CWDE | - Opcode::CDQE | - Opcode::CBD | - Opcode::CDQ | - Opcode::CQO | - Opcode::MOVDDUP | - Opcode::MOVSLDUP | - Opcode::MOVDQ2Q | - Opcode::MOVDQU | - Opcode::MOVDQA | - Opcode::MOVQ | - Opcode::MOVQ2DQ | - Opcode::MOVSHDUP | - Opcode::MOVUPS | - Opcode::PEXTRW | - Opcode::PINSRW | - Opcode::MOV | - Opcode::LODS | - Opcode::STOS | - Opcode::LAHF | - Opcode::SAHF | - Opcode::MOVS | - Opcode::INS | - Opcode::OUTS | - Opcode::MOVSX_b | - Opcode::MOVSX_w | - Opcode::MOVZX_b | - Opcode::MOVZX_w | - Opcode::MOVSX | - Opcode::MOVSXD | - Opcode::XCHG | - Opcode::CMOVA | - Opcode::CMOVB | - Opcode::CMOVG | - Opcode::CMOVGE | - Opcode::CMOVL | - Opcode::CMOVLE | - Opcode::CMOVNA | - Opcode::CMOVNB | - Opcode::CMOVNO | - Opcode::CMOVNP | - Opcode::CMOVNS | - Opcode::CMOVNZ | - Opcode::CMOVO | - Opcode::CMOVP | - Opcode::CMOVS | - Opcode::CMOVZ | - Opcode::SETO | - Opcode::SETNO | - Opcode::SETB | - Opcode::SETAE | - Opcode::SETZ | - Opcode::SETNZ | - Opcode::SETBE | - Opcode::SETA | - Opcode::SETS | - Opcode::SETNS | - Opcode::SETP | - Opcode::SETNP | - Opcode::SETL | - Opcode::SETGE | - Opcode::SETLE | - Opcode::SETG => { write!(out, "{}", colors.data_op(self)) } - - Opcode::VCOMISD | - Opcode::VCOMISS | - Opcode::VUCOMISD | - Opcode::VUCOMISS | - Opcode::VCMPPD | - Opcode::VCMPPS | - Opcode::VCMPSD | - Opcode::VCMPSS | - Opcode::VMAXPD | - Opcode::VMAXPS | - Opcode::VMAXSD | - Opcode::VMAXSS | - Opcode::VMINPD | - Opcode::VMINPS | - Opcode::VMINSD | - Opcode::VMINSS | - Opcode::VPCMPEQB | - Opcode::VPCMPEQD | - Opcode::VPCMPEQQ | - Opcode::VPCMPEQW | - Opcode::VPCMPGTB | - Opcode::VPCMPGTD | - Opcode::VPCMPGTQ | - Opcode::VPCMPGTW | - Opcode::VPCMPISTRI | - Opcode::VPCMPISTRM | - Opcode::VPMAXSB | - Opcode::VPMAXSD | - Opcode::VPMAXSW | - Opcode::VPMAXUD | - Opcode::VPMINSD | - Opcode::VPMINUD | - Opcode::VPTEST | - Opcode::VTESTPD | - Opcode::VTESTPS | - Opcode::PCMPEQB | - Opcode::PCMPEQD | - Opcode::PCMPEQQ | - Opcode::PCMPEQW | - Opcode::PCMPESTRI | - Opcode::PCMPESTRM | - Opcode::PCMPGTB | - Opcode::PCMPGTD | - Opcode::PCMPGTQ | - Opcode::PCMPGTW | - Opcode::PCMPISTRI | - Opcode::PCMPISTRM | - Opcode::PTEST | - Opcode::MAXPS | - Opcode::MAXSD | - Opcode::MAXSS | - Opcode::MINPS | - Opcode::MINSD | - Opcode::MINSS | - Opcode::PMAXSB | - Opcode::PMAXSW | - Opcode::PMAXUB | - Opcode::PMAXUD | - Opcode::PMAXUW | - Opcode::PMINSB | - Opcode::PMINSD | - Opcode::PMINSW | - Opcode::PMINUB | - Opcode::PMINUD | - Opcode::PMINUW | - Opcode::CMPS | - Opcode::SCAS | - Opcode::TEST | - Opcode::CMPSD | - Opcode::CMPSS | - Opcode::CMP | - Opcode::CMPPS | - Opcode::CMPXCHG => { write!(out, "{}", colors.comparison_op(self)) } - - Opcode::WRMSR | - Opcode::RDMSR | - Opcode::RDTSC | - Opcode::RDPMC | - Opcode::FXSAVE | - Opcode::FXRSTOR | - Opcode::LDMXCSR | - Opcode::STMXCSR | - Opcode::XSAVE | - Opcode::XRSTOR | - Opcode::XSAVEOPT | - Opcode::LFENCE | - Opcode::MFENCE | - Opcode::SFENCE | - Opcode::CLFLUSH | - Opcode::SGDT | - Opcode::SIDT | - Opcode::LGDT | - Opcode::LIDT | - Opcode::SMSW | - Opcode::LMSW | - Opcode::SWAPGS | - Opcode::RDTSCP | - Opcode::INVLPG | - Opcode::CPUID | - Opcode::WBINVD | - Opcode::INVD | - Opcode::SYSRET | - Opcode::CLTS | - Opcode::SYSCALL | - Opcode::LSL | - Opcode::SLDT | - Opcode::STR | - Opcode::LLDT | - Opcode::LTR | - Opcode::VERR | - Opcode::VERW | - Opcode::JMPE | - Opcode::EMMS | - Opcode::GETSEC | - Opcode::LFS | - Opcode::LGS | - Opcode::LSS | - Opcode::RSM | - Opcode::SYSENTER | - Opcode::SYSEXIT | - Opcode::UD2E | - Opcode::VMREAD | - Opcode::VMWRITE | - Opcode::VMCALL | - Opcode::VMLAUNCH | - Opcode::VMRESUME | - Opcode::VMXOFF | - Opcode::MONITOR | - Opcode::MWAIT | - Opcode::CLAC | - Opcode::STAC | - Opcode::ENCLS | - Opcode::ENCLV | - Opcode::XGETBV | - Opcode::XSETBV | - Opcode::VMFUNC | - Opcode::XEND | - Opcode::XTEST | - Opcode::ENCLU | - Opcode::RDPKRU | - Opcode::WRPKRU | - Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } - - Opcode::AESDEC | - Opcode::AESDECLAST | - Opcode::AESENC | - Opcode::AESENCLAST | - Opcode::AESIMC | - Opcode::AESKEYGENASSIST | - Opcode::VAESDEC | - Opcode::VAESDECLAST | - Opcode::VAESENC | - Opcode::VAESENCLAST | - Opcode::VAESIMC | - Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) } - - Opcode::UD2 | - Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } - } - } -} - -impl fmt::Display for Instruction { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.colorize(&NoColors, fmt) - } -} - -/* - * Can't implement this as accepting a formatter because rust - * doesn't let me build one outside println! or write! or whatever. - * - * can't write this as an intermediate struct because i refuse to copy - * all data into the struct, and having a function producing a struct with - * some lifetimes gets really hairy if it's from a trait - same GAT kind - * of nonsense as i saw with ContextRead, because someone could hold onto - * the dang intermediate struct forever. - * - * so write to some Write thing i guess. bite me. i really just want to - * stop thinking about how to support printing instructions... - */ -impl > Colorize for Instruction { - fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { - // TODO: I DONT LIKE THIS, there is no address i can give contextualize here, - // the address operand maybe should be optional.. - self.contextualize(colors, 0, Some(&NoContext), out) - } -} - -/// No per-operand context when contextualizing an instruction! -struct NoContext; - -impl > ShowContextual for Instruction { - fn contextualize(&self, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { - if self.prefixes.lock() { - write!(out, "lock ")?; - } - - if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) { - // only a few of you actually use the prefix... - if self.prefixes.rep() { - write!(out, "rep ")?; - } else if self.prefixes.repz() { - write!(out, "repz ")?; - } else if self.prefixes.repnz() { - write!(out, "repnz ")?; - } - } - - self.opcode.colorize(colors, out)?; - - match self.operands[0] { - OperandSpec::Nothing => { - return Ok(()); - }, - _ => { - write!(out, " ")?; - if let Some(prefix) = self.segment_override_for_op(0) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[0]); - x.colorize(colors, out)?; - - for i in 1..4 { - match self.opcode { - Opcode::MOVSX_b | - Opcode::MOVZX_b => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - _ => { - write!(out, ", byte ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - }, - Opcode::MOVSX_w | - Opcode::MOVZX_w => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - _ => { - write!(out, ", word ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - }, - _ => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - _ => { - write!(out, ", ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - } - } - } - } - } - Ok(()) - } -} - -#[cfg(feature="std")] -impl > ShowContextual], Color, T, Y> for Instruction { - fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option]>, out: &mut T) -> fmt::Result { - if self.prefixes.lock() { - write!(out, "lock ")?; - } - - if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) { - // only a few of you actually use the prefix... - if self.prefixes.rep() { - write!(out, "rep ")?; - } else if self.prefixes.repz() { - write!(out, "repz ")?; - } else if self.prefixes.repnz() { - write!(out, "repnz ")?; - } - } - - self.opcode.colorize(colors, out)?; - - match context.and_then(|xs| xs[0].as_ref()) { - Some(s) => { write!(out, " {}", s)?; }, - None => { - match self.operands[0] { - OperandSpec::Nothing => { - return Ok(()); - }, - _ => { - write!(out, " ")?; - if let Some(prefix) = self.segment_override_for_op(0) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[0]); - x.colorize(colors, out)?; - } - }; - for i in 1..4 { - match self.opcode { - Opcode::MOVSX_b | - Opcode::MOVZX_b => { - match context.and_then(|xs| xs[i].as_ref()) { - Some(s) => { write!(out, ", {}", s)? } - None => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - _ => { - write!(out, ", byte ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - } - } - }, - Opcode::MOVSX_w | - Opcode::MOVZX_w => { - match context.and_then(|xs| xs[i].as_ref()) { - Some(s) => { write!(out, ", {}", s)? } - None => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - &OperandSpec::RegMMM => { - write!(out, ", ")?; - } - _ => { - write!(out, ", word ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - } - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - } - } - }, - _ => { - match context.and_then(|xs| xs[i].as_ref()) { - Some(s) => { write!(out, ", {}", s)? } - None => { - match &self.operands[i] { - &OperandSpec::Nothing => { - return Ok(()); - }, - _ => { - write!(out, ", ")?; - if let Some(prefix) = self.segment_override_for_op(1) { - write!(out, "{}:", prefix)?; - } - let x = Operand::from_spec(self, self.operands[i]); - x.colorize(colors, out)? - } - } - } - } - } - } - } - Ok(()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 624b3fa..e7ca97d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6214 +10,11 @@ extern crate alloc; extern crate yaxpeax_arch; -mod vex; -mod display; +pub mod long_mode; +pub use long_mode::Arch as x86_64; -use core::hint::unreachable_unchecked; +mod protected_mode; +pub use protected_mode::Arch as x86_32; -use yaxpeax_arch::{Arch, Decoder, LengthedInstruction}; - -#[cfg(feature="use-serde")] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub struct RegSpec { - pub num: u8, - pub bank: RegisterBank -} -#[cfg(not(feature="use-serde"))] -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct RegSpec { - pub num: u8, - pub bank: RegisterBank -} - -use core::hash::Hash; -use core::hash::Hasher; -impl Hash for RegSpec { - fn hash(&self, state: &mut H) { - let code = ((self.bank as u16) << 8) | (self.num as u16); - code.hash(state); - } -} - -// This is only to select alternate opcode maps for the 0f escape byte. -// This often could be treated as a size prefix but in some cases selects -// an entirely different operation. -#[derive(Debug)] -enum OpcodeMap { - Map66, - MapF2, - MapF3, -} - -#[derive(Debug)] -pub enum ConditionCode { - O, - NO, - B, - AE, - Z, - NZ, - A, - BE, - S, - NS, - P, - NP, - L, - GE, - G, - LE, -} - -#[allow(non_snake_case)] -impl RegSpec { - #[inline] - fn from_parts(num: u8, extended: bool, bank: RegisterBank) -> RegSpec { - RegSpec { - num: num + if extended { 0b1000 } else { 0 }, - bank: bank - } - } - - #[inline] - fn gp_from_parts(num: u8, extended: bool, width: u8, rex: bool) -> RegSpec { -// println!("from_parts width: {}, num: {}, extended: {}", width, num, extended); - RegSpec { - num: num + if extended { 0b1000 } else { 0 }, - bank: width_to_gp_reg_bank(width, rex) - } - } - - #[inline] - pub fn rip() -> RegSpec { - RegSpec { - num: 0, - bank: RegisterBank::RIP - } - } - - #[inline] - pub fn eip() -> RegSpec { - RegSpec { - num: 0, - bank: RegisterBank::EIP - } - } - - #[inline] - pub fn eflags() -> RegSpec { - RegSpec { - num: 0, - bank: RegisterBank::EFlags - } - } - - #[inline] - pub fn rflags() -> RegSpec { - RegSpec { - num: 0, - bank: RegisterBank::RFlags - } - } - - #[inline] - pub fn rbp() -> RegSpec { - RegSpec { - num: 5, - bank: RegisterBank::Q - } - } - - #[inline] - pub fn rsp() -> RegSpec { - RegSpec { - num: 4, - bank: RegisterBank::Q - } - } - - #[inline] - pub fn fs() -> RegSpec { - RegSpec { bank: RegisterBank::S, num: 3 } - } - - #[inline] - pub fn gs() -> RegSpec { - RegSpec { bank: RegisterBank::S, num: 4 } - } - - #[inline] - pub fn rax() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 0 } - } - - #[inline] - pub fn rcx() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 1 } - } - - #[inline] - pub fn rdx() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 2 } - } - - #[inline] - pub fn rsi() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 6 } - } - - #[inline] - pub fn rdi() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 7 } - } - - #[inline] - pub fn r8() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 8 } - } - - #[inline] - pub fn r9() -> RegSpec { - RegSpec { bank: RegisterBank::Q, num: 9 } - } - - #[inline] - pub fn eax() -> RegSpec { - RegSpec { bank: RegisterBank::D, num: 0 } - } - - #[inline] - pub fn ax() -> RegSpec { - RegSpec { bank: RegisterBank::W, num: 0 } - } - - #[inline] - pub fn al() -> RegSpec { - RegSpec { bank: RegisterBank::B, num: 0 } - } - - #[inline] - pub fn cl() -> RegSpec { - RegSpec { bank: RegisterBank::B, num: 1 } - } -} - -#[allow(non_camel_case_types)] -#[allow(dead_code)] -enum SizeCode { - b, - vd, - vq, - vqp -} - -#[derive(Clone, Debug, PartialEq)] -pub enum Operand { - ImmediateI8(i8), - ImmediateU8(u8), - ImmediateI16(i16), - ImmediateU16(u16), - ImmediateU32(u32), - ImmediateI32(i32), - ImmediateU64(u64), - ImmediateI64(i64), - Register(RegSpec), - DisplacementU32(u32), - DisplacementU64(u64), - RegDeref(RegSpec), - RegDisp(RegSpec, i32), - RegScale(RegSpec, u8), - RegIndexBase(RegSpec, RegSpec), - RegIndexBaseDisp(RegSpec, RegSpec, i32), - RegScaleDisp(RegSpec, u8, i32), - RegIndexBaseScale(RegSpec, RegSpec, u8), - RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32), - Nothing, -} - -impl OperandSpec { - pub fn is_memory(&self) -> bool { - match self { - OperandSpec::DispU32 | - OperandSpec::DispU64 | - OperandSpec::Deref | - OperandSpec::Deref_rsi | - OperandSpec::Deref_rdi | - OperandSpec::RegDisp | - OperandSpec::RegScale | - OperandSpec::RegIndexBase | - OperandSpec::RegIndexBaseDisp | - OperandSpec::RegScaleDisp | - OperandSpec::RegIndexBaseScale | - OperandSpec::RegIndexBaseScaleDisp => { - true - }, - OperandSpec::ImmI8 | - OperandSpec::ImmI16 | - OperandSpec::ImmI32 | - OperandSpec::ImmI64 | - OperandSpec::ImmU8 | - OperandSpec::ImmU16 | - OperandSpec::ImmU32 | - OperandSpec::ImmU64 | - OperandSpec::RegRRR | - OperandSpec::RegMMM | - OperandSpec::RegVex | - OperandSpec::AL | - OperandSpec::CL | - OperandSpec::Nothing => { - false - } - } - } -} -impl Operand { - fn from_spec(inst: &Instruction, spec: OperandSpec) -> Operand { - match spec { - OperandSpec::Nothing => { - Operand::Nothing - } - // the register in modrm_rrr - OperandSpec::RegRRR => { - Operand::Register(inst.modrm_rrr) - } - // the register in modrm_mmm (eg modrm mod bits were 11) - OperandSpec::RegMMM => { - Operand::Register(inst.modrm_mmm) - } - OperandSpec::RegVex => { - Operand::Register(inst.vex_reg) - } - OperandSpec::AL => { - Operand::Register(RegSpec::al()) - } - OperandSpec::CL => { - Operand::Register(RegSpec::cl()) - } - OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), - OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), - OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), - OperandSpec::ImmU16 => Operand::ImmediateU16(inst.imm as u16), - OperandSpec::ImmI32 => Operand::ImmediateI32(inst.imm as i32), - OperandSpec::ImmU32 => Operand::ImmediateU32(inst.imm as u32), - OperandSpec::ImmI64 => Operand::ImmediateI64(inst.imm as i64), - OperandSpec::ImmU64 => Operand::ImmediateU64(inst.imm as u64), - OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp as u32), - OperandSpec::DispU64 => Operand::DisplacementU64(inst.disp as u64), - OperandSpec::Deref => { - Operand::RegDeref(inst.modrm_mmm) - } - OperandSpec::Deref_rsi => { - Operand::RegDeref(RegSpec::rsi()) - } - OperandSpec::Deref_rdi => { - Operand::RegDeref(RegSpec::rdi()) - } - OperandSpec::RegDisp => { - Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) - } - OperandSpec::RegScale => { - Operand::RegScale(inst.sib_index, inst.scale) - } - OperandSpec::RegIndexBase => { - Operand::RegIndexBase(inst.modrm_mmm, inst.sib_index) - } - OperandSpec::RegIndexBaseDisp => { - Operand::RegIndexBaseDisp(inst.modrm_mmm, inst.sib_index, inst.disp as i32) - } - OperandSpec::RegScaleDisp => { - Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) - } - OperandSpec::RegIndexBaseScale => { - Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) - } - OperandSpec::RegIndexBaseScaleDisp => { - Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) - } - } - } - pub fn is_memory(&self) -> bool { - match self { - Operand::DisplacementU32(_) | - Operand::DisplacementU64(_) | - Operand::RegDeref(_) | - Operand::RegDisp(_, _) | - Operand::RegScale(_, _) | - Operand::RegIndexBase(_, _) | - Operand::RegIndexBaseDisp(_, _, _) | - Operand::RegScaleDisp(_, _, _) | - Operand::RegIndexBaseScale(_, _, _) | - Operand::RegIndexBaseScaleDisp(_, _, _, _) => { - true - }, - Operand::ImmediateI8(_) | - Operand::ImmediateU8(_) | - Operand::ImmediateI16(_) | - Operand::ImmediateU16(_) | - Operand::ImmediateU32(_) | - Operand::ImmediateI32(_) | - Operand::ImmediateU64(_) | - Operand::ImmediateI64(_) | - Operand::Register(_) | - Operand::Nothing => { - false - } - } - } -} - -#[test] -fn operand_size() { - assert_eq!(core::mem::size_of::(), 1); - assert_eq!(core::mem::size_of::(), 2); - // assert_eq!(core::mem::size_of::(), 4); - // assert_eq!(core::mem::size_of::(), 40); -} - -#[allow(non_camel_case_types)] -#[cfg(feature="use-serde")] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub enum RegisterBank { - Q, D, W, B, rB, // Quadword, Dword, Word, Byte - CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... - X, Y, Z, // XMM, YMM, ZMM - ST, MM, // ST, MM regs (x87, mmx) - K, // AVX512 mask registers -} -#[allow(non_camel_case_types)] -#[cfg(not(feature="use-serde"))] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum RegisterBank { - Q, D, W, B, rB, // Quadword, Dword, Word, Byte - CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... - X, Y, Z, // XMM, YMM, ZMM - ST, MM, // ST, MM regs (x87, mmx) - K, // AVX512 mask registers -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] -pub enum Segment { - DS = 0, CS, ES, FS, GS, SS -} - -const BMI1: [Opcode; 6] = [ - Opcode::ANDN, - Opcode::BEXTR, - Opcode::BLSI, - Opcode::BLSMSK, - Opcode::BLSR, - Opcode::TZCNT, -]; - -// TODO: -// PTWRITE -// RDFSBASE -// RDGSBASE -// WRFSBASE -// WRGSBASE -// TPAUSE -// UMONITOR -// UMWAIT -// CLFLUSHOPT -// CLWB -#[allow(non_camel_case_types)] -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum Opcode { - ADD = 1, - OR = 2, - ADC = 3, - SBB = 4, - AND = 5, - XOR = 6, - SUB = 7, - CMP = 8, - Invalid, - XADD, - BT, - BTS, - BTC, - BTR, - BSF, - BSR, - TZCNT, - MOVSS, - ADDSS, - SUBSS, - MULSS, - DIVSS, - MINSS, - MAXSS, - SQRTSS, - MOVSD, - SQRTSD, - ADDSD, - SUBSD, - MULSD, - DIVSD, - MINSD, - MAXSD, - MOVSLDUP, - MOVSHDUP, - MOVDDUP, - HADDPS, - HSUBPS, - ADDSUBPS, - CVTSI2SS, - CVTSI2SD, - CVTTSD2SI, - CVTTPS2DQ, - CVTPD2DQ, - CVTSD2SI, - CVTSD2SS, - CVTTSS2SI, - CVTSS2SI, - CVTSS2SD, - CVTDQ2PD, - LDDQU, - MOVSX_b, - MOVSX_w, - MOVZX_b, - MOVZX_w, - MOVSX, - MOVSXD, - SAR, - SAL, - SHR, - SHRD, - SHL, - RCR, - RCL, - ROR, - ROL, - INC, - DEC, - HLT, - CALL, - CALLF, - JMP, - JMPF, - PUSH, - POP, - LEA, - NOP, - PREFETCHNTA, - PREFETCH0, - PREFETCH1, - PREFETCH2, - XCHG, - POPF, - INT, - INTO, - IRET, - RETF, - ENTER, - LEAVE, - MOV, - RETURN, - PUSHF, - WAIT, - CBW, - CWDE, - CDQE, - CBD, - CDQ, - CQO, - LODS, - STOS, - LAHF, - SAHF, - CMPS, - SCAS, - MOVS, - TEST, - INS, - OUTS, - IMUL, - JO, - JNO, - JB, - JNB, - JZ, - JNZ, - JA, - JNA, - JS, - JNS, - JP, - JNP, - JL, - JGE, - JLE, - JG, - CMOVA, - CMOVB, - CMOVG, - CMOVGE, - CMOVL, - CMOVLE, - CMOVNA, - CMOVNB, - CMOVNO, - CMOVNP, - CMOVNS, - CMOVNZ, - CMOVO, - CMOVP, - CMOVS, - CMOVZ, - DIV, - IDIV, - MUL, - NEG, - NOT, - CMPXCHG, - SETO, - SETNO, - SETB, - SETAE, - SETZ, - SETNZ, - SETBE, - SETA, - SETS, - SETNS, - SETP, - SETNP, - SETL, - SETGE, - SETLE, - SETG, - CPUID, - UD2, - WBINVD, - INVD, - SYSRET, - CLTS, - SYSCALL, - LSL, - LAR, - SGDT, - SIDT, - LGDT, - LIDT, - SMSW, - LMSW, - SWAPGS, - RDTSCP, - INVLPG, - FXSAVE, - FXRSTOR, - LDMXCSR, - STMXCSR, - XSAVE, - XRSTOR, - XSAVEOPT, - LFENCE, - MFENCE, - SFENCE, - CLFLUSH, - WRMSR, - RDTSC, - RDMSR, - RDPMC, - SLDT, - STR, - LLDT, - LTR, - VERR, - VERW, - CLC, - STC, - CLI, - STI, - CLD, - STD, - JMPE, - POPCNT, - MOVDQU, - MOVDQA, - MOVQ, - CMPSS, - CMPSD, - UNPCKLPS, - UNPCKHPS, - PSHUFHW, - PSHUFLW, - MOVUPS, - MOVQ2DQ, - MOVDQ2Q, - RSQRTSS, - RCPSS, - - ANDN, - BEXTR, - BLSI, - BLSMSK, - BLSR, - VMCALL, - VMLAUNCH, - VMRESUME, - VMXOFF, - MONITOR, - MWAIT, - CLAC, - STAC, - ENCLS, - ENCLV, - XGETBV, - XSETBV, - VMFUNC, - XEND, - XTEST, - ENCLU, - RDPKRU, - WRPKRU, - - ADDPS, - ANDNPS, - ANDPS, - BSWAP, - CMPPS, - COMISS, - CVTDQ2PS, - CVTPI2PS, - CVTPI2PD, - CVTPS2PD, - CVTPS2PI, - CVTTPS2PI, - DIVPS, - EMMS, - GETSEC, - LFS, - LGS, - LSS, - MASKMOVQ, - MAXPS, - MINPS, - MOVAPS, - MOVAPD, - MOVD, - MOVLPS, - MOVHPS, - MOVLHPS, - MOVHLPS, - MOVUPD, - MOVMSKPS, - MOVNTI, - MOVNTPS, - MOVNTQ, - MULPS, - ORPS, - PACKSSDW, - PACKSSWB, - PACKUSWB, - PADDB, - PADDD, - PADDQ, - PADDSB, - PADDSW, - PADDUSB, - PADDUSW, - PADDW, - PAND, - PANDN, - PAVGB, - PAVGW, - PCMPEQB, - PCMPEQD, - PCMPEQW, - PCMPGTB, - PCMPGTD, - PCMPGTW, - PEXTRW, - PINSRW, - PMADDWD, - PMAXSW, - PMAXUB, - PMINSW, - PMINUB, - PMOVMSKB, - PMULHUW, - PMULHW, - PMULLW, - PMULUDQ, - POR, - PSADBW, - PSHUFW, - PSHUFD, - PSLLD, - PSLLDQ, - PSLLQ, - PSLLW, - PSRAD, - PSRAW, - PSRLD, - PSRLDQ, - PSRLQ, - PSRLW, - PSUBB, - PSUBD, - PSUBQ, - PSUBSB, - PSUBSW, - PSUBUSB, - PSUBUSW, - PSUBW, - PUNPCKHBW, - PUNPCKHDQ, - PUNPCKHWD, - PUNPCKLBW, - PUNPCKLDQ, - PUNPCKLWD, - PUNPCKLQDQ, - PUNPCKHQDQ, - PXOR, - RCPPS, - RSM, - RSQRTPS, - SHLD, - SHUFPS, - SLHD, - SQRTPS, - SUBPS, - SYSENTER, - SYSEXIT, - UCOMISS, - UD2E, - VMREAD, - VMWRITE, - XORPS, - - VMOVDDUP, - VPSHUFLW, - VHADDPS, - VHSUBPS, - VADDSUBPS, - VCVTPD2DQ, - VLDDQU, - - VCOMISD, - VCOMISS, - VUCOMISD, - VUCOMISS, - VADDPD, - VADDPS, - VADDSD, - VADDSS, - VADDSUBPD, - VAESDEC, - VAESDECLAST, - VAESENC, - VAESENCLAST, - VAESIMC, - VAESKEYGENASSIST, - VBLENDPD, - VBLENDPS, - VBLENDVPD, - VBLENDVPS, - VBROADCASTF128, - VBROADCASTI128, - VBROADCASTSD, - VBROADCASTSS, - VCMPSD, - VCMPSS, - VCMPPD, - VCMPPS, - VCVTDQ2PD, - VCVTDQ2PS, - VCVTPD2PS, - VCVTPH2PS, - VCVTPS2DQ, - VCVTPS2PD, - VCVTSS2SD, - VCVTSI2SS, - VCVTSI2SD, - VCVTSD2SI, - VCVTSD2SS, - VCVTPS2PH, - VCVTSS2SI, - VCVTTPD2DQ, - VCVTTPS2DQ, - VCVTTSS2SI, - VCVTTSD2SI, - VDIVPD, - VDIVPS, - VDIVSD, - VDIVSS, - VDPPD, - VDPPS, - VEXTRACTF128, - VEXTRACTI128, - VEXTRACTPS, - VFMADD132PD, - VFMADD132PS, - VFMADD132SD, - VFMADD132SS, - VFMADD213PD, - VFMADD213PS, - VFMADD213SD, - VFMADD213SS, - VFMADD231PD, - VFMADD231PS, - VFMADD231SD, - VFMADD231SS, - VFMADDSUB132PD, - VFMADDSUB132PS, - VFMADDSUB213PD, - VFMADDSUB213PS, - VFMADDSUB231PD, - VFMADDSUB231PS, - VFMSUB132PD, - VFMSUB132PS, - VFMSUB132SD, - VFMSUB132SS, - VFMSUB213PD, - VFMSUB213PS, - VFMSUB213SD, - VFMSUB213SS, - VFMSUB231PD, - VFMSUB231PS, - VFMSUB231SD, - VFMSUB231SS, - VFMSUBADD132PD, - VFMSUBADD132PS, - VFMSUBADD213PD, - VFMSUBADD213PS, - VFMSUBADD231PD, - VFMSUBADD231PS, - VFNMADD132PD, - VFNMADD132PS, - VFNMADD132SD, - VFNMADD132SS, - VFNMADD213PD, - VFNMADD213PS, - VFNMADD213SD, - VFNMADD213SS, - VFNMADD231PD, - VFNMADD231PS, - VFNMADD231SD, - VFNMADD231SS, - VFNMSUB132PD, - VFNMSUB132PS, - VFNMSUB132SD, - VFNMSUB132SS, - VFNMSUB213PD, - VFNMSUB213PS, - VFNMSUB213SD, - VFNMSUB213SS, - VFNMSUB231PD, - VFNMSUB231PS, - VFNMSUB231SD, - VFNMSUB231SS, - VGATHERDPD, - VGATHERDPS, - VGATHERQPD, - VGATHERQPS, - VHADDPD, - VHSUBPD, - VINSERTF128, - VINSERTI128, - VINSERTPS, - VMASKMOVDQU, - VMASKMOVPD, - VMASKMOVPS, - VMAXPD, - VMAXPS, - VMAXSD, - VMAXSS, - VMINPD, - VMINPS, - VMINSD, - VMINSS, - VMOVAPD, - VMOVAPS, - VMOVD, - VMOVDQA, - VMOVDQU, - VMOVHLPS, - VMOVHPD, - VMOVHPS, - VMOVLHPS, - VMOVLPD, - VMOVLPS, - VMOVMSKPD, - VMOVMSKPS, - VMOVNTDQ, - VMOVNTDQA, - VMOVNTPD, - VMOVNTPS, - VMOVQ, - VMOVSS, - VMOVSD, - VMOVSHDUP, - VMOVSLDUP, - VMOVUPD, - VMOVUPS, - VMPSADBW, - VMULPD, - VMULPS, - VMULSD, - VMULSS, - VPABSB, - VPABSD, - VPABSW, - VPACKSSDW, - VPACKSSWB, - VPACKUSWB, - VPADDB, - VPADDD, - VPADDQ, - VPADDSB, - VPADDSW, - VPADDUSB, - VPADDUSW, - VPADDW, - VPALIGNR, - VPAND, - VPANDN, - VPAVGB, - VPAVGW, - VPBLENDD, - VPBLENDVB, - VPBLENDW, - VPBROADCASTB, - VPBROADCASTD, - VPBROADCASTQ, - VPBROADCASTW, - VPCLMULQDQ, - VPCMPEQB, - VPCMPEQD, - VPCMPEQQ, - VPCMPEQW, - VPCMPGTB, - VPCMPGTD, - VPCMPGTQ, - VPCMPGTW, - VPCMPISTRI, - VPCMPISTRM, - VPERM2F128, - VPERM2I128, - VPERMD, - VPERMILPD, - VPERMILPS, - VPERMPD, - VPERMPS, - VPERMQ, - VPEXTRB, - VPEXTRD, - VPEXTRQ, - VPEXTRW, - VPGATHERDD, - VPGATHERDQ, - VPGATHERQD, - VPGATHERQQ, - VPHADDD, - VPHADDSW, - VPHADDW, - VPHADDUBSW, - VPHMINPOSUW, - VPHSUBD, - VPHSUBSW, - VPHSUBW, - VPINSRB, - VPINSRD, - VPINSRQ, - VPINSRW, - VPMADDWD, - VPMASKMOVD, - VPMASKMOVQ, - VPMAXSB, - VPMAXSD, - VPMAXSW, - VPMAXUD, - VPMINSD, - VPMINUD, - VPMOVMSKB, - VPMOVSXBD, - VPMOVSXBQ, - VPMOVSXBW, - VPMOVSXDQ, - VPMOVSXWD, - VPMOVSXWQ, - VPMOVZXBD, - VPMOVZXBQ, - VPMOVZXBW, - VPMOVZXDQ, - VPMOVZXWD, - VPMOVZXWQ, - VPMULDQ, - VPMULHRSW, - VPMULHUW, - VPMULHW, - VPMULLD, - VPMULLW, - VPMULUDQ, - VPOR, - VPSADBW, - VPSHUFB, - VPSHUFD, - VPSIGNB, - VPSIGND, - VPSIGNW, - VPSLLD, - VPSLLDQ, - VPSLLQ, - VPSLLVD, - VPSLLVQ, - VPSLLW, - VPSRAD, - VPSRAVD, - VPSRAW, - VPSRLD, - VPSRLDQ, - VPSRLQ, - VPSRLVD, - VPSRLVQ, - VPSRLW, - VPSUBB, - VPSUBD, - VPSUBQ, - VPSUBSB, - VPSUBSW, - VPSUBUSB, - VPSUBUSW, - VPSUBW, - VPTEST, - VPUNPCKHBW, - VPUNPCKHDQ, - VPUNPCKHQDQ, - VPUNPCKHWD, - VPUNPCKLBW, - VPUNPCKLDQ, - VPUNPCKLQDQ, - VPUNPCKLWD, - VPXOR, - VRCPPS, - VROUNDPD, - VROUNDPS, - VROUNDSD, - VROUNDSS, - VRSQRTPS, - VRSQRTSS, - VRCPSS, - VSHUFPD, - VSHUFPS, - VSQRTPD, - VSQRTPS, - VSQRTSS, - VSQRTSD, - VSUBPD, - VSUBPS, - VSUBSD, - VSUBSS, - VTESTPD, - VTESTPS, - VUNPCKHPD, - VUNPCKHPS, - VUNPCKLPD, - VUNPCKLPS, - VXORPD, - VXORPS, - VZEROUPPER, - - PCLMULQDQ, - AESKEYGENASSIST, - AESIMC, - AESENC, - AESENCLAST, - AESDEC, - AESDECLAST, - PCMPGTQ, - PCMPISTRM, - PCMPISTRI, - PCMPESTRI, - PACKUSDW, - PCMPESTRM, - PCMPEQQ, - PTEST, - PHMINPOSUW, - MPSADBW, - PMOVZXDQ, - PMOVSXDQ, - PMOVZXBD, - PMOVSXBD, - PMOVZXWQ, - PMOVSXWQ, - PMOVZXBQ, - PMOVSXBQ, - PMOVSXWD, - PMOVZXWD, - PEXTRQ, - PEXTRB, - PMOVSXBW, - PMOVZXBW, - PINSRQ, - PINSRD, - PINSRB, - EXTRACTPS, - INSERTPS, - ROUNDSS, - ROUNDSD, - ROUNDPS, - ROUNDPD, - PMAXSB, - PMAXUW, - PMAXUD, - PMINSD, - PMINSB, - PMINUD, - PMINUW, - BLENDW, - BLENDDVB, - BLENDVPS, - BLENDVPD, - BLENDPS, - BLENDPD, - PMULDQ, - MOVNTDQA, - PMULLD, - PALIGNR, - PSIGNW, - PSIGND, - PSIGNB, - PSHUFB, - PMULHRSU, - PMADDUBSW, - PABSD, - PABSW, - PABSB, - PHSUBSW, - PHSUBW, - PHSUBD, - PHADDD, - PHADDSW, - PHADDW, - HSUBPD, - HADDPD, - ADDSUBPD, -} - -#[derive(Debug)] -pub struct Instruction { - pub prefixes: Prefixes, - modrm_rrr: RegSpec, - modrm_mmm: RegSpec, // doubles as sib_base - sib_index: RegSpec, - vex_reg: RegSpec, - scale: u8, - length: u8, - operand_count: u8, - operands: [OperandSpec; 4], - imm: u64, - disp: u64, - pub opcode: Opcode, -} - -impl yaxpeax_arch::Instruction for Instruction { - fn well_defined(&self) -> bool { - // TODO: this is incorrect! - true - } -} - -#[derive(Debug, PartialEq)] -pub enum DecodeError { - ExhaustedInput, - InvalidOpcode, - InvalidOperand, - InvalidPrefixes, - TooLong, - IncompleteDecoder, -} - -impl yaxpeax_arch::DecodeError for DecodeError { - fn data_exhausted(&self) -> bool { self == &DecodeError::ExhaustedInput } - fn bad_opcode(&self) -> bool { self == &DecodeError::InvalidOpcode } - fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand } -} - -#[allow(non_camel_case_types)] -#[derive(Debug, Copy, Clone, PartialEq)] -enum OperandSpec { - Nothing, - // the register in modrm_rrr - RegRRR, - // the register in modrm_mmm (eg modrm mod bits were 11) - RegMMM, - // the register selected by vex-vvvv bits - RegVex, - // the register `al`. Used for MOVS. - AL, - // the register `cl`. Used for SHLD and SHRD. - CL, - ImmI8, - ImmI16, - ImmI32, - ImmI64, - ImmU8, - ImmU16, - ImmU32, - ImmU64, - DispU32, - DispU64, - Deref, - Deref_rsi, - Deref_rdi, - RegDisp, - RegScale, - RegIndexBase, - RegIndexBaseDisp, - RegScaleDisp, - RegIndexBaseScale, - RegIndexBaseScaleDisp -} - -// the Hash, Eq, and PartialEq impls here are possibly misleading. -// They exist because downstream some structs are spelled like -// Foo for T == x86_64. This is only to access associated types -// which themselves are bounded, but their #[derive] require T to -// implement these traits. -#[cfg(feature="use-serde")] -#[derive(Hash, Eq, PartialEq, Debug, Serialize, Deserialize)] -#[allow(non_camel_case_types)] -pub struct x86_64; - -#[cfg(not(feature="use-serde"))] -#[derive(Hash, Eq, PartialEq, Debug)] -#[allow(non_camel_case_types)] -pub struct x86_64; - -impl Arch for x86_64 { - type Address = u64; - type Instruction = Instruction; - type DecodeError = DecodeError; - type Decoder = InstDecoder; - type Operand = Operand; -} - -impl LengthedInstruction for Instruction { - type Unit = u64; - fn len(&self) -> u64 { - self.length.into() - } - fn min_size() -> u64 { - 1 - } -} - -#[derive(PartialEq)] -pub struct InstDecoder { - // extensions tracked here: - // 0. SSE3 - // 1. SSSE3 - // 2. monitor (intel-only?) - // 3. vmx (some atom chips still lack it) - // 4. fma3 (intel haswell/broadwell+, amd piledriver+) - // 5. cmpxchg16b (some amd are missingt this one) - // 6. sse4.1 - // 7. sse4.2 - // 8. movbe - // 9. popcnt (independent of BMI) - // 10. aesni - // 11. xsave (xsave, xrestor, xsetbv, xgetbv) - // 12. rdrand (intel ivybridge+, amd ..??) - // 13. sgx (eadd, eblock, ecreate, edbgrd, edbgwr, einit, eldb, eldu, epa, eremove, etrace, - // ewb, eenter, eexit, egetkey, ereport, eresume) - // 14. bmi1 (intel haswell+, amd jaguar+) - // 15. avx2 (intel haswell+, amd excavator+) - // 16. bmi2 (intel ?, amd ?) - // 17. invpcid - // 18. mpx - // 19. avx512_f - // 20. avx512_dq - // 21. rdseed - // 22. adx - // 23. avx512_fma - // 24. pcommit - // 25. clflushopt - // 26. clwb - // 27. avx512_pf - // 28. avx512_er - // 29. avx512_cd - // 30. sha - // 31. avx512_bw - // 32. avx512_vl - // 33. prefetchwt1 - // 34. avx512_vbmi - // 35. avx512_vbmi2 - // 36. gfni (galois field instructions) - // 37. vaes - // 38. pclmulqdq - // 39. avx_vnni - // 40. avx512_bitalg - // 41. avx512_vpopcntdq - // 42. avx512_4vnniw - // 43. avx512_4fmaps - // 44. cx8 // cmpxchg8 - is this actually optional in x86_64? - // 45. syscall // syscall/sysret - actually optional in x86_64? - // 46. rdtscp // actually optional in x86_64? - // 47. abm (lzcnt, popcnt) - // 48. sse4a - // 49. 3dnowprefetch // actually optional? - // 50. xop - // 51. skinit - // 52. tbm - // 53. intel quirks - // 54. amd quirks - // 55. avx (intel ?, amd ?) - flags: u64, -} - -impl InstDecoder { - /// Instantiates an x86_64 decoder that decodes the bare minimum of x86_64. - /// - /// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences - /// and any instructions defined by extensions. - pub fn minimal() -> Self { - InstDecoder { - flags: 0, - } - } - - pub fn sse3(&self) -> bool { - self.flags & (1 << 0) != 0 - } - - pub fn with_sse3(mut self) -> Self { - self.flags |= 1 << 0; - self - } - - pub fn ssse3(&self) -> bool { - self.flags & (1 << 1) != 0 - } - - pub fn with_ssse3(mut self) -> Self { - self.flags |= 1 << 1; - self - } - - pub fn monitor(&self) -> bool { - self.flags & (1 << 2) != 0 - } - - pub fn with_monitor(mut self) -> Self { - self.flags |= 1 << 2; - self - } - - pub fn vmx(&self) -> bool { - self.flags & (1 << 3) != 0 - } - - pub fn with_vmx(mut self) -> Self { - self.flags |= 1 << 3; - self - } - - pub fn fma3(&self) -> bool { - self.flags & (1 << 4) != 0 - } - - pub fn with_fma3(mut self) -> Self { - self.flags |= 1 << 4; - self - } - - pub fn cmpxchg16b(&self) -> bool { - self.flags & (1 << 5) != 0 - } - - pub fn with_cmpxchg16b(mut self) -> Self { - self.flags |= 1 << 5; - self - } - - pub fn sse4_1(&self) -> bool { - self.flags & (1 << 6) != 0 - } - - pub fn with_sse4_1(mut self) -> Self { - self.flags |= 1 << 6; - self - } - - pub fn sse4_2(&self) -> bool { - self.flags & (1 << 7) != 0 - } - - pub fn with_sse4_2(mut self) -> Self { - self.flags |= 1 << 7; - self - } - - pub fn movbe(&self) -> bool { - self.flags & (1 << 8) != 0 - } - - pub fn with_movbe(mut self) -> Self { - self.flags |= 1 << 8; - self - } - - pub fn popcnt(&self) -> bool { - self.flags & (1 << 9) != 0 - } - - pub fn with_popcnt(mut self) -> Self { - self.flags |= 1 << 9; - self - } - - pub fn aesni(&self) -> bool { - self.flags & (1 << 10) != 0 - } - - pub fn with_aesni(mut self) -> Self { - self.flags |= 1 << 10; - self - } - - pub fn xsave(&self) -> bool { - self.flags & (1 << 11) != 0 - } - - pub fn with_xsave(mut self) -> Self { - self.flags |= 1 << 11; - self - } - - pub fn rdrand(&self) -> bool { - self.flags & (1 << 12) != 0 - } - - pub fn with_rdrand(mut self) -> Self { - self.flags |= 1 << 12; - self - } - - pub fn sgx(&self) -> bool { - self.flags & (1 << 13) != 0 - } - - pub fn with_sgx(mut self) -> Self { - self.flags |= 1 << 13; - self - } - - pub fn bmi1(&self) -> bool { - self.flags & (1 << 14) != 0 - } - - pub fn with_bmi1(mut self) -> Self { - self.flags |= 1 << 14; - self - } - - pub fn avx2(&self) -> bool { - self.flags & (1 << 15) != 0 - } - - pub fn with_avx2(mut self) -> Self { - self.flags |= 1 << 15; - self - } - - pub fn bmi2(&self) -> bool { - self.flags & (1 << 16) != 0 - } - - pub fn with_bmi2(mut self) -> Self { - self.flags |= 1 << 16; - self - } - - pub fn invpcid(&self) -> bool { - self.flags & (1 << 17) != 0 - } - - pub fn with_invpcid(mut self) -> Self { - self.flags |= 1 << 17; - self - } - - pub fn mpx(&self) -> bool { - self.flags & (1 << 18) != 0 - } - - pub fn with_mpx(mut self) -> Self { - self.flags |= 1 << 18; - self - } - - pub fn avx512_f(&self) -> bool { - self.flags & (1 << 19) != 0 - } - - pub fn with_avx512_f(mut self) -> Self { - self.flags |= 1 << 19; - self - } - - pub fn avx512_dq(&self) -> bool { - self.flags & (1 << 20) != 0 - } - - pub fn with_avx512_dq(mut self) -> Self { - self.flags |= 1 << 20; - self - } - - pub fn rdseed(&self) -> bool { - self.flags & (1 << 21) != 0 - } - - pub fn with_rdseed(mut self) -> Self { - self.flags |= 1 << 21; - self - } - - pub fn adx(&self) -> bool { - self.flags & (1 << 22) != 0 - } - - pub fn with_adx(mut self) -> Self { - self.flags |= 1 << 22; - self - } - - pub fn avx512_fma(&self) -> bool { - self.flags & (1 << 23) != 0 - } - - pub fn with_avx512_fma(mut self) -> Self { - self.flags |= 1 << 23; - self - } - - pub fn pcommit(&self) -> bool { - self.flags & (1 << 24) != 0 - } - - pub fn with_pcommit(mut self) -> Self { - self.flags |= 1 << 24; - self - } - - pub fn clflushopt(&self) -> bool { - self.flags & (1 << 25) != 0 - } - - pub fn with_clflushopt(mut self) -> Self { - self.flags |= 1 << 25; - self - } - - pub fn clwb(&self) -> bool { - self.flags & (1 << 26) != 0 - } - - pub fn with_clwb(mut self) -> Self { - self.flags |= 1 << 26; - self - } - - pub fn avx512_pf(&self) -> bool { - self.flags & (1 << 27) != 0 - } - - pub fn with_avx512_pf(mut self) -> Self { - self.flags |= 1 << 27; - self - } - - pub fn avx512_er(&self) -> bool { - self.flags & (1 << 28) != 0 - } - - pub fn with_avx512_er(mut self) -> Self { - self.flags |= 1 << 28; - self - } - - pub fn avx512_cd(&self) -> bool { - self.flags & (1 << 29) != 0 - } - - pub fn with_avx512_cd(mut self) -> Self { - self.flags |= 1 << 29; - self - } - - pub fn sha(&self) -> bool { - self.flags & (1 << 30) != 0 - } - - pub fn with_sha(mut self) -> Self { - self.flags |= 1 << 30; - self - } - - pub fn avx512_bw(&self) -> bool { - self.flags & (1 << 31) != 0 - } - - pub fn with_avx512_bw(mut self) -> Self { - self.flags |= 1 << 31; - self - } - - pub fn avx512_vl(&self) -> bool { - self.flags & (1 << 32) != 0 - } - - pub fn with_avx512_vl(mut self) -> Self { - self.flags |= 1 << 32; - self - } - - pub fn prefetchwt1(&self) -> bool { - self.flags & (1 << 33) != 0 - } - - pub fn with_prefetchwt1(mut self) -> Self { - self.flags |= 1 << 33; - self - } - - pub fn avx512_vbmi(&self) -> bool { - self.flags & (1 << 34) != 0 - } - - pub fn with_avx512_vbmi(mut self) -> Self { - self.flags |= 1 << 34; - self - } - - pub fn avx512_vbmi2(&self) -> bool { - self.flags & (1 << 35) != 0 - } - - pub fn with_avx512_vbmi2(mut self) -> Self { - self.flags |= 1 << 35; - self - } - - pub fn gfni(&self) -> bool { - self.flags & (1 << 36) != 0 - } - - pub fn with_gfni(mut self) -> Self { - self.flags |= 1 << 36; - self - } - - pub fn vaes(&self) -> bool { - self.flags & (1 << 37) != 0 - } - - pub fn with_vaes(mut self) -> Self { - self.flags |= 1 << 37; - self - } - - pub fn pclmulqdq(&self) -> bool { - self.flags & (1 << 38) != 0 - } - - pub fn with_pclmulqdq(mut self) -> Self { - self.flags |= 1 << 38; - self - } - - pub fn avx_vnni(&self) -> bool { - self.flags & (1 << 39) != 0 - } - - pub fn with_avx_vnni(mut self) -> Self { - self.flags |= 1 << 39; - self - } - - pub fn avx512_bitalg(&self) -> bool { - self.flags & (1 << 40) != 0 - } - - pub fn with_avx512_bitalg(mut self) -> Self { - self.flags |= 1 << 40; - self - } - - pub fn avx512_vpopcntdq(&self) -> bool { - self.flags & (1 << 41) != 0 - } - - pub fn with_avx512_vpopcntdq(mut self) -> Self { - self.flags |= 1 << 41; - self - } - - pub fn avx512_4vnniw(&self) -> bool { - self.flags & (1 << 42) != 0 - } - - pub fn with_avx512_4vnniw(mut self) -> Self { - self.flags |= 1 << 42; - self - } - - pub fn avx512_4fmaps(&self) -> bool { - self.flags & (1 << 43) != 0 - } - - pub fn with_avx512_4fmaps(mut self) -> Self { - self.flags |= 1 << 43; - self - } - - pub fn cx8(&self) -> bool { - self.flags & (1 << 44) != 0 - } - - pub fn with_cx8(mut self) -> Self { - self.flags |= 1 << 44; - self - } - - pub fn syscall(&self) -> bool { - self.flags & (1 << 45) != 0 - } - - pub fn with_syscall(mut self) -> Self { - self.flags |= 1 << 45; - self - } - - pub fn rdtscp(&self) -> bool { - self.flags & (1 << 46) != 0 - } - - pub fn with_rdtscp(mut self) -> Self { - self.flags |= 1 << 46; - self - } - - pub fn abm(&self) -> bool { - self.flags & (1 << 47) != 0 - } - - pub fn with_abm(mut self) -> Self { - self.flags |= 1 << 47; - self - } - - pub fn sse4a(&self) -> bool { - self.flags & (1 << 48) != 0 - } - - pub fn with_sse4a(mut self) -> Self { - self.flags |= 1 << 48; - self - } - - pub fn _3dnowprefetch(&self) -> bool { - self.flags & (1 << 49) != 0 - } - - pub fn with_3dnowprefetch(mut self) -> Self { - self.flags |= 1 << 49; - self - } - - pub fn xop(&self) -> bool { - self.flags & (1 << 50) != 0 - } - - pub fn with_xop(mut self) -> Self { - self.flags |= 1 << 50; - self - } - - pub fn skinit(&self) -> bool { - self.flags & (1 << 51) != 0 - } - - pub fn with_skinit(mut self) -> Self { - self.flags |= 1 << 51; - self - } - - pub fn tbm(&self) -> bool { - self.flags & (1 << 52) != 0 - } - - pub fn with_tbm(mut self) -> Self { - self.flags |= 1 << 52; - self - } - - pub fn intel_quirks(&self) -> bool { - self.flags & (1 << 53) != 0 - } - - pub fn with_intel_quirks(mut self) -> Self { - self.flags |= 1 << 53; - self - } - - pub fn amd_quirks(&self) -> bool { - self.flags & (1 << 54) != 0 - } - - pub fn with_amd_quirks(mut self) -> Self { - self.flags |= 1 << 54; - self - } - - pub fn avx(&self) -> bool { - self.flags & (1 << 55) != 0 - } - - pub fn with_avx(mut self) -> Self { - self.flags |= 1 << 55; - self - } - - /// Optionally reject or reinterpret instruction according to the decoder's - /// declared extensions. - fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), DecodeError> { - match inst.opcode { - Opcode::TZCNT => { - if !self.bmi1() { - // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as - // bsf. - inst.opcode = Opcode::BSF; - } - } - Opcode::LDDQU | - Opcode::ADDSUBPS | - Opcode::ADDSUBPD | - Opcode::HADDPS | - Opcode::HSUBPS | - Opcode::HADDPD | - Opcode::HSUBPD | - Opcode::MOVSHDUP | - Opcode::MOVSLDUP | - Opcode::MOVDDUP | - Opcode::MONITOR | - Opcode::MWAIT => { - // via Intel section 5.7, SSE3 Instructions - if !self.sse3() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::PHADDW | - Opcode::PHADDSW | - Opcode::PHADDD | - Opcode::PHSUBW | - Opcode::PHSUBSW | - Opcode::PHSUBD | - Opcode::PABSB | - Opcode::PABSW | - Opcode::PABSD | - Opcode::PMADDUBSW | - Opcode::PMULHRSU | - Opcode::PSHUFB | - Opcode::PSIGNB | - Opcode::PSIGNW | - Opcode::PSIGND | - Opcode::PALIGNR => { - // via Intel section 5.8, SSSE3 Instructions - if !self.ssse3() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::PMULLD | - Opcode::PMULDQ | - Opcode::MOVNTDQA | - Opcode::BLENDPD | - Opcode::BLENDPS | - Opcode::BLENDVPD | - Opcode::BLENDVPS | - Opcode::BLENDDVB | - Opcode::BLENDW | - Opcode::PMINUW | - Opcode::PMINUD | - Opcode::PMINSB | - Opcode::PMINSD | - Opcode::PMAXUW | - Opcode::PMAXUD | - Opcode::PMAXSB | - Opcode::ROUNDPS | - Opcode::ROUNDPD | - Opcode::ROUNDSS | - Opcode::ROUNDSD | - Opcode::EXTRACTPS | - Opcode::INSERTPS | - Opcode::PINSRB | - Opcode::PINSRD | - Opcode::PINSRQ | - Opcode::PEXTRB | - Opcode::PEXTRW | - Opcode::PEXTRQ | - Opcode::PMOVSXBW | - Opcode::PMOVZXBW | - Opcode::PMOVSXBD | - Opcode::PMOVZXBD | - Opcode::PMOVSXWD | - Opcode::PMOVZXWD | - Opcode::PMOVSXBQ | - Opcode::PMOVZXBQ | - Opcode::PMOVSXWQ | - Opcode::PMOVZXWQ | - Opcode::PMOVSXDQ | - Opcode::PMOVZXDQ | - Opcode::MPSADBW | - Opcode::PHMINPOSUW | - Opcode::PTEST | - Opcode::PCMPEQQ | - Opcode::PACKUSDW => { - // via Intel section 5.10, SSE4.1 Instructions - if !self.sse4_1() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::PCMPESTRI | - Opcode::PCMPESTRM | - Opcode::PCMPISTRI | - Opcode::PCMPISTRM | - Opcode::PCMPGTQ => { - // via Intel section 5.11, SSE4.2 Instructions - if !self.sse4_2() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::AESDEC | - Opcode::AESDECLAST | - Opcode::AESENC | - Opcode::AESENCLAST | - Opcode::AESIMC | - Opcode::AESKEYGENASSIST => { - // via Intel section 5.12. AESNI AND PCLMULQDQ - if !self.aesni() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::PCLMULQDQ => { - // via Intel section 5.12. AESNI AND PCLMULQDQ - if !self.pclmulqdq() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - // AVX... - /* // TODO - Opcode::XABORT | - Opcode::XACQUIRE | - Opcode::XRELEASE | - Opcode::XBEGIN | - Opcode::XEND | - Opcode::XTEST => { - if !self.tsx() { - inst.opcode = Opcode::Invalid; - return Err(()); - } - } - */ - /* // TODO - Opcode::SHA1MSG1 | - Opcode::SHA1MSG2 | - Opcode::SHA1NEXTE | - Opcode::SHA1RNDS4 | - Opcode::SHA256MSG1 | - Opcode::SHA256MSG2 | - Opcode::SHA256RNDS2 => { - if !self.sha() { - inst.opcode = Opcode::Invalid; - return Err(()); - } - }*/ - Opcode::ENCLV | - Opcode::ENCLS | - Opcode::ENCLU => { - if !self.sgx() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::VMOVDDUP | - Opcode::VPSHUFLW | - Opcode::VHADDPS | - Opcode::VHSUBPS | - Opcode::VADDSUBPS | - Opcode::VCVTPD2DQ | - Opcode::VLDDQU | - Opcode::VCOMISD | - Opcode::VCOMISS | - Opcode::VUCOMISD | - Opcode::VUCOMISS | - Opcode::VADDPD | - Opcode::VADDPS | - Opcode::VADDSD | - Opcode::VADDSS | - Opcode::VADDSUBPD | - Opcode::VBLENDPD | - Opcode::VBLENDPS | - Opcode::VBLENDVPD | - Opcode::VBLENDVPS | - Opcode::VBROADCASTF128 | - Opcode::VBROADCASTI128 | - Opcode::VBROADCASTSD | - Opcode::VBROADCASTSS | - Opcode::VCMPSD | - Opcode::VCMPSS | - Opcode::VCMPPD | - Opcode::VCMPPS | - Opcode::VCVTDQ2PD | - Opcode::VCVTDQ2PS | - Opcode::VCVTPD2PS | - Opcode::VCVTPH2PS | - Opcode::VCVTPS2DQ | - Opcode::VCVTPS2PD | - Opcode::VCVTSS2SD | - Opcode::VCVTSI2SS | - Opcode::VCVTSI2SD | - Opcode::VCVTSD2SI | - Opcode::VCVTSD2SS | - Opcode::VCVTPS2PH | - Opcode::VCVTSS2SI | - Opcode::VCVTTPD2DQ | - Opcode::VCVTTPS2DQ | - Opcode::VCVTTSS2SI | - Opcode::VCVTTSD2SI | - Opcode::VDIVPD | - Opcode::VDIVPS | - Opcode::VDIVSD | - Opcode::VDIVSS | - Opcode::VDPPD | - Opcode::VDPPS | - Opcode::VEXTRACTF128 | - Opcode::VEXTRACTI128 | - Opcode::VEXTRACTPS | - Opcode::VFMADD132PD | - Opcode::VFMADD132PS | - Opcode::VFMADD132SD | - Opcode::VFMADD132SS | - Opcode::VFMADD213PD | - Opcode::VFMADD213PS | - Opcode::VFMADD213SD | - Opcode::VFMADD213SS | - Opcode::VFMADD231PD | - Opcode::VFMADD231PS | - Opcode::VFMADD231SD | - Opcode::VFMADD231SS | - Opcode::VFMADDSUB132PD | - Opcode::VFMADDSUB132PS | - Opcode::VFMADDSUB213PD | - Opcode::VFMADDSUB213PS | - Opcode::VFMADDSUB231PD | - Opcode::VFMADDSUB231PS | - Opcode::VFMSUB132PD | - Opcode::VFMSUB132PS | - Opcode::VFMSUB132SD | - Opcode::VFMSUB132SS | - Opcode::VFMSUB213PD | - Opcode::VFMSUB213PS | - Opcode::VFMSUB213SD | - Opcode::VFMSUB213SS | - Opcode::VFMSUB231PD | - Opcode::VFMSUB231PS | - Opcode::VFMSUB231SD | - Opcode::VFMSUB231SS | - Opcode::VFMSUBADD132PD | - Opcode::VFMSUBADD132PS | - Opcode::VFMSUBADD213PD | - Opcode::VFMSUBADD213PS | - Opcode::VFMSUBADD231PD | - Opcode::VFMSUBADD231PS | - Opcode::VFNMADD132PD | - Opcode::VFNMADD132PS | - Opcode::VFNMADD132SD | - Opcode::VFNMADD132SS | - Opcode::VFNMADD213PD | - Opcode::VFNMADD213PS | - Opcode::VFNMADD213SD | - Opcode::VFNMADD213SS | - Opcode::VFNMADD231PD | - Opcode::VFNMADD231PS | - Opcode::VFNMADD231SD | - Opcode::VFNMADD231SS | - Opcode::VFNMSUB132PD | - Opcode::VFNMSUB132PS | - Opcode::VFNMSUB132SD | - Opcode::VFNMSUB132SS | - Opcode::VFNMSUB213PD | - Opcode::VFNMSUB213PS | - Opcode::VFNMSUB213SD | - Opcode::VFNMSUB213SS | - Opcode::VFNMSUB231PD | - Opcode::VFNMSUB231PS | - Opcode::VFNMSUB231SD | - Opcode::VFNMSUB231SS | - Opcode::VGATHERDPD | - Opcode::VGATHERDPS | - Opcode::VGATHERQPD | - Opcode::VGATHERQPS | - Opcode::VHADDPD | - Opcode::VHSUBPD | - Opcode::VINSERTF128 | - Opcode::VINSERTI128 | - Opcode::VINSERTPS | - Opcode::VMASKMOVDQU | - Opcode::VMASKMOVPD | - Opcode::VMASKMOVPS | - Opcode::VMAXPD | - Opcode::VMAXPS | - Opcode::VMAXSD | - Opcode::VMAXSS | - Opcode::VMINPD | - Opcode::VMINPS | - Opcode::VMINSD | - Opcode::VMINSS | - Opcode::VMOVAPD | - Opcode::VMOVAPS | - Opcode::VMOVD | - Opcode::VMOVDQA | - Opcode::VMOVDQU | - Opcode::VMOVHLPS | - Opcode::VMOVHPD | - Opcode::VMOVHPS | - Opcode::VMOVLHPS | - Opcode::VMOVLPD | - Opcode::VMOVLPS | - Opcode::VMOVMSKPD | - Opcode::VMOVMSKPS | - Opcode::VMOVNTDQ | - Opcode::VMOVNTDQA | - Opcode::VMOVNTPD | - Opcode::VMOVNTPS | - Opcode::VMOVQ | - Opcode::VMOVSS | - Opcode::VMOVSD | - Opcode::VMOVSHDUP | - Opcode::VMOVSLDUP | - Opcode::VMOVUPD | - Opcode::VMOVUPS | - Opcode::VMPSADBW | - Opcode::VMULPD | - Opcode::VMULPS | - Opcode::VMULSD | - Opcode::VMULSS | - Opcode::VPABSB | - Opcode::VPABSD | - Opcode::VPABSW | - Opcode::VPACKSSDW | - Opcode::VPACKSSWB | - Opcode::VPACKUSWB | - Opcode::VPADDB | - Opcode::VPADDD | - Opcode::VPADDQ | - Opcode::VPADDSB | - Opcode::VPADDSW | - Opcode::VPADDUSB | - Opcode::VPADDUSW | - Opcode::VPADDW | - Opcode::VPALIGNR | - Opcode::VPAND | - Opcode::VPANDN | - Opcode::VPAVGB | - Opcode::VPAVGW | - Opcode::VPBLENDD | - Opcode::VPBLENDVB | - Opcode::VPBLENDW | - Opcode::VPBROADCASTB | - Opcode::VPBROADCASTD | - Opcode::VPBROADCASTQ | - Opcode::VPBROADCASTW | - Opcode::VPCLMULQDQ | - Opcode::VPCMPEQB | - Opcode::VPCMPEQD | - Opcode::VPCMPEQQ | - Opcode::VPCMPEQW | - Opcode::VPCMPGTB | - Opcode::VPCMPGTD | - Opcode::VPCMPGTQ | - Opcode::VPCMPGTW | - Opcode::VPCMPISTRI | - Opcode::VPCMPISTRM | - Opcode::VPERM2F128 | - Opcode::VPERM2I128 | - Opcode::VPERMD | - Opcode::VPERMILPD | - Opcode::VPERMILPS | - Opcode::VPERMPD | - Opcode::VPERMPS | - Opcode::VPERMQ | - Opcode::VPEXTRB | - Opcode::VPEXTRD | - Opcode::VPEXTRQ | - Opcode::VPEXTRW | - Opcode::VPGATHERDD | - Opcode::VPGATHERDQ | - Opcode::VPGATHERQD | - Opcode::VPGATHERQQ | - Opcode::VPHADDD | - Opcode::VPHADDSW | - Opcode::VPHADDW | - Opcode::VPHADDUBSW | - Opcode::VPHMINPOSUW | - Opcode::VPHSUBD | - Opcode::VPHSUBSW | - Opcode::VPHSUBW | - Opcode::VPINSRB | - Opcode::VPINSRD | - Opcode::VPINSRQ | - Opcode::VPINSRW | - Opcode::VPMADDWD | - Opcode::VPMASKMOVD | - Opcode::VPMASKMOVQ | - Opcode::VPMAXSB | - Opcode::VPMAXSD | - Opcode::VPMAXSW | - Opcode::VPMAXUD | - Opcode::VPMINSD | - Opcode::VPMINUD | - Opcode::VPMOVMSKB | - Opcode::VPMOVSXBD | - Opcode::VPMOVSXBQ | - Opcode::VPMOVSXBW | - Opcode::VPMOVSXDQ | - Opcode::VPMOVSXWD | - Opcode::VPMOVSXWQ | - Opcode::VPMOVZXBD | - Opcode::VPMOVZXBQ | - Opcode::VPMOVZXBW | - Opcode::VPMOVZXDQ | - Opcode::VPMOVZXWD | - Opcode::VPMOVZXWQ | - Opcode::VPMULDQ | - Opcode::VPMULHRSW | - Opcode::VPMULHUW | - Opcode::VPMULHW | - Opcode::VPMULLD | - Opcode::VPMULLW | - Opcode::VPMULUDQ | - Opcode::VPOR | - Opcode::VPSADBW | - Opcode::VPSHUFB | - Opcode::VPSHUFD | - Opcode::VPSIGNB | - Opcode::VPSIGND | - Opcode::VPSIGNW | - Opcode::VPSLLD | - Opcode::VPSLLDQ | - Opcode::VPSLLQ | - Opcode::VPSLLVD | - Opcode::VPSLLVQ | - Opcode::VPSLLW | - Opcode::VPSRAD | - Opcode::VPSRAVD | - Opcode::VPSRAW | - Opcode::VPSRLD | - Opcode::VPSRLDQ | - Opcode::VPSRLQ | - Opcode::VPSRLVD | - Opcode::VPSRLVQ | - Opcode::VPSRLW | - Opcode::VPSUBB | - Opcode::VPSUBD | - Opcode::VPSUBQ | - Opcode::VPSUBSB | - Opcode::VPSUBSW | - Opcode::VPSUBUSB | - Opcode::VPSUBUSW | - Opcode::VPSUBW | - Opcode::VPTEST | - Opcode::VPUNPCKHBW | - Opcode::VPUNPCKHDQ | - Opcode::VPUNPCKHQDQ | - Opcode::VPUNPCKHWD | - Opcode::VPUNPCKLBW | - Opcode::VPUNPCKLDQ | - Opcode::VPUNPCKLQDQ | - Opcode::VPUNPCKLWD | - Opcode::VPXOR | - Opcode::VRCPPS | - Opcode::VROUNDPD | - Opcode::VROUNDPS | - Opcode::VROUNDSD | - Opcode::VROUNDSS | - Opcode::VRSQRTPS | - Opcode::VRSQRTSS | - Opcode::VRCPSS | - Opcode::VSHUFPD | - Opcode::VSHUFPS | - Opcode::VSQRTPD | - Opcode::VSQRTPS | - Opcode::VSQRTSS | - Opcode::VSQRTSD | - Opcode::VSUBPD | - Opcode::VSUBPS | - Opcode::VSUBSD | - Opcode::VSUBSS | - Opcode::VTESTPD | - Opcode::VTESTPS | - Opcode::VUNPCKHPD | - Opcode::VUNPCKHPS | - Opcode::VUNPCKLPD | - Opcode::VUNPCKLPS | - Opcode::VXORPD | - Opcode::VXORPS | - Opcode::VZEROUPPER => { - // TODO: check a table for these - if !self.avx() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - Opcode::VAESDEC | - Opcode::VAESDECLAST | - Opcode::VAESENC | - Opcode::VAESENCLAST | - Opcode::VAESIMC | - Opcode::VAESKEYGENASSIST => { - // TODO: check a table for these - if !self.avx() || !self.aesni() { - inst.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - other => { - if !self.bmi1() { - if BMI1.contains(&other) { - return Err(DecodeError::InvalidOpcode); - } - } - } - } - Ok(()) - } -} - -impl Default for InstDecoder { - /// Instantiates an x86_64 decoder that probably decodes what you want. - /// - /// Attempts to match real processors in interpretation of undefined sequences, and decodes any - /// instruction defined in any extension. - fn default() -> Self { - Self { - flags: 0xffffffff_ffffffff, - } - } -} - -impl Decoder for InstDecoder { - type Error = DecodeError; - - fn decode>(&self, bytes: T) -> Result { - let mut instr = Instruction::invalid(); - decode_one(self, bytes, &mut instr) - .map(|_: ()| instr) - } - fn decode_into>(&self, instr: &mut Instruction, bytes: T) -> Result<(), Self::Error> { - decode_one(self, bytes, instr) - } -} - -impl Opcode { - pub fn condition(&self) -> Option { - match self { - Opcode::JO | - Opcode::CMOVO | - Opcode::SETO => { Some(ConditionCode::O) }, - Opcode::JNO | - Opcode::CMOVNO | - Opcode::SETNO => { Some(ConditionCode::NO) }, - Opcode::JB | - Opcode::CMOVB | - Opcode::SETB => { Some(ConditionCode::B) }, - Opcode::JNB | - Opcode::CMOVNB | - Opcode::SETAE => { Some(ConditionCode::AE) }, - Opcode::JZ | - Opcode::CMOVZ | - Opcode::SETZ => { Some(ConditionCode::Z) }, - Opcode::JNZ | - Opcode::CMOVNZ | - Opcode::SETNZ => { Some(ConditionCode::NZ) }, - Opcode::JA | - Opcode::CMOVA | - Opcode::SETA => { Some(ConditionCode::A) }, - Opcode::JNA | - Opcode::CMOVNA | - Opcode::SETBE => { Some(ConditionCode::BE) }, - Opcode::JS | - Opcode::CMOVS | - Opcode::SETS => { Some(ConditionCode::S) }, - Opcode::JNS | - Opcode::CMOVNS | - Opcode::SETNS => { Some(ConditionCode::NS) }, - Opcode::JP | - Opcode::CMOVP | - Opcode::SETP => { Some(ConditionCode::P) }, - Opcode::JNP | - Opcode::CMOVNP | - Opcode::SETNP => { Some(ConditionCode::NP) }, - Opcode::JL | - Opcode::CMOVL | - Opcode::SETL => { Some(ConditionCode::L) }, - Opcode::JGE | - Opcode::CMOVGE | - Opcode::SETGE => { Some(ConditionCode::GE) }, - Opcode::JG | - Opcode::CMOVG | - Opcode::SETG => { Some(ConditionCode::G) }, - Opcode::JLE | - Opcode::CMOVLE | - Opcode::SETLE => { Some(ConditionCode::LE) }, - _ => None, - } - } -} - -impl Default for Instruction { - fn default() -> Self { - Instruction::invalid() - } -} - -impl Instruction { - pub fn operand(&self, i: u8) -> Operand { - assert!(i < 4); - Operand::from_spec(self, self.operands[i as usize]) - } - - pub fn operand_count(&self) -> u8 { - let mut i = 0; - for op in self.operands.iter() { - if let OperandSpec::Nothing = op { - return i; - } else { - i += 1; - } - } - return i; - } - - pub fn operand_present(&self, i: u8) -> bool { - assert!(i < 4); - if let OperandSpec::Nothing = self.operands[i as usize] { - false - } else { - true - } - } - - pub fn invalid() -> Instruction { - Instruction { - prefixes: Prefixes::new(0), - opcode: Opcode::Invalid, - modrm_rrr: RegSpec::rax(), - modrm_mmm: RegSpec::rax(), // doubles as sib_base - sib_index: RegSpec::rax(), - vex_reg: RegSpec::rax(), - scale: 0, - length: 0, - disp: 0, - imm: 0, - operand_count: 0, - operands: [OperandSpec::Nothing; 4], - } - } - - pub fn is_invalid(&self) -> bool { - match self.opcode { - Opcode::Invalid => true, - _ => false - } - } - - pub fn segment_override_for_op(&self, op: u8) -> Option { - match self.opcode { - Opcode::STOS => { - if op == 0 { - Some(Segment::ES) - } else { - None - } - } - Opcode::LODS => { - if op == 1 { - Some(self.prefixes.segment) - } else { - None - } - } - Opcode::MOVS => { - if op == 0 { - Some(Segment::ES) - } else if op == 1 { - Some(self.prefixes.segment) - } else { - None - } - } - Opcode::CMPS => { - if op == 0 { - Some(self.prefixes.segment) - } else if op == 1 { - Some(Segment::ES) - } else { - None - } - }, - _ => { - // most operands are pretty simple: - if self.operands[op as usize].is_memory() && - self.prefixes.segment != Segment::DS { - Some(self.prefixes.segment) - } else { - None - } - } - } - } -} - -#[derive(Debug, Copy, Clone)] -pub struct Prefixes { - bits: u8, - rex: PrefixRex, - segment: Segment, -} - -#[derive(Debug, Copy, Clone)] -pub struct PrefixVex { - bits: u8, -} - -#[allow(dead_code)] -impl PrefixVex { - #[inline] - fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } - #[inline] - fn x(&self) -> bool { (self.bits & 0x02) == 0x02 } - #[inline] - fn r(&self) -> bool { (self.bits & 0x04) == 0x04 } - #[inline] - fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } - #[inline] - fn l(&self) -> bool { (self.bits & 0x10) == 0x10 } -} - -#[derive(Debug, Copy, Clone)] -pub struct PrefixRex { - bits: u8 -} - -#[allow(dead_code)] -impl Prefixes { - fn new(bits: u8) -> Prefixes { - Prefixes { - bits: bits, - rex: PrefixRex { bits: 0 }, - segment: Segment::DS, - } - } - #[inline] - fn rep(&self) -> bool { self.bits & 0x30 == 0x10 } - #[inline] - fn set_rep(&mut self) { self.bits = (self.bits & 0xcf) | 0x10 } - #[inline] - pub fn repz(&self) -> bool { self.bits & 0x30 == 0x20 } - #[inline] - fn set_repz(&mut self) { self.bits = (self.bits & 0xcf) | 0x20 } - #[inline] - pub fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 } - #[inline] - fn set_repnz(&mut self) { self.bits = (self.bits & 0xcf) | 0x30 } - #[inline] - fn operand_size(&self) -> bool { self.bits & 0x1 == 1 } - #[inline] - fn set_operand_size(&mut self) { self.bits = self.bits | 0x1 } - #[inline] - fn address_size(&self) -> bool { self.bits & 0x2 == 2 } - #[inline] - fn set_address_size(&mut self) { self.bits = self.bits | 0x2 } - #[inline] - fn set_lock(&mut self) { self.bits |= 0x4 } - #[inline] - pub fn lock(&self) -> bool { self.bits & 0x4 == 4 } - #[inline] - fn cs(&mut self) { self.segment = Segment::CS } - #[inline] - fn set_cs(&mut self) { self.segment = Segment::CS } - #[inline] - pub fn ds(&self) -> bool { self.segment == Segment::DS } - #[inline] - fn set_ds(&mut self) { self.segment = Segment::DS } - #[inline] - pub fn es(&self) -> bool { self.segment == Segment::ES } - #[inline] - fn set_es(&mut self) { self.segment = Segment::ES } - #[inline] - pub fn fs(&self) -> bool { self.segment == Segment::FS } - #[inline] - fn set_fs(&mut self) { self.segment = Segment::FS } - #[inline] - pub fn gs(&self) -> bool { self.segment == Segment::GS } - #[inline] - fn set_gs(&mut self) { self.segment = Segment::GS } - #[inline] - pub fn ss(&self) -> bool { self.segment == Segment::SS } - #[inline] - fn set_ss(&mut self) { self.segment = Segment::SS } - #[inline] - fn rex(&self) -> &PrefixRex { &self.rex } - #[inline] - fn vex(&self) -> PrefixVex { PrefixVex { bits: self.rex.bits } } - - #[inline] - fn rex_from(&mut self, bits: u8) { - self.rex.bits = bits; - } - - #[inline] - fn vex_from_c5(&mut self, bits: u8) { - // collect rex bits - let r = bits & 0x80; - let wrxb = (r >> 5) ^ 0x04; - let l = (bits & 0x04) << 2; - let synthetic_rex = wrxb | l | 0x80; - self.rex.from(synthetic_rex); - } - - #[inline] - fn vex_from_c4(&mut self, high: u8, low: u8) { - let w = low & 0x80; - let rxb = (high >> 5) ^ 0x07; - let wrxb = rxb | w >> 4; - let l = (low & 0x04) << 2; - let synthetic_rex = wrxb | l | 0x80; - self.rex.from(synthetic_rex); - } -} - -impl PrefixRex { - #[inline] - fn present(&self) -> bool { (self.bits & 0xc0) == 0x40 } - #[inline] - fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } - #[inline] - fn x(&self) -> bool { (self.bits & 0x02) == 0x02 } - #[inline] - fn r(&self) -> bool { (self.bits & 0x04) == 0x04 } - #[inline] - fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } - #[inline] - fn from(&mut self, prefix: u8) { - self.bits = prefix; - } -} - -#[allow(non_camel_case_types)] -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum OperandCode { - ModRM_0x0f00, - ModRM_0x0f01, - ModRM_0x0f13, - ModRM_0x0fae, - ModRM_0x0fba, - ModRM_0xf238, - ModRM_0xf30fc7, - ModRM_0x660f38, - ModRM_0x660f3a, - CVT_AA, - CVT_DA, - Rq_Cq_0, - Rq_Dq_0, - Cq_Rq_0, - Dq_Rq_0, - FS, - GS, - Yb_DX, - Yv_DX, - DX_Xb, - DX_Xv, - OR, - AH, - AX_Xv, - DX_AX, - E_G_xmm, - Ev_Ivs, - Ew_Sw, - Fw, - I_3, - Ib, - Ibs, - Ivs, - Iw, - Iw_Ib, - Jvds, - Ob_AL, - Ov_AX, - Sw_Ew, - Yb_AL, - Yb_Xb, - Yv_AX, - Yv_Xv, - G_E_q, - G_M_q, - E_G_q, - Rv_Gmm_Ib, - G_mm_Ew_Ib, - Mq_Dq, - eAX, - ModRM_0x0f38, - ModRM_0x0f3a, - ModRM_0x0f71, - ModRM_0x0f72, - ModRM_0x0f73, - ModRM_0x660f71, - ModRM_0x660f72, - ModRM_0x660f73, - ModRM_0x0fc7, - Nothing, - Implied, - Unsupported, - Zv_R0 = 0x40, - Zv_R1 = 0x41, - Zv_R2 = 0x42, - Zv_R3 = 0x43, - Zv_R4 = 0x44, - Zv_R5 = 0x45, - Zv_R6 = 0x46, - Zv_R7 = 0x47, - Zv_AX_R0 = 0x48, - Zv_AX_R1 = 0x49, - Zv_AX_R2 = 0x4a, - Zv_AX_R3 = 0x4b, - Zv_AX_R4 = 0x4c, - Zv_AX_R5 = 0x4d, - Zv_AX_R6 = 0x4e, - Zv_AX_R7 = 0x4f, - Zb_Ib_R0 = 0x50, - Zb_Ib_R1 = 0x51, - Zb_Ib_R2 = 0x52, - Zb_Ib_R3 = 0x53, - Zb_Ib_R4 = 0x54, - Zb_Ib_R5 = 0x55, - Zb_Ib_R6 = 0x56, - Zb_Ib_R7 = 0x57, - Zv_Ivq_R0 = 0x58, - Zv_Ivq_R1 = 0x59, - Zv_Ivq_R2 = 0x5a, - Zv_Ivq_R3 = 0x5b, - Zv_Ivq_R4 = 0x5c, - Zv_Ivq_R5 = 0x5d, - Zv_Ivq_R6 = 0x5e, - Zv_Ivq_R7 = 0x5f, - Gv_Eb = 0x60, - Gv_Ew = 0x61, - Gdq_Ed = 0x62, - G_E_mm_Ib = 0x64, - G_E_xmm_Ib = 0x65, - AL_Ib = 0x66, - AX_Ivd = 0x67, - AL_Ob = 0x68, - AL_Xb = 0x69, - AX_AL = 0x6a, - AX_Ov = 0x6b, - - Eb_Gb = 0x80, - Ev_Gv = 0x81, - Gb_Eb = 0xc2, - Gv_Ev = 0xc3, - Gb_Eb_Ib = 0xc4, - Gv_Ev_Iv = 0xc5, - // gap: 0xc6 - Gd_U_xmm = 0xc7, - M_G_xmm = 0xc9, - ModRM_0x0f12 = 0xcb, - ModRM_0x0f16 = 0xce, - ModRM_0xc0_Eb_Ib = 0x86, - ModRM_0xc1_Ev_Ib = 0x87, - ModRM_0xd0_Eb_1 = 0x88, - ModRM_0xd1_Ev_1 = 0x89, - ModRM_0xd2_Eb_CL = 0x8a, - ModRM_0xd3_Ev_CL = 0x8b, - ModRM_0x80_Eb_Ib = 0x8c, - ModRM_0x83_Ev_Ibs = 0x8d, - // this would be Eb_Ivs, 0x8e - ModRM_0x81_Ev_Ivs = 0x8f, - ModRM_0xc6_Eb_Ib = 0x90, - ModRM_0xc7_Ev_Iv = 0x91, - ModRM_0xfe_Eb = 0x92, - ModRM_0x8f_Ev = 0x93, - // gap, 0x94 - ModRM_0xff_Ev = 0x95, - ModRM_0xf6 = 0x96, - ModRM_0xf7 = 0x97, - Eb_R0 = 0x98, - Ev = 0x99, - ModRM_0x0f18 = 0x9b, - // gap, 0x9a - Gv_M = 0xdb, - G_mm_Edq = 0xdd, - G_mm_E = 0xdf, - G_xmm_Ed = 0xe1, - G_xmm_Eq = 0xe3, - G_mm_E_xmm = 0xe5, - G_E_mm = 0xe7, - Edq_G_mm = 0xe9, - E_G_mm = 0xeb, - G_xmm_E_mm = 0xed, - G_xmm_Edq = 0xef, - G_U_mm = 0xf1, - Ev_Gv_Ib = 0xf3, - Ev_Gv_CL = 0xf5, - G_M_xmm = 0xf7, - G_E_xmm = 0xf9, -} - -fn base_opcode_map(v: u8) -> Opcode { - match v { - 0 => Opcode::ADD, - 1 => Opcode::OR, - 2 => Opcode::ADC, - 3 => Opcode::SBB, - 4 => Opcode::AND, - 5 => Opcode::SUB, - 6 => Opcode::XOR, - 7 => Opcode::CMP, - _ => { unsafe { unreachable_unchecked() } } - } -} - -const BITWISE_OPCODE_MAP: [Opcode; 8] = [ - Opcode::ROL, - Opcode::ROR, - Opcode::RCL, - Opcode::RCR, - Opcode::SHL, - Opcode::SHR, - Opcode::SAL, - Opcode::SAR -]; - -const OPCODE_660F_MAP: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x10 - OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPD), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x20 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPD), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTPI2PD), OperandCode::G_xmm_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x30 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f38), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f3a), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x40 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x50 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLBW), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLWD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLDQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSWB), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTB), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTW), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSWB), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHBW), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHWD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHDQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSDW), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLQDQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHQDQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_xmm_Eq), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQA), OperandCode::G_E_xmm), -// 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFD), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f71), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f72), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f73), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQB), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::HADDPD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::HSUBPD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x90 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xa0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::ADDSUBPD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xe0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PXOR), OperandCode::G_E_xmm), -// 0xf0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -]; - -fn read_opcode_660f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { - bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { - *length += 1; - (OPCODE_660F_MAP[b as usize], b) - }) -} - -const OPCODE_F20F_MAP: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x10 - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSD), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVDDUP), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x20 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Edq), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x30 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf238), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x40 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x50 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SQRTSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::ADDSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MULSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSD2SS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SUBSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MINSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::DIVSD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MAXSD), OperandCode::G_E_xmm), -// 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFLW), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::HADDPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::HSUBPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x90 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xa0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPSD), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::ADDSUBPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQ2Q), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xe0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTPD2DQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xf0 - OpcodeRecord(Interpretation::Instruction(Opcode::LDDQU), OperandCode::G_M_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -]; - -fn read_opcode_f20f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { - bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { - *length += 1; - (OPCODE_F20F_MAP[b as usize], b) - }) -} - -const OPCODE_F30F_MAP: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x10 - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSS), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSLDUP), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSHDUP), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x20 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SS), OperandCode::G_xmm_Edq), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTTSS2SI), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSS2SI), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x30 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x40 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x50 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SQRTSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::RSQRTSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::RCPSS), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::ADDSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MULSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTSS2SD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTTPS2DQ), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SUBSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MINSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::DIVSS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MAXSS), OperandCode::G_E_xmm), -// 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQU), OperandCode::G_E_xmm), -// 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFHW), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQU), OperandCode::E_G_xmm), -// 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x90 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xa0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::POPCNT), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPSS), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30fc7), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ2DQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xe0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTDQ2PD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xf0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -]; - -fn read_opcode_f30f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { - bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { - *length += 1; - (OPCODE_F30F_MAP[b as usize], b) - }) - /* - match bytes_iter.next() { - Some(b) => { - *length += 1; - match b { - 0x10 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::G_E_xmm) }, - 0x11 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::E_G_xmm) }, - 0x12 => { instruction.opcode = Opcode::MOVSLDUP; Some(OperandCode::G_E_xmm) }, - 0x2a => { instruction.opcode = Opcode::CVTSI2SS; Some(OperandCode::G_E_xmm) }, - 0x2c => { instruction.opcode = Opcode::CVTTSS2SI; Some(OperandCode::G_E_xmm) }, - 0x2d => { instruction.opcode = Opcode::CVTSS2SI; Some(OperandCode::G_E_xmm) }, - 0x51 => { instruction.opcode = Opcode::SQRTSS; Some(OperandCode::G_E_xmm) }, - 0x58 => { instruction.opcode = Opcode::ADDSS; Some(OperandCode::G_E_xmm) }, - 0x59 => { instruction.opcode = Opcode::MULSS; Some(OperandCode::G_E_xmm) }, - 0x5a => { instruction.opcode = Opcode::CVTSS2SD; Some(OperandCode::G_E_xmm) }, - 0x5c => { instruction.opcode = Opcode::SUBSS; Some(OperandCode::G_E_xmm) }, - 0x5d => { instruction.opcode = Opcode::MINSS; Some(OperandCode::G_E_xmm) }, - 0x5e => { instruction.opcode = Opcode::DIVSS; Some(OperandCode::G_E_xmm) }, - 0x5f => { instruction.opcode = Opcode::MAXSS; Some(OperandCode::G_E_xmm) }, - _ => { - instruction.opcode = Opcode::Invalid; - Some(OperandCode::Nothing) - } - } - } - None => { - None - } - } - */ -} -const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), - OpcodeRecord(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CLTS), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SYSRET), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::INVD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::WBINVD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::UD2), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x10 - OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f12), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVLPS), OperandCode::M_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKLPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKHPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f16), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVHPS), OperandCode::M_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f18), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), -// 0x20 - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Dq_0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Cq_Rq_0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Dq_Rq_0), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::E_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTPI2PS), OperandCode::G_xmm_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTPS), OperandCode::M_G_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTTPS2PI), OperandCode::G_mm_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PI), OperandCode::G_mm_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::UCOMISS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::COMISS), OperandCode::G_E_xmm), - -// 0x30 - OpcodeRecord(Interpretation::Instruction(Opcode::WRMSR), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::RDTSC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::RDMSR), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::RDPMC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SYSENTER), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SYSEXIT), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::GETSEC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f38), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f3a), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - -// 0x40 - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVO), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNO), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVZ), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNZ), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNA), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVA), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVS), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNS), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVP), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNP), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVL), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVGE), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVLE), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMOVG), OperandCode::Gv_Ev), - -// 0x50 - OpcodeRecord(Interpretation::Instruction(Opcode::MOVMSKPS), OperandCode::Gd_U_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::SQRTPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::RSQRTPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::RCPPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::ANDPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::ANDNPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::ORPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::XORPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::ADDPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MULPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PD), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::CVTDQ2PS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::SUBPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MINPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::DIVPS), OperandCode::G_E_xmm), - OpcodeRecord(Interpretation::Instruction(Opcode::MAXPS), OperandCode::G_E_xmm), - -// 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLBW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLWD), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLDQ), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSWB), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTB), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTD), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSWB), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHBW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHWD), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHDQ), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSDW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::G_mm_Edq), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_mm_E), - -// 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFW), OperandCode::G_E_mm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f71), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f72), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f73), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::EMMS), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::VMREAD), OperandCode::E_G_q), - OpcodeRecord(Interpretation::Instruction(Opcode::VMWRITE), OperandCode::G_E_q), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::Edq_G_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::E_G_mm), - -// 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNO), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JB), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNB), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JZ), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNZ), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNA), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JA), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JS), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNS), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JP), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JNP), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JL), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JGE), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JLE), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JG), OperandCode::Jvds), - -// 0x90 - OpcodeRecord(Interpretation::Instruction(Opcode::SETO), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETNO), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETB), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETAE), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETZ), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETNZ), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETBE), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETA), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETS), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETNS), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETP), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETNP), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETL), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETGE), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETLE), OperandCode::Eb_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::SETG), OperandCode::Eb_R0), - -// 0xa0 - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::FS), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::FS), - OpcodeRecord(Interpretation::Instruction(Opcode::CPUID), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::BT), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::GS), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS), - OpcodeRecord(Interpretation::Instruction(Opcode::RSM), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::BTS), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fae), - OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev), - -// 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::LSS), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::BTR), OperandCode::E_G_q), - OpcodeRecord(Interpretation::Instruction(Opcode::LFS), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::LGS), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_b), OperandCode::Gv_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_w), OperandCode::Gv_Ew), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), // JMPE, ITANIUM - OpcodeRecord(Interpretation::Instruction(Opcode::UD2E), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fba), - OpcodeRecord(Interpretation::Instruction(Opcode::BTC), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::TZCNT), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::BSR), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_b), OperandCode::Gv_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_w), OperandCode::Gv_Ew), - -// 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPPS), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTI), OperandCode::Mq_Dq), - OpcodeRecord(Interpretation::Instruction(Opcode::PINSRW), OperandCode::G_mm_Ew_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Rv_Gmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SHUFPS), OperandCode::G_E_xmm_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fc7), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R7), - -// 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PSRLW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PSRLD), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PSRLQ), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDQ), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::PMULLW), OperandCode::G_E_mm), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PMOVMSKB), OperandCode::G_U_mm), - - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMINUB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PAND), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PANDN), OperandCode::Unsupported), - -// 0xe0 - OpcodeRecord(Interpretation::Instruction(Opcode::PAVGB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSRAW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSRAD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PAVGW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMULHUW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMULHW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMINSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::POR), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDSB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PXOR), OperandCode::G_E_mm), -// 0xf0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PSLLW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSLLD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSLLQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMULUDQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PMADDWD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSADBW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::MASKMOVQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PSUBQ), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDB), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDW), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::PADDD), OperandCode::Unsupported), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -]; -fn read_opcode_0f_map>(bytes_iter: &mut T, length: &mut u8) -> Result { - bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { - *length += 1; - OPCODE_0F_MAP[b as usize] - }) -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -enum Interpretation { - Instruction(Opcode), - Prefix, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -// this should be a 32-byte struct.. -struct OpcodeRecord(Interpretation, OperandCode); - -#[test] -fn opcode_record_size() { - // there are more than 256 opcodes... - assert_eq!(core::mem::size_of::(), 4); -} - -const OPCODES: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0x40: - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), -// 0x50: - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R7), -// 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVSXD), OperandCode::Gdq_Ed), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ivs), - OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Iv), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gb_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yb_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yv_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xv), -// 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNO), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JB), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNB), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JZ), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNZ), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNA), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JA), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JS), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNS), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JP), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNP), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JL), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JGE), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JLE), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JG), OperandCode::Ibs), -// 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x80_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x81_Ev_Ivs), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x83_Ev_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ew_Sw), - OpcodeRecord(Interpretation::Instruction(Opcode::LEA), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Sw_Ew), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x8f_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_AA), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_DA), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSHF), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::POPF), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SAHF), OperandCode::AH), - OpcodeRecord(Interpretation::Instruction(Opcode::LAHF), OperandCode::AH), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AL_Ob), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AX_Ov), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ob_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ov_AX), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yb_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yv_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yb_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yv_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AL_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yb_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yv_AX), - OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AL_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AX_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yb_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yv_AX), -// 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R7), -// 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc0_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw), - OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv), - OpcodeRecord(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::LEAVE), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Iw), - OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::I_3), - OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::INTO), OperandCode::Fw), - OpcodeRecord(Interpretation::Instruction(Opcode::IRET), OperandCode::Fw), -// 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd0_Eb_1), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd1_Ev_1), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd2_Eb_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd3_Ev_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // XLAT - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 d8 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 d9 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 da - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 db - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 dc - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 dd - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 de - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // x86 df - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xe0 - // LOOPNZ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // LOOPZ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // LOOP - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // JECXZ - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // IN - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // IN - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // OUT - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // OUT - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xe8 - OpcodeRecord(Interpretation::Instruction(Opcode::CALL), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Ibs), - // IN - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // IN - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // OUT - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - // OUT - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -// 0xf0 - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - // ICEBP? - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), -// 0xf4 - OpcodeRecord(Interpretation::Instruction(Opcode::HLT), OperandCode::Nothing), - // CMC - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf6), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf7), - OpcodeRecord(Interpretation::Instruction(Opcode::CLC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::STC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CLI), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::STI), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CLD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::STD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xfe_Eb), - // TODO: test 0xff /3 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xff_Ev), -]; - -#[allow(non_snake_case)] -pub(crate) fn read_E>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result { - let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); - if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, bank) - } else { - read_M(bytes_iter, instr, modrm, length) - } -} -#[allow(non_snake_case)] -pub(crate) fn read_E_xmm>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { - if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::X) - } else { - read_M(bytes_iter, instr, modrm, length) - } -} -#[allow(non_snake_case)] -pub(crate) fn read_E_ymm>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { - if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::Y) - } else { - read_M(bytes_iter, instr, modrm, length) - } -} - -#[allow(non_snake_case)] -fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result { - instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank); - Ok(OperandSpec::RegMMM) -} - -#[allow(non_snake_case)] -fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { - let modbits = modrm >> 6; - let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; - let sibbyte = bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?; - *length += 1; - - let op_spec = if (sibbyte & 7) == 0b101 { - let disp = if modbits == 0b00 { - *length += 4; - read_num(bytes_iter, 4)? as i32 - } else if modbits == 0b01 { - *length += 1; - read_num(bytes_iter, 1)? as i8 as i32 - } else { - *length += 4; - read_num(bytes_iter, 4)? as i32 - }; - - if ((sibbyte >> 3) & 7) == 0b100 { - if modbits == 0b00 && !instr.prefixes.rex().x() { - instr.disp = disp as u32 as u64; - - OperandSpec::DispU32 - } else { - let reg = RegSpec::from_parts(0b100, instr.prefixes.rex().x(), addr_width); - instr.modrm_mmm = reg; - - if disp == 0 { - OperandSpec::Deref - } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp - } - } - } else { - instr.modrm_mmm = RegSpec::from_parts(5, instr.prefixes.rex().b(), addr_width); - - instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width); - let scale = 1u8 << (sibbyte >> 6); - instr.scale = scale; - - if disp == 0 { - if modbits == 0 { - OperandSpec::RegScaleDisp - } else { - OperandSpec::RegIndexBaseScaleDisp - } - } else { - instr.disp = disp as i64 as u64; - if modbits == 0 { - OperandSpec::RegScale - } else { - OperandSpec::RegIndexBaseScale - } - } - } - } else { - instr.modrm_mmm = RegSpec::from_parts(sibbyte & 7, instr.prefixes.rex().b(), addr_width); - - let disp = if modbits == 0b00 { - 0 - } else if modbits == 0b01 { - *length += 1; - read_num(bytes_iter, 1)? as i8 as i32 - } else { - *length += 4; - read_num(bytes_iter, 4)? as i32 - }; - - if ((sibbyte >> 3) & 7) == 0b100 { - if disp == 0 { - OperandSpec::Deref - } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp - } - } else { - instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width); - let scale = 1u8 << (sibbyte >> 6); - instr.scale = scale; - if disp == 0 { - OperandSpec::RegIndexBaseScale - } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegIndexBaseScaleDisp - } - } - }; - Ok(op_spec) -} - -#[allow(non_snake_case)] -fn read_M>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { - let modbits = modrm >> 6; - let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; - let mmm = modrm & 7; - let op_spec = if mmm == 4 { - return read_sib(bytes_iter, instr, modrm, length); - } else if mmm == 5 && modbits == 0b00 { - *length += 4; - let disp = read_num(bytes_iter, 4)? as i32; - instr.modrm_mmm = - if addr_width == RegisterBank::Q { RegSpec::rip() } else { RegSpec::eip() }; - if disp == 0 { - OperandSpec::Deref - } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp - } - } else { - instr.modrm_mmm = RegSpec::from_parts(mmm, instr.prefixes.rex().b(), addr_width); - - if modbits == 0b00 { - OperandSpec::Deref - } else { - let disp = if modbits == 0b01 { - *length += 1; - read_num(bytes_iter, 1)? as i8 as i32 - } else { - *length += 4; - read_num(bytes_iter, 4)? as i32 - }; - if disp == 0 { - OperandSpec::Deref - } else { - instr.disp = disp as i64 as u64; - OperandSpec::RegDisp - } - } - }; - Ok(op_spec) -} - -#[inline] -fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { - match width { - 1 => return if rex { RegisterBank::rB } else { RegisterBank::B }, - 2 => return RegisterBank::W, - 4 => return RegisterBank::D, - 8 => return RegisterBank::Q, - _ => unsafe { unreachable_unchecked(); } - } -} - -fn read_instr>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), DecodeError> { - let mut length = 0u8; - let mut alternate_opcode_map: Option = None; -// use core::intrinsics::unlikely; - let mut prefixes = Prefixes::new(0); - - fn escapes_are_prefixes_actually(prefixes: &mut Prefixes, opc_map: &mut Option) { - match opc_map { - Some(OpcodeMap::Map66) => { - prefixes.set_operand_size(); - }, - Some(OpcodeMap::MapF2) => { - prefixes.set_repnz(); - }, - Some(OpcodeMap::MapF3) => { - prefixes.set_rep(); - }, - None => {} - } - *opc_map = None; - } - - let record: OpcodeRecord = loop { -// let operand_code = loop { - match bytes_iter.next() { - Some(b) => { - length += 1; - let record = OPCODES[b as usize]; - if (b & 0xf0) == 0x40 { - prefixes.rex_from(b); - } else if b == 0x0f { - let record = match alternate_opcode_map { - Some(opcode_map) => { - let (rec, opcode_byte) = match opcode_map { - OpcodeMap::Map66 => { - read_opcode_660f_map(&mut bytes_iter, &mut length)? - }, - OpcodeMap::MapF2 => { - read_opcode_f20f_map(&mut bytes_iter, &mut length)? - }, - OpcodeMap::MapF3 => { - read_opcode_f30f_map(&mut bytes_iter, &mut length)? - }, - }; - if rec == OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing) { - escapes_are_prefixes_actually(&mut prefixes, &mut Some(opcode_map)); - OPCODE_0F_MAP[opcode_byte as usize] - } else { - rec - } - }, - None => { - read_opcode_0f_map(&mut bytes_iter, &mut length)? - } - }; - - break record; - } else if let Interpretation::Instruction(_) = record.0 { - escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map); - break record; - } else { - // some prefix seen after we saw rex, but before the 0f escape or an actual - // opcode. so we must forget the rex prefix! - // this is to handle sequences like 41660f21cf - // where if 660f21 were a valid opcode, 41 would apply a rex.b - // prefix, but since 660f21 is not valid, the opcode is interpreted - // as 0f21, where 66 is a prefix, which makes 41 not the last - // prefix before the opcode, and it's discarded. - - // 2.3.2 - // Any VEX-encoded instruction with a LOCK prefix preceding VEX will #UD. - // 2.3.3 - // Any VEX-encoded instruction with a 66H, F2H, or F3H prefix preceding VEX - // will #UD. - // 2.3.4 - // Any VEX-encoded instruction with a REX prefix proceeding VEX will #UD. - if b == 0xc5 { - if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() { - // rex and then vex is invalid! reject it. - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidPrefixes); - } else { - instruction.prefixes = prefixes; - vex::two_byte_vex(&mut bytes_iter, instruction, length)?; - - if decoder != &InstDecoder::default() { - decoder.revise_instruction(instruction)?; - } - return Ok(()); - } - } else if b == 0xc4 { - if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() { - // rex and then vex is invalid! reject it. - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidPrefixes); - } else { - instruction.prefixes = prefixes; - vex::three_byte_vex(&mut bytes_iter, instruction, length)?; - if decoder != &InstDecoder::default() { - decoder.revise_instruction(instruction)?; - } - return Ok(()); - } - } - - prefixes.rex_from(0); - escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map); - match b { - 0x26 => { - prefixes.set_es(); - }, - 0x2e => { - prefixes.set_cs(); - }, - 0x36 => { - prefixes.set_ss(); - }, - 0x3e => { - prefixes.set_ds(); - }, - 0x64 => { - prefixes.set_fs(); - }, - 0x65 => { - prefixes.set_gs(); - }, - 0x66 => { - alternate_opcode_map = Some(OpcodeMap::Map66); - }, - 0x67 => { - prefixes.set_address_size(); - }, - 0x9b => { - // TODO: WAIT prefix - return Err(DecodeError::IncompleteDecoder); - }, - 0xf0 => { - prefixes.set_lock(); - }, - 0xf2 => { - alternate_opcode_map = Some(OpcodeMap::MapF2); - }, - 0xf3 => { - alternate_opcode_map = Some(OpcodeMap::MapF3); - }, - _ => { unsafe { unreachable_unchecked(); } } - } - } - }, - None => { - return Err(DecodeError::ExhaustedInput); - } - } - }; - if let Interpretation::Instruction(opcode) = record.0 { - instruction.opcode = opcode; - } else { - unsafe { unreachable_unchecked(); } - } - instruction.prefixes = prefixes; - read_operands(decoder, bytes_iter, instruction, record.1, &mut length)?; - instruction.length = length; - - if decoder != &InstDecoder::default() { - // we might have to fix up or reject this instruction under whatever cpu features we need to - // pretend to have. - decoder.revise_instruction(instruction)?; - } - Ok(()) -} -fn read_operands>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), DecodeError> { - if (operand_code as u8) & 0x40 == 0x40 { - instruction.operands[0] = OperandSpec::RegRRR; - } - if (operand_code as u8) >= 0x40 && (operand_code as u8) < 0x60 { - let reg = (operand_code as u8) & 0x07; - let category = ((operand_code as u8) & 0x18) >> 3; - if category == 0 { - // these are Zv_R - let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); - let bank = if opwidth == 4 { - RegisterBank::D - } else if opwidth == 2 { - RegisterBank::W - } else { - RegisterBank::Q - }; - instruction.modrm_rrr = - RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); - instruction.operand_count = 1; - // Zv_AX are missing! - } else if category == 2 { - // these are Zb_Ib_R - instruction.modrm_rrr = - RegSpec::gp_from_parts(reg, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present()); - instruction.imm = - read_imm_unsigned(&mut bytes_iter, 1, length)?; - instruction.operands[1] = OperandSpec::ImmU8; - instruction.operand_count = 2; - } else { - // category == 3, Zv_Ivq_R - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let bank = if opwidth == 4 { - RegisterBank::D - } else if opwidth == 2 { - RegisterBank::W - } else { - RegisterBank::Q - }; - instruction.modrm_rrr = - RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); - instruction.imm = - read_imm_ivq(&mut bytes_iter, opwidth, length)?; - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - } - return Ok(()); - } - - let mut modrm = 0; - let mut opwidth = 0; - let mut mem_oper = OperandSpec::Nothing; - let mut bank = RegisterBank::Q; - let code_int = operand_code as u8; - if ((code_int) & 0x80) == 0x80 { - // cool! we can precompute opwidth and know we need to read_E. - if (code_int & 1) == 1 { - // further, this is an vdq E - opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - if opwidth == 4 { - bank = RegisterBank::D; - } else if opwidth == 2 { - bank = RegisterBank::W; - } - } else { - opwidth = 1; - if instruction.prefixes.rex().present() { - bank = RegisterBank::rB; - } else { - bank = RegisterBank::B; - } - }; - modrm = read_modrm(&mut bytes_iter, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), bank); - - mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - - let numeric_code = (operand_code as u8) & 0xbf; - if numeric_code >= 0x80 && numeric_code < 0x84 { - let (mmm, rrr) = if numeric_code & 0x02 == 2 { - (1, 0) - } else { - (0, 1) - }; - instruction.operands[mmm] = mem_oper; - instruction.operands[rrr] = OperandSpec::RegRRR; - instruction.operand_count = 2; - } else if operand_code == OperandCode::Ibs { - instruction.imm = - read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[0] = OperandSpec::ImmI8; - instruction.operand_count = 1; - } else { - match operand_code { - /* - Gv_Ev_Iv, - Gb_Eb_Ib, - Yb_DX, - Yv_DX, - DX_Xb, - DX_Xv, - OR, - AH, - AL_Ib, - AL_Ob, - AL_Xb, - AX_AL, - AX_Ivd, - AX_Ov, - AX_Xv, - DX_AX, - Eb_1, - Eb_Ib, - Eb_CL, - Ev, - Ev_1, - Ev_CL, - Ev_Ibs, - Ev_Iv, - Ev_Ivs, - Ew_Sw, - Fw, - Gv_M, - I_3, - Ib, - Ibs, - Ivs, - Iw, - Iw_Ib, - Ob_AL, - Ov_AX, - Sw_Ew, - Yb_AL, - Yb_Xb, - Yv_AX, - Yv_Xv, - Zb_Ib, - Zv, - Zv_AX, - */ - OperandCode::Eb_R0 => { - if (modrm & 0b00111000) != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc6".to_owned()); - } - - instruction.operands[0] = mem_oper; - instruction.operand_count = 1; - }, - op @ OperandCode::AL_Ob | - op @ OperandCode::AX_Ov => { - let opwidth = match op { - OperandCode::AL_Ob => 1, - OperandCode::AX_Ov => { - imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 }; - // stupid RCT thing: - let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; - let imm = read_num(&mut bytes_iter, addr_width)?; - *length += addr_width; - instruction.modrm_rrr = - RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()); - instruction.disp = imm; - if instruction.prefixes.address_size() { - instruction.operands[1] = OperandSpec::DispU32; - } else { - instruction.operands[1] = OperandSpec::DispU64; - }; - instruction.operand_count = 2; - } - op @ OperandCode::Ob_AL | - op @ OperandCode::Ov_AX => { - let opwidth = match op { - OperandCode::Ob_AL => 1, - OperandCode::Ov_AX => { - imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes) - } - _ => { - unsafe { unreachable_unchecked() } - } - }; - let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 }; - // stupid RCT thing: - let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; - let imm = read_num(&mut bytes_iter, addr_width)?; - *length += addr_width; - instruction.disp = imm; - instruction.operands[0] = if instruction.prefixes.address_size() { - OperandSpec::DispU32 - } else { - OperandSpec::DispU64 - }; - instruction.modrm_rrr = - RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()); - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; - } - _op @ OperandCode::ModRM_0x80_Eb_Ib | - _op @ OperandCode::ModRM_0x81_Ev_Ivs => { - instruction.operands[0] = mem_oper; - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; - instruction.opcode = base_opcode_map((modrm >> 3) & 7); - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - }, - _op @ OperandCode::ModRM_0xc6_Eb_Ib | - _op @ OperandCode::ModRM_0xc7_Ev_Iv => { - if (modrm & 0b00111000) != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string()); - } - - instruction.operands[0] = mem_oper; - instruction.opcode = Opcode::MOV; - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - }, - op @ OperandCode::ModRM_0xc0_Eb_Ib | - op @ OperandCode::ModRM_0xc1_Ev_Ib | - op @ OperandCode::ModRM_0xd0_Eb_1 | - op @ OperandCode::ModRM_0xd1_Ev_1 | - op @ OperandCode::ModRM_0xd3_Ev_CL => { - instruction.operands[0] = mem_oper; - instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); - if let OperandCode::ModRM_0xd3_Ev_CL = op { - instruction.modrm_rrr = RegSpec::cl(); - instruction.operands[1] = OperandSpec::RegRRR; - } else { - let num = match op { - OperandCode::ModRM_0xc0_Eb_Ib | - OperandCode::ModRM_0xc1_Ev_Ib => { - *length += 1; - read_num(&mut bytes_iter, 1)? - } - _ => { - // these are the _1 variants, everything else is unreachable - 1 - } - }; - instruction.imm = num; - instruction.operands[1] = OperandSpec::ImmI8; - } - instruction.operand_count = 2; - }, - _op @ OperandCode::ModRM_0xf6 | - _op @ OperandCode::ModRM_0xf7 => { - instruction.operands[0] = mem_oper; - instruction.operand_count = 1; - match (modrm >> 3) & 7 { - 0 | 1 => { - instruction.opcode = Opcode::TEST; - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - }, - 2 => { - instruction.opcode = Opcode::NOT; - }, - 3 => { - instruction.opcode = Opcode::NEG; - }, - 4 => { - instruction.opcode = Opcode::MUL; - }, - 5 => { - instruction.opcode = Opcode::IMUL; - }, - 6 => { - instruction.opcode = Opcode::DIV; - }, - 7 => { - instruction.opcode = Opcode::IDIV; - }, - _ => { - unsafe { unreachable_unchecked(); } - } - } - }, - OperandCode::ModRM_0xfe_Eb => { - instruction.operands[0] = mem_oper; - instruction.opcode = [ - Opcode::INC, - Opcode::DEC, - Opcode::Invalid, - Opcode::Invalid, - Opcode::Invalid, - Opcode::Invalid, - Opcode::Invalid, - Opcode::Invalid - ][((modrm >> 3) & 7) as usize]; - instruction.operand_count = 1; - } - OperandCode::ModRM_0xff_Ev => { - instruction.operands[0] = mem_oper; - let opcode = [ - Opcode::INC, - Opcode::DEC, - Opcode::CALL, - Opcode::CALLF, - Opcode::JMP, - Opcode::JMPF, - Opcode::PUSH, - Opcode::Invalid - ][((modrm >> 3) & 7) as usize]; - instruction.opcode = opcode; - instruction.operand_count = 1; - } - OperandCode::Gv_Eb => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 1, length)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::Gv_Ew => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::Gdq_Ed => { - let opwidth = 8; - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4 /* opwidth */, length)?; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::Ev => { - instruction.operands[0] = mem_oper; - instruction.operand_count = 1; - }, - OperandCode::Gv_M => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr = - RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); - instruction.operand_count = 2; - }, - OperandCode::E_G_xmm => { - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[0] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; - }, - OperandCode::G_E_mm => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - } - instruction.operand_count = 2; - }, - OperandCode::G_U_mm => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::D; - if mem_oper != OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); - } - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - instruction.operand_count = 2; - }, - op @ OperandCode::G_M_xmm | - op @ OperandCode::G_E_xmm => { - instruction.modrm_rrr.bank = RegisterBank::X; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operand_count = 2; - if instruction.operands[1] == OperandSpec::RegMMM { - if op == OperandCode::G_M_xmm { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } else { - // fix the register to XMM - instruction.modrm_mmm.bank = RegisterBank::X; - } - } - }, - OperandCode::G_E_xmm_Ib => { - let modrm = read_modrm(&mut bytes_iter, length)?; - - instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; - instruction.modrm_rrr = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.imm = - read_num(&mut bytes_iter, 1)? as u8 as u64; - *length += 1; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - }, - OperandCode::G_E_mm_Ib => { - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; - instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.imm = - read_num(&mut bytes_iter, 1)? as u8 as u64; - *length += 1; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - }, - OperandCode::G_mm_Ew_Ib => { - let modrm = read_modrm(&mut bytes_iter, length)?; - -// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); - instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); - instruction.operands[0] = OperandSpec::RegRRR; - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::D; - } - instruction.imm = - read_num(&mut bytes_iter, 1)? as u8 as u64; - *length += 1; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - } - OperandCode::AL_Ib => { - instruction.modrm_rrr = - RegSpec::al(); - instruction.imm = - read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; - } - OperandCode::AX_Ivd => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.modrm_rrr = - RegSpec::gp_from_parts(0, false, opwidth, false); - instruction.imm = - read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; - instruction.operands[1] = match opwidth { - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - } - OperandCode::Ivs => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); - instruction.imm = - read_imm_unsigned(&mut bytes_iter, opwidth, length)?; - instruction.operands[0] = match opwidth { - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 1; - }, - OperandCode::ModRM_0x83_Ev_Ibs => { - instruction.operands[0] = mem_oper; - instruction.opcode = base_opcode_map((modrm >> 3) & 7); - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; - }, - OperandCode::Jvds => { - let offset = read_num(&mut bytes_iter, 4)?; - *length += 4; - instruction.imm = offset; - instruction.operand_count = 1; - instruction.operands[0] = OperandSpec::ImmI32; - } - OperandCode::Gb_Eb_Ib => { - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.imm = - read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - } - OperandCode::Gv_Ev_Iv => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.imm = - read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; - instruction.operands[2] = match opwidth { - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - 8 => OperandSpec::ImmI64, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 3; - } - OperandCode::Ev_Gv_Ib => { - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.imm = - read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - } - OperandCode::Ev_Gv_CL => { - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operands[2] = OperandSpec::CL; - instruction.operand_count = 3; - } - OperandCode::Nothing => { - instruction.operand_count = 0; - } - _ => { - unlikely_operands(decoder, bytes_iter, instruction, operand_code, mem_oper, length)?; - } - }; - } - - Ok(()) -} -fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, length: &mut u8) -> Result<(), DecodeError> { - match operand_code { - OperandCode::ModRM_0x0f71 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLW; - } - 4 => { - instruction.opcode = Opcode::PSRAW; - } - 6 => { - instruction.opcode = Opcode::PSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::ModRM_0x0f72 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLD; - } - 4 => { - instruction.opcode = Opcode::PSRAD; - } - 6 => { - instruction.opcode = Opcode::PSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::ModRM_0x0f73 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLQ; - } - 6 => { - instruction.opcode = Opcode::PSLLQ; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::ModRM_0x660f38 => { - let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; - match op { - 0xdb => { instruction.opcode = Opcode::AESIMC; } - 0xdc => { instruction.opcode = Opcode::AESENC; } - 0xdd => { instruction.opcode = Opcode::AESENCLAST; } - 0xde => { instruction.opcode = Opcode::AESDEC; } - 0xdf => { instruction.opcode = Opcode::AESDECLAST; } - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - }; - // all these SO FAR are G_E_xmm - let modrm = read_modrm(&mut bytes_iter, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); - - - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; - instruction.operand_count = 2; - } - OperandCode::ModRM_0x660f3a => { - let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; - match op { - 0xdf => { - instruction.opcode = Opcode::AESKEYGENASSIST; - // read operands right here right now - - let modrm = read_modrm(&mut bytes_iter, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); - - - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; - instruction.imm = - read_imm_unsigned(&mut bytes_iter, 1, length)?; - instruction.operands[2] = OperandSpec::ImmU8; - instruction.operand_count = 3; - } - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - }; - } - OperandCode::ModRM_0x660f71 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLW; - } - 4 => { - instruction.opcode = Opcode::PSRAW; - } - 6 => { - instruction.opcode = Opcode::PSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::ModRM_0x660f72 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLD; - } - 4 => { - instruction.opcode = Opcode::PSRAD; - } - 6 => { - instruction.opcode = Opcode::PSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::ModRM_0x660f73 => { - instruction.operand_count = 2; - - let modrm = read_modrm(&mut bytes_iter, length)?; - if modrm & 0xc0 != 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLQ; - } - 3 => { - instruction.opcode = Opcode::PSRLDQ; - } - 6 => { - instruction.opcode = Opcode::PSLLQ; - } - 7 => { - instruction.opcode = Opcode::PSLLDQ; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - - instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; - instruction.operands[0] = OperandSpec::RegMMM; - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmU8; - }, - OperandCode::G_mm_Edq => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - if instruction.prefixes.rex().w() { - instruction.modrm_mmm.bank = RegisterBank::Q; - } else { - instruction.modrm_mmm.bank = RegisterBank::D; - } - } - } - OperandCode::G_mm_E => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - } - } - OperandCode::Edq_G_mm => { - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - if instruction.prefixes.rex().w() { - instruction.modrm_mmm.bank = RegisterBank::Q; - } else { - instruction.modrm_mmm.bank = RegisterBank::D; - } - } - } - OperandCode::E_G_mm => { - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - } - } - OperandCode::G_xmm_Ed => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::X; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::D; - } - }, - OperandCode::G_xmm_Edq => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::X; - if mem_oper == OperandSpec::RegMMM { - if instruction.prefixes.rex().w() { - instruction.modrm_mmm.bank = RegisterBank::Q; - } else { - instruction.modrm_mmm.bank = RegisterBank::D; - } - } - }, - OperandCode::G_xmm_Eq => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::X; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::Q; - } - }, - OperandCode::G_mm_E_xmm => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::MM; - instruction.modrm_rrr.num &= 0b111; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::X; - } - }, - OperandCode::G_xmm_E_mm => { - instruction.operands[1] = mem_oper; - instruction.modrm_rrr.bank = RegisterBank::X; - if mem_oper == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::MM; - instruction.modrm_mmm.num &= 0b111; - } - }, - // sure hope these aren't backwards huh - OperandCode::AL_Xb => { - instruction.operands[0] = OperandSpec::AL; - instruction.operands[1] = OperandSpec::Deref_rsi; - } - // TODO: two memory operands! this is wrong!!! - OperandCode::Yb_Xb => { - instruction.operands[0] = OperandSpec::Deref_rdi; - instruction.operands[1] = OperandSpec::Deref_rsi; - } - OperandCode::Yb_AL => { - instruction.operands[0] = OperandSpec::Deref_rdi; - instruction.operands[1] = OperandSpec::AL; - } - OperandCode::AX_Xv => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - instruction.modrm_rrr = match opwidth { - 2 => RegSpec::ax(), - 4 => RegSpec::eax(), - 8 => RegSpec::rax(), - _ => { unreachable!(); } - }; - instruction.modrm_mmm = RegSpec::rsi(); - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = OperandSpec::Deref; - } - OperandCode::Yv_AX => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - instruction.modrm_rrr = match opwidth { - 2 => RegSpec::ax(), - 4 => RegSpec::eax(), - 8 => RegSpec::rax(), - _ => { unreachable!(); } - }; - instruction.modrm_mmm = RegSpec::rdi(); - instruction.operands[0] = OperandSpec::Deref; - instruction.operands[1] = OperandSpec::RegRRR; - } - OperandCode::Yv_Xv => { - // TODO: repsect prefixes - instruction.operands[0] = OperandSpec::Deref_rdi; - instruction.operands[1] = OperandSpec::Deref_rsi; - } - OperandCode::ModRM_0x0f12 => { - instruction.modrm_rrr.bank = RegisterBank::X; - instruction.operands[1] = mem_oper; - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::X; - instruction.opcode = Opcode::MOVHLPS; - } else { - instruction.opcode = Opcode::MOVLPS; - } - } - OperandCode::ModRM_0x0f16 => { - instruction.modrm_rrr.bank = RegisterBank::X; - instruction.operands[1] = mem_oper; - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.modrm_mmm.bank = RegisterBank::X; - instruction.opcode = Opcode::MOVLHPS; - } else { - instruction.opcode = Opcode::MOVHPS; - } - } - OperandCode::ModRM_0x0f18 => { - if mem_oper == OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); - } - let rrr = instruction.modrm_rrr.num & 0b111; - instruction.operands[0] = mem_oper; - instruction.opcode = match rrr { - 0 => Opcode::PREFETCHNTA, - 1 => Opcode::PREFETCH0, - 2 => Opcode::PREFETCH1, - 3 => Opcode::PREFETCH2, - _ => Opcode::NOP, - }; - } - OperandCode::Gd_U_xmm => { - instruction.operands[1] = mem_oper; - if instruction.operands[1] != OperandSpec::RegMMM { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - instruction.modrm_rrr.bank = RegisterBank::D; - instruction.modrm_mmm.bank = RegisterBank::X; - } - OperandCode::M_G_xmm => { - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = mem_oper; - if instruction.operands[0] == OperandSpec::RegMMM { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - instruction.modrm_rrr.bank = RegisterBank::X; - } - OperandCode::Ew_Sw => { - let opwidth = 2; - let modrm = read_modrm(&mut bytes_iter, length)?; - - // check r - if ((modrm >> 3) & 7) > 5 { - // return Err(()); //Err("Invalid r".to_owned()); - return Err(DecodeError::InvalidOperand); - } - - instruction.modrm_rrr = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; - - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.modrm_mmm = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[0] = OperandSpec::RegMMM; - } else { - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - }, - OperandCode::Sw_Ew => { - let modrm = read_modrm(&mut bytes_iter, length)?; - - // check r - if ((modrm >> 3) & 7) > 5 { - // return Err(()); // Err("Invalid r".to_owned()); - return Err(DecodeError::InvalidOperand); - } - - instruction.modrm_rrr = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operand_count = 2; - - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.modrm_mmm = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[1] = OperandSpec::RegMMM; - } else { - instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; - } - }, - OperandCode::CVT_AA => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - instruction.opcode = match opwidth { - 2 => { Opcode::CBW }, - 4 => { Opcode::CWDE }, - 8 => { Opcode::CDQE }, - _ => { unreachable!("invalid operation width"); }, - } - } - OperandCode::CVT_DA => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); - instruction.opcode = match opwidth { - 2 => { Opcode::CBD }, - 4 => { Opcode::CDQ }, - 8 => { Opcode::CQO }, - _ => { unreachable!("invalid operation width"); }, - } - } - OperandCode::Iw => { - instruction.imm = - read_imm_unsigned(&mut bytes_iter, 2, length)?; - instruction.operands[0] = OperandSpec::ImmU16; - instruction.operand_count = 1; - } - OperandCode::ModRM_0x0f00 => { - instruction.operand_count = 1; - let modrm = read_modrm(&mut bytes_iter, length)?; - let r = (modrm >> 3) & 7; - if r == 0 { - instruction.opcode = Opcode::SLDT; - } else if r == 1 { - instruction.opcode = Opcode::STR; - } else if r == 2 { - instruction.opcode = Opcode::LLDT; - } else if r == 3 { - instruction.opcode = Opcode::LTR; - } else if r == 4 { - instruction.opcode = Opcode::VERR; - } else if r == 5 { - instruction.opcode = Opcode::VERW; - } else if r == 6 { - instruction.opcode = Opcode::JMPE; - instruction.operand_count = 0; - return Ok(()); - } else if r == 7 { - instruction.opcode = Opcode::Invalid; - instruction.operand_count = 0; - return Err(DecodeError::InvalidOperand); - } else { - unreachable!("r <= 8"); - } - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; - } - OperandCode::ModRM_0x0f01 => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - let r = (modrm >> 3) & 7; - if r == 0 { - let mod_bits = modrm >> 6; - let m = modrm & 7; - if mod_bits == 0b11 { - instruction.operand_count = 0; - match m { - 0b000 => { - instruction.opcode = Opcode::ENCLV; - }, - 0b001 => { - instruction.opcode = Opcode::VMCALL; - }, - 0b010 => { - instruction.opcode = Opcode::VMLAUNCH; - }, - 0b011 => { - instruction.opcode = Opcode::VMRESUME; - }, - 0b100 => { - instruction.opcode = Opcode::VMXOFF; - }, - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } else { - instruction.opcode = Opcode::SGDT; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - } else if r == 1 { - let mod_bits = modrm >> 6; - let m = modrm & 7; - if mod_bits == 0b11 { - instruction.operand_count = 0; - match m { - 0b000 => { - instruction.opcode = Opcode::MONITOR; - } - 0b001 => { - instruction.opcode = Opcode::MWAIT; - }, - 0b010 => { - instruction.opcode = Opcode::CLAC; - } - 0b011 => { - instruction.opcode = Opcode::STAC; - } - 0b111 => { - instruction.opcode = Opcode::ENCLS; - } - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } else { - instruction.opcode = Opcode::SIDT; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - } else if r == 2 { - let mod_bits = modrm >> 6; - let m = modrm & 7; - if mod_bits == 0b11 { - instruction.operand_count = 0; - match m { - 0b000 => { - instruction.opcode = Opcode::XGETBV; - } - 0b001 => { - instruction.opcode = Opcode::XSETBV; - } - 0b100 => { - instruction.opcode = Opcode::VMFUNC; - } - 0b101 => { - instruction.opcode = Opcode::XEND; - } - 0b110 => { - instruction.opcode = Opcode::XTEST; - } - 0b111 => { - instruction.opcode = Opcode::ENCLU; - } - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } else { - instruction.opcode = Opcode::LGDT; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - } else if r == 3 { - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.opcode = Opcode::Invalid; - instruction.operand_count = 0; - return Err(DecodeError::InvalidOperand); - } else { - instruction.opcode = Opcode::LIDT; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - } else if r == 4 { - // TODO: this permits storing only to word-size registers - // spec suggets this might do something different for f.ex rdi? - instruction.opcode = Opcode::SMSW; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; - } else if r == 5 { - let m = modrm & 7; - match m { - 0b110 => { - instruction.opcode = Opcode::RDPKRU; - instruction.operand_count = 1; - } - 0b111 => { - instruction.opcode = Opcode::WRPKRU; - instruction.operand_count = 1; - } - _ => { - instruction.opcode = Opcode::Invalid; - instruction.operand_count = 0; - return Err(DecodeError::InvalidOpcode); - } - } - } else if r == 6 { - instruction.opcode = Opcode::LMSW; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; - } else if r == 7 { - let mod_bits = modrm >> 6; - let m = modrm & 7; - if mod_bits == 0b11 { - if m == 0 { - instruction.opcode = Opcode::SWAPGS; - instruction.operand_count = 0; - } else if m == 1 { - instruction.opcode = Opcode::RDTSCP; - instruction.operand_count = 0; - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } else { - instruction.opcode = Opcode::INVLPG; - instruction.operand_count = 1; - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - } - } else { - unreachable!("r <= 8"); - } - } - OperandCode::ModRM_0x0fae => { - let modrm = read_modrm(&mut bytes_iter, length)?; - let r = (modrm >> 3) & 7; - let mod_bits = modrm >> 6; - - // all the 0b11 instructions are err or no-operands - if mod_bits == 0b11 { - instruction.operand_count = 0; - let m = modrm & 7; - match r { - // invalid rrr for 0x0fae, mod: 11 - 0 | 1 | 2 | 3 | 4 => { - return Err(DecodeError::InvalidOpcode); - }, - 5 => { - instruction.opcode = Opcode::LFENCE; - // Intel's manual accepts m != 0, AMD supports m != 0 though the manual - // doesn't say (tested on threadripper) - if !decoder.amd_quirks() && !decoder.intel_quirks() { - if m != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - } - }, - 6 => { - instruction.opcode = Opcode::MFENCE; - // Intel's manual accepts m != 0, AMD supports m != 0 though the manual - // doesn't say (tested on threadripper) - if !decoder.amd_quirks() && !decoder.intel_quirks() { - if m != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - } - }, - 7 => { - instruction.opcode = Opcode::SFENCE; - // Intel's manual accepts m != 0, AMD supports m != 0 though the manual - // doesn't say (tested on threadripper) - if !decoder.amd_quirks() && !decoder.intel_quirks() { - if m != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - } - }, - _ => { unsafe { unreachable_unchecked() } /* r <=7 */ } - } - } else { - instruction.operand_count = 1; - instruction.opcode = [ - Opcode::FXSAVE, - Opcode::FXRSTOR, - Opcode::LDMXCSR, - Opcode::STMXCSR, - Opcode::XSAVE, - Opcode::XRSTOR, - Opcode::XSAVEOPT, - Opcode::CLFLUSH, - ][r as usize]; - instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; - } - } - OperandCode::ModRM_0x0fba => { - let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); - let modrm = read_modrm(&mut bytes_iter, length)?; - let r = (modrm >> 3) & 7; - match r { - 0 | 1 | 2 | 3 => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }, - 4 => { - instruction.opcode = Opcode::BT; - } - 5 => { - instruction.opcode = Opcode::BTS; - } - 6 => { - instruction.opcode = Opcode::BTR; - } - 7 => { - instruction.opcode = Opcode::BTC; - } - _ => { - unreachable!("r < 8"); - } - } - - instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; - - instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; - instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; - } - op @ OperandCode::Rq_Cq_0 | - op @ OperandCode::Rq_Dq_0 | - op @ OperandCode::Cq_Rq_0 | - op @ OperandCode::Dq_Rq_0 => { - let bank = match op { - OperandCode::Rq_Cq_0 | - OperandCode::Cq_Rq_0 => RegisterBank::CR, - OperandCode::Rq_Dq_0 | - OperandCode::Dq_Rq_0 => RegisterBank::DR, - _ => unsafe { unreachable_unchecked() } - }; - let (rrr, mmm) = match op { - OperandCode::Rq_Cq_0 | - OperandCode::Rq_Dq_0 => (1, 0), - OperandCode::Cq_Rq_0 | - OperandCode::Dq_Rq_0 => (0, 1), - _ => unsafe { unreachable_unchecked() } - }; - - let modrm = read_modrm(&mut bytes_iter, length)?; - let mut m = modrm & 7; - let mut r = (modrm >> 3) & 7; - if instruction.prefixes.rex().r() { - r += 0b1000; - } - if instruction.prefixes.rex().b() { - m += 0b1000; - } - instruction.modrm_rrr = - RegSpec { bank: bank, num: r }; - instruction.modrm_mmm = - RegSpec { bank: RegisterBank::Q, num: m }; - instruction.operands[mmm] = OperandSpec::RegMMM; - instruction.operands[rrr] = OperandSpec::RegRRR; - instruction.operand_count = 2; - } - OperandCode::FS => { - instruction.modrm_rrr = RegSpec::fs(); - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operand_count = 1; - } - OperandCode::GS => { - instruction.modrm_rrr = RegSpec::gs(); - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operand_count = 1; - } - OperandCode::I_3 => { - instruction.imm = 3; - instruction.operands[0] = OperandSpec::ImmU8; - instruction.operand_count = 1; - } - _ => { - instruction.operand_count = 0; - instruction.opcode = Opcode::Invalid; -// return Err(()); // Err(format!("unsupported operand code: {:?}", operand_code)); - return Err(DecodeError::InvalidOperand); - } - }; - Ok(()) -} - -fn decode_one<'b, T: IntoIterator>(decoder: &InstDecoder, bytes: T, instr: &'b mut Instruction) -> Result<(), DecodeError> { - instr.operands = [ - OperandSpec::Nothing, - OperandSpec::Nothing, - OperandSpec::Nothing, - OperandSpec::Nothing, - ]; - let bytes_iter = bytes.into_iter(); - read_instr(decoder, bytes_iter, instr) -} - -#[inline] -fn read_num>(bytes: &mut T, width: u8) -> Result { - let mut result = 0u64; - let mut idx = 0; - loop { - if idx == width { - return Ok(result); - } - let byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - result |= (byte as u64) << (idx * 8); - idx += 1; - } -} - -#[inline] -fn read_imm_ivq>(bytes: &mut T, width: u8, length: &mut u8) -> Result { - match width { - 2 => { - *length += 2; - Ok(read_num(bytes, 2)? as u16 as u64) - }, - 4 => { - *length += 4; - Ok(read_num(bytes, 4)? as u32 as u64) - }, - 8 => { - *length += 8; - Ok(read_num(bytes, 8)? as u64) - }, - _ => { - unsafe { unreachable_unchecked(); } - } - } -} - -#[inline] -fn read_imm_signed>(bytes: &mut T, num_width: u8, length: &mut u8) -> Result { - if num_width == 1 { - *length += 1; - Ok(read_num(bytes, 1)? as i8 as i64) - } else if num_width == 2 { - *length += 2; - Ok(read_num(bytes, 2)? as i16 as i64) - } else { - *length += 4; - // this is for 4 and 8, the only values for num_width may be 1, 2, 4, and 8. - Ok(read_num(bytes, 4)? as i32 as i64) - } -} - -#[inline] -fn read_imm_unsigned>(bytes: &mut T, width: u8, length: &mut u8) -> Result { - read_num(bytes, width).map(|res| { - *length += width; - res - }) -} - -#[inline] -fn imm_width_from_prefixes_64(interpretation: SizeCode, prefixes: Prefixes) -> u8 { - match interpretation { - SizeCode::b => 1, - SizeCode::vd => { - if prefixes.rex().w() || !prefixes.operand_size() { 4 } else { 2 } - }, - SizeCode::vq => { - // TODO: this should be address_size - // but i'm not sure if that breaks other instructions rn - if prefixes.operand_size() { - 2 - } else { - 8 // TODO: this 8 should be arch width. - } - }, - SizeCode::vqp => { - if prefixes.rex().w() { - 8 - } else if prefixes.operand_size() { - 2 - } else { - 4 - } - }, - } -} - -#[inline] -fn read_modrm>(bytes_iter: &mut T, length: &mut u8) -> Result { - bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b }) -} +mod real_mode; +pub use real_mode::Arch as x86_16; diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs new file mode 100644 index 0000000..ff51613 --- /dev/null +++ b/src/long_mode/display.rs @@ -0,0 +1,2068 @@ +extern crate yaxpeax_arch; + +use core::fmt; + +use yaxpeax_arch::{Colorize, ShowContextual, NoColors, YaxColors}; +use yaxpeax_arch::display::*; + +use crate::long_mode::{RegSpec, RegisterBank, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixRex, OperandSpec, DecodeError}; + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + DecodeError::ExhaustedInput => { write!(f, "exhausted input") }, + DecodeError::InvalidOpcode => { write!(f, "invalid opcode") }, + DecodeError::InvalidOperand => { write!(f, "invalid operand") }, + DecodeError::InvalidPrefixes => { write!(f, "invalid prefixes") }, + DecodeError::TooLong => { write!(f, "too long") }, + DecodeError::IncompleteDecoder => { write!(f, "the decoder is incomplete") }, + } + } +} + +impl fmt::Display for InstDecoder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self == &InstDecoder::default() { + return write!(f, ""); + } else if self == &InstDecoder::minimal() { + return write!(f, ""); + } + if self.sse3() { write!(f, "sse3 ")? } + if self.ssse3() { write!(f, "ssse3 ")? } + if self.monitor() { write!(f, "monitor ")? } + if self.vmx() { write!(f, "vmx ")? } + if self.fma3() { write!(f, "fma3 ")? } + if self.cmpxchg16b() { write!(f, "cmpxchg16b ")? } + if self.sse4_1() { write!(f, "sse4_1 ")? } + if self.sse4_2() { write!(f, "sse4_2 ")? } + if self.movbe() { write!(f, "movbe ")? } + if self.popcnt() { write!(f, "popcnt ")? } + if self.aesni() { write!(f, "aesni ")? } + if self.xsave() { write!(f, "xsave ")? } + if self.rdrand() { write!(f, "rdrand ")? } + if self.sgx() { write!(f, "sgx ")? } + if self.bmi1() { write!(f, "bmi1 ")? } + if self.avx2() { write!(f, "avx2 ")? } + if self.bmi2() { write!(f, "bmi2 ")? } + if self.invpcid() { write!(f, "invpcid ")? } + if self.mpx() { write!(f, "mpx ")? } + if self.avx512_f() { write!(f, "avx512_f ")? } + if self.avx512_dq() { write!(f, "avx512_dq ")? } + if self.rdseed() { write!(f, "rdseed ")? } + if self.adx() { write!(f, "adx ")? } + if self.avx512_fma() { write!(f, "avx512_fma ")? } + if self.pcommit() { write!(f, "pcommit ")? } + if self.clflushopt() { write!(f, "clflushopt ")? } + if self.clwb() { write!(f, "clwb ")? } + if self.avx512_pf() { write!(f, "avx512_pf ")? } + if self.avx512_er() { write!(f, "avx512_er ")? } + if self.avx512_cd() { write!(f, "avx512_cd ")? } + if self.sha() { write!(f, "sha ")? } + if self.avx512_bw() { write!(f, "avx512_bw ")? } + if self.avx512_vl() { write!(f, "avx512_vl ")? } + if self.prefetchwt1() { write!(f, "prefetchwt1 ")? } + if self.avx512_vbmi() { write!(f, "avx512_vbmi ")? } + if self.avx512_vbmi2() { write!(f, "avx512_vbmi2 ")? } + if self.gfni() { write!(f, "gfni ")? } + if self.vaes() { write!(f, "vaes ")? } + if self.pclmulqdq() { write!(f, "pclmulqdq ")? } + if self.avx_vnni() { write!(f, "avx_vnni ")? } + if self.avx512_bitalg() { write!(f, "avx512_bitalg ")? } + if self.avx512_vpopcntdq() { write!(f, "avx512_vpopcntdq ")? } + if self.avx512_4vnniw() { write!(f, "avx512_4vnniw ")? } + if self.avx512_4fmaps() { write!(f, "avx512_4fmaps ")? } + if self.cx8() { write!(f, "cx8 ")? } + if self.syscall() { write!(f, "syscall ")? } + if self.rdtscp() { write!(f, "rdtscp ")? } + if self.abm() { write!(f, "abm ")? } + if self.sse4a() { write!(f, "sse4a ")? } + if self._3dnowprefetch() { write!(f, "_3dnowprefetch ")? } + if self.xop() { write!(f, "xop ")? } + if self.skinit() { write!(f, "skinit ")? } + if self.tbm() { write!(f, "tbm ")? } + if self.intel_quirks() { write!(f, "intel_quirks ")? } + if self.amd_quirks() { write!(f, "amd_quirks ")? } + if self.avx() { write!(f, "avx ")? } + Ok(()) + } +} + +impl fmt::Display for PrefixRex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.present() { + write!(f, "rex:{}{}{}{}", + if self.w() { "w" } else { "-" }, + if self.r() { "r" } else { "-" }, + if self.x() { "x" } else { "-" }, + if self.b() { "b" } else { "-" }, + ) + } else { + write!(f, "rex:none") + } + } +} + +impl fmt::Display for Segment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Segment::CS => write!(f, "cs"), + Segment::DS => write!(f, "ds"), + Segment::ES => write!(f, "es"), + Segment::FS => write!(f, "fs"), + Segment::GS => write!(f, "gs"), + Segment::SS => write!(f, "ss"), + } + } +} + +impl fmt::Display for RegSpec { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let name = match self.bank { + RegisterBank::Q => { + ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"][self.num as usize] + }, + RegisterBank::D => { + ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"][self.num as usize] + }, + RegisterBank::W => { + ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"][self.num as usize] + }, + RegisterBank::B => { + ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"][self.num as usize] + }, + RegisterBank::rB => { + ["al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"][self.num as usize] + }, + RegisterBank::EIP => { "eip" }, + RegisterBank::RIP => { "rip" }, + RegisterBank::EFlags => { "eflags" }, + RegisterBank::RFlags => { "rflags" }, + RegisterBank::CR => { + ["cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15"][self.num as usize] + } + RegisterBank::DR => { + ["dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"][self.num as usize] + } + RegisterBank::X => { + ["xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"][self.num as usize] + }, + RegisterBank::Y => { + ["ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"][self.num as usize] + }, + RegisterBank::Z => { + ["zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31"][self.num as usize] + }, + RegisterBank::ST => { + ["st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"][self.num as usize] + }, + RegisterBank::MM => { + ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"][self.num as usize] + } + RegisterBank::S => { + ["cs", "ds", "es", "fs", "gs", "ss"][self.num as usize] + } + RegisterBank::K => { + ["k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"][self.num as usize] + } + }; + write!(f, "{}", name) + } +} + +impl fmt::Display for Operand { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + self.colorize(&NoColors, fmt) + } +} + +impl > Colorize for Operand { + fn colorize(&self, colors: &Y, f: &mut T) -> fmt::Result { + match self { + &Operand::ImmediateU8(imm) => { + write!(f, "{}", colors.number(u8_hex(imm))) + } + &Operand::ImmediateI8(imm) => { + write!(f, "{}", + colors.number(signed_i8_hex(imm))) + }, + &Operand::ImmediateU16(imm) => { + write!(f, "{}", colors.number(u16_hex(imm))) + } + &Operand::ImmediateI16(imm) => { + write!(f, "{}", + colors.number(signed_i16_hex(imm))) + }, + &Operand::ImmediateU32(imm) => { + write!(f, "{}", colors.number(u32_hex(imm))) + } + &Operand::ImmediateI32(imm) => { + write!(f, "{}", + colors.number(signed_i32_hex(imm))) + }, + &Operand::ImmediateU64(imm) => { + write!(f, "{}", colors.number(u64_hex(imm))) + } + &Operand::ImmediateI64(imm) => { + write!(f, "{}", + colors.number(signed_i64_hex(imm))) + }, + &Operand::Register(ref spec) => { + write!(f, "{}", colors.register(spec)) + } + &Operand::DisplacementU32(imm) => { + write!(f, "[{}]", colors.address(u32_hex(imm))) + } + &Operand::DisplacementU64(imm) => { + write!(f, "[{}]", colors.address(u64_hex(imm))) + } + &Operand::RegDisp(ref spec, disp) => { + write!(f, "[{} ", colors.register(spec))?; + format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; + write!(f, "]") + }, + &Operand::RegDeref(ref spec) => { + write!(f, "[{}]", colors.register(spec)) + }, + &Operand::RegScale(ref spec, scale) => { + write!(f, "[{} * {}]", + colors.register(spec), + colors.number(scale) + ) + }, + &Operand::RegScaleDisp(ref spec, scale, disp) => { + write!(f, "[{} * {} ", + colors.register(spec), + colors.number(scale), + )?; + format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; + write!(f, "]") + }, + &Operand::RegIndexBase(ref base, ref index) => { + write!(f, "[{} + {}]", + colors.register(base), + colors.register(index) + ) + } + &Operand::RegIndexBaseDisp(ref base, ref index, disp) => { + write!(f, "[{} + {} ", + colors.register(base), + colors.register(index), + )?; + format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; + write!(f, "]") + }, + &Operand::RegIndexBaseScale(ref base, ref index, scale) => { + write!(f, "[{} + {} * {}]", + colors.register(base), + colors.register(index), + colors.number(scale) + ) + } + &Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => { + write!(f, "[{} + {} * {} ", + colors.register(base), + colors.register(index), + colors.number(scale), + )?; + format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; + write!(f, "]") + }, + &Operand::Nothing => { Ok(()) }, + } + } +} + +impl fmt::Display for Opcode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &Opcode::POPCNT => write!(f, "popcnt"), + &Opcode::MOVDQU => write!(f, "movdqu"), + &Opcode::MOVDQA => write!(f, "movdqa"), + &Opcode::MOVQ => write!(f, "movq"), + &Opcode::CMPSS => write!(f, "cmpss"), + &Opcode::CMPSD => write!(f, "cmpsd"), + &Opcode::UNPCKLPS => write!(f, "unpcklps"), + &Opcode::UNPCKHPS => write!(f, "unpckhps"), + &Opcode::MOVUPS => write!(f, "movups"), + &Opcode::MOVQ2DQ => write!(f, "movq2dq"), + &Opcode::MOVDQ2Q => write!(f, "movdq2q"), + &Opcode::RSQRTSS => write!(f, "rsqrtss"), + &Opcode::MOVSHDUP => write!(f, "movshdup"), + &Opcode::CVTTPS2DQ => write!(f, "cvttps2dq"), + &Opcode::CVTPD2DQ => write!(f, "cvtpd2dq"), + &Opcode::RCPSS => write!(f, "rcpss"), + &Opcode::CVTDQ2PD => write!(f, "cvtdq2pd"), + &Opcode::PSHUFHW => write!(f, "pshufhw"), + &Opcode::PSHUFLW => write!(f, "pshuflw"), + &Opcode::XADD => write!(f, "xadd"), + &Opcode::BT => write!(f, "bt"), + &Opcode::BTS => write!(f, "bts"), + &Opcode::BTR => write!(f, "btr"), + &Opcode::BTC => write!(f, "btc"), + &Opcode::BSF => write!(f, "bsf"), + &Opcode::BSR => write!(f, "bsr"), + &Opcode::TZCNT => write!(f, "tzcnt"), + &Opcode::MOVSS => write!(f, "movss"), + &Opcode::SQRTSS => write!(f, "sqrtss"), + &Opcode::ADDSS => write!(f, "addss"), + &Opcode::SUBSS => write!(f, "subss"), + &Opcode::MULSS => write!(f, "mulss"), + &Opcode::DIVSS => write!(f, "divss"), + &Opcode::MINSS => write!(f, "minss"), + &Opcode::MAXSS => write!(f, "maxss"), + &Opcode::MOVSD => write!(f, "movsd"), + &Opcode::SQRTSD => write!(f, "sqrtsd"), + &Opcode::ADDSD => write!(f, "addsd"), + &Opcode::SUBSD => write!(f, "subsd"), + &Opcode::MULSD => write!(f, "mulsd"), + &Opcode::DIVSD => write!(f, "divsd"), + &Opcode::MINSD => write!(f, "minsd"), + &Opcode::MAXSD => write!(f, "maxsd"), + &Opcode::MOVDDUP => write!(f, "movddup"), + &Opcode::MOVSLDUP => write!(f, "movsldup"), + &Opcode::HADDPS => write!(f, "haddps"), + &Opcode::HSUBPS => write!(f, "hsubps"), + &Opcode::ADDSUBPS => write!(f, "addsubps"), + &Opcode::CVTSI2SS => write!(f, "cvtsi2ss"), + &Opcode::CVTSI2SD => write!(f, "cvtsi2sd"), + &Opcode::CVTTSD2SI => write!(f, "cvttsd2si"), + &Opcode::CVTSD2SI => write!(f, "cvtsd2si"), + &Opcode::CVTSD2SS => write!(f, "cvtsd2ss"), + &Opcode::CVTTSS2SI => write!(f, "cvttss2si"), + &Opcode::CVTSS2SI => write!(f, "cvtss2si"), + &Opcode::CVTSS2SD => write!(f, "cvtss2sd"), + &Opcode::LDDQU => write!(f, "lddqu"), + &Opcode::STI => write!(f, "sti"), + &Opcode::STD => write!(f, "std"), + &Opcode::STC => write!(f, "stc"), + &Opcode::CLI => write!(f, "cli"), + &Opcode::CLD => write!(f, "cld"), + &Opcode::CLC => write!(f, "clc"), + &Opcode::SLDT => write!(f, "sldt"), + &Opcode::STR => write!(f, "str"), + &Opcode::LLDT => write!(f, "lldt"), + &Opcode::LTR => write!(f, "ltr"), + &Opcode::VERR => write!(f, "verr"), + &Opcode::VERW => write!(f, "verw"), + &Opcode::JMPE => write!(f, "jmpe"), + &Opcode::WRMSR => write!(f, "wrmsr"), + &Opcode::RDMSR => write!(f, "rdmsr"), + &Opcode::RDTSC => write!(f, "rdtsc"), + &Opcode::RDPMC => write!(f, "rdpmc"), + &Opcode::FXSAVE => write!(f, "fxsave"), + &Opcode::FXRSTOR => write!(f, "fxrstor"), + &Opcode::LDMXCSR => write!(f, "ldmxcsr"), + &Opcode::STMXCSR => write!(f, "stmxcsr"), + &Opcode::XSAVE => write!(f, "xsave"), + &Opcode::XRSTOR => write!(f, "xrstor"), + &Opcode::XSAVEOPT => write!(f, "xsaveopt"), + &Opcode::LFENCE => write!(f, "lfence"), + &Opcode::MFENCE => write!(f, "mfence"), + &Opcode::SFENCE => write!(f, "sfence"), + &Opcode::CLFLUSH => write!(f, "clflush"), + &Opcode::SGDT => write!(f, "sgdt"), + &Opcode::SIDT => write!(f, "sidt"), + &Opcode::LGDT => write!(f, "lgdt"), + &Opcode::LIDT => write!(f, "lidt"), + &Opcode::SMSW => write!(f, "smsw"), + &Opcode::LMSW => write!(f, "lmsw"), + &Opcode::SWAPGS => write!(f, "swapgs"), + &Opcode::RDTSCP => write!(f, "rdtscp"), + &Opcode::INVLPG => write!(f, "invlpg"), + &Opcode::CPUID => write!(f, "cpuid"), + &Opcode::UD2 => write!(f, "ud2"), + &Opcode::WBINVD => write!(f, "wbinvd"), + &Opcode::INVD => write!(f, "invd"), + &Opcode::SYSRET => write!(f, "sysret"), + &Opcode::CLTS => write!(f, "clts"), + &Opcode::SYSCALL => write!(f, "syscall"), + &Opcode::LSL => write!(f, "lsl"), + &Opcode::LAR => write!(f, "lar"), + &Opcode::INC => write!(f, "inc"), + &Opcode::DEC => write!(f, "dec"), + &Opcode::HLT => write!(f, "hlt"), + &Opcode::SBB => write!(f, "sbb"), + &Opcode::AND => write!(f, "and"), + &Opcode::XOR => write!(f, "xor"), + &Opcode::OR => write!(f, "or"), + &Opcode::PUSH => write!(f, "push"), + &Opcode::POP => write!(f, "pop"), + &Opcode::LEA => write!(f, "lea"), + &Opcode::NOP => write!(f, "nop"), + &Opcode::PREFETCHNTA => write!(f, "prefetchnta"), + &Opcode::PREFETCH0 => write!(f, "prefetch0"), + &Opcode::PREFETCH1 => write!(f, "prefetch1"), + &Opcode::PREFETCH2 => write!(f, "prefetch2"), + &Opcode::XCHG => write!(f, "xchg"), + &Opcode::POPF => write!(f, "popf"), + &Opcode::ADD => write!(f, "add"), + &Opcode::ADC => write!(f, "adc"), + &Opcode::SUB => write!(f, "sub"), + &Opcode::INT => write!(f, "int"), + &Opcode::INTO => write!(f, "into"), + &Opcode::IRET => write!(f, "iret"), + &Opcode::RETF => write!(f, "retf"), + &Opcode::ENTER => write!(f, "enter"), + &Opcode::LEAVE => write!(f, "leave"), + &Opcode::MOV => write!(f, "mov"), + &Opcode::RETURN => write!(f, "ret"), + &Opcode::PUSHF => write!(f, "pushf"), + &Opcode::WAIT => write!(f, "wait"), + &Opcode::LODS => write!(f, "lods"), + &Opcode::STOS => write!(f, "stos"), + &Opcode::LAHF => write!(f, "lahf"), + &Opcode::SAHF => write!(f, "sahf"), + &Opcode::CMPS => write!(f, "cmps"), + &Opcode::SCAS => write!(f, "scas"), + &Opcode::MOVS => write!(f, "movs"), + &Opcode::TEST => write!(f, "test"), + &Opcode::CMP => write!(f, "cmp"), + &Opcode::INS => write!(f, "ins"), + &Opcode::OUTS => write!(f, "outs"), + &Opcode::IMUL => write!(f, "imul"), + &Opcode::JO => write!(f, "jo"), + &Opcode::JNO => write!(f, "jno"), + &Opcode::JB => write!(f, "jb"), + &Opcode::JNB => write!(f, "jnb"), + &Opcode::JZ => write!(f, "jz"), + &Opcode::JNZ => write!(f, "jnz"), + &Opcode::JA => write!(f, "ja"), + &Opcode::JNA => write!(f, "jna"), + &Opcode::JS => write!(f, "js"), + &Opcode::JNS => write!(f, "jns"), + &Opcode::JP => write!(f, "jp"), + &Opcode::JNP => write!(f, "jnp"), + &Opcode::JL => write!(f, "jl"), + &Opcode::JGE => write!(f, "jge"), + &Opcode::JLE => write!(f, "jle"), + &Opcode::JG => write!(f, "jg"), + &Opcode::CALL => write!(f, "call"), + &Opcode::JMP => write!(f, "jmp"), + &Opcode::CALLF => write!(f, "callf"), + &Opcode::JMPF => write!(f, "jmpf"), + &Opcode::SAR => write!(f, "sar"), + &Opcode::SAL => write!(f, "sal"), + &Opcode::SHR => write!(f, "shr"), + &Opcode::SHRD => write!(f, "shrd"), + &Opcode::SHL => write!(f, "shl"), + &Opcode::RCR => write!(f, "rcr"), + &Opcode::RCL => write!(f, "rcl"), + &Opcode::ROR => write!(f, "ror"), + &Opcode::ROL => write!(f, "rol"), + &Opcode::CMOVA => write!(f, "cmova"), + &Opcode::CMOVB => write!(f, "cmovb"), + &Opcode::CMOVG => write!(f, "cmovg"), + &Opcode::CMOVGE => write!(f, "cmovge"), + &Opcode::CMOVL => write!(f, "cmovl"), + &Opcode::CMOVLE => write!(f, "cmovle"), + &Opcode::CMOVNA => write!(f, "cmovna"), + &Opcode::CMOVNB => write!(f, "cmovnb"), + &Opcode::CMOVNO => write!(f, "cmovno"), + &Opcode::CMOVNP => write!(f, "cmovnp"), + &Opcode::CMOVNS => write!(f, "cmovns"), + &Opcode::CMOVNZ => write!(f, "cmovnz"), + &Opcode::CMOVO => write!(f, "cmovo"), + &Opcode::CMOVP => write!(f, "cmovp"), + &Opcode::CMOVS => write!(f, "cmovs"), + &Opcode::CMOVZ => write!(f, "cmovz"), + &Opcode::NEG => write!(f, "neg"), + &Opcode::NOT => write!(f, "not"), + &Opcode::MUL => write!(f, "mul"), + &Opcode::DIV => write!(f, "div"), + &Opcode::IDIV => write!(f, "idiv"), + &Opcode::CMPXCHG => write!(f, "cmpxchg"), + &Opcode::MOVSX_b => write!(f, "movsx"), + &Opcode::MOVSX_w => write!(f, "movsx"), + &Opcode::MOVZX_b => write!(f, "movzx"), + &Opcode::MOVZX_w => write!(f, "movzx"), + &Opcode::MOVSXD => write!(f, "movsxd"), + &Opcode::MOVSX => write!(f, "movsx"), + &Opcode::SETO => write!(f, "seto"), + &Opcode::SETNO => write!(f, "setno"), + &Opcode::SETB => write!(f, "setb"), + &Opcode::SETAE => write!(f, "setae"), + &Opcode::SETZ => write!(f, "setz"), + &Opcode::SETNZ => write!(f, "setnz"), + &Opcode::SETBE => write!(f, "setbe"), + &Opcode::SETA => write!(f, "seta"), + &Opcode::SETS => write!(f, "sets"), + &Opcode::SETNS => write!(f, "setns"), + &Opcode::SETP => write!(f, "setp"), + &Opcode::SETNP => write!(f, "setnp"), + &Opcode::SETL => write!(f, "setl"), + &Opcode::SETGE => write!(f, "setge"), + &Opcode::SETLE => write!(f, "setle"), + &Opcode::SETG => write!(f, "setg"), + &Opcode::ADDPS => write!(f, "addps"), + &Opcode::ANDNPS => write!(f, "andnps"), + &Opcode::ANDPS => write!(f, "andps"), + &Opcode::BSWAP => write!(f, "bswap"), + &Opcode::CMPPS => write!(f, "cmpps"), + &Opcode::COMISS => write!(f, "comiss"), + &Opcode::CVTDQ2PS => write!(f, "cvtdq2ps"), + &Opcode::CVTPI2PS => write!(f, "cvtpi2ps"), + &Opcode::CVTPI2PD => write!(f, "cvtpi2pd"), + &Opcode::CVTPS2PD => write!(f, "cvtps2pd"), + &Opcode::CVTPS2PI => write!(f, "cvtps2pi"), + &Opcode::CVTTPS2PI => write!(f, "cvttps2pi"), + &Opcode::DIVPS => write!(f, "divps"), + &Opcode::EMMS => write!(f, "emms"), + &Opcode::GETSEC => write!(f, "getsec"), + &Opcode::LFS => write!(f, "lfs"), + &Opcode::LGS => write!(f, "lgs"), + &Opcode::LSS => write!(f, "lss"), + &Opcode::MASKMOVQ => write!(f, "maskmovq"), + &Opcode::MAXPS => write!(f, "maxps"), + &Opcode::MINPS => write!(f, "minps"), + &Opcode::MOVAPS => write!(f, "movaps"), + &Opcode::MOVAPD => write!(f, "movapd"), + &Opcode::MOVD => write!(f, "movd"), + &Opcode::MOVLPS => write!(f, "movlps"), + &Opcode::MOVLHPS => write!(f, "movlhps"), + &Opcode::MOVHPS => write!(f, "movhps"), + &Opcode::MOVHLPS => write!(f, "movhlps"), + &Opcode::MOVUPD => write!(f, "movupd"), + &Opcode::MOVMSKPS => write!(f, "movmskps"), + &Opcode::MOVNTI => write!(f, "movnti"), + &Opcode::MOVNTPS => write!(f, "movntps"), + &Opcode::MOVNTQ => write!(f, "movntq"), + &Opcode::MULPS => write!(f, "mulps"), + &Opcode::ORPS => write!(f, "orps"), + &Opcode::PACKSSDW => write!(f, "packssdw"), + &Opcode::PACKSSWB => write!(f, "packsswb"), + &Opcode::PACKUSWB => write!(f, "packuswb"), + &Opcode::PADDB => write!(f, "paddb"), + &Opcode::PADDD => write!(f, "paddd"), + &Opcode::PADDQ => write!(f, "paddq"), + &Opcode::PADDSB => write!(f, "paddsb"), + &Opcode::PADDSW => write!(f, "paddsw"), + &Opcode::PADDUSB => write!(f, "paddusb"), + &Opcode::PADDUSW => write!(f, "paddusw"), + &Opcode::PADDW => write!(f, "paddw"), + &Opcode::PAND => write!(f, "pand"), + &Opcode::PANDN => write!(f, "pandn"), + &Opcode::PAVGB => write!(f, "pavgb"), + &Opcode::PAVGW => write!(f, "pavgw"), + &Opcode::PCMPEQB => write!(f, "pcmpeqb"), + &Opcode::PCMPEQD => write!(f, "pcmpeqd"), + &Opcode::PCMPEQW => write!(f, "pcmpeqw"), + &Opcode::PCMPGTB => write!(f, "pcmpgtb"), + &Opcode::PCMPGTD => write!(f, "pcmpgtd"), + &Opcode::PCMPGTW => write!(f, "pcmpgtw"), + &Opcode::PEXTRW => write!(f, "pextrw"), + &Opcode::PINSRW => write!(f, "pinsrw"), + &Opcode::PMADDWD => write!(f, "pmaddwd"), + &Opcode::PMAXSW => write!(f, "pmaxsw"), + &Opcode::PMAXUB => write!(f, "pmaxub"), + &Opcode::PMINSW => write!(f, "pminsw"), + &Opcode::PMINUB => write!(f, "pminub"), + &Opcode::PMOVMSKB => write!(f, "pmovmskb"), + &Opcode::PMULHUW => write!(f, "pmulhuw"), + &Opcode::PMULHW => write!(f, "pmulhw"), + &Opcode::PMULLW => write!(f, "pmullw"), + &Opcode::PMULUDQ => write!(f, "pmuludq"), + &Opcode::POR => write!(f, "por"), + &Opcode::PSADBW => write!(f, "psadbw"), + &Opcode::PSHUFW => write!(f, "pshufw"), + &Opcode::PSHUFD => write!(f, "pshufd"), + &Opcode::PSLLD => write!(f, "pslld"), + &Opcode::PSLLDQ => write!(f, "pslldq"), + &Opcode::PSLLQ => write!(f, "psllq"), + &Opcode::PSLLW => write!(f, "psllw"), + &Opcode::PSRAD => write!(f, "psrad"), + &Opcode::PSRAW => write!(f, "psraw"), + &Opcode::PSRLD => write!(f, "psrld"), + &Opcode::PSRLDQ => write!(f, "psrldq"), + &Opcode::PSRLQ => write!(f, "psrlq"), + &Opcode::PSRLW => write!(f, "psrlw"), + &Opcode::PSUBB => write!(f, "psubb"), + &Opcode::PSUBD => write!(f, "psubd"), + &Opcode::PSUBQ => write!(f, "psubq"), + &Opcode::PSUBSB => write!(f, "psubsb"), + &Opcode::PSUBSW => write!(f, "psubsw"), + &Opcode::PSUBUSB => write!(f, "psubusb"), + &Opcode::PSUBUSW => write!(f, "psubusw"), + &Opcode::PSUBW => write!(f, "psubw"), + &Opcode::PUNPCKHBW => write!(f, "punpckhbw"), + &Opcode::PUNPCKHDQ => write!(f, "punpckhdq"), + &Opcode::PUNPCKHWD => write!(f, "punpckhwd"), + &Opcode::PUNPCKLBW => write!(f, "punpcklbw"), + &Opcode::PUNPCKLDQ => write!(f, "punpckldq"), + &Opcode::PUNPCKLWD => write!(f, "punpcklwd"), + &Opcode::PUNPCKLQDQ => write!(f, "punpcklqdq"), + &Opcode::PUNPCKHQDQ => write!(f, "punpckhqdq"), + &Opcode::PXOR => write!(f, "pxor"), + &Opcode::RCPPS => write!(f, "rcpps"), + &Opcode::RSM => write!(f, "rsm"), + &Opcode::RSQRTPS => write!(f, "rsqrtps"), + &Opcode::SHLD => write!(f, "shld"), + &Opcode::SHUFPS => write!(f, "shufps"), + &Opcode::SLHD => write!(f, "slhd"), + &Opcode::SQRTPS => write!(f, "sqrtps"), + &Opcode::SUBPS => write!(f, "subps"), + &Opcode::SYSENTER => write!(f, "sysenter"), + &Opcode::SYSEXIT => write!(f, "sysexit"), + &Opcode::UCOMISS => write!(f, "ucomiss"), + &Opcode::UD2E => write!(f, "ud2e"), + &Opcode::VMREAD => write!(f, "vmread"), + &Opcode::VMWRITE => write!(f, "vmwrite"), + &Opcode::XORPS => write!(f, "xorps"), + &Opcode::CBW => write!(f, "cbw"), + &Opcode::CWDE => write!(f, "cwde"), + &Opcode::CDQE => write!(f, "cdqe"), + &Opcode::CBD => write!(f, "cbd"), + &Opcode::CDQ => write!(f, "cdq"), + &Opcode::CQO => write!(f, "cqo"), + &Opcode::ANDN => write!(f, "andn"), + &Opcode::BEXTR => write!(f, "bextr"), + &Opcode::BLSI => write!(f, "blsi"), + &Opcode::BLSMSK => write!(f, "blsmsk"), + &Opcode::BLSR => write!(f, "blsr"), + &Opcode::VMCALL => write!(f, "vmcall"), + &Opcode::VMLAUNCH => write!(f, "vmlaunch"), + &Opcode::VMRESUME => write!(f, "vmresume"), + &Opcode::VMXOFF => write!(f, "vmxoff"), + &Opcode::MONITOR => write!(f, "monitor"), + &Opcode::MWAIT => write!(f, "mwait"), + &Opcode::CLAC => write!(f, "clac"), + &Opcode::STAC => write!(f, "stac"), + &Opcode::ENCLS => write!(f, "encls"), + &Opcode::ENCLV => write!(f, "enclv"), + &Opcode::XGETBV => write!(f, "xgetbv"), + &Opcode::XSETBV => write!(f, "xsetbv"), + &Opcode::VMFUNC => write!(f, "vmfunc"), + &Opcode::XEND => write!(f, "xend"), + &Opcode::XTEST => write!(f, "xtest"), + &Opcode::ENCLU => write!(f, "enclu"), + &Opcode::RDPKRU => write!(f, "rdpkru"), + &Opcode::WRPKRU => write!(f, "wrpkru"), + &Opcode::VADDPD => write!(f, "vaddpd"), + &Opcode::VADDPS => write!(f, "vaddps"), + &Opcode::VADDSUBPD => write!(f, "vaddsubpd"), + &Opcode::VAESDEC => write!(f, "vaesdec"), + &Opcode::VAESDECLAST => write!(f, "vaesdeclast"), + &Opcode::VAESENC => write!(f, "vaesenc"), + &Opcode::VAESENCLAST => write!(f, "vaesenclast"), + &Opcode::VAESIMC => write!(f, "vaesimc"), + &Opcode::VAESKEYGENASSIST => write!(f, "vaeskeygenassist"), + &Opcode::VBLENDPD => write!(f, "vblendpd"), + &Opcode::VBLENDPS => write!(f, "vblendps"), + &Opcode::VBLENDVPD => write!(f, "vblendvpd"), + &Opcode::VBLENDVPS => write!(f, "vblendvps"), + &Opcode::VBROADCASTF128 => write!(f, "vbroadcastf128"), + &Opcode::VBROADCASTI128 => write!(f, "vbroadcasti128"), + &Opcode::VBROADCASTSD => write!(f, "vbroadcastsd"), + &Opcode::VBROADCASTSS => write!(f, "vbroadcastss"), + &Opcode::VCMPPD => write!(f, "vcmppd"), + &Opcode::VCMPPS => write!(f, "vcmpps"), + &Opcode::VCVTDQ2PD => write!(f, "vcvtdq2pd"), + &Opcode::VCVTDQ2PS => write!(f, "vcvtdq2ps"), + &Opcode::VCVTPD2PS => write!(f, "vcvtpd2ps"), + &Opcode::VCVTPH2PS => write!(f, "vcvtph2ps"), + &Opcode::VCVTPS2DQ => write!(f, "vcvtps2dq"), + &Opcode::VCVTPS2PD => write!(f, "vcvtps2pd"), + &Opcode::VCVTPS2PH => write!(f, "vcvtps2ph"), + &Opcode::VCVTTPD2DQ => write!(f, "vcvttpd2dq"), + &Opcode::VCVTTPS2DQ => write!(f, "vcvttps2dq"), + &Opcode::VDIVPD => write!(f, "vdivpd"), + &Opcode::VDIVPS => write!(f, "vdivps"), + &Opcode::VDPPD => write!(f, "vdppd"), + &Opcode::VDPPS => write!(f, "vdpps"), + &Opcode::VEXTRACTF128 => write!(f, "vextractf128"), + &Opcode::VEXTRACTI128 => write!(f, "vextracti128"), + &Opcode::VEXTRACTPS => write!(f, "vextractps"), + &Opcode::VFMADD132PD => write!(f, "vfmadd132pd"), + &Opcode::VFMADD132PS => write!(f, "vfmadd132ps"), + &Opcode::VFMADD213PD => write!(f, "vfmadd213pd"), + &Opcode::VFMADD213PS => write!(f, "vfmadd213ps"), + &Opcode::VFMADD231PD => write!(f, "vfmadd231pd"), + &Opcode::VFMADD231PS => write!(f, "vfmadd231ps"), + &Opcode::VFMADDSUB132PD => write!(f, "vfmaddsub132pd"), + &Opcode::VFMADDSUB132PS => write!(f, "vfmaddsub132ps"), + &Opcode::VFMADDSUB213PD => write!(f, "vfmaddsub213pd"), + &Opcode::VFMADDSUB213PS => write!(f, "vfmaddsub213ps"), + &Opcode::VFMADDSUB231PD => write!(f, "vfmaddsub231pd"), + &Opcode::VFMADDSUB231PS => write!(f, "vfmaddsub231ps"), + &Opcode::VFMSUB132PD => write!(f, "vfmsub132pd"), + &Opcode::VFMSUB132PS => write!(f, "vfmsub132ps"), + &Opcode::VFMSUB213PD => write!(f, "vfmsub213pd"), + &Opcode::VFMSUB213PS => write!(f, "vfmsub213ps"), + &Opcode::VFMSUB231PD => write!(f, "vfmsub231pd"), + &Opcode::VFMSUB231PS => write!(f, "vfmsub231ps"), + &Opcode::VFMSUBADD132PD => write!(f, "vfmsubadd132pd"), + &Opcode::VFMSUBADD132PS => write!(f, "vfmsubadd132ps"), + &Opcode::VFMSUBADD213PD => write!(f, "vfmsubadd213pd"), + &Opcode::VFMSUBADD213PS => write!(f, "vfmsubadd213ps"), + &Opcode::VFMSUBADD231PD => write!(f, "vfmsubadd231pd"), + &Opcode::VFMSUBADD231PS => write!(f, "vfmsubadd231ps"), + &Opcode::VFNMADD132PD => write!(f, "vfnmadd132pd"), + &Opcode::VFNMADD132PS => write!(f, "vfnmadd132ps"), + &Opcode::VFNMADD213PD => write!(f, "vfnmadd213pd"), + &Opcode::VFNMADD213PS => write!(f, "vfnmadd213ps"), + &Opcode::VFNMADD231PD => write!(f, "vfnmadd231pd"), + &Opcode::VFNMADD231PS => write!(f, "vfnmadd231ps"), + &Opcode::VFNMSUB132PD => write!(f, "vfnmsub132pd"), + &Opcode::VFNMSUB132PS => write!(f, "vfnmsub132ps"), + &Opcode::VFNMSUB213PD => write!(f, "vfnmsub213pd"), + &Opcode::VFNMSUB213PS => write!(f, "vfnmsub213ps"), + &Opcode::VFNMSUB231PD => write!(f, "vfnmsub231pd"), + &Opcode::VFNMSUB231PS => write!(f, "vfnmsub231ps"), + &Opcode::VGATHERDPD => write!(f, "vgatherdpd"), + &Opcode::VGATHERDPS => write!(f, "vgatherdps"), + &Opcode::VGATHERQPD => write!(f, "vgatherqpd"), + &Opcode::VGATHERQPS => write!(f, "vgatherqps"), + &Opcode::VHADDPD => write!(f, "vhaddpd"), + &Opcode::VHSUBPD => write!(f, "vhsubpd"), + &Opcode::VINSERTF128 => write!(f, "vinsertf128"), + &Opcode::VINSERTI128 => write!(f, "vinserti128"), + &Opcode::VINSERTPS => write!(f, "vinsertps"), + &Opcode::VMASKMOVDQU => write!(f, "vmaskmovdqu"), + &Opcode::VMASKMOVPD => write!(f, "vmaskmovpd"), + &Opcode::VMASKMOVPS => write!(f, "vmaskmovps"), + &Opcode::VMAXPD => write!(f, "vmaxpd"), + &Opcode::VMAXPS => write!(f, "vmaxps"), + &Opcode::VMINPD => write!(f, "vminpd"), + &Opcode::VMINPS => write!(f, "vminps"), + &Opcode::VMOVAPD => write!(f, "vmovapd"), + &Opcode::VMOVAPS => write!(f, "vmovaps"), + &Opcode::VMOVD => write!(f, "vmovd"), + &Opcode::VMOVDQA => write!(f, "vmovdqa"), + &Opcode::VMOVDQU => write!(f, "vmovdqu"), + &Opcode::VMOVHLPS => write!(f, "vmovhlps"), + &Opcode::VMOVHPD => write!(f, "vmovhpd"), + &Opcode::VMOVHPS => write!(f, "vmovhps"), + &Opcode::VMOVLHPS => write!(f, "vmovlhps"), + &Opcode::VMOVLPD => write!(f, "vmovlpd"), + &Opcode::VMOVLPS => write!(f, "vmovlps"), + &Opcode::VMOVMSKPD => write!(f, "vmovmskpd"), + &Opcode::VMOVMSKPS => write!(f, "vmovmskps"), + &Opcode::VMOVNTDQ => write!(f, "vmovntdq"), + &Opcode::VMOVNTDQA => write!(f, "vmovntdqa"), + &Opcode::VMOVNTPD => write!(f, "vmovntpd"), + &Opcode::VMOVNTPS => write!(f, "vmovntps"), + &Opcode::VMOVQ => write!(f, "vmovq"), + &Opcode::VMOVSHDUP => write!(f, "vmovshdup"), + &Opcode::VMOVSLDUP => write!(f, "vmovsldup"), + &Opcode::VMOVUPD => write!(f, "vmovupd"), + &Opcode::VMOVUPS => write!(f, "vmovups"), + &Opcode::VMPSADBW => write!(f, "vmpsadbw"), + &Opcode::VMULPD => write!(f, "vmulpd"), + &Opcode::VMULPS => write!(f, "vmulps"), + &Opcode::VPABSB => write!(f, "vpabsb"), + &Opcode::VPABSD => write!(f, "vpabsd"), + &Opcode::VPABSW => write!(f, "vpabsw"), + &Opcode::VPACKSSDW => write!(f, "vpackssdw"), + &Opcode::VPACKSSWB => write!(f, "vpacksswb"), + &Opcode::VPACKUSWB => write!(f, "vpackuswb"), + &Opcode::VPADDB => write!(f, "vpaddb"), + &Opcode::VPADDD => write!(f, "vpaddd"), + &Opcode::VPADDQ => write!(f, "vpaddq"), + &Opcode::VPADDSB => write!(f, "vpaddsb"), + &Opcode::VPADDSW => write!(f, "vpaddsw"), + &Opcode::VPADDUSB => write!(f, "vpaddusb"), + &Opcode::VPADDUSW => write!(f, "vpaddusw"), + &Opcode::VPADDW => write!(f, "vpaddw"), + &Opcode::VPALIGNR => write!(f, "vpalignr"), + &Opcode::VPAND => write!(f, "vpand"), + &Opcode::VPANDN => write!(f, "vpandn"), + &Opcode::VPAVGB => write!(f, "vpavgb"), + &Opcode::VPAVGW => write!(f, "vpavgw"), + &Opcode::VPBLENDD => write!(f, "vpblendd"), + &Opcode::VPBLENDVB => write!(f, "vpblendvb"), + &Opcode::VPBLENDW => write!(f, "vpblendw"), + &Opcode::VPBROADCASTB => write!(f, "vpbroadcastb"), + &Opcode::VPBROADCASTD => write!(f, "vpbroadcastd"), + &Opcode::VPBROADCASTQ => write!(f, "vpbroadcastq"), + &Opcode::VPBROADCASTW => write!(f, "vpbroadcastw"), + &Opcode::VPCLMULQDQ => write!(f, "vpclmulqdq"), + &Opcode::VPCMPEQB => write!(f, "vpcmpeqb"), + &Opcode::VPCMPEQD => write!(f, "vpcmpeqd"), + &Opcode::VPCMPEQQ => write!(f, "vpcmpeqq"), + &Opcode::VPCMPEQW => write!(f, "vpcmpeqw"), + &Opcode::VPCMPGTB => write!(f, "vpcmpgtb"), + &Opcode::VPCMPGTD => write!(f, "vpcmpgtd"), + &Opcode::VPCMPGTQ => write!(f, "vpcmpgtq"), + &Opcode::VPCMPGTW => write!(f, "vpcmpgtw"), + &Opcode::VPCMPISTRI => write!(f, "vpcmpistri"), + &Opcode::VPCMPISTRM => write!(f, "vpcmpistrm"), + &Opcode::VPERM2F128 => write!(f, "vperm2f128"), + &Opcode::VPERM2I128 => write!(f, "vperm2i128"), + &Opcode::VPERMD => write!(f, "vpermd"), + &Opcode::VPERMILPD => write!(f, "vpermilpd"), + &Opcode::VPERMILPS => write!(f, "vpermilps"), + &Opcode::VPERMPD => write!(f, "vpermpd"), + &Opcode::VPERMPS => write!(f, "vpermps"), + &Opcode::VPERMQ => write!(f, "vpermq"), + &Opcode::VPEXTRB => write!(f, "vpextrb"), + &Opcode::VPEXTRD => write!(f, "vpextrd"), + &Opcode::VPEXTRQ => write!(f, "vpextrq"), + &Opcode::VPEXTRW => write!(f, "vpextrw"), + &Opcode::VPGATHERDD => write!(f, "vpgatherdd"), + &Opcode::VPGATHERDQ => write!(f, "vpgatherdq"), + &Opcode::VPGATHERQD => write!(f, "vpgatherqd"), + &Opcode::VPGATHERQQ => write!(f, "vpgatherqq"), + &Opcode::VPHADDD => write!(f, "vphaddd"), + &Opcode::VPHADDSW => write!(f, "vphaddsw"), + &Opcode::VPHADDUBSW => write!(f, "vphaddubsw"), + &Opcode::VPHADDW => write!(f, "vphaddw"), + &Opcode::VPHMINPOSUW => write!(f, "vphminposuw"), + &Opcode::VPHSUBD => write!(f, "vphsubd"), + &Opcode::VPHSUBSW => write!(f, "vphsubsw"), + &Opcode::VPHSUBW => write!(f, "vphsubw"), + &Opcode::VPINSRB => write!(f, "vpinsrb"), + &Opcode::VPINSRD => write!(f, "vpinsrd"), + &Opcode::VPINSRQ => write!(f, "vpinsrq"), + &Opcode::VPINSRW => write!(f, "vpinsrw"), + &Opcode::VPMADDWD => write!(f, "vpmaddwd"), + &Opcode::VPMASKMOVD => write!(f, "vpmaskmovd"), + &Opcode::VPMASKMOVQ => write!(f, "vpmaskmovq"), + &Opcode::VPMAXSB => write!(f, "vpmaxsb"), + &Opcode::VPMAXSD => write!(f, "vpmaxsd"), + &Opcode::VPMAXSW => write!(f, "vpmaxsw"), + &Opcode::VPMAXUD => write!(f, "vpmaxud"), + &Opcode::VPMINSD => write!(f, "vpminsd"), + &Opcode::VPMINUD => write!(f, "vpminud"), + &Opcode::VPMOVMSKB => write!(f, "vpmovmskb"), + &Opcode::VPMOVSXBD => write!(f, "vpmovsxbd"), + &Opcode::VPMOVSXBQ => write!(f, "vpmovsxbq"), + &Opcode::VPMOVSXBW => write!(f, "vpmovsxbw"), + &Opcode::VPMOVSXDQ => write!(f, "vpmovsxdq"), + &Opcode::VPMOVSXWD => write!(f, "vpmovsxwd"), + &Opcode::VPMOVSXWQ => write!(f, "vpmovsxwq"), + &Opcode::VPMOVZXBD => write!(f, "vpmovzxbd"), + &Opcode::VPMOVZXBQ => write!(f, "vpmovzxbq"), + &Opcode::VPMOVZXBW => write!(f, "vpmovzxbw"), + &Opcode::VPMOVZXDQ => write!(f, "vpmovzxdq"), + &Opcode::VPMOVZXWD => write!(f, "vpmovzxwd"), + &Opcode::VPMOVZXWQ => write!(f, "vpmovzxwq"), + &Opcode::VPMULDQ => write!(f, "vpmuldq"), + &Opcode::VPMULHRSW => write!(f, "vpmulhrsw"), + &Opcode::VPMULHUW => write!(f, "vpmulhuw"), + &Opcode::VPMULHW => write!(f, "vpmulhw"), + &Opcode::VPMULLD => write!(f, "vpmulld"), + &Opcode::VPMULLW => write!(f, "vpmullw"), + &Opcode::VPMULUDQ => write!(f, "vpmuludq"), + &Opcode::VPOR => write!(f, "vpor"), + &Opcode::VPSADBW => write!(f, "vpsadbw"), + &Opcode::VPSHUFB => write!(f, "vpshufb"), + &Opcode::VPSHUFD => write!(f, "vpshufd"), + &Opcode::VPSIGNB => write!(f, "vpsignb"), + &Opcode::VPSIGND => write!(f, "vpsignd"), + &Opcode::VPSIGNW => write!(f, "vpsignw"), + &Opcode::VPSLLD => write!(f, "vpslld"), + &Opcode::VPSLLDQ => write!(f, "vpslldq"), + &Opcode::VPSLLQ => write!(f, "vpsllq"), + &Opcode::VPSLLVD => write!(f, "vpsllvd"), + &Opcode::VPSLLVQ => write!(f, "vpsllvq"), + &Opcode::VPSLLW => write!(f, "vpsllw"), + &Opcode::VPSRAD => write!(f, "vpsrad"), + &Opcode::VPSRAVD => write!(f, "vpsravd"), + &Opcode::VPSRAW => write!(f, "vpsraw"), + &Opcode::VPSRLD => write!(f, "vpsrld"), + &Opcode::VPSRLDQ => write!(f, "vpsrldq"), + &Opcode::VPSRLQ => write!(f, "vpsrlq"), + &Opcode::VPSRLVD => write!(f, "vpsrlvd"), + &Opcode::VPSRLVQ => write!(f, "vpsrlvq"), + &Opcode::VPSRLW => write!(f, "vpsrlw"), + &Opcode::VPSUBB => write!(f, "vpsubb"), + &Opcode::VPSUBD => write!(f, "vpsubd"), + &Opcode::VPSUBQ => write!(f, "vpsubq"), + &Opcode::VPSUBSB => write!(f, "vpsubsb"), + &Opcode::VPSUBSW => write!(f, "vpsubsw"), + &Opcode::VPSUBUSB => write!(f, "vpsubusb"), + &Opcode::VPSUBUSW => write!(f, "vpsubusw"), + &Opcode::VPSUBW => write!(f, "vpsubw"), + &Opcode::VPTEST => write!(f, "vptest"), + &Opcode::VPUNPCKHBW => write!(f, "vpunpckhbw"), + &Opcode::VPUNPCKHDQ => write!(f, "vpunpckhdq"), + &Opcode::VPUNPCKHQDQ => write!(f, "vpunpckhqdq"), + &Opcode::VPUNPCKHWD => write!(f, "vpunpckhwd"), + &Opcode::VPUNPCKLBW => write!(f, "vpunpcklbw"), + &Opcode::VPUNPCKLDQ => write!(f, "vpunpckldq"), + &Opcode::VPUNPCKLQDQ => write!(f, "vpunpcklqdq"), + &Opcode::VPUNPCKLWD => write!(f, "vpunpcklwd"), + &Opcode::VPXOR => write!(f, "vpxor"), + &Opcode::VRCPPS => write!(f, "vrcpps"), + &Opcode::VROUNDPD => write!(f, "vroundpd"), + &Opcode::VROUNDPS => write!(f, "vroundps"), + &Opcode::VRSQRTPS => write!(f, "vrsqrtps"), + &Opcode::VSHUFPD => write!(f, "vshufpd"), + &Opcode::VSHUFPS => write!(f, "vshufps"), + &Opcode::VSQRTPD => write!(f, "vsqrtpd"), + &Opcode::VSQRTPS => write!(f, "vsqrtps"), + &Opcode::VSUBPD => write!(f, "vsubpd"), + &Opcode::VSUBPS => write!(f, "vsubps"), + &Opcode::VTESTPD => write!(f, "vtestpd"), + &Opcode::VTESTPS => write!(f, "vtestps"), + &Opcode::VUNPCKHPD => write!(f, "vunpckhpd"), + &Opcode::VUNPCKHPS => write!(f, "vunpckhps"), + &Opcode::VUNPCKLPD => write!(f, "vunpcklpd"), + &Opcode::VUNPCKLPS => write!(f, "vunpcklps"), + &Opcode::VXORPD => write!(f, "vxorpd"), + &Opcode::VXORPS => write!(f, "vxorps"), + &Opcode::VZEROUPPER => write!(f, "vzeroupper"), + &Opcode::VMOVDDUP => write!(f, "vmovddup"), + &Opcode::VPSHUFLW => write!(f, "vpshuflw"), + &Opcode::VHADDPS => write!(f, "vhaddps"), + &Opcode::VHSUBPS => write!(f, "vhsubps"), + &Opcode::VADDSUBPS => write!(f, "vaddsubps"), + &Opcode::VCVTPD2DQ => write!(f, "vcvtpd2dq"), + &Opcode::VLDDQU => write!(f, "vlddqu"), + &Opcode::VADDSD => write!(f, "vaddsd"), + &Opcode::VADDSS => write!(f, "vaddss"), + &Opcode::VCMPSD => write!(f, "vcmpsd"), + &Opcode::VCMPSS => write!(f, "vcmpss"), + &Opcode::VCOMISD => write!(f, "vcomisd"), + &Opcode::VCOMISS => write!(f, "vcomiss"), + &Opcode::VCVTSD2SI => write!(f, "vcvtsd2si"), + &Opcode::VCVTSD2SS => write!(f, "vcvtsd2ss"), + &Opcode::VCVTSI2SD => write!(f, "vcvtsi2sd"), + &Opcode::VCVTSI2SS => write!(f, "vcvtsi2ss"), + &Opcode::VCVTSS2SD => write!(f, "vcvtss2sd"), + &Opcode::VCVTSS2SI => write!(f, "vcvtss2si"), + &Opcode::VCVTTSD2SI => write!(f, "vcvttsd2si"), + &Opcode::VCVTTSS2SI => write!(f, "vcvttss2si"), + &Opcode::VDIVSD => write!(f, "vdivsd"), + &Opcode::VDIVSS => write!(f, "vdivss"), + &Opcode::VFMADD132SD => write!(f, "vfmadd132sd"), + &Opcode::VFMADD132SS => write!(f, "vfmadd132ss"), + &Opcode::VFMADD213SD => write!(f, "vfmadd213sd"), + &Opcode::VFMADD213SS => write!(f, "vfmadd213ss"), + &Opcode::VFMADD231SD => write!(f, "vfmadd231sd"), + &Opcode::VFMADD231SS => write!(f, "vfmadd231ss"), + &Opcode::VFMSUB132SD => write!(f, "vfmsub132sd"), + &Opcode::VFMSUB132SS => write!(f, "vfmsub132ss"), + &Opcode::VFMSUB213SD => write!(f, "vfmsub213sd"), + &Opcode::VFMSUB213SS => write!(f, "vfmsub213ss"), + &Opcode::VFMSUB231SD => write!(f, "vfmsub231sd"), + &Opcode::VFMSUB231SS => write!(f, "vfmsub231ss"), + &Opcode::VFNMADD132SD => write!(f, "vfnmadd132sd"), + &Opcode::VFNMADD132SS => write!(f, "vfnmadd132ss"), + &Opcode::VFNMADD213SD => write!(f, "vfnmadd213sd"), + &Opcode::VFNMADD213SS => write!(f, "vfnmadd213ss"), + &Opcode::VFNMADD231SD => write!(f, "vfnmadd231sd"), + &Opcode::VFNMADD231SS => write!(f, "vfnmadd231ss"), + &Opcode::VFNMSUB132SD => write!(f, "vfnmsub132sd"), + &Opcode::VFNMSUB132SS => write!(f, "vfnmsub132ss"), + &Opcode::VFNMSUB213SD => write!(f, "vfnmsub213sd"), + &Opcode::VFNMSUB213SS => write!(f, "vfnmsub213ss"), + &Opcode::VFNMSUB231SD => write!(f, "vfnmsub231sd"), + &Opcode::VFNMSUB231SS => write!(f, "vfnmsub231ss"), + &Opcode::VMAXSD => write!(f, "vmaxsd"), + &Opcode::VMAXSS => write!(f, "vmaxss"), + &Opcode::VMINSD => write!(f, "vminsd"), + &Opcode::VMINSS => write!(f, "vminss"), + &Opcode::VMOVSD => write!(f, "vmovsd"), + &Opcode::VMOVSS => write!(f, "vmovss"), + &Opcode::VMULSD => write!(f, "vmulsd"), + &Opcode::VMULSS => write!(f, "vmulss"), + &Opcode::VRCPSS => write!(f, "vrcpss"), + &Opcode::VROUNDSD => write!(f, "vroundsd"), + &Opcode::VROUNDSS => write!(f, "vroundss"), + &Opcode::VRSQRTSS => write!(f, "vrsqrtss"), + &Opcode::VSQRTSD => write!(f, "vsqrtsd"), + &Opcode::VSQRTSS => write!(f, "vsqrtss"), + &Opcode::VSUBSD => write!(f, "vsubsd"), + &Opcode::VSUBSS => write!(f, "vsubss"), + &Opcode::VUCOMISD => write!(f, "vucomisd"), + &Opcode::VUCOMISS => write!(f, "vucomiss"), + &Opcode::PCLMULQDQ => write!(f, "pclmulqdq"), + &Opcode::AESKEYGENASSIST => write!(f, "aeskeygenassist"), + &Opcode::AESIMC => write!(f, "aesimc"), + &Opcode::AESENC => write!(f, "aesenc"), + &Opcode::AESENCLAST => write!(f, "aesenclast"), + &Opcode::AESDEC => write!(f, "aesdec"), + &Opcode::AESDECLAST => write!(f, "aesdeclast"), + &Opcode::PCMPGTQ => write!(f, "pcmpgtq"), + &Opcode::PCMPISTRM => write!(f, "pcmpistrm"), + &Opcode::PCMPISTRI => write!(f, "pcmpistri"), + &Opcode::PCMPESTRI => write!(f, "pcmpestri"), + &Opcode::PACKUSDW => write!(f, "packusdw"), + &Opcode::PCMPESTRM => write!(f, "pcmpestrm"), + &Opcode::PCMPEQQ => write!(f, "pcmpeqq"), + &Opcode::PTEST => write!(f, "ptest"), + &Opcode::PHMINPOSUW => write!(f, "phminposuw"), + &Opcode::MPSADBW => write!(f, "mpsadbw"), + &Opcode::PMOVZXDQ => write!(f, "pmovzxdq"), + &Opcode::PMOVSXDQ => write!(f, "pmovsxdq"), + &Opcode::PMOVZXBD => write!(f, "pmovzxbd"), + &Opcode::PMOVSXBD => write!(f, "pmovsxbd"), + &Opcode::PMOVZXWQ => write!(f, "pmovzxwq"), + &Opcode::PMOVSXWQ => write!(f, "pmovsxwq"), + &Opcode::PMOVZXBQ => write!(f, "pmovzxbq"), + &Opcode::PMOVSXBQ => write!(f, "pmovsxbq"), + &Opcode::PMOVSXWD => write!(f, "pmovsxwd"), + &Opcode::PMOVZXWD => write!(f, "pmovzxwd"), + &Opcode::PEXTRQ => write!(f, "pextrq"), + &Opcode::PEXTRB => write!(f, "pextrb"), + &Opcode::PMOVSXBW => write!(f, "pmovsxbw"), + &Opcode::PMOVZXBW => write!(f, "pmovzxbw"), + &Opcode::PINSRQ => write!(f, "pinsrq"), + &Opcode::PINSRD => write!(f, "pinsrd"), + &Opcode::PINSRB => write!(f, "pinsrb"), + &Opcode::EXTRACTPS => write!(f, "extractps"), + &Opcode::INSERTPS => write!(f, "insertps"), + &Opcode::ROUNDSS => write!(f, "roundss"), + &Opcode::ROUNDSD => write!(f, "roundsd"), + &Opcode::ROUNDPS => write!(f, "roundps"), + &Opcode::ROUNDPD => write!(f, "roundpd"), + &Opcode::PMAXSB => write!(f, "pmaxsb"), + &Opcode::PMAXUW => write!(f, "pmaxuw"), + &Opcode::PMAXUD => write!(f, "pmaxud"), + &Opcode::PMINSD => write!(f, "pminsd"), + &Opcode::PMINSB => write!(f, "pminsb"), + &Opcode::PMINUD => write!(f, "pminud"), + &Opcode::PMINUW => write!(f, "pminuw"), + &Opcode::BLENDW => write!(f, "blendw"), + &Opcode::BLENDDVB => write!(f, "blenddvb"), + &Opcode::BLENDVPS => write!(f, "blendvps"), + &Opcode::BLENDVPD => write!(f, "blendvpd"), + &Opcode::BLENDPS => write!(f, "blendps"), + &Opcode::BLENDPD => write!(f, "blendpd"), + &Opcode::PMULDQ => write!(f, "pmuldq"), + &Opcode::MOVNTDQA => write!(f, "movntdqa"), + &Opcode::PMULLD => write!(f, "pmulld"), + &Opcode::PALIGNR => write!(f, "palignr"), + &Opcode::PSIGNW => write!(f, "psignw"), + &Opcode::PSIGND => write!(f, "psignd"), + &Opcode::PSIGNB => write!(f, "psignb"), + &Opcode::PSHUFB => write!(f, "pshufb"), + &Opcode::PMULHRSU => write!(f, "pmulhrsu"), + &Opcode::PMADDUBSW => write!(f, "pmaddubsw"), + &Opcode::PABSD => write!(f, "pabsd"), + &Opcode::PABSW => write!(f, "pabsw"), + &Opcode::PABSB => write!(f, "pabsb"), + &Opcode::PHSUBSW => write!(f, "phsubsw"), + &Opcode::PHSUBW => write!(f, "phsubw"), + &Opcode::PHSUBD => write!(f, "phsubd"), + &Opcode::PHADDD => write!(f, "phaddd"), + &Opcode::PHADDSW => write!(f, "phaddsw"), + &Opcode::PHADDW => write!(f, "phaddw"), + &Opcode::HSUBPD => write!(f, "hsubpd"), + &Opcode::HADDPD => write!(f, "haddpd"), + &Opcode::ADDSUBPD => write!(f, "addsubpd"), + &Opcode::Invalid => write!(f, "invalid"), + } + } +} + +impl > Colorize for Opcode { + fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { + match self { + Opcode::VHADDPS | + Opcode::VHSUBPS | + Opcode::VADDSUBPS | + Opcode::VADDPD | + Opcode::VADDPS | + Opcode::VADDSD | + Opcode::VADDSS | + Opcode::VADDSUBPD | + Opcode::VFMADD132PD | + Opcode::VFMADD132PS | + Opcode::VFMADD132SD | + Opcode::VFMADD132SS | + Opcode::VFMADD213PD | + Opcode::VFMADD213PS | + Opcode::VFMADD213SD | + Opcode::VFMADD213SS | + Opcode::VFMADD231PD | + Opcode::VFMADD231PS | + Opcode::VFMADD231SD | + Opcode::VFMADD231SS | + Opcode::VFMADDSUB132PD | + Opcode::VFMADDSUB132PS | + Opcode::VFMADDSUB213PD | + Opcode::VFMADDSUB213PS | + Opcode::VFMADDSUB231PD | + Opcode::VFMADDSUB231PS | + Opcode::VFMSUB132PD | + Opcode::VFMSUB132PS | + Opcode::VFMSUB132SD | + Opcode::VFMSUB132SS | + Opcode::VFMSUB213PD | + Opcode::VFMSUB213PS | + Opcode::VFMSUB213SD | + Opcode::VFMSUB213SS | + Opcode::VFMSUB231PD | + Opcode::VFMSUB231PS | + Opcode::VFMSUB231SD | + Opcode::VFMSUB231SS | + Opcode::VFMSUBADD132PD | + Opcode::VFMSUBADD132PS | + Opcode::VFMSUBADD213PD | + Opcode::VFMSUBADD213PS | + Opcode::VFMSUBADD231PD | + Opcode::VFMSUBADD231PS | + Opcode::VFNMADD132PD | + Opcode::VFNMADD132PS | + Opcode::VFNMADD132SD | + Opcode::VFNMADD132SS | + Opcode::VFNMADD213PD | + Opcode::VFNMADD213PS | + Opcode::VFNMADD213SD | + Opcode::VFNMADD213SS | + Opcode::VFNMADD231PD | + Opcode::VFNMADD231PS | + Opcode::VFNMADD231SD | + Opcode::VFNMADD231SS | + Opcode::VFNMSUB132PD | + Opcode::VFNMSUB132PS | + Opcode::VFNMSUB132SD | + Opcode::VFNMSUB132SS | + Opcode::VFNMSUB213PD | + Opcode::VFNMSUB213PS | + Opcode::VFNMSUB213SD | + Opcode::VFNMSUB213SS | + Opcode::VFNMSUB231PD | + Opcode::VFNMSUB231PS | + Opcode::VFNMSUB231SD | + Opcode::VFNMSUB231SS | + Opcode::VDIVPD | + Opcode::VDIVPS | + Opcode::VDIVSD | + Opcode::VDIVSS | + Opcode::VHADDPD | + Opcode::VHSUBPD | + Opcode::HADDPD | + Opcode::HSUBPD | + Opcode::VMULPD | + Opcode::VMULPS | + Opcode::VMULSD | + Opcode::VMULSS | + Opcode::VPABSB | + Opcode::VPABSD | + Opcode::VPABSW | + Opcode::PABSB | + Opcode::PABSD | + Opcode::PABSW | + Opcode::VPSIGNB | + Opcode::VPSIGND | + Opcode::VPSIGNW | + Opcode::PSIGNB | + Opcode::PSIGND | + Opcode::PSIGNW | + Opcode::VPADDB | + Opcode::VPADDD | + Opcode::VPADDQ | + Opcode::VPADDSB | + Opcode::VPADDSW | + Opcode::VPADDUSB | + Opcode::VPADDUSW | + Opcode::VPADDW | + Opcode::VPAVGB | + Opcode::VPAVGW | + Opcode::VPMULDQ | + Opcode::VPMULHRSW | + Opcode::VPMULHUW | + Opcode::VPMULHW | + Opcode::VPMULLD | + Opcode::VPMULLW | + Opcode::VPMULUDQ | + Opcode::PCLMULQDQ | + Opcode::PMULDQ | + Opcode::PMULHRSU | + Opcode::PMULLD | + Opcode::VPSUBB | + Opcode::VPSUBD | + Opcode::VPSUBQ | + Opcode::VPSUBSB | + Opcode::VPSUBSW | + Opcode::VPSUBUSB | + Opcode::VPSUBUSW | + Opcode::VPSUBW | + Opcode::VROUNDPD | + Opcode::VROUNDPS | + Opcode::VRSQRTPS | + Opcode::VSQRTPD | + Opcode::VSQRTPS | + Opcode::VSUBPD | + Opcode::VSUBPS | + Opcode::VSUBSD | + Opcode::VSUBSS | + Opcode::VRCPSS | + Opcode::VROUNDSD | + Opcode::VROUNDSS | + Opcode::ROUNDPD | + Opcode::ROUNDPS | + Opcode::ROUNDSD | + Opcode::ROUNDSS | + Opcode::VRSQRTSS | + Opcode::VSQRTSD | + Opcode::VSQRTSS | + Opcode::VPSADBW | + Opcode::VMPSADBW | + Opcode::VPHADDD | + Opcode::VPHADDSW | + Opcode::VPHADDW | + Opcode::VPHSUBD | + Opcode::VPHSUBSW | + Opcode::VPHSUBW | + Opcode::VPHADDUBSW | + Opcode::VPMADDWD | + Opcode::VDPPD | + Opcode::VDPPS | + Opcode::VRCPPS | + Opcode::VPAND | + Opcode::VPANDN | + Opcode::VPOR | + Opcode::VPXOR | + Opcode::VXORPD | + Opcode::VXORPS | + Opcode::VPSLLD | + Opcode::VPSLLDQ | + Opcode::VPSLLQ | + Opcode::VPSLLVD | + Opcode::VPSLLVQ | + Opcode::VPSLLW | + Opcode::VPSRAD | + Opcode::VPSRAVD | + Opcode::VPSRAW | + Opcode::VPSRLD | + Opcode::VPSRLDQ | + Opcode::VPSRLQ | + Opcode::VPSRLVD | + Opcode::VPSRLVQ | + Opcode::VPSRLW | + Opcode::PHADDD | + Opcode::PHADDSW | + Opcode::PHADDW | + Opcode::PHSUBD | + Opcode::PHSUBSW | + Opcode::PHSUBW | + Opcode::PMADDUBSW | + Opcode::ADDSUBPD | + Opcode::MPSADBW | + Opcode::RCPSS | + Opcode::RSQRTSS | + Opcode::SQRTSD | + Opcode::ADDSD | + Opcode::SUBSD | + Opcode::MULSD | + Opcode::DIVSD | + Opcode::SQRTSS | + Opcode::ADDSS | + Opcode::SUBSS | + Opcode::MULSS | + Opcode::DIVSS | + Opcode::HADDPS | + Opcode::HSUBPS | + Opcode::ADDSUBPS | + Opcode::XADD| + Opcode::DIV | + Opcode::IDIV | + Opcode::MUL | + Opcode::NEG | + Opcode::NOT | + Opcode::SAR | + Opcode::SAL | + Opcode::SHR | + Opcode::SHRD | + Opcode::SHL | + Opcode::RCR | + Opcode::RCL | + Opcode::ROR | + Opcode::ROL | + Opcode::INC | + Opcode::DEC | + Opcode::SBB | + Opcode::AND | + Opcode::XOR | + Opcode::OR | + Opcode::LEA | + Opcode::ADD | + Opcode::ADC | + Opcode::SUB | + Opcode::POPCNT | + Opcode::BT | + Opcode::BTS | + Opcode::BTR | + Opcode::BTC | + Opcode::BSF | + Opcode::BSR | + Opcode::TZCNT | + Opcode::ANDN | + Opcode::BEXTR | + Opcode::BLSI | + Opcode::BLSMSK | + Opcode::BLSR | + Opcode::ADDPS | + Opcode::ANDNPS | + Opcode::ANDPS | + Opcode::COMISS | + Opcode::DIVPS | + Opcode::MULPS | + Opcode::ORPS | + Opcode::PADDB | + Opcode::PADDD | + Opcode::PADDQ | + Opcode::PADDSB | + Opcode::PADDSW | + Opcode::PADDUSB | + Opcode::PADDUSW | + Opcode::PADDW | + Opcode::PAND | + Opcode::PANDN | + Opcode::PAVGB | + Opcode::PAVGW | + Opcode::PMADDWD | + Opcode::PMULHUW | + Opcode::PMULHW | + Opcode::PMULLW | + Opcode::PMULUDQ | + Opcode::POR | + Opcode::PSADBW | + Opcode::PSHUFD | + Opcode::PSHUFW | + Opcode::PSHUFB | + Opcode::PSLLD | + Opcode::PSLLDQ | + Opcode::PSLLQ | + Opcode::PSLLW | + Opcode::PSRAD | + Opcode::PSRAW | + Opcode::PSRLD | + Opcode::PSRLDQ | + Opcode::PSRLQ | + Opcode::PSRLW | + Opcode::PSUBB | + Opcode::PSUBD | + Opcode::PSUBQ | + Opcode::PSUBSB | + Opcode::PSUBSW | + Opcode::PSUBUSB | + Opcode::PSUBUSW | + Opcode::PSUBW | + Opcode::PXOR | + Opcode::RSQRTPS | + Opcode::SQRTPS | + Opcode::SUBPS | + Opcode::XORPS | + Opcode::RCPPS | + Opcode::SHLD | + Opcode::SLHD | + Opcode::UCOMISS | + Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) } + Opcode::POPF | + Opcode::PUSHF | + Opcode::ENTER | + Opcode::LEAVE | + Opcode::PUSH | + Opcode::POP => { write!(out, "{}", colors.stack_op(self)) } + Opcode::WAIT | + Opcode::PREFETCHNTA | + Opcode::PREFETCH0 | + Opcode::PREFETCH1 | + Opcode::PREFETCH2 | + Opcode::NOP => { write!(out, "{}", colors.nop_op(self)) } + + /* Control flow */ + Opcode::HLT | + Opcode::INT | + Opcode::INTO | + Opcode::IRET | + Opcode::RETF | + Opcode::RETURN => { write!(out, "{}", colors.stop_op(self)) } + Opcode::CALL | + Opcode::CALLF | + Opcode::JMP | + Opcode::JMPF | + Opcode::JO | + Opcode::JNO | + Opcode::JB | + Opcode::JNB | + Opcode::JZ | + Opcode::JNZ | + Opcode::JA | + Opcode::JNA | + Opcode::JS | + Opcode::JNS | + Opcode::JP | + Opcode::JNP | + Opcode::JL | + Opcode::JGE | + Opcode::JLE | + Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) } + + /* Data transfer */ + Opcode::VCVTDQ2PD | + Opcode::VCVTDQ2PS | + Opcode::VCVTPD2DQ | + Opcode::VCVTPD2PS | + Opcode::VCVTPH2PS | + Opcode::VCVTPS2DQ | + Opcode::VCVTPS2PD | + Opcode::VCVTPS2PH | + Opcode::VCVTTPD2DQ | + Opcode::VCVTTPS2DQ | + Opcode::VCVTSD2SI | + Opcode::VCVTSD2SS | + Opcode::VCVTSI2SD | + Opcode::VCVTSI2SS | + Opcode::VCVTSS2SD | + Opcode::VCVTSS2SI | + Opcode::VCVTTSD2SI | + Opcode::VCVTTSS2SI | + Opcode::VMOVDDUP | + Opcode::VPSHUFLW | + Opcode::VBLENDPD | + Opcode::VBLENDPS | + Opcode::VBLENDVPD | + Opcode::VBLENDVPS | + Opcode::BLENDDVB | + Opcode::BLENDPD | + Opcode::BLENDPS | + Opcode::BLENDVPD | + Opcode::BLENDVPS | + Opcode::BLENDW | + Opcode::VBROADCASTF128 | + Opcode::VBROADCASTI128 | + Opcode::VBROADCASTSD | + Opcode::VBROADCASTSS | + Opcode::VEXTRACTF128 | + Opcode::VEXTRACTI128 | + Opcode::VEXTRACTPS | + Opcode::EXTRACTPS | + Opcode::VGATHERDPD | + Opcode::VGATHERDPS | + Opcode::VGATHERQPD | + Opcode::VGATHERQPS | + Opcode::VINSERTF128 | + Opcode::VINSERTI128 | + Opcode::VINSERTPS | + Opcode::INSERTPS | + Opcode::VMASKMOVDQU | + Opcode::VMASKMOVPD | + Opcode::VMASKMOVPS | + Opcode::VMOVAPD | + Opcode::VMOVAPS | + Opcode::VMOVD | + Opcode::VMOVDQA | + Opcode::VMOVDQU | + Opcode::VMOVHLPS | + Opcode::VMOVHPD | + Opcode::VMOVHPS | + Opcode::VMOVLHPS | + Opcode::VMOVLPD | + Opcode::VMOVLPS | + Opcode::VMOVMSKPD | + Opcode::VMOVMSKPS | + Opcode::VMOVNTDQ | + Opcode::VMOVNTDQA | + Opcode::VMOVNTPD | + Opcode::VMOVNTPS | + Opcode::MOVNTDQA | + Opcode::VMOVQ | + Opcode::VMOVSHDUP | + Opcode::VMOVSLDUP | + Opcode::VMOVUPD | + Opcode::VMOVUPS | + Opcode::VMOVSD | + Opcode::VMOVSS | + + Opcode::VPBLENDD | + Opcode::VPBLENDVB | + Opcode::VPBLENDW | + Opcode::VPBROADCASTB | + Opcode::VPBROADCASTD | + Opcode::VPBROADCASTQ | + Opcode::VPBROADCASTW | + Opcode::VPGATHERDD | + Opcode::VPGATHERDQ | + Opcode::VPGATHERQD | + Opcode::VPGATHERQQ | + Opcode::VPCLMULQDQ | + Opcode::VPMOVMSKB | + Opcode::VPMOVSXBD | + Opcode::VPMOVSXBQ | + Opcode::VPMOVSXBW | + Opcode::VPMOVSXDQ | + Opcode::VPMOVSXWD | + Opcode::VPMOVSXWQ | + Opcode::VPMOVZXBD | + Opcode::VPMOVZXBQ | + Opcode::VPMOVZXBW | + Opcode::VPMOVZXDQ | + Opcode::VPMOVZXWD | + Opcode::VPMOVZXWQ | + Opcode::PMOVSXBD | + Opcode::PMOVSXBQ | + Opcode::PMOVSXBW | + Opcode::PMOVSXDQ | + Opcode::PMOVSXWD | + Opcode::PMOVSXWQ | + Opcode::PMOVZXBD | + Opcode::PMOVZXBQ | + Opcode::PMOVZXBW | + Opcode::PMOVZXDQ | + Opcode::PMOVZXWD | + Opcode::PMOVZXWQ | + Opcode::VUNPCKHPD | + Opcode::VUNPCKHPS | + Opcode::VUNPCKLPD | + Opcode::VUNPCKLPS | + Opcode::VPUNPCKHBW | + Opcode::VPUNPCKHDQ | + Opcode::VPUNPCKHQDQ | + Opcode::VPUNPCKHWD | + Opcode::VPUNPCKLBW | + Opcode::VPUNPCKLDQ | + Opcode::VPUNPCKLQDQ | + Opcode::VPUNPCKLWD | + Opcode::VSHUFPD | + Opcode::VSHUFPS | + Opcode::VPACKSSDW | + Opcode::PACKUSDW | + Opcode::VPACKSSWB | + Opcode::VPACKUSWB | + Opcode::VPALIGNR | + Opcode::PALIGNR | + Opcode::VPERM2F128 | + Opcode::VPERM2I128 | + Opcode::VPERMD | + Opcode::VPERMILPD | + Opcode::VPERMILPS | + Opcode::VPERMPD | + Opcode::VPERMPS | + Opcode::VPERMQ | + Opcode::VPEXTRB | + Opcode::VPEXTRD | + Opcode::VPEXTRQ | + Opcode::VPEXTRW | + Opcode::PEXTRB | + Opcode::PEXTRQ | + Opcode::PINSRB | + Opcode::PINSRD | + Opcode::PINSRQ | + Opcode::VPINSRB | + Opcode::VPINSRD | + Opcode::VPINSRQ | + Opcode::VPINSRW | + Opcode::VPMASKMOVD | + Opcode::VPMASKMOVQ | + Opcode::VPSHUFB | + Opcode::VPSHUFD | + Opcode::VPHMINPOSUW | + Opcode::PHMINPOSUW | + Opcode::VZEROUPPER | + Opcode::VLDDQU | + Opcode::BSWAP | + Opcode::CVTDQ2PD | + Opcode::CVTDQ2PS | + Opcode::CVTPD2DQ | + Opcode::CVTPI2PS | + Opcode::CVTPI2PD | + Opcode::CVTPS2PD | + Opcode::CVTPS2PI | + Opcode::CVTSD2SI | + Opcode::CVTSD2SS | + Opcode::CVTSI2SD | + Opcode::CVTSI2SS | + Opcode::CVTSS2SD | + Opcode::CVTSS2SI | + Opcode::CVTTPS2DQ | + Opcode::CVTTPS2PI | + Opcode::CVTTSD2SI | + Opcode::CVTTSS2SI | + Opcode::MASKMOVQ | + Opcode::MOVAPS | + Opcode::MOVAPD | + Opcode::MOVD | + Opcode::MOVHPS | + Opcode::MOVHLPS | + Opcode::MOVLPS | + Opcode::MOVLHPS | + Opcode::MOVMSKPS | + Opcode::MOVNTI | + Opcode::MOVNTPS | + Opcode::MOVNTQ | + Opcode::MOVSD | + Opcode::MOVSS | + Opcode::MOVUPD | + Opcode::PSHUFHW | + Opcode::PSHUFLW | + Opcode::PUNPCKHBW | + Opcode::PUNPCKHDQ | + Opcode::PUNPCKHWD | + Opcode::PUNPCKLBW | + Opcode::PUNPCKLDQ | + Opcode::PUNPCKLWD | + Opcode::PUNPCKLQDQ | + Opcode::PUNPCKHQDQ | + Opcode::PACKSSDW | + Opcode::PACKSSWB | + Opcode::PACKUSWB | + Opcode::UNPCKHPS | + Opcode::UNPCKLPS | + Opcode::SHUFPS | + Opcode::PMOVMSKB | + Opcode::LDDQU | + Opcode::CLC | + Opcode::CLI | + Opcode::CLD | + Opcode::STC | + Opcode::STI | + Opcode::STD | + Opcode::CBW | + Opcode::CWDE | + Opcode::CDQE | + Opcode::CBD | + Opcode::CDQ | + Opcode::CQO | + Opcode::MOVDDUP | + Opcode::MOVSLDUP | + Opcode::MOVDQ2Q | + Opcode::MOVDQU | + Opcode::MOVDQA | + Opcode::MOVQ | + Opcode::MOVQ2DQ | + Opcode::MOVSHDUP | + Opcode::MOVUPS | + Opcode::PEXTRW | + Opcode::PINSRW | + Opcode::MOV | + Opcode::LODS | + Opcode::STOS | + Opcode::LAHF | + Opcode::SAHF | + Opcode::MOVS | + Opcode::INS | + Opcode::OUTS | + Opcode::MOVSX_b | + Opcode::MOVSX_w | + Opcode::MOVZX_b | + Opcode::MOVZX_w | + Opcode::MOVSX | + Opcode::MOVSXD | + Opcode::XCHG | + Opcode::CMOVA | + Opcode::CMOVB | + Opcode::CMOVG | + Opcode::CMOVGE | + Opcode::CMOVL | + Opcode::CMOVLE | + Opcode::CMOVNA | + Opcode::CMOVNB | + Opcode::CMOVNO | + Opcode::CMOVNP | + Opcode::CMOVNS | + Opcode::CMOVNZ | + Opcode::CMOVO | + Opcode::CMOVP | + Opcode::CMOVS | + Opcode::CMOVZ | + Opcode::SETO | + Opcode::SETNO | + Opcode::SETB | + Opcode::SETAE | + Opcode::SETZ | + Opcode::SETNZ | + Opcode::SETBE | + Opcode::SETA | + Opcode::SETS | + Opcode::SETNS | + Opcode::SETP | + Opcode::SETNP | + Opcode::SETL | + Opcode::SETGE | + Opcode::SETLE | + Opcode::SETG => { write!(out, "{}", colors.data_op(self)) } + + Opcode::VCOMISD | + Opcode::VCOMISS | + Opcode::VUCOMISD | + Opcode::VUCOMISS | + Opcode::VCMPPD | + Opcode::VCMPPS | + Opcode::VCMPSD | + Opcode::VCMPSS | + Opcode::VMAXPD | + Opcode::VMAXPS | + Opcode::VMAXSD | + Opcode::VMAXSS | + Opcode::VMINPD | + Opcode::VMINPS | + Opcode::VMINSD | + Opcode::VMINSS | + Opcode::VPCMPEQB | + Opcode::VPCMPEQD | + Opcode::VPCMPEQQ | + Opcode::VPCMPEQW | + Opcode::VPCMPGTB | + Opcode::VPCMPGTD | + Opcode::VPCMPGTQ | + Opcode::VPCMPGTW | + Opcode::VPCMPISTRI | + Opcode::VPCMPISTRM | + Opcode::VPMAXSB | + Opcode::VPMAXSD | + Opcode::VPMAXSW | + Opcode::VPMAXUD | + Opcode::VPMINSD | + Opcode::VPMINUD | + Opcode::VPTEST | + Opcode::VTESTPD | + Opcode::VTESTPS | + Opcode::PCMPEQB | + Opcode::PCMPEQD | + Opcode::PCMPEQQ | + Opcode::PCMPEQW | + Opcode::PCMPESTRI | + Opcode::PCMPESTRM | + Opcode::PCMPGTB | + Opcode::PCMPGTD | + Opcode::PCMPGTQ | + Opcode::PCMPGTW | + Opcode::PCMPISTRI | + Opcode::PCMPISTRM | + Opcode::PTEST | + Opcode::MAXPS | + Opcode::MAXSD | + Opcode::MAXSS | + Opcode::MINPS | + Opcode::MINSD | + Opcode::MINSS | + Opcode::PMAXSB | + Opcode::PMAXSW | + Opcode::PMAXUB | + Opcode::PMAXUD | + Opcode::PMAXUW | + Opcode::PMINSB | + Opcode::PMINSD | + Opcode::PMINSW | + Opcode::PMINUB | + Opcode::PMINUD | + Opcode::PMINUW | + Opcode::CMPS | + Opcode::SCAS | + Opcode::TEST | + Opcode::CMPSD | + Opcode::CMPSS | + Opcode::CMP | + Opcode::CMPPS | + Opcode::CMPXCHG => { write!(out, "{}", colors.comparison_op(self)) } + + Opcode::WRMSR | + Opcode::RDMSR | + Opcode::RDTSC | + Opcode::RDPMC | + Opcode::FXSAVE | + Opcode::FXRSTOR | + Opcode::LDMXCSR | + Opcode::STMXCSR | + Opcode::XSAVE | + Opcode::XRSTOR | + Opcode::XSAVEOPT | + Opcode::LFENCE | + Opcode::MFENCE | + Opcode::SFENCE | + Opcode::CLFLUSH | + Opcode::SGDT | + Opcode::SIDT | + Opcode::LGDT | + Opcode::LIDT | + Opcode::SMSW | + Opcode::LMSW | + Opcode::SWAPGS | + Opcode::RDTSCP | + Opcode::INVLPG | + Opcode::CPUID | + Opcode::WBINVD | + Opcode::INVD | + Opcode::SYSRET | + Opcode::CLTS | + Opcode::SYSCALL | + Opcode::LSL | + Opcode::SLDT | + Opcode::STR | + Opcode::LLDT | + Opcode::LTR | + Opcode::VERR | + Opcode::VERW | + Opcode::JMPE | + Opcode::EMMS | + Opcode::GETSEC | + Opcode::LFS | + Opcode::LGS | + Opcode::LSS | + Opcode::RSM | + Opcode::SYSENTER | + Opcode::SYSEXIT | + Opcode::UD2E | + Opcode::VMREAD | + Opcode::VMWRITE | + Opcode::VMCALL | + Opcode::VMLAUNCH | + Opcode::VMRESUME | + Opcode::VMXOFF | + Opcode::MONITOR | + Opcode::MWAIT | + Opcode::CLAC | + Opcode::STAC | + Opcode::ENCLS | + Opcode::ENCLV | + Opcode::XGETBV | + Opcode::XSETBV | + Opcode::VMFUNC | + Opcode::XEND | + Opcode::XTEST | + Opcode::ENCLU | + Opcode::RDPKRU | + Opcode::WRPKRU | + Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } + + Opcode::AESDEC | + Opcode::AESDECLAST | + Opcode::AESENC | + Opcode::AESENCLAST | + Opcode::AESIMC | + Opcode::AESKEYGENASSIST | + Opcode::VAESDEC | + Opcode::VAESDECLAST | + Opcode::VAESENC | + Opcode::VAESENCLAST | + Opcode::VAESIMC | + Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) } + + Opcode::UD2 | + Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) } + } + } +} + +impl fmt::Display for Instruction { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + self.colorize(&NoColors, fmt) + } +} + +/* + * Can't implement this as accepting a formatter because rust + * doesn't let me build one outside println! or write! or whatever. + * + * can't write this as an intermediate struct because i refuse to copy + * all data into the struct, and having a function producing a struct with + * some lifetimes gets really hairy if it's from a trait - same GAT kind + * of nonsense as i saw with ContextRead, because someone could hold onto + * the dang intermediate struct forever. + * + * so write to some Write thing i guess. bite me. i really just want to + * stop thinking about how to support printing instructions... + */ +impl > Colorize for Instruction { + fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { + // TODO: I DONT LIKE THIS, there is no address i can give contextualize here, + // the address operand maybe should be optional.. + self.contextualize(colors, 0, Some(&NoContext), out) + } +} + +/// No per-operand context when contextualizing an instruction! +struct NoContext; + +impl > ShowContextual for Instruction { + fn contextualize(&self, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { + if self.prefixes.lock() { + write!(out, "lock ")?; + } + + if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) { + // only a few of you actually use the prefix... + if self.prefixes.rep() { + write!(out, "rep ")?; + } else if self.prefixes.repz() { + write!(out, "repz ")?; + } else if self.prefixes.repnz() { + write!(out, "repnz ")?; + } + } + + self.opcode.colorize(colors, out)?; + + match self.operands[0] { + OperandSpec::Nothing => { + return Ok(()); + }, + _ => { + write!(out, " ")?; + if let Some(prefix) = self.segment_override_for_op(0) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[0]); + x.colorize(colors, out)?; + + for i in 1..4 { + match self.opcode { + Opcode::MOVSX_b | + Opcode::MOVZX_b => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + _ => { + write!(out, ", byte ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + }, + Opcode::MOVSX_w | + Opcode::MOVZX_w => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + _ => { + write!(out, ", word ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + }, + _ => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + _ => { + write!(out, ", ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + } + } + } + } + } + Ok(()) + } +} + +#[cfg(feature="std")] +impl > ShowContextual], Color, T, Y> for Instruction { + fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option]>, out: &mut T) -> fmt::Result { + if self.prefixes.lock() { + write!(out, "lock ")?; + } + + if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) { + // only a few of you actually use the prefix... + if self.prefixes.rep() { + write!(out, "rep ")?; + } else if self.prefixes.repz() { + write!(out, "repz ")?; + } else if self.prefixes.repnz() { + write!(out, "repnz ")?; + } + } + + self.opcode.colorize(colors, out)?; + + match context.and_then(|xs| xs[0].as_ref()) { + Some(s) => { write!(out, " {}", s)?; }, + None => { + match self.operands[0] { + OperandSpec::Nothing => { + return Ok(()); + }, + _ => { + write!(out, " ")?; + if let Some(prefix) = self.segment_override_for_op(0) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[0]); + x.colorize(colors, out)?; + } + }; + for i in 1..4 { + match self.opcode { + Opcode::MOVSX_b | + Opcode::MOVZX_b => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + _ => { + write!(out, ", byte ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + } + } + }, + Opcode::MOVSX_w | + Opcode::MOVZX_w => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + &OperandSpec::RegMMM => { + write!(out, ", ")?; + } + _ => { + write!(out, ", word ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + } + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + } + } + }, + _ => { + match context.and_then(|xs| xs[i].as_ref()) { + Some(s) => { write!(out, ", {}", s)? } + None => { + match &self.operands[i] { + &OperandSpec::Nothing => { + return Ok(()); + }, + _ => { + write!(out, ", ")?; + if let Some(prefix) = self.segment_override_for_op(1) { + write!(out, "{}:", prefix)?; + } + let x = Operand::from_spec(self, self.operands[i]); + x.colorize(colors, out)? + } + } + } + } + } + } + } + Ok(()) + } +} diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs new file mode 100644 index 0000000..1468a9c --- /dev/null +++ b/src/long_mode/mod.rs @@ -0,0 +1,6209 @@ +mod vex; +mod display; + +use core::hint::unreachable_unchecked; + +use yaxpeax_arch::{Decoder, LengthedInstruction}; + +#[cfg(feature="use-serde")] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct RegSpec { + pub num: u8, + pub bank: RegisterBank +} +#[cfg(not(feature="use-serde"))] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct RegSpec { + pub num: u8, + pub bank: RegisterBank +} + +use core::hash::Hash; +use core::hash::Hasher; +impl Hash for RegSpec { + fn hash(&self, state: &mut H) { + let code = ((self.bank as u16) << 8) | (self.num as u16); + code.hash(state); + } +} + +// This is only to select alternate opcode maps for the 0f escape byte. +// This often could be treated as a size prefix but in some cases selects +// an entirely different operation. +#[derive(Debug)] +enum OpcodeMap { + Map66, + MapF2, + MapF3, +} + +#[derive(Debug)] +pub enum ConditionCode { + O, + NO, + B, + AE, + Z, + NZ, + A, + BE, + S, + NS, + P, + NP, + L, + GE, + G, + LE, +} + +#[allow(non_snake_case)] +impl RegSpec { + #[inline] + fn from_parts(num: u8, extended: bool, bank: RegisterBank) -> RegSpec { + RegSpec { + num: num + if extended { 0b1000 } else { 0 }, + bank: bank + } + } + + #[inline] + fn gp_from_parts(num: u8, extended: bool, width: u8, rex: bool) -> RegSpec { +// println!("from_parts width: {}, num: {}, extended: {}", width, num, extended); + RegSpec { + num: num + if extended { 0b1000 } else { 0 }, + bank: width_to_gp_reg_bank(width, rex) + } + } + + #[inline] + pub fn rip() -> RegSpec { + RegSpec { + num: 0, + bank: RegisterBank::RIP + } + } + + #[inline] + pub fn eip() -> RegSpec { + RegSpec { + num: 0, + bank: RegisterBank::EIP + } + } + + #[inline] + pub fn eflags() -> RegSpec { + RegSpec { + num: 0, + bank: RegisterBank::EFlags + } + } + + #[inline] + pub fn rflags() -> RegSpec { + RegSpec { + num: 0, + bank: RegisterBank::RFlags + } + } + + #[inline] + pub fn rbp() -> RegSpec { + RegSpec { + num: 5, + bank: RegisterBank::Q + } + } + + #[inline] + pub fn rsp() -> RegSpec { + RegSpec { + num: 4, + bank: RegisterBank::Q + } + } + + #[inline] + pub fn fs() -> RegSpec { + RegSpec { bank: RegisterBank::S, num: 3 } + } + + #[inline] + pub fn gs() -> RegSpec { + RegSpec { bank: RegisterBank::S, num: 4 } + } + + #[inline] + pub fn rax() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 0 } + } + + #[inline] + pub fn rcx() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 1 } + } + + #[inline] + pub fn rdx() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 2 } + } + + #[inline] + pub fn rsi() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 6 } + } + + #[inline] + pub fn rdi() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 7 } + } + + #[inline] + pub fn r8() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 8 } + } + + #[inline] + pub fn r9() -> RegSpec { + RegSpec { bank: RegisterBank::Q, num: 9 } + } + + #[inline] + pub fn eax() -> RegSpec { + RegSpec { bank: RegisterBank::D, num: 0 } + } + + #[inline] + pub fn ax() -> RegSpec { + RegSpec { bank: RegisterBank::W, num: 0 } + } + + #[inline] + pub fn al() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 0 } + } + + #[inline] + pub fn cl() -> RegSpec { + RegSpec { bank: RegisterBank::B, num: 1 } + } +} + +#[allow(non_camel_case_types)] +#[allow(dead_code)] +enum SizeCode { + b, + vd, + vq, + vqp +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Operand { + ImmediateI8(i8), + ImmediateU8(u8), + ImmediateI16(i16), + ImmediateU16(u16), + ImmediateU32(u32), + ImmediateI32(i32), + ImmediateU64(u64), + ImmediateI64(i64), + Register(RegSpec), + DisplacementU32(u32), + DisplacementU64(u64), + RegDeref(RegSpec), + RegDisp(RegSpec, i32), + RegScale(RegSpec, u8), + RegIndexBase(RegSpec, RegSpec), + RegIndexBaseDisp(RegSpec, RegSpec, i32), + RegScaleDisp(RegSpec, u8, i32), + RegIndexBaseScale(RegSpec, RegSpec, u8), + RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32), + Nothing, +} + +impl OperandSpec { + pub fn is_memory(&self) -> bool { + match self { + OperandSpec::DispU32 | + OperandSpec::DispU64 | + OperandSpec::Deref | + OperandSpec::Deref_rsi | + OperandSpec::Deref_rdi | + OperandSpec::RegDisp | + OperandSpec::RegScale | + OperandSpec::RegIndexBase | + OperandSpec::RegIndexBaseDisp | + OperandSpec::RegScaleDisp | + OperandSpec::RegIndexBaseScale | + OperandSpec::RegIndexBaseScaleDisp => { + true + }, + OperandSpec::ImmI8 | + OperandSpec::ImmI16 | + OperandSpec::ImmI32 | + OperandSpec::ImmI64 | + OperandSpec::ImmU8 | + OperandSpec::ImmU16 | + OperandSpec::ImmU32 | + OperandSpec::ImmU64 | + OperandSpec::RegRRR | + OperandSpec::RegMMM | + OperandSpec::RegVex | + OperandSpec::AL | + OperandSpec::CL | + OperandSpec::Nothing => { + false + } + } + } +} +impl Operand { + fn from_spec(inst: &Instruction, spec: OperandSpec) -> Operand { + match spec { + OperandSpec::Nothing => { + Operand::Nothing + } + // the register in modrm_rrr + OperandSpec::RegRRR => { + Operand::Register(inst.modrm_rrr) + } + // the register in modrm_mmm (eg modrm mod bits were 11) + OperandSpec::RegMMM => { + Operand::Register(inst.modrm_mmm) + } + OperandSpec::RegVex => { + Operand::Register(inst.vex_reg) + } + OperandSpec::AL => { + Operand::Register(RegSpec::al()) + } + OperandSpec::CL => { + Operand::Register(RegSpec::cl()) + } + OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8), + OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), + OperandSpec::ImmI16 => Operand::ImmediateI16(inst.imm as i16), + OperandSpec::ImmU16 => Operand::ImmediateU16(inst.imm as u16), + OperandSpec::ImmI32 => Operand::ImmediateI32(inst.imm as i32), + OperandSpec::ImmU32 => Operand::ImmediateU32(inst.imm as u32), + OperandSpec::ImmI64 => Operand::ImmediateI64(inst.imm as i64), + OperandSpec::ImmU64 => Operand::ImmediateU64(inst.imm as u64), + OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp as u32), + OperandSpec::DispU64 => Operand::DisplacementU64(inst.disp as u64), + OperandSpec::Deref => { + Operand::RegDeref(inst.modrm_mmm) + } + OperandSpec::Deref_rsi => { + Operand::RegDeref(RegSpec::rsi()) + } + OperandSpec::Deref_rdi => { + Operand::RegDeref(RegSpec::rdi()) + } + OperandSpec::RegDisp => { + Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) + } + OperandSpec::RegScale => { + Operand::RegScale(inst.sib_index, inst.scale) + } + OperandSpec::RegIndexBase => { + Operand::RegIndexBase(inst.modrm_mmm, inst.sib_index) + } + OperandSpec::RegIndexBaseDisp => { + Operand::RegIndexBaseDisp(inst.modrm_mmm, inst.sib_index, inst.disp as i32) + } + OperandSpec::RegScaleDisp => { + Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) + } + OperandSpec::RegIndexBaseScale => { + Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) + } + OperandSpec::RegIndexBaseScaleDisp => { + Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) + } + } + } + pub fn is_memory(&self) -> bool { + match self { + Operand::DisplacementU32(_) | + Operand::DisplacementU64(_) | + Operand::RegDeref(_) | + Operand::RegDisp(_, _) | + Operand::RegScale(_, _) | + Operand::RegIndexBase(_, _) | + Operand::RegIndexBaseDisp(_, _, _) | + Operand::RegScaleDisp(_, _, _) | + Operand::RegIndexBaseScale(_, _, _) | + Operand::RegIndexBaseScaleDisp(_, _, _, _) => { + true + }, + Operand::ImmediateI8(_) | + Operand::ImmediateU8(_) | + Operand::ImmediateI16(_) | + Operand::ImmediateU16(_) | + Operand::ImmediateU32(_) | + Operand::ImmediateI32(_) | + Operand::ImmediateU64(_) | + Operand::ImmediateI64(_) | + Operand::Register(_) | + Operand::Nothing => { + false + } + } + } +} + +#[test] +fn operand_size() { + assert_eq!(core::mem::size_of::(), 1); + assert_eq!(core::mem::size_of::(), 2); + // assert_eq!(core::mem::size_of::(), 4); + // assert_eq!(core::mem::size_of::(), 40); +} + +#[allow(non_camel_case_types)] +#[cfg(feature="use-serde")] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub enum RegisterBank { + Q, D, W, B, rB, // Quadword, Dword, Word, Byte + CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... + X, Y, Z, // XMM, YMM, ZMM + ST, MM, // ST, MM regs (x87, mmx) + K, // AVX512 mask registers +} +#[allow(non_camel_case_types)] +#[cfg(not(feature="use-serde"))] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum RegisterBank { + Q, D, W, B, rB, // Quadword, Dword, Word, Byte + CR, DR, S, EIP, RIP, EFlags, RFlags, // Control reg, Debug reg, Selector, ... + X, Y, Z, // XMM, YMM, ZMM + ST, MM, // ST, MM regs (x87, mmx) + K, // AVX512 mask registers +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum Segment { + DS = 0, CS, ES, FS, GS, SS +} + +const BMI1: [Opcode; 6] = [ + Opcode::ANDN, + Opcode::BEXTR, + Opcode::BLSI, + Opcode::BLSMSK, + Opcode::BLSR, + Opcode::TZCNT, +]; + +// TODO: +// PTWRITE +// RDFSBASE +// RDGSBASE +// WRFSBASE +// WRGSBASE +// TPAUSE +// UMONITOR +// UMWAIT +// CLFLUSHOPT +// CLWB +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Opcode { + ADD = 1, + OR = 2, + ADC = 3, + SBB = 4, + AND = 5, + XOR = 6, + SUB = 7, + CMP = 8, + Invalid, + XADD, + BT, + BTS, + BTC, + BTR, + BSF, + BSR, + TZCNT, + MOVSS, + ADDSS, + SUBSS, + MULSS, + DIVSS, + MINSS, + MAXSS, + SQRTSS, + MOVSD, + SQRTSD, + ADDSD, + SUBSD, + MULSD, + DIVSD, + MINSD, + MAXSD, + MOVSLDUP, + MOVSHDUP, + MOVDDUP, + HADDPS, + HSUBPS, + ADDSUBPS, + CVTSI2SS, + CVTSI2SD, + CVTTSD2SI, + CVTTPS2DQ, + CVTPD2DQ, + CVTSD2SI, + CVTSD2SS, + CVTTSS2SI, + CVTSS2SI, + CVTSS2SD, + CVTDQ2PD, + LDDQU, + MOVSX_b, + MOVSX_w, + MOVZX_b, + MOVZX_w, + MOVSX, + MOVSXD, + SAR, + SAL, + SHR, + SHRD, + SHL, + RCR, + RCL, + ROR, + ROL, + INC, + DEC, + HLT, + CALL, + CALLF, + JMP, + JMPF, + PUSH, + POP, + LEA, + NOP, + PREFETCHNTA, + PREFETCH0, + PREFETCH1, + PREFETCH2, + XCHG, + POPF, + INT, + INTO, + IRET, + RETF, + ENTER, + LEAVE, + MOV, + RETURN, + PUSHF, + WAIT, + CBW, + CWDE, + CDQE, + CBD, + CDQ, + CQO, + LODS, + STOS, + LAHF, + SAHF, + CMPS, + SCAS, + MOVS, + TEST, + INS, + OUTS, + IMUL, + JO, + JNO, + JB, + JNB, + JZ, + JNZ, + JA, + JNA, + JS, + JNS, + JP, + JNP, + JL, + JGE, + JLE, + JG, + CMOVA, + CMOVB, + CMOVG, + CMOVGE, + CMOVL, + CMOVLE, + CMOVNA, + CMOVNB, + CMOVNO, + CMOVNP, + CMOVNS, + CMOVNZ, + CMOVO, + CMOVP, + CMOVS, + CMOVZ, + DIV, + IDIV, + MUL, + NEG, + NOT, + CMPXCHG, + SETO, + SETNO, + SETB, + SETAE, + SETZ, + SETNZ, + SETBE, + SETA, + SETS, + SETNS, + SETP, + SETNP, + SETL, + SETGE, + SETLE, + SETG, + CPUID, + UD2, + WBINVD, + INVD, + SYSRET, + CLTS, + SYSCALL, + LSL, + LAR, + SGDT, + SIDT, + LGDT, + LIDT, + SMSW, + LMSW, + SWAPGS, + RDTSCP, + INVLPG, + FXSAVE, + FXRSTOR, + LDMXCSR, + STMXCSR, + XSAVE, + XRSTOR, + XSAVEOPT, + LFENCE, + MFENCE, + SFENCE, + CLFLUSH, + WRMSR, + RDTSC, + RDMSR, + RDPMC, + SLDT, + STR, + LLDT, + LTR, + VERR, + VERW, + CLC, + STC, + CLI, + STI, + CLD, + STD, + JMPE, + POPCNT, + MOVDQU, + MOVDQA, + MOVQ, + CMPSS, + CMPSD, + UNPCKLPS, + UNPCKHPS, + PSHUFHW, + PSHUFLW, + MOVUPS, + MOVQ2DQ, + MOVDQ2Q, + RSQRTSS, + RCPSS, + + ANDN, + BEXTR, + BLSI, + BLSMSK, + BLSR, + VMCALL, + VMLAUNCH, + VMRESUME, + VMXOFF, + MONITOR, + MWAIT, + CLAC, + STAC, + ENCLS, + ENCLV, + XGETBV, + XSETBV, + VMFUNC, + XEND, + XTEST, + ENCLU, + RDPKRU, + WRPKRU, + + ADDPS, + ANDNPS, + ANDPS, + BSWAP, + CMPPS, + COMISS, + CVTDQ2PS, + CVTPI2PS, + CVTPI2PD, + CVTPS2PD, + CVTPS2PI, + CVTTPS2PI, + DIVPS, + EMMS, + GETSEC, + LFS, + LGS, + LSS, + MASKMOVQ, + MAXPS, + MINPS, + MOVAPS, + MOVAPD, + MOVD, + MOVLPS, + MOVHPS, + MOVLHPS, + MOVHLPS, + MOVUPD, + MOVMSKPS, + MOVNTI, + MOVNTPS, + MOVNTQ, + MULPS, + ORPS, + PACKSSDW, + PACKSSWB, + PACKUSWB, + PADDB, + PADDD, + PADDQ, + PADDSB, + PADDSW, + PADDUSB, + PADDUSW, + PADDW, + PAND, + PANDN, + PAVGB, + PAVGW, + PCMPEQB, + PCMPEQD, + PCMPEQW, + PCMPGTB, + PCMPGTD, + PCMPGTW, + PEXTRW, + PINSRW, + PMADDWD, + PMAXSW, + PMAXUB, + PMINSW, + PMINUB, + PMOVMSKB, + PMULHUW, + PMULHW, + PMULLW, + PMULUDQ, + POR, + PSADBW, + PSHUFW, + PSHUFD, + PSLLD, + PSLLDQ, + PSLLQ, + PSLLW, + PSRAD, + PSRAW, + PSRLD, + PSRLDQ, + PSRLQ, + PSRLW, + PSUBB, + PSUBD, + PSUBQ, + PSUBSB, + PSUBSW, + PSUBUSB, + PSUBUSW, + PSUBW, + PUNPCKHBW, + PUNPCKHDQ, + PUNPCKHWD, + PUNPCKLBW, + PUNPCKLDQ, + PUNPCKLWD, + PUNPCKLQDQ, + PUNPCKHQDQ, + PXOR, + RCPPS, + RSM, + RSQRTPS, + SHLD, + SHUFPS, + SLHD, + SQRTPS, + SUBPS, + SYSENTER, + SYSEXIT, + UCOMISS, + UD2E, + VMREAD, + VMWRITE, + XORPS, + + VMOVDDUP, + VPSHUFLW, + VHADDPS, + VHSUBPS, + VADDSUBPS, + VCVTPD2DQ, + VLDDQU, + + VCOMISD, + VCOMISS, + VUCOMISD, + VUCOMISS, + VADDPD, + VADDPS, + VADDSD, + VADDSS, + VADDSUBPD, + VAESDEC, + VAESDECLAST, + VAESENC, + VAESENCLAST, + VAESIMC, + VAESKEYGENASSIST, + VBLENDPD, + VBLENDPS, + VBLENDVPD, + VBLENDVPS, + VBROADCASTF128, + VBROADCASTI128, + VBROADCASTSD, + VBROADCASTSS, + VCMPSD, + VCMPSS, + VCMPPD, + VCMPPS, + VCVTDQ2PD, + VCVTDQ2PS, + VCVTPD2PS, + VCVTPH2PS, + VCVTPS2DQ, + VCVTPS2PD, + VCVTSS2SD, + VCVTSI2SS, + VCVTSI2SD, + VCVTSD2SI, + VCVTSD2SS, + VCVTPS2PH, + VCVTSS2SI, + VCVTTPD2DQ, + VCVTTPS2DQ, + VCVTTSS2SI, + VCVTTSD2SI, + VDIVPD, + VDIVPS, + VDIVSD, + VDIVSS, + VDPPD, + VDPPS, + VEXTRACTF128, + VEXTRACTI128, + VEXTRACTPS, + VFMADD132PD, + VFMADD132PS, + VFMADD132SD, + VFMADD132SS, + VFMADD213PD, + VFMADD213PS, + VFMADD213SD, + VFMADD213SS, + VFMADD231PD, + VFMADD231PS, + VFMADD231SD, + VFMADD231SS, + VFMADDSUB132PD, + VFMADDSUB132PS, + VFMADDSUB213PD, + VFMADDSUB213PS, + VFMADDSUB231PD, + VFMADDSUB231PS, + VFMSUB132PD, + VFMSUB132PS, + VFMSUB132SD, + VFMSUB132SS, + VFMSUB213PD, + VFMSUB213PS, + VFMSUB213SD, + VFMSUB213SS, + VFMSUB231PD, + VFMSUB231PS, + VFMSUB231SD, + VFMSUB231SS, + VFMSUBADD132PD, + VFMSUBADD132PS, + VFMSUBADD213PD, + VFMSUBADD213PS, + VFMSUBADD231PD, + VFMSUBADD231PS, + VFNMADD132PD, + VFNMADD132PS, + VFNMADD132SD, + VFNMADD132SS, + VFNMADD213PD, + VFNMADD213PS, + VFNMADD213SD, + VFNMADD213SS, + VFNMADD231PD, + VFNMADD231PS, + VFNMADD231SD, + VFNMADD231SS, + VFNMSUB132PD, + VFNMSUB132PS, + VFNMSUB132SD, + VFNMSUB132SS, + VFNMSUB213PD, + VFNMSUB213PS, + VFNMSUB213SD, + VFNMSUB213SS, + VFNMSUB231PD, + VFNMSUB231PS, + VFNMSUB231SD, + VFNMSUB231SS, + VGATHERDPD, + VGATHERDPS, + VGATHERQPD, + VGATHERQPS, + VHADDPD, + VHSUBPD, + VINSERTF128, + VINSERTI128, + VINSERTPS, + VMASKMOVDQU, + VMASKMOVPD, + VMASKMOVPS, + VMAXPD, + VMAXPS, + VMAXSD, + VMAXSS, + VMINPD, + VMINPS, + VMINSD, + VMINSS, + VMOVAPD, + VMOVAPS, + VMOVD, + VMOVDQA, + VMOVDQU, + VMOVHLPS, + VMOVHPD, + VMOVHPS, + VMOVLHPS, + VMOVLPD, + VMOVLPS, + VMOVMSKPD, + VMOVMSKPS, + VMOVNTDQ, + VMOVNTDQA, + VMOVNTPD, + VMOVNTPS, + VMOVQ, + VMOVSS, + VMOVSD, + VMOVSHDUP, + VMOVSLDUP, + VMOVUPD, + VMOVUPS, + VMPSADBW, + VMULPD, + VMULPS, + VMULSD, + VMULSS, + VPABSB, + VPABSD, + VPABSW, + VPACKSSDW, + VPACKSSWB, + VPACKUSWB, + VPADDB, + VPADDD, + VPADDQ, + VPADDSB, + VPADDSW, + VPADDUSB, + VPADDUSW, + VPADDW, + VPALIGNR, + VPAND, + VPANDN, + VPAVGB, + VPAVGW, + VPBLENDD, + VPBLENDVB, + VPBLENDW, + VPBROADCASTB, + VPBROADCASTD, + VPBROADCASTQ, + VPBROADCASTW, + VPCLMULQDQ, + VPCMPEQB, + VPCMPEQD, + VPCMPEQQ, + VPCMPEQW, + VPCMPGTB, + VPCMPGTD, + VPCMPGTQ, + VPCMPGTW, + VPCMPISTRI, + VPCMPISTRM, + VPERM2F128, + VPERM2I128, + VPERMD, + VPERMILPD, + VPERMILPS, + VPERMPD, + VPERMPS, + VPERMQ, + VPEXTRB, + VPEXTRD, + VPEXTRQ, + VPEXTRW, + VPGATHERDD, + VPGATHERDQ, + VPGATHERQD, + VPGATHERQQ, + VPHADDD, + VPHADDSW, + VPHADDW, + VPHADDUBSW, + VPHMINPOSUW, + VPHSUBD, + VPHSUBSW, + VPHSUBW, + VPINSRB, + VPINSRD, + VPINSRQ, + VPINSRW, + VPMADDWD, + VPMASKMOVD, + VPMASKMOVQ, + VPMAXSB, + VPMAXSD, + VPMAXSW, + VPMAXUD, + VPMINSD, + VPMINUD, + VPMOVMSKB, + VPMOVSXBD, + VPMOVSXBQ, + VPMOVSXBW, + VPMOVSXDQ, + VPMOVSXWD, + VPMOVSXWQ, + VPMOVZXBD, + VPMOVZXBQ, + VPMOVZXBW, + VPMOVZXDQ, + VPMOVZXWD, + VPMOVZXWQ, + VPMULDQ, + VPMULHRSW, + VPMULHUW, + VPMULHW, + VPMULLD, + VPMULLW, + VPMULUDQ, + VPOR, + VPSADBW, + VPSHUFB, + VPSHUFD, + VPSIGNB, + VPSIGND, + VPSIGNW, + VPSLLD, + VPSLLDQ, + VPSLLQ, + VPSLLVD, + VPSLLVQ, + VPSLLW, + VPSRAD, + VPSRAVD, + VPSRAW, + VPSRLD, + VPSRLDQ, + VPSRLQ, + VPSRLVD, + VPSRLVQ, + VPSRLW, + VPSUBB, + VPSUBD, + VPSUBQ, + VPSUBSB, + VPSUBSW, + VPSUBUSB, + VPSUBUSW, + VPSUBW, + VPTEST, + VPUNPCKHBW, + VPUNPCKHDQ, + VPUNPCKHQDQ, + VPUNPCKHWD, + VPUNPCKLBW, + VPUNPCKLDQ, + VPUNPCKLQDQ, + VPUNPCKLWD, + VPXOR, + VRCPPS, + VROUNDPD, + VROUNDPS, + VROUNDSD, + VROUNDSS, + VRSQRTPS, + VRSQRTSS, + VRCPSS, + VSHUFPD, + VSHUFPS, + VSQRTPD, + VSQRTPS, + VSQRTSS, + VSQRTSD, + VSUBPD, + VSUBPS, + VSUBSD, + VSUBSS, + VTESTPD, + VTESTPS, + VUNPCKHPD, + VUNPCKHPS, + VUNPCKLPD, + VUNPCKLPS, + VXORPD, + VXORPS, + VZEROUPPER, + + PCLMULQDQ, + AESKEYGENASSIST, + AESIMC, + AESENC, + AESENCLAST, + AESDEC, + AESDECLAST, + PCMPGTQ, + PCMPISTRM, + PCMPISTRI, + PCMPESTRI, + PACKUSDW, + PCMPESTRM, + PCMPEQQ, + PTEST, + PHMINPOSUW, + MPSADBW, + PMOVZXDQ, + PMOVSXDQ, + PMOVZXBD, + PMOVSXBD, + PMOVZXWQ, + PMOVSXWQ, + PMOVZXBQ, + PMOVSXBQ, + PMOVSXWD, + PMOVZXWD, + PEXTRQ, + PEXTRB, + PMOVSXBW, + PMOVZXBW, + PINSRQ, + PINSRD, + PINSRB, + EXTRACTPS, + INSERTPS, + ROUNDSS, + ROUNDSD, + ROUNDPS, + ROUNDPD, + PMAXSB, + PMAXUW, + PMAXUD, + PMINSD, + PMINSB, + PMINUD, + PMINUW, + BLENDW, + BLENDDVB, + BLENDVPS, + BLENDVPD, + BLENDPS, + BLENDPD, + PMULDQ, + MOVNTDQA, + PMULLD, + PALIGNR, + PSIGNW, + PSIGND, + PSIGNB, + PSHUFB, + PMULHRSU, + PMADDUBSW, + PABSD, + PABSW, + PABSB, + PHSUBSW, + PHSUBW, + PHSUBD, + PHADDD, + PHADDSW, + PHADDW, + HSUBPD, + HADDPD, + ADDSUBPD, +} + +#[derive(Debug)] +pub struct Instruction { + pub prefixes: Prefixes, + modrm_rrr: RegSpec, + modrm_mmm: RegSpec, // doubles as sib_base + sib_index: RegSpec, + vex_reg: RegSpec, + scale: u8, + length: u8, + operand_count: u8, + operands: [OperandSpec; 4], + imm: u64, + disp: u64, + pub opcode: Opcode, +} + +impl yaxpeax_arch::Instruction for Instruction { + fn well_defined(&self) -> bool { + // TODO: this is incorrect! + true + } +} + +#[derive(Debug, PartialEq)] +pub enum DecodeError { + ExhaustedInput, + InvalidOpcode, + InvalidOperand, + InvalidPrefixes, + TooLong, + IncompleteDecoder, +} + +impl yaxpeax_arch::DecodeError for DecodeError { + fn data_exhausted(&self) -> bool { self == &DecodeError::ExhaustedInput } + fn bad_opcode(&self) -> bool { self == &DecodeError::InvalidOpcode } + fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand } +} + +#[allow(non_camel_case_types)] +#[derive(Debug, Copy, Clone, PartialEq)] +enum OperandSpec { + Nothing, + // the register in modrm_rrr + RegRRR, + // the register in modrm_mmm (eg modrm mod bits were 11) + RegMMM, + // the register selected by vex-vvvv bits + RegVex, + // the register `al`. Used for MOVS. + AL, + // the register `cl`. Used for SHLD and SHRD. + CL, + ImmI8, + ImmI16, + ImmI32, + ImmI64, + ImmU8, + ImmU16, + ImmU32, + ImmU64, + DispU32, + DispU64, + Deref, + Deref_rsi, + Deref_rdi, + RegDisp, + RegScale, + RegIndexBase, + RegIndexBaseDisp, + RegScaleDisp, + RegIndexBaseScale, + RegIndexBaseScaleDisp +} + +// the Hash, Eq, and PartialEq impls here are possibly misleading. +// They exist because downstream some structs are spelled like +// Foo for T == x86_64. This is only to access associated types +// which themselves are bounded, but their #[derive] require T to +// implement these traits. +#[cfg(feature="use-serde")] +#[derive(Hash, Eq, PartialEq, Debug, Serialize, Deserialize)] +#[allow(non_camel_case_types)] +pub struct Arch; + +#[cfg(not(feature="use-serde"))] +#[derive(Hash, Eq, PartialEq, Debug)] +#[allow(non_camel_case_types)] +pub struct Arch; + +impl yaxpeax_arch::Arch for Arch { + type Address = u64; + type Instruction = Instruction; + type DecodeError = DecodeError; + type Decoder = InstDecoder; + type Operand = Operand; +} + +impl LengthedInstruction for Instruction { + type Unit = u64; + fn len(&self) -> u64 { + self.length.into() + } + fn min_size() -> u64 { + 1 + } +} + +#[derive(PartialEq)] +pub struct InstDecoder { + // extensions tracked here: + // 0. SSE3 + // 1. SSSE3 + // 2. monitor (intel-only?) + // 3. vmx (some atom chips still lack it) + // 4. fma3 (intel haswell/broadwell+, amd piledriver+) + // 5. cmpxchg16b (some amd are missingt this one) + // 6. sse4.1 + // 7. sse4.2 + // 8. movbe + // 9. popcnt (independent of BMI) + // 10. aesni + // 11. xsave (xsave, xrestor, xsetbv, xgetbv) + // 12. rdrand (intel ivybridge+, amd ..??) + // 13. sgx (eadd, eblock, ecreate, edbgrd, edbgwr, einit, eldb, eldu, epa, eremove, etrace, + // ewb, eenter, eexit, egetkey, ereport, eresume) + // 14. bmi1 (intel haswell+, amd jaguar+) + // 15. avx2 (intel haswell+, amd excavator+) + // 16. bmi2 (intel ?, amd ?) + // 17. invpcid + // 18. mpx + // 19. avx512_f + // 20. avx512_dq + // 21. rdseed + // 22. adx + // 23. avx512_fma + // 24. pcommit + // 25. clflushopt + // 26. clwb + // 27. avx512_pf + // 28. avx512_er + // 29. avx512_cd + // 30. sha + // 31. avx512_bw + // 32. avx512_vl + // 33. prefetchwt1 + // 34. avx512_vbmi + // 35. avx512_vbmi2 + // 36. gfni (galois field instructions) + // 37. vaes + // 38. pclmulqdq + // 39. avx_vnni + // 40. avx512_bitalg + // 41. avx512_vpopcntdq + // 42. avx512_4vnniw + // 43. avx512_4fmaps + // 44. cx8 // cmpxchg8 - is this actually optional in x86_64? + // 45. syscall // syscall/sysret - actually optional in x86_64? + // 46. rdtscp // actually optional in x86_64? + // 47. abm (lzcnt, popcnt) + // 48. sse4a + // 49. 3dnowprefetch // actually optional? + // 50. xop + // 51. skinit + // 52. tbm + // 53. intel quirks + // 54. amd quirks + // 55. avx (intel ?, amd ?) + flags: u64, +} + +impl InstDecoder { + /// Instantiates an x86_64 decoder that decodes the bare minimum of x86_64. + /// + /// Pedantic and only decodes what the spec says is well-defined, rejecting undefined sequences + /// and any instructions defined by extensions. + pub fn minimal() -> Self { + InstDecoder { + flags: 0, + } + } + + pub fn sse3(&self) -> bool { + self.flags & (1 << 0) != 0 + } + + pub fn with_sse3(mut self) -> Self { + self.flags |= 1 << 0; + self + } + + pub fn ssse3(&self) -> bool { + self.flags & (1 << 1) != 0 + } + + pub fn with_ssse3(mut self) -> Self { + self.flags |= 1 << 1; + self + } + + pub fn monitor(&self) -> bool { + self.flags & (1 << 2) != 0 + } + + pub fn with_monitor(mut self) -> Self { + self.flags |= 1 << 2; + self + } + + pub fn vmx(&self) -> bool { + self.flags & (1 << 3) != 0 + } + + pub fn with_vmx(mut self) -> Self { + self.flags |= 1 << 3; + self + } + + pub fn fma3(&self) -> bool { + self.flags & (1 << 4) != 0 + } + + pub fn with_fma3(mut self) -> Self { + self.flags |= 1 << 4; + self + } + + pub fn cmpxchg16b(&self) -> bool { + self.flags & (1 << 5) != 0 + } + + pub fn with_cmpxchg16b(mut self) -> Self { + self.flags |= 1 << 5; + self + } + + pub fn sse4_1(&self) -> bool { + self.flags & (1 << 6) != 0 + } + + pub fn with_sse4_1(mut self) -> Self { + self.flags |= 1 << 6; + self + } + + pub fn sse4_2(&self) -> bool { + self.flags & (1 << 7) != 0 + } + + pub fn with_sse4_2(mut self) -> Self { + self.flags |= 1 << 7; + self + } + + pub fn movbe(&self) -> bool { + self.flags & (1 << 8) != 0 + } + + pub fn with_movbe(mut self) -> Self { + self.flags |= 1 << 8; + self + } + + pub fn popcnt(&self) -> bool { + self.flags & (1 << 9) != 0 + } + + pub fn with_popcnt(mut self) -> Self { + self.flags |= 1 << 9; + self + } + + pub fn aesni(&self) -> bool { + self.flags & (1 << 10) != 0 + } + + pub fn with_aesni(mut self) -> Self { + self.flags |= 1 << 10; + self + } + + pub fn xsave(&self) -> bool { + self.flags & (1 << 11) != 0 + } + + pub fn with_xsave(mut self) -> Self { + self.flags |= 1 << 11; + self + } + + pub fn rdrand(&self) -> bool { + self.flags & (1 << 12) != 0 + } + + pub fn with_rdrand(mut self) -> Self { + self.flags |= 1 << 12; + self + } + + pub fn sgx(&self) -> bool { + self.flags & (1 << 13) != 0 + } + + pub fn with_sgx(mut self) -> Self { + self.flags |= 1 << 13; + self + } + + pub fn bmi1(&self) -> bool { + self.flags & (1 << 14) != 0 + } + + pub fn with_bmi1(mut self) -> Self { + self.flags |= 1 << 14; + self + } + + pub fn avx2(&self) -> bool { + self.flags & (1 << 15) != 0 + } + + pub fn with_avx2(mut self) -> Self { + self.flags |= 1 << 15; + self + } + + pub fn bmi2(&self) -> bool { + self.flags & (1 << 16) != 0 + } + + pub fn with_bmi2(mut self) -> Self { + self.flags |= 1 << 16; + self + } + + pub fn invpcid(&self) -> bool { + self.flags & (1 << 17) != 0 + } + + pub fn with_invpcid(mut self) -> Self { + self.flags |= 1 << 17; + self + } + + pub fn mpx(&self) -> bool { + self.flags & (1 << 18) != 0 + } + + pub fn with_mpx(mut self) -> Self { + self.flags |= 1 << 18; + self + } + + pub fn avx512_f(&self) -> bool { + self.flags & (1 << 19) != 0 + } + + pub fn with_avx512_f(mut self) -> Self { + self.flags |= 1 << 19; + self + } + + pub fn avx512_dq(&self) -> bool { + self.flags & (1 << 20) != 0 + } + + pub fn with_avx512_dq(mut self) -> Self { + self.flags |= 1 << 20; + self + } + + pub fn rdseed(&self) -> bool { + self.flags & (1 << 21) != 0 + } + + pub fn with_rdseed(mut self) -> Self { + self.flags |= 1 << 21; + self + } + + pub fn adx(&self) -> bool { + self.flags & (1 << 22) != 0 + } + + pub fn with_adx(mut self) -> Self { + self.flags |= 1 << 22; + self + } + + pub fn avx512_fma(&self) -> bool { + self.flags & (1 << 23) != 0 + } + + pub fn with_avx512_fma(mut self) -> Self { + self.flags |= 1 << 23; + self + } + + pub fn pcommit(&self) -> bool { + self.flags & (1 << 24) != 0 + } + + pub fn with_pcommit(mut self) -> Self { + self.flags |= 1 << 24; + self + } + + pub fn clflushopt(&self) -> bool { + self.flags & (1 << 25) != 0 + } + + pub fn with_clflushopt(mut self) -> Self { + self.flags |= 1 << 25; + self + } + + pub fn clwb(&self) -> bool { + self.flags & (1 << 26) != 0 + } + + pub fn with_clwb(mut self) -> Self { + self.flags |= 1 << 26; + self + } + + pub fn avx512_pf(&self) -> bool { + self.flags & (1 << 27) != 0 + } + + pub fn with_avx512_pf(mut self) -> Self { + self.flags |= 1 << 27; + self + } + + pub fn avx512_er(&self) -> bool { + self.flags & (1 << 28) != 0 + } + + pub fn with_avx512_er(mut self) -> Self { + self.flags |= 1 << 28; + self + } + + pub fn avx512_cd(&self) -> bool { + self.flags & (1 << 29) != 0 + } + + pub fn with_avx512_cd(mut self) -> Self { + self.flags |= 1 << 29; + self + } + + pub fn sha(&self) -> bool { + self.flags & (1 << 30) != 0 + } + + pub fn with_sha(mut self) -> Self { + self.flags |= 1 << 30; + self + } + + pub fn avx512_bw(&self) -> bool { + self.flags & (1 << 31) != 0 + } + + pub fn with_avx512_bw(mut self) -> Self { + self.flags |= 1 << 31; + self + } + + pub fn avx512_vl(&self) -> bool { + self.flags & (1 << 32) != 0 + } + + pub fn with_avx512_vl(mut self) -> Self { + self.flags |= 1 << 32; + self + } + + pub fn prefetchwt1(&self) -> bool { + self.flags & (1 << 33) != 0 + } + + pub fn with_prefetchwt1(mut self) -> Self { + self.flags |= 1 << 33; + self + } + + pub fn avx512_vbmi(&self) -> bool { + self.flags & (1 << 34) != 0 + } + + pub fn with_avx512_vbmi(mut self) -> Self { + self.flags |= 1 << 34; + self + } + + pub fn avx512_vbmi2(&self) -> bool { + self.flags & (1 << 35) != 0 + } + + pub fn with_avx512_vbmi2(mut self) -> Self { + self.flags |= 1 << 35; + self + } + + pub fn gfni(&self) -> bool { + self.flags & (1 << 36) != 0 + } + + pub fn with_gfni(mut self) -> Self { + self.flags |= 1 << 36; + self + } + + pub fn vaes(&self) -> bool { + self.flags & (1 << 37) != 0 + } + + pub fn with_vaes(mut self) -> Self { + self.flags |= 1 << 37; + self + } + + pub fn pclmulqdq(&self) -> bool { + self.flags & (1 << 38) != 0 + } + + pub fn with_pclmulqdq(mut self) -> Self { + self.flags |= 1 << 38; + self + } + + pub fn avx_vnni(&self) -> bool { + self.flags & (1 << 39) != 0 + } + + pub fn with_avx_vnni(mut self) -> Self { + self.flags |= 1 << 39; + self + } + + pub fn avx512_bitalg(&self) -> bool { + self.flags & (1 << 40) != 0 + } + + pub fn with_avx512_bitalg(mut self) -> Self { + self.flags |= 1 << 40; + self + } + + pub fn avx512_vpopcntdq(&self) -> bool { + self.flags & (1 << 41) != 0 + } + + pub fn with_avx512_vpopcntdq(mut self) -> Self { + self.flags |= 1 << 41; + self + } + + pub fn avx512_4vnniw(&self) -> bool { + self.flags & (1 << 42) != 0 + } + + pub fn with_avx512_4vnniw(mut self) -> Self { + self.flags |= 1 << 42; + self + } + + pub fn avx512_4fmaps(&self) -> bool { + self.flags & (1 << 43) != 0 + } + + pub fn with_avx512_4fmaps(mut self) -> Self { + self.flags |= 1 << 43; + self + } + + pub fn cx8(&self) -> bool { + self.flags & (1 << 44) != 0 + } + + pub fn with_cx8(mut self) -> Self { + self.flags |= 1 << 44; + self + } + + pub fn syscall(&self) -> bool { + self.flags & (1 << 45) != 0 + } + + pub fn with_syscall(mut self) -> Self { + self.flags |= 1 << 45; + self + } + + pub fn rdtscp(&self) -> bool { + self.flags & (1 << 46) != 0 + } + + pub fn with_rdtscp(mut self) -> Self { + self.flags |= 1 << 46; + self + } + + pub fn abm(&self) -> bool { + self.flags & (1 << 47) != 0 + } + + pub fn with_abm(mut self) -> Self { + self.flags |= 1 << 47; + self + } + + pub fn sse4a(&self) -> bool { + self.flags & (1 << 48) != 0 + } + + pub fn with_sse4a(mut self) -> Self { + self.flags |= 1 << 48; + self + } + + pub fn _3dnowprefetch(&self) -> bool { + self.flags & (1 << 49) != 0 + } + + pub fn with_3dnowprefetch(mut self) -> Self { + self.flags |= 1 << 49; + self + } + + pub fn xop(&self) -> bool { + self.flags & (1 << 50) != 0 + } + + pub fn with_xop(mut self) -> Self { + self.flags |= 1 << 50; + self + } + + pub fn skinit(&self) -> bool { + self.flags & (1 << 51) != 0 + } + + pub fn with_skinit(mut self) -> Self { + self.flags |= 1 << 51; + self + } + + pub fn tbm(&self) -> bool { + self.flags & (1 << 52) != 0 + } + + pub fn with_tbm(mut self) -> Self { + self.flags |= 1 << 52; + self + } + + pub fn intel_quirks(&self) -> bool { + self.flags & (1 << 53) != 0 + } + + pub fn with_intel_quirks(mut self) -> Self { + self.flags |= 1 << 53; + self + } + + pub fn amd_quirks(&self) -> bool { + self.flags & (1 << 54) != 0 + } + + pub fn with_amd_quirks(mut self) -> Self { + self.flags |= 1 << 54; + self + } + + pub fn avx(&self) -> bool { + self.flags & (1 << 55) != 0 + } + + pub fn with_avx(mut self) -> Self { + self.flags |= 1 << 55; + self + } + + /// Optionally reject or reinterpret instruction according to the decoder's + /// declared extensions. + fn revise_instruction(&self, inst: &mut Instruction) -> Result<(), DecodeError> { + match inst.opcode { + Opcode::TZCNT => { + if !self.bmi1() { + // tzcnt is only supported if bmi1 is enabled. without bmi1, this decodes as + // bsf. + inst.opcode = Opcode::BSF; + } + } + Opcode::LDDQU | + Opcode::ADDSUBPS | + Opcode::ADDSUBPD | + Opcode::HADDPS | + Opcode::HSUBPS | + Opcode::HADDPD | + Opcode::HSUBPD | + Opcode::MOVSHDUP | + Opcode::MOVSLDUP | + Opcode::MOVDDUP | + Opcode::MONITOR | + Opcode::MWAIT => { + // via Intel section 5.7, SSE3 Instructions + if !self.sse3() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::PHADDW | + Opcode::PHADDSW | + Opcode::PHADDD | + Opcode::PHSUBW | + Opcode::PHSUBSW | + Opcode::PHSUBD | + Opcode::PABSB | + Opcode::PABSW | + Opcode::PABSD | + Opcode::PMADDUBSW | + Opcode::PMULHRSU | + Opcode::PSHUFB | + Opcode::PSIGNB | + Opcode::PSIGNW | + Opcode::PSIGND | + Opcode::PALIGNR => { + // via Intel section 5.8, SSSE3 Instructions + if !self.ssse3() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::PMULLD | + Opcode::PMULDQ | + Opcode::MOVNTDQA | + Opcode::BLENDPD | + Opcode::BLENDPS | + Opcode::BLENDVPD | + Opcode::BLENDVPS | + Opcode::BLENDDVB | + Opcode::BLENDW | + Opcode::PMINUW | + Opcode::PMINUD | + Opcode::PMINSB | + Opcode::PMINSD | + Opcode::PMAXUW | + Opcode::PMAXUD | + Opcode::PMAXSB | + Opcode::ROUNDPS | + Opcode::ROUNDPD | + Opcode::ROUNDSS | + Opcode::ROUNDSD | + Opcode::EXTRACTPS | + Opcode::INSERTPS | + Opcode::PINSRB | + Opcode::PINSRD | + Opcode::PINSRQ | + Opcode::PEXTRB | + Opcode::PEXTRW | + Opcode::PEXTRQ | + Opcode::PMOVSXBW | + Opcode::PMOVZXBW | + Opcode::PMOVSXBD | + Opcode::PMOVZXBD | + Opcode::PMOVSXWD | + Opcode::PMOVZXWD | + Opcode::PMOVSXBQ | + Opcode::PMOVZXBQ | + Opcode::PMOVSXWQ | + Opcode::PMOVZXWQ | + Opcode::PMOVSXDQ | + Opcode::PMOVZXDQ | + Opcode::MPSADBW | + Opcode::PHMINPOSUW | + Opcode::PTEST | + Opcode::PCMPEQQ | + Opcode::PACKUSDW => { + // via Intel section 5.10, SSE4.1 Instructions + if !self.sse4_1() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::PCMPESTRI | + Opcode::PCMPESTRM | + Opcode::PCMPISTRI | + Opcode::PCMPISTRM | + Opcode::PCMPGTQ => { + // via Intel section 5.11, SSE4.2 Instructions + if !self.sse4_2() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::AESDEC | + Opcode::AESDECLAST | + Opcode::AESENC | + Opcode::AESENCLAST | + Opcode::AESIMC | + Opcode::AESKEYGENASSIST => { + // via Intel section 5.12. AESNI AND PCLMULQDQ + if !self.aesni() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::PCLMULQDQ => { + // via Intel section 5.12. AESNI AND PCLMULQDQ + if !self.pclmulqdq() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + // AVX... + /* // TODO + Opcode::XABORT | + Opcode::XACQUIRE | + Opcode::XRELEASE | + Opcode::XBEGIN | + Opcode::XEND | + Opcode::XTEST => { + if !self.tsx() { + inst.opcode = Opcode::Invalid; + return Err(()); + } + } + */ + /* // TODO + Opcode::SHA1MSG1 | + Opcode::SHA1MSG2 | + Opcode::SHA1NEXTE | + Opcode::SHA1RNDS4 | + Opcode::SHA256MSG1 | + Opcode::SHA256MSG2 | + Opcode::SHA256RNDS2 => { + if !self.sha() { + inst.opcode = Opcode::Invalid; + return Err(()); + } + }*/ + Opcode::ENCLV | + Opcode::ENCLS | + Opcode::ENCLU => { + if !self.sgx() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::VMOVDDUP | + Opcode::VPSHUFLW | + Opcode::VHADDPS | + Opcode::VHSUBPS | + Opcode::VADDSUBPS | + Opcode::VCVTPD2DQ | + Opcode::VLDDQU | + Opcode::VCOMISD | + Opcode::VCOMISS | + Opcode::VUCOMISD | + Opcode::VUCOMISS | + Opcode::VADDPD | + Opcode::VADDPS | + Opcode::VADDSD | + Opcode::VADDSS | + Opcode::VADDSUBPD | + Opcode::VBLENDPD | + Opcode::VBLENDPS | + Opcode::VBLENDVPD | + Opcode::VBLENDVPS | + Opcode::VBROADCASTF128 | + Opcode::VBROADCASTI128 | + Opcode::VBROADCASTSD | + Opcode::VBROADCASTSS | + Opcode::VCMPSD | + Opcode::VCMPSS | + Opcode::VCMPPD | + Opcode::VCMPPS | + Opcode::VCVTDQ2PD | + Opcode::VCVTDQ2PS | + Opcode::VCVTPD2PS | + Opcode::VCVTPH2PS | + Opcode::VCVTPS2DQ | + Opcode::VCVTPS2PD | + Opcode::VCVTSS2SD | + Opcode::VCVTSI2SS | + Opcode::VCVTSI2SD | + Opcode::VCVTSD2SI | + Opcode::VCVTSD2SS | + Opcode::VCVTPS2PH | + Opcode::VCVTSS2SI | + Opcode::VCVTTPD2DQ | + Opcode::VCVTTPS2DQ | + Opcode::VCVTTSS2SI | + Opcode::VCVTTSD2SI | + Opcode::VDIVPD | + Opcode::VDIVPS | + Opcode::VDIVSD | + Opcode::VDIVSS | + Opcode::VDPPD | + Opcode::VDPPS | + Opcode::VEXTRACTF128 | + Opcode::VEXTRACTI128 | + Opcode::VEXTRACTPS | + Opcode::VFMADD132PD | + Opcode::VFMADD132PS | + Opcode::VFMADD132SD | + Opcode::VFMADD132SS | + Opcode::VFMADD213PD | + Opcode::VFMADD213PS | + Opcode::VFMADD213SD | + Opcode::VFMADD213SS | + Opcode::VFMADD231PD | + Opcode::VFMADD231PS | + Opcode::VFMADD231SD | + Opcode::VFMADD231SS | + Opcode::VFMADDSUB132PD | + Opcode::VFMADDSUB132PS | + Opcode::VFMADDSUB213PD | + Opcode::VFMADDSUB213PS | + Opcode::VFMADDSUB231PD | + Opcode::VFMADDSUB231PS | + Opcode::VFMSUB132PD | + Opcode::VFMSUB132PS | + Opcode::VFMSUB132SD | + Opcode::VFMSUB132SS | + Opcode::VFMSUB213PD | + Opcode::VFMSUB213PS | + Opcode::VFMSUB213SD | + Opcode::VFMSUB213SS | + Opcode::VFMSUB231PD | + Opcode::VFMSUB231PS | + Opcode::VFMSUB231SD | + Opcode::VFMSUB231SS | + Opcode::VFMSUBADD132PD | + Opcode::VFMSUBADD132PS | + Opcode::VFMSUBADD213PD | + Opcode::VFMSUBADD213PS | + Opcode::VFMSUBADD231PD | + Opcode::VFMSUBADD231PS | + Opcode::VFNMADD132PD | + Opcode::VFNMADD132PS | + Opcode::VFNMADD132SD | + Opcode::VFNMADD132SS | + Opcode::VFNMADD213PD | + Opcode::VFNMADD213PS | + Opcode::VFNMADD213SD | + Opcode::VFNMADD213SS | + Opcode::VFNMADD231PD | + Opcode::VFNMADD231PS | + Opcode::VFNMADD231SD | + Opcode::VFNMADD231SS | + Opcode::VFNMSUB132PD | + Opcode::VFNMSUB132PS | + Opcode::VFNMSUB132SD | + Opcode::VFNMSUB132SS | + Opcode::VFNMSUB213PD | + Opcode::VFNMSUB213PS | + Opcode::VFNMSUB213SD | + Opcode::VFNMSUB213SS | + Opcode::VFNMSUB231PD | + Opcode::VFNMSUB231PS | + Opcode::VFNMSUB231SD | + Opcode::VFNMSUB231SS | + Opcode::VGATHERDPD | + Opcode::VGATHERDPS | + Opcode::VGATHERQPD | + Opcode::VGATHERQPS | + Opcode::VHADDPD | + Opcode::VHSUBPD | + Opcode::VINSERTF128 | + Opcode::VINSERTI128 | + Opcode::VINSERTPS | + Opcode::VMASKMOVDQU | + Opcode::VMASKMOVPD | + Opcode::VMASKMOVPS | + Opcode::VMAXPD | + Opcode::VMAXPS | + Opcode::VMAXSD | + Opcode::VMAXSS | + Opcode::VMINPD | + Opcode::VMINPS | + Opcode::VMINSD | + Opcode::VMINSS | + Opcode::VMOVAPD | + Opcode::VMOVAPS | + Opcode::VMOVD | + Opcode::VMOVDQA | + Opcode::VMOVDQU | + Opcode::VMOVHLPS | + Opcode::VMOVHPD | + Opcode::VMOVHPS | + Opcode::VMOVLHPS | + Opcode::VMOVLPD | + Opcode::VMOVLPS | + Opcode::VMOVMSKPD | + Opcode::VMOVMSKPS | + Opcode::VMOVNTDQ | + Opcode::VMOVNTDQA | + Opcode::VMOVNTPD | + Opcode::VMOVNTPS | + Opcode::VMOVQ | + Opcode::VMOVSS | + Opcode::VMOVSD | + Opcode::VMOVSHDUP | + Opcode::VMOVSLDUP | + Opcode::VMOVUPD | + Opcode::VMOVUPS | + Opcode::VMPSADBW | + Opcode::VMULPD | + Opcode::VMULPS | + Opcode::VMULSD | + Opcode::VMULSS | + Opcode::VPABSB | + Opcode::VPABSD | + Opcode::VPABSW | + Opcode::VPACKSSDW | + Opcode::VPACKSSWB | + Opcode::VPACKUSWB | + Opcode::VPADDB | + Opcode::VPADDD | + Opcode::VPADDQ | + Opcode::VPADDSB | + Opcode::VPADDSW | + Opcode::VPADDUSB | + Opcode::VPADDUSW | + Opcode::VPADDW | + Opcode::VPALIGNR | + Opcode::VPAND | + Opcode::VPANDN | + Opcode::VPAVGB | + Opcode::VPAVGW | + Opcode::VPBLENDD | + Opcode::VPBLENDVB | + Opcode::VPBLENDW | + Opcode::VPBROADCASTB | + Opcode::VPBROADCASTD | + Opcode::VPBROADCASTQ | + Opcode::VPBROADCASTW | + Opcode::VPCLMULQDQ | + Opcode::VPCMPEQB | + Opcode::VPCMPEQD | + Opcode::VPCMPEQQ | + Opcode::VPCMPEQW | + Opcode::VPCMPGTB | + Opcode::VPCMPGTD | + Opcode::VPCMPGTQ | + Opcode::VPCMPGTW | + Opcode::VPCMPISTRI | + Opcode::VPCMPISTRM | + Opcode::VPERM2F128 | + Opcode::VPERM2I128 | + Opcode::VPERMD | + Opcode::VPERMILPD | + Opcode::VPERMILPS | + Opcode::VPERMPD | + Opcode::VPERMPS | + Opcode::VPERMQ | + Opcode::VPEXTRB | + Opcode::VPEXTRD | + Opcode::VPEXTRQ | + Opcode::VPEXTRW | + Opcode::VPGATHERDD | + Opcode::VPGATHERDQ | + Opcode::VPGATHERQD | + Opcode::VPGATHERQQ | + Opcode::VPHADDD | + Opcode::VPHADDSW | + Opcode::VPHADDW | + Opcode::VPHADDUBSW | + Opcode::VPHMINPOSUW | + Opcode::VPHSUBD | + Opcode::VPHSUBSW | + Opcode::VPHSUBW | + Opcode::VPINSRB | + Opcode::VPINSRD | + Opcode::VPINSRQ | + Opcode::VPINSRW | + Opcode::VPMADDWD | + Opcode::VPMASKMOVD | + Opcode::VPMASKMOVQ | + Opcode::VPMAXSB | + Opcode::VPMAXSD | + Opcode::VPMAXSW | + Opcode::VPMAXUD | + Opcode::VPMINSD | + Opcode::VPMINUD | + Opcode::VPMOVMSKB | + Opcode::VPMOVSXBD | + Opcode::VPMOVSXBQ | + Opcode::VPMOVSXBW | + Opcode::VPMOVSXDQ | + Opcode::VPMOVSXWD | + Opcode::VPMOVSXWQ | + Opcode::VPMOVZXBD | + Opcode::VPMOVZXBQ | + Opcode::VPMOVZXBW | + Opcode::VPMOVZXDQ | + Opcode::VPMOVZXWD | + Opcode::VPMOVZXWQ | + Opcode::VPMULDQ | + Opcode::VPMULHRSW | + Opcode::VPMULHUW | + Opcode::VPMULHW | + Opcode::VPMULLD | + Opcode::VPMULLW | + Opcode::VPMULUDQ | + Opcode::VPOR | + Opcode::VPSADBW | + Opcode::VPSHUFB | + Opcode::VPSHUFD | + Opcode::VPSIGNB | + Opcode::VPSIGND | + Opcode::VPSIGNW | + Opcode::VPSLLD | + Opcode::VPSLLDQ | + Opcode::VPSLLQ | + Opcode::VPSLLVD | + Opcode::VPSLLVQ | + Opcode::VPSLLW | + Opcode::VPSRAD | + Opcode::VPSRAVD | + Opcode::VPSRAW | + Opcode::VPSRLD | + Opcode::VPSRLDQ | + Opcode::VPSRLQ | + Opcode::VPSRLVD | + Opcode::VPSRLVQ | + Opcode::VPSRLW | + Opcode::VPSUBB | + Opcode::VPSUBD | + Opcode::VPSUBQ | + Opcode::VPSUBSB | + Opcode::VPSUBSW | + Opcode::VPSUBUSB | + Opcode::VPSUBUSW | + Opcode::VPSUBW | + Opcode::VPTEST | + Opcode::VPUNPCKHBW | + Opcode::VPUNPCKHDQ | + Opcode::VPUNPCKHQDQ | + Opcode::VPUNPCKHWD | + Opcode::VPUNPCKLBW | + Opcode::VPUNPCKLDQ | + Opcode::VPUNPCKLQDQ | + Opcode::VPUNPCKLWD | + Opcode::VPXOR | + Opcode::VRCPPS | + Opcode::VROUNDPD | + Opcode::VROUNDPS | + Opcode::VROUNDSD | + Opcode::VROUNDSS | + Opcode::VRSQRTPS | + Opcode::VRSQRTSS | + Opcode::VRCPSS | + Opcode::VSHUFPD | + Opcode::VSHUFPS | + Opcode::VSQRTPD | + Opcode::VSQRTPS | + Opcode::VSQRTSS | + Opcode::VSQRTSD | + Opcode::VSUBPD | + Opcode::VSUBPS | + Opcode::VSUBSD | + Opcode::VSUBSS | + Opcode::VTESTPD | + Opcode::VTESTPS | + Opcode::VUNPCKHPD | + Opcode::VUNPCKHPS | + Opcode::VUNPCKLPD | + Opcode::VUNPCKLPS | + Opcode::VXORPD | + Opcode::VXORPS | + Opcode::VZEROUPPER => { + // TODO: check a table for these + if !self.avx() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + Opcode::VAESDEC | + Opcode::VAESDECLAST | + Opcode::VAESENC | + Opcode::VAESENCLAST | + Opcode::VAESIMC | + Opcode::VAESKEYGENASSIST => { + // TODO: check a table for these + if !self.avx() || !self.aesni() { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + other => { + if !self.bmi1() { + if BMI1.contains(&other) { + return Err(DecodeError::InvalidOpcode); + } + } + } + } + Ok(()) + } +} + +impl Default for InstDecoder { + /// Instantiates an x86_64 decoder that probably decodes what you want. + /// + /// Attempts to match real processors in interpretation of undefined sequences, and decodes any + /// instruction defined in any extension. + fn default() -> Self { + Self { + flags: 0xffffffff_ffffffff, + } + } +} + +impl Decoder for InstDecoder { + type Error = DecodeError; + + fn decode>(&self, bytes: T) -> Result { + let mut instr = Instruction::invalid(); + decode_one(self, bytes, &mut instr) + .map(|_: ()| instr) + } + fn decode_into>(&self, instr: &mut Instruction, bytes: T) -> Result<(), Self::Error> { + decode_one(self, bytes, instr) + } +} + +impl Opcode { + pub fn condition(&self) -> Option { + match self { + Opcode::JO | + Opcode::CMOVO | + Opcode::SETO => { Some(ConditionCode::O) }, + Opcode::JNO | + Opcode::CMOVNO | + Opcode::SETNO => { Some(ConditionCode::NO) }, + Opcode::JB | + Opcode::CMOVB | + Opcode::SETB => { Some(ConditionCode::B) }, + Opcode::JNB | + Opcode::CMOVNB | + Opcode::SETAE => { Some(ConditionCode::AE) }, + Opcode::JZ | + Opcode::CMOVZ | + Opcode::SETZ => { Some(ConditionCode::Z) }, + Opcode::JNZ | + Opcode::CMOVNZ | + Opcode::SETNZ => { Some(ConditionCode::NZ) }, + Opcode::JA | + Opcode::CMOVA | + Opcode::SETA => { Some(ConditionCode::A) }, + Opcode::JNA | + Opcode::CMOVNA | + Opcode::SETBE => { Some(ConditionCode::BE) }, + Opcode::JS | + Opcode::CMOVS | + Opcode::SETS => { Some(ConditionCode::S) }, + Opcode::JNS | + Opcode::CMOVNS | + Opcode::SETNS => { Some(ConditionCode::NS) }, + Opcode::JP | + Opcode::CMOVP | + Opcode::SETP => { Some(ConditionCode::P) }, + Opcode::JNP | + Opcode::CMOVNP | + Opcode::SETNP => { Some(ConditionCode::NP) }, + Opcode::JL | + Opcode::CMOVL | + Opcode::SETL => { Some(ConditionCode::L) }, + Opcode::JGE | + Opcode::CMOVGE | + Opcode::SETGE => { Some(ConditionCode::GE) }, + Opcode::JG | + Opcode::CMOVG | + Opcode::SETG => { Some(ConditionCode::G) }, + Opcode::JLE | + Opcode::CMOVLE | + Opcode::SETLE => { Some(ConditionCode::LE) }, + _ => None, + } + } +} + +impl Default for Instruction { + fn default() -> Self { + Instruction::invalid() + } +} + +impl Instruction { + pub fn operand(&self, i: u8) -> Operand { + assert!(i < 4); + Operand::from_spec(self, self.operands[i as usize]) + } + + pub fn operand_count(&self) -> u8 { + let mut i = 0; + for op in self.operands.iter() { + if let OperandSpec::Nothing = op { + return i; + } else { + i += 1; + } + } + return i; + } + + pub fn operand_present(&self, i: u8) -> bool { + assert!(i < 4); + if let OperandSpec::Nothing = self.operands[i as usize] { + false + } else { + true + } + } + + pub fn invalid() -> Instruction { + Instruction { + prefixes: Prefixes::new(0), + opcode: Opcode::Invalid, + modrm_rrr: RegSpec::rax(), + modrm_mmm: RegSpec::rax(), // doubles as sib_base + sib_index: RegSpec::rax(), + vex_reg: RegSpec::rax(), + scale: 0, + length: 0, + disp: 0, + imm: 0, + operand_count: 0, + operands: [OperandSpec::Nothing; 4], + } + } + + pub fn is_invalid(&self) -> bool { + match self.opcode { + Opcode::Invalid => true, + _ => false + } + } + + pub fn segment_override_for_op(&self, op: u8) -> Option { + match self.opcode { + Opcode::STOS => { + if op == 0 { + Some(Segment::ES) + } else { + None + } + } + Opcode::LODS => { + if op == 1 { + Some(self.prefixes.segment) + } else { + None + } + } + Opcode::MOVS => { + if op == 0 { + Some(Segment::ES) + } else if op == 1 { + Some(self.prefixes.segment) + } else { + None + } + } + Opcode::CMPS => { + if op == 0 { + Some(self.prefixes.segment) + } else if op == 1 { + Some(Segment::ES) + } else { + None + } + }, + _ => { + // most operands are pretty simple: + if self.operands[op as usize].is_memory() && + self.prefixes.segment != Segment::DS { + Some(self.prefixes.segment) + } else { + None + } + } + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct Prefixes { + bits: u8, + rex: PrefixRex, + segment: Segment, +} + +#[derive(Debug, Copy, Clone)] +pub struct PrefixVex { + bits: u8, +} + +#[allow(dead_code)] +impl PrefixVex { + #[inline] + fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } + #[inline] + fn x(&self) -> bool { (self.bits & 0x02) == 0x02 } + #[inline] + fn r(&self) -> bool { (self.bits & 0x04) == 0x04 } + #[inline] + fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } + #[inline] + fn l(&self) -> bool { (self.bits & 0x10) == 0x10 } +} + +#[derive(Debug, Copy, Clone)] +pub struct PrefixRex { + bits: u8 +} + +#[allow(dead_code)] +impl Prefixes { + fn new(bits: u8) -> Prefixes { + Prefixes { + bits: bits, + rex: PrefixRex { bits: 0 }, + segment: Segment::DS, + } + } + #[inline] + fn rep(&self) -> bool { self.bits & 0x30 == 0x10 } + #[inline] + fn set_rep(&mut self) { self.bits = (self.bits & 0xcf) | 0x10 } + #[inline] + pub fn repz(&self) -> bool { self.bits & 0x30 == 0x20 } + #[inline] + fn set_repz(&mut self) { self.bits = (self.bits & 0xcf) | 0x20 } + #[inline] + pub fn repnz(&self) -> bool { self.bits & 0x30 == 0x30 } + #[inline] + fn set_repnz(&mut self) { self.bits = (self.bits & 0xcf) | 0x30 } + #[inline] + fn operand_size(&self) -> bool { self.bits & 0x1 == 1 } + #[inline] + fn set_operand_size(&mut self) { self.bits = self.bits | 0x1 } + #[inline] + fn address_size(&self) -> bool { self.bits & 0x2 == 2 } + #[inline] + fn set_address_size(&mut self) { self.bits = self.bits | 0x2 } + #[inline] + fn set_lock(&mut self) { self.bits |= 0x4 } + #[inline] + pub fn lock(&self) -> bool { self.bits & 0x4 == 4 } + #[inline] + fn cs(&mut self) { self.segment = Segment::CS } + #[inline] + fn set_cs(&mut self) { self.segment = Segment::CS } + #[inline] + pub fn ds(&self) -> bool { self.segment == Segment::DS } + #[inline] + fn set_ds(&mut self) { self.segment = Segment::DS } + #[inline] + pub fn es(&self) -> bool { self.segment == Segment::ES } + #[inline] + fn set_es(&mut self) { self.segment = Segment::ES } + #[inline] + pub fn fs(&self) -> bool { self.segment == Segment::FS } + #[inline] + fn set_fs(&mut self) { self.segment = Segment::FS } + #[inline] + pub fn gs(&self) -> bool { self.segment == Segment::GS } + #[inline] + fn set_gs(&mut self) { self.segment = Segment::GS } + #[inline] + pub fn ss(&self) -> bool { self.segment == Segment::SS } + #[inline] + fn set_ss(&mut self) { self.segment = Segment::SS } + #[inline] + fn rex(&self) -> &PrefixRex { &self.rex } + #[inline] + fn vex(&self) -> PrefixVex { PrefixVex { bits: self.rex.bits } } + + #[inline] + fn rex_from(&mut self, bits: u8) { + self.rex.bits = bits; + } + + #[inline] + fn vex_from_c5(&mut self, bits: u8) { + // collect rex bits + let r = bits & 0x80; + let wrxb = (r >> 5) ^ 0x04; + let l = (bits & 0x04) << 2; + let synthetic_rex = wrxb | l | 0x80; + self.rex.from(synthetic_rex); + } + + #[inline] + fn vex_from_c4(&mut self, high: u8, low: u8) { + let w = low & 0x80; + let rxb = (high >> 5) ^ 0x07; + let wrxb = rxb | w >> 4; + let l = (low & 0x04) << 2; + let synthetic_rex = wrxb | l | 0x80; + self.rex.from(synthetic_rex); + } +} + +impl PrefixRex { + #[inline] + fn present(&self) -> bool { (self.bits & 0xc0) == 0x40 } + #[inline] + fn b(&self) -> bool { (self.bits & 0x01) == 0x01 } + #[inline] + fn x(&self) -> bool { (self.bits & 0x02) == 0x02 } + #[inline] + fn r(&self) -> bool { (self.bits & 0x04) == 0x04 } + #[inline] + fn w(&self) -> bool { (self.bits & 0x08) == 0x08 } + #[inline] + fn from(&mut self, prefix: u8) { + self.bits = prefix; + } +} + +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum OperandCode { + ModRM_0x0f00, + ModRM_0x0f01, + ModRM_0x0fae, + ModRM_0x0fba, + ModRM_0xf238, + ModRM_0xf30fc7, + ModRM_0x660f38, + ModRM_0x660f3a, + CVT_AA, + CVT_DA, + Rq_Cq_0, + Rq_Dq_0, + Cq_Rq_0, + Dq_Rq_0, + FS, + GS, + Yb_DX, + Yv_DX, + DX_Xb, + DX_Xv, + AH, + AX_Xv, + // DX_AX, + E_G_xmm, + // Ev_Ivs, + Ew_Sw, + Fw, + I_3, + Ib, + Ibs, + Ivs, + Iw, + Iw_Ib, + Jvds, + Ob_AL, + Ov_AX, + Sw_Ew, + Yb_AL, + Yb_Xb, + Yv_AX, + Yv_Xv, + G_E_q, + E_G_q, + Rv_Gmm_Ib, + G_mm_Ew_Ib, + Mq_Dq, + ModRM_0x0f38, + ModRM_0x0f3a, + ModRM_0x0f71, + ModRM_0x0f72, + ModRM_0x0f73, + ModRM_0x660f71, + ModRM_0x660f72, + ModRM_0x660f73, + ModRM_0x0fc7, + Nothing, + // Implied, + Unsupported, + Zv_R0 = 0x40, + Zv_R1 = 0x41, + Zv_R2 = 0x42, + Zv_R3 = 0x43, + Zv_R4 = 0x44, + Zv_R5 = 0x45, + Zv_R6 = 0x46, + Zv_R7 = 0x47, + // Zv_AX_R0 = 0x48, + Zv_AX_R1 = 0x49, + Zv_AX_R2 = 0x4a, + Zv_AX_R3 = 0x4b, + Zv_AX_R4 = 0x4c, + Zv_AX_R5 = 0x4d, + Zv_AX_R6 = 0x4e, + Zv_AX_R7 = 0x4f, + Zb_Ib_R0 = 0x50, + Zb_Ib_R1 = 0x51, + Zb_Ib_R2 = 0x52, + Zb_Ib_R3 = 0x53, + Zb_Ib_R4 = 0x54, + Zb_Ib_R5 = 0x55, + Zb_Ib_R6 = 0x56, + Zb_Ib_R7 = 0x57, + Zv_Ivq_R0 = 0x58, + Zv_Ivq_R1 = 0x59, + Zv_Ivq_R2 = 0x5a, + Zv_Ivq_R3 = 0x5b, + Zv_Ivq_R4 = 0x5c, + Zv_Ivq_R5 = 0x5d, + Zv_Ivq_R6 = 0x5e, + Zv_Ivq_R7 = 0x5f, + Gv_Eb = 0x60, + Gv_Ew = 0x61, + Gdq_Ed = 0x62, + G_E_mm_Ib = 0x64, + G_E_xmm_Ib = 0x65, + AL_Ib = 0x66, + AX_Ivd = 0x67, + AL_Ob = 0x68, + AL_Xb = 0x69, + // AX_AL = 0x6a, + AX_Ov = 0x6b, + + Eb_Gb = 0x80, + Ev_Gv = 0x81, + Gb_Eb = 0xc2, + Gv_Ev = 0xc3, + Gb_Eb_Ib = 0xc4, + Gv_Ev_Iv = 0xc5, + // gap: 0xc6 + Gd_U_xmm = 0xc7, + M_G_xmm = 0xc9, + ModRM_0x0f12 = 0xcb, + ModRM_0x0f16 = 0xce, + ModRM_0xc0_Eb_Ib = 0x86, + ModRM_0xc1_Ev_Ib = 0x87, + ModRM_0xd0_Eb_1 = 0x88, + ModRM_0xd1_Ev_1 = 0x89, + ModRM_0xd2_Eb_CL = 0x8a, + ModRM_0xd3_Ev_CL = 0x8b, + ModRM_0x80_Eb_Ib = 0x8c, + ModRM_0x83_Ev_Ibs = 0x8d, + // this would be Eb_Ivs, 0x8e + ModRM_0x81_Ev_Ivs = 0x8f, + ModRM_0xc6_Eb_Ib = 0x90, + ModRM_0xc7_Ev_Iv = 0x91, + ModRM_0xfe_Eb = 0x92, + ModRM_0x8f_Ev = 0x93, + // gap, 0x94 + ModRM_0xff_Ev = 0x95, + ModRM_0xf6 = 0x96, + ModRM_0xf7 = 0x97, + Eb_R0 = 0x98, + Ev = 0x99, + ModRM_0x0f18 = 0x9b, + // gap, 0x9a + Gv_M = 0xdb, + G_mm_Edq = 0xdd, + G_mm_E = 0xdf, + // G_xmm_Ed = 0xe1, + G_xmm_Eq = 0xe3, + G_mm_E_xmm = 0xe5, + G_E_mm = 0xe7, + Edq_G_mm = 0xe9, + E_G_mm = 0xeb, + G_xmm_E_mm = 0xed, + G_xmm_Edq = 0xef, + G_U_mm = 0xf1, + Ev_Gv_Ib = 0xf3, + Ev_Gv_CL = 0xf5, + G_M_xmm = 0xf7, + G_E_xmm = 0xf9, +} + +fn base_opcode_map(v: u8) -> Opcode { + match v { + 0 => Opcode::ADD, + 1 => Opcode::OR, + 2 => Opcode::ADC, + 3 => Opcode::SBB, + 4 => Opcode::AND, + 5 => Opcode::SUB, + 6 => Opcode::XOR, + 7 => Opcode::CMP, + _ => { unsafe { unreachable_unchecked() } } + } +} + +const BITWISE_OPCODE_MAP: [Opcode; 8] = [ + Opcode::ROL, + Opcode::ROR, + Opcode::RCL, + Opcode::RCR, + Opcode::SHL, + Opcode::SHR, + Opcode::SAL, + Opcode::SAR +]; + +const OPCODE_660F_MAP: [OpcodeRecord; 256] = [ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x10 + OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPD), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x20 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPD), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPI2PD), OperandCode::G_xmm_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x30 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f38), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f3a), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x40 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x50 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x60 + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLBW), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLWD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLDQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSWB), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTB), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTW), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSWB), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHBW), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHWD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHDQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSDW), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLQDQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHQDQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_xmm_Eq), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQA), OperandCode::G_E_xmm), +// 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFD), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f71), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f72), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x660f73), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQB), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::HADDPD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::HSUBPD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x80 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x90 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xa0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xb0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xc0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xd0 + OpcodeRecord(Interpretation::Instruction(Opcode::ADDSUBPD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xe0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PXOR), OperandCode::G_E_xmm), +// 0xf0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +]; + +fn read_opcode_660f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { + bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { + *length += 1; + (OPCODE_660F_MAP[b as usize], b) + }) +} + +const OPCODE_F20F_MAP: [OpcodeRecord; 256] = [ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x10 + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSD), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVDDUP), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x20 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Edq), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTTSD2SI), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSD2SI), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x30 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf238), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x40 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x50 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SQRTSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::ADDSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MULSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSD2SS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SUBSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MINSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::DIVSD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MAXSD), OperandCode::G_E_xmm), +// 0x60 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFLW), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::HADDPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::HSUBPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x80 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x90 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xa0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xb0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xc0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPSD), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xd0 + OpcodeRecord(Interpretation::Instruction(Opcode::ADDSUBPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQ2Q), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xe0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPD2DQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xf0 + OpcodeRecord(Interpretation::Instruction(Opcode::LDDQU), OperandCode::G_M_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +]; + +fn read_opcode_f20f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { + bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { + *length += 1; + (OPCODE_F20F_MAP[b as usize], b) + }) +} + +const OPCODE_F30F_MAP: [OpcodeRecord; 256] = [ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x10 + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSS), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSLDUP), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSHDUP), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x20 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SS), OperandCode::G_xmm_Edq), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTTSS2SI), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSS2SI), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x30 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x40 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x50 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SQRTSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RSQRTSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RCPSS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::ADDSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MULSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTSS2SD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTTPS2DQ), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SUBSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MINSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::DIVSS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MAXSS), OperandCode::G_E_xmm), +// 0x60 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQU), OperandCode::G_E_xmm), +// 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFHW), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVDQU), OperandCode::E_G_xmm), +// 0x80 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x90 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xa0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xb0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::POPCNT), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xc0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPSS), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30fc7), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xd0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ2DQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xe0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTDQ2PD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xf0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +]; + +fn read_opcode_f30f_map>(bytes_iter: &mut T, length: &mut u8) -> Result<(OpcodeRecord, u8), DecodeError> { + bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { + *length += 1; + (OPCODE_F30F_MAP[b as usize], b) + }) + /* + match bytes_iter.next() { + Some(b) => { + *length += 1; + match b { + 0x10 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::G_E_xmm) }, + 0x11 => { instruction.opcode = Opcode::MOVSS; Some(OperandCode::E_G_xmm) }, + 0x12 => { instruction.opcode = Opcode::MOVSLDUP; Some(OperandCode::G_E_xmm) }, + 0x2a => { instruction.opcode = Opcode::CVTSI2SS; Some(OperandCode::G_E_xmm) }, + 0x2c => { instruction.opcode = Opcode::CVTTSS2SI; Some(OperandCode::G_E_xmm) }, + 0x2d => { instruction.opcode = Opcode::CVTSS2SI; Some(OperandCode::G_E_xmm) }, + 0x51 => { instruction.opcode = Opcode::SQRTSS; Some(OperandCode::G_E_xmm) }, + 0x58 => { instruction.opcode = Opcode::ADDSS; Some(OperandCode::G_E_xmm) }, + 0x59 => { instruction.opcode = Opcode::MULSS; Some(OperandCode::G_E_xmm) }, + 0x5a => { instruction.opcode = Opcode::CVTSS2SD; Some(OperandCode::G_E_xmm) }, + 0x5c => { instruction.opcode = Opcode::SUBSS; Some(OperandCode::G_E_xmm) }, + 0x5d => { instruction.opcode = Opcode::MINSS; Some(OperandCode::G_E_xmm) }, + 0x5e => { instruction.opcode = Opcode::DIVSS; Some(OperandCode::G_E_xmm) }, + 0x5f => { instruction.opcode = Opcode::MAXSS; Some(OperandCode::G_E_xmm) }, + _ => { + instruction.opcode = Opcode::Invalid; + Some(OperandCode::Nothing) + } + } + } + None => { + None + } + } + */ +} +const OPCODE_0F_MAP: [OpcodeRecord; 256] = [ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), + OpcodeRecord(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_M), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CLTS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSRET), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::INVD), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::WBINVD), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::UD2), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x10 + OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f12), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVLPS), OperandCode::M_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKLPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::UNPCKHPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f16), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVHPS), OperandCode::M_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f18), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Ev), +// 0x20 + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Cq_0), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Rq_Dq_0), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Cq_Rq_0), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Dq_Rq_0), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVAPS), OperandCode::E_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPI2PS), OperandCode::G_xmm_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTPS), OperandCode::M_G_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTTPS2PI), OperandCode::G_mm_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PI), OperandCode::G_mm_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::UCOMISS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::COMISS), OperandCode::G_E_xmm), + +// 0x30 + OpcodeRecord(Interpretation::Instruction(Opcode::WRMSR), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::RDTSC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::RDMSR), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::RDPMC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSENTER), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SYSEXIT), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::GETSEC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f38), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f3a), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + +// 0x40 + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVO), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNO), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVB), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNB), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVZ), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNZ), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNA), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVA), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVS), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNS), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVP), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVNP), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVL), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVGE), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVLE), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMOVG), OperandCode::Gv_Ev), + +// 0x50 + OpcodeRecord(Interpretation::Instruction(Opcode::MOVMSKPS), OperandCode::Gd_U_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::SQRTPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RSQRTPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::RCPPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ANDPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ANDNPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ORPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::XORPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::ADDPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MULPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTPS2PD), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::CVTDQ2PS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::SUBPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MINPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::DIVPS), OperandCode::G_E_xmm), + OpcodeRecord(Interpretation::Instruction(Opcode::MAXPS), OperandCode::G_E_xmm), + +// 0x60 + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLBW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLWD), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKLDQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSWB), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTB), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTD), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSWB), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHBW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHWD), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PUNPCKHDQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PACKSSDW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::G_mm_Edq), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::G_mm_E), + +// 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFW), OperandCode::G_E_mm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f71), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f72), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f73), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::EMMS), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::VMREAD), OperandCode::E_G_q), + OpcodeRecord(Interpretation::Instruction(Opcode::VMWRITE), OperandCode::G_E_q), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVD), OperandCode::Edq_G_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVQ), OperandCode::E_G_mm), + +// 0x80 + OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNO), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JB), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNB), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JZ), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNZ), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNA), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JA), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JS), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNS), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JP), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JNP), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JL), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JGE), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JLE), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JG), OperandCode::Jvds), + +// 0x90 + OpcodeRecord(Interpretation::Instruction(Opcode::SETO), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETNO), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETB), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETAE), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETZ), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETNZ), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETBE), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETA), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETS), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETNS), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETP), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETNP), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETL), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETGE), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETLE), OperandCode::Eb_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::SETG), OperandCode::Eb_R0), + +// 0xa0 + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::FS), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::FS), + OpcodeRecord(Interpretation::Instruction(Opcode::CPUID), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::BT), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SHLD), OperandCode::Ev_Gv_CL), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::GS), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::GS), + OpcodeRecord(Interpretation::Instruction(Opcode::RSM), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::BTS), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SHRD), OperandCode::Ev_Gv_CL), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fae), + OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev), + +// 0xb0 + OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPXCHG), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::LSS), OperandCode::Gv_M), + OpcodeRecord(Interpretation::Instruction(Opcode::BTR), OperandCode::E_G_q), + OpcodeRecord(Interpretation::Instruction(Opcode::LFS), OperandCode::Gv_M), + OpcodeRecord(Interpretation::Instruction(Opcode::LGS), OperandCode::Gv_M), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_b), OperandCode::Gv_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_w), OperandCode::Gv_Ew), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), // JMPE, ITANIUM + OpcodeRecord(Interpretation::Instruction(Opcode::UD2E), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fba), + OpcodeRecord(Interpretation::Instruction(Opcode::BTC), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::TZCNT), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::BSR), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_b), OperandCode::Gv_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSX_w), OperandCode::Gv_Ew), + +// 0xc0 + OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::XADD), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPPS), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTI), OperandCode::Mq_Dq), + OpcodeRecord(Interpretation::Instruction(Opcode::PINSRW), OperandCode::G_mm_Ew_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::Rv_Gmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SHUFPS), OperandCode::G_E_xmm_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fc7), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::BSWAP), OperandCode::Zv_R7), + +// 0xd0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLD), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRLQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDQ), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULLW), OperandCode::G_E_mm), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PMOVMSKB), OperandCode::G_U_mm), + + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMINUB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PAND), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PANDN), OperandCode::Unsupported), + +// 0xe0 + OpcodeRecord(Interpretation::Instruction(Opcode::PAVGB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRAW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSRAD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PAVGW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULHUW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULHW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMINSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::POR), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDSB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PXOR), OperandCode::G_E_mm), +// 0xf0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSLLQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMULUDQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PMADDWD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSADBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::MASKMOVQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PSUBQ), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDB), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDW), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::PADDD), OperandCode::Unsupported), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +]; +fn read_opcode_0f_map>(bytes_iter: &mut T, length: &mut u8) -> Result { + bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { + *length += 1; + OPCODE_0F_MAP[b as usize] + }) +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum Interpretation { + Instruction(Opcode), + Prefix, +} + +#[derive(Copy, Clone, Debug, PartialEq)] +// this should be a 32-byte struct.. +struct OpcodeRecord(Interpretation, OperandCode); + +#[test] +fn opcode_record_size() { + // there are more than 256 opcodes... + assert_eq!(core::mem::size_of::(), 4); +} + +const OPCODES: [OpcodeRecord; 256] = [ + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0x40: + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), +// 0x50: + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R7), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R7), +// 0x60 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVSXD), OperandCode::Gdq_Ed), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ivs), + OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Iv), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gb_Eb_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yb_DX), + OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yv_DX), + OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xb), + OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xv), +// 0x70 + OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNO), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JB), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNB), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JZ), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNZ), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNA), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JA), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JS), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNS), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JP), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JNP), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JL), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JGE), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JLE), OperandCode::Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::JG), OperandCode::Ibs), +// 0x80 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x80_Eb_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x81_Ev_Ivs), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x83_Ev_Ibs), + OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Eb_Gb), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ev_Gv), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gb_Eb), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gv_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ew_Sw), + OpcodeRecord(Interpretation::Instruction(Opcode::LEA), OperandCode::Gv_M), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Sw_Ew), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x8f_Ev), + OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R7), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_AA), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_DA), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::PUSHF), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::POPF), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::SAHF), OperandCode::AH), + OpcodeRecord(Interpretation::Instruction(Opcode::LAHF), OperandCode::AH), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AL_Ob), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AX_Ov), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ob_AL), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ov_AX), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yb_Xb), + OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yv_Xv), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yb_Xb), + OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yv_Xv), + OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AL_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AX_Ivd), + OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yb_AL), + OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yv_AX), + OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AL_Xb), + OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AX_Xv), + OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yb_AL), + OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yv_AX), +// 0xb0 + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R7), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R0), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R1), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R2), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R3), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R4), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R5), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R6), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Ivq_R7), +// 0xc0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc0_Eb_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw), + OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv), + OpcodeRecord(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::LEAVE), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Iw), + OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::I_3), + OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::Ib), + OpcodeRecord(Interpretation::Instruction(Opcode::INTO), OperandCode::Fw), + OpcodeRecord(Interpretation::Instruction(Opcode::IRET), OperandCode::Fw), +// 0xd0 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd0_Eb_1), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd1_Ev_1), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd2_Eb_CL), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd3_Ev_CL), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // XLAT + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 d8 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 d9 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 da + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 db + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 dc + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 dd + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 de + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // x86 df + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xe0 + // LOOPNZ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // LOOPZ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // LOOP + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // JECXZ + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // IN + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // IN + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // OUT + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // OUT + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xe8 + OpcodeRecord(Interpretation::Instruction(Opcode::CALL), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Jvds), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Ibs), + // IN + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // IN + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // OUT + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + // OUT + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +// 0xf0 + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + // ICEBP? + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), +// 0xf4 + OpcodeRecord(Interpretation::Instruction(Opcode::HLT), OperandCode::Nothing), + // CMC + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf6), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf7), + OpcodeRecord(Interpretation::Instruction(Opcode::CLC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::STC), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CLI), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::STI), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::CLD), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::STD), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xfe_Eb), + // TODO: test 0xff /3 + OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xff_Ev), +]; + +#[allow(non_snake_case)] +pub(self) fn read_E>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result { + let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); + if modrm >= 0b11000000 { + read_modrm_reg(instr, modrm, bank) + } else { + read_M(bytes_iter, instr, modrm, length) + } +} +#[allow(non_snake_case)] +pub(self) fn read_E_xmm>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { + if modrm >= 0b11000000 { + read_modrm_reg(instr, modrm, RegisterBank::X) + } else { + read_M(bytes_iter, instr, modrm, length) + } +} +#[allow(non_snake_case)] +pub(self) fn read_E_ymm>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { + if modrm >= 0b11000000 { + read_modrm_reg(instr, modrm, RegisterBank::Y) + } else { + read_M(bytes_iter, instr, modrm, length) + } +} + +#[allow(non_snake_case)] +fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result { + instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank); + Ok(OperandSpec::RegMMM) +} + +#[allow(non_snake_case)] +fn read_sib>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { + let modbits = modrm >> 6; + let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; + let sibbyte = bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?; + *length += 1; + + let op_spec = if (sibbyte & 7) == 0b101 { + let disp = if modbits == 0b00 { + *length += 4; + read_num(bytes_iter, 4)? as i32 + } else if modbits == 0b01 { + *length += 1; + read_num(bytes_iter, 1)? as i8 as i32 + } else { + *length += 4; + read_num(bytes_iter, 4)? as i32 + }; + + if ((sibbyte >> 3) & 7) == 0b100 { + if modbits == 0b00 && !instr.prefixes.rex().x() { + instr.disp = disp as u32 as u64; + + OperandSpec::DispU32 + } else { + let reg = RegSpec::from_parts(0b100, instr.prefixes.rex().x(), addr_width); + instr.modrm_mmm = reg; + + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } + } + } else { + instr.modrm_mmm = RegSpec::from_parts(5, instr.prefixes.rex().b(), addr_width); + + instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width); + let scale = 1u8 << (sibbyte >> 6); + instr.scale = scale; + + if disp == 0 { + if modbits == 0 { + OperandSpec::RegScaleDisp + } else { + OperandSpec::RegIndexBaseScaleDisp + } + } else { + instr.disp = disp as i64 as u64; + if modbits == 0 { + OperandSpec::RegScale + } else { + OperandSpec::RegIndexBaseScale + } + } + } + } else { + instr.modrm_mmm = RegSpec::from_parts(sibbyte & 7, instr.prefixes.rex().b(), addr_width); + + let disp = if modbits == 0b00 { + 0 + } else if modbits == 0b01 { + *length += 1; + read_num(bytes_iter, 1)? as i8 as i32 + } else { + *length += 4; + read_num(bytes_iter, 4)? as i32 + }; + + if ((sibbyte >> 3) & 7) == 0b100 { + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } + } else { + instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width); + let scale = 1u8 << (sibbyte >> 6); + instr.scale = scale; + if disp == 0 { + OperandSpec::RegIndexBaseScale + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegIndexBaseScaleDisp + } + } + }; + Ok(op_spec) +} + +#[allow(non_snake_case)] +fn read_M>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result { + let modbits = modrm >> 6; + let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q }; + let mmm = modrm & 7; + let op_spec = if mmm == 4 { + return read_sib(bytes_iter, instr, modrm, length); + } else if mmm == 5 && modbits == 0b00 { + *length += 4; + let disp = read_num(bytes_iter, 4)? as i32; + instr.modrm_mmm = + if addr_width == RegisterBank::Q { RegSpec::rip() } else { RegSpec::eip() }; + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } + } else { + instr.modrm_mmm = RegSpec::from_parts(mmm, instr.prefixes.rex().b(), addr_width); + + if modbits == 0b00 { + OperandSpec::Deref + } else { + let disp = if modbits == 0b01 { + *length += 1; + read_num(bytes_iter, 1)? as i8 as i32 + } else { + *length += 4; + read_num(bytes_iter, 4)? as i32 + }; + if disp == 0 { + OperandSpec::Deref + } else { + instr.disp = disp as i64 as u64; + OperandSpec::RegDisp + } + } + }; + Ok(op_spec) +} + +#[inline] +fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { + match width { + 1 => return if rex { RegisterBank::rB } else { RegisterBank::B }, + 2 => return RegisterBank::W, + 4 => return RegisterBank::D, + 8 => return RegisterBank::Q, + _ => unsafe { unreachable_unchecked(); } + } +} + +fn read_instr>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), DecodeError> { + let mut length = 0u8; + let mut alternate_opcode_map: Option = None; +// use core::intrinsics::unlikely; + let mut prefixes = Prefixes::new(0); + + fn escapes_are_prefixes_actually(prefixes: &mut Prefixes, opc_map: &mut Option) { + match opc_map { + Some(OpcodeMap::Map66) => { + prefixes.set_operand_size(); + }, + Some(OpcodeMap::MapF2) => { + prefixes.set_repnz(); + }, + Some(OpcodeMap::MapF3) => { + prefixes.set_rep(); + }, + None => {} + } + *opc_map = None; + } + + let record: OpcodeRecord = loop { +// let operand_code = loop { + match bytes_iter.next() { + Some(b) => { + length += 1; + let record = OPCODES[b as usize]; + if (b & 0xf0) == 0x40 { + prefixes.rex_from(b); + } else if b == 0x0f { + let record = match alternate_opcode_map { + Some(opcode_map) => { + let (rec, opcode_byte) = match opcode_map { + OpcodeMap::Map66 => { + read_opcode_660f_map(&mut bytes_iter, &mut length)? + }, + OpcodeMap::MapF2 => { + read_opcode_f20f_map(&mut bytes_iter, &mut length)? + }, + OpcodeMap::MapF3 => { + read_opcode_f30f_map(&mut bytes_iter, &mut length)? + }, + }; + if rec == OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing) { + escapes_are_prefixes_actually(&mut prefixes, &mut Some(opcode_map)); + OPCODE_0F_MAP[opcode_byte as usize] + } else { + rec + } + }, + None => { + read_opcode_0f_map(&mut bytes_iter, &mut length)? + } + }; + + break record; + } else if let Interpretation::Instruction(_) = record.0 { + escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map); + break record; + } else { + // some prefix seen after we saw rex, but before the 0f escape or an actual + // opcode. so we must forget the rex prefix! + // this is to handle sequences like 41660f21cf + // where if 660f21 were a valid opcode, 41 would apply a rex.b + // prefix, but since 660f21 is not valid, the opcode is interpreted + // as 0f21, where 66 is a prefix, which makes 41 not the last + // prefix before the opcode, and it's discarded. + + // 2.3.2 + // Any VEX-encoded instruction with a LOCK prefix preceding VEX will #UD. + // 2.3.3 + // Any VEX-encoded instruction with a 66H, F2H, or F3H prefix preceding VEX + // will #UD. + // 2.3.4 + // Any VEX-encoded instruction with a REX prefix proceeding VEX will #UD. + if b == 0xc5 { + if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() { + // rex and then vex is invalid! reject it. + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidPrefixes); + } else { + instruction.prefixes = prefixes; + vex::two_byte_vex(&mut bytes_iter, instruction, length)?; + + if decoder != &InstDecoder::default() { + decoder.revise_instruction(instruction)?; + } + return Ok(()); + } + } else if b == 0xc4 { + if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() { + // rex and then vex is invalid! reject it. + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidPrefixes); + } else { + instruction.prefixes = prefixes; + vex::three_byte_vex(&mut bytes_iter, instruction, length)?; + if decoder != &InstDecoder::default() { + decoder.revise_instruction(instruction)?; + } + return Ok(()); + } + } + + prefixes.rex_from(0); + escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map); + match b { + 0x26 => { + prefixes.set_es(); + }, + 0x2e => { + prefixes.set_cs(); + }, + 0x36 => { + prefixes.set_ss(); + }, + 0x3e => { + prefixes.set_ds(); + }, + 0x64 => { + prefixes.set_fs(); + }, + 0x65 => { + prefixes.set_gs(); + }, + 0x66 => { + alternate_opcode_map = Some(OpcodeMap::Map66); + }, + 0x67 => { + prefixes.set_address_size(); + }, + 0x9b => { + // TODO: WAIT prefix + return Err(DecodeError::IncompleteDecoder); + }, + 0xf0 => { + prefixes.set_lock(); + }, + 0xf2 => { + alternate_opcode_map = Some(OpcodeMap::MapF2); + }, + 0xf3 => { + alternate_opcode_map = Some(OpcodeMap::MapF3); + }, + _ => { unsafe { unreachable_unchecked(); } } + } + } + }, + None => { + return Err(DecodeError::ExhaustedInput); + } + } + }; + if let Interpretation::Instruction(opcode) = record.0 { + instruction.opcode = opcode; + } else { + unsafe { unreachable_unchecked(); } + } + instruction.prefixes = prefixes; + read_operands(decoder, bytes_iter, instruction, record.1, &mut length)?; + instruction.length = length; + + if decoder != &InstDecoder::default() { + // we might have to fix up or reject this instruction under whatever cpu features we need to + // pretend to have. + decoder.revise_instruction(instruction)?; + } + Ok(()) +} +fn read_operands>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), DecodeError> { + if (operand_code as u8) & 0x40 == 0x40 { + instruction.operands[0] = OperandSpec::RegRRR; + } + if (operand_code as u8) >= 0x40 && (operand_code as u8) < 0x60 { + let reg = (operand_code as u8) & 0x07; + let category = ((operand_code as u8) & 0x18) >> 3; + if category == 0 { + // these are Zv_R + let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); + let bank = if opwidth == 4 { + RegisterBank::D + } else if opwidth == 2 { + RegisterBank::W + } else { + RegisterBank::Q + }; + instruction.modrm_rrr = + RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); + instruction.operand_count = 1; + // Zv_AX are missing! + } else if category == 2 { + // these are Zb_Ib_R + instruction.modrm_rrr = + RegSpec::gp_from_parts(reg, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present()); + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 1, length)?; + instruction.operands[1] = OperandSpec::ImmU8; + instruction.operand_count = 2; + } else { + // category == 3, Zv_Ivq_R + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let bank = if opwidth == 4 { + RegisterBank::D + } else if opwidth == 2 { + RegisterBank::W + } else { + RegisterBank::Q + }; + instruction.modrm_rrr = + RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); + instruction.imm = + read_imm_ivq(&mut bytes_iter, opwidth, length)?; + instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + } + return Ok(()); + } + + let mut modrm = 0; + let mut opwidth = 0; + let mut mem_oper = OperandSpec::Nothing; + let mut bank = RegisterBank::Q; + let code_int = operand_code as u8; + if ((code_int) & 0x80) == 0x80 { + // cool! we can precompute opwidth and know we need to read_E. + if (code_int & 1) == 1 { + // further, this is an vdq E + opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + if opwidth == 4 { + bank = RegisterBank::D; + } else if opwidth == 2 { + bank = RegisterBank::W; + } + } else { + opwidth = 1; + if instruction.prefixes.rex().present() { + bank = RegisterBank::rB; + } else { + bank = RegisterBank::B; + } + }; + modrm = read_modrm(&mut bytes_iter, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), bank); + + mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + + let numeric_code = (operand_code as u8) & 0xbf; + if numeric_code >= 0x80 && numeric_code < 0x84 { + let (mmm, rrr) = if numeric_code & 0x02 == 2 { + (1, 0) + } else { + (0, 1) + }; + instruction.operands[mmm] = mem_oper; + instruction.operands[rrr] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } else if operand_code == OperandCode::Ibs { + instruction.imm = + read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[0] = OperandSpec::ImmI8; + instruction.operand_count = 1; + } else { + match operand_code { + /* + Gv_Ev_Iv, + Gb_Eb_Ib, + Yb_DX, + Yv_DX, + DX_Xb, + DX_Xv, + OR, + AH, + AL_Ib, + AL_Ob, + AL_Xb, + AX_AL, + AX_Ivd, + AX_Ov, + AX_Xv, + DX_AX, + Eb_1, + Eb_Ib, + Eb_CL, + Ev, + Ev_1, + Ev_CL, + Ev_Ibs, + Ev_Iv, + Ev_Ivs, + Ew_Sw, + Fw, + Gv_M, + I_3, + Ib, + Ibs, + Ivs, + Iw, + Iw_Ib, + Ob_AL, + Ov_AX, + Sw_Ew, + Yb_AL, + Yb_Xb, + Yv_AX, + Yv_Xv, + Zb_Ib, + Zv, + Zv_AX, + */ + OperandCode::Eb_R0 => { + if (modrm & 0b00111000) != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc6".to_owned()); + } + + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + }, + op @ OperandCode::AL_Ob | + op @ OperandCode::AX_Ov => { + let opwidth = match op { + OperandCode::AL_Ob => 1, + OperandCode::AX_Ov => { + imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes) + } + _ => { + unsafe { unreachable_unchecked() } + } + }; + let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 }; + // stupid RCT thing: + let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; + let imm = read_num(&mut bytes_iter, addr_width)?; + *length += addr_width; + instruction.modrm_rrr = + RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()); + instruction.disp = imm; + if instruction.prefixes.address_size() { + instruction.operands[1] = OperandSpec::DispU32; + } else { + instruction.operands[1] = OperandSpec::DispU64; + }; + instruction.operand_count = 2; + } + op @ OperandCode::Ob_AL | + op @ OperandCode::Ov_AX => { + let opwidth = match op { + OperandCode::Ob_AL => 1, + OperandCode::Ov_AX => { + imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes) + } + _ => { + unsafe { unreachable_unchecked() } + } + }; + let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 }; + // stupid RCT thing: + let addr_width = if instruction.prefixes.address_size() { 2 } else { 4 }; + let imm = read_num(&mut bytes_iter, addr_width)?; + *length += addr_width; + instruction.disp = imm; + instruction.operands[0] = if instruction.prefixes.address_size() { + OperandSpec::DispU32 + } else { + OperandSpec::DispU64 + }; + instruction.modrm_rrr = + RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + _op @ OperandCode::ModRM_0x80_Eb_Ib | + _op @ OperandCode::ModRM_0x81_Ev_Ivs => { + instruction.operands[0] = mem_oper; + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.opcode = base_opcode_map((modrm >> 3) & 7); + instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + }, + _op @ OperandCode::ModRM_0xc6_Eb_Ib | + _op @ OperandCode::ModRM_0xc7_Ev_Iv => { + if (modrm & 0b00111000) != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string()); + } + + instruction.operands[0] = mem_oper; + instruction.opcode = Opcode::MOV; + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + }, + op @ OperandCode::ModRM_0xc0_Eb_Ib | + op @ OperandCode::ModRM_0xc1_Ev_Ib | + op @ OperandCode::ModRM_0xd0_Eb_1 | + op @ OperandCode::ModRM_0xd1_Ev_1 | + op @ OperandCode::ModRM_0xd3_Ev_CL => { + instruction.operands[0] = mem_oper; + instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); + if let OperandCode::ModRM_0xd3_Ev_CL = op { + instruction.modrm_rrr = RegSpec::cl(); + instruction.operands[1] = OperandSpec::RegRRR; + } else { + let num = match op { + OperandCode::ModRM_0xc0_Eb_Ib | + OperandCode::ModRM_0xc1_Ev_Ib => { + *length += 1; + read_num(&mut bytes_iter, 1)? + } + _ => { + // these are the _1 variants, everything else is unreachable + 1 + } + }; + instruction.imm = num; + instruction.operands[1] = OperandSpec::ImmI8; + } + instruction.operand_count = 2; + }, + _op @ OperandCode::ModRM_0xf6 | + _op @ OperandCode::ModRM_0xf7 => { + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + match (modrm >> 3) & 7 { + 0 | 1 => { + instruction.opcode = Opcode::TEST; + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.operands[1] = match opwidth { + 1 => OperandSpec::ImmI8, + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + }, + 2 => { + instruction.opcode = Opcode::NOT; + }, + 3 => { + instruction.opcode = Opcode::NEG; + }, + 4 => { + instruction.opcode = Opcode::MUL; + }, + 5 => { + instruction.opcode = Opcode::IMUL; + }, + 6 => { + instruction.opcode = Opcode::DIV; + }, + 7 => { + instruction.opcode = Opcode::IDIV; + }, + _ => { + unsafe { unreachable_unchecked(); } + } + } + }, + OperandCode::ModRM_0xfe_Eb => { + instruction.operands[0] = mem_oper; + instruction.opcode = [ + Opcode::INC, + Opcode::DEC, + Opcode::Invalid, + Opcode::Invalid, + Opcode::Invalid, + Opcode::Invalid, + Opcode::Invalid, + Opcode::Invalid + ][((modrm >> 3) & 7) as usize]; + instruction.operand_count = 1; + } + OperandCode::ModRM_0xff_Ev => { + instruction.operands[0] = mem_oper; + let opcode = [ + Opcode::INC, + Opcode::DEC, + Opcode::CALL, + Opcode::CALLF, + Opcode::JMP, + Opcode::JMPF, + Opcode::PUSH, + Opcode::Invalid + ][((modrm >> 3) & 7) as usize]; + instruction.opcode = opcode; + instruction.operand_count = 1; + } + OperandCode::Gv_Eb => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; + + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 1, length)?; + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, + OperandCode::Gv_Ew => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; + + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, + OperandCode::Gdq_Ed => { + let opwidth = 8; + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4 /* opwidth */, length)?; + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, + OperandCode::Ev => { + instruction.operands[0] = mem_oper; + instruction.operand_count = 1; + }, + OperandCode::Gv_M => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr = + RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); + instruction.operand_count = 2; + }, + OperandCode::E_G_xmm => { + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[0] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + }, + OperandCode::G_E_mm => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + } + instruction.operand_count = 2; + }, + OperandCode::G_U_mm => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::D; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + instruction.operand_count = 2; + }, + op @ OperandCode::G_M_xmm | + op @ OperandCode::G_E_xmm => { + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operand_count = 2; + if instruction.operands[1] == OperandSpec::RegMMM { + if op == OperandCode::G_M_xmm { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } else { + // fix the register to XMM + instruction.modrm_mmm.bank = RegisterBank::X; + } + } + }, + OperandCode::G_E_xmm_Ib => { + let modrm = read_modrm(&mut bytes_iter, length)?; + + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.modrm_rrr = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.imm = + read_num(&mut bytes_iter, 1)? as u8 as u64; + *length += 1; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + }, + OperandCode::G_E_mm_Ib => { + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.imm = + read_num(&mut bytes_iter, 1)? as u8 as u64; + *length += 1; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + }, + OperandCode::G_mm_Ew_Ib => { + let modrm = read_modrm(&mut bytes_iter, length)?; + +// println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); + instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); + instruction.operands[0] = OperandSpec::RegRRR; + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } + instruction.imm = + read_num(&mut bytes_iter, 1)? as u8 as u64; + *length += 1; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCode::AL_Ib => { + instruction.modrm_rrr = + RegSpec::al(); + instruction.imm = + read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmI8; + instruction.operand_count = 2; + } + OperandCode::AX_Ivd => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.modrm_rrr = + RegSpec::gp_from_parts(0, false, opwidth, false); + instruction.imm = + read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.operands[1] = match opwidth { + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 2; + } + OperandCode::Ivs => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); + instruction.imm = + read_imm_unsigned(&mut bytes_iter, opwidth, length)?; + instruction.operands[0] = match opwidth { + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 1; + }, + OperandCode::ModRM_0x83_Ev_Ibs => { + instruction.operands[0] = mem_oper; + instruction.opcode = base_opcode_map((modrm >> 3) & 7); + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmI8; + instruction.operand_count = 2; + }, + OperandCode::Jvds => { + let offset = read_num(&mut bytes_iter, 4)?; + *length += 4; + instruction.imm = offset; + instruction.operand_count = 1; + instruction.operands[0] = OperandSpec::ImmI32; + } + OperandCode::Gb_Eb_Ib => { + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = + read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCode::Gv_Ev_Iv => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let numwidth = if opwidth == 8 { 4 } else { opwidth }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = + read_imm_signed(&mut bytes_iter, numwidth, length)? as u64; + instruction.operands[2] = match opwidth { + 2 => OperandSpec::ImmI16, + 4 => OperandSpec::ImmI32, + 8 => OperandSpec::ImmI64, + _ => unsafe { unreachable_unchecked() } + }; + instruction.operand_count = 3; + } + OperandCode::Ev_Gv_Ib => { + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.imm = + read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[2] = OperandSpec::ImmI8; + instruction.operand_count = 3; + } + OperandCode::Ev_Gv_CL => { + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::CL; + instruction.operand_count = 3; + } + OperandCode::Nothing => { + instruction.operand_count = 0; + } + _ => { + unlikely_operands(decoder, bytes_iter, instruction, operand_code, mem_oper, length)?; + } + }; + } + + Ok(()) +} +fn unlikely_operands>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, length: &mut u8) -> Result<(), DecodeError> { + match operand_code { + OperandCode::ModRM_0x0f71 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLW; + } + 4 => { + instruction.opcode = Opcode::PSRAW; + } + 6 => { + instruction.opcode = Opcode::PSLLW; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::ModRM_0x0f72 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLD; + } + 4 => { + instruction.opcode = Opcode::PSRAD; + } + 6 => { + instruction.opcode = Opcode::PSLLD; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::ModRM_0x0f73 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLQ; + } + 6 => { + instruction.opcode = Opcode::PSLLQ; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::ModRM_0x660f38 => { + let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; + match op { + 0xdb => { instruction.opcode = Opcode::AESIMC; } + 0xdc => { instruction.opcode = Opcode::AESENC; } + 0xdd => { instruction.opcode = Opcode::AESENCLAST; } + 0xde => { instruction.opcode = Opcode::AESDEC; } + 0xdf => { instruction.opcode = Opcode::AESDECLAST; } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + }; + // all these SO FAR are G_E_xmm + let modrm = read_modrm(&mut bytes_iter, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); + + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.operand_count = 2; + } + OperandCode::ModRM_0x660f3a => { + let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; + match op { + 0xdf => { + instruction.opcode = Opcode::AESKEYGENASSIST; + // read operands right here right now + + let modrm = read_modrm(&mut bytes_iter, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X); + + + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?; + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 1, length)?; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.operand_count = 3; + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + }; + } + OperandCode::ModRM_0x660f71 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLW; + } + 4 => { + instruction.opcode = Opcode::PSRAW; + } + 6 => { + instruction.opcode = Opcode::PSLLW; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::ModRM_0x660f72 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLD; + } + 4 => { + instruction.opcode = Opcode::PSRAD; + } + 6 => { + instruction.opcode = Opcode::PSLLD; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::ModRM_0x660f73 => { + instruction.operand_count = 2; + + let modrm = read_modrm(&mut bytes_iter, length)?; + if modrm & 0xc0 != 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + let r = (modrm >> 3) & 7; + match r { + 2 => { + instruction.opcode = Opcode::PSRLQ; + } + 3 => { + instruction.opcode = Opcode::PSRLDQ; + } + 6 => { + instruction.opcode = Opcode::PSLLQ; + } + 7 => { + instruction.opcode = Opcode::PSLLDQ; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + + instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.operands[0] = OperandSpec::RegMMM; + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmU8; + }, + OperandCode::G_mm_Edq => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.rex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + } + } + OperandCode::G_mm_E => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + } + } + OperandCode::Edq_G_mm => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.rex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + } + } + OperandCode::E_G_mm => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + } + } + /* + OperandCode::G_xmm_Ed => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::D; + } + }, + */ + OperandCode::G_xmm_Edq => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + if instruction.prefixes.rex().w() { + instruction.modrm_mmm.bank = RegisterBank::Q; + } else { + instruction.modrm_mmm.bank = RegisterBank::D; + } + } + }, + OperandCode::G_xmm_Eq => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::Q; + } + }, + OperandCode::G_mm_E_xmm => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::MM; + instruction.modrm_rrr.num &= 0b111; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::X; + } + }, + OperandCode::G_xmm_E_mm => { + instruction.operands[1] = mem_oper; + instruction.modrm_rrr.bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::MM; + instruction.modrm_mmm.num &= 0b111; + } + }, + // sure hope these aren't backwards huh + OperandCode::AL_Xb => { + instruction.operands[0] = OperandSpec::AL; + instruction.operands[1] = OperandSpec::Deref_rsi; + } + // TODO: two memory operands! this is wrong!!! + OperandCode::Yb_Xb => { + instruction.operands[0] = OperandSpec::Deref_rdi; + instruction.operands[1] = OperandSpec::Deref_rsi; + } + OperandCode::Yb_AL => { + instruction.operands[0] = OperandSpec::Deref_rdi; + instruction.operands[1] = OperandSpec::AL; + } + OperandCode::AX_Xv => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + instruction.modrm_rrr = match opwidth { + 2 => RegSpec::ax(), + 4 => RegSpec::eax(), + 8 => RegSpec::rax(), + _ => { unreachable!(); } + }; + instruction.modrm_mmm = RegSpec::rsi(); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::Deref; + } + OperandCode::Yv_AX => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + instruction.modrm_rrr = match opwidth { + 2 => RegSpec::ax(), + 4 => RegSpec::eax(), + 8 => RegSpec::rax(), + _ => { unreachable!(); } + }; + instruction.modrm_mmm = RegSpec::rdi(); + instruction.operands[0] = OperandSpec::Deref; + instruction.operands[1] = OperandSpec::RegRRR; + } + OperandCode::Yv_Xv => { + // TODO: repsect prefixes + instruction.operands[0] = OperandSpec::Deref_rdi; + instruction.operands[1] = OperandSpec::Deref_rsi; + } + OperandCode::ModRM_0x0f12 => { + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::X; + instruction.opcode = Opcode::MOVHLPS; + } else { + instruction.opcode = Opcode::MOVLPS; + } + } + OperandCode::ModRM_0x0f16 => { + instruction.modrm_rrr.bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.modrm_mmm.bank = RegisterBank::X; + instruction.opcode = Opcode::MOVLHPS; + } else { + instruction.opcode = Opcode::MOVHPS; + } + } + OperandCode::ModRM_0x0f18 => { + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + let rrr = instruction.modrm_rrr.num & 0b111; + instruction.operands[0] = mem_oper; + instruction.opcode = match rrr { + 0 => Opcode::PREFETCHNTA, + 1 => Opcode::PREFETCH0, + 2 => Opcode::PREFETCH1, + 3 => Opcode::PREFETCH2, + _ => Opcode::NOP, + }; + } + OperandCode::Gd_U_xmm => { + instruction.operands[1] = mem_oper; + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_rrr.bank = RegisterBank::D; + instruction.modrm_mmm.bank = RegisterBank::X; + } + OperandCode::M_G_xmm => { + instruction.operands[1] = instruction.operands[0]; + instruction.operands[0] = mem_oper; + if instruction.operands[0] == OperandSpec::RegMMM { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + instruction.modrm_rrr.bank = RegisterBank::X; + } + OperandCode::Ew_Sw => { + let opwidth = 2; + let modrm = read_modrm(&mut bytes_iter, length)?; + + // check r + if ((modrm >> 3) & 7) > 5 { + // return Err(()); //Err("Invalid r".to_owned()); + return Err(DecodeError::InvalidOperand); + } + + instruction.modrm_rrr = + RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + let mod_bits = modrm >> 6; + if mod_bits == 0b11 { + instruction.modrm_mmm = + RegSpec { bank: RegisterBank::W, num: modrm & 7}; + instruction.operands[0] = OperandSpec::RegMMM; + } else { + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + }, + OperandCode::Sw_Ew => { + let modrm = read_modrm(&mut bytes_iter, length)?; + + // check r + if ((modrm >> 3) & 7) > 5 { + // return Err(()); // Err("Invalid r".to_owned()); + return Err(DecodeError::InvalidOperand); + } + + instruction.modrm_rrr = + RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operand_count = 2; + + let mod_bits = modrm >> 6; + if mod_bits == 0b11 { + instruction.modrm_mmm = + RegSpec { bank: RegisterBank::W, num: modrm & 7}; + instruction.operands[1] = OperandSpec::RegMMM; + } else { + instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; + } + }, + OperandCode::CVT_AA => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + instruction.opcode = match opwidth { + 2 => { Opcode::CBW }, + 4 => { Opcode::CWDE }, + 8 => { Opcode::CDQE }, + _ => { unreachable!("invalid operation width"); }, + } + } + OperandCode::CVT_DA => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + instruction.opcode = match opwidth { + 2 => { Opcode::CBD }, + 4 => { Opcode::CDQ }, + 8 => { Opcode::CQO }, + _ => { unreachable!("invalid operation width"); }, + } + } + OperandCode::Iw => { + instruction.imm = + read_imm_unsigned(&mut bytes_iter, 2, length)?; + instruction.operands[0] = OperandSpec::ImmU16; + instruction.operand_count = 1; + } + OperandCode::ModRM_0x0f00 => { + instruction.operand_count = 1; + let modrm = read_modrm(&mut bytes_iter, length)?; + let r = (modrm >> 3) & 7; + if r == 0 { + instruction.opcode = Opcode::SLDT; + } else if r == 1 { + instruction.opcode = Opcode::STR; + } else if r == 2 { + instruction.opcode = Opcode::LLDT; + } else if r == 3 { + instruction.opcode = Opcode::LTR; + } else if r == 4 { + instruction.opcode = Opcode::VERR; + } else if r == 5 { + instruction.opcode = Opcode::VERW; + } else if r == 6 { + instruction.opcode = Opcode::JMPE; + instruction.operand_count = 0; + return Ok(()); + } else if r == 7 { + instruction.opcode = Opcode::Invalid; + instruction.operand_count = 0; + return Err(DecodeError::InvalidOperand); + } else { + unreachable!("r <= 8"); + } + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; + } + OperandCode::ModRM_0x0f01 => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; + let r = (modrm >> 3) & 7; + if r == 0 { + let mod_bits = modrm >> 6; + let m = modrm & 7; + if mod_bits == 0b11 { + instruction.operand_count = 0; + match m { + 0b000 => { + instruction.opcode = Opcode::ENCLV; + }, + 0b001 => { + instruction.opcode = Opcode::VMCALL; + }, + 0b010 => { + instruction.opcode = Opcode::VMLAUNCH; + }, + 0b011 => { + instruction.opcode = Opcode::VMRESUME; + }, + 0b100 => { + instruction.opcode = Opcode::VMXOFF; + }, + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } else { + instruction.opcode = Opcode::SGDT; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + } else if r == 1 { + let mod_bits = modrm >> 6; + let m = modrm & 7; + if mod_bits == 0b11 { + instruction.operand_count = 0; + match m { + 0b000 => { + instruction.opcode = Opcode::MONITOR; + } + 0b001 => { + instruction.opcode = Opcode::MWAIT; + }, + 0b010 => { + instruction.opcode = Opcode::CLAC; + } + 0b011 => { + instruction.opcode = Opcode::STAC; + } + 0b111 => { + instruction.opcode = Opcode::ENCLS; + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } else { + instruction.opcode = Opcode::SIDT; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + } else if r == 2 { + let mod_bits = modrm >> 6; + let m = modrm & 7; + if mod_bits == 0b11 { + instruction.operand_count = 0; + match m { + 0b000 => { + instruction.opcode = Opcode::XGETBV; + } + 0b001 => { + instruction.opcode = Opcode::XSETBV; + } + 0b100 => { + instruction.opcode = Opcode::VMFUNC; + } + 0b101 => { + instruction.opcode = Opcode::XEND; + } + 0b110 => { + instruction.opcode = Opcode::XTEST; + } + 0b111 => { + instruction.opcode = Opcode::ENCLU; + } + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } else { + instruction.opcode = Opcode::LGDT; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + } else if r == 3 { + let mod_bits = modrm >> 6; + if mod_bits == 0b11 { + instruction.opcode = Opcode::Invalid; + instruction.operand_count = 0; + return Err(DecodeError::InvalidOperand); + } else { + instruction.opcode = Opcode::LIDT; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + } else if r == 4 { + // TODO: this permits storing only to word-size registers + // spec suggets this might do something different for f.ex rdi? + instruction.opcode = Opcode::SMSW; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; + } else if r == 5 { + let m = modrm & 7; + match m { + 0b110 => { + instruction.opcode = Opcode::RDPKRU; + instruction.operand_count = 1; + } + 0b111 => { + instruction.opcode = Opcode::WRPKRU; + instruction.operand_count = 1; + } + _ => { + instruction.opcode = Opcode::Invalid; + instruction.operand_count = 0; + return Err(DecodeError::InvalidOpcode); + } + } + } else if r == 6 { + instruction.opcode = Opcode::LMSW; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; + } else if r == 7 { + let mod_bits = modrm >> 6; + let m = modrm & 7; + if mod_bits == 0b11 { + if m == 0 { + instruction.opcode = Opcode::SWAPGS; + instruction.operand_count = 0; + } else if m == 1 { + instruction.opcode = Opcode::RDTSCP; + instruction.operand_count = 0; + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } else { + instruction.opcode = Opcode::INVLPG; + instruction.operand_count = 1; + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + } + } else { + unreachable!("r <= 8"); + } + } + OperandCode::ModRM_0x0fae => { + let modrm = read_modrm(&mut bytes_iter, length)?; + let r = (modrm >> 3) & 7; + let mod_bits = modrm >> 6; + + // all the 0b11 instructions are err or no-operands + if mod_bits == 0b11 { + instruction.operand_count = 0; + let m = modrm & 7; + match r { + // invalid rrr for 0x0fae, mod: 11 + 0 | 1 | 2 | 3 | 4 => { + return Err(DecodeError::InvalidOpcode); + }, + 5 => { + instruction.opcode = Opcode::LFENCE; + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { + if m != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + } + }, + 6 => { + instruction.opcode = Opcode::MFENCE; + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { + if m != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + } + }, + 7 => { + instruction.opcode = Opcode::SFENCE; + // Intel's manual accepts m != 0, AMD supports m != 0 though the manual + // doesn't say (tested on threadripper) + if !decoder.amd_quirks() && !decoder.intel_quirks() { + if m != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + } + }, + _ => { unsafe { unreachable_unchecked() } /* r <=7 */ } + } + } else { + instruction.operand_count = 1; + instruction.opcode = [ + Opcode::FXSAVE, + Opcode::FXRSTOR, + Opcode::LDMXCSR, + Opcode::STMXCSR, + Opcode::XSAVE, + Opcode::XRSTOR, + Opcode::XSAVEOPT, + Opcode::CLFLUSH, + ][r as usize]; + instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; + } + } + OperandCode::ModRM_0x0fba => { + let opwidth = imm_width_from_prefixes_64(SizeCode::vq, instruction.prefixes); + let modrm = read_modrm(&mut bytes_iter, length)?; + let r = (modrm >> 3) & 7; + match r { + 0 | 1 | 2 | 3 => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }, + 4 => { + instruction.opcode = Opcode::BT; + } + 5 => { + instruction.opcode = Opcode::BTS; + } + 6 => { + instruction.opcode = Opcode::BTR; + } + 7 => { + instruction.opcode = Opcode::BTC; + } + _ => { + unreachable!("r < 8"); + } + } + + instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; + + instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64; + instruction.operands[1] = OperandSpec::ImmI8; + instruction.operand_count = 2; + } + op @ OperandCode::Rq_Cq_0 | + op @ OperandCode::Rq_Dq_0 | + op @ OperandCode::Cq_Rq_0 | + op @ OperandCode::Dq_Rq_0 => { + let bank = match op { + OperandCode::Rq_Cq_0 | + OperandCode::Cq_Rq_0 => RegisterBank::CR, + OperandCode::Rq_Dq_0 | + OperandCode::Dq_Rq_0 => RegisterBank::DR, + _ => unsafe { unreachable_unchecked() } + }; + let (rrr, mmm) = match op { + OperandCode::Rq_Cq_0 | + OperandCode::Rq_Dq_0 => (1, 0), + OperandCode::Cq_Rq_0 | + OperandCode::Dq_Rq_0 => (0, 1), + _ => unsafe { unreachable_unchecked() } + }; + + let modrm = read_modrm(&mut bytes_iter, length)?; + let mut m = modrm & 7; + let mut r = (modrm >> 3) & 7; + if instruction.prefixes.rex().r() { + r += 0b1000; + } + if instruction.prefixes.rex().b() { + m += 0b1000; + } + instruction.modrm_rrr = + RegSpec { bank: bank, num: r }; + instruction.modrm_mmm = + RegSpec { bank: RegisterBank::Q, num: m }; + instruction.operands[mmm] = OperandSpec::RegMMM; + instruction.operands[rrr] = OperandSpec::RegRRR; + instruction.operand_count = 2; + } + OperandCode::FS => { + instruction.modrm_rrr = RegSpec::fs(); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operand_count = 1; + } + OperandCode::GS => { + instruction.modrm_rrr = RegSpec::gs(); + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operand_count = 1; + } + OperandCode::I_3 => { + instruction.imm = 3; + instruction.operands[0] = OperandSpec::ImmU8; + instruction.operand_count = 1; + } + _ => { + instruction.operand_count = 0; + instruction.opcode = Opcode::Invalid; +// return Err(()); // Err(format!("unsupported operand code: {:?}", operand_code)); + return Err(DecodeError::InvalidOperand); + } + }; + Ok(()) +} + +fn decode_one<'b, T: IntoIterator>(decoder: &InstDecoder, bytes: T, instr: &'b mut Instruction) -> Result<(), DecodeError> { + instr.operands = [ + OperandSpec::Nothing, + OperandSpec::Nothing, + OperandSpec::Nothing, + OperandSpec::Nothing, + ]; + let bytes_iter = bytes.into_iter(); + read_instr(decoder, bytes_iter, instr) +} + +#[inline] +fn read_num>(bytes: &mut T, width: u8) -> Result { + let mut result = 0u64; + let mut idx = 0; + loop { + if idx == width { + return Ok(result); + } + let byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + result |= (byte as u64) << (idx * 8); + idx += 1; + } +} + +#[inline] +fn read_imm_ivq>(bytes: &mut T, width: u8, length: &mut u8) -> Result { + match width { + 2 => { + *length += 2; + Ok(read_num(bytes, 2)? as u16 as u64) + }, + 4 => { + *length += 4; + Ok(read_num(bytes, 4)? as u32 as u64) + }, + 8 => { + *length += 8; + Ok(read_num(bytes, 8)? as u64) + }, + _ => { + unsafe { unreachable_unchecked(); } + } + } +} + +#[inline] +fn read_imm_signed>(bytes: &mut T, num_width: u8, length: &mut u8) -> Result { + if num_width == 1 { + *length += 1; + Ok(read_num(bytes, 1)? as i8 as i64) + } else if num_width == 2 { + *length += 2; + Ok(read_num(bytes, 2)? as i16 as i64) + } else { + *length += 4; + // this is for 4 and 8, the only values for num_width may be 1, 2, 4, and 8. + Ok(read_num(bytes, 4)? as i32 as i64) + } +} + +#[inline] +fn read_imm_unsigned>(bytes: &mut T, width: u8, length: &mut u8) -> Result { + read_num(bytes, width).map(|res| { + *length += width; + res + }) +} + +#[inline] +fn imm_width_from_prefixes_64(interpretation: SizeCode, prefixes: Prefixes) -> u8 { + match interpretation { + SizeCode::b => 1, + SizeCode::vd => { + if prefixes.rex().w() || !prefixes.operand_size() { 4 } else { 2 } + }, + SizeCode::vq => { + // TODO: this should be address_size + // but i'm not sure if that breaks other instructions rn + if prefixes.operand_size() { + 2 + } else { + 8 // TODO: this 8 should be arch width. + } + }, + SizeCode::vqp => { + if prefixes.rex().w() { + 8 + } else if prefixes.operand_size() { + 2 + } else { + 4 + } + }, + } +} + +#[inline] +fn read_modrm>(bytes_iter: &mut T, length: &mut u8) -> Result { + bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b }) +} diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs new file mode 100644 index 0000000..5c671d8 --- /dev/null +++ b/src/long_mode/vex.rs @@ -0,0 +1,2363 @@ +use crate::long_mode::OperandSpec; +use crate::long_mode::DecodeError; +use crate::long_mode::RegSpec; +use crate::long_mode::RegisterBank; +use crate::long_mode::Instruction; +use crate::long_mode::Opcode; +use crate::long_mode::read_modrm; +use crate::long_mode::read_E; +use crate::long_mode::read_E_xmm; +use crate::long_mode::read_E_ymm; +use crate::long_mode::read_imm_unsigned; + +#[derive(Debug)] +enum VEXOpcodeMap { + Map0F, + Map0F38, + Map0F3A, +} + +#[derive(Debug)] +enum VEXOpcodePrefix { + None, + Prefix66, + PrefixF3, + PrefixF2, +} + +#[allow(non_camel_case_types)] +#[derive(Debug)] +enum VEXOperandCode { + Nothing, + VPS_71, + VPS_71_L, + VPS_72, + VPS_72_L, + VPS_73, + VPS_73_L, + VMOVSS_10, + VMOVSD_10, + VMOVSD_11, + VMOVSS_11, + E_G_xmm, + U_G_xmm, + M_G_xmm, + G_M_xmm, + G_U_xmm, + E_G_xmm_imm8, + U_G_xmm_imm8, + E_G_ymm, + U_G_ymm, + M_G_ymm, + G_E_ymm, + G_M_ymm, + G_U_ymm, + E_V_G_ymm, + E_V_G_xmm, + E_xmm_G_ymm_imm8, + Ev_G_xmm_imm8, + G_Ex_V_xmm, + G_Ey_V_ymm, + G_E_xmm, + G_E_xmm_imm8, + G_E_ymm_imm8, + G_xmm_E_xmm, + G_xmm_E_ymm, + G_ymm_E_xmm, + G_ymm_E_ymm, + G_V_ymm_E_xmm, + M_V_G_xmm, + M_V_G_ymm, + G_V_E_xmm, + G_V_E_xmm_imm8, + G_V_E_xmm_xmm4, + G_V_E_ymm, + G_V_E_ymm_imm8, + G_V_E_ymm_ymm4, + G_V_M_xmm, + G_V_M_ymm, + V_xmm_G_ymm_E_ymm_imm8, + V_ymm_G_ymm_E_xmm_imm8, + G_V_xmm_Ew_imm8, + Eq_G_xmm, + Ed_G_xmm, + G_xmm_Ed, + G_xmm_Eq, +} + +#[inline(never)] +pub(crate) fn three_byte_vex>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), DecodeError> { + let vex_byte_one = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + let vex_byte_two = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + length += 2; + let p = vex_byte_two & 0x03; + let p = match p { + 0x00 => VEXOpcodePrefix::None, + 0x01 => VEXOpcodePrefix::Prefix66, + 0x02 => VEXOpcodePrefix::PrefixF3, + 0x03 => VEXOpcodePrefix::PrefixF2, + _ => { unreachable!("p is two bits"); } + }; + let m = vex_byte_one & 0b11111; +// println!("m: {:05b}", m); + let m = match m { + 0b00001 => VEXOpcodeMap::Map0F, + 0b00010 => VEXOpcodeMap::Map0F38, + 0b00011 => VEXOpcodeMap::Map0F3A, + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + }; + instruction.vex_reg = RegSpec { + bank: RegisterBank::X, + num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111, + }; + instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); + + read_vex_instruction(m, bytes, instruction, &mut length, p)?; + instruction.length = length; + Ok(()) +} + +pub(crate) fn two_byte_vex>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), DecodeError> { + let vex_byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + length += 1; + let p = vex_byte & 0x03; + let p = match p { + 0x00 => VEXOpcodePrefix::None, + 0x01 => VEXOpcodePrefix::Prefix66, + 0x02 => VEXOpcodePrefix::PrefixF3, + 0x03 => VEXOpcodePrefix::PrefixF2, + _ => { unreachable!("p is two bits"); } + }; + instruction.vex_reg = RegSpec { + bank: RegisterBank::X, + num: ((vex_byte >> 3) & 0b1111) ^ 0b1111, + }; + instruction.prefixes.vex_from_c5(vex_byte); + + read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p)?; + instruction.length = length; + Ok(()) +} + +fn read_vex_operands>(bytes: &mut T, instruction: &mut Instruction, length: &mut u8, operand_code: VEXOperandCode) -> Result<(), DecodeError> { +// println!("operand code: {:?}", operand_code); + match operand_code { + VEXOperandCode::VPS_71 => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b010 => { + instruction.opcode = Opcode::VPSRLW; + } + 0b100 => { + instruction.opcode = Opcode::VPSRAW; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLW; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + /* + 0x71 => (Opcode::VPSLLW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRAW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRLW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }), + */ + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VPS_71_L => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b010 => { + instruction.opcode = Opcode::VPSRLW; + } + 0b100 => { + instruction.opcode = Opcode::VPSRAW; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLW; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + /* + 0x71 => (Opcode::VPSLLW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRAW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x71 => (Opcode::VPSRLW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }), + */ + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VPS_72 => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b010 => { + instruction.opcode = Opcode::VPSRLD; + } + 0b100 => { + instruction.opcode = Opcode::VPSRAD; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLD; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + /* + 0x72 => (Opcode::VPSLLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRAD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + */ + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VPS_72_L => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b010 => { + instruction.opcode = Opcode::VPSRLD; + } + 0b100 => { + instruction.opcode = Opcode::VPSRAD; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLD; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + /* + 0x72 => (Opcode::VPSLLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRAD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x72 => (Opcode::VPSRLD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + */ + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VPS_73 => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b010 => { + instruction.opcode = Opcode::VPSRLQ; + } + 0b011 => { + instruction.opcode = Opcode::VPSRLDQ; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLQ; + } + 0b111 => { + instruction.opcode = Opcode::VPSLLDQ; + } + _ => { + return Err(DecodeError::InvalidOpcode); + } + } + // VEXOperandCode::G_E_xmm_imm8 ? this is reg1, reg2, imm8, but r is used for + // picking the opcode. is one of these actually the vex reg? + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VPS_73_L => { + let modrm = read_modrm(bytes, length)?; + match (modrm >> 3) & 0b111 { + 0b000 | + 0b001 | + 0b100 | + 0b101 => { + return Err(DecodeError::InvalidOpcode); + } + 0b010 => { + instruction.opcode = Opcode::VPSRLQ; + } + 0b011 => { + instruction.opcode = Opcode::VPSRLDQ; + } + 0b110 => { + instruction.opcode = Opcode::VPSLLQ; + } + 0b111 => { + instruction.opcode = Opcode::VPSLLDQ; + } + _ => { + unreachable!("r is only three bits"); + } + } + // VEXOperandCode::G_E_ymm_imm8 ? this is reg1, reg2, imm8, but r is used for + // picking the opcode. is one of these actually the vex reg? + Err(DecodeError::IncompleteDecoder) // :) + } + VEXOperandCode::VMOVSS_10 | + VEXOperandCode::VMOVSD_10 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + match mem_oper { + OperandSpec::RegMMM => { + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegMMM; + }, + other => { + instruction.operands[1] = other; + } + } + Ok(()) + }, + VEXOperandCode::VMOVSS_11 | + VEXOperandCode::VMOVSD_11 => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[1] = OperandSpec::RegRRR; + match mem_oper { + OperandSpec::RegMMM => { + instruction.operands[0] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegMMM; + }, + other => { + instruction.operands[0] = other; + } + } + Ok(()) + }, + VEXOperandCode::Nothing => { + Ok(()) + }, + VEXOperandCode::Ev_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[2] = OperandSpec::ImmU8; + instruction.imm = read_imm_unsigned(bytes, 1, length)?; + Ok(()) + }, + _op @ VEXOperandCode::E_G_xmm | + _op @ VEXOperandCode::U_G_xmm | + _op @ VEXOperandCode::M_G_xmm | + _op @ VEXOperandCode::E_G_xmm_imm8 | + _op @ VEXOperandCode::U_G_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } + + _op @ VEXOperandCode::G_M_xmm | + _op @ VEXOperandCode::G_U_xmm | + _op @ VEXOperandCode::G_E_xmm | + _op @ VEXOperandCode::G_E_xmm_imm8 => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + + _op @ VEXOperandCode::E_G_ymm | + _op @ VEXOperandCode::U_G_ymm | + _op @ VEXOperandCode::M_G_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + Ok(()) + } + + _op @ VEXOperandCode::G_M_ymm | + _op @ VEXOperandCode::G_U_ymm | + _op @ VEXOperandCode::G_E_ymm => { + if instruction.vex_reg.num != 0 { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOperand); + } + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + Ok(()) + } + _op @ VEXOperandCode::G_V_E_ymm | + _op @ VEXOperandCode::G_V_M_ymm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + Ok(()) + } + _op @ VEXOperandCode::E_V_G_ymm | + _op @ VEXOperandCode::M_V_G_ymm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + instruction.vex_reg.bank = RegisterBank::Y; + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegRRR; + Ok(()) + } + _op @ VEXOperandCode::G_V_M_xmm | + _op @ VEXOperandCode::G_V_E_xmm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + Ok(()) + } + + _op @ VEXOperandCode::E_V_G_xmm | + _op @ VEXOperandCode::M_V_G_xmm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegRRR; + Ok(()) + } + + VEXOperandCode::G_Ex_V_xmm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); + let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; + instruction.sib_index.bank = RegisterBank::X; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operands[2] = OperandSpec::RegVex; + Ok(()) + } + VEXOperandCode::G_Ey_V_ymm => { + let modrm = read_modrm(bytes, length)?; + instruction.modrm_rrr = + RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); + let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; + instruction.vex_reg.bank = RegisterBank::Y; + instruction.sib_index.bank = RegisterBank::Y; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.operands[2] = OperandSpec::RegVex; + Ok(()) + } + + VEXOperandCode::E_xmm_G_ymm_imm8 | + VEXOperandCode::G_E_ymm_imm8 | + VEXOperandCode::G_xmm_E_xmm | + VEXOperandCode::G_xmm_E_ymm | + VEXOperandCode::G_ymm_E_xmm | + VEXOperandCode::G_ymm_E_ymm | + VEXOperandCode::G_V_E_xmm_imm8 | + VEXOperandCode::G_V_E_xmm_xmm4 | + VEXOperandCode::G_V_E_ymm_imm8 | + VEXOperandCode::G_V_E_ymm_ymm4 | + VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 | + VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 | + VEXOperandCode::Eq_G_xmm | + VEXOperandCode::Ed_G_xmm | + VEXOperandCode::G_xmm_Ed | + VEXOperandCode::G_xmm_Eq | + VEXOperandCode::G_V_ymm_E_xmm | + VEXOperandCode::G_V_xmm_Ew_imm8 => { + Err(DecodeError::IncompleteDecoder) // :) + } + + } +} + +fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: &mut T, instruction: &mut Instruction, length: &mut u8, p: VEXOpcodePrefix) -> Result<(), DecodeError> { + let opc = bytes.next().ok_or(DecodeError::ExhaustedInput)?; + *length += 1; + + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex().l(); + +// println!("reading vex instruction from opcode prefix {:?}, L: {}, opc: {:#x}, map:{:?}", p, L, opc, opcode_map); +// println!("w? {}", instruction.prefixes.vex().w()); + + // several combinations simply have no instructions. check for those first. + let (opcode, operand_code) = match opcode_map { + VEXOpcodeMap::Map0F => { + match p { + VEXOpcodePrefix::None => { + match opc { + 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + // ugh +// 0x12 => (Opcode::VMOVHLPS, ..), +// 0x12 => (Opcode::VMOVLPS, ..), + 0x13 => (Opcode::VMOVLPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::M_G_xmm + }), + 0x14 => (Opcode::VUNPCKLPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x15 => (Opcode::VUNPCKHPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + // ugh +// 0x16 => (Opcode::VMOVHPS, ..), +// 0x16 => (Opcode::VMOVLHPS, ..), + 0x17 => (Opcode::VMOVHPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::M_G_xmm + }), + 0x28 => (Opcode::VMOVAPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x29 => (Opcode::VMOVAPS, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0x2B => (Opcode::VMOVNTPS, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0x2e => (Opcode::VUCOMISS, VEXOperandCode::G_E_xmm), + 0x2f => (Opcode::VCOMISS, VEXOperandCode::G_E_xmm), + 0x50 => (Opcode::VMOVMSKPS, if L { + VEXOperandCode::U_G_ymm + } else { + VEXOperandCode::U_G_xmm + }), + 0x51 => (Opcode::VSQRTPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x52 => (Opcode::VRSQRTPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x53 => (Opcode::VRCPPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x57 => (Opcode::VXORPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x58 => (Opcode::VADDPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x59 => (Opcode::VMULPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5A => (Opcode::VCVTPS2PD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5B => (Opcode::VCVTDQ2PS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5C => (Opcode::VSUBPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5D => (Opcode::VMINPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5E => (Opcode::VDIVPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5F => (Opcode::VMAXPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing), + 0xC2 => (Opcode::VCMPPS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0xC6 => (Opcode::VSHUFPS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + }, + VEXOpcodePrefix::Prefix66 => { + match opc { + 0x0a => (Opcode::VROUNDSS, VEXOperandCode::G_V_E_xmm_imm8), + 0x0b => (Opcode::VROUNDSD, VEXOperandCode::G_V_E_xmm_imm8), + 0x10 => (Opcode::VMOVUPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x11 => (Opcode::VMOVUPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x12 => (Opcode::VMOVLPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_M_xmm + }), + 0x13 => (Opcode::VMOVLPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::M_G_xmm + }), + 0x14 => (Opcode::VUNPCKLPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x15 => (Opcode::VUNPCKHPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x16 => (Opcode::VMOVHPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_M_xmm + }), + 0x17 => (Opcode::VMOVHPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::M_G_xmm + }), + 0x28 => (Opcode::VMOVAPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x29 => (Opcode::VMOVAPD, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0x2B => (Opcode::VMOVNTPD, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0x2e => (Opcode::VUCOMISD, VEXOperandCode::G_E_xmm), + 0x2f => (Opcode::VCOMISD, VEXOperandCode::G_E_xmm), + 0x50 => (Opcode::VMOVMSKPD, if L { + VEXOperandCode::G_U_ymm + } else { + VEXOperandCode::G_U_xmm + }), + 0x51 => (Opcode::VSQRTPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x57 => (Opcode::VXORPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x58 => (Opcode::VADDPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x59 => (Opcode::VMULPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5A => (Opcode::VCVTPD2PS, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_xmm_E_xmm + }), + 0x5B => (Opcode::VCVTPS2DQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5C => (Opcode::VSUBPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5D => (Opcode::VMINPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5E => (Opcode::VDIVPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x5F => (Opcode::VMAXPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x60 => (Opcode::VPUNPCKLBW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x61 => (Opcode::VPUNPCKLWD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x62 => (Opcode::VPUNPCKLDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x63 => (Opcode::VPACKSSWB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x64 => (Opcode::VPCMPGTB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x65 => (Opcode::VPCMPGTW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x66 => (Opcode::VPCMPGTD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x67 => (Opcode::VPACKUSWB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x68 => (Opcode::VPUNPCKHBW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x69 => (Opcode::VPUNPCKHWD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x6A => (Opcode::VPUNPCKHDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x6B => (Opcode::VPACKSSDW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x6C => (Opcode::VPUNPCKLQDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x6D => (Opcode::VPUNPCKHQDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x6E => if instruction.prefixes.vex().w() { + (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_xmm_Eq + }) + } else { + (Opcode::VMOVD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_xmm_Ed + }) + }, + 0x6F => (Opcode::VMOVDQA, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x70 => (Opcode::VPSHUFD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x71 => (Opcode::Invalid, if L { + VEXOperandCode::VPS_71_L + } else { + VEXOperandCode::VPS_71 + }), + 0x72 => (Opcode::Invalid, if L { + VEXOperandCode::VPS_72_L + } else { + VEXOperandCode::VPS_72 + }), + 0x73 => (Opcode::Invalid, if L { + VEXOperandCode::VPS_73_L + } else { + VEXOperandCode::VPS_73 + }), + 0x74 => (Opcode::VPCMPEQB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x75 => (Opcode::VPCMPEQW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x76 => (Opcode::VPCMPEQD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x7C => (Opcode::VHADDPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x7D => (Opcode::VHSUBPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x7E => if instruction.prefixes.vex().w() { + (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::Eq_G_xmm + }) + } else { + (Opcode::VMOVD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::Ed_G_xmm + }) + } + 0x7F => (Opcode::VMOVDQA, if L { + VEXOperandCode::E_G_ymm + } else { + VEXOperandCode::E_G_xmm + }), + 0xC2 => (Opcode::VCMPPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xC4 => (Opcode::VPINSRW, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_xmm_Ew_imm8 + }), + 0xC5 => (Opcode::VPEXTRW, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::U_G_xmm_imm8 + }), + 0xC6 => (Opcode::VSHUFPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD0 => (Opcode::VADDSUBPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD1 => (Opcode::VPSRLW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD2 => (Opcode::VPSRLD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD3 => (Opcode::VPSRLQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD4 => (Opcode::VPADDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD5 => (Opcode::VPMULLW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD6 => (Opcode::VMOVQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm + }), + 0xD7 => (Opcode::VPMOVMSKB, if L { + VEXOperandCode::U_G_ymm + } else { + VEXOperandCode::U_G_xmm + }), + 0xD8 => (Opcode::VPSUBUSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xD9 => (Opcode::VPSUBUSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDB => (Opcode::VPAND, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDC => (Opcode::VPADDUSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0xDD => (Opcode::VPADDUSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDF => (Opcode::VPANDN, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE0 => (Opcode::VPAVGB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE1 => (Opcode::VPSRAW, if L { + VEXOperandCode::G_V_ymm_E_xmm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE2 => (Opcode::VPSRAD, if L { + VEXOperandCode::G_V_ymm_E_xmm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE3 => (Opcode::VPAVGW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE4 => (Opcode::VPMULHUW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE5 => (Opcode::VPMULHW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE6 => (Opcode::VCVTTPD2DQ, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0xE7 => (Opcode::VMOVNTDQ, if L { + VEXOperandCode::M_G_ymm + } else { + VEXOperandCode::M_G_xmm + }), + 0xE8 => (Opcode::VPSUBSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xE9 => (Opcode::VPSUBSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xEB => (Opcode::VPOR, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xEC => (Opcode::VPADDSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xED => (Opcode::VPADDSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xEE => (Opcode::VPMAXSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xEF => (Opcode::VPXOR, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF1 => (Opcode::VPSLLW, if L { + VEXOperandCode::G_V_ymm_E_xmm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF2 => (Opcode::VPSLLD, if L { + VEXOperandCode::G_V_ymm_E_xmm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF3 => (Opcode::VPSLLQ, if L { + VEXOperandCode::G_V_ymm_E_xmm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF4 => (Opcode::VPMULUDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF5 => (Opcode::VPMADDWD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF6 => (Opcode::VPSADBW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF7 => (Opcode::VMASKMOVDQU, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm + }), + 0xF8 => (Opcode::VPSUBB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xF9 => (Opcode::VPSUBW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xFA => (Opcode::VPSUBD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xFB => (Opcode::VPSUBQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xFC => (Opcode::VPADDB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xFD => (Opcode::VPADDW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xFE => (Opcode::VPADDD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } + VEXOpcodePrefix::PrefixF2 => { + match opc { + 0x10 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_10), + 0x11 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_11), + 0x12 => (Opcode::VMOVDDUP, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x2a => (Opcode::VCVTSI2SD, if instruction.prefixes.vex().w() { + VEXOperandCode::G_V_E_xmm // 64-bit last operand + } else { + VEXOperandCode::G_V_E_xmm // 32-bit last operand + }), + 0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::G_E_xmm // 64-bit + } else { + VEXOperandCode::G_E_xmm // 32-bit + }), + 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::G_E_xmm // 64-bit + } else { + VEXOperandCode::G_E_xmm // 32-bit + }), + 0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm), + 0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm), + 0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm), + 0x5a => (Opcode::CVTSD2SS, VEXOperandCode::G_V_E_xmm), + 0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm), + 0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm), + 0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm), + 0x5f => (Opcode::VMAXSD, VEXOperandCode::G_V_E_xmm), + 0x70 => (Opcode::VPSHUFLW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x7c => (Opcode::VHADDPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x7d => (Opcode::VHSUBPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xc2 => (Opcode::VCMPSD, VEXOperandCode::G_V_E_xmm_imm8), + 0xd0 => (Opcode::VADDSUBPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xe6 => (Opcode::VCVTPD2DQ, if L { + VEXOperandCode::G_xmm_E_ymm + } else { + VEXOperandCode::G_xmm_E_xmm + }), + 0xf0 => (Opcode::VLDDQU, if L { + VEXOperandCode::G_M_ymm + } else { + VEXOperandCode::G_M_ymm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } + VEXOpcodePrefix::PrefixF3 => { + match opc { + 0x10 => (Opcode::VMOVSS, VEXOperandCode::VMOVSS_10), + 0x11 => (Opcode::VMOVSS, VEXOperandCode::VMOVSS_11), + 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x2a => (Opcode::VCVTSI2SS, if instruction.prefixes.vex().w() { + VEXOperandCode::G_V_E_xmm // 64-bit last operand + } else { + VEXOperandCode::G_V_E_xmm // 32-bit last operand + }), + 0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::G_E_xmm // 64-bit + } else { + VEXOperandCode::G_E_xmm // 32-bit + }), + 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { + VEXOperandCode::G_E_xmm // 64-bit + } else { + VEXOperandCode::G_E_xmm // 32-bit + }), + 0x51 => (Opcode::VSQRTSS, VEXOperandCode::G_V_E_xmm), + 0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm), + 0x53 => (Opcode::VRCPSS, VEXOperandCode::G_V_E_xmm), + 0x58 => (Opcode::VADDSS, VEXOperandCode::G_V_E_xmm), + 0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_E_xmm), + 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_E_xmm), + 0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }), + 0x5c => (Opcode::VSUBSS, VEXOperandCode::G_V_E_xmm), + 0x5d => (Opcode::VMINSS, VEXOperandCode::G_V_E_xmm), + 0x5e => (Opcode::VDIVSS, VEXOperandCode::G_V_E_xmm), + 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_E_xmm), + 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), + 0x70 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm_imm8 } else { VEXOperandCode::G_E_xmm_imm8 }), + 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), + 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), + 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } + } + } + VEXOpcodeMap::Map0F38 => { + // TODO: verify rejecting invalid W bit + if let VEXOpcodePrefix::Prefix66 = p { + // possibly valid! + match opc { + 0x00 => (Opcode::VPSHUFB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x01 => (Opcode::VPHADDW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x02 => (Opcode::VPHADDD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x03 => (Opcode::VPHADDSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x04 => (Opcode::VPHADDUBSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x05 => (Opcode::VPHSUBW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x06 => (Opcode::VPHSUBD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x07 => (Opcode::VPHSUBSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x08 => (Opcode::VPSIGNB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x09 => (Opcode::VPSIGNW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x0A => (Opcode::VPSIGND, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x0B => (Opcode::VPMULHRSW, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x0C => (Opcode::VPERMILPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x0D => (Opcode::VPERMILPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x0E => (Opcode::VTESTPS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x0F => (Opcode::VTESTPD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x13 => (Opcode::VCVTPH2PS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x16 => (Opcode::VPERMPS, if L { + VEXOperandCode::G_V_E_xmm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x17 => (Opcode::VPTEST, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x18 => (Opcode::VBROADCASTSS, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x19 => (Opcode::VBROADCASTSD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x1A => (Opcode::VBROADCASTF128, if L { + VEXOperandCode::G_M_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x1C => (Opcode::VPABSB, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x1D => (Opcode::VPABSW, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x1E => (Opcode::VPABSD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x20 => (Opcode::VPMOVSXBW, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x21 => (Opcode::VPMOVSXBD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x22 => (Opcode::VPMOVSXBQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x23 => (Opcode::VPMOVSXWD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x24 => (Opcode::VPMOVSXWQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x25 => (Opcode::VPMOVSXDQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x28 => (Opcode::VPMULDQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x29 => (Opcode::VPCMPEQQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x2A => (Opcode::VMOVNTDQA, if L { + VEXOperandCode::G_M_ymm + } else { + VEXOperandCode::G_M_xmm + }), + 0x2C => (Opcode::VMASKMOVPS, if L { + VEXOperandCode::G_V_M_ymm + } else { + VEXOperandCode::G_V_M_xmm + }), + 0x2D => (Opcode::VMASKMOVPD, if L { + VEXOperandCode::G_V_M_ymm + } else { + VEXOperandCode::G_V_M_xmm + }), + 0x2E => (Opcode::VMASKMOVPS, if L { + VEXOperandCode::M_V_G_ymm + } else { + VEXOperandCode::M_V_G_xmm + }), + 0x2F => (Opcode::VMASKMOVPD, if L { + VEXOperandCode::M_V_G_ymm + } else { + VEXOperandCode::M_V_G_xmm + }), + 0x30 => (Opcode::VPMOVZXBW, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x31 => (Opcode::VPMOVZXBD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x32 => (Opcode::VPMOVZXBQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x33 => (Opcode::VPMOVZXWD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x34 => (Opcode::VPMOVZXWQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x35 => (Opcode::VPMOVZXDQ, if L { + VEXOperandCode::G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x36 => (Opcode::VPERMD, if L { + VEXOperandCode::G_V_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x37 => (Opcode::VPCMPGTQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x39 => (Opcode::VPMINSD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x3B => (Opcode::VPMINUD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x3C => (Opcode::VPMAXSB, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x3D => (Opcode::VPMAXSD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x3F => (Opcode::VPMAXUD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x40 => (Opcode::VPMULLD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x41 => (Opcode::VPHMINPOSUW, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm + }), + 0x45 => if instruction.prefixes.vex().w() { + (Opcode::VPSRLVQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }) + } else { + (Opcode::VPSRLVD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }) + }, + 0x46 => (Opcode::VPSRAVD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x47 => if instruction.prefixes.vex().w() { + (Opcode::VPSLLVQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }) + } else { + (Opcode::VPSLLVD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }) + }, + 0x58 => (Opcode::VPBROADCASTD, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x59 => (Opcode::VPBROADCASTQ, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_xmm + }), + 0x5A => (Opcode::VBROADCASTI128, if L { + VEXOperandCode::G_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x78 => (Opcode::VPBROADCASTB, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_ymm + }), + 0x79 => (Opcode::VPBROADCASTW, if L { + VEXOperandCode::G_E_ymm + } else { + VEXOperandCode::G_E_ymm + }), + 0x8C => { + if instruction.prefixes.vex().w() { + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x8E => { + if instruction.prefixes.vex().w() { + (Opcode::VPMASKMOVD, if L { + VEXOperandCode::E_V_G_ymm + } else { + VEXOperandCode::E_V_G_xmm + }) + } else { + (Opcode::VPMASKMOVQ, if L { + VEXOperandCode::E_V_G_ymm + } else { + VEXOperandCode::E_V_G_xmm + }) + } + }, + 0x90 => { + if instruction.prefixes.vex().w() { + (Opcode::VPGATHERDQ, if L { + VEXOperandCode::G_Ey_V_ymm + } else { + VEXOperandCode::G_Ex_V_xmm + }) + } else { + (Opcode::VPGATHERDD, if L { + VEXOperandCode::G_Ey_V_ymm + } else { + VEXOperandCode::G_Ex_V_xmm + }) + } + }, + 0x91 => { + if instruction.prefixes.vex().w() { + (Opcode::VPGATHERQQ, if L { + VEXOperandCode::G_Ey_V_ymm + } else { + VEXOperandCode::G_Ex_V_xmm + }) + } else { + (Opcode::VPGATHERQD, if L { + VEXOperandCode::G_Ey_V_ymm + } else { + VEXOperandCode::G_Ex_V_xmm + }) + } + }, + 0x92 => { + if instruction.prefixes.vex().w() { + (Opcode::VGATHERDPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VGATHERDPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x93 => { + if instruction.prefixes.vex().w() { + (Opcode::VGATHERQPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } else { + (Opcode::VGATHERQPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }) + } + }, + 0x96 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADDSUB132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x97 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUBADD132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x98 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADD132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x99 => if instruction.prefixes.vex().w() { + (Opcode::VFMADD132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMADD132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0x9A => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUB132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x9B => if instruction.prefixes.vex().w() { + (Opcode::VFMSUB132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMSUB132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0x9C => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMADD132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x9D => if instruction.prefixes.vex().w() { + (Opcode::VFNMADD132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMADD132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0x9E => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB132PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMSUB132PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0x9F => if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMSUB132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xA6 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADDSUB213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xA7 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUBADD213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xA8 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADD213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xA9 => if instruction.prefixes.vex().w() { + (Opcode::VFMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xAA => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUB213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xAB => if instruction.prefixes.vex().w() { + (Opcode::VFMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xAC => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMADD213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xAD => if instruction.prefixes.vex().w() { + (Opcode::VFNMADD213SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMADD213SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xAE => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB213PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMSUB213PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xAF => if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB213SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMSUB213SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xB6 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADDSUB231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADDSUB231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xB7 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUBADD231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUBADD231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xB8 => { + if instruction.prefixes.vex().w() { + (Opcode::VFMADD231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMADD231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xB9 => if instruction.prefixes.vex().w() { + (Opcode::VFMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xBA => { + if instruction.prefixes.vex().w() { + (Opcode::VFMSUB231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFMSUB231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xBB => if instruction.prefixes.vex().w() { + (Opcode::VFMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xBC => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMADD231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMADD231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xBD => if instruction.prefixes.vex().w() { + (Opcode::VFNMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xBE => { + if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB231PD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } else { + (Opcode::VFNMSUB231PS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_ymm + }) + } + }, + 0xBF => if instruction.prefixes.vex().w() { + (Opcode::VFNMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) + } else { + (Opcode::VFNMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) + }, + 0xDB => (Opcode::VAESIMC, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm + }), + 0xDC => (Opcode::VAESENC, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDD => (Opcode::VAESENCLAST, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDE => (Opcode::VAESDEC, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm + }), + 0xDF => (Opcode::VAESDECLAST, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } else { + // the only VEX* 0f38 instructions have an implied 66 prefix. + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + VEXOpcodeMap::Map0F3A => { + if let VEXOpcodePrefix::Prefix66 = p { + // possibly valid! + match opc { + 0x00 => (Opcode::VPERMQ, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x01 => (Opcode::VPERMPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x02 => (Opcode::VPBLENDD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x04 => (Opcode::VPERMILPS, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x05 => (Opcode::VPERMILPD, if L { + VEXOperandCode::G_V_E_ymm + } else { + VEXOperandCode::G_V_E_xmm + }), + 0x06 => (Opcode::VPERM2F128, if L { + VEXOperandCode::G_V_E_ymm + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x08 => (Opcode::VROUNDPS, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x09 => (Opcode::VROUNDPD, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x0C => (Opcode::VBLENDPS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x0D => (Opcode::VBLENDPD, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x0E => (Opcode::VPBLENDW, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x0F => (Opcode::VPALIGNR, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x14 => (Opcode::VPEXTRB, if L || instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::Ev_G_xmm_imm8 + }), + 0x15 => (Opcode::VPEXTRW, if L || instruction.prefixes.vex().w() { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::Ev_G_xmm_imm8 + }), + 0x16 => if instruction.prefixes.vex().w() { + (Opcode::VPEXTRQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_ymm_imm8 + }) + } else { + (Opcode::VPEXTRD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + // varies on W + VEXOperandCode::Ev_G_xmm_imm8 + }) + }, + 0x17 => (Opcode::VEXTRACTPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_ymm_imm8 + }), + 0x18 => (Opcode::VINSERTF128, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x19 => (Opcode::VEXTRACTF128, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x1D => (Opcode::VCVTPS2PH, if L { + VEXOperandCode::E_xmm_G_ymm_imm8 + } else { + VEXOperandCode::E_G_xmm_imm8 + }), + 0x20 => (Opcode::VPINSRB, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x21 => (Opcode::VINSERTPS, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x22 => if instruction.prefixes.vex().w() { + (Opcode::VPINSRQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }) + } else { + (Opcode::VPINSRD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }) + }, + 0x38 => (Opcode::VINSERTI128, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 + }), + 0x39 => (Opcode::VEXTRACTI128, if L { + VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x40 => (Opcode::VDPPS, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x41 => (Opcode::VDPPD, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x42 => (Opcode::VMPSADBW, if L { + VEXOperandCode::G_E_ymm_imm8 + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x44 => (Opcode::VPCLMULQDQ, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_V_E_xmm_imm8 + }), + 0x46 => (Opcode::VPERM2I128, if L { + VEXOperandCode::G_V_E_ymm_imm8 + } else { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + }), + 0x4A => (Opcode::VBLENDVPS, if L { + VEXOperandCode::G_V_E_ymm_ymm4 + } else { + VEXOperandCode::G_V_E_xmm_xmm4 + }), + 0x4B => (Opcode::VBLENDVPD, if L { + VEXOperandCode::G_V_E_ymm_ymm4 + } else { + VEXOperandCode::G_V_E_xmm_xmm4 + }), + 0x4C => (Opcode::VPBLENDVB, if L { + VEXOperandCode::G_V_E_ymm_ymm4 + } else { + VEXOperandCode::G_V_E_xmm_xmm4 + }), + 0x62 => (Opcode::VPCMPISTRM, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0x63 => (Opcode::VPCMPISTRI, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + 0xDF => (Opcode::VAESKEYGENASSIST, if L { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_E_xmm_imm8 + }), + _ => { + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + } else { + // the only VEX* 0f3a instructions have an implied 66 prefix. + instruction.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + } + }; + instruction.opcode = opcode; + read_vex_operands(bytes, instruction, length, operand_code) +} diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs new file mode 100644 index 0000000..de7ec27 --- /dev/null +++ b/src/protected_mode/mod.rs @@ -0,0 +1 @@ +pub struct Arch {} diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs new file mode 100644 index 0000000..de7ec27 --- /dev/null +++ b/src/real_mode/mod.rs @@ -0,0 +1 @@ +pub struct Arch {} diff --git a/src/vex.rs b/src/vex.rs deleted file mode 100644 index 8a7434f..0000000 --- a/src/vex.rs +++ /dev/null @@ -1,2363 +0,0 @@ -use OperandSpec; -use DecodeError; -use RegSpec; -use RegisterBank; -use Instruction; -use Opcode; -use read_modrm; -use read_E; -use read_E_xmm; -use read_E_ymm; -use read_imm_unsigned; - -#[derive(Debug)] -enum VEXOpcodeMap { - Map0F, - Map0F38, - Map0F3A, -} - -#[derive(Debug)] -enum VEXOpcodePrefix { - None, - Prefix66, - PrefixF3, - PrefixF2, -} - -#[allow(non_camel_case_types)] -#[derive(Debug)] -enum VEXOperandCode { - Nothing, - VPS_71, - VPS_71_L, - VPS_72, - VPS_72_L, - VPS_73, - VPS_73_L, - VMOVSS_10, - VMOVSD_10, - VMOVSD_11, - VMOVSS_11, - E_G_xmm, - U_G_xmm, - M_G_xmm, - G_M_xmm, - G_U_xmm, - E_G_xmm_imm8, - U_G_xmm_imm8, - E_G_ymm, - U_G_ymm, - M_G_ymm, - G_E_ymm, - G_M_ymm, - G_U_ymm, - E_V_G_ymm, - E_V_G_xmm, - E_xmm_G_ymm_imm8, - Ev_G_xmm_imm8, - G_Ex_V_xmm, - G_Ey_V_ymm, - G_E_xmm, - G_E_xmm_imm8, - G_E_ymm_imm8, - G_xmm_E_xmm, - G_xmm_E_ymm, - G_ymm_E_xmm, - G_ymm_E_ymm, - G_V_ymm_E_xmm, - M_V_G_xmm, - M_V_G_ymm, - G_V_E_xmm, - G_V_E_xmm_imm8, - G_V_E_xmm_xmm4, - G_V_E_ymm, - G_V_E_ymm_imm8, - G_V_E_ymm_ymm4, - G_V_M_xmm, - G_V_M_ymm, - V_xmm_G_ymm_E_ymm_imm8, - V_ymm_G_ymm_E_xmm_imm8, - G_V_xmm_Ew_imm8, - Eq_G_xmm, - Ed_G_xmm, - G_xmm_Ed, - G_xmm_Eq, -} - -#[inline(never)] -pub(crate) fn three_byte_vex>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), DecodeError> { - let vex_byte_one = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - let vex_byte_two = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - length += 2; - let p = vex_byte_two & 0x03; - let p = match p { - 0x00 => VEXOpcodePrefix::None, - 0x01 => VEXOpcodePrefix::Prefix66, - 0x02 => VEXOpcodePrefix::PrefixF3, - 0x03 => VEXOpcodePrefix::PrefixF2, - _ => { unreachable!("p is two bits"); } - }; - let m = vex_byte_one & 0b11111; -// println!("m: {:05b}", m); - let m = match m { - 0b00001 => VEXOpcodeMap::Map0F, - 0b00010 => VEXOpcodeMap::Map0F38, - 0b00011 => VEXOpcodeMap::Map0F3A, - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - }; - instruction.vex_reg = RegSpec { - bank: RegisterBank::X, - num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111, - }; - instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); - - read_vex_instruction(m, bytes, instruction, &mut length, p)?; - instruction.length = length; - Ok(()) -} - -pub(crate) fn two_byte_vex>(bytes: &mut T, instruction: &mut Instruction, mut length: u8) -> Result<(), DecodeError> { - let vex_byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - length += 1; - let p = vex_byte & 0x03; - let p = match p { - 0x00 => VEXOpcodePrefix::None, - 0x01 => VEXOpcodePrefix::Prefix66, - 0x02 => VEXOpcodePrefix::PrefixF3, - 0x03 => VEXOpcodePrefix::PrefixF2, - _ => { unreachable!("p is two bits"); } - }; - instruction.vex_reg = RegSpec { - bank: RegisterBank::X, - num: ((vex_byte >> 3) & 0b1111) ^ 0b1111, - }; - instruction.prefixes.vex_from_c5(vex_byte); - - read_vex_instruction(VEXOpcodeMap::Map0F, bytes, instruction, &mut length, p)?; - instruction.length = length; - Ok(()) -} - -fn read_vex_operands>(bytes: &mut T, instruction: &mut Instruction, length: &mut u8, operand_code: VEXOperandCode) -> Result<(), DecodeError> { -// println!("operand code: {:?}", operand_code); - match operand_code { - VEXOperandCode::VPS_71 => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLW; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAW; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - /* - 0x71 => (Opcode::VPSLLW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x71 => (Opcode::VPSRAW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x71 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }), - */ - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VPS_71_L => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLW; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAW; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - /* - 0x71 => (Opcode::VPSLLW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x71 => (Opcode::VPSRAW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x71 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }), - */ - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VPS_72 => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLD; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAD; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - /* - 0x72 => (Opcode::VPSLLD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x72 => (Opcode::VPSRAD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x72 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - */ - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VPS_72_L => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLD; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAD; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - /* - 0x72 => (Opcode::VPSLLD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x72 => (Opcode::VPSRAD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x72 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - */ - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VPS_73 => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLQ; - } - 0b011 => { - instruction.opcode = Opcode::VPSRLDQ; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLQ; - } - 0b111 => { - instruction.opcode = Opcode::VPSLLDQ; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - // VEXOperandCode::G_E_xmm_imm8 ? this is reg1, reg2, imm8, but r is used for - // picking the opcode. is one of these actually the vex reg? - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VPS_73_L => { - let modrm = read_modrm(bytes, length)?; - match (modrm >> 3) & 0b111 { - 0b000 | - 0b001 | - 0b100 | - 0b101 => { - return Err(DecodeError::InvalidOpcode); - } - 0b010 => { - instruction.opcode = Opcode::VPSRLQ; - } - 0b011 => { - instruction.opcode = Opcode::VPSRLDQ; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLQ; - } - 0b111 => { - instruction.opcode = Opcode::VPSLLDQ; - } - _ => { - unreachable!("r is only three bits"); - } - } - // VEXOperandCode::G_E_ymm_imm8 ? this is reg1, reg2, imm8, but r is used for - // picking the opcode. is one of these actually the vex reg? - Err(DecodeError::IncompleteDecoder) // :) - } - VEXOperandCode::VMOVSS_10 | - VEXOperandCode::VMOVSD_10 => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegRRR; - match mem_oper { - OperandSpec::RegMMM => { - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegMMM; - }, - other => { - instruction.operands[1] = other; - } - } - Ok(()) - }, - VEXOperandCode::VMOVSS_11 | - VEXOperandCode::VMOVSD_11 => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[1] = OperandSpec::RegRRR; - match mem_oper { - OperandSpec::RegMMM => { - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegMMM; - }, - other => { - instruction.operands[0] = other; - } - } - Ok(()) - }, - VEXOperandCode::Nothing => { - Ok(()) - }, - VEXOperandCode::Ev_G_xmm_imm8 => { - if instruction.vex_reg.num != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E(bytes, instruction, modrm, 8, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.operands[2] = OperandSpec::ImmU8; - instruction.imm = read_imm_unsigned(bytes, 1, length)?; - Ok(()) - }, - _op @ VEXOperandCode::E_G_xmm | - _op @ VEXOperandCode::U_G_xmm | - _op @ VEXOperandCode::M_G_xmm | - _op @ VEXOperandCode::E_G_xmm_imm8 | - _op @ VEXOperandCode::U_G_xmm_imm8 => { - if instruction.vex_reg.num != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - Ok(()) - } - - _op @ VEXOperandCode::G_M_xmm | - _op @ VEXOperandCode::G_U_xmm | - _op @ VEXOperandCode::G_E_xmm | - _op @ VEXOperandCode::G_E_xmm_imm8 => { - if instruction.vex_reg.num != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - Ok(()) - } - - _op @ VEXOperandCode::E_G_ymm | - _op @ VEXOperandCode::U_G_ymm | - _op @ VEXOperandCode::M_G_ymm => { - if instruction.vex_reg.num != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegRRR; - Ok(()) - } - - _op @ VEXOperandCode::G_M_ymm | - _op @ VEXOperandCode::G_U_ymm | - _op @ VEXOperandCode::G_E_ymm => { - if instruction.vex_reg.num != 0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - Ok(()) - } - _op @ VEXOperandCode::G_V_E_ymm | - _op @ VEXOperandCode::G_V_M_ymm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - instruction.vex_reg.bank = RegisterBank::Y; - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = mem_oper; - Ok(()) - } - _op @ VEXOperandCode::E_V_G_ymm | - _op @ VEXOperandCode::M_V_G_ymm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - instruction.vex_reg.bank = RegisterBank::Y; - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegRRR; - Ok(()) - } - _op @ VEXOperandCode::G_V_M_xmm | - _op @ VEXOperandCode::G_V_E_xmm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = mem_oper; - Ok(()) - } - - _op @ VEXOperandCode::E_V_G_xmm | - _op @ VEXOperandCode::M_V_G_xmm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.operands[0] = mem_oper; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegRRR; - Ok(()) - } - - VEXOperandCode::G_Ex_V_xmm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X); - let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; - instruction.sib_index.bank = RegisterBank::X; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operands[2] = OperandSpec::RegVex; - Ok(()) - } - VEXOperandCode::G_Ey_V_ymm => { - let modrm = read_modrm(bytes, length)?; - instruction.modrm_rrr = - RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); - let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; - instruction.vex_reg.bank = RegisterBank::Y; - instruction.sib_index.bank = RegisterBank::Y; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operands[2] = OperandSpec::RegVex; - Ok(()) - } - - VEXOperandCode::E_xmm_G_ymm_imm8 | - VEXOperandCode::G_E_ymm_imm8 | - VEXOperandCode::G_xmm_E_xmm | - VEXOperandCode::G_xmm_E_ymm | - VEXOperandCode::G_ymm_E_xmm | - VEXOperandCode::G_ymm_E_ymm | - VEXOperandCode::G_V_E_xmm_imm8 | - VEXOperandCode::G_V_E_xmm_xmm4 | - VEXOperandCode::G_V_E_ymm_imm8 | - VEXOperandCode::G_V_E_ymm_ymm4 | - VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 | - VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 | - VEXOperandCode::Eq_G_xmm | - VEXOperandCode::Ed_G_xmm | - VEXOperandCode::G_xmm_Ed | - VEXOperandCode::G_xmm_Eq | - VEXOperandCode::G_V_ymm_E_xmm | - VEXOperandCode::G_V_xmm_Ew_imm8 => { - Err(DecodeError::IncompleteDecoder) // :) - } - - } -} - -fn read_vex_instruction>(opcode_map: VEXOpcodeMap, bytes: &mut T, instruction: &mut Instruction, length: &mut u8, p: VEXOpcodePrefix) -> Result<(), DecodeError> { - let opc = bytes.next().ok_or(DecodeError::ExhaustedInput)?; - *length += 1; - - // the name of this bit is `L` in the documentation, so use the same name here. - #[allow(non_snake_case)] - let L = instruction.prefixes.vex().l(); - -// println!("reading vex instruction from opcode prefix {:?}, L: {}, opc: {:#x}, map:{:?}", p, L, opc, opcode_map); -// println!("w? {}", instruction.prefixes.vex().w()); - - // several combinations simply have no instructions. check for those first. - let (opcode, operand_code) = match opcode_map { - VEXOpcodeMap::Map0F => { - match p { - VEXOpcodePrefix::None => { - match opc { - 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), - // ugh -// 0x12 => (Opcode::VMOVHLPS, ..), -// 0x12 => (Opcode::VMOVLPS, ..), - 0x13 => (Opcode::VMOVLPS, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::M_G_xmm - }), - 0x14 => (Opcode::VUNPCKLPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x15 => (Opcode::VUNPCKHPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - // ugh -// 0x16 => (Opcode::VMOVHPS, ..), -// 0x16 => (Opcode::VMOVLHPS, ..), - 0x17 => (Opcode::VMOVHPS, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::M_G_xmm - }), - 0x28 => (Opcode::VMOVAPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x29 => (Opcode::VMOVAPS, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), - 0x2B => (Opcode::VMOVNTPS, if L { - VEXOperandCode::M_G_ymm - } else { - VEXOperandCode::M_G_xmm - }), - 0x2e => (Opcode::VUCOMISS, VEXOperandCode::G_E_xmm), - 0x2f => (Opcode::VCOMISS, VEXOperandCode::G_E_xmm), - 0x50 => (Opcode::VMOVMSKPS, if L { - VEXOperandCode::U_G_ymm - } else { - VEXOperandCode::U_G_xmm - }), - 0x51 => (Opcode::VSQRTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x52 => (Opcode::VRSQRTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x53 => (Opcode::VRCPPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x57 => (Opcode::VXORPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x58 => (Opcode::VADDPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x59 => (Opcode::VMULPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5A => (Opcode::VCVTPS2PD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x5B => (Opcode::VCVTDQ2PS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x5C => (Opcode::VSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5D => (Opcode::VMINPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5E => (Opcode::VDIVPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5F => (Opcode::VMAXPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x77 => (Opcode::VZEROUPPER, VEXOperandCode::Nothing), - 0xC2 => (Opcode::VCMPPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0xC6 => (Opcode::VSHUFPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - }, - VEXOpcodePrefix::Prefix66 => { - match opc { - 0x0a => (Opcode::VROUNDSS, VEXOperandCode::G_V_E_xmm_imm8), - 0x0b => (Opcode::VROUNDSD, VEXOperandCode::G_V_E_xmm_imm8), - 0x10 => (Opcode::VMOVUPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x11 => (Opcode::VMOVUPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x12 => (Opcode::VMOVLPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_M_xmm - }), - 0x13 => (Opcode::VMOVLPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::M_G_xmm - }), - 0x14 => (Opcode::VUNPCKLPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x15 => (Opcode::VUNPCKHPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x16 => (Opcode::VMOVHPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_M_xmm - }), - 0x17 => (Opcode::VMOVHPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::M_G_xmm - }), - 0x28 => (Opcode::VMOVAPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x29 => (Opcode::VMOVAPD, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), - 0x2B => (Opcode::VMOVNTPD, if L { - VEXOperandCode::M_G_ymm - } else { - VEXOperandCode::M_G_xmm - }), - 0x2e => (Opcode::VUCOMISD, VEXOperandCode::G_E_xmm), - 0x2f => (Opcode::VCOMISD, VEXOperandCode::G_E_xmm), - 0x50 => (Opcode::VMOVMSKPD, if L { - VEXOperandCode::G_U_ymm - } else { - VEXOperandCode::G_U_xmm - }), - 0x51 => (Opcode::VSQRTPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x57 => (Opcode::VXORPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x58 => (Opcode::VADDPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x59 => (Opcode::VMULPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5A => (Opcode::VCVTPD2PS, if L { - VEXOperandCode::G_xmm_E_ymm - } else { - VEXOperandCode::G_xmm_E_xmm - }), - 0x5B => (Opcode::VCVTPS2DQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x5C => (Opcode::VSUBPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5D => (Opcode::VMINPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5E => (Opcode::VDIVPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5F => (Opcode::VMAXPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x60 => (Opcode::VPUNPCKLBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x61 => (Opcode::VPUNPCKLWD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x62 => (Opcode::VPUNPCKLDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x63 => (Opcode::VPACKSSWB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x64 => (Opcode::VPCMPGTB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x65 => (Opcode::VPCMPGTW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x66 => (Opcode::VPCMPGTD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x67 => (Opcode::VPACKUSWB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x68 => (Opcode::VPUNPCKHBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x69 => (Opcode::VPUNPCKHWD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6A => (Opcode::VPUNPCKHDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6B => (Opcode::VPACKSSDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6C => (Opcode::VPUNPCKLQDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6D => (Opcode::VPUNPCKHQDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6E => if instruction.prefixes.vex().w() { - (Opcode::VMOVQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_xmm_Eq - }) - } else { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_xmm_Ed - }) - }, - 0x6F => (Opcode::VMOVDQA, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x70 => (Opcode::VPSHUFD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x71 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_71_L - } else { - VEXOperandCode::VPS_71 - }), - 0x72 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_72_L - } else { - VEXOperandCode::VPS_72 - }), - 0x73 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_73_L - } else { - VEXOperandCode::VPS_73 - }), - 0x74 => (Opcode::VPCMPEQB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x75 => (Opcode::VPCMPEQW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x76 => (Opcode::VPCMPEQD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7C => (Opcode::VHADDPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7D => (Opcode::VHSUBPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7E => if instruction.prefixes.vex().w() { - (Opcode::VMOVQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Eq_G_xmm - }) - } else { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ed_G_xmm - }) - } - 0x7F => (Opcode::VMOVDQA, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), - 0xC2 => (Opcode::VCMPPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xC4 => (Opcode::VPINSRW, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_xmm_Ew_imm8 - }), - 0xC5 => (Opcode::VPEXTRW, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::U_G_xmm_imm8 - }), - 0xC6 => (Opcode::VSHUFPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD0 => (Opcode::VADDSUBPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD1 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD2 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD3 => (Opcode::VPSRLQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD4 => (Opcode::VPADDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD5 => (Opcode::VPMULLW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD6 => (Opcode::VMOVQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm - }), - 0xD7 => (Opcode::VPMOVMSKB, if L { - VEXOperandCode::U_G_ymm - } else { - VEXOperandCode::U_G_xmm - }), - 0xD8 => (Opcode::VPSUBUSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD9 => (Opcode::VPSUBUSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDB => (Opcode::VPAND, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDC => (Opcode::VPADDUSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0xDD => (Opcode::VPADDUSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDF => (Opcode::VPANDN, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE0 => (Opcode::VPAVGB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE1 => (Opcode::VPSRAW, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE2 => (Opcode::VPSRAD, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE3 => (Opcode::VPAVGW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE4 => (Opcode::VPMULHUW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE5 => (Opcode::VPMULHW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE6 => (Opcode::VCVTTPD2DQ, if L { - VEXOperandCode::G_xmm_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0xE7 => (Opcode::VMOVNTDQ, if L { - VEXOperandCode::M_G_ymm - } else { - VEXOperandCode::M_G_xmm - }), - 0xE8 => (Opcode::VPSUBSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE9 => (Opcode::VPSUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEB => (Opcode::VPOR, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEC => (Opcode::VPADDSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xED => (Opcode::VPADDSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEE => (Opcode::VPMAXSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEF => (Opcode::VPXOR, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF1 => (Opcode::VPSLLW, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF2 => (Opcode::VPSLLD, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF3 => (Opcode::VPSLLQ, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF4 => (Opcode::VPMULUDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF5 => (Opcode::VPMADDWD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF6 => (Opcode::VPSADBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF7 => (Opcode::VMASKMOVDQU, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm - }), - 0xF8 => (Opcode::VPSUBB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF9 => (Opcode::VPSUBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFA => (Opcode::VPSUBD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFB => (Opcode::VPSUBQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFC => (Opcode::VPADDB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFD => (Opcode::VPADDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFE => (Opcode::VPADDD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } - VEXOpcodePrefix::PrefixF2 => { - match opc { - 0x10 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_10), - 0x11 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_11), - 0x12 => (Opcode::VMOVDDUP, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x2a => (Opcode::VCVTSI2SD, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand - } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand - }), - 0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit - } else { - VEXOperandCode::G_E_xmm // 32-bit - }), - 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit - } else { - VEXOperandCode::G_E_xmm // 32-bit - }), - 0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm), - 0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm), - 0x59 => (Opcode::VMULSD, VEXOperandCode::G_V_E_xmm), - 0x5a => (Opcode::CVTSD2SS, VEXOperandCode::G_V_E_xmm), - 0x5c => (Opcode::VSUBSD, VEXOperandCode::G_V_E_xmm), - 0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm), - 0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm), - 0x5f => (Opcode::VMAXSD, VEXOperandCode::G_V_E_xmm), - 0x70 => (Opcode::VPSHUFLW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x7c => (Opcode::VHADDPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7d => (Opcode::VHSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xc2 => (Opcode::VCMPSD, VEXOperandCode::G_V_E_xmm_imm8), - 0xd0 => (Opcode::VADDSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xe6 => (Opcode::VCVTPD2DQ, if L { - VEXOperandCode::G_xmm_E_ymm - } else { - VEXOperandCode::G_xmm_E_xmm - }), - 0xf0 => (Opcode::VLDDQU, if L { - VEXOperandCode::G_M_ymm - } else { - VEXOperandCode::G_M_ymm - }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } - VEXOpcodePrefix::PrefixF3 => { - match opc { - 0x10 => (Opcode::VMOVSS, VEXOperandCode::VMOVSS_10), - 0x11 => (Opcode::VMOVSS, VEXOperandCode::VMOVSS_11), - 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x2a => (Opcode::VCVTSI2SS, if instruction.prefixes.vex().w() { - VEXOperandCode::G_V_E_xmm // 64-bit last operand - } else { - VEXOperandCode::G_V_E_xmm // 32-bit last operand - }), - 0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit - } else { - VEXOperandCode::G_E_xmm // 32-bit - }), - 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex().w() { - VEXOperandCode::G_E_xmm // 64-bit - } else { - VEXOperandCode::G_E_xmm // 32-bit - }), - 0x51 => (Opcode::VSQRTSS, VEXOperandCode::G_V_E_xmm), - 0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm), - 0x53 => (Opcode::VRCPSS, VEXOperandCode::G_V_E_xmm), - 0x58 => (Opcode::VADDSS, VEXOperandCode::G_V_E_xmm), - 0x59 => (Opcode::VMULSS, VEXOperandCode::G_V_E_xmm), - 0x5a => (Opcode::VCVTSS2SD, VEXOperandCode::G_V_E_xmm), - 0x5b => (Opcode::VCVTTPS2DQ, if L { VEXOperandCode::G_ymm_E_ymm } else { VEXOperandCode::G_xmm_E_xmm }), - 0x5c => (Opcode::VSUBSS, VEXOperandCode::G_V_E_xmm), - 0x5d => (Opcode::VMINSS, VEXOperandCode::G_V_E_xmm), - 0x5e => (Opcode::VDIVSS, VEXOperandCode::G_V_E_xmm), - 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_E_xmm), - 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x70 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm_imm8 } else { VEXOperandCode::G_E_xmm_imm8 }), - 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), - 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), - 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), - 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } - } - } - VEXOpcodeMap::Map0F38 => { - // TODO: verify rejecting invalid W bit - if let VEXOpcodePrefix::Prefix66 = p { - // possibly valid! - match opc { - 0x00 => (Opcode::VPSHUFB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x01 => (Opcode::VPHADDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x02 => (Opcode::VPHADDD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x03 => (Opcode::VPHADDSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x04 => (Opcode::VPHADDUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x05 => (Opcode::VPHSUBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x06 => (Opcode::VPHSUBD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x07 => (Opcode::VPHSUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x08 => (Opcode::VPSIGNB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x09 => (Opcode::VPSIGNW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0A => (Opcode::VPSIGND, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0B => (Opcode::VPMULHRSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0C => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0D => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0E => (Opcode::VTESTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x0F => (Opcode::VTESTPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x13 => (Opcode::VCVTPH2PS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x16 => (Opcode::VPERMPS, if L { - VEXOperandCode::G_V_E_xmm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x17 => (Opcode::VPTEST, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x18 => (Opcode::VBROADCASTSS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x19 => (Opcode::VBROADCASTSD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x1A => (Opcode::VBROADCASTF128, if L { - VEXOperandCode::G_M_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x1C => (Opcode::VPABSB, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x1D => (Opcode::VPABSW, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x1E => (Opcode::VPABSD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x20 => (Opcode::VPMOVSXBW, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x21 => (Opcode::VPMOVSXBD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x22 => (Opcode::VPMOVSXBQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x23 => (Opcode::VPMOVSXWD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x24 => (Opcode::VPMOVSXWQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x25 => (Opcode::VPMOVSXDQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x28 => (Opcode::VPMULDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x29 => (Opcode::VPCMPEQQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x2A => (Opcode::VMOVNTDQA, if L { - VEXOperandCode::G_M_ymm - } else { - VEXOperandCode::G_M_xmm - }), - 0x2C => (Opcode::VMASKMOVPS, if L { - VEXOperandCode::G_V_M_ymm - } else { - VEXOperandCode::G_V_M_xmm - }), - 0x2D => (Opcode::VMASKMOVPD, if L { - VEXOperandCode::G_V_M_ymm - } else { - VEXOperandCode::G_V_M_xmm - }), - 0x2E => (Opcode::VMASKMOVPS, if L { - VEXOperandCode::M_V_G_ymm - } else { - VEXOperandCode::M_V_G_xmm - }), - 0x2F => (Opcode::VMASKMOVPD, if L { - VEXOperandCode::M_V_G_ymm - } else { - VEXOperandCode::M_V_G_xmm - }), - 0x30 => (Opcode::VPMOVZXBW, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x31 => (Opcode::VPMOVZXBD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x32 => (Opcode::VPMOVZXBQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x33 => (Opcode::VPMOVZXWD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x34 => (Opcode::VPMOVZXWQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x35 => (Opcode::VPMOVZXDQ, if L { - VEXOperandCode::G_E_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x36 => (Opcode::VPERMD, if L { - VEXOperandCode::G_V_E_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x37 => (Opcode::VPCMPGTQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x39 => (Opcode::VPMINSD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3B => (Opcode::VPMINUD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3C => (Opcode::VPMAXSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3D => (Opcode::VPMAXSD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3F => (Opcode::VPMAXUD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x40 => (Opcode::VPMULLD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x41 => (Opcode::VPHMINPOSUW, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm - }), - 0x45 => if instruction.prefixes.vex().w() { - (Opcode::VPSRLVQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) - } else { - (Opcode::VPSRLVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) - }, - 0x46 => (Opcode::VPSRAVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x47 => if instruction.prefixes.vex().w() { - (Opcode::VPSLLVQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) - } else { - (Opcode::VPSLLVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) - }, - 0x58 => (Opcode::VPBROADCASTD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x59 => (Opcode::VPBROADCASTQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x5A => (Opcode::VBROADCASTI128, if L { - VEXOperandCode::G_E_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x78 => (Opcode::VPBROADCASTB, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_ymm - }), - 0x79 => (Opcode::VPBROADCASTW, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_ymm - }), - 0x8C => { - if instruction.prefixes.vex().w() { - (Opcode::VPMASKMOVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VPMASKMOVQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x8E => { - if instruction.prefixes.vex().w() { - (Opcode::VPMASKMOVD, if L { - VEXOperandCode::E_V_G_ymm - } else { - VEXOperandCode::E_V_G_xmm - }) - } else { - (Opcode::VPMASKMOVQ, if L { - VEXOperandCode::E_V_G_ymm - } else { - VEXOperandCode::E_V_G_xmm - }) - } - }, - 0x90 => { - if instruction.prefixes.vex().w() { - (Opcode::VPGATHERDQ, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) - } else { - (Opcode::VPGATHERDD, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) - } - }, - 0x91 => { - if instruction.prefixes.vex().w() { - (Opcode::VPGATHERQQ, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) - } else { - (Opcode::VPGATHERQD, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) - } - }, - 0x92 => { - if instruction.prefixes.vex().w() { - (Opcode::VGATHERDPD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }) - } else { - (Opcode::VGATHERDPS, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }) - } - }, - 0x93 => { - if instruction.prefixes.vex().w() { - (Opcode::VGATHERQPD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }) - } else { - (Opcode::VGATHERQPS, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }) - } - }, - 0x96 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADDSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADDSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x97 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUBADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUBADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x98 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x99 => if instruction.prefixes.vex().w() { - (Opcode::VFMADD132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMADD132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0x9A => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x9B => if instruction.prefixes.vex().w() { - (Opcode::VFMSUB132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMSUB132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0x9C => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x9D => if instruction.prefixes.vex().w() { - (Opcode::VFNMADD132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMADD132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0x9E => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0x9F => if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB132SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMSUB132SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xA6 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADDSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADDSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xA7 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUBADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUBADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xA8 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xA9 => if instruction.prefixes.vex().w() { - (Opcode::VFMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xAA => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xAB => if instruction.prefixes.vex().w() { - (Opcode::VFMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xAC => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xAD => if instruction.prefixes.vex().w() { - (Opcode::VFNMADD213SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMADD213SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xAE => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xAF => if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB213SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMSUB213SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xB6 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADDSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADDSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xB7 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUBADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUBADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xB8 => { - if instruction.prefixes.vex().w() { - (Opcode::VFMADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xB9 => if instruction.prefixes.vex().w() { - (Opcode::VFMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xBA => { - if instruction.prefixes.vex().w() { - (Opcode::VFMSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFMSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xBB => if instruction.prefixes.vex().w() { - (Opcode::VFMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xBC => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xBD => if instruction.prefixes.vex().w() { - (Opcode::VFNMADD231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMADD231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xBE => { - if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } else { - (Opcode::VFNMSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) - } - }, - 0xBF => if instruction.prefixes.vex().w() { - (Opcode::VFNMSUB231SD, VEXOperandCode::G_V_E_xmm /* 64bit */) - } else { - (Opcode::VFNMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) - }, - 0xDB => (Opcode::VAESIMC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm - }), - 0xDC => (Opcode::VAESENC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDD => (Opcode::VAESENCLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDE => (Opcode::VAESDEC, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDF => (Opcode::VAESDECLAST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm - }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } else { - // the only VEX* 0f38 instructions have an implied 66 prefix. - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - VEXOpcodeMap::Map0F3A => { - if let VEXOpcodePrefix::Prefix66 = p { - // possibly valid! - match opc { - 0x00 => (Opcode::VPERMQ, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x01 => (Opcode::VPERMPD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x02 => (Opcode::VPBLENDD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x04 => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x05 => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x06 => (Opcode::VPERM2F128, if L { - VEXOperandCode::G_V_E_ymm - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x08 => (Opcode::VROUNDPS, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x09 => (Opcode::VROUNDPD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x0C => (Opcode::VBLENDPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0D => (Opcode::VBLENDPD, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0E => (Opcode::VPBLENDW, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0F => (Opcode::VPALIGNR, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x14 => (Opcode::VPEXTRB, if L || instruction.prefixes.vex().w() { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ev_G_xmm_imm8 - }), - 0x15 => (Opcode::VPEXTRW, if L || instruction.prefixes.vex().w() { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ev_G_xmm_imm8 - }), - 0x16 => if instruction.prefixes.vex().w() { - (Opcode::VPEXTRQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_ymm_imm8 - }) - } else { - (Opcode::VPEXTRD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - // varies on W - VEXOperandCode::Ev_G_xmm_imm8 - }) - }, - 0x17 => (Opcode::VEXTRACTPS, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_ymm_imm8 - }), - 0x18 => (Opcode::VINSERTF128, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x19 => (Opcode::VEXTRACTF128, if L { - VEXOperandCode::E_xmm_G_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x1D => (Opcode::VCVTPS2PH, if L { - VEXOperandCode::E_xmm_G_ymm_imm8 - } else { - VEXOperandCode::E_G_xmm_imm8 - }), - 0x20 => (Opcode::VPINSRB, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x21 => (Opcode::VINSERTPS, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x22 => if instruction.prefixes.vex().w() { - (Opcode::VPINSRQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }) - } else { - (Opcode::VPINSRD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }) - }, - 0x38 => (Opcode::VINSERTI128, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 - }), - 0x39 => (Opcode::VEXTRACTI128, if L { - VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x40 => (Opcode::VDPPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x41 => (Opcode::VDPPD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x42 => (Opcode::VMPSADBW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x44 => (Opcode::VPCLMULQDQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x46 => (Opcode::VPERM2I128, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - }), - 0x4A => (Opcode::VBLENDVPS, if L { - VEXOperandCode::G_V_E_ymm_ymm4 - } else { - VEXOperandCode::G_V_E_xmm_xmm4 - }), - 0x4B => (Opcode::VBLENDVPD, if L { - VEXOperandCode::G_V_E_ymm_ymm4 - } else { - VEXOperandCode::G_V_E_xmm_xmm4 - }), - 0x4C => (Opcode::VPBLENDVB, if L { - VEXOperandCode::G_V_E_ymm_ymm4 - } else { - VEXOperandCode::G_V_E_xmm_xmm4 - }), - 0x62 => (Opcode::VPCMPISTRM, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x63 => (Opcode::VPCMPISTRI, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0xDF => (Opcode::VAESKEYGENASSIST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - _ => { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - } else { - // the only VEX* 0f3a instructions have an implied 66 prefix. - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } - } - }; - instruction.opcode = opcode; - read_vex_operands(bytes, instruction, length, operand_code) -} diff --git a/test/test.rs b/test/test.rs index 7248117..fc4f1b1 100644 --- a/test/test.rs +++ b/test/test.rs @@ -4,7 +4,7 @@ extern crate yaxpeax_x86; use std::fmt::Write; use yaxpeax_arch::{Decoder, LengthedInstruction}; -use yaxpeax_x86::{DecodeError, InstDecoder}; +use yaxpeax_x86::long_mode::{DecodeError, InstDecoder, Opcode}; fn test_invalid(data: &[u8]) { test_invalid_under(&InstDecoder::default(), data); @@ -12,7 +12,7 @@ fn test_invalid(data: &[u8]) { fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { if let Ok(inst) = decoder.decode(data.into_iter().cloned()) { - assert_eq!(inst.opcode, yaxpeax_x86::Opcode::Invalid, "decoded {:?} from {:02x?} under decoder {}", inst.opcode, data, decoder); + assert_eq!(inst.opcode, Opcode::Invalid, "decoded {:?} from {:02x?} under decoder {}", inst.opcode, data, decoder); } else { // this is fine } -- cgit v1.1