;_Header ;******************************************************************* ; NOVA CONTROL SYSTEM --- Lawrence Livermore Laboratory ; ; Copyright 1984 by The Regents of the University of California ;******************************************************************* ; ;_Module_Name: PRXHEAP _File: [VCDEV.PRXRTS]PRXHEAP.MAC ; ;_Description: ; Praxis heap management routines for Stand-alone LSI-11 ;_Call: ; JSR PC,PRX$AINIT ; JSR PC,PRX$AFLEX ; JSR PC,PRX$FREE ;_Remarks: ;_Identifier: { none } ;******************************************************************* ;_Author: T. A. SHERMAN _Creation_Date: 14-APR-1984 ;_Revisions: ; 1.000 14-APR-1984 TAS Initial Key-in. ; 1.001 19-Sep-1984 FWH Put Macros inside so self-contained ;******************************************************************* ;_End .TITLE PRXHEAP ; .MCALL PRXMLB ; PRXMLB ;------------------------------------------------------------------ ; Macros used inside this module .MACRO RAISE ID MOV #ID,-(SP) JSR PC,PRX$RAISE .ENDM ;;----------------------------------------------------------------- .PAGE .PSECT $HEAP,REL,CON,LCL,D,RW LOHEAP::.BLKB 256. .PSECT $HEAPA,REL,CON,LCL,D,RW HIHEAP::.WORD 0 .PAGE .PSECT $CODE1,REL,CON,LCL,I,RO HEAPINIT:: MOV #LOHEAP,R0 ; Get pointer to heap CLR (R0) ; Point to no succ CLR 2(R0) ; Point to no pred MOV #-1,4(R0) ; Set stat to free MOV #HIHEAP,6(R0) ; Get hi heap limit SUB #LOHEAP,6(R0) ; Minus lo heap limit SUB #8.,6(R0) ; Minus size of header ; PRINT ; PRINT ,#LOHEAP ; PRINT ,#HIHEAP RTS PC ; Return PRX$AINIT:: ; Allocate and initialize PRX$AFLEX:: MOV R3,-(SP) ; Save R3 MOV R2,-(SP) ; Save R2 MOV R1,-(SP) ; Save R1 MOV 10(SP),-(SP) ; Push num. bytes to allocate JSR PC,PRX$ALLOC ; Call allocate routine MOV 10(SP),R1 ; Get num. bytes to initialize INC R1 ; Round up ( INC followed by ASR ) ASR R1 ; Halve for word count MOV 12(SP),R2 ; Get pointer to constructor MOV R0,R3 ; Get pointer to block 10$: MOV (R2)+,(R3)+ ; Copy constructor SOB R1,10$ ; Until word count is zero MOV (SP)+,R1 ; Restore R1 MOV (SP)+,R2 ; Restore R2 MOV (SP)+,R3 ; Restore R3 MOV (SP)+,(SP) ; Pop parameter MOV (SP)+,(SP) ; Ditto RTS PC ; Return .PAGE PRX$ALLOC:: ; Allocate MOV R5,-(SP) ; Save R5 MOV R4,-(SP) ; Save R4 MOV R3,-(SP) ; Save R3 MOV #LOHEAP,-(SP) ; Get pointer to heap BIT #1,12(SP) ; Allocation size odd BNE 5$ ; If NE yes BR 7$ 5$: INC 12(SP) ; Round up 7$: MOV 12(SP),R0 ; PRINT ,R0 JMP L50$ L10$: MOV @SP,R5 ; Point to this block ; PRINT ,(R5) ; PRINT ,2(R5) TSTB 4(R5) ; Is it free BNE L12$ ; If NE yes ; PRINT JMP L40$ L12$: ; PRINT MOV 6(R5),R4 ; Get size of block ; PRINT ,R4 CMP R4,12(SP) ; Is block an exact fit BNE L13$ ; If NE no ; PRINT JMP L20$ L13$: SUB #8.,R4 ; Add size of a header CMP R4,12(SP) ; Is block large enough to split BGE L14$ ; If GE yes ; PRINT JMP L40$ L14$: ; PRINT MOV R5,R4 ; Make pointer to new block for excess ADD 12(SP),R4 ; Add size of allocation ADD #8.,R4 ; Plus size of header ; PRINT ,R4 MOV (R5),(R4) ; Point him at our succ ; PRINT ,(R4) MOV (R4),R3 ; Did we have a succ BEQ 15$ ; If EQ no MOV R4,2(R3) ; Point our succ at him 15$: MOV R4,(R5) ; Point us at him MOV R5,2(R4) ; Point him at us ; PRINT ,2(R4) MOV #-1,4(R4) ; Set his stat to free ; PRINT MOV 6(R5),6(R4) ; Get his size SUB 12(SP),6(R4) ; Sub size of allocation SUB #8.,6(R4) ; Plus size of header ; PRINT ,6(R4) MOV 12(SP),6(R5) ; Get our size L20$: CLRB 4(R5) ; Set our stat to allocated MOV R5,R0 ; Get pointer to block ADD #8.,R0 ; Add size of header ; PRINT ; PRINT ,0(R5) ; PRINT ,2(R5) ; PRINT ,4(R5) ; PRINT ,6(R5) 30$: TST (SP)+ ; Clean up stack MOV (SP)+,R3 ; Restore R3 MOV (SP)+,R2 ; Restore R2 MOV (SP)+,R1 ; Restore R1 MOV (SP)+,(SP) ; Pop parameter off stack RTS PC ; Return L40$: MOV @0(SP),@SP ; Get pointer to next block L50$: MOV @SP,R0 ; PRINT ,R0 TST @SP ; Is this a nil pointer BEQ 60$ ; If EQ yes JMP L10$ 60$: RAISE x$heap$empty ; Raise exception .PAGE PRX$FREE:: MOV R5,-(SP) ; Save R5 MOV R4,-(SP) ; Save R4 MOV R3,-(SP) ; Save R3 MOV #LOHEAP,-(SP) ; Get pointer to heap SUB #8.,12(SP) ; Sub header size BR 60$ 10$: CMP @SP,12(SP) ; Is this the block to free BNE 50$ ; If NE no MOV @SP,R5 ; Point to this block MOVB #-1,4(R5) ; Set stat to free 20$: MOV (R5),R4 ; Is there a block below us BEQ 30$ ; If EQ no TSTB 4(R4) ; Is it free also BEQ 30$ ; If EQ no ADD 6(R4),6(R5) ; Add his size to us ADD #8.,6(R5) ; Plus his header size MOV (R4),(R5) ; Point to his succ MOV (R5),R3 ; Did he have a succ BEQ 30$ ; If EQ no MOV R5,2(R3) ; Point his succ at us 30$: MOV 2(R5),R4 ; Is there a block above us BEQ 40$ ; If EQ no TSTB 4(R4) ; Is it free also BEQ 40$ ; If EQ no ADD 6(R5),6(R4) ; Add our size to him ADD #8.,6(R4) ; Plus our header size MOV (R5),(R4) ; Point him at our succ MOV (R4),R3 ; Did we have a succ BEQ 40$ ; If EQ no MOV R4,2(R3) ; Point our succ at him 40$: TST (SP)+ ; Clean up stack MOV (SP)+,R3 ; Restore R3 MOV (SP)+,R4 ; Restore R4 MOV (SP)+,R5 ; Restore R5 MOV (SP)+,(SP) ; Pop parameter off stack RTS PC ; Return 50$: MOV @0(SP),@SP ; Get pointer to next block 60$: TST @SP ; Is this a nil pointer BNE 10$ ; If NE no 70$: RAISE x$failed$free ; Raise exception .END