diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c index bc560aea..860272a0 100644 --- a/src/lj_ccallback.c +++ b/src/lj_ccallback.c @@ -198,21 +198,23 @@ static void callback_mcode_init(global_State *g, uint32_t *page) void *target = (void *)lj_vm_ffi_callback; MSize slot; #if LJ_ARCH_PPC64 - *p++ = PPCI_LI | PPCF_T(RID_TMP) | ((((intptr_t)target) >> 32) & 0xffff); - *p++ = PPCI_LI | PPCF_T(RID_R12) | ((((intptr_t)g) >> 32) & 0xffff); - *p++ = PPCI_RLDICR | PPCF_T(RID_TMP) | PPCF_A(RID_TMP) | PPCF_SH(32) | PPCF_M6(63-32); /* sldi */ + // Store on R0 the global state and point R12 to the function so TOC is calculated correctly. + *p++ = PPCI_LI | PPCF_T(RID_R12) | ((((intptr_t)target) >> 32) & 0xffff); + *p++ = PPCI_LI | PPCF_T(RID_TMP) | ((((intptr_t)g) >> 32) & 0xffff); *p++ = PPCI_RLDICR | PPCF_T(RID_R12) | PPCF_A(RID_R12) | PPCF_SH(32) | PPCF_M6(63-32); /* sldi */ - *p++ = PPCI_ORIS | PPCF_A(RID_TMP) | PPCF_T(RID_TMP) | ((((intptr_t)target) >> 16) & 0xffff); - *p++ = PPCI_ORIS | PPCF_A(RID_R12) | PPCF_T(RID_R12) | ((((intptr_t)g) >> 16) & 0xffff); - *p++ = PPCI_ORI | PPCF_A(RID_TMP) | PPCF_T(RID_TMP) | (((intptr_t)target) & 0xffff); - *p++ = PPCI_ORI | PPCF_A(RID_R12) | PPCF_T(RID_R12) | (((intptr_t)g) & 0xffff); + *p++ = PPCI_RLDICR | PPCF_T(RID_TMP) | PPCF_A(RID_TMP) | PPCF_SH(32) | PPCF_M6(63-32); /* sldi */ + *p++ = PPCI_ORIS | PPCF_A(RID_R12) | PPCF_T(RID_R12) | ((((intptr_t)target) >> 16) & 0xffff); + *p++ = PPCI_ORIS | PPCF_A(RID_TMP) | PPCF_T(RID_TMP) | ((((intptr_t)g) >> 16) & 0xffff); + *p++ = PPCI_ORI | PPCF_A(RID_R12) | PPCF_T(RID_R12) | (((intptr_t)target) & 0xffff); + *p++ = PPCI_ORI | PPCF_A(RID_TMP) | PPCF_T(RID_TMP) | (((intptr_t)g) & 0xffff); + *p++ = PPCI_MTCTR | PPCF_T(RID_R12); #else /* PPC 32bits */ *p++ = PPCI_LIS | PPCF_T(RID_TMP) | (u32ptr(target) >> 16); *p++ = PPCI_LIS | PPCF_T(RID_R12) | (u32ptr(g) >> 16); *p++ = PPCI_ORI | PPCF_A(RID_TMP)|PPCF_T(RID_TMP) | (u32ptr(target) & 0xffff); *p++ = PPCI_ORI | PPCF_A(RID_R12)|PPCF_T(RID_R12) | (u32ptr(g) & 0xffff); -#endif *p++ = PPCI_MTCTR | PPCF_T(RID_TMP); +#endif *p++ = PPCI_BCTR; for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) { *p++ = PPCI_LI | PPCF_T(RID_R11) | slot; diff --git a/src/vm_ppc64.dasc b/src/vm_ppc64.dasc index 5d15d01a..cd38d544 100644 --- a/src/vm_ppc64.dasc +++ b/src/vm_ppc64.dasc @@ -2286,11 +2286,12 @@ static void build_subroutines(BuildCtx *ctx) |//-- FFI helper functions ----------------------------------------------- |//----------------------------------------------------------------------- | - |// Handler for callback functions. Callback slot number in r11, g in r12. + |// Handler for callback functions. Callback slot number in r11, g in r0. |->vm_ffi_callback: |.if FFI |.type CTSTATE, CTState, PC | pic_code_setup vm_ffi_callback + | mr r12, r0 // Use r12 as saveregs overwrites r0 | saveregs | ld CTSTATE, GL:r12->ctype_state | addi DISPATCH, r12, GG_G2DISP