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. */
37 EALIGN (BP_SYM (memcpy), 5, 0)
41 cfi_adjust_cfa_offset(32)
43 cfi_offset(30,(20-32))
47 cfi_offset(31,(24-32))
49 andi. 11,3,3 /* check alignment of dst. */
50 clrlwi 0,0,30 /* Number of bytes until the 1st word of dst. */
51 clrlwi 10,4,30 /* check alignment of src. */
53 ble- cr1,.L2 /* If move < 32 bytes use short move code. */
56 srwi 9,5,2 /* Number of full words remaining. */
62 /* Move 0-3 bytes as needed to get the destination word aligned. */
74 clrlwi 10,12,30 /* check alignment of src again. */
75 srwi 9,31,2 /* Number of full words remaining. */
77 /* Copy words from source to destination, assuming the destination is
78 aligned on a word boundary.
80 At this point we know there are at least 25 bytes left (32-7) to copy.
81 The next step is to determine if the source is also word aligned.
82 If not branch to the unaligned move code at .L6. which uses
83 a load, shift, store strategy.
85 Otherwise source and destination are word aligned, and we can use
86 the optimized word copy loop. */
88 clrlwi 11,31,30 /* calculate the number of tail bytes */
90 bne- cr6,.L6 /* If source is not word aligned. */
92 /* Move words where destination and source are word aligned.
93 Use an unrolled loop to copy 4 words (16-bytes) per iteration.
94 If the the copy is not an exact multiple of 16 bytes, 1-3
95 words are copied as needed to set up the main loop. After
96 the main loop exits there may be a tail of 1-3 bytes. These bytes are
97 copied a halfword/byte at a time as needed to preserve alignment. */
99 srwi 8,31,4 /* calculate the 16 byte loop count */
150 /* At this point we have a tail of 0-3 bytes and we know that the
151 destination is word aligned. */
161 /* Return original dst pointer. */
168 /* Copy up to 31 bytes. This is divided into two cases 0-8 bytes and
169 9-31 bytes. Each case is handled without loops, using binary
172 In the short (0-8 byte) case no attempt is made to force alignment
173 of either source or destination. The hardware will handle the
174 unaligned load/stores with small delays for crossing 32- 64-byte, and
175 4096-byte boundaries. Since these short moves are unlikely to be
176 unaligned or cross these boundaries, the overhead to force
177 alignment is not justified.
179 The longer (9-31 byte) move is more likely to cross 32- or 64-byte
180 boundaries. Since only loads are sensitive to the 32-/64-byte
181 boundaries it is more important to align the source than the
182 destination. If the source is not already word aligned, we first
183 move 1-3 bytes as needed. While the destination and stores may
184 still be unaligned, this is only an issue for page (4096 byte
185 boundary) crossing, which should be rare for these short moves.
186 The hardware handles this case automatically with a small delay. */
194 ble cr6,.LE8 /* Handle moves of 0-8 bytes. */
195 /* At least 9 bytes left. Get the source word aligned. */
200 beq .L3 /* If the source is already word aligned skip this. */
201 /* Copy 1-3 bytes to get source address word aligned. */
224 /* At least 6 bytes left and the source is word aligned. */
226 16: /* Move 16 bytes. */
237 8: /* Move 8 bytes. */
245 4: /* Move 4 bytes. */
251 2: /* Move 2-3 bytes. */
262 1: /* Move 1 byte. */
267 /* Return original dst pointer. */
273 /* Special case to copy 0-8 bytes. */
282 /* Return original dst pointer. */
309 /* Return original dst pointer. */
318 /* Copy words where the destination is aligned but the source is
319 not. Use aligned word loads from the source, shifted to realign
320 the data, to allow aligned destination stores.
321 Use an unrolled loop to copy 4 words (16-bytes) per iteration.
322 A single word is retained for storing at loop exit to avoid walking
323 off the end of a page within the loop.
324 If the copy is not an exact multiple of 16 bytes, 1-3
325 words are copied as needed to set up the main loop. After
326 the main loop exits there may be a tail of 1-3 bytes. These bytes are
327 copied a halfword/byte at a time as needed to preserve alignment. */
330 cmplwi cr6,11,0 /* are there tail bytes left ? */
331 subf 5,10,12 /* back up src pointer to prev word alignment */
332 slwi 10,10,3 /* calculate number of bits to shift 1st word left */
333 addi 11,9,-1 /* we move one word after the loop */
334 srwi 8,11,2 /* calculate the 16 byte loop count */
335 lwz 6,0(5) /* load 1st src word into R6 */
337 lwz 7,4(5) /* load 2nd src word into R7 */
339 subfic 9,10,32 /* number of bits to shift 2nd word right */
343 /* there are at least two words to copy, so copy them */
344 slw 0,6,10 /* shift 1st src word to left align it in R0 */
345 srw 8,7,9 /* shift 2nd src word to right align it in R8 */
346 or 0,0,8 /* or them to get word to store */
347 lwz 6,8(5) /* load the 3rd src word */
348 stw 0,0(4) /* store the 1st dst word */
349 slw 0,7,10 /* now left align 2nd src word into R0 */
350 srw 8,6,9 /* shift 3rd src word to right align it in R8 */
351 or 0,0,8 /* or them to get word to store */
353 stw 0,4(4) /* store the 2nd dst word */
357 /* there is a third word to copy, so copy it */
358 slw 0,6,10 /* shift 3rd src word to left align it in R0 */
359 srw 8,7,9 /* shift 4th src word to right align it in R8 */
360 or 0,0,8 /* or them to get word to store */
361 stw 0,0(4) /* store 3rd dst word */
369 slw 0,6,10 /* shift 1st src word to left align it in R0 */
370 srw 8,7,9 /* shift 2nd src word to right align it in R8 */
372 or 0,0,8 /* or them to get word to store */
377 stw 0,0(4) /* store the 1st dst word */
382 /* copy 16 bytes at a time */
407 /* calculate and store the final word */
415 bne cr6,.L9 /* If the tail is 0 bytes we are done! */
417 /* Return original dst pointer. */
423 END (BP_SYM (memcpy))
425 libc_hidden_builtin_def (memcpy)