duskos

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

commit 30eb221dc5d83a0d0c2cd806169c1345c157d17c
parent e21b0d58a2a6318211eeab557712c62f58bc206e
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sat, 17 Sep 2022 07:37:58 -0400

cc/vm: add "type" field

Its value is a cc/type. The replaces the "opsunsigned" flag and will help
having width-variable ops generation.

Diffstat:
Mfs/cc/gen.fs | 2+-
Mfs/cc/type.fs | 18+++++++++++-------
Mfs/cc/vm/commonhi.fs | 2+-
Mfs/cc/vm/commonlo.fs | 11++++++-----
Mfs/cc/vm/forth.fs | 11++++++-----
Mfs/cc/vm/i386.fs | 2+-
6 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs @@ -171,7 +171,7 @@ BOPSCNT wordtbl bopgentblpost ( -- ) 'w vm>>=, : decl>op ( dnode -- ) - dup Declare type typeunsigned? if opsunsigned! then ( dnode ) + dup Declare type to vmop type ( dnode ) case of Declare :isglobal? r@ Declare address mem>op endof of Declare :isarg? r@ Declare address ps+>op endof diff --git a/fs/cc/type.fs b/fs/cc/type.fs @@ -4,18 +4,22 @@ \ All information related to a basic type fits in a 32b integer, so that's \ how "type" is passed around. Structure: -\ b2:0 = size. 0=0 1=8 2=16 3=32 4+=reserved for future use -\ b3 = sign. 0=signed 1=unsigned -\ b6:4 = *lvl. Indirection levels, from 0 to 7. +\ b1:0 = size. 0=0 1=8 2=16 3=32 +\ b2 = sign. 0=signed 1=unsigned +\ b5:3 = *lvl. Indirection levels, from 0 to 7. -0 const TYPE_VOID -4 const TYPE_UINT +$0 const TYPE_VOID +$3 const TYPE_INT +$7 const TYPE_UINT 4 stringlist typenames "void" "char" "short" "int" : typeunsigned? ( type -- flags ) 2 rshift 1 and ; +: typesigned! ( type -- type ) $1b and ; +: typeunsigned! ( type -- type ) $4 or ; : type*lvl ( type -- lvl ) 3 rshift 3 and ; -: type*lvl! ( lvl type -- type ) $f and swap 3 lshift or ; -: type*lvl+ ( type -- type ) dup type*lvl 1+ swap type*lvl! ; +: type*lvl! ( lvl type -- type ) $1f and swap 3 lshift or ; +: type*lvl+ ( type -- type ) 8 + $1f and ; +: type*lvl- ( type -- type ) 8 - $1f and ; create _ 0 c, 1 c, 2 c, 4 c, : typesize ( type -- size-in-bytes ) dup type*lvl if drop 4 else 3 and _ + c@ then ; diff --git a/fs/cc/vm/commonhi.fs b/fs/cc/vm/commonhi.fs @@ -1,3 +1,3 @@ \ Code common to all VM implementations (high part) -: ops$ selop2 vmop :init selop1 vmop :init 0 to opsunsigned neutral# ; +: ops$ selop2 vmop :init selop1 vmop :init neutral# ; diff --git a/fs/cc/vm/commonlo.fs b/fs/cc/vm/commonlo.fs @@ -4,6 +4,7 @@ \ Loading another VM impl will break the previous one. In Dusk, it's not a \ problem because there is no CC cross-compiling. You'll always want to compile \ with one VM: your CPU's. +?f<< /cc/type.fs : _err abort" vm error" ; : _assert not if _err then ; @@ -28,14 +29,16 @@ $13 const VM_*ARGSFRAME $14 const VM_*REGISTER struct[ VMOp - sfield loc \ one of the VM_ constants + sfield loc \ one of the VM_ constants sfield arg + sfield type \ from cc/type sfield other \ link to the "other" op 4 &+ 'arg \ Initialize op to VM_NONE, "freeing" any resource it held. - : :init VM_NONE swap to loc ; + : :init VM_NONE over to loc TYPE_INT swap to type ; : :loclo loc $f and ; - : :deref? loc $10 and bool ; + \ Is op a pointer? + : :pointer? loc $10 and bool ; : :noop# loc VM_NONE = _assert ; : :keep ( self -- arg loc ) dup arg swap loc ; : :push ( self -- arg loc ) dup >r :keep VM_NONE to r> loc ; @@ -47,7 +50,6 @@ operands structbind VMOp vmop operands VMOp SZ + structbind VMOp vmop^ \ the "other" op vmop^ :self to vmop other vmop :self to vmop^ other -0 value opsunsigned \ when 1, ops are considered unsigned : _sel ['] vmop rebind vmop other ['] vmop^ rebind ; : selop1 ( -- ) operands _sel ; @@ -55,7 +57,6 @@ vmop :self to vmop^ other : selectedop ( -- n ) \ 0 == Op1 1 == Op2 vmop :self operands <> ; : selop^ vmop other _sel ; -: opsunsigned! 1 to opsunsigned ; : .ops selectedop .x1 spc> 4 >r operands begin @+ .x spc> next drop nl> ; diff --git a/fs/cc/vm/forth.fs b/fs/cc/vm/forth.fs @@ -44,7 +44,7 @@ struct+[ VMOp \ Resolve current operand and compile a push to PS as either VM_TOS or \ VM_*TOS. : :compile& >r - r@ :deref? if r@ :loclo r@ _ r> :>*TOS else r@ loc r@ _ r> :>TOS then ; + r@ :pointer? if r@ :loclo r@ _ r> :>*TOS else r@ loc r@ _ r> :>TOS then ; \ Resolve current operand and forces dereferencing. Always yields VM_TOS. : :compile ( -- ) >r r@ :compile& r@ loc VM_*TOS = if compile @ r@ :>TOS then rdrop ; @@ -54,7 +54,7 @@ struct+[ VMOp : neutral# psoff if abort" unbalanced PS" then ; \ transform current operand in its reference -: ?&op>op ( -- f ) vmop :deref? if vmop :loclo to vmop loc 1 else 0 then ; +: ?&op>op ( -- f ) vmop :pointer? if vmop :loclo to vmop loc 1 else 0 then ; : &op>op ?&op>op _assert ; : op>reg vmop :loclo VM_REGISTER = if exit then @@ -66,7 +66,7 @@ struct+[ VMOp : ?tos>reg _ selop^ _ selop^ ; \ dereference current operand -: *op>op vmop :deref? if +: *op>op vmop :pointer? if vmop :compile vmop :>*TOS op>reg else vmop loc $10 or to vmop loc then .ops ; @@ -156,8 +156,9 @@ postop vmop--, 1- : swapifTOS vmop :TOS? if compile swap then ; \ 2 fields: signed op, unsigned op -: binop doer ' , ' , does> opsunsigned if CELLSZ + then @ ( w ) - selop1 vmop :compile \ op1 is TOS +: binop doer ' , ' , does> ( 'w ) + selop1 vmop type typeunsigned? if CELLSZ + then @ ( w ) + vmop :compile \ op1 is TOS selop2 hasop# swapifTOS vmop :compile vmop :forgetTOS ( w ) execute, PS- selop1 ; \ result in op1 as VM_TOS diff --git a/fs/cc/vm/i386.fs b/fs/cc/vm/i386.fs @@ -258,7 +258,7 @@ struct+[ VMOp : _ selop1 op>reg opAsm selop2 opAsm cmp, vmop :init selop1 opAsm 0 i) mov, ; -: vm<, _ opAsm opsunsigned if setb, else setl, then ; +: vm<, _ opAsm vmop type typeunsigned? if setb, else setl, then ; : vm==, _ opAsm setz, ; : _ ( 'w -- ) selop1 opAsm selop2 opAsm execute vmop :init selop1 vmboolify, ; : vm&&, ['] and, _ ;