Google
 

Trailing-Edge - PDP-10 Archives - de-10-omona-v-mc9 - core1.mac
There are 6 other files named core1.mac in the archive. Click here to see a list.
TITLE CORE1 - LOGICAL AND PHYSICAL CORE ALLOCATION ROUTINES - V1547
SUBTTL T. HASTINGS/TH/RCC/CHW/JMF/DAL 2 AUG 77
	SEARCH	F,S
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VCORE1,1547
			;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

	ENTRY	CORE1		;ALWAYS LOAD CORE1(FOR LIB SEARCH)


;CORE ALLOCATION IS DONE ON A 1K BLOCK BASIS
;USING A USE BIT TABLE(CORTAB).  EACH 1K BLOCK IS REPRESENTED BY A 1 OR 2
;BIT ENTRY IN CORTAB (2 BITS IF THE LOCK UUO IS INCLUDED IN THE SYSTEM)
;A ZERO ENTRY MEANS BLOCK NOT IN USE
;A NON-ZERO ENTRY INDICATES MEMORY IN USE AS FOLLOWS:
;(NUMBERS IN BRACKETS INDICATE CONTENTS OF ENTRIES IN CORTAB IN THE FOLLOWING FORMAT
;[CONTENTS OF CORTAB IN SYSTEM NOT INCLUDING LOCK UUO, CONTENTS OF CORTAB
;IN SYSTEM INCLUDING LOCK UUO]

; 1. IN USE BY MONITOR [1,2]
; 2. IN USE BY A LOCKED JOB [-,2]
; 3. IN USE BY A JOB NOT LOCKED [1,1]
; 4. NON-EXISTANT [1,2]

;WHEN THE SYSTEM IS STARTED, SYSINI SETS THE CORTAB TABLE
;IT ALSO SETS A BYTE POINTER(CORLST) WHICH POINTS TO THE 
;LOWEST NON-EXISTANT BLOCK IMMEDIATELY ABOVE THE HIGHEST
;EXISTANT BLOCK. IT ALSO SETS CORTAL TO THE NO. OF
;FREE BLOCKS AVAILABLE.
;THE CORE1 ROUTINE ASSIGNS CORE IF POSSIBLE, SETS THE USE BITS,
;AND MOVES THE JOB IF NEW ASSIGNMENT IS A DIFFERENT PLACE THAN OLD
;THE JBTADR TABLE IS ALSO UPDATED BY THE CORE ROUTINES
;LH=PROTECTION,RH=RELOCATION
;JOBADR IS MODIFIED IF CORE FOR CURRENT JOB
;HARDWARE RELOC. AND PROTEC. ARE RESET IF CURRENT JOB
;FINALLY JOBREL(PROTECTION) IN JOB DATA AREA IS ALWAYS UPDATED

;LIST OF GLOBALS AFFECTED:
;JBTADR,CORTAL,CORTAB,HOLEF,SHFWAT,JOBADR,HOLES

;CORE UUO
;CALL:	MOVEI	AC,HIGHEST REL. ADR. DESIRED IN LOW SEG
;	HRLI	AC,HIGHEST REL. ADR. DESIRED IN HIGH SEG
;	CALL	AC,[SIXBIT /CORE/]
;	ERROR	RETURN
;	OK	RETURN TO USER, JOB MOVED IF NECESSARY
;RETURN NO. OF FREE 1K BLOCKS IN AC(OR MAX. NO. BLOCKS ALLOWED IF SWAPPING SYS)
;BOTH HALVES 0 MEANS ERROR RETURN NO. OF FREE 1K BLOCKS(OR MAX. NO. OF BLOCKS
; ALLOWED IF SWAPPING SYSTEM) IMMEDIATELY WITHOUT AFFECTING CORE
; OR WAITING FOR IO DEVICES
;LH=0 MEANS DO NOT CHANGE HIGH SEG ASSIGNMENT
;RH=0 MEANS DO NOT CHANGE LOW SEG ASSIGNMENT

	EXTERN	JOB,CORTAL,PAGSIZ,PG.BDY,W2PLSH,P2WLSH,JBTSTS
	EXTERN	ESTOP1,IOWAIT,SETREL,STOTAC,WSCHED

CORUUO::SKIPE	T1		;IF ZERO CORE REQUESTED JUST RETURN
				; THE AMOUNT AVAILABLE
	PUSHJ	P,CHGCOR	;CHANGE THE CORE ASSIGNMENT
	  SKIPA			;NOT ENOUGH
	AOS	(P)		;OK RETURN TO USER
IFE FTSWAP,<
	MOVE	T1,CORTAL	;RETURN NO. OF FREE 1K BLOCKS (COUNTING
>				; DORMANT AND IDLE SEGMENTS AS FREE)
IFN FTSWAP,<
	PUSHJ	P,CORBND	;T1 = UPPER BOUND ON WORDS FOR JOB
	LSH	T1,W2KLSH##	;CONVERT TO K
>
	JRST	STOTAC		;STORE IN USER AC AND RETURN TO USER
;SUBROUTINE TO CHANGE CORE - JUST LIKE CORE UUO
; EXCEPT VALUE NOT STORED IN USER'S UUO ACS
; USED BY MONITOR JOBS INSTEAD OF CORE UUOS
;CALL:	MOVE	T1,XWD NEW HIGH, NEW LOW SEG HIGHEST ADR
;	PUSHJ	P,CHGCOR
;	  ERROR RETURN
;	OK RETURN

CHGCOR::PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSH	P,T1		;NO, SAVE HIGHEST DESIRED ADDRESS IN BOTH SEGS
IFN FTVM,<
	MOVSI	T2,JACCT
	TDNE	T2,JBTSTS##(J)	;PRIVILEGED PROGRAM?
	TLO	P1,PHONLY	;YES, PHYSICAL ONLY THEN
>
	PUSHJ	P,IOWAIT	;WAIT FOR ALL DEVICE INACTIVE
	HRRZ	T1,(P)		;HIGHEST REL. LOC. DESIRED FOR LOW SEG(RH)
	JUMPE	T1,CORU1	;IS RH 0(IF YES DO NOT CHANGE LOW SEG)?
	IORI	T1,PG.BDY	;NO, MAKE IT AN EVEN MULTIPLE OF 1K-1
IFN FTLOCK,<
	MOVSI	T2,NSHF!NSWP	;LOCKED JOBS CANNOT CHANGE THEIR SIZE
	TDNN	T2,JBTSTS(J)	;IS HE LOCKED?
>
	PUSHJ	P,CORE1		;TRY TO ASSIGN CORE
	  JRST	CORERR		;NOT AVAILABLE, ERROR RETURN
				; SUM OF NEW LOW AND OLD HIGH SEG TOO BIG
CORU1:	HLRZ	T1,(P)		;CHECK TO SEE IF USER IS REQUESTING HIGH CORE
IFE FT2REL,<
	CAMG	T1,USRREL	;0 MEANS NO CHANGE, 1 THRU TOP OF LOW SEG MEANS
				; RETURN HIGH CORE (IF ANY), ALWAYS LEGAL
>				; EVEN IF NO HIGH SEG HARD WARE OR SOFTWARE
IFN FT2REL,<
	EXTERN	UCORHI
	PUSHJ	P,UCORHI	;TRY TO ASSIGN CORE FOR HIGH SEG,
				; UCORHI EXPECTS ARG ON PD LIST
	  JRST	CORERR		;ERROR-ACTIVE IO(SAVE IN PROGRESS FOR SOME USER)
>				; OR SUM OF NEW LOW SEG AND NEW HIGH SEG TOO BIG
				; OR PROTECTION FAILURE (CAN'T UPDATE)
	AOS	-1(P)		;SET FOR OK(SKIP) RETURN
CORERR:	POP	P,T1		;REMOVE ARG FROM LIST

IFN FTSWAP,<
	MOVE	T1,JBTSTS(J)	;JOB STATUS WORD
	TLNE	T1,JXPN!SWP	;MUST LOW SEGMENT BE SWAPPED OUT TO EXPAND OR
				; HIGH SEGMENT LOGICAL CORE ASSIGNED ON DISK?
	PUSHJ	P,WSCHED	;YES, CALL SCHEDULER TO STOP JOB
				; LOW SEG MUST BE SWAPPED OUT TO EXPAND
>				; OR HIGH SEG LOGICAL CORE ASSIGNED ON DISK
	POPJ	P,
;SUBROUTINE TO RETURN UPPER BOUND CORE LIMIT FOR JOB IN WORDS
;CALL:	MOVE	J,JOB NO
;	PUSHJ	P,CORBND
;	ALWAYS RETURN - T1 = UPPER BOUND

	INTERN	CORBND
CORBND:
	PUSH	P,T2
IFN FTLOCK,<
	PUSH	P,J		;SAVE JOB NUMBER
	MOVSI	T1,NSWP!NSHF
	MOVEI	T2,0
	TDNE	T1,JBTSTS(J)	;SEGMENT LOCKED?
	PUSHJ	P,SEGSIZ	;YES, GET ITS CORE SIZE
	PUSH	P,T2		;SAVE CORE SIZE
	MOVE	J,JBTSGN##(J)	;GET HIGH SEG NUMBER
	MOVEI	T2,0
	JUMPLE	J,CRBND1	;USING A HIGH SEG?
	TDNE	T1,JBTSTS(J)	; THAT IS LOCKED?
	PUSHJ	P,SEGSIZ	;YES, GET HIGH SEG SIZE
CRBND1:	POP	P,T1		;GET BACK LOW SEG SIZE
	ADD	T1,T2		;GET TOTAL SIZE THIS JOBS LOCKED CORE
	LSH	T1,P2WLSH
	ADD	T1,CORMAX	;ADD TO CORMAX TO GET APPARENT CORMAX
	POP	P,J		;RESTORE JOB NUMBER
>
IFE FTLOCK,<
	MOVE	T1,CORMAX	;GET CORMAX
>
IFN FTTLIM,<
	LDB	T2,JBYLCR	;GET THIS JOBS CORE LIMIT
	JUMPE	T2,CRBND2
	LSH	T2,^D9
	CAMLE	T1,T2		;WE WANT
	MOVE	T1,T2		; THE SMALLER OF THE TWO
CRBND2:
IFN FTVM,<
	PUSHJ	P,FNDPDB##	;FIND THE PDB
	  JRST	CRBND4		;NO LIMIT OR GUIDELINE IF NO PDB
	HRRZ	T2,.PDCVL##(W)	;CURRENT PHYSICAL LIMIT OR GUIDELINE
	JUMPE	T2,CRBND3	;IGNORE IF NONE
	TRZN	T2,400000	;LIMIT?
	JUMPL	P1,CRBND3	;NO, IGNORE GUIDELINE IF PHONLY
	LSH	T2,P2WLSH##	;NUMBER OF WORDS
	CAMLE	T1,T2		;SMALLEST YET?
	MOVE	T1,T2		;NO, USE SMALLER
CRBND3:	HRRZ	T2,.PDMVL##(W)	;FINALLY, MAX PHYSICAL LIMIT
	JUMPE	T2,CRBND4
	LSH	T2,P2WLSH##
	CAMLE	T1,T2
	MOVE	T1,T2
CRBND4:>

>	;END FTTLIM
IFN FTLOCK,<
	LSH	T1,W2PLSH
	CAILE	T1,@CORLIM##	;CORLIM MIGHT BE EVEN SMALLER
	HRRZ	T1,CORLIM##	; IF SO, IT IS THE LIMIT
	LSH	T1,P2WLSH
>
IFN FTPDBS,< ;IF WE SWAP PDB'S
	SUBI	T1,PDBWDS##		;SIZE OF PDB IN WORDS
					; ROUNDED UP TO PAGE SIZE
> ;END FTPDBS 
IFN FTKI10!FTKL10,<
	SUBI	T1,UPMSZW##	;ACCOUNT FOR THE FACT THAT THE UPMP IS ALLOCATED
				; FROM USER CORE. THUS, MAXIMUM SIZE A JOB
				; A JOB CAN OBTAIN IS MIN (CORMAX, JOB LIMIT)-
				; THE SIZE OF THE USER PAGE MAP PAGE
>
IFN FTVM,<
	JUMPL	P1,T2POPJ##	;RETURN IF PHYSICAL ONLY
	PUSHJ	P,FNDPDB##
	  PJRST	T2POPJ##	;NO LIMITS IF NO PDB
	HLRZ	T2,.PDCVL##(W)	;CURRENT VIRTUAL LIMIT
	LSH	T2,P2WLSH##	;CONVERT TO PAGES
	CAMGE	T1,T2
	MOVE	T1,T2
>
	PJRST	T2POPJ##	;YES, USE SMALLER JOB LIMIT
;CORLM.	UUO -- SET JOB'S CORE LIMIT
;CALL:	HRLZI	AC,12
;	HRRI	AC,LIMIT IN NO. OF WORDS
;	SETUUO	AC,
;	ERROR
;	OK

IFN FTTLIM,<
	INTERN CORELM
CORELM:	JUMPE	T2,CORLM1
	CAIG	T2,MINMAX##	;GREATER THAN MIN
	MOVEI	T2,MINMAX	;YES--USE MINMAX
	ADDI	T2,PG.BDY##	;ROUND UP TO LAST LOWSEG ADDRESS
				;  + HIGH SEG SIZE
				;THIS IS TO BE SIMILAR TO CORE UUO
	TLNE	T2,-1		;SEE IF OVERFLOW
	SETOM	T2		;YES--SET TO INFINITY
	LSH	T2,-^D9		;CONVERT TO 512 UNITS
CORLM1:	DPB	T2,JBYLCR##	;STORE
	JRST	CPOPJ1		;RETURN

>
;ROUTINE TO TEST FOR ANY ACTIVE DEVICES

;CALL:	MOVE	J,JOB NUMBER OR HIGH SEG NUMBER
;	MOVE	R,ADDRESS OF JOB DATA AREA
;	PUSHJ	P,ANYACT
;	DEVICES	ACTIVE
;	DEVICES	NOT ACTIVE EXCEPT POSSIBLY TTY
;IN REENTRANT SYSTEMS ANYACT IS BROKEN INTO 2 CALLS, ANYSAV AND ANYDEV
;ANYSAV TESTS WHTETHER THIS IS A HI SEG THAT HAS A SAVE IN PROGRESS
	INTERN	ANYACT,ANYDEV
	EXTERN	JOBMAX,SAVE3
ANYACT:
IFN FT2REL,<
	EXTERN	ANYSAV
	PUSHJ	P,ANYSAV	;IS A SAVE IN PROGRESS FOR HI SEG?
	  POPJ	P,		;YES - RETURN
>

ANYDEV:	PUSHJ	P,SAVE3		;PRESERVE ACCUMULATORS P1, P2, P3

ANYDV1:
IFN FTMS,<	EXTERNAL ANYRUN
	PUSHJ	P,ANYRUN	;IS THIS JOB RUNNING ON THE SLAVE
	  POPJ	P,		;YES, RETURN IMMEDIATELY
>
IFN FT2REL,<
	CAILE	J,JOBMAX	;YES, IT THIS A HIGH SEG?
	JRST	CPOPJ1		;YES, OK TO SHUFFLE OR SWAP SINCE NSHF,NSWP NOT SET
				; AND NO SAVE IN PROGRESS
>
	LDB	P1,PJBSTS##	;JOB'S QUEUE CODE
IFN FTVM,<
	CAIE	P1,PIOWQ##	;IN PAGING I/O WAIT?
>
	CAIN	P1,DIOWQ##	;OR DSK I/O WAIT?
	POPJ	P,		;YES, CAN'T SWAP IT OUT NOW
				; ONLY HAPPENS IF LOCK IS TRYING
				; TO FORCE THIS JOB OUT
	MOVEI	P1,USRJDA	;ASSUME JOB IS CURRENT JOB (DEVICE TABLE IS THE MONITOR)
	CAMN	J,.C0JOB##	;IS IT?
	JRST	ANYDV2		;YES
IFN FTKI10!FTKL10,<
	PUSHJ	P,SVEUB##	;NO, MAKE THE JOB DATA AREA ADDRESSABLE
>
	MOVEI	P1,JOBJDA(R)
ANYDV2:	MOVEI	S,IOACT		;IO DEVICE ACTIVE BIT
	HRRZ	P2,JOBJMH(P1)	;GET NO. OF USER IO CHANNELS IN USE
				; FOR JOB(EITHER FROM JOB DATA AREA
				; OR FROM MONITOR (IGNORE LH WHICH MAY BE-1
				; IF SAVGET IN PROGRESS)
	TLO	P1,P2		;SET TO ADD P1 TO P2
IFE FTMSGSER,<
ANY:	SKIPE	F,@P1		;IS A DEVICE ASSIGNED TO THIS CHANNEL?
	TDNN	S,DEVIOS(F)	;YES, IS IT ACTIVE?
> ;END FTMSGSER
IFN FTMSGSER,<
ANY:	SKIPN	F,@P1		;IS THERE A DEVICE ASSIGNED?
	JRST	ANY2		;NO--LOOK AT NEXT CHAN.
	TLZ	F,-1		;CLEAR FLAGS
	CAIG	P2,17		;TOO MANY CHANS
	CAML	F,SYSSIZ##
	STOPCD	.,STOP,JJW,	;++JOB JDA WRONG
	LDB	P3,PDVTYP##	;GET THE DEVICE TYPE
	CAIE	P3,<.TYMPX/.TYEST> ;MPX?
	JRST	ANY1		;NO--JUST LOOK AT IOACT
	PUSHJ	P,MPXACT##	;SEE IF IT IS ACTIVE
	  POPJ	P,0		;RETURN IF ACTIVE
	JRST	ANY2		;LOOK AT NEXT DEVICE
ANY1:	TDNN	S,DEVIOS(F)	;IS DEVICE ACTIVE?
> ;END FTMSGSER
ANY2:	SOJGE	P2,ANY		;NO, KEEP LOOKING
	JUMPL	P2,ANY3		;YES, FINISHED YET?
	MOVSI	P3,DVTTY	;DEVICE IS A TTY BIT
	TDNN	P3,DEVMOD(F)	;NOT FINISHED, IS DEVICE TTY?
	POPJ	P,		;NO, ERROR RETURN, CANNOT ASSIGN CORE
	JRST	ANY2		;YES, KEEP LOOKING FOR AN ACTIVE DEVICE

ANY3:
IFN FTDHIA,<
	SKIPN	F,DIADSK##	;DSK CHAN STOPPED?
	JRST	CPOPJ1##	;NO, OK RETURN
	LDB	P1,PJOBN##	;YES, IS THIS THE JOB THAT STOPPED IT!
	CAMN	P1,J
	POPJ	P,		;YES, SOMETHING IS ACTIVE
>
	PJRST	CPOPJ1##	;OK RETURN
;ROUTINE TO FLUSH PHYSICAL CORE ASSIGNED IN MEMORY
;NOTE: THIS ROUTINE DIFERS SIGNIFICANTLY FROM CORE0 AND CORE1 IN THAT
;IT IS ONLY A PHYSICAL  REMOVAL OF CORE(VIRTAL IS NOT AFFECTED)
;SEE COMMENTS FOR CORE1
;CALL:	MOVE	J,HIGH OR LOW SEGMENT NUMBER
;	PUSHJ	P,KCORE1
;	ALWAYS	RETURN HERE
;SCORE1 IS CALLED FROM SHUFFLER WITH T1 SET TO SEG SIZE

	INTERN	KCORE1,SCORE1

KCORE1:	MOVEI	T1,0		;SETUP DESIRED HIGHEST ADR
SCORE1:	SOS	(P)		;CORE1 WILL ALWAYS SKIP RETURN
	JRST	CORE1A##	;BYPASS LOGICAL CORE ASSIGNMENT PART
				; AND FLUSH PHYSICAL CORE(LOGICAL CORE UNEFFECTED)
;CALL:	MOVE	T1,HIGHEST LEGAL ASSRESSABLE LOC. DESIRED
;	MOVE	J,JOB NUMBER
;	MOVE	R,[XWD PROT.,RELOC.]=JBTADR(J)
;	PUSHJ	P,CORE0
;	ERROR	;EITHER JOB HAS ACTIVE IO
		; OR NOT ENOUGH CORE
;	OK	RETURN
;JOB IS MOVED IF NECESSARY TO SATISFY REQUEST
;R IS SET TO NEW CORE ASSIGNMENT ON EITHER RETURN
;0 MEANS NONE ASSIGNED IN MEMORY, ASSIGNED ON DISK
INTERNAL CORE0
INTERNAL CORE1,FTTIME,FTTRPSET,FTSWAP
EXTERNAL JOBJDA,JOB,USRJDA,JBTADR
EXTERNAL JOBPC,JBTDAT
EXTERNAL CORTAL,CORLST,HOLEF,CLRWRD
EXTERNAL CPOPJ,CPOPJ1,JOBJMH,JOBENB,JOBDPD,JOBDPG
EXTERNAL JOBPR1,CPOPJ1,JOBPRT,USRPC,CORMAX
;ENTER HERE FROM CORE CONSOLE COMMAND OR INITIAL CORE
;ASSIGNMENT OF JUST A JOB DATA AREA FOR RUN COMMAND
;IE ENTER WHEN DEVICES MAY BE ACTIVE OR JOB MAY HAVE NO PREVIOUS CORE
;JOB CAN HAVE CORE IN MEMORY, CORE ON DISK, OR NONE EITHER PLACE
;JOB CANNOT BE IN PROCESS OF SWAP OUT OR SWAP IN(CALLER'S RESPONSIBILITY)
;CORE0 NO LONGER REASSIGN CORE ON DISK IF OLD CORE ON DISK
;BECAUSE OF FRAGMENTED SWAPPING(TOO HARD) UNLESS 0 BEING ASKED FOR
;THEREFORE THE CORE COMMAND CAUSES JOB TO BE SWAPPED INTO CORE FIRST(INCORE=1)
;HOWEVER, THE R,RUN,GET,KJOB COMMANDS DO NOT REQUIRE THE PREVIOUS CORE IMAGE TO
;BE SWAPPED IN(AS THIS IS SLOW). THEY ASK FOR 140 WORDS, AND LARGER DISK SPACE IS RELINQUISHED
;UPON SWAPIN BY THE SWAPPER, VIRTAL IS INCREASED THEN RATHER THAN
;ON THE CALL TO CORE0.
;IT WILL TRY TO REASSIGN CORE IN MEMORY IF OLD CORE IN MEMORY
;IF THIS FAILS, IT WILL REASSIGN NEW CORE ON DISK AND ASK SWAPPER TO EXPAND
;IF JOB DID NOT HAVE OLD CORE, AN ATTEMPT WILL BE MADE TO ASSIGN CORE IN MEMORY
;IF THIS FAILS, TI WILL BE ASSIGNED ON THE DISK AND ASK SWAPPER TO EXPAND
;THE OTHER PLACES IN THE MONITOR WHERE THE IN-CORE COUNT IS TOUCHED IS
;IN GET WHERE IT INCREMENTS TO SHARE COPY ALREADY IN CORE.
;AND END OF SWAPIN OF LOW SEG AND HIGH SEG IS ALREADY IN CORE FOR OTHER USER
;THE CORE ROUTINES DO NOT ALTER THE HIGH SEG IN CORE COUNT.  IT IS UP TO THE  CALLER
;(IN SEGCON) TO CALL THE CORE ROUTINES ONLY IF IN CORE COUNT IS 0.
;AND END OF SWAPIN OF LOW SEG AND HIGH SEG IS ALREADY IN CORE FOR OTHER USER
CORE0:
IFE FTSWAP,<
	JUMPE	R,CORE1		;IS JOB WITHOUT CORE IN MEMORY?
				;NO
>
IFN FTSWAP,<
	EXTERN	IMGOUT,CPOPJ1,CHGSWP
	JUMPN	R,CORE0A	;DOES JOB HAVE CORE IN MEMORY?
				; (ALWAYS TRUE BOTH SEGS IF CORE UUO)
	IFE	FT2REL,<
	EXTERN	CORMAX
	CAML	T1,CORMAX	;NO, WILL REQUEST FIT IN PHYSICAL CORE?
				; COMPARE WITH LARGEST PERMITTED ADR+1(BUILD AND
				; ONCE CAN RESTART CORMAX)

	>
	IFN	FT2REL,<
	EXTERN	SUMSEG
	PUSHJ	P,SUMSEG	;NO, WILL SUM OF BOTH SEGMENTS FIT IN PHYSICAL CORE?
				; LARGEST PERMITTED CORE. COMPARE SUM WITH CORMAX
	>
	  POPJ	P,		;NO, GIVE ERROR RETURN
	MOVSI	T2,SWP		;IS JOB SWAPPED OUT?
	TDNN	T2,JBTSTS(J)	;(MAY HAVE 0 DISK SPACE ALTHOUGH SWAPPED OUT)
	JRST	CORE1		;NO, TRY TO ASSIGN CORE IN MEMORY
	PUSHJ	P,CHGSWP	;YES, CHANGE ASSIGNMENT OF SWAPPING SPACE ON DISK
				; INCREASE VIRTAL(COUNT OF FREE 1K BLOCKS OF SWAPPING
				; (SHOULD NEVER NEED TO DECREASE VIRTAL SINCE
				; CORE COMMAND ALWAYS SWAPS JOB IN FIRST).
				; (FRAGMENTATION POSTPONES RETURNING SPACE AND
				; INCREASING VIRTAL UNTIL SWAP IN IF NOT ASKING
				; FOR 0 VIRTUAL CORE)
	JRST	CPOPJ1		;GIVE OK RETURN TO CALLER

CORE0A:
>
IFN FTTRPSET,<
	EXTERN	STOPTS
	SKIPN	STOPTS		;NO,IS TIME SHARING STOPPED BY
				; TRPSET UUO DONE FOR JOB 1?
>

	PUSHJ	P,ANYACT	;NO,ANY ACTIVE DEVICE?
	  POPJ	P,		;YES, CANNOT ASSIGN CORE
				; NO, FALL INTO CORE1
;ROUTINE TO TRY TO ASSIGN CORE IN CORE
;LOW OR HIGH SEG MUST NOT BE SWAPPED OUT(CALLER'S RESPONSIBILITY)
;AND MUST NOT HAVE ANY ACTIVE DEVICES(IT MAY HAVE 0 CORE IN CORE THOUGH)
;IN OTHER WORDS HIGH OR LOW SEG MAY OR MAY NOT HAVE VIRTUAL CORE
;BUT IF IT HAS VIRTUAL CORE IT MUST BE IN PHYSICAL CORE
;THIS IS BOTH A LOGICAL AND A PHYSICAL CORE ASSIGNMENT
;FIRST OLD CORE IS RETURNED TO SYSTEM
;THEN NEW REQUEST IS ATTEMPTED TO BE SATISFIED IN LOWEST
;POSITION POSSIBLE.  THUS CORE TENDS TO BE PACKED
;IF NEW REQUEST CANNOT BE GRANTED, OLD AMOUNT IS RETAINED, IF NON-SWAPPING SYS
;OTHERWISE SWAPPER IS CALLED(XPAND) TO EXPAND CORE BY SWAPPING OUT


	EXTERN	SEGSIZ

CORE1:	JUMPL	T1,CPOPJ##	;DON'T ALLOW NEGATIVE ARGUMENTS
IFN FTLOCK,<
	MOVSI	T2,NSHF!NSWP	;LOCKED SEGMENTS CANNOT CHANGE THEIR CORE SIZE
	TDNE	T2,JBTSTS(J)	;IS THIS SEGMENT LOCKED?
	POPJ	P,		;YES, ERROR RETURN
	;END IFN FTLOCK
>
	CAILE	J,JOBMAX##	;IS THIS A HIGH SEGMENT?
	JRST	CORE12		;YES, PROCEED
	MOVE	T3,T1		;LOW SEGMENT, SAVE AMOUNT OF CORE REQUESTED
	PUSHJ	P,HSVAD##	;COMPUTE HIGH SEGMENT BOUNDS
	CAIL	T3,(T2)		;TRYING TO EXPAND INTO THE HIGH SEGMENT?
	JUMPN	T1,CPOPJ##	;YES IF THERE IS ONE - JUMP IF SO
	MOVE	T1,T3		;OK, RESTORE ARGUMENT
CORE12:
	NOSCHEDULE		;PREVENT SCHEDULING

IFN FTSWAP,<
	EXTERN	VIRTAL
	PUSHJ	P,SEGSIZ	;T2=OLD SEG SIZE
IFN FTKI10!FTKL10,<
	JUMPE	T2,CORE10
	CAIG	J,JOBMAX##	;IF THIS IS A LOW SEGMENT,
	SUBI	T2,UPMPSZ##	;SUBTRACT OUT THE SIZE OF THE UPMP WHICH WAS
				; ADDED IN FOR ACCOUNTING PURPOSES
>
CORE10:	SKIPN	T3,T1		;IS O BEING REQUESTED?
	MOVNI	T3,1		;YES, PRETEND -1(DEPEND ON ASH BUG WHICH KEEPS -1
				; ON RT. SHIFT)
	ASH	T3,W2PLSH	;CONVERT TO NO. OF K-1(01,0,1,2,...)
	SUB	T3,T2		;NO. OF K-1 INCREASE=NEW-OLD-1
IFN FTVM,<
	PUSHJ	P,VIRCHK##	;ALLOCATE CORE ON DSK? (USER JUST GOING
				; VIRTUAL OR ALREADY VIRTUAL)
	  POPJ	P,		;ALREADY VIRTUAL BUT TRYING TO EXCEED LIMITS
	  PJRST	CPOPJ1##	;YES, TAKE GOOD RETURN
	PUSHJ	P,SAVE1##
	TLO	P1,PHONLY	;PHYSICAL ONLY FOR CORBND
>
	CAMGE	T3,VIRTAL	;IS THERE ENOUGH FREE VIRTUAL CORE IN SYSTEM?
>
IFE FT2REL,<
	CAML	T1,CORMAX	; YES, IS REQUEST LESS THAN MAX. ALLOWED COR+1?
>
IFN FT2REL,<
	EXTERN	SUMSEG
	PUSHJ	P,SUMSEG	;YES, IS SUM OF SEGS LESS THAN MAX. ALLOWED CORE+1?
>
	  POPJ	P,		;NO, ERROR RETURN
IFN FTSWAP,<
	AOJE	T3,CPOPJ1	;YES, GET NO. K OF INCREASE AND
				;RETURN WITHOUT MOVING CORE IF NO CHANGE IN SIZE
IFN	FTVM,<
	CAILE	J,JOBMAX	;IF A LOW SEG...
	JRST	CORE11
	SKIPN	R		;IF GOING FROM 0 TO N,
	ADDI	T3,UPMPSZ##	;U DECREASE VIRTAL
	SKIPN	T1		;IF GOING FROM N TO 0,
	SUBI	T3,UPMPSZ##	;U DECREASE VIRTAL
CORE11:	>  ;END FTVM
	MOVNS	T3		;MAKE MINUS FOR UPDATE
	ADDM	T3,VIRTAL	;AND UPDATE TOTAL VIRTUAL CORE IN SYSTEM
				; SINCE THIS REQUEST CAN BE SATISFIIED
>
	JRST	CORE1A##	;GO ASSIGN CORE IN CORE OR ON THE DISK
;ROUTINE TO CLEAR PART OF JOB DATA AREA(PART PROTECTED FROM USER IO)
;CALLED WHEN SWAP READ ERROR AND AT SYSTEM RESTART(140)
;	MOVE	J,JOB NO.
;CALL:	MOVE	R,ADDRESS OF JOB DATA AREA
;	PUSHJ	P,CLRJOB
INTERNAL CLRJOB
EXTERNAL JOBPRT,JOBPR1,JOBPFI,JOBENB
EXTERNAL JOBPD1,JOBDDT

CLRJOB:
IFN FTKI10!FTKL10,<
	PUSHJ	P,SVEUB##	;MAKE SURE JOB DATA AREA IS ADDRESSABLE
>
	SETZM	JOBPRT(R)	;FIRST LOC. PROTECTED FROM USER
	MOVSI	T1,JOBPRT(R)
	HRRI	T1,JOBPR1(R)
	MOVE	T2,JOBDDT(R)	;SAVE DDT STARTING ADDRESS
	BLT	T1,JOBJDA##+17(R)
	MOVEM	T2,JOBDDT(R)
	SETZM	JOBENB(R)	;ALSO CLEAR APR ENABLE WORD
	SETZM	JOBPD1(R)	;AND UUO PC FLAGS(USED WHEN JOB STARTS)
	PJRST	ESTOP1		;GO SET JOB STATUS NOT BE ALLOWED
				;NOTE JACCT IS CLEARED

IFE FTVM,<
;SUBROUTINE TO RETURN EXTENDED EXEC PUSH DOWN LIST FOR CURRENT JOB
;(JOB HAS USER CORE TOO)
;AND MOVE PUSH DOWN LIST CONTENTS BACK TO USER AREA
;RESET PUSH DOWN POINTER BACK TO ORIGINAL LIST IN USER AREA
;CALL:	SKIPE	T2,USREPL
;	PUSHJ	P,GIVEPL
;	ALWAYS	RETURN
	INTERN	GIVEPL
	EXTERN	EPL4WD,USREPL
	EXTERN	JOBPD1,JOBLPD,MMXPDL,SYSSIZ

GIVEPL:	HRRZ	T1,P		;PUSH DOWN POINTER
	CAML	T1,LOCORE##	;P=NULPDL?
	CAMLE	T1,SYSSIZ	;IS IT STILL IN THE MONITOR (IN AN EPL)?
	JRST	GIVEP1		;NO, DO NOT ADJUST P SINCE IT IS ALREADY IN USER AREA
	HRLI	T1,1(T2)	;(SOURCE)=BEG OF EXTENDED PD LIST+1
	HRRI	T1,JOBPD1+1(R)	;(DEST)=BEG OF USER PD LIST+1
	BLT	T1,JOBLPD(R)	;(STOP)=LAST T3 OF USER PD LIST
	SUBI	P,(T2)		;YES, BEG OF EPL-OLD CURRENT T3=CUR LENGTH
	HRLI	P,MMXPDL+1(P)	;CUR LENGTH-MAX LENGTH=-NO WORDS LEFT BEFORE PDOVF
	ADDI	P,JOBPD1(R)	;CUR LENGTH +BEG OF LIST IN USER AREA=NEW CURRENT T3
	SKIPLE	P		;DID IT FIT BACK IN THE JOB DATA AREA?
	STOPCD	GIVEP1,JOB,CRP,	;++CAN'T RETURN PDL
GIVEP1:	SETZM	USREPL		;FLAG NO MORE EXEC CORE ALLOCATED
	MOVEI	T1,EPL4WD	;SIZE OF EXTENDED PD LIST IN 4 WORDS
	PJRST	GIV4WD		;GIVE SPACE BACK AND RETURN

>	;END IFE FTVM
	INTERN	GET4WD,GIV4WD,GETWDS,GIVWDS,SETZRS
	EXTERN	SAVE4,FREPTR,LOCORE

;SUBROUTINE TO GET "FREE" CORE
;ENTER GET4WD: T2=# 4 WORD BLOCKS TO GET
;ENTER GETWDS: T2=# WORDS TO GET
;RETURN CPOPJ IF NOT AVAILABLE, WITH T2=LARGEST HOLE AVAILABLE
;RETURN CPOPJ1 IF GOTTEN, WITH T1=LOC OF CORE
GETWDS:	ADDI	T2,3		;CONVERT TO 4 WORD BLOCKS
	ASH	T2,-2
GET4WD:	MOVE	T1,T2		;NUMBER OF BLOCKSTO GET
	MOVEI	T2,FREPTR	;L(AOBJN WORD)
	PUSH	P,T1		;SAVE NUMBER BEING REQUESTED
	PUSHJ	P,GETBIT	;GET, SET THE BITS
	  JRST	GET4W2		;NOT ENOUGH AVAILABLE
GET4W1:	POP	P,T2		;RESTORE AMOUNT GOTTEN
IFN FTRSP,<
	ADDM	T2,FRUSED##	;BUMP FREE-CORE-USED WORD
>
	LSH	T1,2		;*4 TO CONVERT TO AN ADDRESS
	ADD	T1,LOCORE	;+START OF TABLE = ACTUAL ADDRESS
	PJRST	CPOPJ1		;TAKE GOOD RETURN

;HERE IF REQUESTED AMOUNT ISNT AVAILABLE
GET4W2:	MOVE	T2,T1		;LARGEST HOLE WE FOUND
	JRST	TPOPJ##		;TAKE LOST RETURN

;SUBROUTINE TO ZERO BITS IN A BIT TABLE
;CALLING SEQUENCE:
;	MOVE	T1,NUMBER OF BITS TO CLEAR
;	MOVE	T2,AOBJN POINTER TO TABLE
;	MOVE	T3,BIT POSITION WITHIN TABLE
;	PUSHJ	P,ZERBTS
;ALWAYS RETURNS CPOPJ

ZERBTS::IDIVI	T3,^D36		;36 BITS/WORD
	HRLS	T3		;WORD NUMBER TO BOTH HALVES
	ADD	T2,T3		;POINT AOBJN POINTER TO WORD IN TABLE
	MOVE	T3,T4		;BIT POSITION WITHIN WORD
	PJRST	SETZRS		;ZERO TIME BITS

;SUBROUTINE TO RETURN "FREE" CORE
;ENTER GIVWDS: T1=# WDS. TO RETURN, T2=START ADR. OF CORE
;ENTER GIV4WD: T1=# 4 WRD. BLOCKS TO RETURN, T2=START ADR. OF CORE
GIVWDS:	ADDI	T1,3		;CONVERT TO # 4WD. BLOCKS
	ASH	T1,-2
GIV4WD:	SUB	T2,LOCORE	;GET ADR. RELATIVE TO START OF TABLE
IFN FTRSP,<
	MOVN	T3,T1
	ADDM	T3,FRUSED##	;DECREMENT FREE-CORE USED
>
	LSH	T2,-2		;/4 TO CONVERT TO BITS
	IDIVI	T2,^D36		;COMPUTE WORD LOC, STARTING BIT
	HRLS	T2		;WORD POSITION IN BOTH HALVES
	ADD	T2,FREPTR	;SET AOBJN WORD FOR TABLE
				;FALL INTO SETZRS

;SUBROUTINE TO SET ZEROS IN A TABLE
;ARG	T1=HOW MANY BITS TO CLEAR
;	T2=AOBJN POINTER FOR TABLE
;	T3=POSITION IN WORD OF FIRST BIT TO CLEAR
;	(0=BIT 0, 1=BIT 1, ETC.)

INTERN	SETZRS
SETZRS:	EXCH	T1,T3		;SET ACS FOR CLRBTS
	MOVEI	T4,^D36		;ADJUST FOR 1ST WORD
	SUBM	T4,T1
	HRRZ	T4,T2		;SET T4 FOR CLRBTS
	PUSH	P,T2		;SAVE AOBJN WORD
	PUSHJ	P,CLRBTS	;CLEAR SOME BITS
	  STOPCD	T2POPJ##,DEBUG,BAC, ;++BIT ALREADY CLEAR
	POP	P,T2		;RESTORE AOBJN WORD
	HLRE	T3,T2		;LENGTH OF POINTER
	SUB	T2,T3		;COMPUTE TOP OF TABLE
	CAILE	T4,(T2)		;FINAL ADR PAST TOP?
	STOPCD	CPOPJ,DEBUG,PTT, ;++PAST TOP OF TABLE
	POPJ	P,		;NO, GOOD RETURN
	INTERN	GETZ,GETZR,SETOS
	STRTAD==200000
;SUBROUTINE TO FIND N CONSECUTIVE 0'S IN A TABLE
;ENTER WITH P1 = AOBJN WORD TO THE TABLE
;P2 = PREVIOUS BEST SO FAR
;RH(P3)= HOW MANY,  BIT STRTAD =1 IF START LOC SPECIFIED
;LH(P3) HAS BITS 0,1,2 USED BY FILSER
;EXIT CPOPJ1 IF FOUND, WITH P4 = WHERE THE HOLE IS, P1=UPDATED POINTER
;EXIT CPOPJ IF UNSUCCESSFUL, P2 = LARGEST HOLE FOUND
;P2,P4 CHANGED
;NOTE--SHOULD NOT CONTAIN A METER POINT SINCE IS CALLED
;      BY ENDSTS ON 407 START BEFORE METINI IS CALLED
GETZ:	TLNE	P3,STRTAD	;START LOC SPECIFIED?  (NOTE THAT ENTRY TO ROUTINE
				; IS AT GETZR IF START LOC SPECIFIED)
	POPJ	P,		;YES, ERROR RETURN
	MOVEI	T4,^D36		;NO. SET UP COUNT
	SETCM	T1,(P1)		;WORD TO INVESTIGATE
	JUMPE	T1,GETZ4	;FULL IF 0
	JUMPG	T1,GETZ3	;1ST BIT UNAVAILABLE IF POSITIVE
GETZ1:	SETCA	T1,		;SET TO REAL CONTENTS
	JFFO	T1,.+2		;COUNT THE NUMBER OF 0'S
	MOVEI	T2,^D36		;36 OF THEM
GETZR:	MOVE	T3,T2		;SHIFT COUNT (T3 CAN BE .GT. 36 AT GETZ2)
	MOVEM	P1,P4		;SAVE POSITION IN P4
	HRLM	T4,P4		;LOC OF HOLE
GETZ2:	CAIL	T3,(P3)		;FOUND ENOUGH?
	JRST	CPOPJ1		;YES. GOOD RETURN
	CAILE	T3,(P2)		;NO. BEST SO FAR?
	HRRI	P2,(T3)		;YES. SAVE IT
	SUBI	T4,(T2)		;DECREASE POSITION COUNTER
	JUMPLE	T4,GETZ5	;0'S ON END
	TLNE	P3,STRTAD	;THIS HOLE NOT GOOD ENOUGH
	POPJ	P,		;ERROR RETURN IF START ADDRESS GIVEN
	SETCA	T1,		;NOW WE WANT TO COUNT 1'S
	LSH	T1,1(T2)	;REMOVE BITS WE ALREADY LOOKED AT
	JUMPE	T1,GETZ4	;GO IF THE REST OF THE WORD IS ALL ONES
GETZ3:	JFFO	T1,.+1		;NUMBER OF (REAL) 1'S
	LSH	T1,(T2)		;GET RID OF THEM
	CAIN	T4,^D36		;1ST POSITION IN WORD?
	ADDI	T4,1		;YES, SUBTRACT REAL JFFO COUNT
	SUBI	T4,1(T2)	;DECREASE POSITION COUNT
	JUMPG	T4,GETZ1	;TRY NEXT 0 - HOLE
GETZ4:	AOBJN	P1,GETZ		;1'S ON END - START FRESH AT NEXT WORD

;HERE IF THE DESIRED SIZE NOT YET FOUND, BUT THE WORD HAD 0'S ON THE END
GETZ5:	AOBJP	P1,CPOPJ	;THROUGH IF END OF SAT
	SKIPGE	T1,(P1)		;NEXT WORD POSITIVE?
	JRST	GETZ		;NO. THIS HOLE NOT GOOD ENOUGH
	JFFO	T1,.+2		;YES. COUNT THE 0'S
	MOVEI	T2,^D36		;36 0'S
	ADDI	T3,(T2)		;ADD TO PREVIOUS ZERO-COUNT
	MOVEI	T4,^D36		;RESET T4
	JRST	GETZ2		;AND TEST THIS HOLE
;SUBROUTINE TO SET UP A BIT MASK FOR IORM OR ANDCAM INTO A TABLE
;ENTER WITH T1=POSITION (36=BIT0, 1=BIT35)
; AND T3=HOW MANY
;AFTER THE FIRST CALL USE BITMS2, T3=COUNT RETURNS T1=MASK,
;T3=REMAINING COUNT ROUTINE HAS RETURNED FINAL MASK IF
;T3 .LE. 0 ASSUMES T4=ADR IN TABLE, BITMS2 INCREMENTS T4

INTERN	BITMSK,BITMS2
BITMSK:	PUSH	P,T1		;SAVE POSITION
	MOVN	T1,T3		 ;- COUNT
	CAILE	T3,^D36		;MORE THAN 1 WORD?
	MOVNI	T1,^D36		;YES, SETTLE FOR A WORD (OR LESS)
	MOVSI	T2,400000	;SET TO PROPOGATE A MASK
	ASH	T2,1(T1)	;GET THE RIGHT NUMBER OF BITS
	SETZ	T1,
	LSHC	T1,@0(P)	;POSITION THE BITS IN T1 (=MASK)
	SUB	T3,0(P)		;REDUCE THE COUNT TO THE NEW VALUE
	PJRST	T2POPJ##	;AND RETURN
;HERE AFTER FIRST CALL, MASK STARTS AT BIT 0
BITMS2:	SETO	T1,		;MASK STARTS AT BIT 0
	MOVNI	T2,-^D36(T3)	;SET UP SHIFT
	CAIGE	T3,^D36		;DONT SHIFT IS .GE. 36
	LSH	T1,(T2)		;POSTION THE MASK
	SUBI	T3,^D36		;REDUCE THE COUNT
	AOJA	T4,CPOPJ	;UPDATE THE POSITION AND RETURN

;SUBROUTINE TO MARK BITS AS TAKEN IN A TABLE
;USES ACS AS RETURNED BY GETZ - P3=HOW MANY
;  LH(P4)=POSITION, RH(P4)=WHERE (POSITION=36 IF BIT0, 1 IF BIT35)
;RETURNS CPOPJ IF BIT IS ALREADY SET, CPOPJ1 NORMALLY RESPECTS T1
SETOS:	PUSH	P,T1		;SAVE T1
	MOVE	T4,P4		;WHERE
	HRRZ	T3,P3		;COUNT
	HLRZ	T1,P4		;POSITION IN WORD
	PUSHJ	P,BITMSK	;SET UP A MASK
SETOS1:	CONO	PI,PIOFF##	;BETTER NOT INTERRUPT HERE
	TDNE	T1,(T4)		;BIT ALREADY ON?
	JRST	SETOS2		;YES
	IORM	T1,(T4)		;NO, NOW IT IS
	CONO	PI,PION##	;RESTOR PI
	JUMPLE	T3,TPOPJ1##	;DONE IF COUNT .LE. 0
	PUSHJ	P,BITMS2	;NOT DONE, GET MASK FOR NEXT WORD
	JRST	SETOS1		 ;AND GO SET THE BITS IN THAT WORD
;HERE IF BIT ALREADY ON
SETOS2:	CONO	PI,PION##	;PI CAN BE ON
	PUSH	P,T3		;SAVE CURRENT COUNT
	HLRZ	T1,P4		;RESTORE ORIGINAL VALUES
	HRRZ	T3,P3
	MOVE	T4,P4
	PUSHJ	P,BITMSK	;AND GENERATE A MASK
SETOS3:	CAMN	T3,(P)		;IS THE COUNT FOR MASK=COUNT WHEN SET?
	JRST	SETOS4		;YES, DONE
	ANDCAM	T1,(T4)		;NO, CLEAR THOSE BITS
	PUSHJ	P,BITMS2	;GENERATE NEXT MASK
	JRST	SETOS3		;AND CONTINUE
SETOS4:	POP	P,(P)		;CLEARED ALL THE RIGHT BITS - FIX PD LIST
	PJRST	TPOPJ##		;AND NON-SKIP RETURN


;SUBROUTINE TO OBTAIN FREE BITS, MARK THEM AS TAKEN IN THE TABLE
;ENTER WITH T1=HOW MANY,
;T2=XWD ADR OF 1ST WORD OF TABLE, ADR OF TABLE AOBJN WORD (OR 0, LOC OF AOBJN)
;RETURNS CPOPJ IF NOT ENOUGH AVAILABLE, T1=SIZE OF LARGEST HOLE
;RETURNS CPOPJ1 IF GOTTEN, T1= RELATIVE ADDRESS OF BLOCK OBTAINED
;T3 IS UPDATED AOBJN POINTER
INTERN GETBIT
GETBIT:	PUSHJ	P,SAVE4		;SAVE P1-P4
	TLNN	T2,-1		;STARTING AT AN OFFSET?
	HRL	T2,(T2)		;NO, START AT FIRST WORD
	PUSH	P,T2		;SAVE ADR OF AOBJN WORD FOR TABLE
GETBI1:	MOVE	P1,0(P)		;GET AOBJN WORD
	MOVE	P1,(P1)
	SETZ	P2,		;NO BEST SO FAR
	MOVE	P3,T1		;NUMBER OF BITS TO GET
	PUSHJ	P,GETZ		;GET THE BITS
	  JRST	GETBI2		;NOT ENOUGH AVAILABLE
	HRRZ	T1,P4		;GOT THEM - FIRST WORD WITH ZEROES
	HLRZ	T2,(P)		;LOC OF FIRST WORD OF TABLE
	SUBI	T1,(T2)		;COMPUTE RELATIVE ADDRESS OF START
	IMULI	T1,^D36		;36 BITS PER WORD
	HLRZ	T2,P4		;BIT POSITION OF 1ST 0 IN THE WORD
	MOVNS	T2
	ADDI	T1,^D36(T2)	;T1= RELATIVE LOC WITHIN THE TABLE
	PUSHJ	P,SETOS		;MARK THE BITS AS TAKEN
	  SKIPA	T1,P3		;SOME FINK SNUCK IN ON US!
	AOSA	-1(P)		;GOT THEM - WIN RETURN
	JRST	GETBI1		;TRY AGAIN TO GET SOME BITS

	MOVE	T3,P1		;UPDATED POINTER
	JRST	T2POPJ##	;RETURN
;HERE IF NOT ENOUGH ARE AVAILABLE
GETBI2:	MOVE	T1,P2		;T1=LARGEST HOLE FOUND
	PJRST	T2POPJ##	;NON-SKIP RETURN
;ROUTINE TO CLEAR BITS FROM A TABLE
;ENTER T1=POSITION, T3=COUNT, T4=TABLE ADR
; POSITION=36 IF BIT0, 1 IF BIT35
;RETURNS POPJ IF BIT ALREADY 0, POPJ1 OTHERWISE
INTERN	CLRBTS
CLRBTS:	PUSHJ	P,BITMSK	;GENERATE A MASK
CLRBT1:	CONO	PI,PIOFF##	;CANT INTERRUPT
	MOVE	T2,(T4)		;WORD TO CLEAR BITS FROM
	TDC	T2,T1		;ARE THE BITS ALREADY OFF?
	TDNE	T2,T1
	PJRST	ONPOPJ##	;YES, RESTORE PI AND NON-SKIP
	MOVEM	T2,(T4)		;NO, NOW THEY ARE
	CONO	PI,PION##	;RESTORE THE PI
	JUMPLE	T3,CPOPJ1	;DONE IF COUNT .LE. 0
	PUSHJ	P,BITMS2	;GENERATE MASK FOR NEXT WORD
	JRST	CLRBT1		 ;AND GO CLEAR THOSE BITS

;SUBROUTINE TO FIND N CONSECUTIVE ZEROS IN A TABLE
;ARGS	T1=AOBJN POINTER TO TABLE
;	T2=PREVIOUS BEST
;	T3=HOW MANY, BIT STRTAD=1 IF START ADDR SPECIFIED
;VALUES	IF UNSUCCESSFUL, T2=LARGEST HOLE FOUND, NON-SKIP RETURN
;	IF SUCCESSFUL, T4=POSITION OF BEGINNING OF HOLE, SKIP RETURN
;THIS ROUTINE CALLS GETZ BUT SATISFIES STANDARD AC CONVENTIONS

INTERN	CLGETZ

CLGETZ:	PUSHJ	P,SAVE4		;SAVE GLOBAL ACS
	MOVE	P1,T1		;SET ACS FOR GETZ
	MOVE	P2,T2
	MOVE	P3,T3
	PUSHJ	P,GETZ		;GET THE BITS
	  CAIA		;NOT ENOUGH AVAILABLE
	AOS	(P)		;OK, SET FOR SKIP RETURN
	MOVE	T1,P1		;RESTORE T-ACS WITH ANSWERS
	MOVE	T2,P2
	MOVE	T3,P3
	MOVE	T4,P4
	POPJ	P,		;TAKE WIN OR LOSE RETURN
;SUBROUTINE TO SET BITS IN A TABLE
;ARGS	T3=HOW MANY
;	T4=POSITION OF FIRST, RH=ADDR, LH=POSITION, 36=BIT 0,1=BIT 35
;THIS ROUTINE CALLS SETOS BUT SATISFIES STANDARD AC CONVENTIONS
CSETOS::PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	P3,T3		;SET ACS FOR SETOS
	MOVE	P4,T4
	PUSHJ	P,SETOS		;SET THE BITS
	STOPCD	CPOPJ,DEBUG,BNZ, ;++BIT NOT ZERO

	POPJ	P,		;OK, RETURN
COREND:	END