Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 16 additions & 36 deletions src/libc/allocator.src
Original file line number Diff line number Diff line change
@@ -1,60 +1,40 @@
assume adl=1

section .text
public _malloc, _free, _realloc

public _calloc
_calloc:
pop de
pop bc
ex (sp),hl
push bc
push de
call __imulu
push hl
push hl
call _malloc
pop de
add hl,de
xor a,a
sbc hl,de
ld e,a
push de
push hl
call nz,_memset
pop de
pop de
pop de
ret

public _malloc, _free, _realloc, _calloc

if defined ALLOCATOR_SIMPLE

_malloc := __simple_malloc
_free := __simple_free
_realloc := __simple_realloc
extern __simple_free
extern __simple_malloc
extern __simple_realloc
_calloc := __nonzero_fill_calloc
extern __simple_free
extern __simple_malloc
extern __simple_realloc

else if defined ALLOCATOR_STANDARD

_malloc := __standard_malloc
_free := __standard_free
_realloc := __standard_realloc
extern __standard_malloc
extern __standard_free
extern __standard_realloc
_calloc := __nonzero_fill_calloc
extern __standard_malloc
extern __standard_free
extern __standard_realloc

else ; custom functions provided by the program

_malloc := __custom_malloc
_free := __custom_free
_realloc := __custom_realloc
extern __custom_malloc
extern __custom_free
extern __custom_realloc
_calloc := __generic_calloc
extern __custom_malloc
extern __custom_free
extern __custom_realloc

end if

extern __imulu
extern _memset
extern __nonzero_fill_calloc
extern __generic_calloc
4 changes: 3 additions & 1 deletion src/libc/allocator_simple.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

public __simple_malloc
__simple_malloc:
; returns NULL when size is zero
pop bc
ex (sp),hl
push bc
ld de,(_heap_ptr)
dec hl
add hl,de
jr c,.null
ld bc,___heaptop
ld bc,___heaptop-1
sbc hl,bc
jr nc,.null
add hl,bc
Expand Down
3 changes: 2 additions & 1 deletion src/libc/allocator_standard.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ void *_standard_malloc(size_t alloc_size)

/* add size of block header to real size */
const size_t size = alloc_size + sizeof(block_t);
if (size < alloc_size)
/* abort if alloc_size is 0 or size overflowed */
if (size <= alloc_size)
{
return NULL;
}
Expand Down
163 changes: 163 additions & 0 deletions src/libc/calloc.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
assume adl=1

; __nonzero_fill_calloc assumes that malloc(0) returns NULL
; __generic_calloc makes no assumptions

;-------------------------------------------------------------------------------

section .text

public __generic_calloc

if defined __TICE__

; uses TICE specific hardware/platform optimizations

; void *calloc(size_t nmemb, size_t size)
__generic_calloc:
pop de
pop bc
ex (sp), hl
push bc
push de
call __imulu
push hl
push hl
call _malloc
pop bc ; reset SP
pop bc ; BC = size
; test for NULL
add hl, bc
; or a, a ; assumes that ptr + size does not overflow on TICE
sbc hl, bc
ret z ; return NULL
; inlined bzero
push hl
ex de, hl ; DE = dest
; test if the size is zero
scf
sbc hl, hl
add hl, bc
jr nc, .finish
; large region of all zeros on the Ti84CE
ld hl, $E40000 ; HL = src
ldir
pop hl ; return value
ret

else

; makes no hardware assumptions

; void *calloc(size_t nmemb, size_t size)
__generic_calloc:
pop de
pop bc
ex (sp), hl
push bc
push de
call __imulu
push hl
push hl
call _malloc
pop bc ; reset SP
pop bc ; BC = size
; test for NULL
add hl, bc
xor a, a
sbc hl, bc
ret z ; return NULL
; inlined memset/bzero
cpi
add hl, bc
ret c ; size is zero
dec hl
ld (hl), a
ret po ; size is one
push hl
pop de
dec de
lddr
ret

end if

;-------------------------------------------------------------------------------

section .text

public __nonzero_fill_calloc

if defined __TICE__

; uses TICE specific hardware/platform optimizations

; void *calloc(size_t nmemb, size_t size)
__nonzero_fill_calloc:
pop de
pop bc
ex (sp), hl
push bc
push de
call __imulu
push hl
push hl
call _malloc
pop bc ; reset SP
pop bc ; BC = size
; test for NULL
add hl, bc
; or a, a ; assumes that ptr + size does not overflow on TICE
sbc hl, bc
ret z ; return NULL
; inlined bzero
; assumes that malloc(0) returns NULL, so we can skip the check for zero size
push hl
ex de, hl ; DE = dest
; large region of all zeros on the Ti84CE
ld hl, $E40000 ; HL = src
ldir
pop hl ; return value
ret

else

; makes no hardware assumptions

; void *calloc(size_t nmemb, size_t size)
__nonzero_fill_calloc:
pop de
pop bc
ex (sp), hl
push bc
push de
call __imulu
push hl
push hl
call _malloc
pop bc ; reset SP
pop bc ; BC = size
; test for NULL
add hl, bc
xor a, a
sbc hl, bc
ret z ; return NULL
; inlined memset/bzero
; assumes that malloc(0) returns NULL, so we can skip the check for zero size
add hl, bc
cpd
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it is okay for cpd to read nonnull_ptr_from_malloc + size

ld (hl), a
ret po ; size is one
push hl
pop de
dec de
lddr
ret

end if

;-------------------------------------------------------------------------------

extern __imulu
extern _malloc
extern _memset
6 changes: 6 additions & 0 deletions test/standalone/asprintf_fprintf/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,12 @@ int memccpy_tests(void) {
return __LINE__;
}

/* check that no crashes occur with small calloc sizes */
buf = (char*)calloc(1, sizeof(char));
free(buf);
buf = (char*)calloc(0, sizeof(char));
free(buf);

buf = (char*)calloc(file_size + 1, sizeof(char));
if (buf == NULL) {
perror("calloc failure");
Expand Down
Loading