| /* |
| * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> |
| * Copyright (C) 2004 Microtronix Datacom Ltd |
| * |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file "COPYING" in the main directory of this archive |
| * for more details. |
| */ |
| |
| #include <linux/types.h> |
| #include <linux/string.h> |
| |
| void *memmove(void *d, const void *s, size_t count) |
| { |
| unsigned long dst, src; |
| |
| if (!count) |
| return d; |
| |
| if (d < s) { |
| dst = (unsigned long) d; |
| src = (unsigned long) s; |
| |
| if ((count < 8) || ((dst ^ src) & 3)) |
| goto restup; |
| |
| if (dst & 1) { |
| *(char *)dst++ = *(char *)src++; |
| count--; |
| } |
| if (dst & 2) { |
| *(short *)dst = *(short *)src; |
| src += 2; |
| dst += 2; |
| count -= 2; |
| } |
| while (count > 3) { |
| *(long *)dst = *(long *)src; |
| src += 4; |
| dst += 4; |
| count -= 4; |
| } |
| restup: |
| while (count--) |
| *(char *)dst++ = *(char *)src++; |
| } else { |
| dst = (unsigned long) d + count; |
| src = (unsigned long) s + count; |
| |
| if ((count < 8) || ((dst ^ src) & 3)) |
| goto restdown; |
| |
| if (dst & 1) { |
| src--; |
| dst--; |
| count--; |
| *(char *)dst = *(char *)src; |
| } |
| if (dst & 2) { |
| src -= 2; |
| dst -= 2; |
| count -= 2; |
| *(short *)dst = *(short *)src; |
| } |
| while (count > 3) { |
| src -= 4; |
| dst -= 4; |
| count -= 4; |
| *(long *)dst = *(long *)src; |
| } |
| restdown: |
| while (count--) { |
| src--; |
| dst--; |
| *(char *)dst = *(char *)src; |
| } |
| } |
| |
| return d; |
| } |