cvm: improve comments
They were a bit terse.
This commit is contained in:
parent
fc7971d64f
commit
25f4312523
15
cvm/vm.c
15
cvm/vm.c
@ -21,6 +21,8 @@ static VM vm;
|
||||
static uint64_t blkop = 0; // 5 bytes
|
||||
static FILE *blkfp;
|
||||
|
||||
// Read single byte from I/O handler, if set. addr is a word only because of
|
||||
// Forth's cell size, but can't actually address more than a byte-ful of ports.
|
||||
static byte io_read(word addr)
|
||||
{
|
||||
addr &= 0xff;
|
||||
@ -44,6 +46,9 @@ static void io_write(word addr, byte val)
|
||||
}
|
||||
}
|
||||
|
||||
// I/O hook to read/write a chunk of 1024 byte to blkfs at specified blkid.
|
||||
// This is used by EFS@ and EFS! in xcomp.fs.
|
||||
// See comment above BLK_PORT define for poking convention.
|
||||
static void iowr_blk(byte val)
|
||||
{
|
||||
blkop <<= 8;
|
||||
@ -62,29 +67,37 @@ static void iowr_blk(byte val)
|
||||
}
|
||||
}
|
||||
|
||||
// get/set word from/to memory
|
||||
static word gw(word addr) { return vm.mem[addr+1] << 8 | vm.mem[addr]; }
|
||||
static void sw(word addr, word val) {
|
||||
vm.mem[addr] = val;
|
||||
vm.mem[addr+1] = val >> 8;
|
||||
}
|
||||
// pop word from SP
|
||||
static word pop() {
|
||||
if (vm.uflw) return 0;
|
||||
if (vm.SP >= SP_ADDR) { vm.uflw = true; }
|
||||
return vm.mem[vm.SP++] | vm.mem[vm.SP++] << 8;
|
||||
}
|
||||
// push word to SP
|
||||
static void push(word x) {
|
||||
vm.SP -= 2; sw(vm.SP, x);
|
||||
if (vm.SP < vm.minSP) { vm.minSP = vm.SP; }
|
||||
}
|
||||
// pop word from RS
|
||||
static word popRS() {
|
||||
if (vm.uflw) return 0;
|
||||
if (vm.RS <= RS_ADDR) { vm.uflw = true; }
|
||||
word x = gw(vm.RS); vm.RS -= 2; return x;
|
||||
}
|
||||
// push word to RS
|
||||
static void pushRS(word val) {
|
||||
vm.RS += 2; sw(vm.RS, val);
|
||||
if (vm.RS > vm.maxRS) { vm.maxRS = vm.RS; }
|
||||
}
|
||||
|
||||
// The functions below directly map to native forth words defined in the
|
||||
// dictionary (B30)
|
||||
static void execute(word wordref) {
|
||||
byte wtype = vm.mem[wordref];
|
||||
if (wtype == 0) { // native
|
||||
@ -242,6 +255,7 @@ static void MINUS2() { push(pop()-2); }
|
||||
static void PLUS2() { push(pop()+2); }
|
||||
static void RSHIFT() { word u = pop(); push(pop()>>u); }
|
||||
static void LSHIFT() { word u = pop(); push(pop()<<u); }
|
||||
|
||||
static void native(NativeWord func) {
|
||||
vm.nativew[vm.nativew_count++] = func;
|
||||
}
|
||||
@ -284,6 +298,7 @@ VM* VM_init() {
|
||||
vm.iowr[i] = NULL;
|
||||
}
|
||||
vm.iowr[BLK_PORT] = iowr_blk;
|
||||
// Added in the same order as in xcomp.fs
|
||||
native(EXIT);
|
||||
native(_br_);
|
||||
native(_cbr_);
|
||||
|
24
cvm/vm.h
24
cvm/vm.h
@ -14,28 +14,30 @@ typedef void (*NativeWord) ();
|
||||
typedef byte (*IORD) ();
|
||||
typedef void (*IOWR) (byte data);
|
||||
|
||||
/* Native word placement
|
||||
Being a C VM, all actual native code is outside the VM's memory. However,
|
||||
we have a stable ABI to conform to. VM_init() configures the memory by
|
||||
placing references to stable words at proper offsets, and then add all other
|
||||
native words next to it. This will result in a "boot binary" that is much
|
||||
more compact than a real Collapse OS memory layout.
|
||||
*/
|
||||
typedef struct {
|
||||
byte mem[0x10000];
|
||||
word SP;
|
||||
word RS;
|
||||
word IP;
|
||||
word SP; // parameter Stack Pointer
|
||||
word RS; // Return Stack pointer
|
||||
word IP; // Interpreter Pointer
|
||||
// A list of native words' code. This is filled in VM_init() by calls to
|
||||
// native(). The order is very important because we refer to these elements
|
||||
// by index. For example, "0x42 CODE FOO" in Forth creates the native word
|
||||
// FOO which, when executed, will call the code at index 0x42 in this array.
|
||||
NativeWord nativew[0x100];
|
||||
byte nativew_count;
|
||||
// Array of 0x100 function pointers to IO read and write routines. Leave to
|
||||
// NULL when IO port is unhandled.
|
||||
IORD iord[0x100];
|
||||
IOWR iowr[0x100];
|
||||
word xcurrent; // only used during native bootstrap
|
||||
// Used for keeping track of max RS and min SP during the lifetime of the
|
||||
// program. Useful for debugging.
|
||||
word maxRS;
|
||||
word minSP;
|
||||
bool running;
|
||||
// Whether we're in stack underflow situation. Alters the behavior of some
|
||||
// core action, notably popping. Doesn't stay set for more than a single
|
||||
// execute cycle. The goal is to avoid over-popping in native words that
|
||||
// pop more than once and thus corrupt memory.
|
||||
bool uflw;
|
||||
} VM;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user