diff -r 7602d7fb60d9 -r 026da5437111 sourcepawn/jit/x86/jit_x86.cpp
--- a/sourcepawn/jit/x86/jit_x86.cpp Fri Jul 11 06:51:21 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3049 +0,0 @@
-/**
- * vim: set ts=4 :
- * =============================================================================
- * SourceMod
- * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- *
- * As a special exception, AlliedModders LLC gives you permission to link the
- * code of this program (as well as its derivative works) to "Half-Life 2," the
- * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
- * by the Valve Corporation. You must obey the GNU General Public License in
- * all respects for all other code used. Additionally, AlliedModders LLC grants
- * this exception to all derivative works. AlliedModders LLC defines further
- * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
- * or .
- *
- * Version: $Id$
- */
-
-#include
-#include
-#include
-#include "jit_x86.h"
-#include "opcode_helpers.h"
-#include
-#include "../jit_version.h"
-#include "../sp_vm_engine.h"
-#include "../engine2.h"
-#include "../BaseRuntime.h"
-#include "../sp_vm_basecontext.h"
-
-#if defined USE_UNGEN_OPCODES
-#include "ungen_opcodes.h"
-#endif
-
-JITX86 g_Jit1;
-ISourcePawnEngine *engine = &g_engine1;
-
-inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
-{
- return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
-}
-
-inline void WriteOp_Move_Pri(JitWriter *jit)
-{
- //mov eax, edx
- IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Move_Alt(JitWriter *jit)
-{
- //mov edx, eax
- IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Xchg(JitWriter *jit)
-{
- //xchg eax, edx
- IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
-}
-
-inline void WriteOp_Push(JitWriter *jit)
-{
- //push stack, DAT offset based
- //sub edi, 4
- //mov ecx, [ebp+]
- //mov [edi], ecx
- cell_t val = jit->read_cell();
- 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_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
- }
- IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
-}
-
-inline void WriteOp_Push_C(JitWriter *jit)
-{
- //push stack
- //mov [edi-4],
- //sub edi, 4
- cell_t val = jit->read_cell();
- IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-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 {
- IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
- }
-}
-
-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 {
- IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
- }
-}
-
-inline void WriteOp_Push_S(JitWriter *jit)
-{
- //push stack, FRM offset based
- //sub edi, 4
- //mov ecx, [ebx+]
- //mov [edi], ecx
- cell_t val = jit->read_cell();
- 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 {
- 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);
-}
-
-inline void WriteOp_Push_Pri(JitWriter *jit)
-{
- //mov [edi-4], eax
- //sub edi, 4
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_Push_Alt(JitWriter *jit)
-{
- //mov [edi-4], edx
- //sub edi, 4
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_Push2_C(JitWriter *jit)
-{
- Macro_PushN_C(jit, 2);
-}
-
-inline void WriteOp_Push3_C(JitWriter *jit)
-{
- Macro_PushN_C(jit, 3);
-}
-
-inline void WriteOp_Push4_C(JitWriter *jit)
-{
- Macro_PushN_C(jit, 4);
-}
-
-inline void WriteOp_Push5_C(JitWriter *jit)
-{
- Macro_PushN_C(jit, 5);
-}
-
-inline void WriteOp_Push2_Adr(JitWriter *jit)
-{
- Macro_PushN_Addr(jit, 2);
-}
-
-inline void WriteOp_Push3_Adr(JitWriter *jit)
-{
- Macro_PushN_Addr(jit, 3);
-}
-
-inline void WriteOp_Push4_Adr(JitWriter *jit)
-{
- Macro_PushN_Addr(jit, 4);
-}
-
-inline void WriteOp_Push5_Adr(JitWriter *jit)
-{
- Macro_PushN_Addr(jit, 5);
-}
-
-inline void WriteOp_Push2_S(JitWriter *jit)
-{
- Macro_PushN_S(jit, 2);
-}
-
-inline void WriteOp_Push3_S(JitWriter *jit)
-{
- Macro_PushN_S(jit, 3);
-}
-
-inline void WriteOp_Push4_S(JitWriter *jit)
-{
- Macro_PushN_S(jit, 4);
-}
-
-inline void WriteOp_Push5_S(JitWriter *jit)
-{
- Macro_PushN_S(jit, 5);
-}
-
-inline void WriteOp_Push5(JitWriter *jit)
-{
- Macro_PushN(jit, 5);
-}
-
-inline void WriteOp_Push4(JitWriter *jit)
-{
- Macro_PushN(jit, 4);
-}
-
-inline void WriteOp_Push3(JitWriter *jit)
-{
- Macro_PushN(jit, 3);
-}
-
-inline void WriteOp_Push2(JitWriter *jit)
-{
- Macro_PushN(jit, 2);
-}
-
-inline void WriteOp_Zero_Pri(JitWriter *jit)
-{
- //xor eax, eax
- IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Zero_Alt(JitWriter *jit)
-{
- //xor edx, edx
- IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Add(JitWriter *jit)
-{
- //add eax, edx
- IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Sub(JitWriter *jit)
-{
- //sub eax, edx
- IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Sub_Alt(JitWriter *jit)
-{
- //neg eax
- //add eax, edx
- IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
- IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Proc(JitWriter *jit)
-{
- CompData *co = (CompData *)jit->data;
-
- /* Specialized code to align this taking in account the function magic number */
- jitoffs_t cur_offs = jit->get_outputpos();
- jitoffs_t offset = ((cur_offs & 0xFFFFFFF8) + 8) - cur_offs;
- if (!((offset + cur_offs) & 8))
- {
- offset += 8;
- }
- if (offset)
- {
- for (jit_uint32_t i=0; iwrite_ubyte(IA32_INT3);
- }
- }
-
- /* Write the info struct about this function */
- jit->write_uint32(JIT_FUNCMAGIC);
- jit->write_uint32(co->func_idx);
-
- /* Now we have to backpatch our reloction offset! */
- {
- jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
- jitcode_t rebase = ((CompData *)jit->data)->rebase;
- *(jitoffs_t *)((unsigned char *)rebase + offs) = jit->get_outputpos();
- }
-
- /* Lastly, if we're writing, keep track of the function count */
- if (jit->outbase)
- {
- co->func_idx++;
- }
-
- //push old frame on stack:
- //mov ecx, [esi+frm]
- //mov [edi-4], ecx
- //sub edi, 8 ;extra un-used slot for non-existant CIP
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
- //save frame:
- //mov ecx, edi - get new frame
- //mov ebx, edi - store frame back
- //sub ecx, ebp - relocate local frame
- //mov [esi+frm], ecx
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
- IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
- IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
- IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG);
-}
-
-inline void WriteOp_Lidx_B(JitWriter *jit)
-{
- cell_t val = jit->read_cell();
- //shl eax,
- //add eax, edx
- //mov eax, [ebp+eax]
- IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
- IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- Write_Check_VerifyAddr(jit, AMX_REG_PRI);
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-
-inline void WriteOp_Idxaddr_B(JitWriter *jit)
-{
- //shl eax,
- //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_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Shl(JitWriter *jit)
-{
- //mov ecx, edx
- //shl eax, cl
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
- IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Shr(JitWriter *jit)
-{
- //mov ecx, edx
- //shr eax, cl
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
- IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Sshr(JitWriter *jit)
-{
- //mov ecx, edx
- //sar eax, cl
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
- IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Shl_C_Pri(JitWriter *jit)
-{
- //shl eax,
- jit_uint8_t val = (jit_uint8_t)jit->read_cell();
- if (val == 1)
- {
- IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG);
- } else {
- IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
- }
-}
-
-inline void WriteOp_Shl_C_Alt(JitWriter *jit)
-{
- //shl edx,
- jit_uint8_t val = (jit_uint8_t)jit->read_cell();
- if (val == 1)
- {
- IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG);
- } else {
- IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
- }
-}
-
-inline void WriteOp_Shr_C_Pri(JitWriter *jit)
-{
- //shr eax,
- jit_uint8_t val = (jit_uint8_t)jit->read_cell();
- if (val == 1)
- {
- IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG);
- } else {
- IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
- }
-}
-
-inline void WriteOp_Shr_C_Alt(JitWriter *jit)
-{
- //shr edx,
- jit_uint8_t val = (jit_uint8_t)jit->read_cell();
- if (val == 1)
- {
- IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG);
- } else {
- IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
- }
-}
-
-inline void WriteOp_SMul(JitWriter *jit)
-{
- //mov ecx, edx
- //imul edx
- //mov edx, ecx
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
- IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
- IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
-}
-
-inline void WriteOp_Not(JitWriter *jit)
-{
- //test eax, eax
- //mov eax, 0
- //sete al
- IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
- IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
- IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
-}
-
-inline void WriteOp_Neg(JitWriter *jit)
-{
- //neg eax
- IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Xor(JitWriter *jit)
-{
- //xor eax, edx
- IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Or(JitWriter *jit)
-{
- //or eax, edx
- IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_And(JitWriter *jit)
-{
- //and eax, edx
- IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_Invert(JitWriter *jit)
-{
- //not eax
- IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Add_C(JitWriter *jit)
-{
- //add eax,
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
- else
- IA32_Add_Eax_Imm32(jit, val);
-}
-
-inline void WriteOp_SMul_C(JitWriter *jit)
-{
- //imul eax,
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
- else
- IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
-}
-
-inline void WriteOp_Sign_Pri(JitWriter *jit)
-{
- //shl eax, 24
- //sar eax, 24
- IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
- IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
-}
-
-inline void WriteOp_Sign_Alt(JitWriter *jit)
-{
- //shl edx, 24
- //sar edx, 24
- IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
- IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
-}
-
-inline void WriteOp_Eq(JitWriter *jit)
-{
- //cmp eax, edx ; PRI == ALT ?
- //mov eax, 0
- //sete al
- IA32_Cmp_Reg_Rm(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_E);
-}
-
-inline void WriteOp_Neq(JitWriter *jit)
-{
- //cmp eax, edx ; PRI != ALT ?
- //mov eax, 0
- //setne al
- IA32_Cmp_Reg_Rm(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_NE);
-}
-
-inline void WriteOp_Sless(JitWriter *jit)
-{
- //cmp eax, edx ; PRI < ALT ? (signed)
- //mov eax, 0
- //setl al
- IA32_Cmp_Reg_Rm(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_L);
-}
-
-inline void WriteOp_Sleq(JitWriter *jit)
-{
- //cmp eax, edx ; PRI <= ALT ? (signed)
- //mov eax, 0
- //setle al
- IA32_Cmp_Reg_Rm(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_LE);
-}
-
-inline void WriteOp_Sgrtr(JitWriter *jit)
-{
- //cmp eax, edx ; PRI > ALT ? (signed)
- //mov eax, 0
- //setg al
- IA32_Cmp_Reg_Rm(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_G);
-}
-
-inline void WriteOp_Sgeq(JitWriter *jit)
-{
- //cmp eax, edx ; PRI >= ALT ? (signed)
- //mov eax, 0
- //setge al
- IA32_Cmp_Reg_Rm(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_GE);
-}
-
-inline void WriteOp_Eq_C_Pri(JitWriter *jit)
-{
- //cmp eax, ; PRI == value ?
- //mov eax, 0
- //sete al
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
- else
- IA32_Cmp_Eax_Imm32(jit, val);
- IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
- IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
-}
-
-inline void WriteOp_Eq_C_Alt(JitWriter *jit)
-{
- //xor eax, eax
- //cmp edx, ; ALT == value ?
- //sete al
- cell_t val = jit->read_cell();
- IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
- else
- IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
- IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
-}
-
-inline void WriteOp_Inc_Pri(JitWriter *jit)
-{
- //add eax, 1
- IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
-}
-
-inline void WriteOp_Inc_Alt(JitWriter *jit)
-{
- //add edx, 1
- IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
-}
-
-inline void WriteOp_Inc(JitWriter *jit)
-{
- //add [ebp+], 1
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
- else
- IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
-}
-
-inline void WriteOp_Inc_S(JitWriter *jit)
-{
- //add [ebx+], 1
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
- else
- IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
-}
-
-inline void WriteOp_Inc_I(JitWriter *jit)
-{
- //add [ebp+eax], 1
- IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
-}
-
-inline void WriteOp_Dec_Pri(JitWriter *jit)
-{
- //sub eax, 1
- IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
-}
-
-inline void WriteOp_Dec_Alt(JitWriter *jit)
-{
- //sub edx, 1
- IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
-}
-
-inline void WriteOp_Dec(JitWriter *jit)
-{
- //sub [ebp+], 1
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
- } else {
- IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
- }
-}
-
-inline void WriteOp_Dec_S(JitWriter *jit)
-{
- //sub [ebx+], 1
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
- } else {
- IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
- }
-}
-
-inline void WriteOp_Dec_I(JitWriter *jit)
-{
- //sub [ebp+eax], 1
- IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
-}
-
-inline void WriteOp_Load_Pri(JitWriter *jit)
-{
- //mov eax, [ebp+]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
- }
-}
-
-inline void WriteOp_Load_Alt(JitWriter *jit)
-{
- //mov edx, [ebp+]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
- }
-}
-
-inline void WriteOp_Load_S_Pri(JitWriter *jit)
-{
- //mov eax, [ebx+]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
- }
-}
-
-inline void WriteOp_Load_S_Alt(JitWriter *jit)
-{
- //mov edx, [ebx+]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
- }
-}
-
-inline void WriteOp_Lref_Pri(JitWriter *jit)
-{
- //mov eax, [ebp+]
- //mov eax, [ebp+eax]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
- }
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-
-inline void WriteOp_Lref_Alt(JitWriter *jit)
-{
- //mov edx, [ebp+]
- //mov edx, [ebp+edx]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
- }
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
-}
-
-inline void WriteOp_Lref_S_Pri(JitWriter *jit)
-{
- //mov eax, [ebx+]
- //mov eax, [ebp+eax]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
- }
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-
-inline void WriteOp_Lref_S_Alt(JitWriter *jit)
-{
- //mov edx, [ebx+]
- //mov edx, [ebp+edx]
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
- }
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
-}
-
-inline void WriteOp_Const_Pri(JitWriter *jit)
-{
- //mov eax,
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
-}
-
-inline void WriteOp_Const_Alt(JitWriter *jit)
-{
- //mov edx,
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
-}
-
-inline void WriteOp_Addr_Pri(JitWriter *jit)
-{
- //mov eax, [esi+frm]
- //add eax,
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
- } else {
- IA32_Add_Eax_Imm32(jit, val);
- }
-}
-
-inline void WriteOp_Addr_Alt(JitWriter *jit)
-{
- //mov edx, [esi+frm]
- //add edx,
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG);
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
- } else {
- IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
- }
-}
-
-inline void WriteOp_Stor_Pri(JitWriter *jit)
-{
- //mov [ebp+], eax
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
- } else {
- IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
- }
-}
-
-inline void WriteOp_Stor_Alt(JitWriter *jit)
-{
- //mov [ebp+], edx
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
- } else {
- IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
- }
-}
-
-inline void WriteOp_Stor_S_Pri(JitWriter *jit)
-{
- //mov [ebx+], eax
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
- } else {
- IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
- }
-}
-
-inline void WriteOp_Stor_S_Alt(JitWriter *jit)
-{
- //mov [ebx+], edx
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
- } else {
- IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
- }
-}
-
-inline void WriteOp_Idxaddr(JitWriter *jit)
-{
- //lea eax, [edx+4*eax]
- IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
-}
-
-inline void WriteOp_Sref_Pri(JitWriter *jit)
-{
- //mov ecx, [ebp+]
- //mov [ebp+ecx], eax
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
- }
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
-}
-
-inline void WriteOp_Sref_Alt(JitWriter *jit)
-{
- //mov ecx, [ebp+]
- //mov [ebp+ecx], edx
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
- }
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
-}
-
-inline void WriteOp_Sref_S_Pri(JitWriter *jit)
-{
- //mov ecx, [ebx+]
- //mov [ebp+ecx], eax
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
- }
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
-}
-
-inline void WriteOp_Sref_S_Alt(JitWriter *jit)
-{
- //mov ecx, [ebx+]
- //mov [ebp+ecx], edx
- cell_t val = jit->read_cell();
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
- } else {
- IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
- }
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
-}
-
-inline void WriteOp_Pop_Pri(JitWriter *jit)
-{
- //mov eax, [edi]
- //add edi, 4
- IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_Pop_Alt(JitWriter *jit)
-{
- //mov edx, [edi]
- //add edi, 4
- IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_Swap_Pri(JitWriter *jit)
-{
- //add [edi], eax
- //sub eax, [edi]
- //add [edi], eax
- //neg eax
- IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
- IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
- IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
- IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
-}
-
-inline void WriteOp_Swap_Alt(JitWriter *jit)
-{
- //add [edi], edx
- //sub edx, [edi]
- //add [edi], edx
- //neg edx
- IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
- IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
- IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
- IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
-}
-
-inline void WriteOp_PushAddr(JitWriter *jit)
-{
- //mov ecx, [esi+frm] ;get address (offset from frame)
- //sub edi, 4
- //add ecx,
- //mov [edi], ecx
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
- } else {
- IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
- }
- IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
-}
-
-inline void WriteOp_Movs(JitWriter *jit)
-{
- //cld
- //push esi
- //push edi
- //lea esi, [ebp+eax]
- //lea edi, [ebp+edx]
- //if dword:
- // mov ecx, dword
- // rep movsd
- //if byte:
- // mov ecx, byte
- // rep movsb
- //pop edi
- //pop esi
- cell_t val = jit->read_cell();
- unsigned int dwords = val >> 2;
- unsigned int bytes = val & 0x3;
-
- IA32_Cld(jit);
- IA32_Push_Reg(jit, REG_ESI);
- IA32_Push_Reg(jit, REG_EDI);
- IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
- IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
- if (dwords)
- {
- IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
- IA32_Rep(jit);
- IA32_Movsd(jit);
- }
- if (bytes)
- {
- IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
- IA32_Rep(jit);
- IA32_Movsb(jit);
- }
- IA32_Pop_Reg(jit, REG_EDI);
- IA32_Pop_Reg(jit, REG_ESI);
-}
-
-inline void WriteOp_Fill(JitWriter *jit)
-{
- //push edi
- //lea edi, [ebp+edx]
- //mov ecx, >> 2
- //cld
- //rep stosd
- //pop edi
- unsigned int val = jit->read_cell() >> 2;
-
- IA32_Push_Reg(jit, REG_EDI);
- IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
- IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
- IA32_Cld(jit);
- IA32_Rep(jit);
- IA32_Stosd(jit);
- IA32_Pop_Reg(jit, REG_EDI);
-}
-
-inline void WriteOp_GenArray(JitWriter *jit, bool autozero)
-{
- 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] ;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
- 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_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4);
- IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP);
- IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
- IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow);
-
- WriteOp_Tracker_Push_Reg(jit, REG_ECX);
-
- if (autozero)
- {
- /* Zero out the array - inline a quick fill */
- //push eax ;save pri
- //push edi ;save stk
- //xor eax, eax ;zero source
- //mov edi, [edi] ;get heap ptr out of the stack
- //add edi, ebp ;relocate
- //cld ;clear direction flag
- //rep stosd ;copy (note: ECX is sane from above)
- //pop edi ;pop stk
- //pop eax ;pop pri
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Push_Reg(jit, REG_EDI);
- IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG);
- IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG);
- IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
- IA32_Cld(jit);
- IA32_Rep(jit);
- IA32_Stosd(jit);
- IA32_Pop_Reg(jit, REG_EDI);
- IA32_Pop_Reg(jit, REG_EAX);
- }
- } else {
- //mov ecx, num_dims
- //mov edx, 0/1
- //call [genarray]
- IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
- if (autozero)
- {
- IA32_Mov_Reg_Imm32(jit, REG_EDX, 1);
- } else {
- IA32_Mov_Reg_Imm32(jit, REG_EDX, 0);
- }
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray);
- }
-}
-
-inline void WriteOp_Load_Both(JitWriter *jit)
-{
- WriteOp_Load_Pri(jit);
- WriteOp_Load_Alt(jit);
-}
-
-inline void WriteOp_Load_S_Both(JitWriter *jit)
-{
- WriteOp_Load_S_Pri(jit);
- WriteOp_Load_S_Alt(jit);
-}
-
-inline void WriteOp_Const(JitWriter *jit)
-{
- //mov [ebp+],
- cell_t addr = jit->read_cell();
- cell_t val = jit->read_cell();
- if (addr <= SCHAR_MAX && addr >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
- } else {
- IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
- }
-}
-
-inline void WriteOp_Const_S(JitWriter *jit)
-{
- //mov [ebx+],
- cell_t offs = jit->read_cell();
- cell_t val = jit->read_cell();
- if (offs <= SCHAR_MAX && offs >= SCHAR_MIN)
- {
- IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
- } else {
- IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
- }
-}
-
-inline void WriteOp_Load_I(JitWriter *jit)
-{
- //mov eax, [ebp+eax]
- Write_Check_VerifyAddr(jit, AMX_REG_PRI);
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-
-inline void WriteOp_Lodb_I(JitWriter *jit)
-{
- Write_Check_VerifyAddr(jit, AMX_REG_PRI);
-
- //mov eax, [ebp+eax]
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-
- //and eax,
- cell_t val = jit->read_cell();
- switch(val)
- {
- case 1:
- {
- IA32_And_Eax_Imm32(jit, 0x000000FF);
- break;
- }
- case 2:
- {
- IA32_And_Eax_Imm32(jit, 0x0000FFFF);
- break;
- }
- }
-}
-
-inline void WriteOp_Stor_I(JitWriter *jit)
-{
- //mov [ebp+edx], eax
- Write_Check_VerifyAddr(jit, AMX_REG_ALT);
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
-}
-
-inline void WriteOp_Strb_I(JitWriter *jit)
-{
- Write_Check_VerifyAddr(jit, AMX_REG_ALT);
- //mov [ebp+edx], eax
- cell_t val = jit->read_cell();
- switch (val)
- {
- case 1:
- {
- IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
- break;
- }
- case 2:
- {
- IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
- break;
- }
- case 4:
- {
- IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
- break;
- }
- }
-}
-
-inline void WriteOp_Lidx(JitWriter *jit)
-{
- //lea eax, [edx+4*eax]
- //mov eax, [ebp+eax]
- IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
- Write_Check_VerifyAddr(jit, AMX_REG_PRI);
- IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
-}
-
-inline void WriteOp_Stack(JitWriter *jit)
-{
- //add edi,
- cell_t val = jit->read_cell();
- 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);
- }
-
- if (val > 0)
- {
- Write_CheckStack_Min(jit);
- } else if (val < 0) {
- Write_CheckStack_Low(jit);
- }
-}
-
-inline void WriteOp_StackAdjust(JitWriter *jit)
-{
- cell_t val = jit->read_cell();
-
- assert(val <= 0);
-
- //lea edi, [ebx-val]
-
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Lea_DispRegImm8(jit, AMX_REG_STK, AMX_REG_FRM, val);
- }
- else
- {
- IA32_Lea_DispRegImm32(jit, AMX_REG_STK, AMX_REG_FRM, val);
- }
-
- /* We assume the compiler has generated good code --
- * That is, we do not bother validating this amount!
- */
-}
-
-inline void WriteOp_Heap(JitWriter *jit)
-{
- //mov edx, [esi+hea]
- //add [esi+hea],
- cell_t val = jit->read_cell();
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP);
- } else {
- IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP);
- }
-
- /* NOTE: Backwards from op.stack */
- if (val > 0)
- {
- Write_CheckHeap_Low(jit);
- } else if (val < 0) {
- Write_CheckHeap_Min(jit);
- }
-}
-
-inline void WriteOp_SDiv(JitWriter *jit)
-{
- //mov ecx, edx
- //mov edx, eax
- //sar edx, 31
- //idiv ecx
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
- IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
- IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
- Write_Check_DivZero(jit, AMX_REG_TMP);
- 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_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
- IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
- Write_Check_DivZero(jit, AMX_REG_TMP);
- IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
-}
-
-inline void WriteOp_Retn(JitWriter *jit)
-{
- //mov ebx, [edi+4] - get old frm
- //add edi, 8 - pop stack
- //mov [esi+frm], ebx - restore frame pointer
- //add ebx, ebp - relocate
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4);
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
- IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
- IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
-
- /* pop params */
- //mov ecx, [edi]
- //lea edi, [edi+ecx*4+4]
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
- IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4);
-
- //ret - return (EIP on real stack!)
- IA32_Return(jit);
-}
-
-void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
-{
- ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
-}
-
-void ProfCallGate_End(sp_context_t *ctx)
-{
- ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
-}
-
-const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
-{
- uint32_t max, iter;
- sp_fdbg_symbol_t *sym;
- sp_fdbg_arraydim_t *arr;
- uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
-
- max = plugin->debug.syms_num;
- for (iter = 0; iter < max; iter++)
- {
- sym = (sp_fdbg_symbol_t *)cursor;
-
- if (sym->ident == SP_SYM_FUNCTION
- && sym->codestart <= offs
- && sym->codeend > offs)
- {
- return plugin->debug.stringbase + sym->name;
- }
-
- if (sym->dimcount > 0)
- {
- cursor += sizeof(sp_fdbg_symbol_t);
- arr = (sp_fdbg_arraydim_t *)cursor;
- cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
- continue;
- }
-
- cursor += sizeof(sp_fdbg_symbol_t);
- }
-
- return NULL;
-}
-
-inline void WriteOp_Call(JitWriter *jit)
-{
- cell_t offs;
- jitoffs_t jmp;
- CompData *data;
-
- data = (CompData *)jit->data;
- offs = jit->read_cell();
-
- if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
- {
- const char *name;
-
- /* Find the function name */
- if ((name = find_func_name(data->plugin, offs)) == NULL)
- {
- name = "unknown";
- }
-
- //push name
- //push [esi+context]
- //call ProfCallGate_Begin
- //add esp, 8
- IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
- IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
- jmp = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
-
- //call
- //push eax
- jmp = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
- IA32_Push_Reg(jit, REG_EAX);
-
- //push [esi+context]
- //call ProfCallGate_End
- //add esp, 4
- //pop eax
- IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
- jmp = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
- IA32_Pop_Reg(jit, REG_EAX);
- }
- else
- {
- jmp = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
- }
-}
-
-inline void WriteOp_Bounds(JitWriter *jit)
-{
- cell_t val = jit->read_cell();
-
- //cmp eax,
- //ja :error
- if (val <= SCHAR_MAX && val >= SCHAR_MIN)
- {
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
- } else {
- IA32_Cmp_Eax_Imm32(jit, val);
- }
- IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds);
-}
-
-inline void WriteOp_Halt(JitWriter *jit)
-{
- AlignMe(jit);
-
- //mov ecx, [esi+ret]
- //mov [ecx], eax
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
- IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
-
- /* :TODO:
- * We don't support sleeping or halting with weird values.
- * So we're omitting the mov eax that was here.
- */
- jit->read_cell();
-
- CompData *data = (CompData *)jit->data;
- IA32_Jump_Imm32_Abs(jit, data->jit_return);
-}
-
-inline void WriteOp_Break(JitWriter *jit)
-{
- CompData *data = (CompData *)jit->data;
- if (data->debug)
- {
- //jit->write_ubyte(IA32_INT3);
- //mov ecx,
- jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0);
- jitoffs_t save = jit->get_outputpos();
- jit->set_outputpos(wr);
- jit->write_uint32((uint32_t)(wr));
- jit->set_outputpos(save);
- wr = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, wr, data->jit_break);
- }
-}
-
-inline void WriteOp_Jump(JitWriter *jit)
-{
- //jmp
- cell_t amx_offs = jit->read_cell();
- IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false));
-}
-
-inline void WriteOp_Jzer(JitWriter *jit)
-{
- //test eax, eax
- //jz
- cell_t target = jit->read_cell();
- IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Jnz(JitWriter *jit)
-{
- //test eax, eax
- //jnz
- cell_t target = jit->read_cell();
- IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Jeq(JitWriter *jit)
-{
- //cmp eax, edx
- //je
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Jneq(JitWriter *jit)
-{
- //cmp eax, edx
- //jne
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Jsless(JitWriter *jit)
-{
- //cmp eax, edx
- //jl
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_L, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Jsleq(JitWriter *jit)
-{
- //cmp eax, edx
- //jle
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_LE, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_JsGrtr(JitWriter *jit)
-{
- //cmp eax, edx
- //jg
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_G, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_JsGeq(JitWriter *jit)
-{
- //cmp eax, edx
- //jge
- cell_t target = jit->read_cell();
- IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_GE, RelocLookup(jit, target, false));
-}
-
-inline void WriteOp_Switch(JitWriter *jit)
-{
- cell_t offs = jit->read_cell();
- cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t));
-
- struct casetbl
- {
- cell_t val;
- cell_t offs;
- };
-
- /* Read the number of cases, then advance by one */
- cell_t num_cases = *tbl++;
- if (!num_cases)
- {
- /* Special treatment for 0 cases */
- //jmp
- IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
- } else {
- /* Check if the case layout is fully sequential */
- casetbl *iter = (casetbl *)(tbl + 1);
- casetbl *cases = iter;
- cell_t first = iter[0].val;
- cell_t last = first;
- bool sequential = true;
- for (cell_t i=1; i HIGH)
- * This check is valid for both sequential and non-sequential.
- */
- cell_t low_bound = cases[0].val;
- if (low_bound != 0)
- {
- /* negate it so we'll get a lower bound of 0 */
- //lea ecx, [eax-]
- low_bound = -low_bound;
- if (low_bound >= SCHAR_MIN && low_bound <= SCHAR_MAX)
- {
- IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
- } else {
- IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
- }
- } else {
- //mov ecx, eax
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
- }
- cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val);
- //cmp ecx,
- if (high_bound >= SCHAR_MIN && high_bound <= SCHAR_MAX)
- {
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound);
- } else {
- IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound);
- }
- //ja
- IA32_Jump_Cond_Imm32_Abs(jit, CC_A, RelocLookup(jit, *tbl, false));
-
- /**
- * Now we've taken the default case out of the way, it's time to do the
- * full check, which is different for sequential vs. non-sequential.
- */
- if (sequential)
- {
- /* we're now theoretically guaranteed to be jumping to a correct offset.
- * ECX still has the correctly bound offset in it, luckily!
- * thus, we simply need to relocate ECX and store the cases.
- */
- //lea ecx, [ecx*4]
- //add ecx,
- IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0);
- jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG);
- IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG);
- /* The case table starts here. Go back and write the output pointer. */
- jitoffs_t cur_pos = jit->get_outputpos();
- jit->set_outputpos(tbl_offs);
- jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos));
- jit->set_outputpos(cur_pos);
- //now we can write the case table, finally!
- jit_uint32_t base = (jit_uint32_t)jit->outbase;
- for (cell_t i=0; iwrite_uint32(base + RelocLookup(jit, cases[i].offs, false));
- }
- } else {
- /* The slow version. Go through each case and generate a check.
- * In the future we should replace case tables of more than ~8 cases with a
- * hash table lookup.
- * :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case,
- * but only if we're under N cases or so!
- * :THOUGHT: Write out a static btree lookup :)
- */
- cell_t val;
- for (cell_t i=0; i OR cmp al,
- if (val >= SCHAR_MIN && val <= SCHAR_MAX)
- {
- IA32_Cmp_Al_Imm8(jit, val);
- } else {
- IA32_Cmp_Eax_Imm32(jit, cases[i].val);
- }
- IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, cases[i].offs, false));
- }
- /* After all this, jump to the default case! */
- IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
- }
- }
-}
-
-inline void WriteOp_Casetbl(JitWriter *jit)
-{
- /* do nothing here, switch does all ze work */
- cell_t num_cases = jit->read_cell();
-
- /* Two cells per case, one extra case for the default jump */
- num_cases = (num_cases * 2) + 1;
- jit->inptr += num_cases;
-}
-
-inline void WriteOp_Sysreq_C(JitWriter *jit)
-{
- /* store the number of parameters on the stack,
- * and store the native index as well.
- */
- cell_t native_index = jit->read_cell();
-
- if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
- {
- ((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
- return;
- }
-
- //mov ecx,
- IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
-
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c);
-}
-
-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 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_ERROR_INSTRUCTION_PARAM;
- return;
- }
-
- //mov eax,
- //mov ecx,
- IA32_Mov_Reg_Imm32(jit, REG_EAX, num_params);
- IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
-
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_n);
-}
-
-inline void WriteOp_Sysreq_N(JitWriter *jit)
-{
- /* The big daddy of opcodes. */
- 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_ERROR_INSTRUCTION_PARAM;
- return;
- }
-
- /* store the number of parameters on the stack */
- //mov [edi-4], num_params
- //sub edi, 4
- IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4);
- IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-
- /* save registers we will need */
- //push edx
- IA32_Push_Reg(jit, AMX_REG_ALT);
-
- /* Align the stack to 16 bytes */
- //push ebx
- //mov ebx, esp
- //and esp, 0xFFFFFF0
- //sub esp, 4
- IA32_Push_Reg(jit, REG_EBX);
- IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
- IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
- IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- /* push some callback stuff */
- //push edi ; stack
- //push ; native index
- IA32_Push_Reg(jit, AMX_REG_STK);
- if (native_index <= SCHAR_MAX && native_index >= SCHAR_MIN)
- {
- IA32_Push_Imm8(jit, (jit_int8_t)native_index);
- } else {
- IA32_Push_Imm32(jit, native_index);
- }
-
- /* Relocate stack, heap, frm information, then store back */
- //mov eax, [esi+context]
- //mov ecx, [esi+hea]
- //sub edi, ebp
- //mov [eax+hp], ecx
- //mov ecx, [esi]
- //mov [eax+sp], edi
- //mov [eax+frm], ecx
- IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
- IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
- IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
- IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
- IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
-
- /* finally, push the last parameter and make the call */
- //push eax ; context
- //call NativeCallback
- IA32_Push_Reg(jit, REG_EAX);
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- if (!data->debug)
- {
- if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
- {
- IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
- }
- else
- {
- IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
- }
- }
- else
- {
- if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
- {
- IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
- }
- else
- {
- IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
- }
- }
-
- /* 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_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
-
- /* restore what we damaged */
- //mov esp, ebx
- //pop ebx
- //add edi, ebp
- //pop edx
- IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
- IA32_Pop_Reg(jit, REG_EBX);
- IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
- IA32_Pop_Reg(jit, AMX_REG_ALT);
-
- /* 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.
- */
- num_params++;
- num_params *= 4;
- //add edi,
- if (num_params <= SCHAR_MAX && num_params >= SCHAR_MIN)
- {
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG);
- } else {
- IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG);
- }
-}
-
-inline void WriteOp_Tracker_Push_C(JitWriter *jit)
-{
- CompData *data = (CompData *)jit->data;
- cell_t val = jit->read_cell();
-
- /* Save registers that may be damaged by the call */
- //push eax
- //push edx
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Push_Reg(jit, AMX_REG_ALT);
-
- /* Get the context ptr, push it and call the check */
- //mov eax, [esi+context]
- //push eax
- //call JIT_VerifyOrAllocateTracker
- IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
- IA32_Push_Reg(jit, REG_EAX);
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
-
- /* Check for errors */
- //cmp eax, 0
- //jnz :error
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
-
- /* Restore */
- //pop eax
- IA32_Pop_Reg(jit, REG_EAX);
-
- /* Push the value into the stack and increment pCur */
- //mov edx, [eax+vm[]]
- //mov ecx, [edx+pcur]
- //add [edx+pcur], 4
- //mov [ecx], *4 ; we want the count in bytes not in cells
- IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
- IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
- IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG);
-
- /* Restore PRI & ALT */
- //pop edx
- //pop eax
- IA32_Pop_Reg(jit, AMX_REG_ALT);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-}
-
-inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit)
-{
- CompData *data = (CompData *)jit->data;
-
- /* Save registers that may be damaged by the call */
- //push eax
- //push edx
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Push_Reg(jit, AMX_REG_ALT);
-
- /* Get the context ptr, push it and call the check */
- //mov eax, [esi+context]
- //push eax
- //call JIT_VerifyLowBoundTracker
- IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
- IA32_Push_Reg(jit, REG_EAX);
- jitoffs_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker);
-
- /* Check for errors */
- //cmp eax, 0
- //jnz :error
- IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
- IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
-
- /* Restore */
- //pop eax
- IA32_Pop_Reg(jit, REG_EAX);
-
- /* Pop the value from the stack and decrease the heap by it*/
- //mov edx, [eax+vm[]]
- //sub [edx+pcur], 4
- //mov ecx, [edx+pcur]
- //mov ecx, [ecx]
- //sub [esi+hea], ecx
- IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
- IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
- IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG);
- IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP);
-
- Write_CheckHeap_Min(jit);
-
- /* Restore PRI & ALT */
- //pop edx
- //pop eax
- IA32_Pop_Reg(jit, AMX_REG_ALT);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-}
-
-inline void WriteOp_Stradjust_Pri(JitWriter *jit)
-{
- //add eax, 4
- //sar eax, 2
- IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG);
- IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG);
-}
-
-inline void WriteOp_FloatAbs(JitWriter *jit)
-{
- //mov eax, [edi]
- //and eax, 0x7FFFFFFF
- IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
- IA32_And_Eax_Imm32(jit, 0x7FFFFFFF);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_Float(JitWriter *jit)
-{
- //fild [edi]
- //push eax
- //fstp [esp]
- //pop eax
- IA32_Fild_Mem32(jit, AMX_REG_STK);
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Fstp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_FloatAdd(JitWriter *jit)
-{
- //push eax
- //fld [edi]
- //fadd [edi+4]
- //fstp [esp]
- //pop eax
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
- IA32_Fadd_Mem32_Disp8(jit, AMX_REG_STK, 4);
- IA32_Fstp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- /* Rectify the stack */
- //add edi, 8
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
-}
-
-inline void WriteOp_FloatSub(JitWriter *jit)
-{
- //push eax
- //fld [edi]
- //fsub [edi+4]
- //fstp [esp]
- //pop eax
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
- IA32_Fsub_Mem32_Disp8(jit, AMX_REG_STK, 4);
- IA32_Fstp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- /* Rectify the stack */
- //add edi, 8
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
-}
-
-inline void WriteOp_FloatMul(JitWriter *jit)
-{
- //push eax
- //fld [edi]
- //fmul [edi+4]
- //fstp [esp]
- //pop eax
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
- IA32_Fmul_Mem32_Disp8(jit, AMX_REG_STK, 4);
- IA32_Fstp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- /* Rectify the stack */
- //add edi, 8
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
-}
-
-inline void WriteOp_FloatDiv(JitWriter *jit)
-{
- //push eax
- //fld [edi]
- //fdiv [edi+4]
- //fstp [esp]
- //pop eax
- IA32_Push_Reg(jit, AMX_REG_PRI);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
- IA32_Fdiv_Mem32_Disp8(jit, AMX_REG_STK, 4);
- IA32_Fstp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- /* Rectify the stack */
- //add edi, 8
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
-}
-
-inline void WriteOp_RountToNearest(JitWriter *jit)
-{
- //push eax
- //fld [edi]
-
- //fstcw [esp]
- //mov eax, [esp]
- //push eax
-
- //mov [esp+4], 0x3FF
- //fadd st(0), st(0)
- //fldcw [esp+4]
-
- //push eax
- //push 0x3F000000 ; 0.5f
- //fadd [esp]
- //fistp [esp+4]
- //pop eax
- //pop eax
-
- //pop ecx
- //sar eax, 1
- //mov [esp], ecx
- //fldcw [esp]
- //add esp, 4
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
-
- IA32_Fstcw_Mem16_ESP(jit);
- IA32_Mov_Reg_RmESP(jit, REG_EAX);
- IA32_Push_Reg(jit, REG_EAX);
-
- IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x3FF);
- IA32_Fadd_FPUreg_ST0(jit, 0);
- IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Push_Imm32(jit, 0x3F000000);
- IA32_Fadd_Mem32_ESP(jit);
- IA32_Fistp_Mem32_Disp8_Esp(jit, 4);
- IA32_Pop_Reg(jit, REG_EAX);
- IA32_Pop_Reg(jit, AMX_REG_PRI);
-
- IA32_Pop_Reg(jit, REG_ECX);
- IA32_Sar_Rm_1(jit, REG_EAX, MOD_REG);
- IA32_Mov_RmESP_Reg(jit, REG_ECX);
- IA32_Fldcw_Mem16_ESP(jit);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_RoundToFloor(JitWriter *jit)
-{
- //push eax
- //fld [edi]
-
- //fstcw [esp]
- //mov eax, [esp]
- //push eax
-
- //mov [esp+4], 0x7FF
- //fldcw [esp+4]
-
- //push eax
- //fistp [esp]
- //pop eax
-
- //pop ecx
- //mov [esp], ecx
- //fldcw [esp]
- //add esp, 4
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
-
- IA32_Fstcw_Mem16_ESP(jit);
- IA32_Mov_Reg_RmESP(jit, REG_EAX);
- IA32_Push_Reg(jit, REG_EAX);
-
- IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x7FF);
- IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fistp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, REG_EAX);
-
- IA32_Pop_Reg(jit, REG_ECX);
- IA32_Mov_RmESP_Reg(jit, REG_ECX);
- IA32_Fldcw_Mem16_ESP(jit);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_RoundToCeil(JitWriter *jit)
-{
- //push eax
- //fld [edi]
-
- //fstcw [esp]
- //mov eax, [esp]
- //push eax
-
- //mov [esp+4], 0xBFF
- //fldcw [esp+4]
-
- //push eax
- //fistp [esp]
- //pop eax
-
- //pop ecx
- //mov [esp], ecx
- //fldcw [esp]
- //add esp, 4
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
-
- IA32_Fstcw_Mem16_ESP(jit);
- IA32_Mov_Reg_RmESP(jit, REG_EAX);
- IA32_Push_Reg(jit, REG_EAX);
-
- IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xBFF);
- IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fistp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, REG_EAX);
-
- IA32_Pop_Reg(jit, REG_ECX);
- IA32_Mov_RmESP_Reg(jit, REG_ECX);
- IA32_Fldcw_Mem16_ESP(jit);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_RoundToZero(JitWriter *jit)
-{
- //push eax
- //fld [edi]
-
- //fstcw [esp]
- //mov eax, [esp]
- //push eax
-
- //mov [esp+4], 0xFFF
- //fldcw [esp+4]
-
- //push eax
- //fistp [esp]
- //pop eax
-
- //pop ecx
- //mov [esp], ecx
- //fldcw [esp]
- //add esp, 4
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fld_Mem32(jit, AMX_REG_STK);
-
- IA32_Fstcw_Mem16_ESP(jit);
- IA32_Mov_Reg_RmESP(jit, REG_EAX);
- IA32_Push_Reg(jit, REG_EAX);
-
- IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xFFF);
- IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
-
- IA32_Push_Reg(jit, REG_EAX);
- IA32_Fistp_Mem32_ESP(jit);
- IA32_Pop_Reg(jit, REG_EAX);
-
- IA32_Pop_Reg(jit, REG_ECX);
- IA32_Mov_RmESP_Reg(jit, REG_ECX);
- IA32_Fldcw_Mem16_ESP(jit);
- IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- /* Rectify the stack */
- //add edi, 4
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
-}
-
-inline void WriteOp_FloatCompare(JitWriter *jit)
-{
- CompData *data = (CompData *)jit->data;
-
- //fld [edi]
- //fld [edi+4]
- //fucomip st(0), st(1)
- //mov ecx,
- //cmovz eax, [ecx+4]
- //cmovb eax, [ecx+8]
- //cmova eax, [ecx]
- //fstp st(0)
-
- IA32_Fld_Mem32(jit, AMX_REG_STK);
- IA32_Fld_Mem32_Disp8(jit, AMX_REG_STK, 4);
- IA32_Fucomip_ST0_FPUreg(jit, 1);
- IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, (jit_int32_t)jit->outbase + data->jit_rounding_table);
- IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_Z, 4);
- IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_B, 8);
- IA32_CmovCC_Rm(jit, AMX_REG_TMP, CC_A);
- IA32_Fstp_FPUreg(jit, 0);
-
- /* Rectify the stack */
- //add edi, 8
- IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
-}
-
-/*************************************************
- *************************************************
- * JIT PROPER ************************************
- * The rest from now on is the JIT engine *
- *************************************************
- *************************************************/
-
-cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
-{
- sp_native_t *native;
- sp_plugin_t *plugin;
-
- plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
-
- native = &plugin->natives[native_idx];
-
- ctx->n_idx = native_idx;
-
- /* Technically both aren't needed, I guess */
- if (native->status == SP_NATIVE_UNBOUND)
- {
- ctx->n_err = SP_ERROR_INVALID_NATIVE;
- return 0;
- }
-
- return native->pfn(GET_CONTEXT(ctx), params);
-}
-
-cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
-{
- cell_t val;
- sp_native_t *native;
- sp_plugin_t *plugin;
-
- plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
-
- native = &plugin->natives[native_idx];
-
- ctx->n_idx = native_idx;
-
- /* Technically both aren't needed, I guess */
- if (native->status == SP_NATIVE_UNBOUND)
- {
- ctx->n_err = SP_ERROR_INVALID_NATIVE;
- return 0;
- }
-
- plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
- val = native->pfn(GET_CONTEXT(ctx), params);
- plugin->profiler->OnNativeEnd();
-
- return val;
-}
-
-cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
-{
- cell_t save_sp = ctx->sp;
- cell_t save_hp = ctx->hp;
-
- sp_plugin_t *pl = GETPLUGIN(ctx);
-
- ctx->n_idx = native_idx;
-
- if (ctx->hp < (cell_t)pl->data_size)
- {
- ctx->n_err = SP_ERROR_HEAPMIN;
- return 0;
- }
-
- if (ctx->hp + STACK_MARGIN > ctx->sp)
- {
- ctx->n_err = SP_ERROR_STACKLOW;
- return 0;
- }
-
- if ((uint32_t)ctx->sp >= pl->mem_size)
- {
- ctx->n_err = SP_ERROR_STACKMIN;
- return 0;
- }
-
- cell_t result = NativeCallback(ctx, native_idx, params);
-
- if (ctx->n_err != SP_ERROR_NONE)
- {
- return result;
- }
-
- if (save_sp != ctx->sp)
- {
- ctx->n_err = SP_ERROR_STACKLEAK;
- return result;
- }
- else if (save_hp != ctx->hp)
- {
- ctx->n_err = SP_ERROR_HEAPLEAK;
- return result;
- }
-
- return result;
-}
-
-cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
-{
- cell_t save_sp = ctx->sp;
- cell_t save_hp = ctx->hp;
-
- sp_plugin_t *pl = GETPLUGIN(ctx);
-
- ctx->n_idx = native_idx;
-
- if (ctx->hp < (cell_t)pl->data_size)
- {
- ctx->n_err = SP_ERROR_HEAPMIN;
- return 0;
- }
-
- if (ctx->hp + STACK_MARGIN > ctx->sp)
- {
- ctx->n_err = SP_ERROR_STACKLOW;
- return 0;
- }
-
- if ((uint32_t)ctx->sp >= pl->mem_size)
- {
- ctx->n_err = SP_ERROR_STACKMIN;
- return 0;
- }
-
- cell_t result = NativeCallback_Profile(ctx, native_idx, params);
-
- if (ctx->n_err != SP_ERROR_NONE)
- {
- return result;
- }
-
- if (save_sp != ctx->sp)
- {
- ctx->n_err = SP_ERROR_STACKLEAK;
- return result;
- }
- else if (save_hp != ctx->hp)
- {
- ctx->n_err = SP_ERROR_HEAPLEAK;
- return result;
- }
-
- return result;
-}
-
-static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
-{
- return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
-}
-
-jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
-{
- if (jit->outptr)
- {
- CompData *data = (CompData *)jit->data;
- if (relative)
- {
- /* The actual offset is EIP relative. We need to relocate it.
- * Note that this assumes that we're pointing to the next op.
- */
- pcode_offs += jit->get_inputpos();
- }
- /* Offset must always be 1)positive and 2)less than or equal to the codesize */
- assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
- /* Do the lookup in the native dictionary. */
- return *(jitoffs_t *)(data->rebase + pcode_offs);
- }
- else
- {
- return 0;
- }
-}
-
-void WriteErrorRoutines(CompData *data, JitWriter *jit)
-{
- AlignMe(jit);
-
- data->jit_error_divzero = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO);
-
- data->jit_error_stacklow = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_STACKLOW);
-
- data->jit_error_stackmin = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_STACKMIN);
-
- data->jit_error_bounds = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS);
-
- data->jit_error_memaccess = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_MEMACCESS);
-
- data->jit_error_heaplow = jit->get_outputpos();
- Write_SetError(jit, SP_ERROR_HEAPLOW);
-
- 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);
-}
-
-bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
-{
- CompData *data = (CompData *)co;
- sp_plugin_t *plugin = data->plugin;
-
- if (data->plugin == NULL)
- {
- if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
- {
- if (err != NULL)
- {
- *err = SP_ERROR_NOTDEBUGGING;
- }
- co->Abort();
- return false;
- }
-
- data->SetRuntime(prt);
- plugin = data->plugin;
- }
-
- /* The first phase is to browse */
- uint8_t *code = plugin->pcode;
- uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
- OPCODE op;
-
- /*********************************************
- * 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);
- uint32_t codemem = 0;
-
- /* Initial code is written "blank,"
- * so we can check the exact memory usage.
- */
- data->codesize = plugin->pcode_size;
- writer.data = data;
- writer.inbase = (cell_t *)code;
- writer.outptr = NULL;
- writer.outbase = NULL;
- /* Allocate relocation. One extra cell for final CIP. */
- data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t));
-
- /* 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;
-
- /* Write the prologue of the JIT */
- data->jit_return = Write_Execute_Function(jit);
-
- /* Write the SYSREQ.N opcode if we need to */
- if (!(data->inline_level & JIT_INLINE_NATIVES))
- {
- AlignMe(jit);
- data->jit_sysreq_n = jit->get_outputpos();
- WriteOp_Sysreq_N_Function(jit);
- }
-
- /* Write the debug section if we need it */
- if (data->debug == true)
- {
- AlignMe(jit);
- data->jit_break = jit->get_outputpos();
- Write_BreakDebug(jit);
- }
-
- /* Plugins compiled with -O0 will need this! */
- AlignMe(jit);
- data->jit_sysreq_c = jit->get_outputpos();
- WriteOp_Sysreq_C_Function(jit);
-
- AlignMe(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))
- {
- AlignMe(jit);
- data->jit_verify_addr_eax = jit->get_outputpos();
- Write_Check_VerifyAddr(jit, REG_EAX);
-
- AlignMe(jit);
- data->jit_verify_addr_edx = jit->get_outputpos();
- Write_Check_VerifyAddr(jit, REG_EDX);
- }
-
- /* Write the rounding table for the float compare opcode */
- data->jit_rounding_table = jit->get_outputpos();
- Write_RoundingTable(jit);
-
- /* Actual code generation! */
- if (writer.outbase == NULL)
- {
- /* First Pass - find codesize and resolve relocation */
- jitoffs_t pcode_offs;
- jitoffs_t native_offs;
-
- for (; writer.inptr < endptr;)
- {
- /* Store the native offset into the rebase memory.
- * This large chunk of memory lets us do an instant lookup
- * based on an original pcode offset.
- */
- pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
- native_offs = jit->get_outputpos();
- *((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
-
- /* Now read the opcode and continue. */
- op = (OPCODE)writer.read_cell();
-
- /* Patch the floating point natives with our opcodes */
- if (op == OP_SYSREQ_N)
- {
- cell_t idx = writer.read_cell();
- if (data->jit_float_table[idx].found)
- {
- writer.inptr -= 2;
- *(writer.inptr++) = data->jit_float_table[idx].index;
- *(writer.inptr++) = OP_NOP;
- *(writer.inptr++) = OP_NOP;
- op = (OPCODE)data->jit_float_table[idx].index;
- }
- else
- {
- writer.inptr--;
- }
- }
- switch (op)
- {
- #include "opcode_switch.inc"
- }
- /* Check for errors. This should only happen in the first pass. */
- if (data->error_set != SP_ERROR_NONE)
- {
- *err = data->error_set;
- co->Abort();
- return false;
- }
- }
- /* Write these last because error jumps should be unpredicted, and thus forward */
- WriteErrorRoutines(data, jit);
-
- /* Write the final CIP to the last position in the reloc array */
- pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
- native_offs = jit->get_outputpos();
- *((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
-
- /* the total codesize is now known! */
- codemem = writer.get_outputpos();
- writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem);
- engine->SetReadWrite(writer.outbase);
- writer.outptr = writer.outbase;
- /* go back for third pass */
- goto jit_rewind;
- }
- else
- {
- /*******
- * THIRD PASS - write opcode info
- *******/
- for (; writer.inptr < endptr;)
- {
- op = (OPCODE)writer.read_cell();
- switch (op)
- {
- #include "opcode_switch.inc"
- }
- }
- /* Write these last because error jumps should be unpredicted, and thus forward */
- WriteErrorRoutines(data, jit);
-
- engine->SetReadExecute(writer.outbase);
- }
-
- /*************
- * FOURTH PASS - Context Setup
- *************/
-
- /* setup basics */
- sp_context_t *ctx = data->runtime->GetBaseContext()->GetCtx();
-
- /* Clear out any old cruft */
- if (plugin->codebase != NULL)
- {
- FreePluginVars(data->runtime->m_pPlugin);
- FreeContextVars(ctx);
- }
-
- plugin->codebase = writer.outbase;
- plugin->jit_codesize = codemem;
- plugin->jit_memsize = 0;
-
- /* setup memory */
-
- ctx->hp = plugin->data_size;
- ctx->sp = plugin->mem_size - sizeof(cell_t);
- ctx->frm = ctx->sp;
- ctx->n_err = SP_ERROR_NONE;
- ctx->n_idx = SP_ERROR_NONE;
- plugin->prof_flags = data->profile;
- plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
-
- const char *strbase = plugin->info.stringbase;
- uint32_t max, iter;
-
- /* relocate public info */
- if ((max = plugin->info.publics_num))
- {
- plugin->publics = new sp_public_t[max];
- plugin->jit_memsize += sizeof(sp_public_t) * max;
- for (iter=0; iterpublics[iter].name = strbase + plugin->info.publics[iter].name;
- plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
- /* Encode the ID as a straight code offset */
- plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
- }
- }
-
- /* relocate pubvar info */
- if ((max = plugin->info.pubvars_num))
- {
- uint8_t *dat = plugin->memory;
- plugin->pubvars = new sp_pubvar_t[max];
- plugin->jit_memsize += sizeof(sp_pubvar_t) * max;
- for (iter=0; iterpubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
- plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
- }
- }
-
- /* relocate native info */
- if ((max = plugin->info.natives_num))
- {
- plugin->natives = new sp_native_t[max];
- plugin->jit_memsize += sizeof(sp_native_t) * max;
- for (iter=0; iternatives[iter].name = strbase + plugin->info.natives[iter].name;
- plugin->natives[iter].pfn = &InvalidNative;
- plugin->natives[iter].status = SP_NATIVE_UNBOUND;
- plugin->natives[iter].flags = 0;
- plugin->natives[iter].user = NULL;
- }
- }
-
- /**
- * 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;
- plugin->files = new sp_debug_file_t[max];
- plugin->jit_memsize += sizeof(sp_debug_file_t) * max;
- for (iter=0; iterfiles[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
- plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
- }
-
- /* relocate lines */
- max = plugin->debug.lines_num;
- plugin->lines = new sp_debug_line_t[max];
- plugin->jit_memsize += sizeof(sp_debug_line_t) * max;
- for (iter=0; iterlines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
- plugin->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);
-
- max = plugin->debug.syms_num;
- plugin->symbols = new sp_debug_symbol_t[max];
- plugin->jit_memsize += sizeof(sp_debug_symbol_t) * max;
- for (iter=0; itercodestart > data->codesize)
- {
- plugin->symbols[iter].codestart = 0;
- } else {
- plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
- }
- if (sym->codeend > data->codesize)
- {
- plugin->symbols[iter].codeend = data->codesize;
- } else {
- plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
- }
- plugin->symbols[iter].name = strbase + sym->name;
- plugin->symbols[iter].sym = sym;
-
- if (sym->dimcount > 0)
- {
- cursor += sizeof(sp_fdbg_symbol_t);
- arr = (sp_fdbg_arraydim_t *)cursor;
- plugin->symbols[iter].dims = arr;
- cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
- continue;
- }
-
- plugin->symbols[iter].dims = NULL;
- cursor += sizeof(sp_fdbg_symbol_t);
- }
- }
-
- tracker_t *trk = new tracker_t;
- ctx->vm[JITVARS_TRACKER] = trk;
- ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
- ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
- ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
- trk->pBase = (ucell_t *)malloc(1024);
- trk->pCur = trk->pBase;
- trk->size = 1024 / sizeof(cell_t);
-
- plugin->jit_memsize += trk->size;
-
- /* clean up relocation+compilation memory */
- co->Abort();
-
- *err = SP_ERROR_NONE;
-
- return true;
-}
-
-SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
-{
- JitWriter jw;
- JitWriter *jit = &jw;
-
- jw.outbase = NULL;
- jw.outptr = NULL;
- jw.data = NULL;
-
- /* First pass, calculate size */
-rewind:
- /* Align the stack to 16 bytes */
- //push ebx
- //push edi
- //push esi
- //mov edi, [esp+16] ;store ctx
- //mov esi, [esp+20] ;store params
- //mov ebx, esp
- //and esp, 0xFFFFFF0
- //sub esp, 4
- IA32_Push_Reg(jit, REG_EBX);
- IA32_Push_Reg(jit, REG_EDI);
- IA32_Push_Reg(jit, REG_ESI);
- IA32_Mov_Reg_Esp_Disp8(jit, REG_EDI, 16);
- IA32_Mov_Reg_Esp_Disp8(jit, REG_ESI, 20);
- IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
- IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
- IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
-
- //push pData ;push pData
- //push esi ;push params
- //push edi ;push ctx
- //call [callback] ;invoke the meta-callback
- //mov esp, ebx ;restore the stack
- //pop esi ;restore esi
- //pop edi ;restore edi
- //pop ebx ;restore ebx
- //ret ;return
- IA32_Push_Imm32(jit, (jit_int32_t)pData);
- IA32_Push_Reg(jit, REG_ESI);
- IA32_Push_Reg(jit, REG_EDI);
- uint32_t call = IA32_Call_Imm32(jit, 0);
- IA32_Write_Jump32_Abs(jit, call, (void *)callback);
- IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
- IA32_Pop_Reg(jit, REG_ESI);
- IA32_Pop_Reg(jit, REG_EDI);
- IA32_Pop_Reg(jit, REG_EBX);
- IA32_Return(jit);
-
- if (jw.outbase == NULL)
- {
- /* Second pass: Actually write */
- jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos());
- if (!jw.outbase)
- {
- return NULL;
- }
- engine->SetReadWrite(jw.outbase);
- jw.outptr = jw.outbase;
-
- goto rewind;
- }
-
- engine->SetReadExecute(jw.outbase);
-
- return (SPVM_NATIVE_FUNC)jw.outbase;
-}
-
-void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
-{
- engine->FreePageMemory((void *)func);
-}
-
-int JITX86::ContextExecute(sp_plugin_t *pl, 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)pl->codebase;
- return fn(ctx, code_idx, result);
-}
-
-ICompilation *JITX86::StartCompilation()
-{
- CompData *data = new CompData;
-
- data->jit_float_table = NULL;
-
- return data;
-}
-
-void CompData::SetRuntime(BaseRuntime *runtime)
-{
- plugin = runtime->m_pPlugin;
-
- uint32_t max_natives = plugin->info.natives_num;
- const char *strbase = plugin->info.stringbase;
-
- this->runtime = runtime;
-
- inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
- error_set = SP_ERROR_NONE;
-
- jit_float_table = new floattbl_t[max_natives];
- for (uint32_t i=0; iinfo.natives[i].name;
- if (!strcmp(name, "FloatAbs"))
- {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FABS;
- } else if (!strcmp(name, "FloatAdd")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOATADD;
- } else if (!strcmp(name, "FloatSub")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOATSUB;
- } else if (!strcmp(name, "FloatMul")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOATMUL;
- } else if (!strcmp(name, "FloatDiv")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOATDIV;
- } else if (!strcmp(name, "float")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOAT;
- } else if (!strcmp(name, "FloatCompare")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_FLOATCMP;
- } else if (!strcmp(name, "RoundToZero")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_RND_TO_ZERO;
- } else if (!strcmp(name, "RoundToCeil")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_RND_TO_CEIL;
- } else if (!strcmp(name, "RoundToFloor")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_RND_TO_FLOOR;
- } else if (!strcmp(name, "RoundToNearest")) {
- jit_float_table[i].found = true;
- jit_float_table[i].index = OP_RND_TO_NEAREST;
- }
- }
-}
-
-ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
-{
- CompData *data = new CompData;
-
- data->SetRuntime(runtime);
-
- return data;
-}
-
-void CompData::Abort()
-{
- if (rebase)
- {
- engine->BaseFree(rebase);
- }
- delete [] jit_float_table;
- delete this;
-}
-
-void JITX86::FreeContextVars(sp_context_t *ctx)
-{
- free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
- delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
-}
-
-void JITX86::FreePluginVars(sp_plugin_t *pl)
-{
- delete [] pl->files;
- delete [] pl->lines;
- delete [] pl->natives;
- delete [] pl->publics;
- delete [] pl->pubvars;
- delete [] pl->symbols;
-
- if (pl->codebase != NULL)
- {
- g_engine1.FreePageMemory(pl->codebase);
- pl->codebase = NULL;
- }
-
- pl->files = NULL;
- pl->lines = NULL;
- pl->natives = NULL;
- pl->publics = NULL;
- pl->pubvars = NULL;
- pl->symbols = NULL;
-}
-
-bool CompData::SetOption(const char *key, const char *val)
-{
- if (strcmp(key, SP_JITCONF_DEBUG) == 0)
- {
- if ((atoi(val) == 1) || !strcmp(val, "yes"))
- {
- debug = true;
- } else {
- debug = false;
- }
- if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
- {
- debug = false;
- return false;
- }
- return true;
- }
- else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
- {
- profile = atoi(val);
-
- /** Callbacks must be profiled to profile functions! */
- if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
- {
- profile |= SP_PROF_CALLBACKS;
- }
-
- return true;
- }
-
- return false;
-}
-