Paste: UM32
Author: | mrjbq7 |
Mode: | factor |
Date: | Mon, 19 May 2025 19:58:56 |
Plain Text |
USING: accessors alien.data alien.endian arrays command-line
formatting io io.encodings.binary io.files kernel
kernel.private math math.bitwise math.functions math.private
namespaces sequences sequences.private specialized-arrays
strings vectors ;
IN: um32
SPECIALIZED-ARRAY: ube32
TUPLE: UM32
{ error string }
{ clk fixnum }
{ r array }
{ mem vector }
{ freelist vector }
;
: <UM32> ( program -- um32 )
[ "" 0 { 0 0 0 0 0 0 0 0 0 } ] dip 1vector V{ } clone UM32 boa ;
: get-reg ( r vm -- i )
{ fixnum UM32 } declare r>> nth-unsafe { fixnum } declare ; inline
: set-reg ( i r vm -- )
{ fixnum UM32 } declare r>> set-nth-unsafe ;
: get-ip ( vm -- ip ) 8 swap get-reg ;
: set-ip ( ip vm -- ) 8 swap set-reg ;
: get-bank ( bank vm -- mem )
{ fixnum UM32 } declare mem>> nth { array } declare ; inline
: set-bank ( mem bank vm -- )
{ fixnum UM32 } declare mem>> set-nth ;
: get-mem ( addr bank vm -- i )
{ fixnum fixnum UM32 } declare get-bank nth { fixnum } declare ; inline
: set-mem ( i addr bank vm -- )
{ fixnum fixnum UM32 } declare get-bank set-nth ;
: halt-vm ( vm reason -- vm ) >>error ;
: check-ip ( vm -- vm )
8 over get-reg 0 pick get-bank length <
[ "IP out of bounds" halt-vm ] unless ;
: get-instruction ( addr vm -- instr )
{ fixnum UM32 } declare mem>> 0 swap nth-unsafe { array } declare nth-unsafe ; inline
: fetch ( vm -- vm instr )
dup get-ip [ over get-instruction ] [ 1 fixnum+fast pick set-ip ] bi ;
: decode-opcode ( instr -- opcode ) { fixnum } declare -28 shift 4 bits ; inline
: decode-a ( instr -- a ) { fixnum } declare -6 shift 3 bits ; inline
: decode-b ( instr -- b ) { fixnum } declare -3 shift 3 bits ; inline
: decode-c ( instr -- c ) { fixnum } declare 3 bits ; inline
: decode-abc ( instr -- a b c )
[ decode-a ] [ decode-b ] [ decode-c ] tri ; inline
: decode-ai ( instr -- a i )
{ fixnum } declare [ -25 shift 3 bits ] [ 25 bits ] bi ; inline
:: op-math ( vm instr quot -- vm )
instr decode-abc :> ( a b c )
b vm get-reg
c vm get-reg
quot call
a vm set-reg
vm ; inline
:: op-cmov ( vm instr -- vm )
instr decode-c vm get-reg zero? [
instr decode-b vm get-reg
instr decode-a vm set-reg
] unless vm ;
:: op-load ( vm instr -- vm )
instr decode-abc :> ( a b c )
c vm get-reg
b vm get-reg
vm get-mem
a vm set-reg
vm ;
:: op-store ( vm instr -- vm )
instr decode-abc :> ( a b c )
c vm get-reg
b vm get-reg
a vm get-reg
vm set-mem
vm ;
: op-add ( vm instr -- vm ) [ fixnum+fast 32 bits ] op-math ;
: op-mul ( vm instr -- vm ) [ fixnum*fast 32 bits ] op-math ;
: op-div ( vm instr -- vm ) [ fixnum/i-fast 32 bits ] op-math ;
: op-nand ( vm instr -- vm ) [ fixnum-bitand fixnum-bitnot 32 bits ] op-math ;
: op-halt ( vm instr -- vm ) drop "halted" halt-vm ;
: free-bank ( vm -- bankid )
{ UM32 } declare
dup freelist>> [ mem>> length ] [ nip pop ] if-empty ;
:: op-alloc ( vm instr -- vm )
instr decode-c vm get-reg 0 <array>
vm free-bank [ vm set-bank ] [ instr decode-b vm set-reg ] bi vm ;
:: op-free ( vm instr -- vm )
{ } instr decode-c vm get-reg [ vm set-bank ] [ vm freelist>> push ] bi vm ;
: op-out ( vm instr -- vm )
decode-c over get-reg write1 flush ;
: op-in ( vm instr -- vm )
decode-c read1 swap pick set-reg ;
:: op-exec ( vm instr -- vm )
instr decode-b vm get-reg [ vm get-bank clone 0 vm set-bank ] unless-zero
instr decode-c vm get-reg 8 vm set-reg vm ;
: op-literal ( vm instr -- vm )
decode-ai swap pick set-reg ;
: handle ( vm instr -- vm )
dup decode-opcode {
[ op-cmov ]
[ op-load ]
[ op-store ]
[ op-add ]
[ op-mul ]
[ op-div ]
[ op-nand ]
[ op-halt ]
[ op-alloc ]
[ op-free ]
[ op-out ]
[ op-in ]
[ op-exec ]
[ op-literal ]
[ drop "bad opcode" halt-vm ]
[ drop "bad opcode" halt-vm ]
} dispatch ;
: run-um32 ( program -- vm )
<UM32> [
fetch handle check-ip { UM32 } declare
[ 1 fixnum+fast ] change-clk dup error>> empty?
] loop ;
: run-um32-file ( filename -- vm )
binary file-contents ube32 cast-array { } like run-um32 ;
: um32-main ( -- )
command-line get first run-um32-file drop ;
MAIN: um32-main
New Annotation