Update copyright notices with scripts/update-copyrights.
[glibc.git] / sysdeps / powerpc / powerpc64 / power6 / memset.S
bloba7913a10a6a1ba8da0fe81d5a2f2d91319f8f346
1 /* Optimized 64-bit memset implementation for POWER6.
2    Copyright (C) 1997-2013 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/>.  */
19 #include <sysdep.h>
20 #include <bp-sym.h>
21 #include <bp-asm.h>
23 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
24    Returns 's'.
26    The memset is done in three sizes: byte (8 bits), word (32 bits),
27    cache line (256 bits). There is a special case for setting cache lines
28    to 0, to take advantage of the dcbz instruction.  */
30         .machine power6
31 EALIGN (BP_SYM (memset), 7, 0)
32         CALL_MCOUNT 3
34 #define rTMP    r0
35 #define rRTN    r3      /* Initial value of 1st argument.  */
36 #if __BOUNDED_POINTERS__
37 # define rMEMP0 r4      /* Original value of 1st arg.  */
38 # define rCHR   r5      /* Char to set in each byte.  */
39 # define rLEN   r6      /* Length of region to set.  */
40 # define rMEMP  r10     /* Address at which we are storing.  */
41 #else
42 # define rMEMP0 r3      /* Original value of 1st arg.  */
43 # define rCHR   r4      /* Char to set in each byte.  */
44 # define rLEN   r5      /* Length of region to set.  */
45 # define rMEMP  r6      /* Address at which we are storing.  */
46 #endif
47 #define rALIGN  r7      /* Number of bytes we are setting now (when aligning). */
48 #define rMEMP2  r8
49 #define rMEMP3  r9      /* Alt mem pointer.  */
50 L(_memset):
51 #if __BOUNDED_POINTERS__
52         cmpldi  cr1, rRTN, 0
53         CHECK_BOUNDS_BOTH_WIDE (rMEMP0, rTMP, rTMP2, rLEN)
54         beq     cr1, L(b0)
55         STORE_RETURN_VALUE (rMEMP0)
56         STORE_RETURN_BOUNDS (rTMP, rTMP2)
57 L(b0):
58 #endif
59 /* Take care of case for size <= 4.  */
60         cmpldi  cr1, rLEN, 8
61         andi.   rALIGN, rMEMP0, 7
62         mr      rMEMP, rMEMP0
63         ble     cr1, L(small)
65 /* Align to doubleword boundary.  */
66         cmpldi  cr5, rLEN, 31
67         rlwimi  rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
68         beq+    L(aligned2)
69         mtcrf   0x01, rMEMP0
70         subfic  rALIGN, rALIGN, 8
71         cror    28,30,31                /* Detect odd word aligned.  */
72         add     rMEMP, rMEMP, rALIGN
73         sub     rLEN, rLEN, rALIGN
74         rlwimi  rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
75         bt      29, L(g4)
76 /* Process the even word of doubleword.  */
77         bf+     31, L(g2)
78         stb     rCHR, 0(rMEMP0)
79         bt      30, L(g4x)
80 L(g2):
81         sth     rCHR, -6(rMEMP)
82 L(g4x):
83         stw     rCHR, -4(rMEMP)
84         b       L(aligned)
85 /* Process the odd word of doubleword.  */
86 L(g4):
87         bf      28, L(g4x) /* If false, word aligned on odd word.  */
88         bf+     31, L(g0)
89         stb     rCHR, 0(rMEMP0)
90         bt      30, L(aligned)
91 L(g0):
92         sth     rCHR, -2(rMEMP)
94 /* Handle the case of size < 31.  */
95 L(aligned2):
96         rlwimi  rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
97 L(aligned):
98         mtcrf   0x01, rLEN
99         ble     cr5, L(medium)
100 /* Align to 32-byte boundary.  */
101         andi.   rALIGN, rMEMP, 0x18
102         subfic  rALIGN, rALIGN, 0x20
103         insrdi  rCHR,rCHR,32,0 /* Replicate word to double word. */
104         beq     L(caligned)
105         mtcrf   0x01, rALIGN
106         add     rMEMP, rMEMP, rALIGN
107         sub     rLEN, rLEN, rALIGN
108         cmplwi  cr1, rALIGN, 0x10
109         mr      rMEMP2, rMEMP
110         bf      28, L(a1)
111         stdu    rCHR, -8(rMEMP2)
112 L(a1):  blt     cr1, L(a2)
113         std     rCHR, -8(rMEMP2)
114         stdu    rCHR, -16(rMEMP2)
115 L(a2):
117 /* Now aligned to a 32 byte boundary.  */
118         .align 4
119 L(caligned):
120         cmpldi  cr1, rCHR, 0
121         clrrdi. rALIGN, rLEN, 5
122         mtcrf   0x01, rLEN
123         beq     cr1, L(zloopstart) /* Special case for clearing memory using dcbz.  */
124         beq     L(medium)       /* We may not actually get to do a full line.  */
125         .align 4
126 /* Storing a non-zero "c" value. We are aligned at a sector (32-byte)
127    boundary may not be at cache line (128-byte) boundary.  */
128 L(nzloopstart):
129 /* memset in 32-byte chunks until we get to a cache line boundary.
130    If rLEN is less then the distance to the next cache-line boundary use
131    cacheAligned1 code to finish the tail.  */
132         cmpldi  cr1,rLEN,128
134         andi.   rTMP,rMEMP,127
135         blt     cr1,L(cacheAligned1)
136         addi    rMEMP3,rMEMP,32
137         beq     L(nzCacheAligned)
138         addi    rLEN,rLEN,-32
139         std     rCHR,0(rMEMP)
140         std     rCHR,8(rMEMP)
141         std     rCHR,16(rMEMP)
142         addi    rMEMP,rMEMP,32
143         andi.   rTMP,rMEMP3,127
144         std     rCHR,-8(rMEMP3)
146         beq     L(nzCacheAligned)
147         addi    rLEN,rLEN,-32
148         std     rCHR,0(rMEMP3)
149         addi    rMEMP,rMEMP,32
150         std     rCHR,8(rMEMP3)
151         andi.   rTMP,rMEMP,127
152         std     rCHR,16(rMEMP3)
153         std     rCHR,24(rMEMP3)
155         beq     L(nzCacheAligned)
156         addi    rLEN,rLEN,-32
157         std     rCHR,32(rMEMP3)
158         addi    rMEMP,rMEMP,32
159         cmpldi  cr1,rLEN,128
160         std     rCHR,40(rMEMP3)
161         cmpldi  cr6,rLEN,256
162         li      rMEMP2,128
163         std     rCHR,48(rMEMP3)
164         std     rCHR,56(rMEMP3)
165         blt     cr1,L(cacheAligned1)
166         b       L(nzCacheAligned128)
168 /* Now we are aligned to the cache line and can use dcbtst.  */
169         .align 4
170 L(nzCacheAligned):
171         cmpldi  cr1,rLEN,128
172         blt     cr1,L(cacheAligned1)
173         b       L(nzCacheAligned128)
174         .align 5
175 L(nzCacheAligned128):
176         cmpldi  cr1,rLEN,256
177         addi    rMEMP3,rMEMP,64
178         std     rCHR,0(rMEMP)
179         std     rCHR,8(rMEMP)
180         std     rCHR,16(rMEMP)
181         std     rCHR,24(rMEMP)
182         std     rCHR,32(rMEMP)
183         std     rCHR,40(rMEMP)
184         std     rCHR,48(rMEMP)
185         std     rCHR,56(rMEMP)
186         addi    rMEMP,rMEMP3,64
187         addi    rLEN,rLEN,-128
188         std     rCHR,0(rMEMP3)
189         std     rCHR,8(rMEMP3)
190         std     rCHR,16(rMEMP3)
191         std     rCHR,24(rMEMP3)
192         std     rCHR,32(rMEMP3)
193         std     rCHR,40(rMEMP3)
194         std     rCHR,48(rMEMP3)
195         std     rCHR,56(rMEMP3)
196         bge     cr1,L(nzCacheAligned128)
197         dcbtst  0,rMEMP
198         b       L(cacheAligned1)
199         .align 5
200 /* Storing a zero "c" value. We are aligned at a sector (32-byte)
201    boundary but may not be at cache line (128-byte) boundary.  If the
202    remaining length spans a full cache line we can use the Data cache
203    block zero instruction. */
204 L(zloopstart):
205 /* memset in 32-byte chunks until we get to a cache line boundary.
206    If rLEN is less then the distance to the next cache-line boundary use
207    cacheAligned1 code to finish the tail.  */
208         cmpldi  cr1,rLEN,128
209         beq     L(medium)
210 L(getCacheAligned):
211         andi.   rTMP,rMEMP,127
212         nop
213         blt     cr1,L(cacheAligned1)
214         addi    rMEMP3,rMEMP,32
215         beq     L(cacheAligned)
216         addi    rLEN,rLEN,-32
217         std     rCHR,0(rMEMP)
218         std     rCHR,8(rMEMP)
219         std     rCHR,16(rMEMP)
220         addi    rMEMP,rMEMP,32
221         andi.   rTMP,rMEMP3,127
222         std     rCHR,-8(rMEMP3)
223 L(getCacheAligned2):
224         beq     L(cacheAligned)
225         addi    rLEN,rLEN,-32
226         std     rCHR,0(rMEMP3)
227         std     rCHR,8(rMEMP3)
228         addi    rMEMP,rMEMP,32
229         andi.   rTMP,rMEMP,127
230         std     rCHR,16(rMEMP3)
231         std     rCHR,24(rMEMP3)
232 L(getCacheAligned3):
233         beq     L(cacheAligned)
234         addi    rLEN,rLEN,-32
235         std     rCHR,32(rMEMP3)
236         addi    rMEMP,rMEMP,32
237         cmpldi  cr1,rLEN,128
238         std     rCHR,40(rMEMP3)
239         cmpldi  cr6,rLEN,256
240         li      rMEMP2,128
241         std     rCHR,48(rMEMP3)
242         std     rCHR,56(rMEMP3)
243         blt     cr1,L(cacheAligned1)
244         blt     cr6,L(cacheAligned128)
245         b       L(cacheAlignedx)
247 /* Now we are aligned to the cache line and can use dcbz.  */
248         .align 5
249 L(cacheAligned):
250         cmpldi  cr1,rLEN,128
251         cmpldi  cr6,rLEN,256
252         blt     cr1,L(cacheAligned1)
253         li      rMEMP2,128
254 L(cacheAlignedx):
255         cmpldi  cr5,rLEN,640
256         blt     cr6,L(cacheAligned128)
257         bgt     cr5,L(cacheAligned512)
258         cmpldi  cr6,rLEN,512
259         dcbz    0,rMEMP
260         cmpldi  cr1,rLEN,384
261         dcbz    rMEMP2,rMEMP
262         addi    rMEMP,rMEMP,256
263         addi    rLEN,rLEN,-256
264         blt     cr1,L(cacheAligned1)
265         blt     cr6,L(cacheAligned128)
266         b       L(cacheAligned256)
267         .align 5
268 /* A simple loop for the longer (>640 bytes) lengths.  This form limits
269    the branch miss-predicted to exactly 1 at loop exit.*/
270 L(cacheAligned512):
271         cmpli   cr1,rLEN,128
272         blt     cr1,L(cacheAligned1)
273         dcbz    0,rMEMP
274         addi    rLEN,rLEN,-128
275         addi    rMEMP,rMEMP,128
276         b       L(cacheAligned512)
277         .align 5
278 L(cacheAligned256):
280         cmpldi  cr6,rLEN,512
282         dcbz    0,rMEMP
283         cmpldi  cr1,rLEN,384
284         dcbz    rMEMP2,rMEMP
285         addi    rMEMP,rMEMP,256
286         addi    rLEN,rLEN,-256
288         bge     cr6,L(cacheAligned256)
290         blt     cr1,L(cacheAligned1)
291         .align 4
292 L(cacheAligned128):
293         dcbz    0,rMEMP
294         addi    rMEMP,rMEMP,128
295         addi    rLEN,rLEN,-128
296         nop
297 L(cacheAligned1):
298         cmpldi  cr1,rLEN,32
299         blt     cr1,L(handletail32)
300         addi    rMEMP3,rMEMP,32
301         addi    rLEN,rLEN,-32
302         std     rCHR,0(rMEMP)
303         std     rCHR,8(rMEMP)
304         std     rCHR,16(rMEMP)
305         addi    rMEMP,rMEMP,32
306         cmpldi  cr1,rLEN,32
307         std     rCHR,-8(rMEMP3)
308 L(cacheAligned2):
309         blt     cr1,L(handletail32)
310         addi    rLEN,rLEN,-32
311         std     rCHR,0(rMEMP3)
312         std     rCHR,8(rMEMP3)
313         addi    rMEMP,rMEMP,32
314         cmpldi  cr1,rLEN,32
315         std     rCHR,16(rMEMP3)
316         std     rCHR,24(rMEMP3)
317         nop
318 L(cacheAligned3):
319         blt     cr1,L(handletail32)
320         addi    rMEMP,rMEMP,32
321         addi    rLEN,rLEN,-32
322         std     rCHR,32(rMEMP3)
323         std     rCHR,40(rMEMP3)
324         std     rCHR,48(rMEMP3)
325         std     rCHR,56(rMEMP3)
327 /* We are here because the length or remainder (rLEN) is less than the
328    cache line/sector size and does not justify aggressive loop unrolling.
329    So set up the preconditions for L(medium) and go there.  */
330         .align 3
331 L(handletail32):
332         cmpldi  cr1,rLEN,0
333         beqlr   cr1
334         b       L(medium)
336         .align 5
337 L(small):
338 /* Memset of 8 bytes or less.  */
339         cmpldi  cr6, rLEN, 4
340         cmpldi  cr5, rLEN, 1
341         ble     cr6,L(le4)
342         subi    rLEN, rLEN, 4
343         stb     rCHR,0(rMEMP)
344         stb     rCHR,1(rMEMP)
345         stb     rCHR,2(rMEMP)
346         stb     rCHR,3(rMEMP)
347         addi    rMEMP,rMEMP, 4
348         cmpldi  cr5, rLEN, 1
349 L(le4):
350         cmpldi  cr1, rLEN, 3
351         bltlr   cr5
352         stb     rCHR, 0(rMEMP)
353         beqlr   cr5
354         stb     rCHR, 1(rMEMP)
355         bltlr   cr1
356         stb     rCHR, 2(rMEMP)
357         beqlr   cr1
358         stb     rCHR, 3(rMEMP)
359         blr
361 /* Memset of 0-31 bytes.  */
362         .align 5
363 L(medium):
364         insrdi  rCHR,rCHR,32,0 /* Replicate word to double word.  */
365         cmpldi  cr1, rLEN, 16
366 L(medium_tail2):
367         add     rMEMP, rMEMP, rLEN
368 L(medium_tail):
369         bt-     31, L(medium_31t)
370         bt-     30, L(medium_30t)
371 L(medium_30f):
372         bt      29, L(medium_29t)
373 L(medium_29f):
374         bge     cr1, L(medium_27t)
375         bflr    28
376         std     rCHR, -8(rMEMP)
377         blr
379 L(medium_31t):
380         stbu    rCHR, -1(rMEMP)
381         bf-     30, L(medium_30f)
382 L(medium_30t):
383         sthu    rCHR, -2(rMEMP)
384         bf-     29, L(medium_29f)
385 L(medium_29t):
386         stwu    rCHR, -4(rMEMP)
387         blt     cr1, L(medium_27f)
388 L(medium_27t):
389         std     rCHR, -8(rMEMP)
390         stdu    rCHR, -16(rMEMP)
391 L(medium_27f):
392         bflr    28
393 L(medium_28t):
394         std     rCHR, -8(rMEMP)
395         blr
396 END_GEN_TB (BP_SYM (memset),TB_TOCLESS)
397 libc_hidden_builtin_def (memset)
399 /* Copied from bzero.S to prevent the linker from inserting a stub
400    between bzero and memset.  */
401 ENTRY (BP_SYM (__bzero))
402         CALL_MCOUNT 3
403 #if __BOUNDED_POINTERS__
404         mr      r6,r4
405         li      r5,0
406         mr      r4,r3
407         /* Tell memset that we don't want a return value.  */
408         li      r3,0
409         b       L(_memset)
410 #else
411         mr      r5,r4
412         li      r4,0
413         b       L(_memset)
414 #endif
415 END_GEN_TB (BP_SYM (__bzero),TB_TOCLESS)
417 weak_alias (BP_SYM (__bzero), BP_SYM (bzero))