duskos

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

commit cdca6e1e444eaf821349faee056e759171f9edff
parent 4c7cc46d8197325c815e08cd6bdc0b06c52f15f6
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sat,  1 Apr 2023 14:20:39 -0400

hal: add &) operand modifier

Diffstat:
Mfs/comp/c/expr.fs | 6+++---
Mfs/doc/hal.txt | 24+++++++++++++++++++++---
Mfs/tests/asm/hal.fs | 16+++++++++++++---
Mposix/vm.c | 49+++++++++++++++++++++++++++++++++++--------------
4 files changed, 72 insertions(+), 23 deletions(-)

diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs @@ -75,12 +75,12 @@ struct[ Result CONST of = arg i) endof CDECL of = dup cdecl dup CDecl :halop ( self cdecl halop ) - swap CDecl :reference? if A>) lea, A*) then ( self halop ) + swap CDecl :reference? if A>) lea, A&) then ( self halop ) swap :nb) endof PS of = arg PSP+) endof - REF of = target :hal# A>) lea, A*) endof + REF of = target :hal# A>) lea, A&) endof DEREF of = - dup target dup :isW? if :release W*) else :hal# then ( self halop ) + dup target dup :isW? if :release W&) else :hal# then ( self halop ) A>) @, A) swap :nb) endof abort" :hal# error" endcase ; : :hal$ dup :hal# swap :release ; diff --git a/fs/doc/hal.txt b/fs/doc/hal.txt @@ -11,7 +11,7 @@ A) -- op PSP) -- op RSP) -- op m) addr -- op -+) op disp -- op ++) op disp -- op Can be applied multiple times Maximum displacement in Low HAL: 8-bit @@ -62,10 +62,11 @@ The "high" layer of the HAL is provided by the assembler. Operand words: i) -W*) Direct W register operand -A*) Direct A register operand +W&) Direct W register operand +A&) Direct A register operand A>) A register is the destination (instead of W) <>) Direction of the operation is inverted +&) Reference to operand (see below) Branching and conditions: @@ -88,3 +89,20 @@ Width-aware compiler words: %, op -- <<, op -- >>, op -- + +### &) operand modifier + +The &) word takes an input operand and returns its reference counterpart. For +example, m) becomes i), W) becomes W*), etc. This also works with displacements. +For example, "RSP) 4 +) &)" yields an operand that points to RSP+4. + +This operand might not be adressable directly by the host CPU. In that case, the +HAL operator will compile two instructions. For example, "RSP) 4 +) &) +," under +i386 would yield "bx sp 4 +) lea, ax bx add,". Only RSP) and PSP) can be +referenced with displacement. + +The "&)" word never writes instructions directly, only operator words. The +"lea," above wouldn't be written when "&)" is called, but when "+," is. + +If the &) word is called with an operand that can't be referenced, this word has +no effect. For example "W&) &)" is the same as "W&)". diff --git a/fs/tests/asm/hal.fs b/fs/tests/asm/hal.fs @@ -153,11 +153,11 @@ code test15 ( n n -- n ) nip, exit, $42 4 test15 $420 #eq -\ test W*), A*) and A>) +\ test W&), A&) and A>) code test16 ( a b -- n ) \ a + b*b PSP) A>) @, nip, - W*) *, - A*) +, + W&) *, + A&) +, exit, 4 5 test16 29 #eq @@ -169,4 +169,14 @@ code test17 ( n -- ) exit, 42 test17 foo @ $1234 42 + #eq + +\ test &). this returns item "idx" from PSP +code test18 ( ... idx -- n ) + 2 <<n, PSP) &) +, W) @, + exit, + +42 12 123 0 test18 123 #eq +1 test18 12 #eq +2 test18 42 #eq +2drop drop testend diff --git a/posix/vm.c b/posix/vm.c @@ -4,8 +4,8 @@ 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) +b2:0 type 0=W 1=A 2=PSP 3=RSP 4=memory/immediate +b3 has disp? (type "memory" always has disp) b4 direct register mode (AREG, WREG)? b5 A dst? b6 invert? @@ -51,13 +51,15 @@ no assembler to complete the HAL to "full" level later. It's all in there. // Fake memory location to refer to the registers directly #define WREG 0x8000000 #define AREG 0x8000001 +#define PSPREG 0x8000002 +#define RSPREG 0x8000003 +#define TREG 0x8000004 #define OPW 0 #define OPA 1 #define OPPSP 2 #define OPRSP 3 #define OPMEM 4 -#define OPIMM 5 #define OPHASDISP 0x08 #define OPDIRECT 0x10 #define OPADEST 0x20 @@ -88,6 +90,7 @@ struct VM { dword PC; // when PC >= MEMSZ, machine is halted dword W; // W is PS top dword A; + dword T; // tmp register. not directly addressable byte Z; byte C; byte SC; // signed C @@ -119,6 +122,9 @@ static dword gdr(dword addr) { switch(addr) { case WREG: return vm.W; case AREG: return vm.A; + case PSPREG: return vm.PSP; + case RSPREG: return vm.RSP; + case TREG: return vm.T; default: return gd(addr); } } @@ -131,6 +137,8 @@ static void sdr(dword addr, dword d) { switch(addr) { case WREG: vm.W = d; break; case AREG: vm.A = d; break; + case PSPREG: vm.PSP = d; break; + case RSPREG: vm.RSP = d; break; default: sd(addr, d); } } @@ -183,7 +191,8 @@ 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 >> 12)&0xf)); } +static dword hbankget(dword operand) { + return operand&OPHASDISP ? gd(hbankaddr((operand >> 12)&0xf)) : 0; } static dword hbankset(dword operand, dword val) { byte idx = (++vm.hbankidx) % HBANKCNT; sd(hbankaddr(idx), val); @@ -295,19 +304,27 @@ static void readop() { opdget = def_opdget; opdset = def_opdset; opsget = def_opsget; opsset = def_opsset; } - opdst = &vm.W; - opaddr = 0; + opdst = op & OPADEST ? &vm.A : &vm.W; switch (op & 0x17) { case OPW: opaddr = vm.W; break; case OPW|OPDIRECT: opaddr = WREG; break; case OPA: opaddr = vm.A; break; case OPA|OPDIRECT: opaddr = AREG; break; case OPPSP: opaddr = vm.PSP; break; + case OPPSP|OPDIRECT: opaddr = PSPREG; break; case OPRSP: opaddr = vm.RSP; break; - case OPIMM: opaddr = vm.PC; vm.PC += 4; return; + case OPRSP|OPDIRECT: opaddr = RSPREG; break; + case OPMEM: opaddr = gpc(); return; + case OPMEM|OPDIRECT: opaddr = vm.PC; vm.PC += 4; return; + default: + printf("Invalid HAL operand %x\n", op); + vmabort(); + } + if (op & OPHASDISP) { + if (op & OPDIRECT) { + vm.T = gdr(opaddr) + gpc(); opaddr = TREG; + } else { opaddr += gpc(); } } - if (op & OPHASDISP) opaddr += gpc(); - if (op & OPADEST) opdst = &vm.A; } static void _wfetch() { readop(); opdset(opsget()); } static void _wswap() { readop(); dword n; n = opsget(); opsset(opdget()); opdset(n); } @@ -355,7 +372,10 @@ static void MAYBEKEY() { static void MAKEMEM() { vm.W = hbankset(OPHASDISP|OPMEM, vm.W); } // operand n -- operand static void ADDDISP() { - dword by = ppop(); if (by) vm.W = hbankset(vm.W, by)|OPHASDISP; } + dword by = ppop(); if (by) { + vm.W = hbankset(vm.W, hbankget(vm.W)+by)|OPHASDISP; + } +} static void MAYBEWORD() { // 0x30 dword c, a; @@ -941,7 +961,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("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); @@ -990,20 +1010,21 @@ static void buildsysdict() { entry("branch!"); storewr(); retwr(); entry("yield"); compileop(0x07); retwr(); makeimm(); entry(";"); compileop(0x02); cwrite(0x3d); retwr(); makeimm(); - entry("i)"); callwr(find("m)")); cwrite(0x0c); /* W+n */ dwrite(1); retwr(); entry("*"); binopwr(0x02, OPPSP); nipwr(); retwr(); entry("and"); binopwr(0x08, OPPSP); nipwr(); retwr(); entry("or"); binopwr(0x09, OPPSP); nipwr(); retwr(); entry("xor"); binopwr(0x0a, OPPSP); nipwr(); retwr(); entry("lshift"); wopwr(0x12 /* @! */, OPPSP); binopwr(0x05, OPPSP); nipwr(); retwr(); entry("rshift"); wopwr(0x12 /* @! */, OPPSP); binopwr(0x06, OPPSP); nipwr(); retwr(); - entry("<<n,"); callwr(find("i)")); callwr(find("<<,")); retwr(); - 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(); entry("<>)"); litwr(OPINVERT); callwr(find("xor")); retwr(); + entry("&)"); litwr(OPDIRECT); callwr(find("or")); retwr(); + entry("i)"); callwr(find("m)")); callwr(find("&)")); retwr(); entry("!,"); callwr(find("<>)")); callwr(find("@,")); retwr(); + entry("<<n,"); callwr(find("i)")); callwr(find("<<,")); retwr(); + entry(">>n,"); callwr(find("i)")); callwr(find(">>,")); retwr(); entry("dup,"); litwr(0xfffffffc); callwr(find("ps+,")); callwr(find("PSP)")); callwr(find("!,")); retwr();