From 1572e928b41b5c0765d7f47b346110da14e58b9e Mon Sep 17 00:00:00 2001 From: iximeow Date: Sun, 6 Dec 2020 15:17:52 -0800 Subject: add ldc/sdc instructions and a slew of 32b thumb2 tests --- src/armv7.rs | 70 +++++++ src/armv7/thumb.rs | 193 +++++++++++++++++- test/armv7/thumb.rs | 557 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 815 insertions(+), 5 deletions(-) diff --git a/src/armv7.rs b/src/armv7.rs index 4cfbc77..d98cfb0 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -175,6 +175,32 @@ impl > ShowContextual { unreachable!(); } } }, + Opcode::STCL(coproc) => { + write!(out, "stcl p{}", coproc)?; + let ops = self.operands.iter(); + for op in ops { + if let Operand::Nothing = op { + break; + } + write!(out, ", ")?; + op.colorize(colors, out)?; + } + + Ok(()) + } + Opcode::STC(coproc) => { + write!(out, "stc p{}", coproc)?; + let ops = self.operands.iter(); + for op in ops { + if let Operand::Nothing = op { + break; + } + write!(out, ", ")?; + op.colorize(colors, out)?; + } + + Ok(()) + } Opcode::STC2L(coproc) => { write!(out, "stc2l p{}", coproc)?; let ops = self.operands.iter(); @@ -201,6 +227,32 @@ impl > ShowContextual { + write!(out, "ldc p{}", coproc)?; + let ops = self.operands.iter(); + for op in ops { + if let Operand::Nothing = op { + break; + } + write!(out, ", ")?; + op.colorize(colors, out)?; + } + + Ok(()) + } + Opcode::LDCL(coproc) => { + write!(out, "ldcl p{}", coproc)?; + let ops = self.operands.iter(); + for op in ops { + if let Operand::Nothing = op { + break; + } + write!(out, ", ")?; + op.colorize(colors, out)?; + } + + Ok(()) + } Opcode::LDC2(coproc) => { write!(out, "ldc2 p{}", coproc)?; let ops = self.operands.iter(); @@ -535,14 +587,20 @@ impl > Colorize { write!(out, "{}", colors.platform_op(self)) }, } } @@ -557,14 +615,20 @@ impl Display for Opcode { Opcode::LDRSBT => { write!(f, "ldrsbt") }, Opcode::STRD => { write!(f, "strd") }, Opcode::LDRD => { write!(f, "ldrd") }, + Opcode::LDC(_) => { write!(f, "ldc") }, + Opcode::LDCL(_) => { write!(f, "ldcl") }, Opcode::LDC2(_) => { write!(f, "ldc2") }, Opcode::LDC2L(_) => { write!(f, "ldc2l") }, + Opcode::STC(_) => { write!(f, "stc") }, + Opcode::STCL(_) => { write!(f, "stcl") }, Opcode::STC2(_) => { write!(f, "stc2") }, Opcode::STC2L(_) => { write!(f, "stc2l") }, Opcode::MCRR2(_, _) => { write!(f, "mcrr2") }, Opcode::MCR2(_, _, _) => { write!(f, "mcr2") }, Opcode::MRRC2(_, _) => { write!(f, "mrrc2") }, Opcode::MRC2(_, _, _) => { write!(f, "mrc2") }, + Opcode::MCRR(_, _) => { write!(f, "mcrr") }, + Opcode::MRRC(_, _) => { write!(f, "mrrc") }, Opcode::CDP2(_, _, _) => { write!(f, "cdp2") }, Opcode::SRS(p, u) => { write!(f, "srs{}{}", if *u { "i" } else { "d" }, if *p { "b" } else { "a" }) }, Opcode::RFE(p, u) => { write!(f, "rfe{}{}", if *u { "i" } else { "d" }, if *p { "b" } else { "a" }) }, @@ -842,13 +906,19 @@ pub enum Opcode { LDRSBT, STRD, LDRD, + LDC(u8), + LDCL(u8), LDC2(u8), LDC2L(u8), + STC(u8), + STCL(u8), STC2(u8), STC2L(u8), MCRR2(u8, u8), MCR2(u8, u8, u8), MRRC2(u8, u8), + MCRR(u8, u8), + MRRC(u8, u8), MRC2(u8, u8, u8), CDP2(u8, u8, u8), SRS(bool, bool), diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 2743c13..ab28be8 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -4,6 +4,7 @@ use std::fmt; use armv7::ConditionCode; use armv7::DecodeError; +use armv7::CReg; use armv7::Reg; use armv7::RegShift; use armv7::Operand; @@ -1025,8 +1026,9 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I } else { // `Coprocessor, Advanced SIMD, and Floating-point instructions` (`A6-249`) // v6T2 - eprintln!("TODO: coproc/simd/fp"); - return Err(DecodeError::Incomplete); + // op1 == 01, op2 == 1xxxxxx + // this means `assert!(instr2[10])` + return decode_table_a6_30(decoder, inst, instr2, lower2); } } else if opword < 0b11111 { // op1 == 0b10 @@ -1253,6 +1255,7 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I } else { // `Data-processing (plain binary immediate)` (`A6-232`) // v6T2 + // aka table `A6-12` let op = instr2[4..9].load::(); let i = instr2[10..11].load::(); inst.s = false; @@ -3028,7 +3031,6 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I } else { if op2[3] { // `Long multiply, long multiply accumulate, and divide` (`A6-248`) - return Err(DecodeError::Incomplete); let op1 = instr2[4..7].load::(); let op2 = lower2[4..8].load::(); @@ -3302,13 +3304,15 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I } } - return Err(DecodeError::Incomplete); } } } } else { // `Coprocessor, Advanced SIMD, and Floating-point instructions` (`A6-249`) - return Err(DecodeError::Incomplete); + // v6T2 + // op1 == 11, op2 == 1xxxxxx + // this means `assert!(instr2[10])` + return decode_table_a6_30(decoder, inst, instr2, lower2); } } } else { @@ -4180,3 +4184,182 @@ pub fn decode_into>(decoder: &InstDecoder, inst: &mut I } Ok(()) } + +fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: BitArray, lower2: BitArray) -> Result<(), DecodeError> { + // implementation of table `A6-30 Coprocessor, Advanced SIMD, and Floating-point instructions` + let op1 = instr2[4..10].load::(); + if op1 & 0b11_1110 == 0b00_0000 { + inst.opcode = Opcode::UDF; + inst.operands = [ + Operand::Nothing, + Operand::Nothing, + Operand::Nothing, + Operand::Nothing, + ]; + return Err(DecodeError::InvalidOpcode); + } else if op1 & 0b110000 == 0b110000 { + // TODO: `Advanced SIMD data-processing instructions on A7-259` + return Err(DecodeError::Incomplete); + } else { + let coproc = lower2[8..12].load::(); + if coproc & 0b1110 != 0b1010 { + // `not 101x` rows + if op1 == 0b000100 { + // `MCRR, MCRR2 on page A8-479` + let crm = lower2[0..4].load::(); + let opc1 = lower2[4..8].load::(); + let rt = lower2[12..16].load::(); + let rt2 = instr2[0..4].load::(); + if instr2[12] { + inst.opcode = Opcode::MCRR2(coproc, opc1); + } else { + inst.opcode = Opcode::MCRR(coproc, opc1); + } + inst.operands = [ + Operand::Reg(Reg::from_u8(rt)), + Operand::Reg(Reg::from_u8(rt2)), + Operand::CReg(CReg::from_u8(crm)), + Operand::Nothing, + ]; + } else if op1 == 0b000101 { + // `MRRC, MRRC2 on page A8-495` + let crm = lower2[0..4].load::(); + let opc1 = lower2[4..8].load::(); + let rt = lower2[12..16].load::(); + let rt2 = instr2[0..4].load::(); + // manual typo!! the manual spells the operands + // `, , , , ` + // but the operand name is `opc1`! + // + // this is a very uninteresting typo, but fun to spot nonetheless + if instr2[12] { + inst.opcode = Opcode::MRRC2(coproc, opc1); + } else { + inst.opcode = Opcode::MRRC(coproc, opc1); + } + inst.operands = [ + Operand::Reg(Reg::from_u8(rt)), + Operand::Reg(Reg::from_u8(rt2)), + Operand::CReg(CReg::from_u8(crm)), + Operand::Nothing, + ]; + } else { + if op1 & 1 == 0 { + // `STC, STC2 on page A8-663` + let p = instr2[8]; + let u = instr2[7]; + let w = instr2[5]; + let rn = instr2[0..4].load::(); + let crd = lower2[12..16].load::(); + let imm8 = lower2[0..8].load::(); + + if instr2[12] { + if instr2[6] { + inst.opcode = Opcode::STC2L(coproc); + } else { + inst.opcode = Opcode::STC2(coproc); + } + } else { + if instr2[6] { + inst.opcode = Opcode::STCL(coproc); + } else { + inst.opcode = Opcode::STC(coproc); + } + } + inst.operands = [ + Operand::CReg(CReg::from_u8(crd)), + if p { + Operand::RegDerefPreindexOffset( + Reg::from_u8(rn), + imm8 << 2, + u, + w, + ) + } else { + if w { + Operand::RegDerefPostindexOffset( + Reg::from_u8(rn), + imm8 << 2, + u, + false, // TODO: wback? this is true? not true? + ) + } else { + Operand::RegDeref(Reg::from_u8(rn)) + } + }, + if !p && !w { + Operand::CoprocOption(imm8 as u8) + } else { + Operand::Nothing + }, + Operand::Nothing, + ]; + } else { + // `LDC, LDC2 (immediate or literal) on A8-393 or A8-395` + let p = instr2[8]; + let u = instr2[7]; + let w = instr2[5]; + let rn = instr2[0..4].load::(); + let crd = lower2[12..16].load::(); + let imm8 = lower2[0..8].load::(); + + if rn == 0b1111 { + // `LDC, LDC2 (literal) on A8-395` + // notable for rejecting writeback + if w { + decoder.unpredictable()?; + } + } else { + // `LDC, LDC2 (immediate) on A8-393` + } + + if instr2[12] { + if instr2[6] { + inst.opcode = Opcode::LDC2L(coproc); + } else { + inst.opcode = Opcode::LDC2(coproc); + } + } else { + if instr2[6] { + inst.opcode = Opcode::LDCL(coproc); + } else { + inst.opcode = Opcode::LDC(coproc); + } + } + inst.operands = [ + Operand::CReg(CReg::from_u8(crd)), + if p { + Operand::RegDerefPreindexOffset( + Reg::from_u8(rn), + imm8 << 2, + u, + w, + ) + } else { + if w { + Operand::RegDerefPostindexOffset( + Reg::from_u8(rn), + imm8 << 2, + u, + false, // TODO: wback? this is true? not true? + ) + } else { + Operand::RegDeref(Reg::from_u8(rn)) + } + }, + if !p && !w { + Operand::CoprocOption(imm8 as u8) + } else { + Operand::Nothing + }, + Operand::Nothing, + ]; + } + } + } else { + // `101x` rows + return Err(DecodeError::Incomplete); + } + } + Ok(()) +} diff --git a/test/armv7/thumb.rs b/test/armv7/thumb.rs index f61e94d..7ab89fb 100644 --- a/test/armv7/thumb.rs +++ b/test/armv7/thumb.rs @@ -3394,3 +3394,560 @@ fn test_decode_ux_sx_cases() { "uxtb r2, r1" ); } + +#[test] +fn test_decode_ldr_32b_cases() { + test_display( + &[0x73, 0xe8, 0x7e, 0x5a], + "ldrd r5, r10, [r3], -0x1f8" + ); + test_display( + &[0x93, 0xf8, 0x7e, 0x5a], + "ldrb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xb3, 0xf8, 0x7e, 0x5a], + "ldrh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xd3, 0xf8, 0x7e, 0x5a], + "ldr.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xf3, 0xe8, 0x7e, 0x5a], + "ldrd r5, r10, [r3], 0x1f8" + ); + test_display( + &[0x53, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, -0x1f8]" + ); + test_display( + &[0x73, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, -0x1f8]!" + ); + test_display( + &[0x93, 0xf9, 0x7e, 0x5a], + "ldrsb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xb3, 0xf9, 0x7e, 0x5a], + "ldrsh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xd3, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, 0x1f8]" + ); + test_display( + &[0xf3, 0xe9, 0x7e, 0x5a], + "ldrd r5, r10, [r3, 0x1f8]!" + ); +} + +#[test] +fn test_decode_coproc_ld_32b_cases() { + test_display( + &[0x33, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x73, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x93, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xb3, 0xfc, 0x7e, 0x54], + "ldc2 p4, c5, [r3], 0x1f8" + ); + test_display( + &[0xd3, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xf3, 0xfc, 0x7e, 0x54], + "ldc2l p4, c5, [r3], 0x1f8" + ); + test_display( + &[0x13, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x33, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x53, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x73, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x93, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xb3, 0xfd, 0x7e, 0x54], + "ldc2 p4, c5, [r3, 0x1f8]!" + ); + test_display( + &[0xd3, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xf3, 0xfd, 0x7e, 0x54], + "ldc2l p4, c5, [r3, 0x1f8]!" + ); +} +#[test] +fn test_decode_str_32b_cases() { + test_display( + &[0x43, 0xe8, 0x7e, 0x5a], + "strex r10, r5, [r3, 0x1f8]" + ); + test_display( + &[0x63, 0xe8, 0x7e, 0x5a], + "strd r5, r10, [r3], -0x1f8" + ); + test_display( + &[0x83, 0xf8, 0x7e, 0x5a], + "strb.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xa3, 0xf8, 0x7e, 0x5a], + "strh.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xc3, 0xe8, 0x7e, 0x5a], + "strexd lr, r5, r10, [r3]" + ); + test_display( + &[0xc3, 0xf8, 0x7e, 0x5a], + "str.w r5, [r3, 0xa7e]" + ); + test_display( + &[0xe3, 0xe8, 0x7e, 0x5a], + "strd r5, r10, [r3], 0x1f8" + ); + test_display( + &[0x43, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, -0x1f8]" + ); + test_display( + &[0x63, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, -0x1f8]!" + ); + test_display( + &[0xc3, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, 0x1f8]" + ); + test_display( + &[0xe3, 0xe9, 0x7e, 0x5a], + "strd r5, r10, [r3, 0x1f8]!" + ); +} + +#[test] +fn test_decode_coproc_st_32b_cases() { + test_display( + &[0x23, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x63, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], -0x1f8" + ); + test_display( + &[0x83, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xa3, 0xfc, 0x7e, 0x54], + "stc2 p4, c5, [r3], 0x1f8" + ); + test_display( + &[0xc3, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], {0x7e}" + ); + test_display( + &[0xe3, 0xfc, 0x7e, 0x54], + "stc2l p4, c5, [r3], 0x1f8" + ); + test_display( + &[0x03, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x23, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x43, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, -0x1f8]" + ); + test_display( + &[0x63, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, -0x1f8]!" + ); + test_display( + &[0x83, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xa3, 0xfd, 0x7e, 0x54], + "stc2 p4, c5, [r3, 0x1f8]!" + ); + test_display( + &[0xc3, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, 0x1f8]" + ); + test_display( + &[0xe3, 0xfd, 0x7e, 0x54], + "stc2l p4, c5, [r3, 0x1f8]!" + ); +} +#[test] +fn test_decode_stm_ldm_32b_cases() { + test_display( + &[0x83, 0xe8, 0x7e, 0x5a], + "stm.w r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0xa3, 0xe8, 0x7e, 0x5a], + "stm.w r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x03, 0xe9, 0x7e, 0x5a], + "stmdb r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x23, 0xe9, 0x7e, 0x5a], + "stmdb r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + + test_display( + &[0x93, 0xe8, 0x7e, 0x5a], + "ldm.w r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0xb3, 0xe8, 0x7e, 0x5a], + "ldm.w r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x13, 0xe9, 0x7e, 0x5a], + "ldmdb r3, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); + test_display( + &[0x33, 0xe9, 0x7e, 0x5a], + "ldmdb r3!, {r1, r2, r3, r4, r5, r6, sb, fp, ip, lr}" + ); +} +#[test] +fn test_decode_sat_ext_32b_cases() { + test_display( + &[0x43, 0xf3, 0x7e, 0x5a], + "sbfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0xc3, 0xf3, 0x7e, 0x5a], + "ubfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0x43, 0xf7, 0x7e, 0x5a], + "sbfx r10, r3, 0x15, 0x1f" + ); + test_display( + &[0xc3, 0xf7, 0x7e, 0x5a], + "ubfx r10, r3, 0x15, 0x1f" + ); + + test_display( + &[0x83, 0xf3, 0x7e, 0x5a], + "usat r10, 0x1e, r3, lsl 21" + ); + test_display( + &[0xa3, 0xf3, 0x7e, 0x5a], + "usat r10, 0x1e, r3, asr 21" + ); + test_display( + &[0x83, 0xf7, 0x7e, 0x5a], + "usat r10, 0x1e, r3, lsl 21" + ); + test_display( + &[0xa3, 0xf7, 0x7e, 0x5a], + "usat r10, 0x1e, r3, asr 21" + ); +} +#[test] +fn test_decode_bitwise_32b_cases() { + test_display( + &[0x23, 0xf0, 0x7e, 0x5a], + "bic r10, r3, 0x3f800000" + ); + test_display( + &[0x33, 0xf0, 0x7e, 0x5a], + "bics r10, r3, 0x3f800000" + ); + test_display( + &[0x23, 0xea, 0x7e, 0x5a], + "bic.w r10, r3, lr, ror 21" + ); + test_display( + &[0x33, 0xea, 0x7e, 0x5a], + "bics.w r10, r3, lr, ror 21" + ); + test_display( + &[0x23, 0xf4, 0x7e, 0x5a], + "bic r10, r3, 0x3f80" + ); + test_display( + &[0x33, 0xf4, 0x7e, 0x5a], + "bics r10, r3, 0x3f80" + ); + + test_display( + &[0x03, 0xf0, 0x7e, 0x5a], + "and r10, r3, 0x3f800000" + ); + test_display( + &[0x13, 0xf0, 0x7e, 0x5a], + "ands r10, r3, 0x3f800000" + ); + test_display( + &[0x03, 0xea, 0x7e, 0x5a], + "and.w r10, r3, lr, ror 21" + ); + test_display( + &[0x13, 0xea, 0x7e, 0x5a], + "ands.w r10, r3, lr, ror 21" + ); + test_display( + &[0x03, 0xf4, 0x7e, 0x5a], + "and r10, r3, 0x3f80" + ); + test_display( + &[0x13, 0xf4, 0x7e, 0x5a], + "ands r10, r3, 0x3f80" + ); + + test_display( + &[0x43, 0xf0, 0x7e, 0x5a], + "orr r10, r3, 0x3f800000" + ); + test_display( + &[0x53, 0xf0, 0x7e, 0x5a], + "orrs r10, r3, 0x3f800000" + ); + test_display( + &[0x43, 0xea, 0x7e, 0x5a], + "orr.w r10, r3, lr, ror 21" + ); + test_display( + &[0x53, 0xea, 0x7e, 0x5a], + "orrs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x43, 0xf4, 0x7e, 0x5a], + "orr r10, r3, 0x3f80" + ); + test_display( + &[0x53, 0xf4, 0x7e, 0x5a], + "orrs r10, r3, 0x3f80" + ); + + test_display( + &[0x83, 0xf0, 0x7e, 0x5a], + "eor r10, r3, 0x3f800000" + ); + test_display( + &[0x93, 0xf0, 0x7e, 0x5a], + "eors r10, r3, 0x3f800000" + ); + test_display( + &[0x83, 0xea, 0x7e, 0x5a], + "eor.w r10, r3, lr, ror 21" + ); + test_display( + &[0x93, 0xea, 0x7e, 0x5a], + "eors.w r10, r3, lr, ror 21" + ); + test_display( + &[0x83, 0xf4, 0x7e, 0x5a], + "eor r10, r3, 0x3f80" + ); + test_display( + &[0x93, 0xf4, 0x7e, 0x5a], + "eors r10, r3, 0x3f80" + ); + + test_display( + &[0x63, 0xf0, 0x7e, 0x5a], + "orn r10, r3, 0x3f800000" + ); + test_display( + &[0x73, 0xf0, 0x7e, 0x5a], + "orns r10, r3, 0x3f800000" + ); + test_display( + &[0x63, 0xea, 0x7e, 0x5a], + "orn r10, r3, lr, ror 21" + ); + test_display( + &[0x73, 0xea, 0x7e, 0x5a], + "orns r10, r3, lr, ror 21" + ); + test_display( + &[0x63, 0xf4, 0x7e, 0x5a], + "orn r10, r3, 0x3f80" + ); + test_display( + &[0x73, 0xf4, 0x7e, 0x5a], + "orns r10, r3, 0x3f80" + ); +} +#[test] +fn test_decode_arithmetic_32b_cases() { + test_display( + &[0xa3, 0xf1, 0x7e, 0x5a], + "sub.w r10, r3, 0x3f800000" + ); + test_display( + &[0xb3, 0xf1, 0x7e, 0x5a], + "subs.w r10, r3, 0x3f800000" + ); + test_display( + &[0xa3, 0xf2, 0x7e, 0x5a], + "sub.w r10, r3, 0x57e" + ); + test_display( + &[0xa3, 0xeb, 0x7e, 0x5a], + "sub.w r10, r3, lr, ror 21" + ); + test_display( + &[0xb3, 0xeb, 0x7e, 0x5a], + "subs.w r10, r3, lr, ror 21" + ); + test_display( + &[0xa3, 0xf6, 0x7e, 0x5a], + "sub.w r10, r3, 0xd7e" + ); + test_display( + &[0xa3, 0xf5, 0x7e, 0x5a], + "sub.w r10, r3, 0x3f80" + ); + test_display( + &[0xb3, 0xf5, 0x7e, 0x5a], + "subs.w r10, r3, 0x3f80" + ); + + test_display( + &[0x03, 0xf1, 0x7e, 0x5a], + "add.w r10, r3, 0x3f800000" + ); + test_display( + &[0x13, 0xf1, 0x7e, 0x5a], + "adds.w r10, r3, 0x3f800000" + ); + test_display( + &[0x03, 0xf2, 0x7e, 0x5a], + "add.w r10, r3, 0x57e" + ); + test_display( + &[0x03, 0xeb, 0x7e, 0x5a], + "add.w r10, r3, lr, ror 21" + ); + test_display( + &[0x13, 0xeb, 0x7e, 0x5a], + "adds.w r10, r3, lr, ror 21" + ); + test_display( + &[0x03, 0xf5, 0x7e, 0x5a], + "add.w r10, r3, 0x3f80" + ); + test_display( + &[0x13, 0xf5, 0x7e, 0x5a], + "adds.w r10, r3, 0x3f80" + ); + test_display( + &[0x03, 0xf6, 0x7e, 0x5a], + "add.w r10, r3, 0xd7e" + ); + + test_display( + &[0x43, 0xf1, 0x7e, 0x5a], + "adc r10, r3, 0x3f800000" + ); + test_display( + &[0x53, 0xf1, 0x7e, 0x5a], + "adcs r10, r3, 0x3f800000" + ); + test_display( + &[0x43, 0xeb, 0x7e, 0x5a], + "adc.w r10, r3, lr, ror 21" + ); + test_display( + &[0x53, 0xeb, 0x7e, 0x5a], + "adcs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x43, 0xf5, 0x7e, 0x5a], + "adc r10, r3, 0x3f80" + ); + test_display( + &[0x53, 0xf5, 0x7e, 0x5a], + "adcs r10, r3, 0x3f80" + ); + + test_display( + &[0x63, 0xf1, 0x7e, 0x5a], + "sbc r10, r3, 0x3f800000" + ); + test_display( + &[0x73, 0xf1, 0x7e, 0x5a], + "sbcs r10, r3, 0x3f800000" + ); + test_display( + &[0x63, 0xeb, 0x7e, 0x5a], + "sbc.w r10, r3, lr, ror 21" + ); + test_display( + &[0x73, 0xeb, 0x7e, 0x5a], + "sbcs.w r10, r3, lr, ror 21" + ); + test_display( + &[0x63, 0xf5, 0x7e, 0x5a], + "sbc r10, r3, 0x3f80" + ); + test_display( + &[0x73, 0xf5, 0x7e, 0x5a], + "sbcs r10, r3, 0x3f80" + ); + + test_display( + &[0xc3, 0xf1, 0x7e, 0x5a], + "rsb.w r10, r3, 0x3f800000" + ); + test_display( + &[0xd3, 0xf1, 0x7e, 0x5a], + "rsbs.w r10, r3, 0x3f800000" + ); + test_display( + &[0xc3, 0xeb, 0x7e, 0x5a], + "rsb r10, r3, lr, ror 21" + ); + test_display( + &[0xd3, 0xeb, 0x7e, 0x5a], + "rsbs r10, r3, lr, ror 21" + ); + test_display( + &[0xc3, 0xf5, 0x7e, 0x5a], + "rsb.w r10, r3, 0x3f80" + ); + test_display( + &[0xd3, 0xf5, 0x7e, 0x5a], + "rsbs.w r10, r3, 0x3f80" + ); +} -- cgit v1.1