OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / libc / string / generic / memmove.c
1 /* Copy memory to memory until the specified number of bytes
2    has been copied.  Overlap is handled correctly.
3    Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Torbjorn Granlund (tege@sics.se).
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #include <string.h>
23
24 #include "memcopy.h"
25 #include "pagecopy.h"
26
27 libc_hidden_proto(memcpy)
28
29 static void _wordcopy_bwd_aligned (long int dstp, long int srcp, size_t len)
30 {
31   op_t a0, a1;
32
33   switch (len % 8)
34     {
35     case 2:
36       srcp -= 2 * OPSIZ;
37       dstp -= 1 * OPSIZ;
38       a0 = ((op_t *) srcp)[1];
39       len += 6;
40       goto do1;
41     case 3:
42       srcp -= 3 * OPSIZ;
43       dstp -= 2 * OPSIZ;
44       a1 = ((op_t *) srcp)[2];
45       len += 5;
46       goto do2;
47     case 4:
48       srcp -= 4 * OPSIZ;
49       dstp -= 3 * OPSIZ;
50       a0 = ((op_t *) srcp)[3];
51       len += 4;
52       goto do3;
53     case 5:
54       srcp -= 5 * OPSIZ;
55       dstp -= 4 * OPSIZ;
56       a1 = ((op_t *) srcp)[4];
57       len += 3;
58       goto do4;
59     case 6:
60       srcp -= 6 * OPSIZ;
61       dstp -= 5 * OPSIZ;
62       a0 = ((op_t *) srcp)[5];
63       len += 2;
64       goto do5;
65     case 7:
66       srcp -= 7 * OPSIZ;
67       dstp -= 6 * OPSIZ;
68       a1 = ((op_t *) srcp)[6];
69       len += 1;
70       goto do6;
71
72     case 0:
73       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
74         return;
75       srcp -= 8 * OPSIZ;
76       dstp -= 7 * OPSIZ;
77       a0 = ((op_t *) srcp)[7];
78       goto do7;
79     case 1:
80       srcp -= 9 * OPSIZ;
81       dstp -= 8 * OPSIZ;
82       a1 = ((op_t *) srcp)[8];
83       len -= 1;
84       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
85         goto do0;
86       goto do8;                 /* No-op.  */
87     }
88
89   do
90     {
91     do8:
92       a0 = ((op_t *) srcp)[7];
93       ((op_t *) dstp)[7] = a1;
94     do7:
95       a1 = ((op_t *) srcp)[6];
96       ((op_t *) dstp)[6] = a0;
97     do6:
98       a0 = ((op_t *) srcp)[5];
99       ((op_t *) dstp)[5] = a1;
100     do5:
101       a1 = ((op_t *) srcp)[4];
102       ((op_t *) dstp)[4] = a0;
103     do4:
104       a0 = ((op_t *) srcp)[3];
105       ((op_t *) dstp)[3] = a1;
106     do3:
107       a1 = ((op_t *) srcp)[2];
108       ((op_t *) dstp)[2] = a0;
109     do2:
110       a0 = ((op_t *) srcp)[1];
111       ((op_t *) dstp)[1] = a1;
112     do1:
113       a1 = ((op_t *) srcp)[0];
114       ((op_t *) dstp)[0] = a0;
115
116       srcp -= 8 * OPSIZ;
117       dstp -= 8 * OPSIZ;
118       len -= 8;
119     }
120   while (len != 0);
121
122   /* This is the right position for do0.  Please don't move
123      it into the loop.  */
124  do0:
125   ((op_t *) dstp)[7] = a1;
126 }
127
128 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
129    before SRCP to block finishing right before DSTP with LEN `op_t'
130    words (not LEN bytes!).  DSTP should be aligned for memory
131    operations on `op_t', but SRCP must *not* be aligned.  */
132
133 static void _wordcopy_bwd_dest_aligned (long int dstp, long int srcp, size_t len)
134 {
135   op_t a0, a1, a2, a3;
136   int sh_1, sh_2;
137
138   /* Calculate how to shift a word read at the memory operation
139      aligned srcp to make it aligned for copy.  */
140
141   sh_1 = 8 * (srcp % OPSIZ);
142   sh_2 = 8 * OPSIZ - sh_1;
143
144   /* Make srcp aligned by rounding it down to the beginning of the op_t
145      it points in the middle of.  */
146   srcp &= -OPSIZ;
147   srcp += OPSIZ;
148
149   switch (len % 4)
150     {
151     case 2:
152       srcp -= 3 * OPSIZ;
153       dstp -= 1 * OPSIZ;
154       a2 = ((op_t *) srcp)[2];
155       a1 = ((op_t *) srcp)[1];
156       len += 2;
157       goto do1;
158     case 3:
159       srcp -= 4 * OPSIZ;
160       dstp -= 2 * OPSIZ;
161       a3 = ((op_t *) srcp)[3];
162       a2 = ((op_t *) srcp)[2];
163       len += 1;
164       goto do2;
165     case 0:
166       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
167         return;
168       srcp -= 5 * OPSIZ;
169       dstp -= 3 * OPSIZ;
170       a0 = ((op_t *) srcp)[4];
171       a3 = ((op_t *) srcp)[3];
172       goto do3;
173     case 1:
174       srcp -= 6 * OPSIZ;
175       dstp -= 4 * OPSIZ;
176       a1 = ((op_t *) srcp)[5];
177       a0 = ((op_t *) srcp)[4];
178       len -= 1;
179       if (OP_T_THRES <= 3 * OPSIZ && len == 0)
180         goto do0;
181       goto do4;                 /* No-op.  */
182     }
183
184   do
185     {
186     do4:
187       a3 = ((op_t *) srcp)[3];
188       ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
189     do3:
190       a2 = ((op_t *) srcp)[2];
191       ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2);
192     do2:
193       a1 = ((op_t *) srcp)[1];
194       ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2);
195     do1:
196       a0 = ((op_t *) srcp)[0];
197       ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
198
199       srcp -= 4 * OPSIZ;
200       dstp -= 4 * OPSIZ;
201       len -= 4;
202     }
203   while (len != 0);
204
205   /* This is the right position for do0.  Please don't move
206      it into the loop.  */
207  do0:
208   ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
209 }
210
211 void *memmove (void *dest, const void *src, size_t len)
212 {
213   unsigned long int dstp = (long int) dest;
214   unsigned long int srcp = (long int) src;
215
216   /* This test makes the forward copying code be used whenever possible.
217      Reduces the working set.  */
218   if (dstp - srcp >= len)       /* *Unsigned* compare!  */
219     {
220 #if 1
221 #warning REMINDER: generic-opt memmove assumes memcpy does forward copying!
222       memcpy(dest, src, len);
223 #else
224       /* Copy from the beginning to the end.  */
225
226       /* If there not too few bytes to copy, use word copy.  */
227       if (len >= OP_T_THRES)
228         {
229           /* Copy just a few bytes to make DSTP aligned.  */
230           len -= (-dstp) % OPSIZ;
231           BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
232
233           /* Copy whole pages from SRCP to DSTP by virtual address
234              manipulation, as much as possible.  */
235
236           PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
237
238           /* Copy from SRCP to DSTP taking advantage of the known
239              alignment of DSTP.  Number of bytes remaining is put
240              in the third argument, i.e. in LEN.  This number may
241              vary from machine to machine.  */
242
243           WORD_COPY_FWD (dstp, srcp, len, len);
244
245           /* Fall out and copy the tail.  */
246         }
247
248       /* There are just a few bytes to copy.  Use byte memory operations.  */
249       BYTE_COPY_FWD (dstp, srcp, len);
250 #endif
251     }
252   else
253     {
254       /* Copy from the end to the beginning.  */
255       srcp += len;
256       dstp += len;
257
258       /* If there not too few bytes to copy, use word copy.  */
259       if (len >= OP_T_THRES)
260         {
261           /* Copy just a few bytes to make DSTP aligned.  */
262           len -= dstp % OPSIZ;
263           BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ);
264
265           /* Copy from SRCP to DSTP taking advantage of the known
266              alignment of DSTP.  Number of bytes remaining is put
267              in the third argument, i.e. in LEN.  This number may
268              vary from machine to machine.  */
269
270           WORD_COPY_BWD (dstp, srcp, len, len);
271
272           /* Fall out and copy the tail.  */
273         }
274
275       /* There are just a few bytes to copy.  Use byte memory operations.  */
276       BYTE_COPY_BWD (dstp, srcp, len);
277     }
278
279   return (dest);
280 }
281 libc_hidden_proto(memmove)
282 libc_hidden_def(memmove)