1 #ifndef _I386_STRING_H_
2 #define _I386_STRING_H_
5 #include <internal/types.h>
8 #ifndef _INTERNAL_STDDEF_H
9 #include <internal/stddef.h>
13 * On a 486 or Pentium, we are better off not using the
14 * byte string operations. But on a 386 or a PPro the
15 * byte string ops are faster than doing it by hand
16 * (MUCH faster on a Pentium).
18 * Also, the byte strings actually work correctly. Forget
19 * the i486 routines for now as they may be broken..
21 #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
22 #include <asm/string-486.h>
26 * This string-include defines all string functions as inline
27 * functions. Use gcc. It also assumes ds=es=data space, this should be
28 * normal. Most of the string-functions are rather heavily hand-optimized,
29 * see especially strtok,strstr,str[c]spn. They should work, but are not
30 * very easy to understand. Everything is done entirely within the register
31 * set, making the functions fast and clean. String instructions have been
32 * used through-out, making for "slightly" unclear code :-)
34 * NO Copyright (C) 1991, 1992 Linus Torvalds,
35 * consider these trivial functions to be PD.
38 #define __HAVE_ARCH_STRCPY
39 extern inline char * strcpy(char * dest
,const char *src
)
48 : "=&S" (d0
), "=&D" (d1
), "=&a" (d2
)
49 :"0" (src
),"1" (dest
) : "memory");
53 #define __HAVE_ARCH_STRNCPY
54 extern inline char * strncpy(char * dest
,const char *src
,size_t count
)
68 : "=&S" (d0
), "=&D" (d1
), "=&c" (d2
), "=&a" (d3
)
69 :"0" (src
),"1" (dest
),"2" (count
) : "memory");
73 #define __HAVE_ARCH_STRCAT
74 extern inline char * strcat(char * dest
,const char * src
)
86 : "=&S" (d0
), "=&D" (d1
), "=&a" (d2
), "=&c" (d3
)
87 : "0" (src
), "1" (dest
), "2" (0), "3" (0xffffffff):"memory");
91 #define __HAVE_ARCH_STRNCAT
92 extern inline char * strncat(char * dest
,const char * src
,size_t count
)
105 "testb %%al,%%al\n\t"
109 : "=&S" (d0
), "=&D" (d1
), "=&a" (d2
), "=&c" (d3
)
110 : "0" (src
),"1" (dest
),"2" (0),"3" (0xffffffff), "g" (count
)
115 #define __HAVE_ARCH_STRCMP
116 extern inline int strcmp(const char * cs
,const char * ct
)
120 __asm__
__volatile__(
125 "testb %%al,%%al\n\t"
127 "xorl %%eax,%%eax\n\t"
129 "2:\tsbbl %%eax,%%eax\n\t"
132 :"=a" (__res
), "=&S" (d0
), "=&D" (d1
)
137 #define __HAVE_ARCH_STRNCMP
138 extern inline int strncmp(const char * cs
,const char * ct
,size_t count
)
142 __asm__
__volatile__(
149 "testb %%al,%%al\n\t"
151 "2:\txorl %%eax,%%eax\n\t"
153 "3:\tsbbl %%eax,%%eax\n\t"
156 :"=a" (__res
), "=&S" (d0
), "=&D" (d1
), "=&c" (d2
)
157 :"1" (cs
),"2" (ct
),"3" (count
));
161 #define __HAVE_ARCH_STRCHR
162 extern inline char * strchr(const char * s
, int c
)
165 register char * __res
;
166 __asm__
__volatile__(
172 "testb %%al,%%al\n\t"
177 :"=a" (__res
), "=&S" (d0
) : "1" (s
),"0" (c
));
181 #define __HAVE_ARCH_STRRCHR
182 extern inline char * strrchr(const char * s
, int c
)
185 register char * __res
;
186 __asm__
__volatile__(
192 "leal -1(%%esi),%0\n"
193 "2:\ttestb %%al,%%al\n\t"
195 :"=g" (__res
), "=&S" (d0
), "=&a" (d1
) :"0" (0),"1" (s
),"2" (c
));
199 #define __HAVE_ARCH_STRLEN
200 extern inline size_t strlen(const char * s
)
204 __asm__
__volatile__(
210 :"=c" (__res
), "=&D" (d0
) :"1" (s
),"a" (0), "0" (0xffffffff));
214 extern inline void * __memcpy(void * to
, const void * from
, size_t n
)
217 __asm__
__volatile__(
223 "1:\ttestb $1,%b4\n\t"
227 : "=&c" (d0
), "=&D" (d1
), "=&S" (d2
)
228 :"0" (n
/4), "q" (n
),"1" ((long) to
),"2" ((long) from
)
234 * This looks horribly ugly, but the compiler can optimize it totally,
235 * as the count is constant.
237 extern inline void * __constant_memcpy(void * to
, const void * from
, size_t n
)
243 *(unsigned char *)to
= *(const unsigned char *)from
;
246 *(unsigned short *)to
= *(const unsigned short *)from
;
249 *(unsigned short *)to
= *(const unsigned short *)from
;
250 *(2+(unsigned char *)to
) = *(2+(const unsigned char *)from
);
253 *(unsigned long *)to
= *(const unsigned long *)from
;
255 case 6: /* for Ethernet addresses */
256 *(unsigned long *)to
= *(const unsigned long *)from
;
257 *(2+(unsigned short *)to
) = *(2+(const unsigned short *)from
);
260 *(unsigned long *)to
= *(const unsigned long *)from
;
261 *(1+(unsigned long *)to
) = *(1+(const unsigned long *)from
);
264 *(unsigned long *)to
= *(const unsigned long *)from
;
265 *(1+(unsigned long *)to
) = *(1+(const unsigned long *)from
);
266 *(2+(unsigned long *)to
) = *(2+(const unsigned long *)from
);
269 *(unsigned long *)to
= *(const unsigned long *)from
;
270 *(1+(unsigned long *)to
) = *(1+(const unsigned long *)from
);
271 *(2+(unsigned long *)to
) = *(2+(const unsigned long *)from
);
272 *(3+(unsigned long *)to
) = *(3+(const unsigned long *)from
);
275 *(unsigned long *)to
= *(const unsigned long *)from
;
276 *(1+(unsigned long *)to
) = *(1+(const unsigned long *)from
);
277 *(2+(unsigned long *)to
) = *(2+(const unsigned long *)from
);
278 *(3+(unsigned long *)to
) = *(3+(const unsigned long *)from
);
279 *(4+(unsigned long *)to
) = *(4+(const unsigned long *)from
);
283 __asm__ __volatile__( \
287 : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
288 : "0" (n/4),"1" ((long) to),"2" ((long) from) \
293 case 0: COMMON(""); return to
;
294 case 1: COMMON("\n\tmovsb"); return to
;
295 case 2: COMMON("\n\tmovsw"); return to
;
296 default: COMMON("\n\tmovsw\n\tmovsb"); return to
;
303 #define __HAVE_ARCH_MEMCPY
304 #define memcpy(t, f, n) \
305 (__builtin_constant_p(n) ? \
306 __constant_memcpy((t),(f),(n)) : \
307 __memcpy((t),(f),(n)))
309 #define __HAVE_ARCH_MEMMOVE
310 extern inline void * memmove(void * dest
,const void * src
, size_t n
)
314 __asm__
__volatile__(
318 : "=&c" (d0
), "=&S" (d1
), "=&D" (d2
)
319 :"0" (n
),"1" (src
),"2" (dest
)
322 __asm__
__volatile__(
327 : "=&c" (d0
), "=&S" (d1
), "=&D" (d2
)
329 "1" (n
-1+(const char *)src
),
330 "2" (n
-1+(char *)dest
)
335 #define memcmp __builtin_memcmp
337 #define __HAVE_ARCH_MEMCHR
338 extern inline void * memchr(const void * cs
,int c
,size_t count
)
341 register void * __res
;
344 __asm__
__volatile__(
351 :"=D" (__res
), "=&c" (d0
) : "a" (c
),"0" (cs
),"1" (count
));
355 extern inline void * __memset_generic(void * s
, char c
,size_t count
)
358 __asm__
__volatile__(
362 : "=&c" (d0
), "=&D" (d1
)
363 :"a" (c
),"1" (s
),"0" (count
)
368 /* we might want to write optimized versions of these later */
369 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
372 * memset(x,0,y) is a reasonably common thing to do, so we want to fill
373 * things 32 bits at a time even when we don't know the size of the
374 * area at compile-time..
376 extern inline void * __constant_c_memset(void * s
, unsigned long c
, size_t count
)
379 __asm__
__volatile__(
385 "1:\ttestb $1,%b3\n\t"
389 : "=&c" (d0
), "=&D" (d1
)
390 :"a" (c
), "q" (count
), "0" (count
/4), "1" ((long) s
)
395 /* Added by Gertjan van Wingerde to make minix and sysv module work */
396 #define __HAVE_ARCH_STRNLEN
397 extern inline size_t strnlen(const char * s
, size_t count
)
401 __asm__
__volatile__(
404 "1:\tcmpb $0,(%0)\n\t"
411 :"=a" (__res
), "=&d" (d0
)
412 :"c" (s
),"1" (count
));
415 /* end of additional stuff */
418 * This looks horribly ugly, but the compiler can optimize it totally,
419 * as we by now know that both pattern and count is constant..
421 extern inline void * __constant_c_and_count_memset(void * s
, unsigned long pattern
, size_t count
)
427 *(unsigned char *)s
= pattern
;
430 *(unsigned short *)s
= pattern
;
433 *(unsigned short *)s
= pattern
;
434 *(2+(unsigned char *)s
) = pattern
;
437 *(unsigned long *)s
= pattern
;
441 __asm__ __volatile__("cld\n\t" \
444 : "=&c" (d0), "=&D" (d1) \
445 : "a" (pattern),"0" (count/4),"1" ((long) s) \
450 case 0: COMMON(""); return s
;
451 case 1: COMMON("\n\tstosb"); return s
;
452 case 2: COMMON("\n\tstosw"); return s
;
453 default: COMMON("\n\tstosw\n\tstosb"); return s
;
460 #define __constant_c_x_memset(s, c, count) \
461 (__builtin_constant_p(count) ? \
462 __constant_c_and_count_memset((s),(c),(count)) : \
463 __constant_c_memset((s),(c),(count)))
465 #define __memset(s, c, count) \
466 (__builtin_constant_p(count) ? \
467 __constant_count_memset((s),(c),(count)) : \
468 __memset_generic((s),(c),(count)))
470 #define __HAVE_ARCH_MEMSET
471 #define memset(s, c, count) \
472 (__builtin_constant_p(c) ? \
473 __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
474 __memset((s),(c),(count)))
477 * find the first occurrence of byte 'c', or 1 past the area if none
479 #define __HAVE_ARCH_MEMSCAN
480 extern inline void * memscan(void * addr
, int c
, size_t size
)
489 : "=D" (addr
), "=c" (size
)
490 : "0" (addr
), "1" (size
), "a" (c
));