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