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