#include #include #include "jit_x86.h" #include "opcode_helpers.h" #include "x86_macros.h" inline void WriteOp_Move_Pri(JitWriter *jit) { //mov eax, edx IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Move_Alt(JitWriter *jit) { //mov edx, eax IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Xchg(JitWriter *jit) { //xchg eax, edx IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT); } inline void WriteOp_Push(JitWriter *jit) { //push stack, DAT offset based //sub ebp, 4 //mov ecx, [edi+] //mov [ebp], ecx cell_t val = jit->read_cell(); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); //optimize encoding a bit... if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); } inline void WriteOp_Push_C(JitWriter *jit) { //push stack //mov [ebp-4], //sub ebp, 4 cell_t val = jit->read_cell(); IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Zero(JitWriter *jit) { //mov [edi+], 0 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val); else IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val); } inline void WriteOp_Zero_S(JitWriter *jit) { //mov [ebx+], 0 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val); else IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val); } inline void WriteOp_Push_S(JitWriter *jit) { //push stack, FRM offset based //sub ebp, 4 //mov ecx, [ebx+] //mov [ebp], ecx cell_t val = jit->read_cell(); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); //optimize encoding a bit... if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); } inline void WriteOp_Push_Pri(JitWriter *jit) { //mov [ebp-4], eax //sub ebp, 4 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Push_Alt(JitWriter *jit) { //mov [ebp-4], edx //sub ebp, 4 IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Push2_C(JitWriter *jit) { Macro_PushN_C(jit, 2); } inline void WriteOp_Push3_C(JitWriter *jit) { Macro_PushN_C(jit, 3); } inline void WriteOp_Push4_C(JitWriter *jit) { Macro_PushN_C(jit, 4); } inline void WriteOp_Push5_C(JitWriter *jit) { Macro_PushN_C(jit, 5); } inline void WriteOp_Push2_Adr(JitWriter *jit) { Macro_PushN_Addr(jit, 2); } inline void WriteOp_Push3_Adr(JitWriter *jit) { Macro_PushN_Addr(jit, 3); } inline void WriteOp_Push4_Adr(JitWriter *jit) { Macro_PushN_Addr(jit, 4); } inline void WriteOp_Push5_Adr(JitWriter *jit) { Macro_PushN_Addr(jit, 5); } inline void WriteOp_Push2_S(JitWriter *jit) { Macro_PushN_S(jit, 2); } inline void WriteOp_Push3_S(JitWriter *jit) { Macro_PushN_S(jit, 3); } inline void WriteOp_Push4_S(JitWriter *jit) { Macro_PushN_S(jit, 4); } inline void WriteOp_Push5_S(JitWriter *jit) { Macro_PushN_S(jit, 5); } inline void WriteOp_Push5(JitWriter *jit) { Macro_PushN(jit, 5); } inline void WriteOp_Push4(JitWriter *jit) { Macro_PushN(jit, 4); } inline void WriteOp_Push3(JitWriter *jit) { Macro_PushN(jit, 3); } inline void WriteOp_Push2(JitWriter *jit) { Macro_PushN(jit, 2); } inline void WriteOp_Zero_Pri(JitWriter *jit) { //xor eax, eax IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Zero_Alt(JitWriter *jit) { //xor edx, edx IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Add(JitWriter *jit) { //add eax, edx IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Sub(JitWriter *jit) { //sub eax, edx IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Sub_Alt(JitWriter *jit) { //neg eax //add eax, edx IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Proc(JitWriter *jit) { //push old frame on stack: //sub ebp, 4 //mov ecx, [frm] //mov [ebp], ecx IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG); IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG); //save frame: //mov [frm], ebp - get new frame //mov ebx, ebp - store frame back //sub [frm], edi - relocate local frame IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_STK, MOD_MEM_REG); IA32_Mov_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG); IA32_Sub_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_DAT, MOD_MEM_REG); } inline void WriteOp_Shl(JitWriter *jit) { //mov ecx, edx //shl eax, cl IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Shr(JitWriter *jit) { //mov ecx, edx //shr eax, cl IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Sshr(JitWriter *jit) { //mov ecx, edx //sar eax, cl IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Shl_C_Pri(JitWriter *jit) { //shl eax, jit_uint8_t val = (jit_uint8_t)jit->read_cell(); IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); } inline void WriteOp_Shl_C_Alt(JitWriter *jit) { //shl edx, jit_uint8_t val = (jit_uint8_t)jit->read_cell(); IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); } inline void WriteOp_Shr_C_Pri(JitWriter *jit) { //shr eax, jit_uint8_t val = (jit_uint8_t)jit->read_cell(); IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG); } inline void WriteOp_Shr_C_Alt(JitWriter *jit) { //shr edx, jit_uint8_t val = (jit_uint8_t)jit->read_cell(); IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG); } inline void WriteOp_SMul(JitWriter *jit) { //mov ecx, edx //imul edx //mov edx, ecx IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG); IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); } inline void WriteOp_UMul(JitWriter *jit) { //mov ecx, edx //mul edx //mov edx, ecx IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG); IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); } inline void WriteOp_Not(JitWriter *jit) { //test eax, eax //mov eax, 0 //sete al IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); } inline void WriteOp_Neg(JitWriter *jit) { //neg eax IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Xor(JitWriter *jit) { //xor eax, edx IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Or(JitWriter *jit) { //or eax, edx IA32_Or_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_And(JitWriter *jit) { //and eax, edx IA32_And_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Invert(JitWriter *jit) { //not eax IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Add_C(JitWriter *jit) { //add eax, cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); else IA32_Add_Eax_Imm32(jit, val); } inline void WriteOp_SMul_C(JitWriter *jit) { //imul eax, cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val); else IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val); } inline void WriteOp_Sign_Pri(JitWriter *jit) { //shl eax, 24 //sar eax, 24 IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG); } inline void WriteOp_Sign_Alt(JitWriter *jit) { //shl edx, 24 //sar edx, 24 IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG); } inline void WriteOp_Eq(JitWriter *jit) { //cmp eax, edx ; PRI == ALT ? //mov eax, 0 //sete al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); } inline void WriteOp_Neq(JitWriter *jit) { //cmp eax, edx ; PRI != ALT ? //mov eax, 0 //setne al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE); } inline void WriteOp_Less(JitWriter *jit) { //cmp eax, edx ; PRI < ALT ? (unsigned) //mov eax, 0 //setb al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B); } inline void WriteOp_Leq(JitWriter *jit) { //cmp eax, edx ; PRI <= ALT ? (unsigned) //mov eax, 0 //setbe al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE); } inline void WriteOp_Grtr(JitWriter *jit) { //cmp eax, edx ; PRI > ALT ? (unsigned) //mov eax, 0 //seta al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A); } inline void WriteOp_Geq(JitWriter *jit) { //cmp eax, edx ; PRI >= ALT ? (unsigned) //mov eax, 0 //setae al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE); } inline void WriteOp_Sless(JitWriter *jit) { //cmp eax, edx ; PRI < ALT ? (signed) //mov eax, 0 //setl al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L); } inline void WriteOp_Sleq(JitWriter *jit) { //cmp eax, edx ; PRI <= ALT ? (signed) //mov eax, 0 //setle al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE); } inline void WriteOp_Sgrtr(JitWriter *jit) { //cmp eax, edx ; PRI > ALT ? (signed) //mov eax, 0 //setg al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G); } inline void WriteOp_Sgeq(JitWriter *jit) { //cmp eax, edx ; PRI >= ALT ? (signed) //mov eax, 0 //setge al IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE); } inline void WriteOp_Eq_C_Pri(JitWriter *jit) { //cmp eax, ; PRI == value ? //mov eax, 0 //sete al cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val); else IA32_Cmp_Eax_Imm32(jit, val); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); } inline void WriteOp_Eq_C_Alt(JitWriter *jit) { //xor eax, eax //cmp edx, ; ALT == value ? //sete al cell_t val = jit->read_cell(); IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val); else IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val); IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E); } inline void WriteOp_Inc_Pri(JitWriter *jit) { //add eax, 1 IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); } inline void WriteOp_Inc_Alt(JitWriter *jit) { //add edx, 1 IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); } inline void WriteOp_Inc(JitWriter *jit) { //add [edi+], 1 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); else IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); } inline void WriteOp_Inc_S(JitWriter *jit) { //add [ebx+], 1 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); else IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); } inline void WriteOp_Inc_I(JitWriter *jit) { //add [edi+eax], 1 IA32_Add_Rm_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); } inline void WriteOp_Dec_Pri(JitWriter *jit) { //sub eax, 1 IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG); } inline void WriteOp_Dec_Alt(JitWriter *jit) { //sub edx, 1 IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG); } inline void WriteOp_Dec(JitWriter *jit) { //sub [edi+], 1 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val); else IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val); } inline void WriteOp_Dec_S(JitWriter *jit) { //sub [ebx+], 1 cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val); else IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val); } inline void WriteOp_Dec_I(JitWriter *jit) { //sub [edi+eax], 1 IA32_Sub_Rm_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1); } inline void WriteOp_Load_Pri(JitWriter *jit) { //mov eax, [edi+] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); } inline void WriteOp_Load_Alt(JitWriter *jit) { //mov edx, [edi+] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); } inline void WriteOp_Load_S_Pri(JitWriter *jit) { //mov eax, [ebx+] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); } inline void WriteOp_Load_S_Alt(JitWriter *jit) { //mov edx, [ebx+] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); } inline void WriteOp_Lref_Pri(JitWriter *jit) { //mov eax, [edi+] //mov eax, [edi+eax] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } inline void WriteOp_Lref_Alt(JitWriter *jit) { //mov edx, [edi+] //mov edx, [edi+edx] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); } inline void WriteOp_Lref_S_Pri(JitWriter *jit) { //mov eax, [ebx+] //mov eax, [edi+eax] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } inline void WriteOp_Lref_S_Alt(JitWriter *jit) { //mov edx, [ebx+] //mov edx, [edi+edx] cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); } inline void WriteOp_Const_Pri(JitWriter *jit) { //mov eax, cell_t val = jit->read_cell(); IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val); } inline void WriteOp_Const_Alt(JitWriter *jit) { //mov edx, cell_t val = jit->read_cell(); IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val); } inline void WriteOp_Addr_Pri(JitWriter *jit) { //mov eax, frm //add eax, cell_t val = jit->read_cell(); IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_INFO_FRM, MOD_MEM_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG); else IA32_Add_Eax_Imm32(jit, val); } inline void WriteOp_Addr_Alt(JitWriter *jit) { //mov edx, frm //add edx, cell_t val = jit->read_cell(); IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_INFO_FRM, MOD_MEM_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG); else IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG); } inline void WriteOp_Stor_Pri(JitWriter *jit) { //mov [edi+], eax cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val); else IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val); } inline void WriteOp_Stor_Alt(JitWriter *jit) { //mov [edi+], edx cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val); else IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val); } inline void WriteOp_Stor_S_Pri(JitWriter *jit) { //mov [ebx+], eax cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val); else IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val); } inline void WriteOp_Stor_S_Alt(JitWriter *jit) { //mov [ebx+], edx cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val); else IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val); } inline void WriteOp_Idxaddr(JitWriter *jit) { //lea eax, [edx+4*eax] IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); } inline void WriteOp_Idxaddr_B(JitWriter *jit) { //shl eax, //add eax, edx cell_t val = jit->read_cell(); IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); } inline void WriteOp_Sref_Pri(JitWriter *jit) { //mov ecx, [edi+] //mov [edi+ecx], eax cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); } inline void WriteOp_Sref_Alt(JitWriter *jit) { //mov ecx, [edi+] //mov [edi+ecx], edx cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); } inline void WriteOp_Sref_S_Pri(JitWriter *jit) { //mov ecx, [ebx+] //mov [edi+ecx], eax cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI); } inline void WriteOp_Sref_S_Alt(JitWriter *jit) { //mov ecx, [ebx+] //mov [edi+ecx], edx cell_t val = jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); else IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT); } inline void WriteOp_Align_Pri(JitWriter *jit) { //xor eax, cell_t val = sizeof(cell_t) - jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val); else IA32_Xor_Eax_Imm32(jit, val); } inline void WriteOp_Align_Alt(JitWriter *jit) { //xor edx, cell_t val = sizeof(cell_t) - jit->read_cell(); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val); else IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val); } inline void WriteOp_Pop_Pri(JitWriter *jit) { //mov eax, [ebp] //add ebp, 4 IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Pop_Alt(JitWriter *jit) { //mov edx, [ebp] //add ebp, 4 IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Swap_Pri(JitWriter *jit) { //add [ebp], eax //sub eax, [ebp] //add [ebp], eax //neg eax IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG); IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG); IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG); } inline void WriteOp_Swap_Alt(JitWriter *jit) { //add [ebp], edx //sub edx, [ebp] //add [ebp], edx //neg edx IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG); IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG); } inline void WriteOp_PushAddr(JitWriter *jit) { //mov ecx, frm ;get address (offset from frame) //add ecx, //mov [ebp-4], ecx //sub ebp, 4 cell_t val = jit->read_cell(); IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG); else IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG); IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4); IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); } inline void WriteOp_Movs(JitWriter *jit) { //cld //push esi //lea esi, [edi+eax] //add edi, edx //if dword: // mov ecx, dword // rep movsd //if byte: // mov ecx, byte // rep movsb //sub edi, edx //sub edi, //pop esi cell_t val = jit->read_cell(); unsigned int dwords = val >> 2; unsigned int bytes = val & 0x3; IA32_Cld(jit); IA32_Push_Reg(jit, REG_ESI); IA32_Lea_Reg_DispRegMult(jit, REG_ESI, REG_EDI, AMX_REG_PRI, NOSCALE); IA32_Add_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG); if (dwords) { IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, dwords); IA32_Rep(jit); IA32_Movsd(jit); } if (bytes) { IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, bytes); IA32_Rep(jit); IA32_Movsb(jit); } IA32_Sub_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Sub_Rm_Imm8(jit, REG_EDI, (jit_uint8_t)val, MOD_REG); else IA32_Sub_Rm_Imm32(jit, REG_EDI, val, MOD_REG); IA32_Pop_Reg(jit, REG_ESI); } inline void WriteOp_Fill(JitWriter *jit) { //add edi, edx //mov ecx, >> 2 //cld //rep stosd //sub edi, edx //sub edi, >> 2 unsigned int val = jit->read_cell() >> 2; IA32_Add_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG); IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val); IA32_Cld(jit); IA32_Rep(jit); IA32_Stosd(jit); IA32_Sub_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Sub_Rm_Imm8(jit, REG_EDI, (jit_uint8_t)val, MOD_REG); else IA32_Sub_Rm_Imm32(jit, REG_EDI, val, MOD_REG); } inline void WriteOp_Heap_Pri(JitWriter *jit) { //mov edx, [hea] //add [hea], eax IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); IA32_Add_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP); } inline void WriteOp_Push_Heap_C(JitWriter *jit) { //mov ecx, [hea] //mov [edi+ecx], //add [hea], 4 cell_t val = jit->read_cell(); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); IA32_Mov_Rm_Imm32_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, val); IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, 4, AMX_INFO_HEAP); } inline void WriteOp_Pop_Heap_Pri(JitWriter *jit) { //sub [hea], 4 //mov ecx, [hea] //mov eax, [edi+ecx] IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_INFO, 4, AMX_INFO_HEAP); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_TMP, NOSCALE); } inline void WriteOp_Load_Both(JitWriter *jit) { WriteOp_Const_Pri(jit); WriteOp_Const_Alt(jit); } inline void WriteOp_Load_S_Both(JitWriter *jit) { WriteOp_Load_S_Pri(jit); WriteOp_Load_S_Alt(jit); } inline void WriteOp_Const(JitWriter *jit) { //mov [edi+], cell_t addr = jit->read_cell(); cell_t val = jit->read_cell(); if (addr < SCHAR_MAX && addr > SCHAR_MIN) { IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr); } else { IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr); } } inline void WriteOp_Const_S(JitWriter *jit) { //mov [ebx+], cell_t offs = jit->read_cell(); cell_t val = jit->read_cell(); if (offs < SCHAR_MAX && offs > SCHAR_MIN) { IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs); } else { IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs); } } inline void WriteOp_Load_I(JitWriter *jit) { //mov eax, [edi+eax] Write_Check_VerifyAddr(jit, AMX_REG_PRI, false); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } inline void WriteOp_Lodb_I(JitWriter *jit) { Write_Check_VerifyAddr(jit, AMX_REG_PRI, false); //mov eax, [edi+eax] IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); //and eax, cell_t val = jit->read_cell(); switch(val) { case 1: { IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF); break; } case 2: { IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF); break; } } } inline void WriteOp_Stor_I(JitWriter *jit) { //mov [edi+edx], eax Write_Check_VerifyAddr(jit, AMX_REG_ALT, false); IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); } inline void WriteOp_Strb_I(JitWriter *jit) { Write_Check_VerifyAddr(jit, AMX_REG_ALT, false); //mov [edi+edx], eax cell_t val = jit->read_cell(); switch (val) { case 1: { IA32_Mov_Rm8_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); break; } case 2: { IA32_Mov_Rm16_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); break; } case 3: { IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); break; } } } inline void WriteOp_Lidx(JitWriter *jit) { //lea eax, [edx+4*eax] //mov eax, [edi+eax] IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); Write_Check_VerifyAddr(jit, AMX_REG_PRI, false); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } inline void WriteOp_Lidx_B(JitWriter *jit) { cell_t val = jit->read_cell(); //shl eax, //add eax, edx //mov eax, [edi+eax] IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG); IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); Write_Check_VerifyAddr(jit, AMX_REG_PRI, false); IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } inline void WriteOp_Lctrl(JitWriter *jit) { cell_t val = jit->read_cell(); switch (val) { case 0: { //mov ecx, [esi+ctx] //mov eax, [ecx+] IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_CONTEXT); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_ECX, offsetof(sp_context_t, base)); break; } case 1: { //mov eax, edi IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG); break; } case 2: { //mov eax, [esi+hea] IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP); break; } case 3: { //mov ecx, [esi+ctx] //mov eax, [ecx+ctx.memory] IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_CONTEXT); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_ECX, offsetof(sp_context_t, memory)); break; } case 4: { //mov eax, ebp //sub eax, edi - unrelocate IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG); IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG); break; } case 5: { //mov eax, [esi+frm] IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_FRM); break; } case 6: { //mov eax, [cip] jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0); jitoffs_t save = jit->jit_curpos(); jit->setpos(imm32); jit->write_int32((uint32_t)(jit->outbase + save)); jit->setpos(save); break; } } } inline void WriteOp_Sctrl(JitWriter *jit) { cell_t val = jit->read_cell(); switch (val) { case 2: { //mov [esi+hea], eax IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, AMX_REG_PRI); break; } case 4: { //lea ebp, [edi+eax] IA32_Lea_Reg_DispRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); break; } case 5: { //mov ebx, eax - overwrite frm //mov frm, eax - overwrite stacked frame //add ebx, edi - relocate local frm IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_PRI, MOD_REG); IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_PRI, MOD_MEM_REG); IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); break; } case 6: { IA32_Jump_Reg(jit, AMX_REG_PRI); break; } } } inline void WriteOp_Stack(JitWriter *jit) { //mov edx, ebp //add ebp, //sub edx, edi cell_t val = jit->read_cell(); IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG); if (val < SCHAR_MAX && val > SCHAR_MIN) IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG); else IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG); IA32_Sub_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG); Write_CheckMargin_Stack(jit); } /************************************************* ************************************************* * JIT PROPER ************************************ * The rest of the from now on is the JIT engine * ************************************************* *************************************************/ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err) { CompData *data = (CompData *)co; sp_plugin_t *plugin = data->plugin; /* The first phase is to browse */ uint8_t *code = plugin->pcode; uint8_t *cip; uint8_t *end_cip = plugin->pcode + plugin->pcode_size; OPCODE op; int op_c; uint32_t reloc_count = 0; /* FIRST PASS (light load) - Get initial opcode information */ for (cip = code; cip < end_cip;) { op = (OPCODE)*(ucell_t *)cip; if ((unsigned)op >= OP_NUM_OPCODES) { AbortCompilation(co); *err = SP_ERR_INVALID_INSTRUCTION; return NULL; } cip += sizeof(cell_t); op_c = OpAdvTable[op]; if (op_c >= 0) { cip += op_c; } else if (op_c == -3) { AbortCompilation(co); *err = SP_ERR_INVALID_INSTRUCTION; return NULL; } else if (op_c == -2) { reloc_count++; cip += sizeof(cell_t); } else if (op_c == -1) { switch (op) { case OP_CASETBL: { ucell_t num = *(ucell_t *)cip; cip += sizeof(cell_t); reloc_count += (num + 1); cip += ((2*num) + 1) * sizeof(cell_t); break; } default: { AbortCompilation(co); *err = SP_ERR_INVALID_INSTRUCTION; return NULL; } } } } /********************************************* * SECOND PASS (medium load): writer.outbase is NULL, getting size only * THIRD PASS (heavy load!!): writer.outbase is valid and output is written *********************************************/ JitWriter writer; JitWriter *jit = &writer; cell_t *endptr = (cell_t *)(end_cip); /* Initial code is written "blank," * so we can check the exact memory usage. */ writer.inptr = (cell_t *)code; writer.outptr = NULL; writer.outbase = NULL; /* Get inlining level */ int inline_level = data->inline_level; //:TODO: Jump back here once finished! /* Start writing the actual code */ data->jit_return = Write_Execute_Function(jit); /* Write error checking routines in case they are needed */ data->jit_verify_addr_eax = jit->jit_curpos(); Write_Check_VerifyAddr(jit, REG_EAX, true); data->jit_verify_addr_edx = jit->jit_curpos(); Write_Check_VerifyAddr(jit, REG_EDX, true); for (; writer.inptr <= endptr;) { op = (OPCODE)writer.read_cell(); switch (op) { case OP_MOVE_PRI: { WriteOp_Move_Pri(jit); break; } case OP_MOVE_ALT: { WriteOp_Move_Alt(jit); break; } case OP_XCHG: { WriteOp_Xchg(jit); break; } case OP_PUSH: { WriteOp_Push(jit); break; } case OP_PUSH_S: { WriteOp_Push_S(jit); break; } case OP_PUSH2_C: { WriteOp_Push2_C(jit); break; } case OP_PUSH3_C: { WriteOp_Push3(jit); break; } case OP_PUSH4_C: { WriteOp_Push4_C(jit); break; } case OP_PUSH5_C: { WriteOp_Push5_C(jit); break; } case OP_PUSH2_ADR: { WriteOp_Push2_Adr(jit); break; } case OP_PUSH3_ADR: { WriteOp_Push3_Adr(jit); break; } case OP_PUSH4_ADR: { WriteOp_Push4_Adr(jit); break; } case OP_PUSH5_ADR: { WriteOp_Push5_Adr(jit); break; } case OP_PUSH2_S: { WriteOp_Push2_S(jit); break; } case OP_PUSH3_S: { WriteOp_Push3_S(jit); break; } case OP_PUSH4_S: { WriteOp_Push4_S(jit); break; } case OP_PUSH5_S: { WriteOp_Push5_S(jit); break; } case OP_PUSH5: { WriteOp_Push5(jit); break; } case OP_PUSH4: { WriteOp_Push4(jit); break; } case OP_PUSH3: { WriteOp_Push3(jit); break; } case OP_PUSH2: { WriteOp_Push2(jit); break; } case OP_ZERO_PRI: { WriteOp_Zero_Pri(jit); break; } case OP_ZERO_ALT: { WriteOp_Zero_Alt(jit); break; } case OP_PROC: { WriteOp_Proc(jit); break; } case OP_SHL: { WriteOp_Shl(jit); break; } case OP_SHR: { WriteOp_Shr(jit); break; } case OP_SSHR: { WriteOp_Sshr(jit); break; } case OP_SHL_C_PRI: { WriteOp_Shl_C_Pri(jit); break; } case OP_SHL_C_ALT: { WriteOp_Shl_C_Alt(jit); break; } case OP_SHR_C_PRI: { WriteOp_Shr_C_Pri(jit); break; } case OP_SHR_C_ALT: { WriteOp_Shr_C_Alt(jit); break; } case OP_SMUL: { WriteOp_SMul(jit); break; } case OP_UMUL: { WriteOp_UMul(jit); break; } case OP_ADD: { WriteOp_Add(jit); break; } case OP_SUB: { WriteOp_Sub(jit); break; } case OP_SUB_ALT: { WriteOp_Sub_Alt(jit); break; } case OP_NOP: { /* do nothing */ break; } case OP_NOT: { WriteOp_Not(jit); break; } case OP_NEG: { WriteOp_Neg(jit); break; } case OP_XOR: { WriteOp_Xor(jit); break; } case OP_OR: { WriteOp_Or(jit); break; } case OP_AND: { WriteOp_And(jit); break; } case OP_INVERT: { WriteOp_Invert(jit); break; } case OP_ADD_C: { WriteOp_Add_C(jit); break; } case OP_SMUL_C: { WriteOp_SMul_C(jit); break; } case OP_SIGN_PRI: { WriteOp_Sign_Pri(jit); break; } case OP_SIGN_ALT: { WriteOp_Sign_Alt(jit); break; } case OP_EQ: { WriteOp_Eq(jit); break; } case OP_NEQ: { WriteOp_Neq(jit); break; } case OP_LESS: { WriteOp_Less(jit); break; } case OP_LEQ: { WriteOp_Leq(jit); break; } case OP_GRTR: { WriteOp_Grtr(jit); break; } case OP_GEQ: { WriteOp_Geq(jit); break; } case OP_SLESS: { WriteOp_Sless(jit); break; } case OP_SLEQ: { WriteOp_Sleq(jit); break; } case OP_SGRTR: { WriteOp_Sgrtr(jit); break; } case OP_SGEQ: { WriteOp_Sgeq(jit); break; } case OP_EQ_C_PRI: { WriteOp_Eq_C_Pri(jit); break; } case OP_EQ_C_ALT: { WriteOp_Eq_C_Alt(jit); break; } case OP_INC_PRI: { WriteOp_Inc_Pri(jit); break; } case OP_INC_ALT: { WriteOp_Inc_Alt(jit); break; } case OP_INC: { WriteOp_Inc(jit); break; } case OP_INC_S: { WriteOp_Inc_S(jit); break; } case OP_INC_I: { WriteOp_Inc_I(jit); break; } case OP_DEC_PRI: { WriteOp_Dec_Pri(jit); break; } case OP_DEC_ALT: { WriteOp_Dec_Alt(jit); break; } case OP_DEC: { WriteOp_Dec(jit); break; } case OP_DEC_S: { WriteOp_Dec_S(jit); break; } case OP_DEC_I: { WriteOp_Dec_I(jit); break; } case OP_LOAD_PRI: { WriteOp_Load_Pri(jit); break; } case OP_LOAD_ALT: { WriteOp_Load_Alt(jit); break; } case OP_LOAD_S_PRI: { WriteOp_Load_S_Pri(jit); break; } case OP_LOAD_S_ALT: { WriteOp_Load_S_Alt(jit); break; } case OP_LREF_PRI: { WriteOp_Lref_Pri(jit); break; } case OP_LREF_ALT: { WriteOp_Lref_Alt(jit); break; } case OP_LREF_S_PRI: { WriteOp_Lref_Pri(jit); break; } case OP_LREF_S_ALT: { WriteOp_Lref_Alt(jit); break; } case OP_CONST_PRI: { WriteOp_Const_Pri(jit); break; } case OP_CONST_ALT: { WriteOp_Const_Alt(jit); break; } case OP_ADDR_PRI: { WriteOp_Addr_Pri(jit); break; } case OP_ADDR_ALT: { WriteOp_Addr_Alt(jit); break; } case OP_STOR_PRI: { WriteOp_Stor_Pri(jit); break; } case OP_STOR_ALT: { WriteOp_Stor_Alt(jit); break; } case OP_STOR_S_PRI: { WriteOp_Stor_S_Pri(jit); break; } case OP_STOR_S_ALT: { WriteOp_Stor_S_Alt(jit); break; } case OP_IDXADDR: { WriteOp_Idxaddr(jit); break; } case OP_SREF_PRI: { WriteOp_Sref_Pri(jit); break; } case OP_SREF_ALT: { WriteOp_Sref_Alt(jit); break; } case OP_SREF_S_PRI: { WriteOp_Sref_S_Pri(jit); break; } case OP_SREF_S_ALT: { WriteOp_Sref_S_Alt(jit); break; } case OP_ALIGN_PRI: { WriteOp_Align_Pri(jit); break; } case OP_ALIGN_ALT: { WriteOp_Align_Alt(jit); break; } case OP_POP_PRI: { WriteOp_Pop_Pri(jit); break; } case OP_POP_ALT: { WriteOp_Pop_Alt(jit); break; } case OP_SWAP_PRI: { WriteOp_Swap_Pri(jit); break; } case OP_SWAP_ALT: { WriteOp_Swap_Alt(jit); break; } case OP_PUSH_ADR: { WriteOp_PushAddr(jit); break; } case OP_MOVS: { WriteOp_Movs(jit); break; } case OP_FILL: { WriteOp_Fill(jit); break; } case OP_HEAP_PRI: { WriteOp_Heap_Pri(jit); break; } case OP_PUSH_HEAP_C: { WriteOp_Push_Heap_C(jit); break; } case OP_POP_HEAP_PRI: { WriteOp_Pop_Heap_Pri(jit); break; } case OP_PUSH_C: { WriteOp_Push_C(jit); break; } case OP_ZERO: { WriteOp_Zero(jit); break; } case OP_ZERO_S: { WriteOp_Zero_S(jit); break; } case OP_PUSH_PRI: { WriteOp_Push_Pri(jit); break; } case OP_PUSH_ALT: { WriteOp_Push_Alt(jit); break; } case OP_LOAD_BOTH: { WriteOp_Load_Both(jit); break; } case OP_LOAD_S_BOTH: { WriteOp_Load_S_Both(jit); break; } case OP_CONST: { WriteOp_Const(jit); break; } case OP_CONST_S: { WriteOp_Const_S(jit); break; } case OP_LOAD_I: { WriteOp_Load_I(jit); break; } case OP_LODB_I: { WriteOp_Lodb_I(jit); break; } case OP_STOR_I: { WriteOp_Stor_I(jit); break; } case OP_STRB_I: { WriteOp_Strb_I(jit); break; } case OP_LIDX: { WriteOp_Lidx(jit); break; } case OP_LIDX_B: { WriteOp_Lidx_B(jit); break; } case OP_IDXADDR_B: { WriteOp_Idxaddr_B(jit); break; } case OP_LCTRL: { WriteOp_Lctrl(jit); break; } case OP_SCTRL: { WriteOp_Sctrl(jit); break; } case OP_STACK: { WriteOp_Stack(jit); break; } default: { AbortCompilation(co); *err = SP_ERR_INVALID_INSTRUCTION; return NULL; } } } *err = SP_ERR_NONE; return NULL; } const char *JITX86::GetVMName() { return "JIT (x86)"; } ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin) { CompData *data = new CompData; data->plugin = plugin; return data; } void JITX86::AbortCompilation(ICompilation *co) { delete (CompData *)co; } bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val) { CompData *data = (CompData *)co; if (strcmp(key, "debug") == 0) { data->debug = (atoi(val) == 1); if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG)) { data->debug = false; return false; } return true; } return false; }