mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-07 12:47:58 -10:00
GPUExec dispatched every emulated instruction through executeOpcode(): a call, a return and the register spills either side of them, per op. The function could never be inlined into the loop: it holds label addresses (computed goto), and it is recursive -- jump/jr run their delay slot through it. GPUExec now dispatches through its own computed-goto table to labels inside GPUExec, where the (GPU_OP_HOT) handlers are inlined; the loop's post-op bookkeeping follows unchanged. executeOpcode() stays exactly as it was for the delay slot. One X-macro, GPU_OPCODE_LIST, generates both tables and both label blocks, so the two copies cannot drift (it also replaces executeOpcode's hand-written 64-entry table). Non-GNU compilers keep the executeOpcode() call. Emulated output unchanged: frame_hash_ab CSVs byte-identical to develop over 300 Doom gameplay frames and 400 yarc frames; gpu_idle_probe_falsify passes (the idle probe keys on index 53 after dispatch, as before). Measured on top of #1137, Doom gameplay from one savestate: - cachegrind (ir_ab.sh --ref, 300 frames): Ir -4.07%, D1 miss -4.13%, I1 miss +2.80% (GPUExec is larger), LL +0.16%. - Mac Studio M4 Max wall, test_benchmark 900 frames, A/B/B/A x3: avg 3.60 -> 3.38 ms (-6.1%), p99 4.3 -> 4.0 ms, every B run faster than every A run; yarc 3.39 -> 3.34 ms (-1.6%). Co-authored-by: Claude Fable 5.1 <[email protected]>