added cmps, bounds, halt, and other fixes/additions

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4090
This commit is contained in:
David Anderson 2006-09-21 02:58:59 +00:00
parent 2ada767528
commit 9ba07e4b28
6 changed files with 168 additions and 8 deletions

View File

@ -25,6 +25,7 @@ typedef int32_t cell_t;
#define SP_ERR_STACKMIN 13 /* Stack went beyond its minimum value */
#define SP_ERR_HEAPMIN 14 /* Heap went beyond its minimum value */
#define SP_ERR_DIVIDE_BY_ZERO 15 /* Division by zero */
#define SP_ERR_ARRAY_BOUNDS 16 /* Array index is out of bounds */
/**********************************************
*** The following structures are reference structures.

View File

@ -930,6 +930,37 @@ inline void WriteOp_Movs(JitWriter *jit)
IA32_Pop_Reg(jit, REG_ESI);
}
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);
IA32_Sbb_Eax_Imm32(jit, -1);
//:cmps1
//pop esi
//pop edi
IA32_Send_Jump8_Here(jit, jmp);
IA32_Pop_Reg(jit, REG_ESI);
IA32_Pop_Reg(jit, REG_EDI);
}
inline void WriteOp_Fill(JitWriter *jit)
{
//add edi, edx
@ -1322,6 +1353,36 @@ inline void WriteOp_Retn(JitWriter *jit)
IA32_Jump_Reg(jit, AMX_REG_TMP);
}
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);
}
/*************************************************
*************************************************
* JIT PROPER ************************************
@ -1409,6 +1470,7 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
data->jit_chkmargin_heap = 0;
data->jit_verify_addr_eax = 0;
data->jit_verify_addr_edx = 0;
data->jit_bounds = 0;
/* Start writing the actual code */
data->jit_return = Write_Execute_Function(jit);
@ -1426,8 +1488,11 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
Write_CheckMargin_Heap(jit);
data->jit_chkmargin_heap = jitpos;
/* Begin opcode browsing */
jitpos = jit->jit_curpos();
Write_BoundsCheck(jit);
data->jit_bounds = jitpos;
/* Begin opcode browsing */
for (; writer.inptr <= endptr;)
{
op = (OPCODE)writer.read_cell();
@ -2073,6 +2138,21 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
WriteOp_Retn(jit);
break;
}
case OP_CMPS:
{
WriteOp_Cmps(jit);
break;
}
case OP_BOUNDS:
{
WriteOp_Bounds(jit);
break;
}
case OP_HALT:
{
WriteOp_Halt(jit);
break;
}
default:
{
AbortCompilation(co);

View File

@ -24,6 +24,7 @@ public:
jitoffs_t jit_verify_addr_eax;
jitoffs_t jit_verify_addr_edx;
jitoffs_t jit_chkmargin_heap;
jitoffs_t jit_bounds;
int inline_level;
bool checks;
bool debug;

View File

@ -159,7 +159,7 @@ void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg)
//sub esp, 4 - correct stack for returning to non-inlined JIT
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
}
Write_Error(jit, SP_ERR_DIVZERO);
Write_Error(jit, SP_ERR_DIVIDE_BY_ZERO);
//continue:
IA32_Send_Jump8_Here(jit, jmp);
@ -227,13 +227,66 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg, bool firstcall)
}
}
void Write_BoundsCheck(JitWriter *jit)
{
CompData *data = (CompData *)jit->data;
bool always_inline = ((data->inline_level & JIT_INLINE_ERRORCHECKS) == JIT_INLINE_ERRORCHECKS);
/* :TODO: break out on high -O level? */
if (!always_inline)
{
if (data->jit_bounds)
{
/* just generate the call */
//mov ecx, <val>
//call <offs>
IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, jit->read_cell());
jitoffs_t call = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32(jit, call, data->jit_bounds);
} else {
//cmp eax, 0
//jl :err_bounds
//cmp eax, ecx
//jg :err_bounds
//ret
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_PRI, 0);
jitoffs_t jmp1 = IA32_Jump_Cond_Imm8(jit, CC_L, 0);
//:TODO: make sure this is right order
IA32_Cmp_Rm_Reg(jit, AMX_REG_PRI, AMX_REG_TMP, MOD_REG);
jitoffs_t jmp2 = IA32_Jump_Cond_Imm8(jit, CC_G, 0);
IA32_Return(jit);
IA32_Send_Jump8_Here(jit, jmp1);
IA32_Send_Jump8_Here(jit, jmp2);
Write_Error(jit, SP_ERR_ARRAY_BOUNDS);
}
} else {
//cmp eax, 0
//jl :err_bounds
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_PRI, 0);
jitoffs_t jmp1 = IA32_Jump_Cond_Imm8(jit, CC_L, 0);
//cmp eax, <val>
//jg :err_bounds
IA32_Cmp_Rm_Imm32(jit, MOD_REG, AMX_REG_PRI, jit->read_cell());
jitoffs_t jmp2 = IA32_Jump_Cond_Imm8(jit, CC_G, 0);
//jmp :continue
jitoffs_t cont = IA32_Jump_Imm8(jit, 0);
//:err_bounds
IA32_Send_Jump8_Here(jit, jmp1);
IA32_Send_Jump8_Here(jit, jmp2);
Write_Error(jit, SP_ERR_ARRAY_BOUNDS);
//:continue
IA32_Send_Jump8_Here(jit, cont);
}
}
void Write_CheckMargin_Heap(JitWriter *jit)
{
CompData *data = (CompData *)jit->data;
bool always_inline = ((data->inline_level & JIT_INLINE_ERRORCHECKS) == JIT_INLINE_ERRORCHECKS);
if (always_inline && data->jit_chkmargin_heap)
if (!always_inline && data->jit_chkmargin_heap)
{
/* just generate the call */
jitoffs_t call = IA32_Call_Imm32(jit, 0);

View File

@ -32,11 +32,16 @@ void Write_CheckMargin_Stack(JitWriter *jit);
* Verifies heap margins.
*/
void Write_CheckMargin_Heap(JitWriter *jit);
/**
* Checks for division by zero.
*/
* Checks for division by zero.
*/
void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg);
/**
* Writes a bounds check.
*/
void Write_BoundsCheck(JitWriter *jit);
/**
* These are for writing the PushN opcodes.
@ -166,10 +171,10 @@ typedef enum
OP_DEC_S, //DONE
OP_DEC_I, //DONE
OP_MOVS, //DONE
OP_CMPS,
OP_CMPS, //DONE
OP_FILL, //DONE
OP_HALT,
OP_BOUNDS,
OP_HALT, //DONE
OP_BOUNDS, //DONE
OP_SYSREQ_PRI,
OP_SYSREQ_C,
OP_FILE, //DEPRECATED

View File

@ -63,6 +63,8 @@
#define IA32_SUB_REG_RM 0x2B // encoding is /r
#define IA32_SUB_RM_IMM8 0x83 // encoding is /5 <imm8>
#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
#define IA32_SBB_RM_REG 0x19 // encoding is /r
#define IA32_SBB_EAX_IMM32 0x1D // encoding is <imm32>
#define IA32_JMP_IMM32 0xE9 // encoding is imm32
#define IA32_JMP_IMM8 0xEB // encoding is imm8
#define IA32_JMP_RM 0xFF // encoding is /4
@ -76,6 +78,7 @@
#define IA32_CMP_RM_IMM32 0x81 // encoding is /7 <imm32>
#define IA32_CMP_RM_IMM8 0x83 // encoding is /7 <imm8>
#define IA32_CMP_EAX_IMM32 0x3D // no extra encoding
#define IA32_CMPSB 0xA6 // no extra encoding
#define IA32_TEST_RM_REG 0x85 // encoding is /r
#define IA32_JCC_IMM 0x70 // encoding is +cc <imm8>
#define IA32_JCC_IMM32_1 0x0F // opcode part 1
@ -342,6 +345,12 @@ inline void IA32_Sub_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, j
jit->write_ubyte(ia32_modrm(mode, src, dest));
}
inline void IA32_Sbb_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(IA32_SBB_RM_REG);
jit->write_ubyte(ia32_modrm(mode, src, dest));
}
inline void IA32_Sub_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(IA32_SUB_REG_RM);
@ -362,6 +371,12 @@ inline void IA32_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val,
jit->write_int32(val);
}
inline void IA32_Sbb_Eax_Imm32(JitWriter *jit, jit_int32_t value)
{
jit->write_ubyte(IA32_SBB_EAX_IMM32);
jit->write_int32(value);
}
inline void IA32_Div_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode)
{
jit->write_ubyte(IA32_DIV_RM);
@ -859,6 +874,11 @@ inline void IA32_SetCC_Rm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t cond)
jit->write_ubyte(ia32_modrm(MOD_REG, 0, reg));
}
inline void IA32_Cmpsb(JitWriter *jit)
{
jit->write_ubyte(IA32_CMPSB);
}
inline void IA32_Rep(JitWriter *jit)
{
jit->write_ubyte(IA32_REP);