CARVE ANSWER — the MON 60B "answer result block" (offsets 40B-47B) decoded, per-command layouts¶
Full path: E:\Dev\Ronny\NDInsight\SINTRAN\ND500\CARVE-ANSWER-RESULT-BLOCKS-2026-08-10.md
Date: 2026-08-10. Question (P4 of the ND-500 plan): carve the per-MICFU answer RESULT
BLOCK layouts ("mailbox message word offsets 40B-47B and any others") for the MON 60B commands
that return data, so they can be modeled in the Classic Nd500MicrocodeServicer.
Sources (all offsets reproduced from bytes with a direct read of the carve before publishing):
- tools\sintran-segment-carver\versions\L-VSX-500\segments\030-S3SM5.bin (base 40000B,
big-endian) + re\030-S3SM5.dis (regenerated 2026-07-31) — the ND-500 System Monitor.
- SINTRAN\NPL-SOURCE\NPL\5P-P2-MON60.NPL (grade NPL — logic only, different revision).
- SINTRAN\NPL-SOURCE\SYMBOLS\L07\N500-SYMBOLS.SYMB.TXT (grade SYMBOL).
- E:\Dev\Ronny\ND500UC\docs\MC\CONT-STORE-10611.md — the REAL classic ND-500 microcode
disassembly (round-trip verified 2026-08-10), for the microcode-side cross-check.
- SINTRAN\ND500\nd-500-mon\mon60-callers\STATUS\ (caller side, prior carve).
Grades: [V] = read in the L07 bytes this session, [SYMBOL], [NPL], [MC] = read in the CONT-STORE-10611 microcode listing, [I] = inferred, [OPEN] = not established.
0. HEADLINE — the "result block at 40B-47B" is NOT in the 5MPM mailbox message¶
The ,X 40/,X 43/,X 46/,X 47 stores in the FUNCS bodies land in the MON 60 info block
(the ZPREG..ZPREG+5DFSIZE block of the N500DF datafield, working copy S500DF), not in
the 5MPM message. The numeric collision with the message's 5PPA1=40/5PPA2=42/OSTRA=44
parameter-address region (catalog §8 R1) is exactly that — a collision between two different
structures that both use octal-40-ish offsets.
Layout of the result block [SYMBOL, L07 N500-SYMBOLS.SYMB.TXT] — a 5-entry array of
3-word parameter records starting at info-block offset 40B:
| n | 5DDn (32-bit VALUE, hi word first) |
5Pn (user ADDRESS the value is copied to) |
|---|---|---|
| 1 | 5DD1=40 (5D11=40 hi, 5D12=41 lo) |
5P1=42 |
| 2 | 5DD2=43 (5D21=43 hi, 5D22=44 lo) |
5P2=45 |
| 3 | 5DD3=46 (5D31=46 hi, 5D32=47 lo) |
5P3=50 |
| 4 | 5DD4=51 (5D41=51 hi, 5D42=52 lo) |
5P4=53 |
| 5 | 5DD5=54 (5D51=54 hi, 5D52=55 lo) |
5P5=56 |
Context symbols: ZPREG=7, ZXREG=10, ZTREG=11, ZAREG=12, ZDREG=13, ZLREG=14, ZBREG=16,
5FUNC(TION)=20, 5DFSIZE=50 — so the info block copied around the system-monitor call covers
datafield offsets 7..56B, which contains the whole 40B-56B result array.
Poisoned priors corrected by this carve:
1. re\ND500-SYSTEM-MONITOR\FUNCS-BODIES\README.md said "LDX ,B -11 = the message pointer".
WRONG — B-11 is the info block (see §1); the message pointer is B-67. (Corrected
in that README in this change.)
2. ND500-MAILBOX-MESSAGE-CATALOG.md UNKNOWN #2 said the 40B-47B answer block "has NO symbol
evidence — treat as NON-EXISTENT". Half right: it is not a message structure, but it very
much exists — it is the 5DDn/5Pn array above, and every FUNCS ,X 40+ store is one of its
slots. (Catalog updated to point here.)
3. The nd-500-bus-interface skill's "VERSION (057B RMVER) ... returns CPU-DF descriptor-CACHED
values (no hardware access)" is wrong for the classic path: RMVER's classic branch does a
LIVE 3RMICV mailbox round trip (§4.4). GETCP (170B) is the purely cached one.
1. The plumbing — how a FUNCS result reaches the MON 60 caller [V + NPL]¶
caller (nd-500-mon) MON 60 params: addresses of caller locals
-> N500M 5IFUNC[code] marshals params into the info block (values -> 5DDn, addrs -> 5Pn)
-> 5NOPAR MOVAA: N500DF+ZPREG (50B words) -> S500DF [NPL 034460]
-> FPT2ENTRY -> 5FP2E@142231 the ND-500 System Monitor (ND-100 code in 030-S3SM5)
-> FUNCS[code] performs the operation; WRITES RESULT VALUES INTO 5DDn
(the ",X 40/43/46/47" stores, X = B-11 = S500DF-ZPREG)
<- return
-> 5PT2RET MOVAA: S500DF -> N500DF+ZPREG [NPL 034757]
-> post-return FUNCS(X) the NPL "( 5 ) F U N C S" table @034534 - per-code routine
copies 5DDn -> [5Pn] (STDS0) or block-copies (TOUSMOVE)
-> RET5 back to the caller; caller reads its locals
There are two different tables both named FUNCS — do not confuse them:
- the system monitor's dispatch FUNCS @142031B in 030-S3SM5 (does the work);
- the NPL post-return table FUNCS @034534 in 5P-P2-MON60.NPL (copies results to the user).
5FP2E frame map [V, entry code 142231-142267 + pool words byte-verified]:
| Frame cell | Contents | Evidence |
|---|---|---|
B-11 |
info block base = S500DF-ZPREG = static cell 165777B (pool word M[142345]=165777) |
142247 LDX 76; 142250 STX ,B -11; every result store LDX ,B -11; STD ,X 40/43/46 |
B-67 |
logical (window) address of the caller process's 5MPM MESSAGE (MESSBUFF) | computed 142261-142264 from the message bank field; every message field access LDX ,B -67; ST?/LD? ,X 7/10/11/13/14 |
B-65 |
ABUFA = message[140B-141B] = com-buffer ND-100 physical address (32-bit) |
142266 LDD ,X 140; STD ,B -65; used as msg[11B-12B] in transfer builders |
B-56 |
current ND-500 CPU-DF (descriptor) | 142270-142273 via GCPUDF-pool call; LDT ,X -3 = IOX base for IOXT |
B-57 |
secondary descriptor (used by CSLOA with offsets 57, -22, -30..-32, +50) |
142231-142233 |
Common helpers (pool words byte-verified): 063007 = build message / set MICFU := A;
063026 = second prep helper; 104236 = send + wait for the mailbox answer;
141567 = success exit; 141600 = error exit; 142441 = register-number range check;
051116 = WRTAG; 051052 = TAG read-back helper.
2. The post-return copy table — which 5DDn/5Pn each data-returning command uses [NPL 035117-035703]¶
Every MON 60B command that returns data does it through one of these routines (RET5 = returns
nothing). This is the authoritative per-command result-block usage:
| code | NPL routine | copies to user |
|---|---|---|
| 000 RREG | FRREG |
5DD2 -> [5P2] (register value, 32-bit) |
| 002/003/032/121 PMREAD/DMREAD/DAMR/RSWPDATA | FPMREAD |
5DD4 -> [5P4] (no. of bytes read); block TOUSMOVE(dest=5P3, len=5D42) (the read data, from the MON60/com-buffer) |
| 010 RRGS | FRRGS |
block TOUSMOVE(dest=5P1, len=NREGS*4) (all registers) |
| 012 PRSTART (RUNN) | FPRSTART |
5DD1 -> [5P1] (STOP REASON); block TOUSMOVE(dest=5P2, len=200B) ("stop (trap) info") |
| 013 CONNFI | FCONNFI |
5DD5 -> [5P5] (open-file number) |
| 015 RES5 | FRES5 |
block TOUSMOVE(dest=5P2, len=11B) |
| 016/116 REL5/XN5REL | FREL5 |
if process in BREAK state: same copies as FPRSTART |
| 023/157 RCNT (read control store) | FRCNTS |
block TOUSMOVE(dest=5P3, len=5D22*2) |
| 026/030/067/130 DMEXA/PMEXA/SPRTE/SFSYDOM | FDMEXA |
5DD2 -> [5P2] (examined 4 bytes / entry) |
| 041 RSTATU (STATUS) | FRSTATU |
5DD1 -> [5P1], 5DD2 -> [5P2], 5DD3 -> [5P3] |
| 051/057 RIREG/RMICV | FRMICV |
5DD1 -> [5P1] |
| 060 LIMEM | FLIMEM |
block TOUSMOVE(dest=5P1, len=74B) (memory-conf table) |
| 070 GPRTE | FGPRTE |
block TOUSMOVE(dest=5P2, len=250B) (process table entry) |
| 071/072 SSGTE/GSGTE | FSSGTE/FGSGTE |
block TOUSMOVE(dest=5P2, len=154B) (phys-segment entry) |
| 073 RPHSG | FRPHSG |
5DD5 -> [5P5]; block TOUSMOVE(dest=5P4, len=5D32) |
| 154 DBUGSW | FDBUGSW |
no copy (releases CPU if 5D12=1) |
| 156 NRMICV (read system info) | FNRMICV |
block TOUSMOVE(dest=5P1, len=134B) |
| 166 RDTRACE | FRDTRACE |
block TOUSMOVE(dest=5P2, len=5D12*24B) (160 bits/trace word) |
| 170 GCPUTYPE | FGCPUTYPE |
5DD1 -> [5P1] (CPU type), 5DD2 -> [5P2] (mic version + parameter) |
| 172 RSCRREG | FRSCRREG |
block TOUSMOVE(dest=5P3, len=5D22*4) (4 bytes/SRF register) |
(STDS0 = store the 32-bit AD at the user address; TOUSMOVE = block copy to the user from
the MON60 buffer.) Histogram (062-066), RPROC 077 (read message) and the log families are
handled in 5IFUNC on the resident side and copy independently (e.g. IREAHIST copies
5HIDATA via TOUSMOVE(5P1, 200B) + 5HIOUTSIDE -> [5P1+200B] [NPL 032303-032312]).
3. Which FUNCS bodies write those slots, and where the data comes from [V bytes]¶
3.1 Mailbox-answer commands — the message offsets read AFTER the answer¶
These are the commands whose result the microcode must produce. All message offsets are
ND-100 word offsets within the 5MPM message (X = B-67).
| FUNCS | MICFU sent [V] | request fields written [V] | answer fields READ after 104236 send+wait [V] |
lands in |
|---|---|---|---|---|
000 REGRE @142365 |
16B 3EXAR (SAA 16) |
msg[7] = register number (5D12, range-checked @142441) |
msg[10B-11B] = 32-bit register value (142403-142406) |
5DD2 |
001 REGWR @142410 |
17B 3DEPR (SAA 17) |
msg[7] = register number, msg[10B-11B] = 32-bit value (5DD2) |
none (status-only answer) | — |
026 DMEXA @153051 |
06B 3EXAD (SAA 6) |
msg[7-10B] = 32-bit address (5DD1), msg[14B] = word from [B+55] (qualifier, identity [OPEN]) |
msg[11B-12B] = examined 32-bit value (153073-153076) |
5DD2 |
030 PMEXA @153042 |
32B (SAA 32) |
same as DMEXA | same: msg[11B-12B] |
5DD2 |
027 DMDEP @153107 |
07B 3DEPD (SAA 7) |
msg[7-10B] = address, msg[11B-12B] = value (5DD2), msg[14B] = [B+55] |
none | — |
031 PMDEP @153100 |
33B (SAA 33) |
same as DMDEP | none | — |
002/003/032/121 PMREA/DMREA/AMEMR/FSWPR @142456-142616 |
34B / 10B / (per-variant) (SAA 34/10/...) |
via shared builder: msg[7-10B] = ND-500 address (5DD2), msg[11B-12B] = ABUFA com-buffer physical address (B-65), msg[13B] = byte count |
answer data is DMA'd by the microcode into the com-buffer at msg[11B-12B]; post-return TOUSMOVE hands it to the user |
user buffer 5P3 |
057 RMVER @164652 (classic branch @164727) |
1 3RMICV (SAA 1 @164733, gated on CPUDF[10B] bit 0) |
header only | msg[7] = microprogram version halfword (164740-164744: -> 5D12, 5D11 zeroed) |
5DD1 |
037 CSLOA @153441 tail (@154503-154530) |
1 3RMICV (SAA 1 @154512, after load + micro start) |
header only | msg[7] compared against CPUDF[-7] (the version word taken from the control-store FILE); mismatch -> error via pool 23; msg[10B] -> CPUDF[20B] (CPU parameter cache) |
CPU-DF cache |
166 DUMPT @174626 |
trace family (SAA 74) |
msg[7], msg[10B-...] params |
trace data block via com-buffer | user via 5P2 |
172 RSCRR @174776 |
77B LOOKSRF (SAA 77) |
msg[7] = first SRF register, msg[10B], msg[11B-12B] |
SRF data via com-buffer | user via 5P3 |
162-165 INITR/CLRTR/ARMTR/DISAR @174526+ |
70B family (SAA 70 @174552) |
msg[7], msg[10B], msg[11B], msg[12B] params (174536-174552) |
status-only | — |
Notes:
- REGWR byte-pins the catalog §7c "layout (INFERRED)" for 17B 3DEPR: word 7 = register
number, words 10B-11B = the 32-bit value. And REGRE shows the single-register READ twin is
16B 3EXAR (not 20B 3RREG, which is the register-BLOCK read used by REGSR/REGSW
10B/11B), answering into words 10B-11B.
- msg[14B] (the MSWMC slot) is written on the examine/deposit paths with a word from the
monitor's own datafield (LDA ,B 55); its meaning (process/domain qualifier?) is [OPEN].
3.2 RSTAT (041B) — the STATUS command, incl. the "third word" (target 1)¶
The caller (nd-500-mon STATUS @127551) passes THREE result addresses; FRSTATU copies
5DD1/5DD2/5DD3 back. RSTAT @156064 fills them without any mailbox traffic [V]:
156064 JPL I 12 -> sub1 @156102 (status + third word; skip-return on success)
156066 LDX ,B -11
156067 STD ,X 40 ; 5DD1 := status double
156070 STZ ,X 46 ; 5D31 := 0
156071 STT ,X 47 ; 5D32 := T = the "third word"
156072 JPL I 6 -> sub2 @156154 (MAR)
156074 STD ,X 43 ; 5DD2 := MAR
156075 JMP I 4 -> 141567 (OK exit)
- sub1 @156102: if
CPUDF[27B] & 7 == 3(SAMSON — mask wordM[156146]=000007[V]) then status halves := 0/0 and third word := -1. Else (classic): one half = liveIOXTread ofRSTA5(LDT ,X -3; AAT 2; IOXT— CPU-DF holds the IOX base at offset -3); the other half = a 5015-side register read through TAG:WRTAG(14B CNTR); WRTAG(3 DUCLK); read @051052(= the CSCNT register read back); the third word =WRTAG(12B WAR); WRTAG(3 DUCLK); read @051052, masked withM[156152]=037777B(= the 5015 WA register, 14 bits). - sub2 @156154: SAMSON -> 0; classic -> two
IOXTreads at offset 0 (RMAR5, LS first), MS part maskedM[156205]=000377B-> the 24-bit MAR.
So the three STATUS results are: (1) interface status double = {5015 CSCNT half, RSTA5
half} (which half is hi vs lo not pinned here — the caller's decode loops print "ND-100" bits
from one half, "ND-500" bits from the other [caller carve]); (2) MAR (24-bit);
(3) the 5015 WA register & 37777B (-1 on ND-5000). The meaning of the WA read-back
as a status ("last control-store address touched"?) is [OPEN] — the identity of the read is
[V], its interpretation is not. This resolves the STATUS folder's "UNKNOWN: identity of the
third returned word" at the mechanism level.
3.3 GETCP (170B) — pure cache read [V @174676-174722]¶
5DD1 := (0, CPUDF[27B] & 7) ; CPU TYPE (1=OLD500, 3=SAMSON; mask word = 000007)
if CPUDF[10B] bit 0: 5DD2 := (CPUDF[20B] << 16) | CPUDF[-7] ; (CPU parameter, micro version)
else: 5DD2 := 0
No hardware or mailbox access at all. The cache cells are:
- CPUDF[-7] = microprogram VERSION — written by CSLOA from the control-store FILE
image (154034 SAX 7; LDA I ,X 144 = file word 7 in one loader branch; 155126 SAX 10;
LDA I ,X 112 = file word 10B in the other; buffer base pool M[154200]=M[155240]=166056B
[V]) and range-classified into a type code merged into CPUDF[27B] low 3 bits (mask
M[155243]=177770B [V]).
- CPUDF[20B] = CPU PARAMETER — zeroed at load (155132 STZ ,X 20), then written from
msg[10B] of the post-load 3RMICV answer (154525-154530).
- CPUDF[10B] bit 0 = the "version valid" gate; its writer was not located this session [OPEN].
3.4 SPRES (043B) — target 2 verdict: it stores INTO the request, returns nothing¶
FUNCS[043] = ERRFP (no system-monitor op); post-return FUNCS[043] = RET5 (no copy);
ISRES [NPL] tests 5D11/5D12 (=0,0 -> reserve this CPU only; else whole system) and exits
via 5OKRET. The single STD ,X 6 the J04 caller performs (mon60-callers/043B-SPRES) is
therefore parameter 1 IN (the scope selector consumed as 5DD1), not a returned word.
No answer-block modeling is needed for SPRES/SPREL. The "presence"-flavored data commands are
GETCP (§3.3) and RSTAT (§3.2).
4. Classic microcode cross-check — CONT-STORE-10611 [MC]¶
The real classic control store confirms the mailbox answer model from the other side:
- Function dispatch =
JMPRELinto a table at007636 + fn(007632-007635: MICFU masked 16-bit, range-checked against50B,A+1 ... JMPREL). Entries beyond the implemented set jump to007740. - Illegal function @007740:
SARG=4 -> AL#25; JMP 011405— answers with status 4 (5ERANSWER).011405is the common completion:AL#25 -> AM#20; JSR 007550writes the status halfword to ND-100 memory, then TAG status/reset-activate ops + doorbell. - The TAG-OUT DMA helper family @007540-007564 matches the carved TAG truth exactly:
007543/007544= DMA READ of ND-100 memory at MAR (TAG codes206/006, MOST+LEAST),007546/007550= DMA WRITE (codes207/007),007552/007553= read MAR (codes000/200),IODIN/IODOUT= the data latch. - fn 1 (3RMICV) @007637 -> 011430:
JSR 007777loadsLARG 24563Binto AM#20 — 24563B = decimal 10611 = the image's own identifier stamped in microword 0 bits 15-0 — thenJSR 007550(ONE halfword DMA write), thenJMP 011405(answer status 3). So the classic version answer is sourced from the loaded image and is the same value CSLOA extracted from the file, which is exactly why CSLOA'smsg[7] == CPUDF[-7]verify passes. In THIS image the CPU-parameter halfword is not written by fn 1 [MC] —msg[10B]keeps whatever it held (SINTRAN caches it regardless). The 5800/B30 microcode writes both. - fn 44B (3RPREG, histogram) @007702 -> 007721: samples
A,P(the macro P register), writes it with007546(a MOST+LEAST pair = 32 bits), then two more halfword writes (AM#10 - 1= current process, andAM#15) before011405. Matches SINTRAN's HISTSAMPLE, which reads the sampled P as a 32-bit double atN500A = msg[7-10B][NPL 135103]. - The landing offsets of these sequential DMA writes depend on where the fetch loop leaves MAR;
the SINTRAN read side ([V]:
msg[7]/msg[10B]) pins them in practice. The microcode fetch loop's MAR bookkeeping was not fully decoded [OPEN — cosmetic].
5. What the Classic Nd500MicrocodeServicer must model (consequences)¶
- 3RMICV (MICFU 1): write the version halfword to
msg[7]and the CPU-parameter halfword tomsg[10B], thenN5STA:=3. The version MUST equal the version word of the loaded control-store image (classic 144-bit/9-part image: the 16-bit part holding microword-0 bits 15-0, which SINTRAN's CSLOA reads out of the file at word offset 10B in the classic loader branch; =24563Bfor CONT-STORE-10611) — otherwise CSLOA fails its post-load verify and LOAD-CONTROL-STORE errors out even though the store loaded. CPU parameter: the 10611 image would leave it unchanged; writing 0 (or a modeled parameter) is safe — SINTRAN only caches it intoCPUDF[20B]for GETCP to report. - 16B
3EXAR(register examine): answer the 32-bit register value atmsg[10B-11B]. 17B3DEPR(register deposit): consumemsg[7](reg number) +msg[10B-11B](value); status-only answer. (Byte-pinned; upgrades catalog §7c.) - 06B/32B examine: answer the 32-bit value at
msg[11B-12B](request address atmsg[7-10B]). 07B/33B deposit: consumemsg[11B-12B]; status-only. - Memory reads (34B/10B family): DMA the data to the ND-100 physical address in
msg[11B-12B](the com-bufferABUFA), byte countmsg[13B]— same shape as the already modeled 13B/14B RESIRD/RESIWR. - 44B histogram: write the sampled P as a 32-bit double at
msg[7-10B](per SINTRAN's consumer; the extra process/AM#15 halfwords are unread by SINTRAN). - Answers carrying data for STATUS/GETCP need NO microcode support: RSTAT is IOX + TAG
read-back on the 3022/5015 (the emulator's register model already covers RSTA5/RMAR5; the
WRTAG CNTR/WAR + DUCLK + readpath must return the CSCNT and WA registers), and GETCP is pure ND-100-side cache. - Illegal MICFU: status 4 (
5ERANSWER) — the classic microcode does exactly this (007740), including for out-of-range codes > 50B.
6. Open items (marked, not guessed)¶
- Meaning of the RSTAT third word (5015 WA register &
37777B) as a status quantity; and which half of5DD1is the ND-500 vs ND-100 status half (order inside sub1's epilogue not traced). msg[14B]qualifier written from[B+55]on examine/deposit paths.- Writer of the
CPUDF[10B]bit-0 "version valid" gate. - Who writes
5DD4(bytes-read count) for the memory-read family — the microcode answer or the ND-100 body; not traced this session. - RMVER's two non-classic branches (octobus/
[B-57-22]bit-3 path with the 4-wordMOVEWfrom[B-57+50B]; region 164701-164726 partially data-garbled in the listing). - The
SAA 32/33examine/deposit codes used by PMEXA/PMDEP vs the N5XXC table's 32=EXAMP/33=DEPMP naming ("program-memory examine" riding the P-space codes) — naming only.
7. Evidence appendix¶
Pool/mask words byte-verified directly from 030-S3SM5.bin (python struct read, base 40000B):
M[156076]=156102, M[156077]=141600, M[156100]=156154, M[156101]=141567, M[156146]=7,
M[156152]=37777, M[156204]=7, M[156205]=377, M[174721]=7, M[142433]=63007, M[142434]=63026,
M[142435]=141600, M[142436]=142441, M[142437]=104236, M[142440]=141567, M[156150]=51116,
M[156151]=51052, M[164771]=63007, M[164772]=104236, M[164773]=141600, M[164775]=141567,
M[154602]=63007, M[154603]=104236, M[154200]=166056, M[155240]=166056, M[155243]=177770,
M[142345]=165777 (all octal).
Cross-references: re\ND500-SYSTEM-MONITOR\FUNCS-dispatch-table.md (table addresses),
mon60-callers\STATUS\README.md (caller side), ND500-MAILBOX-MESSAGE-CATALOG.md §§7c/8,
E:\Dev\Ronny\ND500UC\docs\MC\CONT-STORE-10611.md + docs\DISASSEMBLER-VALIDATION-2026-08-10.md
(image identifier 24563B=10611, parity proof).