mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
FFI: Add callback support for PPC.
This commit is contained in:
parent
10474987bd
commit
1b0d646004
@ -98,11 +98,14 @@
|
|||||||
|
|
|
|
||||||
|.macro saveregs
|
|.macro saveregs
|
||||||
| stwu sp, -CFRAME_SPACE(sp)
|
| stwu sp, -CFRAME_SPACE(sp)
|
||||||
| save_ 14; save_ 15; save_ 16; save_ 17; save_ 18; save_ 19
|
| save_ 14; save_ 15; save_ 16
|
||||||
| mflr r0; mfcr r12
|
| mflr r0
|
||||||
| save_ 20; save_ 21; save_ 22; save_ 23; save_ 24; save_ 25
|
| save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
|
||||||
| stw r0, SAVE_LR; stw r12, SAVE_CR
|
| stw r0, SAVE_LR
|
||||||
|
| save_ 23; save_ 24; save_ 25
|
||||||
|
| mfcr r0
|
||||||
| save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31
|
| save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31
|
||||||
|
| stw r0, SAVE_CR
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|
|
|
|
||||||
|.macro restoreregs
|
|.macro restoreregs
|
||||||
@ -610,21 +613,29 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| mr RB, BASE
|
| mr RB, BASE
|
||||||
| mr BASE, TMP2 // Restore caller BASE.
|
| mr BASE, TMP2 // Restore caller BASE.
|
||||||
| lwz LFUNC:TMP1, FRAME_FUNC(TMP2)
|
| lwz LFUNC:TMP1, FRAME_FUNC(TMP2)
|
||||||
| cmplwi TMP0, 0
|
#if LJ_HASFFI
|
||||||
|
| cmplwi TMP0, 1
|
||||||
|
#endif
|
||||||
| lwz PC, -16(RB) // Restore PC from [cont|PC].
|
| lwz PC, -16(RB) // Restore PC from [cont|PC].
|
||||||
| beq >1
|
|
||||||
| subi TMP2, RD, 8
|
| subi TMP2, RD, 8
|
||||||
| lwz TMP1, LFUNC:TMP1->pc
|
| lwz TMP1, LFUNC:TMP1->pc
|
||||||
| stwx TISNIL, RA, TMP2 // Ensure one valid arg.
|
| stwx TISNIL, RA, TMP2 // Ensure one valid arg.
|
||||||
|
#if LJ_HASFFI
|
||||||
|
| ble >1
|
||||||
|
#endif
|
||||||
| lwz KBASE, PC2PROTO(k)(TMP1)
|
| lwz KBASE, PC2PROTO(k)(TMP1)
|
||||||
| // BASE = base, RA = resultptr, RB = meta base
|
| // BASE = base, RA = resultptr, RB = meta base
|
||||||
| mtctr TMP0
|
| mtctr TMP0
|
||||||
| bctr // Jump to continuation.
|
| bctr // Jump to continuation.
|
||||||
|
|
|
|
||||||
|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.
|
||||||
| subi TMP1, RB, 16
|
| subi TMP1, RB, 16
|
||||||
| sub RC, TMP1, BASE
|
| sub RC, TMP1, BASE
|
||||||
| b ->vm_call_tail
|
| b ->vm_call_tail
|
||||||
|
#endif
|
||||||
|
|
|
|
||||||
|->cont_cat: // RA = resultptr, RB = meta base
|
|->cont_cat: // RA = resultptr, RB = meta base
|
||||||
| lwz INS, -4(PC)
|
| lwz INS, -4(PC)
|
||||||
@ -2490,7 +2501,7 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| lwz r0, 36(sp)
|
| lwz r0, 36(sp)
|
||||||
| fmul FARG1, FARG1, f15
|
| fmul FARG1, FARG1, f15
|
||||||
| mtlr r0
|
| mtlr r0
|
||||||
| fsub FARG1, f14, FARG1;
|
| fsub FARG1, f14, FARG1
|
||||||
| lfd f14, 16(sp); lfd f15, 24(sp); addi sp, sp, 32; blr
|
| lfd f14, 16(sp); lfd f15, 24(sp); addi sp, sp, 32; blr
|
||||||
|1:
|
|1:
|
||||||
| b extern pow
|
| b extern pow
|
||||||
@ -2526,6 +2537,71 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|//-- FFI helper functions -----------------------------------------------
|
|//-- FFI helper functions -----------------------------------------------
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|// Handler for callback functions. Callback slot number in r11, g in r12.
|
||||||
|
|->vm_ffi_callback:
|
||||||
|
#if LJ_HASFFI
|
||||||
|
|.type CTSTATE, CTState, PC
|
||||||
|
| saveregs
|
||||||
|
| lwz CTSTATE, GL:r12->ctype_state
|
||||||
|
| addi DISPATCH, r12, GG_G2DISP
|
||||||
|
| stw r11, CTSTATE->cb.slot
|
||||||
|
| stw r3, CTSTATE->cb.gpr[0]
|
||||||
|
| stfd f1, CTSTATE->cb.fpr[0]
|
||||||
|
| stw r4, CTSTATE->cb.gpr[1]
|
||||||
|
| stfd f2, CTSTATE->cb.fpr[1]
|
||||||
|
| stw r5, CTSTATE->cb.gpr[2]
|
||||||
|
| stfd f3, CTSTATE->cb.fpr[2]
|
||||||
|
| stw r6, CTSTATE->cb.gpr[3]
|
||||||
|
| stfd f4, CTSTATE->cb.fpr[3]
|
||||||
|
| stw r7, CTSTATE->cb.gpr[4]
|
||||||
|
| stfd f5, CTSTATE->cb.fpr[4]
|
||||||
|
| stw r8, CTSTATE->cb.gpr[5]
|
||||||
|
| stfd f6, CTSTATE->cb.fpr[5]
|
||||||
|
| stw r9, CTSTATE->cb.gpr[6]
|
||||||
|
| stfd f7, CTSTATE->cb.fpr[6]
|
||||||
|
| stw r10, CTSTATE->cb.gpr[7]
|
||||||
|
| stfd f8, CTSTATE->cb.fpr[7]
|
||||||
|
| addi TMP0, sp, CFRAME_SPACE+8
|
||||||
|
| stw TMP0, CTSTATE->cb.stack
|
||||||
|
| mr CARG1, CTSTATE
|
||||||
|
| stw CTSTATE, SAVE_PC // Any value outside of bytecode is ok.
|
||||||
|
| mr CARG2, sp
|
||||||
|
| bl extern lj_ccallback_enter // (CTState *cts, void *cf)
|
||||||
|
| // Returns lua_State *.
|
||||||
|
| lwz BASE, L:CRET1->base
|
||||||
|
| li TISNUM, LJ_TISNUM // Setup type comparison constants.
|
||||||
|
| lwz RC, L:CRET1->top
|
||||||
|
| lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
|
||||||
|
| li ZERO, 0
|
||||||
|
| mr L, CRET1
|
||||||
|
| stw TMP3, TMPD
|
||||||
|
| lwz LFUNC:RB, FRAME_FUNC(BASE)
|
||||||
|
| ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
|
||||||
|
| li TISNIL, LJ_TNIL
|
||||||
|
| li_vmstate INTERP
|
||||||
|
| lfs TOBIT, TMPD
|
||||||
|
| stw TMP3, TMPD
|
||||||
|
| sub RC, RC, BASE
|
||||||
|
| st_vmstate
|
||||||
|
| lfs TONUM, TMPD
|
||||||
|
| ins_callt
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|->cont_ffi_callback: // Return from FFI callback.
|
||||||
|
#if LJ_HASFFI
|
||||||
|
| lwz CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH)
|
||||||
|
| stw BASE, L->base
|
||||||
|
| stw RB, L->top
|
||||||
|
| stw L, CTSTATE->L
|
||||||
|
| mr CARG1, CTSTATE
|
||||||
|
| mr CARG2, RA
|
||||||
|
| bl extern lj_ccallback_leave // (CTState *cts, TValue *o)
|
||||||
|
| lwz CRET1, CTSTATE->cb.gpr[0]
|
||||||
|
| lfd FARG1, CTSTATE->cb.fpr[0]
|
||||||
|
| lwz CRET2, CTSTATE->cb.gpr[1]
|
||||||
|
| 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.
|
||||||
|
2777
src/buildvm_ppc.h
2777
src/buildvm_ppc.h
File diff suppressed because it is too large
Load Diff
@ -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_PPC
|
||||||
|
|
||||||
|
#define CALLBACK_MCODE_HEAD 24
|
||||||
|
#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))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* Missing support for this architecture. */
|
/* Missing support for this architecture. */
|
||||||
@ -70,8 +77,8 @@ MSize lj_ccallback_ptr2slot(CTState *cts, void *p)
|
|||||||
return ~0u; /* Not a known callback function pointer. */
|
return ~0u; /* Not a known callback function pointer. */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LJ_TARGET_X86ORX64
|
|
||||||
/* Initialize machine code for callback function pointers. */
|
/* Initialize machine code for callback function pointers. */
|
||||||
|
#if LJ_TARGET_X86ORX64
|
||||||
static void callback_mcode_init(global_State *g, uint8_t *page)
|
static void callback_mcode_init(global_State *g, uint8_t *page)
|
||||||
{
|
{
|
||||||
uint8_t *p = page;
|
uint8_t *p = page;
|
||||||
@ -103,6 +110,25 @@ 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_PPC
|
||||||
|
static void callback_mcode_init(global_State *g, uint32_t *page)
|
||||||
|
{
|
||||||
|
uint32_t *p = page;
|
||||||
|
void *target = (void *)lj_vm_ffi_callback;
|
||||||
|
MSize slot;
|
||||||
|
*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);
|
||||||
|
*p++ = PPCI_MTCTR | PPCF_T(RID_TMP);
|
||||||
|
*p++ = PPCI_BCTR;
|
||||||
|
for (slot = 0; slot < CALLBACK_MAX_SLOT; slot++) {
|
||||||
|
*p++ = PPCI_LI | PPCF_T(RID_R11) | slot;
|
||||||
|
*p = PPCI_B | (((page-p) & 0x00ffffffu) << 2);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
lua_assert(p - page <= CALLBACK_MCODE_SIZE);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
/* Missing support for this architecture. */
|
/* Missing support for this architecture. */
|
||||||
#define callback_mcode_init(g, p) UNUSED(p)
|
#define callback_mcode_init(g, p) UNUSED(p)
|
||||||
@ -224,8 +250,28 @@ void lj_ccallback_mcode_free(CTState *cts)
|
|||||||
#elif LJ_TARGET_PPC
|
#elif LJ_TARGET_PPC
|
||||||
|
|
||||||
#define CALLBACK_HANDLE_REGARG \
|
#define CALLBACK_HANDLE_REGARG \
|
||||||
UNUSED(ngpr); UNUSED(nfpr); UNUSED(maxgpr); goto done; /* NYI */
|
if (isfp) { \
|
||||||
#define CALLBACK_HANDLE_RET /* NYI */
|
if (nfpr + 1 <= CCALL_NARG_FPR) { \
|
||||||
|
sp = &cts->cb.fpr[nfpr]; \
|
||||||
|
nfpr += 1; \
|
||||||
|
cta = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \
|
||||||
|
goto done; \
|
||||||
|
} \
|
||||||
|
} else { /* Try to pass argument in GPRs. */ \
|
||||||
|
if (n > 1) { \
|
||||||
|
lua_assert(ctype_isinteger(cta->info) && n == 2); /* int64_t. */ \
|
||||||
|
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
|
||||||
|
} \
|
||||||
|
if (ngpr + n <= maxgpr) { \
|
||||||
|
sp = &cts->cb.gpr[ngpr]; \
|
||||||
|
ngpr += n; \
|
||||||
|
goto done; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CALLBACK_HANDLE_RET \
|
||||||
|
if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
|
||||||
|
*(double *)dp = *(float *)dp; /* FPRs always hold doubles. */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Missing calling convention definitions for this architecture"
|
#error "Missing calling convention definitions for this architecture"
|
||||||
@ -327,14 +373,14 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
|
|||||||
#endif
|
#endif
|
||||||
if (!ctype_isvoid(ctr->info)) {
|
if (!ctype_isvoid(ctr->info)) {
|
||||||
uint8_t *dp = (uint8_t *)&cts->cb.gpr[0];
|
uint8_t *dp = (uint8_t *)&cts->cb.gpr[0];
|
||||||
#ifdef CALLBACK_HANDLE_RET
|
|
||||||
CALLBACK_HANDLE_RET
|
|
||||||
#endif
|
|
||||||
#if CCALL_NUM_FPR
|
#if CCALL_NUM_FPR
|
||||||
if (ctype_isfp(ctr->info))
|
if (ctype_isfp(ctr->info))
|
||||||
dp = (uint8_t *)&cts->cb.fpr[0];
|
dp = (uint8_t *)&cts->cb.fpr[0];
|
||||||
#endif
|
#endif
|
||||||
lj_cconv_ct_tv(cts, ctr, dp, o, 0);
|
lj_cconv_ct_tv(cts, ctr, dp, o, 0);
|
||||||
|
#ifdef CALLBACK_HANDLE_RET
|
||||||
|
CALLBACK_HANDLE_RET
|
||||||
|
#endif
|
||||||
/* Extend returned integers to (at least) 32 bits. */
|
/* Extend returned integers to (at least) 32 bits. */
|
||||||
if (ctype_isinteger_or_bool(ctr->info) && ctr->size < 4) {
|
if (ctype_isinteger_or_bool(ctr->info) && ctr->size < 4) {
|
||||||
if (ctr->info & CTF_UNSIGNED)
|
if (ctr->info & CTF_UNSIGNED)
|
||||||
|
@ -161,7 +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
|
#if LJ_TARGET_X86ORX64 || LJ_TARGET_PPC
|
||||||
ERRDEF(FFI_CBACKOV, "too many callbacks")
|
ERRDEF(FFI_CBACKOV, "too many callbacks")
|
||||||
#else
|
#else
|
||||||
ERRDEF(FFI_CBACKOV, "no support for callbacks (yet)")
|
ERRDEF(FFI_CBACKOV, "no support for callbacks (yet)")
|
||||||
|
Loading…
Reference in New Issue
Block a user