ND-500 <-> SINTRAN 5MPM Mailbox Message Catalog¶
Full path: E:\Dev\Ronny\NDInsight\SINTRAN\ND500\ND500-MAILBOX-MESSAGE-CATALOG.md
Compiled 2026-07-16 from a full-source sweep (NPL driver docs, system-monitor carve, swapper RE,
symbol tables, manuals). Purpose: the specification for reimplementing the ND-500 microcode's
mailbox servicing as C# logic in the RetroCore emulator (the emulated CpuND500 is a MACRO-
instruction emulator; microcode behavior must be code). Companion:
ND500-WHO-ANSWERS-THE-MAILBOX.md (who services it), ND500-CS-LOAD-TRACE-FINDINGS-2026-07-16.md.
Scope: classic ND-500 (3022/5015, DMA/MAR). Evidence grades per repo convention: BYTES / SYMBOL / NPL (different revision - logic only) / MANUAL / INFERRED.
Two structural cautions (load-bearing):
- The authoritative field-offset source is swapper\N500-SYMBOLS.SYMB (SYMBOL) cross-checked with
SINTRAN\NPL-SOURCE\SYMBOLS\{L07,M06}\N500-SYMBOLS.SYMB.TXT + NPL AAX <sym>; LDATX usage.
Flat, alphabetical, 5-char truncated - a value is proven, "is a message offset" is INFERRED from
usage. Validated via known slots STOPR=11, TRAPN=16.
- MP-P2-N500.md section 7.6 "Message Buffer Fields" is a DIFFERENT, CONFLICTING table
(5MSFL=0, XADPR=1, FUNCV=2, ... N5STA=15) - most plausibly the ND-100 process-descriptor/MESSBUFF
working layout, NOT the 5MPM block. Do NOT implement from 7.6.
1. Message header - field table (octal word offsets), per-direction overlay¶
Block lives in ND-100 physical memory, bank 5MBBANK (XMSINIT: 5FPMAILBOX =: D:=0; AD SH 12).
Message size 55MESSIZE = 200B = 128 words (SYMBOL). Header = 6 words + data part (MANUAL
ND-05.012.01 sec 13). MAR carries the message's ND-100 WORD address (live-proven).
| Off | Symbol | Meaning | Grade |
|---|---|---|---|
| -1 | 5MSFL |
flags: 5IEXQUEUE=bit15, 5SYSRES=14, 5CPUBOUND=13, + 5IBRK, 52ESCSET, 5ITMQUEUE |
SYMBOL+NPL |
| 0-1 | LINK/LINK2 |
forward queue link (double word, LINK@3) |
SYMBOL+NPL |
| 2 | N5STA |
status word (values sec 3.4); NPL reads it TWICE with cache-flush (BSET BCM 120 DX, "fool the cache", MP:1874) |
SYMBOL+NPL |
| 3 | SENDE |
sender; watchdog = -1 (RP:821) | SYMBOL+NPL |
| 4 | X5CPU |
receiver/CPU; precondition = MPACTIVE (MP:3061) |
SYMBOL+NPL |
| 5 | X5ACT |
size/activation; zeroed in ACT51 (MP:3027) | SYMBOL+NPL |
| 6 | MICFU |
the command the ND-500 executes (sec 2) | SYMBOL+NPL |
| 7 | N500A |
ND-500 logical address (transfer descriptor); MESSB=7 in the mailbox-header overlay |
SYMBOL+NPL |
| 11 | N100A/STOPR/ACPRO/KFLIP |
overlay: transfer=ND-100 phys addr; answer=stop reason; also actual-process / error-flag (MONICO) | SYMBOL+NPL, overlay INFERRED |
| 12 | NUMPA |
number of params / write-back mask (MONICO clears; 5ACTSWAPPER writes 6; MCHANDLE write-back count) | SYMBOL+NPL |
| 13 | NRBYT/MCNO/FUNCV |
overlay: transfer=byte count; MON-call answer=mon-call number; restart=function return value (MONICO) | SYMBOL+NPL |
| 14 | MSWMC |
swapper-monitor-call subfield | SYMBOL |
| 16 | TRAPN |
trap number (fault activation reads it, MP:762) | SYMBOL+NPL |
| 22 | MAILINK |
exec-queue head (datafield field); LEXQUEUE=14 = queue length |
SYMBOL |
| 37 | SMCNO |
saved mon-call number (MCHANDLE copies MCNO here, MP:1302) | SYMBOL+NPL |
| 57 | CNTXP |
per-message context page | SYMBOL |
| 140 | ABUFA |
auxiliary buffer address | SYMBOL |
| 143 | SPFLA |
special flag: nonzero -> DECOMESS jumps to that ROUTINE ADDRESS (dispatch override) | SYMBOL+NPL |
| 144 | XADPR |
process-descriptor address (MCCO loads proc desc from it, CC:827) | SYMBOL+NPL |
| 147 | PLINK |
backward queue link (priority double-linked list) | SYMBOL+NPL |
Housekeeping negatives (low grade, SYMBOL): 5PRIO=-5, 5CPUN=-6, 500TU=-10 (CPU time used).
Offsets 11 and 13 are single slots with direction/type-dependent meaning - interpret per current
MICFU/N5STA. (Not a contradiction: flat symbol table holds all aliases at the same value.)
2. ND-100 -> ND-500 message types (MICFU codes, all SYMBOL-verified)¶
| MICFU | Symbol | Purpose | Built at (NPL) |
|---|---|---|---|
| 1 | 3RMICV |
read microprogram version - watchdog | RP:282/384/822 |
| 5 | 3SWMESS |
message to swapper (SWFUN field at off 7) | MP:2876 |
| 23B | 3START |
start process | MP:2991 |
| 24B | 3MONCO |
restart after monitor call | MP:808, CC:824 (MONICO), MP:2887 |
| 25B | 3TRACO |
trap continue | MP:808 |
| 26B | 3WMONCO |
wait monitor call | MP:808 |
| 27B | 3FITRNSF |
file transfer (uses N500A/N100A/NRBYT descriptor) | MP:2991 |
| 34B | 3MONO |
mon-call variant - semantics UNKNOWN | (symbol only) |
| 44B | 3RPREG |
read P register - histogram (HIMESS) | RP:803/811 |
| 46B | 33MON |
mon-call variant - semantics UNKNOWN | (symbol only) |
Also referenced, numeric value unresolved: 3RMED/3WMEP (MP:839 error-answer decode).
General contract (MANUAL ND-05.012.01 sec 13, DERIVED - microcode internals are in NO SINTRAN
source): activate -> leave IDLE -> DMA-fetch message at MAR -> N5STA:=WAITING(2) -> execute MICFU
-> write answer fields + N5STA:=ANSWER(3)/5ERANSWER(4) (preserve 160000B power-fail bits) ->
finished + level 12 (gated by CONTROL bit 0).
Per-type behavior:
- 3START: run the process from its saved P until it stops -> answer = a stop message (sec 3).
- 3MONCO: consume MONICO's write-back (FUNCV(13)=return value, KFLIP(11)=error flag,
NUMPA(12)=0) and resume the process past its MON call. THE reactivation of every round trip.
- 3TRACO / 3WMONCO: trap-continue / wait-variant; DECOMESS treats all four alike for STOPR dispatch.
- 3FITRNSF: bulk transfer via N500A/N100A/NRBYT; completion may stop with 5FMOCALL.
- 3RMICV (watchdog, SENDE=-1): return microprogram version, ANSWER(3). ND-100 side re-arms
the timeout (IFM500XQ, reset TMRXQ/TMR) - the answer just proves the microcode is alive.
- 3RPREG (HIMESS): sample ND-500 P register -> ANSWER(3) -> CHN5STATUS calls HISTSAMPLE.
Answer write-back rule (what the emulated microcode must write): N5STA:=ANSWER(3);
STOPR(11) = stop reason; MON call: MCNO(13) = MON number + params in the data part; trap:
TRAPN(16) + STOPR:=TRAPCODE(2); failure: 5ERANSWER(4). (NPL/DERIVED - constrained by what
SINTRAN reads, sec 3.)
3. ND-500 -> ND-100 (microcode-written stop/answer messages)¶
3.1 STOPR values (offset 11)¶
MOCALL=1 (monitor call), TRAPCODE=2 (trap), 5FMOCALL=3 (file-transfer MON call) - SYMBOL.
Others -> "restart ND-100 process". TPSTRA=65 UNVERIFIED.
3.2 The level-12 ISR chain (BYTES: 026-S3IMPIT @ 135010/135205/135361/137206)¶
5STDRIV: CPU alive check -> CLE5STATUS mask 177377 -> if status /\ 720B != 0 error path
(5PFAIL->BHPFAIL+KPOWDOWN, 5DMAERR->N5DMAERR, else N5IERR; all -> N500ERR -> XRSTARTALL) ->
else walk exec queue from MAILINK via LINK until -1, per non-DUMMESS message call CHN5STATUS
-> XACT500 -> WT12.
CHN5STATUS dispatch on N5STA (VERIFIED): ANSWER+HIMESS -> HISTSAMPLE; ANSWER+WATCHDOG -> re-arm timeout; ANSWER other -> DECOMESS; 5ERANSWER -> DECOERRMESS; >100B -> 5RRTWT (restart ND-100 proc); MSGN500/WAITING on the answer path -> XTER500 (terminate! inconsistency case).
DECOMESS (verbatim NPL logic): if SPFLA(143) nonzero -> A=:P (jump to that address).
Else read MICFU: if in {3MONCO,3TRACO,3START,3WMONCO} read STOPR: MOCALL/5FMOCALL -> MCHANDLE,
TRAPCODE -> TRAPDECODER, else 5RRTWT. Else 5RRTWT. Then NXTMSG.
MCHANDLE/MCHANDEL (X=msg, T=stop reason, B=CPU datafield): read MCNO(13) -> save to
SMCNO(37) -> special-case 347B -> 5SERV(050211B) -> range L12MIN=500B..L12MAX=523B ->
MBSUSPROC -> GOSW (byte-proven table @137625B: 500 STAPR/SWITP, 501 NSTOP, 502 SWITP, 503 NINST,
504 NOUTS=141027 (bytes; NOT OSTRS), 505 GERRC, 506 5SIBM, 507 SPRIO, 510 SWMC,
511 DVIO/NOUTS, 512/513 A5XMS/B5XMS, 514 M5TMO, 515 5MTRA, 516-523 -> NORMM=137167 unimplemented).
Out of range -> NORMM -> 5RRTWT.
3.3 MONICO/MCCO restart write-back (CC:359-372, VERIFIED - the emulated microcode CONSUMES this)¶
OKMONICO: T:=0 / EMONICO: T:=1 (error)
MONICO: FUNCV(13) := function value; KFLIP(11) := error flag; NUMPA(12) := 0
MICFU(6) := 3MONCO
MCCO: N5STA(2) := MSGN500(1) (WN5STATUS)
proc-desc := [XADPR(144)]; PSTAT := 5ACTIVE (clear run status)
5ADP3, NUMPA:=4, FUNCV/KFLIP cleared, MICFU:=3MONCO.
3.4 N5STA values¶
0 free (INFERRED) | 1 MSGN500 | 2 WAITING | 3 ANSWER | 4 5ERANSWER |
swapper states: SWPWAIT=5, SWPPING=6, PSWWAIT=7, PSW1WAIT=15 | high bits 160000B = power-fail
flags, ALWAYS preserved (A/\160000\/MSGN500, MP:992) | >100B = restart-ND-100-process class.
4. The swapper message family¶
- ND-100 -> swapper:
SWMSGbuffer @110054B (SYMBOL). Admin fields:SWPFU=101, RETP2=102, SWPST=103, HSWPI=104, SWPIN=105(+ SPFLA/XADPR). 5ACTSWAPPER (MP:2851-2908):HSWPI:=&MSGTOSW,SWPFU:=SWACTIVE(state marker, NOT the function code),SWPST:=SWFUN(from MSGTOSW off 7, or TRAPN on the fault path) - the swapper dispatches on SWPST (earlier SWPFU guess REFUTED),NUMPA:=6, FUNCV:=0, MICFU:=3MONCO-> MCCO -> XACTRDY. - SWFUN namespace = MSW* (29 codes 0..34B, SYMBOL): MSWFI=0, MSWUF=1, MSWSO=2, MSWMI=3, MSWMD=4, MSWIN=5, MSWPO=6, MSWSTART=7, MSWFO=10, MSWIP=11, MSWPFAULT=12, MSWME=13, MSWMC=14, MSWSP=15, MSWSG=16, MSWIS=17, MSWRS=20, MSWWB=23, MSWSWAIT=24, MSWPR=33, MSWDO=34. Only the bold four have NPL comments; the rest are truncated - semantics OPEN.
- The swapper's own 29-entry dispatch (BYTES,
swapper\swapper-k01-handlers.md): function code at DSEG 0x240B8, bound <=34B, jump table at DSEG 0x26198. Handlers: 0 free-slot, 1 release-WS, 2 copy-desc, 3 release-range, 4 deep swap-in/out scan, 5 init/activate WS, 6/7/16/25/26/27 shared generic swap request (fixed sub-code 66B via MON 377B sub-fn 2), 8 connect/page-in (RPHS), 9 alloc+link, 10 page-fault accounting, 11/12/20 NO-OP, 13 link desc, 14/15 attach/detach, 17 reinit tables, 18 set config, 19 swap/fix by id, 21 set desc fields, 22 page-in WS, 23 UNKNOWN, 24 create desc, 28 perform swap (MSWDO). - Swapper -> ND-100 = MON 377B (N5SWAP), decoded by SWPDECODER (MP:913):
SWPFU <= SWFMAX=6-> GOSW: 0 ESWPFATAL, 1 LNEWSWAP(argc4), 2 LSWPAGE(argc7, disk transfer - dominant), 3 LPRSUSPEND, 4 LALLOPAGE(argc6), 5 LDATREADY(argc3), 6 LCLTSB(argc2).SWPFA=2047B-> fatal. Disk work runs on the ND-100 (RT prog 5SWAP/5SWRT: reserve proc 0, ABSLI MON 131, wait PSW1WAIT). Swap-wait FIFO: X5MXF/X5SWF/X5SWT/X5SWB in X500DF; SWPD4 drains at PSWWAIT.
5. Queue / special mechanics¶
- Insert/remove:
ITO500XQ(set 5IEXQUEUE, priority-insert LINK/PLINK, LEXQUEUE++; semaphore must be held),IFM500XQ(reverse),FR5TMQ(time queue). ND-5000: ITOFIFOQ ring. - Walk:
MAILINK->LINK@3until -1, physical reads via 5MBBANK. DUMMESSis the ADDRESS of a sentinel message (set in XMSINIT), not a constant; walkers skip it by address compare. (7DUMM=30is unrelated - do not conflate.)- Watchdog: SENDE=-1, MICFU=3RMICV; its ANSWER re-arms TMRXQ/TMR. The emulated microcode must complete every operation + release the lock in finite time or SINTRAN times out and master-clears.
- XMSINIT builds: zeroed mailbox area (5NPMAILBOX pages), per-process message buffers (proc-desc MESSBUFF -> its message; 55MESSIZE=200B words each), HIMESS, WATCHDOG, SWMSG, DUMMESS sentinel, swap FIFO. Count is install-dependent, not fixed.
- ACT50 + preconditions, TERM5/X5MCST teardown: see bus reference sec 5/9 +
ND500-CS-LOAD-TRACE-FINDINGS-2026-07-16.md(MAR = WORD address; strobes on IOX READ). - SLOCK/SUNLOCK semaphore = ND-5000 only (no-ops on classic).
6. UNKNOWNS - carve before coding (no guessing)¶
3MONO=34B,33MON=46Bmicrocode semantics.- RESOLVED 2026-08-10 (
CARVE-ANSWER-RESULT-BLOCKS-2026-08-10.md): the "answer result block at 40B-47B" is NOT a message structure - the FUNCS,X 40/41/43/46/47stores are the MON 60 info block parameter records5DD1..5DD5(values @ 40/43/46/51/54B) +5P1..5P5(user addresses @ 42/45/50/53/56B), baseB-11 = S500DF-ZPREG = 165777B[V bytes + L07 SYMBOL]. The per-command mailbox ANSWER offsets (what the emulated microcode must write) are in that carve doc: 16B/17B register value @ msg 10B-11B, examine answers @ msg 11B-12B, 3RMICV version @ msg 7 + CPU parameter @ msg 10B (cached to CPUDF[20B] by CSLOA's post-load verify). TPSTRA=65stop reason - UNVERIFIED.- Exact microcode step sequence per MICFU - DERIVED only; the C# model is constrained by what SINTRAN reads back. Pull ND-05.012.01 sec 13 full text if more fidelity is needed.
- ~24 MSW* swapper function codes lack names/semantics.
- Swapper generic sub-code 66B (fn 6/7/16/25/26/27): meaning to the 5SWAP receiver UNKNOWN.
- Swapper handler idx 23 target UNKNOWN.
3RMED/3WMEPnumeric values unresolved.- Swapper physical WRITE-back primitive unknown (RPHS reads only; no WPHS found).
MCHANDELvsMCHANDLEvs alleged alias5MONICO- alias uncited.- MP-P2-N500.md section 7.6 field table CONFLICTS with the symbol layout - do not implement from it.
7. Microcode-side cross-check (ND-5800 MICRO-5800-B30 disassembly, added 2026-07-16)¶
Source: E:\Dev\Ronny\ND5000UC\microcode\MAILBOX-MICROCODE-PSEUDOCODE.md (full pseudo-C of the
mailbox servicer with per-microword evidence grading; [V]=verified in listing, [D]=derived,
[X]=cross). Caution: that image is the ND-5800 (SAMSON/Octobus) revision — the SINTRAN-facing
protocol matches, but the MICFU table has generational differences (below).
Confirmations of this catalog from the actual microcode:
- Read order in the fetch path matches the symbol layout exactly: N5STA check (must be 1) ->
CPU-target check (matches X5CPU=MPACTIVE precondition) -> MICFU -> vectored dispatch [V].
- N5STA := WAITING(2) is written unconditionally BEFORE executing the MICFU [V value].
- Answer values: success SC10 := 3 (ANSWER), illegal/reject SC10 := 4 (5ERANSWER) [V].
- Queue walk terminates on link = -1 [V] (matches "LINK until -1", sec 5).
- MICFU is range-checked to 0..77B (64-entry dispatch table); bit 15 of the MICFU halfword is
stripped before dispatch (flag, not function number) [V/D].
- 3RPREG=44B confirmed: handler MSG_HISTOG reads the ND-500 P register (A,IAC,P) into the
answer [V] — exactly the HIMESS histogram sample.
- 3RMICV=1 (MSG_VERSRD) answers two halfwords: microcode version (0o27232 in B30) + a
CPU-parameter halfword from microcode-internal state [V]. If DECOMESS/watchdog only reads one,
the second is don't-care — carve to decide what the emulator must write.
- Classic ND-500 oracle (Ronny, 2026-07-17): a genuine classic image (e.g. the incoming
10509/10609 floppy) must SELF-REPORT its version 10509/10609 through READ MICRO PROGRAM
VERSION — i.e. the version halfword comes FROM the loaded control-store image, so the
emulator's 3RMICV answer must be sourced from the loaded image, not a constant.
- 3START(23B) and 3TRACO(25B) dispatch to the SAME handler [V]. 3MONCO(24B) delivers the restart
value into the process's X1 register before resuming macro execution [V destination register;
that it equals FUNCV(13) is the plausible but uncarved link]. 3WMONCO(26B) additionally
block-copies answer data into process memory before resuming [V flow].
Resolves (partially) UNKNOWN #1 — but on the 5800 image only:
- 3MONO=34B -> handler MSG_IMEMRD: instruction-memory block READ (word-aligned only, else
5ERANSWER). NOT a mon-call variant.
- 33MON=46B -> handler MSG_DUDC: dump-dirty + clear data cache. NOT a mon-call variant.
- (Whether the classic-500 microcode assigns 34B/46B the same way is UNVERIFIED.)
Generational discrepancies (B30/5800 vs this catalog's classic-500 scope) — do not code either
way without deciding which machine is being emulated:
- MICFU 05 (3SWMESS) -> MSG_ILLEG in B30. The 5800 swapper delivery evidently does not use
MICFU 5 (SWMSG delivery on the 5800 may ride 3MONCO/SWPST only, per sec 4's 5ACTSWAPPER which
already sets MICFU:=3MONCO).
- MICFU 27B (3FITRNSF) -> MSG_ILLEG in B30.
- Extra B30 MICFUs with no entry in sec 2 (SINTRAN may never send them, or symbols not yet found):
10/11B DMEMRD/DMEMWR (data-memory copy in process context), 12B CACHE, 13/14B RESIRD/RESIWR,
22B STARTP0 (start swapper/process 0), 30/31B PHYSRD/PHYSWR, 35B IMEMWR, 42B PRT, 45B CLEAR,
47B IDLE (drop process, go idle), 50-52B UNIX-500 context ops, 70-75B trace-memory family,
76B CACI (cache inhibit), 77B LOOKSRF (debug SRF read).
Doorbell (5800/Octobus form): answer completion strobes ACCP command word 100401B; activation
arrives as OCB command 100501B (or vector codes 1/2). On the classic 500 these correspond to the
level-12/ident path and CONTROL-activate respectively [X].
7b. MON-call EXIT path — DECODED in the B30 microcode (2026-07-16)¶
Closes this catalog's "exact microcode step sequence" gap for the outbound direction. Full
pseudo-C: MAILBOX-MICROCODE-PSEUDOCODE.md sec 3.8. All [V] in the B30 listing unless noted.
- Recognition is a TRAP, not an opcode. A
CALLGwhose target lies in the monitor entry table (manual encodingEQU 37B9+n— "segment 31") raises an instruction-fetch trap; trap code 6 -> CALL_MON (@003744), trap code 7 -> CALL_DOM (cross-domain). Dispatcher: TRAP_MONC @012740. - MCNO = low halfword of the CALLG target address (read from NPC) — i.e. the entry-table layout puts the MON number in the address low bits [V read; encoding cross [X]].
- Parameters: per CALLG argument, the microcode fetches the operand specifier (G,OPS) and writes an (address, value) word pair into the message data part (CALL_MON8 loop @003772-004000). Arg count comes from the CALLG (held in LC), bounded <= 16.
- Output-call fast data: for MCNO 504B/511B/512B (= GOSW NOUTS/DVIO/A5XMSG) the user's buffer is inline-copied into the message before stopping (CALL_5XX/CALL_5_MATCH) — the ND-100 gets the bytes without a second fetch.
- Header write — byte-matches this catalog's consecutive slots: saved P (word, offset
not yet pinned), then
STOPR(11) := MOCALL(1),NUMPA(12) := argc,MCNO(13) := n(CALL_MON9 @004007-004011), thenP := Lso 3MONCO resumes after the CALLG. - Delivery: the stop is an ANSWER to the process's OWN activation message (address kept
in microcode state since the fetch):
N5STA := ANSWER(3)+ doorbell (CALL_END9 -> MSG_END0). MICFU is left unchanged — exactly why DECOMESS accepts any of {3MONCO,3TRACO,3START,3WMONCO} and dispatches on STOPR. - Microcode-shortcut screening before answering (CALL_END @013613): 270B/271B/333B/335B/ 500B dump the dirty data cache first (DMA coherency; 333B = the UDMA special); 501B/502B/600B get local start/stop/swapper assists; one NDIX case answers and KEEPS EXECUTING (asynchronous MON call, CALL_NDIX @025401); 117B/120B/144B/201B take a wait variant (CALL_WF).
- Restart consumption byte-anchored on the microcode side too: on 3MONCO the microcode moves the function value into X1 (@015721) and the error flag into the K flag (K,ZRO/K,ONE @015727/015731) — matching MONICO's FUNCV(13)/KFLIP(11) write-back and the manual's CALLG error convention ("IF K GO Error", code in W1).
- ~~Still open: the trap-stop writer~~ TRAP STOPS DECODED 2026-07-16 (pseudo-C doc
sec 3.9). Summary:
- Trap collection: TRAP_SAM gathers ALU/MIC/IDU status; trap number = IDU status low byte; a 5-word trap record is parked in the SRF trap area (0o40).
- Triage (TRAP_FIND): per-process context block (base 0o4000) + system enable registers decide: (a) LOCAL macro trap handler via the domain's DIT (handler address table, per-trap enable bytes — TRAP_ENT/TRAP_START set P and resume macro execution), or (b) STOP to the ND-100, or (c) out-of-band OCB message.
- The stop writes into the process's OWN message, same as a MON stop:
STOPR(11) := TRAPCODE(2)(TRAP_GEN1 @013513 / TRAP_GEN4B @013571), saved P,TRAPN := trap number(TRAP_GEN4C @013574; page fault = 0o46), plus status words and the trap record in the data part (TRAP_GEN2/3). TRAP_END then answersN5STA := 3 (ANSWER)— or 4 (5ERANSWER) if the run-state flag says the process wasn't running — and rings the doorbell (MSG_END0). - A SYSTRA halfword (SRF cell 0o2004) marks "system traps": those ALSO emit an out-of-band OCB message type 201B built by the microcode itself through ACCP_XWRITE (matches manual: "message built by the microprogram, sent directly through the ACCP"). Other OCB codes: 203B CPU-unavailable (MSG_START refusal path via CPU_AVAIL? on SRF cell 0o2016), 204B/205B/206B/210B protocol/not-recognized errors.
- Page fault (0o46): if no local handler, TRAP_GEN4 stop plus TRAP_SWAP — a message to the swapper is built in the START_MESS area (0o20000): demand paging stops to the ND-100 and/or wakes the swapper.
- Still open (fine-grain): TRAP_GEN3 exact word map (where TRAPN@16 + fault params land), TRAP_OCB00..20 per-subtype payloads, saved-P offset, DIT layout, full trap-number list.
7c. 13B/14B RESIRD/RESIWR field layout + INIT_SAMSON verdict (microcode answer 2026-07-17)¶
Source: MICROCODE-ANSWER-INIT-SAMSON-AND-13B-2026-07-17.md (lossless B30 listing, all [V]):
| Message word offset (octal) | 13B RESIRD | 14B RESIWR |
|---|---|---|
| 7-10B (32-bit word, hi first) | source: ND-500 address | dest: ND-500 address |
| 11B-12B (32-bit word, hi first) | dest: physical (MMS) address | source: physical (MMS) address |
| 13B (halfword) | byte count (rounded up to words) | byte count |
- Both are PURE BLOCK COPIES - no content generation, no validation; TRAPN(16B) is never read (the live trace's TRAPN=10746B in 13B requests is leftover buffer garbage).
- The ND-500 address is the FULL 32-bit word at offsets 7-10B. The live msg-5 "N500A=177B" therefore decodes as high half 177B -> source likely 0x7F0000 (just under the 8MB top) - INFERRED: a memory-SIZING probe, matching "Error in memory configuration". [I]
- INIT_SAMSON writes NOTHING into ND-500 memory 0-2048 [V]: it clears SRF/caches/TSBs, reads SYSPAR from the ACCP, composes CPUPAR from the CPU model; all config constants live in the microword patch panel 000020-000037 (VERSION=027232B etc.) - in CONTROL STORE, not RAM. Whatever SINTRAN validates at ND-500 addr 0 was placed there by the ND-100 itself.
- After servicing, the microcode ONLY writes N5STA:=3 + doorbell - it never touches 3022 register state. (Live trace: SINTRAN polls RSTA5 for ~340ms right after MICRO-START, reading $0, before sending the first 13B - what it waits for is an OPEN question on the 3022/SINTRAN side, not the microcode.)
- Emulator status 2026-07-17: 13B corrected to the 32-bit source decode; 14B implemented (was silently dropped -> 5ERANSWER); 14B->13B round-trip unit-tested.
- LOAD-SWAPPER wire sequence (OBSERVED live 2026-07-17): the swapper image transfer = 44 x 14B RESIWR (2048-byte blocks into ND-500 0x5A000-0x6F000 + one 256-byte block to 0x24800; mostly zeros + code/data pages), then one MICFU=12B MSG_CACHE (param 147717B - conditional cache clears, B30 @015640) to make the freshly written code coherent, then one MICFU=21B (SENDE=1B, X5CPU=0B, N500A=0B). Rejecting ANY of these aborts the load SILENTLY ("Loading Swapper" repeats on every status/start-swapper, no error text; list-a-p shows process 1 magic 0). Emulator: 12B answered (no-op, no caches); 22B MSG_STARTP0 accepted; 21B still rejected = the current blocker (2nd trace run 2026-07-17: 21B is the ONLY 5ERANSWER; SINTRAN performs NO memory-based aliveness probe - the swapper-loaded verdict rides entirely on the 21B answer). NOTE: on the 5800 B30 image MICFU 21B dispatches to MSG_ILLEG - a CLASSIC-500 MICFU, generation-dependent.
-
MICFU 21B IDENTIFIED (2026-07-17):
3WREG= REGISTER WRITE (twin3RREG=20B = REGISTER READ). Symbol3WREG=000021[SYMBOL: N500-SYMBOLS.SYMB:4743 + L07/M06 tables]; NPL receive dispatch N5XXC slot 21 = WRREG, "queue only", no ND-100 post-processing [NPL: MP-P2-N500.NPL:393-422]; layout [MANUAL: ND-05.012.01 Micro Program Guide sec 13.13]:Msg word (octal) 21B REGISTER WRITE (3WREG) 6 MICFU = 21B 7 first register number to write (live trace: 0) 10B number of registers 11B-12B 32-bit physical ND-100 address of the register values Semantics: DMA-read N register values from ND-100 memory into the ND-500 register block starting at register X - SINTRAN loading process-0's INITIAL REGISTER CONTEXT (incl. P) after placing the swapper image. The answer carries NO data - DECOMESS routes non- {3MONCO,3TRACO,3START,3WMONCO} answers to 5RRTWT; LDSWA only needs ANSWER(3) vs 5ERANSWER(4). Register-image width in ND-100 memory (2 words/reg, hi first) is INFERRED - log offsets 10B-12B on the next live run to pin count+source.
-
MICFU 17B IDENTIFIED (2026-07-19):
3DEPR= DEPOSIT REGISTER (DEPRG) - the single- register write member of the ND-500 register examine/deposit family. NEW carve driven by the D4 boot-harness instruction trace (see 7c-bis below). Symbol3DEPR=000017[SYMBOL: N500-SYMBOLS.SYMB:3192 (L07) + N5000-SYMBOLS.SYMB:3282 (M06)]. NPL receive dispatchN5XXC@133512 slot 17 =DEPRG[NPL: MP-P2-N500.NPL:397, table rowWAMED, RNEWCO, EXARG, DEPRG= codes 14-17]. Like 21B it is QUEUE-ONLY (falls to the common tail @133626 = set timeout timer +GO FAR TOQUEUE; no ND-100 post-processing, MICFU is not rewritten) [NPL: MP-P2-N500.NPL:414-422]. On the answer,DECOMESSsees MICFU=3DEPR is NOT in {3MONCO,3TRACO,3START,3WMONCO} -> routes to5RRTWT(restart the requesting ND-100 process). The answer carries NO data on the deposit path - the microcode need only set N5STA:=ANSWER(3) vs 5ERANSWER(4), identical rule to the 21B twin.The register family and its symbols (EXA=examine/read, DEP=deposit/write; suffix = address space):
3EXAD/3DEPD= 06/07 (memory-descriptor),3EXAR/3DEPR= 16/17 (ReGister),3EXAP/3DEPP= 32/33 (memory-physical) [NPL: MP-P2-N500.NPL:395,397,400]. So 16B =EXARG= EXAMINE REGISTER (read one register - the read twin of 17B; queue-only, same common tail) [SYMBOL:3EXAR=000016]. Adjacent 15B =RNEWCOis NOT a register op but a microprogram/control-store reload-restart handler ("...FIND ANOTHER PROCESS TO LOAD THE MIC.PROGR.") with real body logic [NPL: MP-P2-N500.NPL:568-570; SYMBOL3RESO=000015].Layout (INFERRED, register-family mirror of 20B/21B - NOT byte-pinned): word 6 MICFU=17B, word 7 register number, plus a value/count field; the microcode listing that defines the exact single-register deposit fields lives outside this repo (
ND5000UC, referenced only), so the per-register semantics are NOT asserted. For the D4 hack only the ANSWER(3) matters.GENERATION: register examine/deposit/read/write (06/07, 16/17, 20/21, 32/33) is a CLASSIC-500 family. DIRECT B30 evidence exists only for the 21B twin (-> MSG_ILLEG on the 5800 image, lines 336-338); that 17B is likewise classic-only is a strong family inference, NOT an independently carved B30 fact. The SINTRAN SENDER (
N5XXC, L07) is common to both machines and emits 17B regardless; the generational split is whether the target microcode honors it. Sender-of-record for the message BUILD (which stores MICFU:=17B) is NOT locatable in the available NPL - 3DEPR/3EXAR/3RREG/3WREG are never literally stored anywhere in the tree (only the N5XXC table + fall-through label reference them), so the register messages are built by numeric code from a table or by an ND-500-monitor command interpreter absent from this source set. Not guessed.
7c-bis. D4 boot-harness trace (2026-07-19) - 17B DEPRG is the post-CS-load blocker¶
Instruction-level trace + 3022 register log of the D4 Nd500_D4_RunDomain_RealCpu_Capture
run (offline EnableTraceFile + hex-aware SINTRAN-L symbol resolver; artifacts in the
scratchpad). CORRECTS the older "stuck in CS-load / Loading Swapper" framing:
- CS-load COMPLETES.
RETG5:=0(MON-60 25B MICRO-START) fires and 5CLOST (0x0200) CLEARS in the full run (3022 logRETG5 RESTART/MICRO-START (0x00) -> 5CLOST CLEARED). ThecsStore[]read-back model in NDBusND500IF works. The earlier "stuck forever" read was an artifact of a capped CPU-trace window landing mid-download. - After CS-load, SINTRAN drives a repeating mailbox bring-up cycle against one reused
message buffer:
...N x 14B RESIWR (process-0 image) -> 12B MSG_CACHE -> 21B 3WREG (register block) -> 17B 3DEPR (single-register deposit) -> 1B 3RMICV (watchdog poll), then repeats. - On the emulated servicer (built as
Nd500Generation.Classic, NDBusND500IF.cs:933) every message in that cycle is ACCEPTED except 17B, which has no servicer case -> hits thedefault-> 5ERANSWER(4) [Nd500MicrocodeServicer.cs:608-612]. SINTRAN gets the error, cannot advance the bring-up, and re-sends the whole cycle = the D4 "NO WELL DEFINED PROGRAM" wall now sits HERE, one step past the 21B blocker of 7c. - Fix direction: on Classic, answer 17B DEPRG with ANSWER(3) (queue-only, no data read-back), same contract as 21B. Whether the register value must actually be deposited into CpuND500 to satisfy a LATER check is untested - the immediate gate is only the error answer.
7d. The "swapper alive" contract (2026-07-17 - the M1/M2 acceptance chain)¶
The full chain SINTRAN needs to consider the swapper started; ND-100 side NPL/byte-cited, swapper side byte-verified from swapper-k01-pseg.asm:
- 21B 3WREG accepted: copy the register block into process-0 context, N5STA:=3, doorbell. (Current blocker - rejecting it silently aborts LOAD-SWAPPER.)
- START-SWAPPER (STSWP 54B -> RUNSW @163621) -> MSWSTART [MP-P2-N500.NPL:431-442]: SWMSG gets MICFU:=3START(23B), SENDE:=5SWPROC, SWPFU:=SWACTIVE, priority 300, queued. (22B STARTP0 is the separate watchdog variant - NOT this path.)
- On 3START the CPU runs process 0 from the P loaded in step 1. Swapper startup [BYTES, swapper-k01-pseg.asm entry @PSEG+4]: stack init -> "REV.-K01" build-tag self-check (mismatch -> error 32B -> MON 0B LEAVE) -> main: zero DSEG 0x240B0/0x240B4 -> MON 377B (N5SWAP, CALLG seg-31 offset 377B), argc 4, first arg VALUE = 1. The swapper announces itself by NO other means - no memory write, no self-built message; the MON-call trap IS the aliveness signal.
- The microcode/emulator answer to that trap (stop contract): on the swapper's OWN activation message (SWMSG): STOPR(11B):=MOCALL(1), NUMPA(12B):=4, MCNO(13B):=377B, param addresses @40B+, param VALUES @100B+ (5DP1@101B = 1), N5STA:=3, doorbell.
- SINTRAN closes the loop [NPL: MP-P2-N500.NPL 1346/912-919/933-1006/1031]: DECOMESS (3START+MOCALL) -> MCHANDLE -> (A=N5SWAP AND X=SWMSG) -> SWPDECODER -> SWPFU=1 -> LNEWSWAP -> first time (HSWPI=0) -> SWPD4: SWMSG.N5STA := PSWWAIT(7) = "swapper free" - THE observable success state. 5ACTSWAPPER hands work to the swapper only when it sees PSWWAIT; "Loading Swapper" stops recurring.
Magic number (list-active-processes): lives at MAGNO = message-buffer offset -3
[SYMBOL: MAGNO=177775, N500-SYMBOLS.SYMB:5715]; displayed via MON 60 RPROC 077B -> IRMESS
copying the raw buffer incl. negative header [NPL: 5P-P2-MON60.NPL:1500-1513]. The WRITER
of MAGNO is NOT FOUND in the NPL tree (system-monitor code, likely RESRV 15B worker in
030-S3SM5 - carve to settle); do NOT use "magic != 0" as an acceptance criterion yet.
POISONED PRIOR: ND500-SWAPPER-LOADING-MECHANISM.md claims the swapper is NOT loaded into
ND-500 memory - DISPROVEN by the byte-verified SWAPPER-K analysis and the live 44x14B
block-write trace. Do not cite that claim.
- The caller/worker chain (byte-cited, nd-500-mon carve + FUNCS table):
LOAD-SWAPPER cmd (case 010211-010216 in nd-500-mon) -> MON 60 subfn 7B SWLOD ("PLACE
SWAPPER", one param = swapper segment name) -> FUNCS[007] LDSWA @143551 in 030-S3SM5 =
the worker that performs the whole observed wire sequence (14B loop + 12B + 21B).
START-SWAPPER cmd (case 010217-010221) -> subfn 54B STSWP (no params) -> FUNCS[054]
RUNSW @163621 "start (run) swapper" - only reached AFTER a successful load, so the
actual start message (22B STARTP0 / 23B 3START?) was never observed: the load dies at 21B
first.
- SENDER FOUND + BYTE-VERIFIED (carve 2026-07-17): the post-CS-load 13B burst is the
TSTMC/TSTPA memory pattern test in 030-S3SM5 (52235B/52606B; called from CSLOA's tail
@155565): write pattern into the ND-500 page via the multiport window (STATX loop),
13B read-back, word-for-word compare; 4 patterns per page (177777B/0/125252B/052525B);
mismatch -> EIMDCONF 2054B; the CS verify's own error is EILOCS 2103B. Msg-5 source =
top page of the configured part = SIZING check (the 0x7F0000 inference is now grounded).
MON 60B twins AMEMR/AMEMW (FUNCS[032], 142474/142545) build the same 13B/14B messages.
Details: ND500-CS-LOAD-TRACE-FINDINGS-2026-07-16.md section 6a.
Key sources¶
ND500-BUS-INTERFACE-REFERENCE.md sec 5-7; ND500-EVIDENCE-AND-CONTRADICTIONS.md 2.5.7/2.6.2/2.6.5;
...\re\ND500-SYSTEM-MONITOR\ND500-5MPM-MESSAGE-AND-ACTIVATION.md + ND500-LEVEL12-RETURN-PATH.ASM;
ND500-STATUS-AND-INDEX.md sec 2.1-2.3; ND500-SWAPPER-ANALYSIS.md sec 12 +
swapper\swapper-k01-deep-analysis.md + swapper\swapper-k01-handlers.md;
ND500-BUS-OCTOBUS-HW-INTERFACE.md sec 3; CC-P2-N500.md sec 13; RP-P2-N500.md (XMSINIT).
8. Carver responses to the microcode-RE requests (R1-R9), added 2026-07-16¶
Answers to E:\Dev\Ronny\NDInsight\SINTRAN\ND500\CARVER-REQUESTS-FROM-MICROCODE-RE.md. The
microcode (E:\Dev\Ronny\ND5000UC\microcode\MAILBOX-MICROCODE-PSEUDOCODE.md) proves read/write
ORDER and VALUES but not absolute offsets or consumers; this section pins them from the SINTRAN side.
Provenance / how to read the grades below.
- L07 byte source: E:\Dev\Ronny\NDInsight\tools\sintran-segment-carver\versions\L-VSX-500\re\segments-ref\026-S3IMPIT\026-S3IMPIT.asm
(load base 32000B, big-endian .bin; sha256 0806cd3e...). This IS the L07 driver image.
- L07 offset authority (SYMBOL): E:\Dev\Ronny\NDInsight\SINTRAN\NPL-SOURCE\SYMBOLS\L07\N500-SYMBOLS.SYMB.TXT
(L07-native, not s3vs-4). Every field offset below was read from this file.
- Routine logic (NPL): E:\Dev\Ronny\NDInsight\SINTRAN\NPL-SOURCE\NPL\MP-P2-N500.NPL and
RP-P2-N500.NPL / CC-P2-N500.NPL. Address relation proven this session: the NPL emits
s3vs-4 addresses that map to the L07 carve with a constant +200B shift in the driver region
(NPL NOUTSTR @140627 <-> L07 141027 byte-confirmed; NPL GOSW dispatch @137342 <-> L07 ~137542
byte-confirmed). So NPL gives authoritative logic; the L07 bytes confirm the same structure
shifted. Grade BYTES = read directly in 026-S3IMPIT.asm; NPL = read in the s3vs-4 NPL
whose structure the L07 shift matches; SYMBOL = L07 symbol file.
R1. MON-call parameter block offsets - VERIFIED and REFINED¶
GOSW dispatch table - BYTE-CONFIRMED in L07 (026-S3IMPIT.asm). MCHANDEL computes
5CMNO-L12MIN and runs a 20-slot computed goto (LDA;SUB;RADD SA DP @~137542, then 20x JMP I 60
@137545-137570). The pointer table is at L07 137625B (20 words, MON 500B-523B). Decoded
pointer words (BYTES):
| MON | slot | ptr word | handler | note |
|---|---|---|---|---|
| 500 STAPROC | 137625 | 140356 | 140356B | |
| 501 NSTOPROC | 137626 | 140511 | 140511B | |
| 502 SWITPROC | 137627 | 140356 | =140356B | shares STAPROC body |
| 503 NINSTR/DVINST | 137630 | 141272 | 141272B | |
| 504 NOUTS | 137631 | 141027 | 141027B | matches catalog exactly |
| 505 GERRC | 137632 | 141633 | 141633B | |
| 506 5SIBMO | 137633 | 141716 | 141716B | |
| 507 SPRIO | 137634 | 142033 | 142033B | |
| 510 SWMC | 137635 | 142153 | 142153B | |
| 511 DVIO | 137636 | 141027 | =141027B | shares NOUTS body (new) |
| 512 A5XMSG | 137637 | 142253 | 142253B | |
| 513 B5XMSG | 137640 | 142253 | =142253B | shares A5XMSG body |
| 514 M5TMOUT | 137641 | 140563 | 140563B | |
| 515 5MTRANS | 137642 | 143445 | 143445B | |
| 516-523 | 137643-137650 | 137651.. | -> NORMM | six stubs JMP I via word 137726=137167 (NORMM) |
So 504 NOUTS = 511 DVIO = 141027B (one body), 512 A5XMSG = 513 B5XMSG = 142253B, 500 STAPROC = 502 SWITPROC = 140356B, and 516-523 all funnel to NORMM=137167B (BYTES-confirmed; this refines the catalog's "516-523 -> NORMM" and adds the shared-body facts).
Parameter offsets (SYMBOL, L07) - the 5AP1..5DP4 rows are CONFIRMED, plus 5AP5/5DP5 exist:
5AP1=100, 5DP1=101, 5AP2=102, 5DP2=103, 5AP3=104, 5DP3=105, 5AP4=106, 5DP4=107, and reads/writes
of 5AP5=110, 5DP5=111 appear (RFRRE), so the value array extends past 4. The
ND500-MONITOR-CALL-PARAMETER-PASSING.md sec 2.1 rows are verified against the L07 symbol file
(they were previously only asserted; now L07-native SYMBOL).
Pair order / (address,value) question - REFINED, partial refutation of the microcode [D] framing.
As CONSUMED by the ND-100 (NPL, byte-mapped): a parameter's 32-bit VALUE lives in a
consecutive-word double 5APn(even)=high 16b, 5DPn(odd)=low 16b (N5FUD @137527 reads
LDDTX at 5AP1, checks high IF A><0 then takes low A:=D; A5XMSG write-back @142673 does
*AAX 5APn; STZTX (zero high) ; AAX 5DPn-5APn; STATX (store value low), with input:/output:
comments naming param N -> {5APn,5DPn}). Operand/buffer ADDRESSES are a SEPARATE region, not
adjacent to the values: 5PPA1=40, 5PPA2=42, OSTRA=44 (SYMBOL; N5FUD reads "BUFFER ADDRESS" from
5PPA2=42), plus I/O-descriptor fields ABUFA=140, LBUFA=141, TODF=142. So the microcode's
per-arg "(address,value) word pair" is consumed as TWO separate arrays (VALUE at 100B+, ADDRESS
at 40B+), NOT one consecutive (addr,val) pair at 100B. Whether 5APn(high) originally carried the
operand's high value-word or its address cannot be distinguished from the SINTRAN side (immediates
give high=0 either way, and write-back overwrites 5APn) - do not assert either; the CONSUMED
positions above are what the emulator must honor. This partly resolves catalog UNKNOWN #2: the
40B-47B region DOES have symbols (5PPA1=40, 5PPA2=42, OSTRA=44) - it is the parameter-address/pointer
array, not "no symbol evidence."
Inline user buffer for 504/511/512 (R1c): flagged by MIFLAG bit WSMC(bit 0) = "data
buffer is in com-buffer (by mic.prog)" (DVIO/NOUTSTR @140627: IF MIFLAG NBIT WSMC -> issue a
3RMED(10) data-memory read to DMA it; else the microcode already filled it -> go straight to the
driver). Max length = 4000B bytes ("because of COM.BUFFER SIZE", checked as D>>4000 in
NOUTSTR/NINSTR/A5XMSG). The buffer is NOT inline in the 200B(=128-word) header - it is a separate
com-buffer addressed by ABUFA=140 (ND-100 phys, 32-bit) / referenced via LBUFA=141; the
ND-500 logical data address is carried in OSTRA=44 -> copied to N500A=7, byte count to
NRBYT=13. (Grade: SYMBOL offsets + NPL logic.)
R2. Saved-P location - the mon/trap stop saved-P is NOT read by SINTRAN¶
- The only place SINTRAN reads the ND-500 process P from a message is
HISTSAMPLE@135103 (NPL):*AAX N500A; LDDTX-> reads the sampled P fromN500A=7(32-bit double), for the3RPREG(44) histogram sample; it compares against the histogram target window. (NPL + SYMBOL.) - On a MON-call / trap STOP there is NO SINTRAN read of the microcode's saved-P word. MCHANDLE,
TRAPDECODER and DECOMESS never read it; the microcode self-resumes (
CALL_MON9setsIAC_P:=L, i.e. P:=return-addr) so SINTRAN does not need it. The saved-P the microcode writes atCALL_MON9 @004006is therefore write-only w.r.t. the ND-100 normal path. - The ND-100 shadow program's P (a different thing) is a proc-descriptor/datafield slot
DPREG=0(*DPREG@3 STATX, "ADDR OF FROMESC INTO P OF PROGRAM", MP @~132341) - NOT a message offset and NOT the ND-500 P. - No
XADPR(144)-based P read exists. Emulator consequence: the saved-P word in a MON/trap stop is don't-care to SINTRAN; only the explicit3RPREGpath needs P, delivered at message offsetN500A=7.
R3. Trap stop consumption - TRAPDECODER @135314 (NPL)¶
- Read order:
TRAPDECODERfirst readsTRAPN=16(*AAX TRAPN-1; LDDTX-> D=trap number, as a double). - Full legal range = 0..53B.
IF D>53 THEN ILTRAP(unknown trap ->WN5STATUS(illegal) -> 5RRTWT). So legal trap numbers are 0 through 53 octal; anything above is rejected as ILTRAP. - 46B = PAGE FAULT (special-cased): routes to
ITRAPDECODER, which (unless the message is the swapper's ownSWMSG, or the swapper isn't started) builds a swap requestMSWPFAULT SHZ 10 + trapnointoTRAPNand calls5ACTSWAPPER. Confirms microcode page-fault=0o46. - All other traps (D<=53, D!=46) take the generic error path
ITRPERR/ITRP2ERR: it reads5CPUN=-6(CPU#, masked/\377),SENDE=3(sender=process#),XADPR=144->RTRES(RT reference), builds a 4-word error record(ETRIPRC+trapno, process#, RT-ref, CPU#), logs via9FLER(TRPELIST,4), then5RRTWT. - On trap numbers 0o44 / 0o51: SINTRAN's TRAPDECODER does not special-case them (only 46B is
special) - they fall into the generic error/report path. The microcode's 44/46/51 specials
(
TRAP_ENTbypassing the enable byte) are a microcode-LOCAL-handler matter; by the time a trap STOPS to the ND-100, only 46B gets special treatment. Named trap-number table not found in the driver (traps are handled numerically); a symbolic trap-name list would have to come from a separate symbol set - marked UNKNOWN, not guessed.
R4. Does SINTRAN (L07) SEND MICFU 05 (3SWMESS) or 27B (3FITRNSF)? - NO. Discrepancy resolved.¶
Micfunc values (L07 SYMBOL): 3RMIC=1, 3SWME=5, 3RMED=10, 3WMED=11, 3STAR=23, 3MONC=24,
3TRAC=25, 3WMON=26, 3FITR=27, 3PHSR=30, 3PHSW=31, 3RPRE=44 (plus 3RMEP=34, 3WMEP=35, 3MONO=34,
33MON=46).
Sender-side dispatch table N5XXC @133512 (NPL) - the ND-100 twin of the microcode MSG_TABLE.
N500C (Level-2 monitor routine "execute commands to nd-500") reads MICFU from the message and
A GOSW into a 00-77B table. This is a major catalog addition; it enumerates every
micro-function SINTRAN can drive:
| # | routine | # | routine | # | routine | # | routine |
|---|---|---|---|---|---|---|---|
| 00 | STUPR | 01 | RMICVE | 02 | MILLFU | 03 | MILLFU |
| 04 | MILLFU | 05 | SWMESS | 06 | EXAMD | 07 | DEPMD |
| 10 | RMEMD | 11 | WMEMD | 12 | CACHE | 13 | RAMED |
| 14 | WAMED | 15 | RNEWCO | 16 | EXARG | 17 | DEPRG |
| 20 | REREG | 21 | WRREG | 22 | P0START | 23 | STAOPP |
| 24 | MONCO | 25 | MTRACO | 26 | WMONCO | 27 | 5RLBH |
| 30 | MPHSREAD | 31 | MPHSWRITE | 32 | EXAMP | 33 | DEPMP |
| 34 | RMEMP | 35 | WMEMP | 36 | FQUEUE | 37 | RAMEP |
| 40 | WAMEP | 41 | RLIMI | 42 | PRTRAP | 43 | WLIMI |
| 44 | MILLFU | 45 | MPCLR | 46 | MILLFU | 47 | MILLFU |
| 50 | MILLFU | 51 | MILLFU | 52 | NKREL | 53 | MILLFU |
| 60 | CLRPROC | 70-75 | TRC70..TRC75 | 76 | SCACHEMODE | 77 | RSCRREG |
05 (3SWMESS) is NEVER put on the wire. SWMESS @133635 (the slot-05 routine) translates a
swapper request into 3START(23) (*MICFU@3 STATX @133661, MSWSTART path) or 3MONCO(24)
(@134145, MSWSWAIT path) or CALL 5ACTSWAPPER; GO TRACO. Grep confirms 3SWMESS/3SWME occurs
ONLY in comparisons (IF ...=3SWMESS, 4 sites), never stored as a MICFU. 27B (3FITRNSF) is NEVER
sent either: its only occurrence is a comparison (IF ...=3FITRNSF, MP @145326); the slot-27
routine 5RLBH @134542 releases a file-transfer buffer header and GO MONCO (emits 3MONCO(24)).
=> B30's 05 -> MSG_ILLEG and 27B -> MSG_ILLEG are CONSISTENT with SINTRAN L07; no version
problem. (Grade NPL, independently corroborated by the B30 microcode.)
Senders of the "extra B30 codes" - most ARE used, and the two tables largely agree:
10 RMEMD / 11 WMEMD (data-mem R/W = B30 DMEMRD/DMEMWR), 13 RAMED / 14 WAMED (= B30 RESIRD/RESIWR),
12 CACHE, 22 P0START (= B30 STARTP0, see R7), 30 MPHSREAD / 31 MPHSWRITE (= PHYSRD/PHYSWR),
34 RMEMP / 35 WMEMP (= IMEMRD/IMEMWR), 42 PRTRAP (= PRT), 45 MPCLR (= CLEAR),
70-75 TRC70-75 (= trace family), 76 SCACHEMODE (= CACI), 77 RSCRREG (= LOOKSRF). Generational
differences: SINTRAN N5XXC marks 46/47/50/51 as MILLFU (illegal) whereas B30 assigns
46=DUDC / 47=IDLE / 50-51=UNIX5RE/CM; and 52 = NKREL (nucleus release) vs B30 UNIX5REL.
Actual 3xxx micfuncs SINTRAN transmits to the ND-500 in normal operation: 1, 10, 11, 22, 23,
24, 25, 26, 44 (plus the monitor/debug micro-functions 06-21,30-37,40-43,45,70-77 issued via
N500C for LOOK-AT etc.). STARTP0/MICFU 22B sender = P0START (see R7).
R5. 3RMICV watchdog answer - SINTRAN reads NEITHER answer halfword¶
CHN5STATUS @135004, ANSWER + WATCHDOG branch (lines 135024-135036, NPL): it identifies the
message by ADDRESS (IF X=WATCHDOG), removes it from the ex-queue (SLOCK; IFM500XQ; SUNLOCK),
and re-arms the timeout (0=:TMRXQ; LTTMR=:TMR). It reads NO message offsets at all - not
the version halfword, not the second (CPU-parameter) halfword. The mere return as N5STA=ANSWER(3)
proves the microcode alive. => the second halfword is NOT consumed; no consumer of it was found
anywhere in the driver. The monitor "read microprogram version" command (RMICVE, N5XXC slot 01)
just queues the message (falls into the common ...; A=:TMR; GO TOQUEUE tail @133626); its answer
returns ANSWER -> DECOMESS -> MICFU=3RMICV(1) is not in {3MONCO,3TRACO,3START,3WMONCO} -> 5RRTWT
(restart the requesting ND-100 process, which reads the version from the message). Emulator: for
the watchdog it suffices to set N5STA:=ANSWER(3); writing the version + CPU-parameter halfwords is
harmless but unread on the watchdog path.
R6. NUMPA write-back mask - bit k => 5AP(k+1)/5DP(k+1), BYTE/NPL-confirmed¶
- Write-back primitive: for parameter N,
*AAX 5APn; STZTX(zero the high word) thenAAX 5DPn-5APn; STATX(store the return value into the low word). Confirmed for N=2,3,4,5 in A5XMSG (@142673-142745) with matchingoutput: A=:Nth parametercomments. - Mask semantics CONFIRMED: DVINST sets
NUMPA:=4(bit 2) and writes the returned byte count toNOCHR=104B (=5AP3)-> bit 2 => parameter 3 (5AP3/5DP3), exactly "bit k => 5AP(k+1)/5DP(k+1)". DVIO setsNUMPA:=100000B(bit 15 = extended write-back to the11xxxDVIO slots,11NOCHRET). XMSG builds the mask from anXMRETMASK(func)table (@143145) and stores it toNUMPA=12. Swapper path setsNUMPA:=6(bits 1+2 => params 2 and 3; MP @145057 "Par #2 & par #3 will be written"). - Applied by:
INSMONCO@147334 /MONICO(CC-P2-N500.NPL@023022) store the mask toNUMPA-SMCNO/-NUMPAand clear FUNCV; the microcode 3MONCO restart consumes NUMPA to drive its conditional write-back loop. Write-back values land at the odd5DPnslots (101,103,105,107,111); the even5APn(100,102,104,106,110) are zeroed. (Grade: SYMBOL offsets + NPL logic.)
R7. ND-5000 mailbox head + system-parameter init¶
- Queue head the ND-500 polls: the message-communication FIFO, described by the CPU
datafield sub-block
N500DF.X500DF:X5FIF=6(FIFO base pointer),X5HEN=3(get/"hente" index),X5FYL=4(fill index),X5MXF=5(capacity =MX5PROCS).XMSINIT @131123(RP-P2-N500.NPL) allocates the FIFO buffer inside5MBBANKand stores its base intoX5FIF(@131635,*AAX X5FIF-X5SWF; STDTX),X5MXF:=MX5PROCS(@131637). The readerXN500 @134723(026-S3IMPIT) polls it: readsX5MXF/X5HEN, computesX5FIF + HENTE*elem_size, dereferences (CNVBYADR), and services messages untilHENTE=FYLLE. This is the ITOFIFOQ ring (classic ND-500 usesMAILINKat datafield offset 22; ND-5000 uses this X500DF FIFO instead). The exact MPM word address is install-dependent (computed by XMSINIT in 5MBBANK, held inX5FIF), not a fixed constant. A separate swap-wait FIFO usesX5SWF=51/X5SWB=52/X5SWH/X5SWM. - System parameters mechanism = an Octobus "WriteSysPar" message, NOT MICFU 22B, NOT a CS
side-table.
CON5IDENT @147133andMFPREPARE @147100(MP-P2-N500.NPL) build an Octobus multibyte message with commandMCOMMAND := CMSYSPAR SHZ 10 \/ N100IDENT("Send system par") and send it viaMBSEND; the ACCP's ACK/NACK ("Ack/Nack answer on 'WriteSysPar' message, i.e. I'm present") is caught by5OMBREAD, which setsCPUAVAILABLE |= 5ALIVE. So the ND-100 hands the ND-5000 its ident/system parameters over Octobus at connect time. The GIVEINT interrupt words the microcode composes ((ident & 037400)|100001/|100401) arrive on the ND-100 as the level-12 ident thatCON5IDENTconnected (N100IDENT). - MICFU 22B (STARTP0) sender =
P0START@134500 (MP-P2-N500.NPL, N5XXC slot 22): reuses theWATCHDOGmessage, inserts it in the ex-queue (ITO500XQ), stores the micro-function value intoMICFU=6(*MICFU@3 STATX), setsN5STA:=MSGN500(1), activates the ND-500. (Earlier grep for "STARTP0" found nothing because the routine is named P0START and stores the raw code, not a named3STARTP0symbol.) Grade NPL.
R8. OCB multibyte receivers - 5OMBREAD @146550 (MP-P2-N500.NPL)¶
The ND-100 receive side for Octobus multibyte messages from the ACCP / 5000 microprogram /
MF-controller. It reads a record via OMBREAD from OCTORING (OMD 5OMDNO) into LMFIELD, then
decodes ETYPE -> CSTS = high byte (ETYPE SHZ -10), CMICP = low byte (ETYPE /\ 377):
- Type 201B = HW-fault / General trap from the microprogram (IF CMICP=1 AND CSTS=200 OR A=201):
it attaches the shadow-process id (LMFIELD.S5 -> proc desc -> RTRES into LMFIELD.S4), sets
the error record at LMFIELD+2, size MMSGLENGTH+4. This is the consuming-end match for
the microcode TRAP_OCBM(0o201) system-trap message.
- MFACK/MFNACK = ack of the WriteSysPar/alive message -> CPUAVAILABLE |= 5ALIVE (see R7).
- Other error codes (CSTS/\17<17, "known error message"): indexed into the fatal/non-fatal
table MPFATAL:=(1\0,0\1,0\0,0\0,0\1,1\0); fatal -> XRSTARTALL. Record at LMFIELD+3 (or +2 for
MF-controller), size MMSGLENGTH+2.
- Payload = the error-log record documented in the routine header: omdsource, emainstat,
elog1..elog4, emaster, eslave, eaddress, esyndrom (matches the manual ND-05.020.01 HW-fault
multibyte format). Everything is then handed to 9FLER (error logger) with (LMREC, LMSIZE).
- Per-subtype maps for 203B/204B/205B/206B/210B are NOT individually decoded on the ND-100 side -
the receiver treats them generically (CSTS-indexed error record + MPFATAL classification), so the
microcode's TRAP_OCB00..20 payloads cannot be closed from the SINTRAN consumer beyond "an
error-log record forwarded to 9FLER." Address note (honest): the request cited "OMBREAD
@037660 in 026-S3IMPIT"; the receiver I find is 5OMBREAD (NPL @146550 -> L07 ~146750) with a
low-level OMBREAD helper. 037660B in 026-S3IMPIT.asm disassembles as unrelated interrupt
code - the 037660 anchor could NOT be confirmed; use 5OMBREAD as the receiver.
R9. DECOERRMESS and trap-shaped (N5STA=4) messages - HANDLED SPECIALLY, not purely error¶
DECOERRMESS @135240 (the 5ERANSWER(4) branch of CHN5STATUS) is not a pure error path. It
reads TRAPN=16 (*AAX TRAPN-1; LDDTX -> D) and MICFU=6 (A), and:
IF D=46 AND (MICFU in {3MONCO,3RMED,3WMEP,3RMEP,3WMONCO,3PHSREAD,3PHSWRITE,3WMED,3TRACO,3START})
GO ITRAPDECODER % page fault -> same swapper path as a normal trap
CALL 5RRTWT % otherwise restart the ND-100 process
5ERANSWER(4) with a legal page-fault micfunc
is still processed as a page fault (into ITRAPDECODER -> swapper), exactly reproducing the
microcode's TRAP_END N5STA:=4 case (set when the run-state flag says no process was running).
Note the discriminator SINTRAN uses is TRAPN=46 + legal MICFU, not STOPR (DECOERRMESS never reads
STOPR). Emulator: MUST reproduce the conditional - a 5ERANSWER carrying a page fault is not a
throwaway error; drop the page-fault-shaped 5ERANSWER into the trap/swapper path.
Cross-cutting note (both directions). The SINTRAN-side N5XXC dispatch (R4) and the microcode
MSG_TABLE are now both catalogued; the mailbox header offsets used above are all L07-SYMBOL-verified
(N5STA=2, SENDE=3, X5CPU=4, X5ACT=5, MICFU=6, N500A/H500A=7, STOPR/KFLIP/N100A=11, NUMPA=12,
MCNO/FUNCV/NRBYT=13, MSWMC=14, TRAPN=16, X5SND=30, SMCNO=37, XMICF=60, 5PPA1/PDR1=40, 5PPA2=42,
OSTRA=44, ABUFA=140, LBUFA=141, TODF=142, SPFLA=143, XADPR=144, 5AP1..5AP5=100/102/104/106/110,
5DP1..5DP5=101/103/105/107/111), confirming section 1's table from the L07 file directly.
8.1 Octobus FIFO follow-ups (O1 asserts) - answers for the microcode-RE LLM, 2026-07-16¶
Follow-ups to R7 from E:\Dev\Ronny\NDInsight\SINTRAN\ND500\CARVER-REQUESTS-FROM-MICROCODE-RE.md
§10.5. Sources: E:\Dev\Ronny\NDInsight\SINTRAN\NPL-SOURCE\NPL\XC-P2-N500.NPL (ITOFIFOQ @030370),
...\MP-P2-N500.NPL (XN500, XKICK500, CON5IDENT), ...\RP-P2-N500.NPL (XMSINIT @131123), and
...\SYMBOLS\L07\N500-SYMBOLS.SYMB.TXT. Grades as in §8 (BYTES = in 026-S3IMPIT.asm; else NPL/SYMBOL).
The X500DF ring (offsets SYMBOL, L07). One ring in the shared 5MPM bank, in the ND-500 CPU
datafield sub-block N500DF.X500DF:
| off | sym | role |
|---|---|---|
| 1 | X5NCP |
NCPU |
| 3 | X5HEN |
"hente" = consumer/get index (advanced by XN500) |
| 4 | X5FYL |
"fylle" = producer/put index (advanced by ITOFIFOQ) |
| 5 | X5MXF |
ring capacity (= MX5PROCS) |
| 6 | X5FIF |
ring base pointer (5MBBANK-relative) |
| 7 | X5STA |
this CPU's Octobus station (shared-ext copy) |
| 14 | X5SWM |
swap-FIFO SWMSG cell |
| 20 | X5BTI |
ring bottom/init marker (-1) |
| 26 | X1STA |
the ND-100's Octobus station (= N1OCTDEST) |
| 50/51/52 | X5SWH/X5SWF/X5SWB |
swap-wait FIFO head/front/back |
| 54 | X5NKS |
Nucleus-Kernel start |
(2) FIFO element format - PROVEN. Each element is exactly one double-word (2 ND-100 words) =
the message's 5MBBANK word-address, nothing else (no ident/type word). Producer ITOFIFOQ
(XC-P2-N500.NPL @030370) writes it with CNVWADR + STDTX; consumer XN500 (026-S3IMPIT,
NPL @134723) reads it with LDDTX + CNVBYADR -> N5MESSAGE. Element stride = 2 words
(index SH 1 in both), so element[i] = X5FIF_base + i*2.
(1) How SINTRAN links the outgoing message (the ND-5000 equivalent of ACT50's MAR write) - PROVEN
producer + kick; one microcode-side detail flagged. Two steps replace the classic
IOX LMAR5 + LCON5=5:
1. ITOFIFOQ @030370 (called with the N100/N500 semaphore held, IOF): read X5FYL, compute
new=(X5FYL+1) mod X5MXF, store new back to X5FYL, then write the message address into
element[old X5FYL] = X5FIF_base + oldFYL*2 (STDTX). It self-patches to P+1; EXIT (no-op) on a
classic ("old") 500 - the ring path is nd5000-only; classic still uses the MAR.
2. XKICK500 @146322 (LV12KICK @146355): sends an Octobus kick to 5STATION (the ND-500's
station) via SKICK. Kick types: CLRKICK, IDLEKICK, N100KICK (ACT52 @145520 uses
N100KICK). This is the doorbell that pulls the idle microcode out of its #CPUDF poll.
So SINTRAN "links" the message by appending its address to the X500DF ring at X5FYL and then
kicking. FLAG (confirm microcode-side): which exact word the #CPUDF poll reads to notice new
work cannot be proven from the SINTRAN side - candidates are X5FYL (offset 4, the fill index
SINTRAN advances) or the ring base X5FIF (offset 6). SINTRAN's observable act is "advance X5FYL +
write element + Octobus kick"; point srf[#CPUDF] at this X500DF structure and read the fill
index / element accordingly. (XN500's own X5HEN walk is the ND-100 answer/retire scan - do NOT
mistake it for the microcode's consume pointer.)
(3) X500DF location / init - XMSINIT @131123 (RP-P2-N500.NPL). 5MBBANK = 5FPMAILBOX SH 12;
after zeroing the 5NPMAILBOX message pages, X500DF = the running 5MBBANK-relative allocation
pointer (@131153). Per-CPU shared datafield extensions (MSMLINK, stride 5EXTDFSIZE) are laid out
for every CPU S5CPUDF..E5CPUDF, reached from each CPU datafield's MAILLINK; for MUDOM (nd5000)
CPUs they carry X5STA (station), X5ACC/X5OCT/X5HWB (ACCP/Octobus/HW buffers). The
message-communication FIFO buffer is allocated in 5MBBANK at MSIN2 (@131630): X5FIF := base,
X5MXF := MX5PROCS, X5BTI := -1; the swap-wait FIFO plus X5NCP:=NCPU, X1STA:=N1OCTDEST,
X5NKS:=5NKSTART are set alongside.
(4) SYSPAR ident/station - mechanism PROVEN; numeric values NOT carved. The ND-100 hands the
ND-5000 its parameters by an Octobus message MCOMMAND := CMSYSPAR SHZ 10 \/ N100IDENT, built by
CON5IDENT @147133 / MFPREPARE @147100 and sent via MBSEND ("Send system par."); the ACCP ACK
is caught by 5OMBREAD -> CPUAVAILABLE |= 5ALIVE. Station is per-CPU 5STATION = CPUNO+FN5DEST-1
(RP @132221); the ND-100's own station is X1STA = N1OCTDEST. The GIVEINT ident the microcode ORs
((SYSPAR & 037400)|100001) derives from N100IDENT. Not proven (marked, not guessed): the
numeric values of CMSYSPAR, N100IDENT, FN5DEST, and the SYSPAR cell offset are NOT in
N500-SYMBOLS.SYMB.TXT - they live in the MON60/Octobus symbol set (SYSPAR is referenced as
"N500DF+SYSPAR", a 16-word block saved/restored in 5P-P2-MON60.NPL @032702). Pull those symbols
to pin the exact bits (item 4 is the "can wait" one).
8.2 O1 round 2 - the real head cell + resolved SYSPAR values, 2026-07-16¶
Sources: E:\Dev\Ronny\NDInsight\SINTRAN\NPL-SOURCE\NPL\CC-P2-N500.NPL (ITO500XQ @022547),
...\MP-P2-N500.NPL (XACTRDY/ACT50-52 @145266-145534), and the L07/swapper N500-SYMBOLS.SYMB
(5-char-truncated names). Offsets SYMBOL(L07); logic NPL.
(1) SOLVED - the head cell + the work flag, and the "third write" the microcode-RE LLM predicted.
At each nd5000 activation site the producer does THREE writes under the N100/N500 semaphore, then
kicks:
1. ITO500XQ @022547 (the predicted third write) - the classic ex-queue insert, run on the
nd5000 path too: it (a) sets 5MSFL bit 5IEXQUEUE in the message, (b) priority-links the
message into the ex-queue via LINK(0)/PLINK(147) with the head at MAILINK(=22B, in the
CPU datafield), and (c) MIN LEXQUEUE - increments the ex-queue length counter
LEXQUEUE(=14B). IFM500XQ @022665 reverses it (clear 5IEXQUEUE, decrement LEXQUEUE).
2. ITOFIFOQ @030370 - message address into the X500DF ring at X5FYL (§8.1).
3. XKICK500 @146322 - the Octobus kick to 5STATION.
So the halfword work flag the microcode IDLE poll tests nonzero is LEXQUEUE (ex-queue length,
CPU-datafield offset 14B): ITO500XQ makes it nonzero when work is queued, IFM500XQ returns it
to 0 when the queue drains. The ex-queue head the microcode walks is MAILINK(22B) (walked
LINK@3 until -1, exactly as SINTRAN's own XACT500/N500 walk it) - this is the match for the
microcode's unexplained ADR_EXQUE (srf 0o2020). The microcode's #CPUDF (srf 0o2017)
points at the ND-500 CPU datafield; mem[#CPUDF + 14B] = LEXQUEUE is the poll flag, and
mem[#CPUDF + 22B] = MAILINK is the queue head. (The X500DF FIFO of §8.1 is a second, parallel
structure carrying the message address for the kick path; ITO500XQ+MAILINK/LEXQUEUE is the
primary ex-queue.) CONFIRM microcode-side: that #CPUDF reads offset 14B (LEXQUEUE) as the flag
and 22B (MAILINK) as the head - both are now named with offsets, so this is a direct check.
MPACTIVE=1 (the X5CPU precondition value).
(2)/(4) SYSPAR values - RESOLVED (SYMBOL, L07/swapper N500-SYMBOLS, 5-char-truncated names):
- CMSYSPAR = 16B (CMSYS) - the Octobus "send system parameter" command code.
- N100IDENT = 1 (N100I) - the ND-100's Octobus ident.
- FN5DEST = 70B (FN5DE) - first ND-500 Octobus station; per-CPU 5STATION = CPUNO+FN5DEST-1.
- SYSPAR = 111B (SYSPA) - offset of the 16-word SYSPAR block within N500DF (saved/
restored in 5P-P2-MON60.NPL @032702, X:=16).
- So CON5IDENT/MFPREPARE send MCOMMAND = CMSYSPAR SHZ 10 \/ N100IDENT = (16B<<8)|1 = 016001B.
The ND-100 N500DF.SYSPAR block (16 words @ +111B) is the source; the microcode's own
ADR_SYSPAR (srf 0o2006) is the destination; GIVEINT's (SYSPAR & 037400)|100001 ident derives
from N100IDENT=1.
(3) GIVEINT ident FIFO - no separate SINTRAN ring (cheap answer). The microcode's outbound ident
FIFO (ADR_FIFOB, srf 0o2002) is drained by the ACCP/Octobus hardware into a level-12 interrupt;
there is no SINTRAN-side ident ring consuming it. SINTRAN only connects the Octobus ident so it
receives that interrupt - CON5IDENT @147133 -> ECONID with N100IDENT(=1) on LV12B. So the
producer/consumer pair is microcode-FIFO -> ACCP-hardware -> ND-100 level-12 ISR, not a shared
software ring like X500DF. (Nothing further to carve unless the ACCP's internal ident-buffer layout
is wanted, which is a hardware/ACCP question, not SINTRAN.)