2 * ================================================================
3 * SourcePawn (C)2004-2007 AlliedModders LLC. All rights reserved.
4 * ================================================================
6 * This file is not open source and may not be copied without explicit
7 * written permission of AlliedModders LLC. This file may not be redistributed
8 * in whole or significant part.
9 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
18 #include "opcode_helpers.h"
19 #include "x86_macros.h"
20 #include "jit_version.h"
22 #if defined USE_UNGEN_OPCODES
23 #include "ungen_opcodes.h"
26 inline void WriteOp_Move_Pri(JitWriter *jit)
29 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
32 inline void WriteOp_Move_Alt(JitWriter *jit)
35 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
38 inline void WriteOp_Xchg(JitWriter *jit)
41 IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
44 inline void WriteOp_Push(JitWriter *jit)
46 //push stack, DAT offset based
48 //mov ecx, [ebp+<val>]
50 cell_t val = jit->read_cell();
51 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
52 //optimize encoding a bit...
53 if (val < SCHAR_MAX && val > SCHAR_MIN)
55 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
57 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
59 IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
62 inline void WriteOp_Push_C(JitWriter *jit)
67 cell_t val = jit->read_cell();
68 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
69 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
72 inline void WriteOp_Zero(JitWriter *jit)
75 cell_t val = jit->read_cell();
76 if (val < SCHAR_MAX && val > SCHAR_MIN)
78 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val);
80 IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
84 inline void WriteOp_Zero_S(JitWriter *jit)
87 cell_t val = jit->read_cell();
88 if (val < SCHAR_MAX && val > SCHAR_MIN)
90 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val);
92 IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
96 inline void WriteOp_Push_S(JitWriter *jit)
98 //push stack, FRM offset based
100 //mov ecx, [ebx+<val>]
102 cell_t val = jit->read_cell();
103 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
104 //optimize encoding a bit...
105 if (val < SCHAR_MAX && val > SCHAR_MIN)
107 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
109 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
111 IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
114 inline void WriteOp_Push_Pri(JitWriter *jit)
118 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
119 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
122 inline void WriteOp_Push_Alt(JitWriter *jit)
126 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
127 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
130 inline void WriteOp_Push2_C(JitWriter *jit)
132 Macro_PushN_C(jit, 2);
135 inline void WriteOp_Push3_C(JitWriter *jit)
137 Macro_PushN_C(jit, 3);
140 inline void WriteOp_Push4_C(JitWriter *jit)
142 Macro_PushN_C(jit, 4);
145 inline void WriteOp_Push5_C(JitWriter *jit)
147 Macro_PushN_C(jit, 5);
150 inline void WriteOp_Push2_Adr(JitWriter *jit)
152 Macro_PushN_Addr(jit, 2);
155 inline void WriteOp_Push3_Adr(JitWriter *jit)
157 Macro_PushN_Addr(jit, 3);
160 inline void WriteOp_Push4_Adr(JitWriter *jit)
162 Macro_PushN_Addr(jit, 4);
165 inline void WriteOp_Push5_Adr(JitWriter *jit)
167 Macro_PushN_Addr(jit, 5);
170 inline void WriteOp_Push2_S(JitWriter *jit)
172 Macro_PushN_S(jit, 2);
175 inline void WriteOp_Push3_S(JitWriter *jit)
177 Macro_PushN_S(jit, 3);
180 inline void WriteOp_Push4_S(JitWriter *jit)
182 Macro_PushN_S(jit, 4);
185 inline void WriteOp_Push5_S(JitWriter *jit)
187 Macro_PushN_S(jit, 5);
190 inline void WriteOp_Push5(JitWriter *jit)
195 inline void WriteOp_Push4(JitWriter *jit)
200 inline void WriteOp_Push3(JitWriter *jit)
205 inline void WriteOp_Push2(JitWriter *jit)
210 inline void WriteOp_Zero_Pri(JitWriter *jit)
213 IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
216 inline void WriteOp_Zero_Alt(JitWriter *jit)
219 IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
222 inline void WriteOp_Add(JitWriter *jit)
225 IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
228 inline void WriteOp_Sub(JitWriter *jit)
231 IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
234 inline void WriteOp_Sub_Alt(JitWriter *jit)
238 IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
239 IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
242 inline void WriteOp_Proc(JitWriter *jit)
244 /* align this to four byte boundaries!
245 * This is a decent optimization - x86 likes calls to be properly aligned, otherwise there's an alignment exception
246 * Since all calls are jumped to by relocation, the nops/garbage will never be hit by the runtime process.
247 * Just in case, we guard this memory with INT3 to break into the debugger.
249 jitoffs_t cur_offs = jit->get_outputpos();
250 CompData *co = (CompData *)jit->data;
253 cur_offs = 4 - (cur_offs % 4);
254 for (unsigned int i=0; i<cur_offs; i++)
256 jit->write_ubyte(IA32_INT3);
260 /* Write the info struct about this function */
261 jit->write_uint32(JIT_FUNCMAGIC);
262 jit->write_uint32(co->func_idx);
264 /* Now we have to backpatch our reloction offset! */
266 jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
267 jitcode_t rebase = ((CompData *)jit->data)->rebase;
268 *(jitoffs_t *)((unsigned char *)rebase + offs) = jit->get_outputpos();
271 /* Lastly, if we're writing, keep track of the function count */
277 //push old frame on stack:
280 //sub edi, 8 ;extra un-used slot for non-existant CIP
281 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
282 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
283 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
285 //mov ecx, edi - get new frame
286 //mov ebx, edi - store frame back
287 //sub ecx, ebp - relocate local frame
289 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
290 IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
291 IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
292 IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG);
295 inline void WriteOp_Lidx_B(JitWriter *jit)
297 cell_t val = jit->read_cell();
301 IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
302 IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
303 Write_Check_VerifyAddr(jit, AMX_REG_PRI);
304 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
307 inline void WriteOp_Idxaddr_B(JitWriter *jit)
311 cell_t val = jit->read_cell();
312 IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
313 IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
316 inline void WriteOp_Shl(JitWriter *jit)
320 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
321 IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
324 inline void WriteOp_Shr(JitWriter *jit)
328 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
329 IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
332 inline void WriteOp_Sshr(JitWriter *jit)
336 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
337 IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
340 inline void WriteOp_Shl_C_Pri(JitWriter *jit)
343 jit_uint8_t val = (jit_uint8_t)jit->read_cell();
346 IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG);
348 IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
352 inline void WriteOp_Shl_C_Alt(JitWriter *jit)
355 jit_uint8_t val = (jit_uint8_t)jit->read_cell();
358 IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG);
360 IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
364 inline void WriteOp_Shr_C_Pri(JitWriter *jit)
367 jit_uint8_t val = (jit_uint8_t)jit->read_cell();
370 IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG);
372 IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
376 inline void WriteOp_Shr_C_Alt(JitWriter *jit)
379 jit_uint8_t val = (jit_uint8_t)jit->read_cell();
382 IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG);
384 IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
388 inline void WriteOp_SMul(JitWriter *jit)
393 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
394 IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
395 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
398 inline void WriteOp_Not(JitWriter *jit)
403 IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
404 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
405 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
408 inline void WriteOp_Neg(JitWriter *jit)
411 IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
414 inline void WriteOp_Xor(JitWriter *jit)
417 IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
420 inline void WriteOp_Or(JitWriter *jit)
423 IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
426 inline void WriteOp_And(JitWriter *jit)
429 IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
432 inline void WriteOp_Invert(JitWriter *jit)
435 IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
438 inline void WriteOp_Add_C(JitWriter *jit)
441 cell_t val = jit->read_cell();
442 if (val < SCHAR_MAX && val > SCHAR_MIN)
443 IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
445 IA32_Add_Eax_Imm32(jit, val);
448 inline void WriteOp_SMul_C(JitWriter *jit)
451 cell_t val = jit->read_cell();
452 if (val < SCHAR_MAX && val > SCHAR_MIN)
453 IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
455 IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
458 inline void WriteOp_Sign_Pri(JitWriter *jit)
462 IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
463 IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
466 inline void WriteOp_Sign_Alt(JitWriter *jit)
470 IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
471 IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
474 inline void WriteOp_Eq(JitWriter *jit)
476 //cmp eax, edx ; PRI == ALT ?
479 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
480 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
481 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
484 inline void WriteOp_Neq(JitWriter *jit)
486 //cmp eax, edx ; PRI != ALT ?
489 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
490 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
491 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
494 inline void WriteOp_Sless(JitWriter *jit)
496 //cmp eax, edx ; PRI < ALT ? (signed)
499 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
500 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
501 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L);
504 inline void WriteOp_Sleq(JitWriter *jit)
506 //cmp eax, edx ; PRI <= ALT ? (signed)
509 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
510 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
511 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE);
514 inline void WriteOp_Sgrtr(JitWriter *jit)
516 //cmp eax, edx ; PRI > ALT ? (signed)
519 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
520 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
521 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G);
524 inline void WriteOp_Sgeq(JitWriter *jit)
526 //cmp eax, edx ; PRI >= ALT ? (signed)
529 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
530 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
531 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE);
534 inline void WriteOp_Eq_C_Pri(JitWriter *jit)
536 //cmp eax, <val> ; PRI == value ?
539 cell_t val = jit->read_cell();
540 if (val < SCHAR_MAX && val > SCHAR_MIN)
541 IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
543 IA32_Cmp_Eax_Imm32(jit, val);
544 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
545 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
548 inline void WriteOp_Eq_C_Alt(JitWriter *jit)
551 //cmp edx, <val> ; ALT == value ?
553 cell_t val = jit->read_cell();
554 IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
555 if (val < SCHAR_MAX && val > SCHAR_MIN)
556 IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
558 IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
559 IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
562 inline void WriteOp_Inc_Pri(JitWriter *jit)
565 IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
568 inline void WriteOp_Inc_Alt(JitWriter *jit)
571 IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
574 inline void WriteOp_Inc(JitWriter *jit)
577 cell_t val = jit->read_cell();
578 if (val < SCHAR_MAX && val > SCHAR_MIN)
579 IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
581 IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
584 inline void WriteOp_Inc_S(JitWriter *jit)
587 cell_t val = jit->read_cell();
588 if (val < SCHAR_MAX && val > SCHAR_MIN)
589 IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
591 IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
594 inline void WriteOp_Inc_I(JitWriter *jit)
597 IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
600 inline void WriteOp_Dec_Pri(JitWriter *jit)
603 IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
606 inline void WriteOp_Dec_Alt(JitWriter *jit)
609 IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
612 inline void WriteOp_Dec(JitWriter *jit)
615 cell_t val = jit->read_cell();
616 if (val < SCHAR_MAX && val > SCHAR_MIN)
618 IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
620 IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
624 inline void WriteOp_Dec_S(JitWriter *jit)
627 cell_t val = jit->read_cell();
628 if (val < SCHAR_MAX && val > SCHAR_MIN)
630 IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
632 IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
636 inline void WriteOp_Dec_I(JitWriter *jit)
639 IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
642 inline void WriteOp_Load_Pri(JitWriter *jit)
644 //mov eax, [ebp+<val>]
645 cell_t val = jit->read_cell();
646 if (val < SCHAR_MAX && val > SCHAR_MIN)
648 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
650 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
654 inline void WriteOp_Load_Alt(JitWriter *jit)
656 //mov edx, [ebp+<val>]
657 cell_t val = jit->read_cell();
658 if (val < SCHAR_MAX && val > SCHAR_MIN)
660 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
662 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
666 inline void WriteOp_Load_S_Pri(JitWriter *jit)
668 //mov eax, [ebx+<val>]
669 cell_t val = jit->read_cell();
670 if (val < SCHAR_MAX && val > SCHAR_MIN)
672 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
674 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
678 inline void WriteOp_Load_S_Alt(JitWriter *jit)
680 //mov edx, [ebx+<val>]
681 cell_t val = jit->read_cell();
682 if (val < SCHAR_MAX && val > SCHAR_MIN)
684 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
686 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
690 inline void WriteOp_Lref_Pri(JitWriter *jit)
692 //mov eax, [ebp+<val>]
694 cell_t val = jit->read_cell();
695 if (val < SCHAR_MAX && val > SCHAR_MIN)
697 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
699 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
701 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
704 inline void WriteOp_Lref_Alt(JitWriter *jit)
706 //mov edx, [ebp+<val>]
708 cell_t val = jit->read_cell();
709 if (val < SCHAR_MAX && val > SCHAR_MIN)
711 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
713 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
715 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
718 inline void WriteOp_Lref_S_Pri(JitWriter *jit)
720 //mov eax, [ebx+<val>]
722 cell_t val = jit->read_cell();
723 if (val < SCHAR_MAX && val > SCHAR_MIN)
725 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
727 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
729 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
732 inline void WriteOp_Lref_S_Alt(JitWriter *jit)
734 //mov edx, [ebx+<val>]
736 cell_t val = jit->read_cell();
737 if (val < SCHAR_MAX && val > SCHAR_MIN)
739 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
741 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
743 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
746 inline void WriteOp_Const_Pri(JitWriter *jit)
749 cell_t val = jit->read_cell();
750 IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
753 inline void WriteOp_Const_Alt(JitWriter *jit)
756 cell_t val = jit->read_cell();
757 IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
760 inline void WriteOp_Addr_Pri(JitWriter *jit)
764 cell_t val = jit->read_cell();
765 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
766 if (val < SCHAR_MAX && val > SCHAR_MIN)
768 IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
770 IA32_Add_Eax_Imm32(jit, val);
774 inline void WriteOp_Addr_Alt(JitWriter *jit)
778 cell_t val = jit->read_cell();
779 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG);
780 if (val < SCHAR_MAX && val > SCHAR_MIN)
782 IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
784 IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
788 inline void WriteOp_Stor_Pri(JitWriter *jit)
790 //mov [ebp+<val>], eax
791 cell_t val = jit->read_cell();
792 if (val < SCHAR_MAX && val > SCHAR_MIN)
794 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
796 IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
800 inline void WriteOp_Stor_Alt(JitWriter *jit)
802 //mov [ebp+<val>], edx
803 cell_t val = jit->read_cell();
804 if (val < SCHAR_MAX && val > SCHAR_MIN)
806 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
808 IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
812 inline void WriteOp_Stor_S_Pri(JitWriter *jit)
814 //mov [ebx+<val>], eax
815 cell_t val = jit->read_cell();
816 if (val < SCHAR_MAX && val > SCHAR_MIN)
818 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
820 IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
824 inline void WriteOp_Stor_S_Alt(JitWriter *jit)
826 //mov [ebx+<val>], edx
827 cell_t val = jit->read_cell();
828 if (val < SCHAR_MAX && val > SCHAR_MIN)
830 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
832 IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
836 inline void WriteOp_Idxaddr(JitWriter *jit)
838 //lea eax, [edx+4*eax]
839 IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
842 inline void WriteOp_Sref_Pri(JitWriter *jit)
844 //mov ecx, [ebp+<val>]
846 cell_t val = jit->read_cell();
847 if (val < SCHAR_MAX && val > SCHAR_MIN)
849 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
851 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
853 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
856 inline void WriteOp_Sref_Alt(JitWriter *jit)
858 //mov ecx, [ebp+<val>]
860 cell_t val = jit->read_cell();
861 if (val < SCHAR_MAX && val > SCHAR_MIN)
863 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
865 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
867 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
870 inline void WriteOp_Sref_S_Pri(JitWriter *jit)
872 //mov ecx, [ebx+<val>]
874 cell_t val = jit->read_cell();
875 if (val < SCHAR_MAX && val > SCHAR_MIN)
877 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
879 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
881 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
884 inline void WriteOp_Sref_S_Alt(JitWriter *jit)
886 //mov ecx, [ebx+<val>]
888 cell_t val = jit->read_cell();
889 if (val < SCHAR_MAX && val > SCHAR_MIN)
891 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
893 IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
895 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
898 inline void WriteOp_Pop_Pri(JitWriter *jit)
902 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
903 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
906 inline void WriteOp_Pop_Alt(JitWriter *jit)
910 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
911 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
914 inline void WriteOp_Swap_Pri(JitWriter *jit)
920 IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
921 IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
922 IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
923 IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
926 inline void WriteOp_Swap_Alt(JitWriter *jit)
932 IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
933 IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
934 IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
935 IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
938 inline void WriteOp_PushAddr(JitWriter *jit)
940 //mov ecx, [esi+frm] ;get address (offset from frame)
944 cell_t val = jit->read_cell();
945 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
946 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
947 if (val < SCHAR_MAX && val > SCHAR_MIN)
949 IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
951 IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
953 IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
956 inline void WriteOp_Movs(JitWriter *jit)
971 cell_t val = jit->read_cell();
972 unsigned int dwords = val >> 2;
973 unsigned int bytes = val & 0x3;
976 IA32_Push_Reg(jit, REG_ESI);
977 IA32_Push_Reg(jit, REG_EDI);
978 IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
979 IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
982 IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
988 IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
992 IA32_Pop_Reg(jit, REG_EDI);
993 IA32_Pop_Reg(jit, REG_ESI);
996 inline void WriteOp_Fill(JitWriter *jit)
1000 //mov ecx, <val> >> 2
1004 unsigned int val = jit->read_cell() >> 2;
1006 IA32_Push_Reg(jit, REG_EDI);
1007 IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
1008 IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
1012 IA32_Pop_Reg(jit, REG_EDI);
1015 inline void WriteOp_GenArray(JitWriter *jit, bool autozero)
1017 cell_t val = jit->read_cell();
1020 /* flat array. we can generate this without indirection tables. */
1021 /* Note that we can overwrite ALT because technically STACK should be destroying ALT */
1022 //mov edx, [esi+info.heap]
1024 //mov [edi], edx ;store base of array into stack
1025 //lea edx, [edx+ecx*4] ;get the final new heap pointer
1026 //mov [esi+info.heap], edx ;store heap pointer back
1027 //add edx, ebp ;relocate
1028 //cmp edx, edi ;compare against stack pointer
1029 //jae :error ;error out if not enough space
1030 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
1031 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
1032 IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
1033 IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4);
1034 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP);
1035 IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
1036 IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
1037 IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow);
1039 WriteOp_Tracker_Push_Reg(jit, REG_ECX);
1043 /* Zero out the array - inline a quick fill */
1044 //push eax ;save pri
1045 //push edi ;save stk
1046 //xor eax, eax ;zero source
1047 //mov edi, [edi] ;get heap ptr out of the stack
1048 //add edi, ebp ;relocate
1049 //cld ;clear direction flag
1050 //rep stosd ;copy (note: ECX is sane from above)
1053 IA32_Push_Reg(jit, REG_EAX);
1054 IA32_Push_Reg(jit, REG_EDI);
1055 IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG);
1056 IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG);
1057 IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
1061 IA32_Pop_Reg(jit, REG_EDI);
1062 IA32_Pop_Reg(jit, REG_EAX);
1068 IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
1071 IA32_Mov_Reg_Imm32(jit, REG_EDX, 1);
1073 IA32_Mov_Reg_Imm32(jit, REG_EDX, 0);
1075 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1076 IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray);
1080 inline void WriteOp_Load_Both(JitWriter *jit)
1082 WriteOp_Load_Pri(jit);
1083 WriteOp_Load_Alt(jit);
1086 inline void WriteOp_Load_S_Both(JitWriter *jit)
1088 WriteOp_Load_S_Pri(jit);
1089 WriteOp_Load_S_Alt(jit);
1092 inline void WriteOp_Const(JitWriter *jit)
1094 //mov [ebp+<addr>], <val>
1095 cell_t addr = jit->read_cell();
1096 cell_t val = jit->read_cell();
1097 if (addr < SCHAR_MAX && addr > SCHAR_MIN)
1099 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
1101 IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
1105 inline void WriteOp_Const_S(JitWriter *jit)
1107 //mov [ebx+<offs>], <val>
1108 cell_t offs = jit->read_cell();
1109 cell_t val = jit->read_cell();
1110 if (offs < SCHAR_MAX && offs > SCHAR_MIN)
1112 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
1114 IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
1118 inline void WriteOp_Load_I(JitWriter *jit)
1120 //mov eax, [ebp+eax]
1121 Write_Check_VerifyAddr(jit, AMX_REG_PRI);
1122 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
1125 inline void WriteOp_Lodb_I(JitWriter *jit)
1127 Write_Check_VerifyAddr(jit, AMX_REG_PRI);
1129 //mov eax, [ebp+eax]
1130 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
1132 //and eax, <bitmask>
1133 cell_t val = jit->read_cell();
1138 IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);
1143 IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);
1149 inline void WriteOp_Stor_I(JitWriter *jit)
1151 //mov [ebp+edx], eax
1152 Write_Check_VerifyAddr(jit, AMX_REG_ALT);
1153 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
1156 inline void WriteOp_Strb_I(JitWriter *jit)
1158 Write_Check_VerifyAddr(jit, AMX_REG_ALT);
1159 //mov [ebp+edx], eax
1160 cell_t val = jit->read_cell();
1165 IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
1170 IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
1175 IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
1181 inline void WriteOp_Lidx(JitWriter *jit)
1183 //lea eax, [edx+4*eax]
1184 //mov eax, [ebp+eax]
1185 IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
1186 Write_Check_VerifyAddr(jit, AMX_REG_PRI);
1187 IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
1190 inline void WriteOp_Stack(JitWriter *jit)
1193 cell_t val = jit->read_cell();
1194 if (val < SCHAR_MAX && val > SCHAR_MIN)
1196 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG);
1198 IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG);
1203 Write_CheckStack_Min(jit);
1204 } else if (val < 0) {
1205 Write_CheckStack_Low(jit);
1209 inline void WriteOp_Heap(JitWriter *jit)
1211 //mov edx, [esi+hea]
1212 //add [esi+hea], <val>
1213 cell_t val = jit->read_cell();
1214 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
1215 if (val < SCHAR_MAX && val > SCHAR_MIN)
1217 IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP);
1219 IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP);
1222 /* NOTE: Backwards from op.stack */
1225 Write_CheckHeap_Low(jit);
1226 } else if (val < 0) {
1227 Write_CheckHeap_Min(jit);
1231 inline void WriteOp_SDiv(JitWriter *jit)
1237 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
1238 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
1239 IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
1240 Write_Check_DivZero(jit, AMX_REG_TMP);
1241 IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
1244 inline void WriteOp_SDiv_Alt(JitWriter *jit)
1250 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
1251 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1252 IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
1253 Write_Check_DivZero(jit, AMX_REG_TMP);
1254 IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
1257 inline void WriteOp_Retn(JitWriter *jit)
1259 //mov ebx, [edi+4] - get old frm
1260 //add edi, 8 - pop stack
1261 //mov [esi+frm], ebx - restore frame pointer
1262 //add ebx, ebp - relocate
1263 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4);
1264 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
1265 IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
1266 IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
1270 //lea edi, [edi+ecx*4+4]
1271 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
1272 IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4);
1274 //ret - return (EIP on real stack!)
1278 inline void WriteOp_Call(JitWriter *jit)
1280 cell_t offs = jit->read_cell();
1282 jitoffs_t jmp = IA32_Call_Imm32(jit, 0);
1283 IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
1286 inline void WriteOp_Bounds(JitWriter *jit)
1288 cell_t val = jit->read_cell();
1292 if (val < SCHAR_MAX && val > SCHAR_MIN)
1294 IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
1296 IA32_Cmp_Eax_Imm32(jit, val);
1298 IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds);
1301 inline void WriteOp_Halt(JitWriter *jit)
1303 //mov ecx, [esi+ret]
1305 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
1306 IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
1309 * We don't support sleeping or halting with weird values.
1310 * So we're omitting the mov eax <val> that was here.
1314 CompData *data = (CompData *)jit->data;
1315 IA32_Jump_Imm32_Abs(jit, data->jit_return);
1318 inline void WriteOp_Break(JitWriter *jit)
1320 CompData *data = (CompData *)jit->data;
1323 //jit->write_ubyte(IA32_INT3);
1325 jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0);
1326 jitoffs_t save = jit->get_outputpos();
1327 jit->set_outputpos(wr);
1328 jit->write_uint32((uint32_t)(wr));
1329 jit->set_outputpos(save);
1331 wr = IA32_Call_Imm32(jit, 0);
1332 IA32_Write_Jump32(jit, wr, data->jit_break);
1336 inline void WriteOp_Jump(JitWriter *jit)
1339 cell_t amx_offs = jit->read_cell();
1340 IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false));
1343 inline void WriteOp_Jzer(JitWriter *jit)
1347 cell_t target = jit->read_cell();
1348 IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
1349 IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false));
1352 inline void WriteOp_Jnz(JitWriter *jit)
1356 cell_t target = jit->read_cell();
1357 IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
1358 IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false));
1361 inline void WriteOp_Jeq(JitWriter *jit)
1365 cell_t target = jit->read_cell();
1366 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1367 IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false));
1370 inline void WriteOp_Jneq(JitWriter *jit)
1374 cell_t target = jit->read_cell();
1375 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1376 IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, RelocLookup(jit, target, false));
1379 inline void WriteOp_Jsless(JitWriter *jit)
1383 cell_t target = jit->read_cell();
1384 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1385 IA32_Jump_Cond_Imm32_Abs(jit, CC_L, RelocLookup(jit, target, false));
1388 inline void WriteOp_Jsleq(JitWriter *jit)
1392 cell_t target = jit->read_cell();
1393 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1394 IA32_Jump_Cond_Imm32_Abs(jit, CC_LE, RelocLookup(jit, target, false));
1397 inline void WriteOp_JsGrtr(JitWriter *jit)
1401 cell_t target = jit->read_cell();
1402 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1403 IA32_Jump_Cond_Imm32_Abs(jit, CC_G, RelocLookup(jit, target, false));
1406 inline void WriteOp_JsGeq(JitWriter *jit)
1410 cell_t target = jit->read_cell();
1411 IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
1412 IA32_Jump_Cond_Imm32_Abs(jit, CC_GE, RelocLookup(jit, target, false));
1415 inline void WriteOp_Switch(JitWriter *jit)
1417 cell_t offs = jit->read_cell();
1418 cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t));
1426 /* Read the number of cases, then advance by one */
1427 cell_t num_cases = *tbl++;
1430 /* Special treatment for 0 cases */
1432 IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
1434 /* Check if the case layout is fully sequential */
1435 casetbl *iter = (casetbl *)(tbl + 1);
1436 casetbl *cases = iter;
1437 cell_t first = iter[0].val;
1438 cell_t last = first;
1439 bool sequential = true;
1440 for (cell_t i=1; i<num_cases; i++)
1442 if (iter[i].val != ++last)
1448 /* Time to generate.
1449 * First check whether the bounds are correct: if (a < LOW || a > HIGH)
1450 * This check is valid for both sequential and non-sequential.
1452 cell_t low_bound = cases[0].val;
1455 /* negate it so we'll get a lower bound of 0 */
1456 //lea ecx, [eax-<LOWER_BOUND>]
1457 low_bound = -low_bound;
1458 if (low_bound > SCHAR_MIN && low_bound < SCHAR_MAX)
1460 IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
1462 IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
1465 cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val);
1466 //cmp ecx, <UPPER BOUND BOUND>
1467 if (high_bound > SCHAR_MIN && high_bound < SCHAR_MAX)
1469 IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound);
1471 IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound);
1474 IA32_Jump_Cond_Imm32_Abs(jit, CC_A, RelocLookup(jit, *tbl, false));
1477 * Now we've taken the default case out of the way, it's time to do the
1478 * full check, which is different for sequential vs. non-sequential.
1482 /* we're now theoretically guaranteed to be jumping to a correct offset.
1483 * ECX still has the correctly bound offset in it, luckily!
1484 * thus, we simply need to relocate ECX and store the cases.
1487 //add ecx, <case table start>
1488 IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0);
1489 jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG);
1490 IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG);
1491 /* The case table starts here. Go back and write the output pointer. */
1492 jitoffs_t cur_pos = jit->get_outputpos();
1493 jit->set_outputpos(tbl_offs);
1494 jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos));
1495 jit->set_outputpos(cur_pos);
1496 //now we can write the case table, finally!
1497 jit_uint32_t base = (jit_uint32_t)jit->outbase;
1498 for (cell_t i=0; i<num_cases; i++)
1500 jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false));
1503 /* The slow version. Go through each case and generate a check.
1504 * In the future we should replace case tables of more than ~8 cases with a
1505 * hash table lookup.
1506 * :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case,
1507 * but only if we're under N cases or so!
1508 * :THOUGHT: Write out a static btree lookup :)
1511 for (cell_t i=0; i<num_cases; i++)
1514 //cmp eax, <val> OR cmp al, <val>
1515 if (val > SCHAR_MIN && val < SCHAR_MAX)
1517 IA32_Cmp_Al_Imm8(jit, val);
1519 IA32_Cmp_Eax_Imm32(jit, cases[i].val);
1521 IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, cases[i].offs, false));
1523 /* After all this, jump to the default case! */
1524 IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
1529 inline void WriteOp_Casetbl(JitWriter *jit)
1531 /* do nothing here, switch does all ze work */
1532 cell_t num_cases = jit->read_cell();
1534 /* Two cells per case, one extra case for the default jump */
1535 num_cases = (num_cases * 2) + 1;
1536 jit->inptr += num_cases;
1539 inline void WriteOp_Sysreq_C(JitWriter *jit)
1541 /* store the number of parameters on the stack,
1542 * and store the native index as well.
1544 cell_t native_index = jit->read_cell();
1546 if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
1548 ((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
1552 //mov ecx, <native_index>
1553 IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
1555 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1556 IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c);
1559 inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit)
1561 /* store the number of parameters on the stack,
1562 * and store the native index as well.
1564 cell_t native_index = jit->read_cell();
1565 cell_t num_params = jit->read_cell();
1567 if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
1569 ((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
1573 //mov eax, <num_params>
1574 //mov ecx, <native_index>
1575 IA32_Mov_Reg_Imm32(jit, REG_EAX, num_params);
1576 IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
1578 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1579 IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_n);
1582 inline void WriteOp_Sysreq_N(JitWriter *jit)
1584 /* The big daddy of opcodes. */
1585 cell_t native_index = jit->read_cell();
1586 cell_t num_params = jit->read_cell();
1587 CompData *data = (CompData *)jit->data;
1589 if ((uint32_t)native_index >= data->plugin->info.natives_num)
1591 data->error_set = SP_ERROR_INSTRUCTION_PARAM;
1595 /* store the number of parameters on the stack */
1596 //mov [edi-4], num_params
1598 IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4);
1599 IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
1601 /* save registers we will need */
1603 IA32_Push_Reg(jit, AMX_REG_ALT);
1605 /* push some callback stuff */
1607 //push <native> ; native index
1608 IA32_Push_Reg(jit, AMX_REG_STK);
1609 if (native_index < SCHAR_MAX && native_index > SCHAR_MIN)
1611 IA32_Push_Imm8(jit, (jit_int8_t)native_index);
1613 IA32_Push_Imm32(jit, native_index);
1616 /* Relocate stack, heap, frm information, then store back */
1617 //mov eax, [esi+context]
1618 //mov ecx, [esi+hea]
1623 //mov [eax+frm], ecx
1624 IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
1625 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
1626 IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
1627 IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
1628 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
1629 IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
1630 IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
1632 /* finally, push the last parameter and make the call */
1633 //push eax ; context
1634 //call NativeCallback
1635 IA32_Push_Reg(jit, REG_EAX);
1636 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1639 IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
1641 IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
1644 /* check for errors */
1645 //mov ecx, [esi+context]
1648 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
1649 IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
1650 IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
1652 /* restore what we damaged */
1656 IA32_Add_Rm_Imm8(jit, REG_ESP, 4*3, MOD_REG);
1657 IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
1658 IA32_Pop_Reg(jit, AMX_REG_ALT);
1660 /* pop the stack. do not check the margins.
1661 * Note that this is not a true macro - we don't bother to
1662 * set ALT here because nothing will be using it.
1666 //add edi, <val*4+4>
1667 if (num_params < SCHAR_MAX && num_params > SCHAR_MIN)
1669 IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG);
1671 IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG);
1675 inline void WriteOp_Tracker_Push_C(JitWriter *jit)
1677 CompData *data = (CompData *)jit->data;
1678 cell_t val = jit->read_cell();
1680 /* Save registers that may be damaged by the call */
1683 IA32_Push_Reg(jit, AMX_REG_PRI);
1684 IA32_Push_Reg(jit, AMX_REG_ALT);
1686 /* Get the context ptr, push it and call the check */
1687 //mov eax, [esi+context]
1689 //call JIT_VerifyOrAllocateTracker
1690 IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
1691 IA32_Push_Reg(jit, REG_EAX);
1692 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1693 IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
1695 /* Check for errors */
1698 IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
1699 IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
1703 IA32_Pop_Reg(jit, REG_EAX);
1705 /* Push the value into the stack and increment pCur */
1706 //mov edx, [eax+vm[]]
1707 //mov ecx, [edx+pcur]
1709 //mov [ecx], <val>*4 ; we want the count in bytes not in cells
1710 IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
1711 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
1712 IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
1713 IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG);
1715 /* Restore PRI & ALT */
1718 IA32_Pop_Reg(jit, AMX_REG_ALT);
1719 IA32_Pop_Reg(jit, AMX_REG_PRI);
1722 inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit)
1724 CompData *data = (CompData *)jit->data;
1726 /* Save registers that may be damaged by the call */
1729 IA32_Push_Reg(jit, AMX_REG_PRI);
1730 IA32_Push_Reg(jit, AMX_REG_ALT);
1732 /* Get the context ptr, push it and call the check */
1733 //mov eax, [esi+context]
1735 //call JIT_VerifyLowBoundTracker
1736 IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
1737 IA32_Push_Reg(jit, REG_EAX);
1738 jitoffs_t call = IA32_Call_Imm32(jit, 0);
1739 IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker);
1741 /* Check for errors */
1744 IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
1745 IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
1749 IA32_Pop_Reg(jit, REG_EAX);
1751 /* Pop the value from the stack and decrease the heap by it*/
1752 //mov edx, [eax+vm[]]
1754 //mov ecx, [edx+pcur]
1756 //sub [esi+hea], ecx
1757 IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
1758 IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
1759 IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
1760 IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG);
1761 IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP);
1763 Write_CheckHeap_Min(jit);
1765 /* Restore PRI & ALT */
1768 IA32_Pop_Reg(jit, AMX_REG_ALT);
1769 IA32_Pop_Reg(jit, AMX_REG_PRI);
1772 inline void WriteOp_Stradjust_Pri(JitWriter *jit)
1776 IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG);
1777 IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG);
1780 /*************************************************
1781 *************************************************
1782 * JIT PROPER ************************************
1783 * The rest from now on is the JIT engine *
1784 *************************************************
1785 *************************************************/
1787 cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
1789 sp_native_t *native = &ctx->natives[native_idx];
1791 ctx->n_idx = native_idx;
1793 /* Technically both aren't needed, I guess */
1794 if (native->status == SP_NATIVE_UNBOUND)
1796 ctx->n_err = SP_ERROR_INVALID_NATIVE;
1800 return native->pfn(ctx->context, params);
1803 static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
1805 sp_context_t *ctx = pCtx->GetContext();
1806 ctx->n_err = SP_ERROR_INVALID_NATIVE;
1811 cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
1813 cell_t save_sp = ctx->sp;
1814 cell_t save_hp = ctx->hp;
1816 ctx->n_idx = native_idx;
1818 if (ctx->hp < ctx->heap_base)
1820 ctx->n_err = SP_ERROR_HEAPMIN;
1824 if (ctx->hp + STACK_MARGIN > ctx->sp)
1826 ctx->n_err = SP_ERROR_STACKLOW;
1830 if ((uint32_t)ctx->sp >= ctx->mem_size)
1832 ctx->n_err = SP_ERROR_STACKMIN;
1836 cell_t result = NativeCallback(ctx, native_idx, params);
1838 if (ctx->n_err != SP_ERROR_NONE)
1843 if (save_sp != ctx->sp)
1845 ctx->n_err = SP_ERROR_STACKLEAK;
1847 } else if (save_hp != ctx->hp) {
1848 ctx->n_err = SP_ERROR_HEAPLEAK;
1855 jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
1859 CompData *data = (CompData *)jit->data;
1862 /* The actual offset is EIP relative. We need to relocate it.
1863 * Note that this assumes that we're pointing to the next op.
1865 pcode_offs += jit->get_inputpos();
1867 /* Offset must always be 1)positive and 2)less than or equal to the codesize */
1868 assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
1869 /* Do the lookup in the native dictionary. */
1870 return *(jitoffs_t *)(data->rebase + pcode_offs);
1876 void WriteErrorRoutines(CompData *data, JitWriter *jit)
1878 data->jit_error_divzero = jit->get_outputpos();
1879 Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO);
1881 data->jit_error_stacklow = jit->get_outputpos();
1882 Write_SetError(jit, SP_ERROR_STACKLOW);
1884 data->jit_error_stackmin = jit->get_outputpos();
1885 Write_SetError(jit, SP_ERROR_STACKMIN);
1887 data->jit_error_bounds = jit->get_outputpos();
1888 Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS);
1890 data->jit_error_memaccess = jit->get_outputpos();
1891 Write_SetError(jit, SP_ERROR_MEMACCESS);
1893 data->jit_error_heaplow = jit->get_outputpos();
1894 Write_SetError(jit, SP_ERROR_HEAPLOW);
1896 data->jit_error_heapmin = jit->get_outputpos();
1897 Write_SetError(jit, SP_ERROR_HEAPMIN);
1899 data->jit_error_array_too_big = jit->get_outputpos();
1900 Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG);
1902 data->jit_extern_error = jit->get_outputpos();
1903 Write_GetError(jit);
1906 sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
1908 CompData *data = (CompData *)co;
1909 sp_plugin_t *plugin = data->plugin;
1911 /* The first phase is to browse */
1912 uint8_t *code = plugin->pcode;
1913 uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
1916 /*********************************************
1917 * FIRST PASS (medium load): writer.outbase is NULL, getting size only
1918 * SECOND PASS (heavy load!!): writer.outbase is valid and output is written
1919 *********************************************/
1922 JitWriter *jit = &writer;
1923 cell_t *endptr = (cell_t *)(end_cip);
1924 uint32_t codemem = 0;
1926 /* Initial code is written "blank,"
1927 * so we can check the exact memory usage.
1929 data->codesize = plugin->pcode_size;
1931 writer.inbase = (cell_t *)code;
1932 writer.outptr = NULL;
1933 writer.outbase = NULL;
1934 /* Allocate relocation. One extra cell for final CIP. */
1935 data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t));
1937 /* We will jump back here for second pass */
1939 /* Initialize pass vars */
1940 writer.inptr = writer.inbase;
1941 data->jit_verify_addr_eax = 0;
1942 data->jit_verify_addr_edx = 0;
1944 /* Write the prologue of the JIT */
1945 data->jit_return = Write_Execute_Function(jit);
1947 /* Write the SYSREQ.N opcode if we need to */
1948 if (!(data->inline_level & JIT_INLINE_NATIVES))
1950 data->jit_sysreq_n = jit->get_outputpos();
1951 WriteOp_Sysreq_N_Function(jit);
1954 /* Write the debug section if we need it */
1955 if (data->debug == true)
1957 data->jit_break = jit->get_outputpos();
1958 Write_BreakDebug(jit);
1961 /* Plugins compiled with -O0 will need this! */
1962 data->jit_sysreq_c = jit->get_outputpos();
1963 WriteOp_Sysreq_C_Function(jit);
1965 data->jit_genarray = jit->get_outputpos();
1966 WriteIntrinsic_GenArray(jit);
1968 /* Write error checking routines that are called to */
1969 if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
1971 data->jit_verify_addr_eax = jit->get_outputpos();
1972 Write_Check_VerifyAddr(jit, REG_EAX);
1974 data->jit_verify_addr_edx = jit->get_outputpos();
1975 Write_Check_VerifyAddr(jit, REG_EDX);
1978 /* Actual code generation! */
1979 if (writer.outbase == NULL)
1981 /* First Pass - find codesize and resolve relocation */
1982 jitoffs_t pcode_offs;
1983 jitoffs_t native_offs;
1985 for (; writer.inptr < endptr;)
1987 /* Store the native offset into the rebase memory.
1988 * This large chunk of memory lets us do an instant lookup
1989 * based on an original pcode offset.
1991 pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
1992 native_offs = jit->get_outputpos();
1993 *((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
1995 /* Now read the opcode and continue. */
1996 op = (OPCODE)writer.read_cell();
1999 #include "opcode_switch.inc"
2001 /* Check for errors. This should only happen in the first pass. */
2002 if (data->error_set != SP_ERROR_NONE)
2004 *err = data->error_set;
2005 AbortCompilation(co);
2009 /* Write these last because error jumps should be unpredicted, and thus forward */
2010 WriteErrorRoutines(data, jit);
2012 /* Write the final CIP to the last position in the reloc array */
2013 pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
2014 native_offs = jit->get_outputpos();
2015 *((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
2017 /* the total codesize is now known! */
2018 codemem = writer.get_outputpos();
2019 writer.outbase = (jitcode_t)engine->ExecAlloc(codemem);
2020 writer.outptr = writer.outbase;
2021 /* go back for third pass */
2025 * THIRD PASS - write opcode info
2027 for (; writer.inptr < endptr;)
2029 op = (OPCODE)writer.read_cell();
2032 #include "opcode_switch.inc"
2035 /* Write these last because error jumps should be unpredicted, and thus forward */
2036 WriteErrorRoutines(data, jit);
2040 * FOURTH PASS - Context Setup
2043 sp_context_t *ctx = new sp_context_t;
2044 memset(ctx, 0, sizeof(sp_context_t));
2047 ctx->codebase = writer.outbase;
2048 ctx->plugin = plugin;
2050 ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
2053 ctx->memory = new uint8_t[plugin->memory];
2054 memcpy(ctx->memory, plugin->data, plugin->data_size);
2055 ctx->mem_size = plugin->memory;
2056 ctx->heap_base = plugin->data_size;
2057 ctx->hp = ctx->heap_base;
2058 ctx->sp = ctx->mem_size - sizeof(cell_t);
2060 const char *strbase = plugin->info.stringbase;
2063 /* relocate public info */
2064 if ((max = plugin->info.publics_num))
2066 ctx->publics = new sp_public_t[max];
2067 for (iter=0; iter<max; iter++)
2069 ctx->publics[iter].name = strbase + plugin->info.publics[iter].name;
2070 ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
2071 /* Encode the ID as a straight code offset */
2072 ctx->publics[iter].funcid = (ctx->publics[iter].code_offs << 1);
2076 /* relocate pubvar info */
2077 if ((max = plugin->info.pubvars_num))
2079 uint8_t *dat = ctx->memory;
2080 ctx->pubvars = new sp_pubvar_t[max];
2081 for (iter=0; iter<max; iter++)
2083 ctx->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
2084 ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
2088 /* relocate native info */
2089 if ((max = plugin->info.natives_num))
2091 ctx->natives = new sp_native_t[max];
2092 for (iter=0; iter<max; iter++)
2094 ctx->natives[iter].name = strbase + plugin->info.natives[iter].name;
2095 ctx->natives[iter].pfn = &InvalidNative;
2096 ctx->natives[iter].status = SP_NATIVE_UNBOUND;
2101 * If we're debugging, make sure we copy the necessary info.
2105 strbase = plugin->debug.stringbase;
2107 /* relocate files */
2108 max = plugin->debug.files_num;
2109 ctx->files = new sp_debug_file_t[max];
2110 for (iter=0; iter<max; iter++)
2112 ctx->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
2113 ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
2116 /* relocate lines */
2117 max = plugin->debug.lines_num;
2118 ctx->lines = new sp_debug_line_t[max];
2119 for (iter=0; iter<max; iter++)
2121 ctx->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
2122 ctx->lines[iter].line = plugin->debug.lines[iter].line;
2125 /* relocate arrays */
2126 sp_fdbg_symbol_t *sym;
2127 sp_fdbg_arraydim_t *arr;
2128 uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
2130 max = plugin->debug.syms_num;
2131 ctx->symbols = new sp_debug_symbol_t[max];
2132 for (iter=0; iter<max; iter++)
2134 sym = (sp_fdbg_symbol_t *)cursor;
2137 * @brief There is an "issue" where the compiler will give totally bogus code
2138 * address because codegeneration is still being calculated. A simple fix for
2139 * this is to coerce the codestart value to 0 when it's invalid.
2141 if (sym->codestart > data->codesize)
2143 ctx->symbols[iter].codestart = 0;
2145 ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
2147 if (sym->codeend > data->codesize)
2149 ctx->symbols[iter].codeend = data->codesize;
2151 ctx->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
2153 ctx->symbols[iter].name = strbase + sym->name;
2154 ctx->symbols[iter].sym = sym;
2156 if (sym->dimcount > 0)
2158 cursor += sizeof(sp_fdbg_symbol_t);
2159 arr = (sp_fdbg_arraydim_t *)cursor;
2160 ctx->symbols[iter].dims = arr;
2161 cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
2165 ctx->symbols[iter].dims = NULL;
2166 cursor += sizeof(sp_fdbg_symbol_t);
2170 tracker_t *trk = new tracker_t;
2171 ctx->vm[JITVARS_TRACKER] = trk;
2172 trk->pBase = (ucell_t *)malloc(1024);
2173 trk->pCur = trk->pBase;
2174 trk->size = 1024 / sizeof(cell_t);
2176 functracker_t *fnc = new functracker_t;
2177 ctx->vm[JITVARS_FUNCINFO] = fnc;
2178 ctx->vm[JITVARS_REBASE] = data->rebase;
2179 fnc->code_size = codemem;
2180 fnc->num_functions = data->func_idx;
2182 /* clean up relocation+compilation memory */
2183 data->rebase = NULL;
2184 AbortCompilation(co);
2186 *err = SP_ERROR_NONE;
2191 SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
2194 JitWriter *jit = &jw;
2200 /* First pass, calculate size */
2202 //push pData ;push pData
2203 //push [esp+12] ;push params
2204 //push [esp+12] ;push ctx
2205 //call [callback] ;invoke the meta-callback
2206 //add esp, 12 ;restore the stack
2208 IA32_Push_Imm32(jit, (jit_int32_t)pData);
2209 IA32_Push_Rm_Disp8_ESP(jit, 12);
2210 IA32_Push_Rm_Disp8_ESP(jit, 12);
2211 uint32_t call = IA32_Call_Imm32(jit, 0);
2212 IA32_Write_Jump32_Abs(jit, call, (void *)callback);
2213 IA32_Add_Rm_Imm8(jit, REG_ESP, 12, MOD_REG);
2216 if (jw.outbase == NULL)
2218 /* Second pass: Actually write */
2219 jw.outbase = (jitcode_t)engine->ExecAlloc(jw.get_outputpos());
2224 jw.outptr = jw.outbase;
2229 return (SPVM_NATIVE_FUNC)jw.outbase;
2232 void JITX86::DestroyFakenative(SPVM_NATIVE_FUNC func)
2234 engine->ExecFree(func);
2237 const char *JITX86::GetVMName()
2242 int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
2244 typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
2245 CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase;
2246 return fn(ctx, code_idx, result);
2249 void JITX86::FreeContext(sp_context_t *ctx)
2251 engine->ExecFree(ctx->codebase);
2252 delete [] ctx->memory;
2253 delete [] ctx->files;
2254 delete [] ctx->lines;
2255 delete [] ctx->natives;
2256 delete [] ctx->publics;
2257 delete [] ctx->pubvars;
2258 delete [] ctx->symbols;
2259 engine->BaseFree(ctx->vm[JITVARS_REBASE]);
2260 free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
2261 delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
2265 ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
2267 CompData *data = new CompData;
2269 data->plugin = plugin;
2270 data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
2271 data->error_set = SP_ERROR_NONE;
2276 void JITX86::AbortCompilation(ICompilation *co)
2278 if (((CompData *)co)->rebase)
2280 engine->BaseFree(((CompData *)co)->rebase);
2282 delete (CompData *)co;
2285 bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val)
2287 CompData *data = (CompData *)co;
2289 if (strcmp(key, "debug") == 0)
2291 if ((atoi(val) == 1) || !strcmp(val, "yes"))
2295 data->debug = false;
2297 if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG))
2299 data->debug = false;
2308 unsigned int JITX86::GetAPIVersion()
2310 return SOURCEPAWN_VM_API_VERSION;
2313 bool JITX86::FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
2315 uint8_t *rebase = (uint8_t *)ctx->vm[JITVARS_REBASE];
2317 /* Is this within the pcode bounds? */
2318 if (code_addr >= ctx->plugin->pcode_size - sizeof(uint32_t))
2324 code_addr = *(jitoffs_t *)(rebase + code_addr);
2326 /* Check if this is in the relocation bounds */
2327 functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
2328 if (code_addr >= fnc->code_size)
2333 /* Get the function info and sanity check */
2334 funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
2335 if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
2348 bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
2350 /* Check if this is in the relocation bounds */
2351 functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
2352 if (code_addr >= fnc->code_size)
2357 /* Get the function info and sanity check */
2358 funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
2359 if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
2372 unsigned int JITX86::FunctionCount(const sp_context_t *ctx)
2374 functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
2376 return fnc->num_functions;
2379 const char *JITX86::GetVersionString()
2381 return SVN_FULL_VERSION;
2384 const char *JITX86::GetCPUOptimizations()
2386 return "Generic 80486";