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
|
//add ebp, 4
|
||||||
IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_STK, MOD_MEM_REG);
|
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);
|
IA32_Add_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void WriteOp_Pop_Alt(JitWriter *jit)
|
inline void WriteOp_Pop_Alt(JitWriter *jit)
|
||||||
@ -1049,16 +1048,6 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
|
|||||||
} else if (op_c == -1) {
|
} else if (op_c == -1) {
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OP_SYSREQ_C:
|
|
||||||
case OP_SYSREQ_PRI:
|
|
||||||
case OP_SYSREQ_N:
|
|
||||||
{
|
|
||||||
if (!data->always_inline)
|
|
||||||
{
|
|
||||||
reloc_count++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OP_CASETBL:
|
case OP_CASETBL:
|
||||||
{
|
{
|
||||||
ucell_t num = *(ucell_t *)cip;
|
ucell_t num = *(ucell_t *)cip;
|
||||||
@ -1083,14 +1072,30 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err)
|
|||||||
*********************************************/
|
*********************************************/
|
||||||
|
|
||||||
JitWriter writer;
|
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.inptr = (cell_t *)code;
|
||||||
writer.outptr = NULL;
|
writer.outptr = NULL;
|
||||||
writer.outbase = NULL;
|
writer.outbase = NULL;
|
||||||
|
|
||||||
//redo_pass:
|
/* Get inlining level */
|
||||||
cell_t *endptr = (cell_t *)(end_cip);
|
int inline_level = data->inline_level;
|
||||||
JitWriter *jit = &writer;
|
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;)
|
for (; writer.inptr <= endptr;)
|
||||||
{
|
{
|
||||||
op = (OPCODE)writer.read_cell();
|
op = (OPCODE)writer.read_cell();
|
||||||
|
@ -9,12 +9,12 @@ using namespace SourcePawn;
|
|||||||
class CompData : public ICompilation
|
class CompData : public ICompilation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompData() : plugin(NULL), debug(false), always_inline(true)
|
CompData() : plugin(NULL), debug(false), inline_level(2)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
sp_plugin_t *plugin;
|
sp_plugin_t *plugin;
|
||||||
bool always_inline;
|
int inline_level;
|
||||||
bool debug;
|
bool debug;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,5 +43,6 @@ public:
|
|||||||
#define AMX_INFO_FRM AMX_REG_INFO
|
#define AMX_INFO_FRM AMX_REG_INFO
|
||||||
#define AMX_INFO_HEAP 4
|
#define AMX_INFO_HEAP 4
|
||||||
#define AMX_INFO_RETVAL 8
|
#define AMX_INFO_RETVAL 8
|
||||||
|
#define AMX_INFO_CONTEXT 12
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
|
||||||
|
@ -6,26 +6,129 @@
|
|||||||
|
|
||||||
int OpAdvTable[OP_NUM_OPCODES];
|
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:
|
* The state expected by our plugin is:
|
||||||
* #define AMX_REG_PRI REG_EAX
|
* #define AMX_REG_PRI REG_EAX (done)
|
||||||
#define AMX_REG_ALT REG_EDX
|
#define AMX_REG_ALT REG_EDX (done)
|
||||||
#define AMX_REG_STK REG_EBP
|
#define AMX_REG_STK REG_EBP (done)
|
||||||
#define AMX_REG_DAT REG_EDI
|
#define AMX_REG_DAT REG_EDI (done)
|
||||||
#define AMX_REG_TMP REG_ECX
|
#define AMX_REG_TMP REG_ECX (nothing)
|
||||||
#define AMX_REG_INFO REG_ESI
|
#define AMX_REG_INFO REG_ESI (done)
|
||||||
#define AMX_REG_FRM REG_EBX
|
#define AMX_REG_FRM REG_EBX (done)
|
||||||
#define AMX_INFO_FRM AMX_REG_INFO
|
#define AMX_INFO_FRM AMX_REG_INFO (done)
|
||||||
#define AMX_INFO_HEAP 4
|
#define AMX_INFO_HEAP 4 (done)
|
||||||
#define AMX_INFO_RETVAL 12
|
#define AMX_INFO_RETVAL 8 (done)
|
||||||
|
#define AMX_INFO_CONTEXT 12 (done)
|
||||||
*
|
*
|
||||||
* The variables we're passed in:
|
* The variables we're passed in:
|
||||||
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
|
* 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)
|
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_LOAD_S_BOTH] = sizeof(cell_t)*2;
|
||||||
OpAdvTable[OP_CONST] = sizeof(cell_t)*2;
|
OpAdvTable[OP_CONST] = sizeof(cell_t)*2;
|
||||||
OpAdvTable[OP_CONST_S] = sizeof(cell_t)*2;
|
OpAdvTable[OP_CONST_S] = sizeof(cell_t)*2;
|
||||||
|
OpAdvTable[OP_SYSREQ_N] = sizeof(cell_t)*2;
|
||||||
|
|
||||||
/* instructions with 1 parameter */
|
/* instructions with 1 parameter */
|
||||||
OpAdvTable[OP_LOAD_PRI] = sizeof(cell_t);
|
OpAdvTable[OP_LOAD_PRI] = sizeof(cell_t);
|
||||||
@ -199,6 +303,7 @@ JITX86::JITX86()
|
|||||||
OpAdvTable[OP_BOUNDS] = sizeof(cell_t);
|
OpAdvTable[OP_BOUNDS] = sizeof(cell_t);
|
||||||
OpAdvTable[OP_PUSH_ADR] = sizeof(cell_t);
|
OpAdvTable[OP_PUSH_ADR] = sizeof(cell_t);
|
||||||
OpAdvTable[OP_PUSH_HEAP_C] = sizeof(cell_t);
|
OpAdvTable[OP_PUSH_HEAP_C] = sizeof(cell_t);
|
||||||
|
OpAdvTable[OP_SYSREQ_C] = sizeof(cell_t);
|
||||||
|
|
||||||
/* instructions with 0 parameters */
|
/* instructions with 0 parameters */
|
||||||
OpAdvTable[OP_LOAD_I] = 0;
|
OpAdvTable[OP_LOAD_I] = 0;
|
||||||
@ -261,6 +366,7 @@ JITX86::JITX86()
|
|||||||
OpAdvTable[OP_BREAK] = 0;
|
OpAdvTable[OP_BREAK] = 0;
|
||||||
OpAdvTable[OP_HEAP_PRI] = 0;
|
OpAdvTable[OP_HEAP_PRI] = 0;
|
||||||
OpAdvTable[OP_POP_HEAP_PRI] = 0;
|
OpAdvTable[OP_POP_HEAP_PRI] = 0;
|
||||||
|
OpAdvTable[OP_SYSREQ_PRI] = 0;
|
||||||
|
|
||||||
/* opcodes that need relocation */
|
/* opcodes that need relocation */
|
||||||
OpAdvTable[OP_CALL] = -2;
|
OpAdvTable[OP_CALL] = -2;
|
||||||
|
@ -3,6 +3,19 @@
|
|||||||
|
|
||||||
#include "..\jit_helpers.h"
|
#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_Addr(JitWriter *jit, int i);
|
||||||
void Macro_PushN_S(JitWriter *jit, int i);
|
void Macro_PushN_S(JitWriter *jit, int i);
|
||||||
void Macro_PushN_C(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_IMM32 0x81 // encoding is /6
|
||||||
#define IA32_XOR_RM_IMM8 0x83 // encoding is /6
|
#define IA32_XOR_RM_IMM8 0x83 // encoding is /6
|
||||||
#define IA32_ADD_RM_REG 0x01 // encoding is /r
|
#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_IMM32 0x81 // encoding is /0
|
||||||
#define IA32_ADD_RM_IMM8 0x83 // encoding is /0
|
#define IA32_ADD_RM_IMM8 0x83 // encoding is /0
|
||||||
#define IA32_ADD_EAX_IMM32 0x05 // no extra encoding
|
#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_IMM8 0x83 // encoding is /5 <imm8>
|
||||||
#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
|
#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 <imm32>
|
||||||
#define IA32_JMP_IMM32 0xE9 // encoding is 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_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_REG_IMM 0xB8 // encoding is +r <imm32>
|
||||||
#define IA32_MOV_RM_REG 0x89 // encoding is /r
|
#define IA32_MOV_RM_REG 0x89 // encoding is /r
|
||||||
#define IA32_MOV_REG_MEM 0x8B // 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);
|
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,
|
inline void IA32_Add_Rm_Imm8_Disp8(JitWriter *jit,
|
||||||
jit_uint8_t dest,
|
jit_uint8_t dest,
|
||||||
jit_int8_t val,
|
jit_int8_t val,
|
||||||
@ -652,6 +662,15 @@ inline jitoffs_t IA32_Jump_Imm32(JitWriter *jit, jit_int32_t disp)
|
|||||||
return ptr;
|
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)
|
inline jitoffs_t IA32_Jump_Cond_Imm32(JitWriter *jit, jit_uint8_t cond, jit_int32_t disp)
|
||||||
{
|
{
|
||||||
jitoffs_t ptr;
|
jitoffs_t ptr;
|
||||||
@ -671,6 +690,12 @@ inline jitoffs_t IA32_Call_Imm32(JitWriter *jit, jit_int32_t disp)
|
|||||||
return ptr;
|
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)
|
inline void IA32_Write_Jump8(JitWriter *jit, jitoffs_t jmp, jitoffs_t target)
|
||||||
{
|
{
|
||||||
//save old ptr
|
//save old ptr
|
||||||
|
@ -189,10 +189,6 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
<File
|
|
||||||
RelativePath="..\sp_vm_base.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\sp_vm_basecontext.h"
|
RelativePath="..\sp_vm_basecontext.h"
|
||||||
>
|
>
|
||||||
@ -319,6 +315,10 @@
|
|||||||
RelativePath="..\..\include\sp_vm_api.h"
|
RelativePath="..\..\include\sp_vm_api.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\sp_vm_base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\sp_vm_context.h"
|
RelativePath="..\..\include\sp_vm_context.h"
|
||||||
>
|
>
|
||||||
|
@ -58,7 +58,18 @@ int BaseContext::Execute(uint32_t public_func, cell_t *result)
|
|||||||
return err;
|
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)
|
int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
|
||||||
|
Loading…
Reference in New Issue
Block a user