From 43603aff869e2ba0a09d100523210f1f8cfc08b7 Mon Sep 17 00:00:00 2001 From: hikarupsp Date: Thu, 20 Mar 2014 18:24:21 +0900 Subject: [PATCH] =?utf8?q?=E3=82=AD=E3=83=BC=E3=83=9C=E3=83=BC=E3=83=89?= =?utf8?q?=E9=96=A2=E9=80=A3=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- dpndenv.c | 9 +- jitcx86.c | 3543 +++++++++++++++++++++++++++++++------------------------------ osecpu.h | 1 + 3 files changed, 1778 insertions(+), 1775 deletions(-) diff --git a/dpndenv.c b/dpndenv.c index 9ad5cbd..0601a89 100644 --- a/dpndenv.c +++ b/dpndenv.c @@ -79,6 +79,9 @@ if (kc == NSDownArrowFunctionKey) i = KEY_DOWN; if (kc == NSInsertFunctionKey) i = KEY_INS; if (kc == NSDeleteFunctionKey) i = KEY_DEL; + if (i == KEY_EMPTY && isascii(kc)){ + i = kc; + } // 修飾キー // TODO : 下の方の右辺、iとjが混ざっているのは修正すべき? j = 0; @@ -93,11 +96,7 @@ if ((GetKeyState(VK_CAPITAL) & (1 << 0)) != 0) i |= KEY_MODIFIER_CAPITAL; */ - NSLog(@"%X", kc); - if (isascii(kc)){ - i = kc; - } - + // NSLog(@"%X", i); if (i != -1) { putKeybuf(i | j); } diff --git a/jitcx86.c b/jitcx86.c index c65ed6a..f55c3ac 100644 --- a/jitcx86.c +++ b/jitcx86.c @@ -1,1771 +1,1774 @@ -#include "osecpu.h" -#include "jitc.h" - -#if (JITC_ARCNUM == 0x0001) -// -// for x86-32bit -// - -// F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない. -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) -{ - // For IA-32 (x86, 32-bit) - // 本来ならこのレイヤでは文法チェックしない - // - // dst : 現在の書き込みアドレス。 - // dst1 : 書き込みアドレスの最大値 - // src : 現在の読み込みアドレス(ヘッダ部は飛ばしてある - // src1 : 読み込みアドレスの最大値 - // src0 : 読み込みバイナリのアドレス - struct JitCompWork w; - 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) { - jitCompPutOp_PUSHAD(w.dst); - // Load cache - jitCompA000_loadRegCacheAll(&w); - jitCompA000_loadPRegCacheAll(&w); - } - if (level <= JITC_LV_SLOWER) { - // env.debugInfo0 <- 0; - // env.debugInfo1 <- debugInfo1; - jitCompPutOp_MOV_EAX_ZERO(w.dst); - jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO0, IA32_REG0_EAX); - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); - jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); - } - while (src < src1) { - w.prefix = 0; //0x04 CND 命令で変更される - if (w.dst + 256 > dst1) { - // 書き込み領域が残り256バイト未満ならエラー - w.err = JITC_ERR_DST1; - goto err_w; - } - timecount++; - if (timecount >= 64) { - timecount -= 64; - /* 未完成(timeoutチェックコードを入れる) */ - } - if(*src != 0x00 && *src != 0x01 && *src != 0x34){ - DEBUGCode(&w, *src); - } - prefix_continue: - // CND命令コンパイル後ここに戻る - switch (*src) { - case 0x00: - // NOP - if (w.prefix != 0) { - // 「条件付きでNOPを実行」するなんて、矛盾している! - w.err = JITC_ERR_PREFIX; - goto err_w; - } - break; - - case 0x01: - // LB : ラベル設置命令。(6byte) - // ・prefex = 1にする - // ・timecount++し、timecountのチェックをする。 - // ・ラベル位置を登録する。 - // ・割り込みがある場合、このタイミングで割り込みを発生させる。 - // Encode: - // 0 1 2345 - // 01 opt imm32 - // - if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { - //beginFunc()中のLB - // LB命令の後に0x3C命令・・・beginFunc() - enter0 = w.dst; - jitCompPutOp_JMPnear(w.dst, 0); - } - - if (src[6] == 0x34) { - // 後続命令はDATA - // なので、DATA部分をJMPですっとばすコードを生成 - // DAT_SA0(label, typ32, length) ・・・メモリ確保命令 - - i = jitCompGetImm32(&src[6 + 1]); // type32 を取得 - j = 32; - - if (i != 1) { - i = jitCompA000_convTyp(i); - j = 0; - switch (i >> 1) { - case 1: - j = 1; - break; - case 2: - j = 2; - break; - case 3: - j = 4; - break; - } - } - // jはデータサイズになる - j *= jitCompGetImm32(&src[6 + 5]); // len32 - if (j <= 0){ - w.err = JITC_ERR_BADTYPE; - } - // DATA部分を飛び越すジャンプ - tmp_ucp = w.dst; - jitCompPutOp_JMPnear(w.dst, j); - -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (j < 127 - jitCompA0001_OPTIMIZE_ALIGN) { - //飛び先が十分近いので - // 今書いたのはなかったことにして、 - w.dst -= 5; - // よりサイズの小さな書き方にする - jitCompPutOp_JMPshort(w.dst, j); - } -#endif - } -#if (jitCompA0001_OPTIMIZE_ALIGN != 0) - // アラインを jitCompA0001_OPTIMIZE_ALIGNにそろえる - - i = ((int)w.dst + 1) & (jitCompA0001_OPTIMIZE_ALIGN - 1); /* ALIGNで割ったあまりを計算 */ - i = jitCompA0001_OPTIMIZE_ALIGN - i; - if (i == 1) { jitCompPutByte1(w.dst, 0x90); j += i; } /* NOP(); */ - if (i == 2) { jitCompPutByte2(w.dst, 0x89, 0xc0); j += i; } /* MOV(EAX, EAX); */ - if (i == 3) { jitCompPutByte3(w.dst, 0x8d, 0x76, 0x00); j += i; } /* LEA(ESI, [ESI+0]); */ - if (i == 4) { jitCompPutByte4(w.dst, 0x8d, 0x74, 0x26, 0x00); j += i; } /* LEA(ESI, [ESI*1+0]); */ - if (i == 5) { jitCompPutByte1(w.dst, 0x0d); jitCompPutImm32(w.dst, 0); j += i; } /* OR(EAX, 0); */ - if (i == 6) { jitCompPutByte2(w.dst, 0x8d, 0xb6); jitCompPutImm32(w.dst, 0); j += i; } /* LEA(ESI, [ESI+0]); */ - if (i == 7) { jitCompPutByte3(w.dst, 0x8d, 0xb4, 0x26); jitCompPutImm32(w.dst, 0); j += 7; } /* LEA(ESI, [ESI*1+0]); */ -#endif - if (src[6] == 0x34) { - // 後続命令はDATA - // パディングに合わせて一個前の相対ジャンプを修正 - tmp_ucp[1] = j & 0xff; - if (*tmp_ucp == 0xe9) { - // Near jump so imm is DWORD - tmp_ucp[2] = (j >> 8) & 0xff; - tmp_ucp[3] = (j >> 16) & 0xff; - tmp_ucp[4] = (j >> 24) & 0xff; - } - } - if ((flags & JITC_PHASE1) == 0) { // Phase 0ならば - i = jitCompGetLabelNum(&w, src + 2); - if (label[i].opt != 0 && w.err == 0) { - w.err = JITC_ERR_LABELREDEF; // すでに同じ値のラベルがあればエラー - goto err_w; - } - if (w.prefix != 0) { // CND命令の直後にラベルは設置できない - w.err = JITC_ERR_PREFIX; - goto err_w; - } - label[i].opt = src[1] + 1; - label[i].typ = 0; /* TYP_CODE */ - label[i].p = w.dst; - label[i].p1 = w.dst + 1; - lastlabel = i; - } - cmp0reg = -1; - timecount = 0; - /* 未完成(timeoutチェックコードを入れる) */ - break; - - case 0x02: - // LIMM : 定数即値代入命令(6byte) - // Encode: - // 0 1 2345 - // 02 reg0R imm32 - // - // reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 - - if (src[1] == 0x3f && w.prefix != 0){ - // CND命令の直後でR3Fを書き換えるなんて変だよね - w.err = JITC_ERR_PREFIX; - } - -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[1] == 0x3f) { - // R3Fへの代入は例外で、 w.r3f を使用 - w.r3f = jitCompGetImm32(src + 2); - break; - } -#endif - i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得 - /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */ - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - -#if (jitCompA0001_OPTIMIZE_MOV != 0) - // size optimization - // MOV reg, 0 -> XOR reg, reg - if (i == 0) { - jitCompPutOp_XOR_GReg_GReg(w.dst, reg0, reg0); - jitCompA0001_movRxxEax(&w, src[1]); - break; - } -#endif - /* reg0 のレジスタに対応したMOV命令を発行 */ - jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, i); - - if (reg0 == 0){ - // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 - jitCompA0001_movRxxEax(&w, src[1]); - } - - break; - - case 0x03: /* 未完成(plsまで対応) */ - // PLIMM : ラベル番号代入命令(6byte) - // Encode: - // 0 1 2345 - // 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) { - // プログラムカウンタに TYP_CODEでない値は代入できない - w.err = JITC_ERR_LABELTYP; - goto err_w; - } - } - if (src[1] == 0x3f) { - // プログラムカウンタへの代入 - if (w.prefix == 0) { - // CND命令による条件付きでなければ、即座に移動 - jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ - } else { - // 直前はCND命令。 - - /* - * CND命令 - * 1 2 - * 04 reg0R - * - * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd - */ - - // Jccの条件変更 - // 0F 75 - 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)) // label番号iが確保されているか、Phase 1なら - j = label[i].p - (w.dst + 4); // j はとび先の相対番地 - jitCompPutImm32(w.dst, j); // JMP もしくは JZ 命令のアドレス部を記述 -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (-128 - 3 <= j && j < 0) { - if (w.dst[-5] == 0xe9) { - j += 3; - w.dst -= 5; - jitCompPutByte1(w.dst, 0xeb); /* JMP(?); */ - } else { - j += 4; - w.dst -= 6; - jitCompPutByte1(w.dst, w.dst[1] ^ 0xf0); - } - jitCompPutByte1(w.dst, j & 0xff); - } -#endif - } else { // プログラムカウンタ以外への代入 - // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 - reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); - // ラベルのパスを各レジスタに代入 - jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, (int)label[i].p); - // レジスタへの代入をメモリでエミュレーションする場合は、スタックに書き込む。 - if (reg0 == 0){ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 0, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - - if (level < JITC_LV_FASTEST) { - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 8, reg0); /* p0 */ - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, label[i].typ); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 4, IA32_REG0_EAX); /* typ */ - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, (int)label[i].p1); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 12, IA32_REG0_EAX); /* p1 */ - jitCompPutOp_MOV_EAX_ZERO(w.dst); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 16, IA32_REG0_EAX); /* liveSign */ - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, envOffset_PTRCTRL); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 20, IA32_REG0_EAX); /* pls */ - } - } - break; - - case 0x04: - // CND (prefix) - // 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 - - if (src[1] >= 0x40){ - // R00-R3F 以外のレジスタは比較対象にできない - w.err = JITC_ERR_REGNUM; - goto err_w; - } - - // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す - reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */); - - /* TEST命令を発行 */ - if (reg0 < 0) { - // 比較対象のレジスタはメモリ上にある - jitCompPutByte1(w.dst, 0xf7); /* TEST = 1111 011w : mod 000 r/m : immediate data */ - jitCompPutModRM_Disp_BaseEBP(&w, src[1] * 4, 0); - } else { - // 比較対象はキャッシュレジスタ上にある - jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); /* TEST = 1111 011w : 11 000 reg : immediate data */ - } - jitCompPutImm32(w.dst, 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; - goto prefix_continue; - - case 0x08: /* LMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i == 0x0001){ - w.err = JITC_ERR_BADTYPE; - } - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 0); // read - cmp0reg = -1; - } - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); - if (reg0 != IA32_REG0_EAX && reg1 == IA32_REG2_EDX){ - reg1 = IA32_REG0_EAX; - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_storeRegCacheEdx(&w); - } - if (reg1 <= 3 /* EAX, EDX */){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); - } - if (level < JITC_LV_FASTER){ - jitCompA0001_checkLimit(&w, reg1, src[6]); - } - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - switch (i) { - case 0x0002: - jitCompPutByte3(w.dst, 0x0f, 0xbe, reg0 << 3 | reg1); /* MOVSX(reg0,BYTE [reg1]); */ - break; - case 0x0003: - jitCompPutByte3(w.dst, 0x0f, 0xb6, reg0 << 3 | reg1); /* MOVZX(reg0,BYTE [reg1]); */ - break; - case 0x0004: - jitCompPutByte3(w.dst, 0x0f, 0xbf, reg0 << 3 | reg1); /* MOVSX(reg0,WORD [reg1]); */ - break; - case 0x0005: - jitCompPutByte3(w.dst, 0x0f, 0xb7, reg0 << 3 | reg1); /* MOVZX(reg0,WORD [reg1]); */ - break; - case 0x0006: - case 0x0007: - jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ - break; - default: - w.err = JITC_ERR_BADTYPE; - } - if (reg0 == IA32_REG0_EAX){ - jitCompA0001_movRxxEax(&w, src[1]); - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_loadRegCacheEdx(&w); - } - break; - - case 0x09: /* SMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i == 0x0001){ - w.err = JITC_ERR_BADTYPE; - } - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 1); // write - cmp0reg = -1; - } - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); - if (reg0 != IA32_REG0_EAX && reg1 == IA32_REG2_EDX){ - reg1 = IA32_REG0_EAX; - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_storeRegCacheEdx(&w); - } - if (reg1 <= 3 /* EAX, EDX */){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6]) + 0); /* MOV(reg1, [EBP+?]); */ - } - if (level < JITC_LV_FASTER){ - jitCompA0001_checkLimit(&w, reg1, src[6]); - } - if (reg0 == IA32_REG0_EAX){ - jitCompA0001_movEaxRxx(&w, src[1]); - } - /* 値の範囲チェック */ - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - switch (i) { - case 0x0002: - case 0x0003: - jitCompPutByte2(w.dst, 0x88, reg0 << 3 | reg1); /* MOV([reg1], BYTE(reg0)); */ - break; - case 0x0004: - case 0x0005: - jitCompPutByte3(w.dst, 0x66, 0x89, reg0 << 3 | reg1); /* MOV([reg1], WORD(reg0)); */ - break; - case 0x0006: - case 0x0007: - jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ - break; - default: - w.err = JITC_ERR_BADTYPE; - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_loadRegCacheEdx(&w); - } - break; - - case 0x0a: /* PLMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i != 0x0001){ - w.err = JITC_ERR_BADTYPE; - } - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 0); // read - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); - // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ - // reg1 = 0; /* EAX */ - if (reg0 == reg1 && reg0 != 0) { - // bugfix: hinted by yao, 2013.09.14. thanks! - jitCompA000_storePRegCacheAll(&w); - reg1 = IA32_REG2_EDX; - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_storeRegCacheEdx(&w); - } - if (reg1 <= 3 /* EAX, EDX */){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); /* MOV(reg1, [EBP+?]); */ - } - if (level < JITC_LV_FASTER){ - jitCompA0001_checkLimit(&w, reg1, src[6]); - } - jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ - if (reg0 == IA32_REG0_EAX){ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]), IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - for (i = 4; i < 32; i += 4) { - jitCompPutByte3(w.dst, 0x8b, 0x40 | reg1, i); /* MOV(EAX, [reg1+?]); */ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - if (reg1 == IA32_REG2_EDX){ - jitCompA000_loadRegCacheEdx(&w); - } - break; - - case 0x0b: /* PSMEM */ /* 完成 */ - i = jitCompGetImm32(src + 2); - if (i != 0x0001) w.err = JITC_ERR_BADTYPE; - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType(&w, src[6], i, 1); // write - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); - /* これをやってはいけない!(by K, 2013.08.02) */ - // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) - // reg1 = 0; /* EAX */ - if (reg1 == IA32_REG2_EDX){ - jitCompA000_storeRegCacheEdx(&w); - } - if (reg1 <= 3 /* EAX, EDX */){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); /* MOV(reg1, [EBP+?]); */ - } - if (level < JITC_LV_FASTER){ - jitCompA0001_checkLimit(&w, reg1, src[6]); - } - if (reg0 == IA32_REG0_EAX){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[1])); /* MOV(reg0, [EBP+?]); */ - } - jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ - for (i = 4; i < 32; i += 4) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[1]) + i); /* MOV(EAX, [EBP+?]); */ - jitCompPutByte3(w.dst, 0x89, 0x40 | reg1, i); /* MOV([reg1+?], EAX); */ - } - if (reg1 == IA32_REG2_EDX) - jitCompA000_loadRegCacheEdx(&w); - break; - - case 0x0e: /* PADD */ /* 完成 */ - if (level < JITC_LV_FASTER) { - jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 2), 2); // other, aliveテストはとりあえずしない. - cmp0reg = -1; - } - reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectPRegCache(src[6], -1 /* mem */); - if (reg1 < 0 /* mem */){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[6])); /* MOV(reg0, [EBP+?]); */ - } - if (reg1 >= 0 && reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - i = jitCompGetImm32(src + 2); - j = -1; - if (i == 1){ - j = 5; /* 32 */ - } else { - i = jitCompA000_convTyp(i); - if (0x0002 <= i && i <= 0x0007){ - j = (i - 0x0002) >> 1; - } - } - if (j < 0) { - w.err = JITC_ERR_BADTYPE; - goto err_w; - } -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[7] == 0x3f) { - j = w.r3f << j; -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= j && j <= 0x7f) { -#if (jitCompA0001_USE_R3F_INCDEC != 0) - if (j == 1) { - /* INC */ - jitCompPutByte1(w.dst, 0x40 | reg0); - goto padd1; - } - if (j == -1) { - /* DEC */ - jitCompPutByte1(w.dst, 0x48 | reg0); - goto padd1; - } -#endif - /* ADD(reg0, im8); */ - jitCompPutByte3(w.dst, 0x83, 0xc0 | reg0, j & 0xff); - goto padd1; - } -#endif - if (reg0 == 0) { - jitCompPutByte1(w.dst, 0x05); /* ADD(reg0, ?); */ - } else { - jitCompPutByte2(w.dst, 0x81, 0xc0 | reg0); /* ADD(reg0, ?); */ - } - jitCompPutImm32(w.dst, j); - goto padd1; - } -#endif - if (src[7] >= 0x40){ - w.err = JITC_ERR_REGNUM; - } - if (j == 0) { - reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); - if (reg1 >= 0) { - jitCompPutByte2(w.dst, 0x01, 0xc0 | reg1 << 3 | reg0); /* ADD(reg0, reg1); */ - } else { - jitCompPutByte1(w.dst, 0x03); /* ADD(reg0, [EBP+?]); */ - jitCompPutModRM_Disp_BaseEBP(&w, src[7] * 4, reg0); - } - } - else { - reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); - reg2 = IA32_REG2_EDX; - jitCompA000_storeRegCacheEdx(&w); - if (reg1 < 0){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg2, src[7] * 4); /* MOV(reg2, [EBP+?]); */ - } - if (reg1 >= 0 && reg1 != reg2) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg2); /* MOV(reg2, reg1); */ - } - jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg2, j); /* SHL(reg2, ?); */ - jitCompPutByte2(w.dst, 0x01, 0xc0 | reg2 << 3 | reg0); /* ADD(reg0, reg2); */ - jitCompA000_loadRegCacheEdx(&w); - } -#if (jitCompA0001_USE_R3F_IMM32 != 0) - padd1: -#endif - if (reg0 == IA32_REG0_EAX){ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]), reg0); /* MOV([EBP+?], reg0); */ - } - if (src[1] != src[6]) { - for (i = 4; i < 32; i += 4) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - } - cmp0reg = -1; - break; - - case 0x0f: /* PDIF */ /* 未完成 */ - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompA0001_checkCompPtr(&w, src[6], src[7]); - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[6])); /* MOV(reg0, [EBP+?]); */ - jitCompPutByte1(w.dst, 0x2b); /* SUB(EAX, [EBP+?]); */ - jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[7]) + 0, reg0); - i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); - j = -1; - if (0x0002 <= i && i <= 0x0007){ - j = (i - 0x0002) >> 1; - } - if (j < 0) { - w.err = JITC_ERR_BADTYPE; - goto err_w; - } - if (j > 0) { - jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, j); /* SAR(reg0,?); */ - } - if (reg0 == IA32_REG0_EAX){ - jitCompA0001_movRxxEax(&w, src[1]); - } - cmp0reg = src[1]; - cmp0lev = 1; - break; - - case 0x10: /* OR */ - case 0x11: /* XOR */ - case 0x12: /* AND */ - case 0x14: /* ADD */ - case 0x15: /* SUB */ - case 0x16: /* MUL */ - if (src[1] >= 0x3f){ - w.err = JITC_ERR_REGNUM; - } - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[2] == 0x3f) { // SUBのみ該当. - if (*src != 0x15){ - w.err = JITC_ERR_REGNUM; - } - reg2 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (reg2 >= 0){ - jitCompA000_storeRegCacheAll(&w); - } - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ - jitCompPutImm32(w.dst, w.r3f); - jitCompPutByte1(w.dst, 0x2b); - jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } -#endif - if (reg1 < 0) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, src[2] * 4); /* MOV(reg0, [EBP+?]); */ - } - if (reg1 >= 0 && reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - if (!(src[0] == 0x10 && src[3] == 0xff)) { - // bugfix: hinted by Iris, 2013.06.26. thanks! - cmp0reg = src[1]; - cmp0lev = 1; - if (src[0] < 0x14){ - cmp0lev = 2; - } - if (src[0] == 0x16){ - cmp0reg = -1; - } - } - if (!(src[0] == 0x10 && src[3] == 0xff)) { -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - if (*src == 0x16 && w.r3f == -1) { - jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } -#if (jitCompA0001_USE_R3F_INCDEC != 0) - if ((*src == 0x14 && w.r3f == 1) || (*src == 0x15 && w.r3f == -1)) { - jitCompPutByte1(w.dst, 0x40 | reg0); /* INC(reg0); */ - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } - if ((*src == 0x15 && w.r3f == 1) || (*src == 0x14 && w.r3f == -1)) { - jitCompPutByte1(w.dst, 0x48 | reg0); /* DEC(reg0); */ - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } -#endif -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= w.r3f && w.r3f <= 0x7f) { - if (*src != 0x16) { - static unsigned char basic_op_table_im8[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; - jitCompPutByte3(w.dst, 0x83, basic_op_table_im8[*src - 0x10] | reg0, w.r3f & 0xff); - } else{ - jitCompPutByte3(w.dst, 0x6b, 0xc0 | reg0 << 3 | reg0, w.r3f & 0xff); - } - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } -#endif - if (reg0 == IA32_REG0_EAX) { - static unsigned char basic_op_table_im32_eax[] = { 0x0d, 0x35, 0x25, 0, 0x05, 0x2d, 0xc0 }; - if (*src == 0x16) { - jitCompPutByte1(w.dst, 0x69); - } - jitCompPutByte1(w.dst, basic_op_table_im32_eax[*src - 0x10]); - } else{ - if (*src != 0x16) { - static unsigned char basic_op_table_im32_reg[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; - jitCompPutByte2(w.dst, 0x81, basic_op_table_im32_reg[*src - 0x10] | reg0); - } - else { - jitCompPutByte2(w.dst, 0x69, 0xc0 | reg0 << 3 | reg0); - } - } - jitCompPutImm32(w.dst, w.r3f); - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - } -#endif - reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (src[3] >= 0x40){ - w.err = JITC_ERR_REGNUM; - } - if (*src != 0x16) { - if (reg1 >= 0) { - static unsigned char basic_op_table_rr[] = { 0x09, 0x31, 0x21, 0, 0x01, 0x29 }; /* op(reg,reg); */ - jitCompPutByte2(w.dst, basic_op_table_rr[*src - 0x10], 0xc0 | reg1 << 3 | reg0); - } else{ - static unsigned char basic_op_table_rm[] = { 0x0b, 0x33, 0x23, 0, 0x03, 0x2b, 0xaf }; /* op(reg,mem); */ - jitCompPutByte1(w.dst, basic_op_table_rm[*src - 0x10]); - jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); - } - } else{ - if (reg1 >= 0) { - jitCompPutByte3(w.dst, 0x0f, 0xaf, 0xc0 | reg0 << 3 | reg1); - } else{ - jitCompPutByte2(w.dst, 0x0f, 0xaf); - jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); - } - } - } - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - break; - - case 0x18: /* SHL */ - case 0x19: /* SAR */ - if (src[1] >= 0x3f){ - w.err = JITC_ERR_REGNUM; - } - if (src[3] >= 0x40){ - w.err = JITC_ERR_REGNUM; - } -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); - if (src[1] >= 0x3f){ - w.err = JITC_ERR_REGNUM; - } - if (reg1 == -1){ - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, src[2] * 4); /* MOV(reg1, [EBP+?]); */ - } else{ - if (reg0 != reg1) { - jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ - } - } - if (*src == 0x18) { - /* SHL(reg0, im8); */ - jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg0, w.r3f); - } - if (*src == 0x19) { - /* SAR(reg0, im8); */ - jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, w.r3f); - } - if (reg0 == IA32_REG0_EAX){ - jitCompA0001_movRxxEax(&w, src[1]); - } - cmp0reg = src[1]; - cmp0lev = 1; - break; - } -#endif - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[2] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(w.dst, w.r3f); - } else{ - jitCompA0001_movEaxRxx(&w, src[2]); - } -#else - jitCompA0001_movEaxRxx(&w, src[2]); -#endif - if (*src == 0x18) { - /* SHL(EAX, CL); */ - jitCompPutByte2(w.dst, 0xd3, 0xe0); - } - if (*src == 0x19) { - /* SAR(EAX, CL); */ - jitCompPutByte2(w.dst, 0xd3, 0xf8); - } - jitCompA0001_movRxxEax(&w, src[1]); - jitCompA000_loadRegCacheAll(&w); // 手抜き. - cmp0reg = src[1]; - cmp0lev = 1; - break; - - case 0x1a: /* DIV */ - case 0x1b: /* MOD */ - if (src[1] >= 0x3f || src[2] >= 0x40 || src[3] >= 0x40){ - w.err = JITC_ERR_REGNUM; - } - jitCompA000_storeRegCacheAll(&w); // 手抜き. -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8 | 1); /* MOV(ECX, ?); */ - jitCompPutImm32(w.dst, w.r3f); - } else{ - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ - } - if (src[2] == 0x3f) { - jitCompPutByte1(w.dst, 0xb8 | 0); /* MOV(EAX, ?); */ - jitCompPutImm32(w.dst, w.r3f); - } else{ - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, src[2] * 4); /* MOV(EAX, [EBP+?]); */ - } -#else - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, src[2] * 4); /* MOV(EAX, [EBP+?]); */ -#endif - jitCompPutByte1(w.dst, 0x99); /* CDQ(); */ - /* ECXがゼロではないことを確認すべき */ - jitCompPutByte2(w.dst, 0xf7, 0xf9); /* IDIV(ECX); */ - if (*src == 0x1a) { - jitCompPutOp_MOV_EBPDisp_GReg(&w, src[1] * 4, IA32_REG0_EAX); - } - if (*src == 0x1b) { - jitCompPutOp_MOV_EBPDisp_GReg(&w, src[1] * 4, IA32_REG2_EDX); - } - jitCompA000_loadRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x1c: /* PLMT0 */ - case 0x1d: /* PLMT1 */ - if (src[1] >= 0x40 || src[2] >= 0x40){ - w.err = JITC_ERR_PREGNUM; - } - if (level < JITC_LV_FASTEST) { - cmp0reg = -1; - if (level < JITC_LV_FASTER) { - // typ が一致していることを確認. - // plsとliveSignが一致していることを確認. - - // preg1はp0 <= p <= p1 を満たしているか?. - // 新しいp0/p1は古いp0?p1に適合しているか?. - - } - } - - case 0x1e: /* PCP */ /* 未完成(p1まで完成) */ - if (src[1] >= 0x40 || src[2] >= 0x40){ - w.err = JITC_ERR_PREGNUM; - } - if (src[2] == 0x3f){ - w.err = JITC_ERR_PREGNUM; - } - if (src[1] != 0x3f) { - /* src[2] == 0xff の場合に対応できてない */ - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32; i += 4) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + i); /* MOV(EAX, [EBP+?]); */ - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - } else { - if (level < JITC_LV_FASTER) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ - jitCompPutByte3(w.dst, 0x83, 0xf8, 0); /* CMP(EAX, 0); */ - jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(w.dst, errfnc - (w.dst + 4)); - /* セキュリティチェックが足りてない!(aliveとか) */ - } - reg0 = IA32_REG0_EAX; - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[2]) + 0); /* MOV(EAX, [EBP+?]); */ - if (level < JITC_LV_FASTER) { - jitCompPutByte1(w.dst, 0x3b); /* CMP(reg0, [EBP+?]); */ - jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[2]) + 8, reg0); /* p0 */ - jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(w.dst, errfnc - (w.dst + 4)); - } - jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ - } - break; - - case 0x1f: /* PCST */ - if (jitCompGetImm32(src + 2) == 0) { - if (level < JITC_LV_FASTER){ - jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 7), 2); - } - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32 - 4; i += 4) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ - if (i == 4) { - jitCompPutByte1(w.dst, 0x0d); /* OR(EAX, ?); */ - jitCompPutImm32(w.dst, 0x80000000); - } - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 28, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - } - if (jitCompGetImm32(src + 7) == 0) { - jitCompA000_storePRegCacheAll(&w); // 手抜き. - for (i = 0; i < 32 - 4; i += 4) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ - if (i == 4) { - jitCompPutByte1(w.dst, 0x25); /* AND(EAX, ?); */ - jitCompPutImm32(w.dst, 0x7fffffff); - } - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - } - if (level < JITC_LV_FASTER) { - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + 28); /* MOV(EAX, [EBP+?]); */ - jitCompPutByte1(w.dst, 0x3d); /* CMP(EAX, ?); */ - jitCompPutImm32(w.dst, debugInfo1); - jitCompPutByte2(w.dst, 0x74, 8); /* JE */ - jitCompPutOp_MOV_EAX_ZERO(w.dst); - jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 0, IA32_REG0_EAX); /* MOV([EBP+?], EAX); (1+1+4) */ - } - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - } - w.err = JITC_ERR_OPECODE; - goto err_w; - - case 0x20: /* CMPE */ - case 0x21: /* CMPNE */ - case 0x22: /* CMPL */ - case 0x23: /* CMPGE */ - case 0x24: /* CMPLE */ - case 0x25: /* CMPG */ - case 0x26: /* TSTZ */ - case 0x27: /* TSTNZ */ - reg0 = jitCompA000_selectRegCache(src[2], IA32_REG0_EAX); - reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); - if (src[1] == 0x3f) { - /* 特殊構文チェック */ - if (w.prefix != 0) { - w.err = JITC_ERR_PREFIX; - goto err_w; - } - if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { - w.err = JITC_ERR_IDIOM; - goto err_w; - } - } - if (reg0 == 0) - jitCompA0001_movEaxRxx(&w, src[2]); -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (src[3] == 0x3f) { -#if (jitCompA0001_OPTIMIZE_CMP != 0) - if ((*src <= 0x25 && w.r3f == 0) || (*src >= 0x26 && w.r3f == -1)) { - i = 0; - if (cmp0reg == src[2]) { - if (cmp0lev >= 1 && (src[0] == 0x20 || src[0] == 0x21 || src[0] == 0x26 || src[0] == 0x27)){ - i = 1; - } - if (cmp0lev >= 2 && (src[0] == 0x22 || src[0] == 0x23 || src[0] == 0x24 || src[0] == 0x25)){ - i = 1; - } - } - if (i == 0) { - jitCompPutByte2(w.dst, 0x85, 0xc0 | reg0 << 3 | reg0); /* TEST(reg0, reg0); */ - } - cmp0reg = src[2]; - cmp0lev = 2; - goto cmpcc1; - } -#endif -#if (jitCompA0001_USE_R3F_IMM8 != 0) - if (-0x80 <= w.r3f && w.r3f <= 0x7f && *src <= 0x25) { - jitCompPutByte3(w.dst, 0x83, 0xf8 | reg0, w.r3f); - goto cmpcc1; - } -#endif - if (reg0 == 0) { - if (*src <= 0x25) { - jitCompPutByte1(w.dst, 0x3d); - } - if (*src >= 0x26) { - jitCompPutByte1(w.dst, 0xa9); - } - } - else { - if (*src <= 0x25) { - jitCompPutByte2(w.dst, 0x81, 0xf8 | reg0); - } - if (*src >= 0x26) { - jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); - } - } - jitCompPutImm32(w.dst, w.r3f); - goto cmpcc1; - } -#endif - if (src[3] >= 0x40){ - w.err = JITC_ERR_PREGNUM; - } - if (reg1 >= 0) { - if (*src <= 0x25) { - jitCompPutByte2(w.dst, 0x39, 0xc0 | reg1 << 3 | reg0); - } - if (*src >= 0x26) { - jitCompPutByte2(w.dst, 0x85, 0xc0 | reg1 << 3 | reg0); - } - } else{ - if (*src <= 0x25) { - jitCompPutByte1(w.dst, 0x3b); - } - if (*src >= 0x26) { - jitCompPutByte1(w.dst, 0x85); - } - jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); - } - cmpcc1: - if (w.err != 0){ - goto err_w; - } - static unsigned char cmpcc_table0[] = { - 0x04, 0x05, 0x0c, 0x0d, 0x0e, 0x0f, 0x04, 0x05, /* CMPcc, TSTcc */ - 0x04, 0x05, 0x02, 0x03, 0x06, 0x07 /* PCMPcc */ - }; -#if (jitCompA0001_USE_R3F_CMPJMP != 0) - if (src[1] == 0x3f) { - /* 特殊構文を利用した最適化 */ - jitCompPutByte2(w.dst, 0x0f, 0x80 | cmpcc_table0[*src - 0x20]); - src += 6; - 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 (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)){ - j = label[i].p - (w.dst + 4); - } - jitCompPutImm32(w.dst, j); -#if (jitCompA0001_OPTIMIZE_JMP != 0) - if (-128 - 4 <= j && j < 0) { - j += 4; - w.dst -= 6; - jitCompPutByte2(w.dst, w.dst[1] ^ 0xf0, j & 0xff); - } -#endif - src += 6; - if (w.err != 0){ - goto err_w; - } - continue; - } -#endif - /* 一般的なJITC */ - reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); - jitCompPutByte3(w.dst, 0x0f, 0x90 | cmpcc_table0[*src - 0x20], 0xc0 | reg0); /* SETcc(BYTE(reg0)); */ - jitCompPutByte3(w.dst, 0x0f, 0xb6, 0xc0 | reg0 << 3 | reg0); /* MOVZX(reg0, BYTE(reg0)); */ - jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ - if (reg0 == 0){ - jitCompA0001_movRxxEax(&w, src[1]); - } - cmp0reg = src[2]; - cmp0lev = 1; - break; - - case 0x28: /* PCMPE */ - case 0x29: /* PCMPNE */ - case 0x2a: /* PCMPL */ - case 0x2b: /* PCMPGE */ - case 0x2c: /* PCMPLE */ - case 0x2d: /* PCMPG */ - if (src[1] == 0x3f) { - /* 特殊構文チェック */ - if (w.prefix != 0) { - w.err = JITC_ERR_PREFIX; - goto err_w; - } - if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { - w.err = JITC_ERR_IDIOM; - goto err_w; - } - } - if (src[2] >= 0x40) { - w.err = JITC_ERR_PREGNUM; - } - jitCompA000_storePRegCacheAll(&w); // 手抜き. - if (src[3] != 0xff){ - jitCompA0001_checkCompPtr(&w, src[2], src[3]); - } - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + 0); /* MOV(EAX, [EBP+?]); */ - if (src[3] != 0xff) { - jitCompPutByte1(w.dst, 0x3b); /* CMP(EAX, [EBP+?]); */ - jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[3]) + 0, 0); - } else{ - /* ヌルポインタとの比較はこれでいいのか?たぶんよくない */ - jitCompPutByte3(w.dst, 0x83, 0xf8, 0x00); /* CMP(EAX, 0); */ - } - cmp0reg = -1; - goto cmpcc1; - - case 0x30: /* talloc(old:F4) */ - case 0x31: /* tfree(old:F5) */ - case 0x32: /* malloc(old:F6) */ - case 0x33: /* mfree(old:F7) */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - - jitCompPutOp_PUSH_Imm8(w.dst, src[3]); - jitCompPutOp_PUSH_Imm8(w.dst, src[2]); - jitCompPutOp_PUSH_Imm8(w.dst, src[1]); - jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); - - switch (*src) { - case 0x30: - j = ((unsigned char *)&funcf4) - (w.dst + 1 + 4); - break; - case 0x31: - j = ((unsigned char *)&funcf5) - (w.dst + 1 + 4); - break; - case 0x32: - j = ((unsigned char *)&funcf6) - (w.dst + 1 + 4); - break; - case 0x33: - j = ((unsigned char *)&funcf7) - (w.dst + 1 + 4); - break; - } - jitCompPutOp_CALL_Relative(w.dst, j); - jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 16); - - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x34: /* data (暫定) */ - // 0 1234 5678 9 - // 34 typ32 len32 data... - // len32 is NOT byte size! - - cmp0reg = -1; - if (w.prefix != 0) { - w.err = JITC_ERR_PREFIX; - goto err_w; - } - int k, tmpData, bitCount, dataWidth; - // kはtyp32 - k = jitCompGetImm32(&src[1]); - dataWidth = jitCompA000_dataWidth(k); - if (lastlabel >= 0 && label[lastlabel].typ == 0){ - //直前のラベルタイプを設定 - label[lastlabel].typ = k; - } - if (k != 1) { - i = jitCompA000_convTyp(k); - if (i < 2 || i > 7) { - w.err = JITC_ERR_BADTYPE; - goto err_w; - } - } - // jはlen32 - j = jitCompGetImm32(&src[5]); - oldsrc = src; - src += 9; - - // srcはdata本体を指す - if (k != 1) { - // 一般データ - bitCount = 7; - while (j > 0) { - if (src >= src1) { - // バイトコードを末端を超えて読もうとした - w.err = JITC_ERR_SRC1; - src = oldsrc; - goto err_w; - } - if (w.dst + 256 > dst1) { - // 書き込み先の残り容量が256Bytesを切った - w.err = JITC_ERR_DST1; - src = oldsrc; - goto err_w; - } - tmpData = 0; - for (k = 0; k < dataWidth; k++) { - // dataWidthビットごとに切り出してtmpDataに入れる - tmpData = tmpData << 1 | ((*src >> bitCount) & 1); - bitCount--; - if (bitCount < 0) { - bitCount = 7; - src++; - } - } - if ((i & 1) == 0 && dataWidth <= 31 && (tmpData >> (dataWidth - 1)) != 0) { - // 符号あり型で、かつtmpDataの符号ビットが1なので、マイナスにする - tmpData -= 1 << dataWidth; - } - if (i == 2 || i == 3) { - // BYTE - jitCompPutByte1(w.dst, tmpData & 0xff); - } - if (i == 4 || i == 5) { - // WORD - jitCompPutByte2(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff); - } - if (i == 6 || i == 7) { - // DWORD - jitCompPutByte4(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff, (tmpData >> 16) & 0xff, (tmpData >> 24) & 0xff); - } - j--; - } - } else{ - // VPtr型 - while (j > 0) { - if (src >= src1) { - // バイトコードを末端を超えて読もうとした - w.err = JITC_ERR_SRC1; - src = oldsrc; - goto err_w; - } - if (w.dst + 256 > dst1) { - // 書き込み先の残り容量が256Bytesを切った - w.err = JITC_ERR_DST1; - src = oldsrc; - goto err_w; - } - i = jitCompGetImm32(src); - src += 4; - if ((flags & JITC_PHASE1) != 0 && w.err == 0) { - // Only in phase1 - if (label[i].opt == 0) { - // ローカルラベルはだめです... - w.err = JITC_ERR_LABELNODEF; - goto err_w; - } - } - jitCompPutImm32(w.dst, (int)label[i].p); - jitCompPutImm32(w.dst, label[i].typ); - jitCompPutImm32(w.dst, (int)label[i].p); - jitCompPutImm32(w.dst, (int)label[i].p1); - jitCompPutImm32(w.dst, 0); /* liveSign */ - jitCompPutImm32(w.dst, envOffset_PTRCTRL); /* pls */ - jitCompPutImm32(w.dst, 0); - jitCompPutImm32(w.dst, 0); - j--; - } - } - if (lastlabel >= 0 && label[lastlabel].p1 < w.dst){ - label[lastlabel].p1 = w.dst; - } - continue; - - case 0x3c: /* ENTER */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutOp_PUSH_Imm8(w.dst, src[6]); - jitCompPutOp_PUSH_Imm8(w.dst, src[5]); - jitCompPutOp_PUSH_Imm8(w.dst, src[4] & 0x0f); - jitCompPutOp_PUSH_Imm8(w.dst, (src[4] >> 4) & 0x0f); - jitCompPutOp_PUSH_Imm8(w.dst, src[3]); - jitCompPutOp_PUSH_Imm8(w.dst, src[2]); - jitCompPutOp_PUSH_Imm8(w.dst, src[1]); - jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); - j = ((unsigned char *)&func3c) - (w.dst + 1 + 4); - jitCompPutOp_CALL_Relative(w.dst, j) - jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 32); - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0x3d: /* LEAVE */ - jitCompA000_storeRegCacheAll(&w); // 手抜き. - jitCompA000_storePRegCacheAll(&w); // 手抜き. - jitCompPutOp_PUSH_Imm8(w.dst, src[6]); - jitCompPutOp_PUSH_Imm8(w.dst, src[5]); - jitCompPutOp_PUSH_Imm8(w.dst, src[4] & 0x0f); - jitCompPutOp_PUSH_Imm8(w.dst, (src[4] >> 4) & 0x0f); - jitCompPutOp_PUSH_Imm8(w.dst, src[3]); - jitCompPutOp_PUSH_Imm8(w.dst, src[2]); - jitCompPutOp_PUSH_Imm8(w.dst, src[1]); - jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); - j = ((unsigned char *)&func3d) - (w.dst + 1 + 4); - jitCompPutOp_CALL_Relative(w.dst, j) - jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 32); - jitCompA000_loadRegCacheAll(&w); // 手抜き. - jitCompA000_loadPRegCacheAll(&w); // 手抜き. - cmp0reg = -1; - break; - - case 0xfe: /* remark */ - if (src[1] == 0x01 && src[2] == 0x00) { - // DBGINFO1 - if (level <= JITC_LV_SLOWER) { - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); - jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); - } - } - if (src[1] == 0x01 && src[2] == 0x03) { - // DBGINFO1CLR - if (level <= JITC_LV_SLOWER) { - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, -1); - jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); - } - } - if (src[1] == 0x05 && src[2] == 0x00) { - // DBGINFO0 - if (level <= JITC_LV_SLOWEST) { - debugInfo0 = jitCompGetImm32(src + 3); - jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo0); - jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO0, IA32_REG0_EAX); - } - } - break; - - default: - w.err = JITC_ERR_OPECODE; - goto err_w; - } - if (w.err != 0){ - goto err_w; - } - jitCompA0001_fixPrefix(&w); - if (w.err != 0) { - goto err_w; - } - - if(*src != 0x00 && *src != 0x01 && *src != 0x34){ - DEBUGCode(&w, 315315); - } - - src += jitCompCmdLen(src); - } - if (enter0 != NULL) { - j = w.dst - (enter0 + 4); - enter0[0] = j & 0xff; - enter0[1] = (j >> 8) & 0xff; - enter0[2] = (j >> 16) & 0xff; - enter0[3] = (j >> 24) & 0xff; - } - if ((flags & JITC_NOSTARTUP) == 0) { - jitCompA000_storeRegCacheAll(&w); - jitCompA000_storePRegCacheAll(&w); - jitCompPutOp_POPAD(w.dst); - } - if ((flags & JITC_PHASE1) != 0){ - return w.dst - dst00; - } - return 0; - -err_w: - if ((w.err & JITC_ERR_PHASE0ONLY) != 0) { - if ((flags & JITC_PHASE1) == 0){ - w.err &= ~JITC_ERR_PHASE0ONLY; - } - } - if (w.err == (JITC_ERR_MASK & JITC_ERR_REGNUM)) errmsg = "reg-number error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_DST1)) errmsg = "dst1 error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_OPECODE)) errmsg = "opecode error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNUM)) errmsg = "label number too large"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELREDEF)) errmsg = "label redefine"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIX)) { errmsg = "prefix redefine"; w.dst -= 2; } - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNODEF)) errmsg = "label not defined"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELTYP)) errmsg = "label type error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_IDIOM)) errmsg = "idiom error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_PREGNUM)) errmsg = "preg-number error"; - if (w.err == (JITC_ERR_MASK & JITC_ERR_SRC1)) errmsg = "src1 error"; - 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); - for (i = 0; i < 16; i++) - fprintf(stderr, "%02X ", src[i]); - static char *table[0x30] = { - "NOP", "LB", "LIMM", "PLIMM", "CND", "??", "??", "??", - "LMEM", "SMEM", "PLMEM", "PSMEM", "LEA", "??", "PADD", "PDIF", - "CP/OR", "XOR", "AND", "??", "ADD", "SUB", "MUL", "??", - "SHL", "SAR", "DIV", "MOD", "PLMT0", "PLMT1", "PCP", "PCST", - "CMPE", "CMPNE", "CMPL", "CMPGE", "CMPLE", "CMPG", "TSTZ", "TSTNZ", - "PCMPE", "PCMPNE", "PCMPL", "PCMPGE", "PCMPLE", "PCMPG", "??", "EXT" }; - errmsg = "??"; - if (*src < 0x30) errmsg = table[*src]; - fprintf(stderr, "(%s)\n", errmsg); - } - return -1; -} - -unsigned char *jitCompCallFunc(unsigned char *dst, void *func) -{ - //この関数の中では結局w->dstしか参照していない - struct JitCompWork w; - w.dst = dst; - jitCompA000_storeRegCacheAll(&w); - jitCompA000_storePRegCacheAll(&w); - jitCompPutOp_PUSHAD(w.dst); - jitCompPutOp_PUSH_GReg(w.dst, IA32_REG0_EAX); /* for 16Byte-align(Mac OSX) */ - jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); - - int j = ((unsigned char *)func) - (w.dst + 1 + 4); - jitCompPutOp_CALL_Relative(w.dst, j); - - jitCompPutOp_POP_GReg(w.dst, IA32_REG0_EAX); - jitCompPutOp_POP_GReg(w.dst, IA32_REG0_EAX); /* for 16Byte-align (Mac OSX) */ - jitCompPutOp_POPAD(w.dst); - jitCompA000_loadRegCacheAll(&w); - jitCompA000_loadPRegCacheAll(&w); - jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(0x30) + 0); - - jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ - return w.dst; -} - -unsigned char *jitCompInit(unsigned char *dst) -{ - errfnc = dst; - return jitCompCallFunc(dst, &errHndl); -} - -void jitcRunBinary(void (*bin)(char *), HOSECPU_RuntimeEnvironment *env) -{ - (*bin)(((char *)env) + jitCompA0001_EBP128); /* サイズを節約するためにEBPをjitCompA0001_EBP128バイトずらす */ - return; -} - -void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int i, *pi; - 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++){ - pi[i] = r->ireg[i]; - } - pp = (void *)r->junkStack; - r->junkStack += p1 * 32; - for (i = 0; i < p1; i++){ - //pp[i] = r->preg[i]; - PRegCopy(&pp[i], &r->preg[i]); - // - } - pp = (void *)r->junkStack; - r->junkStack += 32; - //*pp = r->preg[0x30]; - PRegCopy(pp, &r->preg[0x30]); - // - pi = (void *)r->junkStack; - r->junkStack += 4; - *pi = opt << 16 | r1 << 8 | p1; - for (i = 0; i < lenR; i++){ - r->ireg[r0 + i] = r->ireg[0x30 + i]; - } - for (i = 0; i < lenP; i++){ - r->preg[p0 + i] = r->preg[0x31 + i]; - } - return; -} - -void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) -{ - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - int i; - r->junkStack -= 4; - r->junkStack -= 32; - HOSECPU_PointerRegisterEntry *pp = (void *)r->junkStack; - - //r->preg[0x30] = *pp; - PRegCopy(&r->preg[0x30], pp); - // - r->junkStack -= p1 * 32; pp = (void *)r->junkStack; - for (i = 0; i < p1; i++){ - //r->preg[i] = pp[i]; - PRegCopy(&r->preg[i], &pp[i]); - // - } - r->junkStack -= r1 * 4; int *pi = (void *)r->junkStack; - for (i = 0; i < r1; i++){ - r->ireg[i] = pi[i]; - } - return; -} - -void funcf4(char *ebp, int pxx, int typ, int len) -{ - 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 *p = r->junkStack; - if (r->junkStack + width * r->ireg[len] + 256 > r->junkStack1){ - (*(r->errHndl))(r); - } - r->junkStack += width * r->ireg[len]; - r->preg[pxx].p = p; - r->preg[pxx].typ = r->ireg[typ]; - r->preg[pxx].p0 = p; - r->preg[pxx].p1 = (void *)r->junkStack; - int *pi = (int *)r->junkStack; - *pi = width * r->ireg[len]; - r->junkStack += sizeof (int); - if (r->ireg[typ] == 1) { - int i, i1 = (width * r->ireg[len]) >> 2; - pi = p; - for (i = 0; i < i1; i++){ - pi[i] = 0; - } - } - return; -} - -void funcf5(char *ebp, int pxx, int typ, int len) -{ - // pxxはダミーで参照されない - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - r->junkStack -= sizeof (int); - int *pi = (int *)r->junkStack; - r->junkStack -= *pi; -#if 0 - int width = jitCompA000_dataWidth(r->ireg[typ]); - void *p = r->junkStack; - r->junkStack -= width * r->ireg[len]; -#endif - return; -} - -void funcf6(char *ebp, int pxx, int typ, int len) -{ - 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 *p = malloc(width * r->ireg[len]); - r->preg[pxx].p = p; - r->preg[pxx].typ = r->ireg[typ]; - r->preg[pxx].p0 = p; - r->preg[pxx].p1 = (unsigned char *)p + width * r->ireg[len]; - if (r->ireg[typ] == 1) { - int i, i1 = (width * r->ireg[len]) >> 2, *pi; - pi = p; - for (i = 0; i < i1; i++){ - pi[i] = 0; - } - for (i = 1; i < i1; i += 8){ - pi[i] |= -1; - } - } - return; -} - -void funcf7(char *ebp, int pxx, int typ, int len) -{ - // typとlenはダミーで参照されない - HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); - free(r->preg[pxx].p); - return; -} - -void errHndl(HOSECPU_RuntimeEnvironment *r) -{ - r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - jitCompA0001_EBP128); - (*(r->errHndl))(r); - // ここに帰ってきてはいけない. -} - -/* - * jitcの出力コードをひとまとめにする関数を作成しその中身をjitCompile()で生成 - * - * qq : 出力バイナリの書き込み位置のアドレスへの参照(書き込み位置を呼び出しに反映させるため参照渡しにする) - * q1 : 出力バイナリの書き込み位置のアドレスの最大値 - * p0 : (*.ose)バイナリの読み込み位置のアドレス(ヘッダ部除去済) - * p1 : (*.ose)バイナリの読み込み位置の取りうる最大値 - * (ただし、「確保したメモリ」の最大値なのでこれより手前にゴミデータが入っているかもしれない) - * ret=1 : ヘッダのエラー - * ret=2 : jitコンパイルエラー - */ -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; - int i; - - if (p0[0] != 0x05 || p0[1] != SIGN1){ - // OSECPUのヘッダ (05E1) を確認 - return 1; - } - - jitCompPutOp_PUSH_GReg(q, IA32_REG5_EBP); - - *q++ = 0x8b; *q++ = 0x6c; *q++ = 0x24; *q++ = 0x08; /* MOV(EBP,[ESP+8]); */ - - 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 (i < 0){ - return 2; - } - q += i; - - jitCompPutOp_POP_GReg(q, IA32_REG5_EBP); - *q++ = 0xc3; /* RET(); */ - *qq = q; - return 0; -} - -#if (USE_DEBUGGER != 0) - -int dbgrGetRegNum(const char *p) -{ - int i, j, r = -1; - if (p[2] <= ' ') { - i = p[0] - '0'; - j = p[1] - '0'; - if (i > 9){ - i -= 'A' - '0' - 10; - } - if (j > 9){ - j -= 'A' - '0' - 10; - } - if (0 <= i && i <= 15 && 0 <= j && j <= 15){ - r = i << 4 | j; - } - } - return r; -} - -void dbgrMain(HOSECPU_RuntimeEnvironment *r) -{ - if (r->dbgr == 0){ - return; - } - for (;;) { - char cmd[64], *p; - int i, j, k; - - printf("\ndbgr>"); - p = fgets(cmd, 64, stdin); - if (p == NULL){ - break; - } - if (cmd[0] == '\0'){ - continue; - } - if (cmd[0] == 'q' && cmd[1] <= ' '){ - break; - } - if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '\0') { - p = &cmd[2]; - 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]); - } else{ - puts("register name error"); - } - continue; - } - if (*p == 'P') { - i = dbgrGetRegNum(p + 1); - if (0 <= i && i <= 0x3f) { - p = "invalid"; - if (0 <= r->preg[i].typ && r->preg[i].typ <= 0x15) { - 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", - "T_SINT1", "T_UINT1", "T_SINT12", "T_UINT12", - "T_SINT20", "T_UINT20", "T_SINT24", "T_UINT24", - "T_SINT28", "T_UINT28" - }; - p = typName[r->preg[i].typ]; - } - 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); - k = (r->preg[i].p - r->preg[i].p0) / j; - printf(" pos = 0x%08X = %d\n", k, k); - } - else { - puts(" null pointer"); - } - } - else - puts("register name error"); - continue; - } - } - puts("command error"); - } - return; -} - -#endif - - +#include "osecpu.h" +#include "jitc.h" + +#if (JITC_ARCNUM == 0x0001) +// +// for x86-32bit +// + +// F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない. +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) +{ + // For IA-32 (x86, 32-bit) + // 本来ならこのレイヤでは文法チェックしない + // + // dst : 現在の書き込みアドレス。 + // dst1 : 書き込みアドレスの最大値 + // src : 現在の読み込みアドレス(ヘッダ部は飛ばしてある + // src1 : 読み込みアドレスの最大値 + // src0 : 読み込みバイナリのアドレス + struct JitCompWork w; + 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) { + jitCompPutOp_PUSHAD(w.dst); + // Load cache + jitCompA000_loadRegCacheAll(&w); + jitCompA000_loadPRegCacheAll(&w); + } + if (level <= JITC_LV_SLOWER) { + // env.debugInfo0 <- 0; + // env.debugInfo1 <- debugInfo1; + jitCompPutOp_MOV_EAX_ZERO(w.dst); + jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO0, IA32_REG0_EAX); + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); + jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); + } + while (src < src1) { + w.prefix = 0; //0x04 CND 命令で変更される + if (w.dst + 256 > dst1) { + // 書き込み領域が残り256バイト未満ならエラー + w.err = JITC_ERR_DST1; + goto err_w; + } + timecount++; + if (timecount >= 64) { + timecount -= 64; + /* 未完成(timeoutチェックコードを入れる) */ + } +#if ENABLE_DEBUG_CODE != 0 + if(*src != 0x00 && *src != 0x01 && *src != 0x34){ + + DEBUGCode(&w, *src); + } +#endif + prefix_continue: + // CND命令コンパイル後ここに戻る + switch (*src) { + case 0x00: + // NOP + if (w.prefix != 0) { + // 「条件付きでNOPを実行」するなんて、矛盾している! + w.err = JITC_ERR_PREFIX; + goto err_w; + } + break; + + case 0x01: + // LB : ラベル設置命令。(6byte) + // ・prefex = 1にする + // ・timecount++し、timecountのチェックをする。 + // ・ラベル位置を登録する。 + // ・割り込みがある場合、このタイミングで割り込みを発生させる。 + // Encode: + // 0 1 2345 + // 01 opt imm32 + // + if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { + //beginFunc()中のLB + // LB命令の後に0x3C命令・・・beginFunc() + enter0 = w.dst; + jitCompPutOp_JMPnear(w.dst, 0); + } + + if (src[6] == 0x34) { + // 後続命令はDATA + // なので、DATA部分をJMPですっとばすコードを生成 + // DAT_SA0(label, typ32, length) ・・・メモリ確保命令 + + i = jitCompGetImm32(&src[6 + 1]); // type32 を取得 + j = 32; + + if (i != 1) { + i = jitCompA000_convTyp(i); + j = 0; + switch (i >> 1) { + case 1: + j = 1; + break; + case 2: + j = 2; + break; + case 3: + j = 4; + break; + } + } + // jはデータサイズになる + j *= jitCompGetImm32(&src[6 + 5]); // len32 + if (j <= 0){ + w.err = JITC_ERR_BADTYPE; + } + // DATA部分を飛び越すジャンプ + tmp_ucp = w.dst; + jitCompPutOp_JMPnear(w.dst, j); + +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (j < 127 - jitCompA0001_OPTIMIZE_ALIGN) { + //飛び先が十分近いので + // 今書いたのはなかったことにして、 + w.dst -= 5; + // よりサイズの小さな書き方にする + jitCompPutOp_JMPshort(w.dst, j); + } +#endif + } +#if (jitCompA0001_OPTIMIZE_ALIGN != 0) + // アラインを jitCompA0001_OPTIMIZE_ALIGNにそろえる + + i = ((int)w.dst + 1) & (jitCompA0001_OPTIMIZE_ALIGN - 1); /* ALIGNで割ったあまりを計算 */ + i = jitCompA0001_OPTIMIZE_ALIGN - i; + if (i == 1) { jitCompPutByte1(w.dst, 0x90); j += i; } /* NOP(); */ + if (i == 2) { jitCompPutByte2(w.dst, 0x89, 0xc0); j += i; } /* MOV(EAX, EAX); */ + if (i == 3) { jitCompPutByte3(w.dst, 0x8d, 0x76, 0x00); j += i; } /* LEA(ESI, [ESI+0]); */ + if (i == 4) { jitCompPutByte4(w.dst, 0x8d, 0x74, 0x26, 0x00); j += i; } /* LEA(ESI, [ESI*1+0]); */ + if (i == 5) { jitCompPutByte1(w.dst, 0x0d); jitCompPutImm32(w.dst, 0); j += i; } /* OR(EAX, 0); */ + if (i == 6) { jitCompPutByte2(w.dst, 0x8d, 0xb6); jitCompPutImm32(w.dst, 0); j += i; } /* LEA(ESI, [ESI+0]); */ + if (i == 7) { jitCompPutByte3(w.dst, 0x8d, 0xb4, 0x26); jitCompPutImm32(w.dst, 0); j += 7; } /* LEA(ESI, [ESI*1+0]); */ +#endif + if (src[6] == 0x34) { + // 後続命令はDATA + // パディングに合わせて一個前の相対ジャンプを修正 + tmp_ucp[1] = j & 0xff; + if (*tmp_ucp == 0xe9) { + // Near jump so imm is DWORD + tmp_ucp[2] = (j >> 8) & 0xff; + tmp_ucp[3] = (j >> 16) & 0xff; + tmp_ucp[4] = (j >> 24) & 0xff; + } + } + if ((flags & JITC_PHASE1) == 0) { // Phase 0ならば + i = jitCompGetLabelNum(&w, src + 2); + if (label[i].opt != 0 && w.err == 0) { + w.err = JITC_ERR_LABELREDEF; // すでに同じ値のラベルがあればエラー + goto err_w; + } + if (w.prefix != 0) { // CND命令の直後にラベルは設置できない + w.err = JITC_ERR_PREFIX; + goto err_w; + } + label[i].opt = src[1] + 1; + label[i].typ = 0; /* TYP_CODE */ + label[i].p = w.dst; + label[i].p1 = w.dst + 1; + lastlabel = i; + } + cmp0reg = -1; + timecount = 0; + /* 未完成(timeoutチェックコードを入れる) */ + break; + + case 0x02: + // LIMM : 定数即値代入命令(6byte) + // Encode: + // 0 1 2345 + // 02 reg0R imm32 + // + // reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 + + if (src[1] == 0x3f && w.prefix != 0){ + // CND命令の直後でR3Fを書き換えるなんて変だよね + w.err = JITC_ERR_PREFIX; + } + +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[1] == 0x3f) { + // R3Fへの代入は例外で、 w.r3f を使用 + w.r3f = jitCompGetImm32(src + 2); + break; + } +#endif + i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得 + /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */ + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + +#if (jitCompA0001_OPTIMIZE_MOV != 0) + // size optimization + // MOV reg, 0 -> XOR reg, reg + if (i == 0) { + jitCompPutOp_XOR_GReg_GReg(w.dst, reg0, reg0); + jitCompA0001_movRxxEax(&w, src[1]); + break; + } +#endif + /* reg0 のレジスタに対応したMOV命令を発行 */ + jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, i); + + if (reg0 == 0){ + // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 + jitCompA0001_movRxxEax(&w, src[1]); + } + + break; + + case 0x03: /* 未完成(plsまで対応) */ + // PLIMM : ラベル番号代入命令(6byte) + // Encode: + // 0 1 2345 + // 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) { + // プログラムカウンタに TYP_CODEでない値は代入できない + w.err = JITC_ERR_LABELTYP; + goto err_w; + } + } + if (src[1] == 0x3f) { + // プログラムカウンタへの代入 + if (w.prefix == 0) { + // CND命令による条件付きでなければ、即座に移動 + jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ + } else { + // 直前はCND命令。 + + /* + * CND命令 + * 1 2 + * 04 reg0R + * + * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd + */ + + // Jccの条件変更 + // 0F 75 + 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)) // label番号iが確保されているか、Phase 1なら + j = label[i].p - (w.dst + 4); // j はとび先の相対番地 + jitCompPutImm32(w.dst, j); // JMP もしくは JZ 命令のアドレス部を記述 +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (-128 - 3 <= j && j < 0) { + if (w.dst[-5] == 0xe9) { + j += 3; + w.dst -= 5; + jitCompPutByte1(w.dst, 0xeb); /* JMP(?); */ + } else { + j += 4; + w.dst -= 6; + jitCompPutByte1(w.dst, w.dst[1] ^ 0xf0); + } + jitCompPutByte1(w.dst, j & 0xff); + } +#endif + } else { // プログラムカウンタ以外への代入 + // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 + reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); + // ラベルのパスを各レジスタに代入 + jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, (int)label[i].p); + // レジスタへの代入をメモリでエミュレーションする場合は、スタックに書き込む。 + if (reg0 == 0){ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 0, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + + if (level < JITC_LV_FASTEST) { + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 8, reg0); /* p0 */ + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, label[i].typ); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 4, IA32_REG0_EAX); /* typ */ + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, (int)label[i].p1); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 12, IA32_REG0_EAX); /* p1 */ + jitCompPutOp_MOV_EAX_ZERO(w.dst); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 16, IA32_REG0_EAX); /* liveSign */ + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, envOffset_PTRCTRL); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 20, IA32_REG0_EAX); /* pls */ + } + } + break; + + case 0x04: + // CND (prefix) + // 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 + + if (src[1] >= 0x40){ + // R00-R3F 以外のレジスタは比較対象にできない + w.err = JITC_ERR_REGNUM; + goto err_w; + } + + // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す + reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */); + + /* TEST命令を発行 */ + if (reg0 < 0) { + // 比較対象のレジスタはメモリ上にある + jitCompPutByte1(w.dst, 0xf7); /* TEST = 1111 011w : mod 000 r/m : immediate data */ + jitCompPutModRM_Disp_BaseEBP(&w, src[1] * 4, 0); + } else { + // 比較対象はキャッシュレジスタ上にある + jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); /* TEST = 1111 011w : 11 000 reg : immediate data */ + } + jitCompPutImm32(w.dst, 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; + goto prefix_continue; + + case 0x08: /* LMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i == 0x0001){ + w.err = JITC_ERR_BADTYPE; + } + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 0); // read + cmp0reg = -1; + } + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); + if (reg0 != IA32_REG0_EAX && reg1 == IA32_REG2_EDX){ + reg1 = IA32_REG0_EAX; + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_storeRegCacheEdx(&w); + } + if (reg1 <= 3 /* EAX, EDX */){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); + } + if (level < JITC_LV_FASTER){ + jitCompA0001_checkLimit(&w, reg1, src[6]); + } + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + switch (i) { + case 0x0002: + jitCompPutByte3(w.dst, 0x0f, 0xbe, reg0 << 3 | reg1); /* MOVSX(reg0,BYTE [reg1]); */ + break; + case 0x0003: + jitCompPutByte3(w.dst, 0x0f, 0xb6, reg0 << 3 | reg1); /* MOVZX(reg0,BYTE [reg1]); */ + break; + case 0x0004: + jitCompPutByte3(w.dst, 0x0f, 0xbf, reg0 << 3 | reg1); /* MOVSX(reg0,WORD [reg1]); */ + break; + case 0x0005: + jitCompPutByte3(w.dst, 0x0f, 0xb7, reg0 << 3 | reg1); /* MOVZX(reg0,WORD [reg1]); */ + break; + case 0x0006: + case 0x0007: + jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ + break; + default: + w.err = JITC_ERR_BADTYPE; + } + if (reg0 == IA32_REG0_EAX){ + jitCompA0001_movRxxEax(&w, src[1]); + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_loadRegCacheEdx(&w); + } + break; + + case 0x09: /* SMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i == 0x0001){ + w.err = JITC_ERR_BADTYPE; + } + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 1); // write + cmp0reg = -1; + } + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); + if (reg0 != IA32_REG0_EAX && reg1 == IA32_REG2_EDX){ + reg1 = IA32_REG0_EAX; + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_storeRegCacheEdx(&w); + } + if (reg1 <= 3 /* EAX, EDX */){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6]) + 0); /* MOV(reg1, [EBP+?]); */ + } + if (level < JITC_LV_FASTER){ + jitCompA0001_checkLimit(&w, reg1, src[6]); + } + if (reg0 == IA32_REG0_EAX){ + jitCompA0001_movEaxRxx(&w, src[1]); + } + /* 値の範囲チェック */ + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + switch (i) { + case 0x0002: + case 0x0003: + jitCompPutByte2(w.dst, 0x88, reg0 << 3 | reg1); /* MOV([reg1], BYTE(reg0)); */ + break; + case 0x0004: + case 0x0005: + jitCompPutByte3(w.dst, 0x66, 0x89, reg0 << 3 | reg1); /* MOV([reg1], WORD(reg0)); */ + break; + case 0x0006: + case 0x0007: + jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ + break; + default: + w.err = JITC_ERR_BADTYPE; + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_loadRegCacheEdx(&w); + } + break; + + case 0x0a: /* PLMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i != 0x0001){ + w.err = JITC_ERR_BADTYPE; + } + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 0); // read + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); + // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) /* これをやってはいけない!(by K, 2013.08.02) */ + // reg1 = 0; /* EAX */ + if (reg0 == reg1 && reg0 != 0) { + // bugfix: hinted by yao, 2013.09.14. thanks! + jitCompA000_storePRegCacheAll(&w); + reg1 = IA32_REG2_EDX; + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_storeRegCacheEdx(&w); + } + if (reg1 <= 3 /* EAX, EDX */){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); /* MOV(reg1, [EBP+?]); */ + } + if (level < JITC_LV_FASTER){ + jitCompA0001_checkLimit(&w, reg1, src[6]); + } + jitCompPutByte2(w.dst, 0x8b, reg0 << 3 | reg1); /* MOV(reg0, [reg1]); */ + if (reg0 == IA32_REG0_EAX){ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]), IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + for (i = 4; i < 32; i += 4) { + jitCompPutByte3(w.dst, 0x8b, 0x40 | reg1, i); /* MOV(EAX, [reg1+?]); */ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + if (reg1 == IA32_REG2_EDX){ + jitCompA000_loadRegCacheEdx(&w); + } + break; + + case 0x0b: /* PSMEM */ /* 完成 */ + i = jitCompGetImm32(src + 2); + if (i != 0x0001) w.err = JITC_ERR_BADTYPE; + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType(&w, src[6], i, 1); // write + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectPRegCache(src[6], IA32_REG2_EDX); + /* これをやってはいけない!(by K, 2013.08.02) */ + // if (reg0 != 0 /* EAX */ && reg1 == 2 /* EDX */) + // reg1 = 0; /* EAX */ + if (reg1 == IA32_REG2_EDX){ + jitCompA000_storeRegCacheEdx(&w); + } + if (reg1 <= 3 /* EAX, EDX */){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg1, PRegOffset(src[6])); /* MOV(reg1, [EBP+?]); */ + } + if (level < JITC_LV_FASTER){ + jitCompA0001_checkLimit(&w, reg1, src[6]); + } + if (reg0 == IA32_REG0_EAX){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[1])); /* MOV(reg0, [EBP+?]); */ + } + jitCompPutByte2(w.dst, 0x89, reg0 << 3 | reg1); /* MOV([reg1], reg0); */ + for (i = 4; i < 32; i += 4) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[1]) + i); /* MOV(EAX, [EBP+?]); */ + jitCompPutByte3(w.dst, 0x89, 0x40 | reg1, i); /* MOV([reg1+?], EAX); */ + } + if (reg1 == IA32_REG2_EDX) + jitCompA000_loadRegCacheEdx(&w); + break; + + case 0x0e: /* PADD */ /* 完成 */ + if (level < JITC_LV_FASTER) { + jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 2), 2); // other, aliveテストはとりあえずしない. + cmp0reg = -1; + } + reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectPRegCache(src[6], -1 /* mem */); + if (reg1 < 0 /* mem */){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[6])); /* MOV(reg0, [EBP+?]); */ + } + if (reg1 >= 0 && reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + i = jitCompGetImm32(src + 2); + j = -1; + if (i == 1){ + j = 5; /* 32 */ + } else { + i = jitCompA000_convTyp(i); + if (0x0002 <= i && i <= 0x0007){ + j = (i - 0x0002) >> 1; + } + } + if (j < 0) { + w.err = JITC_ERR_BADTYPE; + goto err_w; + } +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[7] == 0x3f) { + j = w.r3f << j; +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= j && j <= 0x7f) { +#if (jitCompA0001_USE_R3F_INCDEC != 0) + if (j == 1) { + /* INC */ + jitCompPutByte1(w.dst, 0x40 | reg0); + goto padd1; + } + if (j == -1) { + /* DEC */ + jitCompPutByte1(w.dst, 0x48 | reg0); + goto padd1; + } +#endif + /* ADD(reg0, im8); */ + jitCompPutByte3(w.dst, 0x83, 0xc0 | reg0, j & 0xff); + goto padd1; + } +#endif + if (reg0 == 0) { + jitCompPutByte1(w.dst, 0x05); /* ADD(reg0, ?); */ + } else { + jitCompPutByte2(w.dst, 0x81, 0xc0 | reg0); /* ADD(reg0, ?); */ + } + jitCompPutImm32(w.dst, j); + goto padd1; + } +#endif + if (src[7] >= 0x40){ + w.err = JITC_ERR_REGNUM; + } + if (j == 0) { + reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); + if (reg1 >= 0) { + jitCompPutByte2(w.dst, 0x01, 0xc0 | reg1 << 3 | reg0); /* ADD(reg0, reg1); */ + } else { + jitCompPutByte1(w.dst, 0x03); /* ADD(reg0, [EBP+?]); */ + jitCompPutModRM_Disp_BaseEBP(&w, src[7] * 4, reg0); + } + } + else { + reg1 = jitCompA000_selectRegCache(src[7], -1 /* mem */); + reg2 = IA32_REG2_EDX; + jitCompA000_storeRegCacheEdx(&w); + if (reg1 < 0){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg2, src[7] * 4); /* MOV(reg2, [EBP+?]); */ + } + if (reg1 >= 0 && reg1 != reg2) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg2); /* MOV(reg2, reg1); */ + } + jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg2, j); /* SHL(reg2, ?); */ + jitCompPutByte2(w.dst, 0x01, 0xc0 | reg2 << 3 | reg0); /* ADD(reg0, reg2); */ + jitCompA000_loadRegCacheEdx(&w); + } +#if (jitCompA0001_USE_R3F_IMM32 != 0) + padd1: +#endif + if (reg0 == IA32_REG0_EAX){ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]), reg0); /* MOV([EBP+?], reg0); */ + } + if (src[1] != src[6]) { + for (i = 4; i < 32; i += 4) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + } + cmp0reg = -1; + break; + + case 0x0f: /* PDIF */ /* 未完成 */ + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompA0001_checkCompPtr(&w, src[6], src[7]); + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[6])); /* MOV(reg0, [EBP+?]); */ + jitCompPutByte1(w.dst, 0x2b); /* SUB(EAX, [EBP+?]); */ + jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[7]) + 0, reg0); + i = jitCompA000_convTyp(jitCompGetImm32(src + 2)); + j = -1; + if (0x0002 <= i && i <= 0x0007){ + j = (i - 0x0002) >> 1; + } + if (j < 0) { + w.err = JITC_ERR_BADTYPE; + goto err_w; + } + if (j > 0) { + jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, j); /* SAR(reg0,?); */ + } + if (reg0 == IA32_REG0_EAX){ + jitCompA0001_movRxxEax(&w, src[1]); + } + cmp0reg = src[1]; + cmp0lev = 1; + break; + + case 0x10: /* OR */ + case 0x11: /* XOR */ + case 0x12: /* AND */ + case 0x14: /* ADD */ + case 0x15: /* SUB */ + case 0x16: /* MUL */ + if (src[1] >= 0x3f){ + w.err = JITC_ERR_REGNUM; + } + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[2] == 0x3f) { // SUBのみ該当. + if (*src != 0x15){ + w.err = JITC_ERR_REGNUM; + } + reg2 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (reg2 >= 0){ + jitCompA000_storeRegCacheAll(&w); + } + jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); */ + jitCompPutImm32(w.dst, w.r3f); + jitCompPutByte1(w.dst, 0x2b); + jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } +#endif + if (reg1 < 0) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, src[2] * 4); /* MOV(reg0, [EBP+?]); */ + } + if (reg1 >= 0 && reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + if (!(src[0] == 0x10 && src[3] == 0xff)) { + // bugfix: hinted by Iris, 2013.06.26. thanks! + cmp0reg = src[1]; + cmp0lev = 1; + if (src[0] < 0x14){ + cmp0lev = 2; + } + if (src[0] == 0x16){ + cmp0reg = -1; + } + } + if (!(src[0] == 0x10 && src[3] == 0xff)) { +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + if (*src == 0x16 && w.r3f == -1) { + jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } +#if (jitCompA0001_USE_R3F_INCDEC != 0) + if ((*src == 0x14 && w.r3f == 1) || (*src == 0x15 && w.r3f == -1)) { + jitCompPutByte1(w.dst, 0x40 | reg0); /* INC(reg0); */ + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } + if ((*src == 0x15 && w.r3f == 1) || (*src == 0x14 && w.r3f == -1)) { + jitCompPutByte1(w.dst, 0x48 | reg0); /* DEC(reg0); */ + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } +#endif +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= w.r3f && w.r3f <= 0x7f) { + if (*src != 0x16) { + static unsigned char basic_op_table_im8[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; + jitCompPutByte3(w.dst, 0x83, basic_op_table_im8[*src - 0x10] | reg0, w.r3f & 0xff); + } else{ + jitCompPutByte3(w.dst, 0x6b, 0xc0 | reg0 << 3 | reg0, w.r3f & 0xff); + } + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } +#endif + if (reg0 == IA32_REG0_EAX) { + static unsigned char basic_op_table_im32_eax[] = { 0x0d, 0x35, 0x25, 0, 0x05, 0x2d, 0xc0 }; + if (*src == 0x16) { + jitCompPutByte1(w.dst, 0x69); + } + jitCompPutByte1(w.dst, basic_op_table_im32_eax[*src - 0x10]); + } else{ + if (*src != 0x16) { + static unsigned char basic_op_table_im32_reg[] = { 0xc8, 0xf0, 0xe0, 0, 0xc0, 0xe8 }; + jitCompPutByte2(w.dst, 0x81, basic_op_table_im32_reg[*src - 0x10] | reg0); + } + else { + jitCompPutByte2(w.dst, 0x69, 0xc0 | reg0 << 3 | reg0); + } + } + jitCompPutImm32(w.dst, w.r3f); + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + } +#endif + reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (src[3] >= 0x40){ + w.err = JITC_ERR_REGNUM; + } + if (*src != 0x16) { + if (reg1 >= 0) { + static unsigned char basic_op_table_rr[] = { 0x09, 0x31, 0x21, 0, 0x01, 0x29 }; /* op(reg,reg); */ + jitCompPutByte2(w.dst, basic_op_table_rr[*src - 0x10], 0xc0 | reg1 << 3 | reg0); + } else{ + static unsigned char basic_op_table_rm[] = { 0x0b, 0x33, 0x23, 0, 0x03, 0x2b, 0xaf }; /* op(reg,mem); */ + jitCompPutByte1(w.dst, basic_op_table_rm[*src - 0x10]); + jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); + } + } else{ + if (reg1 >= 0) { + jitCompPutByte3(w.dst, 0x0f, 0xaf, 0xc0 | reg0 << 3 | reg1); + } else{ + jitCompPutByte2(w.dst, 0x0f, 0xaf); + jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); + } + } + } + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + break; + + case 0x18: /* SHL */ + case 0x19: /* SAR */ + if (src[1] >= 0x3f){ + w.err = JITC_ERR_REGNUM; + } + if (src[3] >= 0x40){ + w.err = JITC_ERR_REGNUM; + } +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + reg1 = jitCompA000_selectRegCache(src[2], -1 /* mem */); + if (src[1] >= 0x3f){ + w.err = JITC_ERR_REGNUM; + } + if (reg1 == -1){ + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, src[2] * 4); /* MOV(reg1, [EBP+?]); */ + } else{ + if (reg0 != reg1) { + jitCompPutByte2(w.dst, 0x89, 0xc0 | reg1 << 3 | reg0); /* MOV(reg0, reg1); */ + } + } + if (*src == 0x18) { + /* SHL(reg0, im8); */ + jitCompPutByte3(w.dst, 0xc1, 0xe0 | reg0, w.r3f); + } + if (*src == 0x19) { + /* SAR(reg0, im8); */ + jitCompPutByte3(w.dst, 0xc1, 0xf8 | reg0, w.r3f); + } + if (reg0 == IA32_REG0_EAX){ + jitCompA0001_movRxxEax(&w, src[1]); + } + cmp0reg = src[1]; + cmp0lev = 1; + break; + } +#endif + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[2] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(w.dst, w.r3f); + } else{ + jitCompA0001_movEaxRxx(&w, src[2]); + } +#else + jitCompA0001_movEaxRxx(&w, src[2]); +#endif + if (*src == 0x18) { + /* SHL(EAX, CL); */ + jitCompPutByte2(w.dst, 0xd3, 0xe0); + } + if (*src == 0x19) { + /* SAR(EAX, CL); */ + jitCompPutByte2(w.dst, 0xd3, 0xf8); + } + jitCompA0001_movRxxEax(&w, src[1]); + jitCompA000_loadRegCacheAll(&w); // 手抜き. + cmp0reg = src[1]; + cmp0lev = 1; + break; + + case 0x1a: /* DIV */ + case 0x1b: /* MOD */ + if (src[1] >= 0x3f || src[2] >= 0x40 || src[3] >= 0x40){ + w.err = JITC_ERR_REGNUM; + } + jitCompA000_storeRegCacheAll(&w); // 手抜き. +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8 | 1); /* MOV(ECX, ?); */ + jitCompPutImm32(w.dst, w.r3f); + } else{ + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ + } + if (src[2] == 0x3f) { + jitCompPutByte1(w.dst, 0xb8 | 0); /* MOV(EAX, ?); */ + jitCompPutImm32(w.dst, w.r3f); + } else{ + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, src[2] * 4); /* MOV(EAX, [EBP+?]); */ + } +#else + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG1_ECX, src[3] * 4); /* MOV(ECX, [EBP+?]); */ + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, src[2] * 4); /* MOV(EAX, [EBP+?]); */ +#endif + jitCompPutByte1(w.dst, 0x99); /* CDQ(); */ + /* ECXがゼロではないことを確認すべき */ + jitCompPutByte2(w.dst, 0xf7, 0xf9); /* IDIV(ECX); */ + if (*src == 0x1a) { + jitCompPutOp_MOV_EBPDisp_GReg(&w, src[1] * 4, IA32_REG0_EAX); + } + if (*src == 0x1b) { + jitCompPutOp_MOV_EBPDisp_GReg(&w, src[1] * 4, IA32_REG2_EDX); + } + jitCompA000_loadRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x1c: /* PLMT0 */ + case 0x1d: /* PLMT1 */ + if (src[1] >= 0x40 || src[2] >= 0x40){ + w.err = JITC_ERR_PREGNUM; + } + if (level < JITC_LV_FASTEST) { + cmp0reg = -1; + if (level < JITC_LV_FASTER) { + // typ が一致していることを確認. + // plsとliveSignが一致していることを確認. + + // preg1はp0 <= p <= p1 を満たしているか?. + // 新しいp0/p1は古いp0?p1に適合しているか?. + + } + } + + case 0x1e: /* PCP */ /* 未完成(p1まで完成) */ + if (src[1] >= 0x40 || src[2] >= 0x40){ + w.err = JITC_ERR_PREGNUM; + } + if (src[2] == 0x3f){ + w.err = JITC_ERR_PREGNUM; + } + if (src[1] != 0x3f) { + /* src[2] == 0xff の場合に対応できてない */ + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32; i += 4) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + i); /* MOV(EAX, [EBP+?]); */ + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + } else { + if (level < JITC_LV_FASTER) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ + jitCompPutByte3(w.dst, 0x83, 0xf8, 0); /* CMP(EAX, 0); */ + jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(w.dst, errfnc - (w.dst + 4)); + /* セキュリティチェックが足りてない!(aliveとか) */ + } + reg0 = IA32_REG0_EAX; + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutOp_MOV_GReg_EBPDisp(&w, reg0, PRegOffset(src[2]) + 0); /* MOV(EAX, [EBP+?]); */ + if (level < JITC_LV_FASTER) { + jitCompPutByte1(w.dst, 0x3b); /* CMP(reg0, [EBP+?]); */ + jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[2]) + 8, reg0); /* p0 */ + jitCompPutByte2(w.dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(w.dst, errfnc - (w.dst + 4)); + } + jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ + } + break; + + case 0x1f: /* PCST */ + if (jitCompGetImm32(src + 2) == 0) { + if (level < JITC_LV_FASTER){ + jitCompA0001_checkType0(&w, src[6], jitCompGetImm32(src + 7), 2); + } + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32 - 4; i += 4) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ + if (i == 4) { + jitCompPutByte1(w.dst, 0x0d); /* OR(EAX, ?); */ + jitCompPutImm32(w.dst, 0x80000000); + } + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 28, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + } + if (jitCompGetImm32(src + 7) == 0) { + jitCompA000_storePRegCacheAll(&w); // 手抜き. + for (i = 0; i < 32 - 4; i += 4) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + i); /* MOV(EAX, [EBP+?]); */ + if (i == 4) { + jitCompPutByte1(w.dst, 0x25); /* AND(EAX, ?); */ + jitCompPutImm32(w.dst, 0x7fffffff); + } + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + i, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + } + if (level < JITC_LV_FASTER) { + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[6]) + 28); /* MOV(EAX, [EBP+?]); */ + jitCompPutByte1(w.dst, 0x3d); /* CMP(EAX, ?); */ + jitCompPutImm32(w.dst, debugInfo1); + jitCompPutByte2(w.dst, 0x74, 8); /* JE */ + jitCompPutOp_MOV_EAX_ZERO(w.dst); + jitCompPutOp_MOV_EBPDisp_GReg(&w, PRegOffset(src[1]) + 0, IA32_REG0_EAX); /* MOV([EBP+?], EAX); (1+1+4) */ + } + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + } + w.err = JITC_ERR_OPECODE; + goto err_w; + + case 0x20: /* CMPE */ + case 0x21: /* CMPNE */ + case 0x22: /* CMPL */ + case 0x23: /* CMPGE */ + case 0x24: /* CMPLE */ + case 0x25: /* CMPG */ + case 0x26: /* TSTZ */ + case 0x27: /* TSTNZ */ + reg0 = jitCompA000_selectRegCache(src[2], IA32_REG0_EAX); + reg1 = jitCompA000_selectRegCache(src[3], -1 /* mem */); + if (src[1] == 0x3f) { + /* 特殊構文チェック */ + if (w.prefix != 0) { + w.err = JITC_ERR_PREFIX; + goto err_w; + } + if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { + w.err = JITC_ERR_IDIOM; + goto err_w; + } + } + if (reg0 == 0) + jitCompA0001_movEaxRxx(&w, src[2]); +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (src[3] == 0x3f) { +#if (jitCompA0001_OPTIMIZE_CMP != 0) + if ((*src <= 0x25 && w.r3f == 0) || (*src >= 0x26 && w.r3f == -1)) { + i = 0; + if (cmp0reg == src[2]) { + if (cmp0lev >= 1 && (src[0] == 0x20 || src[0] == 0x21 || src[0] == 0x26 || src[0] == 0x27)){ + i = 1; + } + if (cmp0lev >= 2 && (src[0] == 0x22 || src[0] == 0x23 || src[0] == 0x24 || src[0] == 0x25)){ + i = 1; + } + } + if (i == 0) { + jitCompPutByte2(w.dst, 0x85, 0xc0 | reg0 << 3 | reg0); /* TEST(reg0, reg0); */ + } + cmp0reg = src[2]; + cmp0lev = 2; + goto cmpcc1; + } +#endif +#if (jitCompA0001_USE_R3F_IMM8 != 0) + if (-0x80 <= w.r3f && w.r3f <= 0x7f && *src <= 0x25) { + jitCompPutByte3(w.dst, 0x83, 0xf8 | reg0, w.r3f); + goto cmpcc1; + } +#endif + if (reg0 == 0) { + if (*src <= 0x25) { + jitCompPutByte1(w.dst, 0x3d); + } + if (*src >= 0x26) { + jitCompPutByte1(w.dst, 0xa9); + } + } + else { + if (*src <= 0x25) { + jitCompPutByte2(w.dst, 0x81, 0xf8 | reg0); + } + if (*src >= 0x26) { + jitCompPutByte2(w.dst, 0xf7, 0xc0 | reg0); + } + } + jitCompPutImm32(w.dst, w.r3f); + goto cmpcc1; + } +#endif + if (src[3] >= 0x40){ + w.err = JITC_ERR_PREGNUM; + } + if (reg1 >= 0) { + if (*src <= 0x25) { + jitCompPutByte2(w.dst, 0x39, 0xc0 | reg1 << 3 | reg0); + } + if (*src >= 0x26) { + jitCompPutByte2(w.dst, 0x85, 0xc0 | reg1 << 3 | reg0); + } + } else{ + if (*src <= 0x25) { + jitCompPutByte1(w.dst, 0x3b); + } + if (*src >= 0x26) { + jitCompPutByte1(w.dst, 0x85); + } + jitCompPutModRM_Disp_BaseEBP(&w, src[3] * 4, reg0); + } + cmpcc1: + if (w.err != 0){ + goto err_w; + } + static unsigned char cmpcc_table0[] = { + 0x04, 0x05, 0x0c, 0x0d, 0x0e, 0x0f, 0x04, 0x05, /* CMPcc, TSTcc */ + 0x04, 0x05, 0x02, 0x03, 0x06, 0x07 /* PCMPcc */ + }; +#if (jitCompA0001_USE_R3F_CMPJMP != 0) + if (src[1] == 0x3f) { + /* 特殊構文を利用した最適化 */ + jitCompPutByte2(w.dst, 0x0f, 0x80 | cmpcc_table0[*src - 0x20]); + src += 6; + 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 (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)){ + j = label[i].p - (w.dst + 4); + } + jitCompPutImm32(w.dst, j); +#if (jitCompA0001_OPTIMIZE_JMP != 0) + if (-128 - 4 <= j && j < 0) { + j += 4; + w.dst -= 6; + jitCompPutByte2(w.dst, w.dst[1] ^ 0xf0, j & 0xff); + } +#endif + src += 6; + if (w.err != 0){ + goto err_w; + } + continue; + } +#endif + /* 一般的なJITC */ + reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); + jitCompPutByte3(w.dst, 0x0f, 0x90 | cmpcc_table0[*src - 0x20], 0xc0 | reg0); /* SETcc(BYTE(reg0)); */ + jitCompPutByte3(w.dst, 0x0f, 0xb6, 0xc0 | reg0 << 3 | reg0); /* MOVZX(reg0, BYTE(reg0)); */ + jitCompPutByte2(w.dst, 0xf7, 0xd8 | reg0); /* NEG(reg0); */ + if (reg0 == 0){ + jitCompA0001_movRxxEax(&w, src[1]); + } + cmp0reg = src[2]; + cmp0lev = 1; + break; + + case 0x28: /* PCMPE */ + case 0x29: /* PCMPNE */ + case 0x2a: /* PCMPL */ + case 0x2b: /* PCMPGE */ + case 0x2c: /* PCMPLE */ + case 0x2d: /* PCMPG */ + if (src[1] == 0x3f) { + /* 特殊構文チェック */ + if (w.prefix != 0) { + w.err = JITC_ERR_PREFIX; + goto err_w; + } + if (src[4] != 0x04 || src[5] != 0x3f || src[6] != 0x03 || src[7] != 0x3f) { + w.err = JITC_ERR_IDIOM; + goto err_w; + } + } + if (src[2] >= 0x40) { + w.err = JITC_ERR_PREGNUM; + } + jitCompA000_storePRegCacheAll(&w); // 手抜き. + if (src[3] != 0xff){ + jitCompA0001_checkCompPtr(&w, src[2], src[3]); + } + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(src[2]) + 0); /* MOV(EAX, [EBP+?]); */ + if (src[3] != 0xff) { + jitCompPutByte1(w.dst, 0x3b); /* CMP(EAX, [EBP+?]); */ + jitCompPutModRM_Disp_BaseEBP(&w, PRegOffset(src[3]) + 0, 0); + } else{ + /* ヌルポインタとの比較はこれでいいのか?たぶんよくない */ + jitCompPutByte3(w.dst, 0x83, 0xf8, 0x00); /* CMP(EAX, 0); */ + } + cmp0reg = -1; + goto cmpcc1; + + case 0x30: /* talloc(old:F4) */ + case 0x31: /* tfree(old:F5) */ + case 0x32: /* malloc(old:F6) */ + case 0x33: /* mfree(old:F7) */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + + jitCompPutOp_PUSH_Imm8(w.dst, src[3]); + jitCompPutOp_PUSH_Imm8(w.dst, src[2]); + jitCompPutOp_PUSH_Imm8(w.dst, src[1]); + jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); + + switch (*src) { + case 0x30: + j = ((unsigned char *)&funcf4) - (w.dst + 1 + 4); + break; + case 0x31: + j = ((unsigned char *)&funcf5) - (w.dst + 1 + 4); + break; + case 0x32: + j = ((unsigned char *)&funcf6) - (w.dst + 1 + 4); + break; + case 0x33: + j = ((unsigned char *)&funcf7) - (w.dst + 1 + 4); + break; + } + jitCompPutOp_CALL_Relative(w.dst, j); + jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 16); + + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x34: /* data (暫定) */ + // 0 1234 5678 9 + // 34 typ32 len32 data... + // len32 is NOT byte size! + + cmp0reg = -1; + if (w.prefix != 0) { + w.err = JITC_ERR_PREFIX; + goto err_w; + } + int k, tmpData, bitCount, dataWidth; + // kはtyp32 + k = jitCompGetImm32(&src[1]); + dataWidth = jitCompA000_dataWidth(k); + if (lastlabel >= 0 && label[lastlabel].typ == 0){ + //直前のラベルタイプを設定 + label[lastlabel].typ = k; + } + if (k != 1) { + i = jitCompA000_convTyp(k); + if (i < 2 || i > 7) { + w.err = JITC_ERR_BADTYPE; + goto err_w; + } + } + // jはlen32 + j = jitCompGetImm32(&src[5]); + oldsrc = src; + src += 9; + + // srcはdata本体を指す + if (k != 1) { + // 一般データ + bitCount = 7; + while (j > 0) { + if (src >= src1) { + // バイトコードを末端を超えて読もうとした + w.err = JITC_ERR_SRC1; + src = oldsrc; + goto err_w; + } + if (w.dst + 256 > dst1) { + // 書き込み先の残り容量が256Bytesを切った + w.err = JITC_ERR_DST1; + src = oldsrc; + goto err_w; + } + tmpData = 0; + for (k = 0; k < dataWidth; k++) { + // dataWidthビットごとに切り出してtmpDataに入れる + tmpData = tmpData << 1 | ((*src >> bitCount) & 1); + bitCount--; + if (bitCount < 0) { + bitCount = 7; + src++; + } + } + if ((i & 1) == 0 && dataWidth <= 31 && (tmpData >> (dataWidth - 1)) != 0) { + // 符号あり型で、かつtmpDataの符号ビットが1なので、マイナスにする + tmpData -= 1 << dataWidth; + } + if (i == 2 || i == 3) { + // BYTE + jitCompPutByte1(w.dst, tmpData & 0xff); + } + if (i == 4 || i == 5) { + // WORD + jitCompPutByte2(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff); + } + if (i == 6 || i == 7) { + // DWORD + jitCompPutByte4(w.dst, tmpData & 0xff, (tmpData >> 8) & 0xff, (tmpData >> 16) & 0xff, (tmpData >> 24) & 0xff); + } + j--; + } + } else{ + // VPtr型 + while (j > 0) { + if (src >= src1) { + // バイトコードを末端を超えて読もうとした + w.err = JITC_ERR_SRC1; + src = oldsrc; + goto err_w; + } + if (w.dst + 256 > dst1) { + // 書き込み先の残り容量が256Bytesを切った + w.err = JITC_ERR_DST1; + src = oldsrc; + goto err_w; + } + i = jitCompGetImm32(src); + src += 4; + if ((flags & JITC_PHASE1) != 0 && w.err == 0) { + // Only in phase1 + if (label[i].opt == 0) { + // ローカルラベルはだめです... + w.err = JITC_ERR_LABELNODEF; + goto err_w; + } + } + jitCompPutImm32(w.dst, (int)label[i].p); + jitCompPutImm32(w.dst, label[i].typ); + jitCompPutImm32(w.dst, (int)label[i].p); + jitCompPutImm32(w.dst, (int)label[i].p1); + jitCompPutImm32(w.dst, 0); /* liveSign */ + jitCompPutImm32(w.dst, envOffset_PTRCTRL); /* pls */ + jitCompPutImm32(w.dst, 0); + jitCompPutImm32(w.dst, 0); + j--; + } + } + if (lastlabel >= 0 && label[lastlabel].p1 < w.dst){ + label[lastlabel].p1 = w.dst; + } + continue; + + case 0x3c: /* ENTER */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutOp_PUSH_Imm8(w.dst, src[6]); + jitCompPutOp_PUSH_Imm8(w.dst, src[5]); + jitCompPutOp_PUSH_Imm8(w.dst, src[4] & 0x0f); + jitCompPutOp_PUSH_Imm8(w.dst, (src[4] >> 4) & 0x0f); + jitCompPutOp_PUSH_Imm8(w.dst, src[3]); + jitCompPutOp_PUSH_Imm8(w.dst, src[2]); + jitCompPutOp_PUSH_Imm8(w.dst, src[1]); + jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); + j = ((unsigned char *)&func3c) - (w.dst + 1 + 4); + jitCompPutOp_CALL_Relative(w.dst, j) + jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 32); + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0x3d: /* LEAVE */ + jitCompA000_storeRegCacheAll(&w); // 手抜き. + jitCompA000_storePRegCacheAll(&w); // 手抜き. + jitCompPutOp_PUSH_Imm8(w.dst, src[6]); + jitCompPutOp_PUSH_Imm8(w.dst, src[5]); + jitCompPutOp_PUSH_Imm8(w.dst, src[4] & 0x0f); + jitCompPutOp_PUSH_Imm8(w.dst, (src[4] >> 4) & 0x0f); + jitCompPutOp_PUSH_Imm8(w.dst, src[3]); + jitCompPutOp_PUSH_Imm8(w.dst, src[2]); + jitCompPutOp_PUSH_Imm8(w.dst, src[1]); + jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); + j = ((unsigned char *)&func3d) - (w.dst + 1 + 4); + jitCompPutOp_CALL_Relative(w.dst, j) + jitCompPutOp_ADD_GReg_Imm8(w.dst, IA32_REG4_ESP, 32); + jitCompA000_loadRegCacheAll(&w); // 手抜き. + jitCompA000_loadPRegCacheAll(&w); // 手抜き. + cmp0reg = -1; + break; + + case 0xfe: /* remark */ + if (src[1] == 0x01 && src[2] == 0x00) { + // DBGINFO1 + if (level <= JITC_LV_SLOWER) { + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); + jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); + } + } + if (src[1] == 0x01 && src[2] == 0x03) { + // DBGINFO1CLR + if (level <= JITC_LV_SLOWER) { + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, -1); + jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO1, IA32_REG0_EAX); + } + } + if (src[1] == 0x05 && src[2] == 0x00) { + // DBGINFO0 + if (level <= JITC_LV_SLOWEST) { + debugInfo0 = jitCompGetImm32(src + 3); + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo0); + jitCompPutOp_MOV_EBPDisp_GReg(&w, envOffset_DBGINFO0, IA32_REG0_EAX); + } + } + break; + + default: + w.err = JITC_ERR_OPECODE; + goto err_w; + } + if (w.err != 0){ + goto err_w; + } + jitCompA0001_fixPrefix(&w); + if (w.err != 0) { + goto err_w; + } +#if ENABLE_DEBUG_CODE != 0 + if(*src != 0x00 && *src != 0x01 && *src != 0x34){ + DEBUGCode(&w, 315315); + } +#endif + src += jitCompCmdLen(src); + } + if (enter0 != NULL) { + j = w.dst - (enter0 + 4); + enter0[0] = j & 0xff; + enter0[1] = (j >> 8) & 0xff; + enter0[2] = (j >> 16) & 0xff; + enter0[3] = (j >> 24) & 0xff; + } + if ((flags & JITC_NOSTARTUP) == 0) { + jitCompA000_storeRegCacheAll(&w); + jitCompA000_storePRegCacheAll(&w); + jitCompPutOp_POPAD(w.dst); + } + if ((flags & JITC_PHASE1) != 0){ + return w.dst - dst00; + } + return 0; + +err_w: + if ((w.err & JITC_ERR_PHASE0ONLY) != 0) { + if ((flags & JITC_PHASE1) == 0){ + w.err &= ~JITC_ERR_PHASE0ONLY; + } + } + if (w.err == (JITC_ERR_MASK & JITC_ERR_REGNUM)) errmsg = "reg-number error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_DST1)) errmsg = "dst1 error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_OPECODE)) errmsg = "opecode error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNUM)) errmsg = "label number too large"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELREDEF)) errmsg = "label redefine"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_PREFIX)) { errmsg = "prefix redefine"; w.dst -= 2; } + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELNODEF)) errmsg = "label not defined"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_LABELTYP)) errmsg = "label type error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_IDIOM)) errmsg = "idiom error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_PREGNUM)) errmsg = "preg-number error"; + if (w.err == (JITC_ERR_MASK & JITC_ERR_SRC1)) errmsg = "src1 error"; + 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); + for (i = 0; i < 16; i++) + fprintf(stderr, "%02X ", src[i]); + static char *table[0x30] = { + "NOP", "LB", "LIMM", "PLIMM", "CND", "??", "??", "??", + "LMEM", "SMEM", "PLMEM", "PSMEM", "LEA", "??", "PADD", "PDIF", + "CP/OR", "XOR", "AND", "??", "ADD", "SUB", "MUL", "??", + "SHL", "SAR", "DIV", "MOD", "PLMT0", "PLMT1", "PCP", "PCST", + "CMPE", "CMPNE", "CMPL", "CMPGE", "CMPLE", "CMPG", "TSTZ", "TSTNZ", + "PCMPE", "PCMPNE", "PCMPL", "PCMPGE", "PCMPLE", "PCMPG", "??", "EXT" }; + errmsg = "??"; + if (*src < 0x30) errmsg = table[*src]; + fprintf(stderr, "(%s)\n", errmsg); + } + return -1; +} + +unsigned char *jitCompCallFunc(unsigned char *dst, void *func) +{ + //この関数の中では結局w->dstしか参照していない + struct JitCompWork w; + w.dst = dst; + jitCompA000_storeRegCacheAll(&w); + jitCompA000_storePRegCacheAll(&w); + jitCompPutOp_PUSHAD(w.dst); + jitCompPutOp_PUSH_GReg(w.dst, IA32_REG0_EAX); /* for 16Byte-align(Mac OSX) */ + jitCompPutOp_PUSH_GReg(w.dst, IA32_REG5_EBP); + + int j = ((unsigned char *)func) - (w.dst + 1 + 4); + jitCompPutOp_CALL_Relative(w.dst, j); + + jitCompPutOp_POP_GReg(w.dst, IA32_REG0_EAX); + jitCompPutOp_POP_GReg(w.dst, IA32_REG0_EAX); /* for 16Byte-align (Mac OSX) */ + jitCompPutOp_POPAD(w.dst); + jitCompA000_loadRegCacheAll(&w); + jitCompA000_loadPRegCacheAll(&w); + jitCompPutOp_MOV_GReg_EBPDisp(&w, IA32_REG0_EAX, PRegOffset(0x30) + 0); + + jitCompPutByte2(w.dst, 0xff, 0xe0); /* JMP(EAX); */ + return w.dst; +} + +unsigned char *jitCompInit(unsigned char *dst) +{ + errfnc = dst; + return jitCompCallFunc(dst, &errHndl); +} + +void jitcRunBinary(void (*bin)(char *), HOSECPU_RuntimeEnvironment *env) +{ + (*bin)(((char *)env) + jitCompA0001_EBP128); /* サイズを節約するためにEBPをjitCompA0001_EBP128バイトずらす */ + return; +} + +void func3c(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int i, *pi; + 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++){ + pi[i] = r->ireg[i]; + } + pp = (void *)r->junkStack; + r->junkStack += p1 * 32; + for (i = 0; i < p1; i++){ + //pp[i] = r->preg[i]; + PRegCopy(&pp[i], &r->preg[i]); + // + } + pp = (void *)r->junkStack; + r->junkStack += 32; + //*pp = r->preg[0x30]; + PRegCopy(pp, &r->preg[0x30]); + // + pi = (void *)r->junkStack; + r->junkStack += 4; + *pi = opt << 16 | r1 << 8 | p1; + for (i = 0; i < lenR; i++){ + r->ireg[r0 + i] = r->ireg[0x30 + i]; + } + for (i = 0; i < lenP; i++){ + r->preg[p0 + i] = r->preg[0x31 + i]; + } + return; +} + +void func3d(char *ebp, int opt, int r1, int p1, int lenR, int lenP, int r0, int p0) +{ + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + int i; + r->junkStack -= 4; + r->junkStack -= 32; + HOSECPU_PointerRegisterEntry *pp = (void *)r->junkStack; + + //r->preg[0x30] = *pp; + PRegCopy(&r->preg[0x30], pp); + // + r->junkStack -= p1 * 32; pp = (void *)r->junkStack; + for (i = 0; i < p1; i++){ + //r->preg[i] = pp[i]; + PRegCopy(&r->preg[i], &pp[i]); + // + } + r->junkStack -= r1 * 4; int *pi = (void *)r->junkStack; + for (i = 0; i < r1; i++){ + r->ireg[i] = pi[i]; + } + return; +} + +void funcf4(char *ebp, int pxx, int typ, int len) +{ + 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 *p = r->junkStack; + if (r->junkStack + width * r->ireg[len] + 256 > r->junkStack1){ + (*(r->errHndl))(r); + } + r->junkStack += width * r->ireg[len]; + r->preg[pxx].p = p; + r->preg[pxx].typ = r->ireg[typ]; + r->preg[pxx].p0 = p; + r->preg[pxx].p1 = (void *)r->junkStack; + int *pi = (int *)r->junkStack; + *pi = width * r->ireg[len]; + r->junkStack += sizeof (int); + if (r->ireg[typ] == 1) { + int i, i1 = (width * r->ireg[len]) >> 2; + pi = p; + for (i = 0; i < i1; i++){ + pi[i] = 0; + } + } + return; +} + +void funcf5(char *ebp, int pxx, int typ, int len) +{ + // pxxはダミーで参照されない + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + r->junkStack -= sizeof (int); + int *pi = (int *)r->junkStack; + r->junkStack -= *pi; +#if 0 + int width = jitCompA000_dataWidth(r->ireg[typ]); + void *p = r->junkStack; + r->junkStack -= width * r->ireg[len]; +#endif + return; +} + +void funcf6(char *ebp, int pxx, int typ, int len) +{ + 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 *p = malloc(width * r->ireg[len]); + r->preg[pxx].p = p; + r->preg[pxx].typ = r->ireg[typ]; + r->preg[pxx].p0 = p; + r->preg[pxx].p1 = (unsigned char *)p + width * r->ireg[len]; + if (r->ireg[typ] == 1) { + int i, i1 = (width * r->ireg[len]) >> 2, *pi; + pi = p; + for (i = 0; i < i1; i++){ + pi[i] = 0; + } + for (i = 1; i < i1; i += 8){ + pi[i] |= -1; + } + } + return; +} + +void funcf7(char *ebp, int pxx, int typ, int len) +{ + // typとlenはダミーで参照されない + HOSECPU_RuntimeEnvironment *r = (HOSECPU_RuntimeEnvironment *) (ebp - jitCompA0001_EBP128); + free(r->preg[pxx].p); + return; +} + +void errHndl(HOSECPU_RuntimeEnvironment *r) +{ + r = (HOSECPU_RuntimeEnvironment *) (((char *)r) - jitCompA0001_EBP128); + (*(r->errHndl))(r); + // ここに帰ってきてはいけない. +} + +/* + * jitcの出力コードをひとまとめにする関数を作成しその中身をjitCompile()で生成 + * + * qq : 出力バイナリの書き込み位置のアドレスへの参照(書き込み位置を呼び出しに反映させるため参照渡しにする) + * q1 : 出力バイナリの書き込み位置のアドレスの最大値 + * p0 : (*.ose)バイナリの読み込み位置のアドレス(ヘッダ部除去済) + * p1 : (*.ose)バイナリの読み込み位置の取りうる最大値 + * (ただし、「確保したメモリ」の最大値なのでこれより手前にゴミデータが入っているかもしれない) + * ret=1 : ヘッダのエラー + * ret=2 : jitコンパイルエラー + */ +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; + int i; + + if (p0[0] != 0x05 || p0[1] != SIGN1){ + // OSECPUのヘッダ (05E1) を確認 + return 1; + } + + jitCompPutOp_PUSH_GReg(q, IA32_REG5_EBP); + + *q++ = 0x8b; *q++ = 0x6c; *q++ = 0x24; *q++ = 0x08; /* MOV(EBP,[ESP+8]); */ + + 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 (i < 0){ + return 2; + } + q += i; + + jitCompPutOp_POP_GReg(q, IA32_REG5_EBP); + *q++ = 0xc3; /* RET(); */ + *qq = q; + return 0; +} + +#if (USE_DEBUGGER != 0) + +int dbgrGetRegNum(const char *p) +{ + int i, j, r = -1; + if (p[2] <= ' ') { + i = p[0] - '0'; + j = p[1] - '0'; + if (i > 9){ + i -= 'A' - '0' - 10; + } + if (j > 9){ + j -= 'A' - '0' - 10; + } + if (0 <= i && i <= 15 && 0 <= j && j <= 15){ + r = i << 4 | j; + } + } + return r; +} + +void dbgrMain(HOSECPU_RuntimeEnvironment *r) +{ + if (r->dbgr == 0){ + return; + } + for (;;) { + char cmd[64], *p; + int i, j, k; + + printf("\ndbgr>"); + p = fgets(cmd, 64, stdin); + if (p == NULL){ + break; + } + if (cmd[0] == '\0'){ + continue; + } + if (cmd[0] == 'q' && cmd[1] <= ' '){ + break; + } + if (cmd[0] == 'p' && cmd[1] <= ' ' && cmd[1] != '\0') { + p = &cmd[2]; + 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]); + } else{ + puts("register name error"); + } + continue; + } + if (*p == 'P') { + i = dbgrGetRegNum(p + 1); + if (0 <= i && i <= 0x3f) { + p = "invalid"; + if (0 <= r->preg[i].typ && r->preg[i].typ <= 0x15) { + 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", + "T_SINT1", "T_UINT1", "T_SINT12", "T_UINT12", + "T_SINT20", "T_UINT20", "T_SINT24", "T_UINT24", + "T_SINT28", "T_UINT28" + }; + p = typName[r->preg[i].typ]; + } + 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); + k = (r->preg[i].p - r->preg[i].p0) / j; + printf(" pos = 0x%08X = %d\n", k, k); + } + else { + puts(" null pointer"); + } + } + else + puts("register name error"); + continue; + } + } + puts("command error"); + } + return; +} + +#endif + + #endif \ No newline at end of file diff --git a/osecpu.h b/osecpu.h index 62b4f22..fee9151 100644 --- a/osecpu.h +++ b/osecpu.h @@ -53,6 +53,7 @@ #define USE_DEBUGGER 1 #define USE_TEK5 1 +#define ENABLE_DEBUG_CODE 0 // env.dbg_currentCodeに実行するコードを保存するデバッグコードを挿入する /* JITC mode flags */ #define JITC_LV_SLOWEST 0 /* デバッグ支援は何でもやる */ -- 2.11.0