Google
 

Trailing-Edge - PDP-10 Archives - bb-d868c-bm_tops20_v4_2020_distr - language-sources/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/DZN	24-Aug-79


;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, 1979 BY DIGITAL EQUIPMENT CORPORATION


SEARCH	LNKPAR,LNKLOW,MACTEN,UUOSYM
IFN TOPS20,<SEARCH	MACSYM, MONSYM>
SALL

ENTRY	LNKXIT
EXTERN	LNKCOR,LNKLOG,LNKFIO
EXTERN	.JB41


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

VERSION


SEGMENT


;LOCAL ACC DEFINITION
R==R1
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)
;START OF VERSION 4A
;770	Add code to allow first-time paging in und-symbol table routine.
;772	Adjust symbol table pointer to after undefined symbol table.
;773	Fix GSDLT in case the GS area is already gone.
;774	Fix bad calculation of UW in EXE file writer.
;776	Fix /SAVE of small program with no data in pages 0 or 1.
;1110	Output PSECT name as part of error message in GETSST.
;1111	Fix core management bug introduced by edit 772.
;1113	See that LINK doesn't shrink on TOPS-20 until really necessary.
;1121	Fix edit 772 so symbol table and undefined table don't overlap.
;1125	Don't try to do a RUN UUO to the hiseg file when generating an EXE file.
;1127	Set up the module length for PAT.. in the runtime symbol table.
;1132	Teach the EXE file writer about PSECTs above the high segment.
;1144	Zap PA1050 but not DDT on /EXECUTE, /DEBUG when running from .EXE file.
;1145	Set up symbol table pointers on TOPS-20 if no .EXE file written; broken by 1144.
;1146	Force writing an .EXE file more often, especially with PSECTs.
;1147	Adjust LC.LB when adjusting LW.S1 in JBEXE.  Broken by 732.
;1152	Set RC.HL for .LOW. during initialization when loading overlays.
;1160	Don't put junk in the undefined table when symbol used in Polish.
;1170	Fix core management problems when not writing an EXE file.
;1171	Fix edit 1146 to say LNKPCL if bad PSECT properties, even on TOPS-10.
;1172	Fix many problems with runtime symbol table generator.
;1174	Label and clean up all error messages.
;1202	Fix problems introduced by edits 1172 and 1174.
;1212	Use E$$SOE label instead of ZCMP7E, broken by 1174 (in off conditional).
;1214	Fix unmatched angle bracket bug in .EXE file code.
;1216	Preserve P acs in SYMOUT.
;1217	Clean up the listings for release.
;1220	Release on both TOPS-10 and TOPS-20 as version 4A(1220).
SUBTTL	ENTER HERE


LNKXIT:	JFCL	.+1		;IN CASE CCL ENTRY
E$$EXS::.ERR.	(MS,0,V%L,L%I,S%I,EXS,<EXIT segment>) ;[1174]
	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,E$$IOV##	;[1174] INPUT ERROR
	HRRZM	T1,HL.S1
	HLRZM	T1,HC.S1
	MOVEI	R,1		;[1152] LOW SEGMENT
	MOVE	R,@RC.TB	;[1152] POINTER TO RC BLOCK FOR LC AREA
	HRRZM	T1,RC.CV(R)	;[1152] SAVE AS CURRENT VALUE OF RELOC COUNTER
	HRRZM	T1,RC.HL(R)	;[1152] AND FIRST FREE BEYOND ROOT
	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,E$$IOV##	;[1174]
	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	CHKRST		;[1172] NOW GO DO RUNTIME SYMBOL TABLE
;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
	PUSHJ	P,E$$IHC##	;[1174] DIE WITH ERROR

;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
	PUSHJ	P,E$$ILC##	;[1174] DIE WITH ERROR


;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	RUNTIME SYMBOL TABLE GENERATION


;HERE TO DECIDE IF WE WANT TO PUT A RUNTIME SYMBOL TABLE INTO THE
;IMAGE, AND IF SO, TO DO IT.  WE WANT A RUNTIME SYMBOL TABLE IF ANY
;OF THE FOLLOWING CONDITIONS ARE TRUE:
;
; 1.	C(.JBDDT) IS NONZERO
; 2.	USER SAID /SYMSEG
; 3.	USER SAID /SYFILE:RADIX50
;
;IF THE USER SAID /NOSYMBOLS, WE NEVER WANT A RUNTIME SYMBOL TABLE.

CHKRST:	SKIPE	PAG.S1		;[1172] FIND JOBDAT
	SKIPA	T1,JOBPTR	;[1172] IN DY IF PAGING
	MOVE	T1,LC.LB	;[1172] IN LC AREA IF NOT
	SKIPN	T2,VERNUM	;[1202] /VERSION? (CHECK NOW FOR OLDSYM)
	SKIPA	T2,.JBVER(T1)	;[1202] NO, FETCH FROM .JBVER
	MOVEM	T2,.JBVER(T1)	;[1202] OVERRIDE IF /VERSION
	MOVEM	T2,VERNUM	;[1202] STORE FOR SYMBOL FILES
	SETZM	.JBSYM(T1)	;[1172] ASSUME NO SYMBOLS
	SETZM	.JBUSY(T1)	;[1172]   ..
	SKIPE	NOSYMS		;[1172] /NOSYMBOLS?
	JRST	NORST		;[1172] YES, FORGET IT
	SKIPN	.JBDDT(T1)	;[1172] C(.JBDDT) <> 0?
	SKIPE	SYMSEG		;[1172] OR USER SAY /SYMSEG?
	JRST	DORST		;[1172] YES, GO DO IT!
	SKIPL	SYMFRM		;[1172] /SYFILE:RADIX50?
	JRST	NORST		;[1172] NOPE, NO SYMBOL TABLE

;  ..
;  ..

;HERE TO GENERATE A RUNTIME SYMBOL TABLE.
;FIRST, MAKE SURE THE AREA (LC/HC) THAT THE SYMBOLS ARE GOING
;INTO IS BIG ENOUGH, OR IS PAGING AND THE RIGHT PAGE IS IN.

DORST:
IFN FTOVERLAY,<
	SKIPL	LNKMAX		;[1172] LOADING OVERLAYS?
	JRST	OVLRST		;[1172] YES, THINGS ARE DIFFERENT
> ;END IFN FTOVERLAY

E$$SST::.ERR.	(MS,0,V%L,L%I,S%I,SST,<Sorting symbol table>) ;[1174]
	PUSHJ	P,GETSST	;[1172] FIND BASE OF SYMBOLS, SET R AND P4
	SKIPE	PAG.S0(R)	;[1172] SYMBOL SEGMENT PAGING?
	JRST	DORST2		;[1172] YES, GO GET THE RIGHT PAGE INTO MEMORY
	MOVE	P2,RC.HL(P4)	;[1172] GET FIRST WORD OF TABLE
	SUB	P2,LL.S0(R)	;[1172] CONVERT TO OFFSET IN SEGMENT
	SUB	P2,LW.S0(R)	;[1172] THENCE TO OFFSET IN WINDOW
	ADD	P2,TAB.LB(R)	;[1172] FIRST ADDRESS WE'RE GOING TO STORE INTO
	CAMG	P2,TAB.AB(R)	;[1172] IS THE AREA BIG ENOUGH?
	JRST	DORST4		;[1172] YES, GO FILL IT IN
	MOVE	P1,R		;[1172] WHICH AREA TO EXPAND
	SUB	P2,TAB.AB(R)	;[1172] HOW MUCH WE NEED
	PUSHJ	P,LNKCOR	;[1172] EXPAND THE AREA
	  JRST	DORST2		;[1172] FINE, JUST START PAGING
	JRST	DORST3		;[1172] GO CHECK PAGING FOR THE FIRST TIME
;HERE IF PAGING TO BRING THE RIGHT LC/HC PAGE INTO MEMORY.

DORST2:	PUSHJ	P,LSYP		;[1172] NOW PAGING, GET RIGHT PAGE IN MEMORY
DORST3:	PUSHJ	P,CHKPAG	;[1172] SEE IF WE JUST STARTED PAGING
DORST4:	MOVE	T1,RC.HL(P4)	;[1172] NOW TO SET UP XX.PT
	SUB	T1,LL.S0(R)	;[1172] FIRST ADDRESS TO STORE INTO
	SUB	T1,LW.S0(R)	;[1172] CONVERT TO OFFSET IN AREA
	ADD	T1,TAB.LB(R)	;[1172] ADDRESS IN AREA
	MOVEM	T1,TAB.PT(R)	;[1172] STORE FOR SYMOUT


;OK, EVERYTHING IS INITIALIZED.  NOW WRITE OUT THE SYMBOL TABLE(S).

	SKIPE	USYM		;[1172] ANY UNDEFINED SYMBOLS?
	PUSHJ	P,DOUDFS	;[1172] YES, WRITE THEM OUT
	PUSHJ	P,GSDLT		;[1172] DELETE THE GS AREA
	SKIPN	SYMFUL		;[1172] IF ANY ROOM LEFT
	PUSHJ	P,DOLOCS	;[1172] WRITE THE LOCAL SYMBOLS OUT


;THE SYMBOLS HAVE BEEN WRITTEN.  NOW UPDATE THE HL/HC WORDS, THEN GO CLEAN UP.

	MOVE	T1,TAB.PT(R)	;[1172] NEXT FREE WORD
	SUB	T1,TAB.LB(R)	;[1172] OFFSET IN WINDOW
	ADD	T1,LW.S0(R)	;[1172] OFFSET IN SEGMENT
	CAMLE	T1,HL.S0(R)	;[1172] BIGGEST WE'VE SEEN?
	MOVEM	T1,HL.S0(R)	;[1172] YES, STORE IT
	CAMLE	T1,HC.S0(R)	;[1172] BIGGEST LOADED LOC?
	MOVEM	T1,HC.S0(R)	;[1172] YES, STORE IT
	ADD	T1,LL.S0(R)	;[1172] FORM VIRTUAL ADDRESS
	CAMLE	T1,RC.HL(P4)	;[1172] BIGGEST YET FOR THIS PSECT?
	MOVEM	T1,RC.HL(P4)	;[1172] YES, REMEMBER IT
	SKIPGE	SYMFRM		;[1172] OLD STYLE SYMBOL FILE WANTED?
	PUSHJ	P,OLDSYM	;[1172] YES, WRITE IT OUT
E$$STC::.ERR.	(MS,0,V%L,L%I,S%I,STC,<Symbol table completed>) ;[1174]
	JRST	FINRST		;[1172] GO JOIN COMMON CLEAN UP CODE
;HERE WHEN LOADING OVERLAYS.

IFN FTOVERLAY,<
OVLRST:	HLRE	T2,PH.RDX	;[1172] GET - NO. OF SYMBOLS
	MOVM	T3,T2		;[1172] +
	ADD	T3,HL.S1	;[1172] HIGHEST LOCATION
	ADD	T3,SPACE	;[1172] PLUS BUFFER SPACE
	IOR.	T3,.PGSIZ	;[1172] UP TO PAGE BOUND
	ADDI	T3,1		;[1172] NEXT FREE
	ADD	T3,T2		;[1172] START OF SYMBOLS
	HLL	T3,PH.RDX	;[1172] - COUNT
	MOVEM	T3,JOB116	;[1172] STORE IN INTERNAL PTR
	MOVEM	T3,.JBSYM(T1)	;[1172] STORE SYMBOL TABLE PTR
> ;END IFN FTOVERLAY


;HERE IF NOT WRITING A RUNTIME SYMBOL TABLE.  JUST DELETE LINK'S TABLES.

NORST:	PUSHJ	P,GSDLT		;[1172] GET RID OF THE GS AREA
	; ..
	; ..

;ALL PATHS REJOIN HERE.  DELETE TABLES, SET UP JOBDAT, AND EXIT.

FINRST:	SKIPLE	T1,SYMFRM	;[1172] WANT NEW STYLE SYMBOL FILE?
	PUSHJ	P,SAVSYM	;[1172] YES, WRITE IT OUT
	PUSHJ	P,AS.ZAP	;[1172] DONE WITH AS AREA
	MOVEI	T1,AC		;[1172] ALGOL SYMS CHANNEL
	SKIPE	PAG.AS		;[1172] AREA PAGING?
	PUSHJ	P,DVDEL.##	;[1172] YES, DELETE OVERFLOW FILE
	  JFCL			;[1172] DON'T CARE
	PUSHJ	P,FX.ZAP	;[1172] DONE WITH FX AREA

IFN FTOVERLAY,<
	SKIPL	LNKMAX		;[1172] LOADING OVERLAYS?
	JRST	FINRS2		;[1172] YES, SAVE LS AREA
> ;END IFN FTOVERLAY

	PUSHJ	P,LS.ZAP	;[1172] KILL OFF THE LS AREA
	MOVEI	T1,SC		;[1172] LS OVERFLOW CHANNEL
	SKIPE	PAG.LS		;[1172] LS AREA PAGING?
	PUSHJ	P,DVDEL.##	;[1172] YES, DELETE OVERFLOW FILE
	  JFCL			;[1172] WASN'T PAGING


;NOW UPDATE JOBDAT, THEN EXIT VIA SAVTST.

FINRS2:	SKIPE	PAG.S1		;[1172] LC AREA PAGING?
	SKIPA	P1,JOBPTR	;[1172] YES, JOBDAT IS IN DY
	MOVE	P1,LC.LB	;[1172] NO, IT'S IN LC
	SKIPE	PAG.S2		;[1172] HC AREA?
	SKIPA	P2,JBHPTR	;[1172] YES, FETCH DY PTR
	MOVE	P2,HC.LB	;[1172] NO, FETCH HC PTR (OR 0)
	PUSHJ	P,JOBSET	;[1172] SET UP JOBDAT
	PUSHJ	P,HJBSET	;[1172] VESTIGAL JOBDAT
	JRST	SAVTST		;[1172] DONE WITH CHKRST, GO CHECK /SAVE
;GETSST - ROUTINE TO FIGURE OUT WHERE THE SYMBOL TABLE GOES
;CALLED ONLY WHEN A RUNTIME SYMBOL TABLE IS DEFINITELY NEEDED.
;RETURNS WITH:
;
;	SSGNAM/		NAME (SIXBIT) OF PSECT TO APPEND SYMBOLS TO
;	R/		AREA PSECT IS IN, LC.IX OR HC.IX
;	P4/		POINTER TO RC BLOCK OF PSECT NAMED IN SSGNAM
;	RC.HL(P4)/	FIRST ADDRESS TO STORE A SYMBOL IN
;	SYMLIM/		LAST ADDRESS TO STORE A SYMBOL IN
;
;ALSO UPDATES LOWLOC IF NECESSARY.

GETSST:	SKIPGE	R,SYMSEG	;[1172] /SYMSEG TO A PSECT?
	JRST	GETS10		;[1132] YES, GO FIND IT
GETS2:	CAIN	R,2		;[1172] /SYMSEG:HIGH?
	JRST	GETS8		;[1172] YES, TREAT IT LIKE /SYMSEG:PSECT:.HIGH.


;HERE IF /SYMSEG:LOW OR NO /SYMSEG (E.G., C(.JBDDT<>0).
;WE WANT TO APPEND PAT.. AND THE SYMBOL TABLE TO THE LAST PSECT IN THE IMAGE.
;OUR FIRST MISSION IS TO FIND THAT PSECT...

	SETZB	R,T3		;[1172] INIT HIGHEST ADDR AND PSECT IDX
GETS4:	MOVE	T1,@RC.TB	;[1172] GET POINTER TO RC BLOCK OF NEXT PSECT
	MOVE	T2,RC.SG(T1)	;[1172] GET THE SEGMENT THAT THIS PSECT IS IN
	CAIE	T2,1		;[1172] IN THE LOW SEGMENT?
	JRST	GETS6		;[1172] NO, IT DOESN'T COUNT FOR /SYMSEG:LOW
	MOVE	T2,RC.HL(T1)	;[1172] GET THE FIRST FREE AFTER THIS PSECT
	CAMG	T2,T3		;[1132] HIGHEST SO FAR?
	JRST	GETS6		;[1132] NO, CONTINUE
	MOVE	T3,T2		;[1132] SAVE NEW BEST
	MOVE	T4,R		;[1132] AND WHAT PSECT IT WAS
	MOVE	T2,RC.NM(T1)	;[1172] GET THE WINNER'S NAME
	MOVEM	T2,SSGNAM	;[1172] STORE FOR ERROR MESSAGES
GETS6:	CAMGE	R,RC.NO		;[1132] ALL DONE?
	AOJA	R,GETS4		;[1132] NO, LOOP
	MOVE	R,T4		;[1132] YES, SAVE PSECT INDEX OF LAST ONE
	JRST	GETS14		;[1132] GO UPDATE THAT PSECT
;HERE ON /SYMSEG:HIGH.  FAKE /SYMSEG:PSECT:.HIGH. AND FALL INTO PSECT CODE.

GETS8:	MOVE	T1,['.HIGH.']	;[1132] /SYMSEG:HIGH IS JUST LIKE A PSECT
	MOVEM	T1,SSGNAM	;[1132] STORE


;HERE ON /SYMSEG:PSECT:xxxxxx.  FIND THE PSECT IN THE RC TABLES.

GETS10:	SETZ	R,		;[727] YES, HAVE PSECT NAME
GETS12:	MOVE	T1,@RC.TB	;[1132]
	MOVE	T1,RC.NM(T1)	;[1132] GET PSECT NAME
	CAMN	T1,SSGNAM	;[1132] IS THIS THE ONE?
	JRST	GETS14		;[1132] YES,
	ADDI	R,1		;[715] NEXT ONE
	CAMG	R,RC.NO		;[715] ANY MORE?
	JRST	GETS12		;[1132] YES, LOOP
E$$NPS::.ERR.	(MS,.EC,V%L,L%W,S%W,NPS,<Non-existent psect >)	;[1110] ;[1174]
	.ETC.	(SBX,.EC!.EP,,,,SSGNAM)	;[1174] OUTPUT PSECT NAME
	.ETC.	(STR,,,,,,< specified for symbol table>) ;[1174]
	MOVEI	R,1		;[1132] SET TO LOW
	MOVEM	R,SYMSEG	;[1132]
	JRST	GETS2		;[1132] AND LOOP BACK
;HERE WITH THE PSECT INDEX TO USE IN R, AND ITS NAME IN SSGNAM.
;WE NOW WANT TO CALCULATE HOW FAR THE SYMBOL TABLE IS ALLOWED TO EXTEND.
;BELIEVE THE USER'S /UPTO SWITCH IF HE GAVE ONE, OTHERWISE STOP ONE BELOW
;THE NEXT PSECT ORIGIN WE WOULD CROSS, OR STOP AT 777777 IF NO MORE PSECTS.

GETS14:	MOVE	P4,@RC.TB	;[1172] POINTER TO THIS PSECT'S RC BLOCK
	SKIPE	SYMLIM		;[1172] USER TYPE /UPTO?
	JRST	GETS20		;[1172] YES, BELIEVE IT
	MOVE	T4,RC.HL(P4)	;[1172] ADDR OF START OF PATCH AREA
	ADDI	R,1		;[1172] START THE SEARCH AT THE NEXT PSECT


;LOOP BACK HERE ON EACH NEW PSECT, LOOKING FOR ONE WHOSE ORIGIN
;IS .GE. C(T4).

GETS16:	CAMLE	R,RC.NO		;[1172] CHECKED THEM ALL YET?
	JRST	GETS18		;[1172] YES, GO USE 777777
	MOVE	T1,@RC.TB	;[1172] GET PSECT'S RC BLOCK
	MOVE	T2,RC.IV(T1)	;[1172] GET ORIGIN OF THIS PSECT
	CAMGE	T2,T4		;[1172] START ABOVE THE SYMSEG PSECT?
	AOJA	R,GETS16	;[1172] NO, MUST HAVE BEEN OVERLAPPING PSECT
	MOVE	T3,RC.HL(T1)	;[1172] YES, CHECK FOR ZERO-LENGTH PSECT
	CAMG	T3,T2		;[1172] WOULD WE OVERWRITE ANYTHING?
	AOJA	R,GETS16	;[1172] NO, IGNORE THIS PSECT
	SOSA	T2		;[1172] YES, LAST ADDR TO USE IS ONE LESS
GETS18:	MOVEI	T2,777777	;[1172] NO MORE PSECTS, USE END OF SECTION 0
	MOVEM	T2,SYMLIM	;[1172] STORE NEWLY CALCULATED LIMIT


;NOW SET UP SOME FINAL THINGS FOR THE REST OF LINK, THEN RETURN.

GETS20:	MOVE	R,RC.SG(P4)	;[1172] FETCH SEGMENT INDEX FOR PSECTS
	MOVE	T1,RC.HL(P4)	;[1172] START OF PATCH AREA
	MOVEM	T1,PATLOC	;[1172] REMEMBER FOR RST
	ADD	T1,PATSPC	;[1172] START OF REAL SYMBOL TABLE
	MOVEM	T1,RC.HL(P4)	;[1172] UPDATE SIZE OF PSECT
	TRZ	T1,777		;[1172] ROUND DOWN TO PAGE BOUND
	CAMGE	T1,LOWLOC	;[1172] LOWEST LOCATION YET LOADED?
	MOVEM	T1,LOWLOC	;[1172] YES, SAVE FOR EXE FILE WRITER.
	POPJ	P,		;[1172] END OF GETSST
;HERE IF PAGING TO SETUP LC/HC AREA TO INSERT SYMBOLS INTO.
;WRITE OUT ENTIRE WINDOW, THEN SET UP LAST PAGE ONLY.
;AREA WILL EXPAND AS REQUIRED IN SYMOUT.

LSYP:	HRLZ	T1,LW.S0(R)	;[1172] BOTTOM OF WINDOW
	HRR	T1,UW.S0(R)	;[1172] TOP
	PUSHJ	P,@TB.OUT##(R)	;[1172] WRITE ENTIRE WINDOW TO DISK
	MOVE	T1,TAB.AB(R)	;[1172] REDUCE WINDOW TO ONE PAGE
	ANDCMI	T1,.IPM		;[1172] NEW BOTTOM OF AREA
	SUBI	T1,1		;[1172] FIRST WORD BELOW NEW BASE
	CAML	T1,TAB.LB(R)	;[1172] AREA ALREADY ONE PAGE?
	PUSHJ	P,GBCK.L##	;[1172] NO, SHRINK IT DOWN
	MOVE	T1,RC.HL(P4)	;[1172] GET FIRST ADDR TO STORE A SYMBOL IN
	SUB	T1,LL.S0(R)	;[1172] RELATIVE TO SEGMENT START
	ANDCMI	T1,.IPM		;[1172] NEW BOTTOM OF WINDOW
	MOVEM	T1,LW.S0(R)	;[1172] STORE
	IORI	T1,.IPM		;[1172] NEW TOP OF WINDOW
	CAMN	T1,UW.S0(R)	;[1172] WHERE IT WAS ALREADY?
	POPJ	P,		;[1172] YES, DONE
	MOVEM	T1,UW.S0(R)	;[1172] NO, MUST READ IN THE DATA
	HRL	T1,LW.S0(R)	;[1172] FORM TRANSFER WORD
	PJRST	@TB.IN(R)	;[1172] READ IN DATA AND RETURN
;HERE TO WRITE THE UNDEFINED SYMBOL TABLE.  THE TABLE IS GENERATED
;BY SCANNING THE GLOBAL SYMBOL TABLE LOOKING FOR UNDEFINED SYMBOLS.
;WE GENERATE ONE RADIX50 PAIR FOR EACH UNDEFINED SYMBOL, AND ADDITIONAL
;PAIRS IF ANY ADDITIVE FIXUPS ARE ENCOUNTERED.
;
;THE ONLY FIXUP TYPES HANDLED ARE ADDITIVE AND RIGHT AND LEFT HALF CHAINED.
;OTHER TYPES, SUCH AS SYMBOL FIXUPS AND POLISH, ARE DISCARDED HERE.  THIS
;IS DUE TO LACK OF A SYMBOL TABLE FORMAT SPEC, AND LACK OF DDT SUPPORT.
;
;ENTERED WITH:
;
;	P4/	POINTER TO RC BLOCK OF /SYMSEG PSECT
;	R/	INDEX TO /SYMSEG AREA, LC OR HC


DOUDFS:	MOVE	T1,TAB.PT(R)	;[1172] LINK'S ADDRESS OF NEXT WORD
	SUB	T1,TAB.LB(R)	;[1172] FIND OFFSET IN WINDOW
	ADD	T1,LW.S0(R)	;[1172] FIND OFFSET IN SEGMENT
	ADD	T1,LL.S0(R)	;[1172] FORM ABSOLUTE ADDRESS
	HRLZM	T1,JOB117	;[1172] STORE IN LH(JOB117) FOR A WHILE
	SETZM	SYMDEW		;[1172] DON'T NEED EXTRA ROOM FROM SYMOUT
	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
	PUSHJ	P,SYMOUT	;[1172] STORE W2/W3 IN IMAGE
	  JRST	UDFDN		;[1172] NO MORE ROOM, CLOSE UP SHOP
	AOS	JOB117		;[1172] ANOTHER ONE STORED, BUMP COUNT
	TXNE	W1,PS.FXP	;ANY ADDITIVE GLOBAL FIXUPS
	JRST	UDFGB		;YES, RECREATE THE REQUESTS
	JRST	UDFNXT		;[1172] NO, LOOK FOR ANOTHER SYMBOL
;THE LOOP BELOW FINDS THE S.FXP TRIPLET IN THE GS AREA, THEN CHASES
;THE CHAIN OF FIXUPS DEPENDING ON THIS SYMBOL THROUGH THE FX AREA,
;WRITING UNDEFINED SYMBOL TABLE ENTRIES FOR APPLICABLE FIXUPS AS IT GOES.
;
;ENTER AT UDFGB.

UDFGB0:	TXNE	W1,S.LST	;IS THIS THE LAST BLOCK
	JRST	UDFNXT		;[1172] 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	T1,.L+2(T1)	;[1172] GET VALUE
UDFGB1:	ADD	T1,FX.LB	;RELOCATE IN FIXUP TABLE
	SKIPL	W1,0(T1)	;GET FLAGS
	JRST	UDFERR		;JUST INCASE
	TXNE	W1,FP.SYM	;[1160] FIXUP BASED ON UNDEFINED SYMBOL?
	TXNN	W1,FS.FXR!FS.FXL ;[1160] CAN ONLY PUT OUT RH OR LH ADDITIVE
	JRST	UDFGB2		;[1160] CAN'T OUTPUT POLISH, SYM FIXUPS, ETC.
	DMOVE	W2,1(T1)	;GET DATA WORDS
	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
	PUSHJ	P,SYMOUT	;[1172] WRITE W2/W3 INTO THE IMAGE
	  JRST	UDFDN		;[1172] SPACE EXCEEDED, STOP
	AOS	JOB117		;[1172] OK, WROTE ANOTHER ONE
UDFGB2:	HRRZ	T1,W1		;GET POINTER
	JUMPE	T1,UDFNXT	;[1172] ALL DONE IF ZERO
	JRST	UDFGB1		;GET NEXT BLOCK


;HERE WHEN AN UNDEFINED SYMBOL WITH PS.FXP SET IS NOT FOLLOWED BY A
;SECONDARY TRIPLET WITH S.FXP SET.

UDFERR:	JRST	UDFNXT		;[1172] SYMBOL TABLE FOULED UP
;HERE WHEN FINISHED WRITING THE UNDEFINED SYMBOL TABLE.
;SET UP .JBUSY AND RETURN.

UDFDN:	SKIPE	PAG.S1		;[1172] PAGING?
	SKIPA	T1,JOBPTR	;[1172] YES, LOAD CORRECT OFFSET
	MOVE	T1,LC.LB	;[1172] CODE OFFSET
	HRRZ	T2,JOB117	;[1172] GET NUMBER OF UNDEFINED SYMBOLS
	IMULI	T2,-2		;[1172] 2 WORDS/SYMBOL, WANT NEGATIVE
	HRRM	T2,JOB117	;[1172] FORM ADDR,,-LEN
	MOVSS	T2,JOB117	;[1172] FORM -LEN,,ADDR
	MOVEM	T2,.JBUSY(T1)	;[1172] STORE IN IMAGE
	POPJ	P,		;[1172] DONE WITH UNDEFINED TABLE, RETURN
;SUBROUTINE TO DELETE THE GS AREA, AND CUT BACK MEMORY IF POSSIBLE.

GSDLT:
IFE TOPS20,<			;[1113] DON'T SHRINK BACK ON TOPS-20
	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
	SKIPN	GS.LB		;[773] GS AREA ALREADY GONE?
	JRST	GSDLT1		;[773] YES, DON'T RECREATE IT
	MOVEM	T2,GS.AB	;RESET TABLE
	MOVEM	T2,GS.UB
	CAMLE	T2,GS.LB	;INCASE WE REDUCED IT ALL
	JRST	E$$RED		;[1174] NO, ALL IS WELL
GSDLT1:	MOVEM	T2,TAB.UB(T1)	;[773] RESET HIGHEST FREE LOC AGAIN
	SETZM	GS.LB		;SO XX.ZAP CAN WORK
E$$RED::.ERR.	(MS,.EC,V%L,L%I,S%I,RED,<Reducing low segment to >) ;[1174]
	.ETC.	(COR,.EP,,,,.JBREL)
> ;END OF IFE TOPS20
GSNRED:	PUSHJ	P,GS.ZAP	;GET RID OF GS
	POPJ	P,		;[1172] END OF GSDLT
;HERE TO WRITE THE DEFINED SYMBOLS INTO THE IMAGE.

DOLOCS:	SKIPE	PAG.LS		;[1172] PAGING?
	PUSHJ	P,SYMINI	;[1172] YES, SET WINDOW TO END OF LS AREA
	MOVEI	T1,2		;[1172] NEED ENOUGH WARNING TO PUT A TITLE OUT
	MOVEM	T1,SYMDEW	;[1172] STORE FOR SYMOUT
	MOVE	T1,TAB.PT(R)	;[1172] COMPUTE START OF THIS TABLE
	SUB	T1,TAB.LB(R)	;[1172] OFFSET IN WINDOW TO FIRST AFTER USY
	ADD	T1,LW.S0(R)	;[1172] OFFSET IN SEGMENT
	ADD	T1,LL.S0(R)	;[1172] FORM ABSOLUTE ADDRESS FOR RH(.JBSYM)
	HRLZM	T1,JOB116	;[1172] STORE IN LH(JOB116) A WHILE
	PUSHJ	P,PATOUT	;[1172] WRITE THE PAT.. SYMBOL AND MODULE
	SKIPN	SYMFUL		;[1172] ANY ROOM LEFT?
	PUSHJ	P,LSLOOP	;[1172] DO THE WORK


;HERE WHEN THE SYMBOLS HAVE BEEN INSERTED INTO THE IMAGE.  UPDATE .JBSYM.

	SKIPE	PAG.S1		;[1172] PAGING?
	SKIPA	T1,JOBPTR	;[1172] YES, JOBDAT'S IN DY
	MOVE	T1,LC.LB	;[1172] NO, IT'S IN LC
	HRRZ	T2,JOB116	;[1172] NUMBER OF WORD PAIRS WRITTEN
	IMULI	T2,-2		;[1172] WANT -COUNT
	HRRM	T2,JOB116	;[1172] ADDR,,-LEN
	MOVSS	T2,JOB116	;[1172] -LEN,,ADDR
	MOVEM	T2,.JBSYM(T1)	;[1172] STORE IN JOBDAT
	POPJ	P,		;[1172] DONE WITH DOLOCS
;HERE TO MOVE SYMBOLS TO TOP OF CORE
;IF SORTING PUT SORT BUFFER IN AREA GS

SYMINI:	SKIPL	UW.LS		;[1172] 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,FR.CNT##	;[1172] SEE HOW MUCH IS FREE
	LSH	T1,-1		;[1172] TAKE HALF OF IT FOR LS WINDOW
	ANDCMI	T1,.IPM		;[1172] KEEP ON A PAGE BOUND
	CAIGE	T1,2*.IPS	;[1172] BUT NEED AT LEAST TWO PAGES
	MOVEI	T1,2*.IPS	;[1172] SO FORCE AT LEAST THAT MANY
	MOVE	T2,LS.AB	;[1172] CALCULATE CURRENT SIZE OF LS AREA
	SUB	T2,LS.LB	;[1172] LAST - FIRST
	ADDI	T2,1		;[1172] PLUS 1
	CAML	T2,T1		;[1172] HAVE LESS THAN WE WANT?
	JRST	RDSYM2		;[1172] ALREADY BIG ENOUGH
	SUB	T1,T2		;[1172] HOW MUCH MORE WE NEED
	MOVEI	P1,LS.IX	;[1172] ARRANGE TO GET IT
	MOVE	P2,T1		;[1172] HOW MUCH TO GET
	PUSHJ	P,LNKCOR##	;[1172] SHUFFLE
	  PUSHJ	P,E$$MEF##	;[1174] CANNOT HAPPEN


;NOW READ THE LAST PAGE OF SYMBOLS INTO THE FIRST PAGE OF THE LS AREA.
;LSLOOP WILL QUICKLY FALL OFF THE BOTTOM (READING BACKWARDS), AND
;FILL THE ENTIRE WINDOW WITH THE NEXT LOWER PIECE.

RDSYM2:	MOVE	T1,LSYM		;[1172] LAST WORD OF SYMBOLS + 1
	SUBI	T1,1		;[1172] LAST WORD IN USE
	ANDCMI	T1,.IPM		;[1172] BOTTOM OF NEW WINDOW
	MOVEM	T1,LW.LS	;[1172] SET FOR PAGING ROUTINES
	ADD	T1,LS.AB	;[1172] ADD WINDOW SIZE
	SUB	T1,LS.LB	;[1172] TO GET TOP OF WINDOW
	MOVEM	T1,UW.LS	;[1172] STORE FOR PAGING ROUTINES
	MOVE	T1,LSYM		;[1172] FIRST UNUSED WORD AGAIN
	SUB	T1,LW.LS	;[1172] HOW FAR INTO WINDOW IT IS
	ADD	T1,LS.LB	;[1172] FIX IN MEMORY
	MOVEM	T1,LS.PT	;[1172] SAVE FOR GETSYM
	HRLZ	T1,LW.LS	;[1172] NOW FILL BOTTOM PAGE
	HRR	T1,LW.LS	;[1172] REST WILL BE FILLED BY PAGSYM
	IORI	T1,.IPM		;[1172] ROUND UP TO TOP OF PAGE
	PJRST	LS.IN##		;[1172] FILL THE WINDOW AND RETURN
;LNKOV2 FILLS THE LS AREA WITH SYMBOL TRIPLETS, ZEROES THE LC AREA,
;AND THEN PUSHJ'S DIRECTLY TO LSLOOP TO CONVERT THE SYMBOLS TO
;RADIX50 AND PUT A RUNTIME SYMBOL TABLE INTO THE LC AREA.  IT
;THEN WRITES THE LC AREA TO THE APPROPRIATE PLACE IN THE OVERLAY FILE.
;
;THIS IS AN INITIALIZATION ROUTINE CALLED BY LNKOV2 TO SET THINGS UP
;BEFORE CALLING LSLOOP.

IFN FTOVERLAY,<

LSOVX::	MOVX	T1,.INFIN	;[1172] DON'T STOP FOR A SYMBOL LIMIT
	MOVEM	T1,SYMLIM	;[1172] SINCE NOT REALLY LOADING INTO MEMORY
	SETZM	SYMDEW		;[1172] DON'T NEED ANY WARNING
	SETZM	SYMFUL		;[1172] HAVE LOTS OF ROOM FOR SYMBOLS
	SETZM	JOB116		;[1172] LSLOOP AOSES THIS FOR EVERY SYMBOL
	SKIPN	LNKNO.		;[1172] IS THIS THE ROOT?
	PJRST	PATOUT		;[1172] YES, WRITE PAT.. AND RETURN
	MOVNI	T1,2		;[1172] NO, INIT TTLPTR
	MOVEM	T1,TTLPTR	;[1172] SO FIRST MODULE WILL BE RIGHT
	POPJ	P,		;[1172] RETURN TO LNKOV2
> ;END IFN FTOVERLAY
;HERE TO WRITE THE PAT.. SYMBOL AND MODULE TO THE SYMBOL TABLE.

PATOUT:	MOVE	W2,[RADIX50 04,PAT..]	;[1172] NAME
	MOVE	W3,PATLOC	;[1172] VALUE
	PUSHJ	P,SYMOUT	;[1172] WRITE IT OUT
	  JRST	[HRLI W3,-2	;[1172] SYMBOL WON'T FIT, JUST WRITE NAME
		SETZM SYMDEW	;[1172] IF IT WILL FIT
		JRST PATOU2]	;[1172] RE-JOIN COMMON CODE
	AOS	JOB116		;[1172] A SYMBOL PAIR SUCCESSFULLY WRITTEN
	HRLI	W3,-4		;[1172] FOUR WORDS IN THIS MODULE
PATOU2:	MOVE	T1,TAB.PT(R)	;[1172] BEFORE WRITING THE TITLE,
	SUB	T1,TAB.LB(R)	;[1172] FIGURE OUT WHERE IT GOES
	ADD	T1,LW.S0(R)	;[1172] AS AN OFFSET INTO THE SEGMENT
	MOVEM	T1,TTLPTR	;[1172] SAVE FOR LTITLE
	TLZ	W2,740000	;[1172] MAKE 0,PAT.. BE THE TITLE
	PUSHJ	P,SYMOUT	;[1172] WRITE THE TITLE
	  CAIA			;[1172] OOPS! SEE WHAT WENT WRONG
	JRST	PATOU4		;[1172] OK, NOW GO WRITE THE REAL SYMBOLS
	SKIPN	SYMDEW		;[1172] 4,PAT.. FAILED ABOVE? (DON'T USE SYMFUL)
	JRST	[SETZM JOB116	;[1172] YES, THERE WON'T BE A SYMBOL TABLE
		POPJ P,]	;[1172] JUST RETURN
	SETZM	SYMDEW		;[1172] USE OUR RESERVE FOR PAT..'S TITLE
	PUSHJ	P,SYMOUT	;[1172] WRITE IT
	  JFCL			;[1172] CAN'T HAPPEN
PATOU4:	AOS	JOB116		;[1172] ANOTHER SYMBOL WRITTEN
	POPJ	P,		;[1172] DONE
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
	SKIPE	SYMFUL		;[1172] SKIPPING FOR LAST MODULE NAME?
	JRST	LSLOOP		;[1172] YES, REJECT ALL OTHER RANDOM SYMBOLS
	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
	  JRST	[SETZM SYMDEW	;[1172] GO INTO FIND MODULE NAME MODE
		JRST LSLOOP]	;[1172] START THE HUNT
	AOS	JOB116		;[1172] ANOTHER SYMBOL STORED
	JRST	LSLOOP		;AND BACK FOR MORE

LSLUPC:	MOVEI	T1,4		;[1172] NEED FOUR WORDS OR NOTHING
	MOVEM	T1,SYMDEW	;[1172] SO BUMP WARNING LEVEL
	PUSHJ	P,SYMOUT	;OUTPUT IT
	  JRST	[SETZM SYMDEW	;[1172] WON'T BOTH FIT
		JRST LSLOOP]	;[1172] CLOSE OFF TABLE AND STOP
	AOS	JOB116		;[1172] ANOTHER PAIR OUT
	MOVEI	T1,2		;[1172] PUT SYMOUT CUTOFF BACK
	MOVEM	T1,SYMDEW	;[1172] NEXT PAIR GUARANTEED TO FIT
	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 ON A TITLE IN THE LS AREA.

LTITLE:	TXNE	W1,PT.PSC	;[1132] JUST A PSECT DEFINITION?
	JRST	LSLOOP		;[1132] YES, DON'T PUT IN SYMBOL TABLE
	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
	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
	  JRST	[SETZM SYMDEW	;[1172] USE THE RESERVE TO STORE THIS TITLE
		JRST .-1]	;[1172] TRY AGAIN
	AOS	JOB116		;[1172] COUNT ANOTHER SYMBOL PAIR
	SKIPE	SYMFUL		;[1172] WAS THIS OUR LAST TITLE?
	POPJ	P,		;[1172] YES, QUIT, SINCE NO MORE ROOM
	JRST	LSLOOP		;RETURN



BTITLE:	SKIPE	SYMFUL		;[1172] ROOM FOR THIS?
	JRST	LSLOOP		;[1172] NO, DON'T STORE IT
	TXO	W2,R5.LCL!R5.GLB	;MAKE RADIX50 14,SYM
	HRRZ	W3,W3		;BLOCK LEVEL ONLY
	JRST	LSLUP1		;AND TREAT AS LOCAL SYMBOL
;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
	JRST	CPOPJ1		;SKIP RETURN
;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
	HRLZ	T1,LS.LB	;[1172] MOVE FIRST BLOCK OF SYMBOLS
	HRR	T1,LS.AB	;[1172]   UP TO LAST BLOCK OF LS AREA
	ANDCMI	T1,.IPM		;[1172] NOW HAVE SRC,,DEST
	BLT	T1,@LS.AB	;[1172] MOVE THE DATA
	MOVE	T1,LS.AB	;[1172] CHECK TO SEE IF LAST TIME
	ANDCMI	T1,.IPM		;[1172] ACCOUNT FOR PAGE WE KEPT
	MOVEI	T2,.IPM		;[1172] MASK FOR PAGE OFFSET
	ANDM	T2,LS.PT	;[1172] OFFSET TO CURRENT SYMBOL
	ADDM	T1,LS.PT	;[1172] MOVE POINTER TO LAST PAGE OF AREA
	SUB	T1,LW.LS	;[1172] BOTTOM ADDR IF WE FINISHED THIS TIME
	SUBI	T1,1		;[1172] GET LOCATION BELOW FIRST USED
	CAML	T1,LS.LB	;[1172] LS AREA TOO BIG (LAST TIME)?
	PUSHJ	P,GBCK.L##	;[1172] YES, GET RID OF BOTTOM PART
	MOVE	T1,LW.LS	;[1172] GET OLD LOWER WINDOW ADDRESS
	IORI	T1,.IPM		;[1172] THE END OF THAT PAGE
	MOVEM	T1,UW.LS	;[1172] FORM NEW UPPER WINDOW
	ADD	T1,LS.LB	;[1172] SUBTRACT LENGTH OF AREA
	SUB	T1,LS.AB	;[1172] TO FORM LOWER WINDOW
	MOVEM	T1,LW.LS	;[1172] STORE FOR PAGING ROUTINES
	HRLZ	T1,T1		;[1172] NOW TO READ IN THE DATA
	HRR	T1,UW.LS	;[1172] TRANSFER WORD TO WHOLE AREA
	SUBI	T1,.IPS		;[1172] BUT WE ALREADY HAVE LAST PAGE
	PUSHJ	P,LS.IN		;[1172] FILL UP THE AREA
	JRST	CPOPJ1		;[1172] 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
E03CNW::.ERR.	(MS,.EC,V%L,L%F,S%F,CNW) ;[1174]
	.ETC.	(STR,,,,,,<FNDNIC>)
;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 TO WRITE THE RADIX-50 SYMBOL IN W2/W3 TO THE IMAGE.
;RETURNS NON-SKIP, MESSAGE PRINTED, IF SYMBOL WON'T FIT BELOW SYMLIM.
;SYMBOL WON'T FIT IF IT IS WITHIN C(SYMDEW) WORDS OF PASSING SYMLIM.

SYMOUT:	MOVE	T1,TAB.PT(R)	;[1172] ADDRESS TO STORE INTO NEXT
	AOS	T2,T1		;[1172] LAST ADDRESS THIS SYMBOL WILL USE
	SUB	T2,TAB.LB(R)	;[1172] CONVERT TO OFFSET IN SEGMENT
	ADD	T2,TAB.LW(R)	;[1172] (USUALLY SAME AS VIRTUAL ADDRESS)
	ADD	T2,LL.S0(R)	;[1172] MAKE SURE IT'S A VIRTUAL ADDRESS
	ADD	T2,SYMDEW	;[1172] RESPECT DISTANT EARLY WARNING FACTOR
	CAMG	T2,SYMLIM	;[1172] WOULD WE STORE BEYOND LEGAL BOUNDS?
	JRST	SYMOU2		;[1172] NO, CONTINUE
	SKIPE	SYMFUL		;[1172] ALREADY ISSUED A MESSAGE?
	POPJ	P,		;[1172] YES, DONT SAY IT AGAIN
	SETOM	SYMFUL		;[1172] REMEMBER FOR NEXT TIME & CALLERS
E$$ISS::.ERR.	(MS,.EC,V%L,L%W,S%W,ISS,<Insufficient space for symbol table after psect >) ;[1174]
	.ETC.	(SBX,.EP!.EC,,,,SSGNAM)
	.ETC.	(STR,,,,,,< -- table truncated>)
	POPJ	P,		;[1172] ERROR RETURN
;HERE IF NOT PAST SYMLIM.  CHECK TO SEE IF THE AREA/WINDOW IS BIG ENOUGH.

SYMOU2:	CAMG	T1,TAB.AB(R)	;[1172] STILL ROOM IN THE AREA?
	AOJA	T1,SYMOU8	;[1172] YES, GO STORE THE SYMBOL
	SETOM	LS.PP		;[1172] DON'T SHRINK THE LS AREA
	SPUSH	<P1,P2>		;[1216] PRESERVE OVER LNKCOR
	MOVE	P1,R		;[1172] SEGMENT TO EXPAND
	MOVEI	P2,.IPS		;[1172] BY ONE PAGE
	PUSHJ	P,LNKCOR##	;[1172] EXPAND
	  PUSHJ	P,E$$MEF##	;[1174] SHOULD NEVER GET HERE
	SPOP	<P2,P1>		;[1216] RESTORE SACRED COWS
	SETZM	LS.PP		;[1172] RESTORE

IFN FTOVERLAY,<
	SKIPL	LNKMAX		;[1172] LSLOOP CALLED FROM LNKOV2?
	SKIPN	PAG.S0(R)	;[1172] AND LNKCOR STARTED AREA PAGING?
	CAIA			;[1172] NO
	PUSHJ	P,E$$MEF##	;[1174] YES, LNKOV2 CAN'T HANDLE THAT
> ;END IFN FTOVERLAY

	PUSHJ	P,CHKPAG	;[1172] FIX JOBDAT IF JUST STARTED PAGING
	SKIPN	TAB.PG(R)	;[1172] AREA NOW PAGING?
	JRST	SYMOUT		;[1172] NO, GO TRY AGAIN
	MOVE	T1,LW.S0(R)	;[1172] YES, MUST UPDATE UW
	ADD	T1,TAB.AB(R)	;[1172] LNKCOR SOMETIMES DOES
	SUB	T1,TAB.LB(R)	;[1172] BUT SOMETIMES IT DOESN'T
	MOVEM	T1,UW.S0(R)	;[1172] SO MAKE SURE IT'S RIGHT
	ANDCMI	T1,.IPM		;[1172] FIRST ADDRESS IN PAGE WE JUST ADDED
	CAML	T1,HC.S0(R)	;[1172] ANY DATA FURTHER ON IN OVERFLOW FILE?
	JRST	SYMOUT		;[1172] NO, JUST LEAVE NEW PAGE ZERO
	HRLZ	T1,T1		;[1172] YES, MUST FILL IN NEW PAGE
	HRR	T1,UW.S0(R)	;[1172] OTHERWISE WE LOSE DATA
	PUSHJ	P,@TB.IN(R)	;[1172] DO THE I/O
	JRST	SYMOUT		;[1172] AND TRY AGAIN


;HERE WHEN ALL IS OK TO STORE THE NEW SYMBOL.

SYMOU8:	DMOVEM	W2,-2(T1)	;[1172] DO THE STORE
	MOVEM	T1,TAB.PT(R)	;[1172] UPDATE THE PT FOR NEXT TIME

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
;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)
E$$OES::PUSH	P,[MC]		;[1174]
	.ERR.	(ST,,V%L,L%W,S%W,OES,<Output error on symbol file, file closed, load 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
E01OES::PUSH	P,[DC]		;[1174]
	.ERR.	(ST,,V%L,L%W,S%W,OES)
	POPJ	P,
;HERE TO SET UP THE REST OF THE JOBDAT AREA. ENTER WITH P1 POINTING TO JOBDAT
;AREA AND P2 TO VESTIGIAL JOBDAT (0 IF NO HIGH SEGMENT).

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

;  ..
;  ..

;COMPUTE ADDRESS AT WHICH TO START PROGRAM. IF A DEBUGGER IS LOADED, THIS IS NOT
;NECESSARILY THE MAIN PROGRAM'S START ADDRESS, BUT DEPENDS ON THE DEBUGGER.

	SETZ	T1,		;[1144] ASSUME WE DON'T START PROGRAM
	SKIPE	EXECSW		;GO INTO EXECUTION?
	MOVE	T1,STADDR	;YES, ASSUME .JBSA
	HRRZ	T2,DEBUGSW	;[1144] IF DEBUGGING, DEBUGGER'S START ADDRESS
	SKIPGE	DEBUGSW		;[1144]   TAKES PRIORITY SO
	MOVE	T1,@STLOCN(T2)	;[1144]   FIND IT
	HRRM	T1,EXECSW	;IN ANY CASE STORE BACK IN EXECSW
	POPJ	P,
;TABLE OF WHERE TO START FOR EACH DEBUGGER.

DEFINE KEYMAC(A,B)<
  XALL					;;[1144] GIVE A GOOD LISTING
  IFIDN <A><DEB>,<			;;[1144] SELECT ONLY DEBUGGING KEYWORDS
    %%1==-1				;;[1144] SKIP DUMMY ENTRY
    IRP B,<				;;[1144] CHECK EACH KEYWORD
      IFGE %%1,<			;;[1144]   THAT IS NOT THE DUMMY
        IFN <%%1&1>,<			;;[1144]   AND IS A DEGUGGER NAME
          %%2==0			;;[1144] ASSUME WE WON'T FIND A DEBUGGER
          IFN TOPS20,<			;;[1144] TOPS-20 UDDT IS SPECIAL
            IFIDN <B><DDT>,<		;;[1144] CHECK FOR DDT DEBUGGER
	[770000]		;UDDT STARTS AT 770000
              %%2==1			;;[1144] REMEMBER WE FOUND A DEBUGGER
            >
          >
          IFIDN <B><FORDDT>,<		;;[1144] FORDDT IS SPECIAL
	STADDR			;FORDDT FORCES START ADDRESS TO ITSELF
            %%2==1			;;[1144] REMEMBER WE FOUND A DEBUGGER
          >
          IFIDN <B><COBDDT>,<		;;[1144] COBDDT IS SPECIAL
	STADDR			;COBDDT GETS CONTROL FROM COBOL PROGRAM
            %%2==1			;;[1144] REMEMBER WE FOUND A DEBUGGER
          >
          IFE %%2,<			;;[1144] IF IT WASN'T ABOVE DEBUGGERS
	.JBDDT(P1)		;OTHER DEBUGGERS SET .JBDDT
          >
        >
      >
      %%1==%%1+1			;;[1144] ADVANCE TO NEXT ENTRY
    >
  >
  PURGE %%1,%%2				;;[1144] CLEAN UP AFTERWARD
  SALL					;;[1144]   ..
>

STLOCN:	KEYWORDS
;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 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
	POPJ	P,		;[1172] DONE
	PUSHJ	P,RDJBH		;SET UP JOBDAT IN HIGH
	POPJ	P,



;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##
SUBTTL	DECIDE TO LOAD OR SAVE


;DETERMINE IF WE CAN LOAD THE PROGRAM INTO MEMORY OR MUST WRITE AN .EXE FILE
;INSTEAD. WE MUST WRITE AN .EXE FILE IF ANY OF THE FOLLOWING ARE SATISFIED:
;
;  1.	USER SPECIFIED /SAVE (SCAN BLOCK ALREADY SET UP).
;  2.	THERE ARE PAGE GAPS BETWEEN PSECTS, EXCEPT BELOW .HIGH. (BEWARE THAT
;	OVERLAPS DO NOT COUNT AS GAPS).
;  3.	THERE ARE ANY PSECTS ABOVE THE HIGH SEGMENT.
;  4.	ANY PSECT HAS NON-DEFAULT WRITEABILITY.
;  5.	THE PROGRAM WILL NOT FIT IN MEMORY WITH LINK'S FINAL PLACEMENT CODE
;	(THIS INCLUDES THE CASE IN WHICH THE REMAP UUO WOULD HAVE TO MOVE THE
;	HIGH SEGMENT DOWN).

SAVTST:	SKIPE	IO.PTR+%VC	;[1146] SAVE FILE REQUIRED?
	JRST	JBSAVE		;YES

;TEST FOR GAPS BETWEEN PSECTS, PSECTS ABOVE THE HIGH SEGMENT AND PSECT
;PROPERTIES THAT WE CAN'T HANDLE EXCEPT IN AN EXE FILE.

	MOVE	T1,HL.S1	;[1146] SEE IF LOW SEG (CONTAINS ALL PSECTS)
	SKIPE	LL.S2		;[1170]   HITS HIGH SEG (IF ANY) WHICH CHECKS
	CAMG	T1,LL.S2	;[1146]   FOR PSECTS ABOVE HIGH SEG ORIGIN
	SKIPA			;[1146] NO--OK SO FAR
	JRST	JBCMPX		;[1146] YES--CAN'T LOAD IT
	MOVEI	R,0		;[1146] START AT .ABS.
	MOVE	W1,@RC.TB	;[1146] GET POINTER TO ITS RELOC BLOCK
	MOVE	T1,RC.HL(W1)	;[1146] START WITH ITS HIGH LIMIT
	ADDI	R,1		;[1146] ADVANCE TO .LOW. FOR CHECKS
	MOVX	T4,2		;[1146] # OF SEG CONTAINING ONLY .HIGH.
	; ..
	; ..

;BACK HERE FOR EACH NEW PSECT.

SAVTS1:	MOVE	W2,@RC.TB	;[1146] GET POINTER TO THIS RELOC BLOCK
	MOVE	T2,RC.AT(W2)	;[1171] GET THIS PSECT'S ATTRIBUTES

IFE TOPS20,<
	CAMN	T4,RC.SG(W2)	;[1171] TOPS-10 HIGH SEGMENT?
	JRST	[TXNE T2,AT.RW	;[1171] YES, USER ASKED FOR WRITEABLE?
		JRST JBCMPX	;[1171] YES, LET MONITOR FIGURE IT OUT
		JRST SAVTS2]	;[1171] NO, ATTRIBUTES ARE OK
> ;END IFE TOPS20

	TXNE	T2,AT.RO	;[1171] NON-HI SEG PAGE TO BE READ ONLY?
	JRST	JBCMPX		;[1171] YES, WE CAN'T HANDLE IT
SAVTS2:	CAML	T1,RC.HL(W2)	;[1171] DOES PREVIOUS PSECT ENGULF THIS ONE?
	JRST	SAVTS6		;[1171] YES--NO GAP POSSIBLE YET
	CAMN	T4,RC.SG(W2)	;[1146] POSSIBLE GAP BELOW .HIGH.?
	JRST	SAVTS5		;[1171] YES--OK. USUAL CASE
	MOVEI	T2,-1(T1)	;[1146] COMPUTE LAST PAGE USED
	LSH	T2,-9		;[1146]   ..
	LDB	T3,[POINTR RC.IV(W2),^-^O777] ;[1146] GET FIRST PAGE USED BY NEXT PSECT
	SUB	T3,T2		;[1146] COMPUTE # PAGES BETWEEN THIS AND LAST
	SOJG	T3,JBCMPX	;[1146] CAN'T LEAVE GAPS IN MEMORY
SAVTS5:	MOVE	T1,RC.HL(W2)	;[1171] SO FAR SO GOOD--ADVANCE TO NEXT PSECT
SAVTS6:	MOVE	W1,W2		;[1171] ADVANCE TO NEXT PSECT
	CAMGE	R,RC.NO		;[1146] LOOKED AT ALL PSECTS?
	AOJA	R,SAVTS1	;[1146] NO--LOOK AT NEXT
	;  ..
	;  ..

;COMPUTE HOW MUCH MEMORY IT WILL TAKE TO HOLD THE PROGRAM DURING THE LAST STAGES
;OF LOADING, AND MAKE SURE THAT WE CAN GET THAT MUCH.  IF  WE  CAN'T,  THEN  THE
;PROGRAM IS TOO COMPLEX. THERE ARE TWO SIZES TO WORRY ABOUT:
;
;  1.	LINK'S  LOW SEGMENT + THE PROGRAM'S ACTUALLY LOADED LOW SEGMENT (DOESN'T
;	COUNT BLOCK'S AT THE END OF THE LOW SEGMENT) + THE PROGRAM'S ACTUALLY
;	LOADED HIGH SEGMENT. THIS IS THE MEMORY REQUIREMENT IN JBLOAD.
;
;  2.	THE  PROGRAM'S  ENTIRE  LOW  SEGMENT + HIGH SEGMENT.  THIS IS THE MEMORY
;	REQUIREMENT IN THE FINAL EXIT CODE AT %5.  NOTE THAT  WE  MUST  REMEMBER
;	THAT WE HAVE A HIGH SEGMENT NOW BUT WON'T THEN.

	MOVE	T1,DY.AB	;[1146] START WITH HIGHEST ADDR LINK NEEDS
	ADD	T1,HC.S1	;[1146] ADD LENGTH OF ACTUALLY LOADED CODE
	IOR.	T1,.PGSIZ	;[1146]   ..
	SKIPE	LL.S2		;[1170] HIGH SEG EXISTS
	CAMGE	T1,LL.S2	;[1146]   AND ORIGIN BELOW WHERE WE CAN PUT IT?
	SKIPA			;[1146] NO--OK
	JRST	JBCMPX		;[1146] YES--REMAP WOULD FAIL SO TOO COMPLEX
	ADD	T1,HC.S2	;[1170] ADD LENGTH OF HIGH SEGMENT
	IOR.	T1,.PGSIZ	;[1146]   ..
	HRRZ	T2,.JBHRL##	;[1170] DON'T COUNT SIZE OF CURRENT HIGH SEG
	SUB	T2,HIORGN	;[1170]   ..
	MOVNI	T2,2(T2)	;[1170]   ..
	ADD	T2,HL.S1	;[1170] + ENTIRE PROGRAM LOW SEG
	IOR.	T2,.PGSIZ	;[1170]   ROUNDED TO A PAGE
	ADD	T2,HL.S2	;[1170] + ENTIRE PROGRAM HIGH SEG
	IOR.	T2,.PGSIZ	;[1170]   ROUNDED TO A PAGE TOO
	CAMGE	T1,T2		;[1170] PICK MAX OF TWO
	MOVE	T1,T2		;[1170]   ..
	TLNE	T1,-1		;[732] OVERFLOWED INTO THE LH?
	JRST	JBCMPX		;[1146] YES--CAN'T FIT SO WRITE .EXE FILE
IFE TOPS20,<			;[1113] SEE IF WE CAN EXPAND ON TOPS-10
	CAMG	T1,.JBREL	;DO WE HAVE ENOUGH ALREADY?
	JRST	JBLOAD		;[1146] YES, READ IN REST OF TEMP FILE
	CORE	T1,		;NO TRY FOR IT
	  JRST	JBCMPX		;[1146] WON'T FIT--WRITE .EXE FILE
	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)
>
IFN TOPS20,<			;[1113] WE'RE AS BIG AS WE CAN GET ON TOPS-20
	CAMLE	T1,.JBREL	;[1113] DO WE HAVE ENOUGH ALREADY?
	JRST	JBCMPX		;[1146] NO--PROGRAM WON'T FIT WITH LINK
>
	JRST	JBLOAD		;[1146] PROGRAM WILL FIT--GO BRING IT IN
SUBTTL	FORCE nnnLNK/SAVE


;HERE IF USER DID NOT SPECIFY /SAVE BUT PROGRAM IS TOO COMPLEX (TOO LARGE, PSECT
;GAPS, ETC.) TO LOAD. DUMMY UP A SCAN BLOCK AS IF THE USER TYPED nnnLNK/SAVE,
;PRINT A WARNING AND FALL INTO .EXE WRITING CODE.

JBCMPX:	MOVEI	T2,F.LEN	;[1146] SET UP 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
	SKIPE	EXECSW		;WANT TO EXECUTE?
	JRST	E$$PCX		;[1174] YES--LNKPCX
E$$PCL::.ERR.	(MS,.EC,V%L,L%W,S%W,PCL,<Program too complex to load, saving as file >) ;[1174]
	.ETC.	(JMP,.EC,,,,JBCMP2)
E$$PCX::.ERR.	(MS,.EC,V%L,L%W,S%I,PCX,<Program too complex to load and execute, will run from file >) ;[1174]
JBCMP2:	.ETC.	(FSP,,,,,%VC)
;	JRST	JBSAVE		;[1146] FALL THROUGH TO WRITE .EXE FILE
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:				;[1174] WRITE A SAVED FILE
E$$CSF::.ERR.	(MS,0,V%L,L%I,S%I,CSF,<Creating saved file>) ;[1174]
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)
>
	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
	SKIPL	SYMSEG		;[1132] SYMBOLS IN A PSECT?
	JRST	JBSAVX		;[1132] NO, SKIP THIS
	HLRE	T1,.JBSYM(P1)	;[1132] YES, GET -LENGTH OF TABLE
	HRRZ	T2,.JBSYM(P1)	;[1132] GET FIRST ADDR OF TABLE
	SUB	T2,T1		;[1132] COMPUTE FIRST FREE AFTER TABLE
	CAMLE	T2,HC.S1	;[1132] UPDATE AMOUNT OF CODE IN LC AREA
	MOVEM	T2,HC.S1	;[1132] BUT NEVER DECREASE
	CAMLE	T2,HL.S1	;[1132] ALSO UPDATE SIZE OF SEGMENT
	MOVEM	T2,HL.S1	;[1132] NEVER DECREASE
JBSAVX:
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
	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
E$$SOE::PUSH	P,[DC]		;[1174]
	.ERR.	(ST,,V%L,L%F,S%F,SOE,<Saved file output error>) ;[1174]
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 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,E$$OEX	;[1174]
	PUSHJ	P,DVRLS.##	;RELEASE DEV
	PJRST	DVZAP.##	;FORGET ABOUT .XPN FILE NOW

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

;HERE TO WRITE THE EXE FILE.
;THE STRATEGY IS:
;RESERVE ONE PAGE FOR THE DIRECTORY.
;WRITE OUT EACH PSECT (POINTED TO BY RC.TB), COMPRESSING OUT ZERO PAGES,
;  AND ACCUMULATING THE EXE DIRECTORY IN A BLOCK IN THE DY AREA.
;GO BACK TO THE BEGINNING OF THE FILE AND WRITE OUT THE EXE DIRECTORY.
;NOTES:
;PAGE 0 IS ALWAYS WRITTEN, AND IF A HIGH SEG EXIST, SO IS ITS FIRST PAGE.
;IF THE EXE DIRECTORY PAGE IN THE DY AREA OVERFLOWS, LINK WRITES IT OUT
;  AT THE BEGINNING OF THE FILE, THEN FREES UP ANOTHER PAGE IN THE FILE BY
;  MAKING A BACKWARDS PASS OVER THE EXE FILE, MOVING EACH PAGE DOWN ONE.


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
IFN FTOVERLAY,<

;IF LOADING OVERLAYS, IT IS THE EXE FILE GENERATOR'S RESPONSIBILITY
;TO INSERT THE SYMBOLS INTO THE PROGRAM ON THE FLY WHILE IT IS WRITING
;THE EXE FILE.  THE SYMBOLS ARE IN THE LS AREA IN RADIX50 FORM.
;THE EXE FILE WRITING LOOP IS VERY PAGE ORIENTED, SO TO MAKE THINGS
;EASIER, WE WILL COPY THE FIRST PARTIAL PAGE OF SYMBOLS INTO THE
;LC AREA HERE.

	SKIPL	LNKMAX		;[1132] LOADING OVERLAYS?
	SKIPN	JOB116		;[1132] AND SYMBOLS TO PROCESS?
	JRST	JBEXEE		;[1132] NO, SKIP THIS
	HRRZ	P3,JOB116	;[1132] GET FIRST ADDRESS TO COPY INTO
	HRRZ	P4,P3		;[1132] COMPUTE LAST ADDRESS IN P4
	ADDI	P4,777		;[1132] ROUND UP TO PAGE BOUND
	ANDCMI	P4,777		;[1132] ADDRESS OF FIRST FULL PAGE OF SYMS
	CAMLE	P4,HL.S1	;[1132] MAKE SURE EXE FILE WRITER GOES THIS FAR
	MOVEM	P4,HL.S1	;[1132] SO OVERLAY CODE CAN JUST CONTINUE
	MOVEI	R,1		;[1132] POINTER TO .LOW. RC BLOCK
	MOVE	R,@SG.TB	;[1132] SINCE OVERLAY SYMBOLS ARE IN .LOW.
	CAMLE	P4,RC.HL(R)	;[1132] UPDATE .LOW. TO SYMBOLS WRITTEN HERE
	MOVEM	P4,RC.HL(R)	;[1132] BUT NEVER SHRINK IT
	ANDI	P3,777		;[1132] OFFSET TO FIRST WORD TO WRITE
	JUMPE	P3,JBEXEE	;[1132] IF PAGE-ALIGNED, NOTHING TO DO
	CAMLE	P4,HC.S1	;[1132] SINCE COPYING SYMS, UPDATE NON-ZERO PTR
	MOVEM	P4,HC.S1	;[1132] ALSO REMEMBERS HOW LONG LC AREA IS
	SKIPE	PAG.S1		;[1132] IS LC AREA PAGING?
	JRST	JBEXEB		;[1132] YES, GO SET ON CORRECT PAGE
	MOVE	P2,P4		;[1132] EXTEND LC AREA TO WHERE SYMS GO
	ADD	P2,LC.LB	;[1132] MIGHT BE QUITE A WAY IF BIG /SPACE
	SUB	P2,LC.AB	;[1132] DISTANCE = LAST ADDR - SIZE OF LC AREA
	SUBI	P2,1		;[1132] SIZE IS LAST-FIRST+1
	JUMPLE	P2,JBEXEC	;[1132] ALREADY THERE
	MOVEI	P1,LC.IX	;[1132] TELL LNKCOR TO EXPAND LC AREA
	PUSHJ	P,LNKCOR	;[1132] DO IT
	  JRST	JBEXEB		;[1132] FAILED, BUT LC AREA IS PAGING NOW
	JRST	JBEXEC		;[1132] OK, GO DO THE COPY
;HERE IF THE LC AREA IS PAGING, EITHER FROM THE START, OR BECAUSE
;IT COULDN'T EXPAND FAR ENOUGH.  JUST SET UP A ONE-PAGE WINDOW TO
;THE PAGE WE WANT TO COPY INTO.

JBEXEB:	HRLZ	T1,LW.S1	;[1132] WRITE ENTIRE LC AREA
	HRR	T1,UW.S1	;[1132] TO AVOID LOST DATA
	PUSHJ	P,LC.OUT##	;[1132] DUMP IT TO THE OVERFLOW FILE
	MOVE	T1,LC.LB	;[1132] REDUCE LC WINDOW TO ONE PAGE
	ADDI	T1,777		;[1132] AVOIDS CHECKS FOR OVER 256K
	MOVEM	T1,LC.AB	;[1132] AREA IS NOW 1 PAGE
	MOVSI	T1,-1000(P4)	;[1132] LOWEST LOCATION TO READ
	MOVSM	T1,LW.S1	;[1132] UPDATE LOWER WINDOW
	HRRI	T1,-1(P4)	;[1132] HIGHEST LOCATION TO READ
	HRRZM	T1,UW.S1	;[1132] UPDATE UPPER WINDOW
	PUSHJ	P,LC.IN		;[1132] READ IN CODE IN THAT PAGE


;HERE WHEN THE LC AREA INCLUDES THE PAGE THAT WE WANT TO UPDATE.
;NOW GET THE PAGE OF SYMBOLS WE WANT TO PUT HERE INTO THE LS AREA.

JBEXEC:	PUSHJ	P,CHKPAG	;[1132] IN CASE WE JUST STARTED PAGING
	SKIPN	LW.LS		;[1132] ARE THE FIRST PAGE OF SYMBOLS IN?
	JRST	JBEXED		;[1132] YES, GO DO THE COPY
	MOVE	T1,LW.LS	;[1132] WRITE CURRENT LS WINDOW
	ADD	T1,LS.AB	;[1132] SO SYMBOLS WON'T BE LOST
	SUB	T1,LS.LB	;[1132] T1 HAS NEW UPPER BOUND
	MOVEM	T1,UW.LS	;[1132] STORE IN CASE IT WAS -1
	HRL	T1,LW.LS	;[1132] ARG TO LS.OUT
	PUSHJ	P,LS.OUT	;[1132] WRITE THE LS AREA OUT
	MOVE	T1,LS.LB	;[1132] REDUCE LS WINDOW TO 1 PAGE
	ADDI	T1,777		;[1132] WILL BE EXPANDED LATER IF NEEDED
	MOVEM	T1,LS.AB	;[1132] AB IS LB+1P
	SETZM	LW.LS		;[1132] WANT FIRST PAGE OF SYMBOLS
	MOVEI	T1,777		;[1132] FROM 0 TO 777
	MOVEM	T1,UW.LS	;[1132] UPDATE UPPER WINDOW
	PUSHJ	P,LS.IN		;[1132] READ IN THE SYMBOLS


;HERE WHEN BOTH THE LC AND LS AREAS HAVE THE PAGE IN MEMORY THAT WE CARE
;ABOUT.  NOW TO BLT THE FIRST PARTIAL PAGE OF SYMBOLS INTO THE LC AREA.

JBEXED:	MOVE	T3,LC.LB	;[1132] CALCULATE OFFSET FROM VIRTUAL
	SUB	T3,LW.S1	;[1132]   TO PHYSICAL ADDRESSES
	HRRZ	T1,JOB116	;[1132] FIRST VIRTUAL ADDRESS TO WRITE
	ADD	T1,T3		;[1132] FIRST PHYSICAL ADDRESS
	HRL	T1,LS.LB	;[1132] FROM START OF LS AREA
	MOVE	T2,P4		;[1132] FIRST VIRTUAL ADDRESS NOT TO WRITE
	ADD	T2,T3		;[1132] FIRST PHYSICAL ADDRESS
	BLT	T1,-1(T2)	;[1132] COPY THE SYMBOLS

JBEXEE:
> ;END IFN FTOVERLAY

;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE

	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
		SUB	T1,LW.S1	;[1147] NO, FIND HOW FAR TO SHRINK
		ADDM	T1,LW.S1	;[1147] MOVE VIRTUAL WINDOW UP
		ADDM	T1,LC.LB	;[1147] GIVE AWAY BOTTOM OF AREA
		ADDM	T1,DY.UB	;[1147] GIVE TO AREA JUST BELOW
		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,7		;[1132] 1 FOR REM, 4 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	E$$ECE		;[1174] CAN'T
	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 WRITE THE EXE FILE, COMPRESSING OUT ALL-ZERO PAGES
;USES ACS AS FOLLOWS:
;
;P1	FLAGS,,FILE PAGE
;P2	REPEAT COUNT,,PROCESS PAGE
;P3	ADDRESS WITHIN SEGMENT (PROCESS ADDRESS - LL.S0(R))
;P4	FLAGS TO DETERMINE WHAT TO DO WITH THE DIRECTORY ENTRY,,FILE PAGE COUNT
;
;		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
;R2	POINTER TO RC BLOCK FOR CURRENT PSECT
;W1	STORE PTR
;W2	IOWD TO DATA NOT YET WRITTEN
;W3	IOWD LIST TERMINATOR (0)

ZEROF==1B0			;[1132] LAST THING FOUND WAS A ZERO PAGE
DATAF==1B1			;[1132] LAST THING FOUND WAS A NON-ZERO PAGE
GAPF==1B2			;[1132] LAST THING FOUND WAS AN INTER-PSECT GAP

XCMPRS:	SETZ	R,		;[1132] START WITH .ABS.
	MOVEM	R,RC.CUR	;[1132] STORE CUURENT PSECT INDEX IN RC.CUR
	MOVEI	T1,1		;[1132] CURRENT BLOCK OF EXE DIR
	MOVEM	T1,EXEBLK	;[1132] SAVE FOR XCMPXD
	USETO	DC,5		;[1132] START WRITING DATA AT BLOCK 5
	MOVEI	P1,1		;[1132] NEXT FILE PAGE TO WRITE IS 1
	MOVE	R2,@RC.TB	;[1132] POINTER TO RC BLOCK FOR .ABS.
	MOVE	R,RC.SG(R2)	;[1132] KEEP R POINTING TO SEGMENT INDEX
	MOVE	T1,RC.AT(R2)	;[1132] GET ITS PSECT ATTRIBUTES
	TXNN	T1,AT.RO	;[1132] READ-ONLY?
	TXO	P1,SV%WRT	;[1132] NO, LOWSEG IS USUALLY WRITABLE
	SETZB	P2,P3		;[1132] CORE PAGE 0, CURRENT ADDR IS 0
	MOVX	P4,GAPF		;[1132] FLAG NO OLD EXE DIR ENTRY TO WRITE
	MOVE	R,RC.SG(R2)	;[1132] POINT TO AREA CONTAINING THIS PSECT
	MOVSI	W1,-1000	;[1132] W1 IS AOBJN PTR TO COPY OF EXE DIR
	HRR	W1,EXEDIR	;[1132]   BEING BUILT IN DY AREA
	SETZB	W2,W3		;[1132] INIT IOWD
	SKIPN	LW.S1		;[1132] IS JOBDAT STILL IN DY AREA?
	JRST	XCMLUP		;[1132] NO (NORMAL CASE), GO START WRITING


;FALL THROUGH TO NEXT PAGE
;FALL IN FROM ABOVE

;HERE IF THE LOWEST LOCATION IS IN PAGE 1 OR HIGHER, AND THE
;LC AREA IS PAGING TO DISK.
;IF THAT IS THE CASE, THEN JOBDAT IS IN A BLOCK IN THE DY AREA
;POINTED TO BY JOBPTR, INSTEAD OF IN THE LC AREA.
;WHAT WE WANT TO DO NOW IS WRITE JOBDAT INTO THE EXE FILE DIRECTLY
;FROM THE DY AREA, THEN JUMP INTO THE MAIN LOOP BELOW TO FINISH THE SAVE.

	HRLOI	W2,-.JBDA-1	;[1132] FORM IOWD TO JOBDAT
	ADD	W2,JOBPTR	;[1132] ..
	OUT	DC,W2		;[1132] WRITE JOBDAT TO THE EXE FILE
	  TXCA	P4,DATAF!GAPF!1	;[1132] CLEAR GAPF, SET DATAF, 1 PAGE WRITTEN
	PUSHJ	P,E$$EOE	;[1174] I/O ERROR
	USETO	DC,9		;[1132] WRITE ZEROS INTO THE REST OF PAGE 0
	SETZ	W2,		;[1132] FLAG NO DATA TO WRITE
	JRST	XCMADP		;[1132] GO FIND NEXT PSECT


E$$ECE::PUSH	P,[DC]		;[1174] GIVE OFFENDING CHANNEL TO LNKLOG
	.ERR.	(LRE,0,V%L,L%F,S%F,ECE,<Error creating EXE file>) ;[1174]
;THIS IS THE MAIN LOOP FOR THE EXE FILE WRITER.
;WE GET BACK HERE ON EACH NEW PSECT, ON EACH NEW BLOCK OF PAGES
;READ IN IF AN AREA HAS OVERFLOWED TO DISK, AND ON EACH PAGE OF
;EACH PSECT.

XCMLUP:	SKIPE	PAG.S0(R)	;[1132] AREA OVERFLOWING TO DISK
	CAMG	P3,UW.S0(R)	;[1132]   AND OFF END OF WINDOW?
	CAML	P3,HC.S0(R)	;[1132] NO, BUT OFF END OF SEGMENT?
	JRST	XCMADV		;[1132] OFF END OF SOMETHING
	MOVE	T1,RC.HL(R2)	;[1132] FIRST ADDRESS BEYOND PSECT
	SUB	T1,LL.S0(R)	;[1132] CONVERT TO OFFSET IN SEGMENT, LIKE P3
	CAML	P3,T1		;[1132] OFF END OF PSECT?
	JRST	XCMADV		;[1132] YES, GO FIND THE NEXT ONE


;TIME TO SAVE THE PAGE WHOSE ADDRESS IS IN P3.  SEE IF IT'S ALL ZERO

	HRRZ	T1,P3		;[1132] OFFSET INTO SEGMENT
	SUB	T1,LW.S0(R)	;[1132] OFFSET INTO CURRENT WINDOW
	ADD	T1,TAB.LB(R)	;[1132] ADDRESS OF PAGE IN LINK'S VAS
	SKIPN	W2		;[1132] KNOW BASE OF IOWD YET?
	MOVEI	W2,-1(T1)	;[1132] NO, SET IT UP NOW
	HRLI	T1,-1000	;[1132] SET UP AN AOBJN PTR TO THE PAGE
	SKIPN	(T1)		;[1132] NEXT WORD ZERO?
	AOBJN	T1,.-1		;[1132] YES, LOOP OVER ALL THE PAGES
	JUMPGE	T1,XCMZER	;[1132] JUMP IF PAGE IS ALL ZERO


;HERE WHEN THE PAGE IS NON-ZERO

	TXON	P4,DATAF	;[1132] FLAG IN REAL DATA, FIRST TIME?
	JRST	XCMNWD		;[1132] YES, START A NEW DIRECTORY ENTRY
	ADD	W2,[-1000,,0]	;[1132] NO, JUST BUMP OUTPUT IOWD
	ADDI	P4,1		;[1132] REMEMBER DATA PAGES WRITTEN
	ADD	P2,[1B8]	;[1132] AND REPEAT COUNT FOR THIS ENTRY
	JRST	XCMADP		;[1132] ADVANCE TO THE NEXT PAGE

XCMNWD:	TXZ	P4,ZEROF	;[1132] NO LONGER IN A ZERO AREA
	TXZN	P4,GAPF		;[1132] WERE WE IN A GAP?
	PUSHJ	P,XCMPRD	;[1132] NO, WRITE DIR ENTRY OUT
	HRRZ	W2,P3		;[1132] START A NEW IOWD
	SUB	W2,LW.S0(R)	;[1132] MAKE ADDR INTO OFFSET FROM WINDOW START
	ADD	W2,TAB.LB(R)	;[1132] AND THENCE TO ADDR IN LINK
	SUB	W2,[1000,,1]	;[1132] CONVERT TO ONE PAGE IOWD
	MOVE	P2,P3		;[1132] COMPUTE NEW PROCESS PAGE
	ADD	P2,LL.S0(R)	;[1132] BY FINDING PROCESS ADDRESS
	LSH	P2,-9		;[1132] THEN SHIFTING TO GET A PAGE NUMBER
	ADDI	P4,1		;[1132] WILL WRITE 1 MORE DATA PAGE
	JRST	XCMADP		;[1132] GO ADVANCE TO NEXT PAGE
;HERE ON AN ALL-ZERO PAGE

XCMZER:	TXON	P4,ZEROF	;[1132] IS THIS THE FIRST ALL-ZERO PAGE?
	JRST	XCMNWZ		;[1132] YES, GO SETUP A NEW DIR ENTRY
	ADD	P2,[1B8]	;[1132] JUST BUMP REPEAT COUNT
	JRST	XCMADP		;[1132] ADVANCE TO THE NEXT PAGE


;HERE IF THE ALL-ZERO PAGE IS THE FIRST ONE AFTER DATA OR A GAP.
;IF DATA, WRITE IT OUT AND STORE THE DIR ENTRY. ALWAYS SET UP A NEW ENTRY.

XCMNWZ:	TXZ	P4,DATAF	;[1132] NO LONGER WRITING DATA
	TXZN	P4,GAPF		;[1132] NOT IN A GAP. WERE WE?
	PUSHJ	P,XCMPRD	;[1132] NO, WRITE THE DATA DIR ENTRY
	ADDI	P1,(P4)		;[1132] BUMP FILE PAGE COUNT
	HLLZS	P4		;[1132] CLEAR ACCUMULATED COUNT
	SKIPGE	W2		;[1132] SEEN ANY DATA PAGES?
	OUT	DC,W2		;[1132] YES, WRITE THEM
	TDZA	W2,W2		;[1132] SUCCESS, CLEAR IOWD
	JRST	E$$EOE		;[1174] I/O ERROR
	MOVE	P2,P3		;[1132] SET UP NEW PROCESS PAGE
	ADD	P2,LL.S0(R)	;[1132] BY COMPUTING PROCESS ADDRESS
	LSH	P2,-9		;[1132] THEN SHIFTING TO A PAGE NUMBER


;HERE TO ADVANCE TO THE NEXT PAGE.

XCMADP:	ADDI	P3,1000		;[1132] POINT TO NEXT PAGE
	JRST	XCMLUP		;[1132] LOOP BACK TO PROCESS IT
;HERE WHEN WE RAN OFF THE END OF THE PSECT, THE SEGMENT, OR THE WINDOW.
;FIGURE OUT WHAT TO PROCESS NEXT.

XCMADV:	SKIPGE	W2		;[1132] ANY DATA STILL TO WRITE?
	OUT	DC,W2		;[1132] YES, WRITE IT
	  TDZA	W2,W2		;[1132] SUCCESS, CLEAR IOWD POINTER
	JRST	E$$EOE		;[1174] I/O ERROR
	CAML	P3,HC.S0(R)	;[1132] OFF THE END OF THE SEGMENT?
	JRST	XCMBLK		;[1132] YES, GO WRITE ABZ PAGES AND ADVANCE
	CAML	P3,RC.HL(R2)	;[1132] OFF END OF PSECT?
	JRST	XCMNXP		;[1132] YES, GO FIND THE NEXT ONE


;HERE IF PAGING AND WE RAN OFF THE END OF THE CURRENT LC/HC WINDOW.
;ADVANCE THE WINDOW AND LOOP BACK.

	MOVEM	P3,LW.S0(R)	;[1132] STORE NEW LOWER WINDOW BOUND
	MOVE	T1,P3		;[1132] VIRTUAL ADDRESS OF 1ST WORD TO READ
	ADD	T1,TAB.AB(R)	;[1132] CONVERT TO VIRTUAL ADDRESS OF LAST WORD
	SUB	T1,TAB.LB(R)	;[1132]   BY ADDING SIZE OF LC/HC AREA
	MOVEM	T1,UW.S0(R)	;[1132] STORE NEW UPPER WINDOW BOUND
	CAMGE	T1,HC.S0(R)	;[1132] DOES THE AREA CONTAIN THAT MUCH?
	JRST	XCMRED		;[1132] YES, JUST GO READ IT IN
	SUB	T1,HC.S0(R)	;[1132] NO, FIGURE OUT HOW MUCH EXTRA WE HAVE
	ADDI	T1,1		;[1172] SUBTRACTED ONE TOO MUCH, HC IS FF FORMAT
	ANDCMI	T1,.IPM		;[1132] PUT ON THE PAGE BOUND
	MOVN	T1,T1		;[1132] DECREMENT THE AB OF THE AREA
	ADDM	T1,TAB.AB(R)	;[1132]   SO EXTRA SPACE IS AVAILABLE TO OTHERS
	ADDM	T1,UW.S0(R)	;[1132] AREN'T GOING TO READ THAT MUCH AFTER ALL
	MOVE	T1,UW.S0(R)	;[1132] LAST ADDRESS TO READ
XCMRED:	HRL	T1,P3		;[1132] FIRST,,LAST
	PUSHJ	P,@TB.IN(R)	;[1132] READ IN THE NEXT WINDOW
	JRST	XCMLUP		;[1132] LOOP BACK TO PROCESS THE NEXT PAGE
;HERE IF WE RAN OFF THE END OF THIS SEGMENT (LC OR HC).  WRITE ENOUGH
;ALLOCATED BUT ZERO PAGES INTO THE EXE DIRECTORY TO ALLOCATE THE REST
;OF THE CURRENT PSECT AS ALL ZEROS.

XCMBLK:	MOVE	R3,RC.HL(R2)	;[1132] GET FIRST WORD BEYOND PSECT END
	ADDI	R3,777		;[1132] LAST WORD TO ALLOCATE + A PAGE
	ANDCMI	R3,777		;[1132] GET START OF THAT PAGE
	SUB	R3,P3		;[1132] COMPUTE EXTRA PAGES THAT NEED ALLOCATING
	SUB	R3,LL.S0(R)	;[1132] P3 IS AN OFFSET, BUT R3 IS AN ADDRESS
	JUMPLE	R3,XCMNXP	;[1132] NONE, GO FIND THE NEXT PSECT TO PROCESS
	TXON	P4,ZEROF	;[1132] WERE WE WRITING ZEROS BEFORE THIS?
	JRST	XCMBL2		;[1132] NO, MUST START A NEW DIR ENTRY
	ADD	P3,R3		;[1132] KEEP OFFSET INTO SEGMENT CORRECT
	MOVSI	R3,(R3)		;[1132] PUT COUNT WHERE EXE DIR ENTRY WANTS IT
	ADD	P2,R3		;[1132] JUST BUMP REPEAT COUNT
	JRST	XCMNXP		;[1132] AND GO PROCESS THE NEXT PSECT


;HERE WHEN WE WANT TO WRITE AN ABZ DIRECTORY ENTRY, BUT WE HAVE ANOTHER
;TYPE OF ENTRY IN PROGRESS.  WRITE THE CURRENT ENTRY, THEN START A NEW ONE.

XCMBL2:	TXZ	P4,DATAF	;[1132] REMEMBER NO LONGER WRITING DATA
	TXZN	P4,GAPF		;[1132] WERE WE IN A GAP?
	PUSHJ	P,XCMPRD	;[1132] NO, WRITE THE DIRECTORY ENTRY
	ADDI	P1,(P4)		;[1132] BUMP FILE PAGE POINTER
	HLLZS	P4		;[1132] RESET FILE PAGE COUNT
	MOVE	P2,P3		;[1132] FIRST OFFSET TO WRITE
	ADD	P2,LL.S0(R)	;[1132] FIRST ADDRESS TO WRITE
	LSH	P2,-^D9		;[1132] FIRST PAGE NOT YET WRITTEN
	ADD	P3,R3		;[1132] KEEP OFFSET INTO SEGMENT CORRECT
	MOVSI	R3,-1000(R3)	;[1132] PUT COUNT WHERE EXE DIR ENTRY WANTS IT
	ADD	P2,R3		;[1132] INSERT REPEAT COUNT FROM ABOVE


;HERE TO ADVANCE TO THE NEXT PSECT, IF ANY

XCMNXP:	PUSHJ	P,ADVPSC	;[1132] CALL A SUBROUTINE TO DO THE WORK
	  JRST	XCMPRX		;[1132] ALL DONE, GO CLOSE THE FILE
	JRST	XCMLUP		;[1132] FOUND ANOTHER PSECT, LOOP BACK FOR IT
;ADVPSC -- SUBROUTINE TO ADVANCE TO THE NEXT PSECT.
;CALL:
;	SET UP P1-P4 AS IN XCMPRS
;	PUSHJ	P,ADVPSC
;	  ALL DONE
;	ANOTHER PSECT FOUND
;
;ON THE SKIP RETURN, P1-P4 HAVE BEEN SET UP TO POINT TO THE START OF
;THE NEXT PSECT, INCLUDING PSECT PROPERTIES IN P1.
;THIS ROUTINE ALSO CHECKS TO SEE IF THE OVERLAY SYMBOL TABLE NEEDS TO
;BE APPENDED AFTER THE PSECT OR SEGMENT THAT JUST GOT WRITTEN, AND
;APPENDS IT IF SO.


ADVPSC:
IFN FTOVERLAY,<
	CAIN	R,1		;[1132] IN LOW SEGMENT?
	CAMGE	P3,HL.S1	;[1132] AND JUST FINISHED IT?
	JRST	ADVPS1		;[1132] NO, PROCEED
	SKIPL	LNKMAX		;[1132] YES, LOADING OVERLAYS?
	SKIPN	JOB116		;[1132] AND SYMBOLS NEED INSERTING?
	JRST	ADVPS1		;[1132] NO, PROCEED
	PUSHJ	P,XCMPOV	;[1132] YES, PUT SYMBOLS INTO EXE FILE
ADVPS1:
> ;END IFN FTOVERLAY

	ADD	P3,LL.S0(R)	;[1132] P3 WILL BE AN ADDRESS FOR THIS ROUTINE
	AOS	R,RC.CUR	;[1132] GET PSECT INDEX OF NEXT PSECT
	CAMG	R,RC.NO		;[1132] IS THERE A NEXT ONE?
	JRST	ADVPS2		;[1132] YES, GO PROCESS IT
	SOS	(P)		;[1132] GIVE NON-SKIP RETURN
	JRST	ADVPS6		;[1132] BUT WRITE CURRENT ENTRY FIRST


;HERE WHEN THERE IS ANOTHER PSECT, AND R CONTAINS ITS INDEX.
;POINT R AND R2 TO IT, THEN SET UP ITS PSECT PROPERTIES IN R3

ADVPS2:	MOVE	R2,@RC.TB	;[1132] POINT TO RC BLOCK FOR PSECT
	MOVE	R,RC.SG(R2)	;[1132] PUT SEGMENT PSECT IS IN INTO R
	MOVX	R3,SV%WRT	;[1132] GET ASSUMED PSECT PROPERTY
	MOVE	T1,RC.AT(R2)	;[1132] GET REAL PSECT PROPERTIES
	TXNE	T1,AT.RO	;[1132] EXPLICITLY READ-ONLY?
	TXZ	R3,SV%WRT	;[1132] YES, CLEAR WRITE BIT
	CAIE	R,2		;[1132] IS THIS THE HIGH SEGMENT?
	JRST	ADVPS4		;[1132] NO, PSECT PROPERTIES OK AS THEY ARE
IFE TOPS20,<
	TXO	R3,SV%HIS	;[1132] TOPS-10 HIGH SEG, READ-ONLY
	TXNN	T1,AT.RW	;[1132] EXPLICITLY WRITE-ENABLED?
	TXZ	R3,SV%WRT	;[1132] NO, WRITE-LOCK IT
	MOVE	T1,SSEXT	;[1132] GET SAVE/SSAVE FLAGS
	TXNE	T1,SS.SHR	;[1132] USER TYPE /SSAVE?
> ;END IFE TOPS20
	TXO	R3,SV%SHR	;[1132] /SSAVE OR TOPS-20, MARK SHARABLE

;FALL INTO NEXT PAGE
;HERE WHEN PSECT PROPERTIES COMPUTED IN R3.
;NOW DETERMINE WHETHER TO STORE THIS DIRECTORY ENTRY AND START ANOTHER,
;OR TO JUST LET THIS ONE CONTINUE.
;CAN ONLY LET THIS ONE CONTINUE IF NEXT PSECT IS ADJACENT WITH SAME PROPERTIES.

ADVPS4:	MOVE	T1,RC.IV(R2)	;[1132] GET BOTTOM OF NEW PSECT
	ANDCMI	T1,777		;[1132] ROUND DOWN TO PAGE BOUND
	CAMLE	T1,P3		;[1132] IS THERE A PSECT GAP HERE?
	JRST	[MOVE P3,T1	;[1132] YES, START NEXT LOOP AT BASE OF NEW ONE
		JRST ADVPS6]	;[1132] AND GO DUMP THIS DIRECTORY ENTRY
	MOVE	T2,R3		;[1132] COPY OF PSECT PROPERTIES
	XOR	T2,P1		;[1132] COMPARE WITH OLD
	TXNN	T2,777B8	;[1132] SAME AS LAST TIME?
	JRST	ADVPS8		;[1132] YES, CAN CONTINUE CURRENT DIR ENTRY


;ENTER HERE IF ALL DONE TO WRITE OUT THE LAST DIRECTORY ENTRY AND RETURN.

ADVPS6:	TXC	P4,DATAF!ZEROF	;[1132] XCMPRD WANTS THE FLAGS REVERSED
	TXNN	P4,GAPF		;[1132] IN A GAP FROM LAST TIME?
	PUSHJ	P,XCMPRD	;[1132] NO, WRITE CURRENT DIR ENTRY
	ADDI	P1,(P4)		;[1132] BUMP FILE PAGE COUNT
	MOVX	P4,GAPF		;[1132] FLAG NOW IN A GAP, CLEAR RH P4
ADVPS8:	SUB	P3,LL.S0(R)	;[1132] MAKE P3 AN OFFSET INTO NEW SEGMENT
	TXZ	P1,777B8	;[1132] CLEAR OLD PSECT PROPERTIES
	IOR	P1,R3		;[1132] SET NEW PSECT PROPERTIES
	JRST	CPOPJ1		;[1132] GIVE GOOD RETURN TO CALLER
;HERE TO WRITE OUT A DIRECTORY ENTRY

XCMPRD:	PUSHJ	P,XCMPXD	;SEE IF ENOUGH ROOM
	MOVEM	P1,(W1)		;STORE DIRECTORY PTRS
	TXNN	P4,ZEROF	;[1132] ZERO PAGE? (FLAGS ALREADY CHANGED)
	HLLZS	(W1)		;YES, SO NO FILE PAGES
	PUSHJ	P,XCMPXD	;SECOND WORD 
	MOVEM	P2,(W1)		;[1132]
	POPJ	P,		;[1132]
;HERE TO ALLOCATE A DIRECTORY ENTRY IF SUFFICIENT ROOM EXISTS.
;IF NOT, EXTEND THE FILE BY ONE PAGE TO MAKE ROOM FOR ANOTHER
;PAGE OF DIRECTORY.

XCMPXD:	AOBJN	W1,CPOPJ	;ALLOCATE IF ENOUGH ROOM


;WRITE THE CURRENT PAGE OF THE EXE DIRECTORY TO DISK.
;THEN START FROM THE FRONT OF THE FILE, AND FIX ALL PAGES OF
;EXE DIRECTORY PRESENT, INCLUDING THE ONE WE JUST WROTE.

	HRLOI	T3,-1000-1	;[1132] FORM IOWD TO IN CORE EXE DIRECTORY
	ADD	T3,EXEDIR	;[1132] ..
	SETZ	T4,		;[1132] TERMINATE IO LIST
	USETO	DC,@EXEBLK	;[1132] SET TO LATEST EXE DIRECTORY BLOCK
	OUT	DC,T3		;[1132] WRITE THE DIRECTORY
	  CAIA			;[1132] SUCCESS
	JRST	E$$EOE		;[1174] IO ERROR
	MOVEI	W1,1		;[1132] NOW LOOP OVER DIR, STARTING AT BLOCK 1
XCMPXE:	USETI	DC,@W1		;[1132] SET ON NEXT PAGE OF EXE DIR
	IN	DC,T3		;[1132] READ IT INTO SCRATCH PAGE
	  CAIA			;[1132] OK
	JRST	E$$EOE		;[1174] FAILED
	MOVE	T2,EXEDIR	;[1132] NOW SETUP AOBJN PTR TO EXE DIR PAGE
	HRLI	T2,-400		;[1132] COUNT OF DIR ENTRIES THIS PAGE
XCMPXF:	MOVE	T1,1(T2)	;[1132] GET 1ST WORD OF NEXT ENTRY
	TRNE	T1,-1		;[1132] AN ABZ POINTER?
	AOS	1(T2)		;[1132] NO, BUMP THE FILE PAGE NUMBER
	ADDI	T2,1		;[1132] SKIP 2ND WORD OF THIS DIR ENTRY
	AOBJN	T2,XCMPXF	;[1132] LOOP OVER THE ENTIRE PAGE
	USETO	DC,@W1		;[1132] POINT TO WHERE WE GOT THE PAGE
	OUT	DC,T3		;[1132] PUT IT BACK, SLIGHTLY MODIFIED
	  CAIA			;[1132] OK
	JRST	E$$EOE		;[1174] I/O ERROR
	ADDI	W1,4		;[1132] BLOCK NUMBER OF NEXT PAGE
	CAMG	W1,EXEBLK	;[1132] MORE DIRECTORY PAGE(S) TO PROCESS?
	JRST	XCMPXE		;[1132] YES, PROCESS THEM
	MOVEM	W1,EXEBLK	;[1132] PAGE WE'RE FREEING UP FOR MORE DIRECTORY
;FALL IN FROM ABOVE

;NOW TO LOOP OVER THE FILE BACKWARDS, MOVING ALL OF THE DATA PAGES
;ONE PAGE HIGHER.

	MOVEI	W1,-1(P1)	;[1132] LAST PAGE WRITTEN
	ADDI	W1,0(P4)	;[1132] PLUS ANY FOUND IN THIS DIR ENTRY
	ASHC	W2,-^D27	;[1132] NEED TO LOOK AT IOWD, SINCE PAGES
	ADD	W1,W2		;[1132]   IT POINTS TO HAVEN'T BEEN WRITTEN
	ASHC	W2,^D27		;[1132] RESET IOWD TO PREVIOUS VALUE
	SETZ	W3,		;[1132] CLEAR SIGN BIT LEFT FROM ASHC
	LSH	W1,2		;[1132] CONVERT PAGE TO BLOCK NUMBET
	ADDI	W1,1		;[1132] BLOCK NUMBERS START AT 1
	MOVEI	T2,10(W1)	;[1132] REMEMBER NEXT BLOCK TO WRITE FOR LATER
XCMPXG:	CAMGE	W1,EXEBLK	;[1132] ANY DATA PAGES LEFT TO COPY?
	JRST	XCMPXH		;[1132] NO, GO FINISH UP
	USETI	DC,@W1		;[1132] POINT TO NEXT DATA PAGE
	IN	DC,T3		;[1132] READ IT
	  CAIA			;[1132] OK
	JRST	E$$EOE		;[1174] ERROR
	OUT	DC,T3		;[1132] WRITE IT INTO THE NEXT PAGE
	  CAIA			;[1132] OK
	JRST	E$$EOE		;[1174] ERROR
	SUBI	W1,4		;[1132] BACK UP ONE MORE DATA BLOCK
	JRST	XCMPXG		;[1132] LOOP OVER ALL DATA PAGES


;HERE WHEN THE DIRECTORY AND THE FILE HAVE BEEN UPDATED.
;FIX THE POINTERS THAT OUR CALLERS LOOK AT, THEN RETURN.

XCMPXH:	USETO	DC,@T2		;[1132] NEXT WRITE TO NEXT FREE BLOCK
	ADDI	P1,1		;[1132] THIS DIR ENTRY IS ONE OFF TOO
	MOVE	W1,EXEDIR	;[1132] RESET DIR AOBJN PTR FOR NEXT CALL
	HRLI	W1,-1000	;[1132] SET UP COUNT FOR INITIAL AOBJN
	HRLZ	T1,W1		;[1132] NOW ZERO THE DY AREA BLOCK
	HRRI	T1,1(W1)	;[1132] ..
	SETZM	0(W1)		;[1132] ..
	BLT	T1,777(W1)	;[1132] ..
	POPJ	P,		;[1132] RETURN TO CALLER
IFN FTOVERLAY,<

;HERE WHEN GENERATING AN EXE FILE FOR THE ROOT OF AN OVERLAID PROGRAM,
;AND IT IS TIME TO INSERT THE LOCAL SYMBOLS FROM THE LS AREA INTO THE
;EXE FILE.  ALL ZEROS BEFORE THE SYMBOLS AND THE FIRST PARTIAL PAGE OF
;SYMBOLS HAVE ALREADY BEEN COPIED INTO THE EXE FILE, SINCE THEY WERE
;PUT INTO THE LC AREA AT JBEXE.

XCMPOV:	HRRZ	T1,JOB116	;[1132] SYMBOLS ARE NOT PAGE ALIGNED IN LS
	ANDI	T1,777		;[1132] SO PUT OFFSET TO FIRST SYM IN R3
	MOVEI	R3,1000		;[1132] OFFSET IS REST OF PAGE NOT COPIED
	SUB	R3,T1		;[1132]   AT JBEXE
	SETZB	R2,P3		;[1132] ASSUME LS AREA ISN'T PAGING
	SKIPN	PAG.LS		;[1132] IS THE LS AREA PAGING?
	JRST	XOVDMP		;[1132] NO, JUST DUMP IT TO THE EXE FILE
	MOVE	T1,LW.LS	;[1132] CALCULATE UPPER WINDOW
	ADD	T1,LS.AB	;[1132] FROM LOWER WINDOW + SIZE
	SUB	T1,LS.LB	;[1132] SO WE CAN WRITE OUT CURRENT LS AREA
	MOVEM	T1,UW.LS	;[1132] SAVE IT IN CASE IT WAS -1
	HRL	T1,LW.LS	;[1132] FIRST,,LAST FOR LS.OUT
	PUSHJ	P,LS.OUT	;[1132] UPDATE THE DISK COPY
	PUSHJ	P,FR.CNT##	;[1132] SEE HOW MUCH ROOM IS LEFT
	MOVE	T2,LSYM		;[1132] COUNT OF WORDS IN THE LS AREA
	SUBI	T2,1		;[1132] CONVERT FIRST FREE TO LAST USED
	IORI	T2,777		;[1132] ROUND UP TO PAGE END
	MOVE	T3,LS.AB	;[1132] FIND CURRENT SIZE OF LS AREA
	SUB	T3,LS.LB	;[1132] AS END - START
	CAMG	T2,T3		;[1132] IS AREA BIG ENOUGH?
	JRST	XOVNXW		;[1132] YES, JUST DUMP IT TO THE FILE
	SUB	T2,T3		;[1132] EXTRA WE NEED
	CAMLE	T1,T2		;[1132] LESS THAN WE HAVE?
	MOVE	T1,T2		;[1132] YES, DON'T ASK FOR MORE THAN WE NEED
	SETOM	LS.PP		;[1132] DON'T PAGE THE LS AREA TO SATISFY THIS
	SPUSH	<P1,P2>		;[1132] SAVE CURRENT EXE DIR ENTRY
	MOVEI	P1,LS.IX	;[1132] EXPAND THE LS AREA
	MOVE	P2,T1		;[1132] BY THIS MUCH
	PUSHJ	P,LNKCOR##	;[1132] GO SHUFFLE
	  PUSHJ	P,E$$MEF##	;[1174] FR.CNT LIED!!
	SPOP	<P2,P1>		;[1132] RESTORE THE SACRED COWS
	SETZM	LS.PP		;[1132] LS AREA CAN PAGE NOW

;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE

;HERE WHEN THE LS AREA IS PAGING TO BRING THE NEXT WINDOW OF SYMBOLS
;IN TO BE WRITTEN TO THE EXE FILE.  P3 HAS THE FIRST ADDRESS TO READ IN
;STORED IN IT, AND WE WILL PUT THE COUNT OF HOW FAR THIS PASS FAILED TO
;FINISH BY IN R2.

XOVNXW:	MOVEM	P3,LW.LS	;[1132] INIT LOWER WINDOW
	ADD	P3,LS.AB	;[1132] NOW COMPUTE UPPER WINDOW
	SUB	P3,LS.LB	;[1132] AS LOWER+SIZE
	MOVEM	P3,UW.LS	;[1132] STORE FOR LS.IN
	ANDCMI	P3,777		;[1132] FIRST TO READ NEXT TIME
	MOVE	R2,LSYM		;[1132] END OF SYMBOLS
	SUBI	R2,1		;[1132] LAST WORD CONTAINING SYMBOLS
	IORI	R2,777		;[1132] THE END OF THAT PAGE
	SUB	R2,UW.LS	;[1132] FIND OUT HOW FAR YET TO GO
	JUMPGE	R2,XOVNX2	;[1132] ALL OK UNLESS THIS TIME WILL END IT
	ADDM	R2,LS.AB	;[1132] REDUCE SIZE OF WINDOW
	ADDM	R2,UW.LS	;[1132] AND LAST ADDRESS IN WINDOW
XOVNX2:	HRLZ	T1,LW.LS	;[1132] SET UP LOWEST,,HIGHEST
	HRR	T1,UW.LS	;[1132] FOR LS.IN
	PUSHJ	P,LS.IN		;[1132] READ IN THE NEXT BLOCK OF SYMBOLS
	JUMPLE	R2,XOVDMP	;[1132] IF LAST TIME, WRITE ALL OF LS AREA
	MOVE	T1,UW.LS	;[1132] NOT LAST TIME, ONLY WRITE THROUGH
	ANDCMI	T1,777		;[1132]   FIRST PART OF LAST PAGE
	TROA	T1,R3		;[1132] WILL GET REST OF THAT PAGE NEXT PASS
XOVDMP:	MOVE	T1,LSYM		;[1132] LAST TIME, WRITE THROUGH THE END
	MOVE	W2,LW.LS	;[1132] PUT IOWD TO SYMBOLS TO WRITE IN W2
	ADD	W2,R3		;[1132] DON'T START AT BEGINNING OF LS
	SUB	W2,T1		;[1132] -COUNT IS FIRST-LAST
	HRLZ	W2,W2		;[1132] -COUNT,,0
	HRR	W2,LS.LB	;[1132] -COUNT,,BOTTOM OF LS AREA
	ADDI	W2,-1(R3)	;[1132] BUT DON'T START WRITING AT START
	OUT	DC,W2		;[1132] WRITE THE SYMBOLS
	  TDZA	W2,W2		;[1132] CLEAR W2 AGAIN IN CASE DONE
	JRST	E$$EOE		;[1174] I/O ERROR
	JUMPG	R2,XOVNXW	;[1132] IF NOT DONE, LOOP BACK TO TRY AGAIN
	SKIPE	PAG.LS		;[1132] ALL DONE, ANY TEMP FILE?
	PUSHJ	P,LS.DLT	;[1132] YES, DELETE IT
	PUSHJ	P,LS.ZAP	;[1132] ALL DONE WITH LS AREA

;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE

;NOW THAT THE DATA HAS BEEN WRITTEN, UPDATE THE EXE DIRECTORY TO
;REFLECT THE CHANGE.  ALSO ZERO THE REST  OF THE LAST PAGE WITH A USETO.

	HRRZ	R3,JOB116	;[1132] START OF SYMBOL TABLE
	HLRE	T1,JOB116	;[1132] - COUNT
	SUB	R3,T1		;[1132] FIRST WORD BEYOND TABLE
	ADDI	R3,777		;[1132] ROUND UP TO NEXT PAGE BOUND
	ANDCMI	R3,777		;[1132] FIRST PAGE NOW FREE
	HRRZ	P3,JOB116	;[1132] FIRST WORD WRITTEN
	ADDI	P3,777		;[1132] ROUND UP TO PAGE BOUND
	ANDCMI	P3,777		;[1132] SO WE DON'T COUNT SYMS WRITTEN AT JBEXE
	SUB	R3,P3		;[1132] R3 NOW HAS COUNT OF WORDS WRITTEN HERE
	HRRZ	T1,P1		;[1132] FIRST DISK PAGE FREE BEFORE XCMPOV
	ADDI	T1,(P4)		;[1132] ACCOUNT FOR EXTRA OUTS DONE
	MOVE	R2,R3		;[1132] NUMBER OF WORDS WRITTEN HERE
	LSH	R2,-^D9		;[1132] NUMBER OF PAGES WE ADDED TO THE EXE FILE
	ADD	T1,R2		;[1132] NEW FIRST FREE = OLD + COUNT
	LSH	T1,2		;[1132] CONVERT TO BLOCKS FOR USETO
	USETO	DC,1(T1)	;[1132] SET FILE POINTER TO FIRST FREE BLOCK
	TXON	P4,DATAF	;[1132] NOW IN A DATA DIR ENTRY, FIRST TIME?
	JRST	XOVNWD		;[1132] YES, GO DUMP OLD DIR ENTRY AND START NEW
	ADD	P3,R3		;[1132] MAKE P3 BE THE FIRST FREE ADDRESS
	MOVSI	R3,(R3)		;[1132] TURN WORD COUNT INTO PAGE COUNT IN LH
	ADD	P2,R3		;[1132] BUMP COUNT IN DIR ENTRY
	ADD	P4,R2		;[1132] COUNT FILE PAGES WRITTEN HERE
	POPJ	P,		;[1132] DONE, BACK TO ADVPSC


;HERE TO START A NEW EXE DIRECTORY ENTRY

XOVNWD:	TXZ	P4,ZEROF	;[1132] NO LONGER WRITING AN ABZ ENTRY
	TXZN	P4,GAPF		;[1132] NOR IN A GAP. WERE WE?
	PUSHJ	P,XCMPRD	;[1132] NO, WRITE CURRENT DIR ENTRY
	ADDI	P1,(P4)		;[1132] BUMP FILE PAGE NUMBER
	HRR	P4,R2		;[1132] ACCOUNT FOR PAGES WRITTEN HERE
	MOVE	P2,P3		;[1132] FIRST WORD WE WROTE HERE
	LSH	P2,-^D9		;[1132] FIRST PAGE WE WROTE HERE
	ADD	P3,R3		;[1132] MAKE P3 POINT TO FIRST WORD BEYOND SYMS
	MOVSI	R3,-1000(R3)	;[1132] CONVERT WORD CNT INTO EXE DIR PAGE CNT
	ADD	P2,R3		;[1132] NOW HAVE A NEW EXE DIR SLOT
	POPJ	P,		;[1132] DONE
>;[1214] END IFN FTOVERLAY
;HERE WHEN DONE WRITING THE MEMORY IMAGE TO THE EXE FILE.
;WRITE THE START ADDRESS BLOCK, DELETE THE TEMP FILES, AND
;RETURN THE EXE DIRECTORY STORAGE TO FREE SPACE.

XCMPRX:	SKIPE	PAG.S1		;[1132] STILL GOT AN LC TEMP FILE?
	PUSHJ	P,LC.DLT	;[1132] YES, DELETE IT
	SKIPE	PAG.S2		;[1132] HOW ABOUT AN HC TEMP FILE?
	PUSHJ	P,HC.DLT	;[1132] YES, DELETE IT

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	E$$EOE		;[1174] 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	E$$EOE]		;[1174] ERROR
	MOVE	T1,EXEDIR	;GET BASE AGAIN
	MOVEI	T2,1000		;LENGTH
	PUSHJ	P,DY.RET##	;GIVE SPACE BACK
	JRST	ENDCMP		;CLOSE FILE


E$$EOE::PUSH	P,[DC]		;[1174]
	.ERR.	(ST,,V%L,L%F,S%F,EOE,<EXE file output error>) ;[1174]

>;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,E$$MEF##	;[1174] 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	E$$SOE		;[1212] 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
	JRST	E$$SOE		;[1174] PRINT ERROR AND DIE
;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	FINAL LOADING CLEAN-UP


;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	E01FRE		;[1174] REPORT RENAME ERROR
	SKIPE	PLOTSW		;WANT PLOT PACKAGE?
	JRST	LNKPLT##	;YES
	JRST	ENDSAV		;[1144] NO, RUN PROGRAM OR EXIT

;HERE ON A RENAME ERROR FOR THE OVERLAY FILE
E01FRE::PUSH	P,[%OC]		;[1174] 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	RUNEXE		;[1144] YES, RUN THE .EXE 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
SUBTTL	RUN THE PROGRAM


RUNEXE:	SKIPE	STADDR		;[1144] INFORM USER IF NO START ADDRESS
	JRST	RUNEX1		;[1144] NO
	AOS	ERRNO		;[1144] DON'T START PROGRAM IF NO START ADDR
E$$NSA::.ERR.	(MS,0,V%L,L%F,S%I,NSA,<No start address>) ;[1174]
RUNEX1:	SKIPE	ERRNO		;[1144] DON'T RUN IF ANY ERRORS
	SKIPGE	DEBUGSW		;[1144]   UNLESS DEBUGGING
	JRST	RUNEX2		;[1144] DO RUN PROGRAM
E$$DLT::.ERR.	(MS,0,V%L,L%F,S%W,DLT,<Execution deleted>) ;[1174]
	JRST	ENDZAP		;[1144] JUST ZERO MEMORY AND EXIT
SUBTTL	RUN THE PROGRAM FROM EXE FILE -- TOPS-20


IFN TOPS20,<
RUNEX2:	MOVE	T1,[R%ACS,,ACS]	;[1144] COPY RUN CODE TO WRITABLE PLACE
	BLT	T1,ACS+R%17	;[1144]   ..
	MOVE	T1,[POINT 7,RUNSPC] ;[1144] BUILD TOPS-20 FILE SPEC OF .EXE FILE
	MOVE	T4,IO.PTR+LC	;[1144]   ..
	MOVE	T2,I.DEV(T4)	;[1144]   COPY DEVICE NAME
	PUSHJ	P,SIXTO7	;[1144]     ..
	MOVX	T2,":"		;[1144]   COPY DEVICE DELIMITER
	IDPB	T2,T1		;[1144]     ..
	MOVE	T2,I.NAM(T4)	;[1144]   COPY FILE NAME
	PUSHJ	P,SIXTO7	;[1144]     ..
	MOVX	T2,"."		;[1144]   COPY FILE TYPE DELIMITER
	IDPB	T2,T1		;[1144]     ..
	HLLZ	T2,I.EXT(T4)	;[1144]   COPY FILE TYPE
	PUSHJ	P,SIXTO7	;[1144]     ..
	SETZ	T2,		;[1144]   TURN INTO ASCIZ STRING WITH A NUL
	IDPB	T2,T1		;[1144]     ..
	MOVX	T1,GJ%OLD+GJ%SHT;[1144] GO FIND THE FILE
	HRROI	T2,RUNSPC	;[1144]   ..
	GTJFN			;[1144]   ..
	  ERJMP	E$$GFE		;[1202] GETJFN FAILED FOR EXE FILE
	HRRM	T1,ACS+R%16	;[1144] PUT JFN IN GET JSYS ARGUMENT
	MOVE	T1,EXECSW	;[1144] GET ADDRESS TO START PROGRAM
	HRRM	T1,ACS+R%15	;[1144] STORE IN FINAL JRST
	MOVEI	T1,1000		;[1144] ASSUME WE'LL UNMAP ALL MEMORY PAGES
	SKIPE	DDTMAP		;[1144] SEE IF WE MAPPED IN DDT VIA /DEB:DDT
	MOVEI	T1,764		;[1144] YES--DON'T UNMAP IT THEN
	HRRM	T1,ACS+R%3	;[1144] STORE IN PMAP JSYS ARGUMENT
	PUSHJ	P,EXEMES	;[1144] PRINT PROGRAM EXECUTION MESSAGE

;FINAL EXECUTION. SET PROGRAM NAME, SET NEW SYMBOL TABLE POINTERS IF DDT, MOVE
;SUICIDE CODE TO ACS AND JUMP TO IT.

	SKIPN	T1,RUNAME	;[1144] SET PROGRAM NAME
	MOVE	T1,LODNAM	;[1144]   ..
	SETNM			;[1144]   ..
	SKIPN	DDTMAP		;[1144] SEE IF /DEB:DDT SPECIFIED
	JRST	RUNEX3		;[1144] NO--DON'T SET UP SYMBOL TABLE PTRS
	MOVE	T1,JOB116	;[1144] YES--FORCE-FEED SYMBOL TABLE PTRS TO DDT
	MOVEM	T1,@770001	;[1144]   AT LAST MINUTE FOR LINK DEBUGGERS
	MOVE	T1,JOB117	;[1144]   ..
	MOVEM	T1,@770002	;[1144]   ..
RUNEX3:	MOVE	R%17,[ACS,,R%0]	;[1144] COPY POKED CODE TO ACS
	BLT	R%17,R%17	;[1144]   ..
	JRST	R%4		;[1144] GO UMMAP PAGES, BRING IN PROG AND START
;SIXTO7 CONVERTS A SIXBIT WORD TO AN ASCII STRING WITHOUT TRAILING SPACES.
;CALL:
;	T1/	<BYTE POINTER TO STRING>
;	T2/	<SIXBIT WORD TO CONVERT>
;RETURNS WITH T1 UPDATED, T2 AND T3 DESTROYED.

SIXTO7:	JUMPE	T2,CPOPJ	;[1144] DONE IF SIXBIT HAS GONE TO 0
	SETZ	T3,		;[1144] CLEAR DESTINATION AC
	ROTC	T2,6		;[1144] EXTRACT NEXT SIXBIT CHARACTER
	ADDI	T3,"A"-'A'	;[1144] CONVERT TO ASCII
	IDPB	T3,T1		;[1144] STORE IN DESTINATION STRING
	JRST	SIXTO7		;[1144] LOOP UNTIL DONE

E$$GFE::.ERR.	(MS,.EC,V%L,L%F,S%F,GFE,<GTJFN% JSYS failed for file >) ;[1174]
	.ETC.	(STR,,,,,RUNSPC)

;FINAL SUICIDE CODE FOR RUNNING A PROGRAM ON TOPS-20.

R%ACS:	PHASE	0		;[1144] GET INTO THE ACS
R%0:!	0			;[1144] SEED FOR ZEROING ACS WHEN DONE
R%1:!	-1			;[1144] PMAP ARGUMENTS TO UNMAP ALL OF MEMORY
R%2:!	.FHSLF,,0		;[1144]   ..
R%3:!	PM%CNT+.-.		;[1144]   UNLESS /DEB:DDT THEN DON'T UNMAP UDDT
R%4:!	PMAP			;[1144] BEGINNING OF SUICIDE CODE--UNMAP PAGES
R%5:!	MOVE	R%1,R%16	;[1144] LOAD GET ARGUMENT
R%6:!	GET			;[1144] BRING IN PROGRAM
R%7:!	JSYS	147		;[1144] DO RESET JSYS TO CLEAR PSI, ETC.
R%10:!	DMOVEM	R%14,.JBBLT	;[1144] MOVE LAST CODE TO JOBDAT
R%11:!	JRST	.JBBLT		;[1144]   AND JUMP TO IT
R%12:!	0			;[1144] UNUSED
R%13:!	0			;[1144] UNUSED
R%14:!	BLT	R%17,R%17	;[1144] CODE IN JOBDAT--CLEAR ALL ACS
R%15:!	JRST	.-.		;[1144] POKED TO PROGRAM EXECUTION ADDRESS
R%16:!	.FHSLF,,.-.		;[1144] POKED TO GET JSYS ARGUMENT
R%17:!	R%0,,R%1		;[1144] BLT ARGUMENT TO CLEAR ACS
	DEPHASE
> ;[1144] END OF IFN TOPS20
SUBTTL	RUN THE PROGRAM FROM EXE FILE -- TOPS-10


IFE TOPS20,<
RUNEX2:	MOVE	T1,[U%LOW,,LOW]	;[1144] MOVE DOWN FINAL RUN UUO CODE
	BLT	T1,U%END	;[1144]   ..
IFE FTEXE,<
	SKIPN	T1,IO.PTR+HC	;[1144] GET HIGH SEG POINTER
> ;END IFE FTEXE
	MOVE	T1,IO.PTR+LC	;[1144] SETTLE FOR LOW SEG IF NO HIGH
	MOVE	T2,I.DEV(T1)	;[1144] SET UP RUN UUO DEVICE
	MOVEM	T2,U%RUNB+0	;[1144]   ..
	MOVE	T2,I.NAM(T1)	;[1144] SET UP FILE NAME
	MOVEM	T2,U%RUNB+1	;[1144]   ..
IFE FTEXE,<
	SKIPN	T1,IO.PTR+LC	;[1144] MAKE SURE POINTING AT LOW SEG
	JRST	RUNEX3		;[1144] HISEG ONLY, USE .LOW
	MOVE	T2,I.EXT(T1)	;[1144] MAY AS WELL USE KNOWN EXT
	TLNN	T2,-1		;[1144] EXTENSION KNOWN?
RUNEX3:	MOVSI	T2,'LOW'	;[1144] NO, USE .LOW
> ;END IFE FTEXE
IFN FTEXE,<
	MOVE	T2,I.EXT(T1)	;[1144] GET EXTENSION OF EXE FILE
> ;END IFN FTEXE
	HLLM	T2,U%RUNB+2	;[1144] STORE EXTENSION
	MOVE	T1,RUNCOR	;[1144] LOW SEGMENT SIZE FROM /RUNCOR:
	ADD	T1,RUNCOR+1	;[1144]   AND HIGH SEG SIZE
	MOVEM	T1,U%RUNB+5	;[1144] STORE AS RUN UUO ARGUMENT
	CAIGE	T1,U%END	;[1144] PREPARE TO SHRINK MEMORY TO LARGER
	MOVEI	T1,U%END	;[1144]   OF WHAT WE NEED AND WHAT PROGRAM NEEDS
	HRRM	T1,U%CORA	;[1144] STORE AS CORE UUO ARGUMENT
	HRRZ	T1,EXECSW	;[1144] COMPUTE RUN UUO OFFSET
	SUB	T1,STADDR	;[1144]   IN CASE WE START A DEBUGGER
	HRLM	T1,U%RUNA	;[1144] STORE IN RUN UUO ARGUMENT
	PUSHJ	P,EXEMES	;[1144] PRINT PROGRAM EXECUTION MESSAGES
	JRST	LOW		;[1144] GO SHRINK AND RUN PROGRAM
;FINAL SUICIDE CODE FOR RUNNING A PROGRAM ON TOPS-10.

U%LOW:	PHASE	.TEMP		;[1144] LOW MUST BE FIRST IN .TEMP
	DMOVE	T1,U%CORA	;[1144] LOAD UP CORE AND RUN UUO ARGS
	CORE	T1,		;[1144] REMOVE HIGH SEG AND SHRINK LOW SEG
	  JFCL			;[1144] DON'T WORRY IF FAILURE
	RUN	T2,		;[1144] RUN THE PROGRAM
	  HALT			;[1144] CAN'T--MONITOR PRINTS USEFUL MESSAGE
	EXIT			;[1144] IN CASE USER TYPES CONTINUE
U%RUNB:	.-.			;[1144] RUN UUO DEVICE
	.-.			;[1144]   FILE NAME
	.-.,,0			;[1144]   EXTENSION
	0			;[1144]   UNUSED
	0			;[1144]   PPN (FILE WRITTEN ON [-])
	.-.			;[1144]   MEMORY ARGUMENT
U%CORA:	1,,.-.			;[1144] CORE UUO ARG, POKED WITH LOW SEG SIZE
U%RUNA:	.-.,,U%RUNB		;[1144] RUN UUO ARG, POKED WITH RUN OFFSET
U%END=.-1			;[1144] LAST LOCATION IN PHASED CODE
	DEPHASE			;[1144] BACK TO THE REAL WORLD
LOWLEN==.-U%LOW			;[1144] LENGTH OF PHASED CODE FOR LATER
> ;END IFN TOPS10
SUBTTL	RUN THE PROGRAM FROM EXE FILE -- SUBROUTINES


;TERMES GIVES THE LINK TERMINATION MESSAGE AND CLOSES THE LOG FILE IF ANY. IF
;NECESSARY, THE LOG FILE IS RENAMED TO THE PROPER NAME AS WELL.

TERMES:
E$$FIN::.ERR.	(MS,0,V%L,L%I,S%I,FIN,<LINK finished>) ;[1174]
	SKIPN	IO.PTR+RC	;[1202] A REAL LOG FILE?
	SKIPGE	LOGTTY		;[1202] OR USER'S TERMINAL?
	  JRST	E$$ELF		;[1202] YES, TYPE MESSAGE
	POPJ	P,		;[1202] NO, DONE
E$$ELF::.ERR.	(MS,,V%L,L%I,S%I,ELF,<End of log file>) ;[1174]
	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
E02FRE::PUSH	P,[%RC]		;[1174] CHANNEL FOR ERROR
	.ERR.	(LRE,,V%L,L%F,S%F,FRE)	;[616] SEND THE MESSAGE


;EXEMES GIVES THE PROGRAM EXECUTION MESSAGE. THIS INCLUDES THE NAME OF THE
;PROGRAM, OR THE DEBUGGER IF /DEBUG WAS SPECIFIED.

EXEMES:	SKIPE	T1,DEBUGSW	;[1144] IF DEBUGGING
	JRST	EXEME1		;[1144] THEN [LNKDEB debugger execution]
	SKIPN	T1,RUNAME	;[1144] ELSE [LNKXCT program execution]
	MOVE	T1,LODNAM	;[1144] GET PROGRAM NAME TO PRINT
E$$XCT::.ERR.	(MS,.EC!.EN,V%L,L%F,S%I,XCT) ;[1174]
	.ETC.	(SBX,.EC!.EP,,,,T1)
	.ETC.	(JMP,.EC,,,,EXEME2)

EXEME1:	MOVEI	T1,@DEBNAM(T1)	;[1144] LOAD UP ASCIZ DEBUGGER NAME
E$$DEB::.ERR.	(MS,.EC!.EN,V%L,L%F,S%I,DEB) ;[1174]
	.ETC.	(STR,.EC!.EP,,,,T1)
EXEME2:	.ETC.	(STR,,,,,,< execution>)
	POPJ	P,		;[1144] DONE
;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
E03FRE::PUSH	P,IO.CHN	;[1174] 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	E01FLE##	;[1174] ???
	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	E$$EOI		;[1174] 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	E$$EOO		;[1174]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
E$$EOO::PUSH	P,[TC]		;[1174] TELL WHICH CHANNEL HAD THE ERROR
	.ERR.	(ST,,V%L,L%F,S%F,EOO,<Error on output>)

E$$EOI::;PUSH	P,IO.CHN	;[1174] CHANNEL ALREADY ON STACK
	.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	LOAD PROGRAM INTO MEMORY


;HERE TO BRING THE ENTIRE PROGRAM INTO MEMORY. IF NOT PAGING, THIS ONLY INVOLVES
;COMPACTING THE LC AND HC AREAS DOWN TOWARD 0 AS FAR AS POSSIBLE. IF PAGING,
;MINIMIZE DISK TRANSFERS BY MOVING THE WINDOW (VIA BLT OR POP LOOP) TO ITS FINAL
;LOCATION, THEN READING IN THE REST OF THE APPROPRIATE OVERFLOW FILE AROUND THE
;WINDOW.

JBLOAD:	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
	MOVEM	T1,DY.UB	;[1147] MAKE SURE UB IS UP TO DATE
	ADDI	T1,1		;NEXT FREE
	MOVEM	T1,LC.LB	;MAKE LOWEST FOR LOW CODE
	ADD	T1,HC.S1	;HOW MUCH WE NEED
	SUBI	T1,1		;[1146] LB + LENGTH - 1 FOR LAST NEEDED
	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,JBGCL	;[1170] GO MOVE IF NO HI SEG
	ADDI	T1,1		;LOWER BOUND FOR HISEG
	MOVEM	T1,HC.LB	;RESET IT
	ADD	T1,HC.S2	;[1170] HIGHEST LOC WE NEED
	SUBI	T1,1		;[1146] LB + LENGTH - 1 FOR LAST NEEDED
	IORI	T1,.IPM		;BLOCK BOUND
	MOVEM	T1,HC.AB
	IOR.	T1,.PGSIZ	;UPTO PAGE (OR K) BOUND
	MOVEM	T1,HC.UB	;FOR VERY TOP
;FALL IN FROM ABOVE IFF WE HAVE A HIGH SEGMENT (HC AREA)
;NOW DO THE FOLLOWING:
;
; 1.	IF THE LC AREA IS SO HIGH THAT IT MIGHT GET OVERWRITTEN WHEN WE MOVE THE
;	HC AREA TO WHERE IT BELONGS, THEN MOVE THE LC AREA DOWN OUT OF THE WAY.
; 2.	MOVE THE HC AREA TO WHERE IT BELONGS, AND READ IN ANY DATA STILL OUT IN
;	OVERFLOW FILES.
; 3.	MOVE THE LC AREA TO WHERE IT BELONGS, AND READ IN ANY DATA STILL OUT IN
;	OVERFLOW FILES.
; 4.	DO A CORE UUO TO GET RID OF CORE FOR TABLES NO LONGER NEEDED.
; 5.	MAKE SURE THE CORE BETWEEN AREAS IS STILL ZERO AFTER ALL THIS MOVING.
;
;ENTER FROM ABOVE AT JBGCL (STEP 3) IF WE DON'T HAVE A HIGH SEG.

	MOVEI	R,LC.IX		;[1170] POINT TO LOW SEG FOR JBCGM
	CAMLE	P3,LC.AB	;[1170] MIGHT LC AREA BE WIPED BY MOVING HC?
	PUSHJ	P,JBGCM		;[1170] YES, MOVE LC AREA FIRST
	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
	SKIPN	T1,HC.UB	;[1170] GET LAST LOCATION USED
	MOVE	T1,LC.UB	;[1170] NO HI SEG, END OF LOW IS LAST USED
	IOR.	T1,.PGSIZ	;[1170] UP TO PAGE BOUND IF NEEDED
	CAME	T1,.JBREL	;[1170] ALREADY THE RIGHT SIZE?
	CORE	T1,		;[1170] NO, SHRINK DOWN (OR GROW???)
	  JFCL			;[1170] ALREADY WAS THE RIGHT SIZE
				;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	-1(T1)		;[1170] CLEAR FIRST WORD
	BLT	T1,@TAB.UB(R)	;AND REST
JBGCZ1:	SOJG	R,JBGCZ		;NOW FOR LOW SEG
	JRST	JBEXIT		;[1146] PROGRAM NOW ALL IN MEMORY
;HERE TO MOVE CODE FOR EITHER SEG AND READ IN DATA

	P0==P1-1		;[1146] USED FOR REFERENCING P1 OR P2 VIA R

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,JBGCM		;[1170] MOVE THE AREA, UP OR DOWN
				;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
	POPJ	P,		;[1170] ALL DONE
	EXCH	T1,UW.S0(R)	;GET BASE
	HRLZI	T1,1(T1)	;FIRST LOC TO READ
	HRR	T1,UW.S0(R)	;LAST
	PJRST	@[EXP LC.IN##,HC.IN##]-1(R)	;[1170] READ IT IN AND RETURN
;SUBROUTINE TO MOVE AN AREA TO ITS FINAL RESTING PLACE.
;CALL WITH:
;	R/ INDEX TO SEGMENT, ??.IX
;	P1-P4/ OLD LB/AB OF AREAS
;	??.LB&AB/ NEW LB/AB OF AREAS
;
;UPDATES P1-P4 TO INDICATE THE AREA HAS BEEN MOVED.
;THIS SUBROUTINE USES BLTS, A PIECE AT A TIME IF OVERLAPPING UPWARDS.

JBGCM:	MOVE	W1,HC.S0(R)	;[1170] FIRST, CALCULATE LAST DEST+1
	SUBI	W1,1		;[1170] DEPENDS ON IF PAGING, AND
	IORI	W1,.IPM		;[1170]   WHERE WINDOW IS IF SO
	SKIPE	PAG.S0(R)	;[1170] PAGING?
	CAMG	W1,UW.S0(R)	;[1170] YES, DOES WINDOW POINT TO END OF AREA?
	  CAIA			;[1170] NOT PAGING OR WINDOW AT END
	MOVE	W1,UW.S0(R)	;[1170] WINDOW IN MIDDLE, STOP BLT AT UW
	ADDI	W1,1		;[1170] CONVERT LAST DEST TO FIRST NOT TOUCHED
	ADD	W1,TAB.LB(R)	;[1170] FORM ABSOLUTE ADDRESS
	MOVE	T1,TAB.LB(R)	;[1170] NOW CALCULATE FIRST DESTINATION ADDR
	ADD	T1,LW.S0(R)	;[1170] WHERE CURRENT WINDOW GOES IN NEW LC AREA
	MOVE	T3,W1		;[1170] T1 GETS TOTAL LENGTH TO MOVE
	SUB	T3,T1		;[1170] LAST+1-FIRST IS LENGTH
	MOVE	T4,T1		;[1170] T4 GETS OFFSET (HOW FAR TO MOVE)
	SUB	T4,P0(R)	;[1170] THIS IS ALSO CHUNK SIZE IF OVERLAPS UP
	SKIPG	T4		;[1170] MOVE DOWN OR IN PLACE?
	MOVE	T4,T3		;[1170] YES, MOVE ENTIRE THING IN ONE PIECE
	HRLS	T4		;[1170] FORM CHUNK SIZE,,CHUNK SIZE (FOR BLT AC)
	MOVEI	W3,-1(W1)	;[1170] W1 GETS LAST DEST
	MOVE	T2,P0(R)	;[1170] T2 GETS LAST SOURCE + 1
	ADD	T2,T3		;[1170] FOR LH OF W1 AS PROTOTYPE BLT POINTER
	HRLM	T2,W1		;[1170] W1/ LAST SRC+1,,LAST DST+1
	MOVEM	T1,P0(R)	;[1170] UPDATE P1/P2 SO WE KNOW WE DID THIS

	;  ..
	;  ..

;LOOP BACK HERE TO DO EACH NEW PIECE OF THE BLT. THIS CODE USES ACS AS FOLLOWS:
;
;	T3/	TOTAL # WORDS LEFT TO MOVE
;	T4/	CHUNK SIZE,,CHUNK SIZE (.GT. T3 IF LAST OR ONLY TIME)
;	W1/	LAST SRC+1,,LAST DEST+1 FOR NEXT BLT
;	W2/	SCRATCH AC FOR BLT
;	W3/	LAST DEST FOR NEXT BLT
;
;W1 AND W3 ARE DECREMENTED BY CHUNK SIZE WITH EACH BLT UNTIL DONE.

JBGCM6:	CAIGE	T3,(T4)		;[1170] LAST (OR ONLY) TIME?
	JRST	JBGCM8		;[1170] YES, GO ADJUST CHUNK SIZE ETC.
	SUB	W1,T4		;[1170] DECREMENT PROTOTYPE BLT POINTER
	MOVE	W2,W1		;[1170] SCRATCH COPY FOR BLT
	BLT	W2,(W3)		;[1170] BLT NEXT PIECE
	SUBI	W3,(T4)		;[1170] DECREMENT LAST BLT ADDRESS
	SUBI	T3,(T4)		;[1170] DECREMENT TOTAL LEFT TO DO
	JRST	JBGCM6		;[1170] LOOP BACK


;HERE THE LAST TIME

JBGCM8:	JUMPE	T3,CPOPJ	;[1170] ALL DONE?
	MOVE	T4,T3		;[1170] DO WHAT'S LEFT
	HRLS	T4		;[1170] SET NEW CHUNK SIZE
	JRST	JBGCM6		;[1170] BACK THROUGH THE LOOP, ONE MORE TIME
SUBTTL	HERE TO BLT DOWN AREA AND EITHER GO TO EXECUTION OR EXIT


JBEXIT:	SKIPE	IO.PTR+%XC	;[1146] 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	STADDR		;WARN USER IF NO STARTING ADDRESS
	JRST	JBEX10		;IS A STARTING ADDRESS, KEEP GOING
E01NSA::.OERR.	[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
IFN TOPS20,<
	SKIPN	DDTMAP		;[1145] DDT MAPPED FROM /DEBUG:DDT?
	JRST	JBEX1A		;[1145] NO--NOTHING TO DO
	MOVE	T2,.JBSYM(T1)	;[1145] YES--FORCE-FEED SYMBOL TABLE
	MOVEM	T2,@770001	;[1145]   TO DDT
	MOVE	T2,.JBUSY(T1)	;[1145]   ..
	MOVEM	T2,@770002	;[1145]   ..
JBEX1A:
>
	MOVE	T2,.JBDDT(T1)	;[1145] GET DEBUGGER ADDRESS
;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 TOPS-20, 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,[[ASCIZ /%LNKDLT	Execution deleted/],,%TMES] ;[1144]
	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
E01XCT::			;[1174]
E01DEB::.OERR.	%TMES		;[1174] LNKDEB OR LNKXCT
%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 TOPS-20 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	E01RME		;[1174] 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
E$$RME::.OERR.	%VMRERR		;[1174] LNKRME
	JRST	%REMAP		;NOW TRY AGAIN
E01RME::.OERR.	%RMPE		;[1174] LNKRME
	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		;TOPS-20 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
IFE TOPS20,<
U	(LOW,LOWLEN)		;[1144] LOW CODE FOR RUN UUO--MUST BE FIRST
>
IFN TOPS20,<
U	(ACS,20)		;[1144] PLACE TO WORK ON SUICIDE CODE
U	(RUNSPC,4)		;[1144] ASCIZ FILE SPEC FOR EXE FILE
> ;END IFN TOPS20
U	(TTLPTR)		;BACK POINTER TO LAST SUBPROGRAM
U	(JOBPTR)		;POINTER TO COPY OF JOBDAT AREA
U	(JBHPTR)		;DITTO FOR HIGH SEG
IFE FTEXE,<
U	(LSTPAG)		;-1 WHEN LAST PAGE IS IN CORE
> ;END IFE FTEXE
U	(ERRNO)			;.JBERR COUNT
U	(JOB116)		;.JBSYM FOR .SYM FILE
U	(JOB117)		;.JBUSY FOR .SYM FILE
U	(SYMDEW)		;[1172] RESERVE SPACE IN SYMBOL TABLE
U	(SYMFUL)		;[1172] SYMOUT HAS NON-SKIPPED ONCE
SUBTTL	THE END


XITLIT:	END	LNKXIT