From d636a3decdf8dc503e707fad8b0e2745c0cabd21 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sat, 16 Apr 2011 23:28:51 +0200 Subject: [PATCH] ARM: Add partial support for FFI. --- src/buildvm_arm.dasc | 36 ++++++++++++++++++++++++++++++++++-- src/lj_arch.h | 2 +- src/lj_ccall.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/lj_ccall.h | 12 +++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc index 3e3fb23c..c12b4da8 100644 --- a/src/buildvm_arm.dasc +++ b/src/buildvm_arm.dasc @@ -1873,7 +1873,32 @@ static void build_subroutines(BuildCtx *ctx) | |->vm_ffi_call: #if LJ_HASFFI - | NYI + | .type CCSTATE, CCallState, r4 + | push {CCSTATE, r5, r11, lr} + | mov CCSTATE, CARG1 + | ldr CARG1, CCSTATE:CARG1->spadj + | ldrb CARG2, CCSTATE->nsp + | add CARG3, CCSTATE, #offsetof(CCallState, stack) + | mov r11, sp + | sub sp, sp, CARG1 // Readjust stack. + | subs CARG2, CARG2, #1 + | 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 + | bpl <1 + |2: + | ldr CARG1, CCSTATE->gpr[0] + | ldr CARG2, CCSTATE->gpr[1] + | ldr CARG3, CCSTATE->gpr[2] + | ldr CARG4, CCSTATE->gpr[3] + | blx RB + | mov sp, r11 + | str CRET1, CCSTATE->gpr[0] + | str CRET2, CCSTATE->gpr[1] + | pop {CCSTATE, r5, r11, pc} #endif | |//----------------------------------------------------------------------- @@ -2340,7 +2365,14 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) break; case BC_KCDATA: #if LJ_HASFFI - | NYI + | // RA = dst*8, RC = cdata_const (~) + | mvn RC, RC + | ins_next1 + | ldr CARG1, [KBASE, RC, lsl #2] + | mvn CARG2, #~LJ_TCDATA + | ins_next2 + | strd CARG12, [BASE, RA] + | ins_next3 #endif break; case BC_KSHORT: diff --git a/src/lj_arch.h b/src/lj_arch.h index 5e866fe4..ca5b0df4 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h @@ -137,7 +137,7 @@ #define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKROT 1 #define LJ_ARCH_DUALNUM 2 -#define LJ_ARCH_NOFFI 1 +#define LJ_ARCH_NOFFI 1 /* NYI: comparisons, calls. */ #define LJ_ARCH_NOJIT 1 #elif LUAJIT_TARGET == LUAJIT_ARCH_PPC diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 85d8af9c..da7b4738 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c @@ -164,6 +164,47 @@ } \ } +#elif LJ_TARGET_ARM +/* -- ARM calling conventions --------------------------------------------- */ + +#define CCALL_HANDLE_STRUCTRET \ + /* Return structs of size <= 4 in a GPR. */ \ + cc->retref = !(sz <= 4); \ + if (cc->retref) cc->gpr[ngpr++] = (GPRArg)dp; + +#define CCALL_HANDLE_COMPLEXRET \ + cc->retref = 1; /* Return all complex values by reference. */ \ + cc->gpr[ngpr++] = (GPRArg)dp; + +#define CCALL_HANDLE_COMPLEXRET2 \ + UNUSED(dp); /* Nothing to do. */ + +#define CCALL_HANDLE_STRUCTARG \ + /* Pass all structs by value in registers and/or on the stack. */ + +#define CCALL_HANDLE_COMPLEXARG \ + /* Pass complex by value in 2 or 4 GPRs. */ + +/* ARM has a softfp ABI. */ +#define CCALL_HANDLE_REGARG \ + if ((d->info & CTF_ALIGN) > CTALIGN_PTR) { \ + if (ngpr < maxgpr) \ + ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ + else \ + nsp = (nsp + 1u) & ~1u; /* Align argument on stack. */ \ + } \ + 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. */ \ + ngpr = maxgpr; \ + } else { \ + ngpr += n; \ + } \ + goto done; \ + } + #elif LJ_TARGET_PPCSPE /* -- PPC/SPE calling conventions ----------------------------------------- */ diff --git a/src/lj_ccall.h b/src/lj_ccall.h index 83e2403d..d0979781 100644 --- a/src/lj_ccall.h +++ b/src/lj_ccall.h @@ -47,6 +47,16 @@ typedef LJ_ALIGN(16) union FPRArg { typedef intptr_t GPRArg; +#elif LJ_TARGET_ARM + +#define CCALL_NARG_GPR 4 +#define CCALL_NARG_FPR 0 +#define CCALL_NRET_GPR 2 /* For softfp double. */ +#define CCALL_NRET_FPR 0 +#define CCALL_SPS_FREE 0 /* NYI */ + +typedef intptr_t GPRArg; + #elif LJ_TARGET_PPCSPE #define CCALL_NARG_GPR 8 @@ -91,10 +101,10 @@ typedef struct CCallState { #elif LJ_TARGET_X86 uint8_t resx87; /* Result on x87 stack: 1:float, 2:double. */ #endif - GPRArg gpr[CCALL_NUM_GPR]; /* Arguments/results in GPRs. */ #if CCALL_NUM_FPR 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. */ } CCallState;