root/arch/m68k/lib/memmove.c
/*
 * 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/module.h>
#include <linux/string.h>

void *memmove(void *dest, const void *src, size_t n)
{
        void *xdest = dest;
        size_t temp;

        if (!n)
                return xdest;

        if (dest < src) {
                if ((long)dest & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        *cdest++ = *csrc++;
                        dest = cdest;
                        src = csrc;
                        n--;
                }
#if defined(CONFIG_M68000)
                if ((long)src & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        for (; n; n--)
                                *cdest++ = *csrc++;
                        return xdest;
                }
#endif
                if (n > 2 && (long)dest & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;
                        *sdest++ = *ssrc++;
                        dest = sdest;
                        src = ssrc;
                        n -= 2;
                }
                temp = n >> 2;
                if (temp) {
                        long *ldest = dest;
                        const long *lsrc = src;
                        temp--;
                        do
                                *ldest++ = *lsrc++;
                        while (temp--);
                        dest = ldest;
                        src = lsrc;
                }
                if (n & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;
                        *sdest++ = *ssrc++;
                        dest = sdest;
                        src = ssrc;
                }
                if (n & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        *cdest = *csrc;
                }
        } else {
                dest = (char *)dest + n;
                src = (const char *)src + n;
                if ((long)dest & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        *--cdest = *--csrc;
                        dest = cdest;
                        src = csrc;
                        n--;
                }
#if defined(CONFIG_M68000)
                if ((long)src & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        for (; n; n--)
                                *--cdest = *--csrc;
                        return xdest;
                }
#endif
                if (n > 2 && (long)dest & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;
                        *--sdest = *--ssrc;
                        dest = sdest;
                        src = ssrc;
                        n -= 2;
                }
                temp = n >> 2;
                if (temp) {
                        long *ldest = dest;
                        const long *lsrc = src;
                        temp--;
                        do
                                *--ldest = *--lsrc;
                        while (temp--);
                        dest = ldest;
                        src = lsrc;
                }
                if (n & 2) {
                        short *sdest = dest;
                        const short *ssrc = src;
                        *--sdest = *--ssrc;
                        dest = sdest;
                        src = ssrc;
                }
                if (n & 1) {
                        char *cdest = dest;
                        const char *csrc = src;
                        *--cdest = *--csrc;
                }
        }
        return xdest;
}
EXPORT_SYMBOL(memmove);