浏览代码

FFI: Add callback support for PPC.

Mike Pall 14 年之前
父节点
当前提交
1b0d646004
共有 4 个文件被更改,包括 283 次插入154 次删除
  1. 84 8
      src/buildvm_ppc.dasc
  2. 146 139
      src/buildvm_ppc.h
  3. 52 6
      src/lj_ccallback.c
  4. 1 1
      src/lj_errmsg.h

+ 84 - 8
src/buildvm_ppc.dasc

@@ -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
-|  mflr r0; mfcr r12
-|  save_ 20; save_ 21; save_ 22; save_ 23; save_ 24; save_ 25
-|  stw  r0, SAVE_LR; stw r12, SAVE_CR
+|  save_ 14; save_ 15; save_ 16
+|  mflr r0
+|  save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
+|  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.

文件差异内容过多而无法显示
+ 146 - 139
src/buildvm_ppc.h


+ 52 - 6
src/lj_ccallback.c

@@ -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 */
-#define CALLBACK_HANDLE_RET		/* NYI */
+  if (isfp) { \
+    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)

+ 1 - 1
src/lj_errmsg.h

@@ -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)")

部分文件因为文件数量过多而无法显示