1 /* Optimized 64-bit memset implementation for POWER6.
2 Copyright (C) 1997-2014 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, see
17 <http://www.gnu.org/licenses/>. */
21 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
24 The memset is done in three sizes: byte (8 bits), word (32 bits),
25 cache line (256 bits). There is a special case for setting cache lines
26 to 0, to take advantage of the dcbz instruction. */
33 #define rRTN r3 /* Initial value of 1st argument. */
34 #define rMEMP0 r3 /* Original value of 1st arg. */
35 #define rCHR r4 /* Char to set in each byte. */
36 #define rLEN r5 /* Length of region to set. */
37 #define rMEMP r6 /* Address at which we are storing. */
38 #define rALIGN r7 /* Number of bytes we are setting now (when aligning). */
40 #define rMEMP3 r9 /* Alt mem pointer. */
42 /* Take care of case for size <= 4. */
44 andi. rALIGN, rMEMP0, 7
48 /* Align to doubleword boundary. */
50 insrdi rCHR, rCHR, 8, 48 /* Replicate byte to halfword. */
53 subfic rALIGN, rALIGN, 8
54 cror 28,30,31 /* Detect odd word aligned. */
55 add rMEMP, rMEMP, rALIGN
56 sub rLEN, rLEN, rALIGN
57 insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */
59 /* Process the even word of doubleword. */
68 /* Process the odd word of doubleword. */
70 bf 28, L(g4x) /* If false, word aligned on odd word. */
77 /* Handle the case of size < 31. */
79 insrdi rCHR, rCHR, 16, 32 /* Replicate halfword to word. */
83 /* Align to 32-byte boundary. */
84 andi. rALIGN, rMEMP, 0x18
85 subfic rALIGN, rALIGN, 0x20
86 insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */
89 add rMEMP, rMEMP, rALIGN
90 sub rLEN, rLEN, rALIGN
91 cmplwi cr1, rALIGN, 0x10
97 stdu rCHR, -16(rMEMP2)
100 /* Now aligned to a 32 byte boundary. */
104 clrrdi. rALIGN, rLEN, 5
106 beq cr1, L(zloopstart) /* Special case for clearing memory using dcbz. */
107 beq L(medium) /* We may not actually get to do a full line. */
109 /* Storing a non-zero "c" value. We are aligned at a sector (32-byte)
110 boundary may not be at cache line (128-byte) boundary. */
112 /* memset in 32-byte chunks until we get to a cache line boundary.
113 If rLEN is less than the distance to the next cache-line boundary use
114 cacheAligned1 code to finish the tail. */
118 blt cr1,L(cacheAligned1)
120 beq L(nzCacheAligned)
126 andi. rTMP,rMEMP3,127
129 beq L(nzCacheAligned)
138 beq L(nzCacheAligned)
148 blt cr1,L(cacheAligned1)
149 b L(nzCacheAligned128)
151 /* Now we are aligned to the cache line and can use dcbtst. */
155 blt cr1,L(cacheAligned1)
156 b L(nzCacheAligned128)
158 L(nzCacheAligned128):
179 bge cr1,L(nzCacheAligned128)
183 /* Storing a zero "c" value. We are aligned at a sector (32-byte)
184 boundary but may not be at cache line (128-byte) boundary. If the
185 remaining length spans a full cache line we can use the Data cache
186 block zero instruction. */
188 /* memset in 32-byte chunks until we get to a cache line boundary.
189 If rLEN is less than the distance to the next cache-line boundary use
190 cacheAligned1 code to finish the tail. */
196 blt cr1,L(cacheAligned1)
204 andi. rTMP,rMEMP3,127
226 blt cr1,L(cacheAligned1)
227 blt cr6,L(cacheAligned128)
230 /* Now we are aligned to the cache line and can use dcbz. */
235 blt cr1,L(cacheAligned1)
239 blt cr6,L(cacheAligned128)
240 bgt cr5,L(cacheAligned512)
247 blt cr1,L(cacheAligned1)
248 blt cr6,L(cacheAligned128)
251 /* A simple loop for the longer (>640 bytes) lengths. This form limits
252 the branch miss-predicted to exactly 1 at loop exit.*/
255 blt cr1,L(cacheAligned1)
271 bge cr6,L(cacheAligned256)
273 blt cr1,L(cacheAligned1)
282 blt cr1,L(handletail32)
292 blt cr1,L(handletail32)
302 blt cr1,L(handletail32)
310 /* We are here because the length or remainder (rLEN) is less than the
311 cache line/sector size and does not justify aggressive loop unrolling.
312 So set up the preconditions for L(medium) and go there. */
321 /* Memset of 8 bytes or less. */
344 /* Memset of 0-31 bytes. */
347 insrdi rCHR, rCHR, 32, 0 /* Replicate word to double word. */
350 add rMEMP, rMEMP, rLEN
352 bt- 31, L(medium_31t)
353 bt- 30, L(medium_30t)
357 bge cr1, L(medium_27t)
364 bf- 30, L(medium_30f)
367 bf- 29, L(medium_29f)
370 blt cr1, L(medium_27f)
373 stdu rCHR, -16(rMEMP)
379 END_GEN_TB (memset,TB_TOCLESS)
380 libc_hidden_builtin_def (memset)
382 /* Copied from bzero.S to prevent the linker from inserting a stub
383 between bzero and memset. */
391 weak_alias (__bzero, bzero)