diff --git a/src/lj_ccall.c b/src/lj_ccall.c index eb7c1ee0..da8578ea 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -380,6 +380,37 @@ #define CCALL_HANDLE_COMPLEXARG \ /* Pass complex by value in 2 or 4 GPRs. */ +#if LJ_ARCH_PPC64 +#define CCALL_HANDLE_REGARG \ + if (isva) { /* only GPRs will be used on C ellipsis operator */ \ + goto gpr; \ + } \ + else { \ + if (isfp) { /* Try to pass argument in FPRs. */ \ + if (nfpr + 1 <= CCALL_NARG_FPR) { \ + dp = &cc->fpr[nfpr]; \ + nfpr += 1; \ + ngpr += 1; /* align GPRs */ \ + d = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \ + goto done; \ + } \ + } else { /* Try to pass argument in GPRs. */ \ + gpr: \ + if (n > 1) { \ + lua_assert(n == 2 || n == 4); /* int64_t or complex (float). */ \ + if (ctype_isinteger(d->info)) \ + ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \ + else if (ngpr + n > maxgpr) \ + ngpr = maxgpr; /* Prevent reordering. */ \ + } \ + if (ngpr + n <= maxgpr) { \ + dp = &cc->gpr[ngpr]; \ + ngpr += n; \ + goto done; \ + } \ + } \ + } +#else /* 32 bits */ #define CCALL_HANDLE_REGARG \ if (isfp) { /* Try to pass argument in FPRs. */ \ if (nfpr + 1 <= CCALL_NARG_FPR) { \ @@ -402,6 +433,7 @@ goto done; \ } \ } +#endif #define CCALL_HANDLE_RET \ if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ diff --git a/src/lj_ccall.h b/src/lj_ccall.h index a77afae3..e85f0c4f 100644 --- a/src/lj_ccall.h +++ b/src/lj_ccall.h @@ -85,12 +85,21 @@ typedef union FPRArg { #elif LJ_TARGET_PPC +#if LJ_ARCH_PPC64 +#define CCALL_NARG_GPR 8 +#define CCALL_NARG_FPR 8 +#define CCALL_NRET_GPR 4 /* For complex double. */ +#define CCALL_NRET_FPR 1 +#define CCALL_SPS_EXTRA 14 +#define CCALL_SPS_FREE 0 +#else #define CCALL_NARG_GPR 8 #define CCALL_NARG_FPR 8 #define CCALL_NRET_GPR 4 /* For complex double. */ #define CCALL_NRET_FPR 1 #define CCALL_SPS_EXTRA 4 #define CCALL_SPS_FREE 0 +#endif typedef intptr_t GPRArg; typedef double FPRArg; diff --git a/src/lj_ccallback.c b/src/lj_ccallback.c index 43c29e41..abe097e1 100644 --- a/src/lj_ccallback.c +++ b/src/lj_ccallback.c @@ -61,7 +61,11 @@ static MSize CALLBACK_OFS2SLOT(MSize ofs) #elif LJ_TARGET_PPC +#if LJ_ARCH_PPC64 +#define CALLBACK_MCODE_HEAD 40 +#else /* PPC 32bits */ #define CALLBACK_MCODE_HEAD 24 +#endif #elif LJ_TARGET_MIPS @@ -189,10 +193,21 @@ static void callback_mcode_init(global_State *g, uint32_t *page) uint32_t *p = 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 */ + *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); +#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); *p++ = PPCI_BCTR; for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) { diff --git a/src/lj_target_ppc.h b/src/lj_target_ppc.h index bbf22390..c6e0ef67 100644 --- a/src/lj_target_ppc.h +++ b/src/lj_target_ppc.h @@ -1,5 +1,5 @@ /* -** Definitions for PPC CPUs. +** Definitions for PPC/PPC64 CPUs. ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h */ @@ -131,6 +131,8 @@ static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p, uint32_t exitno) #define PPCF_C(r) ((r) << 6) #define PPCF_MB(n) ((n) << 6) #define PPCF_ME(n) ((n) << 1) +#define PPCF_SH(n) ((((n) & 31) << (11+1)) | (((n) & 32) >> (5-1))) +#define PPCF_M6(n) ((((n) & 31) << (5+1)) | (((n) & 32) << (11-5))) #define PPCF_Y 0x00200000 #define PPCF_DOT 0x00000001 @@ -200,6 +202,13 @@ typedef enum PPCIns { PPCI_RLWINM = 0x54000000, PPCI_RLWIMI = 0x50000000, + PPCI_RLDICL = 0x78000000, + PPCI_RLDICR = 0x78000004, + PPCI_RLDIC = 0x78000008, + PPCI_RLDIMI = 0x7800000c, + PPCI_RLDCL = 0x78000010, + PPCI_RLDCR = 0x78000012, + PPCI_B = 0x48000000, PPCI_BL = 0x48000001, PPCI_BC = 0x40800000,