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
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);
+    }
+}
+
+