dvander@70: #include dvander@70: #include dvander@70: #include "jit_x86.h" dvander@70: #include "opcode_helpers.h" dvander@70: #include "x86_macros.h" dvander@70: dvander@105: #define NUM_INFO_PARAMS 7 dvander@105: dvander@93: jitoffs_t Write_Execute_Function(JitWriter *jit) dvander@73: { dvander@73: /** dvander@73: * The variables we're passed in: dvander@73: * sp_context_t *ctx, uint32_t code_idx, cell_t *result dvander@73: */ dvander@73: dvander@74: /** dvander@74: * !NOTE! dvander@74: * Currently, we do not accept ctx->frm as the new frame pointer. dvander@74: * Instead, we copy the frame from the stack pointer. dvander@74: * This is because we do not support resuming or sleeping! dvander@74: */ dvander@73: dvander@74: //push ebp dvander@74: //mov ebp, esp dvander@74: IA32_Push_Reg(jit, REG_EBP); dvander@74: IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG); dvander@74: dvander@74: //push esi dvander@74: //push edi dvander@74: //push ebx dvander@74: IA32_Push_Reg(jit, REG_ESI); dvander@74: IA32_Push_Reg(jit, REG_EDI); dvander@74: IA32_Push_Reg(jit, REG_EBX); dvander@74: dvander@105: //sub esp, 4*n - reserve info array dvander@74: //mov esi, esp - save info pointer dvander@105: IA32_Sub_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG); dvander@74: IA32_Mov_Reg_Rm(jit, AMX_REG_INFO, REG_ESP, MOD_REG); dvander@74: dvander@83: /* Initial memory setup */ dvander@83: //mov eax, [ebp+16] - get result pointer dvander@83: //mov [esi+8], eax - store into info pointer dvander@74: //mov eax, [ebp+8] - get context dvander@74: //mov [esi+12], eax - store context into info pointer dvander@74: //mov ecx, [eax+] - get heap pointer dvander@74: //mov [esi+4], ecx - store heap into info pointer dvander@105: //mov ebp, [eax+] - get data pointer dvander@83: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16); dvander@83: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL); dvander@74: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8); dvander@83: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT); dvander@74: IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp)); dvander@83: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP); dvander@74: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, data)); dvander@74: dvander@83: /* Frame setup */ dvander@105: //mov edi, [eax+] - get stack pointer dvander@105: //add edi, ebp - relocate to data section dvander@105: //mov ebx, edi - copy sp to frm dvander@75: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_STK, REG_EAX, offsetof(sp_context_t, sp)); dvander@105: IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); dvander@75: IA32_Mov_Reg_Rm(jit, AMX_REG_FRM, AMX_REG_STK, MOD_REG); dvander@75: dvander@83: /* Info memory setup */ dvander@105: //mov ecx, [eax+] - copy memsize to temp var dvander@105: //mov [esi+x], ecx - store unrelocated dvander@105: //add ecx, ebp - relocate dvander@105: //mov [esi+x], ecx - store relocated dvander@83: //mov ecx, [eax+] - get heap low dvander@83: //mov [esi+20], ecx - store heap low into info pointer dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, memory)); dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP_U); dvander@105: IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG); dvander@83: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP); dvander@83: IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, heapbase)); dvander@83: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAPLOW); dvander@75: dvander@83: /* Remaining needed vars */ dvander@105: //mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack) dvander@105: //add ecx, [eax+] - add code base to index dvander@105: IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3))); dvander@93: IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase)); dvander@74: dvander@74: /* by now, everything is set up, so we can call into the plugin */ dvander@74: //call ecx dvander@86: IA32_Call_Reg(jit, REG_ECX); dvander@74: dvander@74: /* if the code flow gets to here, there was a normal return */ dvander@105: //mov ecx, [esi+8] - get retval pointer dvander@105: //mov [ecx], eax - store retval from PRI dvander@74: //mov eax, SP_ERR_NONE - set no error dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, AMX_REG_INFO, AMX_INFO_RETVAL); dvander@105: IA32_Mov_Rm_Reg(jit, REG_ECX, AMX_REG_PRI, MOD_MEM_REG); dvander@74: IA32_Mov_Reg_Imm32(jit, REG_EAX, SP_ERR_NONE); dvander@74: dvander@75: /* save where error checking/halting functions should go to */ dvander@105: jitoffs_t offs_return = jit->get_outputpos(); dvander@105: //mov esp, esi - restore stack pointer dvander@105: IA32_Mov_Reg_Rm(jit, REG_ESP, REG_ESI, MOD_REG); dvander@74: dvander@105: /* _FOR NOW_ ... dvander@105: * We are going to restore SP, HP, and FRM for now. This is for dvander@105: * debugging only, to check for alignment errors. As such: dvander@105: * :TODO: probably remove this. dvander@74: */ dvander@105: //mov ecx, [esi+context] dvander@105: //sub edi, ebp dvander@105: //mov edx, [esi+heap] dvander@105: //mov [ecx+sp], edi dvander@105: //mov [ecx+hp], edx dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_ESI, AMX_INFO_CONTEXT); dvander@105: IA32_Sub_Reg_Rm(jit, REG_EDI, REG_EBP, MOD_REG); dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_ESI, AMX_INFO_HEAP); dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, REG_ECX, REG_EDI, offsetof(sp_context_t, sp)); dvander@105: IA32_Mov_Rm_Reg(jit, REG_ECX, REG_EDX, MOD_REG); dvander@74: dvander@105: //add esp, 4*NUM_INFO_PARAMS dvander@74: //pop ebx dvander@74: //pop edi dvander@74: //pop esi dvander@74: //pop ebp dvander@74: //ret dvander@105: IA32_Add_Rm_Imm8(jit, REG_ESP, 4*NUM_INFO_PARAMS, MOD_REG); dvander@74: IA32_Pop_Reg(jit, REG_EBX); dvander@74: IA32_Pop_Reg(jit, REG_EDI); dvander@74: IA32_Pop_Reg(jit, REG_ESI); dvander@74: IA32_Pop_Reg(jit, REG_EBP); dvander@74: IA32_Return(jit); dvander@74: dvander@74: return offs_return; dvander@73: } dvander@73: dvander@86: void Write_BreakDebug(JitWriter *jit) dvander@86: { dvander@86: //push ecx dvander@86: //mov ecx, [esi+ctx] dvander@86: //cmp [ecx+dbreak], 0 dvander@86: //jnz :nocall dvander@86: IA32_Push_Reg(jit, AMX_REG_TMP); dvander@86: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); faluco@97: IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0); dvander@86: jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_NZ, 0); dvander@86: dvander@86: //pushad dvander@86: IA32_Pushad(jit); dvander@86: dvander@86: //push [esi+frm] dvander@86: //push [ecx+context] dvander@86: //mov ecx, [ecx+dbreak] dvander@86: //call ecx dvander@86: //add esp, 8 dvander@86: //popad faluco@97: IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0 dvander@86: IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, context)); dvander@86: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak)); dvander@86: IA32_Call_Reg(jit, AMX_REG_TMP); dvander@86: IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG); dvander@86: IA32_Popad(jit); dvander@86: dvander@86: //:nocall dvander@86: IA32_Send_Jump8_Here(jit, jmp); dvander@86: IA32_Add_Rm_Imm8(jit, REG_ESP, 4*1, MOD_REG); dvander@86: IA32_Return(jit); dvander@86: } dvander@86: dvander@112: void Write_GetError(JitWriter *jit) dvander@75: { dvander@75: CompData *data = (CompData *)jit->data; dvander@75: dvander@112: //mov eax, [esi+info.context] dvander@112: //mov eax, [eax+ctx.error] dvander@112: //jmp [jit_return] dvander@112: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); dvander@112: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EAX, offsetof(sp_context_t, err)); dvander@112: IA32_Jump_Imm32_Abs(jit, data->jit_return); dvander@112: } dvander@112: dvander@112: void Write_SetError(JitWriter *jit, int error) dvander@112: { dvander@112: CompData *data = (CompData *)jit->data; dvander@112: dvander@75: //mov eax, dvander@112: //jmp [jit_return] dvander@75: IA32_Mov_Reg_Imm32(jit, REG_EAX, error); dvander@112: IA32_Jump_Imm32_Abs(jit, data->jit_return); dvander@75: } dvander@75: faluco@81: void Write_Check_DivZero(JitWriter *jit, jit_uint8_t reg) faluco@81: { faluco@81: //test reg, reg dvander@105: //jz :error faluco@81: IA32_Test_Rm_Reg(jit, reg, reg, MOD_REG); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_Z, ((CompData *)jit->data)->jit_error_divzero); dvander@105: } dvander@105: dvander@105: void Write_CheckHeap_Min(JitWriter *jit) dvander@105: { dvander@105: /* Check if the stack went beyond the heap low. dvander@105: * This usually means there was a compiler error. dvander@105: * NOTE: Special optimization here. dvander@105: * The heap low is always known ahead of time! :) dvander@105: */ dvander@105: CompData *data = (CompData *)jit->data; dvander@105: //cmp [esi+info.heap], dvander@105: //jb :error dvander@105: IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_INFO, AMX_INFO_HEAP, data->plugin->data_size); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_B, data->jit_error_heapmin); dvander@105: } faluco@81: dvander@105: void Write_CheckHeap_Low(JitWriter *jit) dvander@105: { dvander@105: /* Check if the heap is trying to grow beyond the stack. dvander@105: */ dvander@105: //mov ecx, [esi+info.heap] dvander@105: //lea ecx, [ebp+ecx+STACK_MARGIN] dvander@105: //cmp ecx, edi dvander@105: //ja :error ; I think this is right dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); dvander@105: IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN); dvander@105: IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_A, ((CompData *)jit->data)->jit_error_heaplow); faluco@81: } dvander@105: dvander@105: void Write_CheckStack_Min(JitWriter *jit) dvander@105: { dvander@105: /* Check if the stack went beyond the stack top dvander@105: * This usually means there was a compiler error. dvander@105: */ dvander@105: //cmp edi, [esi+info.stacktop] dvander@105: //jae :error dvander@105: IA32_Cmp_Reg_Rm_Disp8(jit, AMX_REG_STK, AMX_REG_INFO, AMX_INFO_STACKTOP); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_stackmin); dvander@105: } dvander@105: dvander@105: void Write_CheckStack_Low(JitWriter *jit) dvander@105: { dvander@105: /* Check if the stack went beyond the heap boundary. dvander@105: * Unfortunately this one isn't as quick as the other check. dvander@105: * The stack margin check is important for sysreq.n having space. dvander@105: */ dvander@105: //mov ecx, [esi+info.heap] dvander@105: //lea ecx, [ebp+ecx+STACK_MARGIN] dvander@105: //cmp edi, ecx dvander@105: //jb :error ; I think this is right dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); dvander@105: IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, AMX_REG_TMP, NOSCALE, STACK_MARGIN); dvander@105: IA32_Cmp_Reg_Rm(jit, AMX_REG_STK, AMX_REG_TMP, MOD_REG); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_stacklow); dvander@105: } dvander@105: dvander@105: void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg) dvander@75: { dvander@75: CompData *data = (CompData *)jit->data; dvander@75: dvander@75: /* :TODO: Should this be checking for below heaplow? dvander@75: * The old JIT did not. dvander@75: */ dvander@75: dvander@75: bool call = false; dvander@75: if (!(data->inline_level & JIT_INLINE_ERRORCHECKS)) dvander@75: { dvander@75: /* If we're not in the initial generation phase, dvander@75: * Write a call to the actual routine instead. dvander@75: */ dvander@105: if ((reg == REG_EAX) && data->jit_verify_addr_eax) dvander@75: { dvander@75: jitoffs_t call = IA32_Call_Imm32(jit, 0); dvander@105: IA32_Write_Jump32(jit, call, data->jit_verify_addr_eax); dvander@105: return; dvander@105: } else if ((reg == REG_EDX) && data->jit_verify_addr_edx) { dvander@105: jitoffs_t call = IA32_Call_Imm32(jit, 0); dvander@105: IA32_Write_Jump32(jit, call, data->jit_verify_addr_edx); dvander@75: return; dvander@75: } dvander@75: call = true; dvander@75: } dvander@75: dvander@105: /** dvander@105: * :TODO: If we can't find a nicer way of doing this, dvander@105: * then scrap it on high optimizations. The second portion is not needed at all! dvander@105: */ dvander@105: dvander@105: /* Part 1: Check if we're in the memory bounds */ dvander@105: //cmp , [esi+info.stpu] dvander@105: //jae :error dvander@105: IA32_Cmp_Reg_Rm_Disp8(jit, reg, AMX_REG_INFO, AMX_INFO_STACKTOP_U); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess); dvander@105: dvander@105: /* Part 2: Check if we're in the invalid region between HP and SP */ dvander@105: jitoffs_t jmp; dvander@105: //cmp , [esi+info.heap] dvander@105: //jb :continue dvander@105: //lea ecx, [ebp+] dvander@105: //cmp edi, ecx dvander@105: //jb :error dvander@105: //:continue dvander@75: IA32_Cmp_Reg_Rm_Disp8(jit, reg, AMX_REG_INFO, AMX_INFO_HEAP); dvander@105: jmp = IA32_Jump_Cond_Imm8(jit, CC_B, 0); dvander@105: IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_TMP, AMX_REG_DAT, reg, NOSCALE, 0); dvander@105: IA32_Cmp_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_STK, MOD_REG); dvander@105: IA32_Jump_Cond_Imm32_Abs(jit, CC_B, ((CompData *)jit->data)->jit_error_memaccess); dvander@105: IA32_Send_Jump8_Here(jit, jmp); dvander@105: dvander@75: if (call) dvander@75: { dvander@75: IA32_Return(jit); dvander@75: } dvander@75: } dvander@75: dvander@70: void Macro_PushN_Addr(JitWriter *jit, int i) dvander@70: { dvander@70: //push eax faluco@97: //mov eax, [esi+frm] dvander@70: //loop i times: dvander@70: // lea ecx, [eax+] faluco@97: // mov [edi-4*i], ecx faluco@97: //sub edi, 4*N dvander@70: //pop eax dvander@70: dvander@70: cell_t val; dvander@70: int n = 1; dvander@70: IA32_Push_Reg(jit, AMX_REG_PRI); faluco@97: IA32_Mov_Reg_Rm(jit, AMX_REG_PRI, AMX_REG_INFO, MOD_MEM_REG); dvander@70: do dvander@70: { dvander@70: val = jit->read_cell(); dvander@70: if (val < SCHAR_MAX && val > SCHAR_MIN) dvander@70: IA32_Lea_DispRegImm8(jit, AMX_REG_TMP, AMX_REG_PRI, (jit_int8_t)val); dvander@70: else dvander@70: IA32_Lea_DispRegImm32(jit, AMX_REG_TMP, AMX_REG_PRI, val); dvander@70: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n); dvander@70: } while (n++ < i); dvander@70: IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG); dvander@70: IA32_Pop_Reg(jit, AMX_REG_PRI); dvander@70: } dvander@70: dvander@70: void Macro_PushN_S(JitWriter *jit, int i) dvander@70: { dvander@70: //loop i times: dvander@70: // mov ecx, [ebx+] faluco@97: // mov [edi-4*i], ecx faluco@97: //sub edi, 4*N dvander@70: dvander@70: cell_t val; dvander@70: int n = 1; dvander@70: do dvander@70: { dvander@70: val = jit->read_cell(); dvander@70: if (val < SCHAR_MAX && val > SCHAR_MIN) dvander@70: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_FRM, (jit_int8_t)val); dvander@70: else dvander@70: IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_FRM, val); dvander@70: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n); dvander@70: } while (n++ < i); dvander@70: IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG); dvander@70: } dvander@70: dvander@70: void Macro_PushN_C(JitWriter *jit, int i) dvander@70: { dvander@70: //loop i times: faluco@97: // mov [edi-4*i], faluco@97: //sub edi, 4*N dvander@70: dvander@70: int n = 1; dvander@70: do dvander@70: { dvander@70: IA32_Mov_Rm_Imm32_Disp8(jit, AMX_REG_STK, jit->read_cell(), -4*n); dvander@70: } while (n++ < i); dvander@70: IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG); dvander@70: } dvander@70: dvander@70: void Macro_PushN(JitWriter *jit, int i) dvander@70: { dvander@70: //loop i times: faluco@97: // mov ecx, [ebp+] faluco@97: // mov [edi-4*i], ecx faluco@97: //sub edi, 4*N dvander@70: dvander@70: cell_t val; dvander@70: int n = 1; dvander@70: do dvander@70: { dvander@70: val = jit->read_cell(); dvander@70: if (val < SCHAR_MAX && val > SCHAR_MIN) dvander@70: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_DAT, (jit_int8_t)val); dvander@70: else dvander@70: IA32_Mov_Reg_Rm_Disp32(jit, AMX_REG_TMP, AMX_REG_DAT, val); dvander@70: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, AMX_REG_TMP, -4*n); dvander@70: } while (n++ < i); dvander@70: IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4*i, MOD_REG); dvander@70: } dvander@70: dvander@105: void WriteOp_Sysreq_N_Function(JitWriter *jit) dvander@105: { dvander@105: /* The big daddy of opcodes. dvander@105: * eax - num_params dvander@105: * ecx - native index dvander@105: */ dvander@105: CompData *data = (CompData *)jit->data; dvander@105: dvander@105: /* store the number of parameters on the stack */ dvander@105: //mov [edi-4], eax dvander@105: //sub edi, 4 dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_STK, REG_EAX, -4); dvander@105: IA32_Sub_Rm_Imm8(jit, AMX_REG_STK, 4, MOD_REG); dvander@105: dvander@105: /* save registers we will need */ dvander@105: //push eax ; num_params for stack popping dvander@105: //push edx dvander@105: IA32_Push_Reg(jit, REG_EAX); dvander@105: IA32_Push_Reg(jit, AMX_REG_ALT); dvander@105: dvander@105: /* push some callback stuff */ dvander@105: //push edi ; stack dvander@105: //push ecx ; native index dvander@105: IA32_Push_Reg(jit, AMX_REG_STK); dvander@105: IA32_Push_Reg(jit, REG_ECX); dvander@105: dvander@105: /* Relocate stack, heap, frm information, then store back */ dvander@105: //sub edi, ebp dvander@105: //mov ecx, [esi+hea] dvander@105: //mov eax, [esi+context] dvander@105: //mov [eax+hp], ecx dvander@105: //mov [eax+sp], edi dvander@105: //mov ecx, [esi+frm] dvander@105: //mov [eax+frm], ecx dvander@105: IA32_Sub_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_HEAP); dvander@105: IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, AMX_REG_INFO, AMX_INFO_CONTEXT); dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, hp)); dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_STK, offsetof(sp_context_t, sp)); dvander@105: IA32_Mov_Reg_Rm(jit, AMX_REG_TMP, AMX_INFO_FRM, MOD_REG); dvander@105: IA32_Mov_Rm_Reg_Disp8(jit, REG_EAX, AMX_REG_TMP, offsetof(sp_context_t, frm)); dvander@105: dvander@105: /* finally, push the last parameter and make the call */ dvander@105: //push eax ; context dvander@105: //call NativeCallback dvander@105: IA32_Push_Reg(jit, REG_EAX); dvander@105: jitoffs_t call = IA32_Call_Imm32(jit, 0); dvander@112: IA32_Write_Jump32_Abs(jit, call, (void *)&NativeCallback); dvander@112: dvander@112: /* Test for error */ dvander@112: //mov ecx, [esi+context] dvander@112: //cmp [ecx+err], 0 dvander@112: //jnz :error dvander@112: IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT); dvander@112: IA32_Cmp_Rm_Imm32_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, err), 0); dvander@112: IA32_Jump_Cond_Imm32_Abs(jit, CC_NZ, data->jit_extern_error); dvander@105: dvander@105: /* restore what we damaged */ dvander@105: //add esp, 4*3 dvander@105: //add edi, ebp dvander@105: //pop edx dvander@105: //pop ecx ; num_params dvander@105: IA32_Add_Rm_Imm8(jit, REG_ESP, 4*3, MOD_REG); dvander@105: IA32_Add_Rm_Reg(jit, AMX_REG_STK, AMX_REG_DAT, MOD_REG); dvander@105: IA32_Pop_Reg(jit, AMX_REG_ALT); dvander@105: IA32_Pop_Reg(jit, REG_ECX); dvander@105: dvander@105: /* pop the AMX stack. do not check the margins. dvander@105: * Note that this is not a true macro - we don't bother to dvander@105: * set ALT here because nothing will be using it. dvander@105: */ dvander@105: //lea edi, [edi+ecx*4+4] dvander@105: IA32_Lea_Reg_DispRegMultImm8(jit, AMX_REG_STK, AMX_REG_STK, REG_ECX, SCALE4, 4); dvander@105: dvander@105: //ret dvander@105: IA32_Return(jit); dvander@105: } dvander@105: