use ::{MSP430, Operand, Opcode, Instruction, Width}; use std::fmt::{Display, Formatter}; use std; use yaxpeax_arch::Arch; // not removing these quite yet... #[allow(deprecated)] use yaxpeax_arch::{Colorize, ShowContextual, YaxColors}; use yaxpeax_arch::display::DisplaySink; 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 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") } } } fn write_register(&mut self, r: u8) -> std::fmt::Result { self.span_start_number(); write!(self, "R{}", r)?; self.span_end_number(); Ok(()) } fn write_operand(&mut self, op: &Operand) -> std::fmt::Result { match op { Operand::Register(reg) => { self.write_register(*reg) }, Operand::Indexed(reg, offset) => { 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) => { self.write_fixed_size("@R")?; self.write_register(*reg) }, Operand::IndirectAutoinc(reg) => { self.write_fixed_size("@R")?; self.write_register(*reg)?; self.write_fixed_size("+") }, Operand::Offset(offset) => { 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) => { 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) => { self.span_start_number(); self.write_char('#')?; self.write_prefixed_u16(*imm)?; self.span_end_number(); Ok(()) }, Operand::Absolute(offset) => { self.span_start_address(); self.write_char('&')?; self.write_prefixed_u16(*offset)?; self.span_end_address(); Ok(()) }, Operand::Const4 => { self.span_start_address(); write!(self, "4")?; self.span_end_address(); Ok(()) }, Operand::Const8 => { self.span_start_address(); write!(self, "8")?; self.span_end_address(); Ok(()) }, Operand::Const0 => { self.span_start_address(); write!(self, "0")?; self.span_end_address(); Ok(()) }, Operand::Const1 => { self.span_start_address(); write!(self, "1")?; self.span_end_address(); Ok(()) }, Operand::Const2 => { self.span_start_address(); write!(self, "2")?; self.span_end_address(); Ok(()) }, Operand::ConstNeg1 => { self.span_start_address(); write!(self, "-1")?; self.span_end_address(); Ok(()) }, Operand::Nothing => { write!(self, "") } } } } 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 ShowContextual<::Address, NoContext, T, Y> for Instruction { fn contextualize(&self, _colors: &Y, _address: ::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 ShowContextual<::Address, [Option], T, Y> for Instruction { fn contextualize(&self, _colors: &Y, _address: ::Address, _context: Option<&[Option]>, out: &mut T) -> std::fmt::Result { let mut out = yaxpeax_arch::display::FmtSink::new(out); display(self, &mut out) } } pub(crate) fn display(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 Colorize 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) } }