Browse Source

PPC: Add tailcall instructions.

Mike Pall 15 years ago
parent
commit
711e55bdf8
1 changed files with 55 additions and 2 deletions
  1. 55 2
      src/buildvm_ppc.dasc

+ 55 - 2
src/buildvm_ppc.dasc

@@ -579,6 +579,9 @@ static void build_subroutines(BuildCtx *ctx)
   |->vmeta_call:			// Resolve and call __call metamethod.
   |  NYI
   |
+  |->vmeta_callt:			// Resolve __call for BC_CALLT.
+  |  NYI
+  |
   |//-- Argument coercion for 'for' statement ------------------------------
   |
   |->vmeta_for:
@@ -1538,10 +1541,60 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     break;
 
   case BC_CALLMT:
-    |  NYI
+    |  // RA = base*8, (RB = 0,) RC = extra_nargs*8
+    |  lwz TMP0, SAVE_MULTRES
+    |  add NARGS8:RC, NARGS8:RC, TMP0
+    |  // Fall through. Assumes BC_CALLT follows.
     break;
   case BC_CALLT:
-    |  NYI
+    |  // RA = base*8, (RB = 0,) RC = (nargs+1)*8
+    |  evlddx LFUNC:RB, BASE, RA
+    |   add RA, BASE, RA
+    |    lwz TMP1, FRAME_PC(BASE)
+    |    subi NARGS8:RC, NARGS8:RC, 8
+    |  checkfunc LFUNC:RB
+    |   addi RA, RA, 8
+    |  checkfail ->vmeta_callt
+    |->BC_CALLT_Z:
+    |  andi. TMP0, TMP1, FRAME_TYPE	// Caveat: preserve cr0 until the crand.
+    |   lbz TMP3, LFUNC:RB->ffid
+    |    xori TMP2, TMP1, FRAME_VARG
+    |    cmpwi cr1, NARGS8:RC, 0
+    |  bne >7
+    |1:
+    |  stw LFUNC:RB, FRAME_FUNC(BASE)	// Copy function down, but keep PC.
+    |  li TMP2, 0
+    |   cmplwi cr7, TMP3, 1		// (> FF_C) Calling a fast function?
+    |    beq cr1, >3
+    |2:
+    |  addi TMP3, TMP2, 8
+    |   evlddx TMP0, RA, TMP2
+    |  cmpw cr1, TMP3, NARGS8:RC
+    |   evstddx TMP0, BASE, TMP2
+    |  mr TMP2, TMP3
+    |  bne cr1, <2
+    |3:
+    |  crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt
+    |  beq >5
+    |4:
+    |  ins_callt
+    |
+    |5:  // Tailcall to a fast function with a Lua frame below.
+    |  lwz INS, -4(TMP1)
+    |  decode_RA8 RA, INS
+    |  sub TMP1, BASE, RA
+    |  lwz LFUNC:TMP1, FRAME_FUNC(TMP1)
+    |  lwz TMP1, LFUNC:TMP1->pc
+    |  lwz KBASE, PC2PROTO(k)(TMP1)	// Need to prepare KBASE.
+    |  b <4
+    |
+    |7:  // Tailcall from a vararg function.
+    |  andi. TMP0, TMP2, FRAME_TYPEP
+    |  bne <1				// Vararg frame below?
+    |  sub BASE, BASE, TMP2		// Relocate BASE down.
+    |  lwz TMP1, FRAME_PC(BASE)
+    |  andi. TMP0, TMP1, FRAME_TYPE
+    |  b <1
     break;
 
   case BC_ITERC: