feat(v4): the machine has a ROM -- read and run, never written
A read-only range of V4_ROM_WORDS words at V4_ROM_BASE, above RAM (MACHINE.md 2, DATASHEET-F18.md 5). Instruction fetch, @p and data fetches read it; a running programme's store there is an address fault. Attached by the owner like every device; a reset detaches it. The host node's range is 4096 words. text.c places branches by the whole address space. The nucleus image is byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
42f8a13914
commit
32753f5479
+13
-5
@@ -43,6 +43,14 @@ static int faulted(v4_node *n, v4_cell addr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The same for a fetch, which may also read the ROM (node.h). */
|
||||
static int faulted_read(v4_node *n, v4_cell addr)
|
||||
{
|
||||
if (v4_node_addr_readable(n, addr)) return 0;
|
||||
v4_node_fault(n, V4_FAULT_ADDRESS, addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* D-16: what each opcode takes from the stacks and leaves on them. If the
|
||||
* data stack holds fewer than `dneed`, or the return stack fewer than
|
||||
* `rneed`, or a stack the opcode leaves one more on is full, it is a fault
|
||||
@@ -142,7 +150,7 @@ void v4_exec_op(v4_node *n, v4_exec_state *es, v4_heat *h,
|
||||
break;
|
||||
|
||||
case V4_OP_FETCH_P:
|
||||
if (faulted(n, n->p)) return;
|
||||
if (faulted_read(n, n->p)) return;
|
||||
if (v4_node_port_index(n, n->p) >= 0) {
|
||||
/* P is a port: the literal is the next word its neighbour
|
||||
* writes, and P stays where it is */
|
||||
@@ -154,18 +162,18 @@ void v4_exec_op(v4_node *n, v4_exec_state *es, v4_heat *h,
|
||||
n->p = add_wrap(n->p, 1);
|
||||
break;
|
||||
case V4_OP_FETCH_INC:
|
||||
if (faulted(n, n->a)) return;
|
||||
if (faulted_read(n, n->a)) return;
|
||||
if (!v4_node_read_ready(n, n->a)) return; /* a port with nothing written to it yet */
|
||||
v4_dstack_push(ds, v4_node_fetch(n, n->a));
|
||||
n->a = add_wrap(n->a, 1);
|
||||
break;
|
||||
case V4_OP_FETCH_B:
|
||||
if (faulted(n, n->b)) return;
|
||||
if (faulted_read(n, n->b)) return;
|
||||
if (!v4_node_read_ready(n, n->b)) return; /* a port with nothing written to it yet */
|
||||
v4_dstack_push(ds, v4_node_fetch(n, n->b));
|
||||
break;
|
||||
case V4_OP_FETCH_A:
|
||||
if (faulted(n, n->a)) return;
|
||||
if (faulted_read(n, n->a)) return;
|
||||
if (!v4_node_read_ready(n, n->a)) return; /* a port with nothing written to it yet */
|
||||
v4_dstack_push(ds, v4_node_fetch(n, n->a));
|
||||
break;
|
||||
@@ -269,7 +277,7 @@ unsigned v4_exec_step_word(v4_node *n, v4_exec_state *es, v4_heat *h)
|
||||
slot = es->resume_slot;
|
||||
} else {
|
||||
/* P itself may be what is outside memory */
|
||||
if (faulted(n, n->p)) return 0;
|
||||
if (faulted_read(n, n->p)) return 0;
|
||||
if (v4_node_port_index(n, n->p) >= 0) {
|
||||
/* P is a port: the node executes what its neighbour writes
|
||||
* there, and P stays where it is */
|
||||
|
||||
+18
-2
@@ -4,6 +4,8 @@
|
||||
|
||||
void v4_node_reset(v4_node *n)
|
||||
{
|
||||
n->rom = NULL; /* attached again by the owner, as every device is */
|
||||
n->rom_words = 0;
|
||||
n->p = 0;
|
||||
n->a = 0;
|
||||
n->b = 0;
|
||||
@@ -66,10 +68,24 @@ int v4_node_guards_intact(const v4_node *n)
|
||||
&& v4_rstack_guards_intact(&n->rs);
|
||||
}
|
||||
|
||||
int v4_node_addr_readable(const v4_node *n, v4_cell addr)
|
||||
{
|
||||
return v4_node_addr_ok(addr)
|
||||
|| ((v4_ucell)addr - (v4_ucell)V4_ROM_BASE) < (v4_ucell)n->rom_words;
|
||||
}
|
||||
|
||||
void v4_node_rom_attach(v4_node *n, const v4_cell *rom, unsigned words)
|
||||
{
|
||||
if (!rom || words > V4_ROM_WORDS) { n->rom = NULL; n->rom_words = 0; return; }
|
||||
n->rom = rom;
|
||||
n->rom_words = words;
|
||||
}
|
||||
|
||||
v4_cell v4_node_load(const v4_node *n, v4_cell addr)
|
||||
{
|
||||
if (!v4_node_addr_ok(addr)) return 0;
|
||||
return n->mem[(unsigned)addr];
|
||||
if (v4_node_addr_ok(addr)) return n->mem[(unsigned)addr];
|
||||
if (v4_node_addr_readable(n, addr)) return n->rom[(v4_ucell)addr - (v4_ucell)V4_ROM_BASE];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void v4_node_store(v4_node *n, v4_cell addr, v4_cell value)
|
||||
|
||||
+1
-1
@@ -216,7 +216,7 @@ static void place_branch(v4_text *t)
|
||||
v4_asm *as = &t->as;
|
||||
if (as->slot == 0) return;
|
||||
if (!v4_iword_branch_legal(as->slot)
|
||||
|| (v4_ucell)v4_iword_slot_mask(as->slot) < (v4_ucell)(V4_NODE_WORDS - 1u))
|
||||
|| (v4_ucell)v4_iword_slot_mask(as->slot) < (v4_ucell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u))
|
||||
(void)v4_asm_label(as);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user