The host node starts in its ROM (entry 12), and the boot feeds it the system's source through the console: capsules/v4/sys/map-64.f18, the fourteen .f18 blobs and end.f18, each found, hash-checked and signature-checked as any capsule, then EOT. The ROM assembles the system and starts it at (IDLE); the host reads the image record (v4_image_from_node) for what only the assembled system knows. A ROM error is reported with its blob, line and meaning, then PARITY:FAIL. Deleted: v4/tools/mkimage.c, capsules/v4/nucleus-64.f18, v4/capsule/*.v4, v4/tools/v4tof18.py. The .f18 files are the source now. - text.c speaks the rest of the ROM's language (set, here, store, start; v4_text_value, v4_text_start), so the oracle reads the same source: test_host_rom_nucleus compares the ROM against text.c on the .f18 files, word for word, image record included. Host tests load the .f18 files. - mkmap image writes v4_map_image (the map's description of the system); hosted and the kernel link the ROM and the map instead of v4_image_64.c. - Hera (Captain Bob's ruling, option 1): births stream the system the ROM assembled, as assembled code; hera.4th is unchanged. test_host_unit's host builds the system with the ROM. - New parity lines: PARITY:V4_F18 per blob, PARITY:V4_ROM words=2049 rom_hash=0xa6c792b5821010b7 instructions=60725216. Acceptance: amd64, aarch64, riscv64 boot to ok> with PARITY:V4_POST tests=538 pass=538 fail=0, POST: PASSED, and PARITY:V4_SYSTEM word_count=317 dict_hash=0xe5a57f3eb72ff94a on all three -- the same hash as the prebuilt nucleus gave. make -C v4 test test-32 hosted-check: all pass. Logs: logs/20261015-141648, -141938, -142350. Startup cost under QEMU TCG, the ROM's assembly (last V4_F18 line to V4_ROM): amd64 26.7 s of 132 s to ok>; aarch64 41.0 s of 195 s; riscv64 20.5 s of 101 s. Hosted native: +0.85 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
420 lines
24 KiB
C
420 lines
24 KiB
C
/* host_map.h -- the memory map the host-node tests give the compiler capsule,
|
|
* and the loader that assembles it.
|
|
*
|
|
* The node's memory map is open (DECOMPOSITION.md D-4), so the tests choose
|
|
* one. Every test_host_*.c uses this one, so that the capsule's variables
|
|
* and buffers are in the same place in all of them:
|
|
*
|
|
* 16 .. the capsule's code, assembled from capsules/v4/sys/ *.f18
|
|
* DICT_W .. DICT_END_W dictionary space for what is defined at run time
|
|
* top of memory buffers, then variables, as below
|
|
*/
|
|
#ifndef V4_TESTS_HOST_MAP_H
|
|
#define V4_TESTS_HOST_MAP_H
|
|
|
|
#include "v4/blocks.h"
|
|
#include "v4/text.h"
|
|
#include <stdio.h>
|
|
|
|
#define TOP ((v4_cell)V4_NODE_WORDS)
|
|
|
|
/* registers and single variables */
|
|
#define NODE_ERROR (TOP - 2)
|
|
#define CONSOLE_TX (TOP - 4)
|
|
#define CONSOLE_RX (TOP - 6)
|
|
#define CONSOLE_ST (TOP - 7)
|
|
#define BASE (TOP - 8)
|
|
#define TO_IN (TOP - 9)
|
|
#define SPAN (TOP - 10)
|
|
#define DP (TOP - 11)
|
|
#define LATEST (TOP - 12)
|
|
#define STATE (TOP - 13)
|
|
#define CFP (TOP - 14) /* the control-flow stack's pointer */
|
|
#define DSTACK_REG (TOP - 15) /* DSTACK-DEPTH (D-16) */
|
|
#define RSTACK_REG (TOP - 16) /* RSTACK-DEPTH */
|
|
|
|
/* each capsule file's scratch cells */
|
|
#define PVARS (TOP - 24) /* (P): input.f18, 8 cells */
|
|
#define DVARS (TOP - 32) /* (D): dict.f18, 5 cells */
|
|
#define CGVARS (TOP - 48) /* (CG): codegen.f18, 14 cells */
|
|
#define CVARS (TOP - 62) /* (C): compile.f18, 10 cells */
|
|
#define FVARS (TOP - 105) /* (F): forth.f18, 7 cells */
|
|
#define SVARS (TOP - 540 - (v4_cell)V4_DATA_DEPTH) /* (S): where PICK and ROLL set stack values aside, one cell for each cell of the stack */
|
|
#define WVARS (TOP - 99) /* (W): numout.f18, 3 cells */
|
|
#define CONTEXT (TOP - 64) /* the vocabulary names are looked up in */
|
|
#define CURRENT (TOP - 63) /* the vocabulary new words go into */
|
|
#define VOC_LINK (TOP - 50) /* the newest vocabulary */
|
|
#define FENCE (TOP - 26) /* FORGET's lower limit */
|
|
#define HLD (TOP - 25) /* where the pictured number has got to */
|
|
|
|
/* buffers (word addresses; a byte address is four times this) */
|
|
#define CFS_W (TOP - 96) /* the control-flow stack, 32 cells */
|
|
#define CFS_CELLS 32
|
|
#define WBUF_W (TOP - 170) /* WORD's buffer: 65 cells = 260 bytes */
|
|
#define WBUF_CELLS 65
|
|
#define TIB_W (TOP - 440) /* the text input buffer: 260 cells = 1040 bytes; a line is at most 1024 */
|
|
#define PAD_W (TOP - 470) /* PAD: 21 cells = 84 bytes */
|
|
#define SBUF_W (TOP - 540) /* 64 cells for the tests' own strings */
|
|
#define HBUF_W (SVARS - 16) /* the hold buffer: 16 cells = 64 bytes */
|
|
#define HEND ((HBUF_W + 16) * 4)
|
|
#define XVARS (HBUF_W - 4) /* (X): words.f18, 4 cells */
|
|
#define QBASE (XVARS - 40) /* the Q words' and DUMP's scratch cells, 39 in all */
|
|
#define BVARS (QBASE - 16) /* blocks.f18: 6 cells not used now, then SCR BLK (SRC) (SRC-HOOK) */
|
|
#define SCR (BVARS + 6)
|
|
#define BLK (BVARS + 7)
|
|
#define SRC (BVARS + 8)
|
|
#define SRC_HOOK (BVARS + 9)
|
|
#define QUIET (BUF0_W - 10) /* 1 while the node does something that is no text's doing: an error then is not told (quit.f18, (RAISED)) */
|
|
#define REFUSED (BUF0_W - 7) /* how many of this node's messages it has been told were refused */
|
|
#define ACL_HOOK (BUF0_W - 6) /* the xt of the access control recheck word, or 0 */
|
|
#define LINE_STATUS (BUF0_W - 9) /* how the last line ended: 0 QUIT, 1 completed, 2 an error */
|
|
#define PORT (BUF0_W - 140) /* the node's ports (node.h): V4_PORTS of them, then "any port", "which port" and the rest as far as V4_PORT_HAVE. Port 0 is where its requests go. */
|
|
#define CONSOLE (BUF0_W - 16) /* the node what this one prints is sent to; 0: whoever sent the text being served */
|
|
#define ROUTE_COUNT (BUF0_W - 17) /* how many entries the table of ways holds */
|
|
#define ROUTE_DEFAULT (BUF0_W - 18) /* the port address for a node not in the table, or 0: there is none */
|
|
#define LOST (BUF0_W - 19) /* how many messages have been let go for want of a way */
|
|
#define PRINT_TO (BUF0_W - 20) /* where what the text being served prints is to go: the node, */
|
|
#define PRINT_PORT (BUF0_W - 33) /* and the port, by its number, that leads there */
|
|
#define DONE_PORT (BUF0_W - 34) /* the port, by its number, that leads back to whoever sent the text being served */
|
|
/* WHOLE MESSAGES (MESH.md 7d.4; core.f18). A node keeps no message but the one it is doing: these are what it
|
|
* builds one in and looks at one with, and where it has got to in going through its wires. */
|
|
#define WIRE (PORT + (v4_cell)V4_PORT_WIRE) /* the six addresses after the ports (node.h): the wire an operation is about, */
|
|
#define WIRE_A (PORT + (v4_cell)V4_PORT_A) /* what it needs, */
|
|
#define WIRE_B (PORT + (v4_cell)V4_PORT_B)
|
|
#define WIRE_DO (PORT + (v4_cell)V4_PORT_DO) /* the operation, */
|
|
#define WIRE_HOW (PORT + (v4_cell)V4_PORT_HOW) /* how it went, */
|
|
#define WIRE_HAVE (PORT + (v4_cell)V4_PORT_HAVE) /* and which wires have a message */
|
|
#define S_HAVE (BUF0_W - 35) /* which wires had a message when the node last asked, */
|
|
#define S_MASK (BUF0_W - 36) /* those of them still to be gone through, */
|
|
#define S_WIRE (BUF0_W - 37) /* the one being gone through, */
|
|
#define S_ON (BUF0_W - 38) /* and whether its mark has been put at its first message */
|
|
#define KEEP (BUF0_W - 40) /* the port the answer to the text being done goes by, on whose wire 8 cells are kept for it; -1: none */
|
|
#define DEFER (BUF0_W - 41) /* a port whose wire had no room for the answer to text that waits to be begun; -1: none */
|
|
#define D_MASK (BUF0_W - 8) /* and a bit for each such port: text whose answer goes by one is not begun on this pass */
|
|
#define IN_HDR (BUF0_W - 56) /* the seven words of the message a wire's mark is at */
|
|
#define ONE (BUF0_W - 49) /* the one word of text of a NACK, a GONE or an answer, coming or going */
|
|
#define OUT_HDR (BUF0_W - 112) /* the seven words of a message this node is putting on a wire */
|
|
#define W_NEED (BUF0_W - 105) /* the wait for room: how many cells, */
|
|
#define W_PORT (BUF0_W - 104) /* and on which port's wire */
|
|
#define P_WAY (BUF0_W - 103) /* the port a message being passed on goes by, */
|
|
#define P_NEED (BUF0_W - 100) /* and the cells it needs there */
|
|
#define H_PORT (BUF0_W - 99) /* the port of the first message left on its wire for want of room on this pass; -1: none */
|
|
#define H_NEED (BUF0_W - 98) /* the cells it needs there */
|
|
#define H_MASK (BUF0_W - 97) /* and a bit for each port something was left for */
|
|
#define A_SELF (BUF0_W - 102) /* 1: a message of this node's own, for the node it waits on, came back and was let go here */
|
|
#define SEND_PTR (BUF0_W - 101) /* where the next word of a text being made ready to send goes */
|
|
#define OUT_TEXT (OUT_W - 64) /* what was printed, four characters to a cell, as it goes on the wire: 64 cells */
|
|
#define SEND_TEXT (OUT_W - 400) /* the text of a message SEND is putting, four characters to a cell: 256 cells */
|
|
/* The ROM's slot packer (MACHINE.md 2.1), in what was free: BUF0_W - 32 .. - 23 and - 122 .. - 120. */
|
|
#define ROM_HERE (BUF0_W - 32) /* the next word address code goes to */
|
|
#define ROM_CUR (BUF0_W - 31) /* the instruction word being built */
|
|
#define ROM_SLOT (BUF0_W - 30) /* its next free slot, 0 .. 6 */
|
|
#define ROM_NLIT (BUF0_W - 29) /* how many literals it owes */
|
|
#define ROM_LITS (BUF0_W - 28) /* the literals, 6 cells */
|
|
#define ROM_PI (BUF0_W - 122) /* working cells */
|
|
#define ROM_RS (BUF0_W - 121)
|
|
#define ROM_RN (BUF0_W - 120)
|
|
/* THE IMAGE RECORD: where the system's source says, with `store`, the addresses a host needs (v4/image.h): where the
|
|
* node waits for a message, its fault table, and KEY's code. */
|
|
#define ROM_IMG (BUF0_W - 119) /* idle, fault table, KEY, the word after KEY: 4 cells */
|
|
/* FREE, plain memory: BUF0_W - 22 .. - 21; - 115 .. - 113; BUF0_W - 144 .. - 141 (what a flush makes zero after
|
|
* a full output buffer); and OUT_W - 144 .. OUT_W - 65. They and
|
|
* the cells above held the messages waiting, the refusals owed and what went with them (MESH.md 7a, 7b), which a
|
|
* node no longer keeps. */
|
|
#define AWAIT_FROM (BUF0_W - 39) /* the node whose word of how text ended is waited for */
|
|
#define NEAR (BUF0_W - 64) /* for each port, the number of the node on the other end; 0: not told */
|
|
#define ROUTES (BUF0_W - 96) /* the table of ways: 16 entries of a node and the port address that leads to it */
|
|
#define ROUTE_MAX 16
|
|
#define ME (BUF0_W - 13) /* this node's number: a message is for it when its first word is this */
|
|
#define OUT_PTR (BUF0_W - 14) /* where the next character printed goes: a cell of the output buffer */
|
|
#define REPLY (BUF0_W - 15) /* the port, by its number, the text being served came on */
|
|
#define MSG (BUF0_W - 48) /* the header of the message being served, 7 cells */
|
|
#define OUT_W (BUF0_W - 400) /* the output buffer: 256 cells, a character to a cell */
|
|
#define OUT_CELLS 256
|
|
/* THE ROM'S STATE (docs/v4.0.0/MACHINE.md 2.1): a reserved area that belongs to the ROM's routines, which payloads
|
|
* call at run time; it is never cleared after the boot. OUT_W - 144 .. OUT_W - 65, which was free. */
|
|
#define ROM_TOK (OUT_W - 144) /* the token being read, as a counted string: 16 cells */
|
|
#define ROM_TOKN (OUT_W - 80) /* how many characters it has */
|
|
#define ROM_PEEK (OUT_W - 79) /* a character put back, plus one; 0: none */
|
|
#define ROM_LINE (OUT_W - 78) /* how many new lines have been read */
|
|
#define ROM_EOF (OUT_W - 77) /* non-zero once EOT has been read: the input has ended */
|
|
#define ROM_FAILED (OUT_W - 76) /* 0, or the code of the error that stopped the ROM */
|
|
#define ROM_ERRLINE (OUT_W - 75) /* ROM_LINE when it failed */
|
|
#define ROM_NBASE (OUT_W - 74) /* (NUMBER): the base, 10 or 16 */
|
|
#define ROM_NNEG (OUT_W - 73) /* 1 after a leading - */
|
|
#define ROM_NI (OUT_W - 72) /* the next character of the token */
|
|
#define ROM_NU (OUT_W - 71) /* the value so far, unsigned */
|
|
#define ROM_NBIG (OUT_W - 70) /* 1 once it has not fitted a cell */
|
|
#define ROM_RECN (OUT_W - 128) /* (DEFINE): cells of symbol records used */
|
|
#define ROM_POOLN (OUT_W - 127) /* cells of the name pool used */
|
|
#define ROM_REC (OUT_W - 126) /* (FIND): the record being looked at */
|
|
#define ROM_CNT (OUT_W - 125) /* (DEFINE): cells in the token's name */
|
|
#define ROM_PTR (OUT_W - 124) /* (SAME?), (DEFINE): where in a name */
|
|
#define ROM_I (OUT_W - 123) /* where in the token */
|
|
#define ROM_WI (OUT_W - 122) /* (WALK): which entry of a table */
|
|
#define ROM_NREF (OUT_W - 121) /* word.f18: how many branches wait for a target */
|
|
#define ROM_NLAB (OUT_W - 120) /* how many labels the word being assembled has */
|
|
#define ROM_WNP (OUT_W - 119) /* cells of the word's name area used */
|
|
#define ROM_NFOR (OUT_W - 118) /* how many FORs are open */
|
|
#define ROM_FORS (OUT_W - 117) /* where each began, 8 cells */
|
|
#define ROM_RDEPTH (OUT_W - 109) /* how many macros are being expanded */
|
|
#define ROM_RPTRS (OUT_W - 108) /* where each is reading, 8 cells */
|
|
#define ROM_T1 (OUT_W - 100) /* working cells */
|
|
#define ROM_T2 (OUT_W - 99)
|
|
#define ROM_T3 (OUT_W - 98)
|
|
#define ROM_T4 (OUT_W - 97)
|
|
#define ROM_CFROM (OUT_W - 96)
|
|
#define ROM_CTO (OUT_W - 95)
|
|
#define ROM_CN (OUT_W - 94)
|
|
#define ROM_RAW (OUT_W - 93) /* in.f18: 1 while a token is read raw, ( and \ being names */
|
|
#define ROM_T5 (OUT_W - 92)
|
|
#define ROM_T6 (OUT_W - 91)
|
|
#define ROM_MLEN (OUT_W - 90) /* the length of the token saved in ROM_MTEMP */
|
|
#define ROM_ORIGIN 16 /* where the system's code begins */
|
|
/* The ROM's other tables, used only while it assembles (cleared at `start`): in the block window, the branches
|
|
* waiting -- four cells each: the word, the line, a symbol record (or, while local, a name), 1 if local -- the
|
|
* labels of the word being assembled -- a name and an address -- and their names; in the text input buffer, a
|
|
* saved token, a character to a cell, a macro's name and its body being collected. */
|
|
#define ROM_REFS BUF0_W /* 128 entries */
|
|
#define ROM_REFS_MAX 128
|
|
#define ROM_LABELS (BUF0_W + 512) /* 64 entries */
|
|
#define ROM_WNAMES (BUF0_W + 640) /* 384 cells */
|
|
#define ROM_WN_SIZE 384
|
|
#define ROM_TSAVE TIB_W /* 16 cells */
|
|
#define ROM_MTEMP (TIB_W + 16) /* 64 cells */
|
|
#define ROM_MBODY (TIB_W + 80) /* 180 cells */
|
|
#define ROM_MBODY_SIZE 180
|
|
/* THE ROM'S SYMBOL TABLE, used only while it assembles, in dictionary space (cleared at `start`): 256 hash heads,
|
|
* then records growing up -- link, name, kind, value -- and names, as counted strings, growing down from the top. */
|
|
#define ROM_SYMH DICT_W
|
|
#define ROM_SYMREC (DICT_W + 256)
|
|
#define ROM_POOLTOP DICT_END_W
|
|
#define ROM_REC_LINK 0
|
|
#define ROM_REC_NAME 1
|
|
#define ROM_REC_KIND 2
|
|
#define ROM_REC_VALUE 3
|
|
#define ROM_KIND_WORD 1
|
|
#define ROM_KIND_CONST 2
|
|
#define ROM_KIND_MACRO 3
|
|
#define ROM_KIND_SET 4
|
|
/* the ROM's error codes */
|
|
#define ROM_ERR_TOO_LONG 1 /* a token longer than 63 characters: "name too long" */
|
|
#define ROM_ERR_COMMENT 2 /* a ( with no ) before the end: "comment not closed" */
|
|
#define ROM_ERR_BAD_NAME 3 /* an opcode, a reserved word, a label, a number or &...: "cannot be used as a name" */
|
|
#define ROM_ERR_DEFINED 4 /* "already defined" */
|
|
#define ROM_ERR_NAMES 5 /* the symbol table is full: "too many names" */
|
|
#define ROM_ERR_FIT 6 /* memory is full, or a branch cannot reach: "does not fit" */
|
|
#define ROM_ERR_OPCODE 7 /* not an opcode the packer takes there */
|
|
#define ROM_ERR_IN_MACRO 8 /* "not allowed in a macro" */
|
|
#define ROM_ERR_MACRO 9 /* "macro without endmacro", "endmacro without macro" */
|
|
#define ROM_ERR_LABEL_DUP 10 /* "label already defined in this word" */
|
|
#define ROM_ERR_LABELS 11 /* "too many labels in one word" */
|
|
#define ROM_ERR_FOR 12 /* FOR nested too deep, NEXT or UNEXT without FOR, FOR without NEXT */
|
|
#define ROM_ERR_UNEXT 13 /* "FOR ... UNEXT must fit one instruction word and hold no literal" */
|
|
#define ROM_ERR_TARGET 14 /* "not something to branch to" */
|
|
#define ROM_ERR_UNDEFINED 15 /* "never defined" */
|
|
#define ROM_ERR_BIG 16 /* "number does not fit a cell" */
|
|
#define ROM_ERR_AMP 17 /* "& needs a word that is already defined" */
|
|
#define ROM_ERR_FETCH_P 18 /* "write the number, not @p" */
|
|
#define ROM_ERR_MISSING 19 /* a name, a target, a value or a string missing at the end */
|
|
#define ROM_ERR_DEEP 20 /* "macros nested too deep" */
|
|
#define ROM_ERR_REFS 21 /* "too many unresolved branches" */
|
|
#define ROM_ERR_VALUE 22 /* "not a value", "not a number" */
|
|
#define ROM_ERR_NO_START 23 /* the input ended with no start */
|
|
#define ROM_ERR_START 24 /* start: not a word */
|
|
#define ROM_ADDR_TOP ((v4_cell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u)) /* the top of the address space */
|
|
#define WORD_DEFINED (BUF0_W - 11) /* the xt of the word that is told of each new entry, or 0 */
|
|
#define WORD_FORGOTTEN (BUF0_W - 12) /* the xt of the word that is told when entries go, or 0 */
|
|
#define LOG_LEVEL (BUF0_W - 5) /* the level at or below which a message is printed */
|
|
#define BOOT_CELLS (BVARS + 14) /* (BOOT): DP and LATEST as the loader left them, 2 cells */
|
|
#define BUF0_W (BVARS - (v4_cell)(V4_BLOCK_SLOTS * V4_BLOCK_CELLS)) /* the block window: the kernel's slots, 256 cells each (v4/blocks.h) */
|
|
/* The ports and the addresses after them, through V4_PORT_HAVE (node.h, MESH.md 7d.3), are not memory and must be where
|
|
* no variable is: after the output buffer, which ends at BUF0_W - 144, and before OUT_HDR, the first variable above it.
|
|
* With 8 ports that is 18 addresses, BUF0_W - 140 to BUF0_W - 123. (They were once among the variables, and what was
|
|
* stored to the variables was stored to ports.) */
|
|
typedef char host_map_ports_fit[(PORT >= OUT_W + OUT_CELLS && PORT + (v4_cell)V4_PORT_HAVE < OUT_HDR) ? 1 : -1];
|
|
/* Nothing printed: a node's variable for it, as at switch-on. */
|
|
#define HOST_MESSAGES_EMPTY(n) do { (n)->mem[OUT_PTR] = OUT_W; } while (0)
|
|
#define QVARS (BUF0_W - 4) /* (Q): quit.f18, system.f18 and blocks.f18, 4 cells */
|
|
#define WBUF (WBUF_W * 4)
|
|
#define TIB (TIB_W * 4)
|
|
#define PAD (PAD_W * 4)
|
|
#define SBUF (SBUF_W * 4)
|
|
|
|
/* dictionary space */
|
|
#ifndef DICT_W
|
|
#define DICT_W ((v4_cell)8192)
|
|
#endif
|
|
#ifndef DICT_END_W
|
|
#define DICT_END_W ((v4_cell)13824) /* 512 cells lower than it was: the block window is four slots now */
|
|
#endif
|
|
/* the texts made ready for the wire are above the dictionary */
|
|
typedef char host_map_texts_fit[(SEND_TEXT >= DICT_END_W && SEND_TEXT + 256 <= OUT_TEXT && OUT_TEXT + 64 == OUT_W) ? 1 : -1];
|
|
|
|
/* How many slots, from slot 0, a branch may sit in on a node this size: those
|
|
* whose address field reaches every word of it. */
|
|
static unsigned host_branch_slots(void)
|
|
{
|
|
unsigned k, slots = 0;
|
|
for (k = 0; k < 4; k++) if ((v4_ucell)v4_iword_slot_mask(k) >= (v4_ucell)(V4_NODE_WORDS - 1u)) slots = k + 1;
|
|
return slots;
|
|
}
|
|
|
|
/* Reset `n`, give the assembler every constant the capsule files ask for, and
|
|
* assemble the `count` files named. Returns 1 if all assembled; otherwise
|
|
* prints which did not and why. The caller may assemble more text and must
|
|
* call v4_text_finish. */
|
|
/* THE CONSTANTS the system's source is assembled with: names for the addresses and numbers of this map. One
|
|
* list, read by host_load (here) and by tools/mkmap.c, which writes it as the system's map blob for the ROM. */
|
|
#define HOST_CONSTANTS(X) \
|
|
X("N-1", V4_CELL_BITS - 1) \
|
|
X("NODE-ERROR", NODE_ERROR) \
|
|
X("CONSOLE-TX", CONSOLE_TX) \
|
|
X("CONSOLE-RX", CONSOLE_RX) \
|
|
X("CONSOLE-STATUS", CONSOLE_ST) \
|
|
X("BASE", BASE) \
|
|
X("TIB", TIB) \
|
|
X(">IN", TO_IN) \
|
|
X("SPAN", SPAN) \
|
|
X("WBUF", WBUF) \
|
|
X("(P)", PVARS) \
|
|
X("DP", DP) \
|
|
X("(LATEST)", LATEST) \
|
|
X("DBASE", DICT_W * 4) \
|
|
X("DLIMIT", DICT_END_W * 4) \
|
|
X("PAD", PAD) \
|
|
X("(D)", DVARS) \
|
|
X("(CG)", CGVARS) \
|
|
X("CG-BSLOTS", (v4_cell)host_branch_slots()) \
|
|
X("STATE", STATE) \
|
|
X("(C)", CVARS) \
|
|
X("(CFP)", CFP) \
|
|
X("(Q)", QVARS) \
|
|
X("(F)", FVARS) \
|
|
X("(S)", SVARS) \
|
|
X("(W)", WVARS) \
|
|
X("(X)", XVARS) \
|
|
X("(BOOT)", BOOT_CELLS) \
|
|
X("(LOG-LEVEL)", LOG_LEVEL) \
|
|
X("(ACL-HOOK)", ACL_HOOK) \
|
|
X("SCR", SCR) \
|
|
X("BLK", BLK) \
|
|
X("(SRC)", SRC) \
|
|
X("(SRC-HOOK)", SRC_HOOK) \
|
|
X("(LINE-STATUS)", LINE_STATUS) \
|
|
X("(PORT)", PORT) \
|
|
X("(ME)", ME) \
|
|
X("(CONSOLE)", CONSOLE) \
|
|
X("(ROUTE#)", ROUTE_COUNT) \
|
|
X("(ROUTE-DEFAULT)", ROUTE_DEFAULT) \
|
|
X("(LOST)", LOST) \
|
|
X("(PRINT-TO)", PRINT_TO) \
|
|
X("(PRINT-PORT)", PRINT_PORT) \
|
|
X("(DONE-PORT)", DONE_PORT) \
|
|
X("(ROUTES)", ROUTES) \
|
|
X("-PORTS", -(v4_cell)V4_PORTS) \
|
|
X("(NEAR)", NEAR) \
|
|
X("(AWAIT-FROM)", AWAIT_FROM) \
|
|
X("(WIRE)", WIRE) \
|
|
X("(WIRE-A)", WIRE_A) \
|
|
X("(WIRE-B)", WIRE_B) \
|
|
X("(WIRE-DO)", WIRE_DO) \
|
|
X("(WIRE-HOW)", WIRE_HOW) \
|
|
X("(WIRE-HAVE)", WIRE_HAVE) \
|
|
X("(S-HAVE)", S_HAVE) \
|
|
X("(S-MASK)", S_MASK) \
|
|
X("(S-WIRE)", S_WIRE) \
|
|
X("(S-ON)", S_ON) \
|
|
X("(KEEP)", KEEP) \
|
|
X("(DEFER)", DEFER) \
|
|
X("(D-MASK)", D_MASK) \
|
|
X("(IN)", IN_HDR) \
|
|
X("(ONE)", ONE) \
|
|
X("(OUT-HDR)", OUT_HDR) \
|
|
X("(W-NEED)", W_NEED) \
|
|
X("(W-PORT)", W_PORT) \
|
|
X("(P-WAY)", P_WAY) \
|
|
X("(P-NEED)", P_NEED) \
|
|
X("(H-PORT)", H_PORT) \
|
|
X("(H-NEED)", H_NEED) \
|
|
X("(H-MASK)", H_MASK) \
|
|
X("(A-SELF)", A_SELF) \
|
|
X("(SEND^)", SEND_PTR) \
|
|
X("(OUT-TEXT)", OUT_TEXT) \
|
|
X("(SEND-TEXT)", SEND_TEXT) \
|
|
X("(QUIET)", QUIET) \
|
|
X("(REFUSED)", REFUSED) \
|
|
X("(OUT^)", OUT_PTR) \
|
|
X("(REPLY)", REPLY) \
|
|
X("(MSG)", MSG) \
|
|
X("(OUT)", OUT_W) \
|
|
X("(WORD-DEFINED)", WORD_DEFINED) \
|
|
X("(WORD-FORGOTTEN)", WORD_FORGOTTEN) \
|
|
X("BLOCK#", V4_REQ_BLOCK) /* the kernel's block requests (v4/blocks.h) */ \
|
|
X("BUFFER#", V4_REQ_BUFFER) \
|
|
X("UPDATE#", V4_REQ_UPDATE) \
|
|
X("SAVE-BUFFERS#", V4_REQ_SAVE_BUFFERS) \
|
|
X("EMPTY-BUFFERS#", V4_REQ_EMPTY_BUFFERS) \
|
|
X("(Q/)", QBASE) /* 5 cells */ \
|
|
X("(QE)", QBASE + 5) /* 8 */ \
|
|
X("(QR)", QBASE + 13) /* 5 */ \
|
|
X("(QL)", QBASE + 18) /* 7 */ \
|
|
X("(QT)", QBASE + 25) /* 6 */ \
|
|
X("(QP)", QBASE + 31) /* 4 */ \
|
|
X("(DP)", QBASE + 35) /* 4 */ \
|
|
X("ADDR-DIGITS", V4_CELL_BITS / 4) \
|
|
X("MSB", (v4_cell)V4_MSB) \
|
|
X("MAXHI", (v4_cell)(V4_MSB - 1u)) \
|
|
X("HIMASK", (v4_cell)(((v4_ucell)1 << (V4_CELL_BITS - 16)) - 1u)) \
|
|
X("2N+15", 2 * V4_CELL_BITS + 15) \
|
|
X("N-18", V4_CELL_BITS - 18) \
|
|
X("N-17", V4_CELL_BITS - 17) \
|
|
X("MAX-INT", (v4_cell)(V4_MSB - 1u)) \
|
|
X("HLD", HLD) \
|
|
X("FENCE", FENCE) \
|
|
X("CONTEXT", CONTEXT) \
|
|
X("CURRENT", CURRENT) \
|
|
X("VOC-LINK", VOC_LINK) \
|
|
X("HEND", HEND) \
|
|
X("-HFLOOR", -(HEND - 62)) \
|
|
X("DSTACK-DEPTH", DSTACK_REG) \
|
|
X("RSTACK-DEPTH", RSTACK_REG) \
|
|
X("CFBASE", CFS_W) \
|
|
X("CFEND", CFS_W + CFS_CELLS)
|
|
|
|
static int host_load(v4_text *tx, v4_node *n, const char *const *files, unsigned count)
|
|
{
|
|
char path[512];
|
|
unsigned i;
|
|
|
|
v4_node_reset(n);
|
|
HOST_MESSAGES_EMPTY(n); /* nothing has been printed and no message waits (core.f18) */
|
|
v4_text_begin(tx, n, 16);
|
|
#define HOST_CONSTANT(name, value) v4_text_constant(tx, name, (v4_cell)(value));
|
|
HOST_CONSTANTS(HOST_CONSTANT)
|
|
#undef HOST_CONSTANT
|
|
v4_node_stack_regs_attach(n, DSTACK_REG, RSTACK_REG);
|
|
for (i = 0; i < count; i++) {
|
|
snprintf(path, sizeof path, "%s/%s", V4_SYS_DIR, files[i]);
|
|
if (!v4_text_assemble_file(tx, path)) {
|
|
printf(" %s does not assemble: %s\n", files[i], v4_text_error(tx));
|
|
return 0;
|
|
}
|
|
}
|
|
/* the newest entry the source laid down (its HDR-LINK) is the
|
|
* assembler's latest: a `header` in a test's own text links to it */
|
|
{
|
|
v4_cell newest;
|
|
if (v4_text_value(tx, "HDR-LINK", &newest)) tx->latest = newest;
|
|
}
|
|
/* one vocabulary, FORTH, whose head cell is LATEST */
|
|
n->mem[CONTEXT] = LATEST;
|
|
n->mem[CURRENT] = LATEST;
|
|
n->mem[VOC_LINK] = 0;
|
|
/* and the text interpreted is the terminal's */
|
|
n->mem[SRC] = TIB;
|
|
return 1;
|
|
}
|
|
|
|
#endif /* V4_TESTS_HOST_MAP_H */
|