OSDN Git Service

Merge branch 'master' of git.sourceforge.jp:/gitroot/heavyosecpu/HeavyOSECPU
[heavyosecpu/HeavyOSECPU.git] / jitcx86a.c
diff --git a/jitcx86a.c b/jitcx86a.c
new file mode 100644 (file)
index 0000000..6804ec8
--- /dev/null
@@ -0,0 +1,275 @@
+#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 jitCompPutModRM_Disp_BaseEBP(struct JitCompWork *w, int disp, int opReg)
+{
+       // EBPをベースとするアドレスオペランドとレジスタオペランドを出力する
+       disp -= jitCompA0001_EBP128;
+       if (-128 <= disp && disp <= 127) {
+               // [EBP + Disp08]
+               jitCompPutByte1(w->dst, IA32_MOD_R_M(IA32_OP_MOD_INDEX_AND_DISP_BYTE, opReg, IA32_REG5_EBP));
+               jitCompPutByte1(w->dst, disp & 0xff);
+       } else {
+               // [EBP + Disp32]
+               jitCompPutByte1(w->dst, IA32_MOD_R_M(IA32_OP_MOD_INDEX_AND_DISP_FULL, opReg, IA32_REG5_EBP));
+               jitCompPutImm32(w->dst, disp);
+       }
+       return;
+}
+
+void jitCompPutOp_MOV_EBPDisp_GReg(struct JitCompWork *w, int disp, int reg32)
+{
+       // MOV([EBP + disp] <- reg32);
+       // MOV Ev, Gv
+       // [1000 100 1] [mod reg r/m]
+       jitCompPutByte1(w->dst, 0x89);
+       jitCompPutModRM_Disp_BaseEBP(w, disp, reg32);
+       return;
+}
+
+void jitCompPutOp_MOV_GReg_EBPDisp(struct JitCompWork *w, int reg32, int disp)
+{
+       // MOV (reg32 <- [EBP + disp])
+       // MOV Gv, Ev
+       // [1000 101 1] [mod reg r/m]
+       jitCompPutByte1(w->dst, 0x8b);
+       jitCompPutModRM_Disp_BaseEBP(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;
+       }
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG0_EAX, rxx * 4);
+       return;
+}
+
+void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx)
+{
+       if (rxx >= 0x40 || rxx < 0){
+               w->err = JITC_ERR_REGNUM;
+       }
+       jitCompPutOp_MOV_EBPDisp_GReg(w, rxx * 4, IA32_REG0_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)
+{
+       //保存されたレジスタキャッシュをメモリからロード
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG3_EBX, 4 * 0); /* EBX = R00; */
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG1_ECX, 4 * 1); /* ECX = R01; */
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG2_EDX, 4 * 2); /* EDX = R02; */
+       return;
+}
+
+void jitCompA000_storeRegCacheAll(struct JitCompWork *w)
+{
+       //レジスタキャッシュをメモリに退避
+       jitCompPutOp_MOV_EBPDisp_GReg(w, 0 * 4, IA32_REG3_EBX); /* R00 = EBX; */
+       jitCompPutOp_MOV_EBPDisp_GReg(w, 1 * 4, IA32_REG1_ECX); /* R01 = ECX; */
+       jitCompPutOp_MOV_EBPDisp_GReg(w, 2 * 4, IA32_REG2_EDX); /* R02 = EDX; */
+       return;
+}
+
+void jitCompA000_loadRegCacheEcx(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG1_ECX, 1 * 4); /* ECX = R01; */
+       return;
+}
+
+void jitCompA000_storeRegCacheEcx(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_EBPDisp_GReg(w, 1 * 4, IA32_REG1_ECX); /* R01 = ECX; */
+       return;
+}
+
+void jitCompA000_loadRegCacheEdx(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG2_EDX, 2 * 4); /* EDX = R02; */
+       return;
+}
+
+void jitCompA000_storeRegCacheEdx(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_EBPDisp_GReg(w, 2 * 4, IA32_REG2_EDX); /* R02 = EDX; */
+       return;
+}
+
+int jitCompA000_selectRegCache(int rxx, int reg)
+{
+       // OSECPUレジスタ番号をIA32レジスタ番号へ変換
+       // 対応するキャッシュレジスタがない場合regが返る
+       switch (rxx) {
+               case 0:
+                       reg = IA32_REG3_EBX;
+                       break;
+               case 1:
+                       reg = IA32_REG1_ECX;
+                       break;
+               case 2:
+                       reg = IA32_REG2_EDX;
+                       break;
+       }
+       return reg;
+}
+
+void jitCompA000_loadPRegCacheAll(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG6_ESI, PRegOffset(0x01) + 0); /* ESI = P01; */
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG7_EDI, PRegOffset(0x02) + 0); /* EDI = P02; */
+       return;
+}
+
+void jitCompA000_storePRegCacheAll(struct JitCompWork *w)
+{
+       jitCompPutOp_MOV_EBPDisp_GReg(w, PRegOffset(0x01) + 0, IA32_REG6_ESI); /* P01 = ESI; */
+       jitCompPutOp_MOV_EBPDisp_GReg(w, PRegOffset(0x02) + 0, IA32_REG7_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)
+{
+       // 指定されたタイプのデータ幅を返す。
+       // unsigned なら奇数(1bit目がOn)
+       // retv = 1     : VPtr
+       // retv = 2 or 3: BYTE ( 8,  4,  2,  1 bit)
+       // retv = 4 or 5: WORD (16, 12 bit)
+       // retv = 6 or 7: DWORD(32, 20, 24, 28 bit)
+       // -1はエラー
+       int r = -1;
+       
+       if (1 <= t && t <= 7){
+               // 1 - 7はそのままでOK
+               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; }
+       jitCompPutOp_MOV_GReg_EBPDisp(w, IA32_REG0_EAX, PRegOffset(pxx) + 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+?]); */
+       jitCompPutModRM_Disp_BaseEBP(w, PRegOffset(pxx) + 8, reg);      /* p0 */
+       jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */
+       jitCompPutImm32(w->dst, errfnc - (w->dst + 4));
+       jitCompPutByte1(w->dst, 0x3b);  /* CMP(reg, [EBP+?]); */
+       jitCompPutModRM_Disp_BaseEBP(w, PRegOffset(pxx) + 12, reg);     /* p1 */
+       jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */
+       jitCompPutImm32(w->dst, errfnc - (w->dst + 4));
+       return;
+}
+
+#endif