diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index e969e293..9a0f540c 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -960,15 +960,55 @@ inline void WriteOp_Fill(JitWriter *jit) IA32_Pop_Reg(jit, REG_EDI); } -inline void WriteOp_Heap_Pri(JitWriter *jit) +inline void WriteOp_Heap_I(JitWriter *jit) { - //mov edx, [esi+hea] - //add [esi+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); + //sub [esi+hea], 4 + //mov ecx, [esi+hea] + //mov ecx, [ebp+ecx] + //sub [esi+hea], 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_RmEBP_Disp_Reg(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE); + IA32_Add_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP); - /* :TODO: should we do a full bounds check here? */ Write_CheckHeap_Min(jit); + Write_CheckHeap_Low(jit); +} + +inline void WriteOp_GenArray(JitWriter *jit) +{ + cell_t val = jit->read_cell(); + if (val == 1) + { + /* flat array. we can generate this without indirection tables. */ + /* Note that we can overwrite ALT because technically STACK should be destroying ALT */ + //mov edx, [esi+info.heap] + //mov ecx, [edi] + //mov [edi], edx ;store base of array into stack + //lea edx, [edx+ecx*4+4] ;get the final new heap pointer + //mov [esi+info.heap], edx ;store heap pointer back + //add edx, ebp ;relocate + //cmp edx, edi ;compare against stack pointer + //jae :error ;error out if not enough space + //shl ecx, 2 + //mov [edx-4], ecx ;store # of cells allocated + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP); + IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG); + IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG); + IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4, 4); + IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP); + IA32_Add_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG); + IA32_Cmp_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG); + IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow); + IA32_Shl_Rm_Imm8(jit, AMX_REG_TMP, 4, MOD_REG); + IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_ALT, AMX_REG_TMP, -4); + } else { + //mov ecx, num_dims + //call [genarray] + IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val); + jitoffs_t call = IA32_Call_Imm32(jit, 0); + IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray); + } } inline void WriteOp_Push_Heap_C(JitWriter *jit) @@ -984,18 +1024,6 @@ inline void WriteOp_Push_Heap_C(JitWriter *jit) Write_CheckHeap_Low(jit); } -inline void WriteOp_Pop_Heap_Pri(JitWriter *jit) -{ - //sub [esi+hea], 4 - //mov ecx, [esi+hea] - //mov eax, [ebp+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_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_TMP, NOSCALE); - - Write_CheckHeap_Min(jit); -} - inline void WriteOp_Load_Both(JitWriter *jit) { WriteOp_Load_Pri(jit); diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h index ee54e78e..88fc895c 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.h +++ b/sourcepawn/vm/jit/x86/jit_x86.h @@ -27,6 +27,7 @@ public: jitoffs_t jit_verify_addr_edx; jitoffs_t jit_break; /* call to op.break */ jitoffs_t jit_sysreq_n; /* call version of op.sysreq.n */ + jitoffs_t jit_genarray; /* call to genarray intrinsic */ jitoffs_t jit_error_bounds; jitoffs_t jit_error_divzero; jitoffs_t jit_error_stacklow; diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index 55b45e71..5263ed52 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -451,6 +451,10 @@ void WriteOp_Sysreq_C_Function(JitWriter *jit) IA32_Return(jit); } +void WriteIntrinsic_GenArray(JitWriter *jit) +{ +} + void WriteOp_Sysreq_N_Function(JitWriter *jit) { /* The big daddy of opcodes. diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.h b/sourcepawn/vm/jit/x86/opcode_helpers.h index 5e303efc..3cf1942a 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.h +++ b/sourcepawn/vm/jit/x86/opcode_helpers.h @@ -16,6 +16,11 @@ jitoffs_t Write_Execute_Function(JitWriter *jit); void WriteOp_Sysreq_N_Function(JitWriter *jit); void WriteOp_Sysreq_C_Function(JitWriter *jit); +/** + * Write the GENARRAY intrinsic function. + */ +void WriteIntrinsic_GenArray(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. @@ -240,9 +245,9 @@ typedef enum OP_SYSREQ_D, // !GEN UNSUPPORT OP_SYSREQ_ND, // !GEN UNSUPPORT /* ----- */ - OP_HEAP_PRI, //DONE + OP_HEAP_I, // OP_PUSH_HEAP_C, //DONE - OP_POP_HEAP_PRI, //DONE + OP_GENARRAY, // /* ----- */ OP_NUM_OPCODES } OPCODE; diff --git a/sourcepawn/vm/jit/x86/opcode_switch.inc b/sourcepawn/vm/jit/x86/opcode_switch.inc index 4f389db7..6b2e3946 100644 --- a/sourcepawn/vm/jit/x86/opcode_switch.inc +++ b/sourcepawn/vm/jit/x86/opcode_switch.inc @@ -458,21 +458,6 @@ 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); @@ -658,6 +643,21 @@ } break; } + case OP_PUSH_HEAP_C: + { + WriteOp_Push_Heap_C(jit); + break; + } + case OP_HEAP_I: + { + WriteOp_Heap_I(jit); + break; + } + case OP_GENARRAY: + { + WriteOp_GenArray(jit); + break; + } #if defined USE_UNGEN_OPCODES #include "ungen_opcode_switch.inc" #endif diff --git a/sourcepawn/vm/jit/x86/x86_macros.h b/sourcepawn/vm/jit/x86/x86_macros.h index a742cceb..85c4a1f1 100644 --- a/sourcepawn/vm/jit/x86/x86_macros.h +++ b/sourcepawn/vm/jit/x86/x86_macros.h @@ -82,6 +82,8 @@ #define IA32_CMP_RM_IMM8 0x83 // encoding is /7 #define IA32_CMP_AL_IMM32 0x3C // no extra encoding #define IA32_CMP_EAX_IMM32 0x3D // no extra encoding +#define IA32_CMP_RM_REG 0x39 // encoding is /r +#define IA32_CMP_REG_RM 0x3B // encoding is /r #define IA32_CMPSB 0xA6 // no extra encoding #define IA32_TEST_RM_REG 0x85 // encoding is /r #define IA32_JCC_IMM 0x70 // encoding is +cc @@ -110,8 +112,6 @@ #define IA32_SHR_RM_CL 0xD3 // encoding is /5 #define IA32_SHL_RM_CL 0xD3 // encoding is /4 #define IA32_SAR_RM_IMM8 0xC1 // encoding is /7 -#define IA32_CMP_RM_REG 0x39 // encoding is /r -#define IA32_CMP_REG_RM 0x3B // encoding is /r #define IA32_SETCC_RM8_1 0x0F // opcode part 1 #define IA32_SETCC_RM8_2 0x90 // encoding is +cc /0 (8bits) #define IA32_XCHG_EAX_REG 0x90 // encoding is +r