commit 70e8edc9ef04c0283c7d469948e7f4d38b0a5544
parent 43e0d94425533d4a7a74d2bfac3ec566e119337a
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 8 Mar 2023 22:12:59 -0500
HAL wip
Those who have been following Collapse OS development for a while know that I
tried at some point to have what I call a Harmonized Assembly Layer, a sort of
cross-CPU simplified assembler. It worked, but the cost in binary size was too
great for its benefits, so I removed it. This is my second take.
This is a much different approach. Now, much of the mechanics for the HAL
assembler is directly in each native kernel. Not only that, but the kernel
isn't a kernel anymore, it's a kernel *assembler*. The binary at boot has
almost no word that a Forth needs. No "@", no "!", no ",", no "dup", no "over",
only HAL words (words that assemble native code) as well as the bare minimum to
get the bootstrapping process started (the interpret loop and the ability to
define new words).
Previously, we could say that the bootstrapping process started at
"xcomp/bootlo.fs", but now it starts inside the kernel code, that is, that
before bootlo can be called, the kernel binary will call itself (in native code)
a little bit to assemble new words allowing to jump into bootlo.
What's the point of all this? Replace comp/c/vm. With the HAL, such a layer
wouldn't be needed anymore and would simplify DuskCC. It would be Dusk'
underpowered LLVM. Unlike comp/c/vm, the HAL could also be used directly for
speeding up code (or getting out of tricky stack juggling situations). Or by
compiler for other languages.
I'm not 100% sure that this will work, but this clearly passes the threshold of
insanity and my head is going to explode from the pressure of that awesomeness.
Now, of course, it's not super impressive because it's only posix/vm.c, but if
it works there, I'm pretty sure it's going to work in i386.
At the moment, "make run" bootstraps that new kernel in bootlo up to the "foo"
point where it calls "bye". As you can see, I'm at a critical point where I need
to fit this system in the "to" semantics. I think it's going to work...
Diffstat:
M | fs/xcomp/bootlo.fs | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
M | posix/vm.c | | | 1157 | ++++++++++++++++++------------------------------------------------------------- |
2 files changed, 307 insertions(+), 931 deletions(-)
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -1,26 +1,46 @@
-," w>e" 0 , sysdict @ , 3 c, HERE @ 5 - sysdict ! ]
- 5 - [ exit,
-," ;" 0 , sysdict @ , $81 c, HERE @ w>e sysdict !
- ' [ execute, ' exit, execute, exit,
-," entry" 0 , sysdict @ , 5 c, HERE @ w>e sysdict ! ]
- dup 1+ swap c@
- dup 1+ align4
- tuck move, nextmeta @ , over @ , c,
- HERE @ w>e swap ! 0 nextmeta ! 0 [rcnt] ! ;
-," code" 0 , sysdict @ , 4 c, HERE @ w>e sysdict ! ]
- sysdict word entry ;
code : ] code ] ;
-code drop 4 p+, exit,
+: noop ;
+: W) 0 ; : A) 1 ; : PSP) 2 ; : RSP) 3 ; : i) $c ;
+code @ W) @, exit,
+code16b W) 16b @, exit,
+code8b W) 8b @, exit,
+: c@ 8b @ ; : w@ 16b @ ;
+: drop, PSP) @, 4 ps+, ;
+code drop drop, exit,
+code ! W>A, drop, A) !, exit,
+code16b W>A, drop, A) 16b !, exit,
+code8b W>A, drop, A) 8b !, exit,
+: c! 8b ! ; : w! 16b ! ;
+code +! W>A, A) @, ] + [ A) !, exit,
+code16b W>A, A) 16b @, ] + [ A) 16b !, exit,
+code8b W>A, A) 8b @, ] + [ A) 8b !, exit,
+code , HERE i) [!], 4 HERE i) [+], exit,
+code16b HERE i) 16b [!], 2 HERE i) [+], exit,
+code8b HERE i) 8b [!], 1 HERE i) [+], exit,
+: c, 8b , ;
+: dup, -4 ps+, PSP) !, ;
+code dup dup, exit,
+code swap PSP) @!, exit,
+: +) swap $08 or ;
+code rot PSP) @!, PSP) 4 +) @!, exit,
+code rot> PSP) 4 +) @!, PSP) @!, exit,
+code 1+ 1 W+, exit,
+code 1- -1 W+, exit,
+: litn -4 ps+, PSP) !, LIT>W, ;
: e>w 5 + ;
+: w>e 5 - ;
: current sysdict @ e>w ;
: immediate current 1- dup c@ $80 or swap c! ;
+: if 0 ?branch, ; immediate
+: ifz 0 branchz, ; immediate
+: ahead 0 branch, ; immediate
+: then HERE @ swap branch! ; immediate
+: ?dup ifz [ dup, ] then ;
+: ' word sysdict @ find dup not if (wnf) then ;
: ['] ' litn ; immediate
: compile ' litn ['] execute, execute, ; immediate
: [compile] ' execute, ; immediate
: allot HERE +! ;
-: if 0 ?branch, ; immediate
-: ahead 0 branch, ; immediate
-: then HERE @ swap branch! ; immediate
: else [compile] ahead HERE @ rot branch! ; immediate
: begin HERE @ ; immediate
: again branch, drop ; immediate
@@ -35,26 +55,27 @@ code drop 4 p+, exit,
again ; immediate
( hello, another comment! )
\ Stack
-: rdrop 4 r+, ; immediate
-: 2rdrop 8 r+, ; immediate
-: r@ RSP>A, A@, ; immediate
+: rdrop 4 rs+, ; immediate
+: 2rdrop 8 rs+, ; immediate
+: r@ dup, RSP) @, ; immediate
: r> [compile] r@ [compile] rdrop ; immediate
-: >r -4 r+, RSP>A, A!, ; immediate
-code 2drop 8 p+, exit,
-: 2dup over over ;
+: >r -4 rs+, RSP) !, drop, ; immediate
+code nip 4 ps+, exit,
+code 2drop PSP) 4 +) @, 8 ps+, exit,
+: over, dup, PSP) 4 +) @, ;
+code over over, exit,
+code 2dup W>A, PSP) @, -8 ps+, PSP) !, W<>A, PSP) 4 +) !, exit,
\ Arithmetic
: > swap < ;
-: 0< <<c nip ;
-: 0>= 0< not ;
+: 0>= $80000000 < ;
+: 0< 0>= not ;
: >= < not ;
: <= > not ;
: <> = not ;
: -^ swap - ;
: / /mod nip ;
: mod /mod drop ;
-: << <<c drop ;
-: >> >>c drop ;
: ?swap ( n n -- l h ) 2dup > if swap then ;
: min ?swap drop ; : max ?swap nip ;
: max0 ( n -- n ) dup 0< if drop 0 then ;
@@ -75,23 +96,21 @@ code 2drop 8 p+, exit,
?dup if begin [compile] then ?dup not until then [compile] rdrop ; immediate
\ Local variables + beginning of compiling words
+code (cell) r> exit,
: create code compile (cell) ;
: const code litn exit, ;
4 const CELLSZ
create toptr 0 , \ pointer to 8b struct [execword, compileword]
-create toptrdef ' @ , ' A@, ,
+create toptrdef ' @ , ' @, ,
: toptr@ ( -- w )
toptr @ 0 toptr ! ?dup not if toptrdef then
compiling if CELLSZ + then @ findmod ;
-: var, ( off -- ) RSP>A, [rcnt] @ neg CELLSZ - -^ A+, toptr@ execute ;
+: var, ( off -- ) RSP) [rcnt] @ neg CELLSZ - -^ +) toptr@ execute ;
: V1 0 var, ; immediate : V2 4 var, ; immediate
: V3 8 var, ; immediate : V4 12 var, ; immediate
-$10 const EMETA_8B
-$11 const EMETA_16B
-: 8b EMETA_8B MOD ! ; immediate
-: 16b EMETA_16B MOD ! ; immediate
+: foo 'A' CELLSZ + (emit) bye ; foo
\ Compiling words
create _ 0 ,
: doer code compile (does) HERE @ _ ! CELLSZ allot ;
diff --git a/posix/vm.c b/posix/vm.c
@@ -1,8 +1,3 @@
-/* Dusk VM for POSIX platforms
-
-The VM is little endian, has a read-only file system and is pretty slow. It's
-enough, however, to generate native binary images for any supported target.
-*/
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
@@ -12,7 +7,6 @@ enough, however, to generate native binary images for any supported target.
#include <libgen.h>
#include <dirent.h>
#include <stdlib.h>
-#undef FOPEN // some platforms' fcntl.h define FOPEN which clashes below.
#define MEMSZ 0x1000000 // 16MB
#define STACKSZ 0x800
@@ -31,6 +25,14 @@ enough, however, to generate native binary images for any supported target.
#define IOBUFSZ 0x200
#define IOBUF (SYSVARS-IOBUFSZ)
+#define OPW 0
+#define OPA 1
+#define OPPSP 2
+#define OPRSP 3
+#define OPIMM 4
+#define OPDISP 0x08
+#define EMETA_8B 0x10
+#define EMETA_16B 0x11
typedef uint8_t byte;
typedef uint16_t word;
@@ -40,9 +42,9 @@ struct VM {
dword PSP;
dword RSP;
dword PC; // when PC >= MEMSZ, machine is halted
+ dword W; // W is PS top
dword A;
byte compiling;
- byte bwidth; // 0=32bit 1=16bit 2=8bit
byte mem[MEMSZ];
};
@@ -62,38 +64,17 @@ static dword memchk(dword a) {
vmabort();
return 0;
}
-static dword bwidth() {
- switch (vm.bwidth) {
- case 1: return 2;
- case 2: return 1;
- default: return 4;
- }
-}
static byte gb(dword addr) { return vm.mem[memchk(addr)]; }
static word gw(dword addr) { return gb(addr) | (gb(addr+1)<<8); }
static dword gd(dword addr) { return gw(addr) | (gw(addr+2)<<16); }
-static dword gv(dword addr) {
- switch (vm.bwidth) {
- case 1: return (dword)gw(addr);
- case 2: return (dword)gb(addr);
- default: return gd(addr);
- }
-}
static dword gpc() { dword n = gd(vm.PC); vm.PC += 4; return n; }
static byte gpcb() { dword n = gb(vm.PC); vm.PC++; return n; }
static void sb(dword addr, byte b) { vm.mem[memchk(addr)] = b; }
static void sw(dword addr, word w) { sb(addr, w); sb(addr+1, w>>8); }
static void sd(dword addr, dword d) { sw(addr, d); sw(addr+2, d>>16); }
-static void sv(dword addr, dword n) {
- switch (vm.bwidth) {
- case 1: sw(addr, n); break;
- case 2: sb(addr, n); break;
- default: sd(addr, n);
- }
-}
-static dword ppeek() { return gd(vm.PSP); }
-static dword ppop() { dword n = ppeek(); vm.PSP += 4; return n; }
-static void ppush(dword d) { vm.PSP -= 4; sd(vm.PSP, d); }
+static dword pnip() { dword n = gd(vm.PSP); vm.PSP += 4; return n; }
+static dword ppop() { dword n = vm.W; vm.W = gd(vm.PSP); vm.PSP += 4; return n; }
+static void ppush(dword n) { vm.PSP -= 4; sd(vm.PSP, vm.W); vm.W = n; }
static dword rpeek() { return gd(vm.RSP); }
static dword rpop() { dword n = rpeek(); vm.RSP += 4; return n; }
static void rpush(dword d) { vm.RSP -= 4; sd(vm.RSP, d); }
@@ -139,462 +120,116 @@ static void dwrite(dword d) {
sd(here(), d);
allot(4);
}
+
static void retwr() { cwrite(0x02); }
-static void litwr(dword n) {
- cwrite(0x03); // LIT
- dwrite(n);
-}
+static void psaddwr(dword n) { cwrite(0x08); dwrite(n); }
+static void wopwr(byte opcode, byte operand, dword disp) {
+ cwrite(opcode);
+ if (disp) operand |= OPDISP;
+ cwrite(operand);
+ if (operand & OPDISP) dwrite(disp);
+}
+static void wfetchwr(byte op, dword disp) { wopwr(0x10, op, disp); }
+static void wstorewr(byte op, dword disp) { wopwr(0x11, op, disp); }
+static void maddnwr(byte op, dword disp, dword n) { wopwr(0x13, op, disp); dwrite(n); }
+static void wistorewr(byte op, dword disp) { wopwr(0x16, op, disp); }
+static void wistorewr8(byte op, dword disp) { wopwr(0x26, op, disp); }
+static void dupwr() { psaddwr(0xfffffffc); wstorewr(OPPSP, 0); }
+static void nipwr() { psaddwr(4); }
+static void dropwr() { wfetchwr(OPPSP, 0); nipwr(); }
+static void wlitwr(dword n) { cwrite(0x0a); dwrite(n); }
+static void alitwr(dword n) { cwrite(0x0b); dwrite(n); }
+static void litwr(dword n) { dupwr(); wlitwr(n); }
+static void callwr(dword a) { cwrite(0x01); dwrite(a); }
+static void brwr(dword a) { cwrite(0x00); dwrite(a); }
+static void writewr() { alitwr(HERE); wistorewr(OPA, 0); maddnwr(OPA, 0, 4); dropwr(); }
+static void cwritewr() { alitwr(HERE); wistorewr8(OPA, 0); maddnwr(OPA, 0, 1); dropwr(); }
+static void compopwr(byte opcode) { litwr(opcode); cwrite(0x3e); }
+static void storewr() { cwrite(0x0e); dropwr(); wstorewr(OPA, 0); dropwr(); }
-static void callwr(dword a) {
- cwrite(0x01); // CALL
- dwrite(a);
-}
-static void jumpwr(dword a) {
- cwrite(0x00); // JUMP
- dwrite(a);
-}
static void callword(dword addr); // forward declaration
-static void _entry(byte *name, byte slen) {
+static void _entry(dword dict, byte *name, byte slen) {
memcpy(&vm.mem[here()], name, slen);
allot(slen);
dwrite(gd(NEXTMETA));
- dwrite(sysdict());
+ dwrite(dict);
cwrite(slen);
sd(SYSDICT, here()-5);
sd(NEXTMETA, 0);
}
static void entry(char *name) {
- _entry((byte*)name, strlen(name));
-}
-
-// Operations
-/* The VM works in a simple manner. The VM reads the byte where PC points to in
-memory, increases PC by 1 and executes the corresponding function in the
-function list below. As simple as this. */
-
-static void JUMP() { // op: 00
- vm.PC = gpc();
-}
-
-static void CALL() { // op: 01
- dword n = gpc();
- rpush(vm.PC);
- vm.PC = n;
-}
-
-static void RET() { // op: 02
- vm.PC = rpop();
-}
-
-static void LIT() { // op: 03
- dword n = gpc();
- ppush(n);
-}
-
-static void BYE() { // op: 04
- vm.PC = MEMSZ;
-}
-
-static void BYEFAIL() { // op: 05
- vmabort();
-}
-
-static void QUIT() { // op: 06
- vm.bwidth = 0;
- sd(MOD, 0);
- vm.RSP = RSTOP;
- vm.compiling = 0;
- vm.PC = mainaddr;
-}
-
-static void ABORT_() { // op: 07
- vm.PSP = PSTOP;
- sd(NEXTMETA, 0);
- QUIT();
-}
-
-static void EXECUTE() { // op: 08
- vm.PC = ppop();
-}
-
-static void CELL() { // op: 09
- ppush(rpop());
-}
-
-static void DOES() { // op: 0a
- dword a = rpop();
- ppush(a+4);
- vm.PC = gd(a);
-}
-
-static void SLIT() { // op: 0b
- dword a = rpop();
- ppush(a);
- vm.PC = a + gb(a) + 1;
-}
-
-// ( a -- a )
-static void BRWR() { // op: 0c
- dword a = here()+1;
- jumpwr(ppop());
- ppush(a);
-}
-
-static void CBR() { // op: 0d
- dword a = gpc();
- if (!ppop()) vm.PC = a;
-}
-
-// ( a -- a )
-static void CBRWR() { // op: 0e
- dword a = here()+1;
- cwrite(0x0d); // CBR
- dwrite(ppop());
- ppush(a);
-}
-
-// ( a -- a )
-static void YIELD() { // op: 0f
- dword pc = vm.PC;
- vm.PC = rpop();
- rpush(pc);
-}
-
-static void PSADD() { // op: 10
- byte n = gpcb();
- vm.PSP += (char)n;
-}
-
-static void PSADDWR() { // op: 11
- dword n = ppop();
- cwrite(0x10); // PSADD
- cwrite(n);
-}
-
-static void BOOTRD() { // op: 14
- ppush(fgetc(fp));
-}
-
-static void STDOUT() { // op: 15
- dword c = ppop();
- write(STDOUT_FILENO, &c, 1);
-}
-
+ _entry(sysdict(), (byte*)name, strlen(name));
+}
+
+/* Operations */
+static void BR() { vm.PC = gpc(); } // 0x00
+static void CALL() { dword n = gpc(); rpush(vm.PC); vm.PC = n; }
+static void RET() { vm.PC = rpop(); }
+static void EXECUTE() { rpush(vm.PC); vm.PC = ppop(); }
+static void CBR() { dword a = gpc(); if (!ppop()) vm.PC = a; }
+// ( a opcode -- a )
+static void BRWR() { cwrite(ppop()); dwrite(vm.W); vm.W = here()-4; }
+static void BRZ() { dword a = gpc(); if (!vm.W) vm.PC = a; }
+
+static void PSADD() { vm.PSP += gpc(); } // 0x08
+static void RSADD() { vm.RSP += gpc(); }
+static void WLIT() { vm.W = gpc(); }
+static void ALIT() { vm.A = gpc(); }
+static void WADD() { vm.W += gpc(); }
+static void AADD() { vm.A += gpc(); }
+static void W2A() { vm.A = vm.W; }
+static void WSWAPA() { dword n = vm.A; vm.A = vm.W; vm.W = n; }
+
+static dword readop() { // 1b optype 4b displacement
+ byte op = gpcb();
+ dword addr;
+ switch (op & 7) {
+ case OPW: addr = vm.W; break;
+ case OPA: addr = vm.A; break;
+ case OPPSP: addr = vm.PSP; break;
+ case OPRSP: addr = vm.RSP; break;
+ case OPIMM: addr = 0; break;
+ default:
+ printf("Illegal readop %02x at PC %08x\n", op, vm.PC-1);
+ vmabort();
+ return 0;
+ }
+ if (op & OPDISP) addr += gpc();
+ return addr;
+}
+static void WFETCH() { vm.W = gd(readop()); } // 0x10
+static void WSTORE() { sd(readop(), vm.W); }
+static void WSWAP() { dword a, n; a = readop(); n = gd(a); sd(a, vm.W); vm.W = n; }
+static void MADDN() { dword a = readop(); dword n=gpc(); sd(a, gd(a)+n); }
+static void WLEA() { vm.W = readop(); }
+static void WIFETCH() { vm.W = gd(gd(readop())); }
+static void WISTORE() { sd(gd(readop()), vm.W); }
+
+static void WFETCH16() { vm.W = gw(readop()); } // 0x18
+static void WSTORE16() { sw(readop(), vm.W); }
+static void WSWAP16() { dword a, n; a = readop(); n = gw(a); sw(a, vm.W); vm.W = n; }
+static void MADDN16() { dword a = readop(); dword n=gpc(); sw(a, gw(a)+(word)n); }
+static void WIFETCH16() { vm.W = gw(gd(readop())); }
+static void WISTORE16() { sw(gd(readop()), vm.W); }
+
+static void WFETCH8() { vm.W = gb(readop()); } // 0x20
+static void WSTORE8() { sb(readop(), vm.W); }
+static void WSWAP8() { dword a, n; a = readop(); n = gb(a); sb(a, vm.W); vm.W = n; }
+static void MADDN8() { dword a = readop(); dword n=gpc(); sb(a, gb(a)+(byte)n); }
+static void WIFETCH8() { vm.W = gb(gd(readop())); }
+static void WISTORE8() { sb(gd(readop()), vm.W); }
+
+static void BOOTRD() { ppush(fgetc(fp)); } // 0x28
+static void STDOUT() { dword c = ppop(); write(STDOUT_FILENO, &c, 1); }
// ( -- c? f )
-static void MAYBEKEY() { // op: 16
+static void MAYBEKEY() {
char c;
if (read(STDIN_FILENO, &c, 1) == 1) {
- ppush(c);
- ppush(1);
- } else {
- ppush(0);
- }
-}
-
-static void FINDMETA() { // op: 17
- dword ll = ppop();
- dword id = ppop();
- ppush(findmeta(id, ll));
-}
-
-static void DUP() { // op: 18
- ppush(ppeek());
-}
-
-static void CDUP() { // op: 19
- if (ppeek()) { DUP(); }
-}
-
-static void SWAP() { // op: 1a
- dword a = ppop();
- dword b = ppop();
- ppush(a); ppush(b);
-}
-
-static void OVER() { // op: 1b
- dword a = gd(vm.PSP+4);
- ppush(a);
-}
-
-static void ROT() { // op: 1c
- dword a = ppop();
- dword b = ppop();
- dword c = ppop();
- ppush(b); ppush(a); ppush(c);
-}
-
-static void ROTR() { // op: 1d
- dword a = ppop();
- dword b = ppop();
- dword c = ppop();
- ppush(a); ppush(c); ppush(b);
-}
-
-static void NIP() { // op: 1e
- dword n = ppop();
- sd(vm.PSP, n);
-}
-
-static void TUCK() { // op: 1f
- dword a = ppop();
- dword b = ppop();
- ppush(a); ppush(b); ppush(a);
+ ppush(c); ppush(1);
+ } else { ppush(0); }
}
-static void RSADD() { // op: 20
- dword n = gpc();
- vm.RSP += n;
-}
-
-static void RSADDWR() { // op: 21
- dword n = ppop();
- cwrite(0x20); // RSADD
- dwrite(n);
- sd(_RCNT_, gd(_RCNT_)+n);
-}
-
-static void SCNT() { // op: 24
- ppush((PSTOP-vm.PSP)>>2);
-}
-
-static void RCNT() { // op: 25
- ppush(((RSTOP-vm.RSP)>>2)-1);
-}
-
-static void RSP2A() { // op: 26
- vm.A = vm.RSP;
-}
-
-static void PSP2A() { // op: 27
- vm.A = vm.PSP;
-}
-
-static void AFETCH() { // op: 28
- ppush(gv(vm.A));
- vm.bwidth = 0;
-}
-
-static void ASTORE() { // op: 29
- sv(vm.A, ppop());
- vm.bwidth = 0;
-}
-
-static void AADDSTORE() { // op: 2a
- sv(vm.A, gv(vm.A)+ppop());
- vm.bwidth = 0;
-}
-
-static void AFETCHSTORE() { // op: 2b
- dword n = ppop();
- ppush(gv(vm.A));
- sv(vm.A, n);
- vm.bwidth = 0;
-}
-
-static void AINC() { // op: 2c
- vm.A += gpc();
-}
-
-static void AIINC() { // op: 2d
- sd(vm.A, gd(vm.A)+gpc());
-}
-
-static void AIFETCH() { // op: 2e
- ppush(gv(gd(vm.A)));
- vm.bwidth = 0;
-}
-
-static void AISTORE() { // op: 2f
- sv(gd(vm.A), ppop());
- vm.bwidth = 0;
-}
-
-static void WRITE() { // op: 30
- sv(here(), ppop());
- allot(bwidth());
- vm.bwidth = 0;
-}
-
-#define ESCAPECNT 3
-static char escapes[ESCAPECNT][2] = {{'n', '\n'}, {'r', '\r'}, {'0', 0}};
-static void SRD() { // op: 31
- dword c;
- callword(inrdaddr);
- c = ppop();
- if (c == '"') {
- c = 0xffffffff;
- } else if (c == '\\') {
- callword(inrdaddr);
- c = ppop();
- for (int i=0; i<ESCAPECNT; i++) {
- if ((dword)escapes[i][0] == c) {
- c = escapes[i][1];
- }
- }
- }
- ppush(c);
-}
-
-static void SWR() { // op: 32
- dword c;
- while (1) {
- SRD();
- c = ppop();
- if (c==0xffffffff) return;
- cwrite(c);
- }
-}
-
-static void SETBW() { // op: 33
- vm.bwidth = ppop();
-}
-
-static void SETA() { // op: 34
- vm.A = ppop();
-}
-
-static void PUSHA() { // op: 35
- ppush(vm.A);
-}
-
-static void GETBW() { // op: 36
- ppush(vm.bwidth);
-}
-
-static void LITA() { // op: 37
- vm.A = gpc();
-}
-
-static void INC() { // op: 38
- ppush(ppop()+1);
-}
-
-static void DEC() { // op: 39
- ppush(ppop()-1);
-}
-
-static void ADD() { // op: 3a
- dword n = ppop();
- ppush(ppop()+n);
-}
-
-static void SUB() { // op: 3b
- dword n = ppop();
- ppush(ppop()-n);
-}
-
-static void MUL() { // op: 3c
- dword n = ppop();
- ppush(ppop()*n);
-}
-
-// ( a b -- r q )
-static void DIVMOD() { // op: 3d
- dword b = ppop();
- dword a = ppop();
- ppush(a%b);
- ppush(a/b);
-}
-
-static void AND() { // op: 3e
- dword n = ppop();
- ppush(ppop()&n);
-}
-
-static void ALIGN4() { // op: 3f
- dword n = ppop();
- n = (here() + n) % 4;
- if (n) { allot(4-n); }
-}
-
-static void OR() { // op: 40
- dword n = ppop();
- ppush(ppop()|n);
-}
-
-static void XOR() { // op: 41
- dword n = ppop();
- ppush(ppop()^n);
-}
-
-static void BOOL() { // op: 42
- if (ppop()) { ppush(1); } else { ppush(0); }
-}
-
-static void NOT() { // op: 43
- if (ppop()) { ppush(0); } else { ppush(1); }
-}
-
-static void LT() { // op: 44
- dword n = ppop();
- if (ppop()<n) { ppush(1); } else { ppush(0); }
-}
-
-static void SHLC() { // op: 45
- dword n = ppop();
- ppush(n<<1);
- ppush(n>>31);
-}
-
-static void SHRC() { // op: 46
- dword n = ppop();
- ppush(n>>1);
- ppush(n&1);
-}
-
-// ( n u -- n )
-static void LSHIFT() { // op: 47
- dword u = ppop();
- dword n = ppop();
- ppush(n<<u);
-}
-
-static void RSHIFT() { // op: 48
- dword u = ppop();
- dword n = ppop();
- ppush(n>>u);
-}
-
-static void MOVE() { // op: 4c
- dword u = ppop();
- dword dst = ppop();
- dword src = ppop();
- if (memchk(dst+u) && memchk(src+u)) {
- if (u && (dst >= src) && (dst < src+u)) {
- fprintf(stderr, "overlapping MOVE! %x %x %d\n", src, dst, u);
- ABORT_();
- return;
- }
- memmove(&vm.mem[dst], &vm.mem[src], u);
- }
-}
-
-static void MOVEWR() { // op: 4d
- dword u = ppop();
- ppush(here());
- allot(u);
- ppush(u);
- MOVE();
-}
-
-static void FINDMOD() { // op: 4e
- ppush(findmod(ppop()));
-}
-
-static void WNF() { // op: 4f
- write(STDOUT_FILENO, &vm.mem[CURWORD+1], vm.mem[CURWORD]);
- write(STDOUT_FILENO, " word not found", 15);
- vm.PC = abortaddr;
-}
-
-static void STACKCHK() { // op: 50
- if (vm.PSP > PSTOP) {
- write(STDOUT_FILENO, "stack underflow", 15);
- vm.PC = abortaddr;
- }
-}
-
-static void MAYBEWORD() { // op: 51
+static void MAYBEWORD() { // 0x30
dword c, a;
if ((a = gd(NEXTWORD))) {
sd(NEXTWORD, 0);
@@ -621,15 +256,15 @@ static void MAYBEWORD() { // op: 51
ppush(CURWORD);
}
-static void WORD() { // op: 52
+static void WORD() {
MAYBEWORD();
- if (!ppeek()) {
+ if (!vm.W) {
write(STDOUT_FILENO, "word expected", 13);
vm.PC = abortaddr;
}
}
-static void PARSE() { // op: 53
+static void PARSE() {
dword s = ppop();
byte len = gb(s++);
dword n = 0;
@@ -675,44 +310,29 @@ err:
ppush(0);
}
-// ( a1 a2 u -- f )
-static void REQ() { // op: 54
- dword u = ppop();
- dword a2 = ppop();
- dword a1 = ppop();
- if (memchk(a1+u) && memchk(a2+u)) {
- ppush(memcmp(&vm.mem[a1], &vm.mem[a2], u) == 0);
- }
-}
-
// ( name 'dict -- entry-or-0 )
-static void FIND() { // op: 55
+static void FIND() {
dword dict = ppop();
dword s = ppop();
byte len = gb(s++);
ppush(_find(dict, &vm.mem[s], len));
}
-static void APOS() { // op: 56
- WORD();
- ppush(sysdict());
- FIND();
- if (!ppeek()) WNF();
-}
-
-static void COMPILING() { // op: 57
- ppush(vm.compiling);
-}
-
-static void STARTCOMP() { // op: 59
- vm.compiling = 1;
+static void WNF() {
+ write(STDOUT_FILENO, &vm.mem[CURWORD+1], vm.mem[CURWORD]);
+ write(STDOUT_FILENO, " word not found", 15);
+ vm.PC = abortaddr;
}
+static void FINDMOD() { vm.W = findmod(vm.W); }
-static void STOPCOMP() { // op: 5a
- vm.compiling = 0;
+static void STACKCHK() { // 0x38
+ if (vm.PSP > PSTOP) {
+ write(STDOUT_FILENO, "stack underflow", 15);
+ vm.PC = abortaddr;
+ }
}
-static void COMPWORD() { // op: 5b
+static void COMPWORD() {
PARSE();
if (ppop()) {
litwr(ppop());
@@ -720,8 +340,8 @@ static void COMPWORD() { // op: 5b
ppush(CURWORD);
ppush(sysdict());
FIND();
- if (!ppeek()) { WNF(); return; }
- if ((gb(ppeek()-1) & 0x80) /* immediate */) {
+ if (!vm.W) { WNF(); return; }
+ if ((gb(vm.W-1) & 0x80) /* immediate */) {
callword(ppop());
STACKCHK();
} else {
@@ -729,7 +349,7 @@ static void COMPWORD() { // op: 5b
}
}
}
-static void RUNWORD() { // op: 5c
+static void RUNWORD() {
if (vm.compiling) {
COMPWORD();
} else {
@@ -738,331 +358,97 @@ static void RUNWORD() { // op: 5c
ppush(CURWORD);
ppush(sysdict());
FIND();
- if (!ppeek()) { WNF(); return; }
+ if (!vm.W) { WNF(); return; }
callword(ppop());
STACKCHK();
}
}
}
-
-static void USLEEP() { // op: 5d
- usleep(ppop());
-}
-
-/* Filesystem
-
-At POSIX level, we don't have access to the underlying FS structure such as
-inodes, making Dusk's 32-bit "ID" system a bit awkward. What we're going to do
-here is have a buffer of all requested paths, and the index in that buffer will
-be our ID.
-
-To simplify cursor management, we have a single IO buffer that we rotate our
-reads into.
-*/
-#define MAXPATHSZ 0x100
-#define FSIDCNT 0x200
-#define FILEPOSOFF 20
-#define FILEDESCOFF 44
-static char fsids[FSIDCNT][MAXPATHSZ] = {0};
-
-static dword findpath(char *path) {
- for (dword i=0; i<FSIDCNT; i++) {
- if (strcmp(path, fsids[i]) == 0) return i;
- }
- return 0;
-}
-
-// Return the "high" part of fd. On a 32-bit system, it's always zero. On a
-// 64-bit system, it's fd >> 32.
-static dword fdhi(int fd) {
- if (sizeof(int) > sizeof(dword)) {
- return (int64_t)fd >> 32;
- } else {
- return 0;
- }
+static void COMPILING() { ppush(vm.compiling); }
+static void STARTCOMP() { vm.compiling = 1; }
+static void STOPCOMP() { vm.compiling = 0; }
+// ( ?disp Woperand opcode -- )
+static void COMPOP() {
+ dword opcode = ppop();
+ dword operand = ppop();
+ dword disp = 0;
+ if (operand & OPDISP) disp = ppop();
+ wopwr(opcode, operand, disp);
}
-static int fdjoin(dword lo, dword hi) {
- if (sizeof(int) > sizeof(dword)) {
- return ((int64_t)hi<<32)|lo;
- } else {
- return lo;
- }
-}
-
-static int getfiledesc(dword hdl) {
- return fdjoin(gd(hdl+FILEDESCOFF), gd(hdl+FILEDESCOFF+4));
-}
-
-static char* getpathfromid(dword fsid) {
- if ((fsid >= FSIDCNT) || !fsids[fsid][0]) {
- printf("Out of bounds FSID %x\n", fsid);
- vm.PC = abortaddr;
- return NULL;
- }
- return fsids[fsid];
-}
-
-static char* pathcat(char *p1, dword s) {
- static char buf1[MAXPATHSZ] = {0};
- static char buf2[MAXPATHSZ] = {0};
- byte len = gb(s++);
- if (!memchk(s+len)) return NULL;
- strcpy(buf1, p1);
- strcat(buf1, "/");
- strncat(buf1, (char*)&vm.mem[s], len);
- if (!realpath(buf1, buf2)) return "/NoSuchFile";
- return buf2;
-}
-
-static dword _newfsid(char *path) {
- dword res = 0;
- while (fsids[++res][0]);
- strcpy(fsids[res], path);
- return res;
-}
-
-static void FCHILD () { // op: 60
- dword s = ppop();
- dword parent = ppop();
- char *path;
- dword res;
-
- path = pathcat(getpathfromid(parent), s);
- if (!path) return;
- res = findpath(path);
- if (!res) {
- // Verify if path actually exists in FS, then create a new ID
- struct stat sb;
- if (stat(path, &sb) != 0) { // does not exist
- ppush(0);
- return;
- }
- res = _newfsid(path);
- }
- ppush(res);
-}
-
-// Our handles are simply the regular IO/File preludes followed by the POSIX
-// file descriptor, a 64bit int.
-static void FOPEN () { // op: 61
- dword fsid = ppop();
- char *path;
- int fd;
- int filesize;
- path = getpathfromid(fsid);
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- printf("Can't open %s\n", path);
- vm.PC = abortaddr;
- return;
- }
- filesize = lseek(fd, 0, SEEK_END);
- lseek(fd, 0, SEEK_SET);
- ppush(here()); // File cursor we're about to create
- dwrite(0); // putback
- dwrite(find("_freadbuf"));
- dwrite(find("abort")); // writebuf
- dwrite(find("drop")); // flush
- dwrite(find("_fclose")); // close
- dwrite(0); // pos
- dwrite(filesize);
- dwrite(0); // bufptr, not used
- dwrite(0); // bufsz, not used
- dwrite(find("_fseek")); // seek
- dwrite(find("abort")); // truncate
- dwrite(fd);
- dwrite(fdhi(fd));
-}
-
-static void FREADBUF() { // op: 62
- dword hdl = ppop();
+static void ALIGN4() { // 0x40
dword n = ppop();
- int res;
- int fd = getfiledesc(hdl);
- if (!fd) {
- ppush(0);
- return;
- }
- if (n > IOBUFSZ) n = IOBUFSZ;
- res = read(fd, &vm.mem[IOBUF], n);
- if (res < 0) {
- printf("I/O readbuf error\n");
- vm.PC = abortaddr;
- return;
- }
- sd(hdl+FILEPOSOFF, lseek(fd, 0, SEEK_CUR));
- if (res) ppush(IOBUF);
- ppush((dword)res);
-}
-
-static void FCLOSE() { // op: 63
- dword hdl = ppop();
- int fd = getfiledesc(hdl);
- if (fd) {
- close(fd);
- sd(hdl+FILEDESCOFF, 0);
- sd(hdl+FILEDESCOFF+4, 0);
- }
-}
-
-// ( id -- info )
-static void FINFO() { // op: 64
- dword fsid = ppop();
- dword dst = find("_fsinfobuf");
- char *path = getpathfromid(fsid);
- char *name = basename(path);
- struct stat s;
- if (stat(path, &s) != 0) { // does not exist
- printf("Can't stat %s\n", path);
- vm.PC = abortaddr;
- return;
- }
- ppush(dst);
- sd(dst, dst+12); // where we'll put the name
- sd(dst+4, s.st_size);
- sd(dst+8, S_ISDIR(s.st_mode));
- sb(dst+12, strlen(name));
- memcpy(&vm.mem[dst+13], name, strlen(name));
-}
-
-static struct dirent* _next(DIR *dirp) {
- struct dirent *d;
- do {
- d = readdir(dirp);
- } while (d && ((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0)));
- return d;
-}
-
-// ( dirid previd -- id-or-0 )
-static void FITER() { // op: 65
- DIR *dirp;
- struct dirent *d;
- char path[MAXPATHSZ] = {0};
- int baselen;
- dword previd = ppop();
- dword dirid = ppop();
- dword curid = 0;
- int matched = 0;
- strcpy(path, getpathfromid(dirid));
- dirp = opendir(path);
- if (!dirp) {
- printf("Couldn't open dir %s\n", path);
- vm.PC = abortaddr;
- return;
- }
- strcat(path, "/");
- baselen = strlen(path);
- do {
- if (curid == previd) matched = 1;
- d = _next(dirp);
- if (d) {
- strcpy(&path[baselen], d->d_name);
- curid = findpath(path);
- if (!curid) curid = _newfsid(path);
- } else { curid = 0; }
- } while (curid && !matched);
- ppush(curid);
+ n = (here() + n) % 4;
+ if (n) { allot(4-n); }
}
-
-static void FSEEK() { // op: 67
- dword hdl = ppop();
- dword pos = ppop();
- int res;
- int fd = getfiledesc(hdl);
- if (!fd) {
- vm.PC = abortaddr;
- return;
- }
- res = lseek(fd, pos, SEEK_SET);
- if (res < 0) {
- printf("I/O lseek error\n");
- vm.PC = abortaddr;
- return;
- }
- sd(hdl+FILEPOSOFF, res);
+// ( 'dict s -- )
+static void ENTRY() {
+ dword s = ppop();
+ dword dict = ppop();
+ byte len = gb(s++);
+ ppush(len+1);
+ ALIGN4();
+ _entry(dict, &vm.mem[s], len);
}
-
-// ( imgname -- )
-static void MOUNTDRV() { // op: 68
- char buf[64] = {0};
- dword str = ppop();
- byte slen = gb(str++);
- memcpy(buf, &vm.mem[str], slen);
- if (fp) {
- fclose(fp);
- fp = NULL;
- }
- fp = fopen(buf, "r+");
- if (!fp) {
- printf("Can't open %s.\n", buf);
- BYEFAIL();
- }
+static void CODE() { ppush(sysdict()); WORD(); ENTRY(); }
+static void addmeta(dword id) {
+ dword a = gd(sysdict()-4);
+ sd(sysdict()-4, here());
+ dwrite(a); dwrite(id);
}
+static void CODE16() { addmeta(EMETA_16B); }
+static void CODE8() { addmeta(EMETA_8B); }
-// ( -- )
-static void UNMOUNTDRV() { // op: 69
- if (fp) {
- fclose(fp);
- fp = NULL;
- }
+static void ADD() { vm.W += pnip(); } // 0x48
+static void SUB() { vm.W = pnip() - vm.W; }
+static void MUL() { vm.W *= pnip(); }
+// ( a b -- r q )
+static void DIVMOD() { dword n = pnip(); ppush(n%vm.W); vm.W = n / vm.W; }
+static void LT() { vm.W = pnip() < vm.W; }
+
+static void AND() { vm.W &= pnip(); } // 0x50
+static void OR() { vm.W |= pnip(); }
+static void XOR() { vm.W ^= pnip(); }
+static void BOOL() { if (vm.W) vm.W = 1; }
+static void NOT() { vm.W = !vm.W; }
+
+static void BYE() { vm.PC = MEMSZ; } // 0x58
+static void BYEFAIL() { vmabort(); }
+static void QUIT() {
+ sd(MOD, 0);
+ vm.RSP = RSTOP;
+ vm.compiling = 0;
+ vm.PC = mainaddr;
}
-
-#define SECSZ 512
-// ( sec dst drv -- )
-static void DRVRD() { // op: 6a
- ppop();
- dword dst = ppop();
- dword sec = ppop();
- fseek(fp, SECSZ * sec, SEEK_SET);
- fread(&vm.mem[dst], SECSZ, 1, fp);
+static void ABORT_() {
+ vm.PSP = PSTOP;
+ sd(NEXTMETA, 0);
+ QUIT();
}
-
-// ( sec src drv -- )
-static void DRVWR() { // op: 6b
- ppop();
- dword src = ppop();
- dword sec = ppop();
- fseek(fp, SECSZ * sec, SEEK_SET);
- fwrite(&vm.mem[src], SECSZ, 1, fp);
+static void DBG() {
+ printf("W %08x A %08x PC %08x PSP %08x RSP %08x MOD %08x\n", vm.W, vm.A, vm.PC, vm.PSP, vm.RSP, gd(MOD));
}
-#define OPCNT 0x6c
+#define OPCNT 0x60
static void (*ops[OPCNT])() = {
- JUMP, CALL, RET, LIT, BYE, BYEFAIL, QUIT, ABORT_,
- EXECUTE, CELL, DOES, SLIT, BRWR, CBR, CBRWR, YIELD,
- PSADD, PSADDWR, NULL, NULL, BOOTRD, STDOUT, MAYBEKEY, FINDMETA,
- DUP, CDUP, SWAP, OVER, ROT, ROTR, NIP, TUCK,
- RSADD, RSADDWR, NULL, NULL, SCNT, RCNT, RSP2A, PSP2A,
- AFETCH, ASTORE, AADDSTORE, AFETCHSTORE, AINC, AIINC, AIFETCH, AISTORE,
- WRITE, SRD, SWR, SETBW, SETA, PUSHA, GETBW, LITA,
- INC, DEC, ADD, SUB, MUL, DIVMOD, AND, ALIGN4,
- OR, XOR, BOOL, NOT, LT, SHLC, SHRC, LSHIFT,
- RSHIFT, NULL, NULL, NULL, MOVE, MOVEWR, FINDMOD, WNF,
- STACKCHK, MAYBEWORD, WORD, PARSE, REQ, FIND, APOS, COMPILING,
- NULL, STARTCOMP, STOPCOMP, COMPWORD, RUNWORD, USLEEP, NULL, NULL,
- FCHILD, FOPEN, FREADBUF, FCLOSE, FINFO, FITER, NULL, FSEEK,
- MOUNTDRV, UNMOUNTDRV, DRVRD, DRVWR};
-
-static char *opnames[OPCNT] = {
- NULL, NULL, NULL, NULL, "bye", "byefail", "quit", "(abort)",
- "execute", "(cell)", "(does)", "(s)", "branch,", NULL, "?branch,", NULL,
- NULL, "p+,", NULL, NULL, "boot<", "(emit)", "(key?)", "findmeta",
- "dup", "?dup", "swap", "over", "rot", "rot>", "nip", "tuck",
- NULL, "r+,", NULL, NULL, "scnt", "rcnt", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- ",", "\"<", ",\"", NULL, NULL, NULL, NULL, NULL,
- "1+", "1-", "+", "-", "*", "/mod", "and", "align4",
- "or", "xor", "bool", "not", "<", "<<c", ">>c", "lshift",
- "rshift", NULL, NULL, NULL, "move", "move,", "findmod", "(wnf)",
- "stack?", "maybeword", "word", "parse", "[]=", "find", "'", "compiling",
- NULL, "]", "[", "compword", "runword", "_usleep", NULL, NULL,
- "_fchild", "_fopen", "_freadbuf", "_fclose", "_finfo", "_fiter", NULL, "_fseek",
- "_mountdrv", "_unmountdrv", "_drv@", "_drv!"};
+ BR, CALL, RET, EXECUTE, CBR, BRWR, BRZ, NULL,
+ PSADD, RSADD, WLIT, ALIT, WADD, AADD, W2A, WSWAPA,
+ WFETCH, WSTORE, WSWAP, MADDN, WLEA, WIFETCH, WISTORE, NULL,
+ WFETCH16, WSTORE16, WSWAP16, MADDN16, WLEA, WIFETCH16, WISTORE16, NULL,
+ WFETCH8, WSTORE8, WSWAP8, MADDN8, WLEA, WIFETCH8, WISTORE8, NULL,
+ BOOTRD, STDOUT, MAYBEKEY, NULL, NULL, NULL, NULL, NULL,
+ MAYBEWORD, WORD, PARSE, FIND, WNF, FINDMOD, NULL, NULL,
+ STACKCHK, COMPWORD, RUNWORD, COMPILING, STARTCOMP, STOPCOMP, COMPOP, NULL,
+ ALIGN4, ENTRY, CODE, CODE16, CODE8, NULL, NULL, NULL,
+ ADD, SUB, MUL, DIVMOD, LT, NULL, NULL, NULL,
+ AND, OR, XOR, BOOL, NOT, NULL, NULL, NULL,
+ BYE, BYEFAIL, QUIT, ABORT_, DBG, NULL, NULL, NULL,
+};
static void oprun1() { // run next op
if (!memchk(vm.PC)) return;
byte opcode = vm.mem[vm.PC++];
+ //printf("op %02x PC %08x PSP %08x RSP %08x\n", opcode, vm.PC-1, vm.PSP, vm.RSP);
if ((opcode >= OPCNT) || (!ops[opcode])) {
printf("Illegal opcode %02x at PC %08x\n", opcode, vm.PC-1);
BYEFAIL();
@@ -1084,55 +470,11 @@ static void callword(dword addr) {
}
}
-// Dictionary building
-static void opentry(byte op) {
- entry(opnames[op]);
- cwrite(op);
- retwr();
-}
-
-static void setbwwr(byte bw) { litwr(bw); cwrite(0x33); }
-
-// Make current entry "binary width" modulable
-static void makebw() {
- dword current = sysdict() + 5;
- dword a = here();
- dwrite(0); dwrite(0x10); // EMETA_8B
- setbwwr(2);
- jumpwr(current);
- sd(sysdict()-4, here());
- dwrite(a); dwrite(0x11); // EMETA_16B
- setbwwr(1);
- jumpwr(current);
-}
-static void makeimm(char *name) {
- dword a = find(name)-1;
- sb(a, gb(a)|0x80);
-}
-
-static void sysconst(char *name, dword val) {
- entry(name);
- litwr(val);
- retwr();
-}
-
-static void sysalias(char *name, char *target) {
- entry(name);
- jumpwr(find(target));
-}
-
-static void asetwr() { cwrite(0x34); }
-static void writewr() { cwrite(0x30); }
-
-static void compileop(byte op) {
- litwr(op);
- callwr(find("c,"));
-}
-static void keepbwwr() {
- cwrite(0x36); // GETBW
- callwr(find("litn"));
- compileop(0x33); // SETBW
-}
+static void wentry(char *name, byte op) { entry(name); cwrite(op); retwr(); }
+static void sysconst(char *name, dword val) { entry(name); litwr(val); retwr(); }
+static void sysalias(char *name, char *target) { entry(name); brwr(find(target)); }
+static void makeimm() { dword a = sysdict()+4; sb(a, gb(a)|0x80); }
+static void compileop(byte op) { litwr(op); cwritewr(); }
static void buildsysdict() {
sd(HERE, 0);
@@ -1141,44 +483,6 @@ static void buildsysdict() {
sd(MOD, 0);
sd(SYSDICT, 0);
sd(SYSDICT+4, 0); // set 0 len byte. See doc/impl
- entry("noop"); retwr();
- for (int i=0x04; i<OPCNT; i++) {
- if (ops[i] && opnames[i]) {
- opentry(i);
- if (i==0x30) makebw();
- }
- }
- entry("@"); asetwr(); cwrite(0x28); retwr(); makebw();
- entry("!"); asetwr(); cwrite(0x29); retwr(); makebw();
- entry("+!"); asetwr(); cwrite(0x2a); retwr(); makebw();
- entry("c@"); setbwwr(2); asetwr(); cwrite(0x28); retwr();
- entry("c!"); setbwwr(2); asetwr(); cwrite(0x29); retwr();
- entry("c,"); setbwwr(2); writewr(); retwr();
- entry("litn"); compileop(0x03); writewr(); retwr();
- entry("execute,"); compileop(0x01); writewr(); retwr();
- entry("exit,"); compileop(0x02); retwr();
- entry("yield"); compileop(0x0f); retwr();
- entry("RSP>A,"); compileop(0x26); retwr();
- entry("PSP>A,"); compileop(0x27); retwr();
- entry("A@,"); keepbwwr(); compileop(0x28); retwr(); makebw();
- entry("A!,"); keepbwwr(); compileop(0x29); retwr(); makebw();
- entry("A+!,"); keepbwwr(); compileop(0x2a); retwr(); makebw();
- entry("A@!,"); keepbwwr(); compileop(0x2b); retwr(); makebw();
- entry("A+,"); compileop(0x2c); writewr(); retwr();
- entry("[A]+,"); compileop(0x2d); writewr(); retwr();
- entry("[A]@,"); keepbwwr(); compileop(0x2e); retwr(); makebw();
- entry("[A]!,"); keepbwwr(); compileop(0x2f); retwr(); makebw();
- entry(">A,"); compileop(0x34); retwr();
- entry("A>,"); compileop(0x35); retwr();
- entry("LIT>A,"); compileop(0x37); writewr(); retwr();
- makeimm("[");
- makeimm("yield");
- sysalias("abort", "byefail");
- abortaddr = find("abort");
- sysalias("in<", "boot<");
- inrdaddr = find("in<");
- sysalias("rtype", "byefail");
- sysalias("branch!", "!");
sysconst("HERE", HERE);
sysconst("NEXTWORD", NEXTWORD);
sysconst("HEREMAX", HEREMAX);
@@ -1190,17 +494,70 @@ static void buildsysdict() {
sysconst("sysdict", SYSDICT);
sysconst("nextmeta", NEXTMETA);
sysconst("[rcnt]", _RCNT_);
- entry("_fsinfobuf"); allot(0x112); // used in FINFO
- entry("main");
+ wentry("boot<", 0x28); wentry("(emit)", 0x29);
+ wentry("word", 0x31); wentry("find", 0x33);
+ wentry("(wnf)", 0x34); wentry("findmod", 0x35);
+ wentry("compword", 0x39); wentry("runword", 0x3a); wentry("compiling", 0x3b);
+ wentry("]", 0x3c); wentry("[", 0x3d); makeimm();
+ wentry("align4", 0x40); wentry("entry", 0x41);
+ wentry("code", 0x42); wentry("code16b", 0x43); wentry("code8b", 0x44);
+ wentry("+", 0x48); wentry("-", 0x49); wentry("*", 0x4a); wentry("/mod", 0x4b);
+ wentry("<", 0x4c);
+ wentry("and", 0x50); wentry("or", 0x51); wentry("xor", 0x52);
+ wentry("bool", 0x53); wentry("not", 0x54);
+ wentry("bye", 0x58); wentry("byefail", 0x59);
+ wentry("quit", 0x5a); wentry("(abort)", 0x5b); wentry("dbg", 0x5c);
+ entry("ps+,"); compileop(0x08); writewr(); retwr();
+ entry("rs+,"); compileop(0x09); writewr(); retwr();
+ entry("LIT>W,"); compileop(0x0a); writewr(); retwr();
+ entry("LIT>A,"); compileop(0x0b); writewr(); retwr();
+ entry("W+,"); compileop(0x0c); writewr(); retwr();
+ entry("A+,"); compileop(0x0d); writewr(); retwr();
+ entry("W>A,"); compileop(0x0e); retwr();
+ entry("W<>A,"); compileop(0x0f); retwr();
+ entry("@,"); compopwr(0x10); retwr();
+ CODE16(); compopwr(0x18); retwr();
+ CODE8(); compopwr(0x20); retwr();
+ entry("!,"); compopwr(0x11); retwr();
+ CODE16(); compopwr(0x19); retwr();
+ CODE8(); compopwr(0x21); retwr();
+ entry("@!,"); compopwr(0x12); retwr();
+ CODE16(); compopwr(0x1a); retwr();
+ CODE8(); compopwr(0x22); retwr();
+ // ( n ?disp operand -- )
+ entry("[+],"); compopwr(0x13); writewr(); retwr();
+ CODE16(); compopwr(0x1b); writewr(); retwr();
+ CODE8(); compopwr(0x23); writewr(); retwr();
+ entry("lea,"); compopwr(0x14); retwr();
+ CODE16(); compopwr(0x1c); retwr();
+ CODE8(); compopwr(0x24); retwr();
+ entry("[@],"); compopwr(0x15); retwr();
+ CODE16(); compopwr(0x1d); retwr();
+ CODE8(); compopwr(0x25); retwr();
+ entry("[!],"); compopwr(0x16); retwr();
+ CODE16(); compopwr(0x1e); retwr();
+ CODE8(); compopwr(0x26); retwr();
+ entry("exit,"); compileop(0x02); retwr();
+ entry("execute,"); compileop(0x01); writewr(); retwr();
+ entry("execute"); cwrite(0x03); retwr();
+ entry("branch,"); litwr(0x00); cwrite(0x05); retwr();
+ entry("?branch,"); litwr(0x04); cwrite(0x05); retwr();
+ entry("branchz,"); litwr(0x06); cwrite(0x05); retwr();
+ entry("branch!"); storewr(); retwr();
+ entry(";"); compileop(0x02); cwrite(0x3d); retwr(); makeimm();
+ entry("16b"); litwr(EMETA_16B); alitwr(MOD); wstorewr(OPA, 0); dropwr(); retwr(); makeimm();
+ entry("8b"); litwr(EMETA_8B); alitwr(MOD); wstorewr(OPA, 0); dropwr(); retwr(); makeimm();
+ sysalias("in<", "boot<");
+ inrdaddr = find("in<");
mainaddr = here();
callwr(find("word"));
callwr(find("runword"));
- jumpwr(mainaddr);
+ brwr(mainaddr);
}
// Interpret loop
int main() {
- strcpy(fsids[0], "fs"); // Set FS root path
+ // strcpy(fsids[0], "fs"); // Set FS root path
fp = fopen("posix/boot.fs", "r");
if (!fp) {
printf("Can't open boot file.\n");
@@ -1210,7 +567,7 @@ int main() {
vm.PC = find("(abort)");
while (vm.PC < MEMSZ) oprun1();
if (fp) fclose(fp);
- if (vm.PC > MEMSZ) {
+ if (1 || (vm.PC > MEMSZ)) {
fprintf(stderr, "Dumping memory to memdump.\n");
FILE *fp = fopen("memdump", "w");
fwrite(vm.mem, MEMSZ, 1, fp);