「60分でできる!JITコンパイラ自作入門」

(0)

(1) 64bit-インタプリタ編

 Sub_AI(SP,16); // SP = SP - 16;
 Mov_RI(R0,0); // R0 = 0;
 Sto_RMD(R0,SP,0); // [SP+0] = R0;
 Sto_RMD(R0,SP,8); // [SP+8] = R0;
Lb_I(1); // L_1:
 Lod_RMD(R0,SP,8); // R0 = [SP+8];
 Lod_RMD(R1,SP,0); // R1 = [SP+0];
 Add_RR(R0,R1); // R0 += R1;
 Sto_RMD(R0,SP,0); // [SP+0] = R0;
 Lod_RMD(R0,SP,8); // R0 = [SP+8];
 Add_RI(R0,1); // R0 += 1;
 Sto_RMD(R0,SP,8); // [SP+8] = R0;
 CmpJlt_RII(R0,100000000,1); // if (R0 < 100000000) goto L_1;
 Lod_RMD(R0,SP,0); // R0 = [SP+0];
 Add_AI(SP,16); // SP = SP + 16;
 End(); // R0に計算結果が入っているので、それを表示して終了;

// int s, i; s = 0;
// for (i = 0; i < 100000000; i++) { s = s + i; }
Mov_RI(Rx,const);Rx = const;
Lod_RMD(Rx,Ax,disp);Rx = [Ax + disp];
Sto_RMD(Rx,Ax,disp);[Ax + disp] = Rx;
Add_RR(Rx,Ry);Rx += Ry;
Add_RI(Rx,const);Rx += const;
Add_AI(Ax,const);Ax += const;
Sub_AI(Ax,const);Ax -= const;
Lb_I(x);L_x:
CmpJlt_RII(Rx,const,y);if (Rx < const) goto L_y;
End();R0の値を表示して終了
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <inttypes.h>

struct Code { int64_t op, a, b, c; };
enum { Mov_RI=1, Lod_RMD, Sto_RMD, Add_RR, Add_RI, Add_AI, Sub_AI, Lb_I, CmpJlt_RII, End };
enum { R0=0, R1=1, SP=6 };

int main()
{
  static struct Code t[17] = {
    { Sub_AI,  SP, 16, -0 }, // -0は命令としては意味を持ってないパラメータ.
    { Mov_RI,  R0, 0,  -0 },
    { Sto_RMD, R0, SP, 0  },
    { Sto_RMD, R0, SP, 8  },
    { Lb_I,    1,  -0, -0 },
    { Lod_RMD, R0, SP, 8  },
    { Lod_RMD, R1, SP, 0  },
    { Add_RR,  R0, R1, -0 },
    { Sto_RMD, R0, SP, 0  },
    { Lod_RMD, R0, SP, 8  },
    { Add_RI,  R0, 1,  -0 },
    { Sto_RMD, R0, SP, 8  },
    { CmpJlt_RII, R0, 100000000, 1 },
    { Lod_RMD, R0, SP, 0  },
    { Add_AI,  SP, 16, -0 },
    { End,     -0, -0, -0 },
    { 0,       -0, -0, -0 }
  };
  int64_t lb[256], r[8], a[8], pc; 
  char m[256]; // メモリ.

  // Lb_I(x)命令を探して位置をlb[]に格納する.
  for (pc = 0; t[pc].op > 0; pc++) {
    if (t[pc].op == Lb_I) { lb[t[pc].a] = pc + 1; }
    // 高速化のために、ラベル命令の次の命令の位置を登録している.
  }

  // 実行開始.
  pc = 0; a[6] = 256;
  clock_t tm0 = clock();
  for (;;) {
    struct Code *tp = &t[pc]; int64_t *mp;
    switch (tp->op) {
    case Mov_RI:  r[tp->a] = tp->b; pc++; continue;
    case Lod_RMD: mp = (int64_t *) (m + a[tp->b] + tp->c); r[tp->a] = *mp; pc++; continue;
    case Sto_RMD: mp = (int64_t *) (m + a[tp->b] + tp->c); *mp = r[tp->a]; pc++; continue;
    case Add_RR:  r[tp->a] += r[tp->b]; pc++; continue;
    case Add_RI:  r[tp->a] += tp->b; pc++; continue;
    case Add_AI:  a[tp->a] += tp->b; pc++; continue;
    case Sub_AI:  a[tp->a] -= tp->b; pc++; continue;
    case Lb_I:    pc++; continue;
    case CmpJlt_RII: if (r[tp->a] < tp->b) { pc = lb[tp->c]; } else { pc++; } continue;
    case End:     goto fin;
    }
  }
fin:
  printf("R0=%" PRId64 " (%.3f[sec])\n", r[0], (clock() - tm0) / (double) CLOCKS_PER_SEC);
  return 0;
}

(2) 64bit-JITコンパイラ編


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS