/* host port for the microcore. micro.c calls only these. a bare-metal port is the five functions below: the uart replaces getc/putc, and every syscall returns -1. port_stub.c is the empty shape the freestanding compile check links. src/baremetal/port.c is the one that boots: a 16550 on riscv virt, a PL011 on aarch64 virt. port_linux.c is the hosted one the test suite runs. the core does not use stdio, malloc, or the string routines. it does need a 64-bit C compiler (division is the compiler's own runtime, not libc) and a zeroed bss before micro_run. memory starts at MICRO_MW_INIT words of 64 bits and grows through micro_mem_alloc when the heap asks for more. */ #ifndef MICRO_PORT_H #define MICRO_PORT_H #include #include "memmap.h" typedef int64_t Cell; typedef uint64_t UCell; #ifndef MICRO_MW_LIMIT #define MICRO_MW_LIMIT 0x7fffffff #endif /* configure initial words and the growth limit before micro_run. */ int micro_memory_config(UCell initial, UCell limit); /* the machine starts at this many words and grows on demand through micro_mem_alloc. the map's initial heap (HEAP_HI) on a growing map, the whole map (MW) otherwise. there is no fixed ceiling: a run that needs more memory asks the port for it. */ #ifndef MICRO_MW_INIT #if HEAP_GROW #define MICRO_MW_INIT HEAP_HI #else #define MICRO_MW_INIT MW #endif #endif /* the machine's memory, in words, from the port. micro_mem_alloc(words) returns a zeroed base with at least words words that stays valid until the next call; the port keeps what it already holds, so a grow keeps the contents. NULL when the port has no more memory. micro_mem_words is the size micro.c has mapped now. */ Cell *micro_mem_alloc(UCell words); UCell micro_mem_words(void); /* next input byte, 0..255, or -1 at end of input. does not report whether another byte follows; micro_eof does that, and the core asks after each read. */ int micro_getc(void); /* 1 when the next micro_getc would return -1, 0 when a byte is waiting. must not consume the byte. called once before the first instruction. */ int micro_eof(void); /* streaming input: micro_getc returns MICRO_WAIT when no byte is waiting yet but more may come (micro_eof then says 0). the run then returns MICRO_SUSPENDED, and the port calls micro_resume once it has bytes. the browser and the extension use this for the language server; a port with blocking input never needs it. micro_run and micro_resume return what run returns, MICRO_SUSPENDED included. */ #define MICRO_WAIT (-2) #define MICRO_SUSPENDED 3 int micro_run(void); /* with MICRO_PORT_IMAGE defined, the port's micro_port_image(mem, org, end) may load an image of its own at mem[org..end): 1 when it did, 0 to use the embedded genome, -1 on error. */ int micro_port_image(Cell *mem, UCell org, UCell end); int micro_resume(void); /* write the low 8 bits. */ void micro_putc(int c); /* a store of op to SYSGATE (ZFP+2; 0xA0002 on the default map). a, b, c are the three words after the gate. mem is the whole machine. return the result, or -1 if op is unsupported. 1 open(path, 0 read | 1 create/truncate) -> fd 2 close(fd) 3 read(fd, buf, n) 4 write(fd, buf, n) one byte per word 5 getenv(name, buf, cap) -> length, or -1 6 time. unix seconds on a hosted port; a hardware counter on bare metal 7 exit(status). does not return 8 a random word, never -1 when the port has a source 9 memory: a = 0 words now, 1 HEAP_LO, 2 HEAP_HI, 3 bytes now, 4 grow to b words 10 bopen(byte_addr, mode) 11 bread(fd, byte_addr, n) 12 bwrite(fd, byte_addr, n) 13 bgetenv(name_byte_addr, dst_byte_addr, cap) ops 1..5 and the names they take are one character per word, 0 terminated. ops 10..13 are packed bytes, 0 terminated, the same layout as a b"..." payload. the bare-metal port keeps files in RAM and answers getenv("BOARD"). the stub returns -1. */ Cell micro_syscall(Cell *mem, Cell op, Cell a, Cell b, Cell c); /* a short diagnostic, usually the stack-overflow lines. not program output. may be a no-op. */ void micro_msg(const char *s); /* copy the linked genome in and run from its entry. 0 on halt, 2 on a stack overflow (after a message). */ int micro_run(void); #endif