xref: /linux/arch/nios2/lib/memmove.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
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 void *memmove(void *d, const void *s, size_t count)
14 {
15 	unsigned long dst, src;
16 
17 	if (!count)
18 		return d;
19 
20 	if (d < s) {
21 		dst = (unsigned long) d;
22 		src = (unsigned long) s;
23 
24 		if ((count < 8) || ((dst ^ src) & 3))
25 			goto restup;
26 
27 		if (dst & 1) {
28 			*(char *)dst++ = *(char *)src++;
29 			count--;
30 		}
31 		if (dst & 2) {
32 			*(short *)dst = *(short *)src;
33 			src += 2;
34 			dst += 2;
35 			count -= 2;
36 		}
37 		while (count > 3) {
38 			*(long *)dst = *(long *)src;
39 			src += 4;
40 			dst += 4;
41 			count -= 4;
42 		}
43 restup:
44 		while (count--)
45 			*(char *)dst++ = *(char *)src++;
46 	} else {
47 		dst = (unsigned long) d + count;
48 		src = (unsigned long) s + count;
49 
50 		if ((count < 8) || ((dst ^ src) & 3))
51 			goto restdown;
52 
53 		if (dst & 1) {
54 			src--;
55 			dst--;
56 			count--;
57 			*(char *)dst = *(char *)src;
58 		}
59 		if (dst & 2) {
60 			src -= 2;
61 			dst -= 2;
62 			count -= 2;
63 			*(short *)dst = *(short *)src;
64 		}
65 		while (count > 3) {
66 			src -= 4;
67 			dst -= 4;
68 			count -= 4;
69 			*(long *)dst = *(long *)src;
70 		}
71 restdown:
72 		while (count--) {
73 			src--;
74 			dst--;
75 			*(char *)dst = *(char *)src;
76 		}
77 	}
78 
79 	return d;
80 }
81