aboutsummaryrefslogtreecommitdiff
path: root/src/long_mode/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/long_mode/mod.rs')
-rw-r--r--src/long_mode/mod.rs53
1 files changed, 30 insertions, 23 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 6475d4e..2f3e510 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -5608,7 +5608,7 @@ pub(self) fn read_E<
>(words: &mut T, instr: &mut Instruction, modrm: u8, width: u8, sink: &mut S) -> Result<OperandSpec, DecodeError> {
let bank = width_to_gp_reg_bank(width, instr.prefixes.rex_unchecked().present());
if modrm >= 0b11000000 {
- read_modrm_reg(instr, modrm, bank)
+ read_modrm_reg(instr, words, modrm, bank, sink)
} else {
read_M(words, instr, modrm, sink)
}
@@ -5643,7 +5643,7 @@ pub(self) fn read_E_xmm<
S: DescriptionSink<FieldDescription>,
>(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result<OperandSpec, DecodeError> {
if modrm >= 0b11000000 {
- read_modrm_reg(instr, modrm, RegisterBank::X)
+ read_modrm_reg(instr, words, modrm, RegisterBank::X, sink)
} else {
read_M(words, instr, modrm, sink)
}
@@ -5654,7 +5654,7 @@ pub(self) fn read_E_ymm<
S: DescriptionSink<FieldDescription>,
>(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result<OperandSpec, DecodeError> {
if modrm >= 0b11000000 {
- read_modrm_reg(instr, modrm, RegisterBank::Y)
+ read_modrm_reg(instr, words, modrm, RegisterBank::Y, sink)
} else {
read_M(words, instr, modrm, sink)
}
@@ -5665,7 +5665,7 @@ pub(self) fn read_E_vex<
S: DescriptionSink<FieldDescription>,
>(words: &mut T, instr: &mut Instruction, modrm: u8, bank: RegisterBank, sink: &mut S) -> Result<OperandSpec, DecodeError> {
if modrm >= 0b11000000 {
- read_modrm_reg(instr, modrm, bank)
+ read_modrm_reg(instr, words, modrm, bank, sink)
} else {
let res = read_M(words, instr, modrm, sink)?;
if (modrm & 0b01_000_000) == 0b01_000_000 {
@@ -5676,8 +5676,18 @@ pub(self) fn read_E_vex<
}
#[allow(non_snake_case)]
-fn read_modrm_reg(instr: &mut Instruction, modrm: u8, reg_bank: RegisterBank) -> Result<OperandSpec, DecodeError> {
+#[inline(always)]
+fn read_modrm_reg<
+ T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
+ S: DescriptionSink<FieldDescription>,
+>(instr: &mut Instruction, words: &mut T, modrm: u8, reg_bank: RegisterBank, sink: &mut S) -> Result<OperandSpec, DecodeError> {
instr.regs[1] = RegSpec::from_parts(modrm & 7, instr.prefixes.rex_unchecked().b(), reg_bank);
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 6,
+ InnerDescription::RegisterNumber("mmm", modrm & 7, instr.regs[1])
+ .with_id(words.offset() as u32 * 8 - 8 + 2)
+ );
Ok(OperandSpec::RegMMM)
}
@@ -7838,14 +7848,7 @@ fn read_operands<
if operand_code.bits() == (OperandCode::Gv_M as u16) {
return Err(DecodeError::InvalidOperand);
}
- let res = read_modrm_reg(instruction, modrm, bank)?;
- sink.record(
- modrm_start,
- modrm_start + 2,
- InnerDescription::RegisterNumber("mmm", modrm & 7, instruction.regs[1])
- .with_id(modrm_start + 2)
- );
- res
+ read_modrm_reg(instruction, words, modrm, bank, sink)?
} else {
read_M(words, instruction, modrm, sink)?
};
@@ -7885,12 +7888,16 @@ fn read_operands<
modrm = read_modrm(words)?;
instruction.regs[0].bank = bank;
instruction.regs[0].num = ((modrm >> 3) & 7) + if instruction.prefixes.rex_unchecked().r() { 0b1000 } else { 0 };
- sink.record(
- modrm_start + 3,
- modrm_start + 5,
- InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0])
- .with_id(modrm_start + 3)
- );
+
+ // for some encodings, the rrr field selects an opcode, not an operand
+ if operand_code.bits() != OperandCode::ModRM_0xc1_Ev_Ib as u16 && operand_code.bits() != OperandCode::ModRM_0xff_Ev as u16 {
+ sink.record(
+ modrm_start + 3,
+ modrm_start + 5,
+ InnerDescription::RegisterNumber("rrr", (modrm >> 3) & 7, instruction.regs[0])
+ .with_id(modrm_start + 3)
+ );
+ }
mem_oper = if modrm >= 0b11000000 {
sink.record(
@@ -7899,7 +7906,7 @@ fn read_operands<
InnerDescription::Misc("mmm field is a register number (mod bits: 11)")
.with_id(modrm_start + 0)
);
- read_modrm_reg(instruction, modrm, bank)?
+ read_modrm_reg(instruction, words, modrm, bank, sink)?
} else {
read_M(words, instruction, modrm, sink)?
};
@@ -8272,9 +8279,9 @@ fn read_operands<
};
if op == 5 {
sink.record(
- modrm_start - 8,
- modrm_start - 1,
- InnerDescription::Number("imm", instruction.imm as i64)
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("imm", num as i64)
.with_id(modrm_start - 8)
);
} else {