Merge branch 'new-isa' into trunk

adds F flag to instructions (~op in the assembler)
makes stack management on the return stack much easier,
and now returning from a function only takes 1 instruction
(~ju) rather than two (mr ju). also, this allows us to
remove some opcodes from the opcode set that were kind of
unneccessary
This commit is contained in:
Kitty-Cricket Piapiac 2023-03-27 19:41:12 -07:00
commit 9c0258e9ff
7 changed files with 61 additions and 59 deletions

13
as.c
View File

@ -8,9 +8,9 @@ V mh(W i,H h){mb(i,h>>8),mb(i+1,h);}
V mw(W i,W w){mh(i,w>>16),mh(i+2,w);}
V mcpy(W dst,B*src,W l){for(W i=0;i<l;++i)mb(dst+i,src[i]);}
#define OPSZ 38
_ B ops[OPSZ*2]="npexpbphpwfbfhfwmbmhmwioiimdmrdddrduswovadsumudianorxrslsrsaeqltgtnojujccacc";
_ B op(B x[2]){W i;for(i=0;i++<OPSZ;)Q(ops[i*2]==x[0]&&ops[1+i*2]==x[1],R i);R OPSZ;}
#define OPSZ 36
_ B ops[OPSZ*2]="npexpbphpwfbfhfwmbmhmwioiissdrswduovadsumudianorxrslsrsaeqltgtnojujccacc";
_ B op(B x[2]){W i=0;WH(i++<OPSZ,Q(ops[i*2]==x[0]&&ops[1+i*2]==x[1],R i));R OPSZ;}
_ B htob(B h){R h>='a'&&h<='f'?h-'a'+10:h>='A'&&h<='F'?h-'F'+10:h>='0'&&h<='9'?h-'0':16;}
_ B ws(B x){R' '==x||'\t'==x||'\r'==x||'\n'==x;}
@ -46,7 +46,7 @@ _ V builtin(S*t){FILE*f;S y,x=*t;++x.p,--x.l;
BE("inc",tasrt(y=next(t),'"'),y.p[y.l-1]=0;WIF(f,(C*)y.p+1,"rb",frun(f)))
tw(x),die(" unknown builtin");}
_ V pass1(S*t){S x=*t;B c,o;c=*x.p;
_ V pass1(S*t){_ B o=0;S x=*t;B c;c=*x.p;
Q('{'==c,/*discard*/)OR
Q('"'==c,mcpy(mel,x.p+1,x.l-=2),mel+=x.l)OR
Q('#'==c,B bs[tz(x)];tto4b(x,bs),mcpy(mel,bs,SZ(bs)),mel+=SZ(bs))OR
@ -56,8 +56,9 @@ _ V pass1(S*t){S x=*t;B c,o;c=*x.p;
Q('`'==c,Macro*m;++x.p,--x.l;Q(m=Hget(Macro,macros,x),Vfor(S,m->ws,y,i,pass1(&y)))OR tw(x),die(" unknown macro"))OR
Q('-'==c,builtin(t))OR
Q(';'==c,N(label->p,die("; at top-level"))label=label->p)OR
Q(2!=x.l||OPSZ==(o=op(x.p)),tw(x),die(" unknown inst"))OR
mb(mel++,o);}
Q('~'==c,++x.p,--x.l,o|=0x40,pass1(&x))OR
Q(2!=x.l||OPSZ==(o|=op(x.p)),tw(x),die(" unknown inst"))OR
mb(mel++,o),o=0;}
_ V pass2(V){Label*l;
Vfor(Ref,refs,r,i,Q(l=lget(r.p,r.n),mw(r.a,l->a))OR tw(r.n),die(" unknown ref"))}

22
d/kmm32
View File

@ -39,9 +39,17 @@ BUSSES
(see ./kip for kip computer i/o)
INSTRUCTION SET
INSTRUCTIONS
Instructions take 1 byte in memory.
Opcodes take 1 byte in memory.
Each binary digit corresponds to:
UFOOOOOO
||O: Opcode
|F: Flip return and data stacks
| (eg 01000010 will put the next byte in memory onto the return stack)
U: Unused
OPCODES
np (--) no-op
ex (--) halt execution
@ -56,13 +64,11 @@ INSTRUCTION SET
mw (n a--) ^ same but with word
io (n p--) move cell `n to io port `p
ii (p--n) gets cell from io port `p and pushes it onto the stack
md (n-~n) move cell from data stack to return stack
mr (n~-n) move cell from return stack to data stack
dd (n--) drop item from data stack
dr (n~~) drop item from return stack
du (n--n n) duplicate item on data stack
ss (n-~n) move cell from data stack to return stack
dr (n--) drop item from data stack
sw (n m--m n) swap items
ov (n m--n m n) bring sescon item on stack over
du (n--n n) duplicate item on data stack
ov (n m--n m n) bring second item on data stack over
ad (n m--n+m) add
su (n m--n-m) subtract
mu (n m--n*m) multiply

View File

@ -33,6 +33,9 @@ SYNTAX
- - Assembler built-in; these can take some amount of arguments.
~ - Switch data and return stacks on the instruction which takes up the rest
of the token.
Otherwise, it is treated as an instruction.
BUILTINS

36
kmm32.c
View File

@ -3,14 +3,15 @@
#define AB b=pop(),A
#define DS ((W*)(mem+(MEMSZ-0x800)))
#define RS ((W*)(mem+(MEMSZ-0x400)))
#define SD (RS-DS)
B dp,rp,mem[MEMSZ];
W ip;
B mem[MEMSZ];
W*dp=DS,*rp=RS,ip;
_ W pop(V){R DS[--dp];}
_ W por(V){R RS[--rp];}
_ V put(W i){DS[dp++]=i;}
_ V pur(W i){RS[rp++]=i;}
_ W pop(V){R*--dp;}
_ V put(W i){*dp++=i;}
_ V pur(W i){*rp++=i;}
_ V swp(V){W*t;t=dp,dp=rp,rp=t;}
B lob(W i){R mem[i];}
H loh(W i){R lob(i)<<8|lob(i+1);}
@ -20,6 +21,7 @@ V sth(W i,H h){stb(i,h>>8),stb(i+1,h);}
V stw(W i,W w){sth(i,w>>16),sth(i+2,w);}
V vec(W i){Q(0x100<(i=low(i)),pur(ip),ip=i)}
#include<stdio.h>
_ W a,b;
_ V np(V){}
_ V ex(V){ip+=0x40001;}
@ -34,13 +36,11 @@ _ V mh(V){AB,sth(b,a);}
_ V mw(V){AB,stw(b,a);}
_ V io(V){AB,ios[b].io(a);}
_ V ii(V){put(ios[pop()].oi());}
_ V md(V){pur(pop());}
_ V mr(V){put(por());}
_ V dd(V){--dp;}
_ V dr(V){--rp;}
_ V du(V){put(DS[dp-1]);}
_ V ss(V){pur(pop());}
_ V dr(V){--dp;}
_ V sw(V){AB,put(b),put(a);}
_ V ov(V){put(DS[dp-2]);}
_ V du(V){put(*(dp-1));}
_ V ov(V){put(*(dp-2));}
_ V ad(V){AB,put(a+b);}
_ V su(V){AB,put(a-b);}
_ V mu(V){AB,put(a*b);}
@ -58,12 +58,12 @@ _ V no(V){put(!pop());}
_ V ju(V){ip=pop();}
_ V jc(V){AB;Q(a,ip=b)}
_ V ca(V){pur(ip),ip=pop();}
_ V cc(V){AB;Q(a,ip=b)}
_ V cc(V){AB;Q(a,pur(ip),ip=b)}
_ V(*ops[])(V)=
/*0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25*/
/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37*/
{np,ex,pb,ph,pw,fb,fh,fw,mb,mh,mw,io,ii,md,mr,dd,dr,du,sw,ov,ad,su,mu,di,an,or,xr,sl,sr,sa,eq,lt,gt,no,ju,jc,ca,cc};
/*0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23*/
/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35*/
{np,ex,pb,ph,pw,fb,fh,fw,mb,mh,mw,io,ii,ss,dr,sw,du,ov,ad,su,mu,di,an,or,xr,sl,sr,sa,eq,lt,gt,no,ju,jc,ca,cc};
V emu(W c){while(c--&&ip<0x40000)ops[mem[ip++]]();}
V lod(B*c,W l){for(ip=0;ip<l;++ip)mem[ip+0x100]=c[ip];dp=rp=0,ip=0x100;}
V emu(W c){B m,f;while(c--&&ip<0x40000){Q((f=(m=mem[ip++])>>6)&1,swp());ops[0x3f&m]();Q(f&1,swp());}}
V lod(B*c,W l){for(ip=0;ip<l;++ip)mem[ip+0x100]=c[ip];ip=0x100;}

View File

@ -13,8 +13,8 @@ typedef int32_t Ws;
typedef struct{V(*io)(W);W(*oi)(V);} IoDevice;
#define MEMSZ 0x40800
extern B dp,rp,mem[MEMSZ];
extern W ip;
extern B mem[MEMSZ];
extern W*dp,*rp,ip;
extern IoDevice*ios;
B lob(W);

View File

@ -1,22 +1,17 @@
-inc "x/dev.inc"
!inc pb #1 ad ; { this is not the case of labels, which can be }
!nl #0a ; { referenced before they are defined }
!+1 pb #01 ad ;
!nl #0a ;
{ source code }
-org #100 { `-org` is an assembler built-in that sets the origin }
:entry { `:entry` is a label definition }
pw @data/hello { `pw` is an instruction, and all words with no }
{ colour prefix are treated as such. }
:loop
du fb
du no pw @end jc { `@end` is a 32-bit reference to `:end` below }
`term:0 io `inc { `term literally includes `pb #0` from dev.inc }
pw @loop ju
; :end
dd dd
; ex
-org #0100
:entry
pw @data/hello-meow pw @s0/put ca
pw @data/hello-world pw @s0/put ca
ex
;
:s0
:put du fb du no pw @end jc `term:0 io `+1 pw @put ju :end dr dr ~ju ; ;
;
:data
:hello "hello, world!" `nl #00 ;
:hello-meow "hello meow :3c" `nl #00 ;
:hello-world "hello, world!!" `nl #00 ;
;

View File

@ -1,21 +1,18 @@
-inc "x/dev.inc"
!vsync pb #0 ;
!ret mr ju ;
!ret ~ju ;
-org #100
:entry
pw @vsync `vsync mw
pw @cursormove `vsync mw
ex
;
:vsync
pw @cursormove ca
`ret
;
:cursormove
pw @data/2b/cursor `disp:blt io
pw @pos fw `disp:pos io
pw #00fff072 `disp:out io
`mouse:pos ii du `disp:pos io pw @pos mw
pw #00ffff72 `disp:out io
`mouse:pos ii du `disp:pos io
pw @pos mw
pw #00f25032 `disp:out io
`ret
:pos #00000000 ;