diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index 9a0f540c..7eea2026 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -1087,21 +1087,14 @@ inline void WriteOp_Lidx(JitWriter *jit) inline void WriteOp_Stack(JitWriter *jit) { - /* :TODO: Find an instance in the compiler where - * the ALT value from STACK is actually used! - */ - //mov edx, edi //add edi, - //sub edx, ebp cell_t val = jit->read_cell(); - IA32_Mov_Reg_Rm(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_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG); if (val > 0) { @@ -1674,6 +1667,9 @@ void WriteErrorRoutines(CompData *data, JitWriter *jit) data->jit_error_heapmin = jit->get_outputpos(); Write_SetError(jit, SP_ERROR_HEAPMIN); + data->jit_error_array_too_big = jit->get_outputpos(); + Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG); + data->jit_extern_error = jit->get_outputpos(); Write_GetError(jit); } @@ -1728,6 +1724,9 @@ jit_rewind: data->jit_sysreq_c = jit->get_outputpos(); WriteOp_Sysreq_C_Function(jit); + data->jit_genarray = jit->get_outputpos(); + WriteIntrinsic_GenArray(jit); + /* Write error checking routines that are called to */ if (!(data->inline_level & JIT_INLINE_ERRORCHECKS)) { diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h index 88fc895c..223d68ca 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.h +++ b/sourcepawn/vm/jit/x86/jit_x86.h @@ -35,6 +35,7 @@ public: jitoffs_t jit_error_memaccess; jitoffs_t jit_error_heaplow; jitoffs_t jit_error_heapmin; + jitoffs_t jit_error_array_too_big; jitoffs_t jit_extern_error; /* returning generic error */ jitoffs_t jit_sysreq_c; /* old version! */ uint32_t codesize; /* total codesize */ diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index 5263ed52..8e1e3c7f 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -451,8 +451,141 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit) IA32_Return(jit); } +void GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], ucell_t dimcount) +{ + cell_t vectors = 1; /* we need one vector to start off with */ + cell_t cur_offs = 0; + cell_t cur_write = 0; + + /* Initialize rotation */ + cur_write = dims[dimcount-1]; + + while (--dimcount >= 1) + { + cell_t cur_dim = dims[dimcount]; + cell_t sub_dim = dims[dimcount-1]; + for (cell_t i=0; iget_outputpos(); + IA32_Cmp_Reg_Rm_ESP(jit, REG_EAX); + jitoffs_t done1 = IA32_Jump_Cond_Imm8(jit, CC_AE, 0); + IA32_Mov_Reg_Rm_Disp_Reg(jit, REG_ECX, AMX_REG_STK, REG_EAX, SCALE4); + IA32_IMul_Reg_Rm(jit, REG_EDX, REG_ECX, MOD_REG); + IA32_Add_Rm_Reg(jit, REG_EDX, REG_ECX, MOD_REG); + IA32_Inc_Reg(jit, REG_EAX); + IA32_Write_Jump8(jit, IA32_Jump_Imm8(jit, loop1), loop1); + IA32_Send_Jump8_Here(jit, done1); + + /* Test if we have heap space for this */ + //mov eax, [esi+info.heap] ;get heap pointer + //lea eax, [eax+edx*4+4] ;new heap pointer + //cmp eax, ;compare to heap low + //jbe :error ;die if we hit this (it should always be >) + //add eax, ebp ;relocate to stack + //cmp eax, edi ;die if above the stack pointer + //jae :error + IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP); + IA32_Lea_Reg_DispRegMultImm8(jit, REG_EAX, REG_EAX, REG_EDX, SCALE4, 4); + IA32_Cmp_Rm_Imm32(jit, MOD_REG, REG_EAX, ((CompData *)jit->data)->plugin->data_size); + IA32_Jump_Cond_Imm32_Abs(jit, CC_BE, ((CompData *)jit->data)->jit_error_array_too_big); + IA32_Add_Rm_Reg(jit, REG_EAX, AMX_REG_DAT, MOD_REG); + IA32_Cmp_Reg_Rm(jit, REG_EAX, AMX_REG_STK, MOD_REG); + IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_array_too_big); + + /* Prepare for indirection iteration */ + //mov eax, [esi+info.heap] ;get heap pointer + //lea ebx, [eax+edx*4+4] ;new heap pointer + //mov [esi+info.heap], ebx ;store back + //lea ebx, [ebp+ebx-4] ;relocate + //mov [ebx], edx ;store back total size + //push eax ;save heap pointer - we need it + IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_HEAP); + IA32_Lea_Reg_DispRegMultImm8(jit, REG_EBX, REG_EAX, REG_EDX, SCALE4, 4); + IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EBX, AMX_INFO_HEAP); + IA32_Lea_Reg_DispRegMultImm8(jit, REG_EBX, AMX_REG_DAT, REG_EBX, NOSCALE, -4); + IA32_Mov_Rm_Reg(jit, REG_EBX, REG_EDX, MOD_MEM_REG); + IA32_Push_Reg(jit, REG_EAX); + + /* This part is too messy to do in straight assembly. + * I'm letting the compiler handle it and thus it's in C. + */ + //lea ebx, [ebp+eax] ;get base pointer + //push dword [esp-4] ;push dimension count + //push edi ;push dim array + //push ebx + //call GenerateArrayIndirectionVectors + //add esp, 4*3 + IA32_Lea_Reg_DispRegMult(jit, REG_EBX, REG_EAX, REG_EBP, NOSCALE); + IA32_Push_Rm_Disp8_ESP(jit, 4); + IA32_Push_Reg(jit, REG_EDI); + IA32_Push_Reg(jit, REG_EBX); + IA32_Write_Jump32_Abs(jit, IA32_Call_Imm32(jit, 0), (void *)&GenerateArrayIndirectionVectors); + IA32_Add_Rm_Imm8(jit, REG_ESP, 4*3, MOD_REG); + + /* Store the heap pointer back into the stack */ + //pop eax ;restore heap pointer + //pop ecx ;restore param count + //lea edi, [edi+ecx*4-4] ;pop params-4 off the stack + //mov [edi], eax ;store back the heap pointer + IA32_Pop_Reg(jit, REG_EAX); + IA32_Pop_Reg(jit, REG_ECX); + IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, -4); + IA32_Mov_Rm_Reg(jit, AMX_REG_STK, REG_EAX, MOD_MEM_REG); + + /* Return to caller */ + //pop eax + //pop ebx + //ret + IA32_Pop_Reg(jit, REG_EAX); + IA32_Pop_Reg(jit, REG_EBX); + IA32_Return(jit); } void WriteOp_Sysreq_N_Function(JitWriter *jit) diff --git a/sourcepawn/vm/jit/x86/x86_macros.h b/sourcepawn/vm/jit/x86/x86_macros.h index 85c4a1f1..18596535 100644 --- a/sourcepawn/vm/jit/x86/x86_macros.h +++ b/sourcepawn/vm/jit/x86/x86_macros.h @@ -102,10 +102,12 @@ #define IA32_NOT_RM 0xF7 // encoding is /2 #define IA32_DIV_RM 0xF7 // encoding is /6 #define IA32_MUL_RM 0xF7 // encoding is /4 -#define IA32_IMUL_RM 0xF7 // encoding is /5 #define IA32_IDIV_RM 0xF7 // encoding is /7 +#define IA32_IMUL_RM 0xF7 // encoding is /5 #define IA32_IMUL_REG_IMM32 0x69 // encoding is /r #define IA32_IMUL_REG_IMM8 0x6B // encoding is /r +#define IA32_IMUL_REG_RM_1 0x0F // encoding is _2 +#define IA32_IMUL_REG_RM_2 0xAF // encoding is /r #define IA32_SHR_RM_IMM8 0xC1 // encoding is /5 #define IA32_SHL_RM_IMM8 0xC1 // encoding is /4 #define IA32_SAR_RM_CL 0xD3 // encoding is /7 @@ -445,6 +447,13 @@ inline void IA32_IMul_Reg_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mod jit->write_int32(value); } +inline void IA32_IMul_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) +{ + jit->write_ubyte(IA32_IMUL_REG_RM_1); + jit->write_ubyte(IA32_IMUL_REG_RM_2); + jit->write_ubyte(ia32_modrm(mode, dest, src)); +} + inline void IA32_Add_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) { jit->write_ubyte(IA32_ADD_RM_REG); @@ -634,6 +643,14 @@ inline void IA32_Push_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp8 jit->write_byte(disp8); } +inline void IA32_Push_Rm_Disp8_ESP(JitWriter *jit, jit_int8_t disp8) +{ + jit->write_ubyte(IA32_PUSH_RM); + jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, REG_SIB)); + jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); + jit->write_byte(disp8); +} + /** * Moving from REGISTER/MEMORY to REGISTER */ @@ -677,6 +694,19 @@ inline void IA32_Mov_Reg_Rm_Disp_Reg(JitWriter *jit, jit->write_ubyte(ia32_sib(src_scale, src_index, src_base)); } +inline void IA32_Mov_Reg_Rm_Disp_Reg_Disp8(JitWriter *jit, + jit_uint8_t dest, + jit_uint8_t src_base, + jit_uint8_t src_index, + jit_uint8_t src_scale, + jit_int8_t disp8) +{ + jit->write_ubyte(IA32_MOV_REG_MEM); + jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); + jit->write_ubyte(ia32_sib(src_scale, src_index, src_base)); + jit->write_byte(disp8); +} + inline void IA32_Mov_Reg_RmEBP_Disp_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, @@ -968,6 +998,13 @@ inline void IA32_Cmp_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, j jit->write_ubyte(ia32_modrm(mode, dest, src)); } +inline void IA32_Cmp_Reg_Rm_ESP(JitWriter *jit, jit_uint8_t cmpreg) +{ + jit->write_ubyte(IA32_CMP_REG_RM); + jit->write_ubyte(ia32_modrm(MOD_MEM_REG, cmpreg, REG_SIB)); + jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); +} + inline void IA32_Cmp_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_int8_t disp8) { jit->write_ubyte(IA32_CMP_REG_RM);