Chine
small stack machine
Install / Use
/learn @tonyrog/ChineREADME
CHINE, a pretty compact opcode scheme
Chine is a byte code machine. The chine machine and its byte code is easy to port to a number of architectures.
INSTRUCTIONS op3/op6
stack effect diagram works like before -- after the right most element is top of the stack so in rot ( a b c -- b c a ) then c is top of the stack before rot and a is top of stack after rot
| opname | stack effect | comment | |-----------|----------------------|---------------| | dup | ( a -- a a ) | | rot | ( a b c -- b c a ) | rotate down | | over | ( a b -- a b a ) | | drop | ( a -- ) | | swap | ( a b -- b a ) | | - | ( a b -- [ a-b ] ) | | + | ( x1 x2 -- [ x1+x2 ] ) | | * | ( x1 x2 -- [ x1x2 ] ) | | nop | ( -- ) | | and | ( a b -- [ a&b ] ) | or | ( a b -- [ a|b ] ) | xor | ( a b -- [ a^b ] ) | 0= | ( a -- [ a==0 ] ) | true = -1 | 0< | ( a -- [ a<0 ] ) | true = -1 | not | ( a -- [ ~a ] ) | negate | ( a -- [ -a ] ) | | / | ( a b -- [ a/b ] ) | | shift | ( a n -- [ (uint)a << n OR (int)a >> -n ] ) | | ! | ( n i -- ) | mem[i] = n | | @ | ( i -- n ) | n = mem[i] | | >r | ( n -- ) R: ( -- n ) | r> | R: ( n -- ) ( -- n ) | r@ | R: ( n -- n ) ( -- n ) | sys u:8 | ( x1 .. xn -- v f ) | | exit | ; ( -- ) R: ( addr -- ) | | yield | ( -- ) | | [] | ( caddr i -- n ) | data access via index | execute | ( caddr -- ) | | fp@ | ( -- fp ) | fetch frame pointer | fp! | ( fp -- ) | set frame pointer | sp@ | ( -- sp ) | fetch stack pointer | sp! | ( sp -- ) | set stack pointer | c! | ( n i -- ) | ((byte)mem)[i] = n | | c@ | ( i -- n ) | n = ((byte*)mem)[i] | | size | ( caddr -- n ) | number of array elements |
INSTRUCTIONS jop
| opname | stack effect | comment | |-----------|---------------------|--------------------| | jmpz | ( f -- ) | top==0 | | jmpnz | ( f -- ) | top!=0 | | next | ( -- ) | rtop>=0 | | jmplz | ( f -- ) | top<0 | | jmp | ( -- ) | | | call | ( -- ) | | | literal | ( -- n ) | | | get <i> | ( -- a ) | a = frame[i] | | array <n> | ( -- caddr ) | | | enter | ( a b c -- ) | set new fp | | leave | ( a b c -- a b c ) | restore old frame | | set <i> | ( a -- ) | frame[i]=a |
compiler built-ins min,max,abs ...
: 1+ 1 + ;
: 1- 1 - ;
: lshift shift ;
: rshift negate shift ;
: < - 0< ;
: > swap - 0< ;
: <= - 0<= ;
: >= swap - 0<= ;
: = - 0= ;
: 2dup over over ;
: 2drop drop drop ;
: u< 2dup xor 0<
if swap drop 0< else - 0< then ;
: u<= 2dup xor 0<
if swap drop 0< else - 0<= then ;
: u> swap u< ;
: u>= swap u<= ;
: 0<> 0= not ;
: 0> 0 > ;
: 0<= 1- 0< ;
: abs ( a -- [ |a| ] )
dup 0< if negate then ;
: min ( a b -- [ min(a,b) ] )
2dup < if drop else swap drop then ;
: max ( a b -- [ max(a,b) ]
2dup < if swap drop else drop then ;
: nip swap drop ;
: tuck swap over ;
: -rot rot rot ;
: arshift dup 32 swap -
-1 swap shift -rot negate shift or ;
: 2* dup + ;
: 2/ 1 arshift ;
: sqr dup * ;
: mod 2dup / * - ;
: jmp* >r exit ;
: SEMI exit ;
: setbit ( fld n -- [ fld or (1 << n) ] )
1 swap lshift or ;
: clrbit ( fld n -- [ fld and ~(1 << n) ] )
1 swap lshift invert and ;
: togglebit ( fld n -- [ fld xor (1 << n) ] )
1 swap lshift xor ;
: tstbit ( fld n -- [ fld and (1 << n) ] )
1 swap lshift and ;
: setclrbit ( fld n f -- [ if (f) setbit els clrbit ] )
if setbit else clrbit then ;
: jmp* ( caddr -- ) >r exit ;
non branch alternatives ( mostly for fun )
: min ( a b -- [ min(a,b) ]
over over over over ( a b -- a b a b a b )
- 0< ( a b a b [ sign(a - b) ] )
-rot ( a b [ sign(a - b) ] a b )
xor ( a b [ sign(a - b) ] [ a xor b ] )
and ( a b [ sign(a - b) and (a xor b) ] )
xor ( a [ b xor ( sign(a-b) and (a xor b) ) ] )
swap drop ; ( [ b xor ( sign(a-b) and (a xor b) ) ] )
: abs ( a -- [ |a| ] )
dup 0< ( a f )
dup ( a f f )
rot swap ( f a f )
negate xor ( f [ a xor -f ] )
+ ( [ f + (a xor -f) ] )
;
: setclrbit ( w n f -- [ if (f) w |= m; else w &= ~m end ] )
negate ( w n -f )
swap 1 swap lshift ( w -f m )
rot ( -f m w )
rot ( m w -f )
over ( m w -f w )
xor ( m w [-f xor w] )
rot ( w [-f xor w] m )
and ( w [ ((-f xor w) and m ) ] )
xor ( [ w xor ((-f xor w) and m ) ] )
;
System calls
Stack effects are written as ( before -- after ) where stacks are describes as " last ... 2nd top " that is top is to the right, the order it is typed in.
| Name | Stack effect |Comment| |-----------------|------------------|-------| | now | ( -- u ) | ms sinc system start | | emit | ( c -- ) | | | recv | ( -- c ) | | | avail | ( -- f ) | | | param@ | ( i si -- v ) | | | param! | ( i si v -- ) | | | timer_init | ( i -- ) | | | timer_start | ( i -- ) | | | timer_stop | ( i -- ) | | | timer_timeout | ( i -- ) | | | timer_running | ( i -- flag ) | | | input@ | ( i k -- v ) | | | select_timer | ( i -- ) | | | deselect_timer | ( i -- ) | | | select_input | ( i -- ) | | | dselect_input | ( i -- ) | | | deselect_all | ( -- ) | | | gpio_input | ( i -- ) | | | gpio_output | ( i -- ) | | | gpio_set | ( i -- ) | | | gpio_clr | ( i -- ) | | | gpio_get | ( i -- n ) | | | analog_send | ( i u16 -- ) | | | analog_recv | ( i -- u16 ) | | | uart_connect | ( baud mode tty -- fd t | err f ) | | | uart_send | ( fd u8 -- t | err f ) | | | uart_recv | ( fd -- u8 t | err f ) | | | uart_avail | ( fd -- flag ) | | | can_disconnect | ( fd -- t | err f ) | | | can_connect | ( bitrate mode dev -- fd t | err f ) | can_send | ( fd fid len A B -- t | err f ) | can_recv | ( fd -- A B len fid t | 0 fid t | err f ) | can_avail | ( fd -- flag ) | can_disconnect | ( fd -- t | err f ) | file_open | ( name flags -- fd t | fd f ) | | | file_write | ( fd buf n -- n t | err f ) | | | file_read | ( fd buf n -- n t | err f ) | | | file_close | ( fd -- t | err f ) | | | file_seek | ( fd offset whence -- offs t | err f ) | |
Compact instructions
[dup,dup] : ( [a] -- [a,a,a] )
[dup,rot] : ( [a,b] -- [b,b,a] )
[dup,over] ( multiple ) ( [a] -- [a,a,a] )
[dup,drop] = id
[dup,swap] : ( [a] -- [a,a] )
[dup,'-'] : ( [a] -- [{const,0}] )
[dup,'+'] : ( [a] -- [{'+',a,a}] )
[dup,'*'] : ( [a] -- [{'*',a,a}] )
[rot,dup] : ( [a,b,c] -- [b,c,a,a] )
[rot,rot] : ( [a,b,c] -- [c,a,b] )
[rot,over] : ( [a,b,c] -- [b,c,a,c] )
[rot,drop] : ( [a,b,c] -- [b,c] )
[rot,swap] : ( [a,b,c] -- [b,a,c] )
[rot,'-'] : ( [a,b,c] -- [b,{'-',c,a}] )
[rot,'+'] : ( [a,b,c] -- [b,{'+',c,a}] )
[rot,'*'] : ( [a,b,c] -- [b,{'*',c,a}] )
[over,dup] : ( [a,b] -- [a,b,a,a] )
[over,rot] : ( [a,b] -- [b,a,a] )
[over,over] : ( [a,b] -- [a,b,a,b] )
[over,drop] = id
[over,swap] : ( [a,b] -- [a,a,b] )
[over,'-'] : ( [a,b] -- [a,{'-',b,a}] )
[over,'+'] : ( [a,b] -- [a,{'+',b,a}] )
[over,'*'] : ( [a,b] -- [a,{'*',b,a}] )
[drop,dup] : ( [a,b] -- [a,a] )
[drop,rot] : ( [a,b,c,d] -- [b,c,a] )
[drop,over] : ( [a,b,c] -- [a,b,a] )
[drop,drop] : ( [a,b] -- [] )
[drop,swap] : ( [a,b,c] -- [b,a] )
[drop,'-'] : ( [a,b,c] -- [{'-',a,b}] )
[drop,'+'] : ( [a,b,c] -- [{'+',a,b}] )
[drop,'*'] : ( [a,b,c] -- [{'*',a,b}] )
[swap,dup] ( multiple ) ( [a,b] -- [b,a,a] )
[swap,rot] : ( [a,b,c] -- [c,b,a] )
[swap,over] : ( [a,b] -- [b,a,b] )
[swap,drop] : ( [a,b] -- [b] )
[swap,swap] = id
[swap,'-'] : ( [a,b] -- [{'-',b,a}] )
[swap,'+'] : ( [a,b] -- [{'+',b,a}] )
[swap,'*'] : ( [a,b] -- [{'*',b,a}] )
['-',dup] : ( [a,b] -- [{'-',a,b},{'-',a,b}] )
['-',rot] : ( [a,b,c,d] -- [b,{'-',c,d},a] )
['-',over] : ( [a,b,c] -- [a,{'-',b,c},a] )
['-',drop] ( multiple ) ( [a,b] -- [] )
['-',swap] : ( [a,b,c] -- [{'-',b,c},a] )
['-','-'] : ( [a,b,c] -- [{'-',a,{'-',b,c}}] )
['-','+'] : ( [a,b,c] -- [{'+',a,{'-',b,c}}] )
['-','*'] : ( [a,b,c] -- [{'*',a,{'-',b,c}}] )
['+',dup] : ( [a,b] -- [{'+',a,b},{'+',a,b}] )
['+',rot] : ( [a,b,c,d] -- [b,{'+',c,d},a] )
['+',over] : ( [a,b,c] -- [a,{'+',b,c},a] )
['+',drop] ( multiple ) ( [a,b] -- [] )
['+',swap] : ( [a,b,c] -- [{'+',b,c},a] )
['+','-'] : ( [a,b,c] -- [{'-',a,{'+',b,c}}] )
['+','+'] : ( [a,b,c] -- [{'+',a,{'+',b,c}}] )
['+','*'] : ( [a,b,c] -- [{'*',a,{'+',b,c}}] )
['*',dup] : ( [a,b] -- [{'*',a,b},{'*',a,b}] )
['*',rot] : ( [a,b,c,d] -- [b,{'*',c,d},a] )
['*',over] : ( [a,b,c] -- [a,{'*',b,c},a] )
['*',drop] ( multiple ) ( [a,b] -- [] )
['*',swap] : ( [a,b,c] -- [{'*',b,c},a] )
['*','-'] : ( [a,b,c] -- [{'-',a,{'*',b,c}}] )
['*','+'] : ( [a,b,c] -- [{'+',a,{'*',b,c}}] )
['*','*'] : ( [a,b,c] -- [{'*',a,{'*',b
