From fb7942ee4dc2bc6792071e9ed39781bd2cddbe6d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 11 Oct 2006 23:47:04 +0000 Subject: [PATCH] and you thought you'd never see the day.. sysreq.n verified! --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40117 --- sourcepawn/vm/jit/x86/jit_x86.cpp | 198 ++++++++++---------- sourcepawn/vm/jit/x86/jit_x86.h | 4 +- sourcepawn/vm/jit/x86/opcode_helpers.cpp | 219 +++-------------------- sourcepawn/vm/jit/x86/opcode_helpers.h | 8 +- sourcepawn/vm/jit/x86/opcode_switch.inc | 16 +- sourcepawn/vm/jit/x86/x86_macros.h | 16 ++ sourcepawn/vm/sp_vm_basecontext.cpp | 1 + 7 files changed, 162 insertions(+), 300 deletions(-) diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index 1a4d763c..5ef91c9d 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -60,9 +60,11 @@ inline void WriteOp_Zero(JitWriter *jit) //mov [ebp+], 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 + } else { IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val); + } } inline void WriteOp_Zero_S(JitWriter *jit) @@ -70,9 +72,11 @@ 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 + } else { IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val); + } } inline void WriteOp_Push_S(JitWriter *jit) @@ -85,9 +89,11 @@ inline void WriteOp_Push_S(JitWriter *jit) 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 + } 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); } @@ -1406,8 +1412,14 @@ inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit) /* store the number of parameters on the stack, * and store the native index as well. */ - cell_t num_params = jit->read_cell(); cell_t native_index = jit->read_cell(); + cell_t num_params = jit->read_cell(); + + if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num) + { + ((CompData *)jit->data)->error_set = SP_ERR_INSTRUCTION_PARAM; + return; + } //mov eax, //mov ecx, @@ -1421,10 +1433,16 @@ inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit) inline void WriteOp_Sysreq_N(JitWriter *jit) { /* The big daddy of opcodes. */ - cell_t num_params = jit->read_cell(); cell_t native_index = jit->read_cell(); + cell_t num_params = jit->read_cell(); CompData *data = (CompData *)jit->data; + if ((uint32_t)native_index >= data->plugin->info.natives_num) + { + data->error_set = SP_ERR_INSTRUCTION_PARAM; + return; + } + /* store the number of parameters on the stack */ //mov [edi-4], num_params //sub edi, 4 @@ -1463,7 +1481,15 @@ inline void WriteOp_Sysreq_N(JitWriter *jit) //call NativeCallback IA32_Push_Reg(jit, REG_EAX); jitoffs_t call = IA32_Call_Imm32(jit, 0); - IA32_Write_Jump32(jit, call, (jitoffs_t)(char *)&NativeCallback); + IA32_Write_Jump32_Abs(jit, call, NativeCallback); + + /* check for errors */ + //mov ecx, [esi+context] + //cmp [ecx+err], 0 + //jnz :error + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, err), 0); + IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error); /* restore what we damaged */ //add esp, 4*3 @@ -1473,12 +1499,6 @@ inline void WriteOp_Sysreq_N(JitWriter *jit) IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); IA32_Pop_Reg(jit, AMX_REG_ALT); - /* check for errors */ - //test eax, eax - //jne :error - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); - IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, data->jit_return); - /* pop the stack. do not check the margins. * Note that this is not a true macro - we don't bother to * set ALT here because nothing will be using it. @@ -1503,9 +1523,16 @@ inline void WriteOp_Sysreq_N(JitWriter *jit) cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) { - /* :TODO: fill this out... */ + sp_native_t *native = &ctx->natives[native_idx]; + + /* Technically both aren't needed, I guess */ + if (native->status == SP_NATIVE_NONE) + { + ctx->err = SP_ERR_NATIVE_PENDING; + return 0; + } - return 0; + return native->pfn(ctx, params); } jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) @@ -1529,6 +1556,33 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) } } +void WriteErrorRoutines(CompData *data, JitWriter *jit) +{ + data->jit_error_divzero = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_DIVIDE_BY_ZERO); + + data->jit_error_stacklow = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_STACKLOW); + + data->jit_error_stackmin = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_STACKMIN); + + data->jit_error_bounds = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_ARRAY_BOUNDS); + + data->jit_error_memaccess = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_MEMACCESS); + + data->jit_error_heaplow = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_HEAPLOW); + + data->jit_error_heapmin = jit->get_outputpos(); + Write_SetError(jit, SP_ERR_HEAPMIN); + + data->jit_extern_error = jit->get_outputpos(); + Write_GetError(jit); +} + sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err) { CompData *data = (CompData *)co; @@ -1536,61 +1590,17 @@ sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err) /* 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; - - /* FIRST PASS (light load) - Get initial opcode information - * :TODO: remove this pass soon, it's not needed anymore! - */ - 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 == -1) { - switch (op) - { - case OP_CASETBL: - { - ucell_t num = *(ucell_t *)cip; - cip += sizeof(cell_t); - 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 + * FIRST PASS (medium load): writer.outbase is NULL, getting size only + * SECOND PASS (heavy load!!): writer.outbase is valid and output is written *********************************************/ JitWriter writer; JitWriter *jit = &writer; cell_t *endptr = (cell_t *)(end_cip); - cell_t jitpos; /* Initial code is written "blank," * so we can check the exact memory usage. @@ -1602,58 +1612,37 @@ sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err) writer.outbase = NULL; data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size); - /* Jump back here for second pass */ + /* We will jump back here for second pass */ jit_rewind: /* Initialize pass vars */ writer.inptr = writer.inbase; data->jit_verify_addr_eax = 0; data->jit_verify_addr_edx = 0; - /* Start writing the actual code */ + /* Write the prologue of the JIT */ data->jit_return = Write_Execute_Function(jit); - /* Write error checking routines that are jumped to */ - if (!(data->inline_level & JIT_INLINE_ERRORCHECKS)) + /* Write the SYSREQ.N opcode if we need to */ + if (!(data->inline_level & JIT_INLINE_NATIVES)) { - jitpos = jit->get_outputpos(); - Write_Check_VerifyAddr(jit, REG_EAX); - data->jit_verify_addr_eax = jitpos; - - jitpos = jit->get_outputpos(); - Write_Check_VerifyAddr(jit, REG_EDX); - data->jit_verify_addr_edx = jitpos; + data->jit_sysreq_n = jit->get_outputpos(); + WriteOp_Sysreq_N_Function(jit); } - /* Write error codes we need */ + /* Write error checking routines that are called to */ + if (!(data->inline_level & JIT_INLINE_ERRORCHECKS)) { - data->jit_error_divzero = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_DIVIDE_BY_ZERO); + data->jit_verify_addr_eax = jit->get_outputpos(); + Write_Check_VerifyAddr(jit, REG_EAX); - data->jit_error_stacklow = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_STACKLOW); - - data->jit_error_stackmin = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_STACKMIN); - - data->jit_error_bounds = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_ARRAY_BOUNDS); - - data->jit_error_memaccess = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_MEMACCESS); - - data->jit_error_heaplow = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_HEAPLOW); - - data->jit_error_heapmin = jit->get_outputpos(); - Write_SetError(jit, true, SP_ERR_HEAPMIN); + data->jit_verify_addr_edx = jit->get_outputpos(); + Write_Check_VerifyAddr(jit, REG_EDX); } /* Actual code generation! */ if (writer.outbase == NULL) { - /******* - * SECOND PASS - get opcode sizes+info - *******/ + /* First Pass - find codesize and resolve relocation */ jitoffs_t pcode_offs; jitoffs_t native_offs; @@ -1673,7 +1662,16 @@ jit_rewind: { #include "opcode_switch.inc" } + /* Check for errors. This should only happen in the first pass. */ + if (data->error_set != SP_ERR_NONE) + { + *err = data->error_set; + AbortCompilation(co); + return NULL; + } } + /* Write these last because error jumps should be unpredicted, and thus forward */ + WriteErrorRoutines(data, jit); /* the total codesize is now known! */ uint32_t mem = writer.get_outputpos(); @@ -1693,6 +1691,8 @@ jit_rewind: #include "opcode_switch.inc" } } + /* Write these last because error jumps should be unpredicted, and thus forward */ + WriteErrorRoutines(data, jit); } /************* @@ -1810,8 +1810,7 @@ jit_rewind: } /* clean up relocation+compilation memory */ - engine->BaseFree(data->rebase); - delete data; + AbortCompilation(co); *err = SP_ERR_NONE; @@ -1848,13 +1847,18 @@ ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin) CompData *data = new CompData; data->plugin = plugin; - data->inline_level = JIT_INLINE_ERRORCHECKS; + data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES; + data->error_set = SP_ERR_NONE; return data; } void JITX86::AbortCompilation(ICompilation *co) { + if (((CompData *)co)->rebase) + { + engine->BaseFree(((CompData *)co)->rebase); + } delete (CompData *)co; } diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h index cf720dc3..49198999 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.h +++ b/sourcepawn/vm/jit/x86/jit_x86.h @@ -33,15 +33,15 @@ public: jitoffs_t jit_error_memaccess; jitoffs_t jit_error_heaplow; jitoffs_t jit_error_heapmin; + jitoffs_t jit_extern_error; uint32_t codesize; int inline_level; + int error_set; bool debug; }; class JITX86 : public IVirtualMachine { -public: - JITX86(); public: const char *GetVMName(); ICompilation *StartCompilation(sp_plugin_t *plugin); diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index a02032a3..92cea6e1 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -4,8 +4,6 @@ #include "opcode_helpers.h" #include "x86_macros.h" -int OpAdvTable[OP_NUM_OPCODES]; - #define NUM_INFO_PARAMS 7 jitoffs_t Write_Execute_Function(JitWriter *jit) @@ -165,16 +163,26 @@ void Write_BreakDebug(JitWriter *jit) IA32_Return(jit); } -void Write_SetError(JitWriter *jit, bool always_inline, int error) +void Write_GetError(JitWriter *jit) +{ + CompData *data = (CompData *)jit->data; + + //mov eax, [esi+info.context] + //mov eax, [eax+ctx.error] + //jmp [jit_return] + IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EAX, offsetof(sp_context_t, err)); + IA32_Jump_Imm32_Abs(jit, data->jit_return); +} + +void Write_SetError(JitWriter *jit, int error) { CompData *data = (CompData *)jit->data; - /* These are so small that we always inline them! */ //mov eax, - //jmp [...jit_return] + //jmp [jit_return] IA32_Mov_Reg_Imm32(jit, REG_EAX, error); - jitoffs_t jmp = IA32_Jump_Imm32(jit, 0); - IA32_Write_Jump32(jit, jmp, data->jit_return); + IA32_Jump_Imm32_Abs(jit, data->jit_return); } void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg) @@ -426,11 +434,18 @@ void WriteOp_Sysreq_N_Function(JitWriter *jit) /* finally, push the last parameter and make the call */ //push eax ; context - //mov eax, [eax+context] //call NativeCallback IA32_Push_Reg(jit, REG_EAX); jitoffs_t call = IA32_Call_Imm32(jit, 0); - IA32_Write_Jump32(jit, call, (jitoffs_t)(char *)&NativeCallback); + IA32_Write_Jump32_Abs(jit, call, (void *)&NativeCallback); + + /* Test for error */ + //mov ecx, [esi+context] + //cmp [ecx+err], 0 + //jnz :error + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, err), 0); + IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error); /* restore what we damaged */ //add esp, 4*3 @@ -442,12 +457,6 @@ void WriteOp_Sysreq_N_Function(JitWriter *jit) IA32_Pop_Reg(jit, AMX_REG_ALT); IA32_Pop_Reg(jit, REG_ECX); - //Note: always safe, we're in a call - //test eax, eax - //jne :error - IA32_Test_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG); - IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, data->jit_return); - /* pop the AMX stack. do not check the margins. * Note that this is not a true macro - we don't bother to * set ALT here because nothing will be using it. @@ -459,183 +468,3 @@ void WriteOp_Sysreq_N_Function(JitWriter *jit) IA32_Return(jit); } -JITX86::JITX86() -{ - memset(OpAdvTable, -1, sizeof(OpAdvTable)); - - /* instructions with 5 parameters */ - OpAdvTable[OP_PUSH5_C] = sizeof(cell_t)*5; - OpAdvTable[OP_PUSH5] = sizeof(cell_t)*5; - OpAdvTable[OP_PUSH5_S] = sizeof(cell_t)*5; - OpAdvTable[OP_PUSH5_ADR] = sizeof(cell_t)*5; - - /* instructions with 4 parameters */ - OpAdvTable[OP_PUSH4_C] = sizeof(cell_t)*4; - OpAdvTable[OP_PUSH4] = sizeof(cell_t)*4; - OpAdvTable[OP_PUSH4_S] = sizeof(cell_t)*4; - OpAdvTable[OP_PUSH4_ADR] = sizeof(cell_t)*4; - - /* instructions with 3 parameters */ - OpAdvTable[OP_PUSH3_C] = sizeof(cell_t)*3; - OpAdvTable[OP_PUSH3] = sizeof(cell_t)*3; - OpAdvTable[OP_PUSH3_S] = sizeof(cell_t)*3; - OpAdvTable[OP_PUSH3_ADR] = sizeof(cell_t)*3; - - /* instructions with 2 parameters */ - OpAdvTable[OP_PUSH2_C] = sizeof(cell_t)*2; - OpAdvTable[OP_PUSH2] = sizeof(cell_t)*2; - OpAdvTable[OP_PUSH2_S] = sizeof(cell_t)*2; - OpAdvTable[OP_PUSH2_ADR] = sizeof(cell_t)*2; - OpAdvTable[OP_LOAD_BOTH] = sizeof(cell_t)*2; - OpAdvTable[OP_LOAD_S_BOTH] = sizeof(cell_t)*2; - OpAdvTable[OP_CONST] = sizeof(cell_t)*2; - OpAdvTable[OP_CONST_S] = sizeof(cell_t)*2; - OpAdvTable[OP_SYSREQ_N] = sizeof(cell_t)*2; - - /* instructions with 1 parameter */ - OpAdvTable[OP_LOAD_PRI] = sizeof(cell_t); - OpAdvTable[OP_LOAD_ALT] = sizeof(cell_t); - OpAdvTable[OP_LOAD_S_PRI] = sizeof(cell_t); - OpAdvTable[OP_LOAD_S_ALT] = sizeof(cell_t); - OpAdvTable[OP_LREF_PRI] = sizeof(cell_t); - 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_CONST_PRI] = sizeof(cell_t); - OpAdvTable[OP_CONST_ALT] = sizeof(cell_t); - OpAdvTable[OP_ADDR_PRI] = sizeof(cell_t); - OpAdvTable[OP_ADDR_ALT] = sizeof(cell_t); - OpAdvTable[OP_STOR_PRI] = sizeof(cell_t); - OpAdvTable[OP_STOR_ALT] = sizeof(cell_t); - OpAdvTable[OP_STOR_S_PRI] = sizeof(cell_t); - OpAdvTable[OP_STOR_S_ALT] = sizeof(cell_t); - OpAdvTable[OP_SREF_PRI] = sizeof(cell_t); - 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_LIDX_B] = sizeof(cell_t); - OpAdvTable[OP_IDXADDR_B] = 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_SHL_C_PRI] = sizeof(cell_t); - OpAdvTable[OP_SHL_C_ALT] = sizeof(cell_t); - OpAdvTable[OP_SHR_C_PRI] = sizeof(cell_t); - OpAdvTable[OP_SHR_C_ALT] = sizeof(cell_t); - OpAdvTable[OP_ADD_C] = sizeof(cell_t); - OpAdvTable[OP_SMUL_C] = sizeof(cell_t); - OpAdvTable[OP_ZERO] = sizeof(cell_t); - OpAdvTable[OP_ZERO_S] = sizeof(cell_t); - OpAdvTable[OP_EQ_C_PRI] = sizeof(cell_t); - OpAdvTable[OP_EQ_C_ALT] = sizeof(cell_t); - OpAdvTable[OP_INC] = sizeof(cell_t); - OpAdvTable[OP_INC_S] = sizeof(cell_t); - OpAdvTable[OP_DEC] = sizeof(cell_t); - OpAdvTable[OP_DEC_S] = sizeof(cell_t); - OpAdvTable[OP_MOVS] = sizeof(cell_t); - OpAdvTable[OP_FILL] = sizeof(cell_t); - OpAdvTable[OP_HALT] = sizeof(cell_t); - OpAdvTable[OP_BOUNDS] = sizeof(cell_t); - OpAdvTable[OP_PUSH_ADR] = sizeof(cell_t); - OpAdvTable[OP_PUSH_HEAP_C] = sizeof(cell_t); - OpAdvTable[OP_SYSREQ_C] = sizeof(cell_t); - OpAdvTable[OP_CALL] = sizeof(cell_t); - OpAdvTable[OP_JUMP] = sizeof(cell_t); - OpAdvTable[OP_JZER] = sizeof(cell_t); - OpAdvTable[OP_JNZ] = sizeof(cell_t); - OpAdvTable[OP_JEQ] = sizeof(cell_t); - OpAdvTable[OP_JNEQ] = sizeof(cell_t); - OpAdvTable[OP_JSLESS] = sizeof(cell_t); - OpAdvTable[OP_JSLEQ] = sizeof(cell_t); - OpAdvTable[OP_JSGRTR] = sizeof(cell_t); - OpAdvTable[OP_JSGEQ] = sizeof(cell_t); - OpAdvTable[OP_SWITCH] = sizeof(cell_t); - - /* instructions with 0 parameters */ - OpAdvTable[OP_LOAD_I] = 0; - OpAdvTable[OP_STOR_I] = 0; - OpAdvTable[OP_LIDX] = 0; - OpAdvTable[OP_IDXADDR] = 0; - OpAdvTable[OP_MOVE_PRI] = 0; - OpAdvTable[OP_MOVE_ALT] = 0; - OpAdvTable[OP_XCHG] = 0; - OpAdvTable[OP_PUSH_PRI] = 0; - OpAdvTable[OP_PUSH_ALT] = 0; - OpAdvTable[OP_POP_PRI] = 0; - OpAdvTable[OP_POP_ALT] = 0; - OpAdvTable[OP_PROC] = 0; - OpAdvTable[OP_RET] = 0; - OpAdvTable[OP_RETN] = 0; - OpAdvTable[OP_CALL_PRI] = 0; - OpAdvTable[OP_SHL] = 0; - OpAdvTable[OP_SHR] = 0; - OpAdvTable[OP_SSHR] = 0; - OpAdvTable[OP_SMUL] = 0; - OpAdvTable[OP_SDIV] = 0; - OpAdvTable[OP_SDIV_ALT] = 0; - OpAdvTable[OP_ADD] = 0; - OpAdvTable[OP_SUB] = 0; - OpAdvTable[OP_SUB_ALT] = 0; - OpAdvTable[OP_AND] = 0; - OpAdvTable[OP_OR] = 0; - OpAdvTable[OP_XOR] = 0; - OpAdvTable[OP_NOT] = 0; - OpAdvTable[OP_NEG] = 0; - OpAdvTable[OP_INVERT] = 0; - OpAdvTable[OP_ZERO_PRI] = 0; - OpAdvTable[OP_ZERO_ALT] = 0; - OpAdvTable[OP_SIGN_PRI] = 0; - OpAdvTable[OP_SIGN_ALT] = 0; - OpAdvTable[OP_EQ] = 0; - OpAdvTable[OP_NEQ] = 0; - OpAdvTable[OP_SLESS] = 0; - OpAdvTable[OP_SLEQ] = 0; - OpAdvTable[OP_SGRTR] = 0; - OpAdvTable[OP_SGEQ] = 0; - OpAdvTable[OP_INC_PRI] = 0; - OpAdvTable[OP_INC_ALT] = 0; - OpAdvTable[OP_INC_I] = 0; - OpAdvTable[OP_DEC_PRI] = 0; - OpAdvTable[OP_DEC_ALT] = 0; - OpAdvTable[OP_DEC_I] = 0; - OpAdvTable[OP_JUMP_PRI] = 0; - OpAdvTable[OP_SWAP_PRI] = 0; - OpAdvTable[OP_SWAP_ALT] = 0; - OpAdvTable[OP_NOP] = 0; - OpAdvTable[OP_BREAK] = 0; - OpAdvTable[OP_HEAP_PRI] = 0; - OpAdvTable[OP_POP_HEAP_PRI] = 0; - OpAdvTable[OP_SYSREQ_PRI] = 0; - - /* 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; - OpAdvTable[OP_SRANGE] = -3; - OpAdvTable[OP_SYMTAG] = -3; - 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 b1c600ac..9859bd4a 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.h +++ b/sourcepawn/vm/jit/x86/opcode_helpers.h @@ -18,8 +18,10 @@ void WriteOp_Sysreq_N_Function(JitWriter *jit); /** * Generates code to set an error state in the VM and return. * This is used for generating the error set points in the VM. + * GetError writes the error from the context. SetError hardcodes. */ -void Write_SetError(JitWriter *jit, bool always_inline, int error); +void Write_GetError(JitWriter *jit); +void Write_SetError(JitWriter *jit, int error); /** * Checks the stacks for min and low errors. @@ -210,7 +212,7 @@ typedef enum OP_SWAP_ALT, //~VERIFIED (swap.alt) OP_PUSH_ADR, //VERIFIED OP_NOP, //VERIFIED (lol) - OP_SYSREQ_N, + OP_SYSREQ_N, //VERIFIED OP_SYMTAG, // !GEN DEPRECATED OP_BREAK, //DONE OP_PUSH2_C, //~VERIFIED (push3.c) @@ -244,6 +246,4 @@ typedef enum OP_NUM_OPCODES } OPCODE; -extern int OpAdvTable[]; - #endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODE_INFO_H_ diff --git a/sourcepawn/vm/jit/x86/opcode_switch.inc b/sourcepawn/vm/jit/x86/opcode_switch.inc index fde04a9d..759fbe1b 100644 --- a/sourcepawn/vm/jit/x86/opcode_switch.inc +++ b/sourcepawn/vm/jit/x86/opcode_switch.inc @@ -643,10 +643,22 @@ WriteOp_Call(jit); break; } + case OP_SYSREQ_N: + { + if (data->inline_level & JIT_INLINE_NATIVES) + { + WriteOp_Sysreq_N(jit); + } else { + WriteOp_Sysreq_N_NoInline(jit); + } + break; + } #if defined USE_UNGEN_OPCODES #include "ungen_opcode_switch.inc" #endif default: { - assert(0); - } \ No newline at end of file + data->error_set = SP_ERR_INVALID_INSTRUCTION; + break; + } + \ No newline at end of file diff --git a/sourcepawn/vm/jit/x86/x86_macros.h b/sourcepawn/vm/jit/x86/x86_macros.h index 1a8d957d..a742cceb 100644 --- a/sourcepawn/vm/jit/x86/x86_macros.h +++ b/sourcepawn/vm/jit/x86/x86_macros.h @@ -899,6 +899,22 @@ inline void IA32_Write_Jump32(JitWriter *jit, jitoffs_t jmp, jitoffs_t target) jit->outptr = oldptr; } +/** + * Corrects a jump using an absolute offset, not a relative one. + */ +inline void IA32_Write_Jump32_Abs(JitWriter *jit, jitoffs_t jmp, void *target) +{ + //save old ptr + jitcode_t oldptr = jit->outptr; + //get relative difference + long diff = ((long)target - ((long)jit->outbase + jmp + 4)); + //overwrite old value + jit->outptr = jit->outbase + jmp; + jit->write_int32(diff); + //restore old ptr + jit->outptr = oldptr; +} + /* For writing and auto-calculating an absolute target */ inline void IA32_Jump_Imm32_Abs(JitWriter *jit, jitoffs_t target) { diff --git a/sourcepawn/vm/sp_vm_basecontext.cpp b/sourcepawn/vm/sp_vm_basecontext.cpp index ef932a3d..718f230b 100644 --- a/sourcepawn/vm/sp_vm_basecontext.cpp +++ b/sourcepawn/vm/sp_vm_basecontext.cpp @@ -12,6 +12,7 @@ using namespace SourcePawn; BaseContext::BaseContext(sp_context_t *_ctx) { ctx = _ctx; + ctx->context = this; } IVirtualMachine *BaseContext::GetVirtualMachine()