2 ; Ullrich von Bassewitz, 17.7.2000
4 ; Allocate a block from the heap.
6 ; void* __fastcall__ malloc (size_t size);
9 ; C implementation was:
11 ; void* malloc (size_t size)
12 ; /* Allocate memory from the given heap. The function returns a pointer to the
13 ; * allocated memory block or a NULL pointer if not enough memory is available.
14 ; * Allocating a zero size block is not allowed.
17 ; struct freeblock* f;
21 ; /* Check for a size of zero, then add the administration space and round
22 ; * up the size if needed.
27 ; size += HEAP_ADMIN_SPACE;
28 ; if (size < sizeof (struct freeblock)) {
29 ; size = sizeof (struct freeblock);
32 ; /* Search the freelist for a block that is big enough */
34 ; while (f && f->size < size) {
38 ; /* Did we find one? */
41 ; /* We found a block big enough. If the block can hold just the
42 ; * requested size, use the block in full. Beware: When slicing blocks,
43 ; * there must be space enough to create a new one! If this is not the
44 ; * case, then use the complete block.
46 ; if (f->size - size < sizeof (struct freeblock)) {
48 ; /* Use the actual size */
51 ; /* Remove the block from the free list */
53 ; /* We have a previous block */
54 ; f->prev->next = f->next;
56 ; /* This is the first block, correct the freelist pointer */
60 ; /* We have a next block */
61 ; f->next->prev = f->prev;
63 ; /* This is the last block, correct the freelist pointer */
69 ; /* We must slice the block found. Cut off space from the upper
70 ; * end, so we can leave the actual free block chain intact.
73 ; /* Decrement the size of the block */
76 ; /* Set f to the now unused space above the current block */
77 ; f = (struct freeblock*) (((unsigned) f) + f->size);
81 ; /* Setup the pointer for the block */
86 ; /* We did not find a block big enough. Try to use new space from the
89 ; if (((unsigned) _hend) - ((unsigned) _hptr) < size) {
90 ; /* Out of heap space */
95 ; /* There is enough space left, take it from the heap top */
97 ; _hptr = (unsigned*) (((unsigned) _hptr) + size);
101 ; /* New block is now in p. Fill in the size and return the user pointer */
108 .importzp ptr1, ptr2, ptr3
115 ;-----------------------------------------------------------------------------
119 sta ptr1 ; Store size in ptr1
122 ; Check for a size of zero, if so, return NULL
125 beq Done ; a/x already contains zero
127 ; Add the administration space and round up the size if needed
130 add #HEAP_ADMIN_SPACE
136 cmp #HEAP_MIN_BLOCKSIZE+1
138 lda #HEAP_MIN_BLOCKSIZE
139 sta ptr1 ; High byte is already zero
141 ; Load a pointer to the freelist into ptr2
148 ; Search the freelist for a block that is big enough. We will calculate
149 ; (f->size - size) here and keep it, since we need the value later.
153 @L3: ldy #freeblock_size
156 tax ; Remember low byte for later
157 iny ; Y points to freeblock_size+1
160 bcs BlockFound ; Beware: Contents of a/x/y are known!
164 iny ; Points to freeblock_next
167 iny ; Points to freeblock_next+1
174 ; We did not find a block big enough. Try to use new space from the heap top.
177 add ptr1 ; _heapptr + size
181 bcs OutOfHeapSpace ; On overflow, we're surely out of space
196 ; There is enough space left, take it from the heap top
199 ldx __heapptr ; p = _heapptr;
204 sty __heapptr ; _heapptr += size;
206 jmp FillSizeAndRet ; Done
208 ; We found a block big enough. If the block can hold just the
209 ; requested size, use the block in full. Beware: When slicing blocks,
210 ; there must be space enough to create a new one! If this is not the
211 ; case, then use the complete block.
212 ; On input, x/a do contain the remaining size of the block. The zero
213 ; flag is set if the high byte of this remaining size is zero.
216 bne SliceBlock ; Block is large enough to slice
217 cpx #HEAP_MIN_BLOCKSIZE+1 ; Check low byte
218 bcs SliceBlock ; Jump if block is large enough to slice
220 ; The block is too small to slice it. Use the block in full. The block
221 ; does already contain the correct size word, all we have to do is to
222 ; remove it from the free list.
224 ldy #freeblock_prev+1 ; Load f->prev
230 dey ; Points to freeblock_next+1
232 beq @L1 ; Jump if f->prev zero
234 ; We have a previous block, ptr3 contains its address.
235 ; Do f->prev->next = f->next
237 lda (ptr2),y ; Load high byte of f->next
238 sta (ptr3),y ; Store high byte of f->prev->next
240 lda (ptr2),y ; Load low byte of f->next
241 sta (ptr3),y ; Store low byte of f->prev->next
244 ; This is the first block, correct the freelist pointer
245 ; Do _hfirst = f->next
247 @L1: lda (ptr2),y ; Load high byte of f->next
250 lda (ptr2),y ; Load low byte of f->next
253 ; Check f->next. Y points always to next if we come here
255 @L2: lda (ptr2),y ; Load low byte of f->next
257 iny ; Points to next+1
258 lda (ptr2),y ; Load high byte of f->next
262 beq @L3 ; Jump if f->next zero
264 ; We have a next block, ptr3 contains its address.
265 ; Do f->next->prev = f->prev
267 lda (ptr2),y ; Load low byte of f->prev
268 sta (ptr3),y ; Store low byte of f->next->prev
269 iny ; Points to prev+1
270 lda (ptr2),y ; Load high byte of f->prev
271 sta (ptr3),y ; Store high byte of f->prev->next
272 jmp RetUserPtr ; Done
274 ; This is the last block, correct the freelist pointer.
275 ; Do _hlast = f->prev
277 @L3: lda (ptr2),y ; Load low byte of f->prev
279 iny ; Points to prev+1
280 lda (ptr2),y ; Load high byte of f->prev
282 jmp RetUserPtr ; Done
284 ; We must slice the block found. Cut off space from the upper end, so we
285 ; can leave the actual free block chain intact.
289 ; Decrement the size of the block. Y points to size+1.
292 lda (ptr2),y ; Low byte of f->size
295 tax ; Save low byte of f->size in X
296 iny ; Points to size+1
297 lda (ptr2),y ; High byte of f->size
301 ; Set f to the space above the current block, which is the new block returned
304 txa ; Get low byte of f->size
307 lda (ptr2),y ; Get high byte of f->size
312 ; Fill the size into the admin space of the block and return the user pointer
315 ldy #freeblock_size ; *p = size;
316 lda ptr1 ; Low byte of block size
318 iny ; Points to freeblock_size+1
323 lda ptr2 ; return ++p;
325 add #HEAP_ADMIN_SPACE