ITS Muddle.
[pdp10-muddle.git] / MUDDLE / ninter.4
diff --git a/MUDDLE/ninter.4 b/MUDDLE/ninter.4
new file mode 100644 (file)
index 0000000..27debb8
--- /dev/null
@@ -0,0 +1,668 @@
+
+TITLE INTERRUPT HANDLER FOR MUDDLE
+
+RELOCATABLE
+
+;C. REEVE  APRIL 1971
+
+.INSRT MUDDLE >
+
+PDLGRO==10000  ;AMOUNT TO GROW A PDL THAT LOSES
+NINT==72.      ;MAXIMUM NUMBER OF INTERRUPTS POSSIBLE
+
+;SET UP LOCATION 42 TO POINT TO TSINT
+
+ZZZ==. ;SAVE CURRENT LOCATION
+
+LOC 42
+î      JSR     TSINT           ;GO TO HANDLER
+
+LOC ZZZ
+
+; GLOBALS NEEDED BY INTERRUPT HANDLER
+
+.GLOBA GCFLG   ;TELLS WHETHER OR NOT GARBAGE COLLECTOR IS RUNNING
+.GLOBA GCINT   ;TELLS GARBAGE COLLECTOR TO SIMULATE AN INTERRUPT
+.GLOBAL INTNUM,INTVEC  ;TV ENTRIES CONCERNING INTERRUPTS
+.GLOBAL AGC    ;CALL THE GARBAGE COLLECTOR
+.GLOBAL VECNEW,PARNEW,GETNUM   ;GC PSEUDO ARGS
+.GLOBAL GCPDL  ;GARBAGE COLLECTORS PDL
+.GLOBAL VECTOP,VECBOT  ;DELIMIT VECTOR SPACE
+.GLOBAL PDLBUF ;AMOUNT OF  PDL GROWTH
+.GLOBAL PGROW  ;POINTS TO DOPE WORD OF NEXT PDL TO GROW
+.GLOBAL TPGROW ;POINTS TO NEXT MUDDLE PDL TO GROW
+.GLOBAL PPGROW ;BLOWN PLANNER PDL
+.GLOBAL PLDGRO ;SEE ABOVE
+.GLOBAL CALER1,TMA,TFA
+.GLOBAL BUFRIN,CHANL0,SYSCHR   ;CHANNEL GLOBALS
+.GLOBAL IFALSE,TPOVFL,PDLOSS
+.GLOBAL FLFLG  ;-1  IFF INTERRUPT IN FAIL
+
+
+.GLOBAL INTINT ;CALLED BY INITIALIZER TO TAKE CARE OF INT PCS
+
+.GLOBAL MSGTYP,TYI,IFLUSH,OCLOS,ERRET  ;SUBROUTINES USED
+;BEGINNING OF ACTUAL INTERRUPT HANDLER (MUST BE IMPURE)
+
+TSINT: 0                       ;INTERRUPT BITS GET STORED HERE
+TSINTR:        0                       ;INTERRUPT PC WORD STORED HERE
+       JRST    TSINTP          ;GO TO PURE CODE
+
+; SOFTWARE INTERNAL INTERRUPTS JSR TO HERE
+
+LCKINT:        0
+       JRST    DOINT
+
+;THE REST OF THIS CODE IS PURE
+
+TSINTP:        SOSGE   INTFLG          ; SKIP IF ENABLED
+       SETOM   INTFLG          ;DONT GET LESS THAN -1
+
+       MOVEM   A,TSAVA         ;SAVE TWO ACS
+       MOVEM   B,TSAVB
+       MOVE    A,TSINT         ;PICK UP INT BIT PATTERN
+       JUMPL   A,2NDWORD       ;DONT CHECK FOR PDL OVERFLOW ETC. IF SIGN BIT ON
+
+       TRZE    A,200000        ;IS THIS A PDL OVERFLOW?
+       JRST    IPDLOV          ;YES, GO HANDLE IT FIRST
+
+IMPCH: TRZE    A,20000         ;IS IT A MEMORY PROTECTION VIOLATION?
+       JRST    IMPV            ;YES, GO HANDLE IT
+
+       TRZE    A,40            ;ILLEGAL OP CODE?
+       JRST    ILOPR           ;YES, GO HANDLE
+
+;DECODE THE REST OF THE INTERRUPTS USING A TABLE
+
+2NDWORD:
+       JUMPL   A,GC2           ;2ND WORD?
+       IORM    A,PIRQ          ;NO, INTO WORD 1
+       JRST    GCQUIT          ;AND DISMISS INT
+
+GC2:   TLZ     A,400000        ;TURN OFF SIGN BIT
+       IORM    A,PIRQ2
+       TRNE    A,177777        ;CHECK FOR CHANNELS
+       JRST    CHNACT          ;GO IF CHANNEL ACTIVITY
+
+GCQUIT:        SKIPGE  INTFLG          ;SKIP IF INTERRUPTS ENABLED
+       JRST    INTDON          ;NO, DEFER REAL HANDLING UNTIL LATER
+
+       MOVE    A,TSINTR        ;PICKUP RETURN WORD
+       MOVEM   A,LCKINT        ;STORE ELSEWHERE
+       MOVEI   A,DOINTE        ;CAUSE DISMISS TO HANDLER
+       HRRM    A,TSINTR        ;STORE IN INT RETURN
+       PUSH    P,INTFLG        ;SAVE INT FLAG
+       SETOM   INTFLG          ;AND DISABLE
+
+
+INTDON:        MOVE    A,TSAVA         ;RESTORE ACS
+       MOVE    B,TSAVB
+       .DISMISS        TSINTR          ;AND DISMISS THE INTERRUPT
+
+; HERE IF INTERRUPTED IN OTHER THAN GC
+
+DOINT: PUSH    P,INTFLG
+DOINTE:        PUSH    P,LCKINT        ;SAVE RETURN
+       SETZM   INTFLG          ;DISABLE
+       AOS     -1(P)           ;INCR SAVED FLAG
+
+;NOW SAVE WORKING ACS
+
+IRP A,,[0,A,B,C,D,E]
+       PUSH    TP,A!STO(PVP)
+       SETZM   A!STO(PVP)      ;NOW ZERO TYPE
+       PUSH    TP,A
+       TERMIN
+       PUSH    P,INTNUM+1(TVP) ;PUSH CURRENT VALUE
+
+DIRQ:  MOVE    A,PIRQ          ;NOW SATRT PROCESSING
+       JFFO    A,FIRQ          ;COUNT BITS AND GO
+       MOVE    A,PIRQ2         ;1ST DONE, LOOK AT 2ND
+       JFFO    A,FIRQ2
+
+INTDN1:
+       POP     P,INTNUM+1(TVP) ;RESTORE CURRENT
+IRP A,,[E,D,C,B,A,0]
+       POP     TP,A
+       POP     TP,A!STO(PVP)
+       TERMIN
+
+       POP     P,LCKINT
+       POP     P,INTFLG
+       JRST    @LCKINT         ;AND RETURN
+
+FIRQ:  PUSHJ   P,GETBIT        ;SET UP THE BIT TO CLOBBER IN PIRQ
+       ANDCAM  A,PIRQ          ;CLOBBER IT
+       ADDI    B,36.           ;OFSET INTO TABLE
+       JRST    XIRQ            ;GO EXECUTE
+
+FIRQ2: PUSHJ   P,GETBIT        ;PREPARE TO CLOBBER BIT
+       ANDCAM  A,PIRQ2         ;CLOBBER IT
+       ADDI    B,71.           ;AGAIN OFFSET INTO TABLE
+XIRQ:
+       CAIN    B,21            ;PDL OVERFLOW?
+       JRST    PDL2            ;YES, HACK APPROPRIATELY
+       MOVEM   B,INTNUM+1(TVP) ;AND SAVE
+       LSH     B,1             ;TIMES 2
+       ADD     B,INTVEC+1(TVP) ;POINT TO LIST OF TASKS
+       SKIPN   A,(B)           ;ANY TASKS?
+       JRST    DIRQ            ;NO, PUNT
+
+       PUSH    TP,$TLIST       ;SAVE LIST
+       PUSH    TP,A
+DOINTS:        HLRZ    C,(A)           ;GET TYPE
+       CAIE    C,TLIST         ;LIST?
+       JRST    IWTYP
+       HRRZ    A,1(A)
+       JUMPE   A,IWTYP         ;LIST IS NIL, LOSE
+       HLRZ    C,(A)           ;CHECK FOR A PROCESS
+       CAIE    C,TPVP
+       JRST    IWTYP
+       HRRZ    D,(A)           ;POINT TO 2D PART OF PAIR
+       PUSH    TP,(D)          ;SETUP CALL TO EVAL
+       PUSH    TP,1(D)
+       MOVE    D,TB            ;GET CURRENT FRAME POINTER
+       MOVE    C,1(A)          ;GET PROCESS WHO WANTS THIS INTERRUPT
+       CAME    C,PVP           ;SKIP IF CURRENT PROCESS
+       MOVE    D,TBSTO+1(C)    ;GET SAVED FRAME
+       HLRE    A,C             ;COMPUTE DOPE WORD POINTER
+       SUBI    C,-1(A)         ;HAVE POINTER
+       HRLI    C,TFRAME        ;BUILD A FRAME HACK
+       HLL     D,OTBSAV(D)     ;GET A WINNING TIME
+       PUSH    TP,C            ;AND PUSH IT
+       PUSH    TP,D
+       MCALL   2,EVAL
+INTCDR:        HRRZ    A,@(TP)         ;CDR THE LIST OF TASKS
+       JUMPE   A,TPPOP
+       MOVEM   A,(TP)          ;SAVE THE CDR'D LIST
+       JRST    DOINTS
+
+TPPOP: SUB     TP,[2,,2]       ;REMOVE LIST
+       JRST    DIRQ
+
+IWTYP: PUSH    TP,(A)          ;SAVE TASK
+       PUSH    TP,1(A)
+       PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE BAD-INTERRUPT-HANDLER-TASK-IGNORED
+       MCALL   1,PRINT
+       MCALL   1,PRINT
+       JRST    INTCDR
+
+PDL2:  MOVEI   B,PDLGRO_-6     ;GET GROWTH SPEC
+       SKIPE   A,PGROW         ;SKIP IF A P IS NOT GROWING
+       DPB     B,[111100,,-1(A)]       ;STORE GROWTH SPEC
+TRYTPG:        SKIPE   A,TPGROW        ;IS TP BLOWN
+       DPB     B,[111100,,-1(A)]       ;YES, SET GROWTH SPEC
+       SKIPE   A,PPGROW                ;POINT TO BLOWN PP
+       DPB     B,[111100,,-1(A)]
+       PUSHJ   P,AGC           ;COLLECT GARBAGE
+       SETZM   PPGROW
+       SETZM   PGROW
+       SETZM   TPGROW
+       JRST    INTDN1
+
+
+
+;SUBROUTINE TO SET AN INTERRUPT HANDLER
+
+MFUNCTION SETINT,SUBR
+       ENTRY   2
+
+       HLRZ    A,(AB)          ;FIRST IS FIXED
+       CAIE    A,TFIX
+       JRST    WTYP1
+       HLRZ    A,2(AB)
+       CAIE    A,TLIST
+       JRST    WTYP2
+       SKIPGE  B,1(AB)         ;GET NUMBER
+       JRST    NEGINT          ;INTERRUPT NEGATIVE
+       HRRZ    C,3(AB)         ;PICKUP LIST
+ISENT1:        PUSH    P,CFINIS                ;FALL INTO INTERNAL SET TO POP TO FINIS
+
+ISETNT:        MOVEI   D,(B)           ;COPY
+       LSH     B,1
+       HRLI    B,(B)           ;TO 2 HALVES
+       ADD     B,INTVEC+1(TVP) ;POINT TO HANDLER
+       JUMPGE  B,INTOBG        ;OUT OF RANGE
+       HRRZ    E,(B)           ;AND OLD POINTER
+       HRRM    E,(C)           ;SPLICE
+       HRRM    C,(B)
+       CAILE   D,35.           ;WHICH MASK?
+       JRST    SETW2
+
+       SUBI    D,36.           ;FIND BIT POSITION
+       MOVSI   A,400000
+       LSH     A,(D)           ;POSTITION
+       IORM    A,MASK1
+       .SUSET  [.SMASK,,MASK1]
+SETIN1:        MOVE    A,(AB)
+       MOVE    B,1(AB)
+CFINIS:        POPJ    P,FINIS ;USED BY SETINT TO SETUP RETURN
+
+SETW2: SUBI    D,71.
+       MOVSI   A,400000
+       LSH     A,(D)
+       IORM    A,MASK2
+       .SUSET  [.SMSK2,,MASK2]
+       JRST    SETIN1
+WTYP1: PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE FIRST-ARG-WRONG-TYPE
+       JRST    CALER1
+
+
+WTYP2: PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE SECOND-ARG-WRONG-TYPE
+       JRST    CALER1
+
+NEGINT:        PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE NEGATIVE-INTERRUPT-NUMBER
+       JRST    CALER1
+INTOBG:        PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE INT-NUMBER-TOO-LARGE
+       JRST    CALER1
+
+BADCHN:        PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE CHANNEL-NOT-PHYSICAL
+       JRST    CALER1
+
+LWTYP: PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE LAST-ARG-WRONG-TYPE
+       JRST    CALER1
+
+; SET A CHANNEL INTERRUPT
+
+MFUNCTION ONCHAR,SUBR
+
+       ENTRY
+
+       SKIPL   B,AB            ;COPY ARG POINTER
+       JRST    TFA
+       ADD     B,[2,,2]        ;POINT TO EXPRESSION ARG
+       PUSHJ   P,CHKRGS        ;CHECK OUT THE ARGS AND MAKE THE LIST
+       GETYP   A,(AB)  ;CHECK FOR A CHANNEL
+       CAIE    A,TCHAN
+       JRST    WTYP1
+       MOVE    C,1(AB)         ;GET CHANNEL
+       SKIPN   C,CHANNO(C)     ;GET CHANNEL
+       JRST    BADCHN
+       ADDI    C,36.           ;POINT INTO INT VECTOR
+       EXCH    B,C
+       PUSHJ   P,ISETNT        ;SET THE INTERRUPT
+       MOVE    A,2(AB)         ;RETURN ARG
+       MOVE    B,3(AB)
+       JRST    FINIS
+
+; SET A CLOCK INTERRUPT
+
+MFUNCTION ONCLOCK,SUBR
+
+       ENTRY
+
+       MOVE    B,AB
+       PUSHJ   P,CHKRGS                ;CHECK ARGS AND MAKE LIST
+       MOVE    C,B     ;COPY LIST POINTER
+       MOVEI   B,13.           ;CLOCK INT NUMBER
+       JRST    ISENT1          ;SET UP THE INT
+
+CHKRGS:        JUMPGE  B,TFA
+       MOVE    C,PVP           ;GET CURRENT PROCESS
+       CAML    B,[-2,,0]       ;CHECK FOR PROCESS ARG
+       JRST    GOTPVP
+       CAMGE   B,[-4,,0]       ;SKIP IF RIGHT NO. OF ARGS
+       JRST    TMA             ;TOO MANY
+       GETYP   A,2(B)          ;CHECK TYPE
+       CAIE    A,TPVP
+       JRST    LWTYP           ;WRONG TYPE
+       MOVE    C,3(B)          ;GET PROCESS
+GOTPVP:        PUSH    TP,$TPVP
+       PUSH    TP,C
+       PUSH    TP,(B)          ;PUSH EXPRESSION
+       PUSH    TP,1(B)
+       MCALL   2,LIST  ;MAKE THE LIST
+       PUSH    TP,A
+       PUSH    TP,B
+       MCALL   1,LIST          ;MAKE A LIST OF A LIST
+       POPJ    P,
+
+
+;ROUTINE TO GET CURRENT INT NUMBER
+
+MFUNCTION GETINT,SUBR
+
+       ENTRY   0
+       MOVSI   A,TFIX
+       MOVE    B,INTNUM+1(TVP)
+       JRST    FINIS
+
+MFUNCTION INTCHAR,SUBR
+
+       ENTRY
+       PUSH    P,CFINIS        ;CAUSE RETURN TO FINIS
+INTCH1:        MOVE    B,INTNUM+1(TVP)
+       JUMPGE  AB,GOTNUM
+       HLRZ    A,(AB)
+       CAIE    A,TFIX
+       JRST    WTYP1
+       MOVE    B,1(AB)
+
+GOTNUM:        SUBI    B,36.           ;CONVERT TO CHANNEL
+       MOVEI   C,(B)           ;SAVE A COPY OF CHANNEL
+       .ITYIC  B,
+       JRST    NOCHRS
+
+       LSH     B,29.
+       MOVSI   A,TCHRS
+       MOVEI   D,(C)   ;COPY CHANNEL AGAIN
+       LSH     D,1             ;TIMES 2
+       ADDI    D,CHANL0+1(TVP) ;POINT TO INFO
+       HRRZ    E,(D)   ;POINT TO CHANNEL
+       HRRZ    E,BUFRIN(E)     ;POINT TO ADDL INFO
+       AOS     SYSCHR(E)
+
+REINT: MOVEI   E,1     ;PREPARE TO RENABLE
+       LSH     E,(C)
+       IORM    E,MASK2
+       .SUSET  [.SMSK2,,MASK2]
+       POPJ    P,
+
+
+NOCHRS:        MOVEI   B,0
+       MOVSI   A,TFALSE
+       JRST    REINT
+
+MFUNCTION QUITTER,SUBR
+
+       ENTRY   0
+
+REQT:  PUSHJ   P,INTCH1        ;CHECK FOR A CHAR
+       CAMN    A,$TFALSE       ;ANY LEFT?
+       JRST    FINIS   ;NO
+       CAME    B,[7_29.]       ;CNTL G?
+       JRST    REQT
+       PUSH    TP,$TCHAN               ;QUIT HERE
+       PUSH    TP,(D)          ;PUSH CHANNEL
+       MCALL   1,RRRES
+       PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE CONTROL-G
+       MCALL   1,ERROR
+       JRST    FINIS
+
+MFUNCTION INTRCH,SUBR,INTCHAN
+
+       ENTRY   0
+
+       MOVE    B,INTNUM+1(TVP) ;GET INT NUMBER
+       SUBI    B,36.
+       JUMPL   B,IFALSE        ;NOT A CHANNEL
+       CAILE   B,17
+       JRST    IFALSE          ;NOT A CHANNEL
+       LSH     B,1             ;TIMES 2
+       ADDI    B,CHANL0(TVP)   ;GET POINTER TO CHANNEL
+       MOVE    A,(B)
+       MOVE    B,1(B)
+       JRST    FINIS
+
+MFUNCTION GASCII,SUBR,ASCII
+       ENTRY   1
+
+       HLRZ    A,(AB)
+       CAIE    A,TCHRS
+       JRST    TRYNUM
+
+       MOVE    B,1(AB)
+       TDNN    B,[3777,,-1]
+       LSH     B,-29.
+       MOVSI   A,TFIX
+       JRST    FINIS
+
+TRYNUM:        CAIE    A,TFIX
+       JRST    WTYP1
+       SKIPGE  B,1(AB)         ;GET NUMBER
+       JRST    TOOBIG
+       CAILE   B,177           ;CHECK RANGE
+       JRST    TOOBIG
+       LSH     B,29.
+       MOVSI   A,TCHRS
+       JRST    FINIS
+
+TOOBIG:        PUSH    TP,$TATOM
+       PUSH    TP,MQUOTE OUT-OF-RANGE
+       JRST    CALER1
+
+;SUBROUTINE TO GET BIT FOR CLOBBERAGE
+
+GETBIT:        MOVNS   B               ;NEGATE
+       MOVSI   A,400000        ;GET THE BIT
+       LSH     A,(B)           ;SHIFT TO POSITION
+       POPJ    P,              ;AND RETURN
+
+;HERE TO HANDLE PDL OVERFLOW.  ASK FOR A GC
+
+IPDLOV:        SKIPE   FLFLG           ;DURING FAILURE,
+       JRST    IMPCH           ;LET FAIL HANDLE BLOWN PDLS
+       MOVEM   A,TSINT         ;SAVE INT WORD
+       MOVEI   A,200000        ;GET BIT TO CLOBBER
+       IORM    A,PIRQ          ;LEAVE A MESSAGE FOR HIGHER LEVEL
+
+       SKIPE   GCFLG           ;IS GC RUNNING?
+       JRST    GCPLOV          ;YES, COMPLAIN GROSSLY
+
+       EXCH    P,GCPDL         ;GET A WINNING PDL
+       HRRZ    B,TSINTR        ;GET POINTER TO LOSING INSTRUCTION
+       LDB     B,[270400,,-1(B)]       ;GET AC FIELD
+       MOVEI   A,(B)           ;COPY IT
+       LSH     A,1             ;TIMES 2
+       ADDI    A,0STO(PVP)     ;POINT TO THIS ACS CURRENT TYPE
+       HLRZ    A,(A)           ;GET THAT TYPE INTO A
+       CAIN    B,P             ;IS IT P
+       MOVEI   B,GCPDL         ;POINT TO SAVED P
+
+       CAIN    B,B             ;OR IS IT B ITSELF
+       MOVEI   B,TSAVB
+       CAIN    B,A             ;OR A
+       MOVEI   B,TSAVA
+
+       CAIN    B,C             ;OR C
+       MOVEI   B,1(P)          ;C WILL BE ON THE STACK
+
+       PUSH    P,C
+       PUSH    P,A
+
+       MOVE    A,(B)           ;GET THE LOSING POINTER
+       MOVEI   C,(A)           ;AND ISOLATE RH
+
+       CAMG    C,VECTOP        ;CHECK IF IN GC SPACE
+       CAMG    C,VECBOT
+       JRST    NOGROW          ;NO, COMPLAIN
+
+       HLRZ    C,A             ;GET -LENGTH
+       SUBI    A,-1(C)         ;POINT TO A DOPE WORD
+       POP     P,C             ;RESTORE TYPE INTO C
+       CAIE    C,TPDL          ;IS IT A P STACK?
+       JRST    TRYTP           ;NO
+       SKIPE   PGROW           ;YES, ALREADY GROWN?
+       JRST    PDLOSS          ;YES, LOSE
+       ADDI    A,PDLBUF        ;POINT TO REAL DOPE WORD
+       HRRM    A,PGROW         ;STORE
+       JRST    PNTRHK          ;FIX UP THE PDL POINTER
+
+TRYTP: CAIE    C,TTP           ;TP STACK
+       JRST    TRYPP
+       SKIPE   TPGROW          ;ALREADY GROWN?
+       JRST    PDLOSS
+       ADDI    A,PDLBUF        ;POINT TO REAL DOPE WORD
+       HRRM    A,TPGROW
+       JRST    PNTRHK          ;GO MUNG POINTER
+
+TRYPP: CAIE    C,TPP           ;PLANNER PDL?
+       JRST    BADPDL
+       SKIPE   PPGROW
+       JRST    PDLOSS          ;LOSER
+       ADDI    A,PDLBUF
+       HRRM    A,PPGROW
+
+
+PNTRHK:        MOVE    C,(B)           ;RESTORE PDL POINTER
+       SUB     C,[PDLBUF,,0]   ;FUDGE THE POINTER
+       MOVEM   C,(B)           ;AND STORE IT
+
+       POP     P,C             ;RESTORE THE WORLD
+       MOVE    A,TSINT         ;RESTORE INT WORD
+
+       EXCH    P,GCPDL         ;GET BACK ORIG PDL
+       JRST    IMPCH           ;LOOK FOR MORE INTERRUPTS
+
+TPOVFL:        SETOM   INTFLG          ;SIMULATE PDL OVFL
+       PUSH    P,A
+       MOVEI   A,200000        ;TURN ON THE BIT
+       IORM    A,PIRQ
+       SUB     TP,[PDLBUF,,0]  ;HACK STACK POINTER
+       HLRE    A,TP            ;FIND DOPEW
+       SUBM    TP,A            ;POINT TO DOPE WORD
+       ADDI    A,1
+       HRRZM   A,TPGROW
+       POP     P,A
+       POPJ    P,
+
+
+;HERE TO HANDLE LOW-LEVEL CHANNELS
+
+
+CHNACT:        SKIPN   GCFLG           ;GET A WINNING PDL
+       EXCH    P,GCPDL
+       ANDI    A,177777        ;ISOLATE CHANNEL BITS
+       PUSH    P,0             ;SAVE
+
+CHNA1: MOVEI   B,0             ;BIT COUNTER
+       JFFO    A,.+2           ;COUNT
+       JRST    CHNA2
+       SUBI    B,35.           ;NOW HAVE CHANNEL
+       MOVMS   B               ;PLUS IT
+       MOVEI   0,1
+       LSH     0,(B)           ;SET TO CLOBBER BIT
+       ANDCM   A,0
+       LSH     B,23.           ;POSITION FOR A .STATUS
+       IOR     B,[.STATUS B]
+       XCT     B               ;DO IT
+       ANDI    B,77            ;ISOLATE DEVICE
+       CAILE   B,2
+       JRST    CHNA1
+       ANDCAM  0,MASK2         ;TURN OFF BIT
+       .SUSET  [.SMSK2,,MASK2]
+       JRST    CHNA1
+
+CHNA2: POP     P,0
+       SKIPN   GCFLG
+       EXCH    P,GCPDL
+       JRST    GCQUIT
+
+;HERE IF PDL OVERFLOW DURING GARBAGE COLLECTION
+
+BADPDL:        SKIPA   B,[[ASCIZ /NON-PDL OVERFLOW
+/]]
+GCPLOV:        MOVEI   B,[ASCIZ /PDL OVERFLOW DURING GARBAGE COLLECTION
+/]
+GFATER:        MOVE    P,GCPDL         ;GET ORIGINAL PDL FOR TYPE OUT
+       JRST    FATERR          ;GO TO FATAL ERROR ROUTINE
+
+NOGROW:        MOVEI   B,[ASCIZ /PDL OVERFLOW ON NON-EXPANDABLE PDL
+/]
+       JRST    GFATER
+
+PDLOSS:        MOVEI   B,[ASCIZ /PDL OVERFLOW BUFFER EXHAUSTED
+/]
+       JRST    GFATER
+
+FATERR:        PUSHJ   P,MSGTYP        ;TYPE THE MESSAGE
+       MOVEI   B,[ASCIZ /FATAL ERROR, PLEASE DUMP SO THAT MUDDLE SYSTEM PROGRAMMERS
+MAY DEBUG./]
+       PUSHJ   P,MSGTYP        ;TYPE THE LOSER MESSAGE
+       PUSHJ   P,OCLOS         ;CLOSE THE TTY
+       .VALUE
+       JRST    .-1
+
+
+;MEMORY PROTECTION INTERRUPT
+
+IMPV:  MOVEI   B,[ASCIZ /MPV -- /]
+
+IMPV1: PUSHJ   P,MSGTYP        ;TYPE
+       SKIPE   GCFLG           ;THESE ERRORS FATAL IN GARBAGE COLLECTOR
+       JRST    GCERR
+
+       MOVE    P,GCPDL         ;MAKE SURE OF A WINNING PDL
+ERLP:  MOVEI   B,[ASCIZ /TYPE "S" TO GO TO SUPERIOR, "R" TO RESTART PROCESS./]
+       PUSHJ   P,IFLUSH        ;FLUSH AWAITING INPUT
+       PUSHJ   P,MSGTYP
+
+       PUSHJ   P,TYI           ;READ THE CHARACTER
+
+       PUSHJ   P,UPLO          ;CONVERT TO UPPER CASE
+       CAIN    A,"S
+       .VALUE
+
+       CAIE    A,"R            ;DOES HE WANT TO RESTART
+       JRST    ERLP            ;NO, TELL HIM AGAIN
+
+       MCALL   0,INTABR        ;ABORT THE PROCESS
+
+INTABR:        MOVEI   A,ERRET         ;REAALY GO TO ERRET
+       HRRM    A,TSINTR
+       .DISMISS        TSINTR
+
+
+GCERR: MOVEI   B,[ASCIZ /IN GARBAGE COLLECTOR
+/]
+       JRST    FATERR
+
+ILOPR: MOVEI   B,[ASCIZ /ILLEGAL OPERATION -- /]
+       JRST    IMPV1
+
+; SUBROUTINE TO CONVERT LOWER CASE LETTERS TO UPPER
+
+UPLO:  CAIG    A,172           ;GEATER THAN Z?
+       CAIG    A,140           ;NO, LESS THAN A
+       POPJ    P,              ;YES, LOSE
+       SUBI    A,40            ;MAKE UPPER CASE
+       POPJ    P,
+
+;SUBROUTINE TO BE CALLED AT INITIALIZE TIME TO FUDGE INT PC
+
+INTINT:        PUSHJ   P,PCHACK        ;FUDGE PC LOSSAGE
+       MOVE    A,MASK1 ;SET MASKS
+       MOVE    B,MASK2
+       .SETM2  A,              ;SET BOTH MASKS
+       POPJ    P,
+
+PCHACK:        .SUSET  [.SMASK,,[200000]]      ;SET FOR ONLY PDL OVERFLOW
+       MOVE    D,TSINT+2       ;SAVE CONTENTS OF ITERRUPT HANDLER
+       MOVEI   A,FUNINT        ;POINT TO DUMMY THEREOF
+       HRRM    A,TSINT+2       ;AND STORE IT
+       HRROI   A,0             ;MAKE A VERY SHORT PDL
+CHPUSH:        PUSH    A,0             ;PUSH SOMETHING AND OVERFLOW
+       .VALUE  [ASCIZ /?/]     ;SHOULD NEVER GET HERE
+
+FUNINT:        HRRM    D,TSINT+2       ;RESTORE STANDARD HANDLER
+       HRRZ    D,TSINTR        ;GET THE LOCATION STORED
+       SUBI    D,CHPUSH        ;FIND THE DIFFERENCE
+       MOVEM   D,PCOFF         ;AND SAVE
+       POP     P,TSINTR        ; POP INTO DISMISS WORD
+       .DISMISS        TSINTR          ;AND DISMISS
+
+
+
+INTLOS:        .VALUE  [ASCIZ /INT/]
+CHARCH:        .VALUE  [ASCIZ /CHAR?/]
+;RANDOM IMPURE CRUFT NEEDED
+
+TSAVA: 0
+TSAVB: 0
+PIRQ:  0                       ;HOLDS REQUEST BITS FOR 1ST WORD
+PIRQ2: 0                       ;SAME FOR WORD 2
+PCOFF: 0
+MASK1: 220040                  ;FIRST MASK
+MASK2: 0                       ;SECOND THEREOF
+
+
+END
+\f\f\ 3\f
\ No newline at end of file