7 Commits
Author SHA1 Message Date
Brian Degenhardt bc33ef1d09 arm64: attribute yaps2 authorship in SPDX copyright headers
Add "yaps2 Dev Team" copyright to the files we authored. Net-new files
(all 42 pcsx2/arm64/ codegen/ProgCache/persist sources, the recompiler
test suite + harness, and the vurunner/eerunner tools) never existed
upstream, so they carry yaps2 sole credit. RecStubs.cpp predates the
fork and was heavily extended, so it keeps PCSX2 credit and adds yaps2.

The five pre-existing arm64 files we only lightly touched (AsmHelpers,
Vif_Dynarec, Vif_UnpackNEON) stay PCSX2-only. GPL-3.0+ license lines are
unchanged throughout; this is authorship attribution only.
2026-07-19 07:37:15 -07:00
Brian DegenhardtandClaude Fable 5 9d65d09a5f vurunner: game-faithful replay — vucap v2 records live config, replay honors it
The live emulator compiles VU code under defaults + GameDB + user INI; the
replay harness pins a deterministic subset. CHECK_XGKICKHACK, the VU clamp
bools, and the VU FPCRs change the COMPILED SHAPE of every block, so replaying
a capture under the pinned config validates different code than the game ran.
That exact blindness hid the Crash Twinsanity mVU_XGKICK_SYNC lost-write bug
(9ee69fc23) for weeks: GameDB forces XGKickHack=true for that game, and every
offline oracle pinned it false.

Close the class, not the instance:

- vucap v2: CapturedConfig block (44 bytes) after the FileHeader — disc
  serial + CRC provenance, gamefixes bitmask (GamefixId order now frozen,
  pinned by test), the six VU clamp bools, and a PORTABLE per-VU FPCR
  encoding (round|ftz|daz — the raw FPControlRegister bitmask is MXCSR on
  x86 / FPCR on aarch64 and captures must replay cross-arch). The probe
  snapshots the live EmuConfig into every capture. Reader accepts v1
  forever (zeroed, not-valid config).

- vurunner applies the recorded snapshot BY DEFAULT, per record (safe:
  PrimeFromCapture resets the block cache). Precedence: harness baseline <
  snapshot / --game <serial> (GameDB entry synthesized once via
  applyGameFixes + SnapshotConfig — covers the legacy v1 corpus) <
  --vu-clamp-mode / PCSX2_VU_XGKICKHACK. vuThread/vu1Instant/vuFlagHack are
  always re-pinned false (single-threaded harness, full-flag interp
  reference); dropping a game-requested one warns once. One stderr line per
  distinct effective config keeps batch stdout diffable. --no-game-config
  restores pre-v2 behavior.

pcsx2-eerunner needs nothing: it boots a full VM (EnableGameFixes defaults
true), so VMManager already applies GameDB there.

Verified: recompiler_tests 1127/1127 (v2 round-trip, v1 legacy read, 44-byte
+ gamefix-bit-order pins, SnapshotConfig mapping); Twinsanity wedge cap
--dump-asm grows 172→266 lines under --game SLES-52568 (the XGKICK sync
blocks) and an env-hack-ON re-capture replayed flag-free reproduces the
identical hack-ON shape from its recorded snapshot alone; 50-cap v1 corpus
slice byte-identical to pre-change behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 20:38:41 -07:00
Brian DegenhardtandClaude Opus 4.8 6ef7ad9bc9 pcsx2-vurunner: hash xgkicklastcycle in cross-JIT oracle digest
Widen HashArchSurface/DumpArchRaw with the one carried XGKICK *timing*
field, xgkicklastcycle (u64, both halves), gated under --hash-pipeline
alongside the flag pipeline. It is serialized by vu_capture and re-primed
by VuSnapshot::Restore, yet DiffVu's compare set omits it — a genuine
blind spot on XGKICK-in-loop programs (pc0x1748), where it is the one
cross-dispatch quantity the per-op architectural surface hides. Inert on
XGKICK-free programs (carries the primed value untouched), so it adds no
noise to the bulk of the corpus.

Verified participating: on the twinsanity pc1748 XGKICK loop the default
digest (a5253d62...) diverges from --no-hash-pipeline (7239f2bb...), with
lastcyc=0xfaad0eaf visible in the raw dump — and another implementation
agrees with it bit-for-bit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:41:03 -07:00
Brian DegenhardtandClaude Opus 4.8 68e92653a5 pcsx2-vurunner: hash carried microVU flag pipeline in cross-JIT oracle digest
--dump-jit-state's HashArchSurface hashed only the per-op architectural
surface (VF/VI/ACC + xgkick), not the carried microVU flag pipeline
(micro_{mac,clip,status}flags[4], pending_q/p). Those are serialized by
vu_capture and re-primed by VuSnapshot::Restore, so two JITs that agree on
VF/VI/ACC can still hand DIFFERENT carried state to the next dispatch —
exactly the blind spot that let the cross-JIT oracle stay green over an
E-bit STATUS-broadcast clobber (fixed in the preceding commit).

Add --hash-pipeline (default on) / --no-hash-pipeline to include/exclude
those fields in the reghash, and print them under --dump-jit-state-raw.
--no-hash-pipeline reproduces the old narrow digest (needed for
XGKICK-bearing/non-terminating caps run in batch, where the JIT leaks
carried state cross-cap — run those per-process). Mirrors DiffVu's
Strict-mode DiffPipeline().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:13:43 -07:00
Brian DegenhardtandClaude Opus 4.8 a187fdc0b6 tools/perf: M2-first CPU profiling rig + runner --perf-jitdump
Step 0 of the `neither` cherry-pick funnel: a repeatable, attributable,
wallclock-anchored CPU bottleneck baseline for our own ARM64 port, since the
RK3562-era numbers are stale and the target has shifted to Snapdragon 865.
Built and validated on M2 Max / Asahi first; the same scripts run on SD865 with
a new devices/<label>.env and no code change.

Test-harness change (no production code path, no shipped env gate):

- pcsx2-eerunner --perf-jitdump: emit a Linux perf jitdump under EmuFolders::Cache
  so `perf inject --jit` resolves EE_/VU0_/VU1_/IOP_/VIF_ block symbols. The enable
  is driven through the EmuCore/Profiler EnablePerfDump config bool (ApplySettings ->
  LoadSettings re-applies Perf::SetJitDumpEnabled every apply, so a manual enable
  would be reset). SetJitDumpDir is set before the first block compiles. Also honors
  an explicit `--renderer null` under --perf-jitdump for the CPU-only diagnostic.
- pcsx2-vurunner --perf-jitdump: same flag for VU-only captures (manual enable; the
  runner doesn't go through ApplySettings).

Tooling (pure stdlib + bash):

- tools/perf/bucket_perf.py: parse a `perf report --stdio` dump into a PCSX2
  subsystem ranking. Buckets tuned against real M2 R&C UYA / Katamari captures:
  JIT-by-prefix (EE/VU0/VU1/IOP/VIF) + VU-glue (mVUlookupProg / dispatch envelope) +
  native VIF + GS (incl. GIF decode + XXH3) + a GPU-driver bucket that quarantines
  the host Asahi/Vulkan/DRM stack (host-specific, NOT an SD865 proxy) + JIT-other
  (unsymbolized continuation blocks) + startup/io + a visible `unattributed`.
- tools/perf/profile_run.sh: one-command wrapper (precondition gate -> perf record
  -> inject --jit -> single report dump -> bucket -> median wallclock + median
  per-bucket share -> summary.md). Device/scene parameterized.
- tools/perf/devices/m2max-asahi.env: the working M2 incantation (P-core PMU
  apple_avalanche_pmu/cycles/, -F 999).
- tools/perf/scenes/*.env: R&C UYA + Katamari cinematic/gameplay scenes (assets are
  copyrighted, not checked in; paths reflect this dev box).

Validated on M2: go/no-go #1 (perf+jitdump resolves 277 JIT symbols) and go/no-go #2
(per-bucket shares stable across 3 runs) both green. First finding: on M2 the `vk`
profile is dominated by the Asahi GPU stack (GS thread ~57% of samples) — the CPU
shape comes from `--renderer null`, where VU (bodies+glue) is the largest emulation
cost.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:40:31 -07:00
Brian DegenhardtandClaude Opus 4.8 474e6c324d pcsx2-vurunner: cross-arch JIT-state dump + --vu-clamp-mode + cycle diff
Tooling to localize arch-specific VU codegen bugs by comparing arm64-rec
against the mature x86-rec over the same vu_capture corpus.

- --dump-jit-state[-raw]: per-capture FNV digest of the JIT architectural
  post-state (VF/VI/ACC/[VU1 xgkick]/VU-mem), basename-keyed so cross-machine
  path prefixes don't pollute a `diff`. Both microVU backends share a
  byte-identical cycle model, so the same capture+budget stops at the same
  guest insn on either arch -- post-states are directly comparable even for
  budget-truncated programs, the class JIT-vs-interp is structurally blind to.
- --vu-clamp-mode N: force EmuConfig VU clamp mode 0..3 (mirrors
  GameDatabase.cpp vuClampMode). The harness otherwise stays at default mode 1
  (vu0Overflow only), which never exercises the extra-overflow per-op operand
  clamp real games request via gamedb (e.g. SoulCalibur III vuClampMode:2).
- RunDiff also reports consumed-cycle divergence (gated on both engines
  hitting the E-bit) -- the EE<->VU0 timing quantity the reg/mem diff can't see.
- VuReplay records jit_cycles/interp_cycles deltas.
- x86 portability: guard the arm64-only progcache/persist includes+calls so
  the same source builds a native x86 vurunner for the cross-arch reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 14:09:37 -07:00
ff1abc36b8 arm64: SDL/kmsdrm frontend, headless runners, and handheld defaults (fork-only)
pcsx2-sdl (SDL3/kmsdrm handheld frontend), pcsx2-eerunner / pcsx2-vurunner headless
JIT regression+divergence tools, the gsrunner libmali CLI flags + Wayland scanner
wiring, and the heterogeneous-CPU thread-pinning default. Fork-only tooling/frontends.

Co-Authored-By: Ryan Walklin <ryan@testtoast.com>
Co-Authored-By: Brian Degenhardt <bmd@bmdhacks.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 20:27:56 -07:00