diff options
| -rw-r--r-- | src/long_mode/display.rs | 66 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 385 | 
2 files changed, 215 insertions, 236 deletions
| diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 181ea14..b1aeee2 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -360,7 +360,6 @@ const MNEMONICS: &[&'static str] = &[      "sub",      "xor",      "cmp", -      "rol",      "ror",      "rcl", @@ -369,13 +368,20 @@ const MNEMONICS: &[&'static str] = &[      "shr",      "sal",      "sar", - -    "invalid", -    "xadd", -    "bt", -    "bts",      "btc",      "btr", +    "bts", +    "cmpxchg", +    "cmpxchg8b", +    "cmpxchg16b", +    "dec", +    "inc", +    "neg", +    "not", +    "xadd", +    "xchg", +    "invalid", +    "bt",      "bsf",      "bsr",      "tzcnt", @@ -420,8 +426,8 @@ const MNEMONICS: &[&'static str] = &[      "movsx",      "movsxd",      "shrd", -    "inc", -    "dec", +//    "inc", +//    "dec",      "hlt",      "call",      "callf", @@ -435,7 +441,7 @@ const MNEMONICS: &[&'static str] = &[      "prefetch0",      "prefetch1",      "prefetch2", -    "xchg", +//    "xchg",      "popf",      "int",      "into", @@ -503,9 +509,9 @@ const MNEMONICS: &[&'static str] = &[      "div",      "idiv",      "mul", -    "neg", -    "not", -    "cmpxchg", +//    "neg", +//    "not", +//    "cmpxchg",      "seto",      "setno",      "setb", @@ -590,6 +596,7 @@ const MNEMONICS: &[&'static str] = &[      "movdq2q",      "rsqrtss",      "rcpss", +      "andn",      "bextr",      "blsi", @@ -620,10 +627,13 @@ const MNEMONICS: &[&'static str] = &[      "enclu",      "rdpkru",      "wrpkru", +      "rdpru",      "clzero", +      "rdseed",      "rdrand", +      "addps",      "addpd",      "andnps", @@ -764,6 +774,7 @@ const MNEMONICS: &[&'static str] = &[      "vmwrite",      "xorps",      "xorpd", +      "vmovddup",      "vpshuflw",      "vpshufhw", @@ -772,6 +783,7 @@ const MNEMONICS: &[&'static str] = &[      "vaddsubps",      "vcvtpd2dq",      "vlddqu", +      "vcomisd",      "vcomiss",      "vucomisd", @@ -1114,6 +1126,7 @@ const MNEMONICS: &[&'static str] = &[      "vzeroall",      "vldmxcsr",      "vstmxcsr", +      "pclmulqdq",      "aeskeygenassist",      "aesimc", @@ -1194,6 +1207,7 @@ const MNEMONICS: &[&'static str] = &[      "phaddw",      "hsubpd",      "haddpd", +      "sha1rnds4",      "sha1nexte",      "sha1msg1", @@ -1201,6 +1215,7 @@ const MNEMONICS: &[&'static str] = &[      "sha256rnds2",      "sha256msg1",      "sha256msg2", +      "lzcnt",      "clgi",      "stgi", @@ -1212,15 +1227,20 @@ const MNEMONICS: &[&'static str] = &[      "invlpga",      "invlpgb",      "tlbsync", +      "movbe", +      "adcx",      "adox", +      "prefetchw", +      "rdpid", -    "cmpxchg8b", -    "cmpxchg16b", +//    "cmpxchg8b", +//    "cmpxchg16b",      "vmptrld",      "vmptrst", +      "bzhi",      "mulx",      "shlx", @@ -1235,10 +1255,12 @@ const MNEMONICS: &[&'static str] = &[      "xsavec64",      "xsaves",      "xsaves64", +      "rdfsbase",      "rdgsbase",      "wrfsbase",      "wrgsbase", +      "crc32",      "salc",      "xlat", @@ -1335,12 +1357,17 @@ const MNEMONICS: &[&'static str] = &[      "fxtract",      "fyl2x",      "fyl2xp1", +      "loopnz",      "loopz",      "loop",      "jrcxz", + +    // started shipping in Tremont, 2020 sept 23      "movdir64b",      "movdiri", + +    // started shipping in Tiger Lake, 2020 sept 2      "aesdec128kl",      "aesdec256kl",      "aesdecwide128kl", @@ -1360,8 +1387,8 @@ const MNEMONICS: &[&'static str] = &[      "femms",      "pi2fw",      "pi2fd", -    "pi2iw", -    "pi2id", +    "pf2iw", +    "pf2id",      "pmulhrw",      "pfcmpge",      "pfmin", @@ -1388,7 +1415,7 @@ const MNEMONICS: &[&'static str] = &[      "enqcmd",      "enqcmds", -    // INVPCID, +    // INVPCID      "invept",      "invvpid",      "invpcid", @@ -1715,8 +1742,6 @@ const MNEMONICS: &[&'static str] = &[      "bndldx",      "bndstx", - -      "vgf2p8affineqb",      "vgf2p8affineinvqb",      "vpshrdq", @@ -1805,6 +1830,7 @@ const MNEMONICS: &[&'static str] = &[      "vpandnq",      "vpandd",      "vpandq", +      "psmash",      "pvalidate",      "rmpadjust", @@ -1814,7 +1840,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/long_mode/mod.rs b/src/long_mode/mod.rs index 61c6f10..8772882 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -1068,33 +1068,14 @@ const XSAVE: [Opcode; 10] = [  #[non_exhaustive]  #[repr(u32)]  pub enum Opcode { -ADD = 0x1000, -ADC = 0x1001, -AND = 0x1002, -BTC = 0x1003, -BTR = 0x1004, -BTS = 0x1005, -CMPXCHG = 0x1006, -CMPXCHG8B = 0x1007, -CMPXCHG16B = 0x1008, -DEC = 0x1009, -INC = 0x100a, -NEG = 0x100b, -NOT = 0x100c, -OR = 0x100d, -SBB = 0x100e, -SUB = 0x100f, -XOR = 0x1010, -XADD = 0x1011, -XCHG = 0x1012, -//    ADD = 0, -//    OR, -//    ADC, -//    SBB, -//    AND, -//    SUB, -//    XOR, -    CMP, +    ADD = 0x1000, +    OR = 0x1001, +    ADC = 0x1002, +    SBB = 0x1003, +    AND = 0x1004, +    SUB = 0x1005, +    XOR = 0x1006, +    CMP = 7,      ROL = 8,      ROR,      RCL, @@ -1102,8 +1083,20 @@ XCHG = 0x1012,      SHL,      SHR,      SAL, -    SAR, -    Invalid = 16, +    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, @@ -5269,7 +5262,7 @@ enum OperandCode {      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().operand_case(OperandCase::MOVQ_f30f).bits(), +    MOVQ_f30f = OperandCodeBuilder::new().read_E().operand_case(OperandCase::MOVQ_f30f).bits(),  //    Unsupported = OperandCodeBuilder::new().operand_case(49).bits(), @@ -5285,7 +5278,7 @@ enum OperandCode {  //    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_modrm().operand_case(OperandCase::ModRM_0xf30f38d8).bits(), +    ModRM_0xf30f38d8 = OperandCodeBuilder::new().read_E().operand_case(OperandCase::ModRM_0xf30f38d8).bits(),      ModRM_0xf30f38dc = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38dc).bits(),      ModRM_0xf30f38dd = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38dd).bits(),      ModRM_0xf30f38de = OperandCodeBuilder::new().read_modrm().operand_case(OperandCase::ModRM_0xf30f38de).bits(), @@ -5454,18 +5447,18 @@ enum OperandCode {      Zv_Ivq_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 5).bits(),      Zv_Ivq_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 6).bits(),      Zv_Ivq_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 7).bits(), -    Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Eb).bits(), -    Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Ew).bits(), -    Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gv_Ew_LSL).bits(), -    Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gdq_Ed).bits(), +    Gv_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Eb).bits(), +    Gv_Ew = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Ew).bits(), +    Gv_Ew_LSL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(), +    Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gdq_Ed).bits(),      Gd_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gd_Ed).bits(),      Md_Gd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Md_Gd).bits(),  //    Edq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(49).bits(), -    Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Gdq_Ev).bits(), -    Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::Mdq_Gdq).bits(), -    G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_xmm_Ib).bits(), -    G_E_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_xmm_Ub).bits(), -    G_U_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_U_xmm_Ub).bits(), +    Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Gdq_Ev).bits(), +    Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::Mdq_Gdq).bits(), +    G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_xmm_Ib).bits(), +    G_E_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_xmm_Ub).bits(), +    G_U_xmm_Ub = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_U_xmm_Ub).bits(),      AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Ob).bits(),      AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Xb).bits(),      AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AX_Ov).bits(), @@ -5511,9 +5504,9 @@ enum OperandCode {      Ev_Gv_CL = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Ev_Gv_CL).bits(),      G_mm_U_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_mm_U_mm).bits(),      G_Mq_mm = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::G_Mq_mm).bits(), -    G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_mm_Ew_Ib).bits(), -    G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::G_E_q).bits(), -    E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::E_G_q).bits(), +    G_mm_Ew_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_mm_Ew_Ib).bits(), +    G_E_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().operand_case(OperandCase::G_E_q).bits(), +    E_G_q = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().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(), @@ -5528,22 +5521,22 @@ enum OperandCode {      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().operand_case(OperandCase::Ew_Sw).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().operand_case(OperandCase::Sw_Ew).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(), -    INV_Gv_M = OperandCodeBuilder::new().operand_case(OperandCase::INV_Gv_M).bits(), -    PMOVX_G_E_xmm = OperandCodeBuilder::new().operand_case(OperandCase::PMOVX_G_E_xmm).bits(), -    PMOVX_E_G_xmm = OperandCodeBuilder::new().operand_case(OperandCase::PMOVX_E_G_xmm).bits(), -    G_Ev_xmm_Ib = OperandCodeBuilder::new().operand_case(OperandCase::G_Ev_xmm_Ib).bits(), -    G_E_mm_Ib = OperandCodeBuilder::new().operand_case(OperandCase::G_E_mm_Ib).bits(), +    INV_Gv_M = OperandCodeBuilder::new().read_E().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(),  }  fn base_opcode_map(v: u8) -> Opcode { @@ -6941,6 +6934,7 @@ fn read_with_annotations<                      });                  }                  prefixes.rex_from(0); +                prefixes.rb_size = RegisterBank::B;              }              if words.offset() >= 15 {                  return Err(DecodeError::TooLong); @@ -7182,6 +7176,7 @@ fn read_operands<                  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, 4)? as u64; @@ -7676,13 +7671,8 @@ fn read_operands<          }          OperandCase::Gv_Eb => {              let w = instruction.prefixes.rb_size(); -            instruction.mem_size = 1; -            let bank = instruction.prefixes.vqp_size(); -            let modrm = read_modrm(words)?; -            instruction.operands[1] = read_E(words, instruction, modrm, w, sink)?; -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank); +            instruction.operands[1] = mem_oper;              sink.record(                  modrm_start as u32 + 3,                  modrm_start as u32 + 5, @@ -7691,18 +7681,16 @@ fn read_operands<              );              if instruction.operands[1] == OperandSpec::RegMMM {                  instruction.mem_size = 0; +                instruction.regs[1].bank = w; +            } else { +                instruction.mem_size = 1;              }              instruction.operand_count = 2;          }          OperandCase::Gv_Ew => {              let w = RegisterBank::W; -            instruction.mem_size = 2; -            let bank = instruction.prefixes.vqp_size(); -            let modrm = read_modrm(words)?; -            instruction.operands[1] = read_E(words, instruction, modrm, w, sink)?; -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank); +            instruction.operands[1] = mem_oper;              sink.record(                  modrm_start as u32 + 3,                  modrm_start as u32 + 5, @@ -7711,16 +7699,21 @@ fn read_operands<              );              if instruction.operands[1] == OperandSpec::RegMMM {                  instruction.mem_size = 0; +                instruction.regs[1].bank = w; +            } else { +                instruction.mem_size = 2;              }              instruction.operand_count = 2;          },          OperandCase::Gdq_Ed => { -            let modrm = read_modrm(words)?; -            instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; -            instruction.mem_size = 4; -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q); +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::Q; +            if mem_oper == OperandSpec::RegMMM { +                instruction.regs[1].bank = RegisterBank::D; +            } else { +                instruction.mem_size = 4; +            }              sink.record(                  modrm_start as u32 + 3,                  modrm_start as u32 + 5, @@ -7745,28 +7738,31 @@ fn read_operands<                  instruction.mem_size = 16;              }          }, -        op @ OperandCase::G_M_xmm | -        op @ OperandCase::G_E_xmm => { +        OperandCase::G_M_xmm => {              instruction.regs[0].bank = RegisterBank::X;              if instruction.operands[1] == OperandSpec::RegMMM { -                if op == OperandCase::G_M_xmm { -                    sink.record( -                        modrm_start + 6, -                        modrm_start + 7, -                        InnerDescription::Misc("mod bits 0b11 are illegal for this opcode") -                            .with_id(modrm_start as u32 - 8) -                    ); -                    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 are illegal for this opcode") +                        .with_id(modrm_start as u32 - 8) +                ); +                return Err(DecodeError::InvalidOperand); +            } +            instruction.mem_size = 16; + +        } +        OperandCase::G_E_xmm => { +            instruction.regs[0].bank = RegisterBank::X; +            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 {                  if instruction.opcode == Opcode::MOVDDUP {                      instruction.mem_size = 8; @@ -7776,11 +7772,8 @@ fn read_operands<              }          },          OperandCase::G_E_xmm_Ib => { -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X); +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::X;              sink.record(                  modrm_start as u32 + 3,                  modrm_start as u32 + 5, @@ -7803,6 +7796,8 @@ fn read_operands<                  } else {                      instruction.mem_size = 16;                  } +            } else { +                instruction.regs[1].bank = RegisterBank::X;              }              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3; @@ -7975,25 +7970,24 @@ fn read_operands<              }          },          OperandCase::G_E_mm_Ib => { -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E_mm(words, instruction, modrm, sink)?; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); +            instruction.operands[1] = mem_oper;              instruction.imm =                  read_num(words, 1)? as u8 as u64; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b0111;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8; +            } else { +                instruction.regs[1].num &= 0b0111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.mem_size = 0;              }              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3;          }          OperandCase::G_Ev_xmm_Ib => { -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X); +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::X;              instruction.imm =                  read_num(words, 1)? as u8 as u64;              if instruction.operands[1] != OperandSpec::RegMMM { @@ -8008,17 +8002,16 @@ fn read_operands<                      Opcode::PINSRD => 4,                      _ => 8,                  }; +            } else { +                instruction.regs[1].bank = RegisterBank::X;              }              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3;          }          OperandCase::PMOVX_E_G_xmm => { -            let modrm = read_modrm(words)?; - -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X); +            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; @@ -8026,18 +8019,16 @@ fn read_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);                  }              }          }          OperandCase::PMOVX_G_E_xmm => { -            let modrm = read_modrm(words)?; - -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::X); +            instruction.regs[0].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; +            instruction.operands[1] = mem_oper;              if instruction.operands[1] != OperandSpec::RegMMM {                  if [Opcode::PMOVSXBQ, Opcode::PMOVZXBQ].contains(&instruction.opcode) {                      instruction.mem_size = 2; @@ -8047,21 +8038,20 @@ fn read_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);                  }              }          }          OperandCase::INV_Gv_M => { -            let modrm = read_modrm(words)?; -            if modrm >= 0xc0 { +            if mem_oper == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q); +            instruction.regs[0].bank = RegisterBank::Q;              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.rex_unchecked().w() {                      instruction.mem_size = 10; @@ -8075,14 +8065,12 @@ fn read_operands<              }          }          OperandCase::G_U_xmm_Ub => { -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E_xmm(words, instruction, modrm, sink)?; +            instruction.operands[1] = mem_oper;              if instruction.operands[1] != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::D); +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::X;              instruction.imm =                  read_num(words, 1)? as u8 as u64;              instruction.operands[2] = OperandSpec::ImmU8; @@ -8166,11 +8154,11 @@ fn read_operands<              };          }          OperandCase::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, instruction.prefixes.rex_unchecked().r(), RegisterBank::X); +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::X; +            if mem_oper == OperandSpec::RegMMM { +                instruction.regs[1].bank = RegisterBank::X; +            }              instruction.imm =                  read_num(words, 1)? as u8 as u64;              if instruction.operands[1] != OperandSpec::RegMMM { @@ -8261,11 +8249,9 @@ fn read_operands<              instruction.operand_count = 3;          }          OperandCase::G_mm_Ew_Ib => { -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::D, sink)?; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM); +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b0111;              if instruction.operands[1] == OperandSpec::RegMMM {                  instruction.regs[1].bank = RegisterBank::D;              } else { @@ -8299,37 +8285,26 @@ fn read_operands<              instruction.regs[1].num &= 0b111;          },          OperandCase::Gv_Ew_LSL => { -            let opwidth = bank_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::W, sink)?; +            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::D;              } else {                  instruction.mem_size = 2;              } -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), opwidth); +            instruction.regs[0].bank = instruction.prefixes.vqp_size();          },          OperandCase::Gdq_Ev => { -            let bank = bank_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E(words, instruction, modrm, bank, sink)?; +            instruction.operands[1] = mem_oper;              // `opwidth` can be 2, 4, or 8 here. if opwidth is 2, the first operand is a dword.              // if opwidth is 4, both registers are dwords. and if opwidth is 8, both registers are              // qword.              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 4;              } -            let regbank = if bank == RegisterBank::W { -                RegisterBank::D -            } else { -                bank +            if instruction.regs[0].bank == RegisterBank::W { +                instruction.regs[0].bank = RegisterBank::D;              }; -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), regbank);              instruction.operand_count = 2;          },          op @ OperandCase::AL_Ob | @@ -8416,17 +8391,14 @@ fn read_operands<          }          OperandCase::Mdq_Gdq => {              let bank = if instruction.prefixes.rex_unchecked().w() { RegisterBank::Q } else { RegisterBank::D }; -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = instruction.operands[0]; -            instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?; +            instruction.operands[1] = OperandSpec::RegRRR; +            instruction.operands[0] = mem_oper;              if instruction.operands[0] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } else { -                instruction.mem_size = bank as u8 +                instruction.mem_size = bank as u8;              } -            instruction.regs[0] = -                RegSpec::gp_from_parts_non_byte((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), bank); +            instruction.regs[0].bank = bank;              instruction.operand_count = 2;          } @@ -8445,15 +8417,14 @@ fn read_operands<                  return Err(DecodeError::InvalidOpcode);              } -            let modrm = read_modrm(words)?; - -            instruction.operands[0] = read_E(words, instruction, modrm, RegisterBank::Q, sink)?; +            instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q); +            instruction.regs[0].bank = RegisterBank::Q;              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 8; +            } else { +                instruction.regs[1].bank = RegisterBank::Q;              }          }          OperandCase::G_E_q => { @@ -8461,15 +8432,14 @@ fn read_operands<                  return Err(DecodeError::InvalidOpcode);              } -            let modrm = read_modrm(words)?; -              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.regs[0] = -                RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex_unchecked().r(), RegisterBank::Q); -            instruction.operands[1] = read_E(words, instruction, modrm, RegisterBank::Q, sink)?; +            instruction.operands[1] = mem_oper; +            instruction.regs[0].bank = RegisterBank::Q;              instruction.operand_count = 2;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8; +            } else { +                instruction.regs[1].bank = RegisterBank::Q;              }          }          OperandCase::G_Mq_mm => { @@ -8493,24 +8463,25 @@ fn read_operands<              //              // 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, instruction.prefixes.rex_unchecked().r(), 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.prefixes.rex_unchecked().w() {                  let op = instruction.operands[0];                  instruction.operands[0] = instruction.operands[1];                  instruction.operands[1] = op; -                instruction.regs[1].bank = RegisterBank::Q;                  instruction.regs[0].bank = RegisterBank::MM;                  instruction.regs[0].num &= 0b111;                  instruction.opcode = Opcode::MOVD; -            } -            if instruction.operands[1] != OperandSpec::RegMMM { -                if instruction.prefixes.rex_unchecked().w() { +                if instruction.operands[1] != OperandSpec::RegMMM {                      instruction.mem_size = 4;                  } else { +                    instruction.regs[1].bank = RegisterBank::Q; +                } +            } else { +                if instruction.operands[1] != OperandSpec::RegMMM {                      instruction.mem_size = 8; +                } else { +                    instruction.regs[1].bank = RegisterBank::X;                  }              }          } @@ -8966,43 +8937,35 @@ fn read_operands<              instruction.operands[1] = OperandSpec::ImmU8;          },          OperandCase::ModRM_0xf30f38d8 => { -            let modrm = read_modrm(words)?; -            let r = (modrm >> 3) & 7; +            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(());                  }                  _ => { @@ -9388,60 +9351,50 @@ fn read_operands<              instruction.regs[0].bank = RegisterBank::X;          }          OperandCase::Ew_Sw => { -            let modrm = read_modrm(words)?; -              // 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, RegisterBank::W, sink)?;                  instruction.mem_size = 2;              }          },          OperandCase::Sw_Ew => { -            let modrm = read_modrm(words)?; -              // 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;              }          }, | 
