feat(memory): retain aligned Thumb BIOS prefetch words
Snapshot the full word at (executing PC+4)&~3 for Thumb BIOS execution, using strict image reads and incoming instruction state. Keep ARM PC+8 open bus separate and unchanged. Commit snapshots only after successful steps; preserve diagnostic behavior for unavailable lookahead. Add original regression coverage for both code alignments, load widths and lanes, signed and unaligned values, processor modes, sequential fetches, ARM/Thumb transitions, SWI, RAM-backed POP exits, BIOS boundaries, failure retention, and nominal device progression. Record source evidence and explicit pipeline/hardware-validation limits. Darwin arm64 validation: 878 workspace tests and 809 core/demo tests in each of debug and release; 39 Python tests; native ROM window tests in both profiles; ten window/graphics smoke modes; fmt, clippy, and rustdoc. Public ARM, Thumb, memory, and BIOS reports match prior passing reports and match between profiles. No physical-hardware validation claimed.
This commit is contained in:
parent
efdc288db6
commit
cb4670c245
12 changed files with 427 additions and 25 deletions
|
|
@ -28,6 +28,7 @@ The repository is a Cargo workspace with three crates:
|
|||
| `crates/gba-core/src/cpu/exception.rs` | Reset state, exception entry, and interrupt sampling |
|
||||
| `crates/gba-core/src/cpu/load_alias_tests.rs` | Original single-load alias regressions for indexing, banks, widths, alignment, I/O, timing, and diagnostics |
|
||||
| `crates/gba-core/src/cpu/bios_access_tests.rs` | Original CPU BIOS protection regressions for retained history, modes, widths, exception returns, and diagnostics |
|
||||
| `crates/gba-core/src/cpu/thumb_bios_access_tests.rs` | Thumb BIOS aligned-word snapshots, transitions, load lanes, boundaries, diagnostics, and nominal timing |
|
||||
| `crates/gba-core/src/cpu/compare_psr_tests.rs` | Original Rd=15 test/compare status restoration, flags, bank, and timing regressions |
|
||||
| `crates/gba-core/src/cpu/status_tests.rs`, `crates/gba-core/src/cpu/exception_tests.rs` | Status, banking, exception, and return tests |
|
||||
| `crates/gba-core/src/cpu/thumb_tests.rs` | Thumb instructions, state switching, and decoder checks |
|
||||
|
|
|
|||
|
|
@ -97,13 +97,15 @@ While executing inside BIOS, ARM and Thumb code can read the mapped image direct
|
|||
While executing outside BIOS, both instruction sets read byte lanes from retained BIOS prefetch data instead.
|
||||
Normal word rotation, odd-halfword behavior, sign extension, and load timing still apply.
|
||||
|
||||
The current interpreter implements a bounded ARM prefetch model:
|
||||
The current interpreter implements bounded ARM and Thumb BIOS prefetch snapshots:
|
||||
|
||||
- Before an ARM BIOS instruction executes, sample its mapped PC+8 word without charging another data access.
|
||||
- Before a Thumb BIOS instruction executes, sample the full mapped word at `(PC+4) & ~3`.
|
||||
BIOS drives a 32-bit word even for a halfword fetch; both distinct lanes are retained.
|
||||
- After successful execution, retain that snapshot for later protected reads. Skipped conditional instructions count as successful execution.
|
||||
- Instructions outside BIOS do not replace the retained value. Re-entering ARM BIOS code refreshes it.
|
||||
- Instructions outside BIOS do not replace the retained value. Re-entering ARM or Thumb BIOS code refreshes it.
|
||||
- Diagnostic failures preserve the previous value and clear the CPU access context.
|
||||
- Successful Thumb BIOS execution or unavailable PC+8 bytes invalidate the known value. Their fetch history is not yet modeled.
|
||||
- Unavailable lookahead bytes invalidate the known value after a successful BIOS instruction.
|
||||
- A protected read without known history returns `MemoryError::Unmapped` at the requested bus address, rather than exposing raw BIOS bytes.
|
||||
|
||||
The initial history is unknown. Direct cartridge startup with `Cpu::new` does not manufacture boot prefetch data.
|
||||
|
|
@ -129,7 +131,10 @@ Instruction fetches remain strict mapped reads outside the CPU data-access conte
|
|||
BIOS writes remain read-only diagnostics. DMA BIOS sources retain their existing unsupported-source diagnostic.
|
||||
Missing BIOS images remain unmapped. The unused-memory ARM open-bus snapshot is separate from this retained BIOS value.
|
||||
|
||||
This models neither a persistent fetch pipeline nor exact bus history across Thumb BIOS code and DMA.
|
||||
The Thumb rule follows documented BIOS bus lanes and a source comparison with NanoBoyAdvance.
|
||||
See [Thumb BIOS prefetch research](../research/thumb-bios-prefetch.md) for evidence, emulator differences, and test scope.
|
||||
This models neither a persistent fetch pipeline nor exact refill, BIOS data-access, or DMA bus history.
|
||||
The boundary diagnostic policy and precise bus timing remain hardware-unverified.
|
||||
Original regressions cover synthetic images, boot, exception returns, access widths, alignment, modes, and diagnostics.
|
||||
The [public BIOS ROM](../public-bios-tests.md) passes its unchanged protected-read assertions in debug and release builds.
|
||||
This result covers these firmware boundaries, not full BIOS service compatibility.
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ Host inspection, ROM-suite memory assertions, instruction fetches, and DMA do no
|
|||
Limits remain explicit:
|
||||
|
||||
- Thumb open bus depends on instruction region, alignment, and prior bus data; it remains unsupported.
|
||||
- [BIOS-protected reads](bios.md#cpu-bios-read-protection) use separate retained ARM BIOS snapshots.
|
||||
- [BIOS-protected reads](bios.md#cpu-bios-read-protection) use separate retained ARM PC+8 or aligned Thumb PC+4 word snapshots.
|
||||
- Unused/write-only I/O reads, DMA latches, and disabled-RAM reads are not modeled here.
|
||||
- Missing BIOS, truncated ROM, unsupported I/O, and save-memory accesses retain their existing diagnostics.
|
||||
- Unused-memory writes remain diagnostics rather than ignored hardware writes. Swaps cannot silently discard their write.
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ See the [root-cause research](research/bios-readback.md) and [CPU BIOS read-prot
|
|||
|
||||
The ARM, Thumb, and memory suites remain separate passing results.
|
||||
This BIOS result covers boundary readback values, not complete BIOS services, exact fetch history, or commercial-game compatibility.
|
||||
Thumb BIOS execution, full pipeline behavior, and exact firmware timing remain unverified.
|
||||
Separate original tests cover bounded [Thumb BIOS snapshots](research/thumb-bios-prefetch.md); this public ROM does not validate that path.
|
||||
Full pipeline behavior, physical-hardware Thumb readback, and exact firmware timing remain unverified.
|
||||
|
||||
## References
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,15 @@ BIOS protected-read root-cause research:
|
|||
|
||||
See [the root-cause analysis and implementation decision](research/bios-readback.md).
|
||||
|
||||
Thumb BIOS fetch research:
|
||||
|
||||
- [NanoBoyAdvance bus at revision 55b5cf0a](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/bus/bus.cc), for full aligned BIOS latch updates on halfword reads.
|
||||
- [NanoBoyAdvance ARM7TDMI loop at the same revision](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh), for Thumb PC+4 fetch order.
|
||||
- [mGBA CPU loop](https://github.com/mgba-emu/mgba/blob/master/src/arm/arm.c), compared with its region-exit retention path; not evidence of exact full-word Thumb BIOS readback.
|
||||
- GBATEK's BIOS/OAM Thumb lane table above supports aligned-word sampling, but describes general unused-memory reads.
|
||||
|
||||
See [Thumb BIOS prefetch snapshots](research/thumb-bios-prefetch.md) for the inference, implementation limits, and original regressions.
|
||||
|
||||
Use [GBATEK](https://problemkaputt.de/gbatek.htm) and ARM7TDMI documentation for further hardware work.
|
||||
Only use game ROMs that you may lawfully use. Do not commit game ROMs, BIOS files, or game assets.
|
||||
The ignore file excludes `roms/`, common game ROM extensions, and save files.
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ Workspace tests, preparation tests, lint checks, rustdoc, native ROM windows, an
|
|||
- Keep synthetic caller-supplied images image-derived, including images with different exit words.
|
||||
- Rerun public ARM, Thumb, and memory suites and native Darwin regressions.
|
||||
|
||||
This change does not implement a persistent instruction pipeline, Thumb BIOS fetch history, or exact firmware timing.
|
||||
The firmware-layout fix did not implement a persistent instruction pipeline, Thumb BIOS fetch history, or exact firmware timing.
|
||||
A subsequent [Thumb BIOS snapshot change](thumb-bios-prefetch.md) adds bounded aligned-word history, with separate tests and explicit limits.
|
||||
It does not prove complete BIOS compatibility or commercial-game support.
|
||||
The public BIOS ROM checks these protected-read values; it is not a comprehensive BIOS service suite.
|
||||
|
|
|
|||
75
docs/research/thumb-bios-prefetch.md
Normal file
75
docs/research/thumb-bios-prefetch.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Thumb BIOS prefetch snapshots
|
||||
|
||||
## Decision
|
||||
|
||||
Retain the full mapped word at `(executing PC + 4) & !3` after a successful Thumb BIOS instruction.
|
||||
Keep ARM's existing PC+8 rule. Keep this BIOS history separate from general unused-memory open bus.
|
||||
|
||||
BIOS has a 32-bit bus. A Thumb instruction fetch selects a halfword, but the BIOS bus drives both word lanes.
|
||||
This gives the following snapshot for an instruction at address P:
|
||||
|
||||
| Executing address | Low halfword | High halfword |
|
||||
| --- | --- | --- |
|
||||
| P aligned to four bytes | BIOS[P+4] | BIOS[P+6] |
|
||||
| P aligned to two bytes only | BIOS[P+2] | BIOS[P+4] |
|
||||
|
||||
The two halfwords need not match. Do not repeat the fetched halfword, zero-extend it, or read an unaligned word at P+4.
|
||||
Do not use ARM's PC+8 offset for Thumb execution.
|
||||
|
||||
## Evidence and confidence
|
||||
|
||||
[GBATEK](https://problemkaputt.de/gbatek-gba-unpredictable-things.htm) documents two related behaviors:
|
||||
|
||||
- Protected BIOS reads return the most recently fetched BIOS opcode.
|
||||
- Thumb open bus while executing in BIOS exposes the two aligned word lanes shown above.
|
||||
|
||||
Its Thumb table describes unused-memory reads, not a dedicated Thumb protected-BIOS test.
|
||||
The retained-word rule combines that bus-width evidence with the documented BIOS latch behavior.
|
||||
We have not measured it on physical hardware.
|
||||
|
||||
[NanoBoyAdvance's bus implementation](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/bus/bus.cc) corroborates the full-word latch.
|
||||
`ReadBIOS` aligns a permitted address down to four bytes and updates its BIOS latch with a full word.
|
||||
It then selects the requested lanes. A halfword access does not reduce the retained latch to 16 bits.
|
||||
Its [ARM7TDMI execution loop](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh) fetches the Thumb PC+4 halfword before dispatching the instruction.
|
||||
This is a source comparison, not a differential emulator run. No implementation code was copied.
|
||||
|
||||
[mGBA's memory implementation](https://github.com/mgba-emu/mgba/blob/master/src/gba/memory.c) was also reviewed.
|
||||
Its region-exit path saves `cpu->prefetch[1]`, while its [Thumb execution loop](https://github.com/mgba-emu/mgba/blob/master/src/arm/arm.c) fetches a halfword.
|
||||
That path does not independently establish both retained word lanes. Its general Thumb BIOS open-bus path also notes an alignment approximation.
|
||||
Do not treat agreement between all emulators, or exact hardware conformance, as established.
|
||||
|
||||
## Implementation scope
|
||||
|
||||
`Memory::begin_cpu_access` samples before execution, using the incoming instruction state and strict mapped bytes.
|
||||
`end_cpu_access` commits BIOS history only after success. Failed instructions preserve previous history.
|
||||
Thumb execution outside BIOS neither initializes nor replaces BIOS history.
|
||||
Host reads remain raw inspection. CPU data loads outside BIOS select lanes from retained history as before.
|
||||
Snapshots add no data accesses or nominal cycles.
|
||||
|
||||
The snapshot does not create a persistent instruction pipeline.
|
||||
It does not model refill-time latches, BIOS data-access ordering within an instruction, DMA bus transitions, or general Thumb open bus.
|
||||
At BIOS boundaries, unavailable lookahead invalidates history under the existing diagnostic policy.
|
||||
A branch can still succeed; a later protected read reports unknown history rather than exposing stale bytes.
|
||||
This boundary policy is conservative, not a hardware claim.
|
||||
|
||||
## Regression coverage
|
||||
|
||||
Original tests in `crates/gba-core/src/cpu/thumb_bios_access_tests.rs` cover:
|
||||
|
||||
- Both Thumb instruction alignments and both output instruction states.
|
||||
- Full words, byte lanes, halfwords, sign extension, rotation, and all processor modes.
|
||||
- Sequential history, ARM/Thumb transitions, SWI entry, and POP-to-PC exits with RAM stack data.
|
||||
- Raw reads inside BIOS and protected reads outside it.
|
||||
- The last complete fetch word, unavailable lookahead, and failure retention.
|
||||
- Separate host reads, unchanged general Thumb open-bus diagnostics, nominal costs, and device progression.
|
||||
|
||||
## Validation result
|
||||
|
||||
The Thumb boundary-read regressions failed on the old history-invalidation path and pass with aligned-word snapshots.
|
||||
Darwin arm64 workspace and core/demo tests pass in debug and release builds.
|
||||
Preparation tests, formatting, lint checks, rustdoc, native ROM windows, and graphics smoke tests also pass.
|
||||
The pinned public ARM, Thumb, memory, and BIOS reports match their previous passing reports exactly.
|
||||
Debug and release reports also match each other for the same fixture paths.
|
||||
|
||||
The pinned public BIOS ROM uses ARM firmware paths. Its unchanged pass is regression evidence, not independent Thumb BIOS coverage.
|
||||
Full pipeline timing and commercial-game compatibility remain outside this change.
|
||||
|
|
@ -43,7 +43,7 @@ Update this file when a feature lands or a limit is removed.
|
|||
- CPU/device stepping with nominal ARM7 instruction costs and memory wait states.
|
||||
- Game Pak wait-state control (`WAITCNT`) for all three ROM windows.
|
||||
- Sequential/non-sequential data accesses, branch refill costs, and variable multiply timing.
|
||||
- Optional caller-supplied 16 KiB BIOS mapping, with CPU read protection based on retained ARM BIOS PC+8 snapshots.
|
||||
- Optional caller-supplied 16 KiB BIOS mapping, with CPU read protection based on retained ARM PC+8 or aligned Thumb PC+4 words.
|
||||
- Optional original BIOS replacement: minimal boot, SoftReset, selective RegisterRamReset, IRQ dispatch, interrupt waits, memory copy/fill, integer/fixed-point arithmetic, affine matrices, bit unpacking, LZ77/run-length/Huffman decompression, and differential filters.
|
||||
- All 16 ARM data-processing operations, with immediate and shifted-register operands.
|
||||
- Logical operations: `AND`, `EOR`, `TST`, `TEQ`, `ORR`, `MOV`, `BIC`, and `MVN`.
|
||||
|
|
@ -94,8 +94,10 @@ The reserved ARM condition code `0xF` and Thumb condition code `0xE` return erro
|
|||
ARMv5+ extensions such as `BLX`, `BKPT`, and Thumb-2 instructions are not supported.
|
||||
The ARMv4T high-register format requires at least one high register; low-to-low forms in that format return errors.
|
||||
`LDRT`/`STRT` single-transfer variants and invalid register combinations return errors.
|
||||
CPU BIOS reads are protected by the executing address using a bounded ARM prefetch snapshot.
|
||||
Thumb BIOS execution and missing lookahead invalidate that history; protected reads with unknown history remain diagnostics.
|
||||
CPU BIOS reads are protected by the executing address using bounded ARM and Thumb prefetch snapshots.
|
||||
Thumb BIOS execution retains the full word at `(PC+4) & ~3`, not a repeated halfword.
|
||||
Missing lookahead invalidates that history; protected reads with unknown history remain diagnostics.
|
||||
Exact refill and BIOS data-access ordering remain unmodeled. The Thumb rule has source-based, not physical-hardware validation.
|
||||
This is not a full fetch pipeline. The original BIOS reproduces documented boundary readback words, not all firmware side effects.
|
||||
Multiply flags N/Z are implemented. Unspecified multiply C/V outputs are preserved deterministically, not hardware-verified.
|
||||
Instruction and memory errors are development diagnostics, not emulated CPU exceptions.
|
||||
|
|
@ -129,7 +131,7 @@ The runner requires known completion addresses and has no debug-port protocol, s
|
|||
|
||||
ARM data reads from unused address ranges use a bounded [PC+8 open-bus snapshot](hardware/cpu.md#arm-unused-memory-data-reads).
|
||||
This is not a fetch pipeline. General Thumb, DMA, and unused/write-only I/O open bus remain unmodeled.
|
||||
BIOS protection uses separate retained ARM BIOS history as described in [BIOS behavior](hardware/bios.md#cpu-bios-read-protection).
|
||||
BIOS protection uses separate retained BIOS fetch snapshots as described in [BIOS behavior](hardware/bios.md#cpu-bios-read-protection).
|
||||
Host inspection and instruction fetches remain strict. Other unmapped reads return errors.
|
||||
Reads beyond the supplied cartridge bytes also return errors.
|
||||
Direct memory-bus halfword and word accesses require alignment.
|
||||
|
|
@ -138,9 +140,9 @@ Writes to cartridge addresses return errors instead of modeling cartridge hardwa
|
|||
|
||||
## Next steps
|
||||
|
||||
1. Extend BIOS prefetch history to Thumb execution and validate broader fetch-history behavior with independent tests.
|
||||
1. Extend general open-bus support with documented Thumb region/alignment rules and explicit limits for history-dependent cases.
|
||||
Validate BIOS snapshots with independent hardware tests before claiming exact refill or data-access history.
|
||||
The desktop runner still uses only the original BIOS. Keep protected reads image-derived for all supplied images.
|
||||
Extend general open-bus support with verified Thumb region/alignment rules and bus history.
|
||||
2. Refine nominal timing with a fetch pipeline, Game Pak prefetch, per-access device updates, and verified timer/IRQ delays.
|
||||
3. Validate keypad retrigger behavior with hardware tests and add remaining device registers; extend BIOS reset coverage as sound/serial support becomes available.
|
||||
Validate STOP entry/wake edges and add external wake sources and remaining DMA device modes.
|
||||
|
|
|
|||
|
|
@ -219,9 +219,12 @@ Status tests cover all modes, flag combinations, interrupt masks, field selectio
|
|||
Exception tests cover vectors, ARM/Thumb return addresses, nested interrupts, mask priority, and return-state restoration.
|
||||
User-bank transfers and failed returns are checked for unintended changes to active and hidden registers.
|
||||
Integration tests execute original vector handlers and check optional BIOS mapping boundaries and write protection.
|
||||
Original BIOS-access regressions check retained ARM PC+8 data for ARM/Thumb callers, all processor modes, load widths, lanes, and rotation.
|
||||
Original BIOS-access regressions check retained ARM PC+8 and aligned Thumb PC+4 words for ARM/Thumb callers.
|
||||
They cover all processor modes, load widths, lanes, rotation, both Thumb code alignments, and distinct halfwords.
|
||||
They verify direct reads while executing inside BIOS, re-entry, SWI/IRQ returns, host-inspection isolation, and original-boot provenance.
|
||||
Unknown history, Thumb BIOS execution, missing lookahead, and diagnostic-step retention have explicit checks.
|
||||
Thumb tests cover sequential snapshots, instruction-state transitions, SWI entry, and RAM-backed POP exits.
|
||||
Unknown history, last valid fetch words, missing lookahead, and diagnostic-step retention have explicit checks.
|
||||
General Thumb unused-memory reads remain diagnostics; supporting Thumb BIOS snapshots does not enable general open bus.
|
||||
Protected loads keep normal nominal costs and advance devices only through machine stepping.
|
||||
Firmware readback regressions separately verify documented boot, SoftReset, returning SWI, IRQ callback, and IRQ return words.
|
||||
They execute ARM/Thumb loads across widths and lanes, check caller state, and trace actual exits to their image data.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue