Skip to content

Commit 4d9dce7

Browse files
committed
optimized memmove
1 parent 9e250a3 commit 4d9dce7

File tree

4 files changed

+132
-5
lines changed

4 files changed

+132
-5
lines changed

src/libc/memmove.src

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _memmove
6+
7+
if PREFER_OS_LIBC
8+
9+
_memmove := 0000A8h
10+
11+
else
12+
13+
if 1
14+
15+
; Optimized for when src != dst
16+
_memmove:
17+
; src > dst | LDIR | 32F + 15R + 1
18+
; src < dst | LDDR | 35F + 12R + 2
19+
; src = dst | LDDR | 35F + 12R + 2
20+
; zero size | | 24F + 12R + 2
21+
22+
ld iy, -1
23+
add iy, sp
24+
ld bc, (iy + 10)
25+
sbc hl, hl
26+
add hl, bc
27+
jr nc, .zero
28+
ld hl, (iy + 7)
29+
ld de, (iy + 4)
30+
sbc hl, de
31+
; src <= dst
32+
jr c, .copy_backwards
33+
; .copy_forwards:
34+
add hl, de
35+
inc hl
36+
; src > dst
37+
ldir
38+
.zero:
39+
ld hl, (iy + 4)
40+
ret
41+
.copy_backwards:
42+
; move HL and DE to the end
43+
ex de, hl
44+
add hl, bc
45+
ex de, hl ; HL = src - dst - 1, DE = dst + size
46+
add hl, de ; HL = src + size - 1
47+
dec de ; DE = dst + size - 1
48+
lddr
49+
ex de, hl
50+
inc hl
51+
ret
52+
53+
else
54+
55+
; Optimized for when src = dst
56+
_memmove:
57+
; src > dst | LDIR | 34F + 15R + 2
58+
; src < dst | LDDR | 36F + 12R + 2
59+
; src = dst | | 30F + 12R + 2
60+
; zero size | | 24F + 12R + 2
61+
62+
ld iy, -1
63+
add iy, sp
64+
ld bc, (iy + 10)
65+
sbc hl, hl
66+
add hl, bc
67+
jr nc, .zero
68+
ld de, (iy + 4)
69+
ld hl, (iy + 7)
70+
dec de ; DE = dst - 1
71+
sbc hl, de
72+
; src >= dst
73+
jr c, .copy_backwards
74+
; .copy_forwards:
75+
inc de
76+
add hl, de
77+
; src == dst
78+
ret z ; <-- Optional, skips LDIR when src == dst
79+
; src > dst or no-overlap
80+
ldir
81+
.zero:
82+
ld hl, (iy + 4)
83+
ret
84+
85+
.copy_backwards:
86+
; src < dst
87+
; move HL and DE to the end
88+
add hl, de ; HL = src - 1
89+
add hl, bc
90+
ex de, hl
91+
add hl, bc
92+
ex de, hl
93+
; HL = src + size - 1
94+
; DE = dst + size - 1
95+
lddr
96+
ex de, hl
97+
inc hl
98+
ret
99+
100+
end if
101+
102+
end if

src/libc/os.src

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ _longjmp := 000098h
88
_memchr := 00009Ch
99
public _memcmp
1010
_memcmp := 0000A0h
11-
public _memmove
12-
_memmove := 0000A8h
1311
public _setjmp
1412
_setjmp := 0000B8h
1513
public _strcat

test/standalone/asprintf_fprintf/src/main.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ extern void* NULL_ptr;
3333
void *T_memcpy(void *__restrict dest, const void *__restrict src, size_t n)
3434
__attribute__((nonnull(1, 2)));
3535

36+
void *T_memmove(void *dest, const void *src, size_t n)
37+
__attribute__((nonnull(1, 2)));
38+
3639
void *T_memset(void *s, int c, size_t n)
3740
__attribute__((nonnull(1)));
3841

@@ -65,6 +68,7 @@ void T_bzero(void* s, size_t n);
6568
#else
6669

6770
#define T_memcpy memcpy
71+
#define T_memmove memmove
6872
#define T_memset memset
6973
#define T_memcmp memcmp
7074
#define T_memccpy memccpy
@@ -575,6 +579,24 @@ int memrchr_test(void) {
575579
return 0;
576580
}
577581

582+
int memmove_test(void) {
583+
char move_str[] = "0123456789";
584+
const char truth_str[] = "9344545689";
585+
C(move_str + 5 == (char*)T_memmove(move_str + 5, move_str + 4, 3));
586+
C(move_str + 3 == (char*)T_memmove(move_str + 3, move_str + 3, 0));
587+
C(move_str + 1 == (char*)T_memmove(move_str + 1, move_str + 3, 4));
588+
C(move_str + 2 == (char*)T_memmove(move_str + 2, move_str + 2, 6));
589+
C(move_str + 9 == (char*)T_memmove(move_str + 9, move_str + 0, 0));
590+
C(move_str + 0 == (char*)T_memmove(move_str + 0, move_str + 9, 1));
591+
C(strcmp(move_str, truth_str) == 0);
592+
593+
C(NULL_ptr - 0 == (char*)T_memmove(NULL_ptr - 0, NULL_ptr - 0, 0));
594+
C(NULL_ptr - 0 == (char*)T_memmove(NULL_ptr - 0, NULL_ptr - 1, 0));
595+
C(NULL_ptr - 1 == (char*)T_memmove(NULL_ptr - 1, NULL_ptr - 0, 0));
596+
597+
return 0;
598+
}
599+
578600
int run_tests(void) {
579601
int ret = 0;
580602
/* boot_asprintf */
@@ -608,10 +630,14 @@ int run_tests(void) {
608630
ret = strncmp_test();
609631
if (ret != 0) { return ret; }
610632

611-
/* strncmp */
633+
/* memrchr */
612634
ret = memrchr_test();
613635
if (ret != 0) { return ret; }
614636

637+
/* memrchr */
638+
ret = memmove_test();
639+
if (ret != 0) { return ret; }
640+
615641
return 0;
616642
}
617643

test/standalone/asprintf_fprintf/src/rename.asm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
section .text
44

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

99
_T_memset := _memset
1010
_T_memcpy := _memcpy
11+
_T_memmove := _memmove
1112
_T_memcmp := _memcmp
1213
_T_memccpy := _memccpy
1314
_T_mempcpy := _mempcpy
@@ -26,6 +27,6 @@ _T_bzero := _bzero
2627
_NULL_ptr:
2728
db $00, $00, $00
2829

29-
extern _memset, _memcpy, _memcmp, _memccpy, _mempcpy, _memrchr
30+
extern _memset, _memcpy, _memmove, _memcmp, _memccpy, _mempcpy, _memrchr
3031
extern _strlen, _strcmp, _strncmp, _stpcpy
3132
extern _bzero

0 commit comments

Comments
 (0)