diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/display.rs | 39 | ||||
-rw-r--r-- | src/lib.rs | 43 |
2 files changed, 68 insertions, 14 deletions
diff --git a/src/display.rs b/src/display.rs index 7836d10..f523e65 100644 --- a/src/display.rs +++ b/src/display.rs @@ -2,12 +2,12 @@ use ::{MSP430, Operand, Opcode, Instruction, Width, DecodeError}; use std::fmt::{self, Display, Formatter}; use std; -use yaxpeax_arch::{Arch, Colorize, ColorSettings, ShowContextual}; +use yaxpeax_arch::{Arch, Colorize, ColorSettings, NoColors, ShowContextual, YaxColors}; impl Display for Instruction { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { let mut s = String::new(); - self.contextualize(None, 0, None, &mut s).unwrap(); + self.contextualize(&NoColors, 0, Some(&NoContext), &mut s).unwrap(); write!(f, "{}", s) } } @@ -22,7 +22,34 @@ impl fmt::Display for DecodeError { } } -impl <T: std::fmt::Write> ShowContextual<<MSP430 as Arch>::Address, [Option<String>], T> for Instruction { +/// No per-operand when contextualizing an instruction. +struct NoContext; + +impl <T: std::fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<<MSP430 as Arch>::Address, NoContext, Color, 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, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<<MSP430 as Arch>::Address, [Option<String>], Color, T, Y> for Instruction { fn contextualize(&self, _colors: Option<&ColorSettings>, _address: <MSP430 as Arch>::Address, _context: Option<&[Option<String>]>, out: &mut T) -> std::fmt::Result { write!(out, "{}", self.opcode)?; match self.op_width { @@ -84,13 +111,13 @@ impl Display for Opcode { impl Display for Operand { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { let mut s = String::new(); - self.colorize(None, &mut s).unwrap(); + self.colorize(&NoColors, &mut s).unwrap(); write!(f, "{}", s) } } -impl <T: std::fmt::Write> Colorize<T> for Operand { - fn colorize(&self, _colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result { +impl <T: std::fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, 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) @@ -40,8 +40,8 @@ pub enum Width { W, B } -impl Instruction { - pub fn blank() -> Instruction { +impl Default for Instruction { + fn default() -> Instruction { Instruction { opcode: Opcode::Invalid(0xffff), op_width: Width::W, @@ -144,16 +144,39 @@ impl yaxpeax_arch::Instruction for Instruction { fn well_defined(&self) -> bool { true } } -#[derive(Default, Debug)] -pub struct InstDecoder {} +#[derive(Debug)] +pub struct InstDecoder { + flags: u8 +} + +impl InstDecoder { + pub fn minimal() -> Self { + InstDecoder { + flags: 0 + } + } + + pub fn with_microcorruption(mut self) -> Self { + self.flags |= 1; + self + } + + pub fn microcorruption_quirks(&self) -> bool { + (self.flags & 1) != 0 + } +} + +impl Default for InstDecoder { + fn default() -> Self { + InstDecoder { + flags: 0xff + } + } +} impl Decoder<Instruction> for InstDecoder { type Error = DecodeError; - fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<Instruction, Self::Error> { - let mut inst = Instruction::blank(); - self.decode_into(&mut inst, bytes).map(|_: ()| inst) - } fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Result<(), Self::Error> { let mut bytes_iter = bytes.into_iter(); let word: Vec<u8> = bytes_iter.by_ref().take(2).collect(); @@ -247,6 +270,10 @@ impl Decoder<Instruction> for InstDecoder { }, */ instrword if instrword < 0x2000 => { // microcorruption msp430 is non-standard and accepts invalid instructions.. + if !self.microcorruption_quirks() { + return Err(DecodeError::InvalidOpcode); + } + let (opcode_idx, operands) = ((instrword & 0x0380) >> 7, instrword & 0x7f); match opcode_idx { x if x < 6 => { |