aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-11-28 02:21:34 -0800
committeriximeow <me@iximeow.net>2020-01-12 17:29:01 -0800
commit179d5d9cb7e94851ba69bf67f6d2dfbafa6aa6fe (patch)
treeaf40c09afea071cf75aec2680e8ca7661267bce2
parenta2aaf35628135974a57dc2e09fb2d71eab2c35e5 (diff)
update arm to revised decoder trait
-rw-r--r--src/armv7.rs210
-rw-r--r--src/armv8/a64.rs997
-rw-r--r--test/armv7.rs14
-rw-r--r--test/armv8/a64.rs169
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);
},