Trailing-Edge
-
PDP-10 Archives
-
bb-d868c-bm_tops20_v4_2020_distr
-
language-sources/lnkxit.mac
There are 38 other files named lnkxit.mac in the archive. Click here to see a list.
TITLE LNKXIT - EXIT MODULE FOR LINK
SUBTTL D.M.NIXON/DMN/JLd/RKH/JBC/JNG/MCHC/DZN 24-Aug-79
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973, 1979 BY DIGITAL EQUIPMENT CORPORATION
SEARCH LNKPAR,LNKLOW,MACTEN,UUOSYM
IFN TOPS20,<SEARCH MACSYM, MONSYM>
SALL
ENTRY LNKXIT
EXTERN LNKCOR,LNKLOG,LNKFIO
EXTERN .JB41
CUSTVR==0 ;CUSTOMER VERSION
DECVER==4 ;DEC VERSION
DECMVR==1 ;DEC MINOR VERSION
DECEVR==1220 ;DEC EDIT VERSION
VERSION
SEGMENT
;LOCAL ACC DEFINITION
R==R1
SUBTTL REVISION HISTORY
;START OF VERSION 1A
;50 HANDLE PAGING DURING LOCAL SYMBOL OUTPUT CORRECTLY
;51 FIX BUG IF UNDEF SYMBOLS BUT DON'T WANT TO KEEP LOCAL SYMS
;53 FIX RETURNS FROM DVMOV. ROUTINE
;54 ADD KIONLY D.P. INST.
;55 STORE VERSION NUMBER (.JBVER) IN .RBVER OF SAVE FILE
;56 FIX LOOP AT JBEX2A IF CORE IMAGE IS MULTIPLE OF 2000
;57 SETUP VESTIGIAL JOB DATA AREA EVEN IF NOT A SAVE FILE
;63 REMOVE MULTIPLY-DEFINED SYMBOLS FROM SYMBOL TABLE (IN CORE)
;65 TENEX SPEEDUPS
;66 SAVE JOB DATA AREA ON /SAVE IF DDT, SYMBOLS AND ALL CODE IN HIGH SEG
;67 PUT ADDITIVE GLOBAL REQUESTS IN UNDEF TABLE
;70 FIX ADDRESS CHECK PROBLEM
;71 MAKE ALL INFO MESSAGES STANDARD FORM
;73 (11314) PREVENT EXECUTION IF UNDEF SYMBOLS
;100 FIX ILL MEM REL ON /SAVE IF LAST BLOCK FILLS ALL OF CORE
;104 OUTPUT FAIL BLOCK HEADER IN LOCAL SYMBOL TABLE
;106 REMOVE HIORG, REPLACE BY LL.S2
;115 MAKE /NOSYMBOLS WORK CORRECTLY
;START OF VERSION 2
;135 ADD OVERLAY FACILITY
;136 FIX VARIOUS BUGS
;140 (12617) FIX ?IO TO UNASSIGNED CHANNEL ON /SYMBOL:TRIPLET FILE
;154 (12991) ONLY LOOK AT RIGHT HALF OF .JBERR TO DELETE EXECUTION
;155 (12988) FIX TEST FOR COBDDT AT RUN UUO TIME
;166 MAKE RADIX50 SYMBOL FILE TYPE 776
;177 FIX ADDRESS CHECK BUG IF PAGING SYMBOLS
;211 FIX ZEROS IN MONITOR SYMBOL TABLE
;213 (12531) LOW SEG OF TWOSEG CORE IMAGE BAD
;221 GET PROTECTION CODE RIGHT ON XPN FILE
;START OF VERSION 2A
;244 DATE75 FIX TO MAKE LOW SEG FILE HAVE CORRECT DATE
;START OF VERSION 2B
;224 PUT SECOND SYMBOL FOR COMMON BLOCK IN RADIX50 SYMBOL TABLE
;226 FIX UNDEFINED SYMBOL BUG (117 NOT SET UP)
;234 FIX VARIOUS BUGS IF HIGH FILE IS MADE RATHER THAN RENAMED
;235 (13845) FIX ZERO COMPRESSOR IF PAGED AND READING ZEROS
;241 USE LARGER OF ABS OR LOW REL BREAK FOR .JBFF
;242 HANDLE USER PAGE FAULT HANDLER CORRECTLY
;244 DATE75 FIX TO MAKE LOW SEG FILE HAVE CORRECT DATE
;247 Change all references to DEBUGSW. Now lh is -1 if set,
; rh is table index for either /DEBUG or /TEST
;266 Correct problems with loading symbols when LS area
; overflows to the DSK.
;267 Get symbol table offest right when core window
; changes.
;270 Use the correct initialization routine when high
; core overflows to the disk during this phase.
;322 Get LSYM and other core management variables right
; so LNKCOR doesn't fail
;324 Don't release the symbol channel if still needed,
; when loading symbols into root of an overlay program.
;330 Release the correct channel when done with symbols
; being loaded into the root of an overlay program.
;335 Keep LSYM from being clobbered when loading symbols
; into root of overlay program. Don't confuse LNKCOR
;336 Fix /RUN switch to work properly
;337 Insert check for no core to zero before BLT and
; prevent possible ILL MEM REF
;353 REMOVE EDIT 225
;357 LABEL EDITS 224,226,234,235,241,242
;360 REMOVE EDIT 336
;401 Remove 5.06 compatability hack setting up vestigial jobdat.
;403 Fix HALT if generating new style symbol file.
;423 Fix ?ILL ADDR IN UUO when the zero compressor tried to use
; the LS area after it had done a CORE UUO to get rid of it.
;433 Support the /RUN switch.
;START OF VERSION 2C
;442 Fix the DVMOV. routine to either RENAME or copy,
; and delete copy routines called if DVMOV. fails.
;443 Don't lose part of local symbols if overflowing to disk.
;467 Correct RT.PT check at SYMO1
;471 Add code for ALGOL debugging system.
;476 Insert missing FTOVERLAY conditional.
;517 Make first word of ALGOL symbol file be 1044,,count.
;524 Check for symseg area reduced to one page & don't zero rest.
;530 Get triplet flag definitions right.
;544 SOUP in LINK version 3 stuff for TOPS-20.
;547 Make LINK assemble with MACRO 51.
;555 Don't round .RBSIZ up to block bound for symbol files.
;557 Clean up the listing for release.
;START OF VERSION 3
;446 CHANGES FOR TENEX
;START OF VERSION 3A
;560 Release on both TOPS-10 and TOPS-20 as LINK version 3A(560)
;START OF VERSION 4
;570 Don't lose local symbols when undefined globals exist.
;575 On /EXECUTE/SAVE to a two segment program, always run xxx.LOW
;606 Get the protection of .HGH and .XPN files right.
;616 Give appropriate error messages when RENAMEs fail
;621 /SAVE AND /SSAVE GENERATE EXE FILE.
; /SAVE AND /SSAVE NO LONGER TAKES ANY ARGUMENT. IF THE CORE
; SIZE IS SPECIFIED, LINK WILL IGNORE IT.
; THE CODE TO GENERATE .HGH/.SHR/.LOW FILES ARE UNDER THE
; CONDITIONAL ASSEMBLY SWITCH FTEXE==0.
;622 Don't set up vestigal JOBDAT unless there's a high segment.
;641 IF HIGH SEG IS PAGED, WRITE OUT WHAT'S IN CORE BEFORE UPDATING
; VESTIGAL JOBDAT AND DUMP TO EXE FILE.
;642 EXE FILE EXTENSION FOR DISK FILE GENERATED FOR NOT HAVING
; ENOUGH CORE
;643 FIX BUG WITH SWITCH SETTING FOR P4 IN XCMPRL.
;644 DON'T DO JSYS 147(RESET) IF WE DO EXIT.
;645 Loop back topage lc if not more core in LSREQ.
;646 Don't touch a high seg page again after high seg is removed
; in %LOW.
;647 Don't zero unneeded memory (better VM performance).
;650 Use VM on TOPS-10 if available.
;652 Avoid bad .SAV file when paging to disk.
;704 Don't write EXE-directory entries for psect gaps.
;713 Fix bug with sparse EXE-directory.
;715 Modify SYMSEG to take psect name.
;724 Check for symbol table range in INGAP.
;725 Fix bug with incrementing process page in XCMPOV.
;726 Fix bug in INGAP routine.
;727 Give Insufficient space error message when symbol table truncated.
;731 SEARCH MACTEN,UUOSYM instead of C.
;732 Use LOWLOC and fix bugs related to page 777.
;733 Fix bug with allocated high seg pages causing bad EXE format.
;742 Don't BLT JOBDAT if process page 0 not the first page.
;744 Fix bug with calculation of EXE file size.
;754 Don't page LS area when doing symbol table output, if paging is needed for the first time for LC(or HC).
;762 Page in the LOWLOC page before generating EXE file.
;764 Update LOWLOC in GETSST incase symbol table is lower than code.
; Also, corrects a bug in updating upper window in XCMPRS routine.
;765 Release on both TOPS-10 and TOPS-20 as LINK version 4(765)
;START OF VERSION 4A
;770 Add code to allow first-time paging in und-symbol table routine.
;772 Adjust symbol table pointer to after undefined symbol table.
;773 Fix GSDLT in case the GS area is already gone.
;774 Fix bad calculation of UW in EXE file writer.
;776 Fix /SAVE of small program with no data in pages 0 or 1.
;1110 Output PSECT name as part of error message in GETSST.
;1111 Fix core management bug introduced by edit 772.
;1113 See that LINK doesn't shrink on TOPS-20 until really necessary.
;1121 Fix edit 772 so symbol table and undefined table don't overlap.
;1125 Don't try to do a RUN UUO to the hiseg file when generating an EXE file.
;1127 Set up the module length for PAT.. in the runtime symbol table.
;1132 Teach the EXE file writer about PSECTs above the high segment.
;1144 Zap PA1050 but not DDT on /EXECUTE, /DEBUG when running from .EXE file.
;1145 Set up symbol table pointers on TOPS-20 if no .EXE file written; broken by 1144.
;1146 Force writing an .EXE file more often, especially with PSECTs.
;1147 Adjust LC.LB when adjusting LW.S1 in JBEXE. Broken by 732.
;1152 Set RC.HL for .LOW. during initialization when loading overlays.
;1160 Don't put junk in the undefined table when symbol used in Polish.
;1170 Fix core management problems when not writing an EXE file.
;1171 Fix edit 1146 to say LNKPCL if bad PSECT properties, even on TOPS-10.
;1172 Fix many problems with runtime symbol table generator.
;1174 Label and clean up all error messages.
;1202 Fix problems introduced by edits 1172 and 1174.
;1212 Use E$$SOE label instead of ZCMP7E, broken by 1174 (in off conditional).
;1214 Fix unmatched angle bracket bug in .EXE file code.
;1216 Preserve P acs in SYMOUT.
;1217 Clean up the listings for release.
;1220 Release on both TOPS-10 and TOPS-20 as version 4A(1220).
SUBTTL ENTER HERE
LNKXIT: JFCL .+1 ;IN CASE CCL ENTRY
E$$EXS::.ERR. (MS,0,V%L,L%I,S%I,EXS,<EXIT segment>) ;[1174]
ZAPTMP ;CLEAR ALL TEMP SPACE
MOVE T1,HC.S0 ;GET ABS BREAK
CAMLE T1,HC.S1 ;LARGER THAN LOW SEG?
MOVEM T1,HC.S1 ;USE LARGER
MOVE T1,HL.S0 ;GET ABS BREAK
CAMLE T1,HL.S1 ;LARGER THAN LOW SEG?
MOVEM T1,HL.S1 ;USE LARGER
IFN FTOVERLAY,<
SKIPGE LNKMAX ;DID WE LOAD ANY OVERLAYS?
JRST LNKX1 ;NO
MOVE T1,PH.OVL ;GET START OF CODE FOR ROOT
USETI OC,(T1) ;POSITION ON THE BLOCK
MOVE P2,PH.LEN ;LENGTH WE NEED
ADD P2,LC.LB
SUB P2,LC.AB ;SEE IF ENOUGH
JUMPLE P2,LNKX0A ;YES
MOVEI P1,LC.IX
PUSHJ P,LNKCOR## ;MUST EXPAND
JRST LNKX0C ;DO IT THE HARD WAY
LNKX0A: MOVE T1,LC.LB
SUBI T1,1
HLL T1,PH.OVL ;SETUP IOWD
SETZ T2,
IN OC,T1 ;READ BACK CORE
LNKX0B: SKIPA T1,OV.S1 ;CORE BOUNDS
PUSHJ P,E$$IOV## ;[1174] INPUT ERROR
HRRZM T1,HL.S1
HLRZM T1,HC.S1
MOVEI R,1 ;[1152] LOW SEGMENT
MOVE R,@RC.TB ;[1152] POINTER TO RC BLOCK FOR LC AREA
HRRZM T1,RC.CV(R) ;[1152] SAVE AS CURRENT VALUE OF RELOC COUNTER
HRRZM T1,RC.HL(R) ;[1152] AND FIRST FREE BEYOND ROOT
JRST LNKX1
;NOW TO READ BACK FIRST FEW BLOCK
LNKX0F: SETZM LW.S1 ;STARTS AT ZERO
MOVE T1,LC.UB
MOVEM T1,LC.AB ;USE IT ALL AGAIN
SUB T1,LC.LB
MOVEM T1,UW.S1 ;UPPER BOUND
PUSHJ P,LC.IN## ;READ IT BACK
JRST LNKX0B ;FIXUP VARIOUS POINTERS
LNKX0C: SETZM LW.S1 ;SET BACK TO START
MOVE T1,PH.OVL
USETI OC,(T1) ;SET ON BLOCK
MOVE T1,LC.UB
MOVEM T1,LC.AB ;USE ALL AVAILABLE SPACE
SUB T1,LC.LB ;GET SIZE OF WINDOW
MOVEM T1,UW.S1 ;UPPER WINDOW
ADDI T1,1
LNKX0D: MOVN T1,T1
HRLZ T1,T1
HRR T1,LC.LB ;IOWD
SUBI T1,1 ;AT LAST
SETZ T2,
IN OC,T1
SKIPA T1,LC.AB
PUSHJ P,E$$IOV## ;[1174]
SUB T1,LC.LB
ADD T1,LW.S1 ;ADD BASE
CAMG T1,PH.LEN ;REACHED END YET?
JRST LNKX0E ;NO
MOVE T1,PH.LEN ;YES, GET WHAT WE REALLY NEED
IORI T1,.IPM
MOVE T2,T1
SUB T2,LW.S1
ADD T2,LC.LB
CAMN T2,LC.UB ;ARE WE IN LAST BLOCK
JRST LNKX0E ;YES, NO CHANGE
MOVEM T2,LC.AB ;RESET UPPER BOUND IN USE
SETZM 1(T2) ;ZERO FIRST WORD
HRLI T2,1(T2)
HRRI T2,2(T2)
BLT T2,@LC.UB ;AND THROUGH REST
LNKX0E: HRL T1,LW.S1 ;ORIGIN
PUSHJ P,LC.OUT## ;WRITE OUT THIS MUCH
MOVE T1,LC.AB
SUB T1,LC.LB ;GET SIZE OF WINDOW
MOVE T2,T1
ADD T2,LW.S1
CAML T2,PH.LEN ;MORE TO DO?
JRST LNKX0F ;NO
AOS T2,T1 ;PUT COPY IN T2
ADDM T1,LW.S1 ;NEW WINDOW BASE
ADDB T2,UW.S1 ;GET NEXT UPPER BOUND
CAMG T2,PH.LEN ;DO WE NEED TO READ IT ALL IN?
JRST LNKX0D ;YES
MOVE T1,PH.LEN ;NO, GET HIGHEST WE NEED
ADDI T1,.DBM ;[650] UP TO NEXT BLOCK
ANDCMI T1,.DBM ;[650] INCASE WAS ALREADY THERE
SUB T1,LW.S1 ;NO. OF WORDS
JRST LNKX0D ;TO INPUT
>;END OF IFN FTOVERLAY
LNKX1: MOVEI R,1 ;SETUP TO POINT TO LOW SEG
MOVE R,@SG.TB
IFN FTOVERLAY,<
SKIPL LNKMAX ;IF LOADING OVERLAYS
SETZM USYM ;IGNORE UNDEFINED SYMBOLS TIL RUN TIME
>
MOVEI T1,PATSP. ;IF NOT ALREADY
SKIPN PATSPC ;SETUP PATCHING SIZE
MOVEM T1,PATSPC ;IN CASE REQUIRED
SETZM FRECOR ;NO NEED NOW
SKIPN FS.SS ;THESE ARE THE ONLY FIXUPS WE CAN DO NOW
SKIPE USYM ;BUT MAY HAVE GLOBAL REQUESTS
CAIA
PUSHJ P,FX.ZAP ;NONE, SO GET RID OF AREA
;NOW TEST FOR CASE INWHICH SYMBOL FILE WAS
;OPENED BUT NOT USED (NOT VERY LIKELY)
SKIPE UW.LS ;NEVER OPENED
SKIPE LW.LS ;NEVER USED IF STILL ZERO
JRST CLSMAP ;STILL IN USE, OR NEVER WAS
IFN FTOVERLAY,<
SKIPL LNKMAX ;IF LOADING OVERLAYS
SKIPN UW.LS ; AND PAGING SYMBOLS
CAIA ;NO
JRST CLSMAP ;KEEP FILE OPEN RATHER THAN READ IN
>
SETZM UW.LS ;CLEAR UNWANTED POINTER
MOVEI T1,SC ;SYMBOL FILE CHAN #
PUSHJ P,DVDEL.## ;DELETE FILE AND REMOVE ALL TRACES
JFCL
SETZM IO.PTR+SC ;AND FORGET ABOUT IT
CLSMAP: SKIPN IO.PTR+MC ;AN OPEN MAP?
JRST RDJBDA ;NO
MOVEI T1,MC ;SET CHAN#
MOVEM T1,IO.CHN ;IN ACTIVE STATE
PUSHJ P,DVRLS.## ;CLOSE FILL AND DO POSITIONING
PUSHJ P,DVZAP.## ;RETURN BUFFERS AND DATA BLOCK
RDJBDA: SKIPE PAG.S2 ;HIGH SEG PAGING?
PUSHJ P,RDJBH ;YES, READ IN .JBHDA
SKIPE PAG.S1 ;LOW SEG PAGING?
PUSHJ P,RDJBL ;YES
HRRZ T1,.JBERR ;GET ERRORS FOR THIS PROCESS
ADD T1,USYM ;EACH UNDEF COUNTS ONE
HRRM T1,.JBERR ;WILL STOP EXECUTION IF NON-ZERO
JRST CHKRST ;[1172] NOW GO DO RUNTIME SYMBOL TABLE
;HERE TO READ IN FIRST 10 WORDS OF HIGH SEGMENT
RDJBH: MOVEI T2,.JBHDA ;NO OF WORDS WE NEED
PUSHJ P,DY.GET ;GET THEM
MOVEM T1,JBHPTR ;STORE LOCATION
SUBI T1,1 ;IOWD IS 1 LESS
HRLI T1,-10 ;SHOULD BE -.JBHDA BUT MACRO 50 NOT YET OUT
SETZ T2, ;TERMINATE LIST
USETI HC,1 ;SET ON BLOCK 1
IN HC,T1 ;READ FIRST 10 WORDS ONLY
POPJ P, ;OK
PUSHJ P,E$$IHC## ;[1174] DIE WITH ERROR
;HERE IF LOWSEG PAGED, WE NEED BOTH ENDS OF FILE AT ONCE
;THEREFORE PUT JOBDAT (0-137) IN DY AREA, POINTER IS JOBPTR
;AND TOP OF FILE IN LC AREA
RDJBL: MOVEI T2,.JBDA ;NEED ONE BLOCK
PUSHJ P,DY.GET
MOVEM T1,JOBPTR ;HOLD OFFSET IN CORE SO WE CAN FIXUP
; REFERENCES TO JOBDAT SYMBOLS
SKIPN LW.S1 ;HOWEVER IF 1ST PAGE IS IN CORE
JRST BLTJBL ;JUST MOVE IT
SUBI T1,1 ;IOWD IS ONE LESS
HRLI T1,-140 ;WORD COUNT
SETZ T2, ;TERMINATE LIST
USETI LC,1 ;READ BLOCK 1
IN LC,T1 ;AT LEAST FIRST 140 WORDS
POPJ P, ;NONE
PUSHJ P,E$$ILC## ;[1174] DIE WITH ERROR
;HERE TO JUST BLT JOBDAT AREA TO SAFE PLACE
BLTJBL: HRL T1,LC.LB ;FROM HERE
HRRI T2,.JBDA(T1) ;TO HERE
BLT T1,-1(T2) ;WELL ALMOST THERE
POPJ P,
SUBTTL RUNTIME SYMBOL TABLE GENERATION
;HERE TO DECIDE IF WE WANT TO PUT A RUNTIME SYMBOL TABLE INTO THE
;IMAGE, AND IF SO, TO DO IT. WE WANT A RUNTIME SYMBOL TABLE IF ANY
;OF THE FOLLOWING CONDITIONS ARE TRUE:
;
; 1. C(.JBDDT) IS NONZERO
; 2. USER SAID /SYMSEG
; 3. USER SAID /SYFILE:RADIX50
;
;IF THE USER SAID /NOSYMBOLS, WE NEVER WANT A RUNTIME SYMBOL TABLE.
CHKRST: SKIPE PAG.S1 ;[1172] FIND JOBDAT
SKIPA T1,JOBPTR ;[1172] IN DY IF PAGING
MOVE T1,LC.LB ;[1172] IN LC AREA IF NOT
SKIPN T2,VERNUM ;[1202] /VERSION? (CHECK NOW FOR OLDSYM)
SKIPA T2,.JBVER(T1) ;[1202] NO, FETCH FROM .JBVER
MOVEM T2,.JBVER(T1) ;[1202] OVERRIDE IF /VERSION
MOVEM T2,VERNUM ;[1202] STORE FOR SYMBOL FILES
SETZM .JBSYM(T1) ;[1172] ASSUME NO SYMBOLS
SETZM .JBUSY(T1) ;[1172] ..
SKIPE NOSYMS ;[1172] /NOSYMBOLS?
JRST NORST ;[1172] YES, FORGET IT
SKIPN .JBDDT(T1) ;[1172] C(.JBDDT) <> 0?
SKIPE SYMSEG ;[1172] OR USER SAY /SYMSEG?
JRST DORST ;[1172] YES, GO DO IT!
SKIPL SYMFRM ;[1172] /SYFILE:RADIX50?
JRST NORST ;[1172] NOPE, NO SYMBOL TABLE
; ..
; ..
;HERE TO GENERATE A RUNTIME SYMBOL TABLE.
;FIRST, MAKE SURE THE AREA (LC/HC) THAT THE SYMBOLS ARE GOING
;INTO IS BIG ENOUGH, OR IS PAGING AND THE RIGHT PAGE IS IN.
DORST:
IFN FTOVERLAY,<
SKIPL LNKMAX ;[1172] LOADING OVERLAYS?
JRST OVLRST ;[1172] YES, THINGS ARE DIFFERENT
> ;END IFN FTOVERLAY
E$$SST::.ERR. (MS,0,V%L,L%I,S%I,SST,<Sorting symbol table>) ;[1174]
PUSHJ P,GETSST ;[1172] FIND BASE OF SYMBOLS, SET R AND P4
SKIPE PAG.S0(R) ;[1172] SYMBOL SEGMENT PAGING?
JRST DORST2 ;[1172] YES, GO GET THE RIGHT PAGE INTO MEMORY
MOVE P2,RC.HL(P4) ;[1172] GET FIRST WORD OF TABLE
SUB P2,LL.S0(R) ;[1172] CONVERT TO OFFSET IN SEGMENT
SUB P2,LW.S0(R) ;[1172] THENCE TO OFFSET IN WINDOW
ADD P2,TAB.LB(R) ;[1172] FIRST ADDRESS WE'RE GOING TO STORE INTO
CAMG P2,TAB.AB(R) ;[1172] IS THE AREA BIG ENOUGH?
JRST DORST4 ;[1172] YES, GO FILL IT IN
MOVE P1,R ;[1172] WHICH AREA TO EXPAND
SUB P2,TAB.AB(R) ;[1172] HOW MUCH WE NEED
PUSHJ P,LNKCOR ;[1172] EXPAND THE AREA
JRST DORST2 ;[1172] FINE, JUST START PAGING
JRST DORST3 ;[1172] GO CHECK PAGING FOR THE FIRST TIME
;HERE IF PAGING TO BRING THE RIGHT LC/HC PAGE INTO MEMORY.
DORST2: PUSHJ P,LSYP ;[1172] NOW PAGING, GET RIGHT PAGE IN MEMORY
DORST3: PUSHJ P,CHKPAG ;[1172] SEE IF WE JUST STARTED PAGING
DORST4: MOVE T1,RC.HL(P4) ;[1172] NOW TO SET UP XX.PT
SUB T1,LL.S0(R) ;[1172] FIRST ADDRESS TO STORE INTO
SUB T1,LW.S0(R) ;[1172] CONVERT TO OFFSET IN AREA
ADD T1,TAB.LB(R) ;[1172] ADDRESS IN AREA
MOVEM T1,TAB.PT(R) ;[1172] STORE FOR SYMOUT
;OK, EVERYTHING IS INITIALIZED. NOW WRITE OUT THE SYMBOL TABLE(S).
SKIPE USYM ;[1172] ANY UNDEFINED SYMBOLS?
PUSHJ P,DOUDFS ;[1172] YES, WRITE THEM OUT
PUSHJ P,GSDLT ;[1172] DELETE THE GS AREA
SKIPN SYMFUL ;[1172] IF ANY ROOM LEFT
PUSHJ P,DOLOCS ;[1172] WRITE THE LOCAL SYMBOLS OUT
;THE SYMBOLS HAVE BEEN WRITTEN. NOW UPDATE THE HL/HC WORDS, THEN GO CLEAN UP.
MOVE T1,TAB.PT(R) ;[1172] NEXT FREE WORD
SUB T1,TAB.LB(R) ;[1172] OFFSET IN WINDOW
ADD T1,LW.S0(R) ;[1172] OFFSET IN SEGMENT
CAMLE T1,HL.S0(R) ;[1172] BIGGEST WE'VE SEEN?
MOVEM T1,HL.S0(R) ;[1172] YES, STORE IT
CAMLE T1,HC.S0(R) ;[1172] BIGGEST LOADED LOC?
MOVEM T1,HC.S0(R) ;[1172] YES, STORE IT
ADD T1,LL.S0(R) ;[1172] FORM VIRTUAL ADDRESS
CAMLE T1,RC.HL(P4) ;[1172] BIGGEST YET FOR THIS PSECT?
MOVEM T1,RC.HL(P4) ;[1172] YES, REMEMBER IT
SKIPGE SYMFRM ;[1172] OLD STYLE SYMBOL FILE WANTED?
PUSHJ P,OLDSYM ;[1172] YES, WRITE IT OUT
E$$STC::.ERR. (MS,0,V%L,L%I,S%I,STC,<Symbol table completed>) ;[1174]
JRST FINRST ;[1172] GO JOIN COMMON CLEAN UP CODE
;HERE WHEN LOADING OVERLAYS.
IFN FTOVERLAY,<
OVLRST: HLRE T2,PH.RDX ;[1172] GET - NO. OF SYMBOLS
MOVM T3,T2 ;[1172] +
ADD T3,HL.S1 ;[1172] HIGHEST LOCATION
ADD T3,SPACE ;[1172] PLUS BUFFER SPACE
IOR. T3,.PGSIZ ;[1172] UP TO PAGE BOUND
ADDI T3,1 ;[1172] NEXT FREE
ADD T3,T2 ;[1172] START OF SYMBOLS
HLL T3,PH.RDX ;[1172] - COUNT
MOVEM T3,JOB116 ;[1172] STORE IN INTERNAL PTR
MOVEM T3,.JBSYM(T1) ;[1172] STORE SYMBOL TABLE PTR
> ;END IFN FTOVERLAY
;HERE IF NOT WRITING A RUNTIME SYMBOL TABLE. JUST DELETE LINK'S TABLES.
NORST: PUSHJ P,GSDLT ;[1172] GET RID OF THE GS AREA
; ..
; ..
;ALL PATHS REJOIN HERE. DELETE TABLES, SET UP JOBDAT, AND EXIT.
FINRST: SKIPLE T1,SYMFRM ;[1172] WANT NEW STYLE SYMBOL FILE?
PUSHJ P,SAVSYM ;[1172] YES, WRITE IT OUT
PUSHJ P,AS.ZAP ;[1172] DONE WITH AS AREA
MOVEI T1,AC ;[1172] ALGOL SYMS CHANNEL
SKIPE PAG.AS ;[1172] AREA PAGING?
PUSHJ P,DVDEL.## ;[1172] YES, DELETE OVERFLOW FILE
JFCL ;[1172] DON'T CARE
PUSHJ P,FX.ZAP ;[1172] DONE WITH FX AREA
IFN FTOVERLAY,<
SKIPL LNKMAX ;[1172] LOADING OVERLAYS?
JRST FINRS2 ;[1172] YES, SAVE LS AREA
> ;END IFN FTOVERLAY
PUSHJ P,LS.ZAP ;[1172] KILL OFF THE LS AREA
MOVEI T1,SC ;[1172] LS OVERFLOW CHANNEL
SKIPE PAG.LS ;[1172] LS AREA PAGING?
PUSHJ P,DVDEL.## ;[1172] YES, DELETE OVERFLOW FILE
JFCL ;[1172] WASN'T PAGING
;NOW UPDATE JOBDAT, THEN EXIT VIA SAVTST.
FINRS2: SKIPE PAG.S1 ;[1172] LC AREA PAGING?
SKIPA P1,JOBPTR ;[1172] YES, JOBDAT IS IN DY
MOVE P1,LC.LB ;[1172] NO, IT'S IN LC
SKIPE PAG.S2 ;[1172] HC AREA?
SKIPA P2,JBHPTR ;[1172] YES, FETCH DY PTR
MOVE P2,HC.LB ;[1172] NO, FETCH HC PTR (OR 0)
PUSHJ P,JOBSET ;[1172] SET UP JOBDAT
PUSHJ P,HJBSET ;[1172] VESTIGAL JOBDAT
JRST SAVTST ;[1172] DONE WITH CHKRST, GO CHECK /SAVE
;GETSST - ROUTINE TO FIGURE OUT WHERE THE SYMBOL TABLE GOES
;CALLED ONLY WHEN A RUNTIME SYMBOL TABLE IS DEFINITELY NEEDED.
;RETURNS WITH:
;
; SSGNAM/ NAME (SIXBIT) OF PSECT TO APPEND SYMBOLS TO
; R/ AREA PSECT IS IN, LC.IX OR HC.IX
; P4/ POINTER TO RC BLOCK OF PSECT NAMED IN SSGNAM
; RC.HL(P4)/ FIRST ADDRESS TO STORE A SYMBOL IN
; SYMLIM/ LAST ADDRESS TO STORE A SYMBOL IN
;
;ALSO UPDATES LOWLOC IF NECESSARY.
GETSST: SKIPGE R,SYMSEG ;[1172] /SYMSEG TO A PSECT?
JRST GETS10 ;[1132] YES, GO FIND IT
GETS2: CAIN R,2 ;[1172] /SYMSEG:HIGH?
JRST GETS8 ;[1172] YES, TREAT IT LIKE /SYMSEG:PSECT:.HIGH.
;HERE IF /SYMSEG:LOW OR NO /SYMSEG (E.G., C(.JBDDT<>0).
;WE WANT TO APPEND PAT.. AND THE SYMBOL TABLE TO THE LAST PSECT IN THE IMAGE.
;OUR FIRST MISSION IS TO FIND THAT PSECT...
SETZB R,T3 ;[1172] INIT HIGHEST ADDR AND PSECT IDX
GETS4: MOVE T1,@RC.TB ;[1172] GET POINTER TO RC BLOCK OF NEXT PSECT
MOVE T2,RC.SG(T1) ;[1172] GET THE SEGMENT THAT THIS PSECT IS IN
CAIE T2,1 ;[1172] IN THE LOW SEGMENT?
JRST GETS6 ;[1172] NO, IT DOESN'T COUNT FOR /SYMSEG:LOW
MOVE T2,RC.HL(T1) ;[1172] GET THE FIRST FREE AFTER THIS PSECT
CAMG T2,T3 ;[1132] HIGHEST SO FAR?
JRST GETS6 ;[1132] NO, CONTINUE
MOVE T3,T2 ;[1132] SAVE NEW BEST
MOVE T4,R ;[1132] AND WHAT PSECT IT WAS
MOVE T2,RC.NM(T1) ;[1172] GET THE WINNER'S NAME
MOVEM T2,SSGNAM ;[1172] STORE FOR ERROR MESSAGES
GETS6: CAMGE R,RC.NO ;[1132] ALL DONE?
AOJA R,GETS4 ;[1132] NO, LOOP
MOVE R,T4 ;[1132] YES, SAVE PSECT INDEX OF LAST ONE
JRST GETS14 ;[1132] GO UPDATE THAT PSECT
;HERE ON /SYMSEG:HIGH. FAKE /SYMSEG:PSECT:.HIGH. AND FALL INTO PSECT CODE.
GETS8: MOVE T1,['.HIGH.'] ;[1132] /SYMSEG:HIGH IS JUST LIKE A PSECT
MOVEM T1,SSGNAM ;[1132] STORE
;HERE ON /SYMSEG:PSECT:xxxxxx. FIND THE PSECT IN THE RC TABLES.
GETS10: SETZ R, ;[727] YES, HAVE PSECT NAME
GETS12: MOVE T1,@RC.TB ;[1132]
MOVE T1,RC.NM(T1) ;[1132] GET PSECT NAME
CAMN T1,SSGNAM ;[1132] IS THIS THE ONE?
JRST GETS14 ;[1132] YES,
ADDI R,1 ;[715] NEXT ONE
CAMG R,RC.NO ;[715] ANY MORE?
JRST GETS12 ;[1132] YES, LOOP
E$$NPS::.ERR. (MS,.EC,V%L,L%W,S%W,NPS,<Non-existent psect >) ;[1110] ;[1174]
.ETC. (SBX,.EC!.EP,,,,SSGNAM) ;[1174] OUTPUT PSECT NAME
.ETC. (STR,,,,,,< specified for symbol table>) ;[1174]
MOVEI R,1 ;[1132] SET TO LOW
MOVEM R,SYMSEG ;[1132]
JRST GETS2 ;[1132] AND LOOP BACK
;HERE WITH THE PSECT INDEX TO USE IN R, AND ITS NAME IN SSGNAM.
;WE NOW WANT TO CALCULATE HOW FAR THE SYMBOL TABLE IS ALLOWED TO EXTEND.
;BELIEVE THE USER'S /UPTO SWITCH IF HE GAVE ONE, OTHERWISE STOP ONE BELOW
;THE NEXT PSECT ORIGIN WE WOULD CROSS, OR STOP AT 777777 IF NO MORE PSECTS.
GETS14: MOVE P4,@RC.TB ;[1172] POINTER TO THIS PSECT'S RC BLOCK
SKIPE SYMLIM ;[1172] USER TYPE /UPTO?
JRST GETS20 ;[1172] YES, BELIEVE IT
MOVE T4,RC.HL(P4) ;[1172] ADDR OF START OF PATCH AREA
ADDI R,1 ;[1172] START THE SEARCH AT THE NEXT PSECT
;LOOP BACK HERE ON EACH NEW PSECT, LOOKING FOR ONE WHOSE ORIGIN
;IS .GE. C(T4).
GETS16: CAMLE R,RC.NO ;[1172] CHECKED THEM ALL YET?
JRST GETS18 ;[1172] YES, GO USE 777777
MOVE T1,@RC.TB ;[1172] GET PSECT'S RC BLOCK
MOVE T2,RC.IV(T1) ;[1172] GET ORIGIN OF THIS PSECT
CAMGE T2,T4 ;[1172] START ABOVE THE SYMSEG PSECT?
AOJA R,GETS16 ;[1172] NO, MUST HAVE BEEN OVERLAPPING PSECT
MOVE T3,RC.HL(T1) ;[1172] YES, CHECK FOR ZERO-LENGTH PSECT
CAMG T3,T2 ;[1172] WOULD WE OVERWRITE ANYTHING?
AOJA R,GETS16 ;[1172] NO, IGNORE THIS PSECT
SOSA T2 ;[1172] YES, LAST ADDR TO USE IS ONE LESS
GETS18: MOVEI T2,777777 ;[1172] NO MORE PSECTS, USE END OF SECTION 0
MOVEM T2,SYMLIM ;[1172] STORE NEWLY CALCULATED LIMIT
;NOW SET UP SOME FINAL THINGS FOR THE REST OF LINK, THEN RETURN.
GETS20: MOVE R,RC.SG(P4) ;[1172] FETCH SEGMENT INDEX FOR PSECTS
MOVE T1,RC.HL(P4) ;[1172] START OF PATCH AREA
MOVEM T1,PATLOC ;[1172] REMEMBER FOR RST
ADD T1,PATSPC ;[1172] START OF REAL SYMBOL TABLE
MOVEM T1,RC.HL(P4) ;[1172] UPDATE SIZE OF PSECT
TRZ T1,777 ;[1172] ROUND DOWN TO PAGE BOUND
CAMGE T1,LOWLOC ;[1172] LOWEST LOCATION YET LOADED?
MOVEM T1,LOWLOC ;[1172] YES, SAVE FOR EXE FILE WRITER.
POPJ P, ;[1172] END OF GETSST
;HERE IF PAGING TO SETUP LC/HC AREA TO INSERT SYMBOLS INTO.
;WRITE OUT ENTIRE WINDOW, THEN SET UP LAST PAGE ONLY.
;AREA WILL EXPAND AS REQUIRED IN SYMOUT.
LSYP: HRLZ T1,LW.S0(R) ;[1172] BOTTOM OF WINDOW
HRR T1,UW.S0(R) ;[1172] TOP
PUSHJ P,@TB.OUT##(R) ;[1172] WRITE ENTIRE WINDOW TO DISK
MOVE T1,TAB.AB(R) ;[1172] REDUCE WINDOW TO ONE PAGE
ANDCMI T1,.IPM ;[1172] NEW BOTTOM OF AREA
SUBI T1,1 ;[1172] FIRST WORD BELOW NEW BASE
CAML T1,TAB.LB(R) ;[1172] AREA ALREADY ONE PAGE?
PUSHJ P,GBCK.L## ;[1172] NO, SHRINK IT DOWN
MOVE T1,RC.HL(P4) ;[1172] GET FIRST ADDR TO STORE A SYMBOL IN
SUB T1,LL.S0(R) ;[1172] RELATIVE TO SEGMENT START
ANDCMI T1,.IPM ;[1172] NEW BOTTOM OF WINDOW
MOVEM T1,LW.S0(R) ;[1172] STORE
IORI T1,.IPM ;[1172] NEW TOP OF WINDOW
CAMN T1,UW.S0(R) ;[1172] WHERE IT WAS ALREADY?
POPJ P, ;[1172] YES, DONE
MOVEM T1,UW.S0(R) ;[1172] NO, MUST READ IN THE DATA
HRL T1,LW.S0(R) ;[1172] FORM TRANSFER WORD
PJRST @TB.IN(R) ;[1172] READ IN DATA AND RETURN
;HERE TO WRITE THE UNDEFINED SYMBOL TABLE. THE TABLE IS GENERATED
;BY SCANNING THE GLOBAL SYMBOL TABLE LOOKING FOR UNDEFINED SYMBOLS.
;WE GENERATE ONE RADIX50 PAIR FOR EACH UNDEFINED SYMBOL, AND ADDITIONAL
;PAIRS IF ANY ADDITIVE FIXUPS ARE ENCOUNTERED.
;
;THE ONLY FIXUP TYPES HANDLED ARE ADDITIVE AND RIGHT AND LEFT HALF CHAINED.
;OTHER TYPES, SUCH AS SYMBOL FIXUPS AND POLISH, ARE DISCARDED HERE. THIS
;IS DUE TO LACK OF A SYMBOL TABLE FORMAT SPEC, AND LACK OF DDT SUPPORT.
;
;ENTERED WITH:
;
; P4/ POINTER TO RC BLOCK OF /SYMSEG PSECT
; R/ INDEX TO /SYMSEG AREA, LC OR HC
DOUDFS: MOVE T1,TAB.PT(R) ;[1172] LINK'S ADDRESS OF NEXT WORD
SUB T1,TAB.LB(R) ;[1172] FIND OFFSET IN WINDOW
ADD T1,LW.S0(R) ;[1172] FIND OFFSET IN SEGMENT
ADD T1,LL.S0(R) ;[1172] FORM ABSOLUTE ADDRESS
HRLZM T1,JOB117 ;[1172] STORE IN LH(JOB117) FOR A WHILE
SETZM SYMDEW ;[1172] DON'T NEED EXTRA ROOM FROM SYMOUT
MOVE P2,HT.PRM ;GET HASH SIZE
SKIPE T1,@HT.PTR ;GET POINTER IF NON-ZERO
JRST UDFTRY ;SEE IF A REQUEST
UDFNXT: SOJGE P2,.-2 ;MORE?
JRST UDFDN ;NO
UDFTRY: ADD T1,GS.LB ;ADD IN BASE
MOVE W1,(T1) ;GET FLAGS
TXNN W1,PS.REQ ;GLOBAL REQUEST
JRST UDFNXT ;NO, TRY NEXT SYMBOL
DMOVE W2,1(T1) ;GET SIXBIT SYMBOL & VALUE (REQUEST POINTER)
PUSHJ P,SXBR50 ;CONVERT TO SIXBIT
TXO W2,R5.GLB ;MAKE GLOBAL DEFINITION
PUSHJ P,SYMOUT ;[1172] STORE W2/W3 IN IMAGE
JRST UDFDN ;[1172] NO MORE ROOM, CLOSE UP SHOP
AOS JOB117 ;[1172] ANOTHER ONE STORED, BUMP COUNT
TXNE W1,PS.FXP ;ANY ADDITIVE GLOBAL FIXUPS
JRST UDFGB ;YES, RECREATE THE REQUESTS
JRST UDFNXT ;[1172] NO, LOOK FOR ANOTHER SYMBOL
;THE LOOP BELOW FINDS THE S.FXP TRIPLET IN THE GS AREA, THEN CHASES
;THE CHAIN OF FIXUPS DEPENDING ON THIS SYMBOL THROUGH THE FX AREA,
;WRITING UNDEFINED SYMBOL TABLE ENTRIES FOR APPLICABLE FIXUPS AS IT GOES.
;
;ENTER AT UDFGB.
UDFGB0: TXNE W1,S.LST ;IS THIS THE LAST BLOCK
JRST UDFNXT ;[1172] YES
ADDI T1,.L ;NO, GET NEXT TRIPLET
UDFGB: HRRZ T1,@HT.PTR ;GET POINTER AGAIN
ADD T1,GS.LB ;ADD IN BASE
SKIPG W1,.L(T1) ;GET NEXT FLAG WORD
JRST UDFERR ;MUST HAVE SIGN BIT ON
TXNN W1,S.FXP ;AND A FIXUP
JRST UDFGB0 ;NOT YET
MOVE T1,.L+2(T1) ;[1172] GET VALUE
UDFGB1: ADD T1,FX.LB ;RELOCATE IN FIXUP TABLE
SKIPL W1,0(T1) ;GET FLAGS
JRST UDFERR ;JUST INCASE
TXNE W1,FP.SYM ;[1160] FIXUP BASED ON UNDEFINED SYMBOL?
TXNN W1,FS.FXR!FS.FXL ;[1160] CAN ONLY PUT OUT RH OR LH ADDITIVE
JRST UDFGB2 ;[1160] CAN'T OUTPUT POLISH, SYM FIXUPS, ETC.
DMOVE W2,1(T1) ;GET DATA WORDS
PUSHJ P,SXBR50 ;CONVERT TO RADIX-50
TXO W2,R5.GLB ;MAKE INTO A GLOBAL DEFINITION
TXO W3,R5.FXA ;AND TURN ON ADDITIVE BIT
TXNE W1,FS.FXL ;LEFT HALF?
TXO W3,R5.FXL ;YES
PUSHJ P,SYMOUT ;[1172] WRITE W2/W3 INTO THE IMAGE
JRST UDFDN ;[1172] SPACE EXCEEDED, STOP
AOS JOB117 ;[1172] OK, WROTE ANOTHER ONE
UDFGB2: HRRZ T1,W1 ;GET POINTER
JUMPE T1,UDFNXT ;[1172] ALL DONE IF ZERO
JRST UDFGB1 ;GET NEXT BLOCK
;HERE WHEN AN UNDEFINED SYMBOL WITH PS.FXP SET IS NOT FOLLOWED BY A
;SECONDARY TRIPLET WITH S.FXP SET.
UDFERR: JRST UDFNXT ;[1172] SYMBOL TABLE FOULED UP
;HERE WHEN FINISHED WRITING THE UNDEFINED SYMBOL TABLE.
;SET UP .JBUSY AND RETURN.
UDFDN: SKIPE PAG.S1 ;[1172] PAGING?
SKIPA T1,JOBPTR ;[1172] YES, LOAD CORRECT OFFSET
MOVE T1,LC.LB ;[1172] CODE OFFSET
HRRZ T2,JOB117 ;[1172] GET NUMBER OF UNDEFINED SYMBOLS
IMULI T2,-2 ;[1172] 2 WORDS/SYMBOL, WANT NEGATIVE
HRRM T2,JOB117 ;[1172] FORM ADDR,,-LEN
MOVSS T2,JOB117 ;[1172] FORM -LEN,,ADDR
MOVEM T2,.JBUSY(T1) ;[1172] STORE IN IMAGE
POPJ P, ;[1172] DONE WITH UNDEFINED TABLE, RETURN
;SUBROUTINE TO DELETE THE GS AREA, AND CUT BACK MEMORY IF POSSIBLE.
GSDLT:
IFE TOPS20,< ;[1113] DON'T SHRINK BACK ON TOPS-20
SKIPN .JBDDT(T1) ;SEE IF WE NEED LOCAL SYMBOLS
SKIPE SYMSEG ;EITHER FOR /DEB OR /SYMSEG
JRST GSNRED ;YES, DON'T CUT BACK CORE YET
MOVEI T1,GS.IX-1 ;START AT AREA JUST LOWER
SKIPN TAB.LB(T1) ;FIND HIGHEST AREA IN USE
SOJA T1,.-1 ;WILL GET THERE EVENTUALLY
MOVE T2,TAB.AB(T1) ;GET HIGHEST LOC IN USE IN IT
IORI T2,1777 ;K BOUND
ADDI T2,2000 ;EXTRA K FOR SAFETY
CAML T2,.JBREL ;ANYTHING TO GIVE BACK?
JRST GSNRED ;NO, REDUCED ALREADY
CORE T2, ;DELETE TOP PART
JRST GSNRED ;NEVER CAN HAPPEN
MOVE T2,.JBREL ;GET NEW TOP
SKIPN GS.LB ;[773] GS AREA ALREADY GONE?
JRST GSDLT1 ;[773] YES, DON'T RECREATE IT
MOVEM T2,GS.AB ;RESET TABLE
MOVEM T2,GS.UB
CAMLE T2,GS.LB ;INCASE WE REDUCED IT ALL
JRST E$$RED ;[1174] NO, ALL IS WELL
GSDLT1: MOVEM T2,TAB.UB(T1) ;[773] RESET HIGHEST FREE LOC AGAIN
SETZM GS.LB ;SO XX.ZAP CAN WORK
E$$RED::.ERR. (MS,.EC,V%L,L%I,S%I,RED,<Reducing low segment to >) ;[1174]
.ETC. (COR,.EP,,,,.JBREL)
> ;END OF IFE TOPS20
GSNRED: PUSHJ P,GS.ZAP ;GET RID OF GS
POPJ P, ;[1172] END OF GSDLT
;HERE TO WRITE THE DEFINED SYMBOLS INTO THE IMAGE.
DOLOCS: SKIPE PAG.LS ;[1172] PAGING?
PUSHJ P,SYMINI ;[1172] YES, SET WINDOW TO END OF LS AREA
MOVEI T1,2 ;[1172] NEED ENOUGH WARNING TO PUT A TITLE OUT
MOVEM T1,SYMDEW ;[1172] STORE FOR SYMOUT
MOVE T1,TAB.PT(R) ;[1172] COMPUTE START OF THIS TABLE
SUB T1,TAB.LB(R) ;[1172] OFFSET IN WINDOW TO FIRST AFTER USY
ADD T1,LW.S0(R) ;[1172] OFFSET IN SEGMENT
ADD T1,LL.S0(R) ;[1172] FORM ABSOLUTE ADDRESS FOR RH(.JBSYM)
HRLZM T1,JOB116 ;[1172] STORE IN LH(JOB116) A WHILE
PUSHJ P,PATOUT ;[1172] WRITE THE PAT.. SYMBOL AND MODULE
SKIPN SYMFUL ;[1172] ANY ROOM LEFT?
PUSHJ P,LSLOOP ;[1172] DO THE WORK
;HERE WHEN THE SYMBOLS HAVE BEEN INSERTED INTO THE IMAGE. UPDATE .JBSYM.
SKIPE PAG.S1 ;[1172] PAGING?
SKIPA T1,JOBPTR ;[1172] YES, JOBDAT'S IN DY
MOVE T1,LC.LB ;[1172] NO, IT'S IN LC
HRRZ T2,JOB116 ;[1172] NUMBER OF WORD PAIRS WRITTEN
IMULI T2,-2 ;[1172] WANT -COUNT
HRRM T2,JOB116 ;[1172] ADDR,,-LEN
MOVSS T2,JOB116 ;[1172] -LEN,,ADDR
MOVEM T2,.JBSYM(T1) ;[1172] STORE IN JOBDAT
POPJ P, ;[1172] DONE WITH DOLOCS
;HERE TO MOVE SYMBOLS TO TOP OF CORE
;IF SORTING PUT SORT BUFFER IN AREA GS
SYMINI: SKIPL UW.LS ;[1172] IF -1 THEN SYMBOL TABLE NOT OUTPUT YET
JRST RDSYM ;JUST READ IT BACK IN
MOVE T1,LSYM ;ADRESS OF LAST SYMBOL STORED +1
SUBI T1,1
IORI T1,.IPM ;BLOCK BOUND
HRL T1,LW.LS ;FORM BLT WORD
HRRZM T1,UW.LS ;SIGNAL ALL OF SYMBOLS ON DSK
PUSHJ P,LS.OUT## ;AND OUTPUT IT
;FALL INTO RDSYM TO READ IT BACK
RDSYM: PUSHJ P,FR.CNT## ;[1172] SEE HOW MUCH IS FREE
LSH T1,-1 ;[1172] TAKE HALF OF IT FOR LS WINDOW
ANDCMI T1,.IPM ;[1172] KEEP ON A PAGE BOUND
CAIGE T1,2*.IPS ;[1172] BUT NEED AT LEAST TWO PAGES
MOVEI T1,2*.IPS ;[1172] SO FORCE AT LEAST THAT MANY
MOVE T2,LS.AB ;[1172] CALCULATE CURRENT SIZE OF LS AREA
SUB T2,LS.LB ;[1172] LAST - FIRST
ADDI T2,1 ;[1172] PLUS 1
CAML T2,T1 ;[1172] HAVE LESS THAN WE WANT?
JRST RDSYM2 ;[1172] ALREADY BIG ENOUGH
SUB T1,T2 ;[1172] HOW MUCH MORE WE NEED
MOVEI P1,LS.IX ;[1172] ARRANGE TO GET IT
MOVE P2,T1 ;[1172] HOW MUCH TO GET
PUSHJ P,LNKCOR## ;[1172] SHUFFLE
PUSHJ P,E$$MEF## ;[1174] CANNOT HAPPEN
;NOW READ THE LAST PAGE OF SYMBOLS INTO THE FIRST PAGE OF THE LS AREA.
;LSLOOP WILL QUICKLY FALL OFF THE BOTTOM (READING BACKWARDS), AND
;FILL THE ENTIRE WINDOW WITH THE NEXT LOWER PIECE.
RDSYM2: MOVE T1,LSYM ;[1172] LAST WORD OF SYMBOLS + 1
SUBI T1,1 ;[1172] LAST WORD IN USE
ANDCMI T1,.IPM ;[1172] BOTTOM OF NEW WINDOW
MOVEM T1,LW.LS ;[1172] SET FOR PAGING ROUTINES
ADD T1,LS.AB ;[1172] ADD WINDOW SIZE
SUB T1,LS.LB ;[1172] TO GET TOP OF WINDOW
MOVEM T1,UW.LS ;[1172] STORE FOR PAGING ROUTINES
MOVE T1,LSYM ;[1172] FIRST UNUSED WORD AGAIN
SUB T1,LW.LS ;[1172] HOW FAR INTO WINDOW IT IS
ADD T1,LS.LB ;[1172] FIX IN MEMORY
MOVEM T1,LS.PT ;[1172] SAVE FOR GETSYM
HRLZ T1,LW.LS ;[1172] NOW FILL BOTTOM PAGE
HRR T1,LW.LS ;[1172] REST WILL BE FILLED BY PAGSYM
IORI T1,.IPM ;[1172] ROUND UP TO TOP OF PAGE
PJRST LS.IN## ;[1172] FILL THE WINDOW AND RETURN
;LNKOV2 FILLS THE LS AREA WITH SYMBOL TRIPLETS, ZEROES THE LC AREA,
;AND THEN PUSHJ'S DIRECTLY TO LSLOOP TO CONVERT THE SYMBOLS TO
;RADIX50 AND PUT A RUNTIME SYMBOL TABLE INTO THE LC AREA. IT
;THEN WRITES THE LC AREA TO THE APPROPRIATE PLACE IN THE OVERLAY FILE.
;
;THIS IS AN INITIALIZATION ROUTINE CALLED BY LNKOV2 TO SET THINGS UP
;BEFORE CALLING LSLOOP.
IFN FTOVERLAY,<
LSOVX:: MOVX T1,.INFIN ;[1172] DON'T STOP FOR A SYMBOL LIMIT
MOVEM T1,SYMLIM ;[1172] SINCE NOT REALLY LOADING INTO MEMORY
SETZM SYMDEW ;[1172] DON'T NEED ANY WARNING
SETZM SYMFUL ;[1172] HAVE LOTS OF ROOM FOR SYMBOLS
SETZM JOB116 ;[1172] LSLOOP AOSES THIS FOR EVERY SYMBOL
SKIPN LNKNO. ;[1172] IS THIS THE ROOT?
PJRST PATOUT ;[1172] YES, WRITE PAT.. AND RETURN
MOVNI T1,2 ;[1172] NO, INIT TTLPTR
MOVEM T1,TTLPTR ;[1172] SO FIRST MODULE WILL BE RIGHT
POPJ P, ;[1172] RETURN TO LNKOV2
> ;END IFN FTOVERLAY
;HERE TO WRITE THE PAT.. SYMBOL AND MODULE TO THE SYMBOL TABLE.
PATOUT: MOVE W2,[RADIX50 04,PAT..] ;[1172] NAME
MOVE W3,PATLOC ;[1172] VALUE
PUSHJ P,SYMOUT ;[1172] WRITE IT OUT
JRST [HRLI W3,-2 ;[1172] SYMBOL WON'T FIT, JUST WRITE NAME
SETZM SYMDEW ;[1172] IF IT WILL FIT
JRST PATOU2] ;[1172] RE-JOIN COMMON CODE
AOS JOB116 ;[1172] A SYMBOL PAIR SUCCESSFULLY WRITTEN
HRLI W3,-4 ;[1172] FOUR WORDS IN THIS MODULE
PATOU2: MOVE T1,TAB.PT(R) ;[1172] BEFORE WRITING THE TITLE,
SUB T1,TAB.LB(R) ;[1172] FIGURE OUT WHERE IT GOES
ADD T1,LW.S0(R) ;[1172] AS AN OFFSET INTO THE SEGMENT
MOVEM T1,TTLPTR ;[1172] SAVE FOR LTITLE
TLZ W2,740000 ;[1172] MAKE 0,PAT.. BE THE TITLE
PUSHJ P,SYMOUT ;[1172] WRITE THE TITLE
CAIA ;[1172] OOPS! SEE WHAT WENT WRONG
JRST PATOU4 ;[1172] OK, NOW GO WRITE THE REAL SYMBOLS
SKIPN SYMDEW ;[1172] 4,PAT.. FAILED ABOVE? (DON'T USE SYMFUL)
JRST [SETZM JOB116 ;[1172] YES, THERE WON'T BE A SYMBOL TABLE
POPJ P,] ;[1172] JUST RETURN
SETZM SYMDEW ;[1172] USE OUR RESERVE FOR PAT..'S TITLE
PUSHJ P,SYMOUT ;[1172] WRITE IT
JFCL ;[1172] CAN'T HAPPEN
PATOU4: AOS JOB116 ;[1172] ANOTHER SYMBOL WRITTEN
POPJ P, ;[1172] DONE
LSLOOP::PUSHJ P,GETSYM ;GET SYMBOL IN W1,W2,W3
POPJ P, ;ALL DONE
JUMPGE W1,LSLOOP ;IGNORE ALL EXTENDED BLOCK
TXNE W1,PT.TTL ;SPECIAL IF TITLE BLOCK
JRST LTITLE ;NEED TO KEEP POINTERS ETC
SKIPE SYMFUL ;[1172] SKIPPING FOR LAST MODULE NAME?
JRST LSLOOP ;[1172] YES, REJECT ALL OTHER RANDOM SYMBOLS
TXNE W1,PT.SYM ;ONLY WANT REAL SYMBOLS
TXNE W1,PS.MDF ;BUT NOT MULTIPLE DEFINITION
JRST LSLOOP ;MUST BE SOME THING ELSE
PUSHJ P,SXBR50 ;CONVERT TO RADIX-50
TXNE W1,PS.GLB ;GLOBAL?
TXO W2,R5.GLB ;YES
TXNE W1,PS.COM ;COMMON?
JRST LSLUPC ;YES, NEEDS TWO SYMBOLS
TXNE W1,PS.LCL ;THEN LOCAL?
TXO W2,R5.LCL ;YES
TXNE W1,PS.DDT ;NO DDT OUTPUT?
TXO W2,R5.DDT ;YES SET BIT
LSLUP1: PUSHJ P,SYMOUT ;PUT SYMBOL IN CORE
JRST [SETZM SYMDEW ;[1172] GO INTO FIND MODULE NAME MODE
JRST LSLOOP] ;[1172] START THE HUNT
AOS JOB116 ;[1172] ANOTHER SYMBOL STORED
JRST LSLOOP ;AND BACK FOR MORE
LSLUPC: MOVEI T1,4 ;[1172] NEED FOUR WORDS OR NOTHING
MOVEM T1,SYMDEW ;[1172] SO BUMP WARNING LEVEL
PUSHJ P,SYMOUT ;OUTPUT IT
JRST [SETZM SYMDEW ;[1172] WON'T BOTH FIT
JRST LSLOOP] ;[1172] CLOSE OFF TABLE AND STOP
AOS JOB116 ;[1172] ANOTHER PAIR OUT
MOVEI T1,2 ;[1172] PUT SYMOUT CUTOFF BACK
MOVEM T1,SYMDEW ;[1172] NEXT PAIR GUARANTEED TO FIT
PUSH P,W3 ;SAVE ADDRESS
MOVX T1,S.COM ;PART WE WANT
PUSHJ P,GETAST ;GET REST OF SYMBOL
JRST [POP P,W3 ;TOO BAD
JRST LSLOOP] ;JUST IGNORE
PUSHJ P,SXBR50 ;IN RADIX50
TXO W2,R5.DDT!R5.GLB ;CODE 44
POP P,T1 ;GET ADDRESS
HRL T1,W3 ;LENGTH ,, ADDRESS
MOVE W3,T1 ;...
JRST LSLUP1 ;OUTPUT IT
;HERE ON A TITLE IN THE LS AREA.
LTITLE: TXNE W1,PT.PSC ;[1132] JUST A PSECT DEFINITION?
JRST LSLOOP ;[1132] YES, DON'T PUT IN SYMBOL TABLE
PUSHJ P,SXBR50 ;CONVERT TO RADIX-50
TXNE W1,PT.BLK ;ONLY A FAIL BLOCK HEADER?
JRST BTITLE ;YES
MOVE T2,TTLPTR ;GET ADDRESS OF LAST PROG
HRRZ T1,TAB.PT(R) ;GET THIS ADDRESS
SUB T1,TAB.LB(R) ;MINUS OFFSET
ADD T1,TAB.LW(R) ;PLUS BASE OF WINDOW
MOVEM T1,TTLPTR ;SAVE FOR NEXT
SUB T1,T2 ;GET DIFFERENCE
MOVN T1,T1 ;NEGATE
HRL W3,T1 ;FIXUP POINTER
PUSH P,W2 ;SAVE SYMBOLS
PUSH P,W3
TTLLUP: MOVX T1,S.TTL!S.SEG ;FLAGS
PUSHJ P,GETAST ;GET EXTENSION TRIPLET
SETZB W2,W3 ;ONLY HERE IF DEFINED BY /SWITCH
SKIPE W3 ;IF ANY HIGH SEG STUFF
MOVE W2,W3 ;USE IT
POP P,W3 ;GET W3 BACK
HLR W3,W2 ;FIX IT UP
POP P,W2
PUSHJ P,SYMOUT ;OUTPUT PSEUDO SYMBOL
JRST [SETZM SYMDEW ;[1172] USE THE RESERVE TO STORE THIS TITLE
JRST .-1] ;[1172] TRY AGAIN
AOS JOB116 ;[1172] COUNT ANOTHER SYMBOL PAIR
SKIPE SYMFUL ;[1172] WAS THIS OUR LAST TITLE?
POPJ P, ;[1172] YES, QUIT, SINCE NO MORE ROOM
JRST LSLOOP ;RETURN
BTITLE: SKIPE SYMFUL ;[1172] ROOM FOR THIS?
JRST LSLOOP ;[1172] NO, DON'T STORE IT
TXO W2,R5.LCL!R5.GLB ;MAKE RADIX50 14,SYM
HRRZ W3,W3 ;BLOCK LEVEL ONLY
JRST LSLUP1 ;AND TREAT AS LOCAL SYMBOL
;HERE TO GET NEXT SYMBOL BLOCK
;CALLED BY
; PUSHJ P,GETSYM
;RETURNS
;W1, W2, W3 WITH SYMBOL INFO
;USES T1
;READS SYMBOL TABLE IN REVERSE ORDER
GTSYM1: PUSHJ P,PAGSYM ;SEE IF PAGING
POPJ P, ;NO, ALL DONE
;FALL INTO GETSYM
GETSYM: MOVNI T1,3 ;BACKUP POINTET TO
ADD T1,LS.PT ;GET NEXT TRIPLET
CAMGE T1,LS.LB ;DON'T GO TOO FAR
JRST GTSYM1 ;SEE IF PAGING
MOVEM T1,LS.PT ;SAFE TO STORE NOW
TMOVE W1,0(T1) ;FLAGS, SYMBOL, VALUE
JRST CPOPJ1 ;SKIP RETURN
;HERE TO READ MORE SYMBOLS IF THEY ARE ON DSK
PAGSYM: SKIPE UW.LS ;NEVER WERE
SKIPN LW.LS ;WERE BUT ALL DONE
POPJ P, ;IN EITHER CASE JUST RETURN CPOPJ
HRLZ T1,LS.LB ;[1172] MOVE FIRST BLOCK OF SYMBOLS
HRR T1,LS.AB ;[1172] UP TO LAST BLOCK OF LS AREA
ANDCMI T1,.IPM ;[1172] NOW HAVE SRC,,DEST
BLT T1,@LS.AB ;[1172] MOVE THE DATA
MOVE T1,LS.AB ;[1172] CHECK TO SEE IF LAST TIME
ANDCMI T1,.IPM ;[1172] ACCOUNT FOR PAGE WE KEPT
MOVEI T2,.IPM ;[1172] MASK FOR PAGE OFFSET
ANDM T2,LS.PT ;[1172] OFFSET TO CURRENT SYMBOL
ADDM T1,LS.PT ;[1172] MOVE POINTER TO LAST PAGE OF AREA
SUB T1,LW.LS ;[1172] BOTTOM ADDR IF WE FINISHED THIS TIME
SUBI T1,1 ;[1172] GET LOCATION BELOW FIRST USED
CAML T1,LS.LB ;[1172] LS AREA TOO BIG (LAST TIME)?
PUSHJ P,GBCK.L## ;[1172] YES, GET RID OF BOTTOM PART
MOVE T1,LW.LS ;[1172] GET OLD LOWER WINDOW ADDRESS
IORI T1,.IPM ;[1172] THE END OF THAT PAGE
MOVEM T1,UW.LS ;[1172] FORM NEW UPPER WINDOW
ADD T1,LS.LB ;[1172] SUBTRACT LENGTH OF AREA
SUB T1,LS.AB ;[1172] TO FORM LOWER WINDOW
MOVEM T1,LW.LS ;[1172] STORE FOR PAGING ROUTINES
HRLZ T1,T1 ;[1172] NOW TO READ IN THE DATA
HRR T1,UW.LS ;[1172] TRANSFER WORD TO WHOLE AREA
SUBI T1,.IPS ;[1172] BUT WE ALREADY HAVE LAST PAGE
PUSHJ P,LS.IN ;[1172] FILL UP THE AREA
JRST CPOPJ1 ;[1172] SKIP RETURN
;HERE TO GET ASSOCIATED SECONDARY TRIPLET
;CALLED BY
; MOVE T1,FLAGS
; PUSHJ P,GETAST
;RETURNS
;+1 FAILED
;+2 SUCCESS
;USES T1, T2, T3
;SETS UP W1, W2, W3
GETAST: MOVE T2,LS.PT ;GET POINTER
GETNAS: ADDI T2,.L ;ENTER HERE WITH T2 SETUP
CAMLE T2,LS.AB ;STILL IN CORE?
JRST FNDNIC ;NOT IN CORE
SKIPGE T3,(T2) ;GET FLAGS
POPJ P, ;FOUND A PRIMARY (FAILED)
XOR T3,T1 ;IFF ALL BITS MATCH
TXZ T3,S.LST ;IGNORE THIS BIT HOWEVER
JUMPN T3,GETNAS ;TRY AGAIN
TMOVE W1,(T2) ;FLAGS, SYMBOL, VALUE
CPOPJ1: AOS (P)
CPOPJ: POPJ P,
FNDNIC: SKIPN UW.LS
POPJ P, ;ALL DONE
E03CNW::.ERR. (MS,.EC,V%L,L%F,S%F,CNW) ;[1174]
.ETC. (STR,,,,,,<FNDNIC>)
;SXBR50 -- SUBROUTINE TO CONVERT SIXBIT TO RADIX-50
;CALLED BY
; MOVE W2,SIXBIT WORD
; PUSHJ P,SXBR50
;RETURN
; RADIX-50 IN W2
;USES T1, T2
SXBR50: MOVE T2,W2 ;GET SIXBIT SYMBOL
SETZ W2, ;WHERE TO STORE RADIX50 SYMBOL
SETZ T1, ;CLEAR RECEIVING ACC
LSHC T1,6 ;GET NEXT CHAR
IMULI W2,50 ;MULTIPLE BY 50
ADD W2,SXBTAB(T1) ;ADD IN NEW CHAR
JUMPN T2,.-4 ;NOT DONE YET
POPJ P,
DEFINE SXBCHR (CHR)<
IRPC CHR,<
RADIX50 0,CHR
>>
XALL
SXBTAB: SXBCHR ( $% . 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ )
SALL
;HERE TO WRITE THE RADIX-50 SYMBOL IN W2/W3 TO THE IMAGE.
;RETURNS NON-SKIP, MESSAGE PRINTED, IF SYMBOL WON'T FIT BELOW SYMLIM.
;SYMBOL WON'T FIT IF IT IS WITHIN C(SYMDEW) WORDS OF PASSING SYMLIM.
SYMOUT: MOVE T1,TAB.PT(R) ;[1172] ADDRESS TO STORE INTO NEXT
AOS T2,T1 ;[1172] LAST ADDRESS THIS SYMBOL WILL USE
SUB T2,TAB.LB(R) ;[1172] CONVERT TO OFFSET IN SEGMENT
ADD T2,TAB.LW(R) ;[1172] (USUALLY SAME AS VIRTUAL ADDRESS)
ADD T2,LL.S0(R) ;[1172] MAKE SURE IT'S A VIRTUAL ADDRESS
ADD T2,SYMDEW ;[1172] RESPECT DISTANT EARLY WARNING FACTOR
CAMG T2,SYMLIM ;[1172] WOULD WE STORE BEYOND LEGAL BOUNDS?
JRST SYMOU2 ;[1172] NO, CONTINUE
SKIPE SYMFUL ;[1172] ALREADY ISSUED A MESSAGE?
POPJ P, ;[1172] YES, DONT SAY IT AGAIN
SETOM SYMFUL ;[1172] REMEMBER FOR NEXT TIME & CALLERS
E$$ISS::.ERR. (MS,.EC,V%L,L%W,S%W,ISS,<Insufficient space for symbol table after psect >) ;[1174]
.ETC. (SBX,.EP!.EC,,,,SSGNAM)
.ETC. (STR,,,,,,< -- table truncated>)
POPJ P, ;[1172] ERROR RETURN
;HERE IF NOT PAST SYMLIM. CHECK TO SEE IF THE AREA/WINDOW IS BIG ENOUGH.
SYMOU2: CAMG T1,TAB.AB(R) ;[1172] STILL ROOM IN THE AREA?
AOJA T1,SYMOU8 ;[1172] YES, GO STORE THE SYMBOL
SETOM LS.PP ;[1172] DON'T SHRINK THE LS AREA
SPUSH <P1,P2> ;[1216] PRESERVE OVER LNKCOR
MOVE P1,R ;[1172] SEGMENT TO EXPAND
MOVEI P2,.IPS ;[1172] BY ONE PAGE
PUSHJ P,LNKCOR## ;[1172] EXPAND
PUSHJ P,E$$MEF## ;[1174] SHOULD NEVER GET HERE
SPOP <P2,P1> ;[1216] RESTORE SACRED COWS
SETZM LS.PP ;[1172] RESTORE
IFN FTOVERLAY,<
SKIPL LNKMAX ;[1172] LSLOOP CALLED FROM LNKOV2?
SKIPN PAG.S0(R) ;[1172] AND LNKCOR STARTED AREA PAGING?
CAIA ;[1172] NO
PUSHJ P,E$$MEF## ;[1174] YES, LNKOV2 CAN'T HANDLE THAT
> ;END IFN FTOVERLAY
PUSHJ P,CHKPAG ;[1172] FIX JOBDAT IF JUST STARTED PAGING
SKIPN TAB.PG(R) ;[1172] AREA NOW PAGING?
JRST SYMOUT ;[1172] NO, GO TRY AGAIN
MOVE T1,LW.S0(R) ;[1172] YES, MUST UPDATE UW
ADD T1,TAB.AB(R) ;[1172] LNKCOR SOMETIMES DOES
SUB T1,TAB.LB(R) ;[1172] BUT SOMETIMES IT DOESN'T
MOVEM T1,UW.S0(R) ;[1172] SO MAKE SURE IT'S RIGHT
ANDCMI T1,.IPM ;[1172] FIRST ADDRESS IN PAGE WE JUST ADDED
CAML T1,HC.S0(R) ;[1172] ANY DATA FURTHER ON IN OVERFLOW FILE?
JRST SYMOUT ;[1172] NO, JUST LEAVE NEW PAGE ZERO
HRLZ T1,T1 ;[1172] YES, MUST FILL IN NEW PAGE
HRR T1,UW.S0(R) ;[1172] OTHERWISE WE LOSE DATA
PUSHJ P,@TB.IN(R) ;[1172] DO THE I/O
JRST SYMOUT ;[1172] AND TRY AGAIN
;HERE WHEN ALL IS OK TO STORE THE NEW SYMBOL.
SYMOU8: DMOVEM W2,-2(T1) ;[1172] DO THE STORE
MOVEM T1,TAB.PT(R) ;[1172] UPDATE THE PT FOR NEXT TIME
IFN FTOVERLAY,<
SKIPE T1,RT.PT ;RELOCATABLE?
CAMN T1,RT.LB ;MAYBE, IS IT?
JRST CPOPJ1 ;[715] NO, SKIP RETURN
IBP RT.PT ;SYMBOL IS NOT
TXNN W1,PS.REL ;IS IT RELOCATABLE?
TDZA T1,T1 ;NO
MOVEI T1,1 ;YES
IDPB T1,RT.PT ;SET BIT
>
JRST CPOPJ1 ;[715] SKIP RETURN
;HERE FOR OLD FORM SYMBOLS (RADIX-50)
;IF IN CORE WRITE THEM OUT WITH THREE INFORMATION WORDS AT FRONT
;HEADER, .JBSYM (116) AND .JBUSY (117)
;HEADER IS 776(TYPE) ,, LENGTH
;OTHER TWO WORDS ARE RELATIVE TO ZERO
;.JBSYM MUST HAVE A NEGATIVE LEFT HALF
;.JBUSY IS ZERO IF NO UNDEFINED SYMBOLS
OLDSYM: MOVEI T1,MC ;USE MAP CHAN INCASE PAGING LC
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%SC ;POINT TO CORRECT DATA
MOVEM T1,IO.PTR+MC
PUSHJ P,DVCHN.##
MOVSI T2,(Z MC,) ;RESET CHAN #
MOVEM T2,I.CHN(T1) ;SINCE %SC IS THERE CURRENTLY
HLRO T2,JOB116 ;NUMBER OF SYMBOLS
MOVM T2,T2
LSH T2,-.DBS2W ;[650] INTO BLOCKS (ASSUME FEW UNDEFS)
MOVEM T2,I.EST(T1)
MOVE T2,VERNUM ;GET VERSION OF CORE IMAGE
SKIPN I.VER(T1) ;SKIP IF SET BY SWITCH
MOVEM T2,I.VER(T1) ;NO, SO SET IT
PUSHJ P,DVNAM.## ;MAKE SURE NAME SETUP
PUSHJ P,DVOPN.## ;INIT DEV
PUSHJ P,DVENT.## ;DO ENTER
;NOW TO STORE THREE INFO WORDS
HLRE T1,JOB116 ;NO. OF DEFINED SYMBOLS
HLRE T2,JOB117 ;NO. OF UNDEFS
MOVM T1,T1 ;+
MOVM T2,T2
ADDI T2,2(T1) ;PLUS TWO EXTRA WORDS
HRLI T2,776 ;BLOCK TYPE FOR LINK
SKIPN T1,JOB117 ;.JBUSY IF NON-ZERO
MOVE T1,JOB116 ;OTHERWISE .JBSYM
HRRZ T1,T1 ;REMOVE NEG LEFT HALF
SUB T1,LL.S0(R) ;REMOVE ORIGIN
SUB T1,LW.S0(R) ;INCASE PAGING
ADD T1,TAB.LB(R) ;FIX IN CORE
;NOW PUT HEADER WORDS IN CORE IMAGE SO WE CAN DUMP IT ALL WITH
;ONE IOWD. PUSH REAL CONTENTS OF THOSE LOCATIONS (USUALLY 0) FIRST,
;THEN RESTORE THEM LATER
SUBI T1,3 ;BACKUP 3
PUSH P,0(T1) ;SAVE WORDS INCASE NOT ZERO
PUSH P,1(T1)
PUSH P,2(T1)
MOVEM T2,0(T1) ;SAVE HEADER
HLLZ T2,JOB117 ;COPY INFO WORDS
MOVEM T2,2(T1) ;TO NEXT 2 LOCS
HLRE T2,T2 ;GET - LENGTH (OR 0)
MOVM T2,T2 ;+
HLL T2,JOB116 ;-LENGTH,,OFFSET
MOVEM T2,1(T1) ;FIRST INFO WORD
HLRE T2,JOB116 ;FIND TOTAL LENGTH TO OUTPUT
HLRE T3,JOB117 ;.JBSYM+.JBUSY
ADD T2,T3
SUBI T2,3 ;+3 INFO WORDS
HRLZ T2,T2 ;-LENGTH
HRRI T2,-1(T1) ;IOWD LENGTH,ADDRESS
SETZ T3, ;TERMINATE
OUT MC,T2 ;DUMP IT
JRST [POP P,2(T1) ;RESTORE DATA
POP P,1(T1)
POP P,0(T1)
PJRST DVRLS.##] ;CLOSE FILE
POP P,2(T1) ;RESTORE DATA
POP P,1(T1)
POP P,0(T1)
E$$OES::PUSH P,[MC] ;[1174]
.ERR. (ST,,V%L,L%W,S%W,OES,<Output error on symbol file, file closed, load continuing>)
POPJ P,
;HERE TO SAVE NEW FORM SYMBOL TABLE
;IF ALL IN CORE JUST OPEN AND WRITE OUT
;IF ON DSK EITHER RENAME OR COPY THEM
SAVSYM: PUSHJ P,.SAVE1## ;NEED AN AC
CAIN T1,1 ;SIXBIT SYM FILE WANTED?
MOVEI P1,LS.IX ;YES, STORED IN LS AREA
CAIN T1,2 ;HOW ABOUT ALGOL .SYM FILE?
MOVEI P1,AS.IX ;YES, USE AS AREA INSTEAD
SKIPN TAB.UW(P1) ;PAGING?
JRST WRTSYM ;NO
MOVE T1,TAB.AB(P1) ;MAKE SURE UW.XX IS OK
SUB T1,TAB.LB(P1) ;MIGHT BE -1 IF LS AREA
ADD T1,TAB.LW(P1) ;NOW HAVE HIGHEST LOC IN CORE
MOVEM T1,TAB.UW(P1) ;UPDATE UW.XX
SETCM T1,TAB.LB(P1) ;ALSO MAKE SURE DISK FILE IS OK
ADD T1,TAB.PT(P1) ;IN CASE NEVER OUTPUT BEFORE
JUMPE T1,.+4 ;FORGET IT IF NOTHING TO OUTPUT
ADD T1,TAB.LW(P1) ;NOTE WE'RE GETTING EXACT WORD CNT
HRL T1,TAB.LW(P1) ;ALGOL 7 NEEDS .RBSIZ EXACT
PUSHJ P,@TB.OUT##(P1) ;SO USE XX.PT INSTEAD OF XX.AB
MOVE T1,TAB.AB(P1) ;NOW READ IN FRONT OF FILE
SUB T1,TAB.LB(P1) ;SO CAN SET UP 10??,,COUNT
SETZM TAB.LW(P1) ;?W.?S MUST BE UP TO DATE
MOVEM T1,TAB.UW(P1) ;FOR FOLLOWING CALL
PUSHJ P,@TB.IN##(P1) ;AS FIRST WORD OF FILE
CAIE P1,AS.IX ;ALGOL?
JRST SAVSY0 ;NO, DO IT FOR LS AREA
MOVE T2,ASYM ;YES, GET SYMBOL COUNT
HRLI T2,1044 ;AND BLOCK TYPE
JRST SAVSY1 ;AND CONTINUE
SAVSY0: MOVE T2,LSYM ;COUNT FOR LS AREA
HRLI T2,1700 ;AND BLOCK TYPE
SAVSY1: SUBI T2,1 ;WORDS FOLLOWING IS 1 LESS
MOVEM T2,@TAB.LB(P1) ;STORE COUNT WORD
PUSHJ P,@TB.OUT##(P1) ;AND UPDATE FILE
MOVEI T1,SC ;FROM CHAN#
CAIN P1,AS.IX ;UNLESS AS AREA
MOVEI T1,AC ;IN WHICH CASE ALGOL CHANNEL
MOVE T2,IO.PTR+%SC ;TO CHANNEL
PUSHJ P,DVPRO. ;GET PROTECTION RIGHT
MOVEI T2,%SC ;TO CHAN#
MOVE T3,IO.PTR+%SC ;GET POINTER TO NEW FILE
MOVE T4,VERNUM ;GET VERSION OF PROGRAM
SKIPN I.VER(T3) ;UNLESS ALREADY SET BY SWITCH...
MOVEM T4,I.VER(T3) ;SAVE FOR ENTER
PJRST DVMOV. ;GO COPY PAGED FILE TO SYMBOL FILE
WRTSYM: MOVEI T1,DC ;USE THIS CHAN
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%SC ;HIDE DATA BLOCK HERE
MOVEM T1,IO.PTR+DC ;NOW BRING IT FORTH
PUSHJ P,DVCHN.## ;PUT ADDRESS OF BLOCK IN T1
MOVSI T2,(Z DC,) ;RESET CHAN # IN AC FIELD
MOVEM T2,I.CHN(T1) ;SINCE %SC IS THERE CURRENTLY
CAIE P1,AS.IX ;ALGOL?
JRST WRTSY0 ;NO, SETUP 1ST WORD FOR LS
MOVE T3,ASYM ;YES, SETUP COUNT WORD
HRLI T3,1044 ;AND BLOCK TYPE
JRST WRTSY1 ;CONTINUE
WRTSY0: MOVE T3,LSYM ;LS AREA COUNT
HRLI T3,1700 ;BLOCK TYPE FOR TRIPLET SYMBOLS
WRTSY1: HRRZ T2,T3 ;SAVE COUNT FOR ESTIMATE
SUBI T3,1 ;WORDS FOLLOWING IS 1 LESS
MOVEM T3,@TAB.LB(P1) ;SAVE WORD COUNT IN AREA
LSH T2,-.DBS2W ;[650] INTO BLOCKS
MOVEM T2,I.EST(T1) ;WE NEED THIS MUCH
MOVE T2,VERNUM ;GET VERSION OF CORE IMAGE
SKIPN I.VER(T1) ;SKIP IF SET BY SWITCH
MOVEM T2,I.VER(T1) ;NO, SO SET IT
PUSHJ P,DVNAM.## ;MAKE SURE NAME IS SET UP
PUSHJ P,DVOPN.## ;INIT DEVICE
PUSHJ P,DVENT.## ;ENTER FILE
;NOW FOR OUTPUT
WRTSY2: MOVE T1,TAB.LB(P1) ;GET BOTTOM ADDR IN CORE
SUB T1,TAB.PT(P1) ;-LENGTH
HRLZ T1,T1 ;-LENGTH,,0
HRR T1,TAB.LB(P1) ;FIRST ADDR OF BUFFER
HRRI T1,-1(T1) ;-LENGTH,,ADDR-1
SETZ T2,
OUT DC,T1 ;OUTPUT IT
PJRST DVRLS.## ;PAGING NO LONGER HANDLED HERE
E01OES::PUSH P,[DC] ;[1174]
.ERR. (ST,,V%L,L%W,S%W,OES)
POPJ P,
;HERE TO SET UP THE REST OF THE JOBDAT AREA. ENTER WITH P1 POINTING TO JOBDAT
;AREA AND P2 TO VESTIGIAL JOBDAT (0 IF NO HIGH SEGMENT).
JOBSET: SKIPE T2,HC.S1 ;GET HIGHEST DATA LOCATION LOADED
SUBI T2,1 ;MAKE IT HIGHEST LOC LOADED
IFN FTOVERLAY,<
SKIPL LNKMAX ;LOADED ANY OVERLAYS?
SKIPN T1,JOB116 ;AND SAVED SYMBOLS?
JRST .+4 ;NO
HLRE T2,T1 ;-LENGTH
MOVM T2,T2
ADDI T2,-1(T1) ;HIGHEST LOCATION
>
HRLZM T2,.JBCOR(P1) ;PUT HIGHEST LOC IN LEFT HALF
HRRZ T2,HL.S1 ;GET HIGHEST LOC REQUIRED
HRL T2,STADDR ;GET STARTING ADDRESS
MOVSM T2,.JBSA(P1) ;SET .JBSA AND .JBFF
HRRZM T2,.JBFF(P1) ;INCASE RESET NOT DONE FIRST
IOR. T2,.PGSIZ ;INCLUDE ALL OF THIS PAGE
HRRZM T2,.JBREL(P1) ;SET .JBREL
MOVSI T2,(HALT) ;PUT A HALT IN .JB41
SKIPN .JB41(P1) ;UNLESS ALREADY SETUP
MOVEM T2,.JB41(P1)
MOVE T2,.JBSYM(P1) ;GET SYMBOL TABLE POINTER
HRRZ T1,T2 ;GET POINTER
JUMPE P2,JOBST0 ;NO HIGH SEG POSSIBLE
CAML T1,LL.S2 ;SEE IF IN HIGH SEG
MOVEM T2,.JBHSM(P2) ;STORE IN HIGH SEG DATA AREA
SKIPE T1,HL.S2 ;GET HIGHEST LOC +1
SUBI T1,1 ;HIGHEST LEGAL ADDRESS
ADD T1,LL.S2 ;PLUS ORIGIN
IOR. T1,.PGSIZ ;PUT ON PAGE BOUND
SKIPN T2,HL.S2 ;[650] LENGTH TO SAVE
JRST JOBST1 ;[650] NONE?
SKIPN .JBDDT##(P1) ;[650] DDT LOADED?
JRST JOBST1 ;[650] NO, NUMBER IS OK
SUBI T2,1 ;[650] YES, BE LIKE MONITOR
IOR. T2,.PGSIZ ;[650] ROUND UP TO TOP OF PAGE
ADDI T2,1 ;[650] THENCE TO BOTTOM OF NEXT
JOBST1: HRL T1,T2 ;[650] LENGTH TO SAVE,,HIGHEST ADDR
MOVEM T1,.JBHRL(P1) ;LENGTH,,HIGHEST ADDRESS
JOBST0: MOVE T1,.JBERR ;GET NO OF PREVIOUS ERRORS
MOVEM T1,.JBERR(P1) ;COUNT AS EXECUTION ERRORS
MOVEM T1,ERRNO ;PROHIBIT EXECUTION IF NON-ZERO
; ..
; ..
;COMPUTE ADDRESS AT WHICH TO START PROGRAM. IF A DEBUGGER IS LOADED, THIS IS NOT
;NECESSARILY THE MAIN PROGRAM'S START ADDRESS, BUT DEPENDS ON THE DEBUGGER.
SETZ T1, ;[1144] ASSUME WE DON'T START PROGRAM
SKIPE EXECSW ;GO INTO EXECUTION?
MOVE T1,STADDR ;YES, ASSUME .JBSA
HRRZ T2,DEBUGSW ;[1144] IF DEBUGGING, DEBUGGER'S START ADDRESS
SKIPGE DEBUGSW ;[1144] TAKES PRIORITY SO
MOVE T1,@STLOCN(T2) ;[1144] FIND IT
HRRM T1,EXECSW ;IN ANY CASE STORE BACK IN EXECSW
POPJ P,
;TABLE OF WHERE TO START FOR EACH DEBUGGER.
DEFINE KEYMAC(A,B)<
XALL ;;[1144] GIVE A GOOD LISTING
IFIDN <A><DEB>,< ;;[1144] SELECT ONLY DEBUGGING KEYWORDS
%%1==-1 ;;[1144] SKIP DUMMY ENTRY
IRP B,< ;;[1144] CHECK EACH KEYWORD
IFGE %%1,< ;;[1144] THAT IS NOT THE DUMMY
IFN <%%1&1>,< ;;[1144] AND IS A DEGUGGER NAME
%%2==0 ;;[1144] ASSUME WE WON'T FIND A DEBUGGER
IFN TOPS20,< ;;[1144] TOPS-20 UDDT IS SPECIAL
IFIDN <B><DDT>,< ;;[1144] CHECK FOR DDT DEBUGGER
[770000] ;UDDT STARTS AT 770000
%%2==1 ;;[1144] REMEMBER WE FOUND A DEBUGGER
>
>
IFIDN <B><FORDDT>,< ;;[1144] FORDDT IS SPECIAL
STADDR ;FORDDT FORCES START ADDRESS TO ITSELF
%%2==1 ;;[1144] REMEMBER WE FOUND A DEBUGGER
>
IFIDN <B><COBDDT>,< ;;[1144] COBDDT IS SPECIAL
STADDR ;COBDDT GETS CONTROL FROM COBOL PROGRAM
%%2==1 ;;[1144] REMEMBER WE FOUND A DEBUGGER
>
IFE %%2,< ;;[1144] IF IT WASN'T ABOVE DEBUGGERS
.JBDDT(P1) ;OTHER DEBUGGERS SET .JBDDT
>
>
>
%%1==%%1+1 ;;[1144] ADVANCE TO NEXT ENTRY
>
>
PURGE %%1,%%2 ;;[1144] CLEAN UP AFTERWARD
SALL ;;[1144] ..
>
STLOCN: KEYWORDS
;HERE TO SETUP REST OF VESTIGIAL JOBDAT AREA
;ENTER WITH P1 POINTING TO JOBDAT AREA
HJBSET: JUMPE P2,CPOPJ ;DON'T NEED TO DO THIS IF NO HIGH SEG
HRRZ T1,HL.S2 ;GET HIGHEST HIGH SEG LOCATION+1
SKIPE .JBDDT(P1) ;IF DDT LOADED
SOJA T1,[IOR. T1,.PGSIZ ;INCLUDE ALL OF THIS PAGE
AOJA T1,.+1] ;IN LENGTH
HRL T1,.JBREN(P1) ;GET .JBREN
MOVSM T1,JOBHRN(P2) ;SET BOTH HALVES OF JOBHRN
MOVE T1,.JBSA(P1) ;PUT .JBSA
MOVEM T1,JOBHSA(P2) ;IN HIGH SEG
MOVE T1,.JB41(P1)
MOVEM T1,JOBH41(P2)
MOVS T1,.JBCOR(P1)
SKIPN .JBDDT(P1) ;TEST FOR RARE CASE OF DDT, SYMBOLS AND CODE
JRST .+3 ; ALL IN HIGH SEGMENT
TRNN T1,-140 ;TRUE IF HIGHEST LOC IS 137 OR LESS
ADDI T1,1 ;IF SO MAKE IT 140 IN HIGH SEG
MOVSM T1,.JBHCR(P2) ; SO WE LOAD LOW
MOVE T1,.JBVER(P1)
MOVEM T1,.JBHVR(P2)
SKIPE T1,RUNAME ;GET PROGNAM
JRST .+3 ;SET
SKIPN T1,SSNAME ;IF NOT TRY SAVE FILE NAME
MOVE T1,LODNAM ;USE DEFAULT IF NOT SET
MOVEM T1,.JBHNM(P2) ;INTO HIGH SEG
MOVE T1,HL.S1 ;HIGHEST LOC +1 IN LOW SEG
SUBI T1,1
IOR. T1,.PGSIZ ;ROUND UP TO PAGE BOUNDARY
ADDI T1,1 ;NEXT PAGE
CAMGE T1,LL.S2 ;GREATER THAN HI-ORG?
MOVE T1,LL.S2 ;NO
LSH T1,-9 ;PAGE #
HRLZM T1,JOBHSO(P2) ;STORE IN HIGH
HRRZM T1,.JBHSO(P1) ;AND STORE
POPJ P,
;HERE TO SEE IF WE JUST STARTED PAGING AND IF SO, COPY
;JOBDAT OR VESTIGAL JOBDAT INTO DY AREA, SO WE CAN ALWAYS
;REFERENCE THEM EVEN IF THEY ARE PAGED OUT.
CHKPAG: SKIPE PAG.S1 ;IF WE ARE PAGING
SKIPE JOBPTR ;FOR FIRST TIME
CAIA ;NO
PUSHJ P,RDJBL ;MUST SETUP JOB DATA AREA
SKIPE PAG.S2 ;SAME FOR HIGH SEG
SKIPE JBHPTR
POPJ P, ;[1172] DONE
PUSHJ P,RDJBH ;SET UP JOBDAT IN HIGH
POPJ P,
;HERE TO GET RID OF VARIOUS AREAS
GS.ZAP: MOVEI T1,GS.IX ;GET AREA
PJRST XX.ZAP## ;GENERAL ROUTINE
FX.ZAP: MOVEI T1,FX.IX
PJRST XX.ZAP##
LS.ZAP: MOVEI T1,LS.IX
PJRST XX.ZAP##
AS.ZAP: MOVEI T1,AS.IX
PJRST XX.ZAP##
SUBTTL DECIDE TO LOAD OR SAVE
;DETERMINE IF WE CAN LOAD THE PROGRAM INTO MEMORY OR MUST WRITE AN .EXE FILE
;INSTEAD. WE MUST WRITE AN .EXE FILE IF ANY OF THE FOLLOWING ARE SATISFIED:
;
; 1. USER SPECIFIED /SAVE (SCAN BLOCK ALREADY SET UP).
; 2. THERE ARE PAGE GAPS BETWEEN PSECTS, EXCEPT BELOW .HIGH. (BEWARE THAT
; OVERLAPS DO NOT COUNT AS GAPS).
; 3. THERE ARE ANY PSECTS ABOVE THE HIGH SEGMENT.
; 4. ANY PSECT HAS NON-DEFAULT WRITEABILITY.
; 5. THE PROGRAM WILL NOT FIT IN MEMORY WITH LINK'S FINAL PLACEMENT CODE
; (THIS INCLUDES THE CASE IN WHICH THE REMAP UUO WOULD HAVE TO MOVE THE
; HIGH SEGMENT DOWN).
SAVTST: SKIPE IO.PTR+%VC ;[1146] SAVE FILE REQUIRED?
JRST JBSAVE ;YES
;TEST FOR GAPS BETWEEN PSECTS, PSECTS ABOVE THE HIGH SEGMENT AND PSECT
;PROPERTIES THAT WE CAN'T HANDLE EXCEPT IN AN EXE FILE.
MOVE T1,HL.S1 ;[1146] SEE IF LOW SEG (CONTAINS ALL PSECTS)
SKIPE LL.S2 ;[1170] HITS HIGH SEG (IF ANY) WHICH CHECKS
CAMG T1,LL.S2 ;[1146] FOR PSECTS ABOVE HIGH SEG ORIGIN
SKIPA ;[1146] NO--OK SO FAR
JRST JBCMPX ;[1146] YES--CAN'T LOAD IT
MOVEI R,0 ;[1146] START AT .ABS.
MOVE W1,@RC.TB ;[1146] GET POINTER TO ITS RELOC BLOCK
MOVE T1,RC.HL(W1) ;[1146] START WITH ITS HIGH LIMIT
ADDI R,1 ;[1146] ADVANCE TO .LOW. FOR CHECKS
MOVX T4,2 ;[1146] # OF SEG CONTAINING ONLY .HIGH.
; ..
; ..
;BACK HERE FOR EACH NEW PSECT.
SAVTS1: MOVE W2,@RC.TB ;[1146] GET POINTER TO THIS RELOC BLOCK
MOVE T2,RC.AT(W2) ;[1171] GET THIS PSECT'S ATTRIBUTES
IFE TOPS20,<
CAMN T4,RC.SG(W2) ;[1171] TOPS-10 HIGH SEGMENT?
JRST [TXNE T2,AT.RW ;[1171] YES, USER ASKED FOR WRITEABLE?
JRST JBCMPX ;[1171] YES, LET MONITOR FIGURE IT OUT
JRST SAVTS2] ;[1171] NO, ATTRIBUTES ARE OK
> ;END IFE TOPS20
TXNE T2,AT.RO ;[1171] NON-HI SEG PAGE TO BE READ ONLY?
JRST JBCMPX ;[1171] YES, WE CAN'T HANDLE IT
SAVTS2: CAML T1,RC.HL(W2) ;[1171] DOES PREVIOUS PSECT ENGULF THIS ONE?
JRST SAVTS6 ;[1171] YES--NO GAP POSSIBLE YET
CAMN T4,RC.SG(W2) ;[1146] POSSIBLE GAP BELOW .HIGH.?
JRST SAVTS5 ;[1171] YES--OK. USUAL CASE
MOVEI T2,-1(T1) ;[1146] COMPUTE LAST PAGE USED
LSH T2,-9 ;[1146] ..
LDB T3,[POINTR RC.IV(W2),^-^O777] ;[1146] GET FIRST PAGE USED BY NEXT PSECT
SUB T3,T2 ;[1146] COMPUTE # PAGES BETWEEN THIS AND LAST
SOJG T3,JBCMPX ;[1146] CAN'T LEAVE GAPS IN MEMORY
SAVTS5: MOVE T1,RC.HL(W2) ;[1171] SO FAR SO GOOD--ADVANCE TO NEXT PSECT
SAVTS6: MOVE W1,W2 ;[1171] ADVANCE TO NEXT PSECT
CAMGE R,RC.NO ;[1146] LOOKED AT ALL PSECTS?
AOJA R,SAVTS1 ;[1146] NO--LOOK AT NEXT
; ..
; ..
;COMPUTE HOW MUCH MEMORY IT WILL TAKE TO HOLD THE PROGRAM DURING THE LAST STAGES
;OF LOADING, AND MAKE SURE THAT WE CAN GET THAT MUCH. IF WE CAN'T, THEN THE
;PROGRAM IS TOO COMPLEX. THERE ARE TWO SIZES TO WORRY ABOUT:
;
; 1. LINK'S LOW SEGMENT + THE PROGRAM'S ACTUALLY LOADED LOW SEGMENT (DOESN'T
; COUNT BLOCK'S AT THE END OF THE LOW SEGMENT) + THE PROGRAM'S ACTUALLY
; LOADED HIGH SEGMENT. THIS IS THE MEMORY REQUIREMENT IN JBLOAD.
;
; 2. THE PROGRAM'S ENTIRE LOW SEGMENT + HIGH SEGMENT. THIS IS THE MEMORY
; REQUIREMENT IN THE FINAL EXIT CODE AT %5. NOTE THAT WE MUST REMEMBER
; THAT WE HAVE A HIGH SEGMENT NOW BUT WON'T THEN.
MOVE T1,DY.AB ;[1146] START WITH HIGHEST ADDR LINK NEEDS
ADD T1,HC.S1 ;[1146] ADD LENGTH OF ACTUALLY LOADED CODE
IOR. T1,.PGSIZ ;[1146] ..
SKIPE LL.S2 ;[1170] HIGH SEG EXISTS
CAMGE T1,LL.S2 ;[1146] AND ORIGIN BELOW WHERE WE CAN PUT IT?
SKIPA ;[1146] NO--OK
JRST JBCMPX ;[1146] YES--REMAP WOULD FAIL SO TOO COMPLEX
ADD T1,HC.S2 ;[1170] ADD LENGTH OF HIGH SEGMENT
IOR. T1,.PGSIZ ;[1146] ..
HRRZ T2,.JBHRL## ;[1170] DON'T COUNT SIZE OF CURRENT HIGH SEG
SUB T2,HIORGN ;[1170] ..
MOVNI T2,2(T2) ;[1170] ..
ADD T2,HL.S1 ;[1170] + ENTIRE PROGRAM LOW SEG
IOR. T2,.PGSIZ ;[1170] ROUNDED TO A PAGE
ADD T2,HL.S2 ;[1170] + ENTIRE PROGRAM HIGH SEG
IOR. T2,.PGSIZ ;[1170] ROUNDED TO A PAGE TOO
CAMGE T1,T2 ;[1170] PICK MAX OF TWO
MOVE T1,T2 ;[1170] ..
TLNE T1,-1 ;[732] OVERFLOWED INTO THE LH?
JRST JBCMPX ;[1146] YES--CAN'T FIT SO WRITE .EXE FILE
IFE TOPS20,< ;[1113] SEE IF WE CAN EXPAND ON TOPS-10
CAMG T1,.JBREL ;DO WE HAVE ENOUGH ALREADY?
JRST JBLOAD ;[1146] YES, READ IN REST OF TEMP FILE
CORE T1, ;NO TRY FOR IT
JRST JBCMPX ;[1146] WON'T FIT--WRITE .EXE FILE
MOVEI T1,HG.TAB ;OK, BUT DON'T FORGET TO GIVE IT TO SOMEONE
SKIPN TAB.LB(T1) ;USUAL LOOP
SOJA T1,.-1
MOVE T2,.JBREL
MOVEM T2,TAB.UB(T1)
>
IFN TOPS20,< ;[1113] WE'RE AS BIG AS WE CAN GET ON TOPS-20
CAMLE T1,.JBREL ;[1113] DO WE HAVE ENOUGH ALREADY?
JRST JBCMPX ;[1146] NO--PROGRAM WON'T FIT WITH LINK
>
JRST JBLOAD ;[1146] PROGRAM WILL FIT--GO BRING IT IN
SUBTTL FORCE nnnLNK/SAVE
;HERE IF USER DID NOT SPECIFY /SAVE BUT PROGRAM IS TOO COMPLEX (TOO LARGE, PSECT
;GAPS, ETC.) TO LOAD. DUMMY UP A SCAN BLOCK AS IF THE USER TYPED nnnLNK/SAVE,
;PRINT A WARNING AND FALL INTO .EXE WRITING CODE.
JBCMPX: MOVEI T2,F.LEN ;[1146] SET UP FILE SPEC
PUSHJ P,DY.GET## ;AS THOUGH WE HAD SEEN /SAVE
MOVE P1,T1 ;STORE POINTER TO "SCAN" BLOCK
HLLZ T2,JOBNUM ;SIXBIT JOBNUMBER
HRRI T2,'LNK' ;REST OF NAME
MOVEM T2,F.NAME(T1)
MOVEM T2,SSNAME ;HERE ALSO
IFE FTEXE,<
MOVSI T2,'HGH' ;MARK NON-SHAREABLE
SKIPN HL.S2 ;IF NO HIGH
MOVSI T2,'SAV' ;SO MESSAGE IS CORRECT
>
IFN FTEXE,<
MOVSI T2,'EXE' ;SO MESSAGE IS CORRECT
>
MOVEM T2,F.EXT(T1)
MOVEM T2,SSEXT ;FOR SAVE FILE
MOVSI T2,'DSK' ;MAKE SURE IT GOES ON DSK
MOVEM T2,F.DEV(T1) ;INCASE DEFAULTS SCREWED UP BY NOW
PUSHJ P,DVOUT.## ;SETUP DATA BLOCK
%VC,,.IODPR ;ON FAKE CHAN IN DUMP MODE
SKIPE EXECSW ;WANT TO EXECUTE?
JRST E$$PCX ;[1174] YES--LNKPCX
E$$PCL::.ERR. (MS,.EC,V%L,L%W,S%W,PCL,<Program too complex to load, saving as file >) ;[1174]
.ETC. (JMP,.EC,,,,JBCMP2)
E$$PCX::.ERR. (MS,.EC,V%L,L%W,S%I,PCX,<Program too complex to load and execute, will run from file >) ;[1174]
JBCMP2: .ETC. (FSP,,,,,%VC)
; JRST JBSAVE ;[1146] FALL THROUGH TO WRITE .EXE FILE
SUBTTL GENERATE .EXE (OR .XPN/.SHR/.HGH/.LOW) FILE
;SOME JOBDAT LOCATIONS WE NEED TO KNOW
.JBHSO==75 ;PAGE # OF HIGH SEG ORIGIN
.JBSDD==114 ;SAVED .JBDDT
.JBS41==122 ;SAVED .JB41
EXTERN .JBREN
JOBHSA==0 ;HIGH .JBSA
JOBH41==1 ;HIGH .JB41
JOBHRN==3 ;HIGH .JBHRL & .JBREN
JOBHSO==7 ;PAGE # OF HIGH SEG ORIGIN IN HIGH
;HERE TO SETUP SAVED LOCATIONS
JBSAVE: ;[1174] WRITE A SAVED FILE
E$$CSF::.ERR. (MS,0,V%L,L%I,S%I,CSF,<Creating saved file>) ;[1174]
IFE FTEXE,<
MOVE T2,.JBDDT(P1) ;GET DDT START
MOVEM T2,.JBSDD(P1) ;TO SAFE PLACE
MOVE T2,.JB41(P1) ;SAME FOR UUO HANDLER
MOVEM T2,.JBS41(P1)
>
HLRZ T1,.JBSA(P1) ;ALSO SETUP RIGHT HALF OF .JBCOR
IFN FTOVERLAY,<
SKIPL LNKMAX ;SEEN ANY?
SKIPN JOB116 ;YES, AND WANT SYMBOLS?
CAIA ;NO
HLRZ T1,.JBCOR(P1) ;INCLUDE SYMBOLS
>
IOR. T1,.PGSIZ ;TO HIGHEST LOC REQUIRED
HRRM T1,.JBCOR(P1) ;SO SAVE GET WORKS
SKIPL SYMSEG ;[1132] SYMBOLS IN A PSECT?
JRST JBSAVX ;[1132] NO, SKIP THIS
HLRE T1,.JBSYM(P1) ;[1132] YES, GET -LENGTH OF TABLE
HRRZ T2,.JBSYM(P1) ;[1132] GET FIRST ADDR OF TABLE
SUB T2,T1 ;[1132] COMPUTE FIRST FREE AFTER TABLE
CAMLE T2,HC.S1 ;[1132] UPDATE AMOUNT OF CODE IN LC AREA
MOVEM T2,HC.S1 ;[1132] BUT NEVER DECREASE
CAMLE T2,HL.S1 ;[1132] ALSO UPDATE SIZE OF SEGMENT
MOVEM T2,HL.S1 ;[1132] NEVER DECREASE
JBSAVX:
IFN FTEXE,<JRST JBEXE> ;SET UP TO WRITE AN EXE FILE
IFE FTEXE,<
SKIPN HC.LB ;ANYTHING IN HIGH SEG?
JRST JBNOHI ;NO, JUST SAVE LOW SEG
SKIPN PAG.S2 ;PAGING HIGH SEG?
JRST JBSHGH ;NO, JUST SAVE IT
;JUST WRITE OUT LAST PAGES
;AND JBHDA (0-7 RELATIVE)
;AND EITHER RENAME OR COPY FILE
;TO RIGHT F/S
HRLZ T1,LW.S2 ;LOWER WINDOW
HRR T1,UW.S2 ;UPPER WINDOW
PUSHJ P,HC.OUT## ;OUTPUT LAST BLOCKS
SETZM LW.S2 ;START BACK AT ZERO
MOVEI T1,.IPM ;READ IN FIRST
PUSHJ P,HC.IN## ;READ IT BACK
PUSHJ P,BLTJHA ;COPY FIRST 10 WORDS BACK
;WE NOW HAVE A HIGH SEG FILE ON DSK
;BUT IS IT THE RIGHT W/S
MOVE T2,IO.PTR+%VC ;[606] TO CHANNEL
PUSHJ P,DVPRO. ;[606] GET THE PROTECTION RIGHT
MOVEI T1,HC ;FROM HIGH CODE OVERFLOW
MOVEI T2,%VC ;TO SAVE FILE
PUSHJ P,DVMOV. ;RENAME OR COPY
JRST JBSHDL ;RENAMED, REMOVE HC AREA
;HERE IF NOT PAGING. WRITE OUT THE HIGH SEGMENT FILE.
JBSHGH: MOVEI R,2 ;POINT TO HIGH SEGMENT
PUSHJ P,SAVINI ;OPEN SAVE FILE
JBSHG1: MOVE T1,HC.AB ;GET LENGTH OF HIGH CODE AREA
SUB T1,HC.LB
SKIPN PAG.S2 ;PAGING (NOT ALL IN CORE)
SKIPE .JBDDT(P1) ;OR DDT LOADED?
JRST JBSHGN ;USE ALL OF AREA
CAMLE T1,HL.S2 ;UNLESS SMALLER THAN HIGHEST LOC
MOVE T1,HL.S2 ;USE HIGHEST LOC LOADED
JBSHGN: MOVN T1,T1 ;IOWD IS NEG
HRLZ T1,T1 ;IN LEFT HALF
HRR T1,HC.LB ;GET ADDRESS OF FIRST WORD
HRRI T1,-1(T1) ;-1
SETZ T2, ;TERMINATE LIST
OUT DC,T1 ;DUMP CORE IMAGE AS IS
JRST JBSHGR ;OK
E$$SOE::PUSH P,[DC] ;[1174]
.ERR. (ST,,V%L,L%F,S%F,SOE,<Saved file output error>) ;[1174]
JBSHGR: MOVEI T1,DC ;MAKE SURE CHAN# SETUP
MOVEM T1,IO.CHN
PUSHJ P,DVRLS.## ;RELEASE DEVICE
;HERE AFTER HI SEG SAVED. DELETE POSSIBLE .HGH/.SHR & .LOW FILES
JBSHDL: MOVEI T1,TC ;CHAN#
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%VC ;PSEUDO CHAN#
MOVEM T1,IO.PTR+TC ;INCASE OF ERROR
PUSHJ P,DVCHN.## ;T1 POINTS TO DATA BLOCK ON RETURN
MOVSI T2,(Z TC,) ;RESET CHAN # IN AC FIELD
MOVEM T2,I.CHN(T1) ;SINCE %VC IS THERE CURRENTLY
SKIPE T2,SSNAME ;GET REQUIRED NAME
JRST .+3 ;USUALLY ITS GIVEN
SKIPN T2,RUNAME ;IF NOT TRY /RUNAME
MOVE T2,LODNAM ;DEFAULT AS LAST RESORT
MOVEM T2,I.NAM(T1) ;DELETE THIS FILE
PUSH P,T2 ;SAVE NAME FOR .LOW
HLLZ T2,SSEXT ;GET EXT WE WANT
TLC T2,331732 ;DELETE OTHER ONE
MOVEM T2,I.EXT(T1)
PUSHJ P,DVOPN.## ;OPEN DEVICE
MOVEI T1,TC ;SET CHAN#
PUSHJ P,DVDEL.##
JFCL
PUSHJ P,DVCHN.##
POP P,I.NAM(T1) ;RESTORE NAME
PUSH P,I.EXT(T1) ;[575] SAVE EXTENSION IN CASE /EXEC
HRLZ T2,SSEXT ;INCASE USER SUPPLIED EXT
SKIPN T2 ;DELETE IT INCASE ONLY HIGH
MOVSI T2,'LOW'
MOVEM T2,I.EXT(T1) ;AND DELETE THIS ALSO
PUSHJ P,DVOPN.## ;OPEN CHAN AGAIN
MOVEI T1,TC ;SET CHAN#
PUSHJ P,DVDEL.##
JFCL
;FALL THROUGH TO NEXT PAGE
;HERE TO SETUP LOW SEG FILE SPEC
PUSHJ P,DVCHN.## ;[575] POINT BACK AT I/O DATA BLOCK
POP P,I.EXT(T1) ;[575] RESTORE EXTENSION IN CASE /EXEC
HRLZ T1,SSEXT ;INCASE USER SUPPLIED
SKIPN T1
MOVSI T1,'LOW' ;IF ANY LOW SEG STUFF
MOVEM T1,SSEXT ;EXT IS NOW LOW NOT SAV
MOVEI T1,HC.IX ;ALL DONE WITH HIGH SEG CODE AREA
PUSHJ P,XX.ZAP ;SO GET RID OF IT
MOVE T1,IO.PTR+DC ;BUT SAVE FILE SPEC
MOVEM T1,IO.PTR+HC ;IN CASE /EXEC
JRST JBSLOW ;NOW SAVE LOW SEG
JBNOHI: HRLZ T1,SSEXT ;INCASE USER SUPPLIED IT
SKIPN T1
IFE TOPS20,<
MOVSI T1,'SAV' ;EXT IS NOW SAV NOT LOW
>
IFN TOPS20,<
MOVSI T1,'EXE' ;EXT IS NOW EXE NOT LOW
>
MOVEM T1,SSEXT
;FALL INTO JBSLOW
;JOBDAT IS NOW SETUP - IF PAGING WRITE OUT REST OF CORE IMAGE
;AND READ IN AS MUCH AS POSSIBLE FOR CORE COMPRESSOR
JBSLOW: SKIPN PAG.S1 ;PAGING?
JRST JBSAV3 ;NO, JUST OUTPUT CORE IMAGE
HRLZ T1,LW.S1 ;GET LOWER WINDOW
HRR T1,UW.S1 ;TO UPPER
PUSHJ P,LC.OUT## ;OUTPUT IT ALL
;NOW TO SEE IF WE CAN READ ALL OF CORE FILE BACK INTO CORE
; IF NOT READ IN AS MUCH AS POSSIBLE
SETZM LW.S1 ;START AT LOWEST LOCATION
MOVE T1,DY.AB ;HIGHEST LOC WE CAN NOT USE
MOVEM T1,DY.UB ;TELL LNKCOR ABOUT IT
ADDI T1,1
MOVEM T1,LC.LB ;BACKUP IF WE CAN
SKIPN T1,LS.LB ;CAN ONLY USE TO BOTTOM OF LS
;AREA IF IT'S STILL THERE
SKIPA T1,.JBREL ;IF IT'S NOT, CAN USE ALL OF CORE
SUBI T1,1 ;LAST TO USE IS START OF LS - 1
MOVEM T1,LC.UB ;RESET POINTERS
MOVEM T1,LC.AB ;FOR CONSISTENCY
SUB T1,LC.LB ;MINUS WHAT WE ALREADY HAVE
MOVEM T1,UW.S1 ;ASSUME IT WON'T FIT
CAMGE T1,HC.S1 ;ENOUGH EXTRA FOR ALL OF FILE?
JRST JBSAV1 ;NO, DO IT THE HARD WAY
MOVE T1,HC.S1 ;WE NEED ONLY THIS MUCH
IORI T1,.IPM ;ROUNDED UP
MOVE T2,T1 ;CAN ALSO CUT BACK LC.AB
ADD T2,LC.LB ;TO WHAT WE ACTUALLY NEED
MOVEM T2,LC.AB ;TO SAVE TIME
PUSHJ P,LC.IN## ;READ WHAT WE CAN
PUSHJ P,LC.DLT ;DELETE LC FILE UNLESS .XPN WANTED
JRST JBSAV2 ;AND COPY 0-137 BACK INTO CORE
JBSAV1: PUSHJ P,LC.IN## ;READ BACK AS MUCH CORE AS WE CAN
JBSAV2: PUSHJ P,BLTJDA ;BLT .JBDA TO LOW SEG
JBSAV3: MOVE T1,LC.LB ;JOBDAT NOW SETUP IN CORE
SKIPN .JBDDT(T1) ;ALWAYS SAVE IF DDT LOADED
SKIPN HC.S2 ;ANY HIGH SEG (HC.LB IS ZERO BY NOW)
JRST JBSAV4 ;NO, SO MUST WANT LOW SEG
MOVE T1,HC.S1 ;YES, SEE IF LOW SEG CONTAINS DATA
CAIG T1,.JBDA ;IF .JBCOR GREATER THAN 137
JRST ENDSAV ;NO, SO NO LOW SEG FILE
JBSAV4: MOVEI R,1 ;POINT TO LOW SEGMENT
PUSHJ P,SAVINI ;INIT/ENTER SAV FILE
SKIPE IO.PTR+%XC ;WANT .XPN FILE?
SKIPE IO.PTR+LC ;BUT NOT PAGING
JRST ZCMPRS ;NO, NOW FOR ZERO COMPRESSOR
PUSHJ P,WRTXPN ;WRITE IT OUT
JRST ZCMPRS ;AND COMPRESS CORE IMAGE
> ;END OF IFE FTEXE
;HERE TO DELETE LC FILE
;CALLED BY
; PUSHJ P,LC.DLT
;USES T1
LC.DLT: SETZM PAG.S1 ;NOT PAGING NOW
SKIPE IO.PTR+%XC ;WANT .XPN FILE?
POPJ P, ;YES, LEAVE OVERFLOW FILE
MOVEI T1,LC
PUSHJ P,DVDEL.## ;DELETE FILE
JFCL ;TOO BAD
POPJ P,
;HERE TO DELETE HC FILE
HC.DLT: SETZM PAG.S2
MOVEI T1,HC
PUSHJ P,DVDEL.##
JFCL
POPJ P,
IFN FTOVERLAY,<
;HERE TO DELETE LS FILE
LS.DLT: SETZM PAG.LS
MOVEI T1,SC
PUSHJ P,DVDEL.##
JFCL
POPJ P,
>
BLTJDA: MOVS T1,JOBPTR ;FORM BLT POINTER
HRR T1,LC.LB ;TO MOVE MODIFIED JOBDAT AREA
HRRZI T2,.JBDA-1(T1) ;BACK INTO FRONT OF CORE
BLT T1,(T2)
MOVE T1,JOBPTR ;GIVE AREA BACK
MOVEI T2,.JBDA
PUSHJ P,DY.RET
SETZM JOBPTR ;AND FORGET ABOUT AREA
SKIPN IO.PTR+%XC ;IF WE WANT .XPN FILE
POPJ P, ;NO
MOVEI T1,.DBM ;YES
PJRST LC.OUT## ;WRITE OUT JOBDATA AREA AGAIN
;NOW READ BACK FIRST 10 WORDS (.JBHDA)
BLTJHA: MOVS T1,JBHPTR ;FORM BLT POINTER
HRR T1,HC.LB ;TO MOVE MODIFIED JOBDAT AREA
HRRZI T2,.JBHDA-1(T1) ;BACK INTO FRONT OF CORE
BLT T1,(T2)
MOVE T1,JBHPTR ;GIVE AREA BACK
MOVEI T2,.JBHDA
PUSHJ P,DY.RET##
SETZM JBHPTR ;AND FORGET ABOUT AREA
MOVEI T1,.DBM ;NOW WRITE IT BACK
PJRST HC.OUT## ;WRITE IT BACK
;BUT IS IT THE RIGHT F/S
IFE FTEXE,<
;HERE TO OPEN SAVE FILE (USING DC)
;ENTER WITH :-
;R = 1 (LOW) OR 2 (HIGH)
SAVINI: MOVEI T1,DC ;CHAN#
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%VC ;PSEUDO CHAN#
MOVEM T1,IO.PTR+DC ;INCASE OF ERROR
PUSHJ P,DVCHN.## ;T1 POINTS TO DATA BLOCK ON RETURN
MOVSI T2,(Z DC,) ;RESET CHAN # IN AC FIELD
MOVEM T2,I.CHN(T1) ;SINCE %VC IS THERE CURRENTLY
SKIPE T2,SSNAME ;GET REQUIRED NAME
JRST .+3 ;USUALLY ITS GIVEN
SKIPN T2,RUNAME ;IF NOT TRY /RUNAME
MOVE T2,LODNAM ;DEFAULT AS LAST RESORT
MOVEM T2,I.NAM(T1) ;SAVE IT
HLLZ T2,SSEXT ;EXT IS EITHER SAV OR LOW
MOVEM T2,I.EXT(T1)
MOVX T2,RB.PRV ;[606] PRESERVE PROTECTION
ANDM T2,I.PRV(T1) ;[606] MAKE CREATION DATE TODAY
MOVE T2,HC.S0(R) ;GET HIGHEST LOC TO SAVE
LSH T2,-.DBS2W ;[650] INTO BLOCKS
ADDI T2,3 ;1 FOR REMAINDER, 2 FOR RIBS
MOVEM T2,I.EST(T1) ;AT LEAST THIS IS ENOUGH
MOVE T2,VERNUM ;GET VERSION OF CORE IMAGE
SKIPN I.VER(T1) ;SKIP IF SET BY SWITCH
MOVEM T2,I.VER(T1) ;NO, SO SET IT
PUSHJ P,DVOPN.## ;OPEN DEVICE
PUSHJ P,DVNAM.## ;MAKE SURE WE HAVE A NAME
PJRST DVENT.## ;ENTER FILE NAME
>;END OF IFE FTEXE
;HERE TO OPEN XPN FILE (IF NOT PAGING) USING LC
XPNINI: MOVEI T1,LC ;CHAN#
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%XC ;PSEUDO CHAN#
MOVEM T1,IO.PTR+LC ;INCASE OF ERROR
SETZM IO.PTR+%XC ;DONE WITH .XPN CHAN NOW
PUSHJ P,DVCHN.## ;T1 POINTS TO DATA BLOCK ON RETURN
MOVSI T2,(Z LC,) ;RESET CHAN # IN AC FIELD
MOVEM T2,I.CHN(T1) ;SINCE %VC IS THERE CURRENTLY
MOVE T2,HC.S1 ;GET HIGHEST LOC TO SAVE
LSH T2,-.DBS2W ;[650] INTO BLOCKS
ADDI T2,3 ;1 FOR REMAINDER, 2 FOR RIBS
MOVEM T2,I.EST(T1) ;AT LEAST THIS IS ENOUGH
MOVE T2,VERNUM ;GET VERSION OF CORE IMAGE
SKIPN I.VER(T1) ;SKIP IF SET BY SWITCH
MOVEM T2,I.VER(T1) ;NO, SO SET IT
PUSHJ P,DVOPN.## ;OPEN DEVICE
PUSHJ P,DVNAM.## ;MAKE SURE FILE NAME SETUP
PJRST DVENT.## ;ENTER FILE NAME
;HERE TO WRITE OUT .XPN FILE IF NOT PAGING
;NOTE, MUST BE DONE BEFORE ZERO COMPRESSION
WRTXPN: PUSHJ P,XPNINI ;OPEN/ENTER FILE
MOVE T1,HC.S1 ;HIGHEST LOC TO OUTPUT
MOVN T1,T1 ;-LENGTH
HRLZ T1,T1 ;IN LEFT HALF
HRR T1,LC.LB ;FORM IOWD
HRRI T1,-1(T1) ;ALMOST
SETZ T2, ;END WORD
OUT LC,T1 ;DUMP OUTPUT
CAIA ;OK
PUSHJ P,E$$OEX ;[1174]
PUSHJ P,DVRLS.## ;RELEASE DEV
PJRST DVZAP.## ;FORGET ABOUT .XPN FILE NOW
E$$OEX::PUSH P,[LC] ;[1174]
.ERR. (ST,,V%L,L%W,S%W,OEX,<Output error on XPN file, file closed, load continuing>) ;[1174]
POPJ P,
IFN FTEXE,<
;HERE TO WRITE THE EXE FILE.
;THE STRATEGY IS:
;RESERVE ONE PAGE FOR THE DIRECTORY.
;WRITE OUT EACH PSECT (POINTED TO BY RC.TB), COMPRESSING OUT ZERO PAGES,
; AND ACCUMULATING THE EXE DIRECTORY IN A BLOCK IN THE DY AREA.
;GO BACK TO THE BEGINNING OF THE FILE AND WRITE OUT THE EXE DIRECTORY.
;NOTES:
;PAGE 0 IS ALWAYS WRITTEN, AND IF A HIGH SEG EXIST, SO IS ITS FIRST PAGE.
;IF THE EXE DIRECTORY PAGE IN THE DY AREA OVERFLOWS, LINK WRITES IT OUT
; AT THE BEGINNING OF THE FILE, THEN FREES UP ANOTHER PAGE IN THE FILE BY
; MAKING A BACKWARDS PASS OVER THE EXE FILE, MOVING EACH PAGE DOWN ONE.
JBEXE: SKIPN HC.LB ;ANY HIGH SEGMENT?
JRST JBEXEN ;NO,
SKIPN T1,UW.S2 ;IS IT PAGED?
JRST JBEXEH ;NO,
HRL T1,LW.S2 ;OUTPUT WORD
PUSHJ P,HC.OUT ;MAKE SURE IT GET OUT
MOVE T1,UW.S2
SUB T1,LW.S2 ;GET LENGTH
MOVEM T1,UW.S2 ;RESET IT
SETZM LW.S2 ;BACK TO FRONT OF FILE
PUSHJ P,HC.IN ;READ IT BACK
JBEXEH: PUSHJ P,HJBSET ;YES, SETUP VESTIGIAL JOBDAT
SKIPE JBHPTR ;WAT IT PAGED?
PUSHJ P,BLTJHA ;YES, READ IT BACK NOW
JBEXEN: MOVEI T2,1000 ;NEED SPACE FOR DIRECTORY
PUSHJ P,DY.GET## ;GO GET IT
DMOVEM T1,EXEDIR ;SAVE BASE
IFN FTOVERLAY,<
;IF LOADING OVERLAYS, IT IS THE EXE FILE GENERATOR'S RESPONSIBILITY
;TO INSERT THE SYMBOLS INTO THE PROGRAM ON THE FLY WHILE IT IS WRITING
;THE EXE FILE. THE SYMBOLS ARE IN THE LS AREA IN RADIX50 FORM.
;THE EXE FILE WRITING LOOP IS VERY PAGE ORIENTED, SO TO MAKE THINGS
;EASIER, WE WILL COPY THE FIRST PARTIAL PAGE OF SYMBOLS INTO THE
;LC AREA HERE.
SKIPL LNKMAX ;[1132] LOADING OVERLAYS?
SKIPN JOB116 ;[1132] AND SYMBOLS TO PROCESS?
JRST JBEXEE ;[1132] NO, SKIP THIS
HRRZ P3,JOB116 ;[1132] GET FIRST ADDRESS TO COPY INTO
HRRZ P4,P3 ;[1132] COMPUTE LAST ADDRESS IN P4
ADDI P4,777 ;[1132] ROUND UP TO PAGE BOUND
ANDCMI P4,777 ;[1132] ADDRESS OF FIRST FULL PAGE OF SYMS
CAMLE P4,HL.S1 ;[1132] MAKE SURE EXE FILE WRITER GOES THIS FAR
MOVEM P4,HL.S1 ;[1132] SO OVERLAY CODE CAN JUST CONTINUE
MOVEI R,1 ;[1132] POINTER TO .LOW. RC BLOCK
MOVE R,@SG.TB ;[1132] SINCE OVERLAY SYMBOLS ARE IN .LOW.
CAMLE P4,RC.HL(R) ;[1132] UPDATE .LOW. TO SYMBOLS WRITTEN HERE
MOVEM P4,RC.HL(R) ;[1132] BUT NEVER SHRINK IT
ANDI P3,777 ;[1132] OFFSET TO FIRST WORD TO WRITE
JUMPE P3,JBEXEE ;[1132] IF PAGE-ALIGNED, NOTHING TO DO
CAMLE P4,HC.S1 ;[1132] SINCE COPYING SYMS, UPDATE NON-ZERO PTR
MOVEM P4,HC.S1 ;[1132] ALSO REMEMBERS HOW LONG LC AREA IS
SKIPE PAG.S1 ;[1132] IS LC AREA PAGING?
JRST JBEXEB ;[1132] YES, GO SET ON CORRECT PAGE
MOVE P2,P4 ;[1132] EXTEND LC AREA TO WHERE SYMS GO
ADD P2,LC.LB ;[1132] MIGHT BE QUITE A WAY IF BIG /SPACE
SUB P2,LC.AB ;[1132] DISTANCE = LAST ADDR - SIZE OF LC AREA
SUBI P2,1 ;[1132] SIZE IS LAST-FIRST+1
JUMPLE P2,JBEXEC ;[1132] ALREADY THERE
MOVEI P1,LC.IX ;[1132] TELL LNKCOR TO EXPAND LC AREA
PUSHJ P,LNKCOR ;[1132] DO IT
JRST JBEXEB ;[1132] FAILED, BUT LC AREA IS PAGING NOW
JRST JBEXEC ;[1132] OK, GO DO THE COPY
;HERE IF THE LC AREA IS PAGING, EITHER FROM THE START, OR BECAUSE
;IT COULDN'T EXPAND FAR ENOUGH. JUST SET UP A ONE-PAGE WINDOW TO
;THE PAGE WE WANT TO COPY INTO.
JBEXEB: HRLZ T1,LW.S1 ;[1132] WRITE ENTIRE LC AREA
HRR T1,UW.S1 ;[1132] TO AVOID LOST DATA
PUSHJ P,LC.OUT## ;[1132] DUMP IT TO THE OVERFLOW FILE
MOVE T1,LC.LB ;[1132] REDUCE LC WINDOW TO ONE PAGE
ADDI T1,777 ;[1132] AVOIDS CHECKS FOR OVER 256K
MOVEM T1,LC.AB ;[1132] AREA IS NOW 1 PAGE
MOVSI T1,-1000(P4) ;[1132] LOWEST LOCATION TO READ
MOVSM T1,LW.S1 ;[1132] UPDATE LOWER WINDOW
HRRI T1,-1(P4) ;[1132] HIGHEST LOCATION TO READ
HRRZM T1,UW.S1 ;[1132] UPDATE UPPER WINDOW
PUSHJ P,LC.IN ;[1132] READ IN CODE IN THAT PAGE
;HERE WHEN THE LC AREA INCLUDES THE PAGE THAT WE WANT TO UPDATE.
;NOW GET THE PAGE OF SYMBOLS WE WANT TO PUT HERE INTO THE LS AREA.
JBEXEC: PUSHJ P,CHKPAG ;[1132] IN CASE WE JUST STARTED PAGING
SKIPN LW.LS ;[1132] ARE THE FIRST PAGE OF SYMBOLS IN?
JRST JBEXED ;[1132] YES, GO DO THE COPY
MOVE T1,LW.LS ;[1132] WRITE CURRENT LS WINDOW
ADD T1,LS.AB ;[1132] SO SYMBOLS WON'T BE LOST
SUB T1,LS.LB ;[1132] T1 HAS NEW UPPER BOUND
MOVEM T1,UW.LS ;[1132] STORE IN CASE IT WAS -1
HRL T1,LW.LS ;[1132] ARG TO LS.OUT
PUSHJ P,LS.OUT ;[1132] WRITE THE LS AREA OUT
MOVE T1,LS.LB ;[1132] REDUCE LS WINDOW TO 1 PAGE
ADDI T1,777 ;[1132] WILL BE EXPANDED LATER IF NEEDED
MOVEM T1,LS.AB ;[1132] AB IS LB+1P
SETZM LW.LS ;[1132] WANT FIRST PAGE OF SYMBOLS
MOVEI T1,777 ;[1132] FROM 0 TO 777
MOVEM T1,UW.LS ;[1132] UPDATE UPPER WINDOW
PUSHJ P,LS.IN ;[1132] READ IN THE SYMBOLS
;HERE WHEN BOTH THE LC AND LS AREAS HAVE THE PAGE IN MEMORY THAT WE CARE
;ABOUT. NOW TO BLT THE FIRST PARTIAL PAGE OF SYMBOLS INTO THE LC AREA.
JBEXED: MOVE T3,LC.LB ;[1132] CALCULATE OFFSET FROM VIRTUAL
SUB T3,LW.S1 ;[1132] TO PHYSICAL ADDRESSES
HRRZ T1,JOB116 ;[1132] FIRST VIRTUAL ADDRESS TO WRITE
ADD T1,T3 ;[1132] FIRST PHYSICAL ADDRESS
HRL T1,LS.LB ;[1132] FROM START OF LS AREA
MOVE T2,P4 ;[1132] FIRST VIRTUAL ADDRESS NOT TO WRITE
ADD T2,T3 ;[1132] FIRST PHYSICAL ADDRESS
BLT T1,-1(T2) ;[1132] COPY THE SYMBOLS
JBEXEE:
> ;END IFN FTOVERLAY
;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE
SKIPN PAG.S1 ;READY TO DUMP CORE, FIRST SEE IF PAGED?
JRST EXEINI ;NO, GO OPEN EXE FILE AND DUMP
;YES, IT'S PAGED. IF NEEDED, FIRST OUTPUT ALL, THEN TRY READ BACK ALL
;OF CORE FILE BACK INTO CORE (OR AS MUCH AS POSSIBLE).
SKIPE T1,LOWLOC ;[732] LOWEST LOCATION IN PAGE0?
JRST [CAMGE T1,LW.S1 ;[732] NO, OUT ON DISK?
JRST .+1 ;[732] YES, GO DO OUTPUT & READ
SUB T1,LW.S1 ;[1147] NO, FIND HOW FAR TO SHRINK
ADDM T1,LW.S1 ;[1147] MOVE VIRTUAL WINDOW UP
ADDM T1,LC.LB ;[1147] GIVE AWAY BOTTOM OF AREA
ADDM T1,DY.UB ;[1147] GIVE TO AREA JUST BELOW
JRST JBEXE1] ;[732]
HRLZ T1,LW.S1 ;GET LOWER WINDOW
HRR T1,UW.S1 ;TO UPPER
PUSHJ P,LC.OUT## ;OUTPUT IT ALL
MOVE T1,LOWLOC ;[762] GET LOWLOC PAGES INTO THE WINDOW
MOVEM T1,LW.S1 ;[762]
MOVE T1,DY.AB ;HIGHEST LOC WE CAN NOT USE
MOVEM T1,DY.UB ;TELL LNKCOR ABOUT IT
ADDI T1,1
MOVEM T1,LC.LB ;BACKUP IF WE CAN
SKIPN HC.S2 ;HOW ABOUT HIGH SEGMENT?
JRST JBEXEA ;NO HIGH SEG, JUMP
MOVE T1,HC.LB ;YES, HIGH SEG STILL EXISTS
SUBI T1,1 ;TOP OF LOW
MOVEM T1,LC.UB ;RESTORE POINTERS
JRST JBEXER ;GO MAKE PAGE BOUND AND CHECK ROOM
JBEXEA: SKIPN T1,LS.LB ;TO BOTTOM OF LS, IF IT'S THERE
SKIPA T1,.JBREL ;IF NOT, ALL OF CORE
SUBI T1,1
MOVEM T1,LC.UB ;RESER
JBEXER: SUB T1,LC.LB ;MAKE SURE
SUBI T1,777 ;WE ARE ON A PAGE BOUND
IORI T1,777 ;...
ADD T1,LC.LB ;ADD IN BASE
MOVEM T1,LC.AB ;FOR CONSISTANCY
SUB T1,LC.LB ;MINUS WHAT WE ALREADY HAVE
MOVE T3,HC.S1 ;[762]
SUB T3,LOWLOC ;[762] GET ACTUALLY NEEDED LENGTH
IORI T3,777 ;[762]
CAMGE T1,T3 ;[762] COMPARE WHAT WE HAVE AND WHAT WE NEED
JRST [ADD T1,LW.S1 ;[762] WE HAVE LESS THAN WE NEED
MOVEM T1,UW.S1 ;[762] UPDATE UPPER WINDOW VALUE
HRL T1,LW.S1 ;[762]
PUSHJ P,LC.IN ;READ IN AS MUCH AS WE CAN
JRST JBEXE1]
MOVE T1,T3 ;[762] WE HAVE MORE THAN WE NEED
ADD T1,LW.S1 ;[762] UPDATE UPPER WINDOW VALUE
MOVEM T1,UW.S1 ;[762]
HRL T1,LW.S1 ;[762]
ADD T3,LC.LB ;[762] CAN CUT BACK LC.AB TO WHAT WE NEED
MOVEM T3,LC.AB ;TO SAVE TIME
PUSHJ P,LC.IN## ;READ WHAT WE CAN
PUSHJ P,LC.DLT ;DELETE FILE UNLESS .XPN WANTED
JBEXE1: SKIPN LW.LC ;[742] WE HAVE PAGE 0 IN CORE?
PUSHJ P,BLTJDA ;BLT .JBDA TO LOW SEG
; JRST EXEINI
;HERE TO OPEN EXE FILE
EXEINI: MOVEI T1,DC ;CHAN#
MOVEM T1,IO.CHN
MOVE T1,IO.PTR+%VC ;PSEUDO CHAN#
MOVEM T1,IO.PTR+DC ;INCASE OF ERROR
PUSHJ P,DVCHN.## ;T1 POINTS TO DATA BLOCK ON RETURN
MOVSI T2,(Z DC,) ;RESET CHAN # IN AC FIELD
MOVEM T2,I.CHN(T1) ;SINCE %VC IS THERE CURRENTLY
SKIPE T2,SSNAME ;GET REQUIRED NAME
JRST .+3 ;USUALLY ITS GIVEN
SKIPN T2,RUNAME ;IF NOT TRY /RUNAME
MOVE T2,LODNAM ;DEFAULT AS LAST RESORT
MOVEM T2,I.NAM(T1) ;SAVE IT
MOVE T2,SSEXT ;GET EXT AND FLAGS
HLLZM T2,I.EXT(T1) ;STORE EXT
SETZM I.PRV(T1) ;MAKE THE CREATION DATE TODAY
MOVE T2,HC.S1 ;[744] GET HIGHEST LOW CORE TO SAVE
ADD T2,HC.S2 ;[744] PLUS THE HIGH CORE TO SAVE
LSH T2,-7 ;INTO BLOCKS
ADDI T2,7 ;[1132] 1 FOR REM, 4 FOR EXE DIR, 2 FOR RIBS
MOVEM T2,I.EST(T1) ;AT LEAST THIS IS ENOUGH
MOVE T2,VERNUM ;GET VERSION OF CORE IMAGE
SKIPN I.VER(T1) ;SKIP IF SET BY SWITCH
MOVEM T2,I.VER(T1) ;NO, SO SET IT
PUSHJ P,DVOPN.## ;OPEN DEVICE
PUSHJ P,DVNAM.## ;MAKE SURE WE HAVE A NAME
MOVE T1,IO.CHN ;YES, NEED UPDATE MODE
PUSHJ P,DVUPD.## ;INCASE LARGE DIRECTORY
JRST E$$ECE ;[1174] CAN'T
SKIPE IO.PTR+%XC ;WANT .XPN FILE?
SKIPE IO.PTR+LC ;BUT NOT PAGING
JRST XCMPRS ;GO WRITE OUT EXE
PUSHJ P,WRTXPN ;WRITE OUT XPN
; JRST XCMPRS
;HERE TO WRITE THE EXE FILE, COMPRESSING OUT ALL-ZERO PAGES
;USES ACS AS FOLLOWS:
;
;P1 FLAGS,,FILE PAGE
;P2 REPEAT COUNT,,PROCESS PAGE
;P3 ADDRESS WITHIN SEGMENT (PROCESS ADDRESS - LL.S0(R))
;P4 FLAGS TO DETERMINE WHAT TO DO WITH THE DIRECTORY ENTRY,,FILE PAGE COUNT
;
; ZEROF TO ZEROF : BUMP REPEAT COUNT
; ZEROF TO DATAF : WRITE OUT CURRENT DIR; START NEW DIR
; ZEROF TO GAPF : WRITE OUT DURRENT DIR
; DATAF TO ZEROF: WRITE OUT CURRENT DIR; START NEW DIR
; DATAF TO DATAF: BUMP REPEAT COUNT
; DATAF TO GAPF: WRITE OUT CURRENT DIR
; GAPF TO ZEROF/DATAF: IGNORE CURRENT ENTRY; START NEW DIR
; GAPF TO GAPF: IGNORE
;
;R INDEX TO SEGMENT EITHER 1 OR 2
;R2 POINTER TO RC BLOCK FOR CURRENT PSECT
;W1 STORE PTR
;W2 IOWD TO DATA NOT YET WRITTEN
;W3 IOWD LIST TERMINATOR (0)
ZEROF==1B0 ;[1132] LAST THING FOUND WAS A ZERO PAGE
DATAF==1B1 ;[1132] LAST THING FOUND WAS A NON-ZERO PAGE
GAPF==1B2 ;[1132] LAST THING FOUND WAS AN INTER-PSECT GAP
XCMPRS: SETZ R, ;[1132] START WITH .ABS.
MOVEM R,RC.CUR ;[1132] STORE CUURENT PSECT INDEX IN RC.CUR
MOVEI T1,1 ;[1132] CURRENT BLOCK OF EXE DIR
MOVEM T1,EXEBLK ;[1132] SAVE FOR XCMPXD
USETO DC,5 ;[1132] START WRITING DATA AT BLOCK 5
MOVEI P1,1 ;[1132] NEXT FILE PAGE TO WRITE IS 1
MOVE R2,@RC.TB ;[1132] POINTER TO RC BLOCK FOR .ABS.
MOVE R,RC.SG(R2) ;[1132] KEEP R POINTING TO SEGMENT INDEX
MOVE T1,RC.AT(R2) ;[1132] GET ITS PSECT ATTRIBUTES
TXNN T1,AT.RO ;[1132] READ-ONLY?
TXO P1,SV%WRT ;[1132] NO, LOWSEG IS USUALLY WRITABLE
SETZB P2,P3 ;[1132] CORE PAGE 0, CURRENT ADDR IS 0
MOVX P4,GAPF ;[1132] FLAG NO OLD EXE DIR ENTRY TO WRITE
MOVE R,RC.SG(R2) ;[1132] POINT TO AREA CONTAINING THIS PSECT
MOVSI W1,-1000 ;[1132] W1 IS AOBJN PTR TO COPY OF EXE DIR
HRR W1,EXEDIR ;[1132] BEING BUILT IN DY AREA
SETZB W2,W3 ;[1132] INIT IOWD
SKIPN LW.S1 ;[1132] IS JOBDAT STILL IN DY AREA?
JRST XCMLUP ;[1132] NO (NORMAL CASE), GO START WRITING
;FALL THROUGH TO NEXT PAGE
;FALL IN FROM ABOVE
;HERE IF THE LOWEST LOCATION IS IN PAGE 1 OR HIGHER, AND THE
;LC AREA IS PAGING TO DISK.
;IF THAT IS THE CASE, THEN JOBDAT IS IN A BLOCK IN THE DY AREA
;POINTED TO BY JOBPTR, INSTEAD OF IN THE LC AREA.
;WHAT WE WANT TO DO NOW IS WRITE JOBDAT INTO THE EXE FILE DIRECTLY
;FROM THE DY AREA, THEN JUMP INTO THE MAIN LOOP BELOW TO FINISH THE SAVE.
HRLOI W2,-.JBDA-1 ;[1132] FORM IOWD TO JOBDAT
ADD W2,JOBPTR ;[1132] ..
OUT DC,W2 ;[1132] WRITE JOBDAT TO THE EXE FILE
TXCA P4,DATAF!GAPF!1 ;[1132] CLEAR GAPF, SET DATAF, 1 PAGE WRITTEN
PUSHJ P,E$$EOE ;[1174] I/O ERROR
USETO DC,9 ;[1132] WRITE ZEROS INTO THE REST OF PAGE 0
SETZ W2, ;[1132] FLAG NO DATA TO WRITE
JRST XCMADP ;[1132] GO FIND NEXT PSECT
E$$ECE::PUSH P,[DC] ;[1174] GIVE OFFENDING CHANNEL TO LNKLOG
.ERR. (LRE,0,V%L,L%F,S%F,ECE,<Error creating EXE file>) ;[1174]
;THIS IS THE MAIN LOOP FOR THE EXE FILE WRITER.
;WE GET BACK HERE ON EACH NEW PSECT, ON EACH NEW BLOCK OF PAGES
;READ IN IF AN AREA HAS OVERFLOWED TO DISK, AND ON EACH PAGE OF
;EACH PSECT.
XCMLUP: SKIPE PAG.S0(R) ;[1132] AREA OVERFLOWING TO DISK
CAMG P3,UW.S0(R) ;[1132] AND OFF END OF WINDOW?
CAML P3,HC.S0(R) ;[1132] NO, BUT OFF END OF SEGMENT?
JRST XCMADV ;[1132] OFF END OF SOMETHING
MOVE T1,RC.HL(R2) ;[1132] FIRST ADDRESS BEYOND PSECT
SUB T1,LL.S0(R) ;[1132] CONVERT TO OFFSET IN SEGMENT, LIKE P3
CAML P3,T1 ;[1132] OFF END OF PSECT?
JRST XCMADV ;[1132] YES, GO FIND THE NEXT ONE
;TIME TO SAVE THE PAGE WHOSE ADDRESS IS IN P3. SEE IF IT'S ALL ZERO
HRRZ T1,P3 ;[1132] OFFSET INTO SEGMENT
SUB T1,LW.S0(R) ;[1132] OFFSET INTO CURRENT WINDOW
ADD T1,TAB.LB(R) ;[1132] ADDRESS OF PAGE IN LINK'S VAS
SKIPN W2 ;[1132] KNOW BASE OF IOWD YET?
MOVEI W2,-1(T1) ;[1132] NO, SET IT UP NOW
HRLI T1,-1000 ;[1132] SET UP AN AOBJN PTR TO THE PAGE
SKIPN (T1) ;[1132] NEXT WORD ZERO?
AOBJN T1,.-1 ;[1132] YES, LOOP OVER ALL THE PAGES
JUMPGE T1,XCMZER ;[1132] JUMP IF PAGE IS ALL ZERO
;HERE WHEN THE PAGE IS NON-ZERO
TXON P4,DATAF ;[1132] FLAG IN REAL DATA, FIRST TIME?
JRST XCMNWD ;[1132] YES, START A NEW DIRECTORY ENTRY
ADD W2,[-1000,,0] ;[1132] NO, JUST BUMP OUTPUT IOWD
ADDI P4,1 ;[1132] REMEMBER DATA PAGES WRITTEN
ADD P2,[1B8] ;[1132] AND REPEAT COUNT FOR THIS ENTRY
JRST XCMADP ;[1132] ADVANCE TO THE NEXT PAGE
XCMNWD: TXZ P4,ZEROF ;[1132] NO LONGER IN A ZERO AREA
TXZN P4,GAPF ;[1132] WERE WE IN A GAP?
PUSHJ P,XCMPRD ;[1132] NO, WRITE DIR ENTRY OUT
HRRZ W2,P3 ;[1132] START A NEW IOWD
SUB W2,LW.S0(R) ;[1132] MAKE ADDR INTO OFFSET FROM WINDOW START
ADD W2,TAB.LB(R) ;[1132] AND THENCE TO ADDR IN LINK
SUB W2,[1000,,1] ;[1132] CONVERT TO ONE PAGE IOWD
MOVE P2,P3 ;[1132] COMPUTE NEW PROCESS PAGE
ADD P2,LL.S0(R) ;[1132] BY FINDING PROCESS ADDRESS
LSH P2,-9 ;[1132] THEN SHIFTING TO GET A PAGE NUMBER
ADDI P4,1 ;[1132] WILL WRITE 1 MORE DATA PAGE
JRST XCMADP ;[1132] GO ADVANCE TO NEXT PAGE
;HERE ON AN ALL-ZERO PAGE
XCMZER: TXON P4,ZEROF ;[1132] IS THIS THE FIRST ALL-ZERO PAGE?
JRST XCMNWZ ;[1132] YES, GO SETUP A NEW DIR ENTRY
ADD P2,[1B8] ;[1132] JUST BUMP REPEAT COUNT
JRST XCMADP ;[1132] ADVANCE TO THE NEXT PAGE
;HERE IF THE ALL-ZERO PAGE IS THE FIRST ONE AFTER DATA OR A GAP.
;IF DATA, WRITE IT OUT AND STORE THE DIR ENTRY. ALWAYS SET UP A NEW ENTRY.
XCMNWZ: TXZ P4,DATAF ;[1132] NO LONGER WRITING DATA
TXZN P4,GAPF ;[1132] NOT IN A GAP. WERE WE?
PUSHJ P,XCMPRD ;[1132] NO, WRITE THE DATA DIR ENTRY
ADDI P1,(P4) ;[1132] BUMP FILE PAGE COUNT
HLLZS P4 ;[1132] CLEAR ACCUMULATED COUNT
SKIPGE W2 ;[1132] SEEN ANY DATA PAGES?
OUT DC,W2 ;[1132] YES, WRITE THEM
TDZA W2,W2 ;[1132] SUCCESS, CLEAR IOWD
JRST E$$EOE ;[1174] I/O ERROR
MOVE P2,P3 ;[1132] SET UP NEW PROCESS PAGE
ADD P2,LL.S0(R) ;[1132] BY COMPUTING PROCESS ADDRESS
LSH P2,-9 ;[1132] THEN SHIFTING TO A PAGE NUMBER
;HERE TO ADVANCE TO THE NEXT PAGE.
XCMADP: ADDI P3,1000 ;[1132] POINT TO NEXT PAGE
JRST XCMLUP ;[1132] LOOP BACK TO PROCESS IT
;HERE WHEN WE RAN OFF THE END OF THE PSECT, THE SEGMENT, OR THE WINDOW.
;FIGURE OUT WHAT TO PROCESS NEXT.
XCMADV: SKIPGE W2 ;[1132] ANY DATA STILL TO WRITE?
OUT DC,W2 ;[1132] YES, WRITE IT
TDZA W2,W2 ;[1132] SUCCESS, CLEAR IOWD POINTER
JRST E$$EOE ;[1174] I/O ERROR
CAML P3,HC.S0(R) ;[1132] OFF THE END OF THE SEGMENT?
JRST XCMBLK ;[1132] YES, GO WRITE ABZ PAGES AND ADVANCE
CAML P3,RC.HL(R2) ;[1132] OFF END OF PSECT?
JRST XCMNXP ;[1132] YES, GO FIND THE NEXT ONE
;HERE IF PAGING AND WE RAN OFF THE END OF THE CURRENT LC/HC WINDOW.
;ADVANCE THE WINDOW AND LOOP BACK.
MOVEM P3,LW.S0(R) ;[1132] STORE NEW LOWER WINDOW BOUND
MOVE T1,P3 ;[1132] VIRTUAL ADDRESS OF 1ST WORD TO READ
ADD T1,TAB.AB(R) ;[1132] CONVERT TO VIRTUAL ADDRESS OF LAST WORD
SUB T1,TAB.LB(R) ;[1132] BY ADDING SIZE OF LC/HC AREA
MOVEM T1,UW.S0(R) ;[1132] STORE NEW UPPER WINDOW BOUND
CAMGE T1,HC.S0(R) ;[1132] DOES THE AREA CONTAIN THAT MUCH?
JRST XCMRED ;[1132] YES, JUST GO READ IT IN
SUB T1,HC.S0(R) ;[1132] NO, FIGURE OUT HOW MUCH EXTRA WE HAVE
ADDI T1,1 ;[1172] SUBTRACTED ONE TOO MUCH, HC IS FF FORMAT
ANDCMI T1,.IPM ;[1132] PUT ON THE PAGE BOUND
MOVN T1,T1 ;[1132] DECREMENT THE AB OF THE AREA
ADDM T1,TAB.AB(R) ;[1132] SO EXTRA SPACE IS AVAILABLE TO OTHERS
ADDM T1,UW.S0(R) ;[1132] AREN'T GOING TO READ THAT MUCH AFTER ALL
MOVE T1,UW.S0(R) ;[1132] LAST ADDRESS TO READ
XCMRED: HRL T1,P3 ;[1132] FIRST,,LAST
PUSHJ P,@TB.IN(R) ;[1132] READ IN THE NEXT WINDOW
JRST XCMLUP ;[1132] LOOP BACK TO PROCESS THE NEXT PAGE
;HERE IF WE RAN OFF THE END OF THIS SEGMENT (LC OR HC). WRITE ENOUGH
;ALLOCATED BUT ZERO PAGES INTO THE EXE DIRECTORY TO ALLOCATE THE REST
;OF THE CURRENT PSECT AS ALL ZEROS.
XCMBLK: MOVE R3,RC.HL(R2) ;[1132] GET FIRST WORD BEYOND PSECT END
ADDI R3,777 ;[1132] LAST WORD TO ALLOCATE + A PAGE
ANDCMI R3,777 ;[1132] GET START OF THAT PAGE
SUB R3,P3 ;[1132] COMPUTE EXTRA PAGES THAT NEED ALLOCATING
SUB R3,LL.S0(R) ;[1132] P3 IS AN OFFSET, BUT R3 IS AN ADDRESS
JUMPLE R3,XCMNXP ;[1132] NONE, GO FIND THE NEXT PSECT TO PROCESS
TXON P4,ZEROF ;[1132] WERE WE WRITING ZEROS BEFORE THIS?
JRST XCMBL2 ;[1132] NO, MUST START A NEW DIR ENTRY
ADD P3,R3 ;[1132] KEEP OFFSET INTO SEGMENT CORRECT
MOVSI R3,(R3) ;[1132] PUT COUNT WHERE EXE DIR ENTRY WANTS IT
ADD P2,R3 ;[1132] JUST BUMP REPEAT COUNT
JRST XCMNXP ;[1132] AND GO PROCESS THE NEXT PSECT
;HERE WHEN WE WANT TO WRITE AN ABZ DIRECTORY ENTRY, BUT WE HAVE ANOTHER
;TYPE OF ENTRY IN PROGRESS. WRITE THE CURRENT ENTRY, THEN START A NEW ONE.
XCMBL2: TXZ P4,DATAF ;[1132] REMEMBER NO LONGER WRITING DATA
TXZN P4,GAPF ;[1132] WERE WE IN A GAP?
PUSHJ P,XCMPRD ;[1132] NO, WRITE THE DIRECTORY ENTRY
ADDI P1,(P4) ;[1132] BUMP FILE PAGE POINTER
HLLZS P4 ;[1132] RESET FILE PAGE COUNT
MOVE P2,P3 ;[1132] FIRST OFFSET TO WRITE
ADD P2,LL.S0(R) ;[1132] FIRST ADDRESS TO WRITE
LSH P2,-^D9 ;[1132] FIRST PAGE NOT YET WRITTEN
ADD P3,R3 ;[1132] KEEP OFFSET INTO SEGMENT CORRECT
MOVSI R3,-1000(R3) ;[1132] PUT COUNT WHERE EXE DIR ENTRY WANTS IT
ADD P2,R3 ;[1132] INSERT REPEAT COUNT FROM ABOVE
;HERE TO ADVANCE TO THE NEXT PSECT, IF ANY
XCMNXP: PUSHJ P,ADVPSC ;[1132] CALL A SUBROUTINE TO DO THE WORK
JRST XCMPRX ;[1132] ALL DONE, GO CLOSE THE FILE
JRST XCMLUP ;[1132] FOUND ANOTHER PSECT, LOOP BACK FOR IT
;ADVPSC -- SUBROUTINE TO ADVANCE TO THE NEXT PSECT.
;CALL:
; SET UP P1-P4 AS IN XCMPRS
; PUSHJ P,ADVPSC
; ALL DONE
; ANOTHER PSECT FOUND
;
;ON THE SKIP RETURN, P1-P4 HAVE BEEN SET UP TO POINT TO THE START OF
;THE NEXT PSECT, INCLUDING PSECT PROPERTIES IN P1.
;THIS ROUTINE ALSO CHECKS TO SEE IF THE OVERLAY SYMBOL TABLE NEEDS TO
;BE APPENDED AFTER THE PSECT OR SEGMENT THAT JUST GOT WRITTEN, AND
;APPENDS IT IF SO.
ADVPSC:
IFN FTOVERLAY,<
CAIN R,1 ;[1132] IN LOW SEGMENT?
CAMGE P3,HL.S1 ;[1132] AND JUST FINISHED IT?
JRST ADVPS1 ;[1132] NO, PROCEED
SKIPL LNKMAX ;[1132] YES, LOADING OVERLAYS?
SKIPN JOB116 ;[1132] AND SYMBOLS NEED INSERTING?
JRST ADVPS1 ;[1132] NO, PROCEED
PUSHJ P,XCMPOV ;[1132] YES, PUT SYMBOLS INTO EXE FILE
ADVPS1:
> ;END IFN FTOVERLAY
ADD P3,LL.S0(R) ;[1132] P3 WILL BE AN ADDRESS FOR THIS ROUTINE
AOS R,RC.CUR ;[1132] GET PSECT INDEX OF NEXT PSECT
CAMG R,RC.NO ;[1132] IS THERE A NEXT ONE?
JRST ADVPS2 ;[1132] YES, GO PROCESS IT
SOS (P) ;[1132] GIVE NON-SKIP RETURN
JRST ADVPS6 ;[1132] BUT WRITE CURRENT ENTRY FIRST
;HERE WHEN THERE IS ANOTHER PSECT, AND R CONTAINS ITS INDEX.
;POINT R AND R2 TO IT, THEN SET UP ITS PSECT PROPERTIES IN R3
ADVPS2: MOVE R2,@RC.TB ;[1132] POINT TO RC BLOCK FOR PSECT
MOVE R,RC.SG(R2) ;[1132] PUT SEGMENT PSECT IS IN INTO R
MOVX R3,SV%WRT ;[1132] GET ASSUMED PSECT PROPERTY
MOVE T1,RC.AT(R2) ;[1132] GET REAL PSECT PROPERTIES
TXNE T1,AT.RO ;[1132] EXPLICITLY READ-ONLY?
TXZ R3,SV%WRT ;[1132] YES, CLEAR WRITE BIT
CAIE R,2 ;[1132] IS THIS THE HIGH SEGMENT?
JRST ADVPS4 ;[1132] NO, PSECT PROPERTIES OK AS THEY ARE
IFE TOPS20,<
TXO R3,SV%HIS ;[1132] TOPS-10 HIGH SEG, READ-ONLY
TXNN T1,AT.RW ;[1132] EXPLICITLY WRITE-ENABLED?
TXZ R3,SV%WRT ;[1132] NO, WRITE-LOCK IT
MOVE T1,SSEXT ;[1132] GET SAVE/SSAVE FLAGS
TXNE T1,SS.SHR ;[1132] USER TYPE /SSAVE?
> ;END IFE TOPS20
TXO R3,SV%SHR ;[1132] /SSAVE OR TOPS-20, MARK SHARABLE
;FALL INTO NEXT PAGE
;HERE WHEN PSECT PROPERTIES COMPUTED IN R3.
;NOW DETERMINE WHETHER TO STORE THIS DIRECTORY ENTRY AND START ANOTHER,
;OR TO JUST LET THIS ONE CONTINUE.
;CAN ONLY LET THIS ONE CONTINUE IF NEXT PSECT IS ADJACENT WITH SAME PROPERTIES.
ADVPS4: MOVE T1,RC.IV(R2) ;[1132] GET BOTTOM OF NEW PSECT
ANDCMI T1,777 ;[1132] ROUND DOWN TO PAGE BOUND
CAMLE T1,P3 ;[1132] IS THERE A PSECT GAP HERE?
JRST [MOVE P3,T1 ;[1132] YES, START NEXT LOOP AT BASE OF NEW ONE
JRST ADVPS6] ;[1132] AND GO DUMP THIS DIRECTORY ENTRY
MOVE T2,R3 ;[1132] COPY OF PSECT PROPERTIES
XOR T2,P1 ;[1132] COMPARE WITH OLD
TXNN T2,777B8 ;[1132] SAME AS LAST TIME?
JRST ADVPS8 ;[1132] YES, CAN CONTINUE CURRENT DIR ENTRY
;ENTER HERE IF ALL DONE TO WRITE OUT THE LAST DIRECTORY ENTRY AND RETURN.
ADVPS6: TXC P4,DATAF!ZEROF ;[1132] XCMPRD WANTS THE FLAGS REVERSED
TXNN P4,GAPF ;[1132] IN A GAP FROM LAST TIME?
PUSHJ P,XCMPRD ;[1132] NO, WRITE CURRENT DIR ENTRY
ADDI P1,(P4) ;[1132] BUMP FILE PAGE COUNT
MOVX P4,GAPF ;[1132] FLAG NOW IN A GAP, CLEAR RH P4
ADVPS8: SUB P3,LL.S0(R) ;[1132] MAKE P3 AN OFFSET INTO NEW SEGMENT
TXZ P1,777B8 ;[1132] CLEAR OLD PSECT PROPERTIES
IOR P1,R3 ;[1132] SET NEW PSECT PROPERTIES
JRST CPOPJ1 ;[1132] GIVE GOOD RETURN TO CALLER
;HERE TO WRITE OUT A DIRECTORY ENTRY
XCMPRD: PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
MOVEM P1,(W1) ;STORE DIRECTORY PTRS
TXNN P4,ZEROF ;[1132] ZERO PAGE? (FLAGS ALREADY CHANGED)
HLLZS (W1) ;YES, SO NO FILE PAGES
PUSHJ P,XCMPXD ;SECOND WORD
MOVEM P2,(W1) ;[1132]
POPJ P, ;[1132]
;HERE TO ALLOCATE A DIRECTORY ENTRY IF SUFFICIENT ROOM EXISTS.
;IF NOT, EXTEND THE FILE BY ONE PAGE TO MAKE ROOM FOR ANOTHER
;PAGE OF DIRECTORY.
XCMPXD: AOBJN W1,CPOPJ ;ALLOCATE IF ENOUGH ROOM
;WRITE THE CURRENT PAGE OF THE EXE DIRECTORY TO DISK.
;THEN START FROM THE FRONT OF THE FILE, AND FIX ALL PAGES OF
;EXE DIRECTORY PRESENT, INCLUDING THE ONE WE JUST WROTE.
HRLOI T3,-1000-1 ;[1132] FORM IOWD TO IN CORE EXE DIRECTORY
ADD T3,EXEDIR ;[1132] ..
SETZ T4, ;[1132] TERMINATE IO LIST
USETO DC,@EXEBLK ;[1132] SET TO LATEST EXE DIRECTORY BLOCK
OUT DC,T3 ;[1132] WRITE THE DIRECTORY
CAIA ;[1132] SUCCESS
JRST E$$EOE ;[1174] IO ERROR
MOVEI W1,1 ;[1132] NOW LOOP OVER DIR, STARTING AT BLOCK 1
XCMPXE: USETI DC,@W1 ;[1132] SET ON NEXT PAGE OF EXE DIR
IN DC,T3 ;[1132] READ IT INTO SCRATCH PAGE
CAIA ;[1132] OK
JRST E$$EOE ;[1174] FAILED
MOVE T2,EXEDIR ;[1132] NOW SETUP AOBJN PTR TO EXE DIR PAGE
HRLI T2,-400 ;[1132] COUNT OF DIR ENTRIES THIS PAGE
XCMPXF: MOVE T1,1(T2) ;[1132] GET 1ST WORD OF NEXT ENTRY
TRNE T1,-1 ;[1132] AN ABZ POINTER?
AOS 1(T2) ;[1132] NO, BUMP THE FILE PAGE NUMBER
ADDI T2,1 ;[1132] SKIP 2ND WORD OF THIS DIR ENTRY
AOBJN T2,XCMPXF ;[1132] LOOP OVER THE ENTIRE PAGE
USETO DC,@W1 ;[1132] POINT TO WHERE WE GOT THE PAGE
OUT DC,T3 ;[1132] PUT IT BACK, SLIGHTLY MODIFIED
CAIA ;[1132] OK
JRST E$$EOE ;[1174] I/O ERROR
ADDI W1,4 ;[1132] BLOCK NUMBER OF NEXT PAGE
CAMG W1,EXEBLK ;[1132] MORE DIRECTORY PAGE(S) TO PROCESS?
JRST XCMPXE ;[1132] YES, PROCESS THEM
MOVEM W1,EXEBLK ;[1132] PAGE WE'RE FREEING UP FOR MORE DIRECTORY
;FALL IN FROM ABOVE
;NOW TO LOOP OVER THE FILE BACKWARDS, MOVING ALL OF THE DATA PAGES
;ONE PAGE HIGHER.
MOVEI W1,-1(P1) ;[1132] LAST PAGE WRITTEN
ADDI W1,0(P4) ;[1132] PLUS ANY FOUND IN THIS DIR ENTRY
ASHC W2,-^D27 ;[1132] NEED TO LOOK AT IOWD, SINCE PAGES
ADD W1,W2 ;[1132] IT POINTS TO HAVEN'T BEEN WRITTEN
ASHC W2,^D27 ;[1132] RESET IOWD TO PREVIOUS VALUE
SETZ W3, ;[1132] CLEAR SIGN BIT LEFT FROM ASHC
LSH W1,2 ;[1132] CONVERT PAGE TO BLOCK NUMBET
ADDI W1,1 ;[1132] BLOCK NUMBERS START AT 1
MOVEI T2,10(W1) ;[1132] REMEMBER NEXT BLOCK TO WRITE FOR LATER
XCMPXG: CAMGE W1,EXEBLK ;[1132] ANY DATA PAGES LEFT TO COPY?
JRST XCMPXH ;[1132] NO, GO FINISH UP
USETI DC,@W1 ;[1132] POINT TO NEXT DATA PAGE
IN DC,T3 ;[1132] READ IT
CAIA ;[1132] OK
JRST E$$EOE ;[1174] ERROR
OUT DC,T3 ;[1132] WRITE IT INTO THE NEXT PAGE
CAIA ;[1132] OK
JRST E$$EOE ;[1174] ERROR
SUBI W1,4 ;[1132] BACK UP ONE MORE DATA BLOCK
JRST XCMPXG ;[1132] LOOP OVER ALL DATA PAGES
;HERE WHEN THE DIRECTORY AND THE FILE HAVE BEEN UPDATED.
;FIX THE POINTERS THAT OUR CALLERS LOOK AT, THEN RETURN.
XCMPXH: USETO DC,@T2 ;[1132] NEXT WRITE TO NEXT FREE BLOCK
ADDI P1,1 ;[1132] THIS DIR ENTRY IS ONE OFF TOO
MOVE W1,EXEDIR ;[1132] RESET DIR AOBJN PTR FOR NEXT CALL
HRLI W1,-1000 ;[1132] SET UP COUNT FOR INITIAL AOBJN
HRLZ T1,W1 ;[1132] NOW ZERO THE DY AREA BLOCK
HRRI T1,1(W1) ;[1132] ..
SETZM 0(W1) ;[1132] ..
BLT T1,777(W1) ;[1132] ..
POPJ P, ;[1132] RETURN TO CALLER
IFN FTOVERLAY,<
;HERE WHEN GENERATING AN EXE FILE FOR THE ROOT OF AN OVERLAID PROGRAM,
;AND IT IS TIME TO INSERT THE LOCAL SYMBOLS FROM THE LS AREA INTO THE
;EXE FILE. ALL ZEROS BEFORE THE SYMBOLS AND THE FIRST PARTIAL PAGE OF
;SYMBOLS HAVE ALREADY BEEN COPIED INTO THE EXE FILE, SINCE THEY WERE
;PUT INTO THE LC AREA AT JBEXE.
XCMPOV: HRRZ T1,JOB116 ;[1132] SYMBOLS ARE NOT PAGE ALIGNED IN LS
ANDI T1,777 ;[1132] SO PUT OFFSET TO FIRST SYM IN R3
MOVEI R3,1000 ;[1132] OFFSET IS REST OF PAGE NOT COPIED
SUB R3,T1 ;[1132] AT JBEXE
SETZB R2,P3 ;[1132] ASSUME LS AREA ISN'T PAGING
SKIPN PAG.LS ;[1132] IS THE LS AREA PAGING?
JRST XOVDMP ;[1132] NO, JUST DUMP IT TO THE EXE FILE
MOVE T1,LW.LS ;[1132] CALCULATE UPPER WINDOW
ADD T1,LS.AB ;[1132] FROM LOWER WINDOW + SIZE
SUB T1,LS.LB ;[1132] SO WE CAN WRITE OUT CURRENT LS AREA
MOVEM T1,UW.LS ;[1132] SAVE IT IN CASE IT WAS -1
HRL T1,LW.LS ;[1132] FIRST,,LAST FOR LS.OUT
PUSHJ P,LS.OUT ;[1132] UPDATE THE DISK COPY
PUSHJ P,FR.CNT## ;[1132] SEE HOW MUCH ROOM IS LEFT
MOVE T2,LSYM ;[1132] COUNT OF WORDS IN THE LS AREA
SUBI T2,1 ;[1132] CONVERT FIRST FREE TO LAST USED
IORI T2,777 ;[1132] ROUND UP TO PAGE END
MOVE T3,LS.AB ;[1132] FIND CURRENT SIZE OF LS AREA
SUB T3,LS.LB ;[1132] AS END - START
CAMG T2,T3 ;[1132] IS AREA BIG ENOUGH?
JRST XOVNXW ;[1132] YES, JUST DUMP IT TO THE FILE
SUB T2,T3 ;[1132] EXTRA WE NEED
CAMLE T1,T2 ;[1132] LESS THAN WE HAVE?
MOVE T1,T2 ;[1132] YES, DON'T ASK FOR MORE THAN WE NEED
SETOM LS.PP ;[1132] DON'T PAGE THE LS AREA TO SATISFY THIS
SPUSH <P1,P2> ;[1132] SAVE CURRENT EXE DIR ENTRY
MOVEI P1,LS.IX ;[1132] EXPAND THE LS AREA
MOVE P2,T1 ;[1132] BY THIS MUCH
PUSHJ P,LNKCOR## ;[1132] GO SHUFFLE
PUSHJ P,E$$MEF## ;[1174] FR.CNT LIED!!
SPOP <P2,P1> ;[1132] RESTORE THE SACRED COWS
SETZM LS.PP ;[1132] LS AREA CAN PAGE NOW
;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE
;HERE WHEN THE LS AREA IS PAGING TO BRING THE NEXT WINDOW OF SYMBOLS
;IN TO BE WRITTEN TO THE EXE FILE. P3 HAS THE FIRST ADDRESS TO READ IN
;STORED IN IT, AND WE WILL PUT THE COUNT OF HOW FAR THIS PASS FAILED TO
;FINISH BY IN R2.
XOVNXW: MOVEM P3,LW.LS ;[1132] INIT LOWER WINDOW
ADD P3,LS.AB ;[1132] NOW COMPUTE UPPER WINDOW
SUB P3,LS.LB ;[1132] AS LOWER+SIZE
MOVEM P3,UW.LS ;[1132] STORE FOR LS.IN
ANDCMI P3,777 ;[1132] FIRST TO READ NEXT TIME
MOVE R2,LSYM ;[1132] END OF SYMBOLS
SUBI R2,1 ;[1132] LAST WORD CONTAINING SYMBOLS
IORI R2,777 ;[1132] THE END OF THAT PAGE
SUB R2,UW.LS ;[1132] FIND OUT HOW FAR YET TO GO
JUMPGE R2,XOVNX2 ;[1132] ALL OK UNLESS THIS TIME WILL END IT
ADDM R2,LS.AB ;[1132] REDUCE SIZE OF WINDOW
ADDM R2,UW.LS ;[1132] AND LAST ADDRESS IN WINDOW
XOVNX2: HRLZ T1,LW.LS ;[1132] SET UP LOWEST,,HIGHEST
HRR T1,UW.LS ;[1132] FOR LS.IN
PUSHJ P,LS.IN ;[1132] READ IN THE NEXT BLOCK OF SYMBOLS
JUMPLE R2,XOVDMP ;[1132] IF LAST TIME, WRITE ALL OF LS AREA
MOVE T1,UW.LS ;[1132] NOT LAST TIME, ONLY WRITE THROUGH
ANDCMI T1,777 ;[1132] FIRST PART OF LAST PAGE
TROA T1,R3 ;[1132] WILL GET REST OF THAT PAGE NEXT PASS
XOVDMP: MOVE T1,LSYM ;[1132] LAST TIME, WRITE THROUGH THE END
MOVE W2,LW.LS ;[1132] PUT IOWD TO SYMBOLS TO WRITE IN W2
ADD W2,R3 ;[1132] DON'T START AT BEGINNING OF LS
SUB W2,T1 ;[1132] -COUNT IS FIRST-LAST
HRLZ W2,W2 ;[1132] -COUNT,,0
HRR W2,LS.LB ;[1132] -COUNT,,BOTTOM OF LS AREA
ADDI W2,-1(R3) ;[1132] BUT DON'T START WRITING AT START
OUT DC,W2 ;[1132] WRITE THE SYMBOLS
TDZA W2,W2 ;[1132] CLEAR W2 AGAIN IN CASE DONE
JRST E$$EOE ;[1174] I/O ERROR
JUMPG R2,XOVNXW ;[1132] IF NOT DONE, LOOP BACK TO TRY AGAIN
SKIPE PAG.LS ;[1132] ALL DONE, ANY TEMP FILE?
PUSHJ P,LS.DLT ;[1132] YES, DELETE IT
PUSHJ P,LS.ZAP ;[1132] ALL DONE WITH LS AREA
;FALL INTO NEXT PAGE
;FALL IN FROM ABOVE
;NOW THAT THE DATA HAS BEEN WRITTEN, UPDATE THE EXE DIRECTORY TO
;REFLECT THE CHANGE. ALSO ZERO THE REST OF THE LAST PAGE WITH A USETO.
HRRZ R3,JOB116 ;[1132] START OF SYMBOL TABLE
HLRE T1,JOB116 ;[1132] - COUNT
SUB R3,T1 ;[1132] FIRST WORD BEYOND TABLE
ADDI R3,777 ;[1132] ROUND UP TO NEXT PAGE BOUND
ANDCMI R3,777 ;[1132] FIRST PAGE NOW FREE
HRRZ P3,JOB116 ;[1132] FIRST WORD WRITTEN
ADDI P3,777 ;[1132] ROUND UP TO PAGE BOUND
ANDCMI P3,777 ;[1132] SO WE DON'T COUNT SYMS WRITTEN AT JBEXE
SUB R3,P3 ;[1132] R3 NOW HAS COUNT OF WORDS WRITTEN HERE
HRRZ T1,P1 ;[1132] FIRST DISK PAGE FREE BEFORE XCMPOV
ADDI T1,(P4) ;[1132] ACCOUNT FOR EXTRA OUTS DONE
MOVE R2,R3 ;[1132] NUMBER OF WORDS WRITTEN HERE
LSH R2,-^D9 ;[1132] NUMBER OF PAGES WE ADDED TO THE EXE FILE
ADD T1,R2 ;[1132] NEW FIRST FREE = OLD + COUNT
LSH T1,2 ;[1132] CONVERT TO BLOCKS FOR USETO
USETO DC,1(T1) ;[1132] SET FILE POINTER TO FIRST FREE BLOCK
TXON P4,DATAF ;[1132] NOW IN A DATA DIR ENTRY, FIRST TIME?
JRST XOVNWD ;[1132] YES, GO DUMP OLD DIR ENTRY AND START NEW
ADD P3,R3 ;[1132] MAKE P3 BE THE FIRST FREE ADDRESS
MOVSI R3,(R3) ;[1132] TURN WORD COUNT INTO PAGE COUNT IN LH
ADD P2,R3 ;[1132] BUMP COUNT IN DIR ENTRY
ADD P4,R2 ;[1132] COUNT FILE PAGES WRITTEN HERE
POPJ P, ;[1132] DONE, BACK TO ADVPSC
;HERE TO START A NEW EXE DIRECTORY ENTRY
XOVNWD: TXZ P4,ZEROF ;[1132] NO LONGER WRITING AN ABZ ENTRY
TXZN P4,GAPF ;[1132] NOR IN A GAP. WERE WE?
PUSHJ P,XCMPRD ;[1132] NO, WRITE CURRENT DIR ENTRY
ADDI P1,(P4) ;[1132] BUMP FILE PAGE NUMBER
HRR P4,R2 ;[1132] ACCOUNT FOR PAGES WRITTEN HERE
MOVE P2,P3 ;[1132] FIRST WORD WE WROTE HERE
LSH P2,-^D9 ;[1132] FIRST PAGE WE WROTE HERE
ADD P3,R3 ;[1132] MAKE P3 POINT TO FIRST WORD BEYOND SYMS
MOVSI R3,-1000(R3) ;[1132] CONVERT WORD CNT INTO EXE DIR PAGE CNT
ADD P2,R3 ;[1132] NOW HAVE A NEW EXE DIR SLOT
POPJ P, ;[1132] DONE
>;[1214] END IFN FTOVERLAY
;HERE WHEN DONE WRITING THE MEMORY IMAGE TO THE EXE FILE.
;WRITE THE START ADDRESS BLOCK, DELETE THE TEMP FILES, AND
;RETURN THE EXE DIRECTORY STORAGE TO FREE SPACE.
XCMPRX: SKIPE PAG.S1 ;[1132] STILL GOT AN LC TEMP FILE?
PUSHJ P,LC.DLT ;[1132] YES, DELETE IT
SKIPE PAG.S2 ;[1132] HOW ABOUT AN HC TEMP FILE?
PUSHJ P,HC.DLT ;[1132] YES, DELETE IT
IFN TOPS20,<
MOVE T1,STADDR ;GET ENTRY VECTOR
TLNN T1,-1 ;JUST AN ADDRESS
HRLI T1,(JRST) ;YES, MAKE COMPATIBLE WITH OLD
PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
MOVE T2,[.SVEVC,,3] ;STORE 2 WORD EVEC
MOVEM T2,(W1) ;STORE HEADER
PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
HLRZM T1,(W1) ;STORE COUNT
PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
HRRZM T1,(W1) ;STORE ADDRESS
XCMPRV:>
MOVE T1,[.SVEND,,1] ;END MARKER
PUSHJ P,XCMPXD ;SEE IF ENOUGH ROOM
MOVEM T1,(W1) ;STORE IT
MOVEI W1,(W1)
SUB W1,EXEDIR ;GET LENGTH
IFN TOPS20,<
SUBI W1,3 ;DON'T COUNT ENTRY VECTOR BLOCK
>
HRLI W1,.SVDIR ;HEADER
MOVE T3,EXEBLK ;SEE WHICH DIRECTORY BLOCK
CAIG T3,1 ;INCASE NOT FIRST
MOVEM W1,@EXEDIR ;COMPLETE BLOCK
USETO DC,@EXEBLK ;NOW TO WRITE THE DIRECTORY
HRRZ T1,EXEDIR
SUBI T1,1
HRLI T1,-1000 ;IOWD
SETZ T2,
OUT DC,T1 ;WRITE IT
CAIA ;OK
JRST E$$EOE ;[1174] ERROR
CAIE T3,1 ;WAS IT JUST SIMPLE CASE?
JRST [USETI DC,1 ;NO
IN DC,1 ;READ BACK FIRST DIRECTORY BLOCK
LSH T3,-2 ;SEE HOW MANY PAGES
IMULI T3,1000 ;ACCOUNT FOR ALL WORDS
ADDI W1,(T3) ;GRAND TOTAL
MOVEM W1,@EXEDIR ;NOW STORE
USETO DC,1 ;WRITE IT BACK
OUT DC,T1
JRST .+1 ;OK
JRST E$$EOE] ;[1174] ERROR
MOVE T1,EXEDIR ;GET BASE AGAIN
MOVEI T2,1000 ;LENGTH
PUSHJ P,DY.RET## ;GIVE SPACE BACK
JRST ENDCMP ;CLOSE FILE
E$$EOE::PUSH P,[DC] ;[1174]
.ERR. (ST,,V%L,L%F,S%F,EOE,<EXE file output error>) ;[1174]
>;END OF IFN FTEXE
IFE FTEXE,<
;HERE FOR ZERO COMPRESSOR
;NOTE! LIKE THE MONITOR WE REMOVE ALL ZEROS (FILEX LEAVES SINGLE ZEROS)
ZCMPRS: MOVE P2,LC.LB ;OUTPUT POINTER
MOVEI P1,.JBSDD-1(P2) ;INPUT POINTER
HRLZ T1,P2 ;FORM BLT POINTER
HRRI T1,1(P2) ;TO CLEAR NON-SAVED PART OF FILE
SETZM (P2) ;CLEAR
BLT T1,-1(P1)
MOVE P3,P2 ;POINT TO PARTIAL IOWD
;EXCEPT WE HAVEN'T SET IT UP YET
;HOWEVER SINCE SOME OF JOBDAT IS NON-ZERO
SKIPN T1,1(P1) ;WE WILL EVENTUALLY FIND A DATUM
AOJA P1,.-1 ;IF WE LOOK LONG ENOUGH
MOVE T2,P1 ;GET ADDRESS
SUB T2,LC.LB ;MINUS CORE OFFSET
ADD T2,LW.S1 ;PLUS WINDOW OFFSET
HRRZM T2,(P3) ;STORE USER ADDRESS
ZCMPR0: SETO P4, ;INITIALIZE ZERO COUNTER
ZCMPR1: ADDI P2,1 ;BUMP COUNT
MOVEM T1,0(P2) ;STORE DATUM
ZCMPR2: ADDI P1,1 ;INCREMENT READIN POINTER
CAML P1,LC.AB ;BUT NOT TOO FAR
JRST ZCMPR5 ;FINISHED OR GET NEXT WINDOW FULL
ZCMPR3: SKIPN T1,1(P1) ;GET NEXT DATUM
AOJA P4,ZCMPR2 ;COUNT A ZERO
JUMPL P4,ZCMPR1 ;NO ZEROS SEEN
MOVE T2,P1 ;GET ADDRESS
SUB T2,LC.LB ;MINUS CORE OFFSET
ADD T2,LW.S1 ;PLUS WINDOW
HRRZM T2,1(P2) ;STORE NEXT IOWD TO BE
MOVEI T2,(P3) ;LAST IOWD
SUBI T2,(P2) ;MINUS CURRENT GIVES -LENGTH
SKIPE T2 ;ALREADY BEEN DONE IF 0
HRLM T2,(P3) ;FIXUP IOWD
AOS P3,P2 ;POINT TO THIS NEW POINTER
JRST ZCMPR0 ;AND GET NEXT DATUM
;HERE WHEN CURRENT WINDOW IS FULL
ZCMPR5: SKIPN LSTPAG ;LAST PAGE IN CORE IF PAGING
SKIPN PAG.S1 ;ALWAYS IN CORE IF NOT
JRST ZCMPR6 ;YES, CAN WRITE OUT ALL OF CORE NOW
MOVE T1,P3 ;HIGHEST ADDRESS WE CAN OUTPUT
IORI T1,.IPM ;HOWEVER IT MAY NOT BE IN LAST BLOCK
CAML T1,P2 ;IN WHICH CASE CREATE AN IOWD AND OUTPUT
;IT ANYWAY. THIS MEANS SAVE FILES
;WILL NOT BE BIT IDENTICAL UNTIL EXPANDED.
JRST ZCMPR7 ;OK, ZERO SEEN IN THIS BLOCK
MOVEI T2,(P3) ;LAST IOWD
SUBI T2,(P2) ;MINUS CURRENT GIVES -LENGTH
HRLM T2,(P3) ;FIXUP IOWD
MOVEI T1,1(P2) ;[652] THIS IS THE HIGHEST TO OUTPUT
MOVE P3,P2 ;MAKE NEW IOWD POINT TO CURRENT POSITION
SKIPGE P4 ;IF WE ARE NOT READING ZEROS
SETZ P4, ;SIGNAL NEW IOWD NEEDED
JRST ZCMPR7 ;OUTPUT WHAT WE HAVE
;HERE TO FIXUP FINAL POINTER AND SET TO WRITE OUT LAST OF CORE IMAGE
ZCMPR6: MOVEI T2,(P2) ;GET ADDRESS
SUBI T2,(P3) ;GIVES LENGTH
MOVN T2,T2 ;NEGATE
HRLM T2,(P3) ;FIXUP IOWD
IFN FTOVERLAY,<
SKIPL LNKMAX ;SEEN ANY OVERLAYS?
SKIPN T1,JOB116 ;AND WANT SYMBOLS?
JRST ZCMP6S ;NO
SUBI T1,1 ;IOWD IS 1 LESS
MOVEM T1,1(P2) ;STORE IOWD
HLRE T2,T1 ;- LENGTH
MOVM T2,T2
SKIPN PAG.LS ;PAGING SYMBOLS?
JRST ZCMP6R ;NO
SETZM LW.LS ;BRING IN THE BASE
SETOM LS.PP ;CERTAINLY CAN'T PAGE IT NOW
PUSHJ P,FR.CNT## ;THERE SHOULD BE SOME MORE ROOM
SUB P2,LC.LB ;MAKE P2 RELATIVE FOR SHUFFLING
PUSH P,P2 ;SAVE IT OVER LNKCOR
MOVEI P1,LS.IX ;WANT ROOM IN LS AREA
MOVE P2,T1 ;USE IT ALL
PUSHJ P,LNKCOR## ;DO SOME BLT'S
PUSHJ P,E$$MEF## ;[1174] CANNOT HAPPEN
POP P,P2 ;RESTORE RELATIVE ADDRESS
ADD P2,LC.LB ;MAKE ABSOLUTE
MOVE T1,LS.UB ;SETUP T1 FOR LS.IN
SUB T1,LS.LB
MOVEM T1,UW.LS ;UPPER WINDOW
ZCMP6A: PUSHJ P,LS.IN## ;READ BACK
MOVE T2,UW.LS ;UPPER BOUND
CAMLE T2,LSYM ;UNLESS TOO MANY
MOVE T2,LSYM ;YES, USE ACTUAL NUMBER
SUB T2,LW.LS ;LENTH OF THIS
MOVEI T1,2(P2) ;NEXT FREE AFTER IOWD
HRL T1,LS.LB ;FROM
ADDI P2,1(T2) ;WHERE TO STOP
BLT T1,(P2) ;MOVE DOWN
MOVE T1,P2 ;GET END
ANDCMI T1,.DBM ;[650] BUT NOT LAST BLOCK
SUB T1,LC.LB ;LENGTH
MOVN T1,T1
HRL T1,T1
HRR T1,LC.LB
SUBI T1,1 ;IOWD
SETZ T2,
OUT DC,T1
SKIPA T1,P2 ;OK
JRST E$$SOE ;[1212] NO
ANDCMI T1,.DBM ;[650]
HRLZ T1,T1 ;FROM
HRR T1,LC.LB ;TO
ANDI P2,.DBM ;[650] KEEP LAST BLOCK
ADD P2,LC.LB ;FIX IT UP AGAIN
BLT T1,(P2) ;MOVE BLOCK DOWN
MOVE T1,UW.LS
SUB T1,LW.LS
ADDI T1,1 ;LENGTH
ADDM T1,UW.LS
ADDB T1,LW.LS
CAML T1,LSYM ;DONE
JRST [MOVEI T1,SC ;SYBMOL CHANNEL:
PUSHJ P,DVDEL.## ; DISCARD IT
JFCL ;DON'T CARE
JRST ZCMP6S] ;AND SETUP START ADDRESS
HRLZ T1,LW.LS
HRR T1,UW.LS ;READ IN REST
JRST ZCMP6A ; OF FILE
ZCMP6R: MOVEI T1,2(P2) ;NEXT FREE
HRL T1,LS.LB ;FROM WHERE
ADDI P2,1(T2) ;ACCOUNT FOR SYMBOLS PLUS IOWD
BLT T1,(P2) ;MOVE SYMBOLS DOWN
ZCMP6S:>
MOVE T1,STADDR ;GET STARTING ADDRESS
HRLI T1,(JRST) ;FORM TRANSFER WORD
MOVEM T1,1(P2) ;STORE AFTER LAST WORD IN FILE
AOS T1,P2 ;WRITE OUT ALL OF CORE
AOJA T1,.+2 ;ONE MORE FOR TRANS WORD
ZCMPR7: ANDCMI T1,.IPM ;GET TO START OF THIS BLOCK
SUB T1,LC.LB ;LENGTH TO OUTPUT
JUMPE T1,ZCMPR8 ;IGNORE IF BLOCK OF ZERO'S
MOVN T1,T1 ;NEGATE IT
HRLZ T1,T1 ;PUT IN LEFT HALF
HRR T1,LC.LB ;FORM IOWD
HRRI T1,-1(T1) ;IOWD IS 1 LESS
SETZ T2, ;TERMINATE LIST
OUT DC,T1 ;DO OUTPUT
JRST ZCMPR8 ;OK
JRST E$$SOE ;[1174] PRINT ERROR AND DIE
;NOW TO MOVE DOWN THE REMAINING DATA IN THE BUFFER PRIOR TO
;READING IN MORE. IF NOT PAGING THIS IS END
ZCMPR8: SKIPE PAG.S1 ;WELL ARE WE PAGING
SKIPE LSTPAG ;BUT DONE IF ON LAST PAGE
JRST ENDCMP ;NO, ALL DONE
MOVE T1,P1 ;GET LOWEST LOCATION TO LEAVE
ANDCMI T1,.IPM ;ON BOUND
SUB T1,LC.LB ;REMOVE CORE OFFSET
ADDM T1,LW.S1 ;ADJUST WINDOW POINTERS
ADDB T1,UW.S1 ;MAY AS WELL
MOVE T2,HC.S1 ;GET HIGHEST LOCATION WE NEED TO SAVE
IORI T2,.IPM ;PUT ON BOUND
CAMLE T2,T1 ;TOO MUCH OR JUST ENOUGH ROOM AVAILABLE?
JRST ZCMPR9 ;NO
SUB T2,T1 ;YES, FIND DIFFERENCE
ADDM T2,UW.S1 ;SO WE DON'T WASTE TIME COUNTING ZEROS
ADDB T2,LC.AB ;OR GET ERRORS ON INPUT
MOVEM T2,LSTPAG ;SIGNAL LAST PAGE WILL SOON BE IN CORE
ZCMPR9: MOVE T1,P3 ;FORM BLT POINTER
ANDCMI T1,.IPM
CAMN T1,LC.LB ;CHECK FOR BLT IN PLACE
JRST ZCMP9A ;AND DON'T WASTE TIME ON IT
HRLZ T1,T1
HRR T1,LC.LB ;TO MOVE DOWN
HRRZI T2,.IPM(T1) ;TO THIS FAR
BLT T1,0(T2)
ZCMP9A: SKIPE T1,LSTPAG ;NOW CUT BACK CORE
IFN FTOVERLAY,<
SKIPL LNKMAX ;UNLESS LOADING OVERLAYS
SKIPA ;IN WHICH CASE WOULD ZAP LS AREA
> ;END IFN FTOVERLAY
CORE T1, ;TRY TO CUT BACK CORE
JRST .+3 ;TOO BAD
MOVE T1,.JBREL ;SETUP
MOVEM T1,LC.UB ;TO BE CONSISTENT
ANDI P3,.IPM ;KEEP OFFSET
CAIN P3,.IPM ;[652] FIRST PAGE ALREADY FINISHED?
SUBI P3,.IPS ;[652] YES, RE-USE IT FOR COMPRESSION
ADD P3,LC.LB ;[652] ADD IN BASE
ANDI P2,.IPM ;SAME AGAIN
CAIN P2,.IPM ;[652] FINISHED?
SUBI P2,.IPS ;[652] YES, RE-USE
ADD P2,LC.LB ;[652] ADD IN BASE
ANDI P1,.IPM
IOR P1,LC.LB
;NOW FOR DATA NOT READ
HRRZ T1,LW.S1 ;THIS IS WINDOW BASE
HRLZI T1,.IPS(T1) ;BUT WE ALREADY HAVE THIS MUCH
HRR T1,UW.S1 ;FOR GENERAL INPUT ROUTINE
PUSHJ P,LC.IN## ;READ IN NEW CORE IMAGE
SKIPE LSTPAG ;HAVE WE READ LAST PAGES YET?
PUSHJ P,LC.DLT ;YES, GET RID OF FILE
JRST ZCMPR3 ;AND CONTINUE
> ;END OF IFE FTEXE
SUBTTL FINAL LOADING CLEAN-UP
;HERE WHEN THROUGH
ENDCMP: MOVEI T1,DC ;MAKE SURE
MOVEM T1,IO.CHN
PUSHJ P,DVRLS.##
SKIPE IO.PTR+%XC ;NEED TO RENAME .XPN FILE?
PUSHJ P,XPNREN ;YES
MOVE T1,IO.PTR+DC ;BUT SAVE FILE SPEC
MOVEM T1,IO.PTR+LC ;IN CASE /EXEC
IFN FTOVERLAY,<
SKIPGE LNKMAX ;DID WE SEE ANY LINKS?
JRST ENDSAV ;NO
MOVEI T1,OC ;YES, RENAME FILE TO WHAT WE WANT
MOVEM T1,IO.CHN
MOVE T2,IO.PTR+%OC ;PTR TO REAL NAME
PUSHJ P,DVPRO. ;SETUP CORRECT PROTECTION
MOVE T1,T2 ;OLD IN IO.CHN, NEW IN T1
PUSHJ P,DVRNF.##
JRST E01FRE ;[1174] REPORT RENAME ERROR
SKIPE PLOTSW ;WANT PLOT PACKAGE?
JRST LNKPLT## ;YES
JRST ENDSAV ;[1144] NO, RUN PROGRAM OR EXIT
;HERE ON A RENAME ERROR FOR THE OVERLAY FILE
E01FRE::PUSH P,[%OC] ;[1174] SET UP CORRECT CHANNEL
.ERR. (LRE,,V%L,L%F,S%F,FRE) ;[616] GIVE A FATAL ERROR
>
ENDSAV::PUSHJ P,TERMES ;PRINT FINAL MESSAGES
SKIPE EXECSW ;GO INTO EXECUTION?
JRST RUNEXE ;[1144] YES, RUN THE .EXE FILE
SKIPN N.ZER## ;RUN SWITCH PENDING?
JRST ENDZAP ;NO, JUST EXIT
SETZM F.EDIT ;MAKE SURE LNKSCN WON'T GET UPSET
JRST LNKSCN## ;AND GO DO THE RUN SWITCH
;NO, CUT CORE BACK TO MINIMUM AND EXIT
ENDZAP: MOVSI 17,ENDCLR ;LOAD ACCS
BLT 17,17 ;WITH EXIT CODE
JRST $4 ;AND JUMP TO THEM
ENDCLR: PHASE 0
1,,20 ; 0 - CORE UUO ARG /SETNAM ARG
20,,21 ; 1 - ZERO BLT PTR
EXP 0,0 ;FUTURE
$4:! CORE 0, ; 4 - CUT CORE TO MINIMUM
JFCL ; 5 - ERROR RETURN
SETZB 0,20 ; 6 - FOR SETNAM AND ZERO BLT
BLT 1,@.JBREL ; 7 - CLEAR ALL BUT ACCS
SETNAM 0, ;10 - CHANGE NAME TO NULL
SETDDT 0, ;11 - CLEAR DDT INCASE DEBUGGING VERSION
MOVEM $15,.JBBLT ;12 - LOAD .JBBLT WITH FINAL ACC BLT
MOVEM $16,.JBBLT+1 ;13 - AND EXIT
JRST .JBBLT ;14 - JUMP TO EXEC PDL
$15:! BLT 17,17 ;15 - CLEAR ACCS
$16:! EXIT ;16 - AND GO AWAY
0,,1 ;17 - BLT PTR TO CLEAR ACCS
DEPHASE
DEFINE KEYMAC (A,B)<
IFIDN <A><DEB>,<
%%==-1
IRP B,<
IFGE %%,<
IFN %%&1,<
[ASCIZ \B\]
>>
%%==%%+1
>>
PURGE %%
>
DEBNAM: KEYWORDS
SUBTTL RUN THE PROGRAM
RUNEXE: SKIPE STADDR ;[1144] INFORM USER IF NO START ADDRESS
JRST RUNEX1 ;[1144] NO
AOS ERRNO ;[1144] DON'T START PROGRAM IF NO START ADDR
E$$NSA::.ERR. (MS,0,V%L,L%F,S%I,NSA,<No start address>) ;[1174]
RUNEX1: SKIPE ERRNO ;[1144] DON'T RUN IF ANY ERRORS
SKIPGE DEBUGSW ;[1144] UNLESS DEBUGGING
JRST RUNEX2 ;[1144] DO RUN PROGRAM
E$$DLT::.ERR. (MS,0,V%L,L%F,S%W,DLT,<Execution deleted>) ;[1174]
JRST ENDZAP ;[1144] JUST ZERO MEMORY AND EXIT
SUBTTL RUN THE PROGRAM FROM EXE FILE -- TOPS-20
IFN TOPS20,<
RUNEX2: MOVE T1,[R%ACS,,ACS] ;[1144] COPY RUN CODE TO WRITABLE PLACE
BLT T1,ACS+R%17 ;[1144] ..
MOVE T1,[POINT 7,RUNSPC] ;[1144] BUILD TOPS-20 FILE SPEC OF .EXE FILE
MOVE T4,IO.PTR+LC ;[1144] ..
MOVE T2,I.DEV(T4) ;[1144] COPY DEVICE NAME
PUSHJ P,SIXTO7 ;[1144] ..
MOVX T2,":" ;[1144] COPY DEVICE DELIMITER
IDPB T2,T1 ;[1144] ..
MOVE T2,I.NAM(T4) ;[1144] COPY FILE NAME
PUSHJ P,SIXTO7 ;[1144] ..
MOVX T2,"." ;[1144] COPY FILE TYPE DELIMITER
IDPB T2,T1 ;[1144] ..
HLLZ T2,I.EXT(T4) ;[1144] COPY FILE TYPE
PUSHJ P,SIXTO7 ;[1144] ..
SETZ T2, ;[1144] TURN INTO ASCIZ STRING WITH A NUL
IDPB T2,T1 ;[1144] ..
MOVX T1,GJ%OLD+GJ%SHT;[1144] GO FIND THE FILE
HRROI T2,RUNSPC ;[1144] ..
GTJFN ;[1144] ..
ERJMP E$$GFE ;[1202] GETJFN FAILED FOR EXE FILE
HRRM T1,ACS+R%16 ;[1144] PUT JFN IN GET JSYS ARGUMENT
MOVE T1,EXECSW ;[1144] GET ADDRESS TO START PROGRAM
HRRM T1,ACS+R%15 ;[1144] STORE IN FINAL JRST
MOVEI T1,1000 ;[1144] ASSUME WE'LL UNMAP ALL MEMORY PAGES
SKIPE DDTMAP ;[1144] SEE IF WE MAPPED IN DDT VIA /DEB:DDT
MOVEI T1,764 ;[1144] YES--DON'T UNMAP IT THEN
HRRM T1,ACS+R%3 ;[1144] STORE IN PMAP JSYS ARGUMENT
PUSHJ P,EXEMES ;[1144] PRINT PROGRAM EXECUTION MESSAGE
;FINAL EXECUTION. SET PROGRAM NAME, SET NEW SYMBOL TABLE POINTERS IF DDT, MOVE
;SUICIDE CODE TO ACS AND JUMP TO IT.
SKIPN T1,RUNAME ;[1144] SET PROGRAM NAME
MOVE T1,LODNAM ;[1144] ..
SETNM ;[1144] ..
SKIPN DDTMAP ;[1144] SEE IF /DEB:DDT SPECIFIED
JRST RUNEX3 ;[1144] NO--DON'T SET UP SYMBOL TABLE PTRS
MOVE T1,JOB116 ;[1144] YES--FORCE-FEED SYMBOL TABLE PTRS TO DDT
MOVEM T1,@770001 ;[1144] AT LAST MINUTE FOR LINK DEBUGGERS
MOVE T1,JOB117 ;[1144] ..
MOVEM T1,@770002 ;[1144] ..
RUNEX3: MOVE R%17,[ACS,,R%0] ;[1144] COPY POKED CODE TO ACS
BLT R%17,R%17 ;[1144] ..
JRST R%4 ;[1144] GO UMMAP PAGES, BRING IN PROG AND START
;SIXTO7 CONVERTS A SIXBIT WORD TO AN ASCII STRING WITHOUT TRAILING SPACES.
;CALL:
; T1/ <BYTE POINTER TO STRING>
; T2/ <SIXBIT WORD TO CONVERT>
;RETURNS WITH T1 UPDATED, T2 AND T3 DESTROYED.
SIXTO7: JUMPE T2,CPOPJ ;[1144] DONE IF SIXBIT HAS GONE TO 0
SETZ T3, ;[1144] CLEAR DESTINATION AC
ROTC T2,6 ;[1144] EXTRACT NEXT SIXBIT CHARACTER
ADDI T3,"A"-'A' ;[1144] CONVERT TO ASCII
IDPB T3,T1 ;[1144] STORE IN DESTINATION STRING
JRST SIXTO7 ;[1144] LOOP UNTIL DONE
E$$GFE::.ERR. (MS,.EC,V%L,L%F,S%F,GFE,<GTJFN% JSYS failed for file >) ;[1174]
.ETC. (STR,,,,,RUNSPC)
;FINAL SUICIDE CODE FOR RUNNING A PROGRAM ON TOPS-20.
R%ACS: PHASE 0 ;[1144] GET INTO THE ACS
R%0:! 0 ;[1144] SEED FOR ZEROING ACS WHEN DONE
R%1:! -1 ;[1144] PMAP ARGUMENTS TO UNMAP ALL OF MEMORY
R%2:! .FHSLF,,0 ;[1144] ..
R%3:! PM%CNT+.-. ;[1144] UNLESS /DEB:DDT THEN DON'T UNMAP UDDT
R%4:! PMAP ;[1144] BEGINNING OF SUICIDE CODE--UNMAP PAGES
R%5:! MOVE R%1,R%16 ;[1144] LOAD GET ARGUMENT
R%6:! GET ;[1144] BRING IN PROGRAM
R%7:! JSYS 147 ;[1144] DO RESET JSYS TO CLEAR PSI, ETC.
R%10:! DMOVEM R%14,.JBBLT ;[1144] MOVE LAST CODE TO JOBDAT
R%11:! JRST .JBBLT ;[1144] AND JUMP TO IT
R%12:! 0 ;[1144] UNUSED
R%13:! 0 ;[1144] UNUSED
R%14:! BLT R%17,R%17 ;[1144] CODE IN JOBDAT--CLEAR ALL ACS
R%15:! JRST .-. ;[1144] POKED TO PROGRAM EXECUTION ADDRESS
R%16:! .FHSLF,,.-. ;[1144] POKED TO GET JSYS ARGUMENT
R%17:! R%0,,R%1 ;[1144] BLT ARGUMENT TO CLEAR ACS
DEPHASE
> ;[1144] END OF IFN TOPS20
SUBTTL RUN THE PROGRAM FROM EXE FILE -- TOPS-10
IFE TOPS20,<
RUNEX2: MOVE T1,[U%LOW,,LOW] ;[1144] MOVE DOWN FINAL RUN UUO CODE
BLT T1,U%END ;[1144] ..
IFE FTEXE,<
SKIPN T1,IO.PTR+HC ;[1144] GET HIGH SEG POINTER
> ;END IFE FTEXE
MOVE T1,IO.PTR+LC ;[1144] SETTLE FOR LOW SEG IF NO HIGH
MOVE T2,I.DEV(T1) ;[1144] SET UP RUN UUO DEVICE
MOVEM T2,U%RUNB+0 ;[1144] ..
MOVE T2,I.NAM(T1) ;[1144] SET UP FILE NAME
MOVEM T2,U%RUNB+1 ;[1144] ..
IFE FTEXE,<
SKIPN T1,IO.PTR+LC ;[1144] MAKE SURE POINTING AT LOW SEG
JRST RUNEX3 ;[1144] HISEG ONLY, USE .LOW
MOVE T2,I.EXT(T1) ;[1144] MAY AS WELL USE KNOWN EXT
TLNN T2,-1 ;[1144] EXTENSION KNOWN?
RUNEX3: MOVSI T2,'LOW' ;[1144] NO, USE .LOW
> ;END IFE FTEXE
IFN FTEXE,<
MOVE T2,I.EXT(T1) ;[1144] GET EXTENSION OF EXE FILE
> ;END IFN FTEXE
HLLM T2,U%RUNB+2 ;[1144] STORE EXTENSION
MOVE T1,RUNCOR ;[1144] LOW SEGMENT SIZE FROM /RUNCOR:
ADD T1,RUNCOR+1 ;[1144] AND HIGH SEG SIZE
MOVEM T1,U%RUNB+5 ;[1144] STORE AS RUN UUO ARGUMENT
CAIGE T1,U%END ;[1144] PREPARE TO SHRINK MEMORY TO LARGER
MOVEI T1,U%END ;[1144] OF WHAT WE NEED AND WHAT PROGRAM NEEDS
HRRM T1,U%CORA ;[1144] STORE AS CORE UUO ARGUMENT
HRRZ T1,EXECSW ;[1144] COMPUTE RUN UUO OFFSET
SUB T1,STADDR ;[1144] IN CASE WE START A DEBUGGER
HRLM T1,U%RUNA ;[1144] STORE IN RUN UUO ARGUMENT
PUSHJ P,EXEMES ;[1144] PRINT PROGRAM EXECUTION MESSAGES
JRST LOW ;[1144] GO SHRINK AND RUN PROGRAM
;FINAL SUICIDE CODE FOR RUNNING A PROGRAM ON TOPS-10.
U%LOW: PHASE .TEMP ;[1144] LOW MUST BE FIRST IN .TEMP
DMOVE T1,U%CORA ;[1144] LOAD UP CORE AND RUN UUO ARGS
CORE T1, ;[1144] REMOVE HIGH SEG AND SHRINK LOW SEG
JFCL ;[1144] DON'T WORRY IF FAILURE
RUN T2, ;[1144] RUN THE PROGRAM
HALT ;[1144] CAN'T--MONITOR PRINTS USEFUL MESSAGE
EXIT ;[1144] IN CASE USER TYPES CONTINUE
U%RUNB: .-. ;[1144] RUN UUO DEVICE
.-. ;[1144] FILE NAME
.-.,,0 ;[1144] EXTENSION
0 ;[1144] UNUSED
0 ;[1144] PPN (FILE WRITTEN ON [-])
.-. ;[1144] MEMORY ARGUMENT
U%CORA: 1,,.-. ;[1144] CORE UUO ARG, POKED WITH LOW SEG SIZE
U%RUNA: .-.,,U%RUNB ;[1144] RUN UUO ARG, POKED WITH RUN OFFSET
U%END=.-1 ;[1144] LAST LOCATION IN PHASED CODE
DEPHASE ;[1144] BACK TO THE REAL WORLD
LOWLEN==.-U%LOW ;[1144] LENGTH OF PHASED CODE FOR LATER
> ;END IFN TOPS10
SUBTTL RUN THE PROGRAM FROM EXE FILE -- SUBROUTINES
;TERMES GIVES THE LINK TERMINATION MESSAGE AND CLOSES THE LOG FILE IF ANY. IF
;NECESSARY, THE LOG FILE IS RENAMED TO THE PROPER NAME AS WELL.
TERMES:
E$$FIN::.ERR. (MS,0,V%L,L%I,S%I,FIN,<LINK finished>) ;[1174]
SKIPN IO.PTR+RC ;[1202] A REAL LOG FILE?
SKIPGE LOGTTY ;[1202] OR USER'S TERMINAL?
JRST E$$ELF ;[1202] YES, TYPE MESSAGE
POPJ P, ;[1202] NO, DONE
E$$ELF::.ERR. (MS,,V%L,L%I,S%I,ELF,<End of log file>) ;[1174]
SKIPN IO.PTR+RC ;SEE IF A LOG FILE?
POPJ P, ;NO
MOVEI T1,RC
MOVEM T1,IO.CHN
SKIPN T1,IO.PTR+%RC ;[616] DO WE NEED TO RENAME FILE?
PJRST DVRLS.## ;[616] NO, JUST RELEASE IT
PUSHJ P,DVRNF.## ;YES, DO IT
CAIA ;[616] GIVE AN ERROR MESSAGE
PJRST DVRLS.## ;CLOSE FILE
E02FRE::PUSH P,[%RC] ;[1174] CHANNEL FOR ERROR
.ERR. (LRE,,V%L,L%F,S%F,FRE) ;[616] SEND THE MESSAGE
;EXEMES GIVES THE PROGRAM EXECUTION MESSAGE. THIS INCLUDES THE NAME OF THE
;PROGRAM, OR THE DEBUGGER IF /DEBUG WAS SPECIFIED.
EXEMES: SKIPE T1,DEBUGSW ;[1144] IF DEBUGGING
JRST EXEME1 ;[1144] THEN [LNKDEB debugger execution]
SKIPN T1,RUNAME ;[1144] ELSE [LNKXCT program execution]
MOVE T1,LODNAM ;[1144] GET PROGRAM NAME TO PRINT
E$$XCT::.ERR. (MS,.EC!.EN,V%L,L%F,S%I,XCT) ;[1174]
.ETC. (SBX,.EC!.EP,,,,T1)
.ETC. (JMP,.EC,,,,EXEME2)
EXEME1: MOVEI T1,@DEBNAM(T1) ;[1144] LOAD UP ASCIZ DEBUGGER NAME
E$$DEB::.ERR. (MS,.EC!.EN,V%L,L%F,S%I,DEB) ;[1174]
.ETC. (STR,.EC!.EP,,,,T1)
EXEME2: .ETC. (STR,,,,,,< execution>)
POPJ P, ;[1144] DONE
;ROUTINE TO CAUSE THE DATA IN A FILE TO BE MOVED FROM ONE FILE SPEC
;TO ANOTHER, EITHER BY A RENAME (IF POSSIBLE), OR BY COPYING THE FILE.
;USES DUMP MODE ON CHANNEL TC FOR OUTPUT IF COPYING NECESSARY.
;CALL IS:
; MOVE T1,OLD CHAN #
; MOVE T2,NEW CHAN #
; PUSHJ P,DVMOV.
; <ALWAYS RETURN>
;PRINTS FATAL ERROR AND STOPS IF RENAME OR COPY CANNOT BE PERFORMED.
;NOTE: THIS SHOULD REALLY BE IN LNKFIO, BUT IT IS HERE FOR NOW,
; SINCE NOBODY CALLS IT BUT LNKXIT, AND THERE IS NO USE MAKING
; ALL OF THE SEGMENTS BE A LOT BIGGER.
DVMOV.::MOVEM T1,IO.CHN ;POINT I/O ROUTINES TO OLD FILE
PUSH P,T2 ;SAVE NEW ONE
MOVE T1,IO.PTR(T1) ;GET POINTER TO OLD DATA BLOCK
MOVE T2,IO.PTR(T2) ;AND TO NEW ONE
MOVE T3,I.DEV(T1) ;GET OLD DEVICE
CAME T3,I.DEV(T2) ;SAME AS NEW ONE?
JRST DVCOPY ;NO, GO COPY FILE
POP P,T2 ;RESTORE NEW CHANNEL
MOVE T1,IO.PTR(T2) ;GET POINTER TO NEW DATA BLOCK
PUSHJ P,DVRNF. ;DO THE RENAME
SKIPA ;FAILED, GIVE ERROR
POPJ P, ;SUCCESS, RETURN
E03FRE::PUSH P,IO.CHN ;[1174] SAVE CHANNEL FOR LNKLOG
.ERR. (LRE,,V%L,L%F,S%F,FRE)
;HERE WHEN CANNOT RENAME THE FILE. MUST DO THE COPY.
DVCOPY: PUSHJ P,DVCLS.## ;MAKE SURE THE INPUT FILE EXISTS
MOVEI T3,I.RIB(T1) ;LOOK IT UP AGAIN
TLO T3,(LOOKUP) ;..
IOR T3,I.CHN(T1) ;..
XCT T3 ;SHOULDN'T FAIL
JRST E01FLE## ;[1174] ???
MOVE T3,I.SIZ(T1) ;GET INPUT FILE SIZE FOR LATER
LSH T3,-.DBS2W ;[650] CONVERT TO BLOCKS (FOR ESTIMATE)
ADDI T3,3 ;2 RIBS PLUS REMAINDER
POP P,T2 ;RESTORE NEW CHANNEL
SPUSH <P1,P2,P3> ;NEED LOTS OF ACS FOR THIS
PUSH P,IO.CHN ;SAVE OLD CHANNEL FOR LATER
MOVE P1,T1 ;SAVE POINTER TO OLD DATA BLOCK
MOVE T1,IO.PTR(T2) ;GET POINTER TO NEW DATA BLOCK
MOVEM T1,IO.PTR+TC ;USE THE TEMP CHAN FOR THE COPY
MOVEM T3,I.EST(T1) ;SET UP ESTIMATE FOR FILSER
MOVSI T2,(Z TC,) ;POINT THE OUTPUT CHAN TO CHAN TC
MOVEM T2,I.CHN(T1) ;SINCE THE PSEUDO-CHANNEL IS THERE
MOVEI T2,TC ;POINT ALL I/O TO THE OUTPUT
MOVEM T2,IO.CHN ;CHANNEL, SO CAN ENTER THE FILE.
PUSHJ P,DVNAM. ;SETUP THE OUTPUT FILE NAME
PUSHJ P,DVOPN. ;GET THE OUTPUT DEVICE
PUSHJ P,DVENT. ;CREATE THE OUTPUT FILE
PUSHJ P,FR.CNT## ;FIND OUT HOW MUCH CORE IS FREE
MOVE T2,I.SIZ(P1) ;AND HOW MUCH WE NEED
ADDI T2,.DBM ;ROUND UP TO DISK BLOCK
ANDCMI T2,.DBM ;SINCE WE NEED THAT MUCH
ANDCMI T1,.DBM ;ALSO, ROUND FREE COUNT DOWN
CAMLE T2,T1 ;HAVE AS MUCH AS WE NEED?
MOVE T2,T1 ;NO, USE WHAT WE HAVE
SKIPN T2 ;BUT IF NONE FREE AT ALL
MOVEI T2,.DBS ;NEED AT LEAST ONE DISK BLOCK
PUSHJ P,DY.GET## ;GET IT ALL
MOVE T3,I.SIZ(P1) ;RESTORE EXACT FILE SIZE
CAMLE T2,T3 ;IS BUFFER BIGGER THAN FILE?
MOVE T2,T3 ;NO, USE FILE SIZE FOR IOWD
MOVN P2,T2 ;FORM AN INPUT IOWD
HRLZ P2,P2 ;LH CONTAINS - COUNT
HRRI P2,-1(T1) ;RH CONTAINS START - 1
SETZ P3, ;IOWD LIST TERMINATED BY ZERO
MOVE T3,I.CHN(P1) ;ASSEMBLE 'IN CH,P2' IN T3
TDO T3,[IN P2] ;SO CAN READ DATA WITH XCT T3
DVMOV1: XCT T3 ;READ NEXT BLOCK OF DATA
JRST DVMOV3 ;GOT DATA, GO OUTPUT IT
MOVE T3,I.CHN(P1) ;NOW NEED TO SEE IF EOF OR ERROR
TDO T3,[STATZ IO.ERR] ;SO ASSEMBLE INSTRUCTION
XCT T3 ;EOF OR ERROR?
JRST E$$EOI ;[1174] ERROR, GIVE UP
MOVE T3,I.SIZ(P1) ;RETRIEVE FILE SIZE
IDIV T3,T2 ;FIND HOW MANY WORDS SHOULD REMAIN
JUMPE T4,DVMOV2 ;NONE, WE'RE ALL DONE
MOVN T4,T4 ;T4 HAS COUNT OF DATA IN BUFFER
HRL P2,T4 ;SO GENERATE AN IOWD TO SEND IT
OUT TC,P2 ;SEND THE DATA
SKIPA ;MADE IT!
JRST E$$EOO ;[1174]OH WELL, GIVE ERROR
DVMOV2: PUSHJ P,DY.RET## ;DONE WITH THE BUFFER, SO FREE IT
PUSHJ P,DVRLS. ;CLOSE THE OUTPUT FILE
POP P,T1 ;RESTORE INPUT CHANNEL
PUSHJ P,DVDEL. ;NOW DELETE INPUT FILE
JFCL ;DON'T CARE IF FAILED
SPOP <P3,P2,P1> ;RESTORE SAVED AC'S
POPJ P, ;AND RETURN
;HERE TO OUTPUT NEXT CHUNK OF FILE
DVMOV3: OUT TC,P2 ;SEND IT
JRST DVMOV1 ;MADE IT, GET NEXT PIECE OF DATA
E$$EOO::PUSH P,[TC] ;[1174] TELL WHICH CHANNEL HAD THE ERROR
.ERR. (ST,,V%L,L%F,S%F,EOO,<Error on output>)
E$$EOI::;PUSH P,IO.CHN ;[1174] CHANNEL ALREADY ON STACK
.ERR. (ST,,V%L,L%F,S%F,EOI,<Error on input>)
;HERE TO GET PROTECTION CODE RIGHT
;CALLED BY
; MOVE T2,NEW DATA BLOCK
; PUSHJ P,DVPRO.
;RETURN
;+1 ALWAYS
DVPRO.: LDB T3,[POINT 9,I.PRV(T2),8] ;GET USER SUPPLIED CODE
JUMPN T3,CPOPJ ;OK
;BUT WE MUST REPLACE 077 BY STANDARD
HRROI T3,<.GTDFL==140>;[606] DEFAULT WORD
GETTAB T3, ;[606] GET IT
SETZ T3, ;[606] CERTAINLY NOT SET
TXNE T3,<<JD.SDP==1B9>>;[606] USER HAVE DEFAULT PROTECTION?
TXNN T3,<<JD.PRT==777B8>>;[606] YES, BUT WE CAN'T HANDLE 0
JRST DVPRO1 ;[606] NOTHING USEFUL, GET SYS DEFAULT
ANDX T3,JD.PRT ;[606] CLEAR EXTRANEOUS BITS
IORM T3,I.PRV(T2) ;[606] SET
POPJ P, ;[606]
;HERE IF NO DEFAULT PROTECTION OR OLD MONITOR
DVPRO1: MOVE T3,[%LDSTP] ;[606] GET STANDARD
GETTAB T3,
MOVSI T3,057000 ;IN CASE OF FAILURE
IORM T3,I.PRV(T2) ;SET IT
POPJ P,
;HERE TO RENAME .XPN FILE
XPNREN: MOVEI T1,LC ;FROM
MOVEM T1,IO.CHN ;SET CHAN#
PUSHJ P,DVCHN.## ;T1 = DATA BLOCK
PUSHJ P,DVOPN.## ;AND AN OPEN CHAN
PUSHJ P,DVNAM.## ;MAKE SURE A GOOD NAME
MOVEI T1,LC
MOVE T2,IO.PTR+%XC ;POINT TO NEW FILE SPEC
MOVE T3,VERNUM ;GET FILE VERSION
SKIPN I.VER(T2) ;UNLESS SET BY PREVIOUS SWITCH
MOVEM T3,I.VER(T2) ;SET UP FOR RENAME OR ENTER
MOVE T2,IO.PTR+%XC ;[606] OUTPUT DATA BLOCK ADDR
PUSHJ P,DVPRO. ;[606] GET THE OUTPUT PROTECTION RIGHT
MOVEI T2,%XC ;TO
PUSHJ P,DVMOV. ;TRY RENAME OR COPY
SETZM IO.PTR+LC ;NOT THERE NOW
POPJ P,
SUBTTL LOAD PROGRAM INTO MEMORY
;HERE TO BRING THE ENTIRE PROGRAM INTO MEMORY. IF NOT PAGING, THIS ONLY INVOLVES
;COMPACTING THE LC AND HC AREAS DOWN TOWARD 0 AS FAR AS POSSIBLE. IF PAGING,
;MINIMIZE DISK TRANSFERS BY MOVING THE WINDOW (VIA BLT OR POP LOOP) TO ITS FINAL
;LOCATION, THEN READING IN THE REST OF THE APPROPRIATE OVERFLOW FILE AROUND THE
;WINDOW.
JBLOAD: DMOVE P1,LC.LB ;SAVE THE CURRENT LOCATIONS
DMOVE P3,LC.AB ; SO WE CAN MOVE DATA
MOVE T1,DY.AB ;TOP OF FIXED AREA
MOVEM T1,DY.UB ;[1147] MAKE SURE UB IS UP TO DATE
ADDI T1,1 ;NEXT FREE
MOVEM T1,LC.LB ;MAKE LOWEST FOR LOW CODE
ADD T1,HC.S1 ;HOW MUCH WE NEED
SUBI T1,1 ;[1146] LB + LENGTH - 1 FOR LAST NEEDED
IORI T1,.IPM ;BLOCK BOUND
MOVEM T1,LC.AB
IOR. T1,.PGSIZ ;TO NEXT PAGE FOR REMAP
MOVEM T1,LC.UB ;ACCOUNT FOR ALL SPACE
JUMPE P2,JBGCL ;[1170] GO MOVE IF NO HI SEG
ADDI T1,1 ;LOWER BOUND FOR HISEG
MOVEM T1,HC.LB ;RESET IT
ADD T1,HC.S2 ;[1170] HIGHEST LOC WE NEED
SUBI T1,1 ;[1146] LB + LENGTH - 1 FOR LAST NEEDED
IORI T1,.IPM ;BLOCK BOUND
MOVEM T1,HC.AB
IOR. T1,.PGSIZ ;UPTO PAGE (OR K) BOUND
MOVEM T1,HC.UB ;FOR VERY TOP
;FALL IN FROM ABOVE IFF WE HAVE A HIGH SEGMENT (HC AREA)
;NOW DO THE FOLLOWING:
;
; 1. IF THE LC AREA IS SO HIGH THAT IT MIGHT GET OVERWRITTEN WHEN WE MOVE THE
; HC AREA TO WHERE IT BELONGS, THEN MOVE THE LC AREA DOWN OUT OF THE WAY.
; 2. MOVE THE HC AREA TO WHERE IT BELONGS, AND READ IN ANY DATA STILL OUT IN
; OVERFLOW FILES.
; 3. MOVE THE LC AREA TO WHERE IT BELONGS, AND READ IN ANY DATA STILL OUT IN
; OVERFLOW FILES.
; 4. DO A CORE UUO TO GET RID OF CORE FOR TABLES NO LONGER NEEDED.
; 5. MAKE SURE THE CORE BETWEEN AREAS IS STILL ZERO AFTER ALL THIS MOVING.
;
;ENTER FROM ABOVE AT JBGCL (STEP 3) IF WE DON'T HAVE A HIGH SEG.
MOVEI R,LC.IX ;[1170] POINT TO LOW SEG FOR JBCGM
CAMLE P3,LC.AB ;[1170] MIGHT LC AREA BE WIPED BY MOVING HC?
PUSHJ P,JBGCM ;[1170] YES, MOVE LC AREA FIRST
MOVEI R,HC.IX ;INDEX TO HIGH
PUSHJ P,JBGCMV ;MOVE HIGH AREA
JBGCL: ;NOW FOR LOW SEG
MOVEI R,LC.IX ;INDEX TO LOW
PUSHJ P,JBGCMV ;MOVE CODE AND READ IN REST OF DATA
SKIPN T1,HC.UB ;[1170] GET LAST LOCATION USED
MOVE T1,LC.UB ;[1170] NO HI SEG, END OF LOW IS LAST USED
IOR. T1,.PGSIZ ;[1170] UP TO PAGE BOUND IF NEEDED
CAME T1,.JBREL ;[1170] ALREADY THE RIGHT SIZE?
CORE T1, ;[1170] NO, SHRINK DOWN (OR GROW???)
JFCL ;[1170] ALREADY WAS THE RIGHT SIZE
;NOW TO ZERO ALL SPACE NOT USED
MOVEI R,HC.IX ;START WITH HIGH SEGMENT
SKIPN TAB.LB(R) ;IS THERE ONE?
SUBI R,1 ;NO
JBGCZ: MOVE T1,TAB.AB(R) ;LAST LOCATION IN USE
CAML T1,TAB.UB(R) ;CHECK FOR ANY CORE TO ZERO
JRST JBGCZ1 ;NONE - SO CHECK FOR FINISH
ADDI T1,2
HRLI T1,-1(T1) ;FORM BLT PTR TO CLEAR UNUSED CORE
SETZM -1(T1) ;[1170] CLEAR FIRST WORD
BLT T1,@TAB.UB(R) ;AND REST
JBGCZ1: SOJG R,JBGCZ ;NOW FOR LOW SEG
JRST JBEXIT ;[1146] PROGRAM NOW ALL IN MEMORY
;HERE TO MOVE CODE FOR EITHER SEG AND READ IN DATA
P0==P1-1 ;[1146] USED FOR REFERENCING P1 OR P2 VIA R
JBGCMV: MOVE T1,TAB.LB(R) ;BASE
ADD T1,LW.S0(R) ;PLUS WINDOW OFFSET
CAME T1,P0(R) ;IF WHERE WE SHOULD BE DO NOTHING
PUSHJ P,JBGCM ;[1170] MOVE THE AREA, UP OR DOWN
;NOW FOR REST OF CODE
SKIPN PAG.S0(R) ;HOWEVER IF THIS SEGMENT NOT PAGED
POPJ P, ;WE MUST BE IN RIGHT PLACE ALREADY
HRRZ T1,LW.S0(R) ;GET LOWER WINDOW
SOJL T1,.+3 ;DONE IF WAS ZERO
SETZM LW.S0(R) ;NOW POINT TO BASE
PUSHJ P,@[EXP LC.IN##,HC.IN##]-1(R)
MOVE T1,HC.S0(R) ;HIGHEST DATA WE NEED
IORI T1,.IPM ;UP TO BOUND
CAMG T1,UW.S0(R) ;IF WE'VE ALREADY GOT IT IN
POPJ P, ;[1170] ALL DONE
EXCH T1,UW.S0(R) ;GET BASE
HRLZI T1,1(T1) ;FIRST LOC TO READ
HRR T1,UW.S0(R) ;LAST
PJRST @[EXP LC.IN##,HC.IN##]-1(R) ;[1170] READ IT IN AND RETURN
;SUBROUTINE TO MOVE AN AREA TO ITS FINAL RESTING PLACE.
;CALL WITH:
; R/ INDEX TO SEGMENT, ??.IX
; P1-P4/ OLD LB/AB OF AREAS
; ??.LB&AB/ NEW LB/AB OF AREAS
;
;UPDATES P1-P4 TO INDICATE THE AREA HAS BEEN MOVED.
;THIS SUBROUTINE USES BLTS, A PIECE AT A TIME IF OVERLAPPING UPWARDS.
JBGCM: MOVE W1,HC.S0(R) ;[1170] FIRST, CALCULATE LAST DEST+1
SUBI W1,1 ;[1170] DEPENDS ON IF PAGING, AND
IORI W1,.IPM ;[1170] WHERE WINDOW IS IF SO
SKIPE PAG.S0(R) ;[1170] PAGING?
CAMG W1,UW.S0(R) ;[1170] YES, DOES WINDOW POINT TO END OF AREA?
CAIA ;[1170] NOT PAGING OR WINDOW AT END
MOVE W1,UW.S0(R) ;[1170] WINDOW IN MIDDLE, STOP BLT AT UW
ADDI W1,1 ;[1170] CONVERT LAST DEST TO FIRST NOT TOUCHED
ADD W1,TAB.LB(R) ;[1170] FORM ABSOLUTE ADDRESS
MOVE T1,TAB.LB(R) ;[1170] NOW CALCULATE FIRST DESTINATION ADDR
ADD T1,LW.S0(R) ;[1170] WHERE CURRENT WINDOW GOES IN NEW LC AREA
MOVE T3,W1 ;[1170] T1 GETS TOTAL LENGTH TO MOVE
SUB T3,T1 ;[1170] LAST+1-FIRST IS LENGTH
MOVE T4,T1 ;[1170] T4 GETS OFFSET (HOW FAR TO MOVE)
SUB T4,P0(R) ;[1170] THIS IS ALSO CHUNK SIZE IF OVERLAPS UP
SKIPG T4 ;[1170] MOVE DOWN OR IN PLACE?
MOVE T4,T3 ;[1170] YES, MOVE ENTIRE THING IN ONE PIECE
HRLS T4 ;[1170] FORM CHUNK SIZE,,CHUNK SIZE (FOR BLT AC)
MOVEI W3,-1(W1) ;[1170] W1 GETS LAST DEST
MOVE T2,P0(R) ;[1170] T2 GETS LAST SOURCE + 1
ADD T2,T3 ;[1170] FOR LH OF W1 AS PROTOTYPE BLT POINTER
HRLM T2,W1 ;[1170] W1/ LAST SRC+1,,LAST DST+1
MOVEM T1,P0(R) ;[1170] UPDATE P1/P2 SO WE KNOW WE DID THIS
; ..
; ..
;LOOP BACK HERE TO DO EACH NEW PIECE OF THE BLT. THIS CODE USES ACS AS FOLLOWS:
;
; T3/ TOTAL # WORDS LEFT TO MOVE
; T4/ CHUNK SIZE,,CHUNK SIZE (.GT. T3 IF LAST OR ONLY TIME)
; W1/ LAST SRC+1,,LAST DEST+1 FOR NEXT BLT
; W2/ SCRATCH AC FOR BLT
; W3/ LAST DEST FOR NEXT BLT
;
;W1 AND W3 ARE DECREMENTED BY CHUNK SIZE WITH EACH BLT UNTIL DONE.
JBGCM6: CAIGE T3,(T4) ;[1170] LAST (OR ONLY) TIME?
JRST JBGCM8 ;[1170] YES, GO ADJUST CHUNK SIZE ETC.
SUB W1,T4 ;[1170] DECREMENT PROTOTYPE BLT POINTER
MOVE W2,W1 ;[1170] SCRATCH COPY FOR BLT
BLT W2,(W3) ;[1170] BLT NEXT PIECE
SUBI W3,(T4) ;[1170] DECREMENT LAST BLT ADDRESS
SUBI T3,(T4) ;[1170] DECREMENT TOTAL LEFT TO DO
JRST JBGCM6 ;[1170] LOOP BACK
;HERE THE LAST TIME
JBGCM8: JUMPE T3,CPOPJ ;[1170] ALL DONE?
MOVE T4,T3 ;[1170] DO WHAT'S LEFT
HRLS T4 ;[1170] SET NEW CHUNK SIZE
JRST JBGCM6 ;[1170] BACK THROUGH THE LOOP, ONE MORE TIME
SUBTTL HERE TO BLT DOWN AREA AND EITHER GO TO EXECUTION OR EXIT
JBEXIT: SKIPE IO.PTR+%XC ;[1146] DO WE WANT .XPN FILE
SKIPE IO.PTR+LC ;AND DON'T ALRADY HAVE AN OVERFLOW FILE
CAIA ;NOT BOTH TRUE
PUSHJ P,WRTXPN ;WRITE OUT CURRENT CORE IMAGE
SKIPE STADDR ;WARN USER IF NO STARTING ADDRESS
JRST JBEX10 ;IS A STARTING ADDRESS, KEEP GOING
E01NSA::.OERR. [ASCIZ \[LNKNSA No start address]
\]
JBEX10: SKIPE JOBPTR ;NEED TO RESTORE .JBDA?
PUSHJ P,BLTJDA ;YES
SKIPE JBHPTR ;SAME FOR HIGH
PUSHJ P,BLTJHA ;RESTORE FIRST 10 WORDS
SKIPE IO.PTR+%XC ;NEED TO RENAME .XPN FILE?
PUSHJ P,XPNREN ;YES
SKIPE IO.PTR+HC ;HIGH SEG OVERFLOW FILE STILL THERE?
PUSHJ P,HC.DLT ;YES, REMOVE IT
SKIPE IO.PTR+LC ;SAME FOR LOW SEG
PUSHJ P,LC.DLT
PUSHJ P,TERMES ;PRINT FINAL MESSAGES
MOVE T1,LC.LB ;LOAD UP OFFSET
IFN TOPS20,<
SKIPN DDTMAP ;[1145] DDT MAPPED FROM /DEBUG:DDT?
JRST JBEX1A ;[1145] NO--NOTHING TO DO
MOVE T2,.JBSYM(T1) ;[1145] YES--FORCE-FEED SYMBOL TABLE
MOVEM T2,@770001 ;[1145] TO DDT
MOVE T2,.JBUSY(T1) ;[1145] ..
MOVEM T2,@770002 ;[1145] ..
JBEX1A:
>
MOVE T2,.JBDDT(T1) ;[1145] GET DEBUGGER ADDRESS
;NOW PUT PHASED CODE INTO LOW SEG
MOVEM T2,%T4 ;SAVE FOR LATER
MOVE T1,[%HIGH,,%LOW] ;MOVE PHASED CODE
BLT T1,%END ;INTO LOWSEG
HRLZ T1,LC.LB ;WHERE WE ARE NOW
ADD T1,[20,,20] ;BLT POINTER TO WHERE WE WILL BE
MOVEM T1,%0 ;STORE BLT POINTER FOR LATER
MOVE T1,LC.AB ;WHERE WE WILL END
SUB T1,LC.LB ;AFTER BLT
HRRM T1,%4 ;STORE FOR LATER
IFN TOPS20,< ;IF TOPS-20, SETUP START VECTOR
MOVEI T1,400000 ;THIS FORK
MOVE T2,STADDR ;ADDRESS
TLNN T2,-1 ;IF LHS NOT SET, PUT JRST
HRLI T2,(JRST) ;IN LEFT
SEVEC ;SET ENTRY VECTOR
>
SKIPN T1,EXECSW ;GET STARTING ADDRESS
JRST JBEX0 ;DON'T WANT TO START
HRLI T1,(JRST) ;COMPLETE INST IF EXECUTING
TRNN T1,-1 ;WANT TO START, BUT DO WE HAVE A VALID ADDRESS
SKIPGE DEBUGSW ;IF /DEB WILL CHECK AT JBEX3
JRST JBEX01 ;OK
JRST JBNEX ;NO, ABORT
JBEX0: MOVE T1,[EXIT] ;STOP JOB
JBEX01: MOVEM T1,%16 ;STORE EXEC OR EXIT
MOVSI T1,(JFCL) ;NO-OP
SKIPE EXECSW ;IF EXECUTION
HLLM T1,%DMES ;EXTRA MESSAGE
SKIPGE DEBUGSW ;IF DEBUGGING
JRST JBEX3 ;CHANGE MESSAGE
MOVE T1,LC.LB ;GET BASE OF LOW CODE
HRRZ T1,.JBERR(T1) ;ANY ERRORS?
SKIPE T1
SKIPN EXECSW ;AND USER WANTS EXECUTION?
JRST JBEX2 ;NO
JBNEX: MOVE T1,[EXIT] ;PUT A STOP TO THAT
MOVEM T1,%16
MOVE T1,%HIGH+%DMES-%LOW
MOVEM T1,%DDMES ;SKIP REST OF MESSAGES
MOVE T1,[[ASCIZ /%LNKDLT Execution deleted/],,%TMES] ;[1144]
BLT T1,%TMES+5
JBEX2: MOVE T1,LC.LB ;GET BASE OF LOW CODE
MOVE T1,.JBVER(T1) ;PICKUP VERSION NUMBER
MOVEM T1,%VER ;STORE IT FOR VERSION WATCHING
SKIPN T1,HC.AB ;GET REAL TOP OF HIGH SEG
MOVE T1,LC.AB ;USE LOWSEG IF NO HIGH
TLO T1,1 ;ALSO REMOVE CURRENT HIGH SEG
MOVEM T1,%T1 ;SAVE CORE UUO ARG
SKIPE T1,HC.LB ;GET BOTTOM OF HIGH SEG
SUBI T1,1 ;TOP OF LOW SEG
HRRZM T1,%T2 ;STORE FOR REMAP
MOVSI T2,(CAIA) ;INCASE NO HIGH SEG
SKIPN T1
MOVEM T2,%REMAP ;OVERWRITE REMAP UUO
SKIPN T1,RUNAME ;GET NAME TO CALL CORE IMAGE
MOVE T1,LODNAM ;USE DEFAULT IF NOT SET
SKIPE %DTXT ;IF NOT ALREADY SET
JRST JBEX20 ;EITHER DDT OR NO NESSAGE
MOVE T3,T1 ;GET A COPY
MOVE T4,[POINT 7,%DTXT]
SETZ T2, ;CLEAR RECEIVING AC
LSHC T2,6 ;GET NEXT CHAR
ADDI T2," " ;INTO ASCII
IDPB T2,T4
JUMPN T3,.-4 ;MORE TO DO
IDPB T3,T4 ;MAKE SURE A 0 THERE
JBEX20: MOVEM T1,%T3 ;FOR SETNAM UUO
;HERE TO SETUP ARGS FOR CORE AND REMAP UUO'S
SKIPE T1,HL.S1 ;GET HIGHEST LOC LOADED +1
SUBI T1,1
IOR. T1,.PGSIZ ;ROUND UP
CAMGE T1,RUNCOR ;MORE THAN USER REQUESTED?
MOVE T1,RUNCOR ;NO, USE SUPPLIED VALUE
MOVEM T1,%1 ;FOR 2ND CORE UUO
MOVE T2,HL.S2 ;SAME FOR HIGH SEG
SOJL T2,JBEX2A ;AS LONG AS THERE IS ONE
IOR. T2,.PGSIZ
CAMGE T2,RUNCOR+1 ;USER SUPPLIED 2ND ARG
MOVE T2,RUNCOR+1 ;AND MORE THAN WE NEED
ADDI T1,1 ;TOP OF LOW SEG +1
CAMGE T1,LL.S2 ;LARGER THAN HI-ORG?
MOVE T1,LL.S2 ;NO, SO ASSUME HI-ORG
CAIE T1,400000 ;CONVENTIONAL HI-ORG?
HRLM T1,%T2 ;NO, FANCY REMAP UUO FOR V/M
ADDI T2,(T1) ;CORE UUO WILL KEEP HISEG
HRLM T2,%1 ;MAKE SURE CORE UOO CORRECT
JBEX2A: MOVE T1,HC.S1 ;GET HIGHEST DATA WORD+1
CAIGE T1,.JBDA ;BUT DON'T ZERO JOBDAT
MOVEI T1,.JBDA
HRRZ T2,%1 ;GET CORE UUO ADDRESS FOR LOW SEG TOP
CAML T1,T2 ;IS FIRST FREE LOC IN BOUNDS?
JRST [MOVSI T3,(JFCL) ;NO, ASSUME EQUAL
CAMG T1,T2 ;IS IT?
JRST [MOVEM T3,%11 ;IN WHICH CASE DON'T DO BLT
JRST .+1] ;BUT DO ZERO LAST WORD
MOVSI T3,(TDZA) ;NO, FIRST FREE LOC IS OUT OF BOUNDS
MOVEM T3,%10 ;JUST ZERO AC 0
JRST JBEX2B] ;AND FORGET FIRST FREE AND BLT
HRRM T1,%10 ;SET FOR ZEROING
HRL T1,T1
ADDI T1,1 ;FORM BLT PTR
MOVEM T1,%2 ;TO CLEAR LOW SEG
JBEX2B: MOVE T4,[%T1,,T1] ;LOAD ACCS
BLT T4,T4
JRST %LOW ;GO TO LOW SEG
JBEX3: MOVE T1,DEBUGSW ;GET INDEX TO DEBUG NAME
DMOVE T1,@DEBNAM(T1) ;GET BOTH WORDS (IF THERE ARE 2)
DMOVEM T1,%DTXT ;STORE
SKIPE EXECSW ;IF NO EXECUTION
CAME T1,[ASCII \COBDD\] ;OR NOT COBDDT
JRST JBEX4 ;START @.JBDDT
SKIPN T1,STADDR ;START COBDDT VIA MAIN PROG
JRST JBNEX ;OR GIVE EXECUTION DELETED MESSAGE
HRLI T1,(JRST) ;FORM INST
MOVEM T1,%16 ;SAVE GOTO ADDRESS
JBEX4:
IFE FTKIONLY,<
MOVE T1,[ASCIZ \[LNKDEB \]
MOVE T1+1,1+[ASCIZ \[LNKDEB \]
> ;END IFE FTKIONLY
IFN FTKIONLY,<
DMOVE T1,[ASCIZ \[LNKDEB \]
> ;END IFN FTKIONLY
DMOVEM T1,%TMES
JRST JBEX2
;HERE FOR PHASED LOWSEG CODE
;ENTER WITH :-
;T1 = ARG FOR CORE UUO
;T2 = ARG FOR REMAP UUO
;T3 = ARG FOR SETNAM UUO
;T4 = ARG FOR SETDDT UUO
%HIGH:
PHASE %LOW
%LOW: CORE T1, ;REMOVE HIGH SEG AND EXCESS LOWSEG
JFCL ;TOO BAD
%REMAP: REMAP T2, ;CHANGED TO SKIPA IF NO HIGH SEG
JRST REMERR ;FAILED
SKIPA T1,%VER ;PICK UP VERSION NUMBER
%VER: .-. ;FROM HERE
MOVEM T1,.JBVER ;SO CORRECT VERSION COMES OUT IF WATCHING
HLRZ T2,%0 ;GET REL 20
MOVE T1,.JBREL ;REMEMBER THIS
MOVEM T1,.JBREL-20(T2);INCASE CORE UUO NOT DONE
IFE TOPS20,<
MOVE T1,.JBPFH## ;GET CURRENT PAGE FAULT HANDLER
EXCH T1,.JBPFH-20(T2) ;GET USER ONE
MOVEM T1,%3 ;SO WE CAN SET IT
>
SETNAM T3, ;FOR ARG WATCHING
SETDDT T4, ;CHANGE TO NEW ADDRESS
%DMES: JRST %RMES ;PATCH IF NEED MESSAGE
E01XCT:: ;[1174]
E01DEB::.OERR. %TMES ;[1174] LNKDEB OR LNKXCT
%DDMES: OUTSTR %DTXT ;NAME OF DEBUGGER
OUTSTR %RTXT ;TELL USER
%RMES: MOVSI 17,%0 ;BLT PTR
IFE TOPS20,<
RESET ;MAKE SURE NO I/O STILL OPEN
>
IFN TOPS20,< ;SPECIAL IF TOPS-20 DDT
MOVEI T1,400000 ;THIS FORK
DIR
CIS
MOVSI T1,(JFCL) ;[644] REPLACE WITH JFCL IF DESIRED
MOVE T2,%16 ;[644] GET IT
CAMN T2,%EXIT ;[644] EXIT? RATHER THAN START ADDR
MOVEM T1,%7 ;[644] YES, REPLACE RESET WITH JFCL
>
BLT 17,17 ;[644] LOAD ACCS
JRST 4 ;[644] GO THERE
%EXIT: EXIT ;[644] THIS IS COMPARED WITH CONTENT OF %16
%TMES: ASCIZ \[LNKXCT \
%DTXT: EXP 0,0 ;ENOUGH FOR 6 CHARS PLUS NULL
%RTXT: ASCIZ \ execution]
\
REMERR: TLZN T2,-1 ;REMAP FOR V/M?
JRST E01RME ;[1174] NO, OR FAILED TWICE
HRRZS %1 ;MAKE SURE CORE UUO IN BOUNDS
SKIPA T1,.+1 ;STOP EXECUTION
EXIT ;WITH AN EXIT
MOVEM T1,%16 ;IF IT WAS ON
E$$RME::.OERR. %VMRERR ;[1174] LNKRME
JRST %REMAP ;NOW TRY AGAIN
E01RME::.OERR. %RMPE ;[1174] LNKRME
EXIT
%RMPE: ASCIZ \?LNKRME REMAP error\
%VMRER: ASCIZ \%LNKRME REMAP error, high segment origin incorrect
\
%0: .-. ;BLT POINTER
%1: .-. ;CORE UUO
%2: .-. ;ZERO CORE BLT PTR
%3: .-. ;PFH
%4: BLT 0,.-. ;BLT LOWSEG DOWN
%5: CORE 1, ;ADJUST CORE
%6: JFCL ;SHOULD NOT FAIL
IFE TOPS20,<
%7: MOVEM 3,.JBPFH## ;SET PAGE FAULT HANDLER
>
IFN TOPS20,<
%7: JSYS 147 ;TOPS-20 RESET, FLUSH PA1050
>
%10: SETZB 0,.-. ;CLEAR FIRST WORD
%11: BLT 2,@.JBREL ;AND REST
%12: MOVEM 15,.JBBLT ;LOAD .JBBLT AT LAST MINUTE
%13: MOVEM 16,.JBBLT+1
%14: JRST .JBBLT ;JUMP INTO EXEC PDL
%15: BLT 17,17 ;CLEAR ALL ACCS
%16: .-. ;START OR EXIT
%17: 0,,1 ;FINAL BLT PTR TO CLEAR ACCS
%END:
DEPHASE
%T1==%END+0
%T2==%T1+1
%T3==%T2+1
%T4==%T3+1
SUBTTL DATA AREAS
.ZZ==.TEMP
IFE TOPS20,<
U (LOW,LOWLEN) ;[1144] LOW CODE FOR RUN UUO--MUST BE FIRST
>
IFN TOPS20,<
U (ACS,20) ;[1144] PLACE TO WORK ON SUICIDE CODE
U (RUNSPC,4) ;[1144] ASCIZ FILE SPEC FOR EXE FILE
> ;END IFN TOPS20
U (TTLPTR) ;BACK POINTER TO LAST SUBPROGRAM
U (JOBPTR) ;POINTER TO COPY OF JOBDAT AREA
U (JBHPTR) ;DITTO FOR HIGH SEG
IFE FTEXE,<
U (LSTPAG) ;-1 WHEN LAST PAGE IS IN CORE
> ;END IFE FTEXE
U (ERRNO) ;.JBERR COUNT
U (JOB116) ;.JBSYM FOR .SYM FILE
U (JOB117) ;.JBUSY FOR .SYM FILE
U (SYMDEW) ;[1172] RESERVE SPACE IN SYMBOL TABLE
U (SYMFUL) ;[1172] SYMOUT HAS NON-SKIPPED ONCE
SUBTTL THE END
XITLIT: END LNKXIT