diff options
| -rw-r--r-- | src/long_mode/display.rs | 8 | ||||
| -rw-r--r-- | src/long_mode/evex.rs | 3 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 1043 | ||||
| -rw-r--r-- | src/long_mode/vex.rs | 218 | ||||
| -rw-r--r-- | src/protected_mode/evex.rs | 3 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 528 | ||||
| -rw-r--r-- | src/protected_mode/vex.rs | 210 | ||||
| -rw-r--r-- | src/shared/evex.in | 1160 | ||||
| -rw-r--r-- | test/long_mode/display.rs | 3 | ||||
| -rw-r--r-- | test/long_mode/evex_generated.rs | 8 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 6 | ||||
| -rw-r--r-- | test/long_mode/operand.rs | 14 | ||||
| -rw-r--r-- | test/long_mode/reuse_test.rs | 10 | ||||
| -rw-r--r-- | test/protected_mode/display.rs | 3 | ||||
| -rw-r--r-- | test/protected_mode/evex_generated.rs | 8 | ||||
| -rw-r--r-- | test/protected_mode/mod.rs | 6 | 
16 files changed, 1595 insertions, 1636 deletions
| diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 107eb94..e60645b 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -3400,7 +3400,13 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:                                              }                                          }                                      } else { -                                        Operand::from_spec(instr, instr.operands[i as usize - 1]).width() / instr.mem_size +                                        // this should never be `None` - that would imply two +                                        // memory operands for a broadcasted operation. +                                        if let Some(width) = Operand::from_spec(instr, instr.operands[i as usize - 1]).width() { +                                            width / instr.mem_size +                                        } else { +                                            0 +                                        }                                      };                                      write!(out, "{{1to{}}}", scale)?;                                  } diff --git a/src/long_mode/evex.rs b/src/long_mode/evex.rs index 483747b..7f456e7 100644 --- a/src/long_mode/evex.rs +++ b/src/long_mode/evex.rs @@ -1,6 +1,7 @@  // use crate::long_mode::{OperandSpec, DecodeError, RegSpec, RegisterBank, Instruction, Opcode}; -use crate::long_mode::{DecodeError, RegSpec, RegisterBank, Instruction, Opcode}; +use crate::long_mode::{Arch, DecodeError, RegSpec, RegisterBank, Instruction, Opcode};  use crate::long_mode::{read_modrm, read_E_vex, read_imm_unsigned}; +use yaxpeax_arch::Reader;  const DEFAULT_EVEX_REGISTER_SIZE: RegisterBank = RegisterBank::Q;  const DEFAULT_EVEX_REGISTER_WIDTH: u8 = 8; diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index a64bab8..d04a091 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -585,20 +585,20 @@ impl Operand {              OperandSpec::Nothing => {                  Operand::Nothing              } -            // the register in modrm_rrr +            // the register in regs[0]              OperandSpec::RegRRR => { -                Operand::Register(inst.modrm_rrr) +                Operand::Register(inst.regs[0])              }              OperandSpec::RegRRR_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegRRR_maskmerge_sae => {                  Operand::RegisterMaskMergeSae( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                      SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), @@ -606,41 +606,41 @@ impl Operand {              }              OperandSpec::RegRRR_maskmerge_sae_noround => {                  Operand::RegisterMaskMergeSaeNoround( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              // the register in modrm_mmm (eg modrm mod bits were 11)              OperandSpec::RegMMM => { -                Operand::Register(inst.modrm_mmm) +                Operand::Register(inst.regs[1])              }              OperandSpec::RegMMM_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.modrm_mmm, +                    inst.regs[1],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegMMM_maskmerge_sae_noround => {                  Operand::RegisterMaskMergeSaeNoround( -                    inst.modrm_mmm, +                    inst.regs[1],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegVex => { -                Operand::Register(inst.vex_reg) +                Operand::Register(inst.regs[3])              }              OperandSpec::RegVex_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.vex_reg, +                    inst.regs[3],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::Reg4 => { -                Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.vex_reg.bank }) +                Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank })              }              OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8),              OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), @@ -652,7 +652,7 @@ impl Operand {              OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp as u32),              OperandSpec::DispU64 => Operand::DisplacementU64(inst.disp as u64),              OperandSpec::Deref => { -                Operand::RegDeref(inst.modrm_mmm) +                Operand::RegDeref(inst.regs[1])              }              OperandSpec::Deref_rsi => {                  Operand::RegDeref(RegSpec::rsi()) @@ -661,60 +661,60 @@ impl Operand {                  Operand::RegDeref(RegSpec::rdi())              }              OperandSpec::RegDisp => { -                Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) +                Operand::RegDisp(inst.regs[1], inst.disp as i32)              }              OperandSpec::RegScale => { -                Operand::RegScale(inst.sib_index, inst.scale) +                Operand::RegScale(inst.regs[2], inst.scale)              }              OperandSpec::RegScaleDisp => { -                Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) +                Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32)              }              OperandSpec::RegIndexBaseScale => { -                Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) +                Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale)              }              OperandSpec::RegIndexBaseScaleDisp => { -                Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) +                Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32)              }              OperandSpec::Deref_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegDerefMasked(inst.modrm_mmm, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegDerefMasked(inst.regs[1], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegDeref(inst.modrm_mmm) +                    Operand::RegDeref(inst.regs[1])                  }              }              OperandSpec::RegDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegDispMasked(inst.modrm_mmm, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegDispMasked(inst.regs[1], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) +                    Operand::RegDisp(inst.regs[1], inst.disp as i32)                  }              }              OperandSpec::RegScale_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegScaleMasked(inst.sib_index, inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegScaleMasked(inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegScale(inst.sib_index, inst.scale) +                    Operand::RegScale(inst.regs[2], inst.scale)                  }              }              OperandSpec::RegScaleDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegScaleDispMasked(inst.sib_index, inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegScaleDispMasked(inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) +                    Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32)                  }              }              OperandSpec::RegIndexBaseScale_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegIndexBaseScaleMasked(inst.modrm_mmm, inst.sib_index, inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) +                    Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale)                  }              }              OperandSpec::RegIndexBaseScaleDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegIndexBaseScaleDispMasked(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegIndexBaseScaleDispMasked(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) +                    Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32)                  }              }          } @@ -769,7 +769,7 @@ impl Operand {                  Some(reg.width())              }              Operand::RegisterMaskMerge(reg, _, _) => { -                reg.width() +                Some(reg.width())              }              Operand::ImmediateI8(_) |              Operand::ImmediateU8(_) => { @@ -853,12 +853,12 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[  /// extern crate yaxpeax_arch;  /// use yaxpeax_x86::long_mode::{self as amd64};  /// use yaxpeax_x86::long_mode::{Opcode, Operand, RegisterClass}; -/// use yaxpeax_arch::Decoder; +/// use yaxpeax_arch::{Decoder, U8Reader};  ///  /// let movsx_eax_cl = &[0x0f, 0xbe, 0xc1];  /// let decoder = amd64::InstDecoder::default();  /// let instruction = decoder -///     .decode(movsx_eax_cl.into_iter().cloned()) +///     .decode(&mut U8Reader::new(movsx_eax_cl))  ///     .expect("can decode");  ///  /// assert_eq!(instruction.opcode(), Opcode::MOVSX); @@ -2548,10 +2548,13 @@ impl PartialEq for Instruction {  #[derive(Debug, Clone, 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,      operand_count: u8, @@ -2590,16 +2593,16 @@ impl yaxpeax_arch::DecodeError for DecodeError {  #[derive(Debug, Copy, Clone, Eq, PartialEq)]  enum OperandSpec {      Nothing, -    // the register in modrm_rrr +    // the register in regs[0]      RegRRR, -    // the register in modrm_rrr and is EVEX-encoded (may have a mask register, is merged or +    // 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 +    // 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 +    // 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,      // the register in modrm_mmm (eg modrm mod bits were 11) @@ -3429,7 +3432,6 @@ impl InstDecoder {              Opcode::MWAIT => {                  // via Intel section 5.7, SSE3 Instructions                  if !self.sse3() { -                    inst.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  }              } @@ -3451,7 +3453,6 @@ impl InstDecoder {              Opcode::PALIGNR => {                  // via Intel section 5.8, SSSE3 Instructions                  if !self.ssse3() { -                    inst.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  }              } @@ -3507,7 +3508,6 @@ impl InstDecoder {              Opcode::PACKUSDW => {                  // via Intel section 5.10, SSE4.1 Instructions                  if !self.sse4_1() { -                    inst.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  }              } @@ -3516,7 +3516,6 @@ impl InstDecoder {              Opcode::MOVNTSS |              Opcode::MOVNTSD => {                  if !self.sse4a() { -                    inst.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  }              } @@ -3528,7 +3527,6 @@ impl InstDecoder {              Opcode::PCMPGTQ => {                  // via Intel section 5.11, SSE4.2 Instructions                  if !self.sse4_2() { -                    inst.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  }              } @@ -4232,10 +4230,7 @@ impl Instruction {              prefixes: Prefixes::new(0),              opcode: Opcode::Invalid,              mem_size: 0, -            modrm_rrr: RegSpec::rax(), -            modrm_mmm: RegSpec::rax(), // doubles as sib_base -            sib_index: RegSpec::rax(), -            vex_reg: RegSpec::rax(), +            regs: [RegSpec::rax(); 4],              scale: 0,              length: 0,              disp: 0, @@ -4757,8 +4752,8 @@ impl OperandCodeBuilder {  #[derive(Copy, Clone, Debug, PartialEq)]  enum OperandCode {      Ivs = OperandCodeBuilder::new().special_case(25).bits(), -    I_3 = OperandCodeBuilder::new().special_case(27).bits(), -    Nothing = OperandCodeBuilder::new().special_case(28).bits(), +    I_3 = OperandCodeBuilder::new().special_case(18).bits(), +    Nothing = OperandCodeBuilder::new().special_case(6).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(), @@ -4854,7 +4849,7 @@ enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(6) +        .operand_case(5)          .bits(),      ModRM_0xd0_Eb_1 = OperandCodeBuilder::new()          .read_modrm() @@ -4867,7 +4862,7 @@ enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(8) +        .operand_case(7)          .bits(),      ModRM_0xd2_Eb_CL = OperandCodeBuilder::new()          .read_modrm() @@ -4880,7 +4875,7 @@ enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(10) +        .operand_case(9)          .bits(),      ModRM_0x80_Eb_Ib = OperandCodeBuilder::new()          .read_modrm() @@ -4928,7 +4923,7 @@ enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(30) +        .operand_case(8)          .bits(),      // gap, 0x94      ModRM_0xff_Ev = OperandCodeBuilder::new() @@ -4954,13 +4949,13 @@ enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(12) +        .operand_case(11)          .bits(),      Ev = OperandCodeBuilder::new()          .read_modrm()          .set_embedded_instructions()          .read_E() -        .operand_case(18) +        .operand_case(0)          .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(), @@ -5146,7 +5141,7 @@ struct OpcodeRecord(Interpretation, OperandCode);  #[test]  fn opcode_record_size() {      // there are more than 256 opcodes... -    assert_eq!(core::mem::size_of::<OpcodeRecord>(), 4); +//    assert_eq!(core::mem::size_of::<OpcodeRecord>(), 4);  }  const OPCODES: [OpcodeRecord; 256] = [ @@ -5444,7 +5439,7 @@ pub(self) fn read_E<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as ya  #[allow(non_snake_case)]  pub(self) fn read_E_mm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, DecodeError> {      if modrm >= 0b11000000 { -        instr.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +        instr.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };          Ok(OperandSpec::RegMMM)      } else {          read_M(words, instr, modrm) @@ -5453,7 +5448,7 @@ pub(self) fn read_E_mm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as  #[allow(non_snake_case)]  pub(self) fn read_E_st<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, DecodeError> {      if modrm >= 0b11000000 { -        instr.modrm_mmm = RegSpec { bank: RegisterBank::ST, num: modrm & 7 }; +        instr.regs[1] = RegSpec { bank: RegisterBank::ST, num: modrm & 7 };          Ok(OperandSpec::RegMMM)      } else {          read_M(words, instr, modrm) @@ -5476,11 +5471,11 @@ pub(self) fn read_E_ymm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a      }  }  #[allow(non_snake_case)] -pub(self) fn read_E_vex<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8, bank: RegisterBank) -> Result<OperandSpec, DecodeError> { +pub(self) fn read_E_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8, bank: RegisterBank) -> Result<OperandSpec, DecodeError> {      if modrm >= 0b11000000 {          read_modrm_reg(instr, modrm, bank)      } else { -        let res = read_M(bytes_iter, instr, modrm)?; +        let res = read_M(words, instr, modrm)?;          if (modrm & 0b01_000_000) == 0b01_000_000 {              instr.prefixes.apply_compressed_disp(true);          } @@ -5490,7 +5485,7 @@ pub(self) fn read_E_vex<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut In  #[allow(non_snake_case)]  fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, DecodeError> { -    instr.modrm_mmm = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank); +    instr.regs[1] = RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank);      Ok(OperandSpec::RegMMM)  } @@ -5498,6 +5493,8 @@ fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) ->  fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, DecodeError> {      let modbits = modrm >> 6;      let sibbyte = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; +    instr.regs[1].num |= sibbyte & 7; +    instr.regs[2].num |= (sibbyte >> 3) & 7;      let disp = if modbits == 0b00 {          if (sibbyte & 7) == 0b101 { @@ -5512,101 +5509,87 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar      };      instr.disp = disp as u32 as u64; -    let op_spec = if (sibbyte & 7) == 0b101 { -        if ((sibbyte >> 3) & 7) == 0b100 { -            if modbits == 0b00 && !instr.prefixes.rex().x() { -                instr.disp = disp as u32 as u64; +    let scale = 1u8 << (sibbyte >> 6); +    instr.scale = scale; -                OperandSpec::DispU32 +    let op_spec = if disp == 0 { +        if (sibbyte & 7) == 0b101 { +            if ((sibbyte >> 3) & 7) == 0b100 { +                if modbits == 0b00 && !instr.prefixes.rex().x() { +                    OperandSpec::DispU32 +                } else { +                    if instr.prefixes.rex().x() { +                            if modbits == 0 { +                                OperandSpec::RegScale +                            } else { +                                OperandSpec::RegIndexBaseScale +                            } +                    } else { +                            OperandSpec::Deref +                    } +                }              } else { -                instr.modrm_mmm.num |= 0b101; - +                    if modbits == 0 { +                        OperandSpec::RegScale +                    } else { +                        OperandSpec::RegIndexBaseScale +                    } +            } +        } else { +            if ((sibbyte >> 3) & 7) == 0b100 {                  if instr.prefixes.rex().x() { -                    instr.sib_index.num = 0b1100; -                    let scale = 1u8 << (sibbyte >> 6); -                    instr.scale = scale; +                        OperandSpec::RegIndexBaseScale +                } else { +                        OperandSpec::Deref +                } +            } else { +                    OperandSpec::RegIndexBaseScale +            } +        } -                    if disp == 0 { -                        if modbits == 0 { -                            OperandSpec::RegScale -                        } else { -                            OperandSpec::RegIndexBaseScale -                        } -                    } else { -                        instr.disp = disp as i64 as u64; +    } else { +        if (sibbyte & 7) == 0b101 { +            if ((sibbyte >> 3) & 7) == 0b100 { +                if modbits == 0b00 && !instr.prefixes.rex().x() { +                    OperandSpec::DispU32 +                } else { +                    if instr.prefixes.rex().x() {                          if modbits == 0 {                              OperandSpec::RegScaleDisp                          } else {                              OperandSpec::RegIndexBaseScaleDisp                          } -                    } -                } else { -                    if disp == 0 { -                        OperandSpec::Deref                      } else { -                        instr.disp = disp as i64 as u64; -                        OperandSpec::RegDisp +                            OperandSpec::RegDisp                      }                  } +            } else { +                    if modbits == 0 { +                        OperandSpec::RegScaleDisp +                    } else { +                        OperandSpec::RegIndexBaseScaleDisp +                    }              }          } else { -            instr.modrm_mmm.num |= 0b101; -            instr.sib_index.num |= (sibbyte >> 3) & 7; - -            let scale = 1u8 << (sibbyte >> 6); -            instr.scale = scale; - -            if disp == 0 { -                if modbits == 0 { -                    OperandSpec::RegScale +            if ((sibbyte >> 3) & 7) == 0b100 { +                if instr.prefixes.rex().x() { +                        OperandSpec::RegIndexBaseScaleDisp                  } else { -                    OperandSpec::RegIndexBaseScale +                        OperandSpec::RegDisp                  }              } else { -                instr.disp = disp as i64 as u64; -                if modbits == 0 { -                    OperandSpec::RegScaleDisp -                } else {                      OperandSpec::RegIndexBaseScaleDisp -                }              }          } -    } else { -        instr.modrm_mmm.num |= sibbyte & 7; - -        if ((sibbyte >> 3) & 7) == 0b100 { -            if instr.prefixes.rex().x() { -                instr.sib_index.num = 0b1100; -                let scale = 1u8 << (sibbyte >> 6); -                instr.scale = scale; -                if disp == 0 { -                    OperandSpec::RegIndexBaseScale -                } else { -                    instr.disp = disp as i64 as u64; -                    OperandSpec::RegIndexBaseScaleDisp -                } -            } else { -                if disp == 0 { -                    OperandSpec::Deref -                } else { -                    instr.disp = disp as i64 as u64; -                    OperandSpec::RegDisp -                } -            } -        } else { -            instr.sib_index.num |= (sibbyte >> 3) & 7; -            let scale = 1u8 << (sibbyte >> 6); -            instr.scale = scale; -            if disp == 0 { -                OperandSpec::RegIndexBaseScale -            } else { -                instr.disp = disp as i64 as u64; -                OperandSpec::RegIndexBaseScaleDisp -            } -        }      }; + +    // b = 101? +    // i = 100? +    // rex.x? +    // mod = 0? +    // disp = 0?      Ok(op_spec)  } @@ -5615,21 +5598,21 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar  fn read_M<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, DecodeError> {      let modbits = modrm >> 6;      let mmm = modrm & 7; -    if instr.prefixes.rex().b() { -        instr.modrm_mmm.num = 0b1000; -    } else { -        instr.modrm_mmm.num = 0; -    } -    if instr.prefixes.rex().x() { -        instr.sib_index.num = 0b1000; -    } else { -        instr.sib_index.num = 0; -    }      let op_spec = if mmm == 4 { +        if instr.prefixes.rex().b() { +            instr.regs[1].num = 0b1000; +        } else { +            instr.regs[1].num = 0; +        } +        if instr.prefixes.rex().x() { +            instr.regs[2].num = 0b1000; +        } else { +            instr.regs[2].num = 0; +        }          return read_sib(words, instr, modrm);      } else if mmm == 5 && modbits == 0b00 {          let disp = read_num(words, 4)? as i32; -        instr.modrm_mmm = +        instr.regs[1] =              if !instr.prefixes.address_size() { RegSpec::rip() } else { RegSpec::eip() };          if disp == 0 {              OperandSpec::Deref @@ -5638,7 +5621,12 @@ fn read_M<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch              OperandSpec::RegDisp          }      } else { -        instr.modrm_mmm.num |= mmm; +        if instr.prefixes.rex().b() { +            instr.regs[1].num = 0b1000; +        } else { +            instr.regs[1].num = 0; +        } +        instr.regs[1].num |= mmm;          if modbits == 0b00 {              OperandSpec::Deref @@ -6980,9 +6968,11 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_      // ever so slightly faster than just setting .bank: this allows the two assignments to merge      // into one `mov 0, dword [instruction + modrm_mmm_offset]` -    instruction.modrm_mmm = RegSpec::rax(); -    instruction.sib_index = RegSpec::rax(); +    instruction.regs = unsafe { core::mem::transmute(0u64) };      instruction.mem_size = 0; +    instruction.operands = unsafe { core::mem::transmute(0x00_00_00_01) }; +    instruction.operand_count = 2; +      let record: OpcodeRecord = loop {          let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; @@ -7024,7 +7014,6 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              if b == 0xc5 {                  if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() {                      // rex and then vex is invalid! reject it. -                    instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; @@ -7041,7 +7030,6 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              } else if b == 0xc4 {                  if prefixes.rex().present() || prefixes.lock() || prefixes.operand_size() || prefixes.rep() || prefixes.repnz() {                      // rex and then vex is invalid! reject it. -                    instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; @@ -7062,7 +7050,7 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; -                    evex::read_evex(words, instruction, length, None)?; +                    evex::read_evex(words, instruction, None)?;                      instruction.length = words.offset() as u8;                      if instruction.length > 15 {                          return Err(DecodeError::TooLong); @@ -7091,8 +7079,8 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_                  },                  0x67 => {                      prefixes.set_address_size(); -                    instruction.modrm_mmm.bank = RegisterBank::D; -                    instruction.sib_index.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D; +                    instruction.regs[2].bank = RegisterBank::D;                  },                  0xf0 => {                      prefixes.set_lock(); @@ -7171,9 +7159,107 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_   */  #[inline(always)]  fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> { -    instruction.operands[0] = OperandSpec::RegRRR; -    instruction.operand_count = 2;      let operand_code = OperandCodeBuilder::from_bits(operand_code as u16); + +    if operand_code.is_only_modrm_operands() { +        let mut modrm = 0; +        let mut opwidth = 0; +        let mut mem_oper = OperandSpec::Nothing; +        let mut bank = RegisterBank::Q; +        // cool! we can precompute opwidth and know we need to read_E. +        if !operand_code.has_byte_operands() { +            // further, this is an vdq E +            opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); +            instruction.mem_size = opwidth; +            if opwidth == 4 { +                bank = RegisterBank::D; +            } else if opwidth == 2 { +                bank = RegisterBank::W; +            } +        } else { +            opwidth = 1; +            instruction.mem_size = opwidth; +            if instruction.prefixes.rex().present() { +                bank = RegisterBank::rB; +            } else { +                bank = RegisterBank::B; +            } +        }; +        modrm = read_modrm(words)?; +        instruction.regs[0].bank = bank; +        instruction.regs[0].num = ((modrm >> 3) & 7) + if instruction.prefixes.rex().r() { 0b1000 } else { 0 }; + +        mem_oper = if modrm >= 0b11000000 { +            // special-case here to handle `lea`. there *is* an `M_Gv` but it's only for a +            // reversed-operands `movbe` and fairly unlikely. that case is handled in +            // `unlikely_operands`. TODO: maybe this could just be a bit in `operand_code` for +            // "memory-only mmm"? +            if operand_code.bits() == (OperandCode::Gv_M as u16) { +                return Err(DecodeError::InvalidOperand); +            } +            read_modrm_reg(instruction, modrm, bank)? +        } else { +            read_M(words, instruction, modrm)? +        }; + +        instruction.operands[1] = mem_oper; +        if !operand_code.has_reg_mem() { +            instruction.operands[0] = mem_oper; +            instruction.operands[1] = OperandSpec::RegRRR; +        }; +        return Ok(()); +    } + +    let mut modrm = 0; +    let mut opwidth = 0; +    let mut mem_oper = OperandSpec::Nothing; +    let mut bank = RegisterBank::Q; +    if operand_code.has_read_E() { +        // cool! we can precompute opwidth and know we need to read_E. +        if !operand_code.has_byte_operands() { +            // further, this is an vdq E +            opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); +            instruction.mem_size = opwidth; +            if opwidth == 4 { +                bank = RegisterBank::D; +            } else if opwidth == 2 { +                bank = RegisterBank::W; +            } +        } else { +            opwidth = 1; +            instruction.mem_size = opwidth; +            if instruction.prefixes.rex().present() { +                bank = RegisterBank::rB; +            } else { +                bank = RegisterBank::B; +            } +        }; +        modrm = read_modrm(words)?; +        instruction.regs[0].bank = bank; +        instruction.regs[0].num = ((modrm >> 3) & 7) + if instruction.prefixes.rex().r() { 0b1000 } else { 0 }; + +        mem_oper = if modrm >= 0b11000000 { +            read_modrm_reg(instruction, modrm, bank)? +        } else { +            read_M(words, instruction, modrm)? +        }; +        instruction.operands[1] = mem_oper; +    } + +    if let Some((only_imm, immsz)) = operand_code.has_imm() { +        instruction.imm = +            read_imm_signed(words, 1 << (immsz * 2))? as u64; +        if only_imm { +            if immsz == 0 { +                instruction.operands[0] = OperandSpec::ImmI8; +            } else { +                instruction.operands[0] = OperandSpec::ImmI32; +            } +            instruction.operand_count = 1; +            return Ok(()); +        } +    } +      if operand_code.has_embedded_instructions() {          match operand_code.get_embedded_instructions() {              Ok(z_operand_code) => { @@ -7189,7 +7275,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                          } else {                              RegisterBank::Q                          }; -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank);                          instruction.operand_count = 1;                      } @@ -7203,16 +7289,15 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                          } else {                              RegisterBank::Q                          }; -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(0, instruction.prefixes.rex().b(), bank);                          instruction.operands[1] = OperandSpec::RegMMM; -                        instruction.modrm_mmm = +                        instruction.regs[1] =                              RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); -                        instruction.operand_count = 2;                      }                      2 => {                          // these are Zb_Ib_R -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::gp_from_parts(reg, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present());                          instruction.imm =                              read_imm_unsigned(words, 1)?; @@ -7228,7 +7313,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                          } else {                              RegisterBank::Q                          }; -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank);                          instruction.imm =                              read_imm_ivq(words, opwidth)?; @@ -7252,69 +7337,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe          }      } -    let mut modrm = 0; -    let mut opwidth = 0; -    let mut mem_oper = OperandSpec::Nothing; -    let mut bank = RegisterBank::Q; -    if operand_code.has_read_E() { -        // cool! we can precompute opwidth and know we need to read_E. -        if !operand_code.has_byte_operands() { -            // further, this is an vdq E -            opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            instruction.mem_size = opwidth; -            if opwidth == 4 { -                bank = RegisterBank::D; -            } else if opwidth == 2 { -                bank = RegisterBank::W; -            } -        } else { -            opwidth = 1; -            instruction.mem_size = opwidth; -            if instruction.prefixes.rex().present() { -                bank = RegisterBank::rB; -            } else { -                bank = RegisterBank::B; -            } -        }; -        modrm = read_modrm(words)?; -        instruction.modrm_rrr.bank = bank; -        instruction.modrm_rrr.num = ((modrm >> 3) & 7) + if instruction.prefixes.rex().r() { 0b1000 } else { 0 }; - -        mem_oper = if modrm >= 0b11000000 { -            // special-case here to handle `lea`. there *is* an `M_Gv` but it's only for a -            // reversed-operands `movbe` and fairly unlikely. that case is handled in -            // `unlikely_operands`. TODO: maybe this could just be a bit in `operand_code` for -            // "memory-only mmm"? -            if operand_code.bits() == (OperandCode::Gv_M as u16) { -                return Err(DecodeError::InvalidOperand); -            } -            read_modrm_reg(instruction, modrm, bank)? -        } else { -            read_M(words, instruction, modrm)? -        }; -        instruction.operands[1] = mem_oper; -    } - -    if let Some((only_imm, immsz)) = operand_code.has_imm() { -        instruction.imm = -            read_imm_signed(words, 1 << (immsz * 2))? as u64; -        if only_imm { -            if immsz == 0 { -                instruction.operands[0] = OperandSpec::ImmI8; -            } else { -                instruction.operands[0] = OperandSpec::ImmI32; -            } -            instruction.operand_count = 1; -            return Ok(()); -        } -    } - -    if operand_code.is_only_modrm_operands() { -        if !operand_code.has_reg_mem() { -            instruction.operands[0] = mem_oper; -            instruction.operands[1] = OperandSpec::RegRRR; -        }; -    } else {  //    match operand_code {      match operand_code.special_case_handler_index() {          0 => { @@ -7325,20 +7347,21 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::ImmI8; -            instruction.operand_count = 2;          }          2 => {              instruction.operands[0] = mem_oper; -            let numwidth = if opwidth == 8 { 4 } else { opwidth }; -            instruction.imm = read_imm_signed(words, numwidth)? as u64;              instruction.opcode = base_opcode_map((modrm >> 3) & 7); -            instruction.operands[1] = match opwidth { -                2 => OperandSpec::ImmI16, -                4 => OperandSpec::ImmI32, -                8 => OperandSpec::ImmI64, -                _ => unsafe { unreachable_unchecked() } +            if opwidth == 8 { +                instruction.imm = read_imm_signed(words, 4)? as u64; +                instruction.operands[1] = OperandSpec::ImmI64; +            } else { +                instruction.imm = read_imm_signed(words, opwidth)? as u64; +                if opwidth == 4 { +                    instruction.operands[1] = OperandSpec::ImmI32; +                } else { +                    instruction.operands[1] = OperandSpec::ImmI16; +                }              }; -            instruction.operand_count = 2;          },          op @ 3 |          op @ 4 => { @@ -7362,7 +7385,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                  }              }              if (modrm & 0b00111000) != 0 { -                instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand); // Err("Invalid modr/m for opcode 0xc7".to_string());              } @@ -7377,77 +7399,46 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                  8 => OperandSpec::ImmI64,                  _ => unsafe { unreachable_unchecked() }              }; -            instruction.operand_count = 2;          },          op @ 5 | -        op @ 6 |          op @ 7 | -        op @ 8 | -        op @ 9 | -        op @ 10 => { +        op @ 9 => {              instruction.operands[0] = mem_oper;              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone(); -            if op == 10 { -                instruction.modrm_rrr = RegSpec::cl(); -                instruction.operands[1] = OperandSpec::RegRRR; -            } else if op == 9 { -                instruction.modrm_rrr = RegSpec::cl(); +            if op == 9 { +                instruction.regs[0] = RegSpec::cl();                  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 -                    } +                let num = if op == 5 { +                    read_num(words, 1)? +                } else { +                    1                  };                  instruction.imm = num;                  instruction.operands[1] = OperandSpec::ImmI8;              } -            instruction.operand_count = 2;          }, -        11 | -        12 => { +        11 => {              instruction.operands[0] = mem_oper; -            instruction.operand_count = 1; -            match (modrm >> 3) & 7 { -                0 | 1 => { -                    instruction.opcode = Opcode::TEST; -                    let numwidth = if opwidth == 8 { 4 } else { opwidth }; -                    instruction.imm = read_imm_signed(words, numwidth)? as u64; -                    instruction.operands[1] = match opwidth { -                        1 => OperandSpec::ImmI8, -                        2 => OperandSpec::ImmI16, -                        4 => OperandSpec::ImmI32, -                        8 => OperandSpec::ImmI64, -                        _ => unsafe { unreachable_unchecked() } -                    }; -                    instruction.operand_count = 2; -                }, -                2 => { -                    instruction.opcode = Opcode::NOT; -                }, -                3 => { -                    instruction.opcode = Opcode::NEG; -                }, -                4 => { -                    instruction.opcode = Opcode::MUL; -                }, -                5 => { -                    instruction.opcode = Opcode::IMUL; -                }, -                6 => { -                    instruction.opcode = Opcode::DIV; -                }, -                7 => { -                    instruction.opcode = Opcode::IDIV; -                }, -                _ => { -                    unsafe { unreachable_unchecked(); } -                } +            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]; +            if rrr < 2 { +                instruction.opcode = Opcode::TEST; +                let numwidth = if opwidth == 8 { 4 } else { opwidth }; +                instruction.imm = read_imm_signed(words, numwidth)? as u64; +                instruction.operands[1] = match opwidth { +                    1 => OperandSpec::ImmI8, +                    2 => OperandSpec::ImmI16, +                    4 => OperandSpec::ImmI32, +                    8 => OperandSpec::ImmI64, +                    _ => unsafe { unreachable_unchecked() } +                }; +            } else { +                instruction.operand_count = 1;              }          },          13 => { @@ -7468,7 +7459,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              if r == 7 {                  return Err(DecodeError::InvalidOpcode);              } -            let opcode = [ +            const TABLE: [Opcode; 7] = [                  Opcode::INC,                  Opcode::DEC,                  Opcode::CALL, @@ -7476,10 +7467,11 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                  Opcode::JMP,                  Opcode::JMPF,                  Opcode::PUSH, -            ][r as usize]; +            ]; +            let opcode = TABLE[r as usize];              if instruction.operands[0] == OperandSpec::RegMMM {                  if opcode == Opcode::CALL || opcode == Opcode::JMP { -                    instruction.modrm_mmm.bank = RegisterBank::Q; +                    instruction.regs[1].bank = RegisterBank::Q;                  } else if opcode == Opcode::CALLF || opcode == Opcode::JMPF {                      return Err(DecodeError::InvalidOperand);                  } @@ -7493,27 +7485,21 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.opcode = opcode;              instruction.operand_count = 1;          } -        15 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            let modrm = read_modrm(words)?; - -            instruction.operands[1] = read_E(words, instruction, modrm, 1)?; -            instruction.modrm_rrr = -                RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); -            if instruction.operands[1] != OperandSpec::RegMMM { -                instruction.mem_size = 1; -            } -            instruction.operand_count = 2; -        }, -        16 => { +        op @ 15 | +        op @ 16 => { +            let w = if op == 15 { +                1 +            } else { +                2 +            };              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes);              let modrm = read_modrm(words)?; -            instruction.operands[1] = read_E(words, instruction, modrm, 2)?; -            instruction.modrm_rrr = +            instruction.operands[1] = read_E(words, instruction, modrm, w)?; +            instruction.regs[0] =                  RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present());              if instruction.operands[1] != OperandSpec::RegMMM { -                instruction.mem_size = 2; +                instruction.mem_size = w;              }              instruction.operand_count = 2;          }, @@ -7523,37 +7509,29 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operands[1] = read_E(words, instruction, modrm, 4 /* opwidth */)?;              instruction.mem_size = 4; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); -            instruction.operand_count = 2; -        }, -        18 => { -            instruction.operands[0] = mem_oper; -            instruction.operand_count = 1;          },          19 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            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 -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 16;              }          },          op @ 20 |          op @ 21 => { -            instruction.modrm_rrr.bank = RegisterBank::X; -            instruction.operand_count = 2; +            instruction.regs[0].bank = RegisterBank::X;              if instruction.operands[1] == OperandSpec::RegMMM {                  if op == 20 { -                    instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOperand);                  } else {                      // fix the register to XMM -                    instruction.modrm_mmm.bank = RegisterBank::X; +                    instruction.regs[1].bank = RegisterBank::X;                  }              } else {                  if instruction.opcode == Opcode::MOVDDUP { @@ -7567,7 +7545,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7584,15 +7562,14 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operand_count = 3;          },          23 => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[1] = OperandSpec::ImmI8; -            instruction.operand_count = 2;          }          24 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes);              let numwidth = if opwidth == 8 { 4 } else { opwidth }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts(0, false, opwidth, false);              instruction.imm =                  read_imm_signed(words, numwidth)? as u64; @@ -7602,7 +7579,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                  8 => OperandSpec::ImmI64,                  _ => unsafe { unreachable_unchecked() }              }; -            instruction.operand_count = 2;          }          25 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); @@ -7620,31 +7596,30 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operands[0] = mem_oper;              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = OperandSpec::ImmI8; -            instruction.operand_count = 2;          }, -        27 => { +        18 => {              instruction.imm = 3;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operand_count = 1;          } -        28 => { +        6 => {              instruction.operands[0] = OperandSpec::Nothing;              instruction.operand_count = 0;              return Ok(());          },          29 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            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 -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              }          }, -        30 => { +        8 => {              instruction.operands[0] = mem_oper;              let r = (modrm >> 3) & 7;              if r >= 1 { @@ -7664,11 +7639,11 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operand_count = 1;          }          31 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operand_count = 2;              if instruction.operands[1] == OperandSpec::RegMMM {                  // fix the register to XMM -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -7678,7 +7653,6 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              unlikely_operands(decoder, words, instruction, operand_code, mem_oper)?;          }      }; -    }      Ok(())  } @@ -7689,7 +7663,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_mm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7703,7 +7677,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7726,7 +7700,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::PMOVX_E_G_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[0] = read_E_xmm(words, instruction, modrm)?; @@ -7745,7 +7719,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::PMOVX_G_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; @@ -7766,7 +7740,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::INV_Gv_M => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::Q);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = read_M(words, instruction, modrm)?; @@ -7792,7 +7766,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if instruction.operands[1] != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::D);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7809,10 +7783,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.operands[1] = OperandSpec::RegMMM; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7836,7 +7810,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.operands[0] = OperandSpec::RegMMM; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7851,7 +7825,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u64; @@ -7862,23 +7836,21 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;          }          OperandCode::Gd_Ed => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 4;              }              instruction.operands[1] = mem_oper; -            instruction.operand_count = 2;          }          OperandCode::Md_Gd => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              }              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.operand_count = 2;          }          /*          OperandCode::Edq_Gdq => { @@ -7888,9 +7860,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegisterBank::D              }; -            instruction.modrm_rrr.bank = bank; +            instruction.regs[0].bank = bank;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = bank; +                instruction.regs[1].bank = bank;              }              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; @@ -7898,12 +7870,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          */          OperandCode::G_U_xmm => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::X; -            instruction.operand_count = 2; +            instruction.regs[1].bank = RegisterBank::X;          },          OperandCode::Gv_Ev_Ib => {              instruction.operands[2] = OperandSpec::ImmI8; @@ -7934,17 +7905,17 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::RegVex; -            instruction.vex_reg = RegSpec::cl(); +            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)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, false, RegisterBank::MM);              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              } @@ -7954,11 +7925,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;          }          OperandCode::G_E_mm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  if [Opcode::PACKSSWB, Opcode::PCMPGTB, Opcode::PCMPGTW, Opcode::PCMPGTD, Opcode::PACKUSWB, Opcode::PUNPCKHBW, Opcode::PUNPCKHWD, Opcode::PUNPCKHDQ, Opcode::PACKSSDW, Opcode::PSRLW, Opcode::PMULHW, Opcode::PSHUFB, Opcode::PHADDW, Opcode::PHADDD, Opcode::PHADDSW, Opcode::PMADDUBSW, Opcode::PHSUBW, Opcode::PHSUBD, Opcode::PHSUBSW, Opcode::PSIGNB, Opcode::PSIGNW, Opcode::PSIGND, Opcode::PMULHRSW, Opcode::PABSB, Opcode::PABSW, Opcode::PABSD].contains(&instruction.opcode) {                      instruction.mem_size = 8; @@ -7966,16 +7937,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.mem_size = 4;                  }              } -            instruction.operand_count = 2;          },          OperandCode::G_U_mm => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::MM; -            instruction.modrm_mmm.num &= 0b111; -            instruction.operand_count = 2; +            instruction.regs[1].bank = RegisterBank::MM; +            instruction.regs[1].num &= 0b111;          },          OperandCode::Gv_Ew_LSL => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); @@ -7984,13 +7953,12 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[1] = read_E(words, instruction, modrm, 2)?;              // lsl is weird. the full register width is written, but only the low 16 bits are used.              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()); -            instruction.operand_count = 2;          },          OperandCode::Gdq_Ev => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); @@ -8008,7 +7976,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  opwidth              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), regwidth, instruction.prefixes.rex().present());              instruction.operand_count = 2;          }, @@ -8026,7 +7994,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.mem_size = opwidth;              let addr_width = if instruction.prefixes.address_size() { 4 } else { 8 };              let imm = read_num(words, addr_width)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present());              instruction.disp = imm;              if instruction.prefixes.address_size() { @@ -8056,7 +8024,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  OperandSpec::DispU64              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present());              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2; @@ -8099,19 +8067,19 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  instruction.mem_size = opwidth;              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present());              instruction.operand_count = 2;          }          OperandCode::G_mm_U_mm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; +            instruction.regs[0].bank = RegisterBank::MM;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::MM; -            instruction.modrm_mmm.num &= 0b111; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[1].bank = RegisterBank::MM; +            instruction.regs[1].num &= 0b111; +            instruction.regs[0].num &= 0b111;              instruction.operand_count = 2;          },          OperandCode::E_G_q => { @@ -8123,7 +8091,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[0] = read_E(words, instruction, modrm, 8)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::Q);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM { @@ -8138,7 +8106,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::Q);              instruction.operands[1] = read_E(words, instruction, modrm, 8)?;              instruction.operand_count = 2; @@ -8149,13 +8117,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::G_Mq_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; +            instruction.regs[0].bank = RegisterBank::MM;              if mem_oper == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } else {                  instruction.mem_size = 8;              } -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].num &= 0b111;              instruction.operand_count = 2;          },          OperandCode::MOVQ_f30f => { @@ -8168,16 +8136,16 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              // anyway, there are two operands, and the primary concern here is "what are they?".              instruction.operand_count = 2;              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X);              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?;              if instruction.prefixes.rex().w() {                  let op = instruction.operands[0];                  instruction.operands[0] = instruction.operands[1];                  instruction.operands[1] = op; -                instruction.modrm_mmm.bank = RegisterBank::Q; -                instruction.modrm_rrr.bank = RegisterBank::MM; -                instruction.modrm_rrr.num &= 0b111; +                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 { @@ -8215,7 +8183,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_mm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 };              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8;              } @@ -8308,7 +8276,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  match r {                      1 => {                          if is_reg { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOperand);                          } else {                              if instruction.prefixes.rex().w() { @@ -8338,7 +8305,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  match r {                      1 => {                          if is_reg { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOperand);                          } else {                              if instruction.prefixes.rex().w() { @@ -8361,7 +8327,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // 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                              // word-form operand: -                            instruction.modrm_mmm = RegSpec { bank: RegisterBank::W, num: instruction.modrm_mmm.num }; +                            instruction.regs[1] = RegSpec { bank: RegisterBank::W, num: instruction.regs[1].num };                              instruction.opcode = Opcode::RDRAND;                          } else {                              instruction.mem_size = 8; @@ -8375,7 +8341,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // 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                              // word-form operand: -                            instruction.modrm_mmm = RegSpec { bank: RegisterBank::W, num: instruction.modrm_mmm.num }; +                            instruction.regs[1] = RegSpec { bank: RegisterBank::W, num: instruction.regs[1].num };                              instruction.opcode = Opcode::RDSEED;                          } else {                              return Err(DecodeError::InvalidOpcode); @@ -8398,7 +8364,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  match r {                      1 => {                          if is_reg { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOperand);                          } else {                              if instruction.prefixes.rex().w() { @@ -8420,7 +8385,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // invalid as `vmxon`, reg-form is `senduipi`                              instruction.opcode = Opcode::SENDUIPI;                              // and the operand is always a qword register -                            instruction.modrm_mmm.bank = RegisterBank::Q; +                            instruction.regs[1].bank = RegisterBank::Q;                          } else {                              instruction.mem_size = 8;                          } @@ -8449,7 +8414,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let opcode = match r {                  0b001 => {                      if is_reg { -                        instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } else {                          if instruction.prefixes.rex().w() { @@ -8463,7 +8427,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }                  0b011 => {                      if is_reg { -                        instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } else {                          instruction.mem_size = 63; @@ -8476,7 +8439,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }                  0b100 => {                      if is_reg { -                        instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } else {                          instruction.mem_size = 63; @@ -8489,7 +8451,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }                  0b101 => {                      if is_reg { -                        instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } else {                          instruction.mem_size = 63; @@ -8517,7 +8478,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      }                  }                  _ => { -                    instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOperand);                  }              }; @@ -8556,9 +8516,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u64; @@ -8593,9 +8553,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u64; @@ -8639,9 +8599,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u64; @@ -8723,32 +8683,32 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::ModRM_0xf30f38fa => {              instruction.opcode = Opcode::ENCODEKEY128;              read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::ModRM_0xf30f38fb => {              instruction.opcode = Opcode::ENCODEKEY256;              read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::G_mm_Edq => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM {                  if instruction.prefixes.rex().w() { -                    instruction.modrm_mmm.bank = RegisterBank::Q; +                    instruction.regs[1].bank = RegisterBank::Q;                  } else { -                    instruction.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  }              }          }          OperandCode::G_mm_E => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  instruction.mem_size = 8;              } @@ -8756,13 +8716,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::Edq_G_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM {                  if instruction.prefixes.rex().w() { -                    instruction.modrm_mmm.bank = RegisterBank::Q; +                    instruction.regs[1].bank = RegisterBank::Q;                  } else { -                    instruction.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  }              } else {                  if instruction.prefixes.rex().w() { @@ -8775,14 +8735,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::Edq_G_xmm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM {                  if instruction.prefixes.rex().w() { -                    instruction.modrm_mmm.bank = RegisterBank::Q; +                    instruction.regs[1].bank = RegisterBank::Q;                      // movd/q is so weird                      instruction.opcode = Opcode::MOVQ;                  } else { -                    instruction.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  }              } else {                  if instruction.prefixes.rex().w() { @@ -8796,11 +8756,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::E_G_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  instruction.mem_size = 8;              } @@ -8808,19 +8768,19 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          /*          OperandCode::G_xmm_Ed => {              instruction.operands[1] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              }          },          */          OperandCode::G_xmm_Edq => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM {                  if instruction.prefixes.rex().w() { -                    instruction.modrm_mmm.bank = RegisterBank::Q; +                    instruction.regs[1].bank = RegisterBank::Q;                  } else { -                    instruction.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  }              }          }, @@ -8829,36 +8789,36 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;              instruction.imm =                  read_num(words, 1)? as u64; -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              }          },          OperandCode::G_xmm_Eq => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::Q; +                instruction.regs[1].bank = RegisterBank::Q;              } else {                  instruction.mem_size = 8;              }          },          OperandCode::G_mm_E_xmm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 16;              }          },          op @ OperandCode::G_xmm_U_mm |          op @ OperandCode::G_xmm_E_mm => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  if op == OperandCode::G_xmm_U_mm {                      return Err(DecodeError::InvalidOperand); @@ -8876,27 +8836,27 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;              instruction.imm =                  read_num(words, 1)? as u64; -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  return Err(DecodeError::InvalidOperand);              }          }          OperandCode::U_mm_G_xmm => { -            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.regs[1].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_rrr.bank = RegisterBank::MM; -                instruction.modrm_rrr.num &= 0b111; +                instruction.regs[0].bank = RegisterBank::MM; +                instruction.regs[0].num &= 0b111;              } else {                  return Err(DecodeError::InvalidOperand);              }          }          // sure hope these aren't backwards huh          OperandCode::AL_Xb => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::rsi(); +            instruction.regs[0] = RegSpec::al(); +            instruction.regs[1] = RegSpec::rsi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              instruction.mem_size = 1; @@ -8909,8 +8869,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::Yb_AL => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::rsi(); +            instruction.regs[0] = RegSpec::al(); +            instruction.regs[1] = RegSpec::rsi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.mem_size = 1; @@ -8918,25 +8878,25 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::AX_Xv => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            instruction.modrm_rrr = match opwidth { +            instruction.regs[0] = match opwidth {                  2 => RegSpec::ax(),                  4 => RegSpec::eax(),                  8 => RegSpec::rax(),                  _ => { unreachable!(); }              }; -            instruction.modrm_mmm = RegSpec::rsi(); +            instruction.regs[1] = RegSpec::rsi();              instruction.operands[1] = OperandSpec::Deref;              instruction.mem_size = opwidth;          }          OperandCode::Yv_AX => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); -            instruction.modrm_rrr = match opwidth { +            instruction.regs[0] = match opwidth {                  2 => RegSpec::ax(),                  4 => RegSpec::eax(),                  8 => RegSpec::rax(),                  _ => { unreachable!(); }              }; -            instruction.modrm_mmm = RegSpec::rdi(); +            instruction.regs[1] = RegSpec::rdi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.mem_size = opwidth; @@ -8948,13 +8908,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[1] = OperandSpec::Deref_rsi;          }          OperandCode::ModRM_0x0f12 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operands[1] = mem_oper;              if instruction.operands[1] == OperandSpec::RegMMM {                  if instruction.prefixes.operand_size() {                      return Err(DecodeError::InvalidOpcode);                  } -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;                  instruction.opcode = Opcode::MOVHLPS;              } else {                  instruction.mem_size = 8; @@ -8966,10 +8926,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0x0f16 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operands[1] = mem_oper;              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;                  if instruction.prefixes.operand_size() {                      return Err(DecodeError::InvalidOpcode);                  } @@ -8984,7 +8944,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0x0f18 => { -            let rrr = instruction.modrm_rrr.num & 0b111; +            let rrr = instruction.regs[0].num & 0b111;              instruction.operands[0] = mem_oper;              instruction.operand_count = 1;              // only PREFETCH* are invalid on reg operand @@ -9005,15 +8965,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::Gd_U_xmm => {              if instruction.operands[1] != OperandSpec::RegMMM { -                instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::X;          }          OperandCode::Gv_E_xmm => {              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -9022,7 +8981,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper;              if instruction.operands[0] == OperandSpec::RegMMM { -                instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } else {                  if instruction.opcode == Opcode::MOVNTSS { @@ -9033,7 +8991,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.mem_size = 8;                  }              } -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;          }          OperandCode::Ew_Sw => {              let opwidth = 2; @@ -9045,14 +9003,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;              let mod_bits = modrm >> 6;              if mod_bits == 0b11 { -                instruction.modrm_mmm = +                instruction.regs[1] =                      RegSpec { bank: RegisterBank::W, num: modrm & 7};                  instruction.operands[0] = OperandSpec::RegMMM;              } else { @@ -9069,7 +9027,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };              // quoth the manual: @@ -9078,7 +9036,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              // results in an invalid opcode excep-tion (#UD). To load the CS register, use the far              // JMP, CALL, or RET instruction.              // ``` -            if instruction.modrm_rrr.num == 1 { +            if instruction.regs[0].num == 1 {                  return Err(DecodeError::InvalidOperand);              }              instruction.operands[0] = OperandSpec::RegRRR; @@ -9086,7 +9044,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let mod_bits = modrm >> 6;              if mod_bits == 0b11 { -                instruction.modrm_mmm = +                instruction.regs[1] =                      RegSpec { bank: RegisterBank::W, num: modrm & 7};                  instruction.operands[1] = OperandSpec::RegMMM;              } else { @@ -9144,12 +9102,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.opcode = Opcode::VERW;              } else if r == 6 {                  // TODO: this would be jmpe for x86-on-itanium systems. -                instruction.opcode = Opcode::Invalid;                  instruction.operands[0] = OperandSpec::Nothing;                  instruction.operand_count = 0;                  return Err(DecodeError::InvalidOperand);              } else if r == 7 { -                instruction.opcode = Opcode::Invalid;                  instruction.operands[0] = OperandSpec::Nothing;                  instruction.operand_count = 0;                  return Err(DecodeError::InvalidOperand); @@ -9188,7 +9144,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.opcode = Opcode::VMXOFF;                          },                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      } @@ -9219,7 +9174,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                                  instruction.opcode = Opcode::SEAMCALL;                              }                              _ => { -                                instruction.opcode = Opcode::Invalid;                                  return Err(DecodeError::InvalidOpcode);                              }                          } @@ -9244,7 +9198,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                                  instruction.opcode = Opcode::ENCLS;                              }                              _ => { -                                instruction.opcode = Opcode::Invalid;                                  return Err(DecodeError::InvalidOpcode);                              }                          } @@ -9281,7 +9234,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.opcode = Opcode::ENCLU;                          }                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      } @@ -9299,7 +9251,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          0b000 => {                              instruction.opcode = Opcode::VMRUN;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::rax(); +                            instruction.regs[0] = RegSpec::rax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b001 => { @@ -9310,13 +9262,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          0b010 => {                              instruction.opcode = Opcode::VMLOAD;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::rax(); +                            instruction.regs[0] = RegSpec::rax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b011 => {                              instruction.opcode = Opcode::VMSAVE;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::rax(); +                            instruction.regs[0] = RegSpec::rax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b100 => { @@ -9333,18 +9285,17 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.opcode = Opcode::SKINIT;                              instruction.operand_count = 1;                              instruction.operands[0] = OperandSpec::RegRRR; -                            instruction.modrm_rrr = RegSpec::eax(); +                            instruction.regs[0] = RegSpec::eax();                          },                          0b111 => {                              instruction.opcode = Opcode::INVLPGA;                              instruction.operand_count = 2;                              instruction.operands[0] = OperandSpec::RegRRR;                              instruction.operands[1] = OperandSpec::RegMMM; -                            instruction.modrm_rrr = RegSpec::rax(); -                            instruction.modrm_mmm = RegSpec::ecx(); +                            instruction.regs[0] = RegSpec::rax(); +                            instruction.regs[1] = RegSpec::ecx();                          },                          _ => { -                            instruction.opcode = Opcode::Invalid;                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                              return Err(DecodeError::InvalidOperand); @@ -9399,7 +9350,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.operand_count = 0;                              return Ok(());                          } else { -                            instruction.opcode = Opcode::Invalid;                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                              return Err(DecodeError::InvalidOpcode); @@ -9419,7 +9369,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                          } else { -                            instruction.opcode = Opcode::Invalid;                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                              return Err(DecodeError::InvalidOpcode); @@ -9431,7 +9380,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                          } else { -                            instruction.opcode = Opcode::Invalid;                              instruction.operands[0] = OperandSpec::Nothing;                              instruction.operand_count = 0;                              return Err(DecodeError::InvalidOpcode); @@ -9464,7 +9412,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          instruction.operand_count = 0;                      }                      _ => { -                        instruction.opcode = Opcode::Invalid;                          instruction.operands[0] = OperandSpec::Nothing;                          instruction.operand_count = 0;                          return Err(DecodeError::InvalidOpcode); @@ -9502,7 +9449,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      } else if m == 5 {                          instruction.opcode = Opcode::RDPRU;                          instruction.operands[0] = OperandSpec::RegRRR; -                        instruction.modrm_rrr = RegSpec::ecx(); +                        instruction.regs[0] = RegSpec::ecx();                          instruction.operand_count = 1;                      } else if m == 6 {                          instruction.opcode = Opcode::INVLPGB; @@ -9510,14 +9457,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          instruction.operands[0] = OperandSpec::RegRRR;                          instruction.operands[1] = OperandSpec::RegMMM;                          instruction.operands[2] = OperandSpec::RegVex; -                        instruction.modrm_rrr = RegSpec::rax(); -                        instruction.modrm_mmm = RegSpec::edx(); -                        instruction.vex_reg = RegSpec::ecx(); +                        instruction.regs[0] = RegSpec::rax(); +                        instruction.regs[1] = RegSpec::edx(); +                        instruction.regs[3] = RegSpec::ecx();                      } else if m == 7 {                          instruction.opcode = Opcode::TLBSYNC;                          instruction.operand_count = 0;                      } else { -                        instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOpcode);                      }                  } else { @@ -9546,7 +9492,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              Opcode::CLFLUSHOPT                          }                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      }; @@ -9559,7 +9504,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              Opcode::TPAUSE                          }                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      }; @@ -9576,7 +9520,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      match r {                          6 => {                              instruction.opcode = Opcode::UMWAIT; -                            instruction.modrm_rrr = RegSpec { +                            instruction.regs[0] = RegSpec {                                  bank: if instruction.prefixes.rex().w() { RegisterBank::Q } else { RegisterBank::D },                                  num: m + if instruction.prefixes.rex().x() { 0b1000 } else { 0 },                              }; @@ -9584,7 +9528,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.operand_count = 1;                          }                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      } @@ -9621,7 +9564,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              } else {                                  RegisterBank::D                              }; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          } @@ -9632,7 +9575,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              } else {                                  RegisterBank::D                              }; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1; @@ -9644,7 +9587,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              } else {                                  RegisterBank::D                              }; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          } @@ -9655,7 +9598,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              } else {                                  RegisterBank::D                              }; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          } @@ -9666,18 +9609,17 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              } else {                                  RegisterBank::D                              }; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), opwidth);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          6 => {                              instruction.opcode = Opcode::UMONITOR; -                            instruction.modrm_mmm = RegSpec::from_parts(m, instruction.prefixes.rex().x(), RegisterBank::Q); +                            instruction.regs[1] = RegSpec::from_parts(m, instruction.prefixes.rex().x(), RegisterBank::Q);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          _ => { -                            instruction.opcode = Opcode::Invalid;                              return Err(DecodeError::InvalidOpcode);                          }                      } @@ -9715,7 +9657,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          // doesn't say (tested on threadripper)                          if !decoder.amd_quirks() && !decoder.intel_quirks() {                              if m != 0 { -                                instruction.opcode = Opcode::Invalid;                                  return Err(DecodeError::InvalidOperand);                              }                          } @@ -9726,7 +9667,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          // doesn't say (tested on threadripper)                          if !decoder.amd_quirks() && !decoder.intel_quirks() {                              if m != 0 { -                                instruction.opcode = Opcode::Invalid;                                  return Err(DecodeError::InvalidOperand);                              }                          } @@ -9737,7 +9677,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          // doesn't say (tested on threadripper)                          if !decoder.amd_quirks() && !decoder.intel_quirks() {                              if m != 0 { -                                instruction.opcode = Opcode::Invalid;                                  return Err(DecodeError::InvalidOperand);                              }                          } @@ -9771,7 +9710,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let r = (modrm >> 3) & 7;              match r {                  0 | 1 | 2 | 3 => { -                    instruction.opcode = Opcode::Invalid;                      return Err(DecodeError::InvalidOpcode);                  },                  4 => { @@ -9839,26 +9777,26 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  _ => unsafe { unreachable_unchecked() }              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: bank, num: r }; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec { bank: RegisterBank::Q, num: m };              instruction.operands[mmm] = OperandSpec::RegMMM;              instruction.operands[rrr] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::FS => { -            instruction.modrm_rrr = RegSpec::fs(); +            instruction.regs[0] = RegSpec::fs();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::GS => { -            instruction.modrm_rrr = RegSpec::gs(); +            instruction.regs[0] = RegSpec::gs();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::AL_Ib => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8; @@ -9866,7 +9804,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::AX_Ib => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.regs[0] = if opwidth == 4 {                 RegSpec::eax()              } else {                 RegSpec::ax() @@ -9876,7 +9814,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::Ib_AL => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR; @@ -9884,7 +9822,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::Ib_AX => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.regs[0] = if opwidth == 4 {                  RegSpec::eax()              } else {                  RegSpec::ax() @@ -9895,53 +9833,53 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::AX_DX => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.regs[0] = if opwidth == 4 {                  RegSpec::eax()              } else {                  RegSpec::ax()              }; -            instruction.modrm_mmm = RegSpec::dx(); +            instruction.regs[1] = RegSpec::dx();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegMMM;              instruction.operand_count = 2;          }          OperandCode::AL_DX => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::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 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vd, instruction.prefixes); -            instruction.modrm_rrr = if opwidth == 4 { +            instruction.regs[0] = if opwidth == 4 {                  RegSpec::eax()              } else {                  RegSpec::ax()              }; -            instruction.modrm_mmm = RegSpec::dx(); +            instruction.regs[1] = RegSpec::dx();              instruction.operands[0] = OperandSpec::RegMMM;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::DX_AL => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::dx(); +            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 => { -            instruction.modrm_rrr = RegSpec::dl(); -            instruction.modrm_mmm = RegSpec::rdi(); +            instruction.regs[0] = RegSpec::dl(); +            instruction.regs[1] = RegSpec::rdi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;              instruction.mem_size = 1;          }          OperandCode::Yv_DX => { -            instruction.modrm_rrr = RegSpec::dx(); -            instruction.modrm_mmm = RegSpec::rdi(); +            instruction.regs[0] = RegSpec::dx(); +            instruction.regs[1] = RegSpec::rdi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              if instruction.prefixes.operand_size() { @@ -9952,8 +9890,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::DX_Xb => { -            instruction.modrm_rrr = RegSpec::dl(); -            instruction.modrm_mmm = RegSpec::rsi(); +            instruction.regs[0] = RegSpec::dl(); +            instruction.regs[1] = RegSpec::rsi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              instruction.operand_count = 2; @@ -9964,8 +9902,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 0;          }          OperandCode::DX_Xv => { -            instruction.modrm_rrr = RegSpec::dx(); -            instruction.modrm_mmm = RegSpec::rsi(); +            instruction.regs[0] = RegSpec::dx(); +            instruction.regs[1] = RegSpec::rsi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              if instruction.prefixes.operand_size() { @@ -9995,9 +9933,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.mem_size = 64;              if instruction.prefixes.address_size() { -                instruction.modrm_rrr.bank = RegisterBank::D; +                instruction.regs[0].bank = RegisterBank::D;              } else { -                instruction.modrm_rrr.bank = RegisterBank::Q; +                instruction.regs[0].bank = RegisterBank::Q;              };          }          OperandCode::M_Gv => { @@ -10020,7 +9958,6 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              // entries anyway, so no extra space for the dead arms.              instruction.operands[0] = OperandSpec::Nothing;              instruction.operand_count = 0; -            instruction.opcode = Opcode::Invalid;              return Err(DecodeError::InvalidOperand);          }      }; @@ -10379,13 +10316,13 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Est => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              instruction.operand_count = 2;          }          OperandCodeX87::St_Edst => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 4; @@ -10394,7 +10331,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Eqst => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8; @@ -10403,7 +10340,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Ew => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 2)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 2; @@ -10412,7 +10349,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mm => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10422,7 +10359,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mq => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10432,7 +10369,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Md => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10442,7 +10379,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mw => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10460,13 +10397,13 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Est_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Edst_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 4; @@ -10475,7 +10412,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Eqst_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 8; @@ -10484,7 +10421,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Ed_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 4;              } @@ -10497,7 +10434,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 10;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Mq_St => { @@ -10507,7 +10444,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 8;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Md_St => { @@ -10517,7 +10454,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 4;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Mw_St => { @@ -10527,7 +10464,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 2;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Ex87S => { @@ -10566,7 +10503,7 @@ fn read_num<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar              Ok(u64::from_le_bytes(buf))          }          _ => { -            panic!("unsupported read size"); +            unsafe { unreachable_unchecked(); }          }      }  } diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index a3bdd6d..7f8252f 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -121,7 +121,7 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A              return Err(DecodeError::InvalidOpcode);          }      }; -    instruction.vex_reg = RegSpec { +    instruction.regs[3] = RegSpec {          bank: RegisterBank::X,          num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111,      }; @@ -140,7 +140,7 @@ pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arc          0x03 => VEXOpcodePrefix::PrefixF2,          _ => { unreachable!("p is two bits"); }      }; -    instruction.vex_reg = RegSpec { +    instruction.regs[3] = RegSpec {          bank: RegisterBank::X,          num: ((vex_byte >> 3) & 0b1111) ^ 0b1111,      }; @@ -172,9 +172,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -205,9 +205,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -235,9 +235,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -265,9 +265,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -298,9 +298,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -337,9 +337,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      unreachable!("r is only three bits");                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -350,7 +350,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::VMOVSS_10 |          VEXOperandCode::VMOVSD_10 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -361,7 +361,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.operand_count = 3;                  },                  other => { -                    if instruction.vex_reg.num != 0 { +                    if instruction.regs[3].num != 0 {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } @@ -379,7 +379,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::VMOVSS_11 |          VEXOperandCode::VMOVSD_11 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[2] = OperandSpec::RegRRR; @@ -390,7 +390,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.operand_count = 3;                  },                  other => { -                    if instruction.vex_reg.num != 0 { +                    if instruction.regs[3].num != 0 {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } @@ -414,7 +414,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.mem_size = 4;                  Opcode::VMOVLPS              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -430,7 +430,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.mem_size = 8;                  Opcode::VMOVHPS              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -443,12 +443,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          },          VEXOperandCode::Ev_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = mem_oper; @@ -471,19 +471,19 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      }                  }              } else if instruction.opcode == Opcode::VPEXTRQ { -                instruction.modrm_mmm.bank = RegisterBank::Q; +                instruction.regs[1].bank = RegisterBank::Q;              }              instruction.operand_count = 3;              instruction.imm = read_imm_unsigned(words, 1)?;              Ok(())          },          VEXOperandCode::G_xmm_Eq => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 8)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -495,12 +495,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_xmm_Ed => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -512,12 +512,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Eq_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 8)?;              instruction.operands[0] = mem_oper; @@ -529,12 +529,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ed_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = mem_oper; @@ -546,16 +546,16 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::VCVT_Gd_Ed_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E(words, instruction, modrm, 4)?;              if let OperandSpec::RegMMM = mem_oper { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -565,16 +565,16 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::VCVT_Gq_Eq_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Q);              let mem_oper = read_E(words, instruction, modrm, 4)?;              if let OperandSpec::RegMMM = mem_oper { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  if instruction.opcode == Opcode::VCVTSS2SI {                      instruction.mem_size = 4; @@ -589,12 +589,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          op @ VEXOperandCode::E_G_xmm |          op @ VEXOperandCode::M_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              match (op, mem_oper) { @@ -622,12 +622,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -639,12 +639,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -656,12 +656,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -675,12 +675,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::E_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -694,12 +694,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::E_xmm_G_ymm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -714,12 +714,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::Gd_U_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -731,12 +731,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Gd_U_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::D);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -751,7 +751,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::G_M_xmm |          op @ VEXOperandCode::G_U_xmm |          op @ VEXOperandCode::G_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -769,7 +769,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -787,12 +787,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_xmm_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -804,12 +804,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_xmm_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -822,7 +822,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          op @ VEXOperandCode::G_ymm_M_xmm |          op @ VEXOperandCode::G_ymm_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -832,7 +832,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOperand);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -850,12 +850,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_ymm_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -869,7 +869,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::E_G_ymm |          op @ VEXOperandCode::M_G_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -883,7 +883,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -897,7 +897,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::G_M_ymm |          op @ VEXOperandCode::G_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -911,7 +911,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -930,9 +930,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOperand);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -945,9 +945,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_ymm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -965,9 +965,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if modrm & 0xc0 == 0xc0 {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex; @@ -983,7 +983,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if modrm & 0xc0 == 0xc0 {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1001,7 +1001,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1021,7 +1021,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_xmm_Ed => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1035,7 +1035,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_xmm_Eq => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 8)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1049,7 +1049,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1065,9 +1065,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1086,7 +1086,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -1101,10 +1101,10 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::G_Ex_V_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?; -            instruction.sib_index.bank = RegisterBank::X; +            instruction.regs[2].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1116,11 +1116,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_Ey_V_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_ymm(words, instruction, modrm)?; -            instruction.vex_reg.bank = RegisterBank::X; -            instruction.sib_index.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::X; +            instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1132,11 +1132,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_Ey_V_ymm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?; -            instruction.vex_reg.bank = RegisterBank::Y; -            instruction.sib_index.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y; +            instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1157,9 +1157,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  (4, RegisterBank::D)              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank); -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1177,9 +1177,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  (4, RegisterBank::D)              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank); -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; @@ -1197,7 +1197,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  (4, RegisterBank::D)              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1232,7 +1232,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              } else {                  (4, RegisterBank::D)              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), bank);              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegVex; @@ -1241,7 +1241,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if mem_oper != OperandSpec::RegMMM {                  instruction.mem_size = opwidth;              } -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              Ok(())          }          VEXOperandCode::MXCSR => { @@ -1270,11 +1270,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_E_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1288,11 +1288,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_E_ymm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex().r(), RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1307,9 +1307,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_ymm_ymm4 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1324,9 +1324,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm_xmm4 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::X); -            instruction.vex_reg.bank = RegisterBank::X; +            instruction.regs[3].bank = RegisterBank::X;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1341,9 +1341,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_ymm_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1356,9 +1356,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_xmm_Ev_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex().x(), RegisterBank::X); -            instruction.vex_reg.bank = 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)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1383,7 +1383,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      }                  }              } else if instruction.opcode == Opcode::VPINSRQ { -                instruction.modrm_mmm.bank = RegisterBank::Q; +                instruction.regs[1].bank = RegisterBank::Q;              }              instruction.operand_count = 4;              Ok(()) diff --git a/src/protected_mode/evex.rs b/src/protected_mode/evex.rs index 9d2a093..cb0a4ba 100644 --- a/src/protected_mode/evex.rs +++ b/src/protected_mode/evex.rs @@ -1,6 +1,7 @@  // use crate::long_mode::{OperandSpec, DecodeError, RegSpec, RegisterBank, Instruction, Opcode}; -use crate::protected_mode::{DecodeError, RegSpec, RegisterBank, Instruction, Opcode}; +use crate::protected_mode::{Arch, DecodeError, RegSpec, RegisterBank, Instruction, Opcode};  use crate::protected_mode::{read_modrm, read_E_vex, read_imm_unsigned}; +use yaxpeax_arch::Reader;  const DEFAULT_EVEX_REGISTER_SIZE: RegisterBank = RegisterBank::D;  const DEFAULT_EVEX_REGISTER_WIDTH: u8 = 4; diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index c3a5334..ac7294f 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -531,18 +531,18 @@ impl Operand {              }              // the register in modrm_rrr              OperandSpec::RegRRR => { -                Operand::Register(inst.modrm_rrr) +                Operand::Register(inst.regs[0])              }              OperandSpec::RegRRR_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegRRR_maskmerge_sae => {                  Operand::RegisterMaskMergeSae( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                      SaeMode::from(inst.prefixes.evex_unchecked().vex().l(), inst.prefixes.evex_unchecked().lp()), @@ -550,41 +550,41 @@ impl Operand {              }              OperandSpec::RegRRR_maskmerge_sae_noround => {                  Operand::RegisterMaskMergeSaeNoround( -                    inst.modrm_rrr, +                    inst.regs[0],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              // the register in modrm_mmm (eg modrm mod bits were 11)              OperandSpec::RegMMM => { -                Operand::Register(inst.modrm_mmm) +                Operand::Register(inst.regs[1])              }              OperandSpec::RegMMM_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.modrm_mmm, +                    inst.regs[1],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegMMM_maskmerge_sae_noround => {                  Operand::RegisterMaskMergeSaeNoround( -                    inst.modrm_mmm, +                    inst.regs[1],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::RegVex => { -                Operand::Register(inst.vex_reg) +                Operand::Register(inst.regs[3])              }              OperandSpec::RegVex_maskmerge => {                  Operand::RegisterMaskMerge( -                    inst.vex_reg, +                    inst.regs[3],                      RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()),                      MergeMode::from(inst.prefixes.evex_unchecked().merge()),                  )              }              OperandSpec::Reg4 => { -                Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.vex_reg.bank }) +                Operand::Register(RegSpec { num: inst.imm as u8, bank: inst.regs[3].bank })              }              OperandSpec::ImmI8 => Operand::ImmediateI8(inst.imm as i8),              OperandSpec::ImmU8 => Operand::ImmediateU8(inst.imm as u8), @@ -595,7 +595,7 @@ impl Operand {              OperandSpec::DispU16 => Operand::DisplacementU16(inst.disp as u16),              OperandSpec::DispU32 => Operand::DisplacementU32(inst.disp),              OperandSpec::Deref => { -                Operand::RegDeref(inst.modrm_mmm) +                Operand::RegDeref(inst.regs[1])              }              OperandSpec::Deref_esi => {                  Operand::RegDeref(RegSpec::esi()) @@ -604,66 +604,66 @@ impl Operand {                  Operand::RegDeref(RegSpec::edi())              }              OperandSpec::RegDisp => { -                Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) +                Operand::RegDisp(inst.regs[1], inst.disp as i32)              }              OperandSpec::RegScale => { -                Operand::RegScale(inst.sib_index, inst.scale) +                Operand::RegScale(inst.regs[2], inst.scale)              }              OperandSpec::RegIndexBase => { -                Operand::RegIndexBase(inst.modrm_mmm, inst.sib_index) +                Operand::RegIndexBase(inst.regs[1], inst.regs[2])              }              OperandSpec::RegIndexBaseDisp => { -                Operand::RegIndexBaseDisp(inst.modrm_mmm, inst.sib_index, inst.disp as i32) +                Operand::RegIndexBaseDisp(inst.regs[1], inst.regs[2], inst.disp as i32)              }              OperandSpec::RegScaleDisp => { -                Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) +                Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32)              }              OperandSpec::RegIndexBaseScale => { -                Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) +                Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale)              }              OperandSpec::RegIndexBaseScaleDisp => { -                Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) +                Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32)              }              OperandSpec::Deref_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegDerefMasked(inst.modrm_mmm, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegDerefMasked(inst.regs[1], RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegDeref(inst.modrm_mmm) +                    Operand::RegDeref(inst.regs[1])                  }              }              OperandSpec::RegDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegDispMasked(inst.modrm_mmm, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegDispMasked(inst.regs[1], inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegDisp(inst.modrm_mmm, inst.disp as i32) +                    Operand::RegDisp(inst.regs[1], inst.disp as i32)                  }              }              OperandSpec::RegScale_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegScaleMasked(inst.sib_index, inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegScaleMasked(inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegScale(inst.sib_index, inst.scale) +                    Operand::RegScale(inst.regs[2], inst.scale)                  }              }              OperandSpec::RegScaleDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegScaleDispMasked(inst.sib_index, inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegScaleDispMasked(inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegScaleDisp(inst.sib_index, inst.scale, inst.disp as i32) +                    Operand::RegScaleDisp(inst.regs[2], inst.scale, inst.disp as i32)                  }              }              OperandSpec::RegIndexBaseScale_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegIndexBaseScaleMasked(inst.modrm_mmm, inst.sib_index, inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegIndexBaseScaleMasked(inst.regs[1], inst.regs[2], inst.scale, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegIndexBaseScale(inst.modrm_mmm, inst.sib_index, inst.scale) +                    Operand::RegIndexBaseScale(inst.regs[1], inst.regs[2], inst.scale)                  }              }              OperandSpec::RegIndexBaseScaleDisp_mask => {                  if inst.prefixes.evex_unchecked().mask_reg() != 0 { -                    Operand::RegIndexBaseScaleDispMasked(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg())) +                    Operand::RegIndexBaseScaleDispMasked(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32, RegSpec::mask(inst.prefixes.evex_unchecked().mask_reg()))                  } else { -                    Operand::RegIndexBaseScaleDisp(inst.modrm_mmm, inst.sib_index, inst.scale, inst.disp as i32) +                    Operand::RegIndexBaseScaleDisp(inst.regs[1], inst.regs[2], inst.scale, inst.disp as i32)                  }              }          } @@ -788,12 +788,12 @@ const REGISTER_CLASS_NAMES: &[&'static str] = &[  /// extern crate yaxpeax_arch;  /// use yaxpeax_x86::protected_mode::{self as amd64};  /// use yaxpeax_x86::protected_mode::{Opcode, Operand, RegisterClass}; -/// use yaxpeax_arch::Decoder; +/// use yaxpeax_arch::{Decoder, U8Reader};  ///  /// let movsx_eax_cl = &[0x0f, 0xbe, 0xc1];  /// let decoder = amd64::InstDecoder::default();  /// let instruction = decoder -///     .decode(movsx_eax_cl.into_iter().cloned()) +///     .decode(&mut U8Reader::new(movsx_eax_cl))  ///     .expect("can decode");  ///  /// assert_eq!(instruction.opcode(), Opcode::MOVSX); @@ -2445,10 +2445,13 @@ pub enum Opcode {  #[derive(Debug)]  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,      operand_count: u8, @@ -4105,10 +4108,7 @@ impl Instruction {              prefixes: Prefixes::new(0),              opcode: Opcode::Invalid,              mem_size: 0, -            modrm_rrr: RegSpec::eax(), -            modrm_mmm: RegSpec::eax(), // doubles as sib_base -            sib_index: RegSpec::eax(), -            vex_reg: RegSpec::eax(), +            regs: [RegSpec::eax(); 4],              scale: 0,              length: 0,              disp: 0, @@ -5345,11 +5345,11 @@ pub(self) fn read_E_ymm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a      }  }  #[allow(non_snake_case)] -pub(self) fn read_E_vex<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, length: &mut u8, bank: RegisterBank) -> Result<OperandSpec, DecodeError> { +pub(self) fn read_E_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8, bank: RegisterBank) -> Result<OperandSpec, DecodeError> {      if modrm >= 0b11000000 {          read_modrm_reg(instr, modrm, bank)      } else { -        let res = read_M(bytes_iter, instr, modrm)?; +        let res = read_M(words, instr, modrm)?;          if (modrm & 0b01_000_000) == 0b01_000_000 {              instr.prefixes.apply_compressed_disp(true);          } @@ -5359,7 +5359,7 @@ pub(self) fn read_E_vex<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut In  #[allow(non_snake_case)]  fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, DecodeError> { -    instr.modrm_mmm = RegSpec::from_parts(modrm & 7, reg_bank); +    instr.regs[1] = RegSpec::from_parts(modrm & 7, reg_bank);      Ok(OperandSpec::RegMMM)  } @@ -5386,7 +5386,7 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar              if modbits == 0b00 {                  OperandSpec::DispU32              } else { -                instr.modrm_mmm.num |= 0b101; +                instr.regs[1].num |= 0b101;                  if disp == 0 {                      OperandSpec::Deref @@ -5395,8 +5395,8 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar                  }              }          } else { -            instr.modrm_mmm.num |= 0b101; -            instr.sib_index.num |= (sibbyte >> 3) & 7; +            instr.regs[1].num |= 0b101; +            instr.regs[2].num |= (sibbyte >> 3) & 7;              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale; @@ -5416,7 +5416,7 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar              }          }      } else { -        instr.modrm_mmm.num |= sibbyte & 7; +        instr.regs[1].num |= sibbyte & 7;          if ((sibbyte >> 3) & 7) == 0b100 {              if disp == 0 { @@ -5425,7 +5425,7 @@ fn read_sib<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ar                  OperandSpec::RegDisp              }          } else { -            instr.sib_index.num |= (sibbyte >> 3) & 7; +            instr.regs[2].num |= (sibbyte >> 3) & 7;              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale; @@ -5448,32 +5448,32 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea      }      match mmm {          0b000 => { -            instr.modrm_mmm = RegSpec::bx(); -            instr.sib_index = RegSpec::si(); +            instr.regs[1] = RegSpec::bx(); +            instr.regs[2] = RegSpec::si();          },          0b001 => { -            instr.modrm_mmm = RegSpec::bx(); -            instr.sib_index = RegSpec::di(); +            instr.regs[1] = RegSpec::bx(); +            instr.regs[2] = RegSpec::di();          },          0b010 => { -            instr.modrm_mmm = RegSpec::bp(); -            instr.sib_index = RegSpec::si(); +            instr.regs[1] = RegSpec::bp(); +            instr.regs[2] = RegSpec::si();          },          0b011 => { -            instr.modrm_mmm = RegSpec::bp(); -            instr.sib_index = RegSpec::di(); +            instr.regs[1] = RegSpec::bp(); +            instr.regs[2] = RegSpec::di();          },          0b100 => { -            instr.modrm_mmm = RegSpec::si(); +            instr.regs[1] = RegSpec::si();          },          0b101 => { -            instr.modrm_mmm = RegSpec::di(); +            instr.regs[1] = RegSpec::di();          },          0b110 => { -            instr.modrm_mmm = RegSpec::bp(); +            instr.regs[1] = RegSpec::bp();          },          0b111 => { -            instr.modrm_mmm = RegSpec::bx(); +            instr.regs[1] = RegSpec::bx();          },          _ => { unreachable!("impossible bit pattern"); }      } @@ -5512,7 +5512,7 @@ fn read_M<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch      if instr.prefixes.address_size() {          return read_M_16bit(words, instr, modrm);      } -    instr.modrm_mmm.bank = RegisterBank::D; +    instr.regs[1].bank = RegisterBank::D;      let modbits = modrm >> 6;      let mmm = modrm & 7;      let op_spec = if mmm == 4 { @@ -5521,7 +5521,7 @@ fn read_M<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch          instr.disp = read_num(words, 4)?;          OperandSpec::DispU32      } else { -        instr.modrm_mmm.num |= mmm; +        instr.regs[1].num |= mmm;          if modbits == 0b00 {              OperandSpec::Deref @@ -6854,6 +6854,12 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_  //    use core::intrinsics::unlikely;      let mut prefixes = Prefixes::new(0); +    instruction.regs = unsafe { core::mem::transmute(0u64) }; +    instruction.mem_size = 0; +    instruction.operands = unsafe { core::mem::transmute(0x00_00_00_01) }; +    instruction.operand_count = 2; + +      let record: OpcodeRecord = loop {          let b = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;          if words.offset() >= 15 { @@ -6989,7 +6995,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                          } else {                              RegisterBank::W                          }; -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(reg, bank);                          instruction.operand_count = 1;                      } @@ -7000,16 +7006,16 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                          } else {                              RegisterBank::W                          }; -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(0, bank);                          instruction.operands[1] = OperandSpec::RegMMM; -                        instruction.modrm_mmm = +                        instruction.regs[1] =                              RegSpec::from_parts(reg, bank);                          instruction.operand_count = 2;                      }                      2 => {                          // these are Zb_Ib_R -                        instruction.modrm_rrr = +                        instruction.regs[0] =                              RegSpec::from_parts(reg, RegisterBank::B);                          instruction.imm =                              read_imm_unsigned(words, 1)?; @@ -7018,13 +7024,13 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                      3 => {                          // category == 3, Zv_Iv_R                          if !instruction.prefixes.operand_size() { -                            instruction.modrm_rrr = +                            instruction.regs[0] =                                  RegSpec::from_parts(reg, RegisterBank::D);                              instruction.imm =                                  read_imm_unsigned(words, 4)?;                              instruction.operands[1] = OperandSpec::ImmI32;                          } else { -                            instruction.modrm_rrr = +                            instruction.regs[0] =                                  RegSpec::from_parts(reg, RegisterBank::W);                              instruction.imm =                                  read_imm_unsigned(words, 2)?; @@ -7063,8 +7069,8 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              bank = RegisterBank::B;          };          modrm = read_modrm(words)?; -        instruction.modrm_rrr.bank = bank; -        instruction.modrm_rrr.num = (modrm >> 3) & 7; +        instruction.regs[0].bank = bank; +        instruction.regs[0].num = (modrm >> 3) & 7;          mem_oper = if modrm >= 0b11000000 {              if operand_code.bits() == (OperandCode::Gv_M as u16) { @@ -7180,10 +7186,10 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operands[0] = mem_oper;              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              if op == 10 { -                instruction.modrm_rrr = RegSpec::cl(); +                instruction.regs[0] = RegSpec::cl();                  instruction.operands[1] = OperandSpec::RegRRR;              } else if op == 9 { -                instruction.modrm_rrr = RegSpec::cl(); +                instruction.regs[0] = RegSpec::cl();                  instruction.operands[1] = OperandSpec::RegRRR;              } else {                  let num = match op { @@ -7278,7 +7284,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              ][r as usize];              if instruction.operands[0] == OperandSpec::RegMMM {                  if opcode == Opcode::CALL || opcode == Opcode::JMP { -                    instruction.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  } else if opcode == Opcode::CALLF || opcode == Opcode::JMPF {                      return Err(DecodeError::InvalidOperand);                  } @@ -7296,7 +7302,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E(words, instruction, modrm, 1)?; -            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +            instruction.regs[0] = if instruction.prefixes.operand_size() {                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W)              } else {                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) @@ -7310,7 +7316,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E(words, instruction, modrm, 2)?; -            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +            instruction.regs[0] = if instruction.prefixes.operand_size() {                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W)              } else {                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D) @@ -7325,20 +7331,20 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operand_count = 1;          },          19 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            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 -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 16;              }          },          op @ 20 |          op @ 21 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operand_count = 2;              if instruction.operands[1] == OperandSpec::RegMMM {                  if op == 20 { @@ -7346,7 +7352,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe                      return Err(DecodeError::InvalidOperand);                  } else {                      // fix the register to XMM -                    instruction.modrm_mmm.bank = RegisterBank::X; +                    instruction.regs[1].bank = RegisterBank::X;                  }              } else {                  if instruction.opcode == Opcode::MOVDDUP { @@ -7360,7 +7366,7 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u32; @@ -7377,18 +7383,18 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operand_count = 3;          },          23 => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          }          24 => {              let opwidth = if instruction.prefixes.operand_size() { -                instruction.modrm_rrr = +                instruction.regs[0] =                      RegSpec::from_parts(0, RegisterBank::W);                  2              } else { -                instruction.modrm_rrr = +                instruction.regs[0] =                      RegSpec::from_parts(0, RegisterBank::D);                  4              }; @@ -7433,16 +7439,16 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              return Ok(());          },          29 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            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.modrm_mmm.bank = RegisterBank::D; +                    instruction.regs[1].bank = RegisterBank::D;                  } else { -                    instruction.modrm_mmm.bank = RegisterBank::X; +                    instruction.regs[1].bank = RegisterBank::X;                  }              } else {                  instruction.mem_size = 4; @@ -7460,11 +7466,11 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe              instruction.operand_count = 1;          }          31 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operand_count = 2;              if instruction.operands[1] == OperandSpec::RegMMM {                  // fix the register to XMM -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -7484,14 +7490,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_mm(words, instruction, modrm)?; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 };              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; +                instruction.regs[1].bank = RegisterBank::MM;              } else {                  instruction.mem_size = 8;              }              instruction.imm = read_num(words, 1)? as u8 as u32; -            *length += 1;              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3;          } @@ -7499,9 +7504,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 };              instruction.imm = read_num(words, 1)? as u8 as u32; -            *length += 1;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = match instruction.opcode {                      Opcode::PEXTRB => 1, @@ -7521,7 +7525,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::PMOVX_E_G_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 };              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[0] = read_E_xmm(words, instruction, modrm)?;              if instruction.operands[0] != OperandSpec::RegMMM { @@ -7539,7 +7543,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::PMOVX_G_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::X, num: (modrm >> 3) & 7 }; +            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)?;              if instruction.operands[1] != OperandSpec::RegMMM { @@ -7559,7 +7563,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::INV_Gv_M => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::D, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::D, num: (modrm >> 3) & 7 };              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = read_M(words, instruction, modrm)?;              if instruction.operands[1] == OperandSpec::RegMMM { @@ -7595,7 +7599,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }              } else {                  // LES -                instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); +                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)?;                  if instruction.prefixes.operand_size() { @@ -7623,7 +7627,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }              } else {                  // LDS -                instruction.modrm_rrr = RegSpec::from_parts((modrm >> 3) & 7, if instruction.prefixes.operand_size() { RegisterBank::W } else { RegisterBank::D }); +                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)?;                  if instruction.prefixes.operand_size() { @@ -7640,7 +7644,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if instruction.operands[1] != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              instruction.imm =                  read_num(words, 1)? as u8 as u32; @@ -7657,10 +7661,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[1] = OperandSpec::RegMMM; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec::from_parts(modrm & 7, RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u32; @@ -7684,7 +7688,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.operands[0] = OperandSpec::RegMMM; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec::from_parts(modrm & 7, RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u32; @@ -7699,7 +7703,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.imm =                  read_num(words, 1)? as u8 as u32; @@ -7710,15 +7714,15 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;          }          OperandCode::Gd_Ed => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              }              instruction.operands[1] = mem_oper;              instruction.operand_count = 2;          }          OperandCode::Md_Gd => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -7727,11 +7731,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::G_U_xmm => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.regs[1].bank = RegisterBank::X;              instruction.operand_count = 2;          },          OperandCode::Gv_Ev_Ib => { @@ -7765,17 +7769,17 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::RegVex; -            instruction.vex_reg = RegSpec::cl(); +            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)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::MM);              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              } @@ -7785,11 +7789,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;          }          OperandCode::G_E_mm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  if [Opcode::PACKSSWB, Opcode::PCMPGTB, Opcode::PCMPGTW, Opcode::PCMPGTD, Opcode::PACKUSWB, Opcode::PUNPCKHBW, Opcode::PUNPCKHWD, Opcode::PUNPCKHDQ, Opcode::PACKSSDW, Opcode::PSRLW, Opcode::PMULHW, Opcode::PSHUFB, Opcode::PHADDW, Opcode::PHADDD, Opcode::PHADDSW, Opcode::PMADDUBSW, Opcode::PHSUBW, Opcode::PHSUBD, Opcode::PHSUBSW, Opcode::PSIGNB, Opcode::PSIGNW, Opcode::PSIGND, Opcode::PMULHRSW, Opcode::PABSB, Opcode::PABSW, Opcode::PABSD].contains(&instruction.opcode) {                      instruction.mem_size = 8; @@ -7800,28 +7804,28 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          },          OperandCode::G_U_mm => { -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::MM; -            instruction.modrm_mmm.num &= 0b111; +            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.modrm_rrr = +                instruction.regs[0] =                      RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::W);              } else { -                instruction.modrm_rrr = +                instruction.regs[0] =                      RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              };              instruction.operands[1] = read_E(words, instruction, modrm, 2)?;              // lsl is weird. the full register width is written, but only the low 16 bits are used.              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              } @@ -7836,7 +7840,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  4              };              instruction.operands[1] = read_E(words, instruction, modrm, opwidth)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              instruction.operand_count = 2;              if instruction.operands[1] != OperandSpec::RegMMM { @@ -7845,7 +7849,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          },          op @ OperandCode::AL_Ob |          op @ OperandCode::AX_Ov => { -            instruction.modrm_rrr = match op { +            instruction.regs[0] = match op {                  OperandCode::AL_Ob => {                      instruction.mem_size = 1;                      RegSpec::al() @@ -7875,7 +7879,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          op @ OperandCode::Ob_AL |          op @ OperandCode::Ov_AX => { -            instruction.modrm_rrr = match op { +            instruction.regs[0] = match op {                  OperandCode::Ob_AL => {                      instruction.mem_size = 1;                      RegSpec::al() @@ -7930,13 +7934,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 0;          }          OperandCode::G_mm_U_mm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; +            instruction.regs[0].bank = RegisterBank::MM;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_mmm.bank = RegisterBank::MM; -            instruction.modrm_mmm.num &= 0b111; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[1].bank = RegisterBank::MM; +            instruction.regs[1].num &= 0b111; +            instruction.regs[0].num &= 0b111;              instruction.operand_count = 2;          },          OperandCode::E_G_q => { @@ -7948,7 +7952,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[0] = read_E(words, instruction, modrm, 4)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM { @@ -7963,7 +7967,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[0] != OperandSpec::RegMMM { @@ -7974,19 +7978,19 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::G_Mq_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; +            instruction.regs[0].bank = RegisterBank::MM;              if mem_oper == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } else {                  instruction.mem_size = 8;              } -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].num &= 0b111;              instruction.operand_count = 2;          },          OperandCode::MOVQ_f30f => {              instruction.operand_count = 2;              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[1] = read_E_xmm(words, instruction, modrm)?;              if instruction.operands[1] != OperandSpec::RegMMM { @@ -8024,7 +8028,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.operands[1] = read_E_mm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; +            instruction.regs[0] = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 };              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8;              } @@ -8162,7 +8166,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // 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                              // word-form operand: -                            instruction.modrm_mmm = RegSpec { bank: RegisterBank::W, num: instruction.modrm_mmm.num }; +                            instruction.regs[1] = RegSpec { bank: RegisterBank::W, num: instruction.regs[1].num };                              instruction.opcode = Opcode::RDRAND;                          } else {                              instruction.mem_size = 8; @@ -8176,7 +8180,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // 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                              // word-form operand: -                            instruction.modrm_mmm = RegSpec { bank: RegisterBank::W, num: instruction.modrm_mmm.num }; +                            instruction.regs[1] = RegSpec { bank: RegisterBank::W, num: instruction.regs[1].num };                              instruction.opcode = Opcode::RDSEED;                          } else {                              return Err(DecodeError::InvalidOpcode); @@ -8219,7 +8223,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              // invalid as `vmxon`, reg-form is `senduipi`                              instruction.opcode = Opcode::SENDUIPI;                              // and the operand is always a dword register -                            instruction.modrm_mmm.bank = RegisterBank::D; +                            instruction.regs[1].bank = RegisterBank::D;                          } else {                              instruction.mem_size = 8;                          } @@ -8342,9 +8346,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u32; @@ -8375,9 +8379,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u32; @@ -8421,9 +8425,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              if instruction.prefixes.operand_size() { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::X, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::X, num: modrm & 7 };              } else { -                instruction.modrm_mmm = RegSpec { bank: RegisterBank::MM, num: modrm & 7 }; +                instruction.regs[1] = RegSpec { bank: RegisterBank::MM, num: modrm & 7 };              }              instruction.operands[0] = OperandSpec::RegMMM;              instruction.imm = read_imm_signed(words, 1)? as u32; @@ -8505,30 +8509,30 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::ModRM_0xf30f38fa => {              instruction.opcode = Opcode::ENCODEKEY128;              read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::ModRM_0xf30f38fb => {              instruction.opcode = Opcode::ENCODEKEY256;              read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::G_mm_Ed => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 4;              }          }          OperandCode::G_mm_E => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  instruction.mem_size = 8;              } @@ -8536,10 +8540,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::Ed_G_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 4;              } @@ -8547,9 +8551,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::Ed_G_xmm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::Y; +            instruction.regs[0].bank = RegisterBank::Y;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 4;              } @@ -8557,11 +8561,11 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          OperandCode::E_G_mm => {              instruction.operands[1] = instruction.operands[0];              instruction.operands[0] = mem_oper; -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  instruction.mem_size = 8;              } @@ -8571,36 +8575,36 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;              instruction.imm =                  read_num(words, 1)?; -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 2;              }          },          OperandCode::G_xmm_Ed => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::D; +                instruction.regs[1].bank = RegisterBank::D;              } else {                  instruction.mem_size = 4;              }          },          OperandCode::G_mm_E_xmm => { -            instruction.modrm_rrr.bank = RegisterBank::MM; -            instruction.modrm_rrr.num &= 0b111; +            instruction.regs[0].bank = RegisterBank::MM; +            instruction.regs[0].num &= 0b111;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 16;              }          },          op @ OperandCode::G_xmm_U_mm |          op @ OperandCode::G_xmm_E_mm => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  if op == OperandCode::G_xmm_U_mm {                      return Err(DecodeError::InvalidOperand); @@ -8614,27 +8618,27 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 3;              instruction.imm =                  read_num(words, 1)?; -            instruction.modrm_rrr.bank = RegisterBank::D; +            instruction.regs[0].bank = RegisterBank::D;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::MM; -                instruction.modrm_mmm.num &= 0b111; +                instruction.regs[1].bank = RegisterBank::MM; +                instruction.regs[1].num &= 0b111;              } else {                  return Err(DecodeError::InvalidOperand);              }          }          OperandCode::U_mm_G_xmm => { -            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.regs[1].bank = RegisterBank::X;              if mem_oper == OperandSpec::RegMMM { -                instruction.modrm_rrr.bank = RegisterBank::MM; -                instruction.modrm_rrr.num &= 0b111; +                instruction.regs[0].bank = RegisterBank::MM; +                instruction.regs[0].num &= 0b111;              } else {                  return Err(DecodeError::InvalidOperand);              }          }          // sure hope these aren't backwards huh          OperandCode::AL_Xb => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::esi(); +            instruction.regs[0] = RegSpec::al(); +            instruction.regs[1] = RegSpec::esi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              instruction.mem_size = 1; @@ -8647,33 +8651,33 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::Yb_AL => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::esi(); +            instruction.regs[0] = RegSpec::al(); +            instruction.regs[1] = RegSpec::esi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.mem_size = 1;              instruction.operand_count = 2;          }          OperandCode::AX_Xv => { -            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +            instruction.regs[0] = if instruction.prefixes.operand_size() {                  instruction.mem_size = 2;                  RegSpec::ax()              } else {                  instruction.mem_size = 4;                  RegSpec::eax()              }; -            instruction.modrm_mmm = RegSpec::esi(); +            instruction.regs[1] = RegSpec::esi();              instruction.operands[1] = OperandSpec::Deref;          }          OperandCode::Yv_AX => { -            instruction.modrm_rrr = if instruction.prefixes.operand_size() { +            instruction.regs[0] = if instruction.prefixes.operand_size() {                  instruction.mem_size = 2;                  RegSpec::ax()              } else {                  instruction.mem_size = 4;                  RegSpec::eax()              }; -            instruction.modrm_mmm = RegSpec::edi(); +            instruction.regs[1] = RegSpec::edi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;          } @@ -8687,13 +8691,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operands[1] = OperandSpec::Deref_esi;          }          OperandCode::ModRM_0x0f12 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operands[1] = mem_oper;              if instruction.operands[1] == OperandSpec::RegMMM {                  if instruction.prefixes.operand_size() {                      return Err(DecodeError::InvalidOpcode);                  } -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;                  instruction.opcode = Opcode::MOVHLPS;              } else {                  instruction.mem_size = 8; @@ -8705,10 +8709,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0x0f16 => { -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;              instruction.operands[1] = mem_oper;              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;                  if instruction.prefixes.operand_size() {                      return Err(DecodeError::InvalidOpcode);                  } @@ -8723,7 +8727,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0x0f18 => { -            let rrr = instruction.modrm_rrr.num & 0b111; +            let rrr = instruction.regs[0].num & 0b111;              instruction.operands[0] = mem_oper;              instruction.operand_count = 1;              instruction.opcode = if mem_oper == OperandSpec::RegMMM && rrr < 4 { @@ -8746,12 +8750,12 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr.bank = RegisterBank::D; -            instruction.modrm_mmm.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::D; +            instruction.regs[1].bank = RegisterBank::X;          }          OperandCode::Gv_E_xmm => {              if instruction.operands[1] == OperandSpec::RegMMM { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -8771,12 +8775,12 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.mem_size = 8;                  }              } -            instruction.modrm_rrr.bank = RegisterBank::X; +            instruction.regs[0].bank = RegisterBank::X;          }          OperandCode::Ew_Gw => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: RegisterBank::W, num: (modrm >> 3) & 7 };              instruction.operands[0] = read_E(words, instruction, modrm, 2)?;              instruction.operands[1] = OperandSpec::RegRRR; @@ -8793,14 +8797,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;              let mod_bits = modrm >> 6;              if mod_bits == 0b11 { -                instruction.modrm_mmm = +                instruction.regs[1] =                      RegSpec { bank: RegisterBank::W, num: modrm & 7};                  instruction.operands[0] = OperandSpec::RegMMM;              } else { @@ -8817,7 +8821,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: RegisterBank::S, num: (modrm >> 3) & 7 };              // quoth the manual: @@ -8826,7 +8830,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              // results in an invalid opcode excep-tion (#UD). To load the CS register, use the far              // JMP, CALL, or RET instruction.              // ``` -            if instruction.modrm_rrr.num == 1 { +            if instruction.regs[0].num == 1 {                  return Err(DecodeError::InvalidOperand);              }              instruction.operands[0] = OperandSpec::RegRRR; @@ -8834,7 +8838,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let mod_bits = modrm >> 6;              if mod_bits == 0b11 { -                instruction.modrm_mmm = +                instruction.regs[1] =                      RegSpec { bank: RegisterBank::W, num: modrm & 7};                  instruction.operands[1] = OperandSpec::RegMMM;              } else { @@ -9047,7 +9051,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          0b000 => {                              instruction.opcode = Opcode::VMRUN;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::eax(); +                            instruction.regs[0] = RegSpec::eax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b001 => { @@ -9058,13 +9062,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          0b010 => {                              instruction.opcode = Opcode::VMLOAD;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::eax(); +                            instruction.regs[0] = RegSpec::eax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b011 => {                              instruction.opcode = Opcode::VMSAVE;                              instruction.operand_count = 1; -                            instruction.modrm_rrr = RegSpec::eax(); +                            instruction.regs[0] = RegSpec::eax();                              instruction.operands[0] = OperandSpec::RegRRR;                          },                          0b100 => { @@ -9081,15 +9085,15 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                              instruction.opcode = Opcode::SKINIT;                              instruction.operand_count = 1;                              instruction.operands[0] = OperandSpec::RegRRR; -                            instruction.modrm_rrr = RegSpec::eax(); +                            instruction.regs[0] = RegSpec::eax();                          },                          0b111 => {                              instruction.opcode = Opcode::INVLPGA;                              instruction.operand_count = 2;                              instruction.operands[0] = OperandSpec::RegRRR;                              instruction.operands[1] = OperandSpec::RegMMM; -                            instruction.modrm_rrr = RegSpec::eax(); -                            instruction.modrm_mmm = RegSpec::ecx(); +                            instruction.regs[0] = RegSpec::eax(); +                            instruction.regs[1] = RegSpec::ecx();                          },                          _ => {                              instruction.opcode = Opcode::Invalid; @@ -9250,7 +9254,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      } else if m == 5 {                          instruction.opcode = Opcode::RDPRU;                          instruction.operands[0] = OperandSpec::RegRRR; -                        instruction.modrm_rrr = RegSpec::ecx(); +                        instruction.regs[0] = RegSpec::ecx();                          instruction.operand_count = 1;                      } else if m == 6 {                          instruction.opcode = Opcode::INVLPGB; @@ -9258,9 +9262,9 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                          instruction.operands[0] = OperandSpec::RegRRR;                          instruction.operands[1] = OperandSpec::RegMMM;                          instruction.operands[2] = OperandSpec::RegVex; -                        instruction.modrm_rrr = RegSpec::eax(); -                        instruction.modrm_mmm = RegSpec::edx(); -                        instruction.vex_reg = RegSpec::ecx(); +                        instruction.regs[0] = RegSpec::eax(); +                        instruction.regs[1] = RegSpec::edx(); +                        instruction.regs[3] = RegSpec::ecx();                      } else if m == 7 {                          instruction.opcode = Opcode::TLBSYNC;                          instruction.operand_count = 0; @@ -9323,7 +9327,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      match r {                          6 => {                              instruction.opcode = Opcode::UMWAIT; -                            instruction.modrm_rrr = RegSpec { +                            instruction.regs[0] = RegSpec {                                  bank: RegisterBank::D,                                  num: m,                              }; @@ -9358,38 +9362,38 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      match r {                          0 => {                              instruction.opcode = Opcode::RDFSBASE; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          1 => {                              instruction.opcode = Opcode::RDGSBASE; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          2 => {                              instruction.opcode = Opcode::WRFSBASE; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          3 => {                              instruction.opcode = Opcode::WRGSBASE; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          5 => {                              instruction.opcode = Opcode::INCSSP; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          }                          6 => {                              instruction.opcode = Opcode::UMONITOR; -                            instruction.modrm_mmm = RegSpec::from_parts(m, RegisterBank::D); +                            instruction.regs[1] = RegSpec::from_parts(m, RegisterBank::D);                              instruction.operands[0] = OperandSpec::RegMMM;                              instruction.operand_count = 1;                          } @@ -9554,53 +9558,53 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  _ => unsafe { unreachable_unchecked() }              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec { bank: bank, num: r }; -            instruction.modrm_mmm = +            instruction.regs[1] =                  RegSpec { bank: RegisterBank::D, num: m };              instruction.operands[mmm] = OperandSpec::RegMMM;              instruction.operands[rrr] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::FS => { -            instruction.modrm_rrr = RegSpec::fs(); +            instruction.regs[0] = RegSpec::fs();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::GS => { -            instruction.modrm_rrr = RegSpec::gs(); +            instruction.regs[0] = RegSpec::gs();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::CS => { -            instruction.modrm_rrr = RegSpec::cs(); +            instruction.regs[0] = RegSpec::cs();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::DS => { -            instruction.modrm_rrr = RegSpec::ds(); +            instruction.regs[0] = RegSpec::ds();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::ES => { -            instruction.modrm_rrr = RegSpec::es(); +            instruction.regs[0] = RegSpec::es();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::SS => { -            instruction.modrm_rrr = RegSpec::ss(); +            instruction.regs[0] = RegSpec::ss();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operand_count = 1;          }          OperandCode::AL_Ib => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8;              instruction.operand_count = 2;          }          OperandCode::AX_Ib => { -            instruction.modrm_rrr = if !instruction.prefixes.operand_size() { +            instruction.regs[0] = if !instruction.prefixes.operand_size() {                 RegSpec::eax()              } else {                 RegSpec::ax() @@ -9610,14 +9614,14 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::Ib_AL => { -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::al();              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::Ib_AX => { -            instruction.modrm_rrr = if !instruction.prefixes.operand_size() { +            instruction.regs[0] = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax() @@ -9627,52 +9631,52 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::AX_DX => { -            instruction.modrm_rrr = if !instruction.prefixes.operand_size() { +            instruction.regs[0] = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax()              }; -            instruction.modrm_mmm = RegSpec::dx(); +            instruction.regs[1] = RegSpec::dx();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegMMM;              instruction.operand_count = 2;          }          OperandCode::AL_DX => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::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.modrm_rrr = if !instruction.prefixes.operand_size() { +            instruction.regs[0] = if !instruction.prefixes.operand_size() {                  RegSpec::eax()              } else {                  RegSpec::ax()              }; -            instruction.modrm_mmm = RegSpec::dx(); +            instruction.regs[1] = RegSpec::dx();              instruction.operands[0] = OperandSpec::RegMMM;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          }          OperandCode::DX_AL => { -            instruction.modrm_rrr = RegSpec::al(); -            instruction.modrm_mmm = RegSpec::dx(); +            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 => { -            instruction.modrm_rrr = RegSpec::dl(); -            instruction.modrm_mmm = RegSpec::edi(); +            instruction.regs[0] = RegSpec::dl(); +            instruction.regs[1] = RegSpec::edi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;              instruction.mem_size = 1;          }          OperandCode::Yv_DX => { -            instruction.modrm_rrr = RegSpec::dx(); -            instruction.modrm_mmm = RegSpec::edi(); +            instruction.regs[0] = RegSpec::dx(); +            instruction.regs[1] = RegSpec::edi();              instruction.operands[0] = OperandSpec::Deref;              instruction.operands[1] = OperandSpec::RegRRR;              if instruction.prefixes.operand_size() { @@ -9683,8 +9687,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 2;          }          OperandCode::DX_Xb => { -            instruction.modrm_rrr = RegSpec::dl(); -            instruction.modrm_mmm = RegSpec::esi(); +            instruction.regs[0] = RegSpec::dl(); +            instruction.regs[1] = RegSpec::esi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              instruction.operand_count = 2; @@ -9695,8 +9699,8 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.operand_count = 0;          }          OperandCode::DX_Xv => { -            instruction.modrm_rrr = RegSpec::dx(); -            instruction.modrm_mmm = RegSpec::esi(); +            instruction.regs[0] = RegSpec::dx(); +            instruction.regs[1] = RegSpec::esi();              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::Deref;              if instruction.prefixes.operand_size() { @@ -9731,10 +9735,10 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              if modrm < 0xc0 { -                instruction.modrm_rrr = +                instruction.regs[0] =                      RegSpec { bank: RegisterBank::D, num: (modrm >> 3) & 7 };                  if instruction.prefixes.operand_size() { -                    instruction.modrm_rrr.bank = RegisterBank::W; +                    instruction.regs[0].bank = RegisterBank::W;                      instruction.mem_size = 4;                  } else {                      instruction.mem_size = 8; @@ -10120,13 +10124,13 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Est => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              instruction.operand_count = 2;          }          OperandCodeX87::St_Edst => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 4; @@ -10135,7 +10139,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Eqst => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E_st(words, instruction, modrm)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 8; @@ -10144,7 +10148,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Ew => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 2)?;              if instruction.operands[1] != OperandSpec::RegMMM {                  instruction.mem_size = 2; @@ -10153,7 +10157,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mm => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10163,7 +10167,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mq => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10173,7 +10177,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Md => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand); @@ -10183,8 +10187,8 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          }          OperandCodeX87::St_Mw => {              instruction.operands[0] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); -            instruction.operands[0] = read_E(words, instruction, modrm, 4)?; +            instruction.regs[0] = RegSpec::st(0); +            instruction.operands[1] = read_E(words, instruction, modrm, 4)?;              if instruction.operands[1] == OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -10201,13 +10205,13 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Est_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Edst_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 4; @@ -10216,7 +10220,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Eqst_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 8; @@ -10225,7 +10229,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCodeX87::Ed_St => {              instruction.operands[0] = read_E_st(words, instruction, modrm)?;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              if instruction.operands[0] != OperandSpec::RegMMM {                  instruction.mem_size = 4;              } @@ -10238,7 +10242,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 10;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Mq_St => { @@ -10248,7 +10252,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 8;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Md_St => { @@ -10258,7 +10262,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 4;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Mw_St => { @@ -10268,7 +10272,7 @@ fn decode_x87<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_              }              instruction.mem_size = 2;              instruction.operands[1] = OperandSpec::RegRRR; -            instruction.modrm_rrr = RegSpec::st(0); +            instruction.regs[0] = RegSpec::st(0);              instruction.operand_count = 2;          }          OperandCodeX87::Ex87S => { diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs index 2f871c6..235d160 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -117,7 +117,7 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A              return Err(DecodeError::InvalidOpcode);          }      }; -    instruction.vex_reg = RegSpec { +    instruction.regs[3] = RegSpec {          bank: RegisterBank::X,          num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111,      }; @@ -125,7 +125,7 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A      read_vex_instruction(m, words, instruction, p)?;      instruction.length = words.offset() as u8; -    instruction.vex_reg.num &= 0b0111; // ignore bit 4 in 32-bit mode +    instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(())  } @@ -138,7 +138,7 @@ pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arc          0x03 => VEXOpcodePrefix::PrefixF2,          _ => { unreachable!("p is two bits"); }      }; -    instruction.vex_reg = RegSpec { +    instruction.regs[3] = RegSpec {          bank: RegisterBank::X,          num: ((vex_byte >> 3) & 0b1111) ^ 0b1111,      }; @@ -146,7 +146,7 @@ pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arc      read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p)?;      instruction.length = words.offset() as u8; -    instruction.vex_reg.num &= 0b0111; // ignore bit 4 in 32-bit mode +    instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(())  } @@ -173,9 +173,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -206,9 +206,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -236,9 +236,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -266,9 +266,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -299,9 +299,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::X); -            instruction.vex_reg.bank = 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)?; @@ -338,9 +338,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      unreachable!("r is only three bits");                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts(modrm & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -351,7 +351,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::VMOVSS_10 |          VEXOperandCode::VMOVSD_10 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -362,7 +362,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.operand_count = 3;                  },                  other => { -                    if instruction.vex_reg.num != 0 { +                    if instruction.regs[3].num != 0 {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } @@ -380,7 +380,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::VMOVSS_11 |          VEXOperandCode::VMOVSD_11 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[2] = OperandSpec::RegRRR; @@ -391,7 +391,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      instruction.operand_count = 3;                  },                  other => { -                    if instruction.vex_reg.num != 0 { +                    if instruction.regs[3].num != 0 {                          instruction.opcode = Opcode::Invalid;                          return Err(DecodeError::InvalidOperand);                      } @@ -415,7 +415,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.mem_size = 4;                  Opcode::VMOVLPS              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -431,7 +431,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  instruction.mem_size = 8;                  Opcode::VMOVHPS              }; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -444,12 +444,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          },          VEXOperandCode::Ev_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = mem_oper; @@ -477,12 +477,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          },          VEXOperandCode::G_xmm_Ed => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -494,12 +494,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ed_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = mem_oper; @@ -511,16 +511,16 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::VCVT_Gd_Ed_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E(words instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4)?;              if let OperandSpec::RegMMM = mem_oper { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 4;              } @@ -530,16 +530,16 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::VCVT_Gd_Eq_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E(words, instruction, modrm, 4)?;              if let OperandSpec::RegMMM = mem_oper { -                instruction.modrm_mmm.bank = RegisterBank::X; +                instruction.regs[1].bank = RegisterBank::X;              } else {                  instruction.mem_size = 8;              } @@ -550,12 +550,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          op @ VEXOperandCode::E_G_xmm |          op @ VEXOperandCode::M_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              match (op, mem_oper) { @@ -583,12 +583,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -600,12 +600,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -617,12 +617,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Ud_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -636,12 +636,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::E_G_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -655,12 +655,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::E_xmm_G_ymm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -675,12 +675,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::Gd_U_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -692,12 +692,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::Gd_U_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              if mem_oper != OperandSpec::RegMMM { @@ -712,7 +712,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::G_M_xmm |          op @ VEXOperandCode::G_U_xmm |          op @ VEXOperandCode::G_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -730,7 +730,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -748,12 +748,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_xmm_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -765,12 +765,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_xmm_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -783,7 +783,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          op @ VEXOperandCode::G_ymm_M_xmm |          op @ VEXOperandCode::G_ymm_E_xmm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -793,7 +793,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOperand);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -811,12 +811,12 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_ymm_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -830,7 +830,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::E_G_ymm |          op @ VEXOperandCode::M_G_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -844,7 +844,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -858,7 +858,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          op @ VEXOperandCode::G_M_ymm |          op @ VEXOperandCode::G_E_ymm => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  instruction.opcode = Opcode::Invalid;                  return Err(DecodeError::InvalidOperand);              } @@ -872,7 +872,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      /* and this is always accepted */                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -891,9 +891,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOperand);                  }              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -906,9 +906,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_ymm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -926,9 +926,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if modrm & 0xc0 == 0xc0 {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex; @@ -944,7 +944,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if modrm & 0xc0 == 0xc0 {                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -962,7 +962,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -982,7 +982,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_xmm_Ed => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E(words, instruction, modrm, 4)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -996,7 +996,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1012,9 +1012,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_ymm_V_ymm_E_xmm_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1033,7 +1033,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  return Err(DecodeError::InvalidOperand);              } -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = mem_oper; @@ -1048,10 +1048,10 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::G_Ex_V_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?; -            instruction.sib_index.bank = RegisterBank::X; +            instruction.regs[2].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1063,11 +1063,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_Ey_V_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_ymm(words, instruction, modrm)?; -            instruction.vex_reg.bank = RegisterBank::X; -            instruction.sib_index.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::X; +            instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1079,11 +1079,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_Ey_V_ymm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?; -            instruction.vex_reg.bank = RegisterBank::Y; -            instruction.sib_index.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y; +            instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1100,9 +1100,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::G_V_E => {              let modrm = read_modrm(words)?;              let (opwidth, bank) = (4, RegisterBank::D); -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1116,9 +1116,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::G_E_V => {              let modrm = read_modrm(words)?;              let (opwidth, bank) = (4, RegisterBank::D); -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; @@ -1132,7 +1132,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          VEXOperandCode::G_E_Ib => {              let modrm = read_modrm(words)?;              let (opwidth, bank) = (4, RegisterBank::D); -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1163,7 +1163,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  }              };              let (opwidth, bank) = (4, RegisterBank::D); -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              let mem_oper = read_E(words, instruction, modrm, opwidth)?;              instruction.operands[0] = OperandSpec::RegVex; @@ -1172,7 +1172,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              if mem_oper != OperandSpec::RegMMM {                  instruction.mem_size = opwidth;              } -            instruction.vex_reg.bank = bank; +            instruction.regs[3].bank = bank;              Ok(())          }          VEXOperandCode::MXCSR => { @@ -1201,11 +1201,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_E_xmm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1219,11 +1219,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              Ok(())          }          VEXOperandCode::G_E_ymm_imm8 => { -            if instruction.vex_reg.num != 0 { +            if instruction.regs[3].num != 0 {                  return Err(DecodeError::InvalidOperand);              }              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1238,9 +1238,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_ymm_ymm4 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_ymm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1255,9 +1255,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_E_xmm_xmm4 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            instruction.vex_reg.bank = RegisterBank::X; +            instruction.regs[3].bank = RegisterBank::X;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1272,9 +1272,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_ymm_E_xmm => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            instruction.vex_reg.bank = RegisterBank::Y; +            instruction.regs[3].bank = RegisterBank::Y;              let mem_oper = read_E_xmm(words, instruction, modrm)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; @@ -1287,9 +1287,9 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          VEXOperandCode::G_V_xmm_Ev_imm8 => {              let modrm = read_modrm(words)?; -            instruction.modrm_rrr = +            instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            instruction.vex_reg.bank = 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)?;              instruction.operands[0] = OperandSpec::RegRRR; diff --git a/src/shared/evex.in b/src/shared/evex.in index 17c9bb7..9c48d33 100644 --- a/src/shared/evex.in +++ b/src/shared/evex.in @@ -5,16 +5,14 @@ use super::OperandSpec;  // as an `EVEX` instruction, but for other modes we can only make this  // determination when reading a `bound`'s `modrm` byte.  #[inline(never)] -pub(crate) fn read_evex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, mut length: u8, evex_byte_one: Option<u8>) -> Result<(), DecodeError> { +pub(crate) fn read_evex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, evex_byte_one: Option<u8>) -> Result<(), DecodeError> {      let evex_byte_one = if let Some(b) = evex_byte_one {        b      } else { -      length += 1; -      bytes.next().ok_or(DecodeError::ExhaustedInput)? +      words.next().ok().ok_or(DecodeError::ExhaustedInput)?      }; -    let evex_byte_two = bytes.next().ok_or(DecodeError::ExhaustedInput)?; -    let evex_byte_three = bytes.next().ok_or(DecodeError::ExhaustedInput)?; -    length += 2; +    let evex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?; +    let evex_byte_three = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = evex_byte_two & 0x03;      let m = evex_byte_one & 0x03;      if m == 0 { @@ -41,15 +39,14 @@ pub(crate) fn read_evex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut I      let vp = ((evex_byte_three >> 3) & 1) << 4;      let vvvvv = ((evex_byte_two >> 3) & 0b1111) | vp; -    instruction.vex_reg = RegSpec { +    instruction.regs[3] = RegSpec {          bank: RegisterBank::X,          num: vvvvv ^ 0b11111 // `vvvvv` is provided in inverted form      };      instruction.prefixes.evex_from(evex_byte_one, evex_byte_two, evex_byte_three); -    let opc = bytes.next().ok_or(DecodeError::ExhaustedInput)?; -    length += 1; +    let opc = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let table_idx = ((m << 2) | p) as usize;      let table = generated::TABLES[table_idx];      if table as *const [_]  == &generated::DUMMY[..] as *const [_] { @@ -65,7 +62,7 @@ pub(crate) fn read_evex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut I      if let Ok(entry) = table.binary_search_by_key(&opc, |x| x.0) {        let (opcode, operand_code) = table[entry].1[index_lower];        instruction.opcode = opcode; -      read_evex_operands(bytes, instruction, operand_code, &mut length)?; +      read_evex_operands(words, instruction, operand_code)?;        if instruction.prefixes.evex_unchecked().vex().compressed_disp() {          let overridden_size = match instruction.opcode {            Opcode::VPEXPANDB => Some(1), @@ -93,7 +90,6 @@ pub(crate) fn read_evex<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut I      } else {        return Err(DecodeError::InvalidOpcode);      } -    instruction.length = length;      Ok(())  } @@ -114,7 +110,7 @@ fn deny_z(inst: &Instruction) -> Result<(), DecodeError> {  }  fn deny_vex_reg(inst: &Instruction) -> Result<(), DecodeError> { -  if inst.vex_reg.num != 0 { +  if inst.regs[3].num != 0 {      Err(DecodeError::InvalidOperand)    } else {      Ok(()) @@ -157,21 +153,21 @@ fn apply_broadcast(inst: &mut Instruction, item_size: u8, reg_size: u8) {  }  fn set_rrr(inst: &mut Instruction, modrm: u8) { -  inst.modrm_rrr.num = (modrm >> 3) & 7; +  inst.regs[0].num = (modrm >> 3) & 7;    if inst.prefixes.evex_unchecked().vex().r() { -    inst.modrm_rrr.num |= 8; +    inst.regs[0].num |= 8;    }    if inst.prefixes.evex_unchecked().rp() { -    inst.modrm_rrr.num |= 16; +    inst.regs[0].num |= 16;    }  }  fn set_reg_sizes(inst: &mut Instruction, size: RegisterBank) { -  inst.modrm_rrr.bank = size; -  inst.vex_reg.bank = size; +  inst.regs[0].bank = size; +  inst.regs[3].bank = size;    for i in 0..inst.operand_count {      if [OperandSpec::RegMMM, OperandSpec::RegMMM_maskmerge, OperandSpec::RegMMM_maskmerge_sae_noround].contains(&inst.operands[i as usize]) { -      inst.modrm_mmm.bank = size; +      inst.regs[1].bank = size;      }    }  } @@ -200,20 +196,20 @@ fn set_reg_sizes_from_ll(inst: &mut Instruction) -> Result<(), DecodeError> {    Ok(())  } -pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instruction: &mut Instruction, operand_code: generated::EVEXOperandCode, length: &mut u8) -> Result<(), DecodeError> { +pub(crate) fn read_evex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, operand_code: generated::EVEXOperandCode) -> Result<(), DecodeError> {    match operand_code {      generated::EVEXOperandCode::Gm_V_E_LL_imm8_sae_bcast => {        deny_vex_reg(instruction)?;        check_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -255,9 +251,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          return Err(DecodeError::InvalidOpcode);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -286,9 +282,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -312,9 +308,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        check_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -344,9 +340,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        check_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -403,9 +399,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        check_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -481,13 +477,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.opcode = Opcode::VREDUCEPD;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -517,13 +513,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -549,13 +545,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -583,9 +579,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = 8; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } @@ -599,11 +595,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      instruction.vex_reg.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      instruction.regs[3].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -612,7 +608,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -626,13 +622,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          (4, RegisterBank::D)        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      instruction.vex_reg.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      instruction.regs[3].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM { -        instruction.modrm_mmm.bank = bank; +        instruction.regs[1].bank = bank;          instruction.mem_size = 0;        } else {          instruction.mem_size = sz; @@ -662,13 +658,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          (4, RegisterBank::D)        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      instruction.vex_reg.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      instruction.regs[3].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM { -        instruction.modrm_mmm.bank = bank; +        instruction.regs[1].bank = bank;          instruction.mem_size = 0;        } else {          instruction.mem_size = sz; @@ -676,20 +672,20 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      }      generated::EVEXOperandCode::G_V_xmm_Ebd_imm8 => {        deny_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      instruction.vex_reg.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      instruction.regs[3].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM { -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;          instruction.mem_size = 0;        } else {          instruction.mem_size = 1; @@ -697,7 +693,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -707,9 +703,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = 8; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } @@ -729,9 +725,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        // specifically for vunpcklpd!!! probably need to reconsider.        apply_broadcast(instruction, 8, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -745,9 +741,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } @@ -764,9 +760,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } @@ -783,9 +779,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR;        instruction.operand_count = 2; @@ -800,10 +796,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = 4; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        // in specific support of vcomisd/vucomisd        if instruction.prefixes.evex_unchecked().broadcast() { @@ -822,10 +818,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = 8; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        // in specific support of vcomisd/vucomisd        if instruction.prefixes.evex_unchecked().broadcast() { @@ -847,9 +843,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.mem_size = 8;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -874,9 +870,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -888,10 +884,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            instruction.operands[0] = OperandSpec::RegRRR_maskmerge;            set_reg_sizes_from_ll(instruction)?;            if !instruction.prefixes.evex_unchecked().vex().w() { -            if instruction.modrm_rrr.bank == RegisterBank::Z { -              instruction.modrm_mmm.bank = RegisterBank::Y; -            } else if instruction.modrm_rrr.bank == RegisterBank::Y { -              instruction.modrm_mmm.bank = RegisterBank::X; +            if instruction.regs[0].bank == RegisterBank::Z { +              instruction.regs[1].bank = RegisterBank::Y; +            } else if instruction.regs[0].bank == RegisterBank::Y { +              instruction.regs[1].bank = RegisterBank::X;              }            }          } @@ -911,12 +907,12 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -933,8 +929,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 8, sz);          set_reg_sizes_from_ll(instruction)?;        } -      instruction.modrm_rrr.bank = RegisterBank::K; -      if instruction.modrm_rrr.num > 7 { +      instruction.regs[0].bank = RegisterBank::K; +      if instruction.regs[0].num > 7 {          return Err(DecodeError::InvalidOperand);        }      } @@ -945,9 +941,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -972,9 +968,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -1009,9 +1005,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1038,9 +1034,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1067,9 +1063,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1093,9 +1089,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1115,9 +1111,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper;        instruction.operand_count = 3; @@ -1142,9 +1138,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper;        instruction.operand_count = 3; @@ -1173,9 +1169,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper;        instruction.operand_count = 3; @@ -1209,9 +1205,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 4, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1273,9 +1269,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 4, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -1292,12 +1288,12 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 4, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -1312,12 +1308,12 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 8, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -1338,11 +1334,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 4, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -1370,9 +1366,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -1399,9 +1395,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;        } else { @@ -1432,9 +1428,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;        } else { @@ -1462,9 +1458,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          if instruction.opcode == Opcode::VMINSS || instruction.opcode == Opcode::VMAXSS {            instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; @@ -1493,18 +1489,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            // sae sets this to `vcvtps2ph ymm, zmm, imm8` -          instruction.modrm_mmm.bank = RegisterBank::Y; -          instruction.modrm_rrr.bank = RegisterBank::Z; +          instruction.regs[1].bank = RegisterBank::Y; +          instruction.regs[0].bank = RegisterBank::Z;            instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround;          } else { -          instruction.modrm_mmm.bank = RegisterBank::X; -          instruction.modrm_rrr.bank = RegisterBank::X; +          instruction.regs[1].bank = RegisterBank::X; +          instruction.regs[0].bank = RegisterBank::X;            instruction.operands[0] = OperandSpec::RegMMM_maskmerge;          }        } else { @@ -1512,12 +1508,12 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            return Err(DecodeError::InvalidOperand);          } else {            instruction.mem_size = 8; -          instruction.modrm_rrr.bank = RegisterBank::X; +          instruction.regs[0].bank = RegisterBank::X;            instruction.operands[0] = mem_oper.masked();          }        }        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;      } @@ -1526,30 +1522,30 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            // sae sets this to `vcvtps2ph ymm, zmm, imm8` -          instruction.modrm_mmm.bank = RegisterBank::Y; -          instruction.modrm_rrr.bank = RegisterBank::Z; +          instruction.regs[1].bank = RegisterBank::Y; +          instruction.regs[0].bank = RegisterBank::Z;            instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround;          } else { -          instruction.modrm_mmm.bank = RegisterBank::X; -          instruction.modrm_rrr.bank = RegisterBank::Y; +          instruction.regs[1].bank = RegisterBank::X; +          instruction.regs[0].bank = RegisterBank::Y;            instruction.operands[0] = OperandSpec::RegMMM_maskmerge;          }        } else {          if instruction.prefixes.evex_unchecked().broadcast() {            return Err(DecodeError::InvalidOperand);          } else { -          instruction.modrm_rrr.bank = RegisterBank::Y; +          instruction.regs[0].bank = RegisterBank::Y;            instruction.operands[0] = mem_oper.masked();          }        }        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.mem_size = 16;        instruction.operand_count = 3; @@ -1559,10 +1555,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Z; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            instruction.operands[0] = OperandSpec::RegMMM_maskmerge_sae_noround; @@ -1578,7 +1574,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.mem_size = 32;        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;      } @@ -1591,11 +1587,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          Opcode::VINSERTI32X4        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Z; -      instruction.vex_reg.bank = RegisterBank::Z; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z; +      instruction.regs[3].bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1604,7 +1600,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR.masked();        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -1617,11 +1613,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          Opcode::VINSERTI32X4        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Y; -      instruction.vex_reg.bank = RegisterBank::Y; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y; +      instruction.regs[3].bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1630,7 +1626,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR.masked();        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -1645,16 +1641,16 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Z; -      instruction.vex_reg.bank = RegisterBank::Z; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z; +      instruction.regs[3].bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.mem_size = 32;        instruction.operands[0] = OperandSpec::RegRRR.masked();        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -1670,14 +1666,14 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Z; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?;        instruction.mem_size = 32;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;      } @@ -1685,10 +1681,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1702,10 +1698,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1719,10 +1715,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1736,10 +1732,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1753,10 +1749,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1770,10 +1766,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1787,10 +1783,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1804,10 +1800,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1822,10 +1818,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1839,10 +1835,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1856,10 +1852,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1873,10 +1869,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -1891,10 +1887,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::Z;        instruction.mem_size = 32;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1905,10 +1901,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        instruction.mem_size = 16;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1919,10 +1915,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        instruction.mem_size = 16;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1933,10 +1929,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        instruction.mem_size = 8;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1947,10 +1943,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        instruction.mem_size = 8;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1961,10 +1957,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        instruction.mem_size = 4;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1975,10 +1971,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        instruction.mem_size = 4;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -1989,10 +1985,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        instruction.mem_size = 2;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -2003,10 +1999,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        instruction.mem_size = 8;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; @@ -2017,10 +2013,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -2035,10 +2031,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -2060,10 +2056,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } else { @@ -2085,10 +2081,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } else { @@ -2110,10 +2106,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } else { @@ -2131,10 +2127,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.opcode = Opcode::VBROADCASTSD;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -2152,10 +2148,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.opcode = Opcode::VBROADCASTSD;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Y;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -2170,10 +2166,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -2197,18 +2193,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        if instruction.prefixes.evex_unchecked().lp() { -        instruction.modrm_rrr.bank = RegisterBank::Z; +        instruction.regs[0].bank = RegisterBank::Z;        } else { -        instruction.modrm_rrr.bank = RegisterBank::Y; +        instruction.regs[0].bank = RegisterBank::Y;        } -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.mem_size = 16;        instruction.operands[0] = mem_oper.masked();        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;      } @@ -2221,15 +2217,15 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          Opcode::VINSERTF32X4        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        set_reg_sizes_from_ll(instruction)?; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.mem_size = 16;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -2237,10 +2233,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        set_reg_sizes_from_ll(instruction)?; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.mem_size = 16;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex; @@ -2251,10 +2247,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        set_reg_sizes_from_ll(instruction)?; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.mem_size = 16;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex; @@ -2272,10 +2268,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          };        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        set_reg_sizes_from_ll(instruction)?; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.mem_size = 16;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex; @@ -2286,20 +2282,20 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::D; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::D; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM { -        instruction.modrm_mmm.bank = RegisterBank::X; +        instruction.regs[1].bank = RegisterBank::X;        } else {          return Err(DecodeError::InvalidOperand);        }        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;      } @@ -2307,13 +2303,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM { -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;        } else {          instruction.mem_size = 2;        } @@ -2321,7 +2317,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;      } @@ -2330,10 +2326,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; @@ -2350,10 +2346,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; @@ -2370,10 +2366,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper != OperandSpec::RegMMM {          instruction.mem_size = 8; @@ -2387,23 +2383,23 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().vex().w() {          if isa_has_qwords() {            instruction.opcode = Opcode::VMOVQ;          }          if mem_oper == OperandSpec::RegMMM { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else {            instruction.mem_size = DEFAULT_EVEX_REGISTER_WIDTH;          }        } else {          if mem_oper == OperandSpec::RegMMM { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          } else {            instruction.mem_size = 4;          } @@ -2417,23 +2413,23 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().vex().w() {          if isa_has_qwords() {            instruction.opcode = Opcode::VMOVQ;          }          if mem_oper == OperandSpec::RegMMM { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else {            instruction.mem_size = DEFAULT_EVEX_REGISTER_WIDTH;          }        } else {          if mem_oper == OperandSpec::RegMMM { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          } else {            instruction.mem_size = 4;          } @@ -2461,9 +2457,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 4, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2473,10 +2469,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL_bcast_W1 => { @@ -2487,9 +2483,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 8, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2499,10 +2495,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL_bcast_W0 => { @@ -2513,9 +2509,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 4, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2525,10 +2521,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Em_G_LL => { @@ -2555,9 +2551,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2583,9 +2579,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2593,7 +2589,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        } else {          return Err(DecodeError::InvalidOperand);        } @@ -2614,9 +2610,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2624,7 +2620,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::K; +        instruction.regs[1].bank = RegisterBank::K;        } else {          return Err(DecodeError::InvalidOperand);        } @@ -2638,9 +2634,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2648,7 +2644,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::K; +        instruction.regs[1].bank = RegisterBank::K;        } else {          return Err(DecodeError::InvalidOperand);        } @@ -2662,9 +2658,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2672,7 +2668,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::K; +        instruction.regs[1].bank = RegisterBank::K;        } else {          return Err(DecodeError::InvalidOperand);        } @@ -2685,9 +2681,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2705,9 +2701,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2725,9 +2721,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -2741,9 +2737,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2757,10 +2753,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          (false, true) => (RegisterBank::X, RegisterBank::Y, 32),          (false, false) => (RegisterBank::X, RegisterBank::X, 16),        }; -      instruction.modrm_rrr.bank = r_sz; +      instruction.regs[0].bank = r_sz;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = m_sz; +        instruction.regs[1].bank = m_sz;        } else {          apply_broadcast(instruction, 4, m_data_sz);        } @@ -2783,9 +2779,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            return Err(DecodeError::InvalidOpcode); @@ -2811,9 +2807,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            return Err(DecodeError::InvalidOpcode); @@ -2835,9 +2831,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            return Err(DecodeError::InvalidOpcode); @@ -2866,9 +2862,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2877,9 +2873,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;          if instruction.prefixes.evex_unchecked().vex().w() { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          }        } else {          return Err(DecodeError::InvalidOperand); @@ -2894,9 +2890,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2904,7 +2900,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;        } else {          return Err(DecodeError::InvalidOperand);        } @@ -2923,9 +2919,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2933,7 +2929,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::X; +        instruction.regs[1].bank = RegisterBank::X;        } else {          instruction.mem_size = 8;        } @@ -2947,9 +2943,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2957,7 +2953,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::X; +        instruction.regs[1].bank = RegisterBank::X;        } else {          instruction.mem_size = 4;        } @@ -2971,9 +2967,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -2981,7 +2977,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::X; +        instruction.regs[1].bank = RegisterBank::X;        } else {          instruction.mem_size = 2;        } @@ -2995,9 +2991,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -3005,7 +3001,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        set_reg_sizes_from_ll(instruction)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0; -        instruction.modrm_mmm.bank = RegisterBank::X; +        instruction.regs[1].bank = RegisterBank::X;        } else {          instruction.mem_size = 1;        } @@ -3019,9 +3015,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3047,15 +3043,15 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -3066,16 +3062,16 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm);        if instruction.prefixes.evex_unchecked().vex().w() { -        instruction.modrm_rrr.bank = DEFAULT_EVEX_REGISTER_SIZE; +        instruction.regs[0].bank = DEFAULT_EVEX_REGISTER_SIZE;        } else { -        instruction.modrm_rrr.bank = RegisterBank::D; +        instruction.regs[0].bank = RegisterBank::D;        } -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        if instruction.prefixes.evex_unchecked().broadcast() { @@ -3122,9 +3118,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3179,9 +3175,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3205,16 +3201,16 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 4, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3228,9 +3224,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 4, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3261,9 +3257,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3282,9 +3278,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = sz; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3294,10 +3290,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL => { @@ -3315,9 +3311,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } @@ -3327,10 +3323,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Maskm_V_Eq_xmm_imm8_sae_W1 => { @@ -3338,9 +3334,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        ensure_W(instruction, 1)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -3356,15 +3352,15 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;        set_reg_sizes(instruction, RegisterBank::X); -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Maskm_V_Ed_xmm_imm8_sae_W0 => { @@ -3372,9 +3368,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        ensure_W(instruction, 0)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -3390,15 +3386,15 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;        set_reg_sizes(instruction, RegisterBank::X); -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL_imm8 => { @@ -3418,24 +3414,24 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_Ed_xmm_imm8 => { @@ -3451,9 +3447,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          };        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        } else { @@ -3465,15 +3461,15 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;        set_reg_sizes(instruction, RegisterBank::X); -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_E_LL_imm8_bcast => { @@ -3501,23 +3497,23 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL_imm8_sae_bcast_W0 => { @@ -3540,13 +3536,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3561,10 +3557,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        } else {          set_reg_sizes_from_ll(instruction)?;        } -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Mask_V_E_LL_imm8_bcast => { @@ -3592,24 +3588,24 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;        }        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;        set_reg_sizes_from_ll(instruction)?; -      if instruction.modrm_rrr.num >= 8 { +      if instruction.regs[0].num >= 8 {          return Err(DecodeError::InvalidOperand);        } else { -        instruction.modrm_rrr.bank = RegisterBank::K; +        instruction.regs[0].bank = RegisterBank::K;        }      }      generated::EVEXOperandCode::Opcode_72_Gm_E_LL_imm8_bcast => { @@ -3617,7 +3613,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        let sz = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        let rrr = (modrm >> 3) & 7;        let item_size = if instruction.prefixes.evex_unchecked().vex().w() { @@ -3648,10 +3644,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, item_size, sz); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegVex_maskmerge;        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -3681,13 +3677,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        };  */ -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3718,13 +3714,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.opcode        }; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3742,13 +3738,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.mem_size = sz;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3766,13 +3762,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          apply_broadcast(instruction, 8, sz);        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3783,13 +3779,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3800,13 +3796,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = regs_size(instruction); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3820,13 +3816,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        apply_broadcast(instruction, 8, sz); -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -3837,10 +3833,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Z)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Z)?; +      instruction.regs[0].bank = RegisterBank::Y;        instruction.operands[1] = mem_oper;        if instruction.prefixes.evex_unchecked().broadcast() {          if mem_oper != OperandSpec::RegMMM { @@ -3860,10 +3856,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Y)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Y)?; +      instruction.regs[0].bank = RegisterBank::X;        instruction.operands[1] = mem_oper;        if instruction.prefixes.evex_unchecked().broadcast() {          if mem_oper != OperandSpec::RegMMM { @@ -3871,8 +3867,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            apply_broadcast(instruction, 8, 32);          } else {            instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; -          instruction.modrm_rrr.bank = RegisterBank::Y; -          instruction.modrm_mmm.bank = RegisterBank::Z; +          instruction.regs[0].bank = RegisterBank::Y; +          instruction.regs[1].bank = RegisterBank::Z;          }        } else {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge; @@ -3885,10 +3881,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; -      instruction.modrm_rrr.bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X;        instruction.operands[1] = mem_oper;        if instruction.prefixes.evex_unchecked().broadcast() {          if mem_oper != OperandSpec::RegMMM { @@ -3896,8 +3892,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            apply_broadcast(instruction, 8, 16);          } else {            instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae; -          instruction.modrm_rrr.bank = RegisterBank::Y; -          instruction.modrm_mmm.bank = RegisterBank::Z; +          instruction.regs[0].bank = RegisterBank::Y; +          instruction.regs[1].bank = RegisterBank::Z;          }        } else {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge; @@ -3921,9 +3917,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -3940,11 +3936,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            } else {              instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;            } -          instruction.modrm_rrr.bank = RegisterBank::Z; +          instruction.regs[0].bank = RegisterBank::Z;            if instruction.prefixes.evex_unchecked().vex().w() { -            instruction.modrm_mmm.bank = RegisterBank::Z; +            instruction.regs[1].bank = RegisterBank::Z;            } else { -            instruction.modrm_mmm.bank = RegisterBank::Y; +            instruction.regs[1].bank = RegisterBank::Y;            }          } else {            let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() { @@ -3962,8 +3958,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio                Err(DecodeError::InvalidOperand),              ][lp]?            }; -          instruction.modrm_rrr.bank = r_sz; -          instruction.modrm_mmm.bank = m_sz; +          instruction.regs[0].bank = r_sz; +          instruction.regs[1].bank = m_sz;          }        } else {          let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() { @@ -3981,7 +3977,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              Err(DecodeError::InvalidOperand),            ][lp]?          }; -        instruction.modrm_rrr.bank = r_sz; +        instruction.regs[0].bank = r_sz;          if instruction.prefixes.evex_unchecked().vex().w() {            apply_broadcast(instruction, 8, m_sz);          } else { @@ -4001,9 +3997,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          instruction.opcode = Opcode::VCVTTPD2UQQ;        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -4012,11 +4008,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().broadcast() {            instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround; -          instruction.modrm_rrr.bank = RegisterBank::Z; +          instruction.regs[0].bank = RegisterBank::Z;            if instruction.opcode == Opcode::VCVTTPD2UQQ { -            instruction.modrm_mmm.bank = RegisterBank::Z; +            instruction.regs[1].bank = RegisterBank::Z;            } else { -            instruction.modrm_mmm.bank = RegisterBank::Y; +            instruction.regs[1].bank = RegisterBank::Y;            }          } else {            let (r_sz, m_sz) = match ( @@ -4028,8 +4024,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              (true, false) => (RegisterBank::Y, RegisterBank::X),              (false, false) => (RegisterBank::X, RegisterBank::X),            }; -          instruction.modrm_rrr.bank = r_sz; -          instruction.modrm_mmm.bank = m_sz; +          instruction.regs[0].bank = r_sz; +          instruction.regs[1].bank = m_sz;          }        } else {          let (r_sz, m_sz) = match ( @@ -4041,7 +4037,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            (false, true) => (RegisterBank::Z, 32),            (false, false) => (RegisterBank::X, 8),          }; -        instruction.modrm_rrr.bank = r_sz; +        instruction.regs[0].bank = r_sz;          if instruction.opcode == Opcode::VCVTPS2PD {            apply_broadcast(instruction, 4, m_sz);          } else { @@ -4061,9 +4057,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -4077,11 +4073,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          if instruction.prefixes.evex_unchecked().broadcast() {            instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;            if instruction.prefixes.evex_unchecked().vex().w() { -            instruction.modrm_rrr.bank = RegisterBank::Y; +            instruction.regs[0].bank = RegisterBank::Y;            } else { -            instruction.modrm_rrr.bank = RegisterBank::Z; +            instruction.regs[0].bank = RegisterBank::Z;            } -          instruction.modrm_mmm.bank = RegisterBank::Z; +          instruction.regs[1].bank = RegisterBank::Z;          } else {            let (r_sz, m_sz) = if instruction.prefixes.evex_unchecked().vex().w() {              [ @@ -4098,8 +4094,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio                Err(DecodeError::InvalidOperand),              ][lp]?            }; -          instruction.modrm_rrr.bank = r_sz; -          instruction.modrm_mmm.bank = m_sz; +          instruction.regs[0].bank = r_sz; +          instruction.regs[1].bank = m_sz;          }        } else {          let (r_sz, m_sz, item_sz) = if instruction.prefixes.evex_unchecked().vex().w() { @@ -4117,7 +4113,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              Err(DecodeError::InvalidOperand),            ][lp]?          }; -        instruction.modrm_rrr.bank = r_sz; +        instruction.regs[0].bank = r_sz;          apply_broadcast(instruction, item_sz, m_sz);        }      } @@ -4125,9 +4121,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -4149,11 +4145,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;            }            if instruction.prefixes.evex_unchecked().vex().w() { -            instruction.modrm_rrr.bank = RegisterBank::Y; +            instruction.regs[0].bank = RegisterBank::Y;            } else { -            instruction.modrm_rrr.bank = RegisterBank::Z; +            instruction.regs[0].bank = RegisterBank::Z;            } -          instruction.modrm_mmm.bank = RegisterBank::Z; +          instruction.regs[1].bank = RegisterBank::Z;          } else {            let (r_sz, m_sz) = match (              instruction.prefixes.evex_unchecked().vex().l(), @@ -4164,8 +4160,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              (true, false) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::X } else { RegisterBank::Y }, RegisterBank::Y),              (false, false) => (RegisterBank::X, RegisterBank::X),            }; -          instruction.modrm_rrr.bank = r_sz; -          instruction.modrm_mmm.bank = m_sz; +          instruction.regs[0].bank = r_sz; +          instruction.regs[1].bank = m_sz;          }        } else {          let (r_sz, m_sz) = match ( @@ -4178,7 +4174,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            (false, true) => (if instruction.prefixes.evex_unchecked().vex().w() { RegisterBank::Y } else { RegisterBank::Z }, 64),            (false, false) => (RegisterBank::X, 16),          }; -        instruction.modrm_rrr.bank = r_sz; +        instruction.regs[0].bank = r_sz;          if instruction.prefixes.evex_unchecked().vex().w() {            apply_broadcast(instruction, 8, m_sz);          } else { @@ -4196,9 +4192,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_vex_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -4218,11 +4214,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;            }            if instruction.opcode == Opcode::VCVTDQ2PS && !instruction.prefixes.evex_unchecked().vex().w() { -            instruction.modrm_rrr.bank = RegisterBank::Z; +            instruction.regs[0].bank = RegisterBank::Z;            } else { -            instruction.modrm_rrr.bank = RegisterBank::Y; +            instruction.regs[0].bank = RegisterBank::Y;            } -          instruction.modrm_mmm.bank = RegisterBank::Z; +          instruction.regs[1].bank = RegisterBank::Z;          } else {            let (r_sz, m_sz) = match (              instruction.prefixes.evex_unchecked().vex().l(), @@ -4233,8 +4229,8 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio              (true, false) => (RegisterBank::X, RegisterBank::Y),              (false, false) => (RegisterBank::X, RegisterBank::X),            }; -          instruction.modrm_rrr.bank = r_sz; -          instruction.modrm_mmm.bank = m_sz; +          instruction.regs[0].bank = r_sz; +          instruction.regs[1].bank = m_sz;          }        } else {          let (r_sz, m_sz) = match ( @@ -4246,7 +4242,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            (false, true) => (RegisterBank::Y, 64),            (false, false) => (RegisterBank::X, 16),          }; -        instruction.modrm_rrr.bank = r_sz; +        instruction.regs[0].bank = r_sz;          apply_broadcast(instruction, 8, m_sz);        } @@ -4261,10 +4257,10 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Z)?; -      instruction.modrm_rrr.bank = RegisterBank::Y; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Z)?; +      instruction.regs[0].bank = RegisterBank::Y;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;        } else { @@ -4281,9 +4277,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex; @@ -4317,9 +4313,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        instruction.operands[1] = OperandSpec::RegVex; @@ -4353,9 +4349,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          }        } -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::Z)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::Z)?;        instruction.operands[1] = mem_oper;        instruction.operand_count = 2; @@ -4392,9 +4388,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;        } else { @@ -4410,9 +4406,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;        } else { @@ -4422,7 +4418,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio          return Err(DecodeError::InvalidOperand);        }        instruction.operands[1] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -4432,13 +4428,13 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        deny_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper;        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3; @@ -4449,14 +4445,14 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio            instruction.opcode = Opcode::VPEXTRD;          }          if let OperandSpec::RegMMM = mem_oper { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else {            instruction.mem_size = DEFAULT_EVEX_REGISTER_WIDTH;          }        } else {          instruction.opcode = Opcode::VPEXTRD;          if let OperandSpec::RegMMM = mem_oper { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          } else {            instruction.mem_size = 4;          } @@ -4466,19 +4462,19 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      instruction.vex_reg.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      instruction.regs[3].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper;        if mem_oper == OperandSpec::RegMMM {          if instruction.prefixes.evex_unchecked().vex().w() { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          }          if instruction.prefixes.evex_unchecked().vex().w() {            if instruction.prefixes.evex_unchecked().broadcast() { @@ -4507,18 +4503,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        deny_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper;        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;        if let OperandSpec::RegMMM = mem_oper { -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;        } else {          instruction.mem_size = 4;        } @@ -4527,18 +4523,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        deny_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper;        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;        if let OperandSpec::RegMMM = mem_oper { -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;        } else {          instruction.mem_size = 2;        } @@ -4547,18 +4543,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_vex_reg(instruction)?;        deny_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::X; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::X; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper;        instruction.operands[1] = OperandSpec::RegRRR; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[2] = OperandSpec::ImmU8;        instruction.operand_count = 3;        if let OperandSpec::RegMMM = mem_oper { -        instruction.modrm_mmm.bank = RegisterBank::D; +        instruction.regs[1].bank = RegisterBank::D;        } else {          instruction.mem_size = 1;        } @@ -4566,9 +4562,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio      generated::EVEXOperandCode::Gm_V_Ed_xmm_imm8_sae => {        check_mask_reg(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        let item_size = if instruction.prefixes.evex_unchecked().vex().w() {          if instruction.opcode == Opcode::VRANGESS { @@ -4605,16 +4601,16 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4;        set_reg_sizes(instruction, RegisterBank::X);      }      generated::EVEXOperandCode::Gm_V_E_xmm_imm8_sae => { -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if let OperandSpec::RegMMM = mem_oper {          /* no mem size */        } else{ @@ -4627,7 +4623,7 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        }        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; -      instruction.imm = read_imm_unsigned(bytes, 1, length)?; +      instruction.imm = read_imm_unsigned(words, 1)?;        instruction.operands[3] = OperandSpec::ImmU8;        instruction.operand_count = 4; @@ -4636,11 +4632,11 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio      generated::EVEXOperandCode::Gm_V_zmm_M_xmm_W0 => {        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      instruction.modrm_rrr.bank = RegisterBank::Z; -      instruction.vex_reg.bank = RegisterBank::Z; -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      instruction.regs[0].bank = RegisterBank::Z; +      instruction.regs[3].bank = RegisterBank::Z; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if let OperandSpec::RegMMM = mem_oper {          return Err(DecodeError::InvalidOperand);        } else{ @@ -4656,9 +4652,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        instruction.mem_size = 16; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if mem_oper == OperandSpec::RegMMM {          return Err(DecodeError::InvalidOperand);        } @@ -4673,9 +4669,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        if mem_oper == OperandSpec::RegMMM {          instruction.operands[1] = OperandSpec::RegVex; @@ -4695,9 +4691,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 1)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper.masked();        if mem_oper == OperandSpec::RegMMM {          instruction.operands[1] = OperandSpec::RegVex; @@ -4717,9 +4713,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR_maskmerge;        if mem_oper == OperandSpec::RegMMM {          instruction.operands[1] = OperandSpec::RegVex; @@ -4739,9 +4735,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper.masked();        if mem_oper == OperandSpec::RegMMM {          instruction.operands[1] = OperandSpec::RegVex; @@ -4761,9 +4757,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() && mem_oper == OperandSpec::RegMMM {          if (!instruction.prefixes.evex_unchecked().vex().w() || !isa_has_qwords()) && instruction.opcode == Opcode::VCVTSI2SD {            instruction.operands[0] = OperandSpec::RegRRR; @@ -4782,9 +4778,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        if mem_oper == OperandSpec::RegMMM {          instruction.mem_size = 0;          if instruction.prefixes.evex_unchecked().vex().w() { -          instruction.modrm_mmm.bank = DEFAULT_EVEX_REGISTER_SIZE; +          instruction.regs[1].bank = DEFAULT_EVEX_REGISTER_SIZE;          } else { -          instruction.modrm_mmm.bank = RegisterBank::D; +          instruction.regs[1].bank = RegisterBank::D;          }        } else {          if instruction.prefixes.evex_unchecked().vex().w() { @@ -4806,18 +4802,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae_noround;        } else {          instruction.operands[0] = OperandSpec::RegRRR;        }        if instruction.prefixes.evex_unchecked().vex().w() { -        instruction.modrm_rrr.bank = DEFAULT_EVEX_REGISTER_SIZE; +        instruction.regs[0].bank = DEFAULT_EVEX_REGISTER_SIZE;        } else { -        instruction.modrm_rrr.bank = RegisterBank::D; +        instruction.regs[0].bank = RegisterBank::D;        }        if mem_oper == OperandSpec::RegMMM { @@ -4833,18 +4829,18 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        check_mask_reg(instruction)?;        deny_z(instruction)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        if instruction.prefixes.evex_unchecked().broadcast() {          instruction.operands[0] = OperandSpec::RegRRR_maskmerge_sae;        } else {          instruction.operands[0] = OperandSpec::RegRRR;        }        if instruction.prefixes.evex_unchecked().vex().w() { -        instruction.modrm_rrr.bank = DEFAULT_EVEX_REGISTER_SIZE; +        instruction.regs[0].bank = DEFAULT_EVEX_REGISTER_SIZE;        } else { -        instruction.modrm_rrr.bank = RegisterBank::D; +        instruction.regs[0].bank = RegisterBank::D;        }        if mem_oper == OperandSpec::RegMMM { @@ -4861,9 +4857,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_z(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -4886,9 +4882,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_z(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = OperandSpec::RegRRR;        instruction.operands[1] = OperandSpec::RegVex;        instruction.operands[2] = mem_oper; @@ -4911,9 +4907,9 @@ pub(crate) fn read_evex_operands<T: Iterator<Item=u8>>(bytes: &mut T, instructio        deny_z(instruction)?;        ensure_W(instruction, 0)?; -      let modrm = read_modrm(bytes, length)?; +      let modrm = read_modrm(words)?;        set_rrr(instruction, modrm); -      let mem_oper = read_E_vex(bytes, instruction, modrm, length, RegisterBank::X)?; +      let mem_oper = read_E_vex(words, instruction, modrm, RegisterBank::X)?;        instruction.operands[0] = mem_oper;        instruction.operands[1] = OperandSpec::RegRRR;        instruction.operand_count = 2; diff --git a/test/long_mode/display.rs b/test/long_mode/display.rs index 4ef3f74..fc59427 100644 --- a/test/long_mode/display.rs +++ b/test/long_mode/display.rs @@ -12,7 +12,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr.display_with(DisplayStyle::C));              assert!( diff --git a/test/long_mode/evex_generated.rs b/test/long_mode/evex_generated.rs index 9c23e4b..dcb4e01 100644 --- a/test/long_mode/evex_generated.rs +++ b/test/long_mode/evex_generated.rs @@ -1,6 +1,6 @@  use std::fmt::Write; -use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction}; +use yaxpeax_arch::{AddressBase, Decoder, U8Reader, LengthedInstruction};  use yaxpeax_x86::long_mode::InstDecoder;  #[allow(dead_code)] @@ -9,7 +9,8 @@ fn test_invalid(data: &[u8]) {  }  fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { -    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) { +    let mut reader = U8Reader::new(data); +    if let Ok(inst) = decoder.decode(&mut reader) {          panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);      } else {          // this is fine @@ -26,7 +27,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr);              assert!( diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index cbd881c..1eedfec 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -16,7 +16,8 @@ fn test_invalid(data: &[u8]) {  }  fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { -    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    if let Ok(inst) = decoder.decode(&mut reader)  {          panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);      } else {          // this is fine @@ -32,7 +33,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr);              assert!( diff --git a/test/long_mode/operand.rs b/test/long_mode/operand.rs index f0300d6..77ce256 100644 --- a/test/long_mode/operand.rs +++ b/test/long_mode/operand.rs @@ -2,15 +2,15 @@ use yaxpeax_x86::long_mode::{Operand, RegSpec};  #[test]  fn register_widths() { -    assert_eq!(Operand::Register(RegSpec::rsp()).width(), 8); -    assert_eq!(Operand::Register(RegSpec::esp()).width(), 4); -    assert_eq!(Operand::Register(RegSpec::sp()).width(), 2); -    assert_eq!(Operand::Register(RegSpec::cl()).width(), 1); -    assert_eq!(Operand::Register(RegSpec::ch()).width(), 1); -    assert_eq!(Operand::Register(RegSpec::gs()).width(), 2); +    assert_eq!(Operand::Register(RegSpec::rsp()).width(), Some(8)); +    assert_eq!(Operand::Register(RegSpec::esp()).width(), Some(4)); +    assert_eq!(Operand::Register(RegSpec::sp()).width(), Some(2)); +    assert_eq!(Operand::Register(RegSpec::cl()).width(), Some(1)); +    assert_eq!(Operand::Register(RegSpec::ch()).width(), Some(1)); +    assert_eq!(Operand::Register(RegSpec::gs()).width(), Some(2));  }  #[test]  fn memory_widths() { -    assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), 8); +    assert_eq!(Operand::RegDeref(RegSpec::rsp()).width(), None);  } diff --git a/test/long_mode/reuse_test.rs b/test/long_mode/reuse_test.rs index 117f3fa..60a91e1 100644 --- a/test/long_mode/reuse_test.rs +++ b/test/long_mode/reuse_test.rs @@ -1989,17 +1989,21 @@ const INSTRUCTIONS: [&'static [u8]; 1982] = [  #[test]  fn test_against_leftover_data() {      use super::rand::{thread_rng, Rng}; +    use yaxpeax_arch::U8Reader;      let mut rng = thread_rng();      let decoder = InstDecoder::default();      for _ in 0..100000 {          let first_vec = INSTRUCTIONS[rng.gen_range(0..INSTRUCTIONS.len())]; -        let first_decode = decoder.decode(first_vec.to_vec().iter().cloned()).unwrap(); +        let mut first_reader = U8Reader::new(first_vec); +        let first_decode = decoder.decode(&mut first_reader).unwrap();          let second_vec = INSTRUCTIONS[rng.gen_range(0..INSTRUCTIONS.len())]; -        let mut reused_decode = decoder.decode(second_vec.to_vec().iter().cloned()).unwrap(); -        decoder.decode_into(&mut reused_decode, first_vec.to_vec().iter().cloned()).unwrap(); +        let mut second_reader = U8Reader::new(second_vec); +        let mut reused_decode = decoder.decode(&mut second_reader).unwrap(); +        let mut first_reader = U8Reader::new(first_vec); +        decoder.decode_into(&mut reused_decode, &mut first_reader).unwrap();          assert_eq!(first_decode, reused_decode);      } diff --git a/test/protected_mode/display.rs b/test/protected_mode/display.rs index 8426a0a..694c38c 100644 --- a/test/protected_mode/display.rs +++ b/test/protected_mode/display.rs @@ -12,7 +12,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr.display_with(DisplayStyle::C));              assert!( diff --git a/test/protected_mode/evex_generated.rs b/test/protected_mode/evex_generated.rs index 333c3c6..236edec 100644 --- a/test/protected_mode/evex_generated.rs +++ b/test/protected_mode/evex_generated.rs @@ -1,6 +1,6 @@  use std::fmt::Write; -use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction}; +use yaxpeax_arch::{AddressBase, Decoder, U8Reader, LengthedInstruction};  use yaxpeax_x86::protected_mode::InstDecoder;  #[allow(dead_code)] @@ -9,7 +9,8 @@ fn test_invalid(data: &[u8]) {  }  fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { -    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) { +    let mut reader = U8Reader::new(data); +    if let Ok(inst) = decoder.decode(&mut reader) {          panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);      } else {          // this is fine @@ -26,7 +27,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr);              assert!( diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 6e2ded9..9221e7d 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -13,7 +13,8 @@ fn test_invalid(data: &[u8]) {  }  fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { -    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    if let Ok(inst) = decoder.decode(&mut reader) {          panic!("decoded {:?} from {:02x?} under decoder {}", inst.opcode(), data, decoder);      } else {          // this is fine @@ -29,7 +30,8 @@ fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str      for b in data {          write!(hex, "{:02x}", b).unwrap();      } -    match decoder.decode(data.into_iter().map(|x| *x)) { +    let mut reader = yaxpeax_arch::U8Reader::new(data); +    match decoder.decode(&mut reader) {          Ok(instr) => {              let text = format!("{}", instr);              assert!( | 
