aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--src/armv7/thumb.rs7
-rw-r--r--tests/armv7/thumb.rs37
3 files changed, 41 insertions, 4 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 5de5ee7..c2cc889 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -30,6 +30,7 @@ as well as thumb2 fixes from @brandonros:
* mvn (immediate) was decoded as mov,
* sxtab was decoded as sxtah,
* lsl, lsr, asr, ror were determining opcode from an incorrect bitfield,
+ * tbh was decoded as an shifted tbb,
* thumb2: (un)signed extend-and-rotate loaded an incorrect field for rotate,
thank you for the patches!
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index e9427d1..7aa3a5d 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -357,15 +357,14 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
// TODO: should_is_must()
// rt == 0b1111
// rd == 0b0000
- inst.opcode = Opcode::TBB;
+ inst.opcode = Opcode::TBH;
inst.operands = [
Operand::RegDerefPreindexRegShift(
Reg::from_u8(rn),
// want `<Rm>, LSL #1`, construct a raw shift
- // ourselves
+ // ourselves. bit 4 clear selects `RegImm`.
RegShift::from_raw(
- 0b10000 | // `RegImm`
- rd as u16 | // reg == rd
+ rd as u16 | // reg == rm
(0b00 << 5) | // LSL
(1 << 7) // shift == #1
),
diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs
index 8c1885d..6384af7 100644
--- a/tests/armv7/thumb.rs
+++ b/tests/armv7/thumb.rs
@@ -4325,3 +4325,40 @@ fn test_decode_shift_reg_32b_cases() {
"ror.w r1, r2, r3"
);
}
+
+#[test]
+fn test_decode_tbb_tbh_cases() {
+ test_display(
+ &[0xdf, 0xe8, 0x13, 0xf0],
+ "tbh [pc, r3, lsl 1]"
+ );
+ test_display(
+ &[0xdf, 0xe8, 0x0b, 0xf0],
+ "tbb [pc, fp]"
+ );
+}
+
+#[test]
+fn test_decode_tbh_operand_shape() {
+ use yaxpeax_arm::armv7::{Opcode, Operand, RegShiftStyle, ShiftStyle};
+
+ let mut reader = yaxpeax_arch::U8Reader::new(&[0xdf, 0xe8, 0x13, 0xf0][..]);
+ let inst = InstDecoder::default_thumb().decode(&mut reader).unwrap();
+ assert_eq!(inst.opcode, Opcode::TBH);
+ match inst.operands[0] {
+ Operand::RegDerefPreindexRegShift(base, shift, add, wback) => {
+ assert_eq!(base.number(), 15);
+ assert!(add);
+ assert!(!wback);
+ match shift.into_shift() {
+ RegShiftStyle::RegImm(s) => {
+ assert_eq!(s.shiftee().number(), 3);
+ assert_eq!(s.stype(), ShiftStyle::LSL);
+ assert_eq!(s.imm(), 1);
+ }
+ RegShiftStyle::RegReg(_) => panic!("TBH index must be a register+immediate shift"),
+ }
+ }
+ other => panic!("unexpected TBH operand: {:?}", other),
+ }
+}