#define JITC_ERR_PREFIXFAR (13 | JITC_ERR_PHASE0ONLY)
#define JITC_ERR_INTERNAL 99
-void errorHandler(struct Regs *r)
+void errorHandler(HOSECPU_RuntimeEnvironment *r)
{
puts("security error! abort...");
- printf("debugInfo0=%d, debugInfo1=%d¥n", r->debugInfo0, r->debugInfo1);
+ printf("debugInfo0=%d, debugInfo1=%d\n", r->debugInfo0, r->debugInfo1);
#if (USE_DEBUGGER != 0)
dbgrMain(r);
#endif
int jitCompCmdLen(const unsigned char *src)
{
+ //BCode命令長を取得する
int i = 1;
if (0x01 <= *src && *src < 0x04) i = 6;
if (*src == 0x04) i = 2;
if (*src == 0xfe) i = 2 + src[1];
return i;
}
-#if (JITC_ARCNUM == 0x0001) /* x86-32bit */
+#if (JITC_ARCNUM == 0x0001)
+//
+// for x86-32bit
+//
/* 他のCPUへ移植する人へ:
以下は最適化のためのものなので、すべて0として簡単に移植しても問題ありません */
#if (jitCompA0001_USE_R3F_IMM32 != 0)
int r3f;
#endif
- char prefix;
+ char prefix; //CND命令の値を記録(初期値=0)
};
#define jitCompPutByte1(p, c0) *p++ = c0
void funcf7(char *ebp, int pxx, int typ, int len); // typとlenはダミーで参照されない.
// F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない.
-void errHndl(struct Regs *r);
+void errHndl(HOSECPU_RuntimeEnvironment *r);
-int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, struct LabelTable *label, int maxLabels, int level, int debugInfo1, int flags)
+/*
+ * dst : 現在の書き込みアドレス。
+ * dst1 : 書き込みアドレスの最大値
+ * src : 現在の読み込みアドレス(ヘッダ部は飛ばしてある
+ * src1 : 読み込みアドレスの最大値
+ * src0 : 読み込みバイナリのアドレス
+ */
+int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *src, const unsigned char *src1, const unsigned char *src0, HOSECPU_LabelListTag *label, int maxLabels, int level, int debugInfo1, int flags)
/* IA-32用 */
/* 本来ならこのレイヤでは文法チェックしない */
{
struct JitCompWork w;
- unsigned char *dst00 = dst, *errmsg = "", *enter0 = NULL, *tmp_ucp;
+ unsigned char *dst00 = dst, *enter0 = NULL, *tmp_ucp;
+ char *errmsg = "";
const unsigned char *oldsrc;
int timecount = 0, i, j = 0, lastlabel = -1, debugInfo0 = -1;
int reg0, reg1, reg2, cmp0reg = -1, cmp0lev = 0;
w.dst = w.dst0 = dst;
w.err = 0;
w.maxLabels = maxLabels;
+
if ((flags & JITC_NOSTARTUP) == 0) {
jitCompPutByte1(w.dst, 0x60); /* PUSHAD(); */
jitCompA000_loadRegCacheAll(&w); /* start-up */
jitCompA0001_movEbpDispReg32(&w, 2304 + 4, 0 /* EAX */); /* MOV(debugInfo1, EAX); */
}
while (src < src1) {
- w.prefix = 0;
- if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; }
+ w.prefix = 0; //0x04 CND 命令で変更される
+ if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; } // 書き込み領域が残り256バイト未満ならエラー
timecount++;
if (timecount >= 64) {
timecount -= 64;
/* 未完成(timeoutチェックコードを入れる) */
}
- prefix_continue:
+ prefix_continue: // CND命令実行後ここに戻る
switch (*src) {
case 0x00: /* NOP */
- if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; }
+ if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } // 「条件付きでNOPを実行」するなんて、矛盾している!
break;
case 0x01: /* LB */
- if (enter0 == NULL && (src[6] == 0x3c || (src[6] == 0xfe && src[7] == 0x01 && src[9] == 0x3c))) {
- jitCompPutByte1(w.dst, 0xe9);
+
+ /*
+ * LB : ラベル設置命令。(6byte)
+ * ・prefex = 1にする
+ * ・timecount++し、timecountのチェックをする。
+ * ・ラベル位置を登録する。
+ * ・割り込みがある場合、このタイミングで割り込みを発生させる。
+ *
+ * 1 2 3 456
+ * LB 01 opt imm32
+ *
+ */
+
+ if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { //beginFunc()中のLB
+ // LB命令の後に0x3C命令・・・beginFunc()
+ jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする
enter0 = w.dst;
- jitCompPutImm32(&w, 0);
+ jitCompPutImm32(&w, 0); // 飛び相対座標が0 ・・・パイプラインのフラッシュ??
}
- if (src[6] == 0x34) {
+ if (src[6] == 0x34) { // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令
tmp_ucp = w.dst;
- jitCompPutByte1(w.dst, 0xe9);
- i = jitCompGetImm32(&src[7]);
+ jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする
+ i = jitCompGetImm32(&src[7]); // type32 を取得
j = 32;
if (i != 1) {
i = jitCompA000_convTyp(i);
}
if ((flags & JITC_PHASE1) == 0) {
i = jitCompGetLabelNum(&w, src + 2);
- //printf("i=%06X %06X¥n", i, src-src0);
+ //printf("i=%06X %06X\n", i, src-src0);
if (label[i].opt != 0 && w.err == 0) { w.err = JITC_ERR_LABELREDEF; goto err_w; }
if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; }
label[i].opt = src[1] + 1;
/* 未完成(timeoutチェックコードを入れる) */
break;
- case 0x02: /* LIMM */
- if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX;
+ case 0x02: /* LIMM */
+
+ /*
+ * LIMM : 定数即値代入命令(6byte)
+ *
+ * 1 2 3456
+ * 02 reg0R imm32
+ *
+ * ・reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。
+ */
+
+ if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX; // CND命令の直後でR3Fを書き換えるなんて変だよね
+
#if (jitCompA0001_USE_R3F_IMM32 != 0)
- if (src[1] == 0x3f) {
+ if (src[1] == 0x3f) { // R3Fへの代入は例外敵に、 w.r3f を使用
w.r3f = jitCompGetImm32(src + 2);
break;
}
#endif
- i = jitCompGetImm32(src + 2);
+ i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得
+
+ /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */
reg0 = jitCompA000_selectRegCache(src[1], 0 /* EAX */);
+
#if (jitCompA0001_OPTIMIZE_MOV != 0)
if (i == 0) {
jitCompPutByte2(w.dst, 0x31, 0xc0 | reg0 << 3 | reg0); /* XOR(reg0, reg0); */
break;
}
#endif
- jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */
+
+ /* reg0 のレジスタに対応したMOV命令を発行 */
+ jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); == 10111000b+wr imm32 */
jitCompPutImm32(&w, i);
- if (reg0 == 0)
+
+ if (reg0 == 0) // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合
+
jitCompA0001_movRxxEax(&w, src[1]);
break;
case 0x03: /* PLIMM */ /* 未完成(plsまで対応) */
- i = jitCompGetLabelNum(&w, src + 2);
- if ((flags & JITC_PHASE1) != 0 && w.err == 0) {
- if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; }
- if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; }
- if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; }
+
+ /*
+ * PLIMM : ラベル番号代入命令(6byte)
+ *
+ * 1 2 3456
+ * 03 PXX imm32
+ *
+ * ・P28 はAPI用
+ * ・P30 はリターンアドレス
+ * ・P3F はプログラムカウンタ
+ */
+
+ i = jitCompGetLabelNum(&w, src + 2); // Pxxに代入するラベルの番号(第二引数)
+ if ((flags & JITC_PHASE1) != 0 && w.err == 0) { // Phase 1であるならば
+ if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } // 指定されたラベル番号は存在しない
+ if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; } //
+ if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; } // プログラムカウンタに TYP_CODEでない値は代入できない
}
- if (src[1] == 0x3f) {
- if (w.prefix == 0) {
+ if (src[1] == 0x3f) { // プログラムカウンタへの代入なら
+ if (w.prefix == 0) { // CND命令による条件付きでなければ、即座に移動
jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */
}
- else {
+ else { // 直前はCND命令。
+
+ /*
+ * CND命令
+ * 1 2
+ * 04 reg0R
+ *
+ * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd
+ */
+
+ // JZのとび先アドレスの書き換え?
w.dst[-1] = w.dst[-2] ^ 0xf1; /* 74->85, 75->84 */
w.dst[-2] = 0x0f;
+
w.prefix = 0;
}
j = 0;
- if ((flags & JITC_PHASE1) != 0 || ((flags & JITC_PHASE1) == 0) && label[i].opt != 0)
- j = label[i].p - (w.dst + 4);
- jitCompPutImm32(&w, j);
+ if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0)) // label番号iが確保されていれば (このif文は意味をなさない)
+ j = label[i].p - (w.dst + 4); // j はとび先の相対番地
+ jitCompPutImm32(&w, j); // JMP もしくは JZ 命令のアドレス部を記述
#if (jitCompA0001_OPTIMIZE_JMP != 0)
if (-128 - 3 <= j && j < 0) {
if (w.dst[-5] == 0xe9) {
}
#endif
}
- else {
+ else { // プログラムカウンタ以外への代入
+
+ // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定
reg0 = jitCompA000_selectPRegCache(src[1], 0 /* EAX */);
jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */
- jitCompPutImm32(&w, (int)label[i].p);
+ jitCompPutImm32(&w, (int)label[i].p); // ラベルのパスを各レジスタに代入
+
+ // レジスタへの代入をメモリでエミュレーションする場合は、スタックに積む。
if (reg0 == 0)
jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32, 0); /* MOV([EBP+?], EAX); */
+
if (level < JITC_LV_FASTEST) {
jitCompA0001_movEbpDispReg32(&w, 256 + src[1] * 32 + 8, reg0); /* MOV([EBP+?], reg0); */ /* p0 */
jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */
break;
case 0x04: /* CND (prefix) */
- if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM;
+
+ /*
+ * CND命令
+ * 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。
+ */
+
+ if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM; // R00-R3F 以外のレジスタは比較対象にできない
+
+ // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す
reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */);
- if (reg0 < 0) {
+
+ /* TEST命令を発行 */
+ if (reg0 < 0) { //比較対象のレジスタはメモリ上にある
jitCompPutByte1(w.dst, 0xf7); /* TEST([EBP+?],1); */
jitCompA0001_85DispN(&w, src[1] * 4, 0);
}
jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); /* TEST(reg0,1); */
}
jitCompPutImm32(&w, 1);
+
+ /* JZ命令を発行 */
jitCompPutByte2(w.dst, 0x74, 0x00); /* JZ($+2) */
cmp0reg = -1;
if (w.err != 0) goto err_w;
src += 2;
- w.prefix = 1;
- w.dst0 = w.dst;
+ w.prefix = 1; // プリフィックスをセット
+ w.dst0 = w.dst;
goto prefix_continue;
case 0x08: /* LMEM */ /* 完成 */
// if (label[i].typ != 1) { w.err = JITC_ERR_LABELTYP; goto err_w; }
}
j = 0;
- if ((flags & JITC_PHASE1) != 0 || ((flags & JITC_PHASE1) == 0) && label[i].opt != 0)
+ if ((flags & JITC_PHASE1) != 0 || (((flags & JITC_PHASE1) == 0) && label[i].opt != 0))
j = label[i].p - (w.dst + 4);
jitCompPutImm32(&w, j);
#if (jitCompA0001_OPTIMIZE_JMP != 0)
if (w.err == (JITC_ERR_MASK & JITC_ERR_BADTYPE)) errmsg = "bad type code";
if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIXFAR)) errmsg = "prefix internal error";
if (w.err == (JITC_ERR_MASK & JITC_ERR_INTERNAL)) errmsg = "general internal error";
- if (*errmsg != '¥0') {
- fprintf(stderr, "JITC: %s at %06X (debugInfo0=%d)¥n ", errmsg, src - src0, debugInfo0);
+ if (*errmsg != '\0') {
+ fprintf(stderr, "JITC: %s at %06X (debugInfo0=%d)\n ", errmsg, src - src0, debugInfo0);
for (i = 0; i < 16; i++)
fprintf(stderr, "%02X ", src[i]);
static char *table[0x30] = {
"PCMPE", "PCMPNE", "PCMPL", "PCMPGE", "PCMPLE", "PCMPG", "??", "EXT" };
errmsg = "??";
if (*src < 0x30) errmsg = table[*src];
- fprintf(stderr, "(%s)¥n", errmsg);
+ fprintf(stderr, "(%s)\n", errmsg);
}
return -1;
}
void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
int i, *pi;
- struct Ptr *pp;
+ HOSECPU_PointerRegisterEntry *pp;
if (r->junkStack + 2048 > r->junkStack1) (*(r->errHndl))(r);
pi = (void *)r->junkStack; r->junkStack += r1 * 4;
for (i = 0; i < r1; i++)
void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
int i;
r->junkStack -= 4;
- r->junkStack -= 32; struct Ptr *pp = (void *)r->junkStack;
+ r->junkStack -= 32;
+ HOSECPU_PointerRegisterEntry *pp = (void *)r->junkStack;
r->preg[0x30] = *pp;
r->junkStack -= p1 * 32; pp = (void *)r->junkStack;
for (i = 0; i < p1; i++)
void funcf4(char *ebp, int pxx, int typ, int len)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3;
if (width < 0 || r->ireg[len] < 0)
(*(r->errHndl))(r);
void funcf5(char *ebp, int pxx, int typ, int len)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
r->junkStack -= sizeof (int);
int *pi = (int *)r->junkStack;
r->junkStack -= *pi;
void funcf6(char *ebp, int pxx, int typ, int len)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
int width = jitCompA000_dataWidth(jitCompA000_convTyp(r->ireg[typ])) >> 3;
if (width < 0 || r->ireg[len] < 0)
(*(r->errHndl))(r);
void funcf7(char *ebp, int pxx, int typ, int len)
{
- struct Regs *r = (struct Regs *) (ebp - jitCompA0001_EBP128);
+ HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128);
free(r->preg[pxx].p);
return;
}
-void errHndl(struct Regs *r)
+void errHndl(HOSECPU_RuntimeEnvironment *r)
{
- r = (struct Regs *) (((char *)r) - jitCompA0001_EBP128);
+ r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - jitCompA0001_EBP128);
(*(r->errHndl))(r);
// ここに帰ってきてはいけない.
}
/*
+ * jitcの出力コードをひとまとめにする関数を作成しその中身をjitCompile()で生成
+ *
* qq : 出力バイナリの書き込み位置のアドレスへの参照(書き込み位置を呼び出しに反映させるため参照渡しにする)
* q1 : 出力バイナリの書き込み位置のアドレスの最大値
* p0 : (*.ose)バイナリの読み込み位置のアドレス(ヘッダ部除去済)
* ret=1 : ヘッダのエラー
* ret=2 : jitコンパイルエラー
*/
-int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, struct LabelTable *label)
+int jitc0(unsigned char **qq, unsigned char *q1, const unsigned char *p0, const unsigned char *p1, int level, HOSECPU_LabelListTag *label)
{
unsigned char *q = *qq;
- if (p0[0] != 0x05 || p0[1] != SIGN1)
+ if (p0[0] != 0x05 || p0[1] != SIGN1) // OSECPUのヘッダ (05E1) を確認
return 1;
*q++ = 0x55; /* PUSH(EBP); */
for (i = 0; i < JITC_MAXLABELS; i++)
label[i].opt = 0;
+ // 以下のjitCompile()呼び出しでは第二引数をq1-2にした方がよいのではないか?
i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, 0);
if (i != 0) return 2;
i = jitCompiler(q, q1, p0 + 2, p1, p0, label, JITC_MAXLABELS, level, di1_serial, JITC_PHASE1 + 0);
#if (USE_DEBUGGER != 0)
-int dbgrGetRegNum(const unsigned char *p)
+int dbgrGetRegNum(const char *p)
{
int i, j, r = -1;
if (p[2] <= ' ') {
return r;
}
-void dbgrMain(struct Regs *r)
+void dbgrMain(HOSECPU_RuntimeEnvironment *r)
{
if (r->dbgr == 0) return;
for (;;) {
- unsigned char cmd[64], *p;
+ char cmd[64], *p;
int i, j, k;
- printf("¥ndbgr>");
+ printf("\ndbgr>");
p = fgets(cmd, 64, stdin);
if (p == NULL) break;
- if (cmd[0] == '¥0') continue;
+ if (cmd[0] == '\0') continue;
if (cmd[0] == 'q' && cmd[1] <= ' ') break;
- if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '¥0') {
+ if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '\0') {
p = &cmd[2];
- while (*p <= ' ' && *p != '¥0') p++;
+ while (*p <= ' ' && *p != '\0') p++;
if (*p == 'R') {
i = dbgrGetRegNum(p + 1);
if (0 <= i && i <= 0x3f) {
- printf("R%02X = 0x%08X = %d¥n", i, r->ireg[i], r->ireg[i]);
+ printf("R%02X = 0x%08X = %d\n", i, r->ireg[i], r->ireg[i]);
}
else
puts("register name error");
if (0 <= i && i <= 0x3f) {
p = "invalid";
if (0 <= r->preg[i].typ && r->preg[i].typ <= 0x15) {
- static unsigned char *typName[] = {
+ static char *typName[] = {
"T_CODE", "T_VPTR", "T_SINT8", "T_UINT8",
"T_SINT16", "T_UINT16", "T_SINT32", "T_UINT32",
"T_SINT4", "T_UINT4", "T_SINT2", "T_UINT2",
};
p = typName[r->preg[i].typ];
}
- printf("P%02X:¥n type = %s(%04X), (origin-ptr) = 0x%08X¥n", i, p, r->preg[i].typ, r->preg[i].p0);
+ printf("P%02X:\n type = %s(%04X), (origin-ptr) = 0x%08X\n", i, p, r->preg[i].typ, (unsigned int)(r->preg[i].p0));
if (r->preg[i].p != NULL && r->preg[i].p0 != NULL) {
j = jitCompA000_dataWidth(jitCompA000_convTyp(r->preg[i].typ)) >> 3;
if (j <= 0) j = 1;
k = (r->preg[i].p1 - r->preg[i].p0) / j;
- printf(" size = 0x%08X = %d¥n", k, k);
+ printf(" size = 0x%08X = %d\n", k, k);
k = (r->preg[i].p - r->preg[i].p0) / j;
- printf(" pos = 0x%08X = %d¥n", k, k);
+ printf(" pos = 0x%08X = %d\n", k, k);
}
else {
puts(" null pointer");