From cf7c141256337dc12f19e98d34efa3aa606af368 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 6 Dec 2020 12:18:20 -0800 Subject: thumb parallel addition and subtraction --- src/armv7.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/armv7/thumb.rs | 78 ++++++++++++++++++++++++++++++++++++- 2 files changed, 186 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/armv7.rs b/src/armv7.rs index 742d1db..be4f0d6 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -365,6 +365,43 @@ impl > Colorize { write!(f, "pli") }, Opcode::RBIT => { write!(f, "rbit") }, Opcode::SEL => { write!(f, "sel") }, + Opcode::SADD16 => { write!(f, "sadd16") }, + Opcode::QADD16 => { write!(f, "qadd16") }, + Opcode::SHADD16 => { write!(f, "shadd16") }, + Opcode::SASX => { write!(f, "sasx") }, + Opcode::QASX => { write!(f, "qasx") }, + Opcode::SHASX => { write!(f, "shasx") }, + Opcode::SSAX => { write!(f, "ssax") }, + Opcode::QSAX => { write!(f, "qsax") }, + Opcode::SHSAX => { write!(f, "shsax") }, + Opcode::SSUB16 => { write!(f, "ssub16") }, + Opcode::QSUB16 => { write!(f, "qsub16") }, + Opcode::SHSUB16 => { write!(f, "shsub16") }, + Opcode::SADD8 => { write!(f, "sadd8") }, + Opcode::QADD8 => { write!(f, "qadd8") }, + Opcode::SHADD8 => { write!(f, "shadd8") }, + Opcode::SSUB8 => { write!(f, "ssub8") }, + Opcode::QSUB8 => { write!(f, "qsub8") }, + Opcode::SHSUB8 => { write!(f, "shsub8") }, + Opcode::UADD16 => { write!(f, "uadd16") }, + Opcode::UQADD16 => { write!(f, "uqadd16") }, + Opcode::UHADD16 => { write!(f, "uhadd16") }, + Opcode::UASX => { write!(f, "uasx") }, + Opcode::UQASX => { write!(f, "uqasx") }, + Opcode::UHASX => { write!(f, "uhasx") }, + Opcode::USAX => { write!(f, "usax") }, + Opcode::UQSAX => { write!(f, "uqsax") }, + Opcode::UHSAX => { write!(f, "uhsax") }, + Opcode::USUB16 => { write!(f, "usub16") }, + Opcode::UQSUB16 => { write!(f, "uqsub16") }, + Opcode::UHSUB16 => { write!(f, "uhsub16") }, + Opcode::UADD8 => { write!(f, "uadd8") }, + Opcode::UQADD8 => { write!(f, "uqadd8") }, + Opcode::UHADD8 => { write!(f, "uhadd8") }, + Opcode::USUB8 => { write!(f, "usub8") }, + Opcode::UQSUB8 => { write!(f, "uqsub8") }, + Opcode::UHSUB8 => { write!(f, "uhsub8") }, } } } @@ -831,6 +904,43 @@ pub enum Opcode { PLI, RBIT, SEL, + + SADD16, + QADD16, + SHADD16, + SASX, + QASX, + SHASX, + SSAX, + QSAX, + SHSAX, + SSUB16, + QSUB16, + SHSUB16, + SADD8, + QADD8, + SHADD8, + SSUB8, + QSUB8, + SHSUB8, + UADD16, + UQADD16, + UHADD16, + UASX, + UQASX, + UHASX, + USAX, + UQSAX, + UHSAX, + USUB16, + UQSUB16, + UHSUB16, + UADD8, + UQADD8, + UHADD8, + USUB8, + UQSUB8, + UHSUB8, } static DATA_PROCESSING_OPCODES: [Opcode; 16] = [ diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 3eac069..e65fe05 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -2876,10 +2876,84 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I let op2 = op2.load::(); if op2 < 0b0100 { // `Parallel addition and subtraction, signed` - return Err(DecodeError::Incomplete); + let op1 = instr2[4..7].load::(); + let op2 = lower2[4..6].load::(); + if op1 == 0 || op1 > 0b100 || op2 == 0b11 { + return Err(DecodeError::InvalidOpcode); + } + + let opcode_idx = (op1 - 1) * 3 + op2; + + let rn = instr2[0..4].load::(); + let rd = lower2[8..12].load::(); + let rm = lower2[0..4].load::(); + + inst.opcode = [ + Opcode::SADD16, + Opcode::QADD16, + Opcode::SHADD16, + Opcode::SASX, + Opcode::QASX, + Opcode::SHASX, + Opcode::SSAX, + Opcode::QSAX, + Opcode::SHSAX, + Opcode::SSUB16, + Opcode::QSUB16, + Opcode::SHSUB16, + Opcode::SADD8, + Opcode::QADD8, + Opcode::SHADD8, + Opcode::SSUB8, + Opcode::QSUB8, + Opcode::SHSUB8, + ][opcode_idx]; + inst.operands = [ + Operand::Reg(Reg::from_u8(rd)), + Operand::Reg(Reg::from_u8(rn)), + Operand::Reg(Reg::from_u8(rm)), + Operand::Nothing, + ]; } else if op2 < 0b1000 { // `Parallel addition and subtraction, unsigned` (`A6-244`) - return Err(DecodeError::Incomplete); + let op1 = instr2[4..7].load::(); + let op2 = lower2[4..6].load::(); + if op1 > 0b100 || op2 == 0b11 { + return Err(DecodeError::InvalidOpcode); + } + + let opcode_idx = (op1 - 1) * 3 + op2; + + let rn = instr2[0..4].load::(); + let rd = lower2[8..12].load::(); + let rm = lower2[0..4].load::(); + + inst.opcode = [ + Opcode::UADD16, + Opcode::UQADD16, + Opcode::UHADD16, + Opcode::UASX, + Opcode::UQASX, + Opcode::UHASX, + Opcode::USAX, + Opcode::UQSAX, + Opcode::UHSAX, + Opcode::USUB16, + Opcode::UQSUB16, + Opcode::UHSUB16, + Opcode::UADD8, + Opcode::UQADD8, + Opcode::UHADD8, + Opcode::USUB8, + Opcode::UQSUB8, + Opcode::UHSUB8, + ][opcode_idx]; + inst.operands = [ + Operand::Reg(Reg::from_u8(rd)), + Operand::Reg(Reg::from_u8(rn)), + Operand::Reg(Reg::from_u8(rm)), + Operand::Nothing, + ]; } else if op2 < 0b1100 { // `Miscellaneous operations` (`A6-246`) let rn = instr2[0..4].load::(); -- cgit v1.1