From: cuz Date: Sun, 16 Jul 2000 22:09:58 +0000 (+0000) Subject: Replaced free.c by an assembler version X-Git-Tag: V2.12.0~3356 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=bc320797c6c3bf0f9d0ed1069984de4ff5e5c919;p=cc65 Replaced free.c by an assembler version git-svn-id: svn://svn.cc65.org/cc65/trunk@158 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile index bce9f6884..4726d5a5f 100644 --- a/libsrc/common/Makefile +++ b/libsrc/common/Makefile @@ -15,20 +15,73 @@ C_OBJS = fclose.o fgets.o fprintf.o strdup.o calloc.o _fopen.o\ fputs.o fread.o fwrite.o gets.o realloc.o bsearch.o strxfrm.o\ - printf.o _hextab.o malloc.o free.o vfprintf.o fdopen.o strtok.o\ + printf.o _hextab.o malloc.o vfprintf.o fdopen.o strtok.o\ _afailed.o fopen.o fgetc.o fputc.o puts.o gets.o perror.o getchar.o\ _printf.o vprintf.o vsprintf.o sprintf.o abort.o qsort.o putchar.o\ errormsg.o _hadd.o cprintf.o vcprintf.o freopen.o locale.o -S_OBJS = isalpha.o isdigit.o _file.o fmisc.o strlower.o strchr.o tolower.o\ - toupper.o errno.o strcpy.o strlen.o strcat.o strcmp.o itoa.o\ - strupper.o isalpha.o isalnum.o isgraph.o islower.o isupper.o\ - isprint.o ispunct.o isspace.o isxdigit.o isblank.o strrchr.o\ - _stksize.o _heap.o stricmp.o strncmp.o strncpy.o atoi.o setjmp.o\ - longjmp.o rand.o atexit.o memset.o memcpy.o memchr.o memcmp.o\ - ltoa.o strcspn.o strncat.o strpbrk.o strspn.o abs.o labs.o jmpvec.o\ - _fdesc.o stkcheck.o zerobss.o copydata.o _swap.o strstr.o strcoll.o\ - _sys.o getcpu.o _oserror.o strerror.o iscntrl.o maperrno.o +S_OBJS = _fdesc.o \ + _file.o \ + _heap.o \ + _oserror.o \ + _stksize.o \ + _swap.o \ + _sys.o \ + abs.o \ + atexit.o \ + atoi.o \ + copydata.o \ + errno.o \ + fmisc.o \ + free.o \ + getcpu.o \ + isalnum.o \ + isalpha.o \ + isblank.o \ + iscntrl.o \ + isdigit.o \ + isgraph.o \ + islower.o \ + isprint.o \ + ispunct.o \ + isspace.o \ + isupper.o \ + isxdigit.o \ + itoa.o \ + jmpvec.o \ + labs.o \ + longjmp.o \ + ltoa.o \ + maperrno.o \ + memchr.o \ + memcmp.o \ + memcpy.o \ + memset.o \ + rand.o \ + setjmp.o \ + stkcheck.o \ + strcat.o \ + strchr.o \ + strcmp.o \ + strcoll.o \ + strcpy.o \ + strcspn.o \ + strerror.o \ + stricmp.o \ + strlen.o \ + strlower.o \ + strncat.o \ + strncmp.o \ + strncpy.o \ + strpbrk.o \ + strrchr.o \ + strspn.o \ + strstr.o \ + strupper.o \ + tolower.o \ + toupper.o \ + zerobss.o + all: $(C_OBJS) $(S_OBJS) diff --git a/libsrc/common/free.c b/libsrc/common/free.c deleted file mode 100644 index 686f4600a..000000000 --- a/libsrc/common/free.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * free.c - * - * Ullrich von Bassewitz, 11.08.1998 - */ - - - -#include -#include "_heap.h" - - - -void free (void* block) -/* Release an allocated memory block. The function will accept NULL pointers - * (and do nothing in this case). - */ -{ - unsigned* b; - unsigned size; - struct freeblock* f; - - - /* Allow NULL arguments */ - if (block == 0) { - return; - } - - /* Get a pointer to the real memory block, then get the size */ - b = (unsigned*) block; - size = *--b; - - /* Check if the block is at the top of the heap */ - if (((int) b) + size == (int) _hptr) { - - /* Decrease _hptr to release the block */ - _hptr = (unsigned*) (((int) _hptr) - size); - - /* Check if the last block in the freelist is now at heap top. If so, - * remove this block from the freelist. - */ - if (f = _hlast) { - if (((int) f) + f->size == (int) _hptr) { - /* Remove the last block */ - _hptr = (unsigned*) (((int) _hptr) - f->size); - if (_hlast = f->prev) { - /* Block before is now last block */ - f->prev->next = 0; - } else { - /* The freelist is empty now */ - _hfirst = 0; - } - } - } - - } else { - - /* Not at heap top, enter the block into the free list */ - _hadd (b, size); - - } -} - - - diff --git a/libsrc/common/free.s b/libsrc/common/free.s new file mode 100644 index 000000000..faa40c672 --- /dev/null +++ b/libsrc/common/free.s @@ -0,0 +1,193 @@ +; +; Ullrich von Bassewitz, 19.03.2000 +; +; Free a block on the heap. +; +; void __fastcall__ free (void* block); +; +; +; C implementation was: +; +; void free (void* block) +; /* Release an allocated memory block. The function will accept NULL pointers +; * (and do nothing in this case). +; */ +; { +; unsigned* b; +; unsigned size; +; struct freeblock* f; +; +; +; /* Allow NULL arguments */ +; if (block == 0) { +; return; +; } +; +; /* Get a pointer to the real memory block, then get the size */ +; b = (unsigned*) block; +; size = *--b; +; +; /* Check if the block is at the top of the heap */ +; if (((int) b) + size == (int) _hptr) { +; +; /* Decrease _hptr to release the block */ +; _hptr = (unsigned*) (((int) _hptr) - size); +; +; /* Check if the last block in the freelist is now at heap top. If so, +; * remove this block from the freelist. +; */ +; if (f = _hlast) { +; if (((int) f) + f->size == (int) _hptr) { +; /* Remove the last block */ +; _hptr = (unsigned*) (((int) _hptr) - f->size); +; if (_hlast = f->prev) { +; /* Block before is now last block */ +; f->prev->next = 0; +; } else { +; /* The freelist is empty now */ +; _hfirst = 0; +; } +; } +; } +; +; } else { +; +; /* Not at heap top, enter the block into the free list */ +; _hadd (b, size); +; +; } +; } +; + + .importzp ptr1, ptr2 + .import __hptr, __hfirst, __hlast + .import pushax, __hadd + .export _free + +; Offsets into struct freeblock + + size = 0 + next = 2 + prev = 4 + +; Code + +_free: sta ptr1 + stx ptr1+1 ; Save block + +; Is the argument NULL? + + ora ptr1+1 ; Is the argument NULL? + beq @L9 ; Jump if yes + +; Decrement the given pointer by 2. The size of the block is stored there. +; Remember the block size in ptr2. + + sec + lda ptr1 + sbc #2 + sta ptr1 + bcs @L1 + dec ptr1+1 +@L1: ldy #size+1 + lda (ptr1),y ; High byte of size + sta ptr2+1 ; Save it + dey + lda (ptr1),y + sta ptr2 + +; Check if the block is on top of the heap + + clc + adc ptr1 + tay + lda ptr1+1 + adc ptr2+1 + cpy __hptr + bne @AddToFreeList + cmp __hptr+1 + bne @AddToFreeList + +; The pointer is located at the heap top. Lower the heap top pointer to +; release the block. + +@L3: lda ptr1 + sta __hptr + lda ptr1+1 + sta __hptr+1 + +; Check if the last block in the freelist is now at heap top. If so, remove +; this block from the freelist. + + lda __hlast + sta ptr2 + ora __hlast+1 + beq @L9 ; Jump if free list empty + lda __hlast+1 + sta ptr2+1 ; Pointer to last block now in ptr2 + + clc + ldy #size + lda (ptr2),y ; Low byte of block size + adc ptr2 + tax + iny ; High byte of block size + lda (ptr2),y + adc ptr2+1 + + cmp __hptr+1 + bne @L9 ; Jump if last block not on top of heap + cpx __hptr + bne @L9 ; Jump if last block not on top of heap + +; Remove the last block + + lda ptr2 + sta __hptr + lda ptr2+1 + sta __hptr+1 + +; Correct the next pointer of the now last block + + ldy #prev+1 ; Offset of ->prev field + lda (ptr2),y + sta ptr1+1 ; Remember f->prev in ptr1 + sta __hlast+1 + dey + lda (ptr2),y + sta ptr1 ; Remember f->prev in ptr1 + sta __hlast + ora __hlast+1 ; -> prev == 0? + bne @L8 ; Jump if free list not empty + +; Free list is now empty (A = 0) + + sta __hfirst + sta __hfirst+1 + +; Done + +@L9: rts + +; Block before is now last block. ptr1 points to f->prev. + +@L8: lda #$00 + dey ; Points to high byte of ->next + sta (ptr1),y + dey ; Low byte of f->prev->next + sta (ptr1),y + rts ; Done + +; The block is not on top of the heap. Add it to the free list. + +@AddToFreeList: + lda ptr1 + ldx ptr1+1 + jsr pushax ; Push b + lda ptr2 + ldx ptr2+1 + jsr pushax ; Push size + jmp __hadd ; Add to free list and return + + +