From fb13ada90394489d802a02d947f22eb97f6b7959 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 16 Jul 2023 15:39:38 -0700 Subject: forward changes along to 16-bit decoder... --- src/real_mode/display.rs | 127 +- src/real_mode/mod.rs | 6754 +++++++++++++++++++++++----------------------- src/real_mode/vex.rs | 2137 +++++---------- 3 files changed, 4138 insertions(+), 4880 deletions(-) (limited to 'src/real_mode') diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index 6f6eb74..9450a39 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -105,9 +105,11 @@ 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", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", "BUG", + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "es", "cs", "ss", "ds", "fs", "gs", "", "", @@ -346,20 +348,36 @@ impl fmt::Display for Opcode { } const MNEMONICS: &[&'static str] = &[ - "invalid", "add", "or", "adc", "sbb", "and", - "xor", "sub", + "xor", "cmp", - "xadd", - "bt", - "bts", + "rol", + "ror", + "rcl", + "rcr", + "shl", + "shr", + "sal", + "sar", "btc", "btr", + "bts", + "cmpxchg", + "cmpxchg8b", + "cmpxchg16b", + "dec", + "inc", + "neg", + "not", + "xadd", + "xchg", + "invalid", + "bt", "bsf", "bsr", "tzcnt", @@ -403,17 +421,9 @@ const MNEMONICS: &[&'static str] = &[ "movzx", "movsx", "movsxd", - "sar", - "sal", - "shr", "shrd", - "shl", - "rcr", - "rcl", - "ror", - "rol", - "inc", - "dec", +// " inc", +// " dec", "hlt", "call", "callf", @@ -427,7 +437,7 @@ const MNEMONICS: &[&'static str] = &[ "prefetch0", "prefetch1", "prefetch2", - "xchg", +// " xchg", "popf", "int", "into", @@ -495,9 +505,9 @@ const MNEMONICS: &[&'static str] = &[ "div", "idiv", "mul", - "neg", - "not", - "cmpxchg", +// " neg", +// " not", +// " cmpxchg", "seto", "setno", "setb", @@ -584,7 +594,8 @@ const MNEMONICS: &[&'static str] = &[ "movdq2q", "rsqrtss", "rcpss", - "andn", + + "andn", "bextr", "blsi", "blsmsk", @@ -614,11 +625,14 @@ const MNEMONICS: &[&'static str] = &[ "enclu", "rdpkru", "wrpkru", - "rdpru", + + "rdpru", "clzero", - "rdseed", + + "rdseed", "rdrand", - "addps", + + "addps", "addpd", "andnps", "andnpd", @@ -758,6 +772,7 @@ const MNEMONICS: &[&'static str] = &[ "vmwrite", "xorps", "xorpd", + "vmovddup", "vpshuflw", "vpshufhw", @@ -766,6 +781,7 @@ const MNEMONICS: &[&'static str] = &[ "vaddsubps", "vcvtpd2dq", "vlddqu", + "vcomisd", "vcomiss", "vucomisd", @@ -1108,6 +1124,7 @@ const MNEMONICS: &[&'static str] = &[ "vzeroall", "vldmxcsr", "vstmxcsr", + "pclmulqdq", "aeskeygenassist", "aesimc", @@ -1188,6 +1205,7 @@ const MNEMONICS: &[&'static str] = &[ "phaddw", "hsubpd", "haddpd", + "sha1rnds4", "sha1nexte", "sha1msg1", @@ -1195,6 +1213,7 @@ const MNEMONICS: &[&'static str] = &[ "sha256rnds2", "sha256msg1", "sha256msg2", + "lzcnt", "clgi", "stgi", @@ -1206,15 +1225,20 @@ const MNEMONICS: &[&'static str] = &[ "invlpga", "invlpgb", "tlbsync", + "movbe", + "adcx", "adox", + "prefetchw", + "rdpid", - "cmpxchg8b", - "cmpxchg16b", +// " cmpxchg8b", +// " cmpxchg16b", "vmptrld", "vmptrst", + "bzhi", "mulx", "shlx", @@ -1229,10 +1253,12 @@ const MNEMONICS: &[&'static str] = &[ "xsavec64", "xsaves", "xsaves64", + "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", + "crc32", "salc", "xlat", @@ -1329,10 +1355,12 @@ const MNEMONICS: &[&'static str] = &[ "fxtract", "fyl2x", "fyl2xp1", + "loopnz", "loopz", "loop", "jcxz", + "pusha", "popa", "bound", @@ -1343,8 +1371,12 @@ const MNEMONICS: &[&'static str] = &[ "daa", "aam", "aad", + + // started shipping in tremont, 2020 sept 23 "movdir64b", "movdiri", + + // started shipping in tiger lake, 2020 sept 2 "aesdec128kl", "aesdec256kl", "aesdecwide128kl", @@ -1364,8 +1396,8 @@ const MNEMONICS: &[&'static str] = &[ "femms", "pi2fw", "pi2fd", - "pi2iw", - "pi2id", + "pf2iw", + "pf2id", "pmulhrw", "pfcmpge", "pfmin", @@ -1388,24 +1420,24 @@ const MNEMONICS: &[&'static str] = &[ "pswapd", "pavgusb", - // ENQCMD + // enqcmd "enqcmd", "enqcmds", - // INVPCID, + // invpcid "invept", "invvpid", "invpcid", - // PTWRITE + // ptwrite "ptwrite", - // GFNI + // gfni "gf2p8affineqb", "gf2p8affineinvqb", "gf2p8mulb", - // CET + // cet "wruss", "wrss", "incssp", @@ -1416,29 +1448,29 @@ const MNEMONICS: &[&'static str] = &[ "endbr64", "endbr32", - // TDX + // tdx "tdcall", "seamret", "seamops", "seamcall", - // WAITPKG + // waitpkg "tpause", "umonitor", "umwait", - // UINTR + // uintr "uiret", "testui", "clui", "stui", "senduipi", - // TSXLDTRK + // tsxldtrk "xsusldtrk", "xresldtrk", - // AVX512F + // avx512f "valignd", "valignq", "vblendmpd", @@ -1559,7 +1591,7 @@ const MNEMONICS: &[&'static str] = &[ "vshufi32x4", "vshufi64x2", - // AVX512DQ + // avx512dq "vcvttpd2qq", "vcvtpd2qq", "vcvttpd2uqq", @@ -1591,7 +1623,7 @@ const MNEMONICS: &[&'static str] = &[ "vreducesd", "vreducess", - // AVX512BW + // avx512bw "vdbpsadbw", "vmovdqu8", "vmovdqu16", @@ -1618,7 +1650,7 @@ const MNEMONICS: &[&'static str] = &[ "vptestmb", "vptestmw", - // AVX512CD + // avx512cd "vpbroadcastm", "vpconflictd", "vpconflictq", @@ -1678,7 +1710,7 @@ const MNEMONICS: &[&'static str] = &[ "kxnorq", "kxorq", - // AVX512ER + // avx512er "vexp2pd", "vexp2ps", "vexp2sd", @@ -1692,7 +1724,7 @@ const MNEMONICS: &[&'static str] = &[ "vrsqrt28sd", "vrsqrt28ss", - // AVX512PF + // avx512pf "vgatherpf0dpd", "vgatherpf0dps", "vgatherpf0qpd", @@ -1710,7 +1742,7 @@ const MNEMONICS: &[&'static str] = &[ "vscatterpf1qpd", "vscatterpf1qps", - // MPX + // mpx "bndmk", "bndcl", "bndcu", @@ -1719,8 +1751,6 @@ const MNEMONICS: &[&'static str] = &[ "bndldx", "bndstx", - - "vgf2p8affineqb", "vgf2p8affineinvqb", "vpshrdq", @@ -1809,6 +1839,7 @@ const MNEMONICS: &[&'static str] = &[ "vpandnq", "vpandd", "vpandq", + "psmash", "pvalidate", "rmpadjust", @@ -1818,7 +1849,7 @@ const MNEMONICS: &[&'static str] = &[ impl Opcode { fn name(&self) -> &'static str { unsafe { - MNEMONICS.get_kinda_unchecked(*self as usize) + MNEMONICS.get_kinda_unchecked(*self as usize & 0xfff) } } } diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 676f9b6..ae191ec 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -404,60 +404,13 @@ impl OperandSpec { OperandSpec::RegDisp => OperandSpec::RegDisp_mask, OperandSpec::RegScale => OperandSpec::RegScale_mask, OperandSpec::RegScaleDisp => OperandSpec::RegScaleDisp_mask, - OperandSpec::RegIndexBase => OperandSpec::RegIndexBase_mask, - OperandSpec::RegIndexBaseDisp => OperandSpec::RegIndexBaseDisp_mask, OperandSpec::RegIndexBaseScale => OperandSpec::RegIndexBaseScale_mask, OperandSpec::RegIndexBaseScaleDisp => OperandSpec::RegIndexBaseScaleDisp_mask, o => o, } } fn is_memory(&self) -> bool { - match self { - OperandSpec::DispU16 | - OperandSpec::DispU32 | - OperandSpec::Deref | - OperandSpec::Deref_si | - OperandSpec::Deref_di | - OperandSpec::Deref_esi | - OperandSpec::Deref_edi | - OperandSpec::RegDisp | - OperandSpec::RegScale | - OperandSpec::RegIndexBase | - OperandSpec::RegIndexBaseDisp | - OperandSpec::RegScaleDisp | - OperandSpec::RegIndexBaseScale | - OperandSpec::RegIndexBaseScaleDisp | - OperandSpec::Deref_mask | - OperandSpec::RegDisp_mask | - OperandSpec::RegScale_mask | - OperandSpec::RegScaleDisp_mask | - OperandSpec::RegIndexBase_mask | - OperandSpec::RegIndexBaseDisp_mask | - OperandSpec::RegIndexBaseScale_mask | - OperandSpec::RegIndexBaseScaleDisp_mask => { - true - }, - OperandSpec::ImmI8 | - OperandSpec::ImmI16 | - OperandSpec::ImmI32 | - OperandSpec::ImmU8 | - OperandSpec::ImmU16 | - OperandSpec::RegRRR | - OperandSpec::RegRRR_maskmerge | - OperandSpec::RegRRR_maskmerge_sae | - OperandSpec::RegRRR_maskmerge_sae_noround | - OperandSpec::RegMMM | - OperandSpec::RegMMM_maskmerge | - OperandSpec::RegMMM_maskmerge_sae_noround | - OperandSpec::RegVex | - OperandSpec::RegVex_maskmerge | - OperandSpec::Reg4 | - OperandSpec::ImmInDispField | - OperandSpec::AbsoluteFarAddress | - OperandSpec::Nothing => { - false - } - } + (*self as u8) & 0x80 != 0 } } /// an `avx512` merging mode. @@ -530,7 +483,7 @@ impl Operand { OperandSpec::Nothing => { Operand::Nothing } - // the register in modrm_rrr + // the register in regs[0] OperandSpec::RegRRR => { Operand::Register(inst.regs[0]) } @@ -556,7 +509,7 @@ impl Operand { MergeMode::from(inst.prefixes.evex_unchecked().merge()), ) } - // the register in modrm_mmm (eg modrm mod bits were 11) + // the register in regs[1] (eg modrm mod bits were 11) OperandSpec::RegMMM => { Operand::Register(inst.regs[1]) } @@ -616,12 +569,6 @@ impl Operand { OperandSpec::RegScale => { Operand::RegScale(inst.regs[2], inst.scale) } - OperandSpec::RegIndexBase => { - Operand::RegIndexBase(inst.regs[1], inst.regs[2]) - } - OperandSpec::RegIndexBaseDisp => { - Operand::RegIndexBaseDisp(inst.regs[1], inst.regs[2], inst.disp as i32) - } OperandSpec::RegScaleDisp => { Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) } @@ -659,20 +606,6 @@ impl Operand { Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32) } } - OperandSpec::RegIndexBase_mask => { - if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseMasked(inst.regs[1], inst.regs[2], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) - } else { - Operand::RegIndexBase(inst.regs[1], inst.regs[2]) - } - } - OperandSpec::RegIndexBaseDisp_mask => { - if inst.prefixes.evex_unchecked().mask_reg() != 0 { - Operand::RegIndexBaseDispMasked(inst.regs[1], inst.regs[2], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) - } else { - Operand::RegIndexBaseDisp(inst.regs[1], inst.regs[2], inst.disp as i32) - } - } OperandSpec::RegIndexBaseScale_mask => { if inst.prefixes.evex_unchecked().mask_reg() != 0 { Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) @@ -773,6 +706,9 @@ impl Operand { fn operand_size() { assert_eq!(core::mem::size_of::(), 1); assert_eq!(core::mem::size_of::(), 2); + assert_eq!(core::mem::size_of::(), 4); + assert_eq!(core::mem::size_of::(), 4); + assert_eq!(core::mem::size_of::(), 8); // assert_eq!(core::mem::size_of::(), 4); // assert_eq!(core::mem::size_of::(), 40); } @@ -788,9 +724,11 @@ pub struct RegisterClass { } const REGISTER_CLASS_NAMES: &[&'static str] = &[ - "dword", - "word", + "BUG. PLEASE REPORT", "byte", + "word", + "BUG. PLEASE REPORT", + "dword", "cr", "dr", "segment", @@ -818,11 +756,11 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[ /// instruction. as an example: /// ``` /// use yaxpeax_x86::real_mode::{self as amd64}; -/// use yaxpeax_x86::real_mode::{Opcode, Operand, RegisterClass, InstDecoder}; +/// use yaxpeax_x86::real_mode::{Opcode, Operand, RegisterClass}; /// use yaxpeax_arch::{Decoder, U8Reader}; /// /// let movsx_ax_cl = &[0x0f, 0xbe, 0xc1]; -/// let decoder = InstDecoder::default(); +/// let decoder = amd64::InstDecoder::default(); /// let instruction = decoder /// .decode(&mut U8Reader::new(movsx_ax_cl)) /// .expect("can decode"); @@ -946,11 +884,11 @@ impl RegisterClass { #[cfg_attr(feature="use-serde", derive(Serialize, Deserialize))] #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] enum RegisterBank { - 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 + D = 4, W = 2, B = 1, // Dword, Word, Byte + CR = 5, DR = 6, S = 7, EIP = 23, EFlags = 24, // Control reg, Debug reg, Selector, ... + X = 8, Y = 12, Z = 16, // XMM, YMM, ZMM + ST = 20, MM = 21, // ST, MM regs (x87, mmx) + K = 22, // AVX512 mask registers } /// the segment register used by the corresponding instruction. @@ -1000,21 +938,42 @@ const XSAVE: [Opcode; 10] = [ #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] +#[repr(u32)] pub enum Opcode { - Invalid, - ADD, - OR, - ADC, - SBB, - AND, - XOR, - SUB, - CMP, - XADD, + ADD = 0x1000, + OR = 0x1001, + ADC = 0x1002, + SBB = 0x1003, + AND = 0x1004, + SUB = 0x1005, + XOR = 0x1006, + CMP = 7, + ROL = 8, + ROR, + RCL, + RCR, + SHL, + SHR, + SAL, + SAR = 0x0f, + BTC = 0x1010, + BTR = 0x1011, + BTS = 0x1012, + CMPXCHG = 0x1013, + CMPXCHG8B = 0x1014, + CMPXCHG16B = 0x1015, + DEC = 0x1016, + INC = 0x1017, + NEG = 0x1018, + NOT = 0x1019, + XADD = 0x101a, + XCHG = 0x101b, + Invalid = 0x1c, +// XADD, BT, - BTS, - BTC, - BTR, +// BTS, +// BTC, +// BTR, BSF, BSR, TZCNT, @@ -1058,17 +1017,9 @@ pub enum Opcode { MOVZX, MOVSX, MOVSXD, - SAR, - SAL, - SHR, SHRD, - SHL, - RCR, - RCL, - ROR, - ROL, - INC, - DEC, +// INC, +// DEC, HLT, CALL, CALLF, @@ -1082,7 +1033,7 @@ pub enum Opcode { PREFETCH0, PREFETCH1, PREFETCH2, - XCHG, +// XCHG, POPF, INT, INTO, @@ -1150,9 +1101,9 @@ pub enum Opcode { DIV, IDIV, MUL, - NEG, - NOT, - CMPXCHG, +// NEG, +// NOT, +// CMPXCHG, SETO, SETNO, SETB, @@ -1879,8 +1830,8 @@ pub enum Opcode { PREFETCHW, RDPID, - CMPXCHG8B, - CMPXCHG16B, +// CMPXCHG8B, +// CMPXCHG16B, VMPTRLD, VMPTRST, @@ -2531,12 +2482,6 @@ impl PartialEq for Instruction { #[derive(Debug, Clone, Copy, Eq)] pub struct Instruction { pub prefixes: Prefixes, - /* - modrm_rrr: RegSpec, - modrm_mmm: RegSpec, // doubles as sib_base - sib_index: RegSpec, - vex_reg: RegSpec, - */ regs: [RegSpec; 4], scale: u8, length: u8, @@ -2594,64 +2539,61 @@ impl std::error::Error for DecodeError { #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] enum OperandSpec { - Nothing, - // the register in modrm_rrr - RegRRR, - // the register in modrm_rrr and is EVEX-encoded (may have a mask register, is merged or + Nothing = 0, + // the register in regs[0] + RegRRR = 0x01, + // the register in regs[0] and is EVEX-encoded (may have a mask register, is merged or // zeroed) - RegRRR_maskmerge, - // the register in modrm_rrr and is EVEX-encoded (may have a mask register, is merged or + RegRRR_maskmerge = 0x41, + // the register in regs[0] and is EVEX-encoded (may have a mask register, is merged or // zeroed). additionally, this instruction has exceptions suppressed with a potentially // custom rounding mode. - RegRRR_maskmerge_sae, - // the register in modrm_rrr and is EVEX-encoded (may have a mask register, is merged or + RegRRR_maskmerge_sae = 0x58, + // the register in regs[0] and is EVEX-encoded (may have a mask register, is merged or // zeroed). additionally, this instruction has exceptions suppressed. - RegRRR_maskmerge_sae_noround, + RegRRR_maskmerge_sae_noround = 0x59, // the register in modrm_mmm (eg modrm mod bits were 11) - RegMMM, + RegMMM = 0x02, // same as `RegRRR`: the register is modrm's `mmm` bits, and may be masked. - RegMMM_maskmerge, - RegMMM_maskmerge_sae_noround, + RegMMM_maskmerge = 0x42, + RegMMM_maskmerge_sae_noround = 0x5a, // the register selected by vex-vvvv bits - RegVex, - RegVex_maskmerge, + RegVex = 0x03, + RegVex_maskmerge = 0x43, // the register selected by a handful of avx2 vex-coded instructions, // stuffed in imm4. - Reg4, - ImmI8, - ImmI16, - ImmI32, - ImmU8, - ImmU16, + Reg4 = 0x04, + ImmI8 = 0x05, + ImmI16 = 0x06, + ImmI32 = 0x07, + // ImmI64 = 0x08, not in 64b + ImmU8 = 0x09, + ImmU16 = 0x0a, // 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. // turns out `insertq` and `extrq` are also two-immediate instructions, so this is generalized // to cover them too. - ImmInDispField, - DispU16, - DispU32, - Deref, - Deref_si, - Deref_di, - Deref_esi, - Deref_edi, - RegDisp, - RegScale, - RegIndexBase, - RegIndexBaseDisp, - RegScaleDisp, - RegIndexBaseScale, - RegIndexBaseScaleDisp, - Deref_mask, - RegDisp_mask, - RegScale_mask, - RegScaleDisp_mask, - RegIndexBase_mask, - RegIndexBaseDisp_mask, - RegIndexBaseScale_mask, - RegIndexBaseScaleDisp_mask, + ImmInDispField = 0x0b, + DispU16 = 0x8c, + DispU32 = 0x8d, + Deref = 0x8e, + Deref_si = 0x8f, + Deref_di = 0x90, + Deref_esi = 0x91, + Deref_edi = 0x92, + RegDisp = 0x93, + RegScale = 0x94, + RegScaleDisp = 0x95, + RegIndexBaseScale = 0x96, + RegIndexBaseScaleDisp = 0x97, + Deref_mask = 0xce, + RegDisp_mask = 0xd3, + RegScale_mask = 0xd4, + RegScaleDisp_mask = 0xd5, + RegIndexBaseScale_mask = 0xd6, + RegIndexBaseScaleDisp_mask = 0xd7, // u16:u{16,32} immediate address for a far call - AbsoluteFarAddress, + AbsoluteFarAddress = 0x98, } // the Hash, Eq, and PartialEq impls here are possibly misleading. @@ -4108,7 +4050,7 @@ impl Default for InstDecoder { impl Decoder for InstDecoder { fn decode::Address, ::Word>>(&self, words: &mut T) -> Result::DecodeError> { let mut instr = Instruction::invalid(); - read_with_annotations(self, words, &mut instr, &mut NullSink)?; + DecodeCtx::new().read_with_annotations(self, words, &mut instr, &mut NullSink)?; instr.length = words.offset() as u8; if words.offset() > 15 { @@ -4133,7 +4075,7 @@ impl AnnotatingDecoder for InstDecoder { T: Reader<::Address, ::Word>, S: DescriptionSink >(&self, instr: &mut Instruction, words: &mut T, sink: &mut S) -> Result<(), ::DecodeError> { - read_with_annotations(self, words, instr, sink)?; + DecodeCtx::new().read_with_annotations(self, words, instr, sink)?; instr.length = words.offset() as u8; if words.offset() > 15 { @@ -4346,7 +4288,7 @@ impl Instruction { prefixes: Prefixes::new(0), opcode: Opcode::NOP, mem_size: 0, - regs: [RegSpec::eax(); 4], + regs: [RegSpec::ax(); 4], scale: 0, length: 0, disp: 0, @@ -4615,6 +4557,17 @@ impl Prefixes { #[inline] fn vex_unchecked(&self) -> PrefixVex { PrefixVex { bits: self.vex.bits } } #[inline] + fn vex_invalid(&self) -> bool { + /* + * if instruction.prefixes.rex_unchecked().present() // but no rex outside 64-bit mode + * || instruction.prefixes.lock() + * || instruction.prefixes.operand_size() + * || instruction.prefixes.rep() + * || instruction.prefixes.repnz() { + */ + (self.bits & 0b1100_0101) > 0 + } + #[inline] pub fn vex(&self) -> Option { let vex = self.vex_unchecked(); if vex.present() { @@ -4778,50 +4731,42 @@ impl OperandCodeBuilder { self } - const fn op0_is_rrr_and_embedded_instructions(mut self) -> Self { - self = self.set_embedded_instructions(); + // deny ModRM `mod=11` + const fn deny_regmmm(mut self) -> Self { self.bits |= 0x2000; self } + const fn denies_regmmm(&self) -> bool { + self.bits & 0x2000 != 0 + } 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 { + fn get_embedded_instructions(&self) -> Option { // 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 }) + if self.has_embedded_instructions() { + Some(ZOperandInstructions { bits: self.bits }) } else { - Err(EmbeddedOperandInstructions { bits: self.bits }) + None } } - #[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 + fn operand_case_handler_index(&self) -> OperandCase { + unsafe { core::mem::transmute(self.bits as u8) } } - const fn operand_case(mut self, case: u16) -> Self { + const fn operand_case(mut self, case: OperandCase) -> Self { // leave 0x4000 unset - self.bits |= case & 0xff; + self.bits |= case as u8 as u16; self } @@ -4869,11 +4814,6 @@ impl OperandCodeBuilder { (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 } @@ -4892,19 +4832,13 @@ impl OperandCodeBuilder { // 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 { + const fn only_imm(mut self) -> 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 - } + fn has_imm(&self) -> bool { + self.bits & 0x100 != 0 } } @@ -4914,230 +4848,388 @@ impl OperandCodeBuilder { pub struct OperandCodeWrapper { code: OperandCode } #[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? +#[derive(Debug, PartialEq, Copy, Clone)] +#[repr(u8)] +enum OperandCase { + Internal = 0, // handled internally and completely by embedded rules. + Gv_M = 1, // "internal", but must be distinguished from Gv_Ev + Ibs = 2, + Jvds = 3, + Nothing = 4, // no operands. this is distinct from `Internal`: `Internal` may specify one or two operands depending on embedded rules. + SingleMMMOper = 5, // one operand, disregard rrr bits of modrm. + BaseOpWithI8 = 6, + BaseOpWithIv = 7, + MovI8 = 8, + MovIv = 9, + BitwiseWithI8 = 10, +// BitwiseWithIv = 9, + ShiftBy1_b, + ShiftBy1_v, + BitwiseByCL, + ModRM_0x8f, + ModRM_0xf6, + ModRM_0xf7, + ModRM_0xfe, + ModRM_0xff, + Gv_Eb, + Gv_Ew, +// Gdq_Ed, + I_3, + E_G_xmm, + G_M_xmm, + G_E_xmm, + G_E_xmm_Ib, + AL_Ibs, + AX_Ivd, + Ivs, + ModRM_0x83, + Ed_G_xmm, + G_Ed_xmm, + + /* + Nothing = Nothing, + Eb_R0 = SingleMMMOper, + Ev = SingleMMMOper, + ModRM_0x80_Eb_Ib = BaseOpWithI8, + ModRM_0x81_Ev_Ivs = BaseOpWithIv, + ModRM_0xc6_Eb_Ib = MovI8, + ModRM_0xc7_Ev_Iv = MovIv, + ModRM_0xc0_Eb_Ib = BitwiseWithI8, + ModRM_0xc1_Ev_Ib = BitwiseWithIv, + ModRM_0xd0_Eb_1 = ShiftBy1_b, + ModRM_0xd1_Ev_1 = ShiftBy1_v, + ModRM_0x8f_Ev = ModRM_0x8f, + ModRM_0xd2_Eb_CL = BitwiseByCL, + ModRM_0xd3_Ev_CL = BitwiseByCL, + ModRM_0xf6 = ModRM_0xf6_0xf7, + ModRM_0xf7 = ModRM_0xf6_0xf7, + ModRM_0xfe_Eb = ModRM_0xfe, + ModRM_0xff_Ev = ModRM_0xff, + Gv_Eb = Gv_Eb, + Gv_Ew = Gv_Ew, + Gdq_Ed = Gdq_Ed, + I_3 = I_3, + E_G_xmm = E_G_xmm, + G_M_xmm = G_M_xmm, + G_E_xmm = G_E_xmm, + G_E_xmm_Ib = G_E_xmm_Ib, + AL_Ibs = AL_Ibs, + AX_Ivd = AX_Ivd, + Ivs = Ivs, + ModRM_0x83_Ev_Ibs = ModRM_0x83, + + Ed_G_xmm = Ed_G_xmm, + + G_Ed_xmm = G_Ed_xmm, + */ + + Ib, + x87_d8, + x87_d9, + x87_da, + x87_db, + x87_dc, + x87_dd, + x87_de, + x87_df, + AL_Ib, + AX_Ib, + Ib_AL, + Ib_AX, + Gv_Ew_LSL, +// Gdq_Ev, + Gd_Ev, + Gv_Ev_Ib, + Gv_Ev_Iv, + AX_DX, + AL_DX, + DX_AX, + DX_AL, + MOVQ_f30f, + Yv_Xv, + Gd_Ed, +// Mdq_Gdq, + Md_Gd, + AL_Ob, + AL_Xb, + AX_Ov, + G_xmm_E_mm, + G_xmm_U_mm, + G_mm_U_xmm, + Rv_Gmm_Ib, + G_xmm_Ed, + G_mm_E_xmm, + Gd_U_xmm, + Gv_E_xmm, + G_xmm_Ew_Ib, + G_E_xmm_Ub, + G_U_xmm_Ub, + G_U_xmm, + M_G_xmm, + G_E_mm, + G_U_mm, + E_G_mm, + Ed_G_mm, + G_mm_Ed, + G_mm_E, + Ev_Gv_Ib, + Ev_Gv_CL, + G_mm_U_mm, + G_Mq_mm, + G_mm_Ew_Ib, + G_E_q, + E_G_q, + 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, + Ew_Sw, + Fw, + I_1, + Iw, + Iw_Ib, + Ob_AL, + Ov_AX, + Sw_Ew, + Yb_AL, + Yb_Xb, + Yv_AX, + Ew_Gw, + ES, + CS, + SS, + DS, + ModRM_0x62, + ModRM_0xc4, + ModRM_0xc5, + INV_Gv_M, + PMOVX_G_E_xmm, + PMOVX_E_G_xmm, + G_Ev_xmm_Ib, + G_E_mm_Ib, + AbsFar, + MOVDIR64B, + ModRM_0x0f00, + ModRM_0x0f01, + ModRM_0x0f0d, + ModRM_0x0f0f, + ModRM_0x0f12, + ModRM_0x0f16, + ModRM_0x0f18, + ModRM_0x0f71, + ModRM_0x0f72, + ModRM_0x0f73, + ModRM_0x0fae, + ModRM_0x0fba, + ModRM_0x0fc7, + ModRM_0x660f78, + ModRM_0xf20f78, + ModRM_0xf30f1e, + ModRM_0xf30f38d8, + ModRM_0xf30f38dc, + ModRM_0xf30f38dd, + ModRM_0xf30f38de, + ModRM_0xf30f38df, + ModRM_0xf30f38fa, + ModRM_0xf30f38fb, + ModRM_0xf30f3af0, +} + +#[allow(non_camel_case_types)] #[repr(u16)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum OperandCode { - 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(), + Ivs = OperandCodeBuilder::new().operand_case(OperandCase::Ivs).bits(), + I_3 = OperandCodeBuilder::new().operand_case(OperandCase::I_3).bits(), + Nothing = OperandCodeBuilder::new().operand_case(OperandCase::Nothing).bits(), + Ib = OperandCodeBuilder::new().operand_case(OperandCase::Ib).bits(), + Ibs = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Ibs).bits(), + Jvds = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Jvds).bits(), + Yv_Xv = OperandCodeBuilder::new().operand_case(OperandCase::Yv_Xv).bits(), + + x87_d8 = OperandCodeBuilder::new().operand_case(OperandCase::x87_d8).bits(), + x87_d9 = OperandCodeBuilder::new().operand_case(OperandCase::x87_d9).bits(), + x87_da = OperandCodeBuilder::new().operand_case(OperandCase::x87_da).bits(), + x87_db = OperandCodeBuilder::new().operand_case(OperandCase::x87_db).bits(), + x87_dc = OperandCodeBuilder::new().operand_case(OperandCase::x87_dc).bits(), + x87_dd = OperandCodeBuilder::new().operand_case(OperandCase::x87_dd).bits(), + x87_de = OperandCodeBuilder::new().operand_case(OperandCase::x87_de).bits(), + x87_df = OperandCodeBuilder::new().operand_case(OperandCase::x87_df).bits(), Eb_R0 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(0) + .operand_case(OperandCase::SingleMMMOper) .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_0x0f0f = OperandCodeBuilder::new().read_modrm().special_case(65).bits(), // 3dnow - 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_0xf30f38d8 = OperandCodeBuilder::new().read_modrm().special_case(45).bits(), - ModRM_0xf30f38dc = OperandCodeBuilder::new().read_modrm().special_case(46).bits(), - ModRM_0xf30f38dd = OperandCodeBuilder::new().read_modrm().special_case(47).bits(), - ModRM_0xf30f38de = OperandCodeBuilder::new().read_modrm().special_case(48).bits(), - ModRM_0xf30f38df = OperandCodeBuilder::new().read_modrm().special_case(49).bits(), - ModRM_0xf30f38fa = OperandCodeBuilder::new().read_modrm().special_case(50).bits(), - ModRM_0xf30f38fb = OperandCodeBuilder::new().read_modrm().special_case(51).bits(), - ModRM_0xf30f3af0 = OperandCodeBuilder::new().read_modrm().special_case(52).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_0xf20f78 = OperandCodeBuilder::new().read_modrm().special_case(58).bits(), - ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().special_case(59).bits(), - ModRM_0xf30f1e = OperandCodeBuilder::new().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(66).bits(), - ModRM_0xc5 = OperandCodeBuilder::new().read_modrm().special_case(67).bits(), + AL_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AL_Ib).bits(), + AX_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ib).bits(), + Ib_AL = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AL).bits(), + Ib_AX = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AX).bits(), + AX_DX = OperandCodeBuilder::new().operand_case(OperandCase::AX_DX).bits(), + AL_DX = OperandCodeBuilder::new().operand_case(OperandCase::AL_DX).bits(), + DX_AX = OperandCodeBuilder::new().operand_case(OperandCase::DX_AX).bits(), + DX_AL = OperandCodeBuilder::new().operand_case(OperandCase::DX_AL).bits(), + MOVQ_f30f = OperandCodeBuilder::new().read_E().operand_case(OperandCase::MOVQ_f30f).bits(), + +// Unsupported = OperandCodeBuilder::new().operand_case(49).bits(), + + ModRM_0x0f00 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0f00).bits(), + ModRM_0x0f01 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0f01).bits(), + ModRM_0x0f0d = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f0d).bits(), + ModRM_0x0f0f = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f0f).bits(), // 3dnow + ModRM_0x0fae = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0fae).bits(), + ModRM_0x0fba = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0fba).bits(), +// ModRM_0xf30fae = OperandCodeBuilder::new().read_modrm().operand_case(46).bits(), +// ModRM_0x660fae = OperandCodeBuilder::new().read_modrm().operand_case(47).bits(), +// ModRM_0xf30fc7 = OperandCodeBuilder::new().read_modrm().operand_case(48).bits(), +// ModRM_0x660f38 = OperandCodeBuilder::new().read_modrm().operand_case(49).bits(), +// ModRM_0xf20f38 = OperandCodeBuilder::new().read_modrm().operand_case(50).bits(), +// ModRM_0xf30f38 = OperandCodeBuilder::new().read_modrm().operand_case(51).bits(), + ModRM_0xf30f38d8 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38d8).bits(), + ModRM_0xf30f38dc = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38dc).bits(), + ModRM_0xf30f38dd = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38dd).bits(), + ModRM_0xf30f38de = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38de).bits(), + ModRM_0xf30f38df = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38df).bits(), + ModRM_0xf30f38fa = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38fa).bits(), + ModRM_0xf30f38fb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38fb).bits(), + ModRM_0xf30f3af0 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f3af0).bits(), +// ModRM_0x660f3a = OperandCodeBuilder::new().read_modrm().operand_case(52).bits(), +// ModRM_0x0f38 = OperandCodeBuilder::new().read_modrm().operand_case(53).bits(), +// ModRM_0x0f3a = OperandCodeBuilder::new().read_modrm().operand_case(54).bits(), + ModRM_0x0f71 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f71).bits(), + ModRM_0x0f72 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f72).bits(), + ModRM_0x0f73 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0x0f73).bits(), + ModRM_0xf20f78 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf20f78).bits(), + ModRM_0x660f78 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x660f78).bits(), + ModRM_0xf30f1e = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xf30f1e).bits(), +// ModRM_0x660f72 = OperandCodeBuilder::new().read_modrm().operand_case(61).bits(), +// ModRM_0x660f73 = OperandCodeBuilder::new().read_modrm().operand_case(62).bits(), +// ModRM_0x660fc7 = OperandCodeBuilder::new().read_modrm().operand_case(63).bits(), + ModRM_0x0fc7 = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0x0fc7).bits(), // xmmword? ModRM_0x0f12 = OperandCodeBuilder::new() .read_modrm() - .op0_is_rrr_and_embedded_instructions() .read_E() .reg_mem() - .operand_case(65) + .operand_case(OperandCase::ModRM_0x0f12) .bits(), // xmmword? ModRM_0x0f16 = OperandCodeBuilder::new() .read_modrm() - .op0_is_rrr_and_embedded_instructions() .read_E() .reg_mem() - .operand_case(66) + .operand_case(OperandCase::ModRM_0x0f16) .bits(), // encode immediates? ModRM_0xc0_Eb_Ib = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(5) + .operand_case(OperandCase::BitwiseWithI8) .bits(), ModRM_0xc1_Ev_Ib = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(6) + .operand_case(OperandCase::BitwiseWithI8) .bits(), ModRM_0xd0_Eb_1 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(7) + .operand_case(OperandCase::ShiftBy1_b) .bits(), ModRM_0xd1_Ev_1 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(8) + .operand_case(OperandCase::ShiftBy1_v) .bits(), ModRM_0xd2_Eb_CL = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(9) + .operand_case(OperandCase::BitwiseByCL) .bits(), ModRM_0xd3_Ev_CL = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(10) + .operand_case(OperandCase::BitwiseByCL) .bits(), ModRM_0x80_Eb_Ib = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .with_imm(false, 0) .byte_operands() - .operand_case(1) + .operand_case(OperandCase::BaseOpWithI8) .bits(), ModRM_0x83_Ev_Ibs = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .with_imm(false, 0) - .operand_case(26) + .operand_case(OperandCase::ModRM_0x83) .bits(), // this would be Eb_Ivs, 0x8e ModRM_0x81_Ev_Ivs = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(2) + .operand_case(OperandCase::BaseOpWithIv) .bits(), ModRM_0xc6_Eb_Ib = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(3) + .operand_case(OperandCase::MovI8) .bits(), ModRM_0xc7_Ev_Iv = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(4) + .operand_case(OperandCase::MovIv) .bits(), ModRM_0xfe_Eb = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(13) + .operand_case(OperandCase::ModRM_0xfe) .bits(), ModRM_0x8f_Ev = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(30) + .operand_case(OperandCase::ModRM_0x8f) .bits(), // gap, 0x94 ModRM_0xff_Ev = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(14) + .operand_case(OperandCase::ModRM_0xff) .bits(), ModRM_0x0f18 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(58) + .operand_case(OperandCase::ModRM_0x0f18) .bits(), ModRM_0xf6 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() .byte_operands() - .operand_case(11) + .operand_case(OperandCase::ModRM_0xf6) .bits(), ModRM_0xf7 = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(12) + .operand_case(OperandCase::ModRM_0xf7) .bits(), Ev = OperandCodeBuilder::new() .read_modrm() - .set_embedded_instructions() .read_E() - .operand_case(18) + .operand_case(OperandCase::SingleMMMOper) .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(), @@ -5147,7 +5239,7 @@ enum OperandCode { 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_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 0).bits(), 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(), @@ -5171,126 +5263,106 @@ enum OperandCode { 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_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(51).bits(), - Md_Gd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(52).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_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(22).bits(), - G_E_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(60).bits(), - G_U_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(61).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(), - MOVDIR64B = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(108).bits(), - M_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(109).bits(), - Gv_Ev_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).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(), + Gv_Eb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Eb).bits(), + Gv_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew).bits(), + Gv_Ew_LSL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(), +// Gdq_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ed).bits(), + Gd_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ed).bits(), + Md_Gd = OperandCodeBuilder::new().read_E().mem_reg().deny_regmmm().operand_case(OperandCase::Md_Gd).bits(), +// Edq_Gdq = OperandCodeBuilder::new().read_E().operand_case(49).bits(), + Gd_Ev = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ev).bits(), +// Md_Gd = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Md_Gd).bits(), + G_E_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_xmm_Ib).bits(), + G_E_xmm_Ub = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_xmm_Ub).bits(), + G_U_xmm_Ub = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_U_xmm_Ub).bits(), + AL_Ob = OperandCodeBuilder::new().operand_case(OperandCase::AL_Ob).bits(), + AL_Xb = OperandCodeBuilder::new().operand_case(OperandCase::AL_Xb).bits(), + AX_Ov = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ov).bits(), + AL_Ibs = OperandCodeBuilder::new().byte_operands().operand_case(OperandCase::AL_Ibs).bits(), + AX_Ivd = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ivd).bits(), + + Eb_Gb = OperandCodeBuilder::new().read_E().byte_operands().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(), + Ev_Gv = OperandCodeBuilder::new().read_E().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(), + Gb_Eb = OperandCodeBuilder::new().read_E().byte_operands().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(), + Gv_Ev = OperandCodeBuilder::new().read_E().only_modrm_operands().reg_mem().operand_case(OperandCase::Internal).bits(), + Gv_M = OperandCodeBuilder::new().read_E().only_modrm_operands().reg_mem().deny_regmmm().operand_case(OperandCase::Gv_M).bits(), + MOVDIR64B = OperandCodeBuilder::new().read_E().reg_mem().deny_regmmm().operand_case(OperandCase::MOVDIR64B).bits(), + M_Gv = OperandCodeBuilder::new().read_E().only_modrm_operands().mem_reg().deny_regmmm().operand_case(OperandCase::Internal).bits(), + Gv_Ev_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Ib).bits(), + Gv_Ev_Iv = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Iv).bits(), + Rv_Gmm_Ib = OperandCodeBuilder::new().read_modrm().read_E().reg_mem().operand_case(OperandCase::Rv_Gmm_Ib).bits(), // gap, 0x9a - 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(), + G_xmm_E_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_E_mm).bits(), + G_xmm_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_U_mm).bits(), + G_mm_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_U_xmm).bits(), + G_xmm_Ed = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ed).bits(), + G_mm_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_E_xmm).bits(), + Gd_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gd_U_xmm).bits(), + Gv_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::Gv_E_xmm).bits(), //= 0x816f, // mirror G_xmm_Ed, but also read an immediate - G_xmm_Ew_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(), - G_Ed_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(31).bits(), - Ed_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(29).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(), - Ed_G_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(67).bits(), - // Ed_G_xmm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().mem_reg().operand_case(68).bits(), - G_mm_Ed = 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_Mq_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_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(76).bits(), - E_G_q = 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(), - ES = OperandCodeBuilder::new().special_case(103).bits(), - CS = OperandCodeBuilder::new().special_case(104).bits(), - SS = OperandCodeBuilder::new().special_case(105).bits(), - DS = OperandCodeBuilder::new().special_case(106).bits(), - ModRM_0x62 = OperandCodeBuilder::new().special_case(107).bits(), - INV_Gv_M = OperandCodeBuilder::new().special_case(108).bits(), - PMOVX_G_E_xmm = OperandCodeBuilder::new().operand_case(109).bits(), - PMOVX_E_G_xmm = OperandCodeBuilder::new().operand_case(110).bits(), - G_Ev_xmm_Ib = OperandCodeBuilder::new().operand_case(111).bits(), - G_E_mm_Ib = OperandCodeBuilder::new().operand_case(112).bits(), - AbsFar = OperandCodeBuilder::new().operand_case(113).bits(), + G_xmm_Ew_Ib = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_xmm_Ew_Ib).bits(), + G_U_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_U_xmm).bits(), + G_M_xmm = OperandCodeBuilder::new().read_E().reg_mem().deny_regmmm().operand_case(OperandCase::G_M_xmm).bits(), + G_E_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_E_xmm).bits(), + E_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::E_G_xmm).bits(), + G_Ed_xmm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_Ed_xmm).bits(), + Ed_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Ed_G_xmm).bits(), + M_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().deny_regmmm().operand_case(OperandCase::M_G_xmm).bits(), + G_E_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_E_mm).bits(), + G_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_U_mm).bits(), + E_G_mm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::E_G_mm).bits(), + Ed_G_mm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Ed_G_mm).bits(), + // Edq_G_xmm = OperandCodeBuilder::new().read_E().mem_reg().operand_case(OperandCase::Edq_G_xmm).bits(), + G_mm_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_mm_Ed).bits(), + G_mm_E = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_mm_E).bits(), + Ev_Gv_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ev_Gv_Ib).bits(), + Ev_Gv_CL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ev_Gv_CL).bits(), + G_mm_U_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_mm_U_mm).bits(), + G_Mq_mm = OperandCodeBuilder::new().read_E().reg_mem().operand_case(OperandCase::G_Mq_mm).bits(), + G_mm_Ew_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_mm_Ew_Ib).bits(), + G_E_q = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_q).bits(), + E_G_q = OperandCodeBuilder::new().read_E().operand_case(OperandCase::E_G_q).bits(), + CVT_AA = OperandCodeBuilder::new().operand_case(OperandCase::CVT_AA).bits(), + CVT_DA = OperandCodeBuilder::new().operand_case(OperandCase::CVT_DA).bits(), + Rq_Cq_0 = OperandCodeBuilder::new().operand_case(OperandCase::Rq_Cq_0).bits(), + Rq_Dq_0 = OperandCodeBuilder::new().operand_case(OperandCase::Rq_Dq_0).bits(), + Cq_Rq_0 = OperandCodeBuilder::new().operand_case(OperandCase::Cq_Rq_0).bits(), + Dq_Rq_0 = OperandCodeBuilder::new().operand_case(OperandCase::Dq_Rq_0).bits(), + FS = OperandCodeBuilder::new().operand_case(OperandCase::FS).bits(), + GS = OperandCodeBuilder::new().operand_case(OperandCase::GS).bits(), + Yb_DX = OperandCodeBuilder::new().operand_case(OperandCase::Yb_DX).bits(), + Yv_DX = OperandCodeBuilder::new().operand_case(OperandCase::Yv_DX).bits(), + DX_Xb = OperandCodeBuilder::new().operand_case(OperandCase::DX_Xb).bits(), + DX_Xv = OperandCodeBuilder::new().operand_case(OperandCase::DX_Xv).bits(), + AH = OperandCodeBuilder::new().operand_case(OperandCase::AH).bits(), + AX_Xv = OperandCodeBuilder::new().operand_case(OperandCase::AX_Xv).bits(), + Ew_Sw = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Ew_Sw).bits(), + Fw = OperandCodeBuilder::new().operand_case(OperandCase::Fw).bits(), + I_1 = OperandCodeBuilder::new().operand_case(OperandCase::I_1).bits(), + Iw = OperandCodeBuilder::new().operand_case(OperandCase::Iw).bits(), + Iw_Ib = OperandCodeBuilder::new().operand_case(OperandCase::Iw_Ib).bits(), + Ob_AL = OperandCodeBuilder::new().operand_case(OperandCase::Ob_AL).bits(), + Ov_AX = OperandCodeBuilder::new().operand_case(OperandCase::Ov_AX).bits(), + Sw_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Sw_Ew).read_E().bits(), + Yb_AL = OperandCodeBuilder::new().operand_case(OperandCase::Yb_AL).bits(), + Yb_Xb = OperandCodeBuilder::new().operand_case(OperandCase::Yb_Xb).bits(), + Yv_AX = OperandCodeBuilder::new().operand_case(OperandCase::Yv_AX).bits(), + Ew_Gw = OperandCodeBuilder::new().operand_case(OperandCase::Ew_Gw).bits(), + ES = OperandCodeBuilder::new().operand_case(OperandCase::ES).bits(), + CS = OperandCodeBuilder::new().operand_case(OperandCase::CS).bits(), + SS = OperandCodeBuilder::new().operand_case(OperandCase::SS).bits(), + DS = OperandCodeBuilder::new().operand_case(OperandCase::DS).bits(), + ModRM_0x62 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0x62).bits(), + INV_Gv_M = OperandCodeBuilder::new().read_E().deny_regmmm().operand_case(OperandCase::INV_Gv_M).bits(), + PMOVX_G_E_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_G_E_xmm).bits(), + PMOVX_E_G_xmm = OperandCodeBuilder::new().read_E().operand_case(OperandCase::PMOVX_E_G_xmm).bits(), + G_Ev_xmm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_Ev_xmm_Ib).bits(), + G_E_mm_Ib = OperandCodeBuilder::new().read_E().operand_case(OperandCase::G_E_mm_Ib).bits(), + AbsFar = OperandCodeBuilder::new().operand_case(OperandCase::AbsFar).bits(), + ModRM_0xc4 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc4).bits(), + ModRM_0xc5 = OperandCodeBuilder::new().operand_case(OperandCase::ModRM_0xc5).bits(), } -const LOCKABLE_INSTRUCTIONS: &[Opcode] = &[ - Opcode::ADD, - Opcode::ADC, - Opcode::AND, - Opcode::BTC, - Opcode::BTR, - Opcode::BTS, - Opcode::CMPXCHG, - Opcode::CMPXCHG8B, - Opcode::DEC, - Opcode::INC, - Opcode::NEG, - Opcode::NOT, - Opcode::OR, - Opcode::SBB, - Opcode::SUB, - Opcode::XOR, - Opcode::XADD, - Opcode::XCHG, -]; - fn base_opcode_map(v: u8) -> Opcode { match v { 0 => Opcode::ADD, @@ -5305,16 +5377,19 @@ fn base_opcode_map(v: u8) -> Opcode { } } -const BITWISE_OPCODE_MAP: [Opcode; 8] = [ - Opcode::ROL, - Opcode::ROR, - Opcode::RCL, - Opcode::RCR, - Opcode::SHL, - Opcode::SHR, - Opcode::SAL, - Opcode::SAR -]; +fn bitwise_opcode_map(v: u8) -> Opcode { + match v { + 0 => Opcode::ROL, + 1 => Opcode::ROR, + 2 => Opcode::RCL, + 3 => Opcode::RCR, + 4 => Opcode::SHL, + 5 => Opcode::SHR, + 6 => Opcode::SAL, + 7 => Opcode::SAR, + _ => { unsafe { unreachable_unchecked() } } + } +} #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Interpretation { @@ -5324,316 +5399,316 @@ enum Interpretation { #[derive(Copy, Clone, Debug, PartialEq)] // this should be a 32-byte struct.. -struct OpcodeRecord(Interpretation, OperandCode); +struct OpcodeRecord(u64); //Interpretation, u32); // OperandCode); -#[test] -fn opcode_record_size() { - // there are more than 256 opcodes... - assert_eq!(core::mem::size_of::(), 4); +impl OpcodeRecord { + const fn new(interp: Interpretation, code: OperandCode) -> Self { + let interp_bits = unsafe { core::mem::transmute::(interp) as u64 }; + let code_bits = code as u16 as u64; + let stored_bits = interp_bits | (code_bits << 32); + OpcodeRecord(stored_bits) + } + + const fn interp(&self) -> Interpretation { + unsafe { core::mem::transmute(self.0 as u32) } + } + + const fn operand(&self) -> OperandCode { + unsafe { core::mem::transmute((self.0 >> 32) as u16) } + } } const OPCODES: [OpcodeRecord; 256] = [ - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::ES), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::ES), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::OR), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::CS), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::ADC), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::SS), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::SS), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::SBB), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::DS), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::DS), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::AND), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::DAA), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::SUB), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::DAS), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::XOR), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::AAA), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::CMP), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::AAS), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADD), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::ES), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::ES), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OR), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::CS), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ADC), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::SS), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::SS), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SBB), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::DS), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::DS), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AND), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DAA), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SUB), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DAS), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XOR), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AAA), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMP), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AAS), OperandCode::Nothing), // 0x40: - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INC), OperandCode::Zv_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::DEC), OperandCode::Zv_R7), // 0x50: - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Zv_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POP), OperandCode::Zv_R7), // 0x60 - OpcodeRecord(Interpretation::Instruction(Opcode::PUSHA), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::POPA), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::BOUND), OperandCode::ModRM_0x62), - OpcodeRecord(Interpretation::Instruction(Opcode::ARPL), OperandCode::Ew_Gw), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ivs), - OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Iv), - OpcodeRecord(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yb_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::INS), OperandCode::Yv_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSHA), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POPA), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::BOUND), OperandCode::ModRM_0x62), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ARPL), OperandCode::Ew_Gw), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ivs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Iv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSH), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IMUL), OperandCode::Gv_Ev_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INS), OperandCode::Yb_DX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INS), OperandCode::Yv_DX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUTS), OperandCode::DX_Xv), // 0x70 - OpcodeRecord(Interpretation::Instruction(Opcode::JO), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNO), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JB), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNB), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JZ), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNZ), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNA), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JA), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JS), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNS), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JP), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JNP), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JL), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JGE), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JLE), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::JG), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JO), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNO), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JB), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNB), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JZ), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNZ), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNA), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JA), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JS), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNS), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JP), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JNP), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JL), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JGE), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JLE), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JG), OperandCode::Ibs), // 0x80 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x80_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x81_Ev_Ivs), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x83_Ev_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Eb_Gb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ev_Gv), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gb_Eb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Gv_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ew_Sw), - OpcodeRecord(Interpretation::Instruction(Opcode::LEA), OperandCode::Gv_M), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Sw_Ew), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x8f_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_AA), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_DA), - OpcodeRecord(Interpretation::Instruction(Opcode::CALLF), OperandCode::AbsFar), - 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), - OpcodeRecord(Interpretation::Instruction(Opcode::LAHF), OperandCode::AH), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AL_Ob), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::AX_Ov), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ob_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Ov_AX), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yb_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yv_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yb_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yv_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AL_Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::AX_Ivd), - OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yb_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::STOS), OperandCode::Yv_AX), - OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AL_Xb), - OpcodeRecord(Interpretation::Instruction(Opcode::LODS), OperandCode::AX_Xv), - OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yb_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yv_AX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x80_Eb_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x81_Ev_Ivs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x83_Ev_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::TEST), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::TEST), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Eb_Gb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Ev_Gv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Gb_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Gv_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Ew_Sw), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LEA), OperandCode::Gv_M), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Sw_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x8f_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::NOP), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_AA), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::CVT_DA), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CALLF), OperandCode::AbsFar), + OpcodeRecord::new(Interpretation::Instruction(Opcode::WAIT), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::PUSHF), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::POPF), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SAHF), OperandCode::AH), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAHF), OperandCode::AH), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::AL_Ob), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::AX_Ov), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Ob_AL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Ov_AX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yb_Xb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVS), OperandCode::Yv_Xv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yb_Xb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMPS), OperandCode::Yv_Xv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::TEST), OperandCode::AL_Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::TEST), OperandCode::AX_Ivd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::STOS), OperandCode::Yb_AL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::STOS), OperandCode::Yv_AX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LODS), OperandCode::AL_Xb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LODS), OperandCode::AX_Xv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yb_AL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SCAS), OperandCode::Yv_AX), // 0xb0 - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R7), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R0), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R1), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R2), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R3), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R4), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R5), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R6), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zb_Ib_R7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R0), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R2), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::Zv_Iv_R7), // 0xc0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc0_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw), - OpcodeRecord(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::LES), OperandCode::ModRM_0xc4), - OpcodeRecord(Interpretation::Instruction(Opcode::LDS), OperandCode::ModRM_0xc5), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv), - OpcodeRecord(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::LEAVE), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Iw), - OpcodeRecord(Interpretation::Instruction(Opcode::RETF), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::I_3), - OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::INTO), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::IRET), OperandCode::Fw), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc0_Eb_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xc1_Ev_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::RETURN), OperandCode::Iw), + OpcodeRecord::new(Interpretation::Instruction(Opcode::RETURN), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LES), OperandCode::ModRM_0xc4), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LDS), OperandCode::ModRM_0xc5), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc6_Eb_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::MOV), OperandCode::ModRM_0xc7_Ev_Iv), + OpcodeRecord::new(Interpretation::Instruction(Opcode::ENTER), OperandCode::Iw_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LEAVE), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::RETF), OperandCode::Iw), + OpcodeRecord::new(Interpretation::Instruction(Opcode::RETF), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INT), OperandCode::I_3), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INT), OperandCode::Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INTO), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IRET), OperandCode::Fw), // 0xd0 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd0_Eb_1), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd1_Ev_1), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd2_Eb_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd3_Ev_CL), - OpcodeRecord(Interpretation::Instruction(Opcode::AAM), OperandCode::Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::AAD), OperandCode::Ib), - OpcodeRecord(Interpretation::Instruction(Opcode::SALC), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd0_Eb_1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd1_Ev_1), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd2_Eb_CL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xd3_Ev_CL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AAM), OperandCode::Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::AAD), OperandCode::Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::SALC), OperandCode::Nothing), // XLAT - OpcodeRecord(Interpretation::Instruction(Opcode::XLAT), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::XLAT), OperandCode::Nothing), // x86 d8 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d8), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d8), // x86 d9 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d9), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_d9), // x86 da - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_da), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_da), // x86 db - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_db), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_db), // x86 dc - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dc), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dc), // x86 dd - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dd), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_dd), // x86 de - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_de), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_de), // x86 df - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_df), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::x87_df), // 0xe0 - 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::JCXZ), 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), - OpcodeRecord(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOPNZ), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOPZ), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LOOP), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JCXZ), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AL_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AX_Ib), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUT), OperandCode::Ib_AX), // 0xe8 - OpcodeRecord(Interpretation::Instruction(Opcode::CALL), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Jvds), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::JMP), OperandCode::Ibs), - OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AL_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::IN), OperandCode::AX_DX), - OpcodeRecord(Interpretation::Instruction(Opcode::OUT), OperandCode::DX_AL), - OpcodeRecord(Interpretation::Instruction(Opcode::OUT), OperandCode::DX_AX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CALL), OperandCode::Jvds), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JMP), OperandCode::Jvds), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::JMP), OperandCode::Ibs), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AL_DX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::IN), OperandCode::AX_DX), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUT), OperandCode::DX_AL), + OpcodeRecord::new(Interpretation::Instruction(Opcode::OUT), OperandCode::DX_AX), // 0xf0 - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), // ICEBP? - OpcodeRecord(Interpretation::Instruction(Opcode::INT), OperandCode::I_1), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), - OpcodeRecord(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::INT), OperandCode::I_1), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Prefix, OperandCode::Nothing), // 0xf4 - OpcodeRecord(Interpretation::Instruction(Opcode::HLT), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::HLT), OperandCode::Nothing), // CMC - 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), - OpcodeRecord(Interpretation::Instruction(Opcode::STC), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CLI), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::STI), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::CLD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::STD), OperandCode::Nothing), - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xfe_Eb), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CMC), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf6), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf7), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CLC), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::STC), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CLI), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::STI), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::CLD), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::STD), OperandCode::Nothing), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xfe_Eb), // TODO: test 0xff /3 - OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xff_Ev), + OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xff_Ev), ]; #[allow(non_snake_case)] +#[inline(always)] pub(self) fn read_E< T: Reader<::Address, ::Word>, S: DescriptionSink, ->(words: &mut T, instr: &mut Instruction, modrm: u8, width: u8, sink: &mut S) -> Result { - if modrm >= 0b11000000 { - let bank = width_to_gp_reg_bank(width); - read_modrm_reg(instr, modrm, bank) - } else { - read_M(words, instr, modrm, sink) - } -} -#[allow(non_snake_case)] -pub(self) fn read_E_mm< - T: Reader<::Address, ::Word>, - S: DescriptionSink, ->(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result { +>(words: &mut T, instr: &mut Instruction, modrm: u8, bank: RegisterBank, sink: &mut S) -> Result { if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::MM) + read_modrm_reg(instr, words, modrm, bank, sink) } else { read_M(words, instr, modrm, sink) } @@ -5644,7 +5719,8 @@ pub(self) fn read_E_st< S: DescriptionSink, >(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result { if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::ST) + instr.regs[1] = RegSpec { bank: RegisterBank::ST, num: modrm & 7 }; + Ok(OperandSpec::RegMMM) } else { read_M(words, instr, modrm, sink) } @@ -5655,7 +5731,7 @@ pub(self) fn read_E_xmm< S: DescriptionSink, >(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result { if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::X) + read_modrm_reg(instr, words, modrm, RegisterBank::X, sink) } else { read_M(words, instr, modrm, sink) } @@ -5666,7 +5742,7 @@ pub(self) fn read_E_ymm< S: DescriptionSink, >(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result { if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, RegisterBank::Y) + read_modrm_reg(instr, words, modrm, RegisterBank::Y, sink) } else { read_M(words, instr, modrm, sink) } @@ -5677,7 +5753,7 @@ pub(self) fn read_E_vex< S: DescriptionSink, >(words: &mut T, instr: &mut Instruction, modrm: u8, bank: RegisterBank, sink: &mut S) -> Result { if modrm >= 0b11000000 { - read_modrm_reg(instr, modrm, bank) + read_modrm_reg(instr, words, modrm, bank, sink) } else { let res = read_M(words, instr, modrm, sink)?; if (modrm & 0b01_000_000) == 0b01_000_000 { @@ -5688,8 +5764,18 @@ pub(self) fn read_E_vex< } #[allow(non_snake_case)] -fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result { +#[inline(always)] +fn read_modrm_reg< + T: Reader<::Address, ::Word>, + S: DescriptionSink, +>(instr: &mut Instruction, words: &mut T, modrm: u8, reg_bank: RegisterBank, sink: &mut S) -> Result { instr.regs[1] = RegSpec::from_parts(modrm & 7, reg_bank); + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 6, + InnerDescription::RegisterNumber("mmm", modrm & 7, instr.regs[1]) + .with_id(words.offset() as u32 * 8 - 8 + 2) + ); Ok(OperandSpec::RegMMM) } @@ -5697,12 +5783,12 @@ fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> fn read_sib_disp< T: Reader<::Address, ::Word>, S: DescriptionSink, ->(instr: &Instruction, words: &mut T, modbits: u8, sibbyte: u8, sink: &mut S) -> Result { +>(instr: &Instruction, words: &mut T, modrm: u8, sibbyte: u8, sink: &mut S) -> Result { let sib_start = words.offset() as u32 * 8 - 8; let modbit_addr = words.offset() as u32 * 8 - 10; let disp_start = words.offset() as u32 * 8; - let disp = if modbits == 0b00 { + let disp = if modrm < 0b01_000_000 { // modbits == 0b00 if (sibbyte & 7) == 0b101 { sink.record(modbit_addr, modbit_addr + 1, InnerDescription::Misc("4-byte displacement").with_id(sib_start + 0)); @@ -5715,7 +5801,7 @@ fn read_sib_disp< } else { 0 } - } else if modbits == 0b01 { + } else if modrm < 0b10_000_000 { // modbits == 0b01 sink.record(modbit_addr, modbit_addr + 1, InnerDescription::Misc("1-byte displacement").with_id(sib_start + 0)); if instr.prefixes.evex().is_some() { @@ -5748,83 +5834,116 @@ fn read_sib< let modrm_start = words.offset() as u32 * 8 - 8; let sib_start = words.offset() as u32 * 8; - let modbits = modrm >> 6; let sibbyte = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; + let disp = read_sib_disp(instr, words, modrm, sibbyte, sink)?; + instr.disp = disp as u32; + instr.regs[1].num |= sibbyte & 7; instr.regs[2].num |= (sibbyte >> 3) & 7; - let disp = read_sib_disp(instr, words, modbits, sibbyte, sink)?; - instr.disp = disp as u32; - let scale = 1u8 << (sibbyte >> 6); instr.scale = scale; - let op_spec = if (sibbyte & 7) == 0b101 { - sink.record( - sib_start, - sib_start + 2, - InnerDescription::Misc("bbb selects displacement in address") - .with_id(sib_start + 0) - ); - if ((sibbyte >> 3) & 7) == 0b100 { + let op_spec = if disp == 0 { + if (sibbyte & 7) == 0b101 { sink.record( - sib_start + 3, - sib_start + 5, - InnerDescription::Misc("iii selects no index register") + sib_start, + sib_start + 2, + InnerDescription::Misc("bbb selects displacement in address, but displacement is 0") .with_id(sib_start + 0) ); - if modbits == 0b00 { + if instr.regs[2].num == 0b0100 { sink.record( - modrm_start + 6, - modrm_start + 7, - InnerDescription::Misc("mod bits select no base register, absolute [disp32] only") + sib_start + 3, + sib_start + 5, + InnerDescription::Misc("iii selects no index register") .with_id(sib_start + 0) ); - OperandSpec::DispU32 + if modrm < 0b01_000_000 { + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::Misc("mod bits select no base register, absolute [disp32] only") + .with_id(sib_start + 0) + ); + OperandSpec::DispU32 + } else { + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) + .with_id(sib_start + 0) + ); + OperandSpec::Deref + } } else { sink.record( - modrm_start + 6, - modrm_start + 7, - InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) + sib_start + 3, + sib_start + 5, + InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) .with_id(sib_start + 0) ); - instr.regs[1].num |= 0b101; - - if disp == 0 { + if modrm < 0b01_000_000 { sink.record( - sib_start, - sib_start + 2, - InnerDescription::Misc("memory access is [rbp + disp] but displacement is 0") + modrm_start + 6, + modrm_start + 7, + InnerDescription::Misc("mod bits select no base register") .with_id(sib_start + 0) ); - OperandSpec::Deref + OperandSpec::RegScale } else { - OperandSpec::RegDisp + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) + .with_id(sib_start + 0) + ); + OperandSpec::RegIndexBaseScale } } } else { - instr.regs[1].num |= 0b101; - instr.regs[2].num |= (sibbyte >> 3) & 7; + if instr.regs[2].num == 0b0100 { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::Misc("iii selects no index register") + .with_id(sib_start + 0) + ); + OperandSpec::Deref + } else { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) + .with_id(sib_start + 0) + ); + OperandSpec::RegIndexBaseScale + } + } + } else { + if (sibbyte & 7) == 0b101 { sink.record( - sib_start + 3, - sib_start + 5, - InnerDescription::RegisterNumber("iii", instr.regs[2].num & 0b111, instr.regs[2]) + sib_start, + sib_start + 2, + InnerDescription::Misc("bbb selects displacement in address") .with_id(sib_start + 0) ); - - let scale = 1u8 << (sibbyte >> 6); - instr.scale = scale; - - if disp == 0 { - if modbits == 0 { + if instr.regs[2].num == 0b0100 { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::Misc("iii selects no index register") + .with_id(sib_start + 0) + ); + if modrm < 0b01_000_000 { sink.record( modrm_start + 6, modrm_start + 7, - InnerDescription::Misc("mod bits select no base register, [index+disp] only, but displacement is 0") + InnerDescription::Misc("mod bits select no base register, absolute [disp32] only") .with_id(sib_start + 0) ); - OperandSpec::RegScale + OperandSpec::DispU32 } else { sink.record( modrm_start + 6, @@ -5832,10 +5951,16 @@ fn read_sib< InnerDescription::RegisterNumber("mod", 0b101, instr.regs[1]) .with_id(sib_start + 0) ); - OperandSpec::RegIndexBaseScale + OperandSpec::RegDisp } } else { - if modbits == 0 { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) + .with_id(sib_start + 0) + ); + if modrm < 0b01_000_000 { sink.record( modrm_start + 6, modrm_start + 7, @@ -5853,42 +5978,28 @@ fn read_sib< OperandSpec::RegIndexBaseScaleDisp } } - } - } else { - instr.regs[1].num |= sibbyte & 7; - sink.record( - sib_start + 0, - sib_start + 2, - InnerDescription::RegisterNumber("bbb", instr.regs[1].num & 0b111, instr.regs[2]) - .with_id(sib_start + 0) - ); - - if ((sibbyte >> 3) & 7) == 0b100 { - sink.record( - sib_start + 3, - sib_start + 5, - InnerDescription::Misc("iii selects no index register") - .with_id(sib_start + 0) - ); - if disp == 0 { - OperandSpec::Deref - } else { - OperandSpec::RegDisp - } } else { - instr.regs[2].num |= (sibbyte >> 3) & 7; sink.record( - sib_start + 3, - sib_start + 5, - InnerDescription::RegisterNumber("iii", instr.regs[2].num & 0b111, instr.regs[2]) + sib_start + 0, + sib_start + 2, + InnerDescription::RegisterNumber("bbb", instr.regs[1].num, instr.regs[2]) .with_id(sib_start + 0) ); - - let scale = 1u8 << (sibbyte >> 6); - instr.scale = scale; - if disp == 0 { - OperandSpec::RegIndexBaseScale + if instr.regs[2].num == 0b0100 { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::Misc("iii selects no index register") + .with_id(sib_start + 0) + ); + OperandSpec::RegDisp } else { + sink.record( + sib_start + 3, + sib_start + 5, + InnerDescription::RegisterNumber("iii", instr.regs[2].num, instr.regs[2]) + .with_id(sib_start + 0) + ); OperandSpec::RegIndexBaseScaleDisp } } @@ -5998,7 +6109,8 @@ fn read_M_16bit< if mmm > 3 { Ok(OperandSpec::Deref) } else { - Ok(OperandSpec::RegIndexBase) + instr.scale = 1; + Ok(OperandSpec::RegIndexBaseScale) } }, 0b01 => { @@ -6024,11 +6136,8 @@ fn read_M_16bit< Ok(OperandSpec::Deref) } } else { - if instr.disp != 0 { - Ok(OperandSpec::RegIndexBaseDisp) - } else { - Ok(OperandSpec::RegIndexBase) - } + instr.scale = 1; + Ok(OperandSpec::RegIndexBaseScaleDisp) } }, 0b10 => { @@ -6054,11 +6163,8 @@ fn read_M_16bit< Ok(OperandSpec::Deref) } } else { - if instr.disp != 0 { - Ok(OperandSpec::RegIndexBaseDisp) - } else { - Ok(OperandSpec::RegIndexBase) - } + instr.scale = 1; + Ok(OperandSpec::RegIndexBaseScaleDisp) } }, _ => { @@ -6161,277 +6267,61 @@ fn read_M< Ok(op_spec) } -#[inline] -fn width_to_gp_reg_bank(width: u8) -> RegisterBank { - let index = width.trailing_zeros(); - - const BANK_LUT: [RegisterBank; 3] = [ - RegisterBank::B, - RegisterBank::W, - RegisterBank::D, - ]; - - *BANK_LUT.get(index as usize).unwrap_or_else(|| unsafe { unreachable_unchecked() }) +/// the actual description for a selection of bits involved in decoding a [`real_mode::Instruction`]. +/// +/// some prefixes are only identified as an `InnerDescription::Misc` string, while some are full +/// `InnerDescription::SegmentPrefix(Segment)`. generally, strings should be considered unstable +/// and only useful for displaying for human consumption. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum InnerDescription { + /// the literal byte read for a `rex` prefix, `0x4_`. while 32-bit code does not have `rex` + /// prefixes, this description is also used for the implied `rex`-type bits in `vex` and `evex` + /// prefixes. + RexPrefix(u8), + /// the segment selected by a segment override prefix. this is not necessarily the actual + /// segement used in the instruction's memory accesses, if any are made. + SegmentPrefix(Segment), + /// the opcode read for this instruction. this may be reported multiple times in an instruction + /// if multiple spans of bits are necessary to determine the opcode. it is a bug if two + /// different `Opcode` are indicated by different `InnerDescription::Opcode` reported from + /// decoding the same instruction. this invariant is not well-tested, and may occur in + /// practice. + Opcode(Opcode), + /// the operand code indicating how to read operands for this instruction. this is an internal + /// detail of `yaxpeax-x86` but is typically named in a manner that can aid understanding the + /// decoding process. `OperandCode` names are unstable, and this variant is only useful for + /// displaying for human consumption. + OperandCode(OperandCodeWrapper), + /// a decoded register: a name for the bits used to decode it, the register number those bits + /// specify, and the fully-constructed [`long_mode::RegSpec`] that was decoded. + RegisterNumber(&'static str, u8, RegSpec), + /// a miscellaneous string describing some bits of the instruction. this may describe a prefix, + /// internal details of a prefix, error or constraints on an opcode, operand encoding details, + /// or other items involved in an instruction. + Misc(&'static str), + /// a number involved in the instruction: typically either a disaplacement or immediate. the + /// string describes which. the `i64` member is typically a sign-extended value from the + /// appropriate original size, meaning there may be incorrect cases of a `65535u16` sign + /// extending to `-1`. bug reports are highly encouraged for unexpected values. + Number(&'static str, i64), + /// a boundary between two logically distinct sections of an instruction. these typically + /// separate the leading prefix string (if any), opcode, and operands (if any). the included + /// string describes which boundary this is. boundary names should not be considered stable, + /// and are useful at most for displaying for human consumption. + Boundary(&'static str), } -#[inline(always)] -fn read_0f_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { - // seems like f2 takes priority, then f3, then 66, then "no prefix". for SOME instructions an - // invalid prefix is in fact an invalid instruction. so just duplicate for the four kinds of - // opcode lists. - if prefixes.repnz() { - REPNZ_0F_CODES[opcode as usize] - } else if prefixes.rep() { - REP_0F_CODES[opcode as usize] - } else if prefixes.operand_size() { - OPERAND_SIZE_0F_CODES[opcode as usize] - } else { - NORMAL_0F_CODES[opcode as usize] - } -} - -fn read_0f38_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { - if prefixes.rep() { - return match opcode { - 0xd8 => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38d8), - 0xdc => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38dc), - 0xdd => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38dd), - 0xde => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38de), - 0xdf => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38df), - 0xf6 => OpcodeRecord(Interpretation::Instruction(Opcode::ADOX), OperandCode::Gv_Ev), - 0xf8 => { - prefixes.unset_operand_size(); - OpcodeRecord(Interpretation::Instruction(Opcode::ENQCMDS), OperandCode::INV_Gv_M) - }, - 0xfa => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38fa), - 0xfb => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38fb), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } - - if prefixes.repnz() { - return match opcode { - 0xf0 => OpcodeRecord(Interpretation::Instruction(Opcode::CRC32), OperandCode::Gv_Eb), - 0xf1 => OpcodeRecord(Interpretation::Instruction(Opcode::CRC32), OperandCode::Gd_Ev), - 0xf8 => { - prefixes.unset_operand_size(); - OpcodeRecord(Interpretation::Instruction(Opcode::ENQCMD), OperandCode::INV_Gv_M) - }, - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } - - if prefixes.operand_size() { - // leave operand size present for `movbe` - if opcode != 0xf0 && opcode != 0xf1 { - prefixes.unset_operand_size(); - } - - return match opcode { - 0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFB), OperandCode::G_E_xmm), - 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDW), OperandCode::G_E_xmm), - 0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDD), OperandCode::G_E_xmm), - 0x03 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDSW), OperandCode::G_E_xmm), - 0x04 => OpcodeRecord(Interpretation::Instruction(Opcode::PMADDUBSW), OperandCode::G_E_xmm), - 0x05 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBW), OperandCode::G_E_xmm), - 0x06 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBD), OperandCode::G_E_xmm), - 0x07 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBSW), OperandCode::G_E_xmm), - 0x08 => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGNB), OperandCode::G_E_xmm), - 0x09 => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGNW), OperandCode::G_E_xmm), - 0x0a => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGND), OperandCode::G_E_xmm), - 0x0b => OpcodeRecord(Interpretation::Instruction(Opcode::PMULHRSW), OperandCode::G_E_xmm), - 0x10 => OpcodeRecord(Interpretation::Instruction(Opcode::PBLENDVB), OperandCode::G_E_xmm), - 0x14 => OpcodeRecord(Interpretation::Instruction(Opcode::BLENDVPS), OperandCode::G_E_xmm), - 0x15 => OpcodeRecord(Interpretation::Instruction(Opcode::BLENDVPD), OperandCode::G_E_xmm), - 0x17 => OpcodeRecord(Interpretation::Instruction(Opcode::PTEST), OperandCode::G_E_xmm), - 0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::PABSB), OperandCode::G_E_xmm), - 0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::PABSW), OperandCode::G_E_xmm), - 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::PABSD), OperandCode::G_E_xmm), - 0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXBW), OperandCode::PMOVX_G_E_xmm), - 0x21 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXBD), OperandCode::PMOVX_G_E_xmm), - 0x22 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXBQ), OperandCode::PMOVX_G_E_xmm), - 0x23 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXWD), OperandCode::PMOVX_G_E_xmm), - 0x24 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXWQ), OperandCode::PMOVX_G_E_xmm), - 0x25 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVSXDQ), OperandCode::PMOVX_G_E_xmm), - 0x28 => OpcodeRecord(Interpretation::Instruction(Opcode::PMULDQ), OperandCode::G_E_xmm), - 0x29 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPEQQ), OperandCode::G_E_xmm), - 0x2a => OpcodeRecord(Interpretation::Instruction(Opcode::MOVNTDQA), OperandCode::G_M_xmm), - 0x2b => OpcodeRecord(Interpretation::Instruction(Opcode::PACKUSDW), OperandCode::G_E_xmm), - 0x30 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXBW), OperandCode::PMOVX_G_E_xmm), - 0x31 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXBD), OperandCode::PMOVX_G_E_xmm), - 0x32 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXBQ), OperandCode::PMOVX_G_E_xmm), - 0x33 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXWD), OperandCode::PMOVX_G_E_xmm), - 0x34 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXWQ), OperandCode::PMOVX_G_E_xmm), - 0x35 => OpcodeRecord(Interpretation::Instruction(Opcode::PMOVZXDQ), OperandCode::PMOVX_G_E_xmm), - 0x37 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPGTQ), OperandCode::G_E_xmm), - 0x38 => OpcodeRecord(Interpretation::Instruction(Opcode::PMINSB), OperandCode::G_E_xmm), - 0x39 => OpcodeRecord(Interpretation::Instruction(Opcode::PMINSD), OperandCode::G_E_xmm), - 0x3a => OpcodeRecord(Interpretation::Instruction(Opcode::PMINUW), OperandCode::G_E_xmm), - 0x3b => OpcodeRecord(Interpretation::Instruction(Opcode::PMINUD), OperandCode::G_E_xmm), - 0x3c => OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSB), OperandCode::G_E_xmm), - 0x3d => OpcodeRecord(Interpretation::Instruction(Opcode::PMAXSD), OperandCode::G_E_xmm), - 0x3e => OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUW), OperandCode::G_E_xmm), - 0x3f => OpcodeRecord(Interpretation::Instruction(Opcode::PMAXUD), OperandCode::G_E_xmm), - 0x40 => OpcodeRecord(Interpretation::Instruction(Opcode::PMULLD), OperandCode::G_E_xmm), - 0x41 => OpcodeRecord(Interpretation::Instruction(Opcode::PHMINPOSUW), OperandCode::G_E_xmm), - 0x80 => OpcodeRecord(Interpretation::Instruction(Opcode::INVEPT), OperandCode::INV_Gv_M), - 0x81 => OpcodeRecord(Interpretation::Instruction(Opcode::INVVPID), OperandCode::INV_Gv_M), - 0x82 => OpcodeRecord(Interpretation::Instruction(Opcode::INVPCID), OperandCode::INV_Gv_M), - 0xcf => OpcodeRecord(Interpretation::Instruction(Opcode::GF2P8MULB), OperandCode::G_E_xmm), - 0xdb => OpcodeRecord(Interpretation::Instruction(Opcode::AESIMC), OperandCode::G_E_xmm), - 0xdc => OpcodeRecord(Interpretation::Instruction(Opcode::AESENC), OperandCode::G_E_xmm), - 0xdd => OpcodeRecord(Interpretation::Instruction(Opcode::AESENCLAST), OperandCode::G_E_xmm), - 0xde => OpcodeRecord(Interpretation::Instruction(Opcode::AESDEC), OperandCode::G_E_xmm), - 0xdf => OpcodeRecord(Interpretation::Instruction(Opcode::AESDECLAST), OperandCode::G_E_xmm), - 0xf0 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::Gv_M), - 0xf1 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::M_Gv), - 0xf5 => OpcodeRecord(Interpretation::Instruction(Opcode::WRUSS), OperandCode::Md_Gd), - 0xf6 => OpcodeRecord(Interpretation::Instruction(Opcode::ADCX), OperandCode::Gv_Ev), - 0xf8 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVDIR64B), OperandCode::MOVDIR64B), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } else { - return match opcode { - 0x00 => OpcodeRecord(Interpretation::Instruction(Opcode::PSHUFB), OperandCode::G_E_mm), - 0x01 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDW), OperandCode::G_E_mm), - 0x02 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDD), OperandCode::G_E_mm), - 0x03 => OpcodeRecord(Interpretation::Instruction(Opcode::PHADDSW), OperandCode::G_E_mm), - 0x04 => OpcodeRecord(Interpretation::Instruction(Opcode::PMADDUBSW), OperandCode::G_E_mm), - 0x05 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBW), OperandCode::G_E_mm), - 0x06 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBD), OperandCode::G_E_mm), - 0x07 => OpcodeRecord(Interpretation::Instruction(Opcode::PHSUBSW), OperandCode::G_E_mm), - 0x08 => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGNB), OperandCode::G_E_mm), - 0x09 => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGNW), OperandCode::G_E_mm), - 0x0a => OpcodeRecord(Interpretation::Instruction(Opcode::PSIGND), OperandCode::G_E_mm), - 0x0b => OpcodeRecord(Interpretation::Instruction(Opcode::PMULHRSW), OperandCode::G_E_mm), - 0x1c => OpcodeRecord(Interpretation::Instruction(Opcode::PABSB), OperandCode::G_E_mm), - 0x1d => OpcodeRecord(Interpretation::Instruction(Opcode::PABSW), OperandCode::G_E_mm), - 0x1e => OpcodeRecord(Interpretation::Instruction(Opcode::PABSD), OperandCode::G_E_mm), - 0xc8 => OpcodeRecord(Interpretation::Instruction(Opcode::SHA1NEXTE), OperandCode::G_E_xmm), - 0xc9 => OpcodeRecord(Interpretation::Instruction(Opcode::SHA1MSG1), OperandCode::G_E_xmm), - 0xca => OpcodeRecord(Interpretation::Instruction(Opcode::SHA1MSG2), OperandCode::G_E_xmm), - 0xcb => OpcodeRecord(Interpretation::Instruction(Opcode::SHA256RNDS2), OperandCode::G_E_xmm), - 0xcc => OpcodeRecord(Interpretation::Instruction(Opcode::SHA256MSG1), OperandCode::G_E_xmm), - 0xcd => OpcodeRecord(Interpretation::Instruction(Opcode::SHA256MSG2), OperandCode::G_E_xmm), - 0xf0 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::Gv_M), - 0xf1 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVBE), OperandCode::M_Gv), - 0xf6 => OpcodeRecord(Interpretation::Instruction(Opcode::WRSS), OperandCode::Md_Gd), - 0xf9 => OpcodeRecord(Interpretation::Instruction(Opcode::MOVDIRI), OperandCode::Md_Gd), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } -} - -fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { - if prefixes.rep() { - if prefixes != &Prefixes::new(0x10) { - return OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing); - } - return match opcode { - 0xf0 => OpcodeRecord(Interpretation::Instruction(Opcode::HRESET), OperandCode::ModRM_0xf30f3af0), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } - - if prefixes.repnz() { - return OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing); - } - - if prefixes.operand_size() { - return match opcode { - 0x08 => OpcodeRecord(Interpretation::Instruction(Opcode::ROUNDPS), OperandCode::G_E_xmm_Ib), - 0x09 => OpcodeRecord(Interpretation::Instruction(Opcode::ROUNDPD), OperandCode::G_E_xmm_Ib), - 0x0a => OpcodeRecord(Interpretation::Instruction(Opcode::ROUNDSS), OperandCode::G_E_xmm_Ib), - 0x0b => OpcodeRecord(Interpretation::Instruction(Opcode::ROUNDSD), OperandCode::G_E_xmm_Ib), - 0x0c => OpcodeRecord(Interpretation::Instruction(Opcode::BLENDPS), OperandCode::G_E_xmm_Ib), - 0x0d => OpcodeRecord(Interpretation::Instruction(Opcode::BLENDPD), OperandCode::G_E_xmm_Ib), - 0x0e => OpcodeRecord(Interpretation::Instruction(Opcode::PBLENDW), OperandCode::G_E_xmm_Ib), - 0x0f => OpcodeRecord(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_xmm_Ib), - 0x14 => OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::G_Ev_xmm_Ib), - 0x15 => OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::G_Ev_xmm_Ib), - 0x16 => OpcodeRecord(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::G_Ev_xmm_Ib), - 0x17 => OpcodeRecord(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::G_Ev_xmm_Ib), - 0x20 => OpcodeRecord(Interpretation::Instruction(Opcode::PINSRB), OperandCode::G_Ev_xmm_Ib), - 0x21 => OpcodeRecord(Interpretation::Instruction(Opcode::INSERTPS), OperandCode::G_Ev_xmm_Ib), - 0x22 => OpcodeRecord(Interpretation::Instruction(Opcode::PINSRD), OperandCode::G_Ev_xmm_Ib), - 0x40 => OpcodeRecord(Interpretation::Instruction(Opcode::DPPS), OperandCode::G_E_xmm_Ib), - 0x41 => OpcodeRecord(Interpretation::Instruction(Opcode::DPPD), OperandCode::G_E_xmm_Ib), - 0x42 => OpcodeRecord(Interpretation::Instruction(Opcode::MPSADBW), OperandCode::G_E_xmm_Ib), - 0x44 => OpcodeRecord(Interpretation::Instruction(Opcode::PCLMULQDQ), OperandCode::G_E_xmm_Ib), - 0x60 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPESTRM), OperandCode::G_E_xmm_Ib), - 0x61 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPESTRI), OperandCode::G_E_xmm_Ib), - 0x62 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPISTRM), OperandCode::G_E_xmm_Ib), - 0x63 => OpcodeRecord(Interpretation::Instruction(Opcode::PCMPISTRI), OperandCode::G_E_xmm_Ib), - 0xcc => OpcodeRecord(Interpretation::Instruction(Opcode::SHA1RNDS4), OperandCode::G_E_xmm_Ib), - 0xce => OpcodeRecord(Interpretation::Instruction(Opcode::GF2P8AFFINEQB), OperandCode::G_E_xmm_Ub), - 0xcf => OpcodeRecord(Interpretation::Instruction(Opcode::GF2P8AFFINEINVQB), OperandCode::G_E_xmm_Ub), - 0xdf => OpcodeRecord(Interpretation::Instruction(Opcode::AESKEYGENASSIST), OperandCode::G_E_xmm_Ub), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; - } - - return match opcode { - 0xcc => OpcodeRecord(Interpretation::Instruction(Opcode::SHA1RNDS4), OperandCode::G_E_xmm_Ub), - 0x0f => OpcodeRecord(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_mm_Ib), - _ => OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), - }; -} - -/// the actual description for a selection of bits involved in decoding a [`real_mode::Instruction`]. -/// -/// some prefixes are only identified as an `InnerDescription::Misc` string, while some are full -/// `InnerDescription::SegmentPrefix(Segment)`. generally, strings should be considered unstable -/// and only useful for displaying for human consumption. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum InnerDescription { - /// the literal byte read for a `rex` prefix, `0x4_`. while 32-bit code does not have `rex` - /// prefixes, this description is also used for the implied `rex`-type bits in `vex` and `evex` - /// prefixes. - RexPrefix(u8), - /// the segment selected by a segment override prefix. this is not necessarily the actual - /// segement used in the instruction's memory accesses, if any are made. - SegmentPrefix(Segment), - /// the opcode read for this instruction. this may be reported multiple times in an instruction - /// if multiple spans of bits are necessary to determine the opcode. it is a bug if two - /// different `Opcode` are indicated by different `InnerDescription::Opcode` reported from - /// decoding the same instruction. this invariant is not well-tested, and may occur in - /// practice. - Opcode(Opcode), - /// the operand code indicating how to read operands for this instruction. this is an internal - /// detail of `yaxpeax-x86` but is typically named in a manner that can aid understanding the - /// decoding process. `OperandCode` names are unstable, and this variant is only useful for - /// displaying for human consumption. - OperandCode(OperandCodeWrapper), - /// a decoded register: a name for the bits used to decode it, the register number those bits - /// specify, and the fully-constructed [`long_mode::RegSpec`] that was decoded. - RegisterNumber(&'static str, u8, RegSpec), - /// a miscellaneous string describing some bits of the instruction. this may describe a prefix, - /// internal details of a prefix, error or constraints on an opcode, operand encoding details, - /// or other items involved in an instruction. - Misc(&'static str), - /// a number involved in the instruction: typically either a disaplacement or immediate. the - /// string describes which. the `i64` member is typically a sign-extended value from the - /// appropriate original size, meaning there may be incorrect cases of a `65535u16` sign - /// extending to `-1`. bug reports are highly encouraged for unexpected values. - Number(&'static str, i64), - /// a boundary between two logically distinct sections of an instruction. these typically - /// separate the leading prefix string (if any), opcode, and operands (if any). the included - /// string describes which boundary this is. boundary names should not be considered stable, - /// and are useful at most for displaying for human consumption. - Boundary(&'static str), -} - -impl InnerDescription { - fn with_id(self, id: u32) -> FieldDescription { - FieldDescription { - desc: self, - id, - } +impl InnerDescription { + fn with_id(self, id: u32) -> FieldDescription { + FieldDescription { + desc: self, + id, + } } } cfg_if::cfg_if! { - if #[cfg(feature = "fmt")] { + if #[cfg(feature="fmt")] { impl fmt::Display for InnerDescription { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -6476,6 +6366,7 @@ cfg_if::cfg_if! { } } +// TODO: this derive ought to be `feature=fmt`.. #[derive(Clone, PartialEq, Eq, Debug)] pub struct FieldDescription { desc: InnerDescription, @@ -6508,44 +6399,66 @@ impl fmt::Display for FieldDescription { } } +#[inline(always)] +fn record_opcode_record_found< + T: Reader<::Address, ::Word>, + S: DescriptionSink, +>(words: &mut T, sink: &mut S, opc: Opcode, code: OperandCode, opc_length: u32) { + let offset = words.offset() as u32; + let opcode_start_bit = (offset - opc_length) * 8; + let opcode_end_bit = offset * 8 - 1; + + if offset > opc_length { + sink.record( + opcode_start_bit - 1, opcode_start_bit - 1, + InnerDescription::Boundary("prefixes end") + .with_id(opcode_start_bit) + ); + } + if opc != Opcode::Invalid { + sink.record(opcode_start_bit, opcode_end_bit, FieldDescription { + desc: InnerDescription::Opcode(opc), + id: offset * 8 - opc_length * 8, + }); + } + sink.record(opcode_start_bit, opcode_end_bit, FieldDescription { + desc: InnerDescription::OperandCode(OperandCodeWrapper { code }), + id: offset * 8 - opc_length * 8 + 1, + }); +} + +#[derive(Copy, Clone)] +struct DecodeCtx { + check_lock: bool, + rrr: u8, +} + +impl DecodeCtx { + fn new() -> Self { + DecodeCtx { + check_lock: false, + rrr: 0 + } + } + fn read_opc_hotpath< T: Reader<::Address, ::Word>, S: DescriptionSink, ->(mut b: u8, mut record: OpcodeRecord, nextb: &mut u8, next_rec: &mut OpcodeRecord, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result, DecodeError> { +>(&mut self, mut b: u8, nextb: &mut u8, record: &mut OpcodeRecord, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result { if b == 0x66 { sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { - desc: InnerDescription::Misc("operand size override (to 16 bits)"), + desc: InnerDescription::Misc("operand size override (to 32 bits)"), id: words.offset() as u32 * 8 - 8, }); b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - record = unsafe { - core::ptr::read_volatile(&OPCODES[b as usize]) - }; + *record = OPCODES[b as usize]; instruction.prefixes.set_operand_size(); } - if let Interpretation::Instruction(opc) = record.0 { - if words.offset() > 1 { - sink.record( - words.offset() as u32 * 8 - 8 - 1, words.offset() as u32 * 8 - 8 - 1, - InnerDescription::Boundary("prefixes end") - .with_id(words.offset() as u32 * 8 - 9) - ); - } - if opc != Opcode::Invalid { - sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { - desc: InnerDescription::Opcode(opc), - id: words.offset() as u32 * 8 - 8, - }); - } - sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { - desc: InnerDescription::OperandCode(OperandCodeWrapper { code: record.1 }), - id: words.offset() as u32 * 8 - 8 + 1, - }); - instruction.mem_size = 0; - instruction.operand_count = 2; + if let Interpretation::Instruction(opc) = record.interp() { + record_opcode_record_found(words, sink, opc, record.operand(), 1); instruction.opcode = opc; - return Ok(Some(record.1)); + return Ok(true); } else if b == 0x0f { if words.offset() > 1 { sink.record( @@ -6555,71 +6468,53 @@ fn read_opc_hotpath< ); } let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - instruction.mem_size = 0; - instruction.operand_count = 2; - let record = if b == 0x38 { + let (r, len) = if b == 0x38 { let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - read_0f38_opcode(b, &mut instruction.prefixes) + (self.read_0f38_opcode(b, &mut instruction.prefixes), 3) } else if b == 0x3a { let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - read_0f3a_opcode(b, &mut instruction.prefixes) + (self.read_0f3a_opcode(b, &mut instruction.prefixes), 3) } else { - read_0f_opcode(b, &mut instruction.prefixes) + (self.read_0f_opcode(b, &mut instruction.prefixes), 2) }; - if let Interpretation::Instruction(opc) = record.0 { + *record = r; + if let Interpretation::Instruction(opc) = record.interp() { + record_opcode_record_found(words, sink, opc, record.operand(), len); instruction.opcode = opc; } else { unsafe { unreachable_unchecked(); } } - return Ok(Some(record.1)); + return Ok(true); } else { *nextb = b; - *next_rec = record; - return Ok(None); + return Ok(false); } } fn read_with_annotations< T: Reader<::Address, ::Word>, S: DescriptionSink, ->(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +>(&mut self, decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { words.mark(); let mut nextb = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; let mut next_rec = OPCODES[nextb as usize]; instruction.prefixes = Prefixes::new(0); // default registers to `[eax; 4]` - instruction.regs = unsafe { core::mem::transmute(0u64) }; +// instruction.regs = unsafe { core::mem::transmute(0u64) }; // default operands to [RegRRR, Nothing, Nothing, Nothing] - instruction.operands = unsafe { core::mem::transmute(0x00_00_00_01) }; - +// instruction.operands = unsafe { core::mem::transmute(0x00_00_00_01) }; + instruction.regs[1] = RegSpec::ax(); + instruction.regs[2] = RegSpec::ax(); - let record: OperandCode = if let Some(rec) = read_opc_hotpath(nextb, next_rec, &mut nextb, &mut next_rec, words, instruction, sink)? { - rec + let record: OperandCode = if self.read_opc_hotpath(nextb, &mut nextb, &mut next_rec, words, instruction, sink)? { + next_rec.operand() } else { let prefixes = &mut instruction.prefixes; let record = loop { let record = next_rec; - if let Interpretation::Instruction(opc) = record.0 { - if words.offset() > 1 { - sink.record( - words.offset() as u32 * 8 - 8 - 1, words.offset() as u32 * 8 - 8 - 1, - InnerDescription::Boundary("prefixes end") - .with_id(words.offset() as u32 * 8 - 9) - ); - } - if opc != Opcode::Invalid { - sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { - desc: InnerDescription::Opcode(opc), - id: words.offset() as u32 * 8 - 8, - }); - } - sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { - desc: InnerDescription::OperandCode(OperandCodeWrapper { code: record.1 }), - id: words.offset() as u32 * 8 - 8 + 1, - }); - instruction.mem_size = 0; - instruction.operand_count = 2; + if let Interpretation::Instruction(opc) = record.interp() { + record_opcode_record_found(words, sink, opc, record.operand(), 1); break record; } else { let b = nextb; @@ -6632,17 +6527,19 @@ fn read_with_annotations< ); } let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - instruction.mem_size = 0; - instruction.operand_count = 2; - if b == 0x38 { + let (rec, len) = if b == 0x38 { let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - break read_0f38_opcode(b, prefixes); + (self.read_0f38_opcode(b, prefixes), 3) } else if b == 0x3a { let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - break read_0f3a_opcode(b, prefixes); + (self.read_0f3a_opcode(b, prefixes), 3) } else { - break read_0f_opcode(b, prefixes); + (self.read_0f_opcode(b, prefixes), 2) + }; + if let Interpretation::Instruction(opc) = record.interp() { + record_opcode_record_found(words, sink, opc, record.operand(), len); } + break rec; } if b == 0x66 { sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription { @@ -6718,6 +6615,7 @@ fn read_with_annotations< id: words.offset() as u32 * 8 - 8, }); prefixes.set_lock(); + self.check_lock = true; }, // unlike 64-bit mode, the vex/evex prefixes are not recorded as prefixes - // they are LES/LDS/BOUND with special-case operand decoding. so we've @@ -6726,308 +6624,333 @@ fn read_with_annotations< } } nextb = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; - next_rec = unsafe { - core::ptr::read_volatile(&OPCODES[nextb as usize]) - }; + next_rec = OPCODES[nextb as usize]; } if words.offset() >= 15 { return Err(DecodeError::TooLong); } }; - if let Interpretation::Instruction(opcode) = record.0 { + if let Interpretation::Instruction(opcode) = record.interp() { instruction.opcode = opcode; } else { unsafe { unreachable_unchecked(); } } - record.1 + record.operand() }; - read_operands(decoder, words, instruction, record, sink)?; - if instruction.prefixes.lock() { - if !LOCKABLE_INSTRUCTIONS.contains(&instruction.opcode) || !instruction.operands[0].is_memory() { + self.read_operands(decoder, words, instruction, record, sink)?; + + if self.check_lock { + if (instruction.opcode as u32) < 0x1000 || !instruction.operands[0].is_memory() { return Err(DecodeError::InvalidPrefixes); } } 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 - - */ + fn read_operands< T: Reader<::Address, ::Word>, S: DescriptionSink ->(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> { +>(&mut self, decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> { sink.record( words.offset() as u32 * 8 - 1, words.offset() as u32 * 8 - 1, InnerDescription::Boundary("opcode ends/operands begin (typically)") .with_id(words.offset() as u32 * 8 - 1) ); - let modrm_start = words.offset() as u32 * 8; - let opcode_start = modrm_start + 8; - 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.regs[0] = - RegSpec::from_parts(reg, bank); - instruction.mem_size = 2; - sink.record( - opcode_start + 0, - opcode_start + 2, - InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) - .with_id(opcode_start + 2) - ); - instruction.operand_count = 1; - } - 1 => { - // Zv_AX - let bank = if instruction.prefixes.operand_size() { - RegisterBank::D - } else { - RegisterBank::W - }; - instruction.regs[0] = - RegSpec::from_parts(0, bank); - instruction.operands[1] = OperandSpec::RegMMM; - instruction.regs[1] = - RegSpec::from_parts(reg, bank); - sink.record( - opcode_start + 0, - opcode_start + 2, - InnerDescription::RegisterNumber("zzz", reg, instruction.regs[1]) - .with_id(opcode_start + 2) - ); - sink.record( - opcode_start + 3, - opcode_start + 7, - InnerDescription::Misc("opcode selects `ax` operand") - .with_id(opcode_start + 2) - ); - if instruction.prefixes.operand_size() { - sink.record( - opcode_start + 3, - opcode_start + 7, - InnerDescription::Misc("operand-size prefix override selects `eax`") - .with_id(opcode_start + 2) - ); - } - instruction.operand_count = 2; - } - 2 => { - // these are Zb_Ib_R - instruction.regs[0] = - RegSpec::from_parts(reg, RegisterBank::B); - sink.record( - opcode_start, - opcode_start + 2, - InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) - .with_id(opcode_start + 1) - ); - instruction.imm = - read_imm_unsigned(words, 1)?; - sink.record( - words.offset() as u32 * 8 - 8, - words.offset() as u32 * 8 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - 8)); - instruction.operands[1] = OperandSpec::ImmU8; - } - 3 => { - // category == 3, Zv_Iv_R - if instruction.prefixes.operand_size() { - instruction.regs[0] = - RegSpec::from_parts(reg, RegisterBank::D); - sink.record( - opcode_start, - opcode_start + 2, - InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) - .with_id(opcode_start + 2) - ); - instruction.imm = - read_imm_unsigned(words, 4)?; - sink.record( - words.offset() as u32 * 8 - 32, - words.offset() as u32 * 8 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - 32 + 1) - ); - instruction.operands[1] = OperandSpec::ImmI32; - } else { - instruction.regs[0] = - RegSpec::from_parts(reg, RegisterBank::W); - sink.record( - opcode_start, - opcode_start + 2, - InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) - .with_id(opcode_start + 2) - ); - instruction.imm = - read_imm_unsigned(words, 2)?; - sink.record( - words.offset() as u32 * 8 - 16, - words.offset() as u32 * 8 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - 16 + 1) - ); - 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. - _ => {} - } - } + let modrm_start = words.offset() as u32 * 8; + let opcode_start = modrm_start - 8; - let mut modrm = 0; - let bank: RegisterBank; - let mut mem_oper = OperandSpec::Nothing; - if operand_code.has_read_E() { - // cool! we can precompute opwidth and know we need to read_E. + if operand_code.is_only_modrm_operands() { + let bank; + // cool! we can precompute width and know we need to read_E. if !operand_code.has_byte_operands() { - // further, this is an vd E, but adcx is always 32-bit operands - if instruction.prefixes.operand_size() || instruction.opcode == Opcode::ADCX || instruction.opcode == Opcode::ADOX { - instruction.mem_size = 4; - bank = RegisterBank::D; + // further, this is an vdq E + bank = if instruction.prefixes.operand_size() || instruction.opcode == Opcode::ADCX || instruction.opcode == Opcode::ADOX { + RegisterBank::D } else { - instruction.mem_size = 2; - bank = RegisterBank::W; - } + RegisterBank::W + }; + instruction.mem_size = bank as u8; } else { - instruction.mem_size = 1; bank = RegisterBank::B; + instruction.mem_size = 1; }; - modrm = read_modrm(words)?; + let modrm = read_modrm(words)?; instruction.regs[0].bank = bank; instruction.regs[0].num = (modrm >> 3) & 7; - sink.record( - modrm_start + 3, - modrm_start + 5, - InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0]) - .with_id(modrm_start + 1) - ); - mem_oper = if modrm >= 0b11000000 { + // for some encodings, the rrr field selects an opcode, not an operand + if operand_code.bits() != OperandCode::ModRM_0xc1_Ev_Ib as u16 && operand_code.bits() != OperandCode::ModRM_0xff_Ev as u16 { + sink.record( + modrm_start + 3, + modrm_start + 5, + InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0]) + .with_id(modrm_start + 3) + ); + } + + let mem_oper = if modrm >= 0b11000000 { sink.record( modrm_start + 6, modrm_start + 7, InnerDescription::Misc("mmm field is a register number (mod bits: 11)") .with_id(modrm_start + 0) ); - if operand_code.bits() == (OperandCode::Gv_M as u16) { + if operand_code.denies_regmmm() { return Err(DecodeError::InvalidOperand); } - let res = read_modrm_reg(instruction, modrm, bank)?; - sink.record( - modrm_start, - modrm_start + 2, - InnerDescription::RegisterNumber("mmm", modrm & 7, instruction.regs[1]) - .with_id(modrm_start + 2) - ); - res + read_modrm_reg(instruction, words, modrm, bank, sink)? } else { read_M(words, instruction, modrm, sink)? }; - instruction.operands[1] = mem_oper; + if !operand_code.has_reg_mem() { + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + } else { + instruction.operands[1] = mem_oper; + instruction.operands[0] = OperandSpec::RegRRR; + } + instruction.operand_count = 2; + return Ok(()); } - if let Some((only_imm, immsz)) = operand_code.has_imm() { - instruction.imm = - read_imm_signed(words, 1 << (immsz * 1))? as u32; - // TODO: hmmm - if immsz == 0 { + if operand_code.has_imm() { + instruction.mem_size = 0; + if operand_code.operand_case_handler_index() == OperandCase::Ibs { + instruction.imm = + read_imm_signed(words, 1)? as u32; sink.record( words.offset() as u32 * 8 - 8, words.offset() as u32 * 8 - 1, InnerDescription::Number("1-byte immediate", instruction.imm as i64) .with_id(words.offset() as u32 * 8), ); + instruction.operands[0] = OperandSpec::ImmI8; } else { + instruction.imm = + read_imm_signed(words, 2)? as u32; sink.record( words.offset() as u32 * 8 - 16, words.offset() as u32 * 8 - 1, InnerDescription::Number("2-byte immediate", instruction.imm as i64) .with_id(words.offset() as u32 * 8), ); - } - if only_imm { - if immsz == 0 { - instruction.operands[0] = OperandSpec::ImmI8; - } else { - if instruction.opcode == Opcode::CALL { - instruction.mem_size = 2; - } - instruction.operands[0] = OperandSpec::ImmI32; + if instruction.opcode == Opcode::CALL { + instruction.mem_size = 2; } - instruction.operand_count = 1; - return Ok(()); + instruction.operands[0] = OperandSpec::ImmI32; } + instruction.operand_count = 1; + return Ok(()); } - if operand_code.is_only_modrm_operands() { + let mut mem_oper = OperandSpec::Nothing; + if operand_code.has_read_E() { + let bank; + // cool! we can precompute width and know we need to read_E. + if !operand_code.has_byte_operands() { + // further, this is an vdq E, but adcx is always 32-bit operands + bank = if instruction.prefixes.operand_size() || instruction.opcode == Opcode::ADCX || instruction.opcode == Opcode::ADOX { + RegisterBank::D + } else { + RegisterBank::W + }; + instruction.mem_size = bank as u8; + } else { + bank = RegisterBank::B; + instruction.mem_size = 1; + }; + let modrm = read_modrm(words)?; + instruction.regs[0].bank = bank; + let rrr = (modrm >> 3) & 7; + self.rrr = rrr; + instruction.regs[0].num = rrr; + + // for some encodings, the rrr field selects an opcode, not an operand + if operand_code.bits() != OperandCode::ModRM_0xc1_Ev_Ib as u16 && operand_code.bits() != OperandCode::ModRM_0xff_Ev as u16 { + sink.record( + modrm_start + 3, + modrm_start + 5, + InnerDescription::RegisterNumber("rrr", self.rrr, instruction.regs[0]) + .with_id(modrm_start + 3) + ); + } + + mem_oper = if modrm >= 0b11000000 { + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::Misc("mmm field is a register number (mod bits: 11)") + .with_id(modrm_start + 0) + ); + if operand_code.denies_regmmm() { + return Err(DecodeError::InvalidOperand); + } + read_modrm_reg(instruction, words, modrm, bank, sink)? + } else { + read_M(words, instruction, modrm, sink)? + }; if !operand_code.has_reg_mem() { instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; - }; + } else { + instruction.operands[1] = mem_oper; + instruction.operands[0] = OperandSpec::RegRRR; + } } else { + instruction.mem_size = 0; + } + + if let Some(z_operand_code) = operand_code.get_embedded_instructions() { + instruction.operands[0] = OperandSpec::RegRRR; + 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.regs[0] = + RegSpec::from_parts(reg, bank); + instruction.mem_size = 2; + sink.record( + opcode_start + 0, + opcode_start + 2, + InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) + .with_id(opcode_start + 2) + ); + instruction.operand_count = 1; + } + 1 => { + // Zv_AX + let bank = if instruction.prefixes.operand_size() { + RegisterBank::D + } else { + RegisterBank::W + }; + instruction.regs[0] = + RegSpec::from_parts(0, bank); + instruction.operands[1] = OperandSpec::RegMMM; + instruction.regs[1] = + RegSpec::from_parts(reg, bank); + sink.record( + opcode_start, + opcode_start + 2, + InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) + .with_id(opcode_start + 1) + ); + sink.record( + opcode_start + 3, + opcode_start + 7, + InnerDescription::Misc("opcode selects `ax` operand") + .with_id(opcode_start + 2) + ); + if instruction.prefixes.operand_size() { + sink.record( + opcode_start + 3, + opcode_start + 7, + InnerDescription::Misc("operand-size prefix override selects `eax`") + .with_id(opcode_start + 2) + ); + } + instruction.operand_count = 2; + } + 2 => { + // these are Zb_Ib_R + instruction.regs[0] = + RegSpec { + num: reg, + bank: RegisterBank::B, + }; + sink.record( + opcode_start, + opcode_start + 2, + InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) + .with_id(opcode_start + 1) + ); + instruction.imm = + read_imm_unsigned(words, 1)?; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - 8)); + instruction.operands[1] = OperandSpec::ImmU8; + instruction.operand_count = 2; + } + 3 => { + // category == 3, Zv_Iv_R + if !instruction.prefixes.operand_size() { + instruction.regs[0] = + RegSpec::from_parts(reg, RegisterBank::W); + instruction.imm = read_num(words, 2)? as u16 as u32; + instruction.operands[1] = OperandSpec::ImmI16; + let width = 2; + sink.record( + words.offset() as u32 * 8 - (8 * width as u32), + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - (8 * width as u32) + 1) + ); + } else { + instruction.regs[0] = + RegSpec::from_parts(reg, RegisterBank::D); + instruction.imm = read_num(words, 4)? as u32; + instruction.operands[1] = OperandSpec::ImmI32; + let width = 4; + sink.record( + words.offset() as u32 * 8 - (8 * width as u32), + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - (8 * width as u32) + 1) + ); + } + sink.record( + opcode_start, + opcode_start + 2, + InnerDescription::RegisterNumber("zzz", reg, instruction.regs[0]) + .with_id(opcode_start + 2) + ); + instruction.operand_count = 2; + } + _ => { + unreachable!("bad category"); + } + } + return Ok(()); + } + + if !operand_code.has_read_E() { + instruction.operands = [OperandSpec::RegRRR, OperandSpec::Nothing, OperandSpec::Nothing, OperandSpec::Nothing]; + } + instruction.operand_count = 2; + // match operand_code { - match operand_code.special_case_handler_index() { - 0 => { + match operand_code.operand_case_handler_index() { + // these operand cases are all `only_*`, and are unreachable here.. + OperandCase::Internal | OperandCase::Gv_M | + OperandCase::Ibs | OperandCase::Jvds => { + } + OperandCase::SingleMMMOper => { instruction.operands[0] = mem_oper; instruction.operand_count = 1; }, - 1 => { - instruction.opcode = base_opcode_map((modrm >> 3) & 7); + OperandCase::BaseOpWithI8 => { + instruction.opcode = base_opcode_map(self.rrr); + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::ImmI8; @@ -7043,51 +6966,53 @@ fn read_operands< InnerDescription::Number("imm", instruction.imm as i64) .with_id(words.offset() as u32 * 8 - 8) ); - instruction.operand_count = 2; } - 2 => { + OperandCase::BaseOpWithIv => { instruction.operands[0] = mem_oper; - let numwidth = if instruction.prefixes.operand_size() { - 4 - } else { - 2 - }; - instruction.imm = read_imm_signed(words, numwidth)? as u32; - instruction.opcode = base_opcode_map((modrm >> 3) & 7); + instruction.opcode = base_opcode_map(self.rrr); sink.record( modrm_start + 3, modrm_start + 5, InnerDescription::Opcode(instruction.opcode) .with_id(modrm_start - 8) ); - sink.record( - words.offset() as u32 * 8 - (numwidth as u32 * 8), - words.offset() as u32 * 8 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - (numwidth as u32 * 8)) - ); - instruction.operands[1] = match numwidth { - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 2; - }, - 3 => { // ModRM_0xc6_Eb_Ib - if modrm == 0xf8 { - instruction.opcode = Opcode::XABORT; - instruction.imm = read_imm_signed(words, 1)? as u32; + if !instruction.prefixes.operand_size() { + let opwidth = 2; + instruction.imm = read_imm_signed(words, opwidth)? as u32; sink.record( - words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - (opwidth as u32 * 8), words.offset() as u32 * 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - 8) + .with_id(words.offset() as u32 * 8 - (opwidth as u32 * 8)) ); - instruction.operands[0] = OperandSpec::ImmI8; - instruction.operand_count = 1; - return Ok(()); + instruction.operands[1] = OperandSpec::ImmI16; + } else { + let opwidth = 4; + instruction.imm = read_imm_signed(words, opwidth)? as u32; + sink.record( + words.offset() as u32 * 8 - (opwidth as u32 * 8), + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - (opwidth as u32 * 8)) + ); + instruction.operands[1] = OperandSpec::ImmI32; } - if (modrm & 0b00111000) != 0 { + }, + OperandCase::MovI8 => { + if self.rrr != 0 { + if mem_oper == OperandSpec::RegMMM && instruction.regs[1].num & 0b0111 == 0 { + instruction.opcode = Opcode::XABORT; + instruction.imm = read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - 8) + ); + instruction.operands[0] = OperandSpec::ImmI8; + instruction.operand_count = 1; + return Ok(()); + } sink.record( modrm_start + 3, modrm_start + 5, @@ -7100,41 +7025,43 @@ fn read_operands< instruction.operands[0] = mem_oper; instruction.opcode = Opcode::MOV; instruction.imm = read_imm_signed(words, 1)? as u32; + instruction.operands[1] = OperandSpec::ImmI8; sink.record( modrm_start + 8, - modrm_start + 8 - 1, + modrm_start + 1 as u32 * 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) .with_id(modrm_start + 8) ); - instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; + } - 4 => { // ModRM_0xc7_Ev_Iv - if modrm == 0xf8 { - instruction.opcode = Opcode::XBEGIN; - instruction.imm = if instruction.prefixes.operand_size() { - sink.record( - modrm_start + 8, - modrm_start + 8 + 32 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(modrm_start + 8) - ); - // TODO: 5? - read_imm_signed(words, 5)? as i32 as u32 - } else { - sink.record( - modrm_start + 8, - modrm_start + 8 + 16 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(modrm_start + 8) - ); - read_imm_signed(words, 2)? as i16 as i32 as u32 - }; - instruction.operands[0] = OperandSpec::ImmI32; - instruction.operand_count = 1; - return Ok(()); - } - if (modrm & 0b00111000) != 0 { + OperandCase::MovIv => { + if self.rrr != 0 { + let opwidth = instruction.regs[0].bank as u8; + if mem_oper == OperandSpec::RegMMM && instruction.regs[1].num & 0b0111 == 0 { + instruction.opcode = Opcode::XBEGIN; + instruction.imm = if opwidth == 2 { + let imm = read_imm_signed(words, 2)? as i16 as i32 as u32; + sink.record( + words.offset() as u32 * 8 - 16, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - 16) + ); + imm + } else { + let imm = read_imm_signed(words, 4)? as i32 as u32; + sink.record( + words.offset() as u32 * 8 - 32, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - 32) + ); + imm + }; + instruction.operands[0] = OperandSpec::ImmI32; + instruction.operand_count = 1; + return Ok(()); + } sink.record( modrm_start + 3, modrm_start + 5, @@ -7147,136 +7074,150 @@ fn read_operands< instruction.operands[0] = mem_oper; instruction.opcode = Opcode::MOV; if !instruction.prefixes.operand_size() { + instruction.imm = read_imm_signed(words, 2)? as u32; sink.record( modrm_start + 8, - modrm_start + 8 + 16 - 1, + modrm_start + 2 as u32 * 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) .with_id(modrm_start + 8) ); - instruction.imm = read_imm_signed(words, 2)? as u32; instruction.operands[1] = OperandSpec::ImmI16; } else { + instruction.imm = read_imm_signed(words, 4)? as u32; sink.record( modrm_start + 8, - modrm_start + 8 + 32 - 1, + modrm_start + 4 as u32 * 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) .with_id(modrm_start + 8) ); - instruction.imm = read_imm_signed(words, 4)? as u32; instruction.operands[1] = OperandSpec::ImmI32; } }, - op @ 5 | - op @ 6 | - op @ 7 | - op @ 8 | - op @ 9 | - op @ 10 => { + OperandCase::BitwiseWithI8 => { instruction.operands[0] = mem_oper; - instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); + instruction.opcode = bitwise_opcode_map(self.rrr); sink.record( modrm_start + 3, modrm_start + 5, InnerDescription::Opcode(instruction.opcode) .with_id(modrm_start - 8) ); - if op == 10 { - instruction.regs[0] = RegSpec::cl(); - sink.record( - modrm_start - 8, - modrm_start - 1, - InnerDescription::RegisterNumber("reg", 1, instruction.regs[0]) - .with_id(modrm_start - 7) - ); - instruction.operands[1] = OperandSpec::RegRRR; - } else if op == 9 { - instruction.regs[0] = RegSpec::cl(); - sink.record( - modrm_start - 8, - modrm_start - 1, - InnerDescription::RegisterNumber("reg", 1, instruction.regs[0]) - .with_id(modrm_start - 7) - ); - instruction.operands[1] = OperandSpec::RegRRR; - } else { - let num = match op { - 5 | - 6 => { - read_num(words, 1)? - } - _ => { - // these are the _1 variants, everything else is unreachable - 1 - } - }; - // TODO: op == 6? - if op == 5 { - sink.record( - modrm_start - 8, - modrm_start - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(modrm_start - 8) - ); - } else { - sink.record( - modrm_start - 8, - modrm_start - 1, - InnerDescription::Misc("opcode specifies integer immediate 1") - .with_id(modrm_start - 8) - ); - } - instruction.imm = num; - instruction.operands[1] = OperandSpec::ImmI8; - } - instruction.operand_count = 2; + let num = read_num(words, 1)?; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", num as i64) + .with_id(modrm_start - 8) + ); + instruction.imm = num; + instruction.operands[1] = OperandSpec::ImmI8; + } + OperandCase::ShiftBy1_v | + OperandCase::ShiftBy1_b => { + instruction.operands[0] = mem_oper; + instruction.opcode = bitwise_opcode_map(self.rrr); + sink.record( + modrm_start + 3, + modrm_start + 5, + InnerDescription::Opcode(instruction.opcode) + .with_id(modrm_start - 8) + ); + let num = 1; + sink.record( + modrm_start - 8, + modrm_start - 1, + InnerDescription::Misc("opcode specifies integer immediate 1") + .with_id(modrm_start - 8) + ); + instruction.imm = num; + instruction.operands[1] = OperandSpec::ImmI8; + } + OperandCase::BitwiseByCL => { + instruction.operands[0] = mem_oper; + instruction.opcode = bitwise_opcode_map(self.rrr); + sink.record( + modrm_start + 3, + modrm_start + 5, + InnerDescription::Opcode(instruction.opcode) + .with_id(modrm_start - 8) + ); + instruction.regs[0] = RegSpec::cl(); + sink.record( + modrm_start - 8, + modrm_start - 1, + InnerDescription::RegisterNumber("reg", 1, instruction.regs[0]) + .with_id(modrm_start - 7) + ); + instruction.operands[1] = OperandSpec::RegRRR; }, - op @ 11 | - op @ 12 => { - let opwidth = if op == 11 { - 1 - } else { - if instruction.prefixes.operand_size() { - 4 - } else { - 2 - } - }; + OperandCase::ModRM_0xf6 => { instruction.operands[0] = mem_oper; const TABLE: [Opcode; 8] = [ Opcode::TEST, Opcode::TEST, Opcode::NOT, Opcode::NEG, Opcode::MUL, Opcode::IMUL, Opcode::DIV, Opcode::IDIV, ]; - let rrr = (modrm >> 3) & 7; - instruction.opcode = TABLE[rrr as usize]; + instruction.opcode = TABLE[self.rrr as usize]; sink.record( modrm_start + 3, modrm_start + 5, InnerDescription::Opcode(instruction.opcode) .with_id(modrm_start - 8) ); - if rrr < 2 { + if self.rrr < 2 { instruction.opcode = Opcode::TEST; - let numwidth = if opwidth == 8 { 4 } else { opwidth }; - instruction.imm = read_imm_signed(words, numwidth)? as u32; - instruction.operands[1] = match opwidth { - 1 => OperandSpec::ImmI8, - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - _ => unsafe { unreachable_unchecked() } - }; + instruction.imm = read_imm_signed(words, 1)? as u32; + instruction.operands[1] = OperandSpec::ImmI8; sink.record( modrm_start + 8, - modrm_start + 8 + numwidth as u32 * 8 - 1, + modrm_start + 8 + 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) .with_id(modrm_start + 8) ); } else { instruction.operand_count = 1; } + }, - 13 => { + OperandCase::ModRM_0xf7 => { instruction.operands[0] = mem_oper; - let r = (modrm >> 3) & 7; + const TABLE: [Opcode; 8] = [ + Opcode::TEST, Opcode::TEST, Opcode::NOT, Opcode::NEG, + Opcode::MUL, Opcode::IMUL, Opcode::DIV, Opcode::IDIV, + ]; + instruction.opcode = TABLE[self.rrr as usize]; + sink.record( + modrm_start + 3, + modrm_start + 5, + InnerDescription::Opcode(instruction.opcode) + .with_id(modrm_start - 8) + ); + if self.rrr < 2 { + if !instruction.prefixes.operand_size() { + instruction.imm = read_imm_signed(words, 2)? as u32; + instruction.operands[1] = OperandSpec::ImmI16; + sink.record( + modrm_start + 8, + modrm_start + 8 + 2 as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(modrm_start + 8) + ); + } else { + instruction.imm = read_imm_signed(words, 4)? as u32; + sink.record( + modrm_start + 8, + modrm_start + 8 + 4 as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(modrm_start + 8) + ); + instruction.operands[1] = OperandSpec::ImmI32; + }; + } else { + instruction.operand_count = 1; + } + }, + OperandCase::ModRM_0xfe => { + instruction.operands[0] = mem_oper; + let r = self.rrr; if r >= 2 { sink.record( modrm_start + 3, @@ -7298,13 +7239,13 @@ fn read_operands< ); instruction.operand_count = 1; } - 14 => { + OperandCase::ModRM_0xff => { instruction.operands[0] = mem_oper; - let r = (modrm >> 3) & 7; + let r = self.rrr; if r == 7 { return Err(DecodeError::InvalidOpcode); } - let opcode = [ + const TABLE: [Opcode; 7] = [ Opcode::INC, Opcode::DEC, Opcode::CALL, @@ -7312,7 +7253,8 @@ fn read_operands< Opcode::JMP, Opcode::JMPF, Opcode::PUSH, - ][r as usize]; + ]; + let opcode = TABLE[r as usize]; sink.record( modrm_start + 3, modrm_start + 5, @@ -7324,16 +7266,22 @@ fn read_operands< // dword. unlikely larger modes, operand-size can't shrink the call operand down. if opcode == Opcode::CALL { instruction.mem_size = 2; + } else if opcode == Opcode::PUSH || opcode == Opcode::POP { + if !instruction.prefixes.operand_size() { + instruction.mem_size = 2; + } else { + instruction.mem_size = 4; + } } else if opcode == Opcode::CALLF || opcode == Opcode::JMPF { return Err(DecodeError::InvalidOperand); } } else { if opcode == Opcode::CALL || opcode == Opcode::JMP || opcode == Opcode::PUSH || opcode == Opcode::POP { - if instruction.prefixes.operand_size() { - instruction.mem_size = 4; - } else { + if !instruction.prefixes.operand_size() { instruction.mem_size = 2; + } else { + instruction.mem_size = 4; } } else if opcode == Opcode::CALLF || opcode == Opcode::JMPF { instruction.mem_size = 4; @@ -7342,55 +7290,50 @@ fn read_operands< instruction.opcode = opcode; instruction.operand_count = 1; } - 15 => { - let modrm = read_modrm(words)?; + OperandCase::Gv_Eb => { + let w = RegisterBank::B; - instruction.operands[1] = read_E(words, instruction, modrm, 1, sink)?; - instruction.regs[0] = if instruction.prefixes.operand_size() || instruction.opcode == Opcode::CRC32 { - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) - } else { - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W) - }; + instruction.operands[1] = mem_oper; + // crc32 is always 32-bits in the first operand + if instruction.opcode == Opcode::CRC32 { + instruction.regs[0].bank = RegisterBank::D; + } sink.record( modrm_start as u32 + 3, modrm_start as u32 + 5, - InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0]) + InnerDescription::RegisterNumber("rrr", self.rrr, instruction.regs[0]) .with_id(modrm_start as u32 + 3) ); - if instruction.operands[1] != OperandSpec::RegMMM { + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.regs[1].bank = w; + } else { instruction.mem_size = 1; } instruction.operand_count = 2; - }, - 16 => { - let modrm = read_modrm(words)?; + } + OperandCase::Gv_Ew => { + let w = RegisterBank::W; - instruction.operands[1] = read_E(words, instruction, modrm, 2, sink)?; - instruction.regs[0] = if instruction.prefixes.operand_size() { - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) - } else { - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W) - }; + instruction.operands[1] = mem_oper; sink.record( modrm_start as u32 + 3, modrm_start as u32 + 5, - InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0]) + InnerDescription::RegisterNumber("rrr", self.rrr, instruction.regs[0]) .with_id(modrm_start as u32 + 3) ); - if instruction.operands[1] != OperandSpec::RegMMM { + if instruction.operands[1] == OperandSpec::RegMMM { + instruction.mem_size = 0; + instruction.regs[1].bank = w; + } else { instruction.mem_size = 2; } instruction.operand_count = 2; }, - 18 => { - instruction.operands[0] = mem_oper; - instruction.operand_count = 1; - }, - 19 => { + OperandCase::E_G_xmm => { instruction.regs[0].bank = RegisterBank::X; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; - instruction.operand_count = 2; if instruction.operands[0] == OperandSpec::RegMMM { sink.record( modrm_start + 6, @@ -7404,23 +7347,22 @@ fn read_operands< instruction.mem_size = 16; } }, - op @ 20 | - op @ 21 => { + OperandCase::G_M_xmm => { + instruction.regs[0].bank = RegisterBank::X; + instruction.mem_size = 16; + + } + OperandCase::G_E_xmm => { instruction.regs[0].bank = RegisterBank::X; - instruction.operand_count = 2; if instruction.operands[1] == OperandSpec::RegMMM { - if op == 20 { - return Err(DecodeError::InvalidOperand); - } else { - sink.record( - modrm_start + 6, - modrm_start + 7, - InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm") - .with_id(modrm_start as u32 + 1) - ); - // fix the register to XMM - instruction.regs[1].bank = RegisterBank::X; - } + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm") + .with_id(modrm_start as u32 + 1) + ); + // fix the register to XMM + instruction.regs[1].bank = RegisterBank::X; } else { if instruction.opcode == Opcode::MOVDDUP { instruction.mem_size = 8; @@ -7429,16 +7371,13 @@ fn read_operands< } } }, - 22 => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + OperandCase::G_E_xmm_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; sink.record( modrm_start as u32 + 3, modrm_start as u32 + 5, - InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0]) + InnerDescription::RegisterNumber("rrr", self.rrr, instruction.regs[0]) .with_id(modrm_start as u32 + 3) ); instruction.imm = @@ -7457,65 +7396,96 @@ fn read_operands< } else { instruction.mem_size = 16; } + } else { + instruction.regs[1].bank = RegisterBank::X; } instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; }, - 23 => { + OperandCase::AL_Ibs => { instruction.regs[0] = RegSpec::al(); + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); + sink.record( + modrm_start as u32 - 8, + modrm_start as u32 - 1, + InnerDescription::RegisterNumber("reg", 0, instruction.regs[0]) + .with_id(modrm_start as u32 - 1) + ); instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; } - 24 => { - let opwidth = if instruction.prefixes.operand_size() { - instruction.regs[0] = - RegSpec::from_parts(0, RegisterBank::D); - 4 + OperandCase::AX_Ivd => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - instruction.regs[0] = - RegSpec::from_parts(0, RegisterBank::W); - 2 + RegisterBank::D }; + instruction.regs[0].num = 0; + instruction.regs[0].bank = bank; + sink.record( + modrm_start as u32 - 8, + modrm_start as u32 - 1, + InnerDescription::RegisterNumber("reg", 0, instruction.regs[0]) + .with_id(modrm_start as u32 - 1) + ); instruction.imm = - read_imm_signed(words, opwidth)? as u32; - instruction.operands[1] = match opwidth { + read_imm_signed(words, bank as u8)? as u32; + instruction.operands[1] = match bank as u8 { 2 => OperandSpec::ImmI16, 4 => OperandSpec::ImmI32, _ => unsafe { unreachable_unchecked() } }; sink.record( - words.offset() as u32 * 8 - opwidth as u32 * 8, + words.offset() as u32 * 8 - bank as u8 as u32 * 8, words.offset() as u32 * 8 - 1, InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - opwidth as u32 * 8 + 1) + .with_id(words.offset() as u32 * 8 - bank as u8 as u32 * 8 + 1) ); - instruction.operand_count = 2; } - 25 => { - let opwidth = if instruction.prefixes.operand_size() { - 4 + OperandCase::Ivs => { + if instruction.prefixes.operand_size() { + instruction.imm = read_imm_unsigned(words, 4)?; + instruction.operands[0] = OperandSpec::ImmI32; + + let opwidth = 4; + sink.record( + words.offset() as u32 * 8 - opwidth as u32 * 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - opwidth as u32 * 8 + 1) + ); } else { - 2 - }; + instruction.imm = read_imm_unsigned(words, 2)?; + instruction.operands[0] = OperandSpec::ImmI16; + + let opwidth = 2; + sink.record( + words.offset() as u32 * 8 - opwidth as u32 * 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("imm", instruction.imm as i64) + .with_id(words.offset() as u32 * 8 - opwidth as u32 * 8 + 1) + ); + } + instruction.operand_count = 1; + }, + OperandCase::ModRM_0x83 => { + instruction.operands[0] = mem_oper; + instruction.opcode = base_opcode_map(self.rrr); instruction.imm = - read_imm_unsigned(words, opwidth)?; + read_imm_signed(words, 1)? as u32; sink.record( - words.offset() as u32 * 8 - opwidth as u32 * 8, + words.offset() as u32 * 8 - 8, words.offset() as u32 * 8 - 1, - InnerDescription::Number("imm", instruction.imm as i64) - .with_id(words.offset() as u32 * 8 - opwidth as u32 * 8 + 1) + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), ); - instruction.operands[0] = match opwidth { - 2 => OperandSpec::ImmI16, - 4 => OperandSpec::ImmI32, - _ => unsafe { unreachable_unchecked() } - }; - instruction.operand_count = 1; - }, - 26 => { - instruction.operands[0] = mem_oper; - instruction.opcode = base_opcode_map((modrm >> 3) & 7); sink.record( modrm_start + 3, modrm_start + 5, @@ -7523,9 +7493,8 @@ fn read_operands< .with_id(modrm_start - 8) ); instruction.operands[1] = OperandSpec::ImmI8; - instruction.operand_count = 2; }, - 27 => { + OperandCase::I_3 => { sink.record( modrm_start - 8, modrm_start - 1, @@ -7536,44 +7505,41 @@ fn read_operands< instruction.operands[0] = OperandSpec::ImmU8; instruction.operand_count = 1; } - 28 => { + OperandCase::Nothing => { if instruction.opcode == Opcode::Invalid { return Err(DecodeError::InvalidOpcode); } if instruction.opcode == Opcode::RETURN { instruction.mem_size = 2; - } else { + } else if instruction.opcode == Opcode::RETF { instruction.mem_size = 4; } + // TODO: leave? instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; return Ok(()); }, - 29 => { + OperandCase::Ed_G_xmm => { instruction.regs[0].bank = RegisterBank::X; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; if instruction.operands[0] == OperandSpec::RegMMM { // fix the register to XMM - if instruction.opcode == Opcode::MOVD { - instruction.regs[1].bank = RegisterBank::D; - } else { - sink.record( - modrm_start + 6, - modrm_start + 7, - InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm") - .with_id(modrm_start as u32 + 1) - ); - instruction.regs[1].bank = RegisterBank::X; - } + sink.record( + modrm_start + 6, + modrm_start + 7, + InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to dword") + .with_id(modrm_start as u32 + 1) + ); + instruction.regs[1].bank = RegisterBank::D; } else { instruction.mem_size = 4; } }, - 30 => { + OperandCase::ModRM_0x8f => { instruction.operands[0] = mem_oper; - let r = (modrm >> 3) & 7; + let r = self.rrr; if r >= 1 { sink.record( modrm_start + 3, @@ -7595,69 +7561,37 @@ fn read_operands< ); instruction.operand_count = 1; } - 31 => { + OperandCase::G_Ed_xmm => { instruction.regs[0].bank = RegisterBank::X; instruction.operand_count = 2; if instruction.operands[1] == OperandSpec::RegMMM { - sink.record( - modrm_start + 6, - modrm_start + 7, - InnerDescription::Misc("mod bits 0b11 select register operand, width fixed to xmm") - .with_id(modrm_start as u32 + 1) - ); // fix the register to XMM instruction.regs[1].bank = RegisterBank::X; } else { instruction.mem_size = 4; } }, - _ => { - let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; - unlikely_operands(decoder, words, instruction, operand_code, mem_oper, sink)?; - } - }; - } - - Ok(()) -} -fn unlikely_operands< - T: Reader<::Address, ::Word>, - S: DescriptionSink ->(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, sink: &mut S) -> Result<(), DecodeError> { - match operand_code { - OperandCode::AbsFar => { - instruction.operands[0] = OperandSpec::AbsoluteFarAddress; - instruction.operand_count = 1; - instruction.mem_size = 0; - // read segment - let addr_size = if instruction.prefixes.operand_size() { - 4 + OperandCase::G_E_mm_Ib => { + instruction.operands[1] = mem_oper; + instruction.imm = + read_num(words, 1)? as u8 as u32; + instruction.regs[0].bank = RegisterBank::MM; + instruction.regs[0].num = self.rrr; + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = 8; } else { - 2 - }; - instruction.imm = read_num(words, addr_size)?; - instruction.disp = read_num(words, 2)? as u16 as u32; - } - OperandCode::G_E_mm_Ib => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E_mm(words, instruction, modrm, sink)?; - instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; - if instruction.operands[1] == OperandSpec::RegMMM { + instruction.regs[1].num &= 0b0111; instruction.regs[1].bank = RegisterBank::MM; - } else { - instruction.mem_size = 8; + instruction.mem_size = 0; } - instruction.imm = read_num(words, 1)? as u8 as u32; instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCode::G_Ev_xmm_Ib => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; - instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; - instruction.imm = read_num(words, 1)? as u8 as u32; + OperandCase::G_Ev_xmm_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; + instruction.imm = + read_num(words, 1)? as u8 as u32; if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = match instruction.opcode { Opcode::PEXTRB => 1, @@ -7670,16 +7604,16 @@ fn unlikely_operands< Opcode::PINSRD => 4, _ => 8, }; + } else { + instruction.regs[1].bank = RegisterBank::X; } instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCode::PMOVX_E_G_xmm => { - let modrm = read_modrm(words)?; - - instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; + OperandCase::PMOVX_E_G_xmm => { + instruction.regs[0].bank = RegisterBank::X; instruction.operands[1] = OperandSpec::RegRRR; - instruction.operands[0] = read_E_xmm(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; if instruction.operands[0] != OperandSpec::RegMMM { if [].contains(&instruction.opcode) { instruction.mem_size = 2; @@ -7687,20 +7621,19 @@ fn unlikely_operands< instruction.mem_size = 8; } } else { + instruction.regs[1].bank = RegisterBank::X; if instruction.opcode == Opcode::MOVLPD || instruction.opcode == Opcode::MOVHPD || instruction.opcode == Opcode::MOVHPS { return Err(DecodeError::InvalidOperand); } } } - OperandCode::PMOVX_G_E_xmm => { - let modrm = read_modrm(words)?; - - instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; + OperandCase::PMOVX_G_E_xmm => { + instruction.regs[0].bank = RegisterBank::X; if instruction.opcode == Opcode::CVTTSD2SI || instruction.opcode == Opcode::CVTSD2SI { instruction.regs[0].bank = RegisterBank::D; } + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; if instruction.operands[1] != OperandSpec::RegMMM { if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) { instruction.mem_size = 2; @@ -7710,22 +7643,18 @@ fn unlikely_operands< instruction.mem_size = 8; } } else { + instruction.regs[1].bank = RegisterBank::X; if instruction.opcode == Opcode::MOVLPD || instruction.opcode == Opcode::MOVHPD { return Err(DecodeError::InvalidOperand); } } } - OperandCode::INV_Gv_M => { - let modrm = read_modrm(words)?; - if modrm >= 0xc0 { - return Err(DecodeError::InvalidOperand); - } - - instruction.regs[0] = RegSpec { bank: RegisterBank::D, num: (modrm >> 3) & 7 }; + OperandCase::INV_Gv_M => { + instruction.regs[0].bank = RegisterBank::D; instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = read_M(words, instruction, modrm, sink)?; + instruction.operands[1] = mem_oper; if [Opcode::LFS, Opcode::LGS, Opcode::LSS].contains(&instruction.opcode) { - if instruction.prefixes.operand_size() { + if !instruction.prefixes.operand_size() { instruction.mem_size = 4; } else { instruction.mem_size = 6; @@ -7737,11 +7666,11 @@ fn unlikely_operands< instruction.mem_size = 16; } } - OperandCode::ModRM_0xc4 => { + OperandCase::ModRM_0xc4 => { let modrm = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; 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() { + if instruction.prefixes.vex_invalid() { // prefixes and then vex is invalid! reject it. return Err(DecodeError::InvalidPrefixes); } else { @@ -7760,21 +7689,21 @@ fn unlikely_operands< } } else { // LES - instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::D } else { RegisterBank::W }); + instruction.regs[0] = 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(words, instruction, modrm, sink)?; - if instruction.prefixes.operand_size() { - instruction.mem_size = 6; - } else { + if !instruction.prefixes.operand_size() { instruction.mem_size = 4; + } else { + instruction.mem_size = 6; } } }, - OperandCode::ModRM_0xc5 => { + OperandCase::ModRM_0xc5 => { let modrm = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; 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() { + if instruction.prefixes.vex_invalid() { // prefixes and then vex is invalid! reject it. return Err(DecodeError::InvalidPrefixes); } else { @@ -7793,31 +7722,29 @@ fn unlikely_operands< } } else { // LDS - instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::D } else { RegisterBank::W }); + instruction.regs[0] = 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(words, instruction, modrm, sink)?; - if instruction.prefixes.operand_size() { - instruction.mem_size = 6; - } else { + if !instruction.prefixes.operand_size() { instruction.mem_size = 4; + } else { + instruction.mem_size = 6; } } }, - OperandCode::G_U_xmm_Ub => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; - if instruction.operands[1] != OperandSpec::RegMMM { + OperandCase::G_U_xmm_Ub => { + if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::D; + instruction.regs[1].bank = RegisterBank::X; instruction.imm = read_num(words, 1)? as u8 as u32; instruction.operands[2] = OperandSpec::ImmU8; instruction.operand_count = 3; } - OperandCode::ModRM_0xf20f78 => { + OperandCase::ModRM_0xf20f78 => { instruction.opcode = Opcode::INSERTQ; let modrm = read_modrm(words)?; @@ -7840,7 +7767,7 @@ fn unlikely_operands< instruction.operands[3] = OperandSpec::ImmInDispField; instruction.operand_count = 4; } - OperandCode::ModRM_0x660f78 => { + OperandCase::ModRM_0x660f78 => { instruction.opcode = Opcode::EXTRQ; let modrm = read_modrm(words)?; @@ -7865,7 +7792,7 @@ fn unlikely_operands< instruction.operand_count = 3; } - OperandCode::ModRM_0xf30f1e => { + OperandCase::ModRM_0xf30f1e => { let modrm = read_modrm(words)?; match modrm { 0xfa => { @@ -7877,35 +7804,35 @@ fn unlikely_operands< instruction.operand_count = 0; }, _ => { - let (sz, bank) = if instruction.prefixes.operand_size() { - (4, RegisterBank::D) + let bank = if instruction.prefixes.operand_size() { + RegisterBank::D } else { - (2, RegisterBank::W) + RegisterBank::W }; instruction.operands[1] = OperandSpec::RegRRR; - instruction.operands[0] = read_E(words, instruction, modrm, sz, sink)?; - instruction.mem_size = sz; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; + instruction.mem_size = bank as u8; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, bank); instruction.operand_count = 2; + } }; } - OperandCode::G_E_xmm_Ub => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - instruction.imm = - read_num(words, 1)? as u8 as u32; - if instruction.operands[1] != OperandSpec::RegMMM { + OperandCase::G_E_xmm_Ub => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::X; + if mem_oper == OperandSpec::RegMMM { + instruction.regs[1].bank = RegisterBank::X; + } else { instruction.mem_size = 16; } + instruction.imm = + read_num(words, 1)? as u8 as u32; instruction.operands[2] = OperandSpec::ImmU8; instruction.operand_count = 3; } - OperandCode::Gd_Ed => { + OperandCase::Gd_Ed => { instruction.regs[0].bank = RegisterBank::D; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::D; @@ -7913,46 +7840,63 @@ fn unlikely_operands< instruction.mem_size = 4; } instruction.operands[1] = mem_oper; - instruction.operand_count = 2; } - OperandCode::Md_Gd => { + OperandCase::Md_Gd => { instruction.regs[0].bank = RegisterBank::D; + instruction.mem_size = 4; + } + /* + OperandCase::Edq_Gdq => { + let bank = if instruction.prefixes.rex_unchecked().w() { + RegisterBank::Q + } else { + RegisterBank::D + }; + + instruction.regs[0].bank = bank; if mem_oper == OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); + instruction.regs[1].bank = bank; } - instruction.mem_size = 4; instruction.operands[1] = instruction.operands[0]; instruction.operands[0] = mem_oper; instruction.operand_count = 2; } - OperandCode::G_U_xmm => { - instruction.regs[0].bank = RegisterBank::X; + */ + OperandCase::G_U_xmm => { if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } + instruction.regs[0].bank = RegisterBank::X; instruction.regs[1].bank = RegisterBank::X; - instruction.operand_count = 2; }, - OperandCode::Gv_Ev_Ib => { + OperandCase::Gv_Ev_Ib => { + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCode::Gv_Ev_Iv => { - let opwidth = if instruction.prefixes.operand_size() { - 4 + OperandCase::Gv_Ev_Iv => { + let opwidth = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; instruction.imm = - read_imm_signed(words, opwidth)? as u32; - instruction.operands[2] = match opwidth { + read_imm_signed(words, opwidth as u8)? as u32; + instruction.operands[2] = match opwidth as u8 { 2 => OperandSpec::ImmI16, 4 => OperandSpec::ImmI32, _ => unsafe { unreachable_unchecked() } }; instruction.operand_count = 3; } - OperandCode::Ev_Gv_Ib => { + OperandCase::Ev_Gv_Ib => { instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.imm = @@ -7960,19 +7904,17 @@ fn unlikely_operands< instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCode::Ev_Gv_CL => { + OperandCase::Ev_Gv_CL => { instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operands[2] = OperandSpec::RegVex; instruction.regs[3] = RegSpec::cl(); instruction.operand_count = 3; } - OperandCode::G_mm_Ew_Ib => { - let modrm = read_modrm(words)?; - - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::MM); + OperandCase::G_mm_Ew_Ib => { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::MM; + instruction.regs[0].num = self.rrr; if instruction.operands[1] == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::D; } else { @@ -7983,9 +7925,9 @@ fn unlikely_operands< instruction.operands[2] = OperandSpec::ImmI8; instruction.operand_count = 3; } - OperandCode::G_E_mm => { + OperandCase::G_E_mm => { instruction.regs[0].bank = RegisterBank::MM; - instruction.regs[0].num &= 0b111; + instruction.regs[0].num = self.rrr; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; @@ -7996,106 +7938,95 @@ fn unlikely_operands< instruction.mem_size = 8; } } - instruction.operand_count = 2; }, - OperandCode::G_U_mm => { + OperandCase::G_U_mm => { instruction.regs[0].bank = RegisterBank::D; if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; - instruction.operand_count = 2; }, - OperandCode::Gv_Ew_LSL => { - let modrm = read_modrm(words)?; - if !instruction.prefixes.operand_size() { - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W); - } else { - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W); - }; - - instruction.operands[1] = read_E(words, instruction, modrm, 2, sink)?; + OperandCase::Gv_Ew_LSL => { + instruction.operands[1] = mem_oper; // lsl is weird. the full register width is written, but only the low 16 bits are used. if instruction.operands[1] == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::W; } else { instruction.mem_size = 2; } - instruction.operand_count = 2; - }, - OperandCode::Gd_Ev => { - let modrm = read_modrm(words)?; - - let opwidth = if instruction.prefixes.operand_size() { - 4 + instruction.regs[0].bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; - instruction.operands[1] = read_E(words, instruction, modrm, opwidth, sink)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); - instruction.operand_count = 2; + }, + OperandCase::Gd_Ev => { + instruction.operands[1] = mem_oper; if instruction.operands[1] != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = 4; } + if instruction.regs[0].bank == RegisterBank::W { + instruction.regs[0].bank = RegisterBank::D; + }; + instruction.operand_count = 2; }, - op @ OperandCode::AL_Ob | - op @ OperandCode::AX_Ov => { - instruction.regs[0] = match op { - OperandCode::AL_Ob => { + op @ OperandCase::AL_Ob | + op @ OperandCase::AX_Ov => { + match op { + OperandCase::AL_Ob => { instruction.mem_size = 1; - RegSpec::al() - }, - OperandCode::AX_Ov => { - if !instruction.prefixes.operand_size() { - instruction.mem_size = 2; - RegSpec::ax() + instruction.regs[0] = RegSpec::al(); + } + OperandCase::AX_Ov => { + let b = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - instruction.mem_size = 4; - RegSpec::eax() - } + RegisterBank::D + }; + instruction.mem_size = b as u8; + instruction.regs[0].num = 0; + instruction.regs[0].bank = b; } _ => { unsafe { unreachable_unchecked() } } }; - let addr_width = if instruction.prefixes.address_size() { 4 } else { 2 }; + let addr_width = if !instruction.prefixes.address_size() { 2 } else { 4 }; let imm = read_num(words, addr_width)?; instruction.disp = imm; - if instruction.prefixes.address_size() { + 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.regs[0] = match op { - OperandCode::Ob_AL => { + op @ OperandCase::Ob_AL | + op @ OperandCase::Ov_AX => { + match op { + OperandCase::Ob_AL => { instruction.mem_size = 1; - RegSpec::al() - }, - OperandCode::Ov_AX => { - if !instruction.prefixes.operand_size() { - instruction.mem_size = 2; - RegSpec::ax() + instruction.regs[0] = RegSpec::al(); + } + OperandCase::Ov_AX => { + let b = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - instruction.mem_size = 4; - RegSpec::eax() - } + RegisterBank::D + }; + instruction.mem_size = b as u8; + instruction.regs[0].num = 0; + instruction.regs[0].bank = b; } _ => { unsafe { unreachable_unchecked() } } }; - let addr_width = if instruction.prefixes.address_size() { 4 } else { 2 }; + let addr_width = if !instruction.prefixes.address_size() { 2 } else { 4 }; let imm = read_num(words, addr_width)?; instruction.disp = imm; - instruction.operands[0] = if instruction.prefixes.address_size() { + instruction.operands[0] = if !instruction.prefixes.address_size() { OperandSpec::DispU16 } else { OperandSpec::DispU32 @@ -8103,24 +8034,24 @@ fn unlikely_operands< instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::I_1 => { + OperandCase::I_1 => { instruction.imm = 1; instruction.operands[0] = OperandSpec::ImmU8; instruction.operand_count = 1; } /* - OperandCode::Unsupported => { + OperandCase::Unsupported => { return Err(DecodeError::IncompleteDecoder); } */ - OperandCode::Iw_Ib => { - instruction.disp = read_num(words, 2)?; - instruction.imm = read_num(words, 1)?; + OperandCase::Iw_Ib => { + instruction.disp = read_num(words, 2)? as u32; + instruction.imm = read_num(words, 1)? as u32; instruction.operands[0] = OperandSpec::ImmInDispField; instruction.operands[1] = OperandSpec::ImmU8; instruction.operand_count = 2; } - OperandCode::Fw => { + OperandCase::Fw => { if !instruction.prefixes.operand_size() { instruction.opcode = Opcode::IRET; } else { @@ -8128,7 +8059,7 @@ fn unlikely_operands< } instruction.operand_count = 0; } - OperandCode::G_mm_U_mm => { + OperandCase::G_mm_U_mm => { instruction.regs[0].bank = RegisterBank::MM; if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); @@ -8138,39 +8069,37 @@ fn unlikely_operands< instruction.regs[0].num &= 0b111; instruction.operand_count = 2; }, - OperandCode::E_G_q => { + OperandCase::E_G_q => { if instruction.prefixes.operand_size() { return Err(DecodeError::InvalidOpcode); } - let modrm = read_modrm(words)?; - - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + instruction.regs[0].bank = RegisterBank::D; instruction.operand_count = 2; if instruction.operands[0] != OperandSpec::RegMMM { instruction.mem_size = 4; + } else { + instruction.regs[1].bank = RegisterBank::D; } } - OperandCode::G_E_q => { + OperandCase::G_E_q => { if instruction.prefixes.operand_size() { return Err(DecodeError::InvalidOpcode); } - let modrm = read_modrm(words)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; - if instruction.operands[0] != OperandSpec::RegMMM { + instruction.operands[1] = mem_oper; + instruction.regs[0].bank = RegisterBank::D; + instruction.operand_count = 2; + if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 4; + } else { + instruction.regs[1].bank = RegisterBank::D; } - instruction.operand_count = 2; } - OperandCode::G_Mq_mm => { + OperandCase::G_Mq_mm => { instruction.operands[1] = instruction.operands[0]; instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::MM; @@ -8182,24 +8111,30 @@ fn unlikely_operands< instruction.regs[0].num &= 0b111; instruction.operand_count = 2; }, - OperandCode::MOVQ_f30f => { + OperandCase::MOVQ_f30f => { + // if rex.w is set, the f3 prefix no longer applies and this becomes an 0f7e movq, + // rather than f30f7e movq. + // + // the difference here is that 0f7e movq has reversed operand order from f30f7e movq, + // in addition to the selected register banks being different. + // + // anyway, there are two operands, and the primary concern here is "what are they?". instruction.operand_count = 2; - let modrm = read_modrm(words)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; + instruction.regs[0].bank = RegisterBank::X; + instruction.operands[1] = mem_oper; if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 8; + } else { + instruction.regs[1].bank = RegisterBank::X; } } - OperandCode::ModRM_0x0f0d => { - let modrm = read_modrm(words)?; - let r = (modrm >> 3) & 0b111; + OperandCase::ModRM_0x0f0d => { + let r = instruction.regs[0].num & 0b111; - let opwidth = if instruction.prefixes.operand_size() { - 4 + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; match r { @@ -8210,22 +8145,26 @@ fn unlikely_operands< instruction.opcode = Opcode::NOP; } } - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = mem_oper; if instruction.operands[0] != OperandSpec::RegMMM { instruction.mem_size = 64; + } else { + instruction.regs[1].bank = bank; } instruction.operand_count = 1; } - OperandCode::ModRM_0x0f0f => { + OperandCase::ModRM_0x0f0f => { // 3dnow instructions are WILD, the opcode is encoded as an imm8 trailing the // instruction. - let modrm = read_modrm(words)?; - instruction.operands[1] = read_E_mm(words, instruction, modrm, sink)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; + instruction.operands[1] = mem_oper; + instruction.regs[0].num &= 0b0111; + instruction.regs[0].bank = RegisterBank::MM; if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 8; + } else { + instruction.regs[1].num &= 0b0111; + instruction.regs[1].bank = RegisterBank::MM; } let opcode = read_modrm(words)?; @@ -8307,7 +8246,7 @@ fn unlikely_operands< } } } - OperandCode::ModRM_0x0fc7 => { + OperandCase::ModRM_0x0fc7 => { if instruction.prefixes.repnz() { let modrm = read_modrm(words)?; let is_reg = (modrm & 0xc0) == 0xc0; @@ -8321,7 +8260,7 @@ fn unlikely_operands< instruction.opcode = Opcode::CMPXCHG8B; instruction.mem_size = 8; instruction.operand_count = 1; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; } return Ok(()); } @@ -8331,10 +8270,10 @@ fn unlikely_operands< } } if instruction.prefixes.operand_size() { - let opwidth = if instruction.prefixes.operand_size() { - 4 + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; let modrm = read_modrm(words)?; let is_reg = (modrm & 0xc0) == 0xc0; @@ -8348,13 +8287,13 @@ fn unlikely_operands< instruction.opcode = Opcode::CMPXCHG8B; instruction.mem_size = 8; instruction.operand_count = 1; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; } return Ok(()); } 6 => { instruction.opcode = Opcode::VMCLEAR; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { // this would be invalid as `vmclear`, so fall back to the parse as // 66-prefixed rdrand. this is a register operand, so just demote it to the @@ -8368,7 +8307,7 @@ fn unlikely_operands< return Ok(()); } 7 => { - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { // this would be invalid as `vmclear`, so fall back to the parse as // 66-prefixed rdrand. this is a register operand, so just demote it to the @@ -8388,10 +8327,10 @@ fn unlikely_operands< } if instruction.prefixes.rep() { - let opwidth = if instruction.prefixes.operand_size() { - 4 + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; let modrm = read_modrm(words)?; let is_reg = (modrm & 0xc0) == 0xc0; @@ -8405,12 +8344,12 @@ fn unlikely_operands< instruction.opcode = Opcode::CMPXCHG8B; instruction.mem_size = 8; instruction.operand_count = 1; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; } } 6 => { instruction.opcode = Opcode::VMXON; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { // invalid as `vmxon`, reg-form is `senduipi` instruction.opcode = Opcode::SENDUIPI; @@ -8423,7 +8362,7 @@ fn unlikely_operands< } 7 => { instruction.opcode = Opcode::RDPID; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -8497,100 +8436,85 @@ fn unlikely_operands< instruction.opcode = opcode; instruction.operand_count = 1; - let opwidth = if instruction.prefixes.operand_size() { - 4 + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; }, - OperandCode::ModRM_0x0f71 => { + OperandCase::ModRM_0x0f71 => { if instruction.prefixes.rep() || instruction.prefixes.repnz() { return Err(DecodeError::InvalidOperand); } - instruction.operand_count = 2; - - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { + if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLW; - } - 4 => { - instruction.opcode = Opcode::PSRAW; - } - 6 => { - instruction.opcode = Opcode::PSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } + let r = instruction.regs[0].num & 0b0111; + const TBL: [Opcode; 8] = [ + Opcode::Invalid, Opcode::Invalid, Opcode::PSRLW, Opcode::Invalid, + Opcode::PSRAW, Opcode::Invalid, Opcode::PSLLW, Opcode::Invalid, + ]; + let opc = TBL[r as usize]; + if opc == Opcode::Invalid { + return Err(DecodeError::InvalidOpcode); } + instruction.opcode = opc; if instruction.prefixes.operand_size() { - instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::X; } else { - instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::MM; + instruction.regs[1].num &= 0b0111; } - instruction.operands[0] = OperandSpec::RegMMM; + instruction.operands[0] = mem_oper; instruction.imm = read_imm_signed(words, 1)? as u32; instruction.operands[1] = OperandSpec::ImmU8; + instruction.operand_count = 2; + }, - OperandCode::ModRM_0x0f72 => { + OperandCase::ModRM_0x0f72 => { if instruction.prefixes.rep() || instruction.prefixes.repnz() { return Err(DecodeError::InvalidOperand); } - instruction.operand_count = 2; - - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { + if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - let r = (modrm >> 3) & 7; - match r { - 2 => { - instruction.opcode = Opcode::PSRLD; - } - 4 => { - instruction.opcode = Opcode::PSRAD; - } - 6 => { - instruction.opcode = Opcode::PSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } + let r = instruction.regs[0].num & 0b0111; + const TBL: [Opcode; 8] = [ + Opcode::Invalid, Opcode::Invalid, Opcode::PSRLD, Opcode::Invalid, + Opcode::PSRAD, Opcode::Invalid, Opcode::PSLLD, Opcode::Invalid, + ]; + let opc = TBL[r as usize]; + if opc == Opcode::Invalid { + return Err(DecodeError::InvalidOpcode); } + instruction.opcode = opc; if instruction.prefixes.operand_size() { - instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::X; } else { - instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::MM; + instruction.regs[1].num &= 0b0111; } - instruction.operands[0] = OperandSpec::RegMMM; + instruction.operands[0] = mem_oper; instruction.imm = read_imm_signed(words, 1)? as u32; instruction.operands[1] = OperandSpec::ImmU8; }, - OperandCode::ModRM_0x0f73 => { + OperandCase::ModRM_0x0f73 => { if instruction.prefixes.rep() || instruction.prefixes.repnz() { return Err(DecodeError::InvalidOperand); } - instruction.operand_count = 2; - - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { + if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - let r = (modrm >> 3) & 7; + let r = instruction.regs[0].num & 0b0111; match r { 2 => { instruction.opcode = Opcode::PSRLQ; @@ -8616,53 +8540,45 @@ fn unlikely_operands< } if instruction.prefixes.operand_size() { - instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::X; } else { - instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; + instruction.regs[1].bank = RegisterBank::MM; + instruction.regs[1].num &= 0b0111; } - instruction.operands[0] = OperandSpec::RegMMM; + instruction.operands[0] = mem_oper; instruction.imm = read_imm_signed(words, 1)? as u32; instruction.operands[1] = OperandSpec::ImmU8; }, - OperandCode::ModRM_0xf30f38d8 => { - let modrm = read_modrm(words)?; - let r = (modrm >> 3) & 7; - instruction.mem_size = 63; + OperandCase::ModRM_0xf30f38d8 => { + instruction.operand_count = 1; + let r = instruction.regs[0].num & 0b111; + if mem_oper == OperandSpec::RegMMM { + return Err(DecodeError::InvalidOperand); + } + match r { 0b000 => { - if modrm >= 0b11_000_000 { - return Err(DecodeError::InvalidOperand); - } instruction.mem_size = 48; instruction.opcode = Opcode::AESENCWIDE128KL; - instruction.operands[0] = read_M(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; return Ok(()); } 0b001 => { - if modrm >= 0b11_000_000 { - return Err(DecodeError::InvalidOperand); - } instruction.mem_size = 48; instruction.opcode = Opcode::AESDECWIDE128KL; - instruction.operands[0] = read_M(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; return Ok(()); } 0b010 => { - if modrm >= 0b11_000_000 { - return Err(DecodeError::InvalidOperand); - } instruction.mem_size = 64; instruction.opcode = Opcode::AESENCWIDE256KL; - instruction.operands[0] = read_M(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; return Ok(()); } 0b011 => { - if modrm >= 0b11_000_000 { - return Err(DecodeError::InvalidOperand); - } instruction.mem_size = 64; instruction.opcode = Opcode::AESDECWIDE256KL; - instruction.operands[0] = read_M(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; return Ok(()); } _ => { @@ -8670,55 +8586,66 @@ fn unlikely_operands< } } } - OperandCode::ModRM_0xf30f38dc => { - read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?; - if let OperandSpec::RegMMM = instruction.operands[1] { + OperandCase::ModRM_0xf30f38dc => { + instruction.regs[0].bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if mem_oper == OperandSpec::RegMMM { + instruction.regs[1].bank = RegisterBank::X; instruction.opcode = Opcode::LOADIWKEY; } else { instruction.mem_size = 48; instruction.opcode = Opcode::AESENC128KL; } } - OperandCode::ModRM_0xf30f38dd => { - read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?; - if let OperandSpec::RegMMM = instruction.operands[1] { + OperandCase::ModRM_0xf30f38dd => { + instruction.regs[0].bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if mem_oper == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 48; instruction.opcode = Opcode::AESDEC128KL; } } - OperandCode::ModRM_0xf30f38de => { - read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?; - if let OperandSpec::RegMMM = instruction.operands[1] { + OperandCase::ModRM_0xf30f38de => { + instruction.regs[0].bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if mem_oper == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 64; instruction.opcode = Opcode::AESENC256KL; } } - OperandCode::ModRM_0xf30f38df => { - read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?; - if let OperandSpec::RegMMM = instruction.operands[1] { + OperandCase::ModRM_0xf30f38df => { + instruction.regs[0].bank = RegisterBank::X; + instruction.operands[1] = mem_oper; + if mem_oper == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 64; instruction.opcode = Opcode::AESDEC256KL; } } - OperandCode::ModRM_0xf30f38fa => { + OperandCase::ModRM_0xf30f38fa => { instruction.opcode = Opcode::ENCODEKEY128; - read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?; + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOpcode); + } instruction.regs[0].bank = RegisterBank::D; instruction.regs[1].bank = RegisterBank::D; } - OperandCode::ModRM_0xf30f38fb => { + OperandCase::ModRM_0xf30f38fb => { instruction.opcode = Opcode::ENCODEKEY256; - read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?; + instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + return Err(DecodeError::InvalidOpcode); + } instruction.regs[0].bank = RegisterBank::D; instruction.regs[1].bank = RegisterBank::D; } - OperandCode::ModRM_0xf30f3af0 => { + OperandCase::ModRM_0xf30f3af0 => { let modrm = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; if modrm & 0xc0 != 0xc0 { return Err(DecodeError::InvalidOpcode); @@ -8728,7 +8655,7 @@ fn unlikely_operands< instruction.imm = read_num(words, 1)?; instruction.operands[0] = OperandSpec::ImmU8; } - OperandCode::G_mm_Ed => { + OperandCase::G_mm_Ed => { instruction.regs[0].bank = RegisterBank::MM; instruction.regs[0].num &= 0b111; if mem_oper == OperandSpec::RegMMM { @@ -8737,9 +8664,10 @@ fn unlikely_operands< instruction.mem_size = 4; } } - OperandCode::G_mm_E => { + OperandCase::G_mm_E => { instruction.regs[0].bank = RegisterBank::MM; instruction.regs[0].num &= 0b111; + instruction.operands[1] = mem_oper; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; @@ -8747,8 +8675,8 @@ fn unlikely_operands< instruction.mem_size = 8; } } - OperandCode::Ed_G_mm => { - instruction.operands[1] = instruction.operands[0]; + OperandCase::Ed_G_mm => { + instruction.operands[1] = OperandSpec::RegRRR; instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::MM; instruction.regs[0].num &= 0b111; @@ -8758,18 +8686,8 @@ fn unlikely_operands< instruction.mem_size = 4; } } - OperandCode::Ed_G_xmm => { - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = mem_oper; - instruction.regs[0].bank = RegisterBank::Y; - if mem_oper == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::D; - } else { - instruction.mem_size = 4; - } - } - OperandCode::E_G_mm => { - instruction.operands[1] = instruction.operands[0]; + OperandCase::E_G_mm => { + instruction.operands[1] = OperandSpec::RegRRR; instruction.operands[0] = mem_oper; instruction.regs[0].bank = RegisterBank::MM; instruction.regs[0].num &= 0b111; @@ -8780,11 +8698,11 @@ fn unlikely_operands< instruction.mem_size = 8; } } - OperandCode::G_xmm_Ew_Ib => { + OperandCase::G_xmm_Ew_Ib => { instruction.operands[2] = OperandSpec::ImmU8; instruction.operand_count = 3; instruction.imm = - read_num(words, 1)?; + read_num(words, 1)? as u32; instruction.regs[0].bank = RegisterBank::X; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::D; @@ -8792,7 +8710,7 @@ fn unlikely_operands< instruction.mem_size = 2; } }, - OperandCode::G_xmm_Ed => { + OperandCase::G_xmm_Ed => { instruction.regs[0].bank = RegisterBank::X; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::D; @@ -8800,7 +8718,7 @@ fn unlikely_operands< instruction.mem_size = 4; } }, - OperandCode::G_mm_E_xmm => { + OperandCase::G_mm_E_xmm => { instruction.regs[0].bank = RegisterBank::MM; instruction.regs[0].num &= 0b111; if mem_oper == OperandSpec::RegMMM { @@ -8809,25 +8727,25 @@ fn unlikely_operands< instruction.mem_size = 16; } }, - op @ OperandCode::G_xmm_U_mm | - op @ OperandCode::G_xmm_E_mm => { + op @ OperandCase::G_xmm_U_mm | + op @ OperandCase::G_xmm_E_mm => { instruction.regs[0].bank = RegisterBank::X; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; } else { - if op == OperandCode::G_xmm_U_mm { + if op == OperandCase::G_xmm_U_mm { return Err(DecodeError::InvalidOperand); } else { instruction.mem_size = 8; } } }, - OperandCode::Rv_Gmm_Ib => { + OperandCase::Rv_Gmm_Ib => { instruction.operands[2] = OperandSpec::ImmU8; instruction.operand_count = 3; instruction.imm = - read_num(words, 1)?; + read_num(words, 1)? as u32; instruction.regs[0].bank = RegisterBank::D; if mem_oper == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::MM; @@ -8836,7 +8754,7 @@ fn unlikely_operands< return Err(DecodeError::InvalidOperand); } } - OperandCode::U_mm_G_xmm => { + OperandCase::G_mm_U_xmm => { instruction.regs[1].bank = RegisterBank::X; if mem_oper == OperandSpec::RegMMM { instruction.regs[0].bank = RegisterBank::MM; @@ -8846,82 +8764,90 @@ fn unlikely_operands< } } // sure hope these aren't backwards huh - OperandCode::AL_Xb => { + OperandCase::AL_Xb => { instruction.regs[0] = RegSpec::al(); - if instruction.prefixes.address_size() { - instruction.regs[1] = RegSpec::esi(); - } else { + if !instruction.prefixes.address_size() { instruction.regs[1] = RegSpec::si(); + } else { + instruction.regs[1] = RegSpec::esi(); } instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::Deref; instruction.mem_size = 1; instruction.operand_count = 2; } - OperandCode::Yb_Xb => { - if instruction.prefixes.address_size() { - instruction.operands[0] = OperandSpec::Deref_edi; - instruction.operands[1] = OperandSpec::Deref_esi; - } else { + OperandCase::Yb_Xb => { + if !instruction.prefixes.address_size() { instruction.operands[0] = OperandSpec::Deref_di; instruction.operands[1] = OperandSpec::Deref_si; + } else { + instruction.operands[0] = OperandSpec::Deref_edi; + instruction.operands[1] = OperandSpec::Deref_esi; } instruction.mem_size = 1; instruction.operand_count = 2; } - OperandCode::Yb_AL => { + OperandCase::Yb_AL => { instruction.regs[0] = RegSpec::al(); - if instruction.prefixes.address_size() { - instruction.regs[1] = RegSpec::edi(); - } else { + if !instruction.prefixes.address_size() { instruction.regs[1] = RegSpec::di(); + } else { + instruction.regs[1] = RegSpec::edi(); } instruction.operands[0] = OperandSpec::Deref; instruction.operands[1] = OperandSpec::RegRRR; instruction.mem_size = 1; instruction.operand_count = 2; } - OperandCode::AX_Xv => { - instruction.regs[0] = if instruction.prefixes.operand_size() { - instruction.mem_size = 2; - RegSpec::ax() + OperandCase::AX_Xv => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - instruction.mem_size = 4; - RegSpec::eax() + RegisterBank::D }; - instruction.regs[1] = RegSpec::esi(); + instruction.regs[0].num = 0; + instruction.regs[0].bank = bank; + if !instruction.prefixes.address_size() { + instruction.regs[1] = RegSpec::si(); + } else { + instruction.regs[1] = RegSpec::esi(); + } instruction.operands[1] = OperandSpec::Deref; + instruction.mem_size = bank as u8; } - OperandCode::Yv_AX => { - instruction.regs[0] = if !instruction.prefixes.operand_size() { - instruction.mem_size = 2; - RegSpec::ax() + OperandCase::Yv_AX => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - instruction.mem_size = 4; - RegSpec::eax() + RegisterBank::D }; - if instruction.prefixes.address_size() { - instruction.operands[0] = OperandSpec::Deref_edi; + instruction.regs[0].num = 0; + instruction.regs[0].bank = bank; + if !instruction.prefixes.address_size() { + instruction.regs[1] = RegSpec::di(); } else { - instruction.operands[0] = OperandSpec::Deref_di; + instruction.regs[1] = RegSpec::edi(); } + instruction.operands[0] = OperandSpec::Deref; instruction.operands[1] = OperandSpec::RegRRR; + instruction.mem_size = bank as u8; } - OperandCode::Yv_Xv => { - instruction.mem_size = if !instruction.prefixes.operand_size() { - 2 + OperandCase::Yv_Xv => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 4 + RegisterBank::D }; - if instruction.prefixes.address_size() { - instruction.operands[0] = OperandSpec::Deref_edi; - instruction.operands[1] = OperandSpec::Deref_esi; - } else { + instruction.mem_size = bank as u8; + if !instruction.prefixes.address_size() { instruction.operands[0] = OperandSpec::Deref_di; instruction.operands[1] = OperandSpec::Deref_si; + } else { + instruction.operands[0] = OperandSpec::Deref_edi; + instruction.operands[1] = OperandSpec::Deref_esi; } } - OperandCode::ModRM_0x0f12 => { + OperandCase::ModRM_0x0f12 => { instruction.regs[0].bank = RegisterBank::X; instruction.operands[1] = mem_oper; if instruction.operands[1] == OperandSpec::RegMMM { @@ -8939,7 +8865,7 @@ fn unlikely_operands< } } } - OperandCode::ModRM_0x0f16 => { + OperandCase::ModRM_0x0f16 => { instruction.regs[0].bank = RegisterBank::X; instruction.operands[1] = mem_oper; if instruction.operands[1] == OperandSpec::RegMMM { @@ -8957,10 +8883,11 @@ fn unlikely_operands< } } } - OperandCode::ModRM_0x0f18 => { + OperandCase::ModRM_0x0f18 => { let rrr = instruction.regs[0].num & 0b111; instruction.operands[0] = mem_oper; instruction.operand_count = 1; + // only PREFETCH* are invalid on reg operand instruction.opcode = if mem_oper == OperandSpec::RegMMM && rrr < 4 { Opcode::NOP } else { @@ -8976,15 +8903,15 @@ fn unlikely_operands< instruction.mem_size = 64; } } - OperandCode::Gd_U_xmm => { + OperandCase::Gd_U_xmm => { if instruction.operands[1] != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } instruction.regs[0].bank = RegisterBank::D; instruction.regs[1].bank = RegisterBank::X; } - OperandCode::Gv_E_xmm => { - // in real-mode the reigster is always dword, regardless of prefixing + OperandCase::Gv_E_xmm => { + // in real-mode the register is always dword, regardless of prefixing instruction.regs[0].bank = RegisterBank::D; if instruction.operands[1] == OperandSpec::RegMMM { instruction.regs[1].bank = RegisterBank::X; @@ -8992,94 +8919,67 @@ fn unlikely_operands< instruction.mem_size = 4; } } - OperandCode::M_G_xmm => { - // in real-mode the reigster is always dword, regardless of prefixing + OperandCase::M_G_xmm => { + // in real-mode the register is always dword, regardless of prefixing instruction.regs[0].bank = RegisterBank::D; - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = mem_oper; - if instruction.operands[0] == OperandSpec::RegMMM { - return Err(DecodeError::InvalidOperand); + if instruction.opcode == Opcode::MOVNTSS { + instruction.mem_size = 4; + } else if instruction.opcode == Opcode::MOVNTPD || instruction.opcode == Opcode::MOVNTDQ || instruction.opcode == Opcode::MOVNTPS { + instruction.mem_size = 16; } else { - if instruction.opcode == Opcode::MOVNTSS { - instruction.mem_size = 4; - } else if instruction.opcode == Opcode::MOVNTPD || instruction.opcode == Opcode::MOVNTDQ || instruction.opcode == Opcode::MOVNTPS { - instruction.mem_size = 16; - } else { - instruction.mem_size = 8; - } + instruction.mem_size = 8; } instruction.regs[0].bank = RegisterBank::X; } - OperandCode::Ew_Gw => { - let modrm = read_modrm(words)?; - - instruction.regs[0] = - RegSpec { bank: RegisterBank::W, num: (modrm >> 3) & 7 }; - instruction.operands[0] = read_E(words, instruction, modrm, 2, sink)?; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.mem_size = 2; - instruction.operand_count = 2; - }, - OperandCode::Ew_Sw => { - let opwidth = 2; - let modrm = read_modrm(words)?; - + OperandCase::Ew_Sw => { // check r - if ((modrm >> 3) & 7) > 5 { + let r = instruction.regs[0].num; + if r > 5 { // return Err(()); //Err("Invalid r".to_owned()); return Err(DecodeError::InvalidOperand); } - instruction.regs[0] = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; + instruction.regs[0].bank = RegisterBank::S; instruction.operands[1] = OperandSpec::RegRRR; + instruction.operands[0] = mem_oper; instruction.operand_count = 2; - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.regs[1] = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[0] = OperandSpec::RegMMM; + if mem_oper == OperandSpec::RegMMM { + instruction.regs[1].bank = RegisterBank::W; } else { - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; instruction.mem_size = 2; } }, - OperandCode::Sw_Ew => { - let modrm = read_modrm(words)?; - + OperandCase::Sw_Ew => { // check r - if ((modrm >> 3) & 7) > 5 { - // return Err(()); // Err("Invalid r".to_owned()); + let r = instruction.regs[0].num; + if r > 5 { + // return Err(()); //Err("Invalid r".to_owned()); return Err(DecodeError::InvalidOperand); } - instruction.regs[0] = - RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 }; - // quoth the manual: // ``` // The MOV instruction cannot be used to load the CS register. Attempting to do so // results in an invalid opcode excep-tion (#UD). To load the CS register, use the far // JMP, CALL, or RET instruction. // ``` - if instruction.regs[0].num == 1 { + if r == 1 { return Err(DecodeError::InvalidOperand); } + + instruction.regs[0].bank = RegisterBank::S; instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; instruction.operand_count = 2; - let mod_bits = modrm >> 6; - if mod_bits == 0b11 { - instruction.regs[1] = - RegSpec { bank: RegisterBank::W, num: modrm & 7}; - instruction.operands[1] = OperandSpec::RegMMM; + if mem_oper == OperandSpec::RegMMM { + instruction.regs[1].bank = RegisterBank::W; } else { - instruction.operands[1] = read_M(words, instruction, modrm, sink)?; instruction.mem_size = 2; } }, - OperandCode::CVT_AA => { + OperandCase::CVT_AA => { instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; instruction.opcode = if instruction.prefixes.operand_size() { @@ -9088,7 +8988,7 @@ fn unlikely_operands< Opcode::CBW }; } - OperandCode::CVT_DA => { + OperandCase::CVT_DA => { instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; instruction.opcode = if instruction.prefixes.operand_size() { @@ -9097,22 +8997,30 @@ fn unlikely_operands< Opcode::CWD }; } - OperandCode::Ib => { + OperandCase::Ib => { + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = OperandSpec::ImmU8; instruction.operand_count = 1; } - OperandCode::Iw => { + OperandCase::Iw => { instruction.imm = read_imm_unsigned(words, 2)?; instruction.operands[0] = OperandSpec::ImmU16; if instruction.opcode == Opcode::RETURN { - instruction.mem_size = 2; - } else { instruction.mem_size = 4; + } else { + instruction.mem_size = 6; } instruction.operand_count = 1; } - OperandCode::ModRM_0x0f00 => { + OperandCase::ModRM_0x0f00 => { instruction.operand_count = 1; let modrm = read_modrm(words)?; let r = (modrm >> 3) & 7; @@ -9140,16 +9048,16 @@ fn unlikely_operands< } else { unreachable!("r <= 8"); } - instruction.operands[0] = read_E(words, instruction, modrm, 2, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { instruction.mem_size = 2; } } - OperandCode::ModRM_0x0f01 => { - let opwidth = if instruction.prefixes.operand_size() { - 2 + OperandCase::ModRM_0x0f01 => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 4 + RegisterBank::D }; let modrm = read_modrm(words)?; let r = (modrm >> 3) & 7; @@ -9163,31 +9071,19 @@ fn unlikely_operands< instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; - match m { - 0b000 => { - instruction.opcode = Opcode::ENCLV; - }, - 0b001 => { - instruction.opcode = Opcode::VMCALL; - }, - 0b010 => { - instruction.opcode = Opcode::VMLAUNCH; - }, - 0b011 => { - instruction.opcode = Opcode::VMRESUME; - }, - 0b100 => { - instruction.opcode = Opcode::VMXOFF; - }, - _ => { - return Err(DecodeError::InvalidOpcode); - } + const TBL: [Opcode; 8] = [ + Opcode::ENCLV, Opcode::VMCALL, Opcode::VMLAUNCH, Opcode::VMRESUME, + Opcode::VMXOFF, Opcode::PCONFIG, Opcode::Invalid, Opcode::Invalid, + ]; + instruction.opcode = TBL[m as usize]; + if instruction.opcode == Opcode::Invalid { + return Err(DecodeError::InvalidOpcode); } } else { instruction.opcode = Opcode::SGDT; instruction.operand_count = 1; instruction.mem_size = 63; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 1 { let mod_bits = modrm >> 6; @@ -9242,7 +9138,7 @@ fn unlikely_operands< instruction.opcode = Opcode::SIDT; instruction.operand_count = 1; instruction.mem_size = 63; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 2 { let mod_bits = modrm >> 6; @@ -9281,7 +9177,7 @@ fn unlikely_operands< instruction.opcode = Opcode::LGDT; instruction.operand_count = 1; instruction.mem_size = 63; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 3 { let mod_bits = modrm >> 6; @@ -9345,7 +9241,7 @@ fn unlikely_operands< instruction.opcode = Opcode::LIDT; instruction.operand_count = 1; instruction.mem_size = 63; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else if r == 4 { // TODO: this permits storing only to word-size registers @@ -9353,7 +9249,7 @@ fn unlikely_operands< instruction.opcode = Opcode::SMSW; instruction.operand_count = 1; instruction.mem_size = 2; - instruction.operands[0] = read_E(words, instruction, modrm, 2, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; } else if r == 5 { let mod_bits = modrm >> 6; if mod_bits != 0b11 { @@ -9361,7 +9257,7 @@ fn unlikely_operands< return Err(DecodeError::InvalidOpcode); } instruction.opcode = Opcode::RSTORSSP; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.mem_size = 8; instruction.operand_count = 1; return Ok(()); @@ -9461,7 +9357,7 @@ fn unlikely_operands< instruction.opcode = Opcode::LMSW; instruction.operand_count = 1; instruction.mem_size = 2; - instruction.operands[0] = read_E(words, instruction, modrm, 2, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; } else if r == 7 { let mod_bits = modrm >> 6; let m = modrm & 7; @@ -9514,9 +9410,9 @@ fn unlikely_operands< instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegMMM; instruction.operands[2] = OperandSpec::RegVex; - instruction.regs[0] = RegSpec::eax(); - instruction.regs[1] = RegSpec::edx(); - instruction.regs[3] = RegSpec::ecx(); + instruction.regs[0] = RegSpec::ax(); + instruction.regs[1] = RegSpec::dx(); + instruction.regs[3] = RegSpec::cx(); } else if m == 7 { if instruction.prefixes.rep() { if instruction.prefixes.repnz() || instruction.prefixes.operand_size() { @@ -9545,13 +9441,13 @@ fn unlikely_operands< instruction.opcode = Opcode::INVLPG; instruction.operand_count = 1; instruction.mem_size = 1; - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; } } else { unreachable!("r <= 8"); } } - OperandCode::ModRM_0x0fae => { + OperandCase::ModRM_0x0fae => { let modrm = read_modrm(words)?; let r = (modrm >> 3) & 7; let m = modrm & 7; @@ -9570,7 +9466,7 @@ fn unlikely_operands< return Err(DecodeError::InvalidOpcode); } }; - instruction.operands[0] = read_E(words, instruction, modrm, 1 /* opwidth */, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::B /* opwidth */, sink)?; instruction.mem_size = 64; instruction.operand_count = 1; } else { @@ -9582,7 +9478,7 @@ fn unlikely_operands< return Err(DecodeError::InvalidOpcode); } }; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operand_count = 1; } @@ -9617,7 +9513,7 @@ fn unlikely_operands< return Err(DecodeError::InvalidOpcode); } instruction.opcode = Opcode::PTWRITE; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { instruction.mem_size = 4; } @@ -9663,7 +9559,7 @@ fn unlikely_operands< instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::W); } else { instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D); - }; + } instruction.operands[0] = OperandSpec::RegMMM; instruction.operand_count = 1; } @@ -9676,7 +9572,7 @@ fn unlikely_operands< match r { 6 => { instruction.opcode = Opcode::CLRSSBSY; - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operand_count = 1; instruction.mem_size = 8; return Ok(()); @@ -9751,63 +9647,51 @@ fn unlikely_operands< instruction.mem_size = mem_size; instruction.operands[0] = read_M(words, instruction, modrm, sink)?; } - }, - OperandCode::ModRM_0x0fba => { - let opwidth = if instruction.prefixes.operand_size() { - 4 + } + OperandCase::ModRM_0x0fba => { + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { - 2 + RegisterBank::D }; let modrm = read_modrm(words)?; let r = (modrm >> 3) & 7; - match r { - 0 | 1 | 2 | 3 => { - return Err(DecodeError::InvalidOpcode); - }, - 4 => { - instruction.opcode = Opcode::BT; - } - 5 => { - instruction.opcode = Opcode::BTS; - } - 6 => { - instruction.opcode = Opcode::BTR; - } - 7 => { - instruction.opcode = Opcode::BTC; - } - _ => { - unreachable!("r < 8"); - } + const TBL: [Opcode; 8] = [ + Opcode::Invalid, Opcode::Invalid, Opcode::Invalid, Opcode::Invalid, + Opcode::BT, Opcode::BTS, Opcode::BTR, Opcode::BTC + ]; + instruction.opcode = TBL[r as usize]; + if instruction.opcode == Opcode::Invalid { + return Err(DecodeError::InvalidOpcode); } - instruction.operands[0] = read_E(words, instruction, modrm, opwidth, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; if instruction.operands[0] != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = bank as u8; } instruction.imm = read_imm_signed(words, 1)? as u32; instruction.operands[1] = OperandSpec::ImmI8; instruction.operand_count = 2; } - op @ OperandCode::Rq_Cq_0 | - op @ OperandCode::Rq_Dq_0 | - op @ OperandCode::Cq_Rq_0 | - op @ OperandCode::Dq_Rq_0 => { + op @ OperandCase::Rq_Cq_0 | + op @ OperandCase::Rq_Dq_0 | + op @ OperandCase::Cq_Rq_0 | + op @ OperandCase::Dq_Rq_0 => { let modrm = read_modrm(words)?; let m = modrm & 7; let r = (modrm >> 3) & 7; let bank = match op { - OperandCode::Rq_Cq_0 | - OperandCode::Cq_Rq_0 => { + OperandCase::Rq_Cq_0 | + OperandCase::Cq_Rq_0 => { if r != 0 && r != 2 && r != 3 && r != 4 { return Err(DecodeError::InvalidOperand); } RegisterBank::CR }, - OperandCode::Rq_Dq_0 | - OperandCode::Dq_Rq_0 => { + OperandCase::Rq_Dq_0 | + OperandCase::Dq_Rq_0 => { if r > 7 { // unreachable but mirrors x86_64 code return Err(DecodeError::InvalidOperand); } @@ -9816,10 +9700,10 @@ fn unlikely_operands< _ => unsafe { unreachable_unchecked() } }; let (rrr, mmm) = match op { - OperandCode::Rq_Cq_0 | - OperandCode::Rq_Dq_0 => (1, 0), - OperandCode::Cq_Rq_0 | - OperandCode::Dq_Rq_0 => (0, 1), + OperandCase::Rq_Cq_0 | + OperandCase::Rq_Dq_0 => (1, 0), + OperandCase::Cq_Rq_0 | + OperandCase::Dq_Rq_0 => (0, 1), _ => unsafe { unreachable_unchecked() } }; @@ -9831,178 +9715,211 @@ fn unlikely_operands< instruction.operands[rrr] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::FS => { - instruction.regs[0] = RegSpec::fs(); + OperandCase::CS => { + instruction.regs[0] = RegSpec::cs(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::GS => { - instruction.regs[0] = RegSpec::gs(); + OperandCase::DS => { + instruction.regs[0] = RegSpec::ds(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::CS => { - instruction.regs[0] = RegSpec::cs(); + OperandCase::ES => { + instruction.regs[0] = RegSpec::es(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::DS => { - instruction.regs[0] = RegSpec::ds(); + OperandCase::SS => { + instruction.regs[0] = RegSpec::ss(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::ES => { - instruction.regs[0] = RegSpec::es(); + OperandCase::FS => { + instruction.regs[0] = RegSpec::fs(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::SS => { - instruction.regs[0] = RegSpec::ss(); + OperandCase::GS => { + instruction.regs[0] = RegSpec::gs(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operand_count = 1; } - OperandCode::AL_Ib => { + OperandCase::AL_Ib => { instruction.regs[0] = RegSpec::al(); + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::ImmU8; instruction.operand_count = 2; } - OperandCode::AX_Ib => { - instruction.regs[0] = if !instruction.prefixes.operand_size() { - RegSpec::ax() + OperandCase::AX_Ib => { + instruction.regs[0].num = 0; + instruction.regs[0].bank = if instruction.prefixes.operand_size() { + RegisterBank::D } else { - RegSpec::eax() + RegisterBank::W }; + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::ImmU8; instruction.operand_count = 2; } - OperandCode::Ib_AL => { + OperandCase::Ib_AL => { instruction.regs[0] = RegSpec::al(); + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = OperandSpec::ImmU8; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::Ib_AX => { - instruction.regs[0] = if !instruction.prefixes.operand_size() { - RegSpec::ax() + OperandCase::Ib_AX => { + instruction.regs[0].num = 0; + instruction.regs[0].bank = if instruction.prefixes.operand_size() { + RegisterBank::D } else { - RegSpec::eax() + RegisterBank::W }; + instruction.imm = + read_imm_signed(words, 1)? as u32; + sink.record( + words.offset() as u32 * 8 - 8, + words.offset() as u32 * 8 - 1, + InnerDescription::Number("1-byte immediate", instruction.imm as i64) + .with_id(words.offset() as u32 * 8), + ); instruction.operands[0] = OperandSpec::ImmU8; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::AX_DX => { - instruction.regs[0] = if !instruction.prefixes.operand_size() { - RegSpec::ax() + OperandCase::AX_DX => { + instruction.regs[0].num = 0; + instruction.regs[0].bank = if instruction.prefixes.operand_size() { + RegisterBank::D } else { - RegSpec::eax() + RegisterBank::W }; instruction.regs[1] = RegSpec::dx(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegMMM; instruction.operand_count = 2; } - OperandCode::AL_DX => { + OperandCase::AL_DX => { instruction.regs[0] = RegSpec::al(); instruction.regs[1] = RegSpec::dx(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegMMM; instruction.operand_count = 2; } - OperandCode::DX_AX => { - instruction.regs[0] = if !instruction.prefixes.operand_size() { - RegSpec::ax() + OperandCase::DX_AX => { + instruction.regs[0].num = 0; + instruction.regs[0].bank = if instruction.prefixes.operand_size() { + RegisterBank::D } else { - RegSpec::eax() + RegisterBank::W }; instruction.regs[1] = RegSpec::dx(); instruction.operands[0] = OperandSpec::RegMMM; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::DX_AL => { + OperandCase::DX_AL => { instruction.regs[0] = RegSpec::al(); instruction.regs[1] = RegSpec::dx(); instruction.operands[0] = OperandSpec::RegMMM; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; } - OperandCode::Yb_DX => { + OperandCase::Yb_DX => { instruction.regs[0] = RegSpec::dl(); - instruction.regs[1] = RegSpec::edi(); + instruction.regs[1] = RegSpec::di(); instruction.operands[0] = OperandSpec::Deref; instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; instruction.mem_size = 1; } - OperandCode::Yv_DX => { + OperandCase::Yv_DX => { instruction.regs[0] = RegSpec::dx(); - instruction.regs[1] = RegSpec::edi(); + instruction.regs[1] = RegSpec::di(); instruction.operands[0] = OperandSpec::Deref; instruction.operands[1] = OperandSpec::RegRRR; - if instruction.prefixes.operand_size() { - instruction.mem_size = 4; - } else { + if !instruction.prefixes.operand_size() { instruction.mem_size = 2; + } else { + instruction.mem_size = 4; } instruction.operand_count = 2; } - OperandCode::DX_Xb => { + OperandCase::DX_Xb => { instruction.regs[0] = RegSpec::dl(); - instruction.regs[1] = RegSpec::esi(); + instruction.regs[1] = RegSpec::si(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::Deref; instruction.operand_count = 2; instruction.mem_size = 1; } - OperandCode::AH => { + OperandCase::AH => { instruction.operands[0] = OperandSpec::Nothing; instruction.operand_count = 0; } - OperandCode::DX_Xv => { + OperandCase::DX_Xv => { instruction.regs[0] = RegSpec::dx(); - instruction.regs[1] = RegSpec::esi(); + instruction.regs[1] = RegSpec::si(); instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::Deref; - if instruction.prefixes.operand_size() { - instruction.mem_size = 4; - } else { + if !instruction.prefixes.operand_size() { instruction.mem_size = 2; + } else { + instruction.mem_size = 4; } 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(words, instruction, operand_code, sink); - } - OperandCode::M_Gv => { - // `lea` operands (`Gv_M`) opportunistically reject a register form of `mmm` early, but - // leaves `M_Gv` to test memory-ness of the `mmm` operand directly. also, swap - // operands. - if let OperandSpec::RegMMM = instruction.operands[1] { - return Err(DecodeError::InvalidOperand); + OperandCase::x87_d8 | + OperandCase::x87_d9 | + OperandCase::x87_da | + OperandCase::x87_db | + OperandCase::x87_dc | + OperandCase::x87_dd | + OperandCase::x87_de | + OperandCase::x87_df => { + return decode_x87(words, instruction, operand_code.operand_case_handler_index(), sink); + } + OperandCase::MOVDIR64B => { + instruction.mem_size = 64; + if !instruction.prefixes.address_size() { + instruction.regs[0].bank = RegisterBank::W; + } else { + instruction.regs[0].bank = RegisterBank::D; } - let temp = instruction.operands[1]; - instruction.operands[1] = instruction.operands[0]; - instruction.operands[0] = temp; } - OperandCode::ModRM_0x62 => { + OperandCase::ModRM_0x62 => { let modrm = read_modrm(words)?; if modrm < 0xc0 { instruction.regs[0] = RegSpec { bank: RegisterBank::D, num: (modrm >> 3) & 7 }; - if instruction.prefixes.operand_size() { + if !instruction.prefixes.operand_size() { instruction.regs[0].bank = RegisterBank::W; instruction.mem_size = 4; } else { @@ -10027,25 +9944,241 @@ fn unlikely_operands< } } } - _ => { - // 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; - return Err(DecodeError::InvalidOperand); + OperandCase::AbsFar => { + instruction.operands[0] = OperandSpec::AbsoluteFarAddress; + instruction.operand_count = 1; + instruction.mem_size = 0; + // read segment + let addr_size = if !instruction.prefixes.operand_size() { + 2 + } else { + 4 + }; + instruction.imm = read_num(words, addr_size)?; + instruction.disp = read_num(words, 2)? as u16 as u32; } + OperandCase::Ew_Gw => { + let modrm = read_modrm(words)?; + + instruction.regs[0] = + RegSpec { bank: RegisterBank::W, num: (modrm >> 3) & 7 }; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; + instruction.operands[1] = OperandSpec::RegRRR; + instruction.mem_size = 2; + instruction.operand_count = 2; + }, }; Ok(()) } +#[inline(always)] +fn read_0f_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { + // seems like f2 takes priority, then f3, then 66, then "no prefix". for SOME instructions an + // invalid prefix is in fact an invalid instruction. so just duplicate for the four kinds of + // opcode lists. + if prefixes.repnz() { + REPNZ_0F_CODES[opcode as usize] + } else if prefixes.rep() { + REP_0F_CODES[opcode as usize] + } else if prefixes.operand_size() { + OPERAND_SIZE_0F_CODES[opcode as usize] + } else { + NORMAL_0F_CODES[opcode as usize] + } +} + +fn read_0f38_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { + if prefixes.rep() { + return match opcode { + 0xd8 => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38d8), + 0xdc => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38dc), + 0xdd => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38dd), + 0xde => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38de), + 0xdf => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38df), + 0xf6 => OpcodeRecord::new(Interpretation::Instruction(Opcode::ADOX), OperandCode::Gv_Ev), + 0xf8 => { + prefixes.unset_operand_size(); + OpcodeRecord::new(Interpretation::Instruction(Opcode::ENQCMDS), OperandCode::INV_Gv_M) + }, + 0xfa => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38fa), + 0xfb => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0xf30f38fb), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } + + if prefixes.repnz() { + return match opcode { + 0xf0 => OpcodeRecord::new(Interpretation::Instruction(Opcode::CRC32), OperandCode::Gv_Eb), + 0xf1 => OpcodeRecord::new(Interpretation::Instruction(Opcode::CRC32), OperandCode::Gd_Ev), + 0xf8 => { + prefixes.unset_operand_size(); + OpcodeRecord::new(Interpretation::Instruction(Opcode::ENQCMD), OperandCode::INV_Gv_M) + }, + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } + + if prefixes.operand_size() { + // leave operand size present for `movbe` + if opcode != 0xf0 && opcode != 0xf1 { + prefixes.unset_operand_size(); + } + + return match opcode { + 0x00 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSHUFB), OperandCode::G_E_xmm), + 0x01 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDW), OperandCode::G_E_xmm), + 0x02 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDD), OperandCode::G_E_xmm), + 0x03 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDSW), OperandCode::G_E_xmm), + 0x04 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMADDUBSW), OperandCode::G_E_xmm), + 0x05 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBW), OperandCode::G_E_xmm), + 0x06 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBD), OperandCode::G_E_xmm), + 0x07 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBSW), OperandCode::G_E_xmm), + 0x08 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGNB), OperandCode::G_E_xmm), + 0x09 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGNW), OperandCode::G_E_xmm), + 0x0a => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGND), OperandCode::G_E_xmm), + 0x0b => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMULHRSW), OperandCode::G_E_xmm), + 0x10 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PBLENDVB), OperandCode::G_E_xmm), + 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDVPS), OperandCode::G_E_xmm), + 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDVPD), OperandCode::G_E_xmm), + 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PTEST), OperandCode::G_E_xmm), + 0x1c => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSB), OperandCode::G_E_xmm), + 0x1d => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSW), OperandCode::G_E_xmm), + 0x1e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSD), OperandCode::G_E_xmm), + 0x20 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXBW), OperandCode::PMOVX_G_E_xmm), + 0x21 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXBD), OperandCode::PMOVX_G_E_xmm), + 0x22 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXBQ), OperandCode::PMOVX_G_E_xmm), + 0x23 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXWD), OperandCode::PMOVX_G_E_xmm), + 0x24 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXWQ), OperandCode::PMOVX_G_E_xmm), + 0x25 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVSXDQ), OperandCode::PMOVX_G_E_xmm), + 0x28 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMULDQ), OperandCode::G_E_xmm), + 0x29 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPEQQ), OperandCode::G_E_xmm), + 0x2a => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVNTDQA), OperandCode::G_M_xmm), + 0x2b => OpcodeRecord::new(Interpretation::Instruction(Opcode::PACKUSDW), OperandCode::G_E_xmm), + 0x30 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXBW), OperandCode::PMOVX_G_E_xmm), + 0x31 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXBD), OperandCode::PMOVX_G_E_xmm), + 0x32 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXBQ), OperandCode::PMOVX_G_E_xmm), + 0x33 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXWD), OperandCode::PMOVX_G_E_xmm), + 0x34 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXWQ), OperandCode::PMOVX_G_E_xmm), + 0x35 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMOVZXDQ), OperandCode::PMOVX_G_E_xmm), + 0x37 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPGTQ), OperandCode::G_E_xmm), + 0x38 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMINSB), OperandCode::G_E_xmm), + 0x39 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMINSD), OperandCode::G_E_xmm), + 0x3a => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMINUW), OperandCode::G_E_xmm), + 0x3b => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMINUD), OperandCode::G_E_xmm), + 0x3c => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMAXSB), OperandCode::G_E_xmm), + 0x3d => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMAXSD), OperandCode::G_E_xmm), + 0x3e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMAXUW), OperandCode::G_E_xmm), + 0x3f => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMAXUD), OperandCode::G_E_xmm), + 0x40 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMULLD), OperandCode::G_E_xmm), + 0x41 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHMINPOSUW), OperandCode::G_E_xmm), + 0x80 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INVEPT), OperandCode::INV_Gv_M), + 0x81 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INVVPID), OperandCode::INV_Gv_M), + 0x82 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INVPCID), OperandCode::INV_Gv_M), + 0xcf => OpcodeRecord::new(Interpretation::Instruction(Opcode::GF2P8MULB), OperandCode::G_E_xmm), + 0xdb => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESIMC), OperandCode::G_E_xmm), + 0xdc => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESENC), OperandCode::G_E_xmm), + 0xdd => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESENCLAST), OperandCode::G_E_xmm), + 0xde => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESDEC), OperandCode::G_E_xmm), + 0xdf => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESDECLAST), OperandCode::G_E_xmm), + 0xf0 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVBE), OperandCode::Gv_M), + 0xf1 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVBE), OperandCode::M_Gv), + 0xf5 => OpcodeRecord::new(Interpretation::Instruction(Opcode::WRUSS), OperandCode::Md_Gd), + 0xf6 => OpcodeRecord::new(Interpretation::Instruction(Opcode::ADCX), OperandCode::Gv_Ev), + 0xf8 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVDIR64B), OperandCode::MOVDIR64B), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } else { + return match opcode { + 0x00 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSHUFB), OperandCode::G_E_mm), + 0x01 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDW), OperandCode::G_E_mm), + 0x02 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDD), OperandCode::G_E_mm), + 0x03 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHADDSW), OperandCode::G_E_mm), + 0x04 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMADDUBSW), OperandCode::G_E_mm), + 0x05 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBW), OperandCode::G_E_mm), + 0x06 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBD), OperandCode::G_E_mm), + 0x07 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PHSUBSW), OperandCode::G_E_mm), + 0x08 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGNB), OperandCode::G_E_mm), + 0x09 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGNW), OperandCode::G_E_mm), + 0x0a => OpcodeRecord::new(Interpretation::Instruction(Opcode::PSIGND), OperandCode::G_E_mm), + 0x0b => OpcodeRecord::new(Interpretation::Instruction(Opcode::PMULHRSW), OperandCode::G_E_mm), + 0x1c => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSB), OperandCode::G_E_mm), + 0x1d => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSW), OperandCode::G_E_mm), + 0x1e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PABSD), OperandCode::G_E_mm), + 0xc8 => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA1NEXTE), OperandCode::G_E_xmm), + 0xc9 => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA1MSG1), OperandCode::G_E_xmm), + 0xca => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA1MSG2), OperandCode::G_E_xmm), + 0xcb => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA256RNDS2), OperandCode::G_E_xmm), + 0xcc => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA256MSG1), OperandCode::G_E_xmm), + 0xcd => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA256MSG2), OperandCode::G_E_xmm), + 0xf0 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVBE), OperandCode::Gv_M), + 0xf1 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVBE), OperandCode::M_Gv), + 0xf6 => OpcodeRecord::new(Interpretation::Instruction(Opcode::WRSS), OperandCode::Md_Gd), + 0xf9 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MOVDIRI), OperandCode::Md_Gd), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } +} + +fn read_0f3a_opcode(&mut self, opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord { + if prefixes.rep() { + if prefixes != &Prefixes::new(0x10) { + return OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing); + } + return match opcode { + 0xf0 => OpcodeRecord::new(Interpretation::Instruction(Opcode::HRESET), OperandCode::ModRM_0xf30f3af0), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } + + if prefixes.repnz() { + return OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing); + } + + if prefixes.operand_size() { + return match opcode { + 0x08 => OpcodeRecord::new(Interpretation::Instruction(Opcode::ROUNDPS), OperandCode::G_E_xmm_Ib), + 0x09 => OpcodeRecord::new(Interpretation::Instruction(Opcode::ROUNDPD), OperandCode::G_E_xmm_Ib), + 0x0a => OpcodeRecord::new(Interpretation::Instruction(Opcode::ROUNDSS), OperandCode::G_E_xmm_Ib), + 0x0b => OpcodeRecord::new(Interpretation::Instruction(Opcode::ROUNDSD), OperandCode::G_E_xmm_Ib), + 0x0c => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDPS), OperandCode::G_E_xmm_Ib), + 0x0d => OpcodeRecord::new(Interpretation::Instruction(Opcode::BLENDPD), OperandCode::G_E_xmm_Ib), + 0x0e => OpcodeRecord::new(Interpretation::Instruction(Opcode::PBLENDW), OperandCode::G_E_xmm_Ib), + 0x0f => OpcodeRecord::new(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_xmm_Ib), + 0x14 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRB), OperandCode::G_Ev_xmm_Ib), + 0x15 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRW), OperandCode::G_Ev_xmm_Ib), + 0x16 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PEXTRD), OperandCode::G_Ev_xmm_Ib), + 0x17 => OpcodeRecord::new(Interpretation::Instruction(Opcode::EXTRACTPS), OperandCode::G_Ev_xmm_Ib), + 0x20 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRB), OperandCode::G_Ev_xmm_Ib), + 0x21 => OpcodeRecord::new(Interpretation::Instruction(Opcode::INSERTPS), OperandCode::G_Ev_xmm_Ib), + 0x22 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PINSRD), OperandCode::G_Ev_xmm_Ib), + 0x40 => OpcodeRecord::new(Interpretation::Instruction(Opcode::DPPS), OperandCode::G_E_xmm_Ib), + 0x41 => OpcodeRecord::new(Interpretation::Instruction(Opcode::DPPD), OperandCode::G_E_xmm_Ib), + 0x42 => OpcodeRecord::new(Interpretation::Instruction(Opcode::MPSADBW), OperandCode::G_E_xmm_Ib), + 0x44 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCLMULQDQ), OperandCode::G_E_xmm_Ib), + 0x60 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPESTRM), OperandCode::G_E_xmm_Ib), + 0x61 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPESTRI), OperandCode::G_E_xmm_Ib), + 0x62 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPISTRM), OperandCode::G_E_xmm_Ib), + 0x63 => OpcodeRecord::new(Interpretation::Instruction(Opcode::PCMPISTRI), OperandCode::G_E_xmm_Ib), + 0xcc => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA1RNDS4), OperandCode::G_E_xmm_Ib), + 0xce => OpcodeRecord::new(Interpretation::Instruction(Opcode::GF2P8AFFINEQB), OperandCode::G_E_xmm_Ub), + 0xcf => OpcodeRecord::new(Interpretation::Instruction(Opcode::GF2P8AFFINEINVQB), OperandCode::G_E_xmm_Ub), + 0xdf => OpcodeRecord::new(Interpretation::Instruction(Opcode::AESKEYGENASSIST), OperandCode::G_E_xmm_Ub), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; + } + + return match opcode { + 0xcc => OpcodeRecord::new(Interpretation::Instruction(Opcode::SHA1RNDS4), OperandCode::G_E_xmm_Ub), + 0x0f => OpcodeRecord::new(Interpretation::Instruction(Opcode::PALIGNR), OperandCode::G_E_mm_Ib), + _ => OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), + }; +} +} + fn decode_x87< T: Reader<::Address, ::Word>, S: DescriptionSink, ->(words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> { +>(words: &mut T, instruction: &mut Instruction, operand_code: OperandCase, sink: &mut S) -> Result<(), DecodeError> { sink.record( words.offset() as u32 * 8 - 8, words.offset() as u32 * 8 - 1, @@ -10082,7 +10215,7 @@ fn decode_x87< let r = (modrm >> 3) & 0b111; let (opcode, x87_operands) = match operand_code { - OperandCode::x87_d8 => { + OperandCase::x87_d8 => { match r { 0 => (Opcode::FADD, OperandCodeX87::St_Edst), 1 => (Opcode::FMUL, OperandCodeX87::St_Edst), @@ -10095,7 +10228,7 @@ fn decode_x87< _ => { unreachable!("impossible r"); } } } - OperandCode::x87_d9 => { + OperandCase::x87_d9 => { match r { 0 => (Opcode::FLD, OperandCodeX87::St_Edst), 1 => { @@ -10194,7 +10327,7 @@ fn decode_x87< _ => { unreachable!("impossible r"); } } } - OperandCode::x87_da => { + OperandCase::x87_da => { if modrm >= 0xc0 { match r { 0 => (Opcode::FCMOVB, OperandCodeX87::St_Est), @@ -10223,7 +10356,7 @@ fn decode_x87< } } } - OperandCode::x87_db => { + OperandCase::x87_db => { if modrm >= 0xc0 { match r { 0 => (Opcode::FCMOVNB, OperandCodeX87::St_Est), @@ -10263,7 +10396,7 @@ fn decode_x87< } } - OperandCode::x87_dc => { + OperandCase::x87_dc => { // mod=11 swaps operand order for some instructions if modrm >= 0xc0 { match r { @@ -10291,7 +10424,7 @@ fn decode_x87< } } } - OperandCode::x87_dd => { + OperandCase::x87_dd => { if modrm >= 0xc0 { match r { 0 => (Opcode::FFREE, OperandCodeX87::Est), @@ -10318,7 +10451,7 @@ fn decode_x87< } } } - OperandCode::x87_de => { + OperandCase::x87_de => { if modrm >= 0xc0 { match r { 0 => (Opcode::FADDP, OperandCodeX87::Est_St), @@ -10353,7 +10486,7 @@ fn decode_x87< } } } - OperandCode::x87_df => { + OperandCase::x87_df => { if modrm >= 0xc0 { match r { 0 => (Opcode::FFREEP, OperandCodeX87::Est), @@ -10429,7 +10562,7 @@ fn decode_x87< OperandCodeX87::St_Ew => { instruction.operands[0] = OperandSpec::RegRRR; instruction.regs[0] = RegSpec::st(0); - instruction.operands[1] = read_E(words, instruction, modrm, 2, sink)?; + instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 2; } @@ -10438,7 +10571,7 @@ fn decode_x87< OperandCodeX87::St_Mm => { instruction.operands[0] = OperandSpec::RegRRR; instruction.regs[0] = RegSpec::st(0); - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[1] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10448,7 +10581,7 @@ fn decode_x87< OperandCodeX87::St_Mq => { instruction.operands[0] = OperandSpec::RegRRR; instruction.regs[0] = RegSpec::st(0); - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[1] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10458,7 +10591,7 @@ fn decode_x87< OperandCodeX87::St_Md => { instruction.operands[0] = OperandSpec::RegRRR; instruction.regs[0] = RegSpec::st(0); - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[1] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10468,7 +10601,7 @@ fn decode_x87< OperandCodeX87::St_Mw => { instruction.operands[0] = OperandSpec::RegRRR; instruction.regs[0] = RegSpec::st(0); - instruction.operands[1] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[1] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10476,7 +10609,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Ew => { - instruction.operands[0] = read_E(words, instruction, modrm, 2, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; instruction.operand_count = 1; if instruction.operands[0] != OperandSpec::RegMMM { instruction.mem_size = 2; @@ -10516,7 +10649,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Mm_St => { - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10526,7 +10659,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Mq_St => { - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10536,7 +10669,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Md_St => { - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10546,7 +10679,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Mw_St => { - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if instruction.operands[0] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -10556,7 +10689,7 @@ fn decode_x87< instruction.operand_count = 2; } OperandCodeX87::Ex87S => { - instruction.operands[0] = read_E(words, instruction, modrm, 4, sink)?; + instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operand_count = 1; if instruction.operands[0] == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); @@ -10570,7 +10703,6 @@ fn decode_x87< Ok(()) } - #[inline] fn read_num::Address, ::Word>>(bytes: &mut T, width: u8) -> Result { match width { @@ -10613,1111 +10745,1111 @@ fn read_modrm::Address, ::Address, ::Word>, - S: DescriptionSink + S: DescriptionSink, >(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { let vex_start = words.offset() as u32 * 8 - 8; let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; @@ -142,7 +139,6 @@ pub(crate) fn three_byte_vex< 0b00010 => VEXOpcodeMap::Map0F38, 0b00011 => VEXOpcodeMap::Map0F3A, _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } }; @@ -150,7 +146,6 @@ pub(crate) fn three_byte_vex< bank: RegisterBank::X, num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111, }; - sink.record( vex_start + 11, vex_start + 14, @@ -211,17 +206,24 @@ pub(crate) fn three_byte_vex< instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); + sink.record( + vex_start + 23, + vex_start + 23, + InnerDescription::Boundary("vex prefix ends/opcode begins") + .with_id(vex_start + 23) + ); + read_vex_instruction(m, words, instruction, p, sink)?; - instruction.length = words.offset() as u8; instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode Ok(()) } +#[inline(always)] pub(crate) fn two_byte_vex< T: Reader<::Address, ::Word>, S: DescriptionSink, >(words: &mut T, vex_byte: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { - let vex_start = words.offset() * 8 - 8; + let vex_start = words.offset() as u32 * 8 - 8; let p = vex_byte & 0x03; let p = match p { 0x00 => VEXOpcodePrefix::None, @@ -277,12 +279,19 @@ pub(crate) fn two_byte_vex< instruction.prefixes.vex_from_c5(vex_byte); + sink.record( + vex_start + 15, + vex_start + 15, + InnerDescription::Boundary("vex prefix ends/opcode begins") + .with_id(vex_start + 15) + ); + read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p, sink)?; - instruction.length = words.offset() as u8; instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode Ok(()) } +#[inline(always)] fn read_vex_operands< T: Reader<::Address, ::Word>, S: DescriptionSink, @@ -292,59 +301,35 @@ fn read_vex_operands< VEXOperandCode::VPS_71 => { let modrm = read_modrm(words)?; if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLW; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAW; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLW; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::X); - instruction.regs[3].bank = RegisterBank::X; - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.imm = read_imm_unsigned(words, 1)?; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - Ok(()) - } - VEXOperandCode::VPS_71_L => { - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + + let bank = if L { + RegisterBank::Y + } else { + RegisterBank::X + }; + + let rrr = (modrm >> 3) & 0b111; + + if rrr == 0b001 && L { + return Err(DecodeError::InvalidOpcode); } - match (modrm >> 3) & 0b111 { - 0b001 => { - instruction.opcode = Opcode::VPSLLW; - } - 0b010 => { - instruction.opcode = Opcode::VPSRLW; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAW; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLW; - } + + instruction.opcode = match rrr { + 0b001 => Opcode::VPSLLW, + 0b010 => Opcode::VPSRLW, + 0b100 => Opcode::VPSRAW, + 0b110 => Opcode::VPSLLW, _ => { return Err(DecodeError::InvalidOpcode); } - } + }; instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::Y); - instruction.regs[3].bank = RegisterBank::Y; + RegSpec::from_parts(modrm & 7, bank); + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegVex; instruction.operands[1] = OperandSpec::RegRRR; instruction.imm = read_imm_unsigned(words, 1)?; @@ -355,39 +340,18 @@ fn read_vex_operands< VEXOperandCode::VPS_72 => { let modrm = read_modrm(words)?; if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - match (modrm >> 3) & 0b111 { - 0b010 => { - instruction.opcode = Opcode::VPSRLD; - } - 0b100 => { - instruction.opcode = Opcode::VPSRAD; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLD; - } - _ => { - return Err(DecodeError::InvalidOpcode); - } - } - instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::X); - instruction.regs[3].bank = RegisterBank::X; - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.imm = read_imm_unsigned(words, 1)?; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - Ok(()) - } - VEXOperandCode::VPS_72_L => { - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } + + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + + let bank = if L { + RegisterBank::Y + } else { + RegisterBank::X + }; + match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLD; @@ -403,8 +367,8 @@ fn read_vex_operands< } } instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::Y); - instruction.regs[3].bank = RegisterBank::Y; + RegSpec::from_parts(modrm & 7, bank); + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegVex; instruction.operands[1] = OperandSpec::RegRRR; instruction.imm = read_imm_unsigned(words, 1)?; @@ -415,9 +379,18 @@ fn read_vex_operands< VEXOperandCode::VPS_73 => { let modrm = read_modrm(words)?; if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } + + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + + let bank = if L { + RegisterBank::Y + } else { + RegisterBank::X + }; + match (modrm >> 3) & 0b111 { 0b010 => { instruction.opcode = Opcode::VPSRLQ; @@ -436,47 +409,8 @@ fn read_vex_operands< } } instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::X); - instruction.regs[3].bank = RegisterBank::X; - instruction.operands[0] = OperandSpec::RegVex; - instruction.operands[1] = OperandSpec::RegRRR; - instruction.imm = read_imm_unsigned(words, 1)?; - instruction.operands[2] = OperandSpec::ImmI8; - instruction.operand_count = 3; - Ok(()) - } - VEXOperandCode::VPS_73_L => { - let modrm = read_modrm(words)?; - if modrm & 0xc0 != 0xc0 { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOperand); - } - match (modrm >> 3) & 0b111 { - 0b000 | - 0b001 | - 0b100 | - 0b101 => { - return Err(DecodeError::InvalidOpcode); - } - 0b010 => { - instruction.opcode = Opcode::VPSRLQ; - } - 0b011 => { - instruction.opcode = Opcode::VPSRLDQ; - } - 0b110 => { - instruction.opcode = Opcode::VPSLLQ; - } - 0b111 => { - instruction.opcode = Opcode::VPSLLDQ; - } - _ => { - unreachable!("r is only three bits"); - } - } - instruction.regs[0] = - RegSpec::from_parts(modrm & 7, RegisterBank::Y); - instruction.regs[3].bank = RegisterBank::Y; + RegSpec::from_parts(modrm & 7, bank); + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegVex; instruction.operands[1] = OperandSpec::RegRRR; instruction.imm = read_imm_unsigned(words, 1)?; @@ -499,7 +433,6 @@ fn read_vex_operands< }, other => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } if instruction.opcode == Opcode::VMOVSS { @@ -528,7 +461,6 @@ fn read_vex_operands< }, other => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } if instruction.opcode == Opcode::VMOVSS { @@ -578,7 +510,6 @@ fn read_vex_operands< VEXOperandCode::Nothing => { if instruction.opcode == Opcode::VZEROUPPER || instruction.opcode == Opcode::VZEROALL { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } } @@ -587,13 +518,12 @@ fn read_vex_operands< }, VEXOperandCode::Ev_G_xmm_imm8 => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; instruction.operands[2] = OperandSpec::ImmU8; @@ -620,13 +550,12 @@ fn read_vex_operands< }, VEXOperandCode::G_xmm_Ed => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; if mem_oper != OperandSpec::RegMMM { @@ -637,13 +566,12 @@ fn read_vex_operands< } VEXOperandCode::Ed_G_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operands[0] = mem_oper; instruction.operands[1] = OperandSpec::RegRRR; if mem_oper != OperandSpec::RegMMM { @@ -654,69 +582,51 @@ fn read_vex_operands< } VEXOperandCode::VCVT_Gd_Ed_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if let OperandSpec::RegMMM = mem_oper { instruction.regs[1].bank = RegisterBank::X; } else { - instruction.mem_size = 4; + if instruction.opcode == Opcode::VCVTTSD2SI || instruction.opcode == Opcode::VCVTSD2SI { + instruction.mem_size = 8; + } else { + instruction.mem_size = 4; + } } instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; instruction.operand_count = 2; Ok(()) } - VEXOperandCode::VCVT_Gd_Eq_xmm => { + VEXOperandCode::M_G_xyLmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; - if let OperandSpec::RegMMM = mem_oper { - instruction.regs[1].bank = RegisterBank::X; - } else { - instruction.mem_size = 8; - } - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operand_count = 2; - Ok(()) - } - op @ VEXOperandCode::E_G_xmm | - op @ VEXOperandCode::M_G_xmm => { - if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; + if mem_oper == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - let modrm = read_modrm(words)?; - instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; - match (op, mem_oper) { - (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => { - /* this is the only accepted operand */ - } - (VEXOperandCode::M_G_xmm, OperandSpec::RegMMM) => { - return Err(DecodeError::InvalidOperand); - } - (VEXOperandCode::M_G_xmm, _) | // otherwise it's memory-constrained and a memory operand - (_, _) => { // ... or unconstrained - /* and this is always accepted */ - } - } if mem_oper != OperandSpec::RegMMM { if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS { instruction.mem_size = 8; } else { - instruction.mem_size = 16; + if L { + instruction.mem_size = 32; + } else { + instruction.mem_size = 16; + } } } instruction.operands[0] = mem_oper; @@ -724,32 +634,42 @@ fn read_vex_operands< instruction.operand_count = 2; Ok(()) } - VEXOperandCode::Ud_G_xmm => { + VEXOperandCode::M_G_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; - if mem_oper != OperandSpec::RegMMM { + if mem_oper == OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; + if mem_oper != OperandSpec::RegMMM { + if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS { + instruction.mem_size = 8; + } else { + instruction.mem_size = 16; + } + } + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; instruction.operand_count = 2; Ok(()) } - VEXOperandCode::Ud_G_ymm => { + VEXOperandCode::Ud_G_xyLmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); - let mem_oper = read_E_ymm(words, instruction, modrm, sink)?; + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; if mem_oper != OperandSpec::RegMMM { return Err(DecodeError::InvalidOperand); } @@ -760,7 +680,6 @@ fn read_vex_operands< } VEXOperandCode::Ud_G_xmm_imm8 => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -779,7 +698,6 @@ fn read_vex_operands< } VEXOperandCode::E_G_xmm_imm8 => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -798,7 +716,6 @@ fn read_vex_operands< } VEXOperandCode::E_xmm_G_ymm_imm8 => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -818,7 +735,6 @@ fn read_vex_operands< VEXOperandCode::Gd_U_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -835,7 +751,6 @@ fn read_vex_operands< } VEXOperandCode::Gd_U_ymm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -855,7 +770,6 @@ fn read_vex_operands< op @ VEXOperandCode::G_U_xmm | op @ VEXOperandCode::G_E_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -880,7 +794,7 @@ fn read_vex_operands< if mem_oper != OperandSpec::RegMMM { if [Opcode::VBROADCASTSS, Opcode::VUCOMISS, Opcode::VCOMISS].contains(&instruction.opcode) { instruction.mem_size = 4; - } else if [Opcode::VMOVDDUP, Opcode::VUCOMISD, Opcode::VCOMISD, Opcode::VCVTPS2PD, Opcode::VMOVQ].contains(&instruction.opcode) { + } else if [Opcode::VMOVDDUP, Opcode::VUCOMISD, Opcode::VCOMISD, Opcode::VCVTPS2PD, Opcode::VMOVD].contains(&instruction.opcode) { instruction.mem_size = 8; } else { instruction.mem_size = 16; @@ -891,7 +805,6 @@ fn read_vex_operands< } VEXOperandCode::G_xmm_E_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -908,7 +821,6 @@ fn read_vex_operands< } VEXOperandCode::G_xmm_E_ymm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -926,7 +838,6 @@ fn read_vex_operands< op @ VEXOperandCode::G_ymm_M_xmm | op @ VEXOperandCode::G_ymm_E_xmm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -954,7 +865,6 @@ fn read_vex_operands< } VEXOperandCode::G_ymm_E_ymm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -970,10 +880,8 @@ fn read_vex_operands< Ok(()) } - op @ VEXOperandCode::E_G_ymm | op @ VEXOperandCode::M_G_ymm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -1001,7 +909,6 @@ fn read_vex_operands< op @ VEXOperandCode::G_M_ymm | op @ VEXOperandCode::G_E_ymm => { if instruction.regs[3].num != 0 { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOperand); } let modrm = read_modrm(words)?; @@ -1102,135 +1009,242 @@ fn read_vex_operands< instruction.operand_count = 3; Ok(()) } - VEXOperandCode::G_V_E_xmm => { + VEXOperandCode::E_G_xyLmm => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; - instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = mem_oper; + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; if mem_oper != OperandSpec::RegMMM { - if [Opcode::VSQRTSS, Opcode::VADDSS, Opcode::VMULSS, Opcode::VSUBSS, Opcode::VMINSS, Opcode::VDIVSS, Opcode::VMAXSS].contains(&instruction.opcode) { - instruction.mem_size = 4; - } else if [Opcode::VSQRTSD, Opcode::VADDSD, Opcode::VMULSD, Opcode::VSUBSD, Opcode::VMINSD, Opcode::VDIVSD, Opcode::VMAXSD].contains(&instruction.opcode) { + if instruction.opcode == Opcode::VMOVLPD || instruction.opcode == Opcode::VMOVHPD || instruction.opcode == Opcode::VMOVHPS { instruction.mem_size = 8; } else { - instruction.mem_size = 16; + if L { + instruction.mem_size = 32; + } else { + instruction.mem_size = 16; + } } } - instruction.operand_count = 3; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegRRR; + + instruction.operand_count = 2; Ok(()) } - VEXOperandCode::G_V_xmm_Ed => { + VEXOperandCode::G_V_E_xyLmm_imm8 => { + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(words, 1)?; + instruction.operands[3] = OperandSpec::ImmU8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 4; + if L { + instruction.mem_size = 32; + } else { + instruction.mem_size = 16; + } } - instruction.operand_count = 3; + instruction.operand_count = 4; Ok(()) } - VEXOperandCode::G_V_E_xmm_imm8 => { + VEXOperandCode::G_E_xyLmm => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = mem_oper; - instruction.imm = read_imm_unsigned(words, 1)?; - instruction.operands[3] = OperandSpec::ImmU8; + instruction.operands[1] = mem_oper; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 16; + if L { + instruction.mem_size = 32; + } else { + instruction.mem_size = 16; + } + + if instruction.opcode == Opcode::VMOVDDUP && !L { + instruction.mem_size = 8; + } else if [Opcode::VBROADCASTSS, Opcode::VUCOMISS, Opcode::VCOMISS].contains(&instruction.opcode) { + instruction.mem_size = 4; + } else if [Opcode::VUCOMISD, Opcode::VCOMISD, Opcode::VCVTPS2PD, Opcode::VMOVD].contains(&instruction.opcode) { + instruction.mem_size = 8; + }; } - instruction.operand_count = 4; + instruction.operand_count = 2; Ok(()) } - VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { + VEXOperandCode::G_V_E_xyLmm => { let modrm = read_modrm(words)?; + // the name of this bit is `L` in the documentation, so use the same name here. + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + let bank = if L { RegisterBank::Y } else { RegisterBank::X }; + instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); - instruction.regs[3].bank = RegisterBank::Y; - let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; - instruction.imm = read_imm_unsigned(words, 1)?; - instruction.operands[3] = OperandSpec::ImmU8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 16; + if [Opcode::VSQRTSS, Opcode::VADDSS, Opcode::VMULSS, Opcode::VSUBSS, Opcode::VMINSS, Opcode::VDIVSS, Opcode::VMAXSS].contains(&instruction.opcode) { + instruction.mem_size = 4; + } else if [Opcode::VSQRTSD, Opcode::VADDSD, Opcode::VMULSD, Opcode::VSUBSD, Opcode::VMINSD, Opcode::VDIVSD, Opcode::VMAXSD].contains(&instruction.opcode) { + instruction.mem_size = 8; + } else { + if L { + instruction.mem_size = 32; + } else { + instruction.mem_size = 16; + } + } } - instruction.operand_count = 4; + instruction.operand_count = 3; Ok(()) } - VEXOperandCode::M_V_G_xmm => { + VEXOperandCode::G_V_E_xmm => { let modrm = read_modrm(words)?; - if modrm & 0xc0 == 0xc0 { - return Err(DecodeError::InvalidOperand); - } - instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; - instruction.operands[0] = mem_oper; + instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; - instruction.operands[2] = OperandSpec::RegRRR; + instruction.operands[2] = mem_oper; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 16; + if [Opcode::VSQRTSS, Opcode::VADDSS, Opcode::VMULSS, Opcode::VSUBSS, Opcode::VMINSS, Opcode::VDIVSS, Opcode::VMAXSS].contains(&instruction.opcode) { + instruction.mem_size = 4; + } else if [Opcode::VSQRTSD, Opcode::VADDSD, Opcode::VMULSD, Opcode::VSUBSD, Opcode::VMINSD, Opcode::VDIVSD, Opcode::VMAXSD].contains(&instruction.opcode) { + instruction.mem_size = 8; + } else { + instruction.mem_size = 16; + } } instruction.operand_count = 3; Ok(()) } - - VEXOperandCode::G_Ex_V_xmm => { + VEXOperandCode::G_V_xmm_Ed => { let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; - instruction.regs[2].bank = RegisterBank::X; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operands[2] = OperandSpec::RegVex; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; if mem_oper != OperandSpec::RegMMM { instruction.mem_size = 4; } instruction.operand_count = 3; Ok(()) } - VEXOperandCode::G_Ey_V_xmm => { + VEXOperandCode::G_V_E_xmm_imm8 => { let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); - let mem_oper = read_E_ymm(words, instruction, modrm, sink)?; - instruction.regs[3].bank = RegisterBank::X; - instruction.regs[2].bank = RegisterBank::Y; + let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; instruction.operands[0] = OperandSpec::RegRRR; - instruction.operands[1] = mem_oper; - instruction.operands[2] = OperandSpec::RegVex; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(words, 1)?; + instruction.operands[3] = OperandSpec::ImmU8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = 4; + instruction.mem_size = 16; } - instruction.operand_count = 3; + instruction.operand_count = 4; Ok(()) } - VEXOperandCode::G_Ey_V_ymm => { + VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => { let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); - let mem_oper = read_E_ymm(words, instruction, modrm, sink)?; instruction.regs[3].bank = RegisterBank::Y; - instruction.regs[2].bank = RegisterBank::Y; + let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = mem_oper; + instruction.imm = read_imm_unsigned(words, 1)?; + instruction.operands[3] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } + instruction.operand_count = 4; + Ok(()) + } + VEXOperandCode::M_V_G_xmm => { + let modrm = read_modrm(words)?; + if modrm & 0xc0 == 0xc0 { + return Err(DecodeError::InvalidOperand); + } + + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; + instruction.operands[0] = mem_oper; + instruction.operands[1] = OperandSpec::RegVex; + instruction.operands[2] = OperandSpec::RegRRR; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } + instruction.operand_count = 3; + Ok(()) + } + + VEXOperandCode::G_ExyL_V_xyLmm => { + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + + let bank = if L && instruction.opcode != Opcode::VGATHERQPS && instruction.opcode != Opcode::VPGATHERQD { + RegisterBank::Y + } else { + RegisterBank::X + }; + + let index_bank = if L { + RegisterBank::Y + } else { + RegisterBank::X + }; + + let modrm = read_modrm(words)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; + if instruction.opcode == Opcode::VPGATHERDQ { + instruction.regs[2].bank = RegisterBank::X; + } else { + instruction.regs[2].bank = index_bank; + } + instruction.regs[3].bank = bank; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; instruction.operands[2] = OperandSpec::RegVex; if mem_oper != OperandSpec::RegMMM { - if instruction.opcode == Opcode::VPGATHERDD { + if instruction.opcode == Opcode::VPGATHERDD || instruction.opcode == Opcode::VPGATHERQD || instruction.opcode == Opcode::VGATHERDPS || instruction.opcode == Opcode::VGATHERQPS { instruction.mem_size = 4; } else { instruction.mem_size = 8; @@ -1241,48 +1255,48 @@ fn read_vex_operands< } VEXOperandCode::G_V_E => { let modrm = read_modrm(words)?; - let (opwidth, bank) = (4, RegisterBank::D); + let bank = RegisterBank::D; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, bank); + RegSpec::from_parts((modrm >> 3) & 7,bank); instruction.regs[3].bank = bank; - let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?; + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = bank as u8; } instruction.operand_count = 3; Ok(()) } VEXOperandCode::G_E_V => { let modrm = read_modrm(words)?; - let (opwidth, bank) = (4, RegisterBank::D); + let bank = RegisterBank::D; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, bank); + RegSpec::from_parts((modrm >> 3) & 7,bank); instruction.regs[3].bank = bank; - let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?; + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; instruction.operands[2] = OperandSpec::RegVex; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = bank as u8; } instruction.operand_count = 3; Ok(()) } VEXOperandCode::G_E_Ib => { let modrm = read_modrm(words)?; - let (opwidth, bank) = (4, RegisterBank::D); + let bank = RegisterBank::D; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, bank); - let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?; + RegSpec::from_parts((modrm >> 3) & 7,bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = mem_oper; instruction.imm = read_imm_unsigned(words, 1)?; instruction.operands[2] = OperandSpec::ImmI8; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = bank as u8; } instruction.operand_count = 3; Ok(()) @@ -1300,19 +1314,18 @@ fn read_vex_operands< Opcode::BLSI } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } }; - let (opwidth, bank) = (4, RegisterBank::D); + let bank = RegisterBank::D; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, bank); - let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?; + RegSpec::from_parts((modrm >> 3) & 7,bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; instruction.operands[0] = OperandSpec::RegVex; instruction.operands[1] = mem_oper; instruction.operand_count = 2; if mem_oper != OperandSpec::RegMMM { - instruction.mem_size = opwidth; + instruction.mem_size = bank as u8; } instruction.regs[3].bank = bank; Ok(()) @@ -1327,11 +1340,10 @@ fn read_vex_operands< Opcode::VSTMXCSR } _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } }; - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; if let OperandSpec::RegMMM = mem_oper { return Err(DecodeError::InvalidOperand); } @@ -1342,10 +1354,44 @@ fn read_vex_operands< instruction.operand_count = 1; Ok(()) } + VEXOperandCode::G_E_xyLmm_imm8 => { + if instruction.regs[3].num != 0 { + return Err(DecodeError::InvalidOperand); + } + + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + + let bank = if L { + RegisterBank::Y + } else { + RegisterBank::X + }; + + let modrm = read_modrm(words)?; + instruction.regs[0] = + RegSpec::from_parts((modrm >> 3) & 7, bank); + let mem_oper = read_E(words, instruction, modrm, bank, sink)?; + instruction.operands[0] = OperandSpec::RegRRR; + instruction.operands[1] = mem_oper; + instruction.imm = read_imm_unsigned(words, 1)?; + instruction.operands[2] = OperandSpec::ImmU8; + if mem_oper != OperandSpec::RegMMM { + instruction.mem_size = 16; + } + instruction.operand_count = 3; + Ok(()) + } VEXOperandCode::G_E_xmm_imm8 => { if instruction.regs[3].num != 0 { return Err(DecodeError::InvalidOperand); } + + #[allow(non_snake_case)] + let L = instruction.prefixes.vex_unchecked().l(); + if L { + return Err(DecodeError::InvalidOperand); + } let modrm = read_modrm(words)?; instruction.regs[0] = RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); @@ -1381,7 +1427,7 @@ fn read_vex_operands< VEXOperandCode::G_V_E_ymm_ymm4 => { let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); + RegSpec::from_parts((modrm >> 3) & 7,RegisterBank::Y); instruction.regs[3].bank = RegisterBank::Y; let mem_oper = read_E_ymm(words, instruction, modrm, sink)?; instruction.operands[0] = OperandSpec::RegRRR; @@ -1398,7 +1444,7 @@ fn read_vex_operands< VEXOperandCode::G_V_E_xmm_xmm4 => { let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + RegSpec::from_parts((modrm >> 3) & 7,RegisterBank::X); instruction.regs[3].bank = RegisterBank::X; let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; instruction.operands[0] = OperandSpec::RegRRR; @@ -1415,7 +1461,7 @@ fn read_vex_operands< VEXOperandCode::G_V_ymm_E_xmm => { let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); + RegSpec::from_parts((modrm >> 3) & 7,RegisterBank::Y); instruction.regs[3].bank = RegisterBank::Y; let mem_oper = read_E_xmm(words, instruction, modrm, sink)?; instruction.operands[0] = OperandSpec::RegRRR; @@ -1430,10 +1476,10 @@ fn read_vex_operands< VEXOperandCode::G_V_xmm_Ev_imm8 => { let modrm = read_modrm(words)?; instruction.regs[0] = - RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); + RegSpec::from_parts((modrm >> 3) & 7,RegisterBank::X); instruction.regs[3].bank = RegisterBank::X; // TODO: but the memory access is word-sized - let mem_oper = read_E(words, instruction, modrm, 4, sink)?; + let mem_oper = read_E(words, instruction, modrm, RegisterBank::D, sink)?; instruction.operands[0] = OperandSpec::RegRRR; instruction.operands[1] = OperandSpec::RegVex; instruction.operands[2] = mem_oper; @@ -1463,6 +1509,7 @@ fn read_vex_operands< } } +#[inline(never)] fn read_vex_instruction< T: Reader<::Address, ::Word>, S: DescriptionSink, @@ -1483,52 +1530,32 @@ fn read_vex_instruction< match p { VEXOpcodePrefix::None => { match opc { - 0x10 => (Opcode::VMOVUPS, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x11 => (Opcode::VMOVUPS, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + 0x10 => (Opcode::VMOVUPS, VEXOperandCode::G_E_xyLmm), + 0x11 => (Opcode::VMOVUPS, VEXOperandCode::E_G_xyLmm), 0x12 => (Opcode::Invalid, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::VMOVLPS_12 }), 0x13 => (Opcode::VMOVLPS, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::M_G_xmm }), - 0x14 => (Opcode::VUNPCKLPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x15 => (Opcode::VUNPCKHPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x14 => (Opcode::VUNPCKLPS, VEXOperandCode::G_V_E_xyLmm), + 0x15 => (Opcode::VUNPCKHPS, VEXOperandCode::G_V_E_xyLmm), 0x16 => (Opcode::Invalid, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::VMOVHPS_16 }), 0x17 => (Opcode::VMOVHPS, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::M_G_xmm }), - 0x28 => (Opcode::VMOVAPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x29 => (Opcode::VMOVAPS, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), + 0x28 => (Opcode::VMOVAPS, VEXOperandCode::G_E_xyLmm), + 0x29 => (Opcode::VMOVAPS, VEXOperandCode::E_G_xyLmm), 0x2B => (Opcode::VMOVNTPS, if L { VEXOperandCode::M_G_ymm } else { @@ -1536,86 +1563,26 @@ fn read_vex_instruction< }), 0x2e => (Opcode::VUCOMISS, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISS, VEXOperandCode::G_E_xmm), - 0x50 => (Opcode::VMOVMSKPS, if L { - VEXOperandCode::Ud_G_ymm - } else { - VEXOperandCode::Ud_G_xmm - }), - 0x51 => (Opcode::VSQRTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x52 => (Opcode::VRSQRTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x53 => (Opcode::VRCPPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x54 => (Opcode::VANDPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x55 => (Opcode::VANDNPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x56 => (Opcode::VORPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x57 => (Opcode::VXORPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x58 => (Opcode::VADDPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x59 => (Opcode::VMULPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x50 => (Opcode::VMOVMSKPS, VEXOperandCode::Ud_G_xyLmm), + 0x51 => (Opcode::VSQRTPS, VEXOperandCode::G_E_xyLmm), + 0x52 => (Opcode::VRSQRTPS, VEXOperandCode::G_E_xyLmm), + 0x53 => (Opcode::VRCPPS, VEXOperandCode::G_E_xyLmm), + 0x54 => (Opcode::VANDPS, VEXOperandCode::G_V_E_xyLmm), + 0x55 => (Opcode::VANDNPS, VEXOperandCode::G_V_E_xyLmm), + 0x56 => (Opcode::VORPS, VEXOperandCode::G_V_E_xyLmm), + 0x57 => (Opcode::VXORPS, VEXOperandCode::G_V_E_xyLmm), + 0x58 => (Opcode::VADDPS, VEXOperandCode::G_V_E_xyLmm), + 0x59 => (Opcode::VMULPS, VEXOperandCode::G_V_E_xyLmm), 0x5A => (Opcode::VCVTPS2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_E_xmm }), - 0x5B => (Opcode::VCVTDQ2PS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x5C => (Opcode::VSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5D => (Opcode::VMINPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5E => (Opcode::VDIVPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x5F => (Opcode::VMAXPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x5B => (Opcode::VCVTDQ2PS, VEXOperandCode::G_E_xyLmm), + 0x5C => (Opcode::VSUBPS, VEXOperandCode::G_V_E_xyLmm), + 0x5D => (Opcode::VMINPS, VEXOperandCode::G_V_E_xyLmm), + 0x5E => (Opcode::VDIVPS, VEXOperandCode::G_V_E_xyLmm), + 0x5F => (Opcode::VMAXPS, VEXOperandCode::G_V_E_xyLmm), 0x77 => if L { (Opcode::VZEROALL, VEXOperandCode::Nothing) } else { @@ -1626,18 +1593,9 @@ fn read_vex_instruction< } else { VEXOperandCode::MXCSR }), - 0xC2 => (Opcode::VCMPPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0xC6 => (Opcode::VSHUFPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), + 0xC2 => (Opcode::VCMPPS, VEXOperandCode::G_V_E_xyLmm_imm8), + 0xC6 => (Opcode::VSHUFPS, VEXOperandCode::G_V_E_xyLmm_imm8), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -1646,64 +1604,33 @@ fn read_vex_instruction< match opc { // 0x0a => (Opcode::VROUNDSS, VEXOperandCode::G_V_E_xmm_imm8), // 0x0b => (Opcode::VROUNDSD, VEXOperandCode::G_V_E_xmm_imm8), - 0x10 => (Opcode::VMOVUPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x11 => (Opcode::VMOVUPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), + 0x10 => (Opcode::VMOVUPD, VEXOperandCode::G_E_xyLmm), + 0x11 => (Opcode::VMOVUPD, VEXOperandCode::G_E_xyLmm), 0x12 => (Opcode::VMOVLPD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_M_xmm }), 0x13 => (Opcode::VMOVLPD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::M_G_xmm }), - 0x14 => (Opcode::VUNPCKLPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x15 => (Opcode::VUNPCKHPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x14 => (Opcode::VUNPCKLPD, VEXOperandCode::G_V_E_xyLmm), + 0x15 => (Opcode::VUNPCKHPD, VEXOperandCode::G_V_E_xyLmm), 0x16 => (Opcode::VMOVHPD, if L { return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_M_xmm }), 0x17 => (Opcode::VMOVHPD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::M_G_xmm }), - 0x28 => (Opcode::VMOVAPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x29 => (Opcode::VMOVAPD, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), - 0x2B => (Opcode::VMOVNTPD, if L { - VEXOperandCode::M_G_ymm - } else { - VEXOperandCode::M_G_xmm - }), + 0x28 => (Opcode::VMOVAPD, VEXOperandCode::G_E_xyLmm), + 0x29 => (Opcode::VMOVAPD, VEXOperandCode::E_G_xyLmm), + 0x2B => (Opcode::VMOVNTPD, VEXOperandCode::M_G_xyLmm), 0x2e => (Opcode::VUCOMISD, VEXOperandCode::G_E_xmm), 0x2f => (Opcode::VCOMISD, VEXOperandCode::G_E_xmm), 0x50 => (Opcode::VMOVMSKPD, if L { @@ -1711,482 +1638,165 @@ fn read_vex_instruction< } else { VEXOperandCode::Gd_U_xmm }), - 0x51 => (Opcode::VSQRTPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x54 => (Opcode::VANDPD, if L { - VEXOperandCode::G_V_E_ymm + 0x51 => (Opcode::VSQRTPD, VEXOperandCode::G_E_xyLmm), + 0x54 => (Opcode::VANDPD, VEXOperandCode::G_V_E_xyLmm), + 0x55 => (Opcode::VANDNPD, VEXOperandCode::G_V_E_xyLmm), + 0x56 => (Opcode::VORPD, VEXOperandCode::G_V_E_xyLmm), + 0x57 => (Opcode::VXORPD, VEXOperandCode::G_V_E_xyLmm), + 0x58 => (Opcode::VADDPD, VEXOperandCode::G_V_E_xyLmm), + 0x59 => (Opcode::VMULPD, VEXOperandCode::G_V_E_xyLmm), + 0x5A => (Opcode::VCVTPD2PS, if L { + VEXOperandCode::G_xmm_E_ymm } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_xmm_E_xmm }), - 0x55 => (Opcode::VANDNPD, if L { - VEXOperandCode::G_V_E_ymm + 0x5B => (Opcode::VCVTPS2DQ, VEXOperandCode::G_E_xyLmm), + 0x5C => (Opcode::VSUBPD, VEXOperandCode::G_V_E_xyLmm), + 0x5D => (Opcode::VMINPD, VEXOperandCode::G_V_E_xyLmm), + 0x5E => (Opcode::VDIVPD, VEXOperandCode::G_V_E_xyLmm), + 0x5F => (Opcode::VMAXPD, VEXOperandCode::G_V_E_xyLmm), + 0x60 => (Opcode::VPUNPCKLBW, VEXOperandCode::G_V_E_xyLmm), + 0x61 => (Opcode::VPUNPCKLWD, VEXOperandCode::G_V_E_xyLmm), + 0x62 => (Opcode::VPUNPCKLDQ, VEXOperandCode::G_V_E_xyLmm), + 0x63 => (Opcode::VPACKSSWB, VEXOperandCode::G_V_E_xyLmm), + 0x64 => (Opcode::VPCMPGTB, VEXOperandCode::G_V_E_xyLmm), + 0x65 => (Opcode::VPCMPGTW, VEXOperandCode::G_V_E_xyLmm), + 0x66 => (Opcode::VPCMPGTD, VEXOperandCode::G_V_E_xyLmm), + 0x67 => (Opcode::VPACKUSWB, VEXOperandCode::G_V_E_xyLmm), + 0x68 => (Opcode::VPUNPCKHBW, VEXOperandCode::G_V_E_xyLmm), + 0x69 => (Opcode::VPUNPCKHWD, VEXOperandCode::G_V_E_xyLmm), + 0x6A => (Opcode::VPUNPCKHDQ, VEXOperandCode::G_V_E_xyLmm), + 0x6B => (Opcode::VPACKSSDW, VEXOperandCode::G_V_E_xyLmm), + 0x6C => (Opcode::VPUNPCKLQDQ, VEXOperandCode::G_V_E_xyLmm), + 0x6D => (Opcode::VPUNPCKHQDQ, VEXOperandCode::G_V_E_xyLmm), + 0x6E => { + (Opcode::VMOVD, if L { + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::G_xmm_Ed + }) + }, + 0x6F => (Opcode::VMOVDQA, VEXOperandCode::G_E_xyLmm), + 0x70 => (Opcode::VPSHUFD, VEXOperandCode::G_E_xyLmm_imm8), + 0x71 => (Opcode::Invalid, VEXOperandCode::VPS_71), + 0x72 => (Opcode::Invalid, VEXOperandCode::VPS_72), + 0x73 => (Opcode::Invalid, VEXOperandCode::VPS_73), + 0x74 => (Opcode::VPCMPEQB, VEXOperandCode::G_V_E_xyLmm), + 0x75 => (Opcode::VPCMPEQW, VEXOperandCode::G_V_E_xyLmm), + 0x76 => (Opcode::VPCMPEQD, VEXOperandCode::G_V_E_xyLmm), + 0x7C => (Opcode::VHADDPD, VEXOperandCode::G_V_E_xyLmm), + 0x7D => (Opcode::VHSUBPD, VEXOperandCode::G_V_E_xyLmm), + 0x7E => { + (Opcode::VMOVD, if L { + return Err(DecodeError::InvalidOpcode); + } else { + VEXOperandCode::Ed_G_xmm + }) + } + 0x7F => (Opcode::VMOVDQA, VEXOperandCode::E_G_xyLmm), + 0xC2 => (Opcode::VCMPPD, VEXOperandCode::G_V_E_xyLmm_imm8), + 0xC4 => (Opcode::VPINSRW, if L { + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_V_xmm_Ev_imm8 }), - 0x56 => (Opcode::VORPD, if L { - VEXOperandCode::G_V_E_ymm + 0xC5 => (Opcode::VPEXTRW, if L { + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::Ud_G_xmm_imm8 }), - 0x57 => (Opcode::VXORPD, if L { - VEXOperandCode::G_V_E_ymm + 0xC6 => (Opcode::VSHUFPD, VEXOperandCode::G_V_E_xyLmm_imm8), + 0xD0 => (Opcode::VADDSUBPD, VEXOperandCode::G_V_E_xyLmm), + 0xD1 => (Opcode::VPSRLW, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x58 => (Opcode::VADDPD, if L { - VEXOperandCode::G_V_E_ymm + 0xD2 => (Opcode::VPSRLD, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x59 => (Opcode::VMULPD, if L { - VEXOperandCode::G_V_E_ymm + 0xD3 => (Opcode::VPSRLQ, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x5A => (Opcode::VCVTPD2PS, if L { - VEXOperandCode::G_xmm_E_ymm - } else { - VEXOperandCode::G_xmm_E_xmm - }), - 0x5B => (Opcode::VCVTPS2DQ, if L { - VEXOperandCode::G_E_ymm + 0xD4 => (Opcode::VPADDQ, VEXOperandCode::G_V_E_xyLmm), + 0xD5 => (Opcode::VPMULLW, VEXOperandCode::G_V_E_xyLmm), + 0xD6 => (Opcode::VMOVD, if L { + return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), - 0x5C => (Opcode::VSUBPD, if L { - VEXOperandCode::G_V_E_ymm + 0xD7 => (Opcode::VPMOVMSKB, VEXOperandCode::Ud_G_xyLmm), + 0xD8 => (Opcode::VPSUBUSB, VEXOperandCode::G_V_E_xyLmm), + 0xD9 => (Opcode::VPSUBUSW, VEXOperandCode::G_V_E_xyLmm), + 0xDA => (Opcode::VPMINUB, VEXOperandCode::G_V_E_xyLmm), + 0xDB => (Opcode::VPAND, VEXOperandCode::G_V_E_xyLmm), + 0xDC => (Opcode::VPADDUSB, VEXOperandCode::G_V_E_xyLmm), + 0xDD => (Opcode::VPADDUSW, VEXOperandCode::G_V_E_xyLmm), + 0xDE => (Opcode::VPMAXUB, VEXOperandCode::G_V_E_xyLmm), + 0xDF => (Opcode::VPANDN, VEXOperandCode::G_V_E_xyLmm), + 0xE0 => (Opcode::VPAVGB, VEXOperandCode::G_V_E_xyLmm), + 0xE1 => (Opcode::VPSRAW, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x5D => (Opcode::VMINPD, if L { - VEXOperandCode::G_V_E_ymm + 0xE2 => (Opcode::VPSRAD, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x5E => (Opcode::VDIVPD, if L { - VEXOperandCode::G_V_E_ymm + 0xE3 => (Opcode::VPAVGW, VEXOperandCode::G_V_E_xyLmm), + 0xE4 => (Opcode::VPMULHUW, VEXOperandCode::G_V_E_xyLmm), + 0xE5 => (Opcode::VPMULHW, VEXOperandCode::G_V_E_xyLmm), + 0xE6 => (Opcode::VCVTTPD2DQ, if L { + VEXOperandCode::G_xmm_E_ymm } else { - VEXOperandCode::G_V_E_xmm + VEXOperandCode::G_E_xmm }), - 0x5F => (Opcode::VMAXPD, if L { - VEXOperandCode::G_V_E_ymm + 0xE7 => (Opcode::VMOVNTDQ, VEXOperandCode::M_G_xyLmm), + 0xE8 => (Opcode::VPSUBSB, VEXOperandCode::G_V_E_xyLmm), + 0xE9 => (Opcode::VPSUBSW, VEXOperandCode::G_V_E_xyLmm), + 0xEA => (Opcode::VPMINSW, VEXOperandCode::G_V_E_xyLmm), + 0xEB => (Opcode::VPOR, VEXOperandCode::G_V_E_xyLmm), + 0xEC => (Opcode::VPADDSB, VEXOperandCode::G_V_E_xyLmm), + 0xED => (Opcode::VPADDSW, VEXOperandCode::G_V_E_xyLmm), + 0xEE => (Opcode::VPMAXSW, VEXOperandCode::G_V_E_xyLmm), + 0xEF => (Opcode::VPXOR, VEXOperandCode::G_V_E_xyLmm), + 0xF1 => (Opcode::VPSLLW, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x60 => (Opcode::VPUNPCKLBW, if L { - VEXOperandCode::G_V_E_ymm + 0xF2 => (Opcode::VPSLLD, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x61 => (Opcode::VPUNPCKLWD, if L { - VEXOperandCode::G_V_E_ymm + 0xF3 => (Opcode::VPSLLQ, if L { + VEXOperandCode::G_V_ymm_E_xmm } else { VEXOperandCode::G_V_E_xmm }), - 0x62 => (Opcode::VPUNPCKLDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x63 => (Opcode::VPACKSSWB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x64 => (Opcode::VPCMPGTB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x65 => (Opcode::VPCMPGTW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x66 => (Opcode::VPCMPGTD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x67 => (Opcode::VPACKUSWB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x68 => (Opcode::VPUNPCKHBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x69 => (Opcode::VPUNPCKHWD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6A => (Opcode::VPUNPCKHDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6B => (Opcode::VPACKSSDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6C => (Opcode::VPUNPCKLQDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6D => (Opcode::VPUNPCKHQDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x6E => if instruction.prefixes.vex_unchecked().w() { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_xmm_Ed - }) - } else { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_xmm_Ed - }) - }, - 0x6F => (Opcode::VMOVDQA, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x70 => (Opcode::VPSHUFD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x71 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_71_L - } else { - VEXOperandCode::VPS_71 - }), - 0x72 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_72_L - } else { - VEXOperandCode::VPS_72 - }), - 0x73 => (Opcode::Invalid, if L { - VEXOperandCode::VPS_73_L - } else { - VEXOperandCode::VPS_73 - }), - 0x74 => (Opcode::VPCMPEQB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x75 => (Opcode::VPCMPEQW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x76 => (Opcode::VPCMPEQD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7C => (Opcode::VHADDPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7D => (Opcode::VHSUBPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7E => if instruction.prefixes.vex_unchecked().w() { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ed_G_xmm - }) - } else { - (Opcode::VMOVD, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ed_G_xmm - }) - } - 0x7F => (Opcode::VMOVDQA, if L { - VEXOperandCode::E_G_ymm - } else { - VEXOperandCode::E_G_xmm - }), - 0xC2 => (Opcode::VCMPPD, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0xC4 => (Opcode::VPINSRW, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_V_xmm_Ev_imm8 - }), - 0xC5 => (Opcode::VPEXTRW, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::Ud_G_xmm_imm8 - }), - 0xC6 => (Opcode::VSHUFPD, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0xD0 => (Opcode::VADDSUBPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD1 => (Opcode::VPSRLW, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD2 => (Opcode::VPSRLD, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD3 => (Opcode::VPSRLQ, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD4 => (Opcode::VPADDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD5 => (Opcode::VPMULLW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD6 => (Opcode::VMOVQ, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm - }), - 0xD7 => (Opcode::VPMOVMSKB, if L { - VEXOperandCode::Ud_G_ymm - } else { - VEXOperandCode::Ud_G_xmm - }), - 0xD8 => (Opcode::VPSUBUSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xD9 => (Opcode::VPSUBUSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDA => (Opcode::VPMINUB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDB => (Opcode::VPAND, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDC => (Opcode::VPADDUSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - 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 { - VEXOperandCode::G_V_E_xmm - }), - 0xE0 => (Opcode::VPAVGB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE1 => (Opcode::VPSRAW, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE2 => (Opcode::VPSRAD, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE3 => (Opcode::VPAVGW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE4 => (Opcode::VPMULHUW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE5 => (Opcode::VPMULHW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE6 => (Opcode::VCVTTPD2DQ, if L { - VEXOperandCode::G_xmm_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0xE7 => (Opcode::VMOVNTDQ, if L { - VEXOperandCode::M_G_ymm - } else { - VEXOperandCode::M_G_xmm - }), - 0xE8 => (Opcode::VPSUBSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xE9 => (Opcode::VPSUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 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 { - VEXOperandCode::G_V_E_xmm - }), - 0xEC => (Opcode::VPADDSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xED => (Opcode::VPADDSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEE => (Opcode::VPMAXSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xEF => (Opcode::VPXOR, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF1 => (Opcode::VPSLLW, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF2 => (Opcode::VPSLLD, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF3 => (Opcode::VPSLLQ, if L { - VEXOperandCode::G_V_ymm_E_xmm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF4 => (Opcode::VPMULUDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF5 => (Opcode::VPMADDWD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF6 => (Opcode::VPSADBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF7 => (Opcode::VMASKMOVDQU, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); + 0xF4 => (Opcode::VPMULUDQ, VEXOperandCode::G_V_E_xyLmm), + 0xF5 => (Opcode::VPMADDWD, VEXOperandCode::G_V_E_xyLmm), + 0xF6 => (Opcode::VPSADBW, VEXOperandCode::G_V_E_xyLmm), + 0xF7 => (Opcode::VMASKMOVDQU, if L { + return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_U_xmm }), - 0xF8 => (Opcode::VPSUBB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xF9 => (Opcode::VPSUBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFA => (Opcode::VPSUBD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFB => (Opcode::VPSUBQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFC => (Opcode::VPADDB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFD => (Opcode::VPADDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xFE => (Opcode::VPADDD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0xF8 => (Opcode::VPSUBB, VEXOperandCode::G_V_E_xyLmm), + 0xF9 => (Opcode::VPSUBW, VEXOperandCode::G_V_E_xyLmm), + 0xFA => (Opcode::VPSUBD, VEXOperandCode::G_V_E_xyLmm), + 0xFB => (Opcode::VPSUBQ, VEXOperandCode::G_V_E_xyLmm), + 0xFC => (Opcode::VPADDB, VEXOperandCode::G_V_E_xyLmm), + 0xFD => (Opcode::VPADDW, VEXOperandCode::G_V_E_xyLmm), + 0xFE => (Opcode::VPADDD, VEXOperandCode::G_V_E_xyLmm), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -2195,25 +1805,15 @@ fn read_vex_instruction< match opc { 0x10 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_10), 0x11 => (Opcode::VMOVSD, VEXOperandCode::VMOVSD_11), - 0x12 => (Opcode::VMOVDDUP, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x2a => (Opcode::VCVTSI2SD, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::G_V_xmm_Ed // 32-bit last operand - } else { + 0x12 => (Opcode::VMOVDDUP, VEXOperandCode::G_E_xyLmm), + 0x2a => (Opcode::VCVTSI2SD, { VEXOperandCode::G_V_xmm_Ed // 32-bit last operand }), - 0x2c => (Opcode::VCVTTSD2SI, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::VCVT_Gd_Eq_xmm - } else { - VEXOperandCode::VCVT_Gd_Eq_xmm + 0x2c => (Opcode::VCVTTSD2SI, { + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), - 0x2d => (Opcode::VCVTSD2SI, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::VCVT_Gd_Eq_xmm - } else { - VEXOperandCode::VCVT_Gd_Eq_xmm + 0x2d => (Opcode::VCVTSD2SI, { + VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit }), 0x51 => (Opcode::VSQRTSD, VEXOperandCode::G_V_E_xmm), 0x58 => (Opcode::VADDSD, VEXOperandCode::G_V_E_xmm), @@ -2223,27 +1823,11 @@ fn read_vex_instruction< 0x5d => (Opcode::VMINSD, VEXOperandCode::G_V_E_xmm), 0x5e => (Opcode::VDIVSD, VEXOperandCode::G_V_E_xmm), 0x5f => (Opcode::VMAXSD, VEXOperandCode::G_V_E_xmm), - 0x70 => (Opcode::VPSHUFLW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x7c => (Opcode::VHADDPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x7d => (Opcode::VHSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x70 => (Opcode::VPSHUFLW, VEXOperandCode::G_E_xyLmm_imm8), + 0x7c => (Opcode::VHADDPS, VEXOperandCode::G_V_E_xyLmm), + 0x7d => (Opcode::VHSUBPS, VEXOperandCode::G_V_E_xyLmm), 0xc2 => (Opcode::VCMPSD, VEXOperandCode::G_V_E_xmm_imm8), - 0xd0 => (Opcode::VADDSUBPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0xd0 => (Opcode::VADDSUBPS, VEXOperandCode::G_V_E_xyLmm), 0xe6 => (Opcode::VCVTPD2DQ, if L { VEXOperandCode::G_xmm_E_ymm } else { @@ -2255,7 +1839,6 @@ fn read_vex_instruction< VEXOperandCode::G_M_xmm }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -2266,20 +1849,14 @@ fn read_vex_instruction< 0x11 => (Opcode::VMOVSS, VEXOperandCode::VMOVSS_11), 0x12 => (Opcode::VMOVSLDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), 0x16 => (Opcode::VMOVSHDUP, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x2a => (Opcode::VCVTSI2SS, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::G_V_xmm_Ed - } else { + 0x2a => (Opcode::VCVTSI2SS, { VEXOperandCode::G_V_xmm_Ed }), - 0x2c => (Opcode::VCVTTSS2SI, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit - } else { - VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit + 0x2c => (Opcode::VCVTTSS2SI, { + VEXOperandCode::VCVT_Gd_Ed_xmm }), - 0x2d => (Opcode::VCVTSS2SI, if instruction.prefixes.vex_unchecked().w() { - VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit - } else { - VEXOperandCode::VCVT_Gd_Ed_xmm // 32-bit + 0x2d => (Opcode::VCVTSS2SI, { + VEXOperandCode::VCVT_Gd_Ed_xmm }), 0x51 => (Opcode::VSQRTSS, VEXOperandCode::G_V_E_xmm), 0x52 => (Opcode::VRSQRTSS, VEXOperandCode::G_V_E_xmm), @@ -2293,17 +1870,12 @@ fn read_vex_instruction< 0x5e => (Opcode::VDIVSS, VEXOperandCode::G_V_E_xmm), 0x5f => (Opcode::VMAXSS, VEXOperandCode::G_V_E_xmm), 0x6f => (Opcode::VMOVDQU, if L { VEXOperandCode::G_E_ymm } else { VEXOperandCode::G_E_xmm }), - 0x70 => (Opcode::VPSHUFHW, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x7e => (Opcode::VMOVQ, if L { instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), - 0x7f => (Opcode::VMOVDQU, if L { VEXOperandCode::E_G_ymm } else { VEXOperandCode::E_G_xmm }), + 0x70 => (Opcode::VPSHUFHW, VEXOperandCode::G_E_xyLmm_imm8), + 0x7e => (Opcode::VMOVD, if L { return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), + 0x7f => (Opcode::VMOVDQU, VEXOperandCode::E_G_xyLmm), 0xc2 => (Opcode::VCMPSS, VEXOperandCode::G_V_E_xmm_imm8), 0xe6 => (Opcode::VCVTDQ2PD, if L { VEXOperandCode::G_ymm_E_xmm } else { VEXOperandCode::G_xmm_E_xmm }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -2315,107 +1887,33 @@ fn read_vex_instruction< if let VEXOpcodePrefix::Prefix66 = p { // possibly valid! match opc { - 0x00 => (Opcode::VPSHUFB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x01 => (Opcode::VPHADDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x02 => (Opcode::VPHADDD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x03 => (Opcode::VPHADDSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x04 => (Opcode::VPMADDUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x05 => (Opcode::VPHSUBW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x06 => (Opcode::VPHSUBD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x07 => (Opcode::VPHSUBSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x08 => (Opcode::VPSIGNB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x09 => (Opcode::VPSIGNW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0A => (Opcode::VPSIGND, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0B => (Opcode::VPMULHRSW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0C => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0D => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x0E => (Opcode::VTESTPS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x0F => (Opcode::VTESTPD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x13 => (Opcode::VCVTPH2PS, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), + 0x00 => (Opcode::VPSHUFB, VEXOperandCode::G_V_E_xyLmm), + 0x01 => (Opcode::VPHADDW, VEXOperandCode::G_V_E_xyLmm), + 0x02 => (Opcode::VPHADDD, VEXOperandCode::G_V_E_xyLmm), + 0x03 => (Opcode::VPHADDSW, VEXOperandCode::G_V_E_xyLmm), + 0x04 => (Opcode::VPMADDUBSW, VEXOperandCode::G_V_E_xyLmm), + 0x05 => (Opcode::VPHSUBW, VEXOperandCode::G_V_E_xyLmm), + 0x06 => (Opcode::VPHSUBD, VEXOperandCode::G_V_E_xyLmm), + 0x07 => (Opcode::VPHSUBSW, VEXOperandCode::G_V_E_xyLmm), + 0x08 => (Opcode::VPSIGNB, VEXOperandCode::G_V_E_xyLmm), + 0x09 => (Opcode::VPSIGNW, VEXOperandCode::G_V_E_xyLmm), + 0x0A => (Opcode::VPSIGND, VEXOperandCode::G_V_E_xyLmm), + 0x0B => (Opcode::VPMULHRSW, VEXOperandCode::G_V_E_xyLmm), + 0x0C => (Opcode::VPERMILPS, VEXOperandCode::G_V_E_xyLmm), + 0x0D => (Opcode::VPERMILPD, VEXOperandCode::G_V_E_xyLmm), + 0x0E => (Opcode::VTESTPS, VEXOperandCode::G_E_xyLmm), + 0x0F => (Opcode::VTESTPD, VEXOperandCode::G_E_xyLmm), + 0x13 => (Opcode::VCVTPH2PS, VEXOperandCode::G_E_xyLmm), 0x16 => (Opcode::VPERMPS, if L { if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } VEXOperandCode::G_V_E_ymm } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x17 => (Opcode::VPTEST, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), + 0x17 => (Opcode::VPTEST, VEXOperandCode::G_E_xyLmm), 0x18 => if instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { (Opcode::VBROADCASTSS, if L { @@ -2425,7 +1923,6 @@ fn read_vex_instruction< }) }, 0x19 => if instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { (Opcode::VBROADCASTSD, if L { @@ -2437,24 +1934,11 @@ fn read_vex_instruction< 0x1A => (Opcode::VBROADCASTF128, if L { VEXOperandCode::G_ymm_M_xmm } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x1C => (Opcode::VPABSB, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x1D => (Opcode::VPABSW, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x1E => (Opcode::VPABSD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), + 0x1C => (Opcode::VPABSB, VEXOperandCode::G_E_xyLmm), + 0x1D => (Opcode::VPABSW, VEXOperandCode::G_E_xyLmm), + 0x1E => (Opcode::VPABSD, VEXOperandCode::G_E_xyLmm), 0x20 => (Opcode::VPMOVSXBW, if L { VEXOperandCode::G_ymm_E_xmm } else { @@ -2485,26 +1969,14 @@ fn read_vex_instruction< } else { VEXOperandCode::G_E_xmm }), - 0x28 => (Opcode::VPMULDQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x29 => (Opcode::VPCMPEQQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x28 => (Opcode::VPMULDQ, VEXOperandCode::G_V_E_xyLmm), + 0x29 => (Opcode::VPCMPEQQ, VEXOperandCode::G_V_E_xyLmm), 0x2A => (Opcode::VMOVNTDQA, if L { VEXOperandCode::G_M_ymm } else { VEXOperandCode::G_M_xmm }), - 0x2B => (Opcode::VPACKUSDW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x2B => (Opcode::VPACKUSDW, VEXOperandCode::G_V_E_xyLmm), 0x2C => (Opcode::VMASKMOVPS, if L { VEXOperandCode::G_V_M_ymm } else { @@ -2558,77 +2030,27 @@ fn read_vex_instruction< 0x36 => (Opcode::VPERMD, if L { VEXOperandCode::G_V_E_ymm } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x37 => (Opcode::VPCMPGTQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x38 => (Opcode::VPMINSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x39 => (Opcode::VPMINSD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3A => (Opcode::VPMINUW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3B => (Opcode::VPMINUD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3C => (Opcode::VPMAXSB, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3D => (Opcode::VPMAXSD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3E => (Opcode::VPMAXUW, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x3F => (Opcode::VPMAXUD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0x40 => (Opcode::VPMULLD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0x37 => (Opcode::VPCMPGTQ, VEXOperandCode::G_V_E_xyLmm), + 0x38 => (Opcode::VPMINSB, VEXOperandCode::G_V_E_xyLmm), + 0x39 => (Opcode::VPMINSD, VEXOperandCode::G_V_E_xyLmm), + 0x3A => (Opcode::VPMINUW, VEXOperandCode::G_V_E_xyLmm), + 0x3B => (Opcode::VPMINUD, VEXOperandCode::G_V_E_xyLmm), + 0x3C => (Opcode::VPMAXSB, VEXOperandCode::G_V_E_xyLmm), + 0x3D => (Opcode::VPMAXSD, VEXOperandCode::G_V_E_xyLmm), + 0x3E => (Opcode::VPMAXUW, VEXOperandCode::G_V_E_xyLmm), + 0x3F => (Opcode::VPMAXUD, VEXOperandCode::G_V_E_xyLmm), + 0x40 => (Opcode::VPMULLD, VEXOperandCode::G_V_E_xyLmm), 0x41 => (Opcode::VPHMINPOSUW, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), 0x45 => if instruction.prefixes.vex_unchecked().w() { - (Opcode::VPSRLVQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) + (Opcode::VPSRLVQ, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VPSRLVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) + (Opcode::VPSRLVD, VEXOperandCode::G_V_E_xyLmm) }, 0x46 => (Opcode::VPSRAVD, if L { if instruction.prefixes.vex_unchecked().w() { @@ -2642,35 +2064,18 @@ fn read_vex_instruction< VEXOperandCode::G_V_E_xmm }), 0x47 => if instruction.prefixes.vex_unchecked().w() { - (Opcode::VPSLLVQ, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) + (Opcode::VPSLLVQ, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VPSLLVD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }) + (Opcode::VPSLLVD, VEXOperandCode::G_V_E_xyLmm) }, - 0x58 => (Opcode::VPBROADCASTD, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), - 0x59 => (Opcode::VPBROADCASTQ, if L { - VEXOperandCode::G_E_ymm - } else { - VEXOperandCode::G_E_xmm - }), + 0x58 => (Opcode::VPBROADCASTD, VEXOperandCode::G_E_xyLmm), + 0x59 => (Opcode::VPBROADCASTQ, VEXOperandCode::G_E_xyLmm), 0x5A => (Opcode::VBROADCASTI128, if L { if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } VEXOperandCode::G_ymm_M_xmm } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x78 => (Opcode::VPBROADCASTB, if L { @@ -2715,107 +2120,51 @@ fn read_vex_instruction< }, 0x90 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VPGATHERDQ, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VPGATHERDQ, VEXOperandCode::G_ExyL_V_xyLmm) } else { - (Opcode::VPGATHERDD, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VPGATHERDD, VEXOperandCode::G_ExyL_V_xyLmm) } }, 0x91 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VPGATHERQQ, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VPGATHERQQ, VEXOperandCode::G_ExyL_V_xyLmm) } else { - (Opcode::VPGATHERQD, if L { - VEXOperandCode::G_Ey_V_xmm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VPGATHERQD, VEXOperandCode::G_ExyL_V_xyLmm) } }, 0x92 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VGATHERDPD, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VGATHERDPD, VEXOperandCode::G_ExyL_V_xyLmm) } else { - (Opcode::VGATHERDPS, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VGATHERDPS, VEXOperandCode::G_ExyL_V_xyLmm) } }, 0x93 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VGATHERQPD, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VGATHERQPD, VEXOperandCode::G_ExyL_V_xyLmm) } else { - (Opcode::VGATHERQPS, if L { - VEXOperandCode::G_Ey_V_ymm - } else { - VEXOperandCode::G_Ex_V_xmm - }) + (Opcode::VGATHERQPS, VEXOperandCode::G_ExyL_V_xyLmm) } }, 0x96 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADDSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADDSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x97 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUBADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUBADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x98 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x99 => if instruction.prefixes.vex_unchecked().w() { @@ -2825,17 +2174,9 @@ fn read_vex_instruction< }, 0x9A => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x9B => if instruction.prefixes.vex_unchecked().w() { @@ -2845,17 +2186,9 @@ fn read_vex_instruction< }, 0x9C => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMADD132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMADD132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x9D => if instruction.prefixes.vex_unchecked().w() { @@ -2865,17 +2198,9 @@ fn read_vex_instruction< }, 0x9E => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMSUB132PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB132PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMSUB132PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB132PS, VEXOperandCode::G_V_E_xyLmm) } }, 0x9F => if instruction.prefixes.vex_unchecked().w() { @@ -2885,47 +2210,23 @@ fn read_vex_instruction< }, 0xA6 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADDSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADDSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xA7 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUBADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUBADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xA8 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xA9 => if instruction.prefixes.vex_unchecked().w() { @@ -2935,17 +2236,9 @@ fn read_vex_instruction< }, 0xAA => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xAB => if instruction.prefixes.vex_unchecked().w() { @@ -2955,17 +2248,9 @@ fn read_vex_instruction< }, 0xAC => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMADD213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMADD213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xAD => if instruction.prefixes.vex_unchecked().w() { @@ -2975,17 +2260,9 @@ fn read_vex_instruction< }, 0xAE => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMSUB213PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB213PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMSUB213PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB213PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xAF => if instruction.prefixes.vex_unchecked().w() { @@ -2995,47 +2272,23 @@ fn read_vex_instruction< }, 0xB6 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADDSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADDSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADDSUB231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xB7 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUBADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUBADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUBADD231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xB8 => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMADD231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xB9 => if instruction.prefixes.vex_unchecked().w() { @@ -3045,17 +2298,9 @@ fn read_vex_instruction< }, 0xBA => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFMSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFMSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFMSUB231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xBB => if instruction.prefixes.vex_unchecked().w() { @@ -3065,17 +2310,9 @@ fn read_vex_instruction< }, 0xBC => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMADD231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMADD231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMADD231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xBD => if instruction.prefixes.vex_unchecked().w() { @@ -3085,17 +2322,9 @@ fn read_vex_instruction< }, 0xBE => { if instruction.prefixes.vex_unchecked().w() { - (Opcode::VFNMSUB231PD, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB231PD, VEXOperandCode::G_V_E_xyLmm) } else { - (Opcode::VFNMSUB231PS, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_ymm - }) + (Opcode::VFNMSUB231PS, VEXOperandCode::G_V_E_xyLmm) } }, 0xBF => if instruction.prefixes.vex_unchecked().w() { @@ -3104,114 +2333,83 @@ fn read_vex_instruction< (Opcode::VFNMSUB231SS, VEXOperandCode::G_V_E_xmm /* 64bit */) }, 0xDB => (Opcode::VAESIMC, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_xmm }), - 0xDC => (Opcode::VAESENC, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDD => (Opcode::VAESENCLAST, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDE => (Opcode::VAESDEC, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), - 0xDF => (Opcode::VAESDECLAST, if L { - VEXOperandCode::G_V_E_ymm - } else { - VEXOperandCode::G_V_E_xmm - }), + 0xDC => (Opcode::VAESENC, VEXOperandCode::G_V_E_xyLmm), + 0xDD => (Opcode::VAESENCLAST, VEXOperandCode::G_V_E_xyLmm), + 0xDE => (Opcode::VAESDEC, VEXOperandCode::G_V_E_xyLmm), + 0xDF => (Opcode::VAESDECLAST, VEXOperandCode::G_V_E_xyLmm), 0xF7 => (Opcode::SHLX, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_V }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } } else if let VEXOpcodePrefix::PrefixF2 = p { match opc { 0xF5 => (Opcode::PDEP, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E }), 0xF6 => (Opcode::MULX, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E }), 0xF7 => (Opcode::SHRX, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_V }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } } else if let VEXOpcodePrefix::PrefixF3 = p { match opc { 0xF5 => (Opcode::PEXT, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E }), 0xF7 => (Opcode::SARX, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_V }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } } else { match opc { 0xF2 => (Opcode::ANDN, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E }), 0xF3 => (Opcode::Invalid, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::BMI1_F3 }), 0xF5 => (Opcode::BZHI, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_V }), 0xF7 => (Opcode::BEXTR, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_V }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } @@ -3227,7 +2425,6 @@ fn read_vex_instruction< } VEXOperandCode::G_E_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x01 => (Opcode::VPERMPD, if L { @@ -3236,94 +2433,43 @@ fn read_vex_instruction< } VEXOperandCode::G_E_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x02 => (Opcode::VPBLENDD, if L { - if instruction.prefixes.vex_unchecked().w() { - return Err(DecodeError::InvalidOpcode); - } - VEXOperandCode::G_V_E_ymm_imm8 - } else { - if instruction.prefixes.vex_unchecked().w() { - return Err(DecodeError::InvalidOpcode); - } - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x04 => (Opcode::VPERMILPS, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x05 => (Opcode::VPERMILPD, if L { - VEXOperandCode::G_E_ymm_imm8 + 0x02 => (Opcode::VPBLENDD, if instruction.prefixes.vex_unchecked().w() { + return Err(DecodeError::InvalidOpcode); } else { - VEXOperandCode::G_E_xmm_imm8 + VEXOperandCode::G_V_E_xyLmm_imm8 }), + 0x04 => (Opcode::VPERMILPS, VEXOperandCode::G_E_xyLmm_imm8), + 0x05 => (Opcode::VPERMILPD, VEXOperandCode::G_E_xyLmm_imm8), 0x06 => (Opcode::VPERM2F128, if L { if instruction.prefixes.vex_unchecked().w() { return Err(DecodeError::InvalidOpcode); } VEXOperandCode::G_V_E_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x08 => (Opcode::VROUNDPS, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x09 => (Opcode::VROUNDPD, if L { - VEXOperandCode::G_E_ymm_imm8 - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x0A => (Opcode::VROUNDSS, if L { - VEXOperandCode::G_V_E_xmm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0B => (Opcode::VROUNDSD, if L { - VEXOperandCode::G_V_E_xmm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0C => (Opcode::VBLENDPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0D => (Opcode::VBLENDPD, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0E => (Opcode::VPBLENDW, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), - 0x0F => (Opcode::VPALIGNR, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), + 0x08 => (Opcode::VROUNDPS, VEXOperandCode::G_E_xyLmm_imm8), + 0x09 => (Opcode::VROUNDPD, VEXOperandCode::G_E_xyLmm_imm8), + 0x0A => (Opcode::VROUNDSS, VEXOperandCode::G_V_E_xmm_imm8), + 0x0B => (Opcode::VROUNDSD, VEXOperandCode::G_V_E_xmm_imm8), + 0x0C => (Opcode::VBLENDPS, VEXOperandCode::G_V_E_xyLmm_imm8), + 0x0D => (Opcode::VBLENDPD, VEXOperandCode::G_V_E_xyLmm_imm8), + 0x0E => (Opcode::VPBLENDW, VEXOperandCode::G_V_E_xyLmm_imm8), + 0x0F => (Opcode::VPALIGNR, VEXOperandCode::G_V_E_xyLmm_imm8), 0x14 => (Opcode::VPEXTRB, if L || instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::Ev_G_xmm_imm8 }), 0x15 => (Opcode::VPEXTRW, if L || instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::Ev_G_xmm_imm8 }), 0x16 => { (Opcode::VPEXTRD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { // varies on W @@ -3331,30 +2477,25 @@ fn read_vex_instruction< }) }, 0x17 => (Opcode::VEXTRACTPS, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::Ev_G_xmm_imm8 }), 0x18 => if instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { (Opcode::VINSERTF128, if L { VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }) }, 0x19 => if instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { (Opcode::VEXTRACTF128, if L { VEXOperandCode::E_xmm_G_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }) }, @@ -3364,20 +2505,17 @@ fn read_vex_instruction< VEXOperandCode::E_G_xmm_imm8 }), 0x20 => (Opcode::VPINSRB, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_xmm_Ev_imm8 }), 0x21 => (Opcode::VINSERTPS, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E_xmm_imm8 }), 0x22 => { (Opcode::VPINSRD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_xmm_Ev_imm8 @@ -3386,33 +2524,21 @@ fn read_vex_instruction< 0x38 => (Opcode::VINSERTI128, if L { VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x39 => (Opcode::VEXTRACTI128, if L { VEXOperandCode::E_xmm_G_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), - 0x40 => (Opcode::VDPPS, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), + 0x40 => (Opcode::VDPPS, VEXOperandCode::G_V_E_xyLmm_imm8), 0x41 => (Opcode::VDPPD, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E_xmm_imm8 }), - 0x42 => (Opcode::VMPSADBW, if L { - VEXOperandCode::G_V_E_ymm_imm8 - } else { - VEXOperandCode::G_V_E_xmm_imm8 - }), + 0x42 => (Opcode::VMPSADBW, VEXOperandCode::G_V_E_xyLmm_imm8), 0x44 => (Opcode::VPCLMULQDQ, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_V_E_xmm_imm8 @@ -3423,7 +2549,6 @@ fn read_vex_instruction< } VEXOperandCode::G_V_E_ymm_imm8 } else { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); }), 0x4A => (Opcode::VBLENDVPS, if L { @@ -3437,7 +2562,6 @@ fn read_vex_instruction< VEXOperandCode::G_V_E_xmm_xmm4 }), 0x4C => if instruction.prefixes.vex_unchecked().w() { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { (Opcode::VPBLENDVB, if L { @@ -3446,57 +2570,28 @@ fn read_vex_instruction< VEXOperandCode::G_V_E_xmm_xmm4 }) }, - 0x60 => (Opcode::VPCMPESTRM, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x61 => (Opcode::VPCMPESTRI, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x62 => (Opcode::VPCMPISTRM, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0x63 => (Opcode::VPCMPISTRI, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), - 0xDF => (Opcode::VAESKEYGENASSIST, if L { - instruction.opcode = Opcode::Invalid; - return Err(DecodeError::InvalidOpcode); - } else { - VEXOperandCode::G_E_xmm_imm8 - }), + 0x60 => (Opcode::VPCMPESTRM, VEXOperandCode::G_E_xmm_imm8), + 0x61 => (Opcode::VPCMPESTRI, VEXOperandCode::G_E_xmm_imm8), + 0x62 => (Opcode::VPCMPISTRM, VEXOperandCode::G_E_xmm_imm8), + 0x63 => (Opcode::VPCMPISTRI, VEXOperandCode::G_E_xmm_imm8), + 0xDF => (Opcode::VAESKEYGENASSIST, VEXOperandCode::G_E_xmm_imm8), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } } else if let VEXOpcodePrefix::PrefixF2 = p { match opc { 0xF0 => (Opcode::RORX, if L { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } else { VEXOperandCode::G_E_Ib }), _ => { - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } } else { // the only VEX* 0f3a instructions have an implied 66 prefix. - instruction.opcode = Opcode::Invalid; return Err(DecodeError::InvalidOpcode); } } -- cgit v1.1