1 #ifndef _I386_STRING_I486_H_
2 #define _I386_STRING_I486_H_
5 * This string-include defines all string functions as inline
6 * functions. Use gcc. It also assumes ds=es=data space, this should be
7 * normal. Most of the string-functions are rather heavily hand-optimized,
8 * see especially strtok,strstr,str[c]spn. They should work, but are not
9 * very easy to understand. Everything is done entirely within the register
10 * set, making the functions fast and clean.
12 * Copyright (C) 1991, 1992 Linus Torvalds
13 * Revised and optimized for i486/pentium
14 * 1994/03/15 by Alberto Vignani/Davide Parodi @crf.it
16 * Split into 2 CPU specific files by Alan Cox to keep #ifdef noise down.
18 * 99/9/15 Proper reg args for newer gcc/egcs - Petkan (petkan@spct.net)
21 #define __HAVE_ARCH_STRCPY
22 extern inline char * strcpy(char * dest
,const char *src
)
24 register char *tmp
= (char *)dest
;
34 :"=r" (src
), "=r" (tmp
), "=q" (dummy
)
40 #define __HAVE_ARCH_STRNCPY
41 extern inline char * strncpy(char * dest
,const char *src
,size_t count
)
43 register char *tmp
= (char *)dest
;
56 "2:\tmovb %2,(%1)\n\t"
61 :"=r" (src
), "=r" (tmp
), "=q" (dummy
), "=r" (count
)
62 :"0" (src
), "1" (tmp
), "3" (count
)
68 #define __HAVE_ARCH_STRCAT
69 extern inline char * strcat(char * dest
,const char * src
)
71 register char *tmp
= (char *)(dest
-1);
77 "2:\tmovb (%2),%b0\n\t"
83 :"=q" (dummy
), "=r" (tmp
), "=r" (src
)
89 #define __HAVE_ARCH_STRNCAT
90 extern inline char * strncat(char * dest
,const char * src
,size_t count
)
92 register char *tmp
= (char *)(dest
-1);
108 :"=q" (dummy
), "=r" (tmp
), "=r" (src
), "=r" (count
)
109 :"1" (tmp
), "2" (src
), "3" (count
)
114 #define __HAVE_ARCH_STRCMP
115 extern inline int strcmp(const char * cs
,const char * ct
)
118 __asm__
__volatile__(
119 "\n1:\tmovb (%1),%b0\n\t"
132 :"=q" (__res
), "=r" (cs
), "=r" (ct
)
138 #define __HAVE_ARCH_STRNCMP
139 extern inline int strncmp(const char * cs
,const char * ct
,size_t count
)
142 __asm__
__volatile__(
158 :"=q" (__res
), "=r" (cs
), "=r" (ct
), "=r" (count
)
159 :"1" (cs
), "2" (ct
), "3" (count
));
163 #define __HAVE_ARCH_STRCHR
164 extern inline char * strchr(const char * s
, int c
)
166 register char * __res
;
167 __asm__
__volatile__(
169 "1:\tmovb (%1),%%al\n\t"
173 "testb %%al,%%al\n\t"
177 :"=a" (__res
), "=r" (s
)
182 #define __HAVE_ARCH_STRRCHR
183 extern inline char * strrchr(const char * s
, int c
)
186 register char * __res
;
187 __asm__
__volatile__(
193 "leal -1(%%esi),%0\n"
194 "2:\ttestb %%al,%%al\n\t"
196 :"=d" (__res
), "=&S" (d0
), "=&a" (d1
)
197 :"0" (0), "1" (s
), "2" (c
));
201 #define __HAVE_ARCH_STRSPN
202 extern inline size_t strspn(const char * cs
, const char * ct
)
205 register char * __res
;
206 __asm__
__volatile__(
215 "testb %%al,%%al\n\t"
218 "movl %%edx,%%ecx\n\t"
223 :"=S" (__res
), "=&a" (d0
), "=&c" (d1
)
224 :"0" (cs
), "1" (0), "2" (0xffffffff), "g" (ct
)
229 #define __HAVE_ARCH_STRCSPN
230 extern inline size_t strcspn(const char * cs
, const char * ct
)
233 register char * __res
;
234 __asm__
__volatile__(
243 "testb %%al,%%al\n\t"
246 "movl %%edx,%%ecx\n\t"
251 :"=S" (__res
), "=&a" (d0
), "=&c" (d1
)
252 :"0" (cs
), "1" (0), "2" (0xffffffff), "g" (ct
)
257 #define __HAVE_ARCH_STRPBRK
258 extern inline char * strpbrk(const char * cs
,const char * ct
)
261 register char * __res
;
262 __asm__
__volatile__(
271 "testb %%al,%%al\n\t"
274 "movl %%edx,%%ecx\n\t"
282 :"=S" (__res
), "=&a" (d0
), "=&c" (d1
)
283 :"0" (cs
), "1" (0), "2" (0xffffffff), "g" (ct
)
288 #define __HAVE_ARCH_STRSTR
289 extern inline char * strstr(const char * cs
,const char * ct
)
292 register char * __res
;
293 __asm__
__volatile__(
299 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
301 "1:\tmovl %4,%%edi\n\t"
302 "movl %%esi,%%eax\n\t"
303 "movl %%edx,%%ecx\n\t"
306 "je 2f\n\t" /* also works for empty string, see above */
307 "xchgl %%eax,%%esi\n\t"
309 "cmpb $0,-1(%%eax)\n\t"
311 "xorl %%eax,%%eax\n\t"
313 :"=a" (__res
), "=&c" (d0
), "=&S" (d1
)
314 :"0" (0), "1" (0xffffffff), "2" (cs
), "g" (ct
)
319 #define __HAVE_ARCH_STRLEN
320 extern inline size_t strlen(const char * s
)
323 * slightly slower on a 486, but with better chances of
324 * register allocation
326 register char dummy
, *tmp
= (char *)s
;
327 __asm__
__volatile__(
333 :"=r" (tmp
),"=q" (dummy
)
339 /* Added by Gertjan van Wingerde to make minix and sysv module work */
340 #define __HAVE_ARCH_STRNLEN
341 extern inline size_t strnlen(const char * s
, size_t count
)
345 __asm__
__volatile__(
348 "1:\tcmpb $0,(%0)\n\t"
355 :"=a" (__res
), "=&d" (d0
)
356 :"1" (count
), "c" (s
));
359 /* end of additional stuff */
361 #define __HAVE_ARCH_STRTOK
362 extern inline char * strtok(char * s
,const char * ct
)
364 register char * __res
;
365 __asm__
__volatile__(
373 "xorl %%eax,%%eax\n\t"
380 "je 7f\n\t" /* empty delimiter-string */
383 "testb %%al,%%al\n\t"
386 "movl %%edx,%%ecx\n\t"
395 "testb %%al,%%al\n\t"
398 "movl %%edx,%%ecx\n\t"
409 "6:\tcmpb $0,(%0)\n\t"
412 "7:\ttestl %0,%0\n\t"
416 :"=b" (__res
),"=S" (___strtok
)
417 :"0" (___strtok
),"1" (s
),"g" (ct
)
418 :"ax","cx","dx","di","memory");
422 #define __memcpy_c(d,s,count) \
424 __memcpy_by4((d),(s),(count)) : \
426 __memcpy_by2((d),(s),(count)) : \
427 __memcpy_g((d),(s),(count))))
429 #define __HAVE_ARCH_MEMCPY
430 #define memcpy(d,s,count) \
431 (__builtin_constant_p(count) ? \
432 __memcpy_c((d),(s),(count)) : \
433 __memcpy_g((d),(s),(count)))
436 * These ought to get tweaked to do some cache priming.
439 extern inline void * __memcpy_by4(void * to
, const void * from
, size_t n
)
441 register void *tmp
= (void *)to
;
442 register int dummy1
,dummy2
;
443 __asm__
__volatile__ (
444 "\n1:\tmovl (%2),%0\n\t"
450 :"=r" (dummy1
), "=r" (tmp
), "=r" (from
), "=r" (dummy2
)
451 :"1" (tmp
), "2" (from
), "3" (n
/4)
456 extern inline void * __memcpy_by2(void * to
, const void * from
, size_t n
)
458 register void *tmp
= (void *)to
;
459 register int dummy1
,dummy2
;
460 __asm__
__volatile__ (
462 "jz 2f\n" /* only a word */
463 "1:\tmovl (%2),%0\n\t"
469 "2:\tmovw (%2),%w0\n\t"
471 :"=r" (dummy1
), "=r" (tmp
), "=r" (from
), "=r" (dummy2
)
472 :"1" (tmp
), "2" (from
), "3" (n
/2)
477 extern inline void * __memcpy_g(void * to
, const void * from
, size_t n
)
480 register void *tmp
= (void *)to
;
481 __asm__
__volatile__ (
486 "1:\tshrl $1,%%ecx\n\t"
491 :"=&c" (d0
), "=&D" (d1
), "=&S" (d2
)
492 :"0" (n
), "1" ((long) tmp
), "2" ((long) from
)
498 #define __HAVE_ARCH_MEMMOVE
499 extern inline void * memmove(void * dest
,const void * src
, size_t n
)
502 register void *tmp
= (void *)dest
;
504 __asm__
__volatile__ (
508 :"=&c" (d0
), "=&S" (d1
), "=&D" (d2
)
509 :"0" (n
), "1" (src
), "2" (tmp
)
512 __asm__
__volatile__ (
517 :"=&c" (d0
), "=&S" (d1
), "=&D" (d2
)
518 :"0" (n
), "1" (n
-1+(const char *)src
), "2" (n
-1+(char *)tmp
)
523 extern inline int memcmp(const void * cs
,const void * ct
,size_t count
)
527 __asm__
__volatile__(
535 :"=a" (__res
), "=&S" (d0
), "=&D" (d1
), "=&c" (d2
)
536 :"0" (0), "1" (cs
), "2" (ct
), "3" (count
));
540 #define __HAVE_ARCH_MEMCHR
541 extern inline void * memchr(const void * cs
,int c
,size_t count
)
544 register void * __res
;
547 __asm__
__volatile__(
554 :"=D" (__res
), "=&c" (d0
)
555 :"a" (c
), "0" (cs
), "1" (count
));
559 #define __memset_cc(s,c,count) \
561 __memset_cc_by4((s),(c),(count)) : \
563 __memset_cc_by2((s),(c),(count)) : \
564 __memset_cg((s),(c),(count))))
566 #define __memset_gc(s,c,count) \
568 __memset_gc_by4((s),(c),(count)) : \
570 __memset_gc_by2((s),(c),(count)) : \
571 __memset_gg((s),(c),(count))))
573 #define __HAVE_ARCH_MEMSET
574 #define memset(s,c,count) \
575 (__builtin_constant_p(c) ? \
576 (__builtin_constant_p(count) ? \
577 __memset_cc((s),(c),(count)) : \
578 __memset_cg((s),(c),(count))) : \
579 (__builtin_constant_p(count) ? \
580 __memset_gc((s),(c),(count)) : \
581 __memset_gg((s),(c),(count))))
583 extern inline void * __memset_cc_by4(void * s
, char c
, size_t count
)
586 * register char *tmp = s;
588 register char *tmp
= (char *)s
;
590 __asm__
__volatile__ (
591 "\n1:\tmovl %2,(%0)\n\t"
595 :"=r" (tmp
), "=r" (dummy
)
596 :"q" (0x01010101UL
* (unsigned char) c
), "0" (tmp
), "1" (count
/4)
601 extern inline void * __memset_cc_by2(void * s
, char c
, size_t count
)
603 register void *tmp
= (void *)s
;
605 __asm__
__volatile__ (
606 "shrl $1,%1\n\t" /* may be divisible also by 4 */
608 "\n1:\tmovl %2,(%0)\n\t"
613 :"=r" (tmp
), "=r" (dummy
)
614 :"q" (0x01010101UL
* (unsigned char) c
), "0" (tmp
), "1" (count
/2)
619 extern inline void * __memset_gc_by4(void * s
, char c
, size_t count
)
621 register void *tmp
= (void *)s
;
623 __asm__
__volatile__ (
628 "1:\tmovl %0,(%1)\n\t"
632 :"=q" (c
), "=r" (tmp
), "=r" (dummy
)
633 :"0" ((unsigned) c
), "1" (tmp
), "2" (count
/4)
638 extern inline void * __memset_gc_by2(void * s
, char c
, size_t count
)
640 register void *tmp
= (void *)s
;
641 register int dummy1
,dummy2
;
642 __asm__
__volatile__ (
644 "shrl $1,%2\n\t" /* may be divisible also by 4 */
649 "1:\tmovl %0,(%1)\n\t"
654 :"=q" (dummy1
), "=r" (tmp
), "=r" (dummy2
)
655 :"0" ((unsigned) c
), "1" (tmp
), "2" (count
/2)
660 extern inline void * __memset_cg(void * s
, char c
, size_t count
)
663 register void *tmp
= (void *)s
;
664 __asm__
__volatile__ (
669 "movb %%al,(%%edi)\n"
671 :"=&c" (d0
), "=&D" (d1
)
672 :"a" (0x0101U
* (unsigned char) c
), "0" (count
), "1" (tmp
)
677 extern inline void * __memset_gg(void * s
,char c
,size_t count
)
680 register void *tmp
= (void *)s
;
681 __asm__
__volatile__ (
687 "movb %%al,(%%edi)\n"
689 :"=&c" (d0
), "=&D" (d1
), "=&D" (d2
)
690 :"0" (count
), "1" (tmp
), "2" (c
)
697 * find the first occurrence of byte 'c', or 1 past the area if none
699 #define __HAVE_ARCH_MEMSCAN
700 extern inline void * memscan(void * addr
, int c
, size_t size
)
709 : "=D" (addr
), "=c" (size
)
710 : "0" (addr
), "1" (size
), "a" (c
));