Wrote the JIT execution function
Solidified some more code --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%4079
This commit is contained in:
parent
3cdf54e7e9
commit
824beee935
@ -830,7 +830,6 @@ inline void WriteOp_Pop_Pri(JitWriter *jit)
|
||||
//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)
|
||||
@ -1049,16 +1048,6 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
|
||||
} else if (op_c == -1) {
|
||||
switch (op)
|
||||
{
|
||||
case OP_SYSREQ_C:
|
||||
case OP_SYSREQ_PRI:
|
||||
case OP_SYSREQ_N:
|
||||
{
|
||||
if (!data->always_inline)
|
||||
{
|
||||
reloc_count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_CASETBL:
|
||||
{
|
||||
ucell_t num = *(ucell_t *)cip;
|
||||
@ -1083,14 +1072,30 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
|
||||
*********************************************/
|
||||
|
||||
JitWriter writer;
|
||||
JitWriter *jit = &writer;
|
||||
cell_t *endptr = (cell_t *)(end_cip);
|
||||
jitoffs_t jit_return;
|
||||
|
||||
/* Initial code is written "blank,"
|
||||
* so we can check the exact memory usage.
|
||||
*/
|
||||
writer.inptr = (cell_t *)code;
|
||||
writer.outptr = NULL;
|
||||
writer.outbase = NULL;
|
||||
|
||||
//redo_pass:
|
||||
cell_t *endptr = (cell_t *)(end_cip);
|
||||
JitWriter *jit = &writer;
|
||||
/* Get inlining level */
|
||||
int inline_level = data->inline_level;
|
||||
bool never_inline = false;
|
||||
|
||||
if (inline_level == 0)
|
||||
{
|
||||
never_inline = true;
|
||||
}
|
||||
|
||||
//:TODO: Jump back here once finished!
|
||||
/* Start writing the actual code */
|
||||
jit_return = Write_Execute_Function(jit, never_inline);
|
||||
|
||||
for (; writer.inptr <= endptr;)
|
||||
{
|
||||
op = (OPCODE)writer.read_cell();
|
||||
|
@ -9,12 +9,12 @@ using namespace SourcePawn;
|
||||
class CompData : public ICompilation
|
||||
{
|
||||
public:
|
||||
CompData() : plugin(NULL), debug(false), always_inline(true)
|
||||
CompData() : plugin(NULL), debug(false), inline_level(2)
|
||||
{
|
||||
};
|
||||
public:
|
||||
sp_plugin_t *plugin;
|
||||
bool always_inline;
|
||||
int inline_level;
|
||||
bool debug;
|
||||
};
|
||||
|
||||
@ -43,5 +43,6 @@ public:
|
||||
#define AMX_INFO_FRM AMX_REG_INFO
|
||||
#define AMX_INFO_HEAP 4
|
||||
#define AMX_INFO_RETVAL 8
|
||||
#define AMX_INFO_CONTEXT 12
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||
|
@ -6,26 +6,129 @@
|
||||
|
||||
int OpAdvTable[OP_NUM_OPCODES];
|
||||
|
||||
void Write_Prologue(JitWriter *jit)
|
||||
jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline)
|
||||
{
|
||||
/**
|
||||
* The state expected by our plugin is:
|
||||
* #define AMX_REG_PRI REG_EAX
|
||||
#define AMX_REG_ALT REG_EDX
|
||||
#define AMX_REG_STK REG_EBP
|
||||
#define AMX_REG_DAT REG_EDI
|
||||
#define AMX_REG_TMP REG_ECX
|
||||
#define AMX_REG_INFO REG_ESI
|
||||
#define AMX_REG_FRM REG_EBX
|
||||
#define AMX_INFO_FRM AMX_REG_INFO
|
||||
#define AMX_INFO_HEAP 4
|
||||
#define AMX_INFO_RETVAL 12
|
||||
* #define AMX_REG_PRI REG_EAX (done)
|
||||
#define AMX_REG_ALT REG_EDX (done)
|
||||
#define AMX_REG_STK REG_EBP (done)
|
||||
#define AMX_REG_DAT REG_EDI (done)
|
||||
#define AMX_REG_TMP REG_ECX (nothing)
|
||||
#define AMX_REG_INFO REG_ESI (done)
|
||||
#define AMX_REG_FRM REG_EBX (done)
|
||||
#define AMX_INFO_FRM AMX_REG_INFO (done)
|
||||
#define AMX_INFO_HEAP 4 (done)
|
||||
#define AMX_INFO_RETVAL 8 (done)
|
||||
#define AMX_INFO_CONTEXT 12 (done)
|
||||
*
|
||||
* The variables we're passed in:
|
||||
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
|
||||
*/
|
||||
|
||||
/**
|
||||
* !NOTE!
|
||||
* Currently, we do not accept ctx->frm as the new frame pointer.
|
||||
* Instead, we copy the frame from the stack pointer.
|
||||
* This is because we do not support resuming or sleeping!
|
||||
*/
|
||||
|
||||
//push ebp
|
||||
//mov ebp, esp
|
||||
IA32_Push_Reg(jit, REG_EBP);
|
||||
IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
|
||||
|
||||
//push esi
|
||||
//push edi
|
||||
//push ebx
|
||||
IA32_Push_Reg(jit, REG_ESI);
|
||||
IA32_Push_Reg(jit, REG_EDI);
|
||||
IA32_Push_Reg(jit, REG_EBX);
|
||||
|
||||
//sub esp, 4*4 - allocate info array
|
||||
//mov esi, esp - save info pointer
|
||||
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_INFO, REG_ESP, MOD_REG);
|
||||
|
||||
//mov eax, [ebp+16] - get result pointer
|
||||
//mov [esi+8], eax - store into info pointer
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_EAX, AMX_INFO_RETVAL);
|
||||
|
||||
//mov eax, [ebp+8] - get context
|
||||
//mov [esi+12], eax - store context into info pointer
|
||||
//mov ecx, [eax+<offs>] - get heap pointer
|
||||
//mov [esi+4], ecx - store heap into info pointer
|
||||
//mov edi, [eax+<offs>] - get data pointer
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_EAX, AMX_INFO_CONTEXT);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
|
||||
IA32_Mov_Rm_Reg_Disp8(jit, REG_ESI, REG_ECX, AMX_INFO_HEAP);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, data));
|
||||
|
||||
//mov ebp, [eax+<offs>] - get stack pointer
|
||||
//add ebp, edi - relocate to data section
|
||||
//mov ebx, ebp - copy sp to frm
|
||||
//mov ecx, [ebp+12] - get code index
|
||||
//add ecx, [eax+<offs>] - add code base to index
|
||||
//mov edx, [eax+<offs>] - get alt
|
||||
//mov eax, [eax+<offs>] - get pri
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_STK, REG_EAX, offsetof(sp_context_t, sp));
|
||||
IA32_Add_Rm_Reg(jit, REG_EBP, AMX_REG_STK, AMX_REG_DAT);
|
||||
IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG);
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EBP, 12);
|
||||
IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, base));
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_ALT, REG_EAX, offsetof(sp_context_t, alt));
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_PRI, REG_EAX, offsetof(sp_context_t, pri));
|
||||
|
||||
/* by now, everything is set up, so we can call into the plugin */
|
||||
|
||||
//call ecx
|
||||
IA32_Call_Rm(jit, REG_ECX);
|
||||
|
||||
/* if the code flow gets to here, there was a normal return */
|
||||
//mov ebp, [esi+8] - get retval pointer
|
||||
//mov [ebp], eax - store retval from PRI
|
||||
//mov eax, SP_ERR_NONE - set no error
|
||||
IA32_Mov_Reg_Rm_Disp8(jit, REG_EBP, AMX_REG_INFO, AMX_INFO_RETVAL);
|
||||
IA32_Mov_Rm_Reg(jit, REG_EBP, AMX_REG_PRI, MOD_MEM_REG);
|
||||
IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERR_NONE);
|
||||
|
||||
/* where error checking/return functions should go to */
|
||||
jitoffs_t offs_return;
|
||||
if (never_inline)
|
||||
{
|
||||
/* We have to write code assume we're breaking out of a call */
|
||||
//jmp [past the next instruction]
|
||||
//add esp, 4
|
||||
jitoffs_t offs = IA32_Jump_Imm8(jit, 0);
|
||||
offs_return = jit->jit_curpos();
|
||||
IA32_Sub_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
|
||||
IA32_Send_Jump8_Here(jit, offs);
|
||||
} else {
|
||||
offs_return = jit->jit_curpos();
|
||||
}
|
||||
|
||||
/* _FOR NOW_ ...
|
||||
* We are _not_ going to restore anything that was on the stack.
|
||||
* This is a tiny, useless optimization based on the fact that
|
||||
* BaseContext::Execute() automatically restores our values anyway.
|
||||
*/
|
||||
|
||||
//add esp, 4*4
|
||||
//pop ebx
|
||||
//pop edi
|
||||
//pop esi
|
||||
//pop ebp
|
||||
//ret
|
||||
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*4, MOD_REG);
|
||||
IA32_Pop_Reg(jit, REG_EBX);
|
||||
IA32_Pop_Reg(jit, REG_EDI);
|
||||
IA32_Pop_Reg(jit, REG_ESI);
|
||||
IA32_Pop_Reg(jit, REG_EBP);
|
||||
IA32_Return(jit);
|
||||
|
||||
return offs_return;
|
||||
}
|
||||
|
||||
void Macro_PushN_Addr(JitWriter *jit, int i)
|
||||
@ -142,6 +245,7 @@ JITX86::JITX86()
|
||||
OpAdvTable[OP_LOAD_S_BOTH] = sizeof(cell_t)*2;
|
||||
OpAdvTable[OP_CONST] = sizeof(cell_t)*2;
|
||||
OpAdvTable[OP_CONST_S] = sizeof(cell_t)*2;
|
||||
OpAdvTable[OP_SYSREQ_N] = sizeof(cell_t)*2;
|
||||
|
||||
/* instructions with 1 parameter */
|
||||
OpAdvTable[OP_LOAD_PRI] = sizeof(cell_t);
|
||||
@ -199,6 +303,7 @@ JITX86::JITX86()
|
||||
OpAdvTable[OP_BOUNDS] = sizeof(cell_t);
|
||||
OpAdvTable[OP_PUSH_ADR] = sizeof(cell_t);
|
||||
OpAdvTable[OP_PUSH_HEAP_C] = sizeof(cell_t);
|
||||
OpAdvTable[OP_SYSREQ_C] = sizeof(cell_t);
|
||||
|
||||
/* instructions with 0 parameters */
|
||||
OpAdvTable[OP_LOAD_I] = 0;
|
||||
@ -261,6 +366,7 @@ JITX86::JITX86()
|
||||
OpAdvTable[OP_BREAK] = 0;
|
||||
OpAdvTable[OP_HEAP_PRI] = 0;
|
||||
OpAdvTable[OP_POP_HEAP_PRI] = 0;
|
||||
OpAdvTable[OP_SYSREQ_PRI] = 0;
|
||||
|
||||
/* opcodes that need relocation */
|
||||
OpAdvTable[OP_CALL] = -2;
|
||||
|
@ -3,6 +3,19 @@
|
||||
|
||||
#include "..\jit_helpers.h"
|
||||
|
||||
/**
|
||||
* This outputs the execution function for a plugin.
|
||||
* It also returns the 'return' offset, which is used for
|
||||
* breaking out of the JIT during runtime.
|
||||
*
|
||||
* If 'never_inline' is true, it outputs slightly different code used for
|
||||
* inlining the error checking routines.
|
||||
*/
|
||||
jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline);
|
||||
|
||||
/**
|
||||
* These are for writing the PushN opcodes.
|
||||
*/
|
||||
void Macro_PushN_Addr(JitWriter *jit, int i);
|
||||
void Macro_PushN_S(JitWriter *jit, int i);
|
||||
void Macro_PushN_C(JitWriter *jit, int i);
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define IA32_XOR_RM_IMM32 0x81 // encoding is /6
|
||||
#define IA32_XOR_RM_IMM8 0x83 // encoding is /6
|
||||
#define IA32_ADD_RM_REG 0x01 // encoding is /r
|
||||
#define IA32_ADD_REG_RM 0x03 // encoding is /r
|
||||
#define IA32_ADD_RM_IMM32 0x81 // encoding is /0
|
||||
#define IA32_ADD_RM_IMM8 0x83 // encoding is /0
|
||||
#define IA32_ADD_EAX_IMM32 0x05 // no extra encoding
|
||||
@ -60,7 +61,9 @@
|
||||
#define IA32_SUB_RM_IMM8 0x83 // encoding is /5 <imm8>
|
||||
#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
|
||||
#define IA32_JMP_IMM32 0xE9 // encoding is imm32
|
||||
#define IA32_JMP_IMM8 0xEB // encoding is imm8
|
||||
#define IA32_CALL_IMM32 0xE8 // relative call, <imm32>
|
||||
#define IA32_CALL_RM 0xFF // encoding is /2
|
||||
#define IA32_MOV_REG_IMM 0xB8 // encoding is +r <imm32>
|
||||
#define IA32_MOV_RM_REG 0x89 // encoding is /r
|
||||
#define IA32_MOV_REG_MEM 0x8B // encoding is /r
|
||||
@ -385,6 +388,13 @@ inline void IA32_Add_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t
|
||||
jit->write_byte(disp);
|
||||
}
|
||||
|
||||
inline void IA32_Add_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
|
||||
{
|
||||
jit->write_ubyte(IA32_ADD_REG_RM);
|
||||
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src));
|
||||
jit->write_byte(disp);
|
||||
}
|
||||
|
||||
inline void IA32_Add_Rm_Imm8_Disp8(JitWriter *jit,
|
||||
jit_uint8_t dest,
|
||||
jit_int8_t val,
|
||||
@ -652,6 +662,15 @@ inline jitoffs_t IA32_Jump_Imm32(JitWriter *jit, jit_int32_t disp)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline jitoffs_t IA32_Jump_Imm8(JitWriter *jit, jit_int8_t disp)
|
||||
{
|
||||
jitoffs_t ptr;
|
||||
jit->write_ubyte(IA32_JMP_IMM8);
|
||||
ptr = jit->jit_curpos();
|
||||
jit->write_byte(disp);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline jitoffs_t IA32_Jump_Cond_Imm32(JitWriter *jit, jit_uint8_t cond, jit_int32_t disp)
|
||||
{
|
||||
jitoffs_t ptr;
|
||||
@ -671,6 +690,12 @@ inline jitoffs_t IA32_Call_Imm32(JitWriter *jit, jit_int32_t disp)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void IA32_Call_Rm(JitWriter *jit, jit_uint8_t reg)
|
||||
{
|
||||
jit->write_ubyte(IA32_CALL_RM);
|
||||
jit->write_ubyte(ia32_modrm(MOD_REG, 2, reg));
|
||||
}
|
||||
|
||||
inline void IA32_Write_Jump8(JitWriter *jit, jitoffs_t jmp, jitoffs_t target)
|
||||
{
|
||||
//save old ptr
|
||||
|
@ -189,10 +189,6 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\sp_vm_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sp_vm_basecontext.h"
|
||||
>
|
||||
@ -319,6 +315,10 @@
|
||||
RelativePath="..\..\include\sp_vm_api.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\sp_vm_base.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\sp_vm_context.h"
|
||||
>
|
||||
|
@ -58,7 +58,18 @@ int BaseContext::Execute(uint32_t public_func, cell_t *result)
|
||||
return err;
|
||||
}
|
||||
|
||||
return vm->ContextExecute(ctx, pubfunc->offs, result);
|
||||
PushCell(ctx->pushcount);
|
||||
ctx->pushcount = 0;
|
||||
|
||||
cell_t save_sp = ctx->sp;
|
||||
cell_t save_hp = ctx->hp;
|
||||
|
||||
err = vm->ContextExecute(ctx, pubfunc->offs, result);
|
||||
|
||||
ctx->sp = save_sp;
|
||||
ctx->hp = save_hp;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
|
||||
|
Loading…
Reference in New Issue
Block a user