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.
19 #define __HAVE_ARCH_STRCPY
20 extern inline char * strcpy(char * dest
,const char *src
)
22 register char *tmp
= (char *)dest
;
32 :"=r" (src
), "=r" (tmp
), "=q" (dummy
)
38 #define __HAVE_ARCH_STRNCPY
39 extern inline char * strncpy(char * dest
,const char *src
,size_t count
)
41 register char *tmp
= (char *)dest
;
54 "2:\tmovb %2,(%1)\n\t"
59 :"=r" (src
), "=r" (tmp
), "=q" (dummy
), "=r" (count
)
60 :"0" (src
), "1" (tmp
), "3" (count
)
66 #define __HAVE_ARCH_STRCAT
67 extern inline char * strcat(char * dest
,const char * src
)
69 register char *tmp
= (char *)(dest
-1);
75 "2:\tmovb (%2),%b0\n\t"
81 :"=q" (dummy
), "=r" (tmp
), "=r" (src
)
87 #define __HAVE_ARCH_STRNCAT
88 extern inline char * strncat(char * dest
,const char * src
,size_t count
)
90 register char *tmp
= (char *)(dest
-1);
106 :"=q" (dummy
), "=r" (tmp
), "=r" (src
), "=r" (count
)
107 :"1" (tmp
), "2" (src
), "3" (count
)
112 #define __HAVE_ARCH_STRCMP
113 extern inline int strcmp(const char * cs
,const char * ct
)
116 __asm__
__volatile__(
117 "\n1:\tmovb (%1),%b0\n\t"
130 :"=q" (__res
), "=r" (cs
), "=r" (ct
)
136 #define __HAVE_ARCH_STRNCMP
137 extern inline int strncmp(const char * cs
,const char * ct
,size_t count
)
140 __asm__
__volatile__(
156 :"=q" (__res
), "=r" (cs
), "=r" (ct
), "=r" (count
)
157 :"1" (cs
), "2" (ct
), "3" (count
));
161 #define __HAVE_ARCH_STRCHR
162 extern inline char * strchr(const char * s
, int c
)
164 register char * __res
;
165 __asm__
__volatile__(
167 "1:\tmovb (%1),%%al\n\t"
171 "testb %%al,%%al\n\t"
175 :"=a" (__res
), "=r" (s
)
180 #define __HAVE_ARCH_STRRCHR
181 extern inline char * strrchr(const char * s
, int c
)
183 register char * __res
;
184 __asm__
__volatile__(
190 "leal -1(%%esi),%0\n"
191 "2:\ttestb %%al,%%al\n\t"
193 :"=d" (__res
):"0" (0),"S" (s
),"a" (c
):"ax","si");
197 #define __HAVE_ARCH_STRSPN
198 extern inline size_t strspn(const char * cs
, const char * ct
)
200 register char * __res
;
201 __asm__
__volatile__(
210 "testb %%al,%%al\n\t"
213 "movl %%edx,%%ecx\n\t"
218 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
219 :"ax","cx","dx","di");
223 #define __HAVE_ARCH_STRCSPN
224 extern inline size_t strcspn(const char * cs
, const char * ct
)
226 register char * __res
;
227 __asm__
__volatile__(
236 "testb %%al,%%al\n\t"
239 "movl %%edx,%%ecx\n\t"
244 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
245 :"ax","cx","dx","di");
249 #define __HAVE_ARCH_STRPBRK
250 extern inline char * strpbrk(const char * cs
,const char * ct
)
252 register char * __res
;
253 __asm__
__volatile__(
262 "testb %%al,%%al\n\t"
265 "movl %%edx,%%ecx\n\t"
273 :"=S" (__res
):"a" (0),"c" (0xffffffff),"0" (cs
),"g" (ct
)
274 :"ax","cx","dx","di");
278 #define __HAVE_ARCH_STRSTR
279 extern inline char * strstr(const char * cs
,const char * ct
)
281 register char * __res
;
282 __asm__
__volatile__(
288 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
290 "1:\tmovl %4,%%edi\n\t"
291 "movl %%esi,%%eax\n\t"
292 "movl %%edx,%%ecx\n\t"
295 "je 2f\n\t" /* also works for empty string, see above */
296 "xchgl %%eax,%%esi\n\t"
298 "cmpb $0,-1(%%eax)\n\t"
300 "xorl %%eax,%%eax\n\t"
302 :"=a" (__res
):"0" (0),"c" (0xffffffff),"S" (cs
),"g" (ct
)
303 :"cx","dx","di","si");
307 #define __HAVE_ARCH_STRLEN
308 extern inline size_t strlen(const char * s
)
311 * slightly slower on a 486, but with better chances of
312 * register allocation
314 register char dummy
, *tmp
= (char *)s
;
315 __asm__
__volatile__(
321 :"=r" (tmp
),"=q" (dummy
)
327 /* Added by Gertjan van Wingerde to make minix and sysv module work */
328 #define __HAVE_ARCH_STRNLEN
329 extern inline size_t strnlen(const char * s
, size_t count
)
332 __asm__
__volatile__(
335 "1:\tcmpb $0,(%0)\n\t"
347 /* end of additional stuff */
349 #define __HAVE_ARCH_STRTOK
350 extern inline char * strtok(char * s
,const char * ct
)
352 register char * __res
;
353 __asm__
__volatile__(
361 "xorl %%eax,%%eax\n\t"
368 "je 7f\n\t" /* empty delimiter-string */
371 "testb %%al,%%al\n\t"
374 "movl %%edx,%%ecx\n\t"
383 "testb %%al,%%al\n\t"
386 "movl %%edx,%%ecx\n\t"
397 "6:\tcmpb $0,(%0)\n\t"
400 "7:\ttestl %0,%0\n\t"
404 :"=b" (__res
),"=S" (___strtok
)
405 :"0" (___strtok
),"1" (s
),"g" (ct
)
406 :"ax","cx","dx","di","memory");
410 #define __memcpy_c(d,s,count) \
412 __memcpy_by4((d),(s),(count)) : \
414 __memcpy_by2((d),(s),(count)) : \
415 __memcpy_g((d),(s),(count))))
417 #define __HAVE_ARCH_MEMCPY
418 #define memcpy(d,s,count) \
419 (__builtin_constant_p(count) ? \
420 __memcpy_c((d),(s),(count)) : \
421 __memcpy_g((d),(s),(count)))
424 * These ought to get tweaked to do some cache priming.
427 extern inline void * __memcpy_by4(void * to
, const void * from
, size_t n
)
429 register void *tmp
= (void *)to
;
430 register int dummy1
,dummy2
;
431 __asm__
__volatile__ (
432 "\n1:\tmovl (%2),%0\n\t"
438 :"=r" (dummy1
), "=r" (tmp
), "=r" (from
), "=r" (dummy2
)
439 :"1" (tmp
), "2" (from
), "3" (n
/4)
444 extern inline void * __memcpy_by2(void * to
, const void * from
, size_t n
)
446 register void *tmp
= (void *)to
;
447 register int dummy1
,dummy2
;
448 __asm__
__volatile__ (
450 "jz 2f\n" /* only a word */
451 "1:\tmovl (%2),%0\n\t"
457 "2:\tmovw (%2),%w0\n\t"
459 :"=r" (dummy1
), "=r" (tmp
), "=r" (from
), "=r" (dummy2
)
460 :"1" (tmp
), "2" (from
), "3" (n
/2)
465 extern inline void * __memcpy_g(void * to
, const void * from
, size_t n
)
467 register void *tmp
= (void *)to
;
468 __asm__
__volatile__ (
473 "1:\tshrl $1,%%ecx\n\t"
479 :"c" (n
),"D" ((long) tmp
),"S" ((long) from
)
480 :"cx","di","si","memory");
485 #define __HAVE_ARCH_MEMMOVE
486 extern inline void * memmove(void * dest
,const void * src
, size_t n
)
488 register void *tmp
= (void *)dest
;
490 __asm__
__volatile__ (
495 :"c" (n
),"S" (src
),"D" (tmp
)
498 __asm__
__volatile__ (
504 :"c" (n
), "S" (n
-1+(const char *)src
), "D" (n
-1+(char *)tmp
)
505 :"cx","si","di","memory");
509 extern inline int memcmp(const void * cs
,const void * ct
,size_t count
)
512 __asm__
__volatile__(
520 :"=abd" (__res
):"0" (0),"S" (cs
),"D" (ct
),"c" (count
)
525 #define __HAVE_ARCH_MEMCHR
526 extern inline void * memchr(const void * cs
,int c
,size_t count
)
528 register void * __res
;
531 __asm__
__volatile__(
538 :"=D" (__res
):"a" (c
),"D" (cs
),"c" (count
)
543 #define __memset_cc(s,c,count) \
545 __memset_cc_by4((s),(c),(count)) : \
547 __memset_cc_by2((s),(c),(count)) : \
548 __memset_cg((s),(c),(count))))
550 #define __memset_gc(s,c,count) \
552 __memset_gc_by4((s),(c),(count)) : \
554 __memset_gc_by2((s),(c),(count)) : \
555 __memset_gg((s),(c),(count))))
557 #define __HAVE_ARCH_MEMSET
558 #define memset(s,c,count) \
559 (__builtin_constant_p(c) ? \
560 (__builtin_constant_p(count) ? \
561 __memset_cc((s),(c),(count)) : \
562 __memset_cg((s),(c),(count))) : \
563 (__builtin_constant_p(count) ? \
564 __memset_gc((s),(c),(count)) : \
565 __memset_gg((s),(c),(count))))
567 extern inline void * __memset_cc_by4(void * s
, char c
, size_t count
)
570 * register char *tmp = s;
572 register char *tmp
= (char *)s
;
574 __asm__
__volatile__ (
575 "\n1:\tmovl %2,(%0)\n\t"
579 :"=r" (tmp
), "=r" (dummy
)
580 :"q" (0x01010101UL
* (unsigned char) c
), "0" (tmp
), "1" (count
/4)
585 extern inline void * __memset_cc_by2(void * s
, char c
, size_t count
)
587 register void *tmp
= (void *)s
;
589 __asm__
__volatile__ (
590 "shrl $1,%1\n\t" /* may be divisible also by 4 */
592 "\n1:\tmovl %2,(%0)\n\t"
597 :"=r" (tmp
), "=r" (dummy
)
598 :"q" (0x01010101UL
* (unsigned char) c
), "0" (tmp
), "1" (count
/2)
603 extern inline void * __memset_gc_by4(void * s
, char c
, size_t count
)
605 register void *tmp
= (void *)s
;
607 __asm__
__volatile__ (
612 "1:\tmovl %0,(%1)\n\t"
616 :"=q" (c
), "=r" (tmp
), "=r" (dummy
)
617 :"0" ((unsigned) c
), "1" (tmp
), "2" (count
/4)
622 extern inline void * __memset_gc_by2(void * s
, char c
, size_t count
)
624 register void *tmp
= (void *)s
;
625 register int dummy1
,dummy2
;
626 __asm__
__volatile__ (
628 "shrl $1,%2\n\t" /* may be divisible also by 4 */
633 "1:\tmovl %0,(%1)\n\t"
638 :"=q" (dummy1
), "=r" (tmp
), "=r" (dummy2
)
639 :"0" ((unsigned) c
), "1" (tmp
), "2" (count
/2)
644 extern inline void * __memset_cg(void * s
, char c
, size_t count
)
646 register void *tmp
= (void *)s
;
647 __asm__
__volatile__ (
652 "movb %%al,(%%edi)\n"
655 :"c" (count
),"D" (tmp
), "a" (0x0101U
* (unsigned char) c
)
656 :"cx","di","memory");
660 extern inline void * __memset_gg(void * s
,char c
,size_t count
)
662 register void *tmp
= (void *)s
;
663 __asm__
__volatile__ (
669 "movb %%al,(%%edi)\n"
672 :"c" (count
),"D" (tmp
), "a" (c
)
673 :"cx","di","memory");
679 * find the first occurrence of byte 'c', or 1 past the area if none
681 #define __HAVE_ARCH_MEMSCAN
682 extern inline void * memscan(void * addr
, int c
, size_t size
)
691 : "=D" (addr
), "=c" (size
)
692 : "0" (addr
), "1" (size
), "a" (c
));