1 /* Optimized memset implementation for PowerPC64.
2 Copyright (C) 1997, 1999, 2000, 2002, 2003, 2007
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
28 The memset is done in three sizes: byte (8 bits), word (32 bits),
29 cache line (256 bits). There is a special case for setting cache lines
30 to 0, to take advantage of the dcbz instruction. */
33 EALIGN (BP_SYM (memset), 5, 0)
37 #define rRTN r3 /* Initial value of 1st argument. */
38 #if __BOUNDED_POINTERS__
39 # define rMEMP0 r4 /* Original value of 1st arg. */
40 # define rCHR r5 /* Char to set in each byte. */
41 # define rLEN r6 /* Length of region to set. */
42 # define rMEMP r10 /* Address at which we are storing. */
44 # define rMEMP0 r3 /* Original value of 1st arg. */
45 # define rCHR r4 /* Char to set in each byte. */
46 # define rLEN r5 /* Length of region to set. */
47 # define rMEMP r6 /* Address at which we are storing. */
49 #define rALIGN r7 /* Number of bytes we are setting now (when aligning). */
52 #define rNEG64 r8 /* Constant -64 for clearing with dcbz. */
53 #define rCLS r8 /* Cache line size obtained from static. */
54 #define rCLM r9 /* Cache line size mask to check for cache alignment. */
56 #if __BOUNDED_POINTERS__
58 CHECK_BOUNDS_BOTH_WIDE (rMEMP0, rTMP, rTMP2, rLEN)
60 STORE_RETURN_VALUE (rMEMP0)
61 STORE_RETURN_BOUNDS (rTMP, rTMP2)
64 /* Take care of case for size <= 4. */
66 andi. rALIGN, rMEMP0, 7
70 /* Align to doubleword boundary. */
72 rlwimi rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword. */
75 subfic rALIGN, rALIGN, 8
76 cror 28,30,31 /* Detect odd word aligned. */
77 add rMEMP, rMEMP, rALIGN
78 sub rLEN, rLEN, rALIGN
79 rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */
81 /* Process the even word of doubleword. */
90 /* Process the odd word of doubleword. */
92 bf 28, L(g4x) /* If false, word aligned on odd word. */
99 /* Handle the case of size < 31. */
101 rlwimi rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word. */
105 /* Align to 32-byte boundary. */
106 andi. rALIGN, rMEMP, 0x18
107 subfic rALIGN, rALIGN, 0x20
108 insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */
111 add rMEMP, rMEMP, rALIGN
112 sub rLEN, rLEN, rALIGN
113 cmplwi cr1, rALIGN, 0x10
116 stdu rCHR, -8(rMEMP2)
117 L(a1): blt cr1, L(a2)
119 stdu rCHR, -16(rMEMP2)
122 /* Now aligned to a 32 byte boundary. */
125 clrrdi. rALIGN, rLEN, 5
127 beq cr1, L(zloopstart) /* Special case for clearing memory using dcbz. */
131 beq L(medium) /* We may not actually get to do a full line. */
132 clrldi. rLEN, rLEN, 59
133 add rMEMP, rMEMP, rALIGN
137 L(c3): dcbtst rNEG64, rMEMP
141 stdu rCHR, -32(rMEMP)
148 stdu rCHR, -32(rMEMP)
150 add rMEMP, rMEMP, rALIGN
154 /* Clear lines of memory in 128-byte chunks. */
156 /* If the remaining length is less the 32 bytes, don't bother getting
157 the cache line size. */
159 li rCLS,128 /* cache line size is 128 */
161 /* Now we know the cache line size, and it is not 32-bytes, but
162 we may not yet be aligned to the cache line. May have a partial
163 line to fill, so touch it 1st. */
168 blt cr1,L(handletail32)
178 /* Now we are aligned to the cache line and can use dcbz. */
181 blt cr1,L(handletail32)
187 /* We are here because the cache line size was set and was not 32-bytes
188 and the remainder (rLEN) is less than the actual cache line size.
189 So set up the preconditions for L(nondcbz) and go there. */
191 clrrwi. rALIGN, rLEN, 5
196 /* Memset of 8 bytes or less. */
219 /* Memset of 0-31 bytes. */
222 insrdi rCHR,rCHR,32,0 /* Replicate word to double word. */
225 add rMEMP, rMEMP, rLEN
227 bt- 31, L(medium_31t)
228 bt- 30, L(medium_30t)
230 bt- 29, L(medium_29t)
232 bge- cr1, L(medium_27t)
239 bf- 30, L(medium_30f)
242 bf- 29, L(medium_29f)
245 blt- cr1, L(medium_27f)
248 stdu rCHR, -16(rMEMP)
254 END_GEN_TB (BP_SYM (memset),TB_TOCLESS)
255 libc_hidden_builtin_def (memset)
257 /* Copied from bzero.S to prevent the linker from inserting a stub
258 between bzero and memset. */
259 ENTRY (BP_SYM (__bzero))
261 #if __BOUNDED_POINTERS__
265 /* Tell memset that we don't want a return value. */
273 END_GEN_TB (BP_SYM (__bzero),TB_TOCLESS)
275 weak_alias (BP_SYM (__bzero), BP_SYM (bzero))