Commit Graph
2 Commits
Author SHA1 Message Date
CydandClaude Opus 4.8 ef4a0b67ac i860 emu: fix 6 core interpreter bugs; boot+velocirender_init+do_init now run clean
Worked the full-render marathon by tracing faults in the real VREND.MNG
firmware and matching them to the ground-truth AS860 assembly (VR_REMOT.S)
and C source (VR_REMOT.C). Six interpreter bugs found and fixed:

1. subs/subu direction: computed src2-src1; must be src1-src2 with
   CC=(src1<src2). Corrupted every subtraction, compare and bounds-check.
2. logical CC: all i860 logicals (and/andnot/or/xor + .h) set CC=(result==0).
   Had wrongly limited it to the AND family, so the `xor 0x0,rN,r0; bnc`
   zero-test idiom spun forever.
3. STORE encoding (the big one): i860 stores encode the SOURCE register in
   bits 15:11 (src1), not the dest field, and SPLIT the 16-bit offset across
   bits 20:16 (high) + bits 10:0 (low). The old decode saved the wrong
   register to the wrong offset, so function prologues never stored r1 and
   every `bri r1` return jumped to 0.
4. ld.b/st.b: op 0x00/0x01 = ld.b, op 0x03 = st.b (byte). Proven by byte-scan
   loops (r5 advanced by 1) and a save/restore pair at 0xf042b418 -> b430.
5. Mem page-span: r16/r32/w16/w32 crashed on 64KB page boundaries; now fall
   back to byte access across the boundary.
6. fmlow.dd (FP subop 0x21): the i860 has no integer multiply, so ints are
   ixfr'd into FP regs, multiplied via fmlow.dd, and fxfr'd back. Implemented
   as a 32x32 -> 64 multiply across the destination register pair.

emu_replay.py now runs the source-accurate init sequence: velocirender_init
on the init(0) command, then do_init before the first real command. Result:
boot idles at 0xf0400590; velocirender_init returns; do_init runs to
completion (~9200 steps of real allocator / name-table / scene-root setup).

Remaining blocker (documented in the tier-0 memory): create()'s switch needs
register-indexed integer loads (VR_REMOT.S: `ld.l r30(r31),r31`) together
with the correct .data link base (~0x1000, not 0) -- the two errors currently
cancel for the immediate paths but break the indexed jump-table dispatch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:35:44 -05:00
CydandClaude Fable 5 e28232e409 Tier 0 emulator: i860 interpreter boots VREND.MNG + runs real render code
emu860.py -- an i860 interpreter (reuses the dis860 decoder) that executes the
real Division firmware. This is the foundation of the preservation-grade
emulator (run the board's own code, vs the GL bridge which interprets the wire).

- Boots VREND.MNG cleanly: i860 init (psr/dirbase/fsr), enables the MMU, then
  idle-spins at 0xf0400590 waiting for a transputer interrupt (init complete).
  Board-config regs modelled (0xfffff720=2, 0xfffff70c=1) via map_control().
- Call harness (cpu.call): invoke firmware functions directly, bypassing the
  (un-emulated) transputer that normally drives the CCB.
- Correct memory map: .data/.bss linked LOW (DATA_BASE=0), so globals resolve.
- FP unit with double precision (register pairs): fadd/fsub/fmul/famov/frcp/
  frsqr/fix/ftrunc/fgt/feq/fxfr/fiadd/fisub.
- Delay slots, control regs, sparse MMIO memory with trap/logging, tail-trace
  and stopat debug aids.

draw_scene now runs real code (incl. a double int->float conversion) until it
needs accumulated scene state -- next step is replaying a captured wire command
sequence through the command dispatcher (jump table @0x47cb8) so the scene
builds and draw_scene emits the IGC coefficient stream (Tier-1 handoff).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:38:25 -05:00