feat(memory): sample Thumb IWRAM refill targets

After successful refill instructions, sample the Thumb IWRAM target and target+2 halfwords to establish bus history. Share ARM/Thumb refill classification with nominal timing. Respect restored instruction state, completed data accesses, region limits, and diagnostic rollback; keep instruction execution and nominal costs unchanged.

Add original regressions for ARM/Thumb BX, Thumb branches and BL, PC writes, stack/block PC loads, status-restoring returns, real SWI/IRQ returns, both target alignments, mirrors/wrap, captured sample ordering, load lanes, failure retention, BIOS isolation, and DMA invalidation. Document official ARM7TDMI refill evidence and the distinction from a full pipeline.

Darwin arm64 validation: 917 workspace tests and 848 core/demo tests per debug/release profile; 39 preparation tests; native ROM windows in both profiles; ten graphics/window smoke modes; fmt, clippy, and rustdoc. Public ARM, Thumb, memory, and BIOS reports remain identical to prior passing results and between profiles. Cold startup, ARM-target refill history, and DMA-to-CPU ordering remain incomplete; no hardware-conformance or commercial-game claim.
This commit is contained in:
0xrsydn 2026-10-06 02:04:07 +07:00
commit 8b0f1a5ead
12 changed files with 566 additions and 35 deletions

View file

@ -66,7 +66,8 @@ struct CpuAccess {
/// Unused-memory reads use ARM PC+8 or supported region-dependent Thumb snapshots.
/// Protected BIOS reads separately retain the snapshot from BIOS execution.
/// Sequential Thumb IWRAM accesses retain addressed bus lanes transactionally.
/// Refill history, a full fetch pipeline, and DMA bus latches are not modeled.
/// Successful refills into Thumb IWRAM sample the target pair to establish history.
/// A full fetch pipeline, ARM-target refill history, and DMA bus latches are not modeled.
pub struct Memory {
external_ram: Vec<u8>,
internal_ram: Vec<u8>,
@ -400,6 +401,24 @@ impl Memory {
}
}
/// Sample only the two target fetches of a completed refill into Thumb IWRAM.
/// This updates bus history, not the CPU's instruction buffer or nominal costs.
/// Incomplete or unsupported refills stay unknown without failing the branch early.
pub(crate) fn refill_cpu_bus_history(&mut self, pc: u32, instruction_set: InstructionSet) {
self.iwram_bus.invalidate();
if instruction_set == InstructionSet::Thumb
&& pc >> 24 == 3
&& pc.wrapping_add(2) >> 24 == 3
{
if let (Some(first), Some(second)) = (
self.snapshot_mapped_halfword(pc),
self.snapshot_mapped_halfword(pc + 2),
) {
self.iwram_bus.refill(pc, [first, second]);
}
}
}
pub(crate) fn invalidate_cpu_bus_history(&mut self) {
self.iwram_bus.invalidate();
}