diff options
| author | iximeow <me@iximeow.net> | 2020-01-03 22:56:28 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 17:19:51 -0800 | 
| commit | ac535caef2da0d82e1e09e053a1186bd737b05d7 (patch) | |
| tree | fb93915474490ef014e505f22df783782eb94531 /src | |
| parent | 332e003cea648a24d40a23899ffc5669ae809da2 (diff) | |
match changes in arch to have Rusty decode, instead of Option
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 144 | 
1 files changed, 87 insertions, 57 deletions
@@ -5,6 +5,8 @@ extern crate serde;  //#[cfg(feature="use-serde")]  //use serde::{Serialize, Deserialize}; +use std::fmt; +  extern crate yaxpeax_arch;  use yaxpeax_arch::{Arch, Decoder, LengthedInstruction}; @@ -23,6 +25,7 @@ pub struct PIC18;  impl Arch for PIC18 {      type Address = u32;      type Instruction = Instruction; +    type DecodeError = DecodeError;      type Decoder = InstDecoder;      type Operand = Operand;  } @@ -53,6 +56,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 { @@ -163,18 +194,17 @@ pub enum Operand {  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 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<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();          if word.len() != 2 { -            return None; +            return Err(DecodeError::ExhaustedInput);          }  //            println!("Decoding {:x?}", word); @@ -183,87 +213,87 @@ impl Decoder<Instruction> for InstDecoder {                  match word[0] {                      0x00 => {                          inst.opcode = Opcode::NOP; -                        Some(()) +                        Ok(())                      },                      0b00000011 => {                          inst.opcode = Opcode::SLEEP; -                        Some(()) +                        Ok(())                      },                      0b00000100 => {                          inst.opcode = Opcode::CLRWDT; -                        Some(()) +                        Ok(())                      },                      0b00000101 => {                          inst.opcode = Opcode::PUSH; -                        Some(()) +                        Ok(())                      },                      0b00000110 => {                          inst.opcode = Opcode::POP; -                        Some(()) +                        Ok(())                      },                      0b00000111 => {                          inst.opcode = Opcode::DAW; -                        Some(()) +                        Ok(())                      },                      0b00001000 => {                          inst.opcode = Opcode::TBLRD_S; -                        Some(()) +                        Ok(())                      },                      0b00001001 => {                          inst.opcode = Opcode::TBLRD_S_I; -                        Some(()) +                        Ok(())                      },                      0b00001010 => {                          inst.opcode = Opcode::TBLRD_S_D; -                        Some(()) +                        Ok(())                      },                      0b00001011 => {                          inst.opcode = Opcode::TBLRD_I_S; -                        Some(()) +                        Ok(())                      },                      0b00001100 => {                          inst.opcode = Opcode::TBLWT_S; -                        Some(()) +                        Ok(())                      },                      0b00001101 => {                          inst.opcode = Opcode::TBLWT_S_I; -                        Some(()) +                        Ok(())                      },                      0b00001110 => {                          inst.opcode = Opcode::TBLWT_S_D; -                        Some(()) +                        Ok(())                      },                      0b00001111 => {                          inst.opcode = Opcode::TBLWT_I_S; -                        Some(()) +                        Ok(())                      },                      0b00010000 => {                          inst.opcode = Opcode::RETFIE; -                        Some(()) +                        Ok(())                      },                      0b00010001 => {                          inst.opcode = Opcode::RETFIE_FAST; -                        Some(()) +                        Ok(())                      },                      0b00010010 => {                          inst.opcode = Opcode::RETURN; -                        Some(()) +                        Ok(())                      },                      0b00010011 => {                          inst.opcode = Opcode::RETURN_FAST; -                        Some(()) +                        Ok(())                      },                      0b00010100 => {                          inst.opcode = Opcode::CALLW; -                        Some(()) +                        Ok(())                      },                      0b11111111 => {                          inst.opcode = Opcode::RESET; -                        Some(()) +                        Ok(())                      },                      _ => {                          inst.opcode = Opcode::Invalid(word[0], word[1]); -                        None +                        Err(DecodeError::InvalidOpcode)                      }                  }              }, @@ -271,60 +301,60 @@ impl Decoder<Instruction> for InstDecoder {                  inst.opcode = Opcode::MOVLB;                  // this ignores high nibble of low word. ok by isa, but...                  inst.operands[0] = Operand::ImmediateU8(word[0] & 0x0f); -                Some(()) +                Ok(())              },              0x02 | 0x03 => {                  inst.opcode = Opcode::MULWF;                  let a = (word[1] & 0x01) == 1;                  inst.operands[0] = Operand::File(word[0], a); -                Some(()) +                Ok(())              },              0x04 | 0x05 | 0x06 | 0x07 => {                  inst.opcode = Opcode::DECF;                  let d = ((word[1] >> 1) & 0x01u8) == 1u8;                  let a = (word[1] & 0x01) == 1;                  inst.operands[0] = Operand::RedirectableFile(word[0], a, d); -                Some(()) +                Ok(())              },              0x08 => {                  inst.opcode = Opcode::SUBLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x09 => {                  inst.opcode = Opcode::IORLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0a => {                  inst.opcode = Opcode::XORLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0b => {                  inst.opcode = Opcode::ANDLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0c => {                  inst.opcode = Opcode::RETLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0d => {                  inst.opcode = Opcode::MULLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0e => {                  inst.opcode = Opcode::MOVLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0x0f => {                  inst.opcode = Opcode::ADDLW;                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              x if x >= 0x10 && x < 0b01100000 => {                  let da = x & 0b0011; @@ -352,7 +382,7 @@ impl Decoder<Instruction> for InstDecoder {                      Opcode::SUBWF                  ][opc as usize];                  inst.operands[0] = Operand::RedirectableFile(word[0], (da & 0x01) == 0x01, (da & 0x02) == 0x02); -                Some(()) +                Ok(())              },              x if x >= 0b01100000 && x < 0b01110000 => {                  let a = x & 1; @@ -368,7 +398,7 @@ impl Decoder<Instruction> for InstDecoder {                      Opcode::MOVWF                  ][opc as usize];                  inst.operands[0] = Operand::File(word[0], a == 1); -                Some(()) +                Ok(())              },              x if x >= 0b01110000 && x < 0b11000000 => {                  let a = x & 1; @@ -383,23 +413,23 @@ impl Decoder<Instruction> for InstDecoder {                  let bit = (x >> 1) & 0b0000111;                  inst.operands[0] = Operand::File(word[0], a == 1);                  inst.operands[1] = Operand::ImmediateU8(bit); -                Some(()) +                Ok(())              },              x if x >= 0b11000000 && x < 0b11010000 => {                  inst.opcode = Opcode::MOVFF;                  let word2: Vec<u8> = bytes_iter.take(2).collect();                  if word2.len() != 2 { -                    return None; +                    return Err(DecodeError::ExhaustedInput);                  }                  if word2[1] & 0xf0 != 0xf0 { -                    return None; +                    return Err(DecodeError::InvalidOperand);                  }                  let src = (word[0] as u16) | ((word[1] as u16 & 0x0f) << 8);                  let dest = (word2[0] as u16) | ((word2[1] as u16 & 0x0f) << 8);                  inst.operands[0] = Operand::AbsoluteFile(src);                  inst.operands[1] = Operand::AbsoluteFile(dest); -                Some(()) +                Ok(())              },              x if x >= 0b11010000 && x < 0b11100000 => {                  inst.opcode = [ @@ -407,7 +437,7 @@ impl Decoder<Instruction> for InstDecoder {                      Opcode::RCALL                  ][((x >> 3) & 1) as usize];                  inst.operands[0] = Operand::ImmediateU32((((x & 0b111) as u32) << 8) | word[0] as u32); -                Some(()) +                Ok(())              },              x if x >= 0b11100000 && x < 0b11101000 => {                  let opc = x & 0b00000111; @@ -422,17 +452,17 @@ impl Decoder<Instruction> for InstDecoder {                      Opcode::BNN                  ][opc as usize];                  inst.operands[0] = Operand::ImmediateU8(word[0]); -                Some(()) +                Ok(())              },              0xee => {                  let f_k_msb = word[0];                  let word2: Vec<u8> = bytes_iter.take(2).collect();                  if word2.len() != 2 { -                    return None; +                    return Err(DecodeError::ExhaustedInput);                  }                  if (word2[1] & 0xf0) != 0xf0 { -                    return None; // invalid instruction +                    return Err(DecodeError::InvalidOperand);                  }                  inst.opcode = Opcode::LFSR; @@ -443,7 +473,7 @@ impl Decoder<Instruction> for InstDecoder {                  inst.operands[0] = Operand::FileFSR(f);                  inst.operands[1] = Operand::ImmediateU32(((k_msb as u32) << 8) | (k_lsb as u32)); -                Some(()) +                Ok(())              }              /* ... */              0xeb | 0xec => { @@ -451,37 +481,37 @@ impl Decoder<Instruction> for InstDecoder {                  let k_lsb = word[0];                  let word2: Vec<u8> = bytes_iter.take(2).collect();                  if word2.len() != 2 { -                    return None; +                    return Err(DecodeError::ExhaustedInput);                  }                  if (word2[1] & 0xf0) != 0xf0 { -                    return None; // invalid instruction +                    return Err(DecodeError::InvalidOperand);                  }                  let k_msb = (((word2[1] & 0xf) as u32) << 8) | word2[0] as u32;                  inst.opcode = Opcode::CALL;                  inst.operands[0] = Operand::ImmediateU32(((k_msb << 8) | k_lsb as u32) << 1); -                Some(()) +                Ok(())              }              0xef => {                  let k_lsb = word[0];                  let word2: Vec<u8> = bytes_iter.take(2).collect();                  if word2.len() != 2 { -                    return None; +                    return Err(DecodeError::ExhaustedInput);                  }                  if (word2[1] & 0xf0) != 0xf0 { -                    return None; // invalid instruction +                    return Err(DecodeError::InvalidOperand);                  }                  let k_msb = (((word2[1] & 0xf) as u32) << 8) | word2[0] as u32;                  inst.opcode = Opcode::GOTO;                  inst.operands[0] = Operand::ImmediateU32(((k_msb << 8) | k_lsb as u32) << 1); -                Some(()) +                Ok(())              } -            _ => None +            _ => Err(DecodeError::InvalidOpcode)          }      }  }  | 
