There are no other files named saver.mac in the archive.
TITLE SAVER -- Write an .EXE file on TOPS-10
;This code will work with non-contiguous core.
IFNDEF FTKI10,<FTKI10==-1> ;Assume we must run on old klunkers
DEFINE HISEGB,<-1(DIR)> ;This is where the HISEG bits live
SSAVE:: ;routine to create a sharable .EXE file from what's in core
TLO T3,200000 ;Set the 'Sharable' bit
SAVE:: ;routine to create a nonsharable .EXE file from what's in core
;T1 & T3 should be 0. File should be open on ch 0
; 1 table entry or address of table in T2
;Table entries are of the following format:
; b0-b17 b18 b19 b20 b21 b22 b27-b35
; neg #of pages CW &w/current R W E start page #
; Table ends on 0 word
TLO T3,400000 ;Set the 'Hiseg' bit
PUSH P,[1776,,0] ;Header block
SETZB D1,D2 ;Initialization
SETZB IOW,IOW2 ;
SETZB NEWD1,FREPAG ;
USETO 0,5 ;Start at page 1 of the file
MOVEI FPAGE,1 ;...
TLNE T2,777777 ;1 entry, or pointer to lots
JRST [MOVE T1,T2 ;Just 1 use it as an entry
JSP PC,SAVER1 ;do that & return
JRST SAVERZ] ;no, close up & return
SAVER0: SKIPN T1,(T2) ;Any more entries in table?
JRST SAVERZ ;no, close up & return
JSP PC,SAVER1 ;Do this part
AOJA T2,SAVER0 ;And go back for more
SAVER1: MOVE T5,T1 ;Isolate page #
TRZ T5,760000 ;Get rid of bits here
SAVER2: MOVEI T3,(T5) ;Set up arg for PAGE.
HRLI T3,.PAGCA ;First we must check
PAGE. T3, ; the access of this page
HALT ;Aged & infirm monitor?
JUMPE FREPAG,SAVER3 ;Did we create a page?
CAIN FREPAG,(T5) ;Is this a page we created?
JRST @.+1 ;yes, treat it like a nonexistant page
SAVER3: JUMPL T3,[SETZ NEWD1, ;This page does not exist
JRST SAVER5] ;Clear new directory entry & go
;Start of some code to implement the access bits
;this won't be very useful until TOPS-10 can handle
;.EXE files with other than either private or hiseg pages.
HRRZS NEWD1 ;Clear bits in left half
TXNN T1,SS%UCA ;Limit to current access?
JRST SAVER4 ;no
TXNN T3,PA.GWR ;Is the process page writable?
JRST .+3 ;no, so file page shouldn't be either
SAVER4: TXNE T1,SS%CPY!SS%WR ;Should we allow writing?
TLOA NEWD1,100000 ;Say it's writable
TDO NEWD1,HISEGB ;Turn on 'Hiseg' and possibly 'sharable' flag
;note that pages are always readable & executable
TXNE T3,PA.GAZ ;Is it zero
TRZ NEWD1,777777 ;Yes, remember that
CAMN NEWD1,D1 ;Same as last time?
JRST [ADD D2,[1000,,0] ;Bump the repeat count
JRST SAVER7] ;Go write it, maybe
;Page does exist, so we should save it
TXNN T3,PA.GAZ ;Allocated but 0
HRRI NEWD1,(FPAGE) ;Start at current file page
SAVER5: ;Here to save the current directory entry (if any) on the stack
JUMPE D1,.+3 ;Don't write nothing there
PUSH P,D1 ;Save the previous directory entry
PUSH P,D2 ; ...
MOVEM NEWD1,D1 ;This one is now current
MOVEI D2,(T5) ;Starting with this process page
PUSHJ P,WRITE ;do it
SAVER7: ;Here to Add a page to the I/O list (if not alloc-but-zero)
;and to output some pages if the block has gotten big enough
TRNN NEWD1,-1 ;non-ex,zero or our own page?
JRST SAVER9 ;yes, don't write anything
TRNE T5,37777 ;Is this page 0?
TXNE T3,PA.GHI ;or a Hiseg page?
AOJA FPAGE,CPYPAG ;yes, must copy it first
JUMPN IOW,SAVER8 ;I/O Word is already set up
;Here to build a new IOWD (or a 0 if zero page)
MOVEI IOW,(T5) ;use current process page
LSH IOW,9 ;Convert to word addr
SOJ IOW, ;addr-1
SAVER8: SUB IOW,[1000,,0] ;Set up to write out another page
CAML IOW,[-10000,,0] ;Is it time to write something?
AOJA FPAGE,SAVER9 ;Not yet
AOJ FPAGE, ;Remember to bump page counter
PUSHJ P,WRITE ;Yes, do it
MOVEI IOW,1(5) ;Build new I/O word
LSH IOW,9 ;Convert to word addr
SOJ IOW, ;
SAVER9: AOBJN T5,SAVER2 ;Try next page
PUSHJ P,WRITE ;Write anything that's left
JRST (PC) ;and return
SAVERZ: ;Everything from (DIR) to (P) is the .EXE file directory
JUMPE D1,.+3 ;Don't write null entry
PUSH P,D1 ;Generate the last directory entry
PUSH P,D2 ;
PUSH P,[1777,,1] ;And the closing block
MOVEI T1,-1(DIR) ;Build I/O word
SUBI T1,(P) ;
MOVNI T2,1(T1) ;Stuff length of main part of directory
HRRM T2,(DIR) ;into the start of it
MOVSI IOW,(T1) ;
HRRI IOW,-1(DIR) ;
USETO 0,1 ;Aim at first block of file
ADJSP P,(T1) ;Clean off the stack
HRLI T1,(T1) ;Will subtract from both halves
ADD P,T1 ;Adjust stack pointer
;; Luser must do this himself if not update mode.
;; If it is update mode, do this only if want to kill old hiseg
;;;;; RELEAS 0, ;Close & release channel
JUMPE FREPAG,SAVEZZ ;Did we create a page of our own
HRLI FREPAG,400000 ;Yes, we ought to get rid of it
MOVEI DIR,1 ;Build argument block
PAGE. T3, ;destroy!!!
JFCL ;oh well, we tried,
CPOPJ: POPJ P, ;and return
CPYPAG: PUSHJ P,WRITE ;Write out anything that's waiting
JUMPN FREPAG,CPYPA2 ;Already got a free page
MOVE IOW,.JBREL ;Try to alloc the page above .JBREL
MOVEM IOW,FREPAG ;Save addr of free page
LSH FREPAG,-9 ;as a page addr
AOJ FREPAG, ;to the page after .JBREL
ADDI IOW,1000 ;
CORE IOW, ;
HALT ;fix this someday
CPYPA2: MOVSI IOW,(T5) ;Construct addr of start of source page
HRRI IOW,(FREPAG) ;dest page #
LSH IOW,9 ;word addresses for BLT
MOVEI IOW2,777(IOW) ;get end of page
BLT IOW,(IOW2) ;copy the page
SETZ IOW2, ;Zero this again for the iolist
HRRI IOW,(FREPAG) ;Get the page back again
LSH IOW,9 ;word addr
SOJ IOW, ;-1
HRLI IOW,-1000 ;
PUSHJ P,WRITE ;Write it out
JRST SAVER9 ;Back for more
OUTSTR [Asciz "?
?I/O error while writing .EXE file.
WRITE: TLNE IOW,777777 ;Nothing waiting to go out
OUT 0,IOW ;There was something, we just wrote it
TDZA IOW,IOW ;Clear the I/O word
JRST IOERROR ;OUCH!!