DataMuseum.dkPresents historical artifacts from the history of: CR80 Hard and Floppy Disks |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CR80 Hard and Floppy Disks Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 15232 (0x3b80) Types: TextFile Names: »CORU1«
└─⟦d9c1548a9⟧ Bits:30005185 8" CR80 Floppy CR80FD_0182 ( UTILITIES FOR X25 HOH ) └─⟦851bd64f0⟧ └─ ⟦this⟧ »ICL.CORU1«
;======================================================================= ; ; COROUTINE MONITOR, PART 1. ; ;======================================================================= MESSAGE <:CALL: COMON1, 790813:> ;======================================================================= ; ; COROUTINE SYSTEM. ; ; THIS SYSTEM IS A MULTIPROGRAMMING SYSTEM FOR RUNNING A NUMBER OF ; PARALLEL ACTIVITIES WITHIN A SINGLE PROCESS. ; ; THE BASIC ENTITIES ARE: ; COROUTINES (PSEUDO PROCESSES) ; SEMAPHORES (SYNCHRONIZING AND COMMUNICATION PRIMITIVES) ; OPERATIONS (BUFFERS / MESSAGES) ; ; THE BASIC FUNCTIONS ARE: ; SIGNAL (SEMAPHORE) ; WAIT (SEMAPHORE) ; SIGNALCH (CHAINED SEMAPHORES) ; WAITCH (CHAINED SEMAPHORE) ; WAITANSWER (MESSAGEREF) ; WAITMESSAGE ; WAIT-TIMER-OR-INTERRUPT ; ;======================================================================= USE BASE ;----------------------------------------------------------------------- ; ; BASIC DESCRIPTORS: ; ; CHAIN ELEMENTS AND QUEUE HEADS AX=0 SUCC:= AX, AX=AX+1 ; SUCCESSOR (FORWARD CHAIN) PRED:= AX, AX=AX+1 ; PREDECESSOR (BACKWARD CHAIN) CHAINSIZE:= AX ; SIZE OF CHAIN HEAD ; SEMAPHORE AX=0 SEMFST:= AX, AX=AX+1 ; FIRST WAITING COROUTINE SEMLST:= AX, AX=AX+1 ; LAST WAITING COROUTINE SEMVAL:= AX, AX=AX+1 ; SEMAPHORE VALUE SEMSIZE:= AX ; SIZE OF SEMAPHORE ; COROUTINE DESCRIPTION AX=CHAINSIZE ; ROOM FOR CHAIN FIELDS SV0:= AX, AX=AX+1 ; REGISTER SAVE AREA SV1:= AX, AX=AX+1 ; SV2:= AX, AX=AX+1 ; SV3:= AX, AX=AX+1 ; SV4:= AX, AX=AX+1 ; SV5:= AX, AX=AX+1 ; SV6:= AX, AX=AX+1 ; CORUSIZE:= AX ; SIZE OF COROUTINE DESCRIPTOR CCHAIN=0 ; CHAIN FOR INITIALIZATION IF TPON THEN TPOS= 8<TPLS OR 1<SMXS TPSIGN: INXFIL, TPSEM TPWAIT: INXFIL, TPSEM TPSGCH: INXFIL, TPSMOP TPWTCH: INXFIL, TPSEM TPEXIT: INXFIL, TPCORU TPWTTI: INXFIL, TPCORU TPWTMS: INXFIL, TPCORU TPWANS: INXFIL, TPCORU DVAL: 0 TPSM: RELFIL OR BINDAT OR 0<RCLGTS OR 1 DVAL <:SEM :> TPCOR: RELFIL OR BINDAT OR (CORUSIZE-1)<RCLGTS OR 1 DCORU: 0 <:CORU:> TPOP: RELFIL OR BINDAT OR 6<RCLGTS OR 1 DOP: 0 <:OP :> TPSEM: 1, TPSM TPSMOP: 2, TPSM, TPOP TPCORU: 1, TPCOR FI READYQ: RDYFST ; ADDRESS OF READY QUEUE ANSWQ: ANSFST ; ADDRESS OF ANSWER QUEUE MESSC: 0 ; COROUTINE WAITING FOR MESSAGE TINTRC: 0 ; COROUTINE WAITING FOR TIMER ; OR INTERRUPT CURRC: INITCH ; ADDRESS OF ACTIVE COROUTINE ; (REF TO INIT CHAIN AT STARTUP) MSBREF: MSBUF ; REF TO RECEIVED MESSAGE RDYFST: LOC ; EMPTY READY QUEUE RDYLST: LOC-1 ; ANSFST: LOC ; EMPTY ANSWER QUEUE ANSLST: LOC-1 ; MSBUF: 0, REPEAT 4 ; BUFFER FOR RECEIVING MESSAGES USE PROG ;----------------------------------------------------------------------- ; ; MAIN WAITING POINT IN COROUTINE SYSTEM ; ; THE SYSTEM SCHEDULES ALL INTERNAL EVENTS BEFORE EXTERNAL EVENTS ; I.E. COROUTINES ARE ACTIVATED FROM THE READY QUEUE UNTIL THE READY ; QUEUE IS EMPTY. ; FINALLY THE SYSTEM AWAITS SOME EXTERNAL EVENT TO TRIGGER A NEW SERIES ; OF INTERNAL EVENTS. ; ;_______________________________________________________________________ WEVENT: MON INITWAIT ; BASE OF EVENT QUEUE MOVC CDELAY R0 ; DELAY MON SETDELAY ; SETDELAY(DELAY) MOV MSBREF R1 ; MESSAGE AREA JMP MAINWT ; GOTO MAIN WAITING POINT WTNEXT: MON RESUMEEVENT ; RESUMEEVENT AND MAINWT: MON WAITNEXT ; WAIT NEXT EVENT TO ARRIVE JMP & TIMERC ; TIMEOUT, JMP & ANSWRC ; ANSWER, JMP & MESSGE ; MESSAGE ARRIVED JMP & INTRPC ; INTERRUPT) ANSWRC: MOV ANSWQ R7 ; ANSWERQUEUE => R7 NEXTAQ: MOV SUCC. X7 R7 ; NEXT COROUTINE => R7 IEQ R7 ANSWQ ; IF NO MORE IN QUEUE JMP WTNEXT ; THEN GOTO WAIT NEXT EVENT SEQ R2 SV2. X7 ; IF NOT WAITING FOR ACTUAL ANSWER JMP NEXTAQ ; THEN GOTO NEXT IN ANSWER QUEUE MOVL SV0. X7 R0 ; REESTABLISH R0, R1 MOV READYQ R5 ; READY QUEUE MOV R7 R4 ; ACTUAL COROUTINE JMP S6 LINK ; LINK(CURRENT, READY QUEUE) JMP SCHED ; GOTO SCHEDULE MESSGE: MOV MESSC R7 ; WAITING COROUTINE => R7 JOZ R7 WTNEXT ; IF NO WAITING COROUTINE ; THEN GOTO WAIT NEXT EVENT MOV R1 SV1. X7 ; SET BUFFER ADDRESS MOV R2 SV2. X7 ; SET MESSAGE REFERENCE MOVC 0 R0 ; MOV R0 MESSC ; CLEAR REF TO WAITING COROUTINE JMP PREPC ; PREPARE COROUTINE FOR RUN TIMERC: INTRPC: MOV TINTRC R7 ; WAITING COROUTINE => R7 JOZ R7 WTNEXT ; IF NO COROUTINE IS WAITING ; THEN GOTO WAIT NEXT EVENT MOVC 0 R0 ; MOV R0 TINTRC ; CLEAR REF TO WAITING COROUTINE JMP PREPC ; GOTO PREPARE COROUTINE FOR RUN PREPC: MOV R7 R4 ; COROUTINE MOVL SV0. X7 R0 ; REESTABLISH R0, R1 MOV READYQ R5 ; READY QUEUE JMP S6 LINKON ; LINKON(COROUTINE, READYQUEUE) SCHED: MOV READYQ R0 ; READY QUEUE MOV SUCC. X0 R7 ; FIRST ELEMENT IN READY QUEUE IEQ R0 R7 ; IF EMPTY (POINTS TO ITSELF) JMP WEVENT ; THEN GOTO WAIT EVENT MOV R7 CURRC ; SET CURRENT COROUTINE ADDC -7 R7 ; MODIFY POINTER FOR UNSTACK MODC SV6+1 ; UNSTACK UNS 6 ; R0 - R6 NOLIST IF TPON THEN MOV R7 DCORU MON OLTO, TPOS OR 1 TPEXIT MOV CURRC R7 FI LIST JMP 0. X6 ; JUMP TO SAVED LINK ;----------------------------------------------------------------------- ; ; PROCEDURE LINK(ELEMENT, QUEUE) ; ; THIS PROCEDURE MOVES A QUEUE ELEMENT FROM ONE QUEUE TO ANOTHER ; THE ELEMENT IS REMOVED FROM WHEREVER IT IS LINKED BEFORE CALL ; THE QUEUES ARE DOUBLE LINKED ; THE ELEMENT IS LINKED INTO THE QUEUE AS THE VERY LAST ELEMENT ; CALL: EXIT: ; R4 ELEMENT ADDRESS UNCHANGED ; R5 QUEUE ADDRESS UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED ; ; ; PROCEDURE LINKON (ELEMENT, QUEUE) ; ; THIS PROCEDURE LINKS AN ELEMENT INTO A QUEUE. ; THE ELEMENT IS EXPECTED NOT TO RESIDE IN ANY QUEUE WHEN THIS PROCEDURE ; IS CALLED (THE VALUES OF THE CHAIN FIELDS ARE CONSIDERED TO BE IRRE- ; LEVANT. ; CALL: EXIT: ; R4 ELEMENT ADDRESS UNCHANGED ; R5 QUEUE ADDRESS UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED ; ; ; PROCEDURE LINKOFF (ELEMENT) ; ; THIS PROCEDURE REMOVES A QUEUE ELEMENT FROM WHEREVER IT IS LINKED UP ; WHEN THIS PROCEDURE IS CALLED. ; CALL: EXIT: ; R4 ELEMENT ADDRESS UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED LINKOFF:MOV R5 SV5. X7 ; SAVE R5 MOVC 0 R5 ; CLEAR QUEUE LINK: MOVL R0 SV0. X7 ; SAVE R0, R1 ; REMOVE ELEMENT FROM QUEUE MOV PRED. X4 R0 ; PRED.ELEMENT => PREDECESSOR MOV SUCC. X4 R1 ; SUCC.ELEMENT => SUCCESSOR MOV R1 SUCC. X0 ; SUCCESSOR => SUCC.PREDECESSOR MOV R0 PRED. X1 ; PREDECESSOR => PRED.SUCCESSOR JON R5 LINTO ; IF LINKOFF THEN MOV SV5. X7 R5 ; REESTABLISH R5 JMP LNKXIT ; GOTO EXIT LINKON: MOVL R0 SV0. X7 ; SAVE R0, R1 MOV R4 SUCC. X4 ; SET EMPTY CHAIN MOV R4 PRED. X4 ; LINTO: ; LINK ELEMENT INTO QUEUE MOV PRED. X5 R0 ; PRED.QUEUE => OLDLAST MOV R4 SUCC. X0 ; ELEMENT => SUCC.OLDLAST MOV R4 PRED. X5 ; ELEMENT => PRED.QUEUE MOV R0 PRED. X4 ; OLDLAST => PRED.ELEMENT MOV R5 SUCC. X4 ; QUEUE => SUCC.ELEMENT LNKXIT: MOVL SV0. X7 R0 ; REESTABLISH R0, R1 JMP 0. X6 ; RETURN TO LINK ;----------------------------------------------------------------------- ; ; PROCEDURE SIGNAL (SEMAPHORE) ; ; THIS PROCEDURE INCREASES THE VALUE OF A SIMPLE SEMAPHORE BY ONE ; IN CASE THE VALUE WAS NEGATIVE BEFORE CALLING THE PROCEDURE (BECAUSE ; A COROUTINE WAS ALREADY WAITING FOR A SIGNAL) THE FIRST WAITING ; COROUTINE IS LINKED INTO THE READY QUEUE (TO BE ACTIVATED) ; IN ANY CASE THE CALLING COROUTINE WILL BE REACTIVATED AFTER CALLING ; THIS PROCEDURE (NO WAITING POINT) ; CALL: EXIT: ; R5 SEMAPHORE ADDRESS UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED SIGNAL: MOV R4 SV4. X7 ; SAVE R4, MOV R5 SV5. X7 ; R5 MOV R6 SV6. X7 ; AND R6 INC SEMVAL.X5 ; INCREASE SEMAPHORE VALUE BY 1 MOV SEMVAL.X5 R6 ; NOLIST IF TPON THEN MOV R6 DVAL MON OLTO, TPOS OR 2 TPSIGN MOV CURRC R7 FI LIST IGE R6 1 ; IF SEMVALUE > 0 JMP SIGXIT ; THEN GOTO EXIT MOV SEMFST.X5 R4 ; SEMFST.SEMAPHORE => COROUTINE MOV READYQ R5 ; READY QUEUE JMP S6 LINK ; LINK (COROUTINE, READY QUEUE) SIGXIT: MOV SV4. X7 R4 ; REESTABLISH R4, MOV SV5. X7 R5 ; R5, MOV SV6. X7 R6 ; AND R6 JMP 0. X6 ; RETURN TO LINK ;----------------------------------------------------------------------- ; ; PROCEDURE WAIT (SEMAPHORE) ; ; THIS PROCEDURE DECREASES THE VALUE OF A SIMPLE SEMAPHORE BY ONE ; IN CASE THE VALUE WAS NOT POSITIVE BEFORE CALLING THIS PROCEDURE ; (BECAUSE NO SIGNALS WERE READY) THE CALLING COROUTINE IS LINKED TO ; THE SEMAPHORE, WAITING FOR A SIGNAL TO ARRIVE. ; THIS IS A WAITING POINT PROCEDURE. ; CALL: EXIT: ; R5 SEMAPHORE ADDRESS UNCHANMGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED WAITS: MODC SV6+1 ; STACK STC 6 ; R0 _ R6 MOV CURRC R7 ; REESTABLISH R7 DEC SEMVAL.X5 ; DECREMENT (SEMVAL.SEMAPHORE) MOV SEMVAL.X5 R6 ; SEMVAL.SEMAPHORE => SEMVALUE NOLIST IF TPON THEN MOV R6 DVAL MON OLTO, TPOS OR 3 TPWAIT MOV CURRC R7 FI LIST MOV R7 R4 ; CURRENT COROUTINE ILT R6 0 ; IF SEMVALUE < 0 JMP S6 LINK ; THEN LINK (CURRENT, SEMAPHORE) JMP SCHED ; GOT SCHEDULE ;----------------------------------------------------------------------- ; ; PROCEDURE SIGNALCH (SEMAPHORE, OPERATION) ; ; THIS PROCEDURE DELIVERS AN OPERATION AT A CHAINED SEMAPHORE. ; IN CASE A COROUTINE IS ALREADY WAITING AT THE SEMAPHORE, THE OPERA- ; TION IS HANDED TO THIS COROUTINE, WHICH IS THEN PUT INTO THE READY ; QUEUE (FOR LATER ACTIVATION). ; IN CASE NO COROUTINE WAITS AT THE SEMAPHORE, THE OPERATION IS LINKED ; TO IT, WAITING TO BE FETCHED BY WAITCH. ; CALL: EXIT: ; R4 OPERATION ADDRESS UNCHANGED ; R5 SEMAPHORE ADDRESS UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED SIGNCH: MOV R4 SV4. X7 ; SAVE R4, MOV R5 SV5. X7 ; R5, MOV R6 SV6. X7 ; AND R6 INC SEMVAL.X5 ; INCREASE SEMAPHORE VALUE MOV SEMVAL.X5 R6 ; NOLIST IF TPON THEN MOV R6 DVAL MOV R4 DOP MON OLTO, TPOS OR 4 TPSGCH MOV CURRC R7 FI LIST SGE R6 1 ; IF SEMVALUE > 0 JMP SCHLSE ; THEN JMP S6 LINKON ; LINKON(OPERATION,SEMAPHORE) JMP SCHXIT ; ELSE SCHLSE: MOV SEMFST.X5 R4 ; FIRST WAITING COROUTINE MOV READYQ R5 ; READY QUEUE JMP S6 LINK ; LINK(WAITINGCORU, READYQYEYE) MOV SV4. X7 R6 ; OPERATION MOV R6 SV4. X4 ; OPERATION => SV4.WAITINGCORU MOV SV4. X7 R4 ; OPERATION JMP S6 LINKOFF ; LINKOFF(OPERATION) SCHXIT: MOV SV4. X7 R4 ; REESTABLISH R4, MOV SV5. X7 R5 ; R5, MOV SV6. X7 R6 ; AND R6 JMP 0. X6 ; RETURN TO LINK ;----------------------------------------------------------------------- ; ; PROCEDURE WAITCH (SEMAPHORE, OPERATION) ; ; THIS PROCEDURE FETCHES AN OPERATION FROM A SEMAPHORE. ; IN CASE AN OPERATION IS READY WHEN THE PROCEDURE IS CALLED, THE OPE- ; RATION IS SIMPLY HANDED TO THE CALLING COROUTINE. ; IN CASE NO OPERATION IS READY AT CALL TIME, THE CALLING COROUTINE IS ; DELAYED UNTIL AN OPERATION ARRIVES FOR IT. ; CALL: EXIT: ; R4 IRRELEVANT OPERATION ADDRESS ; R5 SEMAPHORE UNCHANGED ; R6 LINK UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED WAITCH: MODC SV6+1 ; STACK STC 6 ; R0 - R6 MOV CURRC R7 ; REESTABLISH R7 DEC SEMVAL.X5 ; DECREMENT (SEMVAL.SEMAPHORR) MOV SEMVAL.X5 R6 ; SEMVALUE NOLIST IF TPON THEN MOV R6 DVAL MON OLTO, TPOS OR 5 TPWTCH MOV CURRC R7 FI LIST SLT R6 0 ; IF SEMVALUE < 0 JMP WCHLSE ; THEN MOV R7 R4 ; CURRENT COROUTINE JMP S6 LINK ; LINK(CURRENTCORU, SEMAPHORE) JMP SCHED ; ELSE WCHLSE: MOV SEMFST.X5 R4 ; FIRST WAITING OPERATION JMP S6 LINKOFF ; LINKOFF(OPERATION) MOV R4 SV4. X7 ; OPERATION => SV4.CURRENTCORU JMP SCHED ; GOTO SCHEDULE ;----------------------------------------------------------------------- ; ; PROCEDURE WAITANSWER (MESSAGEREF) ; ; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED ; UNTIL AN ANSWER ARIVES TO THE MESSAGE POINTED OUT BY MESSAGEREF. ; THIS IS A WAITING POINT PROCEDURE. ; CALL: EXIT: ; R2 MESSAGEREF UNCHANGED ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED WANSW: MODC SV6+1 ; STACK STC 6 ; R0 _ R6 MOV CURRC R7 ; REESTABLISH R7 NOLIST IF TPON THEN MOV R7 DCORU MON OLTO, TPOS OR 6 TPWANS MOV CURRC R7 FI LIST MOV R7 R4 ; CURRENT COROUTINE MOV ANSWQ R5 ; ANSWER QUEUE JMP S6 LINK ; LINK (CURRENT, ANSWER QUEUE) JMP SCHED ; GOTO SCHEDULE ;----------------------------------------------------------------------- ; ; PROCEDURE WAITMESSAGE (EVENT, MESSAGE), (ALREADY AWAITED, NORMAL) ; ; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED ; UNTIL A MESSAGE ARRIVES TO THE PROCESS. ; NOTE, THAT ONLY ONE COROUTINE MAY WAIT FOR MESSAGES AT A TIME. ; (USUALLY A DEDICATED MESSAGE SCHEDULER COROUTINE IS THE ONLY COROU_ ; TINE AWAITING MESSAGES). ; THIS IS A WAITING POINT PROCEDURE. ; CALL: EXIT: ; R1 IRRELEVANT MESSAGE ADDRESS ; R2 IRRELEVANT EVENT ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED WTMESS: MODC SV6+1 ; STACK STC 6 ; R0 - R6 MOV CURRC R7 ; REESTABLISH R7 NOLIST IF TPON THEN MOV R7 DCORU MON OLTO, TPOS OR 7 TPWTMS MOV CURRC R7 FI LIST MOV MESSC R2 ; IF ANOTHER COROUTINE IS WAITING JON R2 0. X6 ; THEN RETURN TO LINK INC SV6. X7 ; ELSE INCREMENT LINK MOV R7 MESSC ; CURRC => WAITING FOR MESSAGE MOV R7 R4 ; CURRENT COROUTINE JMP S6 LINKOFF ; LINKOFF(CURRENT COROUTINE) JMP SCHED ; GOTO SCHEDULE ;----------------------------------------------------------------------- ; ; PROCEDURE WAITTIMER_OR_INTERRUPT (), (ALREADY AWAITED, NORMAL) ; ; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED ; UNTIL THE PROCESS IS INTERRUPTED OR TIMED OUT. ; NOTE, THAT ONLY ONE COROUTINE MAY WAIT FOR THESE EVENTS AT A TIME. ; THIS IS A WAITING POINT PROCEDURE. ; CALL: EXIT: ; R7 CURRENT COROUTINE UNCHANGED ; -- IRRELEVANT UNCHANGED WTINTR: MODC SV6+1 ; STACK STC 6 ; R0 _ R6 MOV CURRC R7 ; REESTABLISH R7 NOLIST IF TPON THEN MOV R7 DCORU MON OLTO, TPOS OR 8 TPWTTI MOV CURRC R7 FI LIST MOV TINTRC R0 ; IF ANOTHER COROUTINE IS WAITING JON R0 0. X6 ; THEN RETURN TO LINK INC SV6. X7 ; ELSE INCREMENT LINK MOV R7 TINTRC ; CURRC => WAITING COROUTINE MOV R7 R4 ; CURRENT COROUTINE JMP S6 LINKOFF ; LINKOFF(CURRENT COROUTINE) JMP SCHED ; GOTO SCHEDULE ;----------------------------------------------------------------------- ; ; COROUTINE INITIALIZATION ; ; THIS PIECE OF CODE INITIALIZES ALL COROUTINE DESCRIPTORS AND PUTS ; ALL COROUTINES INTO THE READY QUEUE. ; THIS IS DONE BY SCANNING THE LIST OF COROUTINE BLOCKS (TYPICALLY ; THERE WILL BE A BLOCK PER COROUTINE TYPE - CONTAINING A NUMBER OF ; OF INCARNATIONS OF THE ACTUAL COROUTINE TYPE). ; INITIALIZATION RECORD AX=0 ICHAIN:= AX, AX=AX+1 ; CHAIN TO NEXT INIT BLOCK IPRPC:= AX, AX=AX+1 ; ENTRY POINT OF COROUTINE ISIZE:= AX, AX=AX+1 ; SIZE OF COROUTINE RECORD ICOUNT:= AX, AX=AX+1 ; NUMBER OF COROUTINES IN BLOCK COINIT: MOV CURRC R1 ; START OF INITIALIZATION CHAIN NXTBLC: JOZ R1 SCHED ; IF NO MORE BLOCKS THEN SCHEDULE ADDC -4 R1 ; START OF INIT RECORD MOV R1 R7 ; CURRENT COROUTINE MOV ICOUNT.X7 R0 ; COROUTINE COUNTER MOV IPRPC. X7 R2 ; ENTRY POINT MOV ISIZE. X7 R3 ; COROUTINE RECORD SIZE MOV ICHAIN.X7 R1 ; ADDRESS OF NEXT BLOCK IN CHAIN MOV READYQ R5 ; READY CUEUE NEXTC: MOV R7 R4 ; CURRENT COROUTINE MOV R7 SUCC. X7 ; INIT CHAIN FIELDS MOV R7 PRED. X7 ; JMP S6 LINK ; LINK (CURRENT, READY QUEUE) MOV R2 SV6. X7 ; SET ENTRY POINT (SAVED LINK) ADD R3 R7 ; NEXT COROUTINE RECORD SOB R0 NEXTC ; REPEAT UNTIL COUNT = 0 JMP NXTBLC ; GOTO NEXT BLOCK «eof»