/* capsule.c -- a capsule of F18 code. See capsule.h. * * Nothing here uses the C library. */ #include "v4/capsule.h" #include "v4/iword.h" #include "v4/opcode.h" /* A stretch of zeros shorter than this, between words that are not zero, is * sent with them: starting a new stretch costs four words. */ #define GAP 4u static v4_cell words_of(unsigned a, unsigned b, unsigned c, unsigned d) { unsigned op[V4_SLOT_COUNT]; unsigned k; op[0] = a; op[1] = b; op[2] = c; op[3] = d; for (k = 4; k < V4_SLOT_COUNT; k++) op[k] = V4_OP_NOP; return (v4_cell)v4_iword_assemble(op, 0); } /* `jump addr`, the jump in the first slot so that its address is as wide as * an address can be */ static v4_cell jump_to(v4_cell addr) { v4_ucell mask = (v4_ucell)v4_iword_slot_mask(0); v4_ucell word = (v4_ucell)words_of(V4_OP_JUMP, V4_OP_NOP, V4_OP_NOP, V4_OP_NOP); return (v4_cell)((word & ~mask) | ((v4_ucell)addr & mask)); } unsigned v4_capsule_write(const v4_node *n, v4_cell start, void (*out)(void *self, v4_cell word), void *self) { unsigned k = 0, written = 0; while (k < V4_NODE_WORDS) { unsigned first, last, zeros, i; if (n->mem[k] == 0) { k++; continue; } first = last = k; zeros = 0; for (i = k + 1; i < V4_NODE_WORDS && zeros < GAP; i++) { if (n->mem[i] != 0) { last = i; zeros = 0; } else zeros++; } out(self, words_of(V4_OP_FETCH_P, V4_OP_BANG_A, V4_OP_FETCH_P, V4_OP_PUSH)); out(self, (v4_cell)first); out(self, (v4_cell)(last - first)); out(self, words_of(V4_OP_FETCH_P, V4_OP_STORE_INC, V4_OP_UNEXT, V4_OP_NOP)); for (i = first; i <= last; i++) out(self, n->mem[i]); written += 4u + (last - first + 1u); k = last + 1; } out(self, jump_to(start)); return written + 1u; }