RECOVER-DOMAIN's worker, the PLACE sequence, and where the segment-load defect is NOT¶
Date: 2026-08-02
Subject: MON-DEBUG:PROG (ND-500/5000 monitor J04), bank 1
Depends on: COMMAND-DISPATCH-TABLE-CARVED-2026-08-02.md
Status: [V] for the call graph and the negative result; [I] where marked.
1. The result that matters¶
The ND-500 monitor program never reads domain segment content, and was never
supposed to. The routine that performs a segment placement contains no MON
instruction and no IOX instruction anywhere in its 445 words. It issues MON 60
subfunction 006 (ISEGLOAD) once per segment and lets SINTRAN do the fetching.
So the standing observation - "SINTRAN receives two 006 ISEGLOAD requests and the
floppy is never bulk-read; placement is requested, segment content is never fetched" -
cannot be a monitor-side defect. It is on the SINTRAN side of MON 60, or in our
emulation of it. This closes off the caller as a suspect.
2. The call graph, carved¶
RECOVER-DOMAIN (ordinal 8)
-> handler bank1 003577 marshal domain name, JPL I
-> worker bank1 030302 calls subfn 142 x3, and 043011
-> 043011 routine, calls subfn 130
-> ...
PLACE sequence bank1 043547..044062
043547 JPL 146737 -> subfn 140
043552 JPL 146530 -> subfn 055 START-PLACE
043571 JPL 042115 -> the SEGMENT LOADER <-- first segment
044031 JPL 042115 -> the SEGMENT LOADER <-- second segment
044062 JPL 146533 -> subfn 056 END-PLACE
SEGMENT LOADER bank1 042115..043010 (445 words)
042230 JPL 146335 -> subfn 006 ISEGLOAD
042535 JPL 146335 -> subfn 006 ISEGLOAD
This reproduces the live MON 60B trace exactly. That trace recorded
055 START-PLACE, 006, 006, 056 END-PLACE - a correctly bracketed two-segment
placement (:PSEG + :DSEG). The static call graph produces the same four calls in
the same order, from a single loop over two segments. Request side and code side now
agree, independently.
3. How the thunk call sites were resolved¶
MON 60 calls are not MON instructions in this program. They are JPL I <disp>
through a pointer word into the thunk table at 146310-147067 (123 x 3 words):
+0 SAA <subfunction code> (170400 | code)
+1 JMP I 1 (125001)
+2 146244 -> the MON 60 gateway
thunkmap.py walks every JPL in bank 1, resolves one level of indirection, and
accepts a target only if all three thunk words match - so an address that merely
lands in the range cannot be mistaken for a thunk.
It finds 159 call sites, which is exactly the count the original analysis arrived
at independently (nd-500-mon-j04.prog.md, "159 resolvable call sites"). Two
different methods reaching the same number is the check that makes the map usable.
Subfunction 006 has exactly two call sites in the whole image, 042230 and
042535, and both are inside 042115.
4. What the loader hands ISEGLOAD¶
Both call sites marshal an identical parameter shape into the callee frame using
the documented LDX ,B -176 / STx ,X n idiom:
042515 044616 LDA ,B -162
042516 054602 LDX ,B -176
042517 006006 STA ,X 6 ; param 1 := value of B-162
042520 146135 RADD CLD SB DA
042521 172651 AAA -127
042522 006007 STA ,X 7 ; param 2 := ADDRESS B-127
042523 146135 RADD CLD SB DA
042524 172623 AAA -155
042525 006010 STA ,X 10 ; param 3 := ADDRESS B-155
042526 146135 RADD CLD SB DA
042527 172621 AAA -157
042530 006011 STA ,X 11 ; param 4 := ADDRESS B-157
042531 170411 SAA 11
042532 144151 SWAP CLD SA DD
042533 050643 LDT ,B -135
042534 032012 STF ,X 12 ; param 5 := double built from B-135
042535 135034 JPL I 34 ; -> subfn 006 ISEGLOAD
Five parameters. Three of them (2, 3, 4) are the ADDRESSES of caller locals - they
are output slots for SINTRAN to write back into, computed as B + offset by the
RADD CLD SB DA / AAA -n pair.
The RADD CLD SB DA / AAA -n / STA ,X n idiom is how this program passes an
address rather than a value; LDA ,B -n / STA ,X n passes a value. That is the only
distinction between parameter 1 and parameters 2-4 here.
Note the shape. A call that passes the addresses of caller locals for the callee to
fill in, where the write-back is then empty, is the same shape as the swapper's 7-arg
MON 377B (LSWPAGE) already recorded in
nd500-swapfile-required-then-5swap-trap. Whether that is a real connection or a
coincidence of a common calling convention is [OPEN] - it is flagged here only so
the parallel is not discovered twice.
Difference between the two sites: the first is preceded by
LDT ,B -154 / BSET ZRO 160 DT / STT ,B -154, clearing bit 14 of a flag word at
B-154; the second is not. [I] that this selects which of the two segments is being
placed - the parameter marshalling is otherwise byte-identical, so something must
distinguish them, but the flag's meaning is not carved.
5. Where the defect must be, and what is already known there¶
The SINTRAN-side worker is carved at
tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/60B-N500M/60B-006B-ISEGLOAD/.
Its recorded contract:
A:=5P1; T:=200; CALL FRUSMOVE- copy the segment name (param 1, <= 200B bytes) from the user into the MON 60 buffer.- If
5D51 <> 0, copy a shared-part info block from param 5. GO FAR 5NOPAR- "common path performs the place".
Two things follow:
- Param 1 being a name is consistent with what the loader passes (a value that would be
a pointer to the name string).
[I]- the loader'sB-162was not traced back to a name buffer. - Step 3 is where the actual fetch happens, and step 3 is not carved. That folder's own status line says "L07 body byte-location pending (bank-2 5IFUNC)". The handler itself only copies a name; it cannot be what reads a segment off the disc.
So the next carve target is 5NOPAR, the MON 60 common place path - not
RECOVER-DOMAIN, not the loader, and not ISEGLOAD's own handler body.
6. What this does NOT establish¶
- The worker at
030302is only partly read. Its three calls to subfunction142and its call to043011(which issues subfunction130) were identified, but neither routine was carved.142and130are named only by the existing name-based subfunction correspondence, which section 14 of the main analysis still marks as not code-proven. - The route from
030302to the PLACE sequence at043547was not traced. The PLACE sequence and the loader are confirmed by call-site identity and by matching the live trace, not by walking the control flow from the worker into them. A different command could in principle drive the same PLACE code. - The 159-site map names subfunctions from the thunk's
SAAcode, which is exact. What each code means still comes from the name-based table, not from the SINTRAN worker bodies.
7. Reproducing it¶
cd E:\Dev\Ronny\NDInsight\SINTRAN\ND500\nd-500-mon
wsl python3 <tools>/thunkmap.py nd-500-mon-j04-bank1.bin
wsl python3 <tools>/resolve.py nd-500-mon-j04-bank1.bin nd-500-mon-j04-bank2.bin 42115 460
resolve.py exists because the disassembly's -> 042324 annotation on a JPL I names
the pointer word, not the routine. Disassembling the pointer as code yields
plausible nonsense - the trap the carving skill records as "indirect jumps land on
POINTER words, not code". Both scripts live in tools/sintran-segment-carver/.
One gotcha worth recording: JPL is opcode 0o134, not 0o130 (0o130 is the
conditional-jump group). A resolver with that wrong silently resolves nothing at
all and reads as "this routine makes no calls", which is a false negative that looks
exactly like a finding.