~linaro-toolchain-dev/cortex-strings/trunk

70 by Michael Hope
Added the C only routines from GLIBC 2.16+20120607~git24a6dbe
1
/* _memcopy.c -- subroutines for memory copy functions.
2
   Copyright (C) 1991, 1996 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Torbjorn Granlund (tege@sics.se).
5
6
   The GNU C Library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Lesser General Public
8
   License as published by the Free Software Foundation; either
9
   version 2.1 of the License, or (at your option) any later version.
10
11
   The GNU C Library is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   Lesser General Public License for more details.
15
16
   You should have received a copy of the GNU Lesser General Public
17
   License along with the GNU C Library; if not, see
18
   <http://www.gnu.org/licenses/>.  */
19
20
/* BE VERY CAREFUL IF YOU CHANGE THIS CODE...!  */
21
22
#include <stddef.h>
23
#include "memcopy.h"
24
25
/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
26
   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
27
   Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
28
29
void
30
_wordcopy_fwd_aligned (dstp, srcp, len)
31
     long int dstp;
32
     long int srcp;
33
     size_t len;
34
{
35
  op_t a0, a1;
36
37
  switch (len % 8)
38
    {
39
    case 2:
40
      a0 = ((op_t *) srcp)[0];
41
      srcp -= 6 * OPSIZ;
42
      dstp -= 7 * OPSIZ;
43
      len += 6;
44
      goto do1;
45
    case 3:
46
      a1 = ((op_t *) srcp)[0];
47
      srcp -= 5 * OPSIZ;
48
      dstp -= 6 * OPSIZ;
49
      len += 5;
50
      goto do2;
51
    case 4:
52
      a0 = ((op_t *) srcp)[0];
53
      srcp -= 4 * OPSIZ;
54
      dstp -= 5 * OPSIZ;
55
      len += 4;
56
      goto do3;
57
    case 5:
58
      a1 = ((op_t *) srcp)[0];
59
      srcp -= 3 * OPSIZ;
60
      dstp -= 4 * OPSIZ;
61
      len += 3;
62
      goto do4;
63
    case 6:
64
      a0 = ((op_t *) srcp)[0];
65
      srcp -= 2 * OPSIZ;
66
      dstp -= 3 * OPSIZ;
67
      len += 2;
68
      goto do5;
69
    case 7:
70
      a1 = ((op_t *) srcp)[0];
71
      srcp -= 1 * OPSIZ;
72
      dstp -= 2 * OPSIZ;
73
      len += 1;
74
      goto do6;
75
76
    case 0:
77
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
78
	return;
79
      a0 = ((op_t *) srcp)[0];
80
      srcp -= 0 * OPSIZ;
81
      dstp -= 1 * OPSIZ;
82
      goto do7;
83
    case 1:
84
      a1 = ((op_t *) srcp)[0];
85
      srcp -=-1 * OPSIZ;
86
      dstp -= 0 * OPSIZ;
87
      len -= 1;
88
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
89
	goto do0;
90
      goto do8;			/* No-op.  */
91
    }
92
93
  do
94
    {
95
    do8:
96
      a0 = ((op_t *) srcp)[0];
97
      ((op_t *) dstp)[0] = a1;
98
    do7:
99
      a1 = ((op_t *) srcp)[1];
100
      ((op_t *) dstp)[1] = a0;
101
    do6:
102
      a0 = ((op_t *) srcp)[2];
103
      ((op_t *) dstp)[2] = a1;
104
    do5:
105
      a1 = ((op_t *) srcp)[3];
106
      ((op_t *) dstp)[3] = a0;
107
    do4:
108
      a0 = ((op_t *) srcp)[4];
109
      ((op_t *) dstp)[4] = a1;
110
    do3:
111
      a1 = ((op_t *) srcp)[5];
112
      ((op_t *) dstp)[5] = a0;
113
    do2:
114
      a0 = ((op_t *) srcp)[6];
115
      ((op_t *) dstp)[6] = a1;
116
    do1:
117
      a1 = ((op_t *) srcp)[7];
118
      ((op_t *) dstp)[7] = a0;
119
120
      srcp += 8 * OPSIZ;
121
      dstp += 8 * OPSIZ;
122
      len -= 8;
123
    }
124
  while (len != 0);
125
126
  /* This is the right position for do0.  Please don't move
127
     it into the loop.  */
128
 do0:
129
  ((op_t *) dstp)[0] = a1;
130
}
131
132
/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
133
   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
134
   DSTP should be aligned for memory operations on `op_t's, but SRCP must
135
   *not* be aligned.  */
136
137
void
138
_wordcopy_fwd_dest_aligned (dstp, srcp, len)
139
     long int dstp;
140
     long int srcp;
141
     size_t len;
142
{
143
  op_t a0, a1, a2, a3;
144
  int sh_1, sh_2;
145
146
  /* Calculate how to shift a word read at the memory operation
147
     aligned srcp to make it aligned for copy.  */
148
149
  sh_1 = 8 * (srcp % OPSIZ);
150
  sh_2 = 8 * OPSIZ - sh_1;
151
152
  /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
153
     it points in the middle of.  */
154
  srcp &= -OPSIZ;
155
156
  switch (len % 4)
157
    {
158
    case 2:
159
      a1 = ((op_t *) srcp)[0];
160
      a2 = ((op_t *) srcp)[1];
161
      srcp -= 1 * OPSIZ;
162
      dstp -= 3 * OPSIZ;
163
      len += 2;
164
      goto do1;
165
    case 3:
166
      a0 = ((op_t *) srcp)[0];
167
      a1 = ((op_t *) srcp)[1];
168
      srcp -= 0 * OPSIZ;
169
      dstp -= 2 * OPSIZ;
170
      len += 1;
171
      goto do2;
172
    case 0:
173
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
174
	return;
175
      a3 = ((op_t *) srcp)[0];
176
      a0 = ((op_t *) srcp)[1];
177
      srcp -=-1 * OPSIZ;
178
      dstp -= 1 * OPSIZ;
179
      len += 0;
180
      goto do3;
181
    case 1:
182
      a2 = ((op_t *) srcp)[0];
183
      a3 = ((op_t *) srcp)[1];
184
      srcp -=-2 * OPSIZ;
185
      dstp -= 0 * OPSIZ;
186
      len -= 1;
187
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
188
	goto do0;
189
      goto do4;			/* No-op.  */
190
    }
191
192
  do
193
    {
194
    do4:
195
      a0 = ((op_t *) srcp)[0];
196
      ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
197
    do3:
198
      a1 = ((op_t *) srcp)[1];
199
      ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2);
200
    do2:
201
      a2 = ((op_t *) srcp)[2];
202
      ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2);
203
    do1:
204
      a3 = ((op_t *) srcp)[3];
205
      ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2);
206
207
      srcp += 4 * OPSIZ;
208
      dstp += 4 * OPSIZ;
209
      len -= 4;
210
    }
211
  while (len != 0);
212
213
  /* This is the right position for do0.  Please don't move
214
     it into the loop.  */
215
 do0:
216
  ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
217
}
218
219
/* _wordcopy_bwd_aligned -- Copy block finishing right before
220
   SRCP to block finishing right before DSTP with LEN `op_t' words
221
   (not LEN bytes!).  Both SRCP and DSTP should be aligned for memory
222
   operations on `op_t's.  */
223
224
void
225
_wordcopy_bwd_aligned (dstp, srcp, len)
226
     long int dstp;
227
     long int srcp;
228
     size_t len;
229
{
230
  op_t a0, a1;
231
232
  switch (len % 8)
233
    {
234
    case 2:
235
      srcp -= 2 * OPSIZ;
236
      dstp -= 1 * OPSIZ;
237
      a0 = ((op_t *) srcp)[1];
238
      len += 6;
239
      goto do1;
240
    case 3:
241
      srcp -= 3 * OPSIZ;
242
      dstp -= 2 * OPSIZ;
243
      a1 = ((op_t *) srcp)[2];
244
      len += 5;
245
      goto do2;
246
    case 4:
247
      srcp -= 4 * OPSIZ;
248
      dstp -= 3 * OPSIZ;
249
      a0 = ((op_t *) srcp)[3];
250
      len += 4;
251
      goto do3;
252
    case 5:
253
      srcp -= 5 * OPSIZ;
254
      dstp -= 4 * OPSIZ;
255
      a1 = ((op_t *) srcp)[4];
256
      len += 3;
257
      goto do4;
258
    case 6:
259
      srcp -= 6 * OPSIZ;
260
      dstp -= 5 * OPSIZ;
261
      a0 = ((op_t *) srcp)[5];
262
      len += 2;
263
      goto do5;
264
    case 7:
265
      srcp -= 7 * OPSIZ;
266
      dstp -= 6 * OPSIZ;
267
      a1 = ((op_t *) srcp)[6];
268
      len += 1;
269
      goto do6;
270
271
    case 0:
272
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
273
	return;
274
      srcp -= 8 * OPSIZ;
275
      dstp -= 7 * OPSIZ;
276
      a0 = ((op_t *) srcp)[7];
277
      goto do7;
278
    case 1:
279
      srcp -= 9 * OPSIZ;
280
      dstp -= 8 * OPSIZ;
281
      a1 = ((op_t *) srcp)[8];
282
      len -= 1;
283
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
284
	goto do0;
285
      goto do8;			/* No-op.  */
286
    }
287
288
  do
289
    {
290
    do8:
291
      a0 = ((op_t *) srcp)[7];
292
      ((op_t *) dstp)[7] = a1;
293
    do7:
294
      a1 = ((op_t *) srcp)[6];
295
      ((op_t *) dstp)[6] = a0;
296
    do6:
297
      a0 = ((op_t *) srcp)[5];
298
      ((op_t *) dstp)[5] = a1;
299
    do5:
300
      a1 = ((op_t *) srcp)[4];
301
      ((op_t *) dstp)[4] = a0;
302
    do4:
303
      a0 = ((op_t *) srcp)[3];
304
      ((op_t *) dstp)[3] = a1;
305
    do3:
306
      a1 = ((op_t *) srcp)[2];
307
      ((op_t *) dstp)[2] = a0;
308
    do2:
309
      a0 = ((op_t *) srcp)[1];
310
      ((op_t *) dstp)[1] = a1;
311
    do1:
312
      a1 = ((op_t *) srcp)[0];
313
      ((op_t *) dstp)[0] = a0;
314
315
      srcp -= 8 * OPSIZ;
316
      dstp -= 8 * OPSIZ;
317
      len -= 8;
318
    }
319
  while (len != 0);
320
321
  /* This is the right position for do0.  Please don't move
322
     it into the loop.  */
323
 do0:
324
  ((op_t *) dstp)[7] = a1;
325
}
326
327
/* _wordcopy_bwd_dest_aligned -- Copy block finishing right
328
   before SRCP to block finishing right before DSTP with LEN `op_t'
329
   words (not LEN bytes!).  DSTP should be aligned for memory
330
   operations on `op_t', but SRCP must *not* be aligned.  */
331
332
void
333
_wordcopy_bwd_dest_aligned (dstp, srcp, len)
334
     long int dstp;
335
     long int srcp;
336
     size_t len;
337
{
338
  op_t a0, a1, a2, a3;
339
  int sh_1, sh_2;
340
341
  /* Calculate how to shift a word read at the memory operation
342
     aligned srcp to make it aligned for copy.  */
343
344
  sh_1 = 8 * (srcp % OPSIZ);
345
  sh_2 = 8 * OPSIZ - sh_1;
346
347
  /* Make srcp aligned by rounding it down to the beginning of the op_t
348
     it points in the middle of.  */
349
  srcp &= -OPSIZ;
350
  srcp += OPSIZ;
351
352
  switch (len % 4)
353
    {
354
    case 2:
355
      srcp -= 3 * OPSIZ;
356
      dstp -= 1 * OPSIZ;
357
      a2 = ((op_t *) srcp)[2];
358
      a1 = ((op_t *) srcp)[1];
359
      len += 2;
360
      goto do1;
361
    case 3:
362
      srcp -= 4 * OPSIZ;
363
      dstp -= 2 * OPSIZ;
364
      a3 = ((op_t *) srcp)[3];
365
      a2 = ((op_t *) srcp)[2];
366
      len += 1;
367
      goto do2;
368
    case 0:
369
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
370
	return;
371
      srcp -= 5 * OPSIZ;
372
      dstp -= 3 * OPSIZ;
373
      a0 = ((op_t *) srcp)[4];
374
      a3 = ((op_t *) srcp)[3];
375
      goto do3;
376
    case 1:
377
      srcp -= 6 * OPSIZ;
378
      dstp -= 4 * OPSIZ;
379
      a1 = ((op_t *) srcp)[5];
380
      a0 = ((op_t *) srcp)[4];
381
      len -= 1;
382
      if (OP_T_THRES <= 3 * OPSIZ && len == 0)
383
	goto do0;
384
      goto do4;			/* No-op.  */
385
    }
386
387
  do
388
    {
389
    do4:
390
      a3 = ((op_t *) srcp)[3];
391
      ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
392
    do3:
393
      a2 = ((op_t *) srcp)[2];
394
      ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2);
395
    do2:
396
      a1 = ((op_t *) srcp)[1];
397
      ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2);
398
    do1:
399
      a0 = ((op_t *) srcp)[0];
400
      ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
401
402
      srcp -= 4 * OPSIZ;
403
      dstp -= 4 * OPSIZ;
404
      len -= 4;
405
    }
406
  while (len != 0);
407
408
  /* This is the right position for do0.  Please don't move
409
     it into the loop.  */
410
 do0:
411
  ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
412
}