arch-ops 0.1.1

A library to encode and decode instructions for several architectures
Documentation
use super::{
    insn::{ModRM, X86Instruction, X86Mode},
    X86RegisterClass,
};
use core::ops::{Deref, DerefMut};

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Syntax {
    Intel,
    Att(bool),
}

pub struct InsnPrinter<W> {
    syntax: Syntax,
    mode: X86Mode,
    writer: W,
}

impl<W> InsnPrinter<W> {
    pub const fn new(writer: W, mode: X86Mode, syntax: Syntax) -> Self {
        Self {
            writer,
            mode,
            syntax,
        }
    }

    pub fn into_inner(self) -> W {
        self.writer
    }

    pub fn set_mode(&mut self, mode: X86Mode) {
        self.mode = mode;
    }

    pub fn mode(&self) -> X86Mode {
        self.mode
    }

    pub fn set_syntax(&mut self, syntax: Syntax) {
        self.syntax = syntax
    }

    pub fn syntax(&self) -> Syntax {
        self.syntax
    }
}

impl<W> Deref for InsnPrinter<W> {
    type Target = W;
    fn deref(&self) -> &W {
        &self.writer
    }
}

impl<W> DerefMut for InsnPrinter<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.writer
    }
}

impl<W: core::fmt::Write> InsnPrinter<W> {
    pub fn write_insn(&mut self, insn: &X86Instruction) -> core::fmt::Result {
        let mode = insn.mode_override().unwrap_or(self.mode);

        match self.syntax {
            Syntax::Intel => {
                let mut addr_mode = mode.largest_gpr();
                for op in insn.operands() {
                    match op {
                        super::insn::X86Operand::ModRM(modrm)
                        | super::insn::X86Operand::FarModRM { modrm, .. } => match modrm {
                            ModRM::Indirect { mode, .. }
                            | ModRM::IndirectDisp8 { mode, .. }
                            | ModRM::IndirectDisp32 { mode, .. } => match mode {
                                super::insn::ModRMRegOrSib::Reg(r) => addr_mode = r.class(),
                                super::insn::ModRMRegOrSib::Abs(_) => todo!(),
                                super::insn::ModRMRegOrSib::RipRel(_) => todo!(),
                                super::insn::ModRMRegOrSib::Sib { base, .. } => {
                                    addr_mode = base.class()
                                }
                                super::insn::ModRMRegOrSib::Index16 { .. } => {
                                    addr_mode = X86RegisterClass::Word
                                }
                            },
                            _ => {}
                        },
                        _ => {}
                    }
                }

                if addr_mode != mode.largest_gpr() {
                    self.writer
                        .write_fmt(format_args!("addr{} ", addr_mode.size(mode) * 8))?;
                }
                self.writer.write_fmt(format_args!("{} ", insn.opcode()))?;
            }
            Syntax::Att(_) => todo!("att_syntax"),
        }
        Ok(())
    }
}