xref: /openbmc/linux/arch/nios2/lib/memmove.c (revision 93df8a1e)
1 /*
2  * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
3  * Copyright (C) 2004 Microtronix Datacom Ltd
4  *
5  * This file is subject to the terms and conditions of the GNU General Public
6  * License.  See the file "COPYING" in the main directory of this archive
7  * for more details.
8  */
9 
10 #include <linux/types.h>
11 #include <linux/string.h>
12 
13 #ifdef __HAVE_ARCH_MEMMOVE
14 void *memmove(void *d, const void *s, size_t count)
15 {
16 	unsigned long dst, src;
17 
18 	if (!count)
19 		return d;
20 
21 	if (d < s) {
22 		dst = (unsigned long) d;
23 		src = (unsigned long) s;
24 
25 		if ((count < 8) || ((dst ^ src) & 3))
26 			goto restup;
27 
28 		if (dst & 1) {
29 			*(char *)dst++ = *(char *)src++;
30 			count--;
31 		}
32 		if (dst & 2) {
33 			*(short *)dst = *(short *)src;
34 			src += 2;
35 			dst += 2;
36 			count -= 2;
37 		}
38 		while (count > 3) {
39 			*(long *)dst = *(long *)src;
40 			src += 4;
41 			dst += 4;
42 			count -= 4;
43 		}
44 restup:
45 		while (count--)
46 			*(char *)dst++ = *(char *)src++;
47 	} else {
48 		dst = (unsigned long) d + count;
49 		src = (unsigned long) s + count;
50 
51 		if ((count < 8) || ((dst ^ src) & 3))
52 			goto restdown;
53 
54 		if (dst & 1) {
55 			src--;
56 			dst--;
57 			count--;
58 			*(char *)dst = *(char *)src;
59 		}
60 		if (dst & 2) {
61 			src -= 2;
62 			dst -= 2;
63 			count -= 2;
64 			*(short *)dst = *(short *)src;
65 		}
66 		while (count > 3) {
67 			src -= 4;
68 			dst -= 4;
69 			count -= 4;
70 			*(long *)dst = *(long *)src;
71 		}
72 restdown:
73 		while (count--) {
74 			src--;
75 			dst--;
76 			*(char *)dst = *(char *)src;
77 		}
78 	}
79 
80 	return d;
81 }
82 #endif /* __HAVE_ARCH_MEMMOVE */
83