Google
 

Trailing-Edge - PDP-10 Archives - ap-c796e-sb - lnkxit.mac
There are 38 other files named lnkxit.mac in the archive. Click here to see a list.
TITLE LNKXIT - EXIT MODULE FOR LINK
SUBTTL	D.M.NIXON/DMN/JLd/RKH/JBC/JNG/MCHC	27-Feb-78

;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, 1978 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

ENTRY	LNKXIT
SEARCH	LNKPAR,LNKLOW,MACTEN,UUOSYM
EXTERN	LNKCOR,LNKLOG,LNKFIO
EXTERN	.JB41


CUSTVR==0		;CUSTOMER VERSION
DECVER==4		;DEC VERSION
DECMVR==0		;DEC MINOR VERSION
DECEVR==765		;DEC EDIT VERSION



VERSION


SEGMENT

;LOCAL ACC DEFINITION
R==R1


SALL
SUBTTL	REVISION HISTORY

;START OF VERSION 1A
;50	HANDLE PAGING DURING LOCAL SYMBOL OUTPUT CORRECTLY
;51	FIX BUG IF UNDEF SYMBOLS BUT DON'T WANT TO KEEP LOCAL SYMS
;53	FIX RETURNS FROM DVMOV. ROUTINE
;54	ADD KIONLY D.P. INST.
;55	STORE VERSION NUMBER (.JBVER) IN .RBVER OF SAVE FILE
;56	FIX LOOP AT JBEX2A IF CORE IMAGE IS MULTIPLE OF 2000
;57	SETUP VESTIGIAL JOB DATA AREA EVEN IF NOT A SAVE FILE
;63	REMOVE MULTIPLY-DEFINED SYMBOLS FROM SYMBOL TABLE (IN CORE)
;65	TENEX SPEEDUPS
;66	SAVE JOB DATA AREA ON /SAVE IF DDT, SYMBOLS AND ALL CODE IN HIGH SEG
;67	PUT ADDITIVE GLOBAL REQUESTS IN UNDEF TABLE
;70	FIX ADDRESS CHECK PROBLEM
;71	MAKE ALL INFO MESSAGES STANDARD FORM
;73	(11314) PREVENT EXECUTION IF UNDEF SYMBOLS
;100	FIX ILL MEM REL ON /SAVE IF LAST BLOCK FILLS ALL OF CORE
;104	OUTPUT FAIL BLOCK HEADER IN LOCAL SYMBOL TABLE
;106	REMOVE HIORG, REPLACE BY LL.S2
;115	MAKE /NOSYMBOLS WORK CORRECTLY

;START OF VERSION 2
;135	ADD OVERLAY FACILITY
;136	FIX VARIOUS BUGS
;140	(12617) FIX ?IO TO UNASSIGNED CHANNEL ON /SYMBOL:TRIPLET FILE
;154	(12991) ONLY LOOK AT RIGHT HALF OF .JBERR TO DELETE EXECUTION
;155	(12988) FIX TEST FOR COBDDT AT RUN UUO TIME
;166	MAKE RADIX50 SYMBOL FILE TYPE 776
;177	FIX ADDRESS CHECK BUG IF PAGING SYMBOLS
;211	FIX ZEROS IN MONITOR SYMBOL TABLE
;213	(12531) LOW SEG OF TWOSEG CORE IMAGE  BAD
;221	GET PROTECTION CODE RIGHT ON XPN FILE

;START OF VERSION 2A
;244	DATE75 FIX TO MAKE LOW SEG FILE HAVE CORRECT DATE
;START OF VERSION 2B
;224	PUT SECOND SYMBOL FOR COMMON BLOCK IN RADIX50 SYMBOL TABLE
;226	FIX UNDEFINED SYMBOL BUG (117 NOT SET UP)
;234	FIX VARIOUS BUGS IF HIGH FILE IS MADE RATHER THAN RENAMED
;235	(13845) FIX ZERO COMPRESSOR IF PAGED AND READING ZEROS
;241	USE LARGER OF ABS OR LOW REL BREAK FOR .JBFF
;242	HANDLE USER PAGE FAULT HANDLER CORRECTLY
;244	DATE75 FIX TO MAKE LOW SEG FILE HAVE CORRECT DATE
;247	Change all references to DEBUGSW. Now lh is -1 if set,
;	rh is table index  for either /DEBUG or /TEST
;266	Correct problems with loading symbols when LS area
;	overflows to the DSK.
;267	Get symbol table offest right when core window
;	changes.
;270	Use the correct initialization routine when high
;	core overflows to the disk during this phase.
;322	Get LSYM and other core management variables right
;	so LNKCOR doesn't fail
;324	Don't release the symbol channel if still needed,
;	when loading symbols into root of an overlay program.
;330	Release the correct channel when done with symbols
;	being loaded into the root of an overlay program.
;335	Keep LSYM from being clobbered when loading symbols
;	into root of overlay program.  Don't confuse LNKCOR
;336	Fix /RUN switch to work properly
;337	Insert check for no core to zero before BLT and
;	prevent possible ILL MEM REF
;353	REMOVE EDIT 225
;357	LABEL EDITS 224,226,234,235,241,242
;360	REMOVE EDIT 336
;401	Remove 5.06 compatability hack setting up vestigial jobdat.
;403	Fix HALT if generating new style symbol file.
;423	Fix ?ILL ADDR IN UUO when the zero compressor tried to use
;	the LS area after it had done a CORE UUO to get rid of it.
;433	Support the /RUN switch.
;START OF VERSION 2C
;442	Fix the DVMOV. routine to either RENAME or copy,
;	and delete copy routines called if DVMOV. fails.
;443	Don't lose part of local symbols if overflowing to disk.
;467	Correct RT.PT check at SYMO1
;471	Add code for ALGOL debugging system.
;476	Insert missing FTOVERLAY conditional.
;517	Make first word of ALGOL symbol file be 1044,,count.
;524	Check for symseg area reduced to one page & don't zero rest.
;530	Get triplet flag definitions right.
;544	SOUP in LINK version 3 stuff for TOPS-20.
;547	Make LINK assemble with MACRO 51.
;555	Don't round .RBSIZ up to block bound for symbol files.
;557	Clean up the listing for release.

;START OF VERSION 3
;446	CHANGES FOR TENEX

;START OF VERSION 3A
;560	Release on both TOPS-10 and TOPS-20 as LINK version 3A(560)

;START OF VERSION 4
;570	Don't lose local symbols when undefined globals exist.
;575	On /EXECUTE/SAVE to a two segment program, always run xxx.LOW
;606	Get the protection of .HGH and .XPN files right.
;616	Give appropriate error messages when RENAMEs fail
;621	/SAVE AND /SSAVE GENERATE EXE FILE.  
;	/SAVE AND /SSAVE NO LONGER TAKES ANY ARGUMENT.  IF THE CORE
;	SIZE IS SPECIFIED, LINK WILL IGNORE IT.
;	THE CODE TO GENERATE .HGH/.SHR/.LOW FILES ARE UNDER THE 
;	CONDITIONAL ASSEMBLY SWITCH FTEXE==0.
;622	Don't set up vestigal JOBDAT unless there's a high segment.
;641	IF HIGH SEG IS PAGED, WRITE OUT WHAT'S IN CORE BEFORE UPDATING
;	VESTIGAL JOBDAT AND DUMP TO EXE FILE.
;642	EXE FILE EXTENSION FOR DISK FILE GENERATED FOR NOT HAVING
;	ENOUGH CORE
;643	FIX BUG WITH SWITCH SETTING FOR P4 IN XCMPRL.
;644	DON'T DO JSYS 147(RESET) IF WE DO EXIT.
;645	Loop back topage lc if not more core in LSREQ.
;646	Don't touch a high seg page again after high seg is removed
;	in %LOW.
;647	Don't zero unneeded memory (better VM performance).
;650	Use VM on TOPS-10 if available.
;652	Avoid bad .SAV file when paging to disk.
;704	Don't write EXE-directory entries for psect gaps.
;713	Fix bug with sparse EXE-directory.
;715	Modify SYMSEG to take psect name.
;724	Check for symbol table range in INGAP.
;725	Fix bug with incrementing process page in XCMPOV.
;726	Fix bug in INGAP routine.
;727	Give Insufficient space error message when symbol table truncated.
;731	SEARCH MACTEN,UUOSYM instead of C.
;732	Use LOWLOC and fix bugs related to page 777.
;733	Fix bug with allocated high seg pages causing bad EXE format.
;742	Don't BLT JOBDAT if process page 0 not the first page.
;744	Fix bug with calculation of EXE file size.
;754	Don't page LS area when doing symbol table output, if paging is needed for the first time for LC(or HC).
;762	Page in the LOWLOC page before generating EXE file.
;764	Update LOWLOC in GETSST incase symbol table is lower than code.
;	Also, corrects a bug in updating upper window in XCMPRS routine.
;765	Release on both TOPS-10 and TOPS-20 as LINK version 4(765)
SUBTTL	ENTER HERE

LNKXIT:	JFCL	.+1		;IN CASE CCL ENTRY
	.ERR.	(MS,0,V%L,L%I,S%I,EXS,<EXIT segment>)
	ZAPTMP			;CLEAR ALL TEMP SPACE
	MOVE	T1,HC.S0	;GET ABS BREAK
	CAMLE	T1,HC.S1	;LARGER THAN LOW SEG?
	MOVEM	T1,HC.S1	;USE LARGER
	MOVE	T1,HL.S0	;GET ABS BREAK
	CAMLE	T1,HL.S1	;LARGER THAN LOW SEG?
	MOVEM	T1,HL.S1	;USE LARGER
IFN FTOVERLAY,<
	SKIPGE	LNKMAX		;DID WE LOAD ANY OVERLAYS?
	JRST	LNKX1		;NO
	MOVE	T1,PH.OVL	;GET START OF CODE FOR ROOT
	USETI	OC,(T1)		;POSITION ON THE BLOCK
	MOVE	P2,PH.LEN	;LENGTH WE NEED
	ADD	P2,LC.LB
	SUB	P2,LC.AB	;SEE IF ENOUGH
	JUMPLE	P2,LNKX0A	;YES
	MOVEI	P1,LC.IX
	PUSHJ	P,LNKCOR##	;MUST EXPAND
	  JRST	LNKX0C		;DO IT THE HARD WAY
LNKX0A:	MOVE	T1,LC.LB
	SUBI	T1,1
	HLL	T1,PH.OVL	;SETUP IOWD
	SETZ	T2,
	IN	OC,T1		;READ BACK CORE
LNKX0B:	  SKIPA	T1,OV.S1	;CORE BOUNDS
	PUSHJ	P,ER.IOV##	;INPUT ERROR
	HRRZM	T1,HL.S1	;
	HLRZM	T1,HC.S1
	JRST	LNKX1		;

;NOW TO READ BACK FIRST FEW BLOCK
LNKX0F:	SETZM	LW.S1		;STARTS AT ZERO
	MOVE	T1,LC.UB
	MOVEM	T1,LC.AB	;USE IT ALL AGAIN
	SUB	T1,LC.LB
	MOVEM	T1,UW.S1	;UPPER BOUND
	PUSHJ	P,LC.IN##	;READ IT BACK
	JRST	LNKX0B		;FIXUP VARIOUS POINTERS
LNKX0C:	SETZM	LW.S1		;SET BACK TO START
	MOVE	T1,PH.OVL
	USETI	OC,(T1)		;SET ON BLOCK
	MOVE	T1,LC.UB
	MOVEM	T1,LC.AB	;USE ALL AVAILABLE SPACE
	SUB	T1,LC.LB	;GET SIZE OF WINDOW
	MOVEM	T1,UW.S1	;UPPER WINDOW
	ADDI	T1,1
LNKX0D:	MOVN	T1,T1
	HRLZ	T1,T1
	HRR	T1,LC.LB	;IOWD
	SUBI	T1,1		;AT LAST
	SETZ	T2,
	IN	OC,T1
	  SKIPA	T1,LC.AB
	PUSHJ	P,ER.IOV##
	SUB	T1,LC.LB
	ADD	T1,LW.S1	;ADD BASE
	CAMG	T1,PH.LEN	;REACHED END YET?
	JRST	LNKX0E		;NO
	MOVE	T1,PH.LEN	;YES, GET WHAT WE REALLY NEED
	IORI	T1,.IPM
	MOVE	T2,T1
	SUB	T2,LW.S1
	ADD	T2,LC.LB
	CAMN	T2,LC.UB	;ARE WE IN LAST BLOCK
	JRST	LNKX0E		;YES, NO CHANGE
	MOVEM	T2,LC.AB	;RESET UPPER BOUND IN USE
	SETZM	1(T2)		;ZERO FIRST WORD
	HRLI	T2,1(T2)
	HRRI	T2,2(T2)
	BLT	T2,@LC.UB	;AND THROUGH REST
LNKX0E:	HRL	T1,LW.S1	;ORIGIN
	PUSHJ	P,LC.OUT##	;WRITE OUT THIS MUCH
	MOVE	T1,LC.AB	;
	SUB	T1,LC.LB	;GET SIZE OF WINDOW
	MOVE	T2,T1
	ADD	T2,LW.S1
	CAML	T2,PH.LEN	;MORE TO DO?
	JRST	LNKX0F		;NO
	AOS	T2,T1		;PUT COPY IN T2
	ADDM	T1,LW.S1	;NEW WINDOW BASE
	ADDB	T2,UW.S1	;GET NEXT UPPER BOUND
	CAMG	T2,PH.LEN	;DO WE NEED TO READ IT ALL IN?
	JRST	LNKX0D		;YES
	MOVE	T1,PH.LEN	;NO, GET HIGHEST WE NEED
	ADDI	T1,.DBM		;[650] UP TO NEXT BLOCK
	ANDCMI	T1,.DBM		;[650] INCASE WAS ALREADY THERE
	SUB	T1,LW.S1	;NO. OF WORDS
	JRST	LNKX0D		;TO INPUT

>;END OF IFN FTOVERLAY
LNKX1:	MOVEI	R,1		;SETUP TO POINT TO LOW SEG
	MOVE	R,@SG.TB
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;IF LOADING OVERLAYS
	SETZM	USYM		;IGNORE UNDEFINED SYMBOLS TIL RUN TIME
>
	MOVEI	T1,PATSP.	;IF NOT ALREADY
	SKIPN	PATSPC		;SETUP PATCHING SIZE
	MOVEM	T1,PATSPC	;IN CASE REQUIRED
	SETZM	FRECOR		;NO NEED NOW
	SKIPN	FS.SS		;THESE ARE THE ONLY FIXUPS WE CAN DO NOW
	SKIPE	USYM		;BUT MAY HAVE GLOBAL REQUESTS
	CAIA
	PUSHJ	P,FX.ZAP	;NONE, SO GET RID OF AREA
				;NOW TEST FOR CASE INWHICH SYMBOL FILE WAS
				;OPENED BUT NOT USED (NOT VERY LIKELY)
	SKIPE	UW.LS		;NEVER OPENED
	SKIPE	LW.LS		;NEVER USED IF STILL ZERO
	JRST	CLSMAP		;STILL IN USE, OR NEVER WAS
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;IF LOADING OVERLAYS
	SKIPN	UW.LS		; AND PAGING SYMBOLS
	CAIA			;NO
	JRST	CLSMAP		;KEEP FILE OPEN RATHER THAN READ IN
>
	SETZM	UW.LS		;CLEAR UNWANTED POINTER
	MOVEI	T1,SC		;SYMBOL FILE CHAN #
	PUSHJ	P,DVDEL.##	;DELETE FILE AND REMOVE ALL TRACES
	  JFCL
	SETZM	IO.PTR+SC	;AND FORGET ABOUT IT
CLSMAP:	SKIPN	IO.PTR+MC	;AN OPEN MAP?
	JRST	RDJBDA		;NO
	MOVEI	T1,MC		;SET CHAN#
	MOVEM	T1,IO.CHN	;IN ACTIVE STATE
	PUSHJ	P,DVRLS.##	;CLOSE FILL AND DO POSITIONING
	PUSHJ	P,DVZAP.##	;RETURN BUFFERS AND DATA BLOCK
RDJBDA:	SKIPE	PAG.S2		;HIGH SEG PAGING?
	PUSHJ	P,RDJBH		;YES, READ IN .JBHDA
	SKIPE	PAG.S1		;LOW SEG PAGING?
	PUSHJ	P,RDJBL		;YES
	HRRZ	T1,.JBERR	;GET ERRORS FOR THIS PROCESS
	ADD	T1,USYM		;EACH UNDEF COUNTS ONE
	HRRM	T1,.JBERR	;WILL STOP EXECUTION IF NON-ZERO
	JRST	UDF0		;NOW FOR UNDEFINED SYMBOLS

;HERE TO READ IN FIRST 10 WORDS OF HIGH SEGMENT

RDJBH:	MOVEI	T2,.JBHDA	;NO OF WORDS WE NEED
	PUSHJ	P,DY.GET	;GET THEM
	MOVEM	T1,JBHPTR	;STORE LOCATION
	SUBI	T1,1		;IOWD IS 1 LESS
	HRLI	T1,-10		;SHOULD BE -.JBHDA BUT MACRO 50 NOT YET OUT
	SETZ	T2,		;TERMINATE LIST
	USETI	HC,1		;SET ON BLOCK 1
	IN	HC,T1		;READ FIRST 10 WORDS ONLY
	  POPJ	P,		;OK
	PUSH	P,[HC]
	.ERR.	(ST,,V%L,L%F,S%F,IHC)

;HERE IF LOWSEG PAGED, WE NEED BOTH ENDS OF FILE AT ONCE
;THEREFORE PUT JOBDAT (0-137) IN DY AREA, POINTER IS JOBPTR
;AND TOP OF FILE IN LC AREA

RDJBL:	MOVEI	T2,.JBDA	;NEED ONE BLOCK
	PUSHJ	P,DY.GET
	MOVEM	T1,JOBPTR	;HOLD OFFSET IN CORE SO WE CAN FIXUP
				; REFERENCES TO JOBDAT SYMBOLS
	SKIPN	LW.S1		;HOWEVER IF 1ST PAGE IS IN CORE
	JRST	BLTJBL		;JUST MOVE IT
	SUBI	T1,1		;IOWD IS ONE LESS
	HRLI	T1,-140		;WORD COUNT
	SETZ	T2,		;TERMINATE LIST
	USETI	LC,1		;READ BLOCK 1
	IN	LC,T1		;AT LEAST FIRST 140 WORDS
	  POPJ	P,		;NONE
	PUSH	P,[LC]
	.ERR.	(ST,,V%L,L%F,S%F,ILC)


;HERE TO JUST BLT JOBDAT AREA TO SAFE PLACE
BLTJBL:	HRL	T1,LC.LB	;FROM HERE
	HRRI	T2,.JBDA(T1)	;TO HERE
	BLT	T1,-1(T2)	;WELL ALMOST THERE
	POPJ	P,
SUBTTL	UNDEFINED SYMBOLS

;HERE TO PUT UNDEFINED GLOBALS INTO UNDEF TABLE IN CORE
;THIS IS OLD FORMAT (2 WORD SYMBOLS)
UDF0:	SKIPN	R,SYMSEG	;LOAD OFFSET TO EITHER LC OR HC
	MOVEI	R,LC.IX		;ASSUME LOWSEG FOR SYMBOLS
	SKIPN	NOSYMS		;DON'T WANT UNDEFS IF /NOSYM
	SKIPN	P2,USYM		;ANY UNDEFINED SYMBOLS?
	JRST	NOUNDF		;NO, GET RID OF AREA
				;BUT DO WE REALLY NEED UNDEFS?
	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT POINTER
	MOVE	T1,LC.LB	;NO
	SKIPN	.JBDDT(T1)	;JOBDDT NON-ZERO
	SKIPE	SYMSEG		;OR SYMBOLS REQUESTED
	JRST	UDF0A		;YES
	SKIPE	IO.PTR+%SC	;BUT DO WE WANT SYMBOL FILE
	SKIPL	SYMFRM		; OLD STYLE?
	JRST	NOUNDF		;NO, GET RID OF THEM
UDF0A:	LSH	P2,1		;2 WORDS PER SYMBOL
	MOVE	P4,PATSPC	;NEED TO LEAVE A HOLE FOR PATCHING
	PUSHJ	P,GETSST	;[715] GET FINAL SYMBOL START ADDR
	SKIPE	PAG.S0(R)	;PAGING?
	PUSHJ	P,LSYP		;YES, GET RIGHT PAGE IN CORE
	ADDB	P4,P2		;SPACE WE NEED
	ADD	P2,TAB.LB(R)	;IN CORE
	SUB	P2,LW.S0(R)	;REMOVE WINDOW OFFSET
	CAMG	P2,TAB.AB(R)	;ENOUGH CORE?
	JRST	UDF1		;YES,
	SUB	P2,TAB.AB(R)	;GET EXTRA WE NEED
	MOVEI	P1,(R)		;FROM WHERE
	PUSHJ	P,LNKCOR##	;GET IT
	  PUSHJ	P,NO.COR##	;TOTAL FAILURE
	SKIPN	TAB.PG(R)	;[570] PAGING?
	JRST	UDF0B		;[570] NO, SKIP THIS
	MOVE	T1,P4		;[570] YES, UPDATE UW
	IORI	T1,.IPM		;[570] SINCE PAGING ROUTINES DON'T
	MOVEM	T1,TAB.UW(R)	;[570] WHEN MAKING WINDOW BIGGER
UDF0B:	PUSHJ	P,CHKPAG	;[570] JUST INCASE WE STARTED PAGING
	MOVE	P2,P4		;RELATIVE
	ADD	P2,TAB.LB(R)	;FIX IN CORE
	SUB	P2,LW.S0(R)	;REMOVE WINDOW OFFSET
UDF1:	SKIPGE	SYMSEG		;[715] PSECT NAME USED?
	JRST	.+3		;[715] YES, JUMP
	MOVEM	P4,HC.S0(R)	;FOR .JBCOR
;NOW LOOP THROUGH GS AREA LOOKING FOR UNDEFINED SYMBOLS

	EXCH	P4,HL.S0(R)	;GET BASE OF UNDFS
	MOVN	T2,USYM		;NUMBER OF UNDEF SYMBOLS
	MOVMM	T2,JOB117	;WILL FIX IT LATER, JUST NO. NOW
	HRL	P4,T2		;AOBJN POINTER TO UNDEFS
	LSH	T2,^D18+1	;PUT 2*COUNT IN LEFT HALF
	HRR	T2,P4		;ADDRESS
	ADD	T2,LL.S0(R)	;+OFFSET
	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;CODE OFFSET
	MOVEM	T2,.JBUSY(T1)	;FIXUP POINTER
	ADD	P4,TAB.LB(R)	;FIX IN CORE
	SUB	P4,LW.S0(R)	;REMOVE WINDOW OFFSET
	MOVE	P2,HT.PRM	;GET HASH SIZE
	SKIPE	T1,@HT.PTR	;GET POINTER IF NON-ZERO
	JRST	UDFTRY		;SEE IF A REQUEST
UDFNXT:	SOJGE	P2,.-2		;MORE?
	JRST	UDFDN		;NO

UDFTRY:	ADD	T1,GS.LB	;ADD IN BASE
	MOVE	W1,(T1)		;GET FLAGS
	TXNN	W1,PS.REQ	;GLOBAL REQUEST
	JRST	UDFNXT		;NO, TRY NEXT SYMBOL
	DMOVE	W2,1(T1)	;GET SIXBIT SYMBOL & VALUE (REQUEST POINTER)
	PUSHJ	P,SXBR50	;CONVERT TO SIXBIT
	TXO	W2,R5.GLB	;MAKE GLOBAL DEFINITION
	ADDI	P4,1		;WILL BUMP LOCATION BY 2 (LATER)
	HRRZ	T1,P4		;ADDRESS ONLY
	CAMLE	T1,TAB.AB(R)	;WILL IT FIT IN WHAT WE HAVE?
	PUSHJ	P,UDFEXP	;NO, EXPAND AREA
	DMOVEM	W2,-1(P4)	;STORE NAME & VALUE
	TXNE	W1,PS.FXP	;ANY ADDITIVE GLOBAL FIXUPS
	JRST	UDFGB		;YES, RECREATE THE REQUESTS
UDFLUP:	AOBJN	P4,UDFNXT	;AND COUNT BY 1
UDFDN:				;UNLESS FINISHED
	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;CODE OFFSET
	MOVE	T2,JOB117	;GET NUMBER OF UNDEFS
	LSH	T2,1		;2 WORDS PER SYMBOL
	MOVN	T2,T2
	HRLM	T2,.JBUSY(T1)	;FIXUP POINTER
	MOVE	T2,.JBUSY(T1)	;GET A COPY
	MOVEM	T2,JOB117	;FOR LATER
	JRST	GSDLT		;DELETE GLOBAL SYMBOL TABLE

UDFGB0:	TXNE	W1,S.LST	;IS THIS THE LAST BLOCK
	JRST	UDFLUP		;YES
	ADDI	T1,.L		;NO, GET NEXT TRIPLET
UDFGB:	HRRZ	T1,@HT.PTR	;GET POINTER AGAIN
	ADD	T1,GS.LB	;ADD IN BASE
	SKIPG	W1,.L(T1)	;GET NEXT FLAG WORD
	JRST	UDFERR		;MUST HAVE SIGN BIT ON
	TXNN	W1,S.FXP	;AND A FIXUP
	JRST	UDFGB0		;NOT YET
	MOVE	W3,.L+2(T1)	;GET VALUE
	MOVE	T1,W3
UDFGB1:	ADD	T1,FX.LB	;RELOCATE IN FIXUP TABLE
	SKIPL	W1,0(T1)	;GET FLAGS
	JRST	UDFERR		;JUST INCASE
	TXNN	W1,FP.SYM	;ADDITIVE GLOBAL FIXUP?
	JRST	UDFGB2		;NO
	DMOVE	W2,1(T1)	;GET DATA WORDS
	TXNE	W1,FS.FXS	;SYMBOL FIXUP?
	JRST	UDFGB2		;*** DON'T KNOW HOW TO DO IT YET ***
	PUSHJ	P,SXBR50	;CONVERT TO RADIX-50
	TXO	W2,R5.GLB	;MAKE INTO A GLOBAL DEFINITION
	TXO	W3,R5.FXA	;AND TURN ON ADDITIVE BIT
	TXNE	W1,FS.FXL	;LEFT HALF?
	TXO	W3,R5.FXL	;YES
	ADDI	P4,2		;USES 2 WORDS
	HRRZ	T1,P4		;ADDRESS ONLY
	CAMLE	T1,TAB.AB(R)	;WILL IT FIT
	PUSHJ	P,UDFEXP	;NO
	DMOVEM	W2,-1(P4)	;STORE
	AOS	JOB117		;COUNT 1 MORE WORD PAIR
	SKIPGE	SYMSEG		;[715]
	JRST	UDFGB2		;[715] JUMP IF PSECT SPCIFIED
	MOVEI	T1,2		;AND INCLUDE IN SPACE ASSIGNED
	ADDM	T1,HL.S0(R)	;SINCE WE DIDN'T ACCOUNT FOR IT EARLIER

;FALL THROUGH TO NEXT PAGE
;	JRST	UDFGB2
;FALL IN FROM PREVIOUS PAGE

UDFGB2:	HRRZ	T1,W1		;GET POINTER
	JUMPE	T1,UDFLUP	;ALL DONE IF ZERO
	JRST	UDFGB1		;GET NEXT BLOCK

UDFEXP:	PUSH	P,P2		;SAVE P2 BEFORE EXPANDING CORE
	MOVEI	P1,(R)
	MOVEI	P2,2		;AT LEAST 2 WORDS EXTRA
	SUB	P4,TAB.LB(R)	;REMOVE BASE INCASE WE MOVE
	ADD	P4,LW.S0(R)	;INCASE PAGES CHANGE
	PUSHJ	P,LNKCOR##
	  PUSHJ	P,NO.COR##	;FAILED
	SKIPN	TAB.PG(R)	;[570] PAGING THIS AREA?
	JRST	UDFEX1		;[570] NO, FORGET IT
	MOVE	T1,P4		;[570] YES, MUST UPDATE UW OURSELVES
	IORI	T1,.IPM		;[570] ONLY EXPANDED TO THIS PAGE
	MOVEM	T1,TAB.UW(R)	;[570] UPDATE THE WORD
UDFEX1:	PUSHJ	P,CHKPAG	;[570] INCASE WE STARTED PAGING
	SUB	P4,LW.S0(R)	;BACK AS IT WAS
	ADD	P4,TAB.LB(R)
	POP	P,P2		;RESTORE P2 TO BEFORE UDFEXP
	POPJ	P,

UDFERR:	JRST	UDFLUP		;SYMBOL TABLE FOULED UP
;HERE TO GET RID OF GLOBAL TABLE AND IF POSSIBLE CUT BACK CORE
NOUNDF:	SETZM	USYM		;MAKE SURE ITS CLEAR
	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;BASE OF LOW SEG
	SETZM	.JBUSY(T1)	;CLEAR UNDF POINTER
GSDLT:	SKIPN	.JBDDT(T1)	;SEE IF WE NEED LOCAL SYMBOLS
	SKIPE	SYMSEG		;EITHER FOR /DEB OR /SYMSEG
	JRST	GSNRED		;YES, DON'T CUT BACK CORE YET
	MOVEI	T1,GS.IX-1	;START AT AREA JUST LOWER
	SKIPN	TAB.LB(T1)	;FIND HIGHEST AREA IN USE
	SOJA	T1,.-1		;WILL GET THERE EVENTUALLY
	MOVE	T2,TAB.AB(T1)	;GET HIGHEST LOC IN USE IN IT
	IORI	T2,1777		;K BOUND
	ADDI	T2,2000		;EXTRA K FOR SAFETY
	CAML	T2,.JBREL	;ANYTHING TO GIVE BACK?
	JRST	GSNRED		;NO, REDUCED ALREADY
	CORE	T2,		;DELETE TOP PART
	  JRST	GSNRED		;NEVER CAN HAPPEN
	MOVE	T2,.JBREL	;GET NEW TOP
	MOVEM	T2,GS.AB	;RESET TABLE
	MOVEM	T2,GS.UB
	CAMLE	T2,GS.LB	;INCASE WE REDUCED IT ALL
	JRST	GSRED		;NO, ALL IS WELL
	MOVEM	T2,TAB.UB(T1)	;RESET HIGHEST FREE LOC AGAIN
	SETZM	GS.LB		;SO XX.ZAP CAN WORK
GSRED:	.ERR.	(MS,.EC,V%L,L%I,S%I,RED,<Reducing low segment to >)
	.ETC.	(COR,.EP,,,,.JBREL)
GSNRED:	PUSHJ	P,GS.ZAP	;GET RID OF GS
	JRST	LSY0		;[715] GO DO LOCAL SYMBOLS
;HERE TO SETUP THE SPECIFIED PSECT FOR SYMBOL TABLE

GETSST:	PUSH	P,T1		;[727]
	SKIPL	SYMSEG		;[715] A PSECT WAS SPECIFIED?
	JRST	[SKIPGE	T1,SYMLIM	;[727] HAVE A DEFAULT LIMIT?
		HRRZM	T1,SYMLIM	;[727] YES, MAKE IT THE LIMIT
		SKIPN	HL.S0(R)	;[715] NO, NULL SEGMENT?
		ADD	P4,[EXP .JBDA,.JBHDA]-1(R) ;[715] SAVE JOBDAT
		ADDB	P4,HL.S0(R)	;[715]  HIGHEST LOADED FOR SEG
		POP	P,T1		;[727] RESTORE T1
		POPJ	P,]		;[715] RETURN FROM HERE IF HIGH/LOW
	SETZ	R,		;[727] YES, HAVE PSECT NAME
GETS1:	MOVE	T1,@RC.TB	;[715]
	MOVE	T2,RC.NM(T1)	;[715] GET PSECT NAME
	CAMN	T2,SSGNAM	;[715] IS THIS THE ONE?
	JRST	GETS2		;[715] YES,
	ADDI	R,1		;[715] NEXT ONE
	CAMG	R,RC.NO		;[715] ANY MORE?
	JRST	GETS1		;[715] YES, LOOP
	.ERR.	(MS,,V%M,L%W,S%W,NPS,<NON-EXISTENT PSECT SPECIFIED>)
	SETZM	SSGNAM		;[715]
	MOVEI	R,1		;[715] SET TO LOW
	MOVEM	SYMSEG		;[715]
	POP	P,T1		;[715] RESTORE AC'S
	JRST	GETSST+1	;[715] AND LOOP BACK

GETS2:	MOVE	T2,RC.CV(T1)	;[715] GET HIGHEST LOCATION
	ADDB	P4,T2		;[715] GET SYMBOL START ADDR
	CAMLE	P4,HL.S1	;[715] GREATER THAN HIGHT LOCATION?
	MOVEM	P4,HL.S1	;[715] UPDATE IT IN THAT CASE
	SKIPLE	SYMLIM		;[727] DO WE HAVE A LIMIT
	JRST	GETS3		;[715]  FROM THE LAST CALL TO HERE
GETS4:	ADDI	R,1		;[715] NEXT PSECT
	CAMG	R,RC.NO		;[715] SKIP IF NO MORE
	JRST	[MOVE	T1,@RC.TB	;[715] THERE IS ONE
		MOVE	T2,RC.IV(T1)	;[715] GET ITS ORIGIN
		SUBI	T2,1		;[727] ONE LESS
		MOVEM	T2,SYMLIM	;[715] MAKE IT THE SYMBOL LIMIT
		JRST	GETS3]		;[715]
	SETOM	SYMLIM		;[715] NO LIMIT AND BEEN HERE BEFORE
GETS3:	MOVE	T1,P4		;[764] GET START OF THE SYMBOL TABLE
	TRZ	T1,777		;[764] ROUND DOWN TO PAGE BOUND
	CAMGE	T1,LOWLOC	;[764] LOWER THAN ANY CODE?
	MOVEM	T1,LOWLOC	;[764] YES, UPDATE LOWEST LOCATION
	MOVEI	R,1		;[715] UPDATE SEGMENT#
	POP	P,T1		;[715] RESTORE AC'S
	POPJ	P,		;[715]
SUBTTL	LOCAL SYMBOLS

;IF LOCAL SYMBOLS AREA REQUIRED IN CORE STORE THEM  ON TOP
; OF LOW SEG OR HIGH SEG CODE
;IF LOWSEG LEAVE A GAP (PATSPC) FOR MORE SYMBOLS OR PATCHING
; IF HIGH PUT AGAINST PAGE BOUND (0.5K)
;
;IF LOCAL SYMBOLS NOT REQUIRED JUST FLUSH SPACE
;IF SYMBOLS ON DSK READ BACK IN FIRST

LSY0:	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;LOAD UP OFFSET
	SKIPN	T2,VERNUM	;GET VERSION# SET BY SWITCH
	SKIPA	T2,.JBVER(T1)	;GET VERSION FROM LOC .JBVER
	MOVEM	T2,.JBVER(T1)	;STORE BACK IN CORE IMAGE
	MOVEM	T2,VERNUM	;SAVE FOR .RBVER OF FILES
	SKIPE	NOSYMS		;NOT IF /NOSYMS
	JRST	LSY00
	SKIPN	.JBDDT(T1)	;IF DDT WE NEED LOCALS
	SKIPE	SYMSEG		;OR IF USER SPECIFIED WHERE TO PUT THEM
	JRST	LSREQ		;YES,
LSY00:	SETZM	.JBSYM(T1)	;CLEAR POINTER
	SKIPE	IO.PTR+%SC	;HOWEVER IF WE WANT OLD SYMBOL FILE
	SKIPL	SYMFRM		;WE STILL NEED TO CONVERT SYMBOLS
	JRST	NOLOCS		;NO, DONT BOTHER
;HERE IF /SYMSEG, /SYFILE:RADIX50, OR C(.JBDDT) <> 0.
;CONVERT THE SYMBOLS IN THE LS AREA TO RADIX50 AND PUT THEM IN CORE.

LSREQ:
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;DID WE SEE ANY OVERLAYS?
	JRST	LSOVS		;YES, SPECIAL
>
	.ERR.	(MS,0,V%L,L%I,S%I,SST,<Sorting symbol table>)
	PUSHJ	P,SYMINI	;DO THE MAGIC TO MOVE SYMBOLS UP IN CORE
LSREQ1:	PUSHJ	P,CHKPAG	;[645] INCASE PAGE FOR THE FIRST TIME
	SKIPE	USYM		;IF NO UNDEFINED SYMBOLS
	TDZA	P4,P4		;YES, DONE ALREADY
	MOVE	P4,PATSPC	;NEED TO LEAVE A HOLE FOR PATCHING
	PUSHJ	P,GETSST	;[715] GET FINAL SYMBOL START ADDR
	MOVE	P2,P4		;COPY INCASE NOT ENOUGH
	SKIPE	PAG.S0(R)	;PAGING THIS AREA?
	SKIPE	USYM		;YES, BUT ALREADY SETUP IF UNDEFS
	CAIA			;DON'T HAVE TO WORRY
	PUSHJ	P,LSYP		;YES, GET RIGHT PAGES IN CORE
	SUB	P2,LW.S0(R)	;REMOVE PAGED BASE
	ADD	P2,TAB.LB(R)	;IN CORE
	CAMG	P2,TAB.AB(R)	;ENOUGH CORE?
	JRST	LSY1		;YES,
	SUB	P2,TAB.AB(R)	;GET EXTRA WE NEED
	MOVEI	P1,(R)		;FROM WHERE
	SETOM	LS.PP		;[754] PROHIBIT PAGING OF SYMBOLS
	PUSHJ	P,LNKCOR##	;GET IT
	  JRST	LSREQ1		;[645] NO CORE, LOOP BACK AND PAGE
	SKIPN	TAB.PG(R)	;[570] PAGING?
	JRST	LSREQ0		;[570] NO, FORGET IT
	MOVE	T1,P4		;[570] YES, UPDATE UW
	IORI	T1,.IPM		;[570] FROM MAX VIRT ADDR, IN P4
	MOVEM	T1,TAB.UW(R)	;[570]
LSREQ0:	MOVE	P2,P4		;[570] RELATIVE
	SUB	P2,LW.S0(R)	;REMOVE PAGED BASE
	ADD	P2,TAB.LB(R)	;FIX IN CORE
LSY1:	SETZM	LS.PP		;[754]
	SKIPGE	SYMSEG		;[715]
	JRST	.+3		;[715] JUMP IF PSECT SPCIFIED
	MOVEM	P4,HC.S0(R)	;FOR .JBCOR
	EXCH	P4,HL.S0(R)	;GET BASE OF UNDFS
	SKIPE	PAG.S1		;PAGING?
	SKIPA	T1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;CODE OFFSET
	ADD	P4,LL.S0(R)	;PLUS STARTING OFFSET
	HRRZM	P4,.JBSYM(T1)	;FIXUP POINTER (ADDRESS ONLY)
	HRRZM	P4,JOB116	;AND FOR .SYM FILE
	MOVEI	T1,.IPS		;SIZE WE CARE ABOUT
	SUB	T1,LS.FR	;MINUS FREE
	MOVEM	T1,LSCNT	;LEFT IN THIS BLOCK
	SKIPGE	SYMSEG		;[715] PSECT NAME USED?
	SKIPA	T1,P4		;[715] YES, USED P4 INSTEAD
	MOVE	T1,HL.S0(R)	;SETUP CORE POINTER
	MOVEI	T2,2(T1)	;REL ADDRESS OF "TITLE" FOR PAT..
	MOVEM	T2,TTLPTR
	SUB	T1,LW.S0(R)	;REMOVED PAGED BASE
	ADD	T1,TAB.LB(R)	;ADD FIXED BASE
	MOVEM	T1,TAB.PT(R)	;ABS POINTER TO NEXT FREE LOC


;NOW OUTPUT THE SYMBOL PAT.. IN MODULE PAT.. AS THE LAST SYMBOL

	MOVE	W2,[RADIX50 04,PAT..]	;BE COMPATIBLE (ALMOST)
	SKIPGE	SYMSEG		;[715] PSECT NAME USED?
	SKIPA	W3,P4		;[715] YES, USE P4 INSTEAD
	HRRZ	W3,HL.S0(R)	;VALUE
	SUB	W3,PATSPC	;POINT TO BOTTOM OF AREA
	HLRE	T1,JOB117	;BUT TAKE INTO ACCOUNT UNDEFINED SYMBOLS
	ADD	W3,T1		;WHICH ARE BETWEEN PAT.. AND .JBSYM
	ADD	W3,LL.S0(R)	;ADD IN OFFSET TO SEGMENT
	PUSHJ	P,SYMOUT	;LAST SYMBOL
	  JRST	SYDONE		;[715] EXCEEDED SPACE, ALL DONE
	TLZ	W2,740000	;MAKE RADIX50 0,PAT.. BE THE TITLE
	PUSHJ	P,SYMOUT
	  SKIPA			;[715] EXCEEDED SPACE, ALL DONE
	PUSHJ	P,LSLOOP	;READ ALL OF SYMBOLS
	JRST	SYDONE		;ALL DONE

IFN FTOVERLAY,<
LSOVX::	MOVEM	T1,LSCNT	;STORE WORDS LEFT IN THIS BLOCK
	SETZM	TTLPTR		;START AFRESH
	POPJ	P,

LSOVS:	HLRE	T2,PH.RDX	;GET - NO. OF SYMBOLS
	MOVM	T3,T2		;+
	ADD	T3,HL.S1	;HIGHEST LOCATION
	ADD	T3,SPACE	;PLUS BUFFER SPACE
	ADD	T3,PATSPC	;AND PATCHING SPACE
	IOR.	T3,.PGSIZ	;UP TO PAGE BOUND
	ADDI	T3,1		;NEXT FREE
	ADD	T3,T2		;START OF SYMBOLS
	HLL	T3,PH.RDX	;- COUNT
	MOVEM	T3,JOB116
	MOVEM	T3,.JBSYM(T1)	;STORE SYMBOL TABLE PTR
	JRST	NOLOCS		;BUT DON'T READ IN
>
;HERE TO SETUP CORRECT LC/HC PAGES
;WRITE OUT ALL OF CURRENT (UPTO START OF LAST LOC IN USE)
;ALLOCATE INITIALLY 1 BLOCK (IT WILL EXPAND AS REQUIRED)

LSYP:	HRLZ	T1,LW.S0(R)	;BASE
	HRR	T1,UW.S0(R)	;UPPER LIMIT
	PUSHJ	P,@[EXP LC.OUT##,HC.OUT##]-1(R)	;GO TO CORRECT ROUTINE
	SKIPGE	SYMSEG		;[715] PSECT SPECIFIED?
	SKIPA	T2,P4		;[715] YES,
	HRRZ	T2,HL.S0(R)	;THIS IS THE LOCATION WE REQUIRE
	ANDCMI	T2,.IPM		;WILL BE LOWER PAGE BOUND
	MOVEM	T2,LW.S0(R)	;STORE IT NOW
	IORI	T2,.IPM		;THENCE UPPER BOUND
	EXCH	T2,UW.S0(R)	;SWAP WITH CURRENT
	CAME	T2,UW.S0(R)	;IF IDENTICAL
	JRST	[MOVE	T1,UW.S0(R)	;GET UPPER LIMIT
		HRLI	T1,-.IPM(T1)	;GET LOWER LIMIT FOR THIS BLOCK
		PUSHJ	P,@[EXP LC.IN##,HC.IN##]-1(R)	;READ IN TOP BLOCK
		JRST	LSYP1]		;AND CONTINUE
	HRLZ	T2,TAB.AB(R)	;WE MUST BLT DOWN THE LAST BLOCK
	TLZ	T2,.IPM		;AS IT MAY CONTAIN DATA
	HRR	T2,TAB.LB(R)
	MOVEI	T1,.IPS(T2)	;BASE OF FREE
	BLT	T2,-1(T1)	;MOVE IT
LSYP1:	HRRZ	T1,TAB.LB(R)	;LOWEST LOC IN CORE
	ADDI	T1,.IPS		;FIRST BLOCK NOW CONTAINS DATA
	CAML	T1,TAB.AB(R)	;AREA ONLY ONE PAGE LONG?
	JRST	LSYP2		;YES, DON'T ZERO NEXT AREA
	HRL	T1,T1
	SETZM	(T1)		;ZERO IT
	ADDI	T1,1		;FORM BLT PTR
	BLT	T1,@TAB.AB(R)	;CLEAR ALL OF THIS CORE
;NOW GIVE REST TO NEXT LOWER AREA

LSYP2:	MOVE	T1,TAB.LB(R)	;GET BASE
	IORI	T1,.IPM		;MAKE IT ONE BLOCK LONG
	MOVEM	T1,TAB.AB(R)	;SO WE CAN CORRECTLY COUNT
	MOVEI	T1,-1(R)	;GET INDEX TO NEXT AREA
	SKIPN	TAB.LB(T1)	;FIND ONE SETUP (MUST BE)
	SOJA	T1,.-1		;SHOULD NEVER GET HERE ANYWAY
	MOVE	T2,TAB.AB(T1)	;GET HIGHEST IN USE
	ADDI	T2,1		;POINT TO NEXT FREE
	CAML	T2,TAB.LB(R)	;ALREADY HERE?
	POPJ	P,		;YES, NOTHING WE CAN DO ABOUT IT
	SUBI	T2,1		;UPPER LIMIT AGAIN
	MOVEM	T2,TAB.UB(T1)	;RESET IT FOR LOWER AREA
	HRRZI	T1,1(T2)	;NEXT FREE WHERE BLOCK WILL GOTO
	HRL	T1,TAB.LB(R)	;FROM WHERE IN LEFT
	HRRZM	T1,TAB.LB(R)	;NOW RESET IT
	MOVE	T2,T1		;GET A COPY
	BLT	T1,.IPM(T2)	;THIS BLOCK DOWN
	MOVS	T2,T2		;PUT FROM ADDR. IN RIGHT
	HRLI	T1,(T2)		;NOW FOR ZERO BLT
	HRRI	T1,1(T2)
	SETZM	(T2)
	TLO	T2,.IPM		;STILL HAVE TO SET TOP INUSE
	HLRZM	T2,TAB.AB(R)	;FOR 1 BLOCK
	BLT	T1,.IPM(T2)	;THROUGH THIS BLOCK
	POPJ	P,
LSLOOP::PUSHJ	P,GETSYM	;GET SYMBOL IN W1,W2,W3
	  POPJ	P,		;ALL DONE
	JUMPGE	W1,LSLOOP	;IGNORE ALL EXTENDED BLOCK
	TXNE	W1,PT.TTL	;SPECIAL IF TITLE BLOCK
	JRST	LTITLE		;NEED TO KEEP POINTERS ETC
	TXNE	W1,PT.SYM	;ONLY WANT REAL SYMBOLS
	TXNE	W1,PS.MDF	;BUT NOT MULTIPLE DEFINITION
	JRST	LSLOOP		;MUST BE SOME THING ELSE
	PUSHJ	P,SXBR50	;CONVERT TO RADIX-50
	TXNE	W1,PS.GLB	;GLOBAL?
	TXO	W2,R5.GLB	;YES
	TXNE	W1,PS.COM	;COMMON?
	JRST	LSLUPC		;YES, NEEDS TWO SYMBOLS
	TXNE	W1,PS.LCL	;THEN LOCAL?
	TXO	W2,R5.LCL	;YES
	TXNE	W1,PS.DDT	;NO DDT OUTPUT?
	TXO	W2,R5.DDT	;YES SET BIT
LSLUP1:	PUSHJ	P,SYMOUT	;PUT SYMBOL IN CORE
	  POPJ	P,		;[715] EXCEEDED SPACE, RETURN
	SKIPGE	LSCNT		;DO WE HAVE SOMETHING TO GIVE BACK?
	PUSHJ	P,RDUSYM	;YES, SAFE TO DO SO NOW
	JRST	LSLOOP		;AND BACK FOR MORE

LSLUPC:	PUSHJ	P,SYMOUT	;OUTPUT IT
	  POPJ	P,		;[715] EXCEEDED SPACE, RETURN
	PUSH	P,W3		;SAVE ADDRESS
	MOVX	T1,S.COM	;PART WE WANT
	PUSHJ	P,GETAST	;GET REST OF SYMBOL
	  JRST	[POP	P,W3		;TOO BAD
		JRST	LSLOOP]		;JUST IGNORE
	PUSHJ	P,SXBR50	;IN RADIX50
	TXO	W2,R5.DDT!R5.GLB	;CODE 44
	POP	P,T1		;GET ADDRESS
	HRL	T1,W3		;LENGTH ,, ADDRESS
	MOVE	W3,T1		;...
	JRST	LSLUP1		;OUTPUT IT
;HERE TO GET NEXT SYMBOL BLOCK
;CALLED BY
;	PUSHJ	P,GETSYM
;RETURNS
;W1, W2, W3 WITH SYMBOL INFO
;USES T1
;READS SYMBOL TABLE IN REVERSE ORDER

GTSYM1:	PUSHJ	P,PAGSYM	;SEE IF PAGING
	  POPJ	P,		;NO, ALL DONE
				;FALL INTO GETSYM


GETSYM:	MOVNI	T1,3		;BACKUP POINTET TO
	ADD	T1,LS.PT	;GET NEXT TRIPLET
	CAMGE	T1,LS.LB	;DON'T GO TOO FAR
	JRST	GTSYM1		;SEE IF PAGING
	MOVEM	T1,LS.PT	;SAFE TO STORE NOW
	TMOVE	W1,0(T1)	;FLAGS, SYMBOL, VALUE
	MOVNI	T1,3
	ADDB	T1,LSCNT	;REDUCE COUNT IN THIS BLOCK
	JRST	CPOPJ1		;SKIP RETURN

;HERE TO GIVE BACK TOP BLOCK OF SYMBOLS
;CAN ONLY BE DONE IF WE HAVE FINISHED WITH CURRENT SYMBOL
;AND ITS SECONDARY TRIPLETS
;SPECIFICALLY TITLE SECONDARIES MUST NOT BE DELETED UNTIL
;TITLE IS OUTPUT

RDUSYM:	MOVE	T1,LS.PT	;GET LOWEST ADDRESS WE STILL NEED
	IORI	T1,.IPM		;FORM BLOCK BOUND
	MOVE	T2,LS.AB	;PREV TOP
	SUBI	T2,(T1)		;LENGTH
	JUMPE	T2,CPOPJ	;JUST IN CASE 
	HRLZ	T3,T1		;FORM BLT PTP
	HRRI	T3,1(T1)
	SETZM	(T1)		;CLEAR FIRST WORD
	EXCH	T1,LS.AB	;SET IT SO
	BLT	T3,(T1)
	MOVEI	T1,.IPS		;RESET COUNT
	ADDM	T2,LSCNT	;RESET WORD COUNT
	MOVN	T2,T2		;NEGATE IT
	SKIPE	UW.LS		;LEAVE ALONE IF NOT PAGING
	ADDM	T2,UW.LS	;ADJUST UPPER WINDOW
	POPJ	P,



;HERE TO READ MORE SYMBOLS IF THEY ARE ON DSK

PAGSYM:	SKIPE	UW.LS		;NEVER WERE
	SKIPN	LW.LS		;WERE BUT ALL DONE
	POPJ	P,		;IN EITHER CASE JUST RETURN CPOPJ
	SKIPE	T1,FX.LB	;ANY FIXUPS LEFT
	SOJA	T1,.+2		;YES, BETTER LEAVE AREA WHERE IT IS
	MOVE	T1,.JBREL	;MOVE LAST BLOCK TO A SAFE PLACE
	MOVE	T2,T1		;GET A COPY FOR END OF BLT
	ANDCMI	T1,.IPM		;AT TOP OF CORE
	CAMG	T1,LS.LB	;SAME AREA BLT FROM/TO?
	JRST	PAGSY2		;YES, DON'T CLEAR IT!
	MOVEI	T3,-1(T1)	;END OF VACATED AREA
	CAMLE	T3,LS.AB	;CLEAR ALL OF IT?
	MOVE	T3,LS.AB	;NO, JUST PART NOT DONE
	HRL	T1,LS.LB	;SO WE HAVE THE HOLE IN THE MIDDLE
	BLT	T1,(T2)		;GO
	HRRZ	T1,LS.LB	;NOW TO ZERO THE JUNK WE LEFT BEHIND
	SETZM	(T1)		;FIRST WORD
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	BLT	T1,(T3)		;CLEAR 200 WORDS (USUALLY)
PAGSY2:	MOVE	T1,T2		;
	MOVEM	T1,LS.UB	;ABSOLUTE NEW TOP
	MOVEM	T1,LS.AB	;NO FREE SPACE (AB SAME)
	SUB	T1,LS.LB	;+DIFF (TOTAL AREA - 1)
	ANDCMI	T1,.IPM		;DON'T COUNT PART IN USE
	ADDM	T1,LS.LB	;FIXUP PTRS
	ADDM	T1,LS.PT
	MOVEI	T1,LS.IX	;ACCOUNT FOR NEW FREE SPACE
	PUSHJ	P,ADJ.L		;BY GIVING IT TO NEXT LOWER AREA
;NOW CHECK TO SEE IF AREA IS BIG ENOUGH

PAGSY1:	PUSHJ	P,FR.CNT##	;SEE WHATS FREE
	LSH	T1,-1		;CUT IN HALF
	ANDCMI	T1,.IPM		;BUT KEEP ON A BLOCK BOUND
	JUMPE	T1,[MOVEI T1,(R)	;AREA
		MOVEI	T2,2*.IPS	;SIZE
		PUSHJ	P,EXPSYM	;INCREASE SYMBOL SIZE
		MOVNI	T1,2*.IPS	;NOW GIVE BACK SPACE
		ADDM	T1,TAB.AB(R)
		JRST	PAGSY1]		;AND TRY AGAIN
	CAMLE	T1,LW.LS	;DO WE NEED ALL OF THIS SPACE
	MOVE	T1,LW.LS	;NO, JUST USE ENOUGH
	MOVN	T1,T1		;-INCREASE IN SIZE
	ADDM	T1,LS.LB	;ADJUST LOWER BOUND
	MOVEI	T2,LS.IX-1	;NOW TO FIND NEXT LOWER BOUND
	SKIPN	TAB.LB(T2)	;IN USE
	SOJA	T2,.-1
	MOVE	T3,TAB.AB(T2)	;GET UPPER BOUND OF NEXT LOWER
	CAML	T3,LS.LB	;IS THERE ENOUGH ROOM?
	AOJA	T3,[SPUSH <P1,P2>	;SAVE
		MOVEI	P1,LS.IX	;AREA TO EXPAND
		MOVM	P2,T1		;  AND SIZE
		ADDM	P2,LS.LB	;ADD BACK
		PUSHJ	P,LNKCOR##	;GET THE SPACE
		  PJRST	NO.COR##	;SHOULD NEVER OCCUR
		SPOP	<P2,P1>		;RESTORE
		PJRST	PAGSYM]		;GO GET SYMBOLS
	MOVE	T3,LS.LB	;BOTTOM OF THIS AREA
	SUBI	T3,1		;-1 IS TOP OF NEXT
	MOVEM	T3,TAB.UB(T2)	;TAKE IT ALL (SHUFFLER WILL GET US OUT OF TROUBLE)
	ADDM	T1,LW.LS	;BACKUP WINDOW
	HRLZ	T1,LW.LS	;FORM INPUT PTR
	HRR	T1,UW.LS	;LOWER ,, UPPER
	PUSHJ	P,LS.IN##	;INPUT AREA
	JRST	CPOPJ1		;SKIP RETURN
;HERE TO GET ASSOCIATED SECONDARY TRIPLET
;CALLED BY
;	MOVE	T1,FLAGS
;	PUSHJ	P,GETAST
;RETURNS
;+1	FAILED
;+2	SUCCESS
;USES T1, T2, T3
;SETS UP W1, W2, W3

GETAST:	MOVE	T2,LS.PT	;GET POINTER
GETNAS:	ADDI	T2,.L		;ENTER HERE WITH T2 SETUP
	CAMLE	T2,LS.AB	;STILL IN CORE?
	JRST	FNDNIC		;NOT IN CORE
	SKIPGE	T3,(T2)		;GET FLAGS
	POPJ	P,		;FOUND A PRIMARY (FAILED)
	XOR	T3,T1		;IFF ALL BITS MATCH
	TXZ	T3,S.LST	;IGNORE THIS BIT HOWEVER
	JUMPN	T3,GETNAS	;TRY AGAIN
	TMOVE	W1,(T2)		;FLAGS, SYMBOL, VALUE
CPOPJ1:	AOS	(P)
CPOPJ:	POPJ	P,


FNDNIC:	SKIPN	UW.LS
	POPJ	P,		;ALL DONE
	.ERR.	(MS,.EC,V%L,L%F,S%F,CNW)
	.ETC.	(STR,,,,,,<FNDNIC>)
SYMOUT:	AOS	T1,TAB.PT(R)	;SEE IF ENOUGH TO STORE 2 WORDS
	SKIPG	T2,SYMLIM	;[715] IS IT LIMITED BY NEXT PSECT?
	JRST	SYMO4		;[715] NO,
	PUSH	P,T1		;[715] YES, SAV T1
	SUB	T1,LC.LB	;[715] MINUS WINDOW
	ADD	T1,LW.LC	;[715] CONVERT TO VIRTUAL ADDR
	CAMGE	T1,SYMLIM	;[715] EXCEEDED THE LIMIT
	JRST	[POP	P,T1		;[715] RESTURE T1
		JRST	SYMO4]	;[715] AND RETURN
	SKIPN	SSGNAM		;[727] HAVE A NAME TO OUTPUT?
	JRST	SYMOE1		;[727] NO, JUMP OVER OUTPUTTING NAME
	.ERR.	(MS,.EC,V%L,L%W,S%W,ISS,<Insufficient space for symbol table>)
	.ETC.	(STR,.EC,,,,,< after PSECT >)
	.ETC.	(SBX,.EP!.EC,,,,SSGNAM)
	.ETC.	(STR,,,,,,<--Table truncated>)
	JRST	SYMOE2		;[727]
SYMOE1:	.ERR.	(MS,.EC,V%L,L%W,S%W,ISS)
	.ETC.	(STR,,,,,,<--table truncated>)
SYMOE2:	SOS	TAB.PT(R)	;[727] DECREMENT ONE
	POP	P,T1		;[715]
	POPJ	P,		;[715] ERROR RETURN
SYMO4:	CAMG	T1,TAB.AB(R)
	JRST	SYMO1		;YES
				;SEE IF WE CAN JUST EXPAND
	CAML	T1,TAB.UB(R)	;INTO FREE SPACE?
	JRST	SYMO2		;NO, EXPAND OR WRITE PAGE OUT
	MOVEI	T2,.IPS		;PAGE SIZE
	ADDM	T2,TAB.AB(R)	;ACCOUNT FOR IT
	SKIPE	UW.S0(R)	;IF PAGING THIS SEGMENT
	ADDM	T2,UW.S0(R)	;INCREASE WINDOW
				;FALL INTO SYMO1

SYMO1:	AOS	T1,TAB.PT(R)	;POINT TO NEXT FREE
	DMOVEM	W2,-2(T1)	;STORE SYMBOL & VALUE
IFN FTOVERLAY,<
	SKIPE	T1,RT.PT	;RELOCATABLE?
	CAMN	T1,RT.LB	;MAYBE, IS IT?
	JRST	CPOPJ1		;[715] NO, SKIP RETURN
	IBP	RT.PT		;SYMBOL IS NOT
	TXNN	W1,PS.REL	;IS IT RELOCATABLE?
	TDZA	T1,T1		;NO
	MOVEI	T1,1		;YES
	IDPB	T1,RT.PT	;SET BIT
>
	JRST	CPOPJ1		;[715] SKIP RETURN
	POPJ	P,

;HERE WHEN NOT ENOUGH ROOM
SYMO2:	SKIPE	PAG.S0(R)	;PAGING?
	JRST	SYMO3		;YES, NOT WORTH EXPANDING, JUST OUTPUT IT
	MOVE	T1,R		;EITHER LC.IX OR HC.IX
	MOVEI	T2,.IPS		;EXPAND THIS MUCH
	PUSHJ	P,EXPSYM	;GET SPACE
	JRST	SYMO1		;AND STORE
;SUBROUTINE TO EXPAND CORE, BUT NOT TO PAGE SYMBOLS
;USUALLY CALLED TO CAUSE OTHER AREA TO START PAGING
;CALLED BY
;	MOVEI	T1,AREA
;	MOVEI	T2,SIZE
;	PUSHJ	P,EXPSYM

EXPSYM:	PUSHJ	P,.SAVE2##	;USES P1, P2
	SETOM	LS.PP		;PROHIBIT PAGING OF SYMBOLS
	DMOVE	P1,T1		;GET ARGS
	PUSHJ	P,LNKCOR##	;MUST BE ABLE TO GET IT
	  JRST	NO.COR##	;SHOULD NEVER HAPPEN


;HERE TO SEE IF WE JUST STARTED PAGING AND IF SO, COPY
;JOBDAT OR VESTIGAL JOBDAT INTO DY AREA, SO WE CAN ALWAYS
;REFERENCE THEM EVEN IF THEY ARE PAGED OUT.

CHKPAG:	SKIPE	PAG.S1		;IF WE ARE PAGING
	SKIPE	JOBPTR		;FOR FIRST TIME
	CAIA			;NO
	PUSHJ	P,RDJBL		;MUST SETUP JOB DATA AREA
	SKIPE	PAG.S2		;SAME FOR HIGH SEG
	SKIPE	JBHPTR
	CAIA
	PUSHJ	P,RDJBH		;SET UP JOBDAT IN HIGH
	SETZM	LS.PP		;BACK AS BEFORE
	POPJ	P,

;HERE WHEN WE HAVE TO OUTPUT CORE
;THERE IS NO NEED TO KEEP ANY OF IT SO OUTPUT IT ALL

SYMO3:	AOS	T1,TAB.PT(R)	;POINT TO NEXT FREE
	TRNE	T1,1		;SEE IF 1 FREE LOC
	MOVEM	W2,-2(T1)	;YES, OUTPUT HALF OF SYMBOL
	HRLZ	T1,LW.S0(R)	;OUTPUT ALL OF WINDOW
	HRR	T1,UW.S0(R)
	PUSHJ	P,@[EXP LC.OUT##,HC.OUT##]-1(R)	;GO TO CORRECT ROUTINE
	SKIPGE	SYMFRM		;NEED OLD SYMBOLS (RADIX50)
	PUSHJ	P,OLDSYM	;YES
	HRRZ	T1,TAB.LB(R)	;NOW TO CLEAR JUNK
	HRLI	T1,(T1)
	ADDI	T1,1		;LOW,,LOW+1
	SETZM	-1(T1)
	BLT	T1,@TAB.AB(R)	;TO HIGH
	MOVE	T1,UW.S0(R)	;PREVIOUS HIGH WINDOW
	ADDI	T1,1		;NEW LOW
	MOVEM	T1,LW.S0(R)
	IORI	T1,.IPM		;NEW HIGH IS END OF PAGE
	MOVEM	T1,UW.S0(R)
	MOVE	T1,TAB.PT(R)	;GET POINTER (JUST BEYOND END OF CORE)
	ANDI	T1,.IPM		;SO JUST KEEP OFFSET IN THIS PAGE
	IOR	T1,TAB.LB(R)	;ADD IN BASE
	MOVEM	T1,TAB.PT(R)	;AND STORE
	TRNN	T1,1		;DID WE STORE 1 WORD BEFORE?
	MOVEM	W2,-2(T1)	;NO, DO SO NOW
	MOVEM	W3,-1(T1)
	IORI	T1,.IPM		;LAST ADDRESS IN BLOCK
	MOVEM	T1,TAB.AB(R)	;NOW WINDOWS MATCH
	JRST	CPOPJ1		;[715] SKIP RETURN



;HERE TO GET RID OF VARIOUS AREAS

GS.ZAP:	MOVEI	T1,GS.IX	;GET AREA
	PJRST	XX.ZAP##	;GENERAL ROUTINE

FX.ZAP:	MOVEI	T1,FX.IX
	PJRST	XX.ZAP##

LS.ZAP:	MOVEI	T1,LS.IX
	PJRST	XX.ZAP##

AS.ZAP:	MOVEI	T1,AS.IX	;
	PJRST	XX.ZAP##	;
;HERE TO MOVE SYMBOLS TO TOP OF CORE
;IF SORTING PUT SORT BUFFER IN AREA GS

SYMINI:	SKIPE	FX.LB		;ANY FIXUPS LEFT?
	PUSHJ	P,MOVFX		;YES, MUST MOVE THEM UP
	SKIPN	UW.LS		;IF LOCAL SYMBOLS ON DSK?
	PJRST	MOVSYM		;NO, JUST MOVE UP
;	PJRST	LKPSYM		;READ BACK INTO CORE

;HERE TO WRITE OUT END OF SYMBOL TABLE AND SET IT UP FOR SORTING
LKPSYM:	SKIPL	UW.LS		;IF -1 THEN SYMBOL TABLE NOT OUTPUT YET
	JRST	RDSYM		;JUST READ IT BACK IN
	MOVE	T1,LSYM		;ADRESS OF LAST SYMBOL STORED +1
	SUBI	T1,1
	IORI	T1,.IPM		;BLOCK BOUND
	HRL	T1,LW.LS	;FORM  BLT WORD
	HRRZM	T1,UW.LS	;SIGNAL ALL OF SYMBOLS ON DSK
	PUSHJ	P,LS.OUT##	;AND OUTPUT IT
				;FALL INTO RDSYM TO READ IT BACK


RDSYM:	PUSHJ	P,MOVSYM	;MOVE WHAT WE HAVE UP IN CORE
				;AT THIS POINT THERE IS NO NEED TO READ
				;MORE SYMBOLS, THAT WILL HAPPEN NEXT TIME ANYWAY
				;UNLESS WE ONLY HAVE ONE BLOCK IN CORE
				;THIS CASES PROBLEMS SO READ IN MORE
	MOVE	T1,UW.LS	;UPPER LIMIT
	ANDCMI	T1,.IPM		;START OF THIS PAGE
	CAME	T1,LW.LS	;IS IT THE LOWER PAGE BOUND?
	POPJ	P,		;NO, JUST RETURN
	MOVEI	T1,LS.IX-1	;YES, SEE HOW MUCH SPACE WE HAVE WITHOUT SHUFFLING
	SKIPN	TAB.LB(T1)	;USUAL LOOK FOR LOWER AREA
	SOJA	T1,.-1
	MOVE	T2,LS.LB	;WHERE WE START AT
	SUB	T2,TAB.AB(T1)	;MINUS WHATS IN USE
	SUBI	T2,1		;COUNT OF WHATS FREE
	LSH	T2,-1		;CUT IN HALF
	ANDCMI	T2,.IPM		;ON BLOCK BOUND
	CAMLE	T2,LW.LS	;BUT DON'T GET TOO MUCH
	MOVE	T2,LW.LS	;IF WE DON'T HAVE ENOUGH SYMBOLS
	MOVN	T2,T2		;GET NEG SO WE CAN BACKUP
	ADDM	T2,LS.LB	;MOVE DOWN IN CORE
	ADDM	T2,TAB.UB(T1)	;AND TAKE THIS SPACE
	ADDM	T2,LW.LS	;OPEN WINDOW WIDER
	MOVE	T1,UW.LS	;GET TOP OF WINDOW
	SUBI	T1,.IPS		;BUT WE ALREADY HAVE THIS PAGE
	HRL	T1,LW.LS	;FORM TRANS WORD
	PJRST	LS.IN##		;READ IT IN


;HERE IF TOP OF SYMBOL TABLE IS ALREADY IN CORE
;HOWEVER IT IS NOT AT TOP OF CORE WHERE WE WOULD LIKE IT
;THEREFOR MOVE ALL LS UP TO .JBREL
;USE REVERSE BLT IN ACCS

MOVSYM:
IFN FTOVERLAY,<
	SKIPLE	LNKMAX		;ANY OVERLAYS
	SKIPN	LNKNO.		;BUT NOT ROOT
	JRST	.+3		;NO
	MOVE	T1,LS.UB	;CAN NOT USE TOP OF CORE
	JRST	.+4
>
	SKIPE	T1,FX.LB	;STILL FIXUPS TO DO?
	SOJA	T1,.+2		;YES, MAKE T1 POINT TO HIGHEST FREE
	MOVE	T1,.JBREL	;NO, GET TOP OF CORE
	CAMN	T1,LS.AB	;AT ACTUAL TOP OF LS?
	POPJ	P,		;YES, JUST RETURN
	MOVEM	T1,LS.UB	;MAKE IT TOP
	SUB	T1,LS.AB	;GET DIFFERENCE = OFFSET
	PUSH	P,T1		;SAVE OFFSET
	MOVE	T4,LS.AB	;TOP
	SUB	T4,LS.LB	;-BOTTOM
	ADDI	T4,400001	;400000+LENGTH
	MOVS	T4,T4
	HRR	T4,LS.AB	;TOP OF OLD DATA
	HRLI	T1,(POP T4,0(T4))
	MOVE	T2,[JUMPL T4,T1]
	MOVSI	T3,(POPJ P,)	;REVERSE BLT NOW SET UP
	PUSHJ	P,T1		;DO IT
	MOVE	T2,LS.AB	;[647]
	MOVE	T1,LS.UB
	MOVEM	T1,LS.AB	;SET BOUNDS THE SAME
	POP	P,T1		;OFFSET
	ADD	T1,LS.LB	;NEW BASE
	SUBI	T1,1		;HIGHEST TO GIVE BACK
	HRL	T1,T2		;[647] HIGHEST ADDR TO ZERO
	PUSHJ	P,GBCK.L##
	MOVE	T1,LSYM		;NOW RESET LS.PT TO POINT TO LAST SYMBOL
	SUB	T1,LW.LS	;MINUS WINDOW BASE
	ADD	T1,LS.LB	;PLUS OFFSET IN CORE
	MOVEM	T1,LS.PT	;OK NOW
	POPJ	P,
;HERE TO ADD FREE SPACE TO NEXT LOWEST AREA IN USE
;CALLED BY
;	MOVEI	T1,THIS AREA
;	PUSHJ	P,ADJ.L
;USES T1, T2

ADJ.L:	MOVE	T2,TAB.LB(T1)	;GET CURRENT LOWEST SIZE
	SUBI	T2,1		;THIS IS NOW UPPER OF NEXT LOWER
	SKIPN	TAB.LB-1(T1)	;FIND ONE
	SOJA	T1,.-1		;EVENTUALLY
	MOVEM	T2,TAB.UB-1(T1)
	POPJ	P,		;RETURN
;HERE IF WE HAVE TO MOVE FIXUP AREA (IT MAY CONTAIN SYMBOL FIXUPS)
;MOVE UP TO VERY TOP OF CORE, OUT OF WAY OF  SYMBOLS
;USE REVERSE BLT IN ACCS

MOVFX:	MOVE	T1,.JBREL	;GET TOP OF CORE
	CAMN	T1,FX.AB	;AT ACTUAL TOP OF FIXUPS?
	POPJ	P,		;YES, JUST RETURN
	MOVEM	T1,FX.UB	;MAKE IT TOP
	SUB	T1,FX.AB	;GET DIFFERENCE = OFFSET
	PUSH	P,T1		;SAVE OFFSET
	MOVE	T4,FX.AB	;TOP
	SUB	T4,FX.LB	;-BOTTOM
	ADDI	T4,400001	;400000+LENGTH
	MOVS	T4,T4
	HRR	T4,FX.AB	;TOP OF OLD DATA
	HRLI	T1,(POP T4,0(T4))
	MOVE	T2,[JUMPL T4,T1]
	MOVSI	T3,(POPJ P,)	;REVERSE BLT NOW SET UP
	PUSHJ	P,T1		;DO IT
	MOVE	T1,FX.UB
	MOVEM	T1,FX.AB	;SET BOUNDS THE SAME
	POP	P,T1		;OFFSET
	ADDM	T1,FX.PT
	ADD	T1,FX.LB	;NEW BASE
	SUBI	T1,1		;HIGHEST LOC TO GIVE AWAY
	PJRST	GBCK.L##	;TO NEXT LOWER

SYDONE:	SKIPE	PAG.S1		;PAGING LOW SEG?
	SKIPA	P1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	P1,LC.LB	;LOAD UP OFFSET
	SKIPE	PAG.S2		;PAGING HIGH SEG?
	SKIPA	P2,JBHPTR	;YES, LOAD CORRECT OFFSET
	MOVE	P2,HC.LB	;LOAD UP OFFSET
	MOVE	T2,.JBSYM(P1)	;GET ADDRESS OF BASE OF SYMBOLS
	HRRZ	T3,TAB.PT(R)	;AND CURRENT TOP
	SUB	T3,TAB.LB(R)	;REMOVE OFFSET
	ADD	T3,LW.S0(R)	;BUT ADD IN BASE OF INCORE WINDOW
	CAMG	T3,HC.S0(R)	;[715] PSECT NAME USED?
	JRST	.+3		;[715] YES,  DON'T UPDATE
	MOVEM	T3,HC.S0(R)	;RESET HIGHEST LOC IN USE COUNTERS
	MOVEM	T3,HL.S0(R)	;SO WE WILL PRESERVE THE SYMBOLS
	ADD	T3,LL.S0(R)	;ADD IN SEGMENT OFFSET
	SUBI	T2,0(T3)	;FIND - LENGTH
	HRLM	T2,.JBSYM(P1)	;FIXUP SYMBOL TABLE POINTER
	HRLM	T2,JOB116	;AND FOR .SYM FILE
	SKIPGE	SYMFRM		;OLD STYLE SYMBOL FILE REQUIRED?
	PUSHJ	P,OLDSYM	;YES, WRITE OR COMPLETE IT
	.ERR.	(MS,0,V%L,L%I,S%I,STC,<Symbol table completed>)
	JRST	REMVLS		;SETUP REST AND DELETE LS AREA

NOLOCS:	SKIPE	PAG.S1		;PAGING LOW SEG?
	SKIPA	P1,JOBPTR	;YES, LOAD CORRECT OFFSET
	MOVE	P1,LC.LB	;LOAD UP OFFSET
	SKIPE	PAG.S2		;PAGING HIGH SEG?
	SKIPA	P2,JBHPTR	;YES, LOAD CORRECT OFFSET
	MOVE	P2,HC.LB	;LOAD UP OFFSET

REMVLS:
	SKIPLE	T1,SYMFRM	;NEW STYLE SYMBOL FILE NEEDED?
	PUSHJ	P,SAVSYM	;YES, OUTPUT THEM NOW
	PUSHJ	P,AS.ZAP	;DONE WITH ALGOL SYMBOLS
	PUSHJ	P,FX.ZAP	;ALSO DONE WITH FIXUP BY NOW
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;OVERLAYS?
	JRST	SAVTST		;KEEP UNTIL SAV FILE MADE
>
	PUSHJ	P,LS.ZAP	;GET RID OF LS
	SKIPN	PAG.LS		;IF NOT PAGING
	JRST	SAVTST		;DON'T DELETE LS FILE
	MOVEI	T1,SC		;CAN DELETE CHAN# NOW
	PUSHJ	P,DVDEL.##
	  JFCL
SAVTST:	SKIPE	IO.PTR+%VC	;SAVE FILE REQUIRED?
	JRST	JBSAVE		;YES
	JRST	JBEXIT		;NO, EXECUTE OR FORM CORE IMAGE

SUBTTL	ROUTINES FOR SYMBOLS


LTITLE:	PUSHJ	P,SXBR50	;CONVERT TO RADIX-50
	TXNE	W1,PT.BLK	;ONLY A FAIL BLOCK HEADER?
	JRST	BTITLE		;YES
	MOVE	T2,TTLPTR	;GET ADDRESS OF LAST PROG
	HRRZ	T1,TAB.PT(R)	;GET THIS ADDRESS
	SUB	T1,TAB.LB(R)	;MINUS OFFSET
	ADD	T1,TAB.LW(R)	;PLUS BASE OF WINDOW
	MOVEM	T1,TTLPTR	;SAVE FOR NEXT
	SUB	T1,T2		;GET DIFFERENCE
	MOVN	T1,T1		;NEGATE
	JUMPE	T2,.+2		;IGNORE IF FIRST TIME
	HRL	W3,T1		;FIXUP POINTER
	PUSH	P,W2		;SAVE SYMBOLS
	PUSH	P,W3
TTLLUP:	MOVX	T1,S.TTL!S.SEG	;FLAGS
	PUSHJ	P,GETAST	;GET EXTENSION TRIPLET
	  SETZB	W2,W3		;ONLY HERE IF DEFINED BY /SWITCH
	SKIPE	W3		;IF ANY HIGH SEG STUFF
	MOVE	W2,W3		;USE IT
	POP	P,W3		;GET W3 BACK
	HLR	W3,W2		;FIX IT UP
	POP	P,W2
	PUSHJ	P,SYMOUT	;OUTPUT PSEUDO SYMBOL
	  POPJ	P,		;[715] EXCEEDED SPACE, RETURN
	JRST	LSLOOP		;RETURN



BTITLE:	TXO	W2,R5.LCL!R5.GLB	;MAKE RADIX50 14,SYM
	HRRZ	W3,W3		;BLOCK LEVEL ONLY
	JRST	LSLUP1		;AND TREAT AS LOCAL SYMBOL
;SXBR50 -- SUBROUTINE TO CONVERT SIXBIT TO RADIX-50
;CALLED BY
;	MOVE	W2,SIXBIT WORD
;	PUSHJ	P,SXBR50
;RETURN
;	RADIX-50 IN W2
;USES T1, T2

SXBR50:	MOVE	T2,W2		;GET SIXBIT SYMBOL
	SETZ	W2,		;WHERE TO STORE RADIX50 SYMBOL
	SETZ	T1,		;CLEAR RECEIVING ACC
	LSHC	T1,6		;GET NEXT CHAR
	IMULI	W2,50		;MULTIPLE BY 50
	ADD	W2,SXBTAB(T1)	;ADD IN NEW CHAR
	JUMPN	T2,.-4		;NOT DONE YET
	POPJ	P,

DEFINE SXBCHR (CHR)<
 IRPC CHR,<
  RADIX50 0,CHR
>>

	XALL
SXBTAB:	SXBCHR (    $%        . 0123456789       ABCDEFGHIJKLMNOPQRSTUVWXYZ     )
	SALL
;HERE FOR OLD FORM SYMBOLS (RADIX-50)
;IF IN CORE WRITE THEM OUT WITH THREE INFORMATION WORDS AT FRONT
;HEADER, .JBSYM (116) AND .JBUSY (117)
;HEADER IS 776(TYPE) ,, LENGTH
;OTHER TWO WORDS ARE RELATIVE TO ZERO
;.JBSYM MUST HAVE A NEGATIVE LEFT HALF
;.JBUSY IS ZERO IF NO UNDEFINED SYMBOLS

OLDSYM:	MOVEI	T1,MC		;USE MAP CHAN INCASE PAGING LC
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%SC	;POINT TO CORRECT DATA
	MOVEM	T1,IO.PTR+MC
	PUSHJ	P,DVCHN.##
	MOVSI	T2,(Z MC,)	;RESET CHAN #
	MOVEM	T2,I.CHN(T1)	;SINCE %SC IS THERE CURRENTLY
	HLRO	T2,JOB116	;NUMBER OF SYMBOLS
	MOVM	T2,T2
	LSH	T2,-.DBS2W	;[650] INTO BLOCKS (ASSUME FEW UNDEFS)
	MOVEM	T2,I.EST(T1)
	MOVE	T2,VERNUM	;GET VERSION OF CORE IMAGE
	SKIPN	I.VER(T1)	;SKIP IF SET BY SWITCH
	MOVEM	T2,I.VER(T1)	;NO, SO SET IT
	PUSHJ	P,DVNAM.##	;MAKE SURE NAME SETUP
	PUSHJ	P,DVOPN.##	;INIT DEV
	PUSHJ	P,DVENT.##	;DO ENTER
				;NOW TO STORE THREE INFO WORDS
	HLRE	T1,JOB116	;NO. OF DEFINED SYMBOLS
	HLRE	T2,JOB117	;NO. OF UNDEFS
	MOVM	T1,T1		;+
	MOVM	T2,T2
	ADDI	T2,2(T1)	;PLUS TWO EXTRA WORDS
	HRLI	T2,776		;BLOCK TYPE FOR LINK
	SKIPN	T1,JOB117	;.JBUSY IF NON-ZERO
	MOVE	T1,JOB116	;OTHERWISE .JBSYM
	HRRZ	T1,T1		;REMOVE NEG LEFT HALF
	SUB	T1,LL.S0(R)	;REMOVE ORIGIN
	SUB	T1,LW.S0(R)	;INCASE PAGING
	ADD	T1,TAB.LB(R)	;FIX IN CORE
;NOW PUT HEADER WORDS IN CORE IMAGE SO WE CAN DUMP IT ALL WITH
;ONE IOWD. PUSH REAL CONTENTS OF THOSE LOCATIONS (USUALLY 0) FIRST,
;THEN RESTORE THEM LATER

	SUBI	T1,3		;BACKUP 3
	PUSH	P,0(T1)		;SAVE WORDS INCASE NOT ZERO
	PUSH	P,1(T1)
	PUSH	P,2(T1)
	MOVEM	T2,0(T1)	;SAVE HEADER
	HLLZ	T2,JOB117	;COPY  INFO WORDS
	MOVEM	T2,2(T1)	;TO NEXT 2 LOCS
	HLRE	T2,T2		;GET - LENGTH (OR 0)
	MOVM	T2,T2		;+
	HLL	T2,JOB116	;-LENGTH,,OFFSET
	MOVEM	T2,1(T1)	;FIRST INFO WORD
	HLRE	T2,JOB116	;FIND TOTAL LENGTH TO OUTPUT
	HLRE	T3,JOB117	;.JBSYM+.JBUSY
	ADD	T2,T3
	SUBI	T2,3		;+3 INFO WORDS
	HRLZ	T2,T2		;-LENGTH
	HRRI	T2,-1(T1)	;IOWD LENGTH,ADDRESS
	SETZ	T3,		;TERMINATE
	OUT	MC,T2		;DUMP IT
	  JRST	[POP	P,2(T1)		;RESTORE DATA
		POP	P,1(T1)
		POP	P,0(T1)
		PJRST	DVRLS.##]	;CLOSE FILE
	POP	P,2(T1)		;RESTORE DATA
	POP	P,1(T1)
	POP	P,0(T1)
	PUSH	P,[MC]
	.ERR.	(ST,,V%L,L%W,S%W,OES,<Output error on symbol file, file closed, job continuing>)
	POPJ	P,

;HERE TO SAVE NEW FORM SYMBOL TABLE
;IF ALL IN CORE JUST OPEN AND WRITE OUT
;IF ON DSK EITHER RENAME OR COPY THEM

SAVSYM:	PUSHJ	P,.SAVE1##	;NEED AN AC
	CAIN	T1,1		;SIXBIT SYM FILE WANTED?
	MOVEI	P1,LS.IX	;YES, STORED IN LS AREA
	CAIN	T1,2		;HOW ABOUT ALGOL .SYM FILE?
	MOVEI	P1,AS.IX	;YES, USE AS AREA INSTEAD
	SKIPN	TAB.UW(P1)	;PAGING?
	JRST	WRTSYM		;NO
	MOVE	T1,TAB.AB(P1)	;MAKE SURE UW.XX IS OK
	SUB	T1,TAB.LB(P1)	;MIGHT BE -1 IF LS AREA
	ADD	T1,TAB.LW(P1)	;NOW HAVE HIGHEST LOC IN CORE
	MOVEM	T1,TAB.UW(P1)	;UPDATE UW.XX
	SETCM	T1,TAB.LB(P1)	;ALSO MAKE SURE DISK FILE IS OK
	ADD	T1,TAB.PT(P1)	;IN CASE NEVER OUTPUT BEFORE
	JUMPE	T1,.+4		;FORGET IT IF NOTHING TO OUTPUT
	ADD	T1,TAB.LW(P1)	;NOTE WE'RE GETTING EXACT WORD CNT
	HRL	T1,TAB.LW(P1)	;ALGOL 7 NEEDS .RBSIZ EXACT
	PUSHJ	P,@TB.OUT##(P1)	;SO USE XX.PT INSTEAD OF XX.AB
	MOVE	T1,TAB.AB(P1)	;NOW READ IN FRONT OF FILE
	SUB	T1,TAB.LB(P1)	;SO CAN SET UP 10??,,COUNT
	SETZM	TAB.LW(P1)	;?W.?S MUST BE UP TO DATE
	MOVEM	T1,TAB.UW(P1)	;FOR FOLLOWING CALL
	PUSHJ	P,@TB.IN##(P1)	;AS FIRST WORD OF FILE
	CAIE	P1,AS.IX	;ALGOL?
	  JRST	SAVSY0		;NO, DO IT FOR LS AREA
	MOVE	T2,ASYM		;YES, GET SYMBOL COUNT
	HRLI	T2,1044		;AND BLOCK TYPE
	JRST	SAVSY1		;AND CONTINUE
SAVSY0:	MOVE	T2,LSYM		;COUNT FOR LS AREA
	HRLI	T2,1700		;AND BLOCK TYPE
SAVSY1:	SUBI	T2,1		;WORDS FOLLOWING IS 1 LESS
	MOVEM	T2,@TAB.LB(P1)	;STORE COUNT WORD
	PUSHJ	P,@TB.OUT##(P1)	;AND UPDATE FILE
	MOVEI	T1,SC		;FROM CHAN#
	CAIN	P1,AS.IX	;UNLESS AS AREA
	MOVEI	T1,AC		;IN WHICH CASE ALGOL CHANNEL
	MOVE	T2,IO.PTR+%SC	;TO CHANNEL
	PUSHJ	P,DVPRO.	;GET PROTECTION RIGHT
	MOVEI	T2,%SC		;TO CHAN#
	MOVE	T3,IO.PTR+%SC	;GET POINTER TO NEW FILE
	MOVE	T4,VERNUM	;GET VERSION OF PROGRAM
	SKIPN	I.VER(T3)	;UNLESS ALREADY SET BY SWITCH...
	MOVEM	T4,I.VER(T3)	;SAVE FOR ENTER
	PJRST	DVMOV.		;GO COPY PAGED FILE TO SYMBOL FILE
WRTSYM:	MOVEI	T1,DC		;USE THIS CHAN
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%SC	;HIDE DATA BLOCK HERE
	MOVEM	T1,IO.PTR+DC	;NOW BRING IT FORTH
	PUSHJ	P,DVCHN.##	;PUT ADDRESS OF BLOCK IN T1
	MOVSI	T2,(Z DC,)	;RESET CHAN # IN AC FIELD
	MOVEM	T2,I.CHN(T1)	;SINCE %SC IS THERE CURRENTLY
	CAIE	P1,AS.IX	;ALGOL?
	  JRST	WRTSY0		;NO, SETUP 1ST WORD FOR LS
	MOVE	T3,ASYM		;YES, SETUP COUNT WORD
	HRLI	T3,1044		;AND BLOCK TYPE
	JRST	WRTSY1		;CONTINUE
WRTSY0:	MOVE	T3,LSYM		;LS AREA COUNT
	HRLI	T3,1700		;BLOCK TYPE FOR TRIPLET SYMBOLS
WRTSY1:	HRRZ	T2,T3		;SAVE COUNT FOR ESTIMATE
	SUBI	T3,1		;WORDS FOLLOWING IS 1 LESS
	MOVEM	T3,@TAB.LB(P1)	;SAVE WORD COUNT IN AREA
	LSH	T2,-.DBS2W	;[650] INTO BLOCKS
	MOVEM	T2,I.EST(T1)	;WE NEED THIS MUCH
	MOVE	T2,VERNUM	;GET VERSION OF CORE IMAGE
	SKIPN	I.VER(T1)	;SKIP IF SET BY SWITCH
	MOVEM	T2,I.VER(T1)	;NO, SO SET IT
	PUSHJ	P,DVNAM.##	;MAKE SURE NAME IS SET UP
	PUSHJ	P,DVOPN.##	;INIT DEVICE
	PUSHJ	P,DVENT.##	;ENTER FILE
				;NOW FOR OUTPUT
WRTSY2:	MOVE	T1,TAB.LB(P1)	;GET BOTTOM ADDR IN CORE
	SUB	T1,TAB.PT(P1)	;-LENGTH
	HRLZ	T1,T1		;-LENGTH,,0
	HRR	T1,TAB.LB(P1)	;FIRST ADDR OF BUFFER
	HRRI	T1,-1(T1)	;-LENGTH,,ADDR-1
	SETZ	T2,
	OUT	DC,T1		;OUTPUT IT
	PJRST	DVRLS.##	;PAGING NO LONGER HANDLED HERE
	PUSH	P,[DC]
	.ERR.	(ST,,V%L,L%W,S%W,OES)
	POPJ	P,
SUBTTL	GENERATE .EXE (OR .XPN/.SHR/.HGH/.LOW) FILE
	
;SOME JOBDAT LOCATIONS WE NEED TO KNOW
.JBHSO==75		;PAGE # OF HIGH SEG ORIGIN
.JBSDD==114		;SAVED .JBDDT
.JBS41==122		;SAVED .JB41
	EXTERN	.JBREN
JOBHSA==0		;HIGH .JBSA
JOBH41==1		;HIGH .JB41
JOBHRN==3		;HIGH .JBHRL & .JBREN
JOBHSO==7		;PAGE # OF HIGH SEG ORIGIN IN HIGH

;HERE TO SETUP SAVED LOCATIONS
JBSAVE:	.ERR.	(MS,0,V%L,L%I,S%I,CSF,<Creating saved file>)
	SKIPE	PAG.S1		;PAGING?
	SKIPA	P1,JOBPTR	;YES
	MOVE	P1,LC.LB	;NO, USE INCORE ADDRESS
	SKIPE	PAG.S2		;PAGING HIGH SEG?
	SKIPA	P2,JBHPTR	;YES, LOAD CORRECT OFFSET
	MOVE	P2,HC.LB	;LOAD UP OFFSET
IFE FTEXE,<
	MOVE	T2,.JBDDT(P1)	;GET DDT  START
	MOVEM	T2,.JBSDD(P1)	;TO SAFE PLACE
	MOVE	T2,.JB41(P1)	;SAME FOR UUO HANDLER
	MOVEM	T2,.JBS41(P1)
>
	PUSHJ	P,JOBSET	;SETUP REST OF JOBDAT
	HLRZ	T1,.JBSA(P1)	;ALSO SETUP RIGHT HALF OF .JBCOR
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;SEEN ANY?
	SKIPN	JOB116		;YES, AND WANT SYMBOLS?
	CAIA			;NO
	HLRZ	T1,.JBCOR(P1)	;INCLUDE SYMBOLS
>
	IOR.	T1,.PGSIZ	;TO HIGHEST LOC REQUIRED
	HRRM	T1,.JBCOR(P1)	;SO SAVE GET WORKS
IFN FTEXE,<JRST	JBEXE>		;SET UP TO WRITE AN EXE FILE
IFE FTEXE,<
	SKIPN	HC.LB		;ANYTHING IN HIGH SEG?
	JRST	JBNOHI		;NO, JUST SAVE LOW SEG
	PUSHJ	P,HJBSET	;SETUP VESTIGIAL JOB DATA AREA (HIGH)
	SKIPN	PAG.S2		;PAGING HIGH SEG?
	JRST	JBSHGH		;NO, JUST SAVE IT
				;JUST WRITE OUT LAST PAGES
				;AND JBHDA (0-7 RELATIVE)
				;AND EITHER RENAME OR COPY FILE
				;TO RIGHT F/S
	HRLZ	T1,LW.S2	;LOWER WINDOW
	HRR	T1,UW.S2	;UPPER WINDOW
	PUSHJ	P,HC.OUT##	;OUTPUT LAST BLOCKS

	SETZM	LW.S2		;START BACK AT ZERO
	MOVEI	T1,.IPM		;READ IN FIRST
	PUSHJ	P,HC.IN##	;READ IT BACK
	PUSHJ	P,BLTJHA	;COPY FIRST 10 WORDS BACK
				;WE NOW HAVE A HIGH SEG FILE ON DSK
				;BUT IS IT THE RIGHT W/S
	MOVE	T2,IO.PTR+%VC	;[606] TO CHANNEL
	PUSHJ	P,DVPRO.	;[606] GET THE PROTECTION RIGHT
	MOVEI	T1,HC		;FROM HIGH CODE OVERFLOW
	MOVEI	T2,%VC		;TO SAVE FILE
	PUSHJ	P,DVMOV.	;RENAME OR COPY
	JRST	JBSHDL		;RENAMED, REMOVE HC AREA

;HERE IF NOT PAGING. WRITE OUT THE HIGH SEGMENT FILE.
JBSHGH:	MOVEI	R,2		;POINT TO HIGH SEGMENT
	PUSHJ	P,SAVINI	;OPEN SAVE FILE
JBSHG1:	MOVE	T1,HC.AB	;GET LENGTH OF HIGH CODE AREA
	SUB	T1,HC.LB
	SKIPN	PAG.S2		;PAGING (NOT ALL IN CORE)
	SKIPE	.JBDDT(P1)	;OR DDT LOADED?
	JRST	JBSHGN		;USE ALL OF AREA
	CAMLE	T1,HL.S2	;UNLESS SMALLER THAN HIGHEST LOC
	MOVE	T1,HL.S2	;USE HIGHEST LOC LOADED
JBSHGN:	MOVN	T1,T1		;IOWD IS NEG
	HRLZ	T1,T1		;IN LEFT HALF
	HRR	T1,HC.LB	;GET ADDRESS OF FIRST WORD
	HRRI	T1,-1(T1)	;-1
	SETZ	T2,		;TERMINATE LIST
	OUT	DC,T1		;DUMP CORE IMAGE AS IS
	  JRST	JBSHGR		;OK
	PUSH	P,[DC]
	.ERR.	(ST,,V%L,L%F,S%F,SOE,<SAVE file output error>)
JBSHGR:	MOVEI	T1,DC		;MAKE SURE CHAN# SETUP
	MOVEM	T1,IO.CHN
	PUSHJ	P,DVRLS.##	;RELEASE DEVICE


;HERE AFTER HI SEG SAVED. DELETE POSSIBLE .HGH/.SHR & .LOW FILES
JBSHDL:	MOVEI	T1,TC		;CHAN#
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%VC	;PSEUDO CHAN#
	MOVEM	T1,IO.PTR+TC	;INCASE OF ERROR
	PUSHJ	P,DVCHN.##	;T1 POINTS TO DATA BLOCK ON RETURN
	MOVSI	T2,(Z TC,)	;RESET CHAN # IN AC FIELD
	MOVEM	T2,I.CHN(T1)	;SINCE %VC IS THERE CURRENTLY
	SKIPE	T2,SSNAME	;GET REQUIRED NAME
	JRST	.+3		;USUALLY ITS GIVEN
	SKIPN	T2,RUNAME	;IF NOT TRY /RUNAME
	MOVE	T2,LODNAM	;DEFAULT AS LAST RESORT
	MOVEM	T2,I.NAM(T1)	;DELETE THIS FILE
	PUSH	P,T2		;SAVE NAME FOR .LOW
	HLLZ	T2,SSEXT	;GET EXT WE WANT
	TLC	T2,331732	;DELETE OTHER ONE
	MOVEM	T2,I.EXT(T1)
	PUSHJ	P,DVOPN.##	;OPEN DEVICE
	MOVEI	T1,TC		;SET CHAN#
	PUSHJ	P,DVDEL.##
	  JFCL
	PUSHJ	P,DVCHN.##
	POP	P,I.NAM(T1)	;RESTORE NAME
	PUSH	P,I.EXT(T1)	;[575] SAVE EXTENSION IN CASE /EXEC
	HRLZ	T2,SSEXT	;INCASE USER SUPPLIED EXT
	SKIPN	T2		;DELETE IT INCASE ONLY HIGH
	MOVSI	T2,'LOW'
	MOVEM	T2,I.EXT(T1)	;AND DELETE THIS ALSO
	PUSHJ	P,DVOPN.##	;OPEN CHAN AGAIN
	MOVEI	T1,TC		;SET CHAN#
	PUSHJ	P,DVDEL.##
	  JFCL
;FALL THROUGH TO NEXT PAGE
;HERE TO SETUP LOW SEG FILE SPEC
	PUSHJ	P,DVCHN.##	;[575] POINT BACK AT I/O DATA BLOCK
	POP	P,I.EXT(T1)	;[575] RESTORE EXTENSION IN CASE /EXEC
	HRLZ	T1,SSEXT	;INCASE USER SUPPLIED
	SKIPN	T1
	MOVSI	T1,'LOW'	;IF ANY LOW SEG STUFF
	MOVEM	T1,SSEXT	;EXT IS NOW LOW NOT SAV
	MOVEI	T1,HC.IX	;ALL DONE WITH HIGH SEG CODE AREA
	PUSHJ	P,XX.ZAP	;SO GET RID OF IT
	MOVE	T1,IO.PTR+DC	;BUT SAVE FILE SPEC
	MOVEM	T1,IO.PTR+HC	;IN CASE /EXEC
	JRST	JBSLOW		;NOW SAVE LOW SEG
JBNOHI:	HRLZ	T1,SSEXT	;INCASE USER SUPPLIED IT
	SKIPN	T1
IFE TOPS20,<
	MOVSI	T1,'SAV'	;EXT IS NOW SAV NOT LOW
>
IFN TOPS20,<
	MOVSI	T1,'EXE'	;EXT IS NOW EXE NOT LOW
>
	MOVEM	T1,SSEXT
				;FALL INTO JBSLOW
;JOBDAT IS NOW SETUP - IF PAGING WRITE OUT REST OF CORE IMAGE
;AND READ IN AS MUCH AS POSSIBLE FOR CORE COMPRESSOR
JBSLOW:	SKIPN	PAG.S1		;PAGING?
	JRST	JBSAV3		;NO, JUST OUTPUT CORE IMAGE
	HRLZ	T1,LW.S1	;GET LOWER WINDOW
	HRR	T1,UW.S1	;TO UPPER
	PUSHJ	P,LC.OUT##	;OUTPUT IT ALL
;NOW TO SEE IF WE CAN READ ALL OF CORE FILE BACK INTO CORE
; IF NOT READ IN AS MUCH AS POSSIBLE
	SETZM	LW.S1		;START AT LOWEST LOCATION
	MOVE	T1,DY.AB	;HIGHEST LOC WE CAN NOT USE
	MOVEM	T1,DY.UB	;TELL LNKCOR ABOUT IT
	ADDI	T1,1
	MOVEM	T1,LC.LB	;BACKUP IF WE CAN
	SKIPN	T1,LS.LB	;CAN ONLY USE TO BOTTOM OF LS
				;AREA IF IT'S STILL THERE
	SKIPA	T1,.JBREL	;IF IT'S NOT, CAN USE ALL OF CORE
	SUBI	T1,1		;LAST TO USE IS START OF LS - 1
	MOVEM	T1,LC.UB	;RESET POINTERS
	MOVEM	T1,LC.AB	;FOR CONSISTENCY
	SUB	T1,LC.LB	;MINUS WHAT WE ALREADY HAVE
	MOVEM	T1,UW.S1	;ASSUME IT WON'T FIT
	CAMGE	T1,HC.S1	;ENOUGH EXTRA FOR ALL OF FILE?
	JRST	JBSAV1		;NO, DO IT THE HARD WAY
	MOVE	T1,HC.S1	;WE NEED ONLY THIS MUCH
	IORI	T1,.IPM		;ROUNDED UP
	MOVE	T2,T1		;CAN ALSO CUT BACK LC.AB
	ADD	T2,LC.LB	;TO WHAT WE ACTUALLY NEED
	MOVEM	T2,LC.AB	;TO SAVE TIME
	PUSHJ	P,LC.IN##	;READ WHAT WE CAN
	PUSHJ	P,LC.DLT	;DELETE LC FILE UNLESS .XPN WANTED
	JRST	JBSAV2		;AND COPY 0-137 BACK INTO CORE

JBSAV1:	PUSHJ	P,LC.IN##	;READ BACK AS MUCH CORE AS WE CAN
JBSAV2:	PUSHJ	P,BLTJDA	;BLT .JBDA TO LOW SEG
JBSAV3:	MOVE	T1,LC.LB	;JOBDAT NOW SETUP IN CORE
	SKIPN	.JBDDT(T1)	;ALWAYS SAVE IF DDT LOADED
	SKIPN	HC.S2		;ANY HIGH SEG (HC.LB IS ZERO BY NOW)
	JRST	JBSAV4		;NO, SO MUST WANT LOW SEG
	MOVE	T1,HC.S1	;YES, SEE IF LOW SEG CONTAINS DATA
	CAIG	T1,.JBDA	;IF .JBCOR GREATER THAN 137
	JRST	ENDSAV		;NO, SO NO LOW SEG FILE
JBSAV4:	MOVEI	R,1		;POINT TO LOW SEGMENT
	PUSHJ	P,SAVINI	;INIT/ENTER SAV FILE
	SKIPE	IO.PTR+%XC	;WANT .XPN FILE?
	SKIPE	IO.PTR+LC	;BUT NOT PAGING
	JRST	ZCMPRS		;NO, NOW FOR ZERO COMPRESSOR
	PUSHJ	P,WRTXPN	;WRITE IT OUT
	JRST	ZCMPRS		;AND COMPRESS CORE IMAGE

> ;END OF IFE FTEXE
;HERE TO SETUP REST OF JOBDAT AREA
;ENTER WITH  P1 POINTING TO JOBDAT AREA
;AND P2 TO HIGH DATA AREA (0 IF NO HIGH SEG)

JOBSET:	SKIPE	T2,HC.S1	;GET HIGHEST DATA LOCATION LOADED
	SUBI	T2,1		;MAKE IT HIGHEST LOC LOADED
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;LOADED ANY OVERLAYS?
	SKIPN	T1,JOB116	;AND SAVED SYMBOLS?
	JRST	.+4		;NO
	HLRE	T2,T1		;-LENGTH
	MOVM	T2,T2
	ADDI	T2,-1(T1)	;HIGHEST LOCATION
>
	HRLZM	T2,.JBCOR(P1)	;PUT  HIGHEST LOC IN LEFT HALF
	HRRZ	T2,HL.S1	;GET HIGHEST LOC REQUIRED
	HRL	T2,STADDR	;GET STARTING ADDRESS
	MOVSM	T2,.JBSA(P1)	;SET .JBSA AND .JBFF
	HRRZM	T2,.JBFF(P1)	;INCASE RESET NOT DONE FIRST
	IOR.	T2,.PGSIZ	;INCLUDE ALL OF THIS PAGE
	HRRZM	T2,.JBREL(P1)	;SET .JBREL
	MOVSI	T2,(HALT)	;PUT A HALT IN .JB41
	SKIPN	.JB41(P1)	;UNLESS ALREADY SETUP
	MOVEM	T2,.JB41(P1)
	MOVE	T2,.JBSYM(P1)	;GET SYMBOL TABLE POINTER
	HRRZ	T1,T2		;GET POINTER
	JUMPE	P2,JOBST0	;NO HIGH SEG POSSIBLE
	CAML	T1,LL.S2	;SEE IF IN HIGH SEG
	MOVEM	T2,.JBHSM(P2)	;STORE IN HIGH SEG DATA AREA
	SKIPE	T1,HL.S2	;GET HIGHEST LOC +1
	SUBI	T1,1		;HIGHEST LEGAL ADDRESS
	ADD	T1,LL.S2	;PLUS ORIGIN
	IOR.	T1,.PGSIZ	;PUT ON PAGE BOUND
	SKIPN	T2,HL.S2	;[650] LENGTH TO SAVE
	JRST	JOBST1		;[650] NONE?
	SKIPN	.JBDDT##(P1)	;[650] DDT LOADED?
	JRST	JOBST1		;[650] NO, NUMBER IS OK
	SUBI	T2,1		;[650] YES, BE LIKE MONITOR
	IOR.	T2,.PGSIZ	;[650] ROUND UP TO TOP OF PAGE
	ADDI	T2,1		;[650] THENCE TO BOTTOM OF NEXT
JOBST1:	HRL	T1,T2		;[650] LENGTH TO SAVE,,HIGHEST ADDR
	MOVEM	T1,.JBHRL(P1)	;LENGTH,,HIGHEST ADDRESS
JOBST0:	MOVE	T1,.JBERR	;GET  NO OF PREVIOUS ERRORS
	MOVEM	T1,.JBERR(P1)	;COUNT AS EXECUTION ERRORS
	MOVEM	T1,ERRNO	;PROHIBIT EXECUTION IF NON-ZERO
				;NOW SETUP STARTING ADDRESS FOR EXECUTION
	SETZ	T1,		;INITIALLY ZERO
	SKIPE	EXECSW		;GO INTO EXECUTION?
	MOVE	T1,STADDR	;YES, ASSUME .JBSA
	SKIPGE	DEBUGSW		;UNLESS DEBUG
	MOVE	T1,.JBDDT(P1)	;INWHICH CASE ASSUME DDT SETUP
	HRRM	T1,EXECSW	;IN ANY CASE STORE BACK IN EXECSW
	POPJ	P,
;HERE TO SETUP REST OF VESTIGIAL JOBDAT AREA
;ENTER WITH  P1 POINTING TO JOBDAT AREA

HJBSET:	JUMPE	P2,CPOPJ	;DON'T NEED TO DO THIS IF NO HIGH SEG
	HRRZ	T1,HL.S2	;GET HIGHEST HIGH SEG LOCATION+1
	SKIPE	.JBDDT(P1)	;IF DDT LOADED
	SOJA	T1,[IOR. T1,.PGSIZ	;INCLUDE ALL OF THIS PAGE
		AOJA	T1,.+1]		;IN LENGTH
	HRL	T1,.JBREN(P1)	;GET .JBREN
	MOVSM	T1,JOBHRN(P2)	;SET BOTH HALVES OF JOBHRN
	MOVE	T1,.JBSA(P1)	;PUT .JBSA
	MOVEM	T1,JOBHSA(P2)	;IN HIGH SEG
	MOVE	T1,.JB41(P1)
	MOVEM	T1,JOBH41(P2)
	MOVS	T1,.JBCOR(P1)
	SKIPN	.JBDDT(P1)	;TEST FOR RARE CASE OF DDT, SYMBOLS AND CODE
	JRST	.+3		; ALL IN HIGH SEGMENT
	TRNN	T1,-140		;TRUE IF HIGHEST LOC IS 137 OR LESS
	ADDI	T1,1		;IF SO MAKE IT 140 IN HIGH SEG
	MOVSM	T1,.JBHCR(P2)	; SO WE LOAD LOW
	MOVE	T1,.JBVER(P1)
	MOVEM	T1,.JBHVR(P2)
	SKIPE	T1,RUNAME	;GET PROGNAM
	JRST	.+3		;SET
	SKIPN	T1,SSNAME	;IF NOT TRY SAVE FILE NAME
	MOVE	T1,LODNAM	;USE DEFAULT IF NOT SET
	MOVEM	T1,.JBHNM(P2)	;INTO HIGH SEG
	MOVE	T1,HL.S1	;HIGHEST LOC +1 IN LOW SEG
	SUBI	T1,1
	IOR.	T1,.PGSIZ	;ROUND UP TO PAGE BOUNDARY
	ADDI	T1,1		;NEXT PAGE
	CAMGE	T1,LL.S2	;GREATER THAN HI-ORG?
	MOVE	T1,LL.S2	;NO
	LSH	T1,-9		;PAGE #
	HRLZM	T1,JOBHSO(P2)	;STORE IN HIGH
	HRRZM	T1,.JBHSO(P1)	;AND STORE
	POPJ	P,
;HERE TO DELETE LC FILE
;CALLED BY
;	PUSHJ	P,LC.DLT
;USES T1

LC.DLT:	SETZM	PAG.S1		;NOT PAGING NOW
	SKIPE	IO.PTR+%XC	;WANT .XPN FILE?
	POPJ	P,		;YES, LEAVE OVERFLOW FILE 
	MOVEI	T1,LC
	PUSHJ	P,DVDEL.##	;DELETE FILE
	  JFCL			;TOO BAD
	POPJ	P,

;HERE TO DELETE HC FILE

HC.DLT:	SETZM	PAG.S2
	MOVEI	T1,HC
	PUSHJ	P,DVDEL.##
	  JFCL
	POPJ	P,

IFN FTOVERLAY,<
;HERE TO DELETE LS FILE
LS.DLT:	SETZM PAG.LS
	MOVEI	T1,SC
	PUSHJ	P,DVDEL.##
	  JFCL
	POPJ	P,
>
BLTJDA:	MOVS	T1,JOBPTR	;FORM BLT POINTER
	HRR	T1,LC.LB	;TO MOVE MODIFIED JOBDAT AREA
	HRRZI	T2,.JBDA-1(T1)	;BACK INTO FRONT OF CORE
	BLT	T1,(T2)
	MOVE	T1,JOBPTR	;GIVE AREA BACK
	MOVEI	T2,.JBDA
	PUSHJ	P,DY.RET
	SETZM	JOBPTR		;AND FORGET ABOUT AREA
	SKIPN	IO.PTR+%XC	;IF WE WANT .XPN FILE
	POPJ	P,		;NO
	MOVEI	T1,.DBM		;YES
	PJRST	LC.OUT##	;WRITE OUT JOBDATA AREA  AGAIN

;NOW READ BACK FIRST 10 WORDS (.JBHDA)
BLTJHA:	MOVS	T1,JBHPTR	;FORM BLT POINTER
	HRR	T1,HC.LB	;TO MOVE MODIFIED JOBDAT AREA
	HRRZI	T2,.JBHDA-1(T1)	;BACK INTO FRONT OF CORE
	BLT	T1,(T2)
	MOVE	T1,JBHPTR	;GIVE AREA BACK
	MOVEI	T2,.JBHDA
	PUSHJ	P,DY.RET##
	SETZM	JBHPTR		;AND FORGET ABOUT AREA
	MOVEI	T1,.DBM		;NOW WRITE IT BACK
	PJRST	HC.OUT##	;WRITE IT BACK
				;BUT IS IT THE RIGHT F/S
IFE FTEXE,<

;HERE TO OPEN SAVE FILE (USING DC)
;ENTER WITH :-
;R = 1 (LOW) OR 2 (HIGH)

SAVINI:	MOVEI	T1,DC		;CHAN#
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%VC	;PSEUDO CHAN#
	MOVEM	T1,IO.PTR+DC	;INCASE OF ERROR
	PUSHJ	P,DVCHN.##	;T1 POINTS TO DATA BLOCK ON RETURN
	MOVSI	T2,(Z DC,)	;RESET CHAN # IN AC FIELD
	MOVEM	T2,I.CHN(T1)	;SINCE %VC IS THERE CURRENTLY
	SKIPE	T2,SSNAME	;GET REQUIRED NAME
	JRST	.+3		;USUALLY ITS GIVEN
	SKIPN	T2,RUNAME	;IF NOT TRY /RUNAME
	MOVE	T2,LODNAM	;DEFAULT AS LAST RESORT
	MOVEM	T2,I.NAM(T1)	;SAVE IT
	HLLZ	T2,SSEXT	;EXT IS EITHER SAV OR LOW
	MOVEM	T2,I.EXT(T1)
	MOVX	T2,RB.PRV	;[606] PRESERVE PROTECTION
	ANDM	T2,I.PRV(T1)	;[606] MAKE CREATION DATE TODAY
	MOVE	T2,HC.S0(R)	;GET HIGHEST LOC TO SAVE
	LSH	T2,-.DBS2W	;[650] INTO BLOCKS
	ADDI	T2,3		;1 FOR REMAINDER, 2 FOR RIBS
	MOVEM	T2,I.EST(T1)	;AT LEAST THIS IS ENOUGH
	MOVE	T2,VERNUM	;GET VERSION OF CORE IMAGE
	SKIPN	I.VER(T1)	;SKIP IF SET BY SWITCH
	MOVEM	T2,I.VER(T1)	;NO, SO SET IT
	PUSHJ	P,DVOPN.##	;OPEN DEVICE
	PUSHJ	P,DVNAM.##	;MAKE SURE WE HAVE A NAME
	PJRST	DVENT.##	;ENTER FILE NAME
>;END OF IFE FTEXE

;HERE TO OPEN XPN FILE (IF NOT PAGING) USING LC

XPNINI:	MOVEI	T1,LC		;CHAN#
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%XC	;PSEUDO CHAN#
	MOVEM	T1,IO.PTR+LC	;INCASE OF ERROR
	SETZM	IO.PTR+%XC	;DONE WITH .XPN CHAN NOW
	PUSHJ	P,DVCHN.##	;T1 POINTS TO DATA BLOCK ON RETURN
	MOVSI	T2,(Z LC,)	;RESET CHAN # IN AC FIELD
	MOVEM	T2,I.CHN(T1)	;SINCE %VC IS THERE CURRENTLY
	MOVE	T2,HC.S1	;GET HIGHEST LOC TO SAVE
	LSH	T2,-.DBS2W	;[650] INTO BLOCKS
	ADDI	T2,3		;1 FOR REMAINDER, 2 FOR RIBS
	MOVEM	T2,I.EST(T1)	;AT LEAST THIS IS ENOUGH
	MOVE	T2,VERNUM	;GET VERSION OF CORE IMAGE
	SKIPN	I.VER(T1)	;SKIP IF SET BY SWITCH
	MOVEM	T2,I.VER(T1)	;NO, SO SET IT
	PUSHJ	P,DVOPN.##	;OPEN DEVICE
	PUSHJ	P,DVNAM.##	;MAKE SURE FILE NAME SETUP
	PJRST	DVENT.##	;ENTER FILE NAME


;HERE TO WRITE OUT .XPN FILE IF NOT PAGING
;NOTE, MUST BE DONE BEFORE ZERO COMPRESSION

WRTXPN:	PUSHJ	P,XPNINI	;OPEN/ENTER FILE
	MOVE	T1,HC.S1	;HIGHEST LOC TO OUTPUT
	MOVN	T1,T1		;-LENGTH
	HRLZ	T1,T1		;IN LEFT HALF
	HRR	T1,LC.LB	;FORM IOWD
	HRRI	T1,-1(T1)	;ALMOST
	SETZ	T2,		;END WORD
	OUT	LC,T1		;DUMP OUTPUT
	  CAIA			;OK
	PUSHJ	P,XPNERR
	PUSHJ	P,DVRLS.##	;RELEASE DEV
	PJRST	DVZAP.##	;FORGET ABOUT .XPN FILE NOW

XPNERR:	PUSH	P,[LC]
	.ERR.	(ST,,V%L,L%W,S%W,OEX,<Output error on XPN file, file closed, job continuing>)
	POPJ	P,
IFN FTEXE,<

;HERE FOR EXECUTABLE FILE
;THE ACTIONS IS
;RESERVE SPACE FOR DIRECTORY (1 PAGE)
;WRITE OUT LOW SEGMENT REMOVING ALL ZERO BUT ALLOCATED PAGES
;THEN WRITE OUT THE HIGH SEGMENT THE SAME WAY
;NOW GO BACK AND WRITE THE DIRECTORY
;NOTE, PAGE 0 AND FIRST PAGE OF HIGH SEGMENT ARE ALWAYS WRITTEN

JBEXE:	SKIPN	HC.LB		;ANY HIGH SEGMENT?
	JRST	JBEXEN		;NO,
	SKIPN	T1,UW.S2	;IS IT PAGED?
	JRST	JBEXEH		;NO,
	HRL	T1,LW.S2	;OUTPUT WORD
	PUSHJ	P,HC.OUT	;MAKE SURE IT GET OUT
	MOVE	T1,UW.S2
	SUB	T1,LW.S2	;GET LENGTH
	MOVEM	T1,UW.S2	;RESET IT
	SETZM	LW.S2		;BACK TO FRONT OF FILE
	PUSHJ	P,HC.IN		;READ IT BACK
JBEXEH:	PUSHJ	P,HJBSET	;YES, SETUP VESTIGIAL JOBDAT
	SKIPE	JBHPTR		;WAT IT PAGED?
	PUSHJ	P,BLTJHA	;YES, READ IT BACK NOW
JBEXEN:	MOVEI	T2,1000		;NEED SPACE FOR DIRECTORY
	PUSHJ	P,DY.GET##	;GO GET IT
	DMOVEM	T1,EXEDIR	;SAVE BASE
	SKIPN	PAG.S1		;READY TO DUMP CORE, FIRST SEE IF PAGED?
	JRST	EXEINI		;NO, GO OPEN EXE FILE AND DUMP
;YES, IT'S PAGED.   IF NEEDED, FIRST OUTPUT ALL, THEN TRY READ BACK ALL
;OF CORE FILE BACK INTO CORE (OR AS MUCH AS POSSIBLE).
	SKIPE	T1,LOWLOC	;[732] LOWEST LOCATION IN PAGE0?
	JRST	[CAMGE	T1,LW.S1	;[732] NO, OUT ON DISK?
		JRST	.+1		;[732] YES, GO DO OUTPUT & READ
		MOVEM	T1,LW.S1	;[732] NO, START AT LOWEST LOC
		JRST	JBEXE1]		;[732]
	HRLZ	T1,LW.S1	;GET LOWER WINDOW
	HRR	T1,UW.S1	;TO UPPER
	PUSHJ	P,LC.OUT##	;OUTPUT IT ALL
	MOVE	T1,LOWLOC	;[762] GET LOWLOC PAGES INTO THE WINDOW
	MOVEM	T1,LW.S1	;[762]
	MOVE	T1,DY.AB	;HIGHEST LOC WE CAN NOT USE
	MOVEM	T1,DY.UB	;TELL LNKCOR ABOUT IT
	ADDI	T1,1		;
	MOVEM	T1,LC.LB	;BACKUP IF WE CAN
	SKIPN	HC.S2		;HOW ABOUT HIGH SEGMENT?
	JRST	JBEXEA		;NO HIGH SEG, JUMP
	MOVE	T1,HC.LB	;YES, HIGH SEG STILL EXISTS
	SUBI	T1,1		;TOP OF LOW
	MOVEM	T1,LC.UB	;RESTORE POINTERS
	JRST	JBEXER		;GO MAKE PAGE BOUND AND CHECK ROOM

JBEXEA:	SKIPN	T1,LS.LB	;TO BOTTOM OF LS, IF IT'S THERE
	SKIPA	T1,.JBREL	;IF NOT, ALL OF CORE
	SUBI	T1,1
	MOVEM	T1,LC.UB	;RESER
JBEXER:	SUB	T1,LC.LB	;MAKE SURE
	SUBI	T1,777		;WE ARE ON A PAGE BOUND
	IORI	T1,777		;...
	ADD	T1,LC.LB	;ADD IN BASE
	MOVEM	T1,LC.AB	;FOR CONSISTANCY
	SUB	T1,LC.LB	;MINUS WHAT WE ALREADY HAVE
	MOVE	T3,HC.S1	;[762] 
	SUB 	T3,LOWLOC	;[762] GET ACTUALLY NEEDED LENGTH
	IORI	T3,777		;[762]
	CAMGE	T1,T3		;[762] COMPARE WHAT WE HAVE AND WHAT WE NEED
	JRST	[ADD	T1,LW.S1	;[762] WE HAVE LESS THAN WE NEED
		MOVEM	T1,UW.S1	;[762] UPDATE UPPER WINDOW VALUE
		HRL	T1,LW.S1	;[762]
		PUSHJ	P,LC.IN		;READ IN AS MUCH AS WE CAN
		JRST	JBEXE1]
	MOVE	T1,T3		;[762] WE HAVE MORE THAN WE NEED
	ADD	T1,LW.S1	;[762] UPDATE UPPER WINDOW VALUE
	MOVEM	T1,UW.S1	;[762]
	HRL	T1,LW.S1	;[762]
	ADD	T3,LC.LB	;[762] CAN CUT BACK LC.AB TO WHAT WE NEED
	MOVEM	T3,LC.AB	;TO SAVE TIME
	PUSHJ	P,LC.IN##	;READ WHAT WE CAN
	PUSHJ	P,LC.DLT	;DELETE FILE UNLESS .XPN WANTED
JBEXE1:	SKIPN	LW.LC		;[742] WE HAVE PAGE 0 IN CORE?
	PUSHJ	P,BLTJDA	;BLT .JBDA TO LOW SEG

;	JRST	EXEINI
;HERE TO OPEN EXE FILE

EXEINI:	MOVEI	T1,DC		;CHAN#
	MOVEM	T1,IO.CHN
	MOVE	T1,IO.PTR+%VC	;PSEUDO CHAN#
	MOVEM	T1,IO.PTR+DC	;INCASE OF ERROR
	PUSHJ	P,DVCHN.##	;T1 POINTS TO DATA BLOCK ON RETURN
	MOVSI	T2,(Z DC,)	;RESET CHAN # IN AC FIELD
	MOVEM	T2,I.CHN(T1)	;SINCE %VC IS THERE CURRENTLY
	SKIPE	T2,SSNAME	;GET REQUIRED NAME
	JRST	.+3		;USUALLY ITS GIVEN
	SKIPN	T2,RUNAME	;IF NOT TRY /RUNAME
	MOVE	T2,LODNAM	;DEFAULT AS LAST RESORT
	MOVEM	T2,I.NAM(T1)	;SAVE IT
	MOVE	T2,SSEXT	;GET EXT AND FLAGS
	HLLZM	T2,I.EXT(T1)	;STORE EXT
	SETZM	I.PRV(T1)	;MAKE THE CREATION DATE TODAY
	MOVE	T2,HC.S1	;[744] GET HIGHEST LOW CORE TO SAVE
	ADD	T2,HC.S2	;[744] PLUS THE HIGH CORE TO SAVE
	LSH	T2,-7		;INTO BLOCKS
	ADDI	T2,4		;[744] 1 FOR REMAINDER, 1 FOR EXE-DIR, 2 FOR RIBS
	MOVEM	T2,I.EST(T1)	;AT LEAST THIS IS ENOUGH
	MOVE	T2,VERNUM	;GET VERSION OF CORE IMAGE
	SKIPN	I.VER(T1)	;SKIP IF SET BY SWITCH
	MOVEM	T2,I.VER(T1)	;NO, SO SET IT
	PUSHJ	P,DVOPN.##	;OPEN DEVICE
	PUSHJ	P,DVNAM.##	;MAKE SURE WE HAVE A NAME
	MOVE	T1,IO.CHN	;YES, NEED UPDATE MODE
	PUSHJ	P,DVUPD.##	;INCASE LARGE DIRECTORY
	JRST	[PUSH	P,[DC]		;FATAL CHAN
		.ERR.	(LRE,0,V%L,L%F,S%F,ECE,<Error creating EXE file - >)]
	SKIPE	IO.PTR+%XC	;WANT .XPN FILE?
	SKIPE	IO.PTR+LC	;BUT NOT PAGING
	JRST	XCMPRS		;GO WRITE OUT EXE
	PUSHJ	P,WRTXPN	;WRITE OUT XPN
;	JRST	XCMPRS

;here to compress out pages containing all zeros
;uses acc as follows
;t1	iowd -1000,address
;t2	0 (terminator)
;p1	flags,,file page
;p2	repeat count,,process page
;p3	process address
;P4	FLAGS TO DETERMINE WHAT TO DO WITH THE DIRECTORY ENTRY:
;		ZEROF==400000
;		DATAF==200000
;		GAPF==100000
;	
;		ZEROF TO ZEROF :	BUMP REPEAT COUNT
;		ZEROF TO DATAF :	WRITE OUT CURRENT DIR; START NEW DIR
;		ZEROF TO GAPF :		WRITE OUT DURRENT DIR
;		DATAF TO ZEROF:		WRITE OUT CURRENT DIR; START NEW DIR
;		DATAF TO DATAF:		BUMP REPEAT COUNT
;		DATAF TO GAPF:		WRITE OUT CURRENT DIR
;		GAPF TO ZEROF/DATAF:	IGNORE CURRENT ENTRY; START NEW DIR
;		GAPF TO GAPF:		IGNORE
;r	index to segment either 1 or 2
;w1	store ptr

ZEROF==400000			;[704]
DATAF==200000			;[704]
GAPF==100000			;[704]

XCMPRS:	SETZM	RC.CUR		;[704] INITIALIZE CURRENT PSECT INDEX
	MOVEI	R,1		;MAKE SURE LOW SEGMENT
	MOVEM	R,EXEBLK	;CONVENIENT 1
	USETO	DC,5		;BYPASS DIRECTORY
	MOVE	P1,[SV%WRT+1]	;FLAGS AND FILE PAGE FOR PAGE 0
	SETZB	P2,P3		;CLEAR PROCESS PAGE #
	SETZB	P4,T2		;
	MOVSI	W1,-1000	;- LENGTH
	HRR	W1,EXEDIR	;AOBJN PTR
	MOVE	T3,LOWLOC	;[742] GET LOWEST LOCATION
	CAIL	T3,2000		;[742] LOWEST LOCATION IN PAGE0 OR PAGE 1?
	JRST	XCMPRJ		;[742] NO, 
	MOVE	T1,LC.LB	;[742] YES,
	SUBI	T1,1		;[742]
	JRST	XCMPRL		;[742]

;HERE IF THE LOWEST LOCATION IS IN PAGE 2 OR HIGHER.
;MUST OUTPUT JOBDAT FIRST, THEN CHECK TO SEE IF PAGE0 AND PAGE 1
;IS PART OF .LOW.  IF THAT IS THE CASE, OUTPUT A DIRECTORY ENTRY
;TO MAKE THOSE PAGES ALLOCATED.

XCMPRJ:	HRR	T1,JOBPTR	;[732] OUTPUT JOBDAT DIRECTLY
	SUBI	T1,1		;[732]
	HRLI	T1,-.JBDA+1	;[732]
	OUT	DC,T1		;OUTPUT PAGE 0
	  TLOA	P4,GAPF		;[732] FLAG IT GAP, OUTPUT DIR  HERE
	JRST	XCMPER		;ERROR
	USETO	DC,9		;WRITE REST OF PAGE AS 0
	DMOVEM	P1,1(W1)	;STORE ENTRIES
	HRRI	P1,2		;NEXT FREE FILE PAGE
	AOBJN	W1,.+1		;
	AOBJN	W1,.+1		;[732] ADJUST DIR PTR BY 2 ALSO
	MOVE	T3,HC.S1	;[732] NO CODE IN PAGE0, BUT ANY CODE AT ALL?
	CAIG	T3,.JBDA	;[732]
	JRST	XCMPR8		;[732] NO, NOW FOR HIGH SEG
	MOVE	T2,@RC.TB	;[742] YES, 
	MOVE	T2,RC.CV(T2)	;[742] PAGE 0 AND PAGE 1 IN .LOW.?
	CAILE	T2,.JBDA	;[742]
	JRST	[PUSHJ	P,XCMPXD	;[742] YES, NEED TO MAKE AN ENTRY
		HLLZM	P1,(W1)		;[742] IN EXE DIRECTORY
		PUSHJ	P,XCMPXD	;[742]
		HRLZ	T2,LOWLOC	;[742] ALLOCATE ALL PAGES UP TO
		TLZ	T2,2777		;[742] THAT PAGE THAT CONATAINS LOWLOC
		ADDI	T2,1		;[742] BUMP PROCESS PAGE
		MOVEM	T2,(W1)		;[742]
		JRST 	.+1]		;[742]
	MOVE	P3,LOWLOC	;[732] YES, GET LOWEST LOCATION
	MOVE	P2,P3		;[732] ALSO UPDATE PROCESS PAGE
	LSH	P2,-^D9		;[732]
	HRR	T1,LC.LB	;[742] NOW, READY TO DUMP THE ACTUAL CORE
	SUBI	T1,1		;[742]
	HRLI	T1,-1000	;[732] ASSUME AT LEAST A PAGE
	JRST	XCMPR4		;[732] AND THAT CORE IS ALREADY SETUP

XCMPRL:	HRLI	T1,-1000	;SET UP IOWD WORD
XCMPR7:	SETZ	T2,		;MAKE SURE TERMINATOR IS 0
	OUT	DC,T1		;ALWAYS OUTPUT PAGES 0 & 400
	  TLOA	P4,DATAF	;[704] JUST OUTPUT A DATA PAGE
	JRST	XCMPER		;ERROR
XCMPR0:	ADDI	T1,1000		;NEXT PAGE
	ADDI	P3,1000		;INCREMENT PROCESS ADDRES
	CAILE	P3,777777	;[732] OVERFLOWED INTO LH?
	JRST	[PUSHJ	P,XCMPRD	;[732] YES, WRITE DIR ENTRY OUT
		JRST	XCMPRH]	;[732] TRY HIGH SEG
XCMPR4:	PUSHJ	P,INGAP		;[732] CHECK TO SEE IF IN PSECT GAP
	  JRST XCMPR0		;[704] YES, SKIP OVER THIS PAGE
	MOVEI	T3,1(T1)	;ADDRESS ONLY
	CAMG	T3,TAB.AB(R)	;NEXT PAGE IN CORE
	JRST	XCMPR1		;YES
	CAMLE	P3,HC.S0(R)	;FINISHED?
	JRST	[PUSHJ	P,XCMPRD	;NO, WRITE IT OUT
		JRST	XCMPRH]		;TRY HIGH SEG
	MOVE	T3,TAB.AB(R)	;
	SUB	T3,TAB.LB(R)	;GET SIZE
	ADDI	T3,1		;
	MOVEM	P3,LW.S0(R)	;[713] RESET BASE TO PROCESS PAGE
	ADD	T3,LW.S0(R)	;[764] GET NEW UPPER WINDOW
	CAILE	T3,-1		;[764] MAKE SURE IT DOESN'T OVERFLOW
	MOVEI	T3,-1		;[764] JUST IN CASE
	MOVEM	T3,UW.S0(R)	;[763]
	CAMLE	T3,HC.S0(R)	;STILL IN RANGE?
	JRST	[MOVE	T3,HC.S0(R)	;NO
		IORI	T3,.IPM		;GET PAGE LIMIT
		MOVEM	T3,UW.S0(R)	;SET NEW
		SUB	T3,LW.S0(R)	;GET LENGTH
		ADD	T3,TAB.LB(R)	;
		MOVEM	T3,TAB.AB(R)	;RESET TOP
		JRST	.+1]		;
	HRLZ	T1,LW.S0(R)	;LOWER BOUND
	HRR	T1,UW.S0(R)	;TO UPPER BOUND
	PUSHJ	P,@[EXP LC.IN##,HC.IN]-1(R)	;READ IN NEW PAGE
	MOVE	T3,TAB.LB(R)	;RESET INCORE PROCESS ADDRESS
	MOVEI	T1,-1(T3)	;RESET IOWD ADDRESS
	HRLI	T1,-1000	;AND COUNT
XCMPR1:	MOVEI	T4,(P3)		;[732] MUST USED 2 INSTRS TO DO THIS
	ADDI	T4,1000		;[732] INCASE OVERFLOW INTO LH
	CAMLE	T4,HC.S0(R)	;WHOLE PAGE EXITS?
	JRST	[MOVE T4,HC.S0(R)
		SUBI	T4,(P3)
		MOVN	T4,T4
		HRL	T3,T4
		HRL	T1,T4
		JRST .+2]
	HRLI	T3,-1000	;NORMAL AOBJN WORD
	SKIPE	(T3)		;LOOK FOR A NON-ZERO
	JRST	XCMPR3		;FOUND ONE
	AOBJN	T3,.-2		;LOOP FOR ALL OF PAGE
	TLNE	P4,ZEROF	;[704] GOT A ZERO PAGE, WAS LAST ONE ALSO ZERO?
	JRST	XCMPR2		;[704] LAST ONE WAS ALSO ZERO
	TLNN	P4,DATAF	;[704] NO, WAS LAST ONE DATA?
	TLNA	P4,GAPF		;[704] NO, MUST HAVE BEEN GAP, SO SKIP
	PUSHJ	P,XCMPRD	;[704] YES,IT WAS DATA, GO OUTPUT CURRET DIR
	TLO	P4,ZEROF	;[704] SET ZEROF
	TLZ	P4,DATAF+GAPF	;[704] AND OFF WITH OTHERS
	JRST	XCMPR0		;LOOP AGAIN


;[704] HERE TO SEE OF NEXT PAGE(CORE ADDR IN P3) FALLS IN
;A PSECT GAP.  RETURN IF IN GAP.  SKIP RETURN IF NOT IN A GAP.

INGAP:	CAILE	R,1		;[713] DOING LOW SEG OR ABS?
	JRST	CPOPJ1		;[704] NO, DON'T BOTHER, SKIP RETURN
	CAMLE	P3,HC.S1	;[724] EXCEEDED ADDR SPACE?
	JRST	CPOPJ1		;[724] YES,
	PUSH	P,R		;[704] USES ACS R, T1, AND T2
	PUSH	P,T1		;[704]
	MOVE	R,RC.CUR	;[704] GET CURRENT PSECT
INGAP1:	MOVE	T1,@RC.TB	;[704] GET RELOC TABLE ADDR FOR CURRENT PSECT
	MOVE	T2,RC.SG(T1)	;[704] SET SEGMENT NO.
	CAILE	T2,1		;[713] LOW SEG?
	JRST	INGAP5		;[724] NO, FORGET IT
	MOVE	T2,RC.CV(T1)	;[704] GET CURRENT PSECT BREAK
	TRO	T2,777		;[704] ROUND UP PSECT BREAK
	CAIG	P3,(T2)		;[704] ADDR LARGER THAN THE PSECT BREAK?
	JRST	[MOVE	T2,RC.IV(T1)	;[704] MAKE SURE IT IN PSECT RANGE
		TRZ	T2,777		;[704] ROUND DOWN
		CAIGE	P3,(T2)		;[704] IN RANGE?
		JRST	INGAP3		;[704] NO, IN GAP
		JRST	INGAP5]		;[724] YES, DO SKIP RETURN
	ADDI	R,1		;[704] ADDR IS GT CURRENT PSECT
	CAMLE	R,RC.NO		;[704] IS THERE A NEXT PSECT?
	JRST	INGAP5		;[724] NO, SKIP RETURN
	MOVE	T1,@RC.TB	;[704] GET ADDR OF RELOC TABLE
	MOVE	T2,RC.IV(T1)	;[704] GET ORIGIN
	TRZ	T2,777		;[704] ROUND IT DOWN TO PAGE BOUND
	CAIL	P3,(T2)		;[704] ADDR IS LESS THAN THE ORIGIN?
	JRST	[MOVEM	R,RC.CUR	;[704] UPDATE TO NEXT PSECT
		JRST INGAP1]		;[704] AND LOOP FOR ANOTHER CHECK
INGAP3:
IFN FTOVERLAY,<			;[724]
	SKIPL	LNKMAX		;[724] ANY OVERLAYS (SKIP IF NO)
	JRST	INGAP4>		;[724] YES,
	HRRZ	T1,JOB116	;[724] CHECK TO SEE IF IT'S IN SYMBOL
	HLRE	T2,JOB116	;[724]  TABLE RANGE
	SUBM	T1,T2		;[724] GET TOP
	TRZ	T1,777		;[726] ROUND DOWN LOWER BOUND
	TRO	T2,777		;[726] ROUND UP UB OF SYMBOL TABLE
	CAML	P3,T1		;[724]
	CAMLE	P3,T2		;[724] IN RANGE?
	JRST	INGAP4		;[724] NO,
INGAP5:	POP	P,T1		;[724] YES, RESTORE ACS
	POP	P,R		;[724]
	JRST	CPOPJ1		;[724] SKIP RETURN

INGAP4:	POP	P,T1		;[704] YES, IN A GAP, DO NON-SKIP RET
	POP	P,R		;[704]
	TLOE	P4,GAPF		;[704] WE HAVE A GAP, WAS LAST PAGE ALSO GAP?
	JRST	INGAP2		;[704] BUMP PROCESS PAGE AND RETURN
	PUSHJ	P,XCMPRD	;[704] NO, WRITE OUT LAST DIR,
	TLZ	P4,ZEROF+DATAF	;[704] OFF WITH OTHER FLAGS
INGAP2:	ADDI	P2,1		;[704] BUMP PROCESS PAGE
	POPJ	P,		;[704]

;HERE TO WRITE OUT A DIRECTORY ENTRY

XCMPRD:	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	MOVEM	P1,(W1)		;STORE DIRECTORY PTRS
	TLNE	P4,ZEROF	;[704] ZEFO PAGE?
	HLLZS	(W1)		;YES, SO NO FILE PAGES
	PUSHJ	P,XCMPXD	;SECOND WORD 
	MOVEM	P2,(W1)		;
	LDB	T3,[POINT 9,P2,8]	;GET REPEAT COUNT
	TLNE	P4,DATAF	;[704] DATA PAGE?
	ADDI	P1,1(T3)	;INCREMENT FILE PTR
	ADDI	P2,1(T3)	;AND PROCESS PTR
	TXZ	P2,777B8	;CLEAR REPEAT COUNT
	POPJ	P,

;HERE IF WE HAVE A PAGE OF ALLOCATED ZEROES

XCMPR2:	ADD	P2,[1B8]	;INCREMENT REPEAT COUNT
	TLO	P4,ZEROF	;[704] WE GOT A ZERO PAGE
	TLZ	P4,DATAF+GAPF	;[704] OFF OTHER FLAGS
	JRST	XCMPR0		;GET NEXT PAGE

;HERE IF NON-ZERO FOUND
;IF WE WERE OUTPUTTING DATA LAST, JUST INCREMENT REPEAT COUNT
;IF NOT, UPDATE DIRECTORY

XCMPR3:	SETZ	T2,		;MAKE SURE
	OUT	DC,T1		;OUTPUT THIS PAGE
	  CAIA			;OK
	JRST	XCMPER
	TLNE	P4,DATAF	;[704] LAST PAGE WAS ALSO DATA?
	JRST	[ADD	P2,[1B8]	;[704] BUMP REPEAT COUNT
		JRST	XCMPR0]		;[704]
	TLNN	P4,GAPF		;[704] NO, LAST PAGE GAP THEN SKIP
	PUSHJ	P,XCMPRD	;[704] NO, MUST BE ZERO, OUTPUT DIR
	TLO	P4,DATAF	;[704] SET DATAF
	TLZ	P4,GAPF+ZEROF	;[704] OFF WITH OTHERS
	JRST	XCMPR0		;[704] GET NEXT PAGE


XCMPRH:	TLNN	T1,777		;A PARTIAL WORD?
	JRST	XCMPR8		;NO
	MOVE	T1,P1		;GET FILE PTR
	LSH	T1,2		;IN BLOCKS
	USETO	DC,1(T1)	;ALLOCATE REMAINDER
XCMPR8:	MOVE	T1,HC.S0(R)	;GET HIGHEST DATA LOCATION
	MOVE	T3,HL.S0(R)	;AND HIGHEST ALLOCATEDLOCATION
	IORI	T1,777		;PUT ON PAGE BOUNDARY
	IORI	T3,777		;...
	SUB	T3,T1		;SEE IF SAME PAGE
	JUMPE	T3,XCMPR9	;YES
	HRL	P2,T3		;[733] P2 HAS RIGHT PROCESS PAGE
	SUB	P2,[1B8]	;[733] REPEAT COUNT IS ONE LESS IN LH
	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	HLLZM	P1,(W1)		;STORE FLAGS
	PUSHJ	P,XCMPXD	;
	MOVEM	P2,(W1)		;[733] STORE ALLOCATED BUT ZERO PAGES
XCMPR9:	SKIPE	PAG.S0(R)	;A TEMP FILE STILL?
	PUSHJ	P,@[EXP LC.DLT,HC.DLT]-1(R)	;YES, GET RID OF IT
	CAIE	R,1		;JUST DUMPED LOW CORE?
	JRST	[CAIE	R,2		;JUST DUMPED HIGH CORE?
		JRST XCMPHG		;NO, GO CHECK HIGH
		JRST XCMPRX]		;YES, FINISH UP
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;YES, SEE IF ANY OVERLAY?
	SKIPN	JOB116		;ANY SYMBOLS TO DUMP?
	JRST	XCMPHG		;NO, GO CHECK HIGH
	JRST	XCMPOV		;YES, GO DUMP OVERLAY SYMBOL
>

IFN FTOVERLAY,<
;HERE IF OVERLAY AND LOCAL SYMBOLS OF ROOT MODULES ARE TO BE DUMPED
;FIRST SET UP EXE FILE DIRECTORY ENTRIES FOR THE
;ZERO PAGES BETWEEN LOW CORE AND THE SYMBOL TABLE
;AND THE SYMBOLS.  
;ALSO, ZEROS GET PADDED IN FRONT IS LOCAL SYMBOLS DON'T
;START AT A VIRTUAL PAGE BOUND
;

XCMPOV:	PUSHJ	P,XCMPXD	;INCREMENT W1 AND SEE IF ENOUGH ROOM?
	HLLZM	P1,(W1)		;FLAGS+0 FILE PAGE
	PUSHJ	P,XCMPXD	;ENOUGH ROOM?
	MOVEM	P2,0(W1)	;CORE-PAGE
	HRRZ	T1,JOB116	;START ADDR. FOR LOCAL SYMBOLS
	MOVE	T3,T1
	IDIVI	T1,1000		;T1/PAGE #   T2/ZERO WORDS
	SUBM	T1,P2		;GET THE NUMBER OF ZERO PAGES
	SUBI	P2,1
	DPB	P2,[POINT 9,0(W1),8]	;DEPOSIT AS THE REPEAT COUNT
	PUSHJ	P,XCMPXD	;ENOUGH ROOM?
	MOVEM	P1,(W1)		;FLAGS+FILE PAGE#
	PUSHJ	P,XCMPXD	;ENOUGH ROOM?
	MOVEM	T1,0(W1)	;CORE PAGE #
	ADD	T3,LSYM		;GET REPEAT COUNT FROM START+LENGTH
	LSH	T3,-9		;CONVERT TO PAGE
	SUB	T3,T1		;TAKE AWAY STARTING PAGE COUNT
	ADD	P1,T3		;[725] INCREMENT PROCESS PAGE
	SUBI	T3,1
	DPB	T3,[POINT 9,0(W1),8]	;REPEAT COUNT
	MOVE	P2,T2		;# OF ZEROS IN FRONT
	MOVEI	T2,200		;GET A 200 WORD
	PUSHJ	P,DY.GET##	;SCRATCH BLOCK
	MOVEM	T1,SCRTCH		;SAVE IT, SO WE CAN GIVE BACK
	SUBI	T1,1		;MAKE IT IOWD
	HRLI	T1,-200		;
	SETZ	T2,
XCMPO1:	CAIGE	P2,200		;MORE THAN 200 ZEROS?
	JRST	XCMPO2		;NO,
	OUT	DC,T1		;YES, OUTPUT A BLOCK OF ZEROES
	JRST	[SUBI P2,200
		JRST XCMPO1]
	JRST	XCMPER


;HERE IF LOCAL SYMBOLS ARE PAGED
;

XCMPO2:	PUSH	P,T1		;SAVE IOWD TO SCRATCH FOR A WHILE
	SKIPN	PAG.LS		;PAGED?
	JRST	XCMPLS		;NO
	HRLZ	T1,LW.LS	;YES, GO OUTPUT CURRENT WINDOW
	HRR	T1,LSYM
	PUSHJ	P,LS.OUT##
	SETZM	LW.LS		;START AT LOWEST LOCATION
	SKIPN	HC.S2		;GET MORE CORE AREA--ANY HIGH?
	JRST	XCMPP1		;NO
	MOVE	T1,HC.AB	;YES,
	MOVEM	T1,HC.UB
	JRST 	XCMPP2
XCMPP1:	MOVE	T1,LC.AB
	MOVEM	T1,LC.UB
XCMPP2:	ADDI	T1,1
	MOVEM	T1,LS.LB	;NEW LOWER BOUND
	MOVE	T2,.JBREL	;NEW UPPER BOUND
	MOVEM	T2,LS.UB
	SUBM	T2,T1		;GET LEGTH OF CORE AVAILABLE
	SETZ	R,
	MOVEM	T1,UW.LS	;WE HAVE UPPER WINDOW
	CAMGE	T1,LSYM		;WINDOW BIG ENOUGH FOR ALL?
	JRST	[PUSHJ	P,LS.IN##	;NO, READ IN AS MUCH AS WE CAN
		JRST XCMPO3]
	MOVE	T1,LSYM		;YES, JUST READIN WHAT WE HAVE
	IORI	T1,.IPM
	MOVE	T2,T1
	ADD	T2,LS.LB	;
	MOVEM	T2,LS.AB	;AND UPDATE 
	PUSHJ	P,LS.IN##
	PUSHJ	P,LS.DLT	;GO DELETE THE TMP FILE
	JRST	XCMPO3		;GO FIX UP FIRST BLOCK

;DUMP LOCAL SYMBOLS--HERE ONLY IF NOT PAGED

XCMPLS:	MOVEI	R,LS.IX-1	;SEE WHO HAS CORE RIGHT BELOW IT
	SKIPN	T2,TAB.UB(R)	;LOOK FOR NON-ZERO
	SOJGE	R,.-1		;IT'S ZERO, DECREMENT INDEX
	SUB	T2,TAB.AB(R)	;GET LENTH OF GAP
	SETZ	R,		;KEEP COUNT OF LEGTH OF LS ALREADY OUT
	CAMGE	T2,P2		;IS THE GAP BIT ENOUGH?
	JRST	XCMPO3		;NO, GO FIXUP FIRST BLOCK
	HRLS	P2,P2		;YES, BORROW WHAT WE NEED
	MOVE	R,LSYM		;UPDATE R SO WE KNOW ITS END
	MOVE	T1,LS.LB	;SET UP IOWD
	HLL	T1,JOB116	;IN T1
	SUB	T1,P2		;ADJUST BY NUMBER OF ZEROS
	SUBI	T1,1
	SETZ	T2,		;MAKE SURE ENDS WITH ZERO
	JRST	XCMPO4		;GO DO OUTPUT

XCMPO3:	POP	P,T1		;GET IOWD TO SCRATCH BACK FROM STACK
	MOVEI	T2,201(T1)	;USE SCRATCH SPACE
	MOVEI	P1,1(T1)	;GET START OF THE AREA
	ADD	P1,P2		;GET WHERE DATA SHOULD GO
	HRL	P1,LS.LB
	BLT	P1,(T2)
	MOVE	T4,LS.AB	;
	SUB	T4,LS.LB	;LENTH IN CORE
	ADDI	T4,1		;NUMBER OF WORDS TO BE READ IN
	CAMGE	T4,LSYM		;WOULD WE HAVE READ ALL?
	JRST	[MOVNI	T3,-200(T4)	;NO, NUMBER OF WORDS TO DUMP
		MOVE	R,T4
		SUBI	R,(P2)
		JRST	XCMPO5]
	MOVN	T3,LSYM		;YES, NUMBER OF WORDS TO DUMP
	SUBI	T3,-200(P2)	;LESS BY DATA BLT TO SCRATCH BLOCK
	MOVE	R,LSYM
XCMPO5:	MOVE	T2,LS.LB	;GET BEGINNING OF DATA
	SUBI	T2,-200(P2)	;ADJUST IT TO EXCLUDE DATA TO SCRATCH
	SUBI	T2,1		;1 LESS FOR IOWD
	HRL	T2,T3		;MINUS LENGTH IN LH OF IOWD
	PUSH	P,T2		;SAVE IOWD, NEED IT LATER IF PAGED
	SETZ	T3,		;MAKE SURE LIST END WITH  ZERO
XCMPO4:	OUT	DC,T1
	CAIA
	JRST	XCMPER
	CAML	R,LSYM		;FINISHED?
	JRST	[POP	P,0(P)		;YES, RESTORE STACK
		MOVEI	R,1		;INDICATE WE JUST DID LOW SEG
		MOVE	T1,SCRTCH	;GIVE BACK THE SCRATCH SPACE
		MOVEI	T2,200		;OF 200 WORDS
		PUSHJ	P,DY.RET##
		SKIPE	PAG.LS		;STILL A TEMP FILE?
		PUSHJ	P,LS.DLT	;YES, DELETE IT
		JRST	XCMPHG]		;GO CHECK HIGH CORE

;FALL THROUGH TO NEXT PAGE
;HERE TO DUMP THE NEXT BLOCK OF SYMBOLS, IF NEEDED

	MOVE	T1,LW.LS	;GET LOWER WINDOW
	ADDI	T1,-200(T4)	;INCRREMENT IT
	MOVEM	T1,LW.LS	;NEW LOWER WINDOW
	ADD	T1,T4		;ADD THE NUMBER OF WORDS TO BE READ
	CAML	T1,LSYM		;EXCEEDED THE END?
	MOVE	T1,LSYM		;YES, READ ONLY WHAT WE NEED
	MOVE	R,T1		;UPDATE R
	MOVEM	T1,UW.LS	;UPDATE UPPER WINDOW
	HRL	T1,LW.LS	;LOW WINDOW IN LH FOR LS.IN
	PUSHJ	P,LS.IN##	;GO READ IT
	HRRZ	T1,T1		;GET NEW OUTPUT LENGTH
	SUB	T1,LW.LS
	ADDI	T1,-200(P2)	;ADJUST IT BY PREVIOUS OUT
	MOVN	T3,T1		;NEGATE IT AND SAVE IN CASE  AT END
	MOVE	T1,LW.LS	;GET LOWER WINDOW
	MOVE	T1,0(P)		;GET IOWD FROM STACK
	CAML	R,LSYM		;AT END, NEED TO FISUP THE LH
	HRL	T1,T3		;YES,
	SETZ	T2,	;END LIST WITH ZERO
	JRST	XCMPO4		;GO OUTPUT

>
XCMPHG:	SKIPN	HC.LB		;ANY HIGH SEGMENT?
	JRST	XCMPRX		;NO, FINISH UP
	SKIPN	PAG.S2		;PAGING?
	JRST	XCMPRN		;NO,
	MOVE	T1,HC.AB	;GET TOP
	SUB	T1,HC.LB	;LENTH
	ADDI	T1,1		;ROUND UP
	ANDCMI	T1,777		;MAKE SURE ON PAGE BOUNDARY
	SUBI	T1,1		;GET CORRESPONDING UPPER BOUND
	MOVEM	T1,PAG.S2	;RESET WINDOW
	ADD	T1,HC.LB	;
	MOVEM	T1,HC.AB	;AND CORE BOUND
XCMPRN:	MOVE	T1,SSEXT	;GET TYPE BITS
	HRRZ	P1,P1		;CLEAR FLAGS
IFE TOPS20,<
	TXO	P1,SV%HIS	;HIGH ALWAYS FOR -10
	TXNE	T1,SS.SHR	;SHAREABLE?
> ;END OF IFE TOPS20
	TXO	P1,SV%SHR	;YES,
	MOVE	T1,HC.LB	;START OF HI SEG
	SUBI	T1,1		;IOWD IS 1 LESS
	MOVE	P2,LL.S2	;GET ORIGIN
	LSH	P2,-9		;IN PAGES
	SETZB	P3,P4		;RESET FLAGS
	MOVE	T3,HC.S2	;GET LENGTH OF HI SEG
	CAIL	T3,1000		;LESS THAN 1 PAGE
	AOJA	R,XCMPRL	;NOW SAVE HIGH SEGMENT
	MOVN	T3,T3		;YES, GET ACTUAL WORD COUNT
	HRL	T1,T3		;JUST OUTPUT THAT MUCH
	AOJA	R,XCMPR7	;OF HIGH SEGMENT


XCMPRX:
IFN TOPS20,<
	MOVE	T1,STADDR	;GET ENTRY VECTOR
	TLNN	T1,-1		;JUST AN ADDRESS
	HRLI	T1,(JRST)	;YES, MAKE COMPATIBLE WITH OLD
	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	MOVE	T2,[.SVEVC,,3]	;STORE 2 WORD EVEC
	MOVEM	T2,(W1)		;STORE HEADER
	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	HLRZM	T1,(W1)		;STORE COUNT
	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	HRRZM	T1,(W1)		;STORE ADDRESS
XCMPRV:>
	MOVE	T1,[.SVEND,,1]	;END MARKER
	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	MOVEM	T1,(W1)		;STORE IT
	MOVEI	W1,(W1)		;
	SUB	W1,EXEDIR	;GET LENGTH
IFN TOPS20,<
	SUBI	W1,3		;DON'T COUNT ENTRY VECTOR BLOCK
>
	HRLI	W1,.SVDIR	;HEADER
	MOVE	T3,EXEBLK	;SEE WHICH DIRECTORY BLOCK
	CAIG	T3,1		;INCASE NOT FIRST
	MOVEM	W1,@EXEDIR	;COMPLETE BLOCK
	USETO	DC,@EXEBLK	;NOW TO WRITE THE DIRECTORY
	HRRZ	T1,EXEDIR	;
	SUBI	T1,1		;
	HRLI	T1,-1000	;IOWD
	SETZ	T2,		;
	OUT	DC,T1		;WRITE IT
	  CAIA			;OK
	JRST	XCMPER		;ERROR
	CAIE	T3,1		;WAS IT JUST SIMPLE CASE?
	JRST	[USETI	DC,1		;NO
		IN	DC,1		;READ BACK FIRST DIRECTORY BLOCK
		LSH	T3,-2		;SEE HOW MANY PAGES
		IMULI	T3,1000		;ACCOUNT FOR ALL WORDS
		ADDI	W1,(T3)		;GRAND TOTAL
		MOVEM	W1,@EXEDIR	;NOW STORE
		USETO	DC,1		;WRITE IT BACK
		OUT	DC,T1		;
		  JRST	.+1		;OK
		JRST	XCMPER]		;ERROR
	MOVE	T1,EXEDIR	;GET BASE AGAIN
	MOVEI	T2,1000		;LENGTH
	PUSHJ	P,DY.RET##	;GIVE SPACE BACK
	JRST	ENDCMP		;CLOSE FILE

XCMPXD:	AOBJN	W1,CPOPJ	;ALLOCATE IF ENOUGH ROOM
	PUSH	P,T1		;SAVES SPACE TO SAVE IT HERE
	USETO	DC,@EXEBLK	;SET ON IT
	MOVE	W1,EXEDIR	;PTR TO START
	HRLI	W1,-400		;NO. TO TRY
	MOVEI	T1,1		;INCREMENT
XCMPXE:	MOVE	T3,1(W1)	;GET FILE PAGE
	TRNE	T3,-1		;TEST FOR ALLOCATED BUT ZERO
	ADDM	T1,1(W1)	;INCREMENT REAL PAGE
	ADDI	W1,1		;
	AOBJN	W1,XCMPXE	;LOOP
	HRRZ	T1,EXEDIR	;
	SUBI	T1,1		;
	HRLI	T1,-1000	; FORM IOWD
	SETZ	T2,		;MAKE SURE
	OUT	DC,T1		;WRITE OUT DIRECTORY
	  CAIA			;OK
	JRST	XCMPER		;ERROR
	MOVEI	T3,4		;NO. OF BLOCKS WE WILL MOVE BY
	ADDB	T3,EXEBLK	;WHERE REST OF DIRECTORY WILL GO
	LSH	T3,-2		;NO. OF PAGES
	SUBI	T3,1(P1)	;- NO. OF PAGES TO COPY
	MOVEI	T4,(P1)		;PAGE NO.
	LSH	T4,2		;BLOCK NO.
	HRL	T4,T3		;AOBJN PTR
XCMPXL:	USETI	DC,1(T4)	;SET ON INPUT BLOCK
	IN	DC,T1		;READ FILE BACKWARDS
	  CAIA			;OK
	JRST	XCMPER		;ERROR
	OUT	DC,T1		;WRITE IT BACK OUT 1 PAGE HIGHER
	  CAIA			;OK
	JRST	XCMPER		;
	HRRI	T4,-5(T4)	;SUBTRACT BUT WORRY ABOUT CARRY
	AOBJN	T4,XCMPXL	;LOOP
	HRRZ	W1,EXEDIR	;RESET DEPOSIT PTR
	HRLI	W1,-1000	;
	HRLZ	T1,W1		;
	HRRI	T1,1(W1)	;FORM BLT PTR
	SETZM	(W1)		;
	BLT	T1,777(W1)	;CLEAR DIRECTORY BLOCK
	AOS	T1,P1		;NEW FILE PAGE
	LSH	T1,2		;BLOCKS
	USETO	DC,5(T1)	;RESET OUTPUT PTR
	POP	P,T1		;RESTORE
	POPJ	P,		;

XCMPER:	PUSH	P,[DC]
	.ERR.	(ST,,V%L,L%F,S%F,EOE,<EXE FILE OUTPUT ERROR>)

>;END OF IFN FTEXE
IFE FTEXE,<

;HERE FOR ZERO COMPRESSOR
;NOTE! LIKE THE MONITOR WE REMOVE ALL ZEROS (FILEX LEAVES SINGLE ZEROS)

ZCMPRS:	MOVE	P2,LC.LB	;OUTPUT POINTER
	MOVEI	P1,.JBSDD-1(P2)	;INPUT POINTER
	HRLZ	T1,P2		;FORM BLT POINTER
	HRRI	T1,1(P2)	;TO CLEAR NON-SAVED PART OF FILE
	SETZM	(P2)		;CLEAR
	BLT	T1,-1(P1)
	MOVE	P3,P2		;POINT TO PARTIAL IOWD
				;EXCEPT WE HAVEN'T SET IT UP YET
				;HOWEVER SINCE SOME OF JOBDAT IS NON-ZERO
	SKIPN	T1,1(P1)	;WE WILL EVENTUALLY FIND A DATUM
	AOJA	P1,.-1		;IF WE LOOK LONG ENOUGH
	MOVE	T2,P1		;GET ADDRESS
	SUB	T2,LC.LB	;MINUS CORE OFFSET
	ADD	T2,LW.S1	;PLUS WINDOW OFFSET
	HRRZM	T2,(P3)		;STORE USER ADDRESS
ZCMPR0:	SETO	P4,		;INITIALIZE ZERO COUNTER
ZCMPR1:	ADDI	P2,1		;BUMP COUNT
	MOVEM	T1,0(P2)	;STORE DATUM
ZCMPR2:	ADDI	P1,1		;INCREMENT READIN POINTER
	CAML	P1,LC.AB	;BUT NOT TOO FAR
	JRST	ZCMPR5		;FINISHED OR GET NEXT WINDOW FULL
ZCMPR3:	SKIPN	T1,1(P1)	;GET NEXT DATUM
	AOJA	P4,ZCMPR2	;COUNT A ZERO
	JUMPL	P4,ZCMPR1	;NO ZEROS SEEN
	MOVE	T2,P1		;GET ADDRESS
	SUB	T2,LC.LB	;MINUS CORE OFFSET
	ADD	T2,LW.S1	;PLUS WINDOW
	HRRZM	T2,1(P2)	;STORE NEXT IOWD TO BE
	MOVEI	T2,(P3)		;LAST IOWD
	SUBI	T2,(P2)		;MINUS CURRENT GIVES -LENGTH
	SKIPE	T2		;ALREADY BEEN DONE IF 0
	HRLM	T2,(P3)		;FIXUP IOWD
	AOS	P3,P2		;POINT TO THIS NEW POINTER
	JRST	ZCMPR0		;AND GET NEXT DATUM

;HERE WHEN CURRENT WINDOW IS FULL
ZCMPR5:	SKIPN	LSTPAG		;LAST PAGE IN CORE IF PAGING
	SKIPN	PAG.S1		;ALWAYS IN CORE IF NOT
	JRST	ZCMPR6		;YES, CAN WRITE OUT ALL OF CORE NOW
	MOVE	T1,P3		;HIGHEST ADDRESS WE CAN OUTPUT
	IORI	T1,.IPM		;HOWEVER IT MAY NOT BE IN LAST BLOCK
	CAML	T1,P2		;IN WHICH CASE CREATE AN IOWD AND OUTPUT
				;IT ANYWAY. THIS MEANS SAVE FILES
				;WILL NOT BE BIT IDENTICAL UNTIL EXPANDED.
	JRST	ZCMPR7		;OK, ZERO SEEN  IN THIS BLOCK
	MOVEI	T2,(P3)		;LAST IOWD
	SUBI	T2,(P2)		;MINUS CURRENT GIVES -LENGTH
	HRLM	T2,(P3)		;FIXUP IOWD
	MOVEI	T1,1(P2)	;[652] THIS IS THE HIGHEST TO OUTPUT
	MOVE	P3,P2		;MAKE NEW IOWD POINT TO CURRENT POSITION
	SKIPGE	P4		;IF WE ARE NOT READING ZEROS
	SETZ	P4,		;SIGNAL NEW IOWD NEEDED
	JRST	ZCMPR7		;OUTPUT WHAT WE HAVE


;HERE TO FIXUP FINAL POINTER AND SET TO WRITE OUT LAST OF CORE IMAGE
ZCMPR6:	MOVEI	T2,(P2)		;GET ADDRESS
	SUBI	T2,(P3)		;GIVES LENGTH
	MOVN	T2,T2		;NEGATE
	HRLM	T2,(P3)		;FIXUP IOWD
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;SEEN ANY OVERLAYS?
	SKIPN	T1,JOB116	;AND WANT SYMBOLS?
	JRST	ZCMP6S		;NO
	SUBI	T1,1		;IOWD IS 1 LESS
	MOVEM	T1,1(P2)	;STORE IOWD
	HLRE	T2,T1		;- LENGTH
	MOVM	T2,T2
	SKIPN	PAG.LS		;PAGING SYMBOLS?
	JRST	ZCMP6R		;NO
	SETZM	LW.LS		;BRING IN THE BASE
	SETOM	LS.PP		;CERTAINLY CAN'T PAGE IT NOW
	PUSHJ	P,FR.CNT##	;THERE SHOULD BE SOME MORE ROOM
	SUB	P2,LC.LB	;MAKE P2 RELATIVE FOR SHUFFLING
	PUSH	P,P2		;SAVE IT OVER LNKCOR
	MOVEI	P1,LS.IX	;WANT ROOM IN LS AREA
	MOVE	P2,T1		;USE IT ALL
	PUSHJ	P,LNKCOR##	;DO SOME BLT'S
	  PUSHJ	P,NO.COR##	;CANNOT HAPPEN
	POP	P,P2		;RESTORE RELATIVE ADDRESS
	ADD	P2,LC.LB	;MAKE ABSOLUTE
	MOVE	T1,LS.UB	;SETUP T1 FOR LS.IN
	SUB	T1,LS.LB
	MOVEM	T1,UW.LS	;UPPER WINDOW
ZCMP6A:	PUSHJ	P,LS.IN##	;READ BACK
	MOVE	T2,UW.LS	;UPPER BOUND
	CAMLE	T2,LSYM		;UNLESS TOO MANY
	MOVE	T2,LSYM		;YES, USE ACTUAL NUMBER
	SUB	T2,LW.LS	;LENTH OF THIS 
	MOVEI	T1,2(P2)	;NEXT FREE AFTER IOWD
	HRL	T1,LS.LB	;FROM
	ADDI	P2,1(T2)	;WHERE TO STOP
	BLT	T1,(P2)		;MOVE DOWN
	MOVE	T1,P2		;GET END
	ANDCMI	T1,.DBM		;[650] BUT NOT LAST BLOCK
	SUB	T1,LC.LB	;LENGTH
	MOVN	T1,T1
	HRL	T1,T1
	HRR	T1,LC.LB
	SUBI	T1,1		;IOWD
	SETZ	T2,
	OUT	DC,T1
	  SKIPA	T1,P2		;OK
	JRST	ZCMP7E		;NO
	ANDCMI	T1,.DBM		;[650]
	HRLZ	T1,T1		;FROM
	HRR	T1,LC.LB	;TO
	ANDI	P2,.DBM		;[650] KEEP LAST BLOCK
	ADD	P2,LC.LB	;FIX IT UP AGAIN
	BLT	T1,(P2)		;MOVE BLOCK DOWN
	MOVE	T1,UW.LS
	SUB	T1,LW.LS
	ADDI	T1,1		;LENGTH
	ADDM	T1,UW.LS
	ADDB	T1,LW.LS
	CAML	T1,LSYM		;DONE
	JRST	[MOVEI	T1,SC		;SYBMOL CHANNEL:
		PUSHJ	P,DVDEL.##	;  DISCARD IT
		  JFCL			;DON'T CARE
		JRST	ZCMP6S]		;AND SETUP START ADDRESS
	HRLZ	T1,LW.LS
	HRR	T1,UW.LS	;READ IN REST
	JRST	ZCMP6A		; OF FILE
ZCMP6R:	MOVEI	T1,2(P2)	;NEXT FREE
	HRL	T1,LS.LB	;FROM WHERE
	ADDI	P2,1(T2)	;ACCOUNT FOR SYMBOLS PLUS IOWD
	BLT	T1,(P2)		;MOVE SYMBOLS DOWN
ZCMP6S:>
	MOVE	T1,STADDR	;GET STARTING ADDRESS
	HRLI	T1,(JRST)	;FORM TRANSFER WORD
	MOVEM	T1,1(P2)	;STORE AFTER LAST WORD IN FILE
	AOS	T1,P2		;WRITE OUT ALL OF CORE
	AOJA	T1,.+2		;ONE MORE FOR TRANS WORD
ZCMPR7:	ANDCMI	T1,.IPM		;GET TO START OF THIS BLOCK
	SUB	T1,LC.LB	;LENGTH TO OUTPUT
	JUMPE	T1,ZCMPR8	;IGNORE IF BLOCK OF ZERO'S
	MOVN	T1,T1		;NEGATE IT
	HRLZ	T1,T1		;PUT IN LEFT HALF
	HRR	T1,LC.LB	;FORM IOWD
	HRRI	T1,-1(T1)	;IOWD IS 1 LESS
	SETZ	T2,		;TERMINATE LIST
	OUT	DC,T1		;DO OUTPUT
	  JRST	ZCMPR8		;OK
ZCMP7E:	PUSH	P,[DC]
	.ERR.	(ST,,V%L,L%F,S%F,SOE)

;NOW TO MOVE DOWN  THE REMAINING DATA IN THE BUFFER PRIOR TO
;READING IN MORE. IF NOT PAGING THIS IS END
ZCMPR8:	SKIPE	PAG.S1		;WELL ARE WE PAGING
	SKIPE	LSTPAG		;BUT DONE IF ON LAST PAGE
	JRST	ENDCMP		;NO, ALL DONE
	MOVE	T1,P1		;GET LOWEST LOCATION TO LEAVE
	ANDCMI	T1,.IPM		;ON BOUND
	SUB	T1,LC.LB	;REMOVE CORE OFFSET
	ADDM	T1,LW.S1	;ADJUST WINDOW POINTERS
	ADDB	T1,UW.S1	;MAY AS WELL
	MOVE	T2,HC.S1	;GET HIGHEST LOCATION WE NEED TO SAVE
	IORI	T2,.IPM		;PUT ON BOUND
	CAMLE	T2,T1		;TOO MUCH OR JUST ENOUGH ROOM AVAILABLE?
	JRST	ZCMPR9		;NO
	SUB	T2,T1		;YES, FIND DIFFERENCE
	ADDM	T2,UW.S1	;SO WE DON'T WASTE TIME COUNTING ZEROS
	ADDB	T2,LC.AB	;OR GET ERRORS ON INPUT
	MOVEM	T2,LSTPAG	;SIGNAL LAST PAGE WILL SOON BE IN CORE
ZCMPR9:	MOVE	T1,P3		;FORM BLT POINTER
	ANDCMI	T1,.IPM
	CAMN	T1,LC.LB	;CHECK FOR BLT IN PLACE
	JRST	ZCMP9A		;AND DON'T WASTE TIME ON IT
	HRLZ	T1,T1
	HRR	T1,LC.LB	;TO MOVE DOWN 
	HRRZI	T2,.IPM(T1)	;TO THIS FAR
	BLT	T1,0(T2)
ZCMP9A:	SKIPE	T1,LSTPAG	;NOW CUT BACK CORE
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;UNLESS LOADING OVERLAYS
	SKIPA			;IN WHICH CASE WOULD ZAP LS AREA
> ;END IFN FTOVERLAY
	CORE	T1,		;TRY TO CUT BACK CORE
	  JRST	.+3		;TOO BAD
	MOVE	T1,.JBREL	;SETUP
	MOVEM	T1,LC.UB	;TO BE CONSISTENT
	ANDI	P3,.IPM		;KEEP OFFSET
	CAIN	P3,.IPM		;[652] FIRST PAGE ALREADY FINISHED?
	SUBI	P3,.IPS		;[652] YES, RE-USE IT FOR COMPRESSION
	ADD	P3,LC.LB	;[652] ADD IN BASE
	ANDI	P2,.IPM		;SAME AGAIN
	CAIN	P2,.IPM		;[652] FINISHED?
	SUBI	P2,.IPS		;[652] YES, RE-USE
	ADD	P2,LC.LB	;[652] ADD IN BASE
	ANDI	P1,.IPM
	IOR	P1,LC.LB

;NOW FOR DATA NOT READ
	HRRZ	T1,LW.S1	;THIS IS WINDOW BASE
	HRLZI	T1,.IPS(T1)	;BUT WE ALREADY HAVE THIS MUCH
	HRR	T1,UW.S1	;FOR GENERAL INPUT ROUTINE
	PUSHJ	P,LC.IN##	;READ IN NEW CORE IMAGE
	SKIPE	LSTPAG		;HAVE WE READ LAST PAGES YET?
	PUSHJ	P,LC.DLT	;YES, GET RID OF FILE
	JRST	ZCMPR3		;AND CONTINUE

> ;END OF IFE FTEXE

SUBTTL	RUN UUO

;HERE WHEN THROUGH
ENDCMP:	MOVEI	T1,DC		;MAKE SURE 
	MOVEM	T1,IO.CHN
	PUSHJ	P,DVRLS.##
	SKIPE	IO.PTR+%XC	;NEED TO RENAME .XPN FILE?
	PUSHJ	P,XPNREN	;YES
	MOVE	T1,IO.PTR+DC	;BUT SAVE FILE SPEC
	MOVEM	T1,IO.PTR+LC	;IN CASE /EXEC
IFN FTOVERLAY,<
	SKIPGE	LNKMAX		;DID WE SEE ANY LINKS?
	JRST	ENDSAV		;NO
	MOVEI	T1,OC		;YES, RENAME FILE TO WHAT WE WANT
	MOVEM	T1,IO.CHN
	MOVE	T2,IO.PTR+%OC	;PTR TO REAL NAME
	PUSHJ	P,DVPRO.	;SETUP CORRECT PROTECTION
	MOVE	T1,T2		;OLD IN IO.CHN, NEW IN T1
	PUSHJ	P,DVRNF.##
	  JRST	OVRENE		;[616] REPORT RENAME ERROR
	SKIPE	PLOTSW		;WANT PLOT PACKAGE?
	JRST	LNKPLT##	;YES
	JRST	ENDSAV		;[616] NO, DO RUN UUO OR EXIT

;HERE ON A RENAME ERROR FOR THE OVERLAY FILE
OVRENE:	PUSH	P,[%OC]		;[616] SET UP CORRECT CHANNEL
	.ERR.	(LRE,,V%L,L%F,S%F,FRE)	;[616] GIVE A FATAL ERROR
>
ENDSAV::PUSHJ	P,TERMES	;PRINT FINAL MESSAGES
	SKIPE	EXECSW		;GO INTO EXECUTION?
	JRST	RUNUUO		;YES, DO RUN UUO ON FILE
	SKIPN	N.ZER##		;RUN SWITCH PENDING?
	JRST	ENDZAP		;NO, JUST EXIT
	SETZM	F.EDIT		;MAKE SURE LNKSCN WON'T GET UPSET
	JRST	LNKSCN##	;AND GO DO THE RUN SWITCH

				;NO, CUT CORE BACK TO MINIMUM AND EXIT
ENDZAP:	MOVSI	17,ENDCLR	;LOAD ACCS
	BLT	17,17		;WITH EXIT CODE
	JRST	$4		;AND JUMP TO THEM

ENDCLR:	PHASE	0
	1,,20			; 0 - CORE UUO ARG /SETNAM ARG
	20,,21			; 1 - ZERO BLT PTR
	EXP	0,0		;FUTURE
$4:!	CORE	0,		; 4 - CUT CORE TO MINIMUM
	  JFCL			; 5 - ERROR RETURN
	SETZB	0,20		; 6 - FOR SETNAM AND ZERO BLT
	BLT	1,@.JBREL	; 7 - CLEAR ALL BUT ACCS
	SETNAM	0,		;10 - CHANGE NAME TO NULL
	SETDDT	0,		;11 - CLEAR DDT INCASE DEBUGGING VERSION
	MOVEM	$15,.JBBLT	;12 - LOAD .JBBLT WITH FINAL ACC BLT
	MOVEM	$16,.JBBLT+1	;13 - AND EXIT
	JRST	.JBBLT		;14 - JUMP TO EXEC PDL
$15:!	BLT	17,17		;15 - CLEAR ACCS
$16:!	EXIT			;16 - AND GO AWAY
	0,,1			;17 - BLT PTR TO CLEAR ACCS

	DEPHASE

DEFINE KEYMAC (A,B)<
 IFIDN <A><DEB>,<
  %%==-1
  IRP B,<
   IFGE %%,<
    IFN %%&1,<
    [ASCIZ	\B\]
   >>
   %%==%%+1
 >>
 PURGE %%
>

DEBNAM:	KEYWORDS
;HERE FOR RUN UUO
RUNUUO:	SKIPN	STADDR		;WARN USER IF NO STARTING ADDRESS
	OUTSTR	[ASCIZ	\[LNKNSA No start address]
\]
	SKIPN	STADDR
	AOSA	T2,ERRNO	;PREVENT EXECUTION IF NO START ADDRESS
	MOVE	T2,ERRNO	;SAVE ERROR COUNT, GETS WIPED OUT
	SKIPL	DEBUGSW		;IF DDT
	SKIPA	P1,STADDR	;NO
	MOVE	P1,EXECSW	;NEED TO START AT IT
	SUB	P1,STADDR	;OFFSET OR 0
	MOVE	T1,[%RHIGH,,%RLOW]
	BLT	T1,%RUN		;MOVE DOWN RUN UUO
	SKIPGE	DEBUGSW		;IF DEBUGGING
	JRST	RUNUUD		;YES
	JUMPN	T2,RUNUU2	;ERRORS, TOO BAD U LOSE
	SKIPN	T2,RUNAME	;GET NAME TO CALL CORE IMAGE
	MOVE	T2,LODNAM	;USE DEFAULT IF NOT SET
	MOVE	T4,[POINT 7,%DEXM]
	SETZ	T1,		;CLEAR RECEIVING AC
	LSHC	T1,6		;GET NEXT CHAR
	ADDI	T1," "		;INTO ASCII
	IDPB	T1,T4
	JUMPN	T2,.-4		;MORE TO DO
	IDPB	T2,T4		;MAKE SURE A 0 THERE
RUNUU1:	SKIPN	T1,IO.PTR+HC	;GET HIGH SEG POINTER
	MOVE	T1,IO.PTR+LC	;SETTLE FOR LOW SEG IF NO HIGH
	MOVE	T2,I.DEV(T1)	;GET DEVICE
	MOVEM	T2,%RUN+0	;RUN DEVICE
	MOVE	T2,I.NAM(T1)	;FILE NAME
	MOVEM	T2,%RUN+1
	SKIPN	T1,IO.PTR+LC	;[575] MAKE SURE POINTING AT LOW SEG
	JRST	RUNUU3		;[575] HISEG ONLY, USE .LOW
	MOVE	T2,I.EXT(T1)	;[575] MAY AS WELL USE KNOWN EXT
	TLNN	T2,-1		;[575] EXTENSION KNOWN?
RUNUU3:	MOVSI	T2,'LOW'	;[575] NO, USE .LOW
	HLLZM	T2,%RUN+2	;[575] STORE EXTENSION & ZERO DATE
	SETZM	%RUN+3		;CLEAR DATE TIME
	SETZM	%RUN+4		;PPN
	MOVE	T1,RUNCOR	;CORE FOR RUN UUO IF SET
	ADD	T1,RUNCOR+1	;IN CASE LK+HK
	MOVEM	T1,%RUN+5
	CAIGE	T1,%RUN+7	;USE LARGER OF WHAT WE WANT AND WHAT WE NEED
	MOVEI	T1,%RUN+7
	HRLI	T1,1		;REMOVE HIGH SEG IN EITHER CASE
	MOVEI	T2,%RUN		;ADDRESS OF RUN BLOCK
	HRL	T2,P1		;GET OFFSET
	JRST	%RLOW		;GO TO LOW SEG


RUNUUD:	MOVE	T1,DEBUGSW	;GET DEB INDEX
	DMOVE	T1,@DEBNAM(T1)	;GET NAME (POSSIBLE 6 CHARS  PLUS NULL)
	DMOVEM	T1,%DEXM	;STORE IT
	CAMN	T1,[ASCII \COBDD\]
	SETZ	P1,		;START AT MAIN PROG IF COBOL
IFE FTKIONLY,<
	MOVE	T1,[ASCIZ \[LNKDEB \]		;
	MOVE	T1+1,1+[ASCIZ \[LNKDEB \]	;
> ;END IFE FTKIONLY
IFN FTKIONLY,<
	DMOVE	T1,[ASCIZ \[LNKDEB \]		;
> ;END IFN FTKIONLY
	DMOVEM	T1,%DEXH
	JRST	RUNUU1		;RETURN

RUNUU2:	OUTSTR	DLTTXT
	JRST	ENDZAP		;AND DELETE USER
DLTTXT:	ASCIZ	\?LNKDLT Execution Deleted\
;ENTER WITH :-
;T1 = ARG FOR CORE UUO
;T2 = ARG FOR RUN UUO

%RHIGH:
	PHASE	.TEMP
%RLOW:	CORE	T1,
	  JFCL
	OUTSTR	%DEXH
	OUTSTR	%DEXM		;NAME OF DEBUGGER
	OUTSTR	%REXM		;TELL USER
	RUN	T2,
	  HALT
	EXIT
%DEXH:	ASCIZ	\[LNKXCT \
%DEXM:	EXP	0,0
%REXM:	ASCIZ	\ Execution]
\

%RUN:
	DEPHASE

TERMES:	.ERR.	(MS,0,V%L,L%I,S%I,FIN,<LINK finished>)
	MOVEI	T1,FINMES	;TELL USER WE'VE CLOSE LOG FILE
	SKIPE	LOGSUB		;BUT ONLY IF A REAL LOG FILE
	PUSHJ	P,.TSTRG##
	SKIPN	IO.PTR+RC	;SEE IF A LOG FILE?
	POPJ	P,		;NO
	MOVEI	T1,RC
	MOVEM	T1,IO.CHN
	SKIPN	T1,IO.PTR+%RC	;[616] DO WE NEED TO RENAME FILE?
	PJRST	DVRLS.##	;[616] NO, JUST RELEASE IT
	PUSHJ	P,DVRNF.##	;YES, DO IT
	  CAIA			;[616] GIVE AN ERROR MESSAGE
	PJRST	DVRLS.##	;CLOSE FILE
	PUSH	P,[%RC]		;[616] CHANNEL FOR ERROR
	.ERR.	(LRE,,V%L,L%F,S%F,FRE)	;[616] SEND THE MESSAGE

FINMES:	ASCIZ	\[LNKELF	End of log file]
\
;ROUTINE TO CAUSE THE DATA IN A FILE TO BE MOVED FROM ONE FILE SPEC
;TO ANOTHER, EITHER BY A RENAME (IF POSSIBLE), OR BY COPYING THE FILE.
;USES DUMP MODE ON CHANNEL TC FOR OUTPUT IF COPYING NECESSARY.
;CALL IS:
;	MOVE	T1,OLD CHAN #
;	MOVE	T2,NEW CHAN #
;	PUSHJ	P,DVMOV.
;	<ALWAYS RETURN>
;PRINTS FATAL ERROR AND STOPS IF RENAME OR COPY CANNOT BE PERFORMED.
;NOTE: THIS SHOULD REALLY BE IN LNKFIO, BUT IT IS HERE FOR NOW,
; SINCE NOBODY CALLS IT BUT LNKXIT, AND THERE IS NO USE MAKING
; ALL OF THE SEGMENTS BE A LOT BIGGER.

DVMOV.::MOVEM	T1,IO.CHN	;POINT I/O ROUTINES TO OLD FILE
	PUSH	P,T2		;SAVE NEW ONE
	MOVE	T1,IO.PTR(T1)	;GET POINTER TO OLD DATA BLOCK
	MOVE	T2,IO.PTR(T2)	;AND TO NEW ONE
	MOVE	T3,I.DEV(T1)	;GET OLD DEVICE
	CAME	T3,I.DEV(T2)	;SAME AS NEW ONE?
	JRST	DVCOPY		;NO, GO COPY FILE
	POP	P,T2		;RESTORE NEW CHANNEL
	MOVE	T1,IO.PTR(T2)	;GET POINTER TO NEW DATA BLOCK
	PUSHJ	P,DVRNF.	;DO THE RENAME
	  SKIPA			;FAILED, GIVE ERROR
	POPJ	P,		;SUCCESS, RETURN
	PUSH	P,IO.CHN	;SAVE CHANNEL FOR LNKLOG
	.ERR.	(LRE,,V%L,L%F,S%F,FRE)	;

;HERE WHEN CANNOT RENAME THE FILE. MUST DO THE COPY.
DVCOPY:	PUSHJ	P,DVCLS.##	;MAKE SURE THE INPUT FILE EXISTS
	MOVEI	T3,I.RIB(T1)	;LOOK IT UP AGAIN
	TLO	T3,(LOOKUP)	;..
	IOR	T3,I.CHN(T1)	;..
	XCT	T3		;SHOULDN'T FAIL
	  JRST	LKPERR##	;???
	MOVE	T3,I.SIZ(T1)	;GET INPUT FILE SIZE FOR LATER
	LSH	T3,-.DBS2W	;[650] CONVERT TO BLOCKS (FOR ESTIMATE)
	ADDI	T3,3		;2 RIBS PLUS REMAINDER
	POP	P,T2		;RESTORE NEW CHANNEL
	SPUSH	<P1,P2,P3>	;NEED LOTS OF ACS FOR THIS
	PUSH	P,IO.CHN	;SAVE OLD CHANNEL FOR LATER
	MOVE	P1,T1		;SAVE POINTER TO OLD DATA BLOCK
	MOVE	T1,IO.PTR(T2)	;GET POINTER TO NEW DATA BLOCK
	MOVEM	T1,IO.PTR+TC	;USE THE TEMP CHAN FOR THE COPY
	MOVEM	T3,I.EST(T1)	;SET UP ESTIMATE FOR FILSER
	MOVSI	T2,(Z TC,)	;POINT THE OUTPUT CHAN TO CHAN TC
	MOVEM	T2,I.CHN(T1)	;SINCE THE PSEUDO-CHANNEL IS THERE
	MOVEI	T2,TC		;POINT ALL I/O TO THE OUTPUT
	MOVEM	T2,IO.CHN	;CHANNEL, SO CAN ENTER THE FILE.
	PUSHJ	P,DVNAM.	;SETUP THE OUTPUT FILE NAME
	PUSHJ	P,DVOPN.	;GET THE OUTPUT DEVICE
	PUSHJ	P,DVENT.	;CREATE THE OUTPUT FILE
	PUSHJ	P,FR.CNT##	;FIND OUT HOW MUCH CORE IS FREE
	MOVE	T2,I.SIZ(P1)	;AND HOW MUCH WE NEED
	ADDI	T2,.DBM		;ROUND UP TO DISK BLOCK
	ANDCMI	T2,.DBM		;SINCE WE NEED THAT MUCH
	ANDCMI	T1,.DBM		;ALSO, ROUND FREE COUNT DOWN
	CAMLE	T2,T1		;HAVE AS MUCH AS WE NEED?
	MOVE	T2,T1		;NO, USE WHAT WE HAVE
	SKIPN	T2		;BUT IF NONE FREE AT ALL
	MOVEI	T2,.DBS		;NEED AT LEAST ONE DISK BLOCK
	PUSHJ	P,DY.GET##	;GET IT ALL
	MOVE	T3,I.SIZ(P1)	;RESTORE EXACT FILE SIZE
	CAMLE	T2,T3		;IS BUFFER BIGGER THAN FILE?
	MOVE	T2,T3		;NO, USE FILE SIZE FOR IOWD
	MOVN	P2,T2		;FORM AN INPUT IOWD
	HRLZ	P2,P2		;LH CONTAINS - COUNT
	HRRI	P2,-1(T1)	;RH CONTAINS START - 1
	SETZ	P3,		;IOWD LIST TERMINATED BY ZERO
	MOVE	T3,I.CHN(P1)	;ASSEMBLE 'IN CH,P2' IN T3
	TDO	T3,[IN P2]	;SO CAN READ DATA WITH XCT T3
DVMOV1:	XCT	T3		;READ NEXT BLOCK OF DATA
	  JRST	DVMOV3		;GOT DATA, GO OUTPUT IT
	MOVE	T3,I.CHN(P1)	;NOW NEED TO SEE IF EOF OR ERROR
	TDO	T3,[STATZ IO.ERR]	;SO ASSEMBLE INSTRUCTION
	XCT	T3		;EOF OR ERROR?
	  JRST	INERR		;ERROR, GIVE UP
	MOVE	T3,I.SIZ(P1)	;RETRIEVE FILE SIZE
	IDIV	T3,T2		;FIND HOW MANY WORDS SHOULD REMAIN
	JUMPE	T4,DVMOV2	;NONE, WE'RE ALL DONE
	MOVN	T4,T4		;T4 HAS COUNT OF DATA IN BUFFER
	HRL	P2,T4		;SO GENERATE AN IOWD TO SEND IT
	OUT	TC,P2		;SEND THE DATA
	  SKIPA			;MADE IT!
	JRST	DVMOV4		;OH WELL, GIVE ERROR
DVMOV2:	PUSHJ	P,DY.RET##	;DONE WITH THE BUFFER, SO FREE IT
	PUSHJ	P,DVRLS.	;CLOSE THE OUTPUT FILE
	POP	P,T1		;RESTORE INPUT CHANNEL
	PUSHJ	P,DVDEL.	;NOW DELETE INPUT FILE
	  JFCL			;DON'T CARE IF FAILED
	SPOP	<P3,P2,P1>	;RESTORE SAVED AC'S
	POPJ	P,		;AND RETURN
;HERE TO OUTPUT NEXT CHUNK OF FILE
DVMOV3:	OUT	TC,P2		;SEND IT
	JRST	DVMOV1		;MADE IT, GET NEXT PIECE OF DATA
DVMOV4:	PUSH	P,[TC]		;TELL WHICH CHANNEL HAD THE ERROR
	.ERR.	(ST,,V%L,L%F,S%F,EOO,<Error on output>)	;

INERR:	.ERR.	(ST,,V%L,L%F,S%F,EOI,<Error on input>)	;
;HERE TO GET PROTECTION CODE RIGHT
;CALLED BY
;	MOVE	T2,NEW DATA BLOCK
;	PUSHJ	P,DVPRO.
;RETURN
;+1	ALWAYS

DVPRO.:	LDB	T3,[POINT 9,I.PRV(T2),8]	;GET USER SUPPLIED CODE
	JUMPN	T3,CPOPJ	;OK
				;BUT WE MUST REPLACE 077 BY STANDARD
	HRROI	T3,<.GTDFL==140>;[606] DEFAULT WORD
	GETTAB	T3,		;[606] GET IT
	  SETZ	T3,		;[606] CERTAINLY NOT SET
	TXNE	T3,<<JD.SDP==1B9>>;[606] USER HAVE DEFAULT PROTECTION?
	TXNN	T3,<<JD.PRT==777B8>>;[606] YES, BUT WE CAN'T HANDLE 0
	JRST	DVPRO1		;[606] NOTHING USEFUL, GET SYS DEFAULT
	ANDX	T3,JD.PRT	;[606] CLEAR EXTRANEOUS BITS
	IORM	T3,I.PRV(T2)	;[606] SET
	POPJ	P,		;[606]

;HERE IF NO DEFAULT PROTECTION OR OLD MONITOR
DVPRO1:	MOVE	T3,[%LDSTP]	;[606] GET STANDARD
	GETTAB	T3,
	  MOVSI	T3,057000	;IN CASE OF FAILURE
	IORM	T3,I.PRV(T2)	;SET IT
	POPJ	P,


;HERE TO RENAME .XPN FILE

XPNREN:	MOVEI	T1,LC		;FROM
	MOVEM	T1,IO.CHN	;SET CHAN#
	PUSHJ	P,DVCHN.##	;T1 = DATA BLOCK
	PUSHJ	P,DVOPN.##	;AND AN OPEN CHAN
	PUSHJ	P,DVNAM.##	;MAKE SURE A GOOD NAME
	MOVEI	T1,LC
	MOVE	T2,IO.PTR+%XC	;POINT TO NEW FILE SPEC
	MOVE	T3,VERNUM	;GET FILE VERSION
	SKIPN	I.VER(T2)	;UNLESS SET BY PREVIOUS SWITCH
	MOVEM	T3,I.VER(T2)	;SET UP FOR RENAME OR ENTER
	MOVE	T2,IO.PTR+%XC	;[606] OUTPUT DATA BLOCK ADDR
	PUSHJ	P,DVPRO.	;[606] GET THE OUTPUT PROTECTION RIGHT
	MOVEI	T2,%XC		;TO
	PUSHJ	P,DVMOV.	;TRY RENAME OR COPY
	SETZM	IO.PTR+LC	;NOT THERE NOW
	POPJ	P,
SUBTTL	HERE WHEN NOT ENOUGH CORE TO LOAD OR EXECUTE JOB

;WHEN THERE IS NOT ENOUGH CORE TO LOAD OR EXECUTE JOB
;BUT USER DID NOT SPECIFY A SAV FILE
;GIVE WARNING AND CREATE A SAV FILE
;AND IF /EXECUTE , RUN IT

JBNC:	MOVEI	T2,F.LEN	;SETUP FAKE FILE SPEC
	PUSHJ	P,DY.GET##	;AS THOUGH WE HAD SEEN /SAVE
	MOVE	P1,T1		;STORE POINTER TO "SCAN" BLOCK
	HLLZ	T2,JOBNUM	;SIXBIT JOBNUMBER
	HRRI	T2,'LNK'	;REST OF NAME
	MOVEM	T2,F.NAME(T1)
	MOVEM	T2,SSNAME	;HERE ALSO
IFE FTEXE,<
	MOVSI	T2,'HGH'	;MARK NON-SHAREABLE
	SKIPN	HL.S2		;IF NO HIGH
	MOVSI	T2,'SAV'	;SO MESSAGE IS CORRECT
>
IFN FTEXE,<
	MOVSI	T2,'EXE'	;SO MESSAGE IS CORRECT
>
	MOVEM	T2,F.EXT(T1)	
	MOVEM	T2,SSEXT	;FOR SAVE FILE
	MOVSI	T2,'DSK'	;MAKE SURE IT GOES ON DSK
	MOVEM	T2,F.DEV(T1)	;INCASE DEFAULTS SCREWED UP BY NOW
	PUSHJ	P,DVOUT.##	;SETUP DATA BLOCK
	  %VC,,.IODPR		;ON FAKE CHAN IN DUMP MODE
	SKIPN	EXECSW		;WANT TO EXECUTE?
	TDZA	T1,T1		;NO
	MOVEI	T1,1		;YES
	PUSHJ	P,@[EXP JBNCM1,JBNCM2](T1)	;PRINT MESSAGE
	JRST	JBSAVE		;AND TREAT AS IF /SAVE SEEN

JBNCM1:	.ERR.	(MS,.EC,V%L,L%W,S%W,NCL,<Not enough core to load job, saved as >)
	.ETC.	(FSP,,,,,%VC)
	POPJ	P,

JBNCM2:	.ERR.	(MS,.EC,V%L,L%W,S%I,NCX,<Not enough core to load and execute job, will run from >)
	.ETC.	(FSP,,,,,%VC)
	POPJ	P,
SUBTTL	HERE TO BLT DOWN AREA AND EITHER GO TO EXECUTION OR  EXIT

;HERE TO CHECK FOR HIGH SEG AND MAKE SURE IT'S ON A K BOUNDARY
JBEXIT:	PUSHJ	P,JOBSET	;SETUP REST OF JOBDAT
	PUSHJ	P,HJBSET	;AND VESTIGIAL JOB DATA AREA
	SKIPN	PAG.S1		;SEE IF PAGING LOW
	SKIPE	PAG.S2		;OR HIGH
	PUSHJ	P,JBCC		;YES, SEE IF ENOUGH CORE
	SKIPE	IO.PTR+%XC	;DO WE WANT .XPN FILE
	SKIPE	IO.PTR+LC	;AND DON'T ALRADY HAVE AN OVERFLOW FILE
	CAIA			;NOT BOTH TRUE
	PUSHJ	P,WRTXPN	;WRITE OUT CURRENT CORE IMAGE
	SKIPE	T1,HC.LB	;ANY HIGH SEG CODE
IFN TOPS20,<
	TRNN	T1,.PGSIZ	;[650] ON A PAGE BOUND ALREADY?
	JRST	JBEX1		;[650] YES, EXPECTED
	SUBI	T1,1001		;[650] NO, FIND NEXT LOWER PAGE
> ;END IFN TOPS20
IFE TOPS20,<
	TDNN	T1,.PGSIZ	;[650] ON A (K/P) BOUND?
	JRST	JBEX1		;[650] YES, WHAT LUCK
	SUB	T1,.PGSIZ	;[650] NO, NEXT LOWER PAGE
	SUBI	T1,2		;[650] 1 FOR EVEN PAGE, 1 FOR LOW END
> ;END OF IFE TOPS20
	IOR.	T1,.PGSIZ	;[650] UP TO CORE BLOCK BOUND
	CAMGE	T1,LC.AB	;ENOUGH SPARE TO BLT DOWN?
	JRST	JBEXUP		;NO MOVE UPWARDS
	ADDI	T1,1		;PUT THE 1 BACK
	HRL	T1,HC.LB	;FROM,,TO BLT POINTER
	MOVE	T2,HC.AB
	SUB	T2,HC.LB	;GET LENGTH
	ADDI	T2,(T1)		;LAST ADD TO BLT
	HRRZM	T1,HC.LB	;NEW LOW BASE
	MOVEM	T2,HC.AB	;NEW HIGH BASE
	BLT	T1,-1(T2)	;MOVE DATA
				;NOW TO ZERO REST OF AREA UP TO K BOUND
	HRRZI	T1,-1(T2)	;GET TOP DATA WORD
	IOR.	T1,.PGSIZ	;[650] UP TO CORE BLOCK BOUND
	SETZM	(T2)		;ZERO FIRST WORD
	HRLI	T2,1(T2)	;FORM BLT POINTER
	MOVS	T2,T2		;RIGHT WAY ROUND
	BLT	T2,(T1)		;ZERO JUNK
	JRST	JBEX1		;NOW FOR REMAP


;HERE TO SEE IF WE CAN GET ENOUGH CORE TO FINISH THIS LOAD
;IF WE CAN DO SO (UNLESS ALREADY ENOUGH)
;IF NOT CREATE A SAVE FILE AND TRY TO RUN IT

P0==P1-1			;TO MAKE CODE EASIER TO READ

JBCC:	MOVE	T1,HL.S2	;GET HIGH SEG STUFF
IFE TOPS20,<
	TDZE	T1,.PGSIZ	;BUT MUST BE IN K OR P
>
IFN TOPS20,<
	TRZE	T1,.PGSIZ
>
	IOR.	T1,.PGSIZ	;SO ROUND UP
	ADD	T1,HC.S1	;ADD HIGHEST DATA LOCATION REQUIRED
	ADD	T1,DY.AB	;TOP OF SPACE WE STILL NEED
IFE TOPS20,<
	TDZE	T1,.PGSIZ	;ROUND UP
>
IFN TOPS20,<
	TRZE	T1,.PGSIZ
>
	IOR.	T1,.PGSIZ	;TO NEXT K OR P
	ADDI	T1,1		;UP TO NEXT BLOCK
	TLNE	T1,-1		;[732] OVERFLOWED INTO THE LH?
	JRST	JBNC		;[732] DO IT THE HARD WAY.
	CAMG	T1,.JBREL	;DO WE HAVE ENOUGH ALREADY?
	JRST	JBGC		;YES, READ IN REST OF TEMP FILE
	CORE	T1,		;NO TRY FOR IT
	  JRST	JBNC		;NO LUCK, DO IT THE HARD WAY
	MOVEI	T1,HG.TAB	;OK, BUT DON'T FORGET TO GIVE IT TO SOMEONE
	SKIPN	TAB.LB(T1)	;USUAL LOOP
	SOJA	T1,.-1
	MOVE	T2,.JBREL
	MOVEM	T2,TAB.UB(T1)
				;FALL INTO JBGC TO READ IN READ IN REST OF TEMP FILE
;HERE TO READ IN HIGH/LOW TEMP FILES
;IN ORDER TO MINIMIZE DSK TRANSFERES CURRENT CODE WILL NOT
;BE OUTPUT AND REREAD, RATHER WE WILL BLT CODE TO CORRECT PLACE
;AND READ IN REST ARROUND IT
;AT THE END THE TEMP FILES WILL BE DELETED

JBGC:	DMOVE	P1,LC.LB	;SAVE THE CURRENT LOCATIONS
	DMOVE	P3,LC.AB	; SO WE CAN MOVE DATA
	MOVE	T1,DY.AB	;TOP OF FIXED AREA
	ADDI	T1,1		;NEXT FREE
	MOVEM	T1,LC.LB	;MAKE LOWEST FOR LOW CODE
	ADD	T1,HC.S1	;HOW MUCH WE NEED
	IORI	T1,.IPM		;BLOCK BOUND
	MOVEM	T1,LC.AB
	IOR.	T1,.PGSIZ	;TO NEXT PAGE FOR REMAP
	MOVEM	T1,LC.UB	;ACCOUNT FOR ALL SPACE
	JUMPE	P2,[HRRZ T1,.JBREL
		MOVEM T1,LC.UB	;IGNORE IF NO HIGH SEG
		JRST	JBGCL]		;BUT RESET UPPER LIMIT
	ADDI	T1,1		;LOWER BOUND FOR HISEG
	MOVEM	T1,HC.LB	;RESET IT
	ADD	T1,HL.S2	;HIGHEST LOC WE NEED
	IORI	T1,.IPM		;BLOCK BOUND
	MOVEM	T1,HC.AB
	IOR.	T1,.PGSIZ	;UPTO PAGE (OR K) BOUND
	MOVEM	T1,HC.UB	;FOR VERY TOP
JBGC1:				;NOW FOR MOVES
				;MAKE TWO SIMPLE TESTS FIRST
				;THEN MOVE IN HIGH AND LOW CODE
	JUMPE	P2,JBGCL	;ONLY LOW CODE TO WORRY ABOUT
	CAMGE	P2,HC.LB	;IF BOTTOM OF CODE IS UNDER WHERE IT SHOULD BE
	JRST	JBGCHU		;MOVE IT UP (TO CORRECT PLACE)
	CAMLE	P3,LC.AB	;IF TOP OF LOW IS ABOVE WHERE IT SHOULD BE
	JRST	JBGCLD		;MOVE LOWER

JBGCH:				;NOW FOR HIGH SEG
	SKIPN	T1,HC.UB	;FIRST GET RID OF EXCESS CORE IF ANY
	MOVE	T1,LC.UB	;NO HIGH USE LOW
	CAMLE	T1,.JBREL	;BUT DON'T WASTE TIME IF ALREADY THERE
	CORE	T1,
	  JFCL			;TOO BAD
	JUMPE	P2,JBGCL	;NO HIGH
	MOVEI	R,HC.IX		;INDEX TO HIGH
	PUSHJ	P,JBGCMV	;MOVE HIGH AREA

JBGCL:				;NOW FOR LOW SEG
	MOVEI	R,LC.IX		;INDEX TO LOW
	PUSHJ	P,JBGCMV	;MOVE CODE AND READ IN REST OF DATA
				;NOW TO ZERO ALL SPACE NOT USED
	MOVEI	R,HC.IX		;START WITH HIGH SEGMENT
	SKIPN	TAB.LB(R)	;IS THERE ONE?
	SUBI	R,1		;NO
JBGCZ:	MOVE	T1,TAB.AB(R)	;LAST LOCATION IN USE 
	CAML	T1,TAB.UB(R)	;CHECK FOR ANY CORE TO ZERO
	JRST	JBGCZ1		;NONE - SO CHECK FOR FINISH
	ADDI	T1,2
	HRLI	T1,-1(T1)	;FORM BLT PTR TO CLEAR UNUSED CORE
	SETZM	T1,-1(T1)	;CLEAR FIRST WORD
	BLT	T1,@TAB.UB(R)	;AND REST
JBGCZ1:	SOJG	R,JBGCZ		;NOW FOR LOW SEG
	POPJ	P,		;RETURN

;HERE TO MOVE CODE FOR EITHER SEG AND READ IN DATA

JBGCMV:	MOVE	T1,TAB.LB(R)	;BASE
	ADD	T1,LW.S0(R)	;PLUS WINDOW OFFSET
	CAME	T1,P0(R)	;IF WHERE WE SHOULD BE DO NOTHING
	PUSHJ	P,[CAMG	T1,P0(R)	;OTHERWISE MOVE UP OR DOWN
		JRST	JBGCD	;DOWN
		JRST	JBGCU]	;UP
				;NOW FOR REST OF CODE
	SKIPN	PAG.S0(R)	;HOWEVER IF THIS SEGMENT NOT PAGED
	POPJ	P,		;WE MUST BE IN RIGHT PLACE ALREADY
	HRRZ	T1,LW.S0(R)	;GET LOWER WINDOW
	SOJL	T1,.+3		;DONE IF WAS ZERO
	SETZM	LW.S0(R)	;NOW POINT TO BASE
	PUSHJ	P,@[EXP LC.IN##,HC.IN##]-1(R)
	MOVE	T1,HC.S0(R)	;HIGHEST DATA WE NEED
	IORI	T1,.IPM		;UP TO BOUND
	CAMG	T1,UW.S0(R)	;IF WE'VE ALREADY GOT IT IN
	JRST	.+5		;JUST IGNORE
	EXCH	T1,UW.S0(R)	;GET BASE
	HRLZI	T1,1(T1)	;FIRST LOC TO READ
	HRR	T1,UW.S0(R)	;LAST
	PUSHJ	P,@[EXP LC.IN##,HC.IN##]-1(R)
				;NOW TO ZERO JUNK AT TOP
	HRRZ	T1,TAB.AB(R)	;TOP IN USE OR KNOWN TO BE ZERO
	CAMN	T1,TAB.UB(R)	;ALL TAKEN?
	POPJ	P,		;YES
	HRLI	T1,1(T1)	;FIRST TO ZERO
	SETZM	1(T1)		;CLEAR IT
	ADDI	T1,2		;FORM BLT PTR
	BLT	T1,@TAB.UB(R)	;ALL THE WAY
	POPJ	P,		;ALL DONE

JBGCHU:				;HERE TO MOVE HIGH UP
				;USUAL REVERSE BLT IN T1-T4
	MOVE	T1,HC.LB	;WHERE BOTTOM SHOULD BE
	SUBI	T1,(P2)		;WHERE IT NOW IS (GIVES DIFF)
	ADD	T1,LW.S2	;ADD IN WINDOW ADDRESS
	MOVE	T4,P4		;FIND LENGTH TO MOVE
	SUBI	T4,-1(P2)
	MOVS	T4,T4		;LENGTH IN LEFT
	HRR	T4,P4		;TOP OF OLD DATA
	TLO	T4,(1B0)	;PREVENT PDLOV
	HRLI	T1,(POP T4,0(T4))
	MOVE	T2,[JUMPL T4,T1]
	MOVE	T3,[JRST JBGCH]
	MOVE	P2,HC.LB	;NOW FIXUP P2
	ADD	P2,LW.S2	;SO WE DON'T MOVE THIS STUFF AGAIN
	JRST	T1		;JUMP INTO FAST LOOP

JBGCLD:				;HERE TO MOVE LOW DOWN
	MOVE	T1,LC.LB	;START OF WHERE LOW CODE GOES
	ADD	T1,LW.S1	;WHERE THIS WINDOW GOES
	MOVE	T2,T1		;COPY SO WE CAN END
	HRL	T1,P1		;BLT WORD
	SKIPN	UW.S1		;MAY NOT BE PAGING
	SKIPA	T2,LC.AB	;SO USE ALL OF AVAILABLE CORE
	ADD	T2,UW.S1	;WHERE IT SHOULD END
	BLT	T1,0(T2)	;MOVE ALL DATA
	MOVE	P1,LC.LB	;FIXUP P1 TO REFLECT CHANGE
	ADD	P1,LW.S1	;SO WE DON'T MOVE AGAIN
	JRST	JBGCH		;NOW DO INTERNAL MOVES

;HERE TO MOVE WINDOW UP IN EITHER AREA
;ENTER WITH R=1 FOR LOW
;R=2 FOR HIGH

JBGCU:				;HERE TO MOVE UP
				;USUAL REVERSE BLT IN T1-T4
	MOVE	T1,TAB.LB(R)	;WHERE BOTTOM SHOULD BE
	SUB	T1,P0(R)	;WHERE IT NOW IS (GIVES DIFF)
	ADD	T1,LW.S0(R)	;ADD IN WINDOW ADDRESS
	MOVE	T4,P2(R)	;FIND LENGTH TO MOVE
	SUB	T4,P0(R)
	ADDI	T4,400001	;PREVENT PDLOV, INCREMENT LENGTH CORRECTLY
	MOVS	T4,T4		;LENGTH IN LEFT
	HRR	T4,P2(R)	;TOP OF OLD DATA
	HRLI	T1,(POP T4,0(T4))
	MOVE	T2,[JUMPL T4,T1]
	MOVSI	T3,(POPJ P,)
	PJRST	T1		;JUMP INTO FAST LOOP

JBGCD:				;HERE TO MOVE DOWN
	SKIPN	PAG.S0(R)	;IF NOT PAGED
	JRST	JBGCN		;USE DIFFERENT ROUTINE
	MOVE	T1,TAB.LB(R)	;START OF WHERE LOW CODE GOES
	ADD	T1,LW.S0(R)	;WHERE THIS WINDOW GOES
	MOVE	T2,T1		;COPY SO WE CAN END
	HRL	T1,P0(R)	;BLT WORD
	ADD	T2,UW.S0(R)	;WHERE IT SHOULD END
	BLT	T1,0(T2)	;MOVE ALL DATA
	POPJ	P,

JBGCN:				;MOVE DOWN WHEN NOT PAGED
	MOVE	T1,TAB.LB(R)	;START OF WHERE LOW CODE GOES
	HRL	T1,P0(R)	;WHERE IT IS NOW
	BLT	T1,@TAB.AB(R)	;MOVE IT ALL
	POPJ	P,
;HERE TO MOVE CODE UP TO A K BOUND SO REMAP WILL WORK

JBEXUP:	MOVE	T4,HC.AB	;TOP
	SUB	T4,HC.LB	;MINUS BOTTOM GIVES LENGTH
	MOVE	T1,LC.AB	;GET TO OF CURRENT AREA
	IOR.	T1,.PGSIZ	;[650] PUT ON BLOCK BOUND
	ADD	T1,T4		;GET NEW TOP
	CAMG	T1,HC.UB	;WILL IT FIT?
	JRST	JXUP1		;YES
	CORE	T1,		;EXPAND
	  PUSHJ	P,NO.COR##	;SHOULD NEVER GET HERE
	MOVE	T1,.JBREL	;GET NEW TOP
	MOVEM	T1,HC.UB	;SET IT
	JRST	JBEXUP		;RESET T4

JXUP1:	MOVE	T3,T4		;GET A COPY
	HRL	T4,T4		;IN BOTH HALVES
	ADD	T4,HC.LB	;TOP OF DATA
	TLO	T4,(1B0)	;PREVENT PDLOV
	MOVE	T1,HC.LB	;GET CURRENT BOTTOM
	IOR.	T1,.PGSIZ	;[650] UP TO BLOCK BOUND
	ADDI	T1,1		;STARTS ON NEXT WORD
	MOVE	T2,T1		;GET COPY
	SUB	T1,HC.LB	;GET OFFSET
	HRLI	T1,(POP T4,0(T4))
	PUSH	P,HC.LB		;SAVE OLD BASE
	MOVEM	T2,HC.LB	;RESET BASE
	ADDI	T3,(T2)		;START + LENGTH
	MOVEM	T3,HC.AB	;AND TOP
	MOVE	T2,[JUMPL T4,T1]	;LOAD INST
	MOVSI	T3,(POPJ P,)	;RETURN
	PUSHJ	P,T1		;JUMP INTO CODE IN ACCS
	POP	P,T1		;GET OLD HC.LB
	SETZM	(T1)		;ZERO FIRST WORD
	HRL	T1,T1
	ADDI	T1,1		;BLT PTR
	MOVE	T2,HC.LB	;NEW LOWER BOUND
	BLT	T1,-1(T2)	;CLEAR JUNK WE LEFT BEHIND
				;FALL INTO JBEX1
JBEX1:	SKIPE	STADDR		;WARN USER IF NO STARTING ADDRESS
	JRST	JBEX10		;IS A STARTING ADDRESS, KEEP GOING
	OUTSTR	[ASCIZ	\[LNKNSA No start address]
\]
JBEX10:	SKIPE	JOBPTR		;NEED TO RESTORE .JBDA?
	PUSHJ	P,BLTJDA	;YES
	SKIPE	JBHPTR		;SAME FOR HIGH
	PUSHJ	P,BLTJHA	;RESTORE FIRST 10 WORDS
	SKIPE	IO.PTR+%XC	;NEED TO RENAME .XPN FILE?
	PUSHJ	P,XPNREN	;YES
	SKIPE	IO.PTR+HC	;HIGH SEG OVERFLOW FILE STILL THERE?
	PUSHJ	P,HC.DLT	;YES, REMOVE IT
	SKIPE	IO.PTR+LC	;SAME FOR LOW SEG
	PUSHJ	P,LC.DLT
	PUSHJ	P,TERMES	;PRINT FINAL MESSAGES
	MOVE	T1,LC.LB	;LOAD UP OFFSET
	MOVE	T2,.JBDDT(T1)	;GET DDT ADDRESS
IFN TOPS20,<
	HRRZ	T1,T2		;GET ADDRESS
	CAIE	T1,770000	;IDDT?
	JRST	JBEX1A		;NO
	MOVE	T2,LC.LB	;GET BASE
	MOVE	T1,.JBSYM(T2)	;
	MOVEM	T1,@770001	;GIVE SYMBOLS TO DDT
	MOVE	T1,.JBUSY(T2)	;
	MOVEM	T1,@770002	;AND UNDEFS
	SETZ	T2,		;AND DON'T STORE IN .JBDDT
JBEX1A:>
;NOW PUT PHASED CODE INTO LOW SEG

	MOVEM	T2,%T4		;SAVE FOR LATER
	MOVE	T1,[%HIGH,,%LOW]	;MOVE PHASED CODE
	BLT	T1,%END		;INTO LOWSEG
	HRLZ	T1,LC.LB	;WHERE WE ARE NOW
	ADD	T1,[20,,20]	;BLT POINTER TO WHERE WE WILL BE
	MOVEM	T1,%0		;STORE BLT POINTER FOR LATER
	MOVE	T1,LC.AB	;WHERE WE WILL END
	SUB	T1,LC.LB	;AFTER BLT
	HRRM	T1,%4		;STORE FOR LATER
IFN TOPS20,<			;IF TENEX, SETUP START VECTOR
	MOVEI	T1,400000	;THIS FORK
	MOVE	T2,STADDR	;ADDRESS
	TLNN	T2,-1		;IF LHS NOT SET, PUT JRST
	HRLI	T2,(JRST)	;IN LEFT
	SEVEC			;SET ENTRY VECTOR
>
	SKIPN	T1,EXECSW	;GET STARTING ADDRESS
	JRST	JBEX0		;DON'T WANT TO START
	HRLI	T1,(JRST)	;COMPLETE INST IF EXECUTING
	TRNN	T1,-1		;WANT TO START, BUT DO WE HAVE A VALID ADDRESS
	SKIPGE	DEBUGSW		;IF /DEB WILL CHECK AT JBEX3
	JRST	JBEX01		;OK
	JRST	JBNEX		;NO, ABORT
JBEX0:	MOVE	T1,[EXIT]	;STOP JOB
JBEX01:	MOVEM	T1,%16		;STORE EXEC OR EXIT
	MOVSI	T1,(JFCL)	;NO-OP
	SKIPE	EXECSW		;IF EXECUTION
	HLLM	T1,%DMES	;EXTRA MESSAGE
	SKIPGE	DEBUGSW		;IF DEBUGGING
	JRST	JBEX3		;CHANGE MESSAGE
	MOVE	T1,LC.LB	;GET BASE OF LOW CODE
	HRRZ	T1,.JBERR(T1)	;ANY ERRORS?
	SKIPE	T1
	SKIPN	EXECSW		;AND USER WANTS EXECUTION?
	JRST	JBEX2		;NO
JBNEX:	MOVE	T1,[EXIT]	;PUT A STOP TO THAT
	MOVEM	T1,%16
	MOVE	T1,%HIGH+%DMES-%LOW
	MOVEM	T1,%DDMES	;SKIP REST OF MESSAGES
	MOVE	T1,[DLTTXT,,%TMES]
	BLT	T1,%TMES+5
JBEX2:	MOVE	T1,LC.LB	;GET BASE OF LOW CODE
	MOVE	T1,.JBVER(T1)	;PICKUP VERSION NUMBER
	MOVEM	T1,%VER		;STORE IT FOR VERSION WATCHING
	SKIPN	T1,HC.AB	;GET REAL TOP OF HIGH SEG
	MOVE	T1,LC.AB	;USE LOWSEG IF NO HIGH
	TLO	T1,1		;ALSO REMOVE CURRENT HIGH SEG
	MOVEM	T1,%T1		;SAVE CORE UUO ARG
	SKIPE	T1,HC.LB	;GET BOTTOM OF HIGH SEG
	SUBI	T1,1		;TOP OF LOW SEG
	HRRZM	T1,%T2		;STORE FOR REMAP
	MOVSI	T2,(CAIA)	;INCASE NO HIGH SEG
	SKIPN	T1
	MOVEM	T2,%REMAP	;OVERWRITE REMAP UUO
	SKIPN	T1,RUNAME	;GET NAME TO CALL CORE IMAGE
	MOVE	T1,LODNAM	;USE DEFAULT IF NOT SET
	SKIPE	%DTXT		;IF NOT ALREADY SET
	JRST	JBEX20		;EITHER DDT OR NO NESSAGE
	MOVE	T3,T1		;GET A COPY
	MOVE	T4,[POINT 7,%DTXT]
	SETZ	T2,		;CLEAR RECEIVING AC
	LSHC	T2,6		;GET NEXT CHAR
	ADDI	T2," "		;INTO ASCII
	IDPB	T2,T4
	JUMPN	T3,.-4		;MORE TO DO
	IDPB	T3,T4		;MAKE SURE A 0 THERE
JBEX20:	MOVEM	T1,%T3		;FOR SETNAM UUO
;HERE TO SETUP ARGS FOR CORE AND REMAP UUO'S

	SKIPE	T1,HL.S1	;GET HIGHEST LOC LOADED +1
	SUBI	T1,1
	IOR.	T1,.PGSIZ	;ROUND UP
	CAMGE	T1,RUNCOR	;MORE THAN USER REQUESTED?
	MOVE	T1,RUNCOR	;NO, USE SUPPLIED VALUE
	MOVEM	T1,%1		;FOR 2ND CORE UUO
	MOVE	T2,HL.S2	;SAME FOR HIGH SEG
	SOJL	T2,JBEX2A	;AS LONG AS THERE IS ONE
	IOR.	T2,.PGSIZ
	CAMGE	T2,RUNCOR+1	;USER SUPPLIED 2ND ARG
	MOVE	T2,RUNCOR+1	;AND MORE THAN WE NEED
	ADDI	T1,1		;TOP OF LOW SEG +1
	CAMGE	T1,LL.S2	;LARGER THAN HI-ORG?
	MOVE	T1,LL.S2	;NO,  SO ASSUME HI-ORG
	CAIE	T1,400000	;CONVENTIONAL HI-ORG?
	HRLM	T1,%T2		;NO, FANCY REMAP UUO FOR V/M
	ADDI	T2,(T1)		;CORE UUO WILL KEEP HISEG
	HRLM	T2,%1		;MAKE SURE CORE UOO CORRECT
JBEX2A:	MOVE	T1,HC.S1	;GET HIGHEST DATA WORD+1
	CAIGE	T1,.JBDA	;BUT DON'T ZERO JOBDAT
	MOVEI	T1,.JBDA
	HRRZ	T2,%1		;GET CORE UUO ADDRESS FOR LOW SEG TOP
	CAML	T1,T2		;IS FIRST FREE LOC IN BOUNDS?
	JRST	[MOVSI	T3,(JFCL)	;NO, ASSUME EQUAL
		CAMG	T1,T2		;IS IT?
		JRST	[MOVEM	T3,%11	;IN WHICH CASE DON'T DO BLT
			JRST	.+1]	;BUT DO ZERO LAST WORD
		MOVSI	T3,(TDZA)	;NO, FIRST FREE LOC IS OUT OF BOUNDS
		MOVEM	T3,%10		;JUST ZERO AC 0
		JRST	JBEX2B]		;AND FORGET FIRST FREE AND BLT
	HRRM	T1,%10		;SET FOR ZEROING
	HRL	T1,T1
	ADDI	T1,1		;FORM BLT PTR
	MOVEM	T1,%2		;TO CLEAR LOW SEG
JBEX2B:	MOVE	T4,[%T1,,T1]	;LOAD ACCS
	BLT	T4,T4
	JRST	%LOW		;GO TO LOW SEG

JBEX3:	MOVE	T1,DEBUGSW	;GET INDEX TO DEBUG NAME
	DMOVE	T1,@DEBNAM(T1)	;GET BOTH WORDS (IF THERE ARE 2)
	DMOVEM	T1,%DTXT	;STORE
	SKIPE	EXECSW		;IF NO EXECUTION
	CAME	T1,[ASCII \COBDD\]	;OR NOT COBDDT
	JRST	JBEX4		;START @.JBDDT
	SKIPN	T1,STADDR	;START COBDDT VIA MAIN PROG
	JRST	JBNEX		;OR GIVE EXECUTION DELETED MESSAGE
	HRLI	T1,(JRST)	;FORM INST
	MOVEM	T1,%16		;SAVE GOTO  ADDRESS
JBEX4:
IFE FTKIONLY,<
	MOVE	T1,[ASCIZ \[LNKDEB \]		;
	MOVE	T1+1,1+[ASCIZ \[LNKDEB \]	;
> ;END IFE FTKIONLY
IFN FTKIONLY,<
	DMOVE	T1,[ASCIZ \[LNKDEB \]		;
> ;END IFN FTKIONLY
	DMOVEM	T1,%TMES
	JRST	JBEX2
;HERE FOR PHASED LOWSEG CODE
;ENTER WITH :-
;T1 = ARG FOR CORE UUO
;T2 = ARG FOR REMAP UUO
;T3 = ARG FOR SETNAM UUO
;T4 = ARG FOR SETDDT UUO

%HIGH:
	PHASE	%LOW
%LOW:	CORE	T1,		;REMOVE HIGH SEG AND EXCESS LOWSEG
	  JFCL			;TOO BAD
%REMAP:	REMAP	T2,		;CHANGED TO SKIPA IF NO HIGH SEG
	  JRST	REMERR		;FAILED
	SKIPA	T1,%VER		;PICK UP VERSION NUMBER
%VER:	.-.			;FROM HERE
	MOVEM	T1,.JBVER	;SO CORRECT VERSION COMES OUT IF WATCHING
	HLRZ	T2,%0		;GET REL 20
	MOVE	T1,.JBREL	;REMEMBER THIS
	MOVEM	T1,.JBREL-20(T2);INCASE CORE UUO NOT DONE
IFE TOPS20,<			;
	MOVE	T1,.JBPFH##	;GET CURRENT PAGE FAULT HANDLER
	EXCH	T1,.JBPFH-20(T2)	;GET USER ONE
	MOVEM	T1,%3		;SO WE CAN SET IT
>				;
	SETNAM	T3,		;FOR ARG WATCHING
	SETDDT	T4,		;CHANGE TO NEW ADDRESS
%DMES:	JRST	%RMES		;PATCH IF NEED MESSAGE
	OUTSTR	%TMES		;INFO INDICATOR
%DDMES:	OUTSTR	%DTXT		;NAME OF DEBUGGER
	OUTSTR	%RTXT		;TELL USER
%RMES:	MOVSI	17,%0		;BLT PTR
IFE TOPS20,<			;
	RESET			;MAKE SURE NO I/O STILL OPEN
>				;
IFN TOPS20,<			;SPECIAL IF TENEX DDT
	MOVEI	T1,400000	;THIS FORK
	DIR			;
	CIS			;
	MOVSI	T1,(JFCL)	;[644] REPLACE WITH JFCL IF DESIRED
	MOVE	T2,%16		;[644] GET IT
	CAMN	T2,%EXIT	;[644] EXIT? RATHER THAN START ADDR
	MOVEM	T1,%7		;[644] YES, REPLACE RESET WITH JFCL
>
	BLT	17,17		;[644] LOAD ACCS
	JRST	4		;[644] GO THERE

%EXIT:	EXIT			;[644] THIS IS COMPARED WITH CONTENT OF %16

%TMES:	ASCIZ	\[LNKXCT \
%DTXT:	EXP	0,0		;ENOUGH FOR 6 CHARS PLUS NULL
%RTXT:	ASCIZ	\ Execution]
\

REMERR:	TLZN	T2,-1		;REMAP FOR V/M?
	JRST	REMER1		;NO, OR FAILED TWICE
	HRRZS	%1		;MAKE SURE CORE UUO IN BOUNDS
	SKIPA	T1,.+1		;STOP EXECUTION
	EXIT			;WITH AN EXIT
	MOVEM	T1,%16		;IF IT WAS ON
	OUTSTR	%VMRERR		;WARN USER
	JRST	%REMAP		;NOW TRY AGAIN
REMER1:	OUTSTR	%RMPE		;ERROR MESSAGE
	EXIT
%RMPE:	ASCIZ	\?LNKRME	REMAP error\
%VMRER:	ASCIZ	\%LNKRME	REMAP error, high segment origin incorrect
\

%0:	.-.			;BLT POINTER
%1:	.-.			;CORE UUO
%2:	.-.			;ZERO CORE BLT PTR
%3:	.-.			;PFH
%4:	BLT	0,.-.		;BLT LOWSEG DOWN
%5:	CORE	1,		;ADJUST CORE
%6:	  JFCL			;SHOULD NOT FAIL
IFE TOPS20,<			;
%7:	MOVEM	3,.JBPFH##	;SET PAGE FAULT HANDLER
>				;
IFN TOPS20,<			;
%7:	JSYS	147		;TENEX RESET, FLUSH PA1050
>				;
%10:	SETZB	0,.-.		;CLEAR FIRST WORD
%11:	BLT	2,@.JBREL	;AND REST
%12:	MOVEM	15,.JBBLT	;LOAD .JBBLT AT LAST MINUTE
%13:	MOVEM	16,.JBBLT+1
%14:	JRST	.JBBLT		;JUMP INTO EXEC PDL
%15:	BLT	17,17		;CLEAR ALL ACCS
%16:	.-.			;START OR EXIT
%17:	0,,1			;FINAL BLT PTR TO CLEAR ACCS
%END:
	DEPHASE

%T1==%END+0
%T2==%T1+1
%T3==%T2+1
%T4==%T3+1

SUBTTL	DATA AREAS

.ZZ==.TEMP
U	(LSCNT)			;COUNT OF WORDS LEFT IN THIS 128 WORD BLOCK
U	(TTLPTR)		;BACK POINTER TO LAST SUBPROGRAM
U	(LCSIZE)		;SIZE OF LOCAL SYMBOL FILE
U	(JOBPTR)		;POINTER TO COPY OF JOBDAT AREA
U	(JBHPTR)		;DITTO FOR HIGH SEG
U	(LSTPAG)		;-1 WHEN LAST PAGE IS IN CORE
U	(ERRNO)			;.JBERR COUNT
U	(JOB116)		;.JBSYM FOR .SYM FILE
U	(JOB117)		;.JBUSY FOR .SYM FILE
U	(SCRTCH)		;POINTER TO A SCRATCH PAGE


XITLIT:
END	LNKXIT