OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [include/] [asm-i386/] [string.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1633 jcastillo
#ifndef _I386_STRING_H_
2
#define _I386_STRING_H_
3
 
4
/*
5
 * On a 486 or Pentium, we are better off not using the
6
 * byte string operations. But on a 386 or a PPro the
7
 * byte string ops are faster than doing it by hand
8
 * (MUCH faster on a Pentium).
9
 *
10
 * Also, the byte strings actually work correctly. Forget
11
 * the i486 routines for now as they may be broken..
12
 */
13
#if FIXED_486_STRING && (CPU == 486 || CPU == 586)
14
#include <asm/string-486.h>
15
#else
16
 
17
/*
18
 * This string-include defines all string functions as inline
19
 * functions. Use gcc. It also assumes ds=es=data space, this should be
20
 * normal. Most of the string-functions are rather heavily hand-optimized,
21
 * see especially strtok,strstr,str[c]spn. They should work, but are not
22
 * very easy to understand. Everything is done entirely within the register
23
 * set, making the functions fast and clean. String instructions have been
24
 * used through-out, making for "slightly" unclear code :-)
25
 *
26
 *              Copyright (C) 1991, 1992 Linus Torvalds
27
 */
28
 
29
#define __HAVE_ARCH_STRCPY
30
extern inline char * strcpy(char * dest,const char *src)
31
{
32
__asm__ __volatile__(
33
        "cld\n"
34
        "1:\tlodsb\n\t"
35
        "stosb\n\t"
36
        "testb %%al,%%al\n\t"
37
        "jne 1b"
38
        : /* no output */
39
        :"S" (src),"D" (dest):"si","di","ax","memory");
40
return dest;
41
}
42
 
43
#define __HAVE_ARCH_STRNCPY
44
extern inline char * strncpy(char * dest,const char *src,size_t count)
45
{
46
__asm__ __volatile__(
47
        "cld\n"
48
        "1:\tdecl %2\n\t"
49
        "js 2f\n\t"
50
        "lodsb\n\t"
51
        "stosb\n\t"
52
        "testb %%al,%%al\n\t"
53
        "jne 1b\n\t"
54
        "rep\n\t"
55
        "stosb\n"
56
        "2:"
57
        : /* no output */
58
        :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory");
59
return dest;
60
}
61
 
62
#define __HAVE_ARCH_STRCAT
63
extern inline char * strcat(char * dest,const char * src)
64
{
65
__asm__ __volatile__(
66
        "cld\n\t"
67
        "repne\n\t"
68
        "scasb\n\t"
69
        "decl %1\n"
70
        "1:\tlodsb\n\t"
71
        "stosb\n\t"
72
        "testb %%al,%%al\n\t"
73
        "jne 1b"
74
        : /* no output */
75
        :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
76
return dest;
77
}
78
 
79
#define __HAVE_ARCH_STRNCAT
80
extern inline char * strncat(char * dest,const char * src,size_t count)
81
{
82
__asm__ __volatile__(
83
        "cld\n\t"
84
        "repne\n\t"
85
        "scasb\n\t"
86
        "decl %1\n\t"
87
        "movl %4,%3\n"
88
        "1:\tdecl %3\n\t"
89
        "js 2f\n\t"
90
        "lodsb\n\t"
91
        "stosb\n\t"
92
        "testb %%al,%%al\n\t"
93
        "jne 1b\n"
94
        "2:\txorl %2,%2\n\t"
95
        "stosb"
96
        : /* no output */
97
        :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
98
        :"si","di","ax","cx","memory");
99
return dest;
100
}
101
 
102
#define __HAVE_ARCH_STRCMP
103
extern inline int strcmp(const char * cs,const char * ct)
104
{
105
register int __res;
106
__asm__ __volatile__(
107
        "cld\n"
108
        "1:\tlodsb\n\t"
109
        "scasb\n\t"
110
        "jne 2f\n\t"
111
        "testb %%al,%%al\n\t"
112
        "jne 1b\n\t"
113
        "xorl %%eax,%%eax\n\t"
114
        "jmp 3f\n"
115
        "2:\tsbbl %%eax,%%eax\n\t"
116
        "orb $1,%%eax\n"
117
        "3:"
118
        :"=a" (__res):"S" (cs),"D" (ct):"si","di");
119
return __res;
120
}
121
 
122
#define __HAVE_ARCH_STRNCMP
123
extern inline int strncmp(const char * cs,const char * ct,size_t count)
124
{
125
register int __res;
126
__asm__ __volatile__(
127
        "cld\n"
128
        "1:\tdecl %3\n\t"
129
        "js 2f\n\t"
130
        "lodsb\n\t"
131
        "scasb\n\t"
132
        "jne 3f\n\t"
133
        "testb %%al,%%al\n\t"
134
        "jne 1b\n"
135
        "2:\txorl %%eax,%%eax\n\t"
136
        "jmp 4f\n"
137
        "3:\tsbbl %%eax,%%eax\n\t"
138
        "orb $1,%%al\n"
139
        "4:"
140
        :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx");
141
return __res;
142
}
143
 
144
#define __HAVE_ARCH_STRCHR
145
extern inline char * strchr(const char * s, int c)
146
{
147
register char * __res;
148
__asm__ __volatile__(
149
        "cld\n\t"
150
        "movb %%al,%%ah\n"
151
        "1:\tlodsb\n\t"
152
        "cmpb %%ah,%%al\n\t"
153
        "je 2f\n\t"
154
        "testb %%al,%%al\n\t"
155
        "jne 1b\n\t"
156
        "movl $1,%1\n"
157
        "2:\tmovl %1,%0\n\t"
158
        "decl %0"
159
        :"=a" (__res):"S" (s),"0" (c):"si");
160
return __res;
161
}
162
 
163
#define __HAVE_ARCH_STRRCHR
164
extern inline char * strrchr(const char * s, int c)
165
{
166
register char * __res;
167
__asm__ __volatile__(
168
        "cld\n\t"
169
        "movb %%al,%%ah\n"
170
        "1:\tlodsb\n\t"
171
        "cmpb %%ah,%%al\n\t"
172
        "jne 2f\n\t"
173
        "leal -1(%%esi),%0\n"
174
        "2:\ttestb %%al,%%al\n\t"
175
        "jne 1b"
176
        :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
177
return __res;
178
}
179
 
180
#define __HAVE_ARCH_STRSPN
181
extern inline size_t strspn(const char * cs, const char * ct)
182
{
183
register char * __res;
184
__asm__ __volatile__(
185
        "cld\n\t"
186
        "movl %4,%%edi\n\t"
187
        "repne\n\t"
188
        "scasb\n\t"
189
        "notl %%ecx\n\t"
190
        "decl %%ecx\n\t"
191
        "movl %%ecx,%%edx\n"
192
        "1:\tlodsb\n\t"
193
        "testb %%al,%%al\n\t"
194
        "je 2f\n\t"
195
        "movl %4,%%edi\n\t"
196
        "movl %%edx,%%ecx\n\t"
197
        "repne\n\t"
198
        "scasb\n\t"
199
        "je 1b\n"
200
        "2:\tdecl %0"
201
        :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
202
        :"ax","cx","dx","di");
203
return __res-cs;
204
}
205
 
206
#define __HAVE_ARCH_STRCSPN
207
extern inline size_t strcspn(const char * cs, const char * ct)
208
{
209
register char * __res;
210
__asm__ __volatile__(
211
        "cld\n\t"
212
        "movl %4,%%edi\n\t"
213
        "repne\n\t"
214
        "scasb\n\t"
215
        "notl %%ecx\n\t"
216
        "decl %%ecx\n\t"
217
        "movl %%ecx,%%edx\n"
218
        "1:\tlodsb\n\t"
219
        "testb %%al,%%al\n\t"
220
        "je 2f\n\t"
221
        "movl %4,%%edi\n\t"
222
        "movl %%edx,%%ecx\n\t"
223
        "repne\n\t"
224
        "scasb\n\t"
225
        "jne 1b\n"
226
        "2:\tdecl %0"
227
        :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
228
        :"ax","cx","dx","di");
229
return __res-cs;
230
}
231
 
232
#define __HAVE_ARCH_STRPBRK
233
extern inline char * strpbrk(const char * cs,const char * ct)
234
{
235
register char * __res;
236
__asm__ __volatile__(
237
        "cld\n\t"
238
        "movl %4,%%edi\n\t"
239
        "repne\n\t"
240
        "scasb\n\t"
241
        "notl %%ecx\n\t"
242
        "decl %%ecx\n\t"
243
        "movl %%ecx,%%edx\n"
244
        "1:\tlodsb\n\t"
245
        "testb %%al,%%al\n\t"
246
        "je 2f\n\t"
247
        "movl %4,%%edi\n\t"
248
        "movl %%edx,%%ecx\n\t"
249
        "repne\n\t"
250
        "scasb\n\t"
251
        "jne 1b\n\t"
252
        "decl %0\n\t"
253
        "jmp 3f\n"
254
        "2:\txorl %0,%0\n"
255
        "3:"
256
        :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
257
        :"ax","cx","dx","di");
258
return __res;
259
}
260
 
261
#define __HAVE_ARCH_STRSTR
262
extern inline char * strstr(const char * cs,const char * ct)
263
{
264
register char * __res;
265
__asm__ __volatile__(
266
        "cld\n\t" \
267
        "movl %4,%%edi\n\t"
268
        "repne\n\t"
269
        "scasb\n\t"
270
        "notl %%ecx\n\t"
271
        "decl %%ecx\n\t"        /* NOTE! This also sets Z if searchstring='' */
272
        "movl %%ecx,%%edx\n"
273
        "1:\tmovl %4,%%edi\n\t"
274
        "movl %%esi,%%eax\n\t"
275
        "movl %%edx,%%ecx\n\t"
276
        "repe\n\t"
277
        "cmpsb\n\t"
278
        "je 2f\n\t"             /* also works for empty string, see above */
279
        "xchgl %%eax,%%esi\n\t"
280
        "incl %%esi\n\t"
281
        "cmpb $0,-1(%%eax)\n\t"
282
        "jne 1b\n\t"
283
        "xorl %%eax,%%eax\n\t"
284
        "2:"
285
        :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
286
        :"cx","dx","di","si");
287
return __res;
288
}
289
 
290
#define __HAVE_ARCH_STRLEN
291
extern inline size_t strlen(const char * s)
292
{
293
register int __res;
294
__asm__ __volatile__(
295
        "cld\n\t"
296
        "repne\n\t"
297
        "scasb\n\t"
298
        "notl %0\n\t"
299
        "decl %0"
300
        :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
301
return __res;
302
}
303
 
304
#define __HAVE_ARCH_STRTOK
305
extern inline char * strtok(char * s,const char * ct)
306
{
307
register char * __res;
308
__asm__ __volatile__(
309
        "testl %1,%1\n\t"
310
        "jne 1f\n\t"
311
        "testl %0,%0\n\t"
312
        "je 8f\n\t"
313
        "movl %0,%1\n"
314
        "1:\txorl %0,%0\n\t"
315
        "movl $-1,%%ecx\n\t"
316
        "xorl %%eax,%%eax\n\t"
317
        "cld\n\t"
318
        "movl %4,%%edi\n\t"
319
        "repne\n\t"
320
        "scasb\n\t"
321
        "notl %%ecx\n\t"
322
        "decl %%ecx\n\t"
323
        "je 7f\n\t"                     /* empty delimiter-string */
324
        "movl %%ecx,%%edx\n"
325
        "2:\tlodsb\n\t"
326
        "testb %%al,%%al\n\t"
327
        "je 7f\n\t"
328
        "movl %4,%%edi\n\t"
329
        "movl %%edx,%%ecx\n\t"
330
        "repne\n\t"
331
        "scasb\n\t"
332
        "je 2b\n\t"
333
        "decl %1\n\t"
334
        "cmpb $0,(%1)\n\t"
335
        "je 7f\n\t"
336
        "movl %1,%0\n"
337
        "3:\tlodsb\n\t"
338
        "testb %%al,%%al\n\t"
339
        "je 5f\n\t"
340
        "movl %4,%%edi\n\t"
341
        "movl %%edx,%%ecx\n\t"
342
        "repne\n\t"
343
        "scasb\n\t"
344
        "jne 3b\n\t"
345
        "decl %1\n\t"
346
        "cmpb $0,(%1)\n\t"
347
        "je 5f\n\t"
348
        "movb $0,(%1)\n\t"
349
        "incl %1\n\t"
350
        "jmp 6f\n"
351
        "5:\txorl %1,%1\n"
352
        "6:\tcmpb $0,(%0)\n\t"
353
        "jne 7f\n\t"
354
        "xorl %0,%0\n"
355
        "7:\ttestl %0,%0\n\t"
356
        "jne 8f\n\t"
357
        "movl %0,%1\n"
358
        "8:"
359
        :"=b" (__res),"=S" (___strtok)
360
        :"0" (___strtok),"1" (s),"g" (ct)
361
        :"ax","cx","dx","di","memory");
362
return __res;
363
}
364
 
365
extern inline void * __memcpy(void * to, const void * from, size_t n)
366
{
367
__asm__ __volatile__(
368
        "cld\n\t"
369
        "rep ; movsl\n\t"
370
        "testb $2,%b1\n\t"
371
        "je 1f\n\t"
372
        "movsw\n"
373
        "1:\ttestb $1,%b1\n\t"
374
        "je 2f\n\t"
375
        "movsb\n"
376
        "2:"
377
        : /* no output */
378
        :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from)
379
        : "cx","di","si","memory");
380
return (to);
381
}
382
 
383
/*
384
 * This looks horribly ugly, but the compiler can optimize it totally,
385
 * as the count is constant.
386
 */
387
extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
388
{
389
        switch (n) {
390
                case 0:
391
                        return to;
392
                case 1:
393
                        *(unsigned char *)to = *(const unsigned char *)from;
394
                        return to;
395
                case 2:
396
                        *(unsigned short *)to = *(const unsigned short *)from;
397
                        return to;
398
                case 3:
399
                        *(unsigned short *)to = *(const unsigned short *)from;
400
                        *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
401
                        return to;
402
                case 4:
403
                        *(unsigned long *)to = *(const unsigned long *)from;
404
                        return to;
405
                case 8:
406
                        *(unsigned long *)to = *(const unsigned long *)from;
407
                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
408
                        return to;
409
                case 12:
410
                        *(unsigned long *)to = *(const unsigned long *)from;
411
                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
412
                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
413
                        return to;
414
                case 16:
415
                        *(unsigned long *)to = *(const unsigned long *)from;
416
                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
417
                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
418
                        *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
419
                        return to;
420
                case 20:
421
                        *(unsigned long *)to = *(const unsigned long *)from;
422
                        *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
423
                        *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
424
                        *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
425
                        *(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
426
                        return to;
427
        }
428
#define COMMON(x) \
429
__asm__("cld\n\t" \
430
        "rep ; movsl" \
431
        x \
432
        : /* no outputs */ \
433
        : "c" (n/4),"D" ((long) to),"S" ((long) from) \
434
        : "cx","di","si","memory");
435
 
436
        switch (n % 4) {
437
                case 0: COMMON(""); return to;
438
                case 1: COMMON("\n\tmovsb"); return to;
439
                case 2: COMMON("\n\tmovsw"); return to;
440
                case 3: COMMON("\n\tmovsw\n\tmovsb"); return to;
441
        }
442
#undef COMMON
443
}
444
 
445
#define __HAVE_ARCH_MEMCPY
446
#define memcpy(t, f, n) \
447
(__builtin_constant_p(n) ? \
448
 __constant_memcpy((t),(f),(n)) : \
449
 __memcpy((t),(f),(n)))
450
 
451
#define __HAVE_ARCH_MEMMOVE
452
extern inline void * memmove(void * dest,const void * src, size_t n)
453
{
454
if (dest<src)
455
__asm__ __volatile__(
456
        "cld\n\t"
457
        "rep\n\t"
458
        "movsb"
459
        : /* no output */
460
        :"c" (n),"S" (src),"D" (dest)
461
        :"cx","si","di");
462
else
463
__asm__ __volatile__(
464
        "std\n\t"
465
        "rep\n\t"
466
        "movsb\n\t"
467
        "cld"
468
        : /* no output */
469
        :"c" (n),
470
         "S" (n-1+(const char *)src),
471
         "D" (n-1+(char *)dest)
472
        :"cx","si","di","memory");
473
return dest;
474
}
475
 
476
#define memcmp __builtin_memcmp
477
 
478
#define __HAVE_ARCH_MEMCHR
479
extern inline void * memchr(const void * cs,int c,size_t count)
480
{
481
register void * __res;
482
if (!count)
483
        return NULL;
484
__asm__ __volatile__(
485
        "cld\n\t"
486
        "repne\n\t"
487
        "scasb\n\t"
488
        "je 1f\n\t"
489
        "movl $1,%0\n"
490
        "1:\tdecl %0"
491
        :"=D" (__res):"a" (c),"D" (cs),"c" (count)
492
        :"cx");
493
return __res;
494
}
495
 
496
extern inline void * __memset_generic(void * s, char c,size_t count)
497
{
498
__asm__ __volatile__(
499
        "cld\n\t"
500
        "rep\n\t"
501
        "stosb"
502
        : /* no output */
503
        :"a" (c),"D" (s),"c" (count)
504
        :"cx","di","memory");
505
return s;
506
}
507
 
508
/* we might want to write optimized versions of these later */
509
#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
510
 
511
/*
512
 * memset(x,0,y) is a reasonably common thing to do, so we want to fill
513
 * things 32 bits at a time even when we don't know the size of the
514
 * area at compile-time..
515
 */
516
extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
517
{
518
__asm__ __volatile__(
519
        "cld\n\t"
520
        "rep ; stosl\n\t"
521
        "testb $2,%b1\n\t"
522
        "je 1f\n\t"
523
        "stosw\n"
524
        "1:\ttestb $1,%b1\n\t"
525
        "je 2f\n\t"
526
        "stosb\n"
527
        "2:"
528
        : /* no output */
529
        :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
530
        :"cx","di","memory");
531
return (s);
532
}
533
 
534
/* Added by Gertjan van Wingerde to make minix and sysv module work */
535
#define __HAVE_ARCH_STRNLEN
536
extern inline size_t strnlen(const char * s, size_t count)
537
{
538
register int __res;
539
__asm__ __volatile__(
540
        "movl %1,%0\n\t"
541
        "jmp 2f\n"
542
        "1:\tcmpb $0,(%0)\n\t"
543
        "je 3f\n\t"
544
        "incl %0\n"
545
        "2:\tdecl %2\n\t"
546
        "cmpl $-1,%2\n\t"
547
        "jne 1b\n"
548
        "3:\tsubl %1,%0"
549
        :"=a" (__res)
550
        :"c" (s),"d" (count)
551
        :"dx");
552
return __res;
553
}
554
/* end of additional stuff */
555
 
556
/*
557
 * This looks horribly ugly, but the compiler can optimize it totally,
558
 * as we by now know that both pattern and count is constant..
559
 */
560
extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
561
{
562
        switch (count) {
563
                case 0:
564
                        return s;
565
                case 1:
566
                        *(unsigned char *)s = pattern;
567
                        return s;
568
                case 2:
569
                        *(unsigned short *)s = pattern;
570
                        return s;
571
                case 3:
572
                        *(unsigned short *)s = pattern;
573
                        *(2+(unsigned char *)s) = pattern;
574
                        return s;
575
                case 4:
576
                        *(unsigned long *)s = pattern;
577
                        return s;
578
        }
579
#define COMMON(x) \
580
__asm__("cld\n\t" \
581
        "rep ; stosl" \
582
        x \
583
        : /* no outputs */ \
584
        : "a" (pattern),"c" (count/4),"D" ((long) s) \
585
        : "cx","di","memory")
586
 
587
        switch (count % 4) {
588
                case 0: COMMON(""); return s;
589
                case 1: COMMON("\n\tstosb"); return s;
590
                case 2: COMMON("\n\tstosw"); return s;
591
                case 3: COMMON("\n\tstosw\n\tstosb"); return s;
592
        }
593
#undef COMMON
594
}
595
 
596
#define __constant_c_x_memset(s, c, count) \
597
(__builtin_constant_p(count) ? \
598
 __constant_c_and_count_memset((s),(c),(count)) : \
599
 __constant_c_memset((s),(c),(count)))
600
 
601
#define __memset(s, c, count) \
602
(__builtin_constant_p(count) ? \
603
 __constant_count_memset((s),(c),(count)) : \
604
 __memset_generic((s),(c),(count)))
605
 
606
#define __HAVE_ARCH_MEMSET
607
#define memset(s, c, count) \
608
(__builtin_constant_p(c) ? \
609
 __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
610
 __memset((s),(c),(count)))
611
 
612
/*
613
 * find the first occurrence of byte 'c', or 1 past the area if none
614
 */
615
#define __HAVE_ARCH_MEMSCAN
616
extern inline void * memscan(void * addr, int c, size_t size)
617
{
618
        if (!size)
619
                return addr;
620
        __asm__("cld
621
                repnz; scasb
622
                jnz 1f
623
                dec %%edi
624
1:              "
625
                : "=D" (addr), "=c" (size)
626
                : "0" (addr), "1" (size), "a" (c));
627
        return addr;
628
}
629
 
630
#endif
631
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.