fix(cpu): support single-load writeback register aliases

Allow ARM LDR/LDRB/LDRH/LDRSB/LDRSH to share non-PC base and destination registers with writeback. Keep the loaded value after computing addresses from incoming operands. Preserve PC restrictions, unsupported user transfers, store behavior, and atomic memory diagnostics.

Add original regressions for index modes, offsets, widths, alignment, sign extension, all active banks, timing, I/O/IRQ ordering, and failures. The unchanged pinned public ARM ROM progresses past tests 360 and 361, then fails at test 362 on an unmapped 0x80000000 read; no full-suite pass is claimed.

Verified on Darwin arm64: debug/release workspace and core suites, Python adapter tests, Clippy, rustdoc, native ROM-window checks, and all ten demo smoke tests. Document the new behavior and next memory-access blocker.
This commit is contained in:
0xrsydn 2026-10-05 20:15:18 +07:00
commit ab625dc55d
11 changed files with 367 additions and 12 deletions

View file

@ -49,6 +49,18 @@ Both constructors zero registers deterministically; real reset register values a
Each call to `Cpu::step(&mut memory)` executes one ARM word or one Thumb halfword, not one hardware cycle.
The two halves of Thumb `BL` execute separately. A standalone suffix uses the existing link register.
ARM single loads allow base and destination to share r0–r14, including with pre-indexed or post-indexed writeback.
This applies to `LDR`, `LDRB`, `LDRH`, `LDRSB`, and `LDRSH`.
The loaded value takes precedence over the updated base. Addresses and register offsets use incoming register values.
Pre-indexed loads access the adjusted address; post-indexed loads access the original address.
The discarded post-indexed writeback address is not a second memory access.
Normal alignment, word rotation, odd-halfword behavior, and sign extension still apply.
Loads preserve CPSR and use normal load timing. Device clocks advance after the read, with IRQ sampling on the next step.
Read diagnostics leave CPU state and device clocks unchanged under the existing atomic-error policy.
Stores with matching base/source still store the original base value before writeback.
PC writeback, byte/halfword PC destinations, and unimplemented user-transfer encodings remain diagnostics.
These alias rules implement ARM7 compatibility behavior, not a recommendation for portable ARM assembly.
Block transfers assign the lowest-numbered register to the lowest memory address.
They align addresses down without rotating loaded words, and preserve low base bits during writeback.
On ARM7, an empty register list transfers PC but uses a 64-byte span for addressing and writeback.