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 | |