sourcepawn/jit/x86/jit_x86.cpp
author David Anderson <dvander@alliedmods.net>
Fri Jul 11 08:18:43 2008 +0000 (2008-07-11)
changeset 2193 db7c6362f3f2
parent 2114 959cf6b537c5
child 2195 5b70179559f9
permissions -rw-r--r--
landed massive refactoring of the JIT. contexts are actually contexts now, and a higher level structure wraps sp_plugin_t info. on that note, both sp_plugin_t and sp_context_t are entirely opaque, and not even core has access to them. amazingly, i managed to keep binary compatibility here although a large number of functions are deprecated (and core should eventually stop calling them).

NOTE: the JIT is now embeddable out-of-box and usable by other projects which is pretty cool. I will commit a shell app demonstrating this soon
ds@1952
     1
/**
ds@1952
     2
 * vim: set ts=4 :
ds@1952
     3
 * =============================================================================
dvander@2114
     4
 * SourceMod
dvander@2114
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1952
     6
 * =============================================================================
ds@1952
     7
 *
dvander@2114
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2114
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2114
    10
 * Free Software Foundation.
dvander@2114
    11
 * 
dvander@2114
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2114
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2114
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2114
    15
 * details.
dvander@2114
    16
 *
dvander@2114
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2114
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2114
    19
 *
dvander@2114
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2114
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2114
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2114
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2114
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2114
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2114
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2114
    27
 * or <http://www.sourcemod.net/license.php>.
ds@1952
    28
 *
ds@1952
    29
 * Version: $Id$
ds@1952
    30
 */
ds@1952
    31
ds@1952
    32
#include <string.h>
ds@1952
    33
#include <stdlib.h>
ds@1952
    34
#include <assert.h>
ds@1952
    35
#include "jit_x86.h"
ds@1952
    36
#include "opcode_helpers.h"
ds@1952
    37
#include <x86_macros.h>
dvander@2193
    38
#include "../jit_version.h"
dvander@2193
    39
#include "../sp_vm_engine.h"
dvander@2193
    40
#include "../engine2.h"
dvander@2193
    41
#include "../BaseRuntime.h"
dvander@2193
    42
#include "../sp_vm_basecontext.h"
ds@1952
    43
ds@1952
    44
#if defined USE_UNGEN_OPCODES
ds@1952
    45
#include "ungen_opcodes.h"
ds@1952
    46
#endif
ds@1952
    47
dvander@2193
    48
JITX86 g_Jit1;
dvander@2193
    49
ISourcePawnEngine *engine = &g_engine1;
dvander@2193
    50
dvander@2193
    51
inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
dvander@2193
    52
{
dvander@2193
    53
	return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
dvander@2193
    54
}
dvander@2193
    55
ds@1952
    56
inline void WriteOp_Move_Pri(JitWriter *jit)
ds@1952
    57
{
ds@1952
    58
	//mov eax, edx
ds@1952
    59
	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
    60
}
ds@1952
    61
ds@1952
    62
inline void WriteOp_Move_Alt(JitWriter *jit)
ds@1952
    63
{
ds@1952
    64
	//mov edx, eax
ds@1952
    65
	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
ds@1952
    66
}
ds@1952
    67
ds@1952
    68
inline void WriteOp_Xchg(JitWriter *jit)
ds@1952
    69
{
ds@1952
    70
	//xchg eax, edx
ds@1952
    71
	IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
ds@1952
    72
}
ds@1952
    73
ds@1952
    74
inline void WriteOp_Push(JitWriter *jit)
ds@1952
    75
{
ds@1952
    76
	//push stack, DAT offset based
ds@1952
    77
	//sub edi, 4
ds@1952
    78
	//mov ecx, [ebp+<val>]
ds@1952
    79
	//mov [edi], ecx
ds@1952
    80
	cell_t val = jit->read_cell();
ds@1952
    81
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
    82
	//optimize encoding a bit...
faluco@2029
    83
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
    84
	{
ds@1952
    85
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
    86
	} else {
ds@1952
    87
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
ds@1952
    88
	}
ds@1952
    89
	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
    90
}
ds@1952
    91
ds@1952
    92
inline void WriteOp_Push_C(JitWriter *jit)
ds@1952
    93
{
ds@1952
    94
	//push stack
ds@1952
    95
	//mov [edi-4], <val>
ds@1952
    96
	//sub edi, 4
ds@1952
    97
	cell_t val = jit->read_cell();
ds@1952
    98
	IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
ds@1952
    99
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   100
}
ds@1952
   101
ds@1952
   102
inline void WriteOp_Zero(JitWriter *jit)
ds@1952
   103
{
ds@1952
   104
	//mov [ebp+<val>], 0
ds@1952
   105
	cell_t val = jit->read_cell();
faluco@2029
   106
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   107
	{
ds@1952
   108
		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val);
ds@1952
   109
	} else {
ds@1952
   110
		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
ds@1952
   111
	}
ds@1952
   112
}
ds@1952
   113
ds@1952
   114
inline void WriteOp_Zero_S(JitWriter *jit)
ds@1952
   115
{
ds@1952
   116
	//mov [ebx+<val>], 0
ds@1952
   117
	cell_t val = jit->read_cell();
faluco@2029
   118
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   119
	{
ds@1952
   120
		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val);
ds@1952
   121
	} else {
ds@1952
   122
		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
ds@1952
   123
	}
ds@1952
   124
}
ds@1952
   125
ds@1952
   126
inline void WriteOp_Push_S(JitWriter *jit)
ds@1952
   127
{
ds@1952
   128
	//push stack, FRM offset based
ds@1952
   129
	//sub edi, 4
ds@1952
   130
	//mov ecx, [ebx+<val>]
ds@1952
   131
	//mov [edi], ecx
ds@1952
   132
	cell_t val = jit->read_cell();
ds@1952
   133
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   134
	//optimize encoding a bit...
faluco@2029
   135
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   136
	{
ds@1952
   137
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   138
	} else {
ds@1952
   139
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
ds@1952
   140
	}
ds@1952
   141
	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
   142
}
ds@1952
   143
ds@1952
   144
inline void WriteOp_Push_Pri(JitWriter *jit)
ds@1952
   145
{
ds@1952
   146
	//mov [edi-4], eax
ds@1952
   147
	//sub edi, 4
ds@1952
   148
	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
ds@1952
   149
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   150
}
ds@1952
   151
ds@1952
   152
inline void WriteOp_Push_Alt(JitWriter *jit)
ds@1952
   153
{
ds@1952
   154
	//mov [edi-4], edx
ds@1952
   155
	//sub edi, 4
ds@1952
   156
	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
ds@1952
   157
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   158
}
ds@1952
   159
ds@1952
   160
inline void WriteOp_Push2_C(JitWriter *jit)
ds@1952
   161
{
ds@1952
   162
	Macro_PushN_C(jit, 2);
ds@1952
   163
}
ds@1952
   164
ds@1952
   165
inline void WriteOp_Push3_C(JitWriter *jit)
ds@1952
   166
{
ds@1952
   167
	Macro_PushN_C(jit, 3);
ds@1952
   168
}
ds@1952
   169
ds@1952
   170
inline void WriteOp_Push4_C(JitWriter *jit)
ds@1952
   171
{
ds@1952
   172
	Macro_PushN_C(jit, 4);
ds@1952
   173
}
ds@1952
   174
ds@1952
   175
inline void WriteOp_Push5_C(JitWriter *jit)
ds@1952
   176
{
ds@1952
   177
	Macro_PushN_C(jit, 5);
ds@1952
   178
}
ds@1952
   179
ds@1952
   180
inline void WriteOp_Push2_Adr(JitWriter *jit)
ds@1952
   181
{
ds@1952
   182
	Macro_PushN_Addr(jit, 2);
ds@1952
   183
}
ds@1952
   184
ds@1952
   185
inline void WriteOp_Push3_Adr(JitWriter *jit)
ds@1952
   186
{
ds@1952
   187
	Macro_PushN_Addr(jit, 3);
ds@1952
   188
}
ds@1952
   189
ds@1952
   190
inline void WriteOp_Push4_Adr(JitWriter *jit)
ds@1952
   191
{
ds@1952
   192
	Macro_PushN_Addr(jit, 4);
ds@1952
   193
}
ds@1952
   194
ds@1952
   195
inline void WriteOp_Push5_Adr(JitWriter *jit)
ds@1952
   196
{
ds@1952
   197
	Macro_PushN_Addr(jit, 5);
ds@1952
   198
}
ds@1952
   199
ds@1952
   200
inline void WriteOp_Push2_S(JitWriter *jit)
ds@1952
   201
{
ds@1952
   202
	Macro_PushN_S(jit, 2);
ds@1952
   203
}
ds@1952
   204
ds@1952
   205
inline void WriteOp_Push3_S(JitWriter *jit)
ds@1952
   206
{
ds@1952
   207
	Macro_PushN_S(jit, 3);
ds@1952
   208
}
ds@1952
   209
ds@1952
   210
inline void WriteOp_Push4_S(JitWriter *jit)
ds@1952
   211
{
ds@1952
   212
	Macro_PushN_S(jit, 4);
ds@1952
   213
}
ds@1952
   214
ds@1952
   215
inline void WriteOp_Push5_S(JitWriter *jit)
ds@1952
   216
{
ds@1952
   217
	Macro_PushN_S(jit, 5);
ds@1952
   218
}
ds@1952
   219
ds@1952
   220
inline void WriteOp_Push5(JitWriter *jit)
ds@1952
   221
{
ds@1952
   222
	Macro_PushN(jit, 5);
ds@1952
   223
}
ds@1952
   224
ds@1952
   225
inline void WriteOp_Push4(JitWriter *jit)
ds@1952
   226
{
ds@1952
   227
	Macro_PushN(jit, 4);
ds@1952
   228
}
ds@1952
   229
ds@1952
   230
inline void WriteOp_Push3(JitWriter *jit)
ds@1952
   231
{
ds@1952
   232
	Macro_PushN(jit, 3);
ds@1952
   233
}
ds@1952
   234
ds@1952
   235
inline void WriteOp_Push2(JitWriter *jit)
ds@1952
   236
{
ds@1952
   237
	Macro_PushN(jit, 2);
ds@1952
   238
}
ds@1952
   239
ds@1952
   240
inline void WriteOp_Zero_Pri(JitWriter *jit)
ds@1952
   241
{
ds@1952
   242
	//xor eax, eax
ds@1952
   243
	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
ds@1952
   244
}
ds@1952
   245
ds@1952
   246
inline void WriteOp_Zero_Alt(JitWriter *jit)
ds@1952
   247
{
ds@1952
   248
	//xor edx, edx
ds@1952
   249
	IA32_Xor_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
ds@1952
   250
}
ds@1952
   251
ds@1952
   252
inline void WriteOp_Add(JitWriter *jit)
ds@1952
   253
{
ds@1952
   254
	//add eax, edx
ds@1952
   255
	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   256
}
ds@1952
   257
ds@1952
   258
inline void WriteOp_Sub(JitWriter *jit)
ds@1952
   259
{
ds@1952
   260
	//sub eax, edx
ds@1952
   261
	IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   262
}
ds@1952
   263
ds@1952
   264
inline void WriteOp_Sub_Alt(JitWriter *jit)
ds@1952
   265
{
ds@1952
   266
	//neg eax
ds@1952
   267
	//add eax, edx
ds@1952
   268
	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   269
	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   270
}
ds@1952
   271
ds@1952
   272
inline void WriteOp_Proc(JitWriter *jit)
ds@1952
   273
{
ds@1952
   274
	CompData *co = (CompData *)jit->data;
ds@1952
   275
ds@1952
   276
	/* Specialized code to align this taking in account the function magic number */
ds@1952
   277
	jitoffs_t cur_offs = jit->get_outputpos();
ds@1952
   278
	jitoffs_t offset = ((cur_offs & 0xFFFFFFF8) + 8) - cur_offs;
ds@1952
   279
	if (!((offset + cur_offs) & 8))
ds@1952
   280
	{
ds@1952
   281
		offset += 8;
ds@1952
   282
	}
ds@1952
   283
	if (offset)
ds@1952
   284
	{
ds@1952
   285
		for (jit_uint32_t i=0; i<offset; i++)
ds@1952
   286
		{
ds@1952
   287
			jit->write_ubyte(IA32_INT3);
ds@1952
   288
		}
ds@1952
   289
	}
ds@1952
   290
ds@1952
   291
	/* Write the info struct about this function */
ds@1952
   292
	jit->write_uint32(JIT_FUNCMAGIC);
ds@1952
   293
	jit->write_uint32(co->func_idx);
ds@1952
   294
ds@1952
   295
	/* Now we have to backpatch our reloction offset! */
ds@1952
   296
	{
ds@1952
   297
		jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
ds@1952
   298
		jitcode_t rebase = ((CompData *)jit->data)->rebase;
ds@1952
   299
		*(jitoffs_t *)((unsigned char  *)rebase + offs) = jit->get_outputpos();
ds@1952
   300
	}
ds@1952
   301
ds@1952
   302
	/* Lastly, if we're writing, keep track of the function count */
ds@1952
   303
	if (jit->outbase)
ds@1952
   304
	{
ds@1952
   305
		co->func_idx++;
ds@1952
   306
	}
ds@1952
   307
ds@1952
   308
	//push old frame on stack:
ds@1952
   309
	//mov ecx, [esi+frm]
ds@1952
   310
	//mov [edi-4], ecx
ds@1952
   311
	//sub edi, 8			;extra un-used slot for non-existant CIP
ds@1952
   312
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
ds@1952
   313
	IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
ds@1952
   314
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
   315
	//save frame:
ds@1952
   316
	//mov ecx, edi			- get new frame
ds@1952
   317
	//mov ebx, edi			- store frame back
ds@1952
   318
	//sub ecx, ebp			- relocate local frame
ds@1952
   319
	//mov [esi+frm], ecx
ds@1952
   320
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG);
ds@1952
   321
	IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
ds@1952
   322
	IA32_Sub_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
ds@1952
   323
	IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
   324
}
ds@1952
   325
ds@1952
   326
inline void WriteOp_Lidx_B(JitWriter *jit)
ds@1952
   327
{
ds@1952
   328
	cell_t val = jit->read_cell();
ds@1952
   329
	//shl eax, <val>
ds@1952
   330
	//add eax, edx
ds@1952
   331
	//mov eax, [ebp+eax]
ds@1952
   332
	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
ds@1952
   333
	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   334
	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
ds@1952
   335
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
   336
}
ds@1952
   337
ds@1952
   338
inline void WriteOp_Idxaddr_B(JitWriter *jit)
ds@1952
   339
{
ds@1952
   340
	//shl eax, <val>
ds@1952
   341
	//add eax, edx
ds@1952
   342
	cell_t val = jit->read_cell();
ds@1952
   343
	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
ds@1952
   344
	IA32_Add_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   345
}
ds@1952
   346
ds@1952
   347
inline void WriteOp_Shl(JitWriter *jit)
ds@1952
   348
{
ds@1952
   349
	//mov ecx, edx
ds@1952
   350
	//shl eax, cl
ds@1952
   351
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
ds@1952
   352
	IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   353
}
ds@1952
   354
ds@1952
   355
inline void WriteOp_Shr(JitWriter *jit)
ds@1952
   356
{
ds@1952
   357
	//mov ecx, edx
ds@1952
   358
	//shr eax, cl
ds@1952
   359
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
ds@1952
   360
	IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   361
}
ds@1952
   362
ds@1952
   363
inline void WriteOp_Sshr(JitWriter *jit)
ds@1952
   364
{
ds@1952
   365
	//mov ecx, edx
ds@1952
   366
	//sar eax, cl
ds@1952
   367
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
ds@1952
   368
	IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   369
}
ds@1952
   370
ds@1952
   371
inline void WriteOp_Shl_C_Pri(JitWriter *jit)
ds@1952
   372
{
ds@1952
   373
	//shl eax, <val>
ds@1952
   374
	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
ds@1952
   375
	if (val == 1)
ds@1952
   376
	{
ds@1952
   377
		IA32_Shl_Rm_1(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   378
	} else {
ds@1952
   379
		IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
ds@1952
   380
	}
ds@1952
   381
}
ds@1952
   382
ds@1952
   383
inline void WriteOp_Shl_C_Alt(JitWriter *jit)
ds@1952
   384
{
ds@1952
   385
	//shl edx, <val>
ds@1952
   386
	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
ds@1952
   387
	if (val == 1)
ds@1952
   388
	{
ds@1952
   389
		IA32_Shl_Rm_1(jit, AMX_REG_ALT, MOD_REG);
ds@1952
   390
	} else {
ds@1952
   391
		IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
ds@1952
   392
	}
ds@1952
   393
}
ds@1952
   394
ds@1952
   395
inline void WriteOp_Shr_C_Pri(JitWriter *jit)
ds@1952
   396
{
ds@1952
   397
	//shr eax, <val>
ds@1952
   398
	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
ds@1952
   399
	if (val == 1)
ds@1952
   400
	{
ds@1952
   401
		IA32_Shr_Rm_1(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   402
	} else {
ds@1952
   403
		IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
ds@1952
   404
	}
ds@1952
   405
}
ds@1952
   406
ds@1952
   407
inline void WriteOp_Shr_C_Alt(JitWriter *jit)
ds@1952
   408
{
ds@1952
   409
	//shr edx, <val>
ds@1952
   410
	jit_uint8_t val = (jit_uint8_t)jit->read_cell();
ds@1952
   411
	if (val == 1)
ds@1952
   412
	{
ds@1952
   413
		IA32_Shr_Rm_1(jit, AMX_REG_ALT, MOD_REG);
ds@1952
   414
	} else {
ds@1952
   415
		IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
ds@1952
   416
	}
ds@1952
   417
}
ds@1952
   418
ds@1952
   419
inline void WriteOp_SMul(JitWriter *jit)
ds@1952
   420
{
ds@1952
   421
	//mov ecx, edx
ds@1952
   422
	//imul edx
ds@1952
   423
	//mov edx, ecx
ds@1952
   424
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
ds@1952
   425
	IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
ds@1952
   426
	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
ds@1952
   427
}
ds@1952
   428
ds@1952
   429
inline void WriteOp_Not(JitWriter *jit)
ds@1952
   430
{
ds@1952
   431
	//test eax, eax
ds@1952
   432
	//mov eax, 0
ds@1952
   433
	//sete al
ds@1952
   434
	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
ds@1952
   435
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   436
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
ds@1952
   437
}
ds@1952
   438
ds@1952
   439
inline void WriteOp_Neg(JitWriter *jit)
ds@1952
   440
{
ds@1952
   441
	//neg eax
ds@1952
   442
	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   443
}
ds@1952
   444
ds@1952
   445
inline void WriteOp_Xor(JitWriter *jit)
ds@1952
   446
{
ds@1952
   447
	//xor eax, edx
ds@1952
   448
	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   449
}
ds@1952
   450
ds@1952
   451
inline void WriteOp_Or(JitWriter *jit)
ds@1952
   452
{
ds@1952
   453
	//or eax, edx
ds@1952
   454
	IA32_Or_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   455
}
ds@1952
   456
ds@1952
   457
inline void WriteOp_And(JitWriter *jit)
ds@1952
   458
{
ds@1952
   459
	//and eax, edx
ds@1952
   460
	IA32_And_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   461
}
ds@1952
   462
ds@1952
   463
inline void WriteOp_Invert(JitWriter *jit)
ds@1952
   464
{
ds@1952
   465
	//not eax
ds@1952
   466
	IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   467
}
ds@1952
   468
ds@1952
   469
inline void WriteOp_Add_C(JitWriter *jit)
ds@1952
   470
{
ds@1952
   471
	//add eax, <val>
ds@1952
   472
	cell_t val = jit->read_cell();
faluco@2029
   473
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   474
		IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
ds@1952
   475
	else
ds@1952
   476
		IA32_Add_Eax_Imm32(jit, val);
ds@1952
   477
}
ds@1952
   478
ds@1952
   479
inline void WriteOp_SMul_C(JitWriter *jit)
ds@1952
   480
{
ds@1952
   481
	//imul eax, <val>
ds@1952
   482
	cell_t val = jit->read_cell();
faluco@2029
   483
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   484
		IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
ds@1952
   485
	else
ds@1952
   486
		IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
ds@1952
   487
}
ds@1952
   488
ds@1952
   489
inline void WriteOp_Sign_Pri(JitWriter *jit)
ds@1952
   490
{
ds@1952
   491
	//shl eax, 24
ds@1952
   492
	//sar eax, 24
ds@1952
   493
	IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
ds@1952
   494
	IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
ds@1952
   495
}
ds@1952
   496
ds@1952
   497
inline void WriteOp_Sign_Alt(JitWriter *jit)
ds@1952
   498
{
ds@1952
   499
	//shl edx, 24
ds@1952
   500
	//sar edx, 24
ds@1952
   501
	IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
ds@1952
   502
	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
ds@1952
   503
}
ds@1952
   504
ds@1952
   505
inline void WriteOp_Eq(JitWriter *jit)
ds@1952
   506
{
ds@1952
   507
	//cmp eax, edx	; PRI == ALT ?
ds@1952
   508
	//mov eax, 0
ds@1952
   509
	//sete al
ds@1952
   510
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   511
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   512
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
ds@1952
   513
}
ds@1952
   514
ds@1952
   515
inline void WriteOp_Neq(JitWriter *jit)
ds@1952
   516
{
ds@1952
   517
	//cmp eax, edx	; PRI != ALT ?
ds@1952
   518
	//mov eax, 0
ds@1952
   519
	//setne al
ds@1952
   520
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   521
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   522
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
ds@1952
   523
}
ds@1952
   524
ds@1952
   525
inline void WriteOp_Sless(JitWriter *jit)
ds@1952
   526
{
ds@1952
   527
	//cmp eax, edx	; PRI < ALT ? (signed)
ds@1952
   528
	//mov eax, 0
ds@1952
   529
	//setl al
ds@1952
   530
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   531
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   532
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L);
ds@1952
   533
}
ds@1952
   534
ds@1952
   535
inline void WriteOp_Sleq(JitWriter *jit)
ds@1952
   536
{
ds@1952
   537
	//cmp eax, edx	; PRI <= ALT ? (signed)
ds@1952
   538
	//mov eax, 0
ds@1952
   539
	//setle al
ds@1952
   540
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   541
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   542
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE);
ds@1952
   543
}
ds@1952
   544
ds@1952
   545
inline void WriteOp_Sgrtr(JitWriter *jit)
ds@1952
   546
{
ds@1952
   547
	//cmp eax, edx	; PRI > ALT ? (signed)
ds@1952
   548
	//mov eax, 0
ds@1952
   549
	//setg al
ds@1952
   550
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   551
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   552
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G);
ds@1952
   553
}
ds@1952
   554
ds@1952
   555
inline void WriteOp_Sgeq(JitWriter *jit)
ds@1952
   556
{
ds@1952
   557
	//cmp eax, edx	; PRI >= ALT ? (signed)
ds@1952
   558
	//mov eax, 0
ds@1952
   559
	//setge al
ds@1952
   560
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
   561
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   562
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE);
ds@1952
   563
}
ds@1952
   564
ds@1952
   565
inline void WriteOp_Eq_C_Pri(JitWriter *jit)
ds@1952
   566
{
ds@1952
   567
	//cmp eax, <val>   ; PRI == value ?
ds@1952
   568
	//mov eax, 0
ds@1952
   569
	//sete al
ds@1952
   570
	cell_t val = jit->read_cell();
faluco@2029
   571
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   572
		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
ds@1952
   573
	else
ds@1952
   574
		IA32_Cmp_Eax_Imm32(jit, val);
ds@1952
   575
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
ds@1952
   576
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
ds@1952
   577
}
ds@1952
   578
ds@1952
   579
inline void WriteOp_Eq_C_Alt(JitWriter *jit)
ds@1952
   580
{
ds@1952
   581
	//xor eax, eax
ds@1952
   582
	//cmp edx, <val>   ; ALT == value ?
ds@1952
   583
	//sete al
ds@1952
   584
	cell_t val = jit->read_cell();
ds@1952
   585
	IA32_Xor_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
faluco@2029
   586
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   587
		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
ds@1952
   588
	else
ds@1952
   589
		IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
ds@1952
   590
	IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
ds@1952
   591
}
ds@1952
   592
ds@1952
   593
inline void WriteOp_Inc_Pri(JitWriter *jit)
ds@1952
   594
{
ds@1952
   595
	//add eax, 1
ds@1952
   596
	IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
ds@1952
   597
}
ds@1952
   598
ds@1952
   599
inline void WriteOp_Inc_Alt(JitWriter *jit)
ds@1952
   600
{
ds@1952
   601
	//add edx, 1
ds@1952
   602
	IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
ds@1952
   603
}
ds@1952
   604
ds@1952
   605
inline void WriteOp_Inc(JitWriter *jit)
ds@1952
   606
{
ds@1952
   607
	//add [ebp+<val>], 1
ds@1952
   608
	cell_t val = jit->read_cell();
faluco@2029
   609
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   610
		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
ds@1952
   611
	else
ds@1952
   612
		IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
ds@1952
   613
}
ds@1952
   614
ds@1952
   615
inline void WriteOp_Inc_S(JitWriter *jit)
ds@1952
   616
{
ds@1952
   617
	//add [ebx+<val>], 1
ds@1952
   618
	cell_t val = jit->read_cell();
faluco@2029
   619
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   620
		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
ds@1952
   621
	else
ds@1952
   622
		IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
ds@1952
   623
}
ds@1952
   624
ds@1952
   625
inline void WriteOp_Inc_I(JitWriter *jit)
ds@1952
   626
{
ds@1952
   627
	//add [ebp+eax], 1
ds@1952
   628
	IA32_Add_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
ds@1952
   629
}
ds@1952
   630
ds@1952
   631
inline void WriteOp_Dec_Pri(JitWriter *jit)
ds@1952
   632
{
ds@1952
   633
	//sub eax, 1
ds@1952
   634
	IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
ds@1952
   635
}
ds@1952
   636
ds@1952
   637
inline void WriteOp_Dec_Alt(JitWriter *jit)
ds@1952
   638
{
ds@1952
   639
	//sub edx, 1
ds@1952
   640
	IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
ds@1952
   641
}
ds@1952
   642
ds@1952
   643
inline void WriteOp_Dec(JitWriter *jit)
ds@1952
   644
{
ds@1952
   645
	//sub [ebp+<val>], 1
ds@1952
   646
	cell_t val = jit->read_cell();
faluco@2029
   647
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   648
	{
ds@1952
   649
		IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
ds@1952
   650
	} else {
ds@1952
   651
		IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
ds@1952
   652
	}
ds@1952
   653
}
ds@1952
   654
ds@1952
   655
inline void WriteOp_Dec_S(JitWriter *jit)
ds@1952
   656
{
ds@1952
   657
	//sub [ebx+<val>], 1
ds@1952
   658
	cell_t val = jit->read_cell();
faluco@2029
   659
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   660
	{
ds@1952
   661
		IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
ds@1952
   662
	} else {
ds@1952
   663
		IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
ds@1952
   664
	}
ds@1952
   665
}
ds@1952
   666
ds@1952
   667
inline void WriteOp_Dec_I(JitWriter *jit)
ds@1952
   668
{
ds@1952
   669
	//sub [ebp+eax], 1
ds@1952
   670
	IA32_Sub_RmEBP_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
ds@1952
   671
}
ds@1952
   672
ds@1952
   673
inline void WriteOp_Load_Pri(JitWriter *jit)
ds@1952
   674
{
ds@1952
   675
	//mov eax, [ebp+<val>]
ds@1952
   676
	cell_t val = jit->read_cell();
faluco@2029
   677
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   678
	{
ds@1952
   679
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   680
	} else {
ds@1952
   681
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
ds@1952
   682
	}
ds@1952
   683
}
ds@1952
   684
ds@1952
   685
inline void WriteOp_Load_Alt(JitWriter *jit)
ds@1952
   686
{
ds@1952
   687
	//mov edx, [ebp+<val>]
ds@1952
   688
	cell_t val = jit->read_cell();
faluco@2029
   689
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   690
	{
ds@1952
   691
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   692
	} else {
ds@1952
   693
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
ds@1952
   694
	}
ds@1952
   695
}
ds@1952
   696
ds@1952
   697
inline void WriteOp_Load_S_Pri(JitWriter *jit)
ds@1952
   698
{
ds@1952
   699
	//mov eax, [ebx+<val>]
ds@1952
   700
	cell_t val = jit->read_cell();
faluco@2029
   701
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   702
	{
ds@1952
   703
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   704
	} else {
ds@1952
   705
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
ds@1952
   706
	}
ds@1952
   707
}
ds@1952
   708
ds@1952
   709
inline void WriteOp_Load_S_Alt(JitWriter *jit)
ds@1952
   710
{
ds@1952
   711
	//mov edx, [ebx+<val>]
ds@1952
   712
	cell_t val = jit->read_cell();
faluco@2029
   713
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   714
	{
ds@1952
   715
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   716
	} else {
ds@1952
   717
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
ds@1952
   718
	}
ds@1952
   719
}
ds@1952
   720
ds@1952
   721
inline void WriteOp_Lref_Pri(JitWriter *jit)
ds@1952
   722
{
ds@1952
   723
	//mov eax, [ebp+<val>]
ds@1952
   724
	//mov eax, [ebp+eax]
ds@1952
   725
	cell_t val = jit->read_cell();
faluco@2029
   726
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   727
	{
ds@1952
   728
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   729
	} else {
ds@1952
   730
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
ds@1952
   731
	}
ds@1952
   732
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
   733
}
ds@1952
   734
ds@1952
   735
inline void WriteOp_Lref_Alt(JitWriter *jit)
ds@1952
   736
{
ds@1952
   737
	//mov edx, [ebp+<val>]
ds@1952
   738
	//mov edx, [ebp+edx]
ds@1952
   739
	cell_t val = jit->read_cell();
faluco@2029
   740
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   741
	{
ds@1952
   742
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   743
	} else {
ds@1952
   744
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
ds@1952
   745
	}
ds@1952
   746
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
ds@1952
   747
}
ds@1952
   748
ds@1952
   749
inline void WriteOp_Lref_S_Pri(JitWriter *jit)
ds@1952
   750
{
ds@1952
   751
	//mov eax, [ebx+<val>]
ds@1952
   752
	//mov eax, [ebp+eax]
ds@1952
   753
	cell_t val = jit->read_cell();
faluco@2029
   754
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   755
	{
ds@1952
   756
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   757
	} else {
ds@1952
   758
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
ds@1952
   759
	}
ds@1952
   760
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
   761
}
ds@1952
   762
ds@1952
   763
inline void WriteOp_Lref_S_Alt(JitWriter *jit)
ds@1952
   764
{
ds@1952
   765
	//mov edx, [ebx+<val>]
ds@1952
   766
	//mov edx, [ebp+edx]
ds@1952
   767
	cell_t val = jit->read_cell();
faluco@2029
   768
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   769
	{
ds@1952
   770
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   771
	} else {
ds@1952
   772
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
ds@1952
   773
	}
ds@1952
   774
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
ds@1952
   775
}
ds@1952
   776
ds@1952
   777
inline void WriteOp_Const_Pri(JitWriter *jit)
ds@1952
   778
{
ds@1952
   779
	//mov eax, <val>
ds@1952
   780
	cell_t val = jit->read_cell();
ds@1952
   781
	IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
ds@1952
   782
}
ds@1952
   783
ds@1952
   784
inline void WriteOp_Const_Alt(JitWriter *jit)
ds@1952
   785
{
ds@1952
   786
	//mov edx, <val>
ds@1952
   787
	cell_t val = jit->read_cell();
ds@1952
   788
	IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
ds@1952
   789
}
ds@1952
   790
ds@1952
   791
inline void WriteOp_Addr_Pri(JitWriter *jit)
ds@1952
   792
{
ds@1952
   793
	//mov eax, [esi+frm]
ds@1952
   794
	//add eax, <val>
ds@1952
   795
	cell_t val = jit->read_cell();
ds@1952
   796
	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG);
faluco@2029
   797
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   798
	{
ds@1952
   799
		IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
ds@1952
   800
	} else {
ds@1952
   801
		IA32_Add_Eax_Imm32(jit, val);
ds@1952
   802
	}
ds@1952
   803
}
ds@1952
   804
ds@1952
   805
inline void WriteOp_Addr_Alt(JitWriter *jit)
ds@1952
   806
{
ds@1952
   807
	//mov edx, [esi+frm]
ds@1952
   808
	//add edx, <val>
ds@1952
   809
	cell_t val = jit->read_cell();
ds@1952
   810
	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_INFO, MOD_MEM_REG);
faluco@2029
   811
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   812
	{
ds@1952
   813
		IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
ds@1952
   814
	} else {
ds@1952
   815
		IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
ds@1952
   816
	}
ds@1952
   817
}
ds@1952
   818
ds@1952
   819
inline void WriteOp_Stor_Pri(JitWriter *jit)
ds@1952
   820
{
ds@1952
   821
	//mov [ebp+<val>], eax
ds@1952
   822
	cell_t val = jit->read_cell();
faluco@2029
   823
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   824
	{
ds@1952
   825
		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
ds@1952
   826
	} else {
ds@1952
   827
		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
ds@1952
   828
	}
ds@1952
   829
}
ds@1952
   830
ds@1952
   831
inline void WriteOp_Stor_Alt(JitWriter *jit)
ds@1952
   832
{
ds@1952
   833
	//mov [ebp+<val>], edx
ds@1952
   834
	cell_t val = jit->read_cell();
faluco@2029
   835
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   836
	{
ds@1952
   837
		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
ds@1952
   838
	} else {
ds@1952
   839
		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
ds@1952
   840
	}
ds@1952
   841
}
ds@1952
   842
ds@1952
   843
inline void WriteOp_Stor_S_Pri(JitWriter *jit)
ds@1952
   844
{
ds@1952
   845
	//mov [ebx+<val>], eax
ds@1952
   846
	cell_t val = jit->read_cell();
faluco@2029
   847
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   848
	{
ds@1952
   849
		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
ds@1952
   850
	} else {
ds@1952
   851
		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
ds@1952
   852
	}
ds@1952
   853
}
ds@1952
   854
ds@1952
   855
inline void WriteOp_Stor_S_Alt(JitWriter *jit)
ds@1952
   856
{
ds@1952
   857
	//mov [ebx+<val>], edx
ds@1952
   858
	cell_t val = jit->read_cell();
faluco@2029
   859
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   860
	{
ds@1952
   861
		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
ds@1952
   862
	} else {
ds@1952
   863
		IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
ds@1952
   864
	}
ds@1952
   865
}
ds@1952
   866
ds@1952
   867
inline void WriteOp_Idxaddr(JitWriter *jit)
ds@1952
   868
{
ds@1952
   869
	//lea eax, [edx+4*eax]
ds@1952
   870
	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
ds@1952
   871
}
ds@1952
   872
ds@1952
   873
inline void WriteOp_Sref_Pri(JitWriter *jit)
ds@1952
   874
{
ds@1952
   875
	//mov ecx, [ebp+<val>]
ds@1952
   876
	//mov [ebp+ecx], eax
ds@1952
   877
	cell_t val = jit->read_cell();
faluco@2029
   878
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   879
	{
ds@1952
   880
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   881
	} else {
ds@1952
   882
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
ds@1952
   883
	}
ds@1952
   884
	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
ds@1952
   885
}
ds@1952
   886
ds@1952
   887
inline void WriteOp_Sref_Alt(JitWriter *jit)
ds@1952
   888
{
ds@1952
   889
	//mov ecx, [ebp+<val>]
ds@1952
   890
	//mov [ebp+ecx], edx
ds@1952
   891
	cell_t val = jit->read_cell();
faluco@2029
   892
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   893
	{
ds@1952
   894
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
ds@1952
   895
	} else {
ds@1952
   896
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
ds@1952
   897
	}
ds@1952
   898
	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
ds@1952
   899
}
ds@1952
   900
ds@1952
   901
inline void WriteOp_Sref_S_Pri(JitWriter *jit)
ds@1952
   902
{
ds@1952
   903
	//mov ecx, [ebx+<val>]
ds@1952
   904
	//mov [ebp+ecx], eax
ds@1952
   905
	cell_t val = jit->read_cell();
faluco@2029
   906
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   907
	{
ds@1952
   908
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   909
	} else {
ds@1952
   910
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
ds@1952
   911
	}
ds@1952
   912
	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
ds@1952
   913
}
ds@1952
   914
ds@1952
   915
inline void WriteOp_Sref_S_Alt(JitWriter *jit)
ds@1952
   916
{
ds@1952
   917
	//mov ecx, [ebx+<val>]
ds@1952
   918
	//mov [ebp+ecx], edx
ds@1952
   919
	cell_t val = jit->read_cell();
faluco@2029
   920
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   921
	{
ds@1952
   922
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
ds@1952
   923
	} else {
ds@1952
   924
		IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
ds@1952
   925
	}
ds@1952
   926
	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
ds@1952
   927
}
ds@1952
   928
ds@1952
   929
inline void WriteOp_Pop_Pri(JitWriter *jit)
ds@1952
   930
{
ds@1952
   931
	//mov eax, [edi]
ds@1952
   932
	//add edi, 4
ds@1952
   933
	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
ds@1952
   934
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   935
}
ds@1952
   936
ds@1952
   937
inline void WriteOp_Pop_Alt(JitWriter *jit)
ds@1952
   938
{
ds@1952
   939
	//mov edx, [edi]
ds@1952
   940
	//add edi, 4
ds@1952
   941
	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
ds@1952
   942
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
   943
}
ds@1952
   944
ds@1952
   945
inline void WriteOp_Swap_Pri(JitWriter *jit)
ds@1952
   946
{
ds@1952
   947
	//add [edi], eax
ds@1952
   948
	//sub eax, [edi]
ds@1952
   949
	//add [edi], eax
ds@1952
   950
	//neg eax
ds@1952
   951
	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
ds@1952
   952
	IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
ds@1952
   953
	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
ds@1952
   954
	IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
ds@1952
   955
}
ds@1952
   956
ds@1952
   957
inline void WriteOp_Swap_Alt(JitWriter *jit)
ds@1952
   958
{
ds@1952
   959
	//add [edi], edx
ds@1952
   960
	//sub edx, [edi]
ds@1952
   961
	//add [edi], edx
ds@1952
   962
	//neg edx
ds@1952
   963
	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
ds@1952
   964
	IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
ds@1952
   965
	IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
ds@1952
   966
	IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
ds@1952
   967
}
ds@1952
   968
ds@1952
   969
inline void WriteOp_PushAddr(JitWriter *jit)
ds@1952
   970
{
ds@1952
   971
	//mov ecx, [esi+frm]	;get address (offset from frame)
ds@1952
   972
	//sub edi, 4
ds@1952
   973
	//add ecx, <val>
ds@1952
   974
	//mov [edi], ecx
ds@1952
   975
	cell_t val = jit->read_cell();
ds@1952
   976
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_INFO, MOD_MEM_REG);
ds@1952
   977
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
faluco@2029
   978
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
   979
	{
ds@1952
   980
		IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
ds@1952
   981
	} else {
ds@1952
   982
		IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
ds@1952
   983
	}
ds@1952
   984
	IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
   985
}
ds@1952
   986
ds@1952
   987
inline void WriteOp_Movs(JitWriter *jit)
ds@1952
   988
{
ds@1952
   989
	//cld
ds@1952
   990
	//push esi
ds@1952
   991
	//push edi
ds@1952
   992
	//lea esi, [ebp+eax]
ds@1952
   993
	//lea edi, [ebp+edx]
ds@1952
   994
	//if dword:
ds@1952
   995
	// mov ecx, dword
ds@1952
   996
	// rep movsd
ds@1952
   997
	//if byte:
ds@1952
   998
	// mov ecx, byte
ds@1952
   999
	// rep movsb
ds@1952
  1000
	//pop edi
ds@1952
  1001
	//pop esi
ds@1952
  1002
	cell_t val = jit->read_cell();
ds@1952
  1003
	unsigned int dwords = val >> 2;
ds@1952
  1004
	unsigned int bytes = val & 0x3;
ds@1952
  1005
ds@1952
  1006
	IA32_Cld(jit);
ds@1952
  1007
	IA32_Push_Reg(jit, REG_ESI);
ds@1952
  1008
	IA32_Push_Reg(jit, REG_EDI);
ds@1952
  1009
	IA32_Lea_Reg_DispEBPRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
  1010
	IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
ds@1952
  1011
	if (dwords)
ds@1952
  1012
	{
ds@1952
  1013
		IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
ds@1952
  1014
		IA32_Rep(jit);
ds@1952
  1015
		IA32_Movsd(jit);
ds@1952
  1016
	}
ds@1952
  1017
	if (bytes)
ds@1952
  1018
	{
ds@1952
  1019
		IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
ds@1952
  1020
		IA32_Rep(jit);
ds@1952
  1021
		IA32_Movsb(jit);
ds@1952
  1022
	}
ds@1952
  1023
	IA32_Pop_Reg(jit, REG_EDI);
ds@1952
  1024
	IA32_Pop_Reg(jit, REG_ESI);
ds@1952
  1025
}
ds@1952
  1026
ds@1952
  1027
inline void WriteOp_Fill(JitWriter *jit)
ds@1952
  1028
{
ds@1952
  1029
	//push edi
ds@1952
  1030
	//lea edi, [ebp+edx]
ds@1952
  1031
	//mov ecx, <val> >> 2
ds@1952
  1032
	//cld
ds@1952
  1033
	//rep stosd
ds@1952
  1034
	//pop edi
ds@1952
  1035
	unsigned int val = jit->read_cell() >> 2;
ds@1952
  1036
ds@1952
  1037
	IA32_Push_Reg(jit, REG_EDI);
ds@1952
  1038
	IA32_Lea_Reg_DispEBPRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
ds@1952
  1039
	IA32_Mov_Reg_Imm32(jit, REG_ECX, val);
ds@1952
  1040
	IA32_Cld(jit);
ds@1952
  1041
	IA32_Rep(jit);
ds@1952
  1042
	IA32_Stosd(jit);
ds@1952
  1043
	IA32_Pop_Reg(jit, REG_EDI);
ds@1952
  1044
}
ds@1952
  1045
ds@1952
  1046
inline void WriteOp_GenArray(JitWriter *jit, bool autozero)
ds@1952
  1047
{
ds@1952
  1048
	cell_t val = jit->read_cell();
ds@1952
  1049
	if (val == 1)
ds@1952
  1050
	{
ds@1952
  1051
		/* flat array.  we can generate this without indirection tables. */
ds@1952
  1052
		/* Note that we can overwrite ALT because technically STACK should be destroying ALT */
ds@1952
  1053
		//mov edx, [esi+info.heap]
ds@1952
  1054
		//mov ecx, [edi]
ds@1952
  1055
		//mov [edi], edx			;store base of array into stack
ds@1952
  1056
		//lea edx, [edx+ecx*4]		;get the final new heap pointer
ds@1952
  1057
		//mov [esi+info.heap], edx	;store heap pointer back
ds@1952
  1058
		//add edx, ebp				;relocate
ds@1952
  1059
		//cmp edx, edi				;compare against stack pointer
ds@1952
  1060
		//jae :error				;error out if not enough space
ds@1952
  1061
		IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
ds@1952
  1062
		IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
ds@1952
  1063
		IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
ds@1952
  1064
		IA32_Lea_Reg_DispRegMult(jit, AMX_REG_ALT, AMX_REG_ALT, AMX_REG_TMP, SCALE4);
ds@1952
  1065
		IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_ALT, AMX_INFO_HEAP);
ds@1952
  1066
		IA32_Add_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
ds@1952
  1067
		IA32_Cmp_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
ds@1952
  1068
		IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_heaplow);
ds@1952
  1069
ds@1952
  1070
		WriteOp_Tracker_Push_Reg(jit, REG_ECX);
ds@1952
  1071
ds@1952
  1072
		if (autozero)
ds@1952
  1073
		{
ds@1952
  1074
			/* Zero out the array - inline a quick fill */
ds@1952
  1075
			//push eax				;save pri
ds@1952
  1076
			//push edi				;save stk
ds@1952
  1077
			//xor eax, eax			;zero source
ds@1952
  1078
			//mov edi, [edi]		;get heap ptr out of the stack
ds@1952
  1079
			//add edi, ebp			;relocate
ds@1952
  1080
			//cld					;clear direction flag
ds@1952
  1081
			//rep stosd				;copy (note: ECX is sane from above)
ds@1952
  1082
			//pop edi				;pop stk
ds@1952
  1083
			//pop eax				;pop pri
ds@1952
  1084
			IA32_Push_Reg(jit, REG_EAX);
ds@1952
  1085
			IA32_Push_Reg(jit, REG_EDI);
ds@1952
  1086
			IA32_Xor_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_REG);
ds@1952
  1087
			IA32_Mov_Reg_Rm(jit, REG_EDI, REG_EDI, MOD_MEM_REG);
ds@1952
  1088
			IA32_Add_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG);
ds@1952
  1089
			IA32_Cld(jit);
ds@1952
  1090
			IA32_Rep(jit);
ds@1952
  1091
			IA32_Stosd(jit);
ds@1952
  1092
			IA32_Pop_Reg(jit, REG_EDI);
ds@1952
  1093
			IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  1094
		}
ds@1952
  1095
	} else {
ds@1952
  1096
		//mov ecx, num_dims
ds@1952
  1097
		//mov edx, 0/1
ds@1952
  1098
		//call [genarray]
ds@1952
  1099
		IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
ds@1952
  1100
		if (autozero)
ds@1952
  1101
		{
ds@1952
  1102
			IA32_Mov_Reg_Imm32(jit, REG_EDX, 1);
ds@1952
  1103
		} else {
ds@1952
  1104
			IA32_Mov_Reg_Imm32(jit, REG_EDX, 0);
ds@1952
  1105
		}
ds@1952
  1106
		jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1107
		IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_genarray);
ds@1952
  1108
	}
ds@1952
  1109
}
ds@1952
  1110
ds@1952
  1111
inline void WriteOp_Load_Both(JitWriter *jit)
ds@1952
  1112
{
ds@1952
  1113
	WriteOp_Load_Pri(jit);
ds@1952
  1114
	WriteOp_Load_Alt(jit);
ds@1952
  1115
}
ds@1952
  1116
ds@1952
  1117
inline void WriteOp_Load_S_Both(JitWriter *jit)
ds@1952
  1118
{
ds@1952
  1119
	WriteOp_Load_S_Pri(jit);
ds@1952
  1120
	WriteOp_Load_S_Alt(jit);
ds@1952
  1121
}
ds@1952
  1122
ds@1952
  1123
inline void WriteOp_Const(JitWriter *jit)
ds@1952
  1124
{
ds@1952
  1125
	//mov [ebp+<addr>], <val>
ds@1952
  1126
	cell_t addr = jit->read_cell();
ds@1952
  1127
	cell_t val = jit->read_cell();
faluco@2029
  1128
	if (addr <= SCHAR_MAX && addr >= SCHAR_MIN)
ds@1952
  1129
	{
ds@1952
  1130
		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
ds@1952
  1131
	} else {
ds@1952
  1132
		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
ds@1952
  1133
	}
ds@1952
  1134
}
ds@1952
  1135
ds@1952
  1136
inline void WriteOp_Const_S(JitWriter *jit)
ds@1952
  1137
{
ds@1952
  1138
	//mov [ebx+<offs>], <val>
ds@1952
  1139
	cell_t offs = jit->read_cell();
ds@1952
  1140
	cell_t val = jit->read_cell();
faluco@2029
  1141
	if (offs <= SCHAR_MAX && offs >= SCHAR_MIN)
ds@1952
  1142
	{
ds@1952
  1143
		IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
ds@1952
  1144
	} else {
ds@1952
  1145
		IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
ds@1952
  1146
	}
ds@1952
  1147
}
ds@1952
  1148
ds@1952
  1149
inline void WriteOp_Load_I(JitWriter *jit)
ds@1952
  1150
{
ds@1952
  1151
	//mov eax, [ebp+eax]
ds@1952
  1152
	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
ds@1952
  1153
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
  1154
}
ds@1952
  1155
ds@1952
  1156
inline void WriteOp_Lodb_I(JitWriter *jit)
ds@1952
  1157
{
ds@1952
  1158
	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
ds@1952
  1159
ds@1952
  1160
	//mov eax, [ebp+eax]
ds@1952
  1161
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
  1162
ds@1952
  1163
	//and eax, <bitmask>
ds@1952
  1164
	cell_t val = jit->read_cell();
ds@1952
  1165
	switch(val)
ds@1952
  1166
	{
ds@1952
  1167
	case 1:
ds@1952
  1168
		{
ds@1952
  1169
			IA32_And_Eax_Imm32(jit, 0x000000FF);
ds@1952
  1170
			break;
ds@1952
  1171
		}
ds@1952
  1172
	case 2:
ds@1952
  1173
		{
ds@1952
  1174
			IA32_And_Eax_Imm32(jit, 0x0000FFFF);
ds@1952
  1175
			break;
ds@1952
  1176
		}
ds@1952
  1177
	}
ds@1952
  1178
}
ds@1952
  1179
ds@1952
  1180
inline void WriteOp_Stor_I(JitWriter *jit)
ds@1952
  1181
{
ds@1952
  1182
	//mov [ebp+edx], eax
ds@1952
  1183
	Write_Check_VerifyAddr(jit, AMX_REG_ALT);
ds@1952
  1184
	IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
ds@1952
  1185
}
ds@1952
  1186
ds@1952
  1187
inline void WriteOp_Strb_I(JitWriter *jit)
ds@1952
  1188
{
ds@1952
  1189
	Write_Check_VerifyAddr(jit, AMX_REG_ALT);
ds@1952
  1190
	//mov [ebp+edx], eax
ds@1952
  1191
	cell_t val = jit->read_cell();
ds@1952
  1192
	switch (val)
ds@1952
  1193
	{
ds@1952
  1194
	case 1:
ds@1952
  1195
		{
ds@1952
  1196
			IA32_Mov_Rm8EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
ds@1952
  1197
			break;
ds@1952
  1198
		}
ds@1952
  1199
	case 2:
ds@1952
  1200
		{
ds@1952
  1201
			IA32_Mov_Rm16EBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
ds@1952
  1202
			break;
ds@1952
  1203
		}
ds@1952
  1204
	case 4:
ds@1952
  1205
		{
ds@1952
  1206
			IA32_Mov_RmEBP_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
ds@1952
  1207
			break;
ds@1952
  1208
		}
ds@1952
  1209
	}
ds@1952
  1210
}
ds@1952
  1211
ds@1952
  1212
inline void WriteOp_Lidx(JitWriter *jit)
ds@1952
  1213
{
ds@1952
  1214
	//lea eax, [edx+4*eax]
ds@1952
  1215
	//mov eax, [ebp+eax]
ds@1952
  1216
	IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
ds@1952
  1217
	Write_Check_VerifyAddr(jit, AMX_REG_PRI);
ds@1952
  1218
	IA32_Mov_Reg_RmEBP_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
ds@1952
  1219
}
ds@1952
  1220
ds@1952
  1221
inline void WriteOp_Stack(JitWriter *jit)
ds@1952
  1222
{
ds@1952
  1223
	//add edi, <val>
ds@1952
  1224
	cell_t val = jit->read_cell();
faluco@2029
  1225
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
  1226
	{
ds@1952
  1227
		IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG);
ds@1952
  1228
	} else {
ds@1952
  1229
		IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG);
ds@1952
  1230
	}
ds@1952
  1231
ds@1952
  1232
	if (val > 0)
ds@1952
  1233
	{
ds@1952
  1234
		Write_CheckStack_Min(jit);
ds@1952
  1235
	} else if (val < 0) {
ds@1952
  1236
		Write_CheckStack_Low(jit);
ds@1952
  1237
	}
ds@1952
  1238
}
ds@1952
  1239
ds@1952
  1240
inline void WriteOp_StackAdjust(JitWriter *jit)
ds@1952
  1241
{
ds@1952
  1242
	cell_t val = jit->read_cell();
ds@1952
  1243
ds@1952
  1244
	assert(val <= 0);
ds@1952
  1245
ds@1952
  1246
	//lea edi, [ebx-val]
ds@1952
  1247
	
faluco@2029
  1248
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
  1249
	{
ds@1952
  1250
		IA32_Lea_DispRegImm8(jit, AMX_REG_STK, AMX_REG_FRM, val);
ds@1952
  1251
	}
ds@1952
  1252
	else
ds@1952
  1253
	{
ds@1952
  1254
		IA32_Lea_DispRegImm32(jit, AMX_REG_STK, AMX_REG_FRM, val);
ds@1952
  1255
	}
ds@1952
  1256
ds@1952
  1257
	/* We assume the compiler has generated good code -- 
ds@1952
  1258
	 * That is, we do not bother validating this amount!
ds@1952
  1259
	 */
ds@1952
  1260
}
ds@1952
  1261
ds@1952
  1262
inline void WriteOp_Heap(JitWriter *jit)
ds@1952
  1263
{
ds@1952
  1264
	//mov edx, [esi+hea]
ds@1952
  1265
	//add [esi+hea], <val>
ds@1952
  1266
	cell_t val = jit->read_cell();
ds@1952
  1267
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
faluco@2029
  1268
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
  1269
	{
ds@1952
  1270
		IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, (jit_int8_t)val, AMX_INFO_HEAP);
ds@1952
  1271
	} else {
ds@1952
  1272
		IA32_Add_Rm_Imm32_Disp8(jit, AMX_REG_INFO, val, AMX_INFO_HEAP);
ds@1952
  1273
	}
ds@1952
  1274
ds@1952
  1275
	/* NOTE: Backwards from op.stack */
ds@1952
  1276
	if (val > 0)
ds@1952
  1277
	{
ds@1952
  1278
		Write_CheckHeap_Low(jit);
ds@1952
  1279
	} else if (val < 0) {
ds@1952
  1280
		Write_CheckHeap_Min(jit);
ds@1952
  1281
	}
ds@1952
  1282
}
ds@1952
  1283
ds@1952
  1284
inline void WriteOp_SDiv(JitWriter *jit)
ds@1952
  1285
{
ds@1952
  1286
	//mov ecx, edx
ds@1952
  1287
	//mov edx, eax
ds@1952
  1288
	//sar edx, 31
ds@1952
  1289
	//idiv ecx
ds@1952
  1290
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
ds@1952
  1291
	IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
ds@1952
  1292
	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
ds@1952
  1293
	Write_Check_DivZero(jit, AMX_REG_TMP);
ds@1952
  1294
	IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
ds@1952
  1295
}
ds@1952
  1296
ds@1952
  1297
inline void WriteOp_SDiv_Alt(JitWriter *jit)
ds@1952
  1298
{
ds@1952
  1299
	//mov ecx, eax
ds@1952
  1300
	//mov eax, edx
ds@1952
  1301
	//sar edx, 31
ds@1952
  1302
	//idiv ecx
ds@1952
  1303
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
ds@1952
  1304
	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1305
	IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
ds@1952
  1306
	Write_Check_DivZero(jit, AMX_REG_TMP);
ds@1952
  1307
	IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
ds@1952
  1308
}
ds@1952
  1309
ds@1952
  1310
inline void WriteOp_Retn(JitWriter *jit)
ds@1952
  1311
{
ds@1952
  1312
	//mov ebx, [edi+4]		- get old frm
ds@1952
  1313
	//add edi, 8			- pop stack
ds@1952
  1314
	//mov [esi+frm], ebx	- restore frame pointer
ds@1952
  1315
	//add ebx, ebp			- relocate
ds@1952
  1316
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_FRM, AMX_REG_STK, 4);
ds@1952
  1317
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  1318
	IA32_Mov_Rm_Reg(jit, AMX_REG_INFO, AMX_REG_FRM, MOD_MEM_REG);
ds@1952
  1319
	IA32_Add_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
ds@1952
  1320
ds@1952
  1321
	/* pop params */
ds@1952
  1322
	//mov ecx, [edi]
ds@1952
  1323
	//lea edi, [edi+ecx*4+4] 
ds@1952
  1324
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_MEM_REG);
ds@1952
  1325
	IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, AMX_REG_TMP, SCALE4, 4);
ds@1952
  1326
ds@1952
  1327
	//ret					- return (EIP on real stack!)
ds@1952
  1328
	IA32_Return(jit);
ds@1952
  1329
}
ds@1952
  1330
ds@1952
  1331
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
ds@1952
  1332
{
dvander@2193
  1333
	((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
ds@1952
  1334
}
ds@1952
  1335
ds@1952
  1336
void ProfCallGate_End(sp_context_t *ctx)
ds@1952
  1337
{
dvander@2193
  1338
	((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
ds@1952
  1339
}
ds@1952
  1340
ds@1952
  1341
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
ds@1952
  1342
{
ds@1952
  1343
	uint32_t max, iter;
ds@1952
  1344
	sp_fdbg_symbol_t *sym;
ds@1952
  1345
	sp_fdbg_arraydim_t *arr;
ds@1952
  1346
	uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
ds@1952
  1347
ds@1952
  1348
	max = plugin->debug.syms_num;
ds@1952
  1349
	for (iter = 0; iter < max; iter++)
ds@1952
  1350
	{
ds@1952
  1351
		sym = (sp_fdbg_symbol_t *)cursor;
ds@1952
  1352
ds@1952
  1353
		if (sym->ident == SP_SYM_FUNCTION
ds@1952
  1354
			&& sym->codestart <= offs 
ds@1952
  1355
			&& sym->codeend > offs)
ds@1952
  1356
		{
ds@1952
  1357
			return plugin->debug.stringbase + sym->name;
ds@1952
  1358
		}
ds@1952
  1359
ds@1952
  1360
		if (sym->dimcount > 0)
ds@1952
  1361
		{
ds@1952
  1362
			cursor += sizeof(sp_fdbg_symbol_t);
ds@1952
  1363
			arr = (sp_fdbg_arraydim_t *)cursor;
ds@1952
  1364
			cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
ds@1952
  1365
			continue;
ds@1952
  1366
		}
ds@1952
  1367
ds@1952
  1368
		cursor += sizeof(sp_fdbg_symbol_t);
ds@1952
  1369
	}
ds@1952
  1370
ds@1952
  1371
	return NULL;
ds@1952
  1372
}
ds@1952
  1373
ds@1952
  1374
inline void WriteOp_Call(JitWriter *jit)
ds@1952
  1375
{
ds@1952
  1376
	cell_t offs;
ds@1952
  1377
	jitoffs_t jmp;
ds@1952
  1378
	CompData *data;
ds@1952
  1379
		
ds@1952
  1380
	data = (CompData *)jit->data; 
ds@1952
  1381
	offs = jit->read_cell();
ds@1952
  1382
ds@1952
  1383
	if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
ds@1952
  1384
	{
ds@1952
  1385
		const char *name;
ds@1952
  1386
ds@1952
  1387
		/* Find the function name */
ds@1952
  1388
		if ((name = find_func_name(data->plugin, offs)) == NULL)
ds@1952
  1389
		{
ds@1952
  1390
			name = "unknown";
ds@1952
  1391
		}
ds@1952
  1392
ds@1952
  1393
		//push name
ds@1952
  1394
		//push [esi+context] 
ds@1952
  1395
		//call ProfCallGate_Begin
ds@1952
  1396
		//add esp, 8
ds@1952
  1397
		IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
ds@1952
  1398
		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1399
		jmp = IA32_Call_Imm32(jit, 0);
ds@1952
  1400
		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
ds@1952
  1401
		IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
ds@1952
  1402
ds@1952
  1403
		//call <addr>
ds@1952
  1404
		//push eax
ds@1952
  1405
		jmp = IA32_Call_Imm32(jit, 0);
ds@1952
  1406
		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
ds@1952
  1407
		IA32_Push_Reg(jit, REG_EAX);
ds@1952
  1408
ds@1952
  1409
		//push [esi+context]
ds@1952
  1410
		//call ProfCallGate_End
ds@1952
  1411
		//add esp, 4
ds@1952
  1412
		//pop eax
ds@1952
  1413
		IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1414
		jmp = IA32_Call_Imm32(jit, 0);
ds@1952
  1415
		IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
ds@1952
  1416
		IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  1417
		IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  1418
	}
ds@1952
  1419
	else
ds@1952
  1420
	{
ds@1952
  1421
		jmp = IA32_Call_Imm32(jit, 0);
ds@1952
  1422
		IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
ds@1952
  1423
	}
ds@1952
  1424
}
ds@1952
  1425
ds@1952
  1426
inline void WriteOp_Bounds(JitWriter *jit)
ds@1952
  1427
{
ds@1952
  1428
	cell_t val = jit->read_cell();
ds@1952
  1429
	
ds@1952
  1430
	//cmp eax, <val>
ds@1952
  1431
	//ja :error
faluco@2029
  1432
	if (val <= SCHAR_MAX && val >= SCHAR_MIN)
ds@1952
  1433
	{
ds@1952
  1434
		IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
ds@1952
  1435
	} else {
ds@1952
  1436
		IA32_Cmp_Eax_Imm32(jit, val);
ds@1952
  1437
	}
ds@1952
  1438
	IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_bounds);
ds@1952
  1439
}
ds@1952
  1440
ds@1952
  1441
inline void WriteOp_Halt(JitWriter *jit)
ds@1952
  1442
{
ds@1952
  1443
	AlignMe(jit);
ds@1952
  1444
ds@1952
  1445
	//mov ecx, [esi+ret]
ds@1952
  1446
	//mov [ecx], eax
ds@1952
  1447
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
ds@1952
  1448
	IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
ds@1952
  1449
	
ds@1952
  1450
	/* :TODO: 
ds@1952
  1451
	 * We don't support sleeping or halting with weird values.
ds@1952
  1452
	 * So we're omitting the mov eax <val> that was here.
ds@1952
  1453
	 */
ds@1952
  1454
	jit->read_cell();
ds@1952
  1455
ds@1952
  1456
	CompData *data = (CompData *)jit->data;
ds@1952
  1457
	IA32_Jump_Imm32_Abs(jit, data->jit_return);
ds@1952
  1458
}
ds@1952
  1459
ds@1952
  1460
inline void WriteOp_Break(JitWriter *jit)
ds@1952
  1461
{
ds@1952
  1462
	CompData *data = (CompData *)jit->data;
ds@1952
  1463
	if (data->debug)
ds@1952
  1464
	{
ds@1952
  1465
		//jit->write_ubyte(IA32_INT3);
ds@1952
  1466
		//mov ecx, <cip>
ds@1952
  1467
		jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0);
ds@1952
  1468
		jitoffs_t save = jit->get_outputpos();
ds@1952
  1469
		jit->set_outputpos(wr);
ds@1952
  1470
		jit->write_uint32((uint32_t)(wr));
ds@1952
  1471
		jit->set_outputpos(save);
ds@1952
  1472
		wr = IA32_Call_Imm32(jit, 0);
ds@1952
  1473
		IA32_Write_Jump32(jit, wr, data->jit_break);
ds@1952
  1474
	}
ds@1952
  1475
}
ds@1952
  1476
ds@1952
  1477
inline void WriteOp_Jump(JitWriter *jit)
ds@1952
  1478
{
ds@1952
  1479
	//jmp <offs>
ds@1952
  1480
	cell_t amx_offs = jit->read_cell();
ds@1952
  1481
	IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false));
ds@1952
  1482
}
ds@1952
  1483
ds@1952
  1484
inline void WriteOp_Jzer(JitWriter *jit)
ds@1952
  1485
{
ds@1952
  1486
	//test eax, eax
ds@1952
  1487
	//jz <target>
ds@1952
  1488
	cell_t target = jit->read_cell();
ds@1952
  1489
	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
ds@1952
  1490
	IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false));
ds@1952
  1491
}
ds@1952
  1492
ds@1952
  1493
inline void WriteOp_Jnz(JitWriter *jit)
ds@1952
  1494
{
ds@1952
  1495
	//test eax, eax
ds@1952
  1496
	//jnz <target>
ds@1952
  1497
	cell_t target = jit->read_cell();
ds@1952
  1498
	IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
ds@1952
  1499
	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false));
ds@1952
  1500
}
ds@1952
  1501
ds@1952
  1502
inline void WriteOp_Jeq(JitWriter *jit)
ds@1952
  1503
{
ds@1952
  1504
	//cmp eax, edx
ds@1952
  1505
	//je <target>
ds@1952
  1506
	cell_t target = jit->read_cell();
ds@1952
  1507
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1508
	IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false));
ds@1952
  1509
}
ds@1952
  1510
ds@1952
  1511
inline void WriteOp_Jneq(JitWriter *jit)
ds@1952
  1512
{
ds@1952
  1513
	//cmp eax, edx
ds@1952
  1514
	//jne <target>
ds@1952
  1515
	cell_t target = jit->read_cell();
ds@1952
  1516
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1517
	IA32_Jump_Cond_Imm32_Abs(jit, CC_NE, RelocLookup(jit, target, false));
ds@1952
  1518
}
ds@1952
  1519
ds@1952
  1520
inline void WriteOp_Jsless(JitWriter *jit)
ds@1952
  1521
{
ds@1952
  1522
	//cmp eax, edx
ds@1952
  1523
	//jl <target>
ds@1952
  1524
	cell_t target = jit->read_cell();
ds@1952
  1525
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1526
	IA32_Jump_Cond_Imm32_Abs(jit, CC_L, RelocLookup(jit, target, false));
ds@1952
  1527
}
ds@1952
  1528
ds@1952
  1529
inline void WriteOp_Jsleq(JitWriter *jit)
ds@1952
  1530
{
ds@1952
  1531
	//cmp eax, edx
ds@1952
  1532
	//jle <target>
ds@1952
  1533
	cell_t target = jit->read_cell();
ds@1952
  1534
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1535
	IA32_Jump_Cond_Imm32_Abs(jit, CC_LE, RelocLookup(jit, target, false));
ds@1952
  1536
}
ds@1952
  1537
ds@1952
  1538
inline void WriteOp_JsGrtr(JitWriter *jit)
ds@1952
  1539
{
ds@1952
  1540
	//cmp eax, edx
ds@1952
  1541
	//jg <target>
ds@1952
  1542
	cell_t target = jit->read_cell();
ds@1952
  1543
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1544
	IA32_Jump_Cond_Imm32_Abs(jit, CC_G, RelocLookup(jit, target, false));
ds@1952
  1545
}
ds@1952
  1546
ds@1952
  1547
inline void WriteOp_JsGeq(JitWriter *jit)
ds@1952
  1548
{
ds@1952
  1549
	//cmp eax, edx
ds@1952
  1550
	//jge <target>
ds@1952
  1551
	cell_t target = jit->read_cell();
ds@1952
  1552
	IA32_Cmp_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
ds@1952
  1553
	IA32_Jump_Cond_Imm32_Abs(jit, CC_GE, RelocLookup(jit, target, false));
ds@1952
  1554
}
ds@1952
  1555
ds@1952
  1556
inline void WriteOp_Switch(JitWriter *jit)
ds@1952
  1557
{
ds@1952
  1558
	cell_t offs = jit->read_cell();
ds@1952
  1559
	cell_t *tbl = (cell_t *)((char *)jit->inbase + offs + sizeof(cell_t));
ds@1952
  1560
ds@1952
  1561
	struct casetbl
ds@1952
  1562
	{
ds@1952
  1563
		cell_t val;
ds@1952
  1564
		cell_t offs;
ds@1952
  1565
	};
ds@1952
  1566
ds@1952
  1567
	/* Read the number of cases, then advance by one */
ds@1952
  1568
	cell_t num_cases = *tbl++;
ds@1952
  1569
	if (!num_cases)
ds@1952
  1570
	{
ds@1952
  1571
		/* Special treatment for 0 cases */
ds@1952
  1572
		//jmp <default>
ds@1952
  1573
		IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
ds@1952
  1574
	} else {
ds@1952
  1575
		/* Check if the case layout is fully sequential */
ds@1952
  1576
		casetbl *iter = (casetbl *)(tbl + 1);
ds@1952
  1577
		casetbl *cases = iter;
ds@1952
  1578
		cell_t first = iter[0].val;
ds@1952
  1579
		cell_t last = first;
ds@1952
  1580
		bool sequential = true;
ds@1952
  1581
		for (cell_t i=1; i<num_cases; i++)
ds@1952
  1582
		{
ds@1952
  1583
			if (iter[i].val != ++last)
ds@1952
  1584
			{
ds@1952
  1585
				sequential = false;
ds@1952
  1586
				break;
ds@1952
  1587
			}
ds@1952
  1588
		}
ds@1952
  1589
		/* Time to generate. 
ds@1952
  1590
		 * First check whether the bounds are correct: if (a < LOW || a > HIGH)
ds@1952
  1591
		 * This check is valid for both sequential and non-sequential.
ds@1952
  1592
		 */
ds@1952
  1593
		cell_t low_bound = cases[0].val;
ds@1952
  1594
		if (low_bound != 0)
ds@1952
  1595
		{
ds@1952
  1596
			/* negate it so we'll get a lower bound of 0 */
ds@1952
  1597
			//lea ecx, [eax-<LOWER_BOUND>]
ds@1952
  1598
			low_bound = -low_bound;
faluco@2029
  1599
			if (low_bound >= SCHAR_MIN && low_bound <= SCHAR_MAX)
ds@1952
  1600
			{
ds@1952
  1601
				IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
ds@1952
  1602
			} else {
ds@1952
  1603
				IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, low_bound);
ds@1952
  1604
			}
ds@1952
  1605
		} else {
ds@1952
  1606
			//mov ecx, eax
ds@1952
  1607
			IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
ds@1952
  1608
		}
ds@1952
  1609
		cell_t high_bound = abs(cases[0].val - cases[num_cases-1].val);
ds@1952
  1610
		//cmp ecx, <UPPER BOUND BOUND>
faluco@2029
  1611
		if (high_bound >= SCHAR_MIN && high_bound <= SCHAR_MAX)
ds@1952
  1612
		{
ds@1952
  1613
			IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_TMP, high_bound);
ds@1952
  1614
		} else {
ds@1952
  1615
			IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_TMP, high_bound);
ds@1952
  1616
		}
ds@1952
  1617
		//ja <default case>
ds@1952
  1618
		IA32_Jump_Cond_Imm32_Abs(jit, CC_A, RelocLookup(jit, *tbl, false));
ds@1952
  1619
ds@1952
  1620
		/**
ds@1952
  1621
		 * Now we've taken the default case out of the way, it's time to do the
ds@1952
  1622
		 * full check, which is different for sequential vs. non-sequential.
ds@1952
  1623
		 */
ds@1952
  1624
		if (sequential)
ds@1952
  1625
		{
ds@1952
  1626
			/* we're now theoretically guaranteed to be jumping to a correct offset.
ds@1952
  1627
			 * ECX still has the correctly bound offset in it, luckily!
ds@1952
  1628
			 * thus, we simply need to relocate ECX and store the cases.
ds@1952
  1629
			 */
ds@1952
  1630
			//lea ecx, [ecx*4]
ds@1952
  1631
			//add ecx, <case table start>
ds@1952
  1632
			IA32_Lea_Reg_RegMultImm32(jit, AMX_REG_TMP, AMX_REG_TMP, SCALE4, 0);
ds@1952
  1633
			jitoffs_t tbl_offs = IA32_Add_Rm_Imm32_Later(jit, AMX_REG_TMP, MOD_REG);
ds@1952
  1634
			IA32_Jump_Rm(jit, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
  1635
			/* The case table starts here.  Go back and write the output pointer. */
ds@1952
  1636
			jitoffs_t cur_pos = jit->get_outputpos();
ds@1952
  1637
			jit->set_outputpos(tbl_offs);
ds@1952
  1638
			jit->write_uint32((jit_uint32_t)(jit->outbase + cur_pos));
ds@1952
  1639
			jit->set_outputpos(cur_pos);
ds@1952
  1640
			//now we can write the case table, finally!
ds@1952
  1641
			jit_uint32_t base = (jit_uint32_t)jit->outbase;
ds@1952
  1642
			for (cell_t i=0; i<num_cases; i++)
ds@1952
  1643
			{
ds@1952
  1644
				jit->write_uint32(base + RelocLookup(jit, cases[i].offs, false));
ds@1952
  1645
			}
ds@1952
  1646
		} else {
ds@1952
  1647
			/* The slow version.  Go through each case and generate a check.
ds@1952
  1648
			 * In the future we should replace case tables of more than ~8 cases with a
ds@1952
  1649
			 * hash table lookup.
ds@1952
  1650
			 * :THOUGHT: Another method of optimizing this - fill in the gaps with jumps to the default case,
ds@1952
  1651
			 *  but only if we're under N cases or so!
ds@1952
  1652
			 * :THOUGHT: Write out a static btree lookup :)
ds@1952
  1653
			 */
ds@1952
  1654
			cell_t val;
ds@1952
  1655
			for (cell_t i=0; i<num_cases; i++)
ds@1952
  1656
			{
ds@1952
  1657
				val = cases[i].val;
ds@1952
  1658
				//cmp eax, <val> OR cmp al, <val>
faluco@2029
  1659
				if (val >= SCHAR_MIN && val <= SCHAR_MAX)
ds@1952
  1660
				{
ds@1952
  1661
					IA32_Cmp_Al_Imm8(jit, val);
ds@1952
  1662
				} else {
ds@1952
  1663
					IA32_Cmp_Eax_Imm32(jit, cases[i].val);
ds@1952
  1664
				}
ds@1952
  1665
				IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, cases[i].offs, false));
ds@1952
  1666
			}
ds@1952
  1667
			/* After all this, jump to the default case! */
ds@1952
  1668
			IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, *tbl, false));
ds@1952
  1669
		}
ds@1952
  1670
	}
ds@1952
  1671
}
ds@1952
  1672
ds@1952
  1673
inline void WriteOp_Casetbl(JitWriter *jit)
ds@1952
  1674
{
ds@1952
  1675
	/* do nothing here, switch does all ze work */
ds@1952
  1676
	cell_t num_cases = jit->read_cell();
ds@1952
  1677
ds@1952
  1678
	/* Two cells per case, one extra case for the default jump */
ds@1952
  1679
	num_cases = (num_cases * 2) + 1;
ds@1952
  1680
	jit->inptr += num_cases;
ds@1952
  1681
}
ds@1952
  1682
ds@1952
  1683
inline void WriteOp_Sysreq_C(JitWriter *jit)
ds@1952
  1684
{
ds@1952
  1685
	/* store the number of parameters on the stack, 
ds@1952
  1686
	 * and store the native index as well.
ds@1952
  1687
	 */
ds@1952
  1688
	cell_t native_index = jit->read_cell();
ds@1952
  1689
ds@1952
  1690
	if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
ds@1952
  1691
	{
ds@1952
  1692
		((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
ds@1952
  1693
		return;
ds@1952
  1694
	}
ds@1952
  1695
ds@1952
  1696
	//mov ecx, <native_index>
ds@1952
  1697
	IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
ds@1952
  1698
ds@1952
  1699
	jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1700
	IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_c);
ds@1952
  1701
}
ds@1952
  1702
ds@1952
  1703
inline void WriteOp_Sysreq_N_NoInline(JitWriter *jit)
ds@1952
  1704
{
ds@1952
  1705
	/* store the number of parameters on the stack, 
ds@1952
  1706
	 * and store the native index as well.
ds@1952
  1707
	 */
ds@1952
  1708
	cell_t native_index = jit->read_cell();
ds@1952
  1709
	cell_t num_params = jit->read_cell();
ds@1952
  1710
	
ds@1952
  1711
	if ((uint32_t)native_index >= ((CompData*)jit->data)->plugin->info.natives_num)
ds@1952
  1712
	{
ds@1952
  1713
		((CompData *)jit->data)->error_set = SP_ERROR_INSTRUCTION_PARAM;
ds@1952
  1714
		return;
ds@1952
  1715
	}
ds@1952
  1716
ds@1952
  1717
	//mov eax, <num_params>
ds@1952
  1718
	//mov ecx, <native_index>
ds@1952
  1719
	IA32_Mov_Reg_Imm32(jit, REG_EAX, num_params);
ds@1952
  1720
	IA32_Mov_Reg_Imm32(jit, REG_ECX, native_index);
ds@1952
  1721
ds@1952
  1722
	jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1723
	IA32_Write_Jump32(jit, call, ((CompData *)jit->data)->jit_sysreq_n);
ds@1952
  1724
}
ds@1952
  1725
ds@1952
  1726
inline void WriteOp_Sysreq_N(JitWriter *jit)
ds@1952
  1727
{
ds@1952
  1728
	/* The big daddy of opcodes. */
ds@1952
  1729
	cell_t native_index = jit->read_cell();
ds@1952
  1730
	cell_t num_params = jit->read_cell();
ds@1952
  1731
	CompData *data = (CompData *)jit->data;
ds@1952
  1732
ds@1952
  1733
	if ((uint32_t)native_index >= data->plugin->info.natives_num)
ds@1952
  1734
	{
ds@1952
  1735
		data->error_set = SP_ERROR_INSTRUCTION_PARAM;
ds@1952
  1736
		return;
ds@1952
  1737
	}
ds@1952
  1738
ds@1952
  1739
	/* store the number of parameters on the stack */
ds@1952
  1740
	//mov [edi-4], num_params
ds@1952
  1741
	//sub edi, 4
ds@1952
  1742
	IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, num_params, -4);
ds@1952
  1743
	IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  1744
ds@1952
  1745
	/* save registers we will need */
ds@1952
  1746
	//push edx
ds@1952
  1747
	IA32_Push_Reg(jit, AMX_REG_ALT);
ds@1952
  1748
ds@1952
  1749
	/* Align the stack to 16 bytes */
ds@1952
  1750
	//push ebx
ds@1952
  1751
	//mov ebx, esp
ds@1952
  1752
	//and esp, 0xFFFFFF0
ds@1952
  1753
	//sub esp, 4
ds@1952
  1754
	IA32_Push_Reg(jit, REG_EBX);
ds@1952
  1755
	IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
ds@1952
  1756
	IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
ds@1952
  1757
	IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  1758
ds@1952
  1759
	/* push some callback stuff */
ds@1952
  1760
	//push edi		; stack
ds@1952
  1761
	//push <native>	; native index
ds@1952
  1762
	IA32_Push_Reg(jit, AMX_REG_STK);
faluco@2029
  1763
	if (native_index <= SCHAR_MAX && native_index >= SCHAR_MIN)
ds@1952
  1764
	{
ds@1952
  1765
		IA32_Push_Imm8(jit, (jit_int8_t)native_index);
ds@1952
  1766
	} else {
ds@1952
  1767
		IA32_Push_Imm32(jit, native_index);
ds@1952
  1768
	}
ds@1952
  1769
ds@1952
  1770
	/* Relocate stack, heap, frm information, then store back */
ds@1952
  1771
	//mov eax, [esi+context]
ds@1952
  1772
	//mov ecx, [esi+hea]
ds@1952
  1773
	//sub edi, ebp
ds@1952
  1774
	//mov [eax+hp], ecx
ds@1952
  1775
	//mov ecx, [esi]
ds@1952
  1776
	//mov [eax+sp], edi
ds@1952
  1777
	//mov [eax+frm], ecx
ds@1952
  1778
	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1779
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
ds@1952
  1780
	IA32_Sub_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
ds@1952
  1781
	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp));
ds@1952
  1782
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
ds@1952
  1783
	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp));
ds@1952
  1784
	IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm));
ds@1952
  1785
ds@1952
  1786
	/* finally, push the last parameter and make the call */
ds@1952
  1787
	//push eax		; context
ds@1952
  1788
	//call NativeCallback
ds@1952
  1789
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  1790
	jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1791
	if (!data->debug)
ds@1952
  1792
	{
ds@1952
  1793
		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
ds@1952
  1794
		{
ds@1952
  1795
			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
ds@1952
  1796
		}
ds@1952
  1797
		else
ds@1952
  1798
		{
ds@1952
  1799
			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
ds@1952
  1800
		}
ds@1952
  1801
	}
ds@1952
  1802
	else
ds@1952
  1803
	{
ds@1952
  1804
		if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
ds@1952
  1805
		{
ds@1952
  1806
			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
ds@1952
  1807
		}
ds@1952
  1808
		else
ds@1952
  1809
		{
ds@1952
  1810
			IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
ds@1952
  1811
		}
ds@1952
  1812
	}
ds@1952
  1813
	
ds@1952
  1814
	/* check for errors */
ds@1952
  1815
	//mov ecx, [esi+context]
ds@1952
  1816
	//cmp [ecx+err], 0
ds@1952
  1817
	//jnz :error
ds@1952
  1818
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1819
	IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, n_err), 0);
ds@1952
  1820
	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error);
ds@1952
  1821
ds@1952
  1822
	/* restore what we damaged */
ds@1952
  1823
	//mov esp, ebx
ds@1952
  1824
	//pop ebx
ds@1952
  1825
	//add edi, ebp
ds@1952
  1826
	//pop edx
ds@1952
  1827
	IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
ds@1952
  1828
	IA32_Pop_Reg(jit, REG_EBX);
ds@1952
  1829
	IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG);
ds@1952
  1830
	IA32_Pop_Reg(jit, AMX_REG_ALT);
ds@1952
  1831
ds@1952
  1832
	/* pop the stack.  do not check the margins.
ds@1952
  1833
	 * Note that this is not a true macro - we don't bother to
ds@1952
  1834
	 * set ALT here because nothing will be using it.
ds@1952
  1835
	 */
ds@1952
  1836
	num_params++;
ds@1952
  1837
	num_params *= 4;
ds@1952
  1838
	//add edi, <val*4+4>
faluco@2029
  1839
	if (num_params <= SCHAR_MAX && num_params >= SCHAR_MIN)
ds@1952
  1840
	{
ds@1952
  1841
		IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)num_params, MOD_REG);
ds@1952
  1842
	} else {
ds@1952
  1843
		IA32_Add_Rm_Imm32(jit, AMX_REG_STK, num_params, MOD_REG);
ds@1952
  1844
	}
ds@1952
  1845
}
ds@1952
  1846
ds@1952
  1847
inline void WriteOp_Tracker_Push_C(JitWriter *jit)
ds@1952
  1848
{
ds@1952
  1849
	CompData *data = (CompData *)jit->data;
ds@1952
  1850
	cell_t val = jit->read_cell();
ds@1952
  1851
ds@1952
  1852
	/* Save registers that may be damaged by the call */
ds@1952
  1853
	//push eax
ds@1952
  1854
	//push edx
ds@1952
  1855
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  1856
	IA32_Push_Reg(jit, AMX_REG_ALT);
ds@1952
  1857
ds@1952
  1858
	/* Get the context ptr, push it and call the check */
ds@1952
  1859
	//mov eax, [esi+context]
ds@1952
  1860
	//push eax
ds@1952
  1861
	//call JIT_VerifyOrAllocateTracker
ds@1952
  1862
	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1863
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  1864
	jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1865
	IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyOrAllocateTracker);
ds@1952
  1866
ds@1952
  1867
	/* Check for errors */
ds@1952
  1868
	//cmp eax, 0
ds@1952
  1869
	//jnz :error
ds@1952
  1870
	IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
ds@1952
  1871
	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
ds@1952
  1872
ds@1952
  1873
	/* Restore */
ds@1952
  1874
	//pop eax
ds@1952
  1875
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  1876
ds@1952
  1877
	/* Push the value into the stack and increment pCur */
ds@1952
  1878
	//mov edx, [eax+vm[]]
ds@1952
  1879
	//mov ecx, [edx+pcur]
ds@1952
  1880
	//add [edx+pcur], 4
ds@1952
  1881
	//mov [ecx], <val>*4	; we want the count in bytes not in cells
ds@1952
  1882
	IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
ds@1952
  1883
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
ds@1952
  1884
	IA32_Add_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
ds@1952
  1885
	IA32_Mov_Rm_Imm32(jit, AMX_REG_TMP, val*4, MOD_MEM_REG);
ds@1952
  1886
ds@1952
  1887
	/* Restore PRI & ALT */
ds@1952
  1888
	//pop edx
ds@1952
  1889
	//pop eax
ds@1952
  1890
	IA32_Pop_Reg(jit, AMX_REG_ALT);
ds@1952
  1891
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  1892
}
ds@1952
  1893
ds@1952
  1894
inline void WriteOp_Tracker_Pop_SetHeap(JitWriter *jit)
ds@1952
  1895
{
ds@1952
  1896
	CompData *data = (CompData *)jit->data;
ds@1952
  1897
ds@1952
  1898
	/* Save registers that may be damaged by the call */
ds@1952
  1899
	//push eax
ds@1952
  1900
	//push edx
ds@1952
  1901
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  1902
	IA32_Push_Reg(jit, AMX_REG_ALT);
ds@1952
  1903
ds@1952
  1904
	/* Get the context ptr, push it and call the check */
ds@1952
  1905
	//mov eax, [esi+context]
ds@1952
  1906
	//push eax
ds@1952
  1907
	//call JIT_VerifyLowBoundTracker
ds@1952
  1908
	IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT);
ds@1952
  1909
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  1910
	jitoffs_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  1911
	IA32_Write_Jump32_Abs(jit, call, (void *)JIT_VerifyLowBoundTracker);
ds@1952
  1912
ds@1952
  1913
	/* Check for errors */
ds@1952
  1914
	//cmp eax, 0
ds@1952
  1915
	//jnz :error
ds@1952
  1916
	IA32_Cmp_Rm_Imm8(jit, MOD_REG, REG_EAX, 0);
ds@1952
  1917
	IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_return);
ds@1952
  1918
ds@1952
  1919
	/* Restore */
ds@1952
  1920
	//pop eax
ds@1952
  1921
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  1922
ds@1952
  1923
	/* Pop the value from the stack and decrease the heap by it*/
ds@1952
  1924
	//mov edx, [eax+vm[]]
ds@1952
  1925
	//sub [edx+pcur], 4
ds@1952
  1926
	//mov ecx, [edx+pcur]
ds@1952
  1927
	//mov ecx, [ecx]
ds@1952
  1928
	//sub [esi+hea], ecx
ds@1952
  1929
	IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, offsetof(sp_context_t, vm[JITVARS_TRACKER]));
ds@1952
  1930
	IA32_Sub_Rm_Imm8_Disp8(jit, REG_EDX, 4, offsetof(tracker_t, pCur));
ds@1952
  1931
	IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, REG_EDX, offsetof(tracker_t, pCur));
ds@1952
  1932
	IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_TMP, MOD_MEM_REG);
ds@1952
  1933
	IA32_Sub_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_TMP, AMX_INFO_HEAP);
ds@1952
  1934
ds@1952
  1935
	Write_CheckHeap_Min(jit);
ds@1952
  1936
ds@1952
  1937
	/* Restore PRI & ALT */
ds@1952
  1938
	//pop edx
ds@1952
  1939
	//pop eax
ds@1952
  1940
	IA32_Pop_Reg(jit, AMX_REG_ALT);
ds@1952
  1941
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  1942
}
ds@1952
  1943
ds@1952
  1944
inline void WriteOp_Stradjust_Pri(JitWriter *jit)
ds@1952
  1945
{
ds@1952
  1946
	//add eax, 4
ds@1952
  1947
	//sar eax, 2
ds@1952
  1948
	IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 4, MOD_REG);
ds@1952
  1949
	IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 2, MOD_REG);
ds@1952
  1950
}
ds@1952
  1951
ds@1952
  1952
inline void WriteOp_FloatAbs(JitWriter *jit)
ds@1952
  1953
{
ds@1952
  1954
	//mov eax, [edi]
ds@1952
  1955
	//and eax, 0x7FFFFFFF
ds@1952
  1956
	IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
ds@1952
  1957
	IA32_And_Eax_Imm32(jit, 0x7FFFFFFF);
ds@1952
  1958
ds@1952
  1959
	/* Rectify the stack */
ds@1952
  1960
	//add edi, 4
ds@1952
  1961
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  1962
}
ds@1952
  1963
ds@1952
  1964
inline void WriteOp_Float(JitWriter *jit)
ds@1952
  1965
{
ds@1952
  1966
	//fild [edi]
ds@1952
  1967
	//push eax
ds@1952
  1968
	//fstp [esp]
ds@1952
  1969
	//pop eax
ds@1952
  1970
	IA32_Fild_Mem32(jit, AMX_REG_STK);
ds@1952
  1971
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  1972
	IA32_Fstp_Mem32_ESP(jit);
ds@1952
  1973
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  1974
ds@1952
  1975
	/* Rectify the stack */
ds@1952
  1976
	//add edi, 4
ds@1952
  1977
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  1978
}
ds@1952
  1979
ds@1952
  1980
inline void WriteOp_FloatAdd(JitWriter *jit)
ds@1952
  1981
{
ds@1952
  1982
	//push eax
ds@1952
  1983
	//fld [edi]
ds@1952
  1984
	//fadd [edi+4]
ds@1952
  1985
	//fstp [esp]
ds@1952
  1986
	//pop eax
ds@1952
  1987
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  1988
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  1989
	IA32_Fadd_Mem32_Disp8(jit, AMX_REG_STK, 4);
ds@1952
  1990
	IA32_Fstp_Mem32_ESP(jit);
ds@1952
  1991
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  1992
ds@1952
  1993
	/* Rectify the stack */
ds@1952
  1994
	//add edi, 8
ds@1952
  1995
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  1996
}
ds@1952
  1997
ds@1952
  1998
inline void WriteOp_FloatSub(JitWriter *jit)
ds@1952
  1999
{
ds@1952
  2000
	//push eax
ds@1952
  2001
	//fld [edi]
ds@1952
  2002
	//fsub [edi+4]
ds@1952
  2003
	//fstp [esp]
ds@1952
  2004
	//pop eax
ds@1952
  2005
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  2006
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2007
	IA32_Fsub_Mem32_Disp8(jit, AMX_REG_STK, 4);
ds@1952
  2008
	IA32_Fstp_Mem32_ESP(jit);
ds@1952
  2009
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  2010
ds@1952
  2011
	/* Rectify the stack */
ds@1952
  2012
	//add edi, 8
ds@1952
  2013
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  2014
}
ds@1952
  2015
ds@1952
  2016
inline void WriteOp_FloatMul(JitWriter *jit)
ds@1952
  2017
{
ds@1952
  2018
	//push eax
ds@1952
  2019
	//fld [edi]
ds@1952
  2020
	//fmul [edi+4]
ds@1952
  2021
	//fstp [esp]
ds@1952
  2022
	//pop eax
ds@1952
  2023
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  2024
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2025
	IA32_Fmul_Mem32_Disp8(jit, AMX_REG_STK, 4);
ds@1952
  2026
	IA32_Fstp_Mem32_ESP(jit);
ds@1952
  2027
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  2028
ds@1952
  2029
	/* Rectify the stack */
ds@1952
  2030
	//add edi, 8
ds@1952
  2031
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  2032
}
ds@1952
  2033
ds@1952
  2034
inline void WriteOp_FloatDiv(JitWriter *jit)
ds@1952
  2035
{
ds@1952
  2036
	//push eax
ds@1952
  2037
	//fld [edi]
ds@1952
  2038
	//fdiv [edi+4]
ds@1952
  2039
	//fstp [esp]
ds@1952
  2040
	//pop eax
ds@1952
  2041
	IA32_Push_Reg(jit, AMX_REG_PRI);
ds@1952
  2042
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2043
	IA32_Fdiv_Mem32_Disp8(jit, AMX_REG_STK, 4);
ds@1952
  2044
	IA32_Fstp_Mem32_ESP(jit);
ds@1952
  2045
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  2046
ds@1952
  2047
	/* Rectify the stack */
ds@1952
  2048
	//add edi, 8
ds@1952
  2049
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  2050
}
ds@1952
  2051
ds@1952
  2052
inline void WriteOp_RountToNearest(JitWriter *jit)
ds@1952
  2053
{
ds@1952
  2054
	//push eax
ds@1952
  2055
	//fld [edi]
ds@1952
  2056
ds@1952
  2057
	//fstcw [esp]
ds@1952
  2058
	//mov eax, [esp]
ds@1952
  2059
	//push eax
ds@1952
  2060
ds@1952
  2061
	//mov [esp+4], 0x3FF
ds@1952
  2062
	//fadd st(0), st(0)
ds@1952
  2063
	//fldcw [esp+4]
ds@1952
  2064
ds@1952
  2065
	//push eax	
ds@1952
  2066
	//push 0x3F000000 ; 0.5f
ds@1952
  2067
	//fadd [esp]
ds@1952
  2068
	//fistp [esp+4]
ds@1952
  2069
	//pop eax
ds@1952
  2070
	//pop eax
ds@1952
  2071
ds@1952
  2072
	//pop ecx
ds@1952
  2073
	//sar eax, 1
ds@1952
  2074
	//mov [esp], ecx
ds@1952
  2075
	//fldcw [esp]
ds@1952
  2076
	//add esp, 4
ds@1952
  2077
ds@1952
  2078
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2079
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2080
ds@1952
  2081
	IA32_Fstcw_Mem16_ESP(jit);
ds@1952
  2082
	IA32_Mov_Reg_RmESP(jit, REG_EAX);
ds@1952
  2083
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2084
ds@1952
  2085
	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x3FF);
ds@1952
  2086
	IA32_Fadd_FPUreg_ST0(jit, 0);
ds@1952
  2087
	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
ds@1952
  2088
ds@1952
  2089
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2090
	IA32_Push_Imm32(jit, 0x3F000000);
ds@1952
  2091
	IA32_Fadd_Mem32_ESP(jit);
ds@1952
  2092
	IA32_Fistp_Mem32_Disp8_Esp(jit, 4);
ds@1952
  2093
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  2094
	IA32_Pop_Reg(jit, AMX_REG_PRI);
ds@1952
  2095
ds@1952
  2096
	IA32_Pop_Reg(jit, REG_ECX);
ds@1952
  2097
	IA32_Sar_Rm_1(jit, REG_EAX, MOD_REG);
ds@1952
  2098
	IA32_Mov_RmESP_Reg(jit, REG_ECX);
ds@1952
  2099
	IA32_Fldcw_Mem16_ESP(jit);
ds@1952
  2100
	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  2101
ds@1952
  2102
	/* Rectify the stack */
ds@1952
  2103
	//add edi, 4
ds@1952
  2104
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  2105
}
ds@1952
  2106
ds@1952
  2107
inline void WriteOp_RoundToFloor(JitWriter *jit)
ds@1952
  2108
{
ds@1952
  2109
	//push eax
ds@1952
  2110
	//fld [edi]
ds@1952
  2111
ds@1952
  2112
	//fstcw [esp]
ds@1952
  2113
	//mov eax, [esp]
ds@1952
  2114
	//push eax
ds@1952
  2115
ds@1952
  2116
	//mov [esp+4], 0x7FF
ds@1952
  2117
	//fldcw [esp+4]
ds@1952
  2118
ds@1952
  2119
	//push eax	
ds@1952
  2120
	//fistp [esp]
ds@1952
  2121
	//pop eax
ds@1952
  2122
ds@1952
  2123
	//pop ecx
ds@1952
  2124
	//mov [esp], ecx
ds@1952
  2125
	//fldcw [esp]
ds@1952
  2126
	//add esp, 4
ds@1952
  2127
ds@1952
  2128
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2129
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2130
ds@1952
  2131
	IA32_Fstcw_Mem16_ESP(jit);
ds@1952
  2132
	IA32_Mov_Reg_RmESP(jit, REG_EAX);
ds@1952
  2133
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2134
ds@1952
  2135
	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0x7FF);
ds@1952
  2136
	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
ds@1952
  2137
ds@1952
  2138
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2139
	IA32_Fistp_Mem32_ESP(jit);
ds@1952
  2140
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  2141
ds@1952
  2142
	IA32_Pop_Reg(jit, REG_ECX);
ds@1952
  2143
	IA32_Mov_RmESP_Reg(jit, REG_ECX);
ds@1952
  2144
	IA32_Fldcw_Mem16_ESP(jit);
ds@1952
  2145
	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  2146
ds@1952
  2147
	/* Rectify the stack */
ds@1952
  2148
	//add edi, 4
ds@1952
  2149
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  2150
}
ds@1952
  2151
ds@1952
  2152
inline void WriteOp_RoundToCeil(JitWriter *jit)
ds@1952
  2153
{
ds@1952
  2154
	//push eax
ds@1952
  2155
	//fld [edi]
ds@1952
  2156
ds@1952
  2157
	//fstcw [esp]
ds@1952
  2158
	//mov eax, [esp]
ds@1952
  2159
	//push eax
ds@1952
  2160
ds@1952
  2161
	//mov [esp+4], 0xBFF
ds@1952
  2162
	//fldcw [esp+4]
ds@1952
  2163
ds@1952
  2164
	//push eax	
ds@1952
  2165
	//fistp [esp]
ds@1952
  2166
	//pop eax
ds@1952
  2167
ds@1952
  2168
	//pop ecx
ds@1952
  2169
	//mov [esp], ecx
ds@1952
  2170
	//fldcw [esp]
ds@1952
  2171
	//add esp, 4
ds@1952
  2172
ds@1952
  2173
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2174
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2175
ds@1952
  2176
	IA32_Fstcw_Mem16_ESP(jit);
ds@1952
  2177
	IA32_Mov_Reg_RmESP(jit, REG_EAX);
ds@1952
  2178
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2179
ds@1952
  2180
	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xBFF);
ds@1952
  2181
	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
ds@1952
  2182
ds@1952
  2183
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2184
	IA32_Fistp_Mem32_ESP(jit);
ds@1952
  2185
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  2186
ds@1952
  2187
	IA32_Pop_Reg(jit, REG_ECX);
ds@1952
  2188
	IA32_Mov_RmESP_Reg(jit, REG_ECX);
ds@1952
  2189
	IA32_Fldcw_Mem16_ESP(jit);
ds@1952
  2190
	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  2191
ds@1952
  2192
	/* Rectify the stack */
ds@1952
  2193
	//add edi, 4
ds@1952
  2194
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  2195
}
ds@1952
  2196
ds@1952
  2197
inline void WriteOp_RoundToZero(JitWriter *jit)
ds@1952
  2198
{
ds@1952
  2199
	//push eax
ds@1952
  2200
	//fld [edi]
ds@1952
  2201
ds@1952
  2202
	//fstcw [esp]
ds@1952
  2203
	//mov eax, [esp]
ds@1952
  2204
	//push eax
ds@1952
  2205
ds@1952
  2206
	//mov [esp+4], 0xFFF
ds@1952
  2207
	//fldcw [esp+4]
ds@1952
  2208
ds@1952
  2209
	//push eax	
ds@1952
  2210
	//fistp [esp]
ds@1952
  2211
	//pop eax
ds@1952
  2212
ds@1952
  2213
	//pop ecx
ds@1952
  2214
	//mov [esp], ecx
ds@1952
  2215
	//fldcw [esp]
ds@1952
  2216
	//add esp, 4
ds@1952
  2217
ds@1952
  2218
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2219
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2220
ds@1952
  2221
	IA32_Fstcw_Mem16_ESP(jit);
ds@1952
  2222
	IA32_Mov_Reg_RmESP(jit, REG_EAX);
ds@1952
  2223
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2224
ds@1952
  2225
	IA32_Mov_ESP_Disp8_Imm32(jit, 4, 0xFFF);
ds@1952
  2226
	IA32_Fldcw_Mem16_Disp8_ESP(jit, 4);
ds@1952
  2227
ds@1952
  2228
	IA32_Push_Reg(jit, REG_EAX);
ds@1952
  2229
	IA32_Fistp_Mem32_ESP(jit);
ds@1952
  2230
	IA32_Pop_Reg(jit, REG_EAX);
ds@1952
  2231
ds@1952
  2232
	IA32_Pop_Reg(jit, REG_ECX);
ds@1952
  2233
	IA32_Mov_RmESP_Reg(jit, REG_ECX);
ds@1952
  2234
	IA32_Fldcw_Mem16_ESP(jit);
ds@1952
  2235
	IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  2236
ds@1952
  2237
	/* Rectify the stack */
ds@1952
  2238
	//add edi, 4
ds@1952
  2239
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
ds@1952
  2240
}
ds@1952
  2241
ds@1952
  2242
inline void WriteOp_FloatCompare(JitWriter *jit)
ds@1952
  2243
{
ds@1952
  2244
	CompData *data = (CompData *)jit->data;
ds@1952
  2245
ds@1952
  2246
	//fld [edi]
ds@1952
  2247
	//fld [edi+4]
ds@1952
  2248
	//fucomip st(0), st(1)
ds@1952
  2249
	//mov ecx, <round_table>
ds@1952
  2250
	//cmovz eax, [ecx+4]
ds@1952
  2251
	//cmovb eax, [ecx+8]
ds@1952
  2252
	//cmova eax, [ecx]
ds@1952
  2253
	//fstp st(0)
ds@1952
  2254
ds@1952
  2255
	IA32_Fld_Mem32(jit, AMX_REG_STK);
ds@1952
  2256
	IA32_Fld_Mem32_Disp8(jit, AMX_REG_STK, 4);
ds@1952
  2257
	IA32_Fucomip_ST0_FPUreg(jit, 1);
ds@1952
  2258
	IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, (jit_int32_t)jit->outbase + data->jit_rounding_table);
ds@1952
  2259
	IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_Z, 4);
ds@1952
  2260
	IA32_CmovCC_Rm_Disp8(jit, AMX_REG_TMP, CC_B, 8);
ds@1952
  2261
	IA32_CmovCC_Rm(jit, AMX_REG_TMP, CC_A);
ds@1952
  2262
	IA32_Fstp_FPUreg(jit, 0);
ds@1952
  2263
ds@1952
  2264
	/* Rectify the stack */
ds@1952
  2265
	//add edi, 8
ds@1952
  2266
	IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
ds@1952
  2267
}
ds@1952
  2268
ds@1952
  2269
/*************************************************
ds@1952
  2270
 *************************************************
ds@1952
  2271
 * JIT PROPER ************************************
ds@1952
  2272
 * The rest from now on is the JIT engine        *
ds@1952
  2273
 *************************************************
ds@1952
  2274
 *************************************************/
ds@1952
  2275
ds@1952
  2276
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
ds@1952
  2277
{
ds@1952
  2278
	sp_native_t *native;
dvander@2193
  2279
	sp_plugin_t *plugin;
dvander@2193
  2280
dvander@2193
  2281
	plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
ds@1952
  2282
	
dvander@2193
  2283
	native = &plugin->natives[native_idx];
ds@1952
  2284
ds@1952
  2285
	ctx->n_idx = native_idx;
ds@1952
  2286
	
ds@1952
  2287
	/* Technically both aren't needed, I guess */
ds@1952
  2288
	if (native->status == SP_NATIVE_UNBOUND)
ds@1952
  2289
	{
ds@1952
  2290
		ctx->n_err = SP_ERROR_INVALID_NATIVE;
ds@1952
  2291
		return 0;
ds@1952
  2292
	}
ds@1952
  2293
dvander@2193
  2294
	return native->pfn(GET_CONTEXT(ctx), params);
ds@1952
  2295
}
ds@1952
  2296
ds@1952
  2297
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
ds@1952
  2298
{
ds@1952
  2299
	cell_t val;
ds@1952
  2300
	sp_native_t *native;
dvander@2193
  2301
	sp_plugin_t *plugin;
dvander@2193
  2302
dvander@2193
  2303
	plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
dvander@2193
  2304
dvander@2193
  2305
	native = &plugin->natives[native_idx];
ds@1952
  2306
ds@1952
  2307
	ctx->n_idx = native_idx;
ds@1952
  2308
ds@1952
  2309
	/* Technically both aren't needed, I guess */
ds@1952
  2310
	if (native->status == SP_NATIVE_UNBOUND)
ds@1952
  2311
	{
ds@1952
  2312
		ctx->n_err = SP_ERROR_INVALID_NATIVE;
ds@1952
  2313
		return 0;
ds@1952
  2314
	}
ds@1952
  2315
dvander@2193
  2316
	plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
dvander@2193
  2317
	val = native->pfn(GET_CONTEXT(ctx), params);
dvander@2193
  2318
	plugin->profiler->OnNativeEnd();
ds@1952
  2319
ds@1952
  2320
	return val;
ds@1952
  2321
}
ds@1952
  2322
ds@1952
  2323
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
ds@1952
  2324
{
ds@1952
  2325
	cell_t save_sp = ctx->sp;
ds@1952
  2326
	cell_t save_hp = ctx->hp;
ds@1952
  2327
dvander@2193
  2328
	sp_plugin_t *pl = GETPLUGIN(ctx);
dvander@2193
  2329
ds@1952
  2330
	ctx->n_idx = native_idx;
ds@1952
  2331
dvander@2193
  2332
	if (ctx->hp < (cell_t)pl->data_size)
ds@1952
  2333
	{
ds@1952
  2334
		ctx->n_err = SP_ERROR_HEAPMIN;
ds@1952
  2335
		return 0;
ds@1952
  2336
	}
ds@1952
  2337
ds@1952
  2338
	if (ctx->hp + STACK_MARGIN > ctx->sp)
ds@1952
  2339
	{
ds@1952
  2340
		ctx->n_err = SP_ERROR_STACKLOW;
ds@1952
  2341
		return 0;
ds@1952
  2342
	}
ds@1952
  2343
dvander@2193
  2344
	if ((uint32_t)ctx->sp >= pl->mem_size)
ds@1952
  2345
	{
ds@1952
  2346
		ctx->n_err = SP_ERROR_STACKMIN;
ds@1952
  2347
		return 0;
ds@1952
  2348
	}
ds@1952
  2349
ds@1952
  2350
	cell_t result = NativeCallback(ctx, native_idx, params);
ds@1952
  2351
ds@1952
  2352
	if (ctx->n_err != SP_ERROR_NONE)
ds@1952
  2353
	{
ds@1952
  2354
		return result;
ds@1952
  2355
	}
ds@1952
  2356
ds@1952
  2357
	if (save_sp != ctx->sp)
ds@1952
  2358
	{
ds@1952
  2359
		ctx->n_err = SP_ERROR_STACKLEAK;
ds@1952
  2360
		return result;
ds@1952
  2361
	}
ds@1952
  2362
	else if (save_hp != ctx->hp)
ds@1952
  2363
	{
ds@1952
  2364
		ctx->n_err = SP_ERROR_HEAPLEAK;
ds@1952
  2365
		return result;
ds@1952
  2366
	}
ds@1952
  2367
ds@1952
  2368
	return result;
ds@1952
  2369
}
ds@1952
  2370
ds@1952
  2371
cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
ds@1952
  2372
{
ds@1952
  2373
	cell_t save_sp = ctx->sp;
ds@1952
  2374
	cell_t save_hp = ctx->hp;
ds@1952
  2375
dvander@2193
  2376
	sp_plugin_t *pl = GETPLUGIN(ctx);
dvander@2193
  2377
ds@1952
  2378
	ctx->n_idx = native_idx;
ds@1952
  2379
dvander@2193
  2380
	if (ctx->hp < (cell_t)pl->data_size)
ds@1952
  2381
	{
ds@1952
  2382
		ctx->n_err = SP_ERROR_HEAPMIN;
ds@1952
  2383
		return 0;
ds@1952
  2384
	}
ds@1952
  2385
ds@1952
  2386
	if (ctx->hp + STACK_MARGIN > ctx->sp)
ds@1952
  2387
	{
ds@1952
  2388
		ctx->n_err = SP_ERROR_STACKLOW;
ds@1952
  2389
		return 0;
ds@1952
  2390
	}
ds@1952
  2391
dvander@2193
  2392
	if ((uint32_t)ctx->sp >= pl->mem_size)
ds@1952
  2393
	{
ds@1952
  2394
		ctx->n_err = SP_ERROR_STACKMIN;
ds@1952
  2395
		return 0;
ds@1952
  2396
	}
ds@1952
  2397
ds@1952
  2398
	cell_t result = NativeCallback_Profile(ctx, native_idx, params);
ds@1952
  2399
ds@1952
  2400
	if (ctx->n_err != SP_ERROR_NONE)
ds@1952
  2401
	{
ds@1952
  2402
		return result;
ds@1952
  2403
	}
ds@1952
  2404
ds@1952
  2405
	if (save_sp != ctx->sp)
ds@1952
  2406
	{
ds@1952
  2407
		ctx->n_err = SP_ERROR_STACKLEAK;
ds@1952
  2408
		return result;
ds@1952
  2409
	}
ds@1952
  2410
	else if (save_hp != ctx->hp)
ds@1952
  2411
	{
ds@1952
  2412
		ctx->n_err = SP_ERROR_HEAPLEAK;
ds@1952
  2413
		return result;
ds@1952
  2414
	}
ds@1952
  2415
ds@1952
  2416
	return result;
ds@1952
  2417
}
ds@1952
  2418
ds@1952
  2419
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
ds@1952
  2420
{
dvander@2193
  2421
	return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
ds@1952
  2422
}
ds@1952
  2423
ds@1952
  2424
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
ds@1952
  2425
{
ds@1952
  2426
	if (jit->outptr)
ds@1952
  2427
	{
ds@1952
  2428
		CompData *data = (CompData *)jit->data;
ds@1952
  2429
		if (relative)
ds@1952
  2430
		{
ds@1952
  2431
			/* The actual offset is EIP relative. We need to relocate it.
ds@1952
  2432
			 * Note that this assumes that we're pointing to the next op.
ds@1952
  2433
			 */
ds@1952
  2434
			pcode_offs += jit->get_inputpos();
ds@1952
  2435
		}
ds@1952
  2436
		/* Offset must always be 1)positive and 2)less than or equal to the codesize */
ds@1952
  2437
		assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
ds@1952
  2438
		/* Do the lookup in the native dictionary. */
ds@1952
  2439
		return *(jitoffs_t *)(data->rebase + pcode_offs);
ds@1952
  2440
	}
ds@1952
  2441
	else
ds@1952
  2442
	{
ds@1952
  2443
		return 0;
ds@1952
  2444
	}
ds@1952
  2445
}
ds@1952
  2446
ds@1952
  2447
void WriteErrorRoutines(CompData *data, JitWriter *jit)
ds@1952
  2448
{
ds@1952
  2449
	AlignMe(jit);
ds@1952
  2450
ds@1952
  2451
	data->jit_error_divzero = jit->get_outputpos();
ds@1952
  2452
	Write_SetError(jit, SP_ERROR_DIVIDE_BY_ZERO);
ds@1952
  2453
ds@1952
  2454
	data->jit_error_stacklow = jit->get_outputpos();
ds@1952
  2455
	Write_SetError(jit, SP_ERROR_STACKLOW);
ds@1952
  2456
ds@1952
  2457
	data->jit_error_stackmin = jit->get_outputpos();
ds@1952
  2458
	Write_SetError(jit, SP_ERROR_STACKMIN);
ds@1952
  2459
ds@1952
  2460
	data->jit_error_bounds = jit->get_outputpos();
ds@1952
  2461
	Write_SetError(jit, SP_ERROR_ARRAY_BOUNDS);
ds@1952
  2462
ds@1952
  2463
	data->jit_error_memaccess = jit->get_outputpos();
ds@1952
  2464
	Write_SetError(jit, SP_ERROR_MEMACCESS);
ds@1952
  2465
ds@1952
  2466
	data->jit_error_heaplow = jit->get_outputpos();
ds@1952
  2467
	Write_SetError(jit, SP_ERROR_HEAPLOW);
ds@1952
  2468
ds@1952
  2469
	data->jit_error_heapmin = jit->get_outputpos();
ds@1952
  2470
	Write_SetError(jit, SP_ERROR_HEAPMIN);
ds@1952
  2471
ds@1952
  2472
	data->jit_error_array_too_big = jit->get_outputpos();
ds@1952
  2473
	Write_SetError(jit, SP_ERROR_ARRAY_TOO_BIG);
ds@1952
  2474
ds@1952
  2475
	data->jit_extern_error = jit->get_outputpos();
ds@1952
  2476
	Write_GetError(jit);
ds@1952
  2477
}
ds@1952
  2478
dvander@2193
  2479
bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
ds@1952
  2480
{
ds@1952
  2481
	CompData *data = (CompData *)co;
ds@1952
  2482
	sp_plugin_t *plugin = data->plugin;
ds@1952
  2483
dvander@2193
  2484
	if (data->plugin == NULL)
dvander@2193
  2485
	{
dvander@2193
  2486
		if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
dvander@2193
  2487
		{
dvander@2193
  2488
			if (err != NULL)
dvander@2193
  2489
			{
dvander@2193
  2490
				*err = SP_ERROR_NOTDEBUGGING;
dvander@2193
  2491
			}
dvander@2193
  2492
			co->Abort();
dvander@2193
  2493
			return false;
dvander@2193
  2494
		}
dvander@2193
  2495
dvander@2193
  2496
		data->SetRuntime(prt);
dvander@2193
  2497
		plugin = data->plugin;
dvander@2193
  2498
	}
dvander@2193
  2499
ds@1952
  2500
	/* The first phase is to browse */
ds@1952
  2501
	uint8_t *code = plugin->pcode;
ds@1952
  2502
	uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
ds@1952
  2503
	OPCODE op;
ds@1952
  2504
ds@1952
  2505
	/*********************************************
ds@1952
  2506
	 * FIRST PASS (medium load): writer.outbase is NULL, getting size only
ds@1952
  2507
	 * SECOND PASS (heavy load!!): writer.outbase is valid and output is written
ds@1952
  2508
	 *********************************************/
ds@1952
  2509
ds@1952
  2510
	JitWriter writer;
ds@1952
  2511
	JitWriter *jit = &writer;
ds@1952
  2512
	cell_t *endptr = (cell_t *)(end_cip);
ds@1952
  2513
	uint32_t codemem = 0;
ds@1952
  2514
ds@1952
  2515
	/* Initial code is written "blank,"
ds@1952
  2516
	 * so we can check the exact memory usage.
ds@1952
  2517
	 */
ds@1952
  2518
	data->codesize = plugin->pcode_size;
ds@1952
  2519
	writer.data = data;
ds@1952
  2520
	writer.inbase = (cell_t *)code;
ds@1952
  2521
	writer.outptr = NULL;
ds@1952
  2522
	writer.outbase = NULL;
ds@1952
  2523
	/* Allocate relocation.  One extra cell for final CIP. */
ds@1952
  2524
	data->rebase = (jitcode_t)engine->BaseAlloc(plugin->pcode_size + sizeof(cell_t));
ds@1952
  2525
ds@1952
  2526
	/* We will jump back here for second pass */
ds@1952
  2527
jit_rewind:
ds@1952
  2528
	/* Initialize pass vars */
ds@1952
  2529
	writer.inptr = writer.inbase;
ds@1952
  2530
	data->jit_verify_addr_eax = 0;
ds@1952
  2531
	data->jit_verify_addr_edx = 0;
ds@1952
  2532
ds@1952
  2533
	/* Write the prologue of the JIT */
ds@1952
  2534
	data->jit_return = Write_Execute_Function(jit);
ds@1952
  2535
ds@1952
  2536
	/* Write the SYSREQ.N opcode if we need to */
ds@1952
  2537
	if (!(data->inline_level & JIT_INLINE_NATIVES))
ds@1952
  2538
	{
ds@1952
  2539
		AlignMe(jit);
ds@1952
  2540
		data->jit_sysreq_n = jit->get_outputpos();
ds@1952
  2541
		WriteOp_Sysreq_N_Function(jit);
ds@1952
  2542
	}
ds@1952
  2543
ds@1952
  2544
	/* Write the debug section if we need it */
ds@1952
  2545
	if (data->debug == true)
ds@1952
  2546
	{
ds@1952
  2547
		AlignMe(jit);
ds@1952
  2548
		data->jit_break = jit->get_outputpos();
ds@1952
  2549
		Write_BreakDebug(jit);
ds@1952
  2550
	}
ds@1952
  2551
ds@1952
  2552
	/* Plugins compiled with -O0 will need this! */
ds@1952
  2553
	AlignMe(jit);
ds@1952
  2554
	data->jit_sysreq_c = jit->get_outputpos();
ds@1952
  2555
	WriteOp_Sysreq_C_Function(jit);
ds@1952
  2556
ds@1952
  2557
	AlignMe(jit);
ds@1952
  2558
	data->jit_genarray = jit->get_outputpos();
ds@1952
  2559
	WriteIntrinsic_GenArray(jit);
ds@1952
  2560
ds@1952
  2561
	/* Write error checking routines that are called to */
ds@1952
  2562
	if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
ds@1952
  2563
	{
ds@1952
  2564
		AlignMe(jit);
ds@1952
  2565
		data->jit_verify_addr_eax = jit->get_outputpos();
ds@1952
  2566
		Write_Check_VerifyAddr(jit, REG_EAX);
ds@1952
  2567
	
ds@1952
  2568
		AlignMe(jit);
ds@1952
  2569
		data->jit_verify_addr_edx = jit->get_outputpos();
ds@1952
  2570
		Write_Check_VerifyAddr(jit, REG_EDX);
ds@1952
  2571
	}
ds@1952
  2572
ds@1952
  2573
	/* Write the rounding table for the float compare opcode */
ds@1952
  2574
	data->jit_rounding_table = jit->get_outputpos();
ds@1952
  2575
	Write_RoundingTable(jit);
ds@1952
  2576
ds@1952
  2577
	/* Actual code generation! */
ds@1952
  2578
	if (writer.outbase == NULL)
ds@1952
  2579
	{
ds@1952
  2580
		/* First Pass - find codesize and resolve relocation */
ds@1952
  2581
		jitoffs_t pcode_offs;
ds@1952
  2582
		jitoffs_t native_offs;
ds@1952
  2583
ds@1952
  2584
		for (; writer.inptr < endptr;)
ds@1952
  2585
		{
ds@1952
  2586
			/* Store the native offset into the rebase memory.
ds@1952
  2587
			 * This large chunk of memory lets us do an instant lookup
ds@1952
  2588
			 * based on an original pcode offset.
ds@1952
  2589
			 */
ds@1952
  2590
			pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
ds@1952
  2591
			native_offs = jit->get_outputpos();
ds@1952
  2592
			*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
ds@1952
  2593
ds@1952
  2594
			/* Now read the opcode and continue. */
ds@1952
  2595
			op = (OPCODE)writer.read_cell();
ds@1952
  2596
ds@1952
  2597
			/* Patch the floating point natives with our opcodes */
ds@1952
  2598
			if (op == OP_SYSREQ_N)
ds@1952
  2599
			{
ds@1952
  2600
				cell_t idx = writer.read_cell();
ds@1952
  2601
				if (data->jit_float_table[idx].found)
ds@1952
  2602
				{
ds@1952
  2603
					writer.inptr -= 2;
ds@1952
  2604
					*(writer.inptr++) = data->jit_float_table[idx].index;
ds@1952
  2605
					*(writer.inptr++) = OP_NOP;
ds@1952
  2606
					*(writer.inptr++) = OP_NOP;
ds@1952
  2607
					op = (OPCODE)data->jit_float_table[idx].index;
dvander@2093
  2608
				}
dvander@2093
  2609
				else
dvander@2093
  2610
				{
ds@1952
  2611
					writer.inptr--;
ds@1952
  2612
				}
ds@1952
  2613
			}
ds@1952
  2614
			switch (op)
ds@1952
  2615
			{
ds@1952
  2616
				#include "opcode_switch.inc"
ds@1952
  2617
			}
ds@1952
  2618
			/* Check for errors.  This should only happen in the first pass. */
ds@1952
  2619
			if (data->error_set != SP_ERROR_NONE)
ds@1952
  2620
			{
ds@1952
  2621
				*err = data->error_set;
dvander@2193
  2622
				co->Abort();
dvander@2193
  2623
				return false;
ds@1952
  2624
			}
ds@1952
  2625
		}
ds@1952
  2626
		/* Write these last because error jumps should be unpredicted, and thus forward */
ds@1952
  2627
		WriteErrorRoutines(data, jit);
ds@1952
  2628
ds@1952
  2629
		/* Write the final CIP to the last position in the reloc array */
ds@1952
  2630
		pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
ds@1952
  2631
		native_offs = jit->get_outputpos();
ds@1952
  2632
		*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
ds@1952
  2633
ds@1952
  2634
		/* the total codesize is now known! */
ds@1952
  2635
		codemem = writer.get_outputpos();
ds@1952
  2636
		writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem);
ds@1952
  2637
		engine->SetReadWrite(writer.outbase);
ds@1952
  2638
		writer.outptr = writer.outbase;
ds@1952
  2639
		/* go back for third pass */
ds@1952
  2640
		goto jit_rewind;
dvander@2093
  2641
	}
dvander@2093
  2642
	else
dvander@2093
  2643
	{
ds@1952
  2644
		/*******
ds@1952
  2645
		 * THIRD PASS - write opcode info
ds@1952
  2646
		 *******/
ds@1952
  2647
		for (; writer.inptr < endptr;)
ds@1952
  2648
		{
ds@1952
  2649
			op = (OPCODE)writer.read_cell();
ds@1952
  2650
			switch (op)
ds@1952
  2651
			{
ds@1952
  2652
				#include "opcode_switch.inc"
ds@1952
  2653
			}
ds@1952
  2654
		}
ds@1952
  2655
		/* Write these last because error jumps should be unpredicted, and thus forward */
ds@1952
  2656
		WriteErrorRoutines(data, jit);
ds@1952
  2657
ds@1952
  2658
		engine->SetReadExecute(writer.outbase);
ds@1952
  2659
	}
ds@1952
  2660
ds@1952
  2661
	/*************
ds@1952
  2662
	 * FOURTH PASS - Context Setup
ds@1952
  2663
	 *************/
ds@1952
  2664
ds@1952
  2665
	/* setup  basics */
dvander@2193
  2666
	sp_context_t *ctx = data->runtime->GetBaseContext()->GetCtx();
dvander@2193
  2667
dvander@2193
  2668
	/* Clear out any old cruft */
dvander@2193
  2669
	if (plugin->codebase != NULL)
dvander@2193
  2670
	{
dvander@2193
  2671
		FreePluginVars(data->runtime->m_pPlugin);
dvander@2193
  2672
		FreeContextVars(ctx);
dvander@2193
  2673
	}
dvander@2193
  2674
	
dvander@2193
  2675
	plugin->codebase = writer.outbase;
dvander@2193
  2676
	plugin->jit_codesize = codemem;
dvander@2193
  2677
	plugin->jit_memsize = 0;
ds@1952
  2678
ds@1952
  2679
	/* setup memory */
dvander@2193
  2680
dvander@2193
  2681
	ctx->hp = plugin->data_size;
dvander@2193
  2682
	ctx->sp = plugin->mem_size - sizeof(cell_t);
dvander@2193
  2683
	ctx->frm = ctx->sp;
dvander@2193
  2684
	ctx->n_err = SP_ERROR_NONE;
dvander@2193
  2685
	ctx->n_idx = SP_ERROR_NONE;
dvander@2193
  2686
	plugin->prof_flags = data->profile;
dvander@2193
  2687
	plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
ds@1952
  2688
ds@1952
  2689
	const char *strbase = plugin->info.stringbase;
ds@1952
  2690
	uint32_t max, iter;
ds@1952
  2691
ds@1952
  2692
	/* relocate public info */
ds@1952
  2693
	if ((max = plugin->info.publics_num))
ds@1952
  2694
	{
dvander@2193
  2695
		plugin->publics = new sp_public_t[max];
dvander@2193
  2696
		plugin->jit_memsize += sizeof(sp_public_t) * max;
ds@1952
  2697
		for (iter=0; iter<max; iter++)
ds@1952
  2698
		{
dvander@2193
  2699
			plugin->publics[iter].name = strbase + plugin->info.publics[iter].name;
dvander@2193
  2700
			plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
ds@1952
  2701
			/* Encode the ID as a straight code offset */
dvander@2193
  2702
			plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
ds@1952
  2703
		}
ds@1952
  2704
	}
ds@1952
  2705
ds@1952
  2706
	/* relocate pubvar info */
ds@1952
  2707
	if ((max = plugin->info.pubvars_num))
ds@1952
  2708
	{
dvander@2193
  2709
		uint8_t *dat = plugin->memory;
dvander@2193
  2710
		plugin->pubvars = new sp_pubvar_t[max];
dvander@2193
  2711
		plugin->jit_memsize += sizeof(sp_pubvar_t) * max;
ds@1952
  2712
		for (iter=0; iter<max; iter++)
ds@1952
  2713
		{
dvander@2193
  2714
			plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
dvander@2193
  2715
			plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
ds@1952
  2716
		}
ds@1952
  2717
	}
ds@1952
  2718
ds@1952
  2719
	/* relocate native info */
ds@1952
  2720
	if ((max = plugin->info.natives_num))
ds@1952
  2721
	{
dvander@2193
  2722
		plugin->natives = new sp_native_t[max];
dvander@2193
  2723
		plugin->jit_memsize += sizeof(sp_native_t) * max;
ds@1952
  2724
		for (iter=0; iter<max; iter++)
ds@1952
  2725
		{
dvander@2193
  2726
			plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
dvander@2193
  2727
			plugin->natives[iter].pfn = &InvalidNative;
dvander@2193
  2728
			plugin->natives[iter].status = SP_NATIVE_UNBOUND;
dvander@2193
  2729
			plugin->natives[iter].flags = 0;
dvander@2193
  2730
			plugin->natives[iter].user = NULL;
ds@1952
  2731
		}
ds@1952
  2732
	}
ds@1952
  2733
ds@1952
  2734
	/**
ds@1952
  2735
	 * If we're debugging, make sure we copy the necessary info.
ds@1952
  2736
	 */
ds@1952
  2737
	if (data->debug)
ds@1952
  2738
	{
ds@1952
  2739
		strbase = plugin->debug.stringbase;
ds@1952
  2740
		
ds@1952
  2741
		/* relocate files */
ds@1952
  2742
		max = plugin->debug.files_num;
dvander@2193
  2743
		plugin->files = new sp_debug_file_t[max];
dvander@2193
  2744
		plugin->jit_memsize += sizeof(sp_debug_file_t) * max;
ds@1952
  2745
		for (iter=0; iter<max; iter++)
ds@1952
  2746
		{
dvander@2193
  2747
			plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
dvander@2193
  2748
			plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
ds@1952
  2749
		}
ds@1952
  2750
ds@1952
  2751
		/* relocate lines */
ds@1952
  2752
		max = plugin->debug.lines_num;
dvander@2193
  2753
		plugin->lines = new sp_debug_line_t[max];
dvander@2193
  2754
		plugin->jit_memsize += sizeof(sp_debug_line_t) * max;
ds@1952
  2755
		for (iter=0; iter<max; iter++)
ds@1952
  2756
		{
dvander@2193
  2757
			plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
dvander@2193
  2758
			plugin->lines[iter].line = plugin->debug.lines[iter].line;
ds@1952
  2759
		}
ds@1952
  2760
ds@1952
  2761
		/* relocate arrays */
ds@1952
  2762
		sp_fdbg_symbol_t *sym;
ds@1952
  2763
		sp_fdbg_arraydim_t *arr;
ds@1952
  2764
		uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
ds@1952
  2765
		
ds@1952
  2766
		max = plugin->debug.syms_num;
dvander@2193
  2767
		plugin->symbols = new sp_debug_symbol_t[max];
dvander@2193
  2768
		plugin->jit_memsize += sizeof(sp_debug_symbol_t) * max;
ds@1952
  2769
		for (iter=0; iter<max; iter++)
ds@1952
  2770
		{
ds@1952
  2771
			sym = (sp_fdbg_symbol_t *)cursor;
ds@1952
  2772
ds@1952
  2773
			/**
ds@1952
  2774
			 * @brief There is an "issue" where the compiler will give totally bogus code 
ds@1952
  2775
			 * address because codegeneration is still being calculated.  A simple fix for 
ds@1952
  2776
			 * this is to coerce the codestart value to 0 when it's invalid.
ds@1952
  2777
			 */
ds@1952
  2778
			if (sym->codestart > data->codesize)
ds@1952
  2779
			{
dvander@2193
  2780
				plugin->symbols[iter].codestart = 0;
ds@1952
  2781
			} else {
dvander@2193
  2782
				plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
ds@1952
  2783
			}
ds@1952
  2784
			if (sym->codeend > data->codesize)
ds@1952
  2785
			{
dvander@2193
  2786
				plugin->symbols[iter].codeend = data->codesize;
ds@1952
  2787
			} else {
dvander@2193
  2788
				plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
ds@1952
  2789
			}
dvander@2193
  2790
			plugin->symbols[iter].name = strbase + sym->name;
dvander@2193
  2791
			plugin->symbols[iter].sym = sym;
ds@1952
  2792
ds@1952
  2793
			if (sym->dimcount > 0)
ds@1952
  2794
			{
ds@1952
  2795
				cursor += sizeof(sp_fdbg_symbol_t);
ds@1952
  2796
				arr = (sp_fdbg_arraydim_t *)cursor;
dvander@2193
  2797
				plugin->symbols[iter].dims = arr;
ds@1952
  2798
				cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
ds@1952
  2799
				continue;
ds@1952
  2800
			}
ds@1952
  2801
dvander@2193
  2802
			plugin->symbols[iter].dims = NULL;
ds@1952
  2803
			cursor += sizeof(sp_fdbg_symbol_t);
ds@1952
  2804
		}
ds@1952
  2805
	}
ds@1952
  2806
ds@1952
  2807
	tracker_t *trk = new tracker_t;
ds@1952
  2808
	ctx->vm[JITVARS_TRACKER] = trk;
dvander@2193
  2809
	ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
dvander@2193
  2810
	ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
dvander@2193
  2811
	ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
ds@1952
  2812
	trk->pBase = (ucell_t *)malloc(1024);
ds@1952
  2813
	trk->pCur = trk->pBase;
ds@1952
  2814
	trk->size = 1024 / sizeof(cell_t);
ds@1952
  2815
dvander@2193
  2816
	plugin->jit_memsize += trk->size;
ds@1952
  2817
ds@1952
  2818
	/* clean up relocation+compilation memory */
dvander@2193
  2819
	co->Abort();
ds@1952
  2820
ds@1952
  2821
	*err = SP_ERROR_NONE;
ds@1952
  2822
dvander@2193
  2823
	return true;
ds@1952
  2824
}
ds@1952
  2825
ds@1952
  2826
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
ds@1952
  2827
{
ds@1952
  2828
	JitWriter jw;
ds@1952
  2829
	JitWriter *jit = &jw;
ds@1952
  2830
ds@1952
  2831
	jw.outbase = NULL;
ds@1952
  2832
	jw.outptr = NULL;
ds@1952
  2833
	jw.data = NULL;
ds@1952
  2834
ds@1952
  2835
	/* First pass, calculate size */
ds@1952
  2836
rewind:
ds@1952
  2837
	/* Align the stack to 16 bytes */
ds@1952
  2838
	//push ebx
ds@1952
  2839
	//push edi
ds@1952
  2840
	//push esi
ds@1952
  2841
	//mov edi, [esp+16]	;store ctx
ds@1952
  2842
	//mov esi, [esp+20]	;store params
ds@1952
  2843
	//mov ebx, esp
ds@1952
  2844
	//and esp, 0xFFFFFF0
ds@1952
  2845
	//sub esp, 4
ds@1952
  2846
	IA32_Push_Reg(jit, REG_EBX);
ds@1952
  2847
	IA32_Push_Reg(jit, REG_EDI);
ds@1952
  2848
	IA32_Push_Reg(jit, REG_ESI);
ds@1952
  2849
	IA32_Mov_Reg_Esp_Disp8(jit, REG_EDI, 16);
ds@1952
  2850
	IA32_Mov_Reg_Esp_Disp8(jit, REG_ESI, 20);
ds@1952
  2851
	IA32_Mov_Reg_Rm(jit, REG_EBX, REG_ESP, MOD_REG);
ds@1952
  2852
	IA32_And_Rm_Imm8(jit, REG_ESP, MOD_REG, -16);
ds@1952
  2853
	IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
ds@1952
  2854
ds@1952
  2855
	//push pData		;push pData
ds@1952
  2856
	//push esi			;push params
ds@1952
  2857
	//push edi			;push ctx
ds@1952
  2858
	//call [callback]	;invoke the meta-callback
ds@1952
  2859
	//mov esp, ebx		;restore the stack
ds@1952
  2860
	//pop esi			;restore esi
ds@1952
  2861
	//pop edi			;restore edi
ds@1952
  2862
	//pop ebx			;restore ebx
ds@1952
  2863
	//ret				;return
ds@1952
  2864
	IA32_Push_Imm32(jit, (jit_int32_t)pData);
ds@1952
  2865
	IA32_Push_Reg(jit, REG_ESI);
ds@1952
  2866
	IA32_Push_Reg(jit, REG_EDI);
ds@1952
  2867
	uint32_t call = IA32_Call_Imm32(jit, 0);
ds@1952
  2868
	IA32_Write_Jump32_Abs(jit, call, (void *)callback);
ds@1952
  2869
	IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBX, MOD_REG);
ds@1952
  2870
	IA32_Pop_Reg(jit, REG_ESI);
ds@1952
  2871
	IA32_Pop_Reg(jit, REG_EDI);
ds@1952
  2872
	IA32_Pop_Reg(jit, REG_EBX);
ds@1952
  2873
	IA32_Return(jit);
ds@1952
  2874
ds@1952
  2875
	if (jw.outbase == NULL)
ds@1952
  2876
	{
ds@1952
  2877
		/* Second pass: Actually write */
ds@1952
  2878
		jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos());
ds@1952
  2879
		if (!jw.outbase)
ds@1952
  2880
		{
ds@1952
  2881
			return NULL;
ds@1952
  2882
		}
ds@1952
  2883
		engine->SetReadWrite(jw.outbase);
ds@1952
  2884
		jw.outptr = jw.outbase;
ds@1952
  2885
	
ds@1952
  2886
		goto rewind;
ds@1952
  2887
	}
ds@1952
  2888
ds@1952
  2889
	engine->SetReadExecute(jw.outbase);
ds@1952
  2890
ds@1952
  2891
	return (SPVM_NATIVE_FUNC)jw.outbase;
ds@1952
  2892
}
ds@1952
  2893
ds@1952
  2894
void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
ds@1952
  2895
{
ds@1952
  2896
	engine->FreePageMemory((void *)func);
ds@1952
  2897
}
ds@1952
  2898
dvander@2193
  2899
int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
ds@1952
  2900
{
ds@1952
  2901
	typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
dvander@2193
  2902
 	CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)pl->codebase;
ds@1952
  2903
	return fn(ctx, code_idx, result);
ds@1952
  2904
}
ds@1952
  2905
dvander@2193
  2906
ICompilation *JITX86::StartCompilation()
ds@1952
  2907
{
ds@1952
  2908
	CompData *data = new CompData;
dvander@2193
  2909
dvander@2193
  2910
	data->jit_float_table = NULL;
dvander@2193
  2911
dvander@2193
  2912
	return data;
dvander@2193
  2913
}
dvander@2193
  2914
dvander@2193
  2915
void CompData::SetRuntime(BaseRuntime *runtime)
dvander@2193
  2916
{
dvander@2193
  2917
	plugin = runtime->m_pPlugin;
dvander@2193
  2918
ds@1952
  2919
	uint32_t max_natives = plugin->info.natives_num;
ds@1952
  2920
	const char *strbase = plugin->info.stringbase;
ds@1952
  2921
dvander@2193
  2922
	this->runtime = runtime;
dvander@2193
  2923
dvander@2193
  2924
	inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
dvander@2193
  2925
	error_set = SP_ERROR_NONE;
dvander@2193
  2926
dvander@2193
  2927
	jit_float_table = new floattbl_t[max_natives];
ds@1952
  2928
	for (uint32_t i=0; i<max_natives; i++)
ds@1952
  2929
	{
ds@1952
  2930
		const char *name = strbase + plugin->info.natives[i].name;
ds@1952
  2931
		if (!strcmp(name, "FloatAbs"))
ds@1952
  2932
		{
dvander@2193
  2933
			jit_float_table[i].found = true;
dvander@2193
  2934
			jit_float_table[i].index = OP_FABS;
ds@1952
  2935
		} else if (!strcmp(name, "FloatAdd")) {
dvander@2193
  2936
			jit_float_table[i].found = true;
dvander@2193
  2937
			jit_float_table[i].index = OP_FLOATADD;
ds@1952
  2938
		} else if (!strcmp(name, "FloatSub")) {
dvander@2193
  2939
			jit_float_table[i].found = true;
dvander@2193
  2940
			jit_float_table[i].index = OP_FLOATSUB;
ds@1952
  2941
		} else if (!strcmp(name, "FloatMul")) {
dvander@2193
  2942
			jit_float_table[i].found = true;
dvander@2193
  2943
			jit_float_table[i].index = OP_FLOATMUL;
ds@1952
  2944
		} else if (!strcmp(name, "FloatDiv")) {
dvander@2193
  2945
			jit_float_table[i].found = true;
dvander@2193
  2946
			jit_float_table[i].index = OP_FLOATDIV;
ds@1952
  2947
		} else if (!strcmp(name, "float")) {
dvander@2193
  2948
			jit_float_table[i].found = true;
dvander@2193
  2949
			jit_float_table[i].index = OP_FLOAT;
ds@1952
  2950
		} else if (!strcmp(name, "FloatCompare")) {
dvander@2193
  2951
			jit_float_table[i].found = true;
dvander@2193
  2952
			jit_float_table[i].index = OP_FLOATCMP;
ds@1952
  2953
		} else if (!strcmp(name, "RoundToZero")) {
dvander@2193
  2954
			jit_float_table[i].found = true;
dvander@2193
  2955
			jit_float_table[i].index = OP_RND_TO_ZERO;
ds@1952
  2956
		} else if (!strcmp(name, "RoundToCeil")) {
dvander@2193
  2957
			jit_float_table[i].found = true;
dvander@2193
  2958
			jit_float_table[i].index = OP_RND_TO_CEIL;
ds@1952
  2959
		} else if (!strcmp(name, "RoundToFloor")) {
dvander@2193
  2960
			jit_float_table[i].found = true;
dvander@2193
  2961
			jit_float_table[i].index = OP_RND_TO_FLOOR;
ds@1952
  2962
		} else if (!strcmp(name, "RoundToNearest")) {
dvander@2193
  2963
			jit_float_table[i].found = true;
dvander@2193
  2964
			jit_float_table[i].index = OP_RND_TO_NEAREST;
ds@1952
  2965
		}
ds@1952
  2966
	}
dvander@2193
  2967
}
dvander@2193
  2968
dvander@2193
  2969
ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
dvander@2193
  2970
{
dvander@2193
  2971
	CompData *data = new CompData;
dvander@2193
  2972
dvander@2193
  2973
	data->SetRuntime(runtime);
ds@1952
  2974
ds@1952
  2975
	return data;
ds@1952
  2976
}
ds@1952
  2977
dvander@2193
  2978
void CompData::Abort()
ds@1952
  2979
{
dvander@2193
  2980
	if (rebase)
ds@1952
  2981
	{
dvander@2193
  2982
		engine->BaseFree(rebase);
ds@1952
  2983
	}
dvander@2193
  2984
	delete [] jit_float_table;
dvander@2193
  2985
	delete this;
dvander@2193
  2986
}
dvander@2193
  2987
dvander@2193
  2988
void JITX86::FreeContextVars(sp_context_t *ctx)
dvander@2193
  2989
{
dvander@2193
  2990
	free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
dvander@2193
  2991
	delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
ds@1952
  2992
}
ds@1952
  2993
dvander@2193
  2994
void JITX86::FreePluginVars(sp_plugin_t *pl)
ds@1952
  2995
{
dvander@2193
  2996
	delete [] pl->files;
dvander@2193
  2997
	delete [] pl->lines;
dvander@2193
  2998
	delete [] pl->natives;
dvander@2193
  2999
	delete [] pl->publics;
dvander@2193
  3000
	delete [] pl->pubvars;
dvander@2193
  3001
	delete [] pl->symbols;
dvander@2193
  3002
dvander@2193
  3003
	if (pl->codebase != NULL)
dvander@2193
  3004
	{
dvander@2193
  3005
		g_engine1.FreePageMemory(pl->codebase);
dvander@2193
  3006
		pl->codebase = NULL;
dvander@2193
  3007
	}
dvander@2193
  3008
dvander@2193
  3009
	pl->files = NULL;
dvander@2193
  3010
	pl->lines = NULL;
dvander@2193
  3011
	pl->natives = NULL;
dvander@2193
  3012
	pl->publics = NULL;
dvander@2193
  3013
	pl->pubvars = NULL;
dvander@2193
  3014
	pl->symbols = NULL;
dvander@2193
  3015
}
dvander@2193
  3016
dvander@2193
  3017
bool CompData::SetOption(const char *key, const char *val)
dvander@2193
  3018
{
ds@1952
  3019
	if (strcmp(key, SP_JITCONF_DEBUG) == 0)
ds@1952
  3020
	{
ds@1952
  3021
		if ((atoi(val) == 1) || !strcmp(val, "yes"))
ds@1952
  3022
		{
dvander@2193
  3023
			debug = true;
ds@1952
  3024
		} else {
dvander@2193
  3025
			debug = false;
ds@1952
  3026
		}
dvander@2193
  3027
		if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
ds@1952
  3028
		{
dvander@2193
  3029
			debug = false;
ds@1952
  3030
			return false;
ds@1952
  3031
		}
ds@1952
  3032
		return true;
ds@1952
  3033
	}
ds@1952
  3034
	else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
ds@1952
  3035
	{
dvander@2193
  3036
		profile = atoi(val);
ds@1952
  3037
ds@1952
  3038
		/** Callbacks must be profiled to profile functions! */
dvander@2193
  3039
		if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
ds@1952
  3040
		{
dvander@2193
  3041
			profile |= SP_PROF_CALLBACKS;
ds@1952
  3042
		}
ds@1952
  3043
ds@1952
  3044
		return true;
ds@1952
  3045
	}
ds@1952
  3046
ds@1952
  3047
	return false;
ds@1952
  3048
}
ds@1952
  3049