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
109 .import __hptr, __hfirst, __hlast, __hend
114 ; Offsets into struct freeblock and other constant stuff
126 sta ptr1 ; Store size in ptr1
129 ; Check for a size of zero, if so, return NULL
132 beq Done ; a/x already contains zero
134 ; Add the administration space and round up the size if needed
146 sta ptr1 ; High byte is already zero
148 ; Load a pointer to the freelist into ptr2
155 ; Search the freelist for a block that is big enough. We will calculate
156 ; (f->size - size) here and keep it, since we need the value later.
163 tax ; Remember low byte for later
164 iny ; Y points to size+1
167 bcs BlockFound ; Beware: Contents of a/x/y are known!
174 iny ; Points to next+1
181 ; We did not find a block big enough. Try to use new space from the heap top.
184 add ptr1 ; _hptr + size
188 bcs OutOfHeapSpace ; On overflow, we're surely out of space
203 ; There is enough space left, take it from the heap top
206 ldx __hptr ; p = hptr;
211 sty __hptr ; hptr += size;
213 jmp FillSizeAndRet ; Done
215 ; We found a block big enough. If the block can hold just the
216 ; requested size, use the block in full. Beware: When slicing blocks,
217 ; there must be space enough to create a new one! If this is not the
218 ; case, then use the complete block.
219 ; On input, x/a do contain the remaining size of the block. The zero
220 ; flag is set if the high byte of this remaining size is zero.
223 bne SliceBlock ; Block is large enough to slice
224 cpx #min_size+1 ; Check low byte
225 bcs SliceBlock ; Jump if block is large enough to slice
227 ; The block is too small to slice it. Use the block in full. The block
228 ; does already contain the correct size word, all we have to do is to
229 ; remove it from the free list.
231 ldy #prev+1 ; Load f->prev
237 dey ; Points to next+1
239 beq @L1 ; Jump if f->prev zero
241 ; We have a previous block, ptr3 contains its address.
242 ; Do f->prev->next = f->next
244 lda (ptr2),y ; Load high byte of f->next
245 sta (ptr3),y ; Store high byte of f->prev->next
247 lda (ptr2),y ; Load low byte of f->next
248 sta (ptr3),y ; Store low byte of f->prev->next
251 ; This is the first block, correct the freelist pointer
252 ; Do _hfirst = f->next
254 @L1: lda (ptr2),y ; Load high byte of f->next
257 lda (ptr2),y ; Load low byte of f->next
260 ; Check f->next. Y points always to next if we come here
262 @L2: lda (ptr2),y ; Load low byte of f->next
264 iny ; Points to next+1
265 lda (ptr2),y ; Load high byte of f->next
269 beq @L3 ; Jump if f->next zero
271 ; We have a next block, ptr3 contains its address.
272 ; Do f->next->prev = f->prev
274 lda (ptr2),y ; Load low byte of f->prev
275 sta (ptr3),y ; Store low byte of f->next->prev
276 iny ; Points to prev+1
277 lda (ptr2),y ; Load high byte of f->prev
278 sta (ptr3),y ; Store high byte of f->prev->next
279 jmp RetUserPtr ; Done
281 ; This is the last block, correct the freelist pointer.
282 ; Do _hlast = f->prev
284 @L3: lda (ptr2),y ; Load low byte of f->prev
286 iny ; Points to prev+1
287 lda (ptr2),y ; Load high byte of f->prev
289 jmp RetUserPtr ; Done
291 ; We must slice the block found. Cut off space from the upper end, so we
292 ; can leave the actual free block chain intact.
296 ; Decrement the size of the block. Y points to size+1.
299 lda (ptr2),y ; Low byte of f->size
302 tax ; Save low byte of f->size in X
303 iny ; Points to size+1
304 lda (ptr2),y ; High byte of f->size
308 ; Set f to the space above the current block, which is the new block returned
311 txa ; Get low byte of f->size
314 lda (ptr2),y ; Get high byte of f->size
319 ; Fill the size into the admin space of the block and return the user pointer
322 ldy #size ; *p = size;
323 lda ptr1 ; Low byte of block size
325 iny ; Points to size+1
330 lda ptr2 ; return ++p;