Index: core.ops
===================================================================
RCS file: /cvs/public/parrot/core.ops,v
retrieving revision 1.283
diff -u -r1.283 core.ops
--- core.ops	16 Jun 2003 10:43:56 -0000	1.283
+++ core.ops	16 Jun 2003 19:16:58 -0000
@@ -4811,6 +4811,25 @@
   goto ADDRESS(dest);
 }
 
+inline op invokecc() {
+  opcode_t *dest;
+  PMC * p = interpreter->pmc_reg.registers[0];
+  dest = expr NEXT();
+  interpreter->pmc_reg.registers[1] = new_continuation_pmc(interpreter, dest);
+  dest = (opcode_t *)p->vtable->invoke(interpreter, p, dest);
+
+  goto ADDRESS(dest);
+}
+
+inline op invokecc(in PMC) {
+  opcode_t *dest;
+  PMC * p = $1;
+  dest = expr NEXT();
+  interpreter->pmc_reg.registers[1] = new_continuation_pmc(interpreter, dest);
+  dest = (opcode_t *)p->vtable->invoke(interpreter, p, dest);
+  goto ADDRESS(dest);
+}
+
 inline op compile(OUT PMC, in PMC, in STR) {
   $1 = $2->vtable->invoke(interpreter, $2, $3);
   goto NEXT();
Index: sub.c
===================================================================
RCS file: /cvs/public/parrot/sub.c,v
retrieving revision 1.19
diff -u -r1.19 sub.c
--- sub.c	6 Jun 2003 16:02:50 -0000	1.19
+++ sub.c	16 Jun 2003 19:16:58 -0000
@@ -70,6 +70,15 @@
     return cc;
 }
 
+
+PMC * 
+new_continuation_pmc(struct Parrot_Interp * interp, opcode_t * address)
+{
+    PMC* continuation = pmc_new(interp, enum_class_Continuation);
+    ((struct Parrot_Continuation*)PMC_data(continuation))->continuation = address;
+    return continuation;
+}
+
 /*
  * Uses scope_index to find and return the appropriate scope.
  */
Index: include/parrot/sub.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/sub.h,v
retrieving revision 1.12
diff -u -r1.12 sub.h
--- include/parrot/sub.h	29 Jan 2003 18:34:55 -0000	1.12
+++ include/parrot/sub.h	16 Jun 2003 19:16:58 -0000
@@ -49,6 +49,9 @@
 struct Parrot_Continuation * new_continuation(struct Parrot_Interp * interp,
                                               opcode_t * address);
 
+PMC * new_continuation_pmc(struct Parrot_Interp * interp,
+                           opcode_t * address);
+
 void save_context(struct Parrot_Interp * interp,
                   struct Parrot_Context * ctx);
 
Index: classes/sub.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/sub.pmc,v
retrieving revision 1.14
diff -u -r1.14 sub.pmc
--- classes/sub.pmc	6 Jun 2003 15:14:59 -0000	1.14
+++ classes/sub.pmc	16 Jun 2003 19:16:59 -0000
@@ -55,10 +55,6 @@
                       STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
        }
 
-       /* return address that the interpreter should jump to */
-       stack_push(INTERP, &(INTERP->ctx.control_stack), next,
-		  STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
-
        return ((struct Parrot_Sub*)PMC_data(SELF))->init;
    }
 
Index: t/pmc/sub.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/sub.t,v
retrieving revision 1.7
diff -u -r1.7 sub.t
--- t/pmc/sub.t	13 May 2003 02:01:44 -0000	1.7
+++ t/pmc/sub.t	16 Jun 2003 19:16:59 -0000
@@ -1,101 +1,81 @@
 #! perl -w
 
-use Parrot::Test tests => 5;
+use Parrot::Test tests => 6;
 use Test::More;
 
-output_is(<<'CODE', <<'OUTPUT', "PASM subs");
+output_is(<<'CODE', <<'OUTPUT', "PASM subs - invokecc");
     new P0, .Sub
     set_addr I3, func
     set P0, I3
+
     set I5, 3
     save I5
-    invoke
-    print "done 1\n"
-    set I5, 1
-    clone P1, P0
-    set P0, P1
-    save I5
-    invoke
-    print "done 2\n"
+
+    invokecc
+
+    restore I5
+    print I5
+    print "\n"
     end
 
 func:
-    pushi
-    restore I5
     print I5
     print "\n"
+
     eq I5, 0, endfunc
     dec I5
-    save I5
-    invoke
-    inc I5
-    print I5
-    print " done\n"
+
+    save P1
+    invokecc   # recursive invoke
+    restore P1
+
 endfunc:
-    popi
-    ret
+    invoke P1
 CODE
 3
 2
 1
 0
-1 done
-2 done
-3 done
-done 1
-1
-0
-1 done
-done 2
+3
 OUTPUT
 
-output_is(<<'CODE', <<'OUTPUT', "PASM subs with invoke_p");
+output_is(<<'CODE', <<'OUTPUT', "PASM subs - invokecc_p");
     new P0, .Sub
     set_addr I3, func
     set P0, I3
+
     set I5, 3
     save I5
-    invoke P0
-    print "done 1\n"
-    set I5, 1
-    clone P1, P0
-    set P0, P1
-    save I5
-    invoke P1
-    print "done 2\n"
+
+    invokecc P0
+
+    restore I5
+    print I5
+    print "\n"
     end
 
 func:
-    pushi
-    restore I5
     print I5
     print "\n"
+
     eq I5, 0, endfunc
     dec I5
-    save I5
-    invoke P0
-    inc I5
-    print I5
-    print " done\n"
+
+    save P1
+    invokecc P0  # recursive invoke
+    restore P1
+
 endfunc:
-    popi
-    ret
+    invoke P1
 CODE
 3
 2
 1
 0
-1 done
-2 done
-3 done
-done 1
-1
-0
-1 done
-done 2
+3
 OUTPUT
 
-output_is(<<'CODE', <<'OUTPUT', "Continuations");
+output_is(<<'CODE', <<'OUTPUT', "Continuation");
     new P5, .PerlInt
     set P5, 3
     store_global "foo", P5
@@ -128,7 +108,7 @@
 done
 OUTPUT
 
-output_is(<<'CODE', <<'OUTPUT', "definedness of continuations");
+output_is(<<'CODE', <<'OUTPUT', "definedness of Continuation");
     new P1, .Continuation
     defined I1, P1
     print I1
@@ -163,52 +143,85 @@
     set_addr I3, foo
     set P0, I3
 
-    new P1, .PerlInt
-    set P1, 5
+    new P11, .PerlInt
+    set P11, 5
 
-    invoke
-    set P0, P2 # move sub $f to P0 for invoke
+    invokecc
+    set P0, P2 # move sub $f to P0 for invokecc
 
-    new P1, .PerlInt
-    set P1, 3
+    new P11, .PerlInt
+    set P11, 3
+
+    save P0
+    invokecc
+    restore P0
 
-    invoke
     print P2
     print "\n"
 
-    invoke
+    save P0
+    invokecc
+    restore P0
+
     print P2
     print "\n"
 
-    invoke
+    invokecc
     print P2
     print "\n"
 
     end
 
-# foo takes a number n (P1) and returns a sub (in P2) that takes
-# a number i (P1) and returns n incremented by i.
+# foo takes a number n (P11) and returns a sub (in P2) that takes
+# a number i (P11) and returns n incremented by i.
 foo:
     new_pad 0
-    store_lex 0, "n", P1
+    store_lex 0, "n", P11
     new P2, .Sub	# P2 has now the lexical "n" in the pad
     set_addr I3, f
     set P2, I3
-    pop_pad
-    ret
+    invoke P1
 
-# expects arg in P1, returns incremented result in P2
+# expects arg in P11, returns incremented result in P2
 f:
     find_lex P2, "n"	# invoke-ing the Sub pushes the lexical pad
     			# of the closure on the pad stack
-    add P2, P1		# n += shift
-    pop_pad		# clean up
-    ret
+    add P2, P11		# n += shift
+    invoke P1
 
 CODE
 8
 11
 14
+OUTPUT
+
+output_is(<<'CODE', <<'OUTPUT', "PASM subs - tail invoke");
+    new P0, .Sub
+    set_addr I3, func1
+    set P0, I3
+
+    invokecc
+    print "done\n"
+    end
+
+func1:
+    print "in func1\n"
+
+    new P0, .Sub
+    set_addr I3, func2
+    set P0, I3
+
+    invoke    # tail invoke (reuses context already in P1)
+    print "this should not be called\n"
+
+func2:
+    print "in func2\n"
+    invoke P1
+
+CODE
+in func1
+in func2
+done
 OUTPUT
 
 1;
Index: languages/imcc/t/syn/bsr.t
===================================================================
RCS file: /cvs/public/parrot/languages/imcc/t/syn/bsr.t,v
retrieving revision 1.8
diff -u -r1.8 bsr.t
--- languages/imcc/t/syn/bsr.t	12 Jun 2003 07:51:26 -0000	1.8
+++ languages/imcc/t/syn/bsr.t	16 Jun 2003 19:16:59 -0000
@@ -293,7 +293,7 @@
    $I0 = addr _fact
    set P0, $I0
    saveall
-   invoke
+   invokecc
    save I5
    restoreall
    restore $I0
@@ -309,7 +309,7 @@
    dec I6
    branch _fact
 fin:
-   ret
+   invoke P1
 .end
 
 CODE
