CARVE ANSWER: 3022 bundle — RFLAG/SFLAG, background poll block, LAST-N500-MSG ring¶
Full path: SINTRAN/ND500/CARVE-ANSWER-3022-FLAG-POLL-RING-2026-07-19.md
For: the 3022 bus-interface team. From: SINTRAN carving/RE. Date: 2026-07-19.
Discipline: byte-verified only; segment+octal (SINTRAN) / HEX (Ghidra); NPL is a different revision
(logic only, never authority); anything unresolved is marked ASSUMPTION, not guessed. The emulator's
fabricated "TAG protocol" is not used or confirmed anywhere below.
Grades¶
[BYTES] read from a carved .bin or a live harness capture · [SYMBOL] from a real symbol
artifact · [NPL] from NPL source (different revision — logic only) · [INFER/ASSUMPTION] reasoned,
not evidence.
Evidence sources used¶
- Caller:
SINTRAN/ND500/nd-500-mon/mon60-callers/100B-RFLAG/,101B-SPFLAG/(bytes fromnd-500-mon-j04.prog.asm). - Worker dispatch:
.../re/mon-analysis/60B-N500M/60B-5IFUNC-dispatch-table.md,60B-100B-FLAGS/README.md. - Server table:
.../re/ND500-SYSTEM-MONITOR/FUNCS-dispatch-table.md(dumped from030-S3SM5.bin). - Handler body:
SINTRAN/NPL-SOURCE/NPL/5P-P2-MON60.NPL(RRFLAG/WWFLAG @032453B; FT500/FF500 @140-147). - Poll/watchdog:
SINTRAN/NPL-SOURCE/NPL/RP-P2-N500.NPL(3RMICV build @282/384/820-822; N500TMR @305-347). - Message layout:
ND500-MAILBOX-MESSAGE-CATALOG.md§1-2;swapper/N500-SYMBOLS.SYMB(L07). - Live seed:
ND500-F6-MESSAGE-RING-RAW-CARVE-SEED-2026-07-19.md,ND500-BUS-INTERFACE-COMMAND-LADDER-ANALYSIS-2026-07-19.md.
(a) RFLAG=100B / SFLAG=101B — DO THEY CROSS THE 3022? NO.¶
Verdict: neither RFLAG (100B) nor SFLAG (101B) crosses the 3022 bus. They read/write a flag word
in the target ND-500 process's data segment, which SINTRAN maps into ND-100 addressing via
M1MEXY and touches with ordinary memory instructions. There is no IOXT to the 3022 registers, no
LCON5:=5 ACTIVATE, no MSGHDR/PROCMSG, no MICFU — nothing on the bus. This is a byte-anchored
confirmation of the command-ladder observation (GET/SET-FLAG produced no command-specific 3022 traffic;
the 17-event block was the background watchdog poll, question (b)).
Byte chain¶
-
Caller [BYTES] —
nd-500-mon-j04.prog, main interpreter002662:- RFLAG: thunk
146616 = SAA 100→MON 60at call site005264. Two params:STA ,X 6 = &(B-125)(process number),STA ,X 7 = &(B-127)(flag word; preloadedLDD 174@005253, read back on success005266 LDD ,B -127). - SPFLAG: thunk
146621 = SAA 101→MON 60at005223. Two params from evaluated command-line operands:,X 6 = &(B-125),,X 7 = &(B-127). - Contract [BYTES]:
A=subfunction code via thunkSAA; param1 @gateway,X 6, param2 @,X 7; callsite+1 = error, callsite+2 = success.
- RFLAG: thunk
-
Worker dispatch [BYTES structure / NPL name] —
5IFUNC[100B]=RRFLAG,5IFUNC[101B]=WWFLAG(5P-P2-MON60.NPL:1328). The L07050-S3I5PITdispatcher @030416Brange-checks to177Band has the145Bvalid/illegal boundary — structure byte-confirmed. -
Server side proves no bus op [BYTES] —
FUNCS[100B] = FUNCS[101B] = ERRFP = 141574B(dumped from030-S3SM5.bin, base40000B).ERRFP= "not serviced here"; the table's own note: codes pointing at ERRFP are handled entirely ND-100-side and have no ND-500-side operation. So the MON 60 FLAGS path never reachesFPT2ENTRY/5FP2E, never builds a 5MPM message, never drives the bus. -
What the handler actually does [NPL] —
RRFLAG/WWFLAG@5P-P2-MON60.NPL:1516-1538:The two flag words [SYMBOL/NPL,IF 5D12 = -1 THEN X := 5PRDESCR % -1 = own process ELSE validate 5SWPROC < procno <= MX5PROCS, RTRES != 0; X := actual process descriptor X := X.MESSBUFF; *SENDE@3 LDATX A - 5SWPROC*2 + "F5DSG" =: T; CALL M1MEXY; T =: 5OLDSEG % MAP the ND-500 DATA SEGMENT IF 5FUNCTION = 5RFLAG THEN AD := "FF500".DS0 =: 5DD2 % READ flag word FROM N500 ELSE (auth guard: only RT-prog or user SYSTEM may write another proc) AD := 5DD2 =: "FT500".DS0 % WRITE flag word TO N500 FI; T := 5OLDSEG; CALL M1MEXY % restore caller's segments IF 5RFLAG THEN X := 5P2; AD := 5DD2; CALL STDS0 FI % copy flags to user param2 GO FAR 5OKRET5P-P2-MON60.NPL:141-146]:DASEGSTART = 166000B(start of ND-500 data segment),FT500 = 166002B(flag-word to N500, written by SFLAG),FF500 = 166004B(flag-word from N500, read by RFLAG). These are logical addresses inside the process's data segment, reached only afterM1MEXYmaps that segment;DS0is data-segment-relative addressing. No bus register, no activate.
Parameter block (for the emulator)¶
| Subfn | A (thunk) | param1 @,X 6 |
param2 @,X 7 |
5IFUNC / FUNCS |
|---|---|---|---|---|
| RFLAG | 100B SAA 100 |
ptr → process number (-1=own) |
ptr → flag word (server writes; caller reads back) | RRFLAG / ERRFP |
| SFLAG | 101B SAA 101 |
ptr → process number (-1=own) |
ptr → flag value to write | WWFLAG / ERRFP |
Emulator test-vector (a)¶
- Drive
MON 60withA=0o100, param1→word=-1, param2→a flag cell. Expected bus trace: EMPTY — noLoadMarX2, noLCON5:=5 ACTIVATE, noMSGHDR/PROCMSGfor this command. The only bus events that may appear in the window are the incidental watchdog poll (b), byte-identical regardless of RFLAG/SFLAG. - Functionally, the value comes from ND-500 data-segment memory at logical
FF500=166004B/FT500=166002Bof the process's data segment (the process data segment physically lives in the multiport/5MPM region, reached by ND-100 memory access after the page-table map — not by the message protocol).
Divergence vs current emulator¶
- The emulator returns
GET-FLAG=0Bwith no bus traffic — bus behaviour is correct (there is no round-trip to model). The gap is only that the flag value is not backed by a real per-process data-segment cell; with the ND-500 stopped and no data segment allocated,0is defensible. If/when the emulator maps a process data segment, RFLAG must readdata_seg + 166004Band SFLAG writedata_seg + 166002B; SFLAG on another process must enforce the RT-program / user-SYSTEM guard (EENAUTHORISED). - [ASSUMPTION] L07 byte body of
RRFLAG/WWFLAGin050-S3I5PITis not yet located (README: "L07 body loc pending"); the read/write mechanism above is NPL + the ERRFP byte fact, not a byte disassembly of the L07 handler. It is consistent with all bytes we have but is marked accordingly.
(b) The background poll — ReadMicroVersion = the WATCHDOG (3RMICV). Site-B decode CONFIRMED.¶
What issues it [NPL]: the ND-500 watchdog / time-out machinery in RP-P2-N500.NPL. It is a
timer-driven poll on the monitor level, not per monitor command and not an RT busy-loop.
- Build (RP:282, RP:384):
X:=WATCHDOG; T:=5MBBANK; 3RMICV; *MICFU@3 STATX— setMICFU=3RMICV(=1)in the WATCHDOG buffer;MSGN500; CALL WN5STATUS(N5STA:=1);CALL ITO500XQ(queue to the ND-500 exec queue);X=:TMRXQ; LTTMR=:TMR(arm the timer). - XMSINIT (RP:820-822):
A:=-1; *SENDE@3 STATX("SET SENDER=-1 IN WATCHDOG MESS");3RMICV; *MICFU@3 STATX. So the watchdog buffer is permanently stamped SENDE=-1, MICFU=3RMICV=1. - N500TMR (RP:305-347, "called in IOF"): on each timer tick, if the outstanding timer item is the
WATCHDOG it reads the watchdog's
N5STA— if notANSWER(3)yet →N5TIMOUT/RSTARTALL(master-clear); ifANSWER(3)→ re-armLTTMR=:TMRand re-send (XLOWACT500). Self-perpetuating. - Cadence [SYMBOL]: re-arm interval =
LTTMR = 000023B(= 19 dec) time units (TTMR = 177774B= -4 is the short/error variant). The wall-clock period depends on SINTRAN's basic time unit — [ASSUMPTION] LTTMR is the tick count, the absolute seconds are not pinned from bytes. The point: it is a fixed-interval watchdog timer, which is exactly why it lands incidentally inside random command capture windows (LIST-ACTIVE-PROCESSES, GET-FLAG) and is byte-identical across them.
The MESSAGE BLOCK (site B = the WATCHDOG buffer) — architect decode CONFIRMED byte-for-byte.
Capture 0x424130 AFTER: FF FF FF FF 00 03 FF FF 00 00 00 00 00 01 2E 9A. As 16-bit big-endian words
from the message base, mapped to the catalog header layout (N500-SYMBOLS):
| word | byte off | value | field | meaning |
|---|---|---|---|---|
| 0-1 | 0x424130 | FFFF FFFF |
LINK/LINK2 | queue link = -1 |
| 2 | 0x424134 | 0003 |
N5STA | ANSWER(3) |
| 3 | 0x424136 | FFFF |
SENDE | -1 = WATCHDOG sender (RP:821) |
| 4 | 0x424138 | 0000 |
X5CPU | — |
| 5 | 0x42413A | 0000 |
X5ACT | — |
| 6 | 0x42413C | 0001 |
MICFU | 3RMICV(1) = ReadMicroVersion |
| 7 | 0x42413E | 2E9A |
data | 0x2E9A = 11930 = 027232B = microprogram version |
- CONFIRMED, and strengthened: the architect's
0x2E9A=11930=MicroVersion,00 03=N5STA ANSWER(3)are exactly right. The extra proof is word 3SENDE=0xFFFF=-1, the XMSINIT watchdog marker — this is specifically the WATCHDOG (3RMICV) answer buffer, not merely "a ReadMicroVersion mailbox," and categorically not the ring.3RMICV= the watchdog per the catalog (§2) and RP source. - Version cross-check:
027232B = 11930 = 0x2E9Amatches the ND-5800/B30 microcodeVERSIONword (catalog §7) and the monitor'sMicro program 11930console line.
"ResidentRead" (the other periodic type): in the site-A AFTER capture the buffer was reused with
MICFU = 0x0008 = 10B = 3RMED (resident/absolute-memory read) and got N5STA = 0x0004 = 5ERANSWER.
3RMED is a memory read (DMA/absolute); it is triggered by commands that read ND-500 memory (memory
examine, the config/sizing pattern test, LIST-TABLE's own reads) — not the fixed watchdog timer.
Its exact per-command trigger is [OPEN] (not carved this pass).
Emulator test-vector (b)¶
- Fire an activate whose MAR points at the watchdog buffer; the servicer must answer:
N5STA(word2):=0x0003, leaveSENDE(word3)=0xFFFF,MICFU(word6)=0x0001, and write the version atword7 = 0x2E9A(source it from the loaded control-store image, not a hardcode — classic-500 images must self-report their own 105xx/106xx; see status §7). Poll expected on the LTTMR interval, unsolicited, independent of any monitor command.
Divergence vs current emulator¶
- The emulator already completes this round-trip cleanly (
PROCMSG processed=1,lastMICFU=ReadMicroVersion,ND500Finished) — transport is correct. Two notes: (1) it decodes the poll generically as "ReadMicroVersion" without checkingSENDE=-1, so it does not label it the watchdog — cosmetic. (2)3RMED/"ResidentRead" is answered5ERANSWER(4)in the site-A AFTER capture; whether that rejection is intended is [OPEN] and worth a look (it may be the same ND-500-memory-not-present situation as the sizing probe, in which case 5ERANSWER is fine).
(c) LAST-N500-MSG ring — site A is a MESSAGE BUFFER, not the ring. Architect "03→04 index" REFUTED.¶
Finding: site A (0x420E30) is a 128-word (200B) ND-500 message buffer, structurally identical to the
site-B watchdog buffer but for a real process (SENDE=1, X5CPU=1). It is NOT the LAST-N500-MSG ring, and
the 0x420E35 "03→04" is the N5STA status word flipping ANSWER→5ERANSWER on a REUSED buffer, not a ring
head/tail index.
Site A header decode [BYTES], BEFORE FF FF FF FF 00 03 00 01 00 01 00 00 00 01 2E 9A:
| word | byte off | BEFORE | AFTER | field | meaning |
|---|---|---|---|---|---|
| 0-1 | 0x420E30 | FFFF FFFF |
FFFF FFFF |
LINK | -1 |
| 2 | 0x420E34 | 0003 |
0004 |
N5STA | ANSWER(3) → 5ERANSWER(4) |
| 3 | 0x420E36 | 0001 |
0001 |
SENDE | sender = process 1 (not -1 → not watchdog) |
| 4 | 0x420E38 | 0001 |
0000 |
X5CPU | CPU 1 |
| 5 | 0x420E3A | 0000 |
0000 |
X5ACT | — |
| 6 | 0x420E3C | 0001 |
0008 |
MICFU | 3RMICV(1) → 3RMED(10B) ResidentRead |
| 7 | 0x420E3E | 2E9A |
0801… |
data | version 11930 → new payload |
- So across
LIST-TABLE, this one buffer was reused: a ReadMicroVersion answer (MICFU=1, N5STA=3) was overwritten by a ResidentRead (MICFU=8=10B) that got 5ERANSWER (N5STA=4). The architect's candidate "ring index 03→04 at 0x420E35" is the low byte of N5STA — a message-status change, not an index advance. Refuted. - The "incrementing 16-byte records
11 E6, 11 F4 … 11 FB" at0x420E40+are inside the 128-word message DATA part (offsets ≥8B of the same buffer; a 200B message spans0x420E30–0x420F30). They are message/descriptor payload (or stale content), not a ring of separate records. Note the stride is irregular at the ends (E67→EA7 is a clean 16B, but E4C, ECA, ED7 break it), which is inconsistent with a fixed-record ring and consistent with structured message data. - The tail
00 01 2E 9Aappearing at both sites is simply the sameMICFU=1 / version=11930answer written into two different message buffers (watchdog @site B, process-1 MESSBUFF @site A) — not a shared ring.
Where is the actual LAST-N500-MSG ring? [UNRESOLVED / ASSUMPTION]. I could not byte-locate a
"last 64 messages to ND-500" ring:
- No symbol for it in the L07 tables or the NPL tree (searched LAST-N500, L5MSG, LI5MSG,
LASTMSG, "last 64" — zero hits). The 5IFUNC table has no last-message-ring subfunction (the
nearest listing subfunctions are 133B ILI5EXQ LIST-EXECUTION-QUEUE and 150B ILI5TQU
LIST-TIME-QUEUE — neither is this ring).
- LIST-TABLE is an ND-500-MON:PROG monitor command (ND-60.136 §8.10.9.1). [ASSUMPTION] the
"last 64 messages" ring is a log the monitor program keeps in its own program memory as it sends
MON 60 messages, rendered internally by LIST-TABLE — i.e. it is not a structure in the 5MPM window
at all. Site A is therefore the wrong place to look for it; the raw MPM does not evidence it.
- Record size / capacity(64?) / head-tail pointers: UNRESOLVED. Not guessed. To settle it, carve
the LIST-TABLE handler inside ND-500-MON:PROG (find the "LAST-N500-MSG" table descriptor in the
program's own DSEG) — that binary, not the 5MPM window, is where this lives.
Why the terminal render was empty. LIST-TABLE LAST-N500-MSG printed only > Loading Swapper and
returned. [ASSUMPTION, consistent with all evidence]: with no ND-500 microengine executing real
work, essentially only watchdog/version and a few memory-probe messages have been "sent," so the
monitor's ring log is empty/near-empty; the command also tripped a control-store/swapper-load attempt
(the "> Loading Swapper" line) rather than dumping records. The ring populates only when the monitor
actually drives the ND-500. This is not a 5MPM-window artifact.
Emulator test-vector (c)¶
- Do not assert the emulator's captured 5MPM writes against a "site-A ring." The correct
cross-check target is the ND-500-MON program's internal log, which the harness cannot see from the
MPM window. If a ring cross-check is wanted, it must come from disassembling
LIST-TABLEinND-500-MON:PROGand reading the ring out of the program's DSEG — flagged as the next carve. - Byte-level: treat
0x420E30–0x420F30as one 200B process-1 message buffer (negative-offset header atMAGNO=-3etc.), reused per poll; do not model it as 64×16B records.
Divergence vs current emulator¶
- The emulator's
SnapshotMpmAccess()captures message buffers correctly, but there is no ring in those buffers to match againstLIST-TABLE LAST-N500-MSG. The F6 "strongest cross-check" in the expectation tables (DOMAIN-HANDLING-TWO-INTERFACE-EXPECTATION-TABLES) rests on a ring format that is [TC]/unlocated; it cannot be closed from the MPM window and should be re-scoped to the monitor program's own memory.
Bottom line for the bus team¶
- (a) RFLAG/SFLAG are ND-100-side memory operations on the process data segment
(
FF500=166004B/FT500=166002B, mapped byM1MEXY);FUNCS[100/101]=ERRFP=141574B[BYTES] proves there is no ND-500-side op and no 3022 crossing. Emulator "no bus traffic" is correct. - (b) The periodic poll is the watchdog
3RMICV(MICFU=1, SENDE=-1), timer-armed byLTTMR, re-sent on eachANSWER. Site-B decode CONFIRMED byte-for-byte (and it is the watchdog buffer, not the ring). Answer withN5STA=3, version0x2E9Aat word 7. - (c) Site A is a reused 200B message buffer, not the LAST-N500-MSG ring; the
03→04is N5STA, not an index. The ring itself is not in the 5MPM window and is [UNRESOLVED] — it lives inND-500-MON:PROGmemory; carveLIST-TABLEthere to get the format.