Files
LithosAnanake/capsules/v4/rom/math.f18
T
rajamesandClaude Opus 5.5 11b5d402b1 feat(v4): the shared math in both ROMs, and a mesh node's ROM
MACHINE.md 2.2.  UM*, UM/MOD, D+, DNEGATE, Q.* and Q./ are entries 0-5
of the host ROM and of a mesh node's ROM, from one source (rom/math.f18)
and one entry list (v4/rom_entries.h).  The host ROM starts at entry 18.
The mesh ROM is 277 words; the host ROM 2372.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:46:00 -04:00

144 lines
5.0 KiB
Plaintext

\ math.f18 -- the ROM's shared math (docs/v4.0.0/MACHINE.md 2.2).
\
\ Six routines a payload calls through the ROM's entry table, as a GA144
\ application calls its node ROM's multiply and divide steps, and their
\ helpers. Both ROMs carry them: the host node's and a mesh node's. They
\ were the system's (capsules/v4/sys: core.f18, numout.f18, qmath.f18) and
\ do exactly what they did there; the system's words of those names now call
\ these. No names, no headers, no FORTH.
\
\ Constants from the map (tools/mkmap.c): N-1 NODE-ERROR MSB MAXHI 2N+15
\ N-18 N-17, and (Q/), Q./'s five scratch cells, fixed in the memory map
\ (MACHINE.md 2.1).
\
\ ERRORS. Q./ by zero leaves the result D-11 gives and stores 11, "Division
\ by zero", into NODE-ERROR (D-18).
macro SWAP over push push drop pop pop endmacro
macro - push inv pop + inv endmacro \ x y -- x-y
macro NIP push drop pop endmacro
macro ROT push SWAP pop SWAP endmacro
macro OR over inv and xor endmacro
\ ( u1 u2 -- ulo uhi ) entry 0
: (UM*)
over 1 and inv 1 + over 2/ and \ u1 u2 t0 t0 = u2 2/ if u1 odd
over a! N-1 push \ A: u2 R: loop count
push over 2/ pop \ u1 u2 s t0 s = u1 2/
L: +* unext \ u1 u2 s hi A: lo
push drop pop \ u1 u2 hi
2* a -if L0 drop 1 + jump L1 L0: drop L1: push
over -if L2 drop dup jump L3 L2: drop 0 L3: push
dup -if L4 drop over 1 and jump L5 L4: drop 0 L5:
pop + pop + push
and 1 and a 2* + pop ;
\ ( ulo uhi ud -- urem uquot ) entry 1. One step a bit, the divisor in
\ A. Exact for uhi < ud.
: (UM/MOD)
a! N-1 FOR
-if L0
2* over -if L1 drop 1 + jump L2
L1: drop L2: push 2* pop
jump SUB
L0:
2* over -if L3 drop 1 + jump L4
L3: drop L4: push 2* pop
dup a xor -if L5
drop -if NOSUB jump SUB
L5: drop dup inv a + inv -if L6
drop jump NOSUB
L6: push drop pop jump SETBIT
SUB: inv a + inv
SETBIT: push 1 + pop
NOSUB:
NEXT
over push push drop pop pop ;
\ ( d1 d2 -- d3 ) entry 2
: (D+)
push over push push drop pop \ al bl R: bh ah
over over xor -if L1
drop + -if C1 jump C0
L1: drop over -if L2
drop + jump C1
L2: drop +
C0: pop pop + ;
C1: pop pop + 1 + ;
\ ( d -- -d ) entry 3
: (DNEGATE)
inv over if L1 drop push inv 1 + pop ;
L1: drop 1 + ;
\ ( q -- n ) the system's Q.TO-INT, which Q.* needs
: (Q>INT) push a! 0 pop 15 FOR +* UNEXT drop drop a ;
\ ( a b -- c ) entry 4
: (Q.*)
SWAP push over over (UM*) drop
push push over pop
-if L1 SWAP jump L2 L1: SWAP drop 0 L2:
pop SWAP - push
push over pop (UM*) pop +
ROT pop dup push
over -if L3 drop dup jump L4 L3: drop 0 L4:
push (UM*) pop - (D+)
ROT pop (UM*)
SWAP push 0 (D+) pop
push over pop SWAP (Q>INT) push (Q>INT) pop SWAP ;
: (QERR11) NODE-ERROR b! 11 !b ;
: (D2*C) ( lo hi cin -- lo' hi' cout )
a! dup -if L1 drop 1 jump L2 L1: drop 0 L2: push
over -if L3 drop 1 jump L4 L3: drop 0 L4:
over + +
push 2* a + pop pop ;
: (UQ/) ( a0 a1 b0 b1 -- q0 q1 )
(Q/)+2 a! SWAP !+ ! (Q/) a! SWAP !+ ! 0 0 0
2N+15 FOR
push (Q/) a! @+ @ pop (D2*C)
push (Q/)+1 a! ! (Q/) a! ! pop (D2*C)
if CMP drop jump TAKE
CMP: drop (Q/)+3 b! @b
over over xor if EQH -if SAMEH
drop drop -if NT1 jump TAKE NT1: jump NOTAKE
SAMEH: drop over SWAP push inv pop + inv
-if T2 drop jump NOTAKE T2: drop jump TAKE
EQH: drop drop over (Q/)+2 b! @b
over over xor -if SAMEL
drop drop -if NT3 drop jump TAKEL NT3: drop jump NOTAKEL
SAMEL: drop push inv pop + inv
-if T4 drop jump NOTAKEL T4: drop jump TAKEL
TAKEL: drop (Q/)+2 b! @b push inv pop + inv 0 1 jump END
NOTAKEL: 0 jump END
TAKE: push (Q/)+2 b! @b over over push inv pop + inv push
over over xor -if SB drop NIP -if NB drop 1 jump BD NB: drop 0 jump BD
SB: drop push inv pop + inv -if NB2 drop 1 jump BD NB2: drop 0
BD: pop pop (Q/)+3 b! @b push inv pop + inv
push SWAP pop SWAP - 1 jump END
NOTAKE: 0
END:
NEXT
push (Q/) a! @+ @ pop (D2*C) drop push push drop drop pop pop ;
: (Q./) ( a b -- q ) \ entry 5
over over OR if ZERO drop
push over pop SWAP over xor (Q/)+4 b! !b
-if L1 (DNEGATE) L1: push push -if L2 (DNEGATE) L2: pop pop
dup if CHK drop jump DIV
CHK: drop over -131072 and if CHK2 drop jump DIV
CHK2: drop push push dup pop dup push N-18 FOR 2* UNEXT
over over xor -if SAME drop drop -if NOOV jump OV
SAME: drop push inv pop + inv -if OV
NOOV: drop pop pop jump DIV
OV: drop drop drop pop pop drop drop
(Q/)+4 b! @b -if OVP drop 0 MSB ; OVP: drop -1 MAXHI ;
DIV: (UQ/) (Q/)+4 b! @b -if L3 drop (DNEGATE) ; L3: drop ;
ZERO: drop drop drop
over over OR if Z0 drop -if ZP drop drop 0 MSB jump (QERR11)
ZP: drop drop -1 MAXHI jump (QERR11)
Z0: drop jump (QERR11)