From e7cbde7e54646de2e66275fd08bcddfdd2014e76 Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 3 Jan 2020 19:41:53 -0800 Subject: match changes in arch to have Resulty decode, instead of Option --- src/lib.rs | 82 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cc70c16..ebfb914 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ extern crate termion; use yaxpeax_arch::{Arch, ColorSettings, Colorize, Decoder, LengthedInstruction, ShowContextual}; -use std::fmt::{Display, Formatter}; +use std::fmt::{self, Display, Formatter}; use termion::color; @@ -31,6 +31,7 @@ pub struct PIC17; impl Arch for PIC17 { type Address = u16; type Instruction = Instruction; + type DecodeError = DecodeError; type Decoder = InstDecoder; type Operand = Operand; } @@ -66,6 +67,34 @@ impl LengthedInstruction for Instruction { } } +#[derive(Debug, PartialEq)] +pub enum DecodeError { + ExhaustedInput, + InvalidOpcode, + InvalidOperand, +} + +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 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 } +} + impl Instruction { pub fn blank() -> Instruction { Instruction { @@ -283,18 +312,17 @@ impl Display for Operand { pub struct InstDecoder {} impl Decoder for InstDecoder { - fn decode>(&self, bytes: T) -> Option { + type Error = DecodeError; + + fn decode>(&self, bytes: T) -> Result { let mut blank = Instruction::blank(); - match self.decode_into(&mut blank, bytes) { - Some(_) => Some(blank), - None => None - } + self.decode_into(&mut blank, bytes).map(|_: ()| blank) } - fn decode_into>(&self, inst: &mut Instruction, bytes: T) -> Option<()> { + fn decode_into>(&self, inst: &mut Instruction, bytes: T) -> Result<(), DecodeError> { let mut bytes_iter = bytes.into_iter(); let word: Vec = bytes_iter.by_ref().take(2).collect(); if word.len() != 2 { - return None; + return Err(DecodeError::ExhaustedInput); } match word[1] { @@ -303,34 +331,34 @@ impl Decoder for InstDecoder { match word[0] { 0x00 => { inst.opcode = Opcode::NOP; - Some(()) + Ok(()) }, 0b00000010 => { inst.opcode = Opcode::RETURN; - Some(()) + Ok(()) }, 0b00000011 => { inst.opcode = Opcode::SLEEP; - Some(()) + Ok(()) }, 0b00000100 => { inst.opcode = Opcode::CLRWDT; - Some(()) + Ok(()) }, 0b00000101 => { inst.opcode = Opcode::RETFIE; - Some(()) + Ok(()) }, _ => { inst.opcode = Opcode::Invalid(word[1], word[0]); - None + Err(DecodeError::InvalidOpcode) } } }, 0x01 => { inst.opcode = Opcode::MOVWF; inst.operands = [Operand::File(word[0]), Operand::Nothing]; - Some(()) + Ok(()) }, x if x < 0x30 => { // TODO: consume @@ -366,7 +394,7 @@ impl Decoder for InstDecoder { } else { Operand::W }; - Some(()) + Ok(()) }, x if x < 0x40 => { inst.operands = [Operand::File(word[0]), Operand::Nothing]; @@ -376,9 +404,9 @@ impl Decoder for InstDecoder { 0x32 => Opcode::CPFSGT, 0x33 => Opcode::MULWF, 0x34 => Opcode::TSTFSZ, - 0x35 => { Opcode::Invalid(word[1], word[0]); return None }, - 0x36 => { Opcode::Invalid(word[1], word[0]); return None }, - 0x37 => { Opcode::Invalid(word[1], word[0]); return None }, + 0x35 => { Opcode::Invalid(word[1], word[0]); return Err(DecodeError::InvalidOpcode) }, + 0x36 => { Opcode::Invalid(word[1], word[0]); return Err(DecodeError::InvalidOpcode) }, + 0x37 => { Opcode::Invalid(word[1], word[0]); return Err(DecodeError::InvalidOpcode) }, 0x38 => { inst.operands[1] = Operand::ImmediateU8(0); Opcode::BTG }, 0x39 => { inst.operands[1] = Operand::ImmediateU8(1); Opcode::BTG }, 0x3a => { inst.operands[1] = Operand::ImmediateU8(2); Opcode::BTG }, @@ -389,19 +417,19 @@ impl Decoder for InstDecoder { 0x3f => { inst.operands[1] = Operand::ImmediateU8(7); Opcode::BTG }, _ => { unreachable!(); } }; - Some(()) + Ok(()) }, x if x < 0x60 => { inst.opcode = Opcode::MOVPF; inst.operands[0] = Operand::File((word[1]) & 0x1f); inst.operands[1] = Operand::File(word[0]); - Some(()) + Ok(()) }, x if x < 0x80 => { inst.opcode = Opcode::MOVFP; inst.operands[0] = Operand::File(word[0]); inst.operands[1] = Operand::File((word[1]) & 0x1f); - Some(()) + Ok(()) }, x if x < 0xa0 => { inst.opcode = [ @@ -412,7 +440,7 @@ impl Decoder for InstDecoder { ][(((word[1]) >> 3) & 0x3) as usize]; inst.operands[0] = Operand::File(word[0]); inst.operands[1] = Operand::ImmediateU8((word[1]) & 0x7); - Some(()) + Ok(()) }, x if x < 0xb0 => { inst.opcode = [ @@ -434,7 +462,7 @@ impl Decoder for InstDecoder { Opcode::TABLWTHI ][(x & 0x0f) as usize]; inst.operands = [Operand::File(word[0]), Operand::Nothing]; - Some(()) + Ok(()) }, x if x < 0xc0 => { inst.opcode = [ @@ -456,17 +484,17 @@ impl Decoder for InstDecoder { Opcode::Invalid(word[1], word[0]) ][((word[1]) & 0x0f) as usize]; inst.operands = [Operand::ImmediateU8(word[0]), Operand::Nothing]; - Some(()) + Ok(()) }, x if x < 0xe0 => { inst.opcode = Opcode::GOTO; inst.operands = [Operand::ImmediateU32(word[0] as u32 | (((word[1] as u32) & 0x1f) << 8)), Operand::Nothing]; - Some(()) + Ok(()) }, _ => { inst.opcode = Opcode::CALL; inst.operands = [Operand::ImmediateU32(word[0] as u32 | (((word[1] as u32) & 0x1f) << 8)), Operand::Nothing]; - Some(()) + Ok(()) } } } -- cgit v1.1