diff options
author | iximeow <me@iximeow.net> | 2020-12-06 11:55:59 -0800 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-12-06 12:00:11 -0800 |
commit | bb39c8a890a0650f7762cd100418d735976b5c1e (patch) | |
tree | b6cf46bd81a41c932d039d928d0723c39f435cf5 /src | |
parent | 72109c2385c7b0940072f31fc3bcbeed68006060 (diff) |
fill out more missing thumb2 decoder
Diffstat (limited to 'src')
-rw-r--r-- | src/armv7.rs | 6 | ||||
-rw-r--r-- | src/armv7/thumb.rs | 66 |
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); } |