--- /dev/null
+;
+; _heap.inc
+;
+; (C) Copyright 2003 Ullrich von Bassewitz (uz@cc65.org)
+;
+
+; Assembler include file that makes the constants and structures in _heap.h
+; available for asm code.
+
+HEAP_ADMIN_SPACE = 2
+HEAP_MIN_BLOCKSIZE = 6 ; Minimum size of an allocated block
+
+; Struct freeblock offsets and size. NOTE: For performance reasons, the asm
+; code often uses increment/decrement operators to access other offsets, so
+; just changing offsets here will probably not work.
+freeblock_size = 0
+freeblock_next = 2
+freeblock_prev = 4
+
+; Variables
+.global __heaporg
+.global __heapptr
+.global __heapend
+.global __heapfirst
+.global __heaplast
--- /dev/null
+/*
+ * _heap.h
+ *
+ * Ullrich von Bassewitz, 03.06.1998
+ *
+ */
+
+
+
+#ifndef __HEAP_H
+#define __HEAP_H
+
+
+
+/* Space needed for administering used blocks */
+#define HEAP_ADMIN_SPACE sizeof (unsigned)
+
+/* The data type used to implement the free list.
+ * Beware: Field order is significant!
+ */
+struct freeblock {
+ unsigned size;
+ struct freeblock* next;
+ struct freeblock* prev;
+};
+
+
+
+/* Variables that describe the heap */
+extern unsigned* _heaporg; /* Bottom of heap */
+extern unsigned* _heapptr; /* Current top */
+extern unsigned* _heapend; /* Upper limit */
+extern struct freeblock* _heapfirst; /* First free block in list */
+extern struct freeblock* _heaplast; /* Last free block in list */
+
+
+
+/* End of _heap.h */
+
+#endif
+
+
+
void* __fastcall__ calloc (size_t count, size_t size);
void* __fastcall__ realloc (void* block, size_t size);
void __fastcall__ free (void* block);
-/* Non standard functions */
-void __fastcall__ _heapadd (void* mem, size_t size);
+
+/* Non standard memory management functions */
+
+void __fastcall__ _heapadd (void* mem, size_t size);
+/* Add a block to the heap */
+
+size_t __fastcall__ _heapmemavail (void);
+/* Return the total free heap space */
+
+size_t __fastcall__ _heapmaxavail (void);
+/* Return the size of the largest free block on the heap */
/* Random numbers */
#define RAND_MAX 0x7FFF
_fopen.o \
_heap.o \
_heapadd.o \
+ _heapmaxavail.o \
+ _heapmemavail.o \
_oserror.o \
_printf.o \
_swap.o \
+++ /dev/null
-/*
- * _heap.h
- *
- * Ullrich von Bassewitz, 03.06.1998
- *
- */
-
-
-
-#ifndef __HEAP_H
-#define __HEAP_H
-
-
-
-/* Space needed for administering used blocks */
-#define HEAP_ADMIN_SPACE sizeof (unsigned)
-
-/* The data type used to implement the free list.
- * Beware: Field order is significant!
- */
-struct freeblock {
- unsigned size;
- struct freeblock* next;
- struct freeblock* prev;
-};
-
-
-
-/* Variables that describe the heap */
-extern unsigned* _horg; /* Bottom of heap */
-extern unsigned* _hptr; /* Current top */
-extern unsigned* _hend; /* Upper limit */
-extern struct freeblock* _hfirst; /* First free block in list */
-extern struct freeblock* _hlast; /* Last free block in list */
-
-
-
-/* End of _heap.h */
-
-#endif
-
-
-
; Heap variables and initialization.
;
- .export __horg, __hptr, __hend, __hfirst, __hlast
.constructor initheap, 24
.import __BSS_RUN__, __BSS_SIZE__, __STACKSIZE__
.importzp sp
+ .include "_heap.inc"
+
+
.data
-__horg:
+__heaporg:
.word __BSS_RUN__+__BSS_SIZE__ ; Linker calculates this symbol
-__hptr:
- .word __BSS_RUN__+__BSS_SIZE__ ; Dito
-__hend:
+__heapptr:
+ .word __BSS_RUN__+__BSS_SIZE__ ; Dito
+__heapend:
.word __BSS_RUN__+__BSS_SIZE__
-__hfirst:
- .word 0
-__hlast:
- .word 0
+__heapfirst:
+ .word 0
+__heaplast:
+ .word 0
; Initialization. Will be called from startup!
.code
initheap:
- sec
- lda sp
- sbc #<__STACKSIZE__
- sta __hend
- lda sp+1
+ sec
+ lda sp
+ sbc #<__STACKSIZE__
+ sta __heapend
+ lda sp+1
sbc #>__STACKSIZE__
- sta __hend+1
+ sta __heapend+1
rts
.importzp ptr1, ptr2
.import popax
.import heapadd
- .export _heapadd
+ .export __heapadd
- .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
-_heapadd:
+__heapadd:
sta ptr1 ; Store size in ptr1
stx ptr1+1
jsr popax ; Get the block pointer
lda ptr1 ; Load low byte
ldx ptr1+1 ; Load/check high byte
bne @L1
- cmp #min_size
+ cmp #HEAP_MIN_BLOCKSIZE
bcs @L1
rts ; Block not large enough
; The block is large enough. Set the size field in the block.
-@L1: ldy #size
+@L1: ldy #freeblock_size
sta (ptr2),y
iny
txa
jmp heapadd
-
-
--- /dev/null
+;
+; Ullrich von Bassewitz, 2003-02-01
+;
+; Return the size of the largest free block on the heap.
+;
+; size_t __fastcall__ _heapmaxavail (void);
+;
+;
+
+ .importzp ptr1, ptr2
+ .export __heapmaxavail
+
+ .include "_heap.inc"
+
+ .macpack generic
+
+;-----------------------------------------------------------------------------
+; Code
+
+__heapmaxavail:
+
+; size_t Size = (_heapend - _heapptr) * sizeof (*_heapend);
+
+ lda __heapend
+ sub __heapptr
+ sta ptr2
+ lda __heapend+1
+ sbc __heapptr+1
+ sta ptr2+1
+
+; struct freeblock* F = _heapfirst;
+
+ lda __heapfirst
+ sta ptr1
+ lda __heapfirst+1
+@L1: sta ptr1+1
+
+; while (F) {
+
+ ora ptr1
+ beq @L3 ; Jump if end of free list reached
+
+; if (Size < F->size) {
+
+ ldy #freeblock_size
+ lda ptr2
+ sub (ptr1),y
+ iny
+ lda ptr2+1
+ sbc (ptr1),y
+ bcs @L2
+
+; Size = F->size;
+
+ ldy #freeblock_size
+ lda (ptr1),y
+ sta ptr2
+ iny
+ lda (ptr1),y
+ sta ptr2+1
+
+; F = F->next;
+
+@L2: iny ; Points to F->next
+ lda (ptr1),y
+ tax
+ iny
+ lda (ptr1),y
+ stx ptr1
+ jmp @L1
+
+; return Size;
+
+@L3: lda ptr2
+ ldx ptr2+1
+ rts
+
--- /dev/null
+;
+; Ullrich von Bassewitz, 2003-02-01
+;
+; Return the amount of free memory on the heap.
+;
+; size_t __fastcall__ _heapmemavail (void);
+;
+;
+
+ .importzp ptr1, ptr2
+ .export __heapmemavail
+
+ .include "_heap.inc"
+
+ .macpack generic
+
+;-----------------------------------------------------------------------------
+; Code
+
+__heapmemavail:
+
+; size_t Size = 0;
+
+ lda #0
+ sta ptr2
+ sta ptr2+1
+
+; struct freeblock* F = _heapfirst;
+
+ lda __heapfirst
+ sta ptr1
+ lda __heapfirst+1
+@L1: sta ptr1+1
+
+; while (F) {
+
+ ora ptr1
+ beq @L2 ; Jump if end of free list reached
+
+; Size += F->size;
+
+ ldy #freeblock_size
+ lda (ptr1),y
+ add ptr2
+ sta ptr2
+ iny
+ lda (ptr1),y
+ adc ptr2+1
+ sta ptr2+1
+
+; F = F->next;
+
+ iny ; Points to F->next
+ lda (ptr1),y
+ tax
+ iny
+ lda (ptr1),y
+ stx ptr1
+ jmp @L1
+
+; return Size + (_heapend - _heapptr) * sizeof (*_heapend);
+
+@L2: lda ptr2
+ add __heapend
+ sta ptr2
+ lda ptr2+1
+ adc __heapend+1
+ tax
+
+ lda ptr2
+ sub __heapptr
+ sta ptr2
+ txa
+ sbc __heapptr+1
+ tax
+ lda ptr2
+
+ rts
+
+
+
;
.importzp ptr1, ptr2, ptr3, ptr4
- .import __hptr, __hfirst, __hlast, __hend
.export _free, heapadd
- .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
_free: sta ptr2
; Remember the block size in ptr1.
lda ptr2
- sub #admin_space
+ sub #HEAP_ADMIN_SPACE
sta ptr2
bcs @L1
dec ptr2+1
-@L1: ldy #size+1
+@L1: ldy #freeblock_size+1
lda (ptr2),y ; High byte of size
sta ptr1+1 ; Save it
dey
tay
lda ptr2+1
adc ptr1+1
- cpy __hptr
- bne heapadd ; Add to free list
- cmp __hptr+1
+ cpy __heapptr
+ bne heapadd ; Add to free list
+ cmp __heapptr+1
bne heapadd
; The pointer is located at the heap top. Lower the heap top pointer to
; release the block.
@L3: lda ptr2
- sta __hptr
+ sta __heapptr
lda ptr2+1
- sta __hptr+1
+ sta __heapptr+1
; Check if the last block in the freelist is now at heap top. If so, remove
; this block from the freelist.
- lda __hlast
+ lda __heaplast
sta ptr1
- ora __hlast+1
+ ora __heaplast+1
beq @L9 ; Jump if free list empty
- lda __hlast+1
+ lda __heaplast+1
sta ptr1+1 ; Pointer to last block now in ptr1
- ldy #size
+ ldy #freeblock_size
lda (ptr1),y ; Low byte of block size
add ptr1
tax
- iny ; High byte of block size
+ iny ; High byte of block size
lda (ptr1),y
adc ptr1+1
- cmp __hptr+1
+ cmp __heapptr+1
bne @L9 ; Jump if last block not on top of heap
- cpx __hptr
+ cpx __heapptr
bne @L9 ; Jump if last block not on top of heap
; Remove the last block
lda ptr1
- sta __hptr
+ sta __heapptr
lda ptr1+1
- sta __hptr+1
+ sta __heapptr+1
; Correct the next pointer of the now last block
- ldy #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 __hlast+1
+ sta ptr2+1 ; Remember f->prev in ptr2
+ sta __heaplast+1
dey
lda (ptr1),y
sta ptr2 ; Remember f->prev in ptr2
- sta __hlast
- ora __hlast+1 ; -> prev == 0?
+ sta __heaplast
+ ora __heaplast+1 ; -> prev == 0?
bne @L8 ; Jump if free list not empty
; Free list is now empty (A = 0)
- sta __hfirst
- sta __hfirst+1
+ sta __heapfirst
+ sta __heapfirst+1
; Done
@L8: lda #$00
dey ; Points to high byte of ->next
sta (ptr2),y
- dey ; Low byte of f->prev->next
+ dey ; Low byte of f->prev->next
sta (ptr2),y
- rts ; Done
+ rts ; Done
; The block is not on top of the heap. Add it to the free list. This was
; formerly a separate function called __hadd that was implemented in C as
; /* Merge with the right block */
; f->size += right->size;
; if (f->next = right->next) {
-; f->next->prev = f;
+; f->next->prev = f;
; } else {
-; /* This is now the last block */
-; _hlast = f;
+; /* This is now the last block */
+; _hlast = f;
; }
; } else {
; /* No merge, just set the link */
; /* Merge with the left block */
; left->size += f->size;
; if (left->next = f->next) {
-; left->next->prev = left;
+; left->next->prev = left;
; } else {
-; /* This is now the last block */
-; _hlast = left;
+; /* This is now the last block */
+; _hlast = left;
; }
; } else {
; /* No merge, just set the link */
; Check if the free list is empty, storing _hfirst into ptr3 for later
heapadd:
- lda __hfirst
+ lda __heapfirst
sta ptr3
- lda __hfirst+1
+ lda __heapfirst+1
sta ptr3+1
ora ptr3
bne SearchFreeList
; The free list is empty, so this is the first and only block. A contains
; zero if we come here.
- ldy #next-1
-@L2: iny ; f->next = f->prev = 0;
+ ldy #freeblock_next-1
+@L2: iny ; f->next = f->prev = 0;
sta (ptr2),y
- cpy #prev+1 ; Done?
+ cpy #freeblock_prev+1 ; Done?
bne @L2
lda ptr2
ldx ptr2+1
- sta __hfirst
- stx __hfirst+1 ; _hfirst = f;
- sta __hlast
- stx __hlast+1 ; _hlast = f;
+ sta __heapfirst
+ stx __heapfirst+1 ; _heapfirst = f;
+ sta __heaplast
+ stx __heaplast+1 ; _heaplast = f;
- rts ; Done
+ rts ; Done
; We have to search the free list. As we are doing so, check if it is possible
; to combine this block with another, already existing block. Beware: The
; block may be the "missing link" between two blocks.
; ptr3 contains _hfirst (the start value of the search) when execution reaches
-; this point, Y contains size+1. We do also know that _hfirst (and therefore
+; this point, Y contains size+1. We do also know that _heapfirst (and therefore
; ptr3) is not zero on entry.
SearchFreeList:
lda #0
sta ptr4
- sta ptr4+1 ; left = 0;
- ldy #next+1
+ sta ptr4+1 ; left = 0;
+ ldy #freeblock_next+1
ldx ptr3
-@Loop: lda ptr3+1 ; High byte of right
+@Loop: lda ptr3+1 ; High byte of right
cmp ptr2+1
bne @L1
cpx ptr2
beq @L2
@L1: bcs CheckRightMerge
-@L2: stx ptr4 ; left = right;
+@L2: stx ptr4 ; left = right;
sta ptr4+1
- dey ; Points to next
- lda (ptr3),y ; right = right->next;
+ 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
; a merge. The new block is the new freelist end.
; A is zero when we come here, Y points to next+1
- sta (ptr2),y ; Clear high byte of f->next
+ sta (ptr2),y ; Clear high byte of f->next
dey
- sta (ptr2),y ; Clear low byte of f->next
+ sta (ptr2),y ; Clear low byte of f->next
- lda ptr2 ; _hlast = f;
- sta __hlast
+ lda ptr2 ; _heaplast = f;
+ sta __heaplast
lda ptr2+1
- sta __hlast+1
+ sta __heaplast+1
; Since we have checked the case that the freelist is empty before, if the
; right pointer is NULL, the left *cannot* be NULL here. So skip the
CheckRightMerge:
lda ptr2
- add ptr1 ; f + size
+ add ptr1 ; f + size
tax
lda ptr2+1
adc ptr1+1
; Merge with the right block. Do f->size += right->size;
- ldy #size
+ ldy #freeblock_size
lda ptr1
add (ptr3),y
sta (ptr2),y
- iny ; Points to size+1
+ iny ; Points to size+1
lda ptr1+1
adc (ptr3),y
sta (ptr2),y
; Set f->next = right->next and remember f->next in ptr1 (we don't need the
; size stored there any longer)
- iny ; Points to next
- lda (ptr3),y ; Low byte of right->next
- sta (ptr2),y ; Store to low byte of f->next
+ iny ; Points to next
+ lda (ptr3),y ; Low byte of right->next
+ sta (ptr2),y ; Store to low byte of f->next
sta ptr1
- iny ; Points to next+1
- lda (ptr3),y ; High byte of right->next
- sta (ptr2),y ; Store to high byte of f->next
+ iny ; Points to next+1
+ lda (ptr3),y ; High byte of right->next
+ sta (ptr2),y ; Store to high byte of f->next
sta ptr1+1
ora ptr1
- beq @L1 ; Jump if f->next zero
+ beq @L1 ; Jump if f->next zero
; f->next->prev = f;
- iny ; Points to prev
- lda ptr2 ; Low byte of f
- sta (ptr1),y ; Low byte of f->next->prev
- iny ; Points to prev+1
- lda ptr2+1 ; High byte of f
- sta (ptr1),y ; High byte of f->next->prev
- jmp CheckLeftMerge ; Done
+ iny ; Points to prev
+ lda ptr2 ; Low byte of f
+ sta (ptr1),y ; Low byte of f->next->prev
+ iny ; Points to prev+1
+ lda ptr2+1 ; High byte of f
+ sta (ptr1),y ; High byte of f->next->prev
+ jmp CheckLeftMerge ; Done
; f->next is zero, this is now the last block
-@L1: lda ptr2 ; _hlast = f;
- sta __hlast
+@L1: lda ptr2 ; _heaplast = f;
+ sta __heaplast
lda ptr2+1
- sta __hlast+1
+ sta __heaplast+1
jmp CheckLeftMerge
; No right merge, just set the link.
NoRightMerge:
- ldy #next ; f->next = right;
+ ldy #freeblock_next ; f->next = right;
lda ptr3
sta (ptr2),y
- iny ; Points to next+1
+ iny ; Points to next+1
lda ptr3+1
sta (ptr2),y
- iny ; Points to prev
- lda ptr2 ; right->prev = f;
+ iny ; Points to prev
+ lda ptr2 ; right->prev = f;
sta (ptr3),y
- iny ; Points to prev+1
+ iny ; Points to prev+1
lda ptr2+1
sta (ptr3),y
; Check if the left pointer is zero
CheckLeftMerge:
- lda ptr4 ; left == NULL?
+ lda ptr4 ; left == NULL?
ora ptr4+1
- bne CheckLeftMerge2 ; Jump if there is a left block
+ bne CheckLeftMerge2 ; Jump if there is a left block
; We don't have a left block, so f is actually the new freelist start
- ldy #prev
- sta (ptr2),y ; f->prev = 0;
+ ldy #freeblock_prev
+ sta (ptr2),y ; f->prev = 0;
iny
sta (ptr2),y
- lda ptr2 ; _hfirst = f;
- sta __hfirst
+ lda ptr2 ; _heapfirst = f;
+ sta __heapfirst
lda ptr2+1
- sta __hfirst+1
+ sta __heapfirst+1
- rts ; Done
+ rts ; Done
; Check if the left block is adjacent to the following one
CheckLeftMerge2:
- ldy #size ; Calculate left + left->size
- lda (ptr4),y ; Low byte of left->size
+ ldy #freeblock_size ; Calculate left + left->size
+ lda (ptr4),y ; Low byte of left->size
add ptr4
tax
- iny ; Points to size+1
- lda (ptr4),y ; High byte of left->size
+ iny ; Points to size+1
+ lda (ptr4),y ; High byte of left->size
adc ptr4+1
cpx ptr2
bne NoLeftMerge
cmp ptr2+1
- bne NoLeftMerge ; Jump if blocks not adjacent
+ bne NoLeftMerge ; Jump if blocks not adjacent
; Merge with the left block. Do left->size += f->size;
- dey ; Points to size
+ dey ; Points to size
lda (ptr4),y
add (ptr2),y
sta (ptr4),y
- iny ; Points to size+1
+ iny ; Points to size+1
lda (ptr4),y
adc (ptr2),y
sta (ptr4),y
; Set left->next = f->next and remember left->next in ptr1.
- iny ; Points to next
- lda (ptr2),y ; Low byte of f->next
+ iny ; Points to next
+ lda (ptr2),y ; Low byte of f->next
sta (ptr4),y
sta ptr1
- iny ; Points to next+1
- lda (ptr2),y ; High byte of f->next
+ iny ; Points to next+1
+ lda (ptr2),y ; High byte of f->next
sta (ptr4),y
sta ptr1+1
- ora ptr1 ; left->next == NULL?
+ ora ptr1 ; left->next == NULL?
beq @L1
; Do left->next->prev = left
- iny ; Points to prev
- lda ptr4 ; Low byte of left
+ iny ; Points to prev
+ lda ptr4 ; Low byte of left
sta (ptr1),y
iny
- lda ptr4+1 ; High byte of left
+ lda ptr4+1 ; High byte of left
sta (ptr1),y
- rts ; Done
+ rts ; Done
-; This is now the last block, do _hlast = left
+; This is now the last block, do _heaplast = left
@L1: lda ptr4
- sta __hlast
+ sta __heaplast
lda ptr4+1
- sta __hlast+1
- rts ; Done
+ sta __heaplast+1
+ rts ; Done
; No merge of the left block, just set the link. Y points to size+1 if
; we come here. Do left->next = f.
NoLeftMerge:
- iny ; Points to next
- lda ptr2 ; Low byte of left
+ iny ; Points to next
+ lda ptr2 ; Low byte of left
sta (ptr4),y
iny
- lda ptr2+1 ; High byte of left
+ lda ptr2+1 ; High byte of left
sta (ptr4),y
; 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
+
.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
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
; 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
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,
; 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+1 ; 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.
; 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
FillSizeAndRet:
- ldy #size ; *p = size;
- lda ptr1 ; Low byte of block size
+ ldy #freeblock_size ; *p = 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;
+ lda ptr2 ; return ++p;
ldx ptr2+1
- add #admin_space
+ add #HEAP_ADMIN_SPACE
bcc @L9
inx
@L9: rts
#include <stdlib.h>
#include <string.h>
-#include "_heap.h"
+#include <_heap.h>
diff = size - oldsize;
/* Is the block at the current heap top? */
- if (((int) b) + oldsize == ((int) _hptr)) {
+ if (((int) b) + oldsize == ((int) _heapptr)) {
/* Check if we've enough memory at the heap top */
int newhptr;
- newhptr = ((int) _hptr) + diff;
- if (newhptr <= ((int) _hend)) {
+ newhptr = ((int) _heapptr) + diff;
+ if (newhptr <= ((int) _heapend)) {
/* Ok, there's space enough */
- _hptr = (unsigned*) newhptr;
+ _heapptr = (unsigned*) newhptr;
*b = size;
return block;
}
+