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

BaseIPS.cpp

Committer:
va009039
Date:
2015-05-24
Revision:
4:b62b40563944
Parent:
2:908338b1151a

File content as of revision 4:b62b40563944:

// BaseIPS.cpp 2015/5/22
#include <algorithm>
#include "mbed.h"
#include "BaseIPS.h"

#ifndef NO_MATH
#include <math.h>
#define Round(x) ( (x>=0) ? (int)(x+0.5) : (int)(x-0.5) )
#endif

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);
    }
    size_t namelen = pull_ps();
    int namestart = pull_ps();
    char filename[256];
    namelen = std::min(namelen, sizeof(filename)-1);
    for(size_t 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();
}

#ifndef NO_MATH
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)));
}
#else
void BaseIPS::c_rp_code(void) {
   error("c_rp_code not implemented!\n");
}
void BaseIPS::c_tr_code(void) {
   error("c_tr_code not implemented!\n");
}
#endif

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::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 0: c_rumpelstilzchen(); break;
            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;
            default: usercode(CPC); 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);
    }
}