feat(memory): retain IWRAM lane effects across DMA

Update existing Thumb IWRAM continuation lanes from successful DMA reads and writes before the resumed PC+4 snapshot. Keep channel halfword duplication separate from actual lane accesses. Preserve atomic errors, cold-entry diagnostics, IRQ invalidation, and nominal timing.

Add original DMA matrices and resume regressions; update prior invalidation expectations. Record pinned ares and jgenesis evidence and explicit limits for cross-state history, general open bus, and sub-instruction arbitration.

Validated on Darwin arm64: 939 workspace and 870 core/demo tests per debug/release profile, 39 Python tests, native ROM windows, ten window smoke modes, fmt, clippy, and rustdoc. Public ARM/Thumb/memory/BIOS reports remain identical to the previous results.
This commit is contained in:
0xrsydn 2026-10-06 02:34:58 +07:00
commit 663b25e5d1
15 changed files with 449 additions and 45 deletions

View file

@ -1,5 +1,6 @@
//! Transactional lane history for Thumb IWRAM execution and target-pair refills.
//! Unknown startup/DMA history is not replaced with guessed memory bytes.
//! Completed DMA accesses update existing continuation lanes before the next fetch.
//! Unknown startup history is not replaced with guessed memory bytes.
use std::cell::Cell;
use crate::timing::AccessWidth;
@ -76,6 +77,17 @@ impl IwramBus {
}
}
/// DMA runs between instructions. Commit only after the entire unit succeeds.
/// Keep the expected CPU continuation PC; do not invent one at cold startup.
pub(super) fn dma_access(&mut self, address: u32, width: AccessWidth, value: u32) {
debug_assert!(self.pending.get().is_none());
if address >> 24 == 3 {
if let Some(history) = &mut self.committed {
history.lanes.drive(address, width, value);
}
}
}
pub(super) fn finish(&mut self, succeeded: bool, sequential: bool) {
let pending = self.pending.take();
if succeeded {