feat(memory): support ARM unused-memory open-bus reads
Snapshot mapped PC+8 bytes for ARM data reads in the documented unused ranges. Preserve strict host/fetch/Thumb/DMA diagnostics, missing-ROM errors, existing write rules, and nominal timing. Add original regressions and document the bounded model. The unmodified pinned jsmolka ARM ROM now reaches its verified checkpoint with r12=0 in debug and release: 1344 steps and 11257 nominal cycles. No ROM, manifest, or assertion changes. Validated on Darwin arm64: 842 workspace tests in debug and release; 773 core/demo tests separately; Python adapter tests; native ROM windows; all ten demo window smoke tests; fmt, clippy, and rustdoc.
This commit is contained in:
parent
ab625dc55d
commit
a9493d4cc6
11 changed files with 418 additions and 26 deletions
|
|
@ -68,6 +68,36 @@ On ARM7, an empty register list transfers PC but uses a 64-byte span for address
|
|||
With writeback enabled, `STM` stores the old base only when that register is first in the list.
|
||||
Otherwise, `STM` stores the updated base.
|
||||
|
||||
## ARM unused-memory data reads
|
||||
|
||||
During ARM execution, data reads from `0x00004000..0x01ffffff` and `0x10000000..0xffffffff` return an open-bus value.
|
||||
Open bus means the bus retains previously driven data. GBATEK identifies this ARM value as the instruction word at PC+8.
|
||||
These high addresses do not mirror BIOS, RAM, or cartridge addresses.
|
||||
|
||||
The interpreter snapshots mapped bytes at PC+8 before executing each ARM instruction.
|
||||
All unused-memory reads within that instruction use the same snapshot.
|
||||
Byte and halfword reads select their addressed lanes; the CPU applies normal rotation and sign extension.
|
||||
Base writeback, register aliases, block loads, PC loads, and flags retain their existing instruction semantics.
|
||||
Each data access pays the nominal unused-region cost of one cycle, plus normal code and internal costs.
|
||||
Snapshot reads add no data accesses or device cycles. This is not a simulated prefetch pipeline or Game Pak prefetch.
|
||||
|
||||
The snapshot uses strict mapped reads, without recursive open-bus fallback.
|
||||
If any snapshot byte is unavailable, an unused-memory data read retains its `Unmapped` diagnostic.
|
||||
Missing lookahead does not fail ordinary instructions, mapped loads, or skipped conditional loads.
|
||||
The CPU clears the access context after each instruction, including errors.
|
||||
Host inspection, ROM-suite memory assertions, instruction fetches, and DMA do not inherit this context.
|
||||
|
||||
Limits remain explicit:
|
||||
|
||||
- Thumb open bus depends on instruction region, alignment, and prior bus data; it remains unsupported.
|
||||
- BIOS-protected reads, 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.
|
||||
- No persistent pipeline or bus history exists. Self-modifying code and DMA-to-CPU bus transitions are not hardware-accurate.
|
||||
|
||||
This subset lets public ARM test 362 complete. That test does not assert the loaded data value.
|
||||
Original regressions check the values separately. See [the public ARM result](../public-arm-tests.md).
|
||||
|
||||
## Processor status and exceptions
|
||||
|
||||
User and System share registers. Each exception mode has its own stack pointer, link register, and SPSR.
|
||||
|
|
@ -144,7 +174,7 @@ The new settings apply to subsequent code accesses.
|
|||
Important timing limits:
|
||||
|
||||
- Code S/N counts follow instruction summaries, not a simulated fetch pipeline.
|
||||
- Ordinary code costs use the current instruction address. No speculative PC+8 fetch or startup pipeline fill is performed.
|
||||
- Ordinary code costs use the current instruction address. The ARM open-bus PC+8 snapshot has no fetch timing or startup pipeline fill.
|
||||
- PC writes use destination-region costs and the restored instruction width for nominal refill accesses.
|
||||
- Refill cost calculation does not read target bytes. An invalid branch target fails on the following instruction fetch.
|
||||
- Game Pak prefetch is not implemented. WAITCNT bit 14 is stored but does not accelerate execution.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
The headless runner now executes the unmodified ARM ROM from [jsmolka/gba-tests](https://github.com/jsmolka/gba-tests).
|
||||
This is independent public test code, not a complete ARM7TDMI conformance suite or a new hardware measurement.
|
||||
The full public ARM test still fails. Compare/status and load/writeback alias errors are fixed; the next memory-access failure is recorded below.
|
||||
The pinned public ARM ROM now passes its result checkpoint on Darwin arm64 in debug and release builds.
|
||||
Compare/status, load/writeback aliases, and ARM unused-memory reads are fixed. Earlier failures are retained below.
|
||||
|
||||
## Prepare and run
|
||||
|
||||
|
|
@ -61,7 +62,7 @@ The instruction at the checkpoint is checked during preparation, in addition to
|
|||
|
||||
The case budget is 1,000,000 successful machine steps, including our original BIOS boot.
|
||||
Timeouts, emulator diagnostics, and nonzero r12 all remain failures under the [normal suite rules](rom-tests.md).
|
||||
Preparation does not mean the test passed. The current run exits nonzero and writes a failed JSON report.
|
||||
Preparation does not mean the test passed. Check the runner's exit status and JSON assertions separately.
|
||||
|
||||
## Observed results on Darwin arm64
|
||||
|
||||
|
|
@ -85,7 +86,7 @@ After the compare/status fix, before load/writeback alias support:
|
|||
- This is `LDR r0, [r0, #4]!` in upstream test 360, with base and destination equal.
|
||||
- The CPU is in System/ARM state, and r12 remains zero. The final completion checkpoint has not been reached.
|
||||
|
||||
After load/writeback alias support:
|
||||
After load/writeback alias support, before ARM unused-memory reads:
|
||||
|
||||
- Tests 360 and 361 complete without taking their failure paths.
|
||||
- After 877 successful steps, the runner reports `unmapped memory at 0x80000000`.
|
||||
|
|
@ -95,9 +96,20 @@ After load/writeback alias support:
|
|||
|
||||
Single-load aliases now retain the loaded value rather than the updated base.
|
||||
Original regressions also cover byte, halfword, and signed loads, every non-PC register bank, index modes, offsets, alignment, timing, and failures.
|
||||
The public halfword alias tests later in the ROM have not yet been reached; their source and mGBA's load ordering support the same rule.
|
||||
The next compatibility task is to verify high-address read behavior and implement the appropriate memory mapping or open-bus behavior.
|
||||
Do not bypass test 362, invent a return value, or weaken the result assertion.
|
||||
|
||||
After ARM unused-memory open-bus support:
|
||||
|
||||
- Test 362 completes. The read returns the ARM word at the executing PC plus eight, not a high-address mirror.
|
||||
- Execution also reaches the later halfword alias and block-transfer tests without taking their failure exits.
|
||||
- The runner reaches `eval` at `0x08001d4c` after 1,344 successful steps, including original BIOS boot.
|
||||
- The CPU is in System/ARM state, with CPSR `0x6000001f`, r12 = 0, and 11,257 nominal cycles.
|
||||
- Debug and release runs exit zero, with `reason: checkpoint`, no error, and the result assertion passing.
|
||||
- The pinned ROM, manifest checkpoint, budget, and expected result are unchanged.
|
||||
|
||||
Test 362 checks shifted addressing, writeback, and carry, but does not check the loaded value.
|
||||
Original regressions separately check the returned word, byte lanes, rotation, sign extension, timing, and retained diagnostics.
|
||||
See the bounded [ARM open-bus implementation](hardware/cpu.md#arm-unused-memory-data-reads).
|
||||
This is a passing result for this pinned ARM ROM, not proof of complete instruction, memory, or timing compatibility.
|
||||
No public Thumb, timing, memory, BIOS, graphics, or unsafe suite has been claimed as passing.
|
||||
These results do not establish Pokémon Emerald compatibility.
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ Hardware references used for the core:
|
|||
- [NanoBoyAdvance keypad implementation](https://github.com/nba-emu/NanoBoyAdvance/blob/master/src/nba/src/hw/keypad/keypad.cc), compared for control access widths; its AND/retrigger behavior differs from the chosen polling model.
|
||||
- [mGBA keypad timing issue](https://github.com/mgba-emu/mgba/issues/2490), for frontend frame-based input timing limits.
|
||||
- [Tonc hardware interrupts](https://gbadev.net/tonc/interrupts.html), for keypad source enable and IF/IE bit 12.
|
||||
- [GBATEK memory mirrors and video byte writes](https://problemkaputt.de/gbatek-gba-unpredictable-things.htm).
|
||||
- [GBATEK memory mirrors, video byte writes, and unused-memory reads](https://problemkaputt.de/gbatek-gba-unpredictable-things.htm), for unused address ranges, ARM PC+8 open bus, byte lanes, and the distinct Thumb region/history rules.
|
||||
- [nocash GBA open-bus discussion](https://www.ngemu.com/threads/gba-open-bus.170809/), for the distinction between ARM prefetch and region-dependent Thumb values.
|
||||
- [mGBA memory implementation](https://github.com/mgba-emu/mgba/blob/master/src/gba/memory.c), reviewed for `GBALoadBad`, ARM prefetch sourcing, byte/halfword lane selection, and separate DMA/history behavior.
|
||||
- [GBATEK GBA memory map and bus widths](https://problemkaputt.de/gbatek-gba-memory-map.htm).
|
||||
- [GBATEK GBA DMA transfers](https://problemkaputt.de/gbatek-gba-dma-transfers.htm).
|
||||
- [mGBA DMA implementation](https://github.com/mgba-emu/mgba/blob/master/src/gba/dma.c), used to cross-check masks, repeat behavior, and Game Pak source increments.
|
||||
|
|
|
|||
|
|
@ -130,8 +130,9 @@ They do not hash ROM contents; record source revisions and file checksums alongs
|
|||
|
||||
## Next validation stage
|
||||
|
||||
The first public integration is [jsmolka/gba-tests ARM](public-arm-tests.md), with a verified result-register checkpoint and a known failing baseline.
|
||||
Investigate its next unsupported high-address read at test 362 before claiming the full ARM ROM passes.
|
||||
The first public integration is [jsmolka/gba-tests ARM](public-arm-tests.md), with a verified result-register checkpoint.
|
||||
The pinned ARM ROM now passes this checkpoint on Darwin arm64. Historical failures remain documented.
|
||||
Next, integrate a pinned public Thumb suite with a verified result protocol.
|
||||
For further public ARM7TDMI/GBA tests, inspect their source, license, entry assumptions, and result protocol.
|
||||
Pin source revisions and build instructions before comparing emulator changes.
|
||||
Adapt suites to verified completion addresses and result locations; do not guess them or treat timeouts as passes.
|
||||
|
|
|
|||
|
|
@ -67,8 +67,9 @@ Update this file when a feature lands or a limit is removed.
|
|||
- ROM windows with scanline capture, keyboard input, focus-loss release, bounded execution slices, and interactive keypad wake from STOP.
|
||||
- Optional ROM-window frame limits and an original input-test ROM generator.
|
||||
- Headless JSON ROM suites with per-case checkpoints, register/CPSR/memory assertions, bounded budgets, and structured failure reports.
|
||||
- Hash-pinned preparation of the public `jsmolka/gba-tests` ARM ROM, with an explicit failing compatibility baseline.
|
||||
- Hash-pinned preparation of the public `jsmolka/gba-tests` ARM ROM, passing its result checkpoint on Darwin arm64.
|
||||
- ARM test/compare Rd=15 status restoration, without a PC result write or nominal refill.
|
||||
- ARM unused-memory data reads return a PC+8 word snapshot, with normal byte lanes and load rotation.
|
||||
- Little-endian byte, halfword, and word reads/writes.
|
||||
- ARM7TDMI word-load rotation, aligned stores, and odd-address halfword-load behavior.
|
||||
- Explicit errors for unsupported instructions when their condition passes, and for unsupported memory accesses.
|
||||
|
|
@ -114,10 +115,12 @@ ROM windows have no demo-specific startup checks. Input is sampled between bound
|
|||
Audio, saves, and external BIOS loading remain unavailable. ROM loading does not establish commercial-game compatibility.
|
||||
See [cartridge loading](hardware/cartridge.md) for file limits, step budgets, and exit status.
|
||||
The [ROM suite runner](rom-tests.md) has original regressions and a [pinned public ARM baseline](public-arm-tests.md).
|
||||
The public ARM ROM now gets past its compare/status and word-load alias tests but stops at test 362 on an unmapped read from `0x80000000`.
|
||||
It requires known completion addresses and has no debug-port protocol, scripted input, or rendered-image assertions.
|
||||
The pinned public ARM ROM passes its result checkpoint in debug and release builds. Other public suites remain unverified.
|
||||
The runner requires known completion addresses and has no debug-port protocol, scripted input, or rendered-image assertions.
|
||||
|
||||
Unmapped reads return errors instead of hardware open-bus values.
|
||||
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. Thumb, DMA, BIOS-protected reads, and unused/write-only I/O open bus remain unmodeled.
|
||||
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.
|
||||
CPU load/store instructions apply ARM7TDMI alignment and rotation rules before accessing the bus.
|
||||
|
|
@ -125,8 +128,8 @@ Writes to cartridge addresses return errors instead of modeling cartridge hardwa
|
|||
|
||||
## Next steps
|
||||
|
||||
1. Verify high-address read behavior exposed by public ARM test 362; implement the appropriate memory mapping or open-bus behavior and rerun the pinned suite.
|
||||
Add further public suites only with verified result protocols before claiming instruction compatibility.
|
||||
1. Add a pinned public Thumb suite with a verified result protocol, then address its first compatibility failure.
|
||||
Extend open-bus support with verified Thumb region/alignment rules and bus history, rather than a blanket unmapped-read fallback.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Do not set a Linux cross-compilation target for this validation.
|
|||
The [headless ROM suite runner](rom-tests.md) provides explicit checkpoint and assertion results through `--test-suite PATH.json`.
|
||||
Its tests verify manifest limits, whole-suite validation, exact step boundaries, ARM/Thumb checkpoints, and register/CPSR/memory checks.
|
||||
Additional tests cover DMA/IRQ accounting, HALT/STOP, diagnostic state, case isolation, repeatable JSON output, and failure exit status.
|
||||
These original tests validate the runner. The [public ARM adapter](public-arm-tests.md) is a separate, currently failing compatibility baseline.
|
||||
These original tests validate the runner. The [public ARM adapter](public-arm-tests.md) provides a separate passing checkpoint result for its pinned ROM.
|
||||
Its preparation tests use only synthetic original bytes and no network:
|
||||
|
||||
```sh
|
||||
|
|
@ -60,7 +60,10 @@ They verify pinned URLs, hashes, sizes, checkpoint validation, offline copies, d
|
|||
Compare/status CPU regressions verify saved flags/masks, bank switching, sequential PC/timing, User/System fallback, and atomic diagnostics.
|
||||
Load-alias regressions cover widths, signed/unaligned values, immediate/register offsets, pre/post-indexing, every non-PC register bank, and address wrapping.
|
||||
They verify loaded-value precedence, preserved flags, unchanged stores, nominal timing, I/O reads before device progress, deferred IRQ delivery, and atomic errors.
|
||||
The public ARM ROM progresses past tests 360–361 but still fails on the high-address read in test 362.
|
||||
ARM open-bus regressions cover unused-range boundaries, PC+8 source regions, byte lanes, signed/unaligned loads, writeback, and block loads.
|
||||
They check branch-target resampling, missing lookahead, skipped conditions, nominal timing, device progress, and retained host/fetch/Thumb/DMA diagnostics.
|
||||
The pinned public ARM ROM now reaches its completion checkpoint with r12 = 0 in debug and release builds.
|
||||
This does not establish public Thumb, timing, graphics, BIOS, or commercial-game compatibility.
|
||||
|
||||
ROM-runner tests use temporary files containing original instructions, without Nintendo assets or a desktop session.
|
||||
They check file-size boundaries, bounded reads, short reads, I/O errors, paths, symlinks, and read-only loading.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue