aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGrond <grond@grondhaus.net>2026-06-23 16:44:24 -0700
committeriximeow <me@iximeow.net>2026-07-28 02:53:24 +0000
commitc4015e7157ad07ffdd37f794ee77c5695a001059 (patch)
tree313878ebb0b6766f0b4287c4f7b2b49e37bda20d /tests
parent03b7860359a9bdff793419367563974db335e45e (diff)
Fix the handling of reserved bits in uncommon loads/stores
There's a pattern of load/store instructions that look something like * `ldr<variant> <target registers>, [<base register>, +/- <offset register>]` * `str<variant> <target registers>, [<base register>, +/- <offset register>]` These instructions share a common encoding format, which includes the presence of 4 reserved bits starting at bit 8 in the instruction word. These bits should always be zero, according to `DDI0406C_d_armv7ar_arm.pdf`. However, while this crate did attempt to validate these bits sometimes, the validation was inverted. Instead of checking that the bits were zero, the validation would raise an error if all of the bits were zero! Additionally, some instructions were missing the check and some instructions that did not use the aforementioned encoding scheme incorrectly had the check applied to them. This commit fixes all of the issues I've found along these lines so far.
Diffstat (limited to 'tests')
-rw-r--r--tests/armv7/mod.rs24
1 files changed, 16 insertions, 8 deletions
diff --git a/tests/armv7/mod.rs b/tests/armv7/mod.rs
index 7fff4a8..fc909af 100644
--- a/tests/armv7/mod.rs
+++ b/tests/armv7/mod.rs
@@ -220,24 +220,32 @@ fn test_decode_str_ldr() {
test_all([0x10, 0x00, 0x3f, 0xe4], "ldrt r0, [pc], -0x10");
test_all([0x10, 0x00, 0x4f, 0xe4], "strb r0, [pc], -0x10");
// Extra load/store instructions A5.2.8, page A5-201
- test_all([0xbb, 0x38, 0xa5, 0xe1], "strh r3, [r5, fp]!");
- test_all([0xbb, 0x38, 0xb5, 0xe1], "ldrh r3, [r5, fp]!");
+ test_all([0xbb, 0x30, 0xa5, 0xe1], "strh r3, [r5, fp]!");
+ test_all([0xbb, 0x30, 0xb5, 0xe1], "ldrh r3, [r5, fp]!");
test_all([0xbb, 0x38, 0xe5, 0xe1], "strh r3, [r5, 0x8b]!");
test_all([0xbb, 0x38, 0xf5, 0xe1], "ldrh r3, [r5, 0x8b]!");
- test_armv5([0xdb, 0x48, 0xa6, 0xe1], "ldrd r4, r5, [r6, fp]!");
- test_invalid([0xdb, 0x38, 0xa5, 0xe1]);
- test_all([0xdb, 0x38, 0xb5, 0xe1], "ldrsb r3, [r5, fp]!");
+ test_armv5([0xdb, 0x40, 0xa6, 0xe1], "ldrd r4, r5, [r6, fp]!");
+ test_invalid([0xdb, 0x30, 0xa5, 0xe1]);
+ test_all([0xdb, 0x30, 0xb5, 0xe1], "ldrsb r3, [r5, fp]!");
test_armv5([0xdb, 0x48, 0xe6, 0xe1], "ldrd r4, r5, [r6, 0x8b]!");
test_invalid([0xdb, 0x38, 0xe5, 0xe1]);
test_all([0xdb, 0x38, 0xf5, 0xe1], "ldrsb r3, [r5, 0x8b]!");
test_invalid([0xfb, 0x38, 0xa5, 0xe1]);
- test_all([0xfb, 0x48, 0xa6, 0xe1], "strd r4, r5, [r6, fp]!");
- test_all([0xfb, 0x38, 0xb5, 0xe1], "ldrsh r3, [r5, fp]!");
- test_invalid([0xfb, 0x38, 0xe5, 0xe1]);
+ test_all([0xfb, 0x40, 0xa6, 0xe1], "strd r4, r5, [r6, fp]!");
+ test_all([0xfb, 0x30, 0xb5, 0xe1], "ldrsh r3, [r5, fp]!");
+ test_invalid([0xfb, 0x30, 0xe5, 0xe1]);
test_all([0xfb, 0x48, 0xe6, 0xe1], "strd r4, r5, [r6, 0x8b]!");
test_all([0xfb, 0x38, 0xf5, 0xe1], "ldrsh r3, [r5, 0x8b]!");
test_all([0xfb, 0x38, 0xff, 0xe1], "ldrsh r3, [pc, 0x8b]!");
+ // load/store have had issues about which bits are reserved and which aren't. the
+ // immediate-offset forms (encoding A1 of LDRSH and LDRSB) had incorrect checks for bits 8..11
+ // being 0 when they are simply part of the immediate (as seen above as well!). test both with
+ // bits in this range set and with all bits clear.
+ test_all([0xdb, 0x38, 0xf5, 0xe1], "ldrsb r3, [r5, 0x8b]!");
+ test_all([0xfb, 0x38, 0xf5, 0xe1], "ldrsh r3, [r5, 0x8b]!");
+ test_all([0xfb, 0x30, 0xf5, 0xe1], "ldrsh r3, [r5, 0xb]!");
+ test_all([0xdb, 0x40, 0xf5, 0xe1], "ldrsb r4, [r5, 0xb]!");
}
#[test]