Google
 

Trailing-Edge - PDP-10 Archives - bb-jr93e-bb - 7,6/ap016/ksser.x16
There are 2 other files named ksser.x16 in the archive. Click here to see a list.
TITLE	KSSER - KS20 PROCESSOR DEPENDENT CODE  V116
SUBTTL	DMCC/DBD	17 JUN 86
	SEARCH	F,S
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1978,1986>
;COPYRIGHT (C) 1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.



XP VKSSER,116
;TRACKS VERSION 274 OF KLSER

	ENTRY	KSSER		;LOAD KSSER IF LIBRARY SEARCH
KSSER:

SUBTTL	TRAP HANDLING AND CONTEXT SWITCHING

;HERE TO PROCESS USER ARITHMETIC OVERFLOW TRAPS
SAROVF::
	DMOVE	T1,.USMUO	;GET PC DBL WRD
	MOVE	T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
	TRNN	T3,AP.AOV	;OVERFLOW - IS THE USER ENABLED?
	TLNE	T1,(XC.FOV)	;TRAP CAUSED BY FOV?
	CAIA			;YES,
	JRST	SAROV6		;NOT ENABLED, IGNORE IT
	HRRI	T3,AP.AOV+AP.FOV;ASSUME FLOATING OVERFLOW
	TLNN	T1,(XC.FOV)	;WAS IT A FLOATING OVERFLOW TRAP?
	TRZ	T3,AP.FOV	;NO, INTEGER OVERFLOW
;HERE WITH T1=PC, T3=APRENB BITS
SAROV3:	TLNE	T2,MXSECN	;IN A NON-ZERO SECTION?
	JRST	SAROV9		;CAN'T TRAP IT THIS WAY THEN
	HLLM	T1,.JDAT+JOBTPC## ;SAVE OLD PC
	HRRM	T2,.JDAT+JOBTPC## ;..
	MOVEM	T3,.JDAT+JOBCNI## ;LIKE CONI ON THE KA-10
	MOVE	T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
	TRNE	T3,XP.DDU	;USER WANT TRAPS REENABLED?
	JRST	SAROV5		;YES, LEAVE AS IS
	HLLZS	.JDAT+JOBENB##	;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
	MOVSI	T3,(JFCL)	;NOP
	MOVEM	T3,.USAOT	;IGNORE ARITHMETIC TRAPS
	MOVEI	T3,UP.PDT
	MOVEM	T3,.USPDT	;EXEC WILL FIELD PDL OVERFLOWS
	SETZM	.CPCN1##	;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV5:	MOVEI	T3,XP.CLK	;ALWAYS DISABLE CLOCK
	ANDCAM	T3,.CPCN1##
	HRRZ	T3,.JDAT+JOBAPR## ;PC IN TRAP ROUTINE?
	CAIE	T3,0(T2)
	CAIN	T3,-1(T2)
	JRST	SAROV7		;YES
	HRR	T2,.JDAT+JOBAPR## ;GET USER'S TRAP ADDRESS
	TLZ	T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV+IC.BIS)
	TLO	T1,(XC.USR)	;INSURE PUBLIC AND USER MODE IS SET
SAROV6:	DMOVEM	T1,.USMUO	;NEW PC WITH TRAP CAUSING BITS CLEARED
	MOVE	P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SET UP A STACK
	PUSHJ	P,SCDCHK##	;CHECK IF WE SHOULD RESCHEDULE
	USERAC			;SET USER AC BLOCK
	XJRSTF	.USMUO		;EXIT TO THE USER'S TRAP HANDLER
SAROV7:	MOVEI	T3,XP.LTH	;STUCK IN LOOP BIT
SAROV9:	DMOVEM	T1,.CPAPC##	;SAVE OLD PC FOR ERROR MESSAGE
	HRRM	T3,.CPAEF##
	JRST	SEPDL3
;HERE TO PROCESS EXEC STACK OVERFLOW TRAPS

SEPDLO::EXCH	T1,.USMUP	;GET THE PC
	MOVEM	T1,.CPAPC##+1	;STORE PC
	HLLZ	T1,.USMUO	;FLAGS
	MOVEM	T1,.CPAPC##	;SET AS ERROR PC FOR ERRCON
	TLNN	T1,(XC.USR)	;IN USER MODE?
	JRST	DOPDL		;NOPE, EXEC MODE, TAKE A DUMP

	HRRI	T1,AP.POV	;SET PUSH DOWN OVERFLOW FLAG
SEPDL1:	HRRM	T1,.CPAEF##	;IN .CPAEF SO ERRCON WILL GET CALLED
	MOVE	T1,.USMUP	;RESTORE T1
SEPDL3:	SETOM	.CPSCF##	;SET FORCED RESCHEDULING FLAG
	SETOM	.CPCKF##	;AND CLOCK FLAG
	WRPI	CLKBIT##	;REQUEST A CLOCK INTERRUPT
	JRST	.		;WAIT UNTIL CLOCK LEVEL HAPPENS AND THE JOB
				; IS STOPPED IN USER MODE.

DOPDL::	EXCH	T1,.USMUP	;SAVE PC AND RESTORE T1
	MOVEM	P,@.CPEPL##	;SAVE OLD P
	HRRZS	P		;SEE IF
	CAMLE	P,SYSSIZ##	;UUO OR INTERRUPT LEVEL
	XJRST	[MCSEC1+EXTPDL##] ;UUO, TRY TO EXTEND THE PDL
	JRST	EPOSTP##	;CAN'T RECOVER ON INTERRUPT LEVEL
;HERE TO PROCESS PAGE FAILURE TRAPS

SEILM::	RDPI	.CPTPI##	;SAVE THE PI STATE
	WRPI	PI.OFF		;NOW INSURE THAT PI'S ARE OFF
	RDUBR	.CPTCX##	;SAVE THE TRAP CONTEXT
	EXECAC			;WANT MONITOR'S AC BLOCK
	JRSTF	@[IC.UOU+.+1]	;INSURE USRIOT IS ON SO PXCT WORKS

	MOVEM	T1,.CPSTT##	;SAVE T1 TEMPORARILY
	LDB	T1,[POINT 5,.USPFW,5] ;PICK UP PF CODE
	CAIGE	T1,20		;IS THIS A REAL PAGE FAULT?
	JRST	SEILMA		;YES--GO PROCESS IT
	CAIN	T1,PF.IOP	;IS IT A UBA FAILURE?
	 JRST	SEILMU		;YES, PROCESS
	CAIL	T1,PF.PAR	;IS IT A PARITY OR NXM TRAP?
	JRST	PRTRP		;YES--GO PROCESS
	CAIN	T1,PF.PTP	;IS IT PAGE TABLE PARITY?
	JRST	PTPAR		;YES--GO PROCESS
	STOPCD	.,CPU,IPC	;++ILLEGAL PAGE FAILURE TRAP CODE

	;HERE ON A UNIBUS ADDRESSING FAILURE
	;A USER MODE FAILURE CAN OCCUR IF THE USER HAS IOT, AND MAKES A
	;STRAY REFERENCE.  WE DON'T WANT TO KILL THE SYSTEM.  ALLOW THE
	;USER TO INTERCEPT (NOT APRENB, BUT PSI) SO CAN CHECK WHETHER A
	;DEVICE IS PRESENT.

SEILMU:	DMOVEM	T2,.CPST1##	;SAVE SOME MORE ACS
	DMOVE	T1,.USPFP	;FETCH THE PC THAT FAILED
	 SKIPE	.USJOB##	;IF NULL JOB, IT'S EXEC MODE
	TLNN	T1,(XC.USR)	;USER MODE?
	 STOPCD	.,STOP,UAF,DIEUAF ;++UNIBUS ADDRESSING FAILURE
	DMOVEM	T1,.CPAPC##	;USER MODE, CAN SIMPLY STOP JOB (USER HAS IOT)
	MOVE	T1,.USPFW	;GET THE ADDRESS THAT FAILED
	MOVEM	T1,.USMUP	;SAVE IT IN CASE NON-EXISTANT UBA
	TLZ	T1,^-17		;KEEP ONLY THE UBA NUMBER
	HRRI	T1,UNBSTW	;POINT TO THE UBA STATUS REGISTER
	MOVEI	T3,UBNOGD	;GET PAGE FAIL HANDLER
	EXCH	T3,.USPFN+1	;IN CASE OF ILLEGAL UBA
	MOVEI	T2,UNBNED!UNBTMO ;NON-EXISTANT DEVICE AND TIMEOUT
	BSIO	T2,(T1)		;CLEAR THE BITS
	MOVEM	T3,.USPFN+1	;RESTORE THE USUAL PAGEFAIL HANDLER
	DMOVE	T2,.CPST1##	;AND THE EXTRA ACS
	MOVE	T1,.CPSTT##	;RESTORE T1
	EXCH	T1,.USMUP	;AND PUT IT WHERE SEPDL1 WANTS IT
	MOVEM	T1,.USPFW	;RESTORE ORIGINAL PFW IN CASE OF PSI TRAP
	MOVEI	T1,AP.ILM	;ILL MEM REF BIT
	WRPI	PI.ON		;RESTORE PI SYSTEM
	JRST	SEPDL1		;AND GIVE ?ILL MEM REF AT PC MUMBLE

DIEUAF:	PUSHJ	P,INLMES##	;ADD SOME TEXT
	ASCIZ	/UBA = /
	LDB	T1,[POINT 3,.USPFW,17] ;GET UBA NUMBER
	PUSHJ	P,PRTDI8##	;PRINT IT
	PUSHJ	P,INLMES##	;MORE TEXT
	ASCIZ	/, register address = /
	HRRZ	T1,.USPFW	;GET ADDRESS
	PJRST	PRTDI8##	;PRINT AND RETURN
;HERE ON A PARITY OR NXM TRAP

PRTRP:	SKIPE	.CPPSP##	;CORE SWEEP IN PROGRESS?
	JRST	SWTRP		;YES, JUST SAVE LOCATION OF FAILURE AND DISMISS
	EXCH	T1,.CPSTT##	;RESTORE T1 AND SAVE TRAP CODE
	MOVEM	17,.CPA17##	;SAVE AC 17
	MOVEI	17,.CPA00##	;MAKE BLT POINTER
	BLT	17,.CPA17##-1	;SAVE AC'S IN CPU DATA BLOCK
	MOVE	P,.CPEPD##	;SET UP ERROR STACK
	MOVE	J,.CPJOB##	;SET UP J WITH CURRENT JOB RUNNING
	MOVE	T1,JBTPPN##(J)	;GET ITS PPN
	MOVEM	T1,.CPEJN##	; AND SAVE IT
	MOVE	T1,JBTNAM##(J)	;GET ITS PROGRAM NAME
	MOVEM	T1,.CPEPN##	; AND SAVE IT
	MOVE	P4,.CPSTT##	;GET THE TRAP CODE
	CAIE	P4,PF.NXM	;IS IT A NXM?
	SKIPA	P4,[UE.PEF]	;NO--SET UP PARITY ERROR FLAG
	MOVEI	P4,UE.NXM	;YES--SET UP NXM FLAG
	AOS	.CPNPT##	;COUNT TOTAL NUMBER OF PARITY/NXM TRAPS
	DMOVE	T1,.USPFP	;GET THE PAGE FAIL PC
	DMOVEM	T1,.CPMDP##	;FOR ERROR IN JOB MESSAGES
	DMOVEM	T1,.CPPPD##	;STORE TROUBLE PC
	TDZ	T1,[7777,,-1]	;HOKEY IT UP
	IOR	T1,T2		;SINCE A ONE WORD GETTAB

	MOVEM	T1,.CPPPC##	;SAVE THE PC FOR DAEMON
	MOVEM	T1,.CPMPP##	;ALSO OLD PLACE
	MOVE	T2,.USPFW	;GET THE PAGE FAIL WORD
	MOVEM	T2,.CPPFW##	;SAVE THE PAGE FAIL WORD FOR DAEMON
	TRNE	P4,UE.NXM	;IS THIS A NXM?
	JRST	PRTRPC		;YES--THEN THERE'S NO DATA TO PICK UP
	WRUBR	[SG.LAB+7B11]	;NO--SET PREVIOUS ACS TO BLOCK 7
	PXCT	PX.MEM,[MOVE T3,0] ;PICK UP BAD DATA WORD FROM BLOCK 7
	EXECAC			;RESTORE MONITOR AC SETTINGS
	MOVEM	T3,.CPTBD##	;SAVE BAD DATA FOR DAEMON
PRTRPC:	MOVE	T4,[PXCT PX.MEM,[MAP P1,(T2)]] ;SET UP PXCT OF MAP INSTRUCTION
	SKIPL	.CPPFW##	;IS THIS A USER CONTEXT REFERENCE?
	TLZ	T4,(PX.MEM,)	;NO--THEN PXCT BECOMES REGULAR XCT
	XCT	T4		;DO A MAP TO TURN PF WORD INTO PHYS ADDR IN P1
	MOVEM	P1,.CPPBA##	;SAVE BAD PHYSICAL ADDR FOR DAEMON
	TLZ	P1,777760	;GET RID OF LEFT HALF STUFF
	ROT	P1,W2PLSH##	;TURN RH OF P1 INTO PAGE NUMBER OF BAD LOC
	MOVE	T3,.CPMAP##	;GET PAGE NUMBER OF EPMP FOR THIS CPU
	PUSH	P,.ERPIL/PAGSIZ##(T3)
	HRRM	P1,.ERPIL/PAGSIZ##(T3)
	HRRI	P1,(<PM.DCD>B2+PM.WRT+PM.PUB)
	HRLM	P1,.ERPIL/PAGSIZ##(T3)

	CLRPGT	(0,.ERPIL)	;CLEAR OUT OLD ENTRY FOR .ERPIL
	LSH	P1,-^D27	;TURN P1 INTO WORD NUMBER WITHIN PAGE
	ADDI	P1,.ERPIL	;AND GET PAGE NUMBER CORRESPONDING TO MAP SLOT
	TRNE	P4,UE.NXM	;IS THIS A NXM?
	SKIPA	T1,[[ASCIZ / non-existent memory trap/]] ;YES
	MOVEI	T1,[ASCIZ / parity trap/] ;NO
	PUSHJ	P,PRMPC		;ANNOUNCE ERROR
	MOVEI	T1,[ASCIZ /Page fail word = /]
	MOVE	T2,.CPPFW##
	PUSHJ	P,PRMHW		;PRINT THE PAGE FAIL WORD
	MOVEI	T1,[ASCIZ /Mapped page fail address = /]
	MOVE	T2,.CPPBA##
	PUSHJ	P,PRMHW		;PRINT THE MAP WORD (PHYS. ADDRESS)
	MOVEI	T1,[ASCIZ /Incorrect contents = /]
	MOVE	T2,.CPTBD##
	TRNN	P4,UE.NXM	;IF A NXM, NO DATA TO PRINT
	PUSHJ	P,PRMHW		;PRINT THE BAD DATA
	MOVEI	T1,[ASCIZ /CONI PI, = /]
	MOVE	T2,.CPTPI##
	PUSHJ	P,PRMHW		;PRINT THE CONI PI BITS
	SETZ	P2,		;CLEAR FLAG REGISTER
;HERE TO START RETRIES
	PUSHJ	P,PRTRY		;REFERENCE LOCATION
	 JRST	PRHMF		;RETRIES FAILED! HARD MEMORY FAILURE
;HERE WE KNOW WE CAN RECOVER THE USER
	MOVEM	T1,.CPTGD##	;SAVE THE GOOD DATA FOR ERROR REPORTING
	AOS	.CPSAR##	;UPDATE COUNTER OF SOFT PARITY ERRORS
;HERE IF RETRIES WERE SUCCESFUL, LOG SOFT ERROR AND DISMISS
	TRO	P2,PFCPF0	;INDICATE WE'RE A KS10
	HRLM	P2,.CPPTR##	;SAVE STATUS FLAGS FOR ERROR REPORTING
	HRRM	T3,.CPPTR##	;SAVE RETRY COUNT FOR ERROR REPORTING
	MOVE	T3,.CPMAP##	;GET .EPMP FOR THIS CPU
	POP	P,.ERPIL/PAGSIZ##(T3)

	MOVEI	T1,[ASCIZ /Retry successful! Correct contents = /]
	MOVE	T2,.CPTGD
	PUSHJ	P,PRMHW		;PRINT SUCCESS AND GOOD DATA
	MOVEI	T1,EDELIM##	;GET ADDRESS OF TEXT
	PUSHJ	P,PRMSG		;PRINT END DELIMITER
	MOVEI	T1,.ERKPT	;ASSUME PARITY CODE FOR DAEMON
	TRNE	P4,UE.NXM	;IS THIS REALLY A NXM?
	MOVEI	T1,.ERKSN	;YES--GET NXM CODE
	HRL	T1,.CPSLF##	;THIS CPU'S CDB ADDRESS
	PUSHJ	P,DAEDIE##	;PUT THE ENTRY IN THE QUEUE
	JRST	PTXIT		;EXIT THE TRAP
	;LOCAL RETRY ROUTINE
	;RETURNS +1 IF RETRIES FAIL
	;RETRUNS +2 IF ANY RETRY WINS
	;   T1/GOOD DATA
	;   T3/RETRY WHICH SUCCEEDED (FIRST =1)

PRTRY:	MOVEI	T3,1		;INIT RETRY COUNTER
	MOVEI	T2,TRYBAD	;GET TRAP TEST ADDRESS
	EXCH	T2,.USPFN+1	;EXCHANGE WITH WHAT'S THERE NOW
	PUSH	P,.USPFP	;IF A TRAP HAPPENS, HOW WE GOT HERE IS LOST
	PUSH	P,.USPFP+1	;SAVE ORIG PC

PRTY1:	TRO	P2,PFCPF0	;NOTE THIS IS TEST REFERENCE
	WREBR	@.CPEBR##	;INVALIDATE CACHE
	MOVE	T1,0(P1)	;TRY THE REFERENCE
	TRZ	P2,PFCPF0	;CLEAR THE REFERENCE FLAG
	TRZN	P2,PFCPF2	;ERROR DURING REFERENCE?
	 JRST	PRTY3		;NO--GIVE A GOOD RETURN
	CAIGE	T3,TRPTRY	;YES--RETRY COUNT EXHAUSTED?
	AOJA	T3,PRTY1	;NO--TRY AGAIN
	SKIPA			;YES--GIVE AN ERROR RETURN
PRTY3:	AOS	-2(P)		;SET FOR SKIP RETURN
	POP	P,.USPFP+1	;RESTORE  PC

	POP	P,.USPFP	;RESTORE OLD CONTENTS
	EXCH	T2,.USPFN+1	;RESTORE STANDARD TRAP ADDRESS
	POPJ	P,		;EXIT

;HERE ON TRAPS OCCURING DURING RECOVERY ATTEMPTS
TRYBAD:	TRNN	P2,PFCPF0	;ARE WE HERE BECAUSE OF TEST REFERENCE?
	 STOPCD	(.,HALT,UPF)	;++UNEXPECTED PAGE FAIL
	LDB	T1,[POINT 5,.USPFW,5] ;GET PAGE FAIL CODE
	CAIGE	T1,PF.PAR	;PARITY OR NXM ERROR?
	STOPCD	(.,HALT,WPT)	;++WRONG PARITY TRAP
	TRO	P2,PFCPF2	;YES--INDICATE ERROR
	AOS	.USPFP+1	;GET PC OF TEST REFERENCE
	XJRSTF	.USPFP		;GO BACK AGAIN


;HERE WHEN RETRIES FROM MEMORY FAIL

PRHMF:	SETZM	.CPTGD##	;ZERO "GOOD DATA" SINCE WE DIDN'T GET ANY
	TRNN	P4,UE.NXM	;DON'T DO NEXT IF NXM
	SETZM	(P1)		;ZERO (AND RE-WRITE) THE ROTTEN LOCATION ALSO
	PUSH	P,P2		;SAVE P2
	PUSH	P,T3		;SAVE T3
	PUSHJ	P,PRTRY		;NOW SEE IF IT'S REALLY HARD (MEMORY BROKEN)
	  TDZA	P1,P1		;IT IS, SET P1 = 0
	SETO	P1,		;IT'S NOT, SET P1 = -1
	POP	P,T3		;RESTORE T3
	POP	P,P2		;RESTORE P2
	MOVE	T1,.CPMAP##	;GET .EPMP FOR THIS CPU
	POP	P,.ERPIL/PAGSIZ##(T1)

	AOS	.CPHPT##	;BUMP HARD (AR/ARX) PARITY TRAP COUNT
	TRO	P2,PFCPF0!PFCPF1;SAY HARD ERROR AND KS10 FOR ERROR REPORTING
	HRLM	P2,.CPPTR##	;SAVE FLAGS
	HRRM	T3,.CPPTR##	;SAVE RETRY COUNT FOR ERROR REPORTING
	TRNE	P4,UE.NXM	;IF THIS IS A NXM, MESSAGE IS DIFFERENT
	SKIPA	T1,[[ASCIZ /Retry unsuccessful./]]
	MOVEI	T1,[ASCIZ /Retry unsuccessful. Offending location zeroed./]
	PUSHJ	P,PRMSG		;ANNOUNCE FAILURE
	MOVEI	T1,.ERKPT	;ASSUME PARITY CODE FOR DAEMON
	TRNE	P4,UE.NXM	;IS THIS REALLY A NXM?
	MOVEI	T1,.ERKSN	;YES--GET NXM CODE
	HRL	T1,.CPSLF##	;AND CDB ADDRESS
	PUSHJ	P,DAEDIE##	;CALL DAEMON TO LOG ERROR
	MOVE	T1,.CPPPC##	;GET THE TRAP PC
	TLNE	T1,(XC.USR)	;IS THE TRAP FROM USER MODE?
	JRST	PRHMF1		;YES--GO KILL USER
	HRRZ	T1,.CPPFW##	;GET THE PROBLEM ADDRESS
	SKIPGE	.CPPFW##	;IS THIS A USER CONTEXT REFERENCE?
	JRST	PRHMF0		;YES--GO CHECK IF AT SCHED OR PI LEVEL
	MOVE	T2,SYSLEN##	;NO--GET LENGTH OF MONITOR'S HIGH SEG
	ADDI	T2,MONORG##-1	;FORM EVA OF THE TOP OF THE HIGH SEG
	CAIL	T1,MONORG##	;IS THE ERROR IN THE
	CAILE	T1,(T2)		; MONITOR'S HIGH SEGMENT?
	JRST	PRHMF0		;NO--GO CHECK OTHER THINGS
	LSH	T1,W2PLSH##	;YES--FORM THE EXEC VIRTUAL PAGE NUMBER
	MOVE	T2,.CPPBA##	;GET THE MAPPED PHYSICAL ADDRESS
	TDZ	T2,[777760,,777] ;ONLY WANT BASE ADDRESS OF PAGE
	PUSHJ	P,PAGRPL##	;TRY TO REPLACE THIS CODE PAGE
	  JRST	PARHLT##	;IT DIDN'T WORK
	MOVEI	T1,[ASCIZ /Replaced monitor code page from disk./] ;GET TEXT
	PUSHJ	P,PRMSG		;PRINT IT
	MOVEI	T1,EDELIM##	;GET END DELIMITER
	PUSHJ	P,PRMSG		;PRINT IT
	PJRST	PTXIT		;EXIT THE TRAP
PRHMF0:	SETOM	.CPREP##	;SET PARITY MSG FLAG IN CASE THIS IS FATAL
	TRNE	P4,UE.NXM	;IS THIS A NXM?
	SETZM	.CPREP##	;YES--SET FLAG PROPERLY
	SKIPN	.CPISF##	;ARE WE IN THE SCHEDULER
	CONSZ	PI,PI.IPA	; OR ARE WE AT INTERRUPT LEVEL?
	JRST	PARHLT##	;YES--SORRY BUT WE CAN'T DO A THING
	SKIPGE	.CPPFW##	;WAS THIS A MONITOR REF TO USER SPACE AT UUO LVL?
	JRST	PRHMF2		;YES--TREAT AS USER ERROR
	CAIL	T1,340000	;IS THE ERROR IN THE
	CAILE	T1,377777	; USER PER PROCESS AREA?
	JRST	PARHLT##	;NO--IT'S IN THE MONITOR DATA BASE, FATAL!
	SETZ	P2,		;YES, CALL IT A LOWSEG ERROR
	JRST	PRHMF3		;TREAT AS FATAL USER ERROR
PRHMF1:	TDNN	P4,.CPCN1##	;IS USER ENABLED TO HANDLE THIS HIMSELF?
	JRST	PRHMF2		;NO--GO ON
	MOVE	T2,JBTSTS##(J)	;YES--GET JOB STATUS WORD
	TLNE	T2,JACCT	;IS JOB PRIVILEGED?
	JRST	PRHF1A		;YES--TRAP TO HIM
	MOVE	T2,JBTPPN##(J)	;NO--GET HIS PPN
	CAME	T2,FFAPPN##	;IS IT THE OPERATOR PPN
	CAMN	T2,UMDPPN##	; OR THE USER MODE DIAG PPN?
	JRST	PRHF1A		;YES--LET'S TRAP TO HIM AS REQUESTED
	JRST	PRHMF2		;NO--THEN WE IGNORE HIS TRAP REQUEST
PRHF1A:	MOVEI	T1,EDELIM##	;GET END DELIMITER
	PUSHJ	P,PRMSG		;PRINT IT
	WRPI	PI.ON		;TURN PI'S BACK ON
	DMOVE	T1,.CPPPD##	;GET THE PROBLEM PC
	HRRZ	T3,P4		;PUT PARITY/NXM BIT HERE
	JRST	SAROV3		;GO TRAP TO USER
PRHMF2:	SETZ	P2,		;SET FLAG ASSUMING LOW SEG ERROR
	MOVE	J,.CPJOB##	;GET THE OFFENDING JOB #
	SKIPG	J,JBTSGN##(J)	;DOES THIS JOB HAVE A HIGH SEG?
	JRST	PRHMF3		;NO--GO ON
	HRRZ	T1,.CPPFW##	;GET THE PROBLEM ADDRESS
	CAML	T1,.USHSS	;IS ADDRESS IN THE USER HIGH SEGMENT?
	CAMLE	T1,.USHSE
	JRST	PRHMF3		;NO--GO ON
	SETO	P2,		;YES--SET FLAG INDICATING HIGH SEG ERROR
	PUSHJ	P,HGHPAR##	;GO PROCESS OTHER JOBS USING THIS SEGMENT
PRHMF3:	JUMPN	P1,PRHMF4	;IF MEMORY IS OK, DON'T MARK OUT PAGE
	LDB	T1,[POINT 13,.CPPBA##,26] ;GET THE PAGE NUMBER TO MARK OFF-LINE
	PUSH	P,T1		;SAVE PAGE NUMBER
	IDIVI	T1,^D36		;COMPUTE NXMTAB INDEX AND BITTBL INDEX
	MOVE	T2,BITTBL##(T2)	;GET CORRECT BIT TO SET
	IORM	T2,NXMTAB##(T1)	;MARK OUT PAGE IN NXMTAB
	MOVEI	T1,[ASCIZ /Location still bad after zeroing.
Setting off-line physical page /] ;GET TEXT
	POP	P,T2		; AND PAGE NUMBER
	PUSHJ	P,PRMOC		;TELL HIM WHAT WE DID
	MOVE	T1,[.CSCPO,,.ERCSC]
	PUSHJ	P,DAEDIE##	;LOG CONFIGURATION CHANGE
PRHMF4:	MOVEI	T1,EDELIM##	;GET END DELIMITER
	PUSHJ	P,PRMSG		;PRINT IT
	MOVE	J,.CPJOB##	;GET JOB NUMBER
	JUMPE	P2,PRHMF5	;GO STOP THIS JOB IF LOW SEG ERROR
	MOVEI	T1,JS.MPE	;DID HGHPAR SAY THAT THIS JOB
	TDNE	T1,JBTSTS##(J)	; COULDN'T BE SAVED?
	JRST	PRHMF5		;YES--JUST GO STOP IT
	WRPI	PI.ON		;NO--TURN PI'S BACK ON
	HLLZ	T1,.CPMPS##	;GET CPU REQUESTS MEMORY SCAN BITS
	HRRI	T1,(P4)		;SET PARITY OR NXM BIT
	IORM	T1,.CPAEF##	;SET REQUEST
	MOVE	P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;DUMMY STACK FOR WSCHED
	PUSH	P,.USPFP	;STACK RETURN USER ADDRESS FOR WSCHED
	PUSH	P,.USPFP+1	;SECOND HALF AS WELL

	PJRST	WSCHED##	;RESCHEDULE THIS JOB TO RE-RUN WITH NEW HIGH SEG

PRHMF5:	MOVSI	T1,JACCT	;CLEAR JACCT SO DAMAGED PROGRAM
	ANDCAM	T1,JBTSTS##(J)	; WON'T HAVE PRIVILEGES
	MOVEI	T1,JS.MPE	;ASSUME PARITY ERROR IN JOB
	TRNE	P4,UE.NXM	;IS IT A NXM?
	MOVEI	T1,JS.NXM	;YES--GET NXM IN JOB STATE BIT
	IORM	T1,JBTSTS##(J)	;SET IN JOB STATUS WORD
	HLLZ	T1,.CPMPS##	;GET CPU REQUESTS MEMORY SCAN BITS
	HRRI	T1,(P4)		;SET PARITY OR NXM BIT
	IORM	T1,.CPAEF##	;SET REQUEST FOR PI 7
	SETOM	.CPSCF##	;FORCE RESCHEDULE
	SETOM	.CPCKF##	;SET FLAG FOR PI 7 INTERRUPT
	WRPI	XI.RQC##	;REQUEST PI 7
	WRPI	PI.ON		;ALLOW INTERRUPTS NOW (MAINLY PI 7)
	PJRST	ESTOP##		;GO STOP THIS JOB
;HERE ON TRAP DURING PARITY SWEEP
SWTRP:	EXCH	T1,.CPSTT##	;RESTORE T1, SAVE TRAP CODE
	PUSH	P,T1		;SAVE T1
	HRRZ	T1,.USPFP+1	;GET PC OF TRAP
	CAIE	T1,CPSMPI	;BETTER MATCH THE SWEEP BLT ADDRESS
	STOPCD	(.,HALT,NPI)	;++NOT PARITY INSTRUCTION
	MOVE	T1,.USPFW	;GET THE PAGE FAIL WORD
	MOVEM	T1,.CPPFW##	;AND SAVE IT
	WRUBR	[SG.LAB+07B11]	;SET PREVIOUS AC BLOCK TO 7
	PXCT	PX.MEM,[MOVE T1,0] ;GET BAD DATA WORD FOR DAEMON
	EXECAC			;RESTORE MONITOR'S AC BLOCK
	MOVEM 	T1,.CPTBD##	;SAVE BAD DATA
	SETOM	.CPPTH##	;INDICATE ERROR ON SWEEP
	MOVEI	T1,3		;BUMP RETURN PC BY 3 TO
	ADDM	T1,.USPFP+1	; INDICATE A TRAP HAPPENED
	POP	P,T1		;RESTORE T1
	JRST	PTXIT1		;EXIT BACK TO SWEEP ROUTINE
;ROUTINE TO PRINT A MESSAGE PREFIXED BY "CPUx" AND
;FOLLOWED BY "AT EXEC(USER) PC XXXXXX"
;  T1=MESSAGE ADDRESS

PRMPC:	PUSHJ	P,SAVE1##	;SAVE P1 TO REMEMBER ADDRESS OF MESSAGE
	MOVE	P1,T1		;SAVE
	PUSH	P,.CPTOA##	;SAVE COMMAND OUTPUT ADDRESS
	MOVEI	T2,CTYWAT##	;GET ONE THAT DOESN'T USE PI SYS
	MOVEM	T2,.CPTOA##
	MOVEI	T1,SDELIM##	;GET ADDRESS OF TEXT
	PUSHJ	P,CONMES##	;PRINT START DELIMITER
	MOVE	T2,.CPLOG##	;GET THIS CPU'S NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	MOVE	T1,P1		;GET ADDRESS OF MESSAGE IN T1
	PUSHJ	P,CONMES##	;PRINT MESSAGE
	MOVE	T2,.CPPPC##	;GET SAVED PC
	PUSHJ	P,PCP##		;PRINT "AT EXEC/USER XXXXXX"
	MOVEI	T1,[ASCIZ / on /] ;SEPARATE FROM DATE/TIME
	PUSHJ	P,CONMES##	;PRINT IT
	PUSHJ	P,DAYTIM##	;PRINT DATE AND TIME
	MOVEI	T1,[ASCIZ /Job/];TELL THEM WHO WAS RUNNING
	PUSHJ	P,CONMES##	;PRINT "JOB"
	PUSHJ	P,PRJBNM##	;PRINT JOB INFO
	MOVEI	T1,[ASCIZ / was running
/]
	PUSHJ	P,CONMES##	;PRINT "WAS RUNNING"
PRMPC2:	POP	P,.CPTOA##	;RESTORE SCNSER ADDRESS
	POPJ	P,		;RETURN

;ROUTINES TO PRINT A MESSAGE FOLLOWED BY NUMBER IN HALFWORD OR OCTAL FORMAT
;  T1=MESSAGE ADDRESS, T2=NUMBER
PRMOC:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	MOVEI	P3,OCTPNT##	;GET ADDRESS OF OCTAL PRINT ROUTINE
	JRST	PRMHW1		;GO TO COMMON CODE
PRMHW:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	MOVEI	P3,HWDPNT##	;GET ADDRESS OF HALFWORD PRINT ROUTINE
PRMHW1:	MOVE	P1,T1		;SAVE
	MOVE	P2,T2		;SAVE
	PUSH	P,.CPTOA##	;SAVE COMMAND OUTPUT ADDRESS
	MOVEI	T2,CTYWAT##	;GET ONE THAT DOESN'T USE PI SYS
	MOVEM	T2,.CPTOA##
	MOVE	T1,P1		;GET ADDRESS OF MESSAGE IN T1
	PUSHJ	P,CONMES##	;PRINT MESSAGE
	MOVE	T1,P2		;GET NUMBER TO PRINT (IF ANY)
	PUSHJ	P,(P3)		;PRINT NUMBER IN DESIRED FORMAT
	PUSHJ	P,CRLF##	;END WITH CRLF
	PJRST	PRMPC2		;FINISH UP
;ROUTINE TO PRINT A MESSAGE
;  T1=MESSAGE ADDRESS

PRMSG:	PUSHJ	P,SAVE2##	;SAVE P1,P2 TO REMEMBER ADDRESS OF MESSAGE
	MOVE	P1,T1		;SAVE
	PUSH	P,.CPTOA##	;SAVE COMMAND OUTPUT ADDRESS
	MOVEI	T2,CTYWAT##	;GET ONE THAT DOESN'T USE PI SYS
	MOVEM	T2,.CPTOA##
	MOVE	T1,P1		;GET ADDRESS OF MESSAGE IN T1
	PUSHJ	P,CONMES##	;PRINT MESSAGE
	PUSHJ	P,CRLF##	;END WITH CRLF
	PJRST	PRMPC2		;FINISH UP
;HERE ON PAGE TABLE PARITY TRAP (PF CODE 25)
PTPAR:	WREBR	@.CPEBR##	;CLEAR THE PAGE TABLE
	AOS	.CPPTP##	;COUNT A PAGE TABLE PARITY ERROR
	MOVE	T1,.CPSTT##	;RESTORE T1
	MOVEM	T1,.CPA17##	;SAVE 17
	MOVEI	17,.CPA00##	;MAKE BLT POINTER
	BLT	17,.CPA17##-1	;SAVE ACS IN CPU DATA BLOCK
	MOVE	P,.CPEPD##	;SET UP ERROR STACK
	SKIPGE	T1,.CPPTF##	;PICK UP COUNT OF PAGE TABLE FAILURES
	MOVEI	T1,^D10		;NONE YET, INITIALIZE
	SOSG	T1		;IF COUNT HASN'T EXPIRED, JUST RETRY.
				; COUNTER IS RESET ON EVERY CLOCK TICK.
	STOPCD	.,HALT,PTP,	;++PAGE TABLE PARITY
	MOVEM	T1,.CPPTF##	;REMEMBER COUNTER
	DMOVE	T1,.USPFP	;GET PAGE FAIL PC
	DMOVEM	T1,.CPPPD##	;SAVE FOR PRINT ROUTINE

	MOVE	J,.CPJOB##	;SET UP J WITH CURRENTLY RUNNING JOB
	MOVEI	T1,[ASCIZ / page table parity trap/]
	PUSHJ	P,PRMPC		;ANNOUNCE ERROR
	MOVEI	T1,[ASCIZ /Page fail word = /]
	MOVE	T2,.USPFW
	PUSHJ	P,PRMHW		;PRINT THE PAGE FAIL WORD
	MOVEI	T1,[ASCIZ /CONI PI, = /]
	MOVE	T2,.CPTPI##
	PUSHJ	P,PRMHW		;PRINT THE CONI PI BITS
	MOVEI	T1,EDELIM##	;GET ADDRESS OF TEXT
	PUSHJ	P,PRMSG		;PRINT END DELIMITER
PTXIT:	MOVSI	17,.CPA00##	;BLT POINTER TO RESTORE ACS
	BLT	17,16		;RESTORE ACS
	MOVE	17,.CPA17##	;AC 17 ALSO
PTXIT1:	WRUBR	.CPTCX##		;RESTORE THE CONTEXT AT TIME OF TRAP
	EXCH	T1,.CPTPI##	;GET PI'S AT TRAP ENTRY, SAVE T1
	TRNE	T1,PI.ON	;WERE THE PI'S ON?
	WRPI	PI.ON		;YES--TURN PI'S BACK ON
	EXCH	T1,.CPTPI##	;RESTORE T1
	XJRSTF	.USPFP

;HERE TO HANDLE A PAGE FAULT

SEILMA:	MOVE	T1,.CPSTT##	;RESTORE T1
	WRPI	PI.ON		;RESTORE THE PI SYSTEM
	SKIPN	.CPEJ1##	;SKIP NEXT IF EXEC PAGE FAULT IN PROGRESS
	DMOVEM	T1,.CPST1##	;SAVE T1 AND T2 IN CASE OF CRASH
	DMOVE	T1,.USPFP	;GET THE PAGE FAIL PC
	DMOVEM	T1,.CPAPC##	;STORE IT AS POTENTIAL ERROR PC
	DMOVEM	T1,.USMUP	;STORE WHERE KI WOULD PUT IT
	HRR	T1,T2		;GET PC INTO T1 AS A ONE WORD PC

	MOVE	T2,.USPFW	;GET THE USER PAGE FAIL WORD
	MOVEM	T2,.CPPFW##	;SAVE PAGE FAULT WORD FOR CRASH
;	DPB	T2,[POINT 18,T2,32] ;SHIFT VIRTUAL ADDRESS OVER 3 PLACES
;	ROT	T2,6		;PLACE PAGE FAIL CODE AND VIRTUAL ADDRESS
;				;WHERE IT WAS ON KI10
;	TRZE	T2,40		;USER BIT ON?
;;	TLO	T2,(1B8)	;YES, SET IT WHERE KI10 USER BIT WAS
;				;WE NOW HAVE KI10 STYLE PAGE FAIL WORD.
;	AND	T2,[1777,,37]	;CLEAR UNUSED BITS
;	TLNE	T2,(1B8)	;USER REF?
;	TRNN	T2,10		;YES, ACCESS ALLOWED OFF?
;	JRST	SEILMB		;NOT USER REF OR ACCESS ALLOWED OFF
;	TRNN	T2,4		;USER REF, ACCESS ALLOWED ON. WRITE OFF?
;	TRO	T2,1		;YES, DEDUCE THAT HE TRIED TO WRITE
SEILMB:	TLNE	T1,(XC.USR)	;PAGE FAULT IN EXEC MODE?
	JRST	SEILM0		;NO, PROCEED
	JRST	SEILM7		;YES--EXEC ILL MEM REF, CHECK FOR ERJMP

SEILM0:	MOVE	P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
	SKIPN	.USJOB
	STOPCD	.,CPU,PFN	;++PAGE FAULT IN NULL JOB
	PUSH	P,T1		;SAVE USER'S PC
	MOVE	T3,T2		;FAULT WAS IN USER MODE, SAVE PFC FOR
				; POSSIBLE CALL TO USRFLT
	LDB	T2,[POINT 5,T2,5] ;CLEAR ALL BUT THE PAGE FAIL CODE
	MOVE	T4,.JDAT+JOBENB## ;GET APR ENABLE BITS
	TRNE	T4,AP.ILM	;IS USER ENABLED?
	JRST	SUILM		;YES--DO SUILM INSTEAD
	MOVE	T4,T1		;PC WORD INTO T4 FOR USRFLT
	DMOVE	T1,.USPFP	;GET DOUBLE WORD PC
	PUSHJ	P,USRFLT##	;SEE IF PAGE FAULT FOR A VM USER
				; WILL NOT RETURN IF SO (DISPATCH TO USER)
	HRRI	T1,AP.ILM	;COULDN'T HANDLE IT - USER GETS ILL MEM REF
	JRST	SEPDL1		;GO SAY "ILL. MEM. REF."
;HERE IF AN ILL MEM REF OCCURED IN EXEC MODE, CHECK FOR ERJMP OR
;ERCAL BEFORE CALLING IT AN IME

SEILM7:	CONSO	PI,PI.IPA	;AT INTERRUPT LEVEL?
	JRST	SEJLM2		;NO, UUO LEVEL, OK
	CONSO	PI,PI.IPA-PI.IP7 ;YES - LEVEL 7?
	SKIPN	.CPISF##	;YES, FROM SCHEDULER?
	JRST	SEILME		;PI1 - PI6 OR NON-SCHEDULER PI7
SEJLM2:	SKIPE	.CPEJ1##	;NESTING?
	JRST	SEILM8		;YES, IT'S AN IME
	MOVE	T2,.CPPFW##	;NO, GET PAGE FAULT WORD
IFN FTPEEKSPY,<
	JUMPG	T2,SEJL2A	;JUMP IF NOT USER REF
	PUSHJ	P,INTLVL##	;YES, AT UUO LEVEL?
	  PUSHJ	P,[PUSHJ P,SAVT## ;YES
		   MOVE  T1,.CPPFW## ;GET PAGE FAULT WORD
		   LSH	 T1,W2PLSH## ;PAGE NUMBER
		   ANDI  T1,HLGPGS
		   PUSHJ P,TSSPT## ;A SPY PAGE?
		     POPJ P,	;NO
		   PJRST UADERR##] ;YES,BLAME THE USER
SEJL2A:>
	DMOVEM	T1,.CPEJ1##	;"TOP LEVEL", REMEMBER IN CASE WE NEST
	MOVEM	T1,.CPEJ3##	;ALSO SAVE HERE FOR PSYCHOPATHIC CASES
	SKIP	(T1)		;TOUCH PAGE FAULT PC LOCATION AND
	LDB	T2,[POINT 13,1(T1),12]  ;GET INSTRUCTION FOLLOWING
				; IF THE PC JUMPED OFF INTO THE BOONIES
				; THEN THIS WILL PAGE FAULT AND WE WILL
				; KNOW WE HAVE A REAL IME
	CAIE	T2,<ERJMP>_-^D23	;IS IT AN ERJMP?
	JRST	SEILM8		;NO, THEN WE HAVE AN IME
	MOVE	T2,1(T1)	;GET ENTIRE ERJMP EXPRESSION
	MOVEM	T2,.CPEJ4##	;AND SAVE IT WHERE WE CAN FIND IT
	DMOVE	T1,.CPST1##	;RESTORE FULL AC SET
	MOVEI	T1,@.CPEJ4##	;GET "E" OF ERJMP
				; IF THIS IME'S (NOTE .CPEJ1 STILL
				; NON-ZERO) THEN .CPEJ3 HAS ORIGINAL
				; TRAP PC WHICH STARTED THIS MESS.
	HLLZS	.CPAPC##	;CLEAR JUNK IN RIGHT HALF OF FLAGS WORD (PCS)
	MOVEM	T1,.CPAPC##+1	;SET CONTINUATION ADDRESS
	MOVE	T1,.CPST1##	;RESTORE T1 AGAIN
	SETZM	.CPEJ1##	;CLEAR NESTING FLAG
	WRUBR	.CPTCX##	;RESTORE TRAP CONTEXT
	XJRSTF	.CPAPC##	;....

;HERE ON NESTED IME, "RESTORE" THE FIRST IME AND STOPCD

SEILM8:	DMOVE	T1,.CPEJ1##	;PAGE FAULT PC AND REASON WORDS
	MOVEM	T1,.CPAPC##	;SET TRUE ERROR PC
	MOVEM	T1,.USPFP	;ALSO MAKE UPMP LOOK RIGHT
	MOVEM	T2,.CPPFW##	;SET TRUE PAGE FAULT WORD
	MOVEM	T2,.USPFW	;ALSO MAKE UPMP LOOK RIGHT
SEILME:	SETZM	.CPEJ1##	;CLEAR NESTING FLAG
	STOPCD	.+1,JOB,IME,DIEIME ;++ILL MEM REF FROM EXEC
	DMOVE	T1,.CPST1##	;AND THE TEMP ACS USED
	JRSTF	@.CPAPC##	;RETURN

DIEIME:	PUSHJ	P,INLMES##	;ADD SOME TEXT
	ASCIZ	/Page fail word = /
	MOVE	T1,.USPFW	;GET PAGE FAIL WORD
	PJRST	HWDPNT##	;PRINT AS HALF-WORDS AND RETURN
;HERE FROM SEILM IF PAGE FAULT IS IN USER MODE AND APRENB DONE
; T1=USER PC AND T3=PAGE FAULT WORD
;T3=PAGE FAULT WORD
SUILMX::
	DMOVE	T1,.USMUO	;GET PC FROM "UUO"
	JRST	SUILM1
SUILM::	DMOVE	T1,.USPFP	;GET DOUBLE WORD PC
SUILM1:	MOVE	R,.CPADR##	;GET THE ADDRESS OF THE USER'S JOB DATA AREA
	PUSHJ	P,USRFLT##	;SEE IF PAGE FAULT FOR VM USER
				; WILL NOT RETURN IF SO (DISPATCH TO PFH)

	MOVEI	T3,AP.ILM	;SET ILM BIT FOR USER
	JRST	SAROV3		;FINISH UP
SUPDLO::
	DMOVE	T1,.USMUO	;GET FLAGS & PC
	MOVEI	T3,AP.POV	;SET POV BIT FOR USER
	JRST	SAROV3		;FINISH UP
;ONCE A SECOND TASKS FOR KS10'S
KSSEC::

;HERE ONCE A SECOND TO BE SURE UBA'S DIDN'T LOSE ASSIGNMENTS
	MOVEI	T2,UBA1PI##	;PI'S FOR UBA #1
	MOVEI	T1,UNBSTW	;UBA STATUS REGISTER ADDRESS
	HRLI	T1,1		;DO UBA #1
	PUSHJ	P,UBACHK	;CHECK IT
	MOVEI	T2,UBA3PI##	;PI'S FOR UBA #3
	HRLI	T1,3		;DO UBA #3
	PUSHJ	P,UBACHK	;CHECK IT

;HERE ONCE/SECOND TO COUNT THE KEEP ALIVE COUNTER FOR THE 8080 FRONT END
	LDB	T1,BKPALV	;GET THE CURRENT COUNT
	AOS	T1		;INCREMENT IT
	CAILE	T1,377		;WE COUNT IT MODULO 8-BITS
	SETZ	T1,
	DPB	T1,BKPALV	;PUT IT IN ITS PROPER PLACE
	POPJ	P,		;RETURN

BKPALV:	POINT	8,RLWORD,27	;BYTE POINTER TO KEEP ALIVE COUNT

UBACHK:	PUSHJ	P,UBGOOD	;IS UBA ALIVE?
	  POPJ	P,		;NO--THEN DON'T TRY TO ACCESS IT
	RDIO	T3,(T1)		;YES--GET UBA STATUS
	ANDI	T3,UNBDTR!77	;MASK OFF EXTRA BITS
	IORI	T2,UNBDTR	;SET DISABLE XFER BIT FOR COMPARE/SET
	CAMN	T3,T2		;ARE ALL THE BITS RIGHT ?
	POPJ	P,		;ALL OK
	STOPCD	(.+1,DEBUG,ULP)	;++UBA LOST ITS PI ASSIGNMENT
	WRIO	T2,(T1)		;REASSIGN LEVELS
	POPJ	P,
	SUBTTL	DTESER SIMULATION

;ROUTINES TO TURN KEEP ALIVE FUNCTION ON AND OFF WITH 8080 FRONT END
	$LOW
SVPPC::	PUSH	P,T1		;SAVE T1
	MOVSI	T1,(KPACT)	;KEEP ALIVE ACTIVE BIT
	TDNN	T1,RLWORD	;ARE WE GOING TO GET KAF'ED?
	JRST	DISKA1		;NO, JUST BE A LONG NO-OP
	ANDCAM	T1,RLWORD	;YES, CLEAR THE BIT
	MOVE	T1,(P)		;RESTORE T1
	ADJSP	P,-2		;BALANCE STACK
	PUSHJ	P,@1(P)		;CALL OUR CALLER
	  JRST	ENAKAL		;PROPAGATE NON-SKIP
	AOS	(P)		;AND SKIP
;FALL INTO ENAKAL

ENAKAL::PUSH	P,T1		;SAVE T1
	MOVSI	T1,(KPACT)	;KEEP ALIVE ACTIVE BIT
	IORM	T1,RLWORD	;SET IT
	PJRST	DISKA1		;RETURN

DISKAL::PUSH	P,T1		;SAVE T1
	MOVSI	T1,(KPACT)	;KEEP ALIVE ACTIVE BIT
	ANDCAM	T1,RLWORD	;CLEAR IT
DISKA1:	POP	P,T1		;CAN'T USE TPOPJ SINCE
	POPJ	P,		;  WE MAY NOT BE MAPPED
	$HIGH
;ROUTINE TO GET DATE AND TIME FROM THE FRONT END
;
;IN OUR CASE, THIS (MIGHT BE) A TCU150 ON THE UNIBUS

SPCGDT::MOVE	T1,[EXP CLKCSR]	;GET IO ADDRESS OF CSR
	PUSHJ	P,UBGOOD	;SEE IF INSTALLED
	 POPJ	P,		;NOT INSTALLED, CAN'T HELP
	MOVE	T1,[EXP CLKCSR]	;RESTORE IO ADDRESS
	RDIO	T2,0(T1)	;GET DATE
	RDIO	T3,2(T1)	;GET TIME
	HRL	T2,T3		;SAVE TIME,,DATE
	RDIO	T3,4(T1)	;GET SECOND
	LDB	T1,[POINT 7,T2,26]	;GET YEARS SINCE 1900
	ADDI	T1,^D1900	;MAKE INTO REAL YEAR
	CAIGE	T1,^D1964	;BASIC SANITY CHECK
	 POPJ	P,		;CLOCK IS BAD
	MOVEM	T1,LOCYER##	;SAVE YEAR
	LDB	T1,[POINT 4,T2,30]	;GET MONTH
	 SKIPE	T1		;SANE?
	CAILE	T1,^D12		;...
	 POPJ	P,		;NO
	MOVEM	T1,LOCMON##	;YES, SAVE MONTH
	SOJ	T1,		;MAKE INTO TABLE OFFSET
	LDB	T4,PMONTB##	;GET DAYS IN MONTH - 1
	AOJ	T4,		;MAKE ONE-BASED
	SOJN	T1,SPGDT1	;IF FEBRUARY
	MOVE	T1,LOCYER##	;GET YEAR
	TRNN	T1,3		;AND IF LEAP YEAR
	 AOJ	T4,		;ALLOW FOR EXTRA DAY
SPGDT1:	LDB	T1,[POINT 5,T2,35]	;GET DAY OF MONTY
	SKIPE	T1		;CHECK FOR SANITY
	CAMLE	T1,T4		;...
	 POPJ	P,		;BAD CLOCK
	MOVEM	T1,LOCDAY##	;SAVE DAY OF MONTH
	LDB	T1,[POINT 5,T2,9]	;GET HOUR
	CAILE	T1,^D24		;SEE IF MAKES SENSE
	 POPJ	P,		;SIGH
	CAIN	T1,^D24		;MIDNIGHT?
	 SETZ	T1,		;YES, USE OUR CONVENTION
	MOVEM	T1,LOCHOR##	;SAVE HOUR
	LDB	T1,[POINT 6,T2,17]	;GET MINUTE
	CAILE	T1,^D59		;MAKE SURE IT'S NOT JUNK
	 POPJ	P,		;PARANOIA 1, CLOCK 0
	MOVEM	T1,LOCMIN##	;SET MINUTE
	LDB	T1,[POINT 6,T3,35]	;GET SECOND
	CAILE	T1,^D59		;FINAL CHECK
	 POPJ	P,		;FAILED
	MOVEM	T1,LOCSEC##	;SET SECOND AND VALID FLAG
	JRST	CPOPJ1##	;SUCCESS
;ROUTINE TO SET HARDWARE AND SOFTWARE RELOCATION INFORMATION FOR CURRENT USER
;CALLING SEQUENCE:
;	PUSHJ	P,SETREL
;	...	RETURN HERE
;J = CURRENT JOB NUMBER
;R = PROTECTION,,RELOCATION FOR THE LOW SEGMENT

SETRLH::MOVE	J,.CPJOB##	;J=CURRENT JOB NUMBER
	MOVEI	T1,0
	DPB	T1,JBYHSS##	;FORCE MAP TO BE REDONE
SETREL::MOVE	J,.CPJOB##	;J = CURRENT JOB NUMBER
SETRL1::MOVE	R,JBTADR##(J)	;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
				; OF THE FIRST PAGE OF THE LOW SEGMENT
	MOVEM	R,.CPADR##	;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
	HLRZM	R,.CPREL##	;SET .CPREL FOR ADDRESS CHECKING
IFN FTTRPSET,<
	SKIPE	T1,.CPSTS##	;HAS TIMESHARING BEEN STOPPED VIA TRPSET
	CAIE	T1,(J)		;YES, IS IT THIS JOB?
	JUMPN	T1,SETRLZ	;NO, DON'T CHANGE THE UBR
>
	SKIPE	J		;NULL JOB ALWAYS HAS A UPMP
	JUMPE	R,SETRLZ	;THERE IS NO UPMP IF THE JOB HAS NO CORE
	HRRZ	T1,JBTUPM##(J)	;PAGE NUMBER OF THE CURRENT JOB'S UPMP
	JUMPE	T1,SETRL2	;DON'T CHANGE ANYTHING IF THERE ISN'T ONE
	HRLI	T1,(SG.LUB)	;SET THE LOAD BIT
IFN FTRTTRP,<
	MOVEM	T1,.CPDTO##	;SAVE FOR RTTRP INTERRUPT LEVEL USE
>
	CONO	PI,PI.OFF	;MAKE CHANGING ADDRESSABILITY ATOMIC
	HRRM	T1,@.CPSPT##

	WRUBR	T1		;SETUP THE UBR
	CONO	PI,PI.ON	;CONTEXT SWITCH NOW DONE

	JUMPE	R,SETRLZ	;DONE IF NULL JOB
	HLRZM	R,.USHVA	;SET .USHVA FOR ADDRESS CHECKING AT IRP LEVEL
	SKIPN	T1,.USREL	;HOLEY PROGRAM?
	HLR	T1,R
	HRRZM	T1,.JDAT+JOBREL##	;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL

	SKIPL	T1,JBTSGN##(J)	;JOB HAVE A REAL HIGH SEGMENT?
	SKIPA	T1,JBTADR##(T1)	;YES
	HRLZS	T1		;SIZE OF SPY SEGMENT OR ZERO IF NOT SPY SEGMENT
	LDB	T2,[POINT 9,T1,8];CURRENT SIZE -1 OF THE HIGH SEGMENT
	SKIPE	T1		;IS THERE A SPY OR HIGH SEGEMNT?
	ADDI	T2,1		;YES, ITS ACTUALLY ONE PAGE BIGGER
	LDB	T1,JBYHSS##
	MOVSI	T3,REDOMP!SEGMB	;FORCING THE MAP TO BE REDONE?
	TDNN	T3,JBTSGN##(J)
	CAIE	T1,(T2)		;HAS THE HIGH SEGMENT SIZE CHANGED SINCE THE
				; LAST TIME THIS JOB WAS RUN?
	PUSHJ	P,MAPHGH##	;YES, REDO THE HIGH SEGMENT PART OF THE MAP
	MOVSI	T1,REDOMP!SEGMB	;INDICATE MAP HAS BEEN REDONE NOW
	ANDCAM	T1,JBTSGN##(J)

SETRLZ:	MOVE	T3,JBTPDB##+0	;NULL JOB PDB
	PUSHJ	P,FNDPDS##	;SET UP W
SETRL2:	SKIPN	R,JBTADR##(J)	;RESTORE R - JOB HAVE CORE IN CORE?
	TDZA	T1,T1		;NO, MUST BE THE NULL JOB OR CORE 0
	MOVE	T1,.JDAT+JOBENB## ;JOB'S APR ENABLE BITS
	PJRST	SETCNA##	;SETUP APR ENABLE BITS FOR THE USER
				; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
;	MOVE	J,JOB NUMBER
;	PUSHJ	P,STEUB

MKADD::	CAME	J,.USJOB	;JOB ALREADY ADDRESSABLE?
STEUB::	CAILE	J,JOBMAX##	;IS THIS A LOW SEGMENT?
	POPJ	P,		;NO, THE UBR MUST ALREADY BE SETUP
				; OR DOESN'T NEED TO BE (ADDRESSES WILL BE
				; MAPPED THROUGH THE EXEC MAP)
	PUSH	P,T1		;SAVE A TEMPORARY
	HRRZ	T1,JBTUPM##(J)	;T1 = THE PAGE NUMBER OF THE USER PAGE MAP PAGE
	CONO	PI,PI.OFF	;NO INTERRUPTS WHILE CHANGING UBR/SPT
	SKIPE	T1		;IF NOT ZERO,
	HRRM	T1,@.CPSPT##	; SETUP NEW SPT
	TLO	T1,(SG.LUB)	;REQUEST LOADING OF UBR
	TRNE	T1,17777	;IS THERE A UPMP
	WRUBR	T1		;SET FOR CURRENT USER AND CLEAR THE AM
	CONO	PI,PI.ON	;BOTH THE SPT AND UBR HAVE BEEN CHANGED
	JRST	TPOPJ##		;RESTORE T1 AND RETURN
	SUBTTL	MONITOR CONTEXT SUPPORT ROUTINES

REPEAT 0,<

;COROUTINE TO CONTINUE A SUBROUTINE WITH DECNET CONTEXT SET UP AS
;PREVIOUS CONTEXT USER.
;
;ASSUMES CALLER IS IN REGULAR CONTEXT

SVEUD::	EXCH	J,(P)		;SAVE J, GET CALLER'S PC
	PUSH	P,J		;SAVE CALLER'S PC
				;ASSUME SOME JOB IS ADDRESSABLE
	MOVE	J,.UPMP+SECTAB+0 ;GET CURRENT SECTION POINTER
	EXCH	J,-1(P)		;GET J BACK, SAVE SECTION POINTER
	CONO	PI,PI.OFF	;MAKE SURE NO ONE GETS CONFUSED BY THIS
	PUSH	P,.E0DMP##	;SECTION POINTER TO DECNET CONTEXT
	POP	P,.UPMP+SECTAB+0 ;MAKE IT THE USER MAP
	WREBR	@.CPEBR##	;FLUSH PAGE TABLE
	ADJSP	P,-1		;GET CALLER'S PC OFF STACK
	PUSHJ	P,@1(P)		;CALL CALLER
	 CAIA
	AOS	-1(P)		;CALLER SKIPPED
	POP	P,.UPMP+SECTAB+0	;RESTORE UPMP
	WREBR	@.CPEBR##	;FLUSH PAGE TABLE
	JRST	ONPOPJ##	;RESTORE PI SYSTEM AND RETURN
IFN FTMP,<PRINTX ?MUST FIX .E0RMP/.E0DMP REFERENCES>

;COROUTINE TO CALL A SUBROUTINE IN REGULAR CONTEXT
;AND RESTORE ORIGINAL CONTEXT ON RETURN
;
;CALLED BY RGCALL MACRO

RGXCAL::PUSH	P,.E0RMP##	;GET SECTION 0 POINTER FOR NORMAL CONTEXT
	SKIPA			;AND FALL INTO DNXCAL

;COROUTINE TO CALL A SUBROUTINE IN DECNET CONTEXT
;AND RESTORE ORIGINAL CONTEXT ON RETURN
;
;CALLED BY DNCALL MACRO

DNXCAL::PUSH	P,.E0DMP##	;GET SECTION 0 POINTER FOR DECNET CONTEXT
	EXCH	T1,(P)		;SAVE T1, GET NEW CONTEXT
	PUSH	P,T1		;SAVE NEW CONTEXT MAPPING
	MOVE	T1,.CPEPT##	;ADDRESS OF THE EPT
	MOVE	T1,SECTAB+0(T1)	;GET CURRENT CONTEXT
	EXCH	T1,(P)		;SAVE CURRENT CONTEXT, GET NEW CONTEXT
	PUSH	P,T1		;SAVE NEW CONTEXT MAPPING
	HRRZ	T1,-3(P)	;GET THE PC FROM THE CALL
	HRRZ	T1,-1(T1)	;GET THE RH OF THE XCT INSTR
	MOVEI	T1,@1(T1)	;GET THE EFFECTIVE ADDRESS OF THE JUMP
	EXCH	T1,0(P)		;RESTORE NEW CONTEXT, SAVE WHERE TO GO
DNXCL1:	PUSHJ	P,ETRMAP	;SET UP NEW CONTEXT
	MOVE	T1,-2(P)	;GET BACK ORIGINAL CONTENTS OF T1
	PUSHJ	P,@0(P)		;CALL THE DESIGNATED ROUTINE
	  SKIPA			;PROPOGATE NON-SKIP RETURN
	AOS	-3(P)		;PROPOGATE SKIP RETURN
	MOVEM	T1,-2(P)	;STORE UPDATED CONTENTS OF T1
	ADJSP	P,-1		;CLEAN STACK
	POP	P,T1		;RESTORE ORIGINAL CONTEXT
	PUSHJ	P,ETRMAP	;...
	POP	P,T1		;RESTORE T1
	POPJ	P,		;AND RETURN
;CALL DNMAP TO MAKE DECNET BUFFERS ADDRESSABLE,
;RGMAP TO MAKE USUAL ADDRESS SPACE ADDRESSABLE. ALL ACS ARE PRESERVED.

RGPJ1::	AOS	(P)		;SKIP RETURN
RGMAP::	PUSH	P,T1		;SAVE T1
	MOVE	T1,.E0RMP##	;GET SECTION 0 POINTER FOR NORMAL CONTEXT
	JRST	ETRMP1		;FALL INTO ETRMAP

DNPJ1::	AOS	(P)		;SKIP RETURN
DNMAP::	PUSH	P,T1		;SAVE T1
	MOVE	T1,.E0DMP##	;GET SECTION 0 POINTER FOR DECNET CONTEXT
	JRST	ETRMP1		;FALL INTO ETRMAP

ETRMAP::
	PUSH	P,T1		;WE ADVERTISE THAT ALL ACS ARE PRESERVED
ETRMP1:	PUSH	P,T2		;...
	MOVE	T2,.CPEPT##	;ADDRESS OF THE EPT
	CAMN	T1,SECTAB+0(T2)	;SETTING UP DIFFERENT CONTEXT?
	JRST	TTPOPJ##	;NO, RESTORE ACS AND RETURN
	RDPI	ETRSPI		;SAVE THE PI SYSTEM STATE
	WRPI	PI.TFP+177	;PREVENT INTERRUPTS WHILE CHANGING EBR & SECTAB
	MOVEM	T1,SECTAB+0(T2)	;STORE NEW SECTION 0 POINTER
	ANDI	T1,17777	;ISOLATE PAGE NUMBER OF THE NEW MAP
	LSH	T1,P2WLSH##	;CONVERT TO ADDRESS
	MOVEM	T1,.CPMAP##	;ADDRESS OF CURRENT SECTION 0 MAP
	CONO	PAG,@.CPEBR##	;SO THE PAGING MEMORY SEES THE CHANGE
	MOVE	T1,ETRSPI	;GET SAVED PI STATE
	ANDI	T1,177		;KEEP JUST CHANNELS WHICH WERE ON
	WRPI	PI.TNP(T1)	;TURN THEM BACK ON
	JRST	TTPOPJ##	;RESTORE TEMPS AND RETURN

	$LOW
ETRSPI:	BLOCK	1		;SAVE PI STATE
	$HIGH
;COROUTINE TO ENTER DECNET CONTEXT FOR THIS SUBROUTINE (IF NOT THERE ALREADY)
;AND RETURN TO REGULAR CONTEXT ON EXIT.  NO-OP IF ALREADY IN DECNET CONTEXT

SVDCN::	PUSH	P,T1		;SAVE T1
	MOVE	T1,.CPEPT##	;GET EPT FOR THIS CPU
	MOVE	T1,SECTAB+0(T1)	;GET S0 POINTER
	CAMN	T1,.E0DMP##	;IS IT DECNET?
	JRST	TPOPJ##		;YES, DON'T DO ANYTHING
	EXCH	T1,(P)		;SAVE CURRENT CONTEXT, GET BACK T1
	EXCH	T1,-1(P)	;SAVE T1, GET RETURN PC
	PUSH	P,T1		;SAVE RETURN PC
	MOVE	T1,.E0DMP##	;GET DECNET CONTEXT MAPPING
	PJRST	DNXCL1		;CALL OUR CALLER AND RETURN
>;END REPEAT 0
SUBTTL	IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)

;HERE TO CHECK FOR EXISTENCE OF UBA DEVICES
; CALL	MOVE	T1,<ADR> OF DEVICE TO CHECK
;	PUSHJ	P,UBGOOD
;	LOSE RETURN
;	WIN RETURN
UBGOOD::PUSHJ	P,SAVT##	;RESPECT T REGS
	SETZ	T2,		;BITS FOR TIOE
	MOVE	T3,[EXP UBNOGD] ;TEMP PAGE FAIL TRAP ADDR
	RDPI	T4		;SAVE STATE OF PI'S
	WRPI	PI.OFF		;DISABLE INTERRUPTS
	EXCH	T3,.USPFN+1	;SET TEMPORARY PAGE FAIL TRAP ADR
	TIOE	T2,(T1)		;CHECK FOR DEVICE
	SKIPA			;FAILED
	AOS	(P)		;WIN
	MOVEI	T2,UNBNED!UNBTMO ;CLEAR NED IN UNIBUS ADAPTER
	HRRI	T1,UNBSTW	;GET BASIC ADDRESS OF UNIBUS
	BSIO	T2,(T1)		;CLEAR FLAGS
	MOVEM	T3,.USPFN+1	;RESTORE TRAP VECTOR
	TRNE	T4,PI.ON	;WERE PI'S ON?
	WRPI	PI.ON		;YES--THEN ENABLE THEM
	POPJ	P,		;RETURN

;HERE WHEN ADDRESS IS BUM
UBNOGD:	AOS	.USPFP+1	;SKIP LOSING INSTRUCTION
	JRST	@.USPFP+1	;JUST RETURN(NONSKIP)
SUBTTL	IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)

;ROUTINE TO SAVE AND OPTIONALLY SET UP THE USER BASE REGISTER
; AND RESTORE IT ON A CPOPJ OR CPOPJ1 RETURN
;CALLING SEQUENCE:
;	PUSHJ	P,SVEUB		;TO SAVE USER BASE REGISTER
;OR
;	PUSHJ	P,SVEUB		;TO SAVE USER BASE REGISTER AND SETUP
;				;USER BASE REGISTER FOR JOB IN J
;ALWAYS RETURN HERE

IFE FTXMON,<
SPCSF::			;THE KS DOESN'T DO EXTENDED ADDRESSING, YET
>
SVEUF::
	PUSH	P,@.CPSPT##

	PUSH	P,T1		;SAVE A TEMPORARY
	RDUBR	T1		;GET THE USER BASE REGISTERS
	PUSH	P,J		;SAVE J
	LDB	J,PJOBN##	;GET THE JOB NUMBER OF JOB CURRENTLY USING
				; THIS DEVICE
	PUSHJ	P,STEUB		;SETUP THE UBR SO CURRENT JOB IS ADDRESSABLE
	POP	P,J		;RESTORE J
	JRST	SSEU1		;SAVE THE PREVIOUS CONTENTS OF THE UBR AND EBR

IFE FTXMON,<
SPCSB::				;SET PCS FROM DEVISN
>
SVEUB::	PUSH	P,@.CPSPT##
	PUSH	P,T1		;SAVE A TEMPORARY
	RDUBR	T1		;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
	PUSHJ	P,STEUB		;SETUP THE UBR FOR THE JOB WHOSE JOB NUMBER
				; IS IN J
	JRST	SSEU1		;SAVE THE PREVIOUS CONTENTS OF THE UBR AND THE EBR


SSEUB::	PUSH	P,@.CPSPT##
	PUSH	P,T1		;SAVE A TEMPORARY
	RDUBR	T1		;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
SSEU1:	EXCH	T1,-2(P)	;GET THE CALLER'S PC AND SAVE THE CONTENTS
				; OF THE UBR AND EBR
	EXCH	T1,0(P)		;SAVE THE CALLER'S PC IN A TEMPORARY LOCATION
				; ON THE STACK AND RESTORE T1
	PUSHJ	P,@0(P)		;RETURN TO THE CALLER LEAVING .+1 ON THE
				; STACK SO WHEN THE CALLER DOES A POPJ OR
				; A CPOPJ1, CAN RESTORE THE PREVIOUS CONTENTS
				; OF THE UBR AND THE EBR
	  CAIA			;CPOPJ RETURN
	AOS	-3(P)		;CPOPJ1 RETURN - BUMP RETURN PC
	ADJSP	P,-1		;TOSS CALLER'S PC
	CONO	PI,PI.OFF	;DON'T ALLOW INTERRUPTS UNTIL UBR/SPT AGREE
	POP	P,@.CPSPT##

	EXCH	T1,0(P)		;GET THE PREVIOUS CONTENTS OF THE UBR(&SAVE T1)
	RDUBR	1(P)		;GET PRESENT UBR
	CAMN	T1,1(P)		;GOING TO CHANGE IT TO WHAT IT IS?
	JRST	SSEU2		;YES, DON'T CLEAR THE PAGING MEMORY
	WRUBR	T1		;RESTORE THE UBR
SSEU2:	CONO	PI,PI.ON	;SAFE TO ALLOW INTERRUPTS
	JRST	TPOPJ##		;AND RETURN
;ROUTINE TO SET UP UNIBUS ADAPTER MAPPING REGISTERS FOR A GIVEN
;IOWD FOLLOWING THE PAGING OF A JOB.  PRESERVES T1-T4, P3, P4.
;
;CALL	MOVE	T2,IOWD
;	MOVEI	P1,0		;FIRST CALL
;	MOVE	P3,LOC OF CHANNEL DATA BLOCK
;	MOVE	P4,FRAME-COUNT,,CHARS/WD IF TU45
;	PUSHJ	P,MAPIO
;RETURN	CPOPJ	IF IOWD EXCEEDS AVAILABLE PAGING REGISTERS
;	CPOPJ1	P2=ADDRESS OF FIRST PAGING REGISTER USED
;		P1=ADDRESS OF NEXT PAGING REGISTER TO BE USED

MAPIO::	TLNN	T2,-1		;0 OR CHANNEL JUMPS ARE ILLEGAL
	STOPCD	CPOPJ##,DEBUG,IEZ,  ;++IOWD EQUALS ZERO
	PUSHJ	P,SVEUB		;SAVE AND SETUP UBR
	PUSHJ	P,SAVT##	;SAVE T REGS
	PUSH	P,U		;SAVE U
	MOVE	P1,CHNIMR##(P3)	;UBA #,,1ST ASSIGNED PAGING REGISTER
	HRRZI	T4,-UBAEXP(P1)	;OFFSET FROM BASE OF UBA PAGING REGISTERS
	LSH	T4,P2WLSH##	;CONVERT TO PAGES
	MOVE	U,T2		;SAVE IOWD IN U
	AOS	T2		;ACCOUNT FOR FACT THAT IOWD'S ARE ADDR-1
	ANDI	T2,PG.BDY##	;GET LOW 9 BITS OF STARTING ADDRESS
	ADD	T4,T2		;FORM STARTING "DOUBLE-WORD" -11 ADDRESS
	LSH	T4,2		;TURN INTO BYTE ADDRESS
	MOVEM	T4,CHNIEA##(P3)	;AND SAVE IN CHANNEL DATA BLOCK
	MOVE	T4,CHNMRC##(P3)	;GET MAPPING REGISTER COUNT
	MOVE	T2,U		;T2 AND U = IOWD
	HLROS	U		;U = -WORD COUNT
	MOVEI	T2,1(T2)	;STARTING ADDRESS
	PUSHJ	P,V2PADR	;SEE WHAT KIND OF REFERENCE THIS IS
	 JFCL			;ILLEGAL, WE'LL CATCH IT LATER
	TLZE	P1,(1B0)	;EXEC?
	CAIE	T2,1		;YES, "NO DATA XFER" TYPE IOWD? (INCREMENTED)
	JRST	MAPIO1		;NO, CONTINUE
	MOVEI	T2,CHNDBF##(P3)	;YES, POINT TO ADDRESS OF DUMMY BUFFER
	SETOM	CHNNXF##(P3)	;SET FLAG FOR DEVICE DRIVER TO SET ADDRESS INH
MAPIO1:	MOVE	T1,T2		;ANOTHER ADDRESS (THIS BECOMES A FLAG)
MAPIO2:	PUSHJ	P,V2PADR	;GET PHYSICAL ADDRESS IN T3
	 SKIPGE	USRHCU##	;IF SAVE IN PROGRESS
	SKIPA			;THEN, WE LET ERROR PASS

	 STOPCD	.,JOB,AAO,	;++ACCESS ALLOWED OFF (BUT THE IOWD ADDRESS CHECKED)
	TLZ	P1,(1B0)	;CLEAR EXEC ADDRESS FLAG
	LSH	T3,W2PLSH##	;GET PAGE NUMBER FOR UBA MAPPING
	PUSHJ	P,SETUBB	;GO SET PROPER UBA BITS IN T3
	WRIO	T3,(P1)		;AND LOAD THE PAGING RAM
	JUMPE	T1,MAPIO3	;IF NOT FIRST PAGE, DO WHOLE PAGE
	ANDI	T1,PG.BDY##	;EXTRACT THE WORD NUMBER
	SUBI	T1,PAGSIZ##	;CALCULATE THE NUMBER OF WORDS DONE IN FIRST PAGE
	CAIA			;SKIP PASS 2 CODE
MAPIO3:	 MOVNI	T1,PAGSIZ##	;(- # DONE)
	SUB	U,T1		;-#LEFT = -#LEFT --#DONE
	JUMPGE	U,MAPIO6	;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
	MOVEI	T1,0		;START NEXT PAGE AT ADDRESS 0
	ADDI	P1,1		;POINT TO NEXT MAPPING REGISTER
	ADDI	T2,PAGSIZ##	;STEP TO NEXT PAGE
	SOJG	T4,MAPIO2	;CONTINUE IF THERE IS ROOM
;	JRST	MAPI5A		;WHOOPS! OUT OF PAGING REGISTERS
	SETZ	P1,		;INDICATE NONE
	STOPCD	(UPOPJ##,JOB,OMR) ;++OUT OF MAPPING REGISTERS

	;HERE WITH ENTIRE IOWD MAPPED
	;U/ NUMBER OF WORDS OF LAST PAGE MAPPED BUT NOT USED

MAPIO6:	HRRZ	P2,P1		;GET LAST USED REGISTER ADDRESS
	MOVNS	U		;NEGATE U (NOW - XTRA WDS MAPPED)
	ANDI	U,PG.BDY##	;WORDS INTO LAST PAGE TO TRANSFER
	SKIPN	U		;JUST CROSSED PAGE BOUNDARY?
	 AOS	P2		;YES, ACCOUNT FOR IT
	LSH	U,2		;MAKE INTO AN ELEVEN STYLE ADDRESS
	HRRZI	P2,-UBAEXP(P2)	;GET OFFSET INTO MAPPING REGISTERS
	IMULI	P2,UBAMUL	;MAKE INTO 11 STYLE ADDRESSING
	ADDB	P2,U		;FORM ADDRESS OF LAST WORD TO TRANSFER
	SUB	U,CHNIEA##(P3)	;MINUS STARTING ADDRESS
	TLNE	P4,-1		;USER FRAME COUNT?
	 HLRZ	U,P4		;YES, BELIEVE USER
	MOVEM	U,CHNBTC##(P3)	; AND SAVE THE TOTAL BYTE COUNT
	SKIPGE	CHNNXF##(P3)	;IS THIS A NO-XFER REQUEST?
	 MOVE	P2,CHNIEA##(P3)	;YES--THEN ENDING ADDRESS WILL EQUAL STARTING ADDR
	SKIPGE	P3		;WANT TERMINATION EXPECTED?
	 MOVEM	P2,CHNTCW##(P3)	;STORE FOR LATER CHECKING
	MOVE	P2,CHNIMR##(P3)	;GET ADDRESS OF INITIAL MAPPING REGISTER
	PJRST	UPOPJ1##	;SKIP RETURN
;ROUTINE TO SET THE PROPER BITS FOR A UBA PAGING RAM ENTRY WHICH IS IN T3.
;THE BIT SETTINGS DEPEND ON WHAT KIND OF A DEVICE IS BEING RUN THROUGH MAPIO.

SETUBB:	PUSHJ	P,SAVE1##	;SAVE P1
	SKIPN	P1,DEVMOD(F)	;PICK UP DEVICE CLASSES
	 MOVEI	P1,DVDSK	;MUST BE READING HOME BLOCKS
	TRO	T3,UNBVBT	;ALWAYS SET VALID
	SKIPE	CHNRRV##(P3)	;ARE WE DOING A READ REVERSE OPERATION?
	 TRO	T3,UNBRRV	;YES--SET READ REVERSE
IFN FTSPL,<
	SKIPL	DEVSPL(F)	;SPOOLED DDB'S ARE ALWAYS DISKS
>;FTSPL
	TLNE	P1,DVDSK	; OR IF A "REAL" DISK DDB
	 TRO	T3,UNB36B	; SET FAST XFER MODE
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;IF A SPOOLED DDB (I.E. DISK)
	 POPJ	P,		; WE'RE DONE
>;FTSPL
	TLNE	P1,DVLPT!DVCDR	;IF AN LP20 OR CD20
	 TRO	T3,UNBD18	; SET 18 BITS DISABLE (16 BIT MODE)
	POPJ	P,		;RETURN
;ROUTINE TO TURN A VIRTUAL ADDRESS INTO A PHYSICAL ONE.
;WORRIES ABOUT WHAT SORT OF VIRTUAL ADDRESS IT MIGHT BE (EXEC, USER...)
;
;CALL:	T2/ADDRESS TO MAP
;	F/DDB THAT WANTS IO
;	PUSHJ	P,V2PADR
;	 HERE WHEN PAGE ISN'T ACCESSIBLE (USUALLY RESULTS IN AN AAO)
;	HERE WHEN MAPS OK, T3 IS PHYSICAL ADDRESS.
;
;ONLY T3 IS TRASHED

V2PADR:	MOVE	T3,DEVMOD(F)	;GET DEVMOD
IFE FTSPL,<
	TLNN	T3,DVDSK!DVLPT!DVCDR	;IF A DSK (OR LP20 OR CD20)
>
IFN FTSPL,<
	SKIPL	DEVSPL(F)	;SPOOLED DDBS ARE ALWAYS A DSK
	 TLNE	T3,DVDSK!DVLPT!DVCDR	;IF A DSK (OR LP20 OR CD20)
	CAIA			;MONITOR IO IS POSSIBLE
>
	SKIPN	T3		;IF MIGHT BE READING HOME BLOCK
	 SKIPL	S		; SKIP IF MONITOR IO
	SKIPA	T3,[PXCT 4,[MAP T3,(T2)]] ;NOT MONITOR SPACE, MAP AS USER
	 TLOA	P1,(1B0)	;REMEMBER THIS IS EXEC
	TLZA	P1,(1B0)	;THIS IS NOT
	 MOVSI	T3,(MAP T3,(T2));MONITOR IO, MAP AS EXEC ADDRESS
IFN FTXMON,<			;SHOULD A KS EVER DO EXTENDED SECTIONS
	HRL	T2,DEVISN(F)	;SECTION NUMBER FOR IO
	PUSHJ	P,SSEC1		;ENTER SECTION 1
>
	XCT	T3		;MAP EXEC OR USER, RESULT IN T3
	TLNN	T3,(1B8)	;PAGED REFERENCE? (OUGHTA BE 1)
	 JRST	V2PAD1		;NO, WILL NOT FAULT
	TLNN	T3,(1B1)	;HARD PAGE FAILURE?
	 TLNN	T3,(17B5)	;...

	POPJ	P,		;YES TO EITHER, ACCESS DENIED
V2PAD1:	TLZ	T3,777760	;ACCESS IS OK, CLEAR ACCESS BITS
	JRST	CPOPJ1##	;RETURN SUCCESS
;ROUTINE TO INVALIDATE ENTIRE CACHE AND VALIDATE CORE
; ALWAYS RETURN CPOPJ, SAVING ALL T ACS.

CSDMP::	WREBR	@.CPEBR		;CAUSE CACHE FLUSH
	AOS	.CPCSN##	;COUNT THE SWEEP
	POPJ	P,		;RETURN
SUBTTL	ERRCON - ERROR HANDLING MODULE

;SUBROUTINE TO SWEEP MEMORY TO FIND ADDRESS AND CONTENTS OF BAD WORDS
;IT CALLS CPU INDEPENDENT SUB.(PARERR) TO RECORD DATA ON EACH BAD WORD
;CALL:	PUSHJ	P,@.CPMPS##
;	ALWAYS RETURN WHEN SWEEP OVER (EVEN IF SERIOUS ERROR)
;SWEEP CORE IN ASCENDING ADDRESSES EVEN THOUGH SLOWER, SO DATA STORED ASCENDING
; FOR ERROR REPORTING WITH DAEMON

CPSMPS::PUSHJ	P,MAPLOC##	;GET EXEC MAP SLOT
	MOVE	W,T1		;SAVE BYTE POINTER TO EXEC MAP SLOT
	MOVSI	P3,(<PM.DCD>B2+PM.WRT+PM.PUB)

	LDB	T4,[POINT 14,NWCORE##,26] ;T4=NUMBER OF PAGES TO SCAN
	SKIPA	P4,[POINT 1,NXMTAB##] ;BYTE POINTER TO NXM TABLE
MPSLP1:	AOS	P3		;STEP TO NEXT PAGE
	SOJL	T4,MPSLP5	;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
	ILDB	T1,P4		;DOES THIS PAGE EXIST?
	JUMPN	T1,MPSLP1	;IF NOT, GO BACK FOR NEXT
	DPB	P3,W		;MAP THE CURRENT PAGE
	MOVE	P1,T3		;EVA FOR BEGINNING OF PAGE
	CLRPT	(P1)		;CLEAR HDW PAGE TABLE FOR NEW MAPPING
	MOVEI	T2,PAGSIZ##	;NO. OF WORDS/PAGE TO SCAN
	WREBR	@.CPEBR##	;INVALIDATE CACHE
	SETOM	.CPPSP##	;SET SWEEPING FLAG
CPSMPI::MOVE	P2,(P1)		;TEST NEXT LOCATION
MPSLP2:	SOJLE	T2,MPSLP1	;IF CURRENT PAGE DONE, MAP NEXT
	AOJA	P1,CPSMPI	;GO TEST NEXT WORD IN PAGE

;HERE ON BAD WORD FOUND (NXM OR PARITY) - TRAP HAPPENED AND ADDED 3 TO PC
	MAP	T1,(P1)		;GET THE PHYSICAL ADDRESS OF BAD WORD
	PUSH	P,P1		;SAVE THE EVA
	PUSH	P,T2		;SAVE THE WORD NUMBER IN CURRENT PAGE
	PUSH	P,T3		;SAVE THE POSITION IN THE MAP
	PUSH	P,T4		;SAVE # OF PAGES TO SCAN
	LDB	P1,[POINT 22,T1,35] ;GET JUST THE PHYSICAL ADDRESS OF BAD WORD
	PUSHJ	P,CPIASN##	;CONVERT TO SEG NUMBER IN J
	  TDZA	T1,T1		;INDICATE NO ERROR IN MONITOR OR JOB
	SETO	T1,		;INDICATE AN ERROR IN MONITOR OR JOB
	MOVE	P2,.CPTBD##	;GET BAD DATA WORD STORED BY THE TRAP ROUTINE
	PUSHJ	P,PARRBD##	;RECORD BAD DATA
	POP	P,T4		;RESTORE T4
	POP	P,T3		; AND T3
	POP	P,T2		; AND T2
	POP	P,P1		; AND P1
	SETZM	.CPPTH##	;CLEAR FLAG THAT TRAP HAPPENED
	JRST	MPSLP2		;GO CONTINUE THE SWEEP

MPSLP5:	SETZM	.CPPSP##	;CLEAR SWEEPING FLAG
	PUSHJ	P,UNMAP##	;RESTORE EXEC MAP SLOT
	POPJ	P,		;AND RETURN
	$LIT
KSEND:	END