xref: /haiku/src/system/libroot/posix/string/memmove.c (revision 9642f7705b27e5c270c15fa526d14e1848c2c27d)
1 /*
2  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
3  * Distributed under the terms of the NewOS License.
4  */
5 
6 
7 #include <sys/types.h>
8 #include <string.h>
9 
10 #if !_ASM_MEMCPY
11 
12 typedef int word;
13 
14 #define lsize sizeof(word)
15 #define lmask (lsize - 1)
16 
17 
18 void*
memmove(void * dest,void const * src,size_t count)19 memmove(void* dest, void const* src, size_t count)
20 {
21 	char* d = (char*)dest;
22 	const char* s = (const char*)src;
23 	int len;
24 
25 	if (count == 0 || dest == src)
26 		return dest;
27 
28 	if ((long)d < (long)s) {
29 		if (((long)d | (long)s) & lmask) {
30 			// src and/or dest do not align on word boundary
31 			if ((((long)d ^ (long)s) & lmask) || (count < lsize))
32 				len = count; // copy the rest of the buffer with the byte mover
33 			else
34 				len = lsize - ((long)d & lmask); // move the ptrs up to a word boundary
35 
36 			count -= len;
37 			for (; len > 0; len--)
38 				*d++ = *s++;
39 		}
40 		for (len = count / lsize; len > 0; len--) {
41 			*(word*)d = *(word*)s;
42 			d += lsize;
43 			s += lsize;
44 		}
45 		for (len = count & lmask; len > 0; len--)
46 			*d++ = *s++;
47 	} else {
48 		d += count;
49 		s += count;
50 		if (((long)d | (long)s) & lmask) {
51 			// src and/or dest do not align on word boundary
52 			if ((((long)d ^ (long)s) & lmask) || (count <= lsize))
53 				len = count;
54 			else
55 				len = ((long)d & lmask);
56 
57 			count -= len;
58 			for (; len > 0; len--)
59 				*--d = *--s;
60 		}
61 		for (len = count / lsize; len > 0; len--) {
62 			d -= lsize;
63 			s -= lsize;
64 			*(word*)d = *(word*)s;
65 		}
66 		for (len = count & lmask; len > 0; len--)
67 			*--d = *--s;
68 	}
69 
70 	return dest;
71 }
72 
73 #if defined(__arm__)
74 void* __aeabi_memmove(void* dest, void const* src, size_t count)
75 	__attribute__((__alias__("memmove")));
76 #endif
77 
78 #endif
79