diff options
Diffstat (limited to 'src/armv7')
-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); } |