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 -