diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2005-09-03 18:57:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:06:19 -0400 |
commit | 072dffda1d35c391fe893ec9b1d098145e668fef (patch) | |
tree | 2eee1530619abb7cf751db022216ab483e6fc823 | |
parent | 2855b97020f6d4a4dfb005fb77c0b79c8cb9d13f (diff) |
[PATCH] m68k: cleanup inline mem functions
Use the builtin functions for memset/memclr/memcpy, special optimizations for
page operations have dedicated functions now. Uninline memmove/memchr and
move all functions into a single file and clean it up a little.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/m68k/kernel/m68k_ksyms.c | 4 | ||||
-rw-r--r-- | arch/m68k/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/m68k/lib/memcmp.c | 11 | ||||
-rw-r--r-- | arch/m68k/lib/memcpy.c | 75 | ||||
-rw-r--r-- | arch/m68k/lib/memset.c | 68 | ||||
-rw-r--r-- | arch/m68k/lib/string.c | 237 | ||||
-rw-r--r-- | include/asm-m68k/string.h | 403 |
7 files changed, 245 insertions, 555 deletions
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index fe837e31afbf..73e2f5e168dd 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c | |||
@@ -74,10 +74,6 @@ EXPORT_SYMBOL(vme_brdtype); | |||
74 | EXPORT_SYMBOL(__ashldi3); | 74 | EXPORT_SYMBOL(__ashldi3); |
75 | EXPORT_SYMBOL(__ashrdi3); | 75 | EXPORT_SYMBOL(__ashrdi3); |
76 | EXPORT_SYMBOL(__lshrdi3); | 76 | EXPORT_SYMBOL(__lshrdi3); |
77 | EXPORT_SYMBOL(memcpy); | ||
78 | EXPORT_SYMBOL(memset); | ||
79 | EXPORT_SYMBOL(memcmp); | ||
80 | EXPORT_SYMBOL(memscan); | ||
81 | EXPORT_SYMBOL(__muldi3); | 77 | EXPORT_SYMBOL(__muldi3); |
82 | 78 | ||
83 | EXPORT_SYMBOL(__down_failed); | 79 | EXPORT_SYMBOL(__down_failed); |
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index 34b6dbc29c85..ebe51a513817 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile | |||
@@ -5,4 +5,4 @@ | |||
5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
6 | 6 | ||
7 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | 7 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ |
8 | checksum.o memcmp.o memcpy.o memset.o semaphore.o | 8 | checksum.o string.o semaphore.o |
diff --git a/arch/m68k/lib/memcmp.c b/arch/m68k/lib/memcmp.c deleted file mode 100644 index f4796febb773..000000000000 --- a/arch/m68k/lib/memcmp.c +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | int memcmp(const void * cs,const void * ct,size_t count) | ||
4 | { | ||
5 | const unsigned char *su1, *su2; | ||
6 | |||
7 | for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) | ||
8 | if (*su1 != *su2) | ||
9 | return((*su1 < *su2) ? -1 : +1); | ||
10 | return(0); | ||
11 | } | ||
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c deleted file mode 100644 index 73e181823d9b..000000000000 --- a/arch/m68k/lib/memcpy.c +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | void * memcpy(void * to, const void * from, size_t n) | ||
4 | { | ||
5 | void *xto = to; | ||
6 | size_t temp, temp1; | ||
7 | |||
8 | if (!n) | ||
9 | return xto; | ||
10 | if ((long) to & 1) | ||
11 | { | ||
12 | char *cto = to; | ||
13 | const char *cfrom = from; | ||
14 | *cto++ = *cfrom++; | ||
15 | to = cto; | ||
16 | from = cfrom; | ||
17 | n--; | ||
18 | } | ||
19 | if (n > 2 && (long) to & 2) | ||
20 | { | ||
21 | short *sto = to; | ||
22 | const short *sfrom = from; | ||
23 | *sto++ = *sfrom++; | ||
24 | to = sto; | ||
25 | from = sfrom; | ||
26 | n -= 2; | ||
27 | } | ||
28 | temp = n >> 2; | ||
29 | if (temp) | ||
30 | { | ||
31 | long *lto = to; | ||
32 | const long *lfrom = from; | ||
33 | |||
34 | __asm__ __volatile__("movel %2,%3\n\t" | ||
35 | "andw #7,%3\n\t" | ||
36 | "lsrl #3,%2\n\t" | ||
37 | "negw %3\n\t" | ||
38 | "jmp %%pc@(1f,%3:w:2)\n\t" | ||
39 | "4:\t" | ||
40 | "movel %0@+,%1@+\n\t" | ||
41 | "movel %0@+,%1@+\n\t" | ||
42 | "movel %0@+,%1@+\n\t" | ||
43 | "movel %0@+,%1@+\n\t" | ||
44 | "movel %0@+,%1@+\n\t" | ||
45 | "movel %0@+,%1@+\n\t" | ||
46 | "movel %0@+,%1@+\n\t" | ||
47 | "movel %0@+,%1@+\n\t" | ||
48 | "1:\t" | ||
49 | "dbra %2,4b\n\t" | ||
50 | "clrw %2\n\t" | ||
51 | "subql #1,%2\n\t" | ||
52 | "jpl 4b\n\t" | ||
53 | : "=a" (lfrom), "=a" (lto), "=d" (temp), | ||
54 | "=&d" (temp1) | ||
55 | : "0" (lfrom), "1" (lto), "2" (temp) | ||
56 | ); | ||
57 | to = lto; | ||
58 | from = lfrom; | ||
59 | } | ||
60 | if (n & 2) | ||
61 | { | ||
62 | short *sto = to; | ||
63 | const short *sfrom = from; | ||
64 | *sto++ = *sfrom++; | ||
65 | to = sto; | ||
66 | from = sfrom; | ||
67 | } | ||
68 | if (n & 1) | ||
69 | { | ||
70 | char *cto = to; | ||
71 | const char *cfrom = from; | ||
72 | *cto = *cfrom; | ||
73 | } | ||
74 | return xto; | ||
75 | } | ||
diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c deleted file mode 100644 index d55fdb2ee9d3..000000000000 --- a/arch/m68k/lib/memset.c +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | void * memset(void * s, int c, size_t count) | ||
4 | { | ||
5 | void *xs = s; | ||
6 | size_t temp, temp1; | ||
7 | |||
8 | if (!count) | ||
9 | return xs; | ||
10 | c &= 0xff; | ||
11 | c |= c << 8; | ||
12 | c |= c << 16; | ||
13 | if ((long) s & 1) | ||
14 | { | ||
15 | char *cs = s; | ||
16 | *cs++ = c; | ||
17 | s = cs; | ||
18 | count--; | ||
19 | } | ||
20 | if (count > 2 && (long) s & 2) | ||
21 | { | ||
22 | short *ss = s; | ||
23 | *ss++ = c; | ||
24 | s = ss; | ||
25 | count -= 2; | ||
26 | } | ||
27 | temp = count >> 2; | ||
28 | if (temp) | ||
29 | { | ||
30 | long *ls = s; | ||
31 | |||
32 | __asm__ __volatile__("movel %1,%2\n\t" | ||
33 | "andw #7,%2\n\t" | ||
34 | "lsrl #3,%1\n\t" | ||
35 | "negw %2\n\t" | ||
36 | "jmp %%pc@(2f,%2:w:2)\n\t" | ||
37 | "1:\t" | ||
38 | "movel %3,%0@+\n\t" | ||
39 | "movel %3,%0@+\n\t" | ||
40 | "movel %3,%0@+\n\t" | ||
41 | "movel %3,%0@+\n\t" | ||
42 | "movel %3,%0@+\n\t" | ||
43 | "movel %3,%0@+\n\t" | ||
44 | "movel %3,%0@+\n\t" | ||
45 | "movel %3,%0@+\n\t" | ||
46 | "2:\t" | ||
47 | "dbra %1,1b\n\t" | ||
48 | "clrw %1\n\t" | ||
49 | "subql #1,%1\n\t" | ||
50 | "jpl 1b\n\t" | ||
51 | : "=a" (ls), "=d" (temp), "=&d" (temp1) | ||
52 | : "d" (c), "0" (ls), "1" (temp) | ||
53 | ); | ||
54 | s = ls; | ||
55 | } | ||
56 | if (count & 2) | ||
57 | { | ||
58 | short *ss = s; | ||
59 | *ss++ = c; | ||
60 | s = ss; | ||
61 | } | ||
62 | if (count & 1) | ||
63 | { | ||
64 | char *cs = s; | ||
65 | *cs = c; | ||
66 | } | ||
67 | return xs; | ||
68 | } | ||
diff --git a/arch/m68k/lib/string.c b/arch/m68k/lib/string.c new file mode 100644 index 000000000000..b92b89e1ea0c --- /dev/null +++ b/arch/m68k/lib/string.c | |||
@@ -0,0 +1,237 @@ | |||
1 | |||
2 | #include <linux/types.h> | ||
3 | #include <linux/module.h> | ||
4 | |||
5 | void *memset(void *s, int c, size_t count) | ||
6 | { | ||
7 | void *xs = s; | ||
8 | size_t temp, temp1; | ||
9 | |||
10 | if (!count) | ||
11 | return xs; | ||
12 | c &= 0xff; | ||
13 | c |= c << 8; | ||
14 | c |= c << 16; | ||
15 | if ((long)s & 1) { | ||
16 | char *cs = s; | ||
17 | *cs++ = c; | ||
18 | s = cs; | ||
19 | count--; | ||
20 | } | ||
21 | if (count > 2 && (long)s & 2) { | ||
22 | short *ss = s; | ||
23 | *ss++ = c; | ||
24 | s = ss; | ||
25 | count -= 2; | ||
26 | } | ||
27 | temp = count >> 2; | ||
28 | if (temp) { | ||
29 | long *ls = s; | ||
30 | |||
31 | asm volatile ( | ||
32 | " movel %1,%2\n" | ||
33 | " andw #7,%2\n" | ||
34 | " lsrl #3,%1\n" | ||
35 | " negw %2\n" | ||
36 | " jmp %%pc@(2f,%2:w:2)\n" | ||
37 | "1: movel %3,%0@+\n" | ||
38 | " movel %3,%0@+\n" | ||
39 | " movel %3,%0@+\n" | ||
40 | " movel %3,%0@+\n" | ||
41 | " movel %3,%0@+\n" | ||
42 | " movel %3,%0@+\n" | ||
43 | " movel %3,%0@+\n" | ||
44 | " movel %3,%0@+\n" | ||
45 | "2: dbra %1,1b\n" | ||
46 | " clrw %1\n" | ||
47 | " subql #1,%1\n" | ||
48 | " jpl 1b" | ||
49 | : "=a" (ls), "=d" (temp), "=&d" (temp1) | ||
50 | : "d" (c), "0" (ls), "1" (temp)); | ||
51 | s = ls; | ||
52 | } | ||
53 | if (count & 2) { | ||
54 | short *ss = s; | ||
55 | *ss++ = c; | ||
56 | s = ss; | ||
57 | } | ||
58 | if (count & 1) { | ||
59 | char *cs = s; | ||
60 | *cs = c; | ||
61 | } | ||
62 | return xs; | ||
63 | } | ||
64 | EXPORT_SYMBOL(memset); | ||
65 | |||
66 | void *memcpy(void *to, const void *from, size_t n) | ||
67 | { | ||
68 | void *xto = to; | ||
69 | size_t temp, temp1; | ||
70 | |||
71 | if (!n) | ||
72 | return xto; | ||
73 | if ((long)to & 1) { | ||
74 | char *cto = to; | ||
75 | const char *cfrom = from; | ||
76 | *cto++ = *cfrom++; | ||
77 | to = cto; | ||
78 | from = cfrom; | ||
79 | n--; | ||
80 | } | ||
81 | if (n > 2 && (long)to & 2) { | ||
82 | short *sto = to; | ||
83 | const short *sfrom = from; | ||
84 | *sto++ = *sfrom++; | ||
85 | to = sto; | ||
86 | from = sfrom; | ||
87 | n -= 2; | ||
88 | } | ||
89 | temp = n >> 2; | ||
90 | if (temp) { | ||
91 | long *lto = to; | ||
92 | const long *lfrom = from; | ||
93 | |||
94 | asm volatile ( | ||
95 | " movel %2,%3\n" | ||
96 | " andw #7,%3\n" | ||
97 | " lsrl #3,%2\n" | ||
98 | " negw %3\n" | ||
99 | " jmp %%pc@(1f,%3:w:2)\n" | ||
100 | "4: movel %0@+,%1@+\n" | ||
101 | " movel %0@+,%1@+\n" | ||
102 | " movel %0@+,%1@+\n" | ||
103 | " movel %0@+,%1@+\n" | ||
104 | " movel %0@+,%1@+\n" | ||
105 | " movel %0@+,%1@+\n" | ||
106 | " movel %0@+,%1@+\n" | ||
107 | " movel %0@+,%1@+\n" | ||
108 | "1: dbra %2,4b\n" | ||
109 | " clrw %2\n" | ||
110 | " subql #1,%2\n" | ||
111 | " jpl 4b" | ||
112 | : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1) | ||
113 | : "0" (lfrom), "1" (lto), "2" (temp)); | ||
114 | to = lto; | ||
115 | from = lfrom; | ||
116 | } | ||
117 | if (n & 2) { | ||
118 | short *sto = to; | ||
119 | const short *sfrom = from; | ||
120 | *sto++ = *sfrom++; | ||
121 | to = sto; | ||
122 | from = sfrom; | ||
123 | } | ||
124 | if (n & 1) { | ||
125 | char *cto = to; | ||
126 | const char *cfrom = from; | ||
127 | *cto = *cfrom; | ||
128 | } | ||
129 | return xto; | ||
130 | } | ||
131 | EXPORT_SYMBOL(memcpy); | ||
132 | |||
133 | void *memmove(void *dest, const void *src, size_t n) | ||
134 | { | ||
135 | void *xdest = dest; | ||
136 | size_t temp; | ||
137 | |||
138 | if (!n) | ||
139 | return xdest; | ||
140 | |||
141 | if (dest < src) { | ||
142 | if ((long)dest & 1) { | ||
143 | char *cdest = dest; | ||
144 | const char *csrc = src; | ||
145 | *cdest++ = *csrc++; | ||
146 | dest = cdest; | ||
147 | src = csrc; | ||
148 | n--; | ||
149 | } | ||
150 | if (n > 2 && (long)dest & 2) { | ||
151 | short *sdest = dest; | ||
152 | const short *ssrc = src; | ||
153 | *sdest++ = *ssrc++; | ||
154 | dest = sdest; | ||
155 | src = ssrc; | ||
156 | n -= 2; | ||
157 | } | ||
158 | temp = n >> 2; | ||
159 | if (temp) { | ||
160 | long *ldest = dest; | ||
161 | const long *lsrc = src; | ||
162 | temp--; | ||
163 | do | ||
164 | *ldest++ = *lsrc++; | ||
165 | while (temp--); | ||
166 | dest = ldest; | ||
167 | src = lsrc; | ||
168 | } | ||
169 | if (n & 2) { | ||
170 | short *sdest = dest; | ||
171 | const short *ssrc = src; | ||
172 | *sdest++ = *ssrc++; | ||
173 | dest = sdest; | ||
174 | src = ssrc; | ||
175 | } | ||
176 | if (n & 1) { | ||
177 | char *cdest = dest; | ||
178 | const char *csrc = src; | ||
179 | *cdest = *csrc; | ||
180 | } | ||
181 | } else { | ||
182 | dest = (char *)dest + n; | ||
183 | src = (const char *)src + n; | ||
184 | if ((long)dest & 1) { | ||
185 | char *cdest = dest; | ||
186 | const char *csrc = src; | ||
187 | *--cdest = *--csrc; | ||
188 | dest = cdest; | ||
189 | src = csrc; | ||
190 | n--; | ||
191 | } | ||
192 | if (n > 2 && (long)dest & 2) { | ||
193 | short *sdest = dest; | ||
194 | const short *ssrc = src; | ||
195 | *--sdest = *--ssrc; | ||
196 | dest = sdest; | ||
197 | src = ssrc; | ||
198 | n -= 2; | ||
199 | } | ||
200 | temp = n >> 2; | ||
201 | if (temp) { | ||
202 | long *ldest = dest; | ||
203 | const long *lsrc = src; | ||
204 | temp--; | ||
205 | do | ||
206 | *--ldest = *--lsrc; | ||
207 | while (temp--); | ||
208 | dest = ldest; | ||
209 | src = lsrc; | ||
210 | } | ||
211 | if (n & 2) { | ||
212 | short *sdest = dest; | ||
213 | const short *ssrc = src; | ||
214 | *--sdest = *--ssrc; | ||
215 | dest = sdest; | ||
216 | src = ssrc; | ||
217 | } | ||
218 | if (n & 1) { | ||
219 | char *cdest = dest; | ||
220 | const char *csrc = src; | ||
221 | *--cdest = *--csrc; | ||
222 | } | ||
223 | } | ||
224 | return xdest; | ||
225 | } | ||
226 | EXPORT_SYMBOL(memmove); | ||
227 | |||
228 | int memcmp(const void *cs, const void *ct, size_t count) | ||
229 | { | ||
230 | const unsigned char *su1, *su2; | ||
231 | |||
232 | for (su1 = cs, su2 = ct; count > 0; ++su1, ++su2, count--) | ||
233 | if (*su1 != *su2) | ||
234 | return *su1 < *su2 ? -1 : +1; | ||
235 | return 0; | ||
236 | } | ||
237 | EXPORT_SYMBOL(memcmp); | ||
diff --git a/include/asm-m68k/string.h b/include/asm-m68k/string.h index 44def078132a..6c59215b285e 100644 --- a/include/asm-m68k/string.h +++ b/include/asm-m68k/string.h | |||
@@ -80,43 +80,6 @@ static inline char * strchr(const char * s, int c) | |||
80 | return( (char *) s); | 80 | return( (char *) s); |
81 | } | 81 | } |
82 | 82 | ||
83 | #if 0 | ||
84 | #define __HAVE_ARCH_STRPBRK | ||
85 | static inline char *strpbrk(const char *cs,const char *ct) | ||
86 | { | ||
87 | const char *sc1,*sc2; | ||
88 | |||
89 | for( sc1 = cs; *sc1 != '\0'; ++sc1) | ||
90 | for( sc2 = ct; *sc2 != '\0'; ++sc2) | ||
91 | if (*sc1 == *sc2) | ||
92 | return((char *) sc1); | ||
93 | return( NULL ); | ||
94 | } | ||
95 | #endif | ||
96 | |||
97 | #if 0 | ||
98 | #define __HAVE_ARCH_STRSPN | ||
99 | static inline size_t strspn(const char *s, const char *accept) | ||
100 | { | ||
101 | const char *p; | ||
102 | const char *a; | ||
103 | size_t count = 0; | ||
104 | |||
105 | for (p = s; *p != '\0'; ++p) | ||
106 | { | ||
107 | for (a = accept; *a != '\0'; ++a) | ||
108 | if (*p == *a) | ||
109 | break; | ||
110 | if (*a == '\0') | ||
111 | return count; | ||
112 | else | ||
113 | ++count; | ||
114 | } | ||
115 | |||
116 | return count; | ||
117 | } | ||
118 | #endif | ||
119 | |||
120 | /* strstr !! */ | 83 | /* strstr !! */ |
121 | 84 | ||
122 | #define __HAVE_ARCH_STRLEN | 85 | #define __HAVE_ARCH_STRLEN |
@@ -173,370 +136,18 @@ static inline int strncmp(const char * cs,const char * ct,size_t count) | |||
173 | } | 136 | } |
174 | 137 | ||
175 | #define __HAVE_ARCH_MEMSET | 138 | #define __HAVE_ARCH_MEMSET |
176 | /* | 139 | extern void *memset(void *, int, __kernel_size_t); |
177 | * This is really ugly, but its highly optimizatiable by the | 140 | #define memset(d, c, n) __builtin_memset(d, c, n) |
178 | * compiler and is meant as compensation for gcc's missing | ||
179 | * __builtin_memset(). For the 680[23]0 it might be worth considering | ||
180 | * the optimal number of misaligned writes compared to the number of | ||
181 | * tests'n'branches needed to align the destination address. The | ||
182 | * 680[46]0 doesn't really care due to their copy-back caches. | ||
183 | * 10/09/96 - Jes Sorensen | ||
184 | */ | ||
185 | static inline void * __memset_g(void * s, int c, size_t count) | ||
186 | { | ||
187 | void *xs = s; | ||
188 | size_t temp; | ||
189 | |||
190 | if (!count) | ||
191 | return xs; | ||
192 | |||
193 | c &= 0xff; | ||
194 | c |= c << 8; | ||
195 | c |= c << 16; | ||
196 | |||
197 | if (count < 36){ | ||
198 | long *ls = s; | ||
199 | |||
200 | switch(count){ | ||
201 | case 32: case 33: case 34: case 35: | ||
202 | *ls++ = c; | ||
203 | case 28: case 29: case 30: case 31: | ||
204 | *ls++ = c; | ||
205 | case 24: case 25: case 26: case 27: | ||
206 | *ls++ = c; | ||
207 | case 20: case 21: case 22: case 23: | ||
208 | *ls++ = c; | ||
209 | case 16: case 17: case 18: case 19: | ||
210 | *ls++ = c; | ||
211 | case 12: case 13: case 14: case 15: | ||
212 | *ls++ = c; | ||
213 | case 8: case 9: case 10: case 11: | ||
214 | *ls++ = c; | ||
215 | case 4: case 5: case 6: case 7: | ||
216 | *ls++ = c; | ||
217 | break; | ||
218 | default: | ||
219 | break; | ||
220 | } | ||
221 | s = ls; | ||
222 | if (count & 0x02){ | ||
223 | short *ss = s; | ||
224 | *ss++ = c; | ||
225 | s = ss; | ||
226 | } | ||
227 | if (count & 0x01){ | ||
228 | char *cs = s; | ||
229 | *cs++ = c; | ||
230 | s = cs; | ||
231 | } | ||
232 | return xs; | ||
233 | } | ||
234 | |||
235 | if ((long) s & 1) | ||
236 | { | ||
237 | char *cs = s; | ||
238 | *cs++ = c; | ||
239 | s = cs; | ||
240 | count--; | ||
241 | } | ||
242 | if (count > 2 && (long) s & 2) | ||
243 | { | ||
244 | short *ss = s; | ||
245 | *ss++ = c; | ||
246 | s = ss; | ||
247 | count -= 2; | ||
248 | } | ||
249 | temp = count >> 2; | ||
250 | if (temp) | ||
251 | { | ||
252 | long *ls = s; | ||
253 | temp--; | ||
254 | do | ||
255 | *ls++ = c; | ||
256 | while (temp--); | ||
257 | s = ls; | ||
258 | } | ||
259 | if (count & 2) | ||
260 | { | ||
261 | short *ss = s; | ||
262 | *ss++ = c; | ||
263 | s = ss; | ||
264 | } | ||
265 | if (count & 1) | ||
266 | { | ||
267 | char *cs = s; | ||
268 | *cs = c; | ||
269 | } | ||
270 | return xs; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * __memset_page assumes that data is longword aligned. Most, if not | ||
275 | * all, of these page sized memsets are performed on page aligned | ||
276 | * areas, thus we do not need to check if the destination is longword | ||
277 | * aligned. Of course we suffer a serious performance loss if this is | ||
278 | * not the case but I think the risk of this ever happening is | ||
279 | * extremely small. We spend a lot of time clearing pages in | ||
280 | * get_empty_page() so I think it is worth it anyway. Besides, the | ||
281 | * 680[46]0 do not really care about misaligned writes due to their | ||
282 | * copy-back cache. | ||
283 | * | ||
284 | * The optimized case for the 680[46]0 is implemented using the move16 | ||
285 | * instruction. My tests showed that this implementation is 35-45% | ||
286 | * faster than the original implementation using movel, the only | ||
287 | * caveat is that the destination address must be 16-byte aligned. | ||
288 | * 01/09/96 - Jes Sorensen | ||
289 | */ | ||
290 | static inline void * __memset_page(void * s,int c,size_t count) | ||
291 | { | ||
292 | unsigned long data, tmp; | ||
293 | void *xs = s; | ||
294 | |||
295 | c = c & 255; | ||
296 | data = c | (c << 8); | ||
297 | data |= data << 16; | ||
298 | |||
299 | #ifdef CPU_M68040_OR_M68060_ONLY | ||
300 | |||
301 | if (((unsigned long) s) & 0x0f) | ||
302 | __memset_g(s, c, count); | ||
303 | else{ | ||
304 | unsigned long *sp = s; | ||
305 | *sp++ = data; | ||
306 | *sp++ = data; | ||
307 | *sp++ = data; | ||
308 | *sp++ = data; | ||
309 | |||
310 | __asm__ __volatile__("1:\t" | ||
311 | ".chip 68040\n\t" | ||
312 | "move16 %2@+,%0@+\n\t" | ||
313 | ".chip 68k\n\t" | ||
314 | "subqw #8,%2\n\t" | ||
315 | "subqw #8,%2\n\t" | ||
316 | "dbra %1,1b\n\t" | ||
317 | : "=a" (sp), "=d" (tmp) | ||
318 | : "a" (s), "0" (sp), "1" ((count - 16) / 16 - 1) | ||
319 | ); | ||
320 | } | ||
321 | |||
322 | #else | ||
323 | __asm__ __volatile__("1:\t" | ||
324 | "movel %2,%0@+\n\t" | ||
325 | "movel %2,%0@+\n\t" | ||
326 | "movel %2,%0@+\n\t" | ||
327 | "movel %2,%0@+\n\t" | ||
328 | "movel %2,%0@+\n\t" | ||
329 | "movel %2,%0@+\n\t" | ||
330 | "movel %2,%0@+\n\t" | ||
331 | "movel %2,%0@+\n\t" | ||
332 | "dbra %1,1b\n\t" | ||
333 | : "=a" (s), "=d" (tmp) | ||
334 | : "d" (data), "0" (s), "1" (count / 32 - 1) | ||
335 | ); | ||
336 | #endif | ||
337 | |||
338 | return xs; | ||
339 | } | ||
340 | |||
341 | extern void *memset(void *,int,__kernel_size_t); | ||
342 | |||
343 | #define __memset_const(s,c,count) \ | ||
344 | ((count==PAGE_SIZE) ? \ | ||
345 | __memset_page((s),(c),(count)) : \ | ||
346 | __memset_g((s),(c),(count))) | ||
347 | |||
348 | #define memset(s, c, count) \ | ||
349 | (__builtin_constant_p(count) ? \ | ||
350 | __memset_const((s),(c),(count)) : \ | ||
351 | __memset_g((s),(c),(count))) | ||
352 | 141 | ||
353 | #define __HAVE_ARCH_MEMCPY | 142 | #define __HAVE_ARCH_MEMCPY |
354 | extern void * memcpy(void *, const void *, size_t ); | 143 | extern void *memcpy(void *, const void *, __kernel_size_t); |
355 | /* | 144 | #define memcpy(d, s, n) __builtin_memcpy(d, s, n) |
356 | * __builtin_memcpy() does not handle page-sized memcpys very well, | ||
357 | * thus following the same assumptions as for page-sized memsets, this | ||
358 | * function copies page-sized areas using an unrolled loop, without | ||
359 | * considering alignment. | ||
360 | * | ||
361 | * For the 680[46]0 only kernels we use the move16 instruction instead | ||
362 | * as it writes through the data-cache, invalidating the cache-lines | ||
363 | * touched. In this way we do not use up the entire data-cache (well, | ||
364 | * half of it on the 68060) by copying a page. An unrolled loop of two | ||
365 | * move16 instructions seem to the fastest. The only caveat is that | ||
366 | * both source and destination must be 16-byte aligned, if not we fall | ||
367 | * back to the generic memcpy function. - Jes | ||
368 | */ | ||
369 | static inline void * __memcpy_page(void * to, const void * from, size_t count) | ||
370 | { | ||
371 | unsigned long tmp; | ||
372 | void *xto = to; | ||
373 | |||
374 | #ifdef CPU_M68040_OR_M68060_ONLY | ||
375 | |||
376 | if (((unsigned long) to | (unsigned long) from) & 0x0f) | ||
377 | return memcpy(to, from, count); | ||
378 | |||
379 | __asm__ __volatile__("1:\t" | ||
380 | ".chip 68040\n\t" | ||
381 | "move16 %1@+,%0@+\n\t" | ||
382 | "move16 %1@+,%0@+\n\t" | ||
383 | ".chip 68k\n\t" | ||
384 | "dbra %2,1b\n\t" | ||
385 | : "=a" (to), "=a" (from), "=d" (tmp) | ||
386 | : "0" (to), "1" (from) , "2" (count / 32 - 1) | ||
387 | ); | ||
388 | #else | ||
389 | __asm__ __volatile__("1:\t" | ||
390 | "movel %1@+,%0@+\n\t" | ||
391 | "movel %1@+,%0@+\n\t" | ||
392 | "movel %1@+,%0@+\n\t" | ||
393 | "movel %1@+,%0@+\n\t" | ||
394 | "movel %1@+,%0@+\n\t" | ||
395 | "movel %1@+,%0@+\n\t" | ||
396 | "movel %1@+,%0@+\n\t" | ||
397 | "movel %1@+,%0@+\n\t" | ||
398 | "dbra %2,1b\n\t" | ||
399 | : "=a" (to), "=a" (from), "=d" (tmp) | ||
400 | : "0" (to), "1" (from) , "2" (count / 32 - 1) | ||
401 | ); | ||
402 | #endif | ||
403 | return xto; | ||
404 | } | ||
405 | |||
406 | #define __memcpy_const(to, from, n) \ | ||
407 | ((n==PAGE_SIZE) ? \ | ||
408 | __memcpy_page((to),(from),(n)) : \ | ||
409 | __builtin_memcpy((to),(from),(n))) | ||
410 | |||
411 | #define memcpy(to, from, n) \ | ||
412 | (__builtin_constant_p(n) ? \ | ||
413 | __memcpy_const((to),(from),(n)) : \ | ||
414 | memcpy((to),(from),(n))) | ||
415 | 145 | ||
416 | #define __HAVE_ARCH_MEMMOVE | 146 | #define __HAVE_ARCH_MEMMOVE |
417 | static inline void * memmove(void * dest,const void * src, size_t n) | 147 | extern void *memmove(void *, const void *, __kernel_size_t); |
418 | { | ||
419 | void *xdest = dest; | ||
420 | size_t temp; | ||
421 | |||
422 | if (!n) | ||
423 | return xdest; | ||
424 | |||
425 | if (dest < src) | ||
426 | { | ||
427 | if ((long) dest & 1) | ||
428 | { | ||
429 | char *cdest = dest; | ||
430 | const char *csrc = src; | ||
431 | *cdest++ = *csrc++; | ||
432 | dest = cdest; | ||
433 | src = csrc; | ||
434 | n--; | ||
435 | } | ||
436 | if (n > 2 && (long) dest & 2) | ||
437 | { | ||
438 | short *sdest = dest; | ||
439 | const short *ssrc = src; | ||
440 | *sdest++ = *ssrc++; | ||
441 | dest = sdest; | ||
442 | src = ssrc; | ||
443 | n -= 2; | ||
444 | } | ||
445 | temp = n >> 2; | ||
446 | if (temp) | ||
447 | { | ||
448 | long *ldest = dest; | ||
449 | const long *lsrc = src; | ||
450 | temp--; | ||
451 | do | ||
452 | *ldest++ = *lsrc++; | ||
453 | while (temp--); | ||
454 | dest = ldest; | ||
455 | src = lsrc; | ||
456 | } | ||
457 | if (n & 2) | ||
458 | { | ||
459 | short *sdest = dest; | ||
460 | const short *ssrc = src; | ||
461 | *sdest++ = *ssrc++; | ||
462 | dest = sdest; | ||
463 | src = ssrc; | ||
464 | } | ||
465 | if (n & 1) | ||
466 | { | ||
467 | char *cdest = dest; | ||
468 | const char *csrc = src; | ||
469 | *cdest = *csrc; | ||
470 | } | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | dest = (char *) dest + n; | ||
475 | src = (const char *) src + n; | ||
476 | if ((long) dest & 1) | ||
477 | { | ||
478 | char *cdest = dest; | ||
479 | const char *csrc = src; | ||
480 | *--cdest = *--csrc; | ||
481 | dest = cdest; | ||
482 | src = csrc; | ||
483 | n--; | ||
484 | } | ||
485 | if (n > 2 && (long) dest & 2) | ||
486 | { | ||
487 | short *sdest = dest; | ||
488 | const short *ssrc = src; | ||
489 | *--sdest = *--ssrc; | ||
490 | dest = sdest; | ||
491 | src = ssrc; | ||
492 | n -= 2; | ||
493 | } | ||
494 | temp = n >> 2; | ||
495 | if (temp) | ||
496 | { | ||
497 | long *ldest = dest; | ||
498 | const long *lsrc = src; | ||
499 | temp--; | ||
500 | do | ||
501 | *--ldest = *--lsrc; | ||
502 | while (temp--); | ||
503 | dest = ldest; | ||
504 | src = lsrc; | ||
505 | } | ||
506 | if (n & 2) | ||
507 | { | ||
508 | short *sdest = dest; | ||
509 | const short *ssrc = src; | ||
510 | *--sdest = *--ssrc; | ||
511 | dest = sdest; | ||
512 | src = ssrc; | ||
513 | } | ||
514 | if (n & 1) | ||
515 | { | ||
516 | char *cdest = dest; | ||
517 | const char *csrc = src; | ||
518 | *--cdest = *--csrc; | ||
519 | } | ||
520 | } | ||
521 | return xdest; | ||
522 | } | ||
523 | 148 | ||
524 | #define __HAVE_ARCH_MEMCMP | 149 | #define __HAVE_ARCH_MEMCMP |
525 | extern int memcmp(const void * ,const void * ,size_t ); | 150 | extern int memcmp(const void *, const void *, __kernel_size_t); |
526 | #define memcmp(cs, ct, n) \ | 151 | #define memcmp(d, s, n) __builtin_memcmp(d, s, n) |
527 | (__builtin_constant_p(n) ? \ | ||
528 | __builtin_memcmp((cs),(ct),(n)) : \ | ||
529 | memcmp((cs),(ct),(n))) | ||
530 | |||
531 | #define __HAVE_ARCH_MEMCHR | ||
532 | static inline void *memchr(const void *cs, int c, size_t count) | ||
533 | { | ||
534 | /* Someone else can optimize this, I don't care - tonym@mac.linux-m68k.org */ | ||
535 | unsigned char *ret = (unsigned char *)cs; | ||
536 | for(;count>0;count--,ret++) | ||
537 | if(*ret == c) return ret; | ||
538 | |||
539 | return NULL; | ||
540 | } | ||
541 | 152 | ||
542 | #endif /* _M68K_STRING_H_ */ | 153 | #endif /* _M68K_STRING_H_ */ |