1 /* Optimized memcpy implementation for PowerPC32 on PowerPC64.
2 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
24 /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
27 Memcpy handles short copies (< 32-bytes) using a binary move blocks
28 (no loops) of lwz/stw. The tail (remaining 1-3) bytes is handled
29 with the appropriate combination of byte and halfword load/stores.
30 There is minimal effort to optimize the alignment of short moves.
32 Longer moves (>= 32-bytes) justify the effort to get at least the
33 destination word (4-byte) aligned. Further optimization is
34 possible when both source and destination are word aligned.
35 Each case has an optimized unrolled loop. */
38 EALIGN (BP_SYM (memcpy), 5, 0)
42 cfi_adjust_cfa_offset(32)
44 cfi_offset(30,(20-32))
48 cfi_offset(31,(24-32))
50 andi. 11,3,3 /* check alignment of dst. */
51 clrlwi 0,0,30 /* Number of bytes until the 1st word of dst. */
52 clrlwi 10,4,30 /* check alignment of src. */
54 ble- cr1,.L2 /* If move < 32 bytes use short move code. */
57 srwi 9,5,2 /* Number of full words remaining. */
63 /* Move 0-3 bytes as needed to get the destination word aligned. */
75 clrlwi 10,12,30 /* check alignment of src again. */
76 srwi 9,31,2 /* Number of full words remaining. */
78 /* Copy words from source to destination, assuming the destination is
79 aligned on a word boundary.
81 At this point we know there are at least 25 bytes left (32-7) to copy.
82 The next step is to determine if the source is also word aligned.
83 If not branch to the unaligned move code at .L6. which uses
84 a load, shift, store strategy.
86 Otherwise source and destination are word aligned, and we can use
87 the optimized word copy loop. */
89 clrlwi 11,31,30 /* calculate the number of tail bytes */
91 bne- cr6,.L6 /* If source is not word aligned. */
93 /* Move words where destination and source are word aligned.
94 Use an unrolled loop to copy 4 words (16-bytes) per iteration.
95 If the the copy is not an exact multiple of 16 bytes, 1-3
96 words are copied as needed to set up the main loop. After
97 the main loop exits there may be a tail of 1-3 bytes. These bytes are
98 copied a halfword/byte at a time as needed to preserve alignment. */
100 srwi 8,31,4 /* calculate the 16 byte loop count */
151 /* At this point we have a tail of 0-3 bytes and we know that the
152 destination is word aligned. */
162 /* Return original dst pointer. */
169 /* Copy up to 31 bytes. This is divided into two cases 0-8 bytes and
170 9-31 bytes. Each case is handled without loops, using binary
173 In the short (0-8 byte) case no attempt is made to force alignment
174 of either source or destination. The hardware will handle the
175 unaligned load/stores with small delays for crossing 32- 64-byte, and
176 4096-byte boundaries. Since these short moves are unlikely to be
177 unaligned or cross these boundaries, the overhead to force
178 alignment is not justified.
180 The longer (9-31 byte) move is more likely to cross 32- or 64-byte
181 boundaries. Since only loads are sensitive to the 32-/64-byte
182 boundaries it is more important to align the source than the
183 destination. If the source is not already word aligned, we first
184 move 1-3 bytes as needed. While the destination and stores may
185 still be unaligned, this is only an issue for page (4096 byte
186 boundary) crossing, which should be rare for these short moves.
187 The hardware handles this case automatically with a small delay. */
195 ble cr6,.LE8 /* Handle moves of 0-8 bytes. */
196 /* At least 9 bytes left. Get the source word aligned. */
201 beq .L3 /* If the source is already word aligned skip this. */
202 /* Copy 1-3 bytes to get source address word aligned. */
225 /* At least 6 bytes left and the source is word aligned. */
227 16: /* Move 16 bytes. */
238 8: /* Move 8 bytes. */
246 4: /* Move 4 bytes. */
252 2: /* Move 2-3 bytes. */
263 1: /* Move 1 byte. */
268 /* Return original dst pointer. */
274 /* Special case to copy 0-8 bytes. */
283 /* Return original dst pointer. */
310 /* Return original dst pointer. */
319 /* Copy words where the destination is aligned but the source is
320 not. Use aligned word loads from the source, shifted to realign
321 the data, to allow aligned destination stores.
322 Use an unrolled loop to copy 4 words (16-bytes) per iteration.
323 A single word is retained for storing at loop exit to avoid walking
324 off the end of a page within the loop.
325 If the copy is not an exact multiple of 16 bytes, 1-3
326 words are copied as needed to set up the main loop. After
327 the main loop exits there may be a tail of 1-3 bytes. These bytes are
328 copied a halfword/byte at a time as needed to preserve alignment. */
331 cmplwi cr6,11,0 /* are there tail bytes left ? */
332 subf 5,10,12 /* back up src pointer to prev word alignment */
333 slwi 10,10,3 /* calculate number of bits to shift 1st word left */
334 addi 11,9,-1 /* we move one word after the loop */
335 srwi 8,11,2 /* calculate the 16 byte loop count */
336 lwz 6,0(5) /* load 1st src word into R6 */
338 lwz 7,4(5) /* load 2nd src word into R7 */
340 subfic 9,10,32 /* number of bits to shift 2nd word right */
344 /* there are at least two words to copy, so copy them */
345 slw 0,6,10 /* shift 1st src word to left align it in R0 */
346 srw 8,7,9 /* shift 2nd src word to right align it in R8 */
347 or 0,0,8 /* or them to get word to store */
348 lwz 6,8(5) /* load the 3rd src word */
349 stw 0,0(4) /* store the 1st dst word */
350 slw 0,7,10 /* now left align 2nd src word into R0 */
351 srw 8,6,9 /* shift 3rd src word to right align it in R8 */
352 or 0,0,8 /* or them to get word to store */
354 stw 0,4(4) /* store the 2nd dst word */
358 /* there is a third word to copy, so copy it */
359 slw 0,6,10 /* shift 3rd src word to left align it in R0 */
360 srw 8,7,9 /* shift 4th src word to right align it in R8 */
361 or 0,0,8 /* or them to get word to store */
362 stw 0,0(4) /* store 3rd dst word */
370 slw 0,6,10 /* shift 1st src word to left align it in R0 */
371 srw 8,7,9 /* shift 2nd src word to right align it in R8 */
373 or 0,0,8 /* or them to get word to store */
378 stw 0,0(4) /* store the 1st dst word */
383 /* copy 16 bytes at a time */
408 /* calculate and store the final word */
416 bne cr6,.L9 /* If the tail is 0 bytes we are done! */
418 /* Return original dst pointer. */
424 END (BP_SYM (memcpy))
426 libc_hidden_builtin_def (memcpy)