2006-09-20 02:41:24 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2006-09-23 06:11:01 +02:00
|
|
|
#include <assert.h>
|
2006-09-20 02:41:24 +02:00
|
|
|
#include "jit_x86.h"
|
2006-09-20 04:56:20 +02:00
|
|
|
#include "opcode_helpers.h"
|
|
|
|
#include "x86_macros.h"
|
2006-09-20 02:41:24 +02:00
|
|
|
|
2006-09-20 04:56:20 +02:00
|
|
|
inline void WriteOp_Move_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, edx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Move_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, eax
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Xchg(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xchg eax, edx
|
|
|
|
IA32_Xchg_Eax_Reg(jit, AMX_REG_ALT);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//push stack, DAT offset based
|
|
|
|
//sub ebp, 4
|
|
|
|
//mov ecx, [edi+<val>]
|
|
|
|
//mov [ebp], ecx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
//optimize encoding a bit...
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
|
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Push_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//push stack
|
|
|
|
//mov [ebp-4], <val>
|
|
|
|
//sub ebp, 4
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, val, -4);
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Zero(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [edi+<val>], 0
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, 0, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, 0, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Zero_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebx+<val>], 0
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, 0, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, 0, val);
|
|
|
|
}
|
|
|
|
|
2006-09-20 04:56:20 +02:00
|
|
|
inline void WriteOp_Push_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//push stack, FRM offset based
|
|
|
|
//sub ebp, 4
|
|
|
|
//mov ecx, [ebx+<val>]
|
|
|
|
//mov [ebp], ecx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
//optimize encoding a bit...
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
|
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Push_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebp-4], eax
|
|
|
|
//sub ebp, 4
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_PRI, -4);
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebp-4], edx
|
|
|
|
//sub ebp, 4
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_ALT, -4);
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push2_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_C(jit, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push3_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_C(jit, 3);
|
|
|
|
}
|
|
|
|
|
2006-09-20 04:56:20 +02:00
|
|
|
inline void WriteOp_Push4_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_C(jit, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push5_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_C(jit, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push2_Adr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_Addr(jit, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push3_Adr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_Addr(jit, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push4_Adr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_Addr(jit, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push5_Adr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_Addr(jit, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push2_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_S(jit, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push3_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_S(jit, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push4_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_S(jit, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push5_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN_S(jit, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push5(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN(jit, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push4(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN(jit, 4);
|
|
|
|
}
|
2006-09-20 03:59:56 +02:00
|
|
|
|
2006-09-20 04:56:20 +02:00
|
|
|
inline void WriteOp_Push3(JitWriter *jit)
|
2006-09-20 03:59:56 +02:00
|
|
|
{
|
2006-09-20 04:56:20 +02:00
|
|
|
Macro_PushN(jit, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push2(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Macro_PushN(jit, 2);
|
2006-09-20 03:59:56 +02:00
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Zero_Pri(JitWriter *jit)
|
2006-09-20 03:59:56 +02:00
|
|
|
{
|
2006-09-20 05:56:24 +02:00
|
|
|
//xor eax, eax
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
2006-09-20 03:59:56 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Zero_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xor edx, edx
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
2006-09-20 03:59:56 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Add(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add eax, edx
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
2006-09-20 03:59:56 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Sub(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub eax, edx
|
|
|
|
IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
2006-09-20 04:56:20 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Sub_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//neg eax
|
|
|
|
//add eax, edx
|
|
|
|
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
2006-09-20 04:56:20 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Proc(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//push old frame on stack:
|
|
|
|
//sub ebp, 4
|
2006-09-20 06:52:13 +02:00
|
|
|
//mov ecx, [frm]
|
2006-09-20 05:56:24 +02:00
|
|
|
//mov [ebp], ecx
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_STK, AMX_REG_TMP, MOD_MEM_REG);
|
|
|
|
//save frame:
|
2006-09-20 06:52:13 +02:00
|
|
|
//mov [frm], ebp - get new frame
|
|
|
|
//mov ebx, ebp - store frame back
|
|
|
|
//sub [frm], edi - relocate local frame
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_STK, MOD_MEM_REG);
|
2006-09-20 05:56:24 +02:00
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
|
|
|
|
IA32_Sub_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_DAT, MOD_MEM_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shl(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//shl eax, cl
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Shl_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//shr eax, cl
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Shr_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sshr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//sar eax, cl
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Sar_Rm_CL(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shl_C_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shl eax, <val>
|
|
|
|
jit_uint8_t val = (jit_uint8_t)jit->read_cell();
|
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shl_C_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shl edx, <val>
|
|
|
|
jit_uint8_t val = (jit_uint8_t)jit->read_cell();
|
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shr_C_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shr eax, <val>
|
|
|
|
jit_uint8_t val = (jit_uint8_t)jit->read_cell();
|
|
|
|
IA32_Shr_Rm_Imm8(jit, AMX_REG_PRI, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Shr_C_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shr edx, <val>
|
|
|
|
jit_uint8_t val = (jit_uint8_t)jit->read_cell();
|
|
|
|
IA32_Shr_Rm_Imm8(jit, AMX_REG_ALT, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_SMul(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//imul edx
|
|
|
|
//mov edx, ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_IMul_Rm(jit, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_UMul(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//mul edx
|
|
|
|
//mov edx, ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mul_Rm(jit, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Not(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//test eax, eax
|
|
|
|
//mov eax, 0
|
|
|
|
//sete al
|
|
|
|
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Neg(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//neg eax
|
|
|
|
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Xor(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xor eax, edx
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Or(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//or eax, edx
|
|
|
|
IA32_Or_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_And(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//and eax, edx
|
|
|
|
IA32_And_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Invert(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//not eax
|
|
|
|
IA32_Not_Rm(jit, AMX_REG_PRI, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Add_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add eax, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Add_Eax_Imm32(jit, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_SMul_C(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//imul eax, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_IMul_Reg_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_IMul_Reg_Imm32(jit, AMX_REG_PRI, MOD_REG, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sign_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shl eax, 24
|
|
|
|
//sar eax, 24
|
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
|
|
|
|
IA32_Sar_Rm_Imm8(jit, AMX_REG_PRI, 24, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sign_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shl edx, 24
|
|
|
|
//sar edx, 24
|
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
|
|
|
|
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 24, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Eq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI == ALT ?
|
|
|
|
//mov eax, 0
|
|
|
|
//sete al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Neq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI != ALT ?
|
|
|
|
//mov eax, 0
|
|
|
|
//setne al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_NE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Less(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI < ALT ? (unsigned)
|
|
|
|
//mov eax, 0
|
|
|
|
//setb al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_B);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Leq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI <= ALT ? (unsigned)
|
|
|
|
//mov eax, 0
|
|
|
|
//setbe al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_BE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Grtr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI > ALT ? (unsigned)
|
|
|
|
//mov eax, 0
|
|
|
|
//seta al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_A);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Geq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI >= ALT ? (unsigned)
|
|
|
|
//mov eax, 0
|
|
|
|
//setae al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_AE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sless(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI < ALT ? (signed)
|
|
|
|
//mov eax, 0
|
|
|
|
//setl al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_L);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sleq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI <= ALT ? (signed)
|
|
|
|
//mov eax, 0
|
|
|
|
//setle al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_LE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sgrtr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI > ALT ? (signed)
|
|
|
|
//mov eax, 0
|
|
|
|
//setg al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_G);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sgeq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx ; PRI >= ALT ? (signed)
|
|
|
|
//mov eax, 0
|
|
|
|
//setge al
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_GE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Eq_C_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, <val> ; PRI == value ?
|
|
|
|
//mov eax, 0
|
|
|
|
//sete al
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_PRI, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Cmp_Eax_Imm32(jit, val);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Eq_C_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xor eax, eax
|
|
|
|
//cmp edx, <val> ; ALT == value ?
|
|
|
|
//sete al
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Cmp_Rm_Imm8(jit, MOD_REG, AMX_REG_ALT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_ALT, val);
|
|
|
|
IA32_SetCC_Rm8(jit, AMX_REG_PRI, CC_E);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Inc_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add eax, 1
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Inc_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add edx, 1
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Inc(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add [edi+<val>], 1
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Inc_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add [ebx+<val>], 1
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Inc_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add [edi+eax], 1
|
|
|
|
IA32_Add_Rm_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Dec_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub eax, 1
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_PRI, 1, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Dec_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub edx, 1
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_ALT, 1, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Dec(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub [edi+<val>], 1
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_DAT, 1, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_DAT, 1, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Dec_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub [ebx+<val>], 1
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_FRM, 1, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Sub_Rm_Imm8_Disp32(jit, AMX_REG_FRM, 1, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Dec_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//sub [edi+eax], 1
|
|
|
|
IA32_Sub_Rm_Imm8_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_PRI, NOSCALE, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Load_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [edi+<val>]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Load_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, [edi+<val>]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Load_S_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [ebx+<val>]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Load_S_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, [ebx+<val>]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lref_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [edi+<val>]
|
|
|
|
//mov eax, [edi+eax]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_DAT, val);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lref_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, [edi+<val>]
|
|
|
|
//mov edx, [edi+edx]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_DAT, val);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lref_S_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [ebx+<val>]
|
|
|
|
//mov eax, [edi+eax]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_PRI, AMX_REG_FRM, val);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lref_S_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, [ebx+<val>]
|
|
|
|
//mov edx, [edi+edx]
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_ALT, AMX_REG_FRM, val);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Const_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Const_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_ALT, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Addr_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, frm
|
|
|
|
//add eax, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_INFO_FRM, MOD_MEM_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_PRI, (jit_int8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Add_Eax_Imm32(jit, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Addr_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, frm
|
|
|
|
//add edx, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_INFO_FRM, MOD_MEM_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_ALT, (jit_int8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm32(jit, AMX_REG_ALT, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Stor_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [edi+<val>], eax
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_PRI, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_PRI, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Stor_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [edi+<val>], edx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_DAT, AMX_REG_ALT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_DAT, AMX_REG_ALT, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Stor_S_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebx+<val>], eax
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_PRI, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_PRI, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Stor_S_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebx+<val>], edx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_FRM, AMX_REG_ALT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Rm_Reg_Disp32(jit, AMX_REG_FRM, AMX_REG_ALT, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Idxaddr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//lea eax, [edx+4*eax]
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
|
|
|
|
}
|
|
|
|
|
2006-09-20 17:51:05 +02:00
|
|
|
inline void WriteOp_Idxaddr_B(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//shl eax, <val>
|
|
|
|
//add eax, edx
|
2006-09-20 20:19:31 +02:00
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
|
2006-09-20 17:51:05 +02:00
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Sref_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, [edi+<val>]
|
|
|
|
//mov [edi+ecx], eax
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sref_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, [edi+<val>]
|
|
|
|
//mov [edi+ecx], edx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val);
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sref_S_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, [ebx+<val>]
|
|
|
|
//mov [edi+ecx], eax
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_PRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Sref_S_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, [ebx+<val>]
|
|
|
|
//mov [edi+ecx], edx
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val);
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, AMX_REG_ALT);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Align_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xor eax, <cellsize - val>
|
|
|
|
cell_t val = sizeof(cell_t) - jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Xor_Rm_Imm8(jit, AMX_REG_PRI, MOD_REG, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Xor_Eax_Imm32(jit, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Align_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//xor edx, <cellsize - val>
|
|
|
|
cell_t val = sizeof(cell_t) - jit->read_cell();
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Xor_Rm_Imm8(jit, AMX_REG_ALT, MOD_REG, (jit_int8_t)val);
|
|
|
|
else
|
|
|
|
IA32_Xor_Rm_Imm32(jit, AMX_REG_ALT, MOD_REG, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Pop_Pri(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [ebp]
|
|
|
|
//add ebp, 4
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Pop_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, [ebp]
|
|
|
|
//add ebp, 4
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Swap_Pri(JitWriter *jit)
|
|
|
|
{
|
2006-09-20 20:19:31 +02:00
|
|
|
//add [ebp], eax
|
|
|
|
//sub eax, [ebp]
|
|
|
|
//add [ebp], eax
|
|
|
|
//neg eax
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
|
|
|
|
IA32_Sub_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_PRI, MOD_MEM_REG);
|
|
|
|
IA32_Neg_Rm(jit, AMX_REG_PRI, MOD_REG);
|
2006-09-20 05:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Swap_Alt(JitWriter *jit)
|
|
|
|
{
|
2006-09-20 20:19:31 +02:00
|
|
|
//add [ebp], edx
|
|
|
|
//sub edx, [ebp]
|
|
|
|
//add [ebp], edx
|
|
|
|
//neg edx
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
|
|
|
|
IA32_Sub_Reg_Rm(jit, AMX_REG_ALT, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_ALT, MOD_MEM_REG);
|
|
|
|
IA32_Neg_Rm(jit, AMX_REG_ALT, MOD_REG);
|
2006-09-20 05:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_PushAddr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, frm ;get address (offset from frame)
|
|
|
|
//add ecx, <val>
|
|
|
|
//mov [ebp-4], ecx
|
|
|
|
//sub ebp, 4
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_MEM_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_TMP, (jit_int8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm32(jit, AMX_REG_TMP, val, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4);
|
|
|
|
IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Movs(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cld
|
|
|
|
//push esi
|
|
|
|
//lea esi, [edi+eax]
|
|
|
|
//add edi, edx
|
|
|
|
//if dword:
|
|
|
|
// mov ecx, dword
|
|
|
|
// rep movsd
|
|
|
|
//if byte:
|
|
|
|
// mov ecx, byte
|
|
|
|
// rep movsb
|
|
|
|
//sub edi, edx
|
|
|
|
//sub edi, <val>
|
|
|
|
//pop esi
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
unsigned int dwords = val >> 2;
|
|
|
|
unsigned int bytes = val & 0x3;
|
|
|
|
|
|
|
|
IA32_Cld(jit);
|
|
|
|
IA32_Push_Reg(jit, REG_ESI);
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, REG_ESI, REG_EDI, AMX_REG_PRI, NOSCALE);
|
|
|
|
IA32_Add_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG);
|
|
|
|
if (dwords)
|
|
|
|
{
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, dwords);
|
|
|
|
IA32_Rep(jit);
|
|
|
|
IA32_Movsd(jit);
|
|
|
|
}
|
|
|
|
if (bytes)
|
|
|
|
{
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, bytes);
|
|
|
|
IA32_Rep(jit);
|
|
|
|
IA32_Movsb(jit);
|
|
|
|
}
|
|
|
|
IA32_Sub_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Sub_Rm_Imm8(jit, REG_EDI, (jit_uint8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Sub_Rm_Imm32(jit, REG_EDI, val, MOD_REG);
|
|
|
|
IA32_Pop_Reg(jit, REG_ESI);
|
|
|
|
}
|
|
|
|
|
2006-09-21 04:58:59 +02:00
|
|
|
inline void WriteOp_Cmps(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//push edi
|
|
|
|
//push esi
|
|
|
|
//lea esi, [edi+edx]
|
|
|
|
//lea edi, [edi+eax]
|
|
|
|
IA32_Push_Reg(jit, REG_EDI);
|
|
|
|
IA32_Push_Reg(jit, REG_ESI);
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, REG_ESI, AMX_REG_DAT, AMX_REG_ALT, NOSCALE);
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, REG_EDI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
|
|
|
|
//xor eax, eax
|
|
|
|
//repe cmpsb
|
|
|
|
//je :cmps1
|
|
|
|
IA32_Xor_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
|
|
|
|
IA32_Cmpsb(jit);
|
|
|
|
jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_E, 0);
|
|
|
|
|
|
|
|
//sbb eax, eax
|
|
|
|
//sbb eax, -1
|
|
|
|
IA32_Sbb_Rm_Reg(jit, REG_EAX, REG_EAX, MOD_REG);
|
2006-09-22 23:38:58 +02:00
|
|
|
IA32_Sbb_Eax_Imm32(jit, -1);//:TODO: use imm8 here
|
2006-09-21 04:58:59 +02:00
|
|
|
|
|
|
|
//:cmps1
|
|
|
|
//pop esi
|
|
|
|
//pop edi
|
|
|
|
IA32_Send_Jump8_Here(jit, jmp);
|
|
|
|
IA32_Pop_Reg(jit, REG_ESI);
|
|
|
|
IA32_Pop_Reg(jit, REG_EDI);
|
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
inline void WriteOp_Fill(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//add edi, edx
|
|
|
|
//mov ecx, <val> >> 2
|
|
|
|
//cld
|
|
|
|
//rep stosd
|
|
|
|
//sub edi, edx
|
|
|
|
//sub edi, <val> >> 2
|
|
|
|
unsigned int val = jit->read_cell() >> 2;
|
|
|
|
|
|
|
|
IA32_Add_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, val);
|
|
|
|
IA32_Cld(jit);
|
|
|
|
IA32_Rep(jit);
|
|
|
|
IA32_Stosd(jit);
|
|
|
|
IA32_Sub_Rm_Reg(jit, REG_EDI, AMX_REG_ALT, MOD_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Sub_Rm_Imm8(jit, REG_EDI, (jit_uint8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Sub_Rm_Imm32(jit, REG_EDI, val, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Heap_Pri(JitWriter *jit)
|
|
|
|
{
|
2006-09-20 06:52:13 +02:00
|
|
|
//mov edx, [hea]
|
|
|
|
//add [hea], eax
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_REG_INFO, AMX_INFO_HEAP);
|
|
|
|
IA32_Add_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_PRI, AMX_INFO_HEAP);
|
2006-09-21 01:33:40 +02:00
|
|
|
|
|
|
|
Write_CheckMargin_Heap(jit);
|
2006-09-20 05:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Push_Heap_C(JitWriter *jit)
|
|
|
|
{
|
2006-09-20 06:52:13 +02:00
|
|
|
//mov ecx, [hea]
|
2006-09-20 05:56:24 +02:00
|
|
|
//mov [edi+ecx], <val>
|
2006-09-20 06:52:13 +02:00
|
|
|
//add [hea], 4
|
2006-09-20 05:56:24 +02:00
|
|
|
cell_t val = jit->read_cell();
|
2006-09-20 06:52:13 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
2006-09-20 05:56:24 +02:00
|
|
|
IA32_Mov_Rm_Imm32_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, val);
|
2006-09-20 06:52:13 +02:00
|
|
|
IA32_Add_Rm_Imm8_Disp8(jit, AMX_REG_INFO, 4, AMX_INFO_HEAP);
|
2006-09-21 01:33:40 +02:00
|
|
|
|
|
|
|
Write_CheckMargin_Heap(jit);
|
2006-09-20 05:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Pop_Heap_Pri(JitWriter *jit)
|
|
|
|
{
|
2006-09-20 06:52:13 +02:00
|
|
|
//sub [hea], 4
|
2006-09-20 05:56:24 +02:00
|
|
|
//mov ecx, [hea]
|
|
|
|
//mov eax, [edi+ecx]
|
2006-09-20 06:52:13 +02:00
|
|
|
IA32_Sub_Rm_Imm8_Disp8(jit, AMX_REG_INFO, 4, AMX_INFO_HEAP);
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP);
|
2006-09-20 05:56:24 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_TMP, NOSCALE);
|
2006-09-21 01:33:40 +02:00
|
|
|
|
|
|
|
Write_CheckMargin_Heap(jit);
|
2006-09-20 05:56:24 +02:00
|
|
|
}
|
|
|
|
|
2006-09-20 06:14:53 +02:00
|
|
|
inline void WriteOp_Load_Both(JitWriter *jit)
|
|
|
|
{
|
|
|
|
WriteOp_Const_Pri(jit);
|
|
|
|
WriteOp_Const_Alt(jit);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Load_S_Both(JitWriter *jit)
|
|
|
|
{
|
|
|
|
WriteOp_Load_S_Pri(jit);
|
|
|
|
WriteOp_Load_S_Alt(jit);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Const(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [edi+<addr>], <val>
|
|
|
|
cell_t addr = jit->read_cell();
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
if (addr < SCHAR_MAX && addr > SCHAR_MIN)
|
|
|
|
{
|
|
|
|
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_DAT, val, (jit_int8_t)addr);
|
|
|
|
} else {
|
|
|
|
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_DAT, val, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Const_S(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [ebx+<offs>], <val>
|
|
|
|
cell_t offs = jit->read_cell();
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
|
|
|
|
if (offs < SCHAR_MAX && offs > SCHAR_MIN)
|
|
|
|
{
|
|
|
|
IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_FRM, val, (jit_int8_t)offs);
|
|
|
|
} else {
|
|
|
|
IA32_Mov_Rm_Imm32_Disp32(jit, AMX_REG_FRM, val, offs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-20 10:44:21 +02:00
|
|
|
inline void WriteOp_Load_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov eax, [edi+eax]
|
2006-09-20 17:51:05 +02:00
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lodb_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
|
|
|
|
|
|
|
|
//mov eax, [edi+eax]
|
2006-09-20 10:44:21 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
2006-09-20 17:51:05 +02:00
|
|
|
|
|
|
|
//and eax, <bitmask>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
switch(val)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
{
|
2006-09-22 23:38:58 +02:00
|
|
|
IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x000000FF);//:TODO: replace with AND EAX, imm32
|
2006-09-20 17:51:05 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{
|
2006-09-22 23:38:58 +02:00
|
|
|
IA32_And_Rm_Imm32(jit, AMX_REG_PRI, 0x0000FFFF);//:TODO: replace with AND EAX, imm32
|
2006-09-20 17:51:05 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-09-20 10:44:21 +02:00
|
|
|
}
|
|
|
|
|
2006-09-20 17:51:05 +02:00
|
|
|
inline void WriteOp_Stor_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov [edi+edx], eax
|
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_ALT, false);
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Strb_I(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_ALT, false);
|
|
|
|
//mov [edi+edx], eax
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
IA32_Mov_Rm8_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
IA32_Mov_Rm16_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
|
|
|
|
break;
|
|
|
|
}
|
2006-09-22 23:38:58 +02:00
|
|
|
case 4:
|
2006-09-20 17:51:05 +02:00
|
|
|
{
|
|
|
|
IA32_Mov_Rm_Reg_Disp_Reg(jit, AMX_REG_DAT, AMX_REG_ALT, NOSCALE, AMX_REG_PRI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lidx(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//lea eax, [edx+4*eax]
|
|
|
|
//mov eax, [edi+eax]
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_PRI, AMX_REG_ALT, AMX_REG_PRI, SCALE4);
|
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Lidx_B(JitWriter *jit)
|
|
|
|
{
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
//shl eax, <val>
|
|
|
|
//add eax, edx
|
|
|
|
//mov eax, [edi+eax]
|
2006-09-20 20:19:31 +02:00
|
|
|
IA32_Shl_Rm_Imm8(jit, AMX_REG_PRI, (jit_uint8_t)val, MOD_REG);
|
2006-09-20 17:51:05 +02:00
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
Write_Check_VerifyAddr(jit, AMX_REG_PRI, false);
|
|
|
|
IA32_Mov_Reg_Rm_Disp_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
}
|
2006-09-20 06:14:53 +02:00
|
|
|
|
2006-09-20 22:11:02 +02:00
|
|
|
inline void WriteOp_Lctrl(JitWriter *jit)
|
|
|
|
{
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
//mov ecx, [esi+ctx]
|
|
|
|
//mov eax, [ecx+<offs>]
|
2006-09-22 13:52:48 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, base));
|
2006-09-20 22:11:02 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
//mov eax, edi
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
//mov eax, [esi+hea]
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_HEAP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
//mov ecx, [esi+ctx]
|
|
|
|
//mov eax, [ecx+ctx.memory]
|
2006-09-22 13:52:48 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_TMP, offsetof(sp_context_t, memory));
|
2006-09-20 22:11:02 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
//mov eax, ebp
|
|
|
|
//sub eax, edi - unrelocate
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_REG);
|
|
|
|
IA32_Sub_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_DAT, MOD_REG);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 5:
|
|
|
|
{
|
|
|
|
//mov eax, [esi+frm]
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, AMX_REG_INFO, AMX_INFO_FRM);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 6:
|
|
|
|
{
|
|
|
|
//mov eax, [cip]
|
|
|
|
jitoffs_t imm32 = IA32_Mov_Reg_Imm32(jit, AMX_REG_PRI, 0);
|
|
|
|
jitoffs_t save = jit->jit_curpos();
|
|
|
|
jit->setpos(imm32);
|
|
|
|
jit->write_int32((uint32_t)(jit->outbase + save));
|
|
|
|
jit->setpos(save);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-20 22:29:28 +02:00
|
|
|
inline void WriteOp_Sctrl(JitWriter *jit)
|
|
|
|
{
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
switch (val)
|
|
|
|
{
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
//mov [esi+hea], eax
|
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, AMX_REG_PRI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
//lea ebp, [edi+eax]
|
|
|
|
IA32_Lea_Reg_DispRegMult(jit, AMX_REG_STK, AMX_REG_DAT, AMX_REG_PRI, NOSCALE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 5:
|
|
|
|
{
|
|
|
|
//mov ebx, eax - overwrite frm
|
|
|
|
//mov frm, eax - overwrite stacked frame
|
2006-09-22 23:38:58 +02:00
|
|
|
//add ebx, edi - relocate local frm //:TODO: use LEA here!!!
|
2006-09-20 22:29:28 +02:00
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_INFO_FRM, AMX_REG_PRI, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 6:
|
|
|
|
{
|
|
|
|
IA32_Jump_Reg(jit, AMX_REG_PRI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-20 23:23:48 +02:00
|
|
|
inline void WriteOp_Stack(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, ebp
|
|
|
|
//add ebp, <val>
|
|
|
|
//sub edx, edi
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_STK, MOD_REG);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, (jit_int8_t)val, MOD_REG);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm32(jit, AMX_REG_STK, val, MOD_REG);
|
|
|
|
IA32_Sub_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_DAT, MOD_REG);
|
|
|
|
|
|
|
|
Write_CheckMargin_Stack(jit);
|
|
|
|
}
|
|
|
|
|
2006-09-21 01:33:40 +02:00
|
|
|
inline void WriteOp_Heap(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov edx, hea
|
|
|
|
//add hea, <val>
|
|
|
|
cell_t val = jit->read_cell();
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, AMX_INFO_FRM, AMX_INFO_HEAP);
|
|
|
|
if (val < SCHAR_MAX && val > SCHAR_MIN)
|
|
|
|
IA32_Add_Rm_Imm8_Disp8(jit, AMX_INFO_FRM, (jit_int8_t)val, AMX_INFO_HEAP);
|
|
|
|
else
|
|
|
|
IA32_Add_Rm_Imm32_Disp8(jit, AMX_INFO_FRM, val, AMX_INFO_HEAP);
|
|
|
|
|
|
|
|
Write_CheckMargin_Heap(jit);
|
|
|
|
}
|
|
|
|
|
2006-09-21 00:17:52 +02:00
|
|
|
inline void WriteOp_SDiv(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//mov edx, eax
|
|
|
|
//sar edx, 31
|
|
|
|
//idiv ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
|
2006-09-22 13:52:48 +02:00
|
|
|
Write_Check_DivZero(jit, AMX_REG_TMP);
|
2006-09-21 00:17:52 +02:00
|
|
|
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_SDiv_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, eax
|
|
|
|
//mov eax, edx
|
|
|
|
//sar edx, 31
|
|
|
|
//idiv ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Sar_Rm_Imm8(jit, AMX_REG_ALT, 31, MOD_REG);
|
2006-09-22 13:52:48 +02:00
|
|
|
Write_Check_DivZero(jit, AMX_REG_TMP);
|
2006-09-21 00:17:52 +02:00
|
|
|
IA32_IDiv_Rm(jit, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_UDiv(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, edx
|
|
|
|
//xor edx, edx
|
|
|
|
//div ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
|
2006-09-22 13:52:48 +02:00
|
|
|
Write_Check_DivZero(jit, AMX_REG_TMP);
|
2006-09-21 00:17:52 +02:00
|
|
|
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_UDiv_Alt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, eax
|
|
|
|
//mov eax, edx
|
|
|
|
//xor edx, edx
|
|
|
|
//div ecx
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Xor_Rm_Reg(jit, AMX_REG_ALT, AMX_REG_ALT, MOD_REG);
|
2006-09-22 13:52:48 +02:00
|
|
|
Write_Check_DivZero(jit, AMX_REG_TMP);
|
2006-09-21 00:17:52 +02:00
|
|
|
IA32_Div_Rm(jit, AMX_REG_TMP, MOD_REG);
|
|
|
|
}
|
|
|
|
|
2006-09-21 03:48:19 +02:00
|
|
|
inline void WriteOp_Ret(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ebx, [ebp] - get old FRM
|
|
|
|
//add ebp, 4 - pop stack
|
|
|
|
//mov [esi+frm], ebx - restore
|
|
|
|
//add ebx, edi - relocate
|
|
|
|
//ret
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
2006-09-22 23:38:58 +02:00
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong!
|
2006-09-21 03:48:19 +02:00
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
|
|
|
|
IA32_Return(jit);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Retn(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ebx, [ebp] - get old frm
|
|
|
|
//mov ecx, [ebp+4] - get return eip
|
|
|
|
//add ebp, 8 - pop stack
|
|
|
|
//mov [esi+frm], ebx - restore frame pointer
|
|
|
|
//add ebx, edi - relocate
|
|
|
|
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_STK, 4);
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 8, MOD_REG);
|
2006-09-22 23:38:58 +02:00
|
|
|
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, AMX_REG_FRM, AMX_INFO_FRM);//:TODO: this is wrong!
|
2006-09-21 03:48:19 +02:00
|
|
|
IA32_Add_Rm_Reg(jit, AMX_REG_FRM, AMX_REG_DAT, MOD_REG);
|
|
|
|
|
|
|
|
//add ebp, [ebp] - reduce by this # of params
|
|
|
|
//add ebp, 4 - pop one extra for the # itself
|
|
|
|
IA32_Add_Reg_Rm(jit, AMX_REG_STK, AMX_REG_STK, MOD_MEM_REG);
|
|
|
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
|
|
|
|
|
|
|
//jmp ecx - jump to return eip
|
|
|
|
IA32_Jump_Reg(jit, AMX_REG_TMP);
|
|
|
|
}
|
|
|
|
|
2006-09-21 04:58:59 +02:00
|
|
|
inline void WriteOp_Bounds(JitWriter *jit)
|
|
|
|
{
|
|
|
|
Write_BoundsCheck(jit);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Halt(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//mov ecx, [esi+ret]
|
|
|
|
//mov [ecx], eax
|
|
|
|
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_RETVAL);
|
|
|
|
IA32_Mov_Rm_Reg(jit, AMX_REG_TMP, AMX_REG_PRI, MOD_MEM_REG);
|
|
|
|
|
|
|
|
/* :TODO:
|
|
|
|
* We don't support sleeping or halting with weird values.
|
|
|
|
* So we're omitting the mov eax <val> that was here.
|
|
|
|
*/
|
|
|
|
jit->read_cell();
|
|
|
|
|
|
|
|
CompData *data = (CompData *)jit->data;
|
|
|
|
jitoffs_t reloc;
|
|
|
|
if (data->inline_level & JIT_INLINE_ERRORCHECKS)
|
|
|
|
{
|
|
|
|
reloc = IA32_Jump_Imm32(jit, 0);
|
|
|
|
} else {
|
|
|
|
reloc = IA32_Call_Imm32(jit, 0);
|
|
|
|
}
|
|
|
|
IA32_Write_Jump32(jit, reloc, data->jit_return);
|
|
|
|
}
|
|
|
|
|
2006-09-21 07:04:51 +02:00
|
|
|
inline void WriteOp_Break(JitWriter *jit)
|
|
|
|
{
|
|
|
|
CompData *data = (CompData *)jit->data;
|
|
|
|
if (data->debug)
|
|
|
|
{
|
|
|
|
//mov ecx, <cip>
|
|
|
|
jitoffs_t wr = IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, 0);
|
|
|
|
jitoffs_t save = jit->jit_curpos();
|
|
|
|
jit->setpos(wr);
|
|
|
|
jit->write_uint32((uint32_t)(jit->outbase + wr));
|
|
|
|
jit->setpos(save);
|
|
|
|
|
|
|
|
wr = IA32_Call_Imm32(jit, 0);
|
|
|
|
IA32_Write_Jump32(jit, wr, data->jit_break);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
inline void WriteOp_JRel(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//jmp <offs> ;relative jump
|
|
|
|
cell_t cip_offs = jit->read_cell();
|
|
|
|
|
|
|
|
/* Note that since code size calculation has to be done in the same
|
|
|
|
* phase as building relocation information, we cannot know the jump size
|
|
|
|
* beforehand. Thus, we always write full 32bit jumps for safety.
|
|
|
|
*/
|
|
|
|
jitoffs_t jmp = IA32_Jump_Imm32(jit, 0);
|
|
|
|
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, cip_offs));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jump(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//jmp <offs>
|
|
|
|
cell_t amx_offs = jit->read_cell();
|
|
|
|
|
|
|
|
IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, amx_offs, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jzer(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//test eax, eax
|
|
|
|
//jz <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Jump_Imm32_Abs(jit, RelocLookup(jit, target, false));
|
|
|
|
IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jnz(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//test eax, eax
|
|
|
|
//jnz <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Test_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_PRI, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jeq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//je <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32_Abs(jit, CC_E, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jneq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jne <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_NE, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jless(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jb <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_B, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jleq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jbe <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_BE, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jgrtr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//ja <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_A, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jgeq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jae <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_AE, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jsless(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jl <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_L, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_Jsleq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jle <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_LE, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_JsGrtr(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jg <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_G, RelocLookup(jit, target, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void WriteOp_JsGeq(JitWriter *jit)
|
|
|
|
{
|
|
|
|
//cmp eax, edx
|
|
|
|
//jge <target>
|
|
|
|
cell_t target = jit->read_cell();
|
|
|
|
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_ALT, MOD_REG);
|
|
|
|
IA32_Jump_Cond_Imm32(jit, CC_GE, RelocLookup(jit, target, false));
|
|
|
|
}
|
2006-09-21 04:58:59 +02:00
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
/*************************************************
|
|
|
|
*************************************************
|
|
|
|
* JIT PROPER ************************************
|
2006-09-23 06:11:01 +02:00
|
|
|
* The rest from now on is the JIT engine *
|
2006-09-20 05:56:24 +02:00
|
|
|
*************************************************
|
|
|
|
*************************************************/
|
|
|
|
|
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
|
|
|
|
{
|
|
|
|
if (jit->outptr)
|
|
|
|
{
|
|
|
|
CompData *data = (CompData *)jit->data;
|
|
|
|
if (relative)
|
|
|
|
{
|
|
|
|
/* The actual offset is EIP relative. We need to relocate it.
|
|
|
|
* Note that this assumes that we're pointing to the next op.
|
|
|
|
*/
|
|
|
|
pcode_offs += jit->inputrel();
|
|
|
|
}
|
|
|
|
/* Offset must always be 1)positive and 2)less than the codesize */
|
|
|
|
assert(pcode_offs >= 0 && (uint32_t)pcode_offs < data->codesize);
|
|
|
|
/* Do the lookup in the native dictionary. */
|
|
|
|
return *(jitoffs_t *)(data->rebase + pcode_offs);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-20 05:56:24 +02:00
|
|
|
IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
|
|
|
|
{
|
|
|
|
CompData *data = (CompData *)co;
|
|
|
|
sp_plugin_t *plugin = data->plugin;
|
|
|
|
|
|
|
|
/* The first phase is to browse */
|
|
|
|
uint8_t *code = plugin->pcode;
|
|
|
|
uint8_t *cip;
|
|
|
|
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
|
|
|
|
OPCODE op;
|
|
|
|
int op_c;
|
|
|
|
|
|
|
|
/* FIRST PASS (light load) - Get initial opcode information */
|
|
|
|
for (cip = code; cip < end_cip;)
|
|
|
|
{
|
|
|
|
op = (OPCODE)*(ucell_t *)cip;
|
|
|
|
if ((unsigned)op >= OP_NUM_OPCODES)
|
|
|
|
{
|
|
|
|
AbortCompilation(co);
|
|
|
|
*err = SP_ERR_INVALID_INSTRUCTION;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
cip += sizeof(cell_t);
|
|
|
|
op_c = OpAdvTable[op];
|
|
|
|
if (op_c >= 0)
|
|
|
|
{
|
|
|
|
cip += op_c;
|
|
|
|
} else if (op_c == -3) {
|
|
|
|
AbortCompilation(co);
|
|
|
|
*err = SP_ERR_INVALID_INSTRUCTION;
|
|
|
|
return NULL;
|
|
|
|
} else if (op_c == -2) {
|
2006-09-23 06:11:01 +02:00
|
|
|
/* :TODO: get rid of this block */
|
2006-09-20 05:56:24 +02:00
|
|
|
cip += sizeof(cell_t);
|
|
|
|
} else if (op_c == -1) {
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case OP_CASETBL:
|
|
|
|
{
|
|
|
|
ucell_t num = *(ucell_t *)cip;
|
|
|
|
cip += sizeof(cell_t);
|
|
|
|
cip += ((2*num) + 1) * sizeof(cell_t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
AbortCompilation(co);
|
|
|
|
*err = SP_ERR_INVALID_INSTRUCTION;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************
|
|
|
|
* SECOND PASS (medium load): writer.outbase is NULL, getting size only
|
|
|
|
* THIRD PASS (heavy load!!): writer.outbase is valid and output is written
|
|
|
|
*********************************************/
|
|
|
|
|
|
|
|
JitWriter writer;
|
2006-09-20 09:07:49 +02:00
|
|
|
JitWriter *jit = &writer;
|
|
|
|
cell_t *endptr = (cell_t *)(end_cip);
|
2006-09-21 01:33:40 +02:00
|
|
|
cell_t jitpos;
|
2006-09-20 05:56:24 +02:00
|
|
|
|
2006-09-20 09:07:49 +02:00
|
|
|
/* Initial code is written "blank,"
|
|
|
|
* so we can check the exact memory usage.
|
|
|
|
*/
|
2006-09-23 06:11:01 +02:00
|
|
|
data->codesize = plugin->pcode_size;
|
|
|
|
writer.inbase = (cell_t *)code;
|
2006-09-20 05:56:24 +02:00
|
|
|
writer.outptr = NULL;
|
|
|
|
writer.outbase = NULL;
|
2006-09-23 06:11:01 +02:00
|
|
|
data->rebase = (jitcode_t *)engine->BaseAlloc(plugin->pcode_size);
|
2006-09-20 05:56:24 +02:00
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
/* Jump back here for second pass */
|
|
|
|
jit_rewind:
|
2006-09-21 01:33:40 +02:00
|
|
|
/* Initialize pass vars */
|
2006-09-23 06:11:01 +02:00
|
|
|
writer.inptr = writer.inbase;
|
2006-09-21 01:33:40 +02:00
|
|
|
data->jit_chkmargin_heap = 0;
|
|
|
|
data->jit_verify_addr_eax = 0;
|
|
|
|
data->jit_verify_addr_edx = 0;
|
2006-09-21 04:58:59 +02:00
|
|
|
data->jit_bounds = 0;
|
2006-09-21 01:33:40 +02:00
|
|
|
|
2006-09-20 09:07:49 +02:00
|
|
|
/* Start writing the actual code */
|
2006-09-20 10:44:21 +02:00
|
|
|
data->jit_return = Write_Execute_Function(jit);
|
|
|
|
|
|
|
|
/* Write error checking routines in case they are needed */
|
2006-09-21 07:04:51 +02:00
|
|
|
if (!(data->inline_level & JIT_INLINE_ERRORCHECKS))
|
|
|
|
{
|
|
|
|
jitpos = jit->jit_curpos();
|
|
|
|
Write_Check_VerifyAddr(jit, REG_EAX, true);
|
|
|
|
data->jit_verify_addr_eax = jitpos;
|
|
|
|
|
|
|
|
jitpos = jit->jit_curpos();
|
|
|
|
Write_Check_VerifyAddr(jit, REG_EDX, true);
|
|
|
|
data->jit_verify_addr_edx = jitpos;
|
2006-09-21 01:33:40 +02:00
|
|
|
|
2006-09-21 07:04:51 +02:00
|
|
|
jitpos = jit->jit_curpos();
|
|
|
|
Write_CheckMargin_Heap(jit);
|
|
|
|
data->jit_chkmargin_heap = jitpos;
|
2006-09-21 01:33:40 +02:00
|
|
|
|
2006-09-21 07:04:51 +02:00
|
|
|
jitpos = jit->jit_curpos();
|
|
|
|
Write_BoundsCheck(jit);
|
|
|
|
data->jit_bounds = jitpos;
|
|
|
|
}
|
2006-09-20 09:07:49 +02:00
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
if (writer.outbase == NULL)
|
2006-09-20 05:56:24 +02:00
|
|
|
{
|
2006-09-23 06:11:01 +02:00
|
|
|
/*******
|
|
|
|
* SECOND PASS - get opcode sizes+info
|
|
|
|
*******/
|
|
|
|
jitoffs_t pcode_offs;
|
|
|
|
jitoffs_t native_offs;
|
|
|
|
|
|
|
|
for (; writer.inptr <= endptr;)
|
2006-09-20 05:56:24 +02:00
|
|
|
{
|
2006-09-23 06:11:01 +02:00
|
|
|
/* Store the native offset into the rebase memory.
|
|
|
|
* This large chunk of memory lets us do an instant lookup
|
|
|
|
* based on an original pcode offset.
|
|
|
|
*/
|
|
|
|
pcode_offs = (jitoffs_t)((uint8_t *)writer.inptr - code);
|
|
|
|
native_offs = jit->jit_curpos();
|
|
|
|
*((jitoffs_t *)(data->rebase + pcode_offs)) = native_offs;
|
|
|
|
|
|
|
|
/* Now read the opcode and continue. */
|
|
|
|
op = (OPCODE)writer.read_cell();
|
|
|
|
switch (op)
|
2006-09-21 07:04:51 +02:00
|
|
|
{
|
2006-09-23 06:11:01 +02:00
|
|
|
#include "opcode_switch.inc"
|
2006-09-21 07:04:51 +02:00
|
|
|
}
|
2006-09-23 06:11:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* the total codesize is now known! */
|
|
|
|
uint32_t mem = writer.jit_curpos();
|
|
|
|
writer.outbase = new char[mem];
|
|
|
|
writer.outptr = writer.outbase;
|
|
|
|
/* go back for third pass */
|
|
|
|
goto jit_rewind;
|
|
|
|
} else {
|
|
|
|
/*******
|
|
|
|
* THIRD PASS - write opcode info
|
|
|
|
*******/
|
|
|
|
for (; writer.inptr <= endptr;)
|
|
|
|
{
|
|
|
|
op = (OPCODE)writer.read_cell();
|
|
|
|
switch (op)
|
2006-09-20 06:14:53 +02:00
|
|
|
{
|
2006-09-23 06:11:01 +02:00
|
|
|
#include "opcode_switch.inc"
|
2006-09-20 06:14:53 +02:00
|
|
|
}
|
2006-09-20 04:56:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
sp_context_t *ctx = new sp_context_t;
|
|
|
|
memset(ctx, 0, sizeof(sp_context_t));
|
|
|
|
|
|
|
|
ctx->context = engine->CreateBaseContext(ctx);
|
|
|
|
ctx->data = new uint8_t[plugin->memory];
|
|
|
|
memcpy(ctx->data, plugin->data, plugin->data_size);
|
|
|
|
ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
|
|
|
|
ctx->heapbase = plugin->data_size;
|
|
|
|
ctx->hp = ctx->heapbase;
|
|
|
|
ctx->memory = plugin->memory;
|
|
|
|
ctx->plugin = plugin;
|
|
|
|
ctx->vmbase = this;
|
|
|
|
|
|
|
|
/* :TODO: the rest of this */
|
|
|
|
|
2006-09-20 03:59:56 +02:00
|
|
|
*err = SP_ERR_NONE;
|
|
|
|
|
2006-09-23 06:11:01 +02:00
|
|
|
return ctx->context;
|
2006-09-20 03:59:56 +02:00
|
|
|
}
|
|
|
|
|
2006-09-20 02:41:24 +02:00
|
|
|
const char *JITX86::GetVMName()
|
|
|
|
{
|
|
|
|
return "JIT (x86)";
|
|
|
|
}
|
|
|
|
|
|
|
|
ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
|
|
|
|
{
|
|
|
|
CompData *data = new CompData;
|
|
|
|
|
|
|
|
data->plugin = plugin;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JITX86::AbortCompilation(ICompilation *co)
|
|
|
|
{
|
|
|
|
delete (CompData *)co;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val)
|
|
|
|
{
|
|
|
|
CompData *data = (CompData *)co;
|
|
|
|
|
|
|
|
if (strcmp(key, "debug") == 0)
|
|
|
|
{
|
|
|
|
data->debug = (atoi(val) == 1);
|
|
|
|
if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG))
|
|
|
|
{
|
|
|
|
data->debug = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|