diff options
| author | iximeow <me@iximeow.net> | 2020-08-09 18:32:48 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-08-09 18:32:48 -0700 | 
| commit | 80219e974d78af59afb4250498554ad8eb63274c (patch) | |
| tree | 28b4abb02bbcd9827f67047683ddda021fb9ffed /src | |
| parent | a00851d965cecf8bc31b3a9e668c34648e816060 (diff) | |
port updates to protected-mode decoder
Diffstat (limited to 'src')
| -rw-r--r-- | src/protected_mode/display.rs | 2187 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 3128 | ||||
| -rw-r--r-- | src/protected_mode/vex.rs | 265 | 
3 files changed, 3537 insertions, 2043 deletions
| diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index 77d39ff..6f73df1 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -5,7 +5,7 @@ use core::fmt;  use yaxpeax_arch::{Colorize, ShowContextual, NoColors, YaxColors};  use yaxpeax_arch::display::*; -use crate::protected_mode::{RegSpec, RegisterBank, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixVex, OperandSpec, DecodeError}; +use crate::protected_mode::{RegSpec, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixVex, OperandSpec, DecodeError};  impl fmt::Display for DecodeError {      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -97,7 +97,7 @@ impl fmt::Display for PrefixVex {                  if self.b() { "b" } else { "-" },              )          } else { -            write!(f, "rex:none") +            write!(f, "vex:none")          }      }  } @@ -115,52 +115,34 @@ impl fmt::Display for Segment {      }  } +// register names are grouped by indices scaled by 16. +// xmm, ymm, zmm all get two indices. +const REG_NAMES: &[&'static str] = &[ +    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", +    "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", +    "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", +    "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", +    "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", +    "cs", "ds", "es", "fs", "gs", "ss", "", "", +    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", +    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", +    "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", +    "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", +    "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", +    "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", +    "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", +    "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", +    "eip", "k1", "k2", "k3", "k4", "k5", "k6", "k7", +    "eflags", "k1", "k2", "k3", "k4", "k5", "k6", "k7", +]; +  pub(crate) fn regspec_label(spec: &RegSpec) -> &'static str { -    match spec.bank { -        RegisterBank::D => { -            ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"][spec.num as usize] -        }, -        RegisterBank::W => { -            ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di"][spec.num as usize] -        }, -        RegisterBank::B => { -            ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"][spec.num as usize] -        }, -        RegisterBank::EIP => { "eip" }, -        RegisterBank::EFlags => { "eflags" }, -        RegisterBank::CR => { -            ["cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7"][spec.num as usize] -        } -        RegisterBank::DR => { -            ["dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7"][spec.num as usize] -        } -        RegisterBank::X => { -            ["xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"][spec.num as usize] -        }, -        RegisterBank::Y => { -            ["ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15"][spec.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"][spec.num as usize] -        }, -        RegisterBank::ST => { -            ["st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"][spec.num as usize] -        }, -        RegisterBank::MM => { -            ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"][spec.num as usize] -        } -        RegisterBank::S => { -            ["cs", "ds", "es", "fs", "gs", "ss"][spec.num as usize] -        } -        RegisterBank::K => { -            ["k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"][spec.num as usize] -        } -    } +    unsafe { REG_NAMES.get_unchecked((spec.num as u16 + ((spec.bank as u16) << 3)) as usize) }  }  impl fmt::Display for RegSpec {      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -        write!(f, "{}", regspec_label(self)) +        f.write_str(regspec_label(self))      }  } @@ -195,61 +177,64 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color                      colors.number(signed_i32_hex(imm)))              },              &Operand::Register(ref spec) => { -                write!(f, "{}", colors.register(spec)) +                f.write_str(regspec_label(spec))              }              &Operand::DisplacementU16(imm) => { -                write!(f, "[{}]", colors.address(u32_hex(imm as u32))) +                write!(f, "[{}]", colors.address(u16_hex(imm)))              }              &Operand::DisplacementU32(imm) => {                  write!(f, "[{}]", colors.address(u32_hex(imm)))              }              &Operand::RegDisp(ref spec, disp) => { -                write!(f, "[{} ", colors.register(spec))?; +                write!(f, "[{} ", regspec_label(spec))?;                  format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?;                  write!(f, "]")              },              &Operand::RegDeref(ref spec) => { -                write!(f, "[{}]", colors.register(spec)) +                f.write_str("[")?; +                f.write_str(regspec_label(spec))?; +                f.write_str("]")              },              &Operand::RegScale(ref spec, scale) => {                  write!(f, "[{} * {}]", -                    colors.register(spec), +                    regspec_label(spec),                      colors.number(scale)                  )              },              &Operand::RegScaleDisp(ref spec, scale, disp) => {                  write!(f, "[{} * {} ", -                    colors.register(spec), +                    regspec_label(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) -                ) +                f.write_str("[")?; +                f.write_str(regspec_label(base))?; +                f.write_str(" + ")?; +                f.write_str(regspec_label(index))?; +                f.write_str("]")              }              &Operand::RegIndexBaseDisp(ref base, ref index, disp) => {                  write!(f, "[{} + {} ", -                    colors.register(base), -                    colors.register(index), +                    regspec_label(base), +                    regspec_label(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), +                    regspec_label(base), +                    regspec_label(index),                      colors.number(scale)                  )              }              &Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => {                  write!(f, "[{} + {} * {} ", -                    colors.register(base), -                    colors.register(index), +                    regspec_label(base), +                    regspec_label(index),                      colors.number(scale),                  )?;                  format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?; @@ -262,853 +247,979 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color  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::UNPCKLPD => write!(f, "unpcklpd"), -            &Opcode::UNPCKHPS => write!(f, "unpckhps"), -            &Opcode::UNPCKHPD => write!(f, "unpckhpd"), -            &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::BZHI => write!(f, "bzhi"), -            &Opcode::PDEP => write!(f, "pdep"), -            &Opcode::PEXT => write!(f, "pext"), -            &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::RDPID => write!(f, "rdpid"), -            &Opcode::RDFSBASE => write!(f, "rdfsbase"), -            &Opcode::RDGSBASE => write!(f, "rdgsbase"), -            &Opcode::WRFSBASE => write!(f, "wrfsbase"), -            &Opcode::WRGSBASE => write!(f, "wrgsbase"), -            &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::XSAVEC => write!(f, "xsavec"), -            &Opcode::XSAVES => write!(f, "xsaves"), -            &Opcode::XRSTOR => write!(f, "xrstor"), -            &Opcode::XRSTORS => write!(f, "xrstors"), -            &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::CLFLUSHOPT => write!(f, "clflushopt"), -            &Opcode::CLWB => write!(f, "clwb"), -            &Opcode::LDS => write!(f, "lds"), -            &Opcode::LES => write!(f, "les"), -            &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::IN => write!(f, "in"), -            &Opcode::OUTS => write!(f, "outs"), -            &Opcode::OUT => write!(f, "out"), -            &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::SARX => write!(f, "sarx"), -            &Opcode::SHLX => write!(f, "shlx"), -            &Opcode::SHRX => write!(f, "shrx"), -            &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::RORX => write!(f, "rorx"), -            &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::MULX => write!(f, "mulx"), -            &Opcode::DIV => write!(f, "div"), -            &Opcode::IDIV => write!(f, "idiv"), -            &Opcode::CMPXCHG => write!(f, "cmpxchg"), -            &Opcode::CMPXCHG8B => write!(f, "cmpxchg8b"), -            &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::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::ADDPD => write!(f, "addpd"), -            &Opcode::ANDNPS => write!(f, "andnps"), -            &Opcode::ANDNPD => write!(f, "andnpd"), -            &Opcode::ANDPS => write!(f, "andps"), -            &Opcode::ANDPD => write!(f, "andpd"), -            &Opcode::BSWAP => write!(f, "bswap"), -            &Opcode::CMPPS => write!(f, "cmpps"), -            &Opcode::CMPPD => write!(f, "cmppd"), -            &Opcode::COMISD => write!(f, "comisd"), -            &Opcode::COMISS => write!(f, "comiss"), -            &Opcode::CVTDQ2PS => write!(f, "cvtdq2ps"), -            &Opcode::CVTPS2DQ => write!(f, "cvtps2dq"), -            &Opcode::CVTPI2PS => write!(f, "cvtpi2ps"), -            &Opcode::CVTPI2PD => write!(f, "cvtpi2pd"), -            &Opcode::CVTPS2PD => write!(f, "cvtps2pd"), -            &Opcode::CVTPD2PS => write!(f, "cvtpd2ps"), -            &Opcode::CVTPS2PI => write!(f, "cvtps2pi"), -            &Opcode::CVTPD2PI => write!(f, "cvtpd2pi"), -            &Opcode::CVTTPS2PI => write!(f, "cvttps2pi"), -            &Opcode::CVTTPD2PI => write!(f, "cvttpd2pi"), -            &Opcode::CVTTPD2DQ => write!(f, "cvttpd2dq"), -            &Opcode::DIVPS => write!(f, "divps"), -            &Opcode::DIVPD => write!(f, "divpd"), -            &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::ARPL => write!(f, "arpl"), -            &Opcode::MASKMOVQ => write!(f, "maskmovq"), -            &Opcode::MASKMOVDQU => write!(f, "maskmovdqu"), -            &Opcode::MAXPS => write!(f, "maxps"), -            &Opcode::MAXPD => write!(f, "maxpd"), -            &Opcode::MINPS => write!(f, "minps"), -            &Opcode::MINPD => write!(f, "minpd"), -            &Opcode::MOVAPS => write!(f, "movaps"), -            &Opcode::MOVAPD => write!(f, "movapd"), -            &Opcode::MOVD => write!(f, "movd"), -            &Opcode::MOVLPS => write!(f, "movlps"), -            &Opcode::MOVLPD => write!(f, "movlpd"), -            &Opcode::MOVLHPS => write!(f, "movlhps"), -            &Opcode::MOVHPS => write!(f, "movhps"), -            &Opcode::MOVHPD => write!(f, "movhpd"), -            &Opcode::MOVHLPS => write!(f, "movhlps"), -            &Opcode::MOVUPD => write!(f, "movupd"), -            &Opcode::MOVMSKPS => write!(f, "movmskps"), -            &Opcode::MOVMSKPD => write!(f, "movmskpd"), -            &Opcode::MOVNTI => write!(f, "movnti"), -            &Opcode::MOVNTPS => write!(f, "movntps"), -            &Opcode::MOVNTPD => write!(f, "movntpd"), -            &Opcode::MOVNTQ => write!(f, "movntq"), -            &Opcode::MOVNTDQ => write!(f, "movntdq"), -            &Opcode::MULPS => write!(f, "mulps"), -            &Opcode::MULPD => write!(f, "mulpd"), -            &Opcode::ORPS => write!(f, "orps"), -            &Opcode::ORPD => write!(f, "orpd"), -            &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::SHUFPD => write!(f, "shufpd"), -            &Opcode::SHUFPS => write!(f, "shufps"), -            &Opcode::SLHD => write!(f, "slhd"), -            &Opcode::SQRTPS => write!(f, "sqrtps"), -            &Opcode::SQRTPD => write!(f, "sqrtpd"), -            &Opcode::SUBPS => write!(f, "subps"), -            &Opcode::SUBPD => write!(f, "subpd"), -            &Opcode::SYSENTER => write!(f, "sysenter"), -            &Opcode::SYSEXIT => write!(f, "sysexit"), -            &Opcode::UCOMISD => write!(f, "ucomisd"), -            &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::XORPD => write!(f, "xorpd"), -            &Opcode::CBW => write!(f, "cbw"), -            &Opcode::CWDE => write!(f, "cwde"), -            &Opcode::CDQE => write!(f, "cdqe"), -            &Opcode::CWD => write!(f, "cwd"), -            &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::VMCLEAR => write!(f, "vmclear"), -            &Opcode::VMPTRLD => write!(f, "vmptrld"), -            &Opcode::VMPTRST => write!(f, "vmptrst"), -            &Opcode::VMXON => write!(f, "vmxon"), -            &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::XABORT => write!(f, "xabort"), -            &Opcode::XBEGIN => write!(f, "xbegin"), -            &Opcode::RDSEED => write!(f, "rdseed"), -            &Opcode::LZCNT => write!(f, "lzcnt"), -            &Opcode::CLGI => write!(f, "clgi"), -            &Opcode::STGI => write!(f, "stgi"), -            &Opcode::SKINIT => write!(f, "skinit"), -            &Opcode::VMLOAD => write!(f, "vmload"), -            &Opcode::VMMCALL => write!(f, "vmmcall"), -            &Opcode::VMSAVE => write!(f, "vmsave"), -            &Opcode::VMRUN => write!(f, "vmrun"), -            &Opcode::INVLPGA => write!(f, "invlpga"), -            &Opcode::MOVBE => write!(f, "movbe"), -            &Opcode::ADCX => write!(f, "adcx"), -            &Opcode::ADOX => write!(f, "adox"), -            &Opcode::PREFETCHW => write!(f, "prefetchw"), -            &Opcode::RDRAND => write!(f, "rdrand"), -            &Opcode::SHA1RNDS4 => write!(f, "sha1rnds4"), -            &Opcode::SHA1NEXTE => write!(f, "sha1nexte"), -            &Opcode::SHA1MSG1 => write!(f, "sha1msg1"), -            &Opcode::SHA1MSG2 => write!(f, "sha1msg2"), -            &Opcode::SHA256RNDS2 => write!(f, "sha256rnds2"), -            &Opcode::SHA256MSG1 => write!(f, "sha256msg1"), -            &Opcode::SHA256MSG2 => write!(f, "sha256msg2"), -            &Opcode::Invalid => write!(f, "invalid"), +        f.write_str(self.name()) +    } +} + +const MNEMONICS: &[&'static str] = &[ +    "invalid", +    "add", +    "or", +    "adc", +    "sbb", +    "and", +    "xor", +    "sub", +    "cmp", +    "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", +    "addsubpd", +    "addsubps", +    "cvtsi2ss", +    "cvtsi2sd", +    "cvttsd2si", +    "cvttps2dq", +    "cvtpd2dq", +    "cvtpd2ps", +    "cvtps2dq", +    "cvtsd2si", +    "cvtsd2ss", +    "cvttss2si", +    "cvtss2si", +    "cvtss2sd", +    "cvtdq2pd", +    "lddqu", +    "movsx", +    "movsx", +    "movzx", +    "movzx", +    "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", +    "iretd", +    "iretq", +    "retf", +    "enter", +    "leave", +    "mov", +    "ret", +    "pushf", +    "wait", +    "cbw", +    "cwde", +    "cdqe", +    "cwd", +    "cdq", +    "cqo", +    "lods", +    "stos", +    "lahf", +    "sahf", +    "cmps", +    "scas", +    "movs", +    "test", +    "ins", +    "in", +    "outs", +    "out", +    "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", +    "les", +    "lds", +    "sgdt", +    "sidt", +    "lgdt", +    "lidt", +    "smsw", +    "lmsw", +    "swapgs", +    "rdtscp", +    "invlpg", +    "fxsave", +    "fxrstor", +    "ldmxcsr", +    "stmxcsr", +    "xsave", +    "xrstor", +    "xsaveopt", +    "lfence", +    "mfence", +    "sfence", +    "clflush", +    "clflushopt", +    "clwb", +    "wrmsr", +    "rdtsc", +    "rdmsr", +    "rdpmc", +    "sldt", +    "str", +    "lldt", +    "ltr", +    "verr", +    "verw", +    "cmc", +    "clc", +    "stc", +    "cli", +    "sti", +    "cld", +    "std", +    "jmpe", +    "popcnt", +    "movdqu", +    "movdqa", +    "movq", +    "cmpss", +    "cmpsd", +    "unpcklps", +    "unpcklpd", +    "unpckhps", +    "unpckhpd", +    "pshufhw", +    "pshuflw", +    "movups", +    "movq2dq", +    "movdq2q", +    "rsqrtss", +    "rcpss", +    "andn", +    "bextr", +    "blsi", +    "blsmsk", +    "blsr", +    "vmclear", +    "vmxon", +    "vmcall", +    "vmlaunch", +    "vmresume", +    "vmxoff", +    "monitor", +    "mwait", +    "clac", +    "stac", +    "encls", +    "enclv", +    "xgetbv", +    "xsetbv", +    "vmfunc", +    "xabort", +    "xbegin", +    "xend", +    "xtest", +    "enclu", +    "rdpkru", +    "wrpkru", +    "rdseed", +    "rdrand", +    "addps", +    "addpd", +    "andnps", +    "andnpd", +    "andps", +    "andpd", +    "bswap", +    "cmppd", +    "cmpps", +    "comisd", +    "comiss", +    "cvtdq2ps", +    "cvtpi2ps", +    "cvtpi2pd", +    "cvtps2pd", +    "cvtps2pi", +    "cvtpd2pi", +    "cvttps2pi", +    "cvttpd2pi", +    "cvttpd2dq", +    "divps", +    "divpd", +    "emms", +    "getsec", +    "lfs", +    "lgs", +    "lss", +    "maskmovq", +    "maskmovdqu", +    "maxps", +    "maxpd", +    "minps", +    "minpd", +    "movaps", +    "movapd", +    "movd", +    "movlps", +    "movlpd", +    "movhps", +    "movhpd", +    "movlhps", +    "movhlps", +    "movupd", +    "movmskps", +    "movmskpd", +    "movnti", +    "movntps", +    "movntpd", +    "movntq", +    "movntdq", +    "mulps", +    "mulpd", +    "orps", +    "orpd", +    "packssdw", +    "packsswb", +    "packuswb", +    "paddb", +    "paddd", +    "paddq", +    "paddsb", +    "paddsw", +    "paddusb", +    "paddusw", +    "paddw", +    "pand", +    "pandn", +    "pavgb", +    "pavgw", +    "pcmpeqb", +    "pcmpeqd", +    "pcmpeqw", +    "pcmpgtb", +    "pcmpgtd", +    "pcmpgtw", +    "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", +    "shufpd", +    "shufps", +    "slhd", +    "sqrtps", +    "sqrtpd", +    "subps", +    "subpd", +    "sysenter", +    "sysexit", +    "ucomisd", +    "ucomiss", +    "ud2e", +    "vmread", +    "vmwrite", +    "xorps", +    "xorpd", +    "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", +    "vpmaxub", +    "vpmaxud", +    "vpminsw", +    "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", +    "dpps", +    "dppd", +    "mpsadbw", +    "pmovzxdq", +    "pmovsxdq", +    "pmovzxbd", +    "pmovsxbd", +    "pmovzxwq", +    "pmovsxwq", +    "pmovzxbq", +    "pmovsxbq", +    "pmovsxwd", +    "pmovzxwd", +    "pextrq", +    "pextrd", +    "pextrw", +    "pextrb", +    "pmovsxbw", +    "pmovzxbw", +    "pinsrq", +    "pinsrd", +    "pinsrb", +    "extractps", +    "insertps", +    "roundss", +    "roundsd", +    "roundps", +    "roundpd", +    "pmaxsb", +    "pmaxsd", +    "pmaxuw", +    "pmaxud", +    "pminsd", +    "pminsb", +    "pminud", +    "pminuw", +    "blendw", +    "pblendvb", +    "pblendw", +    "blendvps", +    "blendvpd", +    "blendps", +    "blendpd", +    "pmuldq", +    "movntdqa", +    "pmulld", +    "palignr", +    "psignw", +    "psignd", +    "psignb", +    "pshufb", +    "pmulhrsw", +    "pmaddubsw", +    "pabsd", +    "pabsw", +    "pabsb", +    "phsubsw", +    "phsubw", +    "phsubd", +    "phaddd", +    "phaddsw", +    "phaddw", +    "hsubpd", +    "haddpd", +    "sha1rnds4", +    "sha1nexte", +    "sha1msg1", +    "sha1msg2", +    "sha256rnds2", +    "sha256msg1", +    "sha256msg2", +    "lzcnt", +    "clgi", +    "stgi", +    "skinit", +    "vmload", +    "vmmcall", +    "vmsave", +    "vmrun", +    "invlpga", +    "movbe", +    "adcx", +    "adox", +    "prefetchw", +    "rdpid", +    "cmpxchg8b", +    "cmpxchg16b", +    "vmptrld", +    "vmptrst", +    "bzhi", +    "mulx", +    "shlx", +    "shrx", +    "sarx", +    "pdep", +    "pext", +    "rorx", +    "xrstors", +    "xrstors64", +    "xsavec", +    "xsavec64", +    "xsaves", +    "xsaves64", +    "rdfsbase", +    "rdgsbase", +    "wrfsbase", +    "wrgsbase", +    "crc32", +    "xlat", + +    "f2xm1", +    "fabs", +    "fadd", +    "faddp", +    "fbld", +    "fbstp", +    "fchs", +    "fcmovb", +    "fcmovbe", +    "fcmove", +    "fcmovnb", +    "fcmovnbe", +    "fcmovne", +    "fcmovnu", +    "fcmovu", +    "fcom", +    "fcomi", +    "fcomip", +    "fcomp", +    "fcompp", +    "fcos", +    "fdecstp", +    "fdisi8087_nop", +    "fdiv", +    "fdivp", +    "fdivr", +    "fdivrp", +    "feni8087_nop", +    "ffree", +    "ffreep", +    "fiadd", +    "ficom", +    "ficomp", +    "fidiv", +    "fidivr", +    "fild", +    "fimul", +    "fincstp", +    "fist", +    "fistp", +    "fisttp", +    "fisub", +    "fisubr", +    "fld", +    "fld1", +    "fldcw", +    "fldenv", +    "fldl2e", +    "fldl2t", +    "fldlg2", +    "fldln2", +    "fldpi", +    "fldz", +    "fmul", +    "fmulp", +    "fnclex", +    "fninit", +    "fnop", +    "fnsave", +    "fnstcw", +    "fnstenv", +    "fnstor", +    "fnstsw", +    "fpatan", +    "fprem", +    "fprem1", +    "fptan", +    "frndint", +    "frstor", +    "fscale", +    "fsetpm287_nop", +    "fsin", +    "fsincos", +    "fsqrt", +    "fst", +    "fstp", +    "fstpnce", +    "fsub", +    "fsubp", +    "fsubr", +    "fsubrp", +    "ftst", +    "fucom", +    "fucomi", +    "fucomip", +    "fucomp", +    "fucompp", +    "fxam", +    "fxch", +    "fxtract", +    "fyl2x", +    "fyl2xp1", +    "loopnz", +    "loopz", +    "loop", +    "jrcxz", +    "pusha", +    "popa", +    "arpl", +]; + +impl Opcode { +    fn name(&self) -> &'static str { +        unsafe { +            MNEMONICS.get_unchecked(*self as usize)          }      }  } @@ -1227,7 +1338,7 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VPMULUDQ |              Opcode::PCLMULQDQ |              Opcode::PMULDQ | -            Opcode::PMULHRSU | +            Opcode::PMULHRSW |              Opcode::PMULLD |              Opcode::VPSUBB |              Opcode::VPSUBD | @@ -1298,6 +1409,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::PHSUBW |              Opcode::PMADDUBSW |              Opcode::ADDSUBPD | +            Opcode::DPPS | +            Opcode::DPPD |              Opcode::MPSADBW |              Opcode::RCPSS |              Opcode::RSQRTSS | @@ -1430,14 +1543,56 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::SLHD |              Opcode::UCOMISD |              Opcode::UCOMISS | +            Opcode::F2XM1 | +            Opcode::FABS | +            Opcode::FADD | +            Opcode::FADDP | +            Opcode::FCHS | +            Opcode::FCOS | +            Opcode::FDIV | +            Opcode::FDIVP | +            Opcode::FDIVR | +            Opcode::FDIVRP | +            Opcode::FIADD | +            Opcode::FIDIV | +            Opcode::FIDIVR | +            Opcode::FIMUL | +            Opcode::FISUB | +            Opcode::FISUBR | +            Opcode::FMUL | +            Opcode::FMULP | +            Opcode::FNCLEX | +            Opcode::FNINIT | +            Opcode::FPATAN | +            Opcode::FPREM | +            Opcode::FPREM1 | +            Opcode::FPTAN | +            Opcode::FRNDINT | +            Opcode::FSCALE | +            Opcode::FSIN | +            Opcode::FSINCOS | +            Opcode::FSQRT | +            Opcode::FSUB | +            Opcode::FSUBP | +            Opcode::FSUBR | +            Opcode::FSUBRP | +            Opcode::FXTRACT | +            Opcode::FYL2X | +            Opcode::FYL2XP1 |              Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) }              Opcode::POPF |              Opcode::PUSHF |              Opcode::ENTER |              Opcode::LEAVE | +            Opcode::PUSHA | +            Opcode::POPA |              Opcode::PUSH |              Opcode::POP => { write!(out, "{}", colors.stack_op(self)) }              Opcode::WAIT | +            Opcode::FNOP | +            Opcode::FDISI8087_NOP | +            Opcode::FENI8087_NOP | +            Opcode::FSETPM287_NOP |              Opcode::PREFETCHNTA |              Opcode::PREFETCH0 |              Opcode::PREFETCH1 | @@ -1450,8 +1605,14 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::INT |              Opcode::INTO |              Opcode::IRET | +            Opcode::IRETD | +            Opcode::IRETQ |              Opcode::RETF |              Opcode::RETURN => { write!(out, "{}", colors.stop_op(self)) } +            Opcode::LOOPNZ | +            Opcode::LOOPZ | +            Opcode::LOOP | +            Opcode::JRCXZ |              Opcode::CALL |              Opcode::CALLF |              Opcode::JMP | @@ -1498,7 +1659,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VBLENDPS |              Opcode::VBLENDVPD |              Opcode::VBLENDVPS | -            Opcode::BLENDDVB | +            Opcode::PBLENDVB | +            Opcode::PBLENDW |              Opcode::BLENDPD |              Opcode::BLENDPS |              Opcode::BLENDVPD | @@ -1619,6 +1781,7 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VPEXTRQ |              Opcode::VPEXTRW |              Opcode::PEXTRB | +            Opcode::PEXTRD |              Opcode::PEXTRQ |              Opcode::PINSRB |              Opcode::PINSRD | @@ -1700,6 +1863,7 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::SHUFPS |              Opcode::PMOVMSKB |              Opcode::LDDQU | +            Opcode::CMC |              Opcode::CLC |              Opcode::CLI |              Opcode::CLD | @@ -1739,7 +1903,35 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::MOVZX_b |              Opcode::MOVZX_w |              Opcode::MOVSX | +            Opcode::MOVSXD | +            Opcode::FILD | +            Opcode::FBLD | +            Opcode::FBSTP | +            Opcode::FIST | +            Opcode::FISTP | +            Opcode::FISTTP | +            Opcode::FLD | +            Opcode::FLD1 | +            Opcode::FLDCW | +            Opcode::FLDENV | +            Opcode::FLDL2E | +            Opcode::FLDL2T | +            Opcode::FLDLG2 | +            Opcode::FLDLN2 | +            Opcode::FLDPI | +            Opcode::FLDZ | +            Opcode::FST | +            Opcode::FSTP | +            Opcode::FSTPNCE | +            Opcode::FNSAVE | +            Opcode::FNSTCW | +            Opcode::FNSTENV | +            Opcode::FNSTOR | +            Opcode::FNSTSW | +            Opcode::FRSTOR | +            Opcode::FXCH |              Opcode::XCHG | +            Opcode::XLAT |              Opcode::CMOVA |              Opcode::CMOVB |              Opcode::CMOVG | @@ -1756,6 +1948,14 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::CMOVP |              Opcode::CMOVS |              Opcode::CMOVZ | +            Opcode::FCMOVB | +            Opcode::FCMOVBE | +            Opcode::FCMOVE | +            Opcode::FCMOVNB | +            Opcode::FCMOVNBE | +            Opcode::FCMOVNE | +            Opcode::FCMOVNU | +            Opcode::FCMOVU |              Opcode::SETO |              Opcode::SETNO |              Opcode::SETB | @@ -1802,7 +2002,9 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VPMAXSB |              Opcode::VPMAXSD |              Opcode::VPMAXSW | +            Opcode::VPMAXUB |              Opcode::VPMAXUD | +            Opcode::VPMINSW |              Opcode::VPMINSD |              Opcode::VPMINUD |              Opcode::VPTEST | @@ -1830,6 +2032,7 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::MINSD |              Opcode::MINSS |              Opcode::PMAXSB | +            Opcode::PMAXSD |              Opcode::PMAXSW |              Opcode::PMAXUB |              Opcode::PMAXUD | @@ -1843,12 +2046,27 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::CMPS |              Opcode::SCAS |              Opcode::TEST | +            Opcode::FTST | +            Opcode::FXAM | +            Opcode::FUCOM | +            Opcode::FUCOMI | +            Opcode::FUCOMIP | +            Opcode::FUCOMP | +            Opcode::FUCOMPP | +            Opcode::FCOM | +            Opcode::FCOMI | +            Opcode::FCOMIP | +            Opcode::FCOMP | +            Opcode::FCOMPP | +            Opcode::FICOM | +            Opcode::FICOMP |              Opcode::CMPSD |              Opcode::CMPSS |              Opcode::CMP |              Opcode::CMPPS |              Opcode::CMPPD |              Opcode::CMPXCHG8B | +            Opcode::CMPXCHG16B |              Opcode::CMPXCHG => { write!(out, "{}", colors.comparison_op(self)) }              Opcode::WRMSR | @@ -1867,8 +2085,11 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::XSAVE |              Opcode::XSAVEC |              Opcode::XSAVES | +            Opcode::XSAVEC64 | +            Opcode::XSAVES64 |              Opcode::XRSTOR |              Opcode::XRSTORS | +            Opcode::XRSTORS64 |              Opcode::XSAVEOPT |              Opcode::LFENCE |              Opcode::MFENCE | @@ -1907,7 +2128,6 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::LFS |              Opcode::LGS |              Opcode::LSS | -            Opcode::ARPL |              Opcode::RSM |              Opcode::SYSENTER |              Opcode::SYSEXIT | @@ -1915,8 +2135,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VMREAD |              Opcode::VMWRITE |              Opcode::VMCLEAR | -            Opcode::VMPTRST |              Opcode::VMPTRLD | +            Opcode::VMPTRST |              Opcode::VMXON |              Opcode::VMCALL |              Opcode::VMLAUNCH | @@ -1945,8 +2165,10 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::ENCLU |              Opcode::RDPKRU |              Opcode::WRPKRU | +            Opcode::ARPL |              Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) } +            Opcode::CRC32 |              Opcode::RDSEED |              Opcode::RDRAND |              Opcode::SHA1RNDS4 | @@ -1956,6 +2178,10 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::SHA256RNDS2 |              Opcode::SHA256MSG1 |              Opcode::SHA256MSG2 | +            Opcode::FFREE | +            Opcode::FFREEP | +            Opcode::FDECSTP | +            Opcode::FINCSTP |              Opcode::AESDEC |              Opcode::AESDECLAST |              Opcode::AESENC | @@ -2005,95 +2231,100 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color  /// No per-operand context when contextualizing an instruction!  struct NoContext; +impl Instruction { +    pub fn write_to<T: fmt::Write>(&self, out: &mut T) -> fmt::Result { +        self.contextualize(&NoColors, 0, Some(&NoContext), out) +    } +} +  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 ")?; +        if self.prefixes.rep_any() { +            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)?; +        out.write_str(self.opcode.name())?;          if self.opcode == Opcode::XBEGIN {              return write!(out, " $+{}", colors.number(signed_i32_hex(self.imm as i32)));          } -        match self.operands[0] { -            OperandSpec::Nothing => { -                return Ok(()); -            }, -            _ => { -                write!(out, " ")?; -                if let Some(prefix) = self.segment_override_for_op(0) { -                    write!(out, "{}:", prefix)?; -                } +        if self.operand_count > 0 { +            out.write_str(" ")?; + +            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[0]); +            x.colorize(colors, out)?; + +            for i in 1..self.operand_count { +                match self.opcode { +                    Opcode::MOVSX_b | +                    Opcode::MOVZX_b => { +                        match &self.operands[i as usize] { +                            &OperandSpec::Nothing => { +                                return Ok(()); +                            }, +                            &OperandSpec::RegMMM => { +                                out.write_str(", ")?; +                            } +                            _ => { +                                out.write_str(", byte ")?; +                                if let Some(prefix) = self.segment_override_for_op(i) { +                                    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 as usize]); +                        x.colorize(colors, out)? +                    }, +                    Opcode::MOVSX_w | +                    Opcode::MOVZX_w => { +                        match &self.operands[i as usize] { +                            &OperandSpec::Nothing => { +                                return Ok(()); +                            }, +                            &OperandSpec::RegMMM => { +                                out.write_str(", ")?; +                            } +                            _ => { +                                out.write_str(", 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 as usize]); +                        x.colorize(colors, out)? +                    }, +                    _ => { +                        match &self.operands[i as usize] { +                            &OperandSpec::Nothing => { +                                return Ok(()); +                            }, +                            _ => { +                                out.write_str(", ")?; +                                if let Some(prefix) = self.segment_override_for_op(1) { +                                    write!(out, "{}:", prefix)?; +                                } +                                let x = Operand::from_spec(self, self.operands[i as usize]); +                                x.colorize(colors, out)?                              } -                            let x = Operand::from_spec(self, self.operands[i]); -                            x.colorize(colors, out)?                          }                      }                  } diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 2fe3b3e..82484df 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -65,18 +65,22 @@ impl RegSpec {      }      #[inline] -    fn from_parts(num: u8, bank: RegisterBank) -> RegSpec { +    fn st(num: u8) -> RegSpec { +        if num >= 8 { +            panic!("invalid x87 reg st({})", num); +        } +          RegSpec { -            num: num, -            bank: bank +            num, +            bank: RegisterBank::ST          }      }      #[inline] -    fn gp_from_parts(num: u8, width: u8) -> RegSpec { +    fn from_parts(num: u8, bank: RegisterBank) -> RegSpec {          RegSpec {              num: num, -            bank: width_to_gp_reg_bank(width) +            bank: bank          }      } @@ -97,35 +101,13 @@ impl RegSpec {      }      #[inline] -    pub fn bp() -> RegSpec { -        RegSpec { -            num: 5, -            bank: RegisterBank::W -        } -    } - -    #[inline] -    pub fn ebp() -> RegSpec { -        RegSpec { -            num: 5, -            bank: RegisterBank::D -        } -    } - -    #[inline]      pub fn esp() -> RegSpec { -        RegSpec { -            num: 4, -            bank: RegisterBank::D -        } +        RegSpec { bank: RegisterBank::D, num: 4 }      }      #[inline] -    pub fn sp() -> RegSpec { -        RegSpec { -            num: 4, -            bank: RegisterBank::W -        } +    pub fn ebp() -> RegSpec { +        RegSpec { bank: RegisterBank::D, num: 5 }      }      #[inline] @@ -159,38 +141,53 @@ impl RegSpec {      }      #[inline] -    pub fn bx() -> RegSpec { -        RegSpec { bank: RegisterBank::W, num: 3 } +    pub fn esi() -> RegSpec { +        RegSpec { bank: RegisterBank::D, num: 6 }      }      #[inline] -    pub fn si() -> RegSpec { -        RegSpec { bank: RegisterBank::W, num: 6 } +    pub fn edi() -> RegSpec { +        RegSpec { bank: RegisterBank::D, num: 7 }      }      #[inline] -    pub fn esi() -> RegSpec { -        RegSpec { bank: RegisterBank::D, num: 6 } +    pub fn ax() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 0 }      }      #[inline] -    pub fn di() -> RegSpec { -        RegSpec { bank: RegisterBank::W, num: 7 } +    pub fn cx() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 1 }      }      #[inline] -    pub fn edi() -> RegSpec { -        RegSpec { bank: RegisterBank::D, num: 7 } +    pub fn dx() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 2 }      }      #[inline] -    pub fn ax() -> RegSpec { -        RegSpec { bank: RegisterBank::W, num: 0 } +    pub fn bx() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 3 }      }      #[inline] -    pub fn dx() -> RegSpec { -        RegSpec { bank: RegisterBank::W, num: 2 } +    pub fn sp() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 4 } +    } + +    #[inline] +    pub fn bp() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 5 } +    } + +    #[inline] +    pub fn si() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 6 } +    } + +    #[inline] +    pub fn di() -> RegSpec { +        RegSpec { bank: RegisterBank::W, num: 7 }      }      #[inline] @@ -204,6 +201,11 @@ impl RegSpec {      }      #[inline] +    pub fn dl() -> RegSpec { +        RegSpec { bank: RegisterBank::B, num: 2 } +    } + +    #[inline]      pub fn ah() -> RegSpec {          RegSpec { bank: RegisterBank::B, num: 4 }      } @@ -270,8 +272,8 @@ pub enum Operand {      ImmediateU32(u32),      ImmediateI32(i32),      Register(RegSpec), -    DisplacementU32(u32),      DisplacementU16(u16), +    DisplacementU32(u32),      RegDeref(RegSpec),      RegDisp(RegSpec, i32),      RegScale(RegSpec, u8), @@ -286,8 +288,8 @@ pub enum Operand {  impl OperandSpec {      pub fn is_memory(&self) -> bool {          match self { -            OperandSpec::DispU32 |              OperandSpec::DispU16 | +            OperandSpec::DispU32 |              OperandSpec::Deref |              OperandSpec::Deref_esi |              OperandSpec::Deref_edi | @@ -309,8 +311,8 @@ impl OperandSpec {              OperandSpec::RegRRR |              OperandSpec::RegMMM |              OperandSpec::RegVex | -            OperandSpec::AL | -            OperandSpec::CL | +            OperandSpec::Reg4 | +            OperandSpec::EnterFrameSize |              OperandSpec::Nothing => {                  false              } @@ -334,11 +336,8 @@ impl Operand {              OperandSpec::RegVex => {                  Operand::Register(inst.vex_reg)              } -            OperandSpec::AL => { -                Operand::Register(RegSpec::al()) -            } -            OperandSpec::CL => { -                Operand::Register(RegSpec::cl()) +            OperandSpec::Reg4 => { +                Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.vex_reg.bank })              }              OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8),              OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), @@ -346,8 +345,9 @@ impl Operand {              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::DispU32 => Operand::DisplacementU32(inst.disp), +            OperandSpec::EnterFrameSize => Operand::ImmediateU16(inst.disp as u16),              OperandSpec::DispU16 => Operand::DisplacementU16(inst.disp as u16), +            OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp),              OperandSpec::Deref => {                  Operand::RegDeref(inst.modrm_mmm)              } @@ -447,21 +447,21 @@ fn operand_size() {  #[cfg(feature="use-serde")]  #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]  pub enum RegisterBank { -    D, W, B, // Dword, Word, Byte -    CR, DR, S, EIP, EFlags,  // Control reg, Debug reg, Selector, ... -    X, Y, Z,    // XMM, YMM, ZMM -    ST, MM,     // ST, MM regs (x87, mmx) -    K, // AVX512 mask registers +    D = 0, W = 1, B = 2, // Dword, Word, Byte +    CR = 3, DR = 4, S = 5, EIP = 21, EFlags = 22,  // Control reg, Debug reg, Selector, ... +    X = 6, Y = 10, Z = 14,    // XMM, YMM, ZMM +    ST = 18, MM = 19,     // ST, MM regs (x87, mmx) +    K = 20, // AVX512 mask registers  }  #[allow(non_camel_case_types)]  #[cfg(not(feature="use-serde"))]  #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]  pub enum RegisterBank { -    D, W, B, // Dword, Word, Byte -    CR, DR, S, EIP, EFlags,  // Control reg, Debug reg, Selector, ... -    X, Y, Z,    // XMM, YMM, ZMM -    ST, MM,     // ST, MM regs (x87, mmx) -    K, // AVX512 mask registers +    D = 0, W = 1, B = 2, // Dword, Word, Byte +    CR = 3, DR = 4, S = 5, EIP = 21, EFlags = 22,  // Control reg, Debug reg, Selector, ... +    X = 6, Y = 10, Z = 14,    // XMM, YMM, ZMM +    ST = 18, MM = 19,     // ST, MM regs (x87, mmx) +    K = 20, // AVX512 mask registers  }  #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] @@ -490,14 +490,16 @@ const BMI2: [Opcode; 8] = [  ];  #[allow(dead_code)] -const XSAVE: [Opcode; 8] = [ +const XSAVE: [Opcode; 10] = [      Opcode::XGETBV,      Opcode::XRSTOR,      Opcode::XRSTORS,      Opcode::XSAVE,      Opcode::XSAVEC, +    Opcode::XSAVEC64,      Opcode::XSAVEOPT,      Opcode::XSAVES, +    Opcode::XSAVES64,      Opcode::XSETBV,  ]; @@ -509,15 +511,15 @@ const XSAVE: [Opcode; 8] = [  #[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, +    ADD, +    OR, +    ADC, +    SBB, +    AND, +    XOR, +    SUB, +    CMP,      XADD,      BT,      BTS, @@ -568,7 +570,7 @@ pub enum Opcode {      MOVZX_b,      MOVZX_w,      MOVSX, -    ARPL, +    MOVSXD,      SAR,      SAL,      SHR, @@ -598,6 +600,8 @@ pub enum Opcode {      INT,      INTO,      IRET, +    IRETD, +    IRETQ,      RETF,      ENTER,      LEAVE, @@ -721,6 +725,7 @@ pub enum Opcode {      LTR,      VERR,      VERW, +    CMC,      CLC,      STC,      CLI, @@ -852,7 +857,6 @@ pub enum Opcode {      PCMPGTB,      PCMPGTD,      PCMPGTW, -    PEXTRW,      PINSRW,      PMADDWD,      PMAXSW, @@ -1157,7 +1161,9 @@ pub enum Opcode {      VPMAXSB,      VPMAXSD,      VPMAXSW, +    VPMAXUB,      VPMAXUD, +    VPMINSW,      VPMINSD,      VPMINUD,      VPMOVMSKB, @@ -1264,6 +1270,8 @@ pub enum Opcode {      PCMPEQQ,      PTEST,      PHMINPOSUW, +    DPPS, +    DPPD,      MPSADBW,      PMOVZXDQ,      PMOVSXDQ, @@ -1276,6 +1284,8 @@ pub enum Opcode {      PMOVSXWD,      PMOVZXWD,      PEXTRQ, +    PEXTRD, +    PEXTRW,      PEXTRB,      PMOVSXBW,      PMOVZXBW, @@ -1289,6 +1299,7 @@ pub enum Opcode {      ROUNDPS,      ROUNDPD,      PMAXSB, +    PMAXSD,      PMAXUW,      PMAXUD,      PMINSD, @@ -1296,7 +1307,8 @@ pub enum Opcode {      PMINUD,      PMINUW,      BLENDW, -    BLENDDVB, +    PBLENDVB, +    PBLENDW,      BLENDVPS,      BLENDVPD,      BLENDPS, @@ -1309,7 +1321,7 @@ pub enum Opcode {      PSIGND,      PSIGNB,      PSHUFB, -    PMULHRSU, +    PMULHRSW,      PMADDUBSW,      PABSD,      PABSW, @@ -1350,6 +1362,7 @@ pub enum Opcode {      RDPID,      CMPXCHG8B, +    CMPXCHG16B,      VMPTRLD,      VMPTRST, @@ -1362,13 +1375,121 @@ pub enum Opcode {      PEXT,      RORX,      XRSTORS, +    XRSTORS64,      XSAVEC, +    XSAVEC64,      XSAVES, +    XSAVES64,      RDFSBASE,      RDGSBASE,      WRFSBASE,      WRGSBASE, + +    CRC32, +    XLAT, + +    F2XM1, +    FABS, +    FADD, +    FADDP, +    FBLD, +    FBSTP, +    FCHS, +    FCMOVB, +    FCMOVBE, +    FCMOVE, +    FCMOVNB, +    FCMOVNBE, +    FCMOVNE, +    FCMOVNU, +    FCMOVU, +    FCOM, +    FCOMI, +    FCOMIP, +    FCOMP, +    FCOMPP, +    FCOS, +    FDECSTP, +    FDISI8087_NOP, +    FDIV, +    FDIVP, +    FDIVR, +    FDIVRP, +    FENI8087_NOP, +    FFREE, +    FFREEP, +    FIADD, +    FICOM, +    FICOMP, +    FIDIV, +    FIDIVR, +    FILD, +    FIMUL, +    FINCSTP, +    FIST, +    FISTP, +    FISTTP, +    FISUB, +    FISUBR, +    FLD, +    FLD1, +    FLDCW, +    FLDENV, +    FLDL2E, +    FLDL2T, +    FLDLG2, +    FLDLN2, +    FLDPI, +    FLDZ, +    FMUL, +    FMULP, +    FNCLEX, +    FNINIT, +    FNOP, +    FNSAVE, +    FNSTCW, +    FNSTENV, +    FNSTOR, +    FNSTSW, +    FPATAN, +    FPREM, +    FPREM1, +    FPTAN, +    FRNDINT, +    FRSTOR, +    FSCALE, +    FSETPM287_NOP, +    FSIN, +    FSINCOS, +    FSQRT, +    FST, +    FSTP, +    FSTPNCE, +    FSUB, +    FSUBP, +    FSUBR, +    FSUBRP, +    FTST, +    FUCOM, +    FUCOMI, +    FUCOMIP, +    FUCOMP, +    FUCOMPP, +    FXAM, +    FXCH, +    FXTRACT, +    FYL2X, +    FYL2XP1, + +    LOOPNZ, +    LOOPZ, +    LOOP, +    JRCXZ, + +    PUSHA, +    POPA, +    ARPL,  }  #[derive(Debug)] @@ -1420,16 +1541,18 @@ enum OperandSpec {      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, +    // the register selected by a handful of avx2 vex-coded instructions, +    // stuffed in imm4. +    Reg4,      ImmI8,      ImmI16,      ImmI32,      ImmU8,      ImmU16,      ImmU32, +    // ENTER is a two-immediate instruction, where the first immediate is stored in the disp field. +    // for this case, a second immediate-style operand is needed. +    EnterFrameSize,      DispU16,      DispU32,      Deref, @@ -1446,7 +1569,7 @@ enum OperandSpec {  // the Hash, Eq, and PartialEq impls here are possibly misleading.  // They exist because downstream some structs are spelled like -// Foo<T> for T == x86 This is only to access associated types +// Foo<T> for T == x86. This is only to access associated types  // which themselves are bounded, but their #[derive] require T to  // implement these traits.  #[cfg(feature="use-serde")] @@ -1469,9 +1592,11 @@ impl yaxpeax_arch::Arch for Arch {  impl LengthedInstruction for Instruction {      type Unit = AddressDiff<u32>; +    #[inline]      fn len(&self) -> Self::Unit {          AddressDiff::from_const(self.length.into())      } +    #[inline]      fn min_size() -> Self::Unit {          AddressDiff::from_const(1)      } @@ -1710,7 +1835,7 @@ impl InstDecoder {      }      /// `bmi2` indicates support for the `BZHI`, `MULX`, `PDEP`, `PEXT`, `RORX`, `SARX`, `SHRX`, -    /// and `SHLX` instructions. `bmi2` is implemented in all x86_64 chips that implement `bmi`, +    /// and `SHLX` instructions. `bmi2` is implemented in all x86 chips that implement `bmi`,      /// except the amd `piledriver` and `steamroller` microarchitectures.      pub fn bmi2(&self) -> bool {          self.flags & (1 << 16) != 0 @@ -2199,7 +2324,7 @@ impl InstDecoder {              Opcode::PABSW |              Opcode::PABSD |              Opcode::PMADDUBSW | -            Opcode::PMULHRSU | +            Opcode::PMULHRSW |              Opcode::PSHUFB |              Opcode::PSIGNB |              Opcode::PSIGNW | @@ -2218,7 +2343,7 @@ impl InstDecoder {              Opcode::BLENDPS |              Opcode::BLENDVPD |              Opcode::BLENDVPS | -            Opcode::BLENDDVB | +            Opcode::PBLENDVB |              Opcode::BLENDW |              Opcode::PMINUW |              Opcode::PMINUD | @@ -2227,18 +2352,17 @@ impl InstDecoder {              Opcode::PMAXUW |              Opcode::PMAXUD |              Opcode::PMAXSB | +            Opcode::PMAXSD |              Opcode::ROUNDPS |              Opcode::ROUNDPD |              Opcode::ROUNDSS |              Opcode::ROUNDSD | +            Opcode::PBLENDW |              Opcode::EXTRACTPS |              Opcode::INSERTPS |              Opcode::PINSRB |              Opcode::PINSRD |              Opcode::PINSRQ | -            Opcode::PEXTRB | -            Opcode::PEXTRW | -            Opcode::PEXTRQ |              Opcode::PMOVSXBW |              Opcode::PMOVZXBW |              Opcode::PMOVSXBD | @@ -2251,10 +2375,16 @@ impl InstDecoder {              Opcode::PMOVZXWQ |              Opcode::PMOVSXDQ |              Opcode::PMOVZXDQ | +            Opcode::DPPS | +            Opcode::DPPD |              Opcode::MPSADBW |              Opcode::PHMINPOSUW |              Opcode::PTEST |              Opcode::PCMPEQQ | +            Opcode::PEXTRB | +            Opcode::PEXTRW | +            Opcode::PEXTRD | +            Opcode::PEXTRQ |              Opcode::PACKUSDW => {                  // via Intel section 5.10, SSE4.1 Instructions                  if !self.sse4_1() { @@ -2262,6 +2392,7 @@ impl InstDecoder {                      return Err(DecodeError::InvalidOpcode);                  }              } +            Opcode::CRC32 |              Opcode::PCMPESTRI |              Opcode::PCMPESTRM |              Opcode::PCMPISTRI | @@ -2321,6 +2452,7 @@ impl InstDecoder {                      return Err(DecodeError::InvalidOpcode);                  }              } +            // AVX...              Opcode::VMOVDDUP |              Opcode::VPSHUFLW |              Opcode::VHADDPS | @@ -2553,7 +2685,9 @@ impl InstDecoder {              Opcode::VPMAXSB |              Opcode::VPMAXSD |              Opcode::VPMAXSW | +            Opcode::VPMAXUB |              Opcode::VPMAXUD | +            Opcode::VPMINSW |              Opcode::VPMINSD |              Opcode::VPMINUD |              Opcode::VPMOVMSKB | @@ -2985,6 +3119,7 @@ pub struct Prefixes {      bits: u8,      vex: PrefixVex,      segment: Segment, +    _pad: u8,  }  #[derive(Debug, Copy, Clone)] @@ -3013,10 +3148,9 @@ impl Prefixes {      fn new(bits: u8) -> Prefixes {          Prefixes {              bits: bits, -            vex: PrefixVex { -                bits: 0, -            }, +            vex: PrefixVex { bits: 0 },              segment: Segment::DS, +            _pad: 0,          }      }      fn vex_from(&mut self, bits: u8) { @@ -3037,6 +3171,8 @@ impl Prefixes {      #[inline]      fn set_repnz(&mut self) { self.bits = (self.bits & 0xcf) | 0x30 }      #[inline] +    pub fn rep_any(&self) -> bool { self.bits & 0x30 != 0x00 } +    #[inline]      fn operand_size(&self) -> bool { self.bits & 0x1 == 1 }      #[inline]      fn set_operand_size(&mut self) { self.bits = self.bits | 0x1 } @@ -3096,189 +3232,518 @@ impl Prefixes {      }  } +#[derive(Debug)] +struct OperandCodeBuilder { +    bits: u16 +} + +#[allow(non_camel_case_types)] +enum ZOperandCategory { +    Zv_R = 0, +    Zv_AX = 1, +    Zb_Ib_R = 2, +    Zv_Iv_R = 3, +} + +struct ZOperandInstructions { +    bits: u16 +} + +impl ZOperandInstructions { +    fn category(&self) -> u8 { +        (self.bits >> 4) as u8 & 0b11 +    } +    fn reg(&self) -> u8 { +        (self.bits & 0b111) as u8 +    } +} + +struct EmbeddedOperandInstructions { +    bits: u16 +} + +impl EmbeddedOperandInstructions { +    #[allow(unused)] +    fn bits(&self) -> u16 { +        self.bits +    } +} + +#[allow(non_snake_case)] +impl OperandCodeBuilder { +    const fn new() -> Self { +        OperandCodeBuilder { bits: 0 } +    } + +    const fn bits(&self) -> u16 { +        self.bits +    } + +    const fn from_bits(bits: u16) -> Self { +        Self { bits } +    } + +    const fn read_modrm(mut self) -> Self { +        self.bits |= 0x8000; +        self +    } + +    const fn op0_is_rrr_and_embedded_instructions(mut self) -> Self { +        self = self.set_embedded_instructions(); +        self.bits |= 0x2000; +        self +    } + +    const fn set_embedded_instructions(mut self) -> Self { +        self.bits |= 0x4000; +        self +    } + +    #[allow(unused)] +    const fn op0_is_rrr(&self) -> bool { +        self.bits & 0x2000 != 0 +    } + +    fn has_embedded_instructions(&self) -> bool { +        self.bits & 0x4000 != 0 +    } + +    fn get_embedded_instructions(&self) -> Result<ZOperandInstructions, EmbeddedOperandInstructions> { +        // 0x4000 indicates embedded instructions +        // 0x3fff > 0x0080 indicates the embedded instructions are a Z-style operand +        if self.bits & 0x7f80 <= 0x407f { +            Ok(ZOperandInstructions { bits: self.bits }) +        } else { +            Err(EmbeddedOperandInstructions { bits: self.bits }) +        } +    } + +    #[allow(unused)] +    fn special_case_handler_index(&self) -> u16 { +        self.bits & 0xff +    } + +    const fn special_case(mut self, case: u16) -> Self { +        // leave 0x4000 unset +        self.bits |= case & 0xff; +        self +    } + +    const fn operand_case(mut self, case: u16) -> Self { +        // leave 0x4000 unset +        self.bits |= case & 0xff; +        self +    } + +    const fn op0_is_rrr_and_Z_operand(mut self, category: ZOperandCategory, reg_num: u8) -> Self { +        self = self.set_embedded_instructions(); +        // if op0 is rrr, 0x2000 unset indicates the operand category written in bits 11:10 +        // further, reg number is bits 0:2 +        // +        // when 0x2000 is unset: +        //   0x1cf8 are all unused bits, so far +        // +        // if you're counting, that's 8 bits remaining. +        // it also means one of those (0x0400?) can be used to pick some other interpretation +        // scheme. +        self.bits |= (category as u8 as u16) << 4; +        self.bits |= reg_num as u16 & 0b111; +        self +    } + +    const fn read_E(mut self) -> Self { +        self.bits |= 0x1000; +        self +    } + +    const fn has_read_E(&self) -> bool { +        self.bits & 0x1000 != 0 +    } + +    const fn byte_operands(mut self) -> Self { +        self.bits |= 0x0800; +        self +    } + +    const fn mem_reg(mut self) -> Self { +        self.bits |= 0x0400; +        self +    } + +    const fn reg_mem(self) -> Self { +        // 0x0400 unset +        self +    } + +    const fn has_byte_operands(&self) -> bool { +        (self.bits & 0x0800) != 0 +    } + +    #[allow(unused)] +    const fn has_mem_reg(&self) -> bool { +        (self.bits & 0x0400) != 0 +    } + +    const fn has_reg_mem(&self) -> bool { +        (self.bits & 0x0400) == 0 +    } + +    const fn only_modrm_operands(mut self) -> Self { +        self.bits |= 0x0200; +        self +    } + +    const fn is_only_modrm_operands(&self) -> bool { +        self.bits & 0x0200 != 0 +    } + +    // WHEN AN IMMEDIATE IS PRESENT, THERE ARE ONLY 0x3F ALLOWED SPECIAL CASES. +    // WHEN NO IMMEDIATE IS PRESENT, THERE ARE 0xFF ALLOWED SPECIAL CASES. +    // SIZE IS DECIDED BY THE FOLLOWING TABLE: +    // 0: 1 BYTE +    // 1: 4 BYTES +    const fn with_imm(mut self, only_imm: bool, size: u8) -> Self { +        self.bits |= 0x100; +        self.bits |= (size as u16) << 6; +        self.bits |= (only_imm as u16) << 7; +        self +    } + +    fn has_imm(&self) -> Option<(bool, u8)> { +        if self.bits & 0x100 != 0 { +            Some(((self.bits & 0x80) != 0, (self.bits as u8 >> 6) & 1)) +        } else { +            None +        } +    } +} +  #[allow(non_camel_case_types)]  // might be able to pack these into a u8, but with `Operand` being u16 as well now there's little  // point. table entries will have a padding byte per record already.  //  // many of the one-off per-opcode variants could be written as 'decide based on opcode' but trying  // to pack this more tightly only makes sense if opcode were smaller, to get some space savings. +// +// bit 15 is "read modrm?" +// 0bMxxx_xxxx_xxxx_xxxx +//   | +//   | +//   | +//   | +//   | +//   | +//   ---------------------------> read modr/m?  #[repr(u16)]  #[derive(Copy, Clone, Debug, PartialEq)]  pub enum OperandCode { -    ModRM_0x0f00, -    ModRM_0x0f01, -    ModRM_0x0f0d, -    ModRM_0x0fae, -    ModRM_0x0fba, -    ModRM_0xf238, -    ModRM_0xf30fae, -    ModRM_0x660fae, -    ModRM_0xf30fc7, -    ModRM_0x660f38, -    ModRM_0xf30f38, -    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_0x660f12, -    ModRM_0x660f16, -    ModRM_0x660f71, -    ModRM_0x660f72, -    ModRM_0x660f73, -    ModRM_0x660fc7, -    ModRM_0x0fc7, -    ModRM_0xc4, -    ModRM_0xc5, -    Nothing, -    // Implied, -    Unsupported, -    AL_Ib = 0x100, -    AX_Ib = 0x101, -    Ib_AL = 0x102, -    Ib_AX = 0x103, -    AX_DX = 0x104, -    AL_DX = 0x105, -    DX_AX = 0x106, -    DX_AL = 0x107, -    MOVQ_f30f = 0x108, -    G_xmm_Ed_Ib = 0x1ef, // mirror G_xmm_Edq, but also read an immediate -    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_Iv_R0 = 0x58, -    Zv_Iv_R1 = 0x59, -    Zv_Iv_R2 = 0x5a, -    Zv_Iv_R3 = 0x5b, -    Zv_Iv_R4 = 0x5c, -    Zv_Iv_R5 = 0x5d, -    Zv_Iv_R6 = 0x5e, -    Zv_Iv_R7 = 0x5f, -    Gv_Eb = 0x60, -    Gv_Ew = 0x61, -    Ew_Gw = 0x62, -    G_E_mm_Ib = 0x64, -    G_E_xmm_Ib = 0x65, -    AL_Ibs = 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, -    Gv_E_xmm = 0x1c7, -    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, +    Ivs = OperandCodeBuilder::new().special_case(25).bits(), +    I_3 = OperandCodeBuilder::new().special_case(27).bits(), +    Nothing = OperandCodeBuilder::new().special_case(28).bits(), +    Ib = OperandCodeBuilder::new().with_imm(false, 0).special_case(32).bits(), +    Ibs = OperandCodeBuilder::new().with_imm(true, 0).special_case(33).bits(), +    Jvds = OperandCodeBuilder::new().with_imm(true, 1).special_case(32).bits(), +    Yv_Xv = OperandCodeBuilder::new().special_case(50).bits(), + +    x87_d8 = OperandCodeBuilder::new().special_case(32).bits(), +    x87_d9 = OperandCodeBuilder::new().special_case(33).bits(), +    x87_da = OperandCodeBuilder::new().special_case(34).bits(), +    x87_db = OperandCodeBuilder::new().special_case(35).bits(), +    x87_dc = OperandCodeBuilder::new().special_case(36).bits(), +    x87_dd = OperandCodeBuilder::new().special_case(37).bits(), +    x87_de = OperandCodeBuilder::new().special_case(38).bits(), +    x87_df = OperandCodeBuilder::new().special_case(39).bits(), + +    Eb_R0 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(0) +        .bits(), +    AL_Ib = OperandCodeBuilder::new().special_case(33).with_imm(false, 0).bits(), +    AX_Ib = OperandCodeBuilder::new().special_case(34).with_imm(false, 0).bits(), +    Ib_AL = OperandCodeBuilder::new().special_case(35).with_imm(false, 0).bits(), +    Ib_AX = OperandCodeBuilder::new().special_case(36).with_imm(false, 0).bits(), +    AX_DX = OperandCodeBuilder::new().special_case(44).bits(), +    AL_DX = OperandCodeBuilder::new().special_case(45).bits(), +    DX_AX = OperandCodeBuilder::new().special_case(46).bits(), +    DX_AL = OperandCodeBuilder::new().special_case(47).bits(), +    MOVQ_f30f = OperandCodeBuilder::new().special_case(48).bits(), + +    Unsupported = OperandCodeBuilder::new().special_case(49).bits(), + +    ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().special_case(40).bits(), +    ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().special_case(41).bits(), +    ModRM_0x0f0d = OperandCodeBuilder::new().read_modrm().special_case(42).bits(), +    ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().special_case(43).bits(), +    ModRM_0x0fba = OperandCodeBuilder::new().read_modrm().special_case(44).bits(), +    ModRM_0xf30fae = OperandCodeBuilder::new().read_modrm().special_case(46).bits(), +    ModRM_0x660fae = OperandCodeBuilder::new().read_modrm().special_case(47).bits(), +    ModRM_0xf30fc7 = OperandCodeBuilder::new().read_modrm().special_case(48).bits(), +    ModRM_0x660f38 = OperandCodeBuilder::new().read_modrm().special_case(49).bits(), +    ModRM_0xf20f38 = OperandCodeBuilder::new().read_modrm().special_case(50).bits(), +    ModRM_0xf30f38 = OperandCodeBuilder::new().read_modrm().special_case(51).bits(), +    ModRM_0x660f3a = OperandCodeBuilder::new().read_modrm().special_case(52).bits(), +    ModRM_0x0f38 = OperandCodeBuilder::new().read_modrm().special_case(53).bits(), +    ModRM_0x0f3a = OperandCodeBuilder::new().read_modrm().special_case(54).bits(), +    ModRM_0x0f71 = OperandCodeBuilder::new().read_modrm().special_case(55).bits(), +    ModRM_0x0f72 = OperandCodeBuilder::new().read_modrm().special_case(56).bits(), +    ModRM_0x0f73 = OperandCodeBuilder::new().read_modrm().special_case(57).bits(), +    ModRM_0x660f12 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), +    ModRM_0x660f16 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), +    ModRM_0x660f71 = OperandCodeBuilder::new().read_modrm().special_case(60).bits(), +    ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().special_case(61).bits(), +    ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().special_case(62).bits(), +    ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().special_case(63).bits(), +    ModRM_0x0fc7 = OperandCodeBuilder::new().read_modrm().special_case(64).bits(), +    ModRM_0xc4 = OperandCodeBuilder::new().read_modrm().special_case(65).bits(), +    ModRM_0xc5 = OperandCodeBuilder::new().read_modrm().special_case(66).bits(), +    // xmmword? +    ModRM_0x0f12 = OperandCodeBuilder::new() +        .read_modrm() +        .op0_is_rrr_and_embedded_instructions() +        .read_E() +        .reg_mem() +        .operand_case(65) +        .bits(), +    // xmmword? +    ModRM_0x0f16 = OperandCodeBuilder::new() +        .read_modrm() +        .op0_is_rrr_and_embedded_instructions() +        .read_E() +        .reg_mem() +        .operand_case(66) +        .bits(), +    // encode immediates? +    ModRM_0xc0_Eb_Ib = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(5) +        .bits(), +    ModRM_0xc1_Ev_Ib = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(6) +        .bits(), +    ModRM_0xd0_Eb_1 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(7) +        .bits(), +    ModRM_0xd1_Ev_1 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(8) +        .bits(), +    ModRM_0xd2_Eb_CL = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(9) +        .bits(), +    ModRM_0xd3_Ev_CL = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(10) +        .bits(), +    ModRM_0x80_Eb_Ib = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .with_imm(false, 0) +        .byte_operands() +        .operand_case(1) +        .bits(), +    ModRM_0x83_Ev_Ibs = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .with_imm(false, 0) +        .operand_case(26) +        .bits(),      // 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, +    ModRM_0x81_Ev_Ivs = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(2) +        .bits(), +    ModRM_0xc6_Eb_Ib = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(3) +        .bits(), +    ModRM_0xc7_Ev_Iv = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(4) +        .bits(), +    ModRM_0xfe_Eb = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(13) +        .bits(), +    ModRM_0x8f_Ev = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(30) +        .bits(),      // gap, 0x94 -    ModRM_0xff_Ev = 0x95, -    ModRM_0xf6 = 0x96, -    ModRM_0xf7 = 0x97, -    Eb_R0 = 0x98, -    Ev = 0x99, -    ModRM_0x0f18 = 0x9b, +    ModRM_0xff_Ev = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(14) +        .bits(), +    ModRM_0x0f18 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(58) +        .bits(), +    ModRM_0xf6 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .byte_operands() +        .operand_case(11) +        .bits(), +    ModRM_0xf7 = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(12) +        .bits(), +    Ev = OperandCodeBuilder::new() +        .read_modrm() +        .set_embedded_instructions() +        .read_E() +        .operand_case(18) +        .bits(), +    Zv_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 0).bits(), +    Zv_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 1).bits(), +    Zv_R2 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 2).bits(), +    Zv_R3 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 3).bits(), +    Zv_R4 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 4).bits(), +    Zv_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 5).bits(), +    Zv_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 6).bits(), +    Zv_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 7).bits(), +    // Zv_AX_R0 = 0x48, +    Zv_AX_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 1).bits(), +    Zv_AX_R2 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 2).bits(), +    Zv_AX_R3 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 3).bits(), +    Zv_AX_R4 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 4).bits(), +    Zv_AX_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 5).bits(), +    Zv_AX_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 6).bits(), +    Zv_AX_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 7).bits(), +    Zb_Ib_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 0).bits(), +    Zb_Ib_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 1).bits(), +    Zb_Ib_R2 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 2).bits(), +    Zb_Ib_R3 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 3).bits(), +    Zb_Ib_R4 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 4).bits(), +    Zb_Ib_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 5).bits(), +    Zb_Ib_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 6).bits(), +    Zb_Ib_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zb_Ib_R, 7).bits(), +    Zv_Iv_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 0).bits(), +    Zv_Iv_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 1).bits(), +    Zv_Iv_R2 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 2).bits(), +    Zv_Iv_R3 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 3).bits(), +    Zv_Iv_R4 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 4).bits(), +    Zv_Iv_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 5).bits(), +    Zv_Iv_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 6).bits(), +    Zv_Iv_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 7).bits(), +    Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(15).bits(), +    Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(16).bits(), +    Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(37).bits(), +//    Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(17).bits(), +    Gd_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(40).bits(), +    Md_Gd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(51).bits(), +    G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(29).bits(), +    G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(22).bits(), +    AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(50).bits(), +    AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(52).bits(), +    AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(53).bits(), +    AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().with_imm(false, 0).byte_operands().operand_case(23).bits(), +    AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(24).bits(), + +    Eb_Gb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().mem_reg().bits(), +    Ev_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().mem_reg().bits(), +    Gb_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().reg_mem().bits(), +    Gv_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().bits(), +    Gv_M = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(25).bits(), +    Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).byte_operands().reg_mem().operand_case(40).bits(), +    Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(41).bits(), +    Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(55).bits(),      // gap, 0x9a -    Gv_M = 0xdb, -    G_mm_Edq = 0xdd, -    G_mm_E = 0xdf, -    G_U_xmm = 0xe1, -    G_xmm_Ed = 0xe3, -    G_mm_E_xmm = 0xe5, -    G_E_mm = 0xe7, -    Edq_G_mm = 0xe9, -    Edq_G_xmm = 0x1e9, -    E_G_mm = 0xeb, -    G_xmm_E_mm = 0xed, -    G_xmm_U_mm = 0x1ed, -    U_mm_G_xmm = 0x2ed, -    G_xmm_Edq = 0xef, -    G_U_mm = 0xf1, -    Ev_Gv_Ib = 0xf3, -    Ev_Gv_CL = 0xf5, -    G_M_xmm = 0xf7, -    G_E_xmm = 0xf9, +    G_xmm_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(53).bits(), +    G_xmm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(54).bits(), +    U_mm_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(55).bits(), +    G_xmm_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(57).bits(), +    G_mm_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(58).bits(), +    Gd_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(59).bits(), +    Gv_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(60).bits(), +    //= 0x816f, // mirror G_xmm_Edq, but also read an immediate +    G_xmm_Ed_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(61).bits(), +    G_U_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(62).bits(), +    G_M_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(20).bits(), +    G_E_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(21).bits(), +    E_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(19).bits(), +    M_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(63).bits(), +    G_E_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(64).bits(), +    G_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(65).bits(), +    E_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(66).bits(), +    Edq_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(67).bits(), +    Edq_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(68).bits(), +    G_mm_Edq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(69).bits(), +    G_mm_E = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(70).bits(), +    Ev_Gv_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(71).bits(), +    Ev_Gv_CL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(72).bits(), +    G_mm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(73).bits(), +    G_Md_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(74).bits(), +    G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(75).bits(), +    G_E_d = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(76).bits(), +    E_G_d = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(77).bits(), +    CVT_AA = OperandCodeBuilder::new().special_case(77).bits(), +    CVT_DA = OperandCodeBuilder::new().special_case(78).bits(), +    Rq_Cq_0 = OperandCodeBuilder::new().special_case(79).bits(), +    Rq_Dq_0 = OperandCodeBuilder::new().special_case(80).bits(), +    Cq_Rq_0 = OperandCodeBuilder::new().special_case(81).bits(), +    Dq_Rq_0 = OperandCodeBuilder::new().special_case(82).bits(), +    FS = OperandCodeBuilder::new().special_case(83).bits(), +    GS = OperandCodeBuilder::new().special_case(84).bits(), +    Yb_DX = OperandCodeBuilder::new().special_case(85).bits(), +    Yv_DX = OperandCodeBuilder::new().special_case(86).bits(), +    DX_Xb = OperandCodeBuilder::new().special_case(87).bits(), +    DX_Xv = OperandCodeBuilder::new().special_case(88).bits(), +    AH = OperandCodeBuilder::new().special_case(89).bits(), +    AX_Xv = OperandCodeBuilder::new().special_case(90).bits(), +    Ew_Sw = OperandCodeBuilder::new().special_case(91).bits(), +    Fw = OperandCodeBuilder::new().special_case(92).bits(), +    I_1 = OperandCodeBuilder::new().special_case(93).bits(), +    Iw = OperandCodeBuilder::new().special_case(94).bits(), +    Iw_Ib = OperandCodeBuilder::new().special_case(95).bits(), +    Ob_AL = OperandCodeBuilder::new().special_case(96).bits(), +    Ov_AX = OperandCodeBuilder::new().special_case(97).bits(), +    Sw_Ew = OperandCodeBuilder::new().special_case(98).bits(), +    Yb_AL = OperandCodeBuilder::new().special_case(99).bits(), +    Yb_Xb = OperandCodeBuilder::new().special_case(100).bits(), +    Yv_AX = OperandCodeBuilder::new().special_case(101).bits(), +    Ew_Gw = OperandCodeBuilder::new().special_case(102).bits(),  }  fn base_opcode_map(v: u8) -> Opcode { @@ -3580,13 +4045,6 @@ const OPCODE_660F_MAP: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::PADDQ), OperandCode::G_E_xmm),  ]; -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), @@ -3632,7 +4090,7 @@ 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::CVTSI2SD), OperandCode::G_xmm_Edq), +    OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SD), OperandCode::G_xmm_Ed),      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), @@ -3647,7 +4105,7 @@ 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::ModRM_0xf238), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf20f38),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), @@ -3861,13 +4319,6 @@ const OPCODE_F20F_MAP: [OpcodeRecord; 256] = [      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), @@ -3913,7 +4364,7 @@ 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::CVTSI2SS), OperandCode::G_xmm_Edq), +    OpcodeRecord(Interpretation::Instruction(Opcode::CVTSI2SS), OperandCode::G_xmm_Ed),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::CVTTSS2SI), OperandCode::Gv_E_xmm),      OpcodeRecord(Interpretation::Instruction(Opcode::CVTSS2SI), OperandCode::Gv_E_xmm), @@ -4142,47 +4593,11 @@ const OPCODE_F30F_MAP: [OpcodeRecord; 256] = [      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::LSL), OperandCode::Gv_Ew_LSL),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::CLTS), OperandCode::Nothing), @@ -4307,12 +4722,12 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      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::PCMPEQB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQD), OperandCode::G_E_mm),      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::VMREAD), OperandCode::E_G_d), +    OpcodeRecord(Interpretation::Instruction(Opcode::VMWRITE), OperandCode::G_E_d),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), @@ -4378,7 +4793,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      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::BTR), OperandCode::Ev_Gv),      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), @@ -4396,7 +4811,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      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::MOVNTI), OperandCode::Md_Gd),      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), @@ -4420,56 +4835,50 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      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), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBUSW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMINUB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PAND), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDUSW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PANDN), OperandCode::G_E_mm),  // 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::PAVGB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSRAW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSRAD), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PAVGW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMULHUW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMULHW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTQ), OperandCode::G_Md_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBSW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMINSW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::POR), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDSB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDSW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSW), OperandCode::G_E_mm),      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::PSLLW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSLLD), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSLLQ), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMULUDQ), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PMADDWD), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSADBW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::MASKMOVQ), OperandCode::G_mm_U_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBD), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PSUBQ), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDB), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDW), OperandCode::G_E_mm), +    OpcodeRecord(Interpretation::Instruction(Opcode::PADDD), OperandCode::G_E_mm),      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 { @@ -4587,8 +4996,8 @@ const OPCODES: [OpcodeRecord; 256] = [      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::PUSHA), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::POPA), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::ARPL), OperandCode::Ew_Gw),      OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), @@ -4648,7 +5057,7 @@ const OPCODES: [OpcodeRecord; 256] = [      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::WAIT), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::PUSHF), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::POPF), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::SAHF), OperandCode::AH), @@ -4701,7 +5110,7 @@ const OPCODES: [OpcodeRecord; 256] = [      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::INTO), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::IRET), OperandCode::Fw),  // 0xd0      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd0_Eb_1), @@ -4712,32 +5121,28 @@ const OPCODES: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      // XLAT -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::XLAT), OperandCode::Nothing),      // x86 d8 -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d8),      // x86 d9 -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d9),      // x86 da -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_da),      // x86 db -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_db),      // x86 dc -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dc),      // x86 dd -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dd),      // x86 de -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_de),      // x86 df -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Unsupported), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_df),  // 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), +    OpcodeRecord(Interpretation::Instruction(Opcode::LOOPNZ), OperandCode::Ibs), +    OpcodeRecord(Interpretation::Instruction(Opcode::LOOPZ), OperandCode::Ibs), +    OpcodeRecord(Interpretation::Instruction(Opcode::LOOP), OperandCode::Ibs), +    OpcodeRecord(Interpretation::Instruction(Opcode::JRCXZ), OperandCode::Ibs),      OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AL_Ib),      OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AX_Ib),      OpcodeRecord(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AL), @@ -4754,13 +5159,13 @@ const OPCODES: [OpcodeRecord; 256] = [  // 0xf0      OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing),      // ICEBP? -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::I_1),      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::CMC), 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), @@ -4784,6 +5189,14 @@ pub(self) fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instru      }  }  #[allow(non_snake_case)] +pub(self) fn read_E_st<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::ST) +    } 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) @@ -4809,42 +5222,42 @@ fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) ->  #[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::W } else { RegisterBank::D };      let sibbyte = bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?;      *length += 1; -    let op_spec = if (sibbyte & 7) == 0b101 { -        let disp = if modbits == 0b00 { +    let disp = if modbits == 0b00 { +        if (sibbyte & 7) == 0b101 {              *length += 4; -            read_num(bytes_iter, 4)? as i32 -        } else if modbits == 0b01 { -            *length += 1; -            read_num(bytes_iter, 1)? as i8 as i32 +            read_num(bytes_iter, 4)? as i32 as u32          } else { -            *length += 4; -            read_num(bytes_iter, 4)? as i32 -        }; +            0 +        } +    } else if modbits == 0b01 { +        *length += 1; +        read_num(bytes_iter, 1)? as i8 as i32 as u32 +    } else { +        *length += 4; +        read_num(bytes_iter, 4)? as i32 as u32 +    }; +    instr.disp = disp; +    let op_spec = if (sibbyte & 7) == 0b101 {          if ((sibbyte >> 3) & 7) == 0b100 {              if modbits == 0b00 { -                instr.disp = disp as u32; -                  OperandSpec::DispU32              } else { -                let reg = RegSpec::from_parts(0b100, addr_width); -                instr.modrm_mmm = reg; +                instr.modrm_mmm.num |= 0b101;                  if disp == 0 {                      OperandSpec::Deref                  } else { -                    instr.disp = disp as i32 as u32;                      OperandSpec::RegDisp                  }              }          } else { -            instr.modrm_mmm = RegSpec::from_parts(5, addr_width); +            instr.modrm_mmm.num |= 0b101; +            instr.sib_index.num |= (sibbyte >> 3) & 7; -            instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, addr_width);              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale; @@ -4855,7 +5268,6 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m                      OperandSpec::RegIndexBaseScale                  }              } else { -                instr.disp = disp as i32 as u32;                  if modbits == 0 {                      OperandSpec::RegScaleDisp                  } else { @@ -4864,33 +5276,22 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m              }          }      } else { -        instr.modrm_mmm = RegSpec::from_parts(sibbyte & 7, 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 -        }; +        instr.modrm_mmm.num |= sibbyte & 7;          if ((sibbyte >> 3) & 7) == 0b100 {              if disp == 0 {                  OperandSpec::Deref              } else { -                instr.disp = disp as i32 as u32;                  OperandSpec::RegDisp              }          } else { -            instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, addr_width); +            instr.sib_index.num |= (sibbyte >> 3) & 7; +              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale;              if disp == 0 {                  OperandSpec::RegIndexBaseScale              } else { -                instr.disp = disp as i32 as u32;                  OperandSpec::RegIndexBaseScaleDisp              }          } @@ -4973,17 +5374,17 @@ fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod      if instr.prefixes.address_size() {          return read_M_16bit(bytes_iter, instr, modrm, length);      } -    let addr_width = RegisterBank::D; +    instr.modrm_mmm.bank = RegisterBank::D;      let modbits = modrm >> 6;      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; -        instr.disp = read_num(bytes_iter, 4)? as u32; +        instr.disp = read_num(bytes_iter, 4)?;          OperandSpec::DispU32      } else { -        instr.modrm_mmm = RegSpec::from_parts(mmm, addr_width); +        instr.modrm_mmm.num |= mmm;          if modbits == 0b00 {              OperandSpec::Deref @@ -5012,8 +5413,7 @@ fn width_to_gp_reg_bank(width: u8) -> RegisterBank {          1 => return RegisterBank::B,          2 => return RegisterBank::W,          4 => return RegisterBank::D, -        o => { unreachable!("impossible width: {}", o); } -//        _ => unsafe { unreachable_unchecked() } +        _ => unsafe { unreachable_unchecked(); }      }  } @@ -5044,30 +5444,35 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in          match bytes_iter.next() {              Some(b) => {                  length += 1; +                if length >= 15 { +                    return Err(DecodeError::TooLong); +                }                  let record = OPCODES[b as usize];                  if b == 0x0f { +                    let b = bytes_iter.next().ok_or(DecodeError::ExhaustedInput)?; +                    length += 1;                      let record = match alternate_opcode_map {                          Some(opcode_map) => { -                            let (rec, opcode_byte) = match opcode_map { +                            let rec = match opcode_map {                                  OpcodeMap::Map66 => { -                                    read_opcode_660f_map(&mut bytes_iter, &mut length)? +                                    OPCODE_660F_MAP[b as usize]                                  },                                  OpcodeMap::MapF2 => { -                                    read_opcode_f20f_map(&mut bytes_iter, &mut length)? +                                    OPCODE_F20F_MAP[b as usize]                                  },                                  OpcodeMap::MapF3 => { -                                    read_opcode_f30f_map(&mut bytes_iter, &mut length)? +                                    OPCODE_F30F_MAP[b as usize]                                  },                              };                              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] +                                OPCODE_0F_MAP[b as usize]                              } else {                                  rec                              }                          },                          None => { -                            read_opcode_0f_map(&mut bytes_iter, &mut length)? +                            OPCODE_0F_MAP[b as usize]                          }                      }; @@ -5102,10 +5507,6 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in                          0x67 => {                              prefixes.set_address_size();                          }, -                        0x9b => { -                            // TODO: WAIT prefix -                            return Err(DecodeError::IncompleteDecoder); -                        },                          0xf0 => {                              prefixes.set_lock();                          }, @@ -5115,10 +5516,7 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in                          0xf3 => {                              alternate_opcode_map = Some(OpcodeMap::MapF3);                          }, -//                        _ => { unsafe { unreachable_unchecked(); } } -                        o => { -                            unreachable!("invalid prefix {:#02x}", o); -                        } +                        _ => { unsafe { unreachable_unchecked(); } }                      }                  }              }, @@ -5127,14 +5525,19 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in              }          }      }; +    if record == OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing) { +        return Err(DecodeError::InvalidOpcode); +    }      if let Interpretation::Instruction(opcode) = record.0 {          instruction.opcode = opcode;      } else { -//        unsafe { unreachable_unchecked(); } -        unreachable!("bad record, needs to be an Instruction but was {:?}", record); +        unsafe { unreachable_unchecked(); }      }      instruction.prefixes = prefixes;      read_operands(decoder, bytes_iter, instruction, record.1, &mut length)?; +    if length > 15 { +        return Err(DecodeError::TooLong); +    }      instruction.length = length;      if decoder != &InstDecoder::default() { @@ -5144,289 +5547,213 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in      }      Ok(())  } +/* likely cases +        OperandCode::Eb_R0 => 0 +        _op @ OperandCode::ModRM_0x80_Eb_Ib => 1 +        _op @ OperandCode::ModRM_0x81_Ev_Ivs => 2 +        op @ OperandCode::ModRM_0xc6_Eb_Ib => 3 +        op @ OperandCode::ModRM_0xc7_Ev_Iv => 4 +        op @ OperandCode::ModRM_0xc0_Eb_Ib => 5 +        op @ OperandCode::ModRM_0xc1_Ev_Ib => 6 +        op @ OperandCode::ModRM_0xd0_Eb_1 => 7 +        op @ OperandCode::ModRM_0xd1_Ev_1 => 8 +        op @ OperandCode::ModRM_0xd2_Eb_CL => 9 +        op @ OperandCode::ModRM_0xd3_Ev_CL => 10 +        _op @ OperandCode::ModRM_0xf6 => 11 +        _op @ OperandCode::ModRM_0xf7 => 12 +        OperandCode::ModRM_0xfe_Eb => 13 +        OperandCode::ModRM_0xff_Ev => 14 +        OperandCode::Gv_Eb => 15 +        OperandCode::Gv_Ew => 16 +        OperandCode::Ev => 18 +        OperandCode::E_G_xmm => 19 +        op @ OperandCode::G_M_xmm => 20 +        op @ OperandCode::G_E_xmm => 21 +        OperandCode::G_E_xmm_Ib => 22 +        OperandCode::AL_Ibs => 23 +        OperandCode::AX_Ivd => 24 +        OperandCode::Ivs => 25 +        OperandCode::ModRM_0x83_Ev_Ibs => 26 +        OperandCode::I_3 => 27 +        OperandCode::Nothing => 28 +        OperandCode::G_E_mm_Ib => 29 +        OperandCode::ModRM_0x8f_Ev => 30 + + */ +#[inline(always)]  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(SizeCode::vd, instruction.prefixes); -            let bank = if opwidth == 4 { -                RegisterBank::D -            } else { -                RegisterBank::W -            }; -            instruction.modrm_rrr = -                RegSpec::from_parts(reg, 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, 1); -            instruction.imm = -                read_imm_unsigned(&mut bytes_iter, 1, length)?; -            instruction.operands[1] = OperandSpec::ImmU8; -            instruction.operand_count = 2; -        } else { -            // category == 3, Zv_Iv_R -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            let bank = if opwidth == 4 { -                RegisterBank::D -            } else { -                RegisterBank::W -            }; -            instruction.modrm_rrr = -                RegSpec::from_parts(reg, bank); -            instruction.imm = -                read_num(&mut bytes_iter, opwidth)? as u32; -            *length += opwidth; -            instruction.operands[1] = match opwidth { -                1 => OperandSpec::ImmI8, -                2 => OperandSpec::ImmI16, -                4 => OperandSpec::ImmI32, -                o => { unreachable!("impossibe op width {}", o) } -            }; -            instruction.operand_count = 2; +    instruction.operands[0] = OperandSpec::RegRRR; +    instruction.operand_count = 2; +    let operand_code = OperandCodeBuilder::from_bits(operand_code as u16); +    if operand_code.has_embedded_instructions() { +        match operand_code.get_embedded_instructions() { +            Ok(z_operand_code) => { +                let reg = z_operand_code.reg(); +                match z_operand_code.category() { +                    0 => { +                        // these are Zv_R +                        let bank = if !instruction.prefixes.operand_size() { +                            RegisterBank::D +                        } else { +                            RegisterBank::W +                        }; +                        instruction.modrm_rrr = +                            RegSpec::from_parts(reg, bank); +                        instruction.operand_count = 1; +                    } +                    1 => { +                        // Zv_AX +                    } +                    2 => { +                        // these are Zb_Ib_R +                        instruction.modrm_rrr = +                            RegSpec::from_parts(reg, RegisterBank::B); +                        instruction.imm = +                            read_imm_unsigned(&mut bytes_iter, 1, length)?; +                        instruction.operands[1] = OperandSpec::ImmU8; +                    } +                    3 => { +                        // category == 3, Zv_Iv_R +                        if !instruction.prefixes.operand_size() { +                            instruction.modrm_rrr = +                                RegSpec::from_parts(reg, RegisterBank::D); +                            instruction.imm = +                                read_imm_unsigned(&mut bytes_iter, 4, length)?; +                            instruction.operands[1] = OperandSpec::ImmI32; +                        } else { +                            instruction.modrm_rrr = +                                RegSpec::from_parts(reg, RegisterBank::W); +                            instruction.imm = +                                read_imm_unsigned(&mut bytes_iter, 2, length)?; +                            instruction.operands[1] = OperandSpec::ImmI16; +                        } +                    } +                    _ => { +                        unreachable!("bad category"); +                    } +                } +                return Ok(()); +            }, +            // EmbeddedOperandInstructions but those are entirely handled in the fall-through +            // below. one day this may grow to be an `Err(the_operand_instructions)` though, so for +            // a simpler diff the above is pre-`match`/`Ok`'d. +            _ => {}          } -        return Ok(());      }      let mut modrm = 0; -    let mut opwidth = 0; +    let bank: RegisterBank;      let mut mem_oper = OperandSpec::Nothing; -    let mut bank = RegisterBank::D; -    let code_int = operand_code as u8; -    if ((code_int) & 0x80) == 0x80 { +    if operand_code.has_read_E() {          // cool! we can precompute opwidth and know we need to read_E. -        if (code_int & 1) == 1 { +        if !operand_code.has_byte_operands() {              // further, this is an vd E -            opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            if opwidth == 4 { +            if !instruction.prefixes.operand_size() {                  bank = RegisterBank::D; -            } else if opwidth == 2 { +            } else {                  bank = RegisterBank::W;              }          } else { -            opwidth = 1;              bank = RegisterBank::B;          };          modrm = read_modrm(&mut bytes_iter, length)?; -        instruction.modrm_rrr = -            RegSpec::from_parts((modrm >> 3) & 7, bank); - -        mem_oper = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; -    } +        instruction.modrm_rrr.bank = bank; +        instruction.modrm_rrr.num = (modrm >> 3) & 7; -    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) +        mem_oper = if modrm >= 0b11000000 { +            if operand_code.bits() == (OperandCode::Gv_M as u16) { +                return Err(DecodeError::InvalidOperand); +            } +            read_modrm_reg(instruction, modrm, bank)?          } else { -            (0, 1) +            read_M(&mut bytes_iter, instruction, modrm, length)?          }; -        instruction.operands[mmm] = mem_oper; -        instruction.operands[rrr] = OperandSpec::RegRRR; -        instruction.operand_count = 2; -    } else if operand_code == OperandCode::Ibs { +        instruction.operands[1] = mem_oper; +    } + +    if let Some((only_imm, immsz)) = operand_code.has_imm() {          instruction.imm = -            read_imm_signed(&mut bytes_iter, 1, length)? as u32; -        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()); +            read_imm_signed(&mut bytes_iter, 1 << (immsz * 2), length)? as u32; +        if only_imm { +            if immsz == 0 { +                instruction.operands[0] = OperandSpec::ImmI8; +            } else { +                instruction.operands[0] = OperandSpec::ImmI32;              } +            instruction.operand_count = 1; +            return Ok(()); +        } +    } + +    if operand_code.is_only_modrm_operands() { +        if !operand_code.has_reg_mem() { +            instruction.operands[0] = mem_oper; +            instruction.operands[1] = OperandSpec::RegRRR; +        }; +    } else { +//    match operand_code { +    match operand_code.special_case_handler_index() { +        0 => { +            // turns out xed cand capstone both permit nonzero rrr bits here. +            // if (modrm & 0b00111000) != 0 { +            //    instruction.opcode = Opcode::Invalid; +            //    return Err(DecodeError::InvalidOperand); +            //}              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(SizeCode::vd, instruction.prefixes) -                } -                _ => { -                    unsafe { unreachable_unchecked() } -                } -            }; -            // 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, opwidth); -            instruction.disp = imm; -            if instruction.prefixes.address_size() { -                instruction.operands[1] = OperandSpec::DispU16; -            } else { -                instruction.operands[1] = OperandSpec::DispU32; -            }; +        1 => { +            instruction.operands[0] = mem_oper; +            instruction.operands[1] = OperandSpec::ImmI8;              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(SizeCode::vd, 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 +        2 => { +            instruction.operands[0] = mem_oper; +            let numwidth = if instruction.prefixes.operand_size() { +                2              } else { -                OperandSpec::DispU16 +                4              }; -            instruction.modrm_rrr = -                RegSpec::gp_from_parts(0, opwidth); -            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 u32;              instruction.opcode = base_opcode_map((modrm >> 3) & 7); -            instruction.operands[1] = match opwidth { -                1 => OperandSpec::ImmI8, +            instruction.operands[1] = match numwidth {                  2 => OperandSpec::ImmI16,                  4 => OperandSpec::ImmI32,                  _ => unsafe { unreachable_unchecked() }              };              instruction.operand_count = 2;          }, -        OperandCode::ModRM_0xc4 => { -            let modrm = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; -            if modrm & 0b11000000 == 0b11000000 { -                // interpret the c4 as a vex prefix -                if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { -                    // prefixes and then vex is invalid! reject it. -                    instruction.opcode = Opcode::Invalid; -                    return Err(DecodeError::InvalidPrefixes); -                } else { -                    vex::three_byte_vex(&mut bytes_iter, modrm, instruction, *length)?; -                    *length = instruction.length; - -                    if decoder != &InstDecoder::default() { -                        decoder.revise_instruction(instruction)?; -                    } -                    return Ok(()); -                } -            } else { -                // LES -                instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { 2 } else { 4 }); -                instruction.operands[0] = OperandSpec::RegRRR; -                instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; +        3 => { // ModRM_0xc6_Eb_Ib +            if modrm == 0xf8 { +                instruction.opcode = Opcode::XABORT; +                instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u32; +                instruction.operands[0] = OperandSpec::ImmI8; +                instruction.operand_count = 1; +                return Ok(());              } -        }, -        OperandCode::ModRM_0xc5 => { -            let modrm = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; -            if (modrm & 0b1100_0000) == 0b1100_0000 { -                // interpret the c5 as a vex prefix -                if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { -                    // prefixes and then vex is invalid! reject it. -                    instruction.opcode = Opcode::Invalid; -                    return Err(DecodeError::InvalidPrefixes); -                } else { -                    vex::two_byte_vex(&mut bytes_iter, modrm, instruction, *length)?; -                    *length = instruction.length; - -                    if decoder != &InstDecoder::default() { -                        decoder.revise_instruction(instruction)?; -                    } -                    return Ok(()); -                } -            } else { -                // LDS -                instruction.modrm_rrr = RegSpec::gp_from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { 2 } else { 4 }); -                instruction.operands[0] = OperandSpec::RegRRR; -                instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; +            if (modrm & 0b00111000) != 0 { +                instruction.opcode = Opcode::Invalid; +                return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string());              } -        }, -        op @ OperandCode::ModRM_0xc6_Eb_Ib | -        op @ OperandCode::ModRM_0xc7_Ev_Iv => { + +            instruction.operands[0] = mem_oper; +            instruction.opcode = Opcode::MOV; +            instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u32; +            instruction.operands[1] = OperandSpec::ImmI8; +            instruction.operand_count = 2; +        } +        4 => { // ModRM_0xc7_Ev_Iv              if modrm == 0xf8 { -                if op == OperandCode::ModRM_0xc6_Eb_Ib { -                    instruction.opcode = Opcode::XABORT; -                    instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u32; -                    instruction.operands[0] = OperandSpec::ImmI8; -                    instruction.operand_count = 1; -                    return Ok(()); +                instruction.opcode = Opcode::XBEGIN; +                instruction.imm = if instruction.prefixes.operand_size() { +                    read_imm_signed(&mut bytes_iter, 2, length)? as i16 as i32 as u32                  } else { -                    instruction.opcode = Opcode::XBEGIN; -                    instruction.imm = if opwidth == 2 { -                        read_imm_signed(&mut bytes_iter, 2, length)? as i16 as i32 as u32 -                    } else { -                        read_imm_signed(&mut bytes_iter, 4, length)? as i32 as u32 -                    }; -                    instruction.operands[0] = OperandSpec::ImmI32; -                    instruction.operand_count = 1; -                    return Ok(()); -                } +                    read_imm_signed(&mut bytes_iter, 4, length)? as i32 as u32 +                }; +                instruction.operands[0] = OperandSpec::ImmI32; +                instruction.operand_count = 1; +                return Ok(());              }              if (modrm & 0b00111000) != 0 {                  instruction.opcode = Opcode::Invalid; @@ -5435,30 +5762,32 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              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 u32; -            instruction.operands[1] = match opwidth { -                1 => OperandSpec::ImmI8, -                2 => OperandSpec::ImmI16, -                4 => OperandSpec::ImmI32, -                _ => unsafe { unreachable_unchecked() } -            }; -            instruction.operand_count = 2; +            if instruction.prefixes.operand_size() { +                instruction.imm = read_imm_signed(&mut bytes_iter, 2, length)? as u32; +                instruction.operands[1] = OperandSpec::ImmI16; +            } else { +                instruction.imm = read_imm_signed(&mut bytes_iter, 4, length)? as u32; +                instruction.operands[1] = OperandSpec::ImmI32; +            }          }, -        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 => { +        op @ 5 | +        op @ 6 | +        op @ 7 | +        op @ 8 | +        op @ 9 | +        op @ 10 => {              instruction.operands[0] = mem_oper;              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); -            if let OperandCode::ModRM_0xd3_Ev_CL = op { +            if op == 10 { +                instruction.modrm_rrr = RegSpec::cl(); +                instruction.operands[1] = OperandSpec::RegRRR; +            } else if op == 9 {                  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 => { +                    5 | +                    6 => {                          *length += 1;                          read_num(&mut bytes_iter, 1)?                      } @@ -5472,8 +5801,17 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              }              instruction.operand_count = 2;          }, -        _op @ OperandCode::ModRM_0xf6 | -        _op @ OperandCode::ModRM_0xf7 => { +        op @ 11 | +        op @ 12 => { +            let opwidth = if op == 11 { +                1 +            } else { +                if instruction.prefixes.operand_size() { +                    2 +                } else { +                    4 +                } +            };              instruction.operands[0] = mem_oper;              instruction.operand_count = 1;              match (modrm >> 3) & 7 { @@ -5511,22 +5849,24 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,                  }              }          }, -        OperandCode::ModRM_0xfe_Eb => { +        13 => {              instruction.operands[0] = mem_oper; +            let r = (modrm >> 3) & 7; +            if r >= 2 { +                return Err(DecodeError::InvalidOpcode); +            }              instruction.opcode = [                  Opcode::INC,                  Opcode::DEC, -                Opcode::Invalid, -                Opcode::Invalid, -                Opcode::Invalid, -                Opcode::Invalid, -                Opcode::Invalid, -                Opcode::Invalid -            ][((modrm >> 3) & 7) as usize]; +            ][r as usize];              instruction.operand_count = 1;          } -        OperandCode::ModRM_0xff_Ev => { +        14 => {              instruction.operands[0] = mem_oper; +            let r = (modrm >> 3) & 7; +            if r == 7 { +                return Err(DecodeError::InvalidOpcode); +            }              let opcode = [                  Opcode::INC,                  Opcode::DEC, @@ -5535,8 +5875,7 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,                  Opcode::JMP,                  Opcode::JMPF,                  Opcode::PUSH, -                Opcode::Invalid -            ][((modrm >> 3) & 7) as usize]; +            ][r as usize];              if instruction.operands[0] == OperandSpec::RegMMM {                  if opcode == Opcode::CALL || opcode == Opcode::JMP {                      instruction.modrm_mmm.bank = RegisterBank::D; @@ -5547,92 +5886,48 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              instruction.opcode = opcode;              instruction.operand_count = 1;          } -        OperandCode::Gv_Eb => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +        15 => {              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, opwidth); +            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W) +            } else { +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) +            };              instruction.operand_count = 2;          }, -        OperandCode::Gv_Ew => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +        16 => {              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, opwidth); -            instruction.operand_count = 2; -        }, -        OperandCode::Ew_Gw => { -            let opwidth = 2; -            let modrm = read_modrm(&mut bytes_iter, length)?; - -//                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            instruction.operands[1] = instruction.operands[0]; -            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; -            instruction.modrm_rrr = -                RegSpec::gp_from_parts((modrm >> 3) & 7, opwidth); +            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W) +            } else { +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) +            };              instruction.operand_count = 2;          }, -        OperandCode::Ev => { +        18 => {              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, opwidth); -            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, RegisterBank::X); +        19 => { +            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.operands[0] = mem_oper;              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; -        }, -        OperandCode::G_U_xmm => { -            instruction.operands[1] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::X; -            if mem_oper != OperandSpec::RegMMM { -                return Err(DecodeError::InvalidOperand); +            if instruction.operands[0] == OperandSpec::RegMMM { +                // fix the register to XMM +                instruction.modrm_mmm.bank = RegisterBank::X;              } -            instruction.modrm_mmm.bank = RegisterBank::X; -            instruction.operand_count = 2;          }, -        op @ OperandCode::G_M_xmm | -        op @ OperandCode::G_E_xmm => { +        op @ 20 | +        op @ 21 => {              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 { +                if op == 20 {                      instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOperand);                  } else { @@ -5641,64 +5936,34 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,                  }              }          }, -        OperandCode::G_E_xmm_Ib => { +        22 => {              let modrm = read_modrm(&mut bytes_iter, length)?;              instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?;              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            instruction.operands[0] = OperandSpec::RegRRR; -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u8 as u32; -            *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 u32;              *length += 1; -            if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -            }              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, 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 u32; -            *length += 1; -            instruction.operands[2] = OperandSpec::ImmI8; -            instruction.operand_count = 3; -        } -        OperandCode::AL_Ibs => { +        23 => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_imm_signed(&mut bytes_iter, 1, length)? as u32;              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          } -        OperandCode::AX_Ivd => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = -                RegSpec::gp_from_parts(0, opwidth); +        24 => { +            let opwidth = if instruction.prefixes.operand_size() { +                instruction.modrm_rrr = +                    RegSpec::from_parts(0, RegisterBank::W); +                2 +            } else { +                instruction.modrm_rrr = +                    RegSpec::from_parts(0, RegisterBank::D); +                4 +            };              instruction.imm =                  read_imm_signed(&mut bytes_iter, opwidth, length)? as u32;              instruction.operands[1] = match opwidth { @@ -5708,8 +5973,12 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              };              instruction.operand_count = 2;          } -        OperandCode::Ivs => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +        25 => { +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              instruction.imm =                  read_imm_unsigned(&mut bytes_iter, opwidth, length)?;              instruction.operands[0] = match opwidth { @@ -5719,40 +5988,124 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              };              instruction.operand_count = 1;          }, -        OperandCode::ModRM_0x83_Ev_Ibs => { +        26 => {              instruction.operands[0] = mem_oper;              instruction.opcode = base_opcode_map((modrm >> 3) & 7); -            instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u32;              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          }, -        OperandCode::Jvds => { -            let offset = read_num(&mut bytes_iter, 4)?; -            *length += 4; -            instruction.imm = offset; +        27 => { +            instruction.imm = 3; +            instruction.operands[0] = OperandSpec::ImmU8;              instruction.operand_count = 1; -            instruction.operands[0] = OperandSpec::ImmI32;          } +        28 => { +            instruction.operands[0] = OperandSpec::Nothing; +            instruction.operand_count = 0; +            return Ok(()); +        }, +        29 => { +            instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; +            if instruction.operands[1] == OperandSpec::RegMMM { +                instruction.modrm_mmm.bank = RegisterBank::MM; +            } +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +        }, +        30 => { +            instruction.operands[0] = mem_oper; +            let r = (modrm >> 3) & 7; +            if r >= 1 { +                return Err(DecodeError::InvalidOpcode); +            } +            instruction.opcode = [ +                Opcode::POP, +            ][r as usize]; +            instruction.operand_count = 1; +        } +        _ => { +        let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; +            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_0xc4 => { +            let modrm = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; +            if modrm & 0b11000000 == 0b11000000 { +                // interpret the c4 as a vex prefix +                if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { +                    // prefixes and then vex is invalid! reject it. +                    instruction.opcode = Opcode::Invalid; +                    return Err(DecodeError::InvalidPrefixes); +                } else { +                    vex::three_byte_vex(&mut bytes_iter, modrm, instruction, *length)?; +                    *length = instruction.length; + +                    if decoder != &InstDecoder::default() { +                        decoder.revise_instruction(instruction)?; +                    } +                    return Ok(()); +                } +            } else { +                // LES +                instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); +                instruction.operands[0] = OperandSpec::RegRRR; +                instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; +            } +        }, +        OperandCode::ModRM_0xc5 => { +            let modrm = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; +            if (modrm & 0b1100_0000) == 0b1100_0000 { +                // interpret the c5 as a vex prefix +                if instruction.prefixes.lock() || instruction.prefixes.operand_size() || instruction.prefixes.rep() || instruction.prefixes.repnz() { +                    // prefixes and then vex is invalid! reject it. +                    instruction.opcode = Opcode::Invalid; +                    return Err(DecodeError::InvalidPrefixes); +                } else { +                    vex::two_byte_vex(&mut bytes_iter, modrm, instruction, *length)?; +                    *length = instruction.length; + +                    if decoder != &InstDecoder::default() { +                        decoder.revise_instruction(instruction)?; +                    } +                    return Ok(()); +                } +            } else { +                // LDS +                instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); +                instruction.operands[0] = OperandSpec::RegRRR; +                instruction.operands[1] = read_M(&mut bytes_iter, instruction, modrm, length)?; +            } +        }, +        OperandCode::G_U_xmm => { +            instruction.modrm_rrr.bank = RegisterBank::X; +            if mem_oper != OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.operand_count = 2; +        },          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 u32;              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3;          }          OperandCode::Gv_Ev_Iv => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            let numwidth = if opwidth == 8 { 4 } else { opwidth }; -            instruction.operands[0] = OperandSpec::RegRRR; -            instruction.operands[1] = mem_oper; +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              instruction.imm = -                read_imm_signed(&mut bytes_iter, numwidth, length)? as u32; +                read_imm_signed(&mut bytes_iter, opwidth, length)? as u32;              instruction.operands[2] = match opwidth {                  2 => OperandSpec::ImmI16,                  4 => OperandSpec::ImmI32, -                o => { unreachable!("impossible opwidth: {}", o); } -//                _ => unsafe { unreachable_unchecked() } +                _ => unsafe { unreachable_unchecked() }              };              instruction.operand_count = 3;          } @@ -5767,38 +6120,228 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,          OperandCode::Ev_Gv_CL => {              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.operands[2] = OperandSpec::CL; +            instruction.operands[2] = OperandSpec::RegVex; +            instruction.vex_reg = RegSpec::cl();              instruction.operand_count = 3;          } -        OperandCode::Nothing => { -            instruction.operand_count = 0; -        } -        _ => { -            unlikely_operands(decoder, bytes_iter, instruction, operand_code, mem_oper, length)?; +        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, RegisterBank::MM); +            if instruction.operands[1] == OperandSpec::RegMMM { +                instruction.modrm_mmm.bank = RegisterBank::D; +            } +            instruction.imm = +                read_num(&mut bytes_iter, 1)? as u8 as u32; +            *length += 1; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3;          } -    }; -    } +        OperandCode::G_E_mm => { +            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.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; +        }, +        OperandCode::Gv_Ew_LSL => { +            let modrm = read_modrm(&mut bytes_iter, length)?; +            if instruction.prefixes.operand_size() { +                instruction.modrm_rrr = +                    RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W); +            } else { +                instruction.modrm_rrr = +                    RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); +            }; -    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 { +            instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; +            // lsl is weird. the full register width is written, but only the low 16 bits are used. +            if instruction.operands[1] == OperandSpec::RegMMM { +                instruction.modrm_mmm.bank = RegisterBank::D; +            } +            instruction.operand_count = 2; +        }, +        OperandCode::Gd_Ev => { +            let modrm = read_modrm(&mut bytes_iter, length)?; + +//                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            }; +            instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); +            instruction.operand_count = 2; +        }, +        op @ OperandCode::AL_Ob | +        op @ OperandCode::AX_Ov => { +            instruction.modrm_rrr = match op { +                OperandCode::AL_Ob => RegSpec::al(), +                OperandCode::AX_Ov => { +                    if instruction.prefixes.operand_size() { +                        RegSpec::ax() +                    } else { +                        RegSpec::eax() +                    } +                } +                _ => { +                    unsafe { unreachable_unchecked() } +                } +            }; +            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; +            if instruction.prefixes.address_size() { +                instruction.operands[1] = OperandSpec::DispU16; +            } else { +                instruction.operands[1] = OperandSpec::DispU32; +            }; +            instruction.operand_count = 2; +        } +        op @ OperandCode::Ob_AL | +        op @ OperandCode::Ov_AX => { +            instruction.modrm_rrr = match op { +                OperandCode::Ob_AL => RegSpec::al(), +                OperandCode::Ov_AX => { +                    if instruction.prefixes.operand_size() { +                        RegSpec::ax() +                    } else { +                        RegSpec::eax() +                    } +                } +                _ => { +                    unsafe { unreachable_unchecked() } +                } +            }; +            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::DispU16 +            } else { +                OperandSpec::DispU32 +            }; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2; +        } +        OperandCode::I_1 => { +            instruction.imm = 1; +            instruction.operands[0] = OperandSpec::ImmU8; +            instruction.operand_count = 1; +        }          OperandCode::Unsupported => {              return Err(DecodeError::IncompleteDecoder);          } +        OperandCode::Iw_Ib => { +            instruction.disp = read_num(&mut bytes_iter, 2)?; +            instruction.imm = read_num(&mut bytes_iter, 1)?; +            instruction.operands[0] = OperandSpec::EnterFrameSize; +            instruction.operands[1] = OperandSpec::ImmU8; +            instruction.operand_count = 2; +            *length += 3; +        } +        OperandCode::Fw => { +            if instruction.prefixes.operand_size() { +                instruction.opcode = Opcode::IRET; +            } else { +                instruction.opcode = Opcode::IRETD; +            } +            instruction.operand_count = 0; +        } +        OperandCode::Md_Gd => { +            let opwidth = 4; +            let modrm = read_modrm(&mut bytes_iter, length)?; + +            instruction.operands[1] = instruction.operands[0]; +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; +            if instruction.operands[0] == OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); +            instruction.operand_count = 2; + +        } +        OperandCode::G_mm_U_mm => { +            instruction.modrm_rrr.bank = RegisterBank::MM; +            if mem_oper != OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.modrm_mmm.bank = RegisterBank::MM; +            instruction.modrm_mmm.num &= 0b111; +            instruction.modrm_rrr.num &= 0b111; +            instruction.operand_count = 2; +        }, +        OperandCode::E_G_d => { +            if instruction.prefixes.operand_size() { +                return Err(DecodeError::InvalidOpcode); +            } + +            let modrm = read_modrm(&mut bytes_iter, length)?; + +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); +            instruction.operand_count = 2; +        } +        OperandCode::G_E_d => { +            if instruction.prefixes.operand_size() { +                return Err(DecodeError::InvalidOpcode); +            } + +            let modrm = read_modrm(&mut bytes_iter, length)?; + +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); +            instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            instruction.operand_count = 2; +        } +        OperandCode::G_Md_mm => { +            instruction.operands[1] = instruction.operands[0]; +            instruction.operands[0] = mem_oper; +            instruction.modrm_rrr.bank = RegisterBank::MM; +            if mem_oper == OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.modrm_rrr.num &= 0b111; +            instruction.operand_count = 2; +        },          OperandCode::MOVQ_f30f => {              instruction.operand_count = 2;              let modrm = read_modrm(&mut bytes_iter, length)?;              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?;          }          OperandCode::ModRM_0x0f0d => {              let modrm = read_modrm(&mut bytes_iter, length)?;              let r = (modrm >> 3) & 0b111; -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              match r {                  1 => { @@ -5820,7 +6363,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              let operands = match high {                  0 => {                      // PqQq -                    OperandCode::G_E_mm +                    if low != 0x0f { +                        OperandCode::G_E_mm +                    } else { +                        // PALIGNR +                        OperandCode::G_E_mm_Ib +                    }                  },                  1 => {                      // PqQq @@ -5846,6 +6394,25 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  }              };              instruction.opcode = match opcode { +                0x00 => Opcode::PSHUFB, +                0x01 => Opcode::PHADDW, +                0x02 => Opcode::PHADDD, +                0x03 => Opcode::PHADDSW, +                0x04 => Opcode::PMADDUBSW, +                0x05 => Opcode::PHSUBW, +                0x06 => Opcode::PHSUBD, +                0x07 => Opcode::PHSUBSW, +                0x08 => Opcode::PSIGNB, +                0x09 => Opcode::PSIGNW, +                0x0a => Opcode::PSIGND, +                0x0b => Opcode::PMULHRSW, + +                0x0f => Opcode::PALIGNR, + +                0x1c => Opcode::PABSB, +                0x1d => Opcode::PABSW, +                0x1e => Opcode::PABSD, +                  0xc8 => Opcode::SHA1NEXTE,                  0xc9 => Opcode::SHA1MSG1,                  0xca => Opcode::SHA1MSG2, @@ -5932,7 +6499,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.opcode = opcode;              instruction.operand_count = 1; -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?;          },          OperandCode::ModRM_0x0f71 => { @@ -6030,7 +6601,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = read_E_xmm(&mut bytes_iter, instruction, modrm, length)?;              instruction.operand_count = 2;          } @@ -6045,10 +6615,26 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, 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_0xf20f38 => { +            let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?; +            match op { +                0xf0 => { +                    instruction.opcode = Opcode::CRC32; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::Gv_Eb, length); +                } +                0xf1 => { +                    instruction.opcode = Opcode::CRC32; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::Gd_Ev, length); +                } +                _ => { +                    instruction.opcode = Opcode::Invalid; +                    return Err(DecodeError::InvalidOpcode); +                } +            }; +        }          OperandCode::ModRM_0xf30f38 => {              let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?;              match op { @@ -6065,6 +6651,64 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::ModRM_0x660f38 => {              let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?;              match op { +                0x00 => { instruction.opcode = Opcode::PSHUFB; } +                0x01 => { instruction.opcode = Opcode::PHADDW; } +                0x02 => { instruction.opcode = Opcode::PHADDD; } +                0x03 => { instruction.opcode = Opcode::PHADDSW; } +                0x04 => { instruction.opcode = Opcode::PMADDUBSW; } +                0x05 => { instruction.opcode = Opcode::PHSUBW; } +                0x06 => { instruction.opcode = Opcode::PHSUBD; } +                0x07 => { instruction.opcode = Opcode::PHSUBSW; } +                0x08 => { instruction.opcode = Opcode::PSIGNB; } +                0x09 => { instruction.opcode = Opcode::PSIGNW; } +                0x0a => { instruction.opcode = Opcode::PSIGND; } +                0x0b => { instruction.opcode = Opcode::PMULHRSW; } +                0x0c => { instruction.opcode = Opcode::BLENDPS; } +                0x0d => { instruction.opcode = Opcode::BLENDPD; } + +                0x10 => { instruction.opcode = Opcode::PBLENDVB; } + +                0x14 => { instruction.opcode = Opcode::BLENDVPS; } +                0x15 => { instruction.opcode = Opcode::BLENDVPD; } + +                0x17 => { instruction.opcode = Opcode::PTEST; } + +                0x1c => { instruction.opcode = Opcode::PABSB; } +                0x1d => { instruction.opcode = Opcode::PABSW; } +                0x1e => { instruction.opcode = Opcode::PABSD; } + +                0x20 => { instruction.opcode = Opcode::PMOVSXBW; } +                0x21 => { instruction.opcode = Opcode::PMOVSXBD; } +                0x22 => { instruction.opcode = Opcode::PMOVSXBQ; } +                0x23 => { instruction.opcode = Opcode::PMOVSXWD; } +                0x24 => { instruction.opcode = Opcode::PMOVSXWQ; } +                0x25 => { instruction.opcode = Opcode::PMOVSXDQ; } + +                0x28 => { instruction.opcode = Opcode::PMULDQ; } +                0x29 => { instruction.opcode = Opcode::PCMPEQQ; } +                0x2a => { instruction.opcode = Opcode::MOVNTDQA; } +                0x2b => { instruction.opcode = Opcode::PACKUSDW; } + +                0x30 => { instruction.opcode = Opcode::PMOVZXBW; } +                0x31 => { instruction.opcode = Opcode::PMOVZXBD; } +                0x32 => { instruction.opcode = Opcode::PMOVZXBQ; } +                0x33 => { instruction.opcode = Opcode::PMOVZXWD; } +                0x34 => { instruction.opcode = Opcode::PMOVZXWQ; } +                0x35 => { instruction.opcode = Opcode::PMOVZXDQ; } + +                0x37 => { instruction.opcode = Opcode::PCMPGTQ; } +                0x38 => { instruction.opcode = Opcode::PMINSB; } +                0x39 => { instruction.opcode = Opcode::PMINSD; } +                0x3a => { instruction.opcode = Opcode::PMINUW; } +                0x3b => { instruction.opcode = Opcode::PMINUD; } +                0x3c => { instruction.opcode = Opcode::PMAXSB; } +                0x3d => { instruction.opcode = Opcode::PMAXSD; } +                0x3e => { instruction.opcode = Opcode::PMAXUW; } +                0x3f => { instruction.opcode = Opcode::PMAXUD; } + +                0x40 => { instruction.opcode = Opcode::PMULLD; } +                0x41 => { instruction.opcode = Opcode::PHMINPOSUW; } +                  0xdb => { instruction.opcode = Opcode::AESIMC; }                  0xdc => { instruction.opcode = Opcode::AESENC; }                  0xdd => { instruction.opcode = Opcode::AESENCLAST; } @@ -6085,13 +6729,93 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  RegSpec::from_parts((modrm >> 3) & 7, 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 { +                0x08 => { +                    instruction.opcode = Opcode::ROUNDPS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x09 => { +                    instruction.opcode = Opcode::ROUNDPD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x0a => { +                    instruction.opcode = Opcode::ROUNDSS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x0b => { +                    instruction.opcode = Opcode::ROUNDSD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x0e => { +                    instruction.opcode = Opcode::PBLENDW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x0f => { +                    instruction.opcode = Opcode::PALIGNR; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x14 => { +                    instruction.opcode = Opcode::PEXTRB; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x15 => { +                    instruction.opcode = Opcode::PEXTRW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x16 => { +                    instruction.opcode = Opcode::PEXTRD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x17 => { +                    instruction.opcode = Opcode::EXTRACTPS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x20 => { +                    instruction.opcode = Opcode::PINSRB; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x21 => { +                    instruction.opcode = Opcode::INSERTPS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x22 => { +                    instruction.opcode = Opcode::PINSRD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x40 => { +                    instruction.opcode = Opcode::DPPS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x41 => { +                    instruction.opcode = Opcode::DPPD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x42 => { +                    instruction.opcode = Opcode::MPSADBW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } + +                0x60 => { +                    instruction.opcode = Opcode::PCMPESTRM; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x61 => { +                    instruction.opcode = Opcode::PCMPESTRI; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x62 => { +                    instruction.opcode = Opcode::PCMPISTRM; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x63 => { +                    instruction.opcode = Opcode::PCMPISTRI; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                }                  0xcc => {                      instruction.opcode = Opcode::SHA1RNDS4; @@ -6100,7 +6824,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                          RegSpec::from_parts((modrm >> 3) & 7, 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)?; @@ -6116,7 +6839,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                          RegSpec::from_parts((modrm >> 3) & 7, 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)?; @@ -6220,7 +6942,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[1] = OperandSpec::ImmU8;          },          OperandCode::ModRM_0x660fc7 => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              let modrm = read_modrm(&mut bytes_iter, length)?;              let r = (modrm >> 3) & 7; @@ -6318,7 +7044,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          }          OperandCode::ModRM_0xf30fc7 => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              let modrm = read_modrm(&mut bytes_iter, length)?;              let r = (modrm >> 3) & 7; @@ -6347,7 +7077,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          },          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 { @@ -6355,7 +7084,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          }          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 { @@ -6390,25 +7118,9 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  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 { -                instruction.modrm_mmm.bank = RegisterBank::D; -            } -        },          OperandCode::G_xmm_Ed_Ib => { -            instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::ImmU8; +            instruction.operand_count = 3;              instruction.imm =                  read_num(&mut bytes_iter, 1)?;              *length += 1; @@ -6418,14 +7130,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          },          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_mm_E_xmm => { -            instruction.operands[1] = mem_oper;              instruction.modrm_rrr.bank = RegisterBank::MM;              instruction.modrm_rrr.num &= 0b111;              if mem_oper == OperandSpec::RegMMM { @@ -6434,7 +7144,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          },          op @ OperandCode::G_xmm_U_mm |          op @ 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; @@ -6445,8 +7154,21 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  }              }          }, +        OperandCode::Rv_Gmm_Ib => { +            instruction.operands[2] = OperandSpec::ImmU8; +            instruction.operand_count = 3; +            instruction.imm = +                read_num(&mut bytes_iter, 1)?; +            *length += 1; +            instruction.modrm_rrr.bank = RegisterBank::D; +            if mem_oper == OperandSpec::RegMMM { +                instruction.modrm_mmm.bank = RegisterBank::MM; +                instruction.modrm_mmm.num &= 0b111; +            } else { +                return Err(DecodeError::InvalidOperand); +            } +        }          OperandCode::U_mm_G_xmm => { -            instruction.operands[1] = mem_oper;              instruction.modrm_mmm.bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM {                  instruction.modrm_rrr.bank = RegisterBank::MM; @@ -6457,35 +7179,39 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          }          // sure hope these aren't backwards huh          OperandCode::AL_Xb => { -            instruction.operands[0] = OperandSpec::AL; -            instruction.operands[1] = OperandSpec::Deref_esi; +            instruction.modrm_rrr = RegSpec::al(); +            instruction.modrm_mmm = RegSpec::esi(); +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = OperandSpec::Deref; +            instruction.operand_count = 2;          }          // TODO: two memory operands! this is wrong!!!          OperandCode::Yb_Xb => {              instruction.operands[0] = OperandSpec::Deref_edi;              instruction.operands[1] = OperandSpec::Deref_esi; +            instruction.operand_count = 2;          }          OperandCode::Yb_AL => { -            instruction.operands[0] = OperandSpec::Deref_edi; -            instruction.operands[1] = OperandSpec::AL; +            instruction.modrm_rrr = RegSpec::al(); +            instruction.modrm_mmm = RegSpec::esi(); +            instruction.operands[0] = OperandSpec::Deref; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2;          }          OperandCode::AX_Xv => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = match opwidth { -                2 => RegSpec::ax(), -                4 => RegSpec::eax(), -                _ => { unreachable!(); } +            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +                RegSpec::ax() +            } else { +                RegSpec::eax()              };              instruction.modrm_mmm = RegSpec::esi(); -            instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;          }          OperandCode::Yv_AX => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = match opwidth { -                2 => RegSpec::ax(), -                4 => RegSpec::eax(), -                _ => { unreachable!(); } +            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +                RegSpec::ax() +            } else { +                RegSpec::eax()              };              instruction.modrm_mmm = RegSpec::edi();              instruction.operands[0] = OperandSpec::Deref; @@ -6522,6 +7248,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }              let rrr = instruction.modrm_rrr.num & 0b111;              instruction.operands[0] = mem_oper; +            instruction.operand_count = 1;              instruction.opcode = match rrr {                  0 => Opcode::PREFETCHNTA,                  1 => Opcode::PREFETCH0, @@ -6531,7 +7258,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              };          }          OperandCode::Gd_U_xmm => { -            instruction.operands[1] = mem_oper;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand); @@ -6540,7 +7266,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.modrm_mmm.bank = RegisterBank::X;          }          OperandCode::Gv_E_xmm => { -            instruction.operands[1] = mem_oper;              if instruction.operands[1] == OperandSpec::RegMMM {                  instruction.modrm_mmm.bank = RegisterBank::X;              } @@ -6554,6 +7279,15 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }              instruction.modrm_rrr.bank = RegisterBank::X;          } +        OperandCode::Ew_Gw => { +            let modrm = read_modrm(&mut bytes_iter, length)?; + +            instruction.modrm_rrr = +                RegSpec { bank: RegisterBank::W, num: (modrm >> 3) & 7 }; +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2; +        },          OperandCode::Ew_Sw => {              let opwidth = 2;              let modrm = read_modrm(&mut bytes_iter, length)?; @@ -6602,24 +7336,24 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          },          OperandCode::CVT_AA => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.opcode = match opwidth { -                2 => { Opcode::CBW }, -                4 => { Opcode::CWDE }, -                _ => { unreachable!("invalid operation width"); }, -            } +            instruction.operands[0] = OperandSpec::Nothing; +            instruction.operand_count = 0; +            instruction.opcode = if !instruction.prefixes.operand_size() { +                Opcode::CWDE +            } else { +                Opcode::CBW +            };          }          OperandCode::CVT_DA => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.opcode = match opwidth { -                2 => { Opcode::CWD }, -                4 => { Opcode::CDQ }, -                _ => { unreachable!("invalid operation width"); }, -            } +            instruction.operands[0] = OperandSpec::Nothing; +            instruction.operand_count = 0; +            instruction.opcode = if !instruction.prefixes.operand_size() { +                Opcode::CDQ +            } else { +                Opcode::CWD +            };          }          OperandCode::Ib => { -            instruction.imm = -                read_imm_unsigned(&mut bytes_iter, 1, length)?;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operand_count = 1;          } @@ -6647,10 +7381,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  instruction.opcode = Opcode::VERW;              } else if r == 6 {                  instruction.opcode = Opcode::JMPE; +                instruction.operands[0] = OperandSpec::Nothing;                  instruction.operand_count = 0;                  return Ok(());              } else if r == 7 {                  instruction.opcode = Opcode::Invalid; +                instruction.operands[0] = OperandSpec::Nothing;                  instruction.operand_count = 0;                  return Err(DecodeError::InvalidOperand);              } else { @@ -6659,13 +7395,18 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?;          }          OperandCode::ModRM_0x0f01 => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              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.operands[0] = OperandSpec::Nothing;                      instruction.operand_count = 0;                      match m {                          0b000 => { @@ -6697,6 +7438,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  let mod_bits = modrm >> 6;                  let m = modrm & 7;                  if mod_bits == 0b11 { +                    instruction.operands[0] = OperandSpec::Nothing;                      instruction.operand_count = 0;                      match m {                          0b000 => { @@ -6728,6 +7470,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  let mod_bits = modrm >> 6;                  let m = modrm & 7;                  if mod_bits == 0b11 { +                    instruction.operands[0] = OperandSpec::Nothing;                      instruction.operand_count = 0;                      match m {                          0b000 => { @@ -6771,6 +7514,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                          },                          0b001 => {                              instruction.opcode = Opcode::VMMCALL; +                            instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                          },                          0b010 => { @@ -6787,10 +7531,12 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                          },                          0b100 => {                              instruction.opcode = Opcode::STGI; +                            instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                          },                          0b101 => {                              instruction.opcode = Opcode::CLGI; +                            instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                          },                          0b110 => { @@ -6809,6 +7555,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                          },                          _ => {                              instruction.opcode = Opcode::Invalid; +                            instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                              return Err(DecodeError::InvalidOperand);                          } @@ -6820,7 +7567,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  }              } else if r == 4 {                  // TODO: this permits storing only to word-size registers -                // spec suggets this might do something different for f.ex edi? +                // 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)?; @@ -6829,14 +7576,17 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  match m {                      0b110 => {                          instruction.opcode = Opcode::RDPKRU; -                        instruction.operand_count = 1; +                        instruction.operands[0] = OperandSpec::Nothing; +                        instruction.operand_count = 0;                      }                      0b111 => {                          instruction.opcode = Opcode::WRPKRU; -                        instruction.operand_count = 1; +                        instruction.operands[0] = OperandSpec::Nothing; +                        instruction.operand_count = 0;                      }                      _ => {                          instruction.opcode = Opcode::Invalid; +                        instruction.operands[0] = OperandSpec::Nothing;                          instruction.operand_count = 0;                          return Err(DecodeError::InvalidOpcode);                      } @@ -6851,9 +7601,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  if mod_bits == 0b11 {                      if m == 0 {                          instruction.opcode = Opcode::SWAPGS; +                        instruction.operands[0] = OperandSpec::Nothing;                          instruction.operand_count = 0;                      } else if m == 1 {                          instruction.opcode = Opcode::RDTSCP; +                        instruction.operands[0] = OperandSpec::Nothing;                          instruction.operand_count = 0;                      } else {                          instruction.opcode = Opcode::Invalid; @@ -6875,6 +7627,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              // all the 0b11 instructions are err or no-operands              if mod_bits == 0b11 { +                instruction.operands[0] = OperandSpec::Nothing;                  instruction.operand_count = 0;                  let m = modrm & 7;                  match r { @@ -6933,7 +7686,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          }          OperandCode::ModRM_0x0fba => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); +            let opwidth = if instruction.prefixes.operand_size() { +                2 +            } else { +                4 +            };              let modrm = read_modrm(&mut bytes_iter, length)?;              let r = (modrm >> 3) & 7;              match r { @@ -6960,7 +7717,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?; -            instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as i8 as i32 as u32; +            instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u32;              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          } @@ -7004,31 +7761,19 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          } -        OperandCode::I_3 => { -            instruction.imm = 3; -            instruction.operands[0] = OperandSpec::ImmU8; -            instruction.operand_count = 1; -        }          OperandCode::AL_Ib => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_num(&mut bytes_iter, 1)?; -            *length += 1;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8;              instruction.operand_count = 2;          }          OperandCode::AX_Ib => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.modrm_rrr = if !instruction.prefixes.operand_size() {                 RegSpec::eax()              } else {                 RegSpec::ax()              }; -            instruction.imm = -                read_num(&mut bytes_iter, 1)?; -            *length += 1;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8;              instruction.operand_count = 2; @@ -7036,30 +7781,22 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::Ib_AL => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_num(&mut bytes_iter, 1)?; -            *length += 1;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::Ib_AX => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.modrm_rrr = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax()              }; -            instruction.imm = -                read_num(&mut bytes_iter, 1)?; -            *length += 1;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::AX_DX => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.modrm_rrr = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax() @@ -7077,8 +7814,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operand_count = 2;          }          OperandCode::DX_AX => { -            let opwidth = imm_width_from_prefixes(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.modrm_rrr = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax() @@ -7095,16 +7831,470 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          } +        OperandCode::Yb_DX => { +            instruction.modrm_rrr = RegSpec::dl(); +            instruction.modrm_mmm = RegSpec::edi(); +            instruction.operands[0] = OperandSpec::Deref; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2; +        } +        OperandCode::Yv_DX => { +            instruction.modrm_rrr = RegSpec::dx(); +            instruction.modrm_mmm = RegSpec::edi(); +            instruction.operands[0] = OperandSpec::Deref; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2; +        } +        OperandCode::DX_Xb => { +            instruction.modrm_rrr = RegSpec::dl(); +            instruction.modrm_mmm = RegSpec::esi(); +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = OperandSpec::Deref; +            instruction.operand_count = 2; +        } +        OperandCode::AH => { +            instruction.operands[0] = OperandSpec::Nothing; +            instruction.operand_count = 0; +        } +        OperandCode::DX_Xv => { +            instruction.modrm_rrr = RegSpec::dx(); +            instruction.modrm_mmm = RegSpec::esi(); +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = OperandSpec::Deref; +            instruction.operand_count = 2; +        } +        OperandCode::x87_d8 | +        OperandCode::x87_d9 | +        OperandCode::x87_da | +        OperandCode::x87_db | +        OperandCode::x87_dc | +        OperandCode::x87_dd | +        OperandCode::x87_de | +        OperandCode::x87_df => { +            return decode_x87(decoder, bytes_iter, instruction, operand_code, length); +        }          _ => { +            // TODO: this should be unreachable - safe to panic now? +            // can't simply delete this arm because the non-unlikely operands are handled outside +            // here, and some operands are entirely decoded before reaching match in the first +            // place. +            // perhaps fully-decoded operands could be a return here? they would be jump table +            // entries anyway, so no extra space for the dead arms. +            instruction.operands[0] = OperandSpec::Nothing;              instruction.operand_count = 0;              instruction.opcode = Opcode::Invalid; -//            return Err(()); // Err(format!("unsupported operand code: {:?}", operand_code));              return Err(DecodeError::InvalidOperand);          }      };      Ok(())  } +fn decode_x87<T: Iterator<Item=u8>>(_decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode, length: &mut u8) -> Result<(), DecodeError> { +    #[allow(non_camel_case_types)] +    enum OperandCodeX87 { +        Est, +        St_Est, +        St_Ew, +        St_Md, +        Md, +        Ew, +        Est_St, +        Ed_St, +        Md_St, +        Ex87S, +        Nothing, +    } + +    // every x87 instruction is conditional on rrr bits +    let modrm = read_modrm(&mut bytes_iter, length)?; +    let r = (modrm >> 3) & 0b111; + +    let (opcode, x87_operands) = match operand_code { +        OperandCode::x87_d8 => { +            match r { +                0 => (Opcode::FADD, OperandCodeX87::St_Est), +                1 => (Opcode::FMUL, OperandCodeX87::St_Est), +                2 => (Opcode::FCOM, OperandCodeX87::St_Est), +                3 => (Opcode::FCOMP, OperandCodeX87::St_Est), +                4 => (Opcode::FSUB, OperandCodeX87::St_Est), +                5 => (Opcode::FSUBR, OperandCodeX87::St_Est), +                6 => (Opcode::FDIV, OperandCodeX87::St_Est), +                7 => (Opcode::FDIVR, OperandCodeX87::St_Est), +                _ => { unreachable!("impossible r"); } +            } +        } +        OperandCode::x87_d9 => { +            match r { +                0 => (Opcode::FLD, OperandCodeX87::St_Est), +                1 => { +                    if modrm >= 0xc0 { +                        (Opcode::FXCH, OperandCodeX87::St_Est) +                    } else { +                        return Err(DecodeError::InvalidOpcode); +                    } +                }, +                2 => { +                    if modrm >= 0xc0 { +                        if modrm == 0xd0 { +                            (Opcode::FNOP, OperandCodeX87::Nothing) +                        } else { +                            return Err(DecodeError::InvalidOpcode); +                        } +                    } else { +                        (Opcode::FST, OperandCodeX87::Ed_St) +                    } +                } +                3 => { +                    if modrm >= 0xc0 { +                        (Opcode::FSTPNCE, OperandCodeX87::Est_St) +                    } else { +                        (Opcode::FSTP, OperandCodeX87::Est_St) +                    } +                }, +                4 => { +                    if modrm >= 0xc0 { +                        match modrm { +                            0xe0 => (Opcode::FCHS, OperandCodeX87::Nothing), +                            0xe1 => (Opcode::FABS, OperandCodeX87::Nothing), +                            0xe2 => { return Err(DecodeError::InvalidOpcode); }, +                            0xe3 => { return Err(DecodeError::InvalidOpcode); }, +                            0xe4 => (Opcode::FTST, OperandCodeX87::Nothing), +                            0xe5 => (Opcode::FXAM, OperandCodeX87::Nothing), +                            0xe6 => { return Err(DecodeError::InvalidOpcode); }, +                            0xe7 => { return Err(DecodeError::InvalidOpcode); }, +                            _ => { unreachable!("invalid modrm"); } +                        } +                    } else { +                        (Opcode::FLDENV, OperandCodeX87::Ex87S) // x87 state +                    } +                }, +                5 => { +                    if modrm >= 0xc0 { +                        match modrm { +                            0xe8 => (Opcode::FLD1, OperandCodeX87::Nothing), +                            0xe9 => (Opcode::FLDL2T, OperandCodeX87::Nothing), +                            0xea => (Opcode::FLDL2E, OperandCodeX87::Nothing), +                            0xeb => (Opcode::FLDPI, OperandCodeX87::Nothing), +                            0xec => (Opcode::FLDLG2, OperandCodeX87::Nothing), +                            0xed => (Opcode::FLDLN2, OperandCodeX87::Nothing), +                            0xee => (Opcode::FLDZ, OperandCodeX87::Nothing), +                            0xef => (Opcode::Invalid, OperandCodeX87::Nothing), +                            _ => { unreachable!("invalid modrm"); } +                        } +                    } else { +                        (Opcode::FLDCW, OperandCodeX87::Ew) +                    } +                } +                6 => { +                    if modrm >= 0xc0 { +                        match modrm { +                            0xf0 => (Opcode::F2XM1, OperandCodeX87::Nothing), +                            0xf1 => (Opcode::FYL2X, OperandCodeX87::Nothing), +                            0xf2 => (Opcode::FPTAN, OperandCodeX87::Nothing), +                            0xf3 => (Opcode::FPATAN, OperandCodeX87::Nothing), +                            0xf4 => (Opcode::FXTRACT, OperandCodeX87::Nothing), +                            0xf5 => (Opcode::FPREM1, OperandCodeX87::Nothing), +                            0xf6 => (Opcode::FDECSTP, OperandCodeX87::Nothing), +                            0xf7 => (Opcode::FINCSTP, OperandCodeX87::Nothing), +                            _ => { unreachable!("invalid modrm"); } +                        } +                    } else { +                        (Opcode::FNSTENV, OperandCodeX87::Ex87S) // x87 state +                    } +                } +                7 => { +                    if modrm >= 0xc0 { +                        match modrm { +                            0xf8 => (Opcode::FPREM, OperandCodeX87::Nothing), +                            0xf9 => (Opcode::FYL2XP1, OperandCodeX87::Nothing), +                            0xfa => (Opcode::FSQRT, OperandCodeX87::Nothing), +                            0xfb => (Opcode::FSINCOS, OperandCodeX87::Nothing), +                            0xfc => (Opcode::FRNDINT, OperandCodeX87::Nothing), +                            0xfd => (Opcode::FSCALE, OperandCodeX87::Nothing), +                            0xfe => (Opcode::FSIN, OperandCodeX87::Nothing), +                            0xff => (Opcode::FCOS, OperandCodeX87::Nothing), +                            _ => { unreachable!("invalid modrm"); } +                        } +                    } else { +                        (Opcode::FNSTCW, OperandCodeX87::Ew) +                    } +                } +                _ => { unreachable!("impossible r"); } +            } +        } +        OperandCode::x87_da => { +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FCMOVB, OperandCodeX87::St_Est), +                    1 => (Opcode::FCMOVE, OperandCodeX87::St_Est), +                    2 => (Opcode::FCMOVBE, OperandCodeX87::St_Est), +                    3 => (Opcode::FCMOVU, OperandCodeX87::St_Est), +                    _ => { +                        if modrm == 0xe9 { +                            (Opcode::FUCOMPP, OperandCodeX87::Nothing) +                        } else { +                            return Err(DecodeError::InvalidOpcode); +                        } +                    } +                } +            } else { +                match r { +                    0 => (Opcode::FIADD, OperandCodeX87::St_Md), // 0xd9d0 -> fnop +                    1 => (Opcode::FIMUL, OperandCodeX87::St_Md), +                    2 => (Opcode::FICOM, OperandCodeX87::St_Md), // FCMOVE +                    3 => (Opcode::FICOMP, OperandCodeX87::St_Md), // FCMOVBE +                    4 => (Opcode::FISUB, OperandCodeX87::St_Md), +                    5 => (Opcode::FISUBR, OperandCodeX87::St_Md), // FUCOMPP +                    6 => (Opcode::FIDIV, OperandCodeX87::St_Md), +                    7 => (Opcode::FIDIVR, OperandCodeX87::St_Md), +                    _ => { unreachable!("impossible r"); } +                } +            } +        } +        OperandCode::x87_db => { +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FCMOVNB, OperandCodeX87::St_Est), +                    1 => (Opcode::FCMOVNE, OperandCodeX87::St_Est), +                    2 => (Opcode::FCMOVNBE, OperandCodeX87::St_Est), +                    3 => (Opcode::FCMOVNU, OperandCodeX87::St_Est), +                    4 => { +                        match modrm { +                            0xe0 => (Opcode::FENI8087_NOP, OperandCodeX87::Nothing), +                            0xe1 => (Opcode::FDISI8087_NOP, OperandCodeX87::Nothing), +                            0xe2 => (Opcode::FNCLEX, OperandCodeX87::Nothing), +                            0xe3 => (Opcode::FNINIT, OperandCodeX87::Nothing), +                            0xe4 => (Opcode::FSETPM287_NOP, OperandCodeX87::Nothing), +                            _ => { +                                return Err(DecodeError::InvalidOpcode); +                            } +                        } +                    } +                    5 => (Opcode::FUCOMI, OperandCodeX87::St_Est), +                    6 => (Opcode::FCOMI, OperandCodeX87::St_Est), +                    _ => { +                        return Err(DecodeError::InvalidOpcode); +                    } +                } +            } else { +                match r { +                    0 => (Opcode::FILD, OperandCodeX87::St_Md), +                    1 => (Opcode::FISTTP, OperandCodeX87::Md_St), +                    2 => (Opcode::FIST, OperandCodeX87::Md_St), +                    3 => (Opcode::FISTP, OperandCodeX87::Md_St), +                    5 => (Opcode::FLD, OperandCodeX87::St_Md), // 80bit +                    7 => (Opcode::FSTP, OperandCodeX87::Md_St), // 80bit +                    _ => { +                        return Err(DecodeError::InvalidOpcode); +                    } +                } +            } + +        } +        OperandCode::x87_dc => { +            // mod=11 swaps operand order for some instructions +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FADD, OperandCodeX87::Est_St), +                    1 => (Opcode::FMUL, OperandCodeX87::Est_St), +                    2 => (Opcode::FCOM, OperandCodeX87::St_Est), +                    3 => (Opcode::FCOMP, OperandCodeX87::St_Est), +                    4 => (Opcode::FSUBR, OperandCodeX87::Est_St), +                    5 => (Opcode::FSUB, OperandCodeX87::Est_St), +                    6 => (Opcode::FDIVR, OperandCodeX87::Est_St), +                    7 => (Opcode::FDIV, OperandCodeX87::Est_St), +                    _ => { unreachable!("impossible r"); } +                } +            } else { +                match r { +                    0 => (Opcode::FADD, OperandCodeX87::St_Est), +                    1 => (Opcode::FMUL, OperandCodeX87::St_Est), +                    2 => (Opcode::FCOM, OperandCodeX87::St_Est), +                    3 => (Opcode::FCOMP, OperandCodeX87::St_Est), +                    4 => (Opcode::FSUB, OperandCodeX87::St_Est), +                    5 => (Opcode::FSUBR, OperandCodeX87::St_Est), +                    6 => (Opcode::FDIV, OperandCodeX87::St_Est), +                    7 => (Opcode::FDIVR, OperandCodeX87::St_Est), +                    _ => { unreachable!("impossible r"); } +                } +            } +        } +        OperandCode::x87_dd => { +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FFREE, OperandCodeX87::Est), +                    1 => (Opcode::FXCH, OperandCodeX87::St_Est), +                    2 => (Opcode::FST, OperandCodeX87::Est_St), +                    3 => (Opcode::FSTP, OperandCodeX87::Est_St), +                    4 => (Opcode::FUCOM, OperandCodeX87::St_Est), +                    5 => (Opcode::FUCOMP, OperandCodeX87::St_Est), +                    6 => (Opcode::Invalid, OperandCodeX87::Nothing), +                    7 => (Opcode::Invalid, OperandCodeX87::Nothing), +                    _ => { unreachable!("impossible r"); } +                } +            } else { +                match r { +                    0 => (Opcode::FLD, OperandCodeX87::St_Est), +                    1 => (Opcode::FISTTP, OperandCodeX87::Est_St), +                    2 => (Opcode::FST, OperandCodeX87::Est_St), +                    3 => (Opcode::FSTP, OperandCodeX87::Est_St), +                    4 => (Opcode::FRSTOR, OperandCodeX87::Md), // TODO: m94/108byte +                    5 => (Opcode::Invalid, OperandCodeX87::Nothing), +                    6 => (Opcode::FNSAVE, OperandCodeX87::Est), +                    7 => (Opcode::FNSTSW, OperandCodeX87::Ew), +                    _ => { unreachable!("impossible r"); } +                } +            } +        } +        OperandCode::x87_de => { +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FADDP, OperandCodeX87::Est_St), +                    1 => (Opcode::FMULP, OperandCodeX87::Est_St), +                    // undocumented in intel manual, argument order inferred from +                    // by xed and capstone. TODO: check amd manual. +                    2 => (Opcode::FCOMP, OperandCodeX87::St_Est), +                    3 => { +                        if modrm == 0xd9 { +                            (Opcode::FCOMPP, OperandCodeX87::Nothing) +                        } else { +                            return Err(DecodeError::InvalidOperand); +                        } +                    }, +                    4 => (Opcode::FSUBRP, OperandCodeX87::Est_St), +                    5 => (Opcode::FSUBP, OperandCodeX87::Est_St), +                    6 => (Opcode::FDIVRP, OperandCodeX87::Est_St), +                    7 => (Opcode::FDIVP, OperandCodeX87::Est_St), +                    _ => { unreachable!("impossible r"); } +                } +            } else { +                match r { +                    0 => (Opcode::FIADD, OperandCodeX87::St_Ew), +                    1 => (Opcode::FIMUL, OperandCodeX87::St_Ew), +                    2 => (Opcode::FICOM, OperandCodeX87::St_Ew), +                    3 => (Opcode::FICOMP, OperandCodeX87::St_Ew), +                    4 => (Opcode::FISUB, OperandCodeX87::St_Ew), +                    5 => (Opcode::FISUBR, OperandCodeX87::St_Ew), +                    6 => (Opcode::FIDIV, OperandCodeX87::St_Ew), +                    7 => (Opcode::FIDIVR, OperandCodeX87::St_Ew), +                    _ => { unreachable!("impossible r"); } +                } +            } +        } +        OperandCode::x87_df => { +            if modrm >= 0xc0 { +                match r { +                    0 => (Opcode::FFREEP, OperandCodeX87::Est), +                    1 => (Opcode::FXCH, OperandCodeX87::St_Est), +                    2 => (Opcode::FSTP, OperandCodeX87::Est_St), +                    3 => (Opcode::FSTP, OperandCodeX87::Est_St), +                    4 => { +                        if modrm == 0xe0 { +                            (Opcode::FNSTSW, OperandCodeX87::Ew) +                        } else { +                            return Err(DecodeError::InvalidOpcode); +                        } +                    }, +                    5 => (Opcode::FUCOMIP, OperandCodeX87::St_Est), +                    6 => (Opcode::FCOMIP, OperandCodeX87::St_Est), +                    7 => { +                        return Err(DecodeError::InvalidOpcode); +                    }, +                    _ => { unreachable!("impossible r"); } +                } +            } else { +                match r { +                    0 => (Opcode::FILD, OperandCodeX87::St_Est), +                    1 => (Opcode::FISTTP, OperandCodeX87::Est_St), +                    2 => (Opcode::FIST, OperandCodeX87::Est_St), +                    3 => (Opcode::FISTP, OperandCodeX87::Est_St), +                    4 => (Opcode::FBLD, OperandCodeX87::St_Est), +                    5 => (Opcode::FILD, OperandCodeX87::St_Est), +                    6 => (Opcode::FBSTP, OperandCodeX87::Est_St), +                    7 => (Opcode::FISTP, OperandCodeX87::Est_St), +                    _ => { unreachable!("impossible r"); } +                } +            } +        } +        other => { +            panic!("invalid x87 operand dispatch, operand code is {:?}", other); +        } +    }; +    instruction.opcode = opcode; +    if instruction.opcode == Opcode::Invalid { +        return Err(DecodeError::InvalidOpcode); +    } +    // TODO: support 80-bit operands +    match x87_operands { +        OperandCodeX87::Est => { +            instruction.operands[0] = read_E_st(&mut bytes_iter, instruction, modrm, length)?; +            instruction.operand_count = 1; +        } +        OperandCodeX87::St_Est => { +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operands[1] = read_E_st(&mut bytes_iter, instruction, modrm, length)?; +            instruction.operand_count = 2; +        } +        OperandCodeX87::St_Ew => { +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; +            instruction.operand_count = 2; +        } +        OperandCodeX87::St_Md => { +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operands[1] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            if instruction.operands[1] == OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.operand_count = 2; +        } +        OperandCodeX87::Md => { +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            if instruction.operands[0] == OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.operand_count = 1; +        } +        OperandCodeX87::Ew => { +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 2, length)?; +            instruction.operand_count = 1; +        } +        OperandCodeX87::Est_St => { +            instruction.operands[0] = read_E_st(&mut bytes_iter, instruction, modrm, length)?; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operand_count = 2; +        } +        OperandCodeX87::Ed_St => { +            instruction.operands[0] = read_E_st(&mut bytes_iter, instruction, modrm, length)?; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operand_count = 2; +        } +        OperandCodeX87::Md_St => { +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            if instruction.operands[0] == OperandSpec::RegMMM { +                return Err(DecodeError::InvalidOperand); +            } +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.modrm_rrr = RegSpec::st(0); +            instruction.operand_count = 2; +        } +        OperandCodeX87::Ex87S => { +            instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, 4, length)?; +            instruction.operand_count = 1; +        } +        OperandCodeX87::Nothing => { +            instruction.operand_count = 0; +        }, +    } + +    Ok(()) +} +  fn decode_one<'b, T: IntoIterator<Item=u8>>(decoder: &InstDecoder, bytes: T, instr: &'b mut Instruction) -> Result<(), DecodeError> {      instr.operands = [          OperandSpec::Nothing, @@ -7118,15 +8308,23 @@ fn decode_one<'b, T: IntoIterator<Item=u8>>(decoder: &InstDecoder, bytes: T, ins  #[inline]  fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<u32, DecodeError> { -    let mut result = 0u32; -    let mut idx = 0; -    loop { -        if idx == width { -            return Ok(result); +    match width { +        1 => { bytes.next().map(|x| x as u32).ok_or(DecodeError::ExhaustedInput) } +        2 => { +            bytes.next().and_then(|b0| { +                bytes.next().map(|b1| u16::from_le_bytes([b0, b1]) as u32) +            }).ok_or(DecodeError::ExhaustedInput) +        } +        4 => { +            bytes.next() +                .and_then(|b0| bytes.next().map(|b1| (b0, b1))) +                .and_then(|(b0, b1)| bytes.next().map(|b2| (b0, b1, b2))) +                .and_then(|(b0, b1, b2)| bytes.next().map(|b3| u32::from_le_bytes([b0, b1, b2, b3]))) +                .ok_or(DecodeError::ExhaustedInput) +        } +        _ => { +            panic!("unsupported read size");          } -        let byte = bytes.next().ok_or(DecodeError::ExhaustedInput)?; -        result |= (byte as u32) << (idx * 8); -        idx += 1;      }  } @@ -7153,16 +8351,6 @@ fn read_imm_unsigned<T: Iterator<Item=u8>>(bytes: &mut T, width: u8, length: &mu  }  #[inline] -fn imm_width_from_prefixes(interpretation: SizeCode, prefixes: Prefixes) -> u8 { -    match interpretation { -        SizeCode::b => 1, -        SizeCode::vd => { -            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/protected_mode/vex.rs b/src/protected_mode/vex.rs index b2a845e..497c25d 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -77,7 +77,7 @@ enum VEXOperandCode {      G_V_M_xmm,      G_V_M_ymm,      V_xmm_G_ymm_E_ymm_imm8, -    V_ymm_G_ymm_E_xmm_imm8, +    G_ymm_V_ymm_E_xmm_imm8,      G_V_xmm_Ew_imm8,      Eq_G_xmm,      Ed_G_xmm, @@ -134,7 +134,7 @@ pub(crate) fn two_byte_vex<T: Iterator<Item=u8>>(bytes: &mut T, vex_byte: u8, in      };      instruction.vex_reg = RegSpec {          bank: RegisterBank::X, -        num: ((vex_byte >> 3) & 0b1111) ^ 0b1111, +        num: ((vex_byte >> 3) & 0b0111) ^ 0b0111,      };      instruction.prefixes.vex_from_c5(vex_byte); @@ -162,24 +162,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::X); +            instruction.vex_reg.bank = RegisterBank::X; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VPS_71_L => {              let modrm = read_modrm(bytes, length)?; @@ -197,24 +188,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::Y); +            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VPS_72 => {              let modrm = read_modrm(bytes, length)?; @@ -232,24 +214,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::X); +            instruction.vex_reg.bank = RegisterBank::X; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VPS_72_L => {              let modrm = read_modrm(bytes, length)?; @@ -267,24 +240,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::Y); +            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VPS_73 => {              let modrm = read_modrm(bytes, length)?; @@ -305,9 +269,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::X); +            instruction.vex_reg.bank = RegisterBank::X; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VPS_73_L => {              let modrm = read_modrm(bytes, length)?; @@ -334,9 +304,15 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                      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) // :) +            instruction.modrm_rrr = +                RegSpec::from_parts(modrm & 7, RegisterBank::Y); +            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.operands[0] = OperandSpec::RegVex; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmI8; +            instruction.operand_count = 3; +            Ok(())          }          VEXOperandCode::VMOVSS_10 |          VEXOperandCode::VMOVSD_10 => { @@ -349,9 +325,11 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                  OperandSpec::RegMMM => {                      instruction.operands[1] = OperandSpec::RegVex;                      instruction.operands[2] = OperandSpec::RegMMM; +                    instruction.operand_count = 3;                  },                  other => {                      instruction.operands[1] = other; +                    instruction.operand_count = 2;                  }              }              Ok(()) @@ -367,9 +345,11 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst                  OperandSpec::RegMMM => {                      instruction.operands[0] = OperandSpec::RegVex;                      instruction.operands[2] = OperandSpec::RegMMM; +                    instruction.operand_count = 3;                  },                  other => {                      instruction.operands[0] = other; +                    instruction.operand_count = 2;                  }              }              Ok(()) @@ -389,6 +369,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::ImmU8; +            instruction.operand_count = 3;              instruction.imm = read_imm_unsigned(bytes, 1, length)?;              Ok(())          }, @@ -403,6 +384,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E(bytes, instruction, modrm, 4, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          VEXOperandCode::G_xmm_Ed => { @@ -416,6 +398,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E(bytes, instruction, modrm, 4, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          VEXOperandCode::Eq_G_xmm => { @@ -429,6 +412,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E(bytes, instruction, modrm, 4, length)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2;              Ok(())          }          VEXOperandCode::Ed_G_xmm => { @@ -442,6 +426,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E(bytes, instruction, modrm, 4, length)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::E_G_xmm | @@ -459,6 +444,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::E_xmm_G_ymm_imm8 => { @@ -472,6 +458,9 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmU8; +            instruction.operand_count = 3;              Ok(())          } @@ -489,6 +478,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::G_xmm_E_xmm => { @@ -502,6 +492,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::G_xmm_E_ymm => { @@ -515,6 +506,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::G_ymm_E_xmm => { @@ -528,6 +520,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::G_ymm_E_ymm => { @@ -541,6 +534,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          } @@ -557,6 +551,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operand_count = 2;              Ok(())          } @@ -573,6 +568,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; +            instruction.operand_count = 2;              Ok(())          }          _op @ VEXOperandCode::G_V_E_ymm | @@ -585,6 +581,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; +            instruction.operand_count = 3;              Ok(())          }          _op @ VEXOperandCode::G_V_E_ymm_imm8 => { @@ -598,6 +595,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[2] = mem_oper;              instruction.imm = read_imm_unsigned(bytes, 1, length)?;              instruction.operands[3] = OperandSpec::ImmU8; +            instruction.operand_count = 4;              Ok(())          }          _op @ VEXOperandCode::E_V_G_ymm | @@ -610,6 +608,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; +            instruction.operand_count = 3;              Ok(())          }          _op @ VEXOperandCode::G_V_M_xmm | @@ -621,6 +620,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; +            instruction.operand_count = 3;              Ok(())          }          _op @ VEXOperandCode::G_V_E_xmm_imm8 => { @@ -633,19 +633,21 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[2] = mem_oper;              instruction.imm = read_imm_unsigned(bytes, 1, length)?;              instruction.operands[3] = OperandSpec::ImmU8; +            instruction.operand_count = 4;              Ok(())          } -        _op @ VEXOperandCode::V_ymm_G_ymm_E_xmm_imm8 => { +        _op @ VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => {              let modrm = read_modrm(bytes, length)?;              instruction.modrm_rrr =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.vex_reg.bank = RegisterBank::Y;              let mem_oper = read_E_xmm(bytes, instruction, modrm, length)?; -            instruction.operands[0] = OperandSpec::RegVex; -            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper;              instruction.imm = read_imm_unsigned(bytes, 1, length)?;              instruction.operands[3] = OperandSpec::ImmU8; +            instruction.operand_count = 4;              Ok(())          }          _op @ VEXOperandCode::V_xmm_G_ymm_E_ymm_imm8 => { @@ -658,6 +660,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[2] = mem_oper;              instruction.imm = read_imm_unsigned(bytes, 1, length)?;              instruction.operands[3] = OperandSpec::ImmU8; +            instruction.operand_count = 4;              Ok(())          }          _op @ VEXOperandCode::E_V_G_xmm | @@ -669,6 +672,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; +            instruction.operand_count = 3;              Ok(())          } @@ -681,6 +685,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; +            instruction.operand_count = 3;              Ok(())          }          VEXOperandCode::G_Ey_V_ymm => { @@ -693,6 +698,7 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; +            instruction.operand_count = 3;              Ok(())          }          VEXOperandCode::G_V_E => { @@ -761,13 +767,73 @@ fn read_vex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Inst              instruction.vex_reg.bank = bank;              Ok(())          } - -        VEXOperandCode::G_E_ymm_imm8 | -        VEXOperandCode::G_V_E_xmm_xmm4 | -        VEXOperandCode::G_V_E_ymm_ymm4 | -        VEXOperandCode::G_V_ymm_E_xmm | +        VEXOperandCode::G_E_ymm_imm8 => { +            let modrm = read_modrm(bytes, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); +            let mem_oper = read_E_ymm(bytes, instruction, modrm, length)?; +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = mem_oper; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[2] = OperandSpec::ImmU8; +            instruction.operand_count = 3; +            Ok(()) +        } +        VEXOperandCode::G_V_E_ymm_ymm4 => { +            let modrm = read_modrm(bytes, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, 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; +            instruction.imm = read_imm_unsigned(bytes, 1, length)? >> 4; +            instruction.operands[3] = OperandSpec::Reg4; +            instruction.operand_count = 4; +            Ok(()) +        } +        VEXOperandCode::G_V_E_xmm_xmm4 => { +            let modrm = read_modrm(bytes, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); +            instruction.vex_reg.bank = 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; +            instruction.imm = read_imm_unsigned(bytes, 1, length)? >> 4; +            instruction.operands[3] = OperandSpec::Reg4; +            instruction.operand_count = 4; +            Ok(()) +        } +        VEXOperandCode::G_V_ymm_E_xmm => { +            let modrm = read_modrm(bytes, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); +            instruction.vex_reg.bank = RegisterBank::Y; +            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; +            instruction.operand_count = 3; +            Ok(()) +        }          VEXOperandCode::G_V_xmm_Ew_imm8 => { -            Err(DecodeError::IncompleteDecoder) // :) +            let modrm = read_modrm(bytes, length)?; +            instruction.modrm_rrr = +                RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); +            instruction.vex_reg.bank = RegisterBank::X; +            // TODO: but the memory access is word-sized +            let mem_oper = read_E(bytes, instruction, modrm, 4, length)?; +            instruction.operands[0] = OperandSpec::RegRRR; +            instruction.operands[1] = OperandSpec::RegVex; +            instruction.operands[2] = mem_oper; +            instruction.imm = read_imm_unsigned(bytes, 1, length)?; +            instruction.operands[3] = OperandSpec::ImmI8; +            instruction.operand_count = 4; +            Ok(()) +          }      } @@ -1275,14 +1341,18 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          0xDC => (Opcode::VPADDUSB, if L {                              VEXOperandCode::G_V_E_ymm                          } else { -                            instruction.opcode = Opcode::Invalid; -                            return Err(DecodeError::InvalidOpcode); +                            VEXOperandCode::G_V_E_xmm                          }),                          0xDD => (Opcode::VPADDUSW, if L {                              VEXOperandCode::G_V_E_ymm                          } else {                              VEXOperandCode::G_V_E_xmm                          }), +                        0xDE => (Opcode::VPMAXUB, if L { +                            VEXOperandCode::G_V_E_ymm +                        } else { +                            VEXOperandCode::G_V_E_xmm +                        }),                          0xDF => (Opcode::VPANDN, if L {                              VEXOperandCode::G_V_E_ymm                          } else { @@ -1338,6 +1408,11 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          } else {                              VEXOperandCode::G_V_E_xmm                          }), +                        0xEA => (Opcode::VPMINSW, if L { +                            VEXOperandCode::G_V_E_ymm +                        } else { +                            VEXOperandCode::G_V_E_xmm +                        }),                          0xEB => (Opcode::VPOR, if L {                              VEXOperandCode::G_V_E_ymm                          } else { @@ -2571,10 +2646,10 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          })                      },                      0x38 => (Opcode::VINSERTI128, if L { +                        VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 +                    } else {                          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 @@ -2594,9 +2669,9 @@ fn read_vex_instruction<T: Iterator<Item=u8>>(opcode_map: VEXOpcodeMap, bytes: &                          VEXOperandCode::G_V_E_xmm_imm8                      }),                      0x42 => (Opcode::VMPSADBW, if L { -                        VEXOperandCode::G_E_ymm_imm8 +                        VEXOperandCode::G_V_E_ymm_imm8                      } else { -                        VEXOperandCode::G_E_xmm_imm8 +                        VEXOperandCode::G_V_E_xmm_imm8                      }),                      0x44 => (Opcode::VPCLMULQDQ, if L {                          instruction.opcode = Opcode::Invalid; | 
