sourcepawn/jit/x86/jit_x86.cpp
branchrefac-jit
changeset 2284 026da5437111
parent 2192 7602d7fb60d9
child 2288 15c77b21589a
     1.1 --- a/sourcepawn/jit/x86/jit_x86.cpp	Fri Jul 11 06:51:21 2008 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,3049 +0,0 @@
     1.4 -/**
     1.5 - * vim: set ts=4 :
     1.6 - * =============================================================================
     1.7 - * SourceMod
     1.8 - * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     1.9 - * =============================================================================
    1.10 - *
    1.11 - * This program is free software; you can redistribute it and/or modify it under
    1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
    1.13 - * Free Software Foundation.
    1.14 - * 
    1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
    1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 - * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    1.18 - * details.
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License along with
    1.21 - * this program.  If not, see <http://www.gnu.org/licenses/>.
    1.22 - *
    1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
    1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
    1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    1.26 - * by the Valve Corporation.  You must obey the GNU General Public License in
    1.27 - * all respects for all other code used.  Additionally, AlliedModders LLC grants
    1.28 - * this exception to all derivative works.  AlliedModders LLC defines further
    1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    1.30 - * or <http://www.sourcemod.net/license.php>.
    1.31 - *
    1.32 - * Version: $Id$
    1.33 - */
    1.34 -
    1.35 -#include <string.h>
    1.36 -#include <stdlib.h>
    1.37 -#include <assert.h>
    1.38 -#include "jit_x86.h"
    1.39 -#include "opcode_helpers.h"
    1.40 -#include <x86_macros.h>
    1.41 -#include "../jit_version.h"
    1.42 -#include "../sp_vm_engine.h"
    1.43 -#include "../engine2.h"
    1.44 -#include "../BaseRuntime.h"
    1.45 -#include "../sp_vm_basecontext.h"
    1.46 -
    1.47 -#if defined USE_UNGEN_OPCODES
    1.48 -#include "ungen_opcodes.h"
    1.49 -#endif
    1.50 -
    1.51 -JITX86 g_Jit1;
    1.52 -ISourcePawnEngine *engine = &g_engine1;
    1.53 -
    1.54 -inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
    1.55 -{
    1.56 -	return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
    1.57 -}
    1.58 -
    1.59 -inline void WriteOp_Move_Pri(JitWriter *jit)
    1.60 -{
    1.61 -	//mov eax, edx
    1.62 -	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
    1.63 -}
    1.64 -
    1.65 -inline void WriteOp_Move_Alt(JitWriter *jit)
    1.66 -{
    1.67 -	//mov edx, eax
    1.68 -	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
    1.69 -}
    1.70 -
    1.71 -inline void WriteOp_Xchg(JitWriter *jit)
    1.72 -{
    1.73 -	//xchg eax, edx
    1.74 -	IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
    1.75 -}
    1.76 -
    1.77 -inline void WriteOp_Push(JitWriter *jit)
    1.78 -{
    1.79 -	//push stack, DAT offset based
    1.80 -	//sub edi, 4
    1.81 -	//mov ecx, [ebp+<val>]
    1.82 -	//mov [edi], ecx
    1.83 -	cell_t val = jit->read_cell();
    1.84 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
    1.85 -	//optimize encoding a bit...
    1.86 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
    1.87 -	{
    1.88 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
    1.89 -	} else {
    1.90 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
    1.91 -	}
    1.92 -	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
    1.93 -}
    1.94 -
    1.95 -inline void WriteOp_Push_C(JitWriter *jit)
    1.96 -{
    1.97 -	//push stack
    1.98 -	//mov [edi-4], <val>
    1.99 -	//sub edi, 4
   1.100 -	cell_t val = jit->read_cell();
   1.101 -	IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
   1.102 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.103 -}
   1.104 -
   1.105 -inline void WriteOp_Zero(JitWriter *jit)
   1.106 -{
   1.107 -	//mov [ebp+<val>], 0
   1.108 -	cell_t val = jit->read_cell();
   1.109 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.110 -	{
   1.111 -		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val);
   1.112 -	} else {
   1.113 -		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
   1.114 -	}
   1.115 -}
   1.116 -
   1.117 -inline void WriteOp_Zero_S(JitWriter *jit)
   1.118 -{
   1.119 -	//mov [ebx+<val>], 0
   1.120 -	cell_t val = jit->read_cell();
   1.121 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.122 -	{
   1.123 -		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val);
   1.124 -	} else {
   1.125 -		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
   1.126 -	}
   1.127 -}
   1.128 -
   1.129 -inline void WriteOp_Push_S(JitWriter *jit)
   1.130 -{
   1.131 -	//push stack, FRM offset based
   1.132 -	//sub edi, 4
   1.133 -	//mov ecx, [ebx+<val>]
   1.134 -	//mov [edi], ecx
   1.135 -	cell_t val = jit->read_cell();
   1.136 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.137 -	//optimize encoding a bit...
   1.138 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.139 -	{
   1.140 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
   1.141 -	} else {
   1.142 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
   1.143 -	}
   1.144 -	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
   1.145 -}
   1.146 -
   1.147 -inline void WriteOp_Push_Pri(JitWriter *jit)
   1.148 -{
   1.149 -	//mov [edi-4], eax
   1.150 -	//sub edi, 4
   1.151 -	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
   1.152 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.153 -}
   1.154 -
   1.155 -inline void WriteOp_Push_Alt(JitWriter *jit)
   1.156 -{
   1.157 -	//mov [edi-4], edx
   1.158 -	//sub edi, 4
   1.159 -	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
   1.160 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.161 -}
   1.162 -
   1.163 -inline void WriteOp_Push2_C(JitWriter *jit)
   1.164 -{
   1.165 -	Macro_PushN_C(jit, 2);
   1.166 -}
   1.167 -
   1.168 -inline void WriteOp_Push3_C(JitWriter *jit)
   1.169 -{
   1.170 -	Macro_PushN_C(jit, 3);
   1.171 -}
   1.172 -
   1.173 -inline void WriteOp_Push4_C(JitWriter *jit)
   1.174 -{
   1.175 -	Macro_PushN_C(jit, 4);
   1.176 -}
   1.177 -
   1.178 -inline void WriteOp_Push5_C(JitWriter *jit)
   1.179 -{
   1.180 -	Macro_PushN_C(jit, 5);
   1.181 -}
   1.182 -
   1.183 -inline void WriteOp_Push2_Adr(JitWriter *jit)
   1.184 -{
   1.185 -	Macro_PushN_Addr(jit, 2);
   1.186 -}
   1.187 -
   1.188 -inline void WriteOp_Push3_Adr(JitWriter *jit)
   1.189 -{
   1.190 -	Macro_PushN_Addr(jit, 3);
   1.191 -}
   1.192 -
   1.193 -inline void WriteOp_Push4_Adr(JitWriter *jit)
   1.194 -{
   1.195 -	Macro_PushN_Addr(jit, 4);
   1.196 -}
   1.197 -
   1.198 -inline void WriteOp_Push5_Adr(JitWriter *jit)
   1.199 -{
   1.200 -	Macro_PushN_Addr(jit, 5);
   1.201 -}
   1.202 -
   1.203 -inline void WriteOp_Push2_S(JitWriter *jit)
   1.204 -{
   1.205 -	Macro_PushN_S(jit, 2);
   1.206 -}
   1.207 -
   1.208 -inline void WriteOp_Push3_S(JitWriter *jit)
   1.209 -{
   1.210 -	Macro_PushN_S(jit, 3);
   1.211 -}
   1.212 -
   1.213 -inline void WriteOp_Push4_S(JitWriter *jit)
   1.214 -{
   1.215 -	Macro_PushN_S(jit, 4);
   1.216 -}
   1.217 -
   1.218 -inline void WriteOp_Push5_S(JitWriter *jit)
   1.219 -{
   1.220 -	Macro_PushN_S(jit, 5);
   1.221 -}
   1.222 -
   1.223 -inline void WriteOp_Push5(JitWriter *jit)
   1.224 -{
   1.225 -	Macro_PushN(jit, 5);
   1.226 -}
   1.227 -
   1.228 -inline void WriteOp_Push4(JitWriter *jit)
   1.229 -{
   1.230 -	Macro_PushN(jit, 4);
   1.231 -}
   1.232 -
   1.233 -inline void WriteOp_Push3(JitWriter *jit)
   1.234 -{
   1.235 -	Macro_PushN(jit, 3);
   1.236 -}
   1.237 -
   1.238 -inline void WriteOp_Push2(JitWriter *jit)
   1.239 -{
   1.240 -	Macro_PushN(jit, 2);
   1.241 -}
   1.242 -
   1.243 -inline void WriteOp_Zero_Pri(JitWriter *jit)
   1.244 -{
   1.245 -	//xor eax, eax
   1.246 -	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
   1.247 -}
   1.248 -
   1.249 -inline void WriteOp_Zero_Alt(JitWriter *jit)
   1.250 -{
   1.251 -	//xor edx, edx
   1.252 -	IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
   1.253 -}
   1.254 -
   1.255 -inline void WriteOp_Add(JitWriter *jit)
   1.256 -{
   1.257 -	//add eax, edx
   1.258 -	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.259 -}
   1.260 -
   1.261 -inline void WriteOp_Sub(JitWriter *jit)
   1.262 -{
   1.263 -	//sub eax, edx
   1.264 -	IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.265 -}
   1.266 -
   1.267 -inline void WriteOp_Sub_Alt(JitWriter *jit)
   1.268 -{
   1.269 -	//neg eax
   1.270 -	//add eax, edx
   1.271 -	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
   1.272 -	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.273 -}
   1.274 -
   1.275 -inline void WriteOp_Proc(JitWriter *jit)
   1.276 -{
   1.277 -	CompData *co = (CompData *)jit->data;
   1.278 -
   1.279 -	/* Specialized code to align this taking in account the function magic number */
   1.280 -	jitoffs_t cur_offs = jit->get_outputpos();
   1.281 -	jitoffs_t offset = ((cur_offs & 0xFFFFFFF8) + 8) - cur_offs;
   1.282 -	if (!((offset + cur_offs) & 8))
   1.283 -	{
   1.284 -		offset += 8;
   1.285 -	}
   1.286 -	if (offset)
   1.287 -	{
   1.288 -		for (jit_uint32_t i=0; i<offset; i++)
   1.289 -		{
   1.290 -			jit->write_ubyte(IA32_INT3);
   1.291 -		}
   1.292 -	}
   1.293 -
   1.294 -	/* Write the info struct about this function */
   1.295 -	jit->write_uint32(JIT_FUNCMAGIC);
   1.296 -	jit->write_uint32(co->func_idx);
   1.297 -
   1.298 -	/* Now we have to backpatch our reloction offset! */
   1.299 -	{
   1.300 -		jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
   1.301 -		jitcode_t rebase = ((CompData *)jit->data)->rebase;
   1.302 -		*(jitoffs_t *)((unsigned char  *)rebase + offs) = jit->get_outputpos();
   1.303 -	}
   1.304 -
   1.305 -	/* Lastly, if we're writing, keep track of the function count */
   1.306 -	if (jit->outbase)
   1.307 -	{
   1.308 -		co->func_idx++;
   1.309 -	}
   1.310 -
   1.311 -	//push old frame on stack:
   1.312 -	//mov ecx, [esi+frm]
   1.313 -	//mov [edi-4], ecx
   1.314 -	//sub edi, 8			;extra un-used slot for non-existant CIP
   1.315 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
   1.316 -	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
   1.317 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
   1.318 -	//save frame:
   1.319 -	//mov ecx, edi			- get new frame
   1.320 -	//mov ebx, edi			- store frame back
   1.321 -	//sub ecx, ebp			- relocate local frame
   1.322 -	//mov [esi+frm], ecx
   1.323 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
   1.324 -	IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
   1.325 -	IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
   1.326 -	IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG);
   1.327 -}
   1.328 -
   1.329 -inline void WriteOp_Lidx_B(JitWriter *jit)
   1.330 -{
   1.331 -	cell_t val = jit->read_cell();
   1.332 -	//shl eax, <val>
   1.333 -	//add eax, edx
   1.334 -	//mov eax, [ebp+eax]
   1.335 -	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
   1.336 -	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.337 -	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
   1.338 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
   1.339 -}
   1.340 -
   1.341 -inline void WriteOp_Idxaddr_B(JitWriter *jit)
   1.342 -{
   1.343 -	//shl eax, <val>
   1.344 -	//add eax, edx
   1.345 -	cell_t val = jit->read_cell();
   1.346 -	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
   1.347 -	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.348 -}
   1.349 -
   1.350 -inline void WriteOp_Shl(JitWriter *jit)
   1.351 -{
   1.352 -	//mov ecx, edx
   1.353 -	//shl eax, cl
   1.354 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
   1.355 -	IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
   1.356 -}
   1.357 -
   1.358 -inline void WriteOp_Shr(JitWriter *jit)
   1.359 -{
   1.360 -	//mov ecx, edx
   1.361 -	//shr eax, cl
   1.362 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
   1.363 -	IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
   1.364 -}
   1.365 -
   1.366 -inline void WriteOp_Sshr(JitWriter *jit)
   1.367 -{
   1.368 -	//mov ecx, edx
   1.369 -	//sar eax, cl
   1.370 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
   1.371 -	IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
   1.372 -}
   1.373 -
   1.374 -inline void WriteOp_Shl_C_Pri(JitWriter *jit)
   1.375 -{
   1.376 -	//shl eax, <val>
   1.377 -	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
   1.378 -	if (val == 1)
   1.379 -	{
   1.380 -		IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG);
   1.381 -	} else {
   1.382 -		IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
   1.383 -	}
   1.384 -}
   1.385 -
   1.386 -inline void WriteOp_Shl_C_Alt(JitWriter *jit)
   1.387 -{
   1.388 -	//shl edx, <val>
   1.389 -	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
   1.390 -	if (val == 1)
   1.391 -	{
   1.392 -		IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG);
   1.393 -	} else {
   1.394 -		IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
   1.395 -	}
   1.396 -}
   1.397 -
   1.398 -inline void WriteOp_Shr_C_Pri(JitWriter *jit)
   1.399 -{
   1.400 -	//shr eax, <val>
   1.401 -	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
   1.402 -	if (val == 1)
   1.403 -	{
   1.404 -		IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG);
   1.405 -	} else {
   1.406 -		IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
   1.407 -	}
   1.408 -}
   1.409 -
   1.410 -inline void WriteOp_Shr_C_Alt(JitWriter *jit)
   1.411 -{
   1.412 -	//shr edx, <val>
   1.413 -	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
   1.414 -	if (val == 1)
   1.415 -	{
   1.416 -		IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG);
   1.417 -	} else {
   1.418 -		IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
   1.419 -	}
   1.420 -}
   1.421 -
   1.422 -inline void WriteOp_SMul(JitWriter *jit)
   1.423 -{
   1.424 -	//mov ecx, edx
   1.425 -	//imul edx
   1.426 -	//mov edx, ecx
   1.427 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
   1.428 -	IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
   1.429 -	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
   1.430 -}
   1.431 -
   1.432 -inline void WriteOp_Not(JitWriter *jit)
   1.433 -{
   1.434 -	//test eax, eax
   1.435 -	//mov eax, 0
   1.436 -	//sete al
   1.437 -	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
   1.438 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.439 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
   1.440 -}
   1.441 -
   1.442 -inline void WriteOp_Neg(JitWriter *jit)
   1.443 -{
   1.444 -	//neg eax
   1.445 -	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
   1.446 -}
   1.447 -
   1.448 -inline void WriteOp_Xor(JitWriter *jit)
   1.449 -{
   1.450 -	//xor eax, edx
   1.451 -	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.452 -}
   1.453 -
   1.454 -inline void WriteOp_Or(JitWriter *jit)
   1.455 -{
   1.456 -	//or eax, edx
   1.457 -	IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.458 -}
   1.459 -
   1.460 -inline void WriteOp_And(JitWriter *jit)
   1.461 -{
   1.462 -	//and eax, edx
   1.463 -	IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.464 -}
   1.465 -
   1.466 -inline void WriteOp_Invert(JitWriter *jit)
   1.467 -{
   1.468 -	//not eax
   1.469 -	IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
   1.470 -}
   1.471 -
   1.472 -inline void WriteOp_Add_C(JitWriter *jit)
   1.473 -{
   1.474 -	//add eax, <val>
   1.475 -	cell_t val = jit->read_cell();
   1.476 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.477 -		IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
   1.478 -	else
   1.479 -		IA32_Add_Eax_Imm32(jit, val);
   1.480 -}
   1.481 -
   1.482 -inline void WriteOp_SMul_C(JitWriter *jit)
   1.483 -{
   1.484 -	//imul eax, <val>
   1.485 -	cell_t val = jit->read_cell();
   1.486 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.487 -		IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
   1.488 -	else
   1.489 -		IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
   1.490 -}
   1.491 -
   1.492 -inline void WriteOp_Sign_Pri(JitWriter *jit)
   1.493 -{
   1.494 -	//shl eax, 24
   1.495 -	//sar eax, 24
   1.496 -	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
   1.497 -	IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
   1.498 -}
   1.499 -
   1.500 -inline void WriteOp_Sign_Alt(JitWriter *jit)
   1.501 -{
   1.502 -	//shl edx, 24
   1.503 -	//sar edx, 24
   1.504 -	IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
   1.505 -	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
   1.506 -}
   1.507 -
   1.508 -inline void WriteOp_Eq(JitWriter *jit)
   1.509 -{
   1.510 -	//cmp eax, edx	; PRI == ALT ?
   1.511 -	//mov eax, 0
   1.512 -	//sete al
   1.513 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.514 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.515 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
   1.516 -}
   1.517 -
   1.518 -inline void WriteOp_Neq(JitWriter *jit)
   1.519 -{
   1.520 -	//cmp eax, edx	; PRI != ALT ?
   1.521 -	//mov eax, 0
   1.522 -	//setne al
   1.523 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.524 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.525 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
   1.526 -}
   1.527 -
   1.528 -inline void WriteOp_Sless(JitWriter *jit)
   1.529 -{
   1.530 -	//cmp eax, edx	; PRI < ALT ? (signed)
   1.531 -	//mov eax, 0
   1.532 -	//setl al
   1.533 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.534 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.535 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L);
   1.536 -}
   1.537 -
   1.538 -inline void WriteOp_Sleq(JitWriter *jit)
   1.539 -{
   1.540 -	//cmp eax, edx	; PRI <= ALT ? (signed)
   1.541 -	//mov eax, 0
   1.542 -	//setle al
   1.543 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.544 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.545 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE);
   1.546 -}
   1.547 -
   1.548 -inline void WriteOp_Sgrtr(JitWriter *jit)
   1.549 -{
   1.550 -	//cmp eax, edx	; PRI > ALT ? (signed)
   1.551 -	//mov eax, 0
   1.552 -	//setg al
   1.553 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.554 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.555 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G);
   1.556 -}
   1.557 -
   1.558 -inline void WriteOp_Sgeq(JitWriter *jit)
   1.559 -{
   1.560 -	//cmp eax, edx	; PRI >= ALT ? (signed)
   1.561 -	//mov eax, 0
   1.562 -	//setge al
   1.563 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
   1.564 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.565 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE);
   1.566 -}
   1.567 -
   1.568 -inline void WriteOp_Eq_C_Pri(JitWriter *jit)
   1.569 -{
   1.570 -	//cmp eax, <val>   ; PRI == value ?
   1.571 -	//mov eax, 0
   1.572 -	//sete al
   1.573 -	cell_t val = jit->read_cell();
   1.574 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.575 -		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
   1.576 -	else
   1.577 -		IA32_Cmp_Eax_Imm32(jit, val);
   1.578 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
   1.579 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
   1.580 -}
   1.581 -
   1.582 -inline void WriteOp_Eq_C_Alt(JitWriter *jit)
   1.583 -{
   1.584 -	//xor eax, eax
   1.585 -	//cmp edx, <val>   ; ALT == value ?
   1.586 -	//sete al
   1.587 -	cell_t val = jit->read_cell();
   1.588 -	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
   1.589 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.590 -		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
   1.591 -	else
   1.592 -		IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
   1.593 -	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
   1.594 -}
   1.595 -
   1.596 -inline void WriteOp_Inc_Pri(JitWriter *jit)
   1.597 -{
   1.598 -	//add eax, 1
   1.599 -	IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
   1.600 -}
   1.601 -
   1.602 -inline void WriteOp_Inc_Alt(JitWriter *jit)
   1.603 -{
   1.604 -	//add edx, 1
   1.605 -	IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
   1.606 -}
   1.607 -
   1.608 -inline void WriteOp_Inc(JitWriter *jit)
   1.609 -{
   1.610 -	//add [ebp+<val>], 1
   1.611 -	cell_t val = jit->read_cell();
   1.612 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.613 -		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
   1.614 -	else
   1.615 -		IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
   1.616 -}
   1.617 -
   1.618 -inline void WriteOp_Inc_S(JitWriter *jit)
   1.619 -{
   1.620 -	//add [ebx+<val>], 1
   1.621 -	cell_t val = jit->read_cell();
   1.622 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.623 -		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
   1.624 -	else
   1.625 -		IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
   1.626 -}
   1.627 -
   1.628 -inline void WriteOp_Inc_I(JitWriter *jit)
   1.629 -{
   1.630 -	//add [ebp+eax], 1
   1.631 -	IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
   1.632 -}
   1.633 -
   1.634 -inline void WriteOp_Dec_Pri(JitWriter *jit)
   1.635 -{
   1.636 -	//sub eax, 1
   1.637 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
   1.638 -}
   1.639 -
   1.640 -inline void WriteOp_Dec_Alt(JitWriter *jit)
   1.641 -{
   1.642 -	//sub edx, 1
   1.643 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
   1.644 -}
   1.645 -
   1.646 -inline void WriteOp_Dec(JitWriter *jit)
   1.647 -{
   1.648 -	//sub [ebp+<val>], 1
   1.649 -	cell_t val = jit->read_cell();
   1.650 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.651 -	{
   1.652 -		IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
   1.653 -	} else {
   1.654 -		IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
   1.655 -	}
   1.656 -}
   1.657 -
   1.658 -inline void WriteOp_Dec_S(JitWriter *jit)
   1.659 -{
   1.660 -	//sub [ebx+<val>], 1
   1.661 -	cell_t val = jit->read_cell();
   1.662 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.663 -	{
   1.664 -		IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
   1.665 -	} else {
   1.666 -		IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
   1.667 -	}
   1.668 -}
   1.669 -
   1.670 -inline void WriteOp_Dec_I(JitWriter *jit)
   1.671 -{
   1.672 -	//sub [ebp+eax], 1
   1.673 -	IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
   1.674 -}
   1.675 -
   1.676 -inline void WriteOp_Load_Pri(JitWriter *jit)
   1.677 -{
   1.678 -	//mov eax, [ebp+<val>]
   1.679 -	cell_t val = jit->read_cell();
   1.680 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.681 -	{
   1.682 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
   1.683 -	} else {
   1.684 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
   1.685 -	}
   1.686 -}
   1.687 -
   1.688 -inline void WriteOp_Load_Alt(JitWriter *jit)
   1.689 -{
   1.690 -	//mov edx, [ebp+<val>]
   1.691 -	cell_t val = jit->read_cell();
   1.692 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.693 -	{
   1.694 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
   1.695 -	} else {
   1.696 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
   1.697 -	}
   1.698 -}
   1.699 -
   1.700 -inline void WriteOp_Load_S_Pri(JitWriter *jit)
   1.701 -{
   1.702 -	//mov eax, [ebx+<val>]
   1.703 -	cell_t val = jit->read_cell();
   1.704 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.705 -	{
   1.706 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
   1.707 -	} else {
   1.708 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
   1.709 -	}
   1.710 -}
   1.711 -
   1.712 -inline void WriteOp_Load_S_Alt(JitWriter *jit)
   1.713 -{
   1.714 -	//mov edx, [ebx+<val>]
   1.715 -	cell_t val = jit->read_cell();
   1.716 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.717 -	{
   1.718 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
   1.719 -	} else {
   1.720 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
   1.721 -	}
   1.722 -}
   1.723 -
   1.724 -inline void WriteOp_Lref_Pri(JitWriter *jit)
   1.725 -{
   1.726 -	//mov eax, [ebp+<val>]
   1.727 -	//mov eax, [ebp+eax]
   1.728 -	cell_t val = jit->read_cell();
   1.729 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.730 -	{
   1.731 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
   1.732 -	} else {
   1.733 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
   1.734 -	}
   1.735 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
   1.736 -}
   1.737 -
   1.738 -inline void WriteOp_Lref_Alt(JitWriter *jit)
   1.739 -{
   1.740 -	//mov edx, [ebp+<val>]
   1.741 -	//mov edx, [ebp+edx]
   1.742 -	cell_t val = jit->read_cell();
   1.743 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.744 -	{
   1.745 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
   1.746 -	} else {
   1.747 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
   1.748 -	}
   1.749 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
   1.750 -}
   1.751 -
   1.752 -inline void WriteOp_Lref_S_Pri(JitWriter *jit)
   1.753 -{
   1.754 -	//mov eax, [ebx+<val>]
   1.755 -	//mov eax, [ebp+eax]
   1.756 -	cell_t val = jit->read_cell();
   1.757 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.758 -	{
   1.759 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
   1.760 -	} else {
   1.761 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
   1.762 -	}
   1.763 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
   1.764 -}
   1.765 -
   1.766 -inline void WriteOp_Lref_S_Alt(JitWriter *jit)
   1.767 -{
   1.768 -	//mov edx, [ebx+<val>]
   1.769 -	//mov edx, [ebp+edx]
   1.770 -	cell_t val = jit->read_cell();
   1.771 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.772 -	{
   1.773 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
   1.774 -	} else {
   1.775 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
   1.776 -	}
   1.777 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
   1.778 -}
   1.779 -
   1.780 -inline void WriteOp_Const_Pri(JitWriter *jit)
   1.781 -{
   1.782 -	//mov eax, <val>
   1.783 -	cell_t val = jit->read_cell();
   1.784 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
   1.785 -}
   1.786 -
   1.787 -inline void WriteOp_Const_Alt(JitWriter *jit)
   1.788 -{
   1.789 -	//mov edx, <val>
   1.790 -	cell_t val = jit->read_cell();
   1.791 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
   1.792 -}
   1.793 -
   1.794 -inline void WriteOp_Addr_Pri(JitWriter *jit)
   1.795 -{
   1.796 -	//mov eax, [esi+frm]
   1.797 -	//add eax, <val>
   1.798 -	cell_t val = jit->read_cell();
   1.799 -	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
   1.800 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.801 -	{
   1.802 -		IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
   1.803 -	} else {
   1.804 -		IA32_Add_Eax_Imm32(jit, val);
   1.805 -	}
   1.806 -}
   1.807 -
   1.808 -inline void WriteOp_Addr_Alt(JitWriter *jit)
   1.809 -{
   1.810 -	//mov edx, [esi+frm]
   1.811 -	//add edx, <val>
   1.812 -	cell_t val = jit->read_cell();
   1.813 -	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG);
   1.814 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.815 -	{
   1.816 -		IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
   1.817 -	} else {
   1.818 -		IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
   1.819 -	}
   1.820 -}
   1.821 -
   1.822 -inline void WriteOp_Stor_Pri(JitWriter *jit)
   1.823 -{
   1.824 -	//mov [ebp+<val>], eax
   1.825 -	cell_t val = jit->read_cell();
   1.826 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.827 -	{
   1.828 -		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
   1.829 -	} else {
   1.830 -		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
   1.831 -	}
   1.832 -}
   1.833 -
   1.834 -inline void WriteOp_Stor_Alt(JitWriter *jit)
   1.835 -{
   1.836 -	//mov [ebp+<val>], edx
   1.837 -	cell_t val = jit->read_cell();
   1.838 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.839 -	{
   1.840 -		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
   1.841 -	} else {
   1.842 -		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
   1.843 -	}
   1.844 -}
   1.845 -
   1.846 -inline void WriteOp_Stor_S_Pri(JitWriter *jit)
   1.847 -{
   1.848 -	//mov [ebx+<val>], eax
   1.849 -	cell_t val = jit->read_cell();
   1.850 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.851 -	{
   1.852 -		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
   1.853 -	} else {
   1.854 -		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
   1.855 -	}
   1.856 -}
   1.857 -
   1.858 -inline void WriteOp_Stor_S_Alt(JitWriter *jit)
   1.859 -{
   1.860 -	//mov [ebx+<val>], edx
   1.861 -	cell_t val = jit->read_cell();
   1.862 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.863 -	{
   1.864 -		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
   1.865 -	} else {
   1.866 -		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
   1.867 -	}
   1.868 -}
   1.869 -
   1.870 -inline void WriteOp_Idxaddr(JitWriter *jit)
   1.871 -{
   1.872 -	//lea eax, [edx+4*eax]
   1.873 -	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
   1.874 -}
   1.875 -
   1.876 -inline void WriteOp_Sref_Pri(JitWriter *jit)
   1.877 -{
   1.878 -	//mov ecx, [ebp+<val>]
   1.879 -	//mov [ebp+ecx], eax
   1.880 -	cell_t val = jit->read_cell();
   1.881 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.882 -	{
   1.883 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
   1.884 -	} else {
   1.885 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
   1.886 -	}
   1.887 -	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
   1.888 -}
   1.889 -
   1.890 -inline void WriteOp_Sref_Alt(JitWriter *jit)
   1.891 -{
   1.892 -	//mov ecx, [ebp+<val>]
   1.893 -	//mov [ebp+ecx], edx
   1.894 -	cell_t val = jit->read_cell();
   1.895 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.896 -	{
   1.897 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
   1.898 -	} else {
   1.899 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
   1.900 -	}
   1.901 -	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
   1.902 -}
   1.903 -
   1.904 -inline void WriteOp_Sref_S_Pri(JitWriter *jit)
   1.905 -{
   1.906 -	//mov ecx, [ebx+<val>]
   1.907 -	//mov [ebp+ecx], eax
   1.908 -	cell_t val = jit->read_cell();
   1.909 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.910 -	{
   1.911 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
   1.912 -	} else {
   1.913 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
   1.914 -	}
   1.915 -	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
   1.916 -}
   1.917 -
   1.918 -inline void WriteOp_Sref_S_Alt(JitWriter *jit)
   1.919 -{
   1.920 -	//mov ecx, [ebx+<val>]
   1.921 -	//mov [ebp+ecx], edx
   1.922 -	cell_t val = jit->read_cell();
   1.923 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.924 -	{
   1.925 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
   1.926 -	} else {
   1.927 -		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
   1.928 -	}
   1.929 -	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
   1.930 -}
   1.931 -
   1.932 -inline void WriteOp_Pop_Pri(JitWriter *jit)
   1.933 -{
   1.934 -	//mov eax, [edi]
   1.935 -	//add edi, 4
   1.936 -	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
   1.937 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.938 -}
   1.939 -
   1.940 -inline void WriteOp_Pop_Alt(JitWriter *jit)
   1.941 -{
   1.942 -	//mov edx, [edi]
   1.943 -	//add edi, 4
   1.944 -	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
   1.945 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.946 -}
   1.947 -
   1.948 -inline void WriteOp_Swap_Pri(JitWriter *jit)
   1.949 -{
   1.950 -	//add [edi], eax
   1.951 -	//sub eax, [edi]
   1.952 -	//add [edi], eax
   1.953 -	//neg eax
   1.954 -	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
   1.955 -	IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
   1.956 -	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
   1.957 -	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
   1.958 -}
   1.959 -
   1.960 -inline void WriteOp_Swap_Alt(JitWriter *jit)
   1.961 -{
   1.962 -	//add [edi], edx
   1.963 -	//sub edx, [edi]
   1.964 -	//add [edi], edx
   1.965 -	//neg edx
   1.966 -	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
   1.967 -	IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
   1.968 -	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
   1.969 -	IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
   1.970 -}
   1.971 -
   1.972 -inline void WriteOp_PushAddr(JitWriter *jit)
   1.973 -{
   1.974 -	//mov ecx, [esi+frm]	;get address (offset from frame)
   1.975 -	//sub edi, 4
   1.976 -	//add ecx, <val>
   1.977 -	//mov [edi], ecx
   1.978 -	cell_t val = jit->read_cell();
   1.979 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
   1.980 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
   1.981 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
   1.982 -	{
   1.983 -		IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
   1.984 -	} else {
   1.985 -		IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
   1.986 -	}
   1.987 -	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
   1.988 -}
   1.989 -
   1.990 -inline void WriteOp_Movs(JitWriter *jit)
   1.991 -{
   1.992 -	//cld
   1.993 -	//push esi
   1.994 -	//push edi
   1.995 -	//lea esi, [ebp+eax]
   1.996 -	//lea edi, [ebp+edx]
   1.997 -	//if dword:
   1.998 -	// mov ecx, dword
   1.999 -	// rep movsd
  1.1000 -	//if byte:
  1.1001 -	// mov ecx, byte
  1.1002 -	// rep movsb
  1.1003 -	//pop edi
  1.1004 -	//pop esi
  1.1005 -	cell_t val = jit->read_cell();
  1.1006 -	unsigned int dwords = val >> 2;
  1.1007 -	unsigned int bytes = val & 0x3;
  1.1008 -
  1.1009 -	IA32_Cld(jit);
  1.1010 -	IA32_Push_Reg(jit, REG_ESI);
  1.1011 -	IA32_Push_Reg(jit, REG_EDI);
  1.1012 -	IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
  1.1013 -	IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
  1.1014 -	if (dwords)
  1.1015 -	{
  1.1016 -		IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
  1.1017 -		IA32_Rep(jit);
  1.1018 -		IA32_Movsd(jit);
  1.1019 -	}
  1.1020 -	if (bytes)
  1.1021 -	{
  1.1022 -		IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
  1.1023 -		IA32_Rep(jit);
  1.1024 -		IA32_Movsb(jit);
  1.1025 -	}
  1.1026 -	IA32_Pop_Reg(jit, REG_EDI);
  1.1027 -	IA32_Pop_Reg(jit, REG_ESI);
  1.1028 -}
  1.1029 -
  1.1030 -inline void WriteOp_Fill(JitWriter *jit)
  1.1031 -{
  1.1032 -	//push edi
  1.1033 -	//lea edi, [ebp+edx]
  1.1034 -	//mov ecx, <val> >> 2
  1.1035 -	//cld
  1.1036 -	//rep stosd
  1.1037 -	//pop edi
  1.1038 -	unsigned int val = jit->read_cell() >> 2;
  1.1039 -
  1.1040 -	IA32_Push_Reg(jit, REG_EDI);
  1.1041 -	IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
  1.1042 -	IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
  1.1043 -	IA32_Cld(jit);
  1.1044 -	IA32_Rep(jit);
  1.1045 -	IA32_Stosd(jit);
  1.1046 -	IA32_Pop_Reg(jit, REG_EDI);
  1.1047 -}
  1.1048 -
  1.1049 -inline void WriteOp_GenArray(JitWriter *jit, bool autozero)
  1.1050 -{
  1.1051 -	cell_t val = jit->read_cell();
  1.1052 -	if (val == 1)
  1.1053 -	{
  1.1054 -		/* flat array.  we can generate this without indirection tables. */
  1.1055 -		/* Note that we can overwrite ALT because technically STACK should be destroying ALT */
  1.1056 -		//mov edx, [esi+info.heap]
  1.1057 -		//mov ecx, [edi]
  1.1058 -		//mov [edi], edx			;store base of array into stack
  1.1059 -		//lea edx, [edx+ecx*4]		;get the final new heap pointer
  1.1060 -		//mov [esi+info.heap], edx	;store heap pointer back
  1.1061 -		//add edx, ebp				;relocate
  1.1062 -		//cmp edx, edi				;compare against stack pointer
  1.1063 -		//jae :error				;error out if not enough space
  1.1064 -		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
  1.1065 -		IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
  1.1066 -		IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
  1.1067 -		IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4);
  1.1068 -		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP);
  1.1069 -		IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
  1.1070 -		IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
  1.1071 -		IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow);
  1.1072 -
  1.1073 -		WriteOp_Tracker_Push_Reg(jit, REG_ECX);
  1.1074 -
  1.1075 -		if (autozero)
  1.1076 -		{
  1.1077 -			/* Zero out the array - inline a quick fill */
  1.1078 -			//push eax				;save pri
  1.1079 -			//push edi				;save stk
  1.1080 -			//xor eax, eax			;zero source
  1.1081 -			//mov edi, [edi]		;get heap ptr out of the stack
  1.1082 -			//add edi, ebp			;relocate
  1.1083 -			//cld					;clear direction flag
  1.1084 -			//rep stosd				;copy (note: ECX is sane from above)
  1.1085 -			//pop edi				;pop stk
  1.1086 -			//pop eax				;pop pri
  1.1087 -			IA32_Push_Reg(jit, REG_EAX);
  1.1088 -			IA32_Push_Reg(jit, REG_EDI);
  1.1089 -			IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG);
  1.1090 -			IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG);
  1.1091 -			IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
  1.1092 -			IA32_Cld(jit);
  1.1093 -			IA32_Rep(jit);
  1.1094 -			IA32_Stosd(jit);
  1.1095 -			IA32_Pop_Reg(jit, REG_EDI);
  1.1096 -			IA32_Pop_Reg(jit, REG_EAX);
  1.1097 -		}
  1.1098 -	} else {
  1.1099 -		//mov ecx, num_dims
  1.1100 -		//mov edx, 0/1
  1.1101 -		//call [genarray]
  1.1102 -		IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
  1.1103 -		if (autozero)
  1.1104 -		{
  1.1105 -			IA32_Mov_Reg_Imm32(jit, REG_EDX, 1);
  1.1106 -		} else {
  1.1107 -			IA32_Mov_Reg_Imm32(jit, REG_EDX, 0);
  1.1108 -		}
  1.1109 -		jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1110 -		IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray);
  1.1111 -	}
  1.1112 -}
  1.1113 -
  1.1114 -inline void WriteOp_Load_Both(JitWriter *jit)
  1.1115 -{
  1.1116 -	WriteOp_Load_Pri(jit);
  1.1117 -	WriteOp_Load_Alt(jit);
  1.1118 -}
  1.1119 -
  1.1120 -inline void WriteOp_Load_S_Both(JitWriter *jit)
  1.1121 -{
  1.1122 -	WriteOp_Load_S_Pri(jit);
  1.1123 -	WriteOp_Load_S_Alt(jit);
  1.1124 -}
  1.1125 -
  1.1126 -inline void WriteOp_Const(JitWriter *jit)
  1.1127 -{
  1.1128 -	//mov [ebp+<addr>], <val>
  1.1129 -	cell_t addr = jit->read_cell();
  1.1130 -	cell_t val = jit->read_cell();
  1.1131 -	if (addr <= SCHAR_MAX && addr >= SCHAR_MIN)
  1.1132 -	{
  1.1133 -		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
  1.1134 -	} else {
  1.1135 -		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
  1.1136 -	}
  1.1137 -}
  1.1138 -
  1.1139 -inline void WriteOp_Const_S(JitWriter *jit)
  1.1140 -{
  1.1141 -	//mov [ebx+<offs>], <val>
  1.1142 -	cell_t offs = jit->read_cell();
  1.1143 -	cell_t val = jit->read_cell();
  1.1144 -	if (offs <= SCHAR_MAX && offs >= SCHAR_MIN)
  1.1145 -	{
  1.1146 -		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
  1.1147 -	} else {
  1.1148 -		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
  1.1149 -	}
  1.1150 -}
  1.1151 -
  1.1152 -inline void WriteOp_Load_I(JitWriter *jit)
  1.1153 -{
  1.1154 -	//mov eax, [ebp+eax]
  1.1155 -	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
  1.1156 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
  1.1157 -}
  1.1158 -
  1.1159 -inline void WriteOp_Lodb_I(JitWriter *jit)
  1.1160 -{
  1.1161 -	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
  1.1162 -
  1.1163 -	//mov eax, [ebp+eax]
  1.1164 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
  1.1165 -
  1.1166 -	//and eax, <bitmask>
  1.1167 -	cell_t val = jit->read_cell();
  1.1168 -	switch(val)
  1.1169 -	{
  1.1170 -	case 1:
  1.1171 -		{
  1.1172 -			IA32_And_Eax_Imm32(jit, 0x000000FF);
  1.1173 -			break;
  1.1174 -		}
  1.1175 -	case 2:
  1.1176 -		{
  1.1177 -			IA32_And_Eax_Imm32(jit, 0x0000FFFF);
  1.1178 -			break;
  1.1179 -		}
  1.1180 -	}
  1.1181 -}
  1.1182 -
  1.1183 -inline void WriteOp_Stor_I(JitWriter *jit)
  1.1184 -{
  1.1185 -	//mov [ebp+edx], eax
  1.1186 -	Write_Check_VerifyAddr(jit, AMX_REG_ALT);
  1.1187 -	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
  1.1188 -}
  1.1189 -
  1.1190 -inline void WriteOp_Strb_I(JitWriter *jit)
  1.1191 -{
  1.1192 -	Write_Check_VerifyAddr(jit, AMX_REG_ALT);
  1.1193 -	//mov [ebp+edx], eax
  1.1194 -	cell_t val = jit->read_cell();
  1.1195 -	switch (val)
  1.1196 -	{
  1.1197 -	case 1:
  1.1198 -		{
  1.1199 -			IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
  1.1200 -			break;
  1.1201 -		}
  1.1202 -	case 2:
  1.1203 -		{
  1.1204 -			IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
  1.1205 -			break;
  1.1206 -		}
  1.1207 -	case 4:
  1.1208 -		{
  1.1209 -			IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
  1.1210 -			break;
  1.1211 -		}
  1.1212 -	}
  1.1213 -}
  1.1214 -
  1.1215 -inline void WriteOp_Lidx(JitWriter *jit)
  1.1216 -{
  1.1217 -	//lea eax, [edx+4*eax]
  1.1218 -	//mov eax, [ebp+eax]
  1.1219 -	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
  1.1220 -	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
  1.1221 -	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
  1.1222 -}
  1.1223 -
  1.1224 -inline void WriteOp_Stack(JitWriter *jit)
  1.1225 -{
  1.1226 -	//add edi, <val>
  1.1227 -	cell_t val = jit->read_cell();
  1.1228 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
  1.1229 -	{
  1.1230 -		IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG);
  1.1231 -	} else {
  1.1232 -		IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG);
  1.1233 -	}
  1.1234 -
  1.1235 -	if (val > 0)
  1.1236 -	{
  1.1237 -		Write_CheckStack_Min(jit);
  1.1238 -	} else if (val < 0) {
  1.1239 -		Write_CheckStack_Low(jit);
  1.1240 -	}
  1.1241 -}
  1.1242 -
  1.1243 -inline void WriteOp_StackAdjust(JitWriter *jit)
  1.1244 -{
  1.1245 -	cell_t val = jit->read_cell();
  1.1246 -
  1.1247 -	assert(val <= 0);
  1.1248 -
  1.1249 -	//lea edi, [ebx-val]
  1.1250 -	
  1.1251 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
  1.1252 -	{
  1.1253 -		IA32_Lea_DispRegImm8(jit, AMX_REG_STK, AMX_REG_FRM, val);
  1.1254 -	}
  1.1255 -	else
  1.1256 -	{
  1.1257 -		IA32_Lea_DispRegImm32(jit, AMX_REG_STK, AMX_REG_FRM, val);
  1.1258 -	}
  1.1259 -
  1.1260 -	/* We assume the compiler has generated good code -- 
  1.1261 -	 * That is, we do not bother validating this amount!
  1.1262 -	 */
  1.1263 -}
  1.1264 -
  1.1265 -inline void WriteOp_Heap(JitWriter *jit)
  1.1266 -{
  1.1267 -	//mov edx, [esi+hea]
  1.1268 -	//add [esi+hea], <val>
  1.1269 -	cell_t val = jit->read_cell();
  1.1270 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
  1.1271 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
  1.1272 -	{
  1.1273 -		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP);
  1.1274 -	} else {
  1.1275 -		IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP);
  1.1276 -	}
  1.1277 -
  1.1278 -	/* NOTE: Backwards from op.stack */
  1.1279 -	if (val > 0)
  1.1280 -	{
  1.1281 -		Write_CheckHeap_Low(jit);
  1.1282 -	} else if (val < 0) {
  1.1283 -		Write_CheckHeap_Min(jit);
  1.1284 -	}
  1.1285 -}
  1.1286 -
  1.1287 -inline void WriteOp_SDiv(JitWriter *jit)
  1.1288 -{
  1.1289 -	//mov ecx, edx
  1.1290 -	//mov edx, eax
  1.1291 -	//sar edx, 31
  1.1292 -	//idiv ecx
  1.1293 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
  1.1294 -	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
  1.1295 -	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
  1.1296 -	Write_Check_DivZero(jit, AMX_REG_TMP);
  1.1297 -	IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
  1.1298 -}
  1.1299 -
  1.1300 -inline void WriteOp_SDiv_Alt(JitWriter *jit)
  1.1301 -{
  1.1302 -	//mov ecx, eax
  1.1303 -	//mov eax, edx
  1.1304 -	//sar edx, 31
  1.1305 -	//idiv ecx
  1.1306 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
  1.1307 -	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1308 -	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
  1.1309 -	Write_Check_DivZero(jit, AMX_REG_TMP);
  1.1310 -	IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
  1.1311 -}
  1.1312 -
  1.1313 -inline void WriteOp_Retn(JitWriter *jit)
  1.1314 -{
  1.1315 -	//mov ebx, [edi+4]		- get old frm
  1.1316 -	//add edi, 8			- pop stack
  1.1317 -	//mov [esi+frm], ebx	- restore frame pointer
  1.1318 -	//add ebx, ebp			- relocate
  1.1319 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4);
  1.1320 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.1321 -	IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
  1.1322 -	IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
  1.1323 -
  1.1324 -	/* pop params */
  1.1325 -	//mov ecx, [edi]
  1.1326 -	//lea edi, [edi+ecx*4+4] 
  1.1327 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
  1.1328 -	IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4);
  1.1329 -
  1.1330 -	//ret					- return (EIP on real stack!)
  1.1331 -	IA32_Return(jit);
  1.1332 -}
  1.1333 -
  1.1334 -void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
  1.1335 -{
  1.1336 -	((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
  1.1337 -}
  1.1338 -
  1.1339 -void ProfCallGate_End(sp_context_t *ctx)
  1.1340 -{
  1.1341 -	((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
  1.1342 -}
  1.1343 -
  1.1344 -const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
  1.1345 -{
  1.1346 -	uint32_t max, iter;
  1.1347 -	sp_fdbg_symbol_t *sym;
  1.1348 -	sp_fdbg_arraydim_t *arr;
  1.1349 -	uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
  1.1350 -
  1.1351 -	max = plugin->debug.syms_num;
  1.1352 -	for (iter = 0; iter < max; iter++)
  1.1353 -	{
  1.1354 -		sym = (sp_fdbg_symbol_t *)cursor;
  1.1355 -
  1.1356 -		if (sym->ident == SP_SYM_FUNCTION
  1.1357 -			&& sym->codestart <= offs 
  1.1358 -			&& sym->codeend > offs)
  1.1359 -		{
  1.1360 -			return plugin->debug.stringbase + sym->name;
  1.1361 -		}
  1.1362 -
  1.1363 -		if (sym->dimcount > 0)
  1.1364 -		{
  1.1365 -			cursor += sizeof(sp_fdbg_symbol_t);
  1.1366 -			arr = (sp_fdbg_arraydim_t *)cursor;
  1.1367 -			cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
  1.1368 -			continue;
  1.1369 -		}
  1.1370 -
  1.1371 -		cursor += sizeof(sp_fdbg_symbol_t);
  1.1372 -	}
  1.1373 -
  1.1374 -	return NULL;
  1.1375 -}
  1.1376 -
  1.1377 -inline void WriteOp_Call(JitWriter *jit)
  1.1378 -{
  1.1379 -	cell_t offs;
  1.1380 -	jitoffs_t jmp;
  1.1381 -	CompData *data;
  1.1382 -		
  1.1383 -	data = (CompData *)jit->data; 
  1.1384 -	offs = jit->read_cell();
  1.1385 -
  1.1386 -	if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
  1.1387 -	{
  1.1388 -		const char *name;
  1.1389 -
  1.1390 -		/* Find the function name */
  1.1391 -		if ((name = find_func_name(data->plugin, offs)) == NULL)
  1.1392 -		{
  1.1393 -			name = "unknown";
  1.1394 -		}
  1.1395 -
  1.1396 -		//push name
  1.1397 -		//push [esi+context] 
  1.1398 -		//call ProfCallGate_Begin
  1.1399 -		//add esp, 8
  1.1400 -		IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
  1.1401 -		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1402 -		jmp = IA32_Call_Imm32(jit, 0);
  1.1403 -		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
  1.1404 -		IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
  1.1405 -
  1.1406 -		//call <addr>
  1.1407 -		//push eax
  1.1408 -		jmp = IA32_Call_Imm32(jit, 0);
  1.1409 -		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
  1.1410 -		IA32_Push_Reg(jit, REG_EAX);
  1.1411 -
  1.1412 -		//push [esi+context]
  1.1413 -		//call ProfCallGate_End
  1.1414 -		//add esp, 4
  1.1415 -		//pop eax
  1.1416 -		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1417 -		jmp = IA32_Call_Imm32(jit, 0);
  1.1418 -		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
  1.1419 -		IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.1420 -		IA32_Pop_Reg(jit, REG_EAX);
  1.1421 -	}
  1.1422 -	else
  1.1423 -	{
  1.1424 -		jmp = IA32_Call_Imm32(jit, 0);
  1.1425 -		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
  1.1426 -	}
  1.1427 -}
  1.1428 -
  1.1429 -inline void WriteOp_Bounds(JitWriter *jit)
  1.1430 -{
  1.1431 -	cell_t val = jit->read_cell();
  1.1432 -	
  1.1433 -	//cmp eax, <val>
  1.1434 -	//ja :error
  1.1435 -	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
  1.1436 -	{
  1.1437 -		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
  1.1438 -	} else {
  1.1439 -		IA32_Cmp_Eax_Imm32(jit, val);
  1.1440 -	}
  1.1441 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds);
  1.1442 -}
  1.1443 -
  1.1444 -inline void WriteOp_Halt(JitWriter *jit)
  1.1445 -{
  1.1446 -	AlignMe(jit);
  1.1447 -
  1.1448 -	//mov ecx, [esi+ret]
  1.1449 -	//mov [ecx], eax
  1.1450 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
  1.1451 -	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
  1.1452 -	
  1.1453 -	/* :TODO: 
  1.1454 -	 * We don't support sleeping or halting with weird values.
  1.1455 -	 * So we're omitting the mov eax <val> that was here.
  1.1456 -	 */
  1.1457 -	jit->read_cell();
  1.1458 -
  1.1459 -	CompData *data = (CompData *)jit->data;
  1.1460 -	IA32_Jump_Imm32_Abs(jit, data->jit_return);
  1.1461 -}
  1.1462 -
  1.1463 -inline void WriteOp_Break(JitWriter *jit)
  1.1464 -{
  1.1465 -	CompData *data = (CompData *)jit->data;
  1.1466 -	if (data->debug)
  1.1467 -	{
  1.1468 -		//jit->write_ubyte(IA32_INT3);
  1.1469 -		//mov ecx, <cip>
  1.1470 -		jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0);
  1.1471 -		jitoffs_t save = jit->get_outputpos();
  1.1472 -		jit->set_outputpos(wr);
  1.1473 -		jit->write_uint32((uint32_t)(wr));
  1.1474 -		jit->set_outputpos(save);
  1.1475 -		wr = IA32_Call_Imm32(jit, 0);
  1.1476 -		IA32_Write_Jump32(jit, wr, data->jit_break);
  1.1477 -	}
  1.1478 -}
  1.1479 -
  1.1480 -inline void WriteOp_Jump(JitWriter *jit)
  1.1481 -{
  1.1482 -	//jmp <offs>
  1.1483 -	cell_t amx_offs = jit->read_cell();
  1.1484 -	IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false));
  1.1485 -}
  1.1486 -
  1.1487 -inline void WriteOp_Jzer(JitWriter *jit)
  1.1488 -{
  1.1489 -	//test eax, eax
  1.1490 -	//jz <target>
  1.1491 -	cell_t target = jit->read_cell();
  1.1492 -	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
  1.1493 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false));
  1.1494 -}
  1.1495 -
  1.1496 -inline void WriteOp_Jnz(JitWriter *jit)
  1.1497 -{
  1.1498 -	//test eax, eax
  1.1499 -	//jnz <target>
  1.1500 -	cell_t target = jit->read_cell();
  1.1501 -	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
  1.1502 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false));
  1.1503 -}
  1.1504 -
  1.1505 -inline void WriteOp_Jeq(JitWriter *jit)
  1.1506 -{
  1.1507 -	//cmp eax, edx
  1.1508 -	//je <target>
  1.1509 -	cell_t target = jit->read_cell();
  1.1510 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1511 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false));
  1.1512 -}
  1.1513 -
  1.1514 -inline void WriteOp_Jneq(JitWriter *jit)
  1.1515 -{
  1.1516 -	//cmp eax, edx
  1.1517 -	//jne <target>
  1.1518 -	cell_t target = jit->read_cell();
  1.1519 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1520 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, RelocLookup(jit, target, false));
  1.1521 -}
  1.1522 -
  1.1523 -inline void WriteOp_Jsless(JitWriter *jit)
  1.1524 -{
  1.1525 -	//cmp eax, edx
  1.1526 -	//jl <target>
  1.1527 -	cell_t target = jit->read_cell();
  1.1528 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1529 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_L, RelocLookup(jit, target, false));
  1.1530 -}
  1.1531 -
  1.1532 -inline void WriteOp_Jsleq(JitWriter *jit)
  1.1533 -{
  1.1534 -	//cmp eax, edx
  1.1535 -	//jle <target>
  1.1536 -	cell_t target = jit->read_cell();
  1.1537 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1538 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_LE, RelocLookup(jit, target, false));
  1.1539 -}
  1.1540 -
  1.1541 -inline void WriteOp_JsGrtr(JitWriter *jit)
  1.1542 -{
  1.1543 -	//cmp eax, edx
  1.1544 -	//jg <target>
  1.1545 -	cell_t target = jit->read_cell();
  1.1546 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1547 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_G, RelocLookup(jit, target, false));
  1.1548 -}
  1.1549 -
  1.1550 -inline void WriteOp_JsGeq(JitWriter *jit)
  1.1551 -{
  1.1552 -	//cmp eax, edx
  1.1553 -	//jge <target>
  1.1554 -	cell_t target = jit->read_cell();
  1.1555 -	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
  1.1556 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_GE, RelocLookup(jit, target, false));
  1.1557 -}
  1.1558 -
  1.1559 -inline void WriteOp_Switch(JitWriter *jit)
  1.1560 -{
  1.1561 -	cell_t offs = jit->read_cell();
  1.1562 -	cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t));
  1.1563 -
  1.1564 -	struct casetbl
  1.1565 -	{
  1.1566 -		cell_t val;
  1.1567 -		cell_t offs;
  1.1568 -	};
  1.1569 -
  1.1570 -	/* Read the number of cases, then advance by one */
  1.1571 -	cell_t num_cases = *tbl++;
  1.1572 -	if (!num_cases)
  1.1573 -	{
  1.1574 -		/* Special treatment for 0 cases */
  1.1575 -		//jmp <default>
  1.1576 -		IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
  1.1577 -	} else {
  1.1578 -		/* Check if the case layout is fully sequential */
  1.1579 -		casetbl *iter = (casetbl *)(tbl + 1);
  1.1580 -		casetbl *cases = iter;
  1.1581 -		cell_t first = iter[0].val;
  1.1582 -		cell_t last = first;
  1.1583 -		bool sequential = true;
  1.1584 -		for (cell_t i=1; i<num_cases; i++)
  1.1585 -		{
  1.1586 -			if (iter[i].val != ++last)
  1.1587 -			{
  1.1588 -				sequential = false;
  1.1589 -				break;
  1.1590 -			}
  1.1591 -		}
  1.1592 -		/* Time to generate. 
  1.1593 -		 * First check whether the bounds are correct: if (a < LOW || a > HIGH)
  1.1594 -		 * This check is valid for both sequential and non-sequential.
  1.1595 -		 */
  1.1596 -		cell_t low_bound = cases[0].val;
  1.1597 -		if (low_bound != 0)
  1.1598 -		{
  1.1599 -			/* negate it so we'll get a lower bound of 0 */
  1.1600 -			//lea ecx, [eax-<LOWER_BOUND>]
  1.1601 -			low_bound = -low_bound;
  1.1602 -			if (low_bound >= SCHAR_MIN && low_bound <= SCHAR_MAX)
  1.1603 -			{
  1.1604 -				IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
  1.1605 -			} else {
  1.1606 -				IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
  1.1607 -			}
  1.1608 -		} else {
  1.1609 -			//mov ecx, eax
  1.1610 -			IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
  1.1611 -		}
  1.1612 -		cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val);
  1.1613 -		//cmp ecx, <UPPER BOUND BOUND>
  1.1614 -		if (high_bound >= SCHAR_MIN && high_bound <= SCHAR_MAX)
  1.1615 -		{
  1.1616 -			IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound);
  1.1617 -		} else {
  1.1618 -			IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound);
  1.1619 -		}
  1.1620 -		//ja <default case>
  1.1621 -		IA32_Jump_Cond_Imm32_Abs(jit, CC_A, RelocLookup(jit, *tbl, false));
  1.1622 -
  1.1623 -		/**
  1.1624 -		 * Now we've taken the default case out of the way, it's time to do the
  1.1625 -		 * full check, which is different for sequential vs. non-sequential.
  1.1626 -		 */
  1.1627 -		if (sequential)
  1.1628 -		{
  1.1629 -			/* we're now theoretically guaranteed to be jumping to a correct offset.
  1.1630 -			 * ECX still has the correctly bound offset in it, luckily!
  1.1631 -			 * thus, we simply need to relocate ECX and store the cases.
  1.1632 -			 */
  1.1633 -			//lea ecx, [ecx*4]
  1.1634 -			//add ecx, <case table start>
  1.1635 -			IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0);
  1.1636 -			jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG);
  1.1637 -			IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG);
  1.1638 -			/* The case table starts here.  Go back and write the output pointer. */
  1.1639 -			jitoffs_t cur_pos = jit->get_outputpos();
  1.1640 -			jit->set_outputpos(tbl_offs);
  1.1641 -			jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos));
  1.1642 -			jit->set_outputpos(cur_pos);
  1.1643 -			//now we can write the case table, finally!
  1.1644 -			jit_uint32_t base = (jit_uint32_t)jit->outbase;
  1.1645 -			for (cell_t i=0; i<num_cases; i++)
  1.1646 -			{
  1.1647 -				jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false));
  1.1648 -			}
  1.1649 -		} else {
  1.1650 -			/* The slow version.  Go through each case and generate a check.
  1.1651 -			 * In the future we should replace case tables of more than ~8 cases with a
  1.1652 -			 * hash table lookup.
  1.1653 -			 * :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case,
  1.1654 -			 *  but only if we're under N cases or so!
  1.1655 -			 * :THOUGHT: Write out a static btree lookup :)
  1.1656 -			 */
  1.1657 -			cell_t val;
  1.1658 -			for (cell_t i=0; i<num_cases; i++)
  1.1659 -			{
  1.1660 -				val = cases[i].val;
  1.1661 -				//cmp eax, <val> OR cmp al, <val>
  1.1662 -				if (val >= SCHAR_MIN && val <= SCHAR_MAX)
  1.1663 -				{
  1.1664 -					IA32_Cmp_Al_Imm8(jit, val);
  1.1665 -				} else {
  1.1666 -					IA32_Cmp_Eax_Imm32(jit, cases[i].val);
  1.1667 -				}
  1.1668 -				IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, cases[i].offs, false));
  1.1669 -			}
  1.1670 -			/* After all this, jump to the default case! */
  1.1671 -			IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
  1.1672 -		}
  1.1673 -	}
  1.1674 -}
  1.1675 -
  1.1676 -inline void WriteOp_Casetbl(JitWriter *jit)
  1.1677 -{
  1.1678 -	/* do nothing here, switch does all ze work */
  1.1679 -	cell_t num_cases = jit->read_cell();
  1.1680 -
  1.1681 -	/* Two cells per case, one extra case for the default jump */
  1.1682 -	num_cases = (num_cases * 2) + 1;
  1.1683 -	jit->inptr += num_cases;
  1.1684 -}
  1.1685 -
  1.1686 -inline void WriteOp_Sysreq_C(JitWriter *jit)
  1.1687 -{
  1.1688 -	/* store the number of parameters on the stack, 
  1.1689 -	 * and store the native index as well.
  1.1690 -	 */
  1.1691 -	cell_t native_index = jit->read_cell();
  1.1692 -
  1.1693 -	if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
  1.1694 -	{
  1.1695 -		((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
  1.1696 -		return;
  1.1697 -	}
  1.1698 -
  1.1699 -	//mov ecx, <native_index>
  1.1700 -	IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
  1.1701 -
  1.1702 -	jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1703 -	IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c);
  1.1704 -}
  1.1705 -
  1.1706 -inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit)
  1.1707 -{
  1.1708 -	/* store the number of parameters on the stack, 
  1.1709 -	 * and store the native index as well.
  1.1710 -	 */
  1.1711 -	cell_t native_index = jit->read_cell();
  1.1712 -	cell_t num_params = jit->read_cell();
  1.1713 -	
  1.1714 -	if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
  1.1715 -	{
  1.1716 -		((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
  1.1717 -		return;
  1.1718 -	}
  1.1719 -
  1.1720 -	//mov eax, <num_params>
  1.1721 -	//mov ecx, <native_index>
  1.1722 -	IA32_Mov_Reg_Imm32(jit, REG_EAX, num_params);
  1.1723 -	IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
  1.1724 -
  1.1725 -	jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1726 -	IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_n);
  1.1727 -}
  1.1728 -
  1.1729 -inline void WriteOp_Sysreq_N(JitWriter *jit)
  1.1730 -{
  1.1731 -	/* The big daddy of opcodes. */
  1.1732 -	cell_t native_index = jit->read_cell();
  1.1733 -	cell_t num_params = jit->read_cell();
  1.1734 -	CompData *data = (CompData *)jit->data;
  1.1735 -
  1.1736 -	if ((uint32_t)native_index >= data->plugin->info.natives_num)
  1.1737 -	{
  1.1738 -		data->error_set = SP_ERROR_INSTRUCTION_PARAM;
  1.1739 -		return;
  1.1740 -	}
  1.1741 -
  1.1742 -	/* store the number of parameters on the stack */
  1.1743 -	//mov [edi-4], num_params
  1.1744 -	//sub edi, 4
  1.1745 -	IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4);
  1.1746 -	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.1747 -
  1.1748 -	/* save registers we will need */
  1.1749 -	//push edx
  1.1750 -	IA32_Push_Reg(jit, AMX_REG_ALT);
  1.1751 -
  1.1752 -	/* Align the stack to 16 bytes */
  1.1753 -	//push ebx
  1.1754 -	//mov ebx, esp
  1.1755 -	//and esp, 0xFFFFFF0
  1.1756 -	//sub esp, 4
  1.1757 -	IA32_Push_Reg(jit, REG_EBX);
  1.1758 -	IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
  1.1759 -	IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
  1.1760 -	IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.1761 -
  1.1762 -	/* push some callback stuff */
  1.1763 -	//push edi		; stack
  1.1764 -	//push <native>	; native index
  1.1765 -	IA32_Push_Reg(jit, AMX_REG_STK);
  1.1766 -	if (native_index <= SCHAR_MAX && native_index >= SCHAR_MIN)
  1.1767 -	{
  1.1768 -		IA32_Push_Imm8(jit, (jit_int8_t)native_index);
  1.1769 -	} else {
  1.1770 -		IA32_Push_Imm32(jit, native_index);
  1.1771 -	}
  1.1772 -
  1.1773 -	/* Relocate stack, heap, frm information, then store back */
  1.1774 -	//mov eax, [esi+context]
  1.1775 -	//mov ecx, [esi+hea]
  1.1776 -	//sub edi, ebp
  1.1777 -	//mov [eax+hp], ecx
  1.1778 -	//mov ecx, [esi]
  1.1779 -	//mov [eax+sp], edi
  1.1780 -	//mov [eax+frm], ecx
  1.1781 -	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1782 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
  1.1783 -	IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
  1.1784 -	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
  1.1785 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
  1.1786 -	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
  1.1787 -	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
  1.1788 -
  1.1789 -	/* finally, push the last parameter and make the call */
  1.1790 -	//push eax		; context
  1.1791 -	//call NativeCallback
  1.1792 -	IA32_Push_Reg(jit, REG_EAX);
  1.1793 -	jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1794 -	if (!data->debug)
  1.1795 -	{
  1.1796 -		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
  1.1797 -		{
  1.1798 -			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
  1.1799 -		}
  1.1800 -		else
  1.1801 -		{
  1.1802 -			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
  1.1803 -		}
  1.1804 -	}
  1.1805 -	else
  1.1806 -	{
  1.1807 -		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
  1.1808 -		{
  1.1809 -			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
  1.1810 -		}
  1.1811 -		else
  1.1812 -		{
  1.1813 -			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
  1.1814 -		}
  1.1815 -	}
  1.1816 -	
  1.1817 -	/* check for errors */
  1.1818 -	//mov ecx, [esi+context]
  1.1819 -	//cmp [ecx+err], 0
  1.1820 -	//jnz :error
  1.1821 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1822 -	IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
  1.1823 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
  1.1824 -
  1.1825 -	/* restore what we damaged */
  1.1826 -	//mov esp, ebx
  1.1827 -	//pop ebx
  1.1828 -	//add edi, ebp
  1.1829 -	//pop edx
  1.1830 -	IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
  1.1831 -	IA32_Pop_Reg(jit, REG_EBX);
  1.1832 -	IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
  1.1833 -	IA32_Pop_Reg(jit, AMX_REG_ALT);
  1.1834 -
  1.1835 -	/* pop the stack.  do not check the margins.
  1.1836 -	 * Note that this is not a true macro - we don't bother to
  1.1837 -	 * set ALT here because nothing will be using it.
  1.1838 -	 */
  1.1839 -	num_params++;
  1.1840 -	num_params *= 4;
  1.1841 -	//add edi, <val*4+4>
  1.1842 -	if (num_params <= SCHAR_MAX && num_params >= SCHAR_MIN)
  1.1843 -	{
  1.1844 -		IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG);
  1.1845 -	} else {
  1.1846 -		IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG);
  1.1847 -	}
  1.1848 -}
  1.1849 -
  1.1850 -inline void WriteOp_Tracker_Push_C(JitWriter *jit)
  1.1851 -{
  1.1852 -	CompData *data = (CompData *)jit->data;
  1.1853 -	cell_t val = jit->read_cell();
  1.1854 -
  1.1855 -	/* Save registers that may be damaged by the call */
  1.1856 -	//push eax
  1.1857 -	//push edx
  1.1858 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.1859 -	IA32_Push_Reg(jit, AMX_REG_ALT);
  1.1860 -
  1.1861 -	/* Get the context ptr, push it and call the check */
  1.1862 -	//mov eax, [esi+context]
  1.1863 -	//push eax
  1.1864 -	//call JIT_VerifyOrAllocateTracker
  1.1865 -	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1866 -	IA32_Push_Reg(jit, REG_EAX);
  1.1867 -	jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1868 -	IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
  1.1869 -
  1.1870 -	/* Check for errors */
  1.1871 -	//cmp eax, 0
  1.1872 -	//jnz :error
  1.1873 -	IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
  1.1874 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
  1.1875 -
  1.1876 -	/* Restore */
  1.1877 -	//pop eax
  1.1878 -	IA32_Pop_Reg(jit, REG_EAX);
  1.1879 -
  1.1880 -	/* Push the value into the stack and increment pCur */
  1.1881 -	//mov edx, [eax+vm[]]
  1.1882 -	//mov ecx, [edx+pcur]
  1.1883 -	//add [edx+pcur], 4
  1.1884 -	//mov [ecx], <val>*4	; we want the count in bytes not in cells
  1.1885 -	IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
  1.1886 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
  1.1887 -	IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
  1.1888 -	IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG);
  1.1889 -
  1.1890 -	/* Restore PRI & ALT */
  1.1891 -	//pop edx
  1.1892 -	//pop eax
  1.1893 -	IA32_Pop_Reg(jit, AMX_REG_ALT);
  1.1894 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.1895 -}
  1.1896 -
  1.1897 -inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit)
  1.1898 -{
  1.1899 -	CompData *data = (CompData *)jit->data;
  1.1900 -
  1.1901 -	/* Save registers that may be damaged by the call */
  1.1902 -	//push eax
  1.1903 -	//push edx
  1.1904 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.1905 -	IA32_Push_Reg(jit, AMX_REG_ALT);
  1.1906 -
  1.1907 -	/* Get the context ptr, push it and call the check */
  1.1908 -	//mov eax, [esi+context]
  1.1909 -	//push eax
  1.1910 -	//call JIT_VerifyLowBoundTracker
  1.1911 -	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
  1.1912 -	IA32_Push_Reg(jit, REG_EAX);
  1.1913 -	jitoffs_t call = IA32_Call_Imm32(jit, 0);
  1.1914 -	IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker);
  1.1915 -
  1.1916 -	/* Check for errors */
  1.1917 -	//cmp eax, 0
  1.1918 -	//jnz :error
  1.1919 -	IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
  1.1920 -	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
  1.1921 -
  1.1922 -	/* Restore */
  1.1923 -	//pop eax
  1.1924 -	IA32_Pop_Reg(jit, REG_EAX);
  1.1925 -
  1.1926 -	/* Pop the value from the stack and decrease the heap by it*/
  1.1927 -	//mov edx, [eax+vm[]]
  1.1928 -	//sub [edx+pcur], 4
  1.1929 -	//mov ecx, [edx+pcur]
  1.1930 -	//mov ecx, [ecx]
  1.1931 -	//sub [esi+hea], ecx
  1.1932 -	IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
  1.1933 -	IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
  1.1934 -	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
  1.1935 -	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG);
  1.1936 -	IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP);
  1.1937 -
  1.1938 -	Write_CheckHeap_Min(jit);
  1.1939 -
  1.1940 -	/* Restore PRI & ALT */
  1.1941 -	//pop edx
  1.1942 -	//pop eax
  1.1943 -	IA32_Pop_Reg(jit, AMX_REG_ALT);
  1.1944 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.1945 -}
  1.1946 -
  1.1947 -inline void WriteOp_Stradjust_Pri(JitWriter *jit)
  1.1948 -{
  1.1949 -	//add eax, 4
  1.1950 -	//sar eax, 2
  1.1951 -	IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG);
  1.1952 -	IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG);
  1.1953 -}
  1.1954 -
  1.1955 -inline void WriteOp_FloatAbs(JitWriter *jit)
  1.1956 -{
  1.1957 -	//mov eax, [edi]
  1.1958 -	//and eax, 0x7FFFFFFF
  1.1959 -	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
  1.1960 -	IA32_And_Eax_Imm32(jit, 0x7FFFFFFF);
  1.1961 -
  1.1962 -	/* Rectify the stack */
  1.1963 -	//add edi, 4
  1.1964 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.1965 -}
  1.1966 -
  1.1967 -inline void WriteOp_Float(JitWriter *jit)
  1.1968 -{
  1.1969 -	//fild [edi]
  1.1970 -	//push eax
  1.1971 -	//fstp [esp]
  1.1972 -	//pop eax
  1.1973 -	IA32_Fild_Mem32(jit, AMX_REG_STK);
  1.1974 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.1975 -	IA32_Fstp_Mem32_ESP(jit);
  1.1976 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.1977 -
  1.1978 -	/* Rectify the stack */
  1.1979 -	//add edi, 4
  1.1980 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.1981 -}
  1.1982 -
  1.1983 -inline void WriteOp_FloatAdd(JitWriter *jit)
  1.1984 -{
  1.1985 -	//push eax
  1.1986 -	//fld [edi]
  1.1987 -	//fadd [edi+4]
  1.1988 -	//fstp [esp]
  1.1989 -	//pop eax
  1.1990 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.1991 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.1992 -	IA32_Fadd_Mem32_Disp8(jit, AMX_REG_STK, 4);
  1.1993 -	IA32_Fstp_Mem32_ESP(jit);
  1.1994 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.1995 -
  1.1996 -	/* Rectify the stack */
  1.1997 -	//add edi, 8
  1.1998 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.1999 -}
  1.2000 -
  1.2001 -inline void WriteOp_FloatSub(JitWriter *jit)
  1.2002 -{
  1.2003 -	//push eax
  1.2004 -	//fld [edi]
  1.2005 -	//fsub [edi+4]
  1.2006 -	//fstp [esp]
  1.2007 -	//pop eax
  1.2008 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.2009 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2010 -	IA32_Fsub_Mem32_Disp8(jit, AMX_REG_STK, 4);
  1.2011 -	IA32_Fstp_Mem32_ESP(jit);
  1.2012 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.2013 -
  1.2014 -	/* Rectify the stack */
  1.2015 -	//add edi, 8
  1.2016 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.2017 -}
  1.2018 -
  1.2019 -inline void WriteOp_FloatMul(JitWriter *jit)
  1.2020 -{
  1.2021 -	//push eax
  1.2022 -	//fld [edi]
  1.2023 -	//fmul [edi+4]
  1.2024 -	//fstp [esp]
  1.2025 -	//pop eax
  1.2026 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.2027 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2028 -	IA32_Fmul_Mem32_Disp8(jit, AMX_REG_STK, 4);
  1.2029 -	IA32_Fstp_Mem32_ESP(jit);
  1.2030 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.2031 -
  1.2032 -	/* Rectify the stack */
  1.2033 -	//add edi, 8
  1.2034 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.2035 -}
  1.2036 -
  1.2037 -inline void WriteOp_FloatDiv(JitWriter *jit)
  1.2038 -{
  1.2039 -	//push eax
  1.2040 -	//fld [edi]
  1.2041 -	//fdiv [edi+4]
  1.2042 -	//fstp [esp]
  1.2043 -	//pop eax
  1.2044 -	IA32_Push_Reg(jit, AMX_REG_PRI);
  1.2045 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2046 -	IA32_Fdiv_Mem32_Disp8(jit, AMX_REG_STK, 4);
  1.2047 -	IA32_Fstp_Mem32_ESP(jit);
  1.2048 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.2049 -
  1.2050 -	/* Rectify the stack */
  1.2051 -	//add edi, 8
  1.2052 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.2053 -}
  1.2054 -
  1.2055 -inline void WriteOp_RountToNearest(JitWriter *jit)
  1.2056 -{
  1.2057 -	//push eax
  1.2058 -	//fld [edi]
  1.2059 -
  1.2060 -	//fstcw [esp]
  1.2061 -	//mov eax, [esp]
  1.2062 -	//push eax
  1.2063 -
  1.2064 -	//mov [esp+4], 0x3FF
  1.2065 -	//fadd st(0), st(0)
  1.2066 -	//fldcw [esp+4]
  1.2067 -
  1.2068 -	//push eax	
  1.2069 -	//push 0x3F000000 ; 0.5f
  1.2070 -	//fadd [esp]
  1.2071 -	//fistp [esp+4]
  1.2072 -	//pop eax
  1.2073 -	//pop eax
  1.2074 -
  1.2075 -	//pop ecx
  1.2076 -	//sar eax, 1
  1.2077 -	//mov [esp], ecx
  1.2078 -	//fldcw [esp]
  1.2079 -	//add esp, 4
  1.2080 -
  1.2081 -	IA32_Push_Reg(jit, REG_EAX);
  1.2082 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2083 -
  1.2084 -	IA32_Fstcw_Mem16_ESP(jit);
  1.2085 -	IA32_Mov_Reg_RmESP(jit, REG_EAX);
  1.2086 -	IA32_Push_Reg(jit, REG_EAX);
  1.2087 -
  1.2088 -	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x3FF);
  1.2089 -	IA32_Fadd_FPUreg_ST0(jit, 0);
  1.2090 -	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
  1.2091 -
  1.2092 -	IA32_Push_Reg(jit, REG_EAX);
  1.2093 -	IA32_Push_Imm32(jit, 0x3F000000);
  1.2094 -	IA32_Fadd_Mem32_ESP(jit);
  1.2095 -	IA32_Fistp_Mem32_Disp8_Esp(jit, 4);
  1.2096 -	IA32_Pop_Reg(jit, REG_EAX);
  1.2097 -	IA32_Pop_Reg(jit, AMX_REG_PRI);
  1.2098 -
  1.2099 -	IA32_Pop_Reg(jit, REG_ECX);
  1.2100 -	IA32_Sar_Rm_1(jit, REG_EAX, MOD_REG);
  1.2101 -	IA32_Mov_RmESP_Reg(jit, REG_ECX);
  1.2102 -	IA32_Fldcw_Mem16_ESP(jit);
  1.2103 -	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.2104 -
  1.2105 -	/* Rectify the stack */
  1.2106 -	//add edi, 4
  1.2107 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.2108 -}
  1.2109 -
  1.2110 -inline void WriteOp_RoundToFloor(JitWriter *jit)
  1.2111 -{
  1.2112 -	//push eax
  1.2113 -	//fld [edi]
  1.2114 -
  1.2115 -	//fstcw [esp]
  1.2116 -	//mov eax, [esp]
  1.2117 -	//push eax
  1.2118 -
  1.2119 -	//mov [esp+4], 0x7FF
  1.2120 -	//fldcw [esp+4]
  1.2121 -
  1.2122 -	//push eax	
  1.2123 -	//fistp [esp]
  1.2124 -	//pop eax
  1.2125 -
  1.2126 -	//pop ecx
  1.2127 -	//mov [esp], ecx
  1.2128 -	//fldcw [esp]
  1.2129 -	//add esp, 4
  1.2130 -
  1.2131 -	IA32_Push_Reg(jit, REG_EAX);
  1.2132 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2133 -
  1.2134 -	IA32_Fstcw_Mem16_ESP(jit);
  1.2135 -	IA32_Mov_Reg_RmESP(jit, REG_EAX);
  1.2136 -	IA32_Push_Reg(jit, REG_EAX);
  1.2137 -
  1.2138 -	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x7FF);
  1.2139 -	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
  1.2140 -
  1.2141 -	IA32_Push_Reg(jit, REG_EAX);
  1.2142 -	IA32_Fistp_Mem32_ESP(jit);
  1.2143 -	IA32_Pop_Reg(jit, REG_EAX);
  1.2144 -
  1.2145 -	IA32_Pop_Reg(jit, REG_ECX);
  1.2146 -	IA32_Mov_RmESP_Reg(jit, REG_ECX);
  1.2147 -	IA32_Fldcw_Mem16_ESP(jit);
  1.2148 -	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.2149 -
  1.2150 -	/* Rectify the stack */
  1.2151 -	//add edi, 4
  1.2152 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.2153 -}
  1.2154 -
  1.2155 -inline void WriteOp_RoundToCeil(JitWriter *jit)
  1.2156 -{
  1.2157 -	//push eax
  1.2158 -	//fld [edi]
  1.2159 -
  1.2160 -	//fstcw [esp]
  1.2161 -	//mov eax, [esp]
  1.2162 -	//push eax
  1.2163 -
  1.2164 -	//mov [esp+4], 0xBFF
  1.2165 -	//fldcw [esp+4]
  1.2166 -
  1.2167 -	//push eax	
  1.2168 -	//fistp [esp]
  1.2169 -	//pop eax
  1.2170 -
  1.2171 -	//pop ecx
  1.2172 -	//mov [esp], ecx
  1.2173 -	//fldcw [esp]
  1.2174 -	//add esp, 4
  1.2175 -
  1.2176 -	IA32_Push_Reg(jit, REG_EAX);
  1.2177 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2178 -
  1.2179 -	IA32_Fstcw_Mem16_ESP(jit);
  1.2180 -	IA32_Mov_Reg_RmESP(jit, REG_EAX);
  1.2181 -	IA32_Push_Reg(jit, REG_EAX);
  1.2182 -
  1.2183 -	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xBFF);
  1.2184 -	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
  1.2185 -
  1.2186 -	IA32_Push_Reg(jit, REG_EAX);
  1.2187 -	IA32_Fistp_Mem32_ESP(jit);
  1.2188 -	IA32_Pop_Reg(jit, REG_EAX);
  1.2189 -
  1.2190 -	IA32_Pop_Reg(jit, REG_ECX);
  1.2191 -	IA32_Mov_RmESP_Reg(jit, REG_ECX);
  1.2192 -	IA32_Fldcw_Mem16_ESP(jit);
  1.2193 -	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.2194 -
  1.2195 -	/* Rectify the stack */
  1.2196 -	//add edi, 4
  1.2197 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.2198 -}
  1.2199 -
  1.2200 -inline void WriteOp_RoundToZero(JitWriter *jit)
  1.2201 -{
  1.2202 -	//push eax
  1.2203 -	//fld [edi]
  1.2204 -
  1.2205 -	//fstcw [esp]
  1.2206 -	//mov eax, [esp]
  1.2207 -	//push eax
  1.2208 -
  1.2209 -	//mov [esp+4], 0xFFF
  1.2210 -	//fldcw [esp+4]
  1.2211 -
  1.2212 -	//push eax	
  1.2213 -	//fistp [esp]
  1.2214 -	//pop eax
  1.2215 -
  1.2216 -	//pop ecx
  1.2217 -	//mov [esp], ecx
  1.2218 -	//fldcw [esp]
  1.2219 -	//add esp, 4
  1.2220 -
  1.2221 -	IA32_Push_Reg(jit, REG_EAX);
  1.2222 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2223 -
  1.2224 -	IA32_Fstcw_Mem16_ESP(jit);
  1.2225 -	IA32_Mov_Reg_RmESP(jit, REG_EAX);
  1.2226 -	IA32_Push_Reg(jit, REG_EAX);
  1.2227 -
  1.2228 -	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xFFF);
  1.2229 -	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
  1.2230 -
  1.2231 -	IA32_Push_Reg(jit, REG_EAX);
  1.2232 -	IA32_Fistp_Mem32_ESP(jit);
  1.2233 -	IA32_Pop_Reg(jit, REG_EAX);
  1.2234 -
  1.2235 -	IA32_Pop_Reg(jit, REG_ECX);
  1.2236 -	IA32_Mov_RmESP_Reg(jit, REG_ECX);
  1.2237 -	IA32_Fldcw_Mem16_ESP(jit);
  1.2238 -	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.2239 -
  1.2240 -	/* Rectify the stack */
  1.2241 -	//add edi, 4
  1.2242 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
  1.2243 -}
  1.2244 -
  1.2245 -inline void WriteOp_FloatCompare(JitWriter *jit)
  1.2246 -{
  1.2247 -	CompData *data = (CompData *)jit->data;
  1.2248 -
  1.2249 -	//fld [edi]
  1.2250 -	//fld [edi+4]
  1.2251 -	//fucomip st(0), st(1)
  1.2252 -	//mov ecx, <round_table>
  1.2253 -	//cmovz eax, [ecx+4]
  1.2254 -	//cmovb eax, [ecx+8]
  1.2255 -	//cmova eax, [ecx]
  1.2256 -	//fstp st(0)
  1.2257 -
  1.2258 -	IA32_Fld_Mem32(jit, AMX_REG_STK);
  1.2259 -	IA32_Fld_Mem32_Disp8(jit, AMX_REG_STK, 4);
  1.2260 -	IA32_Fucomip_ST0_FPUreg(jit, 1);
  1.2261 -	IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, (jit_int32_t)jit->outbase + data->jit_rounding_table);
  1.2262 -	IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_Z, 4);
  1.2263 -	IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_B, 8);
  1.2264 -	IA32_CmovCC_Rm(jit, AMX_REG_TMP, CC_A);
  1.2265 -	IA32_Fstp_FPUreg(jit, 0);
  1.2266 -
  1.2267 -	/* Rectify the stack */
  1.2268 -	//add edi, 8
  1.2269 -	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
  1.2270 -}
  1.2271 -
  1.2272 -/*************************************************
  1.2273 - *************************************************
  1.2274 - * JIT PROPER ************************************
  1.2275 - * The rest from now on is the JIT engine        *
  1.2276 - *************************************************
  1.2277 - *************************************************/
  1.2278 -
  1.2279 -cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
  1.2280 -{
  1.2281 -	sp_native_t *native;
  1.2282 -	sp_plugin_t *plugin;
  1.2283 -
  1.2284 -	plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
  1.2285 -	
  1.2286 -	native = &plugin->natives[native_idx];
  1.2287 -
  1.2288 -	ctx->n_idx = native_idx;
  1.2289 -	
  1.2290 -	/* Technically both aren't needed, I guess */
  1.2291 -	if (native->status == SP_NATIVE_UNBOUND)
  1.2292 -	{
  1.2293 -		ctx->n_err = SP_ERROR_INVALID_NATIVE;
  1.2294 -		return 0;
  1.2295 -	}
  1.2296 -
  1.2297 -	return native->pfn(GET_CONTEXT(ctx), params);
  1.2298 -}
  1.2299 -
  1.2300 -cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
  1.2301 -{
  1.2302 -	cell_t val;
  1.2303 -	sp_native_t *native;
  1.2304 -	sp_plugin_t *plugin;
  1.2305 -
  1.2306 -	plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
  1.2307 -
  1.2308 -	native = &plugin->natives[native_idx];
  1.2309 -
  1.2310 -	ctx->n_idx = native_idx;
  1.2311 -
  1.2312 -	/* Technically both aren't needed, I guess */
  1.2313 -	if (native->status == SP_NATIVE_UNBOUND)
  1.2314 -	{
  1.2315 -		ctx->n_err = SP_ERROR_INVALID_NATIVE;
  1.2316 -		return 0;
  1.2317 -	}
  1.2318 -
  1.2319 -	plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
  1.2320 -	val = native->pfn(GET_CONTEXT(ctx), params);
  1.2321 -	plugin->profiler->OnNativeEnd();
  1.2322 -
  1.2323 -	return val;
  1.2324 -}
  1.2325 -
  1.2326 -cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
  1.2327 -{
  1.2328 -	cell_t save_sp = ctx->sp;
  1.2329 -	cell_t save_hp = ctx->hp;
  1.2330 -
  1.2331 -	sp_plugin_t *pl = GETPLUGIN(ctx);
  1.2332 -
  1.2333 -	ctx->n_idx = native_idx;
  1.2334 -
  1.2335 -	if (ctx->hp < (cell_t)pl->data_size)
  1.2336 -	{
  1.2337 -		ctx->n_err = SP_ERROR_HEAPMIN;
  1.2338 -		return 0;
  1.2339 -	}
  1.2340 -
  1.2341 -	if (ctx->hp + STACK_MARGIN > ctx->sp)
  1.2342 -	{
  1.2343 -		ctx->n_err = SP_ERROR_STACKLOW;
  1.2344 -		return 0;
  1.2345 -	}
  1.2346 -
  1.2347 -	if ((uint32_t)ctx->sp >= pl->mem_size)
  1.2348 -	{
  1.2349 -		ctx->n_err = SP_ERROR_STACKMIN;
  1.2350 -		return 0;
  1.2351 -	}
  1.2352 -
  1.2353 -	cell_t result = NativeCallback(ctx, native_idx, params);
  1.2354 -
  1.2355 -	if (ctx->n_err != SP_ERROR_NONE)
  1.2356 -	{
  1.2357 -		return result;
  1.2358 -	}
  1.2359 -
  1.2360 -	if (save_sp != ctx->sp)
  1.2361 -	{
  1.2362 -		ctx->n_err = SP_ERROR_STACKLEAK;
  1.2363 -		return result;
  1.2364 -	}
  1.2365 -	else if (save_hp != ctx->hp)
  1.2366 -	{
  1.2367 -		ctx->n_err = SP_ERROR_HEAPLEAK;
  1.2368 -		return result;
  1.2369 -	}
  1.2370 -
  1.2371 -	return result;
  1.2372 -}
  1.2373 -
  1.2374 -cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
  1.2375 -{
  1.2376 -	cell_t save_sp = ctx->sp;
  1.2377 -	cell_t save_hp = ctx->hp;
  1.2378 -
  1.2379 -	sp_plugin_t *pl = GETPLUGIN(ctx);
  1.2380 -
  1.2381 -	ctx->n_idx = native_idx;
  1.2382 -
  1.2383 -	if (ctx->hp < (cell_t)pl->data_size)
  1.2384 -	{
  1.2385 -		ctx->n_err = SP_ERROR_HEAPMIN;
  1.2386 -		return 0;
  1.2387 -	}
  1.2388 -
  1.2389 -	if (ctx->hp + STACK_MARGIN > ctx->sp)
  1.2390 -	{
  1.2391 -		ctx->n_err = SP_ERROR_STACKLOW;
  1.2392 -		return 0;
  1.2393 -	}
  1.2394 -
  1.2395 -	if ((uint32_t)ctx->sp >= pl->mem_size)
  1.2396 -	{
  1.2397 -		ctx->n_err = SP_ERROR_STACKMIN;
  1.2398 -		return 0;
  1.2399 -	}
  1.2400 -
  1.2401 -	cell_t result = NativeCallback_Profile(ctx, native_idx, params);
  1.2402 -
  1.2403 -	if (ctx->n_err != SP_ERROR_NONE)
  1.2404 -	{
  1.2405 -		return result;
  1.2406 -	}
  1.2407 -
  1.2408 -	if (save_sp != ctx->sp)
  1.2409 -	{
  1.2410 -		ctx->n_err = SP_ERROR_STACKLEAK;
  1.2411 -		return result;
  1.2412 -	}
  1.2413 -	else if (save_hp != ctx->hp)
  1.2414 -	{
  1.2415 -		ctx->n_err = SP_ERROR_HEAPLEAK;
  1.2416 -		return result;
  1.2417 -	}
  1.2418 -
  1.2419 -	return result;
  1.2420 -}
  1.2421 -
  1.2422 -static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
  1.2423 -{
  1.2424 -	return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
  1.2425 -}
  1.2426 -
  1.2427 -jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
  1.2428 -{
  1.2429 -	if (jit->outptr)
  1.2430 -	{
  1.2431 -		CompData *data = (CompData *)jit->data;
  1.2432 -		if (relative)
  1.2433 -		{
  1.2434 -			/* The actual offset is EIP relative. We need to relocate it.
  1.2435 -			 * Note that this assumes that we're pointing to the next op.
  1.2436 -			 */
  1.2437 -			pcode_offs += jit->get_inputpos();
  1.2438 -		}
  1.2439 -		/* Offset must always be 1)positive and 2)less than or equal to the codesize */
  1.2440 -		assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
  1.2441 -		/* Do the lookup in the native dictionary. */
  1.2442 -		return *(jitoffs_t *)(data->rebase + pcode_offs);
  1.2443 -	}
  1.2444 -	else
  1.2445 -	{
  1.2446 -		return 0;
  1.2447 -	}
  1.2448 -}
  1.2449 -
  1.2450 -void WriteErrorRoutines(CompData *data, JitWriter *jit)
  1.2451 -{
  1.2452 -	AlignMe(jit);
  1.2453 -
  1.2454 -	data->jit_error_divzero = jit->get_outputpos();
  1.2455 -	Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO);
  1.2456 -
  1.2457 -	data->jit_error_stacklow = jit->get_outputpos();
  1.2458 -	Write_SetError(jit, SP_ERROR_STACKLOW);
  1.2459 -
  1.2460 -	data->jit_error_stackmin = jit->get_outputpos();
  1.2461 -	Write_SetError(jit, SP_ERROR_STACKMIN);
  1.2462 -
  1.2463 -	data->jit_error_bounds = jit->get_outputpos();
  1.2464 -	Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS);
  1.2465 -
  1.2466 -	data->jit_error_memaccess = jit->get_outputpos();
  1.2467 -	Write_SetError(jit, SP_ERROR_MEMACCESS);
  1.2468 -
  1.2469 -	data->jit_error_heaplow = jit->get_outputpos();
  1.2470 -	Write_SetError(jit, SP_ERROR_HEAPLOW);
  1.2471 -
  1.2472 -	data->jit_error_heapmin = jit->get_outputpos();
  1.2473 -	Write_SetError(jit, SP_ERROR_HEAPMIN);
  1.2474 -
  1.2475 -	data->jit_error_array_too_big = jit->get_outputpos();
  1.2476 -	Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG);
  1.2477 -
  1.2478 -	data->jit_extern_error = jit->get_outputpos();
  1.2479 -	Write_GetError(jit);
  1.2480 -}
  1.2481 -
  1.2482 -bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
  1.2483 -{
  1.2484 -	CompData *data = (CompData *)co;
  1.2485 -	sp_plugin_t *plugin = data->plugin;
  1.2486 -
  1.2487 -	if (data->plugin == NULL)
  1.2488 -	{
  1.2489 -		if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
  1.2490 -		{
  1.2491 -			if (err != NULL)
  1.2492 -			{
  1.2493 -				*err = SP_ERROR_NOTDEBUGGING;
  1.2494 -			}
  1.2495 -			co->Abort();
  1.2496 -			return false;
  1.2497 -		}
  1.2498 -
  1.2499 -		data->SetRuntime(prt);
  1.2500 -		plugin = data->plugin;
  1.2501 -	}
  1.2502 -
  1.2503 -	/* The first phase is to browse */
  1.2504 -	uint8_t *code = plugin->pcode;
  1.2505 -	uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
  1.2506 -	OPCODE op;
  1.2507 -
  1.2508 -	/*********************************************
  1.2509 -	 * FIRST PASS (medium load): writer.outbase is NULL, getting size only
  1.2510 -	 * SECOND PASS (heavy load!!): writer.outbase is valid and output is written
  1.2511 -	 *********************************************/
  1.2512 -
  1.2513 -	JitWriter writer;
  1.2514 -	JitWriter *jit = &writer;
  1.2515 -	cell_t *endptr = (cell_t *)(end_cip);
  1.2516 -	uint32_t codemem = 0;
  1.2517 -
  1.2518 -	/* Initial code is written "blank,"
  1.2519 -	 * so we can check the exact memory usage.
  1.2520 -	 */
  1.2521 -	data->codesize = plugin->pcode_size;
  1.2522 -	writer.data = data;
  1.2523 -	writer.inbase = (cell_t *)code;
  1.2524 -	writer.outptr = NULL;
  1.2525 -	writer.outbase = NULL;
  1.2526 -	/* Allocate relocation.  One extra cell for final CIP. */
  1.2527 -	data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t));
  1.2528 -
  1.2529 -	/* We will jump back here for second pass */
  1.2530 -jit_rewind:
  1.2531 -	/* Initialize pass vars */
  1.2532 -	writer.inptr = writer.inbase;
  1.2533 -	data->jit_verify_addr_eax = 0;
  1.2534 -	data->jit_verify_addr_edx = 0;
  1.2535 -
  1.2536 -	/* Write the prologue of the JIT */
  1.2537 -	data->jit_return = Write_Execute_Function(jit);
  1.2538 -
  1.2539 -	/* Write the SYSREQ.N opcode if we need to */
  1.2540 -	if (!(data->inline_level & JIT_INLINE_NATIVES))
  1.2541 -	{
  1.2542 -		AlignMe(jit);
  1.2543 -		data->jit_sysreq_n = jit->get_outputpos();
  1.2544 -		WriteOp_Sysreq_N_Function(jit);
  1.2545 -	}
  1.2546 -
  1.2547 -	/* Write the debug section if we need it */
  1.2548 -	if (data->debug == true)
  1.2549 -	{
  1.2550 -		AlignMe(jit);
  1.2551 -		data->jit_break = jit->get_outputpos();
  1.2552 -		Write_BreakDebug(jit);
  1.2553 -	}
  1.2554 -
  1.2555 -	/* Plugins compiled with -O0 will need this! */
  1.2556 -	AlignMe(jit);
  1.2557 -	data->jit_sysreq_c = jit->get_outputpos();
  1.2558 -	WriteOp_Sysreq_C_Function(jit);
  1.2559 -
  1.2560 -	AlignMe(jit);
  1.2561 -	data->jit_genarray = jit->get_outputpos();
  1.2562 -	WriteIntrinsic_GenArray(jit);
  1.2563 -
  1.2564 -	/* Write error checking routines that are called to */
  1.2565 -	if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
  1.2566 -	{
  1.2567 -		AlignMe(jit);
  1.2568 -		data->jit_verify_addr_eax = jit->get_outputpos();
  1.2569 -		Write_Check_VerifyAddr(jit, REG_EAX);
  1.2570 -	
  1.2571 -		AlignMe(jit);
  1.2572 -		data->jit_verify_addr_edx = jit->get_outputpos();
  1.2573 -		Write_Check_VerifyAddr(jit, REG_EDX);
  1.2574 -	}
  1.2575 -
  1.2576 -	/* Write the rounding table for the float compare opcode */
  1.2577 -	data->jit_rounding_table = jit->get_outputpos();
  1.2578 -	Write_RoundingTable(jit);
  1.2579 -
  1.2580 -	/* Actual code generation! */
  1.2581 -	if (writer.outbase == NULL)
  1.2582 -	{
  1.2583 -		/* First Pass - find codesize and resolve relocation */
  1.2584 -		jitoffs_t pcode_offs;
  1.2585 -		jitoffs_t native_offs;
  1.2586 -
  1.2587 -		for (; writer.inptr < endptr;)
  1.2588 -		{
  1.2589 -			/* Store the native offset into the rebase memory.
  1.2590 -			 * This large chunk of memory lets us do an instant lookup
  1.2591 -			 * based on an original pcode offset.
  1.2592 -			 */
  1.2593 -			pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
  1.2594 -			native_offs = jit->get_outputpos();
  1.2595 -			*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
  1.2596 -
  1.2597 -			/* Now read the opcode and continue. */
  1.2598 -			op = (OPCODE)writer.read_cell();
  1.2599 -
  1.2600 -			/* Patch the floating point natives with our opcodes */
  1.2601 -			if (op == OP_SYSREQ_N)
  1.2602 -			{
  1.2603 -				cell_t idx = writer.read_cell();
  1.2604 -				if (data->jit_float_table[idx].found)
  1.2605 -				{
  1.2606 -					writer.inptr -= 2;
  1.2607 -					*(writer.inptr++) = data->jit_float_table[idx].index;
  1.2608 -					*(writer.inptr++) = OP_NOP;
  1.2609 -					*(writer.inptr++) = OP_NOP;
  1.2610 -					op = (OPCODE)data->jit_float_table[idx].index;
  1.2611 -				}
  1.2612 -				else
  1.2613 -				{
  1.2614 -					writer.inptr--;
  1.2615 -				}
  1.2616 -			}
  1.2617 -			switch (op)
  1.2618 -			{
  1.2619 -				#include "opcode_switch.inc"
  1.2620 -			}
  1.2621 -			/* Check for errors.  This should only happen in the first pass. */
  1.2622 -			if (data->error_set != SP_ERROR_NONE)
  1.2623 -			{
  1.2624 -				*err = data->error_set;
  1.2625 -				co->Abort();
  1.2626 -				return false;
  1.2627 -			}
  1.2628 -		}
  1.2629 -		/* Write these last because error jumps should be unpredicted, and thus forward */
  1.2630 -		WriteErrorRoutines(data, jit);
  1.2631 -
  1.2632 -		/* Write the final CIP to the last position in the reloc array */
  1.2633 -		pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
  1.2634 -		native_offs = jit->get_outputpos();
  1.2635 -		*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
  1.2636 -
  1.2637 -		/* the total codesize is now known! */
  1.2638 -		codemem = writer.get_outputpos();
  1.2639 -		writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem);
  1.2640 -		engine->SetReadWrite(writer.outbase);
  1.2641 -		writer.outptr = writer.outbase;
  1.2642 -		/* go back for third pass */
  1.2643 -		goto jit_rewind;
  1.2644 -	}
  1.2645 -	else
  1.2646 -	{
  1.2647 -		/*******
  1.2648 -		 * THIRD PASS - write opcode info
  1.2649 -		 *******/
  1.2650 -		for (; writer.inptr < endptr;)
  1.2651 -		{
  1.2652 -			op = (OPCODE)writer.read_cell();
  1.2653 -			switch (op)
  1.2654 -			{
  1.2655 -				#include "opcode_switch.inc"
  1.2656 -			}
  1.2657 -		}
  1.2658 -		/* Write these last because error jumps should be unpredicted, and thus forward */
  1.2659 -		WriteErrorRoutines(data, jit);
  1.2660 -
  1.2661 -		engine->SetReadExecute(writer.outbase);
  1.2662 -	}
  1.2663 -
  1.2664 -	/*************
  1.2665 -	 * FOURTH PASS - Context Setup
  1.2666 -	 *************/
  1.2667 -
  1.2668 -	/* setup  basics */
  1.2669 -	sp_context_t *ctx = data->runtime->GetBaseContext()->GetCtx();
  1.2670 -
  1.2671 -	/* Clear out any old cruft */
  1.2672 -	if (plugin->codebase != NULL)
  1.2673 -	{
  1.2674 -		FreePluginVars(data->runtime->m_pPlugin);
  1.2675 -		FreeContextVars(ctx);
  1.2676 -	}
  1.2677 -	
  1.2678 -	plugin->codebase = writer.outbase;
  1.2679 -	plugin->jit_codesize = codemem;
  1.2680 -	plugin->jit_memsize = 0;
  1.2681 -
  1.2682 -	/* setup memory */
  1.2683 -
  1.2684 -	ctx->hp = plugin->data_size;
  1.2685 -	ctx->sp = plugin->mem_size - sizeof(cell_t);
  1.2686 -	ctx->frm = ctx->sp;
  1.2687 -	ctx->n_err = SP_ERROR_NONE;
  1.2688 -	ctx->n_idx = SP_ERROR_NONE;
  1.2689 -	plugin->prof_flags = data->profile;
  1.2690 -	plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
  1.2691 -
  1.2692 -	const char *strbase = plugin->info.stringbase;
  1.2693 -	uint32_t max, iter;
  1.2694 -
  1.2695 -	/* relocate public info */
  1.2696 -	if ((max = plugin->info.publics_num))
  1.2697 -	{
  1.2698 -		plugin->publics = new sp_public_t[max];
  1.2699 -		plugin->jit_memsize += sizeof(sp_public_t) * max;
  1.2700 -		for (iter=0; iter<max; iter++)
  1.2701 -		{
  1.2702 -			plugin->publics[iter].name = strbase + plugin->info.publics[iter].name;
  1.2703 -			plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
  1.2704 -			/* Encode the ID as a straight code offset */
  1.2705 -			plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
  1.2706 -		}
  1.2707 -	}
  1.2708 -
  1.2709 -	/* relocate pubvar info */
  1.2710 -	if ((max = plugin->info.pubvars_num))
  1.2711 -	{
  1.2712 -		uint8_t *dat = plugin->memory;
  1.2713 -		plugin->pubvars = new sp_pubvar_t[max];
  1.2714 -		plugin->jit_memsize += sizeof(sp_pubvar_t) * max;
  1.2715 -		for (iter=0; iter<max; iter++)
  1.2716 -		{
  1.2717 -			plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
  1.2718 -			plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
  1.2719 -		}
  1.2720 -	}
  1.2721 -
  1.2722 -	/* relocate native info */
  1.2723 -	if ((max = plugin->info.natives_num))
  1.2724 -	{
  1.2725 -		plugin->natives = new sp_native_t[max];
  1.2726 -		plugin->jit_memsize += sizeof(sp_native_t) * max;
  1.2727 -		for (iter=0; iter<max; iter++)
  1.2728 -		{
  1.2729 -			plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
  1.2730 -			plugin->natives[iter].pfn = &InvalidNative;
  1.2731 -			plugin->natives[iter].status = SP_NATIVE_UNBOUND;
  1.2732 -			plugin->natives[iter].flags = 0;
  1.2733 -			plugin->natives[iter].user = NULL;
  1.2734 -		}
  1.2735 -	}
  1.2736 -
  1.2737 -	/**
  1.2738 -	 * If we're debugging, make sure we copy the necessary info.
  1.2739 -	 */
  1.2740 -	if (data->debug)
  1.2741 -	{
  1.2742 -		strbase = plugin->debug.stringbase;
  1.2743 -		
  1.2744 -		/* relocate files */
  1.2745 -		max = plugin->debug.files_num;
  1.2746 -		plugin->files = new sp_debug_file_t[max];
  1.2747 -		plugin->jit_memsize += sizeof(sp_debug_file_t) * max;
  1.2748 -		for (iter=0; iter<max; iter++)
  1.2749 -		{
  1.2750 -			plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
  1.2751 -			plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
  1.2752 -		}
  1.2753 -
  1.2754 -		/* relocate lines */
  1.2755 -		max = plugin->debug.lines_num;
  1.2756 -		plugin->lines = new sp_debug_line_t[max];
  1.2757 -		plugin->jit_memsize += sizeof(sp_debug_line_t) * max;
  1.2758 -		for (iter=0; iter<max; iter++)
  1.2759 -		{
  1.2760 -			plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
  1.2761 -			plugin->lines[iter].line = plugin->debug.lines[iter].line;
  1.2762 -		}
  1.2763 -
  1.2764 -		/* relocate arrays */
  1.2765 -		sp_fdbg_symbol_t *sym;
  1.2766 -		sp_fdbg_arraydim_t *arr;
  1.2767 -		uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
  1.2768 -		
  1.2769 -		max = plugin->debug.syms_num;
  1.2770 -		plugin->symbols = new sp_debug_symbol_t[max];
  1.2771 -		plugin->jit_memsize += sizeof(sp_debug_symbol_t) * max;
  1.2772 -		for (iter=0; iter<max; iter++)
  1.2773 -		{
  1.2774 -			sym = (sp_fdbg_symbol_t *)cursor;
  1.2775 -
  1.2776 -			/**
  1.2777 -			 * @brief There is an "issue" where the compiler will give totally bogus code 
  1.2778 -			 * address because codegeneration is still being calculated.  A simple fix for 
  1.2779 -			 * this is to coerce the codestart value to 0 when it's invalid.
  1.2780 -			 */
  1.2781 -			if (sym->codestart > data->codesize)
  1.2782 -			{
  1.2783 -				plugin->symbols[iter].codestart = 0;
  1.2784 -			} else {
  1.2785 -				plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
  1.2786 -			}
  1.2787 -			if (sym->codeend > data->codesize)
  1.2788 -			{
  1.2789 -				plugin->symbols[iter].codeend = data->codesize;
  1.2790 -			} else {
  1.2791 -				plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
  1.2792 -			}
  1.2793 -			plugin->symbols[iter].name = strbase + sym->name;
  1.2794 -			plugin->symbols[iter].sym = sym;
  1.2795 -
  1.2796 -			if (sym->dimcount > 0)
  1.2797 -			{
  1.2798 -				cursor += sizeof(sp_fdbg_symbol_t);
  1.2799 -				arr = (sp_fdbg_arraydim_t *)cursor;
  1.2800 -				plugin->symbols[iter].dims = arr;
  1.2801 -				cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
  1.2802 -				continue;
  1.2803 -			}
  1.2804 -
  1.2805 -			plugin->symbols[iter].dims = NULL;
  1.2806 -			cursor += sizeof(sp_fdbg_symbol_t);
  1.2807 -		}
  1.2808 -	}
  1.2809 -
  1.2810 -	tracker_t *trk = new tracker_t;
  1.2811 -	ctx->vm[JITVARS_TRACKER] = trk;
  1.2812 -	ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
  1.2813 -	ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
  1.2814 -	ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
  1.2815 -	trk->pBase = (ucell_t *)malloc(1024);
  1.2816 -	trk->pCur = trk->pBase;
  1.2817 -	trk->size = 1024 / sizeof(cell_t);
  1.2818 -
  1.2819 -	plugin->jit_memsize += trk->size;
  1.2820 -
  1.2821 -	/* clean up relocation+compilation memory */
  1.2822 -	co->Abort();
  1.2823 -
  1.2824 -	*err = SP_ERROR_NONE;
  1.2825 -
  1.2826 -	return true;
  1.2827 -}
  1.2828 -
  1.2829 -SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
  1.2830 -{
  1.2831 -	JitWriter jw;
  1.2832 -	JitWriter *jit = &jw;
  1.2833 -
  1.2834 -	jw.outbase = NULL;
  1.2835 -	jw.outptr = NULL;
  1.2836 -	jw.data = NULL;
  1.2837 -
  1.2838 -	/* First pass, calculate size */
  1.2839 -rewind:
  1.2840 -	/* Align the stack to 16 bytes */
  1.2841 -	//push ebx
  1.2842 -	//push edi
  1.2843 -	//push esi
  1.2844 -	//mov edi, [esp+16]	;store ctx
  1.2845 -	//mov esi, [esp+20]	;store params
  1.2846 -	//mov ebx, esp
  1.2847 -	//and esp, 0xFFFFFF0
  1.2848 -	//sub esp, 4
  1.2849 -	IA32_Push_Reg(jit, REG_EBX);
  1.2850 -	IA32_Push_Reg(jit, REG_EDI);
  1.2851 -	IA32_Push_Reg(jit, REG_ESI);
  1.2852 -	IA32_Mov_Reg_Esp_Disp8(jit, REG_EDI, 16);
  1.2853 -	IA32_Mov_Reg_Esp_Disp8(jit, REG_ESI, 20);
  1.2854 -	IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
  1.2855 -	IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
  1.2856 -	IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
  1.2857 -
  1.2858 -	//push pData		;push pData
  1.2859 -	//push esi			;push params
  1.2860 -	//push edi			;push ctx
  1.2861 -	//call [callback]	;invoke the meta-callback
  1.2862 -	//mov esp, ebx		;restore the stack
  1.2863 -	//pop esi			;restore esi
  1.2864 -	//pop edi			;restore edi
  1.2865 -	//pop ebx			;restore ebx
  1.2866 -	//ret				;return
  1.2867 -	IA32_Push_Imm32(jit, (jit_int32_t)pData);
  1.2868 -	IA32_Push_Reg(jit, REG_ESI);
  1.2869 -	IA32_Push_Reg(jit, REG_EDI);
  1.2870 -	uint32_t call = IA32_Call_Imm32(jit, 0);
  1.2871 -	IA32_Write_Jump32_Abs(jit, call, (void *)callback);
  1.2872 -	IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
  1.2873 -	IA32_Pop_Reg(jit, REG_ESI);
  1.2874 -	IA32_Pop_Reg(jit, REG_EDI);
  1.2875 -	IA32_Pop_Reg(jit, REG_EBX);
  1.2876 -	IA32_Return(jit);
  1.2877 -
  1.2878 -	if (jw.outbase == NULL)
  1.2879 -	{
  1.2880 -		/* Second pass: Actually write */
  1.2881 -		jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos());
  1.2882 -		if (!jw.outbase)
  1.2883 -		{
  1.2884 -			return NULL;
  1.2885 -		}
  1.2886 -		engine->SetReadWrite(jw.outbase);
  1.2887 -		jw.outptr = jw.outbase;
  1.2888 -	
  1.2889 -		goto rewind;
  1.2890 -	}
  1.2891 -
  1.2892 -	engine->SetReadExecute(jw.outbase);
  1.2893 -
  1.2894 -	return (SPVM_NATIVE_FUNC)jw.outbase;
  1.2895 -}
  1.2896 -
  1.2897 -void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
  1.2898 -{
  1.2899 -	engine->FreePageMemory((void *)func);
  1.2900 -}
  1.2901 -
  1.2902 -int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
  1.2903 -{
  1.2904 -	typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
  1.2905 - 	CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)pl->codebase;
  1.2906 -	return fn(ctx, code_idx, result);
  1.2907 -}
  1.2908 -
  1.2909 -ICompilation *JITX86::StartCompilation()
  1.2910 -{
  1.2911 -	CompData *data = new CompData;
  1.2912 -
  1.2913 -	data->jit_float_table = NULL;
  1.2914 -
  1.2915 -	return data;
  1.2916 -}
  1.2917 -
  1.2918 -void CompData::SetRuntime(BaseRuntime *runtime)
  1.2919 -{
  1.2920 -	plugin = runtime->m_pPlugin;
  1.2921 -
  1.2922 -	uint32_t max_natives = plugin->info.natives_num;
  1.2923 -	const char *strbase = plugin->info.stringbase;
  1.2924 -
  1.2925 -	this->runtime = runtime;
  1.2926 -
  1.2927 -	inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
  1.2928 -	error_set = SP_ERROR_NONE;
  1.2929 -
  1.2930 -	jit_float_table = new floattbl_t[max_natives];
  1.2931 -	for (uint32_t i=0; i<max_natives; i++)
  1.2932 -	{
  1.2933 -		const char *name = strbase + plugin->info.natives[i].name;
  1.2934 -		if (!strcmp(name, "FloatAbs"))
  1.2935 -		{
  1.2936 -			jit_float_table[i].found = true;
  1.2937 -			jit_float_table[i].index = OP_FABS;
  1.2938 -		} else if (!strcmp(name, "FloatAdd")) {
  1.2939 -			jit_float_table[i].found = true;
  1.2940 -			jit_float_table[i].index = OP_FLOATADD;
  1.2941 -		} else if (!strcmp(name, "FloatSub")) {
  1.2942 -			jit_float_table[i].found = true;
  1.2943 -			jit_float_table[i].index = OP_FLOATSUB;
  1.2944 -		} else if (!strcmp(name, "FloatMul")) {
  1.2945 -			jit_float_table[i].found = true;
  1.2946 -			jit_float_table[i].index = OP_FLOATMUL;
  1.2947 -		} else if (!strcmp(name, "FloatDiv")) {
  1.2948 -			jit_float_table[i].found = true;
  1.2949 -			jit_float_table[i].index = OP_FLOATDIV;
  1.2950 -		} else if (!strcmp(name, "float")) {
  1.2951 -			jit_float_table[i].found = true;
  1.2952 -			jit_float_table[i].index = OP_FLOAT;
  1.2953 -		} else if (!strcmp(name, "FloatCompare")) {
  1.2954 -			jit_float_table[i].found = true;
  1.2955 -			jit_float_table[i].index = OP_FLOATCMP;
  1.2956 -		} else if (!strcmp(name, "RoundToZero")) {
  1.2957 -			jit_float_table[i].found = true;
  1.2958 -			jit_float_table[i].index = OP_RND_TO_ZERO;
  1.2959 -		} else if (!strcmp(name, "RoundToCeil")) {
  1.2960 -			jit_float_table[i].found = true;
  1.2961 -			jit_float_table[i].index = OP_RND_TO_CEIL;
  1.2962 -		} else if (!strcmp(name, "RoundToFloor")) {
  1.2963 -			jit_float_table[i].found = true;
  1.2964 -			jit_float_table[i].index = OP_RND_TO_FLOOR;
  1.2965 -		} else if (!strcmp(name, "RoundToNearest")) {
  1.2966 -			jit_float_table[i].found = true;
  1.2967 -			jit_float_table[i].index = OP_RND_TO_NEAREST;
  1.2968 -		}
  1.2969 -	}
  1.2970 -}
  1.2971 -
  1.2972 -ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
  1.2973 -{
  1.2974 -	CompData *data = new CompData;
  1.2975 -
  1.2976 -	data->SetRuntime(runtime);
  1.2977 -
  1.2978 -	return data;
  1.2979 -}
  1.2980 -
  1.2981 -void CompData::Abort()
  1.2982 -{
  1.2983 -	if (rebase)
  1.2984 -	{
  1.2985 -		engine->BaseFree(rebase);
  1.2986 -	}
  1.2987 -	delete [] jit_float_table;
  1.2988 -	delete this;
  1.2989 -}
  1.2990 -
  1.2991 -void JITX86::FreeContextVars(sp_context_t *ctx)
  1.2992 -{
  1.2993 -	free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
  1.2994 -	delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
  1.2995 -}
  1.2996 -
  1.2997 -void JITX86::FreePluginVars(sp_plugin_t *pl)
  1.2998 -{
  1.2999 -	delete [] pl->files;
  1.3000 -	delete [] pl->lines;
  1.3001 -	delete [] pl->natives;
  1.3002 -	delete [] pl->publics;
  1.3003 -	delete [] pl->pubvars;
  1.3004 -	delete [] pl->symbols;
  1.3005 -
  1.3006 -	if (pl->codebase != NULL)
  1.3007 -	{
  1.3008 -		g_engine1.FreePageMemory(pl->codebase);
  1.3009 -		pl->codebase = NULL;
  1.3010 -	}
  1.3011 -
  1.3012 -	pl->files = NULL;
  1.3013 -	pl->lines = NULL;
  1.3014 -	pl->natives = NULL;
  1.3015 -	pl->publics = NULL;
  1.3016 -	pl->pubvars = NULL;
  1.3017 -	pl->symbols = NULL;
  1.3018 -}
  1.3019 -
  1.3020 -bool CompData::SetOption(const char *key, const char *val)
  1.3021 -{
  1.3022 -	if (strcmp(key, SP_JITCONF_DEBUG) == 0)
  1.3023 -	{
  1.3024 -		if ((atoi(val) == 1) || !strcmp(val, "yes"))
  1.3025 -		{
  1.3026 -			debug = true;
  1.3027 -		} else {
  1.3028 -			debug = false;
  1.3029 -		}
  1.3030 -		if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
  1.3031 -		{
  1.3032 -			debug = false;
  1.3033 -			return false;
  1.3034 -		}
  1.3035 -		return true;
  1.3036 -	}
  1.3037 -	else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
  1.3038 -	{
  1.3039 -		profile = atoi(val);
  1.3040 -
  1.3041 -		/** Callbacks must be profiled to profile functions! */
  1.3042 -		if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
  1.3043 -		{
  1.3044 -			profile |= SP_PROF_CALLBACKS;
  1.3045 -		}
  1.3046 -
  1.3047 -		return true;
  1.3048 -	}
  1.3049 -
  1.3050 -	return false;
  1.3051 -}
  1.3052 -