This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / include / asm-i386 / string.h
1 #ifndef _I386_STRING_H_
2 #define _I386_STRING_H_
3
4 #ifdef __KERNEL__
5 #include <linux/config.h>
6 /*
7  * On a 486 or Pentium, we are better off not using the
8  * byte string operations. But on a 386 or a PPro the
9  * byte string ops are faster than doing it by hand
10  * (MUCH faster on a Pentium).
11  */
12
13 /*
14  * This string-include defines all string functions as inline
15  * functions. Use gcc. It also assumes ds=es=data space, this should be
16  * normal. Most of the string-functions are rather heavily hand-optimized,
17  * see especially strsep,strstr,str[c]spn. They should work, but are not
18  * very easy to understand. Everything is done entirely within the register
19  * set, making the functions fast and clean. String instructions have been
20  * used through-out, making for "slightly" unclear code :-)
21  *
22  *              NO Copyright (C) 1991, 1992 Linus Torvalds,
23  *              consider these trivial functions to be PD.
24  */
25
26 /* AK: in fact I bet it would be better to move this stuff all out of line.
27  */
28 #if !defined(IN_STRING_C)
29
30 static inline char * strcpy(char * dest,const char *src)
31 {
32 int d0, d1, d2;
33 __asm__ __volatile__(
34         "1:\tlodsb\n\t"
35         "stosb\n\t"
36         "testb %%al,%%al\n\t"
37         "jne 1b"
38         : "=&S" (d0), "=&D" (d1), "=&a" (d2)
39         :"0" (src),"1" (dest) : "memory");
40 return dest;
41 }
42
43 static inline char * strncpy(char * dest,const char *src,size_t count)
44 {
45 int d0, d1, d2, d3;
46 __asm__ __volatile__(
47         "1:\tdecl %2\n\t"
48         "js 2f\n\t"
49         "lodsb\n\t"
50         "stosb\n\t"
51         "testb %%al,%%al\n\t"
52         "jne 1b\n\t"
53         "rep\n\t"
54         "stosb\n"
55         "2:"
56         : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
57         :"0" (src),"1" (dest),"2" (count) : "memory");
58 return dest;
59 }
60
61 /*
62  * This is a more generic variant of strncpy_count() suitable for
63  * implementing string-access routines with all sorts of return
64  * code semantics. It's used by mm/usercopy.c.
65  */
66 static inline size_t strncpy_count(char * dest,const char *src,size_t count)
67 {
68         __asm__ __volatile__(
69
70         "1:\tdecl %0\n\t"
71         "js 2f\n\t"
72         "lodsb\n\t"
73         "stosb\n\t"
74         "testb %%al,%%al\n\t"
75         "jne 1b\n\t"
76         "2:"
77         "incl %0"
78         : "=c" (count)
79         :"S" (src),"D" (dest),"0" (count) : "memory");
80
81         return count;
82 }
83
84 static inline char * strcat(char * dest,const char * src)
85 {
86 int d0, d1, d2, d3;
87 __asm__ __volatile__(
88         "repne\n\t"
89         "scasb\n\t"
90         "decl %1\n"
91         "1:\tlodsb\n\t"
92         "stosb\n\t"
93         "testb %%al,%%al\n\t"
94         "jne 1b"
95         : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
96         : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu):"memory");
97 return dest;
98 }
99
100 static inline char * strncat(char * dest,const char * src,size_t count)
101 {
102 int d0, d1, d2, d3;
103 __asm__ __volatile__(
104         "repne\n\t"
105         "scasb\n\t"
106         "decl %1\n\t"
107         "movl %8,%3\n"
108         "1:\tdecl %3\n\t"
109         "js 2f\n\t"
110         "lodsb\n\t"
111         "stosb\n\t"
112         "testb %%al,%%al\n\t"
113         "jne 1b\n"
114         "2:\txorl %2,%2\n\t"
115         "stosb"
116         : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
117         : "0" (src),"1" (dest),"2" (0),"3" (0xffffffffu), "g" (count)
118         : "memory");
119 return dest;
120 }
121
122 static inline int strcmp(const char * cs,const char * ct)
123 {
124 int d0, d1;
125 register int __res;
126 __asm__ __volatile__(
127         "1:\tlodsb\n\t"
128         "scasb\n\t"
129         "jne 2f\n\t"
130         "testb %%al,%%al\n\t"
131         "jne 1b\n\t"
132         "xorl %%eax,%%eax\n\t"
133         "jmp 3f\n"
134         "2:\tsbbl %%eax,%%eax\n\t"
135         "orb $1,%%al\n"
136         "3:"
137         :"=a" (__res), "=&S" (d0), "=&D" (d1)
138                      :"1" (cs),"2" (ct));
139 return __res;
140 }
141
142 static inline int strncmp(const char * cs,const char * ct,size_t count)
143 {
144 register int __res;
145 int d0, d1, d2;
146 __asm__ __volatile__(
147         "1:\tdecl %3\n\t"
148         "js 2f\n\t"
149         "lodsb\n\t"
150         "scasb\n\t"
151         "jne 3f\n\t"
152         "testb %%al,%%al\n\t"
153         "jne 1b\n"
154         "2:\txorl %%eax,%%eax\n\t"
155         "jmp 4f\n"
156         "3:\tsbbl %%eax,%%eax\n\t"
157         "orb $1,%%al\n"
158         "4:"
159                      :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
160                      :"1" (cs),"2" (ct),"3" (count));
161 return __res;
162 }
163
164 static inline char * strchr(const char * s, int c)
165 {
166 int d0;
167 register char * __res;
168 __asm__ __volatile__(
169         "movb %%al,%%ah\n"
170         "1:\tlodsb\n\t"
171         "cmpb %%ah,%%al\n\t"
172         "je 2f\n\t"
173         "testb %%al,%%al\n\t"
174         "jne 1b\n\t"
175         "movl $1,%1\n"
176         "2:\tmovl %1,%0\n\t"
177         "decl %0"
178         :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
179 return __res;
180 }
181
182 static inline char * strrchr(const char * s, int c)
183 {
184 int d0, d1;
185 register char * __res;
186 __asm__ __volatile__(
187         "movb %%al,%%ah\n"
188         "1:\tlodsb\n\t"
189         "cmpb %%ah,%%al\n\t"
190         "jne 2f\n\t"
191         "leal -1(%%esi),%0\n"
192         "2:\ttestb %%al,%%al\n\t"
193         "jne 1b"
194         :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
195 return __res;
196 }
197
198 #endif
199
200 #define __HAVE_ARCH_STRLEN
201 static inline size_t strlen(const char * s)
202 {
203 int d0;
204 register int __res;
205 __asm__ __volatile__(
206         "repne\n\t"
207         "scasb\n\t"
208         "notl %0\n\t"
209         "decl %0"
210         :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffffu));
211 return __res;
212 }
213
214 static inline void * __memcpy(void * to, const void * from, size_t n)
215 {
216 int d0, d1, d2;
217 __asm__ __volatile__(
218         "rep ; movsl\n\t"
219         "testb $2,%b4\n\t"
220         "je 1f\n\t"
221         "movsw\n"
222         "1:\ttestb $1,%b4\n\t"
223         "je 2f\n\t"
224         "movsb\n"
225         "2:"
226         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
227         :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
228         : "memory");
229 return (to);
230 }
231
232 /*
233  * This looks horribly ugly, but the compiler can optimize it totally,
234  * as the count is constant.
235  */
236 static inline void * __constant_memcpy(void * to, const void * from, size_t n)
237 {
238         if (n <= 128)
239                 return __builtin_memcpy(to, from, n);
240
241 #define COMMON(x) \
242 __asm__ __volatile__( \
243         "rep ; movsl" \
244         x \
245         : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
246         : "0" (n/4),"1" ((long) to),"2" ((long) from) \
247         : "memory");
248 {
249         int d0, d1, d2;
250         switch (n % 4) {
251                 case 0: COMMON(""); return to;
252                 case 1: COMMON("\n\tmovsb"); return to;
253                 case 2: COMMON("\n\tmovsw"); return to;
254                 default: COMMON("\n\tmovsw\n\tmovsb"); return to;
255         }
256 }
257   
258 #undef COMMON
259 }
260
261 #define __HAVE_ARCH_MEMCPY
262
263 #ifdef CONFIG_X86_USE_3DNOW
264
265 #include <asm/mmx.h>
266
267 /*
268  *      This CPU favours 3DNow strongly (eg AMD Athlon)
269  */
270
271 static inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
272 {
273         if (len < 512)
274                 return __constant_memcpy(to, from, len);
275         return _mmx_memcpy(to, from, len);
276 }
277
278 static __inline__ void *__memcpy3d(void *to, const void *from, size_t len)
279 {
280         if (len < 512)
281                 return __memcpy(to, from, len);
282         return _mmx_memcpy(to, from, len);
283 }
284
285 #define memcpy(t, f, n) \
286 (__builtin_constant_p(n) ? \
287  __constant_memcpy3d((t),(f),(n)) : \
288  __memcpy3d((t),(f),(n)))
289
290 #else
291
292 /*
293  *      No 3D Now!
294  */
295  
296 #define memcpy(t, f, n) \
297 (__builtin_constant_p(n) ? \
298  __constant_memcpy((t),(f),(n)) : \
299  __memcpy((t),(f),(n)))
300
301 #endif
302
303 /*
304  * struct_cpy(x,y), copy structure *x into (matching structure) *y.
305  *
306  * We get link-time errors if the structure sizes do not match.
307  * There is no runtime overhead, it's all optimized away at
308  * compile time.
309  */
310 extern void __struct_cpy_bug (void);
311
312 #define struct_cpy(x,y)                         \
313 ({                                              \
314         if (sizeof(*(x)) != sizeof(*(y)))       \
315                 __struct_cpy_bug();             \
316         memcpy(x, y, sizeof(*(x)));             \
317 })
318
319 #define __HAVE_ARCH_MEMMOVE
320 static inline void * memmove(void * dest,const void * src, size_t n)
321 {
322 int d0, d1, d2;
323 if (dest<src) {
324         memcpy(dest,src,n);
325 } else
326 __asm__ __volatile__(
327         "std\n\t"
328         "rep\n\t"
329         "movsb\n\t"
330         "cld"
331         : "=&c" (d0), "=&S" (d1), "=&D" (d2)
332         :"0" (n),
333          "1" (n-1+(const char *)src),
334          "2" (n-1+(char *)dest)
335         :"memory");
336 return dest;
337 }
338
339 #define memcmp __builtin_memcmp
340
341 #define __HAVE_ARCH_MEMCHR
342 static inline void * memchr(const void * cs,int c,size_t count)
343 {
344 int d0;
345 register void * __res;
346 if (!count)
347         return NULL;
348 __asm__ __volatile__(
349         "repne\n\t"
350         "scasb\n\t"
351         "je 1f\n\t"
352         "movl $1,%0\n"
353         "1:\tdecl %0"
354         :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
355 return __res;
356 }
357
358 static inline void * __memset_generic(void * s, char c,size_t count)
359 {
360 int d0, d1;
361 __asm__ __volatile__(
362         "rep\n\t"
363         "stosb"
364         : "=&c" (d0), "=&D" (d1)
365         :"a" (c),"1" (s),"0" (count)
366         :"memory");
367 return s;
368 }
369
370 /* we might want to write optimized versions of these later */
371 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
372
373 /*
374  * memset(x,0,y) is a reasonably common thing to do, so we want to fill
375  * things 32 bits at a time even when we don't know the size of the
376  * area at compile-time..
377  */
378 static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
379 {
380 int d0, d1;
381 __asm__ __volatile__(
382         "rep ; stosl\n\t"
383         "testb $2,%b3\n\t"
384         "je 1f\n\t"
385         "stosw\n"
386         "1:\ttestb $1,%b3\n\t"
387         "je 2f\n\t"
388         "stosb\n"
389         "2:"
390         : "=&c" (d0), "=&D" (d1)
391         :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
392         :"memory");
393 return (s);     
394 }
395
396 /* Added by Gertjan van Wingerde to make minix and sysv module work */
397 #define __HAVE_ARCH_STRNLEN
398 static inline size_t strnlen(const char * s, size_t count)
399 {
400 int d0;
401 register int __res;
402 __asm__ __volatile__(
403         "movl %2,%0\n\t"
404         "jmp 2f\n"
405         "1:\tcmpb $0,(%0)\n\t"
406         "je 3f\n\t"
407         "incl %0\n"
408         "2:\tdecl %1\n\t"
409         "cmpl $-1,%1\n\t"
410         "jne 1b\n"
411         "3:\tsubl %2,%0"
412         :"=a" (__res), "=&d" (d0)
413         :"c" (s),"1" (count));
414 return __res;
415 }
416 /* end of additional stuff */
417
418 #define __HAVE_ARCH_STRSTR
419
420 extern char *strstr(const char *cs, const char *ct);
421
422 /*
423  * This looks horribly ugly, but the compiler can optimize it totally,
424  * as we by now know that both pattern and count is constant..
425  */
426 static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
427 {
428         switch (count) {
429                 case 0:
430                         return s;
431                 case 1:
432                         *(unsigned char *)s = pattern;
433                         return s;
434                 case 2:
435                         *(unsigned short *)s = pattern;
436                         return s;
437                 case 3:
438                         *(unsigned short *)s = pattern;
439                         *(2+(unsigned char *)s) = pattern;
440                         return s;
441                 case 4:
442                         *(unsigned long *)s = pattern;
443                         return s;
444         }
445 #define COMMON(x) \
446 __asm__  __volatile__( \
447         "rep ; stosl" \
448         x \
449         : "=&c" (d0), "=&D" (d1) \
450         : "a" (pattern),"0" (count/4),"1" ((long) s) \
451         : "memory")
452 {
453         int d0, d1;
454         switch (count % 4) {
455                 case 0: COMMON(""); return s;
456                 case 1: COMMON("\n\tstosb"); return s;
457                 case 2: COMMON("\n\tstosw"); return s;
458                 default: COMMON("\n\tstosw\n\tstosb"); return s;
459         }
460 }
461   
462 #undef COMMON
463 }
464
465 #define __constant_c_x_memset(s, c, count) \
466 (__builtin_constant_p(count) ? \
467  __constant_c_and_count_memset((s),(c),(count)) : \
468  __constant_c_memset((s),(c),(count)))
469
470 #define __memset(s, c, count) \
471 (__builtin_constant_p(count) ? \
472  __constant_count_memset((s),(c),(count)) : \
473  __memset_generic((s),(c),(count)))
474
475 #define __HAVE_ARCH_MEMSET
476 #define memset(s, c, count) \
477 (__builtin_constant_p(c) ? \
478  __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
479  __memset((s),(c),(count)))
480
481 /*
482  * find the first occurrence of byte 'c', or 1 past the area if none
483  */
484 #define __HAVE_ARCH_MEMSCAN
485 static inline void * memscan(void * addr, int c, size_t size)
486 {
487         if (!size)
488                 return addr;
489         __asm__("repnz; scasb\n\t"
490                 "jnz 1f\n\t"
491                 "dec %%edi\n"
492                 "1:"
493                 : "=D" (addr), "=c" (size)
494                 : "0" (addr), "1" (size), "a" (c));
495         return addr;
496 }
497
498 #endif /* __KERNEL__ */
499
500 #endif