blob: 19ed8b4678f6eca0626f2dbaf7f85e4e38ae4708 [file] [log] [blame] [edit]
/*
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
*
* SPDX-License-Identifier: MIT
*/
#include "aml_memmove.h"
#include <stdint.h>
#include <string.h>
void *memmove(void *dest, const void *src, size_t n)
{
if ((uintptr_t)dest <= (uintptr_t)src || (uintptr_t)dest >= (uintptr_t)src + n) {
/* Start of destination doesn't overlap source, so just use memcpy(). */
return memcpy(dest, src, n);
}
/* Need to copy from tail because there is overlap. */
char *d = (char *)dest + n;
const char *s = (const char *)src + n;
uint32_t *dw;
const uint32_t *sw;
char *head;
char *const tail = (char *)dest;
/* Set 'body' to the last word boundary */
uint32_t *const body = (uint32_t *)(((uintptr_t)tail + 3) & ~3);
if (((uintptr_t)dest & 3) != ((uintptr_t)src & 3)) {
/* Misaligned. no body, no tail. */
head = tail;
} else {
/* Aligned */
if ((uintptr_t)tail > ((uintptr_t)d & ~3))
/* Shorter than the first word boundary */
head = tail;
else
/* Set 'head' to the first word boundary */
head = (char *)((uintptr_t)d & ~3);
}
/* Copy head */
while (d > head)
*(--d) = *(--s);
/* Copy body */
dw = (uint32_t *)d;
sw = (uint32_t *)s;
while (dw > body)
*(--dw) = *(--sw);
/* Copy tail */
d = (char *)dw;
s = (const char *)sw;
while (d > tail)
*(--d) = *(--s);
return dest;
}