diff options
Diffstat (limited to 'src/long_mode')
| -rw-r--r-- | src/long_mode/display.rs | 94 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 319 | 
2 files changed, 395 insertions, 18 deletions
| diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 52018da..df7237d 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -422,6 +422,8 @@ const MNEMONICS: &[&'static str] = &[      "setle",      "setg",      "cpuid", +    "ud0", +    "ud1",      "ud2",      "wbinvd",      "invd", @@ -652,7 +654,6 @@ const MNEMONICS: &[&'static str] = &[      "sysexit",      "ucomisd",      "ucomiss", -    "ud2e",      "vmread",      "vmwrite",      "xorps", @@ -1212,6 +1213,50 @@ const MNEMONICS: &[&'static str] = &[      "loopz",      "loop",      "jrcxz", +    "movdir64b", +    "movdiri", +    "aesdec128kl", +    "aesdec256kl", +    "aesdecwide128kl", +    "aesdecwide256kl", +    "aesenc128kl", +    "aesenc256kl", +    "aesencwide128kl", +    "aesencwide256kl", +    "encodekey128", +    "encodekey256", +    "loadiwkey", + +    // 3dnow +    "femms", +    "pi2fw", +    "pi2fd", +    "pi2iw", +    "pi2id", +    "pmulhrw", +    "pfcmpge", +    "pfmin", +    "pfrcp", +    "pfrsqrt", +    "pfsub", +    "pfadd", +    "pfcmpgt", +    "pfmax", +    "pfrcpit1", +    "pfrsqit1", +    "pfsubr", +    "pfacc", +    "pfcmpeq", +    "pfmul", +    "pfrcpit2", +    "pfnacc", +    "pswapd", +    "pfpnacc", +    "pavgusb", + +    // ENQCMD +    "enqcmd", +    "enqcmds",  ];  impl Opcode { @@ -1425,6 +1470,21 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::HADDPS |              Opcode::HSUBPS |              Opcode::ADDSUBPS | +            Opcode::PMULHRW | +            Opcode::PFRCP | +            Opcode::PFRSQRT | +            Opcode::PFSUB | +            Opcode::PFADD | +            Opcode::PFRCPIT1 | +            Opcode::PFRSQIT1 | +            Opcode::PFSUBR | +            Opcode::PFACC | +            Opcode::PFMUL | +            Opcode::PFRCPIT2 | +            Opcode::PFNACC | +            Opcode::PSWAPD | +            Opcode::PFPNACC | +            Opcode::PAVGUSB |              Opcode::XADD|              Opcode::DIV |              Opcode::IDIV | @@ -1631,6 +1691,10 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::JG => { write!(out, "{}", colors.control_flow_op(self)) }              /* Data transfer */ +            Opcode::PI2FW | +            Opcode::PI2FD | +            Opcode::PF2ID | +            Opcode::PF2IW |              Opcode::VCVTDQ2PD |              Opcode::VCVTDQ2PS |              Opcode::VCVTPD2DQ | @@ -1698,6 +1762,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VMOVNTDQA |              Opcode::VMOVNTPD |              Opcode::VMOVNTPS | +            Opcode::MOVDIR64B | +            Opcode::MOVDIRI |              Opcode::MOVNTDQA |              Opcode::VMOVQ |              Opcode::VMOVSHDUP | @@ -2040,6 +2106,11 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::PMINUB |              Opcode::PMINUD |              Opcode::PMINUW | +            Opcode::PFCMPGE | +            Opcode::PFMIN | +            Opcode::PFCMPGT | +            Opcode::PFMAX | +            Opcode::PFCMPEQ |              Opcode::CMPS |              Opcode::SCAS |              Opcode::TEST | @@ -2119,6 +2190,7 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VERW |              Opcode::JMPE |              Opcode::EMMS | +            Opcode::FEMMS |              Opcode::GETSEC |              Opcode::LFS |              Opcode::LGS | @@ -2126,7 +2198,6 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::RSM |              Opcode::SYSENTER |              Opcode::SYSEXIT | -            Opcode::UD2E |              Opcode::VMREAD |              Opcode::VMWRITE |              Opcode::VMCLEAR | @@ -2164,6 +2235,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::WRPKRU |              Opcode::RDPRU |              Opcode::CLZERO | +            Opcode::ENQCMD | +            Opcode::ENQCMDS |              Opcode::LAR => { write!(out, "{}", colors.platform_op(self)) }              Opcode::CRC32 | @@ -2180,6 +2253,17 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::FFREEP |              Opcode::FDECSTP |              Opcode::FINCSTP | +            Opcode::AESDEC128KL | +            Opcode::AESDEC256KL | +            Opcode::AESDECWIDE128KL | +            Opcode::AESDECWIDE256KL | +            Opcode::AESENC128KL | +            Opcode::AESENC256KL | +            Opcode::AESENCWIDE128KL | +            Opcode::AESENCWIDE256KL | +            Opcode::ENCODEKEY128 | +            Opcode::ENCODEKEY256 | +            Opcode::LOADIWKEY |              Opcode::AESDEC |              Opcode::AESDECLAST |              Opcode::AESENC | @@ -2193,6 +2277,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color              Opcode::VAESIMC |              Opcode::VAESKEYGENASSIST => { write!(out, "{}", colors.misc_op(self)) } +            Opcode::UD0 | +            Opcode::UD1 |              Opcode::UD2 |              Opcode::Invalid => { write!(out, "{}", colors.invalid_op(self)) }          } @@ -2331,7 +2417,7 @@ fn contextualize_intel<T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>>(                          }                          _ => {                              out.write_str(", word ")?; -                            if let Some(prefix) = instr.segment_override_for_op(1) { +                            if let Some(prefix) = instr.segment_override_for_op(i) {                                  write!(out, "{}:", prefix)?;                              }                          } @@ -2346,7 +2432,7 @@ fn contextualize_intel<T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>>(                          },                          _ => {                              out.write_str(", ")?; -                            if let Some(prefix) = instr.segment_override_for_op(1) { +                            if let Some(prefix) = instr.segment_override_for_op(i) {                                  write!(out, "{}:", prefix)?;                              }                              let x = Operand::from_spec(instr, instr.operands[i as usize]); diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 6349aa4..15a1318 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -1071,6 +1071,8 @@ pub enum Opcode {      SETLE,      SETG,      CPUID, +    UD0, +    UD1,      UD2,      WBINVD,      INVD, @@ -1305,7 +1307,6 @@ pub enum Opcode {      SYSEXIT,      UCOMISD,      UCOMISS, -    UD2E,      VMREAD,      VMWRITE,      XORPS, @@ -1878,6 +1879,54 @@ pub enum Opcode {      LOOPZ,      LOOP,      JRCXZ, + +    // started shipping in Tremont, 2020 sept 23 +    MOVDIR64B, +    MOVDIRI, + +    // started shipping in Tiger Lake, 2020 sept 2 +    AESDEC128KL, +    AESDEC256KL, +    AESDECWIDE128KL, +    AESDECWIDE256KL, +    AESENC128KL, +    AESENC256KL, +    AESENCWIDE128KL, +    AESENCWIDE256KL, +    ENCODEKEY128, +    ENCODEKEY256, +    LOADIWKEY, + +    // 3dnow +    FEMMS, +    PI2FW, +    PI2FD, +    PF2IW, +    PF2ID, +    PMULHRW, +    PFCMPGE, +    PFMIN, +    PFRCP, +    PFRSQRT, +    PFSUB, +    PFADD, +    PFCMPGT, +    PFMAX, +    PFRCPIT1, +    PFRSQIT1, +    PFSUBR, +    PFACC, +    PFCMPEQ, +    PFMUL, +    PFRCPIT2, +    PFNACC, +    PSWAPD, +    PFPNACC, +    PAVGUSB, + +    // ENQCMD +    ENQCMD, +    ENQCMDS,  }  #[derive(Debug)] @@ -3913,6 +3962,7 @@ enum OperandCode {      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(), @@ -4121,6 +4171,7 @@ enum OperandCode {      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(),      Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).byte_operands().reg_mem().operand_case(40).bits(),      Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(41).bits(),      Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(55).bits(), @@ -5065,8 +5116,8 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::UD2), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f0d), -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::FEMMS), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f0f),  // 0x10      OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::G_E_xmm),      OpcodeRecord(Interpretation::Instruction(Opcode::MOVUPS), OperandCode::E_G_xmm), @@ -5256,7 +5307,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_b), OperandCode::Gv_Eb),      OpcodeRecord(Interpretation::Instruction(Opcode::MOVZX_w), OperandCode::Gv_Ew),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), // JMPE, ITANIUM -    OpcodeRecord(Interpretation::Instruction(Opcode::UD2E), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::UD1), OperandCode::Gv_Ev),      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0fba),      OpcodeRecord(Interpretation::Instruction(Opcode::BTC), OperandCode::Gv_Ev),      OpcodeRecord(Interpretation::Instruction(Opcode::TZCNT), OperandCode::Gv_Ev), @@ -5334,7 +5385,7 @@ const OPCODE_0F_MAP: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::PADDB), OperandCode::G_E_mm),      OpcodeRecord(Interpretation::Instruction(Opcode::PADDW), OperandCode::G_E_mm),      OpcodeRecord(Interpretation::Instruction(Opcode::PADDD), OperandCode::G_E_mm), -    OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), +    OpcodeRecord(Interpretation::Instruction(Opcode::UD0), OperandCode::Gdq_Ed),  ];  #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -5493,8 +5544,8 @@ const OPCODES: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x83_Ev_Ibs),      OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Eb_Gb),      OpcodeRecord(Interpretation::Instruction(Opcode::TEST), OperandCode::Ev_Gv), -    OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gb_Eb), -    OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Gv_Ev), +    OpcodeRecord(Interpretation::Instruction(Opcode::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), @@ -5975,19 +6026,18 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in                      }                      prefixes.rex_from(0); -                    escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map);                      match b {                          0x26 => { -                            prefixes.set_es(); +//                            prefixes.set_es();                          },                          0x2e => { -                            prefixes.set_cs(); +//                            prefixes.set_cs();                          },                          0x36 => { -                            prefixes.set_ss(); +//                            prefixes.set_ss();                          },                          0x3e => { -                            prefixes.set_ds(); +//                            prefixes.set_ds();                          },                          0x64 => {                              prefixes.set_fs(); @@ -5996,6 +6046,7 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in                              prefixes.set_gs();                          },                          0x66 => { +                            escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map);                              alternate_opcode_map = Some(OpcodeMap::Map66);                          },                          0x67 => { @@ -6007,9 +6058,11 @@ fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, in                              prefixes.set_lock();                          },                          0xf2 => { +                            escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map);                              alternate_opcode_map = Some(OpcodeMap::MapF2);                          },                          0xf3 => { +                            escapes_are_prefixes_actually(&mut prefixes, &mut alternate_opcode_map);                              alternate_opcode_map = Some(OpcodeMap::MapF3);                          },                          _ => { unsafe { unreachable_unchecked(); } } @@ -6833,6 +6886,110 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              instruction.operands[0] = read_E(&mut bytes_iter, instruction, modrm, opwidth, length)?;              instruction.operand_count = 1;          } +        OperandCode::ModRM_0x0f0f => { +            let opcode = read_modrm(&mut bytes_iter, length)?; +            match opcode { +                0x0c => { +                    instruction.opcode = Opcode::PI2FW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x0d => { +                    instruction.opcode = Opcode::PI2FD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x1c => { +                    instruction.opcode = Opcode::PF2IW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x1d => { +                    instruction.opcode = Opcode::PF2ID; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x59 => { +                    instruction.opcode = Opcode::PMULHRW; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x90 => { +                    instruction.opcode = Opcode::PFCMPGE; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x94 => { +                    instruction.opcode = Opcode::PFMIN; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x96 => { +                    instruction.opcode = Opcode::PFRCP; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x97 => { +                    instruction.opcode = Opcode::PFRSQRT; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x9a => { +                    instruction.opcode = Opcode::PFSUB; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0x9e => { +                    instruction.opcode = Opcode::PFADD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xa0 => { +                    instruction.opcode = Opcode::PFCMPGT; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xa4 => { +                    instruction.opcode = Opcode::PFMAX; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xa6 => { +                    instruction.opcode = Opcode::PFRCPIT1; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xa7 => { +                    instruction.opcode = Opcode::PFRSQIT1; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xaa => { +                    instruction.opcode = Opcode::PFSUBR; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xae => { +                    instruction.opcode = Opcode::PFACC; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xb0 => { +                    instruction.opcode = Opcode::PFCMPEQ; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xb4 => { +                    instruction.opcode = Opcode::PFMUL; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xb6 => { +                    instruction.opcode = Opcode::PFRCPIT2; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xba => { +                    instruction.opcode = Opcode::PFNACC; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xbb => { +                    instruction.opcode = Opcode::PSWAPD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xbe => { +                    instruction.opcode = Opcode::PFPNACC; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                0xbf => { +                    instruction.opcode = Opcode::PAVGUSB; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm, length); +                } +                _ => { +                    return Err(DecodeError::InvalidOpcode); +                } +            } +        }          OperandCode::ModRM_0x0f38 => {              let opcode = read_modrm(&mut bytes_iter, length)?; @@ -6861,6 +7018,7 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                      match low {                          0 => OperandCode::Gv_Ev,                          1 => OperandCode::Ev_Gv, +                        9 => OperandCode::M_G_xmm,                          _ => {                              instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode); @@ -6899,6 +7057,13 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                  0xcc => Opcode::SHA256MSG1,                  0xcd => Opcode::SHA256MSG2,                  0xf0 | 0xf1 => Opcode::MOVBE, +                0xf9 => { +                    // TODO: always 32-bit mov, be careful about memory size +                    instruction.opcode = Opcode::MOVDIRI; +                    read_operands(decoder, bytes_iter, instruction, OperandCode::M_G_xmm, length)?; +                    instruction.modrm_rrr.bank = RegisterBank::D; +                    return Ok(()); +                }                  _ => {                      instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode); @@ -6915,6 +7080,9 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              } else if opcode == 0x0f {                  instruction.opcode = Opcode::PALIGNR;                  return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_mm_Ib, length); +            } else { +                instruction.opcode = Opcode::Invalid; +                return Err(DecodeError::InvalidOpcode);              }          },          OperandCode::ModRM_0x0fc7 => { @@ -7120,6 +7288,10 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                      instruction.opcode = Opcode::CRC32;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::Gdq_Ev, length);                  } +                0xf8 => { +                    instruction.opcode = Opcode::ENQCMD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::Gdq_Ev, length); +                }                  _ => {                      instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode); @@ -7129,10 +7301,101 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::ModRM_0xf30f38 => {              let op = bytes_iter.next().ok_or(DecodeError::ExhaustedInput).map(|b| { *length += 1; b })?;              match op { +                0xd8 => { +                    let modrm = read_modrm(&mut bytes_iter, length)?; +                    let r = (modrm >> 3) & 7; +                    match r { +                        0b000 => { +                            if modrm >= 0b11_000_000 { +                                return Err(DecodeError::InvalidOperand); +                            } +                            instruction.opcode = Opcode::AESENCWIDE128KL; +                            instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; +                            return Ok(()); +                        } +                        0b001 => { +                            if modrm >= 0b11_000_000 { +                                return Err(DecodeError::InvalidOperand); +                            } +                            instruction.opcode = Opcode::AESDECWIDE128KL; +                            instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; +                            return Ok(()); +                        } +                        0b010 => { +                            if modrm >= 0b11_000_000 { +                                return Err(DecodeError::InvalidOperand); +                            } +                            instruction.opcode = Opcode::AESENCWIDE256KL; +                            instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; +                            return Ok(()); +                        } +                        0b011 => { +                            if modrm >= 0b11_000_000 { +                                return Err(DecodeError::InvalidOperand); +                            } +                            instruction.opcode = Opcode::AESDECWIDE256KL; +                            instruction.operands[0] = read_M(&mut bytes_iter, instruction, modrm, length)?; +                            return Ok(()); +                        } +                        _ => { +                            return Err(DecodeError::InvalidOpcode); +                        } +                    } +                } +                0xdc => { +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm, length)?; +                    if let OperandSpec::RegMMM = instruction.operands[1] { +                        instruction.opcode = Opcode::LOADIWKEY; +                    } else { +                        instruction.opcode = Opcode::AESENC128KL; +                    } +                } +                0xdd => { +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm, length)?; +                    if let OperandSpec::RegMMM = instruction.operands[1] { +                        return Err(DecodeError::InvalidOperand); +                    } else { +                        instruction.opcode = Opcode::AESDEC128KL; +                    } +                } +                0xde => { +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm, length)?; +                    if let OperandSpec::RegMMM = instruction.operands[1] { +                        return Err(DecodeError::InvalidOperand); +                    } else { +                        instruction.opcode = Opcode::AESENC256KL; +                    } +                } +                0xde => { +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm, length)?; +                    if let OperandSpec::RegMMM = instruction.operands[1] { +                        return Err(DecodeError::InvalidOperand); +                    } else { +                        instruction.opcode = Opcode::AESDEC256KL; +                    } +                }                  0xf6 => {                      instruction.opcode = Opcode::ADOX;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::Gv_Ev, length);                  } +                0xf8 => { +                    instruction.opcode = Opcode::ENQCMDS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::Gdq_Ev, length); +                } +                0xfb => { +                    instruction.opcode = Opcode::ENCODEKEY128; +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_U_xmm, length)?; +                    instruction.modrm_rrr.bank = RegisterBank::D; +                    instruction.modrm_mmm.bank = RegisterBank::D; +                    return Ok(()); +                } +                0xfb => { +                    instruction.opcode = Opcode::ENCODEKEY256; +                    read_operands(decoder, bytes_iter, instruction, OperandCode::G_U_xmm, length)?; +                    instruction.modrm_rrr.bank = RegisterBank::D; +                    instruction.modrm_mmm.bank = RegisterBank::D; +                    return Ok(()); +                }                  _ => {                      instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode); @@ -7209,6 +7472,10 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                      instruction.opcode = Opcode::ADCX;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::Gv_Ev, length);                  } +                0xf8 => { +                    instruction.opcode = Opcode::MOVDIR64B; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::MOVDIR64B, length); +                }                  _ => {                      instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode); @@ -7242,6 +7509,14 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                      instruction.opcode = Opcode::ROUNDSD;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length);                  } +                0x0c => { +                    instruction.opcode = Opcode::BLENDPS; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                } +                0x0d => { +                    instruction.opcode = Opcode::BLENDPD; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                }                  0x0e => {                      instruction.opcode = Opcode::PBLENDW;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); @@ -7296,6 +7571,10 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter                      instruction.opcode = Opcode::MPSADBW;                      return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length);                  } +                0x44 => { +                    instruction.opcode = Opcode::PCLMULQDQ; +                    return read_operands(decoder, bytes_iter, instruction, OperandCode::G_E_xmm_Ib, length); +                }                  0x60 => {                      instruction.opcode = Opcode::PCMPESTRM; @@ -7794,10 +8073,11 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          }          OperandCode::ModRM_0x0f18 => { -            if mem_oper == OperandSpec::RegMMM { +            let rrr = instruction.modrm_rrr.num & 0b111; +            // only PREFETCH* are invalid on reg operand +            if mem_oper == OperandSpec::RegMMM && rrr < 4{                  return Err(DecodeError::InvalidOperand);              } -            let rrr = instruction.modrm_rrr.num & 0b111;              instruction.operands[0] = mem_oper;              instruction.operand_count = 1;              instruction.opcode = match rrr { @@ -8446,6 +8726,17 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::x87_df => {              return decode_x87(decoder, bytes_iter, instruction, operand_code, length);          } +        OperandCode::MOVDIR64B => { +            // at this point we've done a read as if it was Gv_M (`lea` operands). because the +            // first operand is actually a memory address, and this is the only x86 instruction +            // other than movs to have two memory operands, the first operand has to be sized by +            // address-size, not operand-size. +            if instruction.prefixes.address_size() { +                instruction.modrm_rrr.bank = RegisterBank::D; +            } else { +                instruction.modrm_rrr.bank = RegisterBank::Q; +            }; +        }          _ => {              // TODO: this should be unreachable - safe to panic now?              // can't simply delete this arm because the non-unlikely operands are handled outside | 
