#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 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