~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-m68k/string.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.