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