4.3BSD/usr/contrib/icon/rt/suspend.s
#include "../h/config.h"
/*
* suspend suspends from a built-in procedure (a C function).
* The function calling suspend is suspending and the value to
* suspend is contained in arg0 of its argument list. The generator
* or expression frame immediately containing the frame of the
* suspending procedure is duplicated.
*
* suspend returns through the duplicated procedure frame and the
* arg0 descriptor of the suspending function is left on the
* top of the stack. When an alternative is needed, efail causes
* a return through the original procedure frame which was created
* by the original call to the built-in procedure.
*/
Global(_boundary) /* Icon/C boundary address */
Global(_file) /* Current file name */
Global(_k_level) /* Value of &level */
Global(_line) /* Current line number */
Global(_suspend)
#ifdef VAX
_suspend:
/*
* Construct the generator frame
*/
Mask 0x0fc0 # Start new generator frame by saving
# registers upon entry to suspend.
movl _boundary,r6 # Establish new boundary value and
pushl r6 # save it in the new generator frame.
movl sp,gfp # Point gfp at boundary word in new frame
pushl _k_level # Push &level,
pushl _line # line number,
pushl _file # and file name to complete the frame.
/*
* Determine region to be duplicated and copy it. This is just
* like it's done in psusp.
*/
movl 12(fp),r7 # Low word of region to copy is the
# low word of procedure frame of suspending
# procedure.
movl 8(fp),r2 # Get ap of suspending procedure in r2
movl -8(r2),r4 # Get gfp from procedure frame of suspending
# procedure.
bneq f1 # If it is zero,
movl -4(r2),r4 # get saved efp and
subl2 $8,r4 # use efp - 8.
jmp f2
f1: # gfp is not zero,
subl2 $12,r4 # use gfp - 12.
/*
* Copy region to be duplicated to top of stack.
*/
# r7 points at the low word of the region
# to be copied. r4 points at the high end
# of the region. (i.e. r4 is the first
# word not_ to copy.)
f2:
subl2 r7,r4 # r4 = r4 - r7, giving r4 number of bytes
# in region.
subl2 r4,sp # Move stack pointer down to make space
# for region.
movc3 r4,(r7),(sp) # Copy the region by moving r4 bytes starting
# at r7 to the top of the stack.
/*
* Return from suspending function; resumption will return from suspend.
*/
subl3 12(fp),8(fp),r0 # Calculate distance between fp and ap
# in suspender's frame, specifically,
# r0 = ap - fp
addl2 sp,r0 # sp points at the first word of the
# duplicated procedure frame on the
# stack. By adding it to r0, r0 points
# at nwords word in argument list of
# duplicated frame. That is, r0 is
# serving as a pseudo ap.
subl2 $8,r0 # Point r0 at location of saved gfp
# in duplicated frame.
movl gfp,(r0) # Replace saved gfp with new gfp value
movl sp,fp # Point fp at duplicated procedure frame
# in preparation for return through it.
clrl _boundary # Clear the boundary since control is
# going back into Icon code.
ret # Return through duplicated frame. This
# looks like a return from the original
# call to the built-in function.
#endif VAX
#ifdef PORT
DummyFcn(_suspend)
#endif PORT
#ifdef PDP11
/ suspend - Suspend from a (C) function.
/ Duplicates the most recent generator frame outside the
/ current boundary. Suspend does not return directly.
/ The caller is reactivated when an alternative is needed;
/ the return actually comes from efail.
/ Register usage:
/ r0: pointer to top of stack region to be copied,
/ which is just above the procedure descriptor (arg0) of the
/ suspending procedure
/ r2: suspending procedure frame pointer
/ r3: new generator frame pointer
/ r4: old generator frame pointer, indexed down to r0 during copy
/ r5: current procedure frame pointer
_suspend:
mov r5,-(sp) / create new procedure frame
mov sp,r5
mov r4,-(sp) / save registers
mov r3,-(sp)
mov r2,-(sp)
mov _boundary,r2 / r2 <- pointer to suspending procedure frame
mov r2,-(sp) / save Icon/C boundary address
/ Calculate addresses of new generator frame.
mov sp,r3 / r3 <- pointer to new generator frame
mov _k_level,-(sp) / save &level
mov _line,-(sp) / save current line number
mov _file,-(sp) / and file name
mov 4(r2),r0 / r0 <- pointer to top of region to be copied
asl r0 / (= r2 + 10 + 4*nargs)
asl r0
add r2,r0
add $10.,r0
mov -4(r2),r4 / r4 <- generator frame pointer from caller
bne 1f / use saved r3 (gfp) - 6 if non-zero,
mov -2(r2),r4 / else use saved r4 (efp) - 4
cmp -(r4),-(r4)
br 2f
1:
sub $6,r4
br 2f
/ Copy surrounding expression frame.
1:
mov -(r4),-(sp)
2:
cmp r4,r0 / stop at end of frame
bhi 1b
/ Copy return value of suspending function.
mov -(r4),-(sp)
mov -(r4),-(sp)
/ Return from suspending function; reactivation will return from suspend.
mov 2(r2),r1 / r1 <- return pc
mov (r2),r5 / restore old registers
mov -(r2),r4
tst -(r2) / except generator frame pointer
mov -(r2),r2
clr _boundary / returning to Icon code
jmp (r1) / this really suspends
#endif PDP11