diff options
| author | iximeow <me@iximeow.net> | 2020-01-16 23:53:37 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-16 23:53:37 -0800 | 
| commit | 8713eca470b00a7afc2d3d18b3fbe13c77806bc0 (patch) | |
| tree | f858fac3f465b5b69e5e82195e1a9aa47b9cd1e1 | |
| parent | d149e188cf2d8c53fe0c23642ae4831163ac9759 (diff) | |
compat with yaxpeax-arch changes, make microcorruption msp430 support optional
| -rw-r--r-- | src/display.rs | 39 | ||||
| -rw-r--r-- | src/lib.rs | 43 | ||||
| -rw-r--r-- | test/test.rs | 4 | 
3 files changed, 70 insertions, 16 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 => { diff --git a/test/test.rs b/test/test.rs index 5a59df4..663b080 100644 --- a/test/test.rs +++ b/test/test.rs @@ -1,8 +1,8 @@  extern crate yaxpeax_arch; -extern crate yaxpeax_msp430_mc; +extern crate yaxpeax_msp430;  use yaxpeax_arch::{Arch, Decoder}; -use yaxpeax_msp430_mc::{Opcode, MSP430}; +use yaxpeax_msp430::{Opcode, MSP430};  #[test]  fn test_decode() { | 
