1// Copyright 2016 The Fuchsia Authors
2// Copyright (c) 2008 Travis Geiselbrecht
3//
4// Use of this source code is governed by a MIT-style
5// license that can be found in the LICENSE file or at
6// https://opensource.org/licenses/MIT
7
8#include <string.h>
9#include <sys/types.h>
10
11#if !_ASM_MEMMOVE
12
13typedef long word;
14
15#define lsize sizeof(word)
16#define lmask (lsize - 1)
17
18void *
19memmove(void *dest, void const *src, size_t count)
20{
21    char *d = (char *)dest;
22    const char *s = (const char *)src;
23    int len;
24
25    if (count == 0 || dest == src)
26        return dest;
27
28    if ((long)d < (long)s) {
29        if (((long)d | (long)s) & lmask) {
30            // src and/or dest do not align on word boundary
31            if ((((long)d ^ (long)s) & lmask) || (count < lsize))
32                len = count; // copy the rest of the buffer with the byte mover
33            else
34                len = lsize - ((long)d & lmask); // move the ptrs up to a word boundary
35
36            count -= len;
37            for (; len > 0; len--)
38                *d++ = *s++;
39        }
40        for (len = count / lsize; len > 0; len--) {
41            *(word *)d = *(word *)s;
42            d += lsize;
43            s += lsize;
44        }
45        for (len = count & lmask; len > 0; len--)
46            *d++ = *s++;
47    } else {
48        d += count;
49        s += count;
50        if (((long)d | (long)s) & lmask) {
51            // src and/or dest do not align on word boundary
52            if ((((long)d ^ (long)s) & lmask) || (count <= lsize))
53                len = count;
54            else
55                len = ((long)d & lmask);
56
57            count -= len;
58            for (; len > 0; len--)
59                *--d = *--s;
60        }
61        for (len = count / lsize; len > 0; len--) {
62            d -= lsize;
63            s -= lsize;
64            *(word *)d = *(word *)s;
65        }
66        for (len = count & lmask; len > 0; len--)
67            *--d = *--s;
68    }
69
70    return dest;
71}
72
73#endif
74
75