From 8791c71d1b080532ffe2a9e56d87f47968ca4b7b Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:33:45 -0700 Subject: [PATCH 1/4] made bzero alias ti.boot.memclear under PREFER_OS_LIBC --- src/libc/bzero.src | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libc/bzero.src b/src/libc/bzero.src index 5e3402555..364f16654 100644 --- a/src/libc/bzero.src +++ b/src/libc/bzero.src @@ -7,6 +7,13 @@ .ifdef __TICE__ +.ifdef PREFER_OS_LIBC + + ; ti.boot.memclear + .set _bzero, 0x0000B0 + +.else + ; uses the hardware specific $E40000 memory location ; void bzero(void* buf, size_t n) @@ -24,6 +31,8 @@ _bzero: ldir ret +.endif + .else ; makes no hardware assumptions From 2c20b3548121eec915873579a811bf71f8cf796c Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:59:48 -0700 Subject: [PATCH 2/4] optimized TICE calloc --- src/libc/calloc.src | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libc/calloc.src b/src/libc/calloc.src index 4b8a2b2e8..f2cb19b62 100644 --- a/src/libc/calloc.src +++ b/src/libc/calloc.src @@ -23,22 +23,23 @@ _calloc: pop bc ; BC = size ; test for NULL add hl, bc - ; or a, a ; .assumes that ptr + size does not overflow + ; or a, a ; assumes that ptr + size does not overflow 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, .L.finish - ; large region of all zeros on the Ti84CE - ld hl, $E40000 ; HL = src - ldir -.L.finish: - pop hl ; return value + + dec bc + add hl, bc ; move to the end of dst + ; non-zero + (size - 1) sets carry if size is zero + jr c, .L.zero_size + inc bc + ex de, hl ; DE = dst + ; uses the all zeros address range $E40000-$EFFFFF on the Ti84CE + ld hl, $EFFFFF ; HL = src + lddr + ex de, hl +.L.zero_size: + inc hl ret .else From b6720fc944ac2be2dc2dfa27acf98c33995276ab Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:28:00 -0700 Subject: [PATCH 3/4] fixed calloc tests --- test/standalone/asprintf_fprintf/src/main.c | 65 ++++++++++++++++-- test/standalone/asprintf_fprintf/src/rename.s | 68 +++++++++++-------- 2 files changed, 97 insertions(+), 36 deletions(-) diff --git a/test/standalone/asprintf_fprintf/src/main.c b/test/standalone/asprintf_fprintf/src/main.c index 3c397d36e..6af680e03 100644 --- a/test/standalone/asprintf_fprintf/src/main.c +++ b/test/standalone/asprintf_fprintf/src/main.c @@ -91,6 +91,12 @@ __attribute__((__unused__)) static void print_string(const char* str) { // prevents Clang from replacing function calls with builtins #if RENAME_FUNCTIONS +// this does not have __attribute__((malloc)) so we can test aliasing +void *T_malloc(size_t size); + +// this does not have __attribute__((malloc)) so we can test aliasing +void *T_calloc(size_t nmemb, size_t size); + void T_bzero(void* s, size_t n); void *T_memccpy(void *__restrict dest, const void *__restrict src, int c, size_t n) @@ -182,6 +188,8 @@ char *T_strtok_r(char *__restrict s, const char *__restrict delim, char **__rest #else +#define T_malloc malloc +#define T_calloc calloc #define T_bzero bzero #define T_memccpy memccpy #define T_memchr memchr @@ -571,12 +579,6 @@ 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"); @@ -662,7 +664,7 @@ int bzero_test(void) { if (T_strlen(&data[2]) != 0) { return __LINE__; } - T_bzero(NULL, 0); + T_bzero(&data[8], 17); int cmp = T_memcmp(data, truth, 32); if (cmp != 0) { @@ -1520,8 +1522,57 @@ int mem65536_test(void) { return 0; } +int alloc_test(void) { + /* test that malloc works and returns mutable memory */ + + buf = (char*)T_malloc(1); + C(buf != NULL); + *buf = 0xFF; + C(T_memcmp(buf, SINK, 1) > 0); + *buf = 0x00; + C(T_memcmp(buf, SINK, 1) == 0); + free(buf); + + /* check that no crashes occur with small calloc sizes */ + + buf = (char*)T_calloc(1, sizeof(char)); + C(buf != NULL && *buf == 0x00); + free(buf); + + buf = (char*)T_calloc(2, sizeof(char)); + C(buf != NULL && buf[0] == 0x00 && buf[1] == 0x00); + free(buf); + + /* test allocating zero bytes */ + + /** + * malloc(0) is implementation defined, but it should be safe to assume + * that it does not return `buf` + */ + char * const Pointer_Not_From_Malloc = (char*)&buf; + + buf = (char*)T_malloc(0); + C(buf != Pointer_Not_From_Malloc); + free(buf); + + buf = (char*)T_calloc(0, sizeof(char)); + C(buf != Pointer_Not_From_Malloc); + free(buf); + + // ensure that we do not free twice + buf = NULL; + return 0; +} + int run_tests(void) { int ret = 0; + buf = NULL; + + /* malloc and calloc */ + ret = alloc_test(); + free(buf); buf = NULL; + if (ret != 0) { return ret; } + /* boot_asprintf */ ret = boot_sprintf_tests(); free(buf); buf = NULL; diff --git a/test/standalone/asprintf_fprintf/src/rename.s b/test/standalone/asprintf_fprintf/src/rename.s index a2cb56b5a..589c4e58d 100644 --- a/test/standalone/asprintf_fprintf/src/rename.s +++ b/test/standalone/asprintf_fprintf/src/rename.s @@ -10,6 +10,8 @@ _NULL_ptr: .section .text + .global _T_malloc + .global _T_calloc .global _T_bzero .global _T_memccpy .global _T_memchr @@ -42,6 +44,12 @@ _NULL_ptr: ;------------------------------------------------------------------------------- +_T_malloc: + jp _malloc + +_T_calloc: + jp _calloc + _T_bzero: jp _bzero @@ -131,32 +139,34 @@ _T_strtok_r: ;------------------------------------------------------------------------------- - .global _bzero - .global _memccpy - .global _memchr - .global _memcmp - .global _memcpy - .global _memmem - .global _memmove - .global _mempcpy - .global _memrchr - .global _memrmem - .global _memset - .global _stpcpy - .global _stpncpy - .global _strcat - .global _strchr - .global _strchrnul - .global _strcmp - .global _strcpy - .global _strlcat - .global _strlen - .global _strncat - .global _strncmp - .global _strncpy - .global _strnlen - .global _strrchr - .global _strrstr - .global _strstr - .global _strtok - .global _strtok_r + .extern _malloc + .extern _calloc + .extern _bzero + .extern _memccpy + .extern _memchr + .extern _memcmp + .extern _memcpy + .extern _memmem + .extern _memmove + .extern _mempcpy + .extern _memrchr + .extern _memrmem + .extern _memset + .extern _stpcpy + .extern _stpncpy + .extern _strcat + .extern _strchr + .extern _strchrnul + .extern _strcmp + .extern _strcpy + .extern _strlcat + .extern _strlen + .extern _strncat + .extern _strncmp + .extern _strncpy + .extern _strnlen + .extern _strrchr + .extern _strrstr + .extern _strstr + .extern _strtok + .extern _strtok_r From ab834a9c671d5ddd693baae834428765ff065f04 Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:45:48 -0700 Subject: [PATCH 4/4] use 0xFB0000-0xFFFFFF for zero filling in calloc --- src/libc/calloc.src | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libc/calloc.src b/src/libc/calloc.src index f2cb19b62..06621b335 100644 --- a/src/libc/calloc.src +++ b/src/libc/calloc.src @@ -34,8 +34,12 @@ _calloc: jr c, .L.zero_size inc bc ex de, hl ; DE = dst - ; uses the all zeros address range $E40000-$EFFFFF on the Ti84CE - ld hl, $EFFFFF ; HL = src + ; uses an all zeros address range $FB0000-$FFFFFF on the Ti84CE (327680 bytes) + ; $FF0000-$FFFFFF (65536 bytes) has 1 wait state. + ; $FB0000-$FEFFFF has 2 wait states, but a calloc larger than 65536 bytes is basically never. + ; Since we are only reading zeros, writing to this address range should not interfere with CEmu. + scf + sbc hl, hl ; HL = src lddr ex de, hl .L.zero_size: