瀏覽代碼

ARM: Add partial support for FFI.

Mike Pall 14 年之前
父節點
當前提交
d636a3decd
共有 4 個文件被更改,包括 87 次插入4 次删除
  1. 34 2
      src/buildvm_arm.dasc
  2. 1 1
      src/lj_arch.h
  3. 41 0
      src/lj_ccall.c
  4. 11 1
      src/lj_ccall.h

+ 34 - 2
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:

+ 1 - 1
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

+ 41 - 0
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 ----------------------------------------- */
 

+ 11 - 1
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;