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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-newlib/] [newlib-1.17.0/] [newlib/] [libc/] [machine/] [mips/] [strncpy.c] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 jlechner
/*
2
 * strncpy.S -- strncmp function.  On at least some MIPS chips, you get better
3
 * code by hand unrolling the loops, and by using store words to zero the
4
 * remainder of the buffer than the default newlib C version.
5
 *
6
 * Copyright (c) 2001 Red Hat, Inc.
7
 *
8
 * The authors hereby grant permission to use, copy, modify, distribute,
9
 * and license this software and its documentation for any purpose, provided
10
 * that existing copyright notices are retained in all copies and that this
11
 * notice is included verbatim in any distributions. No written agreement,
12
 * license, or royalty fee is required for any of the authorized uses.
13
 * Modifications to this software may be copyrighted by their authors
14
 * and need not follow the licensing terms described here, provided that
15
 * the new terms are clearly indicated on the first page of each file where
16
 * they apply.  */
17
 
18
#include <string.h>
19
#include <stddef.h>
20
#include <stdlib.h>
21
#include <stdint.h>
22
 
23
#if !defined(__GNUC__) || (__GNUC__ < 3)
24
#define __builtin_expect(a,b) a
25
 
26
#else
27
#ifdef __mips64
28
/* Don't use limits test for the size of long, in order to allow the use of
29
   64-bit stores on MIPS3 machines, even if -mlong32 was used.  */
30
typedef unsigned word_type __attribute__ ((mode (DI)));
31
#else
32
typedef unsigned word_type __attribute__ ((mode (SI)));
33
#endif
34
 
35
typedef unsigned si_type __attribute__ ((mode (SI)));
36
typedef unsigned hi_type __attribute__ ((mode (HI)));
37
 
38
#ifndef UNROLL_FACTOR
39
#define UNROLL_FACTOR 4
40
 
41
#elif (UNROLL_FACTOR != 2) && (UNROLL_FACTOR != 4)
42
#error "UNROLL_FACTOR must be 2 or 4"
43
#endif
44
#endif
45
 
46
char *
47
strncpy (char *dst0, const char *src0, size_t count)
48
{
49
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) || defined(__mips16) || !defined(__GNUC__) || (__GNUC__ < 3)
50
  char *dst, *end;
51
  const char *src;
52
  int ch;
53
 
54
  dst = dst0;
55
  src = src0;
56
  end = dst + count;
57
  while (dst != end)
58
    {
59
      *dst++ = ch = *src++;
60
      if (__builtin_expect (ch == '\0', 0))
61
        {
62
          while (dst != end)
63
            *dst++ = '\0';
64
 
65
          break;
66
        }
67
    }
68
 
69
  return dst0;
70
 
71
#else
72
  unsigned char *dst;
73
  unsigned char *dst_end;
74
  unsigned char *end;
75
  const unsigned char *src;
76
  int ch0, ch1;
77
#if UNROLL_FACTOR > 2
78
  int ch2, ch3;
79
#endif
80
  int ch;
81
  int odd_bytes;
82
  size_t long_count;
83
 
84
  dst = (unsigned char *)dst0;
85
  src = (unsigned const char *)src0;
86
  /* Take care of any odd bytes in the source data because we
87
   * want to unroll where we read ahead 2 or 4 bytes at a time and then
88
   * check each byte for the null terminator.  This can result in
89
   * a segfault for the case where the source pointer is unaligned,
90
   * the null terminator is in valid memory, but reading 2 or 4 bytes at a
91
   * time blindly eventually goes outside of valid memory. */
92
  while (((uintptr_t) src & (UNROLL_FACTOR - 1)) != 0 && count > 0)
93
    {
94
      *dst++ = ch = *src++;
95
      --count;
96
      if (ch == '\0')
97
        {
98
          end = dst + count;
99
          while (dst != end)
100
            *dst++ = '\0';
101
 
102
          return dst0;
103
        }
104
    }
105
 
106
  if (__builtin_expect (count >= 4, 1))
107
    {
108
      odd_bytes = (count & (UNROLL_FACTOR - 1));
109
      count -= odd_bytes;
110
 
111
      do
112
        {
113
          ch0 = src[0];
114
          ch1 = src[1];
115
#if UNROLL_FACTOR > 2
116
          ch2 = src[2];
117
          ch3 = src[3];
118
#endif
119
          src += UNROLL_FACTOR;
120
          count -= UNROLL_FACTOR;
121
 
122
          dst[0] = ch0;
123
          if (ch0 == '\0')
124
            goto found_null0;
125
 
126
          dst[1] = ch1;
127
          if (ch1 == '\0')
128
            goto found_null1;
129
 
130
#if UNROLL_FACTOR > 2
131
          dst[2] = ch2;
132
          if (ch2 == '\0')
133
            goto found_null2;
134
 
135
          dst[3] = ch3;
136
          if (ch3 == '\0')
137
            goto found_null3;
138
#endif
139
 
140
          dst += UNROLL_FACTOR;
141
        }
142
      while (count);
143
 
144
      /* fall through, count == 0, no null found, deal with last bytes */
145
      count = odd_bytes;
146
    }
147
 
148
  end = dst + count;
149
  while (dst != end)
150
    {
151
      *dst++ = ch = *src++;
152
      if (ch == '\0')
153
        {
154
          while (dst != end)
155
            *dst++ = '\0';
156
 
157
          break;
158
        }
159
    }
160
 
161
  return dst0;
162
 
163
  /* Found null byte in first byte, count has been decremented by 4, null has
164
     been stored in dst[0].  */
165
 found_null0:
166
  count++;                      /* add 1 to cover remaining byte */
167
  dst -= 1;                     /* adjust dst += 4 gets correct ptr */
168
  /* fall through */
169
 
170
  /* Found null byte in second byte, count has been decremented by 4, null has
171
     been stored in dst[1].  */
172
 found_null1:
173
#if UNROLL_FACTOR > 2
174
  count++;                      /* add 1 to cover remaining byte */
175
  dst -= 1;                     /* adjust dst += 4 gets correct ptr */
176
  /* fall through */
177
 
178
  /* Found null byte in third byte, count has been decremented by 4, null has
179
     been stored in dst[2].  */
180
 found_null2:
181
  count++;                      /* add 1 to cover remaining byte */
182
  dst -= 1;                     /* adjust dst += 4 gets correct ptr */
183
  /* fall through */
184
 
185
  /* Found null byte in fourth byte, count is accurate, dst has not been
186
     updated yet.  */
187
 found_null3:
188
#endif
189
  count += odd_bytes;           /* restore odd byte count */
190
  dst += UNROLL_FACTOR;
191
 
192
  /* Zero fill remainder of the array.  Unroll the loop, and use word/dword
193
     stores where we can.  */
194
  while (count && (((long)dst) & (sizeof (word_type) - 1)) != 0)
195
    {
196
      count--;
197
      *dst++ = 0;
198
    }
199
 
200
  while (count >= UNROLL_FACTOR*sizeof (word_type))
201
    {
202
      count -= UNROLL_FACTOR*sizeof (word_type);
203
      dst += UNROLL_FACTOR*sizeof (word_type);
204
#if UNROLL_FACTOR > 2
205
      ((word_type *)(void *)dst)[-4] = 0;
206
      ((word_type *)(void *)dst)[-3] = 0;
207
#endif
208
      ((word_type *)(void *)dst)[-2] = 0;
209
      ((word_type *)(void *)dst)[-1] = 0;
210
    }
211
 
212
#if UNROLL_FACTOR > 2
213
  if (count >= 2*sizeof (word_type))
214
    {
215
      count -= 2*sizeof (word_type);
216
      ((word_type *)(void *)dst)[0] = 0;
217
      ((word_type *)(void *)dst)[1] = 0;
218
      dst += 2*sizeof (word_type);
219
    }
220
#endif 
221
 
222
  if (count >= sizeof (word_type))
223
    {
224
      count -= sizeof (word_type);
225
      ((word_type *)(void *)dst)[0] = 0;
226
      dst += sizeof (word_type);
227
    }
228
 
229
#ifdef __mips64
230
  if (count >= sizeof (si_type))
231
    {
232
      count -= sizeof (si_type);
233
      ((si_type *)(void *)dst)[0] = 0;
234
      dst += sizeof (si_type);
235
    }
236
#endif
237
 
238
  if (count >= sizeof (hi_type))
239
    {
240
      count -= sizeof (hi_type);
241
      ((hi_type *)(void *)dst)[0] = 0;
242
      dst += sizeof (hi_type);
243
    }
244
 
245
  if (count)
246
    *dst = '\0';
247
 
248
  return dst0;
249
#endif
250
}

powered by: WebSVN 2.1.0

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