Advertisement
Guest User

vm_slow.c

a guest
Aug 25th, 2017
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.15 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include "ibniz.h"
  6.  
  7. #define MAXCODESIZE 4096
  8. #define MAXDATASIZE 4096
  9.  
  10. #define OP_LOADIMM '0'
  11.  
  12. #define ROL(a,s) ((((uint32_t)(a))<<(s))|(((uint32_t)(a))>>(32-(s))))
  13. #define ROR(a,s) ((((uint32_t)(a))>>(s))|(((uint32_t)(a))<<(32-(s))))
  14.  
  15. #define MOVESP(steps) vm.sp=(vm.sp+(steps))&vm.stackmask
  16. #define MOVERSP(steps) vm.rsp=(vm.rsp+(steps))&vm.rstackmask
  17.  
  18. char compiled_code[MAXCODESIZE];
  19. uint32_t compiled_data[MAXDATASIZE];
  20. uint32_t compiled_hints[MAXCODESIZE];
  21.  
  22. void pushmediavariables();
  23.  
  24. uint32_t getdatabits(int n)
  25. {
  26.   int s=(32-n-(vm.dataptr&31));
  27.   uint32_t mask;
  28.   uint32_t a;
  29.   if(n<=0 || vm.datalgt<=0) return 0;
  30.   mask=(1<<n)-1;
  31.   if(s>=0) a=(compiled_data[vm.dataptr>>5]>>s)&mask;
  32.       else a=((compiled_data[vm.dataptr>>5]<<(0-s))|
  33.               (compiled_data[(vm.dataptr>>5)+1]>>(32+s)))&mask;
  34.   vm.dataptr=(vm.dataptr+n)%vm.datalgt;
  35.   return a;
  36. }
  37.  
  38. void vm_compile(char*src)
  39. {
  40.   char*d=compiled_code;
  41.   uint32_t*hd=compiled_hints;
  42.   uint32_t num;
  43.   char*s,nummode=0,shift=0;
  44.   int i,j;
  45.   s=src;
  46.  
  47.   /* parse immediates, skip comments & whitespaces */
  48.  
  49.   for(;;)
  50.   {
  51.     char a=*s++;
  52.     if((!a) || (a>='!' && a<='~'))
  53.     {
  54.       if(a=='.' || (a>='0' && a<='9') || (a>='A' && a<='F'))
  55.       {
  56.         if(nummode==0)
  57.         {
  58.           num=0;
  59.           shift=16;
  60.           nummode=1;
  61.         }
  62.         if(a=='.')
  63.         {
  64.           if(nummode==2)
  65.           {
  66.             *d++=OP_LOADIMM;
  67.             *hd++=num;
  68.             num=0;
  69.           }
  70.           nummode=2;
  71.           shift=12;
  72.         } else
  73.         {
  74.           char digit=(a>='A'?a-'A'+10:a-'0');
  75.           if(nummode==1) num=ROL(num,4);
  76.           num|=digit<<shift;
  77.           if(nummode==2) shift=(shift-4)&31;
  78.         }
  79.       } else
  80.       {
  81.         if(nummode)
  82.         {
  83.           *d++=OP_LOADIMM;
  84.           *hd++=num;
  85.           nummode=0;
  86.         }
  87.         if(a=='\\')
  88.         {
  89.           while(*s && *s!='\n') s++;
  90.           if(!s) break;
  91.           s++;
  92.         }
  93.         else
  94.         {
  95.           if(a!=',')
  96.           {
  97.             if(a=='$') a='\0';
  98.             *d++=a;
  99.             *hd++=0;
  100.             if(a=='\0') break;
  101.           }
  102.         }
  103.       }
  104.     }
  105.   }
  106.  
  107.   /* parse data */
  108.  
  109.   vm.datalgt=0;
  110.   if(s[-1]=='$')
  111.   {
  112.     int digitsz=4;
  113.     compiled_data[0]=0;
  114.     for(;;)
  115.     {
  116.       int a=*s++;
  117.       if(!a) break;
  118.       if(a=='\\')
  119.       {
  120.         while(*s && *s!='\n') s++;
  121.         if(!s) break;
  122.         s++;
  123.       }
  124.       else
  125.       switch(a)
  126.       {
  127.         case('b'):
  128.           digitsz=1;
  129.           break;
  130.         case('q'):
  131.           digitsz=2;
  132.           break;
  133.         case('o'):
  134.           digitsz=3;
  135.           break;
  136.         case('h'):
  137.           digitsz=4;
  138.           break;
  139.         case('A'):case('B'):case('C'):case('D'):case('E'):case('F'):
  140.           a=a-'A'+10+'0';
  141.         case('0'):case('1'):case('2'):case('3'):case('4'):
  142.         case('5'):case('6'):case('7'):case('8'):case('9'):
  143.           a-='0';
  144.           a&=((1<<digitsz)-1);
  145.           {int s=(32-digitsz-(vm.datalgt&31));
  146.            if(s>=0)
  147.            {
  148.              compiled_data[vm.datalgt>>5]|=a<<s;
  149.              compiled_data[(vm.datalgt>>5)+1]=0;
  150.            }
  151.            else
  152.            {
  153.              compiled_data[vm.datalgt>>5]|=a>>(0-s);
  154.              compiled_data[(vm.datalgt>>5)+1]=a<<(32+s);
  155.            }
  156.            vm.datalgt+=digitsz;
  157.           }
  158.           break;
  159.       }
  160.     }
  161.     /* fill last 2 words to ease fetch */
  162.     {int pad=vm.datalgt&31;
  163.     if(pad)
  164.     {
  165.       int i=pad;
  166.       while(i<32)
  167.       {
  168.         compiled_data[vm.datalgt>>5]|=compiled_data[0]>>i;
  169.         i*=2;
  170.       }
  171.     }
  172.     if(!pad) compiled_data[(vm.datalgt>>5)+1]=compiled_data[0];
  173.     else
  174.     {
  175.       compiled_data[(vm.datalgt>>5)+1]=
  176.         (compiled_data[0]<<(32-pad)) |
  177.         (compiled_data[1]>>pad);
  178.     }
  179.     }
  180.   }
  181.  
  182.   /* precalculate skip points */
  183.   vm.codelgt=d-compiled_code;
  184.   for(i=0;;i++)
  185.   {
  186.     int j=i+1,seek0=0,seek1=0,seek2=0;
  187.     char a=compiled_code[i];
  188.     if(a=='\0') { seek0='M'; j=0; }
  189.     if(a=='M') seek0='M';
  190.     else if(a=='?') { seek0=';'; seek1=':'; }
  191.     else if(a==':') seek0=';';
  192.     else if(a=='{') { seek0='}'; }
  193.     int nested = 0;
  194.     if(seek0)
  195.     {
  196.       for(;;j++)
  197.       {
  198.         int a=compiled_code[j];
  199.         if((seek0 == ';' && a == '?') ||
  200.            (seek0 == '}' && a == '{')) {
  201.           nested++;
  202.         } else if(a == seek0 ||
  203.                   (nested == 0 && a == seek1)) {
  204.           nested--;
  205.         }
  206.         if(a=='\0' || nested < 0)
  207.         {
  208.           if(i==j || a==0) compiled_hints[i]=0;
  209.               else compiled_hints[i]=j+1;
  210.           break;
  211.         }
  212.       }
  213.     }
  214.     if(a=='\0') break;
  215.   }
  216.  
  217.   /* DEBUG: dump code */
  218.   /*
  219.   for(i=0;i<vm.codelgt;i++)
  220.   {
  221.     printf("slot %x: opcode %c, hints %x\n",
  222.       i,compiled_code[i],compiled_hints[i]);
  223.   }
  224.   for(i=0;i<vm.datalgt;i+=32)
  225.   {
  226.     printf("datapoint %d/%d: %x\n",i,vm.datalgt,compiled_data[i>>5]);
  227.   }
  228.   */
  229. }
  230.  
  231. void vm_init()
  232. {
  233.   /* video context */
  234.  
  235.   vm.stack=vm.mem+0xE0000;
  236.   vm.stackmask=0x1ffff;
  237.   vm.sp=0;
  238.  
  239.   vm.rstack=vm.mem+0xCC000;
  240.   vm.rstackmask=0x3FFF;
  241.   vm.rsp=0;
  242.  
  243.   /* audio context */
  244.  
  245.   vm.costack=vm.mem+0xD0000;
  246.   vm.costackmask=0xffff;
  247.   vm.cosp=1; // to avoid audio skipping bug at start
  248.  
  249.   vm.corstack=vm.mem+0xC8000;
  250.   vm.corstackmask=0x3FFF;
  251.   vm.corsp=0;
  252.  
  253.   /* state */
  254.  
  255.   vm.ip=compiled_code;
  256.   vm.mediacontext=0;
  257.   vm.videomode=0;
  258.   vm.audiomode=0;
  259.   vm.visiblepage=1;
  260.   vm.dataptr=0;
  261.   vm.userinput=0;
  262.   vm.stopped=0;
  263.   vm.audiotime=vm.videotime=gettimevalue();
  264.  
  265.   vm.spchange[0]=vm.spchange[1]=0;
  266.   vm.wcount[0]=vm.wcount[1]=0;
  267.   vm.currentwcount[0]=vm.currentwcount[1]=0;
  268.   vm.prevsp[0]=vm.prevsp[1]=0;
  269.  
  270.   /* zero out memory */
  271.   if(!vm.datalgt) memset(vm.mem,0,MEMSIZE*sizeof(uint32_t));
  272.   else
  273.   {
  274.     int i;
  275.     vm.dataptr=0;
  276.     for(i=0;i<MEMSIZE;i++) vm.mem[i]=getdatabits(32);
  277.     vm.dataptr=0;
  278.   }
  279.  
  280.   pushmediavariables();
  281. }
  282.  
  283. #define SWAP(t,a,b) { t tmp=(a);(a)=(b);(b)=tmp; }
  284.  
  285. void switchmediacontext()
  286. {
  287.   SWAP(int32_t*,vm.stack,vm.costack);
  288.   SWAP(uint32_t,vm.sp,vm.cosp);
  289.   SWAP(uint32_t,vm.stackmask,vm.costackmask);
  290.   SWAP(uint32_t*,vm.rstack,vm.corstack);
  291.   SWAP(uint32_t,vm.rsp,vm.corsp);
  292.   SWAP(uint32_t,vm.rstackmask,vm.corstackmask);
  293.   vm.mediacontext=vm.preferredmediacontext;
  294. }
  295.  
  296. void stepmediacontext(int skippoint,int at_eoc)
  297. {
  298.   vm.spchange[vm.mediacontext]=vm.sp-vm.prevsp[vm.mediacontext];
  299.   vm.wcount[vm.mediacontext]=vm.currentwcount[vm.mediacontext];
  300.   vm.currentwcount[vm.mediacontext]=0;
  301.   vm.prevsp[vm.mediacontext]=vm.sp;
  302.   vm.prevstackval[vm.mediacontext]=vm.stack[vm.sp];
  303.   if(vm.mediacontext==vm.preferredmediacontext)
  304.   {
  305.     //if(vm.rsp==0)
  306.     vm.ip=compiled_code+skippoint;
  307.     //         else
  308.     //         vm.ip=compiled_code+(vm.rstack[vm.rsp-1]%vm.codelgt);
  309.   } else
  310.   {
  311.     switchmediacontext();
  312.     //if(vm.rsp!=0) vm.ip=compiled_code+(vm.rstack[vm.rsp-1]%vm.codelgt);
  313.     //  else
  314.     if(at_eoc) vm.ip=compiled_code;
  315.   }
  316. }
  317.  
  318. void flipvideopage()
  319. {
  320.   vm.visiblepage=((vm.sp>>16)&1)^1;
  321.   //vm.visiblepage^=1;
  322.   for(;;)
  323.   {
  324.     uint32_t newt=gettimevalue();
  325.     if(newt!=vm.videotime) break;
  326.     waitfortimechange();
  327.   }
  328.   vm.videotime=gettimevalue();
  329. }
  330.  
  331. void pushmediavariables()
  332. {
  333.   vm.currentwcount[vm.mediacontext]++;
  334.   if(vm.mediacontext==0)
  335.   {
  336.     int p=vm.sp&65535;
  337.  
  338.     if(vm.videomode==0)
  339.     {
  340.       if(vm.visiblepage==(vm.sp>>16))
  341.       {
  342.         flipvideopage();
  343.       }
  344.       MOVESP(1);
  345.       vm.stack[vm.sp]=vm.videotime<<16;
  346.       MOVESP(1);
  347.       vm.stack[vm.sp]=(p<<1)-0x10000;
  348.       MOVESP(1);
  349.       vm.stack[vm.sp]=((p&255)<<9)-0x10000;
  350.     } else {
  351.       if(!p)
  352.       {
  353.         flipvideopage();
  354.       }
  355.       MOVESP(1);
  356.       vm.stack[vm.sp]=(vm.videotime<<16)|p;
  357.     }
  358.   } else
  359.   {
  360.     if(!vm.sp) // todo we need something better
  361.     {
  362.       vm.audiotime+=64;
  363.     }
  364.     MOVESP(1);
  365.     vm.stack[vm.sp]=vm.audiotime*65536+vm.sp*64;
  366. //    fprintf(stderr,"%x\n",vm.stack[vm.sp]);
  367.   }
  368. }
  369.  
  370. #define CYCLESPERRUN 10223
  371. int vm_run()
  372. {
  373.   int cycles;
  374.   if(vm.stopped) return 0;
  375.   for(cycles=CYCLESPERRUN;cycles;cycles--)
  376.   {
  377.     char op=*vm.ip++;
  378.     int32_t*a=&vm.stack[vm.sp],*b;
  379.  
  380.     switch(op)
  381.     {
  382.       /*** NUMBERS ***/
  383.  
  384.       case(OP_LOADIMM):
  385.         MOVESP(1);
  386.         vm.stack[vm.sp]=compiled_hints[vm.ip-1-compiled_code];
  387.         break;
  388.  
  389.       /*** ARITHMETIC ***/
  390.  
  391.       case('+'):    // (b a -- a+b)
  392.         MOVESP(-1);
  393.         vm.stack[vm.sp]+=*a;
  394.         break;
  395.  
  396.       case('-'):    // (b a -- a-b)
  397.         MOVESP(-1);
  398.         vm.stack[vm.sp]-=*a;
  399.         break;
  400.  
  401.       case('*'):    // (b a -- a*b)
  402.         MOVESP(-1);
  403.         b=&vm.stack[vm.sp];
  404.         {int64_t m=*a;
  405.          m*=((int32_t)*b);
  406.          *b=m>>16;
  407.          }
  408.         break;
  409.  
  410.       case('/'):    // (b a -- a/b)
  411.         MOVESP(-1);
  412.         b=&vm.stack[vm.sp];
  413.         if(!*a)*b=0;
  414.         else
  415.         {int64_t m=*b;
  416.          m<<=16;
  417.          m/=((int32_t)*a);
  418.          *b=m;}
  419.         break;
  420.  
  421.       case('%'):    // (b a -- a%b)
  422.         MOVESP(-1);
  423.         b=&vm.stack[vm.sp];
  424.         if(!*a)*b=0;
  425.         else
  426.         *b=(*b%*a);
  427.         break;
  428.  
  429.       case('q'):    // (a -- sqrt(a), 0 if a<0)
  430.         if(*a<0) *a=0;
  431.         else *a=sqrt(*a/65536.0)*65536.0;
  432.         break;
  433.  
  434.       case('&'):    // (b a -- a&b)
  435.         MOVESP(-1);
  436.         vm.stack[vm.sp]&=*a;
  437.         break;
  438.  
  439.       case('|'):    // (b a -- a|b)
  440.         MOVESP(-1);
  441.         vm.stack[vm.sp]|=*a;
  442.           break;
  443.  
  444.       case('^'):    // (b a -- a^b)
  445.         MOVESP(-1);
  446.         vm.stack[vm.sp]^=*a;
  447.         break;
  448.  
  449.       case('r'):    // (b a -- b ror a)
  450.         MOVESP(-1);
  451.         b=&vm.stack[vm.sp];
  452.         {int steps=(*a>>16)&31;
  453.          *b=ROR(*b,steps);
  454.         }
  455.         break;
  456.  
  457.       case('l'):    // (b a -- b >> a)
  458.         MOVESP(-1);
  459.         b=&vm.stack[vm.sp];
  460.         {int steps=(*a>>16)&63;
  461.          uint32_t w=*b;
  462.          if(steps<32)
  463.          *b=(w<<steps); else *b=(w>>(steps-32));
  464.          }
  465.         break;
  466.  
  467.       case('~'):    // (a -- NOT a)
  468.         *a=~*a;
  469.         break;
  470.  
  471.       case('s'):    // (a -- sin(a))
  472.         *a=sin(*a*(2*M_PI/65536.0))*65536.0;
  473.         break;
  474.       case('a'):    // (b a -- atan2(a,b))
  475.         MOVESP(-1);
  476.         b=&vm.stack[vm.sp];
  477.         *b=atan2(*a,*b)*(65536.0/(2*M_PI));
  478.         break;
  479.  
  480.       case('<'):    // (a -- a<0?a:0)
  481.         if(*a>=0)*a=0;
  482.         break;
  483.       case('>'):    // (a -- a>0?a:0)
  484.         if(*a&0x80000000)*a=0;
  485.         break;
  486.       case('='):    // (a -- a==0?1:0)
  487.         if(*a)*a=0x10000;else *a=0;
  488.         break;
  489.  
  490.       /*** STACK MANIPULATION ***/
  491.  
  492.       case('d'):    // (a -- a a)
  493.         MOVESP(1);
  494.         vm.stack[vm.sp]=*a;
  495.         break;
  496.  
  497.       case('p'):    // (a --)
  498.         MOVESP(-1);
  499.         break;
  500.  
  501.       case('x'):    // (b a -- a b) // forth: SWAP
  502.         {int32_t tmp=*a;
  503.          b=&vm.stack[(vm.sp-1)&vm.stackmask];
  504.          *a=*b;
  505.          *b=tmp;}
  506.         break;
  507.  
  508.       case('v'):    // (c b a -- b a c) // forth: ROT
  509.         {int32_t a_v=*a,*c;
  510.          b=&vm.stack[(vm.sp-1)&vm.stackmask];
  511.          c=&vm.stack[(vm.sp-2)&vm.stackmask];
  512.          *a=*c;
  513.          *c=*b;
  514.          *b=a_v;}
  515.         break;
  516.  
  517.       case(')'):    // pick from STACK[top-1-i]
  518.         *a=vm.stack[(vm.sp-1-ROL(*a,16))&vm.stackmask];
  519.         break;
  520.  
  521.       case('('):    // store to STACK[top-2-i]
  522.         MOVESP(-1);
  523.         b=&vm.stack[vm.sp];
  524.         MOVESP(-1);
  525.         vm.stack[(vm.sp-ROL(*a,16))&vm.stackmask]=*b;
  526.         break;
  527.  
  528.       case('z'):
  529.         MOVESP(1);
  530.         vm.stack[vm.sp]=ROL(((vm.stack+vm.sp)-vm.mem),16);
  531.         break;
  532.  
  533.       /*** EXTERIOR LOOP ***/
  534.  
  535.       case('M'):    // media switch
  536.         stepmediacontext(compiled_hints[vm.ip-compiled_code-1],0);
  537.         pushmediavariables();
  538.         break;
  539.  
  540.       case('\0'):   // end of code
  541.         //vm.ip=compiled_code; // or top of rstack (don't pop it)
  542.         stepmediacontext(compiled_hints[vm.ip-compiled_code-1],1);
  543.         pushmediavariables();
  544.         break;
  545.  
  546.       case('w'):    // whereami
  547.         pushmediavariables();
  548.         break;
  549.  
  550.       case('T'):    // terminate program
  551.         vm.ip--;
  552.         vm.stopped=1;
  553.         return CYCLESPERRUN-cycles;
  554.  
  555.       /*** MEMORY MANIPULATION ***/
  556.  
  557.       case('@'):    // (addr -- val)
  558.         *a=vm.mem[ROL(*a,16)&(MEMSIZE-1)];
  559.         break;
  560.  
  561.       case('!'):    // (val addr --)
  562.         MOVESP(-1);
  563.         b=&vm.stack[vm.sp];
  564.         MOVESP(-1);
  565.         vm.mem[ROL(*a,16)&(MEMSIZE-1)]=*b;
  566.         break;
  567.  
  568.       /*** PROGRAM CONTROL: Conditional execution ***/
  569.  
  570.       case('?'):    // if
  571.         MOVESP(-1);
  572.         if(*a!=0) break;
  573.       case(':'):    // then
  574.         vm.ip=compiled_code+compiled_hints[vm.ip-compiled_code-1];
  575.       case(';'):    // endif/nop
  576.         break;
  577.  
  578.       /*** PROGRAM CONTROL: Loops ***/
  579.  
  580.       case('i'):    // i counter
  581.         MOVESP(1);
  582.         vm.stack[vm.sp]=ROL(vm.rstack[(vm.rsp-1)&vm.rstackmask],16);
  583.         break;
  584.  
  585.       case('j'):    // j counter
  586.         MOVESP(1);
  587.         vm.stack[vm.sp]=ROL(vm.rstack[(vm.rsp-3)&vm.rstackmask],16);
  588.         break;
  589.  
  590.       case('X'):    // times
  591.         MOVERSP(1);
  592.         MOVESP(-1);
  593.         vm.rstack[vm.rsp]=ROL(*a,16);
  594.       case('['):    // do
  595.         MOVERSP(1);
  596.         vm.rstack[vm.rsp]=vm.ip-compiled_code;
  597.         break;
  598.  
  599.       case('L'):    // loop
  600.         {uint32_t*i=&vm.rstack[(vm.rsp-1)&vm.rstackmask];
  601.         (*i)--;
  602.         if(*i==0) MOVERSP(-2); else
  603.           vm.ip=(vm.rstack[vm.rsp]%vm.codelgt)+compiled_code;
  604.         }
  605.         break;
  606.  
  607.       case(']'):    // while
  608.         MOVESP(-1);
  609.         if(*a) vm.ip=(vm.rstack[vm.rsp]%vm.codelgt)+compiled_code;
  610.           else MOVERSP(-1);
  611.         break;
  612.  
  613.       case('J'):    // jump
  614.         {int point=*a%vm.codelgt; // !!! addressing will change
  615.         MOVESP(-1);
  616.         vm.ip=compiled_code+point;}
  617.         break;
  618.  
  619.       /*** PROGRAM CONTROL: Subroutines ***/
  620.  
  621.       case('{'):    // defsub
  622.         MOVESP(-1);
  623.         vm.mem[ROL(*a,16)&(MEMSIZE-1)]=vm.ip-compiled_code;
  624.         vm.ip=compiled_code+compiled_hints[vm.ip-1-compiled_code];
  625.         break;
  626.       case('}'):    // ret
  627.         vm.ip=compiled_code+(vm.rstack[vm.rsp]%vm.codelgt);
  628.         MOVERSP(-1);
  629.         break;
  630.       case('V'):    // visit
  631.         MOVESP(-1);
  632.         MOVERSP(1);
  633.         vm.rstack[vm.rsp]=vm.ip-compiled_code;
  634.         vm.ip=((vm.mem[ROL(*a,16)&(MEMSIZE-1)])%vm.codelgt)+compiled_code;
  635.         break;
  636.  
  637.       /*** PROGRAM CONTROL: Rstack manipulation ***/
  638.  
  639.       case('R'):    // pull from rstack to mainstack
  640.         MOVESP(1);
  641.         vm.stack[vm.sp]=ROL(vm.rstack[vm.rsp],16);
  642.         MOVERSP(-1);
  643.         break;
  644.       case('P'):    // push from stack to rstack
  645.         MOVERSP(1);
  646.         vm.rstack[vm.rsp]=ROL(*a,16);
  647.         MOVESP(-1);
  648.         break;
  649.  
  650.       /*** INPUT ***/
  651.  
  652.       case('U'):    // userinput
  653.         MOVESP(1);
  654.         vm.stack[vm.sp]=vm.userinput;
  655.         vm.userinput&=0xff00ffff;
  656.         break;
  657.  
  658.       /*** DATA SEGMENT ***/
  659.  
  660.       case('G'):    // getbits
  661.         *a=ROL(getdatabits((*a>>16)&31),16);
  662.         break;
  663.     }
  664.   }
  665.   return CYCLESPERRUN;
  666. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement