#ifndef _NSEEL_GLUE_X86_64_H_ #define _NSEEL_GLUE_X86_64_H_ #define GLUE_MAX_FPSTACK_SIZE 8 #define GLUE_JMP_SET_OFFSET(endOfInstruction,offset) (((int *)(endOfInstruction))[-1] = (offset)) #define GLUE_PREFER_NONFP_DV_ASSIGNS static const unsigned char GLUE_JMP_NC[] = { 0xE9, 0,0,0,0, }; // jmp static const unsigned char GLUE_JMP_IF_P1_Z[] = {0x85, 0xC0, 0x0F, 0x84, 0,0,0,0 }; // test eax, eax, jz static const unsigned char GLUE_JMP_IF_P1_NZ[] = {0x85, 0xC0, 0x0F, 0x85, 0,0,0,0 }; // test eax, eax, jnz #define GLUE_FUNC_ENTER_SIZE 0 #define GLUE_FUNC_LEAVE_SIZE 0 const static unsigned int GLUE_FUNC_ENTER[1]; const static unsigned int GLUE_FUNC_LEAVE[1]; // on x86-64: // stack is always 16 byte aligned // pushing values to the stack (for eel functions) has alignment pushed first, then value (value is at the lower address) // pushing pointers to the stack has the pointer pushed first, then the alignment (pointer is at the higher address) #define GLUE_MOV_PX_DIRECTVALUE_SIZE 10 static void GLUE_MOV_PX_DIRECTVALUE_GEN(void *b, INT_PTR v, int wr) { const static unsigned short tab[3] = { 0xB848 /* mov rax, dv*/, 0xBF48 /* mov rdi, dv */ , 0xB948 /* mov rcx, dv */ }; unsigned short *bb = (unsigned short *)b; *bb++ = tab[wr]; // mov rax, directvalue *(INT_PTR *)bb = v; } const static unsigned char GLUE_PUSH_P1[2]={ 0x50,0x50}; // push rax (pointer); push rax (alignment) #define GLUE_POP_PX_SIZE 2 static void GLUE_POP_PX(void *b, int wv) { static const unsigned char tab[3][GLUE_POP_PX_SIZE]= { {0x58,/*pop eax*/ 0x58}, // pop alignment, then pop pointer {0x5F,/*pop edi*/ 0x5F}, {0x59,/*pop ecx*/ 0x59}, }; memcpy(b,tab[wv],GLUE_POP_PX_SIZE); } static const unsigned char GLUE_PUSH_P1PTR_AS_VALUE[] = { 0x50, /*push rax - for alignment */ 0xff, 0x30, /* push qword [rax] */ }; static int GLUE_POP_VALUE_TO_ADDR(unsigned char *buf, void *destptr) // trashes P2 (rdi) and P3 (rcx) { if (buf) { *buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue *buf++ = 0x8f; *buf++ = 0x01; // pop qword [rcx] *buf++ = 0x5F ; // pop rdi (alignment, safe to trash rdi though) } return 1+10+2; } static int GLUE_COPY_VALUE_AT_P1_TO_PTR(unsigned char *buf, void *destptr) // trashes P2/P3 { if (buf) { *buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue *buf++ = 0x48; *buf++ = 0x8B; *buf++ = 0x38; // mov rdi, [rax] *buf++ = 0x48; *buf++ = 0x89; *buf++ = 0x39; // mov [rcx], rdi } return 3 + 10 + 3; } static int GLUE_POP_FPSTACK_TO_PTR(unsigned char *buf, void *destptr) { if (buf) { *buf++ = 0x48; *buf++ = 0xB8; *(void **) buf = destptr; buf+=8; // mov rax, directvalue *buf++ = 0xDD; *buf++ = 0x18; // fstp qword [rax] } return 2+8+2; } #define GLUE_SET_PX_FROM_P1_SIZE 3 static void GLUE_SET_PX_FROM_P1(void *b, int wv) { static const unsigned char tab[3][GLUE_SET_PX_FROM_P1_SIZE]={ {0x90,0x90,0x90}, // should never be used! (nopnop) {0x48,0x89,0xC7}, // mov rdi, rax {0x48,0x89,0xC1}, // mov rcx, rax }; memcpy(b,tab[wv],GLUE_SET_PX_FROM_P1_SIZE); } #define GLUE_POP_FPSTACK_SIZE 2 static const unsigned char GLUE_POP_FPSTACK[2] = { 0xDD, 0xD8 }; // fstp st0 static const unsigned char GLUE_POP_FPSTACK_TOSTACK[] = { 0x48, 0x81, 0xEC, 16, 0,0,0, // sub rsp, 16 0xDD, 0x1C, 0x24 // fstp qword (%rsp) }; static const unsigned char GLUE_POP_FPSTACK_TO_WTP[] = { 0xDD, 0x1E, /* fstp qword [rsi] */ 0x48, 0x81, 0xC6, 8, 0,0,0,/* add rsi, 8 */ }; #define GLUE_SET_PX_FROM_WTP_SIZE 3 static void GLUE_SET_PX_FROM_WTP(void *b, int wv) { static const unsigned char tab[3][GLUE_SET_PX_FROM_WTP_SIZE]={ {0x48, 0x89,0xF0}, // mov rax, rsi {0x48, 0x89,0xF7}, // mov rdi, rsi {0x48, 0x89,0xF1}, // mov rcx, rsi }; memcpy(b,tab[wv],GLUE_SET_PX_FROM_WTP_SIZE); } #define GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE 2 static void GLUE_PUSH_VAL_AT_PX_TO_FPSTACK(void *b, int wv) { static const unsigned char tab[3][GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE]={ {0xDD,0x00}, // fld qword [rax] {0xDD,0x07}, // fld qword [rdi] {0xDD,0x01}, // fld qword [rcx] }; memcpy(b,tab[wv],GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE); } static unsigned char GLUE_POP_STACK_TO_FPSTACK[] = { 0xDD, 0x04, 0x24, // fld qword (%rsp) 0x48, 0x81, 0xC4, 16, 0,0,0, // add rsp, 16 }; #define GLUE_POP_FPSTACK_TO_WTP_TO_PX_SIZE (GLUE_SET_PX_FROM_WTP_SIZE + sizeof(GLUE_POP_FPSTACK_TO_WTP)) static void GLUE_POP_FPSTACK_TO_WTP_TO_PX(unsigned char *buf, int wv) { GLUE_SET_PX_FROM_WTP(buf,wv); memcpy(buf + GLUE_SET_PX_FROM_WTP_SIZE,GLUE_POP_FPSTACK_TO_WTP,sizeof(GLUE_POP_FPSTACK_TO_WTP)); }; const static unsigned char GLUE_RET=0xC3; static int GLUE_RESET_WTP(unsigned char *out, void *ptr) { if (out) { *out++ = 0x48; *out++ = 0xBE; // mov rsi, constant64 *(void **)out = ptr; out+=sizeof(void *); } return 2+sizeof(void *); } extern void win64_callcode(INT_PTR code, INT_PTR ram_tab); #define GLUE_CALL_CODE(bp, cp, rt) win64_callcode(cp, rt) static unsigned char *EEL_GLUE_set_immediate(void *_p, INT_PTR newv) { char *p=(char*)_p; INT_PTR scan = 0xFEFEFEFEFEFEFEFE; while (*(INT_PTR *)p != scan) p++; *(INT_PTR *)p = newv; return (unsigned char *) (((INT_PTR*)p)+1); } #define INT_TO_LECHARS(x) ((x)&0xff),(((x)>>8)&0xff), (((x)>>16)&0xff), (((x)>>24)&0xff) #define GLUE_INLINE_LOOPS static const unsigned char GLUE_LOOP_LOADCNT[]={ 0xDD, 0x0E, //fistTp qword [rsi] 0x48, 0x8B, 0x0E, // mov rcx, [rsi] 0x48, 0x81, 0xf9, 1,0,0,0, // cmp rcx, 1 0x0F, 0x8C, 0,0,0,0, // JL }; static const unsigned char GLUE_LOOP_CLAMPCNT[]={ 0x48, 0x81, 0xf9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // cmp rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN 0x0F, 0x8C, 10,0,0,0, // JL over-the-mov 0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN }; static const unsigned char GLUE_LOOP_BEGIN[]={ 0x56, //push rsi 0x51, // push rcx }; static const unsigned char GLUE_LOOP_END[]={ 0x59, //pop rcx 0x5E, // pop rsi 0xff, 0xc9, // dec rcx 0x0f, 0x85, 0,0,0,0, // jnz ... }; static const unsigned char GLUE_WHILE_SETUP[]={ 0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN }; static const unsigned char GLUE_WHILE_BEGIN[]={ 0x56, //push rsi 0x51, // push rcx }; static const unsigned char GLUE_WHILE_END[]={ 0x59, //pop rcx 0x5E, // pop rsi 0xff, 0xc9, // dec rcx 0x0f, 0x84, 0,0,0,0, // jz endpt }; static const unsigned char GLUE_WHILE_CHECK_RV[] = { 0x85, 0xC0, // test eax, eax 0x0F, 0x85, 0,0,0,0 // jnz looppt }; static const unsigned char GLUE_SET_P1_Z[] = { 0x48, 0x29, 0xC0 }; // sub rax, rax static const unsigned char GLUE_SET_P1_NZ[] = { 0xb0, 0x01 }; // mov al, 1 #define GLUE_HAS_FXCH static const unsigned char GLUE_FXCH[] = {0xd9, 0xc9}; #define GLUE_HAS_FLDZ static const unsigned char GLUE_FLDZ[] = {0xd9, 0xee}; #define GLUE_HAS_FLD1 static const unsigned char GLUE_FLD1[] = {0xd9, 0xe8}; static EEL_F negativezeropointfive=-0.5f; static EEL_F onepointfive=1.5f; #define GLUE_INVSQRT_NEEDREPL &negativezeropointfive, &onepointfive, #define GLUE_HAS_NATIVE_TRIGSQRTLOG static void *GLUE_realAddress(void *fn, void *fn_e, int *size) { static const unsigned char sig[12] = { 0x89, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; unsigned char *p = (unsigned char *)fn; while (memcmp(p,sig,sizeof(sig))) p++; p+=sizeof(sig); fn = p; while (memcmp(p,sig,sizeof(sig))) p++; *size = p - (unsigned char *)fn; return fn; } // end of x86-64 #endif