_free: sta ptr2
stx ptr2+1 ; Save block
-; Is the argument NULL?
+; Is the argument NULL? If so, bail out.
ora ptr2+1 ; Is the argument NULL?
- beq @L9 ; Jump if yes
-
-; Decrement the given pointer by the admin space amount, so it points to the
-; real block allocated. The size of the block is stored in the admin space.
-; Remember the block size in ptr1.
-
- lda ptr2
- sub #HEAP_ADMIN_SPACE
- sta ptr2
- bcs @L1
- dec ptr2+1
-@L1: ldy #freeblock_size+1
+ bne @L1 ; Jump if no
+ rts ; Bail out if yes
+
+; There's a pointer below the user space that points to the real start of the
+; raw block. We will decrement the high pointer byte and use an offset of 254
+; to save some code. The first word of the raw block is the total size of the
+; block. Remember the block size in ptr1.
+
+@L1: dec ptr2+1 ; Decrement high pointer byte
+ ldy #$FF
+ lda (ptr2),y ; High byte of real block address
+ tax
+ dey
+ lda (ptr2),y
+ stx ptr2+1
+ sta ptr2 ; Set ptr2 to start of real block
+
+ ldy #usedblock::size+1
lda (ptr2),y ; High byte of size
- sta ptr1+1 ; Save it
+ sta ptr1+1 ; Save it
dey
lda (ptr2),y
sta ptr1
lda __heaplast+1
sta ptr1+1 ; Pointer to last block now in ptr1
- ldy #freeblock_size
+ ldy #freeblock::size
lda (ptr1),y ; Low byte of block size
add ptr1
tax
; Correct the next pointer of the now last block
- ldy #freeblock_prev+1 ; Offset of ->prev field
+ ldy #freeblock::prev+1 ; Offset of ->prev field
lda (ptr1),y
sta ptr2+1 ; Remember f->prev in ptr2
sta __heaplast+1
; }
; } else {
; f->prev = 0;
-; /* Special case: This is the new freelist start */
+; /* Special case: This is the new freelist start */
; _hfirst = f;
; }
; }
; }
; }
;
+;
+; On entry, ptr2 must contain a pointer to the block, which must be at least
+; HEAP_MIN_BLOCKSIZE bytes in size, and ptr1 contains the total size of the
+; block.
+;
; Check if the free list is empty, storing _hfirst into ptr3 for later
; The free list is empty, so this is the first and only block. A contains
; zero if we come here.
- ldy #freeblock_next-1
+ ldy #freeblock::next-1
@L2: iny ; f->next = f->prev = 0;
sta (ptr2),y
- cpy #freeblock_prev+1 ; Done?
+ cpy #freeblock::prev+1 ; Done?
bne @L2
lda ptr2
lda #0
sta ptr4
sta ptr4+1 ; left = 0;
- ldy #freeblock_next+1
+ ldy #freeblock::next+1
ldx ptr3
@Loop: lda ptr3+1 ; High byte of right
dey ; Points to next
lda (ptr3),y ; right = right->next;
tax
- iny ; Points to next+1
+ iny ; Points to next+1
lda (ptr3),y
stx ptr3
sta ptr3+1
; Merge with the right block. Do f->size += right->size;
- ldy #freeblock_size
+ ldy #freeblock::size
lda ptr1
add (ptr3),y
sta (ptr2),y
; No right merge, just set the link.
NoRightMerge:
- ldy #freeblock_next ; f->next = right;
+ ldy #freeblock::next ; f->next = right;
lda ptr3
sta (ptr2),y
iny ; Points to next+1
; We don't have a left block, so f is actually the new freelist start
- ldy #freeblock_prev
+ ldy #freeblock::prev
sta (ptr2),y ; f->prev = 0;
iny
sta (ptr2),y
; Check if the left block is adjacent to the following one
CheckLeftMerge2:
- ldy #freeblock_size ; Calculate left + left->size
+ ldy #freeblock::size ; Calculate left + left->size
lda (ptr4),y ; Low byte of left->size
add ptr4
tax
; Do left->next->prev = left
- iny ; Points to prev
+ iny ; Points to prev
lda ptr4 ; Low byte of left
sta (ptr1),y
iny
lda ptr4+1 ; High byte of left
sta (ptr1),y
- rts ; Done
+ rts ; Done
; This is now the last block, do _heaplast = left
; we come here. Do left->next = f.
NoLeftMerge:
- iny ; Points to next
+ iny ; Points to next
lda ptr2 ; Low byte of left
sta (ptr4),y
iny
; Do f->prev = left
- iny ; Points to prev
+ iny ; Points to prev
lda ptr4
sta (ptr2),y
iny
lda ptr4+1
sta (ptr2),y
- rts ; Done
+ rts ; Done
+
+
-