refactor(cpu): share instruction fetch samples with bus history
This commit is contained in:
parent
ea055270f4
commit
e630d7a0ea
18 changed files with 538 additions and 117 deletions
|
|
@ -73,7 +73,8 @@ The existing destination-based refill summaries and one-shot DMA resume timing r
|
|||
The current instruction address still selects nominal code cost rather than a separately scheduled fetch address.
|
||||
|
||||
ARM PC+8 open bus and protected BIOS readback remain separate snapshots.
|
||||
The instruction-buffer sample and those snapshots see mapped memory before instruction effects, but no unified per-access bus model exists yet.
|
||||
The [shared fetch sample](shared-fetch-samples.md) supplies the instruction-buffer entry and supported bus snapshots without duplicate reads.
|
||||
No unified per-access bus model exists yet.
|
||||
The target samples do not establish complete ARM IWRAM or BIOS bus history.
|
||||
Instruction-state-changing compare quirks, Game Pak prefetch, and DMA arbitration remain incomplete.
|
||||
DMA still runs between whole instructions, not during their data accesses or internal cycles.
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ No physical-hardware measurement or external emulator differential run was perfo
|
|||
## Bounded implementation
|
||||
|
||||
`memory/iwram_bus.rs` records lane values and a known-bit mask during consecutive Thumb instructions in IWRAM.
|
||||
Before execution, the mapped PC+4 halfword updates its addressed lanes.
|
||||
Before execution, the pipeline's new mapped PC+4 fetch updates its addressed lanes.
|
||||
The bus-history consumer does not reread memory or reuse the current/decode instruction.
|
||||
During execution, successful IWRAM bus reads and writes update the staged lanes at their actual aligned addresses and widths.
|
||||
The latch sees raw bus data before CPU load rotation and sign extension.
|
||||
Other-region accesses and host inspection do not change it.
|
||||
|
|
@ -65,7 +66,8 @@ For Thumb destinations, those addresses are T and T+2.
|
|||
[NanoBoyAdvance's refill helpers](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh) use that order.
|
||||
Its execution loop then fetches T+4 before executing the first Thumb instruction.
|
||||
|
||||
After a successful refill instruction, we sample the two mapped destination halfwords if both remain in Thumb IWRAM.
|
||||
After a successful refill instruction, the pipeline samples the two mapped destination instructions.
|
||||
The same captured halfwords update bus history if both remain in Thumb IWRAM.
|
||||
The samples replace the old lane history and establish the next expected PC as T.
|
||||
The next instruction's normal PC+4 sample updates one lane while the other retains the captured T+2 halfword.
|
||||
The samples occur after data accesses and status restoration, so loaded PC values and saved Thumb state select the destination.
|
||||
|
|
@ -76,7 +78,7 @@ Failed instructions retain the previous committed history. An unsupported or inc
|
|||
Unmapped instruction targets still fail on the following fetch.
|
||||
Cold direct startup and arbitrary PC changes do not manufacture a refill.
|
||||
|
||||
These are bus-history samples, not instruction-buffer contents or extra emulated cycles.
|
||||
These captured values now supply both bus history and instruction-buffer entries, without extra emulated cycles.
|
||||
ARM and Thumb execution now use a separate instruction buffer. Cold buffer filling does not seed this bus history.
|
||||
Changing T+2 after the branch does not replace its captured bus value; changing T+4 before arrival affects the later sample.
|
||||
Those original tests verify sample ordering, not hardware-accurate self-modifying instruction execution.
|
||||
|
|
|
|||
78
docs/research/shared-fetch-samples.md
Normal file
78
docs/research/shared-fetch-samples.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# Shared instruction-fetch samples
|
||||
|
||||
## Finding and evidence
|
||||
|
||||
Persistent ARM/Thumb instruction buffering exposed duplicate memory reads in the interpreter.
|
||||
The pipeline sampled the new lookahead instruction, then `Memory::begin_cpu_access` reread those bytes for bus history.
|
||||
Thumb IWRAM refills also read their target pair once for history and again for instruction buffering.
|
||||
With instruction-boundary scheduling, those reads normally saw identical bytes. They still represented the same fetch twice.
|
||||
|
||||
This refactor gives instruction buffering and supported bus-history updates a common captured sample.
|
||||
It does not introduce new hardware formulas or change nominal cycle costs.
|
||||
|
||||
Previously reviewed evidence supports this separation:
|
||||
|
||||
- [NanoBoyAdvance at 55b5cf0a](https://github.com/nba-emu/NanoBoyAdvance/blob/55b5cf0ae3d929582ac5bfd486558173502b8354/src/nba/src/arm/arm7tdmi.hh): `Run` fetches the next instruction before execution; refill helpers fetch the target pair.
|
||||
- [ares at 6f6786e0](https://github.com/ares-emulator/ares/blob/6f6786e04f0822a3475463df284f313ab8518d51/ares/gba/cpu/memory.cpp): IWRAM updates local addressed lanes; EWRAM halfword reads drive duplicated halves.
|
||||
- [Thumb BIOS research](thumb-bios-prefetch.md) and [Thumb open-bus rules](../hardware/cpu.md#thumb-unused-memory-data-reads): BIOS/OAM bus observations use an aligned word, not a universally duplicated halfword.
|
||||
|
||||
These sources were reviewed, not copied into the emulator.
|
||||
No physical-hardware measurements or external-emulator differential runs were performed.
|
||||
|
||||
## Sample and consumers
|
||||
|
||||
`memory/fetch.rs` returns an `InstructionFetch` with:
|
||||
|
||||
- Fetch address and instruction state.
|
||||
- Strict instruction result or deferred mapped-read error.
|
||||
- Supported bus-word observation, when it does not require retained IWRAM lanes.
|
||||
|
||||
ARM samples use the fetched word for both instruction bits and bus observation.
|
||||
Thumb samples retain only their selected halfword as instruction bits.
|
||||
Supported 16-bit regions duplicate that halfword for bus observation.
|
||||
BIOS/OAM samples read the adjacent halfword too, without rereading the instruction bytes.
|
||||
Thumb IWRAM supplies the fetched halfword to the existing lane-retaining transaction instead of creating a full bus word.
|
||||
|
||||
The CPU passes only its newly sampled P+8 or P+4 observation to `begin_cpu_access`.
|
||||
It does not replay the bus observations of retained current/decode instructions.
|
||||
The consumer performs no mapped memory read.
|
||||
After successful control flow, the same target samples fill the instruction buffer and supported Thumb IWRAM refill history.
|
||||
Machine IRQ entry uses this refill path; the ARM target still invalidates Thumb IWRAM continuation history.
|
||||
|
||||
Instruction buffers and BIOS/IWRAM latches remain separate retained state.
|
||||
Sampling alone changes no CPU access context, latch, device clock, DMA resume marker, or data-timing trace.
|
||||
Instruction errors discard staged history and speculative buffer advances.
|
||||
A retry takes a new lookahead sample while retaining the previously committed instruction pair.
|
||||
Unavailable lookahead remains diagnostic only when consumed by an instruction or a data read that needs it.
|
||||
Strict instruction reads never use protected BIOS or unused-memory data fallback.
|
||||
|
||||
## Deliberately unchanged limits
|
||||
|
||||
- Cold pipeline filling does not establish previously unknown IWRAM history.
|
||||
- Thumb 16 MiB region crossings remain unsupported for bus snapshots.
|
||||
- ARM-wide local IWRAM history and cross-state latch ownership remain incomplete.
|
||||
- BIOS history commits after successful BIOS instruction execution; target refills do not establish additional BIOS history.
|
||||
- All unused-memory data reads within an instruction still use its entry snapshot.
|
||||
- DMA remains scheduled between whole instructions. Sampling does not add an interleaving point.
|
||||
- Current-instruction and destination-based nominal timing remain unchanged.
|
||||
- Per-access device updates, Game Pak prefetch, and exact refill/arbitration timing remain incomplete.
|
||||
|
||||
## Original tests
|
||||
|
||||
CPU tests split the existing internal fetch/execute helpers and mutate lookahead bytes between them.
|
||||
ARM, narrow Thumb, wide Thumb, and IWRAM tests then require the originally captured values.
|
||||
Those consumption tests failed with the previous duplicate-read path.
|
||||
The split is a test-only ownership check, not a hardware DMA experiment.
|
||||
|
||||
Memory tests use explicit expected lane values across mapped regions and both Thumb alignments.
|
||||
They also check target-pair consumption after mutation, BIOS snapshot retention, strict errors, short ROMs, and data-context isolation.
|
||||
Tests verify that sampling adds no timing or history effects and that failed execution preserves committed history.
|
||||
Existing instruction-buffer, bus-history, exception, DMA, and nominal timing tests remain regression coverage.
|
||||
|
||||
## Validation result
|
||||
|
||||
Workspace and core/demo tests pass in debug and release on Darwin arm64.
|
||||
Formatting, lint checks, rustdoc, preparation tests, native ROM windows, and graphics smoke modes pass.
|
||||
Public ARM, Thumb, memory, and BIOS reports match the previous Thumb-buffer reports exactly, including nominal cycle counts.
|
||||
Debug and release reports also match for the same fixture paths.
|
||||
These checks validate the refactor against existing behavior, not complete hardware bus or timing conformance.
|
||||
|
|
@ -40,7 +40,8 @@ Do not treat agreement between all emulators, or exact hardware conformance, as
|
|||
|
||||
## Implementation scope
|
||||
|
||||
`Memory::begin_cpu_access` samples before execution, using the incoming instruction state and strict mapped bytes.
|
||||
`Memory::begin_cpu_access` now consumes the pipeline's new fetch sample, using the incoming instruction state.
|
||||
The [shared sampler](shared-fetch-samples.md) captures strict mapped bytes before execution.
|
||||
`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.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ ARM-to-Thumb BX and saved-state exception returns therefore capture T and T+2, n
|
|||
Thumb-to-ARM transitions and SWI/IRQ vectors capture ARM pairs.
|
||||
|
||||
`Memory::fetch_instruction` uses strict mapped reads with the selected instruction width.
|
||||
A Thumb fetch reads exactly two bytes, even in a region whose separate bus snapshot uses a full word.
|
||||
Its instruction result needs only two bytes in Thumb state.
|
||||
The later [shared fetch sampler](shared-fetch-samples.md) also captures the adjacent halfword for BIOS/OAM bus observations.
|
||||
Memory mirrors apply. Unmapped and misaligned instruction reads retain diagnostics rather than using data open bus.
|
||||
Lookahead errors remain deferred until their slot executes; a branch can discard them.
|
||||
|
||||
|
|
@ -51,12 +52,12 @@ CPU clones own independent buffers; full CPU equality includes them.
|
|||
Instruction retention and data-bus snapshots remain separate models.
|
||||
Cold instruction-buffer filling does not make unknown IWRAM bus lanes known.
|
||||
Successful DMA can update existing IWRAM bus lanes without changing retained CPU instructions.
|
||||
Refill bus-history sampling and instruction sampling currently perform separate strict mapped reads.
|
||||
Refill bus history and instruction buffering now consume the same captured target pair without a second mapped read.
|
||||
|
||||
Buffer samples add no nominal cycles or data accesses.
|
||||
Timed and untimed execution use the same buffer logic.
|
||||
Destination-based refill summaries and one-shot non-sequential CPU resume costs remain unchanged.
|
||||
Unified fetch-driven bus history, exact region crossings, per-access timing, Game Pak prefetch, and sub-instruction DMA arbitration remain incomplete.
|
||||
Complete fetch-driven bus history, exact region crossings, per-access timing, Game Pak prefetch, and sub-instruction DMA arbitration remain incomplete.
|
||||
Instruction-state-changing compare quirks also remain hardware-unverified.
|
||||
|
||||
## Original regression coverage
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue