diff options
Diffstat (limited to 'src/display.rs')
-rw-r--r-- | src/display.rs | 314 |
1 files changed, 193 insertions, 121 deletions
diff --git a/src/display.rs b/src/display.rs index 12153b1..1927df1 100644 --- a/src/display.rs +++ b/src/display.rs @@ -2,165 +2,237 @@ use ::{MSP430, Operand, Opcode, Instruction, Width}; use std::fmt::{Display, Formatter}; use std; -use yaxpeax_arch::{Arch, Colorize, NoColors, ShowContextual, YaxColors}; +use yaxpeax_arch::Arch; +// not removing these quite yet... +#[allow(deprecated)] +use yaxpeax_arch::{Colorize, ShowContextual, YaxColors}; +use yaxpeax_arch::display::DisplaySink; -impl Display for Instruction { - fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { - let mut s = String::new(); - self.contextualize(&NoColors, 0, Some(&NoContext), &mut s).unwrap(); - write!(f, "{}", s) - } -} - -/// No per-operand when contextualizing an instruction. -pub struct NoContext; - -impl <T: std::fmt::Write, Y: YaxColors> ShowContextual<<MSP430 as Arch>::Address, NoContext, T, Y> for Instruction { - fn contextualize(&self, _colors: &Y, _address: <MSP430 as Arch>::Address, _context: Option<&NoContext>, out: &mut T) -> std::fmt::Result { - write!(out, "{}", self.opcode)?; - match self.op_width { - Width::B => { write!(out, ".b")? }, - Width::W => { } - }; - match self.operands[0] { - Operand::Nothing => return Ok(()), - x @ _ => { - write!(out, " {}", x)?; - } - }; - match self.operands[1] { - Operand::Nothing => return Ok(()), - x @ _ => { - write!(out, ", {}", x)?; - } - }; - Ok(()) - } -} - -#[cfg(feature="std")] -impl <T: std::fmt::Write, Y: YaxColors> ShowContextual<<MSP430 as Arch>::Address, [Option<String>], T, Y> for Instruction { - fn contextualize(&self, _colors: &Y, _address: <MSP430 as Arch>::Address, _context: Option<&[Option<String>]>, out: &mut T) -> std::fmt::Result { - write!(out, "{}", self.opcode)?; - match self.op_width { - Width::B => { write!(out, ".b")? }, - Width::W => { } - }; - match self.operands[0] { - Operand::Nothing => return Ok(()), - x @ _ => { - write!(out, " {}", x)?; - } - }; - match self.operands[1] { - Operand::Nothing => return Ok(()), - x @ _ => { - write!(out, ", {}", x)?; - } - }; - Ok(()) - } +trait DisplaySinkExt { + fn write_register(&mut self, reg: u8) -> std::fmt::Result; + fn write_opcode(&mut self, opc: &Opcode) -> std::fmt::Result; + fn write_operand(&mut self, op: &Operand) -> std::fmt::Result; } -impl Display for Opcode { - fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { - match self { - Opcode::Invalid(a) => { write!(f, "invalid({:04x})", a) }, - Opcode::RRC => { write!(f, "rrc") }, - Opcode::SWPB => { write!(f, "swpb") }, - Opcode::RRA => { write!(f, "rra") }, - Opcode::SXT => { write!(f, "sxt") }, - Opcode::PUSH => { write!(f, "push") }, - Opcode::CALL => { write!(f, "call") }, - Opcode::RETI => { write!(f, "reti") }, - Opcode::JNE => { write!(f, "jne") }, - Opcode::JEQ => { write!(f, "jeq") }, - Opcode::JNC => { write!(f, "jnc") }, - Opcode::JC => { write!(f, "jc") }, - Opcode::JN => { write!(f, "jn") }, - Opcode::JGE => { write!(f, "jge") }, - Opcode::JL => { write!(f, "jl") }, - Opcode::JMP => { write!(f, "jmp") }, - Opcode::MOV => { write!(f, "mov") }, - Opcode::ADD => { write!(f, "add") }, - Opcode::ADDC => { write!(f, "addc") }, - Opcode::SUBC => { write!(f, "subc") }, - Opcode::SUB => { write!(f, "sub") }, - Opcode::CMP => { write!(f, "cmp") }, - Opcode::DADD => { write!(f, "dadd") }, - Opcode::BIT => { write!(f, "bit") }, - Opcode::BIC => { write!(f, "bic") }, - Opcode::BIS => { write!(f, "bis") }, - Opcode::XOR => { write!(f, "xor") }, - Opcode::AND => { write!(f, "and") } +impl<T: DisplaySink> DisplaySinkExt for T { + fn write_opcode(&mut self, opc: &Opcode) -> std::fmt::Result { + match opc { + Opcode::Invalid(a) => { + self.write_fixed_size("invalid")?; + self.write_char('(')?; + self.write_u16(*a)?; + self.write_char(')') + }, + Opcode::RRC => { self.write_fixed_size("rrc") }, + Opcode::SWPB => { self.write_fixed_size("swpb") }, + Opcode::RRA => { self.write_fixed_size("rra") }, + Opcode::SXT => { self.write_fixed_size("sxt") }, + Opcode::PUSH => { self.write_fixed_size("push") }, + Opcode::CALL => { self.write_fixed_size("call") }, + Opcode::RETI => { self.write_fixed_size("reti") }, + Opcode::JNE => { self.write_fixed_size("jne") }, + Opcode::JEQ => { self.write_fixed_size("jeq") }, + Opcode::JNC => { self.write_fixed_size("jnc") }, + Opcode::JC => { self.write_fixed_size("jc") }, + Opcode::JN => { self.write_fixed_size("jn") }, + Opcode::JGE => { self.write_fixed_size("jge") }, + Opcode::JL => { self.write_fixed_size("jl") }, + Opcode::JMP => { self.write_fixed_size("jmp") }, + Opcode::MOV => { self.write_fixed_size("mov") }, + Opcode::ADD => { self.write_fixed_size("add") }, + Opcode::ADDC => { self.write_fixed_size("addc") }, + Opcode::SUBC => { self.write_fixed_size("subc") }, + Opcode::SUB => { self.write_fixed_size("sub") }, + Opcode::CMP => { self.write_fixed_size("cmp") }, + Opcode::DADD => { self.write_fixed_size("dadd") }, + Opcode::BIT => { self.write_fixed_size("bit") }, + Opcode::BIC => { self.write_fixed_size("bic") }, + Opcode::BIS => { self.write_fixed_size("bis") }, + Opcode::XOR => { self.write_fixed_size("xor") }, + Opcode::AND => { self.write_fixed_size("and") } } } -} - -impl Display for Operand { - fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { - let mut s = String::new(); - self.colorize(&NoColors, &mut s).unwrap(); - write!(f, "{}", s) + fn write_register(&mut self, r: u8) -> std::fmt::Result { + self.span_start_number(); + write!(self, "R{}", r)?; + self.span_end_number(); + Ok(()) } -} -impl <T: std::fmt::Write, Y: YaxColors> Colorize<T, Y> for Operand { - fn colorize(&self, _colors: &Y, out: &mut T) -> std::fmt::Result { - fn signed_hex(num: i16) -> String { - if num >= 0 { - format!("+{:#x}", num) - } else { - format!("-{:#x}", -num) - } - } - match self { + fn write_operand(&mut self, op: &Operand) -> std::fmt::Result { + match op { Operand::Register(reg) => { - write!(out, "R{}", reg) + self.write_register(*reg) }, Operand::Indexed(reg, offset) => { - write!(out, "{}(R{})", signed_hex(*offset as i16), reg) + self.span_start_number(); + self.write_prefixed_i16(*offset as i16)?; + self.span_end_number(); + self.write_char('(')?; + self.write_register(*reg)?; + self.write_char(')')?; + Ok(()) }, Operand::RegisterIndirect(reg) => { - write!(out, "@R{}", reg) + self.write_fixed_size("@R")?; + self.write_register(*reg) }, Operand::IndirectAutoinc(reg) => { - write!(out, "@R{}+", reg) + self.write_fixed_size("@R")?; + self.write_register(*reg)?; + self.write_fixed_size("+") }, Operand::Offset(offset) => { - write!(out, "${}", signed_hex(*offset as i16)) + self.write_char('$')?; + let offset: i16 = *offset as i16; + if offset >= 0 { + self.write_char('+')?; + } + self.span_start_number(); + self.write_prefixed_i16(offset)?; + self.span_end_number(); + Ok(()) }, Operand::Symbolic(offset) => { - write!(out, "{}(PC)", signed_hex(*offset as i16)) + self.span_start_number(); + self.write_prefixed_i16(*offset as i16)?; + self.span_end_number(); + self.write_char('(')?; + self.span_start_program_counter(); + self.write_fixed_size("PC")?; + self.span_end_program_counter(); + self.write_char(')')?; + Ok(()) }, Operand::Immediate(imm) => { - write!(out, "#0x{:x}", imm) + self.span_start_number(); + self.write_char('#')?; + self.write_prefixed_u16(*imm)?; + self.span_end_number(); + Ok(()) }, Operand::Absolute(offset) => { - write!(out, "&0x{:x}", offset) + self.span_start_address(); + self.write_char('&')?; + self.write_prefixed_u16(*offset)?; + self.span_end_address(); + Ok(()) }, Operand::Const4 => { - write!(out, "4") + self.span_start_address(); + write!(self, "4")?; + self.span_end_address(); + Ok(()) }, Operand::Const8 => { - write!(out, "8") + self.span_start_address(); + write!(self, "8")?; + self.span_end_address(); + Ok(()) }, Operand::Const0 => { - write!(out, "0") + self.span_start_address(); + write!(self, "0")?; + self.span_end_address(); + Ok(()) }, Operand::Const1 => { - write!(out, "1") + self.span_start_address(); + write!(self, "1")?; + self.span_end_address(); + Ok(()) }, Operand::Const2 => { - write!(out, "2") + self.span_start_address(); + write!(self, "2")?; + self.span_end_address(); + Ok(()) }, Operand::ConstNeg1 => { - write!(out, "-1") + self.span_start_address(); + write!(self, "-1")?; + self.span_end_address(); + Ok(()) }, Operand::Nothing => { - write!(out, "<No Operand>") + write!(self, "<No Operand>") } } } } + +impl Display for Instruction { + fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { + let mut out = yaxpeax_arch::display::FmtSink::new(f); + display(self, &mut out) + } +} + +// the following few items depend on deprecated traits, but not removing them yet +/// No per-operand when contextualizing an instruction. +#[allow(deprecated)] +pub struct NoContext; + +#[allow(deprecated)] +impl <T: std::fmt::Write, Y: YaxColors> ShowContextual<<MSP430 as Arch>::Address, NoContext, T, Y> for Instruction { + fn contextualize(&self, _colors: &Y, _address: <MSP430 as Arch>::Address, _context: Option<&NoContext>, out: &mut T) -> std::fmt::Result { + let mut out = yaxpeax_arch::display::FmtSink::new(out); + display(self, &mut out) + } +} + +#[cfg(feature="std")] +#[allow(deprecated)] +impl <T: std::fmt::Write, Y: YaxColors> ShowContextual<<MSP430 as Arch>::Address, [Option<String>], T, Y> for Instruction { + fn contextualize(&self, _colors: &Y, _address: <MSP430 as Arch>::Address, _context: Option<&[Option<String>]>, out: &mut T) -> std::fmt::Result { + let mut out = yaxpeax_arch::display::FmtSink::new(out); + display(self, &mut out) + } +} + +pub(crate) fn display<T: DisplaySink>(instr: &Instruction, out: &mut T) -> std::fmt::Result { + out.write_opcode(&instr.opcode)?; + if instr.op_width == Width::B { + out.write_fixed_size(".b")?; + } + + match instr.operands[0] { + Operand::Nothing => return Ok(()), + _ => { + out.write_char(' ')?; + out.write_operand(&instr.operands[0])?; + } + }; + match instr.operands[1] { + Operand::Nothing => return Ok(()), + _ => { + out.write_char(' ')?; + out.write_char(',')?; + out.write_operand(&instr.operands[1])?; + } + }; + Ok(()) +} + +impl Display for Opcode { + fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { + let mut out = yaxpeax_arch::display::FmtSink::new(f); + out.write_opcode(self) + } +} + +impl Display for Operand { + fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { + let mut out = yaxpeax_arch::display::FmtSink::new(f); + out.write_operand(self) + } +} + +#[allow(deprecated)] +impl <T: std::fmt::Write, Y: YaxColors> Colorize<T, Y> for Operand { + fn colorize(&self, _colors: &Y, out: &mut T) -> std::fmt::Result { + let mut out = yaxpeax_arch::display::FmtSink::new(out); + out.write_operand(self) + } +} |