aboutsummaryrefslogtreecommitdiff
path: root/src/real_mode/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/real_mode/mod.rs')
-rw-r--r--src/real_mode/mod.rs118
1 files changed, 101 insertions, 17 deletions
diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs
index 7f3ad42..0af0b0b 100644
--- a/src/real_mode/mod.rs
+++ b/src/real_mode/mod.rs
@@ -13,6 +13,7 @@ use core::cmp::PartialEq;
use core::hint::unreachable_unchecked;
use yaxpeax_arch::{AddressDiff, Decoder, Reader, LengthedInstruction};
+use yaxpeax_arch::{AnnotatingDecoder, DescriptionSink, NullSink};
use yaxpeax_arch::{DecodeError as ArchDecodeError};
use core::fmt;
@@ -4090,7 +4091,7 @@ impl Default for InstDecoder {
impl Decoder<Arch> for InstDecoder {
fn decode<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, words: &mut T) -> Result<Instruction, <Arch as yaxpeax_arch::Arch>::DecodeError> {
let mut instr = Instruction::invalid();
- read_instr(self, words, &mut instr)?;
+ read_with_annotations(self, words, &mut instr, &mut NullSink)?;
instr.length = words.offset() as u8;
if words.offset() > 15 {
@@ -4104,7 +4105,7 @@ impl Decoder<Arch> for InstDecoder {
Ok(instr)
}
fn decode_into<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, instr: &mut Instruction, words: &mut T) -> Result<(), <Arch as yaxpeax_arch::Arch>::DecodeError> {
- read_instr(self, words, instr)?;
+ read_with_annotations(self, words, instr, &mut NullSink)?;
instr.length = words.offset() as u8;
if words.offset() > 15 {
@@ -4822,7 +4823,7 @@ impl OperandCodeBuilder {
// |
// ---------------------------> read modr/m?
#[repr(u16)]
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum OperandCode {
Ivs = OperandCodeBuilder::new().special_case(25).bits(),
I_3 = OperandCodeBuilder::new().special_case(27).bits(),
@@ -7087,7 +7088,84 @@ fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {
};
}
-fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction) -> Result<(), DecodeError> {
+#[derive(Clone, Debug, PartialEq, Eq)]
+enum InnerDescription {
+ RexPrefix(u8),
+ SegmentPrefix(Segment),
+ Opcode(Opcode),
+ OperandCode(OperandCode),
+ RegisterNumber(&'static str, u8, RegSpec),
+ Misc(&'static str),
+ Number(&'static str, i64),
+}
+
+impl InnerDescription {
+ fn with_id(self, id: u32) -> FieldDescription {
+ FieldDescription {
+ desc: self,
+ id,
+ }
+ }
+}
+
+impl fmt::Display for InnerDescription {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ InnerDescription::RexPrefix(bits) => {
+ write!(f, "rex prefix: {}{}{}{}",
+ if bits & 0x8 != 0 { "w" } else { "-" },
+ if bits & 0x4 != 0 { "r" } else { "-" },
+ if bits & 0x2 != 0 { "x" } else { "-" },
+ if bits & 0x1 != 0 { "b" } else { "-" },
+ )
+ }
+ InnerDescription::SegmentPrefix(segment) => {
+ write!(f, "segment override: {}", segment)
+ }
+ InnerDescription::Misc(text) => {
+ f.write_str(text)
+ }
+ InnerDescription::Number(text, num) => {
+ write!(f, "{}: {:#x}", text, num)
+ }
+ InnerDescription::Opcode(opc) => {
+ write!(f, "opcode `{}`", opc)
+ }
+ InnerDescription::OperandCode(code) => {
+ write!(f, "operand code `{:?}`", code)
+ }
+ InnerDescription::RegisterNumber(name, num, reg) => {
+ write!(f, "`{}` (`{}` selects register number {})", reg, name, num)
+ }
+ }
+ }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FieldDescription {
+ desc: InnerDescription,
+ id: u32,
+}
+
+impl yaxpeax_arch::FieldDescription for FieldDescription {
+ fn id(&self) -> u32 {
+ self.id
+ }
+ fn is_separator(&self) -> bool {
+ false
+ }
+}
+
+impl fmt::Display for FieldDescription {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.desc, f)
+ }
+}
+
+fn read_with_annotations<
+ T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
+ S: DescriptionSink<FieldDescription>,
+>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {
words.mark();
let mut nextb = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;
let mut next_rec = OPCODES[nextb as usize];
@@ -7174,7 +7252,7 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_
unsafe { unreachable_unchecked(); }
}
instruction.prefixes = prefixes;
- read_operands(decoder, words, instruction, record.1)?;
+ read_operands(decoder, words, instruction, record.1, sink)?;
instruction.length = words.offset() as u8;
if instruction.length > 15 {
return Err(DecodeError::TooLong);
@@ -7226,7 +7304,10 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_
OperandCode::ModRM_0x8f_Ev => 30
*/
-fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> {
+fn read_operands<
+ T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
+ S: DescriptionSink<FieldDescription>
+>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> {
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operand_count = 2;
let operand_code = OperandCodeBuilder::from_bits(operand_code as u16);
@@ -7725,14 +7806,17 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe
},
_ => {
let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) };
- unlikely_operands(decoder, words, instruction, operand_code, mem_oper)?;
+ unlikely_operands(decoder, words, instruction, operand_code, mem_oper, sink)?;
}
};
}
Ok(())
}
-fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec) -> Result<(), DecodeError> {
+fn unlikely_operands<
+ T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>,
+ S: DescriptionSink<FieldDescription>
+>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, sink: &mut S) -> Result<(), DecodeError> {
match operand_code {
OperandCode::G_E_mm_Ib => {
let modrm = read_modrm(words)?;
@@ -7841,7 +7925,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
// prefixes and then vex is invalid! reject it.
return Err(DecodeError::InvalidPrefixes);
} else {
- vex::three_byte_vex(words, modrm, instruction)?;
+ vex::three_byte_vex(words, modrm, instruction, sink)?;
if decoder != &InstDecoder::default() {
decoder.revise_instruction(instruction)?;
@@ -7868,7 +7952,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
// prefixes and then vex is invalid! reject it.
return Err(DecodeError::InvalidPrefixes);
} else {
- vex::two_byte_vex(words, modrm, instruction)?;
+ vex::two_byte_vex(words, modrm, instruction, sink)?;
if decoder != &InstDecoder::default() {
decoder.revise_instruction(instruction)?;
@@ -8729,7 +8813,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
}
OperandCode::ModRM_0xf30f38dc => {
- read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;
if let OperandSpec::RegMMM = instruction.operands[1] {
instruction.opcode = Opcode::LOADIWKEY;
} else {
@@ -8738,7 +8822,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
}
OperandCode::ModRM_0xf30f38dd => {
- read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;
if let OperandSpec::RegMMM = instruction.operands[1] {
return Err(DecodeError::InvalidOperand);
} else {
@@ -8747,7 +8831,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
}
OperandCode::ModRM_0xf30f38de => {
- read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;
if let OperandSpec::RegMMM = instruction.operands[1] {
return Err(DecodeError::InvalidOperand);
} else {
@@ -8756,7 +8840,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
}
OperandCode::ModRM_0xf30f38df => {
- read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;
if let OperandSpec::RegMMM = instruction.operands[1] {
return Err(DecodeError::InvalidOperand);
} else {
@@ -8766,13 +8850,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
}
OperandCode::ModRM_0xf30f38fa => {
instruction.opcode = Opcode::ENCODEKEY128;
- read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::D;
}
OperandCode::ModRM_0xf30f38fb => {
instruction.opcode = Opcode::ENCODEKEY256;
- read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?;
+ read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;
instruction.regs[0].bank = RegisterBank::D;
instruction.regs[1].bank = RegisterBank::D;
}
@@ -10075,7 +10159,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y
if prefixes.lock() || prefixes.operand_size() || prefixes.rep_any() {
return Err(DecodeError::InvalidPrefixes);
} else {
- evex::read_evex(words, instruction, Some(modrm))?;
+ evex::read_evex(words, instruction, Some(modrm), sink)?;
}
}
}