aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-12-06 11:55:59 -0800
committeriximeow <me@iximeow.net>2020-12-06 12:00:11 -0800
commitbb39c8a890a0650f7762cd100418d735976b5c1e (patch)
treeb6cf46bd81a41c932d039d928d0723c39f435cf5 /src
parent72109c2385c7b0940072f31fc3bcbeed68006060 (diff)
fill out more missing thumb2 decoder
Diffstat (limited to 'src')
-rw-r--r--src/armv7.rs6
-rw-r--r--src/armv7/thumb.rs66
2 files changed, 71 insertions, 1 deletions
diff --git a/src/armv7.rs b/src/armv7.rs
index 73530fb..742d1db 100644
--- a/src/armv7.rs
+++ b/src/armv7.rs
@@ -453,6 +453,8 @@ impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::UBFX |
Opcode::BFI |
Opcode::BFC |
+ Opcode::RBIT |
+ Opcode::SEL |
Opcode::MOV |
Opcode::MOVT |
Opcode::MVN => { write!(out, "{}", colors.data_op(self)) },
@@ -663,6 +665,8 @@ impl Display for Opcode {
Opcode::DBG => { write!(f, "dbg") },
Opcode::PLD => { write!(f, "pld") },
Opcode::PLI => { write!(f, "pli") },
+ Opcode::RBIT => { write!(f, "rbit") },
+ Opcode::SEL => { write!(f, "sel") },
}
}
}
@@ -825,6 +829,8 @@ pub enum Opcode {
DBG,
PLD,
PLI,
+ RBIT,
+ SEL,
}
static DATA_PROCESSING_OPCODES: [Opcode; 16] = [
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index 6028e7b..3eac069 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -2882,7 +2882,71 @@ pub fn decode_into<T: IntoIterator<Item=u8>>(decoder: &InstDecoder, inst: &mut I
return Err(DecodeError::Incomplete);
} else if op2 < 0b1100 {
// `Miscellaneous operations` (`A6-246`)
- return Err(DecodeError::Incomplete);
+ let rn = instr2[0..4].load::<u8>();
+ let rd = lower2[8..12].load::<u8>();
+ let rm = lower2[0..4].load::<u8>();
+ let op1 = instr2[4..6].load::<u8>();
+ let op2 = lower2[4..6].load::<usize>();
+ match op1 {
+ 0b00 => {
+ inst.opcode = [
+ Opcode::QADD,
+ Opcode::QDADD,
+ Opcode::QSUB,
+ Opcode::QDSUB,
+ ][op2];
+ inst.operands = [
+ Operand::Reg(Reg::from_u8(rd)),
+ Operand::Reg(Reg::from_u8(rm)),
+ Operand::Reg(Reg::from_u8(rn)),
+ Operand::Nothing,
+ ];
+ }
+ 0b01 => {
+ if rn != rm {
+ decoder.unpredictable()?;
+ }
+ inst.opcode = [
+ Opcode::REV,
+ Opcode::REV16,
+ Opcode::RBIT,
+ Opcode::REVSH,
+ ][op2];
+ inst.operands = [
+ Operand::Reg(Reg::from_u8(rd)),
+ Operand::Reg(Reg::from_u8(rm)),
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
+ 0b10 => {
+ if op2 != 0 {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ inst.opcode = Opcode::SEL;
+ inst.operands = [
+ Operand::Reg(Reg::from_u8(rd)),
+ Operand::Reg(Reg::from_u8(rn)),
+ Operand::Reg(Reg::from_u8(rm)),
+ Operand::Nothing,
+ ];
+ }
+ 0b11 => {
+ if op2 != 0 {
+ return Err(DecodeError::InvalidOpcode);
+ }
+ inst.opcode = Opcode::CLZ;
+ inst.operands = [
+ Operand::Reg(Reg::from_u8(rd)),
+ Operand::Reg(Reg::from_u8(rm)),
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
+ _ => {
+ unreachable!("impossible bit pattern for op1");
+ }
+ }
} else {
return Err(DecodeError::Undefined);
}