FFI: Add callback support for ARM.

This commit is contained in:
Mike Pall 2011-12-12 23:12:25 +01:00
parent 1b0d646004
commit 03c51fc578
5 changed files with 1328 additions and 1147 deletions

View File

@ -502,22 +502,30 @@ static void build_subroutines(BuildCtx *ctx)
| ldr CARG1, [BASE, #-16] // Get continuation. | ldr CARG1, [BASE, #-16] // Get continuation.
| mov CARG4, BASE | mov CARG4, BASE
| mov BASE, RB // Restore caller BASE. | mov BASE, RB // Restore caller BASE.
| cmp CARG1, #0 #if LJ_HASFFI
| cmp CARG1, #1
#endif
| ldr PC, [CARG4, #-12] // Restore PC from [cont|PC]. | ldr PC, [CARG4, #-12] // Restore PC from [cont|PC].
| beq >1
| ldr CARG3, LFUNC:CARG3->field_pc | ldr CARG3, LFUNC:CARG3->field_pc
| mvn INS, #~LJ_TNIL | mvn INS, #~LJ_TNIL
| add CARG2, RA, RC | add CARG2, RA, RC
| str INS, [CARG2, #-4] // Ensure one valid arg. | str INS, [CARG2, #-4] // Ensure one valid arg.
#if LJ_HASFFI
| bls >1
#endif
| ldr KBASE, [CARG3, #PC2PROTO(k)] | ldr KBASE, [CARG3, #PC2PROTO(k)]
| // BASE = base, RA = resultptr, CARG4 = meta base | // BASE = base, RA = resultptr, CARG4 = meta base
| bx CARG1 | bx CARG1
| |
|1: // Tail call from C function. #if LJ_HASFFI
|1:
| beq ->cont_ffi_callback // cont = 1: return from FFI callback.
| // cont = 0: tailcall from C function.
| ldr CARG3, [BASE, FRAME_FUNC] | ldr CARG3, [BASE, FRAME_FUNC]
| sub CARG4, CARG4, #16 | sub CARG4, CARG4, #16
| sub RC, CARG4, BASE | sub RC, CARG4, BASE
| b ->vm_call_tail | b ->vm_call_tail
#endif
| |
|->cont_cat: // RA = resultptr, CARG4 = meta base |->cont_cat: // RA = resultptr, CARG4 = meta base
| ldr INS, [PC, #-4] | ldr INS, [PC, #-4]
@ -2177,6 +2185,50 @@ static void build_subroutines(BuildCtx *ctx)
|//----------------------------------------------------------------------- |//-----------------------------------------------------------------------
|//-- FFI helper functions ----------------------------------------------- |//-- FFI helper functions -----------------------------------------------
|//----------------------------------------------------------------------- |//-----------------------------------------------------------------------
|
|// Handler for callback functions.
|// Saveregs already performed. Callback slot number in [sp], g in r12.
|->vm_ffi_callback:
#if LJ_HASFFI
|.type CTSTATE, CTState, PC
| ldr CTSTATE, GL:r12->ctype_state
| add DISPATCH, r12, #GG_G2DISP
| strd CARG12, CTSTATE->cb.gpr[0]
| strd CARG34, CTSTATE->cb.gpr[2]
| ldr CARG4, [sp]
| add CARG3, sp, #CFRAME_SIZE
| mov CARG1, CTSTATE
| lsr CARG4, CARG4, #3
| str CARG3, CTSTATE->cb.stack
| mov CARG2, sp
| str CARG4, CTSTATE->cb.slot
| str CTSTATE, SAVE_PC // Any value outside of bytecode is ok.
| bl extern lj_ccallback_enter // (CTState *cts, void *cf)
| // Returns lua_State *.
| ldr BASE, L:CRET1->base
| mv_vmstate CARG2, INTERP
| ldr RC, L:CRET1->top
| mov MASKR8, #255
| ldr LFUNC:CARG3, [BASE, FRAME_FUNC]
| mov L, CRET1
| sub RC, RC, BASE
| lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8.
| st_vmstate CARG2
| ins_callt
#endif
|
|->cont_ffi_callback: // Return from FFI callback.
#if LJ_HASFFI
| ldr CTSTATE, [DISPATCH, #DISPATCH_GL(ctype_state)]
| str BASE, L->base
| str CARG4, L->top
| str L, CTSTATE->L
| mov CARG1, CTSTATE
| mov CARG2, RA
| bl extern lj_ccallback_leave // (CTState *cts, TValue *o)
| ldrd CARG12, CTSTATE->cb.gpr[0]
| b ->vm_leave_unw
#endif
| |
|->vm_ffi_call: // Call C function via FFI. |->vm_ffi_call: // Call C function via FFI.
| // Caveat: needs special frame unwinding, see below. | // Caveat: needs special frame unwinding, see below.

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,13 @@ static MSize CALLBACK_OFS2SLOT(MSize ofs)
#define CALLBACK_MAX_SLOT \ #define CALLBACK_MAX_SLOT \
(((CALLBACK_MCODE_SIZE-CALLBACK_MCODE_HEAD)/(CALLBACK_MCODE_GROUP+4*32))*32) (((CALLBACK_MCODE_SIZE-CALLBACK_MCODE_HEAD)/(CALLBACK_MCODE_GROUP+4*32))*32)
#elif LJ_TARGET_ARM
#define CALLBACK_MCODE_HEAD 32
#define CALLBACK_SLOT2OFS(slot) (CALLBACK_MCODE_HEAD + 8*(slot))
#define CALLBACK_OFS2SLOT(ofs) (((ofs)-CALLBACK_MCODE_HEAD)/8)
#define CALLBACK_MAX_SLOT (CALLBACK_OFS2SLOT(CALLBACK_MCODE_SIZE))
#elif LJ_TARGET_PPC #elif LJ_TARGET_PPC
#define CALLBACK_MCODE_HEAD 24 #define CALLBACK_MCODE_HEAD 24
@ -110,6 +117,28 @@ static void callback_mcode_init(global_State *g, uint8_t *page)
} }
lua_assert(p - page <= CALLBACK_MCODE_SIZE); lua_assert(p - page <= CALLBACK_MCODE_SIZE);
} }
#elif LJ_TARGET_ARM
static void callback_mcode_init(global_State *g, uint32_t *page)
{
uint32_t *p = page;
void *target = (void *)lj_vm_ffi_callback;
MSize slot;
/* This must match with the saveregs macro in buildvm_arm.dasc. */
*p++ = ARMI_SUB|ARMF_D(RID_R12)|ARMF_N(RID_R12)|ARMF_M(RID_PC);
*p++ = ARMI_PUSH|ARMF_N(RID_SP)|RSET_RANGE(RID_R4,RID_R11+1)|RID2RSET(RID_LR);
*p++ = ARMI_SUB|ARMI_K12|ARMF_D(RID_R12)|ARMF_N(RID_R12)|CALLBACK_MCODE_HEAD;
*p++ = ARMI_STR|ARMI_LS_P|ARMI_LS_W|ARMF_D(RID_R12)|ARMF_N(RID_SP)|(CFRAME_SIZE-4*9);
*p++ = ARMI_LDR|ARMI_LS_P|ARMI_LS_U|ARMF_D(RID_R12)|ARMF_N(RID_PC);
*p++ = ARMI_LDR|ARMI_LS_P|ARMI_LS_U|ARMF_D(RID_PC)|ARMF_N(RID_PC);
*p++ = u32ptr(g);
*p++ = u32ptr(target);
for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
*p++ = ARMI_MOV|ARMF_D(RID_R12)|ARMF_M(RID_PC);
*p = ARMI_B | ((page-p-2) & 0x00ffffffu);
p++;
}
lua_assert(p - page <= CALLBACK_MCODE_SIZE);
}
#elif LJ_TARGET_PPC #elif LJ_TARGET_PPC
static void callback_mcode_init(global_State *g, uint32_t *page) static void callback_mcode_init(global_State *g, uint32_t *page)
{ {
@ -245,7 +274,12 @@ void lj_ccallback_mcode_free(CTState *cts)
#elif LJ_TARGET_ARM #elif LJ_TARGET_ARM
#define CALLBACK_HANDLE_REGARG \ #define CALLBACK_HANDLE_REGARG \
UNUSED(ngpr); UNUSED(maxgpr); goto done; /* NYI */ if (n > 1) ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
if (ngpr + n <= maxgpr) { \
sp = &cts->cb.gpr[ngpr]; \
ngpr += n; \
goto done; \
}
#elif LJ_TARGET_PPC #elif LJ_TARGET_PPC

View File

@ -161,11 +161,7 @@ ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed")
ERRDEF(FFI_WRCONST, "attempt to write to constant location") ERRDEF(FFI_WRCONST, "attempt to write to constant location")
ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS) ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS)
ERRDEF(FFI_BADCBACK, "bad callback") ERRDEF(FFI_BADCBACK, "bad callback")
#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
ERRDEF(FFI_CBACKOV, "too many callbacks") ERRDEF(FFI_CBACKOV, "too many callbacks")
#else
ERRDEF(FFI_CBACKOV, "no support for callbacks (yet)")
#endif
ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields")
ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)")
#endif #endif

View File

@ -139,6 +139,7 @@ typedef enum ARMIns {
ARMI_S = 0x000100000, ARMI_S = 0x000100000,
ARMI_K12 = 0x02000000, ARMI_K12 = 0x02000000,
ARMI_KNEG = 0x00200000, ARMI_KNEG = 0x00200000,
ARMI_LS_W = 0x00200000,
ARMI_LS_U = 0x00800000, ARMI_LS_U = 0x00800000,
ARMI_LS_P = 0x01000000, ARMI_LS_P = 0x01000000,
ARMI_LS_R = 0x02000000, ARMI_LS_R = 0x02000000,
@ -176,6 +177,7 @@ typedef enum ARMIns {
ARMI_STRB = 0xe4400000, ARMI_STRB = 0xe4400000,
ARMI_STRH = 0xe00000b0, ARMI_STRH = 0xe00000b0,
ARMI_STRD = 0xe00000f0, ARMI_STRD = 0xe00000f0,
ARMI_PUSH = 0xe92d0000,
ARMI_B = 0xea000000, ARMI_B = 0xea000000,
ARMI_BL = 0xeb000000, ARMI_BL = 0xeb000000,