Commit Graph

5 Commits

Author SHA1 Message Date
MechaCat02
ac289bca5e [iterate-4A] jit M0: recompiler seam + in-process differential harness
Foundation for a staged PPC block-recompiler (plan: closure-threaded ->
Cranelift -> block-linking). No codegen yet — proves the integration seam and
the correctness harness before any lowering exists.

New crates/xenia-cpu/src/recompiler.rs:
- run_block: executes a DecodedBlock; M0 falls back to the interpreter's
  execute() for every opcode, so it is bit-identical to step_block. Later
  stages dispatch lowered ops here and fall back only for uncompiled opcodes.
- gates jit_enabled()/diff_enabled() (XENIA_JIT / XENIA_JIT_DIFF, cached).
- In-process differential harness (diff_step): the interpreter is AUTHORITATIVE
  (drives real ctx+mem, so a JIT bug can never corrupt a run); the JIT runs
  SPECULATIVELY on a ctx clone against OverlayMemory (writes buffered in a byte
  HashMap, reads fall through to real pre-block memory), then registers are
  compared. Blocks touching MMIO or sync_sensitive (reservation/barrier) are
  skipped — a device callback can't be run twice and reservation state is
  shared cross-thread. report_diff_summary() prints checked/skipped/mismatch.

Why in-process: the guest is only COARSELY deterministic — coord_idle_advance
ticks vsync from wall-clock when idle, so two separate runs are not bit-exact
and a cross-run signature compare would measure jitter, not JIT divergence.

Supporting changes: PpcContext #[derive(Clone)] (harness clears the speculative
clone's reservation_table Arc); is_mmio() on the MemoryAccess trait (default
false) + GuestMemory impl via find_mmio; execute() made pub(crate); run_superblock
routes the block body (DIFF->diff_step, JIT->run_block, else step_block).

Validated: full boot+movie XENIA_JIT_DIFF=1 run = checked 218.4M blocks,
skipped(mmio/sync) 511.6K (0.23%), MISMATCHES=0 CLEAN; movie plays (ADVreads=30,
tid25 resumes); diff-mode ~2x slower (test-only path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:25:18 +02:00
MechaCat02
68c0ee55ce fix(cpu): PPCBUG-123/124/125/126/161/162/566 XER TBC + lswi/stswi/lmw
Phase 6 batch 2 — XER TBC enabling + load/store-multiple cleanups.

- PPCBUG-123/124/161/566 (coupled): XER TBC field was unmodelled —
  `ctx.xer()` always returned 0 in bits 0-6, and `ctx.set_xer()`
  silently discarded any TBC writes. Result: `lswx` and `stswx` were
  permanent no-ops (the `while bytes_left > 0` loop never executed).
  Fix: add `pub xer_tbc: u8` to `PpcContext`; wire into `xer()` and
  `set_xer()`. Initialize to 0 in `PpcContext::new()`. lswx/stswx
  bodies are correct as-is once the infrastructure is wired.

- PPCBUG-125 lmw: PowerISA marks `lmw rT, D(rA)` invalid when rA is
  in [rT..31]; canary skips the write to rA to preserve the EA base.
  Now matches canary.

- PPCBUG-126/162 lswi/stswi: replaced `instr.rb()` with `instr.nb()`
  for the NB field. Both accessors return identical values today
  (bits 16-20), but the maintenance hazard from the misnomer is now
  removed. A future `rb()` type-system refactor would have broken
  lswi/stswi silently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 13:48:03 +02:00
MechaCat02
a107ac9ae7 fix(cpu): PPCBUG-151 add reservation_width discriminator to stwcx./stdcx.
Track lwarx vs ldarx reservation width in PpcContext as a u8 (4 = word,
8 = doubleword, 0 = none). stwcx. requires width==4; stdcx. requires
width==8. Cross-width pairs (lwarx + stdcx., ldarx + stwcx.) now fail
deterministically with CR0.EQ=0 instead of spuriously succeeding.

The width is held per-thread; the cross-thread reservation table keeps
its existing slot encoding because each host thread consults its own
ctx.reservation_width before committing.

Affected:
  PPCBUG-151  stwcx./stdcx. shared the same reservation slot without
              width discriminator; cross-width commits silently succeeded

Tests: lwarx_then_stdcx_cross_width_fails,
       ldarx_then_stwcx_cross_width_fails

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:44:48 +02:00
MechaCat02
c36cca14f9 xenia-cpu: VMX128, FPSCR, decoder split, scheduler, decode/block caches
Split the monolithic interpreter into cohesive modules: dedicated
decoder (decoder.rs) producing 8-byte DecodedInstr; opcode tables
(opcode.rs); explicit traps (trap.rs); FPSCR helpers (fpscr.rs);
overflow/carry helpers (overflow.rs); a 4 KiB-page-versioned decode
cache and basic-block cache (block_cache.rs); and a full VMX/VMX128
implementation (vmx.rs) covering AltiVec + Xenon's 128-bit extensions.

Add the parallel-execution substrate behind --parallel: a 7-party
phaser (phaser.rs) for round-based barrier sync, ReservationTable
(reservation.rs) for guest LL/SC, and the per-HW-thread scheduler
core (scheduler.rs) that owns ThreadRefs, runqueues, and pending IRQs.

Disassembler is now the single source of truth: disasm.rs gains the
full base + extended + VMX128 mnemonic set, with golden JSON fixtures
and a disasm_goldens test suite. Add a criterion-style interpreter
bench. context.rs grows the per-thread state the new modules need
(reservation slot, FPSCR, vector regs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 16:27:43 +02:00
MechaCat02
c694bb3f43 Initial commit: xenia-rs workspace for Xbox 360 RE
Rust reimplementation of the xenia Xbox 360 emulator targeting reverse-
engineering and preservation, initially scoped to Project Sylpheed.

Includes:
- XEX2 loader (LZX decompression, AES decryption, PE parsing)
- XISO / XGD2 disc image VFS
- PPC interpreter with 200+ opcodes and VMX128 decoding
- Static analyzer: functions, cross-references, labels, asm + SQLite output
- HLE kernel covering the xboxkrnl/xam subset used by Sylpheed init
- Debugger with in-memory and SQLite-backed execution tracing
- `xenia-rs` CLI with extract/dis/exec commands that produce cumulative,
  superset SQLite databases and opt-in instruction/import/branch traces

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-16 23:14:56 +02:00