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