diff options
| author | iximeow <me@iximeow.net> | 2019-11-28 02:21:34 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 17:29:01 -0800 | 
| commit | 179d5d9cb7e94851ba69bf67f6d2dfbafa6aa6fe (patch) | |
| tree | af40c09afea071cf75aec2680e8ca7661267bce2 | |
| parent | a2aaf35628135974a57dc2e09fb2d71eab2c35e5 (diff) | |
update arm to revised decoder trait
| -rw-r--r-- | src/armv7.rs | 210 | ||||
| -rw-r--r-- | src/armv8/a64.rs | 997 | ||||
| -rw-r--r-- | test/armv7.rs | 14 | ||||
| -rw-r--r-- | test/armv8/a64.rs | 169 | 
4 files changed, 899 insertions, 491 deletions
| diff --git a/src/armv7.rs b/src/armv7.rs index 9fe6fea..7d13c89 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -3,7 +3,7 @@  use std::fmt::{Display, Formatter}; -use yaxpeax_arch::{Arch, Colorize, Colored, ColorSettings, Decodable, LengthedInstruction, ShowContextual, YaxColors}; +use yaxpeax_arch::{Arch, Colorize, Colored, ColorSettings, Decoder, LengthedInstruction, ShowContextual, YaxColors};  struct ConditionedOpcode(pub Opcode, pub ConditionCode); @@ -668,16 +668,19 @@ impl ConditionCode {      }  } +#[derive(Default, Debug)] +pub struct InstDecoder {} +  #[allow(non_snake_case)] -impl Decodable for Instruction { -    fn decode<T: IntoIterator<Item=u8>>(bytes: T) -> Option<Self> { +impl Decoder<Instruction> for InstDecoder { +    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> {          let mut blank = Instruction::blank(); -        match blank.decode_into(bytes) { +        match self.decode_into(&mut blank, bytes) {              Some(_) => Some(blank),              None => None          }      } -    fn decode_into<T: IntoIterator<Item=u8>>(&mut self, bytes: T) -> Option<()> { +    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Option<()> {          fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Option<u32> {              let mut iter = bytes.into_iter();              let instr: u32 = @@ -704,38 +707,38 @@ impl Decodable for Instruction {          if cond == 0b1111 {              // do unconditional instruction stuff -            self.condition = ConditionCode::AL; +            inst.condition = ConditionCode::AL;              let op1 = (word >> 20) as u8;              if op1 > 0x80 {                  match (op1 >> 5) & 0b11 {                      0b00 => { -                        self.opcode = Opcode::Incomplete(word); +                        inst.opcode = Opcode::Incomplete(word);                      }                      0b01 => { -                        self.opcode = Opcode::BLX; +                        inst.opcode = Opcode::BLX;                          let operand = ((word & 0xffffff) as i32) << 8 >> 6; -                        self.operands = Operands::BranchOffset( +                        inst.operands = Operands::BranchOffset(                              operand | (                                  ((word >> 23) & 0b10) as i32                              )                          );                      }                      0b10 => { -                        self.opcode = Opcode::Incomplete(word); +                        inst.opcode = Opcode::Incomplete(word);                      }                      0b11 => { -                        self.opcode = Opcode::Incomplete(word); +                        inst.opcode = Opcode::Incomplete(word);                      }                      _ => {                          unreachable!();                      }                  }              } else { -                self.opcode = Opcode::Incomplete(word); +                inst.opcode = Opcode::Incomplete(word);              }              return Some(());          } else { -            self.condition = ConditionCode::build(cond); +            inst.condition = ConditionCode::build(cond);          }          // distinction at this point is on page A5-192 @@ -768,47 +771,47 @@ impl Decodable for Instruction {                              ((word >> 12) & 0x0f) as u8,                              ((word >> 16) & 0x0f) as u8                          ]; -                        self.set_S(s); +                        inst.set_S(s);                          match op {                              0b000 => { -                                self.opcode = Opcode::MUL; -                                self.operands = Operands::MulThreeRegs(R[3], R[0], R[1]); +                                inst.opcode = Opcode::MUL; +                                inst.operands = Operands::MulThreeRegs(R[3], R[0], R[1]);                              },                              0b001 => { -                                self.opcode = Opcode::MLA; -                                self.operands = Operands::MulFourRegs(R[3], R[0], R[1], R[2]); +                                inst.opcode = Opcode::MLA; +                                inst.operands = Operands::MulFourRegs(R[3], R[0], R[1], R[2]);                              },                              0b010 => {                                  if s { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                      return None;                                  } -                                self.opcode = Opcode::UMAAL; -                                self.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); +                                inst.opcode = Opcode::UMAAL; +                                inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]);                              },                              0b011 => {                                  if s { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                      return None;                                  } -                                self.opcode = Opcode::MLS; -                                self.operands = Operands::MulFourRegs(R[3], R[0], R[1], R[2]); +                                inst.opcode = Opcode::MLS; +                                inst.operands = Operands::MulFourRegs(R[3], R[0], R[1], R[2]);                              }                              0b100 => { -                                self.opcode = Opcode::UMULL; -                                self.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); +                                inst.opcode = Opcode::UMULL; +                                inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]);                              }                              0b101 => { -                                self.opcode = Opcode::UMLAL; -                                self.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); +                                inst.opcode = Opcode::UMLAL; +                                inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]);                              }                              0b110 => { -                                self.opcode = Opcode::SMULL; -                                self.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); +                                inst.opcode = Opcode::SMULL; +                                inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]);                              }                              0b111 => { -                                self.opcode = Opcode::SMLAL; -                                self.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]); +                                inst.opcode = Opcode::SMLAL; +                                inst.operands = Operands::MulFourRegs(R[2], R[3], R[0], R[1]);                              }                              _ => { unreachable!(format!("mul upcode: {:x}", op)) }                          } @@ -838,52 +841,52 @@ impl Decodable for Instruction {                                  // this is swp or {ld,st}ex, conditional on bit 23                                  match flags {                                      0b10000 => { -                                        self.opcode = Opcode::SWP; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::SWP; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      },                                      0b10001 | 0b10010 | 0b10011 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          return None;                                      }                                      0b10100 => { -                                        self.opcode = Opcode::SWPB; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::SWPB; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      },                                      0b10101 | 0b10110 | 0b10111 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          return None;                                      }                                      0b11000 => { -                                        self.opcode = Opcode::STREX; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::STREX; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11001 => { -                                        self.opcode = Opcode::LDREX; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::LDREX; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11010 => { -                                        self.opcode = Opcode::STREXD; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::STREXD; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11011 => { -                                        self.opcode = Opcode::LDREXD; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::LDREXD; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11100 => { -                                        self.opcode = Opcode::STREXB; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::STREXB; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11101 => { -                                        self.opcode = Opcode::LDREXB; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::LDREXB; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11110 => { -                                        self.opcode = Opcode::STREXH; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::STREXH; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b11111 => { -                                        self.opcode = Opcode::LDREXH; -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        inst.opcode = Opcode::LDREXH; +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      _ => {                                          /* @@ -900,30 +903,30 @@ impl Decodable for Instruction {                              0b01 => {                      // |c o n d|0 0 0 x|x x x x x x x x x x x x x x x x|1 0 1 1|x x x x|                      // page A5-201 -                                self.opcode = Opcode::Incomplete(word); +                                inst.opcode = Opcode::Incomplete(word);                                  // return Some(());                                  match flags {                                      0b00010 => { -                                        // self.opcode = Opcode::STRHT_sub; -                                        self.opcode = Opcode::Incomplete(word); -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        // inst.opcode = Opcode::STRHT_sub; +                                        inst.opcode = Opcode::Incomplete(word); +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b01010 => { -                                        // self.opcode = Opcode::STRHT_add; -                                        self.opcode = Opcode::Incomplete(word); -                                        self.operands = Operands::ThreeOperand(Rn, Rd, LoOffset); +                                        // inst.opcode = Opcode::STRHT_add; +                                        inst.opcode = Opcode::Incomplete(word); +                                        inst.operands = Operands::ThreeOperand(Rn, Rd, LoOffset);                                      }                                      0b00110 => { -                                        // self.opcode = Opcode::STRHT_sub; -                                        self.opcode = Opcode::Incomplete(word); +                                        // inst.opcode = Opcode::STRHT_sub; +                                        inst.opcode = Opcode::Incomplete(word);                                          let imm = (HiOffset << 4) as u16 | LoOffset as u16; -                                        self.operands = Operands::ThreeOperandImm(Rn, Rd, imm); +                                        inst.operands = Operands::ThreeOperandImm(Rn, Rd, imm);                                      }                                      0b01110 => { -                                        // self.opcode = Opcode::STRHT_add; -                                        self.opcode = Opcode::Incomplete(word); +                                        // inst.opcode = Opcode::STRHT_add; +                                        inst.opcode = Opcode::Incomplete(word);                                          let imm = (HiOffset << 4) as u16 | LoOffset as u16; -                                        self.operands = Operands::ThreeOperandImm(Rn, Rd, imm); +                                        inst.operands = Operands::ThreeOperandImm(Rn, Rd, imm);                                      }                                      _ => {                                          unreachable!(); @@ -934,13 +937,13 @@ impl Decodable for Instruction {                              0b10 => {                      // |c o n d|0 0 0 x|x x x x x x x x x x x x x x x x|1 1 0 1|x x x x|                      // page A5-201 -                                self.opcode = Opcode::Incomplete(word); +                                inst.opcode = Opcode::Incomplete(word);                                  return Some(());                              }                              0b11 => {                      // |c o n d|0 0 0 x|x x x x x x x x x x x x x x x x|1 1 1 1|x x x x|                      // page A5-201 -                                self.opcode = Opcode::Incomplete(word); +                                inst.opcode = Opcode::Incomplete(word);                                  return Some(());                              }                              _ => { unreachable!(); } @@ -970,15 +973,15 @@ impl Decodable for Instruction {                                  },                                  0b011 => {                                      if opcode & 0b11 == 0b01 { -                                        self.opcode = Opcode::BLX; -                                        self.operands = Operands::OneOperand((word & 0x0f) as u8); +                                        inst.opcode = Opcode::BLX; +                                        inst.operands = Operands::OneOperand((word & 0x0f) as u8);                                          return Some(());                                      } else {                                          return None;                                      }                                  },                                  0b100 => { -                                    self.opcode = Opcode::Incomplete(word); +                                    inst.opcode = Opcode::Incomplete(word);                                      return Some(());                                  },                                  0b101 => { @@ -996,15 +999,15 @@ impl Decodable for Instruction {                          } else {                              // |c o n d|0 0 0|1 0 x x|0|x x x x|x x x x|x x x x|1|x x|x|x x x x|                              // multiply and multiply-accumulate  -                            self.opcode = Opcode::Incomplete(word); +                            inst.opcode = Opcode::Incomplete(word);                              return Some(());                          }                      } else {                          if opcode >= 16 {                              unreachable!();                          } -                        self.opcode = DATA_PROCESSING_OPCODES[opcode as usize]; -                        self.set_S(s); +                        inst.opcode = DATA_PROCESSING_OPCODES[opcode as usize]; +                        inst.set_S(s);                          // at this point we know this is a data processing instruction                          // either immediate shift or register shift @@ -1025,15 +1028,15 @@ impl Decodable for Instruction {                              if shift_spec == 0 {                                  if (0b1101 & opcode) == 0b1101 {                                      // MOV or MVN -                                    self.operands = Operands::TwoOperand(Rd, Rm); +                                    inst.operands = Operands::TwoOperand(Rd, Rm);                                  } else { -                                    self.operands = Operands::ThreeOperand(Rd, Rn, Rm); +                                    inst.operands = Operands::ThreeOperand(Rd, Rn, Rm);                                  }                              } else {                                  /*                                   * TODO: look at how this interacts with mov and mvn                                   */ -                                self.operands = Operands::ThreeOperandWithShift(Rd, Rn, Rm, ShiftSpec::Immediate(shift_spec)); +                                inst.operands = Operands::ThreeOperandWithShift(Rd, Rn, Rm, ShiftSpec::Immediate(shift_spec));                              }                          } else {                      //    known 0 because it and bit 5 are not both 1 --v @@ -1053,10 +1056,10 @@ impl Decodable for Instruction {                              // here?                              if (0b1101 & opcode) == 0b1101 {                                  // these are all invalid -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return None;                              } else { -                                self.operands = Operands::ThreeOperandWithShift(Rd, Rn, Rm, ShiftSpec::Register(shift_spec)); +                                inst.operands = Operands::ThreeOperandWithShift(Rd, Rn, Rm, ShiftSpec::Register(shift_spec));                              }                          }                      } @@ -1077,14 +1080,14 @@ impl Decodable for Instruction {                  // the instruction looks like                  // |c o n d|0 0 0|1 0 x x|0|x x x x|x x x x|x x x x x|x x|x|x x x x|                  // misc instructions (page A5-194) -                    self.opcode = Opcode::Incomplete(word); +                    inst.opcode = Opcode::Incomplete(word);                      return Some(());                  } else {                      if opcode >= 16 {                          unreachable!();                      } -                    self.opcode = DATA_PROCESSING_OPCODES[opcode as usize]; -                    self.set_S(s); +                    inst.opcode = DATA_PROCESSING_OPCODES[opcode as usize]; +                    inst.set_S(s);                      let (Rn, imm) = {                          let imm = word & 0x0000ffff; @@ -1092,17 +1095,17 @@ impl Decodable for Instruction {                          ((word & 0x0f) as u8, imm)                      };                      if (opcode == 0b0010 || opcode == 0b0100) && Rn == 0b1111 { -                        self.opcode = Opcode::ADR; +                        inst.opcode = Opcode::ADR;                      }                      match opcode {                          0b1101 => { -                            self.operands = Operands::RegImm( +                            inst.operands = Operands::RegImm(                                  ((word >> 12) & 0xf) as u8,                                  (word & 0x0fff) as u32                              );                          }                          _ => { -                            self.operands = Operands::RegImm(Rn, imm); +                            inst.operands = Operands::RegImm(Rn, imm);                          }                      } @@ -1125,7 +1128,7 @@ impl Decodable for Instruction {                      0x110 -> STRBT                      0x111 -> LDRBT                      */ -                    self.opcode = match op { +                    inst.opcode = match op {                          0b010 => Opcode::STRT(add),                          0b011 => Opcode::LDRT(add),                          0b110 => Opcode::STRBT(add), @@ -1142,12 +1145,12 @@ impl Decodable for Instruction {                      let pre = (op & 0b10000) != 0;                      let wback = (op & 0b00010) != 0;                      let op = op & 0b00101; -                    self.opcode = match op { +                    inst.opcode = match op {                          0b000 => Opcode::STR(add, pre, wback),                          0b001 => {                              if Rn == 0b1111 { -                                self.operands = Operands::RegImm(Rt, imm.into()); -                                self.opcode = Opcode::LDR(add, pre, wback); +                                inst.operands = Operands::RegImm(Rt, imm.into()); +                                inst.opcode = Opcode::LDR(add, pre, wback);                                  return Some(());                              }                              Opcode::LDR(add, pre, wback) @@ -1155,8 +1158,8 @@ impl Decodable for Instruction {                          0b100 => Opcode::STRB(add, pre, wback),                          0b101 => {                              if Rn == 0b1111 { -                                self.operands = Operands::RegImm(Rt, imm.into()); -                                self.opcode = Opcode::LDRB(add, pre, wback); +                                inst.operands = Operands::RegImm(Rt, imm.into()); +                                inst.opcode = Opcode::LDRB(add, pre, wback);                                  return Some(());                              }                              Opcode::LDRB(add, pre, wback) @@ -1164,7 +1167,7 @@ impl Decodable for Instruction {                          _ => { unreachable!(); }                      };                  } -                self.operands = Operands::TwoRegImm(Rn, Rt, imm.into()); +                inst.operands = Operands::TwoRegImm(Rn, Rt, imm.into());              },              0b011 => {                  // page A5-192 to distinguish the following: @@ -1199,7 +1202,7 @@ impl Decodable for Instruction {                          0x110 -> STRBT                          0x111 -> LDRBT                          */ -                        self.opcode = match op { +                        inst.opcode = match op {                              0b010 => Opcode::STRT(add),                              0b011 => Opcode::LDRT(add),                              0b110 => Opcode::STRBT(add), @@ -1216,7 +1219,7 @@ impl Decodable for Instruction {                          let pre = (op & 0b10000) != 0;                          let wback = (op & 0b00010) != 0;                          let op = op & 0b00101; -                        self.opcode = match op { +                        inst.opcode = match op {                              0b000 => Opcode::STR(add, pre, wback),                              0b001 => Opcode::LDR(add, pre, wback),                              0b100 => Opcode::STRB(add, pre, wback), @@ -1232,7 +1235,7 @@ impl Decodable for Instruction {                          let Rt = (word & 0xf) as u8;                          (Rt, Rm, shift)                      }; -                    self.operands = Operands::ThreeOperandWithShift(Rn, Rt, Rm, ShiftSpec::Immediate(shift)); +                    inst.operands = Operands::ThreeOperandWithShift(Rn, Rt, Rm, ShiftSpec::Immediate(shift));                  }                  return Some(());              }, @@ -1245,31 +1248,31 @@ impl Decodable for Instruction {                      let add = (op & 0b001000) != 0;                      let pre = (op & 0b010000) != 0;                      let usermode = (op & 0b000100) != 0; -                    self.opcode = if (op & 1) == 0 { +                    inst.opcode = if (op & 1) == 0 {                              Opcode::STM(add, pre, wback, usermode)                          } else {                              Opcode::LDM(add, pre, wback, usermode)                          }; -                    self.operands = Operands::RegRegList( +                    inst.operands = Operands::RegRegList(                          ((word >> 16) & 0xf) as u8,                          (word & 0xffff) as u16                      );                  } else if op < 0b110000 {                      // 10xxxx                      // the + 1 is to compensate for an architecturally-defined initial offset -                    self.opcode = Opcode::B; -                    self.operands = Operands::BranchOffset(((word & 0x00ffff) + 1) as i16 as i32); +                    inst.opcode = Opcode::B; +                    inst.operands = Operands::BranchOffset(((word & 0x00ffff) + 1) as i16 as i32);                  } else {                      // 11xxxx                      // the + 1 is to compensate for an architecturally-defined initial offset -                    self.opcode = Opcode::BL; -                    self.operands = Operands::BranchOffset(((word & 0x00ffff) + 1) as i16 as i32); +                    inst.opcode = Opcode::BL; +                    inst.operands = Operands::BranchOffset(((word & 0x00ffff) + 1) as i16 as i32);                  }              },              0b110 | 0b111 => {                  // coprocessor instructions and supervisor call                  // page A5-213 -                self.opcode = Opcode::Incomplete(word); +                inst.opcode = Opcode::Incomplete(word);                  return Some(());              },              _ => { unreachable!(); } @@ -1289,6 +1292,7 @@ pub struct ARMv7;  impl Arch for ARMv7 {      type Address = u32;      type Instruction = Instruction; +    type Decoder = InstDecoder;      type Operand = Operands;  } diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 3e0403a..6dd9d68 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -3,7 +3,7 @@  use std::fmt::{Display, Formatter}; -use yaxpeax_arch::{Arch, ColorSettings, Decodable, LengthedInstruction, ShowContextual}; +use yaxpeax_arch::{Arch, ColorSettings, Decoder, LengthedInstruction, ShowContextual};  #[allow(non_snake_case)]  mod docs { @@ -114,6 +114,16 @@ mod docs {          let tmask = Replicate(telem, esize, 64);          (wmask, tmask)      } + +    pub fn DecodeShift(op: u8) -> super::ShiftStyle { +        assert!(op <= 0b11); +        [ +            super::ShiftStyle::LSL, +            super::ShiftStyle::LSR, +            super::ShiftStyle::ASR, +            super::ShiftStyle::ROR, +        ][op as usize] +    }  }  #[allow(non_snake_case)] @@ -134,13 +144,20 @@ pub struct ARMv8 { }  impl Arch for ARMv8 {      type Address = u64;      type Instruction = Instruction; +    type Decoder = InstDecoder;      type Operand = Operand;  }  #[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)]  pub enum SizeCode { X, W }  #[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)] +pub enum SIMDSizeCode { S, D, Q } + +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(C)]  pub struct Instruction {      pub opcode: Opcode,      pub operands: [Operand; 4], @@ -176,16 +193,38 @@ impl Display for Instruction {              Opcode::AND => {                  write!(fmt, "and")?;              }, +            Opcode::BIC => { +                write!(fmt, "bic")?; +            }, +            Opcode::BICS => { +                write!(fmt, "bics")?; +            },              Opcode::ORR => { +                if let Operand::Register(_, 31) = self.operands[1] { +                    if let Operand::Immediate(0) = self.operands[2] { +                        return write!(fmt, "mov {}, {}", self.operands[0], self.operands[1]); +                    } else if let Operand::RegShift(ShiftStyle::LSL, 0, size, r) = self.operands[2] { +                        return write!(fmt, "mov {}, {}", self.operands[0], Operand::Register(size, r)); +                    } +                }                  write!(fmt, "orr")?;              }, +            Opcode::ORN => { +                write!(fmt, "orn")?; +            },              Opcode::EOR => {                  write!(fmt, "eor")?;              }, +            Opcode::EON => { +                write!(fmt, "eon")?; +            },              Opcode::ANDS => {                  write!(fmt, "ands")?;              },              Opcode::ADDS => { +                if let Operand::Register(SizeCode::X, 31) = self.operands[0] { +                    return write!(fmt, "cmn {}, {}", self.operands[1], self.operands[2]); +                }                  write!(fmt, "adds")?;              },              Opcode::ADD => { @@ -536,6 +575,12 @@ impl Display for Instruction {                  }                  write!(fmt, "csinv")?;              } +            Opcode::PACIA => { +                write!(fmt, "pacia")?; +            } +            Opcode::PACIZA => { +                write!(fmt, "paciza")?; +            }          };          if self.operands[0] != Operand::Nothing { @@ -582,6 +627,7 @@ impl Instruction {  }  #[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)]  pub enum Opcode {      Invalid,      MOVN, @@ -593,7 +639,11 @@ pub enum Opcode {      SBCS,      AND,      ORR, +    ORN,      EOR, +    EON, +    BIC, +    BICS,      ANDS,      ADDS,      ADD, @@ -692,6 +742,8 @@ pub enum Opcode {      CSNEG,      CSINC,      CSINV, +    PACIA, +    PACIZA,  }  #[derive(Copy, Clone, Debug, PartialEq)] @@ -699,6 +751,7 @@ pub enum ShiftStyle {      LSL,      LSR,      ASR, +    ROR,      UXTB,      UXTH,      UXTW, @@ -715,6 +768,7 @@ impl Display for ShiftStyle {              ShiftStyle::LSL => { write!(fmt, "lsl") },              ShiftStyle::LSR => { write!(fmt, "lsr") },              ShiftStyle::ASR => { write!(fmt, "asr") }, +            ShiftStyle::ROR => { write!(fmt, "ror") },              ShiftStyle::UXTB => { write!(fmt, "uxtb") },              ShiftStyle::UXTH => { write!(fmt, "uxth") },              ShiftStyle::UXTW => { write!(fmt, "uxtw") }, @@ -728,9 +782,11 @@ impl Display for ShiftStyle {  }  #[derive(Copy, Clone, Debug, PartialEq)] +#[repr(C)]  pub enum Operand {      Nothing,      Register(SizeCode, u16), +    SIMDRegister(SIMDSizeCode, u16),      RegisterOrSP(SizeCode, u16),      ConditionCode(u8),      Offset(u32), @@ -773,6 +829,13 @@ impl Display for Operand {                      }                  }              }, +            Operand::SIMDRegister(size, reg) => { +                match size { +                    SIMDSizeCode::S => { write!(fmt, "s{}", reg) } +                    SIMDSizeCode::D => { write!(fmt, "d{}", reg) } +                    SIMDSizeCode::Q => { write!(fmt, "q{}", reg) } +                } +            }              Operand::RegisterOrSP(size, reg) => {                  if *reg == 31 {                      match size { @@ -913,16 +976,19 @@ impl Display for Operand {      }  } +#[derive(Default, Debug)] +pub struct InstDecoder {} +  #[allow(non_snake_case)] -impl Decodable for Instruction { -    fn decode<T: IntoIterator<Item=u8>>(bytes: T) -> Option<Self> { +impl Decoder<Instruction> for InstDecoder { +    fn decode<T: IntoIterator<Item=u8>>(&self, bytes: T) -> Option<Instruction> {          let mut blank = Instruction::blank(); -        match blank.decode_into(bytes) { +        match self.decode_into(&mut blank, bytes) {              Some(_) => Some(blank),              None => None          }      } -    fn decode_into<T: IntoIterator<Item=u8>>(&mut self, bytes: T) -> Option<()> { +    fn decode_into<T: IntoIterator<Item=u8>>(&self, inst: &mut Instruction, bytes: T) -> Option<()> {          fn read_word<T: IntoIterator<Item=u8>>(bytes: T) -> Option<u32> {              let mut iter = bytes.into_iter();              let instr: u32 = @@ -990,7 +1056,7 @@ impl Decodable for Instruction {                  unreachable!();              }              Section::Unallocated => { -                self.opcode = Opcode::Invalid; +                inst.opcode = Opcode::Invalid;              }              Section::DataProcessingReg => {                  /* @@ -1003,7 +1069,6 @@ impl Decodable for Instruction {                      // These are of the form                      // XXX1101X_...                      let group_bits = (word >> 22) & 0x7; -                    println!("Group bits: {:#b}", group_bits);                      match group_bits {                          0b000 => {                              // Add/subtract (with carry) @@ -1013,49 +1078,49 @@ impl Decodable for Instruction {                              let Rm = ((word >> 16) & 0x1f) as u16;                              if opc2 == 0b000000 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return Some(());                              }                              let size_code = match word >> 29 {                                  0b000 => { -                                    self.opcode = Opcode::ADC; +                                    inst.opcode = Opcode::ADC;                                      SizeCode::W                                  }                                  0b001 => { -                                    self.opcode = Opcode::ADCS; +                                    inst.opcode = Opcode::ADCS;                                      SizeCode::W                                  }                                  0b010 => { -                                    self.opcode = Opcode::SBC; +                                    inst.opcode = Opcode::SBC;                                      SizeCode::W                                  }                                  0b011 => { -                                    self.opcode = Opcode::SBCS; +                                    inst.opcode = Opcode::SBCS;                                      SizeCode::W                                  }                                  0b100 => { -                                    self.opcode = Opcode::ADC; +                                    inst.opcode = Opcode::ADC;                                      SizeCode::X                                  }                                  0b101 => { -                                    self.opcode = Opcode::ADCS; +                                    inst.opcode = Opcode::ADCS;                                      SizeCode::X                                  }                                  0b110 => { -                                    self.opcode = Opcode::SBC; +                                    inst.opcode = Opcode::SBC;                                      SizeCode::X                                  }                                  0b111 => { -                                    self.opcode = Opcode::SBCS; +                                    inst.opcode = Opcode::SBCS;                                      SizeCode::X                                  }                                  _ => { -                                    unreachable!(); +                                    unreachable!("opc and size flag are three bits");                                  }                              }; -                            self.operands = [ +                            inst.operands = [                                  Operand::Register(size_code, Rd),                                  Operand::Register(size_code, Rn),                                  Operand::Register(size_code, Rm), @@ -1064,6 +1129,7 @@ impl Decodable for Instruction {                          },                          0b001 => {                              // Conditional compare (register/immediate) +                            unimplemented!();                          },                          0b010 => {                              // Conditional select @@ -1071,41 +1137,41 @@ impl Decodable for Instruction {                              let sf_op = (word >> 28) & 0x0c;                              if word & 0x20000000 != 0 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return Some(());                              }                              let size = match sf_op | op2 {                                  0b0000 => { -                                    self.opcode = Opcode::CSEL; +                                    inst.opcode = Opcode::CSEL;                                      SizeCode::W                                  },                                  0b0001 => { -                                    self.opcode = Opcode::CSINC; +                                    inst.opcode = Opcode::CSINC;                                      SizeCode::W                                  },                                  0b0100 => { -                                    self.opcode = Opcode::CSINV; +                                    inst.opcode = Opcode::CSINV;                                      SizeCode::W                                  },                                  0b0101 => { -                                    self.opcode = Opcode::CSNEG; +                                    inst.opcode = Opcode::CSNEG;                                      SizeCode::W                                  },                                  0b1000 => { -                                    self.opcode = Opcode::CSEL; +                                    inst.opcode = Opcode::CSEL;                                      SizeCode::X                                  },                                  0b1001 => { -                                    self.opcode = Opcode::CSINC; +                                    inst.opcode = Opcode::CSINC;                                      SizeCode::X                                  },                                  0b1100 => { -                                    self.opcode = Opcode::CSINV; +                                    inst.opcode = Opcode::CSINV;                                      SizeCode::X                                  },                                  0b1101 => { -                                    self.opcode = Opcode::CSNEG; +                                    inst.opcode = Opcode::CSNEG;                                      SizeCode::X                                  },                                  0b0010 | @@ -1116,11 +1182,11 @@ impl Decodable for Instruction {                                  0b1011 |                                  0b1110 |                                  0b1111 => { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                      return Some(());                                  },                                  _ => { -                                    unreachable!(); +                                    unreachable!("sf, op, op2 are four bits total");                                  }                              }; @@ -1129,7 +1195,7 @@ impl Decodable for Instruction {                              let Rm = ((word >> 16) & 0x1f) as u16;                              let cond = ((word >> 12) & 0x0f) as u8; -                            self.operands = [ +                            inst.operands = [                                  Operand::Register(size, Rd),                                  Operand::Register(size, Rn),                                  Operand::Register(size, Rm), @@ -1138,9 +1204,64 @@ impl Decodable for Instruction {                          },                          0b011 => {                              // Data processing (1 source, 2 source) +                            if ((word >> 30) & 1) == 0 { +                                // X0X11010_110XXXXX_XXXXXXXX_XXXXXXXX +                                // Data-processing (2 source) +                                unimplemented!(); +                            } else { +                                // X1X11010_110XXXXX_XXXXXXXX_XXXXXXXX +                                // Data-processing (1 source) +                                let Rd = (word & 0x1f) as u16; +                                let Rn = ((word >> 5) & 0x1f) as u16; +                                let opcode = ((word >> 10) & 0x3f) as u8; +                                let opcode2 = ((word >> 16) & 0x1f) as u8; +                                // So ARMv8 ARM only says that 0b00000 has well-defined +                                // instructions +                                // however, PAC (added in v8.3) says otherwise. +                                match opcode2 { +                                    0b00000 => { +                                        unimplemented!(); +                                    } +                                    0b00001 => { +                                        match opcode { +                                            0b000000 => { +                                                inst.opcode = Opcode::PACIA; +                                                inst.operands = [ +                                                    Operand::Register(SizeCode::X, Rd), +                                                    Operand::RegisterOrSP(SizeCode::X, Rn), +                                                    Operand::Nothing, +                                                    Operand::Nothing, +                                                ]; +                                            } +                                            0b001000 => { +                                                if Rn != 31 { +                                                    // technically this is undefined - do some +                                                    // cores do something with this? +                                                    inst.opcode = Opcode::Invalid; +                                                    return None; +                                                } +                                                inst.opcode = Opcode::PACIZA; +                                                inst.operands = [ +                                                    Operand::Register(SizeCode::X, Rd), +                                                    Operand::Nothing, +                                                    Operand::Nothing, +                                                    Operand::Nothing, +                                                ]; +                                            } +                                            _ => { +                                                inst.opcode = Opcode::Invalid; +                                            } +                                        } +                                    } +                                    _ => { +                                        unimplemented!(); +                                    } +                                } +                            }                          },                          _ => {                              // Data processing (3 source) +                            unimplemented!();                          }                      }                  } else { @@ -1153,12 +1274,37 @@ impl Decodable for Instruction {                      if (word & 0x01000000) == 0 {                          // Logical (shifted register)                          // XXX01010X_... -                        unreachable!(); +                        let sf = (word >> 31) == 1; +                        let size = if sf { SizeCode::X } else { SizeCode::W }; + +                        let opc = (word >> 28) & 6; +                        let n = (word >> 21) & 1; +                        inst.opcode = [ +                            Opcode::AND, +                            Opcode::BIC, +                            Opcode::ORR, +                            Opcode::ORN, +                            Opcode::EOR, +                            Opcode::EON, +                            Opcode::ANDS, +                            Opcode::BICS, +                        ][(opc | n) as usize]; + +                        let shift = ((word >> 22) & 3) as u8; + +                        let Rd = (word & 0x1f) as u16; +                        let Rn = ((word >> 5) & 0x1f) as u16; +                        let imm6 = ((word >> 10) & 0x13) as u8; +                        let Rm = ((word >> 16) & 0x1f) as u16; + +                        inst.operands[0] = Operand::Register(size, Rd); +                        inst.operands[1] = Operand::Register(size, Rn); +                        inst.operands[2] = Operand::RegShift(docs::DecodeShift(shift), imm6, size, Rm);                      } else {                          // Add/subtract ({shifted,extended} register)                          // XXX11011X_...                          // specific instruction is picked by the first two bits.. -                        self.opcode = [ +                        inst.opcode = [                              Opcode::ADD,                              Opcode::ADDS,                              Opcode::SUB, @@ -1174,7 +1320,7 @@ impl Decodable for Instruction {                              // opt (bits 22, 23) must be 0                              if (word >> 22) & 0x03 != 0 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return None;                              } @@ -1184,11 +1330,11 @@ impl Decodable for Instruction {                              let option = (word >> 13) & 0x07;                              let Rm = ((word >> 16) & 0x1f) as u16; -                            self.operands[0] = Operand::Register(size, Rd); -                            self.operands[1] = Operand::Register(size, Rn); +                            inst.operands[0] = Operand::Register(size, Rd); +                            inst.operands[1] = Operand::Register(size, Rn);                              let shift = (imm3 * 16) as u8; -                            self.operands[2] = match option { +                            inst.operands[2] = match option {                                  0b000 => Operand::RegShift(ShiftStyle::UXTB, shift, SizeCode::W, Rm),                                  0b001 => Operand::RegShift(ShiftStyle::UXTH, shift, SizeCode::W, Rm),                                  0b010 => Operand::RegShift(ShiftStyle::UXTW, shift, SizeCode::W, Rm), @@ -1197,14 +1343,14 @@ impl Decodable for Instruction {                                  0b101 => Operand::RegShift(ShiftStyle::SXTH, shift, SizeCode::W, Rm),                                  0b110 => Operand::RegShift(ShiftStyle::SXTW, shift, SizeCode::W, Rm),                                  0b111 => Operand::RegShift(ShiftStyle::SXTX, shift, SizeCode::X, Rm), -                                _ => { unreachable!(); }, +                                _ => { unreachable!("option is three bits"); },                              };                         } else {                              // shifted form                              let shift = (word >> 22) & 0x03;                              if shift == 0b11 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return None;                              } @@ -1214,18 +1360,18 @@ impl Decodable for Instruction {                              let Rm = ((word >> 16) & 0x1f) as u16;                              if size == SizeCode::W && imm6 >= 32 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return None;                              } -                            self.operands[0] = Operand::Register(size, Rd); -                            self.operands[1] = Operand::Register(size, Rn); +                            inst.operands[0] = Operand::Register(size, Rd); +                            inst.operands[1] = Operand::Register(size, Rn); -                            self.operands[2] = match shift { +                            inst.operands[2] = match shift {                                  0b00 => Operand::RegShift(ShiftStyle::LSL, imm6, size, Rm),                                  0b01 => Operand::RegShift(ShiftStyle::LSR, imm6, size, Rm),                                  0b10 => Operand::RegShift(ShiftStyle::ASR, imm6, size, Rm), -                                _ => { unreachable!(); }, +                                _ => { unreachable!("shift is two bits and 0b11 has early test"); },                              };                          }                      } @@ -1242,25 +1388,24 @@ impl Decodable for Instruction {                      0b001 => {                          // PC-rel addressing                          if word >= 0x80000000 { -                            self.opcode = Opcode::ADRP; +                            inst.opcode = Opcode::ADRP;                              let imm = ((word >> 3) & 0x1ffffc) | ((word >> 29) & 0x3); -                            self.operands = [ +                            inst.operands = [                                  Operand::Register(SizeCode::X, (word & 0x1f) as u16),                                  Operand::Immediate(imm * 0x1000),                                  Operand::Nothing,                                  Operand::Nothing                              ];                          } else { -                            self.opcode = Opcode::ADR; +                            inst.opcode = Opcode::ADR;                              let imm = ((word >> 3) & 0x1ffffc) | ((word >> 29) & 0x3); -                            self.operands = [ +                            inst.operands = [                                  Operand::Register(SizeCode::X, (word & 0x1f) as u16),                                  Operand::Immediate(imm),                                  Operand::Nothing,                                  Operand::Nothing                              ];                          }; -                      }                      0b010 |                      0b011 => { @@ -1271,44 +1416,48 @@ impl Decodable for Instruction {                          let shift = (word >> 22) & 0x3;                          let size = match word >> 29 {                              0b000 => { -                                self.opcode = Opcode::ADD; +                                inst.opcode = Opcode::ADD;                                  SizeCode::W                              },                              0b001 => { -                                self.opcode = Opcode::ADDS; +                                inst.opcode = Opcode::ADDS;                                  SizeCode::W                              },                              0b010 => { -                                self.opcode = Opcode::SUB; +                                inst.opcode = Opcode::SUB;                                  SizeCode::W                              },                              0b011 => { -                                self.opcode = Opcode::SUBS; +                                inst.opcode = Opcode::SUBS;                                  SizeCode::W                              },                              0b100 => { -                                self.opcode = Opcode::ADD; +                                inst.opcode = Opcode::ADD;                                  SizeCode::X                              },                              0b101 => { -                                self.opcode = Opcode::ADDS; +                                inst.opcode = Opcode::ADDS;                                  SizeCode::X                              },                              0b110 => { -                                self.opcode = Opcode::SUB; +                                inst.opcode = Opcode::SUB;                                  SizeCode::X                              },                              0b111 => { -                                self.opcode = Opcode::SUBS; +                                inst.opcode = Opcode::SUBS;                                  SizeCode::X                              },                              _ => { -                                unreachable!(); +                                unreachable!("size and opc are three bits");                              }                          }; -                        self.operands[0] = Operand::Register(size, Rd as u16); -                        self.operands[1] = Operand::RegisterOrSP(size, Rn as u16); -                        self.operands[2] = match shift { +                        if inst.opcode == Opcode::ADD || inst.opcode == Opcode::SUB { +                            inst.operands[0] = Operand::RegisterOrSP(size, Rd as u16); +                        } else { +                            inst.operands[0] = Operand::Register(size, Rd as u16); +                        } +                        inst.operands[1] = Operand::RegisterOrSP(size, Rn as u16); +                        inst.operands[2] = match shift {                              0b00 => {                                  Operand::Immediate(imm12 as u32)                              }, @@ -1317,12 +1466,12 @@ impl Decodable for Instruction {                              },                              0b10 |                              0b11 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return None;                              } -                            _ => { unreachable!(); } +                            _ => { unreachable!("shift is two bits"); }                          }; -                        self.operands[3] = Operand::Nothing; +                        inst.operands[3] = Operand::Nothing;                      }                      0b100 => {                          // logical (imm) @@ -1333,43 +1482,43 @@ impl Decodable for Instruction {                          let N = (word >> 22) & 1;                          let size = match word >> 29 {                              0b000 => { -                                self.opcode = Opcode::AND; +                                inst.opcode = Opcode::AND;                                  SizeCode::W                              }                              0b001 => { -                                self.opcode = Opcode::ORR; +                                inst.opcode = Opcode::ORR;                                  SizeCode::W                              }                              0b010 => { -                                self.opcode = Opcode::EOR; +                                inst.opcode = Opcode::EOR;                                  SizeCode::W                              }                              0b011 => { -                                self.opcode = Opcode::ANDS; +                                inst.opcode = Opcode::ANDS;                                  SizeCode::W                              }                              0b100 => { -                                self.opcode = Opcode::AND; +                                inst.opcode = Opcode::AND;                                  SizeCode::X                              }                              0b101 => { -                                self.opcode = Opcode::ORR; +                                inst.opcode = Opcode::ORR;                                  SizeCode::X                              }                              0b110 => { -                                self.opcode = Opcode::EOR; +                                inst.opcode = Opcode::EOR;                                  SizeCode::X                              }                              0b111 => { -                                self.opcode = Opcode::ANDS; +                                inst.opcode = Opcode::ANDS;                                  SizeCode::X                              }                              _ => { -                                unreachable!(); +                                unreachable!("size and opc are three bits");                              }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rd),                              Operand::Register(size, Rn),                              match size { @@ -1387,54 +1536,54 @@ impl Decodable for Instruction {                          let size = match word >> 29 {                              0b000 => {                                  if hw >= 0x10 { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  } else { -                                    self.opcode = Opcode::MOVN; +                                    inst.opcode = Opcode::MOVN;                                  }                                  SizeCode::W                              },                              0b001 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::W                              }                              0b010 => {                                  if hw >= 0x10 { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  } else { -                                    self.opcode = Opcode::MOVZ; +                                    inst.opcode = Opcode::MOVZ;                                  }                                  SizeCode::W                              },                              0b011 => {                                  if hw >= 0x10 { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  } else { -                                    self.opcode = Opcode::MOVK; +                                    inst.opcode = Opcode::MOVK;                                  }                                  SizeCode::W                              },                              0b100 => { -                                self.opcode = Opcode::MOVN; +                                inst.opcode = Opcode::MOVN;                                  SizeCode::X                              },                              0b101 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::X                              }                              0b110 => { -                                self.opcode = Opcode::MOVZ; +                                inst.opcode = Opcode::MOVZ;                                  SizeCode::X                              },                              0b111 => { -                                self.opcode = Opcode::MOVK; +                                inst.opcode = Opcode::MOVK;                                  SizeCode::X                              },                              _ => { -                                unreachable!(); +                                unreachable!("size and opc are three bits");                              }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rd as u16),                              Operand::ImmShift(imm16 as u16, hw as u8),                              Operand::Nothing, @@ -1454,66 +1603,66 @@ impl Decodable for Instruction {                          let size = match sf_opc {                              0b000 => {                                  if N == 0 { -                                    self.opcode = Opcode::SBFM; +                                    inst.opcode = Opcode::SBFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::W                              }                              0b001 => {                                  if N == 0 { -                                    self.opcode = Opcode::BFM; +                                    inst.opcode = Opcode::BFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::W                              }                              0b010 => {                                  if N == 0 { -                                    self.opcode = Opcode::UBFM; +                                    inst.opcode = Opcode::UBFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::W                              }                              0b011 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::W                              }                              0b100 => {                                  if N == 1 { -                                    self.opcode = Opcode::SBFM; +                                    inst.opcode = Opcode::SBFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::X                              }                              0b101 => {                                  if N == 1 { -                                    self.opcode = Opcode::SBFM; +                                    inst.opcode = Opcode::SBFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::X                              }                              0b110 => {                                  if N == 1 { -                                    self.opcode = Opcode::SBFM; +                                    inst.opcode = Opcode::SBFM;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  SizeCode::X                              }                              0b111 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::X                              }                              _ => { -                                unreachable!(); +                                unreachable!("size and opc are three bits");                              }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rd as u16),                              Operand::Register(size, Rn as u16),                              Operand::Immediate(immr as u32), @@ -1532,20 +1681,20 @@ impl Decodable for Instruction {                          if sf_op21 == 0b000 {                              if No0 != 0b00 || imms >= 0x10 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                              } else { -                                self.opcode = Opcode::EXTR; +                                inst.opcode = Opcode::EXTR;                              }                          } else if sf_op21 == 0b100 {                              if No0 != 0b10 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                              } else { -                                self.opcode = Opcode::EXTR; +                                inst.opcode = Opcode::EXTR;                              }                          } else { -                            self.opcode = Opcode::Invalid; +                            inst.opcode = Opcode::Invalid;                          } -                        unreachable!("decode Rd: {}, Rn: {}, imms: {}, Rm: {}, No0: {}", Rd, Rn, imms, Rm, No0); +                        unimplemented!("decode Rd: {}, Rn: {}, imms: {}, Rm: {}, No0: {}", Rd, Rn, imms, Rm, No0);                      }                      _ => { unreachable!() }                  } @@ -1568,45 +1717,131 @@ impl Decodable for Instruction {                  println!("Group byte: {:#b}, bits: {:#b}", group_byte, group_bits);                  match group_bits {                      0b00000 => { -                        let Rt = word & 0x1f; -                        let Rn = (word >> 5) & 0x1f; -                        let Rt2 = (word >> 10) & 0x1f; -                        let o0 = word & 0x0080; -                        let Rs = (word >> 16) & 0x1f; -                        let Lo1 = word & 0x600000; +                        let Rt = (word & 0x1f) as u16; +                        let Rn = ((word >> 5) & 0x1f) as u16; +                        let Rt2 = ((word >> 10) & 0x1f) as u16; +                        let o0 = (word & 0x0080) >> 7; +                        let Rs = ((word >> 16) & 0x1f) as u16; +                        let Lo1 = (word & 0x600000) >> 21;                          let size = (word >> 29) & 0x3;                          // load/store exclusive                          // o2 == 0 -                        self.opcode = match (size, Lo1, o0) { -                            (0b00, 0b00, 0b0) => Opcode::STXRB, -                            (0b00, 0b00, 0b1) => Opcode::STLXRB, -                            (0b00, 0b10, 0b0) => Opcode::LDXRB, -                            (0b00, 0b10, 0b1) => Opcode::LDAXRB, -                            (0b01, 0b00, 0b0) => Opcode::STXRH, -                            (0b01, 0b00, 0b1) => Opcode::STLXRH, -                            (0b01, 0b10, 0b0) => Opcode::LDXRH, -                            (0b01, 0b10, 0b1) => Opcode::LDAXRH, -                            (0b10, 0b00, 0b0) => Opcode::STXR, // 32-bit -                            (0b10, 0b00, 0b1) => Opcode::STLXR, // 32-bit -                            (0b10, 0b01, 0b0) => Opcode::STXP, // 32-bit -                            (0b10, 0b01, 0b1) => Opcode::STLXP, // 32-bit -                            (0b10, 0b10, 0b0) => Opcode::LDXR, // 32-bit -                            (0b10, 0b10, 0b1) => Opcode::LDAXR, // 32-bit -                            (0b10, 0b11, 0b0) => Opcode::LDXP, // 32-bit -                            (0b10, 0b11, 0b1) => Opcode::LDAXP, // 32-bit -                            (0b11, 0b00, 0b0) => Opcode::STXR, // 64-bit -                            (0b11, 0b00, 0b1) => Opcode::STLXR, // 64-bit -                            (0b11, 0b01, 0b0) => Opcode::STXP, // 64-bit -                            (0b11, 0b01, 0b1) => Opcode::STLXP, // 64-bit -                            (0b11, 0b10, 0b0) => Opcode::LDXR, // 64-bit -                            (0b11, 0b10, 0b1) => Opcode::LDAXR, // 64-bit -                            (0b11, 0b11, 0b0) => Opcode::LDXP, // 64-bit -                            (0b11, 0b11, 0b1) => Opcode::LDAXP, // 64-bit +                        inst.opcode = match size { +                            size @ 0b00 | +                            size @ 0b01 => { +                                if Lo1 == 0b00 { +                                    // store ops +                                    inst.operands = [ +                                        Operand::Register(SizeCode::W, Rs), +                                        Operand::Register(SizeCode::W, Rt), +                                        Operand::RegisterOrSP(SizeCode::X, Rn), +                                        Operand::Nothing, +                                    ]; +                                } else if Lo1 == 0b10 { +                                    // load ops +                                    inst.operands = [ +                                        Operand::Register(SizeCode::W, Rt), +                                        Operand::RegisterOrSP(SizeCode::X, Rn), +                                        Operand::Nothing, +                                        Operand::Nothing, +                                    ]; +                                } else { +                                    unreachable!("Lo checked for validity already"); +                                }; +                                if size == 0b00 { +                                    match (Lo1, o0) { +                                        (0b00, 0b0) => Opcode::STXRB, +                                        (0b00, 0b1) => Opcode::STLXRB, +                                        (0b10, 0b0) => Opcode::LDXRB, +                                        (0b10, 0b1) => Opcode::LDAXRB, +                                        _ => { +                                            inst.opcode = Opcode::Invalid; +                                            return None; +                                        } +                                    } +                                } else if size == 0b01 { +                                    match (Lo1, o0) { +                                        (0b00, 0b0) => Opcode::STXRH, +                                        (0b00, 0b1) => Opcode::STLXRH, +                                        (0b10, 0b0) => Opcode::LDXRH, +                                        (0b10, 0b1) => Opcode::LDAXRH, +                                        _ => { +                                            inst.opcode = Opcode::Invalid; +                                            return None; +                                        } +                                    } +                                } else { +                                    unreachable!("size was checked to be 0 or 1"); +                                } +                            } +                            size @ 0b10 | +                            size @ 0b11 => { +                                let size_code = match size { +                                    0b10 => SizeCode::W, +                                    0b11 => SizeCode::X, +                                    _ => { unreachable!("size is already known to be 0b10 or 0b11"); } +                                }; + +                                match Lo1 { +                                    0b00 => { +                                        inst.operands = [ +                                            Operand::Register(SizeCode::W, Rs), +                                            Operand::Register(size_code, Rt), +                                            Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand? +                                            Operand::Nothing, +                                        ]; +                                        match o0 { +                                            0b0 => Opcode::STXR, +                                            0b1 => Opcode::STLXR, +                                            _ => { unreachable!("o0 is one bit"); } +                                        } +                                    } +                                    0b01 => { +                                        inst.operands = [ +                                            Operand::Register(SizeCode::W, Rs), +                                            Operand::Register(size_code, Rt), +                                            Operand::Register(size_code, Rt2), +                                            Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand? +                                        ]; +                                        match o0 { +                                            0b0 => Opcode::STXP, +                                            0b1 => Opcode::STLXP, +                                            _ => { unreachable!("o0 is one bit"); } +                                        } +                                    } +                                    0b10 => { +                                        inst.operands = [ +                                            Operand::Register(size_code, Rt), +                                            Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand? +                                            Operand::Nothing, +                                            Operand::Nothing, +                                        ]; +                                        match o0 { +                                            0b0 => Opcode::LDXR, +                                            0b1 => Opcode::LDAXR, +                                            _ => { unreachable!("o0 is one bit"); } +                                        } +                                    } +                                    0b11 => { +                                        inst.operands = [ +                                            Operand::Register(size_code, Rt), +                                            Operand::Register(size_code, Rt2), +                                            Operand::RegisterOrSP(SizeCode::X, Rn), // memory operand? +                                            Operand::Nothing, +                                        ]; +                                        match o0 { +                                            0b0 => Opcode::LDXP, +                                            0b1 => Opcode::LDAXP, +                                            _ => { unreachable!("o0 is one bit"); } +                                        } +                                    } +                                    _ => { unreachable!("Lo1 is two bits"); } +                                } +                            }                              _ => { -                                Opcode::Invalid +                                unreachable!("size is two bits");                              } -                        }; -                        unreachable!("Rt: {}, Rn: {}, Rt2: {}, Rs: {}", Rt, Rn, Rt2, Rs); +                        }                      },                      0b00001 => {                          let Rt = (word & 0x1f) as u16; @@ -1618,8 +1853,15 @@ impl Decodable for Instruction {                          let size = (word >> 30) & 0x3;                          // load/store exclusive                          // o2 == 1 -                        println!("Word: {:#b}", word); -                        self.opcode = match (size, Lo1, o0) { +                        // STLRB -> Wt (Rt) Xn|SP (Rn) +                        // LDARB -> Wt (Rt) Xn|SP (Rn) +                        // STLRH -> Wt (Rt) Xn|SP (Rn) +                        // LDARH -> Wt (Rt) Xn|SP (Rn) +                        // STLR -> Wt (Rt) Xn|SP (Rn) +                        // LDAR -> Wt (Rt) Xn|SP (Rn) +                        // STLR -> Wt (Rt) Xn|SP (Rn) +                        // LDAR -> Wt (Rt) Xn|SP (Rn) +                        inst.opcode = match (size, Lo1, o0) {                              (0b00, 0b00, 0b1) => Opcode::STLRB,                              (0b00, 0b10, 0b1) => Opcode::LDARB,                              (0b01, 0b00, 0b1) => Opcode::STLRH, @@ -1629,7 +1871,8 @@ impl Decodable for Instruction {                              (0b11, 0b00, 0b1) => Opcode::STLR, // 64-bit                              (0b11, 0b10, 0b1) => Opcode::LDAR, // 64-bit                              _ => { -                                Opcode::Invalid +                                inst.opcode = Opcode::Invalid; +                                return None;                              }                          };                          let size_code = if size == 0b11 { @@ -1638,46 +1881,45 @@ impl Decodable for Instruction {                              SizeCode::W                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size_code, Rt),                              Operand::RegOffset(Rn, 0),                              Operand::Nothing,                              Operand::Nothing,                          ]; -                        unreachable!("Rt: {}, Rn: {}, Rt2: {}, Rs: {}", Rt, Rn, Rt2, Rs);                      },                      0b01000 |                      0b01001 => {                          // load register (literal)                          // V == 0 -                        let opc = (word >> 29) & 0x3; +                        let opc = (word >> 30) & 0x3;                          let Rt = (word & 0x1f) as u16;                          let imm19 = (word >> 5) & 0x7fff;                          let size = match opc {                              0b00 => { -                                self.opcode = Opcode::LDR; +                                inst.opcode = Opcode::LDR;                                  SizeCode::W                              },                              0b01 => { -                                self.opcode = Opcode::LDR; +                                inst.opcode = Opcode::LDR;                                  SizeCode::X                              }                              0b10 => { -                                self.opcode = Opcode::LDRSW; +                                inst.opcode = Opcode::LDRSW;                                  SizeCode::X                              }                              0b11 => { -                                unreachable!("PRFM is not supported"); +                                unimplemented!("PRFM is not supported");                              }                              _ => { -                                unreachable!(); +                                unreachable!("opc is two bits");                              }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rt), -                            Operand::PCOffset(imm19), +                            Operand::PCOffset(imm19 * 4),                              Operand::Nothing,                              Operand::Nothing,                          ]; @@ -1686,22 +1928,43 @@ impl Decodable for Instruction {                      0b01101 => {                          // load register (literal)                          // V == 1 -                        let opc = (word >> 29) & 0x3; -                        let Rt = word & 0x1f; +                        let opc = (word >> 30) & 0x3; +                        let Rt = (word & 0x1f) as u16;                          let imm19 = (word >> 5) & 0x7fff; -                        panic!("C3.3.5 V==1. opc: {}, Rt: {}, imm19: {}", opc, Rt, imm19); + +                        let size_code = match opc { +                            0b00 => SIMDSizeCode::S, +                            0b01 => SIMDSizeCode::D, +                            0b10 => SIMDSizeCode::Q, +                            0b11 => { +                                // 11011100_XXXXXXXX_XXXXXXXX_XXXXXXXX +                                inst.opcode = Opcode::Invalid; +                                return None; +                            } +                            _ => { +                                unreachable!("opc is two bits"); +                            } +                        }; + +                        inst.opcode = Opcode::LDR; +                        inst.operands = [ +                            Operand::SIMDRegister(size_code, Rt), +                            Operand::PCOffset(imm19 * 4), +                            Operand::Nothing, +                            Operand::Nothing, +                        ];                      },                      0b10000 => {                          // load/store no-allocate pair (offset)                          // V == 0                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6); -                        panic!("C3.3.7 V==0, opc_L: {}", opc_L); +                        unimplemented!("C3.3.7 V==0, opc_L: {}", opc_L);                      },                      0b10100 => {                          // load/store no-allocate pair (offset)                          // V == 1                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6); -                        panic!("C3.3.7 V==1, opc_L: {}", opc_L); +                        unimplemented!("C3.3.7 V==1, opc_L: {}", opc_L);                      },                      0b10001 => {                          // load/store register pair (post-indexed) @@ -1713,42 +1976,42 @@ impl Decodable for Instruction {                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6);                          let size = match opc_L {                              0b000 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b001 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b010 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::W                              },                              0b011 => { -                                self.opcode = Opcode::LDPSW; +                                inst.opcode = Opcode::LDPSW;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b100 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b101 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b110 |                              0b111 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::X                              } -                            _ => { unreachable!(); } +                            _ => { unreachable!("opc and L are three bits"); }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rt),                              Operand::Register(size, Rt2),                              Operand::RegPostIndex(Rn, imm7), @@ -1759,7 +2022,7 @@ impl Decodable for Instruction {                          // load/store register pair (post-indexed)                          // V == 1                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6); -                        panic!("C3.3.15 V==1, opc_L: {}", opc_L); +                        unreachable!("C3.3.15 V==1, opc_L: {}", opc_L);                      },                      0b10010 => {                          // load/store register pair (offset) @@ -1771,42 +2034,42 @@ impl Decodable for Instruction {                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6);                          let size = match opc_L {                              0b000 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b001 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b010 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::W                              },                              0b011 => { -                                self.opcode = Opcode::LDPSW; +                                inst.opcode = Opcode::LDPSW;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b100 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b101 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b110 |                              0b111 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::X                              } -                            _ => { unreachable!(); } +                            _ => { unreachable!("opc and L are three bits"); }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rt),                              Operand::Register(size, Rt2),                              Operand::RegOffset(Rn, imm7), @@ -1817,7 +2080,7 @@ impl Decodable for Instruction {                          // load/store register pair (offset)                          // V == 1                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6); -                        panic!("C3.3.14 V==1, opc_L: {}", opc_L); +                        unimplemented!("C3.3.14 V==1, opc_L: {}", opc_L);                      },                      0b10011 => {                          // load/store register pair (pre-indexed) @@ -1829,42 +2092,42 @@ impl Decodable for Instruction {                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6);                          let size = match opc_L {                              0b000 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b001 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b010 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::W                              },                              0b011 => { -                                self.opcode = Opcode::LDPSW; +                                inst.opcode = Opcode::LDPSW;                                  imm7 <<= 2;                                  SizeCode::W                              },                              0b100 => { -                                self.opcode = Opcode::STP; +                                inst.opcode = Opcode::STP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b101 => { -                                self.opcode = Opcode::LDP; +                                inst.opcode = Opcode::LDP;                                  imm7 <<= 3;                                  SizeCode::X                              },                              0b110 |                              0b111 => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  SizeCode::X                              } -                            _ => { unreachable!(); } +                            _ => { unreachable!("opc and L are three bits"); }                          }; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(size, Rt),                              Operand::Register(size, Rt2),                              Operand::RegPreIndex(Rn, imm7), @@ -1875,7 +2138,7 @@ impl Decodable for Instruction {                          // load/store register pair (pre-indexed)                          // V == 1                          let opc_L = ((word >> 22) & 1) | ((word >> 29) & 0x6); -                        panic!("C3.3.16 V==1, opc_L: {}", opc_L); +                        unimplemented!("C3.3.16 V==1, opc_L: {}", opc_L);                      },                      0b11000 |                      0b11001 => { @@ -1891,78 +2154,78 @@ impl Decodable for Instruction {                          println!("load/store: size_opc: {:#b}, category: {:#b}", size_opc, category);                          if word & 0x200000 != 0 {                              if category != 0b10 { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                                  return Some(());                              } else {                                  // Load/store register (register offset)                                  // C3.3.10                                  let size = match size_opc {                                      0b0000 => { -                                        self.opcode = Opcode::STRB; +                                        inst.opcode = Opcode::STRB;                                          SizeCode::W                                      },                                      0b0001 => { -                                        self.opcode = Opcode::LDRB; +                                        inst.opcode = Opcode::LDRB;                                          SizeCode::W                                      },                                      0b0010 => { -                                        self.opcode = Opcode::LDRSB; +                                        inst.opcode = Opcode::LDRSB;                                          SizeCode::X                                      },                                      0b0011 => { -                                        self.opcode = Opcode::LDRSB; +                                        inst.opcode = Opcode::LDRSB;                                          SizeCode::W                                      },                                      0b0100 => { -                                        self.opcode = Opcode::STRH; +                                        inst.opcode = Opcode::STRH;                                          SizeCode::W                                      },                                      0b0101 => { -                                        self.opcode = Opcode::LDRH; +                                        inst.opcode = Opcode::LDRH;                                          SizeCode::W                                      },                                      0b0110 => { -                                        self.opcode = Opcode::LDRSH; +                                        inst.opcode = Opcode::LDRSH;                                          SizeCode::X                                      },                                      0b0111 => { -                                        self.opcode = Opcode::LDRSH; +                                        inst.opcode = Opcode::LDRSH;                                          SizeCode::W                                      },                                      0b1000 => { -                                        self.opcode = Opcode::STR; +                                        inst.opcode = Opcode::STR;                                          SizeCode::W                                      },                                      0b1001 => { -                                        self.opcode = Opcode::LDR; +                                        inst.opcode = Opcode::LDR;                                          SizeCode::W                                      },                                      0b1010 => { -                                        self.opcode = Opcode::LDRSW; +                                        inst.opcode = Opcode::LDRSW;                                          SizeCode::X                                      },                                      0b1011 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          SizeCode::X                                      },                                      0b1100 => { -                                        self.opcode = Opcode::STR; +                                        inst.opcode = Opcode::STR;                                          SizeCode::X                                      },                                      0b1101 => { -                                        self.opcode = Opcode::LDR; +                                        inst.opcode = Opcode::LDR;                                          SizeCode::X                                      },                                      0b1110 => { -                                        panic!("PRFM is not supported yet"); -//                                        self.opcode = Opcode::PRFM; +                                        unimplemented!("PRFM is not supported yet"); +//                                        inst.opcode = Opcode::PRFM;  //                                        SizeCode::X                                      },                                      0b1111 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          SizeCode::X                                      }, -                                    _ => { unreachable!(); } +                                    _ => { unreachable!("size and opc are four bits"); }                                  };                                  let S = ((word >> 12) & 0x1) as u8; @@ -1972,33 +2235,33 @@ impl Decodable for Instruction {                                  let index_size = match option & 0x3 {                                      0b00 |                                      0b01 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          return Some(());                                      },                                      0b10 => { SizeCode::W }                                      0b11 => { SizeCode::X } -                                    _ => { unreachable!(); } +                                    _ => { unreachable!("option is two bits"); }                                  };                                  let shift_style = match option {                                      0b000 |                                      0b001 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          return Some(());                                      },                                      0b010 => { ShiftStyle::UXTW },                                      0b011 => { ShiftStyle::LSL },                                      0b100 |                                      0b101 => { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                          return Some(());                                      },                                      0b110 => { ShiftStyle::SXTW },                                      0b111 => { ShiftStyle::SXTX }, -                                    _ => { unreachable!(); } +                                    _ => { unreachable!("option is three bits"); }                                  }; -                                self.operands = [ +                                inst.operands = [                                      Operand::Register(size, Rt),                                      Operand::RegRegOffset(Rn, index_size, Rm, shift_style, S),                                      Operand::Nothing, @@ -2012,74 +2275,74 @@ impl Decodable for Instruction {                                      // Load/store register (unscaled immediate)                                      let size = match size_opc {                                          0b0000 => { -                                            self.opcode = Opcode::STURB; +                                            inst.opcode = Opcode::STURB;                                              SizeCode::W                                          }                                          0b0001 => { -                                            self.opcode = Opcode::LDURB; +                                            inst.opcode = Opcode::LDURB;                                              SizeCode::W                                          }                                          0b0010 => { -                                            self.opcode = Opcode::LDURSB; +                                            inst.opcode = Opcode::LDURSB;                                              SizeCode::X                                          }                                          0b0011 => { -                                            self.opcode = Opcode::LDURSB; +                                            inst.opcode = Opcode::LDURSB;                                              SizeCode::W                                          }                                          0b0100 => { -                                            self.opcode = Opcode::STURH; +                                            inst.opcode = Opcode::STURH;                                              SizeCode::W                                          }                                          0b0101 => { -                                            self.opcode = Opcode::LDURH; +                                            inst.opcode = Opcode::LDURH;                                              SizeCode::W                                          }                                          0b0110 => { -                                            self.opcode = Opcode::LDURSH; +                                            inst.opcode = Opcode::LDURSH;                                              SizeCode::X                                          }                                          0b0111 => { -                                            self.opcode = Opcode::LDURSH; +                                            inst.opcode = Opcode::LDURSH;                                              SizeCode::W                                          }                                          0b1000 => { -                                            self.opcode = Opcode::STUR; +                                            inst.opcode = Opcode::STUR;                                              SizeCode::W                                          }                                          0b1001 => { -                                            self.opcode = Opcode::LDUR; +                                            inst.opcode = Opcode::LDUR;                                              SizeCode::W                                          }                                          0b1010 => { -                                            self.opcode = Opcode::LDURSW; +                                            inst.opcode = Opcode::LDURSW;                                              SizeCode::X                                          }                                          0b1011 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::W                                          }                                          0b1100 => { -                                            self.opcode = Opcode::STUR; +                                            inst.opcode = Opcode::STUR;                                              SizeCode::X                                          }                                          0b1101 => { -                                            self.opcode = Opcode::LDUR; +                                            inst.opcode = Opcode::LDUR;                                              SizeCode::X                                          }                                          0b1110 => { -                                            panic!("PRFUM not handled yet"); +                                            unimplemented!("PRFUM not handled yet");                                          },                                          0b1111 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::W                                          }                                          _ => { -                                            unreachable!(); +                                            unreachable!("size and opc are four bits");                                          }                                      }; -                                    self.operands = [ +                                    inst.operands = [                                          Operand::Register(size, Rt),                                          Operand::RegOffset(Rn, imm9),                                          Operand::Nothing, @@ -2091,72 +2354,72 @@ impl Decodable for Instruction {                                      let size = match size_opc {                                          0b0000 => { -                                            self.opcode = Opcode::STTRB; +                                            inst.opcode = Opcode::STTRB;                                              SizeCode::W                                          }                                          0b0001 => { -                                            self.opcode = Opcode::LDTRB; +                                            inst.opcode = Opcode::LDTRB;                                              SizeCode::W                                          }                                          0b0010 => { -                                            self.opcode = Opcode::LDTRSB; +                                            inst.opcode = Opcode::LDTRSB;                                              SizeCode::X                                          }                                          0b0011 => { -                                            self.opcode = Opcode::LDTRSB; +                                            inst.opcode = Opcode::LDTRSB;                                              SizeCode::W                                          }                                          0b0100 => { -                                            self.opcode = Opcode::STTRH; +                                            inst.opcode = Opcode::STTRH;                                              SizeCode::W                                          }                                          0b0101 => { -                                            self.opcode = Opcode::LDTRH; +                                            inst.opcode = Opcode::LDTRH;                                              SizeCode::W                                          }                                          0b0110 => { -                                            self.opcode = Opcode::LDTRSH; +                                            inst.opcode = Opcode::LDTRSH;                                              SizeCode::X                                          }                                          0b0111 => { -                                            self.opcode = Opcode::LDTRSH; +                                            inst.opcode = Opcode::LDTRSH;                                              SizeCode::W                                          }                                          0b1000 => { -                                            self.opcode = Opcode::STTR; +                                            inst.opcode = Opcode::STTR;                                              SizeCode::W                                          }                                          0b1001 => { -                                            self.opcode = Opcode::LDTR; +                                            inst.opcode = Opcode::LDTR;                                              SizeCode::W                                          }                                          0b1010 => { -                                            self.opcode = Opcode::LDTRSW; +                                            inst.opcode = Opcode::LDTRSW;                                              SizeCode::X                                          }                                          0b1011 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::W                                          }                                          0b1100 => { -                                            self.opcode = Opcode::STTR; +                                            inst.opcode = Opcode::STTR;                                              SizeCode::X                                          }                                          0b1101 => { -                                            self.opcode = Opcode::LDTR; +                                            inst.opcode = Opcode::LDTR;                                              SizeCode::X                                          }                                          0b1110 |                                          0b1111 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::W                                          }                                          _ => { -                                            unreachable!(); +                                            unreachable!("size and opc are four bits");                                          }                                      }; -                                    self.operands = [ +                                    inst.operands = [                                          Operand::Register(size, Rt),                                          Operand::RegPreIndex(Rn, imm9),                                          Operand::Nothing, @@ -2167,69 +2430,69 @@ impl Decodable for Instruction {                                  0b11 => {                                      let size = match size_opc {                                          0b0000 => { -                                            self.opcode = Opcode::STRB; +                                            inst.opcode = Opcode::STRB;                                              SizeCode::W                                          },                                          0b0001 => { -                                            self.opcode = Opcode::LDRB; +                                            inst.opcode = Opcode::LDRB;                                              SizeCode::W                                          }                                          0b0010 => { -                                            self.opcode = Opcode::LDRSB; +                                            inst.opcode = Opcode::LDRSB;                                              SizeCode::X                                          }                                          0b0011 => { -                                            self.opcode = Opcode::LDRSB; +                                            inst.opcode = Opcode::LDRSB;                                              SizeCode::W                                          }                                          0b0100 => { -                                            self.opcode = Opcode::STRH; +                                            inst.opcode = Opcode::STRH;                                              SizeCode::W                                          }                                          0b0101 => { -                                            self.opcode = Opcode::LDRH; +                                            inst.opcode = Opcode::LDRH;                                              SizeCode::W                                          }                                          0b0110 => { -                                            self.opcode = Opcode::LDRSH; +                                            inst.opcode = Opcode::LDRSH;                                              SizeCode::X                                          }                                          0b0111 => { -                                            self.opcode = Opcode::LDRSH; +                                            inst.opcode = Opcode::LDRSH;                                              SizeCode::W                                          }                                          0b1000 => { -                                            self.opcode = Opcode::STR; +                                            inst.opcode = Opcode::STR;                                              SizeCode::W                                          }                                          0b1001 => { -                                            self.opcode = Opcode::LDR; +                                            inst.opcode = Opcode::LDR;                                              SizeCode::W                                          }                                          0b1010 |                                          0b1011 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::W                                          }                                          0b1100 => { -                                            self.opcode = Opcode::STR; +                                            inst.opcode = Opcode::STR;                                              SizeCode::X                                          }                                          0b1101 => { -                                            self.opcode = Opcode::LDR; +                                            inst.opcode = Opcode::LDR;                                              SizeCode::X                                          }                                          0b1110 |                                          0b1111 => { -                                            self.opcode = Opcode::Invalid; +                                            inst.opcode = Opcode::Invalid;                                              SizeCode::X                                          }                                          _ => { -                                            unreachable!(); +                                            unreachable!("size and opc are four bits");                                          }                                      }; -                                    self.operands = [ +                                    inst.operands = [                                          Operand::Register(size, Rt),                                          if category == 0b01 {                                              Operand::RegPostIndex(Rn, imm9) @@ -2241,7 +2504,7 @@ impl Decodable for Instruction {                                      ];                                  },                                  _ => { -                                    unreachable!(); +                                    unreachable!("category is two bits");                                  }                              }                          } @@ -2253,6 +2516,7 @@ impl Decodable for Instruction {                           * unprivileged, immediate pre-indexd, register offset}                           * V == 1                           */ +                        unimplemented!("load/store register (unscaled immediate), load/store register (immediate post-indexed), V==1");                      }                      0b11010 |                      0b11011 => { @@ -2264,8 +2528,8 @@ impl Decodable for Instruction {                          let size_opc = ((word >> 22) & 0x3) | ((word >> 28) & 0xc);                          match size_opc {                              0b0000 => { -                                self.opcode = Opcode::STRB; -                                self.operands = [ +                                inst.opcode = Opcode::STRB; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12),                                      Operand::Nothing, @@ -2273,8 +2537,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0001 => { -                                self.opcode = Opcode::LDRB; -                                self.operands = [ +                                inst.opcode = Opcode::LDRB; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12),                                      Operand::Nothing, @@ -2282,8 +2546,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0010 => { -                                self.opcode = Opcode::LDRSB; -                                self.operands = [ +                                inst.opcode = Opcode::LDRSB; +                                inst.operands = [                                      Operand::Register(SizeCode::X, Rt),                                      Operand::RegOffset(Rn, imm12),                                      Operand::Nothing, @@ -2291,8 +2555,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0011 => { -                                self.opcode = Opcode::LDRSB; -                                self.operands = [ +                                inst.opcode = Opcode::LDRSB; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12),                                      Operand::Nothing, @@ -2300,8 +2564,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0100 => { -                                self.opcode = Opcode::STRH; -                                self.operands = [ +                                inst.opcode = Opcode::STRH; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12 << 1),                                      Operand::Nothing, @@ -2309,8 +2573,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0101 => { -                                self.opcode = Opcode::LDRH; -                                self.operands = [ +                                inst.opcode = Opcode::LDRH; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12 << 1),                                      Operand::Nothing, @@ -2318,8 +2582,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0110 => { -                                self.opcode = Opcode::LDRSH; -                                self.operands = [ +                                inst.opcode = Opcode::LDRSH; +                                inst.operands = [                                      Operand::Register(SizeCode::X, Rt),                                      Operand::RegOffset(Rn, imm12 << 1),                                      Operand::Nothing, @@ -2327,8 +2591,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b0111 => { -                                self.opcode = Opcode::LDRSH; -                                self.operands = [ +                                inst.opcode = Opcode::LDRSH; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12 << 1),                                      Operand::Nothing, @@ -2336,8 +2600,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b1000 => { -                                self.opcode = Opcode::STR; -                                self.operands = [ +                                inst.opcode = Opcode::STR; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12 << 2),                                      Operand::Nothing, @@ -2345,8 +2609,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b1001 => { -                                self.opcode = Opcode::LDR; -                                self.operands = [ +                                inst.opcode = Opcode::LDR; +                                inst.operands = [                                      Operand::Register(SizeCode::W, Rt),                                      Operand::RegOffset(Rn, imm12 << 2),                                      Operand::Nothing, @@ -2354,18 +2618,18 @@ impl Decodable for Instruction {                                  ];                              }                              0b1010 => { -                                self.opcode = Opcode::LDRSW; -                                self.operands = [ +                                inst.opcode = Opcode::LDRSW; +                                inst.operands = [                                      Operand::Register(SizeCode::X, Rt),                                      Operand::RegOffset(Rn, imm12 << 2),                                      Operand::Nothing,                                      Operand::Nothing,                                  ];                              } -                            0b1011 => { self.opcode = Opcode::Invalid; } +                            0b1011 => { inst.opcode = Opcode::Invalid; }                              0b1100 => { -                                self.opcode = Opcode::STR; -                                self.operands = [ +                                inst.opcode = Opcode::STR; +                                inst.operands = [                                      Operand::Register(SizeCode::X, Rt),                                      Operand::RegOffset(Rn, imm12 << 3),                                      Operand::Nothing, @@ -2373,8 +2637,8 @@ impl Decodable for Instruction {                                  ];                              }                              0b1101 => { -                                self.opcode = Opcode::LDR; -                                self.operands = [ +                                inst.opcode = Opcode::LDR; +                                inst.operands = [                                      Operand::Register(SizeCode::X, Rt),                                      Operand::RegOffset(Rn, imm12 << 3),                                      Operand::Nothing, @@ -2382,31 +2646,36 @@ impl Decodable for Instruction {                                  ];                              }                              0b1110 => { -                                unreachable!("PRFM not yet supported"); +                                unimplemented!("PRFM not yet supported");                              } -                            0b1111 => { self.opcode = Opcode::Invalid; } -                            _ => { unreachable!(); } +                            0b1111 => { inst.opcode = Opcode::Invalid; } +                            _ => { unreachable!("size and opc are four bits"); }                          }                      },                      0b11110 |                      0b11111 => {                          // load/store register (unsigned immediate)                          // V == 1 +                        unimplemented!("load/store register (unsigned immediate) V==1");                      },                      0b00100 => {                          // AdvSIMD load/store multiple structures +                        unimplemented!("AdvSIMD load/store multiple structures");                      },                      0b00101 => {                          // AdvSIMD load/store multiple structures (post-indexed) +                        unimplemented!("AdvSIMD load/store multiple structures (post-indexed)");                      },                      0b00110 => {                          // AdvSIMD load/store single structure +                        unimplemented!("AdvSIMD load/store single structure");                      },                      0b00111 => {                          // AdvSIMD load/store single structure (post-indexed) +                        unimplemented!("AdvSIMD load/store single structures (post-indexed)");                      }                      _ => { -                        self.opcode = Opcode::Invalid; +                        inst.opcode = Opcode::Invalid;                      }                  }              }, @@ -2417,8 +2686,8 @@ impl Decodable for Instruction {                      0b00001 |                      0b00010 |                      0b00011 => { // unconditional branch (imm) -                        self.opcode = Opcode::B; -                        self.operands = [ +                        inst.opcode = Opcode::B; +                        inst.operands = [                              Operand::Offset((word & 0x01ffffff) << 2),                              Operand::Nothing,                              Operand::Nothing, @@ -2426,10 +2695,10 @@ impl Decodable for Instruction {                          ];                      },                      0b00100 => { // compare branch (imm) -                        self.opcode = Opcode::CBZ; +                        inst.opcode = Opcode::CBZ;                          let imm = (word >> 3) & 0x001ffffc;                          let Rt = word & 0x1f; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(SizeCode::W, Rt as u16),                              Operand::Offset(imm),                              Operand::Nothing, @@ -2437,10 +2706,10 @@ impl Decodable for Instruction {                          ];                      },                      0b00101 => { // compare branch (imm) -                        self.opcode = Opcode::CBNZ; +                        inst.opcode = Opcode::CBNZ;                          let imm = (word >> 3) & 0x001ffffc;                          let Rt = word & 0x1f; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(SizeCode::W, Rt as u16),                              Operand::Offset(imm),                              Operand::Nothing, @@ -2451,8 +2720,8 @@ impl Decodable for Instruction {                          let imm = (word >> 3) & 0x0003fffc;                          let b = (word >> 19) & 0x1f;                          let Rt = word & 0x1f; -                        self.opcode = Opcode::TBZ; -                        self.operands = [ +                        inst.opcode = Opcode::TBZ; +                        inst.operands = [                              Operand::Register(SizeCode::W, Rt as u16),                              Operand::Imm16(b as u16),                              Operand::Offset(imm), @@ -2463,8 +2732,8 @@ impl Decodable for Instruction {                          let imm = (word >> 3) & 0x0003fffc;                          let b = (word >> 19) & 0x1f;                          let Rt = word & 0x1f; -                        self.opcode = Opcode::TBNZ; -                        self.operands = [ +                        inst.opcode = Opcode::TBNZ; +                        inst.operands = [                              Operand::Register(SizeCode::W, Rt as u16),                              Operand::Imm16(b as u16),                              Operand::Offset(imm), @@ -2474,8 +2743,8 @@ impl Decodable for Instruction {                      0b01000 => { // conditional branch (imm)                          let imm = (word >> 3) & 0x001ffffc;                          let cond = word & 0x0f; -                        self.opcode = Opcode::Bcc(cond as u8); -                        self.operands = [ +                        inst.opcode = Opcode::Bcc(cond as u8); +                        inst.operands = [                              Operand::Offset(imm),                              Operand::Nothing,                              Operand::Nothing, @@ -2483,15 +2752,15 @@ impl Decodable for Instruction {                          ];                      }                      0b01001 => { // conditional branch (imm) -                        self.opcode = Opcode::Invalid; +                        inst.opcode = Opcode::Invalid;                      }                      /* 0b01010 to 0b01111 seem all invalid? */                      0b10000 |                      0b10001 |                      0b10010 |                      0b10011 => { // unconditional branch (imm) -                        self.opcode = Opcode::BL; -                        self.operands = [ +                        inst.opcode = Opcode::BL; +                        inst.operands = [                              Operand::Offset((word & 0x01ffffff) << 2),                              Operand::Nothing,                              Operand::Nothing, @@ -2499,10 +2768,10 @@ impl Decodable for Instruction {                          ];                      },                      0b10100 => { // compare branch (imm) -                        self.opcode = Opcode::CBZ; +                        inst.opcode = Opcode::CBZ;                          let imm = (word >> 3) & 0x001ffffc;                          let Rt = word & 0x1f; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(SizeCode::X, Rt as u16),                              Operand::Offset(imm),                              Operand::Nothing, @@ -2510,10 +2779,10 @@ impl Decodable for Instruction {                          ];                      },                      0b10101 => { // compare branch (imm) -                        self.opcode = Opcode::CBNZ; +                        inst.opcode = Opcode::CBNZ;                          let imm = (word >> 3) & 0x001ffffc;                          let Rt = word & 0x1f; -                        self.operands = [ +                        inst.operands = [                              Operand::Register(SizeCode::X, Rt as u16),                              Operand::Offset(imm),                              Operand::Nothing, @@ -2524,8 +2793,8 @@ impl Decodable for Instruction {                          let imm = (word >> 3) & 0x0003fffc;                          let b = (word >> 19) & 0x1f;                          let Rt = word & 0x1f; -                        self.opcode = Opcode::TBZ; -                        self.operands = [ +                        inst.opcode = Opcode::TBZ; +                        inst.operands = [                              Operand::Register(SizeCode::X, Rt as u16),                              Operand::Imm16((b as u16) | 0x20),                              Operand::Offset(imm), @@ -2536,8 +2805,8 @@ impl Decodable for Instruction {                          let imm = (word >> 3) & 0x0003fffc;                          let b = (word >> 19) & 0x1f;                          let Rt = word & 0x1f; -                        self.opcode = Opcode::TBNZ; -                        self.operands = [ +                        inst.opcode = Opcode::TBNZ; +                        inst.operands = [                              Operand::Register(SizeCode::X, Rt as u16),                              Operand::Imm16((b as u16) | 0x20),                              Operand::Offset(imm), @@ -2550,35 +2819,35 @@ impl Decodable for Instruction {                          let opc = (word >> 21) & 0x7;                          match (opc, op2, ll) {                              (0b000, 0b000, 0b01) => { -                                self.opcode = Opcode::SVC; +                                inst.opcode = Opcode::SVC;                              }                              (0b000, 0b000, 0b10) => { -                                self.opcode = Opcode::HVC; +                                inst.opcode = Opcode::HVC;                              }                              (0b000, 0b000, 0b11) => { -                                self.opcode = Opcode::SMC; +                                inst.opcode = Opcode::SMC;                              }                              (0b001, 0b000, 0b00) => { -                                self.opcode = Opcode::BRK; +                                inst.opcode = Opcode::BRK;                              }                              (0b010, 0b000, 0b00) => { -                                self.opcode = Opcode::HLT; +                                inst.opcode = Opcode::HLT;                              }                              (0b101, 0b000, 0b01) => { -                                self.opcode = Opcode::DCPS1; +                                inst.opcode = Opcode::DCPS1;                              }                              (0b101, 0b000, 0b10) => { -                                self.opcode = Opcode::DCPS2; +                                inst.opcode = Opcode::DCPS2;                              }                              (0b101, 0b000, 0b11) => { -                                self.opcode = Opcode::DCPS3; +                                inst.opcode = Opcode::DCPS3;                              }                              _ => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                              }                          }                          let imm = (word >> 5) & 0xffff; -                        self.operands = [ +                        inst.operands = [                              Operand::Imm16(imm as u16),                              Operand::Nothing,                              Operand::Nothing, @@ -2588,7 +2857,7 @@ impl Decodable for Instruction {                      0b11001 => { // system                          let remainder = word & 0xffffff;                          if remainder >= 0x400000 { -                            self.opcode = Opcode::Invalid; +                            inst.opcode = Opcode::Invalid;                          } else {                              let Rt = word & 0x1f;                              let Lop0 = ((word >> 19) & 0x7) as u8; @@ -2603,65 +2872,65 @@ impl Decodable for Instruction {                                          match CRn {                                              0b0010 => {                                                  if op1 == 0b011 { -                                                    self.opcode = Opcode::HINT(op2 as u8); +                                                    inst.opcode = Opcode::HINT(op2 as u8);                                                  } else { -                                                    self.opcode = Opcode::Invalid; +                                                    inst.opcode = Opcode::Invalid;                                                  }                                              },                                              0b0011 => {                                                  match op2 {                                                      0b010 => { -                                                        self.opcode = Opcode::CLREX; +                                                        inst.opcode = Opcode::CLREX;                                                      },                                                      0b100 => { -                                                        self.opcode = Opcode::DSB; +                                                        inst.opcode = Opcode::DSB;                                                      },                                                      0b101 => { -                                                        self.opcode = Opcode::DMB; +                                                        inst.opcode = Opcode::DMB;                                                      },                                                      0b110 => { -                                                        self.opcode = Opcode::ISB; +                                                        inst.opcode = Opcode::ISB;                                                      }                                                      _ => { -                                                        self.opcode = Opcode::Invalid; +                                                        inst.opcode = Opcode::Invalid;                                                      }                                                  };                                              },                                              0b0100 => { -                                                self.opcode = Opcode::MSRa(op1 as u8, op2 as u8); -                                                self.operands[0] = Operand::Imm16( +                                                inst.opcode = Opcode::MSRa(op1 as u8, op2 as u8); +                                                inst.operands[0] = Operand::Imm16(                                                      ((word >> 8) & 0xf) as u16                                                  );                                              }                                              _ => { -                                                self.opcode = Opcode::Invalid; +                                                inst.opcode = Opcode::Invalid;                                              }                                          }                                      } else { -                                        self.opcode = Opcode::Invalid; +                                        inst.opcode = Opcode::Invalid;                                      }                                  }                                  0b001 => { -                                    self.opcode = Opcode::SYS; +                                    inst.opcode = Opcode::SYS;                                      panic!("TODO");                                  }                                  0b010 |                                  0b011 => { -                                    self.opcode = Opcode::MSRb(word & 0x0fffff); +                                    inst.opcode = Opcode::MSRb(word & 0x0fffff);                                  }                                  0b100 => { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                                  0b101 => { -                                    self.opcode = Opcode::SYSL; +                                    inst.opcode = Opcode::SYSL;                                      panic!("TODO");                                  }                                  0b110 |                                  0b111 => { -                                    self.opcode = Opcode::MRS(word & 0x0fffff); +                                    inst.opcode = Opcode::MRS(word & 0x0fffff);                                  }                                  _ => { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              }                          } @@ -2673,68 +2942,68 @@ impl Decodable for Instruction {                              0b000 => {                                  if (word & 0x1ffc1f) == 0x1f0000 {                                      let Rn = (word >> 5) & 0x1f; -                                    self.opcode = Opcode::BR; -                                    self.operands = [ +                                    inst.opcode = Opcode::BR; +                                    inst.operands = [                                          Operand::Register(SizeCode::X, Rn as u16),                                          Operand::Nothing,                                          Operand::Nothing,                                          Operand::Nothing                                      ];                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              },                              0b001 => {                                  if (word & 0x1ffc1f) == 0x1f0000 {                                      let Rn = (word >> 5) & 0x1f; -                                    self.opcode = Opcode::BLR; -                                    self.operands = [ +                                    inst.opcode = Opcode::BLR; +                                    inst.operands = [                                          Operand::Register(SizeCode::X, Rn as u16),                                          Operand::Nothing,                                          Operand::Nothing,                                          Operand::Nothing                                      ];                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              },                              0b010 => {                                  if (word & 0x1ffc1f) == 0x1f0000 {                                      let Rn = (word >> 5) & 0x1f; -                                    self.opcode = Opcode::RET; -                                    self.operands = [ +                                    inst.opcode = Opcode::RET; +                                    inst.operands = [                                          Operand::Register(SizeCode::X, Rn as u16),                                          Operand::Nothing,                                          Operand::Nothing,                                          Operand::Nothing                                      ];                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              },                              0b100 => {                                  if (word & 0x1fffff) == 0x1f03e0 { -                                    self.opcode = Opcode::ERET; +                                    inst.opcode = Opcode::ERET;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              },                              0b101 => {                                  if (word & 0x1fffff) == 0x1f03e0 { -                                    self.opcode = Opcode::DRPS; +                                    inst.opcode = Opcode::DRPS;                                  } else { -                                    self.opcode = Opcode::Invalid; +                                    inst.opcode = Opcode::Invalid;                                  }                              },                              _ => { -                                self.opcode = Opcode::Invalid; +                                inst.opcode = Opcode::Invalid;                              }                          }                      }                      0b11011 => { // unconditional branch (reg)                          // the last 1 is bit 24, which C3.2.7 indicates are                          // all invalid encodings (opc is b0101 or lower) -                        self.opcode = Opcode::Invalid; +                        inst.opcode = Opcode::Invalid;                      }                      _ => {                          // TODO: invalid diff --git a/test/armv7.rs b/test/armv7.rs index 09f5333..7b0c2b6 100644 --- a/test/armv7.rs +++ b/test/armv7.rs @@ -1,9 +1,8 @@ -use yaxpeax_arch::{Decodable, LengthedInstruction}; +use yaxpeax_arch::{Arch, Decoder, LengthedInstruction};  use yaxpeax_arm::armv7::{ARMv7, Instruction, ConditionCode, Operands, Opcode, ShiftSpec};  fn test_decode(data: [u8; 4], expected: Instruction) { -    let mut instr = Instruction::blank(); -    instr.decode_into(data.to_vec()); +    let instr = <ARMv7 as Arch>::Decoder::default().decode(data.to_vec()).unwrap();      assert!(          instr == expected,          "decode error for {:02x}{:02x}{:02x}{:02x}:\n  decoded: {:?}\n expected: {:?}\n", @@ -13,8 +12,7 @@ fn test_decode(data: [u8; 4], expected: Instruction) {  }  fn test_display(data: [u8; 4], expected: &'static str) { -    let mut instr = Instruction::blank(); -    instr.decode_into(data.to_vec()); +    let instr = <ARMv7 as Arch>::Decoder::default().decode(data.to_vec()).unwrap();      let text = format!("{}", instr);      assert!(          text == expected, @@ -318,8 +316,7 @@ static instruction_bytes: [u8; 4 * 60] = [  fn test_decode_span() {      let mut i = 0u32;      while i < instruction_bytes.len() as u32 { -        let mut instr = Instruction::blank(); -        instr.decode_into(instruction_bytes[(i as usize)..].iter().map(|x| *x)); +        let instr = <ARMv7 as Arch>::Decoder::default().decode(instruction_bytes[(i as usize)..].iter().cloned()).unwrap();          println!(              "Decoded {:02x}{:02x}{:02x}{:02x}: {}", //{:?}\n  {}",              instruction_bytes[i as usize], @@ -402,9 +399,10 @@ pub fn bench_60000_instrs(b: &mut Bencher) {      b.iter(|| {          for i in (0..1000) {              let mut iter = instruction_bytes.iter().map(|x| *x); +            let decoder = <ARMv7 as Arch>::Decoder::default();              let mut result = Instruction::blank();              loop { -                match result.decode_into(&mut iter) { +                match decoder.decode_into(&mut result, &mut iter) {                      Some(result) => {                          test::black_box(&result);                      }, diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs index 80bd31c..4886fe1 100644 --- a/test/armv8/a64.rs +++ b/test/armv8/a64.rs @@ -1,9 +1,8 @@ -use yaxpeax_arch::{Decodable, LengthedInstruction}; -use yaxpeax_arm::armv8::a64::{ARMv8, Instruction, Operand, Opcode, SizeCode}; +use yaxpeax_arch::{Arch, Decoder, LengthedInstruction}; +use yaxpeax_arm::armv8::a64::{ARMv8, Instruction, Operand, Opcode, SizeCode, ShiftStyle};  fn test_decode(data: [u8; 4], expected: Instruction) { -    let mut instr = Instruction::blank(); -    instr.decode_into(data.to_vec()); +    let instr = <ARMv8 as Arch>::Decoder::default().decode(data.to_vec()).unwrap();      assert!(          instr == expected,          "decode error for {:02x}{:02x}{:02x}{:02x}:\n  decoded: {:?}\n expected: {:?}\n", @@ -13,8 +12,7 @@ fn test_decode(data: [u8; 4], expected: Instruction) {  }  fn test_display(data: [u8; 4], expected: &'static str) { -    let mut instr = Instruction::blank(); -    instr.decode_into(data.to_vec()); +    let instr = <ARMv8 as Arch>::Decoder::default().decode(data.to_vec()).unwrap();      let text = format!("{}", instr);      assert!(          text == expected, @@ -41,19 +39,51 @@ fn test_display_misc() {  fn test_decode_str_ldr() {      test_decode(          [0x31, 0x03, 0x40, 0xf9], -        Instruction::blank() +        Instruction { +            opcode: Opcode::LDR, +            operands: [ +                Operand::Register(SizeCode::X, 17), +                Operand::RegOffset(25, 0), +                Operand::Nothing, +                Operand::Nothing, +            ] +        }      );      test_decode(          [0xf5, 0x5b, 0x00, 0xf9], -        Instruction::blank() +        Instruction { +            opcode: Opcode::STR, +            operands: [ +                Operand::Register(SizeCode::X, 21), +                Operand::RegOffset(31, 0xb0), +                Operand::Nothing, +                Operand::Nothing, +            ] +        }      );      test_decode(          [0x60, 0x02, 0x0a, 0x39], -        Instruction::blank() +        Instruction { +            opcode: Opcode::STRB, +            operands: [ +                Operand::Register(SizeCode::W, 0), +                Operand::RegOffset(19, 0x280), +                Operand::Nothing, +                Operand::Nothing, +            ] +        }      );      test_decode(          [0xfd, 0x7b, 0xbe, 0xa9], -        Instruction::blank() +        Instruction { +            opcode: Opcode::STP, +            operands: [ +                Operand::Register(SizeCode::X, 29), +                Operand::Register(SizeCode::X, 30), +                Operand::RegPreIndex(31, -0x20), +                Operand::Nothing, +            ] +        }      );  } @@ -90,6 +120,44 @@ fn test_decode_misc() {  }  #[test] +fn test_display_ldr() { +    test_display( +        [0xff, 0xff, 0x00, 0x1c], +        "ldr s31, $+0x1ffc" +    ); +    test_display( +        [0xff, 0xff, 0x00, 0x5c], +        "ldr d31, $+0x1ffc" +    ); +    test_display( +        [0xff, 0xff, 0x00, 0x9c], +        "ldr q31, $+0x1ffc" +    ); +    test_display( +        [0xff, 0xff, 0x00, 0xdc], +        "invalid" +    ); +    test_display( +        [0x88, 0xff, 0x00, 0x18], +        "ldr w8, $+0x1ff0" +    ); +    test_display( +        [0x88, 0xff, 0x00, 0x58], +        "ldr x8, $+0x1ff0" +    ); +    test_display( +        [0x88, 0xff, 0x00, 0x98], +        "ldrsw x8, $+0x1ff0" +    ); +    /* TODO: +    test_display( +        [0x88, 0xff, 0x00, 0xd8], +        "prfm plil1keep, 0x1ff0" +    ); +    */ +} + +#[test]  fn test_decode_mov() {      test_decode(          [0x20, 0x00, 0x80, 0x52], @@ -149,7 +217,15 @@ fn test_decode_branch() {  fn test_decode_arithmetic() {      test_decode(          [0x21, 0xfc, 0x41, 0x8b], -        Instruction::blank() +        Instruction { +            opcode: Opcode::ADD, +            operands: [ +                Operand::Register(SizeCode::X, 1), +                Operand::Register(SizeCode::X, 1), +                Operand::RegShift(ShiftStyle::LSR, 63, SizeCode::X, 1), +                Operand::Nothing +            ] +        }      );      test_decode(          [0x21, 0xfc, 0x43, 0x93], @@ -169,7 +245,7 @@ fn test_decode_arithmetic() {              opcode: Opcode::SUBS,              operands: [                  Operand::Register(SizeCode::X, 31), -                Operand::Register(SizeCode::X, 1), +                Operand::RegisterOrSP(SizeCode::X, 1),                  Operand::Immediate(0xe),                  Operand::Nothing,              ] @@ -2168,15 +2244,75 @@ fn test_decode_chrome_entrypoint() {      );  } -static instruction_bytes: [u8; 4 * 0] = [ +static instruction_bytes: [u8; 4 * 61] = [ +    0x00, 0x00, 0x00, 0x00, +    0x00, 0x00, 0x20, 0xd4, +    0x00, 0x00, 0x80, 0x12, +    0x00, 0x01, 0x3f, 0xd6, +    0x00, 0x02, 0x00, 0x36, +    0x00, 0x03, 0x00, 0x35, +    0x00, 0x04, 0x00, 0x36, +    0x00, 0x04, 0x40, 0xf9, +    0x00, 0x07, 0x00, 0x34, +    0x00, 0x08, 0x47, 0xf9, +    0x00, 0x0b, 0x80, 0x52, +    0x00, 0x14, 0x42, 0xf9, +    0x00, 0x1b, 0x80, 0x52, +    0x00, 0x20, 0x40, 0xf9, +    0x00, 0x24, 0x47, 0xf9, +    0x00, 0x2b, 0x03, 0x90, +    0x00, 0x34, 0x42, 0xf9, +    0x00, 0x39, 0x04, 0xb0, +    0x00, 0x3b, 0x04, 0xb0, +    0x00, 0x3c, 0x43, 0xf9, +    0x00, 0x44, 0x44, 0xf9, +    0x00, 0x50, 0x14, 0x91, +    0x00, 0x54, 0x44, 0xf9, +    0x00, 0x58, 0x42, 0xf9, +    0x00, 0x5c, 0x44, 0xf9, +    0x00, 0x60, 0x1e, 0x91, +    0x00, 0x70, 0x47, 0xf9, +    0x00, 0x80, 0x1e, 0x91, +    0x00, 0x80, 0x44, 0xf9, +    0x00, 0x84, 0x47, 0xf9, +    0x00, 0xac, 0x40, 0xf9, +    0x00, 0xc0, 0x09, 0x91, +    0x00, 0xc4, 0x45, 0xf9, +    0x00, 0xcc, 0x41, 0xf9, +    0x00, 0xdc, 0x35, 0x91, +    0x00, 0xf4, 0x47, 0xf9, +    0x01, 0x00, 0x00, 0x14, +    0x01, 0x00, 0x40, 0xf9, +    0x01, 0x05, 0x40, 0xf9, +    0x01, 0xfb, 0x4b, 0x95, +    0x02, 0x00, 0x00, 0x14, +    0x02, 0x00, 0x00, 0x90, +    0x02, 0x00, 0x80, 0x92, +    0x02, 0x04, 0xf8, 0x97, +    0x02, 0x2c, 0x80, 0x52, +    0x08, 0x00, 0x40, 0xf9, +    0x08, 0x01, 0x40, 0xf9, +    0x08, 0x05, 0x40, 0xf9, +    0x08, 0x06, 0xf8, 0x97, +    0x08, 0x09, 0x40, 0xf9, +    0x08, 0x1d, 0x40, 0x92, +    0x08, 0x1f, 0x00, 0x13, +    0x08, 0x21, 0x0a, 0x91, +    0x08, 0x41, 0x00, 0x91, +    0x08, 0x41, 0x40, 0xf9, +    0x08, 0x81, 0x0a, 0x91, +    0x08, 0xa1, 0x11, 0x91, +    0x08, 0xc1, 0x1e, 0x91, +    0x08, 0xdd, 0x46, 0xf9, +    0x08, 0xe1, 0x0e, 0x91, +    0x08, 0xf2, 0xff, 0x36,  ];  #[test]  fn test_decode_span() {      let mut i = 0u64;      while i < instruction_bytes.len() as u64 { -        let mut instr = Instruction::blank(); -        instr.decode_into(instruction_bytes[(i as usize)..].iter().map(|x| *x)); +        let instr = <ARMv8 as Arch>::Decoder::default().decode(instruction_bytes[(i as usize)..].iter().cloned()).unwrap();          println!(              "Decoded {:02x}{:02x}{:02x}{:02x}: {}", //{:?}\n  {}",              instruction_bytes[i as usize], @@ -2195,9 +2331,10 @@ pub fn bench_60000_instrs(b: &mut Bencher) {      b.iter(|| {          for i in (0..1000) {              let mut iter = instruction_bytes.iter().map(|x| *x); +            let decoder = <ARMv8 as Arch>::Decoder::default();              let mut result = Instruction::blank();              loop { -                match result.decode_into(&mut iter) { +                match decoder.decode_into(&mut result, &mut iter) {                      Some(result) => {                          test::black_box(&result);                      }, | 
