*B ; 02-DEC-71 ; CLOCK INITIALIZE ROUTINE ; * G U L F E L E C T R O N I C S Y S T E M S * .TITLE CLINIT .DEF CLINIT .REF T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .REF HEADER,TSTAT,TPRTY,TASKS .REF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF THDTAB,CURTHD,SWAITB,STBPTR,COUNTR,SKDBSY,ABMPLR CLINIT: ;INIT SUBROUTINE FOR TIMERS AND SCHEDULER MOV #TWAITB,R0 ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "EMTRAP" * ; * EMULATOR TRAP SERVICE ROUTINE * ; * * ; * PURPOSE: DECODES ALL EMT CALLS AND TRANSFERS CONTROL TO PROPER* ; * SUBROUTINE, AFTER ALTERING STACK TO LOOK IDENTICAL TO A * ; * "JSR PC,SBRTNE". ; 09-DEC-71 ; TIMER TASK MODULE FOR TESTING TIMERS .DEF T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .DEF T.37HD,T.38HD .TITLE MWKTST SP=%6 EXIT = 4 QTIME = 7 DQTIME = 10 QSKED = 11 DQSKED = 12 TTYOUT = 13 NN = 20. ;# WORDS RESERVED IN EACH TASK'S STACK T.30PR = 1 T.31PR = 1 T.32PR = 2 T.33PR = 3 T.34PR = 4 T.35PR = 5 T.36PR = 1 T.30IN = 0 T.31IN = 0 T.32IN = 0 T.33IN.ôt!¯”Ÿ s@€}@ú&ày@©.;K}@hf€p@”f�@[gÐ4@�m„@Á.[qj@€y‹@ €` @L©C @R«ª:@.(�òehÌôt!h¯xh-²ZhÊó.D~hÎA*}h»ŒEhtJ&) hm4€phr.¶>) h!? MOV R0,TTBPTR MOV #$TWATZ+1+$NRES,R1 A.: CLR (R0)+ ;CLEAR BOTH WAIT AND FIRST TABLES DEC R1 BNE A. MOV #TLAST-2,R0 MOV #$NRES-1*2,R1 B.: MOV R0,TLAST(R1) ;INIT ALL "LASTS" WITH ADDR'S OF FIRSTS TST -(R0) DEC R1 DEC R1 BGE B. MOV #RESTAB+$NRES,R0 MOV #$NRES-1,R1 C.: MOVB -(R0),CURTAB(R1) ;INIT RESOLUTION COUNT * ; * * ; * USAGE: ALL EXTERNAL LINKS TO MONITOR SUBROUTINES ARE MADE VIA * ; * CALLS OF THE FORM: "EMT SNUMBER", WHERE "SNUMBER" IS A * ; * PRE-ASSIGNED INDEX TO THE TABLE OF MONITOR SUBROUTINES. ANY * ; * ARGUMENTS REQUIRED BY THE SUBROUTINE MUST BE PUSHED ONTO THE * ; * STACK PRIOR TO THE CALL. UPON ENTRY TO THE SUBROUTINE THE STACK* ; * WILL LOOK THE SAME AS IF A "JSR PC,SBRTNE" HAD BEE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "SETGET" * ; * SET TIME SET DATE GET TIME GET DATE * ; * * ; * ROUTINES TO SET AND GET CURRENT TIME AND DATE * ; * = 0 T.34IN = 0 T.35IN = 0 T.36IN = 0 TMWRD0: .BYTE 5 ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD1: .BYTE 10. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD2: .BYTE 15. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD3: .BYTE 5 ;DELAY COUNT .BYTE 5 ;RESET TIME TMWRD4: .BYTE 10. ;DELAY COUNT .BYTE 10. ;RESET TIME TMWRD5: .BYTE 15. ;DELAY COUNT .BYTE 15. ;RESET TIME ERS DEC R1 BGE C. MOVB #-1,TIMBSY MOVB #-1,SKDBSY CLRB BASCNT CLR ABMPLR MOV #THDTAB,CURTHD ;FOR SCHEDULER MOV #SWAITB,STBPTR CLR COUNTR .PAGE ; NOW INIT TASKS FOR TEST PGM MOV #HDLIST,R0 MOV #HEADER+60.,R1 MOV #TSTAT+30.,R2 MOV #TPRTY+30.,R3 MOV #7,R4 A: MOV (R0)+,(R1)+ CLRB (R2)+ N THE CALL. * ; * THIS ALLOWS CALLS OF THE JSR-TYPE TO BE COMPATIBLE WITH THE * ; * EMT-TYPE CALLS. ALTHOUGH PROCESSOR STATUS IS RAISED TO LEVEL * ; * SEVEN DURING THE TRAP ROUTINE, IT IS RETURNED TO ITS STATE * ; * AT THE TIME OF CALL WHEN THE CALLED SUBROUTINE IS ENTERED. * ; * * ; * STACK ON ENTRY: * ; * 2(SP): (PS) AT TIME OF TRAP / * ; * USAGE: * ; * USED BY GENERAL ROUTINES TO FETCH CURRENT TIME * ; * AND/OR DATE. USED BY OPERATOR INPUT PROGRAM TO SET * ; * TIME AND/OR DATE FROM TTY KEYBOARD. * ; * * ; * CALLING SEQUENCES: * ; * MOV NEWHR,-(SP) ;PUSH NEW HOUR  TMWRD6: .BYTE 0 ;DELAY COUNT .BYTE 0 ;RESET TIME .PAGE T.30HD: .WORD 1 ;THREAD WORD .WORD T.30BG ;TASK ENTRY .WORD T.30IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.30PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;S MOVB R4,(R3)+ DEC R4 BNE A CMP TASKS,#36. BGE X MOV #36.,TASKS RTS PC HDLIST: .WORD T.30HD,T.31HD,T.32HD,T.33HD,T.34HD,T.35HD,T.36HD .END È}háQ@œh¶Re†h¦S@~h¼.U; hÈCmàh2‹wô_h|x‘hây2ghÚz.Yzb;hÜD~*}hÐk~[h �€ph¯”©÷æ.7Š"÷ Ä@÷¼÷ ¶:· °7fÁñ‹“$R«ª:(”f�.&)×-e�‰Àð•7þÿ÷ ÷àþÿE.L©C L©C  €` þÿ"€y‹(þÿ,L÷•Ô& æ¦Á B¹±±¥.[qjú&ày;K}";K}&ú&ày{,p9 ‚��æ÷ * ; * (SP): (PC) CALLER RETURN ADDRESS * ; * * ; * STACK ON EXIT: * ; * (SP): (PC) CALLER RETURN ADDRESS * ; * * ; * ERROR RETURNS: IF AN EMT CODE IS USED WHICH IS INVALID * ; * ---EITHER OUTSIDE THE LIMITS OF THTATUS .BYTE 30. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.31HD: .WORD 1 ;THREAD WORD .WORD T.31BG ;TASK ENTRY .WORD T.31IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.31PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 .u~#"¯”hf€p@H[gÐ4@H�m„@HŽ.[qj@Hz4f@Hƒ…4f@HL©C @HR«ª:@Hl.(Ê» hÅ*}h³¼M:hzimRhð.[q*}h¢ù}Œshbu~‘hÄu~"hðá~àyh‚"€2gh6™€b;h8¯”F÷æ, & æ÷Š„7ŠT&;K}L©C Ÿ s€}X,”˜&fÀЕ<ˆŠ¢<9·Š€ŠˆŠ¢<2Ž  Î,¸ŠˆŠ¢-Šˆ "ÁPP�P�ˆŠ÷•8,Ü)÷mäÿȵ· Úÿ·Š Á@”‰Šp¢è&‚, É•¡Š÷ÐÀ÷µ÷e²�€·Š÷` Ð,$µ‰–%!À˜G7þÿ&÷ ^º þÿÓ,H·£Í< ·­¿7·­´2÷àþÿÆe1 "þÿE EMT TABLE, OR AN INVALID * ; * CODE WITHIN THE TABLE--- A RETURN IS MADE IMMEDIATELY TO THE * ; * CALLER WITH NO ACTION TAKEN. * ; * THE CALLER SHOULD NOTE THAT HE MAY BE INTERRUPTED BETWEEN HIS * ; * EMT CALL AND THE EVENTUAL RETURN, EVEN IN THE CASE OF AN ERROR.* ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.003  ;STATUS .BYTE 31. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.32HD: .WORD 1 ;THREAD WORD .WORD T.32BG ;TASK ENTRY .WORD T.32IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.32PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT æþÿ÷àþÿ&×-&`‚€È ÷e?Bþÿ þÿ``,$ð �6 °È €¶Èeø¬É,Hÿÿôîð�¶ö÷•[¶üÿoL©C z4fB,l÷ŠSû& Æå Û¦öþÿ÷àþÿw €ïþÿþÿ"[gÐ4Ã,�È%ð•ÿÿÈ%ÿÿœÁEðÿÁ Cw º0´·  ÁebBA  ûJ³‚É6 w ‡ b‚*hf€pã,Ü0œ¢³€ ð‹¢"$·ŠÐô‰À:÷å8Ï,l"ß2 È7þÿB €f÷ 9 þÿÛ0�÷ DÑ &÷ –Ö Â‹ ¦�& &  €NÑ & ÷ «*�m„70¸Ö  º€yܶÆe÷àþÿ÷•ÿÿEw÷àþÿÅþÿ$[qj*þÿÂ,àÀöò÷åîÈð5ô7þÿ&÷ ¢ þÿÓ,ð5ðE÷ —-?ö�ð—- ,( ö�ã·­Ú¶ Î Î�ÑÁ‚{,L·£É  ·­»·­°Ñ BÆe†,p�‚¦÷ (Ž- * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE EMTRAP .REF QUEUE,SUSPND,UNSPND,EXIT,FRETSK,ABORT,QTIME,DQTIME  .BYTE 0 ;STATUS .BYTE 32. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.33HD: .WORD 1 ;THREAD WORD .WORD T.33BG ;TASK ENTRY .WORD T.33IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.33PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WOR ¢ ³¢Á,2ȬÿÿôœÁEðÿW íÁ 9‚W &‚F0$1‚ æ7þÿ ðгÔÀ À À fÁb`÷àþÿE‚þÿ³"b*þÿÍ,L7�vBABW¬ÿùñŠöCEqœ,pJ°‚É…7þÿœó‹æœ& ‹  ‚þÿJ,”€÷ & Â5@Î& ÷ Ö ÂŒ€Ó ÂŒDƒ…4f�m„�,¸€ûÜÓ$ÂŒ€&&fû …„€A¶÷“˜,Üè÷ æ«Áb`BA¥W,ÿúJ°‚fô ¶-ï¶- ”,”êÆeÆe ˆšæ ¦ƒÅöEÀÿg,¸à à ÃÃEàÿöÅ… … … ÅEàÿv‡…Ã�],Ü;Õ`Ã�1Õ`Ã�*Í`Í%<Íå<µ þÿå%õ,ÍåŽ Ã�ÜÎ ÎàÎÎ Î Î ö¶ Û ×,$¶ ŽUŽU°‡¦öþÿ&÷àþÿ×-”Eþÿ þÿ&„,H†€ðEÈ Èe÷et?p6 ,lÈ €¦öþÿw €÷àþÿÈ%þÿ[gÐ4 þÿÓ.�È%ÿÿÅÁ .REF QSKED,DQSKED,TTYOUT,TTYIN,BINASC,ASCBIN .REF MASK,UNMASK,ERRTYP .IFNZ NDISCS .REF DISCIO .ENDC NDISCS .DEF EMTRAP,EMTABL,MAXEMT .PAGE EMTRAP = . ;ENTRY TO EMT SERVICE ROUTINE ;TIMING: 64 MICROSECONDS TST -(SP) ;PUSH STACK TO MAKE ROOM FOR SBRTNE ADDR MOV R0,-(SP) ;SAVE IT MOV 4(SP),R0 ;CALLER RETURN ADDR MOV 6(SP), D 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 33. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.34HD: .WORD 1 ;THREAD WORD .WORD T.34BG ;TASK ENTRY .WORD T.34IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.34PR ;TASK PRIORTY .WORD 0 ;TASK TIME!b&‚Ï,É÷ Àñ—ÀbÁ÷àþÿÐ Á üÿ âbþÿZ$÷Š˜wúþw8f[qj8bY(bp ‚e(‚P ¢E¢dª ²5²d™ Ã$ Ã+ È È(ÖBA  ûJÉ6 w ÑÖ(hf€p.¶ÁØÅ ïøðUòÐÖØÖÜ ØÐÖ Ø"Ö(Ü Ü ßGÿó#4(SP) ;MOVE CALLER'S PS FOR RTI EXIT MOV R0,6(SP) ;WILL LEAVE CALLER'S PC ON STACK @ EXIT DEC R0 ;BACK POINTER ONE BYTE MOVB -(R0),R0 ;BACK POINTER TO EMT INSTR&GET EMT CODE ASL R0 ;NEED TO INDEX WORDS IN TABLE CMP R0,#MAXEMT*2 ;SEE IF CODE IS VALID BHI EMTA20 ;INVALID: OUTSIDE TABLE RANGE EMTA10: MOV EMTABL(R0),2(SP) ;LOAD STACK WITH SUBROUTINE ADDR ; IF $R .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 34. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.35HD: .WORD 1 ;THREAD WORD .WORD T.35BG ;TASK ENTRY .WORD T.35IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.35PR ;TASK PRIORTY .WORD 0 ó&æþÿ÷àþÿ&×-Äþ‚€È ÷e²?eþÿ þÿþÃ,$®÷Uþð �6 °È €¶Èe�  þæ2Hø¬ÿÿôîð�¶öæ¦öþÿ¬L©C  z4f*þÿ,r÷àþÿw €È%È%ÿÿœÁEðÿÁ Ùþÿ [gÐ4 ,–CÁeBA  ûJ³ É6 w û &hf€p³,ºð•ÿÿ÷0œ@Q€ ð‹@"$·Š‡ôß@Q@Ï,ÞÀò'AN INVALID CODE IS USED, THE TABLE ENTRY WILL POINT TO "EMTERR". MOV (SP)+,R0 ;RESTORE USER'S RTI ;POP SUBRTNE ADDRESS AND OLD STATUS ;TO EFFECT TRANSFER, LEAVING RTN TO ;CALLER ON TOP. EMTA20: CLR R0 ;RANGE ERROR: USE ENTRY 0... BR EMTA10 ;...AND FORCE EXIT VIA "EMTERR" .PAGE EMTERR: RTS PC ;ERROR RETURN USED FOR I( ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 35. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.36HD: .WORD 1 ;THREAD WORD .WORD T.36BG ;TASK ENTRY .WORD T.36IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.36PR ;TASK PRIORTY .W)NOT "SKED" MOV R0,-(SP) MOV R1,-(SP) MOV #CLOCK,R0 ;POINTER TO TIME & DATE BYTES MOVB #TICRES,(R0)+ ;RESET [TICTOC] INCB (R0) ;NEXT SECOND CMPB (R0),#60. ;NEW MINUTE? BLT CALA40 ;NO: BUT GO TO END TO RUN "SKNSRT" INCB SKSWCH ;SET TO RUN "SKED" AND NOT "SKNSRT" CLRB (R0)+ ;RESET [SECOND] & GO ON TO... INCB (R0) ;...BU*÷åêȬÿÿôœÁEðÿW ‰0íÁ 9 1  æ7þÿ ðŠQÔÀ À À AÁÑ  þÿQ*Ð0*`÷àþÿBAôñŠúCEqœJ° 7 þÿ* –,RÉ…7þÿœó‹æœ& ‹€÷ @ þÿ$ƒ…4f,v& Â5@Î& ÷ Ö ÂŒ€Ó ÂŒ€û܆�m„M,šÓ$ÂŒ€û AÂÀÁ÷àþÿÐ Á üûþÿ¸"¾ÿ ÷Eþ÷Š“¡wÖµ+NVALID CODES EMTABL = . ;TOP OF EMT LINK TABLE .WORD EMTERR ;#0 ALWAYS AN ERROR .WORD QUEUE ;#1 .WORD SUSPND ;#2 .WORD UNSPND ;#3 .WORD EXIT ;#4 .WORD FRETSK ;#5 .WORD ABORT ;#6 .WORD QTIME ;#7 .WORD DQTIME ;#10 .WORD QSKED ;#11 .WORD DQSKED ;#12 ,ORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 36. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.37HD: .WORD 1 ;T/W .WORD T.37BG ;ENTRY .WORD 0 ;TASK INIT .WORD 0 ;MAX X-TIME .BYTE NN ;STACK SIZE .BYTE 0 ;PRIORIT-MP [MINUTE] CMPB (R0),#60. ;NEW HOUR? BLT CALA40 ;NO: BUT GO RUN SCHEDULER CLRB (R0)+ ;RESET [MINUTE]... INCB (R0) ;...AND BUMP [HOUR] CMPB (R0),#24. ;NEW DAY? BLT CALA40 ;NO CLRB (R0)+ ;YES: RESET [HOUR]... INC (R0) ;...AND BUMP [JDATE] CMP (R0),(PC)+ ;NEW YEAR? MXDAYS: .WORD 0 ;HOLDS #DAYS IN CU.þ[qjÖ(Ò  Ç( ² @§@d  P—Pdû a† a�ó .WORD TTYOUT ;#13 .WORD TTYIN ;#14 .WORD EMTERR ;#15 CURRENTLY UNUSED .WORD BINASC ;#16 .WORD ASCBIN ;#17 .WORD MASK ;#20 .WORD UNMASK ;#21 .WORD ERRTYP ;#22 .IFNZ NDISCS .WORD DISCIO ;#23 .ENDC NDISCS MAXEMT = .-EMTABL/2 .END 0Y .WORD 0 ;TIMER .WORD 0 ;ARG .BYTE 0 ;STATUS .BYTE 37. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.38HD: .WORD 1 ;T/W .WORD T.38BG ;ENTRY .WORD 0 ;TASK INIT .WORD 0 ;MAX X-TIME .BYTE NN ;STACK SIZE .BYTE 0 ;PRIORITY .WOR1RRENT YEAR BLE CALA30 ;NO: GO TO NEXT DAY + MAYBE NEW MONTH ;HAPPY NEW YEAR!! MOV #1,R1 MOV R1,(R0)+ ;RESET [JDATE] MOVB R1,(R0)+ ;RESET [MONTH] MOVB R1,(R0)+ ;RESET [MDAY] INCB (R0) ;BUMP TO NEW YEAR MOVB #28.,FEBARY ;RESET FEBRUARY MOV #365.,MXDAYS ;RESET YEAR LENGTH BITB #3,(R0) ;IS THIS A LEAP YEAR3 * ; * MOV NEWMIN,-(SP) ;PUSH NEW MINUTE * ; * JSR PC,STIME ;CALL "SET TIME" * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * ---------------- * ; * MOV NEWMTH,-(SP) ;PUSH NEW MONTH * ; * MOV NEWDAY,-(SP) ;PUSH NEW 4D 0 ;TIMER .WORD 0 ;ARG .BYTE 0 ;STATUS .BYTE 38. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.30BG: ;TASK #30 BEGIN MOV #MODUL0,-(SP) MOV TMWRD0,-(SP) EMT QTIME ;QUEUE ONE TIMER MODULE TST (SP)+ MOV #LIST30,-(SP) EMT TTYOUT ;TYPE TASK I.D. 5? BNE CALA35 ;NO INC MXDAYS ;YES: BUMP YEAR LENGTH INCB FEBARY ;...AND FEBRUARY BR CALA35 CALA30: ;HERE @ BEGIN OF DAY & NOT NEW YEAR MOV #MONTH,R1 ;INIT POINTER TO DATE BYTE TABLE MOVB (R1)+,R0 ;[MONTH]: USED AS INDEX INCB (R1) ;[MDAY]: NEW DAY CMPB (R1),DAYTAB(R0 ;[MDAY]: END OF MONTH BLE CALA40 ;NO 6.©üX¯”» @H-²Z@H*}@Hº.D~@HÉ2Ú@H[q*}@Hây2g@HYzb;@H].;}¸G@Hù}Œs@HD~*}@Hu~‘@Há~ày@H4.’è€@H €` @H"€2g@H™€b;@H��ļ@H3.��Ã@H��DÉ@H��„Ï@H��ÄÕ@H��Ü@Hj&��Dâ@H7DAY * ; * MOV NEWYR,-(SP) ;PUSH NEW YEAR * ; * JSR PC,SDATE ;CALL "SET DATE" * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * ---------------- * ; * JSR PC,GDATE ;CALL "GET DATE" * ; * MOV (SP*+,CURYR ;PE EMT EXIT T.31BG: ;TASK #31 MOV #LIST31,-(SP) EMT TTYOUT MOV #MODUL2,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #LIST31,-(SP) EMT TTYOUT EMT EXIT T.32BG: ;TASK #32 MOV #MODUL3,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ MOV #MODUL4,-(SP) MOV TMWRD1,-(SP) EMT F MOVB #1,(R1) ;RESET DAY TO FIRST OF MONTH INCB -(R1) ;NEXT MONTH: CAN'T BE JANUARY (ABOVE) CALA35: ;HERE TO ADJUST THE THREAD POINTER POINTER AT THE BEGIN ; OF EACH MONTH. "CURTHD" ALWAYS POINTS TO "TH1BGN" DURING ; ODD-NUMBERED MONTHS, AND TO "TH2BGN" DURING EVEN MONTHS. MOV #THDTAB,CURTHD ;INIT THREAD-START TABLE POINTER BITB #1,MONTH ;ODD-NUMBERED MONTH? BNE CALA40 ;YG(Š©üXh¯”•÷æ,À7Á% Á ýÀþÿÁ1à Á Á M&™€b; "€2gá~àyþÿ á~ày($úÀÁ1˜Á ü7Š7Š÷Æ6[q*}*}u~‘»  D~*}"D~îD÷7 À|Á<Âõ2Yzb;ây2g -²Z|É2Ú< €` ì,ZÃÄŠ‘Ä û×-$÷$‡Š&’è€;}¸G";}¸G&��ļÒ~lHOP CURRENT YEAR (-1900) * ; * MOV (SP*+,CURDAY ;POP CURRENT DATE * ; * MOV (SP*+,CURMTH ;POP CURRENT MONTH * ; * ---------------- * ; * JSR PC,GTIME ;CALL "GET TIME" * ; * MOV (SP*+,CURHR ;POP CURRENT HOUR * ; * MOV (SP*+,CURMIN ;POP CURRENT MINUTE * ; * MOV (SP*+,CURS""D„ˆˆˆ """"""""""@DD€€ˆ""D"""DDDDDDDDDDDD€ˆˆDDD""""""""""""""""ADD*B €€B C©üX4d8 ›\!4d8 +›ãT €4d@#™›ôt!^÷›œwœ,4d8x›u~#"^÷!›ôt!4d8|6V6.›.ù ›/2G›* K»›)Ýñ›u~#"4d6¿1‘›8ÎN›.›//È$Dÿÿÿÿ›™™ÿ?3333333333‘™™LLff&DTUfffffffff"""""""ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅaå Í‹æÄ,L ƒw:ÄB8ŽŒ ýƒàÇ` 5 þÿ€�&ˆ ‚— ýÿ†ƒœÃEÀÿ× >w†× × ò f€ò5ÀeòU@ò €× [æ*ˆ² ¦¦æ× Ž & *ˆÖ G× ‚&(ˆ°Ì 8�L'ˆ°4e÷ ÌQ$ ô �BBâBä" ± üÿü× ÷ ¬ŒÉU@Ò °ðU€ Æe  Å"U%÷‹äþGæÎeÞþæfÇ.Ö … U¥… … … … U¥Ñ Bb‘â‹Ã 0Š æ*ˆ€�Ö BÃÅ.&0 æM &0 & I QTIME TST (SP)+ MOV #MODUL5,-(SP) MOV TMWRD2,-(SP) EMT QTIME TST (SP)+ MOV #LIST32,-(SP) EMT TTYOUT EMT EXIT .PAGE T.33BG: ;TASK #33 MOV T.33HD+14,T.33AR ;TRANSFER ARGUMENT MOV #LIST33,-(SP) EMT TTYOUT EMT EXIT T.34BG: ;TASK #34 MOV T.34HD+14,T.34AR ;TRANSFER ARGUMENT MOV #LIST34,-(JES: LEAVE AS IS ADD #2,CURTHD ;EVEN: ADVANCE TO POINT TO THREAD #2 CALA40: ;HERE ON EVERY MINUTE BOUNDARY TO RUN... ;...THE SCHEDULER. ON THE OTHER 59 SECONDS, RUN "INSERT" ROUTINE. MOV (SP)+,R1 ;RESTORE USER'S FOR "SAVE" MOV (SP)+,R0 ;ALSO INCB SKDBSY ;MARK AND TEST BUSY FLAG BEFORE ENTERING BNE CALA09 ;LOG-JAM: SCHEDULER CURRENTLY RUNNING... ;...DON'T RE-ENTER: IT WILL CLEA.��Ã��DÉ��„Ï ��ÄÕ ��Üâ ˆj��Dâ¼óLEC ;POP CURRENT SECOND * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 001.002 * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; **********************MSP) EMT TTYOUT EMT EXIT T.35BG: ;TASK #35 MOV T.35HD+14,T.35AR ;TRANSFER ARGUMENT MOV #LIST35,-(SP) EMT TTYOUT EMT EXIT T.36BG: MOV #MODUL0,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL1,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL2,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL3,-(SP) EMT NN UP AFTER ITSELF. ; O.K. TO ENTER "SKNSRT" OR ""SKED". SAVE ;SAVE REGS OF INTERRUPTED PGM & RTN HERE SKSWCH: BR .+2 ;SWITCH NORMALLY OPEN TO FALL THROUGH... BR SKRELY ;...TO SKIP "SKED" AND RUN "SKNSRT" ; ON THE MINUTE IT IS CLOSED TO FORCE RUN OF "SKED" INSTEAD. .PAGE SKED: ;THIS IS THE SCHEDULER ;ENTER HERE EVERY MINUTE ON THE MINUTE FROM "CALENDAR" MOV @CURTHD,R0 ;[TH1BOhNhN˜1~NHtÌ:~hN€€7 z±ÆhN÷`b²÷€²ßfßà÷ªOr±÷àn±÷ÖTޱ÷àŠ±Á€÷Î]n±wl±÷Ü[h±wf±� ÷Î]²w²÷Ü[^~àN²w²÷ ‚ ÷ r÷ ¶ß O±Áñ•‹h1Š'hÁ ñvbÂg      w8ÀÄU7šÁ% Á ýÀ VÁ1Và Á Á úÀ>VÁ1˜?VÁ ü7Š�~XOõ7Šò÷ªYD ÷¶YJ 7 6 ÀœOÁþgÂEhéhÄŠ‘Ä û×-$÷$þ‡PLP†PÀPúP4QnQæ &€¶6À ˜À  ,‚6ØO€»~ÐO ù‡ÖO¾hfjÄktj¦jTjT YNY°Z<[ÖO¢e0e®f˜fg P********************************************** .DEF STIME,SDATE,GTIME,GDATE .REF MONTH,MDAY,YEAR,JDATE,SECOND,MINUTE,HOUR .REF TICTOC,DAYTAB,PUSHR,POPR,MXDAYS,JANARY,FEBARY .PAGE STIME: ;SUBROUTINE TO SET NEW TIME MOV R0,-(SP) ;SAVE USER'S MOV 4(SP),R0 ;PULL NEW MINUTE OFF STACK MOV PS,4(SP) ;REPLACE WITH CURRENT STATUS FOR RTI USE CMP R0,#60. ;SEE IQ DQTIME TST (SP)+ MOV #MODUL4,-(SP) EMT DQTIME TST (SP)+ MOV #LIST36,-(SP) EMT TTYOUT EMT EXIT .PAGE T.37BG: ;TASK # 37 MOV #MODUL6,-(SP) EMT QSKED TST (SP)+ BR T.37A MOV #MODUL7,-(SP) EMT QSKED TST (SP)+ T.37A: MOV #LIST37,-(SP) EMT TTYOUT EMT EXIT T.38BG: RGN] OR [TH2BGN] MOV R0,R1 ;SAVE CURRENT THREAD ADDRESS FOR... ;...POSSIBLE MODULE REMOVAL (BELOW) MOV (R0),R0 ;NEXT MODULE'S ADDRESS BEQ SKDEX2 ;END OF THREAD: EXIT MOV R4,PS ;DROP CPU LEVEL TO BE FAIR TO OTHERS MOV STRTWD(R0),-(SP);STACK THIS MODULE'S START WORD FOR... JSR PC,UNPACK ;...CALL TO UNPACK SUBROUTINE, WHICH ; RETURNS WITH TIME & DAS ¨Q~HP¼QÖQ I~ÀPR!R"RÖ~8Q#,R$æXSæTþ ~°QˆÖ æ\R ˆˆæ€R ˆætSæ<þˆÖ æ€RTF MINUTE WITHIN RANGE BHIS STIM10 ;NO: EXIT IN ERROR CMP 6(SP),#24. ;SEE IF NEW HOUR WITHIN RANGE BLO STIM20 ;YES: PROCEED STIM10: ;ROUTINE EXIT POINT: FOR GOOD AND BAD MOV (SP)+,R0 ;RESTORE USER'S RTI ;RETURN AND RESTORE OLD CPU STATUS STIM20: ;HERE WHEN PARAMTERS ARE WITHIN RANGE MOV #340,PS ;LOCK OUT INTERFERENCE FROU ;TASK # 38 MOV #MODUL6,-(SP) EMT DQSKED TST (SP)+ MOV #MODUL7,-(SP) EMT DQSKED TST (SP)+ EMT EXIT .PAGE LIST30: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG VTE OF MODULE'S START WORD SPREAD ON STACK ; (SP) = DAY OF MONTH 2(SP) = HOUR 4(SP) = MINUTE CMPB (SP),MDAY ;SEE IF MODULE IS FOR TODAY BGT SKDEX1 ;FOR TOMORROW OR BEYOND: EXIT BLT SKDB10 ;FOR YESTERDAY OR EARLIER: EXECUTE MODULE CMPB 2(SP),HOUR ;TODAY: THIS HOUR? BGT SKDEX1 ;MODULE IS EARLY: EXIT BLT SKDB10 ;MODULE IS LATE: EXECUTE CMPB 4(SP),MINUTE ;FOR TW ˆˆæ‚Sæ&þˆÖ æ�SæþˆÖ æžSæþˆÖ æ¤R ˆˆ÷ÆþàæÈR ˆˆ÷òþöæìR ˆˆ÷ÿ æSb~(R ˆˆæXSˆÖ æfSˆÖ ætSˆÖ æ‚SˆÖ æ�SˆÖ æ4S ˆˆjRTASK #30 ARG= ŽRTASK #31 ARG=Ú~ R ²RTASK #32 ARG= ÖRTASK #33 ARG= úRTASK #34 ARG= ~SSTASK #35 ARG= BSTASK #36 ARG= !òSüSSäS"#ôS£òS!ôSÂXM CLOCK MOVB R0,MINUTE ;UPDATE CURRENT MINUTE MOVB 6(SP),HOUR ;UPDATE CURRENT HOUR CLR TICTOC ;RESET "TICS" [AND] "SECOND" COUNTERS CLR 6(SP) ;CLEAR ERROR CODE BR STIM10 ;GO EXIT .PAGE SDATE: ;SUBROUTINE TO UPDATE CURRENT MONTH,DAY, AND YEAR JSR R5,PUSHR ;SAVE ALL REGISTERS MOV SP,R0 ;UTILIZE AS SECONDARY STACK POINTER ADD Y .WORD , ;SYS RESERVE .WORD T.30BF ;MSG BUFFER T.30BF: .WORD MSG30X-T.30BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #30 ARG=" T.30AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG30X =. .EVEN .PAGE LIST31: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEZHIS HOUR. THIS MINUTE? BGT SKDEX1 ;TOO SOON SKDB10: MOV #340,PS ;LOCK OUT INTERFERENCE FROM "DQSKED" CMP (R0),#1 ;ALREADY DE-QUEUED? BNE SKDB20 ;STILL O.K. SKDB15: ;ALSO RETURN POINT FROM [SKDD10] ADD #6,SP ;POP SP DUE TO "UNPACK"... BR SKED ;...AND GO BACK FOR ANOTHER ONE SKRELY: BR SKNSRT ;RELAY POINT FOR SKIP TO 'INSERT' RTNE [~�S"öS#øSæfSæüˆÖ ‡12345æú«÷à\~Tô«&×-²ìU‚€È ÷e ?œ÷U@:«ð �6 °È €¶Èeø¬ÿÿôîð—’g¶öfjæ¦öŽ«÷à†«w Ê €Ð~€TÈ%È%ÿÿœÁEðÿÁ CÁeîUBA  ûJ³VÉ6 w ˜ ð•ÿÿ÷0œ.V?V€ ð‹.V!·Šuô‰Àà÷åØÈ¬ÿÿôœ¨~øTÁEðÿÁ 9V1V é7îª ðŠ?V×À À À >ÁîU`÷àÒªBAôñŠ÷CqœÊ°VË�œó‹ æœ\ #16,R0 ;POINT TO NEW "YEAR" ON STACK MOV (R0)+,R1 ;REMOVE YEAR MOV (R0)+,R2 ;AND NEW DAY MOV (R0),R3 ;GET MONTH FROM STACK MOV PS,-(R0) ;LOAD CURRENT PSW ON STACK FOR RTI USE MOV -4(R0),-(R0) ;AND MOVE RTN ADDR INTO PROPER PLACE,TOO CMP R3,#12. ;SEE IF MONTH IS WITHIN RANGE BHI SDAT30 ;ERROR: EXIT MOVB #28.,FEBARY ;RESET FEBRUARY IN PREP ]DIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.31BF ;MSG BUFFER T.31BF: .WORD MSG31X-T.31BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #31 ARG=" T.31AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG31X =. .EVEN LIST32^ .PAGE SKDB20: ;O.K. TO WORK ON THIS MODULE MOV (R0),(R1) ;FIRST: REMOVE MODULE BY "BRIDGING" THE ;THREAD OVER ITSELF, CONNECTING PREVIOUS ;MODULE WITH FOLLOWING ONE MOV #1,(R0) ;SET THIS MODULE INACTIVE... MOV R4,PS ;...DROP CPU LEVEL TO INTERRUPTED LEVEL MOV R0,R1 ;...AND SET UP THE SECONDARY MODULE PNTR MOV 2(R1),R2 ;G_& ‹€÷ Z & Â5~pU@Ó & ÷ >Ö Â5 ûÜÓ$Â5Èó ÅÀîUÁÐ Á ü÷E@´©÷àFª÷Š“§w”ÄU~èUîUðUòUôUöUøUúUüUþUVVVVV V Vdd÷ P!÷H÷ ~`VB· <Á’©ñ‹Áˆ©Á B°g ¹žg±žg±°g9 žgæj©÷ ÷ŠN7Š�&ÀìYЕ<ˆŠ¢<=·ŠzŠˆŠ¢<6ŠˆŠ¢1Šˆ "?~ØVÐЕЕˆŠ÷ó÷mâÿȵ· Øÿ·Šß ·ŠêÀ�çð­âàY·ŠÛ÷•Ô÷ªY„÷µ`FOR NEW YEAR MOV #365.,MXDAYS ;RESET MAX DAYS COUNT BIT #3,R1 ;IS NEW YEAR A LEAP? BNE SDAT40 ;NO: NO EXTRA DAY INCB FEBARY ;YES: ADD FEB 29 INC MXDAYS ;EXTRA DAY IN LEAP YEAR SDAT40: CMPB R2,DAYTAB(R3) ;CHECK DATE FOR PROPER RANGE THIS MONTH BLO SDAT50 ;O.K.: WITHIN RANGE MOVB DAYTAB(R3),R2 ;ERROR: USE LAST DAY RATHER THAN ERR OUT SDAT50: MOV R3,-(SP)a: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.32BF ;MSG BUFFER .PAGE T.32BF: .WORD MSG32X-T.32BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED bET OPTION & TASK WORD BPL SKDC10 ;"R" REPEAT FLAG NOT SET MOV DELTA(R1),-(SP) ;GET REPEAT WORD & STACK IT FOR CALL... JSR PC,UNPACK ;...TO SPREAD IT ON STACK ;NOW THE STACK HAS BOTH THE MODULE'S ;"START" AND "DELTA" WORDS SPREAD ON IT: ;(SP)= D-DATE 2(SP)= D-HOUR 4(SP)= D-MINUTE ["D" MEANS "DELTA"] ;6(SP)= S-DATE 8(SP)= S-HOUR 10(SP)= S-MINUTE ["S" MEANS "START"] cÉ÷ev€!Àjy7¶¨&÷ ìv~PW·£žr ·­‘m·­†h÷àŽ¨"Æeßq È7v¨B<€f÷ ¤¶m ¶m¶cö%< öå< ¶ ö%öå×~ÈW¶ Ã�#ö,àYöìàYÆeÎÎ Î Î ö¶ ¶ ŽUŽU±Ñ &÷ Ö Â‹fœ& & Â5@NÑ & ÷ ˜Ö Â5 †yÜ‚ÆeMƒÄƒ~@XÎEÀÿà à ÃÃEàÿæÄ„ „ „ ÄEàÿ&‡÷à˜§ÀJç÷eB7ˆ§Èð5ï&÷ ²ÿÎ Î�`—-ö�Q—-?ö�BÁö·£< �~¸X ·­/·-$Ñ BÆe�‚¦÷ XÿŽ-ô d ;SAVE MONTH ON STACK FOR USE BELOW MOV #JANARY,R0 ;PREPARE TO CALC JULIAN DAY CLR R4 ;WILL ACCUM TOTAL DAYS SDAT10: DEC R3 ;COUNT DOWN MONTHS BLE SDAT20 ;DONE: EXIT LOOP MOVB (R0)+,R5 ;CAN'T ADD BYTES ADD R5,R4 ;ACCUM DAYS FROM DAY TABLE BR SDAT10 ;LOOP BACK FOR MORE .PAGE SDAT20: ADD R2,R4 ;ADD TODAY'S DATE MOV e .ASCII "TASK #32 ARG=" T.32AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG32X =. .EVEN LIST33: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.33BF f MOV SP,R5 ;INIT SECONDARY STACK POINTER ADD #6,R5 ;POINT TO "S-DATE" ADD (SP)+,(R5)+ ;[D-DATE] + [S-DATE]: ACCUMULATE DAYS ADD (SP)+,(R5)+ ;[D-HOUR] + [S-HOUR]: ACCUMULATE HOURS ADD (SP)+,(R5)+ ;[D-MIN] + [S-MIN]: ACCUMULATE MINUTES CMP #60.,(R5) ;SEE IF MINUTES OVERFLOWED BGT SKDB30 ;NO: O.K. SUB #60.,(R5) :YES: STRIP MODULUS... INC -(R5g¶-ï¶- êÆeÆe ˆª¦öì¦÷àä¦&×-”ÞYƒ€ðEÈ j~0YÈe÷åt?p6 È €¦öª¦÷ࢦw æ€È%È%ÿÿÅÁ°YBA  ûJÉ6 w ÂÁ²YÅ ïøðUò:~¨YªY°Y²Y°Y¶Yއpÿ€àtÿ„àrÿ‚àvÿ†à"Z.Z:ZFZRZ�~ Z^Z3jZØa3jZØa1kZa1kZa3lZ&b3lZ&bÿÿ-~˜Z�Z’Z”Z–Z˜ZšZh #JDATE,R3 ;WILL USE AS POINTER TO DATE BYTES MOV #340,PS ;LOCK OUT INTERFERENCE FROM CLOCK MOV R4,(R3)+ ;LOAD JULIAN DATE MOVB (SP)+,(R3)+ ;LOAD NEW MONTH MOVB R2,(R3)+ ;LOAD DAY OF MONTH MOVB R1,(R3) ;LOAD CURRENT YEAR CLR 22(SP) ;CLEAR ERROR WORD FOR GOOD RETURN SDAT30: JSR R5,POPR ;RESTORE ALL REGISTERS TST (SP)+ ;POP THIRD ARGUMENT SINCi ;MSG BUFFER T.33BF: .WORD MSG33X-T.33BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #33 ARG=" T.33AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG33X =. .EVEN .PAGE LIST34: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE j) ;...AND BUMP HOURS TST (R5)+ ;(EQUALIZE POINTER IN CASE OF BRANCH) SKDB30: CMP #24.,-(R5) ;SEE IF HOURS OVERFLOWED BGT SKDB32 ;NO SUB #24.,(R5) ;YES: STRIP MODULUS... INC (SP) ;...AND BUMP DAYS SKDB32: MOVB MONTH,R3 ;USE CURRENT MONTH AS INDEX MOVB DAYTAB(R3),R3 ;GET # DAYS/MONTH INTO A WORD CMP R3,(SP) ;CHECK IF PAST END OF MONTH kœZžZw ’÷ ` ÷ ÷ Rñ‹oZ*·•0¥¬w xއœ&& && ÷ Ì Ö ˆ ïœ ôŠYh¬æw Dö�›~[ì¤& ÷  w:1ŠoZ5ˆZñ‹mZÏ€ñ•mZ·•Ȥ÷ ,Éw ÷ ÔÌÄ÷ |÷ Äñ‹qZ¹1ŠqZ5ŒZñ‹mZ²€1ŠmZãw ÖÀúY ZüÁw†þÀ"Zq~ˆ[HÀe  jZúÀmZŠ  ZüÀmZÂÿÿ�� oZüP� sZüÀ…ZP� ˆZüÀ ZÁ�ZPÑ W  Zûw x‡‰Á�¤ÁEðÿEÅ ÷ (ñ‹ZDZô•ú·•Ï~\ü£ñ•sZDœ}ZÄ |\1ŠZwæ6\]]"]0]D]V]d]v]Š]’] ]®]º]±ŠuZW¬uZH@ˆZ ´  -m=�Z­ Fý• Z1ŠuZñ• }ZùlE RTI NEEDS TWO RTI ;STACK SET TO RETURN AND RESTORE .PAGE ; NOTE: SUBROUTINES "GTIME" AND "GDATE" SHARE THE SAME CODE. ; THE CARRY BIT IS USED AS A SWITCH TO DETERMINE WHETHER TO LOAD TIME ; OR DATE. BY USING THE PSW TO STORE THIS SWTICH, AND BY RUNNING THE ; ROUTINE UNDER LOCKOUT AFTER THE CARRY BIT IS SET/CLEARED, RE-ENTRANCY ; IS MAINTAINED, AND THE POSSIBILITY OF CLOCK ALIASING IS ELIMINATED. GDATE: ;SUBROUTINE TO GET DATE m0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.34BF ;MSG BUFFER T.34BF: .WORD MSG34X-T.34BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #34 ARG=" T.34AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG34X =. .EVEN .PAGE LIST35: .WORD 1 ;THREAD WORD .Bn BGE SKDB40 ;STILL THIS MONTH SUB R3,(SP) ;GET DAY OF NEXT MONTH .PAGE SKDB40: ;NOW RESTORE MODULE START WORD & STACK SWAB (SP) ;POSITION "DATE"... ASL (SP) ASL (SP) ASL (SP) ;...FOR PLACE BACK IN "START" WORD SWAB 2(SP) ;POSITION "HOUR" ASR 2(SP) ASR 2(SP) ;...FOR ITS PLACE BIS (SP)+,(SP)o~x\=fZ÷ výÖ =ŠúY=ŠþY÷ xœÄñ‹mZ ÷ < Â÷ ¨1ŠmZ÷ `�Z %�ZÄå�Z·•,£±ŠmZ5ˆZ ±ŠoZ%�Z·•£5ŒZí~ð\÷ rw^ ±ŠqZñŠmZ·•ú¢÷±ŠuZfZ÷ æüÖ ïñ•}Z1ŠuZôý• Zñ•}Zâñ‹ƒZý• Zñ•}ZØý•UZñ•}Z±ŠuZÏý•^Zñ•}Zö}œyZ#~h]Zñ•}Zï1ŠƒZ±ŠuZý• Zñ• }Zã1Š}Zw°þý• Zñ• }Zªý• Zñ• }Z£1ŠuZ@ŒZwÀþñ‹…Z˜ý•ZñŠ…Zw&ÿ‰Á�*¢ÁEðÿEÅ DZ:~à]ô•@ŒZ Ê €fZæú÷ øûÖ DŸZ+ÄÅ€¡ q¡y¡ *¡-ƒÃeƒl¡.ñ‹wZB² ¦ÎEÀ–,pCLC ;MARK TO GET DATE (BELOW) BR GTIME+2 SEC ;MARK TO GET TIME (BELOW) GTIME: ;SUBROUTINE TO GET TIME MOV PS,-(SP) ;SAVE CURRENT PSW MOV #340,PS ;LOCK OUT INTERFERENCE FROM CLOCK SUB #12,SP ;NEED FIVE STACK CELLS MOV R0,(SP)+ ;SAVE USER'S SO WE CAN USE IT MOV R1,(SP)+ ;ALSO TST (SP)+ ;PREPARE FOR MOVINqYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.35BF ;MSG BUFFER T.35BF: .WORD MSG35X-T.35BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #35 ARG=" T.35AR: .ASCII " " ;TRANSMITTED ARG r ;[OR] DATE & HOUR... BIS (SP)+,(SP) ;...WITH MINUTE... MOV (SP)+,STRTWD(R1);...AND RE-STORE INTO START WORD TST (R1)+ ;BUMP POINTER TO ALLOW FOR "DELTA" WORD MOV R0,-(SP) JSR PC,QSKED ;RE-QUEUE MODULE IN NEW TIME SLOT TST (SP)+ ;POP RETURN ERROR WORD SKDC10: ;CONTINUE PROCESSING MODULE... ;...WHETHER OR NOT IT WAS REPEATED sG ‘Ê €Ê5@Ä þ~X^=‘ZCZó•Ê5@@wæÄ• ñ•}Zîý•^Zñ•}Z2 ïò äò Ê Þ�à ñ‹wZ ±ŠwZÄ•\ñ•}Zñ’yZÐÄ’Î1ŠwZ²  ‘1‘yZÄ•\ñ•S~Ð^}ZÁñ‹{ZÀ±Š{ZfZ÷ ûÖ ¸½ŠúY½=‘Zñ• }ZfZ÷ ôúÖ ²Ä•=‘Zñ}Zò€÷ öÈ 6·•Ö œ7w 6ï4Á W‡¦Ì~bö�â�÷ÕàÚ�‡f&Á�>øÁ fZ÷ À÷Ö � ±Š…Z„�‡&æ¦f&MÖ €�‚ƒ„…‰æ& æ & ÷ NÖ wàc~�b ÿÿEN„dDSˆdQUŽdXX”dTMô~cDTEX÷ dÆæÒc÷ �÷÷€º÷àc²æÒc÷ ø÷ ¢÷%¢7 ~ÿ÷šzÿ÷–vÿæÄb÷ Ö�Ö ÀÊb$È ü€wæüc÷ 8÷÷b÷C~€càcZæÒc÷ °÷÷ Jí ;RESTORE USER'S MOV (SP)+,R1 ;ALSO RTI ;ZAP! RETURN TO CALLER WITH HIS STATUS ; ...AND THREE PARAMETERS ON STACK. .END } ;SYS RESERVE .WORD T.37BF ;MSG BUFFER T.37BF: .WORD MSG37X-T.37BF-4 ;BUFFER LENGTH .WORD 0 ;RES .ASCII "TASK #37 ARG:" T.37AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG37X =. .EVEN .PAGE MODUL0: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/R~" TO RUN REQUESTED TASK TST (SP)+ ;...AND POP ERROR CODE ON RETURN SKDD10: ;QUEUEING OR NO, NOW CHECK FOR FLAG-SET ASL R2 ;IS THE "F" FLAG OPTION SET? BPL SKDB15 ;NO: THIS MODULE DONE: BACK FOR MORE BISB 8.(R1),@6(R1) ;YES: DO [IOR] OF MASK INTO FLAG LOC'N BR SKDB15 ;DONE WITH MODULE: LOOK FOR MORE SKDEX1: ADD #6,SP ;ADJUST SP FROM CALL TO "UNPACK" SKDEX2ÅâcDÄå�Ä ÃôbS# Ó Ë û÷d*æÒc÷ ôöÙË ÕÕ Û Å Ó÷&dñ£~øcdAC: ? ILL CMD! ILL PAR! NON-QUIESCENT æ7 ôÿ7 òÿ7 ðÿaÃLdc™Ä ýæFd÷ „/~pdÖ  ƒ‡Èdàde(e ÁÁÁW¥,4Ä 2!/‚÷  ÿÅ +!(Ä &7!Ú#Â:›y|d÷à0›ô¥'h4Š'h· ›‡÷à›ô‹c~èd'h­'h ·›÷4dàþæÒc÷ ªõ ‡ô•'h·ꚇ&& æ & ÷ œÖ ñè&÷ x‡æ w ý�¶ Ñ‹À D”Ä¥ À ùD”Äå0�Ü€; ******************************************************************** ; * PROGRAM IDENTIFICATION: "CALENDAR" * ; * DATE & TIME-OF-DAY ROUTINE * ; * * ; * PURPOSE: * ; * --KEEPS 24-HOUR CLOCK AND PERPETUAL CALENDAR UPDATED. * ; * --CALLS THE SCHEDULER ONCE A MINUTE, ON THE MINUTE. �ESET .WORD ARG1 ;ARG .WORD FLAG1 ;FLAG ADDR .WORD MASK1 ;FLAG MASK .WORD JSRTNE ;JSR TARGET MODUL1: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 43 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ‚: ;SCHEDULER EXIT WITH NO STACK POP MOV #340,PS ;PROTECT CHECK OF BUSY FLAG MOVB #-1,SKDBSY ;RESET FLAG TO ALLOW NEXT ENTRY JMP RESTOR ;RETURN TO INTERRUPTED PGM ==>[RESTOR] .PAGE UNPACK: ;INTERNAL SUBROUTINE TO SPREAD A SCHEDULER TIME&DATE ;WORD ONTO THE STACK ;UPON ENTRY, ROUTINE ASSUMES PACKED WORD IS ON TOP OF STACK; ; 15 11 10 6 5 1 ; ƒ~`e¡ ‚CÂà à Â`‚`a…À ïñ¥-úÿ v6 w Âü‡6ú'èd w  ü„…À˜eÄ �Õ•+Á•  â€d Á0B`•�È ôÄeG~Øe0 ‘¶ w lü–%‡Õ•- äÒ‹åÿÿ·öÿ·ðÿ·êÿ· äÿ÷ ~÷ Ž æ÷ ’æÌÿæÊÿÅVfÄÄÿ·ÀÿÆZf&æ¦f&ì8~Pf–%êæ¤™÷àž™÷ ’ÿ�·êÿ€�‚ƒ„…÷ 2÷Ôÿ|™Ævÿù÷ ë·j™wÀæb™æ÷ 7 w¬÷äøÿ‡¶fÿÿxgÓ~ÈfÊf( ERROR XXXXX SXXXXX SXXXXX SXXXXX SXXXXXÔfÛfâféfðfw >û…æî˜÷àè˜Í šÿw–ÿ· ”ÿ·Ò˜„ * ; * * ; * USAGE: * ; * TRIGGERED BY TIME-OF-DAY CLOCK INTERRUPT. * ; * IF TIME OR DATE IS ALTERED BY OUTSIDE PROGRAM(S), * ; * CPU MUST BE ON LEVEL 7 TO AVOID INTERFERENCE. * ; * WHEN READING TIME OR DATE, SAME PRECAUTION SHOULD * ; * BE TAKEN. … ;JSR TARGET MODUL2: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 243 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL3: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 † DAY ^ HOUR ^ MINUTE ;UPON EXIT, STACK HAS THREE WORDS ON IT: ; (SP)= DAY 2(SP)= HOUR 4(SP)= MINUTE MOV (SP),R3 ;COPY T&D WORD MOV R3,R5 ;SAVE IT FOR BELOW BIC #177700,(SP) ;LEAVE MINUTE ALL BY ITSELF ASL R3 ASL R3 SWAB R3 ;GET "HOUR" INTO LOW BYTE BIC #177740,R3 ;CLEAR ALL OTHER STUFF MOV R3,-(SP) ;PUT IT IN ITS OWN PLACE SWAB‡w "ûއ� ø7 ÆÿÅvÿñ~@g#wpÿ÷¶fjÿ·¬˜Ä ÿf&÷ DþÔ ú÷• lÿæ¼f÷ @ó÷ ŽÿÛ‡· †ÿæ~˜÷àx˜Ú7 .ÿ·n˜‡²g´g¶g¸gºg¼g¾gÀgc~¸gb~0hé~¨hf¦æ&& „6  7!Âþ`×þÿß•àþÿô‹'h ­'hˆ * ; * PROGRAMMER: 52 * ; * VERSION: 003.003 * ; * DATE: 02-DEC-71 * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; ******************************************************************** SAVE = 3 ;OP-CODE FOR CAL‰ ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL4: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG3 ;ARG .WORD 0 ;FLAG ADDR Š R5 ASR R5 ASR R5 ASR R5 ;GET [DAY] INTO LOWER BYTE... BIC #177740,R5 ; ...CLEAR GARBAGE... MOV R5,-(SP) ; ...AND PUT IN ITS OWN PLACE RTS PC .PAGE SKNSRT: ;ROUTINE TO INSERT SCHEDULER MODULES FROM THE WAITING ;TABLE. ALSO LOOP RE-ENTRY POINT FROM END MOV #340,PS ;LOCK OUT INTERFERENCE FROM "QSKED" SKNA10: ;LOOP RE‹Wô‹YhSöÿÿô•'hÄ Âg„ —"Hß�þÿ�� ~ i‹hW Ár� —"4ß•àþÿÊ Á ¹žg±žgô•'h4ŠYh² ß�þÿÖ „ƒ‚�÷ @ýö ¶Æe‡öþÿ¶Æeæ÷ &wÀ«~˜iŽ Ž Ž Ž Ž 6 ¶Ú¦¶¶æ—þÿß•àþÿ÷ ÎýK7 ÈýŸ•þÿæ¦f�v®ý ‚Âg²� 6 ²€6„œ×þÿß•àþÿÆB~jŠý&òŒï 7 †ïÊô•'hÁ ôŠ'hß�þÿ‡ô•'h€œ À Ä <°gÂg0Âgžg0Âg°gß�þÿ‡Ÿ•þÿ‡æ—þÿ& ÷ <ÿwäß•àþÿÀýœÈ1Š&~ˆj'h7 ý7 ï7 ü0 ÆþüŠþÿw²&f€(7 ŒL TO [SAVE] SUBROUTINE STRTWD = 4 ;INDEX TO MODULE TIME& DATE WORD DELTA = 6 ;INDEX TO MODULE INCREMENT WORD .DEF QSKED,DQSKED,COUNTR .DEF DAYTAB,CLOCK,TICTOC,SECOND,MINUTE,HOUR .DEF JDATE,MDAY,MONTH,YEAR,MXDAYS,JANARY,FEBARY .DEF SWAITB,STBPTR,THDTAB,CURTHD,ABMPLR,SKDBSY .REF PUSHR,POPR,PPTAB,ABORT .REF QUEUE,FIRST,LAST,$PRIOR,RESTOR,$CTASK .TITLE CALEND .PAGE CALE� .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MODUL5: .WORD 1 ;THREAD WORD .BYTE 35. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG4 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL6: .WORD 1 ;THRŽTURN WHEN LOCKOUT IS ALREADY SET MOV @STBPTR,R0 ;GET ADDRESS OF NEXT MODULE BEQ SKDEX2 ;TABLE EMPTY: EXIT VIA "RESTOR" ADD #2,STBPTR ;NOT EMPTY: POP POINTER BACK ONE CELL MOV #1,(R0) ;SET INACTIVE IN CASE DE-QUEUED BIT #10000,2(R0) ;WAS IT DE-QUEUED WHILE IN TABLE? BNE SKNA10 ;YES: IGNORE AND CONTINUE MOV R4,PS ;RESTORE PREVIOUS CPU LEVEL MOV 4(R0�äü%‚æ—þÿß•àþÿœ'hÁ yÊjkkÚjòjòjÚjkkŸ•þÿ&÷ *Ö æ—þÿß•àþÿð•'h7 °ûŸ•þÿÚ~k�€Ž‡Ÿ•þÿùf¦æ&f… Gw!vüD6 W­'hAÅ AÂg… Á-Zü<W"7Bœ  ƒ°g6C ÄÃ,úæ—þÿß•àþÿW,Ÿ•þÿò °gƒ~xk r°g ò°gžg²`žgL2žg5Š'hÉŸ•þÿ…„ƒ‚�‡ö ¶ ¶ òñ÷f¦æ&„ 86 7!¾û5‚×þÿ÷•à”�'hÁåà~ðkÁ +ô•'hÄ Âg„ Ê �œ Á ¹žg±žg´Š'h4ŠYhß�þÿ„ƒ‚�ö އö—þÿæ÷ |ýw6 ¶ ¶ „ƒ‚�êß•àþÿ÷ 4ûN÷ Dúú~hlKÁ,ûÁ  ÃÂ`�NDAR: ;TIME & DATE ROUTINE ;ENTRY FROM TIME-OF-DAY CLOCK INTERRUPT ;ENTERED ON CPU LEVEL 7 .IFNZ $ABMPL ;OPTION FOR "ABORT" MULTIPLIER DEC ABMPLR ;COUNT DOWN THE ABORT MULTIPLIER BGT CALA08 ;NOT YET: DON'T RUN ABORT OR TIME-SLICE MOV #ABMPCT,ABMPLR ;RESET THE ABORT MULTIPLIER .ENDC $ABMPL DEC COUNTR ;TIC OFF‘EAD WORD .BYTE 34. ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;"START" TIME .WORD 0 ;"DELTA" TIME .WORD ARG4 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK MODUL7: .WORD 1 ;THREAD WORD .BYTE 35. ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;"START" .W’),-(SP) ;STACK MODULE'S DATE WORD FOR... JSR PC,UNPACK ;...CALL TO SPREAD IT ON STACK TST (SP) ;IF "DATE" = 0,... BNE SKNA20 MOVB MDAY,(SP) ;...THEN USE TODAY'S DATE SKNA20: CMP 2(SP),#37 ;IF "HOUR" IS ALL ONES... BNE SKNA30 MOVB HOUR,2(SP) ;...THEN USE CURRENT HOUR SKNA30: CMP 4(SP),#77 ;IF "MIN" IS ALL ONES... BNE SKNA40 MOVB MINUTE,4(SP) ;...TH“ò °gB úŠþÿÿ�°gwû²°g°g²žgòe°gžg·öú‚ ·èúBœ·Þúò•'hñ  FœÆ F`ÆewÐìŠþÿyw v~àlÂìF€ 6 vœ �‚ƒ„…þ&f€6 À #7 €ú ‚æ—þÿß•àþÿœ'hÁåÁ 0Š'hÀ Âg0 0Š0 Ÿ•þÿ�€‡Ÿ•þÿ¶ ÷~Xm¶ ö7 .ú7 ,ú7 *úÀ*úÀ 0 °gð°gžg0`žgÀåöÀ2Ád1 Âgð•'h0ŠYh0Š‹há À ô‡À ÷e æù×-âù2ÁqÖmÂg0œëm‹h0Š'h¯~Ðmá À õ‡öm’nqÜq‚r*sŠn2Þ” CURRENT TASK TIMER BGT CALA08 ;STILL SOME LIFE LEFT INC COUNTR ;RESTORE IN CASE WAS ZERO BEQ CALA08 ;IT WAS. WE IGNORE ZEROES AS "OFF" .PAGE .IFNZ $TMSLC ;OPTION FOR TIME SLICING MOV R1,-(SP) ;SAVE USER'S MOV $PRIOR,R1 ;PRIORITY OF TASK INVOLUNTARILY ; SUSPENDED BY INTERRUPT, OR OF MOST RECENTLY RUN TASK. TSTB PPTAB(R1) ;CHECK FOR TIME-SLICING ON THIS LEVE•ORD 0 ;"DELTA" .WORD ARG5 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK MODUL8: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR–EN USE CURRENT MINUTE .PAGE SKNA40: ;NOW THAT MODULE'S TIME IS READY, BEGIN SEARCH FOR ITS ;PLACE IN ONE OF THE TWO SCHEDULER THREADS. MOV CURTHD,R1 ;POINTS TO [THDTAB] OR [THDTAB+2] CMPB (SP),MDAY ;MODULE DATE :: TODAY'S DATE BGT SKNA60 ;AFTER TODAY: USE CURRENT THREAD BLT SKNA50 ;BEFORE TODAY: USE "FUTURE" THREAD CMPB 2(SP),HOUR ;MODULE HOUR :: CURRENT HOUR —~Hnzn TASK ## 2 æln ˆˆ&o2ñ~Àno TASK ## 3 æo ˆæ& & & ˆ�~8oÖ ˆÐo2õ~°oÀo TASK ## 4 æ²o ˆæ& & æˆÖ ˆ|p2˜L BLE CALA06 ;NOT A T/S LEVEL: GO DO ABORT SEQUENCE MOV R2,-(SP) &SAVE USER'S ASL R1 ;USED AS A WORD INDEX MOV FIRST(R1),R2 ;ADDRESS OF FIRST TASK BEQ CALA05 ;NO TASKS IN QUEUE: DON'T SLICE MOV R2,@LAST(R1) ;LINK FRONT TASK TO END OF THREAD... MOV R2,LAST(R1) ;...AND UPDATE THE "LAST" POINTER MOV (R2),FIRST(R1) ;THEN MAKE "FIRST" POINT TO WHAT WAS ™ TARGET MODUL9: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MASK1 = 123 MASK2 = 234 MASK3 = 345 JSRTNE: MOV #MODUL1,-(SP) MOV TMWRD0šBGT SKNA60 ;LATER TODAY: USE CURRENT THREAD BLT SKNA50 ;WAS EARLIER TODAY: PUT IN "FUTURE" CMPB 4(SP),MINUTE ;MODULE MINUTE :: CURRENT MINUTE BGE SKNA60 ;NOW OR WITHIN HOUR: CURRENT THREAD SKNA50: TST (R1)+ ;WE ARE PAST MODULE'S TIME: USE "FUTURE" SKNA60: ;NOW THAT PROPER THREAD BEGIN WORD'S ADDRESS IS IN R1, ;WE CAN BEGIN SEARCH OF THAT THREAD. MOV (R1),R2 ;ADDR OF›Ü~(plp TASK ## 5 æ^p ˆæ& & & ˆÖ õ&q2Ä~ pq Õ~qTASK ## 6 æq ˆæ& & æˆÖ ôÒq2•~�qÂq TASK ## 7 œ ;THE SECOND TASK IN QUEUE CLR @LAST(R1) ;ZERO THREAD WORD OF NEW LAST TASK CALA05: ;EXIT FROM TIME-SLICE MOV (SP)+,R2 ;RESTORE USER'S MOV (SP)+,R1 ;LIKEWISE BR CALA08 ;BYPASS ABORT SEQUENCE CALA06: ;HERE WHEN LEVEL IS NOT A SLICER: DO ABORT==> MOV (SP)+,R1 ;RESTORE USER'S .ENDC $TMSLC ; ABORT SEQUENCE: TASK'S ABORT COU,-(SP) EMT QTIME TST (SP)+ RTS PC ARG1: '1 ARG2: '2 ARG3: '3 ARG4: '4 ARG5: '5 FLAG1: .BYTE 0 FLAG2: .BYTE 0 FLAG3: .BYTE 0 .END ž ONE OF THE THREAD-BEGIN WORDS BR SKNB00 ;ENTER LOOP FOR FIRST TIME SKNB10: ;THIS IS THE LOOP RETURN POINT AS LONG AS SEARCH CONT'S ADD #6,SP ;POP STACK POINTER FROM "UNPACK" BELOW SKNB00: ;HERE FOR FIRST-TIME ENTRY MOV R2,R1 ;SAVE OLD T/W ADDRESS MOV (R2),R2 ;GET NEXT MODULE'S (T/W) ADDRESS BEQ SKNB30 ;AT END OF THREAD ;NOT @ END: TEST MODULE FOR TIME Ÿæ´q ˆˆûpr2¿~r`r TASK ## 8 æRr ˆæ& ˆÖ ~€rˆs2 <~ørs TASK ## 9 æør ˆææˆÖ ˆ¾s2 ~ps NTER REACHED ZERO (@TIMA40) MOV $CTASK,-(SP) ;STACK CURRENTLY ACTIVE TASK'S NUMBER... JSR PC,ABORT ;...AND REQUEST ITS ABORTION CALA08: ;HERE WHEN READY TO RUN THE CLOCK DECB TICTOC ;# OF TICS PER SECOND BEQ CALA10 ;NEW SECOND CALA09: RTI ;USED AS RETURN ALSO FROM[CALA40] .PAGE CALA10: ;ON EACH SECOND COME HERE CLRB SKSWCH ;INIT TO RUN¡FIRST TASK BEQ TIMA50 ;NO TASKS IN QUEUE. MOV R2,@LAST(R1) ;LINK FRONT TASK TO END OF THREAD... MOV R2,LAST(R1) ;...AND UPDATE THE "LAST" POINTER MOV (R2),FIRST(R1) ;THEN MAKE "FIRST" POINT TO WHAT WAS ;THE SECOND TASK IN QUEUE CLR @LAST(R1) ;ZERO THREAD WORD OF NEW LAST TASK BR TIMB10 ;BYPASS ABORT SEQUENCE TIMA50: .ENDC $TMSLC ;END OF TI¢ MOV 4(R2),-(SP) ;STACK TEST MODULE'S DATE WORD... JSR PC,UNPACK ;...FOR CALL TO SPREAD IT ON STACK CMP 6(SP),(SP) ;NEW MOD'S DATE :: TEST MOD'S DATE BGT SKNB10 ;LATER: KEEP LOOKING BLT SKNB20 ;EARLIER: THREAD NOW CMP 10(SP),2(SP) ;NEW MOD'S HOUR :: TEST MOD'S HOUR BGT SKNB10 ;STILL LATER BLT SKNB20 ;EARLIER CMP 12(SP),4(SP) ;COMPARE MIN£®s TASK ## 10 æ s ˆæ ˆÖ ˆî|ò|ò|þ|Ì~èshNnO‰ OPTRVªOhNúY’g.........÷®‹¢ÿ÷¸‹¦‹÷–ÿ÷•ÿÿk~`tx 7Šr wÆ÷�‹„ÿw È7tÆäsÄã~Ãó~w ¦ 7^w ìw >Ä�\ÿŒŒŒ7‘Z‹7Š0 ÷•ÿÿ, ÷àZ‹÷"{R‹wæÆ.ÿ& ÷ ÿæd‹æ^‹÷•@˜Šˆ~Øtà D÷‹ü A „ &DCƒcà ÷Ú w 2w ΄·ŠÜ w ð  '  7ŠÈ Ä´ „ ‚ ¦&w ¶„‚À•\w ¶wXw ºw ö�Ä øfw Ñ~Pu|÷•t €w „¤ "SKNSRT" AND NOT "SKED" MOV R0,-(SP) MOV R1,-(SP) MOV #CLOCK,R0 ;POINTER TO TIME & DATE BYTES MOVB #TICRES,(R0)+ ;RESET [TICTOC] INCB (R0) ;NEXT SECOND CMPB (R0),#60. ;NEW MINUTE? BLT CALA40 ;NO: BUT GO TO END TO RUN "SKNSRT" INCB SKSWCH ;SET TO RUN "SKED" AND NOT "SKNSRT" CLRB (R0)+ ;RESET [SECOND] & GO ON TO... INCB (R0) ¥ME-SLICING .PAGE ; ABORT SEQUENCE: TASK'S ABORT COUNTER REACHED ZERO (@TIMA40) MOV $CTASK,-(SP) ;STACK CURRENTLY ACTIVE TASK'S NUMBER... JSR PC,ABORT ;...AND REQUEST ITS ABORTION TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #340,PS ;AVOID INTERFERENCE FROM "DQTIME" MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE ¦UTES BGT SKNB10 .PAGE SKNB20: ;HAVE FINALLY FOUND SLOT FOR NEW MODULE. R1 CONTAINS ;ADDR OF PREVIOUS OR "UPSTREAM" MODULE (MIGHT BE THE ;THREAD START WORD) AND R2 CONTAINS ADDR OF DOWNSTREAM ;MODULE, OR ZERO IF NEW MODULE IS BEING PLACED AT END ;OF THREAD. R0 CONTAINS ADDR OF NEW MODULE. ADD #6,SP ;POP SP FROM 1ST CALL TO "UNPACK" SKNB30: ADD #6,SP ;POP SP FROM 2ND§7Š€ wtwhw ŒÄ  Ä%-û‚ÀEøÿÄ Äeäs‚ whÄå÷À6 Áß~÷ æÀ=w F·Š6 À�/ w :À�( w 2À�! w *À ®~Èuw "w *  7� w 7�þw 7Šø7�óÀÒ~Áß~÷ JÄÔÂwð7ŠØ  wèw (‚b‚ ‚ ·®wúw ‚øw �A�Á � � B`ï÷ ³~@vr÷%„€…Ö w|÷‹„û 7Štwr÷•ÿÿjwh·Šg ÄEøÿÄ 7tpwh÷‹P ÄEøÿÄ Ã ttPà õôÿÿtIw Û¹~¸v×-ÉÂ% w ’ ÿÿÀ=w ÀòÁê7Ä ítÀ=w øÀÀe0w ìÀ,w äÂ%ÀÀ@w ~k÷‹¾ÄØüÂe¨ ;...BUMP [MINUTE] CMPB (R0),#60. ;NEW HOUR? BLT CALA40 ;NO: BUT GO RUN SCHEDULER CLRB (R0)+ ;RESET [MINUTE]... INCB (R0) ;...AND BUMP [HOUR] CMPB (R0),#24. ;NEW DAY? BLT CALA40 ;NO CLRB (R0)+ ;YES: RESET [HOUR]... INC (R0) ;...AND BUMP [JDATE] CMP (R0),(PC)+ ;NEW YEAR? MXDAYS: .WORD 0 ;HOL© ADD R0,R1 ;...OF POINTER FOR CURRENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB TIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB15 ª CALL TO "UNPACK" MOV R0,(R1) ;LOAD UPSTREAM THREAD-WORD FOR NEW MOD MOV R2,(R0) ;LOAD NEW T/W FOR DOWNSTREAM MOD BR SKNSRT ;GO BACK FOR POSSIBLE MORE MODULES. .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QSKED" * ; * SYSTEM SUBROUTINE TO QUEUE A SCHEDULER MODULE * ; * «À=»~0w÷–w ´@w Xwºüw’·Š¬w¢À=w – w ü ÿÿÀdw *AÀe0w vÀ,w næH÷BÀFw ·6-À ÷.27ìt,`~¨w€ â÷÷‹( ÀBüÄ:üÃ8üw Ö÷üðÀ?w 7 îw ò7Šø7Šó7Š     w À%0 ‚À%7‡ÀEøÿÄ Ä Ä `‚ ð 1 � q~ xW Ö†ø÷‹Ì ÷‹©Äm¼7ŠºÁ yDx|xŠx”xèxju’zøxvôxNyrvÂyz z`yÞz$v,vVvŠvwHw¬wÊwPw”uÚt¾tƒ·ŠZ7ŠU´÷<D ÷;~˜x2 7.7(÷% Ä„ î‡ÀÀŸw Ô÷%‹À•=w ÀŸöw À• w wúþ÷ Èwêþw¬DS #DAYS IN CURRENT YEAR BLE CALA30 ;NO: GO TO NEXT DAY + MAYBE NEW MONTH ;HAPPY NEW YEAR!! MOV #1,R1 MOV R1,(R0)+ ;RESET [JDATE] MOVB R1,(R0)+ ;RESET [MONTH] MOVB R1,(R0)+ ;RESET [MDAY] INCB (R0) ;BUMP TO NEW YEAR MOVB #28.,FEBARY ;RESET FEBRUARY MOV #365.,MXDAYS ;RESET YEAR LENGTH BITB #3,(R0) ;IS TH­ ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS MODULE'S TIME. MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD ... BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACT® * ; * PURPOSE: * ; * PUTS ADDRESS OF CALLER'S MODULE IN INTERNAL STACK. * ; * THIS TABLE IS EMPTIED BY THE ROUTINE "SKNSRT" WHICH IS * ; * CALLED BY THE SCHEDULER EACH MINUTE JUST BEFORE IT RUNS* ; * THIS METHOD AVOIDS QUEUEING AND SCHEDULER CONFLICTS WHE* ; * ACCESSING THE TWO SCHEDULER THREADS(THE SCHEDULER DROPS* ; * THE CPU LEVEL SO AS ¯Þþ·ŠÞ÷ Ðù÷ ²÷ Ð÷ÄÀ7Ч~yÄ÷m¶¶÷²²w ¬æ¦÷ Àžw ®·”Ö%À/w ¨¯À\ú÷ zÔ÷ \÷íppÜÀ.Ä Ã … L‡Å Äet  ! tB†Ô ù!ò~ˆy t=‚L® !6‚4t4 $t¤ À.!ž‚4tô6t4 $tÔ ô÷%À w à ÅíôÅ Å @w ´@€ ‡À%€ÿ À%÷ Òw š· K~zÊwÜýwÈý�  à ù÷²ÂÜùÄÖùD · Ôù¼‚€Á &C@AƒEPA&f¦æw „€w ’À/w –€w :ƒ‚�„w ÐÒ Û åƒ`ƒ Š~xzƒ Å ßÀEÿ�¯À € € €` Õ÷‹H·à µ÷•8… °‡Å wFù÷•àL…w ¢7аIS A LEAP YEAR? BNE CALA35 ;NO INC MXDAYS ;YES: BUMP YEAR LENGTH INCB FEBARY ;...AND FEBRUARY BR CALA35 CALA30: ;HERE @ BEGIN OF DAY & NOT NEW YEAR MOV #MONTH,R1 ;INIT POINTER TO DATE BYTE TABLE MOVB (R1)+,R0 ;[MONTH]: USED AS INDEX INCB (R1) ;[MDAY]: NEW DAY CMPB (R1),DAYTAB(R0 ;[MDAY]: END OF MONTH BLE CALA40 ±IVE IN EITHER CASE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOV R1,R3 ;COPY MODULE ADDRESS TO PRESERVE R1... ;...IN CASE OF "J" OPTION MOVB OPTION(R1),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R1) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NO: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSP²NOT TO LOCK OUT INTERRUPTS UNNECES-* ; * SARILY), REDUCING THE CONFLICT AREA TO JUST THE FIFO * ; * TABLE. THIS CONFLICT IS AVOIDED, THEN, BY RUNNING * ; * "QSKED" (A SHORT ROUTINE) AND THE FEW WORDS OF CODE * ; * IN "SKNSRT" WHICH ACCESS THE TABLE, UNDER INTERRUPT- * ; * LOCKOUT. * ; * * ; * USAGE: ³÷U4ù÷‹÷E(ùw T76æùæù÷‹ü‘À�òÀ‹� ‹~ðzà p$t÷•à…w V×­ÔÖ÷‹ÊÓ÷•àè„·Š¿÷UÔø×·Ìø·Êø÷•ª7¸÷‹¡¾w @÷‹´ø€Å�¬øÅ�¨ø¯ŒŒŒŒw‘¢„Å’ø÷‹t�å G~h{w†øÄt!tÄ Ä úw ¼w JÄô~Ãõ~w ž@÷eZø%Ä•tt7‘2ô $tªô$tw „ÀBw .À�Àe`€ w À;w ÷ðÄ�ú¬~à{tw úwîû·â·ü÷Æðsf&æ¦fæÌæ €Ö ·Â�‚ƒ„…ÆÒ÷æ°€Ä4t6tüütÄ Ä ÷…÷�0ƒ™÷�.ƒ”7Š$ƒ7Š$ƒ÷‹ ƒý€…Ì~X|w r÷‹ƒý€÷5ƒ÷‹ƒý€÷�gú‚÷�bø‚…´ ;NO MOVB #1,(R1) ;RESET DAY TO FIRST OF MONTH INCB -(R1) ;NEXT MONTH: CAN'T BE JANUARY (ABOVE) CALA35: ;HERE TO ADJUST THE THREAD POINTER POINTER AT THE BEGIN ; OF EACH MONTH. "CURTHD" ALWAYS POINTS TO "TH1BGN" DURING ; ODD-NUMBERED MONTHS, AND TO "TH2BGN" DURING EVEN MONTHS. MOV #THDTAB,CURTHD ;INIT THREAD-START TABLE POINTER BITB #1,MONTH ;ODD-NUMBERED MONTH? BNE CALAµEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP) ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL TO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK #¶ * ; * USERS CAN CALL "QSKED" EITHER VIA JSR (IF LINKED) OR * ; * VIA EMT. IN EITHER CASE THE ADDRESS OF THE MODULE TO BE* ; * THREADED MUST FIRST BE PLACED ON THE STACK.THE STACK * ; * POINTER IS LEFT UNCHANGED ON RETURN. THE STACK LOCATION* ; * ITSELF WILL BE CLEARED IF THE TABLE HAS ROOM FOR * ; * IT AND THE MODULE ITSELF IS INACTIVE (ITS THREAD WORD * ; * MUST·÷‹V  <6tt„ „ !ø…ÃÄþÿ÷%&Ãå„ À&Äe N @ Ä üÀe0w &à óÀ• ù~Ð|Ö ÁtÀÿÿ …÷‹‚‚ý€7�~‚…÷‹r‚ý€À�n‚ÀE€ÿÀ¥÷‹Ð  w Ðÿí÷‹¾À¥ ç…Ä ã‡•w ¶ÿú×­4‚• À•^w T~H}¤ÿÀ•Uw œÿÆäsw€ú… ÷ÿÿn÷ÿÿj  ‚7,tX‚ÁRìtÁ-P‚Ð ðÀD…w@€ 78À ô÷%(!ùƒ… �„ ú ÷%û~À}‚??‘‡Ãÿ~ÃÄþ~w Nÿ…÷%öw ªþ…÷Ú77Ðw ZÿÀ Àe0w àþÀ,w Øþæ²÷¬À°w pþ· ÷ÊœÀÆ…¼~8~ÀÀ÷¸40 ;YES: LEAVE AS IS ADD #2,CURTHD ;EVEN: ADVANCE TO POINT TO THREAD #2 CALA40: ;HERE ON EVERY MINUTE BOUNDARY TO RUN... ;...THE SCHEDULER. ON THE OTHER 59 SECONDS, RUN "INSERT" ROUTINE. MOV (SP)+,R1 ;RESTORE USER'S FOR "SAVE" MOV (SP)+,R0 ;ALSO INCB SKDBSY ;MARK AND TEST BUSY FLAG BEFORE ENTERING BNE CALA09 ;LOG-JAM: SCHEDULER CURRENTLY RUNNING... ;...DON'T RE-ENTER¹ AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFNZ DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT º BE =1). IN CASE OF ONE OF THE ABOVE ERRORS, THE * ; * STACK LOCATION IS LEFT UNCHANGED (NON-ZERO) FOR TESTING* ; * BY THE CALLER. * ; * "QSKED" SAVES & RESTORES ALL REGISTERS THAT IT USES. * ; * IT MAY BE CALLED BY ANY TYPE OF USER AT ANY TIME. * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; ********»ºŒÓÄýÿ C”Ã¥ Ã¥$ × A‡Ãå ÃåÃå Ãå    ¦  ‚eÂ`„ ä�‡ÅýÿÂÆ~ ‡€âƒ ûË× Ãe Ãem~°~Ãe Ãe Ñ�Ò … è€Ð ‡@(ZUZUZÿ@€ ODT-11R V002ABETZUZU *;/\ $G _<^,OWEBP@>SRC-FI!XASPMCFR„~(Béééé=Ʀ)ÅÂÆ¦)ÅÅeL Îxÿ ‡ ¡N N Í ÃŠüÍ ÷ <ÂåÂ%!÷ ,„cÍ À‹ëéÑ�øÃh‹ŠË‹þ€Ãœyf À`ÃEÿ ‡·$Í ÄÍ ÃÄPÇ÷ êÿÍ À‹â„ †¿Ä LÀ÷ê÷õwZÿÁÂê‰ É‹þ€rœ· îÿõpÿî~N-¼: IT WILL CLEAN UP AFTER ITSELF. ; O.K. TO ENTER "SKNSRT" OR ""SKED". SAVE ;SAVE REGS OF INTERRUPTED PGM & RTN HERE SKSWCH: BR .+2 ;SWITCH NORMALLY OPEN TO FALL THROUGH... BR SKRELY ;...TO SKIP "SKED" AND RUN "SKNSRT" ; ON THE MINUTE IT IS CLOSED TO FORCE RUN OF "SKED" INSTEAD. .PAGE SKED: ;THIS IS THE SCHEDULER ;ENTER HERE EVERY MINUTE ON THE MINUTE FROM "CALENDAR" MOV @CURTHD,½TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R4),(SP);YES: REPLACE THE ZERO WITH ACTUAL ARG.. TST (R3)+ ;...AND BUMP SECONDARY MODULE POINTER ;SO THAT REFERENCES BELOW WILL ALLOW FOR ;THE EXTRA MODULE WORD THAT "ARG" USED. TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEU¾************************************************************ .PAGE QSKED: ;SUBROUTINE TO QUEUE A SCHEDULER MODULE ;TO WAIT FOR INSERTION INTO ONE OF THE ;TWO SCHEDULER THREADS MOV (SP),-(SP) ;MOVE RETURN ADDRESS UP FOR RTI LATER MOV PS,2(SP) ;...AND SET UP PS FOR RTI, TOO MOV R0,-(SP) ;SAVE USER'S MOV #340,PS ;RAISE CPU LEVELÀR0 ;[TH1BGN] OR [TH2BGN] MOV R0,R1 ;SAVE CURRENT THREAD ADDRESS FOR... ;...POSSIBLE MODULE REMOVAL (BELOW) MOV (R0),R0 ;NEXT MODULE'S ADDRESS BEQ SKDEX2 ;END OF THREAD: EXIT MOV R4,PS ;DROP CPU LEVEL TO BE FAIR TO OTHERS MOV STRTWD(R0),-(SP);STACK THIS MODULE'S START WORD FOR... JSR PC,UNPACK ;...CALL TO UNPACK SUBROUTINE, WHICH ; RETURNS ÁE TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ ;POP ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED BIT #40,R2 ;TEST "FLAG" OPTION BEQ TIMB60 ;NOT SELECTED BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULE POINTER FOR FLAGS TIMB60: BIT #20,R2 ;IS "JSR" OPTION SELECTED? BEQ TI TO AVOID INTERFERENCE CMP STBPTR,#SKTBND ;IS TABLE FULL? BLOS QSKA40 ;YES: POINTER IS AT BOTTOM, SO ERROR XIT MOV 6(SP),R0 ;MODULE'S ADDRESS BIC #10000,2(R0) ;CLEAR "D" FLAG IN CASE WAS DE-QUEUED DEC (R0) ;IS MODULE INACTIVE (THREAD WORD = 1)? BEQ QSKA20 ;O.K. ADD #2,(R0) ;SEE IF IN "WAIT" TABLE BEQ QSKA30 ;YES: O.K. TO TAKE GOOD EXIT NOW Ã; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QTIME" * ; * TIMER MODULE QUEUEING SUBROUTINE * ; * * ; * PURPOSE: LOADS TIMER MODULES ONTO "WAIT" STACK FOR "TIMER" * ; * "TMNSRT" IS RESPONSIBLE FOR UNLOADING FROM THE STACK * ; * AND STRINGING ONTO PROPER THREAD ÄWITH TIME & DATE OF MODULE'S START WORD SPREAD ON STACK ; (SP) = DAY OF MONTH 2(SP) = HOUR 4(SP) = MINUTE CMPB (SP),MDAY ;SEE IF MODULE IS FOR TODAY BGT SKDEX1 ;FOR TOMORROW OR BEYOND: EXIT BLT SKDB10 ;FOR YESTERDAY OR EARLIER: EXECUTE MODULE CMPB 2(SP),HOUR ;TODAY: THIS HOUR? BGT SKDEX1 ;MODULE IS EARLY: EXIT BLT SKDB10 ;MODULE IS LATE: EXECUTE CMPB 4(SP),MIÅMB15 ;NO: SKIP "J" LINK AND LOOP FOR MORE JSR PC,JSTARG(R3) ;LINK TO USER RTNE. (R1)=MODULE BEGIN BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #340,PS ;PROTECT AGAINST THIS INTERRUPT DURING ;EXIT SEQUENCE DECB TIMBSY ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE Æ BR QSKA35 ;IN THREAD: TAKE ERROR EXIT QSKA20: ;MODULE READY FOR INSERTION IN TABLE SUB #2,STBPTR ;PUSH TABLE POINTER MOV R0,@STBPTR ;LOAD NEW MODULE INTO TABLE QSKA30: CLR 6(SP) ;NOW READY TO EXIT. CLEAR ERROR FLAG QSKA35: DEC (R0) ;EITHER SETS T/W = -1 TO SHOW IN "WAIT" ;...OR RESTORES T/W TO ORIGINAL, IF NOT THREADED QSKA40: MOV (SP)+,R0 ;RESTORE USER'S Ç * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * MOV TIME,-(SP) ;STACK TIMER-RESET WORD * ; * EMT QTIME ;REQUEST TO QUEUE MODULE * ; * OR ÈNUTE ;FOR THIS HOUR. THIS MINUTE? BGT SKDEX1 ;TOO SOON SKDB10: MOV #340,PS ;LOCK OUT INTERFERENCE FROM "DQSKED" CMP (R0),#1 ;ALREADY DE-QUEUED? BNE SKDB20 ;STILL O.K. SKDB15: ;ALSO RETURN POINT FROM [SKDD10] ADD #6,SP ;POP SP DUE TO "UNPACK"... BR SKED ;...AND GO BACK FOR ANOTHER ONE SKRELY: BR SKNSRT ;RELAY POINT FOR SKIP TO 'INSERTÉ ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRUPTED PROGRAM .PAGE TTBPTR: .WORD 0 ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 Ê RTI ;RESTORE USER'S PS & RETURN .PAGE DQSKED: ;SYSTEM SUBROUTINE TO DE-QUEUE A SCHEDULER MODULE MOV (SP),-(SP) ;RE-ORDER STACK FOR "RTI" RETURN AT END MOV PS,2(SP) ;STACK NOW READY FOR "RTI" JSR R5,PUSHR ;PUSH ALL REGS ONTO STACK MOV 20(SP),R0 ;MODULE'S ADDRESS MOV #340,PS ;LOCK OUT INTERFERENCE FROM SCHEDULER CMP #1,(R0) ;HAS MODULE BEEN DË * ; * JSR PC,QTIME * ; * TST (SP)+ ;TEST ERROR RETURN CODE * ; * * ; * THE MODULE MUST BE SET UP, PRIOR TO THE CALL, AS DESCRIBED * ; * IN THE ROS USER'S MANUAL. NOTE THAT CALLS FOR MODULES HAVING * ; * THE "S" SUSPEND OPTION SET WILL CAUSE TRANSFER TO THE * ; * DISPATCHER, AND WILL NOT RETURN UNLESS THEÌ' RTNE .PAGE SKDB20: ;O.K. TO WORK ON THIS MODULE MOV (R0),(R1) ;FIRST: REMOVE MODULE BY "BRIDGING" THE ;THREAD OVER ITSELF, CONNECTING PREVIOUS ;MODULE WITH FOLLOWING ONE MOV #1,(R0) ;SET THIS MODULE INACTIVE... MOV R4,PS ;...DROP CPU LEVEL TO INTERRUPTED LEVEL MOV R0,R1 ;...AND SET UP THE SECONDARY MODULE PNTR MOV 2(R1Í ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST: ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY. .=$NRES*2+. ;RESERVE ONE WORD PER RESOLUTION TLAST: ;TABLE OF POINTERS TO LAST MÐE-QUEUED ALREADY? BEQ DQSK20 ;YES: INACTIVE,SO IGNORE CMP #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWNSTREAM MODULEÏ CALL IS IN ERROR. * ; * ON THESE CALLS THE MODULE'S TASK NUMBER IS AUTOMATICALLY SET * ; * TO THE CURRENTLY ACTIVE TASK'S NUMBER. * ; * IF THE "WAIT" STACK IS FULL, "QTIME" WILL EXIT WITH THE ERROR * ; * CODE WORD ON THE STACK NON-ZERO. THE MODULE WILL NOT BE QUEUED* ; * "QTIME" TAKES ITS ERROR EXIT IF THE REQUESTED MODULE IS ALREADY* ; * IN EITHER A TIMER THREAD OR THE "WAIT" STACK, AND HAS NOT BEEN * ; * FLAGGED FOR DE-QUEUEING. GOOD RETÒ),R2 ;GET OPTION & TASK WORD BPL SKDC10 ;"R" REPEAT FLAG NOT SET MOV DELTA(R1),-(SP) ;GET REPEAT WORD & STACK IT FOR CALL... JSR PC,UNPACK ;...TO SPREAD IT ON STACK ;NOW THE STACK HAS BOTH THE MODULE'S ;"START" AND "DELTA" WORDS SPREAD ON IT: ;(SP)= D-DATE 2(SP)= D-HOUR 4(SP)= D-MINUTE ["D" MEANS "DELTA"] ;6(SP)= S-DATE 8(SP)= S-HOUR 10(SP)= S-MINUTE ["S" MEANSÑODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREAD ;IS EMPTY. .=$NRES*2+. RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8,RES9 .BYTE RES10,RES11,RES12,RES13,RES14,RES15,RES16 .=RESTAB+$NRES .BYTE 0 ;END BYTE CURTAB: .BYTE REÒ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: * ; * SET TIME SET DATE GET TIME GET DATE * ; * * ; * ROUTINES TO SET AND GET CURRENT TIME AND DATE * ; * ÓURNS ARE MADE WHEN THE MODULE* ; * IS FOUND INACTIVE OR MARKED FOR DE-QUEUEING IN THE "WAIT" STACK* ; * IN THIS LAST CASE, THE MARK FOR DE-QUEUEING WILL BE REMOVED, * ; * AND THE MODULE WILL REMAIN WHERE IT IS ON THE "WAIT" STACK. * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.009 * ; * DATE: 30-NOV-71 Ô'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR R5,POPR S1,RES2,RES3,RES4,RES5,RES6,RES7,RES8,RES9 .BYTE RES10,RES11,RES12,RES13,RES14,RES15,RES16 .=CURTAB+$NRES .BYTE 0 ;END BYTE TIMBSY: .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END Ö "START"] MOV SP,R5 ;INIT SECONDARY STACK POINTER ADD #6,R5 ;POINT TO "S-DATE" ADD (SP)+,(R5)+ ;[D-DATE] + [S-DATE]: ACCUMULATE DAYS ADD (SP)+,(R5)+ ;[D-HOUR] + [S-HOUR]: ACCUMULATE HOURS ADD (SP)+,(R5)+ ;[D-MIN] + [S-MIN]: ACCUMULATE MINUTES CMP #60.,(R5) ;SEE IF MINUTES OVERFLOWED BGT SKDB30 ;NO: O.K. SUB #60.,(R5) :YES: STRIP MODULUS... Ú * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE TIMER .DEF QTIME .DEF TIMER .DEF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF UNSPND,QUEUE Ø ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS & RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "D" DE-QUEUE FLAÙELAY COUNT .BYTE 0 ;RESET TIME TMWRD1: .BYTE 10. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD2: .BYTE 15. ;DELAY COUNT .BYTE 0 ;RESET TIME TMWRD3: .BYTE 5 ;DELAY COUNT .BYTE 5 ;RESET TIME TMWRD4: .BYTE 10. ;DELAY COUNT .BYTE 10. ;RESET TIME TMWRD5: .BYTE 15. ;DELAY COUNT .BYTE 15. ;RESET TIME TMWRD6: .BYTE 0 ;DELAY COUNT .BYTE 0 ;RESETÛ INC -(R5) ;...AND BUMP HOURS TST (R5)+ ;(EQUALIZE POINTER IN CASE OF BRANCH) SKDB30: CMP #24.,-(R5) ;SEE IF HOURS OVERFLOWED BGT SKDB32 ;NO SUB #24.,(R5) ;YES: STRIP MODULUS... INC (SP) ;...AND BUMP DAYS SKDB32: MOVB MONTH,R3 ;USE CURRENT MONTH AS INDEX MOVB DAYTAB(R3),R3 ;GET # DAYS/MONTH INTO A WORD CMP R3,(SP) ;CHECK IF PAST END OF ÛE EMT TABLE, OR AN INVALID * ; * CODE WITHIN THE TABLE--- A RETURN IS MADE IMMEDIATELY TO THE * ; * CALLER WITH NO ACTION TAKEN. * ; * THE CALLER SHOULD NOTE THAT HE MAY BE INTERRUPTED BETWEEN HIS * ; * EMT CALL AND THE EVENTUAL RETURN, EVEN IN THE CASE OF AN ERROR.* ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.002 ÜG IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR .WORD 0 ;MULTIPLIER FOR ABORT AND TIME/SLICE CURTHD: .WORD ß TIME .PAGE T.30HD: .WORD 1 ;THREAD WORD .WORD T.30BG ;TASK ENTRY .WORD T.30IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.30PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 30. ;TASK # .WORD 0 Þ .REF $CTASK,$PRIOR,SUSPND .REF PUSHR,POPR,RESTOR .PAGE QTIME: ;ROUTINE TO PUT TIMER MODULE IN "WAIT" STACK MOV PS,-(SP) ;SAVE USER'S PS MOV #340,PS ;RAISE CPU LEVEL TO PROTECT ROUTINE MOV R0,-(SP) ;SAVE USER'S CMP TTBPTR,#TMTBND ;SEE IF STACK IS FULL BHI QTIM50 ;YES: ERROR EXIT MOV 10(SP),R0 ;ADDRESS OF MODULE DEC (R0) áMONTH BGE SKDB40 ;STILL THIS MONTH SUB R3,(SP) ;GET DAY OF NEXT MONTH .PAGE SKDB40: ;NOW RESTORE MODULE START WORD & STACK SWAB (SP) ;POSITION "DATE"... ASL (SP) ASL (SP) ASL (SP) ;...FOR PLACE BACK IN "START" WORD SWAB 2(SP) ;POSITION "HOUR" ASR 2(SP) ASR 2(SP) ;...FOR ITS PLACE BIS àTHDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BEGIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF "WAIT" TABLE á.ôt!¯”Ÿ s@ú&ày@;K}@Ç.hf€p@”f�@[gÐ4@�m„@[qj@.L©C @R«ª:@(¤¯xhš-²ZhRã.D~hVA*}hŽ»ŒEhüm4€ph�!?È}hž».áQ@œh ¶Re†hœ¦S@~h¡Cmàhº‹wô_h›¸.ây2ghbYzâ ;IS TIMER MODULE INACTIVE? (T/W=0?) BNE QTIM30 ;NO: SEE IF ACTIVE OR IN "WAIT" STATE QTIM20: ;HERE WHEN CLEARED TO STACK UP MODULE ADD #2,TTBPTR ;PUSH "WAIT" STACK POINTER MOV R0,@TTBPTR ;ENTER MODULE ADDRESS INTO "WAIT" STACK BIS #C1CBIT,C1COMD ;START UP CLOCK IF IT WAS OFF TST 2(R0) ;CHECK OPTION FLAG FOR "SUSPEND" BMI QTIM60 ;"SUSPEND" SELECTED QTIM40: ã ;STACK SAVE .=NN*2+. T.31HD: .WORD 1 ;THREAD WORD .WORD T.31BG ;TASK ENTRY .WORD T.31IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.31PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 31. ;TASK # ä DAYTAB = .-1 ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH JANARY = . FEBARY = .+1 .BYTE 31.,28.,31.,30.,31.,30.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULIAN DATE MONTå (SP)+,(SP) ;[OR] DATE & HOUR... BIS (SP)+,(SP) ;...WITH MINUTE... MOV (SP)+,STRTWD(R1);...AND RE-STORE INTO START WORD TST (R1)+ ;BUMP POINTER TO ALLOW FOR "DELTA" WORD MOV R0,-(SP) JSR PC,QSKED ;RE-QUEUE MODULE IN NEW TIME SLOT TST (SP)+ ;POP RETURN ERROR WORD SKDC10: ;CONTINUE PROCESSING MODULE... ;...WHETHER OR NOT IT WAS REPEæ ;THIS IS THE "SUCCESSFUL" EXIT CLR 10(SP) ;PREPARE ERROR RETURN CODE TO SHOW O.K. QTIM45: ;HERE WHEN EXITING TO "SUSPEND". AVOID CLEARING 10(SP) MOV 6(SP),4(R0) ;LOAD NEW TIMER/RESET WORD INTO MODULE ; THIS SERVES AS NORMAL INIT FOR TIMER MODULE, AND ALSO RESETS ; THE "RESET" BYTE IN CASE MODULE IS BEING RE-QUEUED AFTER BEING ; DE-QUEUED, ALL WHILE REMAINING IN "WAIT" STACK. QTIM50: ;HERE WHEN EXIT IS ç .WORD 0 ;STACK SAVE .=NN*2+. T.32HD: .WORD 1 ;THREAD WORD .WORD T.32BG ;TASK ENTRY .WORD T.32IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.32PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS .BYTE 32. H: .BYTE 0 ;CURRENT MONTH MDAY: .BYTE 0 ;CURRENT DAY OF MONTH YEAR: .BYTE 0 ;CURRENT YEAR (MINUS 1900) SKDBSY: .BYTE -1 ;SCHEDULER BUSY FLAG: IDLE=-1; .END éATED TSTB R2 ;TASK NUMBER BEQ SKDD10 ;NO QUEUEING WHEN IT IS ZERO MOVB R2,-(SP) ;STACK TASK # IN PREP FOR CALL TO QUEUE .IFNZ DPRTY ;OPTION FOR DYNAMIC PRIORITIES CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITIES .ENDC DPRTY CLR -(SP) ;IMMEDIATE RETURN REQUESTED... ;...OR INIT OF [ARG] IF NEEDED ASL R2 ;IS THE "A" êTO LEAVE NON-ZERO ERROR CODE ON STACK DEC (R0) ;SET T/W=-1 TO SHOW IN "WAIT" STATE... ;...OR TO RESTORE MODULE'S T/W IF IT IS FOUND ALREADY ACTIVE... ; ...OR ALREADY IN "WAIT" STATE MOV (SP)+,R0 ;RESTORE USER'S MOV (SP)+,2(SP) ;MOVE OLD [PS] IN PREP FOR RTI RTI ;ZAP! RETURN TO USER OR GO TO SUSPEND ;ON OLD CPU LEVEL QTIM30: ADD #2,(R0) ;NOT INACTIVE. SEE Ië;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.33HD: .WORD 1 ;THREAD WORD .WORD T.33BG ;TASK ENTRY .WORD T.33IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.33PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ;STATUS ìP #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWNSTREAM MODULE'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 í(ARGUMENT) FLAG SET? BPL SKDC20 ;NO: LEAVE THE ZERO ON STACK FOR ARG'MNT .IFNZ ARG ;OPTION FOR TRANSMITTING ARGUMENT MOV @6(R1),(SP) ;YES: PUT ACTUAL ARG IN PLACE OF ZERO .ENDC ARG TST (R1)+ ;BUMP POINTER IN ANY CASE IF "A" IS SET SKDC20: .IFNZ ARG ;OPTION FOR TRANSMITTING ARGUMENT CLR -(SP) ;PUSH RETURN CODE .ENDC ARG JSR PC,QUEUE ;NîF ACTIVE OR "WAIT" BNE QTIM50 ;ACTIVE: TAKE ERROR EXIT CMPB 5(R0),#-1 ;IN "WAIT": IS IT FLAGGED FOR DE-QUEUE? BNE QTIM50 ;NO: ERROR EXIT BR QTIM40 ;YES: LEAVE THERE AND REMOVE D-Q FLAG .PAGE QTIM60: ;HERE WHEN TASK IS TO BE SUSPENDED UNTIL TIMER EXPIRES MOVB $CTASK,2(R0) ;LOAD MODULE TASK # WITH CURRENT TASK MOV 4(SP),10(SP) ;SET CALLER RTN TO LOOK LIKE "JSR" ï .BYTE 33. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.34HD: .WORD 1 ;THREAD WORD .WORD T.34BG ;TASK ENTRY .WORD T.34IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.34PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT .BYTE 0 ð ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR R5,POPR ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS &ñOW CALL "QUEUE" TO RUN REQUESTED TASK TST (SP)+ ;...AND POP ERROR CODE ON RETURN SKDD10: ;QUEUEING OR NO, NOW CHECK FOR FLAG-SET ASL R2 ;IS THE "F" FLAG OPTION SET? BPL SKDB15 ;NO: THIS MODULE DONE: BACK FOR MORE BISB 8.(R1),@6(R1) ;YES: DO [IOR] OF MASK INTO FLAG LOC'N BR SKDB15 ;DONE WITH MODULE: LOOK FOR MORE SKDEX1: ADD #6,SP ;ADJUST SP FROM CALL TO "Uò MOV #SUSPND,4(SP) ;SET STACK SO RTI WILL GO TO "SUSPEND" BR QTIM45 ;INSTEAD OF RETURNING TO CALLER .PAGE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "DQTIME" * ; * TIMER MODULE DE-QUEUEING SUBROUTINE * ; * ó ;STATUS .BYTE 34. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.35HD: .WORD 1 ;THREAD WORD .WORD T.35BG ;TASK ENTRY .WORD T.35IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.35PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGUMENT ô RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "D" DE-QUEUE FLAG IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGõNPACK" SKDEX2: ;SCHEDULER EXIT WITH NO STACK POP MOV #340,PS ;PROTECT CHECK OF BUSY FLAG MOVB #-1,SKDBSY ;RESET FLAG TO ALLOW NEXT ENTRY JMP RESTOR ;RETURN TO INTERRUPTED PGM ==>[RESTOR] .PAGE UNPACK: ;INTERNAL SUBROUTINE TO SPREAD A SCHEDULER TIME&DATE ;WORD ONTO THE STACK ;UPON ENTRY, ROUTINE ASSUMES PACKED WORD IS ON TOP OF STACK; ; 15 11 10 6 5 1  * ; * PURPOSE: * ; * REMOVES TIMER MODULES FROM TIMER THREADS, IF ACTIVE * ; * AND IF FOUND IN ITS PROPER THREAD. IF ACTIVE BUT NOT * ; * FOUND, ERROR EXIT IS TAKEN. IF STILL IN "WAIT" STACK * ; * IT IS MARKED FOR REMOVAL WHEN "TMNSRT" IS RUN. * ; * IF MODULE IS ALREADY INACTIVE, NO ACTION TAKEN, AND * ; * GOOD EXIT IS TAKEN.÷.BYTE 0 ;STATUS .BYTE 35. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. T.36HD: .WORD 1 ;THREAD WORD .WORD T.36BG ;TASK ENTRY .WORD T.36IN ;TASK INIT .WORD 0 ;MAX XEQ TIME .BYTE NN ;STACK SIZE .BYTE T.36PR ;TASK PRIORTY .WORD 0 ;TASK TIMER .WORD 0 ;ARGøAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR: .WORD 0 ;CLOCK BASE PERIOD MULTIPLIER CURTHD: .WORD THDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BEú; DAY ^ HOUR ^ MINUTE ;UPON EXIT, STACK HAS THREE WORDS ON IT: ; (SP)= DAY 2(SP)= HOUR 4(SP)= MINUTE MOV (SP),R3 ;COPY T&D WORD MOV R3,R5 ;SAVE IT FOR BELOW BIC #177700,(SP) ;LEAVE MINUTE ALL BY ITSELF ASL R3 ASL R3 SWAB R3 ;GET "HOUR" INTO LOW BYTE BIC #177740,R3 ;CLEAR ALL OTHER STUFF MOV R3,-(SP) ;PUT IT IN ITS OWN PLACEú .REF QSKED,DQSKED,TTYOUT,TTYIN,BINASC,ASCBIN .REF MASK,UNMASK,ERRTYP .REF DISCIO,CHKPIO,PFRITE .DEF EMTRAP,EMTABL,MAXEMT .PAGE .ASECT .=30 .WORD EMTRAP,340 ;INIT TRAP LOCATION: RUNS AT LEVEL 7. .CSECT EMTRAP = . ;ENTRY TO EMT SERVICE ROUTINE TST -(SP) ;PUSH STACK TO MAKE ROOM FOR SBRTNE ADDR MOV R0,-(SP) ;SAVE IT MOV 4(SP),R0 ûUMENT .BYTE 0 ;STATUS .BYTE 36. ;TASK # .WORD 0 ;STACK SAVE .=NN*2+. .PAGE T.30BG: ;TASK #30 BEGIN MOV #MODUL0,-(SP) MOV TMWRD0,-(SP) EMT QTIME ;QUEUE ONE TIMER MODULE TST (SP)+ MOV #LIST30,-(SP) EMT TTYOUT ;TYPE TASK I.D. EMT EXIT T.31BG: ;TASK #31 üGIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF "WAIT" TABLE DAYTAB: ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH .BYTE 31.,28.,31.,30.,31.,30ý.u~€¯”(ü��ļh��ÃhH].��DÉh‚��„Ïh¼��ÄÕhö��Üh0��DâhjÛ¯”‘÷æ(  ¤¡¤HãH¸¬¸‚þ SWAB R5 ASR R5 ASR R5 ASR R5 ;GET [DAY] INTO LOWER BYTE... BIC #177740,R5 ; ...CLEAR GARBAGE... MOV R5,-(SP) ; ...AND PUT IN ITS OWN PLACE RTS PC .PAGE SKNSRT: ;ROUTINE TO INSERT SCHEDULER MODULES FROM THE WAITING ;TABLE. ALSO LOOP RE-ENTRY POINT FROM END MOV #340,PS ;LOCK OUT INTERFERENCE FROM "QSKED" SKNA10: ÿMOV #LIST31,-(SP) EMT TTYOUT MOV #MODUL2,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #LIST31,-(SP) EMT TTYOUT EMT EXIT T.32BG: ;TASK #32 MOV #MODUL3,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ MOV #MODUL4,-(SP) MOV TMWRD1,-(SP) EMT QTIME TST (SP)+ MOV #MODUL5,.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULIAN DATE MDAY: .BYTE 0 ;CURRENT DAY OF MONTH MONTH: .BYTE 0 ;CURRENT MONTH YEAR: .BYTE 0 ;CURRENT YEA£‚Ò VÒ¼O¼þ!îþöéö "£ 0Ÿ0#XjWj($(¤,¤æTæTþˆÖ æX ˆˆæ| ˆæpæ<þˆZTX| pí.ÈÖ æ| ˆˆæ~æ&þˆÖ æŒæþˆÖ æšÊ|~Œ(šZ0îæþˆÖ æ  ˆˆ÷ÆþàæÄ  ;LOOP RETURN WHEN LOCKOUT IS ALREADY SET MOV @STBPTR,R0 ;GET ADDRESS OF NEXT MODULE BEQ SKDEX2 ;TABLE EMPTY: EXIT VIA "RESTOR" ADD #2,STBPTR ;NOT EMPTY: POP POINTER BACK ONE CELL MOV #1,(R0) ;SET INACTIVE IN CASE DE-QUEUED BIT #10000,2(R0) ;WAS IT DE-QUEUED WHILE IN TABLE? BNE SKNA10 ;YES: IGNORE AND CONTINUE MOV R4,PS ;RESTORE PREVIOUS CPU LEVEL -(SP) MOV TMWRD2,-(SP) EMT QTIME TST (SP)+ MOV #LIST32,-(SP) EMT TTYOUT EMT EXIT .PAGE T.33BG: ;TASK #33 MOV T.33HD+14,T.33AR ;TRANSFER ARGUMENT MOV #LIST33,-(SP) EMT TTYOUT EMT EXIT T.34BG: ;TASK #34 MOV T.34HD+14,T.34AR ;TRANSFER ARGUMENT MOV #LIST34,-(SP) EMT TTYOUT EMT EXIT T.35R (MINUS 1900) .BYTE 0 ;PAD .END ˆˆ÷òþöæè' Ä*è@. ˆˆ÷ÿ æ  ˆˆæTˆÖ æbˆÖ æp. T b(p3,<ˆÖ æ~ˆÖ æŒˆÖ æ0 ˆˆê ~Œ0m#`fTASK #30 ARG= ‚f|ö+|ŠTASK #31 ARG= 7Š ¦+ ®TASK #32 ARG= î®Ä^+ÄÒTASK #33 ARG= ¥ MOV 4(R0),-(SP) ;STACK MODULE'S DATE WORD FOR... JSR PC,UNPACK ;...CALL TO SPREAD IT ON STACK TST (SP) ;IF "DATE" = 0,... BNE SKNA20 MOVB MDAY,(SP) ;...THEN USE TODAY'S DATE SKNA20: CMP 2(SP),#37 ;IF "HOUR" IS ALL ONES... BNE SKNA30 MOVB HOUR,2(SP) ;...THEN USE CURRENT HOUR SKNA30: CMP 4(SP),#77 ;IF "MIN" IS ALL ONES... BNE SKNA40 MOVB MINUTE,4BG: ;TASK #35 MOV T.35HD+14,T.35AR ;TRANSFER ARGUMENT MOV #LIST35,-(SP) EMT TTYOUT EMT EXIT T.36BG: MOV #MODUL0,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL1,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL2,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL3,-(SP) EMT DQTIME TST (SP)+ MOV #MODUL * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO DE-ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * EMT DQTIME ;REQUEST TO DE-QUEUE MODULE * ; * Òè+èöTASK #34 ARG= \ö Í+ TASK #35 ARG= 0„+0>TASK #36 ARG= È>T<,T!îøSà"#ð£îb î øàð&îÅ,x!ð"ò!ðòÕ,œ#ô ôñ,À (SP) ;...THEN USE CURRENT MINUTE .PAGE SKNA40: ;NOW THAT MODULE'S TIME IS READY, BEGIN SEARCH FOR ITS ;PLACE IN ONE OF THE TWO SCHEDULER THREADS. MOV CURTHD,R1 ;POINTS TO [THDTAB] OR [THDTAB+2] CMPB (SP),MDAY ;MODULE DATE :: TODAY'S DATE BGT SKNA60 ;AFTER TODAY: USE CURRENT THREAD BLT SKNA50 ;BEFORE TODAY: USE "FUTURE" THREAD CMPB 2(SP),HOUR ;MODULE HOUR :: CURRENT 4,-(SP) EMT DQTIME TST (SP)+ MOV #LIST36,-(SP) EMT TTYOUT EMT EXIT .PAGE LIST30: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.30  OR * ; * JSR PC,DQTIME ;DIRECT CALL WITH PROPER LINK * ; * TST (SP)+ ;POP ERROR RETURN CODE * ; * * ; * NOTE THAT THE THREE ROUTINES: [TIMER], [QTIME], AND * ; * [DQTIME] ALLOW AN UNLIMITED NUMBER OF CALLS TO QUEUE * ; * OR DE-QUEUE THE SAME MODULE, REGARDLESS OF ITS STATUS * ; * AT æb§ &beäæüˆÖ ‡12345é üêóHOUR BGT SKNA60 ;LATER TODAY: USE CURRENT THREAD BLT SKNA50 ;WAS EARLIER TODAY: PUT IN "FUTURE" CMPB 4(SP),MINUTE ;MODULE MINUTE :: CURRENT MINUTE BGE SKNA60 ;NOW OR WITHIN HOUR: CURRENT THREAD SKNA50: TST (R1)+ ;WE ARE PAST MODULE'S TIME: USE "FUTURE" SKNA60: ;NOW THAT PROPER THREAD BEGIN WORD'S ADDRESS IS IN R1, ;WE CAN BEGIN SEARCH OF THAT THREAD. MOV (R1),R2 BF ;MSG BUFFER T.30BF: .WORD MSG30X-T.30BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #30 ARG=" T.30AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG30X = .-1 .EVEN .PAGE LIST31: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT ANY GIVEN TIME. THE STATE UPON THE RETURN FROM A * ; * CALL TO [QTIME] OR [DQTIME], ASSUMING A ZERO ERROR CODE* ; * ASSURES THAT THE MODULE IS IN THE MOST RECENTLY * ; * REQUESTED STATE. THE ONLY EXCEPTION IS WHEN A CALL TO * ; * [DQTIME] HAS BEEN MADE AFTER THE REQUESTED MODULE HAS * ; * TIMED OUT AND BEGUN EXECUTION. STRICTLY SPEAKING, THE * ; * CALL IN THIS CASE CAME AFTER THE MODULE WAS RUN. * ; * YEAR * ; * JSR PC,SDATE ;CALL "SET DATE" * ; * * ; * TST (SP)+ ;POP ERROR WORD * ; * TST (SP)+ ;POP ERROR WORD * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; * BNE ERROR ;CALL PARAMETERS IN ERROR * ; *  ;ADDR OF ONE OF THE THREAD-BEGIN WORDS BR SKNB00 ;ENTER LOOP FOR FIRST TIME SKNB10: ;THIS IS THE LOOP RETURN POINT AS LONG AS SEARCH CONT'S ADD #6,SP ;POP STACK POINTER FROM "UNPACK" BELOW SKNB00: ;HERE FOR FIRST-TIME ENTRY MOV R2,R1 ;SAVE OLD T/W ADDRESS MOV (R2),R2 ;GET NEXT MODULE'S (T/W) ADDRESS BEQ SKNB30 ;AT END OF THREAD ;NOT @ END: TEST MODUL .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.31BF ;MSG BUFFER T.31BF: .WORD MSG31X-T.31BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #31 ARG=" T.31AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG31X = .-1 .EVEN LIST32: .WORD 1 ;THREAD WORD; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QTIME" * ; * TIMER MODULE QUEUEING SUBROUTINE * ; * * ; * PURPOSE: LOADS TIMER MODULES ONTO "WAIT" STACK FOR "TIMER" * ; * "TMNSRT" IS RESPONSIBLE FOR UNLOADING FROM THE STACK * ; * AND STRINGING ONTO PROPER THREAD  * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .DEF DQTIME .PAGE DQTIME: ;SYSTEM SUBROUTINE TO DE-QUEUE A TIMER MODULE MOV (SP),-(SP) ;MOVE RTN ADDR IN PREP FOR "RTI" AT END MOV PS,2(SP) ;PLACE [PS] ALSE FOR TIME MOV 4(R2),-(SP) ;STACK TEST MODULE'S DATE WORD... JSR PC,UNPACK ;...FOR CALL TO SPREAD IT ON STACK CMP 6(SP),(SP) ;NEW MOD'S DATE :: TEST MOD'S DATE BGT SKNB10 ;LATER: KEEP LOOKING BLT SKNB20 ;EARLIER: THREAD NOW CMP 10(SP),2(SP) ;NEW MOD'S HOUR :: TEST MOD'S HOUR BGT SKNB10 ;STILL LATER BLT SKNB20 ;EARLIER CMP 12(SP),4(SP)  .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.32BF ;MSG BUFFER .PAGE T.32BF: .WORD MSG32X-T.32BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #32 ARG=" T.32AR: .ASCII " " * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * MOV TIME,-(SP) ;STACK TIMER-RESET WORD * ; * EMT QTIME ;REQUEST TO QUEUE MODULE * ; * OR O FOR "RTI" MOV #340,PS ;RAISE CPU LEVEL: PROTECT AGAINST "TIMER" JSR R5, PUSHR ;SAVE ALL REGISTERS MOV 20(SP),R0 ;GET MODULE'S ADDRESS CMP #1,(R0) ;IS MODULE ALREADY INACTIVE? BEQ DQTM20 ;YES: TAKE GOOD EXIT CMP #-1,(R0) ;IS MODULE STILL IN "WAIT" STACK? BEQ DQTM40 ;YES: GO SET "DE-QUEUE" FLAG MOVB 3(R0),R1 ;IS IN ACTIVE QUEUE: TAKE IT OUT  ;COMPARE MINUTES BGT SKNB10 .PAGE SKNB20: ;HAVE FINALLY FOUND SLOT FOR NEW MODULE. R1 CONTAINS ;ADDR OF PREVIOUS OR "UPSTREAM" MODULE (MIGHT BE THE ;THREAD START WORD) AND R2 CONTAINS ADDR OF DOWNSTREAM ;MODULE, OR ZERO IF NEW MODULE IS BEING PLACED AT END ;OF THREAD. R0 CONTAINS ADDR OF NEW MODULE. ADD #6,SP ;POP SP FROM 1ST CALL TO "UNPACK" SKNB30: ADD #6,SP ;P ;TRANSMITTED ARG .BYTE 15 ;CR MSG32X = .-1 .EVEN LIST33: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.33BF ;MSG BUFFER T.33BF:  * ; * JSR PC,QTIME * ; * TST (SP)+ ;TEST ERROR RETURN CODE * ; * * ; * THE MODULE MUST BE SET UP, PRIOR TO THE CALL, AS DESCRIBED * ; * IN THE ROS USER'S MANUAL. NOTE THAT CALLS FOR MODULES HAVING * ; * THE "S" SUSPEND OPTION SET WILL CAUSE TRANSFER TO THE * ; * DISPATCHER, AND WILL NOT RETURN UNLESS THE BIC #177760,R1 ;GET MODULE'S RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R1,R3 ;SAVE RESOLUTION IN CASE NEEDED BELOW ADD #TFIRST,R1 ;ADDR OF RESOLUTION'S "FIRST" WORD DQTM10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;SAVE UPSTREAM MODULE'S ADDR MOV (R1),R1 ;ADDR OF DOWNSTREAM MODULE BEQ DQTM30 ;END OF THREAD: SEARCH FAIL ERROR OP SP FROM 2ND CALL TO "UNPACK" MOV R0,(R1) ;LOAD UPSTREAM THREAD-WORD FOR NEW MOD MOV R2,(R0) ;LOAD NEW T/W FOR DOWNSTREAM MOD BR SKNSRT ;GO BACK FOR POSSIBLE MORE MODULES. .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "QSKED" * ; * SYSTEM SUBROUTINE TO QUEUE A SCHEDULER MODULE * ; * .WORD MSG33X-T.33BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #33 ARG=" T.33AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG33X = .-1 .EVEN .PAGE LIST34: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE  CALL IS IN ERROR. * ; * ON THESE CALLS THE MODULE'S TASK NUMBER IS AUTOMATICALLY SET * ; * TO THE CURRENTLY ACTIVE TASK'S NUMBER. * ; * IF THE "WAIT" STACK IS FULL, "QTIME" WILL EXIT WITH THE ERROR * ; * CODE WORD ON THE STACK NON-ZERO. THE MODULE WILL NOT BE QUEUED* ; * "QTIME" TAKES ITS ERROR EXIT IF THE REQUESTED MODULE IS ALREADY* ; * IN EITHER A TIMER THREAD OR THE "WAIT" STACK, AND HAS NOT BEEN * ; * FLAGGED FOR DE-QUEUEING. GOOD RET! CMP R0,R1 ;IS THIS THE MODULE TO BE DE-QUEUED? BNE DQTM10 ;NO: KEEP LOOKING MOV (R1),(R2) ;FOUND IT! BRIDGE OVER THIS MODULE... BNE DQTM15 ;...AND EXIT IF NOT LAST MODULE MOV R2,TLAST(R3) ;...BUT UPDATE "LAST" ENTRY IF WAS @ END DQTM15: MOV #1,(R1) ;FINALLY, FLAG MODULE INACTIVE DQTM20: CLR 20(SP) ;CLEAR RETURN ERROR FLAG FOR GOOD EXIT DQTM30: JSR R5,POPR ;RESTORE SAVED " * ; * PURPOSE: * ; * PUTS ADDRESS OF CALLER'S MODULE IN INTERNAL STACK. * ; * THIS TABLE IS EMPTIED BY THE ROUTINE "SKNSRT" WHICH IS * ; * CALLED BY THE SCHEDULER EACH MINUTE JUST BEFORE IT RUNS* ; * THIS METHOD AVOIDS QUEUEING AND SCHEDULER CONFLICTS WHE* ; * ACCESSING THE TWO SCHEDULER THREADS(THE SCHEDULER DROPS* ; * THE CP# .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.34BF ;MSG BUFFER T.34BF: .WORD MSG34X-T.34BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #34 ARG=" T.34AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG34X = .-1 .EVEN .PAGE LIST35: .WORD 1 ;THREAD WORD .BYTE 0 $URNS ARE MADE WHEN THE MODULE* ; * IS FOUND INACTIVE OR MARKED FOR DE-QUEUEING IN THE "WAIT" STACK* ; * IN THIS LAST CASE, THE MARK FOR DE-QUEUEING WILL BE REMOVED, * ; * AND THE MODULE WILL REMAIN WHERE IT IS ON THE "WAIT" STACK. * ; * * ; * PROGRAMMER: 52 * ; * VERSION: 002.008 * ; * DATE: 23-NOV-71 %REGISTERS... RTI ;...AND RETURN TO CALLER WITH HIS PS DQTM40: ;HERE IF MODULE IS STILL IN "WAIT" STACK MOVB #-1,5(R0) ;SET "RESET" BYTE TO ALL ONES TO SHOW ;"TMNSRT" TO IGNORE THIS MODULE BR DQTM20 ;GO TAKE GOOD EXIT .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "TIMER" * ; * &U LEVEL SO AS NOT TO LOCK OUT INTERRUPTS UNNECES-* ; * SARILY), REDUCING THE CONFLICT AREA TO JUST THE FIFO * ; * TABLE. THIS CONFLICT IS AVOIDED, THEN, BY RUNNING * ; * "QSKED" (A SHORT ROUTINE) AND THE FEW WORDS OF CODE * ; * IN "SKNSRT" WHICH ACCESS THE TABLE, UNDER INTERRUPT- * ; * LOCKOUT. * ; * * ; * USAGE:' ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.35BF ;MSG BUFFER T.35BF: .WORD MSG35X-T.35BF-4 ;BUFFER LENGTH .WORD 0 ;SYSTEM RESERVED .ASCII "TASK #35 ARG=" T.35AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15( * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .TITLE TIMER .DEF QTIME .DEF TIMER .DEF TWAITB,TTBPTR,TFIRST,TLAST,RESTAB,CURTAB,TIMBSY,BASCNT .REF UNSPND,QUEUE ) HIGH-RESOLUTION CLOCK PULSE SERVICE ROUTINE * ; * * ; * PURPOSE: --SERVICES ALL TIMER MODULES AT THEIR RESPECTIVE * ; * RESOLUTIONS, PROVIDING THE FEATURES OF TASK * ; * TIME-DELAY, PERIODIC OR ONE-SHOT QUEUEING, * ; * FLAG-SETTING,AND COMPLETION-ROUTINE CALLS. * ; * --KEEPS TRACK OF THE TASK-EXECUTION TIME (ABORT) * ; * * ; * USERS CAN CALL "QSKED" EITHER VIA JSR (IF LINKED) OR * ; * VIA EMT. IN EITHER CASE THE ADDRESS OF THE MODULE TO BE* ; * THREADED MUST FIRST BE PLACED ON THE STACK.THE STACK * ; * POINTER IS LEFT UNCHANGED ON RETURN. THE STACK LOCATION* ; * ITSELF WILL BE CLEARED IF THE TABLE HAS ROOM FOR * ; * IT AND THE MODULE ITSELF IS INACTIVE (ITS THREAD WORD * ; * + ;CR MSG35X = .-1 .EVEN LIST36: .WORD 1 ;THREAD WORD .BYTE 0 ;TTY DEVICE # .BYTE 1 ;IMEDIATE RTN .WORD 0 ;NO I/O CMPLT .BYTE 0 ;NO ERR RTNE .BYTE 0 ;NORMAL MSG .WORD , ;SYS RESERVE .WORD T.36BF ;MSG BUFFER T.36BF: .WORD MSG36X-T.36BF-4 ;BUFFER LENGTH , .REF $CTASK,$PRIOR,SUSPND .REF PUSHR,POPR,RESTOR .PAGE QTIME: ;ROUTINE TO PUT TIMER MODULE IN "WAIT" STACK MOV PS,-(SP) ;SAVE USER'S PS MOV #340,PS ;RAISE CPU LEVEL TO PROTECT ROUTINE MOV R0,-(SP) ;SAVE USER'S CMP TTBPTR,#TMTBND ;SEE IF STACK IS FULL BHI QTIM50 ;YES: ERROR EXIT MOV 10(SP),R0 ;ADDRESS OF MODULE DEC (R0) - * COUNTER, AND CALLS FOR TASK ABORT IF TIME * ; * RUNS OUT. * ; * --PROVIDES (OPTIONAL) TIME-SLICE FEATURE BY * ; * PERIODICALLY ROTATING THE TASKS IN A QUEUE. * ; * * ; * USAGE: ACTIVATED BY CLOCK INTERRUPT. ALL PROGRAMS HANDLE * ; * COMMUNICATION VIA "QTIME" AND "DQTIME". "TIMER" . MUST BE =1). IN CASE OF ONE OF THE ABOVE ERRORS, THE * ; * STACK LOCATION IS LEFT UNCHANGED (NON-ZERO) FOR TESTING* ; * BY THE CALLER. * ; * "QSKED" SAVES & RESTORES ALL REGISTERS THAT IT USES. * ; * IT MAY BE CALLED BY ANY TYPE OF USER AT ANY TIME. * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S */.WORD 0 ;SYSTEM RESERVED .ASCII "TASK #36 ARG=" T.36AR: .ASCII " " ;TRANSMITTED ARG .BYTE 15 ;CR MSG36X = .-1 .EVEN .PAGE MODUL0: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD FLAG1 ;FLAG ADDR .WORD MASK1 0 ;IS TIMER MODULE INACTIVE? (T/W=0?) BNE QTIM30 ;NO: SEE IF ACTIVE OR IN "WAIT" STATE QTIM20: ;HERE WHEN CLEARED TO STACK UP MODULE ADD #2,TTBPTR ;PUSH "WAIT" STACK POINTER MOV R0,@TTBPTR ;ENTER MODULE ADDRESS INTO "WAIT" STACK BIS #C1CBIT,C1COMD ;START UP CLOCK IF IT WAS OFF TST 2(R0) ;CHECK OPTION FLAG FOR "SUSPEND" BMI QTIM60 ;"SUSPEND" SELECTED QTIM40: 1 * ; * CALLS SYSTEM SUBROUTINES "QUEUE", "SAVE", "UNSPND", * ; * AND "ABORT". * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** ; FOLLOWING ARE OFFSET PARAMETERS FOR TIMER MODUL2 ; ******************************************************************** .PAGE QSKED: ;SUBROUTINE TO QUEUE A SCHEDULER MODULE ;TO WAIT FOR INSERTION INTO ONE OF THE ;TWO SCHEDULER THREADS MOV (SP),-(SP) ;MOVE RETURN ADDRESS UP FOR RTI LATER MOV PS,2(SP) ;...AND SET UP PS FOR RTI, TOO MOV R0,-(SP) ;SAVE USER'S MOV #340,PS ;R3 ;FLAG MASK .WORD JSRTNE ;JSR TARGET MODUL1: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 43 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL2: .WORD 1 ;THREAD WORD .BYTE 2 4 ;THIS IS THE "SUCCESSFUL" EXIT CLR 10(SP) ;PREPARE ERROR RETURN CODE TO SHOW O.K. QTIM45: ;HERE WHEN EXITING TO "SUSPEND". AVOID CLEARING 10(SP) MOV 6(SP),4(R0) ;LOAD NEW TIMER/RESET WORD INTO MODULE ; THIS SERVES AS NORMAL INIT FOR TIMER MODULE, AND ALSO RESETS ; THE "RESET" BYTE IN CASE MODULE IS BEING RE-QUEUED AFTER BEING ; DE-QUEUED, ALL WHILE REMAINING IN "WAIT" STACK. QTIM50: ;HERE WHEN EXIT IS 5E REFERENCES SAVE = 3 ;OP-CODE FOR TRAP TO "SAVE" SUBROUTINE TASKNO = 2 ;TASK NUMBER BYTE OPTION = 3 ;OPTION FLAGS BYTE TIMBYT = 4 ;MODULE TIMER BYTE RESET = 5 ;TIMER RESET BYTE TIMARG = 6 ;ARGUMENT (FOR QUEUEING) ADDRESS WORD TMFLAG = 6 ;FLAG ADDRESS WORD (DYNAMIC OFFSET) TIMASK = 8. ;FLAG MASK WORD (DYNAMIC OFFSET) JSTARG 6AISE CPU LEVEL TO AVOID INTERFERENCE CMP STBPTR,#SKTBND ;IS TABLE FULL? BLOS QSKA40 ;YES: POINTER IS AT BOTTOM, SO ERROR XIT MOV 6(SP),R0 ;MODULE'S ADDRESS BIC #10000,2(R0) ;CLEAR "D" FLAG IN CASE WAS DE-QUEUED DEC (R0) ;IS MODULE INACTIVE (THREAD WORD = 1)? BEQ QSKA20 ;O.K. ADD #2,(R0) ;SEE IF IN "WAIT" TABLE BEQ QSKA30 ;YES: O.K. TO TAKE GOO7 ;TASK # .BYTE 243 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG1 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL3: .WORD 1 ;THREAD WORD .BYTE 33. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG2 ;ARG 8TO LEAVE NON-ZERO ERROR CODE ON STACK DEC (R0) ;SET T/W=-1 TO SHOW IN "WAIT" STATE... ;...OR TO RESTORE MODULE'S T/W IF IT IS FOUND ALREADY ACTIVE... ; ...OR ALREADY IN "WAIT" STATE MOV (SP)+,R0 ;RESTORE USER'S MOV (SP)+,2(SP) ;MOVE OLD [PS] IN PREP FOR RTI RTI ;ZAP! RETURN TO USER OR GO TO SUSPEND ;ON OLD CPU LEVEL QTIM30: ADD #2,(R0) ;NOT INACTIVE. SEE I9 = 6 ;USER ROUTINE ADDRESS WORD (DYN OFFSET) .PAGE TIMA00: RTI ;RETURN USED IF CLOCK IS RE-ENTERED ;TO PROCESS QUEUE WHILE PREVIOUS REQUEST IN PROGRESS. TIMA70: ;HERE TO RESET RESOLUTION COUNTERS ;WHEN THEY EXPIRE (FROM TIMA20) MOVB RESTAB(R0),CURTAB(R0) ;RESET FROM PERM TABLE INC R0 ;BUMP TO NEXT RESOLUTION... TSTB RESTAB(R0:D EXIT NOW BR QSKA35 ;IN THREAD: TAKE ERROR EXIT QSKA20: ;MODULE READY FOR INSERTION IN TABLE SUB #2,STBPTR ;PUSH TABLE POINTER MOV R0,@STBPTR ;LOAD NEW MODULE INTO TABLE QSKA30: CLR 6(SP) ;NOW READY TO EXIT. CLEAR ERROR FLAG QSKA35: DEC (R0) ;EITHER SETS T/W = -1 TO SHOW IN "WAIT" ;...OR RESTORES T/W TO ORIGINAL, IF NOT THREADED QSKA40: MOV (SP)+,R0 ;RESTORE; .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL4: .WORD 1 ;THREAD WORD .BYTE 34. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG3 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MODU<F ACTIVE OR "WAIT" BNE QTIM50 ;ACTIVE: TAKE ERROR EXIT CMPB 5(R0),#-1 ;IN "WAIT": IS IT FLAGGED FOR DE-QUEUE? BNE QTIM50 ;NO: ERROR EXIT BR QTIM40 ;YES: LEAVE THERE AND REMOVE D-Q FLAG .PAGE QTIM60: ;HERE WHEN TASK IS TO BE SUSPENDED UNTIL TIMER EXPIRES MOVB $CTASK,2(R0) ;LOAD MODULE TASK # WITH CURRENT TASK MOV 4(SP),10(SP) ;SET CALLER RTN TO LOOK LIKE "JSR" =) ;...AND SEE IF THIS IS THE END BNE TIMA20 ;NOT YET: MORE BR TIMA30 ;END OF COUNTERS: DO ALL THREADS TIMER: ;ENTRY FROM INTERRUPT: CPU LEVEL 7 .IFNZ $TMBAS ;OPTION ALLOWS RESOLUTION FINER THAN RES1 DECB BASCNT ;COUNT DOWN BASIC MULTIPLIER BEQ TIMA10 ;TURNED OVER: ENTER TIMER PROGRAM RTI ;NO NEED TO ENTER TIMA10: ;HERE WHE> USER'S RTI ;RESTORE USER'S PS & RETURN .PAGE DQSKED: ;SYSTEM SUBROUTINE TO DE-QUEUE A SCHEDULER MODULE MOV (SP),-(SP) ;RE-ORDER STACK FOR "RTI" RETURN AT END MOV PS,2(SP) ;STACK NOW READY FOR "RTI" JSR R5,PUSHR ;PUSH ALL REGS ONTO STACK MOV 20(SP),R0 ;MODULE'S ADDRESS MOV #340,PS ;LOCK OUT INTERFERENCE FROM SCHEDULER CMP #1,(R0) ;HAS?L5: .WORD 1 ;THREAD WORD .BYTE 35. ;TASK # .BYTE 3 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD ARG4 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL6: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD @ MOV #SUSPND,4(SP) ;SET STACK SO RTI WILL GO TO "SUSPEND" BR QTIM45 ;INSTEAD OF RETURNING TO CALLER .PAGE ; ******************************************************************** ; * * ; * PROGRAM IDENTIFICATION: "DQTIME" * ; * TIMER MODULE DE-QUEUEING SUBROUTINE * ; * AN BASIC RES'N TURNS OVER MOVB #$TMBAS,BASCNT ;RESET BASE PERIOD MULTIPLIER .ENDC $TMBAS INCB TIMBSY ;CHECK FOR PREVIOUS CALL STILL ACTIVE BNE TIMA00 ;YES: LEAVE INDICATOR SET TO SHOW ;PENDING REQUEST TO RUN; AND RETURN. SAVE ;NOT ACTIVE, SO SAFE TO ENTER. CALL TO ;SAVE ENVIRONMENT AND RETURN WITH: ;(R4) = (PS) B MODULE BEEN DE-QUEUED ALREADY? BEQ DQSK20 ;YES: INACTIVE,SO IGNORE CMP #-1,(R0) ;IS IT STILL IN "WAIT" TABLE? BEQ DQSK50 ;YES: GO SET THE "D" FLAG MOV #2,R5 ;INIT COUNTER TO SEARCH BOTH THREADS MOV #TH1BGN,R1 ;START BY SEARCHING THREAD #1 DQSK10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;COPY ADDRESS OF UPSTREAM MODULE MOV (R1),R1 ;GET DOWC 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL7: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAD * ; * PURPOSE: * ; * REMOVES TIMER MODULES FROM TIMER THREADS, IF ACTIVE * ; * AND IF FOUND IN ITS PROPER THREAD. IF ACTIVE BUT NOT * ; * FOUND, ERROR EXIT IS TAKEN. IF STILL IN "WAIT" STACK * ; * IT IS MARKED FOR REMOVAL WHEN "TMNSRT" IS RUN. * ; * IF MODULE IS ALREADY INACTIVE, NO ACTION TAKEN, AND * ; * GOOD EXIT IS TAKEN.EBEFORE CLOCK INTERRUPT ;(R5) = ADDRESS OF "RESTOR" ROUTINE .PAGE TMNSRT: ;TIMER INSERT ROUTINE: TRANSFERS TIMER MODULE ADDRESS ; FROM WAIT STACK TO APPROPRIATE QUEUE WHEN CONVENIENT FOR TIMER. ; CPU LEVEL SEVEN: AVOID INTERFERENCE WITH "QTIME". MOV @TTBPTR,R0 ;ADDRESS OF TIMER MODULE FROM TOP OF ;"WAIT" STACK BEQ TIMA15 ;STACK EMPTY SUB #2,TTBPTR FNSTREAM MODULE'S ADDRESS BEQ DQSK40 ;END OF THREAD CMP R0,R1 ;IS THIS THE MODULE WE ARE LOOKING FOR? BNE DQSK10 ;NO MOV (R1),(R2) ;YES: "BRIDGE" OVER THIS MODULE IN THREAD MOV #1,(R1) ;...AND SET T/W = 1 TO SHOW INACTIVE DQSK20: ;HERE UPON SUCCESSFUL DE-QUEUE CLR 20(SP) ;ERROR RETURN STATUS: O.K. DQSK30: ;HERE FOR GENERAL EXIT FROM ROUTINE JSR GG MASK .WORD 0 ;JSR TARGET MODUL8: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK # .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET MODUL9: .WORD 1 ;THREAD WORD .BYTE 2 ;TASK H * ; * * ; * USAGE: CALLED BY ANY ROUTINE WISHING TO DE-ACTIVATE A TIMER * ; * MODULE. CALLING SEQUENCE: * ; * * ; * MOV #MODULE,-(SP) ;STACK MODULE'S ADDRESS * ; * EMT DQTIME ;REQUEST TO DE-QUEUE MODULE * ; * I ;NOT EMPTY: POP STACK ONE CELL MOV #1,(R0) ;SET T/W INACTIVE IN CASE WAS DE-QUEUED CMPB 5(R0),#-1 ;IS "RESET" ALL ONES? BEQ TMNSRT ;YES: MODULE WAS "DE-QUEUED": IGNORE IT MOVB 3(R0),R1 ;GET OPTION BYTE BIC #177760,R1 ;ISOLATE RESOLUTION CMP R1,#$NRES-1 ;IS RESOLUTION IN RANGE? BGT TMNSRT ;NO: TOO LARGE ASL R1 ;USED AS WORD INDEX BELOW JR5,POPR ;POP REGS FROM STACK RTI ;RETURN SET ABOVE: RESTORE ORIGINAL CPU STATUS & RETURN DQSK40: ;HERE WHEN END OF THREAD REACHED MOV #TH2BGN,R1 ;SET UP FOR POSSIBLE SEARCH OF THREAD #2 DEC R5 ;LOOP COUNTER BNE DQSK10 ;STILL MUST DO THREAD #2 BR DQSK30 ;SEARCH FAIL: EXIT WITH NON-ZERO ERROR DQSK50: ;HERE WHEN MODULE STILL IN WAIT" TABLE. MUST SET THE ; "DK# .BYTE 0 ;OPTIONS .WORD 0 ;TIMER/RESET .WORD 0 ;ARG .WORD 0 ;FLAG ADDR .WORD 0 ;FLAG MASK .WORD 0 ;JSR TARGET .PAGE MASK1 = 123 MASK2 = 234 MASK3 = 345 JSRTNE: MOV #MODUL1,-(SP) MOV TMWRD0,-(SP) EMT QTIME TST (SP)+ RTS PC ARG1: '1 ARG2: '2 ARG3L OR * ; * JSR PC,DQTIME ;DIRECT CALL WITH PROPER LINK * ; * TST (SP)+ ;POP ERROR RETURN CODE * ; * * ; * NOTE THAT THE THREE ROUTINES: [TIMER], [QTIME], AND * ; * [DQTIME] ALLOW AN UNLIMITED NUMBER OF CALLS TO QUEUE * ; * OR DE-QUEUE THE SAME MODULE, REGARDLESS OF ITS STATUS * ; * AT M MOV R0,@TLAST(R1) ;PUT NEW MODULE'S ADDR @ END PROPER THD> MOV R0,TLAST(R1) ;...AND UPDATE THE "LAST" POINTER ITSELF CLR (R0) ;CLEAR MODULE'S T/W: END OF THREAD BR TMNSRT ;NOW GO BACK AND POP ANY MORE MODULES .PAGE TIMA15: ;RE-ENTER HERE FOR REPEATS (TIMBSY>/=1) MOV R4,PS ;RESTORE PROCESSOR LEVEL TO PREVIOUS CLR R0 ;INIT RESOLUTION INDEX TIMA2N" DE-QUEUE FLAG IN MODULE TO FORCE IGNORE WHEN ; "SKNSRT" RUNS. IF MODULE IS QUEUED AGAIN BEFORE ; "SKNSRT" RUNS, THIS "D" FLAG WILL BE CLEREAD, AND MODULE ; WILL BE LEFT IN THE "WAIT" TABLE. BIS #10000,2(R0) ;SET "D" FLAG IN MODULE OPTION BYTE BR DQSK20 ;TAKE GOOD EXIT COUNTR: .WORD 0 ;THIS IS THE ABORT/TIME-SLICE COUNTER!! ABMPLR .WORD 0 ;MULTIPLIER FOR ABORT AND TIME/SLICE CU: '3 ARG4: '4 ARG5: '5 FLAG1: .BYTE 0 FLAG2: .BYTE 0 FLAG3: .BYTE 0 .EVEN .END PANY GIVEN TIME. THE STATE UPON THE RETURN FROM A * ; * CALL TO [QTIME] OR [DQTIME], ASSUMING A ZERO ERROR CODE* ; * ASSURES THAT THE MODULE IS IN THE MOST RECENTLY * ; * REQUESTED STATE. THE ONLY EXCEPTION IS WHEN A CALL TO * ; * [DQTIME] HAS BEEN MADE AFTER THE REQUESTED MODULE HAS * ; * TIMED OUT AND BEGUN EXECUTION. STRICTLY SPEAKING, THE * ; * CALL IN THIS CASE CAME AFTER THE MODULE WAS RUN. * ; * Q0: ;RETURN HERE WHEN ADVANCING TO NEXT RESN DECB CURTAB(R0) ;COUNT DOWN A RESOLUTION COUNTER BEQ TIMA70 ;EXPIRED: GO RESET IT & BUMP RES'N INDEX TIMA30: ;FALL THROUGH HERE WHEN A RESOLUTION COUNTER IS FOUND ; THAT HAS NOT EXPIRED. SINCE THE RESOLUTIONS ARE COUNTED STARTING ; FROM THE FINEST TOWARDS THE COARSEST, THE RESOLUTION CURRENTLY IN R0 ; IS THE FINEST RESOLUTION THAT HAS NOT EXPIRED. BY DECREMENTING R0, ; THE COARRRTHD: .WORD THDTAB ;POINTER TO CURRENT THREAD BEGIN WORD THDTAB: .WORD TH1BGN ;THREAD BEGIN TABLE .WORD TH2BGN .WORD TH1BGN TH1BGN: .WORD 0 ;ACTUAL BEGIN OF THREAD #1 TH2BGN: .WORD 0 ;#2 STBPTR: .WORD SWAITB ;SCHEDULER "WAIT" TABLE POINTER SWAITB: .WORD 0 ;TOP OF "WAIT" STACK IS ALWAYS ZERO .=$SWATZ*2+. ;THE SCHEDULER "WAIT" TABLE SKTBND = .-2 ;END OF T * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** .DEF DQTIME .PAGE DQTIME: ;SYSTEM SUBROUTINE TO DE-QUEUE A TIMER MODULE MOV (SP),-(SP) ;MOVE RTN ADDR IN PREP FOR "RTI" AT END MOV PS,2(SP) ;PLACE [PS] ALSUSEST RESOLUTION TO EXPIRE IS FOUND. FALLS THROUGH HERE ALSO ; IF ALL RESOLUTIONS EXPIRE, WHICH WILL HAPPEN FROM TIME TO TIME. ASL R0 ;RESOLUTION*2: USE AS WORD INDEX TIMA35: ;LOOP BACK HERE FOR SUCCESSIVE RESOLUTIONS DEC R0 DEC R0 ;COUNT DOWN RESOLUTION INDEX (TWICE, ; SINCE IT WAS MADE INTO A WORD INDEX ABOVE). ON THE FIRST PASS AFTER ; FINDING THE FIRST RES'N NOT TO EXPIRE, THIS BRINGS COUNTER BACK TO ; (DOUBLE)V"WAIT" TABLE DAYTAB = .-1 ;THIS IS THE 12-BYTE TABLE OF DAYS-PER-MONTH JANARY = . FEBARY = .+1 .BYTE 31.,28.,31.,30.,31.,30.,31.,31.,30.,31.,30.,31. CLOCK: ;EXTERNAL REFERENCE FOR TIME-OF-DAY CLOCK AND CALENDAR TICTOC: .BYTE 0 ;COUNTS CLOCK BEATS PER SECOND SECOND: .BYTE 0 ;CURRENT TIME MINUTE: .BYTE 0 ;CURRENT TIME HOUR: .BYTE 0 ;CURRENT TIME JDATE: .WORD 0 ;CURRENT JULXO FOR "RTI" MOV #340,PS ;RAISE CPU LEVEL: PROTECT AGAINST "TIMER" JSR R5, PUSHR ;SAVE ALL REGISTERS MOV 20(SP),R0 ;GET MODULE'S ADDRESS CMP #1,(R0) ;IS MODULE ALREADY INACTIVE? BEQ DQTM20 ;YES: TAKE GOOD EXIT CMP #-1,(R0) ;IS MODULE STILL IN "WAIT" STACK? BEQ DQTM40 ;YES: GO SET "DE-QUEUE" FLAG MOVB 3(R0),R1 ;IS IN ACTIVE QUEUE: TAKE IT OUT Y THE COARSEST RES'N TO EXPIRE. ON SUCCESSIVE PASSES THIS ; MOVES TO NEXT FINER RES'N FOR SERVICING. BLT TIMEXT ;EXIT HERE WHEN ALL RESOLUTIONS HAVE ; BEEN SERVICED, OR IF NO LEVELS ACTUALLY EXPIRED. .PAGE TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE ADD R0,R1 ;...OF POINTER FOR CURRIAN DATE MONTH: .BYTE 0 ;CURRENT MONTH MDAY: .BYTE 0 ;CURRENT DAY OF MONTH YEAR: .BYTE 0 ;CURRENT YEAR (MINUS 1900) SKDBSY: .BYTE -1 ;SCHEDULER BUSY FLAG: IDLE=-1; .END \ BIC #177760,R1 ;GET MODULE'S RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R1,R3 ;SAVE RESOLUTION IN CASE NEEDED BELOW ADD #TFIRST,R1 ;ADDR OF RESOLUTION'S "FIRST" WORD DQTM10: ;LOOP RETURN POINT FOR THREAD SEARCH MOV R1,R2 ;SAVE UPSTREAM MODULE'S ADDR MOV (R1),R1 ;ADDR OF DOWNSTREAM MODULE BEQ DQTM30 ;END OF THREAD: SEARCH FAIL ERROR ]ENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV #340,PS ;AVOID INTERFERENCE WITH "DQTIME" TIMB16: ;LOOP RE-ENTRY POINT MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB T^B~HpÉ~ÀpQ~8qØ~°q` CMP R0,R1 ;IS THIS THE MODULE TO BE DE-QUEUED? BNE DQTM10 ;NO: KEEP LOOKING MOV (R1),(R2) ;FOUND IT! BRIDGE OVER THIS MODULE... BNE DQTM15 ;...AND EXIT IF NOT LAST MODULE MOV R2,TLAST(R3) ;...BUT UPDATE "LAST" ENTRY IF WAS @ END DQTM15: MOV #1,(R1) ;FINALLY, FLAG MODULE INACTIVE DQTM20: CLR 20(SP) ;CLEAR RETURN ERROR FLAG FOR GOOD EXIT DQTM30: JSR R5,POPR ;RESTORE SAVED aIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB16 ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS MODULE'S TIME. ; SINCE COMPLETION ROUTINES RUN UNDER THE "J" OPTION ASSUME R1 POINTS TO ; THE CURRENT MODULE (IT'S THREAD WORD), R1 MUST BE PRESERVED AS SUCH ; UNTIL THE POSSIBLE ROUTINE IS RUN. BUT TWO OTHER POINTERS ARE NEEDED: ; R3 MOVES DOWN THE MODULE TO COMPENSATE FOR OPTIONAL PARAMTERS WHICH ; MAKE THE LIST LONGER, AND R5 IS RESET Tb`~(rç~ ro~södREGISTERS... RTI ;...AND RETURN TO CALLER WITH HIS PS DQTM40: ;HERE IF MODULE IS STILL IN "WAIT" STACK MOVB #-1,5(R0) ;SET "RESET" BYTE TO ALL ONES TO SHOW ;"TMNSRT" TO IGNORE THIS MODULE BR DQTM20 ;GO TAKE GOOD EXIT .PAGE ; ******************************************************************** ; * PROGRAM IDENTIFICATION: "TIMER" * ; * eO POINT TO THE UPSTREAM MODULE ; IN CASE THE CURRENT MODULE IS A "ONE-SHOT" AND IS REMOVED FROM THE ; THREAD. R1 IS LOADED FROM R5 AT THE END OF THE LOOP TO ALLOW THIS. MOV R1,R3 ;INIT R3 AS DYNAMIC LIST POINTER MOV R1,R5 ;INIT R5 IN PREP FOR R1 RESET BELOW MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD .f~�s~~t~€t�~øth HIGH-RESOLUTION CLOCK PULSE SERVICE ROUTINE * ; * * ; * PURPOSE: --SERVICES ALL TIMER MODULES AT THEIR RESPECTIVE * ; * RESOLUTIONS, PROVIDING THE FEATURES OF TASK * ; * TIME-DELAY, PERIODIC OR ONE-SHOT QUEUEING, * ; * FLAG-SETTING,AND COMPLETION-ROUTINE CALLS. * ; * --KEEPS TRACK OF THE TASK-EXECUTION TIME (ABORT) * ; i.. BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACTIVE IN EITHER CASE MOV R2,R5 ;BACK POINTER TO UPSTREAM MODULE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOVB OPTION(R3),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R3) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NOj~puœ~èu$~`v«~Øvl * COUNTER, AND CALLS FOR TASK ABORT IF TIME * ; * RUNS OUT. * ; * --PROVIDES (OPTIONAL) TIME-SLICE FEATURE BY * ; * PERIODICALLY ROTATING THE TASKS IN A QUEUE. * ; * * ; * USAGE: ACTIVATED BY CLOCK INTERRUPT. ALL PROGRAMS HANDLE * ; * COMMUNICATION VIA "QTIME" AND "DQTIME". "TIMER" m: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSPEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP) ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL Tn3~Pwº~ÈwB~@xÉ~¸xp * ; * CALLS SYSTEM SUBROUTINES "QUEUE", "SAVE", "UNSPND", * ; * AND "ABORT". * ; * * ; * G U L F E L E C T R O N I C S Y S T E M S * ; * * ; ******************************************************************** ; FOLLOWING ARE OFFSET PARAMETERS FOR TIMER MODULqO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK # AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFNZ DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY rQ~0yØ~¨y`~ zç~˜ztE REFERENCES SAVE = 3 ;OP-CODE FOR TRAP TO "SAVE" SUBROUTINE TASKNO = 2 ;TASK NUMBER BYTE OPTION = 3 ;OPTION FLAGS BYTE TIMBYT = 4 ;MODULE TIMER BYTE RESET = 5 ;TIMER RESET BYTE TIMARG = 6 ;ARGUMENT (FOR QUEUEING) ADDRESS WORD TMFLAG = 6 ;FLAG ADDRESS WORD (DYNAMIC OFFSET) TIMASK = 8. ;FLAG MASK WORD (DYNAMIC OFFSET) JSTARG u .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R3),(SP);YES: REPLACE THE ZERO WITH ACTUAL ARG TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEUE TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ vo~{ö~ˆ{~~|x = 6 ;USER ROUTINE ADDRESS WORD (DYN OFFSET) .PAGE TIMA00: RTI ;RETURN USED IF CLOCK IS RE-ENTERED ;TO PROCESS QUEUE WHILE PREVIOUS REQUEST IN PROGRESS. TIMA70: ;HERE TO RESET RESOLUTION COUNTERS ;WHEN THEY EXPIRE (FROM TIMA20) MOVB RESTAB(R0),CURTAB(R0) ;RESET FROM PERM TABLE INC R0 ;BUMP TO NEXT RESOLUTION... TSTB RESTAB(R0y ;POP ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED ASLB R2 ;MOVE "ARG" OPTION INTO SIGN BIT BPL TIMB56 ;"A" NOT SET TST (R3)+ ;PASS POINTER OVER ARG, WHETHER USED OR NOT TIMB56: ASLB R2 ;GET "FLAG" OPTION BIT INTO SIGN BPL TIMB60 ;NO FLAG OPTION BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULz~x|�~ð|~h}œ~à}|) ;...AND SEE IF THIS IS THE END BNE TIMA20 ;NOT YET: MORE BR TIMA30 ;END OF COUNTERS: DO ALL THREADS TIMER: ;ENTRY FROM INTERRUPT: CPU LEVEL 7 .IFNZ $TMBAS ;OPTION ALLOWS RESOLUTION FINER THAN RES1 DECB BASCNT ;COUNT DOWN BASIC MULTIPLIER BEQ TIMA10 ;TURNED OVER: ENTER TIMER PROGRAM RTI ;NO NEED TO ENTER TIMA10: ;HERE WHE}E POINTER FOR FLAGS TIMB60: ASLB R2 ;GET "J" OPTION BIT INTO SIGN BPL TIMB70 ;NOT SELECTED JSR PC,@JSTARG(R3) ;LINK TO USER RTNE. (R1)= MODULE BEGIN TIMB70: MOV R5,R1 ;RESET MODULE POINTER (SEE EXPLN. ABOVE) BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #TFIRST,R0 ;PREPARE TO SCAN LIST OF "FIRST" WORDS MOV #$NRES,R1 ~$~X~«~Ð~  €4¿×{w¨ÂƦ)ÅÅew~HL Îxÿ ‡ ¡N N Í ÃŠüÍ ÷ <ÂåÂ%!÷ ,„cÍ À‹ëéÑ�øÃh‹ŠË‹þ€ÃœÀ`ÃEÿ ‡·$Í ÄÍ ÃÄPÇ÷ êÿ-FÀÍ À‹â„ †¿Ä LÀ÷ê÷õwZÿÁÂê‰ É‹þ€rœ· îÿõpÿ’€N BASIC RES'N TURNS OVER MOVB #$TMBAS,BASCNT ;RESET BASE PERIOD MULTIPLIER .ENDC $TMBAS INCB TIMBSY ;CHECK FOR PREVIOUS CALL STILL ACTIVE BNE TIMA00 ;YES: LEAVE INDICATOR SET TO SHOW ;PENDING REQUEST TO RUN; AND RETURN. SAVE ;NOT ACTIVE, SO SAFE TO ENTER. CALL TO ;SAVE ENVIRONMENT AND RETURN WITH: ;(R4) = (PS) � ;LIST SIZE MOV #340,PS ;LOCK OUT PULSE DURING EXIT SEQUENCE TIMEX1: TST (R0)+ ;IF ANY IS NON-ZERO... BNE TIMEX2 ;...DON'T TURN OFF CLOCK DEC R1 ;BE SURE TO DO WHOLE LIST BNE TIMEX1 TST @TTBPTR ;CHECK FOR EMPTY "WAIT" LIST BNE TIMEX2 ;NOT EMPTY: LEAVE CLOCK ON BIC #C1CBIT,C1COMD ;NO MODULES ACTIVE: KILL INTERRUPT TIMEX2: DECB TIMBSY ø„BEFORE CLOCK INTERRUPT ;(R5) = ADDRESS OF "RESTOR" ROUTINE .PAGE TMNSRT: ;TIMER INSERT ROUTINE: TRANSFERS TIMER MODULE ADDRESS ; FROM WAIT STACK TO APPROPRIATE QUEUE WHEN CONVENIENT FOR TIMER. ; CPU LEVEL SEVEN: AVOID INTERFERENCE WITH "QTIME". MOV @TTBPTR,R0 ;ADDRESS OF TIMER MODULE FROM TOP OF ;"WAIT" STACK BEQ TIMA15 ;STACK EMPTY SUB #2,TTBPTR … ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRUˆ ;NOT EMPTY: POP STACK ONE CELL MOV #1,(R0) ;SET T/W INACTIVE IN CASE WAS DE-QUEUED CMPB 5(R0),#-1 ;IS "RESET" ALL ONES? BEQ TMNSRT ;YES: MODULE WAS "DE-QUEUED": IGNORE IT MOVB 3(R0),R1 ;GET OPTION BYTE BIC #177760,R1 ;ISOLATE RESOLUTION ASL R1 ;USED AS WORD INDEX BELOW MOV R0,@TLAST(R1) ;PUT NEW MODULE'S ADDR @ END PROPER THD> MOV R0,TLAST(R1) ‰PTED PROGRAM .PAGE TTBPTR: .WORD TWAITB ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST: ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY. Œ ;...AND UPDATE THE "LAST" POINTER ITSELF CLR (R0) ;CLEAR MODULE'S T/W: END OF THREAD BR TMNSRT ;NOW GO BACK AND POP ANY MORE MODULES .PAGE TIMA15: ;RE-ENTER HERE FOR REPEATS (TIMBSY>/=1) MOV R4,PS ;RESTORE PROCESSOR LEVEL TO PREVIOUS CLR R0 ;INIT RESOLUTION INDEX TIMA20: ;RETURN HERE WHEN ADVANCING TO NEXT RESN DECB CURTAB(R0) ;COUN� .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TFIRST ;ACTUAL TABLE SIZE = [$NRES] WORDS TLAST: ;TABLE OF POINTERS TO LAST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREAD ;IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TLAST ;ACTUAL TABLE SIZE = [$NRES] WORDS �T DOWN A RESOLUTION COUNTER BEQ TIMA70 ;EXPIRED: GO RESET IT & BUMP RES'N INDEX TIMA30: ;FALL THROUGH HERE WHEN A RESOLUTION COUNTER IS FOUND ; THAT HAS NOT EXPIRED. SINCE THE RESOLUTIONS ARE COUNTED STARTING ; FROM THE FINEST TOWARDS THE COARSEST, THE RESOLUTION CURRENTLY IN R0 ; IS THE FINEST RESOLUTION THAT HAS NOT EXPIRED. BY DECREMENTING R0, ; THE COARSEST RESOLUTION TO EXPIRE IS FOUND. FALLS THROUGH HERE ALSO ; IF ALL RESOLUTIONS EXPIRE, WHICH WILL HA‘ .PAGE RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=RESTAB+$NRES ;SET TO ACTUAL TABLE SIZE .BYTE 0 ;END BYTE CURTAB: .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=CURTAB+$NRES ;SET TO ACTUAL TABLE SIZE TIMBSY:”PPEN FROM TIME TO TIME. ASL R0 ;RESOLUTION*2: USE AS WORD INDEX TIMA35: ;LOOP BACK HERE FOR SUCCESSIVE RESOLUTIONS DEC R0 DEC R0 ;COUNT DOWN RESOLUTION INDEX (TWICE, ; SINCE IT WAS MADE INTO A WORD INDEX ABOVE). ON THE FIRST PASS AFTER ; FINDING THE FIRST RES'N NOT TO EXPIRE, THIS BRINGS COUNTER BACK TO ; (DOUBLE) THE COARSEST RES'N TO EXPIRE. ON SUCCESSIVE PASSES THIS ; MOVES TO NEXT FINER RES'N FOR SERVICING. .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END ˜ BLT TIMEXT ;EXIT HERE WHEN ALL RESOLUTIONS HAVE ; BEEN SERVICED, OR IF NO LEVELS ACTUALLY EXPIRED. .PAGE TIMB10: ;NOW WE BEGIN TRAVELING THE THREADS ;ALSO LOOP RE-ENTRY POINT FOR EACH RESOLUTION MOV #TFIRST,R1 ;CALC ADDRESS IN THE QUEUE POINTER TABLE ADD R0,R1 ;...OF POINTER FOR CURRENT RESOLUTION TIMB15: ;LOOP HERE FOR EACH SUCCESSIVE MODULE MOV #œ340,PS ;AVOID INTERFERENCE WITH "DQTIME" MOV R1,R2 ;REMEMBER UPSTREAM MODULE ADDRESS... ;...FOR USE IN DE-QUEUEING "ONE-SHOTS" MOV (R1),R1 ;NEXT MODULE'S THREAD WORD ADDRESS BEQ TIMA35 ;END OF THREAD: GO DOWN TO NEXT RES'N DECB TIMBYT(R1) ;COUNT DOWN MODULE'S TIMER BNE TIMB15 ;NOT EXPIRED: GET NEXT MODULE ;TIMER EXPIRED! IT IS  MODULE'S TIME. MOVB RESET(R1),TIMBYT(R1) ;RESET TIMER BYTE BNE TIMB20 ;MODULE IS A REPEATER: LEAVE IN THREAD MOV (R1),(R2) ;"ONE-SHOT": REMOVE FROM THREAD ... BNE TIMB22 ;...BY "BRIDGING". BRANCH IF NOT LAST MOV R2,TLAST(R0) ;BUT UPDATE "LAST" POINTER IF WAS END TIMB22: MOV #1,(R1) ;SET THREAD WORD INACTIVE IN EITHER CASE TIMB20: MOV R4,PS ;UNLOCK INTERRUPTS: SAFE NOW MOV¤ R1,R3 ;COPY MODULE ADDRESS TO PRESERVE R1... ;...IN CASE OF "J" OPTION MOVB OPTION(R1),R2 ;GET OPTION BYTE FOR THIS MODULE TSTB TASKNO(R1) ;IS MODULE TASK-RELATED? BEQ TIMB54 ;NO: CHECK FOR OTHER OPTIONS ;YES: SET UP STACK FOR CALL TO EITHER ;[SUSPEND] OR [QUEUE] MOVB TASKNO(R3),-(SP);PUSH TASK # FIRST CLR -(SP) ¨ ;IMMEDIATE RETURN REQUEST FOR BOTH, OR ;INIT OF PRIORITY IF NEEDED FOR [QUEUE]. TSTB R2 ;IS "SUSPEND" OPTION SELECTED? BPL TIMB30 ;NO: GO DO QUEUEING JSR PC,UNSPND ;CALL TO "UN-SUSPEND" BR TIMB50 ;GO POP ERROR WORD & CHECK FLAG OPTION TIMB30: ;HERE TO QUEUE A TASK. TASK # AND RETURN CODE ;(OR INITED PRIORITY) ALREADY PUSHED ONTO STACK. .IFN¬Z DPRTY ;DYNAMIC PRIORITIES OPTION CLR -(SP) ;USE SYSTEM-ASSIGNED PRIORITY ; (ACTUALLY LEAVES ZERO AS PRIORITY AND PUSHES NEW RETURN CODE OF ZERO, ; POSSIBLY INITING STACK SPACE FOR PASSED ARGUMENT, IF OPTION IS ON.) .ENDC DPRTY .IFNZ ARG ;SYSTEM OPTION TO PASS ARGUMENT ON QUEUE BIT #100,R2 ;DOES MODULE HAVE AN ARGUMENT TO PASS? BEQ TIMB40 ;NO MOV @TIMARG(R4),(SP);YES: REPLACE° THE ZERO WITH ACTUAL ARG.. TST (R3)+ ;...AND BUMP SECONDARY MODULE POINTER ;SO THAT REFERENCES BELOW WILL ALLOW FOR ;THE EXTRA MODULE WORD THAT "ARG" USED. TIMB40: CLR -(SP) ;MUST PUSH RETURN CODE SINCE ARGUMENT .ENDC ARG ;USED UP LAST ONE. JSR PC,QUEUE ;CALL QUEUE TIMB50: ;HERE AFTER [QUEUE] OR [UNSPND] TST (SP)+ ;POP ´ERROR RETURN CODE TIMB54: ;HERE WHEN NOT TASK-RELATED BIT #40,R2 ;TEST "FLAG" OPTION BEQ TIMB60 ;NOT SELECTED BISB TIMASK(R3),@TMFLAG(R3) ;"IOR" MASK INTO FLAG LOCATION CMP (R3)+,(R3)+ ;BUMP SECONDARY MODULE POINTER FOR FLAGS TIMB60: BIT #20,R2 ;IS "JSR" OPTION SELECTED? BEQ TIMB15 ;NO: SKIP "J" LINK AND LOOP FOR MORE JSR PC,JSTARG(R3) ;LINK TO ¸USER RTNE. (R1)=MODULE BEGIN BR TIMB15 ;LOOP BACK FOR MORE MODULES TIMEXT: ;EXIT POINT FOR [TIMER] MOV #TFIRST,R0 ;PREPARE TO SCAN LIST OF "FIRST" WORDS MOV #$NRES,R1 ;LIST SIZE TIMEX1: TST (R0)+ ;IF ANY IS NON-ZERO... BNE TIMEX2 ;...DON'T TURN OFF CLOCK DEC R1 ;BE SURE TO DO WHOLE LIST BNE TIMEX1 BIC #C1CBIT,C1COMD ;NO MODULES¼ ACTIVE: KILL INTERRUPT TIMEX2: MOV #340,PS ;PROTECT AGAINST THIS INTERRUPT DURING ;EXIT SEQUENCE DECB TIMBSY ;NESTING "BUSY" COUNTER BGE TIMA15 ;NORMALLY RESIDES @ ZERO DURING ROUTINE ;EXECUTION. GOES ABOVE IF ADDITIONAL ;OCCASIONS TO ENTER ROUTINE HAVE ;OCCURRED DURING EXECUTION. IN THIS À ;CASE ROUTINE IS RE-EXECUTED IMMEDIATELY ;IN AN ATTEMPT TO RE-SYNCHRONIZE JMP RESTOR ;NORMAL RETURN TO INTERRUPTED PROGRAM .PAGE TTBPTR: .WORD TWAITB ;TIMER TABLE POINTER TO "WAIT" STACK TWAITB: .WORD 0 ;FIRST LOC'N OF "WAIT" TABLE IS ALWAYS 0 .=$TWATZ*2+. ;RESERVE SPACE FOR TABLE TMTBND = .-2 ;ADDRESS OF LAST TALBE LOCATION TFIRST: Ä ;TABLE OF POINTERS TO FIRST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN ZERO ;WHEN THREAD IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TFIRST ;ACTUAL TABLE SIZE = [$NRES] WORDS TLAST: ;TABLE OF POINTERS TO LAST MODULE IN ;EACH RESOLUTION'S THREAD. CONTAIN THE ;ADDRESS OF [TFIRST(R)] WHEN THREÈAD ;IS EMPTY. .WORD ,,,,,,,,,,,,,,, ;MAX TABLE SIZE: 16 WORDS .=$NRES*2+TLAST ;ACTUAL TABLE SIZE = [$NRES] WORDS .PAGE RESTAB: ;RESOLUTION COUNTER TABLE: PERMANENT .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=RESTAB+$NRES ;SET TO ACTUAL TABLE SIZE .BYTE 0 ;END BYTE CURTAB: .BYTE RES0,RES1,RES2,RES3,RES4,RES5,RES6,RES7,RES8 .BYTE RES9,RES10,RES11,RES12,RES13,RES14,RES15 .=CURTAB+$NRES ;SET TO ACTUAL TABLE SIZE TIMBSY: .BYTE 0 ;FLAG & NESTING COUNTER FOR [TIMER] BASCNT: .BYTE 0 ;OPTIONAL SUB-RESOLUTION PULSE COUNTER .END