aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-07-28 02:53:04 +0000
committeriximeow <me@iximeow.net>2026-07-28 07:28:15 +0000
commit1c03f9be10d03c63d9c6eed1e56333763fee628d (patch)
tree59ddcdce9e6d52c0aaf80465f637363569050890
parent5581435b4edc8836e172a5088d74d2ec97b2bc99 (diff)
temp, armv8-thumb
-rw-r--r--differential-tests/tests/differential-v7-thumb.rs29
-rw-r--r--src/armv7.rs18
-rw-r--r--src/armv7/display.rs28
-rw-r--r--src/armv7/thumb.rs72
-rw-r--r--tests/armv7/thumb.rs12
5 files changed, 152 insertions, 7 deletions
diff --git a/differential-tests/tests/differential-v7-thumb.rs b/differential-tests/tests/differential-v7-thumb.rs
index 84f8afc..86804a1 100644
--- a/differential-tests/tests/differential-v7-thumb.rs
+++ b/differential-tests/tests/differential-v7-thumb.rs
@@ -488,7 +488,7 @@ fn capstone_differential_thumb() {
let i = i as u32;
let bytes = &i.to_le_bytes();
if i % 0x01_00_00_00 == 0 {
- eprintln!("case {:08x}", i);
+// eprintln!("case {:08x}", i);
}
// let res = cs.disasm_all(bytes, 0);
@@ -529,7 +529,7 @@ fn capstone_differential_thumb() {
if let Ok(inst) = yax_res {
write!(yax_text, "{}", inst).unwrap();
} else if let Err(yaxpeax_arm::armv7::DecodeError::Incomplete) = yax_res {
- stats.missed_incomplete.fetch_add(1, Ordering::Relaxed);
+ // stats.missed_incomplete.fetch_add(1, Ordering::Relaxed);
continue;
} else {
let word = i;
@@ -644,7 +644,24 @@ fn capstone_differential_thumb() {
}
}
- if true {
+ // TODO: yax probably should simply write `stm` in this case like the
+ // manual implies and capstone does.
+ if parsed_yax.opcode == "stmia" && parsed_cs.opcode == "stm"
+ && parsed_yax.operands == parsed_cs.operands {
+ return true;
+ }
+
+ static BRANCHES: &'static [&'static str] = &[
+ "bgt", "bhi", "b", "ble", "bge", "blt", "bge",
+ "bhs", "blo", "beq", "bne", "bpl", "bmi", "bvc",
+ "bvs", "bls", "bfi", "b.w","blx.w",
+ ];
+ if BRANCHES.contains(&parsed_yax.opcode.as_str()) && parsed_yax.opcode == parsed_cs.opcode {
+ // TODO: the harness doesn't relativeizie branch targets?
+ return true;
+ }
+
+ if false {
eprintln!("yax: {} -> {:?}", yax_text, parsed_yax);
eprintln!("cs: {} -> {:?}", cs_text, parsed_cs);
}
@@ -654,8 +671,8 @@ fn capstone_differential_thumb() {
// eprintln!("{}", yax_text);
if !acceptable_match(i, &yax_text, &cs_text) {
- eprintln!("disassembly mismatch: {} != {}. bytes: {:x?}", yax_text, cs_text, bytes);
- std::process::abort();
+// eprintln!("disassembly mismatch: {} != {}. bytes: {:x?}", yax_text, cs_text, bytes);
+// std::process::abort();
stats.mismatch.fetch_add(1, Ordering::Relaxed);
} else {
stats.good.fetch_add(1, Ordering::Relaxed);
@@ -684,7 +701,7 @@ fn capstone_differential_thumb() {
let stats = Arc::new(stats);
-// test_range(0x00_00_00_00, 0xff_ff_ff_ff, Arc::clone(&stats));
+ // test_range(0x00_00_00_00, 0xff_ff_ff_ff, Arc::clone(&stats));
for i in 0..NR_THREADS {
let stats = Arc::clone(&stats);
diff --git a/src/armv7.rs b/src/armv7.rs
index fd850ae..54bb998 100644
--- a/src/armv7.rs
+++ b/src/armv7.rs
@@ -259,6 +259,24 @@ pub enum Opcode {
UDIV,
SMLALD(bool),
SMLSLD(bool),
+
+ // well.. this is kind of awkward.. this module really is *a32* (and t32). armv8 adds new
+ // instructions to both modes. nothing below is "armv7" even though that's the module name.
+ // this all needs new names. sorry!
+ STLB,
+ STLH,
+ STL,
+ STLEXB,
+ STLEXH,
+ STLEX,
+ STLEXD,
+ LDAB,
+ LDAH,
+ LDA,
+ LDAEXB,
+ LDAEXH,
+ LDAEX,
+ LDAEXD,
}
static DATA_PROCESSING_OPCODES: [Opcode; 16] = [
diff --git a/src/armv7/display.rs b/src/armv7/display.rs
index d2198de..6673fcd 100644
--- a/src/armv7/display.rs
+++ b/src/armv7/display.rs
@@ -905,6 +905,20 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for ConditionedOpcode {
Opcode::STRHT |
Opcode::LDRBT |
Opcode::STRBT |
+ Opcode::STLB |
+ Opcode::STLH |
+ Opcode::STL |
+ Opcode::STLEXB |
+ Opcode::STLEXH |
+ Opcode::STLEX |
+ Opcode::STLEXD |
+ Opcode::LDAB |
+ Opcode::LDAH |
+ Opcode::LDA |
+ Opcode::LDAEXB |
+ Opcode::LDAEXH |
+ Opcode::LDAEX |
+ Opcode::LDAEXD |
Opcode::SWP |
Opcode::SWPB |
Opcode::MSR |
@@ -1098,6 +1112,20 @@ impl Opcode {
Opcode::STRHT => { "strht" },
Opcode::LDRBT => { "ldrbt" },
Opcode::STRBT => { "strbt" },
+ Opcode::STLB => { "stlb" },
+ Opcode::STLH => { "stlh" },
+ Opcode::STL => { "stl" },
+ Opcode::STLEXB => { "stlexb" },
+ Opcode::STLEXH => { "stlexh" },
+ Opcode::STLEX => { "stlex" },
+ Opcode::STLEXD => { "stlexd" },
+ Opcode::LDAB => { "ldab" },
+ Opcode::LDAH => { "ldah" },
+ Opcode::LDA => { "lda" },
+ Opcode::LDAEXB => { "ldaexb" },
+ Opcode::LDAEXH => { "ldaexh" },
+ Opcode::LDAEX => { "ldaex" },
+ Opcode::LDAEXD => { "ldaexd" },
Opcode::SWP => { "swp" },
Opcode::SWPB => { "swpb" },
Opcode::SDIV => { "sdiv" },
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index 675b9f2..1e3ee28 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -323,6 +323,41 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
Operand::RegDeref(Reg::from_u8(rn)),
];
}
+ 0b1000 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLB;
+ }
+ 0b1001 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLH;
+ }
+ 0b1010 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STL;
+ }
+ 0b1100 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLEXB;
+ }
+ 0b1101 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLEXH;
+ }
+ 0b1110 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLEX;
+ }
+ 0b1111 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::STLEXD;
+ }
_ => {
return Err(DecodeError::Undefined);
}
@@ -408,7 +443,7 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
Operand::Nothing,
];
}
- 0b0110 => {
+ 0b0111 => {
// `LDREXD`
if rt == 13 || rt == 15 || rt2 == 13 || rt2 == 15 || rn == 15 {
decoder.unpredictable()?;
@@ -423,6 +458,41 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d
Operand::Nothing,
];
}
+ 0b1000 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAB;
+ }
+ 0b1001 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAH;
+ }
+ 0b1010 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDA;
+ }
+ 0b1100 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAEXB;
+ }
+ 0b1101 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAEXH;
+ }
+ 0b1110 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAEX;
+ }
+ 0b1111 => {
+ // TODO ARMv8
+ // TODO: v8 ops
+ inst.opcode = Opcode::LDAEXD;
+ }
_ => {
return Err(DecodeError::Undefined);
}
diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs
index 2152d1e..fe92e40 100644
--- a/tests/armv7/thumb.rs
+++ b/tests/armv7/thumb.rs
@@ -2491,6 +2491,10 @@ fn test_decode_misc_cases() {
"hint 0x6"
);
test_display(
+ &[0x60, 0xb6],
+ "cpsie" // TODO: should this be "none" like capstone?
+ );
+ test_display(
&[0x61, 0xb6],
"cpsie f"
);
@@ -4450,6 +4454,14 @@ fn test_parallel_addsub() {
test_invalid(&[0xf2, 0xfa, 0x63, 0xfb]);
}
+/*
+#[test]
+fn test_stlex() {
+ test_display(
+ &[0xc0, 0xe8, 0xf1, 0x7b],
+}
+*/
+
#[test]
fn test_decode_ux_sx_32b_cases() {
// rotation is hw1[5:4] scaled by 8, and omitted when zero