add oversampler
This commit is contained in:
285
oversampling/WDL/eel2/glue_ppc.h
Normal file
285
oversampling/WDL/eel2/glue_ppc.h
Normal file
@@ -0,0 +1,285 @@
|
||||
#ifndef _NSEEL_GLUE_PPC_H_
|
||||
#define _NSEEL_GLUE_PPC_H_
|
||||
|
||||
#define GLUE_MAX_FPSTACK_SIZE 0 // no stack support
|
||||
#define GLUE_MAX_JMPSIZE 30000 // maximum relative jump size for this arch (if not defined, any jump is possible)
|
||||
|
||||
|
||||
// endOfInstruction is end of jump with relative offset, offset passed in is offset from end of dest instruction.
|
||||
// on PPC the offset needs to be from the start of the instruction (hence +4), and also the low two bits are flags so
|
||||
// we make sure they are clear (they should always be clear, anyway, since we always generate 4 byte instructions)
|
||||
#define GLUE_JMP_SET_OFFSET(endOfInstruction,offset) (((short *)(endOfInstruction))[-1] = ((offset) + 4) & 0xFFFC)
|
||||
|
||||
static const unsigned char GLUE_JMP_NC[] = { 0x48,0, 0, 0, }; // b <offset>
|
||||
|
||||
static const unsigned int GLUE_JMP_IF_P1_Z[]=
|
||||
{
|
||||
0x2f830000, //cmpwi cr7, r3, 0
|
||||
0x419e0000, // beq cr7, offset-bytes-from-startofthisinstruction
|
||||
};
|
||||
static const unsigned int GLUE_JMP_IF_P1_NZ[]=
|
||||
{
|
||||
0x2f830000, //cmpwi cr7, r3, 0
|
||||
0x409e0000, // bne cr7, offset-bytes-from-startofthisinstruction
|
||||
};
|
||||
|
||||
|
||||
#define GLUE_MOV_PX_DIRECTVALUE_SIZE 8
|
||||
static void GLUE_MOV_PX_DIRECTVALUE_GEN(void *b, INT_PTR v, int wv)
|
||||
{
|
||||
static const unsigned short tab[3][2] = {
|
||||
{0x3C60, 0x6063}, // addis r3, r0, hw -- ori r3,r3, lw
|
||||
{0x3DC0, 0x61CE}, // addis r14, r0, hw -- ori r14, r14, lw
|
||||
{0x3DE0, 0x61EF}, // addis r15, r0, hw -- oris r15, r15, lw
|
||||
};
|
||||
unsigned int uv=(unsigned int)v;
|
||||
unsigned short *p=(unsigned short *)b;
|
||||
|
||||
*p++ = tab[wv][0]; // addis rX, r0, hw
|
||||
*p++ = (uv>>16)&0xffff;
|
||||
*p++ = tab[wv][1]; // ori rX, rX, lw
|
||||
*p++ = uv&0xffff;
|
||||
}
|
||||
|
||||
|
||||
// mflr r5
|
||||
// stwu r5, -16(r1)
|
||||
const static unsigned int GLUE_FUNC_ENTER[2] = { 0x7CA802A6, 0x94A1FFF0 };
|
||||
#define GLUE_FUNC_ENTER_SIZE 8
|
||||
|
||||
// lwz r5, 0(r1)
|
||||
// addi r1, r1, 16
|
||||
// mtlr r5
|
||||
const static unsigned int GLUE_FUNC_LEAVE[3] = { 0x80A10000, 0x38210010, 0x7CA803A6 };
|
||||
#define GLUE_FUNC_LEAVE_SIZE 12
|
||||
|
||||
const static unsigned int GLUE_RET[]={0x4E800020}; // blr
|
||||
|
||||
static int GLUE_RESET_WTP(unsigned char *out, void *ptr)
|
||||
{
|
||||
const static unsigned int GLUE_SET_WTP_FROM_R17=0x7E308B78; // mr r16 (dest), r17 (src)
|
||||
if (out) memcpy(out,&GLUE_SET_WTP_FROM_R17,sizeof(GLUE_SET_WTP_FROM_R17));
|
||||
return sizeof(GLUE_SET_WTP_FROM_R17);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// stwu r3, -16(r1)
|
||||
const static unsigned int GLUE_PUSH_P1[1]={ 0x9461FFF0};
|
||||
|
||||
|
||||
#define GLUE_POP_PX_SIZE 8
|
||||
static void GLUE_POP_PX(void *b, int wv)
|
||||
{
|
||||
static const unsigned int tab[3] ={
|
||||
0x80610000, // lwz r3, 0(r1)
|
||||
0x81c10000, // lwz r14, 0(r1)
|
||||
0x81e10000, // lwz r15, 0(r1)
|
||||
};
|
||||
((unsigned int *)b)[0] = tab[wv];
|
||||
((unsigned int *)b)[1] = 0x38210010; // addi r1,r1, 16
|
||||
}
|
||||
|
||||
#define GLUE_SET_PX_FROM_P1_SIZE 4
|
||||
static void GLUE_SET_PX_FROM_P1(void *b, int wv)
|
||||
{
|
||||
static const unsigned int tab[3]={
|
||||
0x7c631b78, // never used: mr r3, r3
|
||||
0x7c6e1b78, // mr r14, r3
|
||||
0x7c6f1b78, // mr r15, r3
|
||||
};
|
||||
*(unsigned int *)b = tab[wv];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// lfd f2, 0(r3)
|
||||
// stfdu f2, -16(r1)
|
||||
static const unsigned int GLUE_PUSH_P1PTR_AS_VALUE[] = { 0xC8430000, 0xDC41FFF0 };
|
||||
|
||||
static int GLUE_POP_VALUE_TO_ADDR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
// lfd f2, 0(r1)
|
||||
// addi r1,r1,16
|
||||
// GLUE_MOV_PX_DIRECTVALUE_GEN / GLUE_MOV_PX_DIRECTVALUE_SIZE (r3)
|
||||
// stfd f2, 0(r3)
|
||||
if (buf)
|
||||
{
|
||||
unsigned int *bufptr = (unsigned int *)buf;
|
||||
*bufptr++ = 0xC8410000;
|
||||
*bufptr++ = 0x38210010;
|
||||
GLUE_MOV_PX_DIRECTVALUE_GEN(bufptr, (INT_PTR)destptr,0);
|
||||
bufptr += GLUE_MOV_PX_DIRECTVALUE_SIZE/4;
|
||||
*bufptr++ = 0xd8430000;
|
||||
}
|
||||
return 2*4 + GLUE_MOV_PX_DIRECTVALUE_SIZE + 4;
|
||||
}
|
||||
|
||||
static int GLUE_COPY_VALUE_AT_P1_TO_PTR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
// lfd f2, 0(r3)
|
||||
// GLUE_MOV_PX_DIRECTVALUE_GEN / GLUE_MOV_PX_DIRECTVALUE_SIZE (r3)
|
||||
// stfd f2, 0(r3)
|
||||
|
||||
if (buf)
|
||||
{
|
||||
unsigned int *bufptr = (unsigned int *)buf;
|
||||
*bufptr++ = 0xc8430000;
|
||||
GLUE_MOV_PX_DIRECTVALUE_GEN(bufptr, (INT_PTR)destptr,0);
|
||||
bufptr += GLUE_MOV_PX_DIRECTVALUE_SIZE/4;
|
||||
*bufptr++ = 0xd8430000;
|
||||
}
|
||||
|
||||
return 4 + GLUE_MOV_PX_DIRECTVALUE_SIZE + 4;
|
||||
}
|
||||
|
||||
|
||||
static void GLUE_CALL_CODE(INT_PTR bp, INT_PTR cp, INT_PTR rt)
|
||||
{
|
||||
static const double consttab[] = {
|
||||
NSEEL_CLOSEFACTOR,
|
||||
4503601774854144.0 /* 0x43300000, 0x80000000, used for integer conversion*/,
|
||||
};
|
||||
// we could have r18 refer to the current user-stack pointer, someday, perhaps
|
||||
__asm__(
|
||||
"subi r1, r1, 128\n"
|
||||
"stfd f31, 8(r1)\n"
|
||||
"stfd f30, 16(r1)\n"
|
||||
"stmw r13, 32(r1)\n"
|
||||
"mtctr %0\n"
|
||||
"mr r17, %1\n"
|
||||
"mr r13, %2\n"
|
||||
"lfd f31, 0(%3)\n"
|
||||
"lfd f30, 8(%3)\n"
|
||||
"subi r17, r17, 8\n"
|
||||
"mflr r0\n"
|
||||
"stw r0, 24(r1)\n"
|
||||
"bctrl\n"
|
||||
"lwz r0, 24(r1)\n"
|
||||
"mtlr r0\n"
|
||||
"lmw r13, 32(r1)\n"
|
||||
"lfd f31, 8(r1)\n"
|
||||
"lfd f30, 16(r1)\n"
|
||||
"addi r1, r1, 128\n"
|
||||
::"r" (cp), "r" (bp), "r" (rt), "r" (consttab));
|
||||
};
|
||||
|
||||
static unsigned char *EEL_GLUE_set_immediate(void *_p, INT_PTR newv)
|
||||
{
|
||||
// 64 bit ppc would take some work
|
||||
unsigned int *p=(unsigned int *)_p;
|
||||
while ((p[0]&0x0000FFFF) != 0x0000dead &&
|
||||
(p[1]&0x0000FFFF) != 0x0000beef) p++;
|
||||
p[0] = (p[0]&0xFFFF0000) | (((newv)>>16)&0xFFFF);
|
||||
p[1] = (p[1]&0xFFFF0000) | ((newv)&0xFFFF);
|
||||
|
||||
return (unsigned char *)(p+1);
|
||||
}
|
||||
|
||||
#define GLUE_SET_PX_FROM_WTP_SIZE sizeof(int)
|
||||
static void GLUE_SET_PX_FROM_WTP(void *b, int wv)
|
||||
{
|
||||
static const unsigned int tab[3]={
|
||||
0x7e038378, // mr r3, r16
|
||||
0x7e0e8378, // mr r14, r16
|
||||
0x7e0f8378, // mr r15, r16
|
||||
};
|
||||
*(unsigned int *)b = tab[wv];
|
||||
}
|
||||
static int GLUE_POP_FPSTACK_TO_PTR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
// set r3 to destptr
|
||||
// stfd f1, 0(r3)
|
||||
if (buf)
|
||||
{
|
||||
unsigned int *bufptr = (unsigned int *)buf;
|
||||
GLUE_MOV_PX_DIRECTVALUE_GEN(bufptr, (INT_PTR)destptr,0);
|
||||
bufptr += GLUE_MOV_PX_DIRECTVALUE_SIZE/4;
|
||||
|
||||
*bufptr++ = 0xD8230000; // stfd f1, 0(r3)
|
||||
}
|
||||
return GLUE_MOV_PX_DIRECTVALUE_SIZE + sizeof(int);
|
||||
}
|
||||
#define GLUE_POP_FPSTACK_SIZE 0
|
||||
static const unsigned int GLUE_POP_FPSTACK[1] = { 0 }; // no need to pop, not a stack
|
||||
|
||||
static const unsigned int GLUE_POP_FPSTACK_TOSTACK[] = {
|
||||
0xdc21fff0, // stfdu f1, -16(r1)
|
||||
};
|
||||
|
||||
static const unsigned int GLUE_POP_FPSTACK_TO_WTP[] = {
|
||||
0xdc300008, // stfdu f1, 8(r16)
|
||||
};
|
||||
|
||||
#define GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE 4
|
||||
static void GLUE_PUSH_VAL_AT_PX_TO_FPSTACK(void *b, int wv)
|
||||
{
|
||||
static const unsigned int tab[3] = {
|
||||
0xC8230000, // lfd f1, 0(r3)
|
||||
0xC82E0000, // lfd f1, 0(r14)
|
||||
0xC82F0000, // lfd f1, 0(r15)
|
||||
};
|
||||
*(unsigned int *)b = tab[wv];
|
||||
}
|
||||
|
||||
#define GLUE_POP_FPSTACK_TO_WTP_TO_PX_SIZE (sizeof(GLUE_POP_FPSTACK_TO_WTP) + GLUE_SET_PX_FROM_WTP_SIZE)
|
||||
static void GLUE_POP_FPSTACK_TO_WTP_TO_PX(unsigned char *buf, int wv)
|
||||
{
|
||||
memcpy(buf,GLUE_POP_FPSTACK_TO_WTP,sizeof(GLUE_POP_FPSTACK_TO_WTP));
|
||||
GLUE_SET_PX_FROM_WTP(buf + sizeof(GLUE_POP_FPSTACK_TO_WTP),wv); // ppc preincs the WTP, so we do this after
|
||||
};
|
||||
|
||||
static unsigned int GLUE_POP_STACK_TO_FPSTACK[1] = { 0 }; // todo
|
||||
|
||||
|
||||
static const unsigned int GLUE_SET_P1_Z[] = { 0x38600000 }; // li r3, 0
|
||||
static const unsigned int GLUE_SET_P1_NZ[] = { 0x38600001 }; // li r3, 1
|
||||
|
||||
|
||||
static void *GLUE_realAddress(void *fn, int *size)
|
||||
{
|
||||
// magic numbers: mr r0,r0 ; mr r1,r1 ; mr r2, r2
|
||||
static const unsigned char sig[12] = { 0x7c, 0x00, 0x03, 0x78, 0x7c, 0x21, 0x0b, 0x78, 0x7c, 0x42, 0x13, 0x78 };
|
||||
unsigned char *p = (unsigned char *)fn;
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p+=4;
|
||||
p+=sizeof(sig);
|
||||
fn = p;
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p+=4;
|
||||
*size = p - (unsigned char *)fn;
|
||||
return fn;
|
||||
}
|
||||
|
||||
#define GLUE_STORE_P1_TO_STACK_AT_OFFS_SIZE(x) 4
|
||||
static void GLUE_STORE_P1_TO_STACK_AT_OFFS(void *b, int offs)
|
||||
{
|
||||
// limited to 32k offset
|
||||
*(unsigned int *)b = 0x90610000 + (offs&0xffff);
|
||||
}
|
||||
|
||||
#define GLUE_MOVE_PX_STACKPTR_SIZE 4
|
||||
static void GLUE_MOVE_PX_STACKPTR_GEN(void *b, int wv)
|
||||
{
|
||||
static const unsigned int tab[3] =
|
||||
{
|
||||
0x7c230b78, // mr r3, r1
|
||||
0x7c2e0b78, // mr r14, r1
|
||||
0x7c2f0b78, // mr r15, r1
|
||||
};
|
||||
* (unsigned int *)b = tab[wv];
|
||||
}
|
||||
|
||||
#define GLUE_MOVE_STACK_SIZE 4
|
||||
static void GLUE_MOVE_STACK(void *b, int amt)
|
||||
{
|
||||
// this should be updated to allow for more than 32k moves, but no real need
|
||||
((unsigned int *)b)[0] = 0x38210000 + (amt&0xffff); // addi r1,r1, amt
|
||||
}
|
||||
|
||||
|
||||
|
||||
// end of ppc
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user