Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99q-bb - segcon.x23
There is 1 other file named segcon.x23 in the archive. Click here to see a list.
TITLE	SEGCON - HIGH SEGMENT CONTROL FOR REENTRANT USER PROGRAMMING V1243
SUBTTL	T. HASTINGS/TW/TNM/TH/AF/CHW/TW/PFC/DAL	16-MAY-89

	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1988>


XP VSEGCN,1243
		;PUT VERSION NUMBER IN GLOB LISTING AND LOADER MAP

;ALL OF THE CODE DEALING WITH THE SECOND RELOCATION REGISTER HAS BEEN ISOLATED
;IN THIS ONE ROUTINE NAMED SEGCON

;SIX OF THE MONITOR MODULES CALL SUBROUTINES IN SEGCON WITH PUSHJ'S.
;THIS HAS BEEN DONE FOR TWO REASONS:
;	1.TO MAKE IT EASY TO BUILD SYSTEMS WITH OR WITHOUT 2 REG. CAPABILITY
;	SEGCON CAN BE REPLACED BY A SHORT DUMMY ROUTINE(NULSEG), SO THERE
;	IS NO CONDITIONAL ASSEMBLY REQUIRED TO ELIMINATE MOST OF THE CODE.
;	THOSE CUSTOMERS WHO WOULD LIKE TO ELIMINATE ALL OF THE CODE MAY DO SO BY
;	REASSEMBLING THE MONITOR WITH FEATURE SWITCH FT2REL=0.
;	THIS WILL ELIMINATE ALL PUSHJ CALLS TO SEGCON

;	2. TO MAKE IT CLEAR EXACTLY WHERE TWO SEGMENTS ARE DEALT WITH


;ALL OF THE CALLS TO SEGCON ARE OF THE FORM:
;IFN FT2REL,<
;	EXTERN	XXXXXX
;	PUSHJ	P,XXXXXX
;	ERROR RETURN OR NOTHING TO DO
;	OK RETURN
;>

;OR:
;IFN FT2REL,<
;	EXTERN	XXXXXX
;	PUSHJ	P,XXXXXX
;	OK RETURN
;>

;SEGCON IS GOOD FOR SWAPPING AND NON-SWAPPING SYSTEMS
;AND FOR SYSTEMS WITH AND WITHOUT DISK
;TO MAKE IT CLEAR WHERE EACH SUBROUTINE IS CALLED FROM
;AND WHAT FUNCTION IT IS PERFORMING, THE MODULES OF THE MONITOR HAVE BEEN REPLICATED
;IN SEGCON USING SUBTTL.  THE MODULES ARE:
;	1. CLOCK
;	2. COMCSS
;	3. CORE1
;	4. SAVGET
;	5. SWAP
;	6. UUOCON
	
;ADDITIONAL MONITOR DATA TO HANDLE TWO SEGMENT USER PROGRAMS:

;A NUMBER OF THE ALREADY EXISTING JOB TABLES HAVE BEEN LENGTHENED
;BY AN AMOUNT SEGN(THE NUMBER OF POSSIBLE HIGH SEGMENTS).  THE LOWER
;PART OT THESE TABLES HAVE REMAINED AS THEY WERE(O THRU JOBMAX=JOBN-1)
;WITH ONE WORD PER JOB( OR LOW SEGMENT).  THE NEW HALF(GREATER THAN JOBMAX)
;HAVE ONE WORD FOR EACH HIGH SEGMENT.  A HIGH SEGMENT NUMBER IS REALLY
;A LARGE JOB NUMBER AND IS AN INDEX INTO THE JOB TABLES.
;THE HIGHEST INDEX IN THESE LENGTHENED JOB TABLES IS JBTMAX.
;THERE IS AT LEAST ENOUGH TABLE SPACE SO THAT EACH JOB CAN HAVE A
;DIFFERENT HIGH SEGMENT.  THE FOLLOWING TABLES HAVE BEEN LEGNTHENED:

;JBTSTS- JOB(SEG) STATUS
;	LH=STATUS BITS:
;		SWP=1 IF HIGH SEG SWAPPED OUT(WHETHER SPACE ON DISK OR NONE)
;			OR ON WAY IN OR OUT.  IE SWP=1 MEANS NOT RUNABLE COR IN CORE.
;			SWP=0 WHEN HIGH SEG HAS RUNABLE COR IN CORE
;			EVEN THOUGH ALSO HAS SPACE ONDISK.

;		SNA=1 IF HIGH SEG NO. APPEARS IN AT LEAST ONE USER'S LOGICAL ADR. SPACE
;			SNA IS SIGN BIT OF JBTSTS.
;		SNA=0 IF HIGH SEG IS COMPLETELY FREE OR IS DORMANT,
;		WHERE DORMANT MEANS THAT THE SEGMENT DOES NOT APPEAR IN ANY USER'S
;		  LOGINCAL ADDRESSING SPACE, BUT IS STILL AROUND PHYSICALLY ON DISK
;		  OR IN CORE
;		SHRSEG=1 IF SEG IS SHARABLE(WHETHER IT STILL HAS A NAME OR
;			HAS BEEN SUPERCEDED).
;	BITS 9-17 ARE ACCESS PRIBILEGES - SAME FORMAT AS DISK FILES
;		HSAPOS=RIGHT MOST BIT POSITION
;		HSAMSK=MASK FOR BITS(ALL ONES)
;		HSASIZ=SIZE OF FIELD
;	RH=IN-CORE COUNT(RATHER THAN RUN TIME LEFT) IE NUMBER OF JOBS
;		IN CORE USING HIGH SEG IN CORE
	
;JBTADR- HIGH JOB(SEG) CORE ASSIGNMENT
;	LH=LENGTH-1 OF HIGH SEG(NOT PROTECTION LIKE LOW SEG)
;		FOR LOW SEGS PROTECTION(HIGHEST LEGAL USER ADDRESS) AND LENGTH-1
;		ARE THE SAME. HOWEVER THEY ARE DIFFERENT FOR HIGH SEGS, SO LENGTH-1
;		WAS CHOSEN INSTEAD OF THE PROTECTION AS THE QUANTITY FOR THE LH.
;	RH=ABSOLUTE ADR. OF BEG OF HIGH SEG(NOT RELOCATION LIKE LOW SEG)
;		FOR LOW SEGS THE RELOACTION AND THE ABSOLUTE ORIGIN ARE THE SAME.
;		HOWEVER THEY ARE DIFFERENT FOR HIGH SEGS, SO THE ABSOLUTE ORIGIN WAS
;		CHOSEN INSTEAD OF THE RELOCATION AS THE QUANTITY FOR THE RH.
;	0 MEANS NO CORE IN MEMORY AT ALL
;	CORE IS ASSIGNED DURING SWAP IN AND OUT TOO
;JBTIMI/JBTIMO JOB SWAP INFO
;	JBTIMI/JBTIMO REPLACE OLD IMGIN/IMGOUT RESPECTIVELY=# OF PAGES WHEN
;	BROUGHT IN OR # OF PAGES ON DISK
;	OLD LEFT HALF OF JBTSWP-DSK ADDR-NOW LEFT HALF OF JBTSWP
;JBTCHK- CHECKSUM FOR HIGH SEG WHEN SWAPPED OUT
	
;THE FOLLOWING JOB TABLES HAVE BEEN ADDED:
;JBTSGN(0...JOBMAX) - HIGH SEG NUMBER WHICH JOB IS USING IN CORE OR ON DISK
;	0 MEANS JOB DOES NOT HAVE A HIGH SEGMENT.
;		LH BITS:
;	SPYSEG=1(SIGN BIT) HIGH SEG IS PART OF PHYSICAL CORE(SPY UUO),
;	 RH IS HIGHEST PHYSICAL ADR FOR THIS USER TO LOOK AT
;	SERSEG=1 MEANS THAT THE HIGH SEG WHICH THIS USER IS USING IS SHARABLE
;	 THIS BIT ALSO APPEARS IN THE JBTSTS WORD IN THE SAME POSITION
;	 IN THE WORD, SINCE SHARABLE IS A PROPERTY OF A SEGMENT, NOT OF
;	 THE JOB USING THE SEGMENT.  IT IS DUPLICATED HERE ONLY AS
;	 A CONVENIENCE SO IT WILL APPEAR IN THE LH OF AC ITEM.
;	UWPOFF=1 USER WRITE PROTECT IS OFF FOR THIS USER(NORMALLY 
;	  UWP OS ON, SO UWPOFF=0)
;	 MEDDLE=1 IF USER HAS MEDDLED WITH PROGRAM SO HE SHOULD NOT BE ALLOWED
;		TO TURN OFF UWP OR CHANGE CORE ASSIGNMENT
;		MEDDLE IS SET ONLY IF HIGH SEG IS SHARABLE OR A SPY SEG
;		MEDDLING IS DEFINED AS ANYTHING WHICH CAUSES THE PROGRAM NOT
;		NOT TO BE IN CONTROL OF ITSELF:
;		1. START COMMAND WITH ARG
;		2. DEPOSIT COMMAND(D) IN LOW SEG(HIGH SEG ALWAYS ILLEGAL)
;		3. RUN UUO WITH BIGGER START ADR. INCREMENT THAN 0 OR 1
;		4. GETSEG UUO
;		5. HIGH SEG IS PHYSICAL CORE(SPY UUO)
;CORCNT=1 IF HIGH SEG IN CORE COUNT HAS BEEN INCREMENTED FOR THIS JOB
;		 (JOB LOW SEG MAY OR MAY NOT BE IN CORE)
;		 SET BY INCCNT ROUTINE, CLEARED BY DECCNT ROUTINE
;JBTDEV(JOBN...JBTMAX) - HIGH SEG DEVICE NAME OF FILE STRUCTURE NAME
;			(EG DSKA,DSKB,DTAN,MTAN)
;JBTPPN(JOBN...JBTMAX) - HIGH SEG DIRECTORY NAME(EXTENSION OF JBTPPN TABLE)
;	IS PROJECT-PROGRAMMER IF DISK, 0 IF DTA OR MTA
;JBTNAM(JOBN...JBTMAX) - HIGH SEG NAME(EXTENSION ASSUMED TO BE SHR)
;	(EXTENSION OF JBTPRG TABLE)
;	THE NAME(AND DISK COPY) IS RETAINED EVEN AFTER NO JOBAS ARE USING
;		HIGH SEG IN CORE OR ON DISK, THUS SAVING TIME FOR GET'S.
;		HOWEVER, IF SWAPPING SPACE BECOMES FULL, THESE UNUSED HIGH SEGS
;		ARE DELETED ONE AT A TIME, UNTIL THERE IS ROOM. IF STILL NO ROOM,
;		COPIES OF HIGH SEGS WHICH ARE ALSO IN CORE ARE DELETED.
;		ANY HIGH SEG WHICH HAS A NAME IS SHARABLE AND HAS SHRSEG SET IN JBTSTS.
;		A HIGH SEG WITH SEGSHR SET AND JBTNAM=0 IS A HIGH SEG WHICH HAS BEEN
;		SUPERCEDED BY A LATER VERSION OF A HIGH FILE.
	
;THE FOLLOWING LOCATION HAS BEEN ADDED TO THE JOB DATA AREA:

;JOBHRL - RH IS ANALOGOUS TO JOBREL, HIGHEST RELATIVE(USER) ADR. IN HIGH SEG
;	IE HIGHEST LEGAL USER ADDRESS IN HIGH SEG
;	0 MEANS JOB DOES NOT HAVE A HIGH SEG
;	SET BY MONITOR EVERY TIME JOB RUNS
;	LH IS ANALOGOUS TO LH OF JOBSA, FIRST FREE(RELATIVE) LOCATION IN HIGH SEG
;	SET BY LINKING LOADER, USED ON SAVE FOR AMOUNT TO WRITE
;	THE FIRST FREE LOCATION CONTAINS THE STARTING ADDRESS OF JOB
;	WHICH IS SET BY SAVE FROM JOBSA WHICH WAS SET BY LINKING LOADER
;	BOTH HALVES ARE 0 IF NO HIGH SEG

;JOBCOR - LH IS HIGHEST LOC LOADED WITH DATA IN LOW SEG
;	SET BY LINKING LOADER
;	USED BY SAVE FOR 2 SEG PROGRAM ONLY, WRITE LOW SEG IF LH JOBCOR IS
;	GREATER THAN 137(HIGHEST LOC IN JOB DATA AREA

;THE HIGH SEGMENT HAS A VERY SMALL JOB DATA AREA(10 LOCATIONS)
;WHICH IS USED FOR INITIALIZING THE REGULAR JOB DATA AREA ON A GET
;IN CASE THE JOB DOES NOT HAVE A LOW SEGMENT FILE(HIGHLY DESIRABLE)
;SEE JOBDAT FOR DEFINITIONS.

;THE CONTENTS OF AC J MAY BE A JOB NUMBER OR A HIGH SEGMENT NUMBER
;AC J IS LOADED FROM JBTSGN INDEXED BY JOB NUMBER
;SO THAT AC J CONTAINS LH BITS FOR EASY TESTING WHEN THE RH
;HAS A HIGH EGMENT NUMBER IN IT.  WHEN AC J HAS A JOB NUMBER
;IN IT, THE LH IS ALWAYS 0
;IN SWAP, AC J IS DEFINED TO BE AC J
;HOWEVER, A COMPARE WITH JOBMAX WILL STILL GIVE HIGH SEG OR LOW SEG
;NOTE, THAT SPYSEG IS SIGN BIT SO 'SKIPG' TEST FOR REAL HIGH SEG


;TERMINOLOGY IN THE COMMENTS OF SEGCON:
;'SEG' IS AN ABREVIATION FOR 'SEGMENT'
;'JOB' OR 'JOB NUMBER' ALWAYS REFERS TO NUBERS LESS-THAN OR EQUAL-TO JOBMAX
;THE COMMENTS IN THE REST OF THE MONITOR HAVE NOT BEEN CHANGED, SO THAT THERE ARE
;MANY ROUTINES WHICH ARE NOW DEALING WITH BOTH JOB NUMBERS AND HIG SEG NUMBERS
;(MAINLY IN CORE AND SWAP ROUTINES) WITHOUT KNOWING IT.
;'SEGMENT' REFERS TO BOTH LOW AND HIGH SGMENTS, RATHER THAN JUST HIGH SEGMENTS
;AND WILL ALWAYS BE PRECEDED BY 'LOW' OR 'HIGH' IF BOTH IS NOT INTENDED.
;'JOB NUMBER' IS USED INTERCHANGEABLE WITH 'LOW SEG NUMBER'.
;'ADDRESS','ADR','LOCATION','LOC', AND 'ORIGIN' ALL
;REFER TO USER(IE BEFORE HARDWARE OR SOFTWARE RELOCATION) QUANTITIES.
;MOST OF THE TIME THESE WORDS ARE MODIFIED WITH 'USER' OR 'RELATIVE'.
;HOWEVER, THIS IS NOT COMPLETELY CONSISTENT.
;OCCASIONALLY ABSOLUTE ADDRESSES ARE COMPUTED BY THE MONITOR. IN ALL THESE
;CASES, 'ABSOLUTE' OR 'ABS' PRECEEDS THESE WORDS.
;THE REENTRANT CAPABILITY IMPROVES SYSTEM THRUPUT BY REDUCING THE DEMANDS ON:
;	1. CORE MEMORY - SHARING
;	2. SWAPPING STORAGE - SHARING
;	3. SWAPPING CHANNEL READS
;	4. SWAPPING CHANNEL WRITES
;	5. STORAGE CHANNEL READS - GET
;HOWEVER, 2 COMPETES WITH 4 AND 5, IN THAT TO REDUCE THE DEMANDS 4 AND 5,
;COPIES OF UNUSED (DORMANT) HIGH SEGMENTS ARE KEPT ON THE SWAPPING DEVICE, THEREBY
;INCREASING THE DEMAND FOR SWAPPING STORAGE(2).  THE QUESTION NATURALLY ARISES,
;HOW DOES THE SYSTEM DETERMINE THIS SPACE-TIME TRADEOFF?
;THE MONITOR ACHIEVES THE BALANCE DYNAMICALLY, AFTER THE OPERATOR
;ESTABLISHED THE SIZE OF THE SWAPPING SPACE WHEN THE SYSTEM IS STARTED
;(ONCE ONLY DIALOG). THE MONITOR ASSUMES THAT THERE IS NO SHORTAGE
;OF SWAPPING SPACE, AND SO KEEPS A SINGLE COPY OF AS MANY HIGH SHARABLE
;SEGMENTS IN THE SWAPPING SPACE AS THERE ARE HIGH SEG NUMBERS.
;(THE MAX NUMBER OF HIGH SEG NUMBERS IS ESTABLISHED AT BUILD TIME
;AND IS EQUAL TO OR GREATER THAN THE NUMBER OF JOBS(COUNTING THE NULL JOB).
;THUS DEMANDS 4 AND 5 ARE MINIMIZED.
;HOWEVER IF SWAPING SPACE IS EXHAUSTED, THE MONITOR WILL TRY DELETING
;A HIGH SHARABLE SEG THAT IS NOT IN USE BY ANY JOB.(A SO-CALLED DORMANT SEG)
;WHEN DELETED SEG IS NEXT NEEDED(A GET OCCURRED), IT WILL
;BE GOTTEN FROM STORAGE DEVICE, INCREASING DEMAND 5.  IF NO UNUSED HIGH SEGS EXIST
;THE MONITOR WILL TRY DELETING A HIGH(SHARABLE OR NON-SHARABLE) SEG THAT
;IS IN USE AND HAS A COPY, BOTH ON THE DISK AND IN CORE.  THUS WHEN THIS HIGH SEG IS
;SWAPPED OUT, IT WILL REQUIRE A WRITE, INCREASING DEMAND 4.

;TO RESTATE: THE MONITOR USES ALL THE SWAPPING SPACE AVAILABLE. IF IT RUNS OUT,
;IT INCREASES STORAGE CHANNEL READS(GET), THEN SWAPPING CHANNEL WRITES IN ORDER
;TO OVERCOME THE SPACE SHORTAGE.

;THE SAME LOOK-A-SIDE TECHNIQUE IS USED FOR CORE IN BOTH SWAPPING AND NON-SWAPPING
; SYSTEMS IN THAT THE MONITOR KEEPS DORMANT SEGMENTS IN CORE
;UNTIL THEY ARE NEEDED OR CORE DEMAND REQUIRES THAT THEY BE RETURNED
;THERE IS A THIRD CLASS OF SEGMENTS, CALLED 'IDLE'.
;AN IDLE SEGMENT IS A SHARABLE SEG WHICH IS IN CORE, BUT NO JOB IN CORE
;IS USING IT, BUT SOMEONE ON DISK IS.  IT WILL BE DELETED IF CORE IS NEEDED
;THE 3 CLASSES OF SEGMENTS ARE ACTIVE,IDLE,DORMANT.
;LOCATION CORTAL CONTAINS THE SUM OF FREE BLOCKS+DORMANT BLOCKS
;HOWEVER CORTAB CONTAINS 0 BITS ONLY FOR FREE BLOCKS
;TO FREE STORAGE
;THE CORE COMMAND WITH NO ARG STILL PRINTS CORE AS IF NO DORMANT SEGS IN CORE

;VIRTAL CONTAINS THH AMOUNT OF FREE VIRTUAL CORE LEFT IN SYSTEM
;INCLUDING HIGH SEGMENTS.  SINCE THIS QUANTITY IS USED TO PREVENT
;THE CORE ROUTINES FROM OVER COMMITTING SWAP SPACE. SHARED SEG ARE ONLY
;COUNTED ONCE, AND DORMANT SEGMENTS ARE NOT INCLUDED.  THUS VIRTAL IS
;DECREMENTED WHEN THE FIRST USER SHARES A SEGMENT CHANGING IT FROM DORMANT
;TO ACTIVE
	
	ENTRY	SEGCON

SEGCON::	;ENTRY POINT SYMBOL TO CAUSE LOADING OF SEGCON
		;(AS OPPOSED TO NULSEG OR NEITHER)


SUBTTL	ONCE - ONCE ONLY STARTUP CODE

;LOCATION 'TWOREG' IS A FLAG WHICH IS TESTED AT POINTS WHERE A HIGH
;SEGMENT CAN BE CREATED, TO SEE IF BOTH HARDWARE AND SOFTWARE HAVE TWO
;REGISTER CAPABILITY

;INITIALIZE LOC TWOREG TO 0 IF SOFTWARE OR HARDWARE DOES NOT HAVE 2 SEGMENT
;CAPABILTIY.  SET TWOREG TO -1 IF BOTH DO HAVE 2 SEGMENT CAPABILITY.
;SYMBOL AND2RG IS ANDDED TO 'TWOREG' FROM ONCE ONLY CODE AFTER THE HARDWARE IS
;EXAMINED AND TWOREG HAS BEEN SET TO 0 OR -1 ACCORDINGLY.


	
SUBTTL	COMCSS - COMMAND DECODER SUBROUTINES

;ROUTINE TO STOP NEW USERS FROM SHARAING EXISTING SEGMENTS ON DECTAPE
;AND MAGTAPE WHICH HAVE BEEN JUST ASSIGNED, SINCE THE NEW TAPE MAY HAVE
;A LATER VERSION OF THE FILE WITH THE SAME NAME AS THE SEGMENT.
;REMSEG - DELETE ALL SEGS OF DISK FILE STRUCTURE BEING REMOVED 
;CALLED FROM ASSIGN,DEASG(DEASSIGN,FINISH,KJOB) CONSOLE COMMAND. REMSTRR UUO
;CALL:	MOVE F,DEVICE DATA BLOCK ADDRESS OR STR DATA BLOCK ADR.
;	MOVE T2,DEVMOD(F)	;DEVICE CHARACTERISTICS
;	PUSHJ P,ASGHGH
;	ALWAYS RETURN, C(T2) DESTROYED


ASGHGH::TLNN	T2,DVDTA!DVMTA	;IS THIS DEVICE JUST ASSIGNED A DTA OR MTA?
	POPJ	P,		;NO, NO CONFLICT POSSIBLE
REMSEG::
IFN FTMP,<
	PUSHJ	P,GGVMM##	;GET MM RESOURCE FOR CALL TO CLRNAM
>
	PUSH	P,J		;YES, SAVE JOB NUMBER
ASG1:	MOVE	J,SEGPTR##	;SCAN ALL HIGH SEGMENTS
ASG2:	MOVE	T1,DEVNAM(F)	;GET DEVICE NAME(PHYSICAL)
	CAME	T1,JBTDEV##(J)	;DOES IT MATCH DEVICE NAME OF SEG?
	AOBJN	J,ASG2		;NO, KEEP LOOKING, FINISHED?
	JUMPG	J,IPOPJ##	;RETURN IF FINISHED AND RESTORE JOB NUMBER
	TLZ	J,-1		;CLEAR OUT LH BITS OF HIGH SEG NO.
	PUSHJ	P,CLRNAM	;NOT FINISHED, CLEAR SEG NAME
				;AND RETURN DISK SPACE IF NOT IN USE
	JRST	ASG1		;CONTINUE SCAN, RESTORE T1 TO DEVICE NAME


;ROUTINE TO PRINT SIZE OF HIGH SEG LOGICAL CORE
;CALL:	MOVE J,JOB NO.
;	PUSHJ P,PRTHGH
;	ALWAYS RETURN WITH J RESTORED
;PRINTS +N(UNLESS NOT TWO REG HARDWARE, SO USERS CAN TELL IF 2 REG. HARD.)


PRTHGH::PUSHJ	P,PRTPLS##	;YES, PRINT +
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,J		;SAVE JOB NUMBER
	MOVEI	P1,JBTSGN##-.HBLNK(J) ;START OF CHAIN
	SETZ	T1,		;INIT COUNT
PRTHG1:	SKIPN	P1,.HBLNK(P1)	;NEXT BLOCK
	JRST	PRTHG4		;NO MORE
	SKIPLE	J,.HBSGN(P1)	;SEGMENT #
	TLZA	J,-1		;CLEAR JUNK
	JRST	PRTHG1		;SPY SEG
	PUSHJ	P,SEGSIZ##	;GET SEGMENT SIZE
	ADDI	T1,(T2)		;SUM IT IN
	JRST	PRTHG1		;LOOP FOR MORE

PRTHG4:	POP	P,J		;RESTORE J
	PJRST	RADX10##	;PRINT NUMBER AND RETURN
	
;ROUTINE TO CHECK TO SEE IF USER IS MEDDLING WITH A SHARABLE PROGRAM
; IF YES, TURN UWPOFF OFF SO UWP(USER MODE WRITE PROTECT) WILL BE ON
; AND SET MEDDLE, SO HE CANNOT TURN UWP BACK OFF AND CANNOT CHANGE CORE
; ASSIGNMENT OF HIGH SEG(EXCEPT TO REMOVE IT COMPLETELY)
;CALL:	MOVE J,JOB NO.
;	PUSHJ P,CHKMED
;	ALWAYS RETURN, J RESTORED AND T2 PRESERVED(T1 USED)
;CALLED FROM DEPOSIT, START N, RUN UUO, GETSEG UUO
;T2 PRESERVED


CHKMED::PUSH	P,T2		;SAVE T2
	MOVEI	T2,JBTSGN##-.HBLNK(J) ;START OF CHAIN
CHKMD1:	SKIPN	T2,.HBLNK(T2)	;NEXT HIGH SEG DATA BLOCK
	JRST	T2POPJ##	;RETURN
	SKIPLE	T1,.HBSGN(T2)	;SEGMENT WORD
	TLNN	T1,SHRSEG	;YES, IS IT SHARABLE?
	JRST	CHKMD1		;THIS SEG OK
	MOVSI	T1,MEDDLE	;YES, FLAG THIS USER AS MEDDLING...
	IORM	T1,.HBSGN(T2)	;(MUST DO THIS WAY OR USE SYSPIF
	MOVSI	T1,UWPOFF	;BECAUSE OF SWCUP)
	ANDCAM	T1,.HBSGN(T2)	;...
	JRST	CHKMD1		;CONTINUE
	

;ROUTINE TO COMPUTE NO. OF K USED BY A JOB
;BOTH LOW AND HIGH SEGMENTS
;CALL:	MOVE J, JOB NO.
;	PUSHJ P,JOBSIZ
;	RETURN WITH T2=SIZE IN K, J PRESERVED


JOBSIZ::PUSHJ	P,SEGSIZ##	;SIZE OF LOW SEG
	MOVE	T1,T2		;SAVE IN T1
	PUSHJ	P,SAVE1##	;SAVE AN AC
	MOVEI	P1,JBTSGN##-.HBLNK(J) ;START  OF SEG DATA BLOCK CHAIN
	PUSH	P,J		;SAVE LOW SEG NUMBER
JOBSZ0:	SKIPN	P1,.HBLNK(P1)	;NEXT SEG
	JRST	JOBSZ1		;NO MORE
	SKIPG	J,.HBSGN(P1)	;SEGMENT WORD
	JRST	JOBSZ0		;SKIP SPY SEGS
	HRRZS	J		;CLEAR JUNK
	PUSHJ	P,SEGSIZ##	;YES, GET SIZE OF HIGH SEG
	ADDI	T1,(T2)		;SUM IN
	JRST	JOBSZ0		;NEXT SEG

JOBSZ1:	POP	P,J
	LDB	T2,NFYPGS##	;ROUND UP TO NEXT ONE K BOUNDARY
	ADDI	T2,-UPMPSZ##(T1)
	LSH	T2,P2KLSH	;CONVERT PAGES TO K
	POPJ	P,		;RESTORE JOB NO. AND RETURN
	
SUBTTL CORE1 - LOGICAL AND PHYSICAL CORE ALLOCATION

;ROUTINE TO CHECK FOR SAVE IN PROGRESS FROM A HIGH SEG
;ABOUT TO BE SHUFFLED OR SWAPPED, OR CORE REASSIGNED
;CALL:	MOVE J,LOW OR HIGH SEG TO BE SHUFFLED OR SWAPPED
;	PUSHJ P,ANYSAV
;	RET1 - THIS IS A HIGH SEG WHICH SOME JOB IS DOING A SAVE OF
;	RET2 - THIS IS A HIGH SEG WHICH CAN BE SHUFFLED OR SWAPPED
;CALLED FROM ANYACT IN CORE MODULE,T2 PRESERVED FOR SWAPPER


ANYSAV::CAILE	J,JOBMAX##	;IS THIS A LOW SEG?
	SKIPN	JBTADR##(J)	;NO, IS THIS HIGH SEG IN CORE?
	JRST	CPOPJ1##	;YES, GIVE SINGLE SKIP RETURN
	PUSH	P,T1		;SAVE T1 FOR SHUFFLER
	HRRZ	T1,JBTSHR##(J)	;GET SEGMENT'S SHARE COUNT
	JUMPE	T1,TPOPJ1##	;IF NO SHARERS, IT'S NOT BEING SAVED
	PUSH	P,T2		;FOR THE SWAPPER
	PUSH	P,J		;SAVE HIGH SEG NUMBER
	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER ASSIGNED
ANYSV0:	SKIPN	JBTADR##(J)	;IS JOB IN CORE (R=R)?
	JRST	ANYSV1		;NO
	MOVE	T2,[USRHCU##-.UPMP+.UPMVP] ;FOR MAPWRD
	PUSHJ	P,MAPWRD	;MAKE JOBHCU ADDRESSABLE
	SKIPE	T2		;SKIP IF A BAD ADDRESS
	SKIPL	(T2)		;SAVE OR GET FOR EITHER SEG IN PROGRESS?
ANYSV1:	SOJG	J,ANYSV0	;NO, KEEP LOOKING, FINISHED?
	JUMPLE	J,ANYSV2	;YES, FIND A SAVE OR GET IN PROGRESS
	MOVSI	T1,SWP		;JOB SWAPPED OUT OR ON WAY IN OR OUT BIT
	TDNE	T1,JBTSTS##(J)	;IS THIS JOB SWAPPED OUT OR ON WAY IN OR OUT
	JRST	ANYSV1		;YES, DO NOT LOOK AT JOB DATA AREA
				; SINCE IT MAY NOT HAVE BEEN WRITTEN INTO
				; IF THIS IS A SWAP IN
	MOVEI	T2,JBTSGN##-.HBSGN(J) ;START OF SEGMENT DATA BLOCK CHAIN
ANYSV3:	SKIPN	T2,.HBLNK(T2)	;NEXT BLOCK
	JRST	ANYSV1		;KEEP LOOKING
	HRRZ	T1,.HBSGN(T2)	;SEGMENT NUMBER
	SKIPLE	.HBSGN(T2)	;SCREEN OUT SPY SEGS
	CAIE	T1,@(P)		;IS IT SAME AS HIGH SEG IN QUESTION?
				;(INDIRECT AND INDEX BITS ZERO)
	JRST	ANYSV3		;NO, KEEP LOOKING
	CAIA			;YES, GIVE SAVE ACTIVE RETURN
ANYSV2:	AOS	-3(P)		;NO SAVE IN PROGRESS
	POP	P,J		;RESTORE HIGH SEG NUMBER
	JRST	TTPOPJ##	;GIVE ERROR OR OK RETURN
	
;ROUTINE TO DEPOSIT USER COMMAND ARG IN HIGH SEG IF USER HAS PRIVILEGES
; TO WRITE OR SEG IS NON-SHARABLE
;CALL:	MOVE J,JOB NO.
;	MOVE R,JOB RELOC.
;	MOVE T2,REL. USER ADR. NOT IN LOW SEG
;	MOVE S,WORD TO DEPOSIT
;	PUSHJ P,HGHDEP
;	ERROR RETURN
;	OK RETURN - JOBEXM SET TO USER ADR IN HIGH SEG, S STORED IN HIGH SEG


HGHDEP::TLZ	T2,^-MXSECN	;KEEP ONLY ADDRESS
	PUSH	P,T2		;SAVE T2
	MOVE	M,T2		;MOVE ADDRESS TO M FOR HGHWRD
	PUSHJ	P,HGHWRD	;SET T1 TO HIGH WORD, T2 TO HSB
	  JRST	T2POPJ##	;NOT IN BOUNDS, ERROR RETURN OR NO HIGH SEG
	EXCH	T2,(P)		;SAVE HIGH SEG DATA BLOCK ADDR, GET ADDR
	MOVE	P2,J		;GET JOB NUMBER FOR CHKHSW
	PUSH	P,J		;SAVE JOB NUMBER
	PUSHJ	P,MAPWRD	;T2 = EVA OF WORD
	JUMPE	T2,[POP P,J	;NON-EXISTANT PAGE
		    JRST T2POPJ##] ;GIVE UP
	EXCH	T2,-1(P)	;GET HIGH SEG DATA BLOCK ADDR, SAVE ADDR
	SKIPLE	J,.HBSGN(T2)	;GET HIGH SEG NUMBER
	PUSHJ	P,CHKHSW	;CAN JOB(P2) WRITE IN HIGH SEG(J)?
	  JRST	HGHDP1		;NO, ERROR RETURN
IFN FTMP,<
;THE FOLLOWING TWO INSTRUCTIONS ARE PROBABLY NOT NECESSARY AND ARE
; HERE ONLY FOR SAFETY SAKE, (SOMEONE STORING IN A HIGH SEG AT IRP LEVEL?)
	CONSZ	PI,PI.IPA-PI.IP7;IF AT HARD INTERRUPT LEVEL,
	JRST	HGHDP1		; CAN'T GET THE MM RESOURCE SO MUST FAIL
	PUSHJ	P,GETMM##	;GET THE MM RESOURCE
	  JRST	.-1		;MUST WAIT UNTIL ITS AVAILABLE
>
	MOVEM	S,@-1(P)	;YES,STORE USER ARG
	HRRZM	M,.JDAT+JOBEXM## ;STORE LOC OF DEPOSIT FOR D,E WITH NO ARG
				; LH=O MEANING D WAS LAST DONE RATHER THAN E
	HRRZS	J
	PUSHJ	P,ZERSWP##	;DELETE SWAPPING SPACE,IF ANY
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN THE MM RESOURCE
>
	AOS	-2(P)		;SET FOR SKIP RETURN
HGHDP1:	POP	P,J		;RESTORE J
	JRST	T2POPJ##	;FIX STACK AND RETURN
;ROUTINE TO MAKE ANY WORD OF ANY JOB ADDRESSABLE
; (IN FACT WRITABLE) BY MAPPING IT THROUGH THE
; PER PROCESS MAP OF THE CURRENT JOB
;CALLING SEQUENCE:
;	MOVE	T2,USER VIRTUAL ADDRESS TO BE MAPPED
;	MOVE	J,JOB NUMBER OF JOB CONTAINING THE WORD
;	PUSHJ	P,MAPWRD
;	...	RETURN HERE
;ON RETURN FROM CALL TO MAPWRD T2=EVA OF WORD

MAPWRD::PUSH	P,T2		;SAVE UVA
	PUSHJ	P,RTPTA		;GET POINTER FROM TARGET JOBS MAP
	JUMPE	T2,[SETZM (P)	;NON-EXISTANT PAGE OR SECTION
		    JRST  T2POPJ##] ;PHASE STACK AND RETURN
	TLO	T2,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS (OK IF INDIRECT)
	MOVEM	T2,.UPMP+.UMTMP ;MAKE THAT ADDRESSABLE (EVEN WRITABLE) IN OUR CONTEXT

	CLRPT	.TEMP		;CLEAR AM FOR THIS PAGE
	POP	P,T2		;RESTORE UVA
	ANDI	T2,PG.BDY	;KEEP ONLY PAGE OFFSET
	TRO	T2,.TEMP	;FORM EVA OF WORD
	POPJ	P,		;RETURN IT
;ROUTINE TO RETURN CONTENTS OF A MAP SLOT WHICH MAPS A VIRTUAL PAGE NUMBER
;CALLING SEQUENCE:
;	MOVE	T2,VIRTUAL PAGE NUMBER
;	MOVE	J,JOB NUMBER
;	PUSHJ	P,RTPTR
;	ALWAYS RETURNS HERE, T2 = CONTENTS OF TARGET JOBS MAP SLOT
;PRESERVES ALL ACS AND THE MAP

RTPTA:	LSH	T2,W2PLSH	;CONVERT FROM VIRTUAL ADDRESS TO PAGE NUMBER
RTPTR::	SE1ENT			;MUST BE IN SECTION 1 TO REFERENCE PAGTAB
	PUSH	P,T1		;SAVE A WORKING AC
	PUSH	P,.UPMP+.UMTMP
	HRRZ	T1,JBTUPM##(J)	;TARGET JOB'S PROCESS TABLE
	JUMPE	T1,RTPT3	;NON-EXISTANT?
	HRLI	T1,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS
	MOVEM	T1,.UPMP+.UMTMP ;MAKE THE JOBS MAP ADDRESSABLE
	CLRPT	.TEMP		;CLEAR PAGING MEMORY FOR THIS VIRTUAL ADDRESS
	CAIL	T2,.MCFV/PAGSIZ ;POINTER IN PAGE TABLE OR PROCESS TABLE?
	JRST	RTPT4		;IF A FUNNY SPACE PAGE, NO MORE MAPPING
	MOVE	T1,T2		;GET SECTION PAGE IS IN
	LSH	T1,P2SLSH	;..
RTPT0:	SKIPN	T1,.TEMP+SECTAB(T1) ;GET SECTION MAP POINTER
	JRST	RTPT3		;NONE THERE
	TLNN	T1,(<<PM.ACD^!PM.DCD>B2>) ;INDIRECT?
	JRST	RTPT1		;NO, JUST MAP IT
	LDB	T1,[POINT POINT 5,T1,17] ;SEE RSECT4 IN VMSER FOR DETAILS
	JRST	RTPT0		;CHECK AGAIN
RTPT1:	MOVEM	T1,.UPMP+.UMTMP		;MAKE IT ADDRESSIBLE
	CLRPT	.TEMP		;CLEAR MEMORY
	ANDI	T2,HLGPNO	;GET SECTION RELATIVE PAGE NUMBER
RTPT2:	SKIPA	T2,.TEMP(T2)	;GET POINTER FROM THE MAP
RTPT3:	SETZ	T2,		;HERE ON NON-EXISTANT JOB OR SECTION
	POP	P,.UPMP+.UMTMP
	CLRPT	.TEMP		;CAUSE A REFILL FOR SLOT USED TEMPORARILY
	JRST	TPOPJ##		;RESTORE TEMPORARY AND RETURN

RTPT4:	CAIG	T2,<.UPMVP/PAGSIZ>	;IS IT TRADITIONAL OR A MAP?
	SKIPA	T1,[<.MCFV/PAGSIZ>-.UMORG]
	HRREI	T1,<.UPMVP/PAGSIZ>-SECTAB	;MAP, POINT TO SECTAB
	SUB	T2,T1		;POINT TO CORRECT SLOT
	JRST	RTPT2
	

;ROUTINE TO REMOVE HIGH SEGMENT FROM USER'S LOGICAL ADDRESSING SPACE
;THIS IS CONTRANSTED WITH REMOVING A HIGH SEGMENT FROM PHYSICAL CORE
;WHICH THE SWAPPER DOES EVERY TIME A JOB WITH A HIGH SEG IS SWAPPED OUT (KCORE1)
;THE SEGMENT NUMBER ASSOCIATED WITH THE JOB IS ERASED (JBTSGN)

;IF NO OTHER JOB IS USING HIGH SEG IN CORE(IN CORE COUNT GOES TO 0)
; HIGH SEG IS NOT DELETED FROM CORE(UNLESS NOT SHARABLE) BUT RATHER BECOMES 'IDLE'.
; WHERE IDLE HAS SNA SET.
;IF NO OTHER JOB IS USING HIGH SEG IN LOGICAL ADR. SPACE, HIGH SEG IS
; NOT DELETED FROM CORE OR DISK(UNLESS NOT SHARABLE) BUT RATHER BECOMES 'DORMANT'.
; WHERE DORMANT HAS SNA TURNED OFF, BUT HAS CORE AND/OR DISK SPACE.
;RATHER IT BECOMES DORMANT(UNLESS IT NO LONGER HAS A NAME OR WAS NEVER SHARABLE)
;A DORMANT SEGMENT IS LEFT IN SYSTEM ACCORDING TO:
;	A. SWAP SYS - LEFT ON BOTH SWAPPING DEVICE AND CORE
;	B. NON-SWAP SYS - LEFT IN CORE
;DORMANT SEGMENTS HAVE JNA BIT OFF, HOWEVER THEY HAVE DISK SPACE AND/OR CORE
;DORMANT SEGMENTS ARE FLUSHED ONLY WHEN DISK OR CORE IS NEEDED
; OR HIGH SEGMENT NUMBERS ARE NEEDED

;ROUTINES TO KILL HIGH SEGS OWNED BY A JOB
;VARIOUS ENTRY POINTS ARE AS FOLLOWS:
;
;KILHGA - KILL ALL HIGH SEGS OWNED BY JOB
;KILHGS - KILL ALL HIGH SEGS IN PCS SECTION
;KILHSS - KILL ALL HIGH SEGS IN SECTION SPEC'D BY P1 (INCLUDES VRSN PRTOUT)
;KILHG1 - (ALWAYS CPOPJ1 RETURN) KILL ALL SEGS IN SECTION IF C(J)=0, ELSE
;	  KILL SEG SPECIFIED BY T1 (SEGMENT DATA BLOCK)
;KILHGH - KILL SEG SPECIFIED BY SEGMENT DATA BLOCK IN T1
;KILHGC - LOAD J WITH .CPJOB, THEN USE KILHG1 MINUS THE SKIP RETURN
	
KILHGA::
	PUSHJ	P,SAVE1##
	SETO	P1,		;FLAG TO REMOVE ALL HIGH SEGS
	JRST	KILHG0
KILHG1:				;KILL SEGMENT IN SECTION AND SKIP
	AOS	(P)		; ALWAYS SKIP RETURN
	PUSH	P,T1		;VERWAT DESTROYS T1
	PUSHJ	P,VERWAT##	;SEE IF WATCHING
	  CAIA			;PROCEED
	PUSHJ	P,PRRBKC##	;YES - AND RIGHT BRACKET CRLF
	POP	P,T1
KILHGC::MOVE	J,.CPJOB##	;KILL HIGH SEG(S) FOR CURRENT JOB(GETSEG,REMAP,CORE UUO)
	JUMPE	T1,KILHGS	;IF NO SEG SPEC'D, KILL ALL SEGS IN SECTION
	PUSHJ	P,KILHGH	;KILL THIS SPECIFIC SEGMENT
	PJRST	SETMAP##	;FIX MAPPING

KILHSS::			;ALL SEGS IN SECTION, WITH WATCH VER PRNT
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,VERWAT##	;SEE IF WATCHING
	  JRST	KILHS0		;PROCEED
	PUSHJ	P,PRRBKC##	;YES - AND RIGHT BRACKET CRLF
	JRST	KILHS0		;PROCEED

KILHGS:				;KILL ALL HI SEGS IN PCS SECTION
	PUSHJ	P,SAVE1##	;SAVE P1
	XSFM	P1		;PCS SECTION
KILHS0:	ANDI	P1,MXSECN	;REMEMBER IT
	EXCH	P1,T4		;PUT SECT # IN T4 PRESERVING ORIGINAL CONTENTS
	PUSHJ	P,RSECT4##	;RESOLVE IT
	  JFCL
	EXCH	P1,T4
KILHG0:	SETZ	T1,		;START AT THE BEGINNING
	PUSHJ	P,NXSSP1	;GET NEXT SEGMENT IN SECTION DESIRED
	  POPJ	P,		;NONE
KILHS1:	PUSHJ	P,KILHGH	;YES, KILL THIS HIGH SEG
	JRST	KILHG0		;START AT THE BEGININNING AGAIN

;HERE TO LOOP KILLING ALL SEGS


;SUB TO REMOVE HIGH SEG FROM LOG. ADR. SPACE AND CHANGE HARDWARE RELOC
KILHSH::PUSHJ	P,KILHGC	;REMOVE HIGH SEG FROM LOGICAL ADR. SPACE OF CURRENT JOB
	PJRST	SETMAP##	;THEN RESET HARDWARE RELOC. SO USER CANNOT REFERENCE

;SUB. TO REMOVE HIGH SEG FROM LOGICAL ADR. SPACE OF CURRENT JOB
;T1 HAS ADDRESS OF SEGMENT DATA BLOCK

KILHGH::PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,T1		;SAVE SEGMENT DATA BLOCK ADDR
	PUSH	P,J		;SAVE JOB NUMBER
	SKIPG	J,.HBSGN(T1)	;DOES JOB HAVE A REAL HIGH SEG?
	JRST	KILFIN		;NO, ZERO HIGH SEG NUMBER FOR THIS JOB IN CASE SPY SEG
	TLZE	J,SWCUP		;WAIT COUNT UP FOR THIS SEGMENT?
	PUSHJ	P,[PUSH  P,P2	;YES, SAVE P2
		   MOVE  P2,T1	;HSB IN IN P2
		   EXCH  J,-2(P) ;NEED JOB # IN J
		   PUSHJ P,HGO	;GET GOING AGAIN
		   EXCH  J,-2(P) ;RESTORE J
		   JRST  P2POPJ##]
	PUSHJ	P,SEGSIZ##	;T2=SIZE OF HIGH SEG
	PUSH	P,T2		;SAVE SIZE IN CASE NEED TO INCREASE AMOUNT
				;OF FREE VERTICAL CORE LEFT.
	SKIPN	R,JBTADR##(J)	;YES, IS HIGH SEG ALSO IN CORE?
	JRST	SCNLOG		;NO, SCAN TO SEE IF OTHER USERS USING THIS HIGH SEG
				; IN THEIR LOGICAL ADDRESSING SPACE
	MOVE	T1,-1(P)	;JOB NUMBER
	PUSHJ	P,DECCNT	;YES, DECREMENT HIGH SEG IN CORE COUNT FOR THIS JOB
				; HIGH SEG IN-CORE COUNT TRANSITION TO 0?
	  JRST	KILFN0		;NO, JUST REMOVE HIGH SEG FROM THIS
				; USER'S LOG. ADR SPACE
	
SCNLOG:	MOVE	T1,-1(P)	;RETRIEVE JOB NUMBER
	PUSHJ	P,DECSHR	;WE'RE NOT SHARING ANY MORE
	  JRST	[TLNN	J,SHRSEG ;IF NOT SHARABLE,
		 PUSHJ	 P,KCOREV## ;DELETE CORE IN CORE
		 JRST	KILFN1]	;GO IF NOT LAST SHARER
KILLP0:
IFN FTLOCK,<
	PUSHJ	P,UNLOCK##	;NO. UNLOCK IT
	  JFCL			;?
>
	SKIPE	JBTNAM##(J)	;NO, COULD NEW USER'S SHARE THIS HIGH SEG
				; ON A GET IF WE LEFT IT ON SWAPPING SPACE?
	JRST	KILLP1		;YES, DON'T DELETE IT
	PUSHJ	P,ZERSWP##	;DELETE DISK SPACE(IF ANY)
	PUSHJ	P,KCOREV##	;RETURN REAL PLUS VIRTUAL CORE
	PUSHJ	P,RTNHMP	;RETURN MAP
KILLP1:	MOVSI	T1,SNA		;FLAG HIGH SEG AS UNASSIGNED(OR DORMANT
				; IF STILL IN
				; CORE OR DISK).
	ANDCAM	T1,JBTSTS##(J)
	MOVE	T1,(P)		;SIZE IN K OF HIGH SEG WHICH IS BECOMING DORMANT
	ADDM	T1,VIRTAL##	; OR UNASSIGNED, INCREASE AMOUNT OF VIRTUAL CORE LEFT
				; IN SYSTEM,(EVEN THOUGH CORE AND DISK SPACE
				; MAYBE STILL USED)
	JRST	KILFN1		;SKIP CALLS TO UNLOKH AND DECSHR
KILFN0:	MOVE	T1,-1(P)	;GET JOB NUMBER AGAIN
	PUSHJ	P,DECSHR	;WE'RE NO LONGER SHARING
	  CAIA			;CONTINUE IF NOT LAST SHARER
	JRST	KILLP0		;SWAPPER RECOVERY--LAST SHARER, NOT IN CORE
IFN FTLOCK,<
	PUSH	P,J		;SAVE J
	MOVE	J,-2(P)		;GET JOB #
	EXCH	P4,-3(P)	;HIGH SEG BLOCK ADDR
	PUSHJ	P,UNLOKH##	;IF THE HIGH SEGMENT IS LOCKED, UNLOCK IT IF
				;  NO OTHER LOCKED LOW SEGMENT IS SHARING IT
	EXCH	P4,-3(P)	;PUT BLOCK ADDR BACK
	POP	P,J		;RESTORE J
>
;HERE WITH SEGMENT # IN J, JOB # ON STACK

KILFN1:	MOVE	T2,[NSWP,,ICCMSK]
	TDNN	T2,JBTSTS##(J)	;SEG IN USE OR STILL LOCKED?
	SKIPN	JBTADR##(J)	;NO, DOES IT STILL HAVE PHYSICAL CORE?
	JRST	KILFN2		;DON'T ADJUST CORTAL IF LOCKED, SHARED,OR 0 CORE
	TLNN	J,SHRSEG	;NON-SHARABLE?
	JRST	KILFN2		;YES
	LDB	T1,PCORSZ##	;SIZE OF SEGMENT IN K
	AOS	T1		;ROUND UP
	ADDM	T1,CORTAL##	;INCREASE TOTAL FREE+DORMANT+IDLE CORE
	PUSHJ	P,INDISQ	; JUST WENT IDLE, INSERT IN QUEUE
KILFN2:	PUSHJ	P,CHKTAL	;CHECK CORTAL AGAINST CORTAB, HALT IF BAD
	POP	P,T1		;REMOVE SIZE OF SEG IN K

	

KILFIN:	POP	P,J		;RESTORE JOB #
	MOVE	T1,(P)		;HIGH SEG DATA BLOCK ADDR
	HRRZ	T4,JBTUPM##(J)	;NO HI SEG TO REMOVE IF NO MAP
	SKIPE	T4
	PUSHJ	P,REMHGH##	;REMOVE THE HIGH SEGMENT FROM THE PAGE MAP
	HRRZS	(P)
	MOVEI	T2,JBTSGN##-.HBLNK(J) ;START OF CHAIN
KILFNL:	MOVE	T1,T2		;REMEMBER PREDECESSOR
	HRRZ	T2,.HBLNK(T2)	;POINTER TO NEXT
	SKIPN	T2		;ANY BLOCK AT ALL?
	STOPCD	TPOPJ##,JOB,NSH	;NO SUCH HIGH SEG
	CAME	T2,(P)		;SUCCESSOR THIS HIGH SEG?
	JRST	KILFNL		;NO, LOOP ON
	MOVSI	T2,(UP.CTX)	;DOING THIS FOR PUSH?
	CAMN	J,.CPJOB##	;ONLY IF AT UUO LEVEL
	TDNN	T2,.USBTS	;AND THE BIT IS ON
	JRST	KILFL1		;NORMAL IF NOT PUSH
	CAIE	T1,JBTSGN##-.HBLNK(J) ;IF THIS IS NOT THE JBTSGN ENTRY
	JRST	[POP	P,T2	;FIX STACK
		 JRST	KILFL2]	;CONTINUE
	MOVSI	T2,(1B0)	;IF IT IS,
	IORM	T2,(P)		;THEN FLAG NOT TO RETURN BLOCK
				;(LIGHTING IFIW IS OK)
KILFL1:	MOVE	T2,@(P)		;SUCCESSOR TO OUR BLOCK
	MOVEM	T2,.HBLNK(T1)	;REMOVE OUR BLOCK FROM CHAIN
	POP	P,T2
	JUMPL	T2,KILFL2	;DON'T RETURN BLOCK ON PUSH
	MOVEI	T1,.HBLEN	;# OF WORDS TO GIVE BACK
	PUSHJ	P,GIVWDS##	;RETURN CORE
KILFL2:	SKIPN	R,JBTADR##(J)	;RESTORE LOW SEG RELOC AND PRTECTION
	POPJ	P,		;IF NONE, RETURN
	HLRZ	P1,JBTADR##(J)	;GET LOW-SEG END
	CAME	J,.CPJOB##	;CURRENT JOB?
	PUSHJ	P,SVEUB##	;NO, MAKE SURE ITS ADDRESSABLE
	HRRZ	T1,.JDAT+JOBSA## ;GET START ADDRESS
	CAMLE	T1,P1		;SEE IF LOW SEG
	HLLZS	.JDAT+JOBSA##	;NO - CLEAR IT
	HRRZ	T1,.JDAT+JOBREN##;GET REENTER ADDRESS
;PRIMARY SEGMENT?
	CAMLE	T1,P1		;SEE IF LOW SEG
	HLLZS	.JDAT+JOBREN##	;NO - CLEAR IT
	HRRZS	.JDAT+JOBHRL##	;CLEAR OUT SIZE OF HIGH SEG AS SET BY LOADER
				; SO USER'S CAN TEST FOR HIGH SEG BY SKIPN JOBHRL
	DPB	T1,HIVSIZ##	;HIGH SEG SIZE IS NOW 0

	POPJ	P,		;RETURN
	
;ROUTINE TO CLEAR A HIGH SEGMENT NAME SO NO NEW USERS CAN SHARE
;AND RETURN BOTH DISK AND CORE SPACE (IF ANY) IF HIGH SEG WAS DORMANT(SNA=0)
;IE NO LONGER IN ANY USER'S VIRTUAL ADR. SPACE
;CALL:	MOVE J, HIGH SEG NUMBER
;	PUSHJ P, CLRNAM
;	RETURN J AND R PRESERVED
;CALLED FROM FRESWP,FRECOR,FNDSGN (UREMAP,UCORHI), ASGHGH,RELSEG



CLRNAM::SETZM	JBTDEV##(J)	;CLEAR DEVICE NAME OR STR NAME
	TDZA	T2,T2		;ZERO THE PPN
CLRNM1:	MOVE	T2,JBTPPN##(J)	;PERPETUATE THE CROCK WHICH ALLOWS SYSTAT TO
	EXCH	T2,JBTPPN##(J)	; REPORT THE PPN WHICH AN OBSOLETED SEGMENT CAME FROM
	SKIPE	T2
	TLNE	T2,-1		;POINTER TO A PATH?
	JRST	CLRNM2		;NO
	MOVEI	T1,MAXLVL##+2	;YES, RETURN PATH BLOCK TO MONITOR FREE CORE
	PUSHJ	P,GIVWDS##
	SETZM	JBTPPN##(J)	;AND ZERO THE PATH POINTER
CLRNM2:	SETZM	JBTNAM##(J)	;AND SEG NAME SO NEW USER'S CAN USE
				; CLRNM2 CALLED PQOM ASGHGH AND RELSEG
				; WHEN FILE SUPERCEDED, BUT LEAVE DIR
				; NAME FOR SYSTAT TO PRINT (OBS)
	SKIPGE	JBTSTS##(J)	;IS SEG DORMANT(IE NOT IN ANY USER'S VIRTUAL
				; ADR. SPACE)?
	POPJ	P,		;NO,(SNA=1) ALLOW USER'S TO CONTINUE TO SHARE
				; UNTIL FINISHED, HOWEVER NO NEW USERS CAN
				; SHARE SINCE NO LONGER A NAME
	HRRZ	T1,JBTSHR##(J)	;GET SHARER COUNT TO CHECK
	SKIPE	T1		;DOES IT AGREE?
	STOPCD	.,STOP,SNASHR,	;++SNA/JBTSHR DISCREPENCY (NO)
	PUSHJ	P,ZERSWP##	;YES, RETURN DISK SPACE, IF ANY

	PUSHJ	P,RTNHMP	;RETURN HIGH SEG MAP
				;FALL INTO ROUTINE TO KILL DORMANT CORE
;ROUTINE TO RETURN DORMANT OR IDLE CORE (IF ANY)
;CALL:	MOVE J, HIGH SEG NUMBER
;	PUSHJ P,KDORCR
;	RETURN J,R PRESERVED
;CALLED FROM CLRNAM AND FRECOR


KDORCR:	PUSH	P,R		;SAVE R(EITHER HIGH OR LOW RELOC)
	PUSH	P,CORTAL##	;SAVE FREE CORE COUNT
	PUSH	P,LOKTAL##
	SKIPE	R,JBTADR##(J)	;DOES DORMANT SEG HAVE CORE?
	PUSHJ	P,KCOREH	;YES, RETURN PHYSICAL COREAND FLAG HIGH SEG
				; AS ON DISK IF IT HAS DISK SPACE(SET SWP=1)
	POP	P,LOKTAL##
	POP	P,CORTAL##	;RESTORE FREE CORE COUNT, SINCE DORMANT
				; SEGS ALREADY INCLUDED IN CORTAL
	PUSHJ	P,CHKTAL	;CHECK CORTAL WITH CORTAB, HALT IF BAD
	POP	P,R		;RESTORE R
	POPJ	P,		;RETURN

	
;ROUTINE TO RETURN HIGH SEGMENT CORE(MUST BE SOME) AND FLAG SEG AS ON DISK
; IF HIGH SEG HAS DISK SPACE(IE SET SWP=1 IF JBTIMO NON-ZERO)
;CALL:	MOVE J,HIGH SEG NUMBER
;	MOVE R,HIGH SEG RELOC AND PROTECTION
;	PUSHJ P,KCOREH
;CALLED FROM KDORCR(FRECOR,CLRNAM,KILHGH) AND FORHGH


KCOREH::PUSHJ	P,DLDISQ	; SEG NOT IN CORE ANY MORE
	LDB	T1,IMGOUT##	;DOES HIGH SEG HAVE DISK SPACE?
	JUMPE	T1,KCORE1##	;NO, RETURN CORE
	MOVSI	T1,SWP		;YES, FLAG HIGH SEG AS SWAPPED OUT
	IORM	T1,JBTSTS##(J)	;SET SWP=1
	PUSHJ	P,HCTOD##	;CONVERT MAP ADDRESSES
	JRST	KCORE1##	;THEN RETURN CORE
;ROUTINE TO RETURN A HIGH SEGMENT MAP

RTNHMP:	HLLZS	JBTUPM##(J)		;CLEAR SPT POINTER (MAY STILL NEED ORIGIN)
	SETZ	T2,
	EXCH	T2,JBTVAD##(J)		;CLEAR VIRTUAL ADDRESS AND GET IT
	JUMPE	T2,CPOPJ##		;RETURN IF NONE
	SE1ENT				;MUST BE IN SECTION 1
	PUSHJ	P,SAVJW##		;PRESERVE J (SEGMENT #)
	XMOVEI	T2,-.M2MAP(T2)		;POINT TO WHERE BLOCK STARTS
RTNHM1:	HRRZ	T1,.M2SIZ(T2)		;GET LENGTH OF MAP
	MOVEI	T1,.M2MAX(T1)		;INCL OVERHEAD
IFN FTXMON,<
	PJRST	GVFWDS##		;RETURN THE CORE
>
IFE FTXMON,<
	PUSH	P,T1			;SAVE # OF WORDS
	MOVN	T1,LOCORE##		;FIND LOST WORDS
	ADD	T1,T2
	ANDI	T1,3
	SUBI	T2,(T1)
	ADDM	T1,(P)
	POP	P,T1			;REAL COUNT
	PJRST	GIVWDS##
>
;ROUTINE TO RETURN A HIGH SEG DISK ADDRESS WITHOUT REQUIRING THAT
;THE POINTERS BE CONVERTED IN THE MAP
;CALL:
;
;	MOVE	P1,MAP POINTER	;I.E. ADDRESS IN HIGH SEG DATA BLOCK OF MAP ENTRY
;	MOVE	J,SEG#		;THE SEGMENT IN QUESTION
;	PUSHJ	P,GETHDP	;GET THE ADDRESS
;	<ONLY RETURN - DISK ADDRESS IN T2>
;MUST BE IN SECTION 1

GETHDP::MOVE	T2,(P1)		;GET MAP ENTRY
	TLZ	T2,(PM.NAD^!PM.COR) ;CLEAR ALL BUT COR
	TLZE	T2,(PM.COR)	;IS THIS A DISK ADDRESS?
	LDB	T2,[POINT MT.SAD,@[IW MS.MEM,MEMTAB(T2)],^L<MT.DAD>+MT.SAD-1] ;NO, GET ADDRESS FROM MEMTAB
	POPJ	P,

	
;CORE UUO ROUTINE TO ASSIGN OR REASSIGN CORE FOR HIGH SEG
;CALLED AFTER LOW SEG SEG IS REASSIGNED IF USER HAS NON-ZERO RH IN AC
;CALL:	HRRZ T1,DESCRED HIGHEST USER ADR. IN HIGH SEG
; 	MOVE J, JOB NUMBER
;	PUSHJ P,UCORHI
;	ERROR RETURN - SUM OF SEGMENTS EXCEED MAX. PHYSICAL CORE OR
;		EXCEED TOTAL SYSTEM VIRTUAL CORE CAPACITY
;		SHARABLE PROGRAM MEDDLED WITH(AND NO WRITE PRIV.)
;		 OR HIGH SEG IS SPY SEG

; 	OK RETURN - CORE ASSIGNED(MAYBE NOT IN MEMORY) OR USER ASKED NO CHANGE(LH=0)
;	J AND R RESTORED TO LOW SEG NO AND RELOC

;IF LH IS NON-ZERO BUT LESS THAN 400000 OR END OF LOW SEG(IF GREATER THAN 400000)
;THE HIGH SEGMENT WILL BE REMOVED FROM USERS LOGICAL ADDRESSING SPACE


UCORHI::JUMPE	T1,CPOPJ1##	;ASKING FOR ANY CHANGE?
	HRRO	T3,T1		;SAVE THE USER'S ARGUMENT
	PUSHJ	P,GTRSGN	;GET "RELEVANT" SEGMENT #
	  JRST	UCRHE1		;LOSE IF SPY SEG
	SKIPN	J		;IF NO SEGMENT
	SETZ	T1,		;NO SEGMENT BLOCK POINTER EITHER
	PUSH	P,T1		;SAVE SEGMENT BLOCK POINTER
	PUSHJ	P,HSVAD		;GET ORIGIN AND LENGTH OF THE HIGH SEGMENT
	HRRZS	T3		;CLEAR SIGN SET UP FOR GTRSGN
	CAMGE	T3,T2		;IF NEW HIGHEST ADDRESS .LT.ORIGIN,
	JRST	[POP	P,T1	;RESTORE T1
		 JUMPE	T1,CPOPJ1##
		 JRST	KILHG1]	;KILL THAT SEGMENT
	SKIPN	T1		;CREATING A HIGH SEGMENT?
	MOVE	T1,T2		;YES, HIGHEST ADDRESS EQUALS ORIGIN
	EXCH	T1,T3		;SETUP ARGS FOR CKNZ1
	EXCH	T2,T3		; ..
	IORI	T1,PG.BDY	;ROUND UP TO A PAGE BOUNDRY
	PUSHJ	P,CKNZ1##	;WILL HI SEG OVERLAP LOW SEG?
	  JRST	UCRHE2		;YES, LOSE
	SUB	T1,T3		;NEW LENGTH OF THE HIGH SEG
	MOVEM	T1,(P)		;SAVE THAT (DON'T NEED HSB ADDR ANY MORE)
	LSH	T3,W2PLSH	;HIGH SEG ORIGIN PAGE
	PUSH	P,T3		;SAVE THAT

IFN FTLOCK,<			;LOCK UUO FEATURE?
	MOVE	T3,J		;SAVE J IN T3
	MOVE	J,.USJOB	;GET JOB #
	PUSHJ	P,LOKCHK##	;IS JOB LOCKED?
	  JRST	UCRHE0		;YES, ERROR RETURN-CANNOT CHANGE SIZE
	MOVE	J,T3		;RESTORE J
>
	PUSHJ	P,CHKHWC	;NO, SEE IF CURRENT JOB HAS NOT BEEN MEDDLING OR
				; HAS UPDATE PRIVILEGES IF HAS MEDDLED WITH HIGH SEG
	  JRST	UCRHE0		;NO, ERROR RETURN TO USER
	JUMPN	J,UCORH1	;YES, DOES JOB HAVE A HIGH SEG YET?
				; OR IS THIS FIRST ASSIGNMENT OF CORE TO HIGH SEG
	PUSHJ	P,FNDSGN	;NO, FIND FREE SEG NUMBER BEFORE ASSIGNING CORE
	  JRST	UCRHE0		;ERROR IF NO FREE NUMBERS
	MOVEM	J,.HBSGN(T1)	;SAVE SEGMENT #
	MOVE	J,.USJOB	;GET CURRENT JOB
	EXCH	T1,JBTSGN##(J)	;STORE NEW BLOCK, GET OLD
	HLLM	T1,JBTSGN##(J)	;KEEP BITS
	HRRZ	T2,JBTSGN##(J)	;ADDR OF NEW BLOCK AGAIN
	HRRM	T1,.HBLNK(T2)	;LINK OLD BLOCKS IN
	MOVE	J,.HBSGN(T2)	;RESTORE J TO SEGMENT #
	
UCORH1:	POP	P,T1		;HIGH SEGMENT ORIGIN
	DPB	T1,JBYHSO##	;STORE IT FOR POSTERITY
	LSH	T1,P2WLSH	;HI SEG ADDR
	PUSHJ	P,ZERSWP##	;RETURN SWAPPING SPACE, IF ANY (NULL JOB NEVER HAS
				; SINCE NEW SIZE MAY BE DIFFERENT FROM OLD SIZE
				; SO IT SHOULD BE WRITTEN NEXT SWAPOUT
				; EVEN IF WRITE PROTECTED.
	MOVE	T1,(P)		;CORE ARGUMENT
;HERE TO MAKE SURE THAT ALLOWING THIS HIGH SEGMENT EXPANSION WILL NOT KEEP
; OTHER JOBS SHARING IT FROM BEING ABLE TO BE RUN (SWAPPED IN)
	HLRZ	T2,JBTADR##(J)	;CURRENT SIZE OF THE HIGH SEGMENT
	CAIGE	T2,(T1)		;ALWAYS OK TO GET SMALLER
	TLNN	J,SHRSEG	;ALWAYS OK TO MAKE A NON-SHARABLE SEGMENT BIGGER
	JRST	UCORH4		;OK TO DO THE CORE UUO
	MOVE	P3,(P)		;CORE ARG
	PUSH	P,J		;SAVE THE HIGH SEGMENT NUMBER
	MOVEI	T1,HEXPCK	;ROUTINE TO CHECK HIGH SEG EXPANSION
	TLO	T1,(1B0)	;FLAG NOT TO CALL FOR OURSELVES
	PUSHJ	P,HGHAPP	;APPLY TO ALL HIGH SEGS
	JUMPL	J,UCRHE0	;ABORTED THE SCAN (J NEGATIVE IF SO)?
	POP	P,J		;RESTORE THE HIGH SEGMENT NUMBER
	TDZA	T1,T1		;FLAG THAT WE CALLED HSTOP

UCORH4:	SETO	T1,		;FLAG THAT WE DIDN'T CALL HSTOP
	EXCH	T1,(P)		;SAVE FLAG, GET SIZE
	PUSH	P,T1		;SAVE SIZE
	MOVSI	R,SHRSEG	;THIS A SHARABLE HIGH SEG?
	TDNN	R,JBTSTS##(J)	;(ONLY NEED SCDLOK FORR SHARABLE)
	JRST	UCORH5		;CONTINUE IF NOT SHARABLE
	AOS	T1		;MAX # OF WORDS IN NEW HIGH SEG
	LSH	T1,W2PLSH	;CONVERT TO PAGES
	PUSHJ	P,GTHMAP	;MAKE SURE HIGH SEG MAP CAN HANDLE THIS
	  JRST	UCRHA1
UCORH5:	POP	P,T1		;RESTORE AMOUNT OF CORE REQUEST
	MOVE	R,JBTADR##(J)	;R TO PREVIOUS HIGH SEG CORE ASSIGNMENT(IF ANY)
				;DON'T ALLOW CPU1 TO RUN THIS SEGMENT
				;WHILE CORE SIZE IS CHANGING
	PUSHJ	P,CORE0##	;TRY TO ASSIGN CORE TO HIGH SEG(ON DISK OR MEMORY)
	  JRST	UCRHA0		;ERROR, CORE REQUEST TOO BIG, IF NO ONE IS USING
				; (INCLUDING THIS USER) LEAVE SEG NON-EXISTENT,
				; OTHERWISE DORMANT OR STILL IN USE BY THIS AND/OR
				; OTHER USERS
	POP	P,T1		;RESTORE FLAG
	JUMPN	T1,UCORH7	;NO NEED TO CALL HGO
	PUSH	P,J		;SAVE J
	MOVEI	T1,HGO		;GET EVERYONE USING SEGMENT GOING AGAIN
	TLO	T1,(1B0)	;DON'T TRY TO RESTART US
	PUSHJ	P,HGHAPP
	POP	P,J		;RESTORE J
UCORH7:	MOVSI	T1,SWP		;IF THIS IS A HIGH SEGMENT WHICH WAS CREATED
	SKIPN	JBTADR##(J)	; BY THIS CORE UUO, CORE MAY BE ASSIGNED ON DISK
	IORM	T1,JBTSTS##(J)	;IT WAS - MARK THE HIGH SEGMENT AS SWAPPED
				; SHARE2 WILL MARK THE LOW SEGMENT
	MOVE	T1,.USJOB	;LOAD JOB #
	SJSP	T3,SHARE2	;OK RETURN, MARK USER AS HAVING THIS HIGH SEG IN LOG.
				; ADR. SPACE(IN CASE IT WAS NOT BEFORE)
				; SET RELOC AND SKIP RETURN
				; AND INCREMENT HIGH SEG IN CORE CONT FOR THIS JOB
				; IF NOT ALREADY DONE SO.
				; FLAG (T3) NOT TO CHECK FOR CONNECTING TO IDLE
				; HI-SEG SINCE IT CANNOT BE (BUT LOOKS IDLE)

UCRHA1:	POP	P,T1		;SIZE
UCRHA0:	POP	P,T1		;FLAG
	JUMPN	T1,SETMAP##	;DIDN'T CALL HSTOP
	PUSH	P,J		;SAVE J
	MOVEI	T1,HGO
	TLO	T1,(1B0)
	PUSHJ	P,HGHAPP	;GET EVERYONE ELSE GOING AGAIN
	POP	P,J		;RESTORE J
	PJRST	SETMAP##

UCORHE:	POP	P,T1		;POP OFF JUNK

UCRHE0:	POP	P,T1		;RESTORE PDL
UCRHE2:	POP	P,T1		;ONCE MORE
UCRHE1:	JRST	SETMAP##	;AND SETUP HARDWARE, SET R TO LOW SEG
				; RELOC, J TO CURRENT JOB, AND ERROR RETURN
;SUBROUTINE TO CHECK THAT A HIGH SEG EXPANSION IS LEGAL FOR ALL JOBS
;OWNING THE SEGMENT, AND TO STOP THEM RUNNING WHILE THE EXPANSION OCCURS
;(IN CASE THE MAP MUST BE REDONE)
;P3 HAS CORE ARG

HEXPCK:	PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,HSTOP		;STOP JOB FROM RUNNING
	TLO	P1,PHONLY	;SET PHYS ONLY FOR CORBND
	PUSHJ	P,CORBND##	;AMOUNT OF CORE THIS JOB IS ALLOWED
	PUSHJ	P,SEGSIZ##	;CURRENT SIZE OF THE LOW SEGMENT
	TLZ	P1,PHONLY	;CLEAR BIT (PHONLY=IFIW)
	LSH	T2,P2WLSH
	ADD	T2,P3		;SIZE JOB WILL BE IF HI SEG EXPANDS
	SUBI	T2,UPMSZW##	;CORBND DOESN'T COUNT UPMP SIZE
	CAMG	T2,T1		;WILL THIS JOB STILL FIT?
	POPJ	P,		;YES, CHECK NEXT JOB
	HRRZ	T1,.HBSGN(P2)	;GET SEGMENT #
	PUSH	P,T1		;SAVE IT
HEXPC2:	PUSHJ	P,HGO		;GET THIS JOB GOING AGAIN
	AOS	J		;POINT TO NEXT JOB
	CAMLE	J,HIGHJB##	;OVER THE TOP?
	JRST	HEXPC3		;YES
	MOVE	T1,(P)		;SEGMENT #
	PUSHJ	P,FNDHSB	;OWN THIS SEGMENT?
	  JRST	HEXPC2		;NO
	PUSHJ	P,HGO		;GET THIS JOB GOING AGAIN
	JRST	HEXPC2
HEXPC3:	POP	P,(P)		;FIX STACK
	SETZ	J,		;STOP SCAN NOW AND RETURN J NEGATIVE
	POPJ	P,

;SUBROUTINE TO STOP A JOB FROM RUNNING SO THAT WE CAN MUCK WITH ONE OF ITS
;HIGH SEGS.  CALL WITH J=JOB # TO STOP, AND P2 CONTAINING HSB ADDR
;NOTE:  THIS ROUTINE IS USUALLY CALLED VIA HGHAPP AND SHOULD NOT BE CALLED
;FOR THE JOB CALLING HGHAPP (SEE HGHAPP FOR DETAILS ON HOW TO AVOID THIS)
;AS IF AFTER THAT JOB IS PROCESSED IT IS NECESSARY TO BLOCK FOR ANOTHER JOB,
;THEN THE JOB CALLING HGHAPP WILL NEVER BE RUN AGAIN BY THE SCHEDULAR

HSTOP::	SYSPIF				;PREVENT RACE
	MOVSI	T1,SWCUP		;FLAG THE COUNT IS UP
	IORM	T1,.HBSGN(P2)		;SET THAT
	MOVSI	T1,1			;INCREMENT HIGH SEG COUNT
	.CREF	SCHKM
	ADDM	T1,JBTSGN##(J)		;FOR THE JOB
	SYSPIN
HSTOP1:	PUSHJ	P,ANYRUN##		;JOB RUNNING ANYWHERE?
	  CAIA				;YES, WAIT FOR IT TO STOP
	POPJ	P,			;JOB STOPPED
	PUSH	P,J			;SAVE J
	MOVE	J,.CPJOB##		;US
	MOVSI	T1,-1
	ADDM	T1,JBTCCC##(J)		;DON'T LET JOB ^C OUT
	SETZ	T1,
	PUSHJ	P,SLEEPF##		;WAIT A BIT
	PUSHJ	P,DECCCC##		;REDUCE ^C COUNT
	POP	P,J
	JRST	HSTOP1			;SEE IF IT STOPPED YET

;SUBROUTINE TO GET A JOB GOING AGAIN AFTER IT WAS STOPPED VIA HSTOP.
;NORMALLY CALLED FROM HGHAPP WITH J=JOB# TO START

HGO::	SYSPIF				;INTERLOCK
	MOVSI	T1,SWCUP		;CLEAR THE FACT THE COUNT'S UP
	TDNN	 T1,.HBSGN(P2)		;WAS WAIT COUNT UP?
	JRST	ONPOPJ##		;NO
	ANDCAM	T1,.HBSGN(P2)
	MOVSI	T1,SCHKM		;MASK TO CHECK
	AND	T1,JBTSGN##(J)		;GET COUNT AS IT IS
	SKIPN	T1			;ALREADY ZERO?
	STOPCD	ONPOPJ,DEBUG,SWZ	;++SEGMENT WAIT COUNT ZERO
	ANDCAM	T1,JBTSGN##(J)		;CLEAR FIELD
	SUB	T1,[1,,0]		;DECREMENT FIELD
	.CREF	SCHKM
	IORM	T1,JBTSGN##(J)		;SET DECREMENTED VALUE
	PJRST	ONPOPJ##		;SYSPIN AND RETURN

;SUBROUTINE TO TURN ON REDOMP FOR JOBS USING SEGMENT.  CALLED VIA HGHAPP

HRDOMP:	MOVSI	T1,REDOMP		;TURN IT ON
	IORM	T1,JBTSGN##(J)		;FOR THE JOB
	IORM	T1,.HBSGN(P2)		;AND THE PARTICULAR SEGMENT
	POPJ	P,
	
;UUO TO REMAP TOP PART OF LOW SEGMENT INTO HIGH SEGMENT
;PREVIOUS HIGH SEGMENT(IF IT EXISTED) IS REMOVED FROM LOGICAL ADDRESSING SPACE
;CALL:	MOVE T1,HIGHEST DESIRED REL. ADR. IN NEW LOW SEG.
;				(EXEC ORES IN 1777 TO MAKE EVEN 1K-1)
;	MOVE R,XWD PROTECTION,RELOCATION FOR LOW SEGMENT
;	PUSHJ P,UREMAP
;	ERROR RETURN - DESIRED HIGHEST REL. ADR PAST END OF LOW SEG
;			;OR 1 REGISTER MACHINE
;	OK RETURN - HARDWARE AND SOFTWARE RELOCATION INFO RESET
;	J RESET TO CURRENT JOB NUMBER, AND R TO RELOC
;MUST BE CALLED AT UUO LEVEL ONLY


UREMAP::SETZM	.JDAT+SGAEXT##	;SO NEW HGH CAN TELL SHR FROM HGH
	SETZM	.JDAT+SGANAM##	;NO .JBHRL NAME IS KNOWN
	SETZM	.JDAT+SGAEND##	;ALSO, NO FLAGS (GETSEG VARIETY)
	MOVSI	T2,(UP.GET)
	ANDCAM	T2,.USBTS	;GET NO LONGER IN PROGRESS
UREMA0:	MOVSI	T2,NSWP!NSHF
	TDNE	T2,JBTSTS##(J)	;LOCKED?
	POPJ	P,		;YES, ERROR RETURN
	IORI	T1,PG.BDY	;MAKE AN EVEN MULTIPLE OF 1K-1
	PUSH	P,T1		;YES, SAVE DESIRED HIGHEST ADR OF NEW LOW SEG
	HRRZS	T1		;CLEAR POSSIBLE HIGH SEGMENT ORIGIN
	CAMLE	T1,.CPREL##	;YES, IS NEW TOP OF LOW SEG LESS THAN OR EQUAL TO OLD?
	JRST	TPOPJ##		;NO, ERROR RETURN - 1 REG MACHINE OR ARG TOO BIG
	PUSH	P,.JDAT+SGAEND##;SAVE FLAGS
	PUSH	P,.JDAT+SGANAM##;NAME
	PUSH	P,.JDAT+SGAEXT##;AND EXTENSION IN CASE IOWAIT OR UPMM BLOCKS
	PUSH	P,F		;SAVE F (IOWAIT CHANGED IT)
	PUSHJ	P,IOWAIT##	;WAIT FOR IO TO STOP IN LOW SEG
	POP	P,F		;RESTORE F
IFN FTMP,<
	PUSHJ	P,UPMM##	;MUST OWN THE MM RESOURCE TO DO A REMAP
>
	POP	P,.JDAT+SGAEXT##;RESTORE POSSIBLE GETSEG FLAGS AND SUCH
	POP	P,.JDAT+SGANAM##; ..
	POP	P,.JDAT+SGAEND##; ..
	HRRZ	T2,(P)		;RESTORE DESIRED HIGHEST ADR IN NEW LOW SEG
	SKIPE	T1,.USREL	;IF NON-ZERO, PREVIOUS HIGHEST ADR IN LOW SEG
	JRST	UREMA2		;DON'T CHANGE JBTADR
	HLRZ	T1,JBTADR##(J)	;GET PREVIOUS HIGHEST ADR OF LOW SEG
	HRLM	T2,JBTADR##(J)	;STORE NEW(LESS THAN OR EQUAL) HIGHEST ADR OF LOW SEG
UREMA2:	SUBI	T1,1(T2)	;COMPUTE LENGTH-1 OF NEW HIGH SEG
	JUMPL	T1,UREMA3	;-1 MEANS NEW LOW SEG=OLD LOW SEG
				; RESET HARDWARE BECAUSE NO HIGH SEG ANY MORE
				; FOR SURE, SET RELOC. HARD. AND SKIP RETURN
	ADD	T2,JBTADR##(J)	;ADD ABS. ADR. OF LOW SEG TO LENGTH-1 OF LOW SEG
				;TO FORM LENGTH-1 OF NEW HIGH SEG
	HRLI	T1,1(T2)	;MOVE ABS ADR. OF NEW HIGH SEG TO LH
	POP	P,T2		;RESTORE USER'S ARGUMENT (NEWHGH WILL
				; PUT THE HIGH SEGMENT AT THE LEFT HALF
	HRRZ	T4,T2		;SAVE WHERE,,NEW LOW SEGMENT SIZE
	HLRZS	T2		;WHERE TO PUT THE HIGH SEGMENT
	ANDI	T2,777000	;MAKE SURE ITS ON A PAGE BOUNDARY
	JUMPN	T2,UREMA1	;JUMP IF HIGH SEGMENT STARTING ADDRESS SPECIFIED
	TRNE	T4,400000	;IS THE LOW SEGMENT BIGGER THAN 128K?
	SKIPA	T2,T4		;YES, HIGH SEGMENT ORIGIN IS FIRST PAGE ABOVE
				; THE LOW SEGMENT
	MOVEI	T2,377777	;NO, HIGH SEGMENT GOES AT 400000
	MOVEI	T2,1(T2)	;HIGH SEGMENT ORIGIN (ALSO CLEAR LEFT HALF OF T2)
UREMA1:	MOVE	T3,.CPJOB##	;CURRENT JOB NUMBER
	MOVEM	R,JBTADR##(T3)	;STORE PREVIOUS PROTECTION,,JDAT IN CASE OF ERROR
	MOVEI	T3,1(T1)	;NUMBER OF WORDS IN NEW HIGH SEGMENT
	MOVEI	T1,1(T4)	;ADDRESS WHERE REMAP STARTS
	LSHC	T1,W2PLSH	;T1=FROM PAGE, T2=TO PAGE
	LSH	T3,W2PLSH	;NUMBER OF PAGES
	HLRZ	T4,.JDAT+SGAEXT##	;FILE EXTENSION
	CAIN	T4,'SHR'	;SHARABLE?
	TDZA	T4,T4		;YES
	MOVSI	T4,(1B0)	;INDICATE NON-SHARABLE TO NREMAP
	PUSHJ	P,NREMAP##	;REMAP IT
	  JRST	UREMA4		;HIGH SEGMENT WOULD OVERLAP THE LOW SEGMENT
	SJSP	T3,SHARE1	;SET IN CORE COUNT TO 1, FLAG THIS SEG IN CURRENT
				; JOB'S LOG. ADR. SPACE, AND FLAG HIGH SEG NO.
				; AS ASSIGNED(SNA=1)
				; RESET HARD. AND SOFT. RELOC, AND SKIP RETURN
				; (SET FLAG(T3) SO NOT CHECK FOR CONNECTING TO
				; IDLE HI-SEG SINCE IT CANNOT BE IDLE, BUT
				; IT WILL LOOK LIKE IT IS.)
UREMA4:	SOSA	(P)		;SETRL1 DOES AOS (P), SO FORCE ERROR RETURN

UREMA3:	POP	P,T1		;POP OFF JUNK & GIVE GOOD RETURN
				;FOR UNCHANGED LOW SEG (DISCARD HISEG)
IFN FTMP,<
	PUSHJ	P,TGVMM##	;GIVE UP THE MM IF OWNED
>
	JRST	SETRL1		;REDO PROTECTION-RELOCATION AND GIVE ERROR RETURN
	
;ROUTINE TO FIND A FREE SEG NUMBER FOR A NEW HIGH SEGMENT FOR CURRENT JOB
;CALLED BY CORE UUO AND REMAP UUO(MUST BE CALLED AT UUO LEVEL ONLY)
;TRIES TO FIND A FREE SEGMENT WITHOUT DORMANT COPY ON DISK OR CORE
;IF NONE, IT FINDS A SEG WHICH IS DORMANT ON DISK AND/OR CORE
; DELETES UNUSED DISK AND CORE AND REUSES THAT HIGH SEG NUMBER
;(A SEGMENT CANNOT BE DORMANT ON DISK AND USED IN CORE OR VICE VERSA)
;NEW HIGH SEG IS FLAGGED AS NON-SHARABLE(SHRSEG=0 IN JBTSTS FOR HIGH SEG)
;IN CORE COUNT IS SET TO 0
;CALL:	PUSHJ P,FNDSGN
;	RETURN WITH J SET TO FREE SEG NUMBER
;HOWEVER CURENT JOB IS NOT MARKED AS HAVING THIS SEG IN LOGICAL ADR SPACE
; SINCE THER MAY NOT BE ENOUGH CORE FOR SEGMENT. THE CALLER MUST FLAG USER
; AS HAVEING THIS SEG IN ADDRESSING SPACE IF EVERYTHING OK
;THE LH OF J IS SET TO 0(SHRSEG=MEDDLE=UWPOFF=SPYSEG=0)
;THE CALLER MUST ALSO FLAG HIGH SEG AS ASSIGNED(SNA=1) IF EVERYTHING OK
;T1 RETURNS THE POINTER TO THE (BLANK) SEGMENT DATA BLOCK

FNDSGN::
FND0:	MOVE	J,SEGPTR##	;SCAN JUST HIGH SEGMENTS(NOT JOBS)
	MOVE	T2,[OUTMSK##]	;MASK FOR DISK IMAGE BYTE POINTER
FND1:	SKIPL	JBTSTS##(J)	;SEG NUMBER ASSIGNED(SNA=1)?
	SKIPE	JBTADR##(J)	;NO, DOES HIGH SEG STILL HAVE CORE ANYWAY?
	JRST	FND1A		;YES, KEEP LOOKING
	TDNE	T2,JBTIMO##(J)	;NO, DOES IT HAVE DISK SPACE?
FND1A:	AOBJN	J,FND1		;YES, KEEP LOOKING, MORE TO GO?
	JUMPL	J,FNDOK		;NO, WAS A FREE SEG NUMBER FOUND WITH NO CORE ASSIGNED?
	MOVEI	T2,SEGN##	;NO. OF HIGH SEGMENTS IN SYSTEM
	AOS	J,SEGPT1##	;START AT SEGMENT AFTER LAST DORMANT SEG
FND2:	CAILE	J,JBTMAX##	;STILL LESS THAN OR EQUAL TO MAX SEG NO.?
	HRRZ	J,SEGPTR##	;NO, START OVER AT FIRST HIGH SEG
	SKIPL	T1,JBTSTS##(J)	;IS THIS HIGH SEG NO. ASSIGNED (SNA=1)?
	JRST	FNDOK1		;NO, FOUND A DORMANT SEG?
FND3:	ADDI	J,1		;NO, LOOK AT NEXT ONE
	SOJG	T2,FND2		;LOOKED AT ALL SEG?
	MOVEI	T1,1		;THE ONLY DORMANT SEGMENTS FOUND WERE
				; IN THE PROCESS OF BEING SWAPPED OUT.
	MOVE	J,.CPJOB##	;POINT J BACK AT JOB
IFN FTMP,<
	PUSHJ	P,DIFMM##	;GIVE UP MM IF OWNED
>
	PUSHJ	P,SLEEPF##	;SO WAIT UNTIL SWAPOUT COMPLETES
IFN FTMP,<
	PUSHJ	P,UIFMM##	;GET BACK MM IF IT WAS OWNED
>
	JRST	FND0		;TRY AGAIN
FNDOK1:	TLNE	T1,NSHF		;SWAP OUT OF THIS SEGMENT IN PROGRESS?
	JRST	FND3		;YES, SKIP IT FOR NOW
	MOVEM	J,SEGPT1##	;REMEMBER LAST DORMANT SEGMENT FOUND FOR NEXT TIME
				; SO WILL THROW AWAY OLDEST DORMANT SEG
FNDOK:	TLZ	J,777777	;TURN OFF MEDDLE,SHRSEG,UWPOFF,SPYSEG,CORCNT)
	PUSHJ	P,CLRNAM	;CLEAR HIGH SEG NAME SO NO LONGER
				; SHARABLE TO NEW USERS, DELETE DISK AND CORE(IF ANY)
	SETZM	JBTSTS##(J)	;CLEAR ALL BITS AND IN CORE COUNTS JUST FOR GOOD
				; MEASURE(SHRSEG!SERR COULD BE STILL ON FOR HIGH SEG)
;	PJRST	MAKHSB		;GET A HIGH SEG BLOCK; RETURN WITH ADDRESS IN T1
;
;ROUTINE TO GET A HIGH SEGMENT DATA BLOCK

MAKHSB:	MOVEI	T2,.HBLEN	;GET SEGMENT DATA BLOCK
	PUSHJ	P,GETWDS##	;GET CORE
	  POPJ	P,		;CAN'T GET ONE
	SETZM	(T1)		;CLEAR THE BLOCK OUT
	MOVSI	T2,(T1)		;MAKE A BLT POINTER
	HRRI	T2,1(T1)
	BLT	T2,.HBLEN-1(T1)	;CLEAR OUT THE BLOCK
	JRST	CPOPJ1##	;DONE

;HERE TO FIND THE "RELEVANT" SEGMENT FOR A SECTION (CORE UUO)
;RETURN CPOPJ IF SPY SEG, CPOPJ1 OTHERWISE
;ENTER WITH T3=SECTION,,HIGHEST RELATIVE ADDRESS DESIRED,
;IF SECTION # IS -1, THEN PCS WILL BE USED
;OR 0 FOR LOWEST ORIGINED SEGMENT IN SECTION
;EXIT WITH T1 POINTING TO SEGMENT DATA BLOCK AND J CONTAINING .HBSGN WORD

GTRSGN::
	SKIPN	J,JBTSGN##(J)	;JOB HAVE ANY SEGMENTS?
	JRST	CPOPJ1##	;NO, RETURN SAYING THAT
	HLRE	T4,T3		;SECTION #
	AOSE	T4		;WAS -1 SPECIFIED?
	SOSA	T4		;NO, LEAVE IT AS IS
	XSFM	T4		;GET PCS SECTION
	ANDI	T4,MXSECN	;MASK OFF JUNK
	HRRZS	T3		;CLEAR SECTION # IN T3
	PUSHJ	P,RSECT4##	;RESOLVE IT
	  JFCL
	HRRZS	T1,J		;SEGMENT DATA BLOCK ADDRESS TO T1
	JUMPE	T1,CPOPJ1##	;REALLY ARE NO SEGMENTS
	PUSH	P,T3		;SAVE USER'S ARG
	PUSH	P,[0]		;ASSUME NO SEGMENTS WILL BE FOUND
	MOVSI	T3,-1		;LOWEST ORIGIN SEEN,,LAST ONE SEEN
GTSGLP:	LDB	J,[PSG2LH+.HBSG2(T1)] ;GET SECTION THIS SEGMENT IN
	CAIE	J,(T4)		;IS IT THIS SECTION
	JRST	GTSGLE		;NO, CHECK NEXT
	SKIPN	(P)		;IF NO SEGMENT YET SAVED,
	MOVEM	T1,(P)		;SAVE THIS SEGMENT
	HRRZ	J,.HBSGN(T1)	;GET SEGMENT #
	SKIPL	.HBSGN(T1)	;SPY SEG?
	SKIPA	T2,JBYHSO##	;NO, USE JBYHSO FOR ORIGIN
	MOVE	T2,[PSPOLH+.HBSPO(T1)] ;WHERE A SPY SEG ORIGIN IS STORED
	LDB	T2,T2		;GET ORIGIN
	LSH	T2,P2WLSH	;CONVERT TO WORD ADDRESS
	CAIG	T2,@-1(P)	;THIS HIGH SEG ORIGIN BELOW GIVEN ARG?
	CAIGE	T2,(T3)		;YES, THIS ONE HIGHER THAN LAST?
	JRST	GTSGLO		;NEW ORIGIN>ARG OR LESS THAN PREV FOUND
	MOVEI	T3,(T2)		;REMEMBER NEW HIGHEST ORIGIN
	MOVEM	T1,(P)		;AND ADDR OF SEG DATA BLOCK
GTSGLE:	HRRZ	T1,.HBLNK(T1)	;LINK TO NEXT
	JUMPN	T1,GTSGLP	;LOOP BACK TO CHECK IT
GTSGLX:	POP 	P,T1		;RESTORE ADDR OF DATA BLOCK IF FOUND
	HRRZS	T1		;CLEAR JUNK IN LH
	SKIPE	J,T1		;IS THERE A SEGMENT?
	SKIPL	J,.HBSGN(J)	;YES, GET SEGMENT NUMBER
	AOS	-1(P)		;SKIP RETURN IF NOT SPY
	JRST	T3POPJ##	;SPY SEG

GTSGLO:	TRNE	T3,-1		;FOUND SOME SEGEMENT WHICH MATCHED?
	JRST	GTSGLE		;YES, DON'T CHANGE
	HLRZS	T3		;GET HIGHEST PAGE SO FAR (OR 0,,-1)
	CAIGE	T3,(T2)		;REMEMBER THE LOWEST ADDRESS IF FOUND NONE
	MOVEI	T3,(T2)		;NEW ONE IS LOWER
	MOVSI	T3,(T3)		;REMEMBER IN LEFT HALF
	MOVEM	T1,(P)		;REMEMBER THIS SEGMENT
	JRST	GTSGLE
;SUBROUTINE TO RETURN NEXT SEGMENT ABOVE GIVEN ADDRESS IN SECTION
;CALL WITH T1=ADDRESS, T3=SECTION
;RETURN WITH T1 POINTING TO HIGH SEG DATA BLOCK OR ZERO IF NONE

GTNSGN::PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVE	P2,T1		;ADDRESS ARG
	SETZ	P3,		;DEFAULT FOUND NO SEGMENT
	MOVEI	P4,-1		;HIGHEST ADDR FOUND
	PUSH	P,J		;SAVE J
	MOVE	P1,T3		;PUT SECTION IN P1
	SETZ	T1,		;FIRST CALL
GTNSG1:	PUSHJ	P,NXSSP1	;GET NEXT SEGMENT IN SECTION
	  JRST	GTNSGD		;DONE
	SKIPGE	J,.HBSGN(T1)	;GET SEGMENT WORD
	JRST	[LDB  J,[PSPOLH+.HBSPO(T1)] ;IF SPY SEG, GET FROM SPY ORIGIN
		 JRST GTNSG3]
	HRRZS	J		;CLEAR JUNK
	LDB	J,JBYHSO##	;GET ORIGIN
GTNSG3:	LSH	J,P2WLSH	;CONVERT TO WORD ADDR
	CAILE	J,(P2)		;IS THIS SEGMENT ABOVE GIVEN ADDR?
	CAIL	J,(P4)		;AND IS IT BELOW LAST SEG FOUND
	JRST	GTNSG1		;NOT ABOVE GIVEN OR NOT BELOW LAST
	MOVEI	P4,(J)		;LOWEST FOUND
	HRRZ	P3,T1		;HSB FOR THAT SEGMENT
	JRST	GTNSG1

GTNSGD:	POP	P,J		;RESTORE J
	MOVE	T1,P3		;SEGMENT FOUND (IF ANY)
	POPJ	P,		;RETURN
;SUBROUTINE TO FREE UP CORE IN CORE BY DELETING DORMANT OR IDLE
; SEGMENTS WHICH HAVE DISK COPIES
;ENTER WITH T3= NUMBER OF PAGES REQUIRED
;EXIT CPOPJ IF NOT ENOUGH PAGES CAN BE MADE AVAILABLE,
; EXIT CPOPJ1 IF ENOUGH CORE HAS BEEN FREED
;PRESERVES ALL ACS

FRDCR::	CAMG	T3,BIGHOL##	;THAT MUCH AVAILABLE ALREADY?
	JRST	CPOPJ1##	;YES, RETURN GOODNESS
	PUSHJ	P,FRPCR##	;CAN ENOUGH BE FREED BY ALLOCATING FROM "OUT" QUEUE
	  CAIA			;NO, TRY DELETING DORMANT SEGMENTS
	JRST	CPOPJ1##	;YES, GOODNESS
	CAMLE	T3,CORTAL##	;CAN ENOUGH CORE BE FREED?
	POPJ	P,		;NO
	CAMG	T3,BIGHOL##	;THAT MUCH ALREADY AVAILABLE?
	JRST	CPOPJ1##	;YES, RETURN GOODNESS
IFN FTXMON,<
	PUSHJ	P,SSEC0##	;MUST RUN IN SECTION 0
>
	PUSHJ	P,SAVT##	;SAVE T1-T4
	PUSH	P,J		;SAVE J
	MOVNI	J,DISQ##	; HEADER FOR DORMANT/IDLE SEGMENTS
	HRRE	J,JBTDIQ##(J)	; GET FIRST ENTRY IN QUEUE (OLDEST)
FRDCR1:	MOVEI	T1,ICCMSK	;IN CORE COUNT MASK
	HRLI	T1,NSHF!NSWP	;LOOK FOR DORMANT OR IDLE UNLOCKED SEGMENTS
	MOVE	T3,-4(P)	;AMOUNT OF CORE REQUIRED
	CAMG	T3,BIGHOL##	;IS THAT MUCH AVAILABLE
	JRST	JPOPJ1##	;YES, RESTORE J AND GIVE CORE AVAILABLE RETURN
FRDCR2:	JUMPLE	J,JPOPJ##	; ANY MORE SEGS IN QUEUE?
	HRRE	T2,JBTDIQ##(J)	; YES. GET SUCCESSOR
	MOVEM	T2,NXTSEG	; SAVE IN CASE DELETE ENTRY
	SKIPE	JBTADR##(J)	;SEGMENT IN CORE?
	TDNE	T1,JBTSTS##(J)	;UNLOCKED AND DORMANT OR IDLE?
	JRST	FRDCR3		;NO
	LDB	T2,IMGOUT##	;DOES IT HAVE A DISK COPY?
	JUMPE	T2,FRDCR3	;NO, CONTINUE LOOKING
	SKIPN	T2,FIT##	; FITTING SOMEONE?
	SKIPLE	T2,FINISH##	;OR ACTUALLY SWAPPING HIM IN?
	CAILE	J,JOBMAX##	;YES, A LOW SEG?
	JRST	FRDCR4		;NO
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;START OF SEGMENT DATA BLOCK CHAIN
FRDCR8:	SKIPN	T1,.HBLNK(T1)	;NEXT SDB
	JRST	FRDCR9		;NO MORE
	SKIPLE	T2,.HBSGN(T1)	;GET SEGMENT # IF ANY
	CAIE	J,(T2)		;THIS SEGMENT?
	JRST	FRDCR8		;NOT THIS SEGMENT
FRDCR3:	SKIPLE	J,NXTSEG	; GET NEXT QUEUE ENTRY, IF ANY
	JRST	FRDCR2		; THEIR IS, KEEP GOING
	JRST	JPOPJ##		;SOME OF THE DORMANT SEGMENTS DON'T HAVE A DISK COPY
				; RESTORE S AND GIVE CORE NOT AVAILABLE RETURN

FRDCR9:	POP	P,T1		;RESTORE T1
FRDCR4:	MOVE	T2,SYSUPT##	;SYSTEM UPTIME
	SUB	T2,JBTIDT##(J)	;MINUS TIME WENT IDLE/DORMANT
	CAMG	T2,SGTLIM##	; LESS THAN LIMIT?
	JRST	FRDCR3		;YES. DON'T DELETE IT
	PUSH	P,NXTSEG	; SAVE THE SUCCESSOR
	PUSHJ	P,KDORCR	;DELETE THE DORMANT OR IDLE SEGMENT FROM CORE
	POP	P,J		; RESTORE NEXT QUEUE ENTRY
	JRST	FRDCR1		;SEE IF ENOUGH CORE IS AVAILABLE NOW
;SUBROUTINE TO TRY AND ALLOCATE SUFFICIENT CORE FOR
;A JOB LIKE FRDCR, BUT WILL WAIT TO DUMP THE IN QUEUE
;IF ENOUGH CAN BE ALLOCATED THAT WAY

FRDCRW::
	PUSHJ	P,FRDCR		;SEE IF CAN GET THE USUAL WAY
	  CAIA			;NO, WAIT
	JRST	CPOPJ1##	;RETURN GOODNESS
	PUSHJ	P,UUOLVL##	;IF NOT AT UUO LEVEL,
	  POPJ	P,		;CAN'T WAIT
	PUSHJ	P,SAVT##	;SAVE TS
	PUSH	P,U		;AND U
	PUSH	P,F		;F
FRDCW1:	MOVE	T1,CORTAL##	;MAX AMOUNT AVAILABLE HERE
	ADD	T1,PAGOUC##	;# ON OUT QUEUE
	ADD	T1,PAGIPQ##	;# ON IP QUEUE
	ADD	T1,PAGSNC##	;# ON SLOW QUEUE
	ADD	T1,PAGINC##	;AND FAST IN QUEUE
	CAIL	T3,(T1)		;IS THERE ENOUGH WITH ALL CONSIDERED?
	JRST	FUPOPJ##	;CAN'T ALLOCATE EVEN IF WE DUMP THE QUEUE
	PUSH	P,S		;SAVE S (FOR FILSER)
	PUSHJ	P,PAGQWT	;START I/O AND WAIT UNTIL I/O COMPLETES
	POP	P,S		;RESTORE S (FOR FILSER)
	MOVE	T3,-5(P)	;RESTORE T3
	PUSHJ	P,FRDCR		;NOW IS THERE ENOUGH?
	  JRST	FRDCW1		;STILL NO, CHECK QUEUES AGAIN
				;(IN CASE, EG, PAGIPQ WAS BUSY)
	JRST	FUPOJ1##	;RETURN GOODNESS

PAGQWT:	PUSHJ	P,SSEC0##	;DO THIS IN S0
	PUSHJ	P,SAVJW##	;SAVE J & W
	MOVE	J,.CPJOB##	;BE SURE J IS RELIABLE
	PUSHJ	P,BMSLST##	;BUILD THE LIST
IFN FTMP,<
	PUSHJ	P,REMMM##	;REMEMBER STATE OF MM
>
	PUSHJ	P,IOWAIT##	;WAIT FOR I/O TO STOP
	PUSHJ	P,ZERIPT##	;GIVE UP ICPT
	MOVEI	T1,PQIOQ##	;PUT IN PAGING QUEUE WAIT
	DPB	T1,PJBSTS##	;PUT THERE
	PJRST	WSCHED##	;WAIT


	$LOW			;
NXTSEG:	0			; NEXT SEGMENT IN QUEUE
	$HIGH			;
;ROUTINE TO INCREMENT HIGH SEG SHARE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG
;CALL:	MOVE J,XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
;	MOVE	T2,HIGH SEG DATA BLOCK ADDR
;	MOVE	T1,JOB HUMBER
;	PUSHJ P,INCSHR
;	ALWAYS RETURN WITH C(J)=JBTSGN(T1)
;SHRCNT IS SET TO 1 TO FLAG THIS JOB AS HAVING INCREMENTED SHARE COUNT
;CALLED FROM SHARE1


INCSHR:	PUSH	P,T2		;SAVE T2
	TLON	J,SHRCNT	;HAS HIGH SEG SHARE COUNT ALREADY BEEN
	AOS	JBTSHR##(J)	; INCREMENTED FOR THIS JOB?
				;NO, INCREMENT HIGH SEG SHARE COUNT
	PUSHJ	P,COMIT		;COMPARE J WITH JBTSGN(T1)
	PUSHJ	P,SETSGN
	  MOVEM	J,.HBSGN(T2)	;SAVE SEGMENT NUMBER AND RETURN
	JRST	T2POPJ##	;RESTORE T2 AND RETURN


;ROUTINE TO DECREMENT HIGH SEG SHARE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG
;CALL:	MOVE J XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
;	MOVE T1, JOB NUMBER
;	PUSHJ P,DECSHR
;	RET1 SHARE COUNT NOT YET 0 OR SHARE COUNT NOT UP FOR THIS JOB
;	RET2 SHARE COUNT WENT TO 0
;CALLED FROM KILHGH
;NOTE THAT AN APPROPRIATE JOB MUST BE MAPPED FOR THE UP.CTX TEST


DECSHR:	PUSH	P,T2		;SAVE T2
	PUSHJ	P,COMIT		;COMPARE J WITH JBTSGN(T1)
	MOVSI	T1,(UP.CTX)	;DOING A PUSH?
	TDNN	T1,.USBTS	;?
	TLZN	J,SHRCNT	;HAS HIGH SEG SHARE COUNT ALREADY BEEN
				;DECREMENTED FOR THIS JOB?
	JRST	T2POPJ##	;ALREADY DECR OR PUSH, RESTORE T2 AND RETURN
	SOS	JBTSHR##(J)	;NO, DECREMENT HIGH SEG SHARE COUNT
	PUSHJ	P,SETSGN
	  MOVEM	J,.HBSGN(T2)	;STORE UPDATED SEGMENT #
	POP	P,T2
DCSERR:	HRRE	T1,JBTSHR##(J)	;GET HIGH SEG SHARE COUNT
	JUMPE	T1,DCSDID	;IF WENT TO ZERO, CHECK DORMANT/IDLE AND SKIP RETURN
	SKIPL	T1		;NO, NEGATIVE?
	POPJ	P,		;NO
	AOS	JBTSHR##(J)	;NO, ERROR ADD BACK TO 0
	STOPCD	DCSERR,DEBUG,SSCNEG,	;++SEGMENT SHARE COUNT NEGATIVE

DCSDID:	SKIPE	JBTDIQ##(J)	;IS SEGMENT ALREADY IN QUEUE?
	JRST	CPOPJ1##	;YES, WE'RE DONE, JUST GIVE SKIP RETURN
	PJRST	DECDID		;NO, INSERT IT AND THEN SKIP RETURN
;ROUTINE TO INCREMENT HIGH SEG IN CORE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG WHICH MUST BE IN CORE
;CALL:	MOVE J,XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
;	MOVE T1,JOB NUMBER
;	PUSHJ P,INCCNT
;	ALWAYS RETURN WITH C(J)=JBTSGN(T1)
;CORCNT IS SET TO 1 TO FLAG THIS JOB AS HAVING INCREMENTED IN CORE COUNT
;CALLED FROM SHARES(GET,REMAP,CORE) AND FININ


INCCNT:	PUSH	P,T2		;SAVE T2
	TLON	J,CORCNT	;HAS HIGH SEG IN CORE COUNT ALREADY BEEN
	AOS	JBTSTS##(J)	; INCREMENTED FOR THIS JOB?
				;NO, INCREMENT HIGH SEG IN CORE COUNT
	PUSHJ	P,COMIT		;COMPARE J WITH JBTSGN(T1)
	PUSHJ	P,SETSGN
	  MOVEM	J,.HBSGN(T2)	;STORE CORCNT FLAG FOR THIS JOB
	POP	P,T2		;RESTORE T2
	PJRST	DLDISQ		; NOT DORMANT/IDLE NOW


;ROUTINE TO DECREMENT HIGH SEG IN CORE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG WHICH MUST BE IN CORE
;CALL:	MOVE J XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
;	MOVE T1, JOB NUMBER
;	PUSHJ P,DECCNT
;	RET1 IN CORE COUNT NOT YET 0 OR IN-CORE COUNT NOT UP FOR THIS JOB
;	RET2 IN CORE COUNT WENT TO 0
;CALLED FROM KILHGH,FORHGH,FINOT


DECCNT::PUSH	P,T2		;SAVE T2
	PUSHJ	P,COMIT		;COMPARE J WITH JBTSGN(T1)
DECCN1:	TLZN	J,CORCNT	;HAS HIGH SEG IN CORE COUNT ALREADY BEEN
				;DECREMENTED FOR THIS JOB?
	JRST	T2POPJ##	;YES, RESTORE T2 AND RETURN
	SOS	JBTSTS##(J)	;NO, DECREMENT HIGH SEG IN CORE COUNT
	PUSHJ	P,SETSGN
	  MOVEM	J,.HBSGN(T2)	;CLEAR CORCNT FLAG IN MEMORY FOR THIS JOB
	POP	P,T2
DECERR:	LDB	T1,JBYICC##	;GET HIGH SEG IN CORE COUNT
	TRCN	T1,ICCMSK	;IN CORE COUNT EQUAL ZERO?
	JRST	DECDID		; YES. MARK DORMANT/IDLE AND SKIP RETURN
	TRCE	T1,ICCMSK	;GO NEGATIVE?
	POPJ	P,		;NO
	AOS	JBTSTS##(J)	;NO, ERROR ADD BACK TO 0
	STOPCD	DECERR,DEBUG,ICN,	;++INCORE COUNT NEGATIVE

DECDID:	PUSHJ	P,INDISQ	; INSERT IN QUEUE AND SET TIME
	SETZ	T1,		;CLEAR COUNT
	PJRST	CPOPJ1##	; AND SKIP RETURN
	;SUBROUTINES TO MAINTAIN QUEUE OF DORMANT/IDLE SEGMENTS

; INSERT SEGMENT IN QUEUE
INDISQ:	SKIPE	JBTDIQ##(J)	; IS SEGMENT IN QUEUE?
	PUSHJ	P,DLDISQ	; YES. REMOVE BEFORE REINSERTING
;	SKIPN	JBTADR##(J)	; IN CORE?
;	 POPJ	P,		; NO. LEAVE OUT OF QUEUE
	PUSH	P,T1		; SAVE SPACE TO WORK
	MOVSI	T1,SHRSEG	; ONLY SHAREABLE SEGS CAN BE
	TDNN	T1,JBTSTS##(J)	; IDLE/DORMANT
	JRST	TPOPJ##		; SO DON'T PUT THIS ONE IN QUEUE
	MOVNI	T1,DISQ##	; QUEUE HEADER
	HLL	T1,JBTDIQ##(T1)	; OLD LAST IS OUR PREDECESSOR
	MOVEM	T1,JBTDIQ##(J)	; POINT US TO LAST,,HEAD
	HRLM	J,JBTDIQ##(T1)	; POINT HEADER AT US
	MOVS	T1,T1		; SWAP
	HRRM	J,JBTDIQ##(T1)	; POINT OLD LAST AT US
	MOVE	T1,SYSUPT##	; RECORD THE TIME
	MOVEM	T1,JBTIDT##(J)	; SEGMENT WENT IDLE/DORMANT
	PJRST	TPOPJ##		; AND RETURN

;DELETE SEGMENT FROM QUEUE
DLDISQ:	PUSHJ	P,SSEC0##	;DO THIS IN S0
	PUSH	P,T1		; SAVE SPACE TO WORK
	SKIPN	T1,JBTDIQ##(J)	; IN QUEUE?
	PJRST	TPOPJ##		; NO!!
	SETZM	JBTDIQ##(J)	; CLEAR OUR ENTRY
	HLLM	T1,JBTDIQ##(T1)	; POINT SUCCESSOR BACK AT US
	MOVS	T1,T1		; SWAP
	HLRM	T1,JBTDIQ##(T1)	; POINT PREDECCESSOR TO US
	PJRST	TPOPJ##		;
	
;ROUTINE TO COMPARE RH OF J WITH JBTSGN(T1)
;BEFORE STORES INTO JBTSGN(T1)
;WHERE T1 CONTAINS JOB NUMBER AND J IS HIGH SEG NUMBER
;USED FOR DEBUGGING.  MONITOR CANNOT RUN VERY LONG IF THIS ERROR GOES UNDETECTED
;T2 RETURNED CONTAINING HIGH SEG DATA BLOCK ADDR

COMIT:	PUSHJ	P,LGLPRC##	;MAKE SURE T1 IS A JOB NUMBER
	  STOPCD .,STOP,POR,	;++PROCESS OUT OF RANGE
	EXCH	T1,J		;FOR FNDHSB
	PUSH	P,T1		;SAVE SEGMENT DATA
	PUSHJ	P,FNDHSB	;FIND SEGMENT DATA BLOCK
	  STOPCD .,STOP,BSN,	;++BAD SEGMENT NO.
	MOVE	T2,T1		;SET SEGMENT DATA BLOCK ADDR
	POP	P,T1		;RESTORE SEGMENT DATA
	EXCH	T1,J		;BACK THE WAY IT WAS
	POPJ	P,
	JRST	TPOPJ##		;RESTORE T1 AND RETURN

	
;ROUTINE TO CHANGE RELOC INFO IF SEG JUST ASSIGNED IS A HIGH SEG
;WHICH THE CURRENT USER MAY BE USING
;CALL:	MOVE J,LOW OR HIGH SEG FOR WHICH CORE WAS JUST ASSIGNED(OR RETURNED)
;	PUSHJ P,CURHGH
;	ALSWAYS RETURN WITH J PRESERVED
;	R RESET TO RELOC FOR HIGH SEG IF J IS HIGH SEG, OTHERWISE R AND
;		J UNCHANGED


CURHGH::
	SE1ENT			;MUST BE IN SECTION 1
	PUSH	P,J		;SAVE J
	HRRZS	J		;CLEAR JUNK
	SKIPN	R		;IF SEGMENT HAS NO MORE CORE,
	PUSHJ	P,RTNHMP	;RETURN MAP
	MOVE	T1,(P)		;SEGMENT # IN QUESTION
	MOVE	J,.CPJOB##	;JOB
	PUSHJ	P,FNDHSB	;THIS SEGMENT EXIST FOR CURRENT JOB?
	  JRST	JPOPJ##		;RETURN
				;(CHANGE IF SEGMENT AFFECTED IS FOR CURRENT JOB)
	MOVSI	T2,REDOMP	;FORCE MAP TO BE REDONE FOR THIS SEG
	IORM	T2,.HBSGN(T1)
	PUSHJ	P,MAPHGX##	;SET HARD. AND SOFT. RELOC INFO FOR CURRENT JOB
				; (EVEN THOUGH THIS CALL TO CURHGH MAY BE FOR SOME
				; OTHER JOB) SONCE HIGH SEG MAY BE IN NEW PLACE IN CORE
	HRRZ	J,(P)		;HIGH SEG #
	MOVE	R,JBTADR##(J)	;RESTORE HIGH RELOCATION
	JRST	JPOPJ##		;RESTORE J AND RETURN
	
;ROUTINE TO SEE IF SUM OF BOTH SEGMENTS WILL FIT INTO MAXIMUM SIZE
;OF PHYSICAL CORE TOGETHER
;CALL:	MOVE T1,REQUESTED LENGTH-1 OF SEG BEING ASSIGNED(LOW OR HIGH)
;		T1 IS ASSUMED TO HAVE 1777 ORED IN BEFORE CALL
;	MOVE J,JOB OR HIGH SEG NUMBER
;	PUSHJ P,SUMSEG
;	ERROR RETURN, CAN NEVER FIT
;	OK RETURN
;PREVIOUS CONTENTS OF T1 AND J PRESERVED ON BOTH RETURNS
;IF HIGH SEG, MUST BY CALLED AT UUO LEVEL, IF T1 NON-ZERO
;OK TO CALL FOR HIGH SEG AT CLOCK LEVEL, PROVIDED ASKING FOR 0 ONLY.
;SHUFFLER MODIFIED  SO IT NEVER CALLS SUMSEG(SINCE IT MIGHT SHUFFLE 
;HIGH SEGMENT AT CLOCK LEVEL WHICH IS NOT THE CURRENT USERS)
;THIS WILL BE TRUE AS LONG AS A CORE COMMAND IS NOT IMPLEMENTED WHICH
;ALLOWS USER TO ADJUST HIGH SEG TO ANYTHING BUT 0.
;CALLED FROM CORE UUO(CORE0 AND CORE1 ROUTINES)


SUMSEG::JUMPE	T1,CPOPJ1##	;ASKING FOR 0 CORE(IF YES, COULD BE
				;HIGH SEG AT CLOCK LEVEL)? HAVE NO IDEA WHAT LOW
				; SEG NO. IS HOWEVER, 0 ALWAYS WILL FIT
	PUSH	P,T1		;SAVE USER ARG FOR NO. WORDS -1 FOR A SEG
	PUSH	P,J		;SAVE LOW OR HIGH SEGMENT NUMBER
	CAIG	J,JOBMAX##	;REQUEST IN TERMS OF SOME HIGH SEG?
	TDZA	T2,T2		;NO, ARG GIVEN (T1) WAS LOW SEG SIZE
	SKIPA	J,.CPJOB##	;ARG WAS SOME HIGH SEG, ASSUME UUO LEVEL
	JRST	SUM0		;ARG WAS LOW SEG
	MOVE	J,.CPJOB##	;ASSUME UUO LEVEL AGAIN
	PUSHJ	P,SEGSIZ##	;GET SIZE OF LOW SEG
	SUBI	T2,UPMPSZ##	;SUBTRACT OUT SIZE OF UPT
SUM0:	PUSH	P,T2		;ADD TO ARG GIVEN
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;START OF JOB'S SEGMENT DATA CHAIN
SUM1:	SKIPN	T1,.HBLNK(T1)	;GET NEXT SEGMENT
	JRST	SUM2		;NO MORE
	HRRZ	J,.HBSGN(T1)	;GET SEGMENT WORD
	SKIPLE	.HBSGN(T1)	;SKIP SPY SEGS
	CAMN	J,-1(P)		;AND SPECIFIED SEGMENT
	JRST	SUM1
	PUSHJ	P,SEGSIZ##	;GET SIZE OF THIS SEGMENT
	ADDM	T2,(P)		;PUT INTO THE SUMMATION
	JRST	SUM1		;PROCEED TO NEXT SEGMENT

SUM2:	POP	P,T2		;FINAL SUMATION
	ASH	T2,P2WLSH	;CONVERT FROM PAGES TO WORDS
	ADD	T2,-1(P)	;DESIRED SIZE=OTHER SEG SIZE (WORDS)+
				; REQUEST (ORED 1777) SIZE-1 (OR 0)
	MOVE	J,(P)		;GET ARG AGAIN
	CAILE	J,JOBMAX##	;JOB?
	MOVE	J,.CPJOB##	;NO, ASSUME UUO LEVEL AGAIN
	PUSHJ	P,CORBND##	;GET LIMIT
	POP	P,J		;RESTORE REQUESTING SEG NO
	CAMLE	T2,T1		;IS DESIRED (LENGTH-1)+OTHER LENGTH .LE. JOB UPPER BOUND?
	JRST	TPOPJ##		;NO, ERROR
	JRST	TPOPJ1##	;YES, OK RETURN

	
;ROUTINE TO COMPARE CORTAL(FREE+DORMANT+IDLE CORE) WITH CORTAB(USE BIT TABLE)
;AND HALT IF INCONSISTENT.
;CALL:	PUSHJ P,CHKTAL	-AFTER CORTAL ADJUSTED
;	RETURN ONLY IF OK-ALL ACS SAVED


CHKTAL::
IFE FTMP,<
	SOSLE	CHKCNT##	;CHECK ON THIS CALL?
				; MONGEN DEFAULT MD.CHK==^D32
	POPJ	P,		;NO, AVOID OVERHEAD (5 M:S.) MOST OF TIME
>
IFN FTMP,<
	SOSG	CHKCNT##	;BEEN HERE M.CMCT TIMES?
	PUSHJ	P,MMOWN##	;YES, OWN THE MM RESOURCE?
	  POPJ	P,		;NO, CAN'T DO THIS NOW
>
	SE1ENT			;PAGTAB IS IN A NON-ZERO SECTION
	PUSH	P,T1		;YES, SAVE ALL ACS USED
	MOVEI	T1,M.CMCT##	;CHECK MONITOR CORE MEMORY EVERY M.CMCT CALL
	MOVEM	T1,CHKCNT##	;SO REDUCE MONITOR CPU OVERHEAD
	PUSH	P,J
	PUSH	P,U
	MOVEI	U,0		;SET FREE+DORMANT+IDLE COUNT TO 0
	MOVEI	J,PAGTAB	;START AT BEGINNING
	SSX	J,MS.MEM	;SET SECTION NUMBER
CHKT1:	SKIPGE	(J)		;SKIP IF PAGE IS IN USE
	ADDI	U,1		;NO, ADD 1 TO FREE COUNT
	CAME	J,CORLST##	;FINISHED PAGTAB?
	AOJA	J,CHKT1		;NO,
	MOVE	J,SEGPTR##	;YES, SCAN ALL HIGH SEGMENTS
CHKT2:
REPEAT 1,<			;
	MOVE	T1,JBTSTS##(J)	;
	TLNN	T1,SHRSEG	; SHARABLE?
	JRST	CHKT2A		; NO. JBTADR LIES. SHOULD NEVER BE IN QUEUE
	TRNN	T1,ICCMSK	;
	SKIPN	JBTADR(J)	;
	JRST	CHKT2A		;
	SKIPN	JBTDIQ##(J)	;
	AOS	WRQONE		; OOPS
	JRST	CHKT2B		;
CHKT2A:	SKIPE	JBTDIQ##(J)	;
	AOS	WRQTWO		;
CHKT2B:				;
	$LOW			;
WRQONE:	0			;
WRQTWO:	0			;
	$HIGH			;
>				;
	PUSHJ	P,CHKLKH	;CHECK FOR DORMANT OR IDLE (UNLOCKED)
	  JRST	CHKT3		;NO
	LDB	T1,IMGIN##	;SEGMENT SIZE
	ADD	U,T1		;ADD IT TO TOTAL FREE
CHKT3:	AOBJN	J,CHKT2		;SCANNED ALL HIGH SEGS?
	SUB	U,LOKTAL##	;ACCOUNT FOR PAGES LOKCON IS WAITING FOR
	CAME	U,CORTAL##	;YES, IS FREE+DORMANT+IDLE = BIT TABLE
	STOPCD	.+1,INFO,CMU,	;++CORE MESSED UP
	MOVEM	U,CORTAL##	;FIX CORTAL AND ATTEMPT TO CONTINUE
	POP	P,U		;YES, RESTORE ACS AND RETURN
	POP	P,J
	JRST	TPOPJ##		;RETORE T1 AND RETURN


	
SUBTTL ERRCON - MONITOR DETECTED ERROR ROUTINES

;ILLEGAL MEMORY(ILM) DETERMINE IF WILD TRANSFER OR NOT
;CALL:	HRRZ T1,USER PC
;	PUSHJ P,SEGILM
;	LEGAL PC RETURN(MUST BE ILLEGAL REF)
;	ILLEGAL PC RETURN(MUST BE WILD TRANSFER)


SEGILM::MOVE	T3,T1		;SAVE THE PC
	PUSHJ	P,HSVAD		;GET STARTING AND HIGHEST LEGAL
				; HIGH SEGMENT ADDRESSES
	CAIL	T3,(T2)		;ABOVE THE START OF THE HIGH SEG?
	CAILE	T3,(T1)		;AND BELOW THE TOP OF HIGH SEG?
	AOS	(P)		;NO, ILLEGAL PC RETURN
	POPJ	P,		;YES, PC IN HIGH SEG(MUST BE ILLEGAL REF)

;SUBROUTINE TO PRINT "SWAP OUT CHN MEM PAR ERR" ON ALL JOBS USING HIGH SEG
; CLEAR NAME SO NO NEW USERS WILL GET
;CALL:	MOVE J,LOW OR HIGH SEG NO WHICH HAD MEM PAR ERR ON SWAP OUT
;	PUSHJ P,HGHSWE
;	  HERE IF HIGH SEG
;	SKIP RET IF LOW SEG

HGHSWE::CAIG	J,JOBMAX##	;IS THIS A HIGH SEG?
	JRST	CPOPJ1##	;NO, SKIP RETURN
	PUSHJ	P,CLRNAM	;CLEAR HIGH SEG NAME SO NO NEW USERS WILL GET
	XMOVEI	T1,SWOMES##	;ADR OF SUB IN ERRCON WHICH PRINTS
				; SWAP OUT MEM PAR ERR
	PJRST	HGHAPP		;GO APPLY IT TO ALL JOBS USING HIGH SEG
;SUBROUTINE TO HANDLE SPURIOUS PARITY ERROR (MAYBE READ PAUSE WRITE)
;BLAME ALL JOBS SHARING HIGH SEG OF CURRENT JOB IF NO DISK COPY
;ELSE JUST SWAY OTHERS OUT
;CALL:	MOVE	J,CURRENT JOB NO.
;	PUSHJ	P,HGHSPE
;	ALWAYS RETURN - J - PRESERVED

HGHSPE::PUSHJ	P,SAVE1##	;GET SOME ACS
	PUSH	P,J		;SAVE CURRENT JOB NO.
	MOVEI	P1,JBTSGN##-.HBLNK(J) ;INIT POINTER
HGHSP1:	SKIPN	P1,.HBLNK(P1)	;NEXT HIGH SEG JOB OWNS
	JRST	JPOPJ##		;NO MORE
	SKIPLE	J,.HBSGN(P1)	;SEGMENT SORD
	PUSHJ	P,HGHPAR	;REAL SEGMENT, CALL HGHPAR FOR IT
	JRST	HGHSP1		;LOOP BACK FOR MORE

;SUBROUTINE TO HANDLE MEM PARITY IN A HIGH SEG
;CAUSE ALL JOBS TO BE SWAPPED OUT (SO GOOD DISK COPY GET USED IF ONE)
;IF HIGH SEG DOES NOT HAVE COPY SWAPPED OUT, ALL JOBS GET ERROR MESSAGE
;CALL:	MOVE	J, HIGH SEG NUMBER
;	PUSHJ	P,HGHPAR
;	ALWAYS RETURN

HGHPAR::XMOVEI	T1,HGHPR1	;APPLY SUB TO SWAP OUT ALL JOBS USING HIGH SEG
				; UNLESS LOCKED OR NO DISK COPY
	LDB	T2,IMGOUT##	;ALLOCATION DISK
	PJUMPN	T2,HGHAPP	;IF A COPY THERE, JUST SWAP OUT ALL JOBS USING IT
				; GIVE ERROR MESSAGES TO LOCKED JOBS
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET MM RESOURCE AT CLOCK LEVEL
	  JRST	.-1		;MUST HAVE IT BEFORE PROCEDING
>
	PUSHJ	P,CLRNAM	;CLEAR SEGNAME SO NO ONE NEW WILL USE
				; (RETURN DISK AND CORE SPACE IF DORMANT)
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN MM RESOURCE
>
	MOVEI	T1,PARJB1##	;SUB TO FLAG JOB TO GET MESSAGE AND STOP
				;FALL INTO SUB TO APPLY PARJOB TO ALL JOBS
;ROUTINE TO APPLY A SUB TO EACH JOB WITH THIS HIGH SEG
;CALL:	MOVEI T1,ADR OF SUB. TO BE APPLIED
;	TLO  T1,(1B0)		;IF SUBR SHOULD NOT BE CALLED FOR CURRENT JOB
;	MOVE J,HIGH SEG NUMBER
;	PUSHJ P,HGHAPP
;	ALWAYS RETURN -J MEANINGFULLY CLOBBERED
;SUBROUTINE IS CALLED WITH P2 CONTAINING THE HIGH SEG DATA BLOCK FOR
;THE JOB OWNING THE HIGH SEG AND J CONTAINING THE JOB #
;NOTE THAT FOR SUBRS NOT CALLED FOR CURRENT JOB, THE FLAG FORCES
;THE ROUTINE TO BE CALLED AS AN IFIW IN THE SECTION OF THE CALLER
;IF A SUBROUTINE WISHES TO STOP THE SCAN PREMATURELY, THEN IT
;SHOULD ZERO J.  THIS WILL CAUSE HGHAPP TO EXIT WITH A NEGATIVE VALUE
;IN J WHICH WILL TELL THE CALLER OF HGHAPP THAT THE SCAN WAS PREMATURELY
;ABORTED.  J WILL BE ZERO IF THE SCAN SUCCESSFULLY COMPLETED.

HGHAPP::PUSHJ	P,SAVE2##	;SAVE P1
	PUSH	P,T1		;PUT SUB ADR ON STACK
	HRRZ	P1,J		;REMEMBER BAD HIGH SEG
	MOVE	J,HIGHJB##	;SCAN ALL JOBS FROM HIGHEST DOWN
;LOOP TO SCAN FOR ALL JOBS USING BAD HIGH SEG
HGHPLP:	SKIPGE	(P)		;CALL ON .CPJOB?
	CAME	J,.CPJOB##	;NO, IS THAT THIS JOB?
	SKIPA	T1,P1		;LOAD HIGH SEG #
	JRST	HGHLP1
	PUSHJ	P,FNDHSB	;FIND THAT HIGH SEG
	  JRST	HGHLP1		;NOT FOUND FOR THIS JOB
	MOVE	P2,T1		;P2 HAS THE HSB ADDR
	PUSHJ	P,@(P)		;YES, CALL SUB AS SPECIFIED BY CALLER
HGHLP1:	SOJG	J,HGHPLP	;NO, RUN OUT OF JOBS?
	JRST	TPOPJ##		;DONE

;SUBROUTINE TO CHECK IF A JOB IS LOCKED (LOW OR HIGH SEG)
; OR IF HIGH SEG HAS NO DISK COPY - SET ERROR BIT TO STOP JOB
;ALWAYS SWAP JOB (LOW & HIGH SEG) OUT (UNLESS LOCKED)
; TO TRY TO FIX ERROR IF HIGH SEG HAS DISK COPY
;CALL:	MOVE J,JOB NO.
;	PUSHJ P,HGHPR1
;	ALWAYS RETURN

HGHPR1:
IFN FTLOCK,<			;LOCK UUO FEATURE?
	PUSHJ	P,LOKCHK##	;IS THIS JOB'S LOW OR HI SEG LOCKED?
	  PJRST	PARJB1##	;YES, STOP JOB GIVE ERROR MESSAGE
>
	PJRST	XPANDH##	;NO, SWAP HIM OUT AND ALL OTHER JOBS
				; IF THIS IS A HIGH SEG.
	
SUBTTL	SAVGET - SAVE, GET, R, AND RUN COMMANDS

;THE LOWER CORE LOCATION 0-17 IN USER AREA ARE USED FOR TEMP STORAGE FOR SAVE-GET
;THEY ARE DEFINED IN BEGINNING OF SAVGET ROUTINE


;ROUTINE TO SET EXTENSION OF HIGH SEG
;SAME CALL AS SETEXT EXCEPT S NOT SETUP
;CALLED FROM GETARG(RUN, GET SEG UUO)


SETEX1::TLZ	S,NSRBIT	;TRY SHARABLE SEG FIRST(.SHR) THEN .HGH
				;FALL INTO SETEXT

;ROUTINE TO SET EXTENSION OF HIGH SEGMENT TO SHR(SSAVE,GET,R) OR HGH(SAVE)
;CALL:	HRLI S,0(GET,SSAVE,RUN) OR NSRBIT(SAVE)
;	MOVE R,XWD PROTECT,RELOC FOR LOW SEG
;	MOVEI T2, LOW FILE EXTENSION OR 0 IF NONE TYPED IN
;	PUSHJ P,SETEXT
;	RETURN T1 PRESERVED(TTY INPUT BYTE POINTER)
;	CALLED FROM COMMAND DECODER ROUTINE SGSET, T1 PRESERVED (INPUT BYTE POINTER)


SETEXT::HRLZM	T2,.JDAT+SGALOW##	;SAVE EXTENSION USER TYPED FOR LOW SEG
	MOVE	T2,[SIXBIT /SHRHGH/]	;ASSUME SSAVE COMMAND(OR  GET)
	TLNE	S,NSRBIT	;WAS IT?
	MOVSS	T2		;NO, EXCHANGE ROLES OF EXTENSIONS, MUST
				; BY SAVE
	MOVEM	T2,.JDAT+SGAHGH##	;SAVE FOR ENTER AND RENAME OF HIGH SEGMENT
	POPJ	P,

;SUBROUTINE TO SETUP JOBHRL
;CALL:	MOVE	J,HI SEG NUMBER
;	PUSHJ	P,SETHRL
SETHRL::HLRZ	T2,JBTADR##(J)	;LENGTH-1 OF HIGH SEG
	ADDI	T2,1		;LENGTH
	HLRZ	T1,.JDAT+JOBHRL##  ;RELATIVE FIRST FREE LOC IN HIGH SEG (SET BY LOADER)
	JUMPE	T1,SETHR1	;GO FILL IT IN IF ZERO
	CAMG	T1,T2		;SIZE OKAY?
	SKIPE	USRDDT##	;YES, IS USER USING DDT
SETHR1:	HRLM	T2,.JDAT+JOBHRL##  ;YES, SET FIRST FREE TO BE FIRST WORD BEYOND END
	POPJ	P,		;RETURN
	
;ROUTINE TO SAVE HIGH SEG IF IT EXISTS (AS.SHR(SSAVE) OR .HGH(SAVE))
;AND DETERMINE IF LOW SEG HAS DATA TO BE SAVED, OR NOT(IF YES IT WILL BE WRITTEN
;AS LOW UNLESS USER SPECIFIED DIFFERENTLY RATHER THAN.SAV)
;ALWAYS SAVE LOW SEG IF MAGTAPE OR IF NO HIGH SEG
;CALL:	MOVE J, JOB NUMBER (R,R,F SET UP)
;	PUSHJ P,SAVHGH
;	RETURN1 NO DATA IN LOW SEGMENT
;	RETURN2 SAVE LOW SEGMENT
;	J DESTROYED,SGAEXT RESTORED TO SAV OR USERS TYPED EXTENSION
;	SGALLEN RESTORED TO IOWD FOR LOW SEG IF DTA,PROJ R IF DSK
;	DEVICE INITED ON EITHER RETURN

SAVHGH::SKIPN	T1,JBTSGN##(J)	;ANY HIGH SEGS?
	JRST	SAVLOW		;NO,, RESTORE SGAEXT,SGALEN AND SKIP
				;RETURN SO LOW SEG WILL BE SAVED
				; USER HAS NO CHOICE(MAY BE HAD SPY SEG
	SKIPN	.HBLNK(T1)	;MORE THAN ONE HIGH SEG?
	JRST	[MOVEI T1,DPSERR ;CAN'T DO THIS WITH .HGH FILES (EACH ONE
		 HRRM  T1,.JDAT+SGAEXT## ;WOULD OVERWRITE THE OTHER)
		 JRST  SAVERR##]
	SKIPG	J,.HBSGN(T1)	;DON'T WORRY ABOUT SPY SEGS
	JRST	SAVLOW
	PUSHJ	P,SGH		;SET EXTENSION IN E+1 OF ENTER BLOCK
	PUSHJ	P,SETHRL	;SETUP JOBHRL
	HLRZ	T1,.JDAT+JOBHRL##	;GET CORRECT FIRST REL FREE LOC IN HIGH SEG
	MOVNS	T1		;SET RH=-NO. OF WORDS TO WRITE, LH=-1
	PUSHJ	P,SG4##		;SETUP E+3
	PUSH	P,.JDAT+JOBVER##	;SAVE LOWSEG VERSION
	SKIPE	T1,.VJDT+JOBHVR## ;HISEG VERSION NUMBER
	MOVEM	T1,.JDAT+JOBVER##	;STORE FOR FILSER
	MOVNI	T1,4		;INDICATE HIGH SEGMENT SAVE IN PROGRESS
	HRLM	T1,USRHCU##	;SET LH OF HIGEST CHANNEL USED AS A FLAGE THAT
				; A SAVE IS IN PROGRESS FOR HIGH SEG
	ENTER	0,SGANAM##	;ENTER NAME IN DIRECTORY(SHR OR HGH)
	JRST	[POP P,.JDAT+JOBVER##	;RESTORE LOWSEG VERSION
		JRST SAVERR##]	;  PRINT ERROR MESSAGE
	POP	P,.JDAT+JOBVER##	;RESTORE VERSION
	PUSHJ	P,COPVJD	;COPY LOW SEGMENT JOB DATA AREA NUMBERS TO
				; VESTIGUAL JOBDAT
	PUSHJ	P,OUTHGH
	PUSHJ	P,SGIOCK##	;CHECK FOR TRANSMISSION ERRORS(RETURN IF OK)
	CLOSE	0,		;CLOSE OUTPUT(BEFORE LOOKUP FOR DELETE)
				; SO SHARABLE SEG WILL BE SUPERCEDE BY NEW FILE
				; IF SAME NAME
	HRLZ	T1,.JDAT+SGAHGH## ;DELETE HGH IF SHR WRITTEN OR VICE VERSA
	PUSHJ	P,DELET		;DEPENDING IF THIS WAS A SSAVE OR SAVE COM.
	MOVSI	T1,'SAV'	;DELETE OLD .SAV
	PUSHJ	P,DELET		; FILE, IF ANY.
	SETZ	T3,		;SET FLAG THAT WE CAME FROM "SAVE"
	PUSHJ	P,LOWCHK	;CHANGE EXTENSION FOR LOW FILE TO .LOW
				; UNLESS USER SUPPLIED HIS OWN ARG
	  JRST	.+2		;DO NOT NEED LOW FILE WRITTEN
				; SO DELETE POSSIBLE PREVIOUS VERSION
				; SO USER WILL NOT BE CONFUSED
	JRST	CPOPJ1##	;LOW FILE NEEDED, DO NOT BOTHER TO DELETE
				; GIVE SKIP RETURN TO CALLER
	MOVE	T1,DEVMOD(F)
	TLNE	T1,DVMTA	;DEVICE A MAGTAPE?
	PUSHJ	P,SAVNUL	;YES, WRITE A NULL LOW SEGMENT.
	SKIPN	T1,.JDAT+SGALOW## ;OBTAIN LOW SEGMENT NAME
	MOVSI	T1,(SIXBIT /LOW/) ;FILL IN DEFAULT IF NULL
	JRST	DELET		;DELETE FILE AND GIVE NO SKIP RETURN TO CALLER

SAVNUL:	HRROS	USRHCU##	;SET SAVE IN PROGRESS FLAG
	MOVNI	T1,JOBHRN##+1	;NEGATIVE SIZE OF RECORD TO OUTPUT
	HRLI	T1,JOBNSV##-1	;ADDRESS IN JOBDAT TO WRITE OUT NULL SAVE FILE
	MOVSM	T1,.JDAT+SGALEN## ;SET UP OUTPUT IOWD
	SETZM	.JDAT+JOBHRN##+JOBNSV##	;CLEAR WORD TO INDICATE NULL FILE.
	OUTPUT	0,SGALEN##	;WRITE THE NULL SEGMENT
	HRRZS	USRHCU##	;CLEAR SAVE IN PROGRESS FLAG
	PUSHJ	P,SGIOCK##	;CHECK FOR ERRORS (RETURN IF OK)
	CLOSE	0,		;WRITE EOF
	POPJ	P,
;SUBROUTINE TO SETUP THE VESTIGUAL JOB DATA AREA FROM THE JOB DATA
; AREA ON A SAVE IF NECESSARY
;CALLING SEQUENCE:
;	MOVE	J,SEGMENT # IN QUESTION
;	PUSHJ	P,COPVJD
;ALWAYS RETURNS CPOPJ

COPVJD::MOVE	T1,.CPJOB##	;GET CURRENT JOB
	EXCH	T1,J		;SEGMENT # TO T1, JOB # TO J
	PUSHJ	P,FNDHSB	;GET HIGH SEG DATA BLOCK
	  SKIPA	J,T1		;HUH?
	SKIPLE	J,.HBSGN(T1)	;GET SEGMENT NUMBER FROM HIGH SEG BLOCK
	TLNE	J,SHRSEG	;IS HIGH SEG SHARABLE?
	POPJ	P,		;YES, DO NOT INITIALIZE VESTIGIAL JOB DATA AREA
				; SINCE IT MUST HAVE BEEN DONE WHEN HIGH FILE CREATED
				;  AND USER CANNOT MODIFY NOW
	PUSH	P,T1		;SAVE ADDRESS OF HIGH SEGMENT BLOCK
	LDB	T1,JBYHSO##	;PAGE WHERE HIGH SEGMENT ORIGINS
	PUSH	P,J		;SAVE J
	PUSHJ	P,YANKIZ##	;MAKE SURE THE PAGE IS IN CORE
	  JRST	[PUSHJ P,CRPAGE## ;ABZ, CREATE THE PAGE
		   JRST NEED1P	;CAN'T
		 JRST .+1]	;CONTINUE
	POP	P,J		;RESTORE SEGMENT #
	POP	P,T1		;RESTORE ADDRESS OF HIGH SEGMENT BLOCK
	PUSHJ	P,MAPVJD	;MAKE SURE VESTIGUAL JOB DATA AREA IS MAPPED
				; IT SHOULD BE ALREADY BUT THEN CASES HAVE
				; BEEN SEEN WHEN IT WASN'T
	MOVE	T1,JBTADR##(J)	;NO, INITIALIZE VESTIGIAL JOB DATA AREA IN HIGH SEG
	SUBI	T1,1		;FROM LOW SEG JOB DATA AREA
	PUSH	T1,.JDAT+JOBSA##;SAVE JOB STARTING ADDRESS (RH)
				; AND INITIAL FIRST FREE LOC (LH)
	PUSH	T1,.JDAT+JOB41##;SAVE USER LOC 41(USER UUO HANDLER JSR)
	PUSH	T1,.JDAT+JOBCOR## ;SAVE USER TYPED THIRD (CORE) ARG (RH) AND
				; HIGHEST DATA LOC LOADED IN LOW SEG (LH
	HRR	T2,.JDAT+JOBREN## ;SAVE REENTER COMMAND STARTING ADDRESS
	HLL	T2,.JDAT+JOBHRL## ;AND FIRST (REL) FREE LOCATION SET BY LOADER
	PUSH	T1,T2
	PUSH	T1,.JDAT+JOBVER## ;SAVE BOTH HALVES OF PROGRAM VERSION NUMBER
				; LH IS USED FOR PROGRAMMER NUMBER LAST MODIFYING
	PUSH	T1,.JDAT+SGANAM## ;SAVE NAME OF SEGMENT FOR DDT
	AOBJN	T1,.+1		;SKIP DDT SYMBOL TABLE POINTER
	PUSH	T1,[EXP 0]	;CLEAR 10 (OCTAL) FOR FUTURE
	LDB	T2,JBYHSO##	;PAGE NUMBER WHERE HIGH SEGMENT ORIGINS
	DPB	T2,[POINT 9,(T1),17]
	POPJ	P,		;RETURN
;SUBROUTINE TO OUTPUT THE HIGH SEGMENT
;CALL:
;	PUSHJ	P,OUTHGH
;	RETURN HERE (I/O ERRORS NOT CHECKED FOR)
;
OUTHGH::HLLZ	T1,.JDAT+JOBHRL##	;GET CORRECT FIRST REL FREE LOC IN HIGH SEG
	MOVNM	T1,.JDAT+SGALEN##	;SET LH=-NO. WORDS TO WRITE, RH=0
				; SET AGAIN SINCE ENTER CHANGED E+3
	LDB	T1,JBYHSO##	;STARTING PAGE OF HIGH SEG
	LSH	T1,P2WLSH	;START ADR
	SUBI	T1,1
	HRRM	T1,.JDAT+SGALEN## ;START ADR OF IOWD
	OUTPUT	0,SGALEN##	;WRITE ALL OF ORIGINAL HIGH SEG
	MOVE	J,.CPJOB##	;RESTORE JOB NUMBER OF CURRENT JOB
	HRRZS	USRHCU##	;NOW CLEAR SAVE IN PROGRESS FLAG
	POPJ	P,		;RETURN
;UUO TO GET JUST HIGH SEGMENT, USER CHANNELS 1 THRU 17 UNTOUCHED
;CALL:	MOVEI AC,D	;WHERE D IS LOCATION OF 5 ARG(SEE RUN UUO)
;			;THE 6TH(CORE ARG IS IGNORED) BUT MUST BE IN LEGAL MEMORY
;	CALL AC,[SIXBIT /GETSEG/] OR CALLI AC,40
;	ERROR RETURN UNLESS LH=HALT
;	OK RETURN


UGETHI::PUSHJ	P,SAVE1##	;SAVE P1
	PUSHJ	P,GETARG##	;YES,GET 6 ARGS FROM USER
	SKIPN	T1,.JDAT+SGANEW## ;EXTENDED ARGUMENT SPECIFIED?
	JRST	UGETH1		;NO, SO DON'T CHECK ITS LEGALITY
	JUMPG	T1,UGETH0	;INVALID CORE ARG POINTER IF POSITIVE
				; (1022 IS KNOWN TO LEAVE A SMALL
				;  POSITIVE INTEGER HERE)
	HLRE	T1,T1		;GET LENGTH OF ARGUMENT LIST
	AOJE	T1,UGETH1	;MUST BE EXACTLY 1 WORD
				; (ALGOL IS KNOWN TO LEAVE SIXBIT/DSK/,
				;  I.E., A LARGE NEGATIVE NUMBER)
UGETH0:	SETZM	.JDAT+SGANEW##	;MAKE OLD .EXE FILES WORK - IGNORE GARBAGE
UGETH1:	PUSHJ	P,UGTSSL##	;GET EXTENDED CORE/SECTION ARG
	MOVSI	T1,GTHGH##	;JUST GET THE HIGH SEG
SGETHI::MOVEI	T2,JS.XOR	;CLEAR EXECUTE STATUS
	ANDCAM	T2,JBTSTS##(J)
	MOVSI	T2,(JS.IGS)	;INDICATE IN GETSEG
	IORM	T2,JBTST2##(J)
	PUSHJ	P,GETSEG	;TRY TO SHARE HIGH SEG OR READ IN HIGH FILE
	  JRST	[MOVSI T1,(JS.IGS)
	         ANDCAM T1,JBTST2##(J)
     	         JRST NOFILE##]
;NO FILE FOUND, PRINT MESSAGE OR ERROR RETURN
	  JFCL			;HIGH FILE IN, EVERYTHING OK
	PUSHJ	P,CHKMED	;CHECK TO SEE IF THIS IS SHARABLE SEG(EXT=SHR)
				; IF YES, SET MEDDLE BIT FOR THIS USER
				; SO HE CANNOT TURN OFF UWP OR CHANGE CORE ASSIGNMENT
	MOVSI	T1,(JS.IGS)
	ANDCAM	T1,JBTST2##(J)	;CLEAR "IN GETSEG"
	MOVSI	T1,(UP.GET)
	ANDCAM	T1,.USBTS	;GET NO LONGER IN PROGRESS
	PUSHJ	P,VERWAT##	;SEE IF WATCHING
	  JRST	GETHI1		;NO--RETURN
	PUSH	P,P2		;SAVE P2
	SETO	P2,		;NOT VERSION COMMAND BUT CALL PGMFIL
	PUSHJ	P,VERHGH##	;YES - PRINT HIGH VERSION
	POP	P,P2
	PUSHJ	P,PRRBKC##	;PRINT RIGHT BRACKET <CRLF>
GETHI1:	PUSHJ	P,SGREL##	;RELEASE JUST CHANNEL 0 IF WAS INIT
	JRST	TPOPJ1##	;OK(SKIP RETURN TO USER AFTER REMOVING USER ARG+AC
				;FROM PD LIST WHICH GETARG PUT ON
;ROUTINE TO ADD CURRENT USER TO A SHARED SEGMENT IF IT EXISTS OR
;TRY TO INITIALIZE A HIGH SEGMENT FROM A FILE AND MAKE IT SHARABLE(-SHR) OR NOT(.HGH)
;DEPENDING ON THE EXTENSION OF THE FILE
;CALL:	MOVE J, CURRENT JOB NUMBER
;	ACS F,R,R,P,SETUP
;	MOVE T2,DEVMOD(F)
;	PUSHJ P,GETHGH
;	RETURN1-HIGH SEG NOW IN ADDRESSING SPACE AND NO LOW FILE NEED BE GOTTEN
;	RETURN2 - HIGH SEG NOW IN ADDRESSING SPACE, AND LOW FILE NEEDED
;		OR NO HIGH FILES FOUND, TRY LOW FILE
;IFN FTEXE, <RETURNS - BOTH SEGS IN AND READY TO GO>
;	J RESTORED TO CURRENT JOB NUMBER
;	USER MODE FLAG CLEARED IN UUO PD LIST IR RUN UUO FROM HIGH SEG
;	WHICH IS NO LONGER SAME(SO NO ATTEMPT TO ERROR RETURN IF ERROR)



GETHGH::MOVSI	T1,(JS.EXE)	;CLEAR EXE BIT
	ANDCAM	T1,JBTST2##(J)
	MOVSI	T1,GTBTH##	;GET BOTH SEGMENTS
	PUSHJ	P,GETSEG	;YES, TRY TO ATTACH TO HIGH SEG OR READ
				; IN HIGH FILE IF IT EXISTS, HIGH SEG OK?
	  JRST	NOHIGH		;NO, TRY TO READ IN LOW FILE OLD HIGH
				; SEG STILL IN ADR SPACE(IF ANY)
	  SKIPA			;HIGH FILE OK, GO READ LOW FILE
	JRST	CPOPJ2##	;BOTH FILES IN, RETURN TO CALL+3
	MOVSI	T1,.JDAT+JOBUAL##+10 ;ALSO CLEAR DDT STARTING ADDRESS
	HRRI	T1,.JDAT+JOBUAL##+11
	SETZM	-1(T1)		;CLEAR JOB DATA AREA
	BLT	T1,.JDAT+JOBDA##-1 ; IN CASE THERE IS NO LOW FILE
	SETZM	.JDAT+JOBDDT##
	SETZM	USRDDT##	;IN MONITOR PROTECTED AREA AS WELL AS JOBDAT
				; IN CASE RETURN TO USER WITHOUT RESCHEDULING
	PUSHJ	P,ADJCOR	;COMPUTE AMOUNT OF CORE FOR BOTH LO & HI SEGS
				; FROM USER'S CORE ARG.(IF ANY)
				; RETURNS WITH HI SEG # IN T1
	HRRZ	T1,JBTSGN##(J)	;GET SEGEMTN WE JUST GOT
	HRRZ	T1,.HBSGN(T1)	;SEGMENT #
	HRRO	T1,JBTADR##(T1)	;ABSOLUTE ADDRESS OF HIGH SEG(LH=-1 FOR
				; POPS SO NO PDL UNDERFLOW)
	ADDI	T1,JOBPOP##	;ADD POP OFFSET
	POP	T1,.JDAT+JOBVER## ;RESTORE BOTH HALVES OF PROG. VERSION NO.
	POP	T1,T2		;RESTORE
	HLLM	T2,.JDAT+JOBHRL## ;RELATIVE FIRST FREE LOC IN HIGH SEG
	HRRZM	T2,.JDAT+JOBREN## ;PROGRAM REENTER ADR, LH=0
				; SAVED FOR FUTURE USE
	POP	T1,.JDAT+JOBCOR## ;HIGHEST DATA LOC IN LOW SEG(LH)
				; AMOUNT OF CORE IN RH TO BE ASSIGNED(#J-1)
	POP	T1,.JDAT+JOB41## ;USER UUO HANDLER JSR
	POP	T1,.JDAT+JOBSA## ;FIRST FREE LOC IN LOW SEG(LH), START COMMAND
				; STARTING ADDRESS(RH)
				;HERE FROM SAVE TOO
	SETO	T3,		;FLAG THAT THIS IS "GET"
LOWCHK:	PUSHJ	P,LOWSPC	;SEE IF PC IS IN THE HI SEG. ZERO USRMOD IF SO
	HLRZ	T1,.JDAT+JOBCOR## ;DOES THIS JOB NEED A LOW SEG INPUT OR OUTPUT
	CAIGE	T1,JOBDA##	;I.E. IT THERE ANY DATA LOADED ABOVE JOB DATA AREA
	JRST	SG3##		;NO, RETURN AND DO NOT READ IN LOW FILE
	JUMPE	T3,LOWCK2	;JUMP IF CAME FROM "SAVE"
	MOVSI	T1,(JS.EXE)	;WAS LOOKUP DONE?
	TDZE	T1,JBTST2##(J)
	JRST	LOWCK2		;YES
	MOVSI	T2,'EXE'	;SET UP TO CHECK FOR .EXE FILE
	MOVEM	T2,.JDAT+SGAEXT##	;STORE IN LOOKUP BLOCK
	SKIPL	F		;DEVICE INITED?
	PUSHJ	P,SGOPEN	;NO, DO IT
	TLNE	F,LOOKB		;IS THE FILE ALREADY OPEN?
	JRST	[USETI 0,1	;YES, THEN GO TO BLOCK1
		 JRST .+3]	;AND SKIP THE SECOND LOOKUP
	PUSHJ	P,LUKFIL##	;LOOKUP .EXE FILE
	  JRST	LOWCK2		;NO FOUND--CHECK FOR .LOW
	MOVSI	P1,GTLOW##	;GET ONLY THE LOW SEGMENT
	PUSHJ	P,GETNEW	;READ IN THE .EXE FILE
	  JRST	GETH2B		;LOW SEG LOCKED
	JRST	CPOPJ2##
LOWCK2:	MOVSI	T2,(SIXBIT /LOW/)	;YES, READ OR WRITE LOW FILE WITH EXTENSION .LOW
	JRST	SETLOW

NOHIGH:	PUSHJ	P,LOWSPC	;SEE IF PC IS IN THE  HI SEG. ZERO USRMOD IF SO
	PUSHJ	P,[IFN FTMP,<PUSHJ P,GGVMM##> ;UP MM
		   MOVE  T1,.USUSN ;SECTION TO USE
		   LSH   T1,P2SLSH
		   PUSHJ P,SVPCS##
		   SETZ  T1,
		   PJRST KILHSH] ;THEN REMOVE THE HI SEG
TRYLOW:	MOVE	T2,.JDAT+SGALOW##	;(HERE ON SAVE)
				; LOW FILE EXTENSION USER TYPED OR 0 IF HE DIDN'T
SETLOW:	MOVE	J,.CPJOB##	;IN CASE FROM SAVHGH WHICH CLOBBERED J
	MOVSI	T1,(JS.EXE)	;CLEAR EXE BIT
	ANDCAM	T1,JBTST2##(J)

	MOVEM	T2,.JDAT+SGAEXT##	;SET IN E+1 FOR LOOKUP
	AOS	(P)		;SET FOR NEED LOW READ OR WRITE RETURN
				; (HERE FROM SAVE IF NO HIGH SEG)
	JUMPL	F,SG3##		;HAS DEVICE ALREADY BEEN INITED?
				; INITB=1(BIT 0) IF YES
SGOPEN::OPEN	0,SGAMOD##	;NO, INIT DEVICE IN SAVMOD
	  JRST	SGERRA##	;ERROR, NOT AVAILABLE
	JRST	SG3##		;OK RESTORE SGALEN TO IOWD IF DTA,PP IF DSK AND RET

SAVLOW:	MOVE	T2,DEVMOD(F)
	TLNE	T2,DVMTA	;DEVICE MAGTAPE?
	PUSHJ	P,SAVNUL	;YES, WRITE A NULL HIGH SEGMENT
	JRST	TRYLOW		;RESTORE SGAEXT ETC,

;SUBROUTINE TO SEE IF THE UUO PC IS IN THE LOW SEGMENT AND IF NOT, ZERO
; USER MODE SO ERRORS STOP THE JOB

LOWSPC:	MOVE	T1,.JDAT+SGAEND## ;FLAGS
	TLNE	T1,GTSGO##	;DOING A SEGOP?
	POPJ	P,		;YES, DON'T ZERO USRMOD SINCE SEGOP DOESN'T
				; REMOVE SEGMENTS
	HRRZ	T1,.JDAT+JOBPD1##+1 ;IS CALL FROM HIGH SEGMENT?
	CAMLE	T1,.CPREL##	;COMPARE PC WITH LOW SEG PROTECTION
	HRRZS	.JDAT+JOBPD1##	;YES,(OR EXEC) SO CLEAR USRMOD PC FLAG IN LH
				; SO ERROR MESSAGES WILL NOT ATTEMPT TO ERROR
				; RETURN TO HIGH SEG WHICH IS NO LONGER
				; THE ORIGINAL ONE
	POPJ	P,		;RETURN
	
;ROUTINE TO CREATE A NEW HIGH SEG AND READ IN HIGH FILE OR
;PLACE THE DESIRED SHARABLE HIGH SEGMENT IN CURRENT USER'S LOGICAL ADDRESSING SPACE
;CALL:	MOVE R,LOW SEG RELOC
;	MOVE F,ADR. OF DEVICE DATA BLOCK
;	MOVE J,JOB NUMBER
;IFN FTEXE,<MOVSI T1,FLAGS>
;	PUSHJ P,GETSEG
;	RETURN 1 - HIGH SEG OR FILE NOT FOUND
;	RETURN 2 - HIGH SEG FOUND AND IN LOG ADR. SPACE(IN FACT ALSO IN CORE)
;IFN FTEXE,<RETURN 3 - BOTH SEGS IN AND READY TO GO>


GETSEG::MOVEM	T1,.JDAT+SGAEND##
	PUSHJ	P,SGH		;SET E+3 TO 0 IF DTA,PPN IF DSK
	PUSH	P,F		;SAVE POINTER TO DDB
	SKIPE	USRJDA##+0	;CHANNEL 0 OPEN?
	RELEAS	0,		;YES, RELEASE IT
	POP	P,F		;RESTORE IT
	MOVE	T2,.JDAT+SGANAM## ;GET PROGRAM NAME
IFN FTMP,<
	PUSHJ	P,UPMM##	;MUST HAVE THE MM TO SEARCH THE TABLES
>
	HLRZ	T1,.JDAT+SGAEXT## ;GET USER PROVIDED EXTENSION
	CAIE	T1,'EXE'	;SHARABLE EXTENSION?
	CAIN	T1,'SHR'
	CAIA
	JUMPN	T1,GETH0	;NO, IF SPECIFIED, DO OPEN,LOOKUP
	MOVS	T1,.JDAT+SGADEV## ;USER SUPPLIED DEVICE NAME
	CAIE	T1,'SYS'	;UNQUALIFIED?
	JRST	GETH5		;NO
	MOVSI	T1,SYSSEG##	;SEGMENT FROM SYS BIT
	JUMPE	T1,GETH5	;AVOID SEARCH IF DEFINED EQUAL TO ZERO
	PUSHJ	P,SYSNM##	;GET THE PPN OF USER'S SYS
	  JRST	GETH0		;A LOGICAL NAME
	MOVE	J,SEGPTR##	;YES, SEARCH FOR A KNOWN SEGMENT
GETH3:	CAME	T2,JBTNAM##(J)	;NAME MATCH?
GETH4:	AOBJN	J,GETH3		;NO, TRY THE NEXT ONE
	JUMPGE	J,GETH5		;IF NO MORE, QUIT
	CAMN	T3,JBTPPN##(J)	;FROM THIS USER'S SYS?
	TDNN	T1,JBTSTS##(J)	;NAME MATCHES, FROM SYS?
	JRST	GETH4		;NO, LOOK FOR ANOTHER MATCH
	HRLI	J,SHRSEG	;YES, FLAG AS SHARABLE
	TLO	F,SYSDEV	;AND FROM SYS
	JRST	GETH0A		;SKIP OPEN, LOOKUP, AND CLOSE UUOS
GETH5:	MOVE	T2,DEVMOD(F)	;EXTENSION 'SHR' OR ZERO, SEARCH KNOWN SEGS,
	TLNE	T2,DVDSK	;SKIP IF NOT A DISK
	SKIPA	T1,.JDAT+SGAPPN##	;USE PROVIDED PPN
	MOVEI	T1,0		;IF NON-DISK, PPN ARG=0
	TLNE	T2,DVDSK	;A DSK?
	JUMPE	T1,GETH0	;YES, IF E+3=0 DO THE LOOKUP SINCE THE DEFAULT
				; PATH MAY BE DIFFERENT FROM LOGGED-IN PPN
IFN FTMP,<
	PUSHJ	P,DWNMM##	;GIVE UP THE MM, SRCSEG WILL GET IT BACK
>
	MOVEI	T2,DSKDDB##
	CAIN	T2,(F)		;LOOKING AT PROTOTYPE DDB?
	SKIPA	U,.JDAT+SGADEV##	;YES, USE USER PROVIDED DEVICE
	SKIPE	U,DEVNAM(F)	;NO, USE PHYSICAL NAME FROM DDB
	SKIPE	T2,.JDAT+SGANAM##	;SEG NAME
	PUSHJ	P,SRCSEG	;SEARCH KNOWN SEGMENT TABLE
	  JRST GETH0		;NOT FOUND, GO DO OPEN AND LOOKUP IN CASE ON TAPE
GETH0A:
IFN FTFDAE,<
	LDB	T1,[POINT HSASIZ,JBTSTS##(J),HSAPOS]
	TRNN	T1,400		;SIGN BIT OF OWNER PROTECTION FIELD ON?
				;YES, DO THE LOOKUP SO FILE DAEMON WILL GET
				; CALLED IF IT SHOULD BE
>
	JRST	GETH1		;FOUND, CHECK ACCESS PRIVILEGES

IFN FTFDAE,<
	MOVEI	P1,PR.RED	;CHECK READ ACCESS FOR CURRENT JOB
	MOVE	P2,.CPJOB##	;SINCE WE DON'T NEED TO CALL FILDAE
	PUSHJ	P,CHKHSA	;UNLESS WE GET A PROTECION FAILURE
	  JRST	GETH0		;ACCESS FAILURE, DO THE LOOKUP
	JRST	GETH2D		;CAN READ WITHOUT FILDAE, SKIP THE LOOKUP
>

GETH0:
IFN FTMP,<
	PUSHJ	P,TGVMM##	;GIVE UP MM BEFORE OPEN
>
	OPEN	0,SGAMOD##	;NO, TRY TO ASSIGN DEVICE
	  JRST SGERRA##		;CAN'T, GO PRINT ERROR OR RETURN TO USER.
	MOVE	T1,DEVMOD(F)	;GET DEVICE BITS
	TLNE	T1,DVDTA	;DTA?
	JRST	GETH5A		;YES, SKIP LOOKUP
	MOVSI	T1,'EXE'	;GET EXTENSION OF EXE
	EXCH	T1,.JDAT+SGAEXT##	;PUT IT IN LOOKUP BLOCK AND SAVE OLD EXT
	PUSH	P,T1		;SAVE OLD EXTENSION
	HLRZ	T1,.JDAT+SGALOW##	;GET USER EXTEN.
	SKIPE	T1		;IS THERE ONE?
	CAIN	T1,'EXE'	;OR IS IT "EXE"?
	PUSHJ	P,LUPFIL	;IS THERE AN .EXE FILE?
	  SKIPA	T1,.JDAT+SGAEXT##	;NO
	JRST	[POP	P,(P)	;YES, GO READ IT IN
		 JRST	GETH6]
	HRRZS	T1		;ERROR CODE
	JUMPN	T1,NOFILE##	;REPORT ERROR IF NOT FILE NOT FOUND
	POP	P,.JDAT+SGAEXT##  ;RESTORE EXTENSION
GETH5A:	SETZM	.JDAT+SGAEND##	;CLEAR FLAGS, WE'RE THRU WITH THEM
	MOVSI	T1,(JS.EXE)	;SET EXE BIT
	IORM	T1,JBTST2##(J)	;IN JOB STATUS TO INDICATE LOOKUP FAILED
	MOVE	T1,DEVMOD(F)	;IS THIS MAG TAPE? (MAG TAPE CAN NEVER BE SHARABLE)
	TLNN	T1,DVMTA	;(MAG TAPE PUSHJS ALWAYS SUCCEED)
	PUSHJ	P,LUPFIL	;NO, LOOKUP ON HIGH FILE WITH EXT .SHR
	  JRST TRYHGH		;NOT FOUND, TRY EXTENSION OF .HGH
GETH6:	PUSHJ	P,CAWAIT##	;GET THE CA RESOURCE FOR THIS
	PUSHJ	P,FNDSMS	;DOES SEGMENT ALREADY EXIST?
	  JRST	[HLRZ	T1,.JDAT+SGAEXT##  ;GET LOOKUP'D EXTENSION
		 CAIN	T1,'EXE'  ;EXE?
		 JRST	EXEFND  ;YES
		 JRST	GETH2]  ;GO READ IN HIGH FILE
	JRST	GETH2C		;PROTECTION WAS CHECKED BY THE LOOKUP
GETH1:	MOVEI	P1,PR.RED##	;YES, CHECK EXECUTE ONLY PROTECTION
	MOVE	P2,.CPJOB##	;FOR CURRENT JOB
	PUSHJ	P,CHKHSA	;WITH FILE WHICH INITIALIZED HIGH SEG
IFE FTMP,<
	  POPJ	P,		;CAN'T READ-DTA, MTA NOT AVAIL OR DSK ACCESS RIGHTS
				; NOT PROPER, GIVE HIGH SEG RETURN TO GETSEG
>; END IFE FTMP
IFN FTMP,<
	  PJRST TGVMM##		;RETURN THE MM IF OWNED
>; END IFN FTMP
	JRST	GETH2D		;GO SHARE THE HIGH SEGMENT
;COME HERE IF THERE IS AN .EXE FILE TO BE READ IN
;
EXEFND:	MOVE	P1,.JDAT+SGAEND## ;GET SAVED FLAGS
	PUSHJ	P,GETNEW	;READ IN NEW SAVE FILE
	  JRST	GETH2B		;ERROR, FLUSH THIS USER
	TLNE	P1,GTLOW##	;WAS IT A GETSEG?
	JRST	SETVJD		;NO, SET UP VEST JOB DAT
	TLNE	P1,GT%GTH##	;WAS IT SUCCESSFUL?
	JRST	FIXVJD		;YES, DON'T SET UP VEST JOB DATA AREA
	HLLZS	.JDAT+SGAEXT##	;NO HI SEG IN THE FILE, SO FNFERR
	PJRST	CAFREE##	;RELEASE CA AND EXIT

SETVJD:	TLNN	P1,GT%GTH##	;IS THERE A HI SEG?
	JRST	NOVJD		;NO, DONT SET IT UP
	PUSHJ	P,ADJCOR	;SUBTRACT HIGH SEG SIZE FROM USER'S
				; CORE ARGUMENT
	MOVE	J,JBTSGN##(J)	;HISEG START
	HRRZ	J,.HBSGN(J)	;NEWSEST SEGMENT IS FIRST IN CHAIN
	LDB	T1,JBYHSO##	;GET HISEG START
	MOVE	J,.CPJOB##	;RESTORE JOB #
	TLNN	P1,SV%SHR	;SHARABLE
	PUSHJ	P,YANKIZ##	;BRING PAGE IN, IF OUT
	  JFCL			;SHOULDN'T BE ABLE
	MOVE	T2,JBTSGN##(J)	;GET HIGH SEGMENT NUMBER
	HRRZ	T2,.HBSGN(T2)	;NESEST SEGMENT IS FIRST IN CHAIN
	EXCH	T2,J		;PRESERVE J
	LDB	T3,JBYHSO##	;GET HISEG ORIGIN PAGE
	EXCH	T2,J		;RESTORE J
	MOVE	T2,JBTADR##(T2)	;GET ITS STARTING ADDRESS
	SKIPN	T1,.USREL	;IS JOB HOLEY?
	JRST	SETVJ1		;NO, SKIP JOBCOR FUDGERY
	LSH	T3,P2WLSH	;GET HISEG ADDRESS
	HRRZ	T1,.JDAT+JOBCOR## ;GET BUILT-IN CORE ARG
	CAML	T1,T3		;LINK BUG (OVERLAP ERROR)?
	MOVE	T1,.USREL	;YES, GET A GOOD JOBCOR
	HRRM	T1,.JDAT+JOBCOR## ;MAKE SURE OF JOBCOR
	HLRZ	T1,.JDAT+JOBSA##;GET INITIAL JOBFF
	CAMG	T1,T3		;GOOD VALUE THERE?
	JRST	SETVJ1		;YES, WE'RE DONE
	MOVE	T1,.USREL	;GET REAL JOBREL
	ADDI	T1,1		;MAKE INTO A JOBFF
	HRLM	T1,.JDAT+JOBSA##;GIVE IT A GOOD JOBFF
SETVJ1:	MOVE	T1,.JDAT+JOBSA##;SET UP VESTIGIAL JOB DATA AREA
	MOVEM	T1,JOBHSA##(T2)	;SET UP JOBSA
	MOVE	T1,.JDAT+JOB41##; AND JOB 41
	MOVEM	T1,JOBH41##(T2)
	MOVE	T1,.JDAT+JOBCOR## ; AND JOBCOR
	MOVEM	T1,JOBHCR##(T2)
	MOVE	T1,.JDAT+JOBHRL## ; AND JOBHRL
	HRR	T1,.JDAT+JOBREN##
	MOVEM	T1,JOBHRN##(T2)
	MOVE	T1,.JDAT+JOBVER## ; AND JOBVER
	MOVEM	T1,JOBHVR##(T2)
	JRST	NOVJD		;GO ENTER SEGMENT NAME

;HERE TO CHECK CONSISTANCY OF VESTIGIAL JOBDAT AFTER GETSEG
FIXVJD:	MOVE	J,JBTSGN##(J)	;GET HISEG NUMBER
	HRRZ	J,.HBSGN(J)	;NEW SEGMENT IS FIRST IN CHAIN
	MOVE	T2,JBTADR##(J)	;GET MONITOR ADDRESS OF SEGMENT
	LDB	T3,JBYHSO##	;GET ITS STARTING PAGE
	HRLM	T3,.JBHGA##(T2)	;SAVE ORIGIN PAGE IN SEGMENT
	LSH	T3,P2WLSH	;GET ITS STARTING ADDRESS
	HRRZ	T1,JOBHCR##(T2)	;GET CORE SIZE SPECIFIED IN SEGMENT
	CAIGE	T1,(T3)		;LINK BUG (PAGE OVERLAP)?
	JRST	NOVJD		;NO, NOTHING TO FIX
	HRRZI	T1,-1(T3)	;YES, GET BETTER VALUE
	HRRM	T1,JOBHCR##(T2)	;FIX IN SEGMENT
	HLRZ	T1,JOBHSA##(T2)	;GET INITIAL JOBFF FROM SEGMENT
	CAILE	T1,(T3)		;REASONABLE?
	HRLM	T3,JOBHSA##(T2)	;NO, MAKE BETTER

;HERE TO UPDATE THE KNOWN SEGMENT TABLE (IF NEEDED)
NOVJD:	AOS	(P)		;BUMP RETURN ADDRESS TO CALL+1
	MOVE	J,.CPJOB##	;RESTORE JOB NUMBER
	TLNN	P1,SV%SHR	;DID WE FIND A SHARABLE HIGH SEG?
	JRST	[AOS	(P)	;NO, EXIT TO CALL+3
		 JRST	CAFREE##] ;RELEASE THE CA RESOURCE
	PUSHJ	P,FNDSMM	;IS THIS AN ACTIVE SEGMENT?
	  JRST	STONAM		;NO, GO STORE NAME OF SHARABLE HIGH SEG
				; AND EXIT TO CALL+3
				;(THIS SHOULD NEVER HAPPEN!)
	SOS	(P)		;YES, WE MUST UNDO THE AOS SO THAT WE
				; WILL RETURN TO CALL+2
	JRST	GETH2C		;GO SET UP ITS PARAMETERS

;HERE TO MAP .VJDT TO SEGMENT WHOSE DATA BLOCK IS IN T1

MAPVJD::SE1ENT
	PUSH	P,T2
	PUSH	P,J		;SAVE J
	SKIPG	J,.HBSGN(T1)	;GET SEGMENT #
	TDZA	T2,T2		;CLEAR POINTER
	TLZA	J,-1^!SHRSEG	;CLEAR ALL BUT SHRSEG
	JRST	STRVJD		;CLEAR .UMVJD AND RETURN
	TLZE	J,SHRSEG	;SHARABLE?
	SKIPA	T2,@JBTVAD##(J)	;GET POINTER FROM MAP
	LDB	T2,JBYHSA##	;NON-SHARABLE, POINT TO FIRST PAGE
	HRLI	T2,(<PM.DCD>B2!PM.PUB!PM.WRT)
STRVJD:	MOVEM	T2,.UPMP+.UMVJD
	PUSHJ	P,CLPTZO##	;CLRPT THE ADDRESS
	  EXP	.VJDT
	POP	P,J
	POP	P,T2
	POPJ	P,
GETH2:	PUSHJ	P,INPSEG	;FOUND, GO READ IN HIGH FILE
GETH2B:	  JRST	[PUSHJ	P,CAFREE## ;FREE CA RESOURCE
IFN FTLOCK,< 
		 JRST	LOLOKD]		;LOW SEGMENT IS LOCKED
>
IFE FTLOCK,< 
		 STOPCD	.+1,DEBUG,SCR,]	;++SEGMENT COULDN'T BE READ
>
	PUSHJ	P,FNDSMM	;SEE IF FILE NAME SNUCK INTO SEGMENT TABLE
				; FOR OTHER USER WHILE IO GOING ON(UNLIKELY)
	  JRST STONAM		;USUALLY NOT FOUND
;HERE TO CONNECT JOB TO KNOWN HIGH (SHARABLE) SEG (SEG # ON PD LIST)
GETH2C:	PUSHJ	P,CAFREE##	;RELEASE CA
GETH2D:	PUSHJ	P,VALSEG	;VALIDATE DORMANT SEGMENT
	  JRST	[MOVE T1,.JDAT+SGAPPN## ;PPN SPECIFIED BY USER
		 MOVEM T1,.JDAT+SGALEN## ;STORE FOR LOOKUP
		 JRST GETH0]	;DO THE LOOKUP
	PUSH	P,J		;SAVE SEG #
	MOVE	J,.CPJOB##	;GET JOB #
;IF SEGOP., LOAD T1 WITH HS TO KILL (IF ANY) ELSE SKIP THIS CALL
	PUSH	P,F		;SAVE SYSDEV BIT (KILHGA MIGHT WIPE IT)
	MOVE	T1,.JDAT+SGAEND## ;GET GET BITS
	TLC	T1,GTHGH+GTLOW	;RUN UUO OR COMMAND?
	TLCN	T1,GTHGH+GTLOW	;YES IF BOTH BITS ARE ON
	PUSHJ	P,[PUSHJ P,KILHGA	;KILL ALL HIGH SEGS
IFN FTMP,<	   PUSHJ P,REMMM##>
		   MOVEI T1,PG.BDY ;ARGUMENT FOR GET1PG
		   PUSHJ P,GET1PG## ;REDUCE CORE IMAGE TO PAGE 0, SECTION 0
		   JRST CPOPJ1##];CONTINUE MAINLINE CODE
	  PUSHJ	P,[TLNE	T1,GTSGO## ;DON'T REMOVE ANYTHING IF SEGOP.
		   POPJ	P,	;GET OUT
		   MOVE  T1,.USUSN ;SECTION # TO KILL FOR
		   LSH   T1,P2SLSH
		   PUSHJ P,SVPCS##
		   SETZ  T1,	;KILL ALL SEGMENTS IN PCS SECTION UNLESS RUN
		   PJRST KILHGC] ;REMOVE PRESENT HIGH SEG FROM LOGICAL ADR.
				; SPACE(DELETE CORE SPACE IF JUST ASSIGNED BY
				; INPSEG SINCE NOT NAMED YET)
	POP	P,F		;RESTORE SYSDEV
	MOVE	J,.CPJOB##	;GET JOB #
	HRRZ	T1,(P)		;SEG # HE WANTS
	PUSHJ	P,FNDHSB	;DOES THIS SEGMENT (NOW) EXIST IN HIS ADDR SPACE?
	  SKIPA	J,(P)		;NO, CHARGE ON LOADING NEW SEG #
	JRST	SHRDUP		;DUPLICATE SEGMENT ERROR
;HERE TO SEE IF THE HIGH SEGMENT WILL OVERLAP ANYTHING ELSE
	LDB	T2,JBYHSO##	;PAGE NUMBER OF ORIGIN OF HIGH SEGMENT
	IOR	T2,.USUSN	;SECTION IT'S GOING INTO
	LDB	T1,IMGIN##	;CURRENT SIZE OF THE HIGH SEGMENT
	ADD	T1,T2		;TOP PAGE OF THE HIGH SEGMENT
	PUSHJ	P,CKNZP##	;WILL HIGH AND LOW SEGMENTS OVERLAP?
	  JRST	SHROVL		;YES, LOSE
	POP	P,J		;RESTORE NEW HIGH SEG. NUMBER
	PUSHJ	P,SEGSIZ##	;YES, T2=SIZE IN K OF HIGH SEGMENT
	SKIPL	JBTSTS##(J)	;DORMANT SEGMENT
	CAMG	T2,VIRTAL##	;YES, WILL ALLOWING IT TO BECOME ACTIVE MAKE VIRTAL
				; NEGATIVE
	PUSHJ	P,GSZSG##	;NO, SEE IF LOW + NEW HIGH WILL STILL FIT
	  JRST	SHRNRM		;TOO BIG
	PUSHJ P,[IFN FTMP,<PUSHJ P,DWNMM##>	;GIVE UP THE MM FOR PAGING
		    PUSH P,T2
		    PUSH P,J
		    PUSHJ P,PAGLOW##
		    POP P,J
		    SETZB T2,T3	    ;NO INCREASE
		    PUSHJ P,GSIZD## ;WILL IT FIT NOW?
		      JRST SHRNRM   ;NO
		      JFCL	    ;YES, IF VIRTUAL
		  IFN FTMP,<PUSHJ P,UPMM##>	;GET THE MM BACK
		SKIPGE	JBTSTS##(J)	;DORMANT?
		JRST	T2POPJ##	;NO
		PUSHJ	P,VALSEG	;BE SURE IT'S
	     	  SKIPA			;STILL THERE
					;NO
		JRST	T2POPJ##	;YES
		POP	P,T2		;NOT THERE
		POP	P,(P)		;DO LOOKUP
		JRST	GETH0]					;OUT LOW SEG

	MOVNS	T2		;NO,-NO. OF K IN DORMANT SEG
	SKIPL	JBTSTS##(J)	;IS THIS HIGH SEG ALREADY ACTIVE (SNA-1)?
	ADDM	T2,VIRTAL##	;NO, DECREASE COUNT OF VIRTUAL CORE AVAILABLE
	MOVEI	T1,JS.SFE	;SEGMENT IS FROM AN EXE FILE BIT
	MOVSI	T2,'EXE'	;ASSUME IT WAS
	TDNE	T1,JBTSTS##(J)	;WAS IT?
	MOVEM	T2,.JDAT+SGAEXT## ;YES, STORE EXTENSION FOR THE PROGRAM
	PUSH	P,J		;SAVE CURRENT HIGH SEGMENT NUMBER
	MOVE	J,.CPJOB##	;GET CURRENT JOB NUMBER
	PUSH	P,P1		;SAVE P1
	MOVE	P1,.JDAT+SGAEND## ;GET BITS
	PUSHJ	P,CRESP0	;CREATE THE CURRENT SECTION AND PUT PAGE 0 SECTION 0 IN IT
	POP	P,P1		;RESTORE P1
	PUSHJ	P,MAKHSB	;MAKE A HIGH SEG DATA BLOCK
	  JRST	SHRNRM		;NONE
	PUSH	P,T1		;SAVE NEW SEGMENT DATA BLOCK ADDR
	MOVEI	T2,0		;ASSUME SECTION 0
	PUSHJ	P,GETSSN	;GET SECTION NUMBER
	  MOVE	T2,T1		;NOT 0 OR 1
	POP	P,T1		;RESTORE SEGMENT DATA BLOCK ADDR
	DPB	T2,[PSG2LH+.HBSG2(T1)]
	POP	P,J		;RESTORE SEGMENT NUMBER
	TDZA	T3,T3		;FLAG CALL IS GETSEG OR RUN UUO
				; (SO THAT CONNECTING TO AN IDLE SEG
				; WILL BE CHECKED).
				;(AND DON'T CLEAR BITS FROM LH(J)
	

;HERE FROM CORE AND REMAP UUOS - WITH T3 NON-ZERO AS A FLAG
; NOT TO CHECK FOR CONNECTING TO AN IDLE HI-SEG (SINCE IT LOOKS LIKE
; ONE BUT CANNOT BE)
;T1 HAS HIGH SEG DATA BLOCK ADDR (NOT YET LINKED IN FOR JOB)

SHARE1::HRRZS	J		;CLEAR LEFT HALF FOR NEW SEG
	MOVE	T2,.USJOB	;JOB #
	EXCH	T1,JBTSGN##(T2)	;STORE NEW START OF CHAIN, GET OLD
	HLLM	T1,JBTSGN##(T2)	;RESTORE BITS
	MOVE	T2,JBTSGN##(T2)	;GET NEW BLOCK ADDR AGAIN
	HRRM	T1,.HBLNK(T2)	;STORE
	MOVEM	J,.HBSGN(T2)	;SET SEGMENT # SO FNDHSB WILL FIND IT
SHARE2:	MOVE	T1,.USJOB
	PUSHJ	P,INCSHR	;BUMP SHARE COUNT FOR SEGMENT AND UPDATE JBTSGN
	MOVSI	U,SNA		;MAKE SURE THIS HIGH SEG IS FLAGGED AS IN USE
				; IE SEG IN SOME USER'S LOG. ADR. SPACE
	IORB	U,JBTSTS##(J)	;MAY HAVE BEEN JUST ASSIGNED OR DORMANT
	HLR	U,JBTSTS##(T1)	;JOB STATUS WORD
	TLNN	U,JXPN!SWP	;IS HIGH SEG IN CORE AND NOT EXPANDING?
	JRST	SHARE3		;YES, GO INCREMENT IN CORE COUNT FOR JOB
	TDNE	U,[JXPN,,JXPN]	;JXPN ON ANYWHERE?
	JRST	SETRL0		;YES, WAIT TILL HIGH SEG IN CORE TOO
	MOVSI	U,SWP		;NO, SET SWP BIT SO JOB CANNOT BE RUN
	IORM	U,JBTSTS##(T1)	;UNTIL HIGH SEG IS SWAPPED IN
	MOVSI	U,(JS.NNQ)	;ICPT IGNORED WITH SWP SET, DONT ASSIGN
	IORM	U,JBTST2##(T1)	; IF JUST HIGH SEG COMES IN
	JRST	SETRL2		;GO CALL SCHEDULER


;HERE IF HIGH SEG ALREADY IN-CORE (CORE, REMAP, RUN, GET SEG UUOS)
SHARE3:	SKIPN	T3		;CORE OR REMAP (HI-SEG LOOKS IDLE BUT ISN'T)?
	PUSHJ	P,CHKIDL	;NO, CHECK TO SEE IF HI-SEG IS IDLE IN CORE
				; IE IN-CORE COUNT 0 BUT IN SOME USER'S
				; ADR SPACE WHO IS SWAPPED OUT OR DORMANT IN CORE
				; (IE IN NO ONE'S LOGICAL ADR. SPACE)
				;IF YES, DECREASE COUNT OF FREE CORE (CORTAL)
	MOVE	T1,.USJOB	;CURENT JOB NO. (FOR INCCNT)
	PUSHJ	P,INCCNT	;NO, INCREMENT HIGH SEG IN-CORE COUNT FOR THIS
				; JOB(T1) IF NOT ALREADY INCREMENTED, RETURN
				; WITH J = HIGH SEG NO.
	PUSHJ	P,CHKTAL	;CHECK CORTAL WITH CORTAB, HALT IF DIFF.
	TLNE	U,JXPN		;IS JOB (LOW SEG) EXPANDING?
	JRST	SETRL0		;YES, SWAP JOB OUT
				; (CAN HAPPEN IF CORE UUO WHICH
				; ASSIGNS HIGH SEG AND EXPANDS LOW SEG)
IFN FTMP,<
	PUSHJ	P,INTLVL##	;DON'T RETURN MM AT INTERRUPT LEVEL (VIRCHK)
	PUSHJ	P,TGVMM##	;GIVE UP MM IF OWNED
>
	JRST	SETRL1		;NO, SET HARD AND SOFT RELOC AND RETURN

;HERE WHEN NOT ENOUGH ROOM IN SYSTEM TO ALLOW USER TO USE SEG
;T1=NO. WORDS-1=SUM OF BOTH SEGS-1
SHROVL:	SKIPA	T3,[EXP LOHERR]	;HIGH AND LOW SEGMENTS OVERLAP
SHRNRM:	MOVEI	T3,NECERR	;NOT ENOUGH CORE
SHRERR:	PUSH	P,T1		;SAVE NO. OF WORDS-1 NEEDED FOR MESSAGE IN NROOM
	PUSH	P,T3		;SAVE ERROR CODE
	PUSHJ	P,LOWSPC	;SEE IF PC IS IN THE HI SEG. ZERO USRMOD IF SO
IFN FTMP,<
	PUSHJ	P,TGVMM##	;GIVE UP THE MM IF OWNED
>
	PUSHJ	P,SETMAP##	;GO SET HARDWARE RELOC. SO JOB
				; CANNOT REFERENCE HIGH SEG
	POP	P,T1		;T1 = ERROR CODE
	JRST	NROOM##		;GO PRINT MONITOR MESSAGE AND STOP JOB
				; OR ERROR RETURN TO LOW SEGMENT - 0(P)
				; HAS #WORDS-1
				; (UNLESS UUO HAS A HALT FOLLOWING IT)

SHRDUP:	MOVEI	T3,DPSERR	;DUPLICATE SEGMENT
	JRST	SHRERR
	
STONAM:	MOVE	T3,.CPJOB##	;CURRENT JOB NUMBER
	CAME	T3,CAUSER##	;MUST BE OWNER OF CA RESOURCE HERE
	STOPCD	.+1,DEBUG,DHC,	;++DON'T HAVE CA (BLITHER ON ANYWAY)
	MOVSI	J,SHRSEG	;FLAG THIS USER AS USING A SHARABLE HIGH SEG
	MOVE	T3,JBTSGN##(T3)	;NEW SEGMENT IS FIRST IN CHAIN
	IORB	J,.HBSGN(T3)	;SET BIT
	PUSH	P,T1		;SAVE PPN
	PUSH	P,T2		;SAVE FILE NAME
	SKIPE	T1,.JDAT+SGAPPN## ;PPN OR POINTER TO PATH USER TYPED
	TLNE	T1,-1		;A PATH POINTER?
	JRST	STON0		;NO, STORE INFO AND EXIT
	SKIPE	.JDAT+JOBUAL##	;IS THERE A PATH? I.E., DEVICE WAS DSK
	SKIPN	.JDAT+JOBUAL##+3 ;YES, SFD'S INCLUDED IN THE PATH?
	JRST	STON0		;NO
	MOVEI	T2,MAXLVL##+2	;ROOM FOR THE FULL PATH TERMINATED BY A 0
	PUSHJ	P,GETWDS##	;GET THAT MUCH FREE CORE
	  JRST	[PUSHJ	P,CAFREE## ;FREE CA RESOURCE
		 STOPCD	TTPOPJ##,JOB,CSP,] ;++CANNOT STORE PATH
	MOVEM	T1,-1(P)	;SAVE ADDRESS OF THE FULL PATH
	SETZM	MAXLVL##+1(T1)	;INSURE PATH BLOCK IS TERMINATED BY A 0
	HRLI	T1,.JDAT+JOBUAL##+2 ;ADDRESS OF DATA RETURNED BY THE PATH UUO
	MOVEI	T2,MAXLVL##(T1)	;NUMBER OF WORDS TO BLT
	BLT	T1,(T2)		;COPY THE FULL PATH TO FREE CORE
STON0:	POP	P,JBTNAM##(J)	;STORE THE HIGH SEGMENT NAME
	POP	P,JBTPPN##(J)	; AND THE DIRECTORY OR POINTER TO THE PATH.
	MOVEM	U,JBTDEV##(J)	;STORE DEVICE NAME(STR) FOR HIGH SEG
	MOVSI	T1,SHRSEG	;ALSO FLAG HIGH SEG ASSIGNED
	IORM	T1,JBTSTS##(J)	;BY INPSEG AS SHARABLE FOR OTHER USERS
	MOVE	T1,.JDAT+SGADAT## ;GET E+2
	LDB	T1,[POINT 9,T1,8] ;GET ACCESS RIGHTS FROM LOOKUP E+2
	DPB	T1,[POINT 9,JBTSTS##(J),HSAPOS]	;AND STORE IN MONITOR WITH HIGH
				; SEG STATUS
	HLRZ	T1,.JDAT+SGAEXT## ;EXTENSION
	MOVEI	T2,JS.SFE	;SEGMENT FROM AN EXE FILE BIT
	CAIN	T1,'EXE'	;DID THE SEGMENT COME FROM AN EXE FILE?
	IORM	T2,JBTSTS##(J)	;YES, REMEMBER THAT
	MOVSI	T1,SYSSEG##	;YES, FLAG AS GOTTEN FROM SYS
	TLNE	F,SYSDEV	;FROM SYS
	IORM	T1,JBTSTS##(J)
	PUSHJ	P,CAFREE##	;FREE THE CA
SETRL0:	MOVE	J,.USJOB	;CURRENT JOB NUMBER TO BE EXPANDED
				; (NOT HIGH SEG)
	PUSHJ	P,XPANDH##	;FLAG THIS USER AS TRYING TO EXPAND(SWP=1)
				; SO THAT THIS NEW HIGH SEG WILL BE SWAPPED IN
SETRL2:
IFN FTMP,<
	PUSHJ	P,DWNMM##	;ALL DONE, RETURN THE MM
>
	PUSHJ	P,WSCHED##	;WAIT TILL IT IS SWAPPED IN(CALL SCHEDULER)

SETRL1:
IFN FTMP&FTKL10,<
	PUSHJ	P,CHKSWS##	;SEE IF ATTACHING TO A SHARABLE
				; WRITEABLE HI SEG. IF SO, MAKE
				; SURE ITS UNCACHED IN THIS JOBS MAP
>
	MOVE	J,.USJOB	;CURRENT JOB
	HRRZ	T1,JBTSGN##(J)	;NEWEST HIGH SEG IS ONLY ONE WHICH MIGHT BE
	JUMPE	T1,SETRL3	;RELEVANT
	HRR	T2,JBTSTS##(J)	;RIGHT HALF OF JBTSTS
	HLL	T2,JBTST2##(J)	;LEFT HALF OF JBTST2
	SETCAB	T2,		;COMPLEMENT
	TDNE	[JS.IGS+JS.XOR]	;DO IOR IF BOTH WERE SET (BOTH NOW CLEAR)
	JRST	SETRL3		;NO
	MOVSI	T2,GTSSEG	;SEGMENT WAS GETSEGED BUT
	IORM	T2,.HBSGN(T1)	;YES, LIGHT GETSEGED BIT
SETRL3:	PUSH	P,T1		;SAVE T1
	PUSHJ	P,EXONLY##	;IF EXECUTE ONLY PROTECT THE CORE IMAGE
	AOS	-1(P)		;SKIP RETURN (GETSEG,UCORHI,UREMAP)
	PUSHJ	P,SXOPFH##	;MAKE PFH CONCEALED IF GETSEG OF XO HI-SEG
	PUSHJ	P,STVSIZ##	;STORE CURRENT VIRTUAL SIZE OF BOTH SEGMENTS
	POP	P,T1		;RESTORE SEGMENT DATA BLOCK ADDR
	JUMPE	T1,SETRLH##
	MOVSI	T2,REDOMP	;FORCE THIS MAP TO BE REDONE
	IORM	T2,.HBSGN(T1)
	PUSHJ	P,MAPVJD	;SET UP .VJDT
	SKIPG	T2,.HBSGN(T1)	;A REAL HIGH SEGMENT?
	JRST	SETRL4		;NO
	MOVE	T3,.VJDT+.JBHNM## ;HIGH SEGMENT NAME
	MOVEM	T3,.HBHNM(T1)	;STORE IT (DOESN'T MATTER IF A SPY SEGMENT)
SETRL4:	TLNE	T2,SHRSEG	;YES-IS IT NON-SHARABLE?
	SKIPA	T2,[REDOMP,,]
	PJRST	MAPHGH##
	IORM	T2,JBTSGN##(J)	;TURN IT ON GLOBALLY TOO
	JRST	SETRLH##	;NO, REDO THE MAP
				; FOR CURRENT JOB AND RESTORE R AND J

;ROUTINE TO ADJUST USER'S CORE ARG. IN GET,R,RUN OR SAVE COMMANDS SO THAT
; THE ARG. SUPPLIED IS THE TOTAL OF BOTH THE LO & HI SEGS. IF THERE IS NO
; HI SEG THEN ARG. IS THE LO SEG SIZE AS IN NON-REENTRANT SYSTEMS.
; IF THERE ARE BOTH LO & HI SEGS AND THE ARG. IS LESS THAN THE HI SEG + 1K
; MANDATORY LO SEG SIZE THEN THE CORE ALLOCATION IS UNCHANGED.

;CALL	MOVE J,JOB NO.
;	PUSHJ P,ADJCOR
;	ALWAYS RETURN WITH T2 & U DESTROYED


ADJCOR::SKIPE	U,.JDAT+SGANEW## ;WAS AN ARG. TYPED OF 0 OR NOT AT ALL?
	SKIPN	T1,JBTSGN##(J)	;YES, ANY HIGH SEGS?
	POPJ	P,		;NONE
ADJCO0:	HRRZ	T2,.HBSGN(T1)	;GET SEGMENT NUMBER
	SKIPG	.HBSGN(T1)	;SKIP SPY SEGS
	JRST	ADJCO1
	HLRZ	T2,JBTADR##(T2)	;SIZE
	SKIPE	U,.JDAT+SGANEW##	;WAS AN ARG. TYPED OF 0 OR NOT AT ALL ?
	SUBI	U,1(T2)		;NO - COMPUTE LO SEG SIZE
	JUMPLE	U,CPOPJ##	;IF NOT 1K OR GREATER
ADJCO1:	SKIPE	T1,.HBLNK(T1)	;NEXT HIGH SEG
	JRST	ADJCO0
	MOVEM	U,.JDAT+SGANEW##	;STORE IT
	POPJ	P,		;RETURN
	
				; TO LOW SEG RELOC AND JOB NUMBER
;TRY TO READ IN NON-SHARABLE FILE WITH EXTENSION .HGH

TRYHGH:	MOVE	T1,DEVMOD(F)	;LOOKUP FAILURE, SEE IF OTHER THAN NOT FOUND
	TLNN	T1,DVDSK	;WAS LOOKUP ON DISK?
	JRST	TRYHG2		;NO, MUST BE A NOT FOUND
	HRRZ	T1,.JDAT+SGAEXT##	;PICK UP POSSIBLE ERROR CODE
	CAILE	T1,IPPERR	;FILE NOT FOUND OR NO UFD?
	CAIN	T1,SNFERR	;NO--NON-EXISTANT SFD?
	JRST	TRYHG2		;YES--TRY .HGH
	JRST	NOFILE##	;REPORT ERROR

TRYHG1:	MOVE	J,.CPJOB##	;RESTORE J WHICH MAY HAVE BEEN CLOBBERED BY FILSER
				; AND IS NEEDED BY COMCON FOR ERRORS
	MOVE	T1,DEVMOD(F)	;FAILURE FOR EXTENSTION .HGH
	TLNN	T1,DVDSK	;SAME AS BEFORE?
	POPJ	P,		;JUST NOT FOUND!
	HRRZ	T1,.JDAT+SGAEXT##	;ERROR CODE
	CAILE	T1,IPPERR	;NO FILE OR NO UFD?
	CAIN	T1,SNFERR	;NO--NON-EXISTANT SFD?
	POPJ	P,		;FILE NOT FOUND!
	JRST	NOFILE##	;NO--GIVE ERROR
TRYHG2:	MOVSS	T1,.JDAT+SGAHGH##	;TRY LOOKUP WITH EXTENSION .HGH
	PUSHJ	P,SGH1		;SET EXT AND E+3 OF LOOKUP BLOCK
				; FOR DTA OR DSK
	PUSHJ	P,LUPFIL	;LOOKUP WITH EXT .HGH
	  JRST	TRYHG1		;NOT FOUND, NO HIGH SEG RETURN FROM GETSEG
IFN FTLOCK,< 
	PUSHJ	P,INPSEG	;TRY TO READ IN THE HIGH SEGMENT
	  JRST	LOLOKD		;ERROR, LOW SEGMENT IS LOCKED SO CAN'T
				; ASSIGN CORE FOR THE HIGH SEGMENT
	JRST	CPOPJ1##	;HIGH SEGMENT READ IN, GIVE OK RETURN
LOLOKD:	HRRZ	T2,.JDAT+JOBCOR##	;AMOUNT OF CORE
	PUSH	P,T2		;ERROR REPORTER EXPECTS ARG. ON STACK
	JRST	NOROOM##	;REPORT THE ERROR
>	;END IFN FTLOCK CONDITIONAL
	
;ROUTINE TO READ IN A HIGH FILE INTO TOP OF LOW SEG AND REMAP
;LOOKUP MUST HAVE BEEN ALREADY BEEN DONE
;CALL:	MOVE R,XWD PROTECTION, RELOCATION FOR LOW SET
;	PUSHJ P,INPSEG
;	RETURN1 - NO HIGH FILE,
;	RETURN2 - HIGH FILE READ IN
;	C(J)=JOB NUMBER
;CALLED FROM TRYHGH AND GETH1


INPSEG:	MOVE	J,.CPJOB##	;GET JOB NUMBER (IT MAY HAVE BEEN CLOBBERED BY FILSER)
IFN FTLOCK,< 
	MOVSI	T2,NSHF!NSWP	;CANNOT ASSIGN CORE IF THE JOB IS LOCKED
	TDNE	T2,JBTSTS##(J)	;IS IT LOCKED?
	JRST	[MOVEI T1,SNSERR ;SEGMENT NOT ON SWAPPING SPACE ERROR
		 POPJ P,]	;ERROR RETURN
>	;END IFN FTLOCK CONDITIONAL
	SKIPN	T1,.USREL	;HIGHEST RELATIVE ADDRESS IN THE LOW SEGMENT
	MOVE	T1,.CPREL##	;HIGHEST REL(USER) ADR IN LOW SEG FOR CURRENT USER
	TRO	T1,PG.BDY	;MAKE EVEN 1K-1(SHOULD BE 140) SO CAN USE REMAP UUO
				; OR USER'S LOW SEG IF RUN OR GETSEG UUO
	HRRM	T1,.JDAT+SGALEN##	;STORE ADR-1 OF IOWD FOR READING IN
				; HIGH FILE JUST ABOVE END OF CURRENT LOW SEG
	MOVE	T3,DEVMOD(F)	;DEVICE CHARACTERISTICS
	TLNE	T3,DVMTA	;MTA?
	JRST	INPMAG		;YES, GO DO SOME SPECIAL STUFF
	HLRE	T2,.JDAT+SGALEN##	;-FILE LENGTH FROM DIRECTORY LOOKUP
	JUMPL	T2,INPSE2	;GO IF NEGATIVE WORD COUNT
	JUMPE	T2,GETERR##	;ERROR IF ZERO LENGTH
	LSH	T2,BLKLSH##	;CONVERT BLOCKS TO WORDS
	MOVNS	T2		;NEGATIVE WORD COUNT
	HRLM	T2,.JDAT+SGALEN##	;STORE WORD COUNT IN IOWD
INPSE2:	SUB	T1,T2		;FIRST ADR-1 PLUS(-MINUS) LENGTH YIELDS:
				; LAST USER LOC TO BE READ INTO
	PUSHJ	P,GETCOR##	;ASSIGN ENOUGH CORE FOR LAST WORD OF HIGH FILE
				; RETURN ONLY IF OK
	INPUT	0,SGALEN##	;READIN HIGH FILE
	PUSHJ	P,SGIOCK##	;ANY ERRORS?
	MOVE	T3,DEVMOD(F)	;DEVICE CHARACTERISTICS
	TLNE	T3,DVMTA	;MTA?
	JRST	INPMG2		;YES, DO STUFF WHICH IS DONE ON LOOKUP FOR 
				;DIRECTORY DEVICES
;INSPE3 IS CALLED AS A SUBROUTINE
;FROM GETEXE IN SEGCON IF EXE FILES
;ARE SUPPORTED
INPSE3:	HRRZ	T1,.JDAT+SGALEN##	;GET HIGHEST USER ADR IN ORIGINAL LOW SEG
	EXCTUX	<LDB	T2,[POINT 9,.JBHDA##(T1),17]>
	LSH	T2,P2WLSH
	HRL	T1,T2
	MOVE	J,.CPJOB##	;INPUT CLOBBERS J
	PUSHJ	P,UREMA0	;DO REMAP UUO
	  JRST	[MOVEI	T1,LOHERR	;LOW SEGMENT OVERLAPS HIGH SEGMENT
		POPJ	P,	;ERROR RETURN
]
	JRST	CPOPJ1##	;RETURN, CALLI UUO SETS JOB NO IN J

INPMAG:	MOVNI	T2,MTSIZ##	;LENGTH OF A MAGTAPE RECORD
	HRLM	T2,.JDAT+SGALEN##	;SET TO READ 1ST RECORD OF FILE
	JRST	INPSE2		;GO READ IT

INPMG2:	TRNE	S,IODEND	;EOF?
IFE FTLOCK,<
	POPJ	P,
>
IFN FTLOCK,<
	JRST	TPOPJ##		;YES, THERE IS NO HIGH SEGMENT
>
	MOVE	T1,.JDAT+SGALEN##	;NO, THERE IS A HIGH SEGMENT
	PUSH	P,T1		;SAVE ORIGINAL IOWD
	MOVEI	T1,JOBHRN##+1(T1)	;LENGTH OF HIGH SEG
	EXCTUX	<HLRZ T1,@T1>
	JUMPE	T1,INPMG4	;JUMP IF NULL HIGH SEGMENT
	CAIG	T1,MTSIZ##
	JRST	INPMG3		;WHOLE FILE WAS 1 RECORD
	MOVNM	T1,T2		;-WORD COUNT
	HRL	T2,(P)		;ADDRESS OF START OF 1ST RECORD
	ADD	T2,[XWD MTSIZ##,MTSIZ]	;INCREMENT OVER 1ST RECORD
	MOVSM	T2,.JDAT+SGALEN##	;NEW IOWD
	HRRZ	T2,0(P)		;GET ADDRESS OF FIRST RECORD OF HIGH SEG
	ADD	T1,T2		;HIGHEST ADDRESS NEEDED
	PUSHJ	P,FNDPDS##	;TAPSER WIPES W
	PUSHJ	P,GETCOR##	;GET THE CORE
	INPUT	SGALEN##	;READ THE REST OF THE FILE
	PUSHJ	P,SGIOCK##	;ANY ERRORS?
INPMG3:	STATO	IOTEND+IODEND	;MAGTAPE AT END OF TAPE OR END OF FILE?
	MTAPE	16		;NO, SKIP OVER THE EOF
	SETSTS	DR		;RESET THE EOF BIT
	POP	P,.JDAT+SGALEN##	;RESTORE THE ORIGINAL IOWD
	JRST	INPSE3		;AND CONTINUE

INPMG4:	MTAPE	16		;SKIP TO EOF
	POP	P,T1
IFE FTLOCK,<
	POPJ	P,
>
IFN FTLOCK,<
	PJRST	TPOPJ##
>
	
;ROUTINE TO CHECK IF HIGH SEG ABOUT TO BE SHARED WAS IDLE OR DORMANT
;IF YES, THE COUNT OF FREE+DORMANT+IDLE CORE IS DECREASED
;CALL:	MOVE J,HIGH SEG NUMBER
;	PUSHJ P,CHKIDL
;CALLED FROM GETSEG AND FININ
CHKIDL:	PUSHJ	P,CHKLKH	;CHECK FOR DORMANT OR IDLE (UNLOCKED)
	  POPJ	P,		;NO, CORTAL ALREADY ADJUSTED
	LDB	T1,IMGIN##	;SIZE IN PAGES
	MOVNS	T1		;-NO. OF PAGES IN CORE
	ADDM	T1,CORTAL##	;YES, THEN DECREASE COUNT OF FREE+DORMANT+IDLE
				; CORE SINCE THIS HIGH SEG WILL NOT BE IDLE 
	POPJ	P,		; ANY MORE

;SUBROUTINE TO CHECK FOR CORE ASSIGNED TO A DORMANT OR UNLOCKED
; IDLE SEGMENT SO THAT CORTAL MAY BE ADJUSTED PROPERLY

CHKLKH:	MOVE	T1,JBTSTS##(J)	;GET HIGH SEGMENT STATUS
	TRNN	T1,ICCMSK	;DORMANT OR IDLE?
	SKIPN	JBTADR##(J)	;AND IN CORE?
	POPJ	P,		;NO
	TLNN	T1,NSWP		;NO, IDLE - LOCKED?
	AOS	(P)		;YES, SKIP RETURN
	POPJ	P,		;NO

;ROUTINE TO SETUP LOWER CORE FOR LOOKUP OR ENTER FOR HIGH FILE
;CALL:	LH OF SGAHGH(R) SET TO FILE EXT FOR HIGH SEG
;	PUSHJ P,SGH
;	SETUP SGALEN TO -1 IF DTA OR MTA, PROJ R IF DSK


SGH:	MOVE	T1,.JDAT+SGAHGH##	;SETUP EXTENSION(FOR HIGH FILE SHR OR HGH)
SGH1:	HLLZM	T1,.JDAT+SGAEXT##	;STORE EXTENSION FOR LOOKUP ORENTER
	MOVEI	T1,-1		;SET SGALEN TO -1 IF DEVICE NOT DISK
				; (FIRST REL LOC-1 DUMPED FROR HIGH SEG)
	JRST	SG4##		;OTHERWISE SET TO PROJ,R NO.

;ROUTINE TO DELETE A FILE, SO SUBSEQUENT GET WILL NOT BE CONFUSED
;USED BY SAVE AND SSAVE (NOT BY GET)
;CALL:	HRLI T1, EXTENSION (.LOW,.SHR,.HGH, OR USER TYPED ARG)
;	PUSHJ P,DELET
;	ALWAYS RETURN

DELET:	PUSHJ	P,SGH1		;SETUP EXTENSION, AND E+3 IN DIRECTORY BLOCK
	PUSH	P,DEVPPN(F)
	LOOKUP	0,SGANAM##	;LOOKUP FILE
	JRST	TPOPJ##		;NOT FOUND
	CLOSE	0,		;CLOSE SO RENAME WILL WORK
	POP	P,T1
	CAMN	T1,DEVPPN(F)	;DON'T DELETE IF NOT SAME PPN
	RENAME	0,SGAREN##	;DELETE FILE
	JFCL			;IGNORE IF CAN'T, WE TRIED
	POPJ	P,		;RETURN
	
;ROUTINE CALLED AFTER A HIGH OR LOW SEG SWAP IN READ ERROR
;CLEAR HIGH SEG NAME, SO NO NEW USERS WILL SHARE
;CALL:	MOVE J,HGIH OR LOW SEG NO.
;	PUSHJ P,SEGERR
;	ALWAYS RETURN WITH J=JOB NUMBER


SEGERR::CAIG	J,JOBMAX##	;LOW SEG?
	POPJ	P,		;YES
	MOVE	T1,JBTSTS##(J)	;NO, HAS THE ERROR BEEN DETECTED FOR THIS HIGH SEG
	TLNN	T1,SERR		; ON A PREVIOUS SWAPPING?
	PUSHJ	P,SWPREC##	;NO, RECORD ERROR AND DECREASE OF VIRTUAL CORE
	MOVSI	T1,SERR		;SET HIGH SEG ERROR BIT
	IORM	T1,JBTSTS##(J)	;SO SPACE WILL NEVER BE RETURNED BY SERSWP
	SETZM	JBTNAM##(J)	;CLEAR HI SEG NAME SO NO NEW USER WILL SHARE
	MOVE	J,JBTSWI##(J)	;RETURN JOB NUMBER ASSOCIATED WITH HIGH SEG
	POPJ	P,

;SUBROUTINE TO CALCULATE THE STARTING VIRTUAL
; ADDRESS IN A HIGH SEGMENT AND THE HIGHEST
; LEGAL ADDRESS IN THE SEGMENT
;CALLING SEQUENCE:
;	XMOVEI	T1,SEGMENT DATA BLOCK (OR 0 IF NEW NON-SPY SEGMENT)
;	PUSHJ	P,HSVAD
;RETURNS HERE, T1=HIGHEST LEGAL ADDRESS, T2=
; STARTING VIRTUAL ADDRESS

HSVAD::	PUSH	P,J		;SAVE JOB NUMBER
	PUSHJ	P,HSVORG	;COMPUTE PROPER ORIGIN
HSVAD1:	JUMPLE	J,HSVAD6	;DON'T GO AFTER JBTADR WHEN SPYSEG
	TLO	J,(1B0)		;NO, MAKE A USABLE INDEX OUT OF J
	HLL	T1,JBTADR##(J)	;NO, SIZE OF HI. SEG.
	TRNE	J,-1		;ANY HIGH SEG?
	TLNE	T1,-1		;YES, JBTADR NON-ZERO?
	JRST	HSVAD4		;YES PROCEED.
	TLNN	J,SHRSEG	;SWAPPED OUT OR NON-SHARABLE?
	JRST	HSVAD3		;NON-SHARABLE
	LDB	T1,IMGIN##	;YES, USE IMGIN.
	LSH	T1,P2WLSH	;(CAN'T BE VIRTUAL)
	SOJA	T1,HSVAD5	;..

HSVAD3:	LDB	T1,[PHSSLH+.HBHSZ(T1)] ;SIZE OF SEGMENT
	LSH	T1,P2WLSH	;CONVERT TO WORDS
	SKIPE	T1		;IF ZERO, RETURN 0
	ADDI	T1,(T2)		;ADD IN ORIGIN
	JRST	JPOPJ##		;GET FROM UPMP

HSVAD6:	MOVS	T1,J		;SPY SEG, GET ENDING ADDR FROM SEGMENT WORD
HSVAD4: HLRZS	T1		;CLEAR POSSIBLE SPYSEG BIT
HSVAD5:	SKIPE	T1		;SKIP IF NO HI. SEG.
	ADDI	T1,(T2)		;T1 = HIGHEST ADR.
	JRST	JPOPJ##		;RETURN

HSVORG:	HRRZ	T2,.USREL	;LOAD WHILE J STILL INTACT
	SKIPN	T2		;HIGHEST ADR. IN LOW SEG
	HLRZ	T2,JBTADR##(J)	;LOW SEG PROTECTION
	SKIPN	J,T1		;IS THIS A NEW SEG?
	JRST	HSVNEW		;YES (J CLEARED BY ABOVE)
	SKIPGE	J,.HBSGN(T1)	;IS "EXISTING" SEG A SPY SEG?
	JRST	HSVSPY		;YES, PROCESS AS SUCH
	JUMPE	J,HSVNEW	;IT'S REALLY NEW IF NO SEG #
	TLO	J,(1B0)		;MAKE A USABLE INDEX
	LDB	T2,JBYHSO##	;IF OLD SEG, GET VALUES ALREADY SET UP
	TLZ	J,(1B0)		;SO HSVAD1 DOESN'T GET CONFUSED
	LSH	T2,P2WLSH	;CONVERT TO ADDRESS
	POPJ	P,

HSVNEW:	XSFM	T1		;WHICH SECTION ARE WE IN
	ANDI	T1,MXSECN	;ONLY PCS SECTION #
	EXCH	T1,T4		;SAVE T4, GET T1
	PUSHJ	P,RSECT4##	;S0?
	  JRST	HSVNS0		;NON-EXISTENT
	JUMPE	T4,HSVNS0	;S0
	EXCH	T1,T4		;RESTORE T4 AND PUT SECTIN # IN T1
	LSH	T1,S2PLSH	;CONVERT TO PAGE #
	SE1ENT			;NEED TO REFERENCE PAGE MAPS
HSVNE0:	SKIPN	T2,@[IW MS.MAP,UMAPS(T1)] ;IS THIS ENTRY FREE?
	JRST	HSVNE1		;YES, END OF CONTIGUOUS PART OF LOW SEG HERE
	TRC	T1,PG.BDY	;END OF SECTION?
	TRCE	T1,PG.BDY	;?
	AOJA	T1,HSVNE0	;NO, CHECK NEXT
	SETZ	T2,		;WRAP IT AROUND (SINCE TRYING TO START A NEW
				;SEGMENT, CKNZ1 SHOULD FAIL LATER ANYWAY)
	POPJ	P,		;RETURN

HSVNE1:	TRNN	T1,400		;ABOVE PAGE 400 IN SECTION?
	TRZ	T1,PG.BDY	;NO, START AT 400
	TRO	T1,400		;..
	LSH	T1,P2WLSH	;CONVERT TO SECTION
	HRRZ	T2,T1		;PUT SECTION RELATIVE ORIGIN ADDRESS IN T2
	POPJ	P,

HSVNS0:	EXCH	T1,T4		;RESTORE T4
	TRNE	T2,400000	;IS CONTIGUOUS LOW SEG ABOVE 400?
	AOJA	T2,CPOPJ##	;YES, USE THAT ADDRES
	MOVEI	T2,400000	;ELSE START AT 400000
	POPJ	P,		;RETURN

HSVSPY:	LDB	T2,[PSPOLH+.HBSPO(T1)] ;GET ORIGIN FROM SEGMENT TABLE
	JUMPE	T2,HSVNEW	;NOT SET UP
	LSH	T2,P2WLSH	;CONVERT TO WORD ADDR
	POPJ	P,
;ROUTINE TO GET A NEW-STYLE SAVE FILE:
;
;
;AC USAGE:
;
;	AC		CONTENTS
;
;	P1		LH = FLAGS
;			RH= POINTER TO CURRENT DIRECTORY
;
;	P2		LH = CURRENT FILE PAGE # FOR INPUT FILE
;			RH = DIRECTORY LENGTH COUNTER
;
;	P3		1ST WORD OF CURRENT DIRECTORY ENTRY
;
;	P4		2ND WORD OF CURRENT DIRECTORY ENTRY
;
;
;IT IS POSSIBLE (THOUGH UNLIKELY) THAT THERE ARE MORE THAN ONE 
; DIRECTORY PAGE WHICH HAS TO BE READ. IN THAT CASE, ALL OF THEM
; (THERE MUST BE NO MORE THAN THREE) ARE READ IN INITIALLY BEFORE
; ANY PROCESSING OF THE SAVE FILE BEGINS. THE POINTER TO
; THE 2ND DIRECTORY PAGE IS KEPT IN SGANAM, THE POINTER TO THE 3RD
; PAGE IS IN SGAEXT. WHEN THE PROCESSING OF THE 1ST DIRECTORY PAGE
; IS COMPLETED, THE PAGE IN P1 IS DESTROYED, THE ONE IN
; SGANAM IS MOVED TO P1, AND SGAEXT IS MOVED TO SGANAM.
;
;
;IT ALSO MAY OCCUR THAT A PAGE WHICH IS ABOUT TO BE READ
; IN FROM THE SAVE FILE IS GOING TO OVERLAP ONE OF THE
; DIRECTORY PAGES. IN THAT CASE, THE DIRECTORY PAGE IS MOVED
; TO A FREE PAGE, AND THE NEW PAGE IS READ IN WHERE THE DIRECTORY
; PAGE USED TO BE.
;
;
;THE BASIC ALGORITHM IS AS FOLLOWS:
;
; 1 )	READ IN DIRECTORY PAGE(S) AND STORE POINTER(S) TO IT
; 2 )	COMPUTE # OF PAGES IN CORE IMAGE, AND RANGE OF HIGH SEG
; 3 )	(NON-VM) ALLOCATE CORE FOR ENTIRE FILE AND MOVE DIRECTORY TO TOP OF CORE
; 4 )	GET A DIRECTORY ENTRY
; 5 )	(VM) MOVE DIRECTORY PAGE IF NEW ENTRY WILL OVERLAP IT.
; 6 )	(VM) ALLOCATE CORE FOR PAGES.
; 7 )	INPUT PAGES FROM FILE
; 8 )	(VM) IF FILE GREATER THEN PHYSICAL LIMIT, PAGE OUT PAGES
; 9 )	IF MORE ENTRIES IN DIRECTORY, GO TO STEP 3.
;10 )	(NON-VM) GET RID OF EXTRA CORE, IF NECESSARY, AND CLEAR DIRECTORY (KA ONLY).
;11 )	PERFORM REMAP IF HIGH SEG WAS READ IN
REPEAT 0,<


	***** EXPLANATION OF "GET" FOR EXE FILES *****



The algorithm to get an EXE file is straightforward  in  the
simple  case, and quite complicated in some rare cases.  The
primary problem is obviously the placement and  manipulation
of the directory.
For VM systems, the directory can be longer than  one  page;
for  non-VM  systems,  we have restricted this length to one
page (however, this restriction can be changed in the future
if customer reaction demands it).
For non-VM systems, the directory  is  initially  read  into
page 1 on a GET.  On a GETSEG, it is read into the next page
above the existing low seg (on a KA,  this  means  that  two
extra pages must be allocated).
For VM-systems, the entire directory is read  into  as  many
pages  as  is necessary (pointers to the directory pages are
kept in P1, and the first two words  of  the  user's  shadow
AC's).   As  the  file pages are read into core later, these
directory pages are shuffled around if necessary,  in  order
to  avoid  being  destroyed  by the incoming pages.  As each
directory page is scanned, it is removed from the  page  map
to make room for the file pages.  The only exception to this
rule is when the file fits precisely into available core, in
which  case  the  last  file  page  is read in over the last
directory page.
For non-VM systems, the core allocation algorithm  is  quite
different from that on VM-systems.  The technique chosen was
to allocate all required core before any part of the file is
read  in,  and  then to BLT the directory to the top of that
core.  There were two other algorithms which were considered
but rejected for the following reasons:
          1 )  Keep directory in user AC's
               -eliminates possibility  of  zero-compression
          because directory must be kept very short
               -eliminates   full   file    transportability
          between systems
          2 )  Allocate core on a per-directory-entry basis,
          get  one  extra  page  of core each time, and move
          directory to free core above each core block
               -requires   excessive    memory    management
          overhead
               -requires (possibly) many useless BLT's
               -eliminates possibility of files as large  as
          CORMAX
The  core  allocation  algorithm  is  complicated   by   the
difference between units of allocation of the KA/KI, and the
possibility that the operation  being  performed  may  be  a
GETSEG.   Also, for very small files (e.g.  those which only
contain page zero), extra pages must be allocated  for  page
zero (because input cannot be done directory into page zero)
and for the directory.  The core allocation  algorithm  then
becomes:
          1 )  On a GETSEG, allocate # of pages in high  seg
          minus  one (minus two on KA).  However, on KA's if
          the high seg is less than  three  pages  long,  no
          extra core must be allocated.
          2 )  On a GET, allocate total # of pages  in  file
          minus two (for directory and page zero).  However,
          allocate at least one page (for a grand  total  of
          three  pages) to allow for moving of page zero and
          the  directory.   These  extra  pages  are   later
          flushed.
The basic processing of the file pages is  almost  identical
for non-VM and VM systems with the following exceptions:
          1 )   page 0 is read into page 1  and  BLTed  down
          for  non-VM,  and  into a random free page for VM.
          Only those locations above JOBDDT## are  moved  down
          into physical page zero.
          2 )  VM must be able to read a page from the  file
          immediately  after creating it in order to page it
          out if a user's physical limit is to  be  exceeded
          by  the  file.   In  most  cases, though, all core
          pages for a given directory descriptor are created
          before  any  of  the  corresponding file pages are
          read in.
          3 )  VM systems read the high  seg  directly  into
          the  process  page  number  specified  in the file
          directory.   Non-VM  systems  maintain  a   moving
          pointer  (in the left half of SGAHGH) which points
          to the next low seg page into which the  high  seg
          is  to be read.  This pointer is contually updated
          as each block of the high seg is read in (the high
          seg  may  have  more than one directory descriptor
          because of allocated-but-zero pages).   Therefore,
          the process page number is essentially ignored.
          4 )  VM systems must delete  the  directory  after
          processing  unless  the last page was read in over
          it.   On  non-VM  KI  systems,  the  directory  is
          guaranteed to be overwritten by the last page read
          in.  On non-VM KA systems, this also occurs if the
          number  of  pages in the file was even.  If it was
          odd, the directory  remains  intact  and  must  be
          cleared to zeroes.
          Please notE that EXE files  are  not  supported  on
          DECtape  at  all.   This  is  due  to the inherent
          difficulties in doing so and  the  fact  that  EXE
          files   are   not  transportable  between  certain
          devices anyway.  Also,  EXE  files  which  reflect
          "virtual"   core   images  are  not  supported  on
          Magtape.
>;END OF REPEAT 0
;ROUTINE TO READ IN PART OR ALL OF AN "EXE" SAVE FILE
;
;CALL:
;	MOVSI	P1,FLAGS
;	PUSHJ	P,GETEXE
;	HERE
;
;
;FLAGS: (THESE ARE DEFINED IN COMCON)
;GTLOW		GET THE LOW SEGMENT
;GTHGH		;GET THE HIGH SEGMENT
;GTBTH		;GET BOTH SEGMENTS


;FIRST, WE WILL READ IN ALL THE DIRECTORY PAGES FOR THE SAVE FILE.
;WHEN THIS PAGE OF CODE IS THRU, THE DIRECTORIES WILL BE IN CORE
; AND THE POINTERS TO THEM (OR "IT") WILL BE IN P1,P2,P3.
GETEXE::PUSH	P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
	PUSH	P,.JDAT+JOBUAL##+4 ; LOCATIONS
	PUSH	P,.JDAT+JOBUAL##+5 ; ..
	PUSH	P,.JDAT+JOBUAL##+6 ; ..
	SETZB	P2,.JDAT+SGAEND## ;CLEAR IOWD
	SETZB	P3,DEVISN(F)	;CLEAR AC'S WHERE DIRECTORY POINTERS WILL GO
	DMOVEM	P2,.JDAT+SGANAM## ;DIDN'T HAVE TO READ OVER THE DIRECTORY PAGE
	PUSHJ	P,GETDRP##	;GET A FREE PAGE FOR DIRECTORY
	  JRST	NEED1P		;CAN'T--REPORT ERROR
	MOVEI	T1,(P3)		;GET PAGE #
	PUSHJ	P,CRPAGE##	;CREATE THIS PAGE
	  CAIA
	JRST	MORDR2		
	PUSHJ	P,PAGLOW##	;YES--PAGE OUT THE LOW SEG
	MOVEI	T1,(P3)		;PAGLOW SMASHES T1
	PUSHJ	P,CRPAGE##	;TRY TO CREATE PAGE AGAIN
	  JRST	NEED1P		;COULN'T--ABORT USER
MORDR2:	LSH	T1,P2WLSH	;MAKE INTO AN ADDRESS
	HRRM	T1,P1		;PRESERVE IT
	PUSHJ	P,F1IOWD	;SET UP AN IOWD FOR THIS PAGE
	PUSHJ	P,RDSTUF	;READ 1ST PGE FROM FILE INTO THIS PAGE
	HRR	M,P1		;GET ADDRESS OF DIRECTORY
	PUSHJ	P,GETWDU##	;GET WORD FROM DIRECTORY
	HLRZ	T2,T1		;GET CODE
	CAIE	T2,SV.DIR	;IS THIS THE DIRECTORY?
	JRST	NOTEXE		;NO, REPORT ERROR
	HRRZ	T3,T1		;GET # OF WORDS IN DIRECTORY
	LSH	T3,W2PLSH	;=# OF DIRECTORY PAGES -1
	TRNN	T1,1		;LENGTH MUST BE ODD
	JRST	BADDIR		;EVEN LENGTH
	CAILE	T3,^D64
	JRST	EXEBIG		;IT ISN'T, FLUSH USER
	PUSHJ	P,GTDIRW	;GET 1ST WORD FROM DIRECTORY
	MOVEI	P2,-1(T1)	;SAVE LENGTH FOR LATER
	JUMPE	P2,BADDIR	;DON'T ALLOW NULL DIRECTORIES

;FALL THRU TO NEXT PAGE...

;STILL IN IFN FTEXE CONDITIONAL...
;WE MUST NOW COMPUTE HOW MUCH CORE WE ARE GOING TO NEED FOR THESE
; SEGMENTS, AND THE UPPER AND LOWER LIMITS OF THE HIGH SEG.
;WE WILL DO THIS BY CYCLING THRU THE DIRECTORY AND ADDING UP
; THE NUMBER OF PAGES THAT WE WILL NEED TO ALLOCATE FOR
; THIS FILE.
;
;P1 HAS A POINTER TO THE 1ST DIRECTORY PAGE IN ITS RH
;SGANAM HAS POINTER TO 2ND PAGE (IF ANY)
;SGAEXT HAS POINTER TO 3RD PAGE (IF ANY)
;
;
;THIS ROUTINE ASSUMES THAT ALL ENTRIES FOR THE HIGH SEG
; WILL APPEAR SEQUENTIALLY IN THE DIRECTORY IN INCREASING PAGE
; ADDRESSES. THAT IS, IF WE FIND A HIGH SEG ENTRY, THEN IF WE FIND
; ANOTHER HIGH SEG ENTRY LATER ON, THE SECOND SET OF HIGH SEG PAGES
; MUST BE CONTIGUOUS TO THE FIRST SET OF HIGH SEG PAGES.
;
;WE WILL USE T3 TO HOLD THE TOTAL # OF PAGES NEEDED
; AND T4 = START OF HISEG,,END OF HISEG
	SETZB	T3,T4		;CLEAR OUT THESE AC'S
CKSIZ0:	PUSHJ	P,GTDIRE	;GET THE NEXT DIR ENTRY IN P3,P4
	  JRST	CKSIZ3		;NO MORE LEFT, WE ARE THRU
	PUSHJ	P,WANTIT	;BUT DO WE WANT THIS SEGMENT?
	  JRST	CKSIZ0		;NO, IGNORE IT
	LDB	T2,[POINT 9,P4,8] ;GET REPEAT COUNT
	ADDI	T3,1(T2)	;BUMP TOTAL PAGE COUNT
	JUMPGE	P3,CKSIZ0	;DON'T CHECK LIMITS IF NOT HIGH SEG
	ADDI	T2,(P4)		;COMPUTE LAST PAGE # IN THIS ENTRY
	JUMPE	T4,[HRL	T4,P4	;IF THIS IS THE 1ST HISEG ENTRY,
		    JRST CKSIZ1];SAVE START ADDR AND GO ON
	MOVEI	T1,1(T4)	;# OF NEXT CONTIGUOUS PAGE IN HIGH SEG
	CAIE	T1,(P4)		;IS THIS ENTRY CONTIGOUS WITH PREVIOUS
				; HIGH SEG ENTRY? 
	JRST	BADDIR		;NO, BAD FORMAT FOR DIRECTORY
CKSIZ1:	HRR	T4,T2		;RESET HIGH SEG END PAGE #
	JRST	CKSIZ0		;IT'S OK
;COME HERE WHEN WE HAVE FINISHED SCANNING
; THE DIRECTORIES. WE MUST NOW ROTATE THE DIRECTORY
; POINTERS UNTIL THEY ARE BACK IN THEIR ORIGINAL POSITION.
CKSIZ3:	TRZ	P1,EXESIZ-1	;POINT CURRENT DIR POINTER TO START OF PAGE
	TLZE	P1,SV%DWO##	;MORE THAN ONE PAGE DIRECTORY?
	PUSHJ	P,[PUSHJ P,SAVT## ;IMPORTANT NUMBERS
		   PUSH P,P1	; ..
		   USETI 1	;BACK TO THE BEGINNING OF THE FILE
		   PUSHJ P,SGIOCK## ;MAKE SURE THERE WERE NO I/O ERRORS
		   HRRZ T1,(P)	;FOR IOWD
		   PUSHJ P,F1IOWD ;BUILD AND STORE THE IOWD
		   PUSHJ P,RDSTUF ;READ THE FIRST PAGE OF THE EXE DIRECTORY
		   MOVEI T1,1	;NOW INDICATE NOT READING THE FILE SEQUENCIALLY (GTDIRW)
		   MOVEM T1,.JDAT+SGAEXT## ;CURRENT DIRECTORY POSITION
		   JRST P1POPJ##] ;CONTINUE
;FOR NON-VM SYSTEMS, WE MUST NOW ALLOCATE ENOUGH CORE FOR
; THE ENTIRE EXE FILE, AND MOVE THE DIRECTORY TO THE TOP OF THAT CORE.
; THE DIRECTORY WILL THEN BE OVER-WRITTEN BY THE LAST PAGE
; WHICH IS READ IN FROM THE FILE. HOWEVER, IF A LOW SEGMENT
; MUST BE GOTTEN, AND THE TOTAL # OF PAGES IN THE FILE IS LESS 
; THAN 3, WE MUST ALLOCATE SOME EXTRA CORE BECAUSE PAGE ZERO MUST
; BE READ INTO PAGE 1 AND BLT'ED DOWN WITHOUT CLOBBERING THE
; DIRECTORY.
;
;FOR VM-SYSTEMS, WE MUST NOW DETERMINE IF THIS FILE WILL EXCEED
; THE USER'S PHYSICAL LIMIT AND SET SOME FLAGS APPROPRIATELY.
; ALSO, WE MAY HAVE TO PAGE OUT HIS LOW SEG ON A "VIRTUAL" GETSEG.
;
;WE WILL FIRST COMPUTE SOME VALUES WHICH WE WILL SAVE UNTIL THE
; REMAP WHEN THEY WILL BE NEEDED. THESE ARE AS FOLLOWS:
;	SGAHGH = 1ST PAGE OF HIGH SEG,,LENGTH (IN PAGES) OF HIGH SEG
;	SGALOW = # OF PAGES REQUIRED FOR ENTIRE FILE
;
;FOR VM SYSTEMS, THE STARTING ADDRESS OF THE HIGH SEG WILL
; BE THE ACTUAL USER VIRTUAL PAGE NUMBER FOR THE START
; OF THE HIGH SEG. FOR NON-VM SYSTEMS, THIS PAGE NUMBER WILL BE
; THE LOW SEG PAGE INTO WHICH THE HIGH SEG WILL BE READ,
; AND THEN REMAPPED TO ITS ACTUAL ADDRESS.
;
;
CKSIZ4:	HLRZ	T1,T4		;GET 1ST PAGE OF HIGH SEG
	SKIPE	T1		;IF NO HIGH SEG, DON'T SUBTRACT
	SUBI	T4,-1(T1)	;LAST-FIRST-1 YIELDS # OF PAGES IN HIGH SEG
	MOVEM	T4,.JDAT+SGAHGH## ;SAVE START,,LENGTH OF HIGH SEG
	MOVEM	T3,.JDAT+SGALOW## ; AND TOTAL PAGES IN CORE IMAGE
	PUSHJ	P,GTDIRW	;GET HEADER WORD FROM DIRECTORY
	MOVEI	P2,-1(T1)	;PUT LENGTH OF DIRECTORY ENTRIES IN P2
	HRLI	P2,1		;SO THAT SKPBLK WILL SKIP THE DIRECTORY
	MOVE	J,.CPJOB##	;SET UP JOB NUMBER
	PUSHJ	P,FNDPDS##	;GET THIS GUY'S PDB
	MOVE	T3,.JDAT+SGALOW## ;CHECK # PAGES
	PUSHJ	P,GSIZI##	;IS THERE ROOM?
	  JFCL			;NO
	TLO	P1,GT%PLE##	;SET BIT TO INDICATE THAT THE
				; PHYSICAL LIMIT IS EXCEEDED, SO WE
				; WILL PAGE OUT ALL LOW SEG PAGES
				; AS WE READ THEM IN LATER.
	HLRZ	T1,.PDCVL##(W)	;GET CURRENT VIRTUAL LIMIT
	TLNE	P1,GT%PLE##	;ANY ROOM PHYSICALLY?
	JUMPE	T1,NEEDNP	;NO, PUNT IF NO VIRTUAL AVAILABLE
	CAMGE	T1,.JDAT+SGALOW## ;IS THAT LESS THAN SIZE OF FILE?
	JUMPN	T1,NEEDNP	;NO, CAN'T POSSIBLY FIT FILE IN
	MOVE	J,.CPJOB##	;GET JOB NUMBER
	PUSHJ	P,SEGSIZ##	;GET LOWSEG SIZE
	TLNE	P1,GTMRG##	;THIS A MERGE?
	JRST	CKSIZ5		;YES, DON'T SUBTRACT OUT PAGE 0
	TLNN	P1,GTLOW##	;IS THIS A GETSEG?
	TLNN	P1,GTHGH##	;(LOW OFF AND HGH ON)
	SOS	T2		;NO, PAGE 0 WILL BE OVERWRITTEN
CKSIZ5:	SUBI	T2,UPMPSZ##	;SUBTRACT UPMP OUT ALWAYS
	TLNN	P1,SV%FUL##	;IF DIDN'T PAGE OUT DIRECTORY PAGE
	SOS	T2		;DON'T INCLUDE IT EITHER
	ADD	T2,.JDAT+SGALOW## ;ADD TO NEW HIGH SEG SIZE
	CAMGE	T1,T2		;SEE IF THERE'S ENOUGH ROOM
	JUMPN	T1,NTROOM	;NO
	TLNN	P1,GT%PLE##
	SKIPE	.USVRT		;IS THIS A VIRTUAL GUY?
	TDZA	T1,T1		;YES, PAGE OUT LOW SEG
	SETO	T1,		;DON'T PAGE OUT LOW SEG
	MOVSI	T2,(UP.MPF+UP.GET) ;GETTING GET OR PFH?
	TDNE	T2,.USBTS	;IF SO, PAGE OUT THE LOW SEG
	TLZN	P1,GT%PLE##	;BUT NOT PFH
	SKIPN	T1		;WANT TO PAGE OUT LOW SEG?
	PUSHJ	P,PAGLOW##	;YES, PAGE OUT THE LOW SEGMENT

;THIS IS THE MAIN LOOP FOR DIRECTORY PROCESSING
;THIS LOOP FETCHES ONE DIRECTORY ENTRY AND PROCESSES ALL PAGES
; CONTAINED IN THAT ENTRY.
GTLOOP:	PUSHJ	P,GTDIRE	;GET NEXT DIRECTORY ENTRY
	  JRST	GETFIN		;NO MORE, WE ARE THRU
	PUSHJ	P,WANTIT	;DO WE WANT THIS ENTRY?
	  JRST	GTLOOP		;NO, IGNORE THIS DIRECTORY ENTRY
	HRRZ	T1,P1		;GET CURRENT DIRECTORY POINTER
	TLZ	P1,GT%DAF##	;ASSUME PAGES DESCRIBED IN THIS POINTER WON'T
				;OVERLAP DIR
	PUSHJ	P,CKRADR	;WILL IT BE OVERWRITTEN BY THESE PAGES?
	  PUSHJ	P,MOVDIR	;YES, WE MUST MOVE IT
	MOVE	T1,DEVMOD(F)	;DEVICE CHARACTERISTICS
	TLNN	T1,DVDSK	;AS DISK?
	TLO	P1,GT%DAF	;NO, MUST DO ONE PAGE AT A TIME (NO RANDOM ACCESS)

;FALL THRU TO NEXT PAGE...

;STILL IN IFN FTEXE  CONDITIONAL...
;COME HERE IF NO DIRECTORY PAGES ARE ABOUT TO BE OVER-WRITTEN
;WE CAN NOW READ IN THE SAVE FILE.
;IF THIS ENTRY CONTAINS PAGE ZERO, WE MUST DO SOME SPECIAL
; PROCESSING WHICH IS ON THIS PAGE. IF PAGE ZERO IS NOT
; WITHIN THIS ENTRY, WE SKIP TO THE MAIN LOOP AT "NOTP0".
;
;
	TRNE	P4,-1		;IS THIS PAGE 0?
	JRST	NOTP0		;NO
	SKIPE	.USUSN		;PUT FILE IN SECTION 0?
	TLNN	P1,GTMRG##	;IS THIS A MERGE?
	CAIA			;PUT IN SECTION 0 OR ISN'T A MERGE
	JRST	NOTP0		;MERGING INTO NZS, PUT P0 WHERE IT SHOULD BE
	PUSHJ	P,GTFREP##	;YES, WE CAN'T READ DIRECTLY
				; INTO PAGE 0, SO WE MUST CREATE A
				; DUMMY PAGE INTO WHICH WE WILL READ
				; THIS DATA PAGE. THEN WE WILL MOVE
				; THIS PAGE TO PAGE 0 AND EVERYTHING
				; WILL BE OK.
	   JRST	NEED1P		;COULDN'T GET FREE PAGE
	PUSHJ	P,CRPAGE##	;CREATE IT
	  JRST	NEED1P		;COULDN'T
	LSH	T1,P2WLSH	;PAGE ADDRESS
	PUSH	P,T1		;SAVE PAGE ADDRESS FOR A SEC...
	PUSHJ	P,SKPBLK	;MAKE SURE WE'RE AT THE RIGHT PLACE
	MOVE	T1,(P)		;RESTORE ADDRESS
	PUSHJ	P,F1IOWD	;STORE THE IOWD
	PUSHJ	P,RDSTUF	;READ PAGE FROM SAVE FILE
	HRLZ	T1,0(P)		;PAGE ADDRESS IN LEFT HALF, 0 IN RH
	ADD	T1,[JOBUAL##+.JBLUL##,,JOBUAL##+.JBLUL##] ;SET UP BLT AC
	TLNN	P1,GTMRG##	;DON'T WIPE PAGE 0 ON A MERGE
	EXCTUU	<BLT T1,EXESIZ-1>
	POP	P,T1
	TLNE	P1,GTMRG##	;MERGING?
	SKIPE	.JDAT+.JBPFH##	;YES, ALREADY HAVE A PFH?
	SKIPA	T2,.JDAT+.JBPFH## ;NOT MERGE OR ALREADY HAVE A PFH
	UMOVE	T2,.JBPFH##(T1)	;MERGING PFH, GET ITS ADDRESS
	MOVEM	T2,.JDAT+.JBPFH## ;STORE ADDRESS OF PFH
	TLNE	P1,GTMRG##	;MERGE UUO?
	SKIPN	.JDAT+.JBDDT##	;YES, DDT ALREADY AROUND?
	EXCTUX	<SKIPA T2,.JBDDT##(T1)> ;NO, SET DDT'S ADDRESS
	JRST	HAVDR6		;YES, ALL DONE
	MOVEM	T2,.JDAT+.JBDDT##
	MOVEM	T2,USRDDT##	;SAVE IT OVER CONTEXT SWITCH
	UMOVE	T2,.JBBPT##(T1)	;GET DDT'S UNSOLICITED BREAKPOINT ENTRY
	MOVEM	T2,.JDAT+.JBBPT## ;AND SET IT UP TOO
	TLNE	P1,GTMRG##	;MERGING?
	JRST	HAVDR6		;ALL DONE WITH THE MERGE
	SETZM	.JDAT+.JBHSO##	;INITIALLY CLEAR JOBHSO
	UMOVE	T2,JOB41##(T1)	;RESTORE JOB41
	MOVEM	T2,.JDAT+JOB41##;
HAVDR6:	PUSH	P,T1		;SAVE T1
	TLNN	P1,GTMRG##	;MERGING?
	PUSHJ	P,CRESP0	;NO, CREATE THE SECTION AND COPY PAGE 0 TO IT
	POP	P,T1		;RESTORE T1
	PUSHJ	P,ZAPPAG##	;DESTROY IT
	  JRST	GTABRT##	;COULDN'T DO IT FOR SOME REASON
	ADD	P2,[1,,0]	;CURRENT LOCATION ON DEVICE
	AOS	P3		;BUMP FILE PAGE #
	ADD	P4,[777000,,1]	;INCR. PROCESS PAGE NO, DECR COUNT
	TLC	P4,777000	;IF ONLY PAGE 0, GO BACK FOR MORE
	TLCN	P4,777000
	JRST	GTLOOP

;IF MORE IN THIS DIRECTORY ENTRY, FALL THRU TO NEXT PAGE...
	
;COME HERE IF THE GROUP OF PAGES THAT WE ARE ABOUT TO FETCH
; FROM THE SAVE FILE DO NOT INCLUDE ANY OF THE DIRECTORY PAGES,
; OR PAGE ZERO.

NOTP0:	PUSHJ	P,SKPBLK	;POSITION OURSELVES ON THE DEVICE
	LDB	T3,[POINT 9,P4,8] ;GET REPEAT COUNT
	PUSHJ	P,GETSSN	;GET USE SECTION
	  JRST	[REPEAT 0,<SKIPGE .USUSN	;COMMAND OR UUO?
		 JRST [DPB T1,[POINT 9,P4,26] ;UUO, DON'T RELOCATE
		       JRST NOTP00]> ;CONTINUE
		 LSH T1,S2PLSH	;SECTION NUMBER IN SECTION FIELD
		 ADD P4,T1	;RELOCATE
		 JRST .+1]	;CONTINUE
NOTP00:	HRRZ	T1,P4		;..AND PROCESS PAGE #
	PUSH	P,T3		;SAVE REPEAT COUNT
NOTP01:	PUSH	P,T1		;AND PAGE #
	MOVE	T2,.JDAT+SGANAM## ;THIS COULD BE THE DIRECTORY PAGE
	CAIN	T1,(T2)		;IS IT?
	JRST	NOTP02		;YES, JUST SKIP IT - GETFIN WILL FIX IT UP
	TLNE	P3,SV%SHR	;YES, SHARABLE?
	JRST	.+3		;NO, DON'T CREATE THIS PAGE ON DISK
	TLNE	P1,GT%PLE##	;PHYS. LIMIT EXCEEDED?
	TLO	T1,(1B1)	;YES, CREATE THIS PAGE ON DISK
	TLNN	P1,GT%DAF##	;PAGES IN THIS ENTRY OVERLAP THE EXE DIRECTORY?
	JRST	NOTP03		;NO, CREATE ALL THE PAGES IN ONE FELL SWOOP
	PUSHJ	P,CRPAGE##	;CREATE THIS PAGE
	  JRST	[MOVE T2,.JDAT+SGASAV## ;ERROR CODE
		 CAIE T2,PAGCE% ;IS THIS AN OVERLAP ERROR?
		 JRST NEED1P 	;NO,SOME OTHER TYPE OF ERROR
		 JRST OVRERR]	;NO, REPORT THE ERROR
	TRNE	P3,-1		;SKIP IF ALLOCATED-BUT-ZERO PAGE
	TLNN	P1,GT%DAF##	;ARE WE READING 1 PAGE AT A TIME?
	JRST	NOTP02		;NO, GO ON
	LSH	T1,P2WLSH	;RETURN WITH T1=PAGE #, FIND ADDRESS
	PUSHJ	P,F1IOWD	;MAKE AND STORE AN IOWD
	PUSHJ	P,RDSTUF	;NO, MUST READ PAGES IN AS WE CREATE THEM
	TLNE	P3,SV%HIS!SV%WRT ;IF HIGH SEG, REMAP TAKES CARE OF THIS
	JRST	NOTP0A		;HIGH SEG OR WRITE-ENABLED
	MOVE	T2,(P)		;PAGE #
	TLO	T2,(PG.GAF)	;FLAG TO WRITE-LOCK
	MOVSI	T1,.PAGWL	;WRITE-LOCK/ENABLE FUNCTION
	PUSHJ	P,PAGUUO##	;DO THE PAGE UUO
	  JRST	WLERR		;OOPS
NOTP0A:	MOVE	T1,(P)		;GET SAVED PAGE #
	MOVE	J,.CPJOB##	;MAKE SURE WE HAVE THE RIGHT JOB
	TLNE	P1,GT%PLE##	;PHYS. LIMIT EXCEEDED?
	TLNE	P3,SV%SHR	;AND NON-SHARABLE HIGH SEG?
	SKIPA			;NO
	PUSHJ	P,PAGOUT##	;YES, PAGE IT OUT
	  JFCL			;SHARABLE OR COULDN'T PAGE OUT
NOTP02:	POP	P,T1		;RESTORE PAGE # JUST CREATED
	SOSL	(P)		;MORE PAGES TO CREATE?
	AOJA	T1,NOTP01	;YES, GO DO NEXT PAGE
	POP	P,(P)		;POP OFF JUNK
	JRST	NTRYLP		;FINISHED THIS EXE ENTRY
NOTP03:	MOVE	T2,(P)		;STARTING PAGE NUMBER
	HLL	T2,T1		;BITS FOR CREATE AS COMPUTED ABOVE
	MOVE	T3,-1(P)	;NUMBER OF PAGES REPRESENTED BY THIS ENTRY - 1
	MOVSI	T1,.PAGCD	;PAGE UUO FUNCTION
	MOVNI	T3,1(T3)	;NEGATIVE NUMBER OF PAGES TO CREATE
	PUSHJ	P,PAGUUN##	;CREATE THE NECESSARY NUMBER OF PAGES
	  JRST	[MOVE T2,.JDAT+SGASAV## ;ERROR CODE
		 CAIE T2,PAGCE% ;IS THIS AN OVERLAP ERROR?
		 JRST NEED1P 	;NO,SOME OTHER TYPE OF ERROR
		 JRST OVRERR]	;NO, REPORT THE ERROR
	LDB	T2,[POINT 9,P4,8] ;NO, GET REPEAT COUNT AGAIN
	AOS	T2		;=# OF PAGES IN GROUP
	HRRZ	T1,P4		;GET 1ST PAGE #
	LSH	T1,P2WLSH	;=START ADDRESS OF GROUP
	LSH	T2,P2WLSH	;=LENGTH OF SEGMENT
	PUSHJ	P,FSIOWD	;SETUP THE IOWD
	TRNE	P3,-1		;UNLESS PAGES ARE ALLOCATED-BUT-ZERO...
	PUSHJ	P,RDSTUF	;READ IN ENTIRE GROUP OF PAGES
	TLNE	P3,SV%HIS!SV%WRT ;IF HIGH SEG, REMAP TAKES CARE OF THIS
	JRST	NOTP0B		;HIGH SEG OR WRITE-ENABLED
	MOVE	T2,(P)		;STARTING PAGE NUMBER
	TLO	T2,(PG.GAF)	;WRITE-LOCK BIT
	MOVE	T3,-1(P)	;NUMBER OF PAGES REPRESENTED BY THIS ENTRY - 1
	MOVSI	T1,.PAGWL	;PAGE UUO FUNCTION
	MOVNI	T3,1(T3)	;NEGATIVE NUMBER OF PAGES TO WRITE-LOCK
	PUSHJ	P,PAGUUN##	;WRITE-LOCK THE NECESSARY NUMBER OF PAGES
	  JRST	WLERR		;WRITE-LOCK
NOTP0B:	POP	P,T2		;STARTING PAGE NUMBER
	POP	P,T3		;NUMBER OF PAGES REPRESENTED BY THIS ENTRY - 1
	TRNN	P3,-1		;IF ABZ,
	JRST	NTRYLP		; DONE WITH ENTRY
	MOVSI	T1,.PAGIO	;SETUP TO PAGE OUT THE PAGES
	TLO	T2,(PG.GAF+PG.IDC) ;PAGE OUT AND DON'T CARE IF NOT IN
	MOVNI	T3,1(T3)	;NUMBER OF PAGES
	MOVE	J,.CPJOB##	;SUPERSTITION PERHAPS?
	TLNE	P1,GT%PLE##	;DON'T PAGE THEM OUT IF NO NEED TO GO VIRTUAL
	TLNE	P3,SV%SHR	;ALSO, DON'T PAGE THEM OUT IF IN A SHARABLE HI SEG
	CAIA			; ..
	PUSHJ	P,PAGUUN##	;OUT THEY GO IN ONE FELL SWOOP
	  JFCL			;OH WELL, WE TRIED
;HERE AFTER PROCESSING OF EACH DIRECTORY ENTRY
NTRYLP:	LDB	T1,[POINT 9,P4,8] ;GET REPEAT COUNT AGAIN
	MOVSI	T1,1(T1)	;# OF PAGES,,0
	TRNE	P3,-1		;IF THESE PAGES WERE ABZ, DON'T...
	ADD	P2,T1		;BUMP CURRENT LOCATION POINTER
	TLNE	P3,SV%SHR	;DID WE SEE A SHARABLE HIGH SEG?
	TLO	P1,SV%SHR	;YES, REMEMBER THAT FACT
	JRST	GTLOOP		;GO BACK FOR MORE
;COME HERE WHEN THE ENTIRE SAVE FILE HAS BEEN READ IN...
;
GETFIN:	LDB	T1,[POINT 6,.USUSA,5] ;GET LENGTH OF OLD ENTRY VECTOR
	CAIE	T1,40		;SET BY /START SWITCH?
	SETZM	.USUSA		;NO, FORGET ABOUT THE OLD VALUE
	PUSHJ	P,GTDIRW	;THERE MIGHT BE AN ENTRY VECTOR
	HLRZS	T1		;CODE
	CAIE	T1,SV.STA	;ENTRY VECTOR CODE?
	JRST	GETFI2		;NO
	PUSHJ	P,GTDIRW	;GET NEXT WORD
	MOVE	T2,T1		;SAVE IT FOR THE MOMENT
	PUSHJ	P,GTDIRW	;GET STARTING ADDRESS OR ENTRY VECTOR ADDRESS
	TLZE	T1,770000	;FUNNY BITS ON IN ADDRESS?
	JRST	GETFI2		;YES, PRETEND WE NEVER SAW IT
	SKIPE	T2		;HAVE A LENGTH?
	CAIN	T2,(JRST)	;IF "JRST" TYPE ENTRY VECTOR,
	JRST	GETFI1		; JUST STORE START ADDRESS
	SKIPL	T2		;MUST BE POSITIVE
	CAILE	T2,37		;AND WITHIN OUR RANGE
	JRST	GETFI2		;PRETEND WE NEVER SAW IT
	TRO	T2,40		;TURN ON SIGN BIT TO INDICATE REAL ENTRY VECTOR
	DPB	T2,[POINT 6,T1,5] ;SAVE LENGTH OF THE ENTRY VECTOR
GETFI1:	LDB	T2,[POINT 6,.USUSA,5]	;GET LENGTH SPECIFIER FROM ENTRY VECTOR
	CAIE	T2,40		;WAS THIS SET BY THE USER'S COMMAND?
	MOVEM	T1,.USUSA	;NO, STORE THE FILE'S FOR STARTING THE PROGRAM
	JUMPGE	T1,GETFI2	;GO IF NO "REAL ENTRY" VECTOR
	LDB	T2,[POINT 6,T1,5] ;GET LENGTH OF NEW ONE AGAIN
	CAIGE	T2,42		;ENTRY VECTOR CONTAIN A REENTER ADDRESS?
	SETZM	.JDAT+.JBREN##	;NO, DON'T CONFUSE HUMANS
	SETZM	.JDAT+.JBVER##	;CLEAR THIS IN CASE NOT IN VECTOR
	CAIGE	T2,43		;ENTRY VECTOR CONTAIN A VERSION NUMBER?
	JRST	GETFI2		;NO
	PUSH	P,M		;DON'T KNOW WHETHER IT MATTERS BUT BE SAFE
	MOVE	M,T1		;ADDRESS OF THE ENTRY VECTOR
	ADDI	M,2		;ADDRESS OF THE VERSION NUMBER
	MOVE	T1,.USUSN	;GET /USE OFFSET
	LSH	T1,P2WLSH	;MAKE ADDRESS FROM PAGE
	ADD	M,T1		;GET NEW ADDRESS OF VECTOR
	TLZ	M,770000	;CLEAR OUT THE JUNK
	PUSHJ	P,PFHMWD##	;GET THE VERSION NUMBER
	  CAIA			;IGNORE ADDRESS CHECK
	MOVEM	T1,.JDAT+.JBVER## ;STORE IT WHERE HUMANS LOOK
	POP	P,M		;RESTORE M
GETFI2:	LDB	T1,[POINT 6,.USUSA,5]	;GET LENGTH CODE FOR ENTRY VECTOR
	CAIN	T1,40		;IS IT THE USER'S /START SWITCH?
	JRST	GETFI3		;YES, DON'T MODIFY IT FURTHER
	MOVE	T1,.USUSN	;GET SECTION OFFSET
	LSH	T1,P2WLSH	;IN WORDS
	SKIPN	T2,.USUSA	;IF NO START ADDRESS AT ALL,
	HRRZ	T2,.JDAT+.JBSA## ;GET IT FROM JOBDAT
	JUMPE	T2,GETFI3	;SET NO ENTRY VECTOR IF NO JOBSA
	ADD	T1,T2		;OFFSET BY SECTION
	SKIPN	.USUSA		;IF DEFAULTING,
	TRZ	T1,-1		;ONLY THE SECTION IS VALID
	MOVEM	T1,.USUSA	;SET UP AN ENTRY VECTOR
	SKIPL	T1		;IF A REAL ENTRY VECTOR,
	TRNE	T1,-1		;OR IT HAD A START ADDRESS,
	JRST	GETFI3		;JUST USE THIS
	PUSH	P,M		;OTHERWISE,
	MOVE	M,T1		;TRY TO GET IT FROM JOBDAT
	HRRI	M,.JBSA##	;IN THE APPROPRIATE SECTION
	PUSHJ	P,PFHMWD##	;FETCH
	  SETZ	T1,		;CAN'T DO IT
	POP	P,M		;RESTORE ADDRESS
	TRNN	T1,-1		;IS THERE A JOBSA IN THAT SECTION?
	SETZM	.USUSA		;NO, UN-SET THE ENTRY VECTOR
GETFI3:	SKIPN	T1,.JDAT+SGANAM## ;FILE PAGE OVERLAP THE DIRECTORY PAGE?
	JRST	GETFI5		;NO, JUST GO ZAP THE DIRECTORY PAGE
	TLNE	T1,-1		;WAS THE PAGE FROM THE FILE ABZ?
	JRST	GETFI4		;NO, GO READ THE PAGE
	TLNE	P1,GT%PLE##	;PAGE LIMIT EXECEEDED?
	JRST	[LSH T1,P2WLSH ;MAKABZ WANTS A PAGE ADDRESS
		 PUSHJ P,MAKABZ## ;YES, MAKE AN ABZ PAGE ON THE DISK
		   JFCL		;TRIED
		JRST GETFI6]	;PROCEED
	PUSHJ	P,YANKIZ##	;MAKE SURE PAGE IS IN CORE
	  JFCL			;IF IT DIDN'T WORK, THIS WILL RESULT IN AN IME
	MOVE	T1,.JDAT+SGANAM## ;PAGE NUMBER OF DIRECTORY PAGE
	S1PSHJ	ZERPAG##	;JUST CAUSE THE PAGE TO CONTAIN ZEROES
	JRST	GETFI6		;AND CONTINUE
GETFI4:	HLRZ	T1,.JDAT+SGANAM## ;FILE POSITION OF THE PAGE
	LSH	T1,2		;BLOCK NUMBER
	PUSH	P,P1		;USETI CLOBBERS P1
	USETI	1(T1)		;POSITION THE FILE TO THE PAGE THAT WAS SKIPPED
	POP	P,P1		;RESTORE P1
	PUSHJ	P,SGIOCK##	;CHECK FOR ERRORS
	HRRZ	T1,.JDAT+SGANAM## ;NOW GET PROCESS PAGE NUMBER
	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	PUSHJ	P,F1IOWD	;MAKE AND STORE AN IOWD
	PUSHJ	P,RDSTUF	;NOW THE CORE IMAGE IS COMPLETE
	JRST	GETFI6		;AND CONTINUE
GETFI5:	HRRZ	T1,P1		;GET CURRENT DIRECTORY POINTER
	PUSHJ	P,ZAPPAG##	;FLUSH THE DIRECTORY PAGE
	  JFCL
GETFI6:	TLNE	P1,SV%FUL##	;PAGE OUT A PAGE FOR THE DIRECTORY?
	PUSHJ	P,GTSAVP##	;YES, RESTORE IT THEN
	POP	P,.JDAT+JOBUAL##+6 ;RESTORE PATH BLOCK
	POP	P,.JDAT+JOBUAL##+5 ; ..
	POP	P,.JDAT+JOBUAL##+4 ; ..
	POP	P,.JDAT+JOBUAL##+3 ; ..
	HLRZ	T2,.JDAT+SGAHGH## ;GET 1ST PAGE OF HIGH SEG
	JUMPE	T2,CPOPJ##	;IF NO HIGH SEG, EXIT NOW
	PUSHJ	P,GETSSN	;GET SECTION NUMBER
	  DPB	T1,[POINT 5,T2,26] ;STORE SECTION NUMBER
	MOVE	T1,T2		;IT IS ALSO THE NEW STARTING VIRT PAGE #
	HRRZ	T3,.JDAT+SGAHGH## ;GET # OF PAGES IN HIGH SEG
	TLNE	P1,SV%SHR	;DID WE SEE A SHARABLE HIGH SEG?
	TDZA	T4,T4		;YES, T4=0
	MOVSI	T4,(1B0)	;NO, INDICATE IT TO NREMAP
;COME HERE TO REMAP HIGH SEG
	PUSH	P,.JDAT+JOBSA##	;REMAP CLEARS THESE JOB DATA LOCS
	PUSH	P,.JDAT+JOBREN##	;...
	PUSH	P,.JDAT+JOBHRL##	;...
IFN FTMP,<
	PUSHJ	P,UPMM##	;MUST HAVE THE MM TO DO THE REMAP
>
	PUSHJ	P,NREMAP##	;DO THE REMAP
	 STOPCD	.,STOP,RDS,	;++REMAP DIDN'T SKIP
	POP	P,.JDAT+JOBHRL##	;RESTORE JOB DATA LOCS
	POP	P,.JDAT+JOBREN##	;...
	POP	P,.JDAT+JOBSA##	;...
	SOS	(P)		;SINCE SHARE1 WILL EXIT TO CPOPJ1,
				; WE MUST BACK UP THE RETURN ADDR SO RETURN
				; TO CPOPJ
	JSP	T3,SHARE1	;GO SET UP JBTSGN, ETC...
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT ENTRY IS WHAT
; WE WANT
;
;CALL:
;	DMOVE	P3,DIRECTORY-ENTRY
;	PUSHJ	P,WANTIT
;	HERE IF NO
;	HERE IF YES
;
WANTIT:	TLNE	P1,GTMRG##	;MERGING?
	SKIPN	T2,.JDAT+SGANEW## ;WAS A RANGE OF PAGES SPECIFIED?
	CAIA			;NO, DO THE NORMAL THING
	JRST	WANTI1		;YES, SEE IF PAGES ARE WITHIN THE RANGE
	MOVSI	T2,GTHGH##	;ASSUME HIGH SEG
	TLNN	P3,SV%HIS	;IS THIS THE HISEG?
	MOVSI	T2,GTLOW##	;NO, SET UP LOW SEG BIT
	TDNN	P1,T2		;YES, DID WE WANT THIS SEGMENT?
	POPJ	P,		;NO
WANTI1:	HRRZ	T1,P4		;GET PROCESS PAGE #
	CAIL	T1,<MXSECN*PAGSIZ>+HLGPNO+1	;CHECK UPPER LIMIT
	JRST	BADDIR		;TOO HIGH
	TLNE	P1,GTMRG##	;MERGING?
	TRNN	T2,-1		;AND A RANGE SPECIFIED?
	JRST	WANTI3		;NOT MERGING A SPECIFIED RANGE
	PUSHJ	P,SAVT##	;NEED LOTS OF ACS, EVEN THO A SIX CHAR NAME, MUST SAVE T3
	HLRZ	T3,T2		;LOWER BOUND
	LDB	T4,[POINT 9,P4,8] ;REPEAT COUNT
	ADDI	T4,(T1)		;HIGHEST PAGE DESCRIBED IN THIS POINTER
	CAIG	T1,(T2)		;PROCESS PAGE GREATER THAN HIGHEST PAGE IN RANGE?
	CAIGE	T4,(T3)		;HIGHEST PAGE IN POINTER LESS THAN START OF THE RANGE?
	POPJ	P,		;YES TO EITHER, DON'T WANT THE PAGES
	TLO	P3,SV%WRT	;ALWAYS MERGE AS A LOW SEGMENT PAGE
	TLZ	P3,SV%CON+SV%SHR+SV%HIS
	CAILE	T3,(T1)		;IF THE RANGE DESCRIBED BY THE ENTRY,
	JRST	WANTI2		; IS COMPLETELY ENCOMPASSED BY THE USER
	CAIG	T4,(T2)		; SPECIFIED RANGE, GO GET ALL THE PAGES
	JRST	CPOPJ1##	; REPRESENTED IN THE ENTRY
WANTI2:	HLR	P4,T2		;ADJUST ENTRY TO REPRESENT USER SPECIFIED RANGE
	SUBI	T2,(T3)		;NUMBER OF PAGES TO USER UPPER BOUND
	SUBI	T4,(T3)		;NUMBER OF PAGES TO ENTRY UPPER BOUND
	CAILE	T4,(T2)		;LESSER OF THE TWO
	HRRZ	T4,T2		;NUMBER OF PAGES TO GET
	DPB	T4,[POINT 9,P4,8] ;STORE ADJUSTED REPEAT COUNT
	HLRZS	T2		;USER LOWER BOUND
	SUBI	T2,(T1)		;OFFSET TO FILE PAGE
	ADDI	P3,(T2)		;FIRST FILE PAGE
	JRST	CPOPJ1##	;AND GIVE WANTIT IT RETURN
WANTI3:	JUMPL	P3,WANTI4	;PROCEED IF HIGH SEG
	TRNN	P4,-1		;IS THIS PAGE 0?
	TLNE	P3,SV%WRT	;YES, PAGE MUST BE WRITABLE THEN
	JRST	CPOPJ1##	;IT IS WRITABLE OR NOT PAGE 0
	JRST	BADDIR		;ELSE FLUSH USER

WANTI4:	TLNE	P3,SV%SHR	;THIS PAGE SHARABLE?
	TLON	P1,GT%S1S##	;YES, SAW 1 SHARABLE PAGE
	TLNN	P1,GT%S1S##	;1ST SHARABLE PAGE, OR NOT SHARABLE
	TLOA	P1,GT%GTH##	;THIS PAGE IS OK, SAW A HI-SEG PAGE
	TLON	P1,GT%GTH##	;MODE CHANGE (HI TO SHR OR VICE VERSA). 1ST HI PAGE?
	TRNN	P4,-1		;PAGE OK, PAGE 0 CANT BE IN HI-SEG
	JRST	BADDIR		;PAGE 0 OR MIXTURE OF SHR AND NON-SHR PAGES
	JRST	CPOPJ1##	;PAGE IS OK, TAKE GOOD RETURN
;SUBROUTINE TO READ IN A PAGE FROM THE SAVE FILE
; AND PERFORM SOME MISCELLANEOUS HOUSE-KEEPING
;
;CALL:
;	PUSHJ	P,FSIOWD	;SETUP AN IOWD
;	PUSHJ	P,RDSTUF	;OR,
;	PUSHJ	P,WRSTUF
;	RETURN HERE ONLY IF OK
;
WRSTUF::MOVEI	T1,35		;FILOP. FUNCTION CODE FOR EXTENDED WRITE
	MOVEM	T1,.JDAT+SGALEN## ;STORE THAT FOR THE FILOP. AND FALL INTO COMMON CODE
RDSTUF:	MOVE	T1,DEVIOS(F)	;GET STATUS
	TRNE	T1,IODEND	;EOF?
	JRST	SHTDIR		;YES, FILE TOO SHORT
	TLNN	P1,GTSAV##	;ALWAYS SET USRHCU ON A SAVE
	TLNE	P1,GTLOW##	;DON'T SET USRHCU ON A GETSEG BECAUSE
				; THE BLT TO RESTORE USER CHANNELS WILL FAIL
	HRROS	USRHCU##	;SET SAVE/GET FLAG
	PUSH	P,P1		;AN INPUT KILLS THESE AC'S
	PUSH	P,P4		;...
	.CREF	SGASAV		;SINCE CAN'T HAVE AN EXTERNAL AC
	FILOP.	14,		;(FILOP. SGASAV,)READ SOME STUFF
	  JFCL			;SGIOCK AND THE TEST AT THE BEGINNING OF RDSTUF
				; WILL TAKE CARE OF ERRORS
	MOVE	P1,-1(P)	;GET FLAGS BACK
	HLLM	P1,.JDAT+SGAEND## ;RESTORE COPY IN MEMORY (THEY WERE CLOBBERED
				; BY THE FILOP. ARGUMENT BLOCK)
	PUSHJ	P,SGIOCK##	;CHECK FOR ERRORS
	HRRZS	USRHCU##	;CLEAR FLAG
PP4P1:	POP	P,P4		;RESTORE AC'S
	POP	P,P1		;...
	POPJ	P,		;RETURN
;SUBROUTINE TO MOVE A DIRECTORY PAGE
;
;CALL:
;	MOVE	T1,PAGE # TO MOVE
;	PUSHJ	P,MOVDIR
;	RETURN WITH PAGE MOVED AND DIRECTORY POINTERS UPDATED
;
;COME HERE IF ONE OF THE DIRECTORY PAGES IS ABOUT TO BE
; OVER-WRITTEN BY THE CURRENT DIRECTORY ENTRY. THE DIRECTORY PAGE
; IS MOVED TO ANOTHER FREE PAGE.

MOVDIR:	HRRZ	T2,P3		;FILE PAGE NUMBER
	JUMPE	T2,MOVDR1	;EASY IF ABZ PAGE
	HRRZ	T3,P4		;PROCESS PAGE NUMBER
	SUBM	T1,T3		;OFFSET INTO POINTER
	ADD	T2,T3		;FILE PAGE NUMBER TO REMEMBER
MOVDR1:	HRRM	T1,.JDAT+SGANAM## ;REMEMBER PROCESS PAGE NUMBER TO SKIP 
	HRLM	T2,.JDAT+SGANAM## ; AND FILE PAGE NUMBER THAT HAS TO BE PUT THERE WHEN DONE
	TLO	P1,GT%DAF##	;INDICATE SOME PAGE IN THIS ENTRY OVERLAPS DIRECTORY
	POPJ	P,		;AND RETURN

;SUBROUTINE TO SETUP IOWD TO DO AN EXTENDED FILIO IN UUO (ACTUALLY NEVER
; DOES MORE THAT A SECTION OR CROSSES A SECTION BOUNDARY, BUT COULD DO A
; WHOLE SECTION IN ONE OPERATION)
;CALLING SEQUENCE:
;	MOVE	T1,SECTION NUMBER,,ADDRESS WITHIN SECTION
;	MOVE	T2,POSITIVE WORD COUNT
;	PUSHJ	P,FSIOWD
;	ALWAYS RETURN HERE, IOWD SETUP FOR RDSTUF
;CALL F1IOWD TO SETUP TO READ JUST ONE PAGE

F1IOWD:	MOVEI	T2,PAGSIZ	;WORD COUNT TO READ ONE PAGE
FSIOWD::MOVEM	T1,.JDAT+JOBUAL##+4 ;ADDRESS (OUT OF OTHERS WAY) IN PATH PART OF JOBUAL
	MOVEM	T2,.JDAT+JOBUAL##+3 ;WORD COUNT
	SETZM	.JDAT+JOBUAL##+5;TERMINATE LIST
	SETZM	.JDAT+JOBUAL##+6; IT TAKE TWO WORDS OF ZEROS
	MOVEI	T1,34		;FILOP FUNCTION FO.XIN
	MOVEI	T2,JOBUAL##+3	;ADDRESS OF ARGUMENT LIST
	DMOVEM	T1,.JDAT+SGALEN## ;STORE ARG POINTER IN SHADOW ACS
	MOVE	T1,[2,,SGALEN##];LENGTH,,ADDRESS OF ARG LIST
	MOVEM	T1,.JDAT+SGASAV## ;STORE THAT FOR THE FILOP
	POPJ	P,		;AND RETURN

;STILL IN IFN FTEXE CONDITIONAL...
;ERROR ROUTINES FOR NEW SAVE FILES
;
;HERE IF 1 MORE PAGE IS NEEDED FOR VARIOUS REASONS
NEED1P::PUSH	P,[0]		;WILL BE INCREMENTED TO 1P
	JRST	NOROOM##	;PRINT ERROR MESSAGE

;HERE IF ATTEMPTING TO EXCEED VIRTUAL LIMIT WITH LIMIT IN T1
NEEDNP:	MOVE	T2,.JDAT+SGALOW##	;GET SIZE OF SEG
NTROOM:	SUB	T2,T1		;GET WHAT IS NEEDED
	LSH	T2,P2WLSH	;CONVERT TO WORDS FOR NOROOM
	PUSH	P,T2		;SAVE WHERE NOROOM EXPECTS TO FIND IT
	JRST	NOROOM##	;AND GO GIVE THE ERROR

;WRITE-LOCK ERROR
WLERR:	MOVEI	T1,WLKERR	;WRITE-LOCK ERROR
	PUSHJ	P,SGRELE##	;RESET DEVICE
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/Write-lock error/

;OVERLAY ERROR 
OVRERR::MOVEI	T1,LOHERR	;OVERLAP ERROR
	PUSHJ	P,SGRELE##	;RESET DEVICE
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/Page overlap error/
;DIRECTORY FORMAT ERROR
SHTDIR:	MOVEI	T1,BEDERR
	PUSHJ	P,SGRELE##
	JSP	T1,PHOLD##
	ASCIZ	/File short in EXE file directory/
BADDIR:	MOVEI	T1,BEDERR	;BAD EXE DIRECTORY ERROR
	PUSHJ	P,SGRELE##	;RESET DEVICE
	JSP	T1,PHOLD##
	ASCIZ	/Bad format for EXE file directory/
;NOT AN .EXE FILE (1ST WORD DID NOT HAVE PROPER DIRECTORY CODE IN IT)
NOTEXE:	MOVEI	T1,BEEERR	;ERROR CODE IN CASE THIS IS A RUN UUO
	PUSHJ	P,SGRELE##	;RELEASE DEVICE AND ERROR RETURN TO
				; USER IF RUN UUO OR FIND TTY AND
				; PRINT ?CRLF
	JSP	T1,PHOLD##	;START TTY AND STOP JOB
	ASCIZ	/Not an EXE file/
EXESAV::MOVEI	T1,BEEERR	;ERROR CODE FOR RUN/GETSEG UUO
	PUSHJ	P,SGRELE##	;AN EXE FILE DID NOT HAVE EXE
	JSP	T1,PHOLD##	; EXTENSION
	ASCIZ	/Must have "EXE" extension/
EXEBIG:	MOVEI	T1,DTBERR	;ERROR CODE FOR RUN/GETSEG UUO
	PUSHJ	P,SGRELE##	;EXE DIRECTORY WAS TOO BIG
	JSP	T1,PHOLD##
	ASCIZ	/File directory is too large/
;STILL IN IFN FTEXE CONDITIONAL...
IUUAGL::MOVEI	T1,ILUERR	;ERROR CODE FOR RUN/GETSEG UUO
	PUSHJ	P,SGRELE##	;REPORT ERROR
	JSP	T1,PHOLD##
	ASCIZ	\Illegal section/core argument\
;SUBROUTINE TO CHECK CURRENT LOCATION ON THE DEVICE
;THIS ROUTINE IS USED ONLY IN THE CASE WHERE THE
; DIRECTORY DATA PAGES ARE NOT CONTIGUOUS.
;
;CALL:
;	MOVSI	P2,CURRENT-PAGE-IN-SAVE-FILE
;	HRR	P3,FILE-PAGE-#-OF -THIS-ENTRY
;	PUSHJ	P,SKPBLK
;	RETURN HERE WITH THE DEVICE PROPERLY POSITIONED
;
SKPBLK:	TRNN	P3,-1		;IF PAGES ARE ABZ, WE DON'T NEED
	POPJ	P,		; TO CHECK LOCATION ON DEVICE
	PUSH	P,P1		;USETI KILLS THESE AC'S
	PUSH	P,P4		;SO, WE SAVE THEM FIRST
SKPBK2:	HLRZ	T3,P2		;GET CURRENT FILE PAGE #
	SUBI	T3,(P3)		;FIND DIFFERENCE IN WHERE WE ARE ON
				; THE DEVICE, AND WHERE WE WANT TO GO
	JUMPE	T3,PP4P1	;IF WE ARE THERE, RESTORE P4,P1 AND EXIT
	JUMPG	T3,BADDIR	;IF WE ARE PAST WHERE WE WANT TO BE,
				; IT CAN ONLY BE A BAD FORMAT FILE
	MOVE	T4,DEVMOD(F)	;WE ARE NOT THERE YET (CAN ONLY HAPPEN IF THERE
				; ARE "HOLES" IN THE 
				; SAVE FILE, IMPOSSIBLE UNLESS
				; THE DEFINED STRUCTURE OF THE
				; SAVE FILE CHANGES IN THE
				; FUTURE, OR IF WE ARE SKIPPING 1 SEGMENT.
	TLNE	T4,DVDSK	;IS IT A DISK?
	JRST	[HRL	P2,P3	;YES, RESET COUNTER OF CURRENT FILE PAGE #
		 HRRZ	T3,P3	;FETCH FILE PAGE # FOR THIS ENTRY
		 LSH	T3,2	 ;FIND BLOCK NUMBER
		 USETI	1(T3)	;MOVE TO CORRECT FILE PAGE #
		 JRST	PP4P1]	; AND CONTINUE
	PUSHJ	P,RDSTUF	;NO, READ PAGE OF DATA FROM DEVICE
	ADD	P2,[1,,0]	;BUMP CURRENT FILE PAGE #
	JRST	SKPBK2		;AND CHECK AGAIN


;ROUTINE TO GET THE NEXT DIRECTORY ENTRY FROM THE SAVE FILE
;
;CALL:
;	MOVE	P1,ADDRESS-OF-ENTRY
;	MOVE	P2,CURRENT-LENGTH-OF-DIRECTORY
;	PUSHJ	P,GTDIRE
;	 HERE IF DIRECTORY IS FINISHED
;	HERE IF MORE IN DIRECTORY (ENTRY IS IN P3,P4)
;
GTDIRE::TRNN	P2,-1		;IS THERE ANY MORE?
	POPJ	P,		;NO
	SUBI	P2,NTRYSZ	;DECREMENT LENGTH OF ENTRY
	PUSHJ	P,GTDIRW	;GET 1ST WORD
	MOVE	P3,T1		;STORE IT IN P3
	PUSHJ	P,GTDIRW	;GET NEXT WORD
	MOVE	P4,T1		;STORE IT IN P4
	JRST	CPOPJ1##	;SKIP RETURN
;ROUTINE TO GET ONE WORD FROM THE DIRECTORY
;
;CALL:
;	MOVE	P1,ADDRESS-OF-WORD
;	PUSHJ	P,GTDIRW
;
;ON EXIT, T1 WILL CONTAIN THE WORD FETCHED FROM THE DIRECTORY
;
;IF THE PAGE IS FINISHED, THE PAGE POINTED TO BY P1 IS
; REMOVED FROM THE LOGICAL ADDRESSING SPACE AND A NEW
; DIRECTORY PAGE IS FETCHED FROM SGANAM.

GTDIRW::HRR	M,P1		;GET POINTER TO DIRECTORY
	PUSHJ	P,PFHGWD##	;GET WORD FROM USER SPACE
	  JRST	UADERR##	; MUST USE PFH'S GETWRD ROUTINE SINCE PFH MAY
				; HAVE PAGED OUT THE DIRECTORY PAGE
	AOS	P1		;BUMP POINTER
	TRNE	P1,EXESIZ-1	;OVERLAP TO NEW PAGE?
	POPJ	P,		;NO
	SUBI	P1,EXESIZ	;YES, MOVE POINTER BACK TO LAST PAGE
	PUSH	P,T1		;SAVE CURRENT DIRECTORY ENTRY
	PUSH	P,T3		;THESE ARE THE CURRENT DIRECTORY ENTRIES,
	PUSH	P,T4		; SO, WE MUST SAVE THEM
	SKIPN	T1,.JDAT+SGAEXT## ;READING DIRECTORY SEQUENTIALLY?
	JRST	GTDIR1		;YES
	LSH	T1,2		;CONVERT TO BLOCK NUMBER OF DIRECTORY PAGE
	PUSH	P,P1		;USETI CLOBBERS P1
	USETI	1(T1)		;POSITION TO DIRECTORY PAGE
	PUSHJ	P,SGIOCK##	;CHECK FOR ERRORS
	POP	P,P1		;RESTORE P1
GTDIR1:	HRRZ	T1,P1		;ADDRESS FOR I/O
	PUSHJ	P,F1IOWD	;MAKE AND STORE AN IOWD
	PUSHJ	P,RDSTUF	;READ THE NEXT DIRECTORY PAGE
	PUSHJ	P,SGIOCK##	;CHECK FOR I/O ERRORS
	TLO	P1,SV%DWO	;REMEMBER MULTIPLE PAGE EXE DIRECTORY READ
	SKIPN	.JDAT+SGAEXT##	;SEQUENTIAL I/O?
	JRST	GTDIR2		;YES, ALL DONE
	HLRZ	T1,P2		;NO, MUST PUT THE FILE BACK WHERE IT WAS
	LSH	T1,2		;CONVERT TO BLOCK NUMBER
	PUSH	P,P1		;SAVE THIS VERY IMPORTANT AC
	USETI	1(T1)		;POSITION THE FILE
	PUSHJ	P,SGIOCK##	;ERRORS?
	POP	P,P1		;RESTORE P1
	AOS	.JDAT+SGAEXT##	;WHERE THE NEXT PAGE OF THE DIRECTORY IS
GTDIR2:	POP	P,T4		;RESTORE AC'S
	POP	P,T3
	JRST	TPOPJ##		;RESTORE DIRECTORY ENTRY AND RETURN


;STILL IN IFN FTEXE CONDITIONAL...
;ROUTINE TO SET UP FOR A NEW STYLE SAVE FILE GET
;
;CALL:
;	MOVSI	P1,FLAGS
;	PUSHJ	P,GETNEW
;	 HERE IF ERROR
;	HERE OTHERWISE
;

GETNEW:	MOVE	J,.CPJOB##	;RESTORE JOB NUMBER
IFN FTLOCK,<
	MOVSI	T2,NSHF!NSWP	;CAN'T ASSIGN CORE IF JOB IS LOCKED
	TDNE	T2,JBTSTS##(J)	;LOCKED?
	JRST	[MOVEI	T1,SNSERR	;SEGMENT NOT ON SWAPPING SPACE
		 POPJ	P,]
>;END OF FTLOCK
	PUSH	P,.JDAT+JOBUAL##+2
	PUSH	P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
	PUSH	P,.JDAT+JOBUAL##+4 ; LOCATIONS
	PUSH	P,.JDAT+JOBUAL##+5 ; ..
	PUSH	P,.JDAT+JOBUAL##+6 ; ..
	TLNE	P1,GTHGH##	;DOES HE WANT THE HIGH SEG?
	TLNE	P1,GTLOW##	;BUT NOT THE LOW SEG?
	CAIA			;DOESN'T WANT HIGH SEG OR WANTS BOTH
;FOR KILLING SPECIFIC SEGMENT, LOAD T1 WITH SEGMENT DATA BLOCK ADDRESS
	PUSHJ	P,[TLNE	P1,GTSGO## ;IF SEGOP
		   POPJ	P,	;DON'T DELETE ANY HIGH SEGMENTS
		   IFN FTMP,<
		   PUSHJ P,GGVMM## ;GET THE MM RESOURCE
		   >
		   MOVE  T1,.USUSN
		   LSH   T1,P2SLSH
		   PUSHJ P,SVPCS##
		   SETZ  T1,	;KILL ONLY SPECIFIED SECTION
		   PJRST KILHGC];AND THEN REMOVE THE CURRENT HIGH SEGMENT
	TLNN	P1,GTMRG##	;IS THIS A MERGE?
	TLNN	P1,GTLOW##	;NO, DOES HE WANT THE LOW SEGS?
	JRST	GTHILO		;DOESN'T WANT LOW SEG OR THIS IS A MERGE
	TLNE	P1,GTHGH##	;ALREADY GET THE HIGH SEG?
IFN FTMP,<
	PUSHJ	P,[PUSHJ P,GGVMM## ;GET THE MM
		   PJRST KILHGA] ;KILL ALL SEGMENTS
>
IFE FTMP,<
	PUSHJ	P,KILHGA
>
	MOVEI	T1,EXESIZ-1	;SET UP FOR A CORE 0
	PUSH	P,P1		;SAVE FLAGS
	PUSHJ	P,GET1PG##	;GET CORE MIGHT CALL GETSEG
	POP	P,P1		;RESTORE FLAGS
GTHILO:	POP	P,.JDAT+JOBUAL##+6 ; ..
	POP	P,.JDAT+JOBUAL##+5 ; ..
	POP	P,.JDAT+JOBUAL##+4 ; LOCATIONS
	POP	P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
	POP	P,.JDAT+JOBUAL##+2
	PUSH	P,.JDAT+SGANAM## ;SAVE THIS STUFF
	PUSH	P,.JDAT+SGAEXT## ;...
	PUSH	P,.JDAT+SGALOW## ;SAVE EXTENSION
	PUSH	P,.JDAT+SGANEW## ;SAVE USER CORE ARG
	PUSHJ	P,GETEXE	;READ THE EXE FILE
	POP	P,.JDAT+SGANEW## ;RESTORE USER CORE ARG
	POP	P,.JDAT+SGALOW## ;RESTORE EXTENSION
	POP	P,.JDAT+SGAEXT## ;RESTORE GOOD STUFF
	POP	P,.JDAT+SGANAM##
	MOVE	J,.CPJOB##	;MAKE SURE J IS SET UP WHEN WE LEAVE
	JRST	CPOPJ1##	;RETURN TO CALL+2
;ROUTINE TO CHECK TO SEE IF A GIVEN PAGE IS WITHIN THE RANGE
; OF THE CURRENT DIRECTORY ENTRY. THIS ROUTINE IS NECESSARY
; TO MAKE SURE THAT A DIRECTORY PAGE IS NOT OVERWRITTEN,
; AND TO DO SOME OPTIMIZATION ON THE CHOICE OF A NEW PAGE
; IF A DIRECTORY PAGE MUST BE MOVED.
;
;CALL:
;	MOVE	T1,PAGE ADDRESS/PAGE #
;	DMOVE	P3,DIRECTORY-ENTRY
;	PUSHJ	P,CKRADR/CKRANG
;	 HERE IF THERE IS AN OVERLAP
;	HERE IF OK
;
CKRADR:	LSH	T1,W2PLSH	;MAKE INTO A PAGE NUMBER
CKRANG:	LDB	T2,[POINT 9,P4,8]	;GET REPEAT COUNT
	ADD	P4,.USUSN	;REFLECT THE SECTION THE GET IS BEING DONE INTO
	ADDI	T2,(P4)		;FIND LAST PAGE OF THIS ENTRY
	CAIL	T1,(P4)		;CHECK IF NEW PAGE IS LESS THAN 1ST PAGE
	CAILE	T1,(T2)		;OR GREATER THAN LAST PAGE
	AOS	(P)		;YES, NO CONFLICT
	SUB	P4,.USUSN	;RESTORE TO ORIGINAL VALUE
	POPJ	P,		;OVERLAP, MUST FIND NEW PAGE


;SUBROUTINE TO DETERMINE SECTION NUMBER
;CALLING SEQUENCE:
;	PUSHJ	P,GETSSN
;	  ...			;SECTION NUMBER IN T1
;	NORMAL RETURN		;NO NEED TO ADJUST SECTION NUMBER

GETSSN::
REPEAT 0,<
	SKIPE	T1,.USUSN	;GET SECTION NUMBER FOR CURRENT OP
	CAIN	T1,1000		;***HACK TO ALLOW SCETION 0-1 MAPPING
	JRST	CPOPJ1##	;INDICATE NO ADJUSTMENT NEEDED
	TLZ	T1,400000	;CLEAR SET BY UUO BIT
>
	SKIPN	T1,.USUSN	;GET SECTION NUMBER FOR CURRENT OP
	JRST	CPOPJ1##	;NO ADJUSTMENT NEEDED
	LSH	T1,P2SLSH	;CONVERT TO SECTION NUMBER
	POPJ	P,		;RETURN
;SUBROUTINE TO CREATE A SECTION, CREATE PAGE 0 IN THAT SECTION, AND BLT
; PAGE ZERO OF SECTION 0 TO IT
;CALLING SEQUENCE:
;	PUSHJ	P,CRESPG0	;CREATE .USUSN SECTION
;	ALWAYS RETURN HERE

CRESP0:	PUSHJ	P,GETSSN	;GET SECTION NUMBER
	  SKIPE	.UPMP+SECTAB(T1);NON-ZERO SECTION, GO AWAY IF IT ALREADY EXISTS
	POPJ	P,		;SETCTION 0 OR 1
IFN FTMP,<
	PUSHJ	P,REMMM##	;RETURN MM, REMEMBER IF IT WAS OWNED AND GET IT
				; BACK WHEN DONE IF SO
>
	PUSHJ	P,CRESSN##	;CREATE THE SECTION (FASTER THAN PAGE CREATE)
	  JRST	NEED1P		;COULDN'T
	TLNN	P1,GTLOW##	;IF RUN/GET, THEN CREATE P0
	POPJ	P,		;IF GETSEG, DO NOT
	MOVE	T1,.USUSN	;PAGE ZERO IN THE SECTION
REPEAT 0,<
	TLZ	T1,400000	;CLEAR SET BY UUO BIT
>
	PUSHJ	P,CRPAGE	;CREATE THAT
	  JRST	NEED1P		;COP OUT
	MOVEI	T1,PAGSIZ	;ONE PAGE
	MOVEI	T2,.JDAT	;SECTION ZERO PAGE 0
	MOVE	T3,.USUSN	;USE SECTION
	LSH	T3,S2PLSH	;PAGE 0 OF USE SECTION
	XBLTXU	T1		;MOVE THE PAGE
	POPJ	P,		;RETURN
;SUBROUTINE TO VALIDATE WHETHER SWAPPER COPY OF SEGMENT IS
;VALID OR NOT
;RETURNS CPOPJ1 IF SO, CPOPJ IF NOT.
;CALL:
;		MOVE	J,SEGMENT#
;		PUSHJ	P,VALSEG
;IF THE DISK COPY WAS BAD BUT AN IN CORE COPY WAS GOOD, THEN WE WILL
;RETURN CPOPJ1 WITH THE DISK COPY DELETED.
VALSEG:	LDB	T1,IMGOUT##	;GET OUTCORE SIZE
	JUMPE	T1,CPOPJ1##	;IF NO DISK COPY
	SKIPGE	T2,JBTSWP##(J)	;GET DISK OR FRAGMENT ADDR
	JRST	VALSGF		;FRAGMENTED, MUST PERUSE MAP
	LDB	T2,FRGUT1##	;GET UNIT FROM T1
	SKIPLE	T2,SWPTAB(T2)	;IS IT IN SWPTAB?
	SKIPGE	UNIFKS(T2)	;IS THERE SPACE ON IT?
	JRST	VALSG5		;NO
	JRST	CPOPJ1##	;ALL CLEAR

VALSG5:IFN FTMP,<
	CPLOCK	(SCD)		;DON'T LET SWPLST CHANGE ON US
>				;END IFN FTMP
	MOVSI	T1,SWP!JXPN	;IS THIS HIGH SEGMENT SWAPPED?
	TDNN	T1,JBTSTS(J)	;??
	JRST	VALSG6		;NO, OK TO DELETE COPY OF IT
	SETZM	JBTPRG##(J)	;MAKE NOT SHARABLE (CLRNAM DOES TOO MUCH)
IFN FTMP,<
	PJRST	ULKSCD##	;RELEASE INTERLOCK AND DO LOOKUP
>
IFE FTMP,<
	POPJ	P,
>
;HERE IF THE SEGMENT ISN'T SWAPPED, WE CAN JUST DELETE THE DISK COPY
VALSG6: PUSHJ	P,ZERSWP##	;DELETE DISK COPY
IFN FTMP,<
	AOS	(P)		;SKIP RETURN
	PJRST	ULKSCD##
>				;END IFN FTMP
IFE FTMP,<
	PJRST	CPOPJ1##
>
;HERE FOR A SEGMENT WHOSE DISK COPY IS FRAGMENTED, MUST PERUSE ALL
;MAP ENTRIES

VALSGF:	SE1ENT			;BE SURE WE'RE IN SECTION 1
	PUSHJ	P,SAVE1##	;SAVE A WORKING AC
	HRRZ	T1,.M2SIZ-.M2MAP(P1)	;# OF SLOTS
	LDB	P1,JBYVAD##	;GET ADDR OF MAP
VALSF1:	PUSHJ	P,GETHDP	;GET THE DISK ADDR
	LDB	T2,FRGUT2##	;GET UNIT
	SKIPLE	T2,SWPTAB(T2)	;IS IT IN SWPTAB?
	SKIPGE	UNIFKS(T2)	;IS THERE SPACE ON IT?
	JRST	VALSG5		;NO
	SOJLE	T1,CPOPJ1##	;NO MORE
	AOJA	P1,VALSF1
SUBTTL	SWAP - USER PROGRAM SWAPPING ROUTINES

;ROUTINE CALLED AFTER A HIGH OR LOW SEG JUST SWAPPED IN
;IT SEES IF A HIGH SEG IS STILL TO BE SWAPPED IN
;DOES POST PROCESSING AFTER HIGH SEG SWAPPEN IN
;CALL:	MOVE J,JOB NUMBER
;	PUSHJ P,FININ
;	RETURN0 (VM SYSTEMS ONLY) IF THE HIGH SEG CURRENTLY
;		HAS SWAPPING I/O IN PROGRESS
;	RETURN1 IF HIGH SEG TO BE SWAPPEN IN(HIGH SEG NO. IN AC J)
;	RETURN2 IF NO HIGH SEG, OR HIGH SEG ALREADY IN, OR THIS WAS HIGH SEG
;		AC J RETURNED WITH JOB NUMBER(IE LOW SEG NO.)
;IF CALLED AT FINCHK, NO SWPLST ENTRY WILL BE DELETED

;J CONTAINS JOB OR HIGH SEG NUMBER(SAME AC AS SWAP USES)


FINCHK::
	TDZA	T2,T2		;SET ENTRY AT FINCHK
FININ::	MOVSI	T2,(1B0)	;SET ENTRY AT FININ
	CAILE	J,JOBMAX##	;WAS A LOW SEG JUST SWAPPED IN?
	JRST	FINHGH		;NO, HIGH SEG JUST SWAPPED IN, GO FINISH
IFN FTLOCK,<
	MOVE	T1,J		;IF LOCKING THE LOW SEGMENT,
				;  FORGET ABOUT SWAPPING IN THE HIGH SEGMENT.
				;  IF THE HIGH SEGMENT IS SWAPPED WHEN LOCKING
				;  COMPLETES, THE LOCK UUO WILL SET THE SWP
				;  BIT FOR THE LOW SEGMENT. THE LOK BIT
				;  WILL KEEP THE JOB FROM RUNNING.
>
	HRRI	T2,JBTSGN##-.HBLNK(J) ;POINTER TO CHAIN
FININ0:	HRR	T2,.HBLNK(T2)	;GET NEXT SEGMENT
	TRNN	T2,-1		;ANY?
	SKIPA	J,T1		;IF NO MORE SEGMENTS, HE'S CLEAR
	SKIPG	J,.HBSGN(T2)	;GET SEGMENT WORD
	JUMPG	J,CPOPJ2##	;DONE
	JUMPLE	J,FININ0	;LOOK AT ALL HIGH SEGS
	TLO	T2,@JBTSWI##(J)	;SAVE SWPIN IN CASE SWAPPING I/O IN PROGRESS FOR
				; THIS JOBS HIGH SEGMENT
	HRRZM	T1,JBTSWI##(J)	;YES, SAVE JOB NUMBER(FOR FINHGH AND RETURN)
	TLNE	J,SHRSEG	;IF IT'S NON-SHARABLE, DON'T TRUST JBTADR
	SKIPE	JBTADR##(J)	;YES, IS HIGH SEG ALREADY IN CORE?
				;(NOT POSSIBLE TO BE IN MIDDLE OF SWAPPING)
	JRST	FIN0
IFN FTLOCK,<
	CAMN	T1,LOCK##
	JRST	BOTHIN
>
	JRST	CPOPJ1##
FIN0:	MOVSI	T1,SWP+JXPN	;SWP ON FOR THE HI SEG?
	TDNE	T1,JBTSTS##(J)	; ONLY IF SWAPPING I/O IS IN PROGRESS
	JRST	[HLRZ	T1,T2	;GET JOB #
		 ANDI	T1,JOBMSK## ;KEEP ONLY BITS
		 EXCH	T1,JBTSWI##(J) ;RETURN DOING NOTHING UNTIL HI-SEG I/O IS DONE
		 MOVEI J,(T1)	;RETURN JOB #
		 POPJ P,]	;RESTORE ORIGINAL VALUE OF SWPIN
	PUSHJ	P,CHKIDL	;YES, CHECK IF THIS HIGH SEG IS IDLE(IF YES,
				; DECREASE CORTAL=FREE+DORMANT+IDLE CORE
				; BY SIZE IN K OF HIGH SEG SINCE IT WILL
				; NO LONGER BE IDLE(IN CORE COUNT NON-ZERO)
	MOVE	T1,JBTSWI##(J)	;RESTORE JOB NUMBER
	PUSHJ	P,INCCNT	;INCREMENT HIGH SEG IN CORE COUNT
				; FOR THIS JOB
	PUSHJ	P,CHKTAL	;CHECK CORTAL WITH CORTAB, HALT IF DIFFER
	TLO	J,1
	JRST	FINHG1
FINHGH:	HRRE	T1,JBTSWI##(J)	;JOB WHICH HISEG WAS SWAPPED IN FOR
	JUMPLE	T1,FINHG1	;(MIGRATE) SWAPPED IN FOR NO ONE
	EXCH	T1,J		;JOB # TO J, HIGH SEG TO T1
	PUSHJ	P,FNDHSB	;GET HIGH SEG DATA BLOCK
	  XCT	BSN		;?
	MOVE	T1,.HBSGN(T1)	;SETGMENT # AND BITS
	EXCH	T1,J
	TLZ	J,1		;CLEAR FLAG BIT
	.CREF	HSAMSK		;(WHICH IS IN HSAMSK FIELD)
FINHG1:	JUMPGE	T2,BOTHIN	;DON'T DO THIS IF CALLED AT FINCHK
	PUSH	P,T2		;SAVE T2
	MOVSI	T2,SWP		;CLEAR SWAPPED OUT OR ON WAY FLAG FOR HIGH SEG
	ANDCAM	T2,JBTSTS##(J)	;AND CLEAR SUPPRESS IN-CORE COUNT INCREMENT FLAG
	HRRZ	T2,MIGRAT##	;MIGRATING JOB
	CAME	T1,T2		;IF WE'RE GETTING RID OF A SWAP UNIT
	CAIN	T2,(J)
	 SKIPA
				; MAKE THE HIGH SEG DISAPPEAR

	TLNE	J,UWPOFF	;IS USER MODE WRITE PROTECT(UWP) OFF
				; FOR THIS USER?
	JRST	[PUSHJ P,ZERSWP## ;YES, CHANGE SWAPPING SPACE TO 0 FOR HIGH SEG
				;0 TO JBTIMO,JBTIMI, AND SWP IN JBTSTS(HIGH SEG)
				;NO, KEEP COPY OF SEG ON DISK(USUAL CASE)
				; WHETHER SHARABLE OR NOT
		 JRST FINHG2]
	TLZN	J,1
	PUSHJ	P,DLTSXI##	;DELETE ENTRY FROM SWPLST
FINHG2:	POP	P,T2
BOTHIN:	TLZ	J,-1		;SAVE ONLY SEGMENT NUMBER
	HRRZ	T1,MIGRAT##	;
	CAMN	J,T1		;IF WE'RE REMEMBERING THIS HIGH SEG,
	JRST	CPOPJ2##	;ONLY FOR MIGRATE, RETURN NOW
	MOVE	T1,JBTSWI##(J)	;RESTORE JOB (I.E. LOW SEG) NUMBER
	TLZ	T2,JOBMSK##	;CLEAR SAVED JOB PORTION OF T2
	JRST	FININ0		;CHECK NEXT HIGH SEG
	

;ROUTINE TO CHECK FOR EXPANDING HIGH SEGMENT ON SWAP IN
;IF A JOB IS USING A SHARABLE HIGH SEGMENT WHICH HAS BEEN
;EXPANDED BY ANOTHER JOB, NONE OF THE SHARERS CAN BE
;SWAPPED IN UNTIL ALL HAVE BEEN SWAPPED OUT (JXPN=0)
;CALL:	MOVE J,JOB NUMBER (OR HI SEG) TO BE SWAPPED IN
;	PUSHJ P,CKXPN
;	  RETURN1 IF HIGH SEG IS EXPANDING (J=SAME)
;	RETURN2 ON ALL OTHER CONDITIONS (J=SAME)
;NOTE:	T1 AND T2 ARE PRESERVED (HENCE SHORT NAME FOR ROUTINE)


CKXPN::	AOS	(P)		;ASSUME NONE WILL BE FOUND
	CAILE	J,JOBMAX##	;IS THIS A LOW SEG (JOB #)?
	POPJ	P,		;NO, GIVE GOOD RETURN TO TRY TO FIT
	PUSH	P,T1		;SAVE T1
	PUSH	P,T2
	MOVEI	T2,JBTSGN##-.HBLNK(J) ;STAR OF JOB'S HI SEG CHAIN
	TLO	J,(1B0)		;FLAG WE HAVEN'T SOS'D YET
CKXPN0:	MOVSI	T1,JXPN
CKXPN1:	HRRZ	T2,.HBLNK(T2)	;NEXT SEG
	JUMPE	T2,CKXPN5	;DONE
	SKIPLE	T3,.HBSGN(T2)	;SEGMENT WORD
	TDNN	T1,JBTSTS##(T3)	;JXPN SET FOR HIGH SEG?
	JRST	CKXPN1		;NO, OR SPY SEGS
	TLZE	J,(1B0)		;FLAG
	SOS	-2(P)		;DON'T GIVE SKIP RETURN
	CAME	J,FIT		;THIS JOB IN FIT?
	JRST	CKXPN1		;NO, NOTHING MORE TO DO THEN
	EXCH	J,T3		;GET SEGMENT WORD TO J, SAVING ORIGINAL J
	PUSHJ	P,[PUSH	P,T2	;DECCNT WANTS T2 ALREADY PUSHED
		   JRST DECCN1]	;DECREMENT COUNT
	  JFCL			;DON'T CARE IF IT WENT IDLE
	MOVE	J,T3
	JRST	CKXPN0		;AND LOOP

CKXPN5:	HRRZS	J		;CLEAR JUNK IN LH(J)
	PJRST	TTPOPJ##	;AND RETURN GOOD OR SKIP

	
;ROUTINE CALLED JUST BEFORE HIGH OR LOW SEG TO BE SWAPPED IN
; AND AFTER CORE HAS BEEN ASSIGNED
;FITHGH SEES IF HIGH SEG AND INCREASES IN-CORE COUNT(USUALLY TO 1)
; FOR JOB BEING SWAPPED IN(SWPIN ALREADY SET TO JOB # BY PREVIOUS CALL
; TO FININ FOR LOW SEGMENT OF THIS JOB


FITHGH::CAIG	J,JOBMAX##	;IS THIS A HIGH SEGMENT
	POPJ	P,		;NO,
;DON'T NEED TO CLEAR LEFT HALF OF MIGRAT HERE SINCE BITS AREN'T ON FOR HI SEG
	CAME	J,MIGRAT##	;IS THIS A MIGRATING HIGH SEGMENT?
	JRST	FITHG1		;NO, DO NORMAL STUFF
	LDB	T1,IMGIN##	;ELSE DON'T INCREASE IN-CORE COUNT, BUT
	ADDM	T1,CORTAL##	;DO ADJUST CORTAL
	POPJ	P,
FITHG1:	MOVE	T1,JBTSWI##(J)	;YES, GET JOB NUMBER(SET BY FININ) THAT 
				; GOES WITH THIS HIGH SEG
	MOVSI	F,(JS.SIP)	;INDICATE A SWAP IS IN PROGRESS FOR THIS JOB
	IORM	F,JBTST2##(T1)	; SO IT DOESN'T GET PICKED TO BE SWAPPED OUT
				; WHILE THE HIGH SGEMENT IS BEING SWAPPED IN FOR IT
	PJRST	INCCNT		;INCRENT IN-CORE COUNT AND RETURN


;ROUTINE TO CHECK IF THIS WAS A HIGH SEG JUST SWAPPED OUT
;IF YES, RETURN JOB NUMBER SO LOW SEG CAN BE SWAPPED OUT(IF NOT ACTIVE IO)
;CALL:	MOVE J,HIGH OR LOW SEG NUMBER JUST FINISHED SWAPPING OUT
;	PUSHJ P,FINOT
;	RETURN1 - LOW SEG TO BE WRITTEN, C(J) SET TO JOB(LOW SEG) NUMBER
;	RETURN2 - NOTHIGN MORE TO SWAP OUT FOR THIS JOB


FINOT::	CAIG	J,JOBMAX##	;IS SEG JUST WRITTEN A HIGH SEG?
	JRST	CPOPJ1##	;NO, IT WAS A LOW SEG-NOTHING MORE TO DO
	MOVSI	T1,JXPN		;YES, CLEAR EXPAND BIT FOR THIS HIGH SEG
	ANDCAM	T1,JBTSTS##(J)	;IN CASE IT WAS ON.
	SKIPN	T1,SWPOUT##	;IF LOW SEG NO. IS 0,THIS SWAPOUT WAS
				;A HIGH IDLE SEG(IF NO ASSOCIATED LOW SEG)
	JRST 	FINOT1		;YES,ADJUST CORTAL AND GIVE NOTHING MORE TO
				;SWAPOUT RETURN(ALWAYS SKIP RETURN)
	PUSHJ	P,FPDBT1##	;GET PDB ADDR
	  JRST	FINOTA		;NO PDB, DON'T WORRY ABOUT CONTEXTS
	SKIPGE	.PDCTX##(T1)	;CONTEXT SAVE IN PROGRESS?
	JRST	FINOT0		;YES, DON'T CALL DECCNT
	MOVE	T1,SWPOUT##	;RESTORE JOB NUMBER
FINOTA:	EXCH	T1,J		;HIGH SEG # IN T1, JOB # IN J
	PUSHJ	P,FNDHSB	;FIND HIGH SEG DATA BLOCK
	  JRST	FINOT0		;?
	MOVE	T1,.HBSGN(T1)	;SEGMENT WORD
	EXCH	T1,J		;FOR DECCNT
	PUSHJ	P,DECCNT	;WITH CORRECT CORCNT BIT FROM TABLE
				;FOR JOB FOR WHICH IT WAS JUST SWAPPED OUT
	  JFCL			;ALREADY DECREMENTED. IGNORE.
FINOT0:	MOVE	T1,SWPOUT##	;JOB NUMBER THAT SWAPPING IS IN PROGRESS FOR
	MOVE	T1,JBTSTS##(T1)	;JOB STATUS
	TLNE	T1,SHF		;SWAPPING I/O IN PROGRESS FOR THIS LOW SEGMENT?
	JRST	CPOPJ1##	;YES, NOTHING TO DO
	JRST	 RETJOB		;YES, RETURN JOB NUMBER(LOW SEG NUMBER)
				; TO TRY TO BE SWAPPED OUT
FINOT1:	LDB	T1,IMGOUT##	;GET SIZE OF SHARABLE HIGH DATA SEG
	MOVNS	T1		;DECREMENT CORTAL SINCE SWAPPING IDLE CORE
	ADDM	T1,CORTAL##	;DOESN'T REALLY INCREASE FREE+IDLE+DORMANT COUNT
	MOVSI	T1,NSHF		;CLEAR NSHF WHICH WAS TURNED
	ANDCAM	T1,JBTSTS##(J)	; ON TO KEEP THE SEGMENT FROM APPEARING
				; DORMANT DURING THE SWAP OUT
	PUSHJ	P,DLDISQ	; NOT IN CORE ANY MORE
	JRST	CPOPJ1##	;SKIP RETURN,NO LOW SEG TO SWAP OUT

	
;ROUTINE TO COMPUTE AMOUNT OF CORE NEEDED TO GET THIS USER INTO CORE
;CALL:	MOVE J,JOB NUMBER OR HIGH SEG NUMBER IF LOW SEG ALREADY IN
;	MOVE P1,JBTIMI		;SIZE OF THIS SEG WHEN SWAPPED IN(OR O IF ALREADY IN)
;	PUSHJ P,FITSIZ
;	RET1 - CANNOT FIT THIS USER IN(P1=SUM OF SEGS NEEDED)
;	RET2 - BOTH WILL FIT(P1 RESTORED TO SIZE OF THIS SEG)
;	J RESTORED ON BOTH RETURNS


FITSIZ::JUMPL	J,CPOPJ1##	;PDB'S ALWAYS FIT
	PUSH	P,P1		;SAVE SIZE OF THIS SEG FOR RETURN
	PUSH	P,J		;SAVE LOW OR HIGH SEG NUMBER
	CAILE	J,JOBMAX##	;IS THIS A LOW SEG(IF NO, LOW SEG ALREADY IN)?
	JRST	FITCHK		;YES--NO PDB FOR HISEGS
	MOVEI	T1,JBTSGN##-.HBLNK(J)
FITCK1:	SKIPN	T1,.HBLNK(T1)	;NEXT HIGH SEG
	JRST	FITCHK		;DONE, GO SEE IF JUST THIS HIGH OR LOW SEG WILL FIT
	SKIPG	J,.HBSGN(T1)	;HIGH SEG WORD
	JRST	FITCK1		;SPY SEG
	HRRZS	J		;CLEAR JUNK
	LDB	P2,IMGIN##	;YES, INCLUDE SIZE OF HIGH SEG WHEN SWAPPED IN
	SKIPN	JBTADR##(J)	;IS IT IN CORE SO NO SWAP IN NEEDED?
	ADD	P1,P2		;NO, ADD LENGTH OF HIGH SEG IF NEEDED
	JRST	FITCK1		;NEXT HIGH SEG

FITCHK:	POP	P,J		;RESTORE LOW OR HIGH SEG NUMBER
	MOVE	T1,P1		;COPY TO P1
	SUB	T1,PAGOUC##	;THESE PAGES CAN BE MADE AVAILABLE
	CAMLE	T1,CORTAL##	;IS AMOUNT OF CORE REQUIRED, AVAILABLE?
				; EVEN IF ALL CORE DORMANT SEGS ARE DELETED
	JRST	TPOPJ##		;NO, POP OFF SIZE OF SEG AND RETURN
				; AND SCAN FOR JOB TO SWAP OUT
	POP	P,P1		;RESTORE SIZE OF THIS SEG FOR RETURN
	JRST	CPOPJ1##	;RETURN AND TRY SHUFFLING TO GET A HOLE BIG ENOUGH
				; IF THAT NOT GOOD ENOUGH, DELETE SOME DORMANT
				; SEGS FROM CORE


;ROUTINE TO RETURN HIGH PRIORITY QUEUE NO FOR A JOB
; IF ITS HIGH SEG IS BEING FIT INTO CORE
;CALL:	MOVE	J,FIT(LOW OR HI SEG)
;	PUSHJ	P,FITHPQ
;	RETURN WITH J=JOB NO BEING FITTED

FITHPQ::CAILE	J,JOBMAX##	;IS THIS A HIGH SEG BEING FIT?
	MOVE	J,JBTSWI##(J)	;YES, RETURN JOB NO.
	POPJ	P,		;RETURN


	
;ROUTINE TO COMPUTE SIZE OF CORE FREED UP IF A JOB WERE TO BE FORCED OUT
;CALL:	MOVE J,JOBNUMBER
;	MOVE F,LOW SEG SIZE IN 1K BLOCKS
;	PUSHJ P,FORSIZ
;	RETURN - AC F INCREMENTED APPROPRIATELY(C(J)=JOB NUMBER)
;	ACS T1 AND T2 ARE PRESERVED BECAUSE THEY ARE IN USE BY
;		QUEUE SCANNING ROUTINES


FORSIZ::PUSHJ	P,SAVE3##	;SAVE P1 - P3
	MOVSI	P3,SWP		;SWP BIT SET WHEN HIGH SEG SWAPPED
	TDNE	P3,JBTSTS##(J)	;HAS HIGH SEG ALREADY BEEN SWAPPED OUT FOR
				;THIS JOB(OR IN-CORE COUNT DECREMENTED)?
	POPJ	P,		;NO, RETURN J STILL SETUP TO JOB NUMBER
	MOVEI	P1,JBTSGN##-.HBLNK(J) ;HIGH SEG CHAIN
FORSZ0:	SKIPN	P1,.HBLNK(P1)
	POPJ	P,		;NO MORE SEGS
	SKIPG	P3,.HBSGN(P1)	;SEGMENT WORD FOR THIS SEGMENT
	JRST	FORSZ0		;SPY SEG
	HRRZS	P3		;CLEAR JUNK
	MOVE	P2,JBTSTS##(P3)	;IS HIGH SEGMENT SWAPPABLE?
	TLC	P2,NSWP!SNA	;COMPLEMENT BITS
	TLNN	P2,SNA!NSWP
	POPJ	P,
FORSZ1:	LDB	P2,[POINT 21,JBTIMI##(P3),35]
	JUMPE	P2,FORSZ0	;NOT IN CORE - RETURN
	MOVE	P3,JBTSTS##(P3)	;GET NO. OF IN CORE USERS
	TLNN	P3,SHRSEG	;SHAREABLE?
	JRST	FORSZ2		;NO
	SKIPLE	SGTLIM##	;YES. RETAINING HISEGS?
	SKIPE	ZAPIDF##	;YES. FRUSTRATED?
FORSZ2:	TRZA	P3,-1^!ICCMSK	;LET IT COUNT SIZE
	JRST	FORSZ0		;RETAINING; DON'T COUNT THIS HISEG SIZE
	IDIVI	P2,(P3)		;COMPUTE HISEG SIZE/NO. OR USERS
	ADDI	F,1(P2)		;ADD THIS TO TOTAL JOB SIZE AND ADD 1 FOR LUCK?
	JRST	FORSZ0		;LOOP ON

	
;ROUTINE TO FREE UP CORE FOR SWAPPING SYSTEMS
;BY DELETING ONE DORMANT OR IDLE SEGMENT IN CORE (DISK COPY LEFT IF ANY)
;CALL:	PUSHJ P,FRECR1
;ERROR RETURN-WITH J=HIGH IDLE SEG WITH NO COPY ON DISK (IT MUST BE 
;SWAPPED OUT BEFORE CORE IS FREED SINCE IDLE SEG IS IN SOME SWAPPED OUT USERS
;VIRTUAL ADDRESSING SPACE)
;	 SKIP RETURN - J PRESERVED



FRECR1::PUSH	P,T1		;SAVE CORE ARG(ON CALLS TO FRECOR)
	PUSH	P,J		; SAVE JOB OR SEG NUMBER
	MOVNI	J,DISQ##	;SCAN JUST DORMANT/IDLE HIGH SEGMENTS
	MOVEI	T1,ICCMSK	;MASK FOR CHECKING NON-ZERO IN-CORE COUNT
	HRLI	T1,NSHF!SNA	;LOOK FOR DORMANT SEGMENTS FIRST
				; SNA =0 AND IN CORE COUNT = 0
FREC0:	HRRE	J,JBTDIQ##(J)	;SCAN DORMANT/IDLE SEGMENTS FROM OLDEST
	JUMPLE	J,FREC1		;GO TO NEXT SECTION IF FINISHED
	SKIPE	JBTADR##(J)	;DOES THIS HIGH SEG HAVE CORE?
	TDNE	T1,JBTSTS##(J)	;YES, IS IN-CORE COUNT EQUAL TO 0?
	JRST	FREC0		;NOT DORMANT IN CORE. CONTINUE
	SKIPGE	ZAPIDF##	;SWAPPER GETTING FRUSTRATED?
	JRST	FREC0A		;YES. DELETE ANYWAY
	MOVE	T3,SYSUPT##	;SYSTEM UPTIME
	SUB	T3,JBTIDT##(J)	;MINUS TIME WENT DORMANT
	CAMG	T3,SGTLIM##	;LESS THAN LIMIT?
	JRST	FREC0		;YES. DON'T DELETE IT
FREC0A:	TLO	J,-1		;J MUST BE < 0 AT FREC4 WHEN
	JRST	FREC4		;CALLED BY FRECR1
FREC1:	MOVNI	J,DISQ##	;NOW LOOK AT IDLE SEGMENTS
	MOVEI	T3,ICCMSK	;MASK FOR CHECKING NON-ZERO IN-CORE COUNT
	HRLI	T3,NSHF!NSWP	;NOW LOOK FOR UNLOCKED IDLE SEGMENTS
FREC2:	HRRE	J,JBTDIQ##(J)	;LOOK AT DORMANT/IDLE FROM OLDEST
	JUMPLE	J,FREC2A	;CANT HELP IF NO MORE
	SKIPE	JBTADR##(J)	;DOES THIS SEGMENT HAVE CORE?
	TDNE	T3,JBTSTS##(J)	;IS IT IDLE AND NOT LOCKED?
	JRST	FREC2		;NOT IDLE IN CORE. CONTINUE
FREC3:	MOVSI	T1,SHRSEG	;SHARABLE SEGMENT BIT
	TDNN	T1,JBTSTS##(J)	;IS THIS A NON-SHARABLE HIGH SEGMENT?
	JRST	FREC2		;NO, IT LOOKS IDLE BUT CANNOT BE
	MOVE	T1,FIT##	;SEGMENT BEING SWAPPED IN
	EXCH	T1,J		;SEG # TO T1, JOB # TO J
	CAIG	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	PUSHJ	P,FNDHSB	;DOES THIS HIGH SEG EXIST FOR JOB?
	  JRST	FREC3A		;NO, ITS NOT AN IDLE SEGMENT BELONGING TO THE
	HRRZ	J,.HBSGN(T1)	;GET SEGMENT # BACK
	JRST	FREC2		; IDLE SEGMENT

FREC3A:	MOVE	J,T1		;GET SEG # BACK
	SKIPGE	ZAPIDF##	;SWAPPER GETTING FRUSTRATED?
	JRST	FREC3B		;YES. DELETE ANYWAY
	MOVE	T1,SYSUPT##	;SYSTEM UPTIME
	SUB	T1,JBTIDT##(J)	;MINUS TIME WENT IDLE
	CAMG	T1,SGTLIM##	;LESS THAN LIMIT?
	JRST	FREC2		;YES. DON'T DELETE
FREC3B:	TLO	J,-1		;J MUST BE LESS THAN ZERO WHEN
	JRST	FREC4		;FREC4 ENTERED FROM FRECR1
FREC2A:	POP	P,J		;MEMORY IS FRAGMENTED
	AOS	-1(P)		;GIVE DOUBLE SKIP RETURN SO
	JRST	TPOPJ1##	; SCHED WILL SHUFFLE OR SCAN FOR OUTPUT
;HERE FROM THE LOCK UUO TO DELETE A SPECIFIC DORMANT
; OR IDLE SEGMENT
FREC4::
IFN FTLOCK,<
	PUSH	P,J		;REMEMBER WHERE CALLED FROM
>
	TLZ	J,-1		;CLEAR OUT LH OF SEG NUMBER
	LDB	T1,IMGOUT##	;DOES HIGH SEG ALSO HAVE COPY ON DISK?
	JUMPN	T1,FREC5	;IF NON-ZERO, DO NOT CLEAR NAME SINCE NEW USERS
				; CAN USE DISK COPY
;HERE FROM FRECR1 ROUTINE IF FOUND AN IDLE OR DORMANT SEGMENT IN CORE 
;WITH NO DISK COPY SO CANNOT FREE UP CORE WITHOUT SWAPPING IDLE HIGH SEG FIRST
; NOT NECESSARY TO SWAP DORMANT SEG BUT USEFUL FOR MODIFIED HIGH
;SEGMENTS LIKE LOGIN TO STAY AROUND LONGER
	SETZM	SWPOUT##	;SET ASSOCIATED JOB NUMBER TO ZERO
				;AS A FLAG THAT THERE IS NO LOW SEGMENT
	MOVSI	T1,NSHF		;TURN ON NSHF
	IORM	T1,JBTSTS##(J)	; SO THAT THE SEGMENT WON'T APPEAR TO BE
				; DORMANT DURING THE SWAP OUT
IFN FTLOCK,<
	POP	P,T1		;IF CALLED FROM LOCK
	JUMPG	T1,CPOPJ##	;DON'T RESTORE ACS
>
	POP	P,T1		;EXIT AS ERROR RETURN FROM FREC1
	JRST	TPOPJ##		;WITH J=HIGH SEG TO BE SWAPPED OUT BECAUSE
				;CORE NEEDED AND THERE IS NO COPY
				;ON DISK (WRITE LOCK OFF)
;HERE IF HIGH SEG ALREADY HAS COPY ON DISK
FREC5:	PUSHJ	P,KDORCR	; JUST RETURN DORMANT OR IDLE CORE
				; BUT LEAVE DORMANT DISK COPY
				; STILL DORMANT ON DISK FOR NEW USERS
IFN FTLOCK,<
	POP	P,J		;IF CALLED FROM LOCK
	JUMPG	J,CPOPJ1##	;DON'T RESTORE ACS
>
	POP	P,J		;RESTORE JOB OR SEG NUMBER
	JRST	TPOPJ1##	;RESTORE CORE REQUEST AND SKIP RETURN
;ROUTINE TO LOOK FOR DORMANT OR IDLE SEGMENTS WHICH ARE IN CORE
;CALL:	MOVE	J,WHERE TO START LOOKING
;	MOVE	T1,SEGMENT DESCRIPTOR BITS WHICH MUST BE OFF TO FIND THE SEGMENT
;	PUSHJ	P,FNDSDI
;RETURNS CPOPJ IF NONE FOUND, CPOPJ1 IF ONE FOUND, J = SEGMENT NUMBER
;CLOBBERS T3

FNDSDI:	MOVEI	T3,SEGN##	;NUMBER OF SEGMENTS TO LOOK AT
FNDSD1:	HRRZS	J		;MAKE SURE NO JUNK
	CAILE	J,JBTMAX##	;REACHED THE TOP?
	HRRZ	J,SEGPTR##	;YES, START OVER AT THE BOTTOM
	SKIPE	JBTADR##(J)	;SEGMENT HAVE CORE IN CORE?
	TDNE	T1,JBTSTS##(J)	;YES, DORMANT OR IDLE?
	AOSA	J		;NO, LOOK AT THE NEXT SEGMENT
	JRST	CPOPJ1##	;YES, GIVE FOUND ONE RETURN
	SOJG	T3,FNDSD1	;NO, LOOK AT NEXT
	POPJ	P,		;NONE FOUND RETURN
	
;ROUTINE TO CHECK IF JOB HAS A HIGH SEG WHICH NEEDS TO BE SWAPPED OUT
;IF YES, IT IS WRITTEN FIRST BEFORE LOW SEG
;IN THIS WAY THE IO BUFFERS MAY STAY ACTIVE LONGER
;IN FACT, THE HIGH SEG CAN BE BROUGHT BACK IN WITHOUT LOW SEG
;EVER LEAVING CORE.
;SHF BIT IS SET IN JOB STATUS WORD IF JOB ONLY HAS A LOW SEG, SO IO WILL STOP
;ON NEXT BUFFERFUL.  THUS ONLY 2 SEG JOBS HAVE ACTIVE IO LONGER.
;BUFFER ADVANCE ROUTINES LOOK AT SHF BUT NOT SWP FOR JOB
;CALL:	MOVEM FIT SWAP IN JOB NO.,FIT
;	MOVE J,LOW OR HIGH SEG NUMBER
;	PUSHJ P,FORHGH
;	ALWAYS RETURN WITH HIGH OR LOW SEG TO BE WRITTEN IN J
;

FORHGH::MOVSI	T1,SWP		;SET WHEN HIGH SEG SWAPPED OUT OR IN-CORE
				; COUNT REDUCED
	CAIG	J,JOBMAX##	;IS THIS A HIGH SEG(ONLY IF WAITING FOR HIGH SEG IO)
	TDNE	T1,JBTSTS##(J)	;NO, HAS HIGH SEG ALREADY BEEN SWAPPED FOR THIS USER?
	POPJ	P,		;YES, TRY HIGH SEG AGAIN OR WRITE LOW SEG
	IORM	T1,JBTSTS##(J)	;NO,SET SWAP BIT IN JOB STATUS WORD TO INDICATE
				; 1. HIGH SEG SWAPPED IF ANY OR LOW SEG SWAPPED IF NONE
	MOVEI	T1,JBTSGN##-.HBLNK(J)
FORH0:	SKIPN	T1,.HBLNK(T1)	;NEXT SEG
	JRST	FORH0A
	SKIPLE	T2,.HBSGN(T1)	;ANY SEG?
	TLNN	T2,SHRSEG	;AND THEY MUST BE SHARABLE
	JRST	FORH0
	JRST	FORH1		;YES

FORH0A:	MOVSI	T1,SHF		;NO, SET WAITING TO SHUFFLE BIT IN JOB STATUS WORD
				; SO IO WILL STOP AFTER NEXT BUFFERFUL(MAYBE SPYSEG)
	IORM	T1,JBTSTS##(J)	;CHECK EVERY BUFFERFUL IN ADVBFF, ADVBFE ROUTINES
	POPJ	P,		;RETURN AND TRY TO SWAP OUT LOW SEG
	
;ROUTINE TO CHECK FOR DANGLING HIGH SEGMENT
; WHEN A JOB CANNOT BE FIT INTO CORE
;DANGLING CAN ONLY HAPPEN IF IN-CORE COUNT COUNTED UP
; FOR A HI-SEG FOR JOB BEING SWAPPED IN BECAUSE JOB BEING SWAPPED OUT
; HAD SAME HI-SEG (USUALLY IN-CORE COUNT COUNTED UP AFTER BOTH SEGS ARE
; SWAPPED IN)
;CALL:	MOVE J,FIT		;JOB (OR HIGH SEG NO) WHICH CANNOT FIT
;	SETZM FIT		;PRETEND WE WEREN'T TRYING TO FIT THE JOB
				; IN WITH THE DANGLING HIGH SEGMENT
;	PUSHJ P,NOFITH
;	  SWAP OUT THE FITJOB, J=JOB NO. IF HI-SEG ALREADY ON DISK, =HI SEG NO IF NEEDS SWAPOUT
;	NOT A JOB, OR NO HIGH SEG, OR HI-SEG IN CORE COUNT NOT UP FOR
;	THIS JOB (2ND RETURN IS USUAL CASE)


NOFITH::CAILE	J,JOBMAX##	;IS THIS A LOW SEG BEING FITTED?
	JRST	CPOPJ1##	;YES
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;START OF SEGMENT CHAIN
NOFTH1:	SKIPN	T1,.HBLNK(T1)	;NEXT SEG
	JRST	CPOPJ1##	;NO MORE, GIVE USUAL NO ACTION RETURN
				;YES, FALL INTO FORH1
	SKIPG	T2,.HBSGN(T1)	;GET SEGMENT DATA WORD
	JRST	NOFTH1		;SPYS DON'T COUNT
	TLNE	T2,SHRSEG	;DON'T BOTHER WITH NON-SHARABLES
	TLNN	T2,CORCNT	;HIGH SEG COUNT UP FOR THIS JOB?
	JRST	NOFTH1		;NO
IFN FTLOCK,<
	HRRZS	T2		;CLEAR JUNK
	HLL	T2,JBTSTS##(T2)	;IF THE HIGH SEGMENT IS LOCKED,
	TLNE	T2,NSWP		;BY DEFINITION IT'S NOT DANGLING
	JRST	CPOPJ1##	;YES, GIVE NO ACTION RETURN
>
FORH1:	HRRZM	J,SWPOUT##	;REMEMBER THIS JOB NUMBER DURING HIGH SEG SWAPOUT
	HRRZ	J,.HBSGN(T1)	;GET SEGMENT #
	SKIPE	R,JBTADR##(J)	;IS HIGH SEG STILL IN CORE?
				; MAY NOT BE IF JOB JUST CONNECTED TO HIGH SEG
				; BY GET(XPANDH) OR HIGH SEG SWAPPED OUT PREVIOUSLY
				;SETUP R IN CASE KCOREH CALLED
	SKIPA	J,.HBSGN(T1)	;GET A SEGMENT
	JRST	RETJOB		;OK TO SWAP OUT JOB IF HI SEG ALREADY ON DISK
	MOVE	T1,SWPOUT##	;GET JOB #
	PUSHJ	P,FPDBT1##	;GET PDB
	  JRST	FORHD		;NO PDB; JUST DECREMENT
	SKIPGE	.PDCTX##(T1)	;CONTEXT SAVE IN PROGRESS?
	JRST	RETJOB		;YES, JUST RETURN JOB
	MOVE	T1,SWPOUT##	;RESTORE JOB #
FORHD:	PUSHJ	P,DECCNT	;YES, DECREMENT IN CORE USE COUNT
	  JRST	RETJOB		;STILL GREATER THAN 0(OR NOT IN CORE), SWAP OUT LOW SEG
	

IFN FTLOCK,<
	PUSHJ	P,LOKHGH##	;SEE IF THE HIGH SEGMENT IS LOCKED OR IS
				;  BEING LOCKED
	  JRST	FORH1A		;YES, DON'T DELETE HIGH SEGMENT SINCE ITS LOCKED OR
				;THE LOW SEGMENT WILL BE SWAPPED IN AS SOON AS
				;THE HIGH SEGMENT IS IN PLACE.  INSTEAD JUST
				; COUNT IN CORE COUNT BACK UP FOR
				; THIS JOB AND SWAP OUT
				; ONLY THE LOW SEG.
>

	SKIPE	T1,FIT##	;IS JOB BEING FITTED IN(0 IF NOT FITTING IN)
	CAILE	T1,JOBMAX##	;IS SEGMENT BEING FITTED A LOW SEG(JOB #)
				; (USUALLY SINCE SWAPPER DOES NOT SWAP IN UNTIL
				; ROOM FOR BOTH HIGH AND LOW SEGS
	JRST	FORH2		;FIT HIGH SEG (RARE)
	MOVEI	T1,JBTSGN##-.HBLNK(T1) ;LOOK AT ALL OF JOB'S HIGH SEGS
FORH1X:	SKIPN	T1,.HBLNK(T1)	;ANY MORE SEGS FOR JOB?
	JRST	FORH2		;NO MORE, FIT JOB NOT USING SAME SEG
	HRRZ	T2,.HBSGN(T1)	;GET SUPPOSED SEGMENT NUMBER
	SKIPLE	.HBSGN(T1)	;IGNORING SPY SEGS
	CAIE	T2,(J)		;YES, FIT JOB HIGH SEG SAME?
	JRST	FORH1X		;SPY SEG OR NOT SAME; CHECK NEXT
	MOVE	J,.HBSGN(T1)	;YES, SET UP PROPER BITS FOR THIS SEGMENT
	MOVE	T1,FIT##	;AND PROPER JOB
				; IN PARTICULAR PRESERVE UWPOFF IN CASE JOB
				;BEING SWAPPED OUT HAS WRITE LOCK OFF
				;AND JOB BEING SWAPPED IN HAS IT ON.
FORH1A:	PUSHJ	P,INCCNT	;YES,INCREMENT HIGH SET IN CORE COUNT FOR JOB
				; ABOUT TO BE FITTED IN CORE EVEN THOUGH ITS LOW
				; SEG HAS YET TO BE SWAPPED IN. (COUNT WILL ONLY
				; BE INCREMENTED ONCE SINCE CORCNT BIT WILL BE SET)
				; HIGH SEG WILL NOT APPEAR IDLE IN CORE
				; DURING OTHER SWAPOUTS AND FIT SWAP IN
				; LEAST FRECOR GRAB IT
	JRST	RETJOB		;RETURN AND SWAP JUST LOW SEG OUT (LEAVING
				; HIGH SEG IN CORE FOR FIT USER)
;HERE TO SWAP OUT HIGH SEG UNLESS ALREADY ON DISK
FORH2:	LDB	T1,IMGIN##	;INPUT SIZE
	JUMPE	T1,RETJOB	;RETURN JOB IF HI-SEG CORE IS INCLUDED
				; IN THE LOW SEG.
	MOVE	T1,SWPOUT##	;JOB NUMBER OF JOB WHICH HAS HIGH SEG
				; WHICH MAY BE WRITTEN
	MOVSI	T2,JXPN		;SEGMENT EXPANDING BIT
	TDNE	T2,JBTSTS##(J)	;IS THE SEGMENT EXPANDING?
	PJRST	INCCNT		;YES, INCREMENT IN-CORE COUNT AND
				; SWAP OUT THE HIGH SEGMENT SINCE
				; IT HAS NO DISK COPY (UCORHI
				; CALLED ZERSWP)
	LDB	T2,IMGOUT##	;IS A COPY OF SEG ALREADY ON DISK?
	PJUMPE	T2,INCCNT	;IF NOT(0), RETURN AND WRITE HIGH SEG
				; AFTER INCREMENTING IN-CORE COUNT TO 1
				; SO IT WILL NOT APPEAR IDLE DURING SWAP OUT
	MOVSI	T1,SHRSEG	;SHAREABLE SEGMENT?
	SKIPLE	SGTLIM##	;RETAINING HISEGS?
	SKIPE	ZAPIDF##	;YES FRUSTRATED?
	JRST	FORH2D		;NOT RETAINING OR FRUSTRATED
	TDNN	T1,JBTSTS##(J)	;RETAINING. SHAREABLE? (DON'T DELETE IF IT IS)
	JRST	FORH2D		;NOT SHAREABLE, GO DELETE CORE IMAGE (SHOULD NEVER GET HERE)
	LDB	T2,PCORSZ##	;ACCOUNT FOR MAKING SEGMENT IDLE IN CORE
	ADDI	T2,1		;WE KNOW IT IS NOT LOCKED, HAS CORE, IS
	ADDM	T2,CORTAL##	;SHAREABLE, & HAS NO OTHER USERS IN CORE
	JRST	RETJOB		;NOW SWAP OUT LOW SEGMENT
FORH2D:	PUSHJ	P,KCOREH	;ALREADY ON DISK, JUST RETURN CORE
				; AND FLAG HIGH SEG AS ON DISK(SET SWP=1)
RETJOB:	PUSHJ	P,CHKTAL	;CHECK CORTAL WITH CORTAB, HALT IF DIFFER
	MOVE	J,SWPOUT##	;RETURN JOB NUMBER(LOW SEG NUMBER)
	POPJ	P,		;AND TRY TO SWAP IT OUT

	
;SUBROUTINE TO EXPAND A HIGH (SHARABLE) SEGMENT AT UUO LEVEL
;CALL:	MOVE J, JOB OR HIGH SEG NO. EXPANDING
;	PUSHJ P,XPNHGH
;	ALWAYS RETURN WITH J=JOB NUMBER
;CALLED FROM XPANDH IN SCHED1.


XPNHGH::CAIG	J,JOBMAX##	;IS THIS A LOW SEG EXPANDING?
	POPJ	P,		;YES, RETURN IMMEDIATELY (MAYBE FROM
				; RECURSIVE CALL BELOW)
	TLNN	J,SHRSEG	;NO, IS THIS HIGH SEG NON-SHARABLE?
	JRST	XPNRET		;YES, JUST RETURN CURRENT JOB NO.
	PUSHJ	P,SAVE1##	;NO, SAVE P1 ON STACK
	MOVSI	T1,JXPN		;FLAG THIS SHARABLE HIGH SEG AS EXPANDING
	IORM	T1,JBTSTS##(J)	;SO IF OTHER JOBS GETSEG, THEY WILL BE SWAPPED OUT
	HRRZ	P1,J		;SAVE EXPANDING SHARABLE HIGH SEG NO.

;LOOP TO SCAN ALL JOBS FOR ONES USING THIS SHARABLE HIGH SEG AND FLAG JOBS AS EXPANDING IF IN CORE
	MOVE	J,HIGHJB##	;SCAN ALL JOBS INITIALIZED
	MOVEI	T1,(P1)		;HIGH SEG IN QUESTION
XPNLP1:	PUSHJ	P,FNDHSB	;FIND HIGH SEG FOR THIS JOB
	  SOJG	J,XPNLP1	;NOT FOUND; CHECK NEXT
	JUMPLE	J,XPNRET	;FINISHED?
	MOVSI	T1,SWP		;IS THIS JOB SWAPPED OR LOCKED IN CORE?
	TDNN	T1,JBTSTS##(J)	;
	PUSHJ	P,XPANDH##	;NO, EXPAND THIS JOB BY SWAPPING OUT (UNLESS LOCKED)
	MOVEI	T1,(P1)		;RESTORE # OF HIGH SEG IN QUESTION
	SOJG	J,XPNLP1	;FINISHED?
XPNRET:	MOVE	J,.CPJOB##	;YES, ALWAYS RETURN CURRENT JOB NO.
				; AS LOW SEG NO. ASSOCIATED WITH EXPANDING
				; HIGH SEG NO.
	POPJ	P,		;RETURN (RESTORE P1)

;ROUTINE TO CHECK FOR A HIGH SEG WITH SWAP READ ERROR
;CALLED FROM ZERSWP WHENEVER PHYSICAL DISK SPACE IS BEING RECLAIMED
;CALL:	MOVE J,LOW OR HIGH SEG NO.
;	PUSHJ P,ZERSWH
;	  LOW SEG OR NO ERROR IN HIGH SEG
;	ERROR IN HIGH SEG (ERROR BIT IS THEN CLEARED)


ZERSWH::MOVE	T2,JBTSTS##(J)	;SEGMENT STATUS WORD
	CAILE	J,JOBMAX##	;IS THIS A HIGH SEG?
	TLNN	T2,SERR		;YES, DOES IT HAVE A SWAP READ ERROR?
	POPJ	P,		;NO, RETURN AND RECLAIM PHYSICAL DISK SPACE
	MOVSI	T2,SERR		;YES, SWAP READ ERROR FLAG
	ANDCAM	T2,JBTSTS##(J)	;CLEAR IT IN HIGH SEG STATUS WORD
				; SO BE READY TO COUNT A NEW ERROR
				; IF IT OCCURS IN A NEW PLACE
	JRST	CPOPJ1##	;SKIP RETURN AND DO NOT RECLAIM DISK SPACE
				; SO NO ONE WILL BE ABLE TO USE IT

;SUBROUTINE TO DELETE ENOUGH DORMANT SEGS ON THIS UNIT TO MAKE ROOM
;ARGS	P2=NUMBER 1K BLOCKS NEEDED
;	U=ADDR OF UNIT DATA BLOCK
;PRESERVES P2,U,J
;CLOBBERS P1,P3 ***NOTE: VIOLATION OF SUB CALL CONVENTIONS (KCORE1)
;SKIP RETURN IF OK, NON-SKIP IF NOT



DODELE::PUSH	P,J
	PUSH	P,P1		;SAVE P1
	PUSH	P,P2
	MOVE	J,SEGPTR##
DODEL1:	LDB	T1,IMGOUT##	;GET SPACE ON DISK OF THIS SEG
	SKIPL	P1,JBTSTS##(J)	;SEG UNUSED? (SNA=0)
	CAIN	T1,0		;YES, SPACE ON DISK?
	JRST	DODEL3		;NO, KEEP LOOKING
	TLNE	P1,NSHF		;IS THIS SEGMENT CURRENTLY BEING SWAPPED OUT
	JRST	DODEL3		;YES, KEEP LOOKING
	SKIPL	T2,JBTSWP##(J)	;SEE IF THIS SEG HAS SPACE ON OUR UNIT
	JRST	DODELA		;NOT FRAGMENTED
	TLNN	P1,SWP		;IS THIS HIGH SEG SWAPPED OUT?
	TDZA	P1,P1		;NO, FLAG TO GET DISK ADDRESSES FROM MEMTAB
	MOVE	P1,JBTVAD##(J)	;YES, GET ADDRESSES FROM MAP
DODELC:	SKIPN	T1,T2		;NEW ENTRY
	JRST	DODEL3		;DONE, CAN'T HELP
DODELB:	SKIPG	T2,(T1)		;GET ENTRY IF ANY
	JRST	DODELC		;PROCEED IF LINK
	JUMPN	P1,DODELD	;IF SWAPPED OUT, DO IT DIFFERENTLY
	LDB	T2,[POINT SL.SPN,T2,^L<SL.PPN>+SL.SPN-1] ;GET PHYSICAL PAGE
	SSX	T2,MS.MEM
	LDB	T2,[POINT MT.SUN,MEMTAB(T2),^L<MT.UNT>+MT.SUN-1] ;GET UNIT NUMBER
DODELF:	CAMN	U,SWPTAB##(T2)	;SEE IF ITS US
	JRST	DODEL2		;YES, WE DO HAVE SPACE HERE!
	AOJA	T1,DODELB	;NO, TRY NEXT PIECE

DODELD:	ANDI	T2,SL.CNT	;SAVE ONLY COUNT
	PUSH	P,T2		;SAVE FOR NOW
	HLRZ	T2,(P1)		;GET UNIT PORTION OF DISK ADDRESS
	ANDI	T2,(PM.UNT)	;KEEP ONLY UNIT
	EXCH	T2,(P)		;GET COUNT BACK
	ADDI	P1,(T2)		;POINT TO WHERE NEXT ENTRY COMES FROM
	POP	P,T2		;GET UNIT
	JRST	DODELF		;AND SEE IF IT'S US

DODELA:	LDB	T1,JBYSUN##	;NOT FRAGMENTED, GET UNIT SEG IS ON
	CAME	U,SWPTAB##(T1)	;SKIP IF ON THIS UNIT
	JRST	DODEL3		;NO
DODEL2:	HLLM	J,(P)		;SAVE LEFT HALF OF J ON P=PART OF AOBJN PTR
	TLZ	J,-1		;CLEAR LH OF J SO J=SEGMENT NUMBER
	PUSH	P,P4		;CLRNAM COULD CLOBBER IT
	PUSHJ	P,CLRNAM	;DELETE THE DORMANT SEGMENT
	POP	P,P4		;STUFF THE CALLER WANTS
	HLL	J,(P)		;RESTORE LEFT HALF OF AOBJN PTR
	HRRZS	P2,(P)		;P2=NUMBER OF 1K BLOCKS NEEDED
	CAMG	P2,UNIFKS(U)	;SKIP IF STILL NOT ENOUGH SPACE
	JRST	DODELX		;DONE, EXIT
DODEL3:	AOBJN	J,DODEL1	;JUMP IF MORE SEGS
	SOS	-3(P)		;OFFSET SKIP RETURN, GIVE ERROR RETURN, NOT ENOUGH ROOM
DODELX:	POP	P,P2		;POP OFF NUMBER 1K BLOCKS NEEDED
	POP	P,P1
	JRST	IPOPJ1##

	
;SUBROUTINE TO SEE IF BY DELETING DORMANT SEGS WILL BE ENOUGH ROOM
; ON THIS UNIT
;ARGS	P2=NUMBER 1K BLOCKS NEEDED
;	U=ADDR OF UNIT DATA BLOCK
;CALL	MOVEI	P2,1K BLOCKS NEEDED
;	MOVEI	U,ADDR
;	PUSHJ	P,IFDELE
;	ERROR RETURN - CANT CREATE ENOUGH SPACE ON THIS UNIT
;	OK RETURN - CAN CREATE ENOUGH SPACE BY DELETING SEGS
;PRESERVES P1,P2,P3,P4,U,J

IFDELE::PUSH	P,J
	MOVE	T2,UNIFKS(U)	;T2 IS COUNTER OF AVAILABLE SPACE
	MOVE	J,SEGPTR##
IFDEL1:	LDB	T1,IMGOUT##	;GET DISK SPACE OF THIS SEG
	SKIPL	JBTSTS##(J)	;SEG UNUSED? (SNA=0)
	CAIN	T1,0		;YES, SPACE ON DISK?
	JRST	IFDEL3		;NO, KEEP LOOKING
	SKIPL	JBTSWP##(J)	;FRAGMENTED?
	JRST	IFDEL2		;NO
	PUSH	P,P1		;YES, SAVE P1
	PUSH	P,P3		;AND P3
	MOVSI	P3,SWP		;IS HIGH SEG SWAPPED?
	TDNN	P3,JBTSTS##(J)	;?
	TDZA	P3,P3		;NO
	MOVE	P3,JBTVAD##(J)	;YES, POINT TO MAP
	MOVE	T1,JBTSWP##(J)	;GET FRAGMENT POINTER
;	TLZ	T1,FRGSEG
IFDFK:	HRRZ	P1,T1		;P1=ADDR OF LIST
IFDFK1:	SKIPG	T1,(P1)		;POINTER OR DONE?
	JRST	IFDFK2		;YES
	ANDI	T1,SL.CNT	;SAVE ONLY COUNT
	JUMPN	P3,IFDFK5
	LDB	T3,[POINT SL.SPN,(P1),^L<SL.PPN>+SL.SPN-1] ;PHYSICAL PAGE
	SSX	T3,MS.MEM	;POINT TO MEMTAB
	LDB	T3,[POINT MT.SUN,MEMTAB(T3),^L<MT.UNT>+MT.SUN-1] ;UNIT
IFDFK3:	CAMN	U,SWPTAB##(T3)	;SEE IF ITS THE RIGHT UNIT
	ADD	T2,T1		;YES
	AOJA	P1,IFDFK1

IFDFK5:	HLRZ	T3,(P3)		;GET MAP ENTRY
	ANDI	T3,(PM.UNT)	;SAVE ONLY UNIT
	ADDI	P3,(T1)		;POINT TO NEXT ENTRY
	JRST	IFDFK3

IFDFK2:	JUMPN	T1,IFDFK	;NOT END OF LIST
	POP	P,P3
	POP	P,P1		;RESTORE P1
	JRST	IFDEL4


IFDEL2:	LDB	T3,JBYSUN##	;GET SWAPPING UNIT NUMBER
	CAMN	U,SWPTAB##(T3)
	ADD	T2,T1		;IF RIGHT UNIT, COUNT ITS SPACE
IFDEL4:	CAML	T2,P2		;HAVE ENOUGH YET?
	JRST	IPOPJ1##	;YEAH, MAN
IFDEL3:	AOBJN	J,IFDEL1	;NO, KEEP ON
	JRST	IPOPJ##		;CANT DO IT
	
SUBTTL	UUOCON - UUO HANDLING ROUTINES

;ROUTINE TO CHECK TO SEE IF A KNOWN SEGMENT IS BEING SUPERCEDED BY A FILE
;OF THE SAME NAME WITH EXTENSION OF .SHR IN THE SAME DIRECTORY.
;IF YES, THE SHARABLE SEGMENT IF FLAGGED AS NO LONGER SHARABLE FOR
;ADDITIONAL USERS(ITS NAME IS SET TO 0 IN JBTNAM).  THE USERS
;WHO ARE USING IT WILL CONTINUE TO SHARE IT UNTIL ALL OF THEM ARE THROUGH.
;IF NO USERS ARE USING SEGMENT ON DISK OR CORE, ITS DISK SPACE WILL BE RETURNED.
;CALLED FROM CLOSE INPUT AND OUTPUT DUMP AND BUFFERED(RELSEG) AND SUCCESSFUL RENAME(RELSG1)
;CALL:	MOVE F,ADR. OF DEVICE DATA BLOCK
;	PUSHJ P,RELSEG
;	ALWAYS RETURN (RELSEG)
;	ALWAYS SKIP RETURN (RELSG1)


RELSEG::TLNE	F,ENTRB		;HAS AN ENTER BEEN DONE(HERE ON CLOSE)?
				; IS THIS OUTPUT CLOSE?
				; I.E. WAS A FILE CREATED OR RECREATED?
 	PUSHJ	P,FNDSGU	;YES, DOES A KNOWN SEG ALREADY HAVE THIS NAME?
				; SEARCH USING OLD (RATHER THAN NEW) IF RENAME
	  POPJ	P,		;NO, NO CONFLICT
	JRST	RNMSG1		;YES, CLEAR NAME AND DELETE CORE AND DISK IF
				; BUT LEAVE DIRECTORY NAME FOR SYSTAT
				; SO IT CAN PRINT (OBS) P,P
				; HIGH SEGMENT IS ALREADY DORMANT


;ROUTINE TO RESET HIGH SEG
;CALLED ON RESET UUO
;SETS USER:MODE WRITE PROTECT BIT ON IN HARDWARE AND SOFTWARE FOR THIS
;JOB ONLY(CURRENT JOB). OTHER JOBS MAY HAVE UWP ON OR OFF FOR
;SAME HIGH SEGMENT(EXCEPT THAT INITIALLY SETUWP UUO DOES NOT ALLOW
;TURNING UWP OFF IF HIGH SEG SHARABLE)
;CALL:	MOVE J,CURRENT JOB NUMBER
;	PUSHJ P,HRESET
;	RETURN WITH APR RESET AND SOFTWARE RESET


HRESET::MOVEI	T1,JBTSGN##-.HBLNK(J) ;START OF CHAIN
HRESE1:	SKIPN	T1,.HBLNK(T1)	;NEXT
	JRST	SETMAP##	;GO DO DATAO APR AND SET UWP ON
	MOVSI	T3,UWPOFF	;UWP BIT
	AND	T3,.HBSGN(T1)	;GET STATUS OF BIT
	TLNN	T3,UWPOFF	;WAS UWP OFF?
	JRST	HRESE1		;YES
	ANDCAM	T3,.HBSGN(T1)	;IT WAS OFF, CLEAR UWPOFF
	MOVSI	T3,REDOMP	;FLAG TO REDO MAP FOR THIS SEGMENT
	IORM	T3,.HBSGN(T1)	;..
	JRST	HRESE1
	
;UUO ROUTINE TO SET OR CLEAR USER-MODE WRITE PROTECT(UWP)
;ON HIGH SEGMENT FOR CURRENT JOB
;CALL:	MOVEI AC,0 OR 1(CLEAR OR SET UWP)
;	MOVE J,CURRENT JOB NUMBER
;	PUSHJ P,USTUWP
;	ERROR RETURN - MACHINE OR MONITOR NOT HAVE 2 REG. CAPABILITY OR
;		TRYING TO TURN OFF UWP AFTER R HAS BEEN MEDDLED WITH
;		  AND USER DOES NOT HAVE WRITE PRIV. TO FILE WHICH INIT HIGH SEG
;		OR HIGH SEG IS A SPYSEG(IE PHYSICAL CORE)
;	OK RETURN - WHETHER JOB HAS HIGH SEG OR NOT
;		PREVIOUS SETTING OF UWP RETURNED IN AC(BOTH RETURNS)


USTUWP::PUSHJ	P,SAVE2##	;SAVE ACS P1-P2
	MOVE	P1,T1		;SAVE ARG
	SETZ	T1,		;GET FIRST SEGMENT THIS SECTION
	PUSHJ	P,NXSPCS	;GET IT
	  JRST	USTU0		;NO SEG, GIVE OK RETURN AND 0 AS SETTING
	PUSH	P,T1		;SAVE ADDR OF THIS SEGMENT
	PUSHJ	P,NXSPCS	;IS THERE ANOTHER SEGMENT HERE?
	  JRST	USTU2		;NO, ALL IS WELL
	POP	P,T1		;FIX STACK
	MOVE	J,.HBSGN(T1)	;SET J FOR CALL TO COMIT
	JRST	USTUE		;YERROR (AMBIGUOUS)

USTU2:	POP	P,T2		;SEGMENT DATA BLOCK ADDR

;SEGOP. CALLS HERE TO DO SETUWP FUNCTION
SOSUWP::MOVE	J,.HBSGN(T2)	;GET SEGMENT WORD
	SKIPE	T1,P1		;PUT ARG BACK IN T1
	JRST	UWPON		;USER TRYING TO TURN UWP ON
IFN FTPEEKSPY,<			;PEEK AND SPY
	JUMPL	J,USTUE		;NO, IS THIS A SPY SEG? (IF YES, GIVE ERROR RETURN)
>
	PUSHJ	P,CHKHWC	;NO, HAS CURRENT JOB AVOIDED MEDDLING OR
				;DOES CURRENT JOB HAVE WRITE PRIVILEGES TO FILE
				; EVEN THOUGH MEDDLING WITH PROGRAM?
				; MAYBE SHARED DATA SEGMENT WITH GETSEG UUO
USTUE:	  SOSA	(P)		;NO, THEN DO NOT ALLOW PROGRAM TO TURN OFF UWP
	TLOA	J,UWPOFF	;YES, SO OK TO TURN OFF UWP, EVEN IF THIS
				; IS SHARABLE HIGH SEG
UWPON:	TLZ	J,UWPOFF	;TURN OFF UWPOFF SO UWP WILL BE ON
	TLNE	J,UWPOFF	;WILL HIGH SEG BE WRITEABLE?
IFE FTMP,<
	PUSHJ	P,ZERSWP##	;YES, RETURN SWAPPING SPACE SO HIGH SEG
				; WILL HAVE TO BE WRITTEN WHEN JOB
				; IS SWAPPED OUT
>
IFN FTMP,<
	PUSHJ	P,[PUSHJ P,GGVMM## ;GET MM RESOURCE FOR CALL TO ZERSWP
		   PJRST ZERSWP##] ;RETURN SWAPPING SPACE, GIVE UP MM
>
	MOVE	T1,.CPJOB##	;CURRENT JOB NUMBER
	PUSHJ	P,COMIT		;COMPARE J WITH JBTSGN(T1), HALT IF DIFF.
	TLO	J,REDOMP	;FORCE MAP TO BE REDONE
	PUSHJ	P,SETSGN
	  EXCH	J,.HBSGN(T2)	;MARK NEW UWP SETTING FOR THIS USER AND GET OLD ONE
	TLNE	J,UWPOFF	;WAS UWP OFF?
USTU0:	TDZA	T1,T1		;YES, RETURN 0
	MOVEI	T1,1		;TELL HIM IT WAS ON
	PUSHJ	P,STOTAC##	;TO USER'S AC ARG
IFN FTKL10&FTMP,<
	PUSHJ	P,CLRCSH##	;CAUSE CACHE BITS TO BE CLEARED IN THE MAPS
				; OF ALL JOBS SHARING THIS HIGH SEGMENT SO
				; WRITTEN DATA WILL BE SEEN BY ALL
>
	SKIPN	.USWLP		;MAP IS RIGHT IF WRITE LOCKED PAGES
	PUSHJ	P,SETMAP##	;GO RESET HARDWARE AND SOFTWARE RELOC.
	JRST	CPOPJ1##	;AND RETURN TO THE USER
	
;ROUTINE TO CHECK ACCESS PRIVILEGES FOR SHARED SEGMENTS
;CALL:	MOVE J,HIGH SEG NUMBER
;	MOVEI P1,FUNCTION (FNCEXC,FNCRED,FNCUPD)
;	MOVE P2,JOB NUMBER
;	PUSHJ P,CHKHSA
;	CAN'T READ OR WRITE
;	USER HAS PRIV IF SHARABLE, OR HIGH SEG NOT SHARABLE
;CHKHSW IS WRITE ENTRY POINT, CHKHWC IS WRITE FOR CURRENT JOB
;DTA READ OK IF DEVICE UNASSIGNED,SYSTEM, OR ASSIGNED TO THIS JOB
;DTA WRITE OK IF DEVICE UNASSIGNED OR ASSIGNED TO THAT JOB, EXCEPT CAN'T
;DEPOSIT SYSTEM TAPE
;CALLED FROM SAVGET TO SEE IF USER HAS READ PRIVILEGES TO SHARE
;CALLED FROM DEPOSIT COMMAND IF IN HIGH SEG TO SEE FI WRITE PROV
;CALLED FROM SETUWP IF TRY TO SET UWP TO 0 AND MEDDLE BIT IS ON TO
; SEE IF WRITE PRIV. OK



;ROUTINE TO CHECK WRITE PRIV FOR CURRENT JOB IF MEDDLING
				;GIVE OK RETURN IF CURRENT JOB NOT MEDDLING
CHKHWC::TLNN	J,MEDDLE	;HAS CURRENT USER BEEN MEDDLING WITH ITS HIGH SEG?
				; OR IS THIS A SPY SEG?
	PJRST	CPOPJ1##	;NO, GIVE OK TO UPDATE THIS HIGH SEG RETURN
	MOVE	P2,.CPJOB##	;YES, CHECK UPDATE PRIVILEGES FOR CURRENT JOB
;ROUTINE TO CHECK WRITE PRIV
CHKHSW:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	P1,PR.WRT##	;CHECK FOR WRITE PROTECTION
CHKHSA:	TLNN	J,SHRSEG	;IS THIS HIGH SEG SHARABLE?
	JRST	CPOPJ1##	;NO, ALWAYS OK TO READ OR WRITE
	PUSH	P,J		;SOME MAY WANT IT
	HRRZS	J		;CLEAR LEFT
	SKIPN	T2,JBTPPN##(J)	;YES, IS HIGH SEG FROM DTA OR MTA
				; DIRECTORY NAME IS 0 ON DTA,MTA
	JRST	CHKHS3		;YES, GO SEE IF DEVICE IS AVAILABLE
	TLNN	T2,-1		;FROM AN SFD?
	MOVE	T2,(T2)		;YES, GET THE PPN
	MOVE	T3,JBTPPN##(P2)	;SET REQUESTORS DIRECTORY PPN
	MOVE	T1,P1		;SETUP HIGH SEG ACCESS PRIV
	LDB	T4,JBYSPR##	;HIGH SEG ACCESS PRIV
	MOVE	J,P2		;SETUP JOB NUMBER
	PUSHJ	P,CHKACC##	;GO CHECK ACCESS PRIV (IN DISK SERVICE)
	  PJRST	JPOPJ##		;ERROR - CANNOT ACCESS,RESTORE HIGH SEG NO
	PJRST	JPOPJ1##	;OK TO ACCESS, RESTORE HIGH SEG NO.
CHKHS3:	MOVE	T1,JBTDEV##(J)	;DEVICE NAME OF DTA OR MTA
	PUSHJ	P,DEVPHY##	;YES, SEARCH FOR PHYSICAL DEVICE
	JRST	JPOPJ
	TLNE	F,SYSDEV	;SYSTEM TAPE?
	JRST	CHKHS2		;NO
	LDB	P3,PJOBN##	;JOB DEVICE ASSIGNED TO, IF ANY
	JUMPE	P3,JPOPJ1##	;IS NON-SYSTEM DEVICE ASSIGNED?
				; ALWAYS READ OR WRITE IF UNASSIGNED
	CAMN	P3,P2		;YES, IT IT ASSIGNED TO THIS JOB?
	JRST	JPOPJ1
	JRST	JPOPJ

CHKHS2:	CAIGE	P1,PR.WRT##	;YES, TRYING TO WRITE(UPDATE)CLEAR UWP OR DEPOSIT)
	JRST	JPOPJ1
	JRST	JPOPJ

	
;UUO TO ALLOW PRIVILEGED USER PROGRAM TO LOOK AT ALL OF CORE
; BY HAVING PHYSICAL CORE APPEAR AS HIGH SEG
; ANY PROGRAMS WRITTEN TO USE THIS UO SHOULD BE PROGRAMMED TO USE THE
; PEEK UUO TOO, IN CASE THIS MACHINE OR MONITOR DOES NOT HAVE 2 RELOC. REG.
; OR INSTALLATION DECIDES TO MAKE THIS UUO RESTRICTED
; THIS UUO IS PROVIDED ONLY FOR EFFICIENT, SINCE IT NEED ONLY BE DONE
; ONCE, WHILE PEEK UUO MUST BE DONE FOR EVERY WORD EXAMINED
;CALL:	HRRI AC,HIGHEST PYHSICAL ADR. TOAPPEAR IN HIGH SEG
;	CALL AC,[SIXBIT /SPY/] OR CALLI AC,42
;	ERROR RETURN, ADR. TOO IGH OR THIS USER CAN'T USE
;	 THIS UUO, OR NOT 2 RELOC. REG. MACHINE
;	OK RETURN, HIGH SEG SETUP IN ADDRESSING SPACE
;NOTE: A SPYSEG APPEARS TO THE SYSTEM AS IF TIS USER DOES NOT HAVE A HIGH SEG
; IN ALL CASES EXCEPT WHEN THE RELOC. HARDWARE IS SET. THIS IS BECAUSE
; THE SIGN BIT OF JBTSGN(JOBNUMBER) IS SET TO INDICATE SPY SEG
; AND THE MONITOR CHECK FOR REAL HIGH SEGS SITH SKIPG INSTR.
; THE RH OF JBTSGN(JOBNUMBER) HAS HIGHEST LEGAL PHY. ADR.
; FOR THIS USER TO LOOK AT(CARE IS TAKEN SINCE THIS IS MUCH BIGGER THAN A
; HIGH SEG NUMBER WHICH IS USUALLY IN RH)

IFN FTPEEKSPY,<
USPY::	MOVSI	T1,PVSPYM!PVSPYA
	PUSHJ	P,PRVBIT##	;IS USER PRIVILEGED TO SPY?
	  TDZA	T1,T1		;YES
	POPJ	P,0		;NO, ERROR RETURN
	PUSH	P,J		;SAVE J
	PUSHJ	P,NXSPCS	;GET ANY SEG
	  JRST	USPY0		;CONTINUE IF NONE
	PUSHJ	P,VERWAT##
	SKIPA
	PUSHJ	P,PRRBKC
	SETZ	T1,		;KILL ALL HIGH SEGS IN SECTION
IFN FTMP,<
	PUSHJ	P,UPMM##	;GET MM
>
	PUSHJ	P,KILHGC	;YES, REMOVE PREVIOUS HIGH SEG FROM LOGICAL
IFN FTMP,<
	PUSHJ	P,DWNMM##	;RETURN MM
>
				;ADR. SPACE, IF ANY INCLUDING PREVIOUS SPY SEG
USPY0:	POP	P,J		;RESTORE J
	PUSHJ	P,GETWDU##	;GET USER'S COR ARG ON UUO
	JUMPE	T1,SETRL1	;DOES HE WANT TO SPY AT ALL?
				; IF 0, SET RELOC HARDWARE AND SKIP RETURN
	TLZN	T1,-1		;YES, ANY LH BITS (CLEAR FOR COMPARE)?
	CAML	T1,MEMSIZ##	;NO, IS HIGHEST ADR. USER WANTS ABOVE MONITOR?
	PJRST	SETMAP##	;YES, ERROR RETURN TO USER (AFTER SETTING HARDWARE)
	PUSH	P,T1		;SAVE USER'S ARGUMENT
	CAMGE	T1,SYSSIZ##	;TRYING TO SPY BEYOND END OF MONITOR ?
	JRST	USPY1		;NO, O.K.
	MOVSI	T1,PVSPYA	;YES, IS HE PRIVILEGED TO DO SO ?
	PUSHJ	P,PRVBIT##	;
	  JRST	USPY1		;YES, O.K.
	POP	P,T1		;NO, ERROR RETURN
	PJRST	SETMAP##
USPY1:	POP	P,T3		;RESTORE ARGUMENT
	TRO	T3,PG.BDY	;INSURE AT LEAST ONE PAGE
				; (ALSO MAKE SURE RH CAN NOT LOOK LIKE A HIGH SEG NO.)
	HRLI	T3,SPYSEG!MEDDLE;FLAG THIS USER AS SPYING
	MOVEI	T1,T3-.HBSGN	;FAKE UP HIGH SEG DATA BLOCK FOR HSVAD
	SETZM	.HBSPO(T1)	;FORCE HSVAD TO COMPUTE ORIGN
	PUSHJ	P,HSVAD		;CALCULATE ORIGIN OF SPY SEG IN USER'S ADR SPACE
	TLNE	T1,-1		;TOP VIRTUAL ADDRESS BEYOND 256K
	PJRST	SETMAP##	;YES, GIVE ERROR RETURN
IFN FTXMON,<
	XSFM	T4		;GET PCS
	ANDI	T4,MXSECN	;IGNORE POSSIBLE JUNK
	HRLI	T1,(T4)		;CKNZ1 WANTS RESOLVED ADDRESSES
	HRLI	T2,(T4)		;SO ONLY DO THIS IN S0 IF SO REQUESTED
> ;END IFN FTXMON
	PUSHJ	P,CKNZ1##	;WILL THE SPY SEG OVERLAP THE LOW SEGMENT?
	  PJRST	SETMAP##	;YES, GIVE ERROR RETURN
	PUSH	P,T2		;SAVE T2 (ORIGIN ADDRESS)
	PUSH	P,T3		;SAVE SEGMENT WORD
	PUSHJ	P,MAKHSB
	  JRST	[POP	P,T3	;RESTORE T3
		 POP	P,T2	;AND T2
		 PJRST	SETMAP]	;FINISH UP
	POP	P,.HBSGN(T1)	;STORE SEGMENT WORD
	POP	P,.HBSPO(T1)	;INSERT ORIGIN PAGE (CLEARING REST)
	EXCH	T1,JBTSGN##(J)	;STORE IT AND GET OLD
	HLLM	T1,JBTSGN##(J)	;PRESERVE BITS
	HRRZ	T2,JBTSGN##(J)	;ADDRESS OF NEW BLOCK
	HRRZM	T1,.HBLNK(T2)	;LINK TO NEXT
	JRST	SETRL1		;OK RETURN TO USER AFTER SETTING HARDWARE
>				;END CONDITIONAL ON FTPEEKSPY
IFE FTPEEKSPY,<
USPY==:CPOPJ##
>

;SUBROUTINE TO SEE IF F POINTS AT A KNOWN SEGMENT WHEN NOT
; IN THE CONTEXT OF THE MONITOR JOB (RENAME OR SUPERCEDING CLOSE)
FNDSGU:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSH	P,M		;SAVE M FOR UUO ARGS
	PUSH	P,.JDAT+SGAPPN## ;SAVE POSSIBLE USER AC
	MOVE	T1,.CPJOB##
	PUSH	P,JBTSTS##(T1)	;SAVE STATE OF JS.ASA
	PUSHJ	P,SETASJ##	;SET JS.ASA
	MOVEI	T1,JOBUAL##+MAXLVL##+2 ;WHERE FNDSEG LOOKS FOR PATH PTR
	MOVEM	T1,.JDAT+SGAPPN## ;STORE POINTER TO PATH
	PUSHJ	P,PTHFIL	;GET PATH
	POP	P,T1
	MOVE	J,.CPJOB##	;JOB NUMBER
	TRNN	T1,JS.ASA
	PUSHJ	P,CLRASA##	;CLEAR JS.ASA
	PUSHJ	P,FNDSEG	;A KNOWN SEGMENT?
	  SOS	-2(P)		;NO, SET FOR NON-SKIP RETURN
IFN FTMP,<
	PUSHJ	P,TGVMM##	;FNDSEG MAY RETURN WITH THE MM
>
	POP	P,.JDAT+SGAPPN## ;AND SGAPPN
	MOVE	T4,DEVSER(F)	;RESTORE DEVICE DISPATCH
	MOVE	S,DEVIOS(F)	; AND DEVIOS
	POP	P,M		;RESTORE M
	JRST	CPOPJ1##	;AND GIVE FOUND OR NOT ROUND RETURN
;ROUTINE TO SCAN KNOWN SEG TABLE(JBTPPN/JBTNAM) TO SEE IF A SEG IS ALREADY
;IN IT AFTER FILE HAS BEEN LOOKED UP AND  WRITTEN OR RENAMED
;CALL:	MOVE F,DEVICE DATA BLOCK ADDRESS OF DEVICE WITH FILE
;	PUSHJ P,FNDSEG
;	NOT FOUND RETURN, OR FILE EXT WAS NOT SHR, OR DEVICE HAS SHORT DISP TABLE
			;C(J)=GARBAGE
;	FOUND RETURN, C(J)=HIGH SEG NUMBER(LH=SHRSEG)
;		C(T1)=DIRECTORY NAME(PROJPROG NO IF DISK, 0 IF MTA OR DTA
;		C(T2)=FILE NAME
;		C(U)=DEVICE OR FILE STRUCTURE NAME
;CALLED FROM RELSEG(CLOSE OUTPUT AND SUCCESSFUL RENAME)
;AND GET AFTER INPUT
;MUST BE CALLED AT UUO LEVEL



IFN FTMP,<
;TRY TO FIND A KNOWN SEGMENT, ALWAYS RETURN WITH THE MM
FNDSMM:	PUSHJ	P,FNDSEG
	  SOS	(P)
	PUSHJ	P,MMOWN##
	  PUSHJ	P,UPMM##
	JRST	CPOPJ1##

;TRY TO FIND A KNOWN SEGMENT, RETURNS WITH THE MM ONLY IF FOUND
FNDSMS:	PUSHJ	P,FNDSEG
	  JRST	TGVMM##
	JRST	CPOPJ1##
>
IFE FTMP,<
FNDSMM:
FNDSMS:
>
FNDSEG:	PUSHJ	P,NAMSTR##	;GET FILE STRUCTURE NAME
	  SKIPA	U,DEVNAM(F)	;DEVICE NOT A DISK, USE PHYSICAL NAME
	MOVE	U,T1		;SETUP F.S. NAME
	MOVE	T2,DEVMOD(F)	;DEVICE CHARACTERISTICS
	HLRZ	T1,DEVEXT(F)	;FILE EXTENSION
	TLNE	T2,DVLNG	;IS DEVICE HAVE FILES(MTA,DTA,DSK)?
	CAIE	T1,(SIXBIT /SHR/) ;YES, IS EXTENSION SHR?
	CAIN	T1,(SIXBIT /EXE/) ;ALLOW EXE FILES AS SHARABLE
	SKIPA			;SKIP OVER POPJ IF EXE
	JRST	ZPOPJ##		;NO, DO NOT LOOK FOR NAME IN KNOWN TABLE
	TLNE	T2,DVDSK	;IS THIS DEVICE A DISK?
	SKIPA	T1,DEVPPN(F)	;YES, GET PROJECT-PROGRAMMER NUMBER
	MOVEI	T1,0		;NO, SET DIR TO 0, MUST BE DTA OR MTA
	MOVE	T2,DEVFIL(F)	;GET FILE NAME FROM DEVICE DATA BLOCK
				; OLD (RATHER THAN NEW) IF RENAME
				;FALL INTO SERSEG
	


;ROUTINE SAME AS FNDSEG, EXCEPT DEVICE NOT LOOKED UP(CALLED FROM GET WHEN DEVICE IS DTA)
;USED TO AVOID DOING OPEN AND LOOKUP WHEN DEVICE IS DTA
;SINCE OPEN MAY QUEUE FOR SYS AND LOOKUP SPINS TAPE
;CALL:	MOVE T1,PROJ,PROG NO IF DISK, ZERO IF DTA OR MTA
;	MOVE T2,FILE NAME
;	MOVE U,DEVICE NAME OR FILE STRUCTURE NAME
;	PUSHJ P,SRCSEG
;	NOT FOUND RETURN
;	FOUND RETURN - J SET UP TO HIGH SEG NUMBER
;		LH OF J SET AS SHARABLE(SHRSEG=1)
;		(MEDDLE=UWPOFF=SPYSEG=0)
;RETURNS WITH THE MM RESOURCE

SRCSEG:
IFN FTMP,<
	PUSH	P,.JDAT+SGAPPN## ;SAVE PATH POINTER IN CASE JS.ASA NOT SET
	PUSHJ	P,UPMM##	;MUST HAVE THE MM TO SEARCH TABLES
	POP	P,.JDAT+SGAPPN## ;RESTORE SAME
>
	MOVE	J,SEGPTR##	;POINTER TO JUST HIGH SEGMENTS IN JOB TABLES
FNDLOP:	CAMN	U,JBTDEV##(J)	;DO DEVICE(STR) NAMES MATCH?
	CAME	T2,JBTNAM##(J)	;DO FILE NAMES MATCH?
FNDLP1:	AOBJN	J,FNDLOP	;NO
	JUMPGE	J,CPOPJ##	;JUMP IF NO MATCH
	PUSHJ	P,PTCMP		;DO PATHS MATCH?
	  JRST	FNDLP1		;NO, LOOK AT NEXT SEGMENT
	HRLI	J,SHRSEG	;INDICATE SHARABLE
	JRST	CPOPJ1##	;AND GIVE FOUND RETURN

;SUBROUTINE TO CHECK IF A PATH TO A FILE MATCHES A PATH TO A HIGH SEGMENT

PTCMP:	SKIPE	T4,.JDAT+SGAPPN## ;IS THERE A DIRECTORY OR A PATH?
	TLNE	T4,-1		;SKIP IF THE USER SPECIFIED A PATH
	JRST	[CAMN T1,JBTPPN##(J) ;NOT A PATH, DO DIRECTORIES MATCH?
		 AOS (P)	;YES, FOUND
		 POPJ P,]	;GIVE FOUND OR NOT FOUND RETURN
	PUSHJ	P,SAVT##	;SAVE T1 AND T2
	PUSH	P,M		;AND M
	PUSH	P,J		;AND J
	SKIPE	T3,JBTPPN##(J)	;IS THERE A DIRECTORY OR PATH?
	TLNN	T3,-1		;YES, SKIP IF A DIRECTORY
	JRST	PTCMP0		;A PATH SO SEE IF THEY MATCH
	HRRI	M,3(T4)		;FIRST SFD
	MOVE	T3,T1		;SAVE PPN
	PUSHJ	P,GETWDU##	;GET FIRST SFD OR 0
	JUMPN	T1,PTCMP3	;IF SFDS WERE SUPPLIED, PATHS DON'T MATCH
	MOVE	J,(P)		;RESTORE SEGMENT NUMBER
	CAMN	T3,JBTPPN##(J)	;NO SFDS, PPNS MATCH?
	JRST	PTCMP2		;YES, PATHS MATCH
	JRST	PTCMP3		;NO, NO MATCH
PTCMP0:	HRRI	M,1(T4)		;ADDRESS OF PATH-1
PTCMP1:	PUSHJ	P,GETWD1##	;GET THE NEXT ELEMENT OF THE PATH TO THE SEGMENT?
	CAME	T1,(T3)		;USER PATH SAME AS PATH TO THIS HIGH SEGMENT?
	JRST	PTCMP3		;NO, NO MATCH
	SKIPE	(T3)		;LAST SFD?
	AOJA	T3,PTCMP1	;NO, SEE IF NEXT MATCHES
PTCMP2:	AOS	-2(P)		;GIVE FOUND RETURN
PTCMP3:	POP	P,J		;RESTORE J
	JRST	MPOPJ##		;RESTORE M AND RETURN
;ROUTINE TO GET WORD FROM HIGH SEGMENT IN CORE
;CALL:	MOVE J,JOB NO.
;	MOVE M,RELATIVE(USER) ADDRESS IN HIGH SEGMENT
;	PUSHJ P,HGHWRD
;	ERROR RETURN, ADR NOT IN HIGH SEG OR NO HIGH SEG
;	OK RETURN, CONTENTS OF LOC RETURNED IN T1
;	T2 CONTAINS ADDRESS OF APPROPRIATE HIGH SEG DATA BLOCK
;	ABS. OR USER VIRTUAL ADR. OF LOC RETURNED IN AC T2(USED BY DEPOSIT)

;CAN BE CALLED AT CLOCK OR UUO LEVELS
;CALLED FROM E COMMAND AND CALL,INIT UUOS,SAVE AND GET JOBS


HGHWRD::HLRZ	P1,M		;GET SEGMENT NUMBER
	TDZA	T1,T1		;START AT THE BEGINNING
HGHWR1:	POP	P,T1
	PUSHJ	P,GNXHSB	;GET NEXT SEGMENT THIS SECTION
	  POPJ	P,		;WORD NOT IN HIGH SEG
	PUSH	P,T1
	PUSHJ	P,HSVAD
	CAIG	T2,(M)
	CAIGE	T1,(M)
	JRST	HGHWR1		;LOOK AT NEXT
	EXCTUX	<MOVE T1,(M)>	;GET CONTENTS OF THAT WORD
	PJRST	T2POJ1##	;OK RETURN

	
;ROUTINE TO FLAG SHARABLE SEGMENT AS NO LONGER SHARABLE AND RETURN
;DISK OR CORE IF POSSIBLE, THEN DISPATCH TO SERVICE ROUTINE TO DO RENAME
;CALL:	MOVE	F,ADDRESS OF DEVICE DATA BLOCK
;	PUSHJ	P,RNMSEG
;CALLED FROM RENAME


RNMSEG::PUSHJ	P,FNDSGU	;DOES A KNOWN SEGMENT HAVE OLD NAME?
	  PJRST	UDREN##		;NO SO TRY RENAME
	PUSH	P,J		;YES,SAVE HIGH SEGMENT#
	PUSHJ	P,UDREN##	;ATTEMPT A RENAME
	  JRST	JPOPJ##		;FAILURE
	POP	P,J
	AOS	(P)		;GIVE SUCCESS RETURN
RNMSG1:
IFN FTMP,<
	PUSHJ	P,GGVMM##	;GET MM RESOURCE FOR CALL TO CLRNAM
>
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	JRST	CLRNM1		;CLEAR NAME AND DELETE DISK AND CORE IF ANY
				;AND RETURN

;SUBROUTINE TO LOOKUP A FILE AND RETURN THE PATH TO IT

LUPFIL:	LOOKUP	0,SGANAM##	;LOOKUP THE HIGH SEGMENT
	  POPJ	P,		;LOOKUP ERROR
	MOVEI	T1,JOBUAL##	;WHERE PATH WILL BE STORED
	MOVEM	T1,.JDAT+SGAPPN## ;INDICATE PATH IS KNOWN
	AOS	(P)		;LOOKUP SUCEEDED
	TDZA	T1,T1		;DO PATH ON CHANNEL 0
PTHFIL::HLRZ	T1,.USCTA	;DO PATH ON PROGRAM'S CHANNEL
	HRRZ	T3,.JDAT+SGAPPN## ;ASSUME ITS NOT A DISK
	EXCTXU	<SETZM	(T3)>
	MOVE	T2,DEVMOD(F)	;DEVICE CHARACTERISTICS
	TLNN	T2,DVDSK	;A DISK?
	POPJ	P,		;NO, ALL DONE
	EXCTXU	<MOVEM	T1,(T3)>  ;CHANNEL NUMBER FOR PATH UUO
	HRLI	T3,MAXLVL##+3
	PUSH	P,F		;PATH MIGHT CHANGE F
	PUSH	P,.JDAT+SGANAM## ;SAVE TEMP
	MOVEM	T3,.JDAT+SGANAM## ;STORE ARGUMENT POINTER
	PATH.	0,		;PATH SGANAM,
	  STOPCD	.+1,JOB,PUF, ;++PATH UUO FAILED
	POP	P,.JDAT+SGANAM## ;RESTORE SGANAM
	JRST	FPOPJ##		;AND RETURN
;SUBROUTINE TO FIND A (NON-SHARABLE) HIGH SEGMENT IN THE PCS SECTION
;RETURNS CPOPJ1 IF A NON-SHARABLE HIGH SEG WAS FOUND (T1 POINTS TO HI SEG BLK)
;RETURNS CPOPJ IF EITHER NO SEGMENTS FOUND IN PCS SECTION OR
;ONLY SHARABLE ONES.  T1 IS CLEAR IF NO SEGMENTS FOUND; NON-ZERO OTHERWISE
;J HAS JOB #

FNSPCS::
	PUSH	P,[0]		;HIGH SEG DATA BLOCK FOR SEGMENT
	PUSH	P,T2		;SAVE T2
	PUSH	P,T4		;AND T4
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;POINT TO SEGMENT DATA BLOCKS
	XSFM	T4
	ANDI	T4,MXSECN	;GET SECTION
	PUSHJ	P,RSECT4##	;RESOLVE SECTION #
	  JFCL
FNSPC1:	HRRZ	T1,.HBLNK(T1)	;NEXT SEGMENT DATA BLOCK
	JUMPE	T1,FNSPC2	;IF NO MORE
	LDB	T2,[PSG2LH+.HBSG2(T1)] ;GET SECTION
	CAIE	T2,(T4)		;MATCH?
	JRST	FNSPC1		;NO, LOOK AT NEXT
	SKIPL	J,.HBSGN(T1)	;SEGEMENT #
	SKIPN	-2(P)		;RETURN SPY IF POSSIBLE
	MOVEM	T1,-2(P)	;SAVE AS LAST SEGMENT FOUND IN SECTION
	JUMPLE	J,FNSPC1	;IF SPY OR NON-EX, LOOP
	TLNE	J,SHRSEG	;OR SHARABLE?
	JRST	FNSPC1		;YES, LOOK FOR A NON-SHARABLE ONE
FNSPC2:	POP	P,T4		;RESTORE T4
	POP	P,T2		;AND T2
	POP	P,T1		;RESTORE SEGMENT FOUND (IF ANY)
	SKIPE	J,T1		;IF ZERO, RETURN ZERO IN EVERYTHING
	SKIPLE	J,.HBSGN(T1)	;IF ONLY FOUND SPY
	TLNE	J,SHRSEG	;OR SHARABLE
	POPJ	P,		;THEN GIVE ERROR RETURN
	JRST	CPOPJ1##

;SUBROUTINE TO FIND THE HIGH SEG DATA BLOCK WHERE T1 IS THE SEGMENT #
;AND J IS THE CONTEXT WHICH OWNS THE SEGMENT. SAME A FNDHSB EXCEPTS
;CONTEXT HANDLE (INSTEAD OF JOB NUMBER) IN J.

CFNDHB::PUSH	P,T1		;SAVE SEGMENT NUMBER
	PUSH	P,T2		;SAVE T2
	MOVE	T1,J		;CONTEXT NUMBER TO T1
	PUSHJ	P,CTXSGN##	;GET JBTSGN FOR THAT CONTEXT
	  JRST	TTPOPJ##	;NO SUCH
IFN .HBLNK,<SUBI T1,.HBLNK>	;FOR FIRST REFERENCE
	JRST	FNDHS2		;FIND THE SEGMENT DATA BLOCK

;SUBROUTINE TO FIND THE HIGH SEG DATA BLOCK WHERE T1 IS THE SEGMENT #
;AND J IS THE JOB WHICH OWNS THE SEGMENT.  EXIT CPOPJ IF NONE FOUND,
;CPOPJ1 OTHERWISE WITH T1 POINTING AT HIGH SEG DATA BLOCK

FNDHSB::PUSH	P,T1		;SAVE T1
	PUSH	P,T2		;AND T2
	MOVEI	T1,JBTSGN##-.HBLNK(J) ;POINT TO START
FNDHS1:	HRRZ	T1,.HBLNK(T1)	;POINT TO SEG DATA BLOCK
FNDHS2:	JUMPE	T1,TTPOPJ##	;NOT FOUND, RESTORE STUFF AND RETURN
	MOVE	T2,.HBSGN(T1)	;GET SEGMENT #
	XOR	T2,-1(P)	;DIFFS WITH SEG #
	TDNE	T2,[SPYSEG,,-1]	;COMPARE SEG # AND/OR SIZE AND SPY BIT
	JRST	FNDHS1		;NO, SEARCH ON
	MOVEM	T1,-1(P)	;STORE ADDRESS TO RETURN
	AOS	-2(P)		;SKIP RETURN
	JRST	TTPOPJ##	;SET, RESTORE, AND RETURN

;SUBROUTINE TO FIND "NEXT" SEGMENT IN PCS SECTION
;FIRST CALL:  SET T1 TO ZERO
;SUBSEQUENT CALLS:  T1 CONTAINS ADDR OF HIGH SEG DATA BLOCK OF LAST RETURN
;RETURN CPOPJ WHEN THERE ARE NO MORE BLOCKS
;RETURN CPOPJ1 WITH T1 POINTING AT NEXT HIGH SEG DATA BLOCK FOR SEGMENT
;IN PCS SECTION
;FOR FIRST CALL, J MUST CONTAIN JOB NUMBER
;ALTERNATE ENTRY POINTS:  GNXHSB:  STEP THROUGH ALL SEGMENT BLOCKS
;NXSSP1:  SEARCH FOR ALL SEGMENTS IN SECTION # INDICATED BY P1

GNXHSB::
	PUSHJ	P,SAVE1##		;SAVE P1
	SETO	P1,			;ALL SECTIONS
	JRST	NXSSP1			;SEARCH
NXSPCS::
	PUSHJ	P,SAVE1##		;SAVE P1
	XSFM	P1			;SECTION # TO P1
	ANDI	P1,MXSECN
NXSSP1::				;ENTER HERE WITH SECTION # IN P1
	SKIPN	T1			;T1 NON-ZERO?
	MOVEI	T1,JBTSGN##-.HBLNK(J)	;GET START OF SEG DATA BLOCKS
	PUSH	P,T2			;SAVE T2
	JUMPL	P1,NXSPC1		;DON'T RESOLVE -1
	EXCH	T4,P1			;SAVE T4, PUT SECTION # THERE
	PUSHJ	P,RSECT4##		;RESOLVE SECTION #
	  JFCL
	EXCH	T4,P1
NXSPC1:	HRRZ	T1,.HBLNK(T1)		;NEXT BLOCK
	JUMPE	T1,T2POPJ##		;DONE
	JUMPL	P1,T2POJ1##		;IF P1=-1, WANT ALL SECTIONS
	LDB	T2,[PSG2LH+.HBSG2(T1)]	;SECTION #
	CAIE	T2,(P1)			;THIS ONE?
	JRST	NXSPC1			;NO LOOK ON
	JRST	T2POJ1##		;RETURN
;ROUTINE TO ALLOCATE A HIGH SEGMENT MAP
;SEG NUMBER IN J, T1 HAS # OF WORDS REQUIRED FOR SEGMENT
;EXPANDS EXISTING MAP, OR COPIES OLD MAP TO NEW IF REQUIRED.
;RETURN WITH T1 CONTAINING VIRTUAL ADDRESS OF NEW MAP (FIRST MAP SLOT)

GTHMAP::
	PUSHJ	P,SAVE1##	;SAVE A WORKING AC
	PUSHJ	P,SAVR##	;SAVE R
	SE1ENT			;EXECUTE IN SECTION 1
	PUSH	P,J		;SAVE SEGMENT #
	HRRZS	J		;CLEAR JUNK
GTHMP1:	SKIPN	P1,JBTVAD##(J)	;IS THERE ALREADY A MAP?
	JRST	NEWHMP		;NO
	HRRZ	J,.M2SIZ-.M2MAP(P1) ;GET SIZE OF THIS MAP
	CAIGE	J,(T1)		;MORE SLOTS IN CURRENT MAP THAN REQUESTED?
	JRST	EXTHMP		;NO, EXTEND CURRENT MAP
	HRRZ	J,(P)		;GET SEGMENT #
	XMOVEI	T1,HRDOMP	;MAKE SURE ALL USERS OF SEGMENT HAVE MAP REDONE
	PUSHJ	P,HGHAPP
	JRST	GTHMP7		;LOAD T1 AND RETURN
EXTHMP:				;HERE TO EXTEND MAP IF POSSIBLE
;	(INSERT CODE HERE)
NEWHMP:	MOVEI	T2,.M2MAX(T1)	;SIZE OF HIGH SEG, +OVERHEAD
IFE FTXMON,<			;ROUND UP REQUEST TO FOUR-WORD MULTIPLE
	TRZE	T2,3
	ADDI	T2,4
	MOVNI	T1,.M2MAX	;GET NUMBER OF MAP SLOTS
	ADD	T1,T2		;(PUT EXTRA WORDS IN MAP SLOTS)
>
	PUSH	P,T1		;SAVE # OF WORDS REQ'D
	LSH	T2,1		;*2
IFN FTXMON,<			;IF USING GIVWDS, IN 4-WORD MULTIPLES ANYWAY
	SOS	T2		;-1
>
	MOVE	J,.CPJOB##	;POINT J AT A JOB
IFN FTXMON,<
	PUSHJ	P,GFWNZS##	;THAT MUCH CORE FOR 2NDARY PAGE MAP
>
IFE FTXMON,<
	PUSHJ	P,GETWDS##
>
	  JRST	[POP	P,T1
		 POP	P,J	;RESTORE T1 AND J
		 POPJ	P, ]	;AND RETURN
	HRRZ	J,-1(P)		;GET SEG # BACK AGAIN
	CAME	P1,JBTVAD##(J)	;SOMEONE SNEAK IN WHILE WE WERE BLOCKED?
	JRST	[MOVE	T2,T1	;YES, RETURN THIS BLOCK AND LOOK AGAIN
		 POP	P,T1	;COMPUTE # OF WORDS WE ASKED FOR
		 MOVEI	T1,.M2MAX(T1)
		 LSH	T1,1
		 SOS	T1
		 MOVE	J,.CPJOB##
IFN FTXMON,<
		 PUSHJ	P,GVFWDS##
>
IFE FTXMON,<
		 PUSHJ	P,GIVWDS##
>
		 HRRZ	J,(P)
		 JRST	GTHMP1]
	PUSH	P,T1		;SAVE START ADDRESS OF BLOCK
	ADDI	T1,.M2MAX	;POINT TO FIRST WORD OF MAP PART
	MOVE	T2,-1(P)	;# WORDS IN MAP
	ADD	T2,T1		;LAST WORD OF MAP, PLUS 1
	SOS	T2		;LAST WORD OF MAP
	XOR	T1,T2		;BIT DIFF BETWEEN FIRST AND LAST WORDS
	TRNN	T1,777000	;ARE THEY IN THE SAME PAGE?
	AOJA	T2,GTHMP4	;YES, T2 HAS ADDR OF REST OF BLOCK TO RETURN
				;(BLOCK ALLOCATED FROM BEGINNING)
	MOVEI	T2,<<2*.M2MAX>-IFN FTXMON,<1>>	;IF ALLOCATED FROM END, 2*OVERHEAD-1
	ADD	T2,-1(P)	;+SIZE OF BLOCK=START OF MAP PORTION
	XOR	T1,T2		;BIT DIFFERENCE BETWEEN TWO AGAIN
	TRNE	T1,777000	;STARTING & ENDING ADDRS IN SAME PAGE?
	JRST	GTHMP6		;NO, ALLOCATE FROM MIDDLE
	SUBI	T2,.M2MAX	;START OF MAP, INCL. OVERHEAD
	EXCH	T2,(P)		;START ADDR TO STACK, T2=1ST WORD TO RETURN
IFE FTXMON,<
	TLO	T2,(1B0)	;SET FLAG TO ROUND DOWN COUNT
>
GTHMP4:	POP	P,T1		;START OF NEW MAP
	EXCH	T2,(P)		;# OF SLOTS IN NEW MAP, SAVE ADDR TO RETURN
	HRRZ	J,-1(P)		;GET HIGH SEG #
	PUSH	P,T2		;SAVE # OF SLOTS IN NEW MAP
	PUSHJ	P,CPYHMP	;COPY THE OLD MAP AND SET JBTVAD ETC.
	POP	P,T1		;# OF SLOTS IN NEW MAP
	ADDI	T1,<.M2MAX-IFN FTXMON,<1>> ;# OF WORDS LEFT FROM ALLOCATED BLOCK
	POP	P,T2		;RESTORE ADDRESS TO RETURN
	MOVE	J,.CPJOB##	;RESTORE JOB #
GTHMP5:
IFN FTXMON,<
	PUSHJ	P,GVFWDS##	;RETURN REST OF BLOCK (BEGINNING OR END)
>
IFE FTXMON,<
	TLZE	T2,(1B0)	;ROUND DOWN COUNT?
	TRZA	T1,3		;YES, ONLY GIVE BACK TO PREVIOUS BOUNDARY
	SKIPA	T3,T1
	JRST	GTHM5B
	ANDI	T3,3		;SAVE ONLY EXCESS WORDS
	TRZ	T1,(T3)		;AND ROUND THE NUMBER RETURNED DOWN
	ADDI	T2,(T3)		;POINT UP
GTHM5B:	SKIPE	T1		;(DON'T WANT TO RETURN INTO NEXT BLOCK)
	PUSHJ	P,GIVWDS##
>
GTHMP7:	HRRZ	J,(P)		;RESTORE SEGMENT #
	LDB	T1,JBYVAD##	;POINT T1 AT MAP
	JRST	JPOPJ1##	;RESTORE J AND RETURN

;HERE IF MUST ALLOCATE BLOCK FROM MIDDLE OF ALLOCATED CORE

GTHMP6:	MOVE	T2,(P)		;START OF CORE ALLOCATED
	TRO	T2,PG.BDY	;UP TO PAGE BOUNDARY-1
	SUBI	T2,.M2MAX-1	;START OF WHERE BLOCK WILL BE
	MOVE	T1,T2		;GET THAT
	MOVE	T2,-1(P)	;NUMBER OF SLOTS IN NEW MAP
	HRRZ	J,-2(P)		;SEGMENT #
	PUSH	P,T1		;SAVE ADDRESS OF NEW MAP
	PUSHJ	P,CPYHMP	;COPY THE MAP AND SET JBTVAD
	POP	P,T1		;RESTORE ADDRESS OF NEW MAP
	MOVE	T2,T1		;COPY TO T2
	SUB	T1,(P)		;# OF WORDS TO RETURN AT START
	EXCH	T2,(P)		;SAVE START OF NEW MAP, GET START OF ALLOCATION
	PUSH	P,T1		;SAVE # OF WORDS RETURNED
	MOVE	J,.CPJOB##	;JOB #
IFN FTXMON,<
	PUSHJ	P,GVFWDS##	;RETURN BEGINNING OF BLOCK
>
IFE FTXMON,<
	TRZ	T1,3		;GIVE BACK TO PREVIOUS 4-WORD BOUNDARY
	SKIPE	T1		;ROUND DOWN TO NOTHING?
	PUSHJ	P,GIVWDS##
>
	MOVE	T2,-2(P)	;# OF WORDS IN MAP
	ADDI	T2,.M2MAX	;+OVERHEAD
	POP	P,T1		;# OF WORDS ALREADY RETURNED
	ADD	T1,T2		;# OF WORDS NOT BEING RETURNED
	ADD	T2,(P)		;+START OF BLOCK=FIRST WORD TO RETURN
	SUBI	T1,<.M2MAX*2-IFN FTXMON,<1>> ;COMPUTE -# WORDS TO RETURN THIS TIME
	SUB	T1,-1(P)	;..
	SUB	T1,-1(P)	;ALLOCATED=2*(.M2MAX+SIZE)-1
	MOVNS	T1		;COMPUTED THE NEGATIVE, MAKE POSITIVE
	ADJSP	P,-2		;FIX STACK
	JRST	GTHMP5		;RETURN THE WORDS


;HERE TO COPY OLD MAP TO NEW AND SET JBTVAD, ETC.
;CALL:
;	MOVE	P1,ADDRESS OF OLD MAP AREA (0 IF NONE)
;	MOVE	T1,ADDRESS OF BLOCK NEW MAP
;	MOVE	T2,# OF SLOTS IN NEW MAP
;	MOVE	J,SEGMENT #
;	PUSHJ	P,CPYHMP
;	<ONLY RETURN>

CPYHMP:	PUSH	P,T2		;SAVE # OF SLOTS IN NEW MAP
	PUSH	P,T1		;SAVE NEW MAP ADDR
	JUMPN	P1,OLDHMP	;OLD MAP
	SETZM	(T1)		;CLEAR FIRST WORD
	EXCH	T2,T1		;SOURCE IS NEW BLOCK
	ADDI	T1,.M2MAX	;NUMBER OF WORDS
	MOVE	T3,T2		;AND DESTINATION IS...
	AOJA	T3,CPYHM1	;SECOND WORD
OLDHMP:	MOVE	T3,T1		;DESTINATION ADDRESS IS NEW MAP
	MOVE	T2,P1		;ADDRESS OF OLD MAP
	SUBI	T2,.M2MAP	;POINT AT START OF DATA
	HRRZ	T1,.M2SIZ(T2)	;# OF SLOTS IN OLD MAP
	ADDI	T1,.M2MAX	;ADD IN THE OVERHEAD WORDS
CPYHM1:
IFN FTXMON,<
	EXTEND	T1,[XBLT]	;COPY THE OLD MAP TO THE NEW
>
IFE FTXMON,<
	PUSHJ	P,XBLTAT##
>
	POP	P,T1		;RESTORE ADDRESS OF NEW MAP
	POP	P,.M2SIZ(T1)	;SET # OF SLOTS IN MAP
	ADDI	T1,.M2MAP	;HIDE OVERHEAD WORDS
	DPB	T1,JBYVAD##	;STORE VIRTUAL ADDR OF MAP
	MAP	T2,@T1		;GET PAGE # OF MAP
	LSH	T2,W2PLSH	;CONVERT TO PAGE #
	ANDI	T2,PM.PAG
	HRRM	T2,JBTUPM##(J)	;STORE PAGE NUMBER OF SECONDARY MAP INTO SPT
	JUMPE	P1,CPOPJ##	;RETURN IF THERE WAS NO OLD MAP
	XMOVEI	T1,HRDOMP	;FORCE MAP TO BE REDONE
	PUSHJ	P,HGHAPP	;..
	MOVE	J,.CPJOB##	;IN CASE WE BLOCK
	MOVNI	T2,.M2MAX	;MAKE OVERHEAD WORDS VISIBLE AGAIN
	ADD	T2,P1		;POINTING TO START OF OLD MAP
	PJRST	RTNHM1		;RETURN OLD MAP
;SUBROUTINE TO SET UP J WITH THE CURRENT SETTING OF SWCUP
;AND THEN EXECUTE THE INSTRUCTION FOLLOWING THE CALLER TO MODIFY .HBSGN
;J HAS NEW CONTENTS OF .HBSGN (EXCEPT FOR SWCUP)
;NOTE THAT THE INSTRUCTION CANNOT REFERENCE THE STACK IN ITS "E" FIELD
;EXEMPLARY CALL:
;
;	PUSHJ	P,SETSGN		;CALL TO SET UP
;	  MOVEM	J,.HBSGN(T2)		;INSTRUCTION TO MODIFY .HBSGN
;USED SO THAT CALLER DOESN'T HAVE TO KEEP TRACK OF SWCUP

SETSGN:	PUSH	P,T2			;AND T2
	MOVE	T2,@-1(P)		;GET THE INSTRUCTION
	TLZ	T2,777740		;CLEAR OPCODE AND AC
	TLO	T2,(PUSH P,)		;GET COPY OF BITS
	EXCH	T2,(P)			;RESTORE T2 AND PUT "AND" ON STACK
	TLZ	J,SWCUP			;PUT OUR VALUE IN A KNOWN STATE
	SYSPIF				;SAFETY
	XCT	(P)			;GET STATE OF BIT
	EXCH	T1,(P)			;SAVE T1 AND GET COPY
	AND	T1,[SWCUP,,0]		;SAVE ONLY BIT OF IMPORTANCE
	TDO	J,T1			;SET CURRENT STATE
	POP	P,T1			;RESTORE T1
	POP	P,(P)			;FIX STACK
	XCT	@(P)			;DO THE INSTRUCTION
	AOS	(P)			;SKIP IT
	JRST	ONPOPJ##		;TURN THE PIS ON AND CONTINUE
SEGEND:	END