commit f6985c0591295e6d2d573e7f2599fe95cb86ea6a
parent d76f086cea6d03802dcc9df7c9bd3ccab550e928
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 3 Aug 2022 16:43:47 -0400
cvm: Helloworld!
Diffstat:
2 files changed, 91 insertions(+), 19 deletions(-)
diff --git a/posix/tmpboot.fs b/posix/tmpboot.fs
@@ -0,0 +1 @@
+Hello world!
diff --git a/posix/vm.c b/posix/vm.c
@@ -21,7 +21,8 @@ The VM is little endian.
#define HERE SYSVARS
#define CURRENT HERE+4
#define COMPILING CURRENT+4
-#define CURWORD COMPILING+4
+#define INRD COMPILING+4
+#define CURWORD INRD+4
#define HEREMAX SYSVARS
@@ -34,7 +35,6 @@ struct VM {
dword RSP;
dword PC; // when PC >= MEMSZ, machine is halted
dword toptr;
- dword bootptr;
dword areg;
byte mem[MEMSZ];
};
@@ -43,6 +43,7 @@ struct VM {
static dword lblmain = 0;
static struct VM vm = {0};
+static FILE *bootfp;
// Utilities
static byte gb(dword addr) { return vm.mem[addr]; }
@@ -92,6 +93,7 @@ static void callwr(dword a) {
cwrite(0x01);
dwrite(a);
}
+static void callword(dword addr); // forward declaration
// Operations
@@ -199,7 +201,7 @@ static void NEXT() { // op: 0f
}
static void BOOTRD() { // op: 10
- ppush(gb(vm.bootptr++));
+ ppush(fgetc(bootfp));
}
static void EMIT() { // op: 11
@@ -506,7 +508,41 @@ static void STACKCHK() { // op: 4d
}
}
-#define OPCNT 0x4e
+static void MAYBEWORD() { // op: 4e
+ dword c, a;
+ // save toptr so that it doesn't mess in<, which could be calling a word
+ // with to semantics
+ dword toptr = vm.toptr;
+ vm.toptr = 0;
+ do {
+ callword(gd(INRD));
+ c = ppop();
+ if (c >> 31) { // EOF
+ vm.toptr = toptr;
+ ppush(0);
+ return;
+ }
+ } while (c <= ' ');
+ a = CURWORD+1;
+ do {
+ sb(a++, c);
+ callword(gd(INRD));
+ c = ppop();
+ } while (!(c >> 31) && (c > ' '));
+ vm.toptr = toptr;
+ sb(CURWORD, a-CURWORD-1); // len
+ ppush(CURWORD);
+}
+
+static void WORD() { // op: 4f
+ MAYBEWORD();
+ if (!ppeek()) {
+ printf("word expected");
+ ABORT();
+ }
+}
+
+#define OPCNT 0x50
static void (*ops[OPCNT])() = {
BR, CALL, RET, LIT, BYE, BYEFAIL, QUIT, ABORT,
EXECUTE, CELL, VAL, ALIAS, DOES, SLIT, CBR, NEXT,
@@ -517,7 +553,7 @@ static void (*ops[OPCNT])() = {
CSTORE, CWRITE, WFETCH, WSTORE, FETCH, STORE, ADDSTORE, WRITE,
ADD, SUB, MUL, DIVMOD, AND, OR, XOR, BOOL,
NOT, LT, SHLC, SHRC, LSHIFT, RSHIFT, LITN, EXECUTEWR,
- EXITWR, MOVE, MOVEWR, RTYPE, WNF, STACKCHK};
+ EXITWR, MOVE, MOVEWR, RTYPE, WNF, STACKCHK, MAYBEWORD, WORD};
static char *opnames[OPCNT] = {
"(br)", NULL, NULL, NULL, "bye", "bytefail", "quit", "(abort)",
@@ -529,7 +565,28 @@ static char *opnames[OPCNT] = {
"c!", "c,", "w@", "w!", "@", "!", "+!", ",",
"+", "-", "*", "/mod", "and", "or", "xor", "bool",
"not", "<", "<<c", ">>c", "lshift", "rshift", "litn", "execute,",
- "exit,", "move", "move,", "rtype", "(wnf)", "stack?"};
+ "exit,", "move", "move,", "rtype", "(wnf)", "stack?", "maybeword", "word"};
+
+static void oprun1() { // run next op
+ byte opcode = vm.mem[vm.PC++];
+ if (opcode >= OPCNT) {
+ printf("Illegal opcode %02x at PC %08x\n", opcode, vm.PC-1);
+ BYEFAIL();
+ } else {
+ ops[opcode]();
+ }
+}
+
+static void callword(dword addr) {
+ dword oldPC;
+ // We push a special "0" marker to RS. This way, when PC is 0, we know that
+ // it's time to return from our callword().
+ rpush(0);
+ oldPC = vm.PC;
+ vm.PC = addr;
+ while (vm.PC && (vm.PC < MEMSZ)) oprun1();
+ vm.PC = oldPC;
+}
// Dictionary building
static void entry(char *name) {
@@ -546,6 +603,14 @@ static void opentry(byte op) {
cwrite(op);
}
+static void sysalias(char *name, dword addr) {
+ entry(name);
+ litwr(addr);
+ cwrite(0x34); // @
+ cwrite(0x08); // execute
+ retwr();
+}
+
static void buildsysdict() {
sd(HERE, 0);
sd(CURRENT, 0);
@@ -560,31 +625,37 @@ static void buildsysdict() {
for (int i=0x09; i<0x0b; i++) { opentry(i); retwr(); }
for (int i=0x0b; i<0x10; i++) opentry(i);
for (int i=0x10; i<OPCNT; i++) { opentry(i); retwr(); }
+ sysalias("in<", INRD);
+ sd(INRD, find("boot<"));
lblmain = here();
sd(0x01, lblmain);
- litwr('X');
+ callwr(find("word"));
callwr(find("dup"));
callwr(find("1+"));
- callwr(find("(emit)"));
- callwr(find("(emit)"));
+ callwr(find("swap"));
+ callwr(find("c@"));
+ callwr(find("rtype"));
+ callwr(find("word"));
+ callwr(find("dup"));
+ callwr(find("1+"));
+ callwr(find("swap"));
+ callwr(find("c@"));
+ callwr(find("rtype"));
callwr(find("bye"));
}
// Interpret loop
int main() {
- byte opcode;
vm.PC = 0;
vm.PSP = PSTOP;
vm.RSP = RSTOP;
- buildsysdict();
- while (vm.PC < MEMSZ) {
- opcode = vm.mem[vm.PC++];
- if (opcode >= OPCNT) {
- printf("Illegal opcode %02x at PC %08x\n", opcode, vm.PC-1);
- BYEFAIL();
- } else {
- ops[opcode]();
- }
+ bootfp = fopen("posix/tmpboot.fs", "r");
+ if (!bootfp) {
+ printf("Can't open boot file.\n");
+ return 1;
}
+ buildsysdict();
+ while (vm.PC < MEMSZ) oprun1();
+ fclose(bootfp);
return MEMSZ - vm.PC;
}