From 70153175663f2c29d80dc2d4e1e4d4a68f4efeef Mon Sep 17 00:00:00 2001 From: Kevin <9866117+kerokline@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:22:09 -0400 Subject: [PATCH] tools: remember the resident occupant per dispatch address On hardware the game CD-reads a file to a fixed address and jal's straight into it: identity is implicit in control flow and costs nothing. We rediscover it by walking a band's occupants and CRC-gating each in turn. On a deep band that walk dominates -- the memory-card screen measured 41.25 checks per hit, roughly 41 failed gates before the resident one. Remember which occupant last satisfied each address and try it first. The memo is a hint, never an authority: every call still passes through psx_overlay_static_code_matches(), so a band that swapped occupants fails the memo and falls into the full walk, which then re-seeds it. Correctness is therefore unchanged -- the memo only reorders candidates. Measured headless over an identical 140 s boot window, all ten bands compiled: build throughput chk/hit variant misses all-bands 99.0 1.479 368,479 all-bands + memo 131.4 1.069 81,505 +33% throughput, 4.5x fewer wasted gate calls. It is neutral where chains are already shallow (a savestate-loaded combat workload measured 1.019 chk/hit before the memo and showed no gain), so it pays exactly where it was aimed. Together with the O(1) lookup this overturns the earlier "do not compile all bands" result: all ten bands now beat a three-band build on both workloads measured -- 131.4 vs 107.9 at boot, and parity on the savestate workload -- because more compiled code means more native execution once dispatch is cheap. Co-Authored-By: Claude Opus 5 --- tools/compile_overlays.py | 42 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/tools/compile_overlays.py b/tools/compile_overlays.py index 96bab6ad..d2abb47e 100644 --- a/tools/compile_overlays.py +++ b/tools/compile_overlays.py @@ -2396,6 +2396,20 @@ def generate_overlay_dispatch(variants: list) -> str: lines.append('') lines += emit_table('psx_ov_hash_idx', table_idx) lines.append('') + # Resident-occupant memo. On hardware the game CD-reads a file to a + # fixed address and jal's straight into it -- identity is implicit in + # control flow and costs nothing. We rediscover it by walking a band's + # occupants and CRC-gating each. On a deep band that walk dominated: + # the memory-card screen measured 41.25 checks per hit, i.e. ~41 failed + # gates before the resident one, 4.4 M failed checks per 2 s. + # + # Remember which occupant last satisfied each address and try it first. + # Correctness is unchanged because the memo only reorders candidates -- + # every call still passes psx_overlay_static_code_matches(), so a band + # that swapped occupants fails the memo and falls into the full walk. + # The memo is a hint, never an authority. + lines.append(f'static uint16_t psx_ov_last_hit[{n_entries}];') + lines.append('') lines += [ f'/* {n_entries} dispatch addresses, {len(flat_variants)} variants, ' @@ -2447,10 +2461,19 @@ def generate_overlay_dispatch(variants: list) -> str: ' slot = (slot + 1u) & PSX_OV_HASH_MASK;', ' }', ' {', - ' const PsxOvEntry *e = &psx_ov_entries[psx_ov_hash_idx[slot]];', - ' const PsxOvVariant *v = &psx_ov_variants[e->first];', + ' const uint32_t ei = psx_ov_hash_idx[slot];', + ' const PsxOvEntry *e = &psx_ov_entries[ei];', + ' const PsxOvVariant *base = &psx_ov_variants[e->first];', + ' const uint32_t n = e->n;', + ' uint32_t memo = psx_ov_last_hit[ei];', ' uint32_t i;', - ' for (i = 0; i < e->n; i++, v++) {', + ' if (memo >= n) memo = 0u;', + ' /* Try the occupant that satisfied this address last time. On a', + ' * deep band this is the difference between one CRC gate and', + ' * walking every occupant. It is only a hint: the gate below', + ' * still decides, so a swapped band simply falls through. */', + ' if (n > 1u) {', + ' const PsxOvVariant *v = base + memo;', ' psx_ov_static_checks++;', ' if (psx_overlay_static_code_matches(v->ranges, v->count,', ' v->crc)) {', @@ -2460,6 +2483,19 @@ def generate_overlay_dispatch(variants: list) -> str: ' }', ' psx_ov_static_variant_misses++;', ' }', + ' for (i = 0; i < n; i++) {', + ' const PsxOvVariant *v = base + i;', + ' if (n > 1u && i == memo) continue; /* already tried */', + ' psx_ov_static_checks++;', + ' if (psx_overlay_static_code_matches(v->ranges, v->count,', + ' v->crc)) {', + ' psx_ov_static_hits++;', + ' psx_ov_last_hit[ei] = (uint16_t)i;', + ' v->fn(cpu);', + ' return 1;', + ' }', + ' psx_ov_static_variant_misses++;', + ' }', ' }', ' /* Address is ours but no occupant is resident -> interpreter. */', ' return 0;',