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
3 changes: 3 additions & 0 deletions src/libc/include/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ char *strcasestr(const char *haystack, const char *needle)
char *strtok(char *__restrict s, const char *__restrict delim)
__attribute__((nonnull(2)));

char *strtok_r(char *__restrict s, const char *__restrict delim, char **__restrict save_ptr)
__attribute__((nonnull(2, 3)));

char *strdup(const char *s)
__attribute__((__malloc__)) __attribute__((nonnull(1)));

Expand Down
32 changes: 32 additions & 0 deletions src/libc/memchr.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.assume adl=1

.section .text

.global _memchr
.type _memchr, @function

.ifdef PREFER_CE_LIBC

.set _memchr, 0x00009C

.else

_memchr:
ld iy, -1
add iy, sp
ld bc, (iy + 10)
sbc hl, hl
add hl, bc
jr nc, .L.ret_zero
ld hl, (iy + 4)
ld a, (iy + 7)
cpir
dec hl
ret z ; found match
or a, a
.L.ret_zero:
; return NULL
sbc hl, hl
ret

.endif
42 changes: 42 additions & 0 deletions src/libc/memcmp.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.assume adl=1

.section .text

.global _memcmp
.type _memcmp, @function

.ifdef PREFER_CE_LIBC

.set _memcmp, 0x0000A0

.else

_memcmp:
ld iy, 0
add iy, sp
ld bc, (iy + 9)
sbc hl, hl
adc hl, bc
ld hl, (iy + 6)
ld de, (iy + 3)
call nz, .L.start ; z means BC was zero
.L.ret_zero:
sbc hl, hl
ret

.L.loop:
ret po
inc de
.L.start:
ld a, (de)
cpi
jr z, .L.loop
.L.finish:
ld sp, iy ; ret
dec hl
sub a, (hl)
sbc hl, hl
ld l, a
ret

.endif
27 changes: 0 additions & 27 deletions src/libc/os.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,6 @@
.global _longjmp
.type _longjmp, @function
.set _longjmp, 0x000098
.global _memchr
.type _memchr, @function
.set _memchr, 0x00009C
.global _memcmp
.type _memcmp, @function
.set _memcmp, 0x0000A0
.global _setjmp
.type _setjmp, @function
.set _setjmp, 0x0000B8
.global _strcat
.type _strcat, @function
.set _strcat, 0x0000C0
.global _strchr
.type _strchr, @function
.set _strchr, 0x0000C4
.global _strcpy
.type _strcpy, @function
.set _strcpy, 0x0000CC
.global _strncat
.type _strncat, @function
.set _strncat, 0x0000D8
.global _strncpy
.type _strncpy, @function
.set _strncpy, 0x0000E0
.global _strstr
.type _strstr, @function
.set _strstr, 0x0000F0
.global _strtok
.type _strtok, @function
.set _strtok, 0x0000F4
46 changes: 46 additions & 0 deletions src/libc/strcat.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.assume adl=1

.section .text

.global _strcat
.type _strcat, @function

.ifdef PREFER_CE_LIBC

.set _strcat, 0x0000C0

.else

_strcat:
pop iy
pop de
ex (sp), hl ; src
push de ; dst

; move to the end of src
xor a, a
ld bc, 0
push hl ; src
cpir
sbc hl, hl
sbc hl, bc ; carry is set
ex (sp), hl
ex de, hl
; move to the end of dst

; not needed unless the strlen(dst) + strlen(src) > 16777215 bytes,
; which would imply that the resulting string would not fit into memory
; ld bc, 0
cpir
dec hl

pop bc
ex de, hl
; DE = dst + strlen(dst)
; HL = src
; BC = strlen(src) + 1
ldir
ex (sp), hl ; return value
jp (iy)

.endif
42 changes: 42 additions & 0 deletions src/libc/strchr.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.assume adl=1

.section .text

.global _strchr
.type _strchr, @function

.ifdef PREFER_CE_LIBC

.set _strchr, 0x0000C4

.else

_strchr:
pop bc
pop hl
pop de
push de
push hl
push bc
xor a, a
ld bc, 0
cpir
ld a, e
ex de, hl
; calculate strlen(str) + 1
sbc hl, hl
sbc hl, bc
ex de, hl
; rewind HL to the beginning of str
add hl, bc
push de
pop bc
cpir
dec hl
ret z ; found match
; return NULL
or a, a
sbc hl, hl
ret

.endif
37 changes: 37 additions & 0 deletions src/libc/strcpy.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.assume adl=1

.section .text

.global _strcpy
.type _strcpy, @function

.ifdef PREFER_CE_LIBC

.set _strcpy, 0x0000CC

.else

_strcpy:
pop iy
pop de
ex (sp), hl ; src
push de ; dst

xor a, a
ld bc, 0
; move to the end of src
push hl
cpir
sbc hl, hl
sbc hl, bc
ex (sp), hl
pop bc

; DE = dst
; HL = src
; BC = strlen(src) + 1
ldir
ex (sp), hl ; return dst
jp (iy)

.endif
51 changes: 51 additions & 0 deletions src/libc/strncat.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.assume adl=1

.section .text

.global _strncat
.type _strncat, @function

.ifdef PREFER_OS_LIBC

.set _strncat, 0x0000D8

.else

_strncat:
ld iy, 0
lea bc, iy + 0
add iy, sp
xor a, a
ld hl, (iy + 3) ; dst
cpir
dec hl
push hl ; dst + strlen(dst)

; inlined strnlen
ld bc, (iy + 9) ; max_size
sbc hl, hl
sbc hl, bc
jr z, .L.zero_size
add hl, bc
ld de, (iy + 6) ; src
sbc hl, de
ex de, hl
cpir
jr z, .L.finish_strnlen
inc hl
.L.finish_strnlen:
xor a, a
adc hl, de
.L.zero_size:
pop de ; dst + strlen(dst)
jr z, .L.no_room
push hl
pop bc
ld hl, (iy + 6) ; src
ldir
ld (de), a ; nul terminate
.L.no_room:
ld hl, (iy + 3)
ret

.endif
69 changes: 69 additions & 0 deletions src/libc/strncpy.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
.assume adl=1

.section .text

.global _strncpy
.type _strncpy, @function

.ifdef PREFER_CE_LIBC

.set _strncpy, 0x0000E0

.else

; currently this just copies the stpncpy implementation, and could probably be optimized further
_strncpy:
ld iy, 0
add iy, sp
ld bc, (iy + 9) ; max_len

; inlined strnlen
xor a, a
sbc hl, hl
sbc hl, bc
jr z, .L.zero_size
add hl, bc
ld de, (iy + 6) ; src
sbc hl, de
ex de, hl
cpir
jr z, .L.finish_strnlen
inc hl
.L.finish_strnlen:
xor a, a
adc hl, de
.L.zero_size:

; copy strnlen bytes from src
push hl
ld de, (iy + 3) ; dst
jr z, .L.zero_byte_copy
ld hl, (iy + 6) ; src
pop bc
push bc
ldir
.L.zero_byte_copy:
pop bc

; zero pad the remainder
ld hl, (iy + 9) ; max_len
scf
sbc hl, bc ; clear_size - 1 = max_len - src_len - 1
ex de, hl
jr c, .L.finish ; clear_size <= 0 (or max_len <= src_len)
; HL = dst + src_len
; DE = clear_size - 1
add hl, de
ld (hl), a
jr z, .L.finish ; clear_size == 1
push de
pop bc
push hl
pop de
dec de
lddr
.L.finish:
ld hl, (iy + 3)
ret

.endif
Loading
Loading