Bläddra i källkod

PPC: Add support to call C functions and to return back to C.

Command line starts now, but it can't run any Lua code yet.
Mike Pall 15 år sedan
förälder
incheckning
f4d4af1b6d
1 ändrade filer med 100 tillägg och 4 borttagningar
  1. 100 4
      src/buildvm_ppc.dasc

+ 100 - 4
src/buildvm_ppc.dasc

@@ -134,6 +134,11 @@
 |
 |//-----------------------------------------------------------------------
 |
+|// These basic macros should really be part of DynASM.
+|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro
+|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro
+|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro
+|
 |// Trap for not-yet-implemented parts.
 |.macro NYI; tw 4, sp, sp; .endmacro
 |
@@ -249,13 +254,52 @@ static void build_subroutines(BuildCtx *ctx)
   |//-----------------------------------------------------------------------
   |
   |->vm_returnp:
-  |  NYI
+  |  // See vm_return. Also: TMP2 = previous base.
+  |  andi. TMP0, PC, FRAME_P
+  |   evsplati TMP1, LJ_TTRUE
+  |  beq ->cont_dispatch
+  |
+  |  // Return from pcall or xpcall fast func.
+  |  lwz PC, FRAME_PC(TMP2)		// Fetch PC of previous frame.
+  |  mr BASE, TMP2			// Restore caller base.
+  |  // Prepending may overwrite the pcall frame, so do it at the end.
+  |   stwu TMP1, FRAME_PC(RA)		// Prepend true to results.
   |
   |->vm_returnc:
-  |  NYI
+  |  andi. TMP0, PC, FRAME_TYPE
+  |   addi RD, RD, 8			// RD = (nresults+1)*8.
+  |   stw RD, SAVE_MULTRES
+  |  beq ->BC_RET_Z			// Handle regular return to Lua.
   |
   |->vm_return:
-  |  NYI
+  |  // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return
+  |  // TMP0 = PC & FRAME_TYPE
+  |  cmpwi TMP0, FRAME_C
+  |   rlwinm TMP2, PC, 0, 0, 28
+  |    li_vmstate C
+  |   sub TMP2, BASE, TMP2		// TMP2 = previous base.
+  |  bne ->vm_returnp
+  |
+  |  addic. TMP1, RD, -8
+  |   stw TMP2, L->base
+  |   lwz TMP2, SAVE_NRES
+  |    subi BASE, BASE, 8
+  |    st_vmstate
+  |   slwi TMP2, TMP2, 3
+  |  beq >2
+  |1:
+  |  addic. TMP1, TMP1, -8
+  |   evldd TMP0, 0(RA)
+  |    addi RA, RA, 8
+  |   evstdd TMP0, 0(BASE)
+  |    addi BASE, BASE, 8
+  |  bne <1
+  |
+  |2:
+  |  cmpw TMP2, RD			// More/less results wanted?
+  |  bne >6
+  |3:
+  |  stw BASE, L->top			// Store new top.
   |
   |->vm_leave_cp:
   |  lwz TMP0, SAVE_CFRAME		// Restore previous C frame.
@@ -266,6 +310,27 @@ static void build_subroutines(BuildCtx *ctx)
   |  restoreregs
   |  blr
   |
+  |6:
+  |  ble >7				// Less results wanted?
+  |  // More results wanted. Check stack size and fill up results with nil.
+  |  lwz TMP1, L->maxstack
+  |  cmplw BASE, TMP1
+  |  bge >8
+  |  evstdd TISNIL, 0(BASE)
+  |  addi RD, RD, 8
+  |  addi BASE, BASE, 8
+  |  b <2
+  |
+  |7:  // Less results wanted.
+  |   sub TMP0, RD, TMP2
+  |  cmpwi TMP2, 0			// LUA_MULTRET+1 case?
+  |   sub TMP0, BASE, TMP0		// Subtract the difference.
+  |  iseleq BASE, BASE, TMP0		// Either keep top or shrink it.
+  |  b <3
+  |
+  |8:  // Corner case: need to grow stack for filling up results.
+  |  NYI
+  |
   |->vm_unwind_c:			// Unwind C stack, return from vm_pcall.
   |  NYI
   |->vm_unwind_c_eh:			// Landing pad for external unwinder.
@@ -986,6 +1051,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     break;
 
   case BC_RET:
+    |  NYI
+    |->BC_RET_Z:
     |  NYI
     break;
 
@@ -1077,7 +1144,36 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
 
   case BC_FUNCC:
   case BC_FUNCCW:
-    |  NYI
+    |  // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
+    if (op == BC_FUNCC) {
+      |  lwz TMP0, CFUNC:RB->f
+    } else {
+      |  lwz TMP0, DISPATCH_GL(wrapf)(DISPATCH)
+    }
+    |   add TMP1, RA, NARGS8:RC
+    |   lwz TMP2, L->maxstack
+    |    add RC, BASE, NARGS8:RC
+    |   stw BASE, L->base
+    |  mtctr TMP0
+    |   cmplw TMP1, TMP2
+    |    stw RC, L->top
+    |     li_vmstate C
+    if (op == BC_FUNCCW) {
+      |  lwz CARG2, CFUNC:RB->f
+    }
+    |  mr CARG1, L
+    |   bgt ->vm_growstack_c		// Need to grow stack.
+    |     st_vmstate
+    |  bctrl				// (lua_State *L [, lua_CFunction f])
+    |  // Returns nresults.
+    |  lwz TMP1, L->top
+    |   slwi RD, CRET1, 3
+    |  lwz BASE, L->base
+    |    li_vmstate INTERP
+    |  lwz PC, FRAME_PC(BASE)		// Fetch PC of caller.
+    |   sub RA, TMP1, RD		// RA = L->top - nresults*8
+    |    st_vmstate
+    |  b ->vm_returnc
     break;
 
   /* ---------------------------------------------------------------------- */