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>
This commit is contained in:
rajames
2026-10-15 19:46:00 -04:00
co-authored by Claude Opus 5.5
parent 473e105a69
commit 11b5d402b1
11 changed files with 426 additions and 43 deletions
+17 -1
View File
@@ -8,10 +8,12 @@
* host stack sizes) at one cell width. It writes, as `constant` lines in
* the text assembler's notation, the addresses and codes of
* v4/tests/host_map.h that the ROM's source (capsules/v4/rom) uses: the
* console's receive registers and the ROM's state area (MACHINE.md 2.1).
* console's receive registers, the ROM's state area (MACHINE.md 2.1), the
* math's constants and its shared entries (MACHINE.md 2.2).
* The map has one source, host_map.h; this is how the ROM reads it.
*/
#include "../tests/host_map.h"
#include "../include/v4/rom_entries.h"
#include <stdio.h>
static void constant(const char *name, long value)
@@ -147,5 +149,19 @@ int main(int argc, char **argv)
constant("DEC-LIMIT", (long)(v4_cell)(~(v4_ucell)0 / 10u));
constant("DEC-NLAST", -(long)(~(v4_ucell)0 % 10u) - 1);
constant("HEX-HIGH", (long)(v4_cell)~(~(v4_ucell)0 >> 4));
/* the math's constants (capsules/v4/rom/math.f18) */
constant("N-1", (long)(V4_CELL_BITS - 1));
constant("NODE-ERROR", (long)NODE_ERROR);
constant("(Q/)", (long)QBASE);
constant("MAXHI", (long)(v4_cell)(V4_MSB - 1u));
constant("2N+15", (long)(2 * V4_CELL_BITS + 15));
constant("N-18", (long)(V4_CELL_BITS - 18));
constant("N-17", (long)(V4_CELL_BITS - 17));
/* the shared entries, the start of both ROMs' tables (v4/rom_entries.h) */
printf("macro (MATH-ENTRIES)");
#define MATH_ENTRY_JUMP(i, routine, forth, effect) printf(" jump %s", routine);
V4_ROM_MATH_ENTRIES(MATH_ENTRY_JUMP)
#undef MATH_ENTRY_JUMP
printf(" endmacro\n");
return 0;
}
+16 -15
View File
@@ -1,13 +1,14 @@
/* mkrom.c -- build the ROM, off the node, as a bitstream is built.
*
* mkrom OUT.c OUT.sym MAP.f18 SOURCE.f18...
* mkrom NAME OUT.c OUT.sym MAP.f18 SOURCE.f18...
*
* docs/v4.0.0/MACHINE.md section 2. The ROM is F18 code, written in the
* text assembler's notation (include/v4/text.h) in capsules/v4/rom, and this
* is the only thing built off the node. It assembles MAP.f18 (the memory
* map's constants, from tools/mkmap.c) and then each SOURCE in the order
* given, at the ROM's base address, and writes:
* OUT.c the ROM: const v4_cell v4_rom_<width>[] and its length
* OUT.c the ROM: const v4_cell v4_<NAME>_<width>[] and its length (NAME
* rom: the host node's ROM; mesh_rom: a mesh node's, MACHINE.md 2.2)
* OUT.sym every word of it, "NAME ADDRESS" a line, for the tests
*
* This tool is built with a node whose RAM reaches over the ROM's range
@@ -56,37 +57,37 @@ int main(int argc, char **argv)
int i;
unsigned s;
if (argc < 5) die("usage: mkrom OUT.c OUT.sym MAP.f18 SOURCE.f18...", NULL);
if (argc < 6) die("usage: mkrom NAME OUT.c OUT.sym MAP.f18 SOURCE.f18...", NULL);
if ((v4_ucell)V4_NODE_WORDS != (v4_ucell)ROM_ORIGIN + (v4_ucell)ROM_RANGE)
die("built with the wrong node size: RAM must reach over the ROM's range", NULL);
v4_node_reset(&n);
v4_text_begin(&tx, &n, ROM_ORIGIN);
for (i = 3; i < argc; i++)
for (i = 4; i < argc; i++)
if (!v4_text_assemble_file(&tx, argv[i])) die("does not assemble", v4_text_error(&tx));
if (!v4_text_finish(&tx)) die("not everything is defined", v4_text_error(&tx));
here = v4_text_here(&tx);
if (here - (v4_cell)ROM_ORIGIN > (v4_cell)ROM_RANGE) die("the ROM is larger than its range", NULL);
out = fopen(argv[1], "w");
if (!out) die("cannot write", argv[1]);
out = fopen(argv[2], "w");
if (!out) die("cannot write", argv[2]);
fprintf(out, "/* Generated by v4/tools/mkrom.c from capsules/v4/rom -- do not edit. */\n#include \"v4/cell.h\"\n\n");
fprintf(out, "const v4_cell v4_rom_%d[] = {\n", V4_CELL_BITS);
fprintf(out, "const v4_cell v4_%s_%d[] = {\n", argv[1], V4_CELL_BITS);
for (a = ROM_ORIGIN; a < here; a++) {
fprintf(out, " ");
put_cell(out, n.mem[a]);
fprintf(out, ",\n");
}
if (here == ROM_ORIGIN) fprintf(out, " 0\n");
fprintf(out, "};\nconst unsigned v4_rom_%d_words = %ldu;\n", V4_CELL_BITS, (long)(here - (v4_cell)ROM_ORIGIN));
if (fclose(out) != 0) die("cannot write", argv[1]);
out = fopen(argv[2], "w");
if (!out) die("cannot write", argv[2]);
for (s = 0; s < tx.nsym; s++)
if (tx.sym[s].kind == 1) fprintf(out, "%s %ld\n", tx.pool + tx.sym[s].name, (long)tx.sym[s].value);
fprintf(out, "};\nconst unsigned v4_%s_%d_words = %ldu;\n", argv[1], V4_CELL_BITS, (long)(here - (v4_cell)ROM_ORIGIN));
if (fclose(out) != 0) die("cannot write", argv[2]);
fprintf(stderr, "mkrom: a ROM of %ld words, %d-bit cells -> %s\n", (long)(here - (v4_cell)ROM_ORIGIN), V4_CELL_BITS, argv[1]);
out = fopen(argv[3], "w");
if (!out) die("cannot write", argv[3]);
for (s = 0; s < tx.nsym; s++)
if (tx.sym[s].kind == 1) fprintf(out, "%s %ld\n", tx.pool + tx.sym[s].name, (long)tx.sym[s].value);
if (fclose(out) != 0) die("cannot write", argv[3]);
fprintf(stderr, "mkrom: %s, %ld words, %d-bit cells -> %s\n", argv[1], (long)(here - (v4_cell)ROM_ORIGIN), V4_CELL_BITS, argv[2]);
return 0;
}