summaryrefslogtreecommitdiff
path: root/firmware/common
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-01-21 22:43:02 +0000
committerJens Arnold <amiconn@rockbox.org>2005-01-21 22:43:02 +0000
commit0310f16005a1e98c441221bc0f0f7586d0b19763 (patch)
treec695e2baa4da1bc7fb9381568863e903020335e3 /firmware/common
parent948f0b849785b3e727be6584470d1bb32238ec6a (diff)
downloadrockbox-0310f16005a1e98c441221bc0f0f7586d0b19763.tar.gz
rockbox-0310f16005a1e98c441221bc0f0f7586d0b19763.zip
Revived C implementations of memcpy() and memset() for platforms without asm optimized versions (gmini), replacing the intermediate strings.c. Moved the asm optimized versions 'out of the way' for the implicit 'make' rules by renaming them to *_a.S (for assembler/alternative).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5628 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/common')
-rw-r--r--firmware/common/memcpy.c117
-rw-r--r--firmware/common/memcpy_a.S (renamed from firmware/common/memcpy.S)0
-rw-r--r--firmware/common/memset.c109
-rw-r--r--firmware/common/memset_a.S (renamed from firmware/common/memset.S)0
4 files changed, 226 insertions, 0 deletions
diff --git a/firmware/common/memcpy.c b/firmware/common/memcpy.c
new file mode 100644
index 0000000000..49678920fa
--- /dev/null
+++ b/firmware/common/memcpy.c
@@ -0,0 +1,117 @@
1/*
2FUNCTION
3 <<memcpy>>---copy memory regions
4
5ANSI_SYNOPSIS
6 #include <string.h>
7 void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>);
8
9TRAD_SYNOPSIS
10 void *memcpy(<[out]>, <[in]>, <[n]>
11 void *<[out]>;
12 void *<[in]>;
13 size_t <[n]>;
14
15DESCRIPTION
16 This function copies <[n]> bytes from the memory region
17 pointed to by <[in]> to the memory region pointed to by
18 <[out]>.
19
20 If the regions overlap, the behavior is undefined.
21
22RETURNS
23 <<memcpy>> returns a pointer to the first byte of the <[out]>
24 region.
25
26PORTABILITY
27<<memcpy>> is ANSI C.
28
29<<memcpy>> requires no supporting OS subroutines.
30
31QUICKREF
32 memcpy ansi pure
33 */
34
35#include <_ansi.h>
36#include <stddef.h>
37#include <limits.h>
38
39/* Nonzero if either X or Y is not aligned on a "long" boundary. */
40#define UNALIGNED(X, Y) \
41 (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
42
43/* How many bytes are copied each iteration of the 4X unrolled loop. */
44#define BIGBLOCKSIZE (sizeof (long) << 2)
45
46/* How many bytes are copied each iteration of the word copy loop. */
47#define LITTLEBLOCKSIZE (sizeof (long))
48
49/* Threshhold for punting to the byte copier. */
50#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
51
52_PTR
53_DEFUN (memcpy, (dst0, src0, len0),
54 _PTR dst0 _AND
55 _CONST _PTR src0 _AND
56 size_t len0) __attribute__ ((section (".icode")));
57
58_PTR
59_DEFUN (memcpy, (dst0, src0, len0),
60 _PTR dst0 _AND
61 _CONST _PTR src0 _AND
62 size_t len0)
63{
64#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
65 char *dst = (char *) dst0;
66 char *src = (char *) src0;
67
68 _PTR save = dst0;
69
70 while (len0--)
71 {
72 *dst++ = *src++;
73 }
74
75 return save;
76#else
77 char *dst = dst0;
78 _CONST char *src = src0;
79 long *aligned_dst;
80 _CONST long *aligned_src;
81 unsigned int len = len0;
82
83 /* If the size is small, or either SRC or DST is unaligned,
84 then punt into the byte copy loop. This should be rare. */
85 if (!TOO_SMALL(len) && !UNALIGNED (src, dst))
86 {
87 aligned_dst = (long*)dst;
88 aligned_src = (long*)src;
89
90 /* Copy 4X long words at a time if possible. */
91 while (len >= BIGBLOCKSIZE)
92 {
93 *aligned_dst++ = *aligned_src++;
94 *aligned_dst++ = *aligned_src++;
95 *aligned_dst++ = *aligned_src++;
96 *aligned_dst++ = *aligned_src++;
97 len -= BIGBLOCKSIZE;
98 }
99
100 /* Copy one long word at a time if possible. */
101 while (len >= LITTLEBLOCKSIZE)
102 {
103 *aligned_dst++ = *aligned_src++;
104 len -= LITTLEBLOCKSIZE;
105 }
106
107 /* Pick up any residual with a byte copier. */
108 dst = (char*)aligned_dst;
109 src = (char*)aligned_src;
110 }
111
112 while (len--)
113 *dst++ = *src++;
114
115 return dst0;
116#endif /* not PREFER_SIZE_OVER_SPEED */
117}
diff --git a/firmware/common/memcpy.S b/firmware/common/memcpy_a.S
index e129b99442..e129b99442 100644
--- a/firmware/common/memcpy.S
+++ b/firmware/common/memcpy_a.S
diff --git a/firmware/common/memset.c b/firmware/common/memset.c
new file mode 100644
index 0000000000..c370191cda
--- /dev/null
+++ b/firmware/common/memset.c
@@ -0,0 +1,109 @@
1/*
2FUNCTION
3 <<memset>>---set an area of memory
4
5INDEX
6 memset
7
8ANSI_SYNOPSIS
9 #include <string.h>
10 void *memset(const void *<[dst]>, int <[c]>, size_t <[length]>);
11
12TRAD_SYNOPSIS
13 #include <string.h>
14 void *memset(<[dst]>, <[c]>, <[length]>)
15 void *<[dst]>;
16 int <[c]>;
17 size_t <[length]>;
18
19DESCRIPTION
20 This function converts the argument <[c]> into an unsigned
21 char and fills the first <[length]> characters of the array
22 pointed to by <[dst]> to the value.
23
24RETURNS
25 <<memset>> returns the value of <[m]>.
26
27PORTABILITY
28<<memset>> is ANSI C.
29
30 <<memset>> requires no supporting OS subroutines.
31
32QUICKREF
33 memset ansi pure
34*/
35
36#include <string.h>
37
38#define LBLOCKSIZE (sizeof(long))
39#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
40#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
41
42_PTR
43_DEFUN (memset, (m, c, n),
44 _PTR m _AND
45 int c _AND
46 size_t n)
47{
48#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
49 char *s = (char *) m;
50
51 while (n-- != 0)
52 {
53 *s++ = (char) c;
54 }
55
56 return m;
57#else
58 char *s = (char *) m;
59 unsigned int i;
60 unsigned long buffer;
61 unsigned long *aligned_addr;
62
63 if (!TOO_SMALL (n) && !UNALIGNED (m))
64 {
65 /* If we get this far, we know that n is large and m is word-aligned. */
66
67 aligned_addr = (unsigned long*)m;
68
69 /* Store C into each char sized location in BUFFER so that
70 we can set large blocks quickly. */
71 c &= 0xff;
72 if (LBLOCKSIZE == 4)
73 {
74 buffer = (c << 8) | c;
75 buffer |= (buffer << 16);
76 }
77 else
78 {
79 buffer = 0;
80 for (i = 0; i < LBLOCKSIZE; i++)
81 buffer = (buffer << 8) | c;
82 }
83
84 while (n >= LBLOCKSIZE*4)
85 {
86 *aligned_addr++ = buffer;
87 *aligned_addr++ = buffer;
88 *aligned_addr++ = buffer;
89 *aligned_addr++ = buffer;
90 n -= 4*LBLOCKSIZE;
91 }
92
93 while (n >= LBLOCKSIZE)
94 {
95 *aligned_addr++ = buffer;
96 n -= LBLOCKSIZE;
97 }
98 /* Pick up the remainder with a bytewise loop. */
99 s = (char*)aligned_addr;
100 }
101
102 while (n--)
103 {
104 *s++ = (char)c;
105 }
106
107 return m;
108#endif /* not PREFER_SIZE_OVER_SPEED */
109}
diff --git a/firmware/common/memset.S b/firmware/common/memset_a.S
index bce8936089..bce8936089 100644
--- a/firmware/common/memset.S
+++ b/firmware/common/memset_a.S