Trailing-Edge
-
PDP-10 Archives
-
decuslib10-08
-
43,50501/frecor.mac
There are 5 other files named frecor.mac in the archive. Click here to see a list.
TITLE FRECOR DATA STORAGE IN FREE CORE FOLLOWING USER MEMORY
SUBTTL ERNIE PETRIDES, WESLEYAN UNIVERSITY, JANUARY, 1979
;IMPORTANT INFORMATION FOR THE USER:
; IF HIGH SEGMENT DATA STORAGE IS USED FOR SHARABLE
; PROGRAMS, THE PROGRAMMER MUST BUILD IN A STORAGE MODIFI-
; CATION INTERLOCK TO PREVENT MORE THAN ONE JOB EXECUTING
; THESE ROUTINES SIMULTANEOUSLY !!! ALSO, THESE ROUTINES
; REQUIRE A MINIMUM USEABLE STACK DEPTH OF 5 AND CAN USE A
; MAXIMUM OF UP TO 11 LEVELS. FOLLOWING IS A DESCRIPTION OF
; THE ARGUMENTS PASSED IN AC 16:
;
; ROUTINE SENT RETURNED
; SAV DATA LENGTH,,DATA ADDRESS DATA LENGTH,,STORAGE ADR
; SHR DATA LENGTH,,DATA ADDRESS DATA LENGTH,,STORAGE ADR
; DEL (IGNORED),,STORAGE ADDRESS 0,,SIZE OF DELETED SPACE
; ZER DO HIGH CORE,,DO LOW CORE DELETIONS IN HIGH,,IN LOW
SUBTTL DEFINITIONS AND PARAMETERS
TWOSEG
SALL
ENTRY FC$SAV,FC$SHR,FC$DEL,FC$ZER
EXTERN .JBREL,.JBHRL,.JBFF,.JBHGH,.JBHRN
T1==1 ;GETS RIGHT ARG (ALWAYS PRESERVED)
T2==2 ;GETS LEFT ARG (ALWAYS PRESERVED)
T3==3 ;SCRATCH AC (ALWAYS PRESERVED)
A==16 ;ARGUMENT PASSER (NEGATIVE RETURN ==> ERROR)
P==17 ;PUSH DOWN STACK POINTER
SUBTTL INTERNAL STORAGE
LFCP:: EXP 0 ;LOW SEGMENT FREE-CORE POINTER
SHARED: EXP 0 ;FLAG TO SHOW LOW OR HIGH SEGMENT WORK
RELOC 400000 ;ALL THE REST GOES IN THE HIGH SEGMENT
HFCP:: EXP 0 ;HIGH SEGMENT FREE-CORE POINTER
SUBTTL SUBROUTINE ENTRY PROCEDURE AND ERROR HANDLING
;THIS SETUP IS DONE FOR EACH FC SUBROUTINE ENTRY
SETUP: EXCH T3,(P) ;SAVE TEMP AND GET ROUTINE RTRN ADR
PUSH P,T2 ;SAVE A SECOND TEMP
PUSH P,T1 ;SAVE THE FIRST TEMP
HRRZ T1,A ;PICK UP RIGHT HALF OF ARGUMENT
HLRZ T2,A ;AND PICK UP LEFT HALF
PUSHJ P,(T3) ;DO THE APPROPRIATE ROUTINE
POP P,T1 ;RESTORE THE FIRST TEMP
POP P,T2 ;THE SECOND ONE
POP P,T3 ;AND THE THIRD ONE
POPJ P, ;RETURN TO USER'S PROGRAM
DEFINE ERRMAC
<ITEM CEF,<Core expansion failure>
ITEM ISA,<Illegal to store from accumulator>
ITEM ZLD,<Attempt to store zero length data>
ITEM IDA,<Illegal delete address>
ITEM DFZ,<Internal delete failure on "zero">>
DEFINE ITEM (PFX,MSG)
<PFX'ERR: JSP A,ERRORS
ASCIZ/? FCR'PFX MSG in free-core routines/>
ERRMAC ;SET UP TABLE OF ERROR BRANCHES AND MESSAGES
;HERE ON ALL ERRORS
ERRORS: HRROI A,(A) ;LOAD POINTER TO MESSSAGE AND ERROR MARKER
POPJ P, ;AND RETURN TO SUBROUTINE ENTRY PROCEDURE
SUBTTL FREE-CORE ROUTINES -- SAV,SHR
;HERE TO PUT DATA IN LOW SEGMENT FREE-CORE FOR SAVING
FC$SAV: PUSHJ P,SETUP ;FIRST DO THE SETUP ROUTINE
SETZM SHARED ;SHOW WE'RE WORKING ON LOWSEG
MOVEI A,LFCP ;LOAD ADDRESS OF INITIAL FC PNTR
JRST FCPUT ;DO SAME PUT ROUTINE AS SHR
;HERE TO PUT DATA IN HIGH SEGMENT FREE-CORE FOR SHARING
FC$SHR: PUSHJ P,SETUP ;DO THE STANDARD SETUP
SETOM SHARED ;SHOW WE'RE WORKING ON HISEG
MOVEI A,HFCP ;LOAD ADDRESS OF INITIAL FC PNTR
;FALL THROUGH TO PUT ROUTINE
;HERE TO PUT DATA IN FREE-CORE ON SAV OR SHR
FCPUT: CAIGE T1,20 ;IF DATA ADDRESS IS IN AC'S,
JRST ISAERR ; THEN IT'S AN ILLEGAL ADR
JUMPLE T2,ZLDERR ;ERROR IF ZERO LENGTH DATA
HRRZ T3,(A) ;IF THERE'S NO FIRST LINK,
JUMPE T3,FCNEW ; THEN ADD A NEW ENTRY
;HERE TO SEARCH THROUGH LINKED LIST (A POINTS TO LAST ENTRY)
FCSEA: HRRZ A,(A) ;LOAD LINK TO NEXT FREE-CORE ENTRY
HLRE T3,(A) ;LOAD THE ENTRY'S LENGTH FROM LEFT
ADDI T3,(T2) ;ADD IN THE REQUESTED DATA LENGTH
JUMPLE T3,FCOLD ;RECLAIM ENTRY IF BIG ENOUGH DELETION
HRRZ T3,(A) ;ELSE LOAD ITS LINK TO NEXT ENTRY
JUMPN T3,FCSEA ;AND CONTINUE SEARCH IF IT EXISTS
;HERE TO MAKE NEW FREE-CORE ENTRY AT END OF LIST (A POINTS TO LAST ENTRY)
FCNEW: PUSHJ P,FCGET ;GET T2+1 END SPACE AND RETURN LOC
HRRM T3,(A) ;LINK NEW ENTRY TO FORMER ENTRY
MOVEI A,(T3) ;PUT OUR NODE ADDRESS IN A
HRLZM T2,(A) ;LOAD ENTRY SIZE AND ZERO LINK
JRST FCSTR ;TRANSFER DATA SAME AS BELOW ROUTINE
;HERE TO INSERT DATA IN DELETED ENTRY SPACE (A POINTS TO DELETED ENTRY)
FCOLD: AOJG T3,FCOLD1 ;NO ENTRY DIVISION IF SIZES MATCH
PUSH P,A ;ELSE SAVE NODE POINTER ON STACK
PUSH P,(A) ;AND SAVE OUR NODE HEADER WORD
ADDI A,1(T2) ;CALCULATE ADR OF CREATED NODE
POP P,(A) ;PUT OUR NODE HEADER THERE
HRLM T3,(A) ;BUT USE ITS OWN LENGTH (<=0)
HRRZM A,@(P) ;PUT LINK TO CREATED NODE IN OURS
POP P,A ;RESTORE OUR NODE POINTER TO A
FCOLD1: HRLM T2,(A) ;LOAD OUR DATA LENGTH INTO NODE
;FALL THROUGH TO STORE THE DATA
;HERE TO STORE DATA INTO FREE-CORE ENTRY POINTED TO BY A
FCSTR: HRLI A,(T2) ;PUT DATA LENGTH INTO RETURN ARG
ADDI T2,(A) ;CALCULATE FINAL DATA ADR
AOJ A, ;POINT TO START OF DATA
HRLZS T1 ;PUT RETRIEVAL ADR IN LEFT
HRRI T1,(A) ;AND DESTINATION IN RIGHT
BLT T1,(T2) ;BLOCK TRANSFER THE STUFF
POPJ P, ;AND RETURN TO EXIT ROUTINE
;SUBROUTINE TO ACQUIRE FREE SPACE AT END OF SEGMENT POSSIBLY EXPANDING CORE
;CALL WITH:
; SETXM SHARED ;TO TELL IF HIGH OR LOW SEGMENT
; MOVE T2,<LENGTH OF REQUEST - 1>
; PUSHJ P,FCGET
; RETURN IS HERE WITH STORAGE LOCATION IN T3
; (NEVER RETURNS IF ERROR ON CORE UUO)
;
FCGET: SKIPE SHARED ;IF THIS IS A HISEG REQUEST,
JRST FCGET2 ; THEN DO SPECIAL OTHER STUFF
HRRZ T3,.JBFF ;LOAD ADR OF FIRST FREE IN LOWSEG
ADDI T3,1(T2) ;CALCULATE REQUESTED FRIRST FREE
CAMG T3,.JBREL ;SEE IF THERE'S ENOUGH ROOM IN CORE
JRST FCGET1 ;YES--NO NEED TO EXPAND
CORE T3, ;NO--ASK MONITOR TO EXPAND LOWSEG
JRST FCGET5 ;(CORE ERROR)
HRRZ T3,.JBFF ;RELOAD THE FIRST FREE ADR
ADDI T3,1(T2) ;AND RE-CALCULATE REQUESTED
FCGET1: EXCH T3,.JBFF ;STORE NEW VALUE IN JOB DATA
POPJ P, ;AND RETURN WITH OLD IN T3
FCGET2: HLRZ T3,.JBHGH+.JBHRN ;LOAD HIGH SEGMENT LENGTH
ADDI T3,.JBHGH+1(T2) ;CALCULATE NEEDED FIRST FREE
PUSH P,T3 ;SAVE REQUEST ON THE STACK
HRRZ T3,.JBHRL ;LOAD MOST RECENT WE KNOW ABOUT
CAML T3,(P) ;SEE IF ALREADY ENOUGH ROOM
JRST FCGET3 ;YES--NO NEED TO EXPAND
HRLZ T3,(P) ;NO--LOAD REQUESTED VALUE
CORE T3, ;ASK MONITOR TO EXPAND HISEG
JRST FCGET4 ;(TOO BAD)
FCGET3: POP P,T3 ;RESTORE REQUESTED FIRST FREE
SUBI T3,.JBHGH ;CONVERT ADR TO SEGMENT LENGTH
HLL T3,.JBHGH+.JBHRN ;LOAD PREVIOUS HISEG LENGTH
HRLM T3,.JBHGH+.JBHRN ;STORE NEW VALUE IN JOB DATA
HLRZS T3 ;PUT OLD LENGTH IN RIGHT
ADDI T3,.JBHGH ;AND CONVERT BACK TO ADR
POPJ P, ;RETURN WITH STORAGE ADR IN T3
FCGET4: POP P,(P) ;HERE ON HISEG EXPANSION FAILURE
FCGET5: POP P,(P) ;HERE ON LOWSEG EXPANSION FAILURE
JRST CEFERR ;RESET STACK POINTER AND DO ERROR
SUBTTL FREE-CORE ROUTINES -- DEL
;HERE TO DELETE ENTRY FROM FREE-CORE
FC$DEL: PUSHJ P,SETUP ;DO THE SETUP PROCEDURE
MOVEI A,LFCP ;ASSUME WE'LL DO LOWSEG
CAIL T1,.JBHGH ;BUT IF IT'S A HISEG ADR,
MOVEI A,HFCP ; THEN DO THE HISEG DELETE
FCDEL1: MOVEI T3,(A) ;HERE TO CONTINUE LIST SCAN
HRRZ A,(A) ;LOAD ADDRESS OF NEXT NODE
JUMPE A,IDAERR ;ERROR IF NO MORE IN LIST
CAIE A,-1(T1) ;SEE IF NODE ADR IS THAT OF DATA
JRST FCDEL1 ;LOOP BACK IF NOT FOUND YET
;HERE WHEN FOUND NODE TO DELETE (POINTED TO BY A)
HLRE T1,(A) ;LOAD NODE'S LENGTH FROM LEFT
JUMPLE T1,IDAERR ;ERROR IF ZERO OR ALREADY DELETED
PUSH P,T3 ;SAVE ADDRESS OF PRECEDING NODE
MOVNS T1 ;NEGATE ENTRY'S LENGTH SPEC
HRLZI T2,(T1) ;ALSO PUT INTO LEFT OF T2
HRRI T2,1(A) ;AND MAKE AN AOBJ POINTER
SETZM (T2) ;CLEAR OUT DELETED DATA
AOBJN T2,.-1 ;LOOP UNTIL ALL WORDS DONE
;HERE TO CHECK FOR FORWARD CONCATENATION
HRRZ T2,(A) ;LOAD ADR OF NEXT LINK
JUMPE T2,FCDEL2 ;NOTHING CAN DO IF NOT THERE
HLRE T3,(T2) ;LOAD ITS STORAGE SPEC
JUMPG T3,FCDEL2 ;CAN'T DO IT IF IT'S GOT DATA
MOVEI T3,(T2) ;RELOAD NEXT LINK'S ADR
ADD T3,T1 ;ADD OUR NEGATIVE LENGTH
CAIE T3,1(A) ;IF WE'RE NOT CONTIGUOUS,
JRST FCDEL2 ; THEN SKIP FORWARD ATTEMPT
MOVE T3,(T2) ;ELSE LOAD ITS HEADER WORD
SETZM (T2) ;AND CLEAR ITS HEADER HEADER
HRRM T3,(A) ;USE ITS LINK FOR OURS
HLRES T3 ;GET ITS NEGATIVE LENGTH
ADD T1,T3 ;TOTAL OUR NEGATIVE LENGTH
SOJ T1, ;INCLUDING GAINED HEADER WORD
FCDEL2: HRLM T1,(A) ;PUT LENGTH IN OUR HEADER
;HERE TO CHECK FOR BACKWARD CONCATENATION
POP P,T2 ;UNLOAD ADR OF PRECEDING NODE
CAIE T2,LFCP ;IF IT'S THE LOW FC POINTER,
CAIN T2,HFCP ;OF IT'S THE HIGH FC POINTER,
JRST FCDEL3 ; THEN CAN'T DO IT BACKWARDS
HLRE T3,(T2) ;LOAD ITS LENGTH SPECIFICATION
JUMPG T3,FCDEL3 ;CAN'T DO IT IF HAS DATA IN IT
ADDI T3,(A) ;ADD IN ADDRESS OF OUR NODE
CAIE T3,1(T2) ;IF WE'RE NOT CONTIGUOUS,
JRST FCDEL3 ; THEN THERE'S NOTHING TO DO
HRL A,(A) ;ELSE LOAD OUR LINKAGE POINTER
HLRM A,(T2) ;IN PLACE OF ITS LINKAGE POINTER
SETZM (A) ;ZERO OUR ENTRY HEADER WORD
HLRE T3,(T2) ;RELOAD ITS LENGTH SPEC
ADD T1,T3 ;TOTAL OUR DELETED LENGTHS
SOJ T1, ;AND DON'T FORGET EXTRA HEADER
HRLM T1,(T2) ;PUT LENGTH IN ITS HEADER
;HERE TO EXIT FROM FREE-CORE DELETE ROUTINE
FCDEL3: MOVN A,T1 ;RETURN SIZE FREED BY DELETION
POPJ P, ;AND RETURN TO EXIT PROCEDURE
SUBTTL FREE-CORE ROUTINES -- ZER
;HERE TO DELETE ALL ENTRIES IN FREE-CORE POSSIBLY CONTRACTING CORE
FC$ZER: PUSHJ P,SETUP ;DO THE SETUP PROCEDURE
SETZM SHARED ;INIT AS COUNTER AND FLAG
SKIPE T2 ;IF HISEG ZERO REQUESTED,
HRROS SHARED ; THEN FLAG FOR LATER
JUMPE T1,FCZER1 ;DON'T DO LOWSEG IF NOT REQUESTED
MOVEI T1,LFCP ;LOAD ADDRESS OF LOWSEG FC PNTR
PUSHJ P,FCZSUB ;CALL DELETE SUB FOR STRANGE WORK
JRST FCZER1 ;ERROR RETURN MEANS NO STRUCTURE
HLRE T1,(T3) ;LOAD NEG LENGTH OF LAST ENTRY
ADD T1,.JBFF ;BACK UP ENTRY SIZE FROM END
CAIE T1,1(T3) ;IF ENTRY NOT AT END OF LOWSEG,
JRST FCZER1 ; THEN NOTHING WE CAN DO
HLLZS (T2) ;ELSE MAKE PREVIOUS LINK LAST
SETZM (T3) ;CLEAR THIS HEADER WORD
MOVEM T3,.JBFF ;LOAD NEW FIRST FREE INTO JOBDAT
HRRZ T2,.JBREL ;LOAD HIGHEST LEGAL LOWSEG ADR
TRZ T2,1777 ;CALCULATE LOWEST ADR IN LAST K
CAIG T2,(T3) ;IF NEW FF IS IN THE LAST CHUNK,
JRST FCZER1 ; THEN AVOID USELESS CORE UUO
CORE T3, ;OTHERWISE, CONTRACT THE LOWSEG
JFCL ;IGNORE ANY ERRORS
;HERE WHEN DONE CHECKING LOW SEGMENT
FCZER1: HLLZ T1,SHARED ;LOAD HISEG ZERO INDICATOR
HRLZS SHARED ;SWAP AND INIT DELETION COUNTS
JUMPE T1,FCZER2 ;DON'T ZERO HISEG IF NOT REQUESTED
MOVEI T1,HFCP ;ELSE LOAD ADR OF HISEG FC PNTR
PUSHJ P,FCZSUB ;DO SUB FOR DELETES AND END SEARCH
JRST FCZER2 ;ERROR RETURN MEANS NO STRUCTURE
HLRE T1,(T3) ;LOAD NEG LENGTH OF LAST ENTRY
HLRZ A,.JBHGH+.JBHRN ;LOAD CURRENT HISEG LENGTH
ADDI A,.JBHGH(T1) ;BACK UP ENTRY SIZE FROM END
CAIE A,1(T3) ;IF ENTRY NOT AT END OF HISEG,
JRST FCZER2 ; THEN NOTHING WE CAN DO
HLLZS (T2) ;ELSE MAKE PREVIOUS LINK LAST
SETZM (T3) ;CLEAR THIS HEADER WORD
MOVEI T2,-.JBHGH(T3) ;PUT NEW HISEG LENGTH IN T2
HRLM T2,.JBHGH+.JBHRN ;AND STORE IT INTO HISEG JOBDAT
HLRZ T2,.JBHRL ;LOAD MOST RECENT HISEG LIMIT
TRZ T2,1777 ;CALCULATE LOWEST ADR IN LAST K
CAIG T2,(T3) ;IF OUR NEW FF IS IN SAME K,
JRST FCZER2 ; THEN DON'T DO USELESS UUO
HRLZS T2 ;OTHERWISE, PUT VALUE IN LEFT
CORE T2, ;AND CONTRACT CORE
JFCL ;IGNORING ERRORS
;HERE TO EXIT FROM ZER ROUTINE
FCZER2: MOVS A,SHARED ;LOAD DELETION COUNTS FROM FLAG
POPJ P, ;AND RETURN TO EXIT ROUTINE
;SUBROUTINE TO DELETE FREE-CORE STRUCTURE WITH INITIAL POINTER IN T1
; COUNTING SUCCESSFUL DELETIONS BY INCREMENTING "SHARED", AND
; THEN TO SEARCH FOR END OF LIST LEAVING ADDRESS OF LAST LINK
; IN T3 AND THE ADR OF ITS PREVIOUS LINK IN T2. NEVER RETURNS
; IF A DELETION ERROR IS DETECTED.
;CALL WITH:
; MOVEI T1,XFCP
; PUSHJ P,FCZSUB
; RETURN HERE IF NO STRUCTURE
; RETURN HERE WITH INFO IN T3 AND T2 (AND "SHARED" MODIFIED)
; (NEVER RETURNS ON A DELETION ERROR)
;
FCZSUB: MOVEI T2,(T1) ;LOAD ADDRESS OF INITIAL FC PNTR
FCSUB1: HRRZ T2,(T2) ;CONTINUE SCAN THROUGH LIST
JUMPE T2,FCSUB2 ;OUT IF END OF FC LIST
HLRE T3,(T2) ;LOAD THIS ENTRY'S LENGTH
JUMPLE T3,FCSUB1 ;IGNORE IT IF ALREADY DELETED
MOVEI A,1(T2) ;OTHERWISE, LOAD DATA ADR IN A
PUSHJ P,FC$DEL ;DO THE STANDARD DELETE ROUTINE
JUMPL A,FCSUB6 ;CHECK FOR DELETION FAILURES
AOS SHARED ;BUMP DELETE COUNT IF OKAY
JRST FCZSUB ;LOOP BACK FOR RESCAN
;HERE WHEN ALL IS DELETED FOR FINAL END SEARCH
FCSUB2: MOVEI T2,(T1) ;RELOAD INITIAL FC PNTR ADR
HRRZ T3,(T2) ;LOAD ITS LINK TO NEXT ENTRY
JUMPE T3,FCSUB5 ;NO STRUCTURE IF NOT THERE
FCSUB3: HRRZ A,(T3) ;LOAD NEXT NODE'S LINK TO NEXT
JUMPE A,FCSUB4 ;DONE WHEN FOUND END OF LIST
MOVEI T2,(T3) ;SHIFT BACK PREVIOUS NODE
MOVEI T3,(A) ;SHIFT BACK THIS NODE
JRST FCSUB3 ;CONTINUE SCAN FOR END
;HERE ARE THE EXITS FROM SUBROUTINE "FCZSUB"
FCSUB4: AOS (P) ;SKIP RETURN FOR SUCCESS
FCSUB5: POPJ P, ;PLAIN RETURN FOR NO STRUCTURE
FCSUB6: POP P,(P) ;NON-RETURN IF DELETION FAILURE
JRST DFZERR ;UNLOAD RETURN AND DO ERROR
END