aboutsummaryrefslogtreecommitdiff
path: root/src/protected_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/protected_mode')
-rw-r--r--src/protected_mode/mod.rs78
1 files changed, 75 insertions, 3 deletions
diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs
index 572513d..20125ca 100644
--- a/src/protected_mode/mod.rs
+++ b/src/protected_mode/mod.rs
@@ -5802,7 +5802,11 @@ fn read_sib<
}
#[allow(non_snake_case)]
-fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, DecodeError> {
+fn read_M_16bit<
+ T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
+ S: DescriptionSink<FieldDescription>
+>(words: &mut T, instr: &mut Instruction, modrm: u8, sink: &mut S) -> Result<OperandSpec, DecodeError> {
+ let modrm_start = words.offset() as u32 * 8 - 8;
let modbits = modrm >> 6;
let mmm = modrm & 7;
if modbits == 0b00 && mmm == 0b110 {
@@ -5842,6 +5846,12 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
}
match modbits {
0b00 => {
+ sink.record(
+ modrm_start + 6,
+ modrm_start + 7,
+ InnerDescription::Misc("mmm selects a dereference with no displacement (mod bits: 00)")
+ .with_id(modrm_start + 0)
+ );
if mmm > 3 {
Ok(OperandSpec::Deref)
} else {
@@ -5849,7 +5859,21 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
}
},
0b01 => {
+ let disp_start = words.offset() as u32 * 8;
instr.disp = read_num(words, 1)? as i8 as i32 as u32;
+ let disp_end = words.offset() as u32 * 8;
+ sink.record(
+ modrm_start + 6,
+ modrm_start + 7,
+ InnerDescription::Misc("mmm selects a dereference with 8-bit displacement (mod bits: 01)")
+ .with_id(modrm_start + 0)
+ );
+ sink.record(
+ disp_start,
+ disp_end - 1,
+ InnerDescription::Number("displacement", instr.disp as i64)
+ .with_id(disp_start + 3)
+ );
if mmm > 3 {
if instr.disp != 0 {
Ok(OperandSpec::RegDisp)
@@ -5865,7 +5889,21 @@ fn read_M_16bit<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpea
}
},
0b10 => {
+ let disp_start = words.offset() as u32 * 8;
instr.disp = read_num(words, 2)? as i16 as i32 as u32;
+ let disp_end = words.offset() as u32 * 8;
+ sink.record(
+ modrm_start + 6,
+ modrm_start + 7,
+ InnerDescription::Misc("mmm selects a dereference with 16-bit displacement (mod bits: 10)")
+ .with_id(modrm_start + 0)
+ );
+ sink.record(
+ disp_start,
+ disp_end - 1,
+ InnerDescription::Number("displacement", instr.disp as i64)
+ .with_id(disp_start + 3)
+ );
if mmm > 3 {
if instr.disp != 0 {
Ok(OperandSpec::RegDisp)
@@ -5894,7 +5932,7 @@ fn read_M<
let modrm_start = words.offset() as u32 * 8 - 8;
if instr.prefixes.address_size() {
- return read_M_16bit(words, instr, modrm);
+ return read_M_16bit(words, instr, modrm, sink);
}
instr.regs[1].bank = RegisterBank::D;
let modbits = modrm >> 6;
@@ -7396,7 +7434,7 @@ fn read_with_annotations<
let record: OpcodeRecord = loop {
let record = next_rec;
- if let Interpretation::Instruction(_) = record.0 {
+ if let Interpretation::Instruction(opc) = record.0 {
if words.offset() > 1 {
sink.record(
words.offset() as u32 * 8 - 8 - 1, words.offset() as u32 * 8 - 8 - 1,
@@ -7404,6 +7442,16 @@ fn read_with_annotations<
.with_id(words.offset() as u32 * 8 - 9)
);
}
+ if opc != Opcode::Invalid {
+ sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::Opcode(opc),
+ id: words.offset() as u32 * 8 - 8,
+ });
+ }
+ sink.record((words.offset() - 1) as u32 * 8, (words.offset() - 1) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::OperandCode(record.1),
+ id: words.offset() as u32 * 8 - 8 + 1,
+ });
break record;
} else {
let b = nextb;
@@ -7436,21 +7484,45 @@ fn read_with_annotations<
};
match b {
0x26 => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::ES),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_es();
},
0x2e => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::CS),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_cs();
},
0x36 => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::SS),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_ss();
},
0x3e => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::DS),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_ds();
},
0x64 => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::FS),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_fs();
},
0x65 => {
+ sink.record((words.offset() - 2) as u32 * 8, (words.offset() - 2) as u32 * 8 + 7, FieldDescription {
+ desc: InnerDescription::SegmentPrefix(Segment::GS),
+ id: words.offset() as u32 * 8 - 16,
+ });
prefixes.set_gs();
},
0x66 => {