Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / powerpc / powerpc64 / power6 / wordcopy.c
blob184904db5fcfa96fdd76a941eb91c37415041ec1
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).
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.
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.
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/>. */
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 if (len & 1)
39 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
41 if (len == 1)
42 return;
43 srcp += OPSIZ;
44 dstp += OPSIZ;
45 len -= 1;
50 a0 = ((op_t *) srcp)[0];
51 a1 = ((op_t *) srcp)[1];
52 ((op_t *) dstp)[0] = a0;
53 ((op_t *) dstp)[1] = a1;
55 srcp += 2 * OPSIZ;
56 dstp += 2 * OPSIZ;
57 len -= 2;
59 while (len != 0);
62 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
63 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
64 DSTP should be aligned for memory operations on `op_t's, but SRCP must
65 *not* be aligned. */
67 void
68 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
69 long int dstp;
70 long int srcp;
71 size_t len;
73 op_t a0, a1, a2;
74 int sh_1, sh_2;
75 int align;
77 /* Calculate how to shift a word read at the memory operation
78 aligned srcp to make it aligned for copy. */
80 align = srcp % OPSIZ;
81 sh_1 = 8 * (srcp % OPSIZ);
82 sh_2 = 8 * OPSIZ - sh_1;
84 /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
85 it points in the middle of. */
86 srcp &= -OPSIZ;
87 a0 = ((op_t *) srcp)[0];
89 if (len & 1)
91 a1 = ((op_t *) srcp)[1];
92 ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
94 if (len == 1)
95 return;
97 a0 = a1;
98 srcp += OPSIZ;
99 dstp += OPSIZ;
100 len -= 1;
103 switch (align)
105 case 1:
108 a1 = ((op_t *) srcp)[1];
109 a2 = ((op_t *) srcp)[2];
110 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (64-8));
111 ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (64-8));
112 a0 = a2;
114 srcp += 2 * OPSIZ;
115 dstp += 2 * OPSIZ;
116 len -= 2;
118 while (len != 0);
119 break;
120 case 2:
123 a1 = ((op_t *) srcp)[1];
124 a2 = ((op_t *) srcp)[2];
125 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (64-16));
126 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (64-16));
127 a0 = a2;
129 srcp += 2 * OPSIZ;
130 dstp += 2 * OPSIZ;
131 len -= 2;
133 while (len != 0);
134 break;
135 case 3:
138 a1 = ((op_t *) srcp)[1];
139 a2 = ((op_t *) srcp)[2];
140 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (64-24));
141 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (64-24));
142 a0 = a2;
144 srcp += 2 * OPSIZ;
145 dstp += 2 * OPSIZ;
146 len -= 2;
148 while (len != 0);
149 break;
150 case 4:
153 a1 = ((op_t *) srcp)[1];
154 a2 = ((op_t *) srcp)[2];
155 ((op_t *) dstp)[0] = MERGE (a0, 32, a1, (64-32));
156 ((op_t *) dstp)[1] = MERGE (a1, 32, a2, (64-32));
157 a0 = a2;
159 srcp += 2 * OPSIZ;
160 dstp += 2 * OPSIZ;
161 len -= 2;
163 while (len != 0);
164 break;
165 case 5:
168 a1 = ((op_t *) srcp)[1];
169 a2 = ((op_t *) srcp)[2];
170 ((op_t *) dstp)[0] = MERGE (a0, 40, a1, (64-40));
171 ((op_t *) dstp)[1] = MERGE (a1, 40, a2, (64-40));
172 a0 = a2;
174 srcp += 2 * OPSIZ;
175 dstp += 2 * OPSIZ;
176 len -= 2;
178 while (len != 0);
179 break;
180 case 6:
183 a1 = ((op_t *) srcp)[1];
184 a2 = ((op_t *) srcp)[2];
185 ((op_t *) dstp)[0] = MERGE (a0, 48, a1, (64-48));
186 ((op_t *) dstp)[1] = MERGE (a1, 48, a2, (64-48));
187 a0 = a2;
189 srcp += 2 * OPSIZ;
190 dstp += 2 * OPSIZ;
191 len -= 2;
193 while (len != 0);
194 break;
195 case 7:
198 a1 = ((op_t *) srcp)[1];
199 a2 = ((op_t *) srcp)[2];
200 ((op_t *) dstp)[0] = MERGE (a0, 56, a1, (64-56));
201 ((op_t *) dstp)[1] = MERGE (a1, 56, a2, (64-56));
202 a0 = a2;
204 srcp += 2 * OPSIZ;
205 dstp += 2 * OPSIZ;
206 len -= 2;
208 while (len != 0);
209 break;
214 /* _wordcopy_bwd_aligned -- Copy block finishing right before
215 SRCP to block finishing right before DSTP with LEN `op_t' words
216 (not LEN bytes!). Both SRCP and DSTP should be aligned for memory
217 operations on `op_t's. */
219 void
220 _wordcopy_bwd_aligned (dstp, srcp, len)
221 long int dstp;
222 long int srcp;
223 size_t len;
225 op_t a0, a1;
227 if (len & 1)
229 srcp -= OPSIZ;
230 dstp -= OPSIZ;
231 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
233 if (len == 1)
234 return;
235 len -= 1;
240 srcp -= 2 * OPSIZ;
241 dstp -= 2 * OPSIZ;
243 a1 = ((op_t *) srcp)[1];
244 a0 = ((op_t *) srcp)[0];
245 ((op_t *) dstp)[1] = a1;
246 ((op_t *) dstp)[0] = a0;
248 len -= 2;
250 while (len != 0);
253 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
254 before SRCP to block finishing right before DSTP with LEN `op_t'
255 words (not LEN bytes!). DSTP should be aligned for memory
256 operations on `op_t', but SRCP must *not* be aligned. */
258 void
259 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
260 long int dstp;
261 long int srcp;
262 size_t len;
264 op_t a0, a1, a2;
265 int sh_1, sh_2;
266 int align;
268 /* Calculate how to shift a word read at the memory operation
269 aligned srcp to make it aligned for copy. */
271 align = srcp % OPSIZ;
272 sh_1 = 8 * (srcp % OPSIZ);
273 sh_2 = 8 * OPSIZ - sh_1;
275 /* Make srcp aligned by rounding it down to the beginning of the op_t
276 it points in the middle of. */
277 srcp &= -OPSIZ;
278 a2 = ((op_t *) srcp)[0];
280 if (len & 1)
282 srcp -= OPSIZ;
283 dstp -= OPSIZ;
284 a1 = ((op_t *) srcp)[0];
285 ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
287 if (len == 1)
288 return;
290 a2 = a1;
291 len -= 1;
294 switch (align)
296 case 1:
299 srcp -= 2 * OPSIZ;
300 dstp -= 2 * OPSIZ;
302 a1 = ((op_t *) srcp)[1];
303 a0 = ((op_t *) srcp)[0];
304 ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (64-8));
305 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (64-8));
306 a2 = a0;
308 len -= 2;
310 while (len != 0);
311 break;
312 case 2:
315 srcp -= 2 * OPSIZ;
316 dstp -= 2 * OPSIZ;
318 a1 = ((op_t *) srcp)[1];
319 a0 = ((op_t *) srcp)[0];
320 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (64-16));
321 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (64-16));
322 a2 = a0;
324 len -= 2;
326 while (len != 0);
327 break;
328 case 3:
331 srcp -= 2 * OPSIZ;
332 dstp -= 2 * OPSIZ;
334 a1 = ((op_t *) srcp)[1];
335 a0 = ((op_t *) srcp)[0];
336 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (64-24));
337 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (64-24));
338 a2 = a0;
340 len -= 2;
342 while (len != 0);
343 break;
344 case 4:
347 srcp -= 2 * OPSIZ;
348 dstp -= 2 * OPSIZ;
350 a1 = ((op_t *) srcp)[1];
351 a0 = ((op_t *) srcp)[0];
352 ((op_t *) dstp)[1] = MERGE (a1, 32, a2, (64-32));
353 ((op_t *) dstp)[0] = MERGE (a0, 32, a1, (64-32));
354 a2 = a0;
356 len -= 2;
358 while (len != 0);
359 break;
360 case 5:
363 srcp -= 2 * OPSIZ;
364 dstp -= 2 * OPSIZ;
366 a1 = ((op_t *) srcp)[1];
367 a0 = ((op_t *) srcp)[0];
368 ((op_t *) dstp)[1] = MERGE (a1, 40, a2, (64-40));
369 ((op_t *) dstp)[0] = MERGE (a0, 40, a1, (64-40));
370 a2 = a0;
372 len -= 2;
374 while (len != 0);
375 break;
376 case 6:
379 srcp -= 2 * OPSIZ;
380 dstp -= 2 * OPSIZ;
382 a1 = ((op_t *) srcp)[1];
383 a0 = ((op_t *) srcp)[0];
384 ((op_t *) dstp)[1] = MERGE (a1, 48, a2, (64-48));
385 ((op_t *) dstp)[0] = MERGE (a0, 48, a1, (64-48));
386 a2 = a0;
388 len -= 2;
390 while (len != 0);
391 break;
392 case 7:
395 srcp -= 2 * OPSIZ;
396 dstp -= 2 * OPSIZ;
398 a1 = ((op_t *) srcp)[1];
399 a0 = ((op_t *) srcp)[0];
400 ((op_t *) dstp)[1] = MERGE (a1, 56, a2, (64-56));
401 ((op_t *) dstp)[0] = MERGE (a0, 56, a1, (64-56));
402 a2 = a0;
404 len -= 2;
406 while (len != 0);
407 break;