TITLE LNKXIT - EXIT MODULE FOR LINK SUBTTL D.M.NIXON/DMN/JLd/RKH/JBC/JNG/MCHC/DZN/MFB/PAH/PY/HD/JBS 10-Dec-85 ;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1974,1985,1986. 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, SALL ENTRY LNKXIT EXTERN LNKCOR,LNKLOG,LNKFIO EXTERN .JB41 CUSTVR==0 ;CUSTOMER VERSION DECVER==6 ;DEC VERSION DECMVR==0 ;DEC MINOR VERSION DECEVR==2374 ;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. ;2370 Fix long sym support for DDT symbol tables. SUBTTL ENTER HERE LNKXIT: JFCL .+1 ;IN CASE CCL ENTRY E$$EXS::.ERR. (MS,0,V%L,L%I,S%I,EXS,) ;[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,);[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,) ;[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,) ;[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,) ;[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 ,< ;;[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 ,< ;;[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 ,< ;;[2211] FORDDT IS SPECIAL STADDR ;FORDDT FORCES START ADDRESS TO ITSELF %%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER > IFIDN ,< ;;[2211] COBDDT IS SPECIAL STADDR ;COBDDT GETS CONTROL FROM COBOL PROGRAM %%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER > IFIDN ,< ;;[2211] ALGDDT IS SPECIAL .JBREN(P1) ;[2211] ALGDDT STARTS FROM REENTER ADDRESS %%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER > IFIDN ,< ;;[2211] SIMDDT IS SPECIAL .JBREN(P1) ;[2211] SIMDDT STARTS FROM REENTER ADDRESS %%2==1 ;;[2211] REMEMBER WE FOUND A DEBUGGER > IFIDN ,< ;;[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,) ;[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,) ;[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,,,,,,) ;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,) ;[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 ;[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 ;[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,) 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,) ;[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 ;[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 ;[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 SETNM% ;[1425] Set it MOVX T1, ;[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,) ;[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 -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,) ;[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, ;[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,) ;[2247] SETZM EXECSW ;[2247] Don't execute POPJ P, ;[2247] Return E02NSA::.ERR. (MS,0,V%L,L%F,S%I,NSA,) ;[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,) ;[1174] .ETC. (JMP,.EC,,,,JBCMP2) E$$PCX::.ERR. (MS,.EC,V%L,L%W,S%I,PCX,) ;[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,) ;[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, ;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. JBS