diff options
| author | iximeow <me@iximeow.net> | 2020-01-03 19:17:53 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 17:08:59 -0800 | 
| commit | d03c04b89e7ffb3cce9f830e873e8b50e6b5fd9e (patch) | |
| tree | daf45089626f95fce2debfb37ca2bd0121fba57f | |
| parent | 693e21378ecec332254d48642cd7b751cabeb6da (diff) | |
match changes in arch to have Resulty decode, instead of Option
| -rw-r--r-- | src/display.rs | 14 | ||||
| -rw-r--r-- | src/lib.rs | 52 | 
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)?; @@ -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(())              }          }      } | 
