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
14void *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		}
44restup:
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		}
72restdown:
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