diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index 10e6c32c..a916da7d 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -1215,6 +1215,57 @@ inline void WriteOp_Stack(JitWriter *jit) Write_CheckMargin_Stack(jit); } +inline void WriteOp_SDiv(JitWriter *jit) +{ + //mov ecx, edx + //mov edx, eax + //sar edx, 31 + //idiv ecx + IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG); + Write_Check_DivZero(jit, AMX_REG_TMP); + IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG); + IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); + IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); +} + + +inline void WriteOp_SDiv_Alt(JitWriter *jit) +{ + //mov ecx, eax + //mov eax, edx + //sar edx, 31 + //idiv ecx + IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG); + Write_Check_DivZero(jit, AMX_REG_TMP); + IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG); + IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG); + IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG); +} + +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); + Write_Check_DivZero(jit, AMX_REG_TMP); + IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG); + 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); + Write_Check_DivZero(jit, AMX_REG_TMP); + 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); + IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG); +} + /************************************************* ************************************************* * JIT PROPER ************************************ @@ -1919,6 +1970,26 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err) WriteOp_Stack(jit); break; } + case OP_SDIV: + { + WriteOp_SDiv(jit); + break; + } + case OP_SDIV_ALT: + { + WriteOp_SDiv_Alt(jit); + break; + } + case OP_UDIV: + { + WriteOp_UDiv(jit); + break; + } + case OP_UDIV_ALT: + { + WriteOp_UDiv_Alt(jit); + break; + } default: { AbortCompilation(co); diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index f4136eb7..795502d1 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -221,6 +221,25 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg, bool firstcall) } } +void Write_CheckMargin_Stack(JitWriter *jit) +{ + /* this is small, so we always inline it. + */ + //cmp ebp, [esi+stp] + //jle :continue + IA32_Cmp_Reg_Rm_Disp8(jit, AMX_REG_STK, AMX_REG_INFO, AMX_INFO_STACKTOP); + jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_LE, 0); + if (!(((CompData *)jit->data)->inline_level & JIT_INLINE_ERRORCHECKS)) + { + //sub esp, 4 - correct stack for returning to non-inlined JIT + IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG); + } + Write_Error(jit, SP_ERR_STACKMIN); + //continue: + IA32_Send_Jump8_Here(jit, jmp); +} + + void Macro_PushN_Addr(JitWriter *jit, int i) { //push eax