aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/armv7.rs70
-rw-r--r--src/armv7/thumb.rs193
-rw-r--r--test/armv7/thumb.rs557
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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u3
_ => { 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u3
Ok(())
}
+ Opcode::LDC(coproc) => {
+ 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 <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color
Opcode::HVC |
Opcode::SVC |
Opcode::SMC |
+ Opcode::LDC(_) |
+ Opcode::LDCL(_) |
Opcode::LDC2(_) |
Opcode::LDC2L(_) |
+ Opcode::STC(_) |
+ Opcode::STCL(_) |
Opcode::STC2(_) |
Opcode::STC2L(_) |
Opcode::MCRR2(_, _) |
Opcode::MCR2(_, _, _) |
Opcode::MRRC2(_, _) |
Opcode::MRC2(_, _, _) |
+ Opcode::MCRR(_, _) |
+ Opcode::MRRC(_, _) |
Opcode::CDP2(_, _, _) => { 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<T: IntoIterator<Item=u8>>(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<T: IntoIterator<Item=u8>>(decoder: &InstDecoder, inst: &mut I
} else {
// `Data-processing (plain binary immediate)` (`A6-232`)
// v6T2
+ // aka table `A6-12`
let op = instr2[4..9].load::<u8>();
let i = instr2[10..11].load::<u16>();
inst.s = false;
@@ -3028,7 +3031,6 @@ pub fn decode_into<T: IntoIterator<Item=u8>>(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::<usize>();
let op2 = lower2[4..8].load::<usize>();
@@ -3302,13 +3304,15 @@ pub fn decode_into<T: IntoIterator<Item=u8>>(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<T: IntoIterator<Item=u8>>(decoder: &InstDecoder, inst: &mut I
}
Ok(())
}
+
+fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: BitArray<Lsb0, [u16; 1]>, lower2: BitArray<Lsb0, [u16; 1]>) -> Result<(), DecodeError> {
+ // implementation of table `A6-30 Coprocessor, Advanced SIMD, and Floating-point instructions`
+ let op1 = instr2[4..10].load::<usize>();
+ 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::<u8>();
+ if coproc & 0b1110 != 0b1010 {
+ // `not 101x` rows
+ if op1 == 0b000100 {
+ // `MCRR, MCRR2 on page A8-479`
+ let crm = lower2[0..4].load::<u8>();
+ let opc1 = lower2[4..8].load::<u8>();
+ let rt = lower2[12..16].load::<u8>();
+ let rt2 = instr2[0..4].load::<u8>();
+ 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::<u8>();
+ let opc1 = lower2[4..8].load::<u8>();
+ let rt = lower2[12..16].load::<u8>();
+ let rt2 = instr2[0..4].load::<u8>();
+ // manual typo!! the manual spells the operands
+ // `<coproc>, <opc>, <Rt>, <Rt2>, <CRm>`
+ // 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::<u8>();
+ let crd = lower2[12..16].load::<u8>();
+ let imm8 = lower2[0..8].load::<u16>();
+
+ 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::<u8>();
+ let crd = lower2[12..16].load::<u8>();
+ let imm8 = lower2[0..8].load::<u16>();
+
+ 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"
+ );
+}