diff options
Diffstat (limited to 'src/long_mode')
| -rw-r--r-- | src/long_mode/display.rs | 2068 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 6209 | ||||
| -rw-r--r-- | src/long_mode/vex.rs | 2363 | 
3 files changed, 10640 insertions, 0 deletions
| 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, "<all features>"); +        } else if self == &InstDecoder::minimal() { +            return write!(f, "<no features>"); +        } +        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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u64, NoContext, Color, T, Y> 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u64, [Option<alloc::string::String>], Color, T, Y> for Instruction { +    fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option<alloc::string::String>]>, 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<H: Hasher>(&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::<OperandSpec>(), 1); +    assert_eq!(core::mem::size_of::<RegSpec>(), 2); +    // assert_eq!(core::mem::size_of::<Prefixes>(), 4); +    // assert_eq!(core::mem::size_of::<Instruction>(), 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<T> 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<Instruction> for InstDecoder { +    type Error = DecodeError; + +    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<Instruction, Self::Error> { +        let mut instr = Instruction::invalid(); +        decode_one(self, bytes, &mut instr) +            .map(|_: ()| instr) +    } +    fn decode_into<T: IntoIterator<Item=u8>>(&self, instr: &mut Instruction, bytes: T) -> Result<(), Self::Error> { +        decode_one(self, bytes, instr) +    } +} + +impl Opcode { +    pub fn condition(&self) -> Option<ConditionCode> { +        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<Segment> { +        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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8) -> Result<OpcodeRecord, DecodeError> { +    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::<OpcodeRecord>(), 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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, length: &mut u8) -> Result<OperandSpec, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, DecodeError> { +    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<OperandSpec, DecodeError> { +    instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank); +    Ok(OperandSpec::RegMMM) +} + +#[allow(non_snake_case)] +fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8) -> Result<OperandSpec, DecodeError> { +    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<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), DecodeError> { +    let mut length = 0u8; +    let mut alternate_opcode_map: Option<OpcodeMap> = None; +//    use core::intrinsics::unlikely; +    let mut prefixes = Prefixes::new(0); + +    fn escapes_are_prefixes_actually(prefixes: &mut Prefixes, opc_map: &mut Option<OpcodeMap>) { +        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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<Item=u8>>(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<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u64, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<u64, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, length: &mut u8) -> Result<i64, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mut u8) -> Result<u64, DecodeError> { +    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<T: Iterator<Item=u8>>(bytes_iter: &mut T, length: &mut u8) -> Result<u8, DecodeError> { +    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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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<T: Iterator<Item=u8>>(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) +} | 
