duskos

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

commit f3d3cf2505e0eee11f05b6eb6eaa1b0a54b3f26b
parent 8194bdf05578dc66b765369179a59acc5ca62477
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu, 23 Mar 2023 17:23:16 -0400

halcc: consolidate

The upcoming part, array and advanced pointer arithmetics, is hairy and there's
lots of little things to get right. Among those was fixing a bug with 16b) and
8b) lea, which was broken in the POSIX vm.

Diffstat:
Mfs/comp/c/egen.fs | 6+++---
Mfs/comp/c/expr.fs | 45++++++++++++++++++++++++++-------------------
Mposix/vm.c | 11++++++-----
3 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/fs/comp/c/egen.fs b/fs/comp/c/egen.fs @@ -131,7 +131,7 @@ current ' parseFactor realias _prep +, ; \ ops that can't freely swap their operands -: _prep ( left right -- left halop ) Result :?>PS over Result :?>W ; +: _prep ( left right -- left halop ) Result :?>A over Result :?>W ; : _/, _prep /, ; : _%, _prep %, ; : _<<, _prep <<, ; : _>>, _prep >>, ; @@ -147,7 +147,7 @@ assign _&=, _&, assign _^=, _^, assign _|=, _|, assign _-=, _-, assign _/=, _/, assign _%=, _%, assign _<<=, _<<, assign _>>=, _>>, -: _=, swap dup Result :& Result :?>W$ W>A, dup Result :?>W A) !, ; +: _=, tuck Result :?>W Result :hal# !, ; \ To avoid W juggling, we check if our right operand is W. If it is, no need \ for juggling, all we need is to invert the condition we use. @@ -164,7 +164,7 @@ Z) Z) cmpop _==, NZ) NZ) cmpop _!=, \ the "true" hand, push it to PS, then generate the "cond", keep it in W. When \ we encounter the "false" hand, *then* we generate conditional code which \ cleans up PS. -: _?, ( left right -- res ) Result :>PS ; +: _?, ( left right -- res ) Result :?>W Result :?freeCurrentW ; : _:, ( left right -- res ) swap Result :>W$ PS- W=0>Z, 0 Z) branchC, drop, [compile] else nip, over Result :>W [compile] then ; diff --git a/fs/comp/c/expr.fs b/fs/comp/c/expr.fs @@ -6,6 +6,14 @@ : _err ( -- ) tokdbg abort" expr error" ; : _assert ( f -- ) not if _err then ; +\ Apply indirection level to halop. If necessary, use the A register to get to +\ the right place. +: applylvl ( halop lvl -- halop ) case ( halop ) + 0 of = endof + -1 of = A>) lea, A*) endof + of 0>= r@ for A>) @, A) next drop A) endof + _err endcase ; + struct[ Result 0 const NONE \ Nothing (probably a released W) 1 const CONST \ Is a constant (value in arg) @@ -14,10 +22,9 @@ struct[ Result 4 const PS \ Result pushed to PS, offset in arg sfield type sfield arg - sfield lvl \ indirection levels (*). This is different from CDecl lvl - \ because it track indirections at the *location* level. - \ Sometimes, when we need to know whether we're dealing with a - \ pointer or an actual value, we want to add these 2 levels. + sfield lvl \ indirection levels (*) that have been applied within the + \ expression (not at declaration). This is only used with CDECL + \ type. On the W type, * indirections are applied directly. \ There can only be one result using W at once. Whenever a W result is \ created, it takes the lock. If it's already taken, there's an error. @@ -34,14 +41,13 @@ struct[ Result : :release ( self -- ) dup :isW? if 0 to currentW then NONE swap to type ; : :hal# ( self -- halop ) dup type case ( self ) CONST of = arg i) endof - CDECL of = arg CDecl :halop endof + CDECL of = bi arg CDecl :halop | lvl applylvl endof PS of = arg PSP+) endof abort" :hal# error" endcase ; : :>W ( self -- ) - dup lvl over type W = if - W) else 1+ :Wfree# over :hal# then ( self lvl halop ) - begin swap ?dup while 1- dup if 1- swap [@], else swap @, then W) repeat - drop dup to currentW W swap to type ; + dup :isW? if drop else + :Wfree# dup :hal# @, + dup to currentW W swap to type then ; : :>W$ ( self -- ) dup :>W :release ; : :isconst? ( self -- f ) type CONST = ; : :iszero? bi arg 0 = | :isconst? and ; @@ -49,29 +55,30 @@ struct[ Result : :const# dup :isconst? _assert arg ; : :iscdecl? ( self -- f ) type CDECL = ; : :cdecl# dup :iscdecl? _assert arg ; - : :>PS dup :>W$ dup, PS+ PS over to type psoff neg swap to arg ; + : :>PS + dup :isW? _assert dup :release + dup, PS+ PS over to type psoff neg swap to arg ; : :?freeCurrentW ( -- ) currentW ?dup if :>PS then ; : :?>W dup :isW? if drop else :?freeCurrentW :>W then ; : :?>W$ dup :?>W :release ; - \ Free up W by sending it to PS (if needed). - : :?>PS ( self -- halop ) - dup :isW? if dup :release dup :>PS then :hal# ; - : :* ( self -- ) 1 swap to+ lvl ; - : :& ( self -- ) - dup lvl if -1 swap to+ lvl else - :?freeCurrentW dup :cdecl# CDecl :halop lea, W swap to type then ; + \ Free up W by sending it to A if needed. + : :?>A ( self -- halop ) + dup :isW? if dup :release W>A, A*) else :hal# then ; + : :* ( self -- ) + dup :isW? if W) @, else 1 swap to+ lvl then ; + : :& ( self -- ) -1 swap to+ lvl ; : :<<n ( n self -- ) dup :isconst? if dup arg rot lshift swap to arg else :?>W i) <<, then ; : :>>n ( n self -- ) dup :isconst? if dup arg rot rshift swap to arg else :?>W i) >>, then ; - : :totlvl bi :cdecl# CDecl lvl | lvl + ; + : :arilvl bi :cdecl# CDecl lvl | lvl - ; \ Return the "pointer arithmetics" multiplier to apply to the "other" operand. \ If we're a lvl 1 pointer, return the size of the underlying type, otherwise \ return 1. : :*arisz ( self -- n ) - dup :iscdecl? if dup :totlvl case + dup :iscdecl? if dup :arilvl case 0 of = drop 1 endof 1 of = :cdecl# CDecl type typesize endof drop 4 endcase else drop 1 then ; diff --git a/posix/vm.c b/posix/vm.c @@ -297,7 +297,7 @@ 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 +// 0x28 static void BOOTRD() { ppush(fgetc(fp)); } static void STDOUT() { dword c = ppop(); write(STDOUT_FILENO, &c, 1); } // ( -- c? f ) @@ -526,6 +526,7 @@ 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 WLEA() { GETA; *vm.dst = a; } static void WSUB16() { GETA; *vm.dst -= gw(a); } // 0x70 static void WMUL16() { GETA; *vm.dst *= gw(a); } @@ -845,9 +846,9 @@ static void (*ops[OPCNT])() = { BYE, BYEFAIL, QUIT, ABORT_, DBG, USLEEP, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, WCHECKZ, STOREC, ACHECKZ, - WSUB, WMUL, WDIV, WMOD, WSHL, WSHR, NULL, NULL, - WSUB16, WMUL16, WDIV16, WMOD16, WSHL16, WSHR16, NULL, NULL, - WSUB8, WMUL8, WDIV8, WMOD8, WSHL8, WSHR8, NULL, NULL, + WSUB, WMUL, WDIV, WMOD, WSHL, WSHR, WLEA, NULL, + WSUB16, WMUL16, WDIV16, WMOD16, WSHL16, WSHR16, WLEA, NULL, + WSUB8, WMUL8, WDIV8, WMOD8, WSHL8, WSHR8, WLEA, NULL, WAND, WOR, WXOR, NULL, NULL, NULL, NULL, NULL, WAND16, WOR16, WXOR16, NULL, NULL, NULL, NULL, NULL, WAND8, WOR8, WXOR8, NULL, NULL, NULL, NULL, NULL, @@ -957,10 +958,10 @@ static void buildsysdict() { entry("%,"); compopwr(0x6b); retwr(); entry("<<,"); compopwr(0x6c); retwr(); entry(">>,"); compopwr(0x6d); retwr(); + entry("lea,"); compopwr(0x6e); retwr(); entry("and,"); compopwr(0x80); retwr(); entry("or,"); compopwr(0x81); retwr(); entry("xor,"); compopwr(0x82); retwr(); - entry("lea,"); compopwr(0x28); retwr(); entry("neg,"); compileop(0x4e); retwr(); entry("W=0>Z,"); compileop(0x65); retwr(); entry("C>W,"); compileop(0x66); cwritewr(); retwr();