IPS(Interpreter for Process Structures) for mbed
Dependencies: ConfigFile FATFileSystem mbed
IPS port from linux/unix version.
mbed_blinky.ips
0 VAR led1 " LED1 " DigitalOut led1 ! : main ANFANG 1 JA? 1 led1 @ write 200 wait_ms 0 led1 @ write 200 wait_ms DANN/NOCHMAL ; main
- ips-02.tgz - ips for linux/unix
- ipsdoc.zip - document
- https://bitbucket.org/va009039/ips/
Diff: BaseIPS.cpp
- Revision:
- 1:e74530ad6b9e
- Child:
- 2:908338b1151a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseIPS.cpp Wed May 13 18:39:01 2015 +0900 @@ -0,0 +1,743 @@ +// BaseIPS.cpp 2015/5/6 +#include "mbed.h" +#include "BaseIPS.h" + +#include <math.h> +#define Round(x) ( (x>=0) ? (int)(x+0.5) : (int)(x-0.5) ) + +BaseIPS::BaseIPS() { + PS = 0xfff8; + RS = 0x4f8; + depth=0; + idle=0; + input_ptr = 512; + cycle = 0; + inputfile = NULL; +} + +u16 BaseIPS::peek(u16 a) { + return peekB(a) | peekB(a + 1)<<8; +} + +void BaseIPS::poke(u16 a, u16 w) { + pokeB(a, w & 0xff); + pokeB(a + 1, w>>8); +} + +u32 BaseIPS::peek32(u16 a) { + return peekB(a) | peekB(a + 1)<<8 | peekB(a + 2)<<16 | peekB(a + 3)<<24; +} + + +void BaseIPS::push_ps(u16 w) { + PS -= 2; + poke(PS, w); +} + +u16 BaseIPS::pull_ps() { + PS += 2; + return peek(PS - 2); +} + +void BaseIPS::push_rs(u16 w) { + RS -= 2; + poke(RS, w); +} + +u16 BaseIPS::pull_rs() { + RS += 2; + return peek(RS - 2); +} + +void BaseIPS::c_rumpelstilzchen(void) { // 0 +} + +void BaseIPS::c_defex(void) { // 1 + push_rs(PPC); + PPC = HP; + depth++; +} + +void BaseIPS::c_consex(void) { // 2 + push_ps(peek(HP)); +} + +void BaseIPS::c_varex(void) { // 3 + push_ps(HP); +} + +void BaseIPS::c_retex(void) { // 4 + depth--; + PPC = pull_rs(); +} + +void BaseIPS::c_get(void) { // 5 + poke(PS, peek(peek(PS))); +} + +void BaseIPS::c_getB(void) { // 6 + poke(PS, peekB(peek(PS))); +} + +void BaseIPS::c_put(void) { // 7 + u16 a = pull_ps(); + u16 v = pull_ps(); + if (peek(a) != v) idle=0; + poke(a, v); +} + +void BaseIPS::c_putB(void) { // 8 + u16 a = pull_ps(); + u16 v = pull_ps(); + if (peekB(a) != v) idle=0; + pokeB(a, v); + idle=0; +} + +void BaseIPS::c_1bliteral(void) { // 9 + push_ps(peekB(PPC)); + PPC++; +} + +void BaseIPS::c_2bliteral(void) { // 10 + push_ps(peek(PPC)); + PPC += 2; +} + +void BaseIPS::c_bronz(void) { // 11 + if ((pull_ps() & 1) == 0) PPC=peek(PPC); + else PPC += 2; +} + +void BaseIPS::c_jump(void) { // 12 + PPC = peek(PPC); +} + +void BaseIPS::c_weg(void) { // 13 + PS += 2; +} + +void BaseIPS::c_pweg(void) { // 14 + PS += 4; +} + +void BaseIPS::c_plus(void) { // 15 + s16 v = pull_ps(); + poke(PS, peek(PS) + v); +} + +void BaseIPS::c_minus(void) { // 16 + s16 v = pull_ps(); + poke(PS, peek(PS) - v); +} + +void BaseIPS::c_dup(void) { // 17 + push_ps(peek(PS)); +} + +void BaseIPS::c_pdup(void) { // 18 + push_ps(peek(PS + 2)); + push_ps(peek(PS + 2)); +} + +void BaseIPS::c_vert(void) { // 19 + s16 h=peek(PS); + poke(PS, peek(PS + 2)); + poke(PS + 2, h); +} + +void BaseIPS::c_zwo(void) { // 20 + push_ps(peek(PS+2)); +} + +void BaseIPS::c_rdu(void) { // 21 + s16 h=peek(PS); + poke(PS, peek(PS+2)); + poke(PS+2, peek(PS+4)); + poke(PS+4, h); +} + +void BaseIPS::c_rdo(void) { // 22 + s16 h=peek(PS+4); + poke(PS+4, peek(PS+2)); + poke(PS+2, peek(PS)); + poke(PS, h); +} + +void BaseIPS::c_index(void) { // 23 + push_ps(peek(RS)); +} + +void BaseIPS::c_s_to_r(void) { // 24 + push_rs(pull_ps()); +} + +void BaseIPS::c_r_to_s(void) { // 25 + push_ps(pull_rs()); +} + +void BaseIPS::c_eqz(void) { // 26 + poke(PS,(peek(PS)==0)); +} + +void BaseIPS::c_gz(void) { // 27 + poke(PS,((s16)peek(PS)>0)); +} + +void BaseIPS::c_lz(void) { // 28 + poke(PS,((s16)peek(PS)<0)); +} + +void BaseIPS::c_geu(void) { // 29 + u16 a,b; + b=pull_ps(); + a=peek(PS); + poke(PS,a>=b); +} + +void BaseIPS::c_f_vergl(void) { // 30 + int t; + u16 n,a1,a2; + n=pull_ps(); + a2=pull_ps(); + a1=peek(PS); + t=1; + do { + int b; + b=(s16)peekB(a1++)-(s16)peekB(a2++); + if (b>0) t=2; + else if (b<0) t=0; + n=(n-1)&0xff; + } while (n); + poke(PS,t); +} + +void BaseIPS::c_nicht(void) { // 31 + poke(PS, 0xffff^peek(PS)); +} + +void BaseIPS::c_und(void) { // 32 + u16 v = pull_ps(); + poke(PS, v & peek(PS)); +} + +void BaseIPS::c_oder(void) { // 33 + u16 v = pull_ps(); + poke(PS, v | peek(PS)); +} + +void BaseIPS::c_exo(void) { // 34 + u16 v = pull_ps(); + poke(PS, v ^ peek(PS)); +} + +void BaseIPS::c_bit(void) { // 35 + poke(PS, 1<<peek(PS)); +} + +void BaseIPS::c_cbit(void) { // 36 + int a = pull_ps(); + int b = (pull_ps())&0x07; + pokeB(a, peekB(a)&~(1<<b) ); +} + +void BaseIPS::c_sbit(void) { // 37 + int a,b; + a=pull_ps(); + b=(pull_ps())&0x07; + pokeB(a, peekB(a)|(1<<b) ); +} + +void BaseIPS::c_tbit(void) { // 38 + int a,b; + a=pull_ps(); + b=(peek(PS))&0x07; + if (peekB(a)&(1<<b)) poke(PS,1); + else poke(PS,0); +} + +void BaseIPS::loop_sharedcode(int i) { + int l; + l=(s16)peek(RS); + if (i<=l) { + push_rs(i); + PPC=peek(PPC); + } else { + pull_rs(); + PPC+=2; + } +} + +void BaseIPS::c_jeex(void) { // 39 + PPC=peek(PPC); + push_rs(pull_ps()); + loop_sharedcode((s16)pull_ps()); +} + +void BaseIPS::c_loopex(void) { // 40 + loop_sharedcode((s16)(pull_rs()+1)); +} + +void BaseIPS::c_plusloopex(void) { // 41 + int i; + i=(s16)(pull_rs()); + loop_sharedcode(i+(s16)pull_rs()); +} + +void BaseIPS::c_fieldtrans(void) { // 42 + /* note: cannot call memcpy() here, because memcpy()'s behaviour is not defined when source and destination areas overlap */ + /* memmove() cannot be used either, because its behaviour for overlap is different from what IPS expects */ + int n,d,s,b; + n=pull_ps(); + d=pull_ps(); + s=pull_ps(); + do { + b=peekB(s++); + pokeB(d++,b); + n=(n-1)&0xff; + } while (n); + if (d<=0x400) redraw=1; + idle=0; +} + +void BaseIPS::c_pmul(void) { // 43 + u32 c = pull_ps() * pull_ps(); + push_ps((s16)(c&0xffff)); + push_ps(c>>16); +} + +void BaseIPS::c_pdiv(void) { // 44 + u32 q,n; + u16 d,nh,nl,r; + d=pull_ps(); + nh=pull_ps(); + nl=pull_ps(); + n=(nh<<16)+nl; + if (d==0) { q=0xffff; r=0; } + else { + q=n/d; + r=n%d; + if (q>=0x10000) { q=0xffff; r=0; } + } + push_ps(q); + push_ps(r); +} + +void BaseIPS::c_tue(void) { // 45 + HP = pull_ps(); +} + +void BaseIPS::c_polyname(void) { // 46 + u32 x,p,d; + d=pull_ps(); + x=pull_ps(); + p=pull_ps(); + x= x | (p&0xff00) | ((p&0xff)<<16); + p = d ^ x ^ (x>>1) ^ (x>>2) ^ (x>>7); + x = x ^ ((p&0xff)<<24); + x >>= 7; + push_ps( (x&0xff00) | ((x>>16)&0xff) ); + push_ps( (x&0xff) ); +} + +void BaseIPS::c_scode(void) { // 47 + int i; + u32 nd; + int offs=peek(a_Os); + i=peek(a_NDptr); + nd=peek32(i); + i=peek(a_P3); + while (i) { + i+=offs; + if ( ( (peek32(i) ^ nd) & 0xffffff3f) ==0) { + push_ps(i+6); + return; + } + i=peek(i+4); + } + push_ps(0); +} + +void BaseIPS::c_cscan(void) { // 48 + int a; + int pi,pe; + int comment=0; + pi=peek(a_PI); + pe=peek(a_PE); + + a=pull_ps(); + if (a==1) { + while (pi<=pe) { + if (comment) { + if (peekB(pi)==')') comment=0; + } else { + if (peekB(pi)=='(') comment=1; + else if (peekB(pi)!=' ') { + poke(a_PI,pi); + push_ps(1); + return; + } + } + pi++; + } + push_ps(0); + poke(a_P2,1); + return; + } else { + while (pi<=pe) { + if (peekB(pi)==' ') { + break; + } + pi++; + } + poke(a_PI,pi); + push_ps(0); + } +} + +void BaseIPS::c_chs(void) { // 49 + poke(PS,-(s16)peek(PS)); +} + +void BaseIPS::c_cyc2(void) { // 50 + u32 ch,a,crcc; + int i; + + ch=pull_ps(); + a=pull_ps(); + crcc=(a>>8)|((a&0xff)<<8); + + ch<<=8; + for (i=0;i<=7;i++) { + //int test; + //test=(ch^crcc)&0x8000; + crcc<<=1; + ch<<=1; + if ((ch^crcc)&0x10000) crcc^=0x1021; + } + + push_ps( ((crcc&0xff)<<8) | ((crcc>>8)&0xff) ); +} + +void BaseIPS::c_close(void) { // 51 + if (inputfile) { + file_close(inputfile); + inputfile = NULL; + } +} + +void BaseIPS::c_open(void) { // 52 + if (inputfile) { + file_close(inputfile); + } + int namelen = pull_ps(); + int namestart = pull_ps(); + char filename[256]; + if (namelen > sizeof(filename)-1) { + namelen = sizeof(filename) - 1; + } + for(int i = 0; i < namelen; i++) { + filename[i] = peekB(namestart + i); + } + filename[namelen] = '\0'; + inputfile = file_open(filename); + push_ps(inputfile != NULL ? 1 : 0); +} + +void BaseIPS::c_oscli(void) { // 53 + error("OSCLI not implemented!"); +} + +void BaseIPS::c_load(void) { // 54 + error("LOAD not implemented!"); +} + +void BaseIPS::c_save(void) { // 55 + int namelen = pull_ps(); + int namestart = pull_ps(); + int end = pull_ps(); + int start = pull_ps(); + + char filename[256]; + if (namelen > 255) namelen = 255; + for(int i = 0; i < namelen; i++) { + filename[i] = peekB(namestart + i); + } + filename[namelen] = 0; + + void* fh = file_open(filename, "wb"); + if (fh == NULL) { + push_ps(0); + return; + } + for(int i = start; i < end; i++) { + file_putc(peekB(i), fh); + } + file_close(fh); + push_ps(1); +} + +void BaseIPS::c_setkbptr(void) { // 56 + input_ptr = pull_ps() & 0x3ff; +} + +void BaseIPS::c_getPS(void) { // 57 + push_ps(PS); +} + +void BaseIPS::c_setPS(void) { // 58 + PS=pull_ps(); +} + +void BaseIPS::c_rp_code(void) { // 59 + double theta,x,y,r; + pull_ps(); + y=(s16)pull_ps(); + x=(s16)pull_ps(); + theta=((s16)pull_ps())/10430.38; /* convert to radians */ + theta+=atan2(y,x); + r=sqrt(x*x+y*y)*1.6468; + push_ps(Round(theta*10430.38)); + push_ps((int)(r+0.5)); + push_ps(0); +} + +void BaseIPS::c_tr_code(void) { // 60 + double theta,x,y,r; + pull_ps(); + y=(s16)pull_ps(); + x=(s16)pull_ps(); + theta=((s16)pull_ps())/10430.38; /* convert to radians */ + theta+=atan2(y,x); + r=sqrt(x*x+y*y)*1.6468; + push_ps(0); + push_ps(Round(r*cos(theta))); + push_ps(Round(r*sin(theta))); +} + +void BaseIPS::c_swap3(void) { // 61 + u16 h; + h=peek(PS+6); poke(PS+6,peek(PS)); poke(PS,h); + h=peek(PS+8); poke(PS+8,peek(PS+2)); poke(PS+2,h); + h=peek(PS+10); poke(PS+10,peek(PS+4)); poke(PS+4,h); +} + +void BaseIPS::c_defchar(void) { // 62 + error("DEFCHAR not implemented!\n"); +} + +void BaseIPS::c_pplus(void) { // 63 + u32 h=pull_ps(); + u32 b=(h<<16)+pull_ps(); + h=pull_ps(); + u32 a=(h<<16)+pull_ps(); + u32 c=a+b; + push_ps(c&0xffff); + push_ps(c>>16); +} + +void BaseIPS::c_pminus(void) { // 64 + u32 h = pull_ps(); + u32 b = (h<<16)+pull_ps(); + h = pull_ps(); + u32 a = (h<<16)+pull_ps(); + u32 c = a - b; + push_ps(c&0xffff); + push_ps(c>>16); +} + +void BaseIPS::c_sleepifidle(void) { // 80 +/* extension for IPS-Mu, i.e., the linux/unix version */ + if (idle) { + //do_sleep(); + //leaveloop=0; + } + idle=1; +} + +void BaseIPS::do_20ms(void) { + pokeB(UHR, peekB(UHR) + 2); // 20ms + if (peekB(UHR) == 100) { + pokeB(UHR, 0); + pokeB(UHR+1, peekB(UHR+1) + 1); + if (peekB(UHR+1) == 60) { + pokeB(UHR+1, 0); + pokeB(UHR+2, peekB(UHR+2) + 1); + if (peekB(UHR+2) == 60) { + pokeB(UHR+2, 0); + pokeB(UHR+3, peekB(UHR+3) + 1); + if (peekB(UHR+3) == 24) { + pokeB(UHR+3, 0); + poke(UHR+4, peek(UHR+4) + 1); + } + } + } + } + + const int sus[4]={SU0,SU1,SU2,SU3}; + for (int i = 0; i < 4; i++) { + int su=sus[i]; + if ((peekB(su)&1) == 0) { + if (peekB(su) != 0) { + pokeB(su, peekB(su) - 2); + } else { + if (peekB(su+1) != 0) { + pokeB(su, 98); + pokeB(su+1, peekB(su+1) - 1); + } else { + if (peekB(su+2) != 0) { + pokeB(su+1, 59); + pokeB(su+2, peekB(su+2) - 1); + } else { + if (peekB(su+3) != 0) { + pokeB(su+2, 255); + pokeB(su+3, peekB(su+3) - 1); + } else { + pokeB(su, 1); + } + } + } + } + } + } +} + +void BaseIPS::read_inputfile(void) { + for(int i = 0x200; i < 0x400; i++) { + pokeB(i, ' '); + } + + do { + int ch = file_getc(inputfile); + if (ch<1) { + if (input_ptr == peek(a_PI)) { + file_close(inputfile); + inputfile = NULL; + pokeB(LOADFLAG, 0); + input_ptr = 0x200; + } + break; + } + if (ch=='\r') { + /* ignore \r, we expect at least also a \n as end-of-line */ + } else if (ch=='\n') { + input_ptr=(input_ptr&0xffc0)+64; + } else { + pokeB(input_ptr++,ch); + } + } while (input_ptr<1024 && inputfile); /* 1024 = TVE */ + + if (input_ptr!=peek(a_PI)) { + pokeB(READYFLAG,1); + poke(a_PE,input_ptr-1); + idle=0; + } +} + +void BaseIPS::emulator() { + PPC = 0x0400; + input_ptr = peek(a_PI); + while(1) { + HP = peek(PPC); + PPC += 2; +exec: u16 CPC = peek(HP); + HP += 2; + trace(cycle++, PPC-2, HP-2, CPC, PS, RS); + switch(CPC) { + case 1: c_defex(); break; + case 2: c_consex(); break; + case 3: c_varex(); break; + case 4: c_retex(); break; + case 5: c_get(); break; + case 6: c_getB(); break; + case 7: c_put(); break; + case 8: c_putB(); break; + case 9: c_1bliteral(); break; + case 10: c_2bliteral(); break; + case 11: c_bronz(); break; + case 12: c_jump(); break; + case 13: c_weg(); break; + case 14: c_pweg(); break; + case 15: c_plus(); break; + case 16: c_minus(); break; + case 17: c_dup(); break; + case 18: c_pdup(); break; + case 19: c_vert(); break; + case 20: c_zwo(); break; + case 21: c_rdu(); break; + case 22: c_rdo(); break; + case 23: c_index(); break; + case 24: c_s_to_r(); break; + case 25: c_r_to_s(); break; + case 26: c_eqz(); break; + case 27: c_gz(); break; + case 28: c_lz(); break; + case 29: c_geu(); break; + case 30: c_f_vergl(); break; + case 31: c_nicht(); break; + case 32: c_und(); break; + case 33: c_oder(); break; + case 34: c_exo(); break; + case 35: c_bit(); break; + case 36: c_cbit(); break; + case 37: c_sbit(); break; + case 38: c_tbit(); break; + case 39: c_jeex(); break; + case 40: c_loopex(); break; + case 41: c_plusloopex(); break; + case 42: c_fieldtrans(); break; + case 43: c_pmul(); break; + case 44: c_pdiv(); break; + case 45: c_tue(); goto exec; + case 46: c_polyname(); break; + case 47: c_scode(); break; + case 48: c_cscan(); break; + case 49: c_chs(); break; + case 50: c_cyc2(); break; + case 51: c_close(); break; + case 52: c_open(); break; + case 53: c_oscli(); break; + case 54: c_load(); break; + case 55: c_save(); break; + case 56: c_setkbptr(); break; + case 57: c_getPS(); break; + case 58: c_setPS(); break; + case 59: c_rp_code(); break; + case 60: c_tr_code(); break; + case 61: c_swap3(); break; + case 62: c_defchar(); break; + case 63: c_pplus(); break; + case 64: c_pminus(); break; + case 80: c_sleepifidle(); break; + default: c_rumpelstilzchen(); break; + } + do_io(); + if (test_20ms()) { + do_20ms(); + } + if (inputfile) { + if (!(peekB(READYFLAG)&1) && (peekB(LOADFLAG)&1)) { + read_inputfile(); + } + } + } +} + +void BaseIPS::load_image(const u8* image, int size) { + for(int i = 0; i < size; i++) { + pokeB(i, *image++); + } +} + +void BaseIPS::command(const char* s) { + if (s) { + int cmd_len = strlen(s); + for(int i = 0; i < cmd_len; i++) { + pokeB(i + 64*8, *s++); + } + poke(a_PE, 0x200 + cmd_len); + pokeB(READYFLAG, 1); + } +} + +