File RTS8.PA (PAL assembler source file)

Directory of image this file is from
This file as a plain text file

/4 RTS-8  SMALL REAL TIME SYSTEM V2B
	XLIST	1	/COPYRIGHT ALSO IS IN PARAM.PA
/
/
/
/
/
/
/
/
/
/COPYRIGHT  (C)  1974,1975,1976 BY DIGITAL EQUIPMENT CORPORATION
/
/
/
/
/
/
/
/
/
/
/THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT NOTICE
/AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
/CORPORATION.  DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY
/FOR ANY ERRORS THAT MAY APPEAR IN THIS DOCUMENT.
/
/THE SOFTWARE DESCRIBED IN THIS DOCUMENT IS FURNISHED TO THE PURCHASER
/UNDER A LICENSE FOR USE ON A SINGLE COMPUTER SYSTEM AND CAN BE COPIED
/(WITH INCLUSION OF DIGITAL'S COPYRIGHT NOTICE) ONLY FOR USE IN SUCH
/SYSTEM, EXCEPT AS MAY OTHERWISE BE PROVIDED IN WRITING BY DIGITAL.
/
/DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR THE USE
/OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY
/DIGITAL.
/
/
/
/
/
/
/
/
/
/
	XLIST	0	/LIST EXEC
/EDIT HISTORY:
/RICHARD LARY		LAST EDITED AUG 18, 1974
/SHAWN SPILLMAN EDITED THIS ON 14-SEP-74.
/STANLEY RABINOWITZ EDITED THIS ON 5-APR-75
/	ADDED PDP-12 SUPPORT
/	FIXED ANGLE BRACKET BUG OF SHWANS
/RICHARD LARY EDITED THIS ON 20-NOV-75
/	ADDED KL8A SUPPORT AND RESCHED FUNCTION
/RICHARD LARY EDITED THIS ON 28-DEC-75
/	ADDED FREE-PARTITION OPTION TO WAITM, FIXING BUG
/	FIXED NON-RESIDENT TASK BUG IN FREEJ AND STOPJ
/STANLEY RABINOWITZ EDITED THIS DURING SEP, OCT 1976 (V2B)
/	REMOVED KL8A SUPPORT (NOW IN KL8ASR.PA)
/	ADDED HELPER STUFF FOR KL8A INTERRUPT SKIP CHAIN
/	ADDED WAITX ER
/	ALLOWED RECEIVE TO FALL THROUGH IF NO MSG AND AC NEGATIVE
/	ZERO CERTAIN DECNET TABLES
/	FIXED RACE CONDITION IN SCHEDULER

/BASED ON      T-O-Y    JUNE 5, 1973

/IOT'S FOR OPTIONAL HARDWARE:

	*200

	IFNDEF PDP12	<PDP12=0>	/IF NOT SURE, YOU'RE NOT A PDP-12
	IFZERO PDP8E <
		IFZERO PDP12	<CAFHLT=HLT>	/HALT TO LET USER CLEAR FLAGS
		IFNZRO PDP12	<CAFHLT=JMS IOPRST>  /ISSUE I/O PRESET ON PDP-12
	>
	IFNZRO	PDP8E	<CAFHLT=CAF>	/MACHINE WILL CLEAR FLAGS

SINT=	6254		/SKIP ON USER INTERRUPT
SUF=	6274		/SET USER MODE FLAG
SPL=	6102		/SKIP ON POWER LOW
LINC=	6141		/ENTER LINC MODE
PDP=	2		/ENTER PDP-8/I MODE
ESF=	4		/ENABLE SPECIAL FUNCTIONS

/PAGE 0 OF FIELD 0 *0 /INTERRUPT "VECTOR" 0 /SET TO JMP I 3 ON POWER FAILURE JMP I .+1 INTRPT IFNZRO PWRFAL < PFLADR, PFLRTN /CHANGED BY POWER FAIL TASK > *17 XR, 0 /INDEX REGISTER USED BY EXEC LOC20, 0 /MONITOR CALL LOCATION ** MUST BE AT 20 ** DCDF, CDF 0 CALIOF, IOF JMP I CALEXC DSPOST /** MUST BE AT LOC 24 ** XWAITM /** MUST BE AT LOC 25 ** CALEXC, EXEC /** MUST BE 400 ** ACARG, 0 /HOLDS AC ARG ON EXEC CALLS MPTR, ION /POINTS TO FIRST WORD OF MESSAGE Q POINTER MPT2, JMP I ACARG /" " SECOND " " TASKX, 0 /CURRENT TASK NUMBER INTT, 0 /INTERRUPT-LEVEL TEMPORARY SVSFLG, -1 /SAVE STATE FLAG - /-1 MEANS CPU STATE COUNTS & SHOULD BE SAVED, /0 MEANS CPU STATE IS UNIMPORTANT. TSWFLG, 1 /TASK SWITCHING INHIBITED FLAG - / 1 = TASK SWITCHING ALLOWED / 0 = TASK SWITCHING INHIBITED /-1 = TASK SWITCHING INHIBITED, RESCAN ASAP TODL, 0 /TIME-OF-DAY LOW ORDER TODH, 0 /TIME-OF-DAY HIGH ORDER DATE, TSTCLK /DATE WORD - USED TO INIT CLOCK HANDLER MCREF, 0 /MCR STARTUP EVENT FLAG T, 0 /NON-INTERRUPT LEVEL TEMPORARY IFDEF SWAPPER < COMMAND, ACARG /SWAPPER OVERWRITES WITH INITIAL ENTRY /HOLDS FREE-PARTITION FLAG IN SIGN BIT SWPENT, WIPCAL /SWAPPER OVERWRITES WITH FREEPAR ENTRY > *45 IFNZRO KL8A < KL8LOC, MSABAD /POINTS TO FIRST FREE LOC FOR KL8A IN SKIP CHAIN > ZBLOCK 50-. /RESERVED FOR FUTURE EXPANSION
/SET UP EXEC LINKAGE IN FIELDS 1-7 IFZERO HGHFLD-10&4000 < FIELD 1 *21 CDF 10 CIF 0 JMP CALIOF DSPOST XWAITM > IFZERO HGHFLD-20&4000 < FIELD 2 *21 CDF 20 CIF 0 JMP CALIOF DSPOST XWAITM > IFZERO HGHFLD-30&4000 < FIELD 3 *21 CDF 30 CIF 0 JMP CALIOF DSPOST XWAITM > IFZERO HGHFLD-40&4000 < FIELD 4 *21 CDF 40 CIF 0 JMP CALIOF DSPOST XWAITM >
IFZERO HGHFLD-50&4000 < FIELD 5 *21 CDF 50 CIF 0 JMP CALIOF DSPOST XWAITM > IFZERO HGHFLD-60&4000 < FIELD 6 *21 CDF 60 CIF 0 JMP CALIOF DSPOST XWAITM > IFZERO HGHFLD-70&4000 < FIELD 7 *21 CDF 70 CIF 0 JMP CALIOF DSPOST XWAITM > FIELD 0
/INTERRUPT ROUTINE *200 TS8LOC, CAFHLT /SO WE CAN START AT 200 IFNZRO TS8LOC-200 <SYSERR,_ERROR_> /OS8SUP NEEDS THIS HERE IFDEF SWAPPER < NEWTSK, JMS I COMMAND /DO SWAPPER INITIALIZATION > /(SEE SWAP TASK FOR DETAILS) IFNDEF SWAPPER < NEWTSK, ION > INTFGS, JMP I .+1 /GO AND FIND THE FIRST INTAC, FINDJ /TASK TO RUN INTRPT, IFDEF OS8 < SINT /MUST BE FIRST SKIP IN INTERRUPT CHAIN! SKP JMP I TS8LOC > DCA INTAC /SAVE AC IFNZRO PDP8E <GTF> IFZERO PDP8E < RAR /COMBINE LINK, IF AND DF INTO ONE WORD RIB > DCA INTFGS USERSK, /VERY HIGH PRIORITY USER FLAG TESTS GO HERE IFNZRO KL8A <MSABAD, NOP > /KL8A INTERRUPT DISPATCHER IFZERO KL8A-2 <NOP> /NOP IS FASTER THAN '0' IFZERO KL8A-3 <NOP;NOP> IFNZRO PWRFAL <SPL> /SKIP ON POWER LOW JMP TSTCLK /NO MORE H.P. SKIPS - GO TO SKIP CHAIN IFNZRO PWRFAL < TAD 0 DCA INTT /SAVE LOCATION ZERO TAD (JMP I PFLADR DCA 0 /SET UP 0 FOR RESTART HLT /DON'T TRY ANYTHING FANCY PWFLEF, 0 /POWER FAILURE EVENT FLAG PFLRTN, TAD INTT /** MUST BE AT PWFLEF+1 ** DCA 0 /RESTORE LOCATION OF POWER LOW INTERRUPT TAD (PWFLEF /POST THE POWER-FAIL INTERRUPT POSTDS /TO EXECUTE THE POWER-FAIL TASK (IF ANY) > BSKCHN, DISMIS /BEGINNING OF SKIP CHAIN LIST TSTCLK, CDF CIF 0 /ADDRESS FOLLOWED BY CDF CIF FIELD NOP /SET TO CLSK BY CLOCK ROUTINE JMP I BSKCHN DCDIF0, CDF CIF 0 /CLOCK HANDLER ALWAYS IN FLD 0 JMP I .+1 DISMIS /CHANGED BY CLOCK HANDLER (IF ANY)
/SUBROUTINE TO POST AN EVENT FLAG AND DISMISS FROM INTERRUPTS /ENTER WITH IOF, DF=D.F. OF EVENT FLAG, AC=ADDRESS OF EVENT FLAG DSPOST, SNA JMP DISMIS /NO EVENT FLAG - JUST DISMISS DCA INTT AC4000 TAD I INTT /LINK=1 IF EVENT FLAG.LT.0, 0 IF.GT.0 DCA NEWTSK /SAVE OLD VALUE OF EVENT FLAG DCA I INTT /ZERO EVENT FLAG TO INDICATE EVENT COMPLETION TAD NEWTSK SPA /** LINK MUST BE 0 HERE IF AC IS NEGATIVE ** JMP .+3 /IF E.F. .LT. 0, TASK WAS WAITING FOR EVENT JMS I (FREEJ /SO CLEAR "EVENT WAIT" BIT IN FLAG WORD. EFWT!EORMWT /IF THE TASK WHICH WAS WAITING ON THIS SNL CLA /EVENT FLAG IS HIGHER PRIORITY THAN THE TASK JMP DISMIS /CURRENTLY RUNNING, SUSPEND THE CURRENT TASK TAD 0 /UNLESS WE ARE IN A NON-INTERRUPTABLE ZONE IFDEF OS8 <RIB> /(NAMELY LOCS 0-77 OF A FIELD AND (7700 /NOT USED BY OS/8 BACKGROUND) SZA CLA /OR TASK SWITCHING HAS BEEN SPECIFICALLY TAD TSWFLG /INHIBITED BY THE SOFTWARE SMA SZA CLA /(BY MAKING TSWFLG LE 0) JMP STOPJ STA /IF TASK SWITCHING IS INHIBITED, DCA TSWFLG /SET FLAG TO INSURE A RESCAN OF THE TASK LIST JMP DISMIS /WHEN WE UNINHIBIT IT, THEN DISMISS NORMALLY. STOPJ, ISZ SVSFLG /IS THE STATE OF THE CURRENT TASK WORTH SAVING? JMP NOSVST /NO - FORGET IT. TAD TASKX CLL RTL TAD (TSTABL-1 DCA XR /SAVE THE CURRENT TASK'S STATE TAD INTFGS DCA I XR TAD 0 DCA I XR TAD INTAC DCA I XR IFNZRO EAE < MQA DCA I XR /SAVE THE MQ >
NOSVST, TAD NEWTSK /SET THE CURRENT PRIORITY TO THAT OF THE DCA TASKX /HIGHER PRIORITY TASK AND ATTEMPT TO START IT. ION /ENABLE INTERRUPTS WITH THE "DON'T SAVE STATE" /FLAG ON TO ALLOW FURTHER RESCHEDULING IFDEF SWAPPER < / TAD NEWTSK /FORM A POINTER TO THE TASK FLAGS WORD / TAD (TFTABL /OF THE NEW TASK / DCA INTT /AND STORE IT IN INTT /(ACTUALLY "FREEJ" DID IT FOR US) /**NOTE** IF YOU ENABLE THE PRECEDING 3 LINES, DON'T USE INTT! TAD I INTT /GET TASK FLAGS WORD /(INTERRUPTS COME ON N O W !) SZA CLA /IF ITS 0 (RUNNABLE) THEN RUN IT JMP I (FINDJ /IF ITS 4000 THEN GO SCHEDULE SWAPPER > /THIS MEANS THAT IF ANYBODY WITH HIGHER PRIORITY THAN "NEWTSK" /GETS AN EVENT-FLAG-SETTING INTERRUPT NOW, WE'LL JUST DASH OFF /AND START HIM INSTEAD. /CODE TO START UP A TASK /ENTER WITH TASK# IN "TASK", DF=0, ION, NO STATE (SVSFLG=0) STARTJ, IFZERO HGHFLD <ION> /INTERRUPTS ALREADY ON IF CIF WORKS TAD TASKX CLL RTL TAD (TSTABL-1 /FORM POINTER INTO TASK STATE TABLE DCA XR STA IOF /OK, THINGS ARE GETTING SENSITIVE - TURN INTS OFF DCA SVSFLG /AND RESET SAVE-STATE FLAG TO "YES" TAD I XR DCA INTFGS TAD I XR DCA 0 /SIMULATE AN INTERRUPT FROM THE TASK TAD I XR DCA INTAC /AND DISMISS IT IFNZRO EAE < TAD I XR MQL /RESTORE MQ > /*** CAUSES ERRORS IF MACHINE HAS NO EAE /** NOW FALL INTO "DISMIS" ON NEXT PAGE **
/INTERRUPT DISMISS ROUTINE - ALSO USED TO START TASKS DISMIS, IFNZRO PDP8E < SRQ /ANY OTHER INTERRUPTS PENDING? SKP /NO JMP USERSK /YES - SKIP PREAMBLE STUFF FOR EXTRA SPEED > TAD INTFGS IFNZRO PDP8E < IFNZRO HGHFLD <RTF> IFZERO HGHFLD <RAL> /RTF DOESN'T WORK RIGHT ON 4K 8E'S CLA > IFZERO PDP8E < IFDEF OS8 < TAD (700 /PROPAGATE USER-MODE BIT FROM BIT 5 TO BIT 2 > CLL RTL RAL /USER-MODE BIT NOW IN LINK AND (70 /FAKE AN RTF IF NOT ON A PDP8E TAD DCDF DCA DISCDF IFDEF OS8 < SZL /IF USER MODE WAS ON WHEN WE INTERRUPTED, SUF /TURN IT ON WHEN WE DISMISS > AC4000 TAD INTFGS AND (70 /NOTE THAT THE LINK IS NOW RESTORED TAD DCDIF0 DCA DISCIF DISCIF, 0 DISCDF, 0 > TAD INTAC IFZERO -PDP8E&HGHFLD <ION> /FOR PRE 8E OR 4K 8E MACHINES JMP I 0 IFNZRO PDP12 < IOPRST, 0 TAD (20 / I/O PRESET BIT IN SPECIAL FUNCTIONS REGISTER LINC /ENTER LINC MODE ESF /ENABLE SPECIAL FUNCTION PDP /BACK TO 8-MODE CLA JMP I IOPRST > PAGE
/RTS-8 EXECUTIVE - PROCESSES USER REQUESTS /CALLED BY: JMS 20 /IN ANY FIELD / ARGS / /CODE AT LOC 20 TURNS IOF, DOES CDF CUR AND CIF 0 AND JUMPS HERE EXEC, DCA ACARG /SAVE POSSIBLE AC ARGUMENT TAD TSWFLG /TSWFLG=1 HERE UNLESS WE WERE INTERRUPTED SMA CLA /WHEN WE WERE IN THE PAGE 0 CODE, IN WHICH CASE DCA TSWFLG /ITS -1 - ZERO IT IF IT WAS 1 ION /IT IS NOW OK TO TURN INTERRUPTS BACK ON RDF TAD ECDIF0 DCA EXRET /SAVE RETURN FIELD TAD I (LOC20 /GET LOC 20 OF THE CALLING FIELD DCA LOC20 /SAVE IT IN FIELD 0 IFDEF SWAPPER < TAD I LOC20 /SAVE A COPY OF THE COMMAND FOR LATER DCA COMMAND /IN CASE HE WANTS TO "FREE" > AC3777 AND I LOC20 /GET COMMAND MINUS WAIT BIT ISZ LOC20 TAD CMDJMP DCA .+1 /TURN COMMAND INTO DISPATCH JUMP HLT CMDJMP, JMP I .+1 XSEND /SEND MESSAGE TO A TASK XRECEIV /GET A MESSAGE FROM THE MESSAGE QUEUE XWAITE /WAIT FOR AN EVENT FLAG TO BE POSTED XRUN /RUN A TASK (IF NOT BEING RUN) XSUSPND /SUSPEND EXECUTION OF A TASK XPOST /POST AN EVENT FLAG XSKPINS /INSERT SKIP INTO INTERRUPT CHAIN XDERAL /DERAIL A TASK XBLKARG /BLOCK TASK FOR REASON SPECIFIED BY ARG XSENDW /SEND MESSAGE AND WAIT FOR COMPLETION XUNBARG /UNBLOCK TASK FOR REASON SPECIFIED BY ARG XTSTOP /FORCE A RESCHEDULE XWAITX /WAIT FOR EXACTLY THIS EVENT FLAG
/ROUTINE TO DERAIL A TASK'S EXECUTION INTO A SUBROUTINE XDERAL, TAD I LOC20 ISZ LOC20 DCA T /SAVE ADDR OF DERAIL SUBR TAD ACARG CLL RTL TAD (TSTABL /GET POINTER INTO TASK STATE TABLE DCA MPTR CDF 0 TAD I MPTR AND (70 /GET INSTRUCTION FIELD TAD DCDF DCA DRLCDF ISZ MPTR TAD I MPTR /GET CURRENT TASK PC DRLCDF, HLT /CDF TO TASK FIELD DCA I T /STORE PC IN SUBR HEADER CDF 0 TAD T IAC DCA I MPTR /SET PC TO SUBR HEADER + 1 JMP EXRET /RETURN TO CALLING TASK /SUBROUTINE TO WAIT FOR MULTIPLE EVENTS /CALLED VIA JMS I 25 WITH INTERRUPTS OFF. /THIS ROUTINE SHOULD BE CALLED AFTER SCANNING THE MULTIPLE EVENT FLAGS /(WITH INTERRUPTS OFF) TO AVOID TURNING INTERRUPTS ON BEFORE THE /WAIT MASK IS PLACED IN TFTABL. THE "BLKARG" CALL TO THE RTS EXEC /WOULD TURN INTERRUPTS ON (IN THE EXEC), THUS INVITING /RACE CONDITIONS. XWAITM, 0 IFDEF SWAPPER < /THE "FREE PARTITION" FLAG DCA COMMAND /IS IN THE SIGN BIT OF THE AC > CLA CLL /CLEAR AC (IN CASE SWAPPER NOT PRESENT) /AND LINK (SO TSWAIT WILL ZERO THE TASK AC) TAD XWAITM DCA LOC20 /FAKE A CALL TO EXEC (IN CASE WE MUST WAIT) RDF TAD ECDIF0 DCA EXRET DCA TSWFLG /THIS IS STILL PART OF THE FAKE CALL TAD I LOC20 /GET THE WAIT MASK ISZ LOC20 JMP I (TSWAIT /GO WAIT ON MASK
/INSERT A DEVICE SKIP INTO THE INTERRUPT CHAIN XSKPINS,TAD I LOC20 /GET THE ADDRESS OF THE SKIP - 2 ISZ LOC20 DCA T TAD I T SZA CLA /IF ARGUMENT LOC IS NON-ZERO, JMP EXRET /IT IS ALREADY IN THE SKIP CHAIN - IGNORE TAD (DISMIS /CHAIN IT TO THE END OF THE CHAIN DCA I T ISZ T TAD ECDIF0 DCA I T IFNZRO HGHFLD < TAD EXRET /GET CDF TO NEW "LAST SKIP" INTCDF, CDF CIF 0 /CDF TO FLD OF OLD "LAST SKIP" AND INH INTS /**NOTE: THE IF IS NOW GARBAGE /DO NOT JUMP ANYWHERE! DCA INTCDF /UPDATE "LAST SKIP" FIELD TO NEW ONE > TAD T DCA I INTEND /CHAIN OLD SKIP TO NEW ONE ISZ INTEND IFNZRO HGHFLD < TAD INTCDF > DCA I INTEND STA TAD T DCA INTEND /UPDATE POINTER TO END OF SKIP CHAIN /FALLING INTO EXRET FIXES INSTRUCTION FIELD EXRET, HLT /CDF CIF RETURN FIELD (ALSO INHIBIT INTERRUPTS) IFZERO HGHFLD <IOF> /INTERRUPTS OFF FOR ISZ! ISZ TSWFLG /ALLOW TASK SWITCHING (SKIPS IF RESCAN NECESSARY) IFZERO HGHFLD < JMP .+3 /NO RESCAN NECESSARY ION /TASK SWITCHING STILL INHIBITED, TURN ION AND JMP ECDIF0 /STOP CURRENT JOB AND GO TO RESCAN ION /NOW ITS SAFE TO TURN INTERRUPTS BACK ON > JMP I LOC20 /RETURN TO CALLING TASK ECDIF0, CDF CIF 0 /OOPS - WE MUST TASK SWITCH IMMEDIATELY! JMP I (TSTOP /GO STOP THIS TASK AND RUN SOMEONE ELSE INTEND, BSKCHN
IFNDEF SWAPPER < /RTS-8 SCHEDULER - SCANS TASK FLAGS TABLE TO DETERMINE HIGHEST /PRIORITY RUNNABLE TASK - RUNS WITH INTERRUPTS ON (SOMETIMES) /AND IS STATELESS. FINDJ, CLA CLL IAC /CODE TO FIND FIRST RUNNABLE TASK DCA TASKX /INITIALIZE TASK NUMBER DCA SVSFLG /THE MACHINE STATE IS NOW UNIMPORTANT CLA IAC /AND WE SHOULD RE-ENABLE TASK SWITCHING DCA TSWFLG /SO THAT IF A TASK BECOMES RUNNABLE TAD (TFTABL /AFTER WE SCAN IT, IT WILL INTERRUPT DCA XR /THE SCAN LOOP AND RUN. FINDJL, IFNZRO HGHFLD <CIF 0> /AS WE SEARCH A TASK'S ENTRY IN THE LIST, IFZERO HGHFLD <IOF> TAD I XR /WE ASSUME THAT TASK'S PRIORITY SNA CLA /LOOK FOR FIRST TABLE ENTRY OF 0 JMP I (STARTJ /(THERE HAS TO BE ONE - NAMELY THE NULL TASK) IFZERO HGHFLD <ION> ISZ TASKX /BUMP THE TASK NUMBER (AND PRIORITY) /ALLOW INTERRUPTS FOR ONE CYCLE SINCE JMP FINDJL /"TASKX" IS BIGGER THAN CURRENT REJECTED TASK >
IFDEF SWAPPER < /RTS-8 SCHEDULER - SCANS TASK FLAGS TABLE TO DETERMINE HIGHEST /PRIORITY RUNNABLE TASK - RUNS WITH INTERRUPTS ON (SOMETIMES) /AND IS STATELESS. /THIS SCHEDULER, USED WITH THE SWAPPER, IS SLIGHTLY /SLOWER THAT THE PREVIOUS SCHEDULER, USED WITHOUT THE SWAPPER. /NOTE: THIS ROUTINE IS VERY PRONE TO RACE CONDITIONS. /DO NOT MODIFY IT UNLESS YOU VERY CAREFULLY CHECK OUT WHAT /MIGHT HAPPEN IF AN INTERRUPT OCCURS AFTER EACH STATEMENT ACTION, SNL /IS HE NONRESIDENT? JMP I (STARTJ /NO: START HIM UP IFNZRO EXEC-SWPWT <SYSERR,_ERROR_> /CALEXC.NE.SWPWT TAD CALEXC /AC='SWPWT' DCA I NXR /PUT HIM IN SWAP WAIT TAD (-RUNWT-1 AND I (SWAPPER+TFTABL DCA I (SWAPPER+TFTABL /TAKE SWAPPER OUT OF RUN WAIT /GO FIND SOMEONE ELSE; HOPEFULLY SWAPPER /** NOTE: AC MAY BE NON-ZERO ON ENTRY ** FINDJ, CLA IAC /CODE TO FIND FIRST RUNNABLE TASK DCA TASKX /INITIALIZE TASK NUMBER DCA SVSFLG /THE MACHINE STATE IS NOW UNIMPORTANT /IN CASE WE ARE TASK-SWITCHED OUT OF THE SCAN LOOP /WE WILL NOT SAVE STATE CLA IAC /NOW (NOT EARLIER) WE CAN RE-ENABLE TASK SWITCHING DCA TSWFLG /SO THAT IF A TASK BECOMES RUNNABLE TAD (TFTABL /AFTER WE SCAN IT, IT WILL INTERRUPT DCA NXR /THIS SCAN LOOP AND RUN FINDJL, IFNZRO HGHFLD <CIF 0> /AS WE SEARCH A TASK'S ENTRY IN THE LIST IFZERO HGHFLD <IOF> ISZ NXR /(BUMPING TO NEXT ENTRY) TAD I NXR /WE ASSUME THAT TASK'S PRIORITY CLL RAL /PUT NON-RESIDENT BIT INTO LINK SNA CLA /LOOK FOR THE FIRST TABLE ENTRY OF 0 JMP ACTION /FOUND ONE, START HIM UP IFZERO HGHFLD <ION> ISZ TASKX /BUMP THE TASK NUMBER (AND OUR PRIORITY) JMP FINDJL /ALLOW INTERRUPTS FOR ONE CYCLE SINCE /'TASK' IS BIGGER THAN CURRENT REJECTED TASK /WE MAY RESCHEDULE OUT OF HERE NXR, 0 > PAGE
/SEND A MESSAGE TO A TASK / ***** N O L I T E R A L S O N T H I S P A G E ! XSENDW, STA /SET OR XSEND, DCA SWTFLG /CLEAR WAIT FLAG TAD I LOC20 ISZ LOC20 /GET THE DCA ACARG /TASK NUMBER FROM THE ARGUMENT LIST TAD I LOC20 /GET THE ADDRESS OF THE MESSAGE DCA MSGADR TAD I MSGADR SNA CLA /IS THE MESSAGE ALREADY IN A QUEUE? JMP MSGFRE /NO AC7775 TAD LOC20 DCA LOC20 /BUMP PC BACK TO DO CALL AGAIN MSEFWT, TAD MSGADR JMP I PWAITS /WAIT FOR MESSAGE TO BE FREE MSGFRE, ISZ LOC20 TAD ACARG /GET THE ADDRESS OF THE TARGET TASKS' JMS SRCOMN /MESSAGE QUEUE POINTER DCA MSGCDF /SAVE CDF TO NEW MESSAGE'S FIELD TAD DCDF ADDTOQ, DCA MPTCDF /SAVE CDF TO FIELD OF CURRENT QUEUE POINTER CLA IAC TAD MPTR DCA MPT2 /GET POINTER TO SECOND WORD OF POINTER TAD I MPT2 DCA T /SAVE ADDRESS OF NEXT QUEUE ENTRY TAD I MPTR /FIRST WORD IS A CDF SNA /ZERO TERMINATES THE QUEUE JMP ENDOFQ DCA NXTCDF /SAVE CDF RCVPTR, NXTCDF, HLT AC3777 AND I T /FIRST WORD OF MESSAGE HEADER IS TASK# CIA CLL /COMPARE TO NUMBER OF SENDING TASK TAD TASKX /IF NUMBER IS LOWER WE INSERT SNL CLA /THE MESSAGE BEFORE THIS ONE JMP ENDOFQ CLA IAC TAD T DCA MPTR /OTHERWISE GO ON TO THE NEXT TAD NXTCDF /QUEUE ENTRY JMP ADDTOQ
/COME HERE WHEN WE HAVE FOUND THE PLACE TO INSERT THE MESSAGE ENDOFQ, MPTCDF, HLT /SET DF TO FIELD OF PREVIOUS POINTER TAD I MPTR DCA MPTCDF /SAVE PREVIOUS CDF TAD MSGCDF /LINK THE NEW MESSAGE BETWEEN TWO DCA I MPTR /EXISTING MESSAGES ON THE QUEUE TAD MSGADR DCA I MPT2 /OK - HALF THE LINKAGE IS DONE IOF /MUST TURN INTERRUPTS OFF TO CALL FREEJ! TAD ACARG JMS I PFREEJ /CLEAR MESSAGE WAIT BIT FOR RECEIVER MSGWT!EORMWT /(DO IT NOW SO DF WILL BE CORRECT LATER) TAD TASKX /*** CODE IN THIS RANGE MUST NOT TOUCH LINK *** MSGCDF, HLT /* NOW GO TO THE MESSAGE'S DATA FIELD ION /* WE'RE SAFE - TURN INTERRUPTS ON DCA I MSGADR /* STORE THE SENDING TASK NUMBER ISZ MSGADR /* TAD MPTCDF /* DCA I MSGADR /* STORE CDF TO NEXT MESSAGE IN Q ISZ MSGADR /* TAD T /* DCA I MSGADR /* STORE ADDRESS OF NEXT MESSAGE IN Q ISZ SWTFLG /* SHOULD WE WAIT ON THIS MESSAGE? JMP I PPOSTEX /* NO - RUN RECEIVER IF ITS /* HIGHER PRIORITY, ELSE EXIT AC7776 /DON'T WORRY ABOUT RECEIVER - /WAITING WILL FORCE RESCAN OF TASK LIST - JMP MSEFWT /GO WAIT ON MESSAGE EVENT FLAG /** DF MUST BE SET TO CALLER'S FIELD HERE ** SRCOMN, 0 /SUBROUTINE USED BY SEND AND RECEIVE CLL RAL /GET POINTER TO A TASK'S TAD PMSGTBL /MESSAGE QUEUE POINTER DCA MPTR CDF 0 AC7776 TAD I PEXRET JMP I SRCOMN
/RECEIVE A MESSAGE FROM THE TASK'S MESSAGE QUEUE XRECEIV,TAD TASKX JMS SRCOMN /GET THE MESSAGE QUEUE PTR FOR THIS TASK DCA STOCDF /SAVE CDF TO CALLING FIELD TAD DCDF RCVLP, DCA PRVCDF /SAVE PREVIOUS Q ENTRIES' FIELD TAD I MPTR /GET MESSAGE QUEUE POINTER SNA /IF ZERO, THERE ARE NO MESSAGES IN THE Q JMP NOMSG /SO HANG THE TASK DCA CHNCDF CLA IAC TAD MPTR DCA MPT2 /GET POINTER TO SECOND WORD OF Q POINTER TAD I MPT2 DCA RCVPTR SWTFLG, CHNCDF, HLT /CDF TO FIELD OF Q ENTRY AC3777 /IGNORE SIGN BIT AND ACARG /ACARG CONTAINS TASK DEDICATION (IF ANY) CIA SZA /IS RECEIVER DEDICATED TO ANYONE? TAD I RCVPTR /YES - CHECK ORIGIN OF THIS MESSAGE ISZ RCVPTR CLL RAL /HIGH-ORDER BIT (WAIT BIT) IRRELEVANT SNA CLA /CAN THIS MESSAGE BE RECEIVED? JMP RCVOK /YES - PASS IT ON TAD RCVPTR /NO - CHAIN TO NEXT MESSAGE IN Q DCA MPTR TAD CHNCDF JMP RCVLP RCVOK, TAD I RCVPTR /GET FIRST WORD OF ENTRY DCA T ISZ RCVPTR TAD I RCVPTR PRVCDF, HLT /SET FIELD OF PREVIOUS Q ENTRY DCA I MPT2 /SET PREV Q ENTRIES' POINTER (BOTH WORDS) TAD T /TO THE CONTENTS OF THIS Q ENTRIES' DCA I MPTR /POINTER, REMOVING THIS ENTRY FROM THE Q CLA IAC /FORM A POINTER TO THE FIRST WORD OF TAD RCVPTR /INFORMATION IN THE REMOVED MESSAGE MSGADR, STOCDF, HLT DCA I LOC20 /AND STORE IT IN THE FIRST ARGUMENT TAD CHNCDF /RETURN WITH CDF TO MESSAGE IN AC STOCD2, ISZ LOC20 /SKIP ARG JMP I PEXRET /LITERALS: PWAITS, WAITS PFREEJ, FREEJ PPOSTEX,POSTEX PMSGTBL,MSGTBL PEXRET, EXRET NOMSG, TAD ACARG /LOOK AT AC AGAIN SPA CLA /DID USER WANT TO WAIT IF NO MESSAGE? JMP STOCD2 /NO /YES, FLOW INTO WAITM3 IFNZRO .&1000 <SYSERR,_ERROR_> /PAGE TOO BIG
/WAIT FOR MESSAGE WAITM3, AC7776 TAD LOC20 DCA LOC20 /MOVE PC BACK TO "JMS 20" STL /SET LINK TO PRESERVE AC ACROSS "TSTOP" TAD (MSGWT /BLOCK TASK ON MESSAGE WAIT /COME HERE WITH BLOCKING BITS IN AC. /TASK AC WILL BE CLEARED IF LINK IS 0, PRESERVED IF LINK IS 1 TSWAIT, DCA BLKMSK /ENTER HERE WITH BLOCKING BITS IN AC TSWATX, TAD TASKX /ENTER HERE WITH BLOCKING BITS IN "BLKMSK" TAD (TFTABL /GET INDEX INTO JOB FLAGS TABLE. DCA T TAD BLKMSK /GET BLOCKING BITS CDF 0 DCA I T /NO NEED TO OR THEM IN - WORD WAS ZERO BEFORE. ION /(IN CASE WE CAME FROM "WAITE" OR "WAITM") SNL /SHOULD WE CLEAR TASK AC? TSTOP, DCA ACARG /ENTER HERE WITH TASK AC IN AC XTSTOP, TAD TASKX /TO STOP THE CURRENT TASK BUT NOT BLOCK IT. CLL RTL /GET A POINTER INTO THE TASK'S STATE TABLE ENTRY TAD (TSTABL-1 DCA XR CDF 0 IFNZRO HGHFLD < TAD I (EXRET CLL RAR RTR TAD I (EXRET TAD (-5023 /5023 = 6203 + (6203 SHIFTED RIGHT 3) > DCA I XR /STORE RETURN IF AND DF=IF TAD LOC20 DCA I XR /STORE RETURN PC TAD ACARG DCA I XR /STORE RETURN AC IFNZRO EAE < MQA /EVEN PRESERVE THE MQ OVER MONITOR CALLS DCA I XR /(WHAT THE HECK, ITS ONLY 2 INSTRUCTIONS) > IFDEF SWAPPER < TAD COMMAND SPA CLA /FREE THE PARTITION? WIPCAL, JMS I SWPENT> /YES: LET SWAPPER CODE DO IT JMP I (FINDJ /NO: FIND NEXT TASK TO RUN
/SCHEDULE A TASK TO BE RUN XRUN, TAD (RUNWT JMP UNBLOK XUNBARG,TAD I LOC20 /UNBLOCKING CODE IN ARGUMENT ISZ LOC20 UNBLOK, DCA UNBMSK /AC CONTAINS REASON FOR UNBLOCKING TASK "ACARG" TAD ACARG IOF /FREEJ IS AN INTERRUPT-LEVEL ROUTINE! JMS FREEJ /REMOVE THE GIVEN BLOCKING BIT UNBMSK, 0 ION POSTEX, SNL CLA /SHOULD THE NEW TASK BE RUN NOW? JMP I (EXRET /NO JMP TSTOP /YES-PUT TASK TO SLEEP WITHOUT BLOCKING IT /SUSPEND EXECUTION OF A TASK XSUSPND,TAD (RUNWT JMP BLOK XBLKARG,TAD I LOC20 /BLOCKING CODE IN ARGUMENT ISZ LOC20 BLOK, DCA BLKMSK /SAVE BLOCKING CODE TAD ACARG /GET TASK TO BE BLOCKED SNA JMP TSWATX /0 MEANS CURRENT TASK! / ^ NOTE THE LINK IS RANDOM HERE BUT SINCE ACARG=0 / IT DOESN'T MATTER IF WE CLEAR IT OR NOT CDF 0 TAD (TFTABL DCA T TAD BLKMSK /GET THE BLOCKING FLAG(S) CMA AND I T TAD BLKMSK /OR THEM INTO THE TASK FLAG WORD DCA I T JMP I (EXRET /THIS DOESN'T AFFECT US - JUST RETURN
/ROUTINE TO UNBLOCK A TASK'S EXECUTION /ENTER WITH TASK# IN AC, INTERRUPTS OFF, UNBLOCKING BIT IN CALL+1 FREEJ, 0 CDF 0 TAD (TFTABL DCA INTT TAD I FREEJ /GET UNBLOCKING BIT ISZ FREEJ /BUMP RETURN POINTER CMA AND I INTT DCA I INTT /REMOVE THE FLAG FROM THE TASK FLAG WORD TAD I INTT IFDEF SWAPPER < CLL RAL /IGNORING NON-RESIDENT WAIT, > SNA CLA /IF THE TASK IS NOW RUNNABLE TAD TASKX /AND HAS A HIGHER PRIORITY THAN THE CURRENTLY TAD (TFTABL /RUNNING TASK, RETURN WITH THE LINK ON. CIA STL TAD INTT CLA /OTHERWISE RETURN WITH THE LINK OFF. JMP I FREEJ
/WAIT FOR EVENT FLAG XWAITX, STA /USE 'ACARG' AS FLAG (-1 INDICATES WAITX) XWAITE, DCA ACARG TAD I LOC20 /GET ADDRESS OF EVENT FLAG ISZ LOC20 /SEND HAS ACARG RANDOM BUT NOT -1 WAITS, DCA T /ENTER HERE FROM SEND IFZERO HGHFLD <IOF> /INHIBIT INTERRUPTS IFNZRO HGHFLD <CIF 0> /WHILE TESTING FLAG! TAD I T /EVENT FLAG IS IN SAME FIELD AS CALL SNA CLA /ZERO MEANS EVENT COMPLETED JMP I (EXRET /SO EXIT IMMEDIATELY IFNZRO HGHFLD <IOF> /INTERRUPTS MUST BE OFF BETWEEN SETTING EF /AND SETTING EF WAIT! AC4000 /SET EVENT FLAG TO TASK NUMBER TAD TASKX /WITH HIGH-ORDER BIT ON TO INDICATE DCA I T /THAT TASK IS WAITING FOR EVENT COMPLETION TAD (EFWT ISZ ACARG /WAS THIS A WAITE OR WAITX? JMP TSWAIT /WAITE; AND BLOCK CURRENT TASK ON EVENT WAIT /** NOTE LINK=0 SO ACARG WILL BE CLEARED ** AC7775 /WAITX TAD LOC20 /BUMP PC BACK TO CAL DCA LOC20 /ALSO CLEAR LINK TAD (EORMWT JMP TSWAIT /POST AN EVENT FLAG XPOST, TAD I LOC20 /GET DATA FIELD OF EVENT FLAG ISZ LOC20 DCA .+1 BLKMSK, HLT /CDF TO IT AC4000 TAD I ACARG /ADDRESS WAS IN AC AT CALL DCA T DCA I ACARG /ZERO EVENT FLAG SNL /WAS A TASK WAITING ON EVENT FLAG? JMP I (EXRET /NO - WE'RE DONE TAD T /YES - LOW ORDER BITS ARE TASK NUMBER DCA ACARG TAD (EFWT!EORMWT JMP UNBLOK /UNBLOCK THIS TASK FROM EVENT FLAG WAIT PAGE
/DUMMY TABLE ENTRIES (EACH TASK OVERLAYS ITS ENTRY WHEN IT LOADS): MSGTBX, ZBLOCK NTASKS^2 0;0 /MESSAGES FOR NULL TASK TSTABX, ZBLOCK NTASKS^4 0 .+1 /FIELDS, PC, AC FOR NULL TASK DCA SVSFLG /NULL TASK RUNS STATELESS JMP . TFTABX, IFNZRO NTASKS&40 < 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1> IFNZRO NTASKS&20 < 1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1> IFNZRO NTASKS&10 < 1;1;1;1;1;1;1;1> IFNZRO NTASKS&4 <1;1;1;1> IFNZRO NTASKS&2 <1;1> IFNZRO NTASKS&1 <1> 0 /NULL TASK ALWAYS RUNNABLE IFNZRO TFTABX-TFTABL-1 <TBLERR,_ERROR_> IFDEF SWAPPER < *RESTBL ZBLOCK NTASKS-SWAPPER^2 *PARTBL ZBLOCK PARTNS^4 > IFNZRO KL8A < *KL8ACT KL8ACT, 0 HLT /SAFETY HALT IN CASE USER JMP . /FORGETS TO ASSEMBLE KL8ASR.PA > IFDEF DDCMP < FIELD DDCFLD%10 *LCBTAB ZBLOCK MAXLIN^LCBSIZ > IFDEF NSP < FIELD NSPFLD%10 *CCBTAB ZBLOCK MAXCCB^2 > FIELD 0



Feel free to contact me, David Gesswein djg@pdp8online.com with any questions, comments on the web site, or if you have related equipment, documentation, software etc. you are willing to part with.  I am interested in anything PDP-8 related, computers, peripherals used with them, DEC or third party, or documentation. 

PDP-8 Home Page   PDP-8 Site Map   PDP-8 Site Search