Changes to be able to build system
[reactos.git] / reactos / include / internal / string.h
1 #ifndef _I386_STRING_H_
2 #define _I386_STRING_H_
3
4 #ifndef _LINUX_TYPES_H
5 #include <internal/types.h>
6 #endif
7
8 #ifndef _INTERNAL_STDDEF_H
9 #include <internal/stddef.h>
10 #endif
11
12 /*
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).
17 *
18 * Also, the byte strings actually work correctly. Forget
19 * the i486 routines for now as they may be broken..
20 */
21 #if FIXED_486_STRING && (CPU == 486 || CPU == 586)
22 #include <asm/string-486.h>
23 #else
24
25 /*
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 :-)
33 *
34 * NO Copyright (C) 1991, 1992 Linus Torvalds,
35 * consider these trivial functions to be PD.
36 */
37
38 #define __HAVE_ARCH_STRCPY
39 extern inline char * strcpy(char * dest,const char *src)
40 {
41 int d0, d1, d2;
42 __asm__ __volatile__(
43 "cld\n"
44 "1:\tlodsb\n\t"
45 "stosb\n\t"
46 "testb %%al,%%al\n\t"
47 "jne 1b"
48 : "=&S" (d0), "=&D" (d1), "=&a" (d2)
49 :"0" (src),"1" (dest) : "memory");
50 return dest;
51 }
52
53 #define __HAVE_ARCH_STRNCPY
54 extern inline char * strncpy(char * dest,const char *src,size_t count)
55 {
56 int d0, d1, d2, d3;
57 __asm__ __volatile__(
58 "cld\n"
59 "1:\tdecl %2\n\t"
60 "js 2f\n\t"
61 "lodsb\n\t"
62 "stosb\n\t"
63 "testb %%al,%%al\n\t"
64 "jne 1b\n\t"
65 "rep\n\t"
66 "stosb\n"
67 "2:"
68 : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
69 :"0" (src),"1" (dest),"2" (count) : "memory");
70 return dest;
71 }
72
73 #define __HAVE_ARCH_STRCAT
74 extern inline char * strcat(char * dest,const char * src)
75 {
76 int d0, d1, d2, d3;
77 __asm__ __volatile__(
78 "cld\n\t"
79 "repne\n\t"
80 "scasb\n\t"
81 "decl %1\n"
82 "1:\tlodsb\n\t"
83 "stosb\n\t"
84 "testb %%al,%%al\n\t"
85 "jne 1b"
86 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
87 : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
88 return dest;
89 }
90
91 #define __HAVE_ARCH_STRNCAT
92 extern inline char * strncat(char * dest,const char * src,size_t count)
93 {
94 int d0, d1, d2, d3;
95 __asm__ __volatile__(
96 "cld\n\t"
97 "repne\n\t"
98 "scasb\n\t"
99 "decl %1\n\t"
100 "movl %8,%3\n"
101 "1:\tdecl %3\n\t"
102 "js 2f\n\t"
103 "lodsb\n\t"
104 "stosb\n\t"
105 "testb %%al,%%al\n\t"
106 "jne 1b\n"
107 "2:\txorl %2,%2\n\t"
108 "stosb"
109 : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
110 : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
111 : "memory");
112 return dest;
113 }
114
115 #define __HAVE_ARCH_STRCMP
116 extern inline int strcmp(const char * cs,const char * ct)
117 {
118 int d0, d1;
119 register int __res;
120 __asm__ __volatile__(
121 "cld\n"
122 "1:\tlodsb\n\t"
123 "scasb\n\t"
124 "jne 2f\n\t"
125 "testb %%al,%%al\n\t"
126 "jne 1b\n\t"
127 "xorl %%eax,%%eax\n\t"
128 "jmp 3f\n"
129 "2:\tsbbl %%eax,%%eax\n\t"
130 "orb $1,%%al\n"
131 "3:"
132 :"=a" (__res), "=&S" (d0), "=&D" (d1)
133 :"1" (cs),"2" (ct));
134 return __res;
135 }
136
137 #define __HAVE_ARCH_STRNCMP
138 extern inline int strncmp(const char * cs,const char * ct,size_t count)
139 {
140 register int __res;
141 int d0, d1, d2;
142 __asm__ __volatile__(
143 "cld\n"
144 "1:\tdecl %3\n\t"
145 "js 2f\n\t"
146 "lodsb\n\t"
147 "scasb\n\t"
148 "jne 3f\n\t"
149 "testb %%al,%%al\n\t"
150 "jne 1b\n"
151 "2:\txorl %%eax,%%eax\n\t"
152 "jmp 4f\n"
153 "3:\tsbbl %%eax,%%eax\n\t"
154 "orb $1,%%al\n"
155 "4:"
156 :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
157 :"1" (cs),"2" (ct),"3" (count));
158 return __res;
159 }
160
161 #define __HAVE_ARCH_STRCHR
162 extern inline char * strchr(const char * s, int c)
163 {
164 int d0;
165 register char * __res;
166 __asm__ __volatile__(
167 "cld\n\t"
168 "movb %%al,%%ah\n"
169 "1:\tlodsb\n\t"
170 "cmpb %%ah,%%al\n\t"
171 "je 2f\n\t"
172 "testb %%al,%%al\n\t"
173 "jne 1b\n\t"
174 "movl $1,%1\n"
175 "2:\tmovl %1,%0\n\t"
176 "decl %0"
177 :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
178 return __res;
179 }
180
181 #define __HAVE_ARCH_STRRCHR
182 extern inline char * strrchr(const char * s, int c)
183 {
184 int d0, d1;
185 register char * __res;
186 __asm__ __volatile__(
187 "cld\n\t"
188 "movb %%al,%%ah\n"
189 "1:\tlodsb\n\t"
190 "cmpb %%ah,%%al\n\t"
191 "jne 2f\n\t"
192 "leal -1(%%esi),%0\n"
193 "2:\ttestb %%al,%%al\n\t"
194 "jne 1b"
195 :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
196 return __res;
197 }
198
199 #define __HAVE_ARCH_STRLEN
200 extern inline size_t strlen(const char * s)
201 {
202 int d0;
203 register int __res;
204 __asm__ __volatile__(
205 "cld\n\t"
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" (0xffffffff));
211 return __res;
212 }
213
214 extern inline void * __memcpy(void * to, const void * from, size_t n)
215 {
216 int d0, d1, d2;
217 __asm__ __volatile__(
218 "cld\n\t"
219 "rep ; movsl\n\t"
220 "testb $2,%b4\n\t"
221 "je 1f\n\t"
222 "movsw\n"
223 "1:\ttestb $1,%b4\n\t"
224 "je 2f\n\t"
225 "movsb\n"
226 "2:"
227 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
228 :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
229 : "memory");
230 return (to);
231 }
232
233 /*
234 * This looks horribly ugly, but the compiler can optimize it totally,
235 * as the count is constant.
236 */
237 extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
238 {
239 switch (n) {
240 case 0:
241 return to;
242 case 1:
243 *(unsigned char *)to = *(const unsigned char *)from;
244 return to;
245 case 2:
246 *(unsigned short *)to = *(const unsigned short *)from;
247 return to;
248 case 3:
249 *(unsigned short *)to = *(const unsigned short *)from;
250 *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
251 return to;
252 case 4:
253 *(unsigned long *)to = *(const unsigned long *)from;
254 return to;
255 case 6: /* for Ethernet addresses */
256 *(unsigned long *)to = *(const unsigned long *)from;
257 *(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
258 return to;
259 case 8:
260 *(unsigned long *)to = *(const unsigned long *)from;
261 *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
262 return to;
263 case 12:
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);
267 return to;
268 case 16:
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);
273 return to;
274 case 20:
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);
280 return to;
281 }
282 #define COMMON(x) \
283 __asm__ __volatile__( \
284 "cld\n\t" \
285 "rep ; movsl" \
286 x \
287 : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
288 : "0" (n/4),"1" ((long) to),"2" ((long) from) \
289 : "memory");
290 {
291 int d0, d1, d2;
292 switch (n % 4) {
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;
297 }
298 }
299
300 #undef COMMON
301 }
302
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)))
308
309 #define __HAVE_ARCH_MEMMOVE
310 extern inline void * memmove(void * dest,const void * src, size_t n)
311 {
312 int d0, d1, d2;
313 if (dest<src)
314 __asm__ __volatile__(
315 "cld\n\t"
316 "rep\n\t"
317 "movsb"
318 : "=&c" (d0), "=&S" (d1), "=&D" (d2)
319 :"0" (n),"1" (src),"2" (dest)
320 : "memory");
321 else
322 __asm__ __volatile__(
323 "std\n\t"
324 "rep\n\t"
325 "movsb\n\t"
326 "cld"
327 : "=&c" (d0), "=&S" (d1), "=&D" (d2)
328 :"0" (n),
329 "1" (n-1+(const char *)src),
330 "2" (n-1+(char *)dest)
331 :"memory");
332 return dest;
333 }
334
335 #define memcmp __builtin_memcmp
336
337 #define __HAVE_ARCH_MEMCHR
338 extern inline void * memchr(const void * cs,int c,size_t count)
339 {
340 int d0;
341 register void * __res;
342 if (!count)
343 return NULL;
344 __asm__ __volatile__(
345 "cld\n\t"
346 "repne\n\t"
347 "scasb\n\t"
348 "je 1f\n\t"
349 "movl $1,%0\n"
350 "1:\tdecl %0"
351 :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
352 return __res;
353 }
354
355 extern inline void * __memset_generic(void * s, char c,size_t count)
356 {
357 int d0, d1;
358 __asm__ __volatile__(
359 "cld\n\t"
360 "rep\n\t"
361 "stosb"
362 : "=&c" (d0), "=&D" (d1)
363 :"a" (c),"1" (s),"0" (count)
364 :"memory");
365 return s;
366 }
367
368 /* we might want to write optimized versions of these later */
369 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
370
371 /*
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..
375 */
376 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
377 {
378 int d0, d1;
379 __asm__ __volatile__(
380 "cld\n\t"
381 "rep ; stosl\n\t"
382 "testb $2,%b3\n\t"
383 "je 1f\n\t"
384 "stosw\n"
385 "1:\ttestb $1,%b3\n\t"
386 "je 2f\n\t"
387 "stosb\n"
388 "2:"
389 : "=&c" (d0), "=&D" (d1)
390 :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
391 :"memory");
392 return (s);
393 }
394
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)
398 {
399 int d0;
400 register int __res;
401 __asm__ __volatile__(
402 "movl %2,%0\n\t"
403 "jmp 2f\n"
404 "1:\tcmpb $0,(%0)\n\t"
405 "je 3f\n\t"
406 "incl %0\n"
407 "2:\tdecl %1\n\t"
408 "cmpl $-1,%1\n\t"
409 "jne 1b\n"
410 "3:\tsubl %2,%0"
411 :"=a" (__res), "=&d" (d0)
412 :"c" (s),"1" (count));
413 return __res;
414 }
415 /* end of additional stuff */
416
417 /*
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..
420 */
421 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
422 {
423 switch (count) {
424 case 0:
425 return s;
426 case 1:
427 *(unsigned char *)s = pattern;
428 return s;
429 case 2:
430 *(unsigned short *)s = pattern;
431 return s;
432 case 3:
433 *(unsigned short *)s = pattern;
434 *(2+(unsigned char *)s) = pattern;
435 return s;
436 case 4:
437 *(unsigned long *)s = pattern;
438 return s;
439 }
440 #define COMMON(x) \
441 __asm__ __volatile__("cld\n\t" \
442 "rep ; stosl" \
443 x \
444 : "=&c" (d0), "=&D" (d1) \
445 : "a" (pattern),"0" (count/4),"1" ((long) s) \
446 : "memory")
447 {
448 int d0, d1;
449 switch (count % 4) {
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;
454 }
455 }
456
457 #undef COMMON
458 }
459
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)))
464
465 #define __memset(s, c, count) \
466 (__builtin_constant_p(count) ? \
467 __constant_count_memset((s),(c),(count)) : \
468 __memset_generic((s),(c),(count)))
469
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)))
475
476 /*
477 * find the first occurrence of byte 'c', or 1 past the area if none
478 */
479 #define __HAVE_ARCH_MEMSCAN
480 extern inline void * memscan(void * addr, int c, size_t size)
481 {
482 if (!size)
483 return addr;
484 __asm__("cld
485 repnz; scasb
486 jnz 1f
487 dec %%edi
488 1: "
489 : "=D" (addr), "=c" (size)
490 : "0" (addr), "1" (size), "a" (c));
491 return addr;
492 }
493
494 #endif
495 #endif