MODULE COROUT(ZIP)= BEGIN %< The BLISS-11 out-of-line create and exchange jump routines >% EXTERNAL $BREG; GLOBAL $PREV; GLOBAL ROUTINE $CREAT(NUMPARMS,ROUTNAME,STKBEGIN,STKLEN,RTRN)= ! ! NUMPARMS - the number of parameters passed to the routine, doubled. ! These are below NUMPARMS on the stack ("above" it, ! in terms of actual addresses). ! ROUTNAME - a pointer to the beginning of the routine code. ! STKBEGIN - not the base of the stack, but the lowest address ! of the block allocated for the stack (i.e. the ! number after "AT" in the user's program). ! STKLEN - the size of the allocated block in bytes. ! RTRN - a pointer to the routine to be executed if the ! - new process tries to do a RETURN. ! BEGIN REGISTER A,BASE; MACRO PUSH(EXP)=(A_.A-2; .A_(EXP))$; A_BASE_.STKBEGIN+.STKLEN-2; DECR I FROM .NUMPARMS TO 1 BY 2 DO PUSH(.(NUMPARMS+.I)); ! Push each argument PUSH(.RTRN); ! Push the return address PUSH(.ROUTNAME); ! Push the Starting Adress A_.A-5*2; ! Save Room for R$1 through R$5 .BASE_.A; .BASE END; GLOBAL ROUTINE EXCHJ(STKBASE)= ! ! The call on EXCHJ pushes the stackbase pointer, and puts ! the value passed in R$0. Since EXCHJ itself doesn't ! fiddle with R$0, the routine is not declared with any ! special linkage type. ! The user may wish to decrease the overhead involved in ! an exchange jump by passing the stackbase pointer in a ! register. This has not been done here, in order to achieve ! full generality--that is, the user who wishes to reserve ! one of the registers need only put the RESERVE declaration ! at the head of the module, and need not rewrite this ! routine. ! BEGIN MACRO SAV[REG]=(REG_.REG+1; REG_.REG-1)$, RST[REG]=$; SAV(R1,R2,R3,R4,R5); $PREV_.$BREG; .$BREG_.SP; $BREG_.STKBASE; SP_..STKBASE; RST(R5,R4,R3,R2,R1); .VREG END; END ELUDOM