summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-01-03 19:17:53 -0800
committeriximeow <me@iximeow.net>2020-01-12 17:08:59 -0800
commitd03c04b89e7ffb3cce9f830e873e8b50e6b5fd9e (patch)
treedaf45089626f95fce2debfb37ca2bd0121fba57f
parent693e21378ecec332254d48642cd7b751cabeb6da (diff)
match changes in arch to have Resulty decode, instead of Option
-rw-r--r--src/display.rs14
-rw-r--r--src/lib.rs52
2 files changed, 47 insertions, 19 deletions
diff --git a/src/display.rs b/src/display.rs
index 4593f20..7836d10 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -1,6 +1,6 @@
-use ::{MSP430, Operand, Opcode, Instruction, Width};
+use ::{MSP430, Operand, Opcode, Instruction, Width, DecodeError};
-use std::fmt::{Display, Formatter};
+use std::fmt::{self, Display, Formatter};
use std;
use yaxpeax_arch::{Arch, Colorize, ColorSettings, ShowContextual};
@@ -12,6 +12,16 @@ impl Display for Instruction {
}
}
+impl fmt::Display for DecodeError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ DecodeError::ExhaustedInput => write!(f, "exhausted input"),
+ DecodeError::InvalidOpcode => write!(f, "invalid opcode"),
+ DecodeError::InvalidOperand => write!(f, "invalid operand"),
+ }
+ }
+}
+
impl <T: std::fmt::Write> ShowContextual<<MSP430 as Arch>::Address, [Option<String>], T> 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)?;
diff --git a/src/lib.rs b/src/lib.rs
index faca813..408216e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -23,6 +23,7 @@ pub struct MSP430;
impl Arch for MSP430 {
type Address = u16;
type Instruction = Instruction;
+ type DecodeError = DecodeError;
type Decoder = InstDecoder;
type Operand = Operand;
}
@@ -125,23 +126,40 @@ pub enum Operand {
Nothing
}
+#[derive(Debug, PartialEq)]
+pub enum DecodeError {
+ ExhaustedInput,
+ InvalidOpcode,
+ InvalidOperand,
+}
+
+impl yaxpeax_arch::DecodeError for DecodeError {
+ fn data_exhausted(&self) -> bool { self == &DecodeError::ExhaustedInput }
+ fn bad_opcode(&self) -> bool { self == &DecodeError::InvalidOpcode }
+ fn bad_operand(&self) -> bool { self == &DecodeError::InvalidOperand }
+}
+
+impl yaxpeax_arch::Instruction for Instruction {
+ // TODO: this is wrong!!
+ fn well_defined(&self) -> bool { true }
+}
+
#[derive(Default, Debug)]
pub struct InstDecoder {}
impl Decoder<Instruction> for InstDecoder {
- fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> {
+ type Error = DecodeError;
+
+ fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Result<Instruction, Self::Error> {
let mut inst = Instruction::blank();
- match self.decode_into(&mut inst, bytes) {
- Some(_) => Some(inst),
- None => None
- }
+ self.decode_into(&mut inst, bytes).map(|_: ()| inst)
}
- fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Option<()> {
+ 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();
let fullword = match word[..] {
- [] | [_] => { return None; },
+ [] | [_] => { return Err(DecodeError::ExhaustedInput); },
[low, high] => (high as u16) << 8 | (low as u16),
_ => unreachable!()
};
@@ -245,7 +263,7 @@ impl Decoder<Instruction> for InstDecoder {
} else {
if x == 1 || x == 3 || x == 5 {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOpcode);
}
Width:: B
};
@@ -256,25 +274,25 @@ impl Decoder<Instruction> for InstDecoder {
);
if !decode_operand(&mut bytes_iter, source, As, &mut inst.operands[0]) {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOperand);
};
inst.operands[1] = Operand::Nothing;
- Some(())
+ Ok(())
},
6 => {
if operands == 0 {
inst.opcode = Opcode::RETI;
inst.operands[0] = Operand::Nothing;
inst.operands[1] = Operand::Nothing;
- Some(())
+ Ok(())
} else {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOperand);
}
}
7 => {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOpcode);
}
_ => {
unreachable!();
@@ -295,7 +313,7 @@ impl Decoder<Instruction> for InstDecoder {
][opcode_idx as usize];
inst.operands[0] = Operand::Offset(((offset as i16) << 6) >> 6);
inst.operands[1] = Operand::Nothing;
- Some(())
+ Ok(())
},
instrword @ _ => {
let (opcode_idx, operands) = ((instrword & 0xf000) >> 12, instrword & 0x0fff);
@@ -323,13 +341,13 @@ impl Decoder<Instruction> for InstDecoder {
);
if !decode_operand(&mut bytes_iter, source, As, &mut inst.operands[0]) {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOperand);
}
if !decode_operand(&mut bytes_iter, dest, Ad, &mut inst.operands[1]) {
inst.opcode = Opcode::Invalid(instrword);
- return None;
+ return Err(DecodeError::InvalidOperand);
}
- Some(())
+ Ok(())
}
}
}