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
2 changes: 1 addition & 1 deletion src/libc/include/wchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ size_t wcslen(const wchar_t *s)
__attribute__((nonnull(1)));

size_t wcsnlen(const wchar_t *s, size_t maxlen)
__attribute__((nonnull(1)));
__NOEXCEPT __attribute__((nonnull(1))) __attribute__((__pure__));

int wcscmp(const wchar_t *s1, const wchar_t *s2)
__attribute__((nonnull(1, 2)));
Expand Down
23 changes: 23 additions & 0 deletions src/libc/wcslen.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
assume adl=1

section .text

public _wcslen

; size_t wcslen(const wchar_t *str)
_wcslen:
pop bc
ex (sp), hl
push bc
ld bc, 1
xor a, a
dec hl
.loop:
inc hl
cpi
jr nz, .loop
cp a, (hl)
jr nz, .loop
sbc hl, hl
sbc hl, bc
ret
44 changes: 44 additions & 0 deletions src/libc/wcsnlen.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
assume adl=1

section .text

public _wcsnlen

; size_t wcsnlen(const wchar_t *str, size_t maxlen)
_wcsnlen:
ld hl, 6
add hl, sp
ld bc, (hl)
dec hl
dec hl
dec hl
ld de, (hl)
xor a, a
sbc hl, hl
adc hl, bc
ret z
ex de, hl
call .loop_start
ex de, hl
; return maxlen unless str[maxlen - 1] == L'\0'
ret nz ; low byte was non-zero
ld a, (de)
cp a, c ; cp a, 0
ret nz ; high byte was non-zero
dec hl
; ret ; We can use the RET PO below since overflow won't be set
.loop_lo:
ret po
.loop_hi:
inc hl
.loop_start:
cpi
jr nz, .loop_lo
ret po
cp a, (hl)
jr nz, .loop_hi
ex de, hl
pop de ; reset SP
scf
sbc hl, bc
ret
39 changes: 39 additions & 0 deletions src/libc/wmemchr.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
assume adl=1

section .text

public _wmemchr

; wchar_t *wmemchr(const wchar_t *ptr, int ch, size_t count)
_wmemchr:
ld iy, 0
add iy, sp
ld hl, (iy + 9)
adc hl, hl ; count *= 2
ret z ; return NULL
push hl
pop bc ; BC = count * 2
ld hl, (iy + 3)
ld de, (iy + 6) ; E = lower byte, D = upper byte
call .loop_start
.ret_null:
or a, a
sbc hl, hl
ret

.loop_start:
.no_match:
ld a, e
.loop:
cpir
ret po ; return NULL
; repeat until BC is odd
bit 0, c
jr z, .loop
; lower byte matches, now check the upper byte
ld a, d
xor a, (hl)
jr nz, .no_match
pop bc ; reset SP
dec hl
ret
46 changes: 46 additions & 0 deletions src/libc/wmemcmp.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
assume adl=1

section .text

public _wmemcmp

; int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
_wmemcmp:
ld iy, 0
add iy, sp
ld bc, (iy + 9)
sbc hl, hl
adc hl, bc ; count *= 2
ret z ; return 0
ld de, (iy + 3)
ld hl, (iy + 6)
.loop:
ld a, (de)
xor a, (hl)
inc hl
inc de
ld a, (de)
jr nz, .low_diff
cpi
jr nz, .high_diff
inc de
jp pe, .loop
sbc hl, hl
ret

.high_diff:
dec hl
.low_diff:
; compare high bytes
sub a, (hl) ; s1 - s2
jr nz, .skip_low_check
; compare low bytes
dec de
ld a, (de)
dec hl
sub a, (hl) ; s1 - s2
.skip_low_check:
sbc hl, hl
; A is non-zero here
ld l, a
ret
32 changes: 32 additions & 0 deletions src/libc/wmemcpy.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
assume adl=1

section .text

public _wmemcpy

; CC: !count ? 19*r(PC) + 9*r(SPL) + 3*w(SPL) + 1
; : 25*r(PC) + 18*r(SPL) + 12*w(SPL) + count*(r(src) + w(dest) + 1)
; C: wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
_wmemcpy:
; C: size_t count2 = count * sizeof(wchar_t);
ld hl, 9
add hl, sp
ld hl, (hl) ; hl = count
adc hl, hl ; hl = count * 2
; = count2
; C: if (count2) {
pop iy ; iy = ret
jr z, .zero
; C: __ldir(src, dest, count2);
pop de ; de = dest
ex (sp), hl ; hl = src
pop bc ; bc = count2
push bc
push de
ldir
; C: }
.zero:
; C: return dest;
ex (sp), hl
jp (iy)
; C: }
16 changes: 16 additions & 0 deletions src/libc/wmemmove.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
assume adl=1

section .text

public _wmemmove

; wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count)
_wmemmove:
ld hl, 9
add hl, sp
ld iy, (hl)
add iy, iy ; count *= 2
ld (hl), iy
jp _memmove

extern _memmove
40 changes: 40 additions & 0 deletions src/libc/wmemset.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
assume adl=1

section .text

public _wmemset

; wchar_t *wmemset(wchar_t *dst, wchar_t ch, size_t count)
_wmemset:
pop iy, hl, de, bc
push bc, de, hl, iy
; BC = count
; DE = ch
; HL = dst

; count *= sizeof(wchar_t)
cpi ; hl++ bc--
add hl, bc ; HL = (dst + 1) + (count - 1) = dst + count
ret c ; bc is zero
add hl, bc ; HL = dst + count + (count - 1) = dst + 2 * count - 1

; hl += (count - 1) * 2 + 1
; count -= 2
ld (hl), d ; upper 8 bits
dec hl
ld (hl), e ; lower 8 bits
ret po ; only one element needs to be written

; write multiple elements
push hl
pop de
inc hl
dec de

push bc
; use lddr twice
lddr
pop bc
lddr
dec hl
ret
40 changes: 40 additions & 0 deletions test/standalone/wide_char/autotest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"transfer_files": [
"bin/DEMO.8xp"
],
"target": {
"name": "DEMO",
"isASM": true
},
"sequence": [
"action|launch",
"delay|2000",
"hashWait|1",
"key|enter",
"delay|300",
"hashWait|2"
],
"hashes": {
"1": {
"description": "All tests passed",
"timeout": 5000,
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"38E2AD5A"
]
},
"2": {
"description": "Exit",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"FFAF89BA",
"101734A5",
"9DA19F44",
"A32840C8",
"349F4775"
]
}
}
}
20 changes: 20 additions & 0 deletions test/standalone/wide_char/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ----------------------------
# Makefile Options
# ----------------------------

NAME = DEMO
ICON = icon.png
DESCRIPTION = "CE C Toolchain Demo"
COMPRESSED = NO
ARCHIVED = NO

CFLAGS = -Wall -Wextra -ffreestanding -Wformat=2 -Wshadow -Oz
CXXFLAGS = -Wall -Wextra -ffreestanding -Wformat=2 -Wshadow -Oz

PREFER_OS_LIBC = NO

HAS_PRINTF = YES

# ----------------------------

include $(shell cedev-config --makefile)
Loading
Loading