Browse Source

PPC: Add machine-specific part of FFI.

Mike Pall 14 years ago
parent
commit
4008b351f4
5 changed files with 516 additions and 226 deletions
  1. 91 12
      src/buildvm_ppc.dasc
  2. 355 211
      src/buildvm_ppc.h
  3. 0 1
      src/lj_arch.h
  4. 52 1
      src/lj_ccall.c
  5. 18 1
      src/lj_ccall.h

+ 91 - 12
src/buildvm_ppc.dasc

@@ -2382,7 +2382,62 @@ static void build_subroutines(BuildCtx *ctx)
   |
   |->vm_ffi_call:
 #if LJ_HASFFI
-  |  NYI
+  |  .type CCSTATE, CCallState, CARG1
+  |  lwz TMP1, CCSTATE->spadj
+  |    mflr TMP0
+  |   lbz CARG2, CCSTATE->nsp
+  |   lbz CARG3, CCSTATE->nfpr
+  |  neg TMP1, TMP1
+  |    stw TMP0, 4(sp)
+  |   cmpwi cr1, CARG3, 0
+  |  mr TMP2, sp
+  |   addic. CARG2, CARG2, -1
+  |  stwux sp, sp, TMP1
+  |   crnot 4*cr1+eq, 4*cr1+eq		// For vararg calls.
+  |  stw CCSTATE, -4(TMP2)
+  |   li TMP3, 0
+  |  la TMP1, CCSTATE->stack
+  |   slwi CARG2, CARG2, 2
+  |   blt >2
+  |  la TMP2, 8(sp)
+  |1:
+  |  lwzx TMP0, TMP1, CARG2
+  |  stwx TMP0, TMP2, CARG2
+  |   addic. CARG2, CARG2, -4
+  |  bge <1
+  |2:
+  |  bne cr1, >3
+  |  lfd f1, CCSTATE->fpr[0]
+  |  lfd f2, CCSTATE->fpr[1]
+  |  lfd f3, CCSTATE->fpr[2]
+  |  lfd f4, CCSTATE->fpr[3]
+  |  lfd f5, CCSTATE->fpr[4]
+  |  lfd f6, CCSTATE->fpr[5]
+  |  lfd f7, CCSTATE->fpr[6]
+  |  lfd f8, CCSTATE->fpr[7]
+  |3:
+  |   lwz TMP0, CCSTATE->func
+  |  lwz CARG2, CCSTATE->gpr[1]
+  |  lwz CARG3, CCSTATE->gpr[2]
+  |  lwz CARG4, CCSTATE->gpr[3]
+  |  lwz CARG5, CCSTATE->gpr[4]
+  |   mtctr TMP0
+  |  lwz r8, CCSTATE->gpr[5]
+  |  lwz r9, CCSTATE->gpr[6]
+  |  lwz r10, CCSTATE->gpr[7]
+  |  lwz CARG1, CCSTATE->gpr[0]		// Do this last, since CCSTATE is CARG1.
+  |   bctrl
+  |  lwz TMP2, 0(sp)
+  |  lwz CCSTATE:TMP1, -4(TMP2)
+  |   lwz TMP0, 4(TMP2)
+  |  stw CARG1, CCSTATE:TMP1->gpr[0]
+  |  stfd FARG1, CCSTATE:TMP1->fpr[0]
+  |  stw CARG2, CCSTATE:TMP1->gpr[1]
+  |   mtlr TMP0
+  |  stw CARG3, CCSTATE:TMP1->gpr[2]
+  |   mr sp, TMP2
+  |  stw CARG4, CCSTATE:TMP1->gpr[3]
+  |  blr
 #endif
   |
   |//-----------------------------------------------------------------------
@@ -2440,7 +2495,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
       |  tonum_i f1, CARG3
       |  b >5
       |
-      |8: // RA is an integer, RD is a number.
+      |8: // RA is an integer, RD is not an integer.
+      |  bgt cr1, ->vmeta_comp
+      |  // RA is an integer, RD is a number.
       |  tonum_i f0, CARG2
       |4:
       |  lfd f1, 0(RD)
@@ -2498,9 +2555,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
       |   lwz CARG2, 4(RA)
       |  lwzux TMP1, RD, BASE
       |  checknum cr0, TMP0
-      |    lwz INS, -4(PC)
+      |    lwz TMP2, -4(PC)
       |  checknum cr1, TMP1
-      |    decode_RD4 TMP2, INS
+      |    decode_RD4 TMP2, TMP2
       |   lwz CARG3, 4(RD)
       |  cror 4*cr7+gt, 4*cr0+gt, 4*cr1+gt
       |    addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
@@ -2538,10 +2595,20 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
       |    lwz CARG2, 4(RA)
       |    lwz CARG3, 4(RD)
     }
+    if (LJ_HASFFI) {
+      |  cmpwi cr7, TMP0, LJ_TCDATA
+      |  cmpwi cr5, TMP1, LJ_TCDATA
+    }
     |   not TMP3, TMP0
     |  cmplw TMP0, TMP1
     |   cmplwi cr1, TMP3, ~LJ_TISPRI		// Primitive?
+    if (LJ_HASFFI) {
+      |  cror 4*cr7+eq, 4*cr7+eq, 4*cr5+eq
+    }
     |   cmplwi cr6, TMP3, ~LJ_TISTABUD		// Table or userdata?
+    if (LJ_HASFFI) {
+      |  beq cr7, ->vmeta_equal_cd
+    }
     |    cmplw cr5, CARG2, CARG3
     |  crandc 4*cr0+gt, 4*cr0+eq, 4*cr1+gt	// 2: Same type and primitive.
     |  crorc 4*cr0+lt, 4*cr5+eq, 4*cr0+eq	// 1: Same tv or different type.
@@ -2587,14 +2654,20 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  lwzux TMP0, RA, BASE
     |   srwi RD, RD, 1
     |  lwz STR:TMP3, 4(RA)
-    |    lwz INS, 0(PC)
+    |    lwz TMP2, 0(PC)
     |   subfic RD, RD, -4
     |    addi PC, PC, 4
+    if (LJ_HASFFI) {
+      |  cmpwi TMP0, LJ_TCDATA
+    }
     |   lwzx STR:TMP1, KBASE, RD	// KBASE-4-str_const*4
     |  subfic TMP0, TMP0, LJ_TSTR
+    if (LJ_HASFFI) {
+      |  beq ->vmeta_equal_cd
+    }
     |  sub TMP1, STR:TMP1, STR:TMP3
     |  or TMP0, TMP0, TMP1
-    |    decode_RD4 TMP2, INS
+    |    decode_RD4 TMP2, TMP2
     |  subfic TMP0, TMP0, 0
     |    addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
     |  subfe TMP1, TMP1, TMP1
@@ -2616,9 +2689,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
       |   lwz CARG2, 4(RA)
       |  lwzux TMP1, RD, KBASE
       |  checknum cr0, TMP0
-      |    lwz INS, -4(PC)
+      |    lwz TMP2, -4(PC)
       |  checknum cr1, TMP1
-      |    decode_RD4 TMP2, INS
+      |    decode_RD4 TMP2, TMP2
       |   lwz CARG3, 4(RD)
       |    addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
       if (vk) {
@@ -2639,9 +2712,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
       |  lwzx TMP0, BASE, RA
       |    addi PC, PC, 4
       |   lfdx f0, BASE, RA
-      |    lwz INS, -4(PC)
+      |    lwz TMP2, -4(PC)
       |  lfdx f1, KBASE, RD
-      |    decode_RD4 TMP2, INS
+      |    decode_RD4 TMP2, TMP2
       |  checknum TMP0
       |    addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
       |  bge >3
@@ -2695,11 +2768,17 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |  // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
     |  lwzx TMP0, BASE, RA
     |   srwi TMP1, RD, 3
-    |    lwz INS, 0(PC)
+    |    lwz TMP2, 0(PC)
     |   not TMP1, TMP1
     |    addi PC, PC, 4
+    if (LJ_HASFFI) {
+      |  cmpwi TMP0, LJ_TCDATA
+    }
     |  sub TMP0, TMP0, TMP1
-    |    decode_RD4 TMP2, INS
+    if (LJ_HASFFI) {
+      |  beq ->vmeta_equal_cd
+    }
+    |    decode_RD4 TMP2, TMP2
     |  addic TMP0, TMP0, -1
     |    addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
     |  subfe TMP1, TMP1, TMP1

File diff suppressed because it is too large
+ 355 - 211
src/buildvm_ppc.h


+ 0 - 1
src/lj_arch.h

@@ -163,7 +163,6 @@
 #define LJ_TARGET_MASKROT	1
 #define LJ_TARGET_UNIFYROT	1	/* Want only IR_BROL. */
 #define LJ_ARCH_NUMMODE		LJ_NUMMODE_DUAL_SINGLE
-#define LJ_ARCH_NOFFI		1	/* NYI: comparisons, calls. */
 #define LJ_ARCH_NOJIT		1
 
 #elif LUAJIT_TARGET == LUAJIT_ARCH_PPCSPE

+ 52 - 1
src/lj_ccall.c

@@ -205,6 +205,54 @@
     goto done; \
   }
 
+#elif LJ_TARGET_PPC
+/* -- PPC calling conventions --------------------------------------------- */
+
+#define CCALL_HANDLE_STRUCTRET \
+  cc->retref = 1;  /* Return all structs by reference. */ \
+  cc->gpr[ngpr++] = (GPRArg)dp;
+
+#define CCALL_HANDLE_COMPLEXRET \
+  /* Complex values are returned in 2 or 4 GPRs. */ \
+  cc->retref = 0;
+
+#define CCALL_HANDLE_COMPLEXRET2 \
+  memcpy(dp, sp, ctr->size);  /* Copy complex from GPRs. */
+
+#define CCALL_HANDLE_STRUCTARG \
+  rp = cdataptr(lj_cdata_new(cts, did, sz)); \
+  sz = CTSIZE_PTR;  /* Pass all structs by reference. */
+
+#define CCALL_HANDLE_COMPLEXARG \
+  /* Pass complex by value in 2 or 4 GPRs. */
+
+#define CCALL_HANDLE_REGARG \
+  if (isfp) {  /* Try to pass argument in FPRs. */ \
+    if (nfpr + 1 <= CCALL_NARG_FPR) { \
+      dp = &cc->fpr[nfpr]; \
+      nfpr += 1; \
+      d = ctype_get(cts, CTID_DOUBLE);  /* FPRs always hold doubles. */ \
+      goto done; \
+    } \
+  } else {  /* Try to pass argument in GPRs. */ \
+    if (n > 1) { \
+      lua_assert(n == 2 || n == 4);  /* int64_t or complex (float). */ \
+      if (ctype_isinteger(d->info)) \
+	ngpr = (ngpr + 1u) & ~1u;  /* Align int64_t to regpair. */ \
+      else if (ngpr + n > maxgpr) \
+	ngpr = maxgpr;  /* Prevent reordering. */ \
+    } \
+    if (ngpr + n <= maxgpr) { \
+      dp = &cc->gpr[ngpr]; \
+      ngpr += n; \
+      goto done; \
+    } \
+  }
+
+#define CCALL_HANDLE_RET \
+  if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
+    ctr = ctype_get(cts, CTID_DOUBLE);  /* FPRs always hold doubles. */
+
 #elif LJ_TARGET_PPCSPE
 /* -- PPC/SPE calling conventions ----------------------------------------- */
 
@@ -530,7 +578,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
   }
   if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG);  /* Too few arguments. */
 
-#if LJ_TARGET_X64
+#if LJ_TARGET_X64 || LJ_TARGET_PPC || LJ_TARGET_PPCSPE
   cc->nfpr = nfpr;  /* Required for vararg functions. */
 #endif
   cc->nsp = nsp;
@@ -565,6 +613,9 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct,
     CCALL_HANDLE_COMPLEXRET2
     return 1;  /* One GC step. */
   }
+#ifdef CCALL_HANDLE_RET
+  CCALL_HANDLE_RET
+#endif
 #if CCALL_NUM_FPR
   if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info))
     sp = &cc->fpr[0];

+ 18 - 1
src/lj_ccall.h

@@ -53,10 +53,22 @@ typedef intptr_t GPRArg;
 #define CCALL_NARG_FPR		0
 #define CCALL_NRET_GPR		2	/* For softfp double. */
 #define CCALL_NRET_FPR		0
-#define CCALL_SPS_FREE		0	/* NYI */
+#define CCALL_SPS_FREE		0
 
 typedef intptr_t GPRArg;
 
+#elif LJ_TARGET_PPC
+
+#define CCALL_NARG_GPR		8
+#define CCALL_NARG_FPR		8
+#define CCALL_NRET_GPR		4	/* For complex double. */
+#define CCALL_NRET_FPR		1
+#define CCALL_SPS_EXTRA		3
+#define CCALL_SPS_FREE		1
+
+typedef intptr_t GPRArg;
+typedef double FPRArg;
+
 #elif LJ_TARGET_PPCSPE
 
 #define CCALL_NARG_GPR		8
@@ -100,8 +112,13 @@ typedef struct CCallState {
   uint8_t nfpr;			/* Number of arguments in FPRs. */
 #elif LJ_TARGET_X86
   uint8_t resx87;		/* Result on x87 stack: 1:float, 2:double. */
+#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE
+  uint8_t nfpr;			/* Number of arguments in FPRs. */
 #endif
 #if CCALL_NUM_FPR
+#if LJ_32
+  int32_t align1;
+#endif
   FPRArg fpr[CCALL_NUM_FPR];	/* Arguments/results in FPRs. */
 #endif
   GPRArg gpr[CCALL_NUM_GPR];	/* Arguments/results in GPRs. */

Some files were not shown because too many files changed in this diff