root/arch/nios2/lib/memmove.c
/*
 * 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;
}