1982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer/*
2982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer * This file is subject to the terms and conditions of the GNU General Public
3982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer * License.  See the file COPYING in the main directory of this archive
4982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer * for more details.
5982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer */
6982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer
7982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer#include <linux/module.h>
8982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer#include <linux/string.h>
9982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer
10982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerervoid *memmove(void *dest, const void *src, size_t n)
11982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer{
12982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	void *xdest = dest;
13982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	size_t temp;
14982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer
15982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	if (!n)
16982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		return xdest;
17982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer
18982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	if (dest < src) {
19982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if ((long)dest & 1) {
20982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			char *cdest = dest;
21982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const char *csrc = src;
22982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*cdest++ = *csrc++;
23982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = cdest;
24982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = csrc;
25982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			n--;
26982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
27982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n > 2 && (long)dest & 2) {
28982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			short *sdest = dest;
29982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const short *ssrc = src;
30982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*sdest++ = *ssrc++;
31982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = sdest;
32982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = ssrc;
33982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			n -= 2;
34982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
35982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		temp = n >> 2;
36982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (temp) {
37982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			long *ldest = dest;
38982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const long *lsrc = src;
39982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			temp--;
40982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			do
41982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer				*ldest++ = *lsrc++;
42982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			while (temp--);
43982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = ldest;
44982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = lsrc;
45982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
46982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n & 2) {
47982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			short *sdest = dest;
48982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const short *ssrc = src;
49982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*sdest++ = *ssrc++;
50982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = sdest;
51982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = ssrc;
52982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
53982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n & 1) {
54982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			char *cdest = dest;
55982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const char *csrc = src;
56982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*cdest = *csrc;
57982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
58982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	} else {
59982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		dest = (char *)dest + n;
60982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		src = (const char *)src + n;
61982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if ((long)dest & 1) {
62982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			char *cdest = dest;
63982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const char *csrc = src;
64982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*--cdest = *--csrc;
65982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = cdest;
66982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = csrc;
67982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			n--;
68982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
69982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n > 2 && (long)dest & 2) {
70982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			short *sdest = dest;
71982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const short *ssrc = src;
72982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*--sdest = *--ssrc;
73982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = sdest;
74982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = ssrc;
75982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			n -= 2;
76982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
77982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		temp = n >> 2;
78982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (temp) {
79982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			long *ldest = dest;
80982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const long *lsrc = src;
81982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			temp--;
82982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			do
83982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer				*--ldest = *--lsrc;
84982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			while (temp--);
85982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = ldest;
86982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = lsrc;
87982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
88982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n & 2) {
89982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			short *sdest = dest;
90982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const short *ssrc = src;
91982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*--sdest = *--ssrc;
92982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			dest = sdest;
93982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			src = ssrc;
94982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
95982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		if (n & 1) {
96982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			char *cdest = dest;
97982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			const char *csrc = src;
98982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer			*--cdest = *--csrc;
99982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer		}
100982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	}
101982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer	return xdest;
102982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg Ungerer}
103982cd252ca0b63c11fe398c09c6f2b41217c78c0Greg UngererEXPORT_SYMBOL(memmove);
104