2.9
[glibc/nacl-glibc.git] / sysdeps / powerpc / powerpc32 / power6 / wordcopy.c
blobddf28659f9436e3990ef309bb7158b1b7f435bde
1 /* _memcopy.c -- subroutines for memory copy functions.
2 Copyright (C) 1991, 1996, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Torbjorn Granlund (tege@sics.se).
5 Updated for POWER6 by Steven Munroe (sjmunroe@us.ibm.com).
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.
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.
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. */
22 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */
24 #include <stddef.h>
25 #include <memcopy.h>
27 /* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
28 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
29 Both SRCP and DSTP should be aligned for memory operations on `op_t's. */
31 void
32 _wordcopy_fwd_aligned (dstp, srcp, len)
33 long int dstp;
34 long int srcp;
35 size_t len;
37 op_t a0, a1;
39 if (len & 1)
41 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
43 if (len == 1)
44 return;
45 srcp += OPSIZ;
46 dstp += OPSIZ;
47 len -= 1;
52 a0 = ((op_t *) srcp)[0];
53 a1 = ((op_t *) srcp)[1];
54 ((op_t *) dstp)[0] = a0;
55 ((op_t *) dstp)[1] = a1;
57 srcp += 2 * OPSIZ;
58 dstp += 2 * OPSIZ;
59 len -= 2;
61 while (len != 0);
64 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
65 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
66 DSTP should be aligned for memory operations on `op_t's, but SRCP must
67 *not* be aligned. */
69 void
70 _wordcopy_fwd_dest_aligned (dstp, srcp, len)
71 long int dstp;
72 long int srcp;
73 size_t len;
75 op_t a0, a1, a2;
76 int sh_1, sh_2;
77 int align;
79 /* Calculate how to shift a word read at the memory operation
80 aligned srcp to make it aligned for copy. */
82 align = srcp % OPSIZ;
83 sh_1 = 8 * (srcp % OPSIZ);
84 sh_2 = 8 * OPSIZ - sh_1;
86 /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
87 it points in the middle of. */
88 srcp &= -OPSIZ;
89 a0 = ((op_t *) srcp)[0];
91 if (len & 1)
93 a1 = ((op_t *) srcp)[1];
94 ((op_t *) dstp)[0] = MERGE (a0, sh_1, a1, sh_2);
96 if (len == 1)
97 return;
99 a0 = a1;
100 srcp += OPSIZ;
101 dstp += OPSIZ;
102 len -= 1;
105 switch (align)
107 case 1:
110 a1 = ((op_t *) srcp)[1];
111 a2 = ((op_t *) srcp)[2];
112 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (32-8));
113 ((op_t *) dstp)[1] = MERGE (a1, 8, a2, (32-8));
114 a0 = a2;
116 srcp += 2 * OPSIZ;
117 dstp += 2 * OPSIZ;
118 len -= 2;
120 while (len != 0);
121 break;
122 case 2:
125 a1 = ((op_t *) srcp)[1];
126 a2 = ((op_t *) srcp)[2];
127 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (32-16));
128 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (32-16));
129 a0 = a2;
131 srcp += 2 * OPSIZ;
132 dstp += 2 * OPSIZ;
133 len -= 2;
135 while (len != 0);
136 break;
137 case 3:
140 a1 = ((op_t *) srcp)[1];
141 a2 = ((op_t *) srcp)[2];
142 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (32-24));
143 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (32-24));
144 a0 = a2;
146 srcp += 2 * OPSIZ;
147 dstp += 2 * OPSIZ;
148 len -= 2;
150 while (len != 0);
151 break;
156 /* _wordcopy_bwd_aligned -- Copy block finishing right before
157 SRCP to block finishing right before DSTP with LEN `op_t' words
158 (not LEN bytes!). Both SRCP and DSTP should be aligned for memory
159 operations on `op_t's. */
161 void
162 _wordcopy_bwd_aligned (dstp, srcp, len)
163 long int dstp;
164 long int srcp;
165 size_t len;
167 op_t a0, a1;
169 if (len & 1)
171 srcp -= OPSIZ;
172 dstp -= OPSIZ;
173 ((op_t *) dstp)[0] = ((op_t *) srcp)[0];
175 if (len == 1)
176 return;
177 len -= 1;
182 srcp -= 2 * OPSIZ;
183 dstp -= 2 * OPSIZ;
185 a1 = ((op_t *) srcp)[1];
186 a0 = ((op_t *) srcp)[0];
187 ((op_t *) dstp)[1] = a1;
188 ((op_t *) dstp)[0] = a0;
190 len -= 2;
192 while (len != 0);
195 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
196 before SRCP to block finishing right before DSTP with LEN `op_t'
197 words (not LEN bytes!). DSTP should be aligned for memory
198 operations on `op_t', but SRCP must *not* be aligned. */
200 void
201 _wordcopy_bwd_dest_aligned (dstp, srcp, len)
202 long int dstp;
203 long int srcp;
204 size_t len;
206 op_t a0, a1, a2;
207 int sh_1, sh_2;
208 int align;
210 /* Calculate how to shift a word read at the memory operation
211 aligned srcp to make it aligned for copy. */
213 align = srcp % OPSIZ;
214 sh_1 = 8 * (srcp % OPSIZ);
215 sh_2 = 8 * OPSIZ - sh_1;
217 /* Make srcp aligned by rounding it down to the beginning of the op_t
218 it points in the middle of. */
219 srcp &= -OPSIZ;
220 a2 = ((op_t *) srcp)[0];
222 if (len & 1)
224 srcp -= OPSIZ;
225 dstp -= OPSIZ;
226 a1 = ((op_t *) srcp)[0];
227 ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
229 if (len == 1)
230 return;
232 a2 = a1;
233 len -= 1;
236 switch (align)
238 case 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] = MERGE (a1, 8, a2, (32-8));
247 ((op_t *) dstp)[0] = MERGE (a0, 8, a1, (32-8));
248 a2 = a0;
250 len -= 2;
252 while (len != 0);
253 break;
254 case 2:
257 srcp -= 2 * OPSIZ;
258 dstp -= 2 * OPSIZ;
260 a1 = ((op_t *) srcp)[1];
261 a0 = ((op_t *) srcp)[0];
262 ((op_t *) dstp)[1] = MERGE (a1, 16, a2, (32-16));
263 ((op_t *) dstp)[0] = MERGE (a0, 16, a1, (32-16));
264 a2 = a0;
266 len -= 2;
268 while (len != 0);
269 break;
270 case 3:
273 srcp -= 2 * OPSIZ;
274 dstp -= 2 * OPSIZ;
276 a1 = ((op_t *) srcp)[1];
277 a0 = ((op_t *) srcp)[0];
278 ((op_t *) dstp)[1] = MERGE (a1, 24, a2, (32-24));
279 ((op_t *) dstp)[0] = MERGE (a0, 24, a1, (32-24));
280 a2 = a0;
282 len -= 2;
284 while (len != 0);
285 break;