Trailing-Edge
-
PDP-10 Archives
-
BB-L014E-BM
-
autopatch/formem.c05
There are no other files named formem.c05 in the archive.
REP 2/1 ;05C1
TV FORMEM MEMORY MANAGEMENT,6(2033)
SUBTTL CHRIS SMITH/CKS
;COPYRIGHT (C) 1981 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
WIT
TV FORMEM MEMORY MANAGEMENT,6(2121)
SUBTTL CHRIS SMITH/CKS/EGM/TGS
;COPYRIGHT (C) 1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
INS 96/1 ;05C2
***** End V6 Development *****
2034 DAW 27-Jan-82
Allow overlaid programs to contain symbols.
2052 EGM 27-Apr-82
Add routine to cut back core for the block structured (OTS) core area.
Cause %FREPGS to kill off pages returned for TOPS-10. Cause CREPGS for
TOPS-10 to kill off any pages obtained for an incomplete request.
Make KILPGS for TOPS-10 more forgiving of 'page non existent' errors.
2053 EGM 23-Apr-82
Improve paged core usage when getting additional pages by:
1. Trying to get specific pages contiguous with the start of
the block list, and
2. Considering any initial free block size when determining
the number of new pages to get.
Also preserve the saved PC when linking in a new free block.
2076 RJD 26-Aug-82
Put FUNCT. functions 17 and 20 in conditional code for TOPS-10
and TOPS-20. For TOPS-10, set F.GPSI and F.RPSI equal to
F.ILL.
2106 TGS 13-Sep-82 20-17750
Install trapping and ERR= handling for disk quota exceeded or
disk full. %FUNCT detects whether the routine address is that
of FOROTS, and allows user to override it.
2111 MRB 27-SEP-82 20-17959
Correct edit 2034.
2114 TGS 1-Oct-82 10-33104
Edit 2034 contains an unneded HRRZ T1,.JBSYM.
2121 RJD 28-Oct-82 20-18131
Add two FUNCT. routines which mark and unmark the
pages in the FOROTS memory management table. The
routines are called by FORSRT to let FOROTS know
that the pages used by SORT are unavailable.
REP 4/2 ;05C3
INTERN %MEMINI
WIT
INTERN %MEMINI,%FUNCX ;[2106]
REP 8/2 ;05C4
EXTERN %POPJ,%POPJ1,%POPJ2,%SAVE1,%SAVE2,%SAVE3,%SAVE4,%SAVE
EXTERN I.XSIR,%LEVTAB,%CHNTAB
WIT
INTERN %MRKBL,%UNMBL ;[2121]
EXTERN %POPJ,%POPJ1,%POPJ2,%SAVE1,%SAVE2,%SAVE3,%SAVE4,%SAVE
EXTERN I.XSIR,%LEVTAB,%CHNTAB,%FCHTB ;[2106]
REP 7/5 ;05C5
STKVAR <SAVET,NP> ;ALLOCATE SPACE ON STACK
MOVEM T1,SAVET ;SAVE T1
MOVEI T1,2*HLEN+777(T1) ;ADD IN 2 HEADERS, ROUND UP TO PAGE BOUND
WIT
STKVAR <SAVET,NP,SAVEP,> ;[2053] ALLOCATE SPACE ON STACK
MOVEM T1,SAVET ;SAVE T1
HRRZ T2,BEGPTR ;[2053] Get beginning of list
SKIPN (T2) ;[2053] EOL?
JRST GBANYP ;[2053] Yes - Get any pages, mark initial hole
SKIPG (T2) ;[2053] Is first block free?
JRST GBSSIZ ;[2053] No - use same size
HLRZ T3,HSIZE(T2) ;[2053] Free block size
SUBI T1,HLEN(T3) ;[2053] Reduce words needed
GBSSIZ: DMOVEM P1,SAVEP ;[2053] Save P ACs
MOVEI P1,(T2) ;[2053] Free block address, always top of page
MOVEI P2,HLEN+777(T1) ;[2053] Size + header, rounded to page
LSHC P1,-^D9 ;[2053] Last page number + 1/no. of pages
SUBI P1,(P2) ;[2053] First page number
PUSHJ P,CREPGS ;[2053] Try to get prefered pages
JRST [DMOVE P1,SAVEP ;[2053] No luck, restore P ACs
MOVE T1,SAVET ;[2053] Get original size
JRST GBANYP] ;[2053] Get any pages, mark hole
MOVEI T1,(P1) ;[2053] Got them, get first page number
LSH T1,^D9 ;[2053] New free block address
HRRZ T4,BEGPTR ;[2053] First block contiguous with new one
SKIPL (T4) ;[2053] Is first block free?
HRRZ T4,HFLNK(T4) ;[2053] Yes - new core ends at successor
DMOVE P1,SAVEP ;[2053] Restore P ACs
JRST GBCONT ;[2053] Use prefered pages
GBANYP: MOVEI T1,2*HLEN+777(T1) ;[2053] ADD 2 HEADERS, ROUND UP TO PAGE BOUND
REP 20/5 ;05C6
CAIE T2,(T3) ;NEW CORE CONTIGUOUS WITH OLD?
JRST GBHOLE ;NO, GO HANDLE HOLE
MOVEI T4,(T2) ;COPY END ADDRESS OF NEW CORE
SKIPLE HFLNK(T4) ;CONTIGUOUS WITH A FREE BLOCK?
HRRZ T4,HFLNK(T4) ;YES, CONSIDER NEW CORE ENDING AT END OF FREE BLOCK
JRST GBCONT ;CONTINUE BELOW
GBHOLE: MOVEI T4,-HLEN(T2) ;MAKE HOLE LOOK LIKE PERMANENTLY ALLOCATED BLOCK
HRROM T3,HFLNK(T4) ;SET FORWARD LINK OF HOLE
WIT
;[2053]
GBHOLE: MOVEI T4,-HLEN(T2) ;MAKE HOLE LOOK LIKE PERMANENTLY ALLOCATED BLOCK
HRLI T3,400000 ;[2052] Unique hole marker for CBC function
MOVEM T3,HFLNK(T4) ;[2052] Set forward link of hole
REP 35/5 ;05C7
HRRZM T1,HBLNK(T4) ;POINT SUCCESSOR BACK TO NEW FREE BLOCK
WIT
HRRM T1,HBLNK(T4) ;[2053] POINT SUCCESSOR BACK TO NEW FREE BLOCK
INS 41/8 ;05C8
;[2121] MARK A BLOCK OF CORE ALLOCATED IN THE PAGE TABLE. THIS ROUTINE
;[2121] IS CALLED WHENEVER A SHARABLE SEGMENT OF A LAYERED PRODUCT
;[2121] IS LOADED VIA GET% (GETSEG) BY FOROTS.
;[2121] ARGS: T1 = FIRST PAGE TO MARK
;[2121] T2 = NUMBER OF PAGES
%MRKBL: PUSHJ P,%SAVE4 ;[2121] SAVE P1-P4
DMOVE P1,T1 ;[2121] GET INTO THE CORRECT ACS
MOVEI T1,1 ;[2121] GET PAGE-ALLOCATED BIT
PUSHJ P,DOPGS ;[2121] MOVE BIT THROUGH PAGE BIT MAP
TDNN T1,PTAB(T2) ;[2121] SEE IF PAGES ARE ALL NOT ALLOCATED
SKIPA ;[2121] ALL FREE, FINE
JRST %POPJ1 ;[2121] SOME PAGE ALLOCATED, TRY AGAIN
MOVEI T1,3 ;[2121] SET PAGE-ALLOCATED AND PAGE-EXIST
PUSHJ P,DOPGS ;[2121] MOVE THROUGH THE BIT MAP
IORM T1,PTAB(T2) ;[2121] WITH THIS INSTRUCTION
POPJ P, ;[2121] SUCCESSFUL IN MARKING PAGES
;[2121] UNMARK A BLOCK OF CORE IN THE PAGE TABLE. WHEN A LAYERED PRODUCT
;[2121] DECIDES TO LEAVE (SUCH AS SORT), THE USER SHOULD BE ABLE TO GET
;[2121] THE PAGES USED BY IT.
%UNMBL: PUSHJ P,%SAVE4 ;[2121] SAVE P1-P4
DMOVE P1,T1 ;[2121] GET INTO THE CORRECT ACS
MOVEI T1,3 ;[2121] GET PAGE-ALLOCATED BIT
PUSHJ P,DOPGS ;[2121] MOVE BIT THROUGH PAGE BIT MAP
TDNE T1,PTAB(T2) ;[2121] SEE IF PAGES ARE ALL NOT ALLOCATED
SKIPA ;[2121] ALL FREE, FINE
JRST %POPJ1 ;[2121] SOME PAGE ALLOCATED, TRY AGAIN
MOVEI T1,3 ;[2121] GET BOTH BITS
PUSHJ P,DOPGS ;[2121] MOVE T1 THROUGH BITS IN PTAB
ANDCAM T1,PTAB(T2) ;[2121] MARK PAGES FREE AND NONEXISTENT
POPJ P, ;[2121] DONE
REP 44/8 ;05C9
;ON RETURN, PAGES ARE MARKED FREE IN BIT MAP
WIT
;[2052] On Return, pages are marked free in bit map for TOPS-20,
;[2052] or have been removed and marked free/non existent for TOPS-10
INS 50/8 ;05C10
IF20,< ;[2052]
INS 54/8 ;05C11
>; End IF20 ;[2052]
IF10,< ;[2052]
PJRST KILPGS ;[2052] Remove the pages and update bit map
>; End IF10 ;[2052]
REP 33/9 ;05C12
POPJ P, ;COULDN'T CREATE THEM, ERROR RETURN
WIT
PJRST KILPGS ;[2052] Can't get them all, kill any created
REP 38/9 ;05C13
POPJ P, ;DIDN'T WORK, ERROR RETURN
WIT
PJRST KILPGS ;[2052] Can't get them all, kill any created
REP 20/12 ;05C14
KILLP: MOVE T1,[-PLEN,,1] ;GET AOBJN POINTER TO PAGE. BLOCK
WIT
KILLP: MOVE T3,[-PLEN,,1] ;[2052] GET AOBJN POINTER TO PAGE. BLOCK
KILLP0: MOVE T1,T3 ;[2052] Get working AOBJN pointer
REP 32/12 ;05C15
; ERR (CDP,999,106,?,<Can't destroy page $O (PAGE. error $O)>,<T2,T1>)
$ECALL CDP,%ABORT
JUMPG P2,KILLP ;IF MORE LEFT TO DO, DO THEM
WIT
JRST [CAIE T1,PAGME% ;[2052] Page does not exist?
;[2052] ERR (CDP,999,106,?,<Can't destroy page $O (PAGE. error $O)>,<T2,T1>)
$ECALL CDP,%ABORT ;[2052] No - some fatal error
HRRZ T1,PBLK ;[2052] Get number of pages
CAIN T1,1 ;[2052] Doing 1 page at a time?
JRST .+1 ;[2052] Yes - just continue loop
;[2052] Don't know which page had error
SUBI P1,(T1) ;[2052] Back to first page
ADDI P2,(T1) ;[2052] Reset count
MOVE T3,[-1,,1] ;[2052] Use single step AOBJN ptr.
JRST KILLP0] ;[2052] From this page on
JUMPG P2,KILLP0 ;[2052] IF MORE LEFT TO DO, DO THEM
INS 1/14 ;05C16
;[2052]Routine to trim block structured (OTS) core area
;[2052]No arguments
;[2052]
;[2052] Trim back the block structured core area by removing all free pages
;[2052] at the beginning of the list. Stop triming when an allocated block
;[2052] or EOL is found, or after having split a block such that there are
;[2052] no more free pages at the beginning of the list.
PGTRIM: STKVAR <NXTBLK> ;[2052] Place to save pointer to next block
HRRZ T1,BEGPTR ;[2052] Start with first block
PGTNXT: SKIPG T2,(T1) ;[2052] Is it free, and not EOL?
JRST PGTDON ;[2052] No - finished
HLRZ T3,HSIZE(T1) ;[2052] Get block size for later
HLRZ T4,(T2) ;[2052] Get allocated marker for next block
CAIE T4,400000 ;[2052] Is it a hole?
JRST PGTNHL ;[2052] No - just look at this block
ADDI T3,HLEN ;[2052] Yes - absorb its length
HRLM T3,HSIZE(T1) ;[2052] Into current block
HRRZ T2,HFLNK(T2) ;[2052] Get its successor
HRRM T2,HFLNK(T1) ;[2052] Link hole out of the
HRRM T1,HBLNK(T2) ;[2052] Block structure entirely
JRST PGTPGS ;[2052] Go release some pages
PGTNHL: MOVEI T4,HLEN(T3) ;[2052] Actual block size
CAIGE T4,^D512 ;[2052] Have at least a page?
JRST PGTDON ;[2052] No - nothing more to do
TRZ T4,777000 ;[2052] Excess words in next page
JUMPE T4,PGTNSU ;[2052] None - release some pages from 1 block
CAIG T4,HLEN ;[2052] Enough room for a block of 1 word?
ADDI T4,^D512 ;[2052] No - one less page to free
SUBI T3,(T4) ;[2052] Reduce current block size
JUMPLE T3,PGTDON ;[2052] If no words left forget it
HRLM T3,HSIZE(T1) ;[2052] Save new block size
ADDI T3,HLEN(T1) ;[2052] Excess block address
HRRZM T2,HFLNK(T3) ;[2052] Setup forward link
HRRM T1,HBLNK(T3) ;[2052] Back link
SUBI T4,HLEN ;[2052] Actual size
HRLM T4,HSIZE(T3) ;[2052] Save away
HRRM T3,HFLNK(T1) ;[2052] Update predecessor pointer
HRRM T3,HBLNK(T2) ;[2052] And successor back pointer
PGTNSU: SETZ T2, ;[2052] No successor block to consider
PGTPGS: HRRZM T2,NXTBLK ;[2052] Save next block address
HRRZ T3,HBLNK(T1) ;[2052] Get block predecessor
HRRZ T4,HFLNK(T1) ;[2052] And successor
HRRM T4,HFLNK(T3) ;[2052] Link pages out of
HRRM T3,HBLNK(T4) ;[2052] Block structure
CAMN T1,FREPTR ;[2052] Giving up first free block?
MOVEM T4,FREPTR ;[2052] Yes - advance to next block
HLRZ T2,HSIZE(T1) ;[2052] Get size of block to free
ADDI T2,HLEN ;[2052] Actual size
LSHC T1,-^D9 ;[2052] Page number/no. of pages
PUSHJ P,%FREPGS ;[2052] Free pages
SKIPE T1,NXTBLK ;[2052] Get next block to do if any
JRST PGTNXT ;[2052] Check further
PGTDON: UNSTK ;[2052] Free local storage
POPJ P, ;[2052] Done
REP 43/14 ;05C17
MOVE P1,JOBFF ;GET END+1 OF LOW SEGMENT
WIT
SETZM SYMFP ;[2034] CLEAR "BETWEEN .JBFF AND .JBSYM" PNTR
SKIPN .JBSYM ;[2034] SYMBOL TABLE?
JRST SETJFF ;[2034] NO
HRRZ T1,.JBSYM ;[2034] YES. GET ITS ADDR
CAMG T1,JOBFF ;[2034] HOLE BETWEEN JBFF AND JBSYM?
JRST MRKSYM ;[2034] NO. JUST START MINILP ABOVE TABLE
;[2034] [2114]
HRL T1,JOBFF ;[2034] GET FIRST FREE LOC IN HOLE
MOVEM T1,SYMFP ;[2034] SAVE FUTURE FREE LIST ENTRY
MRKSYM: HRRZ T1,.JBSYM ;[2034] GET SYMBOL TABLE PNTR AGAIN
HLRE T2,.JBSYM ;[2034] CALC TOP OF TABLE+1
SUB T1,T2 ;[2034] P1 NOW POINTS TO TOP OF SYMTAB+1
CAMLE T1,JOBFF ;[2034] IF GREATER THAN CURRENT .JBFF
MOVEM T1,JOBFF ;[2034] SAVE AS NEW .JBFF
HRL T1,.JBSYM ;[2034] CREATE A SYMBOL TABLE FREE LIST ENTRY
MOVEM T1,SYMTP ;[2034] TO USE IF A CORE REQUEST FAILS
SETJFF: MOVE P1,JOBFF ;[2034] GET END+1 OF LOW SEGMENT
REP 7/15 ;05C18
MINILP: CAILE P1,760 ;HAVE WE HIT TOP OF OUR CORE?
POPJ P,
HRRZ T1,.JBHRL ;GET HS BREAK
WIT
MINILP: CAIG P1,760 ;[2034] HAVE WE HIT TOP OF OUR CORE?
JRST NOTTOP ;[2034] NO
SKIPN SYMFP ;[2034] ANY SPACE BETWEEN .JBFF AND .JBSYM?
POPJ P, ;[2034] NO
PUSHJ P,LSINIT ;[2034] YES. MUST MARK A FREE BLOCK
AOS FLLEN ;[2034] MAKE AN ENTRY
MOVE T1,SYMFP ;[2034] GET THE FREE LIST ENTRY
MOVEM T1,(P3) ;[2034] STORE IT
POPJ P, ;[2034]
NOTTOP: HRRZ T1,.JBHRL ;[2034] GET HS BREAK
REP 22/15 ;05C19
JRST CHKSYM ;NO
WIT
JRST CHKDDT ;[2034] NO
REP 26/15 ;05C20
CHKSYM: HRRZ T1,.JBSYM ;SYMBOL TABLE ADDR
MOVEI T2,(T1) ;COPY IT
HLRE T3,.JBSYM ;NEG COUNT
SUB T2,T3 ;GET HIGH ADDR+1
SOJL T2,CHKDDT ;IF NEG, NO SYMBOLS
PUSHJ P,INUSCK ;PAGE IN SYMBOL TABLE?
AOJA P1,MINILP ;YES, LEAVE IT
WIT
;[2034]
INS 3/17 ;05C21
REQBOT: BLOCK 1 ;[2034] BOTTOM OF CORE REQUEST
REQTOP: BLOCK 1 ;[2034] TOP+1 OF CORE REQUEST
SYMFP: BLOCK 1 ;[2034] SPACE BETWEEN .JBFF AND SYMTAB
SYMTP: BLOCK 1 ;[2034] BOTTOM,,TOP+1 OF SYMBOL TABLE
INS 38/30 ;05C22
EXP F.MPG ;[2121] 21 MARK PAGES AS BEING USED
EXP F.UPG ;[2121] 22 UNMARK PAGES
REP 45/30 ;05C23
SKIPLE T1,@FN(L) ;GET FUNCTION CODE
WIT
%FUNCX: SKIPLE T1,@FN(L) ;[2106] GET FUNCTION CODE
REP 32/31 ;05C24
PUSHJ P,LSGET ;ALLOCATE THE CORE
JRST ERR1 ;NOT ENOUGH MEMORY
JRST ERR2 ;ALREADY ALLOCATED
JRST OKRET ;ALLOCATED
WIT
DMOVEM T1,REQBOT ;[2034] SAVE BOTTOM, TOP+1 OF REQUEST
PUSHJ P,LSGET ;[2034] ALLOCATE THE CORE
JRST ERR1 ;[2034] NOT ENOUGH MEMORY
JRST TRYSYM ;[2034] ALREADY ALLOCATED. SEE IF SYMBOL TABLE
JRST OKRET ;[2034] ALLOCATED
;[2034] HERE IF F.GAD CALL FAILS WITH CORE ALREADY ALLOCATED.
;[2034] IF THE TOP OF THE CORE REQUEST IS WITHIN THE BOUNDS OF THE
;[2034] ORIGINAL SYMBOL TABLE, RECORDED AS ALLOCATED, THE SYMBOL
;[2034] TABLE IS INSERTED INTO THE FREE-CORE LIST. IT IS ASSUMED
;[2034] THAT THE USER (OR OVRLAY) KNOWS WHAT HE/SHE/IT IS DOING...
TRYSYM: SKIPN SYMTP ;[2034] ANY OLD SYMBOL TABLE?
JRST ERR2 ;[2034] NO
HLRZ T1,SYMTP ;[2034] GET BOTTOM OF OLD SYMBOL TABLE
CAMLE T1,REQTOP ;[2111][2034]IS IT BELOW TOP OF REQUESTED CORE?
JRST ERR2 ;[2034] NO
HRRZ T2,SYMTP ;[2034] GET TOP+1 OF OLD SYMBOL TABLE
CAMGE T2,REQTOP ;[2034] IS TOP+1 OF REQUESTED CORE WITHIN IT?
JRST ERR2 ;[2034] NO
SKIPE FLLEN ;[2034] ANY ENTRIES IN FREE-LIST YET?
JRST INSSYM ;[2034] YES. GO INSERT THE SYMTAB ENTRY
PUSHJ P,LSINIT ;[2034] NO. CREATE A FREE LIST
AOS FLLEN ;[2034] INCR # ENTRIES
MOVE T1,SYMTP ;[2034] GET THE SYMBOL TABLE ENTRY
MOVEM T1,(P3) ;[2034] DROP IT INTO THE FREE LIST
JRST GADAGN ;[2034] GO TRY AGAIN
INSSYM: PUSHJ P,LSFREE ;[2034] PUT THE SYMBOL TABLE IN THE FREE-LIST
$SNH ;[2111] BETTER BE A FREE LIST
GADAGN: SETZM SYMTP ;[2034] DON'T TRY THIS AGAIN
DMOVE T1,REQBOT ;[2034] GET THE ORIGINAL CORE REQUEST PARAMS
PUSHJ P,LSGET ;[2034] TRY TO GET IT
JRST ERR1 ;[2034] MEMORY FULL
JRST ERR2 ;[2034] ALREADY ALLOCATED
JRST OKRET ;[2034] GOT IT!
REP 235/31 ;05C25
;RETURNS STATUS 0 ALWAYS, WITH LOW SEG SHRUNK IF POSSIBLE
WIT
;[2052] Returns status 0 always, with low seg and OTS core shrunk if possible
INS 239/31 ;05C26
PUSHJ P,PGTRIM ;[2052] Trim OTS core size if possible
REP 322/31 ;05C27
;OR MTOPR, FOR EXAMPLE).
WIT
;[2106] OR MTOPR, FOR EXAMPLE). IF FOROTS WAS THE PREVIOUS OWNER OF
;[2106] THE CHANNEL (BY EVIDENCE OF THE %FCHTB ENTRY BEING IDENTICAL
;[2106] TO THE %CHNTAB ENTRY), IT IS NOT CONSIDERED AN ERROR CONDITION.
IF10,< ;[2076]
F.GPSI==F.ILL ;[2076] TOPS-20 FUNCTION ONLY
> ;[2076]
IF20,< ;[2076]
REP 330/31 ;05C28
SKIPE %CHNTAB(T1) ;CHANNEL IN USE?
JRST ERR1 ;YES, ERROR
SKIPLE T2,@ARG2(L) ;GET PSI LEVEL
WIT
SKIPN %CHNTAB(T1) ;[2106] CHANNEL IN USE?
JRST GPNIU ;[2106] NO, OK
CAME T2,%FCHTB(T1) ;[2106] WAS FOROTS USING IT?
JRST ERR1 ;[2106] NO, GENUINE ERROR
GPNIU: SKIPLE T2,@ARG2(L) ;[2106] GET PSI LEVEL
REP 352/31 ;05C29
WIT
> ;[2076]
INS 367/31 ;05C30
IF10,< ;[2076]
F.RPSI==F.ILL ;[2076] TOPS-20 FUNCITON ONLY
> ;[2076]
IF20,< ;[2076]
REP 392/31 ;05C31
WIT
> ;[2076]
;[2121] FUNCTION 21: MARK PAGES AS BEING UNAVAILABLE
;[2121]
;[2121] ARG1: ADDRESS OF WORD CONTAINING FIRST PAGE NUMBER TO MARK
;[2121] ARG2: ADDRESS OF WORD CONTAINING NUMBER OF PAGES TO MARK
;[2121]
;[2121] RETURN STATUS 0 IF SUCCESSFUL IN MARKING ALL GIVEN PAGES
;[2121] 1 IF ONE OR MORE PAGES ALREADY IN USE
;[2121] 3 IF ILLEGAL ARGUMENT (BAD PAGE NUMBER OR COUNT)
F.MPG: PUSHJ P,CHKPGA ;[2121] CHECK FOR LEGAL ARGUMENTS
JRST ERR3 ;[2121] BAD CALL
PUSHJ P,%MRKBL ;[2121] MOVE THROUGH THE BIT MAP
JRST OKRET ;[2121] SUCCESSFUL RETURN
JRST ERR1 ;[2121] ONE OR MORE PAGES ALREADY IN USE
;[2121] FUNCTION 22: UNMARK PAGES PREVIOUSLY MARKED BY AN MPG AS FREE
;[2121]
;[2121] ARG1: ADDRESS OF WORD CONTAINING FIRST PAGE NUMBER TO UNMARK
;[2121] ARG2: ADDRESS OF WORD CONTAINING NUMBER OF PAGES TO UNMARK
;[2121]
;[2121] RETURN STATUS 0 IF SUCCESSFUL IN UNMARKING ALL GIVEN PAGES
;[2121] 1 IF ONE OR MORE PAGES WAS NOT IN USE
;[2121] 3 IF ILLEGAL ARGUMENT (PAGE NUMBER OR COUNT)
F.UPG: PUSHJ P,CHKPGA ;[2121] CHECK FOR LEGAL ARGUMENTS
JRST ERR3 ;[2121] BAD CALL
PUSHJ P,%UNMBL ;[2121] MOVE THROUGH THE BIT MAP
JRST OKRET ;[2121] SUCCESSFUL RETURN
JRST ERR1 ;[2121] ONE OR MORE PAGES ALREADY IN USE
CHKPGA: SKIPG T1,@ARG1(L) ;[2121] GET PAGE #
POPJ P, ;[2121] BAD CALL
CAILE T1,777 ;[2121] MUST BE A LOCAL PAGE ADDR
POPJ P, ;[2121] BAD CALL
SKIPG T2,@ARG2(L) ;[2121] GET # PAGES
POPJ P, ;[2121] BAD # PAGES
MOVE T3,T1 ;[2121] CHECK TOTAL
ADD T3,T2 ;[2121]
CAILE T3,1000 ;[2121] TOP PAGE + 1 MUST BE .LE. 1000
POPJ P, ;[2121] BAD CALL
JRST %POPJ1 ;[2121]
SUM 234124