2.9
[glibc/nacl-glibc.git] / sysdeps / powerpc / powerpc64 / power6 / wordcopy.c
blobfaddd945b3ec20e9c281c4eff41f36034efee582
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, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */
23 #include <stddef.h>
24 #include <memcopy.h>
26 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
27 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
28 Both SRCP and DSTP should be aligned for memory operations on `op_t's. */
30 void
31 _wordcopy_fwd_aligned (dstp, srcp, len)
32 long int dstp;
33 long int srcp;
34 size_t len;
36 op_t a0, a1;
38 if (len & 1)
40 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
42 if (len == 1)
43 return;
44 srcp += OPSIZ;
45 dstp += OPSIZ;
46 len -= 1;
51 a0 = ((op_t *) srcp)[0];
52 a1 = ((op_t *) srcp)[1];
53 ((op_t *) dstp)[0] = a0;
54 ((op_t *) dstp)[1] = a1;
56 srcp += 2 * OPSIZ;
57 dstp += 2 * OPSIZ;
58 len -= 2;
60 while (len != 0);
63 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
64 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
65 DSTP should be aligned for memory operations on `op_t's, but SRCP must
66 *not* be aligned. */
68 void
69 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
70 long int dstp;
71 long int srcp;
72 size_t len;
74 op_t a0, a1, a2;
75 int sh_1, sh_2;
76 int align;
78 /* Calculate how to shift a word read at the memory operation
79 aligned srcp to make it aligned for copy. */
81 align = srcp % OPSIZ;
82 sh_1 = 8 * (srcp % OPSIZ);
83 sh_2 = 8 * OPSIZ - sh_1;
85 /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
86 it points in the middle of. */
87 srcp &= -OPSIZ;
88 a0 = ((op_t *) srcp)[0];
90 if (len & 1)
92 a1 = ((op_t *) srcp)[1];
93 ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
95 if (len == 1)
96 return;
98 a0 = a1;
99 srcp += OPSIZ;
100 dstp += OPSIZ;
101 len -= 1;
104 switch (align)
106 case 1:
109 a1 = ((op_t *) srcp)[1];
110 a2 = ((op_t *) srcp)[2];
111 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (64-8));
112 ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (64-8));
113 a0 = a2;
115 srcp += 2 * OPSIZ;
116 dstp += 2 * OPSIZ;
117 len -= 2;
119 while (len != 0);
120 break;
121 case 2:
124 a1 = ((op_t *) srcp)[1];
125 a2 = ((op_t *) srcp)[2];
126 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (64-16));
127 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (64-16));
128 a0 = a2;
130 srcp += 2 * OPSIZ;
131 dstp += 2 * OPSIZ;
132 len -= 2;
134 while (len != 0);
135 break;
136 case 3:
139 a1 = ((op_t *) srcp)[1];
140 a2 = ((op_t *) srcp)[2];
141 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (64-24));
142 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (64-24));
143 a0 = a2;
145 srcp += 2 * OPSIZ;
146 dstp += 2 * OPSIZ;
147 len -= 2;
149 while (len != 0);
150 break;
151 case 4:
154 a1 = ((op_t *) srcp)[1];
155 a2 = ((op_t *) srcp)[2];
156 ((op_t *) dstp)[0] = MERGE (a0, 32, a1, (64-32));
157 ((op_t *) dstp)[1] = MERGE (a1, 32, a2, (64-32));
158 a0 = a2;
160 srcp += 2 * OPSIZ;
161 dstp += 2 * OPSIZ;
162 len -= 2;
164 while (len != 0);
165 break;
166 case 5:
169 a1 = ((op_t *) srcp)[1];
170 a2 = ((op_t *) srcp)[2];
171 ((op_t *) dstp)[0] = MERGE (a0, 40, a1, (64-40));
172 ((op_t *) dstp)[1] = MERGE (a1, 40, a2, (64-40));
173 a0 = a2;
175 srcp += 2 * OPSIZ;
176 dstp += 2 * OPSIZ;
177 len -= 2;
179 while (len != 0);
180 break;
181 case 6:
184 a1 = ((op_t *) srcp)[1];
185 a2 = ((op_t *) srcp)[2];
186 ((op_t *) dstp)[0] = MERGE (a0, 48, a1, (64-48));
187 ((op_t *) dstp)[1] = MERGE (a1, 48, a2, (64-48));
188 a0 = a2;
190 srcp += 2 * OPSIZ;
191 dstp += 2 * OPSIZ;
192 len -= 2;
194 while (len != 0);
195 break;
196 case 7:
199 a1 = ((op_t *) srcp)[1];
200 a2 = ((op_t *) srcp)[2];
201 ((op_t *) dstp)[0] = MERGE (a0, 56, a1, (64-56));
202 ((op_t *) dstp)[1] = MERGE (a1, 56, a2, (64-56));
203 a0 = a2;
205 srcp += 2 * OPSIZ;
206 dstp += 2 * OPSIZ;
207 len -= 2;
209 while (len != 0);
210 break;
215 /* _wordcopy_bwd_aligned -- Copy block finishing right before
216 SRCP to block finishing right before DSTP with LEN `op_t' words
217 (not LEN bytes!). Both SRCP and DSTP should be aligned for memory
218 operations on `op_t's. */
220 void
221 _wordcopy_bwd_aligned (dstp, srcp, len)
222 long int dstp;
223 long int srcp;
224 size_t len;
226 op_t a0, a1;
228 if (len & 1)
230 srcp -= OPSIZ;
231 dstp -= OPSIZ;
232 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
234 if (len == 1)
235 return;
236 len -= 1;
241 srcp -= 2 * OPSIZ;
242 dstp -= 2 * OPSIZ;
244 a1 = ((op_t *) srcp)[1];
245 a0 = ((op_t *) srcp)[0];
246 ((op_t *) dstp)[1] = a1;
247 ((op_t *) dstp)[0] = a0;
249 len -= 2;
251 while (len != 0);
254 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
255 before SRCP to block finishing right before DSTP with LEN `op_t'
256 words (not LEN bytes!). DSTP should be aligned for memory
257 operations on `op_t', but SRCP must *not* be aligned. */
259 void
260 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
261 long int dstp;
262 long int srcp;
263 size_t len;
265 op_t a0, a1, a2;
266 int sh_1, sh_2;
267 int align;
269 /* Calculate how to shift a word read at the memory operation
270 aligned srcp to make it aligned for copy. */
272 align = srcp % OPSIZ;
273 sh_1 = 8 * (srcp % OPSIZ);
274 sh_2 = 8 * OPSIZ - sh_1;
276 /* Make srcp aligned by rounding it down to the beginning of the op_t
277 it points in the middle of. */
278 srcp &= -OPSIZ;
279 a2 = ((op_t *) srcp)[0];
281 if (len & 1)
283 srcp -= OPSIZ;
284 dstp -= OPSIZ;
285 a1 = ((op_t *) srcp)[0];
286 ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
288 if (len == 1)
289 return;
291 a2 = a1;
292 len -= 1;
295 switch (align)
297 case 1:
300 srcp -= 2 * OPSIZ;
301 dstp -= 2 * OPSIZ;
303 a1 = ((op_t *) srcp)[1];
304 a0 = ((op_t *) srcp)[0];
305 ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (64-8));
306 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (64-8));
307 a2 = a0;
309 len -= 2;
311 while (len != 0);
312 break;
313 case 2:
316 srcp -= 2 * OPSIZ;
317 dstp -= 2 * OPSIZ;
319 a1 = ((op_t *) srcp)[1];
320 a0 = ((op_t *) srcp)[0];
321 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (64-16));
322 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (64-16));
323 a2 = a0;
325 len -= 2;
327 while (len != 0);
328 break;
329 case 3:
332 srcp -= 2 * OPSIZ;
333 dstp -= 2 * OPSIZ;
335 a1 = ((op_t *) srcp)[1];
336 a0 = ((op_t *) srcp)[0];
337 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (64-24));
338 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (64-24));
339 a2 = a0;
341 len -= 2;
343 while (len != 0);
344 break;
345 case 4:
348 srcp -= 2 * OPSIZ;
349 dstp -= 2 * OPSIZ;
351 a1 = ((op_t *) srcp)[1];
352 a0 = ((op_t *) srcp)[0];
353 ((op_t *) dstp)[1] = MERGE (a1, 32, a2, (64-32));
354 ((op_t *) dstp)[0] = MERGE (a0, 32, a1, (64-32));
355 a2 = a0;
357 len -= 2;
359 while (len != 0);
360 break;
361 case 5:
364 srcp -= 2 * OPSIZ;
365 dstp -= 2 * OPSIZ;
367 a1 = ((op_t *) srcp)[1];
368 a0 = ((op_t *) srcp)[0];
369 ((op_t *) dstp)[1] = MERGE (a1, 40, a2, (64-40));
370 ((op_t *) dstp)[0] = MERGE (a0, 40, a1, (64-40));
371 a2 = a0;
373 len -= 2;
375 while (len != 0);
376 break;
377 case 6:
380 srcp -= 2 * OPSIZ;
381 dstp -= 2 * OPSIZ;
383 a1 = ((op_t *) srcp)[1];
384 a0 = ((op_t *) srcp)[0];
385 ((op_t *) dstp)[1] = MERGE (a1, 48, a2, (64-48));
386 ((op_t *) dstp)[0] = MERGE (a0, 48, a1, (64-48));
387 a2 = a0;
389 len -= 2;
391 while (len != 0);
392 break;
393 case 7:
396 srcp -= 2 * OPSIZ;
397 dstp -= 2 * OPSIZ;
399 a1 = ((op_t *) srcp)[1];
400 a0 = ((op_t *) srcp)[0];
401 ((op_t *) dstp)[1] = MERGE (a1, 56, a2, (64-56));
402 ((op_t *) dstp)[0] = MERGE (a0, 56, a1, (64-56));
403 a2 = a0;
405 len -= 2;
407 while (len != 0);
408 break;