summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/display.rs39
-rw-r--r--src/lib.rs43
-rw-r--r--test/test.rs4
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)
diff --git a/src/lib.rs b/src/lib.rs
index 408216e..74f814c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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() {