1#ifndef _I386_STRING_H_
2#define _I386_STRING_H_
3
4#ifdef __KERNEL__
5#include <linux/config.h>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#define __HAVE_ARCH_STRCPY
27static inline char * strcpy(char * dest,const char *src)
28{
29int d0, d1, d2;
30__asm__ __volatile__(
31 "1:\tlodsb\n\t"
32 "stosb\n\t"
33 "testb %%al,%%al\n\t"
34 "jne 1b"
35 : "=&S" (d0), "=&D" (d1), "=&a" (d2)
36 :"0" (src),"1" (dest) : "memory");
37return dest;
38}
39
40#define __HAVE_ARCH_STRNCPY
41static inline char * strncpy(char * dest,const char *src,size_t count)
42{
43int d0, d1, d2, d3;
44__asm__ __volatile__(
45 "1:\tdecl %2\n\t"
46 "js 2f\n\t"
47 "lodsb\n\t"
48 "stosb\n\t"
49 "testb %%al,%%al\n\t"
50 "jne 1b\n\t"
51 "rep\n\t"
52 "stosb\n"
53 "2:"
54 : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
55 :"0" (src),"1" (dest),"2" (count) : "memory");
56return dest;
57}
58
59#define __HAVE_ARCH_STRCAT
60static inline char * strcat(char * dest,const char * src)
61{
62int d0, d1, d2, d3;
63__asm__ __volatile__(
64 "repne\n\t"
65 "scasb\n\t"
66 "decl %1\n"
67 "1:\tlodsb\n\t"
68 "stosb\n\t"
69 "testb %%al,%%al\n\t"
70 "jne 1b"
71 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
72 : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu):"memory");
73return dest;
74}
75
76#define __HAVE_ARCH_STRNCAT
77static inline char * strncat(char * dest,const char * src,size_t count)
78{
79int d0, d1, d2, d3;
80__asm__ __volatile__(
81 "repne\n\t"
82 "scasb\n\t"
83 "decl %1\n\t"
84 "movl %8,%3\n"
85 "1:\tdecl %3\n\t"
86 "js 2f\n\t"
87 "lodsb\n\t"
88 "stosb\n\t"
89 "testb %%al,%%al\n\t"
90 "jne 1b\n"
91 "2:\txorl %2,%2\n\t"
92 "stosb"
93 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
94 : "0" (src),"1" (dest),"2" (0),"3" (0xffffffffu), "g" (count)
95 : "memory");
96return dest;
97}
98
99#define __HAVE_ARCH_STRCMP
100static inline int strcmp(const char * cs,const char * ct)
101{
102int d0, d1;
103register int __res;
104__asm__ __volatile__(
105 "1:\tlodsb\n\t"
106 "scasb\n\t"
107 "jne 2f\n\t"
108 "testb %%al,%%al\n\t"
109 "jne 1b\n\t"
110 "xorl %%eax,%%eax\n\t"
111 "jmp 3f\n"
112 "2:\tsbbl %%eax,%%eax\n\t"
113 "orb $1,%%al\n"
114 "3:"
115 :"=a" (__res), "=&S" (d0), "=&D" (d1)
116 :"1" (cs),"2" (ct));
117return __res;
118}
119
120#define __HAVE_ARCH_STRNCMP
121static inline int strncmp(const char * cs,const char * ct,size_t count)
122{
123register int __res;
124int d0, d1, d2;
125__asm__ __volatile__(
126 "1:\tdecl %3\n\t"
127 "js 2f\n\t"
128 "lodsb\n\t"
129 "scasb\n\t"
130 "jne 3f\n\t"
131 "testb %%al,%%al\n\t"
132 "jne 1b\n"
133 "2:\txorl %%eax,%%eax\n\t"
134 "jmp 4f\n"
135 "3:\tsbbl %%eax,%%eax\n\t"
136 "orb $1,%%al\n"
137 "4:"
138 :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
139 :"1" (cs),"2" (ct),"3" (count));
140return __res;
141}
142
143#define __HAVE_ARCH_STRCHR
144static inline char * strchr(const char * s, int c)
145{
146int d0;
147register char * __res;
148__asm__ __volatile__(
149 "movb %%al,%%ah\n"
150 "1:\tlodsb\n\t"
151 "cmpb %%ah,%%al\n\t"
152 "je 2f\n\t"
153 "testb %%al,%%al\n\t"
154 "jne 1b\n\t"
155 "movl $1,%1\n"
156 "2:\tmovl %1,%0\n\t"
157 "decl %0"
158 :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
159return __res;
160}
161
162#define __HAVE_ARCH_STRRCHR
163static inline char * strrchr(const char * s, int c)
164{
165int d0, d1;
166register char * __res;
167__asm__ __volatile__(
168 "movb %%al,%%ah\n"
169 "1:\tlodsb\n\t"
170 "cmpb %%ah,%%al\n\t"
171 "jne 2f\n\t"
172 "leal -1(%%esi),%0\n"
173 "2:\ttestb %%al,%%al\n\t"
174 "jne 1b"
175 :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
176return __res;
177}
178
179#define __HAVE_ARCH_STRLEN
180static inline size_t strlen(const char * s)
181{
182int d0;
183register int __res;
184__asm__ __volatile__(
185 "repne\n\t"
186 "scasb\n\t"
187 "notl %0\n\t"
188 "decl %0"
189 :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffffu));
190return __res;
191}
192
193static inline void * __memcpy(void * to, const void * from, size_t n)
194{
195int d0, d1, d2;
196__asm__ __volatile__(
197 "rep ; movsl\n\t"
198 "testb $2,%b4\n\t"
199 "je 1f\n\t"
200 "movsw\n"
201 "1:\ttestb $1,%b4\n\t"
202 "je 2f\n\t"
203 "movsb\n"
204 "2:"
205 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
206 :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
207 : "memory");
208return (to);
209}
210
211
212
213
214
215static inline void * __constant_memcpy(void * to, const void * from, size_t n)
216{
217 if (n <= 128)
218 return __builtin_memcpy(to, from, n);
219
220#define COMMON(x) \
221__asm__ __volatile__( \
222 "rep ; movsl" \
223 x \
224 : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
225 : "0" (n/4),"1" ((long) to),"2" ((long) from) \
226 : "memory");
227{
228 int d0, d1, d2;
229 switch (n % 4) {
230 case 0: COMMON(""); return to;
231 case 1: COMMON("\n\tmovsb"); return to;
232 case 2: COMMON("\n\tmovsw"); return to;
233 default: COMMON("\n\tmovsw\n\tmovsb"); return to;
234 }
235}
236
237#undef COMMON
238}
239
240#define __HAVE_ARCH_MEMCPY
241
242#ifdef CONFIG_X86_USE_3DNOW
243
244#include <asm/mmx.h>
245
246
247
248
249
250static inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
251{
252 if (len < 512)
253 return __constant_memcpy(to, from, len);
254 return _mmx_memcpy(to, from, len);
255}
256
257static __inline__ void *__memcpy3d(void *to, const void *from, size_t len)
258{
259 if (len < 512)
260 return __memcpy(to, from, len);
261 return _mmx_memcpy(to, from, len);
262}
263
264#define memcpy(t, f, n) \
265(__builtin_constant_p(n) ? \
266 __constant_memcpy3d((t),(f),(n)) : \
267 __memcpy3d((t),(f),(n)))
268
269#else
270
271
272
273
274
275#define memcpy(t, f, n) \
276(__builtin_constant_p(n) ? \
277 __constant_memcpy((t),(f),(n)) : \
278 __memcpy((t),(f),(n)))
279
280#endif
281
282
283
284
285
286
287
288
289extern void __struct_cpy_bug (void);
290
291#define struct_cpy(x,y) \
292({ \
293 if (sizeof(*(x)) != sizeof(*(y))) \
294 __struct_cpy_bug(); \
295 memcpy(x, y, sizeof(*(x))); \
296})
297
298#define __HAVE_ARCH_MEMMOVE
299static inline void * memmove(void * dest,const void * src, size_t n)
300{
301int d0, d1, d2;
302if (dest<src) {
303 memcpy(dest,src,n);
304} else
305__asm__ __volatile__(
306 "std\n\t"
307 "rep\n\t"
308 "movsb\n\t"
309 "cld"
310 : "=&c" (d0), "=&S" (d1), "=&D" (d2)
311 :"0" (n),
312 "1" (n-1+(const char *)src),
313 "2" (n-1+(char *)dest)
314 :"memory");
315return dest;
316}
317
318#define memcmp __builtin_memcmp
319
320#define __HAVE_ARCH_MEMCHR
321static inline void * memchr(const void * cs,int c,size_t count)
322{
323int d0;
324register void * __res;
325if (!count)
326 return NULL;
327__asm__ __volatile__(
328 "repne\n\t"
329 "scasb\n\t"
330 "je 1f\n\t"
331 "movl $1,%0\n"
332 "1:\tdecl %0"
333 :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
334return __res;
335}
336
337static inline void * __memset_generic(void * s, char c,size_t count)
338{
339int d0, d1;
340__asm__ __volatile__(
341 "rep\n\t"
342 "stosb"
343 : "=&c" (d0), "=&D" (d1)
344 :"a" (c),"1" (s),"0" (count)
345 :"memory");
346return s;
347}
348
349
350#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
351
352
353
354
355
356
357static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
358{
359int d0, d1;
360__asm__ __volatile__(
361 "rep ; stosl\n\t"
362 "testb $2,%b3\n\t"
363 "je 1f\n\t"
364 "stosw\n"
365 "1:\ttestb $1,%b3\n\t"
366 "je 2f\n\t"
367 "stosb\n"
368 "2:"
369 : "=&c" (d0), "=&D" (d1)
370 :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
371 :"memory");
372return (s);
373}
374
375
376#define __HAVE_ARCH_STRNLEN
377static inline size_t strnlen(const char * s, size_t count)
378{
379int d0;
380register int __res;
381__asm__ __volatile__(
382 "movl %2,%0\n\t"
383 "jmp 2f\n"
384 "1:\tcmpb $0,(%0)\n\t"
385 "je 3f\n\t"
386 "incl %0\n"
387 "2:\tdecl %1\n\t"
388 "cmpl $-1,%1\n\t"
389 "jne 1b\n"
390 "3:\tsubl %2,%0"
391 :"=a" (__res), "=&d" (d0)
392 :"c" (s),"1" (count));
393return __res;
394}
395
396
397#define __HAVE_ARCH_STRSTR
398
399extern char *strstr(const char *cs, const char *ct);
400
401
402
403
404
405static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
406{
407 switch (count) {
408 case 0:
409 return s;
410 case 1:
411 *(unsigned char *)s = pattern;
412 return s;
413 case 2:
414 *(unsigned short *)s = pattern;
415 return s;
416 case 3:
417 *(unsigned short *)s = pattern;
418 *(2+(unsigned char *)s) = pattern;
419 return s;
420 case 4:
421 *(unsigned long *)s = pattern;
422 return s;
423 }
424#define COMMON(x) \
425__asm__ __volatile__( \
426 "rep ; stosl" \
427 x \
428 : "=&c" (d0), "=&D" (d1) \
429 : "a" (pattern),"0" (count/4),"1" ((long) s) \
430 : "memory")
431{
432 int d0, d1;
433 switch (count % 4) {
434 case 0: COMMON(""); return s;
435 case 1: COMMON("\n\tstosb"); return s;
436 case 2: COMMON("\n\tstosw"); return s;
437 default: COMMON("\n\tstosw\n\tstosb"); return s;
438 }
439}
440
441#undef COMMON
442}
443
444#define __constant_c_x_memset(s, c, count) \
445(__builtin_constant_p(count) ? \
446 __constant_c_and_count_memset((s),(c),(count)) : \
447 __constant_c_memset((s),(c),(count)))
448
449#define __memset(s, c, count) \
450(__builtin_constant_p(count) ? \
451 __constant_count_memset((s),(c),(count)) : \
452 __memset_generic((s),(c),(count)))
453
454#define __HAVE_ARCH_MEMSET
455#define memset(s, c, count) \
456(__builtin_constant_p(c) ? \
457 __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
458 __memset((s),(c),(count)))
459
460
461
462
463#define __HAVE_ARCH_MEMSCAN
464static inline void * memscan(void * addr, int c, size_t size)
465{
466 if (!size)
467 return addr;
468 __asm__("repnz; scasb\n\t"
469 "jnz 1f\n\t"
470 "dec %%edi\n"
471 "1:"
472 : "=D" (addr), "=c" (size)
473 : "0" (addr), "1" (size), "a" (c));
474 return addr;
475}
476
477#endif
478
479#endif
480