diff options
| -rw-r--r-- | CHANGELOG | 4 | ||||
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | src/display.rs | 314 | 
3 files changed, 199 insertions, 123 deletions
@@ -1,3 +1,7 @@ +# 0.2.0 + +update to yaxpeax-arch 0.3.1, support `yaxpeax_arch::display::DisplaySink` +  # 0.1.1  add support for `yaxpeax_arch::AnnotatingDecoder` @@ -1,14 +1,14 @@  [package]  name = "yaxpeax-msp430" -version = "0.1.1" +version = "0.2.0"  authors = [ "iximeow <me@iximeow.net>" ]  license = "0BSD"  repository = "http://git.iximeow.net/yaxpeax-msp430/"  description = "msp430 decoders for the yaxpeax project"  [dependencies] -yaxpeax-arch = { version = "0.2.7", default-features = false, features = [] } +yaxpeax-arch = { version = "0.3.1", default-features = false, features = [] }  "serde" = { version = "1.0", optional = true }  "serde_derive" = { version = "1.0", optional = true } 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) +    } +}  | 
