diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h index f89a5be4..95434180 100644 --- a/sourcepawn/include/sp_vm_types.h +++ b/sourcepawn/include/sp_vm_types.h @@ -175,10 +175,20 @@ typedef struct sp_debug_symbol_s sp_fdbg_symbol_t *sym; /* pointer to original symbol */ } sp_debug_symbol_t; +namespace SourcePawn +{ + class IPluginContext; + class IVirtualMachine; +}; + /** * Breaks into a debugger + * Params: + * [0] - plugin context + * [1] - frm + * [2] - cip */ -typedef int (*SPVM_DEBUGBREAK)(struct sp_context_s *); +typedef int (*SPVM_DEBUGBREAK)(SourcePawn::IPluginContext *, uint32_t, uint32_t); #define SPFLAG_PLUGIN_DEBUG (1<<0) /* plugin is in debug mode */ @@ -193,8 +203,8 @@ typedef struct sp_context_s /* general/parent information */ void *base; /* base of generated code and memory */ sp_plugin_t *plugin; /* pointer back to parent information */ - void *context; /* pointer to IPluginContext */ - void *vmbase; /* pointer to IVirtualMachine */ + SourcePawn::IPluginContext *context; /* pointer to IPluginContext */ + SourcePawn::IVirtualMachine *vmbase; /* pointer to IVirtualMachine */ void *user[4]; /* user specific pointers */ void *vm[4]; /* VM specific pointers */ uint32_t flags; /* compilation flags */ diff --git a/sourcepawn/vm/jit/x86/jit_x86.cpp b/sourcepawn/vm/jit/x86/jit_x86.cpp index 932e74e4..2c80df62 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.cpp +++ b/sourcepawn/vm/jit/x86/jit_x86.cpp @@ -1382,6 +1382,23 @@ inline void WriteOp_Halt(JitWriter *jit) IA32_Write_Jump32(jit, reloc, data->jit_return); } +inline void WriteOp_Break(JitWriter *jit) +{ + CompData *data = (CompData *)jit->data; + if (data->debug) + { + //mov ecx, + 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); + } +} + /************************************************* ************************************************* @@ -1476,21 +1493,24 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err) data->jit_return = Write_Execute_Function(jit); /* Write error checking routines in case they are needed */ - jitpos = jit->jit_curpos(); - Write_Check_VerifyAddr(jit, REG_EAX, true); - data->jit_verify_addr_eax = jitpos; + 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; - jitpos = jit->jit_curpos(); - Write_Check_VerifyAddr(jit, REG_EDX, true); - data->jit_verify_addr_edx = jitpos; + jitpos = jit->jit_curpos(); + Write_CheckMargin_Heap(jit); + data->jit_chkmargin_heap = jitpos; - jitpos = jit->jit_curpos(); - Write_CheckMargin_Heap(jit); - data->jit_chkmargin_heap = jitpos; - - jitpos = jit->jit_curpos(); - Write_BoundsCheck(jit); - data->jit_bounds = jitpos; + jitpos = jit->jit_curpos(); + Write_BoundsCheck(jit); + data->jit_bounds = jitpos; + } /* Begin opcode browsing */ for (; writer.inptr <= endptr;) @@ -2153,6 +2173,11 @@ IPluginContext *JITX86::CompileToContext(ICompilation *co, int *err) WriteOp_Halt(jit); break; } + case OP_BREAK: + { + WriteOp_Break(jit); + break; + } default: { AbortCompilation(co); diff --git a/sourcepawn/vm/jit/x86/jit_x86.h b/sourcepawn/vm/jit/x86/jit_x86.h index edcb212f..dd619892 100644 --- a/sourcepawn/vm/jit/x86/jit_x86.h +++ b/sourcepawn/vm/jit/x86/jit_x86.h @@ -25,6 +25,7 @@ public: jitoffs_t jit_verify_addr_edx; jitoffs_t jit_chkmargin_heap; jitoffs_t jit_bounds; + jitoffs_t jit_break; int inline_level; bool checks; bool debug; @@ -53,6 +54,7 @@ public: #define AMX_REG_FRM REG_EBX #define AMX_INFO_FRM AMX_REG_INFO //not relocated +#define AMX_INFO_FRAME 0 //(same thing as above) #define AMX_INFO_HEAP 4 //not relocated #define AMX_INFO_RETVAL 8 //physical #define AMX_INFO_CONTEXT 12 //physical diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.cpp b/sourcepawn/vm/jit/x86/opcode_helpers.cpp index 18ffa95d..f35b7c5e 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.cpp +++ b/sourcepawn/vm/jit/x86/opcode_helpers.cpp @@ -85,7 +85,7 @@ jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline) /* by now, everything is set up, so we can call into the plugin */ //call ecx - IA32_Call_Rm(jit, REG_ECX); + IA32_Call_Reg(jit, REG_ECX); /* if the code flow gets to here, there was a normal return */ //mov ebp, [esi+8] - get retval pointer @@ -133,6 +133,39 @@ jitoffs_t Write_Execute_Function(JitWriter *jit, bool never_inline) return offs_return; } +void Write_BreakDebug(JitWriter *jit) +{ + //push ecx + //mov ecx, [esi+ctx] + //cmp [ecx+dbreak], 0 + //jnz :nocall + IA32_Push_Reg(jit, AMX_REG_TMP); + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); + IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0); + jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0); + + //pushad + IA32_Pushad(jit); + + //push [esi+frm] + //push [ecx+context] + //mov ecx, [ecx+dbreak] + //call ecx + //add esp, 8 + //popad + IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); + IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, context)); + IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak)); + IA32_Call_Reg(jit, AMX_REG_TMP); + IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG); + IA32_Popad(jit); + + //:nocall + IA32_Send_Jump8_Here(jit, jmp); + IA32_Add_Rm_Imm8(jit, REG_ESP, 4*1, MOD_REG); + IA32_Return(jit); +} + void Write_Error(JitWriter *jit, int error) { CompData *data = (CompData *)jit->data; diff --git a/sourcepawn/vm/jit/x86/opcode_helpers.h b/sourcepawn/vm/jit/x86/opcode_helpers.h index 23f66eab..6417ea8a 100644 --- a/sourcepawn/vm/jit/x86/opcode_helpers.h +++ b/sourcepawn/vm/jit/x86/opcode_helpers.h @@ -43,6 +43,11 @@ void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg); */ void Write_BoundsCheck(JitWriter *jit); +/** + * Writes the break debug function. + */ +void Write_BreakDebug(JitWriter *jit); + /** * These are for writing the PushN opcodes. */ @@ -190,7 +195,7 @@ typedef enum OP_NOP, //DONE OP_SYSREQ_N, OP_SYMTAG, //DEPRECATED - OP_BREAK, + OP_BREAK, //DONE OP_PUSH2_C, //DONE OP_PUSH2, //DONE OP_PUSH2_S, //DONE diff --git a/sourcepawn/vm/jit/x86/x86_macros.h b/sourcepawn/vm/jit/x86/x86_macros.h index bf62a38b..2994042a 100644 --- a/sourcepawn/vm/jit/x86/x86_macros.h +++ b/sourcepawn/vm/jit/x86/x86_macros.h @@ -114,11 +114,14 @@ #define IA32_LEA_REG_MEM 0x8D // encoding is /r #define IA32_POP_REG 0x58 // encoding is +r #define IA32_PUSH_REG 0x50 // encoding is +r +#define IA32_PUSH_RM 0xFF // encoding is /6 #define IA32_REP 0xF3 // no extra encoding #define IA32_MOVSD 0xA5 // no extra encoding #define IA32_MOVSB 0xA4 // no extra encoding #define IA32_STOSD 0xAB // no extra encoding #define IA32_CLD 0xFC // no extra encoding +#define IA32_PUSHAD 0x60 // no extra encoding +#define IA32_POPAD 0x61 // no extra encoding inline jit_uint8_t ia32_modrm(jit_uint8_t mode, jit_uint8_t reg, jit_uint8_t rm) { @@ -568,6 +571,23 @@ inline void IA32_Push_Reg(JitWriter *jit, jit_uint8_t reg) jit->write_ubyte(IA32_PUSH_REG+reg); } +inline void IA32_Pushad(JitWriter *jit) +{ + jit->write_ubyte(IA32_PUSHAD); +} + +inline void IA32_Popad(JitWriter *jit) +{ + jit->write_ubyte(IA32_POPAD); +} + +inline void IA32_Push_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t disp8) +{ + jit->write_ubyte(IA32_PUSH_RM); + jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, reg)); + jit->write_ubyte(disp8); +} + /** * Moving from REGISTER/MEMORY to REGISTER */ @@ -771,7 +791,7 @@ 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) +inline void IA32_Call_Reg(JitWriter *jit, jit_uint8_t reg) { jit->write_ubyte(IA32_CALL_RM); jit->write_ubyte(ia32_modrm(MOD_REG, 2, reg)); @@ -853,6 +873,14 @@ inline void IA32_Cmp_Rm_Imm32(JitWriter *jit, jit_uint8_t mode, jit_uint8_t rm, jit->write_int32(imm32); } +inline void IA32_Cmp_Rm_Imm32_Disp8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t disp8, jit_int32_t imm32) +{ + jit->write_ubyte(IA32_CMP_RM_IMM32); + jit->write_ubyte(ia32_modrm(MOD_DISP8, 7, reg)); + jit->write_ubyte(disp8); + jit->write_int32(imm32); +} + inline void IA32_Cmp_Rm_Disp8_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp, jit_int8_t imm8) { jit->write_ubyte(IA32_CMP_RM_IMM8);