mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 09:38:06 +11:00
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 uint64_t blkop = 0; // 5 bytes
|
||||||
static FILE *blkfp;
|
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)
|
static byte io_read(word addr)
|
||||||
{
|
{
|
||||||
addr &= 0xff;
|
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)
|
static void iowr_blk(byte val)
|
||||||
{
|
{
|
||||||
blkop <<= 8;
|
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 word gw(word addr) { return vm.mem[addr+1] << 8 | vm.mem[addr]; }
|
||||||
static void sw(word addr, word val) {
|
static void sw(word addr, word val) {
|
||||||
vm.mem[addr] = val;
|
vm.mem[addr] = val;
|
||||||
vm.mem[addr+1] = val >> 8;
|
vm.mem[addr+1] = val >> 8;
|
||||||
}
|
}
|
||||||
|
// pop word from SP
|
||||||
static word pop() {
|
static word pop() {
|
||||||
if (vm.uflw) return 0;
|
if (vm.uflw) return 0;
|
||||||
if (vm.SP >= SP_ADDR) { vm.uflw = true; }
|
if (vm.SP >= SP_ADDR) { vm.uflw = true; }
|
||||||
return vm.mem[vm.SP++] | vm.mem[vm.SP++] << 8;
|
return vm.mem[vm.SP++] | vm.mem[vm.SP++] << 8;
|
||||||
}
|
}
|
||||||
|
// push word to SP
|
||||||
static void push(word x) {
|
static void push(word x) {
|
||||||
vm.SP -= 2; sw(vm.SP, x);
|
vm.SP -= 2; sw(vm.SP, x);
|
||||||
if (vm.SP < vm.minSP) { vm.minSP = vm.SP; }
|
if (vm.SP < vm.minSP) { vm.minSP = vm.SP; }
|
||||||
}
|
}
|
||||||
|
// pop word from RS
|
||||||
static word popRS() {
|
static word popRS() {
|
||||||
if (vm.uflw) return 0;
|
if (vm.uflw) return 0;
|
||||||
if (vm.RS <= RS_ADDR) { vm.uflw = true; }
|
if (vm.RS <= RS_ADDR) { vm.uflw = true; }
|
||||||
word x = gw(vm.RS); vm.RS -= 2; return x;
|
word x = gw(vm.RS); vm.RS -= 2; return x;
|
||||||
}
|
}
|
||||||
|
// push word to RS
|
||||||
static void pushRS(word val) {
|
static void pushRS(word val) {
|
||||||
vm.RS += 2; sw(vm.RS, val);
|
vm.RS += 2; sw(vm.RS, val);
|
||||||
if (vm.RS > vm.maxRS) { vm.maxRS = vm.RS; }
|
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) {
|
static void execute(word wordref) {
|
||||||
byte wtype = vm.mem[wordref];
|
byte wtype = vm.mem[wordref];
|
||||||
if (wtype == 0) { // native
|
if (wtype == 0) { // native
|
||||||
@ -242,6 +255,7 @@ static void MINUS2() { push(pop()-2); }
|
|||||||
static void PLUS2() { push(pop()+2); }
|
static void PLUS2() { push(pop()+2); }
|
||||||
static void RSHIFT() { word u = pop(); push(pop()>>u); }
|
static void RSHIFT() { word u = pop(); push(pop()>>u); }
|
||||||
static void LSHIFT() { word u = pop(); push(pop()<<u); }
|
static void LSHIFT() { word u = pop(); push(pop()<<u); }
|
||||||
|
|
||||||
static void native(NativeWord func) {
|
static void native(NativeWord func) {
|
||||||
vm.nativew[vm.nativew_count++] = func;
|
vm.nativew[vm.nativew_count++] = func;
|
||||||
}
|
}
|
||||||
@ -284,6 +298,7 @@ VM* VM_init() {
|
|||||||
vm.iowr[i] = NULL;
|
vm.iowr[i] = NULL;
|
||||||
}
|
}
|
||||||
vm.iowr[BLK_PORT] = iowr_blk;
|
vm.iowr[BLK_PORT] = iowr_blk;
|
||||||
|
// Added in the same order as in xcomp.fs
|
||||||
native(EXIT);
|
native(EXIT);
|
||||||
native(_br_);
|
native(_br_);
|
||||||
native(_cbr_);
|
native(_cbr_);
|
||||||
|
24
cvm/vm.h
24
cvm/vm.h
@ -14,28 +14,30 @@ typedef void (*NativeWord) ();
|
|||||||
typedef byte (*IORD) ();
|
typedef byte (*IORD) ();
|
||||||
typedef void (*IOWR) (byte data);
|
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 {
|
typedef struct {
|
||||||
byte mem[0x10000];
|
byte mem[0x10000];
|
||||||
word SP;
|
word SP; // parameter Stack Pointer
|
||||||
word RS;
|
word RS; // Return Stack pointer
|
||||||
word IP;
|
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];
|
NativeWord nativew[0x100];
|
||||||
byte nativew_count;
|
byte nativew_count;
|
||||||
// Array of 0x100 function pointers to IO read and write routines. Leave to
|
// Array of 0x100 function pointers to IO read and write routines. Leave to
|
||||||
// NULL when IO port is unhandled.
|
// NULL when IO port is unhandled.
|
||||||
IORD iord[0x100];
|
IORD iord[0x100];
|
||||||
IOWR iowr[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 maxRS;
|
||||||
word minSP;
|
word minSP;
|
||||||
bool running;
|
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;
|
bool uflw;
|
||||||
} VM;
|
} VM;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user