Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dynasm/dasm_ppc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,11 @@ map_op = {
addic_3 = "30000000RRI",
["addic._3"] = "34000000RRI",
addi_3 = "38000000RR0I",
addil_3 = "38000000RR0J",
li_2 = "38000000RI",
la_2 = "38000000RD",
addis_3 = "3c000000RR0I",
addisl_3 = "3c000000RR0J",
lis_2 = "3c000000RI",
lus_2 = "3c000000RU",
bc_3 = "40000000AAK",
Expand Down Expand Up @@ -842,6 +844,9 @@ map_op = {
srdi_3 = op_alias("rldicl_4", function(p)
p[4] = p[3]; p[3] = "64-("..p[3]..")"
end),
["srdi._3"] = op_alias("rldicl._4", function(p)
p[4] = p[3]; p[3] = "64-("..p[3]..")"
end),
clrldi_3 = op_alias("rldicl_4", function(p)
p[4] = p[3]; p[3] = "0"
end),
Expand Down
11 changes: 10 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,16 @@ ifeq (ppc,$(TARGET_LJARCH))
DASM_AFLAGS+= -D GPR64
endif
ifeq (PS3,$(TARGET_SYS))
DASM_AFLAGS+= -D PPE -D TOC
DASM_AFLAGS+= -D PPE
endif
ifneq (,$(findstring LJ_ARCH_PPC_OPD 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D OPD
endif
ifneq (,$(findstring LJ_ARCH_PPC_OPDENV 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D OPDENV
endif
ifneq (,$(findstring LJ_ARCH_PPC_ELFV2 1,$(TARGET_TESTARCH)))
DASM_AFLAGS+= -D ELFV2
endif
endif
endif
Expand Down
9 changes: 8 additions & 1 deletion src/host/buildvm_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,11 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n,
#else
#define TOCPREFIX ""
#endif
if ((ins >> 26) == 16) {
if ((ins >> 26) == 14) {
fprintf(ctx->fp, "\taddi %d,%d,%s\n", (ins >> 21) & 31, (ins >> 16) & 31, sym);
} else if ((ins >> 26) == 15) {
fprintf(ctx->fp, "\taddis %d,%d,%s\n", (ins >> 21) & 31, (ins >> 16) & 31, sym);
} else if ((ins >> 26) == 16) {
fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n",
(ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym);
} else if ((ins >> 26) == 18) {
Expand Down Expand Up @@ -290,6 +294,9 @@ void emit_asm(BuildCtx *ctx)
int i, rel;

fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
#if LJ_ARCH_PPC_ELFV2
fprintf(ctx->fp, "\t.abiversion 2\n");
#endif
fprintf(ctx->fp, "\t.text\n");
emit_asm_align(ctx, 4);

Expand Down
15 changes: 11 additions & 4 deletions src/lj_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,18 @@
#if LJ_TARGET_CONSOLE
#define LJ_ARCH_PPC32ON64 1
#define LJ_ARCH_NOFFI 1
#if LJ_TARGET_PS3
#define LJ_ARCH_PPC_OPD 1
#endif
#elif LJ_ARCH_BITS == 64
#error "No support for PPC64"
#define LJ_ARCH_PPC32ON64 1
#define LJ_ARCH_NOJIT 1 /* NYI */
#if _CALL_ELF == 2
#define LJ_ARCH_PPC_ELFV2 1
#else
#define LJ_ARCH_PPC_OPD 1
#define LJ_ARCH_PPC_OPDENV 1
#endif
#endif

#if _ARCH_PWR7
Expand Down Expand Up @@ -482,9 +492,6 @@
#error "No support for ILP32 model on ARM64"
#endif
#elif LJ_TARGET_PPC
#if defined(_LITTLE_ENDIAN) && (!defined(_BYTE_ORDER) || (_BYTE_ORDER == _LITTLE_ENDIAN))
#error "No support for little-endian PPC32"
#endif
#if defined(__NO_FPRS__) && !defined(_SOFT_FLOAT)
#error "No support for PPC/e500 anymore (use LuaJIT 2.0)"
#endif
Expand Down
166 changes: 165 additions & 1 deletion src/lj_ccall.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,21 +370,97 @@
#elif LJ_TARGET_PPC
/* -- PPC calling conventions --------------------------------------------- */

#if LJ_ARCH_BITS == 64

#if LJ_ARCH_PPC_ELFV2

#define CCALL_HANDLE_STRUCTRET \
if (sz > 16 && ccall_classify_fp(cts, ctr) <= 0) { \
cc->retref = 1; /* Return by reference. */ \
cc->gpr[ngpr++] = (GPRArg)dp; \
}

#define CCALL_HANDLE_STRUCTRET2 \
int isfp = ccall_classify_fp(cts, ctr); \
int i; \
if (isfp == FTYPE_FLOAT) { \
for (i = 0; i < ctr->size / 4; i++) \
((float *)dp)[i] = cc->fpr[i]; \
} else if (isfp == FTYPE_DOUBLE) { \
for (i = 0; i < ctr->size / 8; i++) \
((double *)dp)[i] = cc->fpr[i]; \
} else { \
if (ctr->size < 8 && LJ_BE) { \
sp += 8 - ctr->size; \
} \
memcpy(dp, sp, ctr->size); \
}

#else

#define CCALL_HANDLE_STRUCTRET \
cc->retref = 1; /* Return all structs by reference. */ \
cc->gpr[ngpr++] = (GPRArg)dp;

#endif

#define CCALL_HANDLE_COMPLEXRET \
/* Complex values are returned in 2 or 4 GPRs. */ \
cc->retref = 0;

#define CCALL_HANDLE_STRUCTARG

#define CCALL_HANDLE_COMPLEXRET2 \
memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */
if (ctr->size == 2*sizeof(float)) { /* Copy complex float from FPRs. */ \
((float *)dp)[0] = cc->fpr[0]; \
((float *)dp)[1] = cc->fpr[1]; \
} else { /* Copy complex double from FPRs. */ \
((double *)dp)[0] = cc->fpr[0]; \
((double *)dp)[1] = cc->fpr[1]; \
}

#define CCALL_HANDLE_COMPLEXARG \
isfp = 1; \
if (d->size == sizeof(float) * 2) { \
d = ctype_get(cts, CTID_COMPLEX_DOUBLE); \
isf32 = 1; \
}

#define CCALL_HANDLE_REGARG \
if (isfp && d->size == sizeof(float)) { \
d = ctype_get(cts, CTID_DOUBLE); \
isf32 = 1; \
} \
if (ngpr < maxgpr) { \
dp = &cc->gpr[ngpr]; \
ngpr += n; \
if (ngpr > maxgpr) { \
nsp += ngpr - 8; \
ngpr = 8; \
if (nsp > CCALL_MAXSTACK) { \
goto err_nyi; \
} \
} \
goto done; \
}

#else

#define CCALL_HANDLE_STRUCTRET \
cc->retref = 1; /* Return all structs by reference. */ \
cc->gpr[ngpr++] = (GPRArg)dp;

#define CCALL_HANDLE_COMPLEXRET \
/* Complex values are returned in 2 or 4 GPRs. */ \
cc->retref = 0;

#define CCALL_HANDLE_STRUCTARG \
rp = cdataptr(lj_cdata_new(cts, did, sz)); \
sz = CTSIZE_PTR; /* Pass all structs by reference. */

#define CCALL_HANDLE_COMPLEXRET2 \
memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */

#define CCALL_HANDLE_COMPLEXARG \
/* Pass complex by value in 2 or 4 GPRs. */

Expand Down Expand Up @@ -419,6 +495,8 @@
}
#endif

#endif

#if !LJ_ABI_SOFTFP
#define CCALL_HANDLE_RET \
if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
Expand Down Expand Up @@ -846,6 +924,50 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct)

#endif

/* -- PowerPC64 ELFv2 ABI struct classification ------------------- */

#if LJ_ARCH_PPC_ELFV2

#define FTYPE_FLOAT 1
#define FTYPE_DOUBLE 2

static unsigned int ccall_classify_fp(CTState *cts, CType *ct) {
if (ctype_isfp(ct->info)) {
if (ct->size == sizeof(float))
return FTYPE_FLOAT;
else
return FTYPE_DOUBLE;
} else if (ctype_iscomplex(ct->info)) {
if (ct->size == sizeof(float) * 2)
return FTYPE_FLOAT;
else
return FTYPE_DOUBLE;
} else if (ctype_isstruct(ct->info)) {
int res = -1;
int sz = ct->size;
while (ct->sib) {
ct = ctype_get(cts, ct->sib);
if (ctype_isfield(ct->info)) {
int sub = ccall_classify_fp(cts, ctype_rawchild(cts, ct));
if (res == -1)
res = sub;
if (sub != -1 && sub != res)
return 0;
} else if (ctype_isbitfield(ct->info) ||
ctype_isxattrib(ct->info, CTA_SUBTYPE)) {
return 0;
}
}
if (res > 0 && sz > res * 4 * 8)
return 0;
return res;
} else {
return 0;
}
}

#endif

/* -- MIPS64 ABI struct classification ---------------------------- */

#if LJ_TARGET_MIPS64
Expand Down Expand Up @@ -1020,6 +1142,9 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
CTSize sz;
MSize n, isfp = 0, isva = 0;
void *dp, *rp = NULL;
#if LJ_TARGET_PPC && LJ_ARCH_BITS == 64
int isf32 = 0;
#endif

#if LJ_TARGET_S390X
uint32_t onstack = 0;
Expand Down Expand Up @@ -1083,7 +1208,37 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
*(void **)dp = rp;
dp = rp;
}
#if LJ_TARGET_PPC && LJ_ARCH_BITS == 64 && LJ_BE
if (ctype_isstruct(d->info) && sz < CTSIZE_PTR) {
dp = (char *)dp + (CTSIZE_PTR - sz);
}
#endif
lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
#if LJ_TARGET_PPC && LJ_ARCH_BITS == 64
if (isfp) {
int i;
for (i = 0; i < d->size / 8 && nfpr < CCALL_NARG_FPR; i++)
cc->fpr[nfpr++] = ((double *)dp)[i];
}
if (isf32) {
int i;
for (i = 0; i < d->size / 8; i++)
((float *)dp)[i*2] = ((double *)dp)[i];
}
#endif
#if LJ_ARCH_PPC_ELFV2
if (ctype_isstruct(d->info)) {
isfp = ccall_classify_fp(cts, d);
int i;
if (isfp == FTYPE_FLOAT) {
for (i = 0; i < d->size / 4 && nfpr < CCALL_NARG_FPR; i++)
cc->fpr[nfpr++] = ((float *)dp)[i];
} else if (isfp == FTYPE_DOUBLE) {
for (i = 0; i < d->size / 8 && nfpr < CCALL_NARG_FPR; i++)
cc->fpr[nfpr++] = ((double *)dp)[i];
}
}
#endif
/* Extend passed integers to 32 bits at least. */
if (ctype_isinteger_or_bool(d->info) && d->size < 4) {
if (d->info & CTF_UNSIGNED)
Expand All @@ -1097,6 +1252,15 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
if (isfp && d->size == sizeof(float))
((float *)dp)[1] = ((float *)dp)[0]; /* Floats occupy high slot. */
#endif
#if LJ_TARGET_PPC && LJ_ARCH_BITS == 64
if ((ctype_isinteger_or_bool(d->info) || ctype_isenum(d->info))
&& d->size <= 4) {
if (d->info & CTF_UNSIGNED)
*(uint64_t *)dp = (uint64_t)*(uint32_t *)dp;
else
*(int64_t *)dp = (int64_t)*(int32_t *)dp;
}
#endif
#if LJ_TARGET_MIPS64 || (LJ_TARGET_ARM64 && LJ_BE)
if ((ctype_isinteger_or_bool(d->info) || ctype_isenum(d->info)
#if LJ_TARGET_MIPS64
Expand Down
13 changes: 13 additions & 0 deletions src/lj_ccall.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,23 @@ typedef union FPRArg {
#elif LJ_TARGET_PPC

#define CCALL_NARG_GPR 8
#if LJ_ARCH_BITS == 64
#define CCALL_NARG_FPR 13
#if LJ_ARCH_PPC_ELFV2
#define CCALL_NRET_GPR 2
#define CCALL_NRET_FPR 8
#define CCALL_SPS_EXTRA 14
#else
#define CCALL_NRET_GPR 1
#define CCALL_NRET_FPR 2
#define CCALL_SPS_EXTRA 16
#endif
#else
#define CCALL_NARG_FPR (LJ_ABI_SOFTFP ? 0 : 8)
#define CCALL_NRET_GPR 4 /* For complex double. */
#define CCALL_NRET_FPR (LJ_ABI_SOFTFP ? 0 : 1)
#define CCALL_SPS_EXTRA 4
#endif
#define CCALL_SPS_FREE 0

typedef intptr_t GPRArg;
Expand Down
Loading