ND-500 Instruction Semantics Reference¶
Authoritative reference for translating carved ND-500 (32-bit) disassembly
into correct pseudo-C. Every semantic statement below is grounded in the
nd500x emulator source (the executable ground truth for what each
instruction does) or the ND-500 Reference Manual bundled with it. The
disassembly notation (the r., b., $, :=, if << go forms our
.ASM files use) is defined by the ragge nd500-dis instruction table.
Scope: the ND-500 (32-bit) instruction set, prioritizing the mnemonics
that actually appear in the carved S3SM5 MON handlers
(410B, 411B, 412B, 413B, 416B, 417B under
../mon-analysis/). Every mnemonic occurring in those six exemplar .ASM
files is covered (see cheat sheet).
Sources cited¶
| Tag | File | What it establishes |
|---|---|---|
| REGS | ~/repos/nd500x/src/cpu/cpu_protos.h:43-99 |
Register model (Nd500Cpu struct) |
| FLAGS | ~/repos/nd500x/src/cpu/instruction_helpers.h:305-314 |
Status-flag bit positions in ST1 |
| DEC | ~/repos/nd500x/src/cpu/cpu_instr.c:302-324 |
address_code -> addressing mode |
| EA | ~/repos/nd500x/src/cpu/cpu_instr.c:664-772 |
effective-address computation |
| FMT | ~/repos/nd500x/src/disasm/nd500_disasm.c:140-324 |
operand notation / register banks |
| TRAP | ~/repos/nd500x/src/cpu/cpu_protos.h:101-145 |
trap bit definitions |
| DOMAIN | ~/repos/nd500x/src/cpu/nd500_domain.h |
domain / stack-limit registers |
| per-instruction | ~/repos/nd500x/src/cpu/instructions/<CLASS>/<Name>.c |
exact operation of that instruction |
| TAB | ~/repos/ragge/pcc-nd500/src/nd500-dis/nd500_instructions.h |
opcode -> disassembler mnemonic |
| MANUAL | ~/repos/nd500x/docs/ND-05.009.4 EN ND-500 Reference Manual.md |
official manual (section numbers) |
NOTE on tooling: our carves are disassembled with ragge nd500-dis; its
notation differs from nd500x's built-in disassembler (e.g. ragge prints
@b.N and DESC(rN) where nd500x prints IND(b.N) and DESCn(...)).
The two share the same opcode->mnemonic table origin, and the semantics
are nd500x's. Where the two disagree on wording this document follows the
ragge output because that is what the .ASM files contain.
1. Cheat sheet — mnemonics appearing in the carved S3SM5 handlers¶
t = data-type prefix (bi,by,h,w,f,d); n = register index 1-4
shown as e.g. w3, f1, d4. src/dst = an operand resolved per the
addressing-mode table (Section 3).
| nd500-dis form | One-line C meaning | Section |
|---|---|---|
tn := src |
Rn = src; (load, zero-extend sub-word) |
5.1 |
tn =: dst |
dst = Rn; (store) |
5.2 |
t stz dst |
dst = 0; |
5.3 |
tn clr |
Rn = 0; |
5.4 |
t move src,dst |
dst = src; |
5.5 |
tn neg |
Rn = -Rn; |
5.6 |
t set1 dst |
dst = 1; |
5.7 |
tn + src |
Rn = Rn + src; |
6.1 |
tn - src |
Rn = Rn - src; |
6.1 |
tn * src |
Rn = Rn * src; |
6.1 |
tn mulad x,y |
Rn = Rn * x + y; |
6.2 |
tn comp src |
set flags from Rn - src (Rn unchanged) |
6.3 |
t comp2 a,b |
set flags from a - b (nothing stored) |
6.3 |
t test src |
set Z/S from src vs 0; C=1 (int) |
6.4 |
tn lind idx,lo,hi |
Rn = idx; then bounds-check -> K/IX |
6.5 |
tn cind idx,lo,hi |
bounds-check idx in [lo,hi] -> K/IX (no load) |
6.5 |
go d |
goto pc+d; (unconditional) |
7.1 |
if = go d |
if (Z) goto pc+d; (equal) |
7.2 |
if >< go d |
if (!Z) goto pc+d; (not equal) |
7.2 |
if > go d |
if (!S && !Z) goto pc+d; (signed >) |
7.2 |
if < go d |
if (S) goto pc+d; (signed <) |
7.2 |
if >= go d |
if (!S) goto pc+d; (signed >=) |
7.2 |
if <= go d |
if (S \|\| Z) goto pc+d; (signed <=) |
7.2 |
if >> go d |
if (C && !Z) goto pc+d; (unsigned >) |
7.2 |
if >>= go d |
if (C) goto pc+d; (unsigned >=) |
7.2 |
if << go d |
if (!C) goto pc+d; (unsigned <) |
7.2 |
if <<= go d |
if (!C \|\| Z) goto pc+d; (unsigned <=) |
7.2 |
if -k go d |
if (!K) goto pc+d; |
7.2 |
entsn dem,maxargs |
build stack frame; enter subroutine (bounded argc) | 8.2 |
entf area |
enter subroutine using fixed (static) data area | 8.2 |
init bos,dmain,dtot |
initialize stack: set B, TOS, frame header | 8.1 |
retd |
PC = L; (return, no frame unwind) |
8.3 |
noop |
do nothing | 5.8 |
bp |
breakpoint trap (BPT) / illegal-instruction | 5.9 |
??? ; opcode 0xNN |
NOT an instruction — mis-aligned byte (see 9) | 9 |
The DESC(rN) wrapper on an operand (e.g. by1 := DESC(r3) $0xF) is an
operand prefix, not a separate instruction; see Section 3.4.
2. Register model (REGS, DOMAIN)¶
All ND-500 programmable registers are 32-bit; the machine is big-endian (FMT lines 145-149; carve headers).
General / accumulator registers (REGS cpu_protos.h:47-50)¶
| Name | Struct field | Role |
|---|---|---|
I1..I4 |
I[0..3] |
integer registers; targets of BY/H/W ops. In disasm shown as W1..W4 for BYTE/HALFWORD/WORD dtypes (FMT 202-217). |
A1..A4 |
A[0..3] |
float accumulators; shown as F1..F4 for FLOAT dtype. |
E1..E4 |
E[0..3] |
float extension; A+E pair forms the 64-bit D1..D4 double register shown for DOUBLEWORD dtype. |
So a disasm token like w3 = integer register I3; f2 = float A2;
d4 = double A4:E4. The register index and data type are encoded in
the opcode, not in an operand — see the per-instruction opcode ranges.
Addressing / linkage registers (REGS cpu_protos.h:52-54)¶
| Name | Field | Role |
|---|---|---|
L |
L |
Link register — holds return address (set by CALL; restored to PC by RETD). |
B |
B |
Local base — base for b. (LOCAL) operands and current stack frame. |
R |
R |
Record base — base for r. (RECORD) operands. |
PC |
PC |
Program counter (called P in the manual). |
Stack-limit / domain registers (REGS cpu_protos.h:56-68, DOMAIN)¶
TOS (top-of-stack limit), LL (lower limit), HL (higher limit),
THA (trap handler address), CED (current executing domain),
CAD (current alternative domain), PS, PSTP, DITBASE, plus control
registers OTE1/2 CTE1/2 MTE1/2 TEMM1/2. Stack frame layout used by the
ENT/INIT/RET family (per DOMAIN nd500_domain.h:38-51 and
CALL/Entsn.c, CONTROL/Init.c):
B+0 PREVB previous B B+12 AUX auxiliary
B+4 RETA return address B+16 N argument count
B+8 SP stack pointer B+20+ ARGn argument addresses
Status register ST1 — flag bit positions (FLAGS)¶
| Flag | Bit | Meaning |
|---|---|---|
Z |
5 | zero |
C |
6 | carry — ND-500 convention: C=1 means NO borrow (i.e. a >= b after a subtract/compare). See COMPARE/Comp.c, ARITHMETIC/Sub2.c. |
S |
7 | sign (result negative) |
K |
8 | "destination full" / index-out-of-bounds condition flag |
O |
9 | overflow |
Higher ST1 bits hold ignorable-trap status bits, e.g. IX (Illegal
Index) = bit 26, STO (Stack Overflow) = bit 27 (TRAP; used by LIND/CIND
and the ENT*/INIT family).
3. Addressing modes / operand notation (DEC, EA, FMT)¶
The first byte after the opcode is the operand address_code; DEC maps it to a mode, EA computes the effective address. Displacements in LOCAL/RECORD/PREINDEXED modes are UNSIGNED (FMT 7-30, EA 638-654, MANUAL §8.4). Branch displacements are SIGNED (Section 7).
3.1 nd500-dis notation seen in the carves¶
| Disasm token | Mode (DEC) | Effective address / value (EA) |
|---|---|---|
$K (small) |
CONSTANT_SHORT | immediate 6-bit signed constant (FMT 178-184) |
$K (with data) |
CONSTANT / ABSOLUTE | immediate literal, or absolute address $addr (FMT 276-299) |
$<double> |
CONSTANT (8-byte) | 64-bit immediate literal |
b.D |
LOCAL (0xC1-0xC3) | B + D (D unsigned) — EA 691-697 |
b.D (short) |
LOCAL_SHORT (top=0x01) | B + low6*4 — EA 699-702 |
r.D |
RECORD (0xC9-0xCB) | R + D (D unsigned) — EA 704-707 |
r.D (short) |
RECORD_SHORT (top=0x02) | R + low6*4 — EA 709-712 |
rN.(D) |
PREINDEXED (0xF4-0xFF) | I[N] + D (D unsigned) — EA 714-722 |
@b.D |
LOCAL_IND (0xC5-0xC7) | mem32[B + D] (indirect) — EA 736-741 |
@b.D(rN) |
LOCAL_IND_PI (0xE4-0xEF) | mem32[B+D] + I[N]*scale — EA 750-772 |
b.D(rN) |
LOCAL_PI (0xD4-0xDF) | B + D + I[N]*scale |
$addr(rN) |
ABSOLUTE_PI (0xE0-0xE3) | addr + I[N]*scale |
Wn/Fn/Dn (as operand) |
REGISTER (0xD0-0xD3) | the register itself (no memory) — DEC 316 |
scale in post-indexed modes = data-element size (BYTE=1, HALF=2, WORD=4,
DOUBLE=8) — EA 759-772. For BIT dtype the index is a bit offset and sets
bit_position (EA 762-772).
3.2 Register bank shown for REGISTER-mode operands (FMT 202-217)¶
FLOAT dtype -> F1..F4; DOUBLEWORD -> D1..D4; everything else -> W1..W4.
3.3 Data-type prefix letters¶
bi=BIT, by=BYTE(8), h=HALFWORD(16), w=WORD(32), f=FLOAT(32),
d=DOUBLEWORD(64). Loads of sub-word types zero-extend into the 32-bit
register (MOVE/AssignTo.c description).
3.4 DESC(rN) and ALT(...) operand prefixes (FMT 151-162, DEC 320)¶
address_code 0xF0-0xF3 is a descriptor prefix (DESC(rN)), 0xC8 an
alternative-domain prefix (ALT(...)). These wrap the following
operand; they change how the operand is fetched (descriptor / alternate
domain) but are not standalone instructions. In carved output such as
by1 := DESC(r3) $0xF, the DESC(r3) decorates the source operand of the
:= load.
4. The MON / subroutine-call mechanism¶
There is no ND-500 "MON" opcode. The SINTRAN MON numbers (e.g. 410B
FixInMemory) are ND-100-side monitor-call numbers. Their ND-500 handler
bodies live in the S3SM5 in-memory segment and are reached through
SINTRAN's own software dispatch: the 0x60 MON vector table in
030-S3SM5.bin (vector slot = 0x60 + 2*<octal MON no.>), as documented
in each carve's header and folder README. The ND-500 CPU reaches them by an
ordinary subroutine transfer, not a dedicated trap opcode.
ND-500 subroutine linkage proper is CALL/CALLG + one of the ENT
entry-point instructions + a RET return (CALL/Call.c lines 95-140):
CALL/CALLGpush nothing yet; they record the return address inLand a pending arg list, then transfer to the callee entry point. The callee's first instruction must be an ENT* (ISE trap otherwise —CALL/Call.c130-140).- The
nd500xCALL path also intercepts indirect segment calls that implement SINTRAN MON dispatch and completes them in-line (CALL/Call.c:105-123,INDIRECT_HANDLED). - ENT builds the stack frame (Section 8); RET tears it down / restores PC.
JUMPS/JUMPG are unconditional absolute jumps (BRANCH/Jumps.c).
NOTE: the manual-mapping table (INSTRUCTION_DOCUMENTATION_STATUS.md) maps
jumps to MANUAL §16.34 "jump to supervisor", but nd500x's Jumps.c
implements it as an ordinary absolute jump. UNRESOLVED (documentation vs
implementation conflict); neither appears in the six exemplars.
5. Load / store / move / clear class (MOVE, CONTROL)¶
5.1 tn := src — AssignTo (load register)¶
MOVE/AssignTo.c; MANUAL §10.1. Opcodes 0xFC04-07 (BI), 0x0004-07 (BY),
0x0008-0B (H), 0x000C-0F (W), 0x0010-13 (F), 0x0014-17 (D).
Operation: Rn = src, right-justified; sub-word (BI/BY/H) types
zero-fill the upper register. Flags: Z, S set from the loaded value.
Register/dtype come from the opcode. C pseudo: I3 = mem[R+0xE8];
5.2 tn =: dst — AssignFrom (store register)¶
MOVE/AssignFrom.c; MANUAL §10.4. Opcodes 0x001C-1F (BY), 0x0020-23 (W),
0x0024-27 (F), 0x0028-2B (D), 0xFC0C-0F (BI), 0xFC10-13 (H).
Operation: dst = Rn (datatype-sized). Source register unaffected.
Flags: Z, S from the stored value. C pseudo: mem[R+0x34] = I2;
Related (not in exemplars but same family): b:=/r:= load B/R from a
source (AssignToBaseReg semantics reversed), b=:/r=: store B/R
(MOVE/AssignToBaseReg.c §10.5, AssignToRecordReg.c §10.6).
5.3 t stz dst — Stz (store zero)¶
MOVE/Stz.c. Opcodes 0x0048 (BY), 0x0049 (H), 0x004A (W), 0x004B (F),
0x004C (D), 0xFC85 (BI). Operation: dst = 0. Flags: Z=1, S=0.
C pseudo: mem[...] = 0;
5.4 tn clr — Clr (clear register)¶
MOVE/Clr.c; MANUAL §10.16. Opcodes 0x0084 (int), 0x0088 (F), 0x008C (D);
register in low 2 bits. Operation: Rn = 0 (whole register; for D also
clears E). Flags: Z=1, S=0. Zero operands. C pseudo: I1 = 0;
5.5 t move src,dst — Move¶
MOVE/Move.c; MANUAL §10.7. Opcodes 0x0019 (BY), 0x001A (W), 0x001B (F),
0x002C (D), 0xFC0B (BI), 0xFC14 (H). Operation: dst = src; source
unaffected. Flags: Z, S from the value. C pseudo: mem[R+0x21]=mem[...] —
2 operands, source first.
5.6 tn neg — Neg (negate register)¶
ARITHMETIC/Neg.c; MANUAL §10.12. Opcodes 0x0090-93 (W), 0x0094-97 (F/D),
0xFE08-0B (BY), 0xFE0C-0F (H). Integer: two's complement Rn = -Rn
(sub-word clears upper bits); float/double: flip sign bit. Zero operands.
Flags: Z, S, C (C=1 iff negating 0), O (O=1 iff negating the greatest
negative integer -> overflow trap).
5.7 t set1 dst — Set1 (set to one)¶
CONTROL/Set1.c; MANUAL §10.18. Opcodes 0x004D (W), 0x0047 (F),
0xFC86/87/88/89 (BI/BY/H/D). Operation: dst = 1. Flags: Z=S=C=O=0.
5.8 noop — Noop¶
CONTROL/Noop.c; MANUAL §15.13. Does nothing; PC advances. No flags.
5.9 bp — Breakpoint¶
CONTROL/Bp.c; MANUAL §16.1. Raises the Breakpoint Trap (BPT) when
enabled, else an Illegal-Instruction (IIC) trap. In nd500x it currently
logs and lets the debugger intercept. Zero operands, no flags. Opcode 0x02.
6. Arithmetic / compare / index class (ARITHMETIC, COMPARE, SYSTEM)¶
6.1 tn + src / tn - src / tn * src — Add / Subtract / Multiply¶
ARITHMETIC/Add.c, Subtract.c, Multiply.c; MANUAL §11.
One explicit operand; the target register Rn is both a source and the
destination.
- + opcodes 0x0054 (W)/0x0058 (F)/0x005C (D)/0xFC34 (BY)/0xFC38 (H):
Rn = Rn + src.
- - opcodes 0x0060 (W)/0x0064 (F)/0x0068 (D)/0xFC3C (BY)/0xFC40 (H):
Rn = Rn - src.
- * opcodes 0x006C (W)/0x0070 (F)/0x0074 (D)/0xFC44 (BY)/0xFC48 (H):
Rn = Rn * src.
Integer arithmetic is signed with datatype-sized wrap; flags Z, S, C, O set
(carry per ND-500 no-borrow convention; O -> overflow trap). Example
w3 - r.0xCC => I3 = I3 - mem[R+0xCC];
NOTE: two-explicit-operand forms add2/sub2/mul2 (ARITHMETIC/Add2.c
etc., dst = dst OP src) exist and share the +/-/* mnemonics for
higher opcodes; the exemplars use the 1-operand register forms above.
6.2 tn mulad x,y — Mulad (multiply and add / sum of products)¶
ARITHMETIC/Mulad.c; MANUAL §11.20. Two operands. Operation:
Rn = Rn * x + y (signed, datatype-sized). Flags Z, S, C, O.
C pseudo: I3 = I3 * x + y;
6.3 tn comp src / t comp2 a,b — Comp / Comp2 (compare)¶
COMPARE/Comp.c (MANUAL §10.9) and COMPARE/Comp2.c (§10.10).
- comp: one operand; computes Rn - src, stores nothing, sets flags.
Z=(Rn==src), C=(Rn>=src) [no-borrow], S=sign, O=signed overflow.
- comp2: two operands; computes a - b, stores nothing, same flags.
Used before the if <cc> go branches to set the condition.
6.4 t test src — Test (test against zero)¶
COMPARE/Test.c; MANUAL §10.11. One operand. Sets Z and S from src
compared to 0; for integer types also forces C=1. Nothing stored.
C pseudo: Z = (src==0); S = (src<0);
6.5 tn lind idx,lo,hi / tn cind idx,lo,hi — Lind / Cind (index bounds check)¶
SYSTEM/Lind.c (MANUAL §15.8) and SYSTEM/Cind.c (§15.9). Three operands
(index, lower, upper), signed comparison after sign-extension.
- lind: Rn = idx; then if idx < lo || idx > hi set K=1 and IX=1
(bit 26 of ST1) else clear both. (LIND loads the index into Rn.)
- cind: identical bounds check but does not load Rn (calculate
index only). Used for array-bounds validation.
Opcodes: lind W=0xAC-AF, cind W=0xB0-B3 (plus BY/H/F/D variants).
7. Branches (BRANCH) — displacements are SIGNED¶
Branch operand is a signed PC-relative displacement; target =
instruction_start_address + displacement (BRANCH/Go.c,
nd500_get_operand_displacement in FMT 350-363, and the is_pc_relative
path FMT 519-535). The disassembler prints the operand value; treat it as a
displacement from the instruction's own address, not an absolute address.
(In mis-aligned mid-block carves the printed target is meaningless — see 9.)
7.1 go d — Go (unconditional)¶
BRANCH/Go.c; MANUAL §13.2. Opcode 0x00C0. PC = addr + d. No flags.
7.2 Conditional if <cc> go d¶
Each tests ST1 flags set by a preceding compare/test/arithmetic; if true,
PC = addr + d, else fall through. Flags are not modified. Opcode/condition
map (TAB 0x00C4..0x00DA, semantics from the named BRANCH/*.c files):
| Disasm | Opcode | Branch taken when | nd500x file |
|---|---|---|---|
if = go |
0x00C4 | Z==1 |
IfEqualGo.c |
if >< go |
0x00C6 | Z==0 |
IfNotEqualGo.c |
if > go |
0x00C8 | S==0 && Z==0 |
IfGreaterThanGo.c |
if < go |
0x00CA | S==1 |
IfLessThanGo.c |
if >= go |
0x00CC | S==0 |
IfGreaterEqualGo.c |
if <= go |
0x00CE | S==1 \|\| Z==1 |
IfLessEqualGo.c |
if k go |
0x00D0 | K==1 |
IfKeyGo.c* |
if -k go |
0x00D2 | K==0 |
IfKeyGo.c* |
if >> go |
0x00D4 | C==1 && Z==0 (unsigned >) |
IfUnsignedGreaterGo.c |
if >>= go |
0x00D6 | C==1 (unsigned >=) |
IfUnsignedGreaterEqualGo.c |
if << go |
0x00D8 | C==0 (unsigned <) |
IfUnsignedLessGo.c |
if <<= go |
0x00DA | C==0 \|\| Z==1 (unsigned <=) |
IfUnsignedLessEqualGo.c |
* IfKeyGo.c implements the branch-when-K-clear variant (if -k go). The
if k go (0x00D0) branch-when-K-set variant is the complementary opcode;
the exemplars (411B) use if -k go. The signed >/>=/</<= forms use
S and Z; the unsigned >>/>>=/<</<<= forms use C (ND-500 no-borrow
carry) and Z.
Also in the family (not in exemplars): if st go (IfStackGo,
BRANCH/IfStackGo.c) — 2 operands, tests a numbered ST1 bit and branches
if clear, setting BT; loop/loopd/loopi (MANUAL §13.4).
8. Entry / stack / return class (CALL, CONTROL)¶
Stack frame field offsets are fixed by the architecture (Section 2).
8.1 init bos,dmain,dtot — Init (initialize stack)¶
CONTROL/Init.c; MANUAL §13.12. Three WORD operands: bottom-of-stack,
main stack demand, total stack demand. Operation: B = bos;
TOS = bos + dtot; write frame header PREVB=0, RETA=0 at B; L = 0;
SP(B+8) = bos + dmain; clears STO. Traps STO if dmain >= dtot.
Executed once at program start before any CALL.
8.2 entsn dem,maxargs / entf area — entry points¶
Both must be reached via a preceding CALL (else ISE trap).
- entsn (CALL/Entsn.c; opcode 0x00BA; MANUAL §13.10): "enter stack
subroutine, bounded args". new_B = mem[old_B + SP]; STO-checks
new_B + dem >= TOS; writes PREVB=old_B, RETA=return addr, new SP,
N = min(actual_args, maxargs), copies up to maxargs arg addresses;
sets B = new_B, L = return addr.
- entf area (CALL/Entf.c; opcode 0x00DD): "enter with fixed/static data
area". Same header, but B is set to the operand address (a static area,
not the stack), so locals persist between calls; inherits caller's SP.
Family (not in exemplars): ents 0xB8, entd 0x9C, entt 0xBC,
entb 0xBD, entfn 0xDE, entm 0xDF (all MANUAL §13.10, CALL/*.c).
8.3 retd — Retd (return direct)¶
CALL/Retd.c; MANUAL §13.11. Opcode 0x0082. PC = L. No frame unwind, B
unchanged. Pairs with ENTD. Family: ret 0x83, retb, retk, retbk,
rett, ifkret (§13.11, CALL/*.c).
9. ??? ; opcode 0x00NN lines — NOT instructions (mis-alignment)¶
Bytes 0xF1, 0xF2, 0xFB, 0x01 printed as ??? ; opcode 0x00NN are
not standalone opcodes: they are absent from the instruction table
(verified against TAB) because 0xF0-0xFF and the top==0x01/0x02 ranges
are operand address-code / prefix bytes (DEC 316-324), and 0x01 is a
short-form region. They appear only where nd500-dis starts decoding
inside an instruction — i.e. the packed 400B-421B fix-family handlers and
the deliberately mid-block entries (417B at 0xBDF6). The carve headers flag
these regions as low-confidence. In pseudo-C, do not invent semantics
for a ??? line; treat the raw bytes as data whose true meaning depends on
the real (caller-fixed) instruction alignment.
Likewise, any decoded instruction on a mid-block boundary (e.g. the leading
by stz/entsn in 417B, or lines that "spill past" the region end noted in
410B/411B/413B) is decoded from a wrong start byte and its mnemonic is not
trustworthy even though individual bytes are ground truth.
10. Coverage confirmation (six exemplars)¶
Every mnemonic that occurs in
410B-FixInMemory.ASM, 411B-MemoryUnfix.ASM, 412B-FileAsSegment.ASM,
413B-FileNotAsSegment.ASM, 416B-SaveND500Segment.ASM,
417B-MaxPagesInMemory.ASM is covered above:
:=, =:, stz, clr, move, neg, set1, noop, bp (§5);
+, -, *, mulad, comp, comp2, test, lind, cind (§6);
go, if << go, if < go, if > go, if >< go, if >= go,
if <<= go, if >>= go, if -k go (§7);
init, entsn, entf, retd (§8);
??? ; opcode 0x00F1/0x00F2/0x00FB/0x0001 (§9);
plus the operand notations $, $<double>, r., b., rN.(), @b.,
DESC(rN) and the register-prefix letters bi/by/h/w/f/d and indices
1..4 (§2-3).
11. Resolved vs UNRESOLVED summary¶
RESOLVED (semantics grounded in nd500x source + manual section):
- Register model, addressing modes, effective-address computation, flags.
- Load/store/move/clear: :=, =:, stz, clr, move, set1, neg, noop.
- Arithmetic: +, -, *, mulad.
- Compare/index: comp, comp2, test, lind, cind.
- All branch conditions go / if <cc> go including the K and unsigned forms.
- Stack/entry/return: init, entsn, entf, retd (and the wider ENT/RET family).
- MON dispatch mechanism (SINTRAN software vector, not a CPU opcode).
- bp (breakpoint) — resolved at the manual level; nd500x implementation
is a debugger stub pending full trap-enable support.
UNRESOLVED:
- ??? ; opcode 0x00F1/0x00F2/0x00FB/0x0001 — not instructions; mis-aligned
operand/prefix bytes (documented in §9, verified absent from the opcode table).
- jumps — documentation (MANUAL §16.34 "jump to supervisor") conflicts
with nd500x's Jumps.c (absolute jump). Not used by the exemplars; the
conflict is left flagged, not guessed.