Skip to content

Commit 827a5b6

Browse files
committed
added C95 wmem*** functions and wsc(n)len
1 parent 9e250a3 commit 827a5b6

File tree

12 files changed

+594
-1
lines changed

12 files changed

+594
-1
lines changed

src/libc/include/wchar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ size_t wcslen(const wchar_t *s)
7575
__attribute__((nonnull(1)));
7676

7777
size_t wcsnlen(const wchar_t *s, size_t maxlen)
78-
__attribute__((nonnull(1)));
78+
__NOEXCEPT __attribute__((nonnull(1))) __attribute__((__pure__));
7979

8080
int wcscmp(const wchar_t *s1, const wchar_t *s2)
8181
__attribute__((nonnull(1, 2)));

src/libc/wcslen.src

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wcslen
6+
7+
; size_t wcslen(const wchar_t *str)
8+
_wcslen:
9+
pop bc
10+
ex (sp), hl
11+
push bc
12+
ld bc, 1
13+
xor a, a
14+
dec hl
15+
.loop:
16+
inc hl
17+
cpi
18+
jr nz, .loop
19+
cp a, (hl)
20+
jr nz, .loop
21+
sbc hl, hl
22+
sbc hl, bc
23+
ret

src/libc/wcsnlen.src

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wcsnlen
6+
7+
; size_t wcsnlen(const wchar_t *str, size_t maxlen)
8+
_wcsnlen:
9+
ld hl, 6
10+
add hl, sp
11+
ld bc, (hl)
12+
dec hl
13+
dec hl
14+
dec hl
15+
ld de, (hl)
16+
xor a, a
17+
sbc hl, hl
18+
adc hl, bc
19+
ret z
20+
ex de, hl
21+
call .loop_start
22+
ex de, hl
23+
; return maxlen unless str[maxlen - 1] == L'\0'
24+
ret nz ; low byte was non-zero
25+
ld a, (de)
26+
cp a, c ; cp a, 0
27+
ret nz ; high byte was non-zero
28+
dec hl
29+
; ret ; We can use the RET PO below since overflow won't be set
30+
.loop_lo:
31+
ret po
32+
.loop_hi:
33+
inc hl
34+
.loop_start:
35+
cpi
36+
jr nz, .loop_lo
37+
ret po
38+
cp a, (hl)
39+
jr nz, .loop_hi
40+
ex de, hl
41+
pop de ; reset SP
42+
scf
43+
sbc hl, bc
44+
ret

src/libc/wmemchr.src

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wmemchr
6+
7+
; wchar_t *wmemchr(const wchar_t *ptr, int ch, size_t count)
8+
_wmemchr:
9+
ld iy, 0
10+
add iy, sp
11+
ld hl, (iy + 9)
12+
adc hl, hl ; count *= 2
13+
ret z ; return NULL
14+
push hl
15+
pop bc ; BC = count * 2
16+
ld hl, (iy + 3)
17+
ld de, (iy + 6) ; E = lower byte, D = upper byte
18+
call .loop_start
19+
.ret_null:
20+
or a, a
21+
sbc hl, hl
22+
ret
23+
24+
.loop_start:
25+
.no_match:
26+
ld a, e
27+
.loop:
28+
cpir
29+
ret po ; return NULL
30+
; repeat until BC is odd
31+
bit 0, c
32+
jr z, .loop
33+
; lower byte matches, now check the upper byte
34+
ld a, d
35+
xor a, (hl)
36+
jr nz, .no_match
37+
pop bc ; reset SP
38+
dec hl
39+
ret

src/libc/wmemcmp.src

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wmemcmp
6+
7+
; int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
8+
_wmemcmp:
9+
ld iy, 0
10+
add iy, sp
11+
ld bc, (iy + 9)
12+
sbc hl, hl
13+
adc hl, bc ; count *= 2
14+
ret z ; return 0
15+
ld de, (iy + 3)
16+
ld hl, (iy + 6)
17+
.loop:
18+
ld a, (de)
19+
xor a, (hl)
20+
inc hl
21+
inc de
22+
ld a, (de)
23+
jr nz, .low_diff
24+
cpi
25+
jr nz, .high_diff
26+
inc de
27+
jp pe, .loop
28+
sbc hl, hl
29+
ret
30+
31+
.high_diff:
32+
dec hl
33+
.low_diff:
34+
; compare high bytes
35+
sub a, (hl) ; s1 - s2
36+
jr nz, .skip_low_check
37+
; compare low bytes
38+
dec de
39+
ld a, (de)
40+
dec hl
41+
sub a, (hl) ; s1 - s2
42+
.skip_low_check:
43+
sbc hl, hl
44+
; A is non-zero here
45+
ld l, a
46+
ret

src/libc/wmemcpy.src

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wmemcpy
6+
7+
; CC: !count ? 19*r(PC) + 9*r(SPL) + 3*w(SPL) + 1
8+
; : 25*r(PC) + 18*r(SPL) + 12*w(SPL) + count*(r(src) + w(dest) + 1)
9+
; C: wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
10+
_wmemcpy:
11+
; C: size_t count2 = count * sizeof(wchar_t);
12+
ld hl, 9
13+
add hl, sp
14+
ld hl, (hl) ; hl = count
15+
adc hl, hl ; hl = count * 2
16+
; = count2
17+
; C: if (count2) {
18+
pop iy ; iy = ret
19+
jr z, .zero
20+
; C: __ldir(src, dest, count2);
21+
pop de ; de = dest
22+
ex (sp), hl ; hl = src
23+
pop bc ; bc = count2
24+
push bc
25+
push de
26+
ldir
27+
; C: }
28+
.zero:
29+
; C: return dest;
30+
ex (sp), hl
31+
jp (iy)
32+
; C: }

src/libc/wmemmove.src

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wmemmove
6+
7+
; wchar_t *wmemmove(wchar_t *dest, const wchar_t *src, size_t count)
8+
_wmemmove:
9+
ld hl, 9
10+
add hl, sp
11+
ld iy, (hl)
12+
add iy, iy ; count *= 2
13+
ld (hl), iy
14+
jp _memmove
15+
16+
extern _memmove

src/libc/wmemset.src

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _wmemset
6+
7+
; wchar_t *wmemset(wchar_t *dst, wchar_t ch, size_t count)
8+
_wmemset:
9+
pop iy, hl, de, bc
10+
push bc, de, hl, iy
11+
; BC = count
12+
; DE = ch
13+
; HL = dst
14+
15+
; count *= sizeof(wchar_t)
16+
cpi ; hl++ bc--
17+
add hl, bc ; HL = (dst + 1) + (count - 1) = dst + count
18+
ret c ; bc is zero
19+
add hl, bc ; HL = dst + count + (count - 1) = dst + 2 * count - 1
20+
21+
; hl += (count - 1) * 2 + 1
22+
; count -= 2
23+
ld (hl), d ; upper 8 bits
24+
dec hl
25+
ld (hl), e ; lower 8 bits
26+
ret po ; only one element needs to be written
27+
28+
; write multiple elements
29+
push hl
30+
pop de
31+
inc hl
32+
dec de
33+
34+
push bc
35+
; use lddr twice
36+
lddr
37+
pop bc
38+
lddr
39+
dec hl
40+
ret
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"transfer_files": [
3+
"bin/DEMO.8xp"
4+
],
5+
"target": {
6+
"name": "DEMO",
7+
"isASM": true
8+
},
9+
"sequence": [
10+
"action|launch",
11+
"delay|2000",
12+
"hashWait|1",
13+
"key|enter",
14+
"delay|300",
15+
"hashWait|2"
16+
],
17+
"hashes": {
18+
"1": {
19+
"description": "All tests passed",
20+
"timeout": 5000,
21+
"start": "vram_start",
22+
"size": "vram_16_size",
23+
"expected_CRCs": [
24+
"38E2AD5A"
25+
]
26+
},
27+
"2": {
28+
"description": "Exit",
29+
"start": "vram_start",
30+
"size": "vram_16_size",
31+
"expected_CRCs": [
32+
"FFAF89BA",
33+
"101734A5",
34+
"9DA19F44",
35+
"A32840C8",
36+
"349F4775"
37+
]
38+
}
39+
}
40+
}

test/standalone/wide_char/makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ----------------------------
2+
# Makefile Options
3+
# ----------------------------
4+
5+
NAME = DEMO
6+
ICON = icon.png
7+
DESCRIPTION = "CE C Toolchain Demo"
8+
COMPRESSED = NO
9+
ARCHIVED = NO
10+
11+
CFLAGS = -Wall -Wextra -ffreestanding -Wformat=2 -Wshadow -Oz
12+
CXXFLAGS = -Wall -Wextra -ffreestanding -Wformat=2 -Wshadow -Oz
13+
14+
PREFER_OS_LIBC = NO
15+
16+
HAS_PRINTF = YES
17+
18+
# ----------------------------
19+
20+
include $(shell cedev-config --makefile)

0 commit comments

Comments
 (0)