18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
38c2ecf20Sopenharmony_ci * Copyright (C) 2004 Microtronix Datacom Ltd
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
68c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
78c2ecf20Sopenharmony_ci * for more details.
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/types.h>
118c2ecf20Sopenharmony_ci#include <linux/string.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_civoid *memmove(void *d, const void *s, size_t count)
148c2ecf20Sopenharmony_ci{
158c2ecf20Sopenharmony_ci	unsigned long dst, src;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	if (!count)
188c2ecf20Sopenharmony_ci		return d;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	if (d < s) {
218c2ecf20Sopenharmony_ci		dst = (unsigned long) d;
228c2ecf20Sopenharmony_ci		src = (unsigned long) s;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci		if ((count < 8) || ((dst ^ src) & 3))
258c2ecf20Sopenharmony_ci			goto restup;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci		if (dst & 1) {
288c2ecf20Sopenharmony_ci			*(char *)dst++ = *(char *)src++;
298c2ecf20Sopenharmony_ci			count--;
308c2ecf20Sopenharmony_ci		}
318c2ecf20Sopenharmony_ci		if (dst & 2) {
328c2ecf20Sopenharmony_ci			*(short *)dst = *(short *)src;
338c2ecf20Sopenharmony_ci			src += 2;
348c2ecf20Sopenharmony_ci			dst += 2;
358c2ecf20Sopenharmony_ci			count -= 2;
368c2ecf20Sopenharmony_ci		}
378c2ecf20Sopenharmony_ci		while (count > 3) {
388c2ecf20Sopenharmony_ci			*(long *)dst = *(long *)src;
398c2ecf20Sopenharmony_ci			src += 4;
408c2ecf20Sopenharmony_ci			dst += 4;
418c2ecf20Sopenharmony_ci			count -= 4;
428c2ecf20Sopenharmony_ci		}
438c2ecf20Sopenharmony_cirestup:
448c2ecf20Sopenharmony_ci		while (count--)
458c2ecf20Sopenharmony_ci			*(char *)dst++ = *(char *)src++;
468c2ecf20Sopenharmony_ci	} else {
478c2ecf20Sopenharmony_ci		dst = (unsigned long) d + count;
488c2ecf20Sopenharmony_ci		src = (unsigned long) s + count;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci		if ((count < 8) || ((dst ^ src) & 3))
518c2ecf20Sopenharmony_ci			goto restdown;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		if (dst & 1) {
548c2ecf20Sopenharmony_ci			src--;
558c2ecf20Sopenharmony_ci			dst--;
568c2ecf20Sopenharmony_ci			count--;
578c2ecf20Sopenharmony_ci			*(char *)dst = *(char *)src;
588c2ecf20Sopenharmony_ci		}
598c2ecf20Sopenharmony_ci		if (dst & 2) {
608c2ecf20Sopenharmony_ci			src -= 2;
618c2ecf20Sopenharmony_ci			dst -= 2;
628c2ecf20Sopenharmony_ci			count -= 2;
638c2ecf20Sopenharmony_ci			*(short *)dst = *(short *)src;
648c2ecf20Sopenharmony_ci		}
658c2ecf20Sopenharmony_ci		while (count > 3) {
668c2ecf20Sopenharmony_ci			src -= 4;
678c2ecf20Sopenharmony_ci			dst -= 4;
688c2ecf20Sopenharmony_ci			count -= 4;
698c2ecf20Sopenharmony_ci			*(long *)dst = *(long *)src;
708c2ecf20Sopenharmony_ci		}
718c2ecf20Sopenharmony_cirestdown:
728c2ecf20Sopenharmony_ci		while (count--) {
738c2ecf20Sopenharmony_ci			src--;
748c2ecf20Sopenharmony_ci			dst--;
758c2ecf20Sopenharmony_ci			*(char *)dst = *(char *)src;
768c2ecf20Sopenharmony_ci		}
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	return d;
808c2ecf20Sopenharmony_ci}
81