/* node.c -- the v4 node. See node.h. */ #include "v4/node.h" void v4_node_reset(v4_node *n) { n->p = 0; n->a = 0; n->b = 0; for (unsigned i = 0; i < V4_NODE_WORDS; i++) n->mem[i] = 0; v4_guard_fill(n->mem_guard_head, V4_MEM_BOUND, V4_GUARD_PATTERN_HEAD); v4_guard_fill(n->mem_guard_tail, V4_MEM_BOUND, V4_GUARD_PATTERN_TAIL); v4_dstack_reset(&n->ds); v4_rstack_reset(&n->rs); v4_node_console_attach(n, -1); v4_node_console_input_attach(n, -1, -1); } int v4_node_guards_intact(const v4_node *n) { return v4_guard_intact(n->mem_guard_head, V4_MEM_BOUND, V4_GUARD_PATTERN_HEAD) && v4_guard_intact(n->mem_guard_tail, V4_MEM_BOUND, V4_GUARD_PATTERN_TAIL) && v4_dstack_guards_intact(&n->ds) && v4_rstack_guards_intact(&n->rs); } v4_cell v4_node_load(const v4_node *n, v4_cell addr) { /* Precondition checked by the caller; see node.h. The unsigned compare is * deliberate: `addr` is signed, and a negative address must not wrap into * a large positive one and read the top of memory instead. */ return n->mem[(unsigned)addr]; } void v4_node_store(v4_node *n, v4_cell addr, v4_cell value) { /* CONSOLE-TX: capture the character, leave memory alone. console_tx is * -1 when no console is attached, which no valid address equals. */ if (addr == n->console_tx) { if (n->console_len < V4_CONSOLE_CAP) n->console[n->console_len++] = (unsigned char)((v4_ucell)value & 0xFFu); else n->console_dropped++; return; } n->mem[(unsigned)addr] = value; } v4_cell v4_node_fetch(v4_node *n, v4_cell addr) { /* console_rx and console_status are -1 when no input is attached, which * no valid address equals. */ if (addr == n->console_status) return n->input_pos < n->input_len ? (v4_cell)-1 : (v4_cell)0; if (addr == n->console_rx) { v4_cell c; if (n->input_pos >= n->input_len) return (v4_cell)-1; c = (v4_cell)n->input[n->input_pos++]; if (n->input_pos == n->input_len) n->input_pos = n->input_len = 0; return c; } return v4_node_load(n, addr); } void v4_node_console_input_attach(v4_node *n, v4_cell rx, v4_cell status) { n->console_rx = rx; n->console_status = status; n->input_len = 0; n->input_pos = 0; } unsigned v4_node_console_feed(v4_node *n, const void *chars, unsigned len) { const unsigned char *c = (const unsigned char *)chars; unsigned i, pending = n->input_len - n->input_pos, took = 0; /* Slide what is pending to the front so the whole buffer is usable. */ if (n->input_pos > 0) { for (i = 0; i < pending; i++) n->input[i] = n->input[n->input_pos + i]; n->input_pos = 0; n->input_len = pending; } while (took < len && n->input_len < V4_CONSOLE_CAP) n->input[n->input_len++] = c[took++]; return took; } void v4_node_console_attach(v4_node *n, v4_cell addr) { n->console_tx = addr; n->console_len = 0; n->console_dropped = 0; }