duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 8194bdf05578dc66b765369179a59acc5ca62477
parent 8ba07a647b5a53edfab0cc524fca20271dd7ff93
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu, 23 Mar 2023 08:51:26 -0400

hal: add W*) A*) and A>) "high" operands

They should help with what's coming...

Diffstat:
Mfs/doc/hal.txt | 3+++
Mfs/tests/asm/hal.fs | 10++++++++++
Mposix/vm.c | 176++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
3 files changed, 116 insertions(+), 73 deletions(-)

diff --git a/fs/doc/hal.txt b/fs/doc/hal.txt @@ -62,6 +62,9 @@ The "high" layer of the HAL is provided by the assembler. Operand words: i) +W*) Direct W register operand +A*) Direct A register operand +A>) A reigter is the destination (instead of W) Branching and conditions: diff --git a/fs/tests/asm/hal.fs b/fs/tests/asm/hal.fs @@ -152,4 +152,14 @@ code test15 ( n n -- n ) PSP) <<, nip, exit, $42 4 test15 $420 #eq + +\ test W*), A*) and A>) +code test16 ( a b -- n ) \ a + b*b + PSP) A>) @, nip, + W*) *, + A*) +, + exit, + +4 5 test16 29 #eq + testend diff --git a/posix/vm.c b/posix/vm.c @@ -4,11 +4,15 @@ 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 5=immediate -b3 has disp? (type "memory" and "immediate" always have disp) -b7:4 number bank id -b8 16b? -b9 8b? +b2:0 type 0=W 1=A 2=PSP 3=RSP 4=memory 5=immediate +b3 has disp? (type "memory" and "immediate" always have disp) +b4 direct register mode (AREG, WREG)? +b5 A dst? +b7:6 unused +b8 16b? +b9 8b? +b11:10 unused +b15:12 number bank id Full HAL: Unlike regular kernels, this VM contains the full HAL because it has no assembler to complete the HAL to "full" level later. It's all in there. @@ -43,6 +47,10 @@ no assembler to complete the HAL to "full" level later. It's all in there. #define IOBUFSZ 0x200 #define IOBUF (HBANK-IOBUFSZ) +// Fake memory location to refer to the registers directly +#define WREG 0x8000000 +#define AREG 0x8000001 + #define OPW 0 #define OPA 1 #define OPPSP 2 @@ -50,6 +58,8 @@ no assembler to complete the HAL to "full" level later. It's all in there. #define OPMEM 4 #define OPIMM 5 #define OPHASDISP 0x08 +#define OPDIRECT 0x10 +#define OPADEST 0x20 #define OP16B 0x100 #define OP8B 0x200 // Condition structure: b6:0 condition ID b7 invert @@ -72,6 +82,7 @@ struct VM { dword PC; // when PC >= MEMSZ, machine is halted dword W; // W is PS top dword A; + dword *dst; byte Z; byte C; byte compiling; @@ -98,11 +109,25 @@ static dword memchk(dword a) { 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 gdr(dword addr) { + switch(addr) { + case WREG: return vm.W; + case AREG: return vm.A; + 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 sdr(dword addr, dword d) { + switch(addr) { + case WREG: vm.W = d; break; + case AREG: vm.A = d; break; + default: sd(addr, 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; } @@ -152,18 +177,18 @@ static void dwrite(dword d) { allot(4); } static dword hbankaddr(byte idx) { return HBANK+((idx%HBANKCNT)*4); } -static dword hbankget(dword operand) { return gd(hbankaddr((operand >> 4)&0xf)); } +static dword hbankget(dword operand) { return gd(hbankaddr((operand >> 12)&0xf)); } static dword hbankset(dword operand, dword val) { byte idx = (++vm.hbankidx) % HBANKCNT; sd(hbankaddr(idx), val); - return operand | (idx << 4); + return operand | (idx << 12); } static void retwr() { cwrite(0x02); } static void psaddwr(dword n) { cwrite(0x08); dwrite(n); } static void wopwr(byte opcode, dword operand) { opcode += (operand&(OP8B|OP16B)) >> 5; - cwrite(opcode); cwrite(operand&0xf); + cwrite(opcode); cwrite(operand); if (operand&OPHASDISP) dwrite(hbankget(operand)); } static void wfetchwr(dword op) { wopwr(0x10, op); } @@ -228,46 +253,51 @@ static void WSWAPA() { dword n = vm.A; vm.A = vm.W; vm.W = n; } static dword readop() { byte op = gpcb(); + vm.dst = &vm.W; dword addr = 0; - switch (op & 7) { + switch (op & 0x17) { case OPW: addr = vm.W; break; + case OPW|OPDIRECT: addr = WREG; break; case OPA: addr = vm.A; break; + case OPA|OPDIRECT: addr = AREG; break; case OPPSP: addr = vm.PSP; break; case OPRSP: addr = vm.RSP; break; case OPIMM: addr = vm.PC; vm.PC += 4; return addr; } if (op & OPHASDISP) addr += gpc(); + if (op & OPADEST) vm.dst = &vm.A; 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(); n += gd(a); sd(a, n); vm.Z = n == 0; } +#define GETA dword a = readop() +static void WFETCH() { GETA; *vm.dst = gdr(a); } // 0x10 +static void WSTORE() { GETA; sdr(a, *vm.dst); } +static void WSWAP() { GETA; dword n; n = gdr(a); sdr(a, *vm.dst); *vm.dst = n; } +static void MADDN() { GETA; dword n=gpc(); n += gdr(a); sdr(a, n); vm.Z = n == 0; } static void WCMP() { - dword n = gd(readop()); vm.Z = n == vm.W; vm.C = vm.W < n; } -static void WIFETCH() { vm.W = gd(gd(readop())); } -static void WISTORE() { sd(gd(readop()), vm.W); } -static void WADD() { vm.W += gd(readop()); vm.Z = vm.W == 0; } - -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(); n += gw(a); sw(a, n); vm.Z = (n&0xffff) == 0; } -static void WCMP16() { vm.Z = gw(readop()) == (vm.W & 0xffff); } -static void WIFETCH16() { vm.W = gw(gd(readop())); } -static void WISTORE16() { sw(gd(readop()), vm.W); } -static void WADD16() { vm.W += gw(readop()); vm.Z = vm.W == 0; } - -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(); n += gb(a); sb(a, n); vm.Z = (n&0xff) == 0; } -static void WCMP8() { vm.Z = gb(readop()) == (vm.W & 0xff); } -static void WIFETCH8() { vm.W = gb(gd(readop())); } -static void WISTORE8() { sb(gd(readop()), vm.W); } -static void WADD8() { vm.W += gb(readop()); vm.Z = vm.W == 0; } - -static void WLEA() { vm.W = readop(); } // 0x28 + GETA; dword n = gdr(a); vm.Z = n == *vm.dst; vm.C = *vm.dst < n; } +static void WIFETCH() { GETA; *vm.dst = gd(gdr(a)); } +static void WISTORE() { GETA; sdr(gdr(a), *vm.dst); } +static void WADD() { GETA; *vm.dst += gdr(a); vm.Z = *vm.dst == 0; } + +static void WFETCH16() { GETA; *vm.dst = gw(a); } // 0x18 +static void WSTORE16() { GETA; sw(a, *vm.dst); } +static void WSWAP16() { GETA; dword n; n = gw(a); sw(a, *vm.dst); *vm.dst = n; } +static void MADDN16() { GETA; dword n=gpc(); n += gw(a); sw(a, n); vm.Z = (n&0xffff) == 0; } +static void WCMP16() { GETA; vm.Z = gw(a) == (*vm.dst & 0xffff); } +static void WIFETCH16() { GETA; *vm.dst = gw(gdr(a)); } +static void WISTORE16() { GETA; sw(gdr(a), *vm.dst); } +static void WADD16() { GETA; *vm.dst += gw(a); vm.Z = *vm.dst == 0; } + +static void WFETCH8() { GETA; *vm.dst = gb(a); } // 0x20 +static void WSTORE8() { GETA; sb(a, *vm.dst); } +static void WSWAP8() { GETA; dword n; n = gb(a); sb(a, *vm.dst); *vm.dst = n; } +static void MADDN8() { GETA; dword n=gpc(); n += gb(a); sb(a, n); vm.Z = (n&0xff) == 0; } +static void WCMP8() { GETA; vm.Z = gb(a) == (*vm.dst & 0xff); } +static void WIFETCH8() { GETA; *vm.dst = gb(gdr(a)); } +static void WISTORE8() { GETA; sb(gdr(a), *vm.dst); } +static void WADD8() { GETA; *vm.dst += gb(a); vm.Z = *vm.dst == 0; } + +static void WLEA() { GETA; *vm.dst = a; } // 0x28 static void BOOTRD() { ppush(fgetc(fp)); } static void STDOUT() { dword c = ppop(); write(STDOUT_FILENO, &c, 1); } // ( -- c? f ) @@ -277,8 +307,6 @@ 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(OPHASDISP|OPMEM, vm.W); } // operand n -- operand @@ -492,38 +520,38 @@ static void WCHECKZ() { vm.Z = !vm.W; } static void STOREC() { vm.W = checkcond(gpcb()); } static void ACHECKZ() { vm.Z = !vm.A; } -static void WSUB() { vm.W -= gd(readop()); } // 0x68 -static void WMUL() { vm.W *= gd(readop()); } -static void WDIV() { vm.W /= gd(readop()); } -static void WMOD() { vm.W %= gd(readop()); } -static void WSHL() { vm.W <<= gd(readop()); } -static void WSHR() { vm.W >>= gd(readop()); } - -static void WSUB16() { vm.W -= gw(readop()); } // 0x70 -static void WMUL16() { vm.W *= gw(readop()); } -static void WDIV16() { vm.W /= gw(readop()); } -static void WMOD16() { vm.W %= gw(readop()); } -static void WSHL16() { vm.W <<= gw(readop()); } -static void WSHR16() { vm.W >>= gw(readop()); } - -static void WSUB8() { vm.W -= gb(readop()); } // 0x78 -static void WMUL8() { vm.W *= gb(readop()); } -static void WDIV8() { vm.W /= gb(readop()); } -static void WMOD8() { vm.W %= gb(readop()); } -static void WSHL8() { vm.W <<= gb(readop()); } -static void WSHR8() { vm.W >>= gb(readop()); } - -static void WAND() { vm.W &= gd(readop()); } // 0x80 -static void WOR() { vm.W |= gd(readop()); } -static void WXOR() { vm.W ^= gd(readop()); } - -static void WAND16() { vm.W &= gw(readop()); } // 0x88 -static void WOR16() { vm.W |= gw(readop()); } -static void WXOR16() { vm.W ^= gw(readop()); } - -static void WAND8() { vm.W &= gb(readop()); } // 0x90 -static void WOR8() { vm.W |= gb(readop()); } -static void WXOR8() { vm.W ^= gb(readop()); } +static void WSUB() { GETA; *vm.dst -= gdr(a); } // 0x68 +static void WMUL() { GETA; *vm.dst *= gdr(a); } +static void WDIV() { GETA; *vm.dst /= gdr(a); } +static void WMOD() { GETA; *vm.dst %= gdr(a); } +static void WSHL() { GETA; *vm.dst <<= gdr(a); } +static void WSHR() { GETA; *vm.dst >>= gdr(a); } + +static void WSUB16() { GETA; *vm.dst -= gw(a); } // 0x70 +static void WMUL16() { GETA; *vm.dst *= gw(a); } +static void WDIV16() { GETA; *vm.dst /= gw(a); } +static void WMOD16() { GETA; *vm.dst %= gw(a); } +static void WSHL16() { GETA; *vm.dst <<= gw(a); } +static void WSHR16() { GETA; *vm.dst >>= gw(a); } + +static void WSUB8() { GETA; *vm.dst -= gb(a); } // 0x78 +static void WMUL8() { GETA; *vm.dst *= gb(a); } +static void WDIV8() { GETA; *vm.dst /= gb(a); } +static void WMOD8() { GETA; *vm.dst %= gb(a); } +static void WSHL8() { GETA; *vm.dst <<= gb(a); } +static void WSHR8() { GETA; *vm.dst >>= gb(a); } + +static void WAND() { GETA; *vm.dst &= gdr(a); } // 0x80 +static void WOR() { GETA; *vm.dst |= gdr(a); } +static void WXOR() { GETA; *vm.dst ^= gdr(a); } + +static void WAND16() { GETA; *vm.dst &= gw(a); } // 0x88 +static void WOR16() { GETA; *vm.dst |= gw(a); } +static void WXOR16() { GETA; *vm.dst ^= gw(a); } + +static void WAND8() { GETA; *vm.dst &= gb(a); } // 0x90 +static void WOR8() { GETA; *vm.dst |= gb(a); } +static void WXOR8() { GETA; *vm.dst ^= gb(a); } /* Filesystem At POSIX level, we don't have access to the underlying FS structure such as @@ -809,7 +837,7 @@ 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, HBANKGET, MAKEMEM, ADDDISP, NULL, + WLEA, BOOTRD, STDOUT, MAYBEKEY, NULL, MAKEMEM, ADDDISP, NULL, MAYBEWORD, WORD, PARSE, FIND, WNF, FINDMOD, NULL, NULL, STACKCHK, COMPWORD, RUNWORD, COMPILING, STARTCOMP, STOPCOMP, RSADDWR, COMPOP, ALIGN4, ENTRY, CODE, CODE16, CODE8, NULL, NULL, NULL, @@ -859,7 +887,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?)", "@)", "m)", "+)", NULL, + NULL, "boot<", "(emit)", "(key?)", NULL, "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, @@ -897,6 +925,7 @@ static void buildsysdict() { sysconst("nextmeta", NEXTMETA); sysconst("[rcnt]", _RCNT_); sysconst("W)", OPW); sysconst("A)", OPA); + sysconst("W*)", OPW|OPDIRECT); sysconst("A*)", OPA|OPDIRECT); sysconst("PSP)", OPPSP); sysconst("RSP)", OPRSP); sysconst("Z)", CONDZ); sysconst("NZ)", CONDNZ); sysconst("C)", CONDC); sysconst("NC)", CONDNC); @@ -959,6 +988,7 @@ static void buildsysdict() { entry(">>n,"); callwr(find("i)")); callwr(find(">>,")); retwr(); entry("16b)"); litwr(OP16B); callwr(find("or")); retwr(); entry("8b)"); litwr(OP8B); callwr(find("or")); retwr(); + entry("A>)"); litwr(OPADEST); callwr(find("or")); retwr(); sysalias("in<", "boot<"); sysalias("rtype", "byefail"); sysalias("abort", "byefail");