summaryrefslogtreecommitdiff
path: root/firmware/common/memmove.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-02-06 16:00:58 +0000
committerJens Arnold <amiconn@rockbox.org>2006-02-06 16:00:58 +0000
commitd036e97d3816ac2bc0eefc57bc033bd5fbbbf0f9 (patch)
tree604e32fcc0cf4ac745774987c5e052544bb25d36 /firmware/common/memmove.c
parent93c15381c8fa25cd30d52d3660c6f909837683fe (diff)
downloadrockbox-d036e97d3816ac2bc0eefc57bc033bd5fbbbf0f9.tar.gz
rockbox-d036e97d3816ac2bc0eefc57bc033bd5fbbbf0f9.zip
Added memmove() to the rockbox core. C implementation taken from newlib. Fully optimised ASM implementations for SH1 and coldfire, reusing the AMS memcpy code path for forward copying.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8601 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/common/memmove.c')
-rw-r--r--firmware/common/memmove.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/firmware/common/memmove.c b/firmware/common/memmove.c
new file mode 100644
index 0000000000..761e9eb104
--- /dev/null
+++ b/firmware/common/memmove.c
@@ -0,0 +1,148 @@
1/*
2FUNCTION
3 <<memmove>>---move possibly overlapping memory
4
5INDEX
6 memmove
7
8ANSI_SYNOPSIS
9 #include <string.h>
10 void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>);
11
12TRAD_SYNOPSIS
13 #include <string.h>
14 void *memmove(<[dst]>, <[src]>, <[length]>)
15 void *<[dst]>;
16 void *<[src]>;
17 size_t <[length]>;
18
19DESCRIPTION
20 This function moves <[length]> characters from the block of
21 memory starting at <<*<[src]>>> to the memory starting at
22 <<*<[dst]>>>. <<memmove>> reproduces the characters correctly
23 at <<*<[dst]>>> even if the two areas overlap.
24
25
26RETURNS
27 The function returns <[dst]> as passed.
28
29PORTABILITY
30<<memmove>> is ANSI C.
31
32<<memmove>> requires no supporting OS subroutines.
33
34QUICKREF
35 memmove ansi pure
36*/
37
38#include "config.h"
39#include <_ansi.h>
40#include <stddef.h>
41#include <limits.h>
42
43/* Nonzero if either X or Y is not aligned on a "long" boundary. */
44#define UNALIGNED(X, Y) \
45 (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
46
47/* How many bytes are copied each iteration of the 4X unrolled loop. */
48#define BIGBLOCKSIZE (sizeof (long) << 2)
49
50/* How many bytes are copied each iteration of the word copy loop. */
51#define LITTLEBLOCKSIZE (sizeof (long))
52
53/* Threshhold for punting to the byte copier. */
54#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
55
56_PTR
57_DEFUN (memmove, (dst_void, src_void, length),
58 _PTR dst_void _AND
59 _CONST _PTR src_void _AND
60 size_t length) ICODE_ATTR;
61
62_PTR
63_DEFUN (memmove, (dst_void, src_void, length),
64 _PTR dst_void _AND
65 _CONST _PTR src_void _AND
66 size_t length)
67{
68#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
69 char *dst = dst_void;
70 _CONST char *src = src_void;
71
72 if (src < dst && dst < src + length)
73 {
74 /* Have to copy backwards */
75 src += length;
76 dst += length;
77 while (length--)
78 {
79 *--dst = *--src;
80 }
81 }
82 else
83 {
84 while (length--)
85 {
86 *dst++ = *src++;
87 }
88 }
89
90 return dst_void;
91#else
92 char *dst = dst_void;
93 _CONST char *src = src_void;
94 long *aligned_dst;
95 _CONST long *aligned_src;
96 unsigned int len = length;
97
98 if (src < dst && dst < src + len)
99 {
100 /* Destructive overlap...have to copy backwards */
101 src += len;
102 dst += len;
103 while (len--)
104 {
105 *--dst = *--src;
106 }
107 }
108 else
109 {
110 /* Use optimizing algorithm for a non-destructive copy to closely
111 match memcpy. If the size is small or either SRC or DST is unaligned,
112 then punt into the byte copy loop. This should be rare. */
113 if (!TOO_SMALL(len) && !UNALIGNED (src, dst))
114 {
115 aligned_dst = (long*)dst;
116 aligned_src = (long*)src;
117
118 /* Copy 4X long words at a time if possible. */
119 while (len >= BIGBLOCKSIZE)
120 {
121 *aligned_dst++ = *aligned_src++;
122 *aligned_dst++ = *aligned_src++;
123 *aligned_dst++ = *aligned_src++;
124 *aligned_dst++ = *aligned_src++;
125 len -= BIGBLOCKSIZE;
126 }
127
128 /* Copy one long word at a time if possible. */
129 while (len >= LITTLEBLOCKSIZE)
130 {
131 *aligned_dst++ = *aligned_src++;
132 len -= LITTLEBLOCKSIZE;
133 }
134
135 /* Pick up any residual with a byte copier. */
136 dst = (char*)aligned_dst;
137 src = (char*)aligned_src;
138 }
139
140 while (len--)
141 {
142 *dst++ = *src++;
143 }
144 }
145
146 return dst_void;
147#endif /* not PREFER_SIZE_OVER_SPEED */
148}