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
13void *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		}
43restup:
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		}
71restdown:
72		while (count--) {
73			src--;
74			dst--;
75			*(char *)dst = *(char *)src;
76		}
77	}
78
79	return d;
80}
81