Skip to content

Optimized memcpy and mempcpy #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 27, 2025
Merged
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
20 changes: 20 additions & 0 deletions src/libc/bzero.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
assume adl=1

section .text

public _bzero

; void bzero(void* buf, size_t n)
_bzero:
ld hl, 6
add hl, sp
ld bc, (hl) ; size
inc bc
cpd ; dec hl
ret po ; zero size
dec hl
dec hl
ld de, (hl) ; buf
ld hl, $E40000 ; large region of all zeros on the Ti84CE
ldir
ret
3 changes: 3 additions & 0 deletions src/libc/include/string.h
Original file line number Diff line number Diff line change
@@ -14,6 +14,9 @@ void *memmove(void *dest, const void *src, size_t n)
void *memset(void *s, int c, size_t n)
__attribute__((nonnull(1)));

void bzero(void *s, size_t n)
__attribute__((nonnull(1)));

int memcmp(const void *s1, const void *s2, size_t n)
__attribute__((nonnull(1, 2)));

21 changes: 10 additions & 11 deletions src/libc/memcpy.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
assume adl=1

section .text

public _memcpy

if PREFER_OS_LIBC
@@ -10,19 +11,17 @@ _memcpy := $0000A4
else

_memcpy:
ld iy,0
add iy,sp
ld bc,(iy + 9) ; Load count
sbc hl,hl
sbc hl,bc
jr z,.zero
ld de,(iy + 3) ; Load destination
ld hl,(iy + 6) ; Load source
ld iy, -1
add iy, sp
ld bc, (iy + 10) ; Load count
sbc hl, hl
add hl, bc
jr nc, .zero
ld de, (iy + 4) ; Load destination
ld hl, (iy + 7) ; Load source
ldir
.zero:
ld hl,(iy + 3) ; Return the destination pointer
ld hl, (iy + 4) ; Return the destination pointer
ret

end if


24 changes: 12 additions & 12 deletions src/libc/mempcpy.src
Original file line number Diff line number Diff line change
@@ -8,14 +8,14 @@ if 0

; faster when count is zero
_mempcpy:
ld iy, 0
ld iy, -1
add iy, sp
ld bc, (iy + 9) ; Load count
ld bc, (iy + 10) ; Load count
sbc hl, hl
sbc hl, bc
ld hl, (iy + 3) ; Load destination
ret z ; zero bytes to copy
ld de, (iy + 6) ; Load source
add hl, bc
ld hl, (iy + 4) ; Load destination
ret nc ; zero bytes to copy
ld de, (iy + 7) ; Load source
ex de, hl
ldir
ex de, hl
@@ -25,14 +25,14 @@ else

; faster in full execution case by 0F + 1 clock cycles
_mempcpy:
ld iy, 0
ld iy, -1
add iy, sp
ld bc, (iy + 9) ; Load count
ld bc, (iy + 10) ; Load count
sbc hl, hl
sbc hl, bc
ld de, (iy + 3) ; Load destination
jr z, .zero_byte_copy ; zero bytes to copy
ld hl, (iy + 6) ; Load source
add hl, bc
ld de, (iy + 4) ; Load destination
jr nc, .zero_byte_copy ; zero bytes to copy
ld hl, (iy + 7) ; Load source
ldir
.zero_byte_copy:
ex de, hl
19 changes: 9 additions & 10 deletions src/libc/memset.src
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
assume adl=1

section .text

public _memset

_memset:
pop iy
pop hl
pop de
pop bc
push bc
push de
push hl
push iy
ld iy, 0
add iy, sp
ld hl, (iy + 3)
ld bc, (iy + 9)
cpi
add hl,bc
add hl, bc
ret c
dec hl
ld (hl),e
ld e, (iy + 6)
ld (hl), e
ret po
push hl
pop de
17 changes: 7 additions & 10 deletions src/libc/strlen.src
Original file line number Diff line number Diff line change
@@ -10,17 +10,14 @@ _strlen := $0000D4
else

_strlen:
pop bc
ex (sp),hl
push bc
xor a,a
ld bc,0
pop iy
ex (sp), hl
xor a, a
ld bc, 0
cpir
or a,a
sbc hl,hl
sbc hl, hl
scf
sbc hl,bc
ret
sbc hl, bc
jp (iy)

end if

1 change: 1 addition & 0 deletions src/libcxx/include/cstring
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ using ::size_t;
using ::memcpy;
using ::memmove;
using ::memset;
using ::bzero;
using ::memcmp;
using ::memchr;
using ::memrchr;
36 changes: 36 additions & 0 deletions test/standalone/asprintf_fprintf/src/main.c
Original file line number Diff line number Diff line change
@@ -49,6 +49,8 @@ size_t T_strlen(const char *s)
int T_strcmp(const char *s1, const char *s2)
__attribute__((nonnull(1, 2)));

void T_bzero(void* s, size_t n);

#else

#define T_memcpy memcpy
@@ -59,6 +61,7 @@ int T_strcmp(const char *s1, const char *s2)
#define T_stpcpy stpcpy
#define T_strlen strlen
#define T_strcmp strcmp
#define T_bzero bzero

#endif

@@ -439,6 +442,35 @@ int mempcpy_test(void) {
return 0;
}

int bzero_test(void) {
char truth[32];
char data[32];
T_memset(data, 0x8F, sizeof(data));
T_memset(&truth[ 0], 0x8F, 8);
T_memset(&truth[ 2], 0x00, 1);
T_memset(&truth[ 8], 0x00, 17);
T_memset(&truth[25], 0x8F, 7);
T_bzero(&data[2], 0);
T_bzero(&data[2], 1);
if (T_strlen(&data[0]) != 2) {
return __LINE__;
}
if (T_strlen(&data[1]) != 1) {
return __LINE__;
}
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) {
printf("cmp: %d\n", cmp);
return __LINE__;
}
return 0;
}

int run_tests(void) {
int ret = 0;
/* boot_asprintf */
@@ -464,6 +496,10 @@ int run_tests(void) {
ret = mempcpy_test();
if (ret != 0) { return ret; }

/* bzero */
ret = bzero_test();
if (ret != 0) { return ret; }

return 0;
}

4 changes: 4 additions & 0 deletions test/standalone/asprintf_fprintf/src/rename.asm
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

public _T_memset, _T_memcpy, _T_memcmp, _T_memccpy, _T_mempcpy
public _T_strlen, _T_strcmp, _T_stpcpy
public _T_bzero

_T_memset := _memset
_T_memcpy := _memcpy
@@ -15,5 +16,8 @@ _T_strlen := _strlen
_T_strcmp := _strcmp
_T_stpcpy := _stpcpy

_T_bzero := _bzero

extern _memset, _memcpy, _memcmp, _memccpy, _mempcpy
extern _strlen, _strcmp, _stpcpy
extern _bzero
Loading