From: hikarupsp Date: Sat, 15 Mar 2014 06:32:33 +0000 (+0900) Subject: jitcx86.cを分割した。 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=e2cd1768d592faab2517f8f8970cd6ba3298ae5c;p=heavyosecpu%2FHeavyOSECPU.git jitcx86.cを分割した。 --- diff --git a/jitc.h b/jitc.h index 1ddcae8..7fc937a 100644 --- a/jitc.h +++ b/jitc.h @@ -2,6 +2,8 @@ #ifndef HeavyOSECPU_jitc_h #define HeavyOSECPU_jitc_h + + // Error flags #define JITC_ERR_MASK 255 #define JITC_ERR_PHASE0ONLY 256 @@ -52,12 +54,15 @@ int jitCompCmdLen(const unsigned char *src); #define envOffset_DBGINFO1 (2304 + 4) // #define jitCompPutImm32(p, i) jitCompPutByte4(p, ((i) & 0xff), (((i) >> 8) & 0xff), (((i) >> 16) & 0xff), (((i) >> 24) & 0xff)) +#define jitCompPutOp_XOR_GReg_GReg(p, d, s) jitCompPutByte2(w.dst, 0x31, 0xc0 | (s) << 3 | (d)); +#define jitCompPutOp_MOV_GReg_Imm32(p, dReg, i) jitCompPutByte1(p, 0xb8 | dReg); jitCompPutImm32(p, i); /* MOV(reg0, ?); == [1011 1 reg] imm32 */ #define jitCompPutOp_PUSHAD(p) jitCompPutByte1(p, 0x60); #define jitCompPutOp_POPAD(p) jitCompPutByte1(p, 0x61); #define jitCompPutOp_PUSH_GReg(p, reg) jitCompPutByte1(p, 0x50 | (reg)); #define jitCompPutOp_POP_GReg(p, reg) jitCompPutByte1(p, 0x58 | (reg)); #define jitCompPutOp_CALL_Relative(p, diff) jitCompPutByte1(w.dst, 0xe8); jitCompPutImm32(&w, j); - +// +#define jitCompPutOp_MOV_EAX_ZERO(p) jitCompPutOp_XOR_GReg_GReg(p, IA32_REG0_EAX, IA32_REG0_EAX); // Optimization settings // 他のCPUへ移植する人へ: @@ -81,6 +86,7 @@ struct JitCompWork { char prefix; //CND命令の値を記録(初期値=0) }; +// @jitcx86a.c int jitCompGetImm32(const unsigned char *src); int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src); void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n); @@ -105,6 +111,9 @@ int jitCompA000_dataWidth(int t); void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac); void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac); void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx); + +// @jitcx86.c +extern unsigned char *errfnc; 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); unsigned char *jitCompCallFunc(unsigned char *dst, void *func); unsigned char *jitCompInit(unsigned char *dst); @@ -124,14 +133,6 @@ void dbgrMain(HOSECPU_RuntimeEnvironment *r); - - - - - - - - #endif #endif diff --git a/jitcx86.c b/jitcx86.c index 5c849af..3012629 100644 --- a/jitcx86.c +++ b/jitcx86.c @@ -5,257 +5,6 @@ // // for x86-32bit // -int jitCompGetImm32(const unsigned char *src) -{ - return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; -} - -int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) -{ - int i = jitCompGetImm32(src); - if (i < 0 || i >= w->maxLabels) { - w->err = JITC_ERR_LABELNUM; - i = 0; - } - return i; -} - -void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) -{ - disp -= jitCompA0001_EBP128; - if (-128 <= disp && disp <= 127) { - jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); - } else { - // 10 + reg + 101 + disp - jitCompPutByte1(w->dst, 0x85 | (n << 3)); - jitCompPutImm32(w->dst, disp); - } - return; -} - -void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) -{ - // MOV Ev, Gv - // MOV + ModR/M(2Mod + 3Reg + 3R/M) - jitCompPutByte1(w->dst, 0x89); /* 1000 1001 MOV(mem, reg32); */ - jitCompA0001_85DispN(w, disp, reg32); - return; -} - -void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) -{ - jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ - jitCompA0001_85DispN(w, disp, reg32); - return; -} - -void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) -{ -#if (jitCompA0001_USE_R3F_IMM32 != 0) - if (rxx == 0x3f) { - jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ - jitCompPutImm32(w->dst, w->r3f); - return; - } -#endif - if (rxx >= 0x40 || rxx < 0){ - w->err = JITC_ERR_REGNUM; - } - jitCompA0001_movReg32EbpDisp(w, IA32_REG0_EAX, rxx * 4); /* MOV(EAX, [EBP+?]); */ - return; -} - -void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) -{ - if (rxx >= 0x40 || rxx < 0){ - w->err = JITC_ERR_REGNUM; - } - jitCompA0001_movEbpDispReg32(w, rxx * 4, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ - return; -} - -void jitCompA0001_fixPrefix(struct JitCompWork *w) -{ - if (w->prefix != 0) { - if (w->dst - w->dst0 > 127){ - w->err = JITC_ERR_REGNUM; - } - w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); - } - return; -} - -void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) -{ - if (p0 >= 0x3f || p0 < 0){ - w->err = JITC_ERR_PREGNUM; - } - if (p1 >= 0x3f || p1 < 0){ - w->err = JITC_ERR_PREGNUM; - } - /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ - return; -} - -void jitCompA000_loadRegCacheAll(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ - return; -} - -void jitCompA000_storeRegCacheAll(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ - return; -} - -void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ - return; -} - -void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ - return; -} - -void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) -{ - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ - return; -} - -void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) -{ - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ - return; -} - -int jitCompA000_selectRegCache(int rxx, int reg) -{ - switch (rxx) { - case 0: - //EBX - reg = 3; - break; - case 1: - //ECX - reg = 1; - break; - case 2: - //EDX - reg = 2; - break; - } - return reg; -} - -void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) -{ - // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ - jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ - jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ - return; -} - -void jitCompA000_storePRegCacheAll(struct JitCompWork *w) -{ - // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ - jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ - jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ - return; -} - -int jitCompA000_selectPRegCache(int pxx, int reg) -{ - // if (pxx == 0) reg = 5; /* EBP */ - switch (pxx) { - case 1: - //ESI - reg = 6; - break; - - case 2: - //EDI - reg = 7; - break; - } - return reg; -} - -int jitCompA000_convTyp(int t) -{ - int r = -1; - - if (1 <= t && t <= 7){ - r = t; - } else if (8 <= t && t <= 13){ - r = 2 | (t & 1); - } else if (14 <= t && t <= 15){ - r = 4 | (t & 1); - } else if (16 <= t && t <= 21){ - r = 6 | (t & 1); - } - return r; -} - -int jitCompA000_dataWidth(int t) -{ - int r = -1; - if (t == 0x0001) r = 256; - t >>= 1; - if (t == 0x0002 / 2) r = 8; - if (t == 0x0004 / 2) r = 16; - if (t == 0x0006 / 2) r = 32; - if (t == 0x0008 / 2) r = 4; - if (t == 0x000a / 2) r = 2; - if (t == 0x000c / 2) r = 1; - if (t == 0x000e / 2) r = 12; - if (t == 0x0010 / 2) r = 20; - if (t == 0x0012 / 2) r = 24; - if (t == 0x0014 / 2) r = 28; - return r; -} - -static unsigned char *errfnc; - -void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) -{ - if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } - if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } - jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ - jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ - jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); - return; -} - -void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) -// data用. -// 将来的にはaliveやアクセス権チェックも入れる -{ - jitCompA0001_checkType0(w, pxx, typ, ac); - return; -} - -void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) -{ - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ - jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ - jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ - jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ - jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); - return; -} // 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) @@ -285,51 +34,54 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr jitCompA000_loadPRegCacheAll(&w); } if (level <= JITC_LV_SLOWER) { - // XOR(EAX, EAX); - jitCompPutByte2(w.dst, 0x31, 0xc0); + // debugInfo0 <- 0; + // + jitCompPutOp_MOV_EAX_ZERO(w.dst); // MOV(debugInfo0, EAX); jitCompA0001_movEbpDispReg32(&w, envOffset_DBGINFO0, IA32_REG0_EAX); - // MOV(EAX, ?); - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, imm32); */ - jitCompPutImm32(w.dst, debugInfo1); + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); jitCompA0001_movEbpDispReg32(&w, envOffset_DBGINFO1, IA32_REG0_EAX); /* MOV(debugInfo1, EAX); */ } while (src < src1) { w.prefix = 0; //0x04 CND 命令で変更される - if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; } // 書き込み領域が残り256バイト未満ならエラー + if (w.dst + 256 > dst1) { + // 書き込み領域が残り256バイト未満ならエラー + w.err = JITC_ERR_DST1; goto err_w; + } timecount++; if (timecount >= 64) { timecount -= 64; /* 未完成(timeoutチェックコードを入れる) */ } - prefix_continue: // CND命令実行後ここに戻る + prefix_continue: + // CND命令コンパイル後ここに戻る switch (*src) { - - case 0x00: /* NOP */ - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } // 「条件付きでNOPを実行」するなんて、矛盾している! + case 0x00: + // NOP + if (w.prefix != 0) { + // 「条件付きでNOPを実行」するなんて、矛盾している! + w.err = JITC_ERR_PREFIX; goto err_w; + } break; - case 0x01: /* LB */ - - /* - * LB : ラベル設置命令。(6byte) - * ・prefex = 1にする - * ・timecount++し、timecountのチェックをする。 - * ・ラベル位置を登録する。 - * ・割り込みがある場合、このタイミングで割り込みを発生させる。 - * - * 1 2 3 456 - * LB 01 opt imm32 - * - */ - + case 0x01: + // LB : ラベル設置命令。(6byte) + // ・prefex = 1にする + // ・timecount++し、timecountのチェックをする。 + // ・ラベル位置を登録する。 + // ・割り込みがある場合、このタイミングで割り込みを発生させる。 + // + // 1 2 3 456 + // LB 01 opt imm32 + // if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { //beginFunc()中のLB // LB命令の後に0x3C命令・・・beginFunc() jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする enter0 = w.dst; jitCompPutImm32(w.dst, 0); // 飛び相対座標が0 ・・・パイプラインのフラッシュ?? } - if (src[6] == 0x34) { // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 + if (src[6] == 0x34) { + // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 tmp_ucp = w.dst; jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする i = jitCompGetImm32(&src[7]); // type32 を取得 @@ -337,9 +89,20 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr if (i != 1) { i = jitCompA000_convTyp(i); j = 0; - if (i == 2 || i == 3) { j = 1; } - if (i == 4 || i == 5) { j = 2; } - if (i == 6 || i == 7) { j = 4; } + switch (i) { + case 2: + case 3: + j = 1; + break; + case 4: + case 5: + j = 2; + break; + case 6: + case 7: + j = 4; + break; + } } j *= jitCompGetImm32(&src[11]); if (j <= 0) w.err = JITC_ERR_BADTYPE; @@ -375,9 +138,14 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr } if ((flags & JITC_PHASE1) == 0) { i = jitCompGetLabelNum(&w, src + 2); - //printf("i=%06X %06X\n", i, src-src0); - if (label[i].opt != 0 && w.err == 0) { w.err = JITC_ERR_LABELREDEF; goto err_w; } - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } + if (label[i].opt != 0 && w.err == 0) { + w.err = JITC_ERR_LABELREDEF; + goto err_w; + } + if (w.prefix != 0) { + w.err = JITC_ERR_PREFIX; + goto err_w; + } label[i].opt = src[1] + 1; label[i].typ = 0; /* TYP_CODE */ label[i].p = w.dst; @@ -389,71 +157,85 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr /* 未完成(timeoutチェックコードを入れる) */ break; - case 0x02: /* LIMM */ - - /* - * LIMM : 定数即値代入命令(6byte) - * - * 1 2 3456 - * 02 reg0R imm32 - * - * ・reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 - */ + case 0x02: + // LIMM : 定数即値代入命令(6byte) + // 1 2 3456 + // 02 reg0R imm32 + // + // reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 - if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX; // CND命令の直後でR3Fを書き換えるなんて変だよね + if (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 を使用 + 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) { - jitCompPutByte2(w.dst, 0x31, 0xc0 | reg0 << 3 | reg0); /* XOR(reg0, reg0); */ + jitCompPutOp_XOR_GReg_GReg(w.dst, reg0, reg0); jitCompA0001_movRxxEax(&w, src[1]); break; } #endif - /* reg0 のレジスタに対応したMOV命令を発行 */ - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); == 10111000b+wr imm32 */ - jitCompPutImm32(w.dst, i); + jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, i); - if (reg0 == 0) // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 - + if (reg0 == 0){ + // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 jitCompA0001_movRxxEax(&w, src[1]); - break; + } - case 0x03: /* PLIMM */ /* 未完成(plsまで対応) */ + break; - /* - * PLIMM : ラベル番号代入命令(6byte) - * - * 1 2 3456 - * 03 PXX imm32 - * - * ・P28 はAPI用 - * ・P30 はリターンアドレス - * ・P3F はプログラムカウンタ - */ + case 0x03: /* 未完成(plsまで対応) */ + // PLIMM : ラベル番号代入命令(6byte) + // + // 1 2 3456 + // 03 PXX imm32 + // + // ・P28 はAPI用 + // ・P30 はリターンアドレス + // ・P3F はプログラムカウンタ + // i = jitCompGetLabelNum(&w, src + 2); // Pxxに代入するラベルの番号(第二引数) - if ((flags & JITC_PHASE1) != 0 && w.err == 0) { // Phase 1であるならば - if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } // 指定されたラベル番号は存在しない - if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; } // - if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; } // プログラムカウンタに TYP_CODEでない値は代入できない + if ((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命令による条件付きでなければ、即座に移動 + if (src[1] == 0x3f) { + // プログラムカウンタへの代入 + if (w.prefix == 0) { + // CND命令による条件付きでなければ、即座に移動 jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ - } - else { // 直前はCND命令。 + } else { + // 直前はCND命令。 /* * CND命令 @@ -463,7 +245,8 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd */ - // JZのとび先アドレスの書き換え? + // Jccの条件変更 + // 0F 75 w.dst[-1] = w.dst[-2] ^ 0xf1; /* 74->85, 75->84 */ w.dst[-2] = 0x0f; @@ -488,8 +271,7 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr jitCompPutByte1(w.dst, j & 0xff); } #endif - } - else { // プログラムカウンタ以外への代入 + } else { // プログラムカウンタ以外への代入 // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); @@ -516,14 +298,15 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr } break; - case 0x04: /* CND (prefix) */ - - /* - * CND命令 - * 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 - */ - - if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM; // R00-R3F 以外のレジスタは比較対象にできない + 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 */); diff --git a/jitcx86a.c b/jitcx86a.c new file mode 100644 index 0000000..c33131c --- /dev/null +++ b/jitcx86a.c @@ -0,0 +1,260 @@ +#include "osecpu.h" +#include "jitc.h" + +#if (JITC_ARCNUM == 0x0001) +// +// for x86-32bit +// +int jitCompGetImm32(const unsigned char *src) +{ + return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; +} + +int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) +{ + int i = jitCompGetImm32(src); + if (i < 0 || i >= w->maxLabels) { + w->err = JITC_ERR_LABELNUM; + i = 0; + } + return i; +} + +void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) +{ + disp -= jitCompA0001_EBP128; + if (-128 <= disp && disp <= 127) { + jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); + } else { + // 10 + reg + 101 + disp + jitCompPutByte1(w->dst, 0x85 | (n << 3)); + jitCompPutImm32(w->dst, disp); + } + return; +} + +void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) +{ + // MOV Ev, Gv + // MOV + ModR/M(2Mod + 3Reg + 3R/M) + jitCompPutByte1(w->dst, 0x89); /* 1000 1001 MOV(mem, reg32); */ + jitCompA0001_85DispN(w, disp, reg32); + return; +} + +void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) +{ + jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ + jitCompA0001_85DispN(w, disp, reg32); + return; +} + +void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) +{ +#if (jitCompA0001_USE_R3F_IMM32 != 0) + if (rxx == 0x3f) { + jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ + jitCompPutImm32(w->dst, w->r3f); + return; + } +#endif + if (rxx >= 0x40 || rxx < 0){ + w->err = JITC_ERR_REGNUM; + } + jitCompA0001_movReg32EbpDisp(w, IA32_REG0_EAX, rxx * 4); /* MOV(EAX, [EBP+?]); */ + return; +} + +void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) +{ + if (rxx >= 0x40 || rxx < 0){ + w->err = JITC_ERR_REGNUM; + } + jitCompA0001_movEbpDispReg32(w, rxx * 4, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ + return; +} + +void jitCompA0001_fixPrefix(struct JitCompWork *w) +{ + if (w->prefix != 0) { + if (w->dst - w->dst0 > 127){ + w->err = JITC_ERR_REGNUM; + } + w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); + } + return; +} + +void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) +{ + if (p0 >= 0x3f || p0 < 0){ + w->err = JITC_ERR_PREGNUM; + } + if (p1 >= 0x3f || p1 < 0){ + w->err = JITC_ERR_PREGNUM; + } + /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ + return; +} + +void jitCompA000_loadRegCacheAll(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ + return; +} + +void jitCompA000_storeRegCacheAll(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ + return; +} + +void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ + return; +} + +void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ + return; +} + +void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) +{ + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ + return; +} + +void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) +{ + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ + return; +} + +int jitCompA000_selectRegCache(int rxx, int reg) +{ + switch (rxx) { + case 0: + //EBX + reg = 3; + break; + case 1: + //ECX + reg = 1; + break; + case 2: + //EDX + reg = 2; + break; + } + return reg; +} + +void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) +{ + // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ + jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ + jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ + return; +} + +void jitCompA000_storePRegCacheAll(struct JitCompWork *w) +{ + // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ + jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ + jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ + return; +} + +int jitCompA000_selectPRegCache(int pxx, int reg) +{ + // if (pxx == 0) reg = 5; /* EBP */ + switch (pxx) { + case 1: + //ESI + reg = 6; + break; + + case 2: + //EDI + reg = 7; + break; + } + return reg; +} + +int jitCompA000_convTyp(int t) +{ + int r = -1; + + if (1 <= t && t <= 7){ + r = t; + } else if (8 <= t && t <= 13){ + r = 2 | (t & 1); + } else if (14 <= t && t <= 15){ + r = 4 | (t & 1); + } else if (16 <= t && t <= 21){ + r = 6 | (t & 1); + } + return r; +} + +int jitCompA000_dataWidth(int t) +{ + int r = -1; + if (t == 0x0001) r = 256; + t >>= 1; + if (t == 0x0002 / 2) r = 8; + if (t == 0x0004 / 2) r = 16; + if (t == 0x0006 / 2) r = 32; + if (t == 0x0008 / 2) r = 4; + if (t == 0x000a / 2) r = 2; + if (t == 0x000c / 2) r = 1; + if (t == 0x000e / 2) r = 12; + if (t == 0x0010 / 2) r = 20; + if (t == 0x0012 / 2) r = 24; + if (t == 0x0014 / 2) r = 28; + return r; +} + +unsigned char *errfnc; + +void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) +{ + if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } + if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } + jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ + jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ + jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); + return; +} + +void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) +// data用. +// 将来的にはaliveやアクセス権チェックも入れる +{ + jitCompA0001_checkType0(w, pxx, typ, ac); + return; +} + +void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) +{ + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ + jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ + jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ + jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ + jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); + return; +} + +#endif