Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_1_19910112 - 6-1-monitor/postld.mac
There are 51 other files named postld.mac in the archive. Click here to see a list.
;------------------------- Autopatch Tape # 13 -------------------------
; *** Edit 7215 to POSTLD.MAC by GRANT on 20-Dec-85, for SPR #20966
; Insure that DDT gets the correct start address for the symbol table 
;------------------------- Autopatch Tape # 12 -------------------------
; UPD ID= 2302, SNARK:<6.1.MONITOR>POSTLD.MAC.12,  19-Jul-85 16:41:20 by MOSER
;TCO 6.1.1492 - MORE JFNS NO SZCOD
;<6-1-MONITOR.FT6>POSTLD.MAC.2, 12-Aug-85 17:11:20, Edit by WHP4
;Stanford changes:
; Use present TAD as system build date instead of last write date of VERSIO.MAC
;
; UPD ID= 2170, SNARK:<6.1.MONITOR>POSTLD.MAC.11,   5-Jun-85 10:50:00 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1635, SNARK:<6.1.MONITOR>POSTLD.MAC.10,  14-Mar-85 10:47:32 by GLINDELL
;  Fix UPD ID 1621 - forgot to load the value to test!
; UPD ID= 1621, SNARK:<6.1.MONITOR>POSTLD.MAC.9,  12-Mar-85 14:44:26 by GLINDELL
;  Add typeout of configuration switches (DEBUG, DCN and NETN) to BUGSTRINGS.
; UPD ID= 1606, SNARK:<6.1.MONITOR>POSTLD.MAC.8,   7-Mar-85 23:17:28 by GLINDELL
;TCO 6.1.1244 - check for no monitor PDV present.
; Also add information on how to debug POSTLD
; UPD ID= 1562, SNARK:<6.1.MONITOR>POSTLD.MAC.7,  24-Feb-85 13:05:43 by GLINDELL
;Remove RET at DOBUGS - not needed any more since 6.0 and 6.1 are split
; UPD ID= 947, SNARK:<6.1.MONITOR>POSTLD.MAC.6,   4-Nov-84 15:31:52 by GLINDELL
;ENCOD is now in XCDSEC
;Add table of contents
; UPD ID= 886, SNARK:<6.1.MONITOR>POSTLD.MAC.5,  15-Oct-84 17:54:55 by GLINDELL
;Type out by how many pages section 0 overflowed, if that happens
;Type out 'SAVING ...' after typeout of POSTLD image format, instead of before
;Make Peter Donahue happy by lowering A%VFST to 735000
; UPD ID= 875, SNARK:<6.1.MONITOR>POSTLD.MAC.4,  12-Oct-84 10:04:24 by GLINDELL
;Make POSTCD section-relative when testing with NRCOD for overlap in PCDSEC
; UPD ID= 871, SNARK:<6.1.MONITOR>POSTLD.MAC.3,  11-Oct-84 10:39:28 by GLINDELL
;Change ST%xxx to SY%xxx because of conflict with SERCOD
; UPD ID= 870, SNARK:<6.1.MONITOR>POSTLD.MAC.2,  11-Oct-84 09:55:15 by GLINDELL
;Rewrite POSTLD for 6.1 address space

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.

	SUBTTL Gunnar Lindell 11-Oct-1984
	SEARCH PROLOG
	TTITLE (POSTLD,, - Postload initialization)

	EXTERN MDDBLK,EDDBLK,NBUGP,FREMEM,FAKDDT,DDTPX,DDTPXA

;A note on how to debug POSTLD:
;
;The best way to debug POSTLD is probably to NOT use EDDT in user mode
; but use the standard user DDT.  For example:
;
;	@GET MON
;	@DDT /USE-SECTION:36	;Cannot use 37 since POSTLD runs there
;	Set your breakpoints and then 
;		0,,142$G
;
	SUBTTL	Table of Contents


;		Table of Contents for POSTLD
;
;
;			   Section			      Page
;   1. Table of contents. . . . . . . . . . . . . . . . . . .    2
;   2. List of POSTLD checks. . . . . . . . . . . . . . . . .    3
;   3. Symbols and macros . . . . . . . . . . . . . . . . . .    4
;   4. Entry vector and psect tables. . . . . . . . . . . . .    5
;   5. POSTLD main code . . . . . . . . . . . . . . . . . . .    6
;   6. Monitor date and time. . . . . . . . . . . . . . . . .    7
;   7. Check assembly symbols . . . . . . . . . . . . . . . .    8
;   8. The monitor PDV. . . . . . . . . . . . . . . . . . . .    9
;   9. Check psects . . . . . . . . . . . . . . . . . . . . .   10
;        9.1.   Section 0 . . . . . . . . . . . . . . . . . .   11
;        9.2.   Symbol section. . . . . . . . . . . . . . . .   12
;  10. Extended code section. . . . . . . . . . . . . . . . .   13
;  11. Check psects
;       11.1.   Extended data section . . . . . . . . . . . .   14
;  12. Write new psect origins. . . . . . . . . . . . . . . .   16
;  13. Sort and output BUGS.. . . . . . . . . . . . . . . . .   17
;  14. Make POSTLD image. . . . . . . . . . . . . . . . . . .   18
;  15. Copy the symbol tables . . . . . . . . . . . . . . . .   21
;  16. Set up MMAP. . . . . . . . . . . . . . . . . . . . . .   22
;  17. Set up EDDT in section 0 . . . . . . . . . . . . . . .   23
;  18. Write the POSTLD image to disk . . . . . . . . . . . .   24
;  19. Subroutines. . . . . . . . . . . . . . . . . . . . . .   26
;  20. Variables. . . . . . . . . . . . . . . . . . . . . . .   27
	SUBTTL List of POSTLD checks

;POSTLD will check various psect boundaries and relationships.
;
; Warnings will be issued if the following relations are not true:
;
;	MDDBLK .LT. 0
;	EDDBLK .LT. 0
;	RSDAT .LE. FFF .LE. RSDATZ
;	0,,XRCOD .EQ. NRCOD
;	0,,XRCOD - 0,,BGPTRZ .GE. NRCODZ - NRCOD - 100000
;
; The symbol table will be truncated unless
;	Symbol_table_size .LE. ERCOD - 1 - 10000 - NRVAR
;
; Adjust psect origins unless:
;
;	RSCOD .EQ. 1000
;	RSCODZ .LT. INCOD
;	INCODZ .LT. RSDAT
;	RSDATZ .LT. PPVAR
;	PPVARZ .LT. RSVAR
;	RSVARZ .LT. NRVAR
;	NRVARZ .LT. PSVAR
;	PSVARZ .LT. JSVAR
;	JSVARZ .LT. NRCOD
;	NRCODZ .LT. NPVAR
;	NPVARZ .LT. 777777
;
;	BGSTR .EQ. SYMSEC,,1000
;	BGSTRZ .LT. BGPTR
;	BGPTRZ .LT. SYPSX
;
;	ERCODZ .LT. SYMSEC,,A%VFST
;
;	XRCODZ .LT. XNCOD
;	XNCODZ .LT. ENCOD
;	0,,ENCODZ .LT. NPVAR
	SUBTTL	Symbols and macros

;***** A%VFST is the presumed start of BOOT.  Nothing above this limit
;***** will be loaded from the EXE file.  It would be better if this
;***** value were obtained from the BOOT assembly, but that is not
;***** linked with the monitor build.  Hence, this must be changed
;***** manually if BOOT grows.  There is a warning in BOOT if A%VFST
;***** changes.

A%VFST=:735000			;BOOT start

;Define # of words for undefined symbol table growth
SYMPAD==200			;200 words should do for a long time

;Define location of MDDT variables in XCDSEC
DDTPGA=:DDTPXA			;Mapped 1-1
DDTPG=:DDTPX			;Page #

NPDL==100			;POSTLD stack size

;Define macros for typeout and error
DEFINE TMSG ($MSG) <
	JRST [	HRROI T1,[ASCIZ \$MSG\]
		PSOUT%
		JRST .+1]
>

DEFINE FMSG ($MSG) <
	JRST [	HRROI T2,[ASCIZ \$MSG\]
		SETZ T3,
		SOUT%
		JRST .+1]
>

DEFINE JSERR <ERCAL .JSERR>

DEFINE JSHLT <ERJMP .JSHLT>
	SUBTTL	Entry vector and psect tables

	.ENDPS RSCOD		;End of RSCOD
	.PSECT POSTCD		;Put POSTLD in psect POSTCD

POSTLD::			;Relative 0 in POSTCD

ENTVEC:	JRST PLDCOD		;Entry vector/start address
	JRST PLDCOD		;	      reenter
	EXP SVNM		;	      version #

;Generate psect tables
;
;Each psect is given an index, designated by a symbol PSECT'I
; That is an index into the PSTBL that contains a pointer to a
; psect block for each psect.
;
;I.e.
;	PSTBL:	Ptr to psect0 block
;		Ptr to psect1 block
;		....
;
;A psect block contains the following entries
	$PNAM==0		;Ptr to ASCIZ string (name of psect)
	$PBGN==1		;Beginning address of psect
	$PEND==2		;End address of psect
	$PLEN==3
	$PNEW==4		;New beginning address of psect
	$PFLG==5		;Flags:
	  P.PSEU==400000,,0	  ;Set if psect is a pseudo psect

;DEFPSX/DEFPS1/DEFPS2 generates an entry in the psect table

;DEFPSX is top level, calls DEFPS1 for each psect in the argument list
DEFINE DEFPSX($PSECT),<
	XLIST
   IRP $PSECT,<
	DEFPS1($PSECT)
   >
	LIST
>

;DEFPS1 strips off a set of angle brackets, if necessary
DEFINE DEFPS1($PSECT),<DEFPS2($PSECT)>

;DEFPS2 does the work
DEFINE DEFPS2($PSECT,$CODE),<
	IFDIF <$CODE><PSEUDO>,<
		.PSECT $PSECT
		$PSECT'Z=:.-1
		$PSECT'L=:$PSECT'Z_-PGSFT
		.ENDPS $PSECT
	>

	$PSECT'I==..PSXN
	..PSXN==..PSXN+1

	[	POINT 7,[ASCIZ /$PSECT/]
		$PSECT
		$PSECT'Z
		$PSECT'Z - $PSECT + 1
		EXP 0
		IFIDN <$CODE><PSEUDO>,<EXP P.PSEU>
		IFDIF <$CODE><PSEUDO>,<EXP 0>
	]
>

PSTBL:

;Execute macro for all psect's
	..PSXN=0

;Note: the psect's will be output in the order they appear in the
; macros (i.e. by ascending psect index)

;Section 0
	DEFPSX <RSCOD,INCOD,RSDAT,PPVAR>
	DEFPSX <RSVAR,NRVAR,<PSVAR,PSEUDO>,<JSVAR,PSEUDO>>
	DEFPSX <NRCOD,<NPVAR,PSEUDO>>

;Section 5 (SYMSEC)
	DEFPSX <BGSTR,BGPTR,SYPSX,ERCOD>

;Section 6 (XCDSEC)
	DEFPSX <XRCOD,XNCOD,ENCOD>

;Section 13
	DEFPSX <<ERVAR,PSEUDO>,<ENVAR,PSEUDO>,<EPVAR,PSEUDO>>
	SUBTTL	POSTLD main code

PLDCOD:

;POSTLD initialization

	MOVE P,[IOWD NPDL,PDL]	;Initialize stack pointer

;Section 0 is mapped into the section POSTCD runs in. This will provide
; POSTLD with access to STKVAR routines, RSKP and so forth. It will also
; allow POSTLD to reference RSDAT variables with local references.

	MOVE T1,[.FHSLF+FH%EPN,,0] ;From page 0 in section 0
	MOVE T2,[.FHSLF+FH%EPN,,PCDSEC*1000] ; to page 0 in POSTCD section
	HRRI T3,<NRCODZ/PGSIZ>+1 ;  all pages including NRCODZ
	HRRI T4,<POSTCD&777777>/PGSIZ ; Get start of POSTCD (section-relative)
	CAMLE T3,T4		;  Will PMAP overlap POSTLD itself?
	IFNSK.			;  -yes,
	  TMSG <
%Warning: The end of NRCOD is higher than the section-relative start
	  of POSTLD. Most of monitor section 0 is mapped into the section
	  POSTLD runs in. This means that all of NRCOD cannot be mapped.
	  This may cause an illegal read or write in POSTLD. However, if
	  POSTLD completes, you can be assured that the image produced will
	  be legal.
>
	  MOVE T3,T4		;   Truncate NRCOD
	ENDIF.
	HRLI T3,(PM%CNT!PM%RD!PM%WR!PM%EPN) ;Read/write and repeat count
	PMAP%			;Do the mapping

;Now POSTLD can make local references to variables and routines in
; section 0. POSTLD uses this to write values to variables in RSDAT,
; to use subroutines in RSCOD (STKVAR e.g.) and to get the version
; string of the monitor.

	CALL RDTAD		;Set date and time of monitor
	CALL CHKREL		;Check relationship between symbols
	CALL MAKPDV		;Build the monitor PDV
	CALL VERPSX		;Verify all psects
	CALL WRTPSX		;Write the new psect origins
	CALL DOBUGS		;Sort BUGS. and write to BUGSTRINGS.TXT
	CALL MAKIMG		;Make section 0 and 1 be like POSTLD image
	CALL SETMMP		;Set up MMAP
	CALL STEDDT		;Set up EDDT in section 0
	CALL SAVIMG		;Save POSTLD image
             
	HALTF%			;All done
	JRST .-1		;Do not allow continue
	SUBTTL	Monitor date and time

;RDTAD - read date and time of monitor (from VERSIO.MAC)

RDTAD:
IFE STANSW,<
	HRROI T1,[ASCIZ /MON/]	;See if MON: is defined
	STDEV%
	IFSKP.			;Yes
	  HRROI T2,[ASCIZ /MON:VERSIO.MAC/] ; -then get VERSIO from MON:
	ELSE.			;No
	  HRROI T2,[ASCIZ /VERSIO.MAC/]	; -then get it from DSK:
	ENDIF.
	MOVX T1,GJ%OLD!GJ%SHT	;Short form, existing file
	GTJFN%			;Get jfn on file
	IFSKP.			; -file exists,
	  MOVEI T2,T2		;  Read into T2
	  MOVEI T3,1		;   one word (date and time last written)
	  RFTAD%		;  Result in T2
	  RLJFN%		;   so release jfn now
	   NOP			;    and ignore error return
	  MOVE T1,T2		;  Move date and time to T1
	ELSE.			; -file does not exist
	  TMSG <
%VERSIO.MAC not found. Current date and time used.
>
	  GTAD%			;  Get current date and time in T1
	ENDIF.
>;IFE STANSW
IFN STANSW,<
	GTAD%			; Get current date and time in T1
>;IFN STANSW
	MOVEM T1,SYSTAD		;Store in SYSTAD
	RET
	SUBTTL	Check assembly symbols

;CHKREL - check the relationship between various symbols
CHKREL:

;MDDBLK must be in page 0
	MOVX T1,MDDBLK
	CAIGE T1,PGSIZ
	IFSKP.
	  TMSG <
%Warning: MDDBLK is not in page 0.
>
	ENDIF.

;EDDBLK must also be in page 0
	MOVX T1,EDDBLK
	CAIGE T1,PGSIZ
	IFSKP.
	  TMSG <
%Warning: EDDBLK is not in page 0.
>
	ENDIF.

;FFF must be defined inside psect RSDAT. This is for user mode exec DDT.
	MOVX T1,FFF
	CAIL T1,RSDAT
	CAILE T1,RSDATZ
	IFNSK.
	  TMSG <
%Warning: FFF is not defined in psect RSDAT.
>
	ENDIF.

;The offset of XRCOD should be the same as the offset of NRCOD
	HRRZI T1,XRCOD		;We dont want section # (in left half)
	CAIN T1,NRCOD
	IFSKP.
	  TMSG <
%Warning: The offset of XRCOD is not the same as NRCOD.
>
	ENDIF.

;Verify that NRCOD will fit into section 1 of the POSTLD image between
; end of BGPTR and beginning of XRCOD. There should also be space for
; the CST's
	HRRZI T1,XRCOD		;Get offset of XRCOD
	SUBI T1,BGPTRZ		; and subtract end of BGPTR
	CAIL T1,<NRCODZ-NRCOD+100000> ;100000 is 4 CST's, 4Meg memory
	IFSKP.
	  TMSG <
%Warning: NRCOD will not fit into section 1 of the POSTLD image.
	  This can not be fixed up by POSTLD.
>
	ENDIF.

	RET			;End of CHKREL
	SUBTTL	The monitor PDV

;MAKPDV - set the monitor PDV
MAKPDV:

;LINK writes a PDV for the monitor. We need the PDV in order to locate
; the symbols. LINK will put the PDV in the symbol psect, right after the
; symbol table.
;
;In order for the monitor to know exactly where the PDV is, there
; is a predefined PDV, at PDVECT. The symbol vector follows immediately
; after the PDV, and both structures are in RSDAT. Having our own PDV
; means that RSDATZ can be trusted at runtime.
;
;What we want to do is:
;	1. Locate the PDV with name MON
;	2. Copy the symbol vector generated by LINK to our own symbol vector
;	3. Remove the PDV that LINK wrote
;	4. Add our own PDV with name MONITR
;	5. Set up PDVSYM and PDVUSY to point to the defined/undefined symbols
;	   subtable
;	6. Finally verify if the symbol table need to be truncated

;Use P1-P6 for the PDV argument block
	MOVEI T1,.POLOC		;Locate a specific PDV
	MOVEI T2,P1		;Argument block is in P1
	HRROI T3,[ASCIZ /MON/]	;PDV name to return
	MOVEI P1+.POCT1,4	;Argument block length
	MOVEI P1+.POPHD,.FHSLF	;Ourself
	MOVEI P1+.POCT2,1	;Read only 1 PDV (couldnt be any more)
	MOVEI P1+.PODAT,Q1	; into Q1
	PDVOP%
	JSHLT			;Cannot recover if we cant find the pdv
	HRRZ T1,P1+.POCT2	;Get count of PDVA's returned
	SKIPG T1		;Any found?
	IFNSK.			; -no, must give up
	  TMSG <
?Fatal error: cannot find a PDV for the monitor with name "MON".
 This should never occur, please check your link command file.
>
	  HALTF%
	ENDIF.
	MOVE P1,Q1		;PDVA to P1

;Move symbol vectors
	MOVE T2,.PVSYM(P1)	;Get address of symbol vector
	MOVE T1,(T2)		;Get count word from symbol vector
	CAIG T1,7		;Larger than 7?
	IFSKP.
	  TMSG <
?Fatal error: Symbol vector in PDV is larger than 7 words
>
	  HALTF%
	ENDIF.
	MOVE T3,[0,,PDVECT+.PVSYM+1] ;Destination
	EXTEND T1,[XBLT]	;Move the symbol vector

;Now remove the PDV that LINK wrote
	MOVE Q1,P1		;Save PDVA for a moment
	MOVEI T1,.POREM		;Remove PDVA
	MOVEI T2,P1		;Argument block is in P1-P6
	MOVEI P1+.POCT1,6	;6 words
	MOVEI P1+.POPHD,.FHSLF	;Ourselves
	SETZB P1+.POCT2,P1+.PODAT ;Clear count and data address
	MOVE P1+.POADR,Q1	;Get PDVA
	MOVE P1+.POADE,Q1	;Ending address
	PDVOP%
	JSERR			;Not fatal....

;Add our own PDV
	MOVEI T1,.POADD		;Add a PDVA
	MOVEI T2,P1		;Argument block is in P1-P6
	MOVEI P1+.POCT1,4	;4 words in argument block
	MOVEI P1+.POPHD,.FHSLF	;Ourselves
	MOVEI P1+.POCT2,1	;1 PDVA to add
	MOVEI P1+.PODAT,Q1	;Data in Q1
	MOVEI Q1,PDVECT		;Address of our PDV
	PDVOP%
	JSERR			;Not fatal....

;Set address of monitor PDV
	MOVEI T1,PDVECT		;Get address of PDV
	MOVEM T1,MONPDV		;Save it for EDDT/MDDT

;Now set up PDVSYM and PDVUSY to contain the address of the respective
; symbol subblocks
	MOVE P1,SYMBLK		;Get length of symbol vector
	IDIVI P1,3		;Make int # of subblocks
	MOVEI T1,SYMBLK+1	;Point to first subblock
	DO.
	  MOVE T2,.STDAT(T1)	;Get data type word
	  LDB T2,[POINTR T2,SY%TYP] ; and extract type field
	  CAIE T2,.R50D		;Defined symbol?
	  IFSKP.		; -yes,
	    MOVEI T3,PDVSYM	;  write address to PDVSYM
	  ELSE.			; -no,
	    MOVEI T3,PDVUSY	;  write address to PDVUSY
	  ENDIF.
	  MOVEM T1,(T3)		; and save into the variable
	  MOVEI T1,3(T1)	;Move to next subblock
	  SOJG P1,TOP.		;Loop back if more to do
	ENDDO.

;Now check if the symbol table need to be truncated
	MOVE T1,PDVSYM		;Get defined symbols
	MOVEI T2,<<ERCOD & 777777>-1-10000-NRVAR> ;Upper limit on symbol table
	LDB T3,[POINTR .STLEN(T1),SY%LEN] ;Get length of symbol table
	CAMG T3,T2		;Symbol table need to be truncated?
	IFSKP.			; -yes,
	  TMSG <
?Error:   the symbol table does not fit into section 0 of the POSTLD
	  image. You have to submit a new build with the psect files
	  POSTLD will write. The maximum size of the symbol table is
	  >
	  CALL OCTOUT		;Output max size in words
	  TMSG < octal words.
>
	ENDIF.
	RET			;End of MAKPDV
	SUBTTL	Check psects

;Define a macro that will simply verify that psect A will end before
; psect B or a specified limit

DEFINE CHKPSX($PSA,$PSB,$LIMIT) <
	XLIST
	MOVE Q1,PSTBL+$PSA'I
   IFB <$LIMIT>,<
	MOVE Q2,PSTBL+$PSB'I
   >
   IFNB <$LIMIT>,<
	SETO Q2,
	MOVE Q3,[$LIMIT]
   >
	CALL .CHPSX
	LIST
>

;VERPSX - verify all psects for overlaps
VERPSX:

;Output header: monitor name and version string
	TMSG <
>
	HRROI T1,TSVN		;System name and version string
	PSOUT%
	TMSG <

- Monitor runtime address space -

  Psect	      Start         End       Length       Free         Limit
>

;Verify all the psects
	CALL CHSEC0		;Check section 0
	CALL CHSYMS		;Check symbol section
	CALL CHXCOD		;Check extended code section
	CALL CHXDAT		;Check extended data section
	TMSG <
>				;Free line

;Type out # of overflows detected
	SKIPE OVRFLW		;Any at all?
	IFSKP.			; -no,
	  TMSG <
No psect overflows detected.
>
	ELSE.			; -yes,
	  TMSG <
? >
	  MOVEI T1,.PRIOU	;  Output to terminal
	  MOVE T2,OVRFLW	;  Get # of overflows
	  MOVX T3,FLD(^D10,NO%RDX) ; Radix 10
	  NOUT%
	   NOP
	  TMSG < overflow(s) detected.
>
	ENDIF.

	RET
	SUBTTL	Check psects -- Section 0

;Start with RSCOD, set its new start address to 1000
CHSEC0:	TMSG <

Section 0/1:

>
	MOVE Q1,PSTBL+RSCODI	;Point to RSCOD
	MOVEI T1,1000		;RSCOD default starting address
	MOVEM T1,$PNEW(Q1)	; and set the new

;Now verify all the psects in section 0
	CHKPSX (RSCOD,INCOD)
	CHKPSX (INCOD,RSDAT)
	CHKPSX (RSDAT,PPVAR)
	CHKPSX (PPVAR,RSVAR)
	CHKPSX (RSVAR,NRVAR)
	CHKPSX (NRVAR,PSVAR)
	CHKPSX (PSVAR,JSVAR)
	CHKPSX (JSVAR,NRCOD)
	CHKPSX (NRCOD,NPVAR)
	CHKPSX (NPVAR,<End of section 0>,777777)

;Type out # of free pages in section 0
; Equal to the number of pages remaining after NPVAR, counting the
; new start address of NPVAR
	MOVE Q1,PSTBL+NPVARI	;Point to NPVAR
	MOVE T1,$PNEW(Q1)	;Get new start address of NPVAR
	ADD T1,$PLEN(Q1)	; and add its length
	SOJ T1,			;  and make end address of new NPVAR
	MOVEI T2,777777		;Highest address in section 0
	SUB T2,T1		;Calculate # of free words in section 0
	SKIPL T2		;If negative, then section 0 overflow
	IFSKP.			; -yes, fatal overflow
	  TMSG <

?Section 0 overflow: rebuild monitor with a smaller configuration.
You need >
	  MOVMS T2		;  Get magnitude
	  ADDI T2,PGSIZ-1	;   and round upwards
	  LSH T2,-^D9		;    and make page number
	  CALL OCTOUT		;  Tell user bad news
	  TMSG < (octal) additional section 0 pages.

>
	ELSE.			; -no, all fits into section 0
	  LSH T2,-^D9		;  Make page number
	  TMSG <

There are >
	  CALL OCTOUT
	  TMSG < (octal) free pages in section 0.

>
	ENDIF.

	RET
	SUBTTL	Check psects -- Symbol section

;Check symbol section
CHSYMS:

;Type out banner
	TMSG <

Symbol section (SYMSEC):

>

;Start with BGSTR, set its new start address to SYMSEC,,1000
	MOVE Q1,PSTBL+BGSTRI	;Point to BGSTR
	MOVE T1,[SYMSEC,,1000]	;Start at SYMSEC,,1000
	MOVEM T1,$PNEW(Q1)	; and save

;Now verify psects in symbol section
	CHKPSX (BGSTR,BGPTR)
	CHKPSX (BGPTR,SYPSX)

;Free line since there will be a gap here
	TMSG <
>

;Do ERCOD

;Calculate the new start address
	MOVE Q1,PSTBL+ERCODI	;Point to ERCOD
	MOVE T1,[SYMSEC,,A%VFST] ;Get BOOT start address, but in SYMSEC
	SUB T1,$PLEN(Q1)	;Subtract length of BOOT
	TRZ T1,777		;Make it page even
	MOVEM T1,$PNEW(Q1)	; and save as ERCOD start address

;Verify ERCOD
	CHKPSX (ERCOD,<BOOT address>,<<SYMSEC,,A%VFST>>)

	RET
	SUBTTL	Extended code section

;Check extended code section
CHXCOD:

;Type out banner
	TMSG <

Extended code section (XCDSEC):

>

;Start with XRCOD, set its new start address to XCDSEC,,NRCOD
	MOVE Q1,PSTBL+XRCODI	;Point to XRCOD
	MOVE Q2,PSTBL+NRCODI	;Point to NRCOD
	MOVE T1,$PNEW(Q2)	;Get new start address of NRCOD
	HRLI T1,XCDSEC		; and make same offset in XCDSEC start of XRCOD
	MOVEM T1,$PNEW(Q1)	; and save

;Verify XRCOD, XNCOD and ENCOD
	CHKPSX (XRCOD,XNCOD)
	CHKPSX (XNCOD,ENCOD)
	CHKPSX (ENCOD,<Extended code overlays NRCOD>,<<XCDSEC,,<NPVAR-1>>>)

	RET
	SUBTTL	Check psects -- Extended data section

;CHXDAT - check extended data sectios
CHXDAT:

	TMSG <

Extended variables section (RESSEC):

>

;Start with ERVAR, and set its new start address
	MOVE Q1,PSTBL+ERVARI	;Point to ERVAR
	MOVE T1,[RESSEC,,1000]	;New start address
	MOVEM T1,$PNEW(Q1)	; and save it

;Now verify the psects
	CHKPSX (ERVAR,ENVAR)
	CHKPSX (ENVAR,EPVAR)
	CHKPSX (EPVAR,,<<RESSEC,,777777>>)

	RET

;.CHPSX - do the work for CHKPSX
;
;Entry:	Q1/ pointer to psect entry for lower psect
;	Q2/ pointer to psect entry for higher psect or -1
;	Q3/ limit if Q2 = -1

.CHPSX:	STKVAR <LIMIT,OVRLAP>
	SETOM LIMIT		;Assume no limit present
	SKIPGE Q2		;Is Q2 negative?
	  MOVEM Q3,LIMIT	; -yes, so there is a limit
	SETZM OVRLAP		;No psect overlap so far
	MOVE T1,$PEND(Q1)	;Get end of lower psect
	SKIPGE T2,LIMIT		;Get limit and check if there is any!
	IFSKP.			; -yes, there was
	  AOS T2		;  make into next free address
	ELSE.
	  MOVE T2,$PBGN(Q2)	; -no, get start of higher psect instead
	ENDIF.
	CAMGE T1,T2		;Compare
	IFSKP.			; -overlap
	 SETOM OVRLAP		;  ** overlap between these psects **
	 AOS OVRFLW		;  Count it
	ENDIF.
;Calculate new psect origin for the higher psect (provided no limit)
	SKIPL LIMIT		;Is there a limit set?
	IFSKP.			; -no, go ahead and calculate next psect
	  MOVE T1,$PNEW(Q1)	;  New start of lower
	  MOVE T2,$PLEN(Q1)	;  Get length of lower
	  ADDI T2,<PGSIZ-1>	;   and round up to whole pages
	  TRZ T2,777		;     and clear out page field
	  ADD T1,T2		;  Add to lower new start address
	  MOVEM T1,$PNEW(Q2)	;   makes new higher start address
	ENDIF.

;Now typeout this psect
;
;The display has the following layout:
;
;PSECT		Start	End	Length	Free	Limit	Notes

	TMSG <  >		;2 spaces
	MOVE T1,$PNAM(Q1)	;Get pointer to name of psect
	PSOUT%
	MOVEI T1,.CHTAB		;Then a <TAB>
	PBOUT%
	MOVE T2,$PBGN(Q1)	;Start
	CALL OCTOUC
	MOVE T2,$PEND(Q1)	;End
	CALL OCTOUC
	MOVE T2,$PLEN(Q1)	;Length
	CALL OCTOUC
	SKIPL T2,LIMIT		;Get limit value (if there is one)
	IFSKP.			; -none,
	  MOVE T2,$PBGN(Q2)	;   use next psect
	  SOJ T2,		;   But only go to the address just before,
				;   thats the limit
	ENDIF.
	SUB T2,$PEND(Q1)	; minus end of lower psect
	CALL OCTOUC		; is # of free words
	SKIPL T2,LIMIT		;Get limit value (if there is any)
	CALL OCTOUC		; -yes, type it out
	SKIPE OVRLAP		;Overlap for this psect?
	TMSG < ** Overlap **>
	TMSG <
>				;End typeout with a new line
	RET
	ENDSV.
	SUBTTL	Write new psect origins

;WRTPSX - write new psect origins to LNKNEW.CCL and PARNEW.MAC
WRTPSX:	STKVAR <LNKJFN,PARJFN>
	TMSG <
A potential set of new psect origins will be written into LNKNEW.CCL
and PARNEW.MAC.
>
	HRROI T1,[ASCIZ /LNKNEW.CCL/] ;File to open
	CALL OUTFIL		;Open outfile
	IFNSK.			; -error
	  TMSG <%Warning: failed to write LNKNEW.CCL
>
	  RET
	ENDIF.
	MOVEM T1,LNKJFN		;Save JFN

	HRROI T1,[ASCIZ /PARNEW.MAC/] ;For pseudo psects
	CALL OUTFIL		;Open outfile
	IFNSK.			; -error
	  TMSG <%Warning: failed to write PARNEW.MAC
>
	  RET
	ENDIF.
	MOVEM T1,PARJFN		;Save JFN

;Clear T3 (count word in SOUT%)
	SETZ T3,

;Output headers for both files
; T1 has PARJFN
	FMSG <;PSECT origins for monitor >
	HRROI T2,TSVN		;Name and version string
	SOUT%
	FMSG <
>

;Do the same for LNKJFN
	MOVE T1,LNKJFN
	FMSG <;PSECT origins for monitor >
	HRROI T2,TSVN		;Name and version string
	SOUT%
	FMSG <
>

;Loop over PSTBL and write the value in $PNEW to file. If the
; pseudo flag is set, then write it to PARNEW, else to LNKNEW.
	MOVSI P1,-..PSXN	;Get # of psects defined
	DO.			;LOOP over all psects
	  MOVE Q1,PSTBL(P1)	;  Get psect block pointer
	  MOVX T1,P.PSEU	;  Get pseudo flag
	  TDNE T1,$PFLG(Q1)	;  Is it set?
	  IFSKP.		;   -no, write to LNKNEW
	    MOVE T1,LNKJFN	;    so get the right JFN
	    FMSG </SET:>	;    LINK set psect switch
	    MOVE T2,$PNAM(Q1)	;    Get pointer to psect name
	    SOUT%		;     and put in file
	    MOVEI T2,":"	;    Colon before value
	    BOUT%		;     and put that in file
	  ELSE.			;   -yes, write to PARNEW
	    MOVE T1,PARJFN	;    so get that JFN
	    MOVE T2,$PNAM(Q1)	;    Get pointer to name
	    SOUT%		;     and put name in file
	    FMSG <=:>		;    Before value
	  ENDIF.
	  MOVE T2,$PNEW(Q1)	;  Get new psect origin
	  MOVX T3,FLD(^D8,NO%RDX) ; Output in radix 8
	  NOUT%			;  Do it
	    JSERR		;   -report error if there is one
	  FMSG <
>				;  End entry with a CRLF
	  AOBJN P1,TOP.		;  Loop back if more psects to do
	ENDDO.

;Now we have to write a psect switch for POSTCD itself into LNKNEW.CCL
; as well as a /SYMSEG switch
	MOVE T1,LNKJFN		;Get LNKNEW.CCL
	FMSG </SET:POSTCD:>
	MOVEI T2,PCDSEC		;POSTCD section #
	MOVX T3,FLD(^D8,NO%RDX)	;Radix 8
	NOUT%
	JSERR
	FMSG <750000
/SYMSEG:PSECT:SYPSX/UPTO:>
	MOVE Q1,PSTBL+SYPSXI	;Point to symbol table start
	MOVE T2,$PNEW(Q1)	;Get start of symbol table
	ADD T2,[<<ERCOD & 777777> - 1 - 10000 - NRVAR - SYMPAD>] ;Add max size
	MOVX T3,FLD(^D8,NO%RDX)	;Radix 8
	NOUT%			;Output it
	JSERR
	FMSG <
>

;Close the files
	MOVE T1,LNKJFN		;LNKNEW.CCL
	CLOSF%
	JSERR
	MOVE T1,PARJFN		;PARNEW.MAC
	CLOSF%
	JSERR

;All done, return
	RET
	ENDSV.
	SUBTTL	Sort and output BUGS.

;DOBUGS - sort all BUGS. and output them to BUGSTRINGS.TXT
DOBUGS:	STKVAR <BUGJFN>
	TMSG <
Writing sorted bug list >
	MOVSI Q1,-NBUGP		;AOBJN ptr to BGPTR's
	DO.			;LOOP over all BGPTR's
	  HRLOI P1,377777	; Max value
	  MOVSI Q2,-NBUGP(Q1)	; LOOP between 0 and NBUGP-Q1
	  HRR Q2,Q1		;  and get start index into RH
	  DO.
	    HRRZ T1,Q2		;   Get current index
	    ADD T1,[BGPTR]	;    and make table pointer
	    HLRZ P2,0(T1)	;   Get section # of buginf/chk/hlt
   Repeat 1,< ;To be removed when all of monitor is recompiled with new PROLOG
	    CAILE P2,37		;   Verify section #
	    JRST DOBUG1		;    -out of range
   >
	    CAIE P2,MSEC1	;   Section 1?
	    IFSKP.		;    -yes, section 1 does not exist in POSTLD,
				;     so make a section-local address (sec 0
				;     is mapped into POSTLD section)..
	      HRRZ P2,0(T1)	;     Get section-local address
	    ELSE.		;    -not section 0,
	      MOVE P2,0(T1)	;     so use full 30-bit address
	    ENDIF.
	    JUMPE P2,DOBUG1	;    -none, go ahead
	    DO.			;   LOOP until bug name is found
	      MOVE T2,1(P2)	;     Get next word from block
	      TLNN T2,770000	;     Sixbit?
	      AOJA P2,TOP.	;     -no, loop back until found
	    ENDDO.
	    TXC T2,1B0		;   So compare works
	    CAML T2,P1		;   Smaller than current minimum?
	    JRST DOBUG1		;   -no, just go ahead
	    MOVE P1,T2		;   -yes, save new minimum
	    HRRZ P3,Q2		;    and remember current index
  DOBUG1:   AOBJN Q2,.+1	;   Skip over ptr to BGSTR
	    AOBJN Q2,TOP.	;   Loop back if more to do
	  ENDDO.
	  CAMN P1,[377777,,777777] ;Found a minimum?
	  JRST DOBUG2		;   -no, only zeroes left
	  ADD P3,[BGPTR]	;   Make pointer to minimum value
	  HRRZ T1,Q1		;    and pointer to top of table
	  ADD T1,[BGPTR]	;     ..
	  DMOVE T2,(P3)		;   Get value of minimum
	  EXCH T2,(T1)		;   Exchange values
	  EXCH T2+1,1(T1)	;   ...
	  DMOVEM T2,(P3)	;   ...
	  AOBJN Q1,.+1		;  Skip over pointer to BGSTR
	  AOBJN Q1,TOP.		;  Loop back if more to do
	ENDDO.

;Now write the sorted bug table to BUGSTRINGS.TXT
DOBUG2:	HRROI T1,[ASCIZ /BUGSTRINGS.TXT/]
	CALL OUTFIL		;Open outfile
	IFNSK.			; -error,
	  TMSG <
%Warning: failed to write BUGSTRINGS.TXT
>
	  RET			;  -nothing more to do
	ENDIF.
	MOVEM T1,BUGJFN		;Save JFN
	TMSG <to file >
	MOVEI T1,.PRIOU		;To terminal
	MOVE T2,BUGJFN
	SETZ T3,		;No format control
	JFNS%
	MOVE T1,BUGJFN		;JFN to T1
	HRROI T2,TSVN		;System name and version
	SETZ T3,		;Break on NULL
	SOUT%			;Go

;Type out feature switches so we know what monitor these BUG. refer to
	FMSG <
Switches are: DEBUG=>
	MOVX T2,DEBUG
	CALL TYPFT		;Type out switch value
	FMSG <, DCN=>
	MOVX T2,DCN
	CALL TYPFT
	FMSG <, NETN=>
	MOVX T2,NETN
	CALL TYPFT
	FMSG <
BUGHLT and BUGCHK names and descriptions

>
	MOVSI Q1,-NBUGP		;AOBJN ptr to sorted BGPTR table
	DO.			;LOOP over table
	  HRRZ Q2,Q1		;  Get current index
	  ADD Q2,[BGPTR]	;  Point to BGPTR entry
	  HLRZ Q3,0(Q2)		;  Get section # of buginf/chk/hlt
   Repeat 1,< ;To be removed when all of monitor has been recompiled
	  CAILE Q3,37		;  Valid section?
	  JRST DOBUG3		;   -no, out of range
   >
	  CAIE Q3,MSEC1		;  Is it section 1?
	  IFSKP.		;   -yes, remake to section-local (section 0/1
				;    are mapped into POSTLD section
	    HRRZ Q3,0(Q2)	;    Get section-local part
	  ELSE.			;   -no,
	    MOVE Q3,0(Q2)	;    Get 30-bit bug address
	  ENDIF.
	  MOVE P4,Q3		;  Save bug address for typeout
	  DO.			;  LOOP
	    MOVE T3,1(Q3)	;    Get next word
	    TLNN T3,770000	;    Is it 6bit?
	    AOJA Q3,TOP.	;    -no, loop back till 6bit is found
	  ENDDO.
	  DO.
	    SETZ T2,		;  Now type out name
	    LSHC T2,6		;  Shift in next character from name
	    ADDI T2," "		;  Make ASCII
	    BOUT%		;   and output to file (JFN still in T1)
	    JUMPN T3,TOP.	;  Continue until all of name is done
	  ENDDO.
	  HRRZ T3,(P4)		;  Get the address in the BUG. instruction
	  HRROI T2,[ASCIZ /	[UNK] /]
	  CAIE T3,XBUGHLT
	  CAIN T3,BUGHLT
	  HRROI T2,[ASCIZ /	[HLT] /]
	  CAIE T3,XBGCCHK
	  CAIN T3,BGCCHK
	  HRROI T2,[ASCIZ /	[CHK] /]
	  CAIE T3,XBGCINF
	  CAIN T3,BGCINF
	  HRROI T2,[ASCIZ /	[INF] /]
	  MOVEI T3,0
	  SOUT%			;  Output description
	  MOVE T2,1(Q2)		;  Get pointer to associated BGSTR
	  TLO T2,(61B5)		;   and make global bp
	  SETZ 3,
	  SOUT%			;  Print the string
	  HRROI T2,[ASCIZ /
/]
	  SOUT%
DOBUG3:	  AOBJN Q1,.+1		;  Skip over BGSTR pointer
	  AOBJN Q1,TOP.		;  Loop back if more to do
	ENDDO.
	CLOSF			;Close BUGSTRINGS.TXT
	 NOP			; Ignore error
	RET
	ENDSV.

;TYPFT - type out feature switch value
;
; T1/ JFN to write on
; T2/ value of switch
;
; Returns with T1 intact

TYPFT:	SKIPE T2		;Switch OFF or ON?
	IFSKP.			;  OFF
	  HRROI T2,[ASCIZ /OFF/]
	ELSE.			;  ON
	  HRROI T2,[ASCIZ /ON/]
	ENDIF.
	SETZ T3,
	SOUT%
	RET
	SUBTTL	Make POSTLD image

;Define a macro that will map a psect to another section

DEFINE MAPPSX ($PSECT,$SECNR) <
	XLIST
	MOVE Q1,PSTBL+$PSECT'I
	MOVX Q2,$SECNR
	CALL .MPPSX
	LIST
>

;MAKIMG - make section 0 and 1 look like POSTLD image
;
;The following steps are taken:
;	1. Create section 1
;	2. Move BGSTR and BGPTR there
;	3. Move NRCOD there, write PNRCOD, unmap NRCOD from section 0
;	4. Move XRCOD and XNCOD to section 1
;	5. Move ENCOD to section 1
;	6. Copy symbols to section 0. Write PDVSYM and PDVUSY.
;	7. Move ERCOD to section 0
;	8. Set entry vector

MAKIMG:	

;Create section 1
	SETZ T1,		;Create section
	MOVE T2,[.FHSLF,,1]	;Ourselves,,section 1
	MOVX T3,SM%RD!SM%WR!SM%EX!1 ;Allow all accesses', map 1 section
	SMAP%

;Map BGSTR/BGPTR into section 1
	MAPPSX (BGSTR,1)
	MAPPSX (BGPTR,1)

;Move NRCOD into section 1 just after BGPTR
	CALL MOVNRC

;Map XRCOD/XNCOD/ENCOD into section 1
	MAPPSX (XRCOD,1)
	MAPPSX (XNCOD,1)
	MAPPSX (ENCOD,1)

;Copy the symbols into section 0
	CALL COPSYM

;Map ERCOD into section 0
	MAPPSX (ERCOD,0)

;Set monitor entry vector.
; The entry vector is read by BOOT, and used as monitor start address
	MOVX T1,.FHSLF		;Ourselves
	MOVE T2,[JRST EVGO]	;Main start location
	HRRM T2,.JBSA		;Write to job area for compatibility
	SEVEC%			;Set entry vector

	RET

;.MPPSX - do the work for MAPPSX
;
;Call:	Q1/ pointer to psect block
;	Q2/ destination section number

.MPPSX:	MOVE T1,$PBGN(Q1)	;Get start address of psect
	LSH T1,-^D9		;Make into page #
	MOVE T2,T1		;Copy to T2 to create destination
	ANDI T2,777		;Keep only section-local page #
	MOVE T4,Q2		;Get destination section #
	LSH T4,^D9		;Make into extended page #
	TDO T2,T4		;And into destination page #
	HRLI T1,.FHSLF!FH%EPN	;Ourselves, extended page #'s
	HRLI T2,.FHSLF!FH%EPN	;   -"-
	MOVE T3,$PEND(Q1)	;Get end address
	SUB T3,$PBGN(Q1)	; minus start address
	LSH T3,-^D9		;# of pages
	AOJ T3,			;Adjust
	HRLI T3,(PM%CNT!PM%RD!PM%WR!PM%CPY!PM%EPN) ;RD/WR, private, extended
				; page #'s
	PMAP%
	RET

;MOVNRC - move the swappable monitor
;
;	1. Move the swappable monitor from section 0 into section 1
;	   just after BGPTR. Write the POSTLD image position of NRCOD
;	   into PNRCOD. Note: we must XBLT NRCOD, and not PMAP it,
;	   since NRCOD in section 0 will be unmapped as the symbol
;	   table will overlay it.
;
;	2. Unmap NRCOD from section 0

MOVNRC:	MOVEI T1,<NRCODZ-NRCOD+1> ;Length of NRCOD in words
	MOVEI T2,NRCOD		;From NRCOD in section 0
	MOVE T3,[XWD MSEC1,<<BGPTRZ & 777777> + 1000> & 777000] ;to next page
				; after BGPTR in section 1
	MOVEM T3,PNRCOD		;Save for PGRINI
	EXTEND T1,[XBLT]	;Move NRCOD
;Now unmap NRCOD from section 0
	SETO T1,		;Unmap
	MOVE T2,[.FHSLF!FH%EPN,,NRCOD/1000] ;Ourselves, from NRCOD
	MOVEI T3,<NRCODZ+1-NRCOD+1000>/1000 ;Get length of NRCOD in pages
	HRLI T3,(PM%CNT!PM%EPN)	;Set count flag
	PMAP%			;Unmap from section 0
	RET
	SUBTTL	Copy the symbol tables

;The symbol tables (undefined and defined) are moved into section 0,
; and are put right after RSVAR, i.e. at the same offset as NRVAR.
;After the move, the PDVSYM and PDVUSY are updated.
;
;Note: the undefined symbols symbol table is always right before the
; defined symbols symbol table.
;Also: we should leave a free space of size SYMPAD before the undefined
; symbol table, since ?DDT will expand that table downwards.
;
;Note: we update .JBSYM and .JBUSY. This is only for FILDDT. FILDDT will
; look for symbols with "physical paging" (i.e. according to EXE directory)
; so if we set up .JBSYM and .JBUSY here as section-0 symbol pointers
; everything will come out well in FILDDT. However, you'd better know that
; you shouldnt use .JBSYM and .JBUSY in the running monitor! Magic,magic...

;If AU is the address of the undefined symbol table, AL the defined,
; and LU and LL are the respective lengths, then
;
;	copy from AU to NRVAR+SYMPAD
;	# of words = AL-AU+LL
;	PDVUSY address = NRVAR+SYMPAD
;	PDVSYM address = PDVUSY address+AL-AU

;Ac usage in COPSYM:
;	P1/ AU
;	P2/ AL
;	P4/ LL
;
;	Q1/ points to undefined symbol block
;	Q2/ points to defined symbol block

COPSYM:	MOVE Q1,PDVUSY		;Get address of undefined symbol block
	MOVE P1,.STPTR(Q1)	;Get AU
	MOVE Q2,PDVSYM		;Get address of defined symbol block
	MOVE P2,.STPTR(Q2)	;Get AL
	LDB P4,[POINTR .STLEN(Q2),SY%LEN] ;Get LL

;Set up for XBLT: T1/ # of words, T2/ src addr, T3/ dest addr
	MOVE T1,P2		;AL
	SUB T1,P1		;  -AU
	ADD T1,P4		;     +LL
	MOVEI T2,SYMPAD(T1)	;Calculate total length of symbol table
	MOVEM T2,SYMLEN		; and save for future use (PGRINI)
	MOVE T2,P1		;From AU
	MOVEI T3,NRVAR+SYMPAD	;       to section 0 overlaying NRVAR
	EXTEND T1,[XBLT]	;Move..

;Fix up PDVUSY and PDVSYM
	MOVEI T1,NRVAR+SYMPAD	;Get new dest address
	MOVEM T1,.STPTR(Q1)	; and save as new undefined addr
	ADD T1,P2		;  +AL
	SUB T1,P1		;     -AU
	MOVEM T1,.STPTR(Q2)	;Save as new defined addr

;Write FREMEM. PGRINI puts temporary CST's at FREMEM
	MOVE T1,SYMLEN		;Get symbol table length
	ADDI T1,NRVAR+SYMPAD+1000 ;Get ending address + 1000
	TRZ T1,777		;T1 has next address of next page after table
	MOVEM T1,FREMEM		; so save it in FREMEM

;Write SYMSTA and SYMEND. These define the start and end address of the symbol
; tables after they are mapped into SYMSEC by PGRINI.
	MOVX T1,<<BGPTRZ+PGSIZ>&VPGNO> ;Start address
	MOVEM T1,SYMSTA		;Save it for PGRINI
;**;[7215] Remove 3 lines at COPSYM+33	CEG 20-Dec-85
	ADD T1,SYMLEN		;Add length
	SOS T1			; - 1 gives ending address
	MOVEM T1,SYMEND		;  and save that too for PGRINI

;Now write .JBSYM and .JBUSY
	MOVE T1,.STPTR(Q1)	;Get pointer to undefined symbol table
	LDB T2,[POINTR .STLEN(Q1),SY%LEN] ;And get length
	MOVNS T2		;Negate
	HRLES T2		; and put into LH
	HLL T1,T2		;  and into T1
	MOVEM T1,.JBUSY		;  -thats the undefined pointer

	MOVE T1,.STPTR(Q2)	;Get pointer to defined symbol table
	LDB T2,[POINTR .STLEN(Q2),SY%LEN] ;And get length
	MOVNS T2		;Negate
	HRLES T2		; and put into LH
	HLL T1,T2		;  and into T1
	MOVEM T1,.JBSYM		;  -thats the defined pointer

	RET
	SUBTTL	Set up MMAP

;SETMMP - set up MMAP.
;
;POSTLD sets up MMAP with a 1-1 mapping for the psects that are
; present in section 0 of the POSTLD image. This mapping is used
; when paging is first turned on in the monitor. The mapping is
; later redone by PGRINI.

SETMMP:	MOVE T1,[0,,RSDATZ]	;All of resident code, and RSDAT
	CALL WRMMAP
	MOVE T1,[RSVAR,,RSVARZ]	;Resident data too
	CALL WRMMAP
	MOVEI T1,NRVAR		;All of the symbol table
	ADD T1,SYMLEN
	HRLI T1,NRVAR
	CALL WRMMAP
	HRLI T1,ERCOD		;And EDDT
	HRRI T1,ERCODZ
	CALLRET WRMMAP

;WRMMAP - write to MMAP
;
;Call:	T1/ first virtual addr,,last virtual addr
;
;Note: its OK with 18-bit addresses since MMAP describes section 0
; of the monitor

WRMMAP:	HLRZ T4,T1		;Get first virtual address
	LSH T4,-PGSFT		;Make page #
	HRRZ T3,T1		;Last VA
	LSH T3,-PGSFT		;Make page #
	MOVE T1,IMMPTR		;Get immediate prototype pointer
	IOR T1,T4		;Make it point to first VA
	DO.			;LOOP
	  CAMLE T4,T3		;  Beyond last?
	  RET			;   -yes, all done
	  MOVEM T1,MMAP(T4)	;  Put pointer in MMAP
	  AOJ T1,		;  Move to next pointer
	  AOJA T4,TOP.		;  Move to next page and loop
	ENDDO.
;Can never get here
	SUBTTL	Set up EDDT in section 0

;STEDDT - set EDDT's environment to section 0
;
;This is accomplished by JSR'ing to FAKDDT in section 0.
; Since we are running in section PCDSEC, and want to return there,
; set up a little program that run in the AC's.

STEDDT:	MOVE 16,[STEDDC,,1]	;Set up to
	BLT 16,5		; move code into AC's 1-5
	XJRST [0,,2]		;Get into Ac 2 in section 0
STEDD1:	RET			;All done

STEDDC:	PHASE 1
	0,,FAKDDT		;[Ac 1] Address to JSR to
	JSR @1			;[Ac 2] JSR to EDDT
	XJRSTF 4		;[Ac 3] Return to PCDSEC
	0			;[Ac 4] PC flags
	PCDSEC,,STEDD1		;[Ac 5] PC
	DEPHASE
	SUBTTL	Write the POSTLD image to disk

;SAVIMG - save the POSTLD image as MONITR.EXE

;Define a macro that will build a SSAVE frame on the stack
DEFINE SSEG ($NAME,$START,$END, %LBL) <
	XLIST
	..NSG=..NSG+2
	MOVE Q1,$END
	MOVE Q2,$START
	HRROI Q3,[ASCIZ /'$NAME/]
	JSP P5,.SVPSX
%LBL:	LIST
>
	..NSG=0			;Initial value

SAVIMG:	TRVAR <SAVJFN,<SAVARG,2>>
	SETOM PLDRUN		;Flag that POSTLD has run
	MOVX T1,GJ%SHT!GJ%FOU	;Short form, next higher generation
	HRROI T2,MONSNM		;Get name to save as
	GTJFN%
	ERJMP .JSERR		; -on error, type out error message and return
	MOVEM T1,SAVJFN		;Save JFN

;Build the arguments to SSAVE. The argument block is built on the stack
	HRLI T1,.FHSLF!FH%EPN	;Ourselves, use extended page #'s
	MOVEI T2,1(P)		;Point to stack frame
	DMOVEM T1,SAVARG	;Save arguments

;Output header
	TMSG <

- POSTLD image layout -

       Start         End        Psect
>

;Build the frames on the stack
	SSEG (<Page 0 and RSCOD>,[EXP 0],[EXP RSCODZ]) ;Page 0 and RSCOD
	SSEG (<INCOD>,[EXP INCOD],[EXP INCODZ])
	SSEG (<RSDAT>,[EXP RSDAT],[EXP RSDATZ])

	MOVE P1,SYMLEN		;Get symbol table length
	ADDI P1,NRVAR+SYMPAD	;Make ending address
	SSEG (<Symbol table>,[EXP NRVAR+SYMPAD],P1)

	SSEG (<ERCOD>,[<ERCOD & 777777>],[<ERCODZ & 777777>])
	SSEG (<BGPTR>,<[XWD MSEC1,<BGSTR & 777777>]>,<[XWD MSEC1,<BGSTRZ & 777777>]>)
	SSEG (<BGSTR>,<[XWD MSEC1,<BGPTR & 777777>]>,<[XWD MSEC1,<BGPTRZ & 777777>]>)

	MOVE P1,PNRCOD		;Get POSTLD start address of NRCOD
	ADDI P1,<NRCODZ-NRCOD>	;Make end address
	SSEG (<NRCOD>,PNRCOD,P1)

	SSEG (<XRCOD>,<[XWD MSEC1,<XRCOD & 777777>]>,<[XWD MSEC1,<XRCODZ & 777777>]>)
	SSEG (<XNCOD>,<[XWD MSEC1,<XNCOD & 777777>]>,<[XWD MSEC1,<XNCODZ & 777777>]>)
	SSEG (<ENCOD>,<[XWD MSEC1,<ENCOD & 777777>]>,<[XWD MSEC1,<ENCODZ & 777777>]>)

;All frames built
	PUSH P,[0]		;Terminate list with a 0

	TMSG <

Saving monitor as >
	MOVEI T1,.PRIOU		;To primary output
	MOVE T2,SAVJFN		;Get JFN again
	SETZ T3,		;No format control
	JFNS%			;Type out the filename string

;Now do the actual SAVE
	DMOVE T1,SAVARG		;Retrieve JFN and address
	SETZ T3,
	SSAVE%			;Save the image
	ADJSP P,-<..NSG+1>	;Fix up stack
	TMSG <

>
	RET
	ENDTV.

;.SVPSX - does the work for SSEG macro in SAVIMG
;
;Call by JSP P5,.SVPSX
;	Q1/ End address
;	Q2/ Start address
;	Q3/ pointer to ASCIZ name of psect to save

.SVPSX:	MOVE T3,Q1		;Get ending address
	LSH T3,-PGSFT		; and make into page number
	MOVE T4,Q2		;Get start address
	LSH T4,-PGSFT		; and make into page number
	SUBI T3,-1(T4)		;Get count of pages to save
	MOVNS T3		;Negate count
	HRLES T3		; and put into left half
	HRRI T3,SS%CPY!SS%RD!SS%EXE!SS%EPN ;Access bits into right half
	PUSH P,T3		;1st word in save frame on stack
	PUSH P,T4		;2nd work (page # to start at) in frame

;Type out pages saved
;
;The display has the following format:
;
;Start	End	Psect

	TMSG <
>				;New line
	MOVE T2,Q2		;Start address
	LSH T2,-PGSFT		; and make into page
	CALL OCTOUC
	MOVE T2,Q1		;Ending address
	LSH T2,-PGSFT		; and make into page
	CALL OCTOUC
	MOVEI T1,.CHTAB		;Then a TAB
	PBOUT%
	MOVE T1,Q3		;Get pointer to name
	PSOUT%

	JRST (P5)		;Return to caller
	SUBTTL	Subroutines

;OCTOUT - output an octal number in free format
;OCTOUC - output an octal number in column format
OCTOUT:	SKIPA T3,[FLD(^D8,NO%RDX)] ;Free format
OCTOUC:	MOVX T3,FLD(^D8,NO%RDX)!NO%LFL!FLD(^D12,NO%COL)
	MOVX T1,.PRIOU		;To primary output
	NOUT%			;Output it
	 JSERR			; - tell error, but continue
	RET

;OUTFIL - open a file for output.
;
;Input:	T1/ pointer to file name
;
;Return +1 if any error, else skip

OUTFIL:	STKVAR <JFN>
	MOVE T2,T1		;Move pointer to name into place
	MOVX T1,GJ%SHT!GJ%FOU	;Short form, next higher generation
	GTJFN%			;Get file
	ERJMP .JSERR		; -type out error and return
	MOVEM T1,JFN		;Save JFN
	MOVX T2,FLD(7,OF%BSZ)!OF%RD!OF%WR
	OPENF%
	IFJER.			;If error,
	  CALL .JSERR		;  type out error message
	  MOVE T1,JFN		;   and release
	  RLJFN%		;    jfn
	   NOP
	  RET
	ENDIF.
	RETSKP			;Success return with JFN in T1
	ENDSV.

;.JSHLT - type out jsys error and halt
.JSHLT:	CALL .JSERR		;Type out error
	HALTF%			; and halt program

;.JSERR - type out jsys error and return
.JSERR:	TMSG <
?Jsys error: >
	MOVX T1,.PRIOU		;To primary output
	HRLOI T2,.FHSLF		;This fork,,last error
	SETZ T3,		;No limit on bytes to transfer
	ERSTR%			;Output error message
	 JFCL
	 JFCL
	TMSG <
>
	RET
	SUBTTL	Variables

PDL:	BLOCK NPDL		;Stack
OVRFLW:	BLOCK 1			;Count of psect overlaps

	END <3,,ENTVEC>		;End of POSTLD