winamp/Src/ns-eel2/glue_x86_64.h

262 lines
7.9 KiB
C
Raw Normal View History

2024-09-24 13:54:57 +01:00
#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