aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-08-09 18:32:48 -0700
committeriximeow <me@iximeow.net>2020-08-09 18:32:48 -0700
commit80219e974d78af59afb4250498554ad8eb63274c (patch)
tree28b4abb02bbcd9827f67047683ddda021fb9ffed
parenta00851d965cecf8bc31b3a9e668c34648e816060 (diff)
port updates to protected-mode decoder
-rw-r--r--src/protected_mode/display.rs2187
-rw-r--r--src/protected_mode/mod.rs3128
-rw-r--r--src/protected_mode/vex.rs265
-rw-r--r--test/protected_mode/mod.rs199
4 files changed, 3636 insertions, 2143 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;
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index e37c1e6..243b283 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -51,7 +51,6 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str
#[test]
fn test_mmx() {
- test_display(&[0x4f, 0x0f, 0xf7, 0xc1], "maskmovq mm0, mm1");
test_display(&[0x0f, 0xf7, 0xc1], "maskmovq mm0, mm1");
test_invalid(&[0x0f, 0xf7, 0x01]);
@@ -75,7 +74,7 @@ fn test_mmx() {
test_display(&[0x0f, 0xf9, 0xc2], "psubw mm0, mm2");
test_display(&[0x0f, 0xfd, 0xd2], "paddw mm2, mm2");
test_display(&[0x0f, 0x6f, 0xe9], "movq mm5, mm1");
- test_display(&[0x0f, 0xe5, 0x3d, 0xaa, 0xbb, 0xcc, 0x77], "pmulhw mm7, [eip + 0x77ccbbaa]");
+ test_display(&[0x0f, 0xe5, 0x3d, 0xaa, 0xbb, 0xcc, 0x77], "pmulhw mm7, [0x77ccbbaa]");
test_display(&[0x0f, 0x38, 0x00, 0xda], "pshufb mm3, mm2");
@@ -521,24 +520,23 @@ fn test_sse4_2() {
test_invalid_under(&InstDecoder::default(), bytes);
}
- test_instr(&[0x66, 0x0f, 0x38, 0x37, 0x03], "pcmpgtq xmm0, [rbx]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x37, 0x03], "pcmpgtq xmm0, [ebx]");
test_instr(&[0x66, 0x0f, 0x38, 0x37, 0xc3], "pcmpgtq xmm0, xmm3");
- test_instr(&[0xf2, 0x0f, 0x38, 0xf0, 0x06], "crc32 eax, [rsi]");
+ test_instr(&[0xf2, 0x0f, 0x38, 0xf0, 0x06], "crc32 eax, [esi]");
test_instr(&[0xf2, 0x0f, 0x38, 0xf0, 0xc6], "crc32 eax, dh");
- test_instr(&[0xf2, 0x0f, 0x38, 0xf1, 0x06], "crc32 eax, [rsi]");
+ test_instr(&[0xf2, 0x0f, 0x38, 0xf1, 0x06], "crc32 eax, [esi]");
test_instr(&[0xf2, 0x0f, 0x38, 0xf1, 0xc6], "crc32 eax, esi");
test_instr(&[0x66, 0xf2, 0x0f, 0x38, 0xf1, 0xc6], "crc32 eax, si");
- test_instr(&[0x66, 0xf2, 0x48, 0x0f, 0x38, 0xf1, 0xc6], "crc32 rax, rsi");
test_instr(&[0x66, 0x0f, 0x3a, 0x60, 0xc6, 0x54], "pcmpestrm xmm0, xmm6, 0x54");
- test_instr(&[0x66, 0x0f, 0x3a, 0x60, 0x06, 0x54], "pcmpestrm xmm0, [rsi], 0x54");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x60, 0x06, 0x54], "pcmpestrm xmm0, [esi], 0x54");
test_instr(&[0x66, 0x0f, 0x3a, 0x61, 0xc6, 0x54], "pcmpestri xmm0, xmm6, 0x54");
- test_instr(&[0x66, 0x0f, 0x3a, 0x61, 0x06, 0x54], "pcmpestri xmm0, [rsi], 0x54");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x61, 0x06, 0x54], "pcmpestri xmm0, [esi], 0x54");
test_instr(&[0x66, 0x0f, 0x3a, 0x62, 0xc6, 0x54], "pcmpistrm xmm0, xmm6, 0x54");
- test_instr(&[0x66, 0x0f, 0x3a, 0x62, 0x06, 0x54], "pcmpistrm xmm0, [rsi], 0x54");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x62, 0x06, 0x54], "pcmpistrm xmm0, [esi], 0x54");
test_instr(&[0x66, 0x0f, 0x3a, 0x63, 0xc6, 0x54], "pcmpistri xmm0, xmm6, 0x54");
- test_instr(&[0x66, 0x0f, 0x3a, 0x63, 0x06, 0x54], "pcmpistri xmm0, [rsi], 0x54");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x63, 0x06, 0x54], "pcmpistri xmm0, [esi], 0x54");
}
#[test]
@@ -558,115 +556,113 @@ fn test_sse4_1() {
test_invalid_under(&InstDecoder::default(), bytes);
}
- test_instr(&[0x66, 0x0f, 0x38, 0x0c, 0x06], "blendps xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x0c, 0x06], "blendps xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x0c, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x0d, 0x06], "blendpd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x0d, 0x06], "blendpd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x0d, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x10, 0x06], "pblendvb xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x10, 0x06], "pblendvb xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x10, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x14, 0x06], "blendvps xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x14, 0x06], "blendvps xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x14, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x15, 0x06], "blendvpd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x15, 0x06], "blendvpd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x15, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x17, 0x06], "ptest xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x17, 0x06], "ptest xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x17, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x20, 0x06], "pmovsxbw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x20, 0x06], "pmovsxbw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x20, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x21, 0x06], "pmovsxbd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x21, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x22, 0x06], "pmovsxbq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x22, 0x06], "pmovsxbq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x22, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x23, 0x06], "pmovsxwd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x23, 0x06], "pmovsxwd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x23, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x24, 0x06], "pmovsxwq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x24, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x25, 0x06], "pmovsxdq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x25, 0x06], "pmovsxdq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x25, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x28, 0x06], "pmuldq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x28, 0x06], "pmuldq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x28, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x29, 0x06], "pcmpeqq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x29, 0x06], "pcmpeqq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x29, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x2a, 0x06], "movntdqa xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x2a, 0x06], "movntdqa xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x2a, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x2b, 0x06], "packusdw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x2b, 0x06], "packusdw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x2b, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x30, 0x06], "pmovzxbw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x30, 0x06], "pmovzxbw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x30, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x31, 0x06], "pmovzxbd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x31, 0x06], "pmovzxbd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x31, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x32, 0x06], "pmovzxbq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x32, 0x06], "pmovzxbq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x32, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x33, 0x06], "pmovzxwd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x33, 0x06], "pmovzxwd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x33, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x34, 0x06], "pmovzxwq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x34, 0x06], "pmovzxwq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x34, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x35, 0x06], "pmovzxdq xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x35, 0x06], "pmovzxdq xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x35, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x38, 0x06], "pminsb xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x38, 0x06], "pminsb xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x38, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x39, 0x06], "pminsd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x39, 0x06], "pminsd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x39, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3a, 0x06], "pminuw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3a, 0x06], "pminuw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3a, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3b, 0x06], "pminud xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3b, 0x06], "pminud xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3b, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3c, 0x06], "pmaxsb xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3c, 0x06], "pmaxsb xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3c, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3d, 0x06], "pmaxsd xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3d, 0x06], "pmaxsd xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3d, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3e, 0x06], "pmaxuw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3e, 0x06], "pmaxuw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3e, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x3f, 0x06], "pmaxud xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x3f, 0x06], "pmaxud xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x3f, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x40, 0x06], "pmulld xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x40, 0x06], "pmulld xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x40, 0x06]);
- test_instr(&[0x66, 0x0f, 0x38, 0x41, 0x06], "phminposuw xmm0, [rsi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x41, 0x06], "phminposuw xmm0, [esi]");
test_invalid(&[0x0f, 0x38, 0x41, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x08, 0x06, 0x31], "roundps xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x08, 0x06, 0x31], "roundps xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x08, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x09, 0x06, 0x31], "roundpd xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x09, 0x06, 0x31], "roundpd xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x09, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x0a, 0x06, 0x31], "roundss xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x0a, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x0b, 0x06, 0x31], "roundsd xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x0b, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x0e, 0x06, 0x31], "pblendw xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x0e, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x14, 0x06, 0x31], "pextrb xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x14, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x15, 0x06, 0x31], "pextrw xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x15, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrd xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x16, 0x06]);
- test_instr(&[0x66, 0x48, 0x0f, 0x3a, 0x16, 0x06, 0x31], "pextrq xmm0, [rsi], 0x31");
- test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x17, 0x06, 0x31], "extractps xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x17, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x20, 0x06, 0x31], "pinsrb xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x20, 0x06, 0x31], "pinsrb xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x20, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x21, 0x06, 0x31], "insertps xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x21, 0x06, 0x31], "insertps xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x21, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x22, 0x06, 0x31], "pinsrd xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x22, 0x06, 0x31], "pinsrd xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x22, 0x06]);
- test_instr(&[0x66, 0x48, 0x0f, 0x3a, 0x22, 0x06, 0x31], "pinsrq xmm0, [rsi], 0x31");
- test_instr(&[0x66, 0x0f, 0x3a, 0x40, 0x06, 0x31], "dpps xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x40, 0x06, 0x31], "dpps xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x40, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x41, 0x06, 0x31], "dppd xmm0, [rsi], 0x31");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x41, 0x06, 0x31], "dppd xmm0, [esi], 0x31");
test_invalid(&[0x0f, 0x3a, 0x41, 0x06]);
- test_instr(&[0x66, 0x0f, 0x3a, 0x42, 0x06, 0x44], "mpsadbw xmm0, [rsi], 0x44");
+ test_instr(&[0x66, 0x0f, 0x3a, 0x42, 0x06, 0x44], "mpsadbw xmm0, [esi], 0x44");
test_invalid(&[0x0f, 0x3a, 0x42, 0x06]);
}
@@ -688,40 +684,40 @@ fn test_ssse3() {
test_invalid_under(&InstDecoder::default(), bytes);
}
test_instr(&[0x66, 0x0f, 0x38, 0x00, 0xda], "pshufb xmm3, xmm2");
- test_instr(&[0x66, 0x0f, 0x38, 0x00, 0x06], "pshufb xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x00, 0x06], "pshufb mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x01, 0x06], "phaddw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x01, 0x06], "phaddw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x02, 0x06], "phaddd xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x02, 0x06], "phaddd mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x03, 0x06], "phaddsw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x03, 0x06], "phaddsw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x04, 0x06], "pmaddubsw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x04, 0x06], "pmaddubsw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x05, 0x06], "phsubw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x05, 0x06], "phsubw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x06, 0x06], "phsubd xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x06, 0x06], "phsubd mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x07, 0x06], "phsubsw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x07, 0x06], "phsubsw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x08, 0x06], "psignb xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x08, 0x06], "psignb mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x09, 0x06], "psignw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x09, 0x06], "psignw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x0a, 0x06], "psignd xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x0a, 0x06], "psignd mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x0b, 0x06], "pmulhrsw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x0b, 0x06], "pmulhrsw mm0, [rsi]");
-
- test_instr(&[0x66, 0x0f, 0x38, 0x1c, 0x06], "pabsb xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x1c, 0x06], "pabsb mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x1d, 0x06], "pabsw xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x1d, 0x06], "pabsw mm0, [rsi]");
- test_instr(&[0x66, 0x0f, 0x38, 0x1e, 0x06], "pabsd xmm0, [rsi]");
- test_instr(&[0x0f, 0x38, 0x1e, 0x06], "pabsd mm0, [rsi]");
-
- test_instr(&[0x66, 0x0f, 0x3a, 0x0f, 0x06, 0x30], "palignr xmm0, [rsi], 0x30");
- test_instr(&[0x0f, 0x3a, 0x0f, 0x06, 0x30], "palignr mm0, [rsi], 0x30");
+ test_instr(&[0x66, 0x0f, 0x38, 0x00, 0x06], "pshufb xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x00, 0x06], "pshufb mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x01, 0x06], "phaddw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x01, 0x06], "phaddw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x02, 0x06], "phaddd xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x02, 0x06], "phaddd mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x03, 0x06], "phaddsw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x03, 0x06], "phaddsw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x04, 0x06], "pmaddubsw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x04, 0x06], "pmaddubsw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x05, 0x06], "phsubw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x05, 0x06], "phsubw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x06, 0x06], "phsubd xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x06, 0x06], "phsubd mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x07, 0x06], "phsubsw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x07, 0x06], "phsubsw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x08, 0x06], "psignb xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x08, 0x06], "psignb mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x09, 0x06], "psignw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x09, 0x06], "psignw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x0a, 0x06], "psignd xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x0a, 0x06], "psignd mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x0b, 0x06], "pmulhrsw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x0b, 0x06], "pmulhrsw mm0, [esi]");
+
+ test_instr(&[0x66, 0x0f, 0x38, 0x1c, 0x06], "pabsb xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x1c, 0x06], "pabsb mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x1d, 0x06], "pabsw xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x1d, 0x06], "pabsw mm0, [esi]");
+ test_instr(&[0x66, 0x0f, 0x38, 0x1e, 0x06], "pabsd xmm0, [esi]");
+ test_instr(&[0x0f, 0x38, 0x1e, 0x06], "pabsd mm0, [esi]");
+
+ test_instr(&[0x66, 0x0f, 0x3a, 0x0f, 0x06, 0x30], "palignr xmm0, [esi], 0x30");
+ test_instr(&[0x0f, 0x3a, 0x0f, 0x06, 0x30], "palignr mm0, [esi], 0x30");
}
#[test]
@@ -922,7 +918,7 @@ fn test_sse() {
#[test]
fn test_mov() {
test_display(&[0xa0, 0x93, 0x62, 0xc4, 0x00], "mov al, [0xc46293]");
- test_display(&[0x67, 0xa0, 0x93, 0x62], "mov al, [0xc293]");
+ test_display(&[0x67, 0xa0, 0x93, 0x62], "mov al, [0x6293]");
test_display(&[0xa1, 0x93, 0x62, 0xc4, 0x00], "mov eax, [0xc46293]");
test_display(&[0x67, 0xa1, 0x93, 0x62], "mov eax, [0x6293]");
test_display(&[0xa2, 0x93, 0x62, 0xc4, 0x00], "mov [0xc46293], al");
@@ -1011,8 +1007,8 @@ fn test_push_pop() {
test_display(&[0x5b], "pop ebx");
test_display(&[0x5e], "pop esi");
test_display(&[0x68, 0x7f, 0x63, 0xc4, 0x00], "push 0xc4637f");
- test_display(&[0x66, 0x8f, 0x00], "pop [rax]");
- test_display(&[0x8f, 0x00], "pop [rax]");
+ test_display(&[0x66, 0x8f, 0x00], "pop [eax]");
+ test_display(&[0x8f, 0x00], "pop [eax]");
}
#[test]
@@ -1106,7 +1102,6 @@ fn test_misc() {
test_display(&[0xcb], "retf");
test_display(&[0x66, 0xcf], "iret");
test_display(&[0xcf], "iretd");
- test_display(&[0x66, 0x4f, 0xcf], "iretq");
test_display(&[0xf2, 0x0f, 0x38, 0xf0, 0xc1], "crc32 eax, cl");
test_display(&[0xf2, 0x0f, 0x38, 0xf1, 0xc1], "crc32 eax, ecx");
test_display(&[0xfe, 0x00], "inc [eax]"); // TODO: inc byte [eax]
@@ -1290,10 +1285,10 @@ fn test_vex() {
test_instr(&[0xc4, 0xc3, 0x75, 0x46, 0x7c, 0x12, 0x05, 0x61], "vperm2i128 ymm7, ymm1, [edx + edx * 1 + 0x5], 0x61");
test_instr(&[0xc4, 0xc3, 0x75, 0x4a, 0x7c, 0x12, 0x05, 0x61], "vblendvps ymm7, ymm1, [edx + edx * 1 + 0x5], ymm6");
test_instr(&[0xc4, 0xc3, 0x71, 0x4a, 0x7c, 0x12, 0x05, 0x61], "vblendvps xmm7, xmm1, [edx + edx * 1 + 0x5], xmm6");
- test_instr(&[0xc4, 0xc3, 0x71, 0x4a, 0xdc, 0x61], "vblendvps xmm3, xmm1, xmm12, xmm6");
+ test_instr(&[0xc4, 0xc3, 0x71, 0x4a, 0xdc, 0x61], "vblendvps xmm3, xmm1, xmm4, xmm6");
test_instr(&[0xc4, 0xc3, 0x75, 0x4b, 0x7c, 0x12, 0x05, 0x61], "vblendvpd ymm7, ymm1, [edx + edx * 1 + 0x5], ymm6");
- test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0x7c, 0x12, 0x05, 0x61], "vblendvpd xmm7, xmm1, [edx + rdx * 1 + 0x5], xmm6");
- test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0xdc, 0x61], "vblendvpd xmm3, xmm1, xmm12, xmm6");
+ test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0x7c, 0x12, 0x05, 0x61], "vblendvpd xmm7, xmm1, [edx + edx * 1 + 0x5], xmm6");
+ test_instr(&[0xc4, 0xc3, 0x71, 0x4b, 0xdc, 0x61], "vblendvpd xmm3, xmm1, xmm4, xmm6");
test_instr(&[0xc4, 0xc3, 0x71, 0x4c, 0x7c, 0x12, 0x05, 0x61], "vpblendvb xmm7, xmm1, [edx + edx * 1 + 0x5], xmm6");
test_instr(&[0xc5, 0xc9, 0xf1, 0x0f], "vpsllw xmm1, xmm6, [edi]");
@@ -1458,6 +1453,10 @@ fn only_32bit() {
test_display(&[0x67, 0xa0, 0xc0, 0xb0], "mov al, [0xb0c0]");
test_display(&[0x67, 0xa1, 0xc0, 0xb0], "mov eax, [0xb0c0]");
test_display(&[0x66, 0x67, 0xa1, 0xc0, 0xb0], "mov ax, [0xb0c0]");
+
+ test_display(&[0x60], "pusha");
+ test_display(&[0x61], "popa");
+ test_display(&[0xce], "into");
}
#[test]