ec82764bef
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>
136 lines
5.6 KiB
Markdown
136 lines
5.6 KiB
Markdown
# Ch285 closeout — syscall 0x40 HLE; next blocker is R5900 EI (COP0 funct 0x38)
|
|
|
|
**Status:** Closed. **Verdict from re-running qbert.elf:**
|
|
`elf_first_unsupported_opcode (pc=0x001000FC instr=0x42000038)` —
|
|
COP0/CO funct 0x38 = R5900 `EI` (Enable Interrupts), an EE-specific
|
|
extension to the MIPS COP0 CO sub-table. qbert advanced 27,091 →
|
|
**27,239 retires (+148)** — the biggest single-chapter jump since
|
|
Ch283. The PC dropped from 0x001113xx (deep into game code) back
|
|
down to 0x001000FC (early init), which means the syscall 0x40
|
|
return successfully unstuck qbert's setup phase and it took the next
|
|
hot block of work.
|
|
|
|
## What landed
|
|
|
|
A narrow HLE case for syscall `$v1 == 0x40` in `ee_core_stub.sv`'s
|
|
existing Ch273 dispatcher. Per Codex framing ("accept the
|
|
registration, return success, continue; don't over-trust the SDK
|
|
name"), the case returns `$v0 = 0` and resumes at `PC + 4`. Two
|
|
lines of new RTL surrounded by a comment block:
|
|
|
|
```sv
|
|
32'h0000_0040: begin
|
|
regfile[2] <= 32'd0;
|
|
gpr128[2] <= 128'd0;
|
|
pc <= pc + 32'd4;
|
|
retire_pulse <= 1'b1;
|
|
state <= S_IFETCH_REQ;
|
|
end
|
|
```
|
|
|
|
The standard PS2 kernel syscall table lists names in this slot like
|
|
`SetVCommonHandler` / `SetVTLBRefillHandler`. The observed call shape
|
|
(`$a0=0x001DFFC0` heap-ish, `$a1=0x0011C326` code-ptr-ish) is
|
|
consistent with a kernel-handler-install pattern. Real PS2 ROM
|
|
implementations of these calls return the previous handler pointer;
|
|
our stub returns 0 since (a) we don't store handler state, and (b)
|
|
qbert clearly doesn't use the return value as a function pointer
|
|
(it advanced 148 instructions past the call without re-trapping in
|
|
a wild jump).
|
|
|
|
If a future ELF needs the previous-handler return, this case can be
|
|
widened with $a0-keyed handler-pointer storage. Not warranted yet.
|
|
|
|
## TB — `tb_ee_core_syscall_hle.sv` extended
|
|
|
|
Existing TB extended with a 4th known case slot (`S_ORI_V1_40` /
|
|
`S_SYS_40` / `S_BNE_40` / `S_DS_40`) plus matching latch
|
|
(`v0_after_40` / `seen_40_return`) and the corresponding assert.
|
|
The display summary now reports `$v0_after_40` next to the other
|
|
three. Pattern identical to the existing 3C/3D/64 cases. The
|
|
unknown-syscall halt still terminates the test.
|
|
|
|
Result: `retired=21 halt=1 trap=0 errors=0 PASS`, with
|
|
`$v0_after_3C=0x001e0000 $v0_after_3D=0x00000000 $v0_after_64=0x00000000 $v0_after_40=0x00000000 $v1_at_halt=0x00007777`.
|
|
|
|
## qbert progression
|
|
|
|
| Chapter | Blocker | retire_count |
|
|
|---|---|---|
|
|
| Post-Ch283 (PCPYUD + gpr128) | LD at 0x00113378 | 27,067 |
|
|
| Post-Ch284 (LD) | SYSCALL $v1=0x40 at 0x00111D24 | 27,091 |
|
|
| **Post-Ch285 (syscall 0x40)** | **`0x42000038` (COP0 EI) at 0x001000FC** | **27,239** |
|
|
|
|
The PC walking *backward* from 0x001113xx to 0x001000FC is a
|
|
positive signal — qbert took the syscall return and looped or
|
|
called back into earlier code, hit the next blocker there. 148
|
|
retires is the largest single-chapter jump on the qbert track
|
|
since Ch283's architectural pivot.
|
|
|
|
## Ch286 framing
|
|
|
|
Instr `0x42000038`:
|
|
- bits 31..26: `010000` = opcode 0x10 (COP0)
|
|
- bits 25..21: `10000` = rs/sub = 0x10 (COP0_CO — "coprocessor
|
|
command")
|
|
- bits 5..0: `111000` = funct 0x38
|
|
|
|
R5900 `EI` (Enable Interrupts). EE-specific extension to the MIPS
|
|
COP0 CO sub-table (alongside `DI` at funct 0x39, plus the standard
|
|
RFE/ERET/TLBP/TLBR/TLBWI/TLBWR/WAIT). Minimal implementation: NOP-
|
|
class it (no model state mutated), PC += 4. We could optionally set
|
|
`status[16]` (EIE bit) if a future test depends on the COP0 Status
|
|
view, but qbert almost certainly doesn't poll Status after EI —
|
|
it's calling EI as standard init noise.
|
|
|
|
Concrete Ch286 scope:
|
|
1. `localparam FUNC_EI = 6'h38; localparam FUNC_DI = 6'h39;`
|
|
2. `is_ei = is_cop0 && (rs_idx == COP0_RS_CO) && (func == FUNC_EI)`
|
|
3. (`is_di` analogous, in case the next chapter trips DI)
|
|
4. Add `!is_ei` (and `!is_di`) to the `(is_cop0 && !is_mfc0 && !is_mtc0 && !is_rfe)` is_nop_class exclusion.
|
|
5. Default execute path retires (PC += 4 via normal `retire_advance`).
|
|
6. Focused TB: encode EI, execute, verify no trap + PC advances + retire fires.
|
|
|
|
5-ish RTL edits. Pure NOP-class extension; no register effects in
|
|
the model.
|
|
|
|
## Files changed
|
|
|
|
- `rtl/ee/ee_core_stub.sv` — 1 new case in the syscall HLE switch
|
|
(~10 LOC with comment).
|
|
- `sim/tb/integration/tb_ee_core_syscall_hle.sv` — 4 new BIOS
|
|
slots, 1 new latch group, 1 new assertion, 1 expanded display
|
|
line.
|
|
|
|
No new TB, no new Makefile target; regression count unchanged at
|
|
**172/172**.
|
|
|
|
## Pattern review (15 chapters)
|
|
|
|
| Ch | Blocker | Edits | Pattern |
|
|
|-----|--------------|-------|---------|
|
|
| 271 | SQ | 5 | NEW 4-beat write |
|
|
| 272 | DADDU | 4 | NEW ALU-low-32 |
|
|
| 273 | SYSCALL HLE | 2 | NEW gated dispatcher |
|
|
| 274 | BEQL | 6 | NEW branch+squash |
|
|
| 275 | SD | 7 | REUSE SQ counter |
|
|
| 276 | DSLL | 4 | REUSE DADDU |
|
|
| 277 | BNEL | 6 | REUSE BEQL squash |
|
|
| 278 | PCPYLD | 4 | NEW MMI narrow-decode |
|
|
| 279 | LQ | 5 | REUSE LW path |
|
|
| 280 | PSUBB | 5 | REUSE MMI narrow (byte-SIMD new) |
|
|
| 281 | PNOR | 5 | REUSE MMI narrow + NOR arm |
|
|
| 282 | PAND | 5 | REUSE MMI narrow + AND arm |
|
|
| 283 | PCPYUD + gpr128 | architectural | NEW 128-bit shadow |
|
|
| 284 | LD | 5 | REUSE Ch283 multi-beat path |
|
|
| **285** | **syscall 0x40** | **~1** | **REUSE Ch273 dispatcher** |
|
|
|
|
Highest-reuse chapter on record. The Ch273 dispatcher was designed
|
|
to be extended — each new $v1 is one switch case. The +148 retires
|
|
shows the cost-to-progress ratio remains favorable.
|
|
|
|
## Regression
|
|
|
|
**172/172 PASS** (unchanged from Ch284; no new TB added in this
|
|
chapter, the existing tb_ee_core_syscall_hle was extended in place).
|