#if LJ_TARGET_X86
/* -- x86 calling conventions --------------------------------------------- */
+#define CCALL_PUSH(arg) \
+ *(GPRArg *)((uint8_t *)cc->stack + nsp) = (GPRArg)(arg), nsp += CTSIZE_PTR
+
#if LJ_ABI_WIN
#define CCALL_HANDLE_STRUCTRET \
/* Return structs bigger than 8 by reference (on stack only). */ \
cc->retref = (sz > 8); \
- if (cc->retref) cc->stack[nsp++] = (GPRArg)dp;
+ if (cc->retref) CCALL_PUSH(dp);
#define CCALL_HANDLE_COMPLEXRET CCALL_HANDLE_STRUCTRET
if (ngpr < maxgpr) \
cc->gpr[ngpr++] = (GPRArg)dp; \
else \
- cc->stack[nsp++] = (GPRArg)dp; \
+ CCALL_PUSH(dp); \
} else { /* Struct with single FP field ends up in FPR. */ \
cc->resx87 = ccall_classify_struct(cts, ctr); \
}
if (ngpr < maxgpr) \
cc->gpr[ngpr++] = (GPRArg)dp; \
else \
- cc->stack[nsp++] = (GPRArg)dp;
+ CCALL_PUSH(dp);
#endif
if (ngpr < maxgpr) \
cc->gpr[ngpr++] = (GPRArg)dp; \
else \
- cc->stack[nsp++] = (GPRArg)dp; \
+ CCALL_PUSH(dp); \
}
#endif
if (ngpr < maxgpr) { \
dp = &cc->gpr[ngpr]; \
if (ngpr + n > maxgpr) { \
- nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \
- if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \
+ nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \
+ if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \
ngpr = maxgpr; \
} else { \
ngpr += n; \
if (ngpr < maxgpr) { \
dp = &cc->gpr[ngpr]; \
if (ngpr + n > maxgpr) { \
- nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \
- if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \
+ nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \
+ if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \
ngpr = maxgpr; \
} else { \
ngpr += n; \
if (ngpr < maxgpr) { \
dp = &cc->gpr[ngpr]; \
if (ngpr + n > maxgpr) { \
- nsp += ngpr + n - maxgpr; /* Assumes contiguous gpr/stack fields. */ \
- if (nsp > CCALL_MAXSTACK) goto err_nyi; /* Too many arguments. */ \
+ nsp += (ngpr + n - maxgpr) * CTSIZE_PTR; /* Assumes contiguous gpr/stack fields. */ \
+ if (nsp > CCALL_SIZE_STACK) goto err_nyi; /* Too many arguments. */ \
ngpr = maxgpr; \
} else { \
ngpr += n; \
lj_cconv_ct_tv(cts, d, (uint8_t *)dp, o, CCF_ARG(narg));
if (ccall_struct_reg(cc, cts, dp, rcl)) {
/* Register overflow? Pass on stack. */
- MSize nsp = cc->nsp, n = rcl[1] ? 2 : 1;
- if (nsp + n > CCALL_MAXSTACK) return 1; /* Too many arguments. */
- cc->nsp = nsp + n;
- memcpy(&cc->stack[nsp], dp, n*CTSIZE_PTR);
+ MSize nsp = cc->nsp, sz = rcl[1] ? 2*CTSIZE_PTR : CTSIZE_PTR;
+ if (nsp + sz > CCALL_SIZE_STACK)
+ return 1; /* Too many arguments. */
+ cc->nsp = nsp + sz;
+ memcpy((uint8_t *)cc->stack + nsp, dp, sz);
}
return 0; /* Ok. */
}
} else {
sz = CTSIZE_PTR;
}
- sz = (sz + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1);
- n = sz / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */
+ n = (sz + CTSIZE_PTR-1) / CTSIZE_PTR; /* Number of GPRs or stack slots needed. */
CCALL_HANDLE_REGARG /* Handle register arguments. */
/* Otherwise pass argument on stack. */
- if (CCALL_ALIGN_STACKARG && !rp && (d->info & CTF_ALIGN) > CTALIGN_PTR) {
- MSize align = (1u << ctype_align(d->info-CTALIGN_PTR)) -1;
- nsp = (nsp + align) & ~align; /* Align argument on stack. */
+ if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */
+ MSize align = (1u << ctype_align(d->info)) - 1;
+ if (rp)
+ align = CTSIZE_PTR-1;
+ nsp = (nsp + align) & ~align;
}
- if (nsp + n > CCALL_MAXSTACK) { /* Too many arguments. */
+ dp = ((uint8_t *)cc->stack) + nsp;
+ nsp += n * CTSIZE_PTR;
+ if (nsp > CCALL_SIZE_STACK) { /* Too many arguments. */
err_nyi:
lj_err_caller(L, LJ_ERR_FFI_NYICALL);
}
- dp = &cc->stack[nsp];
- nsp += n;
isva = 0;
done:
#if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP)
cc->nfpr = nfpr; /* Required for vararg functions. */
#endif
- cc->nsp = nsp;
- cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA)*CTSIZE_PTR;
- if (nsp > CCALL_SPS_FREE)
- cc->spadj += (((nsp-CCALL_SPS_FREE)*CTSIZE_PTR + 15u) & ~15u);
+ cc->nsp = (nsp + CTSIZE_PTR-1) & ~(CTSIZE_PTR-1);
+ cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA) * CTSIZE_PTR;
+ if (cc->nsp > CCALL_SPS_FREE * CTSIZE_PTR)
+ cc->spadj += (((cc->nsp - CCALL_SPS_FREE * CTSIZE_PTR) + 15u) & ~15u);
return gcsteps;
}
LJ_STATIC_ASSERT(CCALL_NUM_GPR <= CCALL_MAX_GPR);
LJ_STATIC_ASSERT(CCALL_NUM_FPR <= CCALL_MAX_FPR);
-#define CCALL_MAXSTACK 32
+#define CCALL_NUM_STACK 31
+#define CCALL_SIZE_STACK (CCALL_NUM_STACK * CTSIZE_PTR)
/* -- C call state -------------------------------------------------------- */
typedef LJ_ALIGN(CCALL_ALIGN_CALLSTATE) struct CCallState {
void (*func)(void); /* Pointer to called function. */
uint32_t spadj; /* Stack pointer adjustment. */
- uint8_t nsp; /* Number of stack slots. */
+ uint8_t nsp; /* Number of bytes on stack. */
uint8_t retref; /* Return value by reference. */
#if LJ_TARGET_X64
uint8_t ngpr; /* Number of arguments in GPRs. */
FPRArg fpr[CCALL_NUM_FPR]; /* Arguments/results in FPRs. */
#endif
GPRArg gpr[CCALL_NUM_GPR]; /* Arguments/results in GPRs. */
- GPRArg stack[CCALL_MAXSTACK]; /* Stack slots. */
+ GPRArg stack[CCALL_NUM_STACK]; /* Stack slots. */
} CCallState;
/* -- C call handling ----------------------------------------------------- */
|.endif
| mov r11, sp
| sub sp, sp, CARG1 // Readjust stack.
- | subs CARG2, CARG2, #1
+ | subs CARG2, CARG2, #4
|.if HFABI
| vldm RB, {d0-d7}
|.endif
| ldr RB, CCSTATE->func
| bmi >2
|1: // Copy stack slots.
- | ldr CARG4, [CARG3, CARG2, lsl #2]
- | str CARG4, [sp, CARG2, lsl #2]
- | subs CARG2, CARG2, #1
+ | ldr CARG4, [CARG3, CARG2]
+ | str CARG4, [sp, CARG2]
+ | subs CARG2, CARG2, #4
| bpl <1
|2:
| ldrd CARG12, CCSTATE->gpr[0]