1 | /* Optimized, inlined string functions. i486/x86-64 version. |
2 | Copyright (C) 2001-2016 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _STRING_H |
20 | # error "Never use <bits/string.h> directly; include <string.h> instead." |
21 | #endif |
22 | |
23 | /* Use the unaligned string inline ABI. */ |
24 | #define _STRING_INLINE_unaligned 1 |
25 | |
26 | /* Enable inline functions only for i486 or better when compiling for |
27 | ia32. */ |
28 | #if !defined __x86_64__ && (defined __i486__ || defined __pentium__ \ |
29 | || defined __pentiumpro__ || defined __pentium4__ \ |
30 | || defined __nocona__ || defined __atom__ \ |
31 | || defined __core2__ || defined __corei7__ \ |
32 | || defined __sandybridge__ || defined __haswell__ \ |
33 | || defined __bonnell__ || defined __silvermont__ \ |
34 | || defined __k6__ || defined __geode__ \ |
35 | || defined __k8__ || defined __athlon__ \ |
36 | || defined __amdfam10__ || defined __bdver1__ \ |
37 | || defined __bdver2__ || defined __bdver3__ \ |
38 | || defined __bdver4__ || defined __btver1__ \ |
39 | || defined __btver2__) |
40 | |
41 | /* We only provide optimizations if the user selects them and if |
42 | GNU CC is used. */ |
43 | # if !defined __NO_STRING_INLINES && defined __USE_STRING_INLINES \ |
44 | && defined __GNUC__ && __GNUC__ >= 2 |
45 | |
46 | # ifndef __STRING_INLINE |
47 | # ifndef __extern_inline |
48 | # define __STRING_INLINE inline |
49 | # else |
50 | # define __STRING_INLINE __extern_inline |
51 | # endif |
52 | # endif |
53 | |
54 | /* The macros are used in some of the optimized implementations below. */ |
55 | # define __STRING_SMALL_GET16(src, idx) \ |
56 | ((((const unsigned char *) (src))[idx + 1] << 8) \ |
57 | | ((const unsigned char *) (src))[idx]) |
58 | # define __STRING_SMALL_GET32(src, idx) \ |
59 | (((((const unsigned char *) (src))[idx + 3] << 8 \ |
60 | | ((const unsigned char *) (src))[idx + 2]) << 8 \ |
61 | | ((const unsigned char *) (src))[idx + 1]) << 8 \ |
62 | | ((const unsigned char *) (src))[idx]) |
63 | |
64 | |
65 | /* Copy N bytes of SRC to DEST. */ |
66 | # define _HAVE_STRING_ARCH_memcpy 1 |
67 | # define memcpy(dest, src, n) \ |
68 | (__extension__ (__builtin_constant_p (n) \ |
69 | ? __memcpy_c ((dest), (src), (n)) \ |
70 | : __memcpy_g ((dest), (src), (n)))) |
71 | # define __memcpy_c(dest, src, n) \ |
72 | ((n) == 0 \ |
73 | ? (dest) \ |
74 | : (((n) % 4 == 0) \ |
75 | ? __memcpy_by4 (dest, src, n) \ |
76 | : (((n) % 2 == 0) \ |
77 | ? __memcpy_by2 (dest, src, n) \ |
78 | : __memcpy_g (dest, src, n)))) |
79 | |
80 | __STRING_INLINE void *__memcpy_by4 (void *__dest, const void *__src, |
81 | size_t __n); |
82 | |
83 | __STRING_INLINE void * |
84 | __memcpy_by4 (void *__dest, const void *__src, size_t __n) |
85 | { |
86 | register unsigned long int __d0, __d1; |
87 | register void *__tmp = __dest; |
88 | __asm__ __volatile__ |
89 | ("1:\n\t" |
90 | "movl (%2),%0\n\t" |
91 | "leal 4(%2),%2\n\t" |
92 | "movl %0,(%1)\n\t" |
93 | "leal 4(%1),%1\n\t" |
94 | "decl %3\n\t" |
95 | "jnz 1b" |
96 | : "=&r" (__d0), "=&r" (__tmp), "=&r" (__src), "=&r" (__d1) |
97 | : "1" (__tmp), "2" (__src), "3" (__n / 4) |
98 | : "memory" , "cc" ); |
99 | return __dest; |
100 | } |
101 | |
102 | __STRING_INLINE void *__memcpy_by2 (void *__dest, const void *__src, |
103 | size_t __n); |
104 | |
105 | __STRING_INLINE void * |
106 | __memcpy_by2 (void *__dest, const void *__src, size_t __n) |
107 | { |
108 | register unsigned long int __d0, __d1; |
109 | register void *__tmp = __dest; |
110 | __asm__ __volatile__ |
111 | ("shrl $1,%3\n\t" |
112 | "jz 2f\n" /* only a word */ |
113 | "1:\n\t" |
114 | "movl (%2),%0\n\t" |
115 | "leal 4(%2),%2\n\t" |
116 | "movl %0,(%1)\n\t" |
117 | "leal 4(%1),%1\n\t" |
118 | "decl %3\n\t" |
119 | "jnz 1b\n" |
120 | "2:\n\t" |
121 | "movw (%2),%w0\n\t" |
122 | "movw %w0,(%1)" |
123 | : "=&q" (__d0), "=&r" (__tmp), "=&r" (__src), "=&r" (__d1) |
124 | : "1" (__tmp), "2" (__src), "3" (__n / 2) |
125 | : "memory" , "cc" ); |
126 | return __dest; |
127 | } |
128 | |
129 | __STRING_INLINE void *__memcpy_g (void *__dest, const void *__src, size_t __n); |
130 | |
131 | __STRING_INLINE void * |
132 | __memcpy_g (void *__dest, const void *__src, size_t __n) |
133 | { |
134 | register unsigned long int __d0, __d1, __d2; |
135 | register void *__tmp = __dest; |
136 | __asm__ __volatile__ |
137 | ("cld\n\t" |
138 | "shrl $1,%%ecx\n\t" |
139 | "jnc 1f\n\t" |
140 | "movsb\n" |
141 | "1:\n\t" |
142 | "shrl $1,%%ecx\n\t" |
143 | "jnc 2f\n\t" |
144 | "movsw\n" |
145 | "2:\n\t" |
146 | "rep; movsl" |
147 | : "=&c" (__d0), "=&D" (__d1), "=&S" (__d2), |
148 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__dest) |
149 | : "0" (__n), "1" (__tmp), "2" (__src), |
150 | "m" ( *(struct { __extension__ char __x[__n]; } *)__src) |
151 | : "cc" ); |
152 | return __dest; |
153 | } |
154 | |
155 | # define _HAVE_STRING_ARCH_memmove 1 |
156 | # ifndef _FORCE_INLINES |
157 | /* Copy N bytes of SRC to DEST, guaranteeing |
158 | correct behavior for overlapping strings. */ |
159 | # define memmove(dest, src, n) __memmove_g (dest, src, n) |
160 | |
161 | __STRING_INLINE void *__memmove_g (void *, const void *, size_t) |
162 | __asm__ ("memmove" ); |
163 | |
164 | __STRING_INLINE void * |
165 | __memmove_g (void *__dest, const void *__src, size_t __n) |
166 | { |
167 | register unsigned long int __d0, __d1, __d2; |
168 | register void *__tmp = __dest; |
169 | if (__dest < __src) |
170 | __asm__ __volatile__ |
171 | ("cld\n\t" |
172 | "rep; movsb" |
173 | : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2), |
174 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__dest) |
175 | : "0" (__n), "1" (__src), "2" (__tmp), |
176 | "m" ( *(struct { __extension__ char __x[__n]; } *)__src)); |
177 | else |
178 | __asm__ __volatile__ |
179 | ("decl %1\n\t" |
180 | "decl %2\n\t" |
181 | "std\n\t" |
182 | "rep; movsb\n\t" |
183 | "cld" |
184 | : "=&c" (__d0), "=&S" (__d1), "=&D" (__d2), |
185 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__dest) |
186 | : "0" (__n), "1" (__n + (const char *) __src), |
187 | "2" (__n + (char *) __tmp), |
188 | "m" ( *(struct { __extension__ char __x[__n]; } *)__src)); |
189 | return __dest; |
190 | } |
191 | # endif |
192 | |
193 | /* Compare N bytes of S1 and S2. */ |
194 | # define _HAVE_STRING_ARCH_memcmp 1 |
195 | # ifndef _FORCE_INLINES |
196 | # ifndef __PIC__ |
197 | /* gcc has problems to spill registers when using PIC. */ |
198 | __STRING_INLINE int |
199 | memcmp (const void *__s1, const void *__s2, size_t __n) |
200 | { |
201 | register unsigned long int __d0, __d1, __d2; |
202 | register int __res; |
203 | __asm__ __volatile__ |
204 | ("cld\n\t" |
205 | "testl %3,%3\n\t" |
206 | "repe; cmpsb\n\t" |
207 | "je 1f\n\t" |
208 | "sbbl %0,%0\n\t" |
209 | "orl $1,%0\n" |
210 | "1:" |
211 | : "=&a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) |
212 | : "0" (0), "1" (__s1), "2" (__s2), "3" (__n), |
213 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s1), |
214 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s2) |
215 | : "cc" ); |
216 | return __res; |
217 | } |
218 | # endif |
219 | # endif |
220 | |
221 | /* Set N bytes of S to C. */ |
222 | # define _HAVE_STRING_ARCH_memset 1 |
223 | # define _USE_STRING_ARCH_memset 1 |
224 | # define memset(s, c, n) \ |
225 | (__extension__ (__builtin_constant_p (n) && (n) <= 16 \ |
226 | ? ((n) == 1 \ |
227 | ? __memset_c1 ((s), (c)) \ |
228 | : __memset_gc ((s), (c), (n))) \ |
229 | : (__builtin_constant_p (c) \ |
230 | ? (__builtin_constant_p (n) \ |
231 | ? __memset_ccn ((s), (c), (n)) \ |
232 | : memset ((s), (c), (n))) \ |
233 | : (__builtin_constant_p (n) \ |
234 | ? __memset_gcn ((s), (c), (n)) \ |
235 | : memset ((s), (c), (n)))))) |
236 | |
237 | # define __memset_c1(s, c) ({ void *__s = (s); \ |
238 | *((unsigned char *) __s) = (unsigned char) (c); \ |
239 | __s; }) |
240 | |
241 | # define __memset_gc(s, c, n) \ |
242 | ({ void *__s = (s); \ |
243 | union { \ |
244 | unsigned int __ui; \ |
245 | unsigned short int __usi; \ |
246 | unsigned char __uc; \ |
247 | } *__u = __s; \ |
248 | unsigned int __c = ((unsigned int) ((unsigned char) (c))) * 0x01010101; \ |
249 | \ |
250 | /* We apply a trick here. `gcc' would implement the following \ |
251 | assignments using immediate operands. But this uses to much \ |
252 | memory (7, instead of 4 bytes). So we force the value in a \ |
253 | registers. */ \ |
254 | if ((n) == 3 || (n) >= 5) \ |
255 | __asm__ __volatile__ ("" : "=r" (__c) : "0" (__c)); \ |
256 | \ |
257 | /* This `switch' statement will be removed at compile-time. */ \ |
258 | switch (n) \ |
259 | { \ |
260 | case 15: \ |
261 | __u->__ui = __c; \ |
262 | __u = __extension__ ((void *) __u + 4); \ |
263 | case 11: \ |
264 | __u->__ui = __c; \ |
265 | __u = __extension__ ((void *) __u + 4); \ |
266 | case 7: \ |
267 | __u->__ui = __c; \ |
268 | __u = __extension__ ((void *) __u + 4); \ |
269 | case 3: \ |
270 | __u->__usi = (unsigned short int) __c; \ |
271 | __u = __extension__ ((void *) __u + 2); \ |
272 | __u->__uc = (unsigned char) __c; \ |
273 | break; \ |
274 | \ |
275 | case 14: \ |
276 | __u->__ui = __c; \ |
277 | __u = __extension__ ((void *) __u + 4); \ |
278 | case 10: \ |
279 | __u->__ui = __c; \ |
280 | __u = __extension__ ((void *) __u + 4); \ |
281 | case 6: \ |
282 | __u->__ui = __c; \ |
283 | __u = __extension__ ((void *) __u + 4); \ |
284 | case 2: \ |
285 | __u->__usi = (unsigned short int) __c; \ |
286 | break; \ |
287 | \ |
288 | case 13: \ |
289 | __u->__ui = __c; \ |
290 | __u = __extension__ ((void *) __u + 4); \ |
291 | case 9: \ |
292 | __u->__ui = __c; \ |
293 | __u = __extension__ ((void *) __u + 4); \ |
294 | case 5: \ |
295 | __u->__ui = __c; \ |
296 | __u = __extension__ ((void *) __u + 4); \ |
297 | case 1: \ |
298 | __u->__uc = (unsigned char) __c; \ |
299 | break; \ |
300 | \ |
301 | case 16: \ |
302 | __u->__ui = __c; \ |
303 | __u = __extension__ ((void *) __u + 4); \ |
304 | case 12: \ |
305 | __u->__ui = __c; \ |
306 | __u = __extension__ ((void *) __u + 4); \ |
307 | case 8: \ |
308 | __u->__ui = __c; \ |
309 | __u = __extension__ ((void *) __u + 4); \ |
310 | case 4: \ |
311 | __u->__ui = __c; \ |
312 | case 0: \ |
313 | break; \ |
314 | } \ |
315 | \ |
316 | __s; }) |
317 | |
318 | # define __memset_ccn(s, c, n) \ |
319 | (((n) % 4 == 0) \ |
320 | ? __memset_ccn_by4 (s, ((unsigned int) ((unsigned char) (c))) * 0x01010101,\ |
321 | n) \ |
322 | : (((n) % 2 == 0) \ |
323 | ? __memset_ccn_by2 (s, \ |
324 | ((unsigned int) ((unsigned char) (c))) * 0x01010101,\ |
325 | n) \ |
326 | : memset (s, c, n))) |
327 | |
328 | __STRING_INLINE void *__memset_ccn_by4 (void *__s, unsigned int __c, |
329 | size_t __n); |
330 | |
331 | __STRING_INLINE void * |
332 | __memset_ccn_by4 (void *__s, unsigned int __c, size_t __n) |
333 | { |
334 | register void *__tmp = __s; |
335 | register unsigned long int __d0; |
336 | # ifdef __i686__ |
337 | __asm__ __volatile__ |
338 | ("cld\n\t" |
339 | "rep; stosl" |
340 | : "=&a" (__c), "=&D" (__tmp), "=&c" (__d0), |
341 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
342 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
343 | : "cc" ); |
344 | # else |
345 | __asm__ __volatile__ |
346 | ("1:\n\t" |
347 | "movl %0,(%1)\n\t" |
348 | "addl $4,%1\n\t" |
349 | "decl %2\n\t" |
350 | "jnz 1b\n" |
351 | : "=&r" (__c), "=&r" (__tmp), "=&r" (__d0), |
352 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
353 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
354 | : "cc" ); |
355 | # endif |
356 | return __s; |
357 | } |
358 | |
359 | __STRING_INLINE void *__memset_ccn_by2 (void *__s, unsigned int __c, |
360 | size_t __n); |
361 | |
362 | __STRING_INLINE void * |
363 | __memset_ccn_by2 (void *__s, unsigned int __c, size_t __n) |
364 | { |
365 | register unsigned long int __d0, __d1; |
366 | register void *__tmp = __s; |
367 | # ifdef __i686__ |
368 | __asm__ __volatile__ |
369 | ("cld\n\t" |
370 | "rep; stosl\n" |
371 | "stosw" |
372 | : "=&a" (__d0), "=&D" (__tmp), "=&c" (__d1), |
373 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
374 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
375 | : "cc" ); |
376 | # else |
377 | __asm__ __volatile__ |
378 | ("1:\tmovl %0,(%1)\n\t" |
379 | "leal 4(%1),%1\n\t" |
380 | "decl %2\n\t" |
381 | "jnz 1b\n" |
382 | "movw %w0,(%1)" |
383 | : "=&q" (__d0), "=&r" (__tmp), "=&r" (__d1), |
384 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
385 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
386 | : "cc" ); |
387 | #endif |
388 | return __s; |
389 | } |
390 | |
391 | # define __memset_gcn(s, c, n) \ |
392 | (((n) % 4 == 0) \ |
393 | ? __memset_gcn_by4 (s, c, n) \ |
394 | : (((n) % 2 == 0) \ |
395 | ? __memset_gcn_by2 (s, c, n) \ |
396 | : memset (s, c, n))) |
397 | |
398 | __STRING_INLINE void *__memset_gcn_by4 (void *__s, int __c, size_t __n); |
399 | |
400 | __STRING_INLINE void * |
401 | __memset_gcn_by4 (void *__s, int __c, size_t __n) |
402 | { |
403 | register void *__tmp = __s; |
404 | register unsigned long int __d0; |
405 | __asm__ __volatile__ |
406 | ("movb %b0,%h0\n" |
407 | "pushw %w0\n\t" |
408 | "shll $16,%0\n\t" |
409 | "popw %w0\n" |
410 | "1:\n\t" |
411 | "movl %0,(%1)\n\t" |
412 | "addl $4,%1\n\t" |
413 | "decl %2\n\t" |
414 | "jnz 1b\n" |
415 | : "=&q" (__c), "=&r" (__tmp), "=&r" (__d0), |
416 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
417 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
418 | : "cc" ); |
419 | return __s; |
420 | } |
421 | |
422 | __STRING_INLINE void *__memset_gcn_by2 (void *__s, int __c, size_t __n); |
423 | |
424 | __STRING_INLINE void * |
425 | __memset_gcn_by2 (void *__s, int __c, size_t __n) |
426 | { |
427 | register unsigned long int __d0, __d1; |
428 | register void *__tmp = __s; |
429 | __asm__ __volatile__ |
430 | ("movb %b0,%h0\n\t" |
431 | "pushw %w0\n\t" |
432 | "shll $16,%0\n\t" |
433 | "popw %w0\n" |
434 | "1:\n\t" |
435 | "movl %0,(%1)\n\t" |
436 | "leal 4(%1),%1\n\t" |
437 | "decl %2\n\t" |
438 | "jnz 1b\n" |
439 | "movw %w0,(%1)" |
440 | : "=&q" (__d0), "=&r" (__tmp), "=&r" (__d1), |
441 | "=m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
442 | : "0" ((unsigned int) __c), "1" (__tmp), "2" (__n / 4) |
443 | : "cc" ); |
444 | return __s; |
445 | } |
446 | |
447 | |
448 | /* Search N bytes of S for C. */ |
449 | # define _HAVE_STRING_ARCH_memchr 1 |
450 | # ifndef _FORCE_INLINES |
451 | __STRING_INLINE void * |
452 | memchr (const void *__s, int __c, size_t __n) |
453 | { |
454 | register unsigned long int __d0; |
455 | # ifdef __i686__ |
456 | register unsigned long int __d1; |
457 | # endif |
458 | register unsigned char *__res; |
459 | if (__n == 0) |
460 | return NULL; |
461 | # ifdef __i686__ |
462 | __asm__ __volatile__ |
463 | ("cld\n\t" |
464 | "repne; scasb\n\t" |
465 | "cmovne %2,%0" |
466 | : "=D" (__res), "=&c" (__d0), "=&r" (__d1) |
467 | : "a" (__c), "0" (__s), "1" (__n), "2" (1), |
468 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
469 | : "cc" ); |
470 | # else |
471 | __asm__ __volatile__ |
472 | ("cld\n\t" |
473 | "repne; scasb\n\t" |
474 | "je 1f\n\t" |
475 | "movl $1,%0\n" |
476 | "1:" |
477 | : "=D" (__res), "=&c" (__d0) |
478 | : "a" (__c), "0" (__s), "1" (__n), |
479 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
480 | : "cc" ); |
481 | # endif |
482 | return __res - 1; |
483 | } |
484 | # endif |
485 | |
486 | # define _HAVE_STRING_ARCH_memrchr 1 |
487 | # ifndef _FORCE_INLINES |
488 | __STRING_INLINE void *__memrchr (const void *__s, int __c, size_t __n); |
489 | |
490 | __STRING_INLINE void * |
491 | __memrchr (const void *__s, int __c, size_t __n) |
492 | { |
493 | register unsigned long int __d0; |
494 | # ifdef __i686__ |
495 | register unsigned long int __d1; |
496 | # endif |
497 | register void *__res; |
498 | if (__n == 0) |
499 | return NULL; |
500 | # ifdef __i686__ |
501 | __asm__ __volatile__ |
502 | ("std\n\t" |
503 | "repne; scasb\n\t" |
504 | "cmovne %2,%0\n\t" |
505 | "cld\n\t" |
506 | "incl %0" |
507 | : "=D" (__res), "=&c" (__d0), "=&r" (__d1) |
508 | : "a" (__c), "0" (__s + __n - 1), "1" (__n), "2" (-1), |
509 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
510 | : "cc" ); |
511 | # else |
512 | __asm__ __volatile__ |
513 | ("std\n\t" |
514 | "repne; scasb\n\t" |
515 | "je 1f\n\t" |
516 | "orl $-1,%0\n" |
517 | "1:\tcld\n\t" |
518 | "incl %0" |
519 | : "=D" (__res), "=&c" (__d0) |
520 | : "a" (__c), "0" (__s + __n - 1), "1" (__n), |
521 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s) |
522 | : "cc" ); |
523 | # endif |
524 | return __res; |
525 | } |
526 | # ifdef __USE_GNU |
527 | # define memrchr(s, c, n) __memrchr ((s), (c), (n)) |
528 | # endif |
529 | # endif |
530 | |
531 | /* Return pointer to C in S. */ |
532 | # define _HAVE_STRING_ARCH_rawmemchr 1 |
533 | __STRING_INLINE void *__rawmemchr (const void *__s, int __c); |
534 | |
535 | # ifndef _FORCE_INLINES |
536 | __STRING_INLINE void * |
537 | __rawmemchr (const void *__s, int __c) |
538 | { |
539 | register unsigned long int __d0; |
540 | register unsigned char *__res; |
541 | __asm__ __volatile__ |
542 | ("cld\n\t" |
543 | "repne; scasb\n\t" |
544 | : "=D" (__res), "=&c" (__d0) |
545 | : "a" (__c), "0" (__s), "1" (0xffffffff), |
546 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
547 | : "cc" ); |
548 | return __res - 1; |
549 | } |
550 | # ifdef __USE_GNU |
551 | __STRING_INLINE void * |
552 | rawmemchr (const void *__s, int __c) |
553 | { |
554 | return __rawmemchr (__s, __c); |
555 | } |
556 | # endif /* use GNU */ |
557 | # endif |
558 | |
559 | |
560 | /* Return the length of S. */ |
561 | # define _HAVE_STRING_ARCH_strlen 1 |
562 | # define strlen(str) \ |
563 | (__extension__ (__builtin_constant_p (str) \ |
564 | ? __builtin_strlen (str) \ |
565 | : __strlen_g (str))) |
566 | __STRING_INLINE size_t __strlen_g (const char *__str); |
567 | |
568 | __STRING_INLINE size_t |
569 | __strlen_g (const char *__str) |
570 | { |
571 | register char __dummy; |
572 | register const char *__tmp = __str; |
573 | __asm__ __volatile__ |
574 | ("1:\n\t" |
575 | "movb (%0),%b1\n\t" |
576 | "leal 1(%0),%0\n\t" |
577 | "testb %b1,%b1\n\t" |
578 | "jne 1b" |
579 | : "=r" (__tmp), "=&q" (__dummy) |
580 | : "0" (__str), |
581 | "m" ( *(struct { char __x[0xfffffff]; } *)__str) |
582 | : "cc" ); |
583 | return __tmp - __str - 1; |
584 | } |
585 | |
586 | |
587 | /* Copy SRC to DEST. */ |
588 | # define _HAVE_STRING_ARCH_strcpy 1 |
589 | # define strcpy(dest, src) \ |
590 | (__extension__ (__builtin_constant_p (src) \ |
591 | ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \ |
592 | ? __strcpy_a_small ((dest), (src), strlen (src) + 1) \ |
593 | : (char *) memcpy ((char *) (dest), \ |
594 | (const char *) (src), \ |
595 | strlen (src) + 1)) \ |
596 | : __strcpy_g ((dest), (src)))) |
597 | |
598 | # define __strcpy_a_small(dest, src, srclen) \ |
599 | (__extension__ ({ char *__dest = (dest); \ |
600 | union { \ |
601 | unsigned int __ui; \ |
602 | unsigned short int __usi; \ |
603 | unsigned char __uc; \ |
604 | char __c; \ |
605 | } *__u = (void *) __dest; \ |
606 | switch (srclen) \ |
607 | { \ |
608 | case 1: \ |
609 | __u->__uc = '\0'; \ |
610 | break; \ |
611 | case 2: \ |
612 | __u->__usi = __STRING_SMALL_GET16 (src, 0); \ |
613 | break; \ |
614 | case 3: \ |
615 | __u->__usi = __STRING_SMALL_GET16 (src, 0); \ |
616 | __u = __extension__ ((void *) __u + 2); \ |
617 | __u->__uc = '\0'; \ |
618 | break; \ |
619 | case 4: \ |
620 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
621 | break; \ |
622 | case 5: \ |
623 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
624 | __u = __extension__ ((void *) __u + 4); \ |
625 | __u->__uc = '\0'; \ |
626 | break; \ |
627 | case 6: \ |
628 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
629 | __u = __extension__ ((void *) __u + 4); \ |
630 | __u->__usi = __STRING_SMALL_GET16 (src, 4); \ |
631 | break; \ |
632 | case 7: \ |
633 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
634 | __u = __extension__ ((void *) __u + 4); \ |
635 | __u->__usi = __STRING_SMALL_GET16 (src, 4); \ |
636 | __u = __extension__ ((void *) __u + 2); \ |
637 | __u->__uc = '\0'; \ |
638 | break; \ |
639 | case 8: \ |
640 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
641 | __u = __extension__ ((void *) __u + 4); \ |
642 | __u->__ui = __STRING_SMALL_GET32 (src, 4); \ |
643 | break; \ |
644 | } \ |
645 | (char *) __dest; })) |
646 | |
647 | __STRING_INLINE char *__strcpy_g (char *__dest, const char *__src); |
648 | |
649 | __STRING_INLINE char * |
650 | __strcpy_g (char *__dest, const char *__src) |
651 | { |
652 | register char *__tmp = __dest; |
653 | register char __dummy; |
654 | __asm__ __volatile__ |
655 | ( |
656 | "1:\n\t" |
657 | "movb (%0),%b2\n\t" |
658 | "leal 1(%0),%0\n\t" |
659 | "movb %b2,(%1)\n\t" |
660 | "leal 1(%1),%1\n\t" |
661 | "testb %b2,%b2\n\t" |
662 | "jne 1b" |
663 | : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy), |
664 | "=m" ( *(struct { char __x[0xfffffff]; } *)__dest) |
665 | : "0" (__src), "1" (__tmp), |
666 | "m" ( *(struct { char __x[0xfffffff]; } *)__src) |
667 | : "cc" ); |
668 | return __dest; |
669 | } |
670 | |
671 | |
672 | # ifdef __USE_GNU |
673 | # define _HAVE_STRING_ARCH_stpcpy 1 |
674 | /* Copy SRC to DEST. */ |
675 | # define __stpcpy(dest, src) \ |
676 | (__extension__ (__builtin_constant_p (src) \ |
677 | ? (strlen (src) + 1 <= 8 \ |
678 | ? __stpcpy_a_small ((dest), (src), strlen (src) + 1) \ |
679 | : __stpcpy_c ((dest), (src), strlen (src) + 1)) \ |
680 | : __stpcpy_g ((dest), (src)))) |
681 | # define __stpcpy_c(dest, src, srclen) \ |
682 | ((srclen) % 4 == 0 \ |
683 | ? __mempcpy_by4 (dest, src, srclen) - 1 \ |
684 | : ((srclen) % 2 == 0 \ |
685 | ? __mempcpy_by2 (dest, src, srclen) - 1 \ |
686 | : __mempcpy_byn (dest, src, srclen) - 1)) |
687 | |
688 | /* In glibc itself we use this symbol for namespace reasons. */ |
689 | # define stpcpy(dest, src) __stpcpy ((dest), (src)) |
690 | |
691 | # define __stpcpy_a_small(dest, src, srclen) \ |
692 | (__extension__ ({ union { \ |
693 | unsigned int __ui; \ |
694 | unsigned short int __usi; \ |
695 | unsigned char __uc; \ |
696 | char __c; \ |
697 | } *__u = (void *) (dest); \ |
698 | switch (srclen) \ |
699 | { \ |
700 | case 1: \ |
701 | __u->__uc = '\0'; \ |
702 | break; \ |
703 | case 2: \ |
704 | __u->__usi = __STRING_SMALL_GET16 (src, 0); \ |
705 | __u = __extension__ ((void *) __u + 1); \ |
706 | break; \ |
707 | case 3: \ |
708 | __u->__usi = __STRING_SMALL_GET16 (src, 0); \ |
709 | __u = __extension__ ((void *) __u + 2); \ |
710 | __u->__uc = '\0'; \ |
711 | break; \ |
712 | case 4: \ |
713 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
714 | __u = __extension__ ((void *) __u + 3); \ |
715 | break; \ |
716 | case 5: \ |
717 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
718 | __u = __extension__ ((void *) __u + 4); \ |
719 | __u->__uc = '\0'; \ |
720 | break; \ |
721 | case 6: \ |
722 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
723 | __u = __extension__ ((void *) __u + 4); \ |
724 | __u->__usi = __STRING_SMALL_GET16 (src, 4); \ |
725 | __u = __extension__ ((void *) __u + 1); \ |
726 | break; \ |
727 | case 7: \ |
728 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
729 | __u = __extension__ ((void *) __u + 4); \ |
730 | __u->__usi = __STRING_SMALL_GET16 (src, 4); \ |
731 | __u = __extension__ ((void *) __u + 2); \ |
732 | __u->__uc = '\0'; \ |
733 | break; \ |
734 | case 8: \ |
735 | __u->__ui = __STRING_SMALL_GET32 (src, 0); \ |
736 | __u = __extension__ ((void *) __u + 4); \ |
737 | __u->__ui = __STRING_SMALL_GET32 (src, 4); \ |
738 | __u = __extension__ ((void *) __u + 3); \ |
739 | break; \ |
740 | } \ |
741 | (char *) __u; })) |
742 | |
743 | __STRING_INLINE char *__mempcpy_by4 (char *__dest, const char *__src, |
744 | size_t __srclen); |
745 | |
746 | __STRING_INLINE char * |
747 | __mempcpy_by4 (char *__dest, const char *__src, size_t __srclen) |
748 | { |
749 | register char *__tmp = __dest; |
750 | register unsigned long int __d0, __d1; |
751 | __asm__ __volatile__ |
752 | ("1:\n\t" |
753 | "movl (%2),%0\n\t" |
754 | "leal 4(%2),%2\n\t" |
755 | "movl %0,(%1)\n\t" |
756 | "leal 4(%1),%1\n\t" |
757 | "decl %3\n\t" |
758 | "jnz 1b" |
759 | : "=&r" (__d0), "=r" (__tmp), "=&r" (__src), "=&r" (__d1) |
760 | : "1" (__tmp), "2" (__src), "3" (__srclen / 4) |
761 | : "memory" , "cc" ); |
762 | return __tmp; |
763 | } |
764 | |
765 | __STRING_INLINE char *__mempcpy_by2 (char *__dest, const char *__src, |
766 | size_t __srclen); |
767 | |
768 | __STRING_INLINE char * |
769 | __mempcpy_by2 (char *__dest, const char *__src, size_t __srclen) |
770 | { |
771 | register char *__tmp = __dest; |
772 | register unsigned long int __d0, __d1; |
773 | __asm__ __volatile__ |
774 | ("shrl $1,%3\n\t" |
775 | "jz 2f\n" /* only a word */ |
776 | "1:\n\t" |
777 | "movl (%2),%0\n\t" |
778 | "leal 4(%2),%2\n\t" |
779 | "movl %0,(%1)\n\t" |
780 | "leal 4(%1),%1\n\t" |
781 | "decl %3\n\t" |
782 | "jnz 1b\n" |
783 | "2:\n\t" |
784 | "movw (%2),%w0\n\t" |
785 | "movw %w0,(%1)" |
786 | : "=&q" (__d0), "=r" (__tmp), "=&r" (__src), "=&r" (__d1), |
787 | "=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest) |
788 | : "1" (__tmp), "2" (__src), "3" (__srclen / 2), |
789 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
790 | : "cc" ); |
791 | return __tmp + 2; |
792 | } |
793 | |
794 | __STRING_INLINE char *__mempcpy_byn (char *__dest, const char *__src, |
795 | size_t __srclen); |
796 | |
797 | __STRING_INLINE char * |
798 | __mempcpy_byn (char *__dest, const char *__src, size_t __srclen) |
799 | { |
800 | register unsigned long __d0, __d1; |
801 | register char *__tmp = __dest; |
802 | __asm__ __volatile__ |
803 | ("cld\n\t" |
804 | "shrl $1,%%ecx\n\t" |
805 | "jnc 1f\n\t" |
806 | "movsb\n" |
807 | "1:\n\t" |
808 | "shrl $1,%%ecx\n\t" |
809 | "jnc 2f\n\t" |
810 | "movsw\n" |
811 | "2:\n\t" |
812 | "rep; movsl" |
813 | : "=D" (__tmp), "=&c" (__d0), "=&S" (__d1), |
814 | "=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest) |
815 | : "0" (__tmp), "1" (__srclen), "2" (__src), |
816 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
817 | : "cc" ); |
818 | return __tmp; |
819 | } |
820 | |
821 | __STRING_INLINE char *__stpcpy_g (char *__dest, const char *__src); |
822 | |
823 | __STRING_INLINE char * |
824 | __stpcpy_g (char *__dest, const char *__src) |
825 | { |
826 | register char *__tmp = __dest; |
827 | register char __dummy; |
828 | __asm__ __volatile__ |
829 | ( |
830 | "1:\n\t" |
831 | "movb (%0),%b2\n\t" |
832 | "leal 1(%0),%0\n\t" |
833 | "movb %b2,(%1)\n\t" |
834 | "leal 1(%1),%1\n\t" |
835 | "testb %b2,%b2\n\t" |
836 | "jne 1b" |
837 | : "=&r" (__src), "=r" (__tmp), "=&q" (__dummy), |
838 | "=m" ( *(struct { char __x[0xfffffff]; } *)__dest) |
839 | : "0" (__src), "1" (__tmp), |
840 | "m" ( *(struct { char __x[0xfffffff]; } *)__src) |
841 | : "cc" ); |
842 | return __tmp - 1; |
843 | } |
844 | # endif |
845 | |
846 | |
847 | /* Copy no more than N characters of SRC to DEST. */ |
848 | # define _HAVE_STRING_ARCH_strncpy 1 |
849 | # define strncpy(dest, src, n) \ |
850 | (__extension__ (__builtin_constant_p (src) \ |
851 | ? ((strlen (src) + 1 >= ((size_t) (n)) \ |
852 | ? (char *) memcpy ((char *) (dest), \ |
853 | (const char *) (src), n) \ |
854 | : __strncpy_cg ((dest), (src), strlen (src) + 1, n))) \ |
855 | : __strncpy_gg ((dest), (src), n))) |
856 | # define __strncpy_cg(dest, src, srclen, n) \ |
857 | (((srclen) % 4 == 0) \ |
858 | ? __strncpy_by4 (dest, src, srclen, n) \ |
859 | : (((srclen) % 2 == 0) \ |
860 | ? __strncpy_by2 (dest, src, srclen, n) \ |
861 | : __strncpy_byn (dest, src, srclen, n))) |
862 | |
863 | __STRING_INLINE char *__strncpy_by4 (char *__dest, const char __src[], |
864 | size_t __srclen, size_t __n); |
865 | |
866 | __STRING_INLINE char * |
867 | __strncpy_by4 (char *__dest, const char __src[], size_t __srclen, size_t __n) |
868 | { |
869 | register char *__tmp = __dest; |
870 | register int __dummy1, __dummy2; |
871 | __asm__ __volatile__ |
872 | ("1:\n\t" |
873 | "movl (%2),%0\n\t" |
874 | "leal 4(%2),%2\n\t" |
875 | "movl %0,(%1)\n\t" |
876 | "leal 4(%1),%1\n\t" |
877 | "decl %3\n\t" |
878 | "jnz 1b" |
879 | : "=&r" (__dummy1), "=r" (__tmp), "=&r" (__src), "=&r" (__dummy2), |
880 | "=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest) |
881 | : "1" (__tmp), "2" (__src), "3" (__srclen / 4), |
882 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
883 | : "cc" ); |
884 | (void) memset (__tmp, '\0', __n - __srclen); |
885 | return __dest; |
886 | } |
887 | |
888 | __STRING_INLINE char *__strncpy_by2 (char *__dest, const char __src[], |
889 | size_t __srclen, size_t __n); |
890 | |
891 | __STRING_INLINE char * |
892 | __strncpy_by2 (char *__dest, const char __src[], size_t __srclen, size_t __n) |
893 | { |
894 | register char *__tmp = __dest; |
895 | register int __dummy1, __dummy2; |
896 | __asm__ __volatile__ |
897 | ("shrl $1,%3\n\t" |
898 | "jz 2f\n" /* only a word */ |
899 | "1:\n\t" |
900 | "movl (%2),%0\n\t" |
901 | "leal 4(%2),%2\n\t" |
902 | "movl %0,(%1)\n\t" |
903 | "leal 4(%1),%1\n\t" |
904 | "decl %3\n\t" |
905 | "jnz 1b\n" |
906 | "2:\n\t" |
907 | "movw (%2),%w0\n\t" |
908 | "movw %w0,(%1)\n\t" |
909 | : "=&q" (__dummy1), "=r" (__tmp), "=&r" (__src), "=&r" (__dummy2), |
910 | "=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest) |
911 | : "1" (__tmp), "2" (__src), "3" (__srclen / 2), |
912 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
913 | : "cc" ); |
914 | (void) memset (__tmp + 2, '\0', __n - __srclen); |
915 | return __dest; |
916 | } |
917 | |
918 | __STRING_INLINE char *__strncpy_byn (char *__dest, const char __src[], |
919 | size_t __srclen, size_t __n); |
920 | |
921 | __STRING_INLINE char * |
922 | __strncpy_byn (char *__dest, const char __src[], size_t __srclen, size_t __n) |
923 | { |
924 | register unsigned long int __d0, __d1; |
925 | register char *__tmp = __dest; |
926 | __asm__ __volatile__ |
927 | ("cld\n\t" |
928 | "shrl $1,%1\n\t" |
929 | "jnc 1f\n\t" |
930 | "movsb\n" |
931 | "1:\n\t" |
932 | "shrl $1,%1\n\t" |
933 | "jnc 2f\n\t" |
934 | "movsw\n" |
935 | "2:\n\t" |
936 | "rep; movsl" |
937 | : "=D" (__tmp), "=&c" (__d0), "=&S" (__d1), |
938 | "=m" ( *(struct { __extension__ char __x[__srclen]; } *)__dest) |
939 | : "1" (__srclen), "0" (__tmp),"2" (__src), |
940 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
941 | : "cc" ); |
942 | (void) memset (__tmp, '\0', __n - __srclen); |
943 | return __dest; |
944 | } |
945 | |
946 | __STRING_INLINE char *__strncpy_gg (char *__dest, const char *__src, |
947 | size_t __n); |
948 | |
949 | __STRING_INLINE char * |
950 | __strncpy_gg (char *__dest, const char *__src, size_t __n) |
951 | { |
952 | register char *__tmp = __dest; |
953 | register char __dummy; |
954 | if (__n > 0) |
955 | __asm__ __volatile__ |
956 | ("1:\n\t" |
957 | "movb (%0),%2\n\t" |
958 | "incl %0\n\t" |
959 | "movb %2,(%1)\n\t" |
960 | "incl %1\n\t" |
961 | "decl %3\n\t" |
962 | "je 3f\n\t" |
963 | "testb %2,%2\n\t" |
964 | "jne 1b\n\t" |
965 | "2:\n\t" |
966 | "movb %2,(%1)\n\t" |
967 | "incl %1\n\t" |
968 | "decl %3\n\t" |
969 | "jne 2b\n\t" |
970 | "3:" |
971 | : "=&r" (__src), "=&r" (__tmp), "=&q" (__dummy), "=&r" (__n) |
972 | : "0" (__src), "1" (__tmp), "3" (__n) |
973 | : "memory" , "cc" ); |
974 | |
975 | return __dest; |
976 | } |
977 | |
978 | |
979 | /* Append SRC onto DEST. */ |
980 | # define _HAVE_STRING_ARCH_strcat 1 |
981 | # define strcat(dest, src) \ |
982 | (__extension__ (__builtin_constant_p (src) \ |
983 | ? __strcat_c ((dest), (src), strlen (src) + 1) \ |
984 | : __strcat_g ((dest), (src)))) |
985 | |
986 | __STRING_INLINE char *__strcat_c (char *__dest, const char __src[], |
987 | size_t __srclen); |
988 | |
989 | __STRING_INLINE char * |
990 | __strcat_c (char *__dest, const char __src[], size_t __srclen) |
991 | { |
992 | # ifdef __i686__ |
993 | register unsigned long int __d0; |
994 | register char *__tmp; |
995 | __asm__ __volatile__ |
996 | ("repne; scasb" |
997 | : "=D" (__tmp), "=&c" (__d0), |
998 | "=m" ( *(struct { char __x[0xfffffff]; } *)__dest) |
999 | : "0" (__dest), "1" (0xffffffff), "a" (0), |
1000 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
1001 | : "cc" ); |
1002 | --__tmp; |
1003 | # else |
1004 | register char *__tmp = __dest; |
1005 | __asm__ __volatile__ |
1006 | ("decl %0\n\t" |
1007 | "1:\n\t" |
1008 | "incl %0\n\t" |
1009 | "cmpb $0,(%0)\n\t" |
1010 | "jne 1b\n" |
1011 | : "=r" (__tmp), |
1012 | "=m" ( *(struct { char __x[0xfffffff]; } *)__dest) |
1013 | : "0" (__tmp), |
1014 | "m" ( *(struct { __extension__ char __x[__srclen]; } *)__src) |
1015 | : "cc" ); |
1016 | # endif |
1017 | (void) memcpy (__tmp, __src, __srclen); |
1018 | return __dest; |
1019 | } |
1020 | |
1021 | __STRING_INLINE char *__strcat_g (char *__dest, const char *__src); |
1022 | |
1023 | __STRING_INLINE char * |
1024 | __strcat_g (char *__dest, const char *__src) |
1025 | { |
1026 | register char *__tmp = __dest; |
1027 | register char __dummy; |
1028 | __asm__ __volatile__ |
1029 | ("decl %1\n\t" |
1030 | "1:\n\t" |
1031 | "incl %1\n\t" |
1032 | "cmpb $0,(%1)\n\t" |
1033 | "jne 1b\n" |
1034 | "2:\n\t" |
1035 | "movb (%2),%b0\n\t" |
1036 | "incl %2\n\t" |
1037 | "movb %b0,(%1)\n\t" |
1038 | "incl %1\n\t" |
1039 | "testb %b0,%b0\n\t" |
1040 | "jne 2b\n" |
1041 | : "=&q" (__dummy), "=&r" (__tmp), "=&r" (__src), |
1042 | "=m" ( *(struct { char __x[0xfffffff]; } *)__dest) |
1043 | : "1" (__tmp), "2" (__src), |
1044 | "m" ( *(struct { char __x[0xfffffff]; } *)__src) |
1045 | : "memory" , "cc" ); |
1046 | return __dest; |
1047 | } |
1048 | |
1049 | |
1050 | /* Append no more than N characters from SRC onto DEST. */ |
1051 | # define _HAVE_STRING_ARCH_strncat 1 |
1052 | # define strncat(dest, src, n) \ |
1053 | (__extension__ ({ char *__dest = (dest); \ |
1054 | __builtin_constant_p (src) && __builtin_constant_p (n) \ |
1055 | ? (strlen (src) < ((size_t) (n)) \ |
1056 | ? strcat (__dest, (src)) \ |
1057 | : (*(char *)__mempcpy (strchr (__dest, '\0'), \ |
1058 | (const char *) (src), \ |
1059 | (n)) = 0, __dest)) \ |
1060 | : __strncat_g (__dest, (src), (n)); })) |
1061 | |
1062 | __STRING_INLINE char *__strncat_g (char *__dest, const char __src[], |
1063 | size_t __n); |
1064 | |
1065 | __STRING_INLINE char * |
1066 | __strncat_g (char *__dest, const char __src[], size_t __n) |
1067 | { |
1068 | register char *__tmp = __dest; |
1069 | register char __dummy; |
1070 | # ifdef __i686__ |
1071 | __asm__ __volatile__ |
1072 | ("repne; scasb\n" |
1073 | "movl %4, %3\n\t" |
1074 | "decl %1\n\t" |
1075 | "1:\n\t" |
1076 | "subl $1,%3\n\t" |
1077 | "jc 2f\n\t" |
1078 | "movb (%2),%b0\n\t" |
1079 | "movsb\n\t" |
1080 | "testb %b0,%b0\n\t" |
1081 | "jne 1b\n\t" |
1082 | "decl %1\n" |
1083 | "2:\n\t" |
1084 | "movb $0,(%1)" |
1085 | : "=&a" (__dummy), "=&D" (__tmp), "=&S" (__src), "=&c" (__n) |
1086 | : "g" (__n), "0" (0), "1" (__tmp), "2" (__src), "3" (0xffffffff) |
1087 | : "memory" , "cc" ); |
1088 | # else |
1089 | --__tmp; |
1090 | __asm__ __volatile__ |
1091 | ("1:\n\t" |
1092 | "cmpb $0,1(%1)\n\t" |
1093 | "leal 1(%1),%1\n\t" |
1094 | "jne 1b\n" |
1095 | "2:\n\t" |
1096 | "subl $1,%3\n\t" |
1097 | "jc 3f\n\t" |
1098 | "movb (%2),%b0\n\t" |
1099 | "leal 1(%2),%2\n\t" |
1100 | "movb %b0,(%1)\n\t" |
1101 | "leal 1(%1),%1\n\t" |
1102 | "testb %b0,%b0\n\t" |
1103 | "jne 2b\n\t" |
1104 | "decl %1\n" |
1105 | "3:\n\t" |
1106 | "movb $0,(%1)" |
1107 | : "=&q" (__dummy), "=&r" (__tmp), "=&r" (__src), "=&r" (__n) |
1108 | : "1" (__tmp), "2" (__src), "3" (__n) |
1109 | : "memory" , "cc" ); |
1110 | #endif |
1111 | return __dest; |
1112 | } |
1113 | |
1114 | |
1115 | /* Compare S1 and S2. */ |
1116 | # define _HAVE_STRING_ARCH_strcmp 1 |
1117 | # define strcmp(s1, s2) \ |
1118 | (__extension__ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \ |
1119 | && (sizeof ((s1)[0]) != 1 || strlen (s1) >= 4) \ |
1120 | && (sizeof ((s2)[0]) != 1 || strlen (s2) >= 4) \ |
1121 | ? memcmp ((const char *) (s1), (const char *) (s2), \ |
1122 | (strlen (s1) < strlen (s2) \ |
1123 | ? strlen (s1) : strlen (s2)) + 1) \ |
1124 | : (__builtin_constant_p (s1) && sizeof ((s1)[0]) == 1 \ |
1125 | && sizeof ((s2)[0]) == 1 && strlen (s1) < 4 \ |
1126 | ? (__builtin_constant_p (s2) && sizeof ((s2)[0]) == 1 \ |
1127 | ? __strcmp_cc ((const unsigned char *) (s1), \ |
1128 | (const unsigned char *) (s2), \ |
1129 | strlen (s1)) \ |
1130 | : __strcmp_cg ((const unsigned char *) (s1), \ |
1131 | (const unsigned char *) (s2), \ |
1132 | strlen (s1))) \ |
1133 | : (__builtin_constant_p (s2) && sizeof ((s1)[0]) == 1 \ |
1134 | && sizeof ((s2)[0]) == 1 && strlen (s2) < 4 \ |
1135 | ? (__builtin_constant_p (s1) \ |
1136 | ? __strcmp_cc ((const unsigned char *) (s1), \ |
1137 | (const unsigned char *) (s2), \ |
1138 | strlen (s2)) \ |
1139 | : __strcmp_gc ((const unsigned char *) (s1), \ |
1140 | (const unsigned char *) (s2), \ |
1141 | strlen (s2))) \ |
1142 | : __strcmp_gg ((s1), (s2)))))) |
1143 | |
1144 | # define __strcmp_cc(s1, s2, l) \ |
1145 | (__extension__ ({ register int __result = (s1)[0] - (s2)[0]; \ |
1146 | if (l > 0 && __result == 0) \ |
1147 | { \ |
1148 | __result = (s1)[1] - (s2)[1]; \ |
1149 | if (l > 1 && __result == 0) \ |
1150 | { \ |
1151 | __result = (s1)[2] - (s2)[2]; \ |
1152 | if (l > 2 && __result == 0) \ |
1153 | __result = (s1)[3] - (s2)[3]; \ |
1154 | } \ |
1155 | } \ |
1156 | __result; })) |
1157 | |
1158 | # define __strcmp_cg(s1, s2, l1) \ |
1159 | (__extension__ ({ const unsigned char *__s2 = (s2); \ |
1160 | register int __result = (s1)[0] - __s2[0]; \ |
1161 | if (l1 > 0 && __result == 0) \ |
1162 | { \ |
1163 | __result = (s1)[1] - __s2[1]; \ |
1164 | if (l1 > 1 && __result == 0) \ |
1165 | { \ |
1166 | __result = (s1)[2] - __s2[2]; \ |
1167 | if (l1 > 2 && __result == 0) \ |
1168 | __result = (s1)[3] - __s2[3]; \ |
1169 | } \ |
1170 | } \ |
1171 | __result; })) |
1172 | |
1173 | # define __strcmp_gc(s1, s2, l2) \ |
1174 | (__extension__ ({ const unsigned char *__s1 = (s1); \ |
1175 | register int __result = __s1[0] - (s2)[0]; \ |
1176 | if (l2 > 0 && __result == 0) \ |
1177 | { \ |
1178 | __result = __s1[1] - (s2)[1]; \ |
1179 | if (l2 > 1 && __result == 0) \ |
1180 | { \ |
1181 | __result = __s1[2] - (s2)[2]; \ |
1182 | if (l2 > 2 && __result == 0) \ |
1183 | __result = __s1[3] - (s2)[3]; \ |
1184 | } \ |
1185 | } \ |
1186 | __result; })) |
1187 | |
1188 | __STRING_INLINE int __strcmp_gg (const char *__s1, const char *__s2); |
1189 | |
1190 | __STRING_INLINE int |
1191 | __strcmp_gg (const char *__s1, const char *__s2) |
1192 | { |
1193 | register int __res; |
1194 | __asm__ __volatile__ |
1195 | ("1:\n\t" |
1196 | "movb (%1),%b0\n\t" |
1197 | "leal 1(%1),%1\n\t" |
1198 | "cmpb %b0,(%2)\n\t" |
1199 | "jne 2f\n\t" |
1200 | "leal 1(%2),%2\n\t" |
1201 | "testb %b0,%b0\n\t" |
1202 | "jne 1b\n\t" |
1203 | "xorl %0,%0\n\t" |
1204 | "jmp 3f\n" |
1205 | "2:\n\t" |
1206 | "movl $1,%0\n\t" |
1207 | "jb 3f\n\t" |
1208 | "negl %0\n" |
1209 | "3:" |
1210 | : "=q" (__res), "=&r" (__s1), "=&r" (__s2) |
1211 | : "1" (__s1), "2" (__s2), |
1212 | "m" ( *(struct { char __x[0xfffffff]; } *)__s1), |
1213 | "m" ( *(struct { char __x[0xfffffff]; } *)__s2) |
1214 | : "cc" ); |
1215 | return __res; |
1216 | } |
1217 | |
1218 | |
1219 | /* Compare N characters of S1 and S2. */ |
1220 | # define _HAVE_STRING_ARCH_strncmp 1 |
1221 | # define strncmp(s1, s2, n) \ |
1222 | (__extension__ (__builtin_constant_p (s1) && strlen (s1) < ((size_t) (n)) \ |
1223 | ? strcmp ((s1), (s2)) \ |
1224 | : (__builtin_constant_p (s2) && strlen (s2) < ((size_t) (n))\ |
1225 | ? strcmp ((s1), (s2)) \ |
1226 | : __strncmp_g ((s1), (s2), (n))))) |
1227 | |
1228 | __STRING_INLINE int __strncmp_g (const char *__s1, const char *__s2, |
1229 | size_t __n); |
1230 | |
1231 | __STRING_INLINE int |
1232 | __strncmp_g (const char *__s1, const char *__s2, size_t __n) |
1233 | { |
1234 | register int __res; |
1235 | __asm__ __volatile__ |
1236 | ("1:\n\t" |
1237 | "subl $1,%3\n\t" |
1238 | "jc 2f\n\t" |
1239 | "movb (%1),%b0\n\t" |
1240 | "incl %1\n\t" |
1241 | "cmpb %b0,(%2)\n\t" |
1242 | "jne 3f\n\t" |
1243 | "incl %2\n\t" |
1244 | "testb %b0,%b0\n\t" |
1245 | "jne 1b\n" |
1246 | "2:\n\t" |
1247 | "xorl %0,%0\n\t" |
1248 | "jmp 4f\n" |
1249 | "3:\n\t" |
1250 | "movl $1,%0\n\t" |
1251 | "jb 4f\n\t" |
1252 | "negl %0\n" |
1253 | "4:" |
1254 | : "=q" (__res), "=&r" (__s1), "=&r" (__s2), "=&r" (__n) |
1255 | : "1" (__s1), "2" (__s2), "3" (__n), |
1256 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s1), |
1257 | "m" ( *(struct { __extension__ char __x[__n]; } *)__s2) |
1258 | : "cc" ); |
1259 | return __res; |
1260 | } |
1261 | |
1262 | |
1263 | /* Find the first occurrence of C in S. */ |
1264 | # define _HAVE_STRING_ARCH_strchr 1 |
1265 | # define _USE_STRING_ARCH_strchr 1 |
1266 | # define strchr(s, c) \ |
1267 | (__extension__ (__builtin_constant_p (c) \ |
1268 | ? ((c) == '\0' \ |
1269 | ? (char *) __rawmemchr ((s), (c)) \ |
1270 | : __strchr_c ((s), ((c) & 0xff) << 8)) \ |
1271 | : __strchr_g ((s), (c)))) |
1272 | |
1273 | __STRING_INLINE char *__strchr_c (const char *__s, int __c); |
1274 | |
1275 | __STRING_INLINE char * |
1276 | __strchr_c (const char *__s, int __c) |
1277 | { |
1278 | register unsigned long int __d0; |
1279 | register char *__res; |
1280 | __asm__ __volatile__ |
1281 | ("1:\n\t" |
1282 | "movb (%0),%%al\n\t" |
1283 | "cmpb %%ah,%%al\n\t" |
1284 | "je 2f\n\t" |
1285 | "leal 1(%0),%0\n\t" |
1286 | "testb %%al,%%al\n\t" |
1287 | "jne 1b\n\t" |
1288 | "xorl %0,%0\n" |
1289 | "2:" |
1290 | : "=r" (__res), "=&a" (__d0) |
1291 | : "0" (__s), "1" (__c), |
1292 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1293 | : "cc" ); |
1294 | return __res; |
1295 | } |
1296 | |
1297 | __STRING_INLINE char *__strchr_g (const char *__s, int __c); |
1298 | |
1299 | __STRING_INLINE char * |
1300 | __strchr_g (const char *__s, int __c) |
1301 | { |
1302 | register unsigned long int __d0; |
1303 | register char *__res; |
1304 | __asm__ __volatile__ |
1305 | ("movb %%al,%%ah\n" |
1306 | "1:\n\t" |
1307 | "movb (%0),%%al\n\t" |
1308 | "cmpb %%ah,%%al\n\t" |
1309 | "je 2f\n\t" |
1310 | "leal 1(%0),%0\n\t" |
1311 | "testb %%al,%%al\n\t" |
1312 | "jne 1b\n\t" |
1313 | "xorl %0,%0\n" |
1314 | "2:" |
1315 | : "=r" (__res), "=&a" (__d0) |
1316 | : "0" (__s), "1" (__c), |
1317 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1318 | : "cc" ); |
1319 | return __res; |
1320 | } |
1321 | |
1322 | |
1323 | /* Find the first occurrence of C in S or the final NUL byte. */ |
1324 | # define _HAVE_STRING_ARCH_strchrnul 1 |
1325 | # define __strchrnul(s, c) \ |
1326 | (__extension__ (__builtin_constant_p (c) \ |
1327 | ? ((c) == '\0' \ |
1328 | ? (char *) __rawmemchr ((s), c) \ |
1329 | : __strchrnul_c ((s), ((c) & 0xff) << 8)) \ |
1330 | : __strchrnul_g ((s), c))) |
1331 | |
1332 | __STRING_INLINE char *__strchrnul_c (const char *__s, int __c); |
1333 | |
1334 | __STRING_INLINE char * |
1335 | __strchrnul_c (const char *__s, int __c) |
1336 | { |
1337 | register unsigned long int __d0; |
1338 | register char *__res; |
1339 | __asm__ __volatile__ |
1340 | ("1:\n\t" |
1341 | "movb (%0),%%al\n\t" |
1342 | "cmpb %%ah,%%al\n\t" |
1343 | "je 2f\n\t" |
1344 | "leal 1(%0),%0\n\t" |
1345 | "testb %%al,%%al\n\t" |
1346 | "jne 1b\n\t" |
1347 | "decl %0\n" |
1348 | "2:" |
1349 | : "=r" (__res), "=&a" (__d0) |
1350 | : "0" (__s), "1" (__c), |
1351 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1352 | : "cc" ); |
1353 | return __res; |
1354 | } |
1355 | |
1356 | __STRING_INLINE char *__strchrnul_g (const char *__s, int __c); |
1357 | |
1358 | __STRING_INLINE char * |
1359 | __strchrnul_g (const char *__s, int __c) |
1360 | { |
1361 | register unsigned long int __d0; |
1362 | register char *__res; |
1363 | __asm__ __volatile__ |
1364 | ("movb %%al,%%ah\n" |
1365 | "1:\n\t" |
1366 | "movb (%0),%%al\n\t" |
1367 | "cmpb %%ah,%%al\n\t" |
1368 | "je 2f\n\t" |
1369 | "leal 1(%0),%0\n\t" |
1370 | "testb %%al,%%al\n\t" |
1371 | "jne 1b\n\t" |
1372 | "decl %0\n" |
1373 | "2:" |
1374 | : "=r" (__res), "=&a" (__d0) |
1375 | : "0" (__s), "1" (__c), |
1376 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1377 | : "cc" ); |
1378 | return __res; |
1379 | } |
1380 | # ifdef __USE_GNU |
1381 | # define strchrnul(s, c) __strchrnul ((s), (c)) |
1382 | # endif |
1383 | |
1384 | |
1385 | # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED |
1386 | /* Find the first occurrence of C in S. This is the BSD name. */ |
1387 | # define _HAVE_STRING_ARCH_index 1 |
1388 | # define index(s, c) \ |
1389 | (__extension__ (__builtin_constant_p (c) \ |
1390 | ? __strchr_c ((s), ((c) & 0xff) << 8) \ |
1391 | : __strchr_g ((s), (c)))) |
1392 | # endif |
1393 | |
1394 | |
1395 | /* Find the last occurrence of C in S. */ |
1396 | # define _HAVE_STRING_ARCH_strrchr 1 |
1397 | # define strrchr(s, c) \ |
1398 | (__extension__ (__builtin_constant_p (c) \ |
1399 | ? __strrchr_c ((s), ((c) & 0xff) << 8) \ |
1400 | : __strrchr_g ((s), (c)))) |
1401 | |
1402 | # ifdef __i686__ |
1403 | __STRING_INLINE char *__strrchr_c (const char *__s, int __c); |
1404 | |
1405 | __STRING_INLINE char * |
1406 | __strrchr_c (const char *__s, int __c) |
1407 | { |
1408 | register unsigned long int __d0, __d1; |
1409 | register char *__res; |
1410 | __asm__ __volatile__ |
1411 | ("cld\n" |
1412 | "1:\n\t" |
1413 | "lodsb\n\t" |
1414 | "cmpb %h2,%b2\n\t" |
1415 | "cmove %1,%0\n\t" |
1416 | "testb %b2,%b2\n\t" |
1417 | "jne 1b" |
1418 | : "=d" (__res), "=&S" (__d0), "=&a" (__d1) |
1419 | : "0" (1), "1" (__s), "2" (__c), |
1420 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1421 | : "cc" ); |
1422 | return __res - 1; |
1423 | } |
1424 | |
1425 | __STRING_INLINE char *__strrchr_g (const char *__s, int __c); |
1426 | |
1427 | __STRING_INLINE char * |
1428 | __strrchr_g (const char *__s, int __c) |
1429 | { |
1430 | register unsigned long int __d0, __d1; |
1431 | register char *__res; |
1432 | __asm__ __volatile__ |
1433 | ("movb %b2,%h2\n" |
1434 | "cld\n\t" |
1435 | "1:\n\t" |
1436 | "lodsb\n\t" |
1437 | "cmpb %h2,%b2\n\t" |
1438 | "cmove %1,%0\n\t" |
1439 | "testb %b2,%b2\n\t" |
1440 | "jne 1b" |
1441 | : "=d" (__res), "=&S" (__d0), "=&a" (__d1) |
1442 | : "0" (1), "1" (__s), "2" (__c), |
1443 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1444 | : "cc" ); |
1445 | return __res - 1; |
1446 | } |
1447 | # else |
1448 | __STRING_INLINE char *__strrchr_c (const char *__s, int __c); |
1449 | |
1450 | __STRING_INLINE char * |
1451 | __strrchr_c (const char *__s, int __c) |
1452 | { |
1453 | register unsigned long int __d0, __d1; |
1454 | register char *__res; |
1455 | __asm__ __volatile__ |
1456 | ("cld\n" |
1457 | "1:\n\t" |
1458 | "lodsb\n\t" |
1459 | "cmpb %%ah,%%al\n\t" |
1460 | "jne 2f\n\t" |
1461 | "leal -1(%%esi),%0\n" |
1462 | "2:\n\t" |
1463 | "testb %%al,%%al\n\t" |
1464 | "jne 1b" |
1465 | : "=d" (__res), "=&S" (__d0), "=&a" (__d1) |
1466 | : "0" (0), "1" (__s), "2" (__c), |
1467 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1468 | : "cc" ); |
1469 | return __res; |
1470 | } |
1471 | |
1472 | __STRING_INLINE char *__strrchr_g (const char *__s, int __c); |
1473 | |
1474 | __STRING_INLINE char * |
1475 | __strrchr_g (const char *__s, int __c) |
1476 | { |
1477 | register unsigned long int __d0, __d1; |
1478 | register char *__res; |
1479 | __asm__ __volatile__ |
1480 | ("movb %%al,%%ah\n" |
1481 | "cld\n\t" |
1482 | "1:\n\t" |
1483 | "lodsb\n\t" |
1484 | "cmpb %%ah,%%al\n\t" |
1485 | "jne 2f\n\t" |
1486 | "leal -1(%%esi),%0\n" |
1487 | "2:\n\t" |
1488 | "testb %%al,%%al\n\t" |
1489 | "jne 1b" |
1490 | : "=r" (__res), "=&S" (__d0), "=&a" (__d1) |
1491 | : "0" (0), "1" (__s), "2" (__c), |
1492 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1493 | : "cc" ); |
1494 | return __res; |
1495 | } |
1496 | # endif |
1497 | |
1498 | |
1499 | # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED |
1500 | /* Find the last occurrence of C in S. This is the BSD name. */ |
1501 | # define _HAVE_STRING_ARCH_rindex 1 |
1502 | # define rindex(s, c) \ |
1503 | (__extension__ (__builtin_constant_p (c) \ |
1504 | ? __strrchr_c ((s), ((c) & 0xff) << 8) \ |
1505 | : __strrchr_g ((s), (c)))) |
1506 | # endif |
1507 | |
1508 | |
1509 | /* Return the length of the initial segment of S which |
1510 | consists entirely of characters not in REJECT. */ |
1511 | # define _HAVE_STRING_ARCH_strcspn 1 |
1512 | # define strcspn(s, reject) \ |
1513 | (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \ |
1514 | ? ((reject)[0] == '\0' \ |
1515 | ? strlen (s) \ |
1516 | : ((reject)[1] == '\0' \ |
1517 | ? __strcspn_c1 ((s), (((reject)[0] << 8) & 0xff00)) \ |
1518 | : __strcspn_cg ((s), (reject), strlen (reject)))) \ |
1519 | : __strcspn_g ((s), (reject)))) |
1520 | |
1521 | __STRING_INLINE size_t __strcspn_c1 (const char *__s, int __reject); |
1522 | |
1523 | # ifndef _FORCE_INLINES |
1524 | __STRING_INLINE size_t |
1525 | __strcspn_c1 (const char *__s, int __reject) |
1526 | { |
1527 | register unsigned long int __d0; |
1528 | register char *__res; |
1529 | __asm__ __volatile__ |
1530 | ("1:\n\t" |
1531 | "movb (%0),%%al\n\t" |
1532 | "leal 1(%0),%0\n\t" |
1533 | "cmpb %%ah,%%al\n\t" |
1534 | "je 2f\n\t" |
1535 | "testb %%al,%%al\n\t" |
1536 | "jne 1b\n" |
1537 | "2:" |
1538 | : "=r" (__res), "=&a" (__d0) |
1539 | : "0" (__s), "1" (__reject), |
1540 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1541 | : "cc" ); |
1542 | return (__res - 1) - __s; |
1543 | } |
1544 | # endif |
1545 | |
1546 | __STRING_INLINE size_t __strcspn_cg (const char *__s, const char __reject[], |
1547 | size_t __reject_len); |
1548 | |
1549 | __STRING_INLINE size_t |
1550 | __strcspn_cg (const char *__s, const char __reject[], size_t __reject_len) |
1551 | { |
1552 | register unsigned long int __d0, __d1, __d2; |
1553 | register const char *__res; |
1554 | __asm__ __volatile__ |
1555 | ("cld\n" |
1556 | "1:\n\t" |
1557 | "lodsb\n\t" |
1558 | "testb %%al,%%al\n\t" |
1559 | "je 2f\n\t" |
1560 | "movl %5,%%edi\n\t" |
1561 | "movl %6,%%ecx\n\t" |
1562 | "repne; scasb\n\t" |
1563 | "jne 1b\n" |
1564 | "2:" |
1565 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1566 | : "0" (__s), "d" (__reject), "g" (__reject_len) |
1567 | : "memory" , "cc" ); |
1568 | return (__res - 1) - __s; |
1569 | } |
1570 | |
1571 | __STRING_INLINE size_t __strcspn_g (const char *__s, const char *__reject); |
1572 | # ifdef __PIC__ |
1573 | |
1574 | __STRING_INLINE size_t |
1575 | __strcspn_g (const char *__s, const char *__reject) |
1576 | { |
1577 | register unsigned long int __d0, __d1, __d2; |
1578 | register const char *__res; |
1579 | __asm__ __volatile__ |
1580 | ("pushl %%ebx\n\t" |
1581 | "movl %4,%%edi\n\t" |
1582 | "cld\n\t" |
1583 | "repne; scasb\n\t" |
1584 | "notl %%ecx\n\t" |
1585 | "leal -1(%%ecx),%%ebx\n" |
1586 | "1:\n\t" |
1587 | "lodsb\n\t" |
1588 | "testb %%al,%%al\n\t" |
1589 | "je 2f\n\t" |
1590 | "movl %4,%%edi\n\t" |
1591 | "movl %%ebx,%%ecx\n\t" |
1592 | "repne; scasb\n\t" |
1593 | "jne 1b\n" |
1594 | "2:\n\t" |
1595 | "popl %%ebx" |
1596 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1597 | : "r" (__reject), "0" (__s), "1" (0), "2" (0xffffffff) |
1598 | : "memory" , "cc" ); |
1599 | return (__res - 1) - __s; |
1600 | } |
1601 | # else |
1602 | __STRING_INLINE size_t |
1603 | __strcspn_g (const char *__s, const char *__reject) |
1604 | { |
1605 | register unsigned long int __d0, __d1, __d2, __d3; |
1606 | register const char *__res; |
1607 | __asm__ __volatile__ |
1608 | ("cld\n\t" |
1609 | "repne; scasb\n\t" |
1610 | "notl %%ecx\n\t" |
1611 | "leal -1(%%ecx),%%edx\n" |
1612 | "1:\n\t" |
1613 | "lodsb\n\t" |
1614 | "testb %%al,%%al\n\t" |
1615 | "je 2f\n\t" |
1616 | "movl %%ebx,%%edi\n\t" |
1617 | "movl %%edx,%%ecx\n\t" |
1618 | "repne; scasb\n\t" |
1619 | "jne 1b\n" |
1620 | "2:" |
1621 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2), "=&d" (__d3) |
1622 | : "0" (__s), "1" (0), "2" (0xffffffff), "3" (__reject), "b" (__reject) |
1623 | /* Clobber memory, otherwise GCC cannot handle this. */ |
1624 | : "memory" , "cc" ); |
1625 | return (__res - 1) - __s; |
1626 | } |
1627 | # endif |
1628 | |
1629 | |
1630 | /* Return the length of the initial segment of S which |
1631 | consists entirely of characters in ACCEPT. */ |
1632 | # define _HAVE_STRING_ARCH_strspn 1 |
1633 | # define strspn(s, accept) \ |
1634 | (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ |
1635 | ? ((accept)[0] == '\0' \ |
1636 | ? ((void) (s), 0) \ |
1637 | : ((accept)[1] == '\0' \ |
1638 | ? __strspn_c1 ((s), (((accept)[0] << 8 ) & 0xff00)) \ |
1639 | : __strspn_cg ((s), (accept), strlen (accept)))) \ |
1640 | : __strspn_g ((s), (accept)))) |
1641 | |
1642 | # ifndef _FORCE_INLINES |
1643 | __STRING_INLINE size_t __strspn_c1 (const char *__s, int __accept); |
1644 | |
1645 | __STRING_INLINE size_t |
1646 | __strspn_c1 (const char *__s, int __accept) |
1647 | { |
1648 | register unsigned long int __d0; |
1649 | register char *__res; |
1650 | /* Please note that __accept never can be '\0'. */ |
1651 | __asm__ __volatile__ |
1652 | ("1:\n\t" |
1653 | "movb (%0),%b1\n\t" |
1654 | "leal 1(%0),%0\n\t" |
1655 | "cmpb %h1,%b1\n\t" |
1656 | "je 1b" |
1657 | : "=r" (__res), "=&q" (__d0) |
1658 | : "0" (__s), "1" (__accept), |
1659 | "m" ( *(struct { char __x[0xfffffff]; } *)__s) |
1660 | : "cc" ); |
1661 | return (__res - 1) - __s; |
1662 | } |
1663 | # endif |
1664 | |
1665 | __STRING_INLINE size_t __strspn_cg (const char *__s, const char __accept[], |
1666 | size_t __accept_len); |
1667 | |
1668 | __STRING_INLINE size_t |
1669 | __strspn_cg (const char *__s, const char __accept[], size_t __accept_len) |
1670 | { |
1671 | register unsigned long int __d0, __d1, __d2; |
1672 | register const char *__res; |
1673 | __asm__ __volatile__ |
1674 | ("cld\n" |
1675 | "1:\n\t" |
1676 | "lodsb\n\t" |
1677 | "testb %%al,%%al\n\t" |
1678 | "je 2f\n\t" |
1679 | "movl %5,%%edi\n\t" |
1680 | "movl %6,%%ecx\n\t" |
1681 | "repne; scasb\n\t" |
1682 | "je 1b\n" |
1683 | "2:" |
1684 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1685 | : "0" (__s), "g" (__accept), "g" (__accept_len), |
1686 | /* Since we do not know how large the memory we access it, use a |
1687 | really large amount. */ |
1688 | "m" ( *(struct { char __x[0xfffffff]; } *)__s), |
1689 | "m" ( *(struct { __extension__ char __x[__accept_len]; } *)__accept) |
1690 | : "cc" ); |
1691 | return (__res - 1) - __s; |
1692 | } |
1693 | |
1694 | __STRING_INLINE size_t __strspn_g (const char *__s, const char *__accept); |
1695 | # ifdef __PIC__ |
1696 | |
1697 | __STRING_INLINE size_t |
1698 | __strspn_g (const char *__s, const char *__accept) |
1699 | { |
1700 | register unsigned long int __d0, __d1, __d2; |
1701 | register const char *__res; |
1702 | __asm__ __volatile__ |
1703 | ("pushl %%ebx\n\t" |
1704 | "cld\n\t" |
1705 | "repne; scasb\n\t" |
1706 | "notl %%ecx\n\t" |
1707 | "leal -1(%%ecx),%%ebx\n" |
1708 | "1:\n\t" |
1709 | "lodsb\n\t" |
1710 | "testb %%al,%%al\n\t" |
1711 | "je 2f\n\t" |
1712 | "movl %%edx,%%edi\n\t" |
1713 | "movl %%ebx,%%ecx\n\t" |
1714 | "repne; scasb\n\t" |
1715 | "je 1b\n" |
1716 | "2:\n\t" |
1717 | "popl %%ebx" |
1718 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1719 | : "d" (__accept), "0" (__s), "1" (0), "2" (0xffffffff), "3" (__accept) |
1720 | : "memory" , "cc" ); |
1721 | return (__res - 1) - __s; |
1722 | } |
1723 | # else |
1724 | __STRING_INLINE size_t |
1725 | __strspn_g (const char *__s, const char *__accept) |
1726 | { |
1727 | register unsigned long int __d0, __d1, __d2, __d3; |
1728 | register const char *__res; |
1729 | __asm__ __volatile__ |
1730 | ("cld\n\t" |
1731 | "repne; scasb\n\t" |
1732 | "notl %%ecx\n\t" |
1733 | "leal -1(%%ecx),%%edx\n" |
1734 | "1:\n\t" |
1735 | "lodsb\n\t" |
1736 | "testb %%al,%%al\n\t" |
1737 | "je 2f\n\t" |
1738 | "movl %%ebx,%%edi\n\t" |
1739 | "movl %%edx,%%ecx\n\t" |
1740 | "repne; scasb\n\t" |
1741 | "je 1b\n" |
1742 | "2:" |
1743 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2), "=&d" (__d3) |
1744 | : "0" (__s), "1" (0), "2" (0xffffffff), "3" (__accept), "b" (__accept) |
1745 | : "memory" , "cc" ); |
1746 | return (__res - 1) - __s; |
1747 | } |
1748 | # endif |
1749 | |
1750 | |
1751 | /* Find the first occurrence in S of any character in ACCEPT. */ |
1752 | # define _HAVE_STRING_ARCH_strpbrk 1 |
1753 | # define strpbrk(s, accept) \ |
1754 | (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ |
1755 | ? ((accept)[0] == '\0' \ |
1756 | ? ((void) (s), (char *) 0) \ |
1757 | : ((accept)[1] == '\0' \ |
1758 | ? strchr ((s), (accept)[0]) \ |
1759 | : __strpbrk_cg ((s), (accept), strlen (accept)))) \ |
1760 | : __strpbrk_g ((s), (accept)))) |
1761 | |
1762 | __STRING_INLINE char *__strpbrk_cg (const char *__s, const char __accept[], |
1763 | size_t __accept_len); |
1764 | |
1765 | __STRING_INLINE char * |
1766 | __strpbrk_cg (const char *__s, const char __accept[], size_t __accept_len) |
1767 | { |
1768 | register unsigned long int __d0, __d1, __d2; |
1769 | register char *__res; |
1770 | __asm__ __volatile__ |
1771 | ("cld\n" |
1772 | "1:\n\t" |
1773 | "lodsb\n\t" |
1774 | "testb %%al,%%al\n\t" |
1775 | "je 2f\n\t" |
1776 | "movl %5,%%edi\n\t" |
1777 | "movl %6,%%ecx\n\t" |
1778 | "repne; scasb\n\t" |
1779 | "jne 1b\n\t" |
1780 | "decl %0\n\t" |
1781 | "jmp 3f\n" |
1782 | "2:\n\t" |
1783 | "xorl %0,%0\n" |
1784 | "3:" |
1785 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1786 | : "0" (__s), "d" (__accept), "g" (__accept_len) |
1787 | : "memory" , "cc" ); |
1788 | return __res; |
1789 | } |
1790 | |
1791 | __STRING_INLINE char *__strpbrk_g (const char *__s, const char *__accept); |
1792 | # ifdef __PIC__ |
1793 | |
1794 | __STRING_INLINE char * |
1795 | __strpbrk_g (const char *__s, const char *__accept) |
1796 | { |
1797 | register unsigned long int __d0, __d1, __d2; |
1798 | register char *__res; |
1799 | __asm__ __volatile__ |
1800 | ("pushl %%ebx\n\t" |
1801 | "movl %%edx,%%edi\n\t" |
1802 | "cld\n\t" |
1803 | "repne; scasb\n\t" |
1804 | "notl %%ecx\n\t" |
1805 | "leal -1(%%ecx),%%ebx\n" |
1806 | "1:\n\t" |
1807 | "lodsb\n\t" |
1808 | "testb %%al,%%al\n\t" |
1809 | "je 2f\n\t" |
1810 | "movl %%edx,%%edi\n\t" |
1811 | "movl %%ebx,%%ecx\n\t" |
1812 | "repne; scasb\n\t" |
1813 | "jne 1b\n\t" |
1814 | "decl %0\n\t" |
1815 | "jmp 3f\n" |
1816 | "2:\n\t" |
1817 | "xorl %0,%0\n" |
1818 | "3:\n\t" |
1819 | "popl %%ebx" |
1820 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&D" (__d2) |
1821 | : "d" (__accept), "0" (__s), "1" (0), "2" (0xffffffff) |
1822 | : "memory" , "cc" ); |
1823 | return __res; |
1824 | } |
1825 | # else |
1826 | __STRING_INLINE char * |
1827 | __strpbrk_g (const char *__s, const char *__accept) |
1828 | { |
1829 | register unsigned long int __d0, __d1, __d2, __d3; |
1830 | register char *__res; |
1831 | __asm__ __volatile__ |
1832 | ("movl %%ebx,%%edi\n\t" |
1833 | "cld\n\t" |
1834 | "repne; scasb\n\t" |
1835 | "notl %%ecx\n\t" |
1836 | "leal -1(%%ecx),%%edx\n" |
1837 | "1:\n\t" |
1838 | "lodsb\n\t" |
1839 | "testb %%al,%%al\n\t" |
1840 | "je 2f\n\t" |
1841 | "movl %%ebx,%%edi\n\t" |
1842 | "movl %%edx,%%ecx\n\t" |
1843 | "repne; scasb\n\t" |
1844 | "jne 1b\n\t" |
1845 | "decl %0\n\t" |
1846 | "jmp 3f\n" |
1847 | "2:\n\t" |
1848 | "xorl %0,%0\n" |
1849 | "3:" |
1850 | : "=S" (__res), "=&a" (__d0), "=&c" (__d1), "=&d" (__d2), "=&D" (__d3) |
1851 | : "0" (__s), "1" (0), "2" (0xffffffff), "b" (__accept) |
1852 | : "memory" , "cc" ); |
1853 | return __res; |
1854 | } |
1855 | # endif |
1856 | |
1857 | |
1858 | /* Find the first occurrence of NEEDLE in HAYSTACK. */ |
1859 | # define _HAVE_STRING_ARCH_strstr 1 |
1860 | # define strstr(haystack, needle) \ |
1861 | (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \ |
1862 | ? ((needle)[0] == '\0' \ |
1863 | ? (haystack) \ |
1864 | : ((needle)[1] == '\0' \ |
1865 | ? strchr ((haystack), (needle)[0]) \ |
1866 | : __strstr_cg ((haystack), (needle), \ |
1867 | strlen (needle)))) \ |
1868 | : __strstr_g ((haystack), (needle)))) |
1869 | |
1870 | /* Please note that this function need not handle NEEDLEs with a |
1871 | length shorter than two. */ |
1872 | __STRING_INLINE char *__strstr_cg (const char *__haystack, |
1873 | const char __needle[], |
1874 | size_t __needle_len); |
1875 | |
1876 | __STRING_INLINE char * |
1877 | __strstr_cg (const char *__haystack, const char __needle[], |
1878 | size_t __needle_len) |
1879 | { |
1880 | register unsigned long int __d0, __d1, __d2; |
1881 | register char *__res; |
1882 | __asm__ __volatile__ |
1883 | ("cld\n" \ |
1884 | "1:\n\t" |
1885 | "movl %6,%%edi\n\t" |
1886 | "movl %5,%%eax\n\t" |
1887 | "movl %4,%%ecx\n\t" |
1888 | "repe; cmpsb\n\t" |
1889 | "je 2f\n\t" |
1890 | "cmpb $0,-1(%%esi)\n\t" |
1891 | "leal 1(%%eax),%5\n\t" |
1892 | "jne 1b\n\t" |
1893 | "xorl %%eax,%%eax\n" |
1894 | "2:" |
1895 | : "=&a" (__res), "=&S" (__d0), "=&D" (__d1), "=&c" (__d2) |
1896 | : "g" (__needle_len), "1" (__haystack), "d" (__needle) |
1897 | : "memory" , "cc" ); |
1898 | return __res; |
1899 | } |
1900 | |
1901 | __STRING_INLINE char *__strstr_g (const char *__haystack, |
1902 | const char *__needle); |
1903 | # ifdef __PIC__ |
1904 | |
1905 | __STRING_INLINE char * |
1906 | __strstr_g (const char *__haystack, const char *__needle) |
1907 | { |
1908 | register unsigned long int __d0, __d1, __d2; |
1909 | register char *__res; |
1910 | __asm__ __volatile__ |
1911 | ("cld\n\t" |
1912 | "repne; scasb\n\t" |
1913 | "notl %%ecx\n\t" |
1914 | "pushl %%ebx\n\t" |
1915 | "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ |
1916 | "movl %%ecx,%%ebx\n" |
1917 | "1:\n\t" |
1918 | "movl %%edx,%%edi\n\t" |
1919 | "movl %%esi,%%eax\n\t" |
1920 | "movl %%ebx,%%ecx\n\t" |
1921 | "repe; cmpsb\n\t" |
1922 | "je 2f\n\t" /* also works for empty string, see above */ |
1923 | "cmpb $0,-1(%%esi)\n\t" |
1924 | "leal 1(%%eax),%%esi\n\t" |
1925 | "jne 1b\n\t" |
1926 | "xorl %%eax,%%eax\n" |
1927 | "2:\n\t" |
1928 | "popl %%ebx" |
1929 | : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2) |
1930 | : "0" (0), "1" (0xffffffff), "2" (__haystack), "3" (__needle), |
1931 | "d" (__needle) |
1932 | : "memory" , "cc" ); |
1933 | return __res; |
1934 | } |
1935 | # else |
1936 | __STRING_INLINE char * |
1937 | __strstr_g (const char *__haystack, const char *__needle) |
1938 | { |
1939 | register unsigned long int __d0, __d1, __d2, __d3; |
1940 | register char *__res; |
1941 | __asm__ __volatile__ |
1942 | ("cld\n\t" |
1943 | "repne; scasb\n\t" |
1944 | "notl %%ecx\n\t" |
1945 | "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ |
1946 | "movl %%ecx,%%edx\n" |
1947 | "1:\n\t" |
1948 | "movl %%ebx,%%edi\n\t" |
1949 | "movl %%esi,%%eax\n\t" |
1950 | "movl %%edx,%%ecx\n\t" |
1951 | "repe; cmpsb\n\t" |
1952 | "je 2f\n\t" /* also works for empty string, see above */ |
1953 | "cmpb $0,-1(%%esi)\n\t" |
1954 | "leal 1(%%eax),%%esi\n\t" |
1955 | "jne 1b\n\t" |
1956 | "xorl %%eax,%%eax\n" |
1957 | "2:" |
1958 | : "=&a" (__res), "=&c" (__d0), "=&S" (__d1), "=&D" (__d2), "=&d" (__d3) |
1959 | : "0" (0), "1" (0xffffffff), "2" (__haystack), "3" (__needle), |
1960 | "b" (__needle) |
1961 | : "memory" , "cc" ); |
1962 | return __res; |
1963 | } |
1964 | # endif |
1965 | |
1966 | |
1967 | /* Bit find functions. We define only the i686 version since for the other |
1968 | processors gcc generates good code. */ |
1969 | # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED |
1970 | # ifdef __i686__ |
1971 | # define _HAVE_STRING_ARCH_ffs 1 |
1972 | # define ffs(word) (__builtin_constant_p (word) \ |
1973 | ? __builtin_ffs (word) \ |
1974 | : ({ int __cnt, __tmp; \ |
1975 | __asm__ __volatile__ \ |
1976 | ("bsfl %2,%0\n\t" \ |
1977 | "cmovel %1,%0" \ |
1978 | : "=&r" (__cnt), "=r" (__tmp) \ |
1979 | : "rm" (word), "1" (-1)); \ |
1980 | __cnt + 1; })) |
1981 | |
1982 | # ifndef ffsl |
1983 | # define ffsl(word) ffs(word) |
1984 | # endif |
1985 | # endif /* i686 */ |
1986 | # endif /* Misc || X/Open */ |
1987 | |
1988 | # ifndef _FORCE_INLINES |
1989 | # undef __STRING_INLINE |
1990 | # endif |
1991 | |
1992 | # endif /* use string inlines && GNU CC */ |
1993 | |
1994 | #endif |
1995 | |