Update.
[glibc/history.git] / sysdeps / generic / wordcopy.c
blob79f45db32d71d96b109a22fe8706100291ac9fe6
1 /* _memcopy.c -- subroutines for memory copy functions.
2 Copyright (C) 1991, 1996 Free Software Foundation, Inc.
3 Contributed by Torbjorn Granlund (tege@sics.se).
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */
22 #include <stddef.h>
23 #include <memcopy.h>
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. */
29 void
30 _wordcopy_fwd_aligned (dstp, srcp, len)
31 long int dstp;
32 long int srcp;
33 size_t len;
35 op_t a0, a1;
37 switch (len % 8)
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;
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. */
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;
120 srcp += 8 * OPSIZ;
121 dstp += 8 * OPSIZ;
122 len -= 8;
124 while (len != 0);
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;
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. */
137 void
138 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
139 long int dstp;
140 long int srcp;
141 size_t len;
143 op_t a0, a1, a2, a3;
144 int sh_1, sh_2;
146 /* Calculate how to shift a word read at the memory operation
147 aligned srcp to make it aligned for copy. */
149 sh_1 = 8 * (srcp % OPSIZ);
150 sh_2 = 8 * OPSIZ - sh_1;
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;
156 switch (len % 4)
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. */
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);
207 srcp += 4 * OPSIZ;
208 dstp += 4 * OPSIZ;
209 len -= 4;
211 while (len != 0);
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);
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. */
224 void
225 _wordcopy_bwd_aligned (dstp, srcp, len)
226 long int dstp;
227 long int srcp;
228 size_t len;
230 op_t a0, a1;
232 switch (len % 8)
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;
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. */
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;
315 srcp -= 8 * OPSIZ;
316 dstp -= 8 * OPSIZ;
317 len -= 8;
319 while (len != 0);
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;
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. */
332 void
333 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
334 long int dstp;
335 long int srcp;
336 size_t len;
338 op_t a0, a1, a2, a3;
339 int sh_1, sh_2;
341 /* Calculate how to shift a word read at the memory operation
342 aligned srcp to make it aligned for copy. */
344 sh_1 = 8 * (srcp % OPSIZ);
345 sh_2 = 8 * OPSIZ - sh_1;
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;
352 switch (len % 4)
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. */
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);
402 srcp -= 4 * OPSIZ;
403 dstp -= 4 * OPSIZ;
404 len -= 4;
406 while (len != 0);
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);