1use super::{
2 insn::{ModRM, X86Instruction, X86Mode},
3 X86RegisterClass,
4};
5use core::ops::{Deref, DerefMut};
6
7#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
8pub enum Syntax {
9 Intel,
10 Att(bool),
11}
12
13pub struct InsnPrinter<W> {
14 syntax: Syntax,
15 mode: X86Mode,
16 writer: W,
17}
18
19impl<W> InsnPrinter<W> {
20 pub const fn new(writer: W, mode: X86Mode, syntax: Syntax) -> Self {
21 Self {
22 writer,
23 mode,
24 syntax,
25 }
26 }
27
28 pub fn into_inner(self) -> W {
29 self.writer
30 }
31
32 pub fn set_mode(&mut self, mode: X86Mode) {
33 self.mode = mode;
34 }
35
36 pub fn mode(&self) -> X86Mode {
37 self.mode
38 }
39
40 pub fn set_syntax(&mut self, syntax: Syntax) {
41 self.syntax = syntax
42 }
43
44 pub fn syntax(&self) -> Syntax {
45 self.syntax
46 }
47}
48
49impl<W> Deref for InsnPrinter<W> {
50 type Target = W;
51 fn deref(&self) -> &W {
52 &self.writer
53 }
54}
55
56impl<W> DerefMut for InsnPrinter<W> {
57 fn deref_mut(&mut self) -> &mut W {
58 &mut self.writer
59 }
60}
61
62impl<W: core::fmt::Write> InsnPrinter<W> {
63 pub fn write_insn(&mut self, insn: &X86Instruction) -> core::fmt::Result {
64 let mode = insn.mode_override().unwrap_or(self.mode);
65
66 match self.syntax {
67 Syntax::Intel => {
68 let mut addr_mode = mode.largest_gpr();
69 for op in insn.operands() {
70 match op {
71 super::insn::X86Operand::ModRM(modrm)
72 | super::insn::X86Operand::FarModRM { modrm, .. } => match modrm {
73 ModRM::Indirect { mode, .. }
74 | ModRM::IndirectDisp8 { mode, .. }
75 | ModRM::IndirectDisp32 { mode, .. } => match mode {
76 super::insn::ModRMRegOrSib::Reg(r) => addr_mode = r.class(),
77 super::insn::ModRMRegOrSib::Abs(_) => todo!(),
78 super::insn::ModRMRegOrSib::RipRel(_) => todo!(),
79 super::insn::ModRMRegOrSib::Sib { base, .. } => {
80 addr_mode = base.class()
81 }
82 super::insn::ModRMRegOrSib::Index16 { .. } => {
83 addr_mode = X86RegisterClass::Word
84 }
85 },
86 _ => {}
87 },
88 _ => {}
89 }
90 }
91
92 if addr_mode != mode.largest_gpr() {
93 self.writer
94 .write_fmt(format_args!("addr{} ", addr_mode.size(mode) * 8))?;
95 }
96 self.writer.write_fmt(format_args!("{} ", insn.opcode()))?;
97 }
98 Syntax::Att(_) => todo!("att_syntax"),
99 }
100 Ok(())
101 }
102}