]> git.sur5r.net Git - cc65/blobdiff - libsrc/common/malloc.s
The spans do now contain the size of a span, no longer the end offset.
[cc65] / libsrc / common / malloc.s
index 548c96ebe5d6ed99e6ddfb8a0da93ed65df2cbd1..0f22090bbc5282028f311677cb54671bd02504f9 100644 (file)
 
 
        .importzp       ptr1, ptr2, ptr3
-       .import         __hptr, __hfirst, __hlast, __hend
        .export         _malloc
 
-       .macpack        generic
-
-; Offsets into struct freeblock and other constant stuff
-
-size           = 0
-next           = 2
-prev           = 4
-admin_space    = 2
-min_size       = 6
+        .include        "_heap.inc"
 
+       .macpack        generic
 
+;-----------------------------------------------------------------------------
 ; Code
 
 _malloc:
-       sta     ptr1            ; Store size in ptr1
+       sta     ptr1                    ; Store size in ptr1
        stx     ptr1+1
 
 ; Check for a size of zero, if so, return NULL
 
        ora     ptr1+1
-       beq     Done            ; a/x already contains zero
+       beq     Done                    ; a/x already contains zero
 
 ; Add the administration space and round up the size if needed
 
        lda     ptr1
-               add     #admin_space
+               add     #HEAP_ADMIN_SPACE
        sta     ptr1
        bcc     @L1
        inc     ptr1+1
 @L1:   ldx     ptr1+1
        bne     @L2
-       cmp     #min_size+1
+       cmp     #HEAP_MIN_BLOCKSIZE+1
        bcs     @L2
-       lda     #min_size
-       sta     ptr1            ; High byte is already zero
+       lda     #HEAP_MIN_BLOCKSIZE
+       sta     ptr1                    ; High byte is already zero
 
 ; Load a pointer to the freelist into ptr2
 
-@L2:   lda     __hfirst
+@L2:   lda     __heapfirst
        sta     ptr2
-               lda     __hfirst+1
+               lda     __heapfirst+1
        sta     ptr2+1
 
 ; Search the freelist for a block that is big enough. We will calculate
@@ -157,21 +150,21 @@ _malloc:
 
        jmp     @L4
 
-@L3:   ldy     #size
+@L3:   ldy     #freeblock::size
                lda     (ptr2),y
                sub     ptr1
-       tax                     ; Remember low byte for later
-       iny                     ; Y points to size+1
+       tax                             ; Remember low byte for later
+       iny                             ; Y points to freeblock::size+1
                lda     (ptr2),y
        sbc     ptr1+1
-       bcs     BlockFound      ; Beware: Contents of a/x/y are known!
+       bcs     BlockFound              ; Beware: Contents of a/x/y are known!
 
 ; Next block in list
 
-       iny                     ; Points to next
+       iny                             ; Points to freeblock::next
        lda     (ptr2),y
        tax
-       iny                     ; Points to next+1
+       iny                             ; Points to freeblock::next+1
        lda     (ptr2),y
        stx     ptr2
        sta     ptr2+1
@@ -180,16 +173,16 @@ _malloc:
 
 ; We did not find a block big enough. Try to use new space from the heap top.
 
-       lda     __hptr
-       add     ptr1            ; _hptr + size
+       lda     __heapptr
+       add     ptr1                    ; _heapptr + size
                tay
-               lda     __hptr+1
+               lda     __heapptr+1
        adc     ptr1+1
-       bcs     OutOfHeapSpace  ; On overflow, we're surely out of space
+       bcs     OutOfHeapSpace          ; On overflow, we're surely out of space
 
-               cmp     __hend+1
+               cmp     __heapend+1
        bne     @L5
-       cpy     __hend
+       cpy     __heapend
 @L5:   bcc     TakeFromTop
        beq     TakeFromTop
 
@@ -199,18 +192,18 @@ OutOfHeapSpace:
        lda     #0
        tax
 Done:  rts
-       
+
 ; There is enough space left, take it from the heap top
 
 TakeFromTop:
-       ldx     __hptr          ; p = hptr;
+       ldx     __heapptr               ; p = _heapptr;
        stx     ptr2
-       ldx     __hptr+1
+       ldx     __heapptr+1
        stx     ptr2+1
 
-       sty     __hptr          ; hptr += size;
-               sta     __hptr+1
-       jmp     FillSizeAndRet  ; Done
+       sty     __heapptr               ; _heapptr += size;
+               sta     __heapptr+1
+       jmp     FillSizeAndRet          ; Done
 
 ; We found a block big enough. If the block can hold just the
 ; requested size, use the block in full. Beware: When slicing blocks,
@@ -220,73 +213,73 @@ TakeFromTop:
 ; flag is set if the high byte of this remaining size is zero.
 
 BlockFound:
-               bne     SliceBlock      ; Block is large enough to slice
-       cpx     #min_size+1     ; Check low byte
-               bcs     SliceBlock      ; Jump if block is large enough to slice
+               bne     SliceBlock              ; Block is large enough to slice
+               cpx     #HEAP_MIN_BLOCKSIZE     ; Check low byte
+               bcs     SliceBlock              ; Jump if block is large enough to slice
 
 ; The block is too small to slice it. Use the block in full. The block
 ; does already contain the correct size word, all we have to do is to
 ; remove it from the free list.
 
-               ldy     #prev+1         ; Load f->prev
+               ldy     #freeblock::prev+1      ; Load f->prev
        lda     (ptr2),y
        sta     ptr3+1
        dey
        lda     (ptr2),y
        sta     ptr3
-       dey                     ; Points to next+1
+       dey                             ; Points to freeblock::next+1
        ora     ptr3+1
-       beq     @L1             ; Jump if f->prev zero
+       beq     @L1                     ; Jump if f->prev zero
 
 ; We have a previous block, ptr3 contains its address.
 ; Do f->prev->next = f->next
 
-       lda     (ptr2),y        ; Load high byte of f->next
-       sta     (ptr3),y        ; Store high byte of f->prev->next
-       dey                     ; Points to next
-       lda     (ptr2),y        ; Load low byte of f->next
-       sta     (ptr3),y        ; Store low byte of f->prev->next
+       lda     (ptr2),y                ; Load high byte of f->next
+       sta     (ptr3),y                ; Store high byte of f->prev->next
+       dey                             ; Points to next
+       lda     (ptr2),y                ; Load low byte of f->next
+       sta     (ptr3),y                ; Store low byte of f->prev->next
        jmp     @L2
 
 ; This is the first block, correct the freelist pointer
 ; Do _hfirst = f->next
 
-@L1:           lda     (ptr2),y        ; Load high byte of f->next
-       sta     __hfirst+1
-       dey                     ; Points to next
-       lda     (ptr2),y        ; Load low byte of f->next
-       sta     __hfirst
+@L1:           lda     (ptr2),y                ; Load high byte of f->next
+       sta     __heapfirst+1
+       dey                             ; Points to next
+       lda     (ptr2),y                ; Load low byte of f->next
+       sta     __heapfirst
 
 ; Check f->next. Y points always to next if we come here
 
-@L2:   lda     (ptr2),y        ; Load low byte of f->next
+@L2:   lda     (ptr2),y                ; Load low byte of f->next
        sta     ptr3
-       iny                     ; Points to next+1
-       lda     (ptr2),y        ; Load high byte of f->next
+       iny                             ; Points to next+1
+       lda     (ptr2),y                ; Load high byte of f->next
        sta     ptr3+1
-       iny                     ; Points to prev
+       iny                             ; Points to prev
        ora     ptr3
-       beq     @L3             ; Jump if f->next zero
+       beq     @L3                     ; Jump if f->next zero
 
 ; We have a next block, ptr3 contains its address.
 ; Do f->next->prev = f->prev
 
-       lda     (ptr2),y        ; Load low byte of f->prev
-       sta     (ptr3),y        ; Store low byte of f->next->prev
-       iny                     ; Points to prev+1
-       lda     (ptr2),y        ; Load high byte of f->prev
-       sta     (ptr3),y        ; Store high byte of f->prev->next
-               jmp     RetUserPtr      ; Done
+       lda     (ptr2),y                ; Load low byte of f->prev
+       sta     (ptr3),y                ; Store low byte of f->next->prev
+       iny                             ; Points to prev+1
+       lda     (ptr2),y                ; Load high byte of f->prev
+       sta     (ptr3),y                ; Store high byte of f->prev->next
+               jmp     RetUserPtr              ; Done
 
 ; This is the last block, correct the freelist pointer.
 ; Do _hlast = f->prev
 
-@L3:           lda     (ptr2),y        ; Load low byte of f->prev
-       sta     __hlast
-       iny                     ; Points to prev+1
-       lda     (ptr2),y        ; Load high byte of f->prev
-       sta     __hlast+1
-       jmp     RetUserPtr      ; Done
+@L3:           lda     (ptr2),y                ; Load low byte of f->prev
+       sta     __heaplast
+       iny                             ; Points to prev+1
+       lda     (ptr2),y                ; Load high byte of f->prev
+       sta     __heaplast+1
+       jmp     RetUserPtr              ; Done
 
 ; We must slice the block found. Cut off space from the upper end, so we
 ; can leave the actual free block chain intact.
@@ -295,41 +288,51 @@ SliceBlock:
 
 ; Decrement the size of the block. Y points to size+1.
 
-       dey                     ; Points to size
-       lda     (ptr2),y        ; Low byte of f->size
+       dey                             ; Points to size
+       lda     (ptr2),y                ; Low byte of f->size
        sub     ptr1
        sta     (ptr2),y
-       tax                     ; Save low byte of f->size in X
-       iny                     ; Points to size+1
-       lda     (ptr2),y        ; High byte of f->size
+       tax                             ; Save low byte of f->size in X
+       iny                             ; Points to size+1
+       lda     (ptr2),y                ; High byte of f->size
        sbc     ptr1+1
        sta     (ptr2),y
 
 ; Set f to the space above the current block, which is the new block returned
 ; to the caller.
 
-       txa                     ; Get low byte of f->size
+       txa                             ; Get low byte of f->size
                add     ptr2
        tax
-       lda     (ptr2),y        ; Get high byte of f->size
+       lda     (ptr2),y                ; Get high byte of f->size
        adc     ptr2+1
        stx     ptr2
        sta     ptr2+1
 
-; Fill the size into the admin space of the block and return the user pointer
+; Fill the size and start address into the admin space of the block
+; (struct usedblock) and return the user pointer
 
 FillSizeAndRet:
-       ldy     #size           ; *p = size;
-       lda     ptr1            ; Low byte of block size
+       ldy     #usedblock::size        ; p->size = size;
+       lda     ptr1                    ; Low byte of block size
        sta     (ptr2),y
-       iny                     ; Points to size+1
+       iny                             ; Points to freeblock::size+1
        lda     ptr1+1
        sta     (ptr2),y
 
 RetUserPtr:
-       lda     ptr2            ; return ++p;
+        ldy     #usedblock::start       ; p->start = p
+        lda     ptr2
+        sta     (ptr2),y
+        iny
+        lda     ptr2+1
+        sta     (ptr2),y
+
+; Return the user pointer, which points behind the struct usedblock
+
+       lda     ptr2                    ; return ++p;
        ldx     ptr2+1
-       add     #admin_space
+       add     #HEAP_ADMIN_SPACE
        bcc     @L9
        inx
 @L9:   rts