mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
feat(timing): Stage-2 #1a — data-load cost in psx_instr_base_cycles (Δ-validated)
Transcribed from Beetle PS_CPU::ReadMemory: a CPU load adds +2 cycles (LWC2 +1); stores posted (~0). psx_instr_base_cycles now returns 3 for LB/LH/LWL/LW/LBU/LHU/LWR, 2 for LWC2, 1 else. Flows to BOTH backends via the single-source seam. Δ GATE (cyc_watch @0x80017FC4, native vs Beetle per-iteration): 46 -> 56 (toward Beetle 91) — load cost closed ~10 cyc; remaining ~35 = later components (I-cache fetch, mult/div, GTE, region/absorb refinements). FMV still streams (no regression). Approximation noted in the header: no scratchpad-free / load-delay-absorb / region yet (Δ-gated next). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -31,12 +31,32 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CPU instruction base cycle cost (execute cycles only; excludes data-access
|
||||
* wait states, which the memory path charges). `insn` is the raw 32-bit MIPS
|
||||
* word. Stage 1: identity. */
|
||||
/* Guest CPU cycle cost for one retired instruction. `insn` is the raw 32-bit MIPS
|
||||
* word. Transcribed from the in-tree Beetle oracle (mednafen psx/cpu.cpp) + psx-spx;
|
||||
* each component verified against Beetle via the cyc_watch DELTA gate
|
||||
* (FAITHFUL_TIMING_PLAN.md §3c). Both backends consume this one function.
|
||||
*
|
||||
* STAGE 2 component #1 — data-memory access (the dominant ~2x gap):
|
||||
* Beetle PS_CPU::ReadMemory: a normal CPU load adds `lts += 2` (LWC loads +1);
|
||||
* stores are POSTED (WriteMemory adds no CPU stall); scratchpad reads add 0.
|
||||
* So: load opcode = 1 (execute) + 2 (data access) = 3; LWC2 = 2; store/other = 1.
|
||||
* NOT YET MODELED (later Δ-gated components, will adjust here / in the mem path):
|
||||
* - scratchpad-vs-RAM region (scratchpad load should be 1, not 3),
|
||||
* - the read-after-load "fudge" (+0/2) and load-delay ABSORB (next-insn discount),
|
||||
* - I-cache instruction-fetch timing, mult/div latency, GTE per-command costs.
|
||||
* This RAM-load base is an upper bound on the load component (no absorb yet); the
|
||||
* Δ gate shows whether we under/overshoot and what to add next. */
|
||||
static inline uint32_t psx_instr_base_cycles(uint32_t insn) {
|
||||
(void)insn;
|
||||
return 1u;
|
||||
uint32_t op = insn >> 26;
|
||||
switch (op) {
|
||||
case 0x20: case 0x21: case 0x22: case 0x23: /* LB LH LWL LW */
|
||||
case 0x24: case 0x25: case 0x26: /* LBU LHU LWR */
|
||||
return 3u; /* 1 execute + 2 data-access */
|
||||
case 0x32: /* LWC2 (GTE load): +1 */
|
||||
return 2u;
|
||||
default:
|
||||
return 1u;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user