aboutsummaryrefslogtreecommitdiff
path: root/differential-tests/tests
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2025-10-19 20:50:09 +0000
committeriximeow <me@iximeow.net>2025-10-19 23:29:05 +0000
commit153b5b3383d016a8a1440b2b932815efed25f847 (patch)
treedd861216ad571e479b74a8bb48cab0c35c091592 /differential-tests/tests
parentd1fefcc4461363b30f69b3cab386254c77de08e0 (diff)
tag instruction decode fixes, differential test precision
Diffstat (limited to 'differential-tests/tests')
-rw-r--r--differential-tests/tests/capstone-differential.rs73
1 files changed, 59 insertions, 14 deletions
diff --git a/differential-tests/tests/capstone-differential.rs b/differential-tests/tests/capstone-differential.rs
index 3602ac5..9f85e83 100644
--- a/differential-tests/tests/capstone-differential.rs
+++ b/differential-tests/tests/capstone-differential.rs
@@ -523,16 +523,6 @@ fn capstone_differential() {
panic!("text: {}, bytes: {:?}", yax_text, bytes);
}
- if cs_text.contains("stz2g ") || cs_text.contains("stzg ") || cs_text.contains("st2g ") || cs_text.contains("stg ") || cs_text.contains("irg ") || cs_text.contains("ssbb") {
- // TODO yax might not scale the offset right?
- continue;
- }
-
- if cs_text.contains("ldg ") {
- // TODO: yax says ldm, cs says ldg
- continue;
- }
-
if cs_text.contains("dfb ") {
// TODO: yax and cs disagree?
continue;
@@ -683,9 +673,9 @@ fn capstone_differential() {
if cs_text.starts_with("sev ") {
return true;
}
-// if yax_text.starts_with("hint ") {
-// return true;
-// }
+ if yax_text.starts_with("hint ") {
+ return true;
+ }
// fmlal v0.2s, v0.4h, v0.h[0] != fmlal v0.2s, v0.2h, v0.h[0]. bytes: [0,
// 0, 80, f]
@@ -694,13 +684,68 @@ fn capstone_differential() {
return true;
}
+ if cs_text.starts_with("irg") && yax_text.starts_with(cs_text) && yax_text.ends_with(", xzr") {
+ // a trailing xzr is implicit in irg if omitted in the instruction
+ // text. yax includes xzr in this case, capstone does not.
+ return true;
+ }
+
+ const TAG_INSTRUCTIONS: [&'static str; 8] = [
+ "stzgm", "stg", "ldg", "stzg",
+ "stgm", "st2g", "ldgm", "stz2g"
+ ];
+
+ for mnemonic in TAG_INSTRUCTIONS {
+ if parsed_yax.opcode != mnemonic || parsed_cs.opcode != mnemonic {
+ continue;
+ }
+
+ for (yax_op, cs_op) in parsed_yax.operands.iter().zip(parsed_cs.operands.iter()) {
+ if yax_op == cs_op {
+ continue;
+ }
+ match (yax_op, cs_op) {
+ (
+ Some(ParsedOperand::MemoryWithOffset {
+ base: cs_base, offset: Some(cs_offset), writeback: cs_writeback
+ }),
+ Some(ParsedOperand::MemoryWithOffset {
+ base: yax_base, offset: Some(yax_offset), writeback: yax_writeback
+ })
+ ) => {
+ if cs_base != yax_base || cs_writeback != yax_writeback {
+ // a pretty fundamental decode mismatch..
+ return false;
+ }
+
+ if *cs_offset != *yax_offset && *yax_offset < 0 {
+ // capstone decodes offsets as an unsigned integer, not
+ // clamping to the signed range -4096 to 4080. yaxpeax
+ // decodes the operand into this range.
+ if (!*yax_offset + 1) & 0x1fff != *cs_offset {
+ return false;
+ }
+ }
+ }
+ _ => {
+ // some operands differ
+ return false;
+ }
+ }
+ }
+
+ // operand matching above looks OK, opcodes are the same, we're good
+ // here.
+ return true;
+ }
+
return false;
}
// eprintln!("{}", yax_text);
if !acceptable_match(&yax_text, &cs_text) {
eprintln!("disassembly mismatch: {} != {}. bytes: {:x?}", yax_text, cs_text, bytes);
-// std::process::abort();
+ std::process::abort();
} else {
stats.good.fetch_add(1, Ordering::Relaxed);
}