Initial commit: retroDE_ps2 — first-of-its-kind PS2 GS FPGA core (DE25-Nano / Agilex 5)
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression (272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps, and all dump-derived textures/traces) is excluded via .gitignore and stays local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
# Ch290 closeout — syscall 0x12 HLE; paired syscall 0x16 surfaces with identical args
|
||||
|
||||
**Status:** Closed. **Verdict from re-running qbert.elf:**
|
||||
`elf_first_unhandled_syscall (pc=0x00112A74 $v1=0x16 (=22))` with
|
||||
arguments **identical to the syscall 0x12 call we just HLE'd**.
|
||||
|
||||
qbert advanced 27,930 → **27,950 retires (+20)** through the
|
||||
handler-install syscall and into a companion call that takes the
|
||||
exact same args. The strongest signal of the run.
|
||||
|
||||
## Codex's framing confirmed
|
||||
|
||||
Codex predicted "$v1=0x12 is a registration call, plausibly
|
||||
AddDmacHandler(5, fn, 0, ctx)". The runner-side observer
|
||||
captured the first occurrence:
|
||||
|
||||
```
|
||||
syscall_0x12 = seen=1 count=1 first_pc=0x00112a54
|
||||
$a0=0x05 $a1=0x00112ab0 $a2=0x00000000 $a3=0x001328c0 → $v0=0
|
||||
```
|
||||
|
||||
This is the classic 4-arg handler-install ABI: small slot index +
|
||||
function pointer + null ctx0 + context pointer.
|
||||
|
||||
## The paired-syscall signal
|
||||
|
||||
The next blocker after 0x12 is `$v1=0x16 (=22)` at PC 0x00112A74,
|
||||
**32 bytes (8 instructions) past the 0x12 call site**. Args:
|
||||
|
||||
| Reg | After syscall 0x12 | At syscall 0x16 blocker |
|
||||
|-----|--------------------|-------------------------|
|
||||
| $a0 | 0x00000005 | **0x00000005** |
|
||||
| $a1 | 0x00112AB0 | **0x00112AB0** |
|
||||
| $a2 | 0x00000000 | **0x00000000** |
|
||||
| $a3 | 0x001328C0 | **0x001328C0** |
|
||||
|
||||
**Identical.** qbert is calling syscall 0x16 with the literally
|
||||
same arguments it just passed to 0x12. The PS2 syscall table cites
|
||||
`EnableIntcHandler` / `EnableDmacHandler` (or similar
|
||||
"enable-just-registered" calls) in the 0x14-0x18 range. The
|
||||
pattern: `Add*Handler` registers, `Enable*Handler` activates.
|
||||
|
||||
This is a Ch291 candidate with very high confidence:
|
||||
- Same Ch285 precedent: accept ($v0 = 0, PC += 4).
|
||||
- Parallel observer in the runner.
|
||||
- One more switch case in the dispatcher.
|
||||
|
||||
## What landed in Ch290
|
||||
|
||||
### Dispatcher case — `rtl/ee/ee_core_stub.sv`
|
||||
|
||||
One new case (the 6th overall) in the Ch273 HLE switch:
|
||||
|
||||
```sv
|
||||
32'h0000_0012: begin
|
||||
regfile[2] <= 32'd0;
|
||||
gpr128[2] <= 128'd0;
|
||||
pc <= pc + 32'd4;
|
||||
retire_pulse <= 1'b1;
|
||||
state <= S_IFETCH_REQ;
|
||||
end
|
||||
```
|
||||
|
||||
Per Codex: do NOT invoke the handler function, do NOT mutate
|
||||
DMAC/INTC state. Just accept the registration and observe what
|
||||
qbert demands next.
|
||||
|
||||
### TB extension — `tb_ee_core_syscall_hle.sv`
|
||||
|
||||
Same mechanical pattern (slots / latch / assertion / display) used
|
||||
for the Ch285 0x40 and Ch289 0x78 extensions. The TB now covers
|
||||
six known syscall numbers (3C / 3D / 40 / 64 / 78 / 12). Result:
|
||||
```
|
||||
$v0_after_3C=0x001e0000 $v0_after_3D=0x00000000 $v0_after_64=0x00000000
|
||||
$v0_after_40=0x00000000 $v0_after_78=0x00000000 $v0_after_12=0x00000000
|
||||
$v1_at_halt=0x00007777
|
||||
```
|
||||
|
||||
### Runner-side observer — `tb_ee_core_elf_runner.sv`
|
||||
|
||||
Parallel to the Ch289 0x78 observer. Same shape: detect retire of
|
||||
SYSCALL with $v1 = 0x12, snapshot PC + $a0..$a3 on first occurrence,
|
||||
emit a SUMMARY line. Worked first try — `syscall_0x12 seen=1
|
||||
count=1 ...`.
|
||||
|
||||
The two observers (0x78 and 0x12) form a small library of "this
|
||||
HLE'd syscall is worth surfacing." The pattern is mechanical and
|
||||
the SUMMARY block now self-documents what qbert is calling the
|
||||
kernel for. As more syscalls accumulate, the SUMMARY becomes a
|
||||
running ledger of qbert's init sequence.
|
||||
|
||||
## qbert progression
|
||||
|
||||
| Chapter | Blocker | retire_count |
|
||||
|---|---|---|
|
||||
| Post-Ch287 (DMAC ctrl) | unmapped 0x1000C000 | 27,912 |
|
||||
| Post-Ch288 (DMAC passive) | syscall 0x78 | 27,920 |
|
||||
| Post-Ch289 (syscall 0x78) | syscall 0x12 | 27,930 |
|
||||
| **Post-Ch290 (syscall 0x12)** | **syscall 0x16 at PC 0x00112A74 (identical args)** | **27,950 (+20)** |
|
||||
|
||||
The +20 retires include the 0x12 syscall return + 8 instructions
|
||||
of setup (likely loading the same args back into $a0/$a1/$a3 from
|
||||
some register holding pattern, or just executing the second call
|
||||
that already had them in place) + the 0x16 syscall trap.
|
||||
|
||||
## Ch291 framing — syscall 0x16
|
||||
|
||||
Args identical to syscall 0x12 — the pattern Codex predicted at
|
||||
Ch290 (registration accepted; next demand will tell us if the
|
||||
handler needs to actually fire). The simplest hypothesis: 0x16 is
|
||||
`Enable*Handler` for the registration that just landed.
|
||||
|
||||
First-pass scope:
|
||||
1. Add `$v1 == 0x16` case to dispatcher: $v0 = 0, PC += 4.
|
||||
2. Parallel observer in the runner (same template as 0x78/0x12).
|
||||
3. TB extension (7th case).
|
||||
|
||||
If qbert then goes on to *poll* for the handler to fire — e.g.,
|
||||
read DMAC D_STAT looking for a channel-5 interrupt bit — then
|
||||
Ch292 has to model the handler-invocation path (real interrupt
|
||||
delivery, COP0 Cause/Status, the registered fn_ptr being called).
|
||||
|
||||
But based on the identical args + Ch285 precedent, $v0=0 is the
|
||||
right shape for the first pass. Let qbert's next demand tell us
|
||||
what's needed.
|
||||
|
||||
## Pattern review (20 chapters)
|
||||
|
||||
20 chapters in: Ch271 + Ch290 = 12 retires → 27,950 retires
|
||||
(2,329× advance). The syscall HLE dispatcher now handles SIX
|
||||
distinct $v1 values, each added in one chapter. The runner-side
|
||||
observer pattern (Ch289/Ch290) makes the diagnostic free.
|
||||
|
||||
## Files changed
|
||||
|
||||
- `rtl/ee/ee_core_stub.sv` — one new HLE case (~10 LOC).
|
||||
- `sim/tb/integration/tb_ee_core_syscall_hle.sv` — extended with
|
||||
syscall 0x12 case.
|
||||
- `sim/tb/integration/tb_ee_core_elf_runner.sv` — syscall_0x12
|
||||
observer + SUMMARY line.
|
||||
|
||||
No new TB, no new Makefile target; regression count unchanged at
|
||||
**175/175**.
|
||||
|
||||
## Regression
|
||||
|
||||
**175/175 PASS** (unchanged from Ch289; no new TB).
|
||||
Reference in New Issue
Block a user