aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG3
-rw-r--r--src/armv7/thumb.rs9
-rw-r--r--tests/armv7/thumb.rs17
3 files changed, 26 insertions, 3 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 19dd69b..60dd00d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,9 @@
behavior as "unpredictable", but capstone and others report this as a
post-index as the bits imply. yaxpeax will still reject this encoding if
configured to reject unpredictable instructions.
+* thumb2: fix ssat and ssat16's second operand being decoded off-by-one.
+ the field is 1-based rather than 0-based, so for example an instruction which
+ had that operand as "1" was incorrectly decoded as being "0"
* ARMv7: do not try to elide memory offset when 0 in postindex operands.
this makes a post-index (and implied writeback!) ambiguous with a pre-indexed
access with offset zero. that is, `[r1, 0]` may be written as `[r1]`, but
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index 077834a..dacf3dd 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -1452,7 +1452,8 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
inst.opcode = Opcode::SSAT;
inst.operands = [
Operand::Reg(Reg::from_u8(rd)),
- Operand::Imm32((lower & 0b11111) as u32),
+ // TODO: ssat r3, #0x3, r7, lsl #22 != ssat r3, #4, r7, lsl #0x16. bytes: [7, f3, 83, 53]
+ Operand::Imm32((lower & 0b11111) as u32 + 1),
Operand::RegShift(shift),
Operand::Nothing,
];
@@ -1466,7 +1467,8 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
inst.opcode = Opcode::SSAT;
inst.operands = [
Operand::Reg(Reg::from_u8(rd)),
- Operand::Imm32((lower & 0b11111) as u32),
+ // TODO: ssat r3, #0x3, r7, lsl #22 != ssat r3, #4, r7, lsl #0x16. bytes: [7, f3, 83, 53]
+ Operand::Imm32((lower & 0b11111) as u32 + 1),
Operand::RegShift(shift),
Operand::Nothing,
];
@@ -1476,7 +1478,8 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
inst.opcode = Opcode::SSAT16;
inst.operands = [
Operand::Reg(Reg::from_u8(rd)),
- Operand::Imm32((lower & 0b11111) as u32),
+ // TODO: testcase
+ Operand::Imm32((lower & 0b11111) as u32 + 1),
Operand::Reg(Reg::from_u8(rn)),
Operand::Nothing,
];
diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs
index b0eb262..00b5802 100644
--- a/tests/armv7/thumb.rs
+++ b/tests/armv7/thumb.rs
@@ -4695,6 +4695,23 @@ fn mrc_mcr_cdp() {
}
#[test]
+fn smml() {
+ // smmla, smmlar, smmls, smmlsr
+ test_display(
+ &[0x64, 0xfb, 0x1f, 0x92],
+ "smmlsr r2, r4, pc, sb"
+ );
+ test_display(
+ &[0x59, 0xfb, 0x1b, 0x66],
+ "smmlar r6, sb, fp, r6"
+ );
+ test_display(
+ &[0x20, 0xfb, 0x1d, 0xd1],
+ "smladx r1, r0, sp, sp"
+ );
+}
+
+#[test]
fn prefetch() {
test_display(
&[0xb0, 0xf8, 0x03, 0xfe],