aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-08-20 01:59:27 -0700
committeriximeow <me@iximeow.net>2021-08-21 19:20:41 -0700
commitb8cdf3ee6293f41b7b9bcb51d1177baeff24868d (patch)
treee87bcb3834f31629da3caf81872065d8c2f5fef2
parent796e955cdc4f17d191b39da55ce704f90c6f37da (diff)
report barebones decoder annotation for vex-coded instructions
-rw-r--r--src/long_mode/vex.rs269
-rw-r--r--src/protected_mode/vex.rs250
-rw-r--r--src/real_mode/vex.rs252
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)
}