Skip to content

Commit 222ed8f

Browse files
committed
Optimized strcmp and strncmp. Also added memrchr
1 parent a1de0bb commit 222ed8f

File tree

7 files changed

+192
-9
lines changed

7 files changed

+192
-9
lines changed

src/libc/memrchr.src

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _memrchr
6+
7+
_memrchr:
8+
ld iy, 0
9+
add iy, sp
10+
ld hl, (iy + 3)
11+
ld bc, (iy + 9)
12+
dec bc
13+
add hl, bc
14+
jr c, .ret_zero
15+
inc bc
16+
ld a, (iy + 6)
17+
cpdr
18+
inc hl
19+
ret z ; found match
20+
.ret_zero:
21+
; return NULL
22+
or a, a
23+
sbc hl, hl
24+
ret

src/libc/os.src

-4
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,12 @@ _setjmp := 0000B8h
1616
_strcat := 0000C0h
1717
public _strchr
1818
_strchr := 0000C4h
19-
public _strcmp
20-
_strcmp := 0000C8h
2119
public _strcpy
2220
_strcpy := 0000CCh
2321
public _strcspn
2422
_strcspn := 0000D0h
2523
public _strncat
2624
_strncat := 0000D8h
27-
public _strncmp
28-
_strncmp := 0000DCh
2925
public _strncpy
3026
_strncpy := 0000E0h
3127
public _strpbrk

src/libc/strcmp.src

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _strcmp
6+
7+
if PREFER_OS_LIBC
8+
9+
_strcmp := $0000C8
10+
11+
else
12+
13+
_strcmp:
14+
ld hl, 3
15+
add hl, sp
16+
ld de, (hl)
17+
inc hl
18+
inc hl
19+
inc hl
20+
ld hl, (hl)
21+
.loop:
22+
ld a, (de)
23+
cp a, (hl)
24+
jr nz, .finish
25+
inc hl
26+
inc de
27+
or a, a
28+
jr nz, .loop
29+
.finish:
30+
sbc hl, hl
31+
ld l, a
32+
ret
33+
34+
end if

src/libc/strncmp.src

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _strncmp
6+
7+
if PREFER_OS_LIBC
8+
9+
_strncmp := $0000DC
10+
11+
else
12+
13+
_strncmp:
14+
ld iy, 0
15+
add iy, sp
16+
ld bc, (iy + 9)
17+
sbc hl, hl
18+
adc hl, bc
19+
ld hl, (iy + 6)
20+
ld de, (iy + 3)
21+
call nz, .start ; z means BC was zero
22+
.ret_zero:
23+
sbc hl, hl
24+
ret
25+
.loop:
26+
ret po ; ret_zero
27+
or a, a
28+
ret z ; ret_zero
29+
inc de
30+
.start:
31+
ld a, (de)
32+
cpi
33+
jr z, .loop
34+
.finish:
35+
ld sp, iy ; ret
36+
dec hl
37+
sub a, (hl)
38+
sbc hl, hl
39+
ld l, a
40+
ret
41+
42+
end if

test/standalone/asprintf_fprintf/src/main.c

+85
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* memccpy
2121
*/
2222

23+
#define C(expr) if (!(expr)) { return __LINE__; }
24+
2325
#define SINK (char*)0xE40000
2426

2527
// prevents Clang from replacing function calls with builtins
@@ -40,6 +42,9 @@ void *T_memccpy(void *__restrict dest, const void *__restrict src, int c, size_t
4042
void *T_mempcpy(void *__restrict dest, const void *__restrict src, size_t n)
4143
__attribute__((nonnull(1, 2)));
4244

45+
void *T_memrchr(const void *s, int c, size_t n)
46+
__attribute__((nonnull(1)));
47+
4348
char *T_stpcpy(char *__restrict dest, const char *__restrict src)
4449
__attribute__((nonnull(1, 2)));
4550

@@ -49,6 +54,9 @@ size_t T_strlen(const char *s)
4954
int T_strcmp(const char *s1, const char *s2)
5055
__attribute__((nonnull(1, 2)));
5156

57+
int T_strncmp(const char *s1, const char *s2, size_t n)
58+
__attribute__((nonnull(1, 2)));
59+
5260
void T_bzero(void* s, size_t n);
5361

5462
#else
@@ -58,9 +66,11 @@ void T_bzero(void* s, size_t n);
5866
#define T_memcmp memcmp
5967
#define T_memccpy memccpy
6068
#define T_mempcpy mempcpy
69+
#define T_memrchr memrchr
6170
#define T_stpcpy stpcpy
6271
#define T_strlen strlen
6372
#define T_strcmp strcmp
73+
#define T_strncmp strncmp
6474
#define T_bzero bzero
6575

6676
#endif
@@ -471,6 +481,73 @@ int bzero_test(void) {
471481
return 0;
472482
}
473483

484+
int strncmp_test(void) {
485+
const char* str0 = "Hello World!";
486+
const char* str1 = "Hello!";
487+
const char* str2 = "Hello";
488+
const char* str3 = "Hello there";
489+
const char* str4 = "Hello, everybody!";
490+
const char* str5 = "Hello, somebody!";
491+
492+
C(T_strcmp(SINK, SINK) == 0);
493+
C(T_strcmp("C", "C") == 0);
494+
C(T_strcmp("A", "C") < 0);
495+
C(T_strcmp("C", "A") > 0);
496+
C(T_strcmp("CD", "CD") == 0);
497+
C(T_strcmp("AB", "CD") < 0);
498+
C(T_strcmp("CD", "AB") > 0);
499+
C(T_strcmp("FE", "FG") < 0);
500+
C(T_strcmp("FG", "FE") > 0);
501+
C(T_strcmp(str0, str1) < 0);
502+
C(T_strcmp(str0, str2) > 0);
503+
C(T_strcmp(str0, str3) < 0);
504+
C(T_strcmp(str4 + 12, str5 + 11) == 0);
505+
506+
C(T_strncmp(SINK, SINK, 0) == 0);
507+
C(T_strncmp(SINK, SINK, 1) == 0);
508+
C(T_strncmp(SINK, SINK, 2) == 0);
509+
C(T_strncmp("C", "C", 1) == 0);
510+
C(T_strncmp("A", "C", 1) < 0);
511+
C(T_strncmp("C", "A", 1) > 0);
512+
C(T_strncmp("CD", "CD", 2) == 0);
513+
C(T_strncmp("AB", "CD", 2) < 0);
514+
C(T_strncmp("CD", "AB", 2) > 0);
515+
C(T_strncmp("FE", "FG", 2) < 0);
516+
C(T_strncmp("FG", "FE", 2) > 0);
517+
C(T_strncmp(str0, str1, 5) == 0);
518+
C(T_strncmp(str0, str2, 10) > 0);
519+
C(T_strncmp(str0, str3, 10) < 0);
520+
C(T_strncmp(str4 + 12, str5 + 11, 5) == 0);
521+
522+
return 0;
523+
}
524+
525+
int memrchr_test(void) {
526+
C(T_memrchr(SINK, 0x00, 0) == NULL);
527+
C(T_memrchr(SINK, 0x00, 1) == SINK);
528+
C(T_memrchr(SINK, 0xFF, 1) == NULL);
529+
C(T_memrchr(SINK, 0x00, 2) == SINK + 2 - 1);
530+
C(T_memrchr(SINK, 0x00, 500) == SINK + 500 - 1);
531+
const char test0[] = "GABCDEFABCDEF";
532+
char const * const test = &test0[1];
533+
534+
const size_t test_size = sizeof(test0) - 1;
535+
const size_t test_strlen = sizeof(test0) - 2;
536+
537+
C(T_memrchr(test, '\0', test_size) == &test[12]);
538+
C(T_memrchr(test, 'A', test_strlen) == &test[6]);
539+
C(T_memrchr(&test[7], 'A', 5) == NULL);
540+
C(T_memrchr(&test[6], 'A', 6) == &test[6]);
541+
C(T_memrchr(&test[5], 'A', 7) == &test[6]);
542+
C(T_memrchr(&test[7], 'B', 5) == &test[7]);
543+
C(T_memrchr(&test[8], 'C', 1) == &test[8]);
544+
C(T_memrchr(&test[8], 'C', 8) == &test[8]);
545+
C(T_memrchr(test, 'G', test_strlen) == NULL);
546+
C(T_memrchr(test, 'G', test_size) == NULL);
547+
C(T_memrchr(test0, 'G', sizeof(test0)) == test0);
548+
return 0;
549+
}
550+
474551
int run_tests(void) {
475552
int ret = 0;
476553
/* boot_asprintf */
@@ -500,6 +577,14 @@ int run_tests(void) {
500577
ret = bzero_test();
501578
if (ret != 0) { return ret; }
502579

580+
/* strncmp */
581+
ret = strncmp_test();
582+
if (ret != 0) { return ret; }
583+
584+
/* strncmp */
585+
ret = memrchr_test();
586+
if (ret != 0) { return ret; }
587+
503588
return 0;
504589
}
505590

test/standalone/asprintf_fprintf/src/rename.asm

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,24 @@
22

33
section .text
44

5-
public _T_memset, _T_memcpy, _T_memcmp, _T_memccpy, _T_mempcpy
6-
public _T_strlen, _T_strcmp, _T_stpcpy
5+
public _T_memset, _T_memcpy, _T_memcmp, _T_memccpy, _T_mempcpy, _T_memrchr
6+
public _T_strlen, _T_strcmp, _T_strncmp, _T_stpcpy
77
public _T_bzero
88

99
_T_memset := _memset
1010
_T_memcpy := _memcpy
1111
_T_memcmp := _memcmp
1212
_T_memccpy := _memccpy
1313
_T_mempcpy := _mempcpy
14+
_T_memrchr := _memrchr
1415

1516
_T_strlen := _strlen
1617
_T_strcmp := _strcmp
18+
_T_strncmp := _strncmp
1719
_T_stpcpy := _stpcpy
1820

1921
_T_bzero := _bzero
2022

21-
extern _memset, _memcpy, _memcmp, _memccpy, _mempcpy
22-
extern _strlen, _strcmp, _stpcpy
23+
extern _memset, _memcpy, _memcmp, _memccpy, _mempcpy, _memrchr
24+
extern _strlen, _strcmp, _strncmp, _stpcpy
2325
extern _bzero

test/standalone/strlcpy/makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Makefile Options
33
# ----------------------------
44

5-
NAME = STRLCPY
5+
NAME = DEMO
66
ICON = icon.png
77
DESCRIPTION = "strlcpy test"
88
COMPRESSED = NO

0 commit comments

Comments
 (0)