Skip to content

Commit b58fc7e

Browse files
committed
optimized memmove
1 parent 9e250a3 commit b58fc7e

File tree

4 files changed

+138
-5
lines changed

4 files changed

+138
-5
lines changed

src/libc/memmove.src

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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 the no-overlap case
16+
_memmove:
17+
; no-overlap | LDIR | 32F + 12R + 1
18+
; src > dst | LDIR | 32F + 12R + 1
19+
; src < dst | LDDR | 36F + 9R + 2
20+
; src = dst | LDDR | 36F + 9R + 2
21+
; zero size | | 24F + 9R + 2
22+
23+
ld iy, -1
24+
add iy, sp
25+
ld bc, (iy + 10)
26+
sbc hl, hl
27+
add hl, bc
28+
jr nc, .zero
29+
ld hl, (iy + 7)
30+
ld de, (iy + 4)
31+
sbc hl, de
32+
; src <= dst
33+
jr c, .copy_backwards
34+
; .copy_forwards:
35+
add hl, de
36+
inc hl
37+
; src > dst or no-overlap
38+
ldir
39+
.zero:
40+
ld hl, (iy + 4)
41+
ret
42+
.copy_backwards:
43+
; move HL and DE to the end
44+
add hl, de ; HL = src - 1
45+
dec de ; DE = dst - 1
46+
add hl, bc
47+
ex de, hl
48+
add hl, bc
49+
ex de, hl
50+
; HL = src + size - 1
51+
; DE = dst + size - 1
52+
lddr
53+
ex de, hl
54+
inc hl
55+
ret
56+
57+
else
58+
59+
; Optimized for the overlapping case
60+
_memmove:
61+
; no overlap | LDIR | 34F + 12R + 2
62+
; src > dst | LDIR | 34F + 12R + 2
63+
; src < dst | LDDR | 36F + 9R + 2
64+
; src = dst | | 30F + 9R + 2
65+
; zero size | | 24F + 9R + 2
66+
67+
ld iy, -1
68+
add iy, sp
69+
ld bc, (iy + 10)
70+
sbc hl, hl
71+
add hl, bc
72+
jr nc, .zero
73+
ld de, (iy + 4)
74+
ld hl, (iy + 7)
75+
dec de ; DE = dst - 1
76+
sbc hl, de
77+
; src >= dst
78+
jr c, .copy_backwards
79+
; .copy_forwards:
80+
inc de
81+
add hl, de
82+
; src == dst
83+
ret z ; <-- Optional, skips LDIR when src == dst
84+
; src > dst or no-overlap
85+
ldir
86+
.zero:
87+
ld hl, (iy + 4)
88+
ret
89+
90+
.copy_backwards:
91+
; src < dst
92+
; move HL and DE to the end
93+
add hl, de ; HL = src - 1
94+
add hl, bc
95+
ex de, hl
96+
add hl, bc
97+
ex de, hl
98+
; HL = src + size - 1
99+
; DE = dst + size - 1
100+
lddr
101+
ex de, hl
102+
inc hl
103+
ret
104+
105+
end if
106+
107+
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: 28 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,25 @@ 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+
C(NULL_ptr - 1 == (char*)T_memmove(NULL_ptr - 1, NULL_ptr - 1, 0));
597+
598+
return 0;
599+
}
600+
578601
int run_tests(void) {
579602
int ret = 0;
580603
/* boot_asprintf */
@@ -608,10 +631,14 @@ int run_tests(void) {
608631
ret = strncmp_test();
609632
if (ret != 0) { return ret; }
610633

611-
/* strncmp */
634+
/* memrchr */
612635
ret = memrchr_test();
613636
if (ret != 0) { return ret; }
614637

638+
/* memrchr */
639+
ret = memmove_test();
640+
if (ret != 0) { return ret; }
641+
615642
return 0;
616643
}
617644

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)