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
|
|
@ -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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue