Revisión | e2cd1768d592faab2517f8f8970cd6ba3298ae5c (tree) |
---|---|
Tiempo | 2014-03-15 15:32:33 |
Autor | hikarupsp <hikarupsp@user...> |
Commiter | hikarupsp |
jitcx86.cを分割した。
@@ -2,6 +2,8 @@ | ||
2 | 2 | #ifndef HeavyOSECPU_jitc_h |
3 | 3 | #define HeavyOSECPU_jitc_h |
4 | 4 | |
5 | + | |
6 | + | |
5 | 7 | // Error flags |
6 | 8 | #define JITC_ERR_MASK 255 |
7 | 9 | #define JITC_ERR_PHASE0ONLY 256 |
@@ -52,12 +54,15 @@ int jitCompCmdLen(const unsigned char *src); | ||
52 | 54 | #define envOffset_DBGINFO1 (2304 + 4) |
53 | 55 | // |
54 | 56 | #define jitCompPutImm32(p, i) jitCompPutByte4(p, ((i) & 0xff), (((i) >> 8) & 0xff), (((i) >> 16) & 0xff), (((i) >> 24) & 0xff)) |
57 | +#define jitCompPutOp_XOR_GReg_GReg(p, d, s) jitCompPutByte2(w.dst, 0x31, 0xc0 | (s) << 3 | (d)); | |
58 | +#define jitCompPutOp_MOV_GReg_Imm32(p, dReg, i) jitCompPutByte1(p, 0xb8 | dReg); jitCompPutImm32(p, i); /* MOV(reg0, ?); == [1011 1 reg] imm32 */ | |
55 | 59 | #define jitCompPutOp_PUSHAD(p) jitCompPutByte1(p, 0x60); |
56 | 60 | #define jitCompPutOp_POPAD(p) jitCompPutByte1(p, 0x61); |
57 | 61 | #define jitCompPutOp_PUSH_GReg(p, reg) jitCompPutByte1(p, 0x50 | (reg)); |
58 | 62 | #define jitCompPutOp_POP_GReg(p, reg) jitCompPutByte1(p, 0x58 | (reg)); |
59 | 63 | #define jitCompPutOp_CALL_Relative(p, diff) jitCompPutByte1(w.dst, 0xe8); jitCompPutImm32(&w, j); |
60 | - | |
64 | +// | |
65 | +#define jitCompPutOp_MOV_EAX_ZERO(p) jitCompPutOp_XOR_GReg_GReg(p, IA32_REG0_EAX, IA32_REG0_EAX); | |
61 | 66 | |
62 | 67 | // Optimization settings |
63 | 68 | // 他のCPUへ移植する人へ: |
@@ -81,6 +86,7 @@ struct JitCompWork { | ||
81 | 86 | char prefix; //CND命令の値を記録(初期値=0) |
82 | 87 | }; |
83 | 88 | |
89 | +// @jitcx86a.c | |
84 | 90 | int jitCompGetImm32(const unsigned char *src); |
85 | 91 | int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src); |
86 | 92 | void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n); |
@@ -105,6 +111,9 @@ int jitCompA000_dataWidth(int t); | ||
105 | 111 | void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac); |
106 | 112 | void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac); |
107 | 113 | void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx); |
114 | + | |
115 | +// @jitcx86.c | |
116 | +extern unsigned char *errfnc; | |
108 | 117 | 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); |
109 | 118 | unsigned char *jitCompCallFunc(unsigned char *dst, void *func); |
110 | 119 | unsigned char *jitCompInit(unsigned char *dst); |
@@ -124,14 +133,6 @@ void dbgrMain(HOSECPU_RuntimeEnvironment *r); | ||
124 | 133 | |
125 | 134 | |
126 | 135 | |
127 | - | |
128 | - | |
129 | - | |
130 | - | |
131 | - | |
132 | - | |
133 | - | |
134 | - | |
135 | 136 | #endif |
136 | 137 | |
137 | 138 | #endif |
@@ -5,257 +5,6 @@ | ||
5 | 5 | // |
6 | 6 | // for x86-32bit |
7 | 7 | // |
8 | -int jitCompGetImm32(const unsigned char *src) | |
9 | -{ | |
10 | - return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; | |
11 | -} | |
12 | - | |
13 | -int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) | |
14 | -{ | |
15 | - int i = jitCompGetImm32(src); | |
16 | - if (i < 0 || i >= w->maxLabels) { | |
17 | - w->err = JITC_ERR_LABELNUM; | |
18 | - i = 0; | |
19 | - } | |
20 | - return i; | |
21 | -} | |
22 | - | |
23 | -void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) | |
24 | -{ | |
25 | - disp -= jitCompA0001_EBP128; | |
26 | - if (-128 <= disp && disp <= 127) { | |
27 | - jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); | |
28 | - } else { | |
29 | - // 10 + reg + 101 + disp | |
30 | - jitCompPutByte1(w->dst, 0x85 | (n << 3)); | |
31 | - jitCompPutImm32(w->dst, disp); | |
32 | - } | |
33 | - return; | |
34 | -} | |
35 | - | |
36 | -void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) | |
37 | -{ | |
38 | - // MOV Ev, Gv | |
39 | - // MOV + ModR/M(2Mod + 3Reg + 3R/M) | |
40 | - jitCompPutByte1(w->dst, 0x89); /* 1000 1001 MOV(mem, reg32); */ | |
41 | - jitCompA0001_85DispN(w, disp, reg32); | |
42 | - return; | |
43 | -} | |
44 | - | |
45 | -void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) | |
46 | -{ | |
47 | - jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ | |
48 | - jitCompA0001_85DispN(w, disp, reg32); | |
49 | - return; | |
50 | -} | |
51 | - | |
52 | -void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) | |
53 | -{ | |
54 | -#if (jitCompA0001_USE_R3F_IMM32 != 0) | |
55 | - if (rxx == 0x3f) { | |
56 | - jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ | |
57 | - jitCompPutImm32(w->dst, w->r3f); | |
58 | - return; | |
59 | - } | |
60 | -#endif | |
61 | - if (rxx >= 0x40 || rxx < 0){ | |
62 | - w->err = JITC_ERR_REGNUM; | |
63 | - } | |
64 | - jitCompA0001_movReg32EbpDisp(w, IA32_REG0_EAX, rxx * 4); /* MOV(EAX, [EBP+?]); */ | |
65 | - return; | |
66 | -} | |
67 | - | |
68 | -void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) | |
69 | -{ | |
70 | - if (rxx >= 0x40 || rxx < 0){ | |
71 | - w->err = JITC_ERR_REGNUM; | |
72 | - } | |
73 | - jitCompA0001_movEbpDispReg32(w, rxx * 4, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ | |
74 | - return; | |
75 | -} | |
76 | - | |
77 | -void jitCompA0001_fixPrefix(struct JitCompWork *w) | |
78 | -{ | |
79 | - if (w->prefix != 0) { | |
80 | - if (w->dst - w->dst0 > 127){ | |
81 | - w->err = JITC_ERR_REGNUM; | |
82 | - } | |
83 | - w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); | |
84 | - } | |
85 | - return; | |
86 | -} | |
87 | - | |
88 | -void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) | |
89 | -{ | |
90 | - if (p0 >= 0x3f || p0 < 0){ | |
91 | - w->err = JITC_ERR_PREGNUM; | |
92 | - } | |
93 | - if (p1 >= 0x3f || p1 < 0){ | |
94 | - w->err = JITC_ERR_PREGNUM; | |
95 | - } | |
96 | - /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ | |
97 | - return; | |
98 | -} | |
99 | - | |
100 | -void jitCompA000_loadRegCacheAll(struct JitCompWork *w) | |
101 | -{ | |
102 | - jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ | |
103 | - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ | |
104 | - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ | |
105 | - return; | |
106 | -} | |
107 | - | |
108 | -void jitCompA000_storeRegCacheAll(struct JitCompWork *w) | |
109 | -{ | |
110 | - jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ | |
111 | - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ | |
112 | - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ | |
113 | - return; | |
114 | -} | |
115 | - | |
116 | -void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) | |
117 | -{ | |
118 | - jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ | |
119 | - return; | |
120 | -} | |
121 | - | |
122 | -void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) | |
123 | -{ | |
124 | - jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ | |
125 | - return; | |
126 | -} | |
127 | - | |
128 | -void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) | |
129 | -{ | |
130 | - jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ | |
131 | - return; | |
132 | -} | |
133 | - | |
134 | -void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) | |
135 | -{ | |
136 | - jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ | |
137 | - return; | |
138 | -} | |
139 | - | |
140 | -int jitCompA000_selectRegCache(int rxx, int reg) | |
141 | -{ | |
142 | - switch (rxx) { | |
143 | - case 0: | |
144 | - //EBX | |
145 | - reg = 3; | |
146 | - break; | |
147 | - case 1: | |
148 | - //ECX | |
149 | - reg = 1; | |
150 | - break; | |
151 | - case 2: | |
152 | - //EDX | |
153 | - reg = 2; | |
154 | - break; | |
155 | - } | |
156 | - return reg; | |
157 | -} | |
158 | - | |
159 | -void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) | |
160 | -{ | |
161 | - // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ | |
162 | - jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ | |
163 | - jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ | |
164 | - return; | |
165 | -} | |
166 | - | |
167 | -void jitCompA000_storePRegCacheAll(struct JitCompWork *w) | |
168 | -{ | |
169 | - // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ | |
170 | - jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ | |
171 | - jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ | |
172 | - return; | |
173 | -} | |
174 | - | |
175 | -int jitCompA000_selectPRegCache(int pxx, int reg) | |
176 | -{ | |
177 | - // if (pxx == 0) reg = 5; /* EBP */ | |
178 | - switch (pxx) { | |
179 | - case 1: | |
180 | - //ESI | |
181 | - reg = 6; | |
182 | - break; | |
183 | - | |
184 | - case 2: | |
185 | - //EDI | |
186 | - reg = 7; | |
187 | - break; | |
188 | - } | |
189 | - return reg; | |
190 | -} | |
191 | - | |
192 | -int jitCompA000_convTyp(int t) | |
193 | -{ | |
194 | - int r = -1; | |
195 | - | |
196 | - if (1 <= t && t <= 7){ | |
197 | - r = t; | |
198 | - } else if (8 <= t && t <= 13){ | |
199 | - r = 2 | (t & 1); | |
200 | - } else if (14 <= t && t <= 15){ | |
201 | - r = 4 | (t & 1); | |
202 | - } else if (16 <= t && t <= 21){ | |
203 | - r = 6 | (t & 1); | |
204 | - } | |
205 | - return r; | |
206 | -} | |
207 | - | |
208 | -int jitCompA000_dataWidth(int t) | |
209 | -{ | |
210 | - int r = -1; | |
211 | - if (t == 0x0001) r = 256; | |
212 | - t >>= 1; | |
213 | - if (t == 0x0002 / 2) r = 8; | |
214 | - if (t == 0x0004 / 2) r = 16; | |
215 | - if (t == 0x0006 / 2) r = 32; | |
216 | - if (t == 0x0008 / 2) r = 4; | |
217 | - if (t == 0x000a / 2) r = 2; | |
218 | - if (t == 0x000c / 2) r = 1; | |
219 | - if (t == 0x000e / 2) r = 12; | |
220 | - if (t == 0x0010 / 2) r = 20; | |
221 | - if (t == 0x0012 / 2) r = 24; | |
222 | - if (t == 0x0014 / 2) r = 28; | |
223 | - return r; | |
224 | -} | |
225 | - | |
226 | -static unsigned char *errfnc; | |
227 | - | |
228 | -void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) | |
229 | -{ | |
230 | - if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } | |
231 | - if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } | |
232 | - jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ | |
233 | - jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ | |
234 | - jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ | |
235 | - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
236 | - return; | |
237 | -} | |
238 | - | |
239 | -void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) | |
240 | -// data用. | |
241 | -// 将来的にはaliveやアクセス権チェックも入れる | |
242 | -{ | |
243 | - jitCompA0001_checkType0(w, pxx, typ, ac); | |
244 | - return; | |
245 | -} | |
246 | - | |
247 | -void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) | |
248 | -{ | |
249 | - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ | |
250 | - jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ | |
251 | - jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ | |
252 | - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
253 | - jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ | |
254 | - jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ | |
255 | - jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ | |
256 | - jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
257 | - return; | |
258 | -} | |
259 | 8 | |
260 | 9 | // F5の場合、decoderが対応するalloc-freeを結びつけるのが簡単で、typやlenを指定必須にしてもフロントエンドコードに影響はない. |
261 | 10 | 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 | ||
285 | 34 | jitCompA000_loadPRegCacheAll(&w); |
286 | 35 | } |
287 | 36 | if (level <= JITC_LV_SLOWER) { |
288 | - // XOR(EAX, EAX); | |
289 | - jitCompPutByte2(w.dst, 0x31, 0xc0); | |
37 | + // debugInfo0 <- 0; | |
38 | + // | |
39 | + jitCompPutOp_MOV_EAX_ZERO(w.dst); | |
290 | 40 | // MOV(debugInfo0, EAX); |
291 | 41 | jitCompA0001_movEbpDispReg32(&w, envOffset_DBGINFO0, IA32_REG0_EAX); |
292 | - // MOV(EAX, ?); | |
293 | - jitCompPutByte1(w.dst, 0xb8); /* MOV(EAX, imm32); */ | |
294 | - jitCompPutImm32(w.dst, debugInfo1); | |
42 | + jitCompPutOp_MOV_GReg_Imm32(w.dst, IA32_REG0_EAX, debugInfo1); | |
295 | 43 | jitCompA0001_movEbpDispReg32(&w, envOffset_DBGINFO1, IA32_REG0_EAX); /* MOV(debugInfo1, EAX); */ |
296 | 44 | } |
297 | 45 | while (src < src1) { |
298 | 46 | w.prefix = 0; //0x04 CND 命令で変更される |
299 | - if (w.dst + 256 > dst1) { w.err = JITC_ERR_DST1; goto err_w; } // 書き込み領域が残り256バイト未満ならエラー | |
47 | + if (w.dst + 256 > dst1) { | |
48 | + // 書き込み領域が残り256バイト未満ならエラー | |
49 | + w.err = JITC_ERR_DST1; goto err_w; | |
50 | + } | |
300 | 51 | timecount++; |
301 | 52 | if (timecount >= 64) { |
302 | 53 | timecount -= 64; |
303 | 54 | /* 未完成(timeoutチェックコードを入れる) */ |
304 | 55 | } |
305 | - prefix_continue: // CND命令実行後ここに戻る | |
56 | + prefix_continue: | |
57 | + // CND命令コンパイル後ここに戻る | |
306 | 58 | switch (*src) { |
307 | - | |
308 | - case 0x00: /* NOP */ | |
309 | - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } // 「条件付きでNOPを実行」するなんて、矛盾している! | |
59 | + case 0x00: | |
60 | + // NOP | |
61 | + if (w.prefix != 0) { | |
62 | + // 「条件付きでNOPを実行」するなんて、矛盾している! | |
63 | + w.err = JITC_ERR_PREFIX; goto err_w; | |
64 | + } | |
310 | 65 | break; |
311 | 66 | |
312 | - case 0x01: /* LB */ | |
313 | - | |
314 | - /* | |
315 | - * LB : ラベル設置命令。(6byte) | |
316 | - * ・prefex = 1にする | |
317 | - * ・timecount++し、timecountのチェックをする。 | |
318 | - * ・ラベル位置を登録する。 | |
319 | - * ・割り込みがある場合、このタイミングで割り込みを発生させる。 | |
320 | - * | |
321 | - * 1 2 3 456 | |
322 | - * LB 01 opt imm32 | |
323 | - * | |
324 | - */ | |
325 | - | |
67 | + case 0x01: | |
68 | + // LB : ラベル設置命令。(6byte) | |
69 | + // ・prefex = 1にする | |
70 | + // ・timecount++し、timecountのチェックをする。 | |
71 | + // ・ラベル位置を登録する。 | |
72 | + // ・割り込みがある場合、このタイミングで割り込みを発生させる。 | |
73 | + // | |
74 | + // 1 2 3 456 | |
75 | + // LB 01 opt imm32 | |
76 | + // | |
326 | 77 | if (enter0 == NULL && (src[6] == 0x3c /* 多数のレジスタをスタックに退避 */ || (src[6] == 0xfe/* REMARK */ && src[7] == 0x01 && src[9] == 0x3c))) { //beginFunc()中のLB |
327 | 78 | // LB命令の後に0x3C命令・・・beginFunc() |
328 | 79 | jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする |
329 | 80 | enter0 = w.dst; |
330 | 81 | jitCompPutImm32(w.dst, 0); // 飛び相対座標が0 ・・・パイプラインのフラッシュ?? |
331 | 82 | } |
332 | - if (src[6] == 0x34) { // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 | |
83 | + if (src[6] == 0x34) { | |
84 | + // LBの次の命令がDATA ・・・DAT_SA0(label, typ32, length) ・・・メモリ確保命令 | |
333 | 85 | tmp_ucp = w.dst; |
334 | 86 | jitCompPutByte1(w.dst, 0xe9); // (x86) JMP rel32 : 次の命令との相対オフセットだけ相対ニアジャンプする |
335 | 87 | i = jitCompGetImm32(&src[7]); // type32 を取得 |
@@ -337,9 +89,20 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
337 | 89 | if (i != 1) { |
338 | 90 | i = jitCompA000_convTyp(i); |
339 | 91 | j = 0; |
340 | - if (i == 2 || i == 3) { j = 1; } | |
341 | - if (i == 4 || i == 5) { j = 2; } | |
342 | - if (i == 6 || i == 7) { j = 4; } | |
92 | + switch (i) { | |
93 | + case 2: | |
94 | + case 3: | |
95 | + j = 1; | |
96 | + break; | |
97 | + case 4: | |
98 | + case 5: | |
99 | + j = 2; | |
100 | + break; | |
101 | + case 6: | |
102 | + case 7: | |
103 | + j = 4; | |
104 | + break; | |
105 | + } | |
343 | 106 | } |
344 | 107 | j *= jitCompGetImm32(&src[11]); |
345 | 108 | if (j <= 0) w.err = JITC_ERR_BADTYPE; |
@@ -375,9 +138,14 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
375 | 138 | } |
376 | 139 | if ((flags & JITC_PHASE1) == 0) { |
377 | 140 | i = jitCompGetLabelNum(&w, src + 2); |
378 | - //printf("i=%06X %06X\n", i, src-src0); | |
379 | - if (label[i].opt != 0 && w.err == 0) { w.err = JITC_ERR_LABELREDEF; goto err_w; } | |
380 | - if (w.prefix != 0) { w.err = JITC_ERR_PREFIX; goto err_w; } | |
141 | + if (label[i].opt != 0 && w.err == 0) { | |
142 | + w.err = JITC_ERR_LABELREDEF; | |
143 | + goto err_w; | |
144 | + } | |
145 | + if (w.prefix != 0) { | |
146 | + w.err = JITC_ERR_PREFIX; | |
147 | + goto err_w; | |
148 | + } | |
381 | 149 | label[i].opt = src[1] + 1; |
382 | 150 | label[i].typ = 0; /* TYP_CODE */ |
383 | 151 | label[i].p = w.dst; |
@@ -389,71 +157,85 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
389 | 157 | /* 未完成(timeoutチェックコードを入れる) */ |
390 | 158 | break; |
391 | 159 | |
392 | - case 0x02: /* LIMM */ | |
393 | - | |
394 | - /* | |
395 | - * LIMM : 定数即値代入命令(6byte) | |
396 | - * | |
397 | - * 1 2 3456 | |
398 | - * 02 reg0R imm32 | |
399 | - * | |
400 | - * ・reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 | |
401 | - */ | |
160 | + case 0x02: | |
161 | + // LIMM : 定数即値代入命令(6byte) | |
162 | + // 1 2 3456 | |
163 | + // 02 reg0R imm32 | |
164 | + // | |
165 | + // reg3F は条件比較慣用句指定用&演算命令即値慣用句指定用。よってCND命令の直後では使用できない。 | |
402 | 166 | |
403 | - if (src[1] == 0x3f && w.prefix != 0) w.err = JITC_ERR_PREFIX; // CND命令の直後でR3Fを書き換えるなんて変だよね | |
167 | + if (src[1] == 0x3f && w.prefix != 0){ | |
168 | + // CND命令の直後でR3Fを書き換えるなんて変だよね | |
169 | + w.err = JITC_ERR_PREFIX; | |
170 | + } | |
404 | 171 | |
405 | 172 | #if (jitCompA0001_USE_R3F_IMM32 != 0) |
406 | - if (src[1] == 0x3f) { // R3Fへの代入は例外敵に、 w.r3f を使用 | |
173 | + if (src[1] == 0x3f) { | |
174 | + // R3Fへの代入は例外で、 w.r3f を使用 | |
407 | 175 | w.r3f = jitCompGetImm32(src + 2); |
408 | 176 | break; |
409 | 177 | } |
410 | 178 | #endif |
411 | 179 | i = jitCompGetImm32(src + 2); // 与えられた即値(第二引数)を取得 |
412 | - | |
413 | 180 | /* R00-R02 なら EBX, ECX, EDX 、それ以外なら EAX のレジスタIDを reg0 に代入 */ |
414 | 181 | reg0 = jitCompA000_selectRegCache(src[1], IA32_REG0_EAX); |
415 | - | |
182 | + | |
416 | 183 | #if (jitCompA0001_OPTIMIZE_MOV != 0) |
184 | + // size optimization | |
185 | + // MOV reg, 0 -> XOR reg, reg | |
417 | 186 | if (i == 0) { |
418 | - jitCompPutByte2(w.dst, 0x31, 0xc0 | reg0 << 3 | reg0); /* XOR(reg0, reg0); */ | |
187 | + jitCompPutOp_XOR_GReg_GReg(w.dst, reg0, reg0); | |
419 | 188 | jitCompA0001_movRxxEax(&w, src[1]); |
420 | 189 | break; |
421 | 190 | } |
422 | 191 | #endif |
423 | - | |
424 | 192 | /* reg0 のレジスタに対応したMOV命令を発行 */ |
425 | - jitCompPutByte1(w.dst, 0xb8 | reg0); /* MOV(reg0, ?); == 10111000b+wr imm32 */ | |
426 | - jitCompPutImm32(w.dst, i); | |
193 | + jitCompPutOp_MOV_GReg_Imm32(w.dst, reg0, i); | |
427 | 194 | |
428 | - if (reg0 == 0) // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 | |
429 | - | |
195 | + if (reg0 == 0){ | |
196 | + // R03以降の、レジスタの内容をメモリ上に格納してエミュレートする場合 | |
430 | 197 | jitCompA0001_movRxxEax(&w, src[1]); |
431 | - break; | |
198 | + } | |
432 | 199 | |
433 | - case 0x03: /* PLIMM */ /* 未完成(plsまで対応) */ | |
200 | + break; | |
434 | 201 | |
435 | - /* | |
436 | - * PLIMM : ラベル番号代入命令(6byte) | |
437 | - * | |
438 | - * 1 2 3456 | |
439 | - * 03 PXX imm32 | |
440 | - * | |
441 | - * ・P28 はAPI用 | |
442 | - * ・P30 はリターンアドレス | |
443 | - * ・P3F はプログラムカウンタ | |
444 | - */ | |
202 | + case 0x03: /* 未完成(plsまで対応) */ | |
203 | + // PLIMM : ラベル番号代入命令(6byte) | |
204 | + // | |
205 | + // 1 2 3456 | |
206 | + // 03 PXX imm32 | |
207 | + // | |
208 | + // ・P28 はAPI用 | |
209 | + // ・P30 はリターンアドレス | |
210 | + // ・P3F はプログラムカウンタ | |
211 | + // | |
445 | 212 | |
446 | 213 | i = jitCompGetLabelNum(&w, src + 2); // Pxxに代入するラベルの番号(第二引数) |
447 | - if ((flags & JITC_PHASE1) != 0 && w.err == 0) { // Phase 1であるならば | |
448 | - if (label[i].opt == 0) { w.err = JITC_ERR_LABELNODEF; goto err_w; } // 指定されたラベル番号は存在しない | |
449 | - if (src[1] != 0x3f && label[i].opt != 2) { w.err = JITC_ERR_LABELTYP; goto err_w; } // | |
450 | - if (src[1] == 0x3f && label[i].typ != 0) { w.err = JITC_ERR_LABELTYP; goto err_w; } // プログラムカウンタに TYP_CODEでない値は代入できない | |
214 | + if ((flags & JITC_PHASE1) != 0 && w.err == 0) { | |
215 | + // Phase 1であるならば | |
216 | + if (label[i].opt == 0) { | |
217 | + // 指定されたラベル番号は存在しない | |
218 | + w.err = JITC_ERR_LABELNODEF; | |
219 | + goto err_w; | |
220 | + } | |
221 | + if (src[1] != 0x3f && label[i].opt != 2) { | |
222 | + // ? | |
223 | + w.err = JITC_ERR_LABELTYP; | |
224 | + goto err_w; | |
225 | + } | |
226 | + if (src[1] == 0x3f && label[i].typ != 0) { | |
227 | + // プログラムカウンタに TYP_CODEでない値は代入できない | |
228 | + w.err = JITC_ERR_LABELTYP; | |
229 | + goto err_w; | |
230 | + } | |
451 | 231 | } |
452 | - if (src[1] == 0x3f) { // プログラムカウンタへの代入なら | |
453 | - if (w.prefix == 0) { // CND命令による条件付きでなければ、即座に移動 | |
232 | + if (src[1] == 0x3f) { | |
233 | + // プログラムカウンタへの代入 | |
234 | + if (w.prefix == 0) { | |
235 | + // CND命令による条件付きでなければ、即座に移動 | |
454 | 236 | jitCompPutByte1(w.dst, 0xe9); /* JMP(?); */ |
455 | - } | |
456 | - else { // 直前はCND命令。 | |
237 | + } else { | |
238 | + // 直前はCND命令。 | |
457 | 239 | |
458 | 240 | /* |
459 | 241 | * CND命令 |
@@ -463,7 +245,8 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
463 | 245 | * いま、dstの末端はJZ命令になっている。 0x0F 0x84 cd |
464 | 246 | */ |
465 | 247 | |
466 | - // JZのとび先アドレスの書き換え? | |
248 | + // Jccの条件変更 | |
249 | + // 0F 75 | |
467 | 250 | w.dst[-1] = w.dst[-2] ^ 0xf1; /* 74->85, 75->84 */ |
468 | 251 | w.dst[-2] = 0x0f; |
469 | 252 |
@@ -488,8 +271,7 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
488 | 271 | jitCompPutByte1(w.dst, j & 0xff); |
489 | 272 | } |
490 | 273 | #endif |
491 | - } | |
492 | - else { // プログラムカウンタ以外への代入 | |
274 | + } else { // プログラムカウンタ以外への代入 | |
493 | 275 | |
494 | 276 | // 代入先が P01, P02なら ESI, EDI,それ以外ならEAXを指定 |
495 | 277 | reg0 = jitCompA000_selectPRegCache(src[1], IA32_REG0_EAX); |
@@ -516,14 +298,15 @@ int jitCompiler(unsigned char *dst, unsigned char *dst1, const unsigned char *sr | ||
516 | 298 | } |
517 | 299 | break; |
518 | 300 | |
519 | - case 0x04: /* CND (prefix) */ | |
520 | - | |
521 | - /* | |
522 | - * CND命令 | |
523 | - * 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 | |
524 | - */ | |
525 | - | |
526 | - if (src[1] >= 0x40) w.err = JITC_ERR_REGNUM; // R00-R3F 以外のレジスタは比較対象にできない | |
301 | + case 0x04: | |
302 | + // CND (prefix) | |
303 | + // 与えられたRxxの最下位ビットが1であれば後続の命令を実行、そうでなければ飛ばす。 | |
304 | + // | |
305 | + if (src[1] >= 0x40){ | |
306 | + // R00-R3F 以外のレジスタは比較対象にできない | |
307 | + w.err = JITC_ERR_REGNUM; | |
308 | + goto err_w; | |
309 | + } | |
527 | 310 | |
528 | 311 | // 比較対象のレジスタがメモリ上にあれば-1, それ以外なら適切なレジスタ番号を返す |
529 | 312 | reg0 = jitCompA000_selectRegCache(src[1], -1 /* mem */); |
@@ -0,0 +1,260 @@ | ||
1 | +#include "osecpu.h" | |
2 | +#include "jitc.h" | |
3 | + | |
4 | +#if (JITC_ARCNUM == 0x0001) | |
5 | +// | |
6 | +// for x86-32bit | |
7 | +// | |
8 | +int jitCompGetImm32(const unsigned char *src) | |
9 | +{ | |
10 | + return (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; | |
11 | +} | |
12 | + | |
13 | +int jitCompGetLabelNum(struct JitCompWork *w, const unsigned char *src) | |
14 | +{ | |
15 | + int i = jitCompGetImm32(src); | |
16 | + if (i < 0 || i >= w->maxLabels) { | |
17 | + w->err = JITC_ERR_LABELNUM; | |
18 | + i = 0; | |
19 | + } | |
20 | + return i; | |
21 | +} | |
22 | + | |
23 | +void jitCompA0001_85DispN(struct JitCompWork *w, int disp, int n) | |
24 | +{ | |
25 | + disp -= jitCompA0001_EBP128; | |
26 | + if (-128 <= disp && disp <= 127) { | |
27 | + jitCompPutByte2(w->dst, 0x45 | (n << 3), disp & 0xff); | |
28 | + } else { | |
29 | + // 10 + reg + 101 + disp | |
30 | + jitCompPutByte1(w->dst, 0x85 | (n << 3)); | |
31 | + jitCompPutImm32(w->dst, disp); | |
32 | + } | |
33 | + return; | |
34 | +} | |
35 | + | |
36 | +void jitCompA0001_movEbpDispReg32(struct JitCompWork *w, int disp, int reg32) | |
37 | +{ | |
38 | + // MOV Ev, Gv | |
39 | + // MOV + ModR/M(2Mod + 3Reg + 3R/M) | |
40 | + jitCompPutByte1(w->dst, 0x89); /* 1000 1001 MOV(mem, reg32); */ | |
41 | + jitCompA0001_85DispN(w, disp, reg32); | |
42 | + return; | |
43 | +} | |
44 | + | |
45 | +void jitCompA0001_movReg32EbpDisp(struct JitCompWork *w, int reg32, int disp) | |
46 | +{ | |
47 | + jitCompPutByte1(w->dst, 0x8b); /* MOV(reg32, mem); */ | |
48 | + jitCompA0001_85DispN(w, disp, reg32); | |
49 | + return; | |
50 | +} | |
51 | + | |
52 | +void jitCompA0001_movEaxRxx(struct JitCompWork *w, int rxx) | |
53 | +{ | |
54 | +#if (jitCompA0001_USE_R3F_IMM32 != 0) | |
55 | + if (rxx == 0x3f) { | |
56 | + jitCompPutByte1(w->dst, 0xb8); /* MOV(EAX, ?); */ | |
57 | + jitCompPutImm32(w->dst, w->r3f); | |
58 | + return; | |
59 | + } | |
60 | +#endif | |
61 | + if (rxx >= 0x40 || rxx < 0){ | |
62 | + w->err = JITC_ERR_REGNUM; | |
63 | + } | |
64 | + jitCompA0001_movReg32EbpDisp(w, IA32_REG0_EAX, rxx * 4); /* MOV(EAX, [EBP+?]); */ | |
65 | + return; | |
66 | +} | |
67 | + | |
68 | +void jitCompA0001_movRxxEax(struct JitCompWork *w, int rxx) | |
69 | +{ | |
70 | + if (rxx >= 0x40 || rxx < 0){ | |
71 | + w->err = JITC_ERR_REGNUM; | |
72 | + } | |
73 | + jitCompA0001_movEbpDispReg32(w, rxx * 4, IA32_REG0_EAX); /* MOV([EBP+?], EAX); */ | |
74 | + return; | |
75 | +} | |
76 | + | |
77 | +void jitCompA0001_fixPrefix(struct JitCompWork *w) | |
78 | +{ | |
79 | + if (w->prefix != 0) { | |
80 | + if (w->dst - w->dst0 > 127){ | |
81 | + w->err = JITC_ERR_REGNUM; | |
82 | + } | |
83 | + w->dst0[-1] = (unsigned char)((w->dst - w->dst0) & 0xff); | |
84 | + } | |
85 | + return; | |
86 | +} | |
87 | + | |
88 | +void jitCompA0001_checkCompPtr(struct JitCompWork *w, int p0, int p1) | |
89 | +{ | |
90 | + if (p0 >= 0x3f || p0 < 0){ | |
91 | + w->err = JITC_ERR_PREGNUM; | |
92 | + } | |
93 | + if (p1 >= 0x3f || p1 < 0){ | |
94 | + w->err = JITC_ERR_PREGNUM; | |
95 | + } | |
96 | + /* 比較可能可能なのかのチェックのコードを出力 */ /* 未完成 */ | |
97 | + return; | |
98 | +} | |
99 | + | |
100 | +void jitCompA000_loadRegCacheAll(struct JitCompWork *w) | |
101 | +{ | |
102 | + jitCompA0001_movReg32EbpDisp(w, 3 /* EBX */, 0 * 4); /* EBX = R00; */ | |
103 | + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ | |
104 | + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ | |
105 | + return; | |
106 | +} | |
107 | + | |
108 | +void jitCompA000_storeRegCacheAll(struct JitCompWork *w) | |
109 | +{ | |
110 | + jitCompA0001_movEbpDispReg32(w, 0 * 4, 3 /* EBX */); /* R00 = EBX; */ | |
111 | + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ | |
112 | + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ | |
113 | + return; | |
114 | +} | |
115 | + | |
116 | +void jitCompA000_loadRegCacheEcx(struct JitCompWork *w) | |
117 | +{ | |
118 | + jitCompA0001_movReg32EbpDisp(w, 1 /* ECX */, 1 * 4); /* ECX = R01; */ | |
119 | + return; | |
120 | +} | |
121 | + | |
122 | +void jitCompA000_storeRegCacheEcx(struct JitCompWork *w) | |
123 | +{ | |
124 | + jitCompA0001_movEbpDispReg32(w, 1 * 4, 1 /* ECX */); /* R01 = ECX; */ | |
125 | + return; | |
126 | +} | |
127 | + | |
128 | +void jitCompA000_loadRegCacheEdx(struct JitCompWork *w) | |
129 | +{ | |
130 | + jitCompA0001_movReg32EbpDisp(w, 2 /* EDX */, 2 * 4); /* EDX = R02; */ | |
131 | + return; | |
132 | +} | |
133 | + | |
134 | +void jitCompA000_storeRegCacheEdx(struct JitCompWork *w) | |
135 | +{ | |
136 | + jitCompA0001_movEbpDispReg32(w, 2 * 4, 2 /* EDX */); /* R02 = EDX; */ | |
137 | + return; | |
138 | +} | |
139 | + | |
140 | +int jitCompA000_selectRegCache(int rxx, int reg) | |
141 | +{ | |
142 | + switch (rxx) { | |
143 | + case 0: | |
144 | + //EBX | |
145 | + reg = 3; | |
146 | + break; | |
147 | + case 1: | |
148 | + //ECX | |
149 | + reg = 1; | |
150 | + break; | |
151 | + case 2: | |
152 | + //EDX | |
153 | + reg = 2; | |
154 | + break; | |
155 | + } | |
156 | + return reg; | |
157 | +} | |
158 | + | |
159 | +void jitCompA000_loadPRegCacheAll(struct JitCompWork *w) | |
160 | +{ | |
161 | + // jitCompA0001_movReg32EbpDisp(w, 5 /* EBP */, 256 + 0 * 32 + 0); /* EBP = P00; */ | |
162 | + jitCompA0001_movReg32EbpDisp(w, 6 /* ESI */, 256 + 1 * 32 + 0); /* ESI = P01; */ | |
163 | + jitCompA0001_movReg32EbpDisp(w, 7 /* EDI */, 256 + 2 * 32 + 0); /* EDI = P02; */ | |
164 | + return; | |
165 | +} | |
166 | + | |
167 | +void jitCompA000_storePRegCacheAll(struct JitCompWork *w) | |
168 | +{ | |
169 | + // jitCompA0001_movEbpDispReg32(w, 256 + 0 * 32 + 0, 5 /* EBP */); /* P00 = EBP; */ | |
170 | + jitCompA0001_movEbpDispReg32(w, 256 + 1 * 32 + 0, 6 /* ESI */); /* P01 = ESI; */ | |
171 | + jitCompA0001_movEbpDispReg32(w, 256 + 2 * 32 + 0, 7 /* EDI */); /* P02 = EDI; */ | |
172 | + return; | |
173 | +} | |
174 | + | |
175 | +int jitCompA000_selectPRegCache(int pxx, int reg) | |
176 | +{ | |
177 | + // if (pxx == 0) reg = 5; /* EBP */ | |
178 | + switch (pxx) { | |
179 | + case 1: | |
180 | + //ESI | |
181 | + reg = 6; | |
182 | + break; | |
183 | + | |
184 | + case 2: | |
185 | + //EDI | |
186 | + reg = 7; | |
187 | + break; | |
188 | + } | |
189 | + return reg; | |
190 | +} | |
191 | + | |
192 | +int jitCompA000_convTyp(int t) | |
193 | +{ | |
194 | + int r = -1; | |
195 | + | |
196 | + if (1 <= t && t <= 7){ | |
197 | + r = t; | |
198 | + } else if (8 <= t && t <= 13){ | |
199 | + r = 2 | (t & 1); | |
200 | + } else if (14 <= t && t <= 15){ | |
201 | + r = 4 | (t & 1); | |
202 | + } else if (16 <= t && t <= 21){ | |
203 | + r = 6 | (t & 1); | |
204 | + } | |
205 | + return r; | |
206 | +} | |
207 | + | |
208 | +int jitCompA000_dataWidth(int t) | |
209 | +{ | |
210 | + int r = -1; | |
211 | + if (t == 0x0001) r = 256; | |
212 | + t >>= 1; | |
213 | + if (t == 0x0002 / 2) r = 8; | |
214 | + if (t == 0x0004 / 2) r = 16; | |
215 | + if (t == 0x0006 / 2) r = 32; | |
216 | + if (t == 0x0008 / 2) r = 4; | |
217 | + if (t == 0x000a / 2) r = 2; | |
218 | + if (t == 0x000c / 2) r = 1; | |
219 | + if (t == 0x000e / 2) r = 12; | |
220 | + if (t == 0x0010 / 2) r = 20; | |
221 | + if (t == 0x0012 / 2) r = 24; | |
222 | + if (t == 0x0014 / 2) r = 28; | |
223 | + return r; | |
224 | +} | |
225 | + | |
226 | +unsigned char *errfnc; | |
227 | + | |
228 | +void jitCompA0001_checkType0(struct JitCompWork *w, int pxx, int typ, int ac) | |
229 | +{ | |
230 | + if (typ <= 0) { w->err = JITC_ERR_BADTYPE; } | |
231 | + if (typ > 0x7f) { w->err = JITC_ERR_INTERNAL; } | |
232 | + jitCompA0001_movReg32EbpDisp(w, 0 /* EAX */, 256 + pxx * 32 + 4); /* MOV(EAX, [EBP+?]); */ /* typ */ | |
233 | + jitCompPutByte3(w->dst, 0x83, 0xf8, typ & 0x7f); /* CMP(EAX, ?); */ | |
234 | + jitCompPutByte2(w->dst, 0x0f, 0x85); /* JNE */ | |
235 | + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
236 | + return; | |
237 | +} | |
238 | + | |
239 | +void jitCompA0001_checkType(struct JitCompWork *w, int pxx, int typ, int ac) | |
240 | +// data用. | |
241 | +// 将来的にはaliveやアクセス権チェックも入れる | |
242 | +{ | |
243 | + jitCompA0001_checkType0(w, pxx, typ, ac); | |
244 | + return; | |
245 | +} | |
246 | + | |
247 | +void jitCompA0001_checkLimit(struct JitCompWork *w, int reg, int pxx) | |
248 | +{ | |
249 | + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ | |
250 | + jitCompA0001_85DispN(w, 256 + pxx * 32 + 8, reg); /* p0 */ | |
251 | + jitCompPutByte2(w->dst, 0x0f, 0x82); /* JB */ | |
252 | + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
253 | + jitCompPutByte1(w->dst, 0x3b); /* CMP(reg, [EBP+?]); */ | |
254 | + jitCompA0001_85DispN(w, 256 + pxx * 32 + 12, reg); /* p1 */ | |
255 | + jitCompPutByte2(w->dst, 0x0f, 0x83); /* JAE */ | |
256 | + jitCompPutImm32(w->dst, errfnc - (w->dst + 4)); | |
257 | + return; | |
258 | +} | |
259 | + | |
260 | +#endif |