commit 82d1ab78f30379c0e65f53af7082f4101ed3f78b
parent 8ac0e4809eb5a9ea59ced26f637dff26aa123bb1
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sun, 12 Mar 2023 21:03:05 -0400
hal: make operands arch-specific and opaque
Words creating and changing HAL operands are now defined in arch-specific
kernel code. The previous HAL operand scheme showed problems when came the time
to harmonize with the assembler. The goal here is to have the assembler
"naturally" extend the HAL defined in the kernel. This can't be done with a
"universal" HAL operand structure. Arches are bound to have different ways to
fit all that information in 32-bit.
Diffstat:
M | fs/xcomp/bootlo.fs | | | 7 | ++----- |
M | posix/dis.c | | | 74 | +++++++++++++++++++++++++++++++++++++++++--------------------------------- |
M | posix/vm.c | | | 79 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
3 files changed, 99 insertions(+), 61 deletions(-)
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -2,15 +2,12 @@ code : ] code ] ;
: :8b code8b ] ;
: :16b code16b ] ;
: noop ;
-: W) 0 ; : A) 1 ; : PSP) 2 ; : RSP) 3 ;
: Z) $11 ; : NZ) $01 ; : C) $22 ; : NC) $02 ;
: dup, -4 ps+, PSP) !, ;
code dup dup, exit,
code swap PSP) @!, exit,
code << 1 <<n, exit,
code >> 1 >>n, exit,
-: i) $80000000 or ;
-: +) $1fffffff and << << or ;
: drop, PSP) @, 4 ps+, ;
code drop drop, exit,
: 2drop, PSP) 4 +) @, 8 ps+, ;
@@ -24,7 +21,7 @@ code over over, exit,
code tuck W>A, PSP) @, dup, W<>A, PSP) 4 +) !, exit,
code 2dup W>A, PSP) @, -8 ps+, PSP) !, W<>A, PSP) 4 +) !, exit,
-code immediate dup, sysdict i) @, 4 W+n, W>A, A) @, $80 orn, A) !, drop, exit,
+code immediate dup, sysdict m) @, 4 W+n, W>A, A) @, $80 orn, A) !, drop, exit,
: EMETA_16B $11 ; : EMETA_8B $10 ;
code 16b dup, MOD LIT>A, EMETA_16B LIT>W, A) !, drop, exit, immediate
code 8b dup, MOD LIT>A, EMETA_8B LIT>W, A) !, drop, exit, immediate
@@ -168,7 +165,7 @@ _to to@+ @@+ _@@+,
_to to!+ @!+ _@!+,
: _lea, dup, lea, ; :16b dup, lea, ; :8b dup, lea, ;
_to to' noop _lea,
-: _toexec ( a -- ) compiling if i) then toptr@ execute ;
+: _toexec ( a -- ) compiling if m) then toptr@ execute ;
: value doer , immediate does> _toexec ;
: here HERE _toexec ; immediate
: alias ' code branch, drop ;
diff --git a/posix/dis.c b/posix/dis.c
@@ -12,8 +12,10 @@ as the ones compiled by the Forth backend of CC.
#define ARGBYTE 1
#define ARGINT 2
#define ARGFIVE 3 // byte + int
-#define ARGEIGHT 4 // 2x int
-#define ARGERR 5 // can't continue, arg size unknown
+#define ARGOP 4 // byte + ?disp
+#define ARGOPN 5 // op + immediate
+#define ARGERR 6 // can't continue, arg size unknown
+#define OPHASDISP 0x08
struct op {
char *name; // NULL= no op
@@ -40,34 +42,34 @@ static struct op ops[OPCNT] = {
{"W2A", ARGNONE},
{"WSWAPA", ARGNONE},
- {"WFETCH", ARGINT},
- {"WSTORE", ARGINT},
- {"WSWAP", ARGINT},
- {"MADDN", ARGEIGHT},
- {"WCMP", ARGINT},
- {"WIFETCH", ARGINT},
- {"WISTORE", ARGINT},
- {"WADD", ARGINT},
-
- {"WFETCH16", ARGINT},
- {"WSTORE16", ARGINT},
- {"WSWAP16", ARGINT},
- {"MADDN16", ARGEIGHT},
- {"WCMP16", ARGINT},
- {"WIFETCH16", ARGINT},
- {"WISTORE16", ARGINT},
- {"WADD16", ARGINT},
-
- {"WFETCH8", ARGINT},
- {"WSTORE8", ARGINT},
- {"WSWAP8", ARGINT},
- {"MADDN8", ARGEIGHT},
- {"WCMP8", ARGINT},
- {"WIFETCH8", ARGINT},
- {"WISTORE8", ARGINT},
- {"WADD8", ARGINT},
-
- {"WLEA", ARGINT},
+ {"WFETCH", ARGOP},
+ {"WSTORE", ARGOP},
+ {"WSWAP", ARGOP},
+ {"MADDN", ARGOPN},
+ {"WCMP", ARGOP},
+ {"WIFETCH", ARGOP},
+ {"WISTORE", ARGOP},
+ {"WADD", ARGOP},
+
+ {"WFETCH16", ARGOP},
+ {"WSTORE16", ARGOP},
+ {"WSWAP16", ARGOP},
+ {"MADDN16", ARGOPN},
+ {"WCMP16", ARGOP},
+ {"WIFETCH16", ARGOP},
+ {"WISTORE16", ARGOP},
+ {"WADD16", ARGOP},
+
+ {"WFETCH8", ARGOP},
+ {"WSTORE8", ARGOP},
+ {"WSWAP8", ARGOP},
+ {"MADDN8", ARGOPN},
+ {"WCMP8", ARGOP},
+ {"WIFETCH8", ARGOP},
+ {"WISTORE8", ARGOP},
+ {"WADD8", ARGOP},
+
+ {"WLEA", ARGOP},
{"BOOTRD", ARGNONE},
{"STDOUT", ARGNONE},
{"MAYBEKEY", ARGNONE},
@@ -165,7 +167,7 @@ struct call {
char *name;
};
-#define CALLCNT 5
+#define CALLCNT 8
struct call calls[CALLCNT] = {
{0x2e8, "-"},
{0x1760, "dup"},
@@ -205,8 +207,14 @@ int printarg(int arg) { // returns 1 on success, 0 on error
printarg(ARGBYTE);
printarg(ARGINT);
break;
- case ARGEIGHT:
- printarg(ARGINT);
+ case ARGOP:
+ n = getchar();
+ offset++;
+ printf("\t%x", n);
+ if (n&OPHASDISP) printarg(ARGINT);
+ break;
+ case ARGOPN:
+ printarg(ARGOP);
printarg(ARGINT);
break;
case ARGERR:
diff --git a/posix/vm.c b/posix/vm.c
@@ -1,3 +1,13 @@
+/* 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.
+
+HAL argument structure:
+b2:0 type 0=W 1=A 2=PSP 3=RSP 4=memory
+b3 has disp? (type "memory" always has disp)
+b7:4 number bank id
+*/
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
@@ -22,14 +32,18 @@
#define NEXTWORD (_RCNT_+4)
#define MOD (NEXTWORD+4)
#define CURWORD (MOD+4)
+#define HBANKCNT 0x10
+#define HBANKSZ (HBANKCNT*4)
+#define HBANK (SYSVARS-HBANKSZ)
#define IOBUFSZ 0x200
-#define IOBUF (SYSVARS-IOBUFSZ)
+#define IOBUF (HBANK-IOBUFSZ)
#define OPW 0
#define OPA 1
#define OPPSP 2
#define OPRSP 3
-#define OPIMM 0x80000000
+#define OPMEM 0xc
+#define OPHASDISP 0x08
#define CONDZ 0x01
#define CONDNZ 0x11
#define EMETA_8B 0x10
@@ -48,6 +62,7 @@ struct VM {
byte Z;
byte C;
byte compiling;
+ byte hbankidx;
byte mem[MEMSZ];
};
@@ -123,15 +138,24 @@ static void dwrite(dword d) {
sd(here(), d);
allot(4);
}
+static dword hbankaddr(byte idx) { return HBANK+((idx%HBANKCNT)*4); }
+static dword hbankget(byte operand) { return gd(hbankaddr(operand >> 4)); }
+static byte hbankset(byte operand, dword val) {
+ byte idx = (++vm.hbankidx) % HBANKCNT;
+ sd(hbankaddr(idx), val);
+ return operand | (idx << 4);
+}
static void retwr() { cwrite(0x02); }
static void psaddwr(dword n) { cwrite(0x08); dwrite(n); }
-static void wopwr(byte opcode, dword operand) { cwrite(opcode); dwrite(operand); }
-static void wfetchwr(dword op) { wopwr(0x10, op); }
-static void wstorewr(dword op) { wopwr(0x11, op); }
-static void maddnwr(dword op, dword n) { wopwr(0x13, op); dwrite(n); }
-static void wistorewr(dword op) { wopwr(0x16, op); }
-static void wistorewr8(dword op) { wopwr(0x26, op); }
+static void wopwr(byte opcode, byte operand) {
+ cwrite(opcode); cwrite(operand&0xf);
+ if (operand&OPHASDISP) dwrite(hbankget(operand)); }
+static void wfetchwr(byte op) { wopwr(0x10, op); }
+static void wstorewr(byte op) { wopwr(0x11, op); }
+static void maddnwr(byte op, dword n) { wopwr(0x13, op); dwrite(n); }
+static void wistorewr(byte op) { wopwr(0x16, op); }
+static void wistorewr8(byte op) { wopwr(0x26, op); }
static void dupwr() { psaddwr(0xfffffffc); wstorewr(OPPSP); }
static void nipwr() { psaddwr(4); }
static void dropwr() { wfetchwr(OPPSP); nipwr(); }
@@ -142,7 +166,7 @@ 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); maddnwr(OPA, 4); dropwr(); }
static void cwritewr() { alitwr(HERE); wistorewr8(OPA); maddnwr(OPA, 1); dropwr(); }
-static void compopwr(byte opcode) { litwr(opcode); cwritewr(); writewr(); }
+static void compopwr(byte opcode) { litwr(opcode); cwrite(0x3f); }
static void storewr() { cwrite(0x0e); dropwr(); wstorewr(OPA); dropwr(); }
static void callword(dword addr); // forward declaration
@@ -186,18 +210,16 @@ static void W2A() { vm.A = vm.W; }
static void WSWAPA() { dword n = vm.A; vm.A = vm.W; vm.W = n; }
static dword readop() {
- dword op = gpc();
- dword disp;
- if (op & OPIMM) { return op & 0x7fffffff; }
- disp = op >> 2;
- if (op & 0x10000000) /* sign extend */ op |= 0xe0000000;
- switch (op & 3) {
- case OPW: return vm.W + disp;
- case OPA: return vm.A + disp;
- case OPPSP: return vm.PSP + disp;
- case OPRSP: return vm.RSP + disp;
+ byte op = gpcb();
+ dword addr = 0;
+ 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;
}
- return 0;
+ if (op & OPHASDISP) addr += gpc();
+ return addr;
}
static void WFETCH() { vm.W = gd(readop()); } // 0x10
static void WSTORE() { sd(readop(), vm.W); }
@@ -236,6 +258,12 @@ static void MAYBEKEY() {
ppush(c); ppush(1);
} else { ppush(0); }
}
+// operand -- n
+static void HBANKGET() { vm.W = hbankget(vm.W); }
+// n -- operand
+static void MAKEMEM() { vm.W = hbankset(OPMEM, vm.W); }
+// operand n -- operand
+static void ADDDISP() { dword by = ppop(); vm.W = hbankset(vm.W, by)|OPHASDISP; }
static void MAYBEWORD() { // 0x30
dword c, a;
@@ -381,6 +409,9 @@ static void RSADDWR() {
dwrite(n);
sd(_RCNT_, gd(_RCNT_)+n);
}
+// ( operand opcode -- )
+static void COMPOP() {
+ dword opcode = ppop(); dword operand = ppop(); wopwr(opcode, operand); }
static void ALIGN4() { // 0x40
dword n = ppop();
@@ -736,9 +767,9 @@ static void (*ops[OPCNT])() = {
WFETCH, WSTORE, WSWAP, MADDN, WCMP, WIFETCH, WISTORE, WADD,
WFETCH16, WSTORE16, WSWAP16, MADDN16, WCMP16, WIFETCH16, WISTORE16, WADD16,
WFETCH8, WSTORE8, WSWAP8, MADDN8, WCMP8, WIFETCH8, WISTORE8, WADD8,
- WLEA, BOOTRD, STDOUT, MAYBEKEY, NULL, NULL, NULL, NULL,
+ WLEA, BOOTRD, STDOUT, MAYBEKEY, HBANKGET, MAKEMEM, ADDDISP, NULL,
MAYBEWORD, WORD, PARSE, FIND, WNF, FINDMOD, NULL, NULL,
- STACKCHK, COMPWORD, RUNWORD, COMPILING, STARTCOMP, STOPCOMP, RSADDWR, NULL,
+ STACKCHK, COMPWORD, RUNWORD, COMPILING, STARTCOMP, STOPCOMP, RSADDWR, COMPOP,
ALIGN4, ENTRY, CODE, CODE16, CODE8, NULL, NULL, NULL,
SUB, MUL, DIVMOD, LSHIFT, RSHIFT, LT, NULL, NULL,
AND, OR, XOR, NULL, NULL, NULL, NULL, NULL,
@@ -780,7 +811,7 @@ static void compileop(byte op) { litwr(op); cwritewr(); }
// Names for simple word-to-code mappings
static char *opnames[OPCNT-0x28] = {
- NULL, "boot<", "(emit)", "(key?)", NULL, NULL, NULL, NULL,
+ NULL, "boot<", "(emit)", "(key?)", "@)", "m)", "+)", NULL,
"maybeword", "word", "parse", "find", "(wnf)", "findmod", NULL, NULL,
"stack?", "compword", "runword", "compiling", "]", NULL, "rs+,", NULL,
"align4", "entry", "code", "code16b", "code8b", NULL, NULL, NULL,
@@ -812,6 +843,8 @@ static void buildsysdict() {
sysconst("sysdict", SYSDICT);
sysconst("nextmeta", NEXTMETA);
sysconst("[rcnt]", _RCNT_);
+ sysconst("W)", OPW); sysconst("A)", OPA);
+ sysconst("PSP)", OPPSP); sysconst("RSP)", OPRSP);
for (int i=0; i<OPCNT-0x28; i++) {
if (opnames[i]) wentry(opnames[i], i+0x28);
}