diff options
Diffstat (limited to 'src/long_mode/vex.rs')
-rw-r--r-- | src/long_mode/vex.rs | 269 |
1 files changed, 214 insertions, 55 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) } |