mirror of
https://github.com/cc65/cc65.git
synced 2025-01-03 16:33:19 +00:00
Replaced free.c by an assembler version
git-svn-id: svn://svn.cc65.org/cc65/trunk@158 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
c6546592b6
commit
bc320797c6
@ -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)
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* free.c
|
||||
*
|
||||
* Ullrich von Bassewitz, 11.08.1998
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
193
libsrc/common/free.s
Normal file
193
libsrc/common/free.s
Normal file
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user