Google
 

Trailing-Edge - PDP-10 Archives - dec-10-omona-u-mc9 - psiser.mac
There are 7 other files named psiser.mac in the archive. Click here to see a list.
TITLE	PSISER -- PROGRAMMED SOFTWARE INTERRUPT SERVICE  V156
SUBTTL	DONALD LEWINE/DAL  01 MAR 77
	SEARCH	F,S
	$RELOC
	$HIGH
;***COPYRIGHT 1973,1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VPSISR,156

PSISER:	ENTRY	PSISER		;FOR LINK AND GLOB


;               TABLE OF CONTENTS FOR PSISER
;
;
;                        SECTION                                   PAGE
;    1. PROTOTYPE PROGRAM INTERRUPT TABLE.........................   2
;    2. PC POINTER TABLE..........................................   3
;    3. BIT MASKS FOR VARIOUS CONDITIONS..........................   4
;    4. INTERRUPT BLOCK FORMAT....................................   5
;    5. PI SYSTEM UUO'S
;         5.1   PISAV.............................................   6
;         5.2   PIRST.............................................   8
;         5.3   DEBRK.............................................   9
;         5.4   PIINI.............................................  10
;         5.5   PISYS.............................................  11
;         5.6   SUBROUTINES.......................................  12
;    6. ROUTINES TO CAUSE INTERRUPTS
;         6.1   ANY UUO TRAP......................................  19
;         6.2   ARITHMETIC FAULT TRAP.............................  20
;         6.3   KSYS TIME.........................................  21
;         6.4   DEVICE OFF LINE...................................  22
;         6.5   I/O DONE..........................................  23
;         6.6   I/O ERROR AND EOF.................................  25
;         6.7   ERROR IN JOB TRAPS................................  26
;         6.8   DEFERED INTERRUPTS................................  27
;    7. INTERRUPT CODE
;         7.1   SIGNAL AN INTERRUPT...............................  29
;         7.2   SUBROUTINES.......................................  33
;    8. MISC. SUBROUTINES.........................................  39
	SUBTTL	PROTOTYPE PROGRAM INTERRUPT TABLE

;A COPY OF THIS TABLE IS BUILT FOR EACH JOB WHICH USES THE SOFTWARE
; INTERRUPT SYSTEM.

PITPRO:	PHASE	0
PITINS:!JFCL			;THIS INSTRUCTION IS EXECUTED WHENEVER
				; WE ARE ABOUT TO GIVE CONTROL TO THE
				; USER IN USER MODE.
PITIVA::!XWD	ZERO5,0		;BITS 0-8  -- HIGHEST VECTOR IN USE + 1
				;BITS 9-12 -- UNUSED
				;BITS 13-17-- ZERO (I DON'T THINK ANYONE
				;		DEPENDS ON THIS)
				;RH -- INTERRUPT VECTOR BASE ADDRESS
PITNPI:!EXP	0		;NUMBER OF PENDING INTERRUPTS
PITNXT:!EXP	0		;INTERRUPT WE WOULD LIKE TO GRANT
				; NEXT. IF C(LH)=0 THEN THIS IS A
				; DDB ADDRESS ELSE IT IS A CONDITION
				; NAME
PITCIB:!XWD	0,0		;RH - CURRENT INTERRUPT BLOCK ADDRESS
PITIPC:!XWD	0,0		;LH - FLAG USED TO REMEMBER THAT A USER
				;	IS PRINTING AN ERROR MESSAGE
				;RH - ADDRESS WHERE PC WAS FOUND IF WE
				;	ARE AT INTERRUPT LEVEL
PITWJB::!BLOCK	1		;JOB NUMBER DOING WAKE UUO
PITENQ:!BLOCK 1			;ENQ/DEQ REQUEST ID
PITDFR:!BLOCK	<<-C$MIN>/^D36>+1  ;BIT TABLE FOR NON-I/O RELATED INTERRUPTS.
				; BIT N = 1 IF CONDITION -N HAPPENED 
				; WHILE JOB WAS NOT IN CORE.
PITTAB:!BLOCK	<<<-C$MIN+1>+3>/4> ;TABLE OF 9 BIT BYTE ONE FOR EACH NON-I/O
				; CONDITION.
	DEPHASE
PIT4WD==<<.-PITPRO>+3>/4	;SIZE OF PIT IN 4-WORD BLOCKS
PITSIZ==:PIT4WD*4		;SIZE OF PIT IN WORDS


PTMVO:	POINT 9,PITIVA(P1),8	;BYTE POINTER TO HIGHEST VECTOR IN USE
	SUBTTL	PC POINTER TABLE

;THIS TABLE IS EXECUTED TO LOAD THE PC OF THE INTERRUPT INTO T2.
; NOTE: SINCE CONDITIONS ARE NEGATIVE THE TABLE GOES BACKWARDS.

IFE FTVM,<
	DEFINE	GJOBPC,<
	PUSHJ	P,[CAME J,.CPJOB##(P4)
		   SKIPA T2,JOBPC##(R)
		   MOVE T2,.CPPC##(P4)
      		   POPJ	P,]
>>

IFN FTVM,<
	DEFINE	GJOBPC,<
	MOVE	T2,.JDAT+JOBPC##
>>

	SALL
	GJOBPC			;NETWORD TOPOLOGY CHANGE
	GJOBPC			;ENQ/DEQ
	GJOBPC			;REMOTE COMPUTER CONDITION
	MOVE	T2,JOBPD1##(R)	;IPCF
	MOVE	T2,.CPAPC##(P4)	;ADR BREAK
	GJOBPC			;WAKE UUO -- PC IS IN JOB DATA AREA
	GJOBPC			;DETACH & ATTACH
	GJOBPC			;NEW DATASET STATUS
	GJOBPC			;KSYS
	GJOBPC			;EXTERNAL ERROR IN JOB
	MOVE	T2,JOBPD1##(R)	;USER INDUCED ERROR IN JOB
	MOVE	T2,.CPPC##(P4)	;APR CLOCK
	MOVE	T2,JOBPD1##(R)	;NXM TRAP
	MOVE	T2,.CPPC##(P4)	;TRAP TYPE 3
	MOVE	T2,.CPPC##(P4)	;PDL LIST OVER FLOW
	GJOBPC			;ARITHMETIC VIOLATION
	MOVE	T2,JOBPD1##(R)	;ADDRESS CHECK
	MOVE	T2,.CPPC##(P4)	;ILL MEM REF
	MOVE	T2,UUO0##	;ILLEGAL UUO
	MOVE	T2,UUO0##	;ANY UUO
	PUSHJ	P,CTLCPC	;CONTROL-C
	GJOBPC			;CONTROL-A
	MOVE	T2,.CPPC##(P4)	;TIME LIMIT EXCEEDED
OPCXCT:	STOPCD	.,HALT,ICC,	;INVALID CONDIDION CODE
	SUBTTL	BIT MASKS FOR VARIOUS CONDITIONS

	DEFINE	BTMASK(X),<
	ZZ==0
	 IRP X,<
	  ZZ==ZZ!<1B<-C$'X>>
	 >
	EXP	ZZ
	>

;CONDITIONS WHICH HAVE A STANDARD SYSTEM ERROR MESSAGE
ERRMSK:	BTMASK	<TLE,IUUO,IMR,ADCK,PLOV,NXM,UEIJ,XEIJ,ADRB>

;CONDITIONS WHICH ARE IGNORED IF THEY HAPPEN IN THE PAGE FAULT HANDLER
PFHMSK:	BTMASK	<AUUO,IUUO,IMR,ADCK,ARIT,PLOV,TRP3,APRC,UEIJ,XEIJ,ADRB>
	SUBTTL	INTERRUPT BLOCK FORMAT

IBKPRO:	PHASE	0
IBKNPC:!EXP	0		;NEW PC AND FLAGS
IBKOPC:!EXP	0		;OLD PC AND FLAGS
IBKICF:!			;INTERRUPT CONTROL FLAGS
	ICFOFF==(1B1)		;TURN INTERRUPT SYSTEM OFF DO NOT
				; RESTORE ON DEBREAK
	ICFTOF==(1B2)		;TURN INTERRUPT SYSTEM OFF. TURN ON
				; ON DEBREAK
	ICFAAI==(1B3)		;ALLOW ADDITIONAL INTERRUPTS
	ICFCNI==(1B4)		;CLEAR NEXT INTERRUPT
	ICFMSG==(1B5)		;PRINT STANDARD MESSAGE
	ICFNOT==(1B6)		;NO TRAPS -- BLOCK IS TURNED OFF
IBKRSN:!XWD	0,0		;REASON
IBKISW::!EXP	0		;INTERRUPT STATUS WORD
	DEPHASE
	RELOC	IBKPRO		;DO NOT WASTE SPACE
	SUBTTL	PI SYSTEM UUO'S -- PISAV.

PISAVE::PUSHJ	P,SAVE4##	;SAVE P1 THRU P4
	HRR	M,T1		;ARGUMENT ADDRESS
	HLRZ	P3,T1		;# OF WORDS
	MOVEI	P4,0		;# OF CALLS TO STORE
	MOVE	P1,JBTPIA##(J)	;ADDRESS OF PI TABLE
	SOS	P3		;ACCOUNT FOR NOT CALLING
	AOS	P4		; OF FIRST WORD TILL DONE
	PUSH	P,M		;SAVE ADDRESS OF FIRST ARG
	JUMPE	P1,PISAV5	;JUMP IF NOT SETUP
	HRRZ	T1,PITIVA(P1)	;GET INTERRUPT VECTOR ADDRESS
	PUSHJ	P,STORE		;STORE FOR USER
	HLRZ	F,DEVLST##	;TELL HIM ABOUT HIS DDB'S
PISAV1:	LDB	T1,PJOBN##	;GET JOB NUMBER
	CAIE	T1,(J)		;IS IT THIS JOB?
	JRST	PISAV2		;NO--LOOK AT NEXT DDB
	LDB	T1,PDVIVO##	;GET INTERRUPT VECTOR OFFSET
	JUMPE	T1,PISAV2	;LOOK AT NEXT IF NOT ENABLED
	MOVE	T1,DEVNAM(F)	;GET THE DEVICE NAME
	PUSHJ	P,STORE		;STORE FOR USER
	LDB	T1,PDVIVO##	;GET THE OFFSET
	SUBI	T1,1		;ADJUST
	LSH	T1,2		;CONVERT TO WORDS
	HRLZ	T1,T1		;PUT IN LH
	HLR	T1,DEVPSI(F)	;PICK UP INTERRUPT REASON BITS
	AND	T1,[-1,,IR.ALL]	;MASK OUT JUNK
	PUSHJ	P,STORE		;PUT IN USER SPACE
	MOVEI	T1,0		;THIRD WORD IS ZERO
	PUSHJ	P,STORE		;PUT IN USER SPACE
PISAV2:	HLRZ	F,DEVSER(F)	;LINK TO NEXT DDB
	JUMPN	F,PISAV1	;LOOP OVER ALL DEVICES
	HRREI	W,C$MIN		;START WITH SMALLEST COND
PISAV3:	MOVE	T1,W		;COPY CONDITION
	PUSHJ	P,CNDPTR	;GET A POINTER TO IT
	LDB	T2,U		;SEE IF ENABLED?
	JUMPE	T2,PISAV4	;NO--LOOK FOR NEXT CONDITION
	PUSHJ	P,STORE		;YES--STORE CONDITION
	LDB	T1,U		;GET OFFSET
	SUBI	T1,1		;CONVERT TO WORDS
	LSH	T1,2		; ..
	HRLZ	T1,T1		;PUT IN LH AND STORE
	PUSHJ	P,STORE		; ..
	MOVEI	T1,0		;STORE WORD 3 AS ZERO
	PUSHJ	P,STORE		; ..
PISAV4:	AOJL	W,PISAV3	;LOOP OVER ALL CONDITIONS
PISAV5:	POP	P,M		;RESTORE ADDRESS OF FIRST WORD
	MOVE	T1,P4		;GET # OF WORDS
	SKIPGE	P1		;SKIP IF SYSTEM IS OFF
	TLO	T1,(SI.ON)	;ELSE SET THE ON FLAG
	PUSHJ	P,PUTWDU##	;STORE FOR USER
	JUMPL	P3,RTZER##	;ERROR IF BLOCK TO SMALL
	JRST	CPOPJ1##	;ELSE WIN
;SUBROUTINE TO STORE A WORD IF IT WILL FIT
;CALL WITH:
;	T1 = WORD TO STORE
;	M = ADDRESS
;	P3 = NUMBER OF WORDS LEFT
;	P4 = NUMBER OF CALLS
;	PUSHJ	P,STORE
;	RETURN HERE ALWAYS
;
;THIS ROUTINE UPDATES P2, P3 AND P4
STORE:	SOSL	P3		;COUNT DOWN ROOM LEFT
	PUSHJ	P,PUTWD1##	;STORE IF WE CAN
	AOJA	P4,CPOPJ##	;RETURN
	SUBTTL	PI SYSTEM UUO'S -- PIRST.

PIRST::	PUSHJ	P,SAVE3##	;SAVE SOME AC'S
	MOVEI	P2,(T1)		;ADDRESS OF BLOCK
	HRR	M,P2		;GET THE FIRST WORD
	PUSHJ	P,GETWDU##	; ..
	HLL	P2,T1		;SAVE FLAGS
	HRRZ	P3,T1		;WORD COUNT
	SOJE	P3,[PUSHJ P,CLRPSI ;IF PIINI. WAS NOT DONE, CLEAR SYS
		    JRST  CPOPJ1##];AND SKIP RETURN TO THE USER
	PUSHJ	P,GETWD1##	;ELSE GET BASE OF IV
	PUSHJ	P,PIINI		;AND DO PIINI
	  JRST	RTZER##		;FAILED!!
	SOJE	P3,CPOPJ1##	;GOOD RETURN IF THAT IS ALL HE WANTS
	HRRI	P2,1(M)		;ADDRESS OF FIRST TRIPLET
	MOVE	P1,JBTPIA##(J)	;ADDRESS OF PI TABLE
PIRST1:	SUBI	P3,3		;ACCOUNT FOR 1 TRIPLET
	JUMPL	P3,[HLLM P2,JBTPIA##(J)
		    JRST CPOPJ1]	;RESTORE FLAGS AND RETURN
	PUSHJ	P,ADDDEV	;ADD IN DEVICE
	  JRST	[PUSHJ P,CLRPSI	;RESET PI SYSTEM SO NOT LEFT HALF RESTORED
		 PJRST RTZER##]	;GIVE ERROR RETURN
	ADDI	P2,3		;COUNT UP ADDRESS
	JRST	PIRST1		;TRY FOR MORE
	SUBTTL	PI SYSTEM UUO'S -- DEBRK.

DEBRK::	SKIPN	P1,JBTPIA##(J)	;GET ADDRESS OF PI TABLE
	JRST	CPOPJ1##	;NO PI IN PROGRESS IF ZERO
	HRRZ	M,PITCIB(P1)	;GET OLD INTERRUPT ADDRESS
	JUMPE	M,CPOPJ1##	;NO PI IN PROGRESS
IFE FTVM,<
	MOVEI	T1,(M)		;GET FIRST ADDRESS
	PUSHJ	P,UADRCK##	;CHECK LEGALITY, DON'T RETURN IF NOT
	MOVEI	T1,3(M)		;LAST ADDRESS
	PUSHJ	P,UADRCK##	;THE SAME
>	;END IFE FTVM
IFN FTVM,<
	MOVEI	T1,(M)		;COPY ADDRESS
	MOVEI	T2,3(M)		;LAST ADDRESS
	PUSHJ	P,LRNGE##	;CALL PFH OR STOP JOB IF APPROPRIATE
>	;END IFN FTVM
IFN FTKA10,<
	ADDI	M,(R)		;RELOCATE ON KA10
>
	SETZM	PITCIB(P1)	;NOW CLEAR INTR ADDR
	EXCTUX	<MOVE T3,IBKOPC(M)> ;GET OLD PC
	MOVE	T4,JOBPD1##(R)	;GET UUO PC
	TLNN	T4,(XC.UIO)	;DOES HE HAVE USER IOT SET
	TLZ	T3,(XC.UIO)	;NO--CLEAR FROM OLD PC
	TLNE	T4,(XC.PUB)	;OLC PC PUBLIC
	TLO	T3,(XC.PUB)	;YES--NEW PC IS TOO
	TLO	T3,USRMOD	;SET USER MODE
	TLZ	T3,37		;CLEAR INDEX AND @
	MOVEM	T3,JOBPD1##(R)	;STORE BACK FOR USER
	MOVEM	T3,JOBPC##(R)	;FOR GJOBPC
	MOVSI	T3,ICFNOT	;CLEAR PI IN PROGRESS BIT
	EXCTUU	<ANDCAM T3,IBKICF(M)> ; IN THE CONTROL BLOCK
	PUSHJ	P,DFRINT	;LOOK FOR MORE WORK
	SKIPE	PITNXT(P1)	;IS THERE A TRAP PENDING?
	PJRST	UTOUSR		;YES--TRAP HIM
	POPJ	P,		;RETURN TO USER
	SUBTTL	PI SYSTEM UUO'S -- PIINI.

;CALL TO INIT THE PI SYSTEM
;CALL WITH:
;	MOVEI	AC,BASE-ADDRESS-OF-INTERRUPT-VECTOR
;	PIINI.	AC,
;	  HERE IF SYSTEM NOT AVAIL
;	NORMAL RETURN IS HERE
;
PIINI::	MOVEI	T1,(T1)		;CLEAR JUNK FROM LH OF T1
	PUSH	P,T1		;SAVE USER ARGUMENT
	PUSHJ	P,CLRPSI	;CLEAR OLD DATA
	MOVEI	T2,PIT4WD	;NUMBER OF 4-WORD BLOCKS TO GET
	PUSHJ	P,GET4WD##	;GO GET THEM
	  JRST	TPOPJ##		;CAN'T
	HRRZM	T1,JBTPIA##(J)	;ADDRESS OF THE PIT
	MOVSI	T2,PITPRO	;PROTOTYPE PIT
	HRR	T2,T1		;WHERE IT GOES
	BLT	T2,PITSIZ-1(T1)	;MOVE IT OVER
	POP	P,PITIVA(T1)	;BASE OF VECTOR
	JRST	CPOPJ1##	;GOOD RETURN
	SUBTTL	PI SYSTEM UUO'S -- PISYS.

PISYS::	PUSHJ	P,SAVE2##	;SAVE P1 AND P2
	TRNE	T1,-1		;ANY ADDRESS GIVEN?
	TLNE	T1,(PS.CSI!PS.RDV!PS.ADV) ;IS ARGUMENT NEEDED?
	SKIPA			;YES
	PJRST	RTZER##		;(0) UNNECESSARY ARG SUPPLIED
	TLNN	T1,(PS.ALL)	;ANYTHING TO DO?
	PJRST	ECOD1##		;(1) NO FUNCTION GIVEN
	TLNE	T1,<-1-PS.ALL>_<-^D18>	;ANY UNUSED BITS SET?
	PJRST	ECOD2##		;(2) UNUSED BIT IS NOT = 0
	SKIPN	JBTPIA##(J)	;PIINI. UUO DONE?
	JRST	ECOD13##	;(13) PIINI. UUO NOT DONE
	MOVE	P2,T1		;COPY ARGUMENT
	MOVE	P1,JBTPIA##(J)	;PLACE IN AN AC FOR INDEXING
	TLNE	P2,(PS.CPI)	;CLEAR PENDING INTERRUPTS?
	PUSHJ	P,CLRAPI	;YES--CLEAR ALL PENDING INTERRUPTS
	TLNE	P2,(PS.CSI)	;CLEAR FOR 1 CONDITION OR DEVICE?
	JRST	[PUSHJ  P,CLRSPI;YES--CLEAR SELECTED PENDING INTERRUPT
		   POPJ P,
		 JRST .+1]
	MOVSI	P1,(SI.ON)	;PI SYSTEM ON BIT
	TLNE	P2,(PS.ON)	;WANT TO TURN ON?
	JRST	[TLNE  P2,(PS.OFF) ;TURN SYSTEM OFF?
		 JRST  ECOD3##	;(3)BOTH TURN OFF AND TURN ON
		 IORB  P1,JBTPIA##(J) ;LIGHT THE BIT
		 AOS   JOBPD1##(R);MAKE UUO LOOK GOOD
		 SKIPE PITNXT(P1) ;WERE WE WAITING FOR THIS?
		 PUSHJ P,UTOUSR   ;YES--MAKE AN INTERRUPT HAPPEN
		 HRRZ	P1,JOBPD1##(R)  ;CHANGE RETURN
		 SUBI	P1,1	; ADDRESS BACK
		 HRRM	P1,JOBPD1##(R)  ; PRESERVING FLAGS
		 JRST  PISYS1]
	TLNE	P2,(PS.OFF)	;WANT TO TURN OFF?
	ANDCAB	P1,JBTPIA##(J)	;CLEAR THE SYSTEM ON BIT
PISYS1:	MOVE	P1,JBTPIA##(J)	;SETUP PIT ADDRESS
	TLNE	P2,(PS.RDV)	;WANT TO REMOVE DEVICE OR COND?
	PJRST	REMDEV		;YES--GO DO THAT
	TLNE	P2,(PS.ADV)	;WANT TO ADD?
	PJRST	ADDDEV		;YES--GO ADD DEVICE
	JRST	CPOPJ1##	;GOOD RETURN
	SUBTTL	PI SYSTEM UUO'S -- SUBROUTINES

;SUBROUTINE TO CLEAR THE SOFTWARE INTERRUPT SYSTEM
;CALL WITH:
;	J = JOB #
;	PUSHJ	P,CLRPSI
;	RETURN HERE ALWAYS
;
CLRPSI::HRRZ	T2,JBTPIA##(J)	;GET ADDRESS OF PIT
	JUMPE	T2,CPOPJ##	;RETURN IF ZERO
	MOVEI	T1,PIT4WD	;NUMBER OF 4-WORD BLOCKS WE HAVE
	PUSHJ	P,GIV4WD##	;RETURN THE CORE
	HLRZ	F,DEVLST##	;POINTER TO FIRST DDB
	SETZB	T2,JBTPIA##(J)	;CLEAR JOB TABLE
CLPSIL:	LDB	T1,PJOBN##	;PICK UP JOB NUMBER
	CAIN	T1,(J)		;IS THIS ME
	DPB	T2,PDVPSI##	;YES--CLEAR PSI BYTE
	HLRZ	F,DEVSER(F)	;LINK TO NEXT DDB
	JUMPN	F,CLPSIL	;LOOP IF NOT AT END OF LIST
	POPJ	P,0		;RETURN
;SUBROUTINE TO REMOVE A DEVICE OR CONDITION
;CALLED ONLY FROM PISYS UUO WITH:
;	P2 = USERS ARGUMENT
;	P1 = ADDRESS OF PRIORITY INTERRUPT TABLE
;	PUSHJ	P,REMDEV
;	  RETURN HERE ON ERROR
;	RETURN HERE IF OK
;
REMDEV:	TLNE	P2,(PS.ADV)	;ALSO WANT TO ADD DEVICE
	PJRST	ECOD14##	;(14) BOTH ADD AND REMOVE SELECTED
	PUSHJ	P,CHKCND	;CHECK THE CONDITION/DEVICE WORD
	  POPJ	P,0		;INVALID
	  JRST	REMDV1		;DEVICE CODE
	PUSH	P,T1		;SAVE CONDITION
	PUSHJ	P,CLRPND	;CLEAR PENDING INTERRUPT IF ANY
	POP	P,T1		;RETURN T1
	PUSHJ	P,CNDPTR	;GET A BYTE POINTER TO FIELD
	MOVEI	T2,0		;STORE THE FIELD
	DPB	T2,U		; AS ZERO
	JRST	CPOPJ1##	;GOOD RETURN
REMDV1:	PUSHJ	P,CLRPND	;CLEAR ANY PENDING INTERRUPTS
	MOVEI	T1,0		;CLEAR THE INTERRUPT BYTE
	DPB	T1,PDVPSI##	; IN THE DDB
	JRST	CPOPJ1##	;GOOD RETURN
;SUBROUTINE TO ADD A DEVICE OR CONDITION
;CALLED FROM PISYS. UUO WITH:
;	P1 = ADDRESS OF PROGRAM INTERRUPT TABLE
;	P2 = USERS ARG POINTER
;	PUSHJ	P,ADDDEV
;	  RETURN HERE ON ERROR
;	RETURN HERE IF ALL IS OK
;
ADDDEV:	PUSHJ	P,CHKCND	;GO CHECK OUT ARGUMENT
	  POPJ	P,0		;INVALID DEVICE OR CONDITION
	  JRST	ADDDDB		;HE WANTS TO ADD A DDB
	PUSHJ	P,CNDPTR	;GET A CONDITION POINTER INTO U
	TDZA	F,F		;CLEAR F AND DO REST OF CALL
ADDDDB:	MOVE	U,PDVIVO##	;BYTE POINTER TO INTERRUPT VECTOR OFFSET
	HRRI	M,1(P2)		;GET THE VECTOR OFFSET WORD
	PUSHJ	P,GETWDU##	; ..
	MOVEI	T2,-1		;ASSUME CONDITION
	SKIPE	F		;ARE WE RIGHT?
	MOVEI	T2,-1-IR.ALL	;NO--LOAD BITS FOR INVALID REASONS
	TRNE	T1,(T2)		;ANY BITS SET
	PJRST	ECOD10##	;(10) UNIMPLEMENTED BIT IS ON
	SKIPE	F		;SKIP IF CONDITION NOT DEVICE
	HRLZM	T1,DEVPSI(F)	;DEVICE STORE REASON BITS
	HLRZ	T1,T1		;PUT VALUE IN RH
	CAMG	T1,CNFMVO##	;IS VALUE TOO BIG?
	TRNE	T1,3		;IS HE CONFUSED?
	PJRST	ECOD7##		;(07)BAD VECTOR OFFSET
IFN FTVM,<
	MOVEI	T2,(T1)		;SAVE ADDRESS OF BLOCK
>
	LSH	T1,-2		;SHIFT OFF ZERO BITS
	ADDI	T1,1		;ADJUST SO ZERO IS A VALID OFFSET
	DPB	T1,U		;STORE OFFSET
	LDB	T3,PTMVO	;GET MAXIMUM VECTOR OFFSET THUS FAR
	CAIGE	T3,(T1)		;GREATER THAN THIS ONE?
	DPB	T1,PTMVO	;NO, SAVE THE GREATEST
IFN FTVM,<
	HRRZ	T1,PITIVA(P1)	;GET USER BASE ADDRESS FOR VECTOR
	ADDI	T1,(T2)		;RELOCATE TO BEGINNING OF THIS BLOCK
	MOVEI	T2,3(T1)	;POINT T2 TO END OF THIS BLOCK
	PUSHJ	P,TRNGE##	;CALL PFH IF BLOCK IS PAGED OUT
>
	PUSHJ	P,GETWD1##	;GET NEXT WORD
	TLNE	T1,-1		;IS PRIORITY TOO BIG
	PJRST	ECOD11##	;(11) PROIRITY IS TOO BIG
	TRNE	T1,-1		;IS RESERVED HALF WORD NON-ZERO
	PJRST	ECOD12##	;(12) RESERVED HALFWORD IN NON-ZERO
IFN FTKI10!FTKL10,<
	PUSHJ	P,APPSI		;GO SET UP TRAP INSTRUCTIONS
>
	PJRST	CPOPJ1##	;GOOD RETURN
;SUBROUTINE TO CLEAR ALL PENDING INTERRUPTS
;CALLED FROM PISYS UUO WITH:
;	P1 = ADDRESS OF PIT
;	PUSHJ	P,CLRAPI
;	RETURN HERE
CLRAPI:	HLRZ	F,DEVLST##	;GET POINTER TO FIRST DDB
CLAPIL:	LDB	T1,PJOBN##	;GET OWNERS JOB NUMBER
	CAIE	T1,(J)		;SKIP IF THIS JOB OWNS THE DEVICE
	JRST	CLAPIN		;NO--LOOK AT THE NEXT DEVICE
	HLLZS	DEVPSI(F)
CLAPIN:	HLRZ	F,DEVSER(F)	;STEP TO NEXT DDB
	JUMPN	F,CLAPIL	;LOOP OVER ALL DDB'S
	SETZM	PITDFR(P1)	;CLEAR ALL THE PENDING BITS
	SETZM	PITNXT(P1)	;CLEAR NEXT INTERRUPT FLAG
	SETZM	PITNPI(P1)	;NO PENDING INTERRUPTS
	POPJ	P,0		;RETURN
;SUBROUTINE TO SET KI10 TRAP 1 INSTRUCTION
; RESPECTS	T1
IFN FTKI10!FTKL10,<
APPSI::	HRRZ	T2,JBTPIA##(J)	;GET ADDRESS OF PI TABLE
	JUMPE	T2,CPOPJ##	;EXIT IF NONE
	LDB  	T2,[POINT 9,PITTAB+2(T2),8] ;GET BYTE FOR TRAP 1
	JUMPE	T2,CPOPJ##	;EXIT IF NOT ENABLED
	MOVEI	T2,APRTRP	;WHERE TO GO ON AN APR TRAP
	MOVEM	T2,.UPMP+.UPAOT	;STORE IN UPMP
	POPJ 	P,0		;RETURN
> ;END FTKI10
;SUBROUTINE TO CLEAR SELECTED PENDING INTERRUPTS
;CALLED FROM PISYS UUO WITH:
;	PUSHJ	P,CLRSPI
;	  RETURN HERE ON ERROR
;	RETURN HERE IF OK
;
CLRSPI:	PUSHJ	P,CHKCND	;CHECK THE CONDITION WORD
	  POPJ	P,0		;INVALID
	  MOVE	T1,DEVNAM(F)	;DEVICE PICK UP DEVICE NAME
	PUSHJ	P,CLRPND	;CLEAR PENDING INTERRUPT
	JRST	CPOPJ1##	;SKIP RETURN
;SUBROUTINE TO FETCH AND VALIDATE THE DEVICE OR CONDITION GIVEN BY THE USER
;CALLED WITH:
;	P2 = USER ARGUMENT
;	PUSHJ	P,CHKCND
;	  RETURN HERE IF THE CONDITION IS INVALID
;	  RETURN HERE IF A DEVICE WAS SPECIFIED
;	RETURN HERE IF A CONDITION WAS SPECIFIED
;
;UPON RETURN F=ADDRESS OF DDB (IF DEVICE)
;	T1 = CONDITION NUMBER (IF CONDITION)
;
CHKCND:	HRR	M,P2		;ADDRESS OF WORD
	PUSHJ	P,GETWDU##	;GET THE WORD
	HLRE	T2,T1		;IF CONDITION T2 NOW = -1
	AOJE	T2,CHKCN1	;SO IF T2+1=0 WE HAVE A CONDITION
	PUSHJ	P,DVCNSG##	;ELSE LOOK FOR A DEVICE
	  JRST	ECOD4##		;(4) NOT A DEVICE
	HRRZ	T2,TTYTAB##(J)	;GET ADDRESS OF THIS JOBS TTY DDB
	CAIN	T2,(F)		;SKIP IF THIS IS NOT HIS TTY
	PJRST	CPOPJ1##	;GOOD RETURN
	LDB	T2,PJOBN##	;GET NAME OF OWNER
	MOVEI	T3,ASSPRG	;SEE IF DEVICE IS
	TDNE	T3,DEVMOD(F)	; OPEN FOR 
	CAIE	T2,(J)		; THIS JOB.
	PJRST	ECOD5##		;(5) OR NOT OPEND BY THIS JOB
	JRST	CPOPJ1##	;SKIP RETURN

CHKCN1:	CAMGE	T1,[C$MIN]	;SKIP IF CODE IS NOT TOO SMALL
	PJRST	ECOD4##		;(4) OR CONDITION CODE TOO SMALL
	JRST	CPOPJ2##	;DOUBLE SKIP
				; RETURN
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- ANY UUO TRAP

;SUBROUTINE CALLED FROM UUOCON ON EVERY UUO
;CALL WITH:
;	PUSHJ	P,ANYUUO
;	  RETURN HERE IF UUO IS TO BE PERFORMED
;	RETURN HERE TO ABORT UUO AND INTERRUPT
;
;RESPECTS ALL AC'S INVLOVED IN UUO DISPATCH
;
ANYUUO::SKIPL	T3,JBTPIA##(J)	;IS HE ENABLED?
	POPJ	P,0		;NO--RETURN QUICKLY
	LDB	T3,[POINT 9,PITTAB+1(T3),8] ;ANY UUO BYTE
	JUMPE	T3,CPOPJ##	;RETURN IF HE DOES NOT WANT TO
				; TRAP EVERY UUO.
IFN FTMS,<
	PUSHJ	P,ONCPU0##	;MUST USE CPU0
>
	PUSHJ	P,SAVE2##	;HE WANTS TO TRAP EVERY UUO SO WE
				; CAN AFFORD TO BE SLOW.
	MOVE	P1,M		;COPY UUO
	TLZ	P1,777		;CLEAR JUNK
	CAMN	P1,[CALLI 137]	;IF THIS IS A DEBRK. DO NOT TRAP SINCE WE
	POPJ	P,0		; CAN NOT DO THIS UUO FOR THE USER.
	MOVE	P1,M		;SAVE M
	MOVE	P2,T1		;SAVE T1
	HRREI	T1,C$AUUO	;FLAG AS ANY UUO
	PUSHJ	P,PSISIG	;GO TRY TO INTERRUPT
	  JRST	AUUO1		;WANTS TO INTERRUPT
	MOVE	M,P1		;RESTORE M
	MOVE	T1,P2		;RESTORE P2
	POPJ	P,0		;RETURN
AUUO1:	TLZ	P1,37		;REMOVE R
	EXCTUU	<MOVEM P1,IBKISW(M)> ;STORE UUO FOR USER TO SEE
	JRST	CPOPJ1##	;SKIP DISPATCH
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- ARITHMETIC FAULT TRAP

;HERE ON ARITHMETIC OVERFLOW
IFN FTKI10!FTKL10,<
APRTRP:	MOVE	P,[MJOBPD##,,.JDAT+JOBPDL##]
	PUSHJ	P,CPUCDB##
	MOVE	J,.CPJOB##(P4)
	MOVE	R,JBTADR##(J)	;EVA OF JOB DATA AREA
	MOVE	T1,.UPMP+.UPMUP	;FETCH PC
	MOVEM	T1,.CPPC##(P4)	;STORE PC WHERE PSISIG WILL FIND IT
IFN FTVM,<
	MOVEM	T1,.JDAT+JOBPC##
>
	SIGNAL	C$ARIT		;SIGNAL AROV
	 JFCL			;DON'T CARE
	JEN	@.CPPC##(P4)	;RETURN TO USER
> ;END FTKI10
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- KSYS TIME

PSIKSY::MOVE	J,HIGHJB##	;GET TOP JOB NUMBER
	MOVE	T3,SYSKTM##	;GET KSYS TIME
KSYSLP:	SIGNAL	C$KSYS		;SIGNAL KSYS
	  EXCTUU <MOVEM T3,IBKISW(M)>
	SOJG	J,KSYSLP	;LOOP OVER ALL JOBS
	POPJ	P,0		;RETURN

;HERE TO SIGNAL NETWORK TOPOLOGY CHANGE
IFN FTNET,<
PSINTC::MOVE	T2,J		;SAVE J FOR NETSER
	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER
NTCLUP:	SIGNAL	C$NTC		;SIGNAL NETWORK TOPOLOGY CHANGE
	  JFCL			;NO STATUS TO STORE
	SOJG	J,NTCLUP	;LOOP OVER ALL JOBS
	MOVE	J,T2
	POPJ	P,		;RETURN
>
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- DEVICE OFF LINE

;SUBROUTINE TO CAUSE AN INTERRUPT FOR AN OFF LINE DEVICE
;CALL WITH:
;	F = DDB
;	PUSHJ	P,PSIHNG
;	  HERE TO GO TO USER  (T3 NEGATIVE IF USER WANTS MESSAGE)
;	HERE IF USER NOT ENABLED
;
PSIHNG::PUSHJ	P,SAVE4##	; ..
	MOVEI	T1,IR.DOL	;SET BIT FOR DEVICE OFF LINE
	PUSHJ	P,PSIDEV	;SIGNAL DEVICE CONDITION
	SKIPL	T3,T1		;SKIP IF ENABLED
	JRST	CPOPJ1##	;NOT
	AOJA	T3,CPOPJ##	;ENABLED--NON-SKIP T3.LT.0IF MSG

;SUBROUTINE TO CAUSE AN INTERRUPT FOR A DOWN DEVICE
;CALL WITH:
;	F = DDB
;	PUSHJ	P,PSIDWN
;	ALWAYS RETURN HERE
;
PSIDWN::PUSHJ	P,SAVT##	;SAVE T1-T4
	MOVEI	T1,IR.IER!IR.OER!IR.DOL	;INPUT ERROR, OUTPUT ERROR, OFF-LINE
	PJRST	PIIDX0		;SIGNAL THE INTERRUPT

;SUBROUTINE TO CAUSE AN INTERRUPT WHEN A DEVICE COMES ON-LINE
;CALL WITH:
;	F=DDB
;	PUSHJ	P,PSIONL
;	ALWAYS RETURN HERE
;
PSIONL::PUSHJ	P,SAVT##	;SAVE T1-T4
	MOVEI	T1,IR.ONL	;DEVICE ON-LINE
	PJRST	PIIDX0		;SIGNAL THE INTERRUPT
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- I/O DONE

;HERE FROM CLOCK1 ON CALL TO SETIOD
PSIIOD::PUSHJ	P,SAVT##	;SAVE T1 THRU T4
	MOVEI	T1,0		;COMPUTE CONDITION BASED ON S
PIIDX0:	PUSHJ	P,SAVE4##	;SAVE P1 THRU P4
IFN FTKI10!FTKL10,<
	HRRZ	T2,P		;IF NOT AT UUO LEVEL
	CAMGE	T2,SYSSIZ##	; (A PTY),
	PUSHJ	P,SVEUF##	; SAVE UBR/EBR VIA F
>
PSIDEV:	PUSH	P,J		;SAVE J
	PUSH	P,M		;SAVE M
	PUSH	P,F
	HLRZ	T2,DEVPSI(F)	;IS THIS DEVICE ENABLED?
IFN FTMSGSER,<
	JUMPE	T2,[MOVEI T2,DEPMSG ;NO--IS IT CONTROLED BY MSGSER?
		 TDNN  T2,DEVMSG(F) ; ..
		 JRST  PIIDX2	;NO--PUNT NOW
		 HRRZ  F,DEVXTR(F) ;YES--STEP TO MPX DDB
		 JRST  .+1]	;CONTINUE
> ;END FTMSGSER
	JUMPN	T1,PIDEV1
	TLNN	S,IO		;SKIP IF DEVICE IS DOING OUTPUT
	TROA	T1,IR.IND	;LOAD UP INPUT BIT
	MOVEI	T1,IR.OUD	;LOAD UP OUTPUT BIT
PIDEV1:	TSNN	T1,DEVPSI(F)	;ENABLED?
	JRST	PIIDX2		;NO
	PUSH	P,T1		;SAVE T1 (POSITIVE NUMBER)
	LDB	J,PJOBN##	;SET UP JOB NUMBER
	SKIPN	P1,JBTPIA##(J)	;DOES USER HAVE PSISER ENABLED
	JRST	PIIDX1		;NO--EXIT NOW
	SKIPE	T2,JBTADR##(J)	;ADDRESS OF JOBDAT
	PUSHJ	P,JSRPC		;GET CORRECT PC
	PUSHJ	P,PISIG1	;GO SIGNAL THE INTERRUPT
	  SKIPA	T1,(P)		;INTERRUPT GRANTED (REMEMBER REASON)
	JRST	PIIDX1		;INTERRUPT REFUSED
	EXCTUU	<IORM T1,IBKRSN(M)> ;STORE REASON WORD
IFN FTMSGSER,<
	HRRZ	F,-1(P)
>
	PUSHJ	P,PSIUDX	;STORE UDX AND DEVICE STATUS FOR USER
	HRROS	(P)		;T1.LT.0 TO TELL CALLER INTERRUPT WAS GRANTED
	MOVSI	T1,ICFMSG	;USER WANTS STANDARD ERROR MESSAGE BIT
	EXCTUX	<TDNE T1,IBKICF(M)>  ;DOES HE WANT THE MESSAGE?
	SETOM	(P)		;YES, INDICATE THAT TO THE CALLER
PIIDX1:	POP	P,T1		;RESTORE T1
PIIDX2:	POP	P,F
	POP	P,M		;RESTORE M
	JRST	JPOPJ##		;RESTORE J AND RETURN
;SUBROUTINE TO FIND CORRECT PC FOR IO DONE INTERRUPT
;CALL WITH:
;	MOVE	T2,JBTADR##(J)		;****NOTE THE AC USED****
;	PUSHJ	P,JSRPC
;	RETURN HERE (PC IS IN T2)
;
JSRPC:	MOVE	T2,JOBPC##(T2)	;GET THE PC FROM JOBDAT
IFN FTMS,<
	SKIPN	.C0ISF##	;JOBPC IS ALWAYS RIGHT IF IN THE SCHEDULER
>
	CAME	J,.C0JOB##	;IS HE RUNNING NOW?
	POPJ	P,0		;NO--RETURN
	MOVE	T2,JBTADR##(J)	;RESTORE JOB'S ADDRESS
	MOVE	T2,JOBPD1##(T2)	;CURRENT JOB, (GET HIS PC)
	CONSO	PI,PI.IPA-PI.IP7  ;A PI IN PROGRESS?
	POPJ	P,		;NO--RETURN
	CONI	PI,T3		;GET PI STATUS
	ANDI	T3,PI.IPA	;JUST GET THE PI BITS
	LSH	T3,^D20		;POSITION SO IP.PI1 IS BIT 1
JSRPC1:	JFFO	T3,JSRPC2	;T4 = OUR PI LEVEL
	MOVEI	T2,0		;NO USER MODE PC STORED BY INTERRUPT
	POPJ	P,0		;RETURN WITH PC HAVING USRMOD=0
JSRPC2:	ANDCM	T3,BITTBL##(T4)	;CLEAR THE BIT JFFO FOUND
	LSH	T4,1		;MAKE *2
	ADDI	T4,40		;BASE OF INTERRUPT VECTOR
	HLRZ	T2,(T4)		;GET THE INSTRUCTION
	CAIE	T2,(JSR)	;IF NOT A JSR THIS MUST HAVE BEEN A
	AOS	T4		; BLKI/BLKO ADVANCE TO 40+2*N+1
	MOVEI	T4,@(T4)	;GET THE EFFECTIVE ADDRESS OF THE JSR
	MOVE	T2,(T4)		;GET OLD PC
	TLNN	T2,USRMOD	;STORED FROM USER?
	JRST	JSRPC1		;NO--KEEP LOOKING AT LOWER PI LEVELS
	HRRM	T4,PITIPC(P1)	;REMEMBER WHERE WE FOUND THIS PC
	POPJ	P,0		;RETURN -- T2 IS PC STORED BY JSR
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- I/O ERROR AND EOF

;HERE JUST BEFORE AN INPUT OR OUTPUT RETURNS TO THE USER
PSIEDN::TLNN	S,IO		;SKIP IF OUTPUT
PSIIDN::SKIPA	T1,[IR.IER]	;INPUT ERROR
PSIODN::MOVEI	T1,IR.OER	;OUTPUT ERROR
	TRNE	S,IODEND	;END OF FILE?
	TRO	T1,IR.EOF	;YES--FLAG THAT CONDITION
	TRNN	S,740000	;ANY ERRORS?
	TRZ	T1,IR.IER!IR.OER;NO--DO NOT SIGNAL ERROR
	JUMPE	T1,CPOPJ##	;EXIT IF NOTHING HAPPENED
	MOVE	T2,JOBPD1##(R)	;LOAD THE PC
	PUSHJ	P,PSISIG	;SIGNAL THE INTERRUPT
	  PUSHJ	P,PSIUDX	;STORE UDX AND DEVICE STATUS
	POPJ	P,0		;RETURN
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- ERROR IN JOB TRAPS

;SUBROUTINE TO PROCESS EXTERNAL ERROR IN JOB INTERRUPTS
;CALL WITH:
;	PUSHJ	P,EXTEIJ
;	RETURN HERE TO PRINT MESSAGE
;	
EXTEIJ::HRREI	T1,C$XEIJ	;EXTERNAL ERROR IN JOB
	PUSHJ	P,PSISIG	;GO SIGNAL CONDITION
	  JRST	ERRGOU##	;WANTS THE TRAP
	POPJ	P,0		;DOES NOT WANT TRAP


;SUBROUTINE TO CAUSE A USER INDUCED ERROR IN JOB INTERRUPT
;CALL WITH:
;	PUSHJ	P,USREIJ
;	  RETURN HERE TO INTERRUPT
;	RETURN HERE TO STOP THE JOB
USREIJ::MOVE	T1,ERRMSK	;IS THE USER ABOUT TO GET A BETTER
	SKIPE	T2,JBTPIA##(J)	; ERROR INTERCEPT
	TDNE	T1,PITDFR(T2)	; ..
	JRST	CPOPJ1##	;YES--DO NOT GIVE 2 INTERRUPTS
	SIGNAL	C$UEIJ		;SIGNAL THE CONDITION
	  POPJ	P,0		;ENABLED
	JRST	CPOPJ1##	;NOT ENABLED
	SUBTTL	ROUTINES TO CAUSE INTERRUPTS -- DEFERED INTERRUPTS

;SUBROUTINE CALLED WHEN USER IS ABOUT TO ENTER USER MODE AND SOMETHING
;  OF INTEREST HAPPENED SINCE HE WAS IN CORE LAST
;
DFRINT:
IFN FTMS,<
	HRRZ	T1,P		;RH(PDL)
	CAMLE	T1,SYSSIZ##	;AT UUO LEVEL?
	PUSHJ	P,ONCPU0##	;YES, MUST BE ON CPU0
	SKPCPU	(0)		;MUST BE ON CPU0 SINCE IF NOT AN
	POPJ	P,		; INTERRUPT COULD BE BEING SIGNALED ON
				; CPU0 WHILE THIS CODE IS BEING EXECUTED ON CPU1
>
	PUSHJ	P,SAVE4##	;SAVE P1 - P4
	PUSHJ	P,CPUSET##	;SETUP J AND P4
	SKIPN	P1,JBTPIA##(J)	;PICK UP PIT ADDRESS
	POPJ	P,0		;NOT ENABLED OR NULL JOB
	MOVSI	T1,(JFCL)	;CLEAR THE INTERRUPT INSTRUCTION
	MOVEM	T1,PITINS(P1)	; ..
	SKIPE	PITCIB(P1)	;ANY PI IN PROGRESS
	POPJ	P,0		;YES -- WAIT FOR DEBRK.
DFRLP:	SKIPN	T1,PITDFR(P1)	;ANY DEFERED INTERRUPTS?
	JRST	DFRDEV		;NO--LOOK FOR A DDB
	JFFO	T1,.+1		;FIND A CONDITION
	MOVN	T1,T2		;SETUP NEGATIVE CONDITION NUMBER
	MOVSI	T2,(1B0)	;SETUP TO CLEAR THE BIT
	LSH	T2,(T1)		; ..
	ANDCAM	T2,PITDFR(P1)	;CLEAR THE DEFFERED INTERRUPT BIT
	PUSHJ	P,GETDPC	;GET JOB'S PC
	PUSHJ	P,DFRSIG	;SIGNAL INTERRUPT
	  SKIPA	T2,PITWJB(P1)	;INTERRUPT GRANTED, GET JOB DOING WAKE
	JRST	DFRLP		;TRY NEXT CONDITION
	CAMN	T1,[C$WAKE]	;WAS IT A WAKE INTERRUPT?
	EXCTUU	<MOVEM T2,IBKISW(M)> ;YES--STORE STATUS
	MOVE	T2,TTYTAB##(J)	;ADDRESS OF TTY DDB
	HRRZ	T2,DDBLDB##(T2)	;ADDRESS OF TTY LDB
	SKIPE	T2		;SKIP IF DETACHED
	SKIPA	T2,LDBDCH##(T2)	;ELSE GET TTY NUMBER
	SOSA	T2		;DETACHED USE -1
	ANDI	T2,777		;ATTACHED USE TTY NUMBER
	CAMN	T1,[C$DATT]	;ATTACH/DETACH INTERRUPT?
	EXCTUU	<MOVEM T2,IBKISW(M)> ;YES--STORE STATUS
	MOVE	T2,SYSKTM##	;GET TIME TO KSYS
	CAMN	T1,[C$KSYS]	;IS IT KSYS?
	EXCTUU	<MOVEM T2,IBKISW(M)> ;YES--STORE STATUS
	MOVE	T2,PITENQ(P1)
	CAMN	T1,[C$QUE]
	EXCTUU	<MOVEM	T2,IBKISW(M)>
IFN FTIPCF,<
	CAMN	T1,[C$IPC]	;IPC SIGNALING?
	PJRST	STRSIG##	;YES, STORE THE REASON WORD
>
	POPJ	P,0		;RETURN
;HERE TO LOOK FOR DEFERED DEVICE INTERRUPTS
DFRDEV:	HLRZ	F,DEVLST##	;POINTER TO FIRST DDB
DFRDV1:	LDB	T1,PJOBN##	;GET JOB NUMBER
	CAIE	T1,(J)		;IS THIS FOR US?
	JRST	DFRDVX		;NO--LOOK AT THE NEXT DDB
	HRRZ	T1,DEVPSI(F)	;GET DEFERED BIT MASK
	JUMPE	T1,DFRDVX	;NOTHING HERE IF ZERO
	ANDCAM	T1,DEVPSI(F)	;CLEAR DEFERED BITS
	PUSHJ	P,GETDPC	;GET CURRENT PC
	PUSHJ	P,DFRSIG	;SIGNAL INTERRUPT
	  SKIPA			;GRANTED
	JRST	DFRDVX		;REFUSED
	EXCTUU	<IORM T1,IBKRSN(M)> ;STORE REASON
	PJRST	PSIUDX		;STORE THE UDX AND STATUS
DFRDVX:	HLRZ	F,DEVSER(F)	;STEP TO NEXT DDB
	JUMPN	F,DFRDV1	;LOOP FOR MORE
	POPJ	P,0		;EXIT

;SUBROUTINE TO FIND THE PC FOR A DEFERRED INTERRUPT
GETDPC:	HRRZ	T2,-6(P)	;PC OF CALLER TO DFRINT
	CAIE	T2,CIPPSI##	;FROM THE CONTEXT SWITCHER?
	SKIPA	T2,JOBPD1##(R)	;NO, UUOXIT, GET UUO PC
	GJOBPC			;YES, GET PC AT CONTEXT SWITCH
	POPJ	P,		; AND RETURN
	SUBTTL	INTERRUPT CODE -- SIGNAL AN INTERRUPT

;SUBROUTINE TO REQUEST AN INTERRUPT.
;CALLED WHEN A CONDITION REQUIRING AN INTERRUPT IS DETECTED WITH:
;	J = JOB NUMBER
;	SIGNAL(COND)
;	  HERE IF USER WILL BE INTERRUPTED
;	HERE IF USER IS NOT ENABLED
;
;	- OR -
;
;	J = JOB NUMBER
;	F = DDB ADDRESS OF DEVICE
;	SIGNAL(REASON BIT)
;	  HERE IF USER WILL BE INTERRUPTED
;	HERE IF USER IS NOT ENABLED
;
;UPPON RETURN 'M' IS SETUP TO BE THE ADDRESS OF WORD 0 IN THE USERS
; 4-WORD INTERRUPT BLOCK. IF THIS IS A KA10 THIS ADDRESS IS RELOCATED
; AND CAN BE ACCESSED DIRECTLY.  IF THIS IS A KI10 THIS IS A USER
; ADDRESS AND AN EXECUTIVE EXECUTE MUST BE USED.
;
;AC USAGE:
;	BECAUSE OF THE NUMBER OF PLACES WHICH MAY WANT TO SIGNAL CONDITIONS
;	ALL AC'S ARE PRESERVED EXCEPT T1 WHICH IS WIPED OUT IN THE SIGNAL
;	MACRO AND M WHICH RETURNS A VALUE.

;NOTE: ON DEVICE CONDITIONS T2 CONTAINS THE OLD PC
PSISIG::PUSHJ	P,PISIG0	;DO THE SIGNAL
	  PJRST	SVEUB##		;ENABLED--SAVE UBR
	JRST	CPOPJ1##	;GOOD RETURN
PISIG0::PUSHJ	P,SAVT##	;SAVE T1-T3
	PUSHJ	P,SAVE4##	;SAVE P1 - P4

;HERE IF YOU DO NOT NEED ANYTHING SAVED
PISIG1::CAMG	J,HIGHJB##	;J OK?
	SKIPN	P1,JBTPIA##(J)	;SETUP P1 AS ADDRESS OF PRIORITY INTERRUPT
				; TABLE
	PJRST	CPOPJ1##	;NOT ENABLED
;FALL THROUGH TO NEXT PAGE
	CAMN	T1,[C$QUE]	;ENQ/DEQ CALL?
	IORM	T2,PITENQ(P1)	;YES--SAVE STATUS
	SKIPGE	T3,JBTSTS##(J)	;IN CONTROL-C STATE?
	TLNE	T3,SWP		;IS THIS JOB IN CORE?
	JRST	SIGDFR		;NO--MUST BE SOMETHING LIKE DISK OFF LINE
	PUSHJ	P,CPUCDB##
	HRRZ	T3,P
	CAMG	T3,SYSSIZ##	;STACK OK?
	JRST	PISIG2		;YES, GO NOW
	CAME	J,.CPJOB##(P4)	;NO--CURRENT JOB?
	PJRST	SIGDFR		;NO--DEFER THE TRAP

PISIG2:	IFN	FTKI10!FTKL10,<	;IS THIS A KI?
	PUSHJ	P,SVEUB##	;YES--SAVE UBR
>;END FTKI10
	PUSHJ	P,SAVR##	;DO NOT CLOBBER R!
	MOVE	R,JBTADR##(J)	;MAKE SURE R POINTS TO JOBDATA AREA
	SKIPGE	T1		;SKIP IF DEVICE CONDITION
	XCT	OPCXCT(T1)	;PUT OLD PC IN T2
DFRSIG:	MOVSI	P3,USRMOD	;SAVE THE USER MODE BIT FROM THE ORIGINAL
	AND	P3,T2		; OLD PC
	CONSZ	PI,PI.IPA-PI.IP7  ;A PI IN PROGRESS?
	JUMPE	P3,SIGDFR	;YES, CAN'T FIND THE USER'S PC IF PC IS IN EXEC MODE
	TLNN	T2,USRMOD	;IS THIS IN USER MODE?
	MOVE	T2,JOBPD1##(R)	;NO--GET UUO PC
IFN FTVM,<
	CAMN	T2,[EXP IC.UOU+TIMFLT##]  ;SEE IF HIDDEN IN UPMP
	MOVE	T2,.UPMP+.UPTMC	;YES--VM MAKES LIFE SO EASY
> ;END FTVM
	TLNN	T2,USRMOD	;IS PC IN USER MODE?
	JRST	CPOPJ1##	;NO USER PC. MUST BE IO DONE FROM FIN
				; COMMAND OR SIMILAR HAPPENING. JUST
				; IGNORE THE INTERRUPT.

	PUSHJ	P,ISPFH		;ARE WE IN USER PAGE FAULT ROUTINE
	  SKIPA T3,[1B0]	;YES--SEE IF WE SHOULD IGNORE THIS TRAP
	JRST	SIG05		;NO--CHARGE AHEAD
	LSH	T3,(T1)		;SHOULD WE IGNORE CONDITION BECAUSE
	TDNE	T3,PFHMSK	; WE ARE IN PFH OR DDT?
	JRST	CPOPJ1##	;YES--FLUSH TRAP
	TLO	P3,(1B0)	;SET 1B0 OF P3 AS A FLAG
;AT THIS POINT, T1=CONDITION OR REASON, T2=OLD PC AND P1=PIT ADDRESS
; IF WE HAVE VM P3.GE.0 FOR NORMAL CASE AND .LT.0 IF INTERRUPT IS TO BE
; HELD TILL EXIT FROM USER PAGE FAULT HANDLER OR DDT

SIG05:	MOVE	P2,T2		;SAVE PC IN PRESERVED AC
	PUSHJ	P,BLKADR	;GET THE ADDRESS OF THE BLOCK
	  JRST	CPOPJ1##	;INVALID ADDRESS
	JUMPL	T1,SIG10	;IS THIS A DEVICE CONDITION?
	TSNN	T1,DEVPSI(F)	;YES--IS USER ENABLED?
	PJRST	CPOPJ1##	;NO--DO NOT TRAP
SIG10:	SKIPN	PITCIB(P1)	;IF WE ARE SERVICING A TRAP NOW OR
	SKIPE	PITNPI(P1)	; WAITING FOR ONE TO HAPPEN, MAKE
	JRST	SIG15		; THIS TRAP STAY PENDING.
	MOVSI	T2,ICFNOT	;TRAP IN PROGRESS BIT
	EXCTUX	<TDNN T2,IBKICF(M)>	;SKIP IF BLOCK IS IN USE
	JRST	SIG20		;NOT IN USE
SIG15:	MOVSI	T2,ICFCNI	;DOES HE WANT THE NEXT INTERRUPT
	EXCTUX	<TDNE T2,IBKICF(M)>	; TO BE CLEARED?
	PJRST	CPOPJ1##		;YES--GO CLEAR IT
	PJRST	SETPND		;NO--CAUSE THIS INTERRUPT TO STAY PENDING
SIG20:	SKIPL	T1		;SKIP IF NOT A DEVICE CONDITION
	EXCTUU	<IORM T1,IBKRSN(M)>	;STORE REASON IN BLOCK
	MOVSI	T2,ICFAAI	;ALLOW ADDITIONAL INTERRUPTS BIT
	MOVSI	T3,ICFNOT	;NO TRAP BIT
	EXCTUX	<TDNN T2,IBKICF(M)>	;DOES HE WANT THE INTERRUPTS?
	EXCTUU	<IORM T3,IBKICF(M)>	;NO--SET THE PI IN PROGRESS FLAG
;FALL THROUGH TO NEXT PAGE
;HERE WHEN INTERRUPT IS READY TO HAPPEN. WE HAVE TO GET THE USER TO
; RUN.
	JUMPGE	T1,SIG30	;JUMP IF IT IS A DDB ADDRESS
	CAMGE	T1,[C$MIN]	;SKIP IF IT IS RIGHT SIZE FOR COND
	JRST	SIG30		;NO--IGNORE MESSAGE IDEA
IFN FTTIME,<
	CAME	T1,[C$TLE]	;TIME LIMIT EXCEEDED?
	JRST	SIG35		;NO
	MOVE	T1,J		;YES
	PUSHJ	P,JOBTMM##	;STATUS IS USERS RUN TIME
	MOVE	T2,T1
	SKIPA	T1,[C$TLE]	;RESTORE CONDITION
>
SIG35:	SETZM	T2		;NO STATUS
	CAMN	T1,[C$IUUO]	;IF ILLEGAL UUO
	MOVE	T2,MPTRAP##	;STATUS IS UUO
	CAMN	T1,[C$ADCK]	;IF ADDRESS CHECK
	MOVE	T2,DEVNAM(F)	;STATUS IS DEVICE NAME
	EXCTUU	<MOVEM	T2,IBKISW(M)>	;STORE STATUS FOR USER
	EXCTUU	<MOVE T3,IBKICF(M)> ;PICK UP FLAGS
	MOVSI	T2,(1B0)	;SET BIT 0
	LSH	T2,(T1)		;SHIFT IT
	TDNE	T2,ERRMSK	;IS THERE AN ERROR MESSAGE?
	TLNN	T3,ICFMSG	;DOES THE USER WANT THE MESSAGE?
	JRST	SIG30		;NO--CHARGE AHEAD
	HRLM	T1,PITIPC(P1)	;REMEMBER WHY WE ARE HERE
	AOS	(P)		;CAUSE SKIP RETURN
	PJRST	SETPNX		;MAKE THIS TRAP WAIT TILL AFTER MESSAGE
SIG30:	JUMPG	P1,SETPND	;IF THE PI SYSTEM IS TURNED OFF THEN
				; THE INTERRUPT SHOULD STAY PENDING
				; UNTIL THE SYSTEM IS TURNED ON.
	JUMPL	P3,SETPNX	;HOLD INTERRUPT IF IN PFH OR DDT
	CAME	J,.CPJOB##(P4)	;CURRENT JOB?
	JRST	SIG40		;NO--SEE IF WE NEED TO WAIT
	HRRZ	T4,PITIPC(P1)	;GET LOCATION OF OLD PC
	JUMPE	T4,SIG40	;JUMP IF NONE STORED
	CAMN	P2,(T4)		;IS IT OUR PC?
	JRST	TOUSR1		;YES--GO INTERRUPT NOW
SIG40:	CAME	T1,[C$KSYS]	;KSYS?
	CAMN	T1,[C$DATT]	;OR DETACH?
	JRST	SIG45		;YES, GO IF IN TI STATE
	CAME	T1,[C$CTLC]	;IF NOT CONTROL C,
	JRST	SIG50		; LOOK AT OTHER POSSIBILITIES
SIG45:	TLNN	P3,USRMOD	;IF THE JOB IS IN USER MODE
	PUSHJ	P,CHKUTP##	; OR IT MAKES SENSE TO STOP IT,
	  JRST	TOUSR1		; GO DO IT NOW
SIG50:	CONSZ	PI,PI.IPA	;IS THERE A PI IN PROGRESS?
	PJRST	SETPNX		;YES--WAIT TO NEXT CLK TICK OR UUO EXIT.
	TLNN	P3,USRMOD	;SKIP IF USER IS IN EXEC MODE
	JRST	SETPNX		;EXEC MODE--WAIT
	CAME	T1,[C$IPC]	;IPCF TO HIMSELF?
	JRST	TOUSR1		;NO__CHANGE PC
	TLZ	P3,USRMOD	;USE UTOUSR
;FALL INTO SETPNX
	SUBTTL	INTERRUPT CODE -- SUBROUTINES

;SUBROUTINE TO CAUSE A INTERRUPT TO BECOME PENDING
;CALLED WITH:
;	T1 = NEGATIVE CONDITION OR POSITIVE ANYTHING
;	F = DDB ADDRESS IF T1 IS NOT NEGATIVE
;	J = JOB NUMBER
;	P1 = ADDRESS OF PROGRAM INTERRUPT TABLE
;	P3 IS .LT. 0 IF WE ARE IN DDT OR PFH
;
;	-OR-
;
;	PUSHJ	P,SETPNX	;TO CAUSE INTERRUPT TO BE GRANTED WHEN
;				; USER IS ABOUT TO BE STARTED IN USER
;				; MODE.
;
;	PUSHJ	P,SETPND	;TO CAUSE INTERRUPT TO STAY PENDING TILL DEBRK.
;				; OR PISYS. WHICH ENABLES PI SYSTEM
;	RETURN HERE
;

SETPNX:	PUSHJ	P,PSIWAK	;WAKEUP JOB
	TDZA	T4,T4		;SET T4=0 AS A FLAG
SETPND:	SETOM	T4		;SET T4=-1 AS A FLAG
	MOVE	T2,T1
	JUMPGE	T1,SETPN1	;TRANSFER IF DEVICE
	MOVSI	T2,(1B0)
	LSH	T2,(T1)		;POSITION BIT
	MOVEI	T3,PITDFR(P1)	;GET MASK OF PENDING INTERRUPTS
	SKIPA
SETPN1:	MOVEI	T3,DEVPSI(F)	;WORD WITH BIT
	TDNE	T2,(T3)		;ALREADY 1 INTERRUPT PENDING?
	POPJ	P,0		;YES--THAT IS PLENTY
	IORM	T2,(T3)		;NO--SET THE BIT
	SKIPL	T3,T1
	HRRZ	T3,F
	AOS	T2,PITNPI(P1)	;COUNT UP THE NUMBER OF PENDING
				; INTERRUPTS
	CAIN	T2,1		;JUST THIS INTERRUPT
	MOVEM	T3,PITNXT(P1)	;YES--WE MUST BE NEXT
	AOJE	T4,CPOPJ##	;EXIT IF WE ARE WAITING FOR DEBRK
	MOVE	T2,[PUSHJ P,UTOUSR] ;YES--GIVE JOBPD1 AFTER UUO AS OLD PC
				; IN CASE OF AOS
	SKIPGE	P3		;IN PAGE FAULT HANDLER OR DDT?
	HRRI	T2,PFHTRP	;YES--WAIT TILL EXIT FROM PFH OR DDT
	MOVEM	T2,PITINS(P1)	; TO CATCH USER ON UUO EXIT
	POPJ	P,0		;RETURN
;SUBROUTINE TO SET UP TO CAUSE AN INTERRUPT FOR A NOT-IN-CORE USER
;SAME CALL AS PSISIG
SIGDFR:	AOS	(P)
	PUSHJ	P,PSIWAK
	JUMPG	T1,[IORM T1,DEVPSI(F) ;STORE IN DDB
		    JRST SGDFR1] ;SETUP PITINS AND EXIT
	CAMN	T1,[C$WAKE]	;WAKE UUO DONE?
	JRST	[MOVE T2,.CPJOB##(P4) ;YES--GET CURRENT JOB
		 MOVEM T2,PITWJB(P1)  ;STORE FOR LATER
		 JRST  .+1]	;CONTINUE
	MOVSI	T2,(1B0)	;SET THE BIT IN DEFERED TRAP MASK
	LSH	T2,(T1)		; ..
	IORM	T2,PITDFR(P1)	; ..
SGDFR1:	HLRZ	T2,PITINS(P1)	;PICKUP INSTRUCTION TO EXECUTE
	CAIE	T2,(JFCL)	;SKIP IF AVAIL TO US.
	POPJ	P,0
	MOVE	T2,[PUSHJ P,DFRINT] ;SET UP TO TRAP ON
	MOVEM	T2,PITINS(P1)	; SWAP IN
	POPJ	P,0		;RETURN-DO NOT STORE AT (M)


;SUBROUTINE CALLED BY ERRCON AFTER PRINTING AN ERROR MESSAGE
;CALL WITH:
;	J = JOB #
;	PUSHJ	P,PSIERR
;	  RETURN HERE TO STOP JOB
;	RETURN HERE TO CONTINUE JOB (INTERRUPT SETUP)
;
PSIERR::SKIPGE	T1,JBTPIA##(J)	;IS THIS GUY ENABLED FOR PSI TRAPS
	SKIPL	PITIPC(T1)	; AND IS THERE AN ERROR TRAP WAITING
	JRST	CPOPJ2##	;NO--STOP HIM
	HRRZS	PITIPC(T1)	;CLEAR FLAG
	SKIPN	PITNXT(T1)	;SHOULD BE SOMETHING PENDING
	JRST	CPOPJ2##	;NO--JUST RETURN
	HRRZ	T1,P
	CAMLE	T1,LOCORE##
	AOS	(P)
	POPJ	P,
;SUBROUTINE TO CHANGE THE USER'S PC AND RESTART HIM AT THE NEW PC
;CALL WITH:
;	PUSHJ	P,TOUSER	;AT UUO EXIT OR FROM CHAN 7
;	-OR-
;	PUSHJ	P,TOUSR1	;FROM SIGNAL IF NO UUO IN PROGRESS
;	-OR-
;	PUSHJ	P,UTOUSR	;ON DEBRK OR PISYS
;
PFHTRP:	HRRZ	T1,(P)		;GET SAVED PC
	SKIPGE	P1,JBTPIA##(J)	;SETUP ADDRESS OF PIT
	CAIE	T1,UUOPSI##	;FROM UUO EXIT?
	POPJ	P,0		;NO--PUNT

UTOUSR:	PUSHJ	P,SAVE2##	;PROTECT P2 FOR PISYS CALL
	MOVE	P1,JBTPIA##(J)	;GET ADDRESS OF PI TABLE
	SKIPE	PITCIB(P1)	;ANY INTERRUPT IN PROGRESS
	POPJ	P,0		;YES -- WEIRD RACE CONDITION
	SKIPL	T1,PITNXT(P1)	;CONDITION CAUSED BY PISYS OR DEBRK
	HRRZ	F,T1		;DEVICE -- SETUP ACCUMULATOR F
	PUSHJ	P,BLKADR	;SETUP M
	  POPJ	P,		;ILLEGAL ADDRESS
	PUSHJ	P,CPUCDB##	;GET CDB ADDRESS
	MOVE	T3,JOBPD1##(R)	;GET OLD PC
	HRRZ	T1,-3(P)	;PICK UP SAVED PC
	CAIN	T1,CIPPSI##	;FROM CIPXIT
	MOVE	T3,.CPPC##(P4)	;YES--MAKE PC CORRECT
	PUSH	P,T3
	MOVE	T2,T3		 ;GET OLD PC
	PUSHJ	P,ISPFH		;IN USERS PAGE FAULT HANDLER
	  JRST	TPOPJ		;YES--WAIT TILL DONE
	POP	P,T3		;GET RETURN PC FOR UUO
IFN FTVM,<
	CAMN	T3,[IC.UOU+TIMFLT##]
	MOVE	T3,.UPMP+.UPTMC
>
	EXCTUU	<MOVEM T3,IBKOPC(M)> ;STORE AS OLD PC FOR THIS TRAP
	SKIPL	P1,JBTPIA##(J)	;LOAD ADDRESS OF PI TABLE
	POPJ	P,0		;SHOULD NEVER HAPPEN
	SKIPL	T1,PITNXT(P1)	;GET TRAP NAME
	HRRZ	F,T1		;DEVICE COPY DDB ADDRESS
	PUSH	P,T1		;SAVE CONDITION NAME
	PUSHJ	P,CLRPND	;NO LONGER PENDING
	POP	P,T1		;RESTORE CONDITION NAME
	PUSHJ	P,BLKADR	;GET ADDRESS OF BLOCK
	  POPJ	P,0		;INVALID ADDRESS
	HLL	P2,JOBPC##(R)	;PICK UP FLAGS
	CAMN	J,.CPJOB##(P4)	;IS THIS THE CURRENT JOB?
	HLL	P2,.CPPC##(P4)	;YES--GET CURRENT FLAGS
	JRST	TOUSR2		;SKIP SETUP OF P4
;MERGE IN HERE IF JOB WAS IN USER MODE WHEN CONDITION HAPPENED
TOUSR1:	EXCTUU	<MOVEM	P2,IBKOPC(M)>	;STORE OLD PC
	PUSHJ	P,CPUCDB##	;SET UP P4
TOUSR2:	EXCTUU	<MOVE T2,IBKNPC(M)>	;GET THE NEW PC
	TLNN	P2,(XC.UIO)	;IS HE IN USER IOT MODE NOW?
	TLZ	T2,(XC.UIO)	;NO--DO NOT ALLOW USER TO SET IT
	TLNE	P2,(XC.PUB)	;LAST INSTRUCTION PUBLIC
	TLO	T2,(XC.PUB)	;YES--FORCE PUBLIC
	TLO	T2,USRMOD	;PUT HIM IN USER MODE
	TLZ	T2,37		;CLEAR INDEX AND INDIRECT
	CAMN	J,.CPJOB##(P4)	;IS THIS THE CURRENT JOB?
	MOVEM	T2,.CPPC##(P4)	;YES--SAVE THE NEW PC
	MOVEM	T2,JOBPC##(R)	;STORE IN JOB DATA AREA
	MOVEM	T2,.CPAPC##(P4)	;FOR ADDRESS BREAK
	MOVE	T3,JOBPD1##(R)	;PICK UP UUO PC
IFN FTVM,<
	CAMN	T3,[EXP IC.UOU+TIMFLT##] ;IS IT FROM PAGE FAULT?
	MOVEM	T2,.UPMP+.UPTMC	;YES--UPDATE SAVED PC
> ;END FTVM
	TLNE	T3,USRMOD	;FROM THE USER
	MOVEM	T2,JOBPD1##(R)	;YES--STORE NEW PC IN JOBDAT
	HRRZ	T4,PITIPC(P1)	;GET THE LOCATION OF THE INTERRUPT PC
	JUMPE	T4,TOUSR3	;JUMP IF NONE
	CAMN	P2,(T4)		;IS IT FROM US?
	MOVEM	T2,(T4)		;YES--ONE MORE PLACE TO PUT THE NEW PC
	HLLZS	PITIPC(P1)	;CLEAR FLAG
TOUSR3:	MOVE	T2,[WTMASK+JERR+CNTRLC,,JS.MPE+JS.JDP+JS.APE+JS.DPM+UTRP]
	ANDCAM	T2,JBTSTS##(J)	;BLAST JBTSTS
	MOVSI	T3,ICFNOT	;MAKE SURE THIS BIT IS
	EXCTUU	<IORM T3,IBKICF(M)>  ;SET
	MOVSI	T2,(SI.ON)	;PI ON FLAG
	MOVSI	T3,ICFOFF	;TURN OFF PI SYSTEM BIT
	EXCTUX	<TDNE T3,IBKICF(M)> ;IS IT SET?
	ANDCAM	T2,JBTPIA##(J)	;YES--TURN OFF THE SYSTEM
	MOVE	T2,JBTPIA##(J)	;ADDRESS OF PI TABLE
	HRRM	M,PITCIB(T2)	;STORE ADDRESS OF INTERRUPT BLOCK
IFN FTKA10,<			;KA10?
	MOVE	T3,M		;COPY ADDRESS
	HRRZ	T2,JBTADR##(J)	;GET RELOCATION
	SUBI	T3,(T2)		;UNRELOCATE
	HRRM	T3,PITCIB(P1)
>	;END FTKI10
	POPJ	P,0		;RETURN
;SUBROUTINE TO CLEAR A PENDING INTERRUPT. THIS SUBROUTINE IS
; CALLED BY ANYONE WHO WANT TO MAKE A PENDING INTERRUPT
; GO AWAY. THIS MUST BE THE ONLY ROUTINE TO CLEAR PENDING INTERRUPTS.
;CALLED WITH:
;	T1 = DEVICE OR CONDITION
;	F = ADDRESS OF DDB IF T1 IS DEVICE
;	P1 = ADDRESS OF PROGRAM INTERRUPT TABLE
;	PUSHJ	P,CLRPND
;	RETURN HERE
CLRPND:	HLRE	T2,T1		;STANDARD TEST FOR CONDITION OR DEVICE
	AOJE	T2,CLPND1	;JUMP IF CONDITION
	HRRZ	T2,DEVPSI(F)	;PENDING INTERRUPT BIT
	JUMPE	T2,CPOPJ##	;NOTHING PENDING CALLER IS CONFUSED
	ANDCAM	T2,DEVPSI(F)	;CLEAR THE BIT
	HRRZ	F,F		;MAKE SURE LH OF F = 0
	CAMN	F,PITNXT(P1)	;WAS THIS TO BE NEXT INTERRUPT?
	SETZM	PITNXT(P1)	;YES--IS NOT ANY MORE
	JRST	CLPND2		;FINISH UP

CLPND1:	MOVSI	T2,(1B0)	;GET BIT IN CORRECT 
	LSH	T2,(T1)		; POSITION
	CAMN	T1,[C$QUE]
	SETZM	PITENQ(P1)
	TDNN	T2,PITDFR(P1)	;IS THE BIT SET?
	POPJ	P,0		;NO--DO NOT TRY TO CLEAR IT
	ANDCAM	T2,PITDFR(P1)	;CLEAR THE BIT
	CAMN	T1,PITNXT(P1)	;WAS THIS TO BE NEXT INTERRUPT?
	SETZM	PITNXT(P1)	;YES--CLEAR SINCE NO LONGER NEXT
CLPND2:	MOVSI	T2,(JFCL)	;CLEAR THE TRAP INSTRUCTION
	MOVEM	T2,PITINS(P1)	; ..
	SOSLE	PITNPI(P1)	;ONE LESS PENDING INTERRUPT
	SKIPE	PITNXT(P1)	;SEE IF SOMETHING NEXT
	POPJ	P,0		;NO MORE PENDING INTERRUPTS OR THIS
				; INTERRUPT NOT NEXT.
;HERE TO FIND INTERRUPT WE WANT TO GRANT NEXT.

	MOVE	T1,PITDFR(P1)	;GET MASK OF PENDING INTERRUPTS
	JFFO	T1,CLRPN5	;JUMP IF A CONDITION IS PENDING
	PUSH	P,F		;SAVE F
	HLRZ	F,DEVLST##	;POINT TO FIRST DDB
CLRPN3:	HRRZ	T1,DEVPSI(F)	;SKIP IF INTERRUPT PENDING FOR THIS DDB
	JUMPE	T1,CLRPN4	;ELSE LOOK AT NEXT DDB
	LDB	T1,PJOBN##	;GET JOB NUMBER OF OWNER
	MOVEM	F,PITNXT(P1)	;SAVE AS NEXT INTERRUPT
	CAMN	T1,J		;FOR THIS JOB?
	JRST	FPOPJ##		;YES--ALL DONE--RESTORE F AND RETURN
CLRPN4:	HLRZ	F,DEVSER(F)	;STEP TO THE NEXT DDB
	JUMPN	F,CLRPN3	;LOOK AT NEXT DDB
;HERE IF THE COUNT OF PENDING INTERRUPTS IS TO HIGH.  WHILE A STOPCD COULD
; BE USED HERE WE WILL JUST DECREMENT THE COUNT AND RETURN
	SOS	PITNPI(P1)	
	JRST	FPOPJ##		;RESTORE F AND RETURN

;HERE IF A NON-I/O CONDITION IS PENDING
CLRPN5:	MOVNM	T2,PITNXT(P1)	;STORE NEGATIVE CONDITION NUMBER
	POPJ	P,0		;RETURN
	SUBTTL	MISC. SUBROUTINES

;SUBROUTINE TO FIGURE OUT OLD PC ON A CONTROL-C
;CALL WITH:
;	PUSHJ	P,CTLCPC
;	RETURN HERE PC IN T2
CTLCPC:	LDB	T2,PJBSTS##	;GET WAIT STATE
	CAIN	T2,TIOWQ##	;IN TTY IO WAIT
	SKIPA	T2,JOBPD1##(R)	;YES--GET UUO PC
	GJOBPC			;NO--GET CURRENT PC
	POPJ	P,0		;RETURN



PSIWAK:	PUSH	P,T1
	PUSHJ	P,WAKEJB##
	JRST	TPOPJ##
;SUBROUTINE TO SEE IF A USER IS ENABLED FOR AN INTERRUPT
;CALL WITH:
;	HRREI	T1,C$????
;	PUSHJ	P,PSITST
;	  HERE IF NOT ENABLED
;	HERE IF ENABLED
;
;	-OR-
;
;	MOVEI	T1,DEVICE-BITS
;	MOVE	F,DDB-ADDRESS
;	PUSHJ	P,PSITST
;	  HERE IF NOT ENABLED
;	HERE IF ENABLED
;
;
;USES T2 AND T3 MAY BE CALLED FOR ANY USER AT ANY TIME
;
PSITST::PUSHJ	P,SAVE1##	;SAVE P1
	SKIPN	P1,JBTPIA##(J)	;PIINI. UUO DONE?
	POPJ	P,0		;NO--NOT ENABLED
	SKIPN	JBTADR##(J)
	JRST	CPOPJ1##
	PUSH	P,U		;SAVE U FOR OUTSIDE WORLD
	PUSHJ	P,CNDPTR	;GET POINTER FOR CONDITION
	LDB	U,U		;GET BYTE OFFSET
	JUMPN	U,UPOPJ1##	;JUMP IF ENABLED FOR THE CONDITION
	JRST	UPOPJ##		;NOT ENABLED
;SUBROUTINE TO SET UP M WITH ADDRESS OF INTERRUPT BLOCK
;CALL WITH:
;	MOVE	T1,CONDITION OR DEVICE
;	PUSHJ	P,BLKADR
;	  RETURN HERE IF ADDRESS IS NO GOOD
;	RETURN HERE WITH M SETUP
;
BLKADR:	PUSH	P,U		;SAVE U
	PUSHJ	P,CNDPTR	;GET POINTER FOR CONDITION
	LDB	U,U		;GET OFFSET
	JUMPE	U,UPOPJ##	;ZERO IS INVALID
	SUBI	U,1		;ACCOUNT FOR ADDI IN ADDDEV
	LSH	U,2		;CONVERT TO WORD ADDRESS
	ADD	U,PITIVA(P1)	;ADD IN BASE OF VECTOR
	HRR	M,U
	PUSH	P,F		;F MIGHT GET ZAPPED
	PUSHJ	P,BLKCHK	;CHECK THE INTERRUPT BLOCK
	  JRST	FUPOPJ##	;BAD ADDRESS
IFN FTKI10!FTKL10,<
	JRST	FUPOJ1##	;GOOD RETURN IF KI OR KL
>
IFN FTKA10,<
	HRRZ	U,JBTADR##(J)	;ADDRESS OF JOB
	ADDI	M,(U)		;RELOCATE
	JRST	FUPOJ1##	;GOOD ADDRESS
>
;SUBROUTINE TO TEST AN INTERRUPT BLOCK POINTED TO BY M AND STOP JOB IF
;	ANY ADDRESS CHECKS
;CALL WITH:
;	M = ADDRESS OF BLOCK
;	T1 = NEGATIVE CONDITION OR POSITIVE ANYTHING
;	F  = DDB ADDRESS IF ANY
;	PUSHJ	P,BLKCHK
;	  RETURN HERE IF NO GOOD
;	RETURN HERE IF GOOD
;
BLKCHK:	PUSHJ	P,VCTSTS	;BLOCK OK?
	  JRST	CPOPJ1##	;YES, BLOCK IS BEAUTIFUL
	PUSH	P,M		;SAVE ASCII STRING,,VECTOR ADDRESS
	SKIPL	T1		;SKIP IF CONDITION
	MOVEI	T1,(F)		;NO CONDITION, GET DDB ADDRESS
	PUSH	P,T1		;AND SAVE IT
	MOVSI	T1,JERR		;CAN'T CONTINUE BIT
	IORM	T1,JBTSTS##(J)	;WILL PREVENT ANY ATTEMPT TO TRAP
	PUSHJ	P,GIVRES##	;PLAY IT SAFE AND GIVE UP RESOURCES
	JSP	T1,ERRPNT##	;START ERROR MESSAGE
	  ASCIZ/PSI interrupt vector at /
	HRRZ	T1,-3(P)	;ERRPNT PUSHED F AND U
	PUSHJ	P,PRTDI8##	;PRINT ADDRESS THAT WE COULDN'T GET
	SKIPL	T2,-2(P)	;SKIP IF CONDTION
	JRST	BLKCK1		;DEVICE, USE NAME
	ROT	T2,-1		;DIVIDE BY TWO TO GET TABLE ADDR
	SKIPGE	T2		;LH OR RH ENTRY?
	SKIPA	T2,PSISBT(T2)	;LH
	MOVS	T2,PSISBT(T2)	;RH
	TRZA	T2,-1		;CLEAR OUT UNUSED HALF
BLKCK1:	SKIPA	T2,DEVNAM(T2)	;GET SIXBIT NAME INSTEAD
	SKIPA	T1,[[ASCIZ/ for condition /]]
	MOVEI	T1,[ASCIZ/ for device /]
	PUSHJ	P,CONMES##	;EXPLAIN REASON
	PUSHJ	P,PRNAME##	;TYPE SIXBIT (CONMES DIDN'T HURT T2)
	HLRZ	T1,-3(P)	;ADDRESS OF FINAL STRING
	PUSHJ	P,CONMES##	;FIX
	SUB	P,[2,,2]	;REMOVE F AND U FROM STACK
	JRST	PCSTOP##	;WON'T RETURN UNLESS AT INTERRUPT LEVEL.
				; IN THAT CASE, IT WILL POP THE LAST
				; TWO LOCATIONS ON THE STACK (WHICH
				; ARE NOW JUNK) AND POPJ, GIVING THE
				; ERROR RETURN BACK TO BLKADR.
;SIXBIT TABLE OF ABBREVIATIONS FOR ERROR CONDTIONS
;USED IF USER'S JOB STOPPED DUE TO ERROR

	'NTC',,0	;(-27) NTWRK TOPOLOGY	(-30)
	'RMC',,'QUE'	;(-25) REMOTE COMPUTER	(-26) ENQ/DEQ
	'ABK',,'IPC'	;(-23) ADR BREAK	(-24) IPCF
	'DAT',,'WAK'	;(-21) DET/ATTACH	(-22) WAKE UUO
	'KSY',,'DSC'	;(-17) KSYS WARNING	(-20) DATASET STATUS
	'UEJ',,'XEJ'	;(-15) USER ERROR	(-16) EXTERNAL ERROR
	'NXM',,'APC'	;(-13) NXM		(-14) CLOCK TICK
	'PDL',,0	;(-11) PDL OV		(-12) TRAP TYPE 3
	'ACK',,'ARI'	;(- 7) ADR CHECK	(-10) ARITHMETIC EXC
	'ILU',,'IMR'	;(- 5) ILL UUO		(- 6) ILL MEM REF
	'STP',,'UUO'	;(- 3) ^C		(- 4) ANY UUO
	'TLE',,0	;(- 1) TIME LIMIT	(- 2) ^A
PSISBT:


;SUBROUTINE CALLED BY BLKCHK TO CHECK LEGALITY OF INTERRUPT BLOCK
;	PUSHJ	P,VCTSTS
;	  RETURN HERE IF EVERYTHING IS FINE
;	RETURN HERE IF SOMETHING BAD, ASCII ADDR IN LH OF M
;TEMPORARY AC'S PRESERVED

VCTSTS:	PUSHJ	P,SAVT##	;SAVE TEMP AC'S
	MOVEI	T1,(M)		;COPY ADDRESS OF BLOCK
	SETO	T3,		;T3 COUNTS LOOPS, WANT TO LOOP TWICE
VCTST1:	HLRZ	T2,JBTADR##(J)	;GET HIGH LEGAL ADDRESS
	CAIG	T1,(T2)		;TOO BIG?
	CAIG	T1,JOBPFI##	;OR TOO SMALL?
	JRST	VCTST2		;YES, INT BLOCK IS AT ILLEGAL ADDRESS
IFN FTVM,<
	MOVEI	T4,(T1)		;GET ADDRESS IN T4
	LSH	T4,W2PLSH##	;MAKE A PAGE ADDRESS
	PUSHJ	P,GTPM4##	;GET PAGE MAP ENTRY IN T4
	JUMPE	T4,VCTST2	;IF NONE, ILLEGAL ADDRESS
	PUSHJ	P,FLTST##	;PAGE EXISTS, IS IT IN CORE?
	  JRST	VCTST3		;NO, PAGED OUT!
>
	ADDI	T1,3		;POINT TO END OF BLOCK
	AOJE	T3,VCTST1	;HAVE TO CHECK BOTH ENDS
	POPJ	P,		;HE PASSED CHECKS, GOOD RETURN

VCTST2:	HRLI	M,[ASCIZ/ illegal/]
	JRST	CPOPJ1##	;BAD RETURN

IFN FTVM,<
VCTST3:	HRLI	M,[ASCIZ/ paged out/]
	JRST	CPOPJ1##	;BAD RETURN
>
;SUBROUTINE TO SEE IF USER IS IN PFH OR DDT
;CALL WITH:
;	T2 = PC
;	PUSHJ	P,ISPFH
;	  HERE IF IN PFH OR DDT
;	HERE IF NOT
;
; RESPECTS ALL AC'S EXCEPT T3
;
ISPFH:	IFN	FTVM,<		;IF THIS IS A VM MONITOR
	PUSHJ	P,INPFH##	;SEE IF WE ARE IN PFH
	  POPJ	P,0		;YES--INDICATE THAT
> ;END FTVM
	HRRZ	T3,JOBDDT##(R)	;GET START OF DDT
	SKIPE	JOBDDT##(R)	;DDT LOADED?
	CAIL	T3,(T2)		;ABOVE START OF DDT?
	JRST	CPOPJ1##	;NO--ALL IS WELL
	HLRZ	T3,JOBDDT##(R)	;GET END OF DDT
	CAIG	T3,(T2)		;ABOVE END?
	AOS	(P)		;YES--NOT IN DDT
	POPJ	P,0		;IN DDT


;SUBROUTINE TO STORE UDX AND DEVICE STATUS IN INTERRUPT BLOCK
;CALL WITH:
;	M = ADDRESS IF INTERRUPT BLOCK
;	S = DEVICE STATUS
;	F = DDB ADDRESS
;	PUSHJ	P,PSIUDX
;	RETURN HERE STATUS STORED
;
PSIUDX:	PUSH	P,U
	PUSHJ	P,IONDF##	;GET I/O INDEX
	  MOVEI	T1,0
	HRLZ	T1,T1		;PUT IN LEFT HALT
	HRR	T1,DEVIOS(F)	;ADD IN DEVICE STATUS
	EXCTUU	<MOVEM T1,IBKISW(M)> ;STORE FOR USER TO SEE
	JRST	UPOPJ##		;RETURN

IFN FTVM,<
;SUBROUTINE TO RETURN PITIVA OR ZERO IF NOT PSIING
PSIIVA::SKIPE	T1,JBTPIA(J)	;PSIING?
	MOVE	T1,PITIVA(T1)	;YES
	POPJ	P,
>
;SUBROUTINE TO BUILD A BYTE POINTER TO THE VECTOR OFFSET BYTE IN
; THE PROGRAM INTERRUPT TABLE OR DDB.
;CALL WITH:
;	T1 = CONDITION NUMBER OR DEVICE NAME
;	PUSHJ	P,CNDPTR
;	RETURN HERE POINTER IN U
;
;PRESERVES T1 WIPES T2,T3
;
CNDPTR:	MOVE	U,PDVIVO##	;ASSUME DEVICE
	HLRE	T2,T1		;IF SMALL NEGATIVE NUMBER T2=-1
	AOJN	T2,CPOPJ##	;RETURN IF DEVICE
	MOVM	T2,T1		;GET POSITIVE CONDITION
	IDIVI	T2,4		;T2 := WORD AND T3 := QUARTER
	MOVE	U,CNPTTB(T3)	;GET A GOOD POINTER
	ADDI	U,(T2)		;ADD IN WORD OFFSET
	POPJ	P,0		;RETURN

CNPTTB:	POINT	9,PITTAB(P1),8	;BYTE 0
	POINT	9,PITTAB(P1),17	;BYTE 1
	POINT	9,PITTAB(P1),26	;BYTE 3
	POINT	9,PITTAB(P1),35	;BYTE 4


PSILIT::XLIST		;LITERALS IN PSISER
	LIT
PSIEND::LIST		;END OF PSISER
	END