update from main archive 961005
[glibc/history.git] / sysdeps / generic / wordcopy.c
blob44dabf6e0053e84eade4d71db46a6a064abe18ba
1 /* _memcopy.c -- subroutines for memory copy functions.
2 Copyright (C) 1991 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
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
20 /* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */
22 #include <ansidecl.h>
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 DEFUN(_wordcopy_fwd_aligned, (dstp, srcp, len),
32 long int dstp AND long int srcp AND size_t len)
34 op_t a0, a1;
36 switch (len % 8)
38 case 2:
39 a0 = ((op_t *) srcp)[0];
40 srcp -= 6 * OPSIZ;
41 dstp -= 7 * OPSIZ;
42 len += 6;
43 goto do1;
44 case 3:
45 a1 = ((op_t *) srcp)[0];
46 srcp -= 5 * OPSIZ;
47 dstp -= 6 * OPSIZ;
48 len += 5;
49 goto do2;
50 case 4:
51 a0 = ((op_t *) srcp)[0];
52 srcp -= 4 * OPSIZ;
53 dstp -= 5 * OPSIZ;
54 len += 4;
55 goto do3;
56 case 5:
57 a1 = ((op_t *) srcp)[0];
58 srcp -= 3 * OPSIZ;
59 dstp -= 4 * OPSIZ;
60 len += 3;
61 goto do4;
62 case 6:
63 a0 = ((op_t *) srcp)[0];
64 srcp -= 2 * OPSIZ;
65 dstp -= 3 * OPSIZ;
66 len += 2;
67 goto do5;
68 case 7:
69 a1 = ((op_t *) srcp)[0];
70 srcp -= 1 * OPSIZ;
71 dstp -= 2 * OPSIZ;
72 len += 1;
73 goto do6;
75 case 0:
76 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
77 return;
78 a0 = ((op_t *) srcp)[0];
79 srcp -= 0 * OPSIZ;
80 dstp -= 1 * OPSIZ;
81 goto do7;
82 case 1:
83 a1 = ((op_t *) srcp)[0];
84 srcp -=-1 * OPSIZ;
85 dstp -= 0 * OPSIZ;
86 len -= 1;
87 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
88 goto do0;
89 goto do8; /* No-op. */
94 do8:
95 a0 = ((op_t *) srcp)[0];
96 ((op_t *) dstp)[0] = a1;
97 do7:
98 a1 = ((op_t *) srcp)[1];
99 ((op_t *) dstp)[1] = a0;
100 do6:
101 a0 = ((op_t *) srcp)[2];
102 ((op_t *) dstp)[2] = a1;
103 do5:
104 a1 = ((op_t *) srcp)[3];
105 ((op_t *) dstp)[3] = a0;
106 do4:
107 a0 = ((op_t *) srcp)[4];
108 ((op_t *) dstp)[4] = a1;
109 do3:
110 a1 = ((op_t *) srcp)[5];
111 ((op_t *) dstp)[5] = a0;
112 do2:
113 a0 = ((op_t *) srcp)[6];
114 ((op_t *) dstp)[6] = a1;
115 do1:
116 a1 = ((op_t *) srcp)[7];
117 ((op_t *) dstp)[7] = a0;
119 srcp += 8 * OPSIZ;
120 dstp += 8 * OPSIZ;
121 len -= 8;
123 while (len != 0);
125 /* This is the right position for do0. Please don't move
126 it into the loop. */
127 do0:
128 ((op_t *) dstp)[0] = a1;
131 /* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
132 block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
133 DSTP should be aligned for memory operations on `op_t's, but SRCP must
134 *not* be aligned. */
136 void
137 DEFUN(_wordcopy_fwd_dest_aligned, (dstp, srcp, len),
138 long int dstp AND long int srcp AND size_t len)
140 op_t a0, a1, a2, a3;
141 int sh_1, sh_2;
143 /* Calculate how to shift a word read at the memory operation
144 aligned srcp to make it aligned for copy. */
146 sh_1 = 8 * (srcp % OPSIZ);
147 sh_2 = 8 * OPSIZ - sh_1;
149 /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
150 it points in the middle of. */
151 srcp &= -OPSIZ;
153 switch (len % 4)
155 case 2:
156 a1 = ((op_t *) srcp)[0];
157 a2 = ((op_t *) srcp)[1];
158 srcp -= 1 * OPSIZ;
159 dstp -= 3 * OPSIZ;
160 len += 2;
161 goto do1;
162 case 3:
163 a0 = ((op_t *) srcp)[0];
164 a1 = ((op_t *) srcp)[1];
165 srcp -= 0 * OPSIZ;
166 dstp -= 2 * OPSIZ;
167 len += 1;
168 goto do2;
169 case 0:
170 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
171 return;
172 a3 = ((op_t *) srcp)[0];
173 a0 = ((op_t *) srcp)[1];
174 srcp -=-1 * OPSIZ;
175 dstp -= 1 * OPSIZ;
176 len += 0;
177 goto do3;
178 case 1:
179 a2 = ((op_t *) srcp)[0];
180 a3 = ((op_t *) srcp)[1];
181 srcp -=-2 * OPSIZ;
182 dstp -= 0 * OPSIZ;
183 len -= 1;
184 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
185 goto do0;
186 goto do4; /* No-op. */
191 do4:
192 a0 = ((op_t *) srcp)[0];
193 ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
194 do3:
195 a1 = ((op_t *) srcp)[1];
196 ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2);
197 do2:
198 a2 = ((op_t *) srcp)[2];
199 ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2);
200 do1:
201 a3 = ((op_t *) srcp)[3];
202 ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2);
204 srcp += 4 * OPSIZ;
205 dstp += 4 * OPSIZ;
206 len -= 4;
208 while (len != 0);
210 /* This is the right position for do0. Please don't move
211 it into the loop. */
212 do0:
213 ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2);
216 /* _wordcopy_bwd_aligned -- Copy block finishing right before
217 SRCP to block finishing right before DSTP with LEN `op_t' words
218 (not LEN bytes!). Both SRCP and DSTP should be aligned for memory
219 operations on `op_t's. */
221 void
222 DEFUN(_wordcopy_bwd_aligned, (dstp, srcp, len),
223 long int dstp AND long int srcp AND size_t len)
225 op_t a0, a1;
227 switch (len % 8)
229 case 2:
230 srcp -= 2 * OPSIZ;
231 dstp -= 1 * OPSIZ;
232 a0 = ((op_t *) srcp)[1];
233 len += 6;
234 goto do1;
235 case 3:
236 srcp -= 3 * OPSIZ;
237 dstp -= 2 * OPSIZ;
238 a1 = ((op_t *) srcp)[2];
239 len += 5;
240 goto do2;
241 case 4:
242 srcp -= 4 * OPSIZ;
243 dstp -= 3 * OPSIZ;
244 a0 = ((op_t *) srcp)[3];
245 len += 4;
246 goto do3;
247 case 5:
248 srcp -= 5 * OPSIZ;
249 dstp -= 4 * OPSIZ;
250 a1 = ((op_t *) srcp)[4];
251 len += 3;
252 goto do4;
253 case 6:
254 srcp -= 6 * OPSIZ;
255 dstp -= 5 * OPSIZ;
256 a0 = ((op_t *) srcp)[5];
257 len += 2;
258 goto do5;
259 case 7:
260 srcp -= 7 * OPSIZ;
261 dstp -= 6 * OPSIZ;
262 a1 = ((op_t *) srcp)[6];
263 len += 1;
264 goto do6;
266 case 0:
267 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
268 return;
269 srcp -= 8 * OPSIZ;
270 dstp -= 7 * OPSIZ;
271 a0 = ((op_t *) srcp)[7];
272 goto do7;
273 case 1:
274 srcp -= 9 * OPSIZ;
275 dstp -= 8 * OPSIZ;
276 a1 = ((op_t *) srcp)[8];
277 len -= 1;
278 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
279 goto do0;
280 goto do8; /* No-op. */
285 do8:
286 a0 = ((op_t *) srcp)[7];
287 ((op_t *) dstp)[7] = a1;
288 do7:
289 a1 = ((op_t *) srcp)[6];
290 ((op_t *) dstp)[6] = a0;
291 do6:
292 a0 = ((op_t *) srcp)[5];
293 ((op_t *) dstp)[5] = a1;
294 do5:
295 a1 = ((op_t *) srcp)[4];
296 ((op_t *) dstp)[4] = a0;
297 do4:
298 a0 = ((op_t *) srcp)[3];
299 ((op_t *) dstp)[3] = a1;
300 do3:
301 a1 = ((op_t *) srcp)[2];
302 ((op_t *) dstp)[2] = a0;
303 do2:
304 a0 = ((op_t *) srcp)[1];
305 ((op_t *) dstp)[1] = a1;
306 do1:
307 a1 = ((op_t *) srcp)[0];
308 ((op_t *) dstp)[0] = a0;
310 srcp -= 8 * OPSIZ;
311 dstp -= 8 * OPSIZ;
312 len -= 8;
314 while (len != 0);
316 /* This is the right position for do0. Please don't move
317 it into the loop. */
318 do0:
319 ((op_t *) dstp)[7] = a1;
322 /* _wordcopy_bwd_dest_aligned -- Copy block finishing right
323 before SRCP to block finishing right before DSTP with LEN `op_t'
324 words (not LEN bytes!). DSTP should be aligned for memory
325 operations on `op_t', but SRCP must *not* be aligned. */
327 void
328 DEFUN(_wordcopy_bwd_dest_aligned, (dstp, srcp, len),
329 long int dstp AND long int srcp AND size_t len)
331 op_t a0, a1, a2, a3;
332 int sh_1, sh_2;
334 /* Calculate how to shift a word read at the memory operation
335 aligned srcp to make it aligned for copy. */
337 sh_1 = 8 * (srcp % OPSIZ);
338 sh_2 = 8 * OPSIZ - sh_1;
340 /* Make srcp aligned by rounding it down to the beginning of the op_t
341 it points in the middle of. */
342 srcp &= -OPSIZ;
343 srcp += OPSIZ;
345 switch (len % 4)
347 case 2:
348 srcp -= 3 * OPSIZ;
349 dstp -= 1 * OPSIZ;
350 a2 = ((op_t *) srcp)[2];
351 a1 = ((op_t *) srcp)[1];
352 len += 2;
353 goto do1;
354 case 3:
355 srcp -= 4 * OPSIZ;
356 dstp -= 2 * OPSIZ;
357 a3 = ((op_t *) srcp)[3];
358 a2 = ((op_t *) srcp)[2];
359 len += 1;
360 goto do2;
361 case 0:
362 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
363 return;
364 srcp -= 5 * OPSIZ;
365 dstp -= 3 * OPSIZ;
366 a0 = ((op_t *) srcp)[4];
367 a3 = ((op_t *) srcp)[3];
368 goto do3;
369 case 1:
370 srcp -= 6 * OPSIZ;
371 dstp -= 4 * OPSIZ;
372 a1 = ((op_t *) srcp)[5];
373 a0 = ((op_t *) srcp)[4];
374 len -= 1;
375 if (OP_T_THRES <= 3 * OPSIZ && len == 0)
376 goto do0;
377 goto do4; /* No-op. */
382 do4:
383 a3 = ((op_t *) srcp)[3];
384 ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);
385 do3:
386 a2 = ((op_t *) srcp)[2];
387 ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2);
388 do2:
389 a1 = ((op_t *) srcp)[1];
390 ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2);
391 do1:
392 a0 = ((op_t *) srcp)[0];
393 ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2);
395 srcp -= 4 * OPSIZ;
396 dstp -= 4 * OPSIZ;
397 len -= 4;
399 while (len != 0);
401 /* This is the right position for do0. Please don't move
402 it into the loop. */
403 do0:
404 ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2);