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/armv7/thumb.rs | |
parent | 72109c2385c7b0940072f31fc3bcbeed68006060 (diff) |
fill out more missing thumb2 decoder
Diffstat (limited to 'src/armv7/thumb.rs')
-rw-r--r-- | src/armv7/thumb.rs | 66 |
1 files changed, 65 insertions, 1 deletions
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); } |