diff options
| author | iximeow <me@iximeow.net> | 2021-08-20 01:59:27 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-08-21 19:20:41 -0700 | 
| commit | b8cdf3ee6293f41b7b9bcb51d1177baeff24868d (patch) | |
| tree | e87bcb3834f31629da3caf81872065d8c2f5fef2 /src | |
| parent | 796e955cdc4f17d191b39da55ce704f90c6f37da (diff) | |
report barebones decoder annotation for vex-coded instructions
Diffstat (limited to 'src')
| -rw-r--r-- | src/long_mode/vex.rs | 269 | ||||
| -rw-r--r-- | src/protected_mode/vex.rs | 250 | ||||
| -rw-r--r-- | src/real_mode/vex.rs | 252 | 
3 files changed, 611 insertions, 160 deletions
diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 893d624..e19621d 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -7,6 +7,7 @@ use crate::long_mode::DecodeError;  use crate::long_mode::FieldDescription;  use crate::long_mode::RegSpec;  use crate::long_mode::RegisterBank; +use crate::long_mode::InnerDescription;  use crate::long_mode::Instruction;  use crate::long_mode::Opcode;  use crate::long_mode::read_modrm; @@ -106,6 +107,7 @@ pub(crate) fn three_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,      S: DescriptionSink<FieldDescription>,  >(words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() as u32 * 8;      let vex_byte_one = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03; @@ -116,7 +118,29 @@ pub(crate) fn three_byte_vex<          0x03 => VEXOpcodePrefix::PrefixF2,          _ => { unreachable!("p is two bits"); }      }; +    sink.record( +        vex_start + 8, +        vex_start + 9, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    );      let m = vex_byte_one & 0b11111; +    sink.record( +        vex_start + 0, +        vex_start + 4, +        InnerDescription::Misc(match m { +            0b00001 => "vex.mmmmm indicates opcode escape of 0f", +            0b00010 => "vex.mmmmm indicates opcode escape of 0f38", +            0b00011 => "vex.mmmmm indicates opcode escape of 0f3a", +            _ => "vex.mmmmm indicates illegal opcode escape and is invalid", +        }) +            .with_id(vex_start) +    );      let m = match m {          0b00001 => VEXOpcodeMap::Map0F,          0b00010 => VEXOpcodeMap::Map0F38, @@ -130,15 +154,81 @@ pub(crate) fn three_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111,      }; +    sink.record( +        vex_start + 11, +        vex_start + 14, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte_one & 0b10000000 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 6, +        vex_start + 6, +        InnerDescription::Misc(if vex_byte_one & 0b01000000 == 0 { +            "vex.x extends extends index reg (if used) by 0b1000" +        } else { +            "vex.x does not alter index reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 5, +        vex_start + 5, +        InnerDescription::Misc(if vex_byte_one & 0b00100000 == 0 { +            "vex.b extends extends base reg (if used) by 0b1000" +        } else { +            "vex.b does not alter base reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 10, +        vex_start + 10, +        InnerDescription::Misc(if vex_byte_two & 0b100 == 0 { +            "vex.l selects 128-bit vector sizes" +        } else { +            "vex.l selects 256-bit vector sizes" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 15, +        vex_start + 15, +        InnerDescription::Misc(if vex_byte_two & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); -    read_vex_instruction(m, words, instruction, p) +    sink.record( +        vex_start + 23, +        vex_start + 23, +        InnerDescription::Boundary("vex prefix ends/opcode begins") +            .with_id(vex_start + 23) +    ); + +    read_vex_instruction(m, words, instruction, p, sink)  }  pub(crate) fn two_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,      S: DescriptionSink<FieldDescription>,  >(words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() as u32 * 8;      let vex_byte = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte & 0x03;      let p = match p { @@ -152,12 +242,63 @@ pub(crate) fn two_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte >> 3) & 0b1111) ^ 0b1111,      }; + +    sink.record( +        vex_start + 0, +        vex_start + 1, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    ); + +    sink.record( +        vex_start + 3, +        vex_start + 6, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 2, +        vex_start + 2, +        InnerDescription::Misc(if vex_byte & 0b100 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c5(vex_byte); -    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p) +    sink.record( +        vex_start + 15, +        vex_start + 15, +        InnerDescription::Boundary("vex prefix ends/opcode begins") +            .with_id(vex_start + 15) +    ); + +    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p, sink)  } -fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode) -> Result<(), DecodeError> { +fn read_vex_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode, sink: &mut S) -> Result<(), DecodeError> {  //    println!("operand code: {:?}", operand_code);      match operand_code {          VEXOperandCode::VPS_71 => { @@ -360,7 +501,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -389,7 +530,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[2] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -426,7 +567,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -442,7 +583,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -464,7 +605,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::ImmU8; @@ -499,7 +640,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 8)?; +            let mem_oper = read_E(words, instruction, modrm, 8, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -516,7 +657,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -533,7 +674,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 8)?; +            let mem_oper = read_E(words, instruction, modrm, 8, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -550,7 +691,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -567,7 +708,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -586,7 +727,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Q); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -610,7 +751,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              match (op, mem_oper) {                  (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => {                      /* this is the only accepted operand */ @@ -643,7 +784,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -660,7 +801,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -677,7 +818,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -696,7 +837,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -715,7 +856,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -735,7 +876,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -752,7 +893,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -785,7 +926,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -808,7 +949,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -825,7 +966,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -848,7 +989,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -871,7 +1012,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -899,7 +1040,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -927,7 +1068,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -947,7 +1088,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -962,7 +1103,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -982,7 +1123,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -999,7 +1140,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1017,7 +1158,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1037,7 +1178,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1051,7 +1192,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 8)?; +            let mem_oper = read_E(words, instruction, modrm, 8, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1065,7 +1206,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1082,7 +1223,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1102,7 +1243,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -1117,7 +1258,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.regs[2].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; @@ -1132,7 +1273,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::X;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1148,7 +1289,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::Y;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1174,7 +1315,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1194,7 +1335,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1213,7 +1354,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              };              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1248,7 +1389,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              };              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = mem_oper;              instruction.operand_count = 2; @@ -1272,7 +1413,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              }; -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  return Err(DecodeError::InvalidOperand);              } @@ -1290,7 +1431,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1308,7 +1449,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.vex_unchecked().r(), RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1324,7 +1465,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1341,7 +1482,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), RegisterBank::X);              instruction.regs[3].bank = RegisterBank::X; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1358,7 +1499,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1374,7 +1515,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7,instruction.prefixes.vex_unchecked().x(), 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)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1406,7 +1547,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y      }  } -fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix) -> Result<(), DecodeError> { +fn read_vex_instruction< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix, sink: &mut S) -> Result<(), DecodeError> { +    let opcode_start = words.offset() as u32 * 8;      let opc = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      // the name of this bit is `L` in the documentation, so use the same name here. @@ -3455,5 +3600,19 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a          }      };      instruction.opcode = opcode; -    read_vex_operands(words, instruction, operand_code) + +    sink.record( +        opcode_start, +        opcode_start + 7, +        InnerDescription::Opcode(instruction.opcode) +            .with_id(opcode_start) +    ); +    sink.record( +        opcode_start + 7, +        opcode_start + 7, +        InnerDescription::Boundary("vex opcode ends/operands begin") +            .with_id(opcode_start + 7) +    ); + +    read_vex_operands(words, instruction, operand_code, sink)  } diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs index 202aeb3..2c73d4b 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -7,6 +7,7 @@ use crate::protected_mode::DecodeError;  use crate::protected_mode::FieldDescription;  use crate::protected_mode::RegSpec;  use crate::protected_mode::RegisterBank; +use crate::protected_mode::InnerDescription;  use crate::protected_mode::Instruction;  use crate::protected_mode::Opcode;  use crate::protected_mode::read_modrm; @@ -103,6 +104,7 @@ pub(crate) fn three_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,      S: DescriptionSink<FieldDescription>,  >(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() as u32 * 8 - 8;      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03;      let p = match p { @@ -112,7 +114,29 @@ pub(crate) fn three_byte_vex<          0x03 => VEXOpcodePrefix::PrefixF2,          _ => { unreachable!("p is two bits"); }      }; +    sink.record( +        vex_start + 8, +        vex_start + 9, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    );      let m = vex_byte_one & 0b11111; +    sink.record( +        vex_start + 0, +        vex_start + 4, +        InnerDescription::Misc(match m { +            0b00001 => "vex.mmmmm indicates opcode escape of 0f", +            0b00010 => "vex.mmmmm indicates opcode escape of 0f38", +            0b00011 => "vex.mmmmm indicates opcode escape of 0f3a", +            _ => "vex.mmmmm indicates illegal opcode escape and is invalid", +        }) +            .with_id(vex_start) +    );      let m = match m {          0b00001 => VEXOpcodeMap::Map0F,          0b00010 => VEXOpcodeMap::Map0F38, @@ -126,9 +150,68 @@ pub(crate) fn three_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111,      }; + +    sink.record( +        vex_start + 11, +        vex_start + 14, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte_one & 0b10000000 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 6, +        vex_start + 6, +        InnerDescription::Misc(if vex_byte_one & 0b01000000 == 0 { +            "vex.x extends extends index reg (if used) by 0b1000" +        } else { +            "vex.x does not alter index reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 5, +        vex_start + 5, +        InnerDescription::Misc(if vex_byte_one & 0b00100000 == 0 { +            "vex.b extends extends base reg (if used) by 0b1000" +        } else { +            "vex.b does not alter base reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 10, +        vex_start + 10, +        InnerDescription::Misc(if vex_byte_two & 0b100 == 0 { +            "vex.l selects 128-bit vector sizes" +        } else { +            "vex.l selects 256-bit vector sizes" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 15, +        vex_start + 15, +        InnerDescription::Misc(if vex_byte_two & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); -    read_vex_instruction(m, words, instruction, p)?; +    read_vex_instruction(m, words, instruction, p, sink)?;      instruction.length = words.offset() as u8;      instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(()) @@ -138,6 +221,7 @@ pub(crate) fn two_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,      S: DescriptionSink<FieldDescription>,  >(words: &mut T, vex_byte: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() * 8 - 8;      let p = vex_byte & 0x03;      let p = match p {          0x00 => VEXOpcodePrefix::None, @@ -150,15 +234,59 @@ pub(crate) fn two_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte >> 3) & 0b1111) ^ 0b1111,      }; + +    sink.record( +        vex_start + 0, +        vex_start + 1, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    ); + +    sink.record( +        vex_start + 3, +        vex_start + 6, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 2, +        vex_start + 2, +        InnerDescription::Misc(if vex_byte & 0b100 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c5(vex_byte); -    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p)?; +    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p, sink)?;      instruction.length = words.offset() as u8;      instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(())  } -fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode) -> Result<(), DecodeError> { +fn read_vex_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode, sink: &mut S) -> Result<(), DecodeError> {  //    println!("operand code: {:?}", operand_code);      match operand_code {          VEXOperandCode::VPS_71 => { @@ -361,7 +489,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -390,7 +518,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[2] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -427,7 +555,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -443,7 +571,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -465,7 +593,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::ImmU8; @@ -498,7 +626,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -515,7 +643,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -532,7 +660,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -551,7 +679,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -571,7 +699,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              match (op, mem_oper) {                  (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => {                      /* this is the only accepted operand */ @@ -604,7 +732,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -621,7 +749,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -638,7 +766,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -657,7 +785,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -676,7 +804,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -696,7 +824,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -713,7 +841,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -746,7 +874,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -769,7 +897,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -786,7 +914,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -809,7 +937,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -832,7 +960,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -860,7 +988,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -888,7 +1016,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -908,7 +1036,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -923,7 +1051,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -943,7 +1071,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -960,7 +1088,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -978,7 +1106,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -998,7 +1126,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1012,7 +1140,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1029,7 +1157,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1049,7 +1177,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -1064,7 +1192,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.regs[2].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; @@ -1079,7 +1207,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::X;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1095,7 +1223,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::Y;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1117,7 +1245,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1133,7 +1261,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1148,7 +1276,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let (opwidth, bank) = (4, RegisterBank::D);              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1179,7 +1307,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let (opwidth, bank) = (4, RegisterBank::D);              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = mem_oper;              instruction.operand_count = 2; @@ -1203,7 +1331,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              }; -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  return Err(DecodeError::InvalidOperand);              } @@ -1221,7 +1349,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1239,7 +1367,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1255,7 +1383,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1272,7 +1400,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.regs[3].bank = RegisterBank::X; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1289,7 +1417,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1305,7 +1433,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.regs[3].bank = RegisterBank::X;              // TODO: but the memory access is word-sized -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1335,7 +1463,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y      }  } -fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix) -> Result<(), DecodeError> { +fn read_vex_instruction< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix, sink: &mut S) -> Result<(), DecodeError> { +    let opcode_start = words.offset() as u32 * 8;      let opc = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      // the name of this bit is `L` in the documentation, so use the same name here. @@ -3370,5 +3502,19 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a          }      };      instruction.opcode = opcode; -    read_vex_operands(words, instruction, operand_code) + +    sink.record( +        opcode_start, +        opcode_start + 7, +        InnerDescription::Opcode(instruction.opcode) +            .with_id(opcode_start) +    ); +    sink.record( +        opcode_start + 7, +        opcode_start + 7, +        InnerDescription::Boundary("vex opcode ends/operands begin") +            .with_id(opcode_start + 7) +    ); + +    read_vex_operands(words, instruction, operand_code, sink)  } diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs index 41102d9..9474a49 100644 --- a/src/real_mode/vex.rs +++ b/src/real_mode/vex.rs @@ -7,6 +7,7 @@ use crate::real_mode::DecodeError;  use crate::real_mode::FieldDescription;  use crate::real_mode::RegSpec;  use crate::real_mode::RegisterBank; +use crate::real_mode::InnerDescription;  use crate::real_mode::Instruction;  use crate::real_mode::Opcode;  use crate::real_mode::read_modrm; @@ -101,8 +102,9 @@ enum VEXOperandCode {  #[inline(never)]  pub(crate) fn three_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, -    S: DescriptionSink<FieldDescription>, +    S: DescriptionSink<FieldDescription>  >(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() as u32 * 8 - 8;      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03;      let p = match p { @@ -112,7 +114,29 @@ pub(crate) fn three_byte_vex<          0x03 => VEXOpcodePrefix::PrefixF2,          _ => { unreachable!("p is two bits"); }      }; +    sink.record( +        vex_start + 8, +        vex_start + 9, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    );      let m = vex_byte_one & 0b11111; +    sink.record( +        vex_start + 0, +        vex_start + 4, +        InnerDescription::Misc(match m { +            0b00001 => "vex.mmmmm indicates opcode escape of 0f", +            0b00010 => "vex.mmmmm indicates opcode escape of 0f38", +            0b00011 => "vex.mmmmm indicates opcode escape of 0f3a", +            _ => "vex.mmmmm indicates illegal opcode escape and is invalid", +        }) +            .with_id(vex_start) +    );      let m = match m {          0b00001 => VEXOpcodeMap::Map0F,          0b00010 => VEXOpcodeMap::Map0F38, @@ -126,9 +150,68 @@ pub(crate) fn three_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte_two >> 3) & 0b1111) ^ 0b1111,      }; + +    sink.record( +        vex_start + 11, +        vex_start + 14, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte_one & 0b10000000 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 6, +        vex_start + 6, +        InnerDescription::Misc(if vex_byte_one & 0b01000000 == 0 { +            "vex.x extends extends index reg (if used) by 0b1000" +        } else { +            "vex.x does not alter index reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 5, +        vex_start + 5, +        InnerDescription::Misc(if vex_byte_one & 0b00100000 == 0 { +            "vex.b extends extends base reg (if used) by 0b1000" +        } else { +            "vex.b does not alter base reg" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 10, +        vex_start + 10, +        InnerDescription::Misc(if vex_byte_two & 0b100 == 0 { +            "vex.l selects 128-bit vector sizes" +        } else { +            "vex.l selects 256-bit vector sizes" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 15, +        vex_start + 15, +        InnerDescription::Misc(if vex_byte_two & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c4(vex_byte_one, vex_byte_two); -    read_vex_instruction(m, words, instruction, p)?; +    read_vex_instruction(m, words, instruction, p, sink)?;      instruction.length = words.offset() as u8;      instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(()) @@ -138,6 +221,7 @@ pub(crate) fn two_byte_vex<      T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,      S: DescriptionSink<FieldDescription>,  >(words: &mut T, vex_byte: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> { +    let vex_start = words.offset() * 8 - 8;      let p = vex_byte & 0x03;      let p = match p {          0x00 => VEXOpcodePrefix::None, @@ -150,15 +234,59 @@ pub(crate) fn two_byte_vex<          bank: RegisterBank::X,          num: ((vex_byte >> 3) & 0b1111) ^ 0b1111,      }; + +    sink.record( +        vex_start + 0, +        vex_start + 1, +        InnerDescription::Misc(match p { +            VEXOpcodePrefix::None => "vex.p indicates no opcode prefix", +            VEXOpcodePrefix::Prefix66 => "vex.p indicates opcode prefix 66", +            VEXOpcodePrefix::PrefixF3 => "vex.p indicates opcode prefix f3", +            VEXOpcodePrefix::PrefixF2 => "vex.p indicates opcode prefix f2", +        }) +            .with_id(vex_start) +    ); + +    sink.record( +        vex_start + 3, +        vex_start + 6, +        InnerDescription::RegisterNumber("vvvv", instruction.regs[3].num, instruction.regs[3]) +            .with_id(vex_start + 2) +    ); + +    sink.record( +        vex_start + 2, +        vex_start + 2, +        InnerDescription::Misc(if vex_byte & 0b100 == 0 { +            "vex.r extends extends rrr by 0b1000" +        } else { +            "vex.r does not alter rrr" +        }) +            .with_id(vex_start + 1) +    ); +    sink.record( +        vex_start + 7, +        vex_start + 7, +        InnerDescription::Misc(if vex_byte & 0b10000000 != 0 { +            "vex.w selects 64-bit operand size" +        } else { +            "vex.w leaves default operand size" +        }) +            .with_id(vex_start + 1) +    ); +      instruction.prefixes.vex_from_c5(vex_byte); -    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p)?; +    read_vex_instruction(VEXOpcodeMap::Map0F, words, instruction, p, sink)?;      instruction.length = words.offset() as u8;      instruction.regs[3].num &= 0b0111; // ignore bit 4 in 32-bit mode      Ok(())  } -fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode) -> Result<(), DecodeError> { +fn read_vex_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, operand_code: VEXOperandCode, sink: &mut S) -> Result<(), DecodeError> {  //    println!("operand code: {:?}", operand_code);      match operand_code {          VEXOperandCode::VPS_71 => { @@ -361,7 +489,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -390,7 +518,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[2] = OperandSpec::RegRRR;              match mem_oper {                  OperandSpec::RegMMM => { @@ -427,7 +555,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -443,7 +571,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex; -            instruction.operands[2] = read_E_xmm(words, instruction, modrm)?; +            instruction.operands[2] = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operand_count = 3;              Ok(())          } @@ -465,7 +593,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operands[2] = OperandSpec::ImmU8; @@ -498,7 +626,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -515,7 +643,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -532,7 +660,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -551,7 +679,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  instruction.regs[1].bank = RegisterBank::X;              } else { @@ -571,7 +699,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              match (op, mem_oper) {                  (VEXOperandCode::E_G_xmm, OperandSpec::RegMMM) => {                      /* this is the only accepted operand */ @@ -604,7 +732,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -621,7 +749,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -638,7 +766,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -657,7 +785,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -676,7 +804,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -696,7 +824,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -713,7 +841,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::D); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              if mem_oper != OperandSpec::RegMMM {                  return Err(DecodeError::InvalidOperand);              } @@ -746,7 +874,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -769,7 +897,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -786,7 +914,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -809,7 +937,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -832,7 +960,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -860,7 +988,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;              if mem_oper != OperandSpec::RegMMM { @@ -888,7 +1016,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              if mem_oper != OperandSpec::RegMMM { @@ -908,7 +1036,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -923,7 +1051,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -943,7 +1071,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -960,7 +1088,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -978,7 +1106,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -998,7 +1126,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1012,7 +1140,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1029,7 +1157,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1049,7 +1177,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = OperandSpec::RegRRR; @@ -1064,7 +1192,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.regs[2].bank = RegisterBank::X;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper; @@ -1079,7 +1207,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::X;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1095,7 +1223,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.regs[3].bank = RegisterBank::Y;              instruction.regs[2].bank = RegisterBank::Y;              instruction.operands[0] = OperandSpec::RegRRR; @@ -1117,7 +1245,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1133,7 +1261,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank);              instruction.regs[3].bank = bank; -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.operands[2] = OperandSpec::RegVex; @@ -1148,7 +1276,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let (opwidth, bank) = (4, RegisterBank::D);              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1179,7 +1307,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let (opwidth, bank) = (4, RegisterBank::D);              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, bank); -            let mem_oper = read_E(words, instruction, modrm, opwidth)?; +            let mem_oper = read_E(words, instruction, modrm, opwidth, sink)?;              instruction.operands[0] = OperandSpec::RegVex;              instruction.operands[1] = mem_oper;              instruction.operand_count = 2; @@ -1203,7 +1331,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      return Err(DecodeError::InvalidOpcode);                  }              }; -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              if let OperandSpec::RegMMM = mem_oper {                  return Err(DecodeError::InvalidOperand);              } @@ -1221,7 +1349,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X); -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1239,7 +1367,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              let modrm = read_modrm(words)?;              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y); -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = mem_oper;              instruction.imm = read_imm_unsigned(words, 1)?; @@ -1255,7 +1383,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_ymm(words, instruction, modrm)?; +            let mem_oper = read_E_ymm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1272,7 +1400,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.regs[3].bank = RegisterBank::X; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1289,7 +1417,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              instruction.regs[0] =                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::Y);              instruction.regs[3].bank = RegisterBank::Y; -            let mem_oper = read_E_xmm(words, instruction, modrm)?; +            let mem_oper = read_E_xmm(words, instruction, modrm, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1305,7 +1433,7 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  RegSpec::from_parts((modrm >> 3) & 7, RegisterBank::X);              instruction.regs[3].bank = RegisterBank::X;              // TODO: but the memory access is word-sized -            let mem_oper = read_E(words, instruction, modrm, 4)?; +            let mem_oper = read_E(words, instruction, modrm, 4, sink)?;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::RegVex;              instruction.operands[2] = mem_oper; @@ -1335,7 +1463,11 @@ fn read_vex_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y      }  } -fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix) -> Result<(), DecodeError> { +fn read_vex_instruction< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(opcode_map: VEXOpcodeMap, words: &mut T, instruction: &mut Instruction, p: VEXOpcodePrefix, sink: &mut S) -> Result<(), DecodeError> { +    let opcode_start = words.offset() as u32 * 8;      let opc = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      // the name of this bit is `L` in the documentation, so use the same name here. @@ -3370,5 +3502,19 @@ fn read_vex_instruction<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch a          }      };      instruction.opcode = opcode; -    read_vex_operands(words, instruction, operand_code) + +    sink.record( +        opcode_start, +        opcode_start + 7, +        InnerDescription::Opcode(instruction.opcode) +            .with_id(opcode_start) +    ); +    sink.record( +        opcode_start + 7, +        opcode_start + 7, +        InnerDescription::Boundary("vex opcode ends/operands begin") +            .with_id(opcode_start + 7) +    ); + +    read_vex_operands(words, instruction, operand_code, sink)  }  | 
