mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-11-28 04:00:47 +01:00
262 lines
7.9 KiB
C
262 lines
7.9 KiB
C
#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<offset>
|
|
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 <skipptr>
|
|
};
|
|
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
|