Swapper microword bring-up — progress + handoff (CpuND5000 LLM → octobus/microcode team)¶
Date: 2026-07-22
Author: CpuND5000 (microword ND-5000 CPU) LLM session
Companion doc: SWAPPER-MICROWORD-DIAGNOSTIC-HANDOFF.md (the self-service loop mechanics)
Status of record for the microword track: memory nd5000-init-datatype-swapper-blocker.md
TL;DR¶
Self-drove the SwapperStartDiagnosticTests loop (run → read throw dump → add the missing
microword case → re-run). Swapper advanced 17 → 34 macro instructions (P 0x08000004 →
0x08000162). Fixed 6 microword gaps, all in CpuND5000.cs / OperandRouter.cs / the
dispatch map, full suite 189/189 green after each.
The 34-instruction stop is NOT a CpuND5000 bug — it is a privileged-instruction trap the microcode raises correctly because the harness's fake PCB doesn't set PIA. See "Current blocker" below. This one is the octobus/context lane.
Fixes landed this session (microword lane — all committed to the working tree on disk)¶
Files: Nuget/HackerCorpLabs.Emulation.CPU.ND5000/src/{CpuND5000.cs, OperandRouter.cs, Registers.cs,
DispatchEntry.cs, Generated/DispatchMapB30.g.cs}, docs/dispatch-map-b30.json,
tools/ND5000FieldGen/Program.cs, and the two test files.
| # | Macro stop | Root cause | Fix |
|---|---|---|---|
| 1 | A,SPEC,LA not implemented (RET_SU 0o4420) |
LA-latch (A_OP 111) unmodeled | Added Registers.La; LOADLA primes it from P; A,SPEC,LA reads, D,SPEC,LA (dest 44) writes |
| 2 | Operand specifier 0xF8/desync → phantom "MON 0 LEAVE" |
CALL (0xC3) has a bare 4-byte direct operand[0] (call target), same class as INIT/ENT; was consuming 3 bytes not 6 → phantom execution | Allow-listed CALL (directMask=1, sizes=[4]) |
| 3 | Operand specifier 0xF5 not implemented (CALL/other) |
Pre-indexed addressing mode (0xF4–0xFF) unimplemented | Implemented pre-indexed in EnsureOcaDecoded: ea = I[n] + disp; ND-500 I1–I4 = microword X1–X4 = Wrf[0-3]; bits1-0 = reg, bits3-2 = disp width; no scaling (mirrors functional CpuND500) |
| 4 | Opcode 376 (0xFE) has no dispatch entry |
FetchAndDispatch only treated 0xFF as a 2-byte prefix |
Widened to b0 >= 0xFC — all of 0xFC/FD/FE/FF are 2-byte prefixes (CLRK = 0xFE03; 170/216/229/225 extended opcodes). 0xF4–0xFB in that range are only ever operand specifiers, never opcodes |
| 5 | D,MIC,RESTU not implemented (RETD 0o4416) |
dest 136 = "CLEAR STACK UNDERFLOW" | No-op (no STU status modeled; documented) |
| 6 | Data type 7 memory access (ENTS 0o270) |
ENTS is a type-less stack op → InstrDt=-1 → TYP,DR resolves to 7 |
dataType:0 override in dispatch map (same as INIT) |
Also added spin-detection + a SPIN DUMP to SwapperStartDiagnosticTests (breaks on the first
self-loop repeat so the ring shows the ENTRY path into a hang, not 16× the loop word).
Current blocker (34 instrs) — PIA, and it is NOT the microword CPU's fault¶
Symptom: at P=0x08000162 the swapper executes dctsb (0xFF1D, a privileged data-cache
instruction). Its microcode DCTSB_1 @ 0o12342 does AND MIC,STS, BM01, COND,MZRO → ILLEG. The
check fails, so it goes ILLEG (0o200) → ILLEG_01 (0o12530+) → DUMMY (0o103, a self-loop
"hang" state). The diagnostic now prints this as a SPIN DUMP.
Researched root cause (authoritative):
- BM01 = 1 << 1 = bit 1 (not bit 0 — earlier misread). MIC,STS = macrostatus register
(dest 84H).
- ND-05.020.01 (ND-5000 Hardware Description) Table 30: macrostatus bit 1 = PIA "Privileged
Instruction Allowed".
- ND-05.020.01 §4.3, p.73: "PIA … is a copy of the PIA-bit in the domain information table
of the currently executing domain … checked by microcode every time a privileged instruction is
executed."
Conclusion: dctsb is behaving correctly — a privileged instruction traps to ILLEG when
PIA is clear. The hang is a diagnostic-harness artifact: the harness posts a minimal fake PCB
(only P set) so the loaded macrostatus is 0 → PIA clear. SINTRAN's real swapper PCB runs in a
privileged domain with PIA set, so a real octobus boot very likely won't hit this.
Empirically confirmed the load path: seeding cpu.Regs.MicSts |= 0x02 directly still hung —
because CNTXTLOAD (0o14742+) reloads the whole macrostatus from the PCB (WRITEST1/
WRITEST2 @ 0o15001-2), overwriting the register seed. So the fix belongs in the PCB, not a
register.
Action for octobus/context lane¶
- Seed PIA (macrostatus bit 1) in the swapper's PCB macrostatus field in
SwapperStartDiagnosticTests(mimicking SINTRAN's privileged PCB), OR verify that the real octobus/SINTRAN boot path already sets it (in which case the diagnostic just needs to match). - The exact PCB macrostatus offset can be pinned from
CNTXTLOAD's ORCON-steppedRD,POFreads (0o14751+, AA=7 = EA3 = PCB base) feedingWRITEST1/WRITEST2. The CpuND5000 LLM can pin it on request. - After PIA is set, re-run the diagnostic —
dctsbshould retire and the swapper continue past 0x08000162.
Notes / open items carried forward¶
- INIT/ENT do not set macro register B (silent, no throw): there are ZERO dest-form
D,DAC,Bwrites in the whole B30 image; B is a DAC side-effect (or comes from context). Not blocking. See memory. - The
0o326ORCON listing bug (MICRO-5800-B30.mdrenders21, raw is0o41) still stands — trustnew Microword(Cs.Hi[a],Cs.Lo[a]). - Data type 6 (TYP,DD 128-bit) still absent from
AccessWidth(off critical path so far). - The domain/permit memory ops (
RD,ADOM/WR,ADOM) are collapsed to flat read/write — the NUCLEUS cross-process path is where a real domain select will eventually be needed.