%%off %%% %%% Trips %%% %%on LOC 0 \.{TRIP X,rY,Z} entry point. GET $0,rW STOU $0,C,NextInst Store return address. GET $2,rY Prefetch \.{rY}. GET $0,rX AND $3,$0,#FF Prefetch \.{Z}. SR $0,$0,16 AND $0,$0,#FF Extract \.{X} GO $0,$0,0 Dispatch on \.{X} Resume PUT rJ,$255 Restore \.{rJ} GET $255,rB Set return value \.{\$255} from \.{rB}. RESUME 0 %%% %%% TRIP Start,$Coroutine,Z %%% return immediately %%% removes the coroutine in $Y from all queues. %%% inserts the coroutine in $Y with a delay of Z units %%% setting its next instruction to $255. %%\mmsskip % \.{TRIP Start,\$Y,Z} will start coroutine \.{\$Y} at \.{\$255} after delay \.{Z}. Start GET $0,rB Get \.{\$255} through \.{rB}. STOU $0,$2,NextInst Store the code addess to the %%% %%% TRIP Continue,$Coroutine,Z %%% returns immediately %%% removes the coroutine in $Y from all queues. %%% inserts the coroutine in $Y with a delay of Z units %%% like Start without changing the next instruction. %%\mmsskip % \.{TRIP Continue,\$Y,Z} will continue coroutine \.{\$Y} after delay \.{Z}. Continue SET $5,$2 coroutine \.{rY}. PUSHJ $4,Delete Remove the coroutine from signals. ADDU $5,$2,WaitList Coroutine \.{rY} as \.{Wait} list. PUSHJ $4,Delete Remove it from the \.{Wait} list, PUSHJ $1,WaitSorted and insert it again with delay \.{Z}. JMP Resume %%% %%% TRIP Send,$Signal,0 %%% returns 1 immediately if the signal queue is empty. %%% returns 0 after transfering control to the receiver otherwise. %%\mmsskip % \.{TRIP SendT,\$Y,0} will send signal \.{\$Y} to the tail of the queue (LIFO). % Returns nonzero in \.{\$255} if the queue is empty. SendT LDOU $1,$2,Left Get the receiver from the tail. JMP 1F %%% %%\mmsskip % \.{TRIP Send,\$Y,0} will send signal \.{\$Y} to the head of the queue (FIFO). % Returns nonzero in \.{\$255} if the queue is empty. Send LDOU $1,$2,Right Get the receiver from the head. 1H PUT rB,1 Return value 1. CMP $0,$2,$1 Is the queue empty? BZ $0,Resume If so, resume. %%% SET $3,C Now, the sender PUSHJ $2,WaitFirst is inserted in the wait list. ADDU $3,$1,WaitList Convert receiver to \.{Wait} list. JMP Next Activate it. %%% %%% TRIP Receive,$Signal,0 %%% Added at the end of the Signal queue. %%% Will return when the signal is sent. %%\mmsskip % \.{TRIP Receive,\$Y,0} will wait until signal \.{\$Y} is received. Receive NEG $0,1 PUT rZ,$0 A negative delay will cause a Pause. %%% TRIP Expect,$Signal,$Z %%% Added sorted in the Scheduler %%% and at the end of the Signal queue. %%% Returns 1 if the signal has arrived %%% and returns 0 if the time $Z has elapsed %%\mmsskip % \.{TRIP Expect,\$Y,\$Z} will wait until signal \.{\$Y} is received % or the timeout delay \.{\$Z} has expired. % Returns nonzero in \.{\$255} if the signal has arrived. Expect SET $1,C Get current coroutine. PUSHJ $0,InsertLeft Enqueue in signal. %%% %%% TRIP Delay,0,$Z %%% Wait until the time in $Z has passed. Pause if $Z<0. %%\mmsskip % \.{TRIP Delay,0,\$Z} will wait for \.{\$Z} units of time. Delay GET $3,rZ Get the delay from \.{\$Z}. BN $3,Pause Pause if delay negative. %%% %%% TRIP DelayI,0,Z %%% Wait until the time in Z has passed. %%\mmsskip % \.{TRIP Delay,0,Z} will wait for \.{Z} (immediate constant) units of time. DelayI SET $2,C Get current coroutine. PUSHJ $1,WaitSorted Insert it into the \.{Wait} list. %%% %%% TRIP Pause,0,0 %%% Returns when activated again. Continue with the next coroutine. %%\mmsskip % \.{TRIP Pause,0,0} will wait indefinitely until reactivated by \.{Start} or \.{Continue}. Pause LDOU $3,Wait,Right This list is never empty. SUBU $1,$3,WaitList Convert to a coroutine. LDTU time,$1,:NextTime \qquad Advance the clock. PUT rB,0 Set return value to 0. Next PUSHJ $2,Delete Delete from \.{Wait} list. PUSHJ $0,Delete Remove from signal. SET C,$0 Make current coroutine. LDOU $0,C,NextInst Get the next instruction PUT rW,$0 and prepare to \.{RESUME}. SET $0,1670 when to end simulation %%hide CMP $0,$0,:time %%hide BNP $0,9F %%hide JMP Resume 9H SET $255,0 %%hide TRAP 0,:Halt,0 %%hide %%off