Merge tag 'drm-intel-next-2017-12-01' of git://anongit.freedesktop.org/drm/drm-intel...
[linux-2.6-microblaze.git] / arch / m68k / lib / memmove.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file COPYING in the main directory of this archive
4  * for more details.
5  */
6
7 #include <linux/module.h>
8 #include <linux/string.h>
9
10 void *memmove(void *dest, const void *src, size_t n)
11 {
12         void *xdest = dest;
13         size_t temp;
14
15         if (!n)
16                 return xdest;
17
18         if (dest < src) {
19                 if ((long)dest & 1) {
20                         char *cdest = dest;
21                         const char *csrc = src;
22                         *cdest++ = *csrc++;
23                         dest = cdest;
24                         src = csrc;
25                         n--;
26                 }
27                 if (n > 2 && (long)dest & 2) {
28                         short *sdest = dest;
29                         const short *ssrc = src;
30                         *sdest++ = *ssrc++;
31                         dest = sdest;
32                         src = ssrc;
33                         n -= 2;
34                 }
35                 temp = n >> 2;
36                 if (temp) {
37                         long *ldest = dest;
38                         const long *lsrc = src;
39                         temp--;
40                         do
41                                 *ldest++ = *lsrc++;
42                         while (temp--);
43                         dest = ldest;
44                         src = lsrc;
45                 }
46                 if (n & 2) {
47                         short *sdest = dest;
48                         const short *ssrc = src;
49                         *sdest++ = *ssrc++;
50                         dest = sdest;
51                         src = ssrc;
52                 }
53                 if (n & 1) {
54                         char *cdest = dest;
55                         const char *csrc = src;
56                         *cdest = *csrc;
57                 }
58         } else {
59                 dest = (char *)dest + n;
60                 src = (const char *)src + n;
61                 if ((long)dest & 1) {
62                         char *cdest = dest;
63                         const char *csrc = src;
64                         *--cdest = *--csrc;
65                         dest = cdest;
66                         src = csrc;
67                         n--;
68                 }
69                 if (n > 2 && (long)dest & 2) {
70                         short *sdest = dest;
71                         const short *ssrc = src;
72                         *--sdest = *--ssrc;
73                         dest = sdest;
74                         src = ssrc;
75                         n -= 2;
76                 }
77                 temp = n >> 2;
78                 if (temp) {
79                         long *ldest = dest;
80                         const long *lsrc = src;
81                         temp--;
82                         do
83                                 *--ldest = *--lsrc;
84                         while (temp--);
85                         dest = ldest;
86                         src = lsrc;
87                 }
88                 if (n & 2) {
89                         short *sdest = dest;
90                         const short *ssrc = src;
91                         *--sdest = *--ssrc;
92                         dest = sdest;
93                         src = ssrc;
94                 }
95                 if (n & 1) {
96                         char *cdest = dest;
97                         const char *csrc = src;
98                         *--cdest = *--csrc;
99                 }
100         }
101         return xdest;
102 }
103 EXPORT_SYMBOL(memmove);