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 | |
parent | 796e955cdc4f17d191b39da55ce704f90c6f37da (diff) |
report barebones decoder annotation for vex-coded instructions
-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) } |