summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/display.rs314
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)
+ }
+}