1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-02 09:37:06 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

5416 lines
208 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE LNKXIT - EXIT MODULE FOR LINK
SUBTTL D.M.NIXON/DMN/JLd/RKH/JBC/JNG/MCHC/DZN/MFB/PAH/PY/HD/JBS/RJF 5-Feb-88
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1973,1986,1988.
; ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
;TRANSFERRED.
;
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
SEARCH LNKPAR,LNKLOW,OVRPAR,MACTEN,UUOSYM
IFN TOPS20,<SEARCH MACSYM, MONSYM>
SALL
ENTRY LNKXIT
EXTERN LNKCOR,LNKLOG,LNKFIO
EXTERN .JB41
CUSTVR==0 ;CUSTOMER VERSION
DECVER==6 ;DEC VERSION
DECMVR==0 ;DEC MINOR VERSION
DECEVR==2404 ;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).
;1235 Clear LOGSUB to avoid possible IO TO UNASSIGNED CHANNEL.
;1242 Make High Segs above 700000 generate .EXE file on TOPS-20
;1244 Kill PA1050 if executing user program, replace CORE UUO with PMAP JSYS
;1257 Put Root node location in RC.HL in .ABS. if overlaid.
;1261 Restore P1 if /SAVE scan block built because of complex program
;1267 Add ALGDDT to KEYMAC definition.
;1272 Fix Edit 1244 to remove PA1050 if low seg ends at end of page.
;1273 Fix RC.HL in .LOW. and .HIGH. to agree with HP.S1 and HP.S2.
;1300 Check BADCORE, issue LNKCFS if non-zero.
;1301 Make .OERR. Messages use verbosity bits.
;1302 Fix bug in 1273, don't use HP.S if RC.HL() is greater.
;1305 Remove edits 1273, 1302, move code into LNKOLD
;1314 Fix bug if more than 400 contiguous non-zero pages of .EXE file.
;1317 Correctly calculate .JBCOR if program ends on page boundary.
;1321 Make SIMDDT start at .JBREN like ALGDDT.
;1323 Check for high seg when simulating CORE UUO with PMAP% JSYS.
;1325 Output secondary fixup chains in undefined symbol table.
;1326 Use new PA1050 suicide COMPT. instead of PMAP%
;START OF VERSION 5
;1400 Use OVRPAR.MAC.
;1401 Performance improvements to overflow and EXE file i/o.
;1415 Write out ALGOL .SYM files on channel TC.
;1423 Support Program Data Vectors
;1425 FTFRK2 Extended addressing support.
;1427 Put ERJMPs after PDVOP%s for pre-Tops-20 Release 5.
;1437 Defer destroying LC file under TOPS-20 until the last minute.
;1442 Don't go thru the SSINI code unless nonzero sections have been
; loaded.
;
;1450 Use PRGFRK, fix some FTFRK2 bugs, insert ERJMP after failing SEVEC.
;1454 Calculate default SYMLIM correctly.
;1455 Fix infinite loop caused by bad test in TTLLUP.
;1460 Clean up SSINI code and kill UUO simulation for xaddr programs.
;1464 Get the right window for the PDV in nonzero sections.
;Start of Version 5.1
;1500-1677 Maintenance edits.
;1506 Conditionalize remaining UUOs in the overlay-writing code.
;1516 Fix bad test at CHKRS0+3
;1521 Get all of overlay links symbol table in .EXE file.
;1522 Make JBGCM/JBGCMV unmap and remap paged areas on the -20.
;1524 Add an entry for PASDDT in STLOCN.
;1531 Handle address before current window in EXE writer
;1532 Test JOBPTR, not LW.S1, to decide if XCMPRS should write the JOBDAT.
;1534 Make sure LC/HC.PT is right following calls to LNKCOR from SYMOU2.
;1536 Handle multi-section LS area without catastrophic failures.
;1757 Correct 1432. PDV address was too large by one
;1760 Keep the section number of the last word of the PDV
;1762 Don't return the PDV prematurely so that start address for programs
; in non-zero sections is set correctly.
;1764 Make use specified entry vectors work in non-zero sections.
;1773 Set up t3 for XSVEC in JBEX1A
;2000 Don't return nonexistent PDV storage at SSINIG+9.
;2006 Fix PDVs over page boundary, use 1 not JRST, use SEVEC in section 0
;2016 Fix /PVBLOCK:HIGH, and set HL.S0(R) and HC.S0(R) if needed.
;2021 Make pages from overflow file private if not writing .EXE file.
;2023 If PMAP fails while writing .EXE because Quota exceeded try expunge.
;2024 Fix edit 2023
;2026 Update copywrite and strip edit banners.
;2027 Conditionalize PMAP error handling.
;2032 Allocate space with LC.IN before reading area from .OVL file.
;2034 Remove Edit 1531.
;2035 Don't map in non-existant pages at JBGMV0.
;2040 Be careful of page boundary when mapping out at SYMINI.
;2043 Don't call BLTJDA if JOBPTR is zero at JBEXE1.
;2052 Don't die when making EXE file if directory is protected.
;2054 Keep the LS overflow area on TOPS-20 if it is still mapped.
;2055 Put the count in T2 before calling DY.GET.
;2056 Print LNKXCT message when executing prog in non-zero section.
;2060 Save the PPN and PATH info for the RUN UUO in RUNEX2.
;2061 Fix typo in 2060.
;2066 Fix 2060 to get PPN from right place and check for default [0,0].
;Start of Version 6
;2202 Use 30 bit addresses for xx.IN and xx.OUT, remove NONZER and FTFRK2.
;2206 Set read-only attributes correctly for non-zero section psects.
;2211 Implement /NOJOBDAT, change the way JOBDAT is automatically suppressed.
;2220 Handle long psect names.
;2232 Don't set .JBREL during exit if user said /NOJOBDAT.
;2237 Implement PDV memory maps.
;2241 Setup P1 and P2 even if /NOJOBDAT.
;2245 Implement the PDV symbol table vector.
;2247 Use an inferior fork for program on TOPS-20.
;2250 Allocate PDV space more efficiently, fix various other bugs.
;2256 Use new-style LS segment triplets to generate the module headers.
;2260 Fix several things with old edits (see LNKHST).
;2261 Fix off-by-one in page attribute setting code.
;2265 Don't set page attributes of null read-only psects.
;2274 Fix some error messages, don't SSAVE% beyond highest section.
;2277 Add new /DEBUG code for loading DDT into non-zero sections.
;2301 Fix error messages for TOPS-20 native files.
;2304 Change DDT error messages, don't check undef sym ptr if def is there.
;2306 Add long PDV name, default PDV, move symbol vector to symbol psect.
;2311 Fix PDVs in high segment, default bit 0 for symbol vector pointer.
;2312 Store the default PDV memory map address in the PDV.
;2314 Allow /DEBUG when SPLFK% fails, remove LINK's PDV and PSI table addrs.
;2317 Fix 2247 to save copy-on-write page attributes correctly.
;2320 Create empty read-only pages when necessary.
;2330 Fix conditionals and add label needed under TOPS-10.
;2335 Fix problems with memory map, TOPS-10 conditionals, add default name.
;2336 Produce symbol vector properly if no default map requested.
;2346 Don't try to GET% EXE file if not on disk.
;2347 Fix arguments to COMPT. to remove PA1050.
;2350 Map non-existant pages properly.
;2352 Don't map too large an area in STUFDD.
;2353 Remove unreachable code, bad AC names, move SPLFK% symbols to LNKPAR.
;2355 Handle pre-emptive debugger starting addresses properly.
;2356 Remove unnecessary TOPS20 conditionals, fix overflow in exe writer.
;2357 Set up DC channel for exe file if splice fork fails.
;2360 Fix problem in edit 2355, don't change STADDR.
;2361 Add the PDV map overhead word before storing the map length.
;2362 Save the DDT start address in EXECSW as well as in STADDR.
;2363 Check which debugger starts, don't assume DDT.
;2364 Use HL.S1 to get highest location loaded for SSAVE.
;2366 Add symbol and entry vectors on TOPS-10.
;2370 Fix off-by-one if segment ends with allocated but zero pages.
;2373 Fix long sym support for DDT symbol tables.
;2402 Print first 6 characters of long program name in the LNKXCT message.
;2403 New coporate copywrite statement.
;2404 Use first six charcters of long load name for call to SETNM%.
;2417 Update copywrite statement to 1988.
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]
SKIPN BADCORE ;[1300] CORE IMAGE ALL FIXED UP?
JRST LNKX0I ;[1300] YES
E$$CFS::.ERR. (MS,0,V%L,L%F,S%C,CFS,<Chained fixups have been suppressed>);[1300] NO
LNKX0I: ZAPTMP ;[1300] 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
HRRZS LL.S2 ;[2247] CLEAR LH IN CASE /REDIRECT
IFN FTOVERLAY,<
SKIPGE LNKMAX ;DID WE LOAD ANY OVERLAYS?
JRST LNKX1 ;NO
MOVE T1,PH+PH.OVL ;[1400] GET START OF CODE FOR ROOT
USETI OC,(T1) ;POSITION ON THE BLOCK
MOVE P2,PH+PH.LLN ;[1400] 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: ;[2247]
IFN TOPS20,< ;[2247]
MOVE T2,LC.AB ;[2247] GET THE TOP OF THE LC AREA
SUB T2,LC.LB ;[2247] MINUS THE BOTTOM IS THE SIZE
MOVEM T2,UW.LC ;[2247] UPPER WINDOW BOUND
SETZB T1,LW.LC ;[2247] START AT ZERO
PUSHJ P,LC.IN## ;[2247] MAP IT IN
>;[2247] IFN TOPS20
MOVE T1,LC.LB ;[2247] READ INTO LC AREA
SUBI T1,1
HLL T1,PH+PH.OVL ;[1400] 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 LNKX0G ;[1257]
;NOW TO READ BACK FIRST FEW BLOCK
LNKX0F: SETZB T1,LW.S1 ;[2202] STARTS AT ZERO
MOVE T2,LC.UB ;[2202] GET MAX SIZE
MOVEM T2,LC.AB ;[2202] USE IT ALL AGAIN
SUB T2,LC.LB ;[2202] GET UPPER BOUND
MOVEM T2,UW.S1 ;[2202] REMEMBER IT
PUSHJ P,LC.IN## ;READ IT BACK
JRST LNKX0B ;FIXUP VARIOUS POINTERS
LNKX0C: SETZM LW.S1 ;SET BACK TO START
MOVE T1,PH+PH.OVL ;[1400]
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: ;[2032]
IFN TOPS20,< ;[2032]
PUSH P,T1 ;[2032] SAVE THE AC
MOVE T1,LW.LC ;[2202] GET THE LOWER BOUND
MOVE T2,UW.LC ;[2202] GET THE UPPER BOUND
PUSHJ P,LC.IN## ;[2032] MAP IN THE WINDOW
POP P,T1 ;[2032] RESTORE THE AC
>;[2032] IFN TOPS20
MOVN T1,T1 ;[2032]
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
IFE TOPS20,< ;[2032] DON'T BLT ON THE -20
CAMG T1,PH+PH.LLN ;[1400] REACHED END YET?
JRST LNKX0E ;NO
MOVE T1,PH+PH.LLN ;[1400] 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
>;[2032] END IFE TOPS20
LNKX0E: MOVE T2,T1 ;[2202] END OF WINDOW
MOVE T1,LW.S1 ;[2202] 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+PH.LLN ;[1400] 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+PH.LLN ;[1400] DO WE NEED TO READ IT ALL IN?
JRST LNKX0D ;YES
MOVE T1,PH+PH.LLN ;[1400] 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
LNKX0GA: MOVEI R,0 ;[1257] SET UP TO POINT TO PSECT
MOVE R,@RC.TB ;[1257] GET POINTER TO .ABS. PSECT BLOCK
MOVE T1,ROOTAB ;[1257] PICK UP ADDRESS IN ROOT NODE
MOVEM T1,RC.HL(R) ;[1257] PUT IN .ABS.
>;END OF IFN FTOVERLAY
LNKX1: ;[2366]
IFN TOPS20,< ;[2366]
;Here to determine whether a JOBDAT should be produced. The rule is:
; If the user said /NOJOBDAT, he won't get one.
; If the user has non-zero sections he won't get one.
; If the user has a psect which starts below 140 he won't get one.
; Otherwise he will.
SKIPE NOJBDA ;[2247] User already said /NOJOBDAT?
JRST LNKX1B ;[2247] Yes, user already made decision
MOVE T1,FXSBIT ;[2247] Get the section bits
TXNE T1,^-1B0 ;[2247] Non-zero sections?
JRST LNKX1A ;[2247] Yes, no JOBDAT for this program
MOVEI R,2 ;[2247] Get index to lowest psect
CAMLE R,RC.NO ;[2247] Is there one?
JRST LNKX1B ;[2247] No, it's single segment and gets JOBDAT
MOVE T1,@RC.TB ;[2247] Point to the RC block
MOVE T1,RC.IV(T1) ;[2247] Get the initial value
CAIG T1,140 ;[2247] Check psect before 140
LNKX1A: SETOM NOJBDA ;[2247] Remember no JOBDAT
;[2306] Here to determine whether a PDV should be produced. The rule is:
;[2306] If the user program has overlays, he won't get one.
;[2306] If the user said /PVBLOCK:NONE, he won't get one.
;[2306] If the user said /PVBLOCK:LOW, /PVBLOCK:HIGH, or /PVBLOCK:PSECT:
;[2306] he will get one.
;[2306] If the user said /PVBLOCK:DEFAULT, or did not say anything, he
;[2306] will get one if he will not get a JOBDAT, or if he specified
;[2306] a /PVDATA of any type. The type he will get will be identical
;[2306] to /PVBLOCK:LOW.
LNKX1B:
HLRZ T1,PRGPDV ;[2306] Get the keyword
IFN FTOVERLAY,< ;[2306]
SKIPN OVERLW ;[2306] Using overlays?
>;[2306] IFN FTOVERLAY
CAIN T1,$SSGNONE ;[2306] /PVBLOCK:NONE?
JRST LNKX1D ;[2306] Yes, toss block and exit
JUMPE T1,LNKXIC ;[2306] Never set?
CAIE T1,$SSGDEFAULT ;[2306] Or /PVBLOCK:DEFAULT?
JRST LNKX1G ;[2306] No, it's specified - must build one
;[2306] Here on /PVBLOCK:DEFAULT - Check for /PVDATA or no JOBDAT
LNKXIC: HRRZ T1,PRGPDV ;[2306] Get the PDV block address
SKIPN T1 ;[2306] Block set up (/PVDATA already seen)?
SKIPE NOJBDA ;[2306] Or no jobdat?
JRST LNKX1F ;[2306] Yes, create the PDV
;[2306] Here if a PDV not wanted - Return the block if there is one
LNKX1D: HRRZ T1,PRGPDV ;[2306] Get the PDV block address
JUMPE T1,LNKX1E ;[2306] No block, don't return it
MOVEI T2,PV.LEN ;[2306] And the length
PUSHJ P,DY.RET## ;[2306] Return it
LNKX1E: SETZM PRGPDV ;[2306] Remember there isn't one
JRST LNKX1H ;[2306] Done
;[2306] Here if a default PDV wanted - Set to /PVBLOCK:LOW and continue
LNKX1F: MOVEI T1,$SSGLOW ;[2306] Get the token
HRLM T1,PRGPDV ;[2306] Set it
;[2306] Here if a PDV is wanted - Create the block if there isn't one yet.
LNKX1G: HRRZ T1,PRGPDV ;[2306] Get the block address
SKIPN T1 ;[2306] Is there one?
PUSHJ P,PVFIX## ;[2306] No, set up the block
LNKX1H:
;[2247] Here to determine whether or not to include .LOW. in the map
MOVE T1,SG.TB+1 ;[2247] Get pointer to .LOW.
SKIPE NOJBDA ;[2247] Need a JOBDAT?
SKIPL RC.AT(T1) ;[2247] Or user program put anything in .LOW.?
JRST LNKX1I ;[2306] Yes, allow for .LOW. in the PDV map
MOVE T1,RC.NO ;[2247] Get number of psects
CAIE T1,1 ;[2247] Are there any other than .LOW.?
SETOM NOLOW ;[2247] Yes, don't put .LOW. in the map
>;[2330] IFN TOPS20
LNKX1I: MOVE R,SG.TB+1 ;[2306] Get the low segment RC block
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
IFE TOPS20,< ;[2054]
;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
> ;[2054] IFE TOPS20
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:
IFN TOPS20,<
SKIPE PRGPDV ;[2306] PROGRAM DATA VECTOR?
PUSHJ P,PDVBLD ;[2306] GO ALLOCATE THE SPACE
SKIPE NOJBDA ;[2306] JOBDAT NOT WANTED?
JRST RBJBDX ;[2211] YES, NO JOBDAT
> ;[1423] IFN TOPS20
SKIPE PAG.S2 ;HIGH SEG PAGING?
PUSHJ P,RDJBH ;YES, READ IN .JBHDA
SKIPE PAG.S1 ;LOW SEG PAGING?
PUSHJ P,RDJBL ;YES
RBJBDX: ;[1460]
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
IFN TOPS20,<
;PDVBLD - ROUTINE TO ALLOCATE SPACE FOR THE PDV
;
PDVBLD: HRRZ P1,PRGPDV ;[2306] GET THE PDV BLOCK
SKIPE .PVNAM(P1) ;[2306] ASCIZ NAME ALREADY SET?
JRST PVBLD1 ;[2306] YES
SKIPE T3,RUNAME ;[2306] GET PROGNAM
JRST .+3 ;[2306] SET
SKIPN T3,SSNAME ;[2306] IF NOT TRY SAVE FILE NAME
MOVE T3,LODNAM ;[2306] USE DEFAULT IF NOT SET
HLLZ T2,JOBNUM ;[2335] SIXBIT JOBNUMBER
HRRI T2,'LNK' ;[2335] REST OF PDV NAME
SKIPN T3 ;[2335] HAVE A NAME
MOVE T3,T2 ;[2335] NO, USE NNNLNK AS NAME
MOVEI T2,1 ;[2306] NEED ONE WORD FOR ASCIZ NAME
TRNE T3,7777 ;[2306] NAME 5 OR 6 CHARACTERS LONG?
MOVEI T2,2 ;[2306] YES, NEED 2 WORDS FOR ASCIZ NAME
PUSH P,T3 ;[2306] SAVE THE SIXBIT NAME
PUSHJ P,DY.GET## ;[2306] GET SPACE FOR ASCIZ NAME
POP P,T3 ;[2306] GET THE SIXBIT NAME BACK
MOVEM T1,.PVNAM(P1) ;[2306] STORE THE ADDRESS
HRLM T2,.PVNAM(P1) ;[2306] AND THE COUNT
MOVE T4,T1 ;[2306] GET THE ADDRESS
HRLI T4,(POINT 7,) ;[2306] MAKE A BYTE POINTER
PUSHJ P,DVDPB.## ;[2306] SIXBIT TO ASCIZ
PVBLD1: PUSHJ P,GETPVS ;[2306] FIND OUT WHERE TO PUT IT
MOVE T1,RC.HL(P4) ;[1423] PICK UP THE DESTINATION ADDRESS
MOVEM T1,PDVADR ;[1423] AND SAVE IT UNTIL LATER
;[2237] Calculate length of memory map here. Repeated calls to PDVMAP will
;[2237] let us compute the maximum length of the memory map. Note that the
;[2306] map may actually be slightly larger than we calculate, if the symbol
;[2306] table goes in an empty psect.
SETZ W3, ;[2306] INIT. MEMORY MAP LENGTH COUNTER
SKIPE NOPDMP ;[2306] DOING A MAP?
JRST PDGTNM ;[2306] NO
MOVEI R,1 ;[2237] START WITH PSECT 1 (.LOW.)
SKIPE NOLOW ;[2247] NEED TO COUNT .LOW.?
MOVEI R,2 ;[2247] NO, START WITH SECOND PSECT
PDLOOP: PUSHJ P,PDVMAP ;[2237] GO FIND A CONTIGUOUS MEMORY BLOCK
JRST PDGTLN ;[2237] NO MORE, WE HAVE THE LENGTH NOW
ADDI W3,MM.SLN ;[2306] FOUND ANOTHER BLOCK, ACCOUNT FOR IT
JRST PDLOOP ;[2237] KEEP COUNTING MEMORY MAP ENTRIES
PDGTLN: SKIPE R ;[2237] DON'T PUT NULL LAST PSECT INTO MAP
ADDI W3,MM.SLN ;[2306] ACCOUNT FOR LAST CALL TO PDVMAP
MOVE T4,RC.IV(P4) ;[2250] GET INITIAL PSECT VALUE
CAMN T4,RC.HL(P4) ;[2250] IS THIS CURRENTLY AN EMPTY PSECT?
ADDI W3,MM.SLN ;[2250] YES, IT WON'T BE ONCE PDV IS IN IT
ADDI W3,1 ;[2361] ACCOUNT FOR MAP LENGTH
MOVEM W3,PDMPLN ;[2237] STORE MAP LENGTH FOR USE IN PDVSET
PDGTNM: HLRZ T1,.PVNAM(P1) ;[2306] GET THE LENGTH OF THE NAME
ADD W3,T1 ;[2306] ADD IT TO LENGTH OF MAP
ADDI W3,PV.LEN ;[2306] ADD LENGTH OF THE PDV AND MAP HEADER
ADDM W3,RC.HL(P4) ;[2306] ACCOUNT FOR PDV+NAME+MAP LENGTH
MOVEM P4,PVPSEG ;[1423] KEEP TRACK OF THE RELOC COUNTER
POPJ P, ;[2237]
;SUBROUTINE TO FIND CONTIGUOUS BLOCKS OF MEMORY WITH THE SAME ATTRIBUTES.
;USED IN BUILDING THE PDV MEMORY MAP, AND TO DETERMINE THE MAP'S LENGTH.
;IF OVERLAPPING PSECTS HAVE CONFLICTING ATTRIBUTES, THEY ARE CONSIDERED TO
;BOTH BE READ-ONLY.
;
; CALL: R/ PSECT # TO START SCANNING IT (MUST BE VALID # OR
; YOU'LL BE SORRY!)
;
; RETURN: +1 NO MORE PSECTS, ACS SAME AS +2 RETURN EXCEPT R
; IS LAST PSECT #+1, OR 0 IF LAST PSECT WAS EMPTY.
;
; +2 T2/ LOW BLOCK ADDR.
; T3/ HIGH BLOCK ADDR.
; T4/ BLOCK ATTRIBUTES (EITHER AT.RO OR 0)
; R/ NEXT PSECT # THAT'S NOT CONTIGUOUS OR HAS
; DIFFERENT ATTRIBUTES AND IS NOT OVERLAPPING
;
; USED ACS: T2, T3, T4, R, W1, W2
;
PDVMAP: MOVE W2,@RC.TB ;[2237] GET PSECT TABLE ADDR.
MOVE T2,RC.IV(W2) ;[2237] GET BLOCK (AND THIS PSECT'S) START ADDR
MOVE T4,RC.AT(W2) ;[2237] GET ATTRIBUTES
TXZ T4,^-AT.RO ;[2237] CLEAR EVERYTHING BUT READ-ONLY BIT
MOVE T3,RC.HL(W2) ;[2237] REMEMBER WHERE THIS PSECT ENDS
CAMLE T3,T2 ;[2237] EMPTY PSECT (START ADDR .LE. END ADDR)?
JRST PDMAP2 ;[2237] NOT NULL, JUMP AHEAD
ADDI R,1 ;[2237] INCREMENT TO NEXT PSECT
CAMG R,RC.NO ;[2237] ALL DONE WITH PSECTS?
JRST PDVMAP ;[2237] NO, USE NEXT PSECT AS BLOCK START
SETZ R, ;[2237] YES, LAST PSECT IS NULL, CLEAR R
POPJ P, ;[2237] TAKE +1 RETURN
PDMAP1: MOVE T3,RC.HL(W2) ;[2237] YES, MAKE IT NEW HIGHEST ADDR. OF BLOCK
PDMAP2: SUBI T3,1 ;[2237] END ADDR. IS CURRENT ADDR. -1
PDMAP3: ADDI R,1 ;[2237] INCREMENT TO NEXT PSECT
CAMLE R,RC.NO ;[2237] ALL DONE WITH PSECTS?
POPJ P, ;[2237] YES, TAKE +1 RETURN
MOVE W2,@RC.TB ;[2237] NO, GET NEXT PSECT TABLE ADDR.
MOVE W1,RC.IV(W2) ;[2237] GET NEXT PSECT START ADDR.
SUBI W1,1 ;[2237] NO, MAKE ADJACENT ADDRESSES EQUAL
CAMLE W1,T3 ;[2237] IS PSECT ADJACENT OR OVERLAPPING?
JRST CPOPJ1 ;[2237] NO, END OF THIS MEMORY MAP ENTRY
CAML W1,T3 ;[2237] YES, DO THEY OVERLAP?
JRST PDVADJ ;[2237] NO, THEY'RE ADJACENT
MOVE W1,RC.AT(W2) ;[2237] YES, GET NEW PSECT'S ATTRIBUTES
TXZ W1,^-AT.RO ;[2237] CLEAR EVERYTHING BUT READ-ONLY BIT
CAME W1,T4 ;[2237] SAME ATTRIBUTES AS LAST PSECT?
MOVX T4,AT.RO ;[2237] NO, MUST BE A CONFLICT - SET BLOCK R.O.
JRST PDVCOM ;[2237] JOIN COMMON CODE
PDVADJ: MOVE W1,RC.AT(W2) ;[2237] YES, GET NEW PSECT'S ATTRIBUTES
TXZ W1,^-AT.RO ;[2237] CLEAR EVERYTHING BUT READ-ONLY BIT
CAME W1,T4 ;[2237] SAME ATTRIBUTES AS LAST PSECT?
JRST CPOPJ1 ;[2237] NO, END OF THIS MEMORY MAP ENTRY
PDVCOM: CAMGE T3,RC.HL(W2) ;[2237] YES, IS END ADDR. HIGHER THAN BEFORE?
JRST PDMAP1 ;[2237] YES, GO LOAD NEW END ADDR. AND CONTINUE
JRST PDMAP3 ;[2237] NO, CONTINUE LOOPING THROUGH ALL PSECTS
;GETPVS - ROUTINE TO FIGURE OUT WHERE THE PROGRAM DATA VECTOR GOES.
;RETURNS WITH:
;
; PVPNAM/ NAME (SIXBIT) OF PSECT TO APPEND PDV TO
; R/ AREA PSECT IS IN, LC.IX OR HC.IX
; P4/ POINTER TO RC BLOCK OF PSECT NAMED IN PVPNAM
; RC.HL(P4)/ FIRST ADDRESS TO STORE THE PDV IN
; PVPLIM/ LAST ADDRESS TO STORE THE PDV IN
;
;ALSO UPDATES LOWLOC IF NECESSARY.
;CLOSE RESEMBLENCE TO GETSST IS NO COINCIDENCE.
GETPVS: HLRZ R,PRGPDV ;[1423] PICK UP DESTINATION
CAIN R,-1 ;[1423] PSECT?
JRST GETP10 ;[1423] YES, GO FIND IT
GETP02: CAIN R,2 ;[1423] /PVBLOCK:HIGH?
JRST GETP08 ;[1423] YES, TREAT LIKE /PVBLOCK:PSECT:.HIGH.
CAIN R,1 ;[1423] /PVBLOCK:LOW?
JRST GETP03 ;[1423] YES
SKIPE LL.S2 ;[1423] DEFAULT -- IS THERE A HIGH SEG?
JRST GETP08 ;[1423] YES, PUT THE PDV THERE
;HERE IF /PVBLOCK:LOW
; APPEND THE PROGRAM DATA VECTOR TO THE LAST PSECT IN THE IMAGE.
; OUR FIRST MISSION IS TO FIND THAT PSECT...
GETP03: SETZB R,T3 ;[1423] INIT HIGHEST ADDR AND PSECT IDX
GETP04: MOVE T1,@RC.TB ;[1423] GET POINTER TO RC BLOCK OF NEXT PSECT
MOVE T2,RC.SG(T1) ;[1423] GET THE SEGMENT THAT THIS PSECT IS IN
CAIE T2,1 ;[1423] IN THE LOW SEGMENT?
JRST GETP06 ;[1423] NO, IT DOESN'T COUNT FOR /PVBLOCK:LOW
MOVE T2,RC.HL(T1) ;[1423] GET THE FIRST FREE AFTER THIS PSECT
CAMG T2,T3 ;[1423] HIGHEST SO FAR?
JRST GETP06 ;[1423] NO, CONTINUE
MOVE T3,T2 ;[1423] SAVE NEW BEST
MOVE T4,R ;[1423] AND WHAT PSECT IT WAS
MOVE T2,RC.NM(T1) ;[1423] GET THE WINNER'S NAME
MOVEM T2,PVPNAM ;[1423] STORE FOR ERROR MESSAGES
GETP06: CAMGE R,RC.NO ;[1423] ALL DONE?
AOJA R,GETP04 ;[1423] NO, LOOP
MOVE R,T4 ;[1423] YES, SAVE PSECT INDEX OF LAST ONE
JRST GETP14 ;[1423] GO UPDATE THAT PSECT
;HERE ON /PVBLOCK:HIGH. FAKE /PVBLOCK:PSECT:.HIGH. AND FALL INTO PSECT CODE.
GETP08: MOVE T1,['.HIGH.'] ;[1423] /PVBLOCK:HIGH IS JUST LIKE A PSECT
MOVEM T1,PVPNAM ;[1423] STORE
;HERE ON /PVBLOCK:PSECT:xxxxxx. FIND THE PSECT IN THE RC TABLES.
GETP10: SETZ R, ;[1423] YES, HAVE PSECT NAME
MOVE W2,PVPNAM ;[2220] GET THE PDV NAME
GETP12: MOVE T1,@RC.TB ;[1423]
MOVE T2,RC.NM(T1) ;[2220] GET PSECT NAME
PUSHJ P,NAMCMP## ;[2220] IS THIS THE ONE?
JRST GETP14 ;[1423] YES,
ADDI R,1 ;[1423] NEXT ONE
CAMG R,RC.NO ;[1423] ANY MORE?
JRST GETP12 ;[1423] YES, LOOP
E$$NPP::.ERR. (MS,.EC,V%L,L%W,S%W,NPP,<Non-existent psect >) ;[1423]
.ETC. (SBX,.EC!.EP,,,,PVPNAM) ;[1423]
.ETC. (STR,,,,,,< specified for program data vector>) ;[1423]
MOVEI R,1 ;[1423] SET TO LOW
HRLM R,PRGPDV ;[1423]
JRST GETP02 ;[1423] AND LOOP BACK
;HERE WITH THE PSECT INDEX TO USE IN R, AND ITS NAME IN PVPNAM.
;NOW CALCULATE THE UPPER BOUND POSSIBLE FOR THE PDV.
;THE NEXT PSECT ORIGIN WE WOULD CROSS, OR STOP AT 777777 IF NO MORE PSECTS.
GETP14: MOVE P4,@RC.TB ;[1423] POINTER TO THIS PSECT'S RC BLOCK
MOVX T1,AT.RP ;[2247] GET THE RELOCATABLE BIT
ANDCAM T1,RC.AT(P4) ;[2247] INDICATE IT EXISTS (IN CASE .LOW.)
MOVE T4,RC.HL(P4) ;[1423] ADDR OF FIRST FREE LOCATION
ADDI R,1 ;[1423] START THE SEARCH AT THE NEXT PSECT
;LOOP BACK HERE ON EACH NEW PSECT, LOOKING FOR ONE WHOSE ORIGIN
;IS .GE. C(T4).
GETP16: CAMLE R,RC.NO ;[1423] CHECKED THEM ALL YET?
JRST GETP18 ;[1423] YES, GO USE 777777
MOVE T1,@RC.TB ;[1423] GET PSECT'S RC BLOCK
MOVE T2,RC.IV(T1) ;[1423] GET ORIGIN OF THIS PSECT
CAMGE T2,T4 ;[1423] START ABOVE THE PDV PSECT?
AOJA R,GETP16 ;[1423] NO, MUST HAVE BEEN OVERLAPPING PSECT
MOVE T3,RC.HL(T1) ;[1423] YES, CHECK FOR ZERO-LENGTH PSECT
CAMG T3,T2 ;[1423] WOULD WE OVERWRITE ANYTHING?
AOJA R,GETP16 ;[1423] NO, IGNORE THIS PSECT
SOSA T2 ;[1423] YES, LAST ADDR TO USE IS ONE LESS
GETP18: HLLO T2,RC.HL(P4) ;[1450] ROUND UP TO SECTION BOUNDARY
MOVEM T2,PVPLIM ;[1423] STORE NEWLY CALCULATED LIMIT
;NOW SET UP SOME FINAL THINGS FOR THE REST OF LINK, THEN RETURN.
GETP20: MOVE R,RC.SG(P4) ;[1423] FETCH SEGMENT INDEX FOR PSECTS
MOVE T1,RC.HL(P4) ;[1423] START OF PROGRAM DATA VECTOR
POPJ P, ;[1423] END OF GETPVS
> ;[1423] IFN TOPS20
;HERE TO READ IN FIRST 10 WORDS OF HIGH SEGMENT
;[2247] Under TOPS-20 just map the first high segment page into the DY area.
;[2247] It is never returned, as there is plenty of memory available,
;[2247] and by the time it could be there won't be anyone who needs it.
RDJBH:
IFE TOPS20,< ;[2247]
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
> ;[1401] IFE TOPS20
IFN TOPS20,<
MOVEI T2,2*.IPS ;[2055] 2*.IPS INSURES ONE FULL PAGE
PUSHJ P,DY.GET ;[1401]
IORI T1,.IPM ;[2247] END OF THIS PAGE
ADDI T1,1 ;[2247] SET ON PAGE BOUNDARY
MOVEM T1,JBHPTR ;[2247] STORE LOCATION
LSH T1,-9 ;[1401]
HRLI T1,.FHSLF ;[1401] PROCESS IS SELF
MOVE T2,T1 ;[1401]
MOVE T1,LL.S2 ;[2247] GET THE HIGH SEGMENT ORIGIN
LSH T1,-9 ;[2247] IN PAGES
HRL T1,HC.JF ;[2247] FORK HANDLE
MOVE T3,[PM%RWX] ;[1401] MOVE ONE PAGE FOR READING
PMAP% ;[1401]
ERCAL E$$IHC## ;[2247] CAN'T DO IT
POPJ P, ;[1401] AND RETURN
> ;[1401] IFN TOPS20
;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
;[2247] Under TOPS-20 just map the first page into the DY area.
;[2247] It is never returned, as there is plenty of memory available,
;[2247] and by the time it could be there won't be anyone who needs it.
RDJBL:
IFE TOPS20,<
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
> ;[1401] IFE TOPS20
IFN TOPS20,<
MOVEI T2,2*.IPS ;[2247] 2*.IPS INSURES ONE FULL PAGE
PUSHJ P,DY.GET ;[1401]
IORI T1,.IPM ;[2247] END OF THIS PAGE
ADDI T1,1 ;[2247] SET ON PAGE BOUNDARY
MOVEM T1,JOBPTR ;[2247] HOLD OFFSET IN CORE
LSH T1,-9 ;[1401]
HRLI T1,.FHSLF ;[1401] PROCESS IS SELF
MOVE T2,T1 ;[1401]
HRLZ T1,LC.JF ;[1401] FILEJFN,,PAGE 0
MOVE T3,[PM%RWX] ;[1401] MOVE ONE PAGE FOR READING
PMAP% ;[1401]
ERCAL E$$ILC## ;[2247] CAN'T DO IT
POPJ P, ;[2247] RETURN
> ;[1401] IFN TOPS20
IFE TOPS20,< ;[2247]
;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
>;[2247] IFE TOPS20
;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:
IFN TOPS20,< ;[2202]
SKIPE NOJBDA ;[2306] JOBDAT NOT WANTED?
JRST CHKRS0 ;[2211] YES, NO JOBDAT
MOVE T1,JOBPTR ;[2306] POINT TO JOBDAT
> ;IFN TOPS20 [2202]
IFE TOPS20,< ;[2306]
SKIPE PAG.S1 ;[1172] FIND JOBDAT
SKIPA T1,JOBPTR ;[1172] IN DY IF PAGING
MOVE T1,LC.LB ;[1172] IN LC AREA IF NOT
>;[2306] IFE TOPS20
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] ..
CHKRS0: SKIPE NOSYMS ;[1460] /NOSYMBOLS?
JRST NORST ;[1172] YES, FORGET IT
IFN TOPS20,< ;[2202]
SKIPN NOJBDA ;[2306] DOES JOBDAT EXIST?
> ;[2202] IFN TOPS20
SKIPN .JBDDT(T1) ;[1172] C(.JBDDT) <> 0?
CHKRS1: SKIPE SYMSEG ;[2211] 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
IFE TOPS20,< ;[2335]
SKIPE PAG.S0(R) ;[2335] SYMBOL SEGMENT PAGING?
> ;[2335] IFE TOPS20
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
;[2306] Here to set up the symbol vector
IFN TOPS20,< ;[2366]
SKIPN T2,PRGPDV ;[2306] Get the pointer to the PDV
JRST SYMVNO ;[2306] No PDV, so no symbol vector
MOVE W1,.PVSYM(T2) ;[2306] Get the symbol table vector address
>;[2366] IFN TOPS20
IFE TOPS20,< ;[2366]
SKIPN W1,SYMVEC ;[2366] Building a symbol vector?
JRST SYMVNO ;[2366] No
>;[2366] IFE TOPS20
SUB W1,LL.S0(R) ;[2311] Subtract the segment base
MOVE W2,W1 ;[2306] Get the address
ADDI W2,SV.LEN-1 ;[2306] Last address needed
CAMG W2,TAB.UW(R) ;[2306] Is it above the window?
CAMGE W1,TAB.LW(R) ;[2306] Is it below the window?
CAIA ;[2306] Must move window
JRST SYMVST ;[2306] No, no need to move window
MOVE T1,TAB.LW(R) ;[2306] Get current lower bound
MOVE T2,TAB.UW(R) ;[2306] And upper bound
PUSHJ P,@[LC.OUT## ;[2306] Remove it
HC.OUT##]-1(R) ;[2306] From the window
MOVE T1,W1 ;[2306] Get the bottom address
TRZ T1,.IPM ;[2306] Put it on a page bound
MOVEM T1,TAB.LW(R) ;[2306] Set the bottom of the window
TRO W2,.IPM ;[2306] Set to top of page
MOVE T2,W2 ;[2306] Get the high address
SUB T2,T1 ;[2306] Get the size
ADD T2,TAB.LB(R) ;[2306] Get the high address in memory
CAMG T2,TAB.AB(R) ;[2306] Will it fit?
JRST SYMVGT ;[2306] Yes, just go get it
PUSH P,T2 ;[2306] Save the upper bound
SUB T2,TAB.AB(R) ;[2306] How much is needed
MOVE P1,R ;[2306] Get the index
MOVE P2,T2 ;[2306] And the amound needed
PUSHJ P,LNKCOR## ;[2306] Try and get it
PUSHJ P,E$$MEF## ;[2306] Only wanted a maximum 2 pages
POP P,T2 ;[2306] Restore the upper bound
SYMVGT: MOVEM T2,TAB.AB(R) ;[2306] Save the upper bound
MOVEM W2,TAB.UW(R) ;[2306] And the size
MOVE T1,TAB.LW(R) ;[2306] Get the lower bound
MOVE T2,TAB.UW(R) ;[2306] And the upper bound
PUSHJ P,@[LC.IN## ;[2306] Get it
HC.IN##]-1(R) ;[2306] Into window
SYMVST: SUB W1,TAB.LW(R) ;[2306] Get the offset into the window
ADD W1,TAB.LB(R) ;[2306] Unrelocate
MOVEI T1,SV.LEN ;[2306] Get the symbol vector length
MOVEM T1,(W1) ;[2306] Store it
MOVE T1,DSTADR ;[2366] Get the address of the defined symbols
IFN TOPS20,< ;[2366]
MOVE T2,FXSBIT ;[2306] Get the section bits
TXNN T2,^-1B0 ;[2306] Any non-zero sections?
HRLI T1,(IFIW) ;[2306] No, make it an IFIW
>;[2366] IFN TOPS20
MOVEM T1,2(W1) ;[2306] Store the defined address
SKIPN USTADR ;[2306] Any undefined symbols?
JRST SYMVS1 ;[2306] No
MOVE T1,USTADR ;[2306] Yes, get the undefined symbol address
IFN TOPS20,< ;[2366]
TXNN T2,^-1B0 ;[2306] Any non-zero sections?
HRLI T1,(IFIW) ;[2306] No, make it an IFIW
>;[2366] IFN TOPS20
SYMVS1: MOVEM T1,SV.SLN+2(W1) ;[2306] Store the undefined address
MOVE T1,DSYCNT ;[2306] Get the defined symbol count
TXO T1,FLD(.R50D,ST%TYP) ;[2306] Set Radix 50 defined type
MOVEM T1,1(W1) ;[2306] Store the count and zero third word
MOVE T1,USYCNT ;[2306] Get the undefined symbol count
TXO T1,FLD(.R50U,ST%TYP) ;[2306] Set Radix 50 undefined type
MOVEM T1,SV.SLN+1(W1) ;[2306] Store it
SETZM 3(W1) ;[2306] Zero the defined table third word
SETZM SV.SLN+3(W1) ;[2306] Zero the undefined table third word
SYMVNO:
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+PH.RDX ;[1400] 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+PH.RDX ;[1400] - COUNT
MOVEM T3,JOB116 ;[1172] STORE IN INTERNAL PTR
MOVEM T3,.JBSYM(T1) ;[1172] STORE SYMBOL TABLE PTR
IFN TOPS20,< ;[2247] Read symbols now on TOPS-20
MOVM P1,T2 ;[2247] Get count of symbols
HRRZ P2,T3 ;[2247] Save the base address
MOVE P3,LS.LB ;[2247] Get the start of the symbols
OVLRS1: MOVE T1,LW.LC ;[2247] Get the lower bound
MOVE T2,UW.LC ;[2247] And the upper bound
PUSHJ P,LC.OUT## ;[2247] Remove it from memory
HRRZ T1,P2 ;[2247] Get base address
TRZ T1,.IPM ;[2247] Put it on a page boundary
HRRZ T2,P1 ;[2247] Get the size wanted
MOVE T3,LC.AB ;[2247] Get the top
SUB T3,LC.LB ;[2247] Get the size available
CAMLE T2,T3 ;[2247] We need less than we have?
MOVE T2,T3 ;[2247] No, use what we have
ADD T2,T1 ;[2247] Get the max address
IORX T2,.IPM ;[2247] Set at end of a page boundary
MOVEM T1,LW.LC ;[2247] Store the new lower bound
MOVEM T2,UW.LC ;[2247] And the new upper
PUSHJ P,LC.IN## ;[2247] Get it
MOVE T3,P2 ;[2247] Get the base address
SUB T3,LW.LC ;[2247] Minus the window
ADD T3,LC.LB ;[2247] Locate in memory
HRRZ T1,T3 ;[2247] Destination for BLT
HRL T1,P3 ;[2247] Source for BLT
ADDI T3,-1(P1) ;[2247] How far we want to go
MOVE T2,T3 ;[2247] Use as last to load
CAMLE T2,LC.AB ;[2247] More than we have
MOVE T2,LC.AB ;[2247] Yes, do what we can
BLT T1,(T2) ;[2247] Copy it
MOVE T2,UW.LC ;[2247] No, Get highest location done
SUBI T2,-1(P2) ;[2247] Figure out how much was done
SUB P1,T2 ;[2247] Reduce the count by that much
JUMPLE P1,NORST ;[2247] Check for none left (done)
ADD P2,T2 ;[2247] Where to copy to next
ADD P3,T2 ;[2247] Where to copy from next
JRST OVLRS1 ;[2247] Copy some more
>;[2247] IFN TOPS20
> ;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:
IFN TOPS20,<
SKIPE PRGPDV ;[1423] CREATE A PDV?
PUSHJ P,PDVSET ;[1423] YES
> ;[2260]
SKIPE PAG.S1 ;[2241] LC AREA PAGING?
SKIPA P1,JOBPTR ;[2241] YES, JOBDAT IS IN DY
MOVE P1,LC.LB ;[2241] NO, IT'S IN LC
SKIPE PAG.S2 ;[2241] HC AREA?
SKIPA P2,JBHPTR ;[2241] YES, FETCH DY PTR
MOVE P2,HC.LB ;[2241] NO, FETCH HC PTR (OR 0)
;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, ;[2211] ASSUME WE DON'T START PROGRAM
SKIPE EXECSW ;[2211] GO INTO EXECUTION?
MOVE T1,STADDR ;[2211] YES, ASSUME .JBSA
HRRZ T2,DEBUGSW ;[2211] IF DEBUGGING, DEBUGGER'S START ADDRESS
SKIPGE DEBUGSW ;[2211] TAKES PRIORITY SO
MOVE T1,@STLOCN(T2) ;[2211] FIND IT
HRRM T1,EXECSW ;[2211] IN ANY CASE STORE BACK IN EXECSW
IFN TOPS20,< ;[2366]
MOVE T1,FXSBIT ;[2211] GET SECTION BITS
SKIPE NOJBDA ;[2306] JOBDAT NOT WANTED
JRST JOBST9 ;[2260] YES, DON'T BOTHER WITH JOBDAT
>;[2366] IFN TOPS20
;SUBTTL SET UP JOBDAT AREA
;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).
IFE TOPS20,< ;[2366]
;[2366] If this is an extended addressing program, then the values must
;[2366] reflect section zero only. It is necessary to figure out what
;[2366] those values are.
MOVE T1,HL.S1 ;[2366] Get the highest loaded
MOVE T2,HC.S1 ;[2366] And the highest code
TLNN T1,-1 ;[2366] Extended addressing?
JRST FINRS3 ;[2366] No, no problem
MOVEI R,1 ;[2366] Start at first psect (ignore .abs.)
SETZ T1, ;[2366] Init highest loaded
MOVEI T3,777777 ;[2366] Highest location were psect can start
MOVEI T4,2 ;[2366] Index for high segment
FNDSZP: MOVE W1,@RC.TB ;[2366] Get pointer to next psect
CAMN T4,RC.SG(W1) ;[2366] High segment?
JRST FNDSZ1 ;[2366] Yes, ignore it
CAMGE T3,RC.IV(W1) ;[2366] Start outside section zero?
JRST FNDSZ1 ;[2366] Yes, ignore
CAMGE T1,RC.HL(W1) ;[2366] Higher than what we have?
MOVE T1,RC.HL(W1) ;[2366] Yes, new highest
FNDSZ1: CAMGE R,RC.NO ;[2366] Looked at all psects?
AOJA R,FNDSZP ;[2366] No, look at next
CAILE T1,777777 ;[2366] High psect cross section?
MOVEI T1,777777 ;[2366] Yes UGLY, but only want section zero
MOVE T2,T1 ;[2366] Use highest loaded as highest code
FINRS3: PUSH P,HL.S1 ;[2366] Keep the actual values
PUSH P,HC.S1 ;[2366] of high loaded and high code
MOVEM T1,HL.S1 ;[2366] Set up only section zero numbers
MOVEM T2,HC.S1 ;[2366] For JOBDAT
>;[2366] IFE TOPS20
SKIPE T2,HC.S1 ;[2211] GET HIGHEST DATA LOCATION LOADED
SUBI T2,1 ;[2211] MAKE IT HIGHEST LOC LOADED
IFN FTOVERLAY,< ;[2211]
SKIPL LNKMAX ;[2211] LOADED ANY OVERLAYS?
SKIPN T1,JOB116 ;[2211] AND SAVED SYMBOLS?
JRST .+4 ;[2211] NO
HLRE T2,T1 ;[2211] -LENGTH
MOVM T2,T2 ;[2211]
ADDI T2,-1(T1) ;[2211] HIGHEST LOCATION
> ;[2211]
HRLZM T2,.JBCOR(P1) ;[2211] PUT HIGHEST LOC IN LEFT HALF
HRRZ T2,HL.S1 ;[2211] GET HIGHEST LOC REQUIRED
HRL T2,STADDR ;[2211] GET STARTING ADDRESS
MOVSM T2,.JBSA(P1) ;[2211] SET .JBSA AND .JBFF
HRRZM T2,.JBFF(P1) ;[2211] INCASE RESET NOT DONE FIRST
IOR. T2,.PGSIZ ;[2211] INCLUDE ALL OF THIS PAGE
HRRZM T2,.JBREL(P1) ;[2211] SET .JBREL
MOVSI T2,(HALT) ;[2211] PUT A HALT IN .JB41
SKIPN .JB41(P1) ;[2211] UNLESS ALREADY SETUP
MOVEM T2,.JB41(P1) ;[2211]
MOVE T2,.JBSYM(P1) ;[2211] GET SYMBOL TABLE POINTER
HRRZ T1,T2 ;[2211] GET POINTER
JUMPE P2,JOBST0 ;[2211] NO HIGH SEG POSSIBLE
CAML T1,LL.S2 ;[2211] SEE IF IN HIGH SEG
MOVEM T2,.JBHSM(P2) ;[2211] STORE IN HIGH SEG DATA AREA
SKIPE T1,HL.S2 ;[2211] GET HIGHEST LOC +1
SUBI T1,1 ;[2211] HIGHEST LEGAL ADDRESS
ADD T1,LL.S2 ;[2211] PLUS ORIGIN
IOR. T1,.PGSIZ ;[2211] PUT ON PAGE BOUND
SKIPN T2,HL.S2 ;[2211] LENGTH TO SAVE
JRST JOBST1 ;[2211] NONE?
SKIPN .JBDDT##(P1) ;[2211] DDT LOADED?
JRST JOBST1 ;[2211] NO, NUMBER IS OK
SUBI T2,1 ;[2211] YES, BE LIKE MONITOR
IOR. T2,.PGSIZ ;[2211] ROUND UP TO TOP OF PAGE
ADDI T2,1 ;[2211] THENCE TO BOTTOM OF NEXT
JOBST1: HRL T1,T2 ;[2211] LENGTH TO SAVE,,HIGHEST ADDR
MOVEM T1,.JBHRL(P1) ;[2211] LENGTH,,HIGHEST ADDRESS
JOBST0: MOVE T1,.JBERR ;[2211] GET NO OF PREVIOUS ERRORS
MOVEM T1,.JBERR(P1) ;[2211] COUNT AS EXECUTION ERRORS
HRRZM T1,ERRNO ;[2070] PROHIBIT EXECUTION IF NON-ZERO
PUSHJ P,HJBSET ;[1172] VESTIGAL JOBDAT
IFE TOPS20,< ;[2366]
POP P,HC.S1 ;[2366] Restore actual highest code
POP P,HL.S1 ;[2366] And highest loaded
>;[2366] IFE TOPS20
JRST SAVTST ;[1172] DONE WITH CHKRST, GO CHECK /SAVE
IFN TOPS20,< ;[2366]
JOBST9: MOVE T1,.JBERR ;[2260] GET # OF PREVIOUS ERRORS
HRRZM T1,ERRNO ;[2260] PROHIBIT EXECUTION IF NON-ZERO
JRST SAVTST ;[2260]
>;[2366] IFN TOPS20
;TABLE OF WHERE TO START FOR EACH DEBUGGER
DEFINE KEYMAC(A,B)<
XALL ;;[2211] GIVE A GOOD LISTING
IFIDN <A><DEB>,< ;;[2211] SELECT ONLY DEBUGGING KEYWORDS
%%1==-1 ;;[2211] SKIP DUMMY ENTRY
IRP B,< ;;[2211] CHECK EACH KEYWORD
IFGE %%1,< ;;[2211] THAT IS NOT THE DUMMY
IFN <%%1&1>,< ;;[2211] AND IS A DEBUGGER NAME
%%2==0 ;;[2211] ASSUME WON'T FIND A DEBUGGER
IFN TOPS20,< ;;[2211] TOPS-20 UDDT IS SPECIAL
IFIDN <B><DDT>,< ;;[2211] CHECK FOR DDT DEBUGGER
[770000] ;UDDT STARTS AT 770000
DEB$DDT==%%1_<-1> ;[2363] SET UP A SYMBOLIC NAME
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
>
IFIDN <B><FORDDT>,< ;;[2211] FORDDT IS SPECIAL
STADDR ;FORDDT FORCES START ADDRESS TO ITSELF
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
IFIDN <B><COBDDT>,< ;;[2211] COBDDT IS SPECIAL
STADDR ;COBDDT GETS CONTROL FROM COBOL PROGRAM
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
IFIDN <B><ALGDDT>,< ;;[2211] ALGDDT IS SPECIAL
.JBREN(P1) ;[2211] ALGDDT STARTS FROM REENTER ADDRESS
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
IFIDN <B><SIMDDT>,< ;;[2211] SIMDDT IS SPECIAL
.JBREN(P1) ;[2211] SIMDDT STARTS FROM REENTER ADDRESS
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
IFIDN <B><PASDDT>,< ;;[2211] PASDDT IS SPECIAL
STADDR ;[2211] PASDDT FORCES START ADDRESS TO ITSELF
%%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER
>
IFE %%2,< ;;[2211] IF IT WASN'T ABOVE DEBUGGERS
.JBDDT(P1) ;OTHER DEBUGGERS SET .JBDDT
>
>
>
%%1==%%1+1 ;;[2211] ADVANCE TO NEXT ENTRY
>
>
PURGE %%1,%%2 ;;[2211] CLEAN UP AFTERWARD
SALL ;;[2211] ..
>
STLOCN: KEYWORDS
;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
MOVE W2,SSGNAM ;[2220] GET THE SYMBOL TABLE PSECT NAME
GETS12: MOVE T1,@RC.TB ;[1132]
MOVE T2,RC.NM(T1) ;[2220] GET PSECT NAME
PUSHJ P,NAMCMP## ;[2220] 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
MOVX T1,AT.RP ;[2247] GET THE RELOCATABLE BIT
ANDCAM T1,RC.AT(P4) ;[2247] INDICATE IT EXISTS (IN CASE .LOW.)
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:
SOS T2,RC.LM(P4) ;[1454] ROUND UP TO SECTION BOUNDARY
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
IFN TOPS20,< ;[2306]
SKIPN T2,PRGPDV ;[2306] WANT A PDV?
JRST GETS22 ;[2335] NO, DON'T HAVE TO ALLOW FOR SIZE
MOVEM T1,.PVSYM(T2) ;[2306] YES, REMEMBER IT'S ADDRESS
>;[2366] IFN TOPS20
IFE TOPS20,< ;[2366]
SETZM SYMVEC ;[2366] NOT BUILDING A SYMBOL VECTOR (YET)
MOVE T2,HL.S1 ;[2366] GET THE HIGHEST LOADED
TLNN T2,-1 ;[2366] LOADED OUTSIDE SECTION ZERO?
JRST GETS22 ;[2366] NO, DON'T HAVE SYMBOL VECTOR
MOVEM T1,SYMVEC ;[2366] YES, REMEMBER IT'S ADDRESS
>;[2366] IFE TOPS20
IFN TOPS20,< ;[2366]
MOVEI T2,MM.SLN ;[2306] GET THE SIZE OF A PSECT
SKIPN NOPDMP ;[2336] WANT DEFAULT MAP?
CAMLE T1,RC.IV(P4) ;[2306] EMPTY PSECT?
JRST GETS21 ;[2306] NO, NO PROBLEM
MOVEI T2,MM.SLN ;[2306] YES, GET THE SIZE OF A MAP ENTRY
ADDM T2,PDMPLN ;[2306] ADD TO SIZE OF MAP
MOVE T1,PVPSEG ;[2306] GET THE RC POINTER FOR THE PDV PSECT
ADDM T2,RC.HL(T1) ;[2306] ACCOUNT FOR ANOTHER PSECT
>;[2366] IFN TOPS20
GETS21: MOVEI T1,SV.LEN ;[2306] SIZE OF SYMBOL VECTOR
ADDB T1,RC.HL(P4) ;[2306] UPDATE SIZE OF PSECT
GETS22: MOVEM T1,PATLOC ;[2366] REMEMBER FOR RST
ADD T1,PATSPC ;[1172] START OF REAL SYMBOL TABLE
MOVEM T1,RC.HL(P4) ;[1172] UPDATE SIZE OF PSECT
IFE TOPS20,< ;[2247]
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.
>;[2247] IFE TOPS20
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: MOVE T1,LW.S0(R) ;[2202] BOTTOM OF WINDOW
MOVE T2,UW.S0(R) ;[2202] TOP
PUSHJ P,@TB.OUT##(R) ;[1172] WRITE ENTIRE WINDOW TO DISK
IFE TOPS20,<
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
> ;[1401] IFE TOPS20
IFN TOPS20,<
MOVE T1,TAB.LB(R) ;[1401] SHRINK WINDOW TO ONE PAGE
ADDI T1,.IPS-1 ;[1401]
MOVEM T1,TAB.AB(R) ;[1401]
> ;[1401] IFN TOPS20
MOVE T2,RC.HL(P4) ;[2202] GET FIRST ADDR TO STORE A SYMBOL IN
SUB T2,LL.S0(R) ;[2202] RELATIVE TO SEGMENT START
ANDCMI T2,.IPM ;[2202] NEW BOTTOM OF WINDOW
MOVEM T2,LW.S0(R) ;[2202] STORE
IORI T2,.IPM ;[2202] NEW TOP OF WINDOW
IFE TOPS20,<
CAMN T2,UW.S0(R) ;[2202] WHERE IT WAS ALREADY?
POPJ P, ;[2202] YES, DONE
> ;[1401] IFE TOPS20
MOVEM T2,UW.S0(R) ;[2202] NO, MUST READ IN THE DATA
MOVE T1,LW.S0(R) ;[2202] GET THE UPPER BOUND
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
MOVEM T1,USTADR ;[2245] SAVE ADDR FOR PDV SYM TABLE VECTOR
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)
TLNN W2,770000 ;[2373] IS IT A LONG SYMBOL?
PUSHJ P,LUNDF ;[2373] YES - GO GET 1ST SXI CHARACTERS
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 USYCNT ;[2306] 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
LUNDF: HRRZ T1,W2 ;[2373] GET THE GS OFFSET TO LONG NAME
ADD T1,GS.LB ;[2373] ADD IN GS BASE
MOVE W2,(T1) ;[2373] 1ST 6 CHARACTERS TO W2
POPJ P, ;[2373] RETURN
;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!FS.FXC ;[1325] CHECK FOR CHAINED OR 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
TXNN W1,FS.FXC ;[1325] IS IT A SECONDARY CHAINED FIXUP?
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 USYCNT ;[2306] 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
MOVE T2,USYCNT ;[2306] GET NUMBER OF UNDEFINED SYMBOLS
ADD T2,T2 ;[2306] TWO WORDS PER SYMBOL
MOVEM T2,USYCNT ;[2245] SAVE FOR PDV SYM TABLE VECTOR
MOVNS T2 ;[2306] WANT -LENGTH OF TABLE
HRRM T2,JOB117 ;[1172] FORM ADDR,,-LEN
MOVSS T2,JOB117 ;[1172] FORM -LEN,,ADDR
IFN TOPS20,< ;[2366]
SKIPE NOJBDA ;[2211] JOBDAT WANTED?
POPJ P, ;[2211] NO
>;[2366] IFN TOPS20
MOVEM T2,.JBUSY(T1) ;NO, 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)
MOVEM T1,DSTADR ;[2245] SAVE FOR PDV SYM TABLE VECTOR
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
MOVE T2,DSYCNT ;[2306] GET HOW MANY SYMBOLS
ADD T2,T2 ;[2306] TWO WORDS PER SYMBOL
MOVEM T2,DSYCNT ;[2245] SAVE FOR PDV SYMBOL TABLE VECTOR
MOVNS T2 ;[2306] WANT -COUNT
HRRM T2,JOB116 ;[1172] ADDR,,-LEN
MOVSS T2,JOB116 ;[1172] -LEN,,ADDR
IFN TOPS20,< ;[2366]
SKIPE NOJBDA ;[2211] JOBDAT WANTED?
POPJ P, ;[2211] NO
>;[2366] IFN TOPS20
IFE TOPS20,< ;[2366]
SKIPE SYMVEC ;[2366] BUILDING A SYMBOL VECTOR
MOVE T2,SYMVEC ;[2366] YES, GET THE VECTOR ADDRESS
>;[2366] IFE TOPS20
MOVEM T2,.JBSYM(T1) ;[2211] NO, 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 T2,LSYM ;[2202] ADDRESS OF LAST SYMBOL STORED +1
SUBI T2,1 ;[2202] HIGHESE ADDRESS STORED TO
IORI T2,.IPM ;[2202] BLOCK BOUND
MOVEM T2,UW.LS ;[2202] REMEMBER WHAT'S THERE
IFN TOPS20,<
CAMG T2,LW.LS ;[2202] Check for current page never used
ADDI T2,.IPS ;[2202] Must write out one page anyways
> ;[1536]
MOVE T1,LW.LS ;[2202] FORM BLT WORD
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$$MMF## ;[2202] CANNOT HAPPEN
PUSHJ P,LS.FXR## ;[1401] DO ANY SYMBOL TABLE FIXUPS REMAINING
;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
MOVE T1,LW.LS ;[2202] NOW FILL BOTTOM PAGE
MOVE T2,LW.LS ;[2202] REST WILL BE FILLED BY PAGSYM
IORI T2,.IPM ;[2202] 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 DSYCNT ;[2306] 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 DSYCNT ;[2306] 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 DSYCNT ;[2306] 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 DSYCNT ;[2306] 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 DSYCNT ;[2306] 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
SETZ W2, ;[2256] ONLY HERE IF DEFINED BY /SWITCH
PUSH P,W2 ;[2256] SAVE THE LOW SEG ORIGIN
MOVX T1,S.TTL!S.SEG!S.SHI ;[2256] FLAGS
PUSHJ P,GETAST ;[2256] GET EXTENSION TRIPLET
SETZ W2, ;[2256] THERE ISN'T ONE
MOVE W3,W2 ;[2256] HIGH SEG BREAK IN W3
POP P,W2 ;[2256] GET BACK LOW SEG BREAK
SKIPE W3 ;IF ANY HIGH SEG STUFF
MOVE W2,W3 ;USE IT
POP P,W3 ;GET W3 BACK
HRR W3,W2 ;[2256] FIX IT UP
POP P,W2
PUSHJ P,SYMOUT ;OUTPUT PSEUDO SYMBOL
JRST [
SKIPN SYMDEW ;[1455] ALREADY EXHAUSED RESERVE?
POPJ P, ;[1455] DON'T KEEP TRYING
SETZM SYMDEW ;[1172] USE THE RESERVE TO STORE THIS TITLE
JRST .-1] ;[1172] TRY AGAIN
AOS DSYCNT ;[2306] 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
IFE TOPS20,<
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
MOVE T2,UW.LS ;[2202] TRANSFER WORD TO WHOLE AREA
SUBI T2,.IPS ;[2202] BUT WE ALREADY HAVE LAST PAGE
PUSHJ P,LS.IN ;[1172] FILL UP THE AREA
JRST CPOPJ1 ;[1172] SKIP RETURN
> ;[1401] IFE TOPS20
IFN TOPS20,<
MOVE T2,LS.PT ;[1510]
SUB T2,LS.LB ;[1510]
ADD T2,LW.LS ;[1510]
MOVEM T2,LS.PT ;[1510] SAVE LS.PT AS VIRTUAL ADDR
MOVE T1,LW.LS ;[2202] SEND OUT CURRENT PAGES
MOVE T2,UW.LS ;[2202] ALL OF THEM
PUSHJ P,LS.OUT ;[1401] DO IT
MOVE T1,LS.AB ;[2202] WHAT'S AVAILABLE?
SUB T1,LS.LB ;[2202] SIZE OF LS AREA
MOVE T2,LW.LS ;[2202] WHAT'S LEFT?
ADDI T2,.IPS-1 ;[2202] SYMBOLS FROM HERE BACK TO 0
SUBM T2,T1 ;[2202] GET THE LOWER BOUND IN T1
SKIPGE T1 ;[2202] GREATER THAN ZERO?
SETZ T1, ;[2202] NO, EVERYTHING UP TO HERE WILL FIT
MOVEM T1,LW.LS ;[2202] NEW LOWER BOUND
MOVEM T2,UW.LS ;[2202] NEW UPPER BOUND
PUSHJ P,LS.IN ;[1401] DO IT
MOVE T1,UW.LS ;[2202] GET THE UPPER BOUND
SUB T1,LW.LS ;[2202] GET THE SIZE
ADD T1,LS.LB ;[2202] ADD THE BASE
MOVEM T1,LS.AB ;[2202] CURRENT BOUND
MOVE T2,LS.PT ;[1510]
SUB T2,LW.LS ;[1510]
ADD T2,LS.LB ;[1510]
MOVEM T2,LS.PT ;[1510]
JRST CPOPJ1 ;[1401] SKIP RETURN
> ;[1401] IFN TOPS20
;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.....) ;[2373] substitute . for non-sixbit characters
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 T1,TAB.PT(R) ;[1534] RENDER TAB.PT VIRTUAL
SUB T1,TAB.LB(R) ;[1534] TAKE OFF AREA BASE
ADD T1,TAB.LW(R) ;[1534] ADD IN WINDOW OFFSET
PUSH P,T1 ;[1534] AND KEEP IT
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
POP P,T1 ;[1534] GET VIRT TAB.PT
SUB T1,TAB.LW(R) ;[1534] AND FIX IN MEMORY AGAIN
ADD T1,TAB.LB(R) ;[1534] IN CASE THINGS MOVED
MOVEM T1,TAB.PT(R) ;[1534]
SPOP <P2,P1> ;[1216] RESTORE SACRED COWS
SETZM LS.PP ;[1172] RESTORE
IFE TOPS20,< ;[2247]
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
>;[2247] IFE TOPS20
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
IFE TOPS20,<
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
MOVE T2,UW.S0(R) ;[2202] OTHERWISE WE LOSE DATA
PUSHJ P,@TB.IN(R) ;[1172] DO THE I/O
> ;[1401] IFE TOPS20
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 T2,TAB.LB(P1) ;[2202] ALSO MAKE SURE DISK FILE IS OK
ADD T2,TAB.PT(P1) ;[2202] IN CASE NEVER OUTPUT BEFORE
JUMPE T2,.+4 ;[2202] FORGET IT IF NOTHING TO OUTPUT
ADD T2,TAB.LW(P1) ;[2202] NOTE WE'RE GETTING EXACT WORD CNT
MOVE T1,TAB.LW(P1) ;[2202] ALGOL 7 NEEDS .RBSIZ EXACT
PUSHJ P,@TB.OUT##(P1) ;SO USE XX.PT INSTEAD OF XX.AB
MOVE T2,TAB.AB(P1) ;[2202] NOW READ IN FRONT OF FILE
SUB T2,TAB.LB(P1) ;[2202] SO CAN SET UP 10??,,COUNT
SETZB T1,TAB.LW(P1) ;[2366] ?W.?S MUST BE UP TO DATE
MOVEM T2,TAB.UW(P1) ;[2202] 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 T3,ASYM ;YES, GET SYMBOL COUNT
HRLI T3,1044 ;AND BLOCK TYPE
JRST SAVSY1 ;AND CONTINUE
SAVSY0: MOVE T3,LSYM ;COUNT FOR LS AREA
HRLI T3,1700 ;AND BLOCK TYPE
SAVSY1: SUBI T3,1 ;WORDS FOLLOWING IS 1 LESS
MOVEM T3,@TAB.LB(P1) ;STORE COUNT WORD
SETZ T1, ;[2366] GET LOWER WINDOW (ALWAYS ZERO)
MOVE T2,TAB.UW(P1) ;[2366] AND UPPER WINDOW
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,TC ;[1415] USE TEMPORARY CHANNEL
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%SC ;HIDE DATA BLOCK HERE
MOVEM T1,IO.PTR+TC ;[1415] NOW USE IT
PUSHJ P,DVCHN.## ;PUT ADDRESS OF BLOCK IN T1
MOVSI T2,(Z TC,) ;[1415] RESET CHANNEL NUMBER IN I/O 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 TC,T1 ;[1415] WRITE IT
PJRST DVRLS.## ;PAGING NO LONGER HANDLED HERE
E01OES::
PUSH P,[TC] ;[1415]
.ERR. (ST,,V%L,L%W,S%W,OES)
POPJ P,
SUBTTL SET UP PROGRAM DATA VECTOR
; PDVSET - ROUTINE TO SET UP THE PROGRAM DATA VECTOR
; THE COPY IS INITIALIZED AND READ INTO THE PROGRAM IMAGE.
IFN TOPS20,<
PDVSET:
HRRZ P1,PRGPDV ;[2306] GET THE PDV BLOCK
HLRZ W3,.PVNAM(P1) ;[2306] GET THE LENGTH OF THE NAME
ADDI W3,PV.LEN ;[2306] ADD THE PDV BLOCK SIZE
ADDM W3,PDMPLN ;[2306] SAVE THE MAXIMUM PDV SIZE
SOS T1,PDMPLN ;[2306] MAX OFFSET IS ONE LESS
ADD T1,PDVADR ;[2306] ADD THE ADDRESS
CAMLE T1,PVPLIM ;[2306] TOO MUCH?
JRST E$$NPD ;[2306] YES, COMPLAIN
ADD W3,PDVADR ;[2306] ADD THE PDV ORIGIN
MOVE T1,W3 ;[2306] GET THE START OF THE MEMORY MAP
SKIPE NOPDMP ;[2306] NO DEFAULT MAP?
SKIPA T1,.PVMEM(P1) ;[2312] GET USER SUPPLIED VALUE
MOVEM T1,.PVMEM(P1) ;[2312] PUT IT IN THE PDV
MOVE T2,FXSBIT ;[2306] GET THE SECTION BITS
JUMPE T1,PDVST1 ;[2306] DON'T BOTHER IF ZERO
TLNN T1,-1 ;[2306] ANYTHING IN LEFT HALF?
HRLI T1,(IFIW) ;[2237] NO, USE IFIW FORMAT
TXNN T2,^-1B0 ;[2237] ANY NON-ZERO SECTIONS EXIST?
MOVEM T1,.PVMEM(P1) ;[2306] NO, PUT IFIW IN THE PDV
PDVST1: SKIPN T1,.PVSTR(P1) ;[2306] GET THE START/EXPORT ADDRESS, IF ANY
JRST PDVST2 ;[2306] NONE FOUND
TLNN T1,-1 ;[2306] ANYTHING IN LEFT HALF?
HRLI T1,(IFIW) ;[2306] NO, SET AS AN IFIW
TXNN T2,^-1B0 ;[2306] SECTION ZERO ONLY?
MOVEM T1,.PVSTR(P1) ;[2306] YES, STORE AS IFIW
PDVST2: SKIPN T1,.PVCST(P1) ;[2306] GET THE CUSTOMER BLOCK ADDRESS, IF ANY
JRST PDVST3 ;[2306] NONE FOUND
TLNN T1,-1 ;[2306] ANYTHING IN LEFT HALF?
HRLI T1,(IFIW) ;[2306] NO, SET AS AN IFIW
TXNN T2,^-1B0 ;[2306] SECTION ZERO ONLY?
MOVEM T1,.PVCST(P1) ;[2306] YES, STORE AS IFIW
PDVST3: SKIPN T1,.PVPRG(P1) ;[2306] GET THE PROGRAM BLOCK ADDRESS, IF ANY
JRST PDVST4 ;[2306] NONE FOUND
TLNN T1,-1 ;[2306] ANYTHING IN LEFT HALF?
HRLI T1,(IFIW) ;[2306] NO, SET AS AN IFIW
TXNN T2,^-1B0 ;[2306] SECTION ZERO ONLY?
MOVEM T1,.PVPRG(P1) ;[2306] YES, STORE AS IFIW
PDVST4: SKIPN T1,.PVSYM(P1) ;[2311] GET THE SYMBOL VECTOR ADDRESS, IF ANY
JRST PDVST5 ;[2311] NONE FOUND
TLNN T1,-1 ;[2311] ANYTHING IN LEFT HALF?
HRLI T1,(IFIW) ;[2311] NO, SET AS AN IFIW
TXNN T2,^-1B0 ;[2311] SECTION ZERO ONLY?
MOVEM T1,.PVSYM(P1) ;[2311] YES, STORE AS IFIW
PDVST5: MOVE T1,VERNUM ;[2311] SET VERSION NUMBER
SKIPN .PVVER(P1) ;[1423] UNLESS EXPLICITLY SET
MOVEM T1,.PVVER(P1) ;[1423]
MOVE T1,COMPDT ;[1423] SET COMPILATION TIME
MOVEM T1,.PVCTM(P1) ;[1423]
;[1423] WHEN COMPILERS BEGIN INCLUDING VERSION NUMBERS ADD HERE TWO LINES TO
;[1423] SET .PVCVR(P1) ALSO.
PUSHJ P,PDVGET ;[2306] GET THE USER'S PDV ADDRESSES IN MEMORY
PUSHJ P,PDVNAM ;[2306] STORE THE NAME
SKIPN NOPDMP ;[2306] USER SUPPLY MAP?
PUSHJ P,PDVMMP ;[2306] NO, BUILD THE MEMORY MAP
PJRST PDVSTO ;[2306] STORE THE PDV ITSELF
;[2306] Store the PDV name, and set the PDV pointer to it
;[2306] Return first address after name in W3
PDVNAM: HRRZ P1,PRGPDV ;[2306] GET THE PDV ADDRESS AGAIN
MOVE T1,PDVADR ;[2306] DESTINATION IN IMAGE MEMORY
ADDI T1,PV.LEN ;[2306] AT END OF PDV BLOCK
MOVE W3,T1 ;[2306] HOLD ONTO THIS ADDRESS
SUB T1,TAB.LW(R) ;[2306] SUBTRACT THE OFFSET
ADD T1,TAB.LB(R) ;[2306] FIXED IN LINK'S MEMORY
HLRZ T2,.PVNAM(P1) ;[2306] GET THE LENGTH OF THE NAME
ADDI T2,-1(T1) ;[2306] NAME END IN LINK'S MEMORY
HRL T1,.PVNAM(P1) ;[2306] BASE OF NAME
BLT T1,(T2) ;[2306] COPY IN THE NAME
HLRZ T2,.PVNAM(P1) ;[2306] GET THE SIZE OF THE NAME
HRRZ T1,.PVNAM(P1) ;[2306] AND THE ADDRESS
PUSHJ P,DY.RET## ;[2306] RETURN THE SPACE
MOVE T1,W3 ;[2306] GET BACK THE ADDRESS
ADD W3,T2 ;[2306] ADD LENGTH, POINT TO NEXT AFTER NAME
ADD T1,LL.S0(R) ;[2311] MAKE THE ADDRESS ABSOLUTE
MOVE T2,FXSBIT ;[2306] GET THE SECTION BITS
TXNN T2,^-1B0 ;[2306] ANY NON-ZERO SECTIONS EXIST?
HRLI T1,(IFIW) ;[2306] NO, USE IFIW FORMAT
MOVEM T1,.PVNAM(P1) ;[2306] SAVE THE POINTER
POPJ P, ;[2306] RETURN
;[2237] Build memory map. The map length must be recalculated, since it
;[2237] could have changed since we allocated space for the PDV, etc.
;[2335] Expects the address of the map in W3.
PDVMMP: SUB W3,TAB.LW(R) ;[2306] SUBTRACT THE OFFSET
ADD W3,TAB.LB(R) ;[2306] FIXED IN LINK'S MEMORY
PUSH P,R ;[2306] KEEP THE SEGMENT INFO
PUSH P,W3 ;[2306] AND KEEP THE FIRST WORD OF THE MAP
ADDI W3,1 ;[2306] THE FIRST WORD IS THE COUNT
PUSH P,[0] ;[2237] INIT. MEMORY MAP LENGTH COUNTER
MOVEI R,1 ;[2237] START WITH PSECT 1 (.LOW.)
SKIPE NOLOW ;[2247] NEED TO COUNT .LOW.?
MOVEI R,2 ;[2247] NO, START WITH SECOND PSECT
PDSLOP: PUSHJ P,PDVMAP ;[2237] GO FIND A CONTIGUOUS MEMORY BLOCK
JRST PDSTLN ;[2237] NO MORE, ALL DONE SCANNING PSECTS
PUSHJ P,MAKXFW ;[2237] CONVERT TO XFIW'S AND STORE ADDRS.
AOS (P) ;[2237] FOUND ANOTHER BLOCK, ACCOUNT FOR IT
JRST PDSLOP ;[2237] KEEP COUNTING MEMORY MAP ENTRIES
PDSTLN: JUMPE R,PDVNUL ;[2237] DON'T PUT NULL LAST PSECT INTO MAP
AOS (P) ;[2237] ACCOUNT FOR LAST CALL TO PDVMAP
PUSHJ P,MAKXFW ;[2237] CONVERT TO XFIW'S AND STORE ADDRS.
PDVNUL: POP P,T1 ;[2237] RESTORE # OF MEMORY MAP ENTRIES
IMULI T1,MM.SLN ;[2250] NUMBER OF WORDS PER SUB-TABLE
ADDI T1,1 ;[2237] ACCOUNT FOR LENGTH WORD (+MISC. WORDS)
;[2237] T1 contains memory map length now.
POP P,W3 ;[2306] GET THE POINTER TO THE FIRST WORD
MOVEM T1,.MMLEN(W3) ;[2306] STORE MAP LENGTH WORD IN MAP
POP P,R ;[2306] RESTORE THE SEGMENT
POPJ P, ;[2306] DONE
;[1423] VERIFY THAT THE NEEDED PAGES ARE CURRENTLY MAPPED IN
;[2306] USES T1-T4, P1, P2
PDVGET: MOVE P2,PVPSEG ;[1423] PICK UP RELOC COUNTER
MOVE R,RC.SG(P2) ;[2006] GET THE SEGMENT NUMBER
MOVN T1,LL.S0(R) ;[2016] GET THE SEGMENT BASE
ADDB T1,PDVADR ;[2016] T1 IS (OFFSET) UPPER BOUND
MOVE P2,T1 ;[1760] T2 IS UPPER BOUND
ADD P2,PDMPLN ;[2237] COMPUTE LAST ADDRESS
CAMLE P2,HC.S0(R) ;[2016] HIGHER THAN HIGHEST CODE?
MOVEM P2,HC.S0(R) ;[2016] YES, MAKE IT HIGHEST
CAMLE P2,HL.S0(R) ;[2016] HIGHER THAN HIGHEST LOADED?
MOVEM P2,HL.S0(R) ;[2016] YES, MAKE IT HIGHEST
SUB P2,TAB.LW(R) ;[2006] SUBTRACT OFFSET
ADD P2,TAB.LB(R) ;[2006] ADD LOWER BOUND
IORI P2,.PGSIZ ;[2006] SET TO END OF PAGE
CAML T1,TAB.LW(R) ;[2006] T1 ABOVE WINDOW BOTTOM?
CAMLE P2,TAB.AB(R) ;[2006] AND T2 BELOW WINDOW TOP?
TRNA ;[2237] NO, REMAP WINDOW
POPJ P, ;[2306] YES
;[1423] CHANGE THE WINDOW MAP TO INCLUDE THE ALLOCATED PDV STORAGE.
SKIPN T2,TAB.UW(R) ;[2202] CHECK FOR PAGING
JRST PDVSNP ;[2006] NOT PAGING - SPECIAL CASE
MOVE T1,TAB.LW(R) ;[2202] MAP OUT CURRENT WINDOW
PUSHJ P,@[LC.OUT##
HC.OUT##]-1(R) ;[1423] AND UNMAP PAGES
MOVE T1,PDVADR ;[2237] GET PDV ADDRESS
ANDCMI T1,.PGSIZ ;[2006] SET TO BEGINNING OF PAGE
MOVEM T1,TAB.LW(R) ;[2006] START AT BEGINNING OF PAGE
MOVE P2,PDVADR ;[2006] GET BACK THE PDV ADDRESS
ADD P2,PDMPLN ;[2237] COMPUTE LAST ADDRESS
IORI P2,.PGSIZ ;[2006] SET TO END OF PAGE
MOVE T2,T1 ;[2006] GET THE BASE
ADD T2,TAB.AB(R) ;[2006] ADD THE UPPER BOUND
SUB T2,TAB.LB(R) ;[2006] MINUS LOWER GIVES MAX SIZE
CAMLE T2,P2 ;[2006] MORE THAN NEEDED?
MOVE T2,P2 ;[2006] NO, USE SMALLER AMOUNT
MOVEM T2,TAB.UW(R) ;[2006] NEW UPPER WINDOW
SUB T2,TAB.LW(R) ;[2006] GET SIZE
ADD T2,TAB.LB(R) ;[2006] GET NEW UPPER BOUND
MOVEM T2,TAB.AB(R) ;[2006] REMEMBER THE NEW BOUND
MOVE T2,TAB.UW(R) ;[2202] GET UPPER WINDOW
PUSHJ P,@[LC.IN##
HC.IN##]-1(R) ;[1423] AND REMAP PAGES
CAMG P2,TAB.UW(R) ;[2006] WILL IT FIT?
POPJ P, ;[2306] YES
SUB P2,TAB.LW(R) ;[2006] REMOVE THE OFFSET
ADD P2,TAB.LB(R) ;[2006] FIND OUT WHERE IT SHOULD GO
PDVSNP: SUB P2,TAB.AB(R) ;[2006] GET THE DIFFERENCE
MOVE P1,R ;[2006] GET THE SEGMENT
PUSHJ P,LNKCOR## ;[2006] EXPAND MEMORY
JRST E$$MEF## ;[2006] NOT EXPECTED TO FAIL
POPJ P, ;[2306] DONE
;[2306] Here to store the actual PDV.
PDVSTO: MOVE T1,PDVADR ;[2006] DESTINATION IN IMAGE MEMORY
SUB T1,TAB.LW(R) ;[2006] SUBTRACT THE OFFSET
ADD T1,TAB.LB(R) ;[2006] FIXED IN LINK'S MEMORY
MOVEI T2,PV.LEN ;[2306] GET THE PDV LENGTH
ADDI T2,-1(T1) ;[2237] PDV END IN LINK'S MEMORY
HRL T1,PRGPDV ;[2006] BASE OF STORED PDV
BLT T1,(T2) ;[1423] COPY IN THE PDV
MOVE T1,LL.S0(R) ;[2016] GET BACK THE OFFSET
ADDM T1,PDVADR ;[2016] ADJUST THE PDV ADDRESS
POPJ P, ;[1423] RETURN
;SUBROUTINE TO CONVERT ADDRESSES TO XFIW'S FOR MEMORY MAP.
;
; CALL: W3/ PDV MEMORY MAP ADDR. TO STORE SUB-TABLE ENTRY INTO
;
; DATA AS RETURNED BY PDVMAP IS STORED IN PROPER FORMAT INTO MEMORY MAP.
; THIS SUBROUTINE ASSUMES THE MAP SUB-TABLES ARE 3 WORDS LONG.
;
; USED ACS: W1, AND T2 AND T3 IF THEY ARE CONVERTED TO IFIW'S
; W3 IS LEFT POINTING TO THE NEXT SUB-TABLE ADDR.
;
MAKXFW: MOVEI W1,MM.SLN ;[2250] INIT. TO R.O., DEFAULT LENGTH
TXNN T4,AT.RO ;[2237] IS BLOCK READ-ONLY?
TXO W1,PM%WR ;[2237] NO, SET "WRITABLE" BIT
MOVEM W1,.MMDAT(W3) ;[2245] STORE ATTRIBUTES,,SUB-TABLE LENGTH
MOVE W1,FXSBIT ;[2237] GET SECTION BITS
TXNE W1,^-1B0 ;[2237] ANY NON-ZERO SECTIONS?
JRST MAKEFW ;[2237] YES, USE EFIW FORMAT
HRLI T2,(IFIW) ;[2237] NO, USE IFIW FORMAT
HRLI T3,(IFIW) ;[2237]
MAKEFW: MOVEM T2,.MMLOW(W3) ;[2245] STORE BLOCK START ADDR.
MOVEM T3,.MMHGH(W3) ;[2245] STORE BLOCK END ADDR.
ADDI W3,MM.SLN ;[2250] STEP TO NEXT SUB-TABLE
POPJ P, ;[2237]
E$$NPD::.ERR. (MS,.EC,V%L,L%W,S%W,NPD,<No space for program data vector in psect >) ;[2306]
.ETC. (SBX,.EP,,,,PVPNAM) ;[2306]
> ;[1423] IFN TOPS20
;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:
IFN TOPS20,< ;[2366]
SKIPE NOJBDA ;[2247] /NOJOBDAT OR NON-ZERO SECTIONS?
POPJ P, ;[2247] YES
>;[2366] IFN TOPS20
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 PROGRAM LOAD IN NONZERO SECTIONS
IFN TOPS20,< ;[2202]
;[2247] Note that P1 points to the user's low segment JOBDAT
;[2247] and P2 points to the user's high segment JOBDAT.
SAVTST: SKIPE NOJBDA ;[2247] Suppressing JOBDAT?
JRST SSINI ;[2247] Yes, don't bother with this
HLRZ T1,.JBSA(P1) ;[2247] Setup right half of .JBCOR
SUBI T1,1 ;[2247] Point at last word used
IFN FTOVERLAY,< ;[2247]
SKIPL LNKMAX ;[2247] Seen any?
SKIPN JOB116 ;[2247] Yes, and want symbols?
CAIA ;[2247] No
HLRZ T1,.JBCOR(P1) ;[2247] Include symbols
> ;[2247] IFN FTOVERLAY
IOR. T1,.PGSIZ ;[2247] To highest loc required
HRRM T1,.JBCOR(P1) ;[2247] So save get works
PUSHJ P,HJBSET ;[2247] And update the vestigial jobdat area
;Now, step through RC.TB checking each PSECT's attributes. If any are
;read-only, set the page access accordingly. If two PSECTS with conflicting
;read/write attributes are on the same page, set the page read-only.
SSINI: MOVEI R,2 ;[2247] START WITH PSECT 2 (.LOW. ALWAYS R/W)
STACC1: CAMLE R,RC.NO ;[2206] YES, FINISHED CHECKING ALL PSECTS?
JRST STDONE ;[2206] YES, EXIT ROUTINE
MOVE W2,@RC.TB ;[2206] NO, GET NEXT PSECT TABLE ADDR.
MOVE T1,RC.AT(W2) ;[2206] GET PSECT ATTRIBUTES
TXNN T1,AT.RO ;[2206] READ-ONLY?
AOJA R,STACC1 ;[2206] NO, STEP TO NEXT PSECT
;A read-only psect has been found. Determine the start page and repeat
;count for setting all the psect pages to read/execute access. Assume
;all psect pages are contiguous, but allow non-existent pages within it.
MOVE T1,RC.IV(W2) ;[2206] YES, GET PSECT INITIAL VALUE
LSH T1,-^D9 ;[2206] TURN INTO PAGE NUMBER
MOVE T3,RC.HL(W2) ;[2206] GET HIGHEST PSECT ADDR. LOADED
SUBI T3,1 ;[2261] GO BACK TO LAST ADDR. ACTUALLY LOADED
LSH T3,-^D9 ;[2206] TURN INTO PAGE NUMBER
SUB T3,T1 ;[2261] MAKE REPEAT COUNT-1 IN T3
JUMPL T3,STACC4 ;[2265] DON'T SET ATTRIBUTES OF NULL PSECTS
HRL T1,LC.JF ;[2206] GET PROCESS DESIGNATOR
STACC2: RPACS% ;[2206] GET PAGE ACCESSIBILITY
ERNAM RPACS% ;[2261] CATCH FATAL ERRORS
TXNE T2,PA%PEX ;[2320] DOES PAGE EXIST?
JRST STACC5 ;[2320] YES, GO DEAL WITH IT
HRRZ P1,T1 ;[2350] GET THE PAGE NUMBER
LSH P1,^D9 ;[2350] MAKE IT AN ADDRESS
MOVE P2,RC.SG(W2) ;[2350] GET THE SEGMENT
PUSHJ P,QMAP ;[2350] MAP IT IN
SETZM (P1) ;[2350] TOUCH THE PAGE
STACC5: MOVX T2,PA%RD+PA%EX ;[2320] SET ACCESS TO READ AND EXECUTE
SPACS% ;[2206] DO IT
ERNAM SPACS% ;[2260] CATCH FATAL ERRORS
STACC3: ADDI T1,1 ;[2206] INCREMENT TO NEXT PAGE
SOJGE T3,STACC2 ;[2261] DECREMENT PAGE CTR. AND CONTINUE
STACC4: AOJA R,STACC1 ;[2265] DONE WITH THIS PSECT, GO TO NEXT ONE
;[2350] Routine to get an address into memory.
;[2350] On entry, P1 contains the address and P2 contains the segment
;[2350] (1=low, 2=high). On return, P1 points to the addressed word
;[2350] in memory.
QMAP: CAMLE P1,TAB.LW(P2) ;[2350] Is it already within the window?
CAML P1,TAB.UW(P2) ;[2350] (between lower and upper limits?)
CAIA ;[2350] No
JRST QMAP1 ;[2350] Yes, simple case
SPUSH <T1,T2,T3,T4> ;[2350] No, get some ACs
MOVE T1,TAB.LW(P2) ;[2350] Get the lower window
MOVE T2,TAB.UW(P2) ;[2350] And the upper
PUSHJ P,@[LC.OUT## ;[2350]
HC.OUT##]-1(P2) ;[2350] Unmap the window
MOVE T1,TAB.LB(P2) ;[2350] Get the area bottom
TRO T1,.IPM ;[2350] Need one page
MOVEM T1,TAB.AB(P2) ;[2350] Set it (always available)
MOVE T1,P1 ;[2350] Get the address
TRZ T1,.IPM ;[2350] Bottom of a page
MOVE T2,T1 ;[2350] Get it again
TRO T2,.IPM ;[2350] Top of page
MOVEM T1,TAB.LW(P2) ;[2350] Set the bottom of the window
MOVEM T2,TAB.UW(P2) ;[2350] And the top
PUSHJ P,@[LC.IN## ;[2350]
HC.IN##]-1(P2) ;[2350] Map the window
SPOP <T4,T3,T2,T1> ;[2350] Restore the ACs
QMAP1: SUB P1,TAB.LW(P2) ;[2350] Get the offset into the window
ADD P1,TAB.LB(P2) ;[2350] Add the base
POPJ P,
STDONE: ;[2206] ALL DONE, FALL THROUGH
; If there is a Program Data Vector, use the PDVOP% JSYS to
; declare its existence.
SETOM XJFLG ;[2277] Assume that extended JSYSes are OK
SKIPN T3,STADDR ;[2247] Address
JRST SSINIG ;[2247] None continue on
SKIPE T2,ENTLEN ;[2247] Entry vector length specified?
JRST SSINIA ;[2247] Yes, don't default it
MOVEI T2,1 ;[2247] Default one word vector
SKIPN NOJBDA ;[2247] Doing a JOBDAT?
MOVEI T2,(JRST) ;[2247] Yes, default TOPS-10 entry vector
SSINIA: MOVE T1,LC.JF ;[2247] Pick up fork handle
XSVEC% ;[1764] Set entry vector
ERCAL [TLNE T3,-1 ;[2247] A section zero address?
JRST [MOVX P2,'XSVEC%' ;[2274] No, a JSYS failure
PJRST E$$UMF##] ;[2274] Go report it
HRL T2,T3 ;[2247] Put args in T2
MOVSS T2 ;[2247] As length,,address
SEVEC% ;[2247] Try the old way
ERNAM (SEVEC%) ;[2247] Catch errors
SETZM XJFLG ;[2277] Extended JSYSes are not OK now
POPJ P,] ;[2247] Success
JRST SSINIB ;[2277] Don't check extended JSYSes again
SSINIG: MOVX T1,.FHSLF ;[2277] Point to LINK
XGVEC% ;[2277] Try fake extended JSYS
ERJMP [SETZM XJFLG ;[2277] Simple case failed, can't do
JRST SSINIB] ;[2277] extended JSYSes any more
SSINIB: SKIPN PRGPDV ;[2277] Is there a PDV?
JRST JBFORK ;[2247] No, don't set it up
MOVEI T1,.POADD ;[2247] Set up PDV
MOVEI T2,P1 ;[2247] Point to argument block
MOVEI P1,4 ;[2247] Four arguments
MOVE P2,LC.JF ;[2247] Get fork handle
MOVEI P3,1 ;[2247] One PDV to set
MOVEI P4,PDVADR ;[2247] Point to the address
PDVOP% ;[1425] [1423]
ERJMP .+1 ;[1427]
HRRZ T1,PRGPDV ;[1762] POINT TO PRIVATE COPY OF PDV
MOVEI T2,PV.LEN ;[2306] GET ITS LENGTH
PUSHJ P,DY.RET## ;[1762] RETURN IT
; At this point three courses are open:
; 1. Remove linker and leave program fork in place.
; 2. Remove linker and start program fork.
; 3. Remove linker, load and start debugger in the program fork.
;
; Set the name of the program fork to be the jobwide program name.
JBFORK: SKIPE IO.PTR+%VC ;[2247] .EXE requested?
PUSHJ P,SAVEXE ;[2247] Yes, do it
MAPDDT: SKIPN GETDDT ;[2277] NEED TO GET DDT?
JRST NODDT ;[2277] NO
SETZM UDDFLG ;[2277] YES, CLEAR "UDDT LOADED" FLAG
MOVEI T3,0 ;[2277] SAY DDT IS IN SECTION 0 FOR NOW
MOVE T1,LC.JF ;[2277] GET FORK JFN
GEVEC% ;[2277] GET LENGTH (DON'T NEED 30 BIT ADDR)
ERNAM GEVEC% ;[2277] CATCH ERRORS
MOVEM T2,EVLEN ;[2277] SAVE IN CASE NEEDED LATER FOR KS
SKIPN XJFLG ;[2277] ARE EXTENDED JSYSES ALLOWED?
JRST TRYUDD ;[2277] NO, ALWAYS USE UDDT
MOVE T4,FXSBIT ;[2277] YES, GET SECTION BITS
TXNE T4,^-1B0 ;[2277] ANY NON-ZERO SECTIONS EXIST?
JRST DOXDDT ;[2277] YES, USE EXTENDED DDT
HLRZS T2 ;[2277] NO, PUT LENGTH ONLY IN RIGHT HALF
CAIN T2,(JRST) ;[2277] TOPS-10 ENTRY VECTOR?
JRST TRYUDD ;[2277] YES, USE UDDT
DOXDDT: MOVX T1,GJ%OLD!GJ%SHT ;[2277] NO, USE XDDT FOR TOPS-20 ENTRY VECTOR
HRROI T2,[ASCIZ/SYS:XDDT.EXE/] ;[2277]
MOVEM T2,DDTASC ;[2314] SAVE ASCIZ DDT FILESPEC
GTJFN% ;[2277] FIND XDDT
ERJMP TRYUDD ;[2277] FAILED, TRY UDDT
MOVEM T1,DDTJFN ;[2277] SAVE JFN
SETCA T4,T4 ;[2277] FIND HIGHEST FREE SECTION FOR XDDT
TRZ T4,17 ;[2277] CLEAR BITS FOR SECTIONS 32-35
MOVN T3,T4 ;[2277] TURN THE BITS UPSIDE-DOWN
AND T3,T4 ;[2277] LEAVES A BIT POINTING TO 1ST FREE SEC.
JFFO T3,.+1 ;[2277] TURN INTO SECTION #
JUMPE T4,E$$NFS ;[2277] 0=NO FREE SECT. FOR XDDT (CAN'T USE 0)
HRL T3,T4 ;[2277] T3 HAS DESIRED (1ST FREE) SECTION # NOW
JRST DDTCOM ;[2277] JOIN COMMON CODE
TRYUDD: MOVX T1,GJ%OLD!GJ%SHT ;[2277] SHORT FORM, FILE MUST EXIST
HRROI T2,[ASCIZ/SYS:UDDT.EXE/] ;[2277]
MOVEM T2,DDTASC ;[2314] SAVE ASCIZ DDT FILESPEC
GTJFN% ;[2277] TRY TO FIND UDDT
ERJMP E$$DNA ;[2277] FAILED, DEBUGGER NOT AVAILABLE
MOVEM T1,DDTJFN ;[2277] SAVE JFN
SETOM UDDFLG ;[2277] FLAG THAT UDDT PTRS. MUST BE STUFFED
DDTCOM: MOVE T1,LC.JF ;[2277] GET PROGRAM FORK HANDLE
SKIPN XJFLG ;[2277] HAVE TO DO NON-EXTENDED CODE?
JRST GVEC0 ;[2277] YES, GO DO IT (FOR KS)
GOTXDD: SKIPN UDDFLG ;[2277] NO, UDDT OR XDDT?
PUSH P,T3 ;[2277] XDDT, SAVE DESIRED SECTION #
XGVEC% ;[2277] GET ENTRY VECTOR
ERNAM XGVEC% ;[2277] TRAP ERRORS
DMOVEM T2,EVLEN ;[2277] REMEMBER ENTRY VECTOR LENGTH & ADDR.
SKIPN UDDFLG ;[2277] UDDT OR XDDT?
POP P,T3 ;[2277] XDDT, RESTORE DDT'S SECTION #
HRR T1,DDTJFN ;[2277] GET DDT JFN
HRL T1,LC.JF ;[2277] GET FORK HANDLE
TXO T1,GT%NOV!GT%ARG ;[2277] DON'T OVERLAY, USE ARG BLOCK
MOVX T2,GT%BAS ;[2277] WE WANT TO SPECIFIY SECTION
MOVEM T2,GETBLK+.GFLAG ;[2277] SET FLAG BITS
HLRZM T3,GETBLK+.GBASE ;[2277] SPECIFY SECTION TO LOAD INTO
MOVEI T2,GETBLK ;[2277] POINT TO ARG BLOCK
GET% ;[2277] NOW BRING IN DDT
ERJMP E$$CLD ;[2277] CANNOT LOAD DDT
HLRZS T3 ;[2314] PUT SECTION # IN T3 RIGHT
MOVNS T3 ;[2314] AND MAKE IT NEGATIVE
MOVX T1,1B0 ;[2314] SECTION # BIT
LSH T1,(T3) ;[2314] SET APPROPRIATE BIT FOR THE SECTION #
IORM T1,FXSBIT ;[2314] DECLARE SECTION TO EXIST
MOVE T1,LC.JF ;[2277] GET PROGRAM FORK HANDLE
SKIPE DEBUGSW ;[2277] WANT TO EXECUTE DDT?
SKIPN EXECSW ;[2277] (ONLY WITH /DEBUG)
JRST NOEXDD ;[2277] NO
HRRZ T4,DEBUGSW ;[2363] WHICH DEBUGGER STARTS PROGRAM?
CAIE T4,DEB$DDT ;[2363] IS IT DDT?
JRST NOEXDD ;[2363] NO, /TEST:DDT ONLY
XGVEC% ;[2277] YES, PICKUP DDT'S ENTRY VECTOR
ERNAM XGVEC% ;[2277] CATCH ERRORS
MOVEM T3,STADDR ;[2277] START ADDR. IS DDT NOW
HRRM T3,EXECSW ;[2362] STORE IN BOTH PLACES
NOEXDD: DMOVE T2,EVLEN ;[2277] RESTORE VECTOR LENGTH & ADDR.
XSVEC% ;[2277] SET IT AGAIN
ERNAM XSVEC% ;[2277] TRAP ERRORS
JRST STUFDD ;[2277] ALL DONE, CONTINUE LINK
;Section 0 style load. This is necessary for KS processors which don't
;have the extended JSYSes. This code is identical in function to the
;above code.
GVEC0: HRR T1,DDTJFN ;[2277] GET DDT JFN
HRL T1,LC.JF ;[2277] GET FORK HANDLE
TXO T1,GT%NOV ;[2277] DON'T OVERLAY
GET% ;[2277] NOW BRING IN DDT
ERJMP E$$CLD ;[2277] CANNOT LOAD DDT
MOVX T1,1B0 ;[2314] SAY THAT SECTION 0 NOW EXISTS
IORM T1,FXSBIT ;[2314] DO IT
MOVE T1,LC.JF ;[2277] GET PROGRAM FORK HANDLE
SKIPE DEBUGSW ;[2277] WANT TO EXECUTE DDT?
SKIPN EXECSW ;[2277] (ONLY WITH /DEBUG)
JRST NOEXS0 ;[2277] NO
GEVEC% ;[2277] YES, GET DDT'S START ADDR.
ERNAM GEVEC% ;[2277] CATCH ERRORS
HRRZM T2,STADDR ;[2277] START PROGRAM AT 0,,ADDR
HRRM T2,EXECSW ;[2362] STORE IT IN BOTH PLACES
NOEXS0: MOVE T2,EVLEN ;[2277] RECOVER OLD ENTRY VECTOR
SEVEC% ;[2277] SET IT (DDT CHANGED IT WHEN GET%'ING)
ERNAM SEVEC% ;[2277] CATCH ERRORS
STUFDD: SKIPN UDDFLG ;[2277] NEED TO STUFF UDDT SYMBOL TABLE PTRS?
JRST NODDT ;[2277] NO, SKIP THIS
MOVEI P2,LC.IX ;[2352] DDT IS ALWAYS IN THE LOW SEGMENT
HLLZ P1,T3 ;[2352] GET DDT'S SECTION #
HRRI P1,DDTSA+1 ;[2352] NEED WORD AFTER DDT START ADDRESS
PUSHJ P,QMAP ;[2352] MAP IT
MOVE P1,(P1) ;[2352] GET SYMBOL TABLE POINTER ADDR
HLL P1,T3 ;[2352] GET THE SECTION NUMBER
PUSH P,P1 ;[2352] REMEMBER THIS ADDRESS
PUSHJ P,QMAP ;[2352] MAP IT IN
MOVE T1,JOB116 ;[2352] GET DEFINED SYM TABLE PTR
MOVEM T1,(P1) ;[2352] STUFF DDT'S SYMBOL TABLE PTR
ERCAL E$$CSP ;[2277] CANNOT SET UDDT'S POINTERS?
POP P,P1 ;[2352] GET ADDRESS BACK
ADDI P1,1 ;[2352] NEXT ADDRESS FOR UNDEFINED
PUSHJ P,QMAP ;[2352] MAP IT IN
MOVE T1,JOB117 ;[2352] GET UNDEFINED SYM TABLE PTR
MOVEM T1,(P1) ;[2352] STUFF DDT'S SYMBOL TABLE PTR
ERCAL E$$CSP ;[2277] CANNOT SET UDDT'S POINTERS?
NODDT: PUSHJ P,ENDEXE ;[2277] Finish up, close log file
SETZM F.EDIT ;[2247] Keep LNKSCN happy
SKIPN EXECSW ;[2247] execute preempts run switch
SKIPN N.ZER## ;[2247] Run switch pending?
CAIA ;[2247] No
JRST LNKSCN## ;[2247] Yes, go do the run switch
;[2247] Here to build the SPLFK% Argument block
MOVEI T1,6 ;[2247] Six arguments
MOVEM T1,ARGBLK+.SFLEN ;[2247] Store in arg block
MOVEI T1,.SFUNS ;[2247] Get function code
MOVEM T1,ARGBLK+.SFCOD ;[2247] Store in arg block
MOVE T1,LC.JF ;[2247] Get the fork handle
MOVEM T1,ARGBLK+.SFUIN ;[2247] Store in arg block
SETZM ARGBLK+.SFUA1 ;[2247] No PC flags
MOVE T1,STADDR ;[2247] Get the start address
HRR T1,EXECSW ;[2355] Debugger may change address
MOVEM T1,ARGBLK+.SFUA2 ;[2247] Store in arg block
PUSHJ P,DOXMES ;[2247] Type the execute message
MOVX T1,SF%ADR ;[2247] Get the "start" bit
SKIPN EXECSW ;[2247] Want to execute this?
SETZ T1, ;[2247] No
MOVEM T1,ARGBLK+.SFUFL ;[2247] Set the flag
MOVEI T1,[KILPAT] ;[2347] Tell PA1050 To go away
COMPT. T1, ;[1460]
JFCL ;[1460] Error return not possible
SKIPE T1,RUNAME ;[1425] Get program name
JRST .+3 ;[1425] Got a name
SKIPN T1,SSNAME ;[1425] If not try save file name
MOVE T1,LODNAM ;[1425] Use default if not set
;**; Insert 2 lines at NODDT+35
TLNN T1,770000 ;[2404] Is it a long name?
MOVE T1,(T1) ;[2404] Yes - use 1st 6 characters
SETNM% ;[1425] Set it
MOVX T1,<SF%EXT!ARGBLK> ;[2247] Get the splice fork arg
SPLFK% ;[2247] Go for the user's program
ERJMP JBNONE ;[2247] Failure!
;[2247] The splice fork failed, probably because the monitor
;[2247] does not have the extended code. Tell the user, and
;[2247] Save the program if it has not already been. Then get
;[2247] and optionally start the user's program.
;[2247] Since this code is not expected to be used, it was
;[2247] designed to be small rather than efficient. In
;[2247] particular, the routine it calls to get the JFN on
;[2247] the .EXE file also opens the file, which them must
;[2247] be closed. This is done to prevent having to write
;[2247] a new routine which would get the JFN without opening
;[2247] the file.
JBNONE: MOVEI T1,DC ;[2357] Set up channel
MOVEM T1,IO.CHN ;[2357] For EXE file
SKIPE R,IO.PTR+%VC ;[2357] .EXE requested?
JRST E$$SPF ;[2247] Yes
MOVEI T2,F.LEN ;[2247] Set up file spec
PUSHJ P,DY.GET## ;[2247] As though we had seen /SAVE
MOVE P1,T1 ;[2247] Store pointer to "scan" block
HLLZ T2,JOBNUM ;[2247] Sixbit jobnumber
HRRI T2,'LNK' ;[2247] Rest of name
MOVEM T2,F.NAME(T1) ;[2247] In the scan block
MOVEM T2,SSNAME ;[2247] Here also
MOVSI T2,'EXE' ;[2247] Get extension
MOVEM T2,F.EXT(T1) ;[2247] Store it in scan block
MOVEM T2,SSEXT ;[2247] For save file
MOVSI T2,'DSK' ;[2247] Make sure it goes on DSK
MOVEM T2,F.DEV(T1) ;[2247] Incase defaults screwed up
PUSHJ P,DVOUT.## ;[2247] Setup data block
%VC,,.IODPR ;[2247] On fake chan in dump mode
SETZ R, ;[2247] In case DVOUT. set it
E$$SPF::.ERR. (MS,.EC,V%L,L%F,S%W,SPF,<Splice fork failed>) ;[2247]
.ETC. (XCT,.EC,,,,<[SKIPE R]>) ;[2247] Already had save file?
.ETC. (JMP,.EC,,,,JBNON1) ;[2247] Yes, don't say "saving on..."
.ETC. (STR,.EC,,,,,<, saving on file >) ;[2247]
.ETC. (FSP,.EC,,,,%VC) ;[2247] Type the filespec
JBNON1: .ETC. (NOP) ;[2247] End
;Remove DDT from the user's core image before creating the .EXE file.
SETZM UDPTRS ;[2314] CLEAR "POKE UDDT IN SEC. 0" FLAG
SKIPN GETDDT ;[2314] DID USER HAVE DDT IN MEMORY?
JRST JBNON3 ;[2314] NO
SETO T1, ;[2314] YES, PREPARE TO DELETE PAGES/SECTION
SKIPE UDDFLG ;[2314] XDDT (ITS OWN SECTION) OR UDDT?
JRST JBNONU ;[2314] UDDT, GO UNMAP JUST UDDT'S PAGES
HRL T2,LC.JF ;[2314] XDDT, GET FORK HANDLE
HRR T2,GETBLK+.GBASE ;[2314] GET SECTION NUMBER
MOVEI T3,1 ;[2314] DELETE 1 SECTION
SMAP% ;[2314] BLOW AWAY XDDT AND ITS SECTION
ERNAM SMAP% ;[2314] CATCH ERRORS
JRST JBNON3 ;[2314] DONE
JBNONU: HRR T2,GETBLK+.GBASE ;[2314] GET SECTION #
LSH T2,^D9 ;[2314] MOVE IT OVER
TXO T2,DDTPAG ;[2314] BEGIN UNMAPPING UDDT AT THIS PAGE
HRL T2,LC.JF ;[2314] GET FORK HANDLE
MOVX T3,PM%CNT+1000-DDTPAG ;[2314] # OF PAGES TO REMOVE FROM PROCESS
PMAP% ;[2314] BLOW AWAY UDDT
ERNAM PMAP% ;[2314] CATCH ERRORS
JBNON3: SKIPN R ;[2314] ALREADY GOT AN .EXE FILE?
PUSHJ P,SAVEXE ;[2314] NO, GO MAKE ONE
SKIPN GETDDT ;[2314] YES, NEED TO LOAD A DDT?
JRST JBNON2 ;[2314] NO
SKIPN UDDFLG ;[2314] YES, UDDT OR XDDT?
JRST JBNONX ;[2314] XDDT, GO DO IT
SKIPE T3,GETBLK+.GBASE ;[2314] UDDT, GET SECTION # TO LOAD IT INTO
JRST JBNONX ;[2314] NON-ZERO, NO CONFLICT WITH LINK & DDT
MOVX T1,<.FHSLF,,770> ;[2314] PREPARE TO SEE IF WE'RE DDT'ING LINK
RPACS% ;[2314] SEE IF UDDT'S FIRST PAGE IS THERE
ERNAM RPACS% ;[2314] CATCH ERRORS
TXNN T2,PA%PEX ;[2314] DOES PAGE EXIST?
JRST JBNONX ;[2314] NO, NO CONFLICT POSSIBLE
MOVE T2,770000 ;[2314] YES, GET FIRST WORD OF PAGE 770
CAMN T2,[JRST 770002] ;[2314] DOES IT LOOK LIKE UDDT?
JRST JBNON4 ;[2314] YES, SPECIAL CASE - DON'T GET% UDDT
JBNONX: MOVX T1,GJ%OLD!GJ%SHT ;[2314] GET GTJFN% BITS
MOVE T2,DDTASC ;[2314] GET ASCIZ DDT FILESPEC
GTJFN% ;[2314] FIND X/UDDT (WE FOUND IT BEFORE)
ERNAM GTJFN% ;[2314] THIS WORKED BEFORE, SHOULD'VE HERE TOO!
HRLI T1,.FHSLF ;[2314] GET FORK HANDLE (LINK)
SKIPN XJFLG ;[2314] EXTENDED JSYSES ALLOWED?
JRST JBNONZ ;[2314] NO, DO IT THE SIMPLE WAY
TXO T1,GT%NOV!GT%ARG ;[2314] YES, DON'T OVERLAY, USE ARG BLOCK
MOVEI T2,GETBLK ;[2314] POINT TO ARG BLOCK
GET% ;[2314] NOW BRING X/UDDT INTO PROPER SECTION
ERNAM GET% ;[2314] THIS WORKED BEFORE, SHOULD'VE HERE TOO!
JRST JBNON2 ;[2314] DDT LOADED, START ADDRS. ALREADY SET
;Here when DDT is loaded with LINK and we want UDDT in section 0.
JBNON4: DMOVE T1,JOB116 ;[2314] GET SYMBOL TABLE PTRS.
DMOVEM T1,UDPTRS ;[2314] SAVE THEM AND REMEMBER TO POKE LATER
JRST JBNON2 ;[2314]
;Here for non-extended (KS) case.
JBNONZ: TXO T1,GT%NOV ;[2314] DON'T OVERLAY
GET% ;[2314] NOW BRING UDDT INTO SECTION 0
ERNAM GET% ;[2314] THIS WORKED BEFORE, SHOULD'VE HERE TOO!
JBNON2: MOVE T1,LC.JF ;[2314] Get the inferior
KFORK% ;[2247] Kill it
ERNAM (KFORK%) ;[2274] Should not fail
PUSHJ P,DVLKP.## ;[2247] Open the exe file
PUSHJ P,E$$EOI ;[2357] Unexpected failure
MOVX T1,CO%NRJ ;[2247] Don't want to lose the JFN
HRR T1,DC.JF ;[2247] Get the JFN
CLOSF% ;[2247] Close it
ERNAM (CLOSF%) ;[2274] Should not fail
MOVE T1,[R%ACS,,ACS] ;[2247] Copy run code to writable place
BLT T1,ACS+R%17 ;[2247]
MOVE T1,DC.JF ;[2247] Get the EXE file JFN
HRRM T1,ACS+R%16 ;[2247] Put JFN in get JSYS argument
MOVE T1,STADDR ;[2247] Get the start address
HRR T1,EXECSW ;[2360] Debugger may change address
SKIPE EXECSW ;[2247] Want to execute?
MOVEM T1,ACS+R%12 ;[2247] Yes, store address
MOVE T2,[JRST @R%12] ;[2247] Get the short JRST
TLNN T1,-1 ;[2247] Doing extended addressing?
MOVEM T2,ACS+R%10 ;[2247] No, use JRST (in case KS10)
MOVX T1,.POREM ;[2314] PREPARE TO REMOVE LINK'S PDV ADDR.
MOVEI T2,[.POADE+1 ;[2353] LENGTH OF ARG BLOCK
.FHSLF ;[2353] DO IT TO OUR FORK (LINK)
0 ;[2353] NO RETURNED VALUES EXPECTED
0 ;[2353] NO BLOCK FOR RETURNED VALUES
20 ;[2353] START ADDR. TO REMOVE PDV ADDR. FROM
<DDTPAG*1000>-1] ;[2353] END ADDR. IS JUST BELOW UDDT
PDVOP% ;[2314] REMOVE LINK'S PDV
ERNAM PDVOP% ;[2314] CATCH ERRORS
MOVEI T1,.FHSLF ;[2314] POINT TO OUT PROCESS
SETO T2, ;[2314] PREPARE TO DISABLE ALL PSI CHANNELS
DIC% ;[2314] TO PREVENT PROBLEMS WHEN ZEROING
ERNAM DIC% ;[2314] TABLE ADDRESSES OUT
MOVEI T2,0 ;[2314] PREPARE TO CLEAR PSI TABLE ADDRS.
SIR% ;[2314] DO IT (RESET% DOESN'T CLEAR ADDRS.)
ERNAM SIR% ;[2314] CATCH ERRORS
DMOVE T1,UDPTRS ;[2314] GET FLAG/PTRS. TO POKE UDDT
SKIPE T1 ;[2314] HAVE TO POKE SECTION 0 UDDT?
DMOVEM T1,@770001 ;[2314] YES, DO IT (CAN'T SEE LINK SYMS. NOW)
MOVE R%17,[ACS,,R%0] ;[2247] Copy poked code to ACS
BLT R%17,R%17 ;[2247] ..
JRST R%4 ;[2247] Go start program
;[2247] Final suicide code for running a program
R%ACS: PHASE 0 ;[2247] Get into the ACS
R%0:! 0 ;[2247] Unused
R%1:! -1 ;[2247] PMAP% arguments to unmap all of memory
R%2:! .FHSLF,,0 ;[2247] ..
R%3:! PM%CNT+DDTPAG ;[2314] Don't unmap DDT (if debugging LINK)
R%4:! PMAP% ;[2247] Beginning of suicide code--unmap pages
R%5:! MOVE R%1,R%16 ;[2247] Load GET% argument
R%6:! GET% ;[2247] Bring in program
R%7:! RESET% ;[2247] Do RESET JSYS to clear PSI, etc.
R%10:! XJRSTF R%11 ;[2247] Start the program
R%11:! 0 ;[2247] PC Flags
R%12:! R%13 ;[2247] Where to start program
R%13:! HALTF% ;[2247] Start of program if no /EXECUTE
R%14:! JRST R%13 ;[2247] Not a continuable halt
R%15:! 0 ;[2247] Unused
R%16:! .FHSLF,,.-. ;[2247] Poked with GET% JSYS argument
R%17:! 0 ;[2247] Unused
DEPHASE
SAVEXE:
E$$CSF::.ERR. (MS,0,V%L,L%I,S%I,CSF,<Creating saved file>) ;[2247]
PUSHJ P,EXEINI ;[2247] Get a JFN
MOVE T1,T3 ;[2247] Fetch spare JFN
HRL T1,LC.JF ;[2247] Get the fork handle
MOVE T3,HL.S1 ;[2364] Get the highest loaded
IORI T3,777777 ;[2274] Set to top of section
ADDI T3,1 ;[2274] Number of words to transfer
LSH T3,-^D9 ;[2274] Convert it to pages
MOVNS T3 ;[2274] Negate it
MOVX T2,<SS%UCA!SS%CPY!SS%RD!SS%WR!SS%EXE!SS%EPN> ;[2317] Get flags
HRL T2,T3 ;[2274] Save all pages
SETZ T3, ;[2247] Starting with page zero
SSAVE% ;Save the pages
ERJMP E$$EOE ;[2247] Too bad
HRRZ T1,DC.JF ;[2346] Get other JFN on exe file
DVCHR% ;[2346] Get the device charisterics
ERNAM (DVCHR%) ;[2346] Very unhealthy device
LDB T2,[POINTR T2,DV%TYP] ;[2346] Get the device type
CAIE T2,.DVDSK ;[2346] Is it a disk?
JRST [HRRZ T1,DC.JF ;[2346] No, get the JFN again
RLJFN% ;[2346] Give it back
ERNAM (RLJFN%) ;[2346] Unexpected problem
SETZM IO.PTR+%VC ;[2346] Remember no usable EXE
POPJ P,] ;[2346] Return
HRRZ T1,DC.JF ;[2346] Get JFN on exe file again
HRL T1,LC.JF ;[2346] And the fork handle
GET% ;[2247] Map them back in
ERNAM (GET%) ;[2247] Unexpected failure
POPJ P, ;[2247] File saved
;[2247] Here to make the final decision about execution, and to type
;[2247] the appropriate messages. Don't execute the program if there
;[2247] are errors unless /DEBUG is set.
DOXMES: SKIPN STADDR ;[2247] Is there a start addr?
PUSHJ P,E02NSA ;[2247] No
SKIPN EXECSW ;[2247] Start it?
POPJ P, ;[2247] No
SKIPE ERRNO ;[2247] Don't run if errors
SKIPGE DEBUGSW ;[2247] Unless debugging
PJRST EXEMES ;[2247] No, announce execution
E02DLT::.ERR. (MS,0,V%L,L%F,S%W,DLT,<Execution deleted>) ;[2247]
SETZM EXECSW ;[2247] Don't execute
POPJ P, ;[2247] Return
E02NSA::.ERR. (MS,0,V%L,L%F,S%I,NSA,<No start address>) ;[2247]
AOS ERRNO ;[2247] Don't execute
POPJ P, ;[2247] Return
> ;[2202] IFN TOPS20
IFE TOPS20,< ;[2247]
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
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
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
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)
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
PUSH P,P1 ;[1261] Save pointer to users JOBDAT area
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)
POP P,P1 ;[1261] RESTORE USERS JOBDAT POINTER
; JRST JBSAVE ;[1146] FALL THROUGH TO WRITE .EXE FILE
SUBTTL GENERATE .EXE (OR .XPN/.SHR/.HGH/.LOW) FILE
>;[2247] IFE TOPS20
;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
IFE TOPS20,< ;[2247]
;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
SUBI T1,1 ;[1317] POINT AT LAST WORD USED
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
MOVE T1,LW.S2 ;[2202] LOWER WINDOW
MOVE T2,UW.S2 ;[2202] UPPER WINDOW
PUSHJ P,HC.OUT## ;OUTPUT LAST BLOCKS
SETZB T1,LW.S2 ;[2202] START BACK AT ZERO
MOVEI T2,.IPM ;[2202] 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
MOVSI T1,'SAV' ;EXT IS NOW SAV 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
MOVE T1,LW.S1 ;[2202] GET LOWER WINDOW
MOVE T2,UW.S1 ;[2202] 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
SETZB T1,LW.S1 ;START AT LOWEST LOCATION
MOVE T2,DY.AB ;HIGHEST LOC WE CAN NOT USE
MOVEM T2,DY.UB ;TELL LNKCOR ABOUT IT
ADDI T2,1
MOVEM T2,LC.LB ;BACKUP IF WE CAN
SKIPN T2,LS.LB ;CAN ONLY USE TO BOTTOM OF LS
;AREA IF IT'S STILL THERE
SKIPA T2,.JBREL ;IF IT'S NOT, CAN USE ALL OF CORE
SUBI T2,1 ;LAST TO USE IS START OF LS - 1
MOVEM T2,LC.UB ;RESET POINTERS
MOVEM T2,LC.AB ;FOR CONSISTENCY
SUB T2,LC.LB ;MINUS WHAT WE ALREADY HAVE
MOVEM T2,UW.S1 ;ASSUME IT WON'T FIT
CAMGE T2,HC.S1 ;ENOUGH EXTRA FOR ALL OF FILE?
JRST JBSAV1 ;NO, DO IT THE HARD WAY
MOVE T2,HC.S1 ;WE NEED ONLY THIS MUCH
IORI T2,.IPM ;ROUNDED UP
MOVE T3,T2 ;CAN ALSO CUT BACK LC.AB
ADD T3,LC.LB ;TO WHAT WE ACTUALLY NEED
MOVEM T3,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 ;[2366] 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,
>;[2247] IFE TOPS20
IFN FTOVERLAY,<
;HERE TO DELETE LS FILE
LS.DLT: SETZM PAG.LS
MOVEI T1,SC
PUSHJ P,DVDEL.##
JFCL
POPJ P,
>
IFE TOPS20,<
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
SETZ T1, ;[2202] YES, START AT THE BEGINNING
MOVEI T2,.DBM ;[2202] NOW WRITE IT BACK
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
SETZ T1, ;[2202] START AT THE BEGINNING
MOVEI T2,.DBM ;[2202] NOW WRITE IT BACK
PJRST HC.OUT## ;WRITE IT BACK
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,
>;[2247] IFE TOPS20
IFN FTEXE,<
IFE TOPS20,< ;[2247]
;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 T2,UW.S2 ;[2202] IS IT PAGED?
JRST JBEXEH ;NO,
MOVE T1,LW.S2 ;[2202] OUTPUT WORD
PUSHJ P,HC.OUT ;MAKE SURE IT GET OUT
MOVE T2,UW.S2 ;[2202]
SUB T2,LW.S2 ;[2202] GET LENGTH
MOVEM T2,UW.S2 ;[2202] RESET IT
SETZB T1,LW.S2 ;[2202] BACK TO FRONT OF FILE
PUSHJ P,HC.IN ;READ IT BACK
JBEXEH: PUSHJ P,HJBSET ;[2366] SETUP VESTIGIAL JOBDAT
SKIPE JBHPTR ;WAS 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: MOVE T1,LW.S1 ;[2202] WRITE ENTIRE LC AREA
MOVE T2,UW.S1 ;[2202] 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
MOVEI T1,-1000(P4) ;[2202] LOWEST LOCATION TO READ
MOVEM T1,LW.S1 ;[2202] UPDATE LOWER WINDOW
HRRI T2,-1(P4) ;[2202] HIGHEST LOCATION TO READ
MOVEM T2,UW.S1 ;[2202] UPDATE UPPER WINDOW
PUSHJ P,LC.IN## ;[2202] 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 T2,LW.LS ;[2202] WRITE CURRENT LS WINDOW
ADD T2,LS.AB ;[2202] SO SYMBOLS WON'T BE LOST
SUB T2,LS.LB ;[2202] T1 HAS NEW UPPER BOUND
MOVEM T2,UW.LS ;[2202] STORE IN CASE IT WAS -1
MOVE T1,LW.LS ;[2202] 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 T1,LW.LS ;[2202] WANT FIRST PAGE OF SYMBOLS
MOVEI T2,777 ;[2202] FROM 0 TO 777
MOVEM T2,UW.LS ;[2202] 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]
MOVE T1,LW.S1 ;[2202] GET LOWER WINDOW
MOVE T2,UW.S1 ;[2202] 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 T2,HC.LB ;[2202] YES, HIGH SEG STILL EXISTS
SUBI T2,1 ;[2202] TOP OF LOW
MOVEM T2,LC.UB ;[2202] RESTORE POINTERS
JRST JBEXER ;GO MAKE PAGE BOUND AND CHECK ROOM
JBEXEA: SKIPN T2,LS.LB ;[2202] TO BOTTOM OF LS, IF IT'S THERE
SKIPA T2,.JBREL ;[2202] IF NOT, ALL OF CORE
SUBI T2,1
MOVEM T2,LC.UB ;[2202] RESERVE
JBEXER: SUB T2,LC.LB ;[2202] MAKE SURE
SUBI T2,777 ;[2202] WE ARE ON A PAGE BOUND
IORI T2,777 ;[2202] ...
ADD T2,LC.LB ;[2202] ADD IN BASE
MOVEM T2,LC.AB ;[2202] FOR CONSISTANCY
SUB T2,LC.LB ;[2202] MINUS WHAT WE ALREADY HAVE
MOVE T3,HC.S1 ;[762]
SUB T3,LOWLOC ;[762] GET ACTUALLY NEEDED LENGTH
IORI T3,777 ;[762]
MOVE T1,LW.S1 ;[2202] GET THE LOWER WINDOW BOUND
CAMGE T2,T3 ;[2202] COMPARE WHAT WE HAVE AND WHAT WE NEED
JRST [ADD T2,LW.S1 ;[2202] WE HAVE LESS THAN WE NEED
MOVEM T2,UW.S1 ;[2202] UPDATE UPPER WINDOW VALUE
PUSHJ P,LC.IN## ;[2202] READ IN AS MUCH AS WE CAN
JRST JBEXE1]
MOVE T2,T3 ;[2202] WE HAVE MORE THAN WE NEED
ADD T2,LW.S1 ;[2202] UPDATE UPPER WINDOW VALUE
MOVEM T2,UW.S1 ;[2202]
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?
SKIPN JOBPTR ;[2043] DON'T BLT .JBDA IF ALREADY IN PLACE
CAIA ;[2043] DON'T GO TO BLTJDA IF JOBPTR IS ZERO
;[2043] OR PAGE 0 IS IN CORE
PUSHJ P,BLTJDA ;BLT .JBDA TO LOW SEG
; JRST EXEINI
>;[2247] IFE TOPS20
;HERE TO OPEN EXE FILE
;[2247] Note that on TOPS-20 the file is not opened, and two JFNs are
;[2247] returned, one in DC.JF and the other in T3.
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
IFE TOPS20,< ;[2247]
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
>;[2247] IFE TOPS20
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
IFN TOPS20,< ;[2202]
POPJ P, ;[1450] RETURN
E$$ECE::PUSH P,IO.CHN ;[2301] GIVE OFFENDING CHANNEL TO LNKLOG
.ERR. (LRE,.EC,V%L,L%F,S%F,ECE,<Error creating EXE file>) ;[2301]
.ETC. (NLN,.EC) ;[2301] CRLF
.ETC. (STR,,,,,ERRJSY) ;[2301] TYPE ERROR TEXT
> ;[2202] IFN TOPS20
IFE TOPS20,< ;[2202]
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 JOBPTR ;[1532] 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,IO.CHN ;[2052] 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
MOVE T1,P3 ;[2356] 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
TLNE P2,777000 ;[2356] OVERFLOW THE COUNT FIELD (1000 PAGES)?
JRST XCMLWD ;[2356] NO, OK
TLO P2,777000 ;[2356] YES, SET COUNT TO 1000 PAGES
TXO P4,ZEROF ;[2356] SET FLAG SO PAGE NUMBER WILL GO OUT
PUSHJ P,XCMPRD ;[2356] WRITE A DIRECTORY ENTRY
TXZ P4,ZEROF ;[2356] RESET FLAG
HRRZI P2,1000(P2) ;[2356] RESET COUNT, ACCOUNT FOR 1000 PAGES
ADDI P1,1000 ;[2356] ACCOUNT FOR 1000 PAGES IN FILE
XCMLWD: JUMPL W2,XCMADP ;[2356] ADVANCE IF IOWD HAS NOT OVERFLOWED
SUB W2,[-1000,,0] ;[1314] REDUCE IOWD
OUT DC,W2 ;[1314] WRITE 177 PAGES OF EXE FILE
MOVEI W2,-1(P3) ;[1314] OFFSET INTO SEGMENT - 1
SUB W2,LW.S0(R) ;[1314] OFFSET INTO CURRENT WINDOW
ADD W2,TAB.LB(R) ;[1314] ADDRESS OF PAGE IN LINK'S VAS
HRLI W2,-1000 ;[1314] FINISH IOWD FOR ONE PAGE
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
MOVE W2,P3 ;[2356] 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
TLNE P2,777000 ;[2356] OVERFLOW THE COUNT FIELD (1000 PAGES)?
JRST XCMADP ;[2356] NO, ADVANCE TO THE NEXT PAGE
TLO P2,777000 ;[2356] YES, SET COUNT TO 1000 PAGES
TXZ P4,ZEROF ;[2356] TURN OFF ZEROF SO PAGE WILL BE ZEROED
PUSHJ P,XCMPRD ;[2356] WRITE A DIRECTORY ENTRY
TXO P4,ZEROF ;[2356] SET THE FLAG AGAIN
HRRZI P2,1000(P2) ;[2356] RESET COUNT, ACCOUNT FOR 1000 PAGES
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 T2,P3 ;[2202] VIRTUAL ADDRESS OF 1ST WORD TO READ
ADD T2,TAB.AB(R) ;[2202] CONVERT TO VIRTUAL ADDRESS OF LAST WORD
SUB T2,TAB.LB(R) ;[2202] BY ADDING SIZE OF LC/HC AREA
MOVEM T2,UW.S0(R) ;[2202] STORE NEW UPPER WINDOW BOUND
CAMGE T2,HC.S0(R) ;[2202] DOES THE AREA CONTAIN THAT MUCH?
JRST XCMRED ;[1132] YES, JUST GO READ IT IN
SUB T2,HC.S0(R) ;[2202] NO, FIGURE OUT HOW MUCH EXTRA WE HAVE
ADDI T2,1 ;[2202] SUBTRACTED ONE TOO MUCH, HC IS FF FORMAT
ANDCMI T2,.IPM ;[2202] PUT ON THE PAGE BOUND
MOVN T2,T2 ;[2202] DECREMENT THE AB OF THE AREA
ADDM T2,TAB.AB(R) ;[2202] SO EXTRA SPACE IS AVAILABLE TO OTHERS
ADDM T2,UW.S0(R) ;[2202] AREN'T GOING TO READ THAT MUCH AFTER ALL
MOVE T2,UW.S0(R) ;[2202] LAST ADDRESS TO READ
XCMRED: MOVE T1,P3 ;[2202] GET LOWER BOUND
PUSHJ P,@TB.IN(R) ;[2202] 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
JRST XCMBL3 ;[2356] GO SET UP COUNT
;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
XCMBL3: HLRZ T1,P2 ;[2356] GET THE CURRENT COUNT
ADD R3,T1 ;[2356] ADD NEW COUNT
XCMBL1: HRLI P2,-1000(R3) ;[2370] PUT COUNT IN EXE DIRECTORY
TLNN R3,-1 ;[2356] MORE THAN ONE SECTION?
JRST XCMNXP ;[2356] NO, GO PROCESS THE NEXT PSECT
HRLI P2,777000 ;[2356] SET MAXIMUM REPEAT COUNT
TXZ P4,ZEROF ;[2356] TELL THE EXE FILE WRITER TO ZERO ENTRY
PUSHJ P,XCMPRD ;[2356] WRITE THE DIRECTORY
TXO P4,ZEROF ;[1132] RESET INCORRECT FLAG
ADDI P2,1000 ;[2356] UPDATE PAGE NUMBER
SUB R3,[1,,0] ;[2356] CORRECT THE COUNT
JRST XCMBL1 ;[2356] TRY AGAIN (MAY NEED SEVERAL
;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
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?
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 T2,LW.LS ;[2202] CALCULATE UPPER WINDOW
ADD T2,LS.AB ;[2202] FROM LOWER WINDOW + SIZE
SUB T2,LS.LB ;[2202] SO WE CAN WRITE OUT CURRENT LS AREA
MOVEM T2,UW.LS ;[2202] SAVE IT IN CASE IT WAS -1
MOVE T1,LW.LS ;[2202] FIRST ADDRESS FOR LS.OUT
PUSHJ P,LS.OUT## ;[2202] 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$$MMF## ;[2202] 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: MOVE T1,LW.LS ;[2202] SET UP LOWEST
MOVE T2,UW.LS ;[2202] AND HIGHEST 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
;[2366] If it's an extended addressing program, write an entry vector.
MOVE T1,HL.S1 ;[2366] Get the highest loaded
TLNN T1,-1 ;[2366] Loaded outside section zero?
JRST XCMPRV ;[2366] No, JOBDAT is sufficient
PUSHJ P,XCMPXD ;[2366] See if enough room
MOVE T2,[.SVEVC,,.ELEV] ;[2366] Two word entry vector
MOVEM T2,(W1) ;[2366] Store header
PUSHJ P,XCMPXD ;[2366] See if enough room
SKIPN T1,ENTLEN ;[2366] Entry vector length specified?
MOVEI T1,(JRST) ;[2366] No, TOPS-10 wants a JRST here
MOVEM T1,(W1) ;[2366] Store it
PUSHJ P,XCMPXD ;[2366] See if room for address
MOVE T1,STADDR ;[2366] GET START ADDRESS
MOVEM T1,(W1) ;[2366] STORE ADDRESS
XCMPRV: MOVE T1,[.SVEND,,1] ;[2366] END MARKER
PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
MOVEM T1,(W1) ;STORE IT
MOVEI W1,(W1)
SUB W1,EXEDIR ;GET LENGTH
MOVE T1,HL.S1 ;[2366] Check for entry vector
TLNE T1,-1 ;[2366] Created if outside section zero
SUBI W1,.ELEV ;[2366] Don't count entry vector in directory
HRLI W1,.SVDIR ;HEADER
MOVE T3,EXEBLK ;SEE WHICH DIRECTORY BLOCK
CAIG T3,1 ;[1401] 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
>;[2247] IFE TOPS20
E$$EOE::
IFE TOPS20,< ;[2274]
PUSH P,[DC] ;[1174]
.ERR. (ST,,V%L,L%F,S%F,EOE,<EXE file output error>) ;[1174]
>;[2274] IFE TOPS20
IFN TOPS20,< ;[2274]
PUSHJ P,JSERR## ;[2274] Get the JSYS error
.ERR. (MS,.EC,V%L,L%F,S%F,EOE,<EXE file output error>) ;[2274]
.ETC. (NLN,.EC) ;[2274] New line for error text
.ETC. (STR,,,,,ERRJSY) ;[2274] Type ERSTR% text
>;[2274] IFN TOPS20
>;END OF IFN FTEXE
IFE TOPS20,< ;[2247]
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$$MMF## ;[2202] CANNOT HAPPEN
POP P,P2 ;RESTORE RELATIVE ADDRESS
ADD P2,LC.LB ;MAKE ABSOLUTE
MOVE T2,LS.UB ;[2202] SETUP T1 FOR LS.IN
SUB T2,LS.LB ;[2202] GET THE SIZE
MOVEM T2,UW.LS ;[2202] UPPER WINDOW
SETZ T1, ;[2202] LOWER WINDOW - START AT BEGINNING
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
MOVE T1,LW.LS ;[2202] GET LOWER AND UPPER WINDOW
MOVE T2,UW.LS ;[2202] 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
MOVE T1,LW.S1 ;[2202] THIS IS WINDOW BASE
ADDI T1,.IPS ;[2202] BUT WE ALREADY HAVE THIS MUCH
MOVE T2,UW.S1 ;[2202] 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
ENDCMP:: ;[2330]
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
> ;[1401] IFE TOPS20
ENDEXE:
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
IFN TOPS20,< ;[2247]
POPJ P, ;[2247] Return
>;[2247] IFN TOPS20
IFE TOPS20,<
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
> ;[1401] IFE TOPS20
DEFINE KEYMAC (A,B)<
IFIDN <A><DEB>,<
%%==-1
IRP B,<
IFGE %%,<
IFN %%&1,<
[ASCIZ \B\]
>>
%%==%%+1
>>
PURGE %%
>
DEBNAM: KEYWORDS
IFE TOPS20,< ;[2247]
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-10
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] ..
SKIPN T2,I.PPN(T1) ;[2066] SET UP PPN - DEFAULT?
JRST RUNEX9 ;[2066] YES, USE IT
TLNN T2,-1 ;[2066] IS THERE A PATH BLOCK?
PUSHJ P,SETPTH ;[2060] YES, SET IT UP
RUNEX9: MOVEM T2,U%RUNB+4 ;[2066] PUT IT IN RUN BLOCK
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
SETPTH: HRL T1,T2 ;[2061] SET START ADDR OF PATH BLOCK FOR BLT
HRRI T1,U%PTH ;[2060] DEST ADDR FOR BLT
BLT T1,<U%PTH+<LN.IO-1>> ;[2060] MOVE IT WHERE IT WILL BE SAVE
MOVEI T2,U%PTH ;[2060] ADDRESS FOR RUN BLOCK
POPJ P, ;[2060]
;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%PTH: BLOCK LN.IO ;[2060] PATH BLOCK
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
> ;[2247] IFE TOPS20
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
SETZM LOGSUB ;[1235] SAY LOG FILE IS CLOSED
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>)
IFN TOPS20,< ;[2277] TOPS-20 ONLY
;Here when DDT cannot be GET%ed into memory for some reason.
E$$CLD: PUSHJ P,JSERR## ;[2353] SETUP ERROR STRING
.ERR. (MS,.EC,V%L,L%F,S%C,CLD,<Cannot load DDT>) ;[2304]
.ETC. (NLN,.EC) ;[2277] CRLF
.ETC. (STR,,,,,ERRJSY) ;[2277] TYPE LAST PROCESS ERROR
MOVE T1,DDTJFN ;[2277] GET DDT'S JFN BACK
GTSTS% ;[2277] GET JFN INFO
ERNAM GTSTS% ;[2277] CATCH ERRORS
TXNE T2,GS%NAM ;[2277] GOT THE JFN ANY MORE?
TXNE T2,GS%OPN ;[2277] YES, IS FILE OPEN ALREADY?
JRST DDTNRL ;[2277] NO, DON'T TOUCH JFN
JRST DDTRLS ;[2277] YES, DO COMMON CODE TO RELEASE DDT
;Can't GTJFN% a DDT.
E$$DNA: PUSHJ P,JSERR## ;[2353] SETUP ERROR STRING
.ERR. (MS,.EC,V%L,L%F,S%C,DNA,<DDT not available>) ;[2304]
.ETC. (NLN,.EC) ;[2277] CRLF
.ETC. (STR,,,,,ERRJSY) ;[2277] TYPE LAST PROCESS ERROR
SETZM GETDDT ;[2314] SAY WE DON'T WANT A DDT ANY MORE
JRST NODDT ;[2277] AND PRETEND WE NEVER WANTED DDT
;No nonexistant section to put XDDT into.
E$$NFS: .ERR. (MS,,V%L,L%F,S%C,NFS,<No free section for XDDT>) ;[2304]
MOVE T1,DDTJFN ;[2277] GET DDT'S JFN
DDTRLS: RLJFN% ;[2277] FORGET IT
ERNAM RLJFN% ;[2277] CATCH WEIRD ERRORS
SETZM DDTJFN ;[2277] REMEMBER THAT WE FORGOT IT
DDTNRL: SKIPE DEBUGSW ;[2277] WERE WE GOING TO START DDT?
SETZM EXECSW ;[2277] YES, DON'T DO IT
SETZM GETDDT ;[2314] SAY WE DON'T WANT A DDT ANY MORE
JRST NODDT ;[2277] CONTINUE AS IF DDT ISN'T WANTED
;UDDT's sym ptrs cannot be set for some reason (probably write-protected).
E$$CSP: PUSHJ P,JSERR## ;[2252] SETUP ERROR STRING
.ERR. (MS,.EC,V%L,L%F,S%C,CSP,<Cannot setup UDDT symbol table pointers>) ;[2304]
.ETC. (NLN,.EC) ;[2277] CRLF
.ETC. (STR,,,,,ERRJSY) ;[2277] TYPE LAST PROCESS ERROR
POPJ P, ;[2353] CONTINUE
> ;[2277] END IFN TOPS20
;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,
IFE TOPS20,< ;[2247]
;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 T2,LW.S0(R) ;[2202] GET LOWER WINDOW
SOJL T2,JBGMV4 ;[2202] DONE IF WAS ZERO
SETZB T1,LW.S0(R) ;[2202] NOW POINT TO BASE
PUSHJ P,@[EXP LC.IN##,HC.IN##]-1(R)
JBGMV4: MOVE T1,HC.S0(R) ;[2202] 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
ADDI T1,1 ;[2202] NEW BASE = OLD UPPER + 1
MOVE T2,UW.S0(R) ;[2202] 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
MOVE T2,VERLVL ;[1301] GET THE VERBOSITY
E01NSA::HRROI T1,[ASCIZ \[LNKNSA No start address]
\] ;[1301] GET DEFAULT
TXNN T2,M%F ;[1301] WANT FIRST LINE?
HRROI T1,[ASCIZ \[LNKNSA]
\] ;[1301] NO, GET PREFIX ONLY
TXNN T2,M%P ;[1301] WANT PREFIX?
HRROI T1,[ASCIZ \[ No start address ]
\] ;[1301] GET FIRST LINE
.XERR. ;[1301] FINISH OFF MESSAGE
JBEX10: SKIPE JOBPTR ;[2366] NEED TO RESTORE .JBDA?
PUSHJ P,BLTJDA ;YES
SKIPE JBHPTR ;SAME FOR HIGH
PUSHJ P,BLTJHA ;RESTORE FIRST 10 WORDS
SKIPE IO.PTR+%XC ;[2366] NEED TO RENAME .XPN FILE?
PUSHJ P,XPNREN ;YES
SKIPE IO.PTR+HC ;HIGH SEG OVERFLOW FILE STILL THERE?
PUSHJ P,HC.DLT ;YES, REMOVE IT
SKIPE IO.PTR+LC ;SAME FOR LOW SEG
PUSHJ P,LC.DLT
PUSHJ P,TERMES ;PRINT FINAL MESSAGES
MOVE T1,LC.LB ;LOAD UP OFFSET
MOVE T2,.JBDDT(T1) ;[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
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 T3,VERLVL ;[1301] GET THE VERBOSITY BITS
E01DLT::HRLI T1,[ASCIZ /%LNKDLT Execution deleted/] ;[1301]
TXNN T3,M%F ;[1301] FIRST WANTED?
HRLI T1,[ASCIZ /%LNKDLT/
EXP 0,0,0,0] ;[1301] NO, GET PREFIX ONLY
TXNN T3,M%P ;[1301] PREFIX WANTED?
HRLI T1,[ASCIZ /% Execution deleted/
EXP 0,0] ;[1301] NO, FIRST
HRRI T1,%TMES
BLT T1,%TMES+5
JBEX2: MOVE T1,LC.LB ;GET BASE OF LOW CODE
MOVE T1,.JBVER(T1) ;PICKUP VERSION NUMBER
MOVEM T1,%VER ;STORE IT FOR VERSION WATCHING
SKIPN T1,HC.AB ;GET REAL TOP OF HIGH SEG
MOVE T1,LC.AB ;USE LOWSEG IF NO HIGH
TLO T1,1 ;ALSO REMOVE CURRENT HIGH SEG
MOVEM T1,%T1 ;SAVE CORE UUO ARG
SKIPE T1,HC.LB ;GET BOTTOM OF HIGH SEG
SUBI T1,1 ;TOP OF LOW SEG
HRRZM T1,%T2 ;STORE FOR REMAP
MOVSI T2,(CAIA) ;INCASE NO HIGH SEG
SKIPN T1
MOVEM T2,%REMAP ;OVERWRITE REMAP UUO
SKIPN T1,RUNAME ;GET NAME TO CALL CORE IMAGE
MOVE T1,LODNAM ;USE DEFAULT IF NOT SET
TLNN T1,770000 ;[2402] IS IT A LONG NAME
MOVE T1,(T1) ;[2402] YES - GET FIRST 6 CHARS
LDB T3,[POINT 7,%TMES,6] ;[1301] GET THE FIRST CHARACTER
CAIN T3,"%" ;[1301] IS THE WARNING MESSAGE THERE
JRST JBEX20 ;[1301] YES, DON'T TOUCH
MOVE T2,VERLVL ;[1301] GET THE VERBOSITY BITS
MOVE T3,<[ASCIZ \[ \]> ;[1301]
TXNN T2,M%P ;[1301] PREFIX WANTED?
MOVEM T3,%TMES ;[1301] NO
MOVE T3,2+<[ASCIZ \ execution ]
\]> ;[1301]
TXNN T2,M%P ;[1301] PREFIX WANTED?
MOVEM T3,%RTXT+2 ;[1301] NO
TXNN T2,M%F ;[1301] FIRST LINE WANTED
JRST [SETZM %DTXT ;[1301] NO, ZERO THE PROGRAM NAME
SETZM %RTXT ;[1301] AND THE 'EXECUTION'
MOVE T2,%TMES+1;[1301] GET THE PREFIX
IORX T2,<BYTE(7) 0,0,"]",15,12> ;[1301] TACK A ']' ON THE END
MOVEM T2,%TMES+1 ;[1301]
JRST JBEX20 ] ;[1301]
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,%ZCBP ;[1244] TO CLEAR LOW SEG
JBEX2B: ;[1272] PREPARE TO GO TO PHASED CODE
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:
MOVE T1,VERLVL ;[1301] GET THE VERBOSITY BITS
TXNN T1,M%P ;[1301] PREFIX WANTED?
JRST JBEX5 ;[1301] NO, GET "[ "
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
JBEX5: MOVE T1,[ASCIZ \[ \] ;[1301] REPLACE THE PREFIX
MOVEM T1,%TMES ;[1301] WITH A BRACKET AND SPACE
JRST JBEX2 ;[1301]
;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
;[1326] P1 = POINTER FOR PA1050 SUICIDE FUNCTION [TOPS-20 ONLY]
;[1326] P2 = ARG BLOCK FOR PA1050 SUICIDE COMPT. [TOPS-20 ONLY]
%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
%REL: MOVEM T1,.JBREL-20(T2) ;[2232] IN CASE 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
RESET ;MAKE SURE NO I/O STILL OPEN
BLT 17,17 ;[644] LOAD ACCS
JRST 4 ;[644] GO THERE
%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
\
IFE TOPS20,< ;[1244]
%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
%7: MOVEM 3,.JBPFH## ;SET PAGE FAULT HANDLER
%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
%ZCBP==%2 ;[1244] PUT POINTER IN ACC 2
> ;[1244]
%END:
DEPHASE
%T1==%END+0
%T2==%T1+1
%T3==%T2+1
%T4==%T3+1
>;[2247] IFE TOPS20
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
IFN TOPS20,<
U (ARGBLK,6) ;[2247] ARGUMENT BLOCK FOR SPLFK%
U (NOLOW) ;[2247] -1 IF .LOW. DOESN'T GO IN PDV MAP
U (GETBLK,.GBASE+1) ;[2277] GET% ARG BLOCK
U (DDTJFN) ;[2277] DDT'S JFN DURING /DEBUG LOADING OF IT
U (EVLEN,2) ;[2277] ENTRY VECTOR LENGTH & ADDR. TEMP
U (UDDFLG) ;[2277] -1=UDDT LOADED, 0=XDDT LOADED
U (XJFLG) ;[2277] -1=EXTENDED JSYSES OK, 0=NOT OK
U (PDMPLN) ;[2304] PRELIMINARY PDV MEMORY MAP LENGTH
U (DDTASC) ;[2314] X/UDDT'S ASCIZ FILESPEC PTR.
U (UDPTRS,2) ;[2314] FLAG/PTRs FOR UDDT LINK
> ;[2202] IFN TOPS20
IFE TOPS20,< ;[2366]
U (SYMVEC) ;[2366] SYMBOL VECTOR ADDRESS
>;[2366] IFE TOPS20
U (DSTADR) ;[2366] DEFINED SYMBOL TABLE ADDR.
U (USTADR) ;[2366] SAME AGAIN FOR UNDEFINED TABLE
U (DSYCNT) ;[2306] COUNT OR SIZE OF DEFINED SYMBOLS
U (USYCNT) ;[2306] COUNT OR SIZE OF UNDEFINED SYMBOLS
XITLIT: END LNKXIT