	.TITLE	HEAP_MANAGEMENT
	.SUBTITLE	DATA STORAGE AREA
	.PSECT	IMPURE_DATA,RD,WRT,NOEXE,NOSHR,LONG,CON,GBL
ARG1:	.LONG	0
ARG2:	.LONG	0
;
;	HEAP STORAGE AREAS
;
;	STORAGE FOR 1 BLOCK LONG SEGMENTS (64 BYTES)
;
ONE_BLOCK:
	.LONG	0,0
;
;	STORAGE FOR 2 BLOCK LONG SEGMENTS (128 BYTES)
;
TWO_BLOCK:
	.LONG	0,0
;
;	STORAGE FOR 3 BLOCK LONG SEGMENTS (192 BYTES)
;
THREE_BLOCK:
	.LONG	0,0
;
;	STORAGE FOR 4 BLOCK LONG SEGMENTS (256 BYTES)
;
FOUR_BLOCK:
	.LONG	0,0
	.PSECT	PURE_DATA,RD,NOWRT,NOEXE,SHR,CON,GBL
VM_ARG:	.LONG	2
	.ADDRESS	ARG1,ARG2
	.PAGE
	.SUBTITLE INIT HEAP SPACE
	.PSECT	CODE,RD,NOWRT,EXE,SHR,CON,GBL
	.ENTRY	INIT_HEAP,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;	INIT THE HEAP QUEUE HEADERS
	MOVAL	ONE_BLOCK,ONE_BLOCK
	MOVL	ONE_BLOCK,ONE_BLOCK+4
	MOVAL	TWO_BLOCK,TWO_BLOCK
	MOVL	TWO_BLOCK,TWO_BLOCK+4
	MOVAL	THREE_BLOCK,THREE_BLOCK
	MOVL	THREE_BLOCK,THREE_BLOCK+4
	MOVAL	FOUR_BLOCK,FOUR_BLOCK
	MOVL	FOUR_BLOCK,FOUR_BLOCK+4
;	LOAD THE INITIAL AMOUNTS ON EACH HEAP
	CALLG	NULL,LOAD_ONE_BLOCK
;	CALLG	NULL,LOAD_TWO_BLOCK                                             ;V1.4
	CALLG	NULL,LOAD_THREE_BLOCK                                           ;V1.4
;	CALLG	NULL,LOAD_FOUR_BLOCK                                            ;V1.4
	RET                                                                     ;**-3
	.PAGE
	.SUBTITLE ALLOCATE FROM SYSSTEM MEMORY-MORE HEAP OF APPROPRIATE SIZE
	.ENTRY	LOAD_ONE_BLOCK,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;	ALLOCATE TO ONE BLOCK LONG SEGMENTS ENOUGH MEMORY FOR
;	500-64 BYTE BLOCKS
	ADDL2	#500,ELEMENT_64		;ADD NEW BLOCKS TO STATISTICS           ;V1.4
	MOVL	#<500*64>,ARG1	;500 BLOCKS (32000 BYTES)
	CALLG	VM_ARG,G^LIB$GET_VM;ASK THE SYSTEM FOR IT
	BLBS	R0,1$
	$EXIT_S	R0
1$:	MOVL	ARG2,R11	;GET STARTING ADDRESS
	MOVL	#500,R10	;SET UP COUNTER FOR 500 BLOCKS
2$:	INSQUE	(R11),ONE_BLOCK	;INSTALL BLOCK OF 64 BYTES IN QUEUE OF FREE STORAGE
	ADDL2	#64,R11		;ADVANCE TO NEXT BLOCK
	SOBGTR	R10,2$		;REPEAT UNTILL ALL BLOCKS INSERTED
	RET
	.ENTRY	LOAD_TWO_BLOCK,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;	ALLOCATE TO TWO BLOCK LONG SEGMENTS ENOUGH MEMORY FOR
;	50-128 BYTE BLOCKS
	ADDL2	#50,ELEMENT_128                                                 ;V1.4
	MOVL	#<50*128>,ARG1	;50 BLOCKS (6400 BYTES)
	CALLG	VM_ARG,G^LIB$GET_VM;ASK THE SYSTEM FOR IT
	BLBS	R0,1$
	$EXIT_S	R0
1$:	MOVL	ARG2,R11	;GET STARTING ADDRESS
	MOVL	#50,R10		;SET UP COUNTER FOR 50 BLOCKS
2$:	INSQUE	(R11),TWO_BLOCK	;INSTALL BLOCK OF 128 BYTES IN QUEUE OF FREE STORAGE
	ADDL2	#128,R11		;ADVANCE TO NEXT BLOCK
	SOBGTR	R10,2$		;REPEAT UNTILL ALL BLOCKS INSERTED
	RET
	.ENTRY	LOAD_THREE_BLOCK,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;	ALLOCATE TO ONE BLOCK LONG SEGMENTS ENOUGH MEMORY FOR
;	2-192 BYTE BLOCKS                                                       ;V1.4
	ADDL2	#2,ELEMENT_192                                                  ;V1.4
	MOVL	#<2*192>,ARG1	;2 BLOCKS (384 BYTES)                           ;V1.4
	CALLG	VM_ARG,G^LIB$GET_VM;ASK THE SYSTEM FOR IT                       ;**-1
	BLBS	R0,1$
	$EXIT_S	R0
1$:	MOVL	ARG2,R11	;GET STARTING ADDRESS
	MOVL	#2,R10	;SET UP COUNTER FOR 2 BLOCKS                            ;V1.4
2$:	INSQUE	(R11),THREE_BLOCK	;INSTALL BLOCK OF 192 BYTES IN QUEUE OF FREE STORAGE
	ADDL2	#192,R11		;ADVANCE TO NEXT BLOCK
	SOBGTR	R10,2$		;REPEAT UNTILL ALL BLOCKS INSERTED
	RET
	.ENTRY	LOAD_FOUR_BLOCK,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;	ALLOCATE TO ONE BLOCK LONG SEGMENTS ENOUGH MEMORY FOR
;	2-256 BYTE BLOCKS
	ADDL2	#2,ELEMENT_256                                                  ;V1.4
	MOVL	#<2*256>,ARG1	;2 BLOCKS (512 BYTES)
	CALLG	VM_ARG,G^LIB$GET_VM;ASK THE SYSTEM FOR IT
	BLBS	R0,1$
	$EXIT_S	R0
1$:	MOVL	ARG2,R11	;GET STARTING ADDRESS
	MOVL	#2,R10	;SET UP COUNTER FOR 2 BLOCKS
2$:	INSQUE	(R11),FOUR_BLOCK	;INSTALL BLOCK OF 512 BYTES IN QUEUE OF FREE STORAGE
	ADDL2	#256,R11		;ADVANCE TO NEXT BLOCK
	SOBGTR	R10,2$		;REPEAT UNTILL ALL BLOCKS INSERTED
	RET
	.PAGE
	.SUBTITLE	ALLOCATE HEAP SPACE
	.ENTRY	ALLOCATE,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;
;	I=ALLOCATE(NUMBER OF BYTES)
;
;	WHERE I IS THE ADDRESS OF THE N*64 BYTE BLOCK ALLOCATED
;
	MOVL	@4(AP),R0		;GET THE COUNT
	BITL	#^X3F,R0		;DOES IT NEED TO BE ROUNDED UP TO
					;NEXT 64 BYTE BLOCK
	BEQL	10$
	BICL2	#^X3F,R0		;LOP OFF LOW ORDER BITS
	ADDL2	#^X40,R0		;AND ROUND UP TO NEXT BLOCK SIZE
10$:	DIVL3	#64,R0,R1		;NUMBER OF BLOCKS
	CASEL	R1,#1,#4		;ALLOCATE FROM APPROPRIATE HEAP
11$:	.WORD	GET_1-11$
	.WORD	GET_2-11$
	.WORD	GET_3-11$
	.WORD	GET_4-11$
;	OTHER SIZE WANTED-ALOCATE AS NEEDED
	MOVL	R0,ARG1			;LOAD BLOCK SIZE
	CALLG	VM_ARG,G^LIB$GET_VM
	BLBS	R0,1$
	$EXIT_S	R0
1$:	MOVL	ARG2,R0
	INCL	ELEMENT_LARGE                                                   ;V1.4
	INCL	ELEMENT_LARGE+4                                                 ;V1.4
	INCL	ELEMENT_LARGE+8                                                 ;V1.4
	RET                                                                     ;V1.4
GET_1:	INCL	ELEMENT_64+4                                                    ;V1.4
	INCL	ELEMENT_64+8                                                    ;V1.4
	REMQUE	@ONE_BLOCK,R0	;GET BLOCK                                      ;V1.4
	BVS	1$		;BRANCH IF NOTHING THERE                        ;**-2
	RET
1$:	CALLG	NULL,LOAD_ONE_BLOCK	;LOAD UP WITH MORE MEMORY
	REMQUE	@ONE_BLOCK,R0		;ALLOCATE
	RET
GET_2:	INCL	ELEMENT_128+4                                                   ;V1.4
	INCL	ELEMENT_128+8                                                   ;V1.4
	REMQUE	@TWO_BLOCK,R0	;GET BLOCK                                      ;V1.4
	BVS	1$		;BRANCH IF NOTHING THERE                        ;**-1
	RET
1$:	CALLG	NULL,LOAD_TWO_BLOCK	;LOAD UP WITH MORE MEMORY
	REMQUE	@TWO_BLOCK,R0		;ALLOCATE
	RET
GET_3:	INCL	ELEMENT_192+4                                                   ;V1.4
	INCL	ELEMENT_192+8                                                   ;V1.4
	REMQUE	@THREE_BLOCK,R0	;GET BLOCK                                      ;V1.4
	BVS	1$		;BRANCH IF NOTHING THERE                        ;**-1
	RET
1$:	CALLG	NULL,LOAD_THREE_BLOCK	;LOAD UP WITH MORE MEMORY
	REMQUE	@THREE_BLOCK,R0		;ALLOCATE
	RET
GET_4:	INCL	ELEMENT_256+4                                                   ;V1.4
	INCL	ELEMENT_256+8                                                   ;V1.4
	REMQUE	@FOUR_BLOCK,R0	;GET BLOCK                                      ;V1.4
	BVS	1$		;BRANCH IF NOTHING THERE                        ;**-1
	RET
1$:	CALLG	NULL,LOAD_FOUR_BLOCK	;LOAD UP WITH MORE MEMORY
	REMQUE	@FOUR_BLOCK,R0		;ALLOCATE
	RET
	.PAGE
	.ENTRY	FREE,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;
;	CALL FREE(SIZE IN BYTES,BLOCK ADDRESS)
;
;
	MOVL	@4(AP),R0		;GET THE COUNT
	BITL	#^X3F,R0		;DOES IT NEED TO BE ROUNDED UP TO
					;NEXT 64 BYTE BLOCK
	BEQL	10$
	BICL2	#^X3F,R0		;LOP OFF LOW ORDER BITS
	ADDL2	#^X40,R0		;AND ROUND UP TO NEXT BLOCK SIZE
10$:	DIVL3	#64,R0,R1
	CASEL	R1,#1,#4		;SELECT WHICH HEAP
11$:	.WORD	PUT_1-11$
	.WORD	PUT_2-11$
	.WORD	PUT_3-11$
	.WORD	PUT_4-11$
;	LARGE SIZE BLOCK-RETURN TO SYSTEM STORAGE
	MOVL	R0,ARG1			;LOAD BLOCK SIZE
	MOVL	@8(AP),ARG2
	CALLG	VM_ARG,G^LIB$FREE_VM
	BLBS	R0,1$
	$EXIT_S	R0
1$:	DECL	ELEMENT_LARGE                                                   ;V1.4
	DECL	ELEMENT_LARGE+4                                                 ;V1.4
	RET                                                                     ;V1.4
PUT_1:	MOVL	@8(AP),R0                                                       ;V1.4
	INSQUE	(R0),ONE_BLOCK                                                  ;V1.4
	DECL	ELEMENT_64+4                                                    ;V1.4
	RET                                                                     ;**-3
PUT_2:	MOVL	@8(AP),R0
	INSQUE	(R0),TWO_BLOCK
	DECL	ELEMENT_128+4                                                   ;V1.4
	RET
PUT_3:	MOVL	@8(AP),R0
	INSQUE	(R0),THREE_BLOCK
	DECL	ELEMENT_192+4                                                   ;V1.4
	RET
PUT_4:	MOVL	@8(AP),R0
	INSQUE	(R0),FOUR_BLOCK
	DECL	ELEMENT_256+4                                                   ;V1.4
	RET
	.END
