#define UNALIGNED(x) (((long)x & (sizeof (long) - 1)))
#define UNALIGNED2(x, y) (((long)x & (sizeof (long) - 1)) | ((long)y & (sizeof (long) - 1)))
#define BIGBLOCKSIZE (sizeof(long) << 2)
#define LITTLEBLOCKSIZE (sizeof(long))
#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
__attribute__((weak,alias("memmove"))) void* memcpy(void* dst, const void* src, size_t len);
__attribute__((weak)) void* memmove(void* dst_void, const void* src_void, size_t len)
{
char* dst = dst_void;
const char* src = src_void;
if (src < dst && dst < src + len)
{
src += len;
dst += len;
while (len--) *--dst = *--src;
}
else
{
#ifndef SQUEEZE
if (!TOO_SMALL(len) && !UNALIGNED2(src, dst))
{
long* aligned_dst = (long*)dst;
const long* aligned_src = (long*)src;
while (len >= BIGBLOCKSIZE)
{
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
len -= BIGBLOCKSIZE;
}
while (len >= LITTLEBLOCKSIZE)
{
*aligned_dst++ = *aligned_src++;
len -= LITTLEBLOCKSIZE;
}
dst = (char*)aligned_dst;
src = (const char*)aligned_src;
}
#endif
while (len--) *dst++ = *src++;
}
return dst_void;
}