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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uC-libc/] [string/] [string.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
2
 * This file is part of the Linux-8086 C library and is distributed
3
 * under the GNU Library General Public License.
4
 */
5
 
6
#include <string.h>
7
#include <malloc.h>
8
 
9
#ifdef __AS386_16__
10
#if __FIRST_ARG_IN_AX__
11
#define BCC_AX_ASM      /* BCC Assembler that can cope with arg in AX  */
12
#else
13
#define BCC_AX_ASM
14
#define BCC_ASM         /* Use 16 bit BCC assembler */
15
#endif
16
 
17
#define PARANOID        /* Include extra code for cld and ES register */
18
#endif
19
 
20
/* This is a basic string package; it includes the most used functions
21
 
22
   strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
23
   memcpy memccpy memchr memset memcmp memmove
24
 
25
   These functions are in seperate files.
26
    strpbrk.o strsep.o strstr.o strtok.o strcspn.o
27
    strspn.o strcasecmp.o strncasecmp.o
28
 */
29
 
30
/********************** Function strlen ************************************/
31
 
32
#ifdef L_strlen
33
size_t strlen(str)
34
const char * str;
35
{
36
#ifdef BCC_AX_ASM
37
#asm
38
#if !__FIRST_ARG_IN_AX__
39
  mov   bx,sp
40
#endif
41
  push  di
42
 
43
#ifdef PARANOID
44
  push  es
45
  push  ds      ; Im not sure if this is needed, so just in case.
46
  pop   es
47
  cld
48
#endif          ! This is almost the same as memchr, but it can
49
                ! stay as a special.
50
 
51
#if __FIRST_ARG_IN_AX__
52
  mov   di,ax
53
#else
54
  mov   di,[bx+2]
55
#endif
56
  mov   cx,#-1
57
  xor   ax,ax
58
  repne
59
  scasb
60
  not   cx
61
  dec   cx
62
  mov   ax,cx
63
 
64
#ifdef PARANOID
65
  pop   es
66
#endif
67
  pop   di
68
#endasm
69
#else
70
   register char * p =(char *) str;
71
   while(*p) p++;
72
   return p-str;
73
#endif  /* ifdef BCC_AX_ASM */
74
}
75
#endif
76
 
77
/********************** Function strcat ************************************/
78
 
79
#ifdef L_strcat
80
char * strcat(d, s)
81
char *d;
82
const char * s;
83
{
84
   (void) strcpy(d+strlen(d), s);
85
   return d;
86
}
87
#endif
88
 
89
/********************** Function strcpy ************************************/
90
 
91
#ifdef L_strcpy
92
char * strcpy(d, s)
93
char *d;
94
const char * s;
95
{
96
   /* This is probably the quickest on an 8086 but a CPU with a cache will
97
    * prefer to do this in one pass */
98
   return memcpy(d, s, strlen(s)+1);
99
}
100
#endif
101
 
102
/********************** Function strcmp ************************************/
103
 
104
#ifdef L_strcmp
105
int strcmp(d, s)
106
const char *d;
107
const char * s;
108
{
109
  /* There are a number of ways to do this and it really does depend on the
110
     types of strings given as to which is better, nevertheless the Glib
111
     method is quite reasonable so we'll take that */
112
 
113
#ifdef BCC_AX_ASM
114
#asm
115
  mov   bx,sp
116
  push  di
117
  push  si
118
 
119
#ifdef PARANOID
120
  push  es
121
  push  ds      ; Im not sure if this is needed, so just in case.
122
  pop   es
123
  cld
124
#endif
125
 
126
#if __FIRST_ARG_IN_AX__
127
  mov   di,ax           ; dest
128
  mov   si,[bx+2]       ; source
129
#else
130
  mov   di,[bx+2]       ; dest
131
  mov   si,[bx+4]       ; source
132
#endif
133
sc_1:
134
  lodsb
135
  scasb
136
  jne   sc_2            ; If bytes are diff skip out.
137
  testb al,al
138
  jne   sc_1            ; If this byte in str1 is nul the strings are equal
139
  xor   ax,ax           ; so return zero
140
  jmp   sc_3
141
sc_2:
142
  sbb   ax,ax           ; Collect correct val (-1,1).
143
  orb   al,#1
144
sc_3:
145
 
146
#ifdef PARANOID
147
  pop   es
148
#endif
149
  pop   si
150
  pop   di
151
#endasm
152
#else /* ifdef BCC_AX_ASM */
153
   register char *s1=(char *)d, *s2=(char *)s, c1,c2;
154
   while((c1= *s1++) == (c2= *s2++) && c1 );
155
   return c1 - c2;
156
#endif /* ifdef BCC_AX_ASM */
157
}
158
#endif
159
 
160
/********************** Function strncat ************************************/
161
 
162
#ifdef L_strncat
163
char * strncat(d, s, l)
164
char *d;
165
const char *s;
166
size_t l;
167
{
168
   register char *s1=d+strlen(d), *s2;
169
 
170
   s2 = memchr(s, 0, l);
171
   if( s2 )
172
      memcpy(s1, s, s2-s+1);
173
   else
174
   {
175
      memcpy(s1, s, l);
176
      s1[l] = '\0';
177
   }
178
   return d;
179
}
180
#endif
181
 
182
/********************** Function strncpy ************************************/
183
 
184
#ifdef L_strncpy
185
char * strncpy(d, s, l)         /* FIXME need the fast version of this */
186
char *d;
187
const char *s;
188
size_t l;
189
{
190
   register char *s1=d;
191
   register const char *s2=s;
192
   while(l > 0)
193
   {
194
      l--;
195
      if( (*s1++ = *s2++) == '\0')
196
         break;
197
   }
198
 
199
   /* This _is_ correct strncpy is supposed to zap */
200
   for(; l>0; l--) *s1++ = '\0';
201
   return d;
202
}
203
#endif
204
 
205
/********************** Function strncmp ************************************/
206
 
207
#ifdef L_strncmp
208
int strncmp(d, s, l)
209
const char *d, *s;
210
size_t l;
211
{
212
#ifdef BCC_AX_ASM
213
#asm
214
  mov   bx,sp
215
  push  si
216
  push  di
217
 
218
#ifdef PARANOID
219
  push  es
220
  push  ds      ! Im not sure if this is needed, so just in case.
221
  pop   es
222
  cld
223
#endif
224
 
225
#if __FIRST_ARG_IN_AX__
226
  mov   si,ax
227
  mov   di,[bx+2]
228
  mov   cx,[bx+4]
229
#else
230
  mov   si,[bx+2]       ! Fetch
231
  mov   di,[bx+4]
232
  mov   cx,[bx+6]
233
#endif
234
 
235
  inc   cx
236
lp1:
237
  dec   cx
238
  je    lp2
239
  lodsb
240
  scasb
241
  jne   lp3
242
  testb al,al
243
  jne   lp1
244
lp2:
245
  xor   ax,ax
246
  jmp   lp4
247
lp3:
248
  sbb   ax,ax
249
  or    al,#1
250
lp4:
251
 
252
#ifdef PARANOID
253
  pop   es
254
#endif
255
  pop   di
256
  pop   si
257
#endasm
258
#else
259
   register char c1=0, c2=0;
260
   while(l-- >0)
261
      if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
262
         break;
263
   return c1-c2;
264
#endif
265
}
266
#endif
267
 
268
/********************** Function strchr ************************************/
269
 
270
#ifdef L_strchr
271
char *
272
strchr(s, c)
273
char * s;
274
int c;
275
{
276
#ifdef BCC_AX_ASM
277
#asm
278
  mov   bx,sp
279
  push  si
280
#if __FIRST_ARG_IN_AX__
281
  mov   bx,[bx+2]
282
  mov   si,ax
283
#else
284
  mov   si,[bx+2]
285
  mov   bx,[bx+4]
286
#endif
287
  xor   ax,ax
288
 
289
#ifdef PARANOID
290
  cld
291
#endif
292
 
293
in_loop:
294
  lodsb
295
  cmp   al,bl
296
  jz    got_it
297
  or    al,al
298
  jnz   in_loop
299
  pop   si
300
  ret
301
got_it:
302
  lea   ax,[si-1]
303
  pop   si
304
 
305
#endasm
306
#else /* ifdef BCC_AX_ASM */
307
   register char ch;
308
   for(;;)
309
   {
310
     if( (ch= *s) == c ) return s;
311
     if( ch == 0 ) return 0;
312
     s++;
313
   }
314
#endif /* ifdef BCC_AX_ASM */
315
}
316
#endif
317
 
318
/********************** Function strrchr ************************************/
319
 
320
#ifdef L_strrchr
321
char * strrchr(s, c)
322
char * s;
323
int c;
324
{
325
   register char * prev = 0;
326
   register char * p = s;
327
   /* For null it's just like strlen */
328
   if( c == '\0' ) return p+strlen(p);
329
 
330
   /* everything else just step along the string. */
331
   while( (p=strchr(p, c)) != 0 )
332
   {
333
      prev = p; p++;
334
   }
335
   return prev;
336
}
337
#endif
338
 
339
/********************** Function strdup ************************************/
340
 
341
#ifdef L_strdup
342
char * strdup(s)
343
const char * s;
344
{
345
   register size_t len;
346
   register char * p;
347
 
348
   len = strlen(s)+1;
349
   p = (char *) malloc(len);
350
   if(p) memcpy(p, s, len); /* Faster than strcpy */
351
   return p;
352
}
353
#endif
354
 
355
/********************** Function memcpy ************************************/
356
 
357
#ifdef L_memcpy
358
void *
359
memcpy(d, s, l)
360
void *d;
361
const void *s;
362
size_t l;
363
{
364
#ifdef BCC_AX_ASM
365
#asm
366
  mov   bx,sp
367
  push  di
368
  push  si
369
 
370
#ifdef PARANOID
371
  push  es
372
  push  ds      ; Im not sure if this is needed, so just in case.
373
  pop   es
374
  cld
375
#endif
376
 
377
#if __FIRST_ARG_IN_AX__
378
  mov   di,ax           ; dest
379
  mov   si,[bx+2]       ; source
380
  mov   cx,[bx+4]       ; count
381
#else
382
  mov   di,[bx+2]       ; dest
383
  mov   si,[bx+4]       ; source
384
  mov   cx,[bx+6]       ; count
385
 
386
  mov   ax,di
387
#endif
388
                ; If di is odd mov 1 byte before doing word move
389
                ; this will speed slightly but
390
                ; NB 8086 has no problem with mis-aligned access.
391
 
392
  shr   cx,#1   ; Do this faster by doing a mov word
393
  rep
394
  movsw
395
  adc   cx,cx   ; Retrieve the leftover 1 bit from cflag.
396
  rep
397
  movsb
398
 
399
#ifdef PARANOID
400
  pop   es
401
#endif
402
  pop   si
403
  pop   di
404
#endasm
405
#else /* ifdef BCC_AX_ASM */
406
   register char *s1=d, *s2=(char *)s;
407
   for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
408
   return d;
409
#endif /* ifdef BCC_AX_ASM */
410
}
411
#endif
412
 
413
/********************** Function memccpy ************************************/
414
 
415
#ifdef L_memccpy
416
void * memccpy(d, s, c, l)      /* Do we need a fast one ? */
417
void *s, *d;
418
int c;
419
size_t l;
420
{
421
   register char *s1=d, *s2=s;
422
   while(l-- > 0)
423
      if((*s1++ = *s2++) == c )
424
         return s1;
425
   return 0;
426
}
427
#endif
428
 
429
/********************** Function memchr ************************************/
430
 
431
#ifdef L_memchr
432
void * memchr(str, c, l)
433
const void * str;
434
int c;
435
size_t l;
436
{
437
#ifdef BCC_ASM
438
#asm
439
  mov   bx,sp
440
  push  di
441
 
442
#ifdef PARANOID
443
  push  es
444
  push  ds      ; Im not sure if this is needed, so just in case.
445
  pop   es
446
  cld
447
#endif
448
 
449
  mov   di,[bx+2]
450
  mov   ax,[bx+4]
451
  mov   cx,[bx+6]
452
  test  cx,cx
453
  je    is_z    ! Zero length, do not find.
454
 
455
  repne         ! Scan
456
  scasb
457
  jne   is_z    ! Not found, ret zero
458
  dec   di      ! Adjust ptr
459
  mov   ax,di   ! return
460
  jmp   xit
461
is_z:
462
  xor   ax,ax
463
xit:
464
 
465
#ifdef PARANOID
466
  pop   es
467
#endif
468
  pop   di
469
#endasm
470
#else /* ifdef BCC_ASM */
471
   register char *p=(char *)str;
472
   while(l-- > 0)
473
   {
474
      if(*p == c) return p;
475
      p++;
476
   }
477
   return 0;
478
#endif /* ifdef BCC_ASM */
479
}
480
#endif
481
 
482
/********************** Function memset ************************************/
483
 
484
#ifdef L_memset
485
void * memset(str, c, l)
486
void * str;
487
int c;
488
size_t l;
489
{
490
#ifdef BCC_AX_ASM
491
#asm
492
  mov   bx,sp
493
  push  di
494
 
495
#ifdef PARANOID
496
  push  es
497
  push  ds      ; Im not sure if this is needed, so just in case.
498
  pop   es
499
  cld
500
#endif
501
 
502
#if __FIRST_ARG_IN_AX__
503
  mov   di,ax           ; Fetch
504
  mov   ax,[bx+2]
505
  mov   cx,[bx+4]
506
#else
507
  mov   di,[bx+2]       ; Fetch
508
  mov   ax,[bx+4]
509
  mov   cx,[bx+6]
510
#endif
511
 
512
; How much difference does this alignment make ?
513
; I don`t think it`s significant cause most will already be aligned.
514
 
515
;  test cx,cx           ; Zero size - skip
516
;  je   xit
517
;
518
;  test di,#1           ; Line it up
519
;  je   s_1
520
;  stosb
521
;  dec  cx
522
;s_1:
523
 
524
  mov   ah,al           ; Replicate byte
525
  shr   cx,#1           ; Do this faster by doing a sto word
526
  rep                   ; Bzzzzz ...
527
  stosw
528
  adc   cx,cx           ; Retrieve the leftover 1 bit from cflag.
529
 
530
  rep                   ; ... z
531
  stosb
532
 
533
xit:
534
  mov   ax,[bx+2]
535
#ifdef PARANOID
536
  pop   es
537
#endif
538
  pop   di
539
#endasm
540
#else /* ifdef BCC_AX_ASM */
541
   register char *s1=str;
542
   while(l-->0) *s1++ = c;
543
   return str;
544
#endif /* ifdef BCC_AX_ASM */
545
}
546
#endif
547
 
548
/********************** Function memcmp ************************************/
549
 
550
#ifdef L_memcmp
551
int memcmp(s, d, l)
552
const void *s, *d;
553
size_t l;
554
{
555
#ifdef BCC_ASM
556
#asm
557
  mov   bx,sp
558
  push  di
559
  push  si
560
 
561
#ifdef PARANOID
562
  push  es
563
  push  ds      ! Im not sure if this is needed, so just in case.
564
  pop   es
565
  cld
566
#endif
567
 
568
  mov   si,[bx+2]       ! Fetch
569
  mov   di,[bx+4]
570
  mov   cx,[bx+6]
571
  xor   ax,ax
572
 
573
  rep                   ! Bzzzzz
574
  cmpsb
575
  je    xit             ! All the same!
576
  sbb   ax,ax
577
  sbb   ax,#-1          ! choose +/-1
578
xit:
579
#ifdef PARANOID
580
  pop   es
581
#endif
582
  pop   si
583
  pop   di
584
#endasm
585
#else /* ifdef BCC_ASM */
586
   register const char *s1=d, *s2=s;
587
   register char c1=0, c2=0;
588
   while(l-- > 0)
589
      if( (c1= *s1++) != (c2= *s2++) )
590
         break;
591
   return c1-c2;
592
#endif /* ifdef BCC_ASM */
593
}
594
#endif
595
 
596
/********************** Function memmove ************************************/
597
 
598
#ifdef L_memmove
599
void *
600
memmove(d, s, l)
601
void *d, *s;
602
size_t l;
603
{
604
   register char *s1=d, *s2=s;
605
   /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
606
   if( s1-s2 >= l ) return memcpy(d,s,l);
607
 
608
   /* This reverse copy only used if we absolutly have to */
609
   s1+=l; s2+=l;
610
   while(l-- >0)
611
      *(--s1) = *(--s2);
612
   return d;
613
}
614
#endif
615
 
616
/********************** Function movedata ***********************************/
617
 
618
#ifdef L_movedata
619
 
620
/* NB There isn't any C version of this function ... */
621
 
622
#ifdef BCC_AX_ASM
623
void
624
__movedata(srcseg, srcoff, destseg, destoff, len)
625
unsigned int srcseg, srcoff, destseg, destoff, len;
626
{
627
#asm
628
  push  bp
629
  mov   bp,sp
630
  push  si
631
  push  di
632
  push  ds
633
#ifdef PARANOID
634
  push  es
635
  cld
636
#endif
637
 
638
  ! sei                 ! Are we _really_ paranoid ?
639
 
640
#if !__FIRST_ARG_IN_AX__
641
  mov   ds,[bp+4]       ! Careful, [bp+xx] is SS based.
642
  mov   si,[bp+6]
643
  mov   es,[bp+8]
644
  mov   di,[bp+10]
645
  mov   cx,[bp+12]
646
#else
647
  mov   ds,ax
648
  mov   si,[bp+4]
649
  mov   es,[bp+6]
650
  mov   di,[bp+8]
651
  mov   cx,[bp+10]
652
#endif
653
  rep
654
   movsb
655
 
656
  ! cli                 ! Are we _really_ paranoid ?
657
 
658
#ifdef PARANOID
659
  pop   es
660
#endif
661
  pop   ds
662
  pop   di
663
  pop   si
664
  pop   bp
665
#endasm
666
}
667
#endif
668
 
669
#endif
670
 
671
/********************** THE END ********************************************/
672
 

powered by: WebSVN 2.1.0

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