diff --git a/sourcepawn/include/sp_vm_api.h b/sourcepawn/include/sp_vm_api.h index 8c6e7589..c07248d8 100644 --- a/sourcepawn/include/sp_vm_api.h +++ b/sourcepawn/include/sp_vm_api.h @@ -59,7 +59,7 @@ namespace SourcePawn virtual void FreeBaseContext(IPluginContext *ctx) =0; /** - * Allocates memory. + * Allocates large blocks of temporary memory. * * @param size Size of memory to allocate. * @return Pointer to memory, NULL if allocation failed. @@ -72,6 +72,21 @@ namespace SourcePawn * @param mem Memory address to free. */ virtual void BaseFree(void *memory) =0; + + /** + * Allocates executable memory. + * + * @param size Size of memory to allocate. + * @return Pointer to memory, NULL if allocation failed. + */ + virtual void *ExecAlloc(size_t size) =0; + + /** + * Frees executable memory. + * + * @param mem Address to free. + */ + virtual void ExecFree(void *address) =0; }; class ICompilation @@ -107,14 +122,14 @@ namespace SourcePawn virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0; /** - * Finalizes a compilation into a new IContext. + * Finalizes a compilation into a new sp_context_t. * Note: This will free the ICompilation pointer. * * @param co Compilation pointer. * @param err Filled with error code on exit. * @return New plugin context. */ - virtual IPluginContext *CompileToContext(ICompilation *co, int *err) =0; + virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0; /** * Aborts a compilation and frees the ICompilation pointer. @@ -128,7 +143,7 @@ namespace SourcePawn * * @param ctx Context structure pointer. */ - virtual void FreeContextVars(sp_context_t *ctx) =0; + virtual void FreeContext(sp_context_t *ctx) =0; /** * Calls the "execute" function on a context. diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h index 95434180..e81802d1 100644 --- a/sourcepawn/include/sp_vm_types.h +++ b/sourcepawn/include/sp_vm_types.h @@ -201,7 +201,7 @@ typedef int (*SPVM_DEBUGBREAK)(SourcePawn::IPluginContext *, uint32_t, uint32_t) typedef struct sp_context_s { /* general/parent information */ - void *base; /* base of generated code and memory */ + void *codebase; /* base of generated code and memory */ sp_plugin_t *plugin; /* pointer back to parent information */ SourcePawn::IPluginContext *context; /* pointer to IPluginContext */ SourcePawn::IVirtualMachine *vmbase; /* pointer to IVirtualMachine */ diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index 57da1767..1835acea 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -5,6 +5,10 @@ #include "opcode_helpers.h" #include "x86_macros.h" +#if defined USE_UNGEN_OPCODES +#include "ungen_opcodes.h" +#endif + inline void WriteOp_Move_Pri(JitWriter *jit) { //mov eax, edx @@ -231,6 +235,27 @@ inline void WriteOp_Proc(JitWriter *jit) IA32_Sub_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_DAT, MOD_MEM_REG); } +inline void WriteOp_Lidx_B(JitWriter *jit) +{ + cell_t val = jit->read_cell(); + //shl eax, <val> + //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_Idxaddr_B(JitWriter *jit) +{ + //shl eax, <val> + //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_Shl(JitWriter *jit) { //mov ecx, edx @@ -293,18 +318,6 @@ inline void WriteOp_SMul(JitWriter *jit) IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG); } -#ifdef UNSUPPORTED -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); -} -#endif - inline void WriteOp_Not(JitWriter *jit) { //test eax, eax @@ -401,54 +414,6 @@ inline void WriteOp_Neq(JitWriter *jit) IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE); } -#ifdef UNSUPPORTED -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); -} -#endif - -#ifdef UNSUPPORTED -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); -} -#endif - -#ifdef UNSUPPORTED -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); -} -#endif - -#ifdef UNSUPPORTED -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); -} -#endif - inline void WriteOp_Sless(JitWriter *jit) { //cmp eax, edx ; PRI < ALT ? (signed) @@ -633,7 +598,6 @@ inline void WriteOp_Load_S_Alt(JitWriter *jit) IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val); } -#ifdef UNSUPPORTED inline void WriteOp_Lref_Pri(JitWriter *jit) { //mov eax, [edi+<val>] @@ -645,9 +609,7 @@ inline void WriteOp_Lref_Pri(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Lref_Alt(JitWriter *jit) { //mov edx, [edi+<val>] @@ -659,9 +621,7 @@ inline void WriteOp_Lref_Alt(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Lref_S_Pri(JitWriter *jit) { //mov eax, [ebx+<val>] @@ -673,9 +633,7 @@ inline void WriteOp_Lref_S_Pri(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Lref_S_Alt(JitWriter *jit) { //mov edx, [ebx+<val>] @@ -687,7 +645,6 @@ inline void WriteOp_Lref_S_Alt(JitWriter *jit) 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); } -#endif inline void WriteOp_Const_Pri(JitWriter *jit) { @@ -773,18 +730,6 @@ inline void WriteOp_Idxaddr(JitWriter *jit) IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4); } -#ifdef UNSUPPORTED -inline void WriteOp_Idxaddr_B(JitWriter *jit) -{ - //shl eax, <val> - //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); -} -#endif - -#ifdef UNSUPPORTED inline void WriteOp_Sref_Pri(JitWriter *jit) { //mov ecx, [edi+<val>] @@ -796,9 +741,7 @@ inline void WriteOp_Sref_Pri(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Sref_Alt(JitWriter *jit) { //mov ecx, [edi+<val>] @@ -810,9 +753,7 @@ inline void WriteOp_Sref_Alt(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Sref_S_Pri(JitWriter *jit) { //mov ecx, [ebx+<val>] @@ -824,9 +765,7 @@ inline void WriteOp_Sref_S_Pri(JitWriter *jit) 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); } -#endif -#ifdef UNSUPPORTED inline void WriteOp_Sref_S_Alt(JitWriter *jit) { //mov ecx, [ebx+<val>] @@ -838,31 +777,6 @@ inline void WriteOp_Sref_S_Alt(JitWriter *jit) 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); } -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Align_Pri(JitWriter *jit) -{ - //xor eax, <cellsize - val> - 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); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Align_Alt(JitWriter *jit) -{ - //xor edx, <cellsize - val> - 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); -} -#endif inline void WriteOp_Pop_Pri(JitWriter *jit) { @@ -963,39 +877,6 @@ inline void WriteOp_Movs(JitWriter *jit) IA32_Pop_Reg(jit, REG_ESI); } -#ifdef UNSUPPORTED -inline void WriteOp_Cmps(JitWriter *jit) -{ - //push edi - //push esi - //lea esi, [edi+edx] - //lea edi, [edi+eax] - IA32_Push_Reg(jit, REG_EDI); - IA32_Push_Reg(jit, REG_ESI); - IA32_Lea_Reg_DispRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); - IA32_Lea_Reg_DispRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); - - //xor eax, eax - //repe cmpsb - //je :cmps1 - IA32_Xor_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); - IA32_Cmpsb(jit); - jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0); - - //sbb eax, eax - //sbb eax, -1 - IA32_Sbb_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); - IA32_Sbb_Eax_Imm32(jit, -1);//:TODO: use imm8 here - - //:cmps1 - //pop esi - //pop edi - IA32_Send_Jump8_Here(jit, jmp); - IA32_Pop_Reg(jit, REG_ESI); - IA32_Pop_Reg(jit, REG_EDI); -} -#endif - inline void WriteOp_Fill(JitWriter *jit) { //add edi, edx @@ -1099,32 +980,6 @@ inline void WriteOp_Load_I(JitWriter *jit) IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } -#ifdef UNSUPPORTED -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, <bitmask> - cell_t val = jit->read_cell(); - switch(val) - { - case 1: - { - IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);//:TODO: replace with AND EAX, imm32 - break; - } - case 2: - { - IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);//:TODO: replace with AND EAX, imm32 - break; - } - } -} -#endif - inline void WriteOp_Stor_I(JitWriter *jit) { //mov [edi+edx], eax @@ -1132,33 +987,6 @@ inline void WriteOp_Stor_I(JitWriter *jit) IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); } -#ifdef UNSUPPORTED -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 4: - { - IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); - break; - } - } -} -#endif - inline void WriteOp_Lidx(JitWriter *jit) { //lea eax, [edx+4*eax] @@ -1168,119 +996,6 @@ inline void WriteOp_Lidx(JitWriter *jit) IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); } -#ifdef UNSUPPORTED -inline void WriteOp_Lidx_B(JitWriter *jit) -{ - cell_t val = jit->read_cell(); - //shl eax, <val> - //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); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Lctrl(JitWriter *jit) -{ - cell_t val = jit->read_cell(); - switch (val) - { - case 0: - { - //mov ecx, [esi+ctx] - //mov eax, [ecx+<offs>] - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, 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, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, 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; - } - } -} -#endif - -#ifdef UNSUPPORTED -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 //:TODO: use LEA here!!! - 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; - } - } -} -#endif - inline void WriteOp_Stack(JitWriter *jit) { //mov edx, ebp @@ -1337,50 +1052,6 @@ inline void WriteOp_SDiv_Alt(JitWriter *jit) IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); } -#ifdef UNSUPPORTED -inline void WriteOp_UDiv(JitWriter *jit) -{ - //mov ecx, edx - //xor edx, edx - //div ecx - IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); - IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); - Write_Check_DivZero(jit, AMX_REG_TMP); - IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_UDiv_Alt(JitWriter *jit) -{ - //mov ecx, eax - //mov eax, edx - //xor edx, edx - //div ecx - IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); - IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); - IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); - Write_Check_DivZero(jit, AMX_REG_TMP); - IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Ret(JitWriter *jit) -{ - //mov ebx, [ebp] - get old FRM - //add ebp, 4 - pop stack - //mov [esi+frm], ebx - restore - //add ebx, edi - relocate - //ret - IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG); - IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); - IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong! - IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); - IA32_Return(jit); -} -#endif - inline void WriteOp_Retn(JitWriter *jit) { //mov ebx, [ebp] - get old frm @@ -1449,21 +1120,6 @@ inline void WriteOp_Break(JitWriter *jit) } } -#ifdef UNSUPPORTED -inline void WriteOp_JRel(JitWriter *jit) -{ - //jmp <offs> ;relative jump - cell_t cip_offs = jit->read_cell(); - - /* Note that since code size calculation has to be done in the same - * phase as building relocation information, we cannot know the jump size - * beforehand. Thus, we always write full 32bit jumps for safety. - */ - jitoffs_t jmp = IA32_Jump_Imm32(jit, 0); - IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs)); -} -#endif - inline void WriteOp_Jump(JitWriter *jit) { //jmp <offs> @@ -1508,50 +1164,6 @@ inline void WriteOp_Jneq(JitWriter *jit) IA32_Jump_Cond_Imm32(jit, CC_NE, RelocLookup(jit, target, false)); } -#ifdef UNSUPPORTED -inline void WriteOp_Jless(JitWriter *jit) -{ - //cmp eax, edx - //jb <target> - cell_t target = jit->read_cell(); - IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); - IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false)); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Jleq(JitWriter *jit) -{ - //cmp eax, edx - //jbe <target> - cell_t target = jit->read_cell(); - IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); - IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false)); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Jgrtr(JitWriter *jit) -{ - //cmp eax, edx - //ja <target> - cell_t target = jit->read_cell(); - IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); - IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false)); -} -#endif - -#ifdef UNSUPPORTED -inline void WriteOp_Jgeq(JitWriter *jit) -{ - //cmp eax, edx - //jae <target> - cell_t target = jit->read_cell(); - IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); - IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false)); -} -#endif - inline void WriteOp_Jsless(JitWriter *jit) { //cmp eax, edx @@ -1617,7 +1229,7 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) } } -IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err) +sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err) { CompData *data = (CompData *)co; sp_plugin_t *plugin = data->plugin; @@ -1750,7 +1362,7 @@ jit_rewind: /* the total codesize is now known! */ uint32_t mem = writer.jit_curpos(); - writer.outbase = new char[mem]; + writer.outbase = (jitcode_t)engine->ExecAlloc(mem); writer.outptr = writer.outbase; /* go back for third pass */ goto jit_rewind; @@ -1768,29 +1380,31 @@ jit_rewind: } } - /******* - * Context Setup - *******/ + /************* + * FOURTH PASS - Context Setup + *************/ + sp_context_t *ctx = new sp_context_t; memset(ctx, 0, sizeof(sp_context_t)); - ctx->base = plugin->base; + /* setup basics */ + ctx->codebase = writer.outbase; ctx->plugin = plugin; - ctx->context = engine->CreateBaseContext(ctx); ctx->vmbase = this; ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0); + /* setup memory */ ctx->data = new uint8_t[plugin->memory]; memcpy(ctx->data, plugin->data, plugin->data_size); ctx->memory = plugin->memory; ctx->heapbase = plugin->data_size; - ctx->hp = ctx->heapbase; ctx->sp = ctx->memory - sizeof(cell_t); const char *strbase = plugin->info.stringbase; uint32_t max, iter; + /* relocate public info */ if ((max = plugin->info.publics_num)) { ctx->publics = new sp_public_t[max]; @@ -1801,6 +1415,7 @@ jit_rewind: } } + /* relocate pubvar info */ if ((max = plugin->info.pubvars_num)) { uint8_t *dat = ctx->data; @@ -1812,21 +1427,26 @@ jit_rewind: } } + /* relocate native info */ if ((max = plugin->info.natives_num)) { ctx->natives = new sp_native_t[max]; for (iter=0; iter<max; iter++) { ctx->natives[iter].name = strbase + plugin->info.natives[iter].name; - //ctx->natives[iter].pfn = SP_NoExecNative; :TODO: + ctx->natives[iter].pfn = NULL; ctx->natives[iter].status = SP_NATIVE_NONE; } } - strbase = plugin->debug.stringbase; - - if (plugin->flags & SP_FLAG_DEBUG) + /** + * If we're debugging, make sure we copy the necessary info. + */ + if (data->debug) { + strbase = plugin->debug.stringbase; + + /* relocate files */ max = plugin->debug.files_num; ctx->files = new sp_debug_file_t[max]; for (iter=0; iter<max; iter++) @@ -1835,6 +1455,7 @@ jit_rewind: ctx->files[iter].name = strbase + plugin->debug.files[iter].name; } + /* relocate lines */ max = plugin->debug.lines_num; ctx->lines = new sp_debug_line_t[max]; for (iter=0; iter<max; iter++) @@ -1843,6 +1464,7 @@ jit_rewind: ctx->lines[iter].line = plugin->debug.lines[iter].line; } + /* relocate arrays */ sp_fdbg_symbol_t *sym; sp_fdbg_arraydim_t *arr; uint8_t *cursor = (uint8_t *)(plugin->debug.symbols); @@ -1872,9 +1494,13 @@ jit_rewind: } } + /* clean up relocation+compilation memory */ + engine->BaseFree(data->rebase); + delete data; + *err = SP_ERR_NONE; - return ctx->context; + return ctx; } const char *JITX86::GetVMName() @@ -1882,6 +1508,26 @@ const char *JITX86::GetVMName() return "JIT (x86)"; } +int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result) +{ + typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *); + CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase; + return fn(ctx, code_idx, result); +} + +void JITX86::FreeContext(sp_context_t *ctx) +{ + engine->ExecFree(ctx->codebase); + delete [] ctx->data; + delete [] ctx->files; + delete [] ctx->lines; + delete [] ctx->natives; + delete [] ctx->publics; + delete [] ctx->pubvars; + delete [] ctx->symbols; + delete ctx; +} + ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin) { CompData *data = new CompData; diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h index 01febc4f..a3a08322 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.h +++ b/sourcepawn/vm/jit/x86/jit_x86.h @@ -42,9 +42,9 @@ public: const char *GetVMName() =0; ICompilation *StartCompilation(sp_plugin_t *plugin); bool SetCompilationOption(ICompilation *co, const char *key, const char *val) ; - IPluginContext *CompileToContext(ICompilation *co, int *err); + sp_context_t *CompileToContext(ICompilation *co, int *err); void AbortCompilation(ICompilation *co); - void FreeContextVars(sp_context_t *ctx); + void FreeContext(sp_context_t *ctx); int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result); }; diff --git a/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj b/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj index 1f3f4973..f7e0b79c 100644 --- a/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj +++ b/sourcepawn/vm/jit/x86/msvc8/jit-x86.vcproj @@ -213,6 +213,10 @@ RelativePath="..\opcode_helpers.h" > </File> + <File + RelativePath="..\ungen_opcodes.h" + > + </File> <File RelativePath="..\x86_macros.h" > @@ -227,6 +231,10 @@ RelativePath="..\opcode_switch.inc" > </File> + <File + RelativePath="..\ungen_opcode_switch.inc" + > + </File> </Filter> <Filter Name="SDK" diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index f6c2d3ff..809567bf 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -6,7 +6,7 @@ int OpAdvTable[OP_NUM_OPCODES]; -jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline) +jitoffs_t Write_Execute_Function(JitWriter *jit) { /** * The variables we're passed in: @@ -79,7 +79,7 @@ jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline) //mov edx, [eax+<offs>] - get alt //mov eax, [eax+<offs>] - get pri IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 12); - IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, base)); + IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase)); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, REG_EAX, offsetof(sp_context_t, alt)); IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_EAX, offsetof(sp_context_t, pri)); @@ -503,7 +503,6 @@ JITX86::JITX86() OpAdvTable[OP_LREF_ALT] = sizeof(cell_t); OpAdvTable[OP_LREF_S_PRI] = sizeof(cell_t); OpAdvTable[OP_LREF_S_ALT] = sizeof(cell_t); - OpAdvTable[OP_LODB_I] = sizeof(cell_t); OpAdvTable[OP_CONST_PRI] = sizeof(cell_t); OpAdvTable[OP_CONST_ALT] = sizeof(cell_t); OpAdvTable[OP_ADDR_PRI] = sizeof(cell_t); @@ -516,19 +515,13 @@ JITX86::JITX86() OpAdvTable[OP_SREF_ALT] = sizeof(cell_t); OpAdvTable[OP_SREF_S_PRI] = sizeof(cell_t); OpAdvTable[OP_SREF_S_ALT] = sizeof(cell_t); - OpAdvTable[OP_STRB_I] = sizeof(cell_t); OpAdvTable[OP_LIDX_B] = sizeof(cell_t); OpAdvTable[OP_IDXADDR_B] = sizeof(cell_t); - OpAdvTable[OP_ALIGN_PRI] = sizeof(cell_t); - OpAdvTable[OP_ALIGN_ALT] = sizeof(cell_t); - OpAdvTable[OP_LCTRL] = sizeof(cell_t); - OpAdvTable[OP_SCTRL] = sizeof(cell_t); OpAdvTable[OP_PUSH_C] = sizeof(cell_t); OpAdvTable[OP_PUSH] = sizeof(cell_t); OpAdvTable[OP_PUSH_S] = sizeof(cell_t); OpAdvTable[OP_STACK] = sizeof(cell_t); OpAdvTable[OP_HEAP] = sizeof(cell_t); - OpAdvTable[OP_JREL] = sizeof(cell_t); OpAdvTable[OP_SHL_C_PRI] = sizeof(cell_t); OpAdvTable[OP_SHL_C_ALT] = sizeof(cell_t); OpAdvTable[OP_SHR_C_PRI] = sizeof(cell_t); @@ -544,7 +537,6 @@ JITX86::JITX86() OpAdvTable[OP_DEC] = sizeof(cell_t); OpAdvTable[OP_DEC_S] = sizeof(cell_t); OpAdvTable[OP_MOVS] = sizeof(cell_t); - OpAdvTable[OP_CMPS] = sizeof(cell_t); OpAdvTable[OP_FILL] = sizeof(cell_t); OpAdvTable[OP_HALT] = sizeof(cell_t); OpAdvTable[OP_BOUNDS] = sizeof(cell_t); @@ -574,9 +566,6 @@ JITX86::JITX86() OpAdvTable[OP_SMUL] = 0; OpAdvTable[OP_SDIV] = 0; OpAdvTable[OP_SDIV_ALT] = 0; - OpAdvTable[OP_UMUL] = 0; - OpAdvTable[OP_UDIV] = 0; - OpAdvTable[OP_UDIV_ALT] = 0; OpAdvTable[OP_ADD] = 0; OpAdvTable[OP_SUB] = 0; OpAdvTable[OP_SUB_ALT] = 0; @@ -592,10 +581,6 @@ JITX86::JITX86() OpAdvTable[OP_SIGN_ALT] = 0; OpAdvTable[OP_EQ] = 0; OpAdvTable[OP_NEQ] = 0; - OpAdvTable[OP_LESS] = 0; - OpAdvTable[OP_LEQ] = 0; - OpAdvTable[OP_GRTR] = 0; - OpAdvTable[OP_GEQ] = 0; OpAdvTable[OP_SLESS] = 0; OpAdvTable[OP_SLEQ] = 0; OpAdvTable[OP_SGRTR] = 0; @@ -622,10 +607,6 @@ JITX86::JITX86() OpAdvTable[OP_JNZ] = -2; OpAdvTable[OP_JEQ] = -2; OpAdvTable[OP_JNEQ] = -2; - OpAdvTable[OP_JLESS] = -2; - OpAdvTable[OP_JLEQ] = -2; - OpAdvTable[OP_JGRTR] = -2; - OpAdvTable[OP_JGEQ] = -2; OpAdvTable[OP_JSLESS] = -2; OpAdvTable[OP_JSLEQ] = -2; OpAdvTable[OP_JSGRTR] = -2; @@ -633,6 +614,7 @@ JITX86::JITX86() OpAdvTable[OP_SWITCH] = -2; /* opcodes that are totally invalid */ + /* :TODO: make an alternate table if USE_UNGEN_OPCODES is on? */ OpAdvTable[OP_FILE] = -3; OpAdvTable[OP_SYMBOL] = -3; OpAdvTable[OP_LINE] = -3; @@ -641,4 +623,24 @@ JITX86::JITX86() OpAdvTable[OP_SYSREQ_D] = -3; OpAdvTable[OP_SYSREQ_ND] = -3; OpAdvTable[OP_PUSH_R] = -3; + OpAdvTable[OP_LODB_I] = -3; + OpAdvTable[OP_STRB_I] = -3; + OpAdvTable[OP_LCTRL] = -3; + OpAdvTable[OP_SCTRL] = -3; + OpAdvTable[OP_ALIGN_PRI] = -3; + OpAdvTable[OP_ALIGN_ALT] = -3; + OpAdvTable[OP_JREL] = -3; + OpAdvTable[OP_CMPS] = -3; + OpAdvTable[OP_UMUL] = -3; + OpAdvTable[OP_UDIV] = -3; + OpAdvTable[OP_UDIV_ALT] = -3; + OpAdvTable[OP_LESS] = -3; + OpAdvTable[OP_LEQ] = -3; + OpAdvTable[OP_GRTR] = -3; + OpAdvTable[OP_GEQ] = -3; + OpAdvTable[OP_JLESS] = -3; + OpAdvTable[OP_JLEQ] = -3; + OpAdvTable[OP_JGRTR] = -3; + OpAdvTable[OP_JGEQ] = -3; + } diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.h b/sourcepawn/vm/jit/x86/opcode_helpers.h index d5b024c5..20388dd2 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.h +++ b/sourcepawn/vm/jit/x86/opcode_helpers.h @@ -63,12 +63,12 @@ typedef enum OP_LOAD_ALT, //DONE OP_LOAD_S_PRI, //DONE OP_LOAD_S_ALT, //DONE - OP_LREF_PRI, //UNSUPPORTED - OP_LREF_ALT, //UNSUPPORTED - OP_LREF_S_PRI, //UNSUPPORTED - OP_LREF_S_ALT, //UNSUPPORTED + OP_LREF_PRI, // !GEN :TODO: we will need this for dynarrays + OP_LREF_ALT, // !GEN :TODO: we will need this for dynarrays + OP_LREF_S_PRI, //DONE + OP_LREF_S_ALT, //DONE OP_LOAD_I, //DONE - OP_LODB_I, //UNSUPPORTED + OP_LODB_I, // !GEN :TODO: - only used for pack access - drop support in compiler first OP_CONST_PRI, //DONE OP_CONST_ALT, //DONE OP_ADDR_PRI, //DONE @@ -77,26 +77,26 @@ typedef enum OP_STOR_ALT, //DONE OP_STOR_S_PRI, //DONE OP_STOR_S_ALT, //DONE - OP_SREF_PRI, //UNSUPPORTED - OP_SREF_ALT, //UNSUPPORTED - OP_SREF_S_PRI, //UNSUPPORTED - OP_SREF_S_ALT, //UNSUPPORTED + OP_SREF_PRI, //DONE + OP_SREF_ALT, //DONE + OP_SREF_S_PRI, // !GEN :TODO: we will need this for dynarrays + OP_SREF_S_ALT, // !GEN :TODO: we will need this for dynarrays OP_STOR_I, //DONE - OP_STRB_I, //UNSUPPORTED + OP_STRB_I, // !GEN :TODO: - only used for pack access, drop support in compiler first OP_LIDX, //DONE - OP_LIDX_B, //UNSUPPORTED + OP_LIDX_B, //DONE OP_IDXADDR, //DONE - OP_IDXADDR_B, //UNSUPPORTED - OP_ALIGN_PRI, //UNSUPPORTED - OP_ALIGN_ALT, //UNSUPPORTED - OP_LCTRL, //UNSUPPORTED - OP_SCTRL, //UNSUPPORTED + OP_IDXADDR_B, //DONE + OP_ALIGN_PRI, // !GEN :TODO: - only used for pack access, drop support in compiler first + OP_ALIGN_ALT, // !GEN :TODO: - only used for pack access, drop support in compiler first + OP_LCTRL, // !GEN + OP_SCTRL, // !GEN OP_MOVE_PRI, //DONE OP_MOVE_ALT, //DONE OP_XCHG, //DONE OP_PUSH_PRI, //DONE OP_PUSH_ALT, //DONE - OP_PUSH_R, //DEPRECATED + OP_PUSH_R, // !GEN DEPRECATED OP_PUSH_C, //DONE OP_PUSH, //DONE OP_PUSH_S, //DONE @@ -105,20 +105,20 @@ typedef enum OP_STACK, //DONE OP_HEAP, //DONE OP_PROC, //DONE - OP_RET, //UNSUPPORTED + OP_RET, // !GEN OP_RETN, //DONE OP_CALL, - OP_CALL_PRI, + OP_CALL_PRI, // !GEN OP_JUMP, //DONE - OP_JREL, //UNSUPPORTED + OP_JREL, // !GEN OP_JZER, //DONE OP_JNZ, //DONE OP_JEQ, //DONE OP_JNEQ, //DONE - OP_JLESS, //UNSUPPORTED - OP_JLEQ, //UNSUPPORTED - OP_JGRTR, //UNSUPPORTED - OP_JGEQ, //UNSUPPORTED + OP_JLESS, // !GEN + OP_JLEQ, // !GEN + OP_JGRTR, // !GEN + OP_JGEQ, // !GEN OP_JSLESS, //DONE OP_JSLEQ, //DONE OP_JSGRTR, //DONE @@ -133,9 +133,9 @@ typedef enum OP_SMUL, //DONE OP_SDIV, //DONE OP_SDIV_ALT, //DONE - OP_UMUL, //UNSUPPORTED - OP_UDIV, //UNSUPPORTED - OP_UDIV_ALT, //UNSUPPORTED + OP_UMUL, // !GEN + OP_UDIV, // !GEN + OP_UDIV_ALT, // !GEN OP_ADD, //DONE OP_SUB, //DONE OP_SUB_ALT, //DONE @@ -155,10 +155,10 @@ typedef enum OP_SIGN_ALT, //DONE OP_EQ, //DONE OP_NEQ, //DONE - OP_LESS, //UNSUPPORTED - OP_LEQ, //UNSUPPORTED - OP_GRTR, //UNSUPPORTED - OP_GEQ, //UNSUPPORTED + OP_LESS, // !GEN + OP_LEQ, // !GEN + OP_GRTR, // !GEN + OP_GEQ, // !GEN OP_SLESS, //DONE OP_SLEQ, //DONE OP_SGRTR, //DONE @@ -176,17 +176,17 @@ typedef enum OP_DEC_S, //DONE OP_DEC_I, //DONE OP_MOVS, //DONE - OP_CMPS, //UNSUPPORTED + OP_CMPS, // !GEN OP_FILL, //DONE OP_HALT, //DONE OP_BOUNDS, //DONE - OP_SYSREQ_PRI, - OP_SYSREQ_C, - OP_FILE, //DEPRECATED - OP_LINE, //DEPRECATED - OP_SYMBOL, //DEPRECATED - OP_SRANGE, //DEPRECATED - OP_JUMP_PRI, + OP_SYSREQ_PRI, // !GEN + OP_SYSREQ_C, + OP_FILE, // !GEN DEPRECATED + OP_LINE, // !GEN DEPRECATED + OP_SYMBOL, // !GEN DEPRECATED + OP_SRANGE, // !GEN DEPRECATED + OP_JUMP_PRI, // !GEN OP_SWITCH, OP_CASETBL, OP_SWAP_PRI, //DONE @@ -194,7 +194,7 @@ typedef enum OP_PUSH_ADR, //DONE OP_NOP, //DONE OP_SYSREQ_N, - OP_SYMTAG, //DEPRECATED + OP_SYMTAG, // !GEN DEPRECATED OP_BREAK, //DONE OP_PUSH2_C, //DONE OP_PUSH2, //DONE @@ -217,8 +217,8 @@ typedef enum OP_CONST, //DONE OP_CONST_S, //DONE /* ----- */ - OP_SYSREQ_D, //UNSUPPORTED - OP_SYSREQ_ND, //UNSUPPORTED + OP_SYSREQ_D, // !GEN UNSUPPORT + OP_SYSREQ_ND, // !GEN UNSUPPORT /* ----- */ OP_HEAP_PRI, //DONE OP_PUSH_HEAP_C, //DONE diff --git a/sourcepawn/vm/jit/x86/opcode_switch.inc b/sourcepawn/vm/jit/x86/opcode_switch.inc index e34bfb93..4ea20788 100644 --- a/sourcepawn/vm/jit/x86/opcode_switch.inc +++ b/sourcepawn/vm/jit/x86/opcode_switch.inc @@ -158,13 +158,6 @@ WriteOp_SMul(jit); break; } -#ifdef UNSUPPORTED - case OP_UMUL: - { - WriteOp_UMul(jit); - break; - } -#endif case OP_ADD: { WriteOp_Add(jit); @@ -245,34 +238,6 @@ WriteOp_Neq(jit); break; } -#ifdef UNSUPPORTED - case OP_LESS: - { - WriteOp_Less(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_LEQ: - { - WriteOp_Leq(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_GRTR: - { - WriteOp_Grtr(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_GEQ: - { - WriteOp_Geq(jit); - break; - } -#endif case OP_SLESS: { WriteOp_Sless(jit); @@ -373,34 +338,26 @@ WriteOp_Load_S_Alt(jit); break; } -#ifdef UNSUPPORTED case OP_LREF_PRI: { WriteOp_Lref_Pri(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_LREF_ALT: { WriteOp_Lref_Alt(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_LREF_S_PRI: { WriteOp_Lref_Pri(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_LREF_S_ALT: { WriteOp_Lref_Alt(jit); break; } -#endif case OP_CONST_PRI: { WriteOp_Const_Pri(jit); @@ -446,48 +403,26 @@ WriteOp_Idxaddr(jit); break; } -#ifdef UNSUPPORTED case OP_SREF_PRI: { WriteOp_Sref_Pri(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_SREF_ALT: { WriteOp_Sref_Alt(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_SREF_S_PRI: { WriteOp_Sref_S_Pri(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_SREF_S_ALT: { WriteOp_Sref_S_Alt(jit); break; } -#endif -#ifdef UNSUPPORTED - case OP_ALIGN_PRI: - { - WriteOp_Align_Pri(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_ALIGN_ALT: - { - WriteOp_Align_Alt(jit); - break; - } -#endif case OP_POP_PRI: { WriteOp_Pop_Pri(jit); @@ -588,58 +523,26 @@ WriteOp_Load_I(jit); break; } -#ifdef UNSUPPORTED - case OP_LODB_I: - { - WriteOp_Lodb_I(jit); - break; - } -#endif case OP_STOR_I: { WriteOp_Stor_I(jit); break; } -#ifdef UNSUPPORTED - case OP_STRB_I: - { - WriteOp_Strb_I(jit); - break; - } -#endif case OP_LIDX: { WriteOp_Lidx(jit); break; } -#ifdef UNSUPPORTED case OP_LIDX_B: { WriteOp_Lidx_B(jit); break; } -#endif -#ifdef UNSUPPORTED case OP_IDXADDR_B: { WriteOp_Idxaddr_B(jit); break; } -#endif -#ifdef UNSUPPORTED - case OP_LCTRL: - { - WriteOp_Lctrl(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_SCTRL: - { - WriteOp_Sctrl(jit); - break; - } -#endif case OP_STACK: { WriteOp_Stack(jit); @@ -660,39 +563,11 @@ WriteOp_SDiv_Alt(jit); break; } -#ifdef UNSUPPORTED - case OP_UDIV: - { - WriteOp_UDiv(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_UDIV_ALT: - { - WriteOp_UDiv_Alt(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_RET: - { - WriteOp_Ret(jit); - break; - } -#endif case OP_RETN: { WriteOp_Retn(jit); break; } -#ifdef UNSUPPORTED - case OP_CMPS: - { - WriteOp_Cmps(jit); - break; - } -#endif case OP_BOUNDS: { WriteOp_Bounds(jit); @@ -708,13 +583,6 @@ WriteOp_Break(jit); break; } -#ifdef UNSUPPORTED - case OP_JREL: - { - WriteOp_JRel(jit); - break; - } -#endif case OP_JUMP: { WriteOp_Jump(jit); @@ -740,34 +608,6 @@ WriteOp_Jneq(jit); break; } -#ifdef UNSUPPORTED - case OP_JLESS: - { - WriteOp_Jless(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_JLEQ: - { - WriteOp_Jeq(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_JGRTR: - { - WriteOp_Jgrtr(jit); - break; - } -#endif -#ifdef UNSUPPORTED - case OP_JGEQ: - { - WriteOp_Jgeq(jit); - break; - } -#endif case OP_JSLESS: { WriteOp_Jsless(jit); @@ -778,6 +618,9 @@ WriteOp_Jsleq(jit); break; } +#if defined USE_UNGEN_OPCODES + #include "ungen_opcode_switch.inc" +#endif default: { assert(0); diff --git a/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc b/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc new file mode 100644 index 00000000..0f9ba552 --- /dev/null +++ b/sourcepawn/vm/jit/x86/ungen_opcode_switch.inc @@ -0,0 +1,100 @@ + case OP_UMUL: + { + WriteOp_UMul(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_ALIGN_PRI: + { + WriteOp_Align_Pri(jit); + break; + } + case OP_ALIGN_ALT: + { + WriteOp_Align_Alt(jit); + break; + } + case OP_LODB_I: + { + WriteOp_Lodb_I(jit); + break; + } + case OP_STRB_I: + { + WriteOp_Strb_I(jit); + break; + } + case OP_LCTRL: + { + WriteOp_Lctrl(jit); + break; + } + case OP_SCTRL: + { + WriteOp_Sctrl(jit); + break; + } + case OP_UDIV: + { + WriteOp_UDiv(jit); + break; + } + case OP_UDIV_ALT: + { + WriteOp_UDiv_Alt(jit); + break; + } + case OP_RET: + { + WriteOp_Ret(jit); + break; + } + case OP_CMPS: + { + WriteOp_Cmps(jit); + break; + } + case OP_JREL: + { + WriteOp_JRel(jit); + break; + } + case OP_JLESS: + { + WriteOp_Jless(jit); + break; + } + case OP_JLEQ: + { + WriteOp_Jeq(jit); + break; + } + case OP_JGRTR: + { + WriteOp_Jgrtr(jit); + break; + } + case OP_JGEQ: + { + WriteOp_Jgeq(jit); + break; + } \ No newline at end of file diff --git a/sourcepawn/vm/jit/x86/ungen_opcodes.h b/sourcepawn/vm/jit/x86/ungen_opcodes.h new file mode 100644 index 00000000..3072db28 --- /dev/null +++ b/sourcepawn/vm/jit/x86/ungen_opcodes.h @@ -0,0 +1,336 @@ +#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ +#define _INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ + +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_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_Align_Pri(JitWriter *jit) +{ + //xor eax, <cellsize - val> + 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, <cellsize - val> + 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_Cmps(JitWriter *jit) +{ + //push edi + //push esi + //lea esi, [edi+edx] + //lea edi, [edi+eax] + IA32_Push_Reg(jit, REG_EDI); + IA32_Push_Reg(jit, REG_ESI); + IA32_Lea_Reg_DispRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE); + IA32_Lea_Reg_DispRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE); + + //xor eax, eax + //repe cmpsb + //je :cmps1 + IA32_Xor_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); + IA32_Cmpsb(jit); + jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0); + + //sbb eax, eax + //sbb eax, -1 + IA32_Sbb_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); + IA32_Sbb_Eax_Imm32(jit, -1);//:TODO: use imm8 here + + //:cmps1 + //pop esi + //pop edi + IA32_Send_Jump8_Here(jit, jmp); + IA32_Pop_Reg(jit, REG_ESI); + IA32_Pop_Reg(jit, REG_EDI); +} + +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, <bitmask> + cell_t val = jit->read_cell(); + switch(val) + { + case 1: + { + IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);//:TODO: replace with AND EAX, imm32 + break; + } + case 2: + { + IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);//:TODO: replace with AND EAX, imm32 + break; + } + } +} + +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 4: + { + IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI); + break; + } + } +} + +inline void WriteOp_Lctrl(JitWriter *jit) +{ + cell_t val = jit->read_cell(); + switch (val) + { + case 0: + { + //mov ecx, [esi+ctx] + //mov eax, [ecx+<offs>] + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, 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, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, 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 //:TODO: use LEA here!!! + 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_UDiv(JitWriter *jit) +{ + //mov ecx, edx + //xor edx, edx + //div ecx + IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); + IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); + Write_Check_DivZero(jit, AMX_REG_TMP); + IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); +} + +inline void WriteOp_UDiv_Alt(JitWriter *jit) +{ + //mov ecx, eax + //mov eax, edx + //xor edx, edx + //div ecx + IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); + IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); + Write_Check_DivZero(jit, AMX_REG_TMP); + IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); +} + +inline void WriteOp_Ret(JitWriter *jit) +{ + //mov ebx, [ebp] - get old FRM + //add ebp, 4 - pop stack + //mov [esi+frm], ebx - restore + //add ebx, edi - relocate + //ret + IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG); + IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong! + IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG); + IA32_Return(jit); +} + +inline void WriteOp_JRel(JitWriter *jit) +{ + //jmp <offs> ;relative jump + cell_t cip_offs = jit->read_cell(); + + /* Note that since code size calculation has to be done in the same + * phase as building relocation information, we cannot know the jump size + * beforehand. Thus, we always write full 32bit jumps for safety. + */ + jitoffs_t jmp = IA32_Jump_Imm32(jit, 0); + IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs)); +} + +inline void WriteOp_Jless(JitWriter *jit) +{ + //cmp eax, edx + //jb <target> + cell_t target = jit->read_cell(); + IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false)); +} + +inline void WriteOp_Jleq(JitWriter *jit) +{ + //cmp eax, edx + //jbe <target> + cell_t target = jit->read_cell(); + IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false)); +} + +inline void WriteOp_Jgrtr(JitWriter *jit) +{ + //cmp eax, edx + //ja <target> + cell_t target = jit->read_cell(); + IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false)); +} + +inline void WriteOp_Jgeq(JitWriter *jit) +{ + //cmp eax, edx + //jae <target> + cell_t target = jit->read_cell(); + IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false)); +} + +#endif //_INCLUDE_SOURCEPAWN_JIT_X86_UNGEN_OPCODES_H_ diff --git a/sourcepawn/vm/sp_vm_engine.cpp b/sourcepawn/vm/sp_vm_engine.cpp index 5bae6220..fa3d2a79 100644 --- a/sourcepawn/vm/sp_vm_engine.cpp +++ b/sourcepawn/vm/sp_vm_engine.cpp @@ -6,8 +6,39 @@ #include "zlib/zlib.h" #include "sp_vm_basecontext.h" +#if defined WIN32 + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#else if defined __GNUC__ + #include <sys/mman.h> +#endif + using namespace SourcePawn; +void *SourcePawnEngine::ExecAlloc(size_t size) +{ +#if defined WIN32 + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else if defined __GNUC__ + void *base = memalign(sysconf(_SC_PAGESIZE), size); + if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) + { + free(base); + return NULL; + } + return base; +#endif +} + +void SourcePawnEngine::ExecFree(void *address) +{ +#if defined WIN32 + VirtualFree(address, 0, MEM_RELEASE); +#else if defined __GNUC__ + free(address); +#endif +} + void *SourcePawnEngine::BaseAlloc(size_t size) { return malloc(size); @@ -28,7 +59,7 @@ void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx) sp_context_t *_ctx = ctx->GetContext(); IVirtualMachine *vm = ctx->GetVirtualMachine(); - vm->FreeContextVars(_ctx); + vm->FreeContext(_ctx); delete ctx; } diff --git a/sourcepawn/vm/sp_vm_engine.h b/sourcepawn/vm/sp_vm_engine.h index 13b18557..66b38e6c 100644 --- a/sourcepawn/vm/sp_vm_engine.h +++ b/sourcepawn/vm/sp_vm_engine.h @@ -67,6 +67,22 @@ namespace SourcePawn * @param mem Memory address to free. */ void BaseFree(void *memory); + + + /** + * Allocates executable memory. + * + * @param size Size of memory to allocate. + * @return Pointer to memory, NULL if allocation failed. + */ + void *ExecAlloc(size_t size); + + /** + * Frees executable memory. + * + * @param mem Address to free. + */ + void ExecFree(void *address); }; };