aboutsummaryrefslogtreecommitdiff
path: root/src/micro/micro_port.h
blob: 1653250358cf17a38ce5de8b8a6974329f47bb8e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* 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 <stdint.h>
#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