Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / powerpc / powerpc32 / power7 / memset.S
blob4e6e013926842742bf5cccb4ab09f95fd983d0d3
1 /* Optimized memset implementation for PowerPC32/POWER7.
2    Copyright (C) 2010 Free Software Foundation, Inc.
3    Contributed by Luis Machado <luisgpm@br.ibm.com>.
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, see
18    <http://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
25    Returns 's'.  */
27         .machine  power7
28 EALIGN (BP_SYM (memset), 5, 0)
29         CALL_MCOUNT
31         .align  4
32 L(_memset):
33         cmplwi  cr7,5,31
34         cmplwi  cr6,5,8
35         mr      10,3            /* Save original argument for later.  */
36         mr      7,1             /* Save original r1 for later.  */
37         cfi_offset(31,-8)
39         /* Replicate byte to word.  */
40         rlwimi  4,4,8,16,23
41         rlwimi  4,4,16,0,15
43         ble     cr6,L(small)    /* If length <= 8, use short copy code.  */
45         neg     0,3
46         ble     cr7,L(medium)   /* If length < 32, use medium copy code.  */
48         /* Save our word twice to create a doubleword that we will later
49            copy to a FPR.  */
50         stwu    1,-32(1)
51         andi.   11,10,7         /* Check alignment of DST.  */
52         mr      12,5
53         stw     4,24(1)
54         stw     4,28(1)
55         beq     L(big_aligned)
57         clrlwi  0,0,29
58         mtocrf  0x01,0
59         subf    5,0,5
61         /* Get DST aligned to 8 bytes.  */
62 1:      bf      31,2f
64         stb     4,0(10)
65         addi    10,10,1
66 2:      bf      30,4f
68         sth     4,0(10)
69         addi    10,10,2
70 4:      bf      29,L(big_aligned)
72         stw     4,0(10)
73         addi    10,10,4
75         .align  4
76 L(big_aligned):
77         cmplwi  cr5,5,255
78         li      0,32
79         cmplwi  cr1,5,160
80         dcbtst  0,10
81         cmplwi  cr6,4,0
82         srwi    9,5,3           /* Number of full doublewords remaining.  */
83         crand   27,26,21
84         mtocrf  0x01,9
85         bt      27,L(huge)
87         /* From this point on, we'll copy 32+ bytes and the value
88            isn't 0 (so we can't use dcbz).  */
90         srwi    8,5,5
91         clrlwi  11,5,29
92         cmplwi  cr6,11,0
93         cmplwi  cr1,9,4
94         mtctr   8
96         /* Copy 1~3 doublewords so the main loop starts
97         at a multiple of 32 bytes.  */
99         bf      30,1f
101         stw     4,0(10)
102         stw     4,4(10)
103         stw     4,8(10)
104         stw     4,12(10)
105         addi    10,10,16
106         bf      31,L(big_loop)
108         stw     4,0(10)
109         stw     4,4(10)
110         addi    10,10,8
111         mr      12,10
112         blt     cr1,L(tail_bytes)
114         b       L(big_loop)
116         .align  4
117 1:      /* Copy 1 doubleword.  */
118         bf      31,L(big_loop)
120         stw     4,0(10)
121         stw     4,4(10)
122         addi    10,10,8
124         /* First use a 32-bytes loop with stw's to try and avoid the LHS due
125            to the lfd we will do next.  Also, ping-pong through r10 and r12
126            to avoid AGEN delays.  */
127         .align  4
128 L(big_loop):
129         addi    12,10,32
130         stw     4,0(10)
131         stw     4,4(10)
132         stw     4,8(10)
133         stw     4,12(10)
134         stw     4,16(10)
135         stw     4,20(10)
136         stw     4,24(10)
137         stw     4,28(10)
138         bdz     L(tail_bytes)
140         addi    10,10,64
141         stw     4,0(12)
142         stw     4,4(12)
143         stw     4,8(12)
144         stw     4,12(12)
145         stw     4,16(12)
146         stw     4,20(12)
147         stw     4,24(12)
148         stw     4,28(12)
149         bdnz    L(big_loop_fast_setup)
151         mr      12,10
152         b       L(tail_bytes)
154         /* Now that we're probably past the LHS window, use the VSX to
155            speed up the loop.  */
156 L(big_loop_fast_setup):
157         li      11,24
158         li      6,16
159         lxvdsx  4,1,11
161         .align  4
162 L(big_loop_fast):
163         addi    12,10,32
164         stxvd2x 4,0,10
165         stxvd2x 4,10,6
166         bdz     L(tail_bytes)
168         addi    10,10,64
169         stxvd2x 4,0,12
170         stxvd2x 4,12,6
171         bdnz    L(big_loop_fast)
173         mr      12,10
175         .align  4
176 L(tail_bytes):
178         /* Check for tail bytes.  */
179         mr      1,7             /* Restore r1.  */
180         beqlr   cr6
182         clrlwi  0,5,29
183         mtocrf  0x01,0
185         /*  At this point we have a tail of 0-7 bytes and we know that the
186         destination is doubleword-aligned.  */
187 4:      /* Copy 4 bytes.  */
188         bf      29,2f
190         stw     4,0(12)
191         addi    12,12,4
192 2:      /* Copy 2 bytes.  */
193         bf      30,1f
195         sth     4,0(12)
196         addi    12,12,2
197 1:      /* Copy 1 byte.  */
198         bflr    31
200         stb     4,0(12)
201         blr
204         /* Special case when value is 0 and we have a long length to deal
205            with.  Use dcbz to zero out 128-bytes at a time.  Before using
206            dcbz though, we need to get the destination 128-bytes aligned.  */
207         .align  4
208 L(huge):
209         lfd     4,24(1)
210         andi.   11,10,127
211         neg     0,10
212         beq     L(huge_aligned)
214         clrlwi  0,0,25
215         subf    5,0,5
216         srwi    0,0,3
217         mtocrf  0x01,0
219         /* Get DST aligned to 128 bytes.  */
220 8:      bf      28,4f
222         stfd    4,0(10)
223         stfd    4,8(10)
224         stfd    4,16(10)
225         stfd    4,24(10)
226         stfd    4,32(10)
227         stfd    4,40(10)
228         stfd    4,48(10)
229         stfd    4,56(10)
230         addi    10,10,64
231         .align  4
232 4:      bf      29,2f
234         stfd    4,0(10)
235         stfd    4,8(10)
236         stfd    4,16(10)
237         stfd    4,24(10)
238         addi    10,10,32
239         .align  4
240 2:      bf      30,1f
242         stfd    4,0(10)
243         stfd    4,8(10)
244         addi    10,10,16
245         .align  4
246 1:      bf      31,L(huge_aligned)
248         stfd    4,0(10)
249         addi    10,10,8
251 L(huge_aligned):
252         srwi    8,5,7
253         clrlwi  11,5,25
254         cmplwi  cr6,11,0
255         mtctr   8
257         /* Copies 128-bytes at a time.  */
258         .align  4
259 L(huge_loop):
260         dcbz    0,10
261         addi    10,10,128
262         bdnz    L(huge_loop)
264         /* We have a tail of 0~127 bytes to handle.  */
265         mr      1,7             /* Restore r1.  */
266         beqlr   cr6
268         subf    9,3,10
269         subf    5,9,12
270         srwi    8,5,3
271         cmplwi  cr6,8,0
272         mtocrf  0x01,8
274         /* We have a tail o 1~127 bytes. Copy up to 15 doublewords for
275         speed.  We'll handle the resulting tail bytes later.  */
276         beq     cr6,L(tail)
278 8:      bf      28,4f
280         stfd    4,0(10)
281         stfd    4,8(10)
282         stfd    4,16(10)
283         stfd    4,24(10)
284         stfd    4,32(10)
285         stfd    4,40(10)
286         stfd    4,48(10)
287         stfd    4,56(10)
288         addi    10,10,64
289         .align  4
290 4:      bf      29,2f
292         stfd    4,0(10)
293         stfd    4,8(10)
294         stfd    4,16(10)
295         stfd    4,24(10)
296         addi    10,10,32
297         .align  4
298 2:      bf      30,1f
300         stfd    4,0(10)
301         stfd    4,8(10)
302         addi    10,10,16
303         .align  4
304 1:      bf      31,L(tail)
306         stfd    4,0(10)
307         addi    10,10,8
309         /* Handle the rest of the tail bytes here.  */
310 L(tail):
311         mtocrf  0x01,5
313         .align  4
314 4:      bf      29,2f
316         stw     4,0(10)
317         addi    10,10,4
318         .align  4
319 2:      bf      30,1f
321         sth     4,0(10)
322         addi    10,10,2
323         .align  4
324 1:      bflr    31
326         stb     4,0(10)
327         blr
330         /* Expanded tree to copy tail bytes without increments.  */
331         .align  4
332 L(copy_tail):
333         bf      29,L(FXX)
335         stw     4,0(10)
336         bf      30,L(TFX)
338         sth     4,4(10)
339         bflr    31
341         stb     4,6(10)
342         blr
344         .align  4
345 L(FXX): bf      30,L(FFX)
347         sth     4,0(10)
348         bflr    31
350         stb     4,2(10)
351         blr
353         .align  4
354 L(TFX): bflr    31
356         stb     4,4(10)
357         blr
359         .align  4
360 L(FFX): bflr    31
362         stb     4,0(10)
363         blr
365         /* Handle copies of 9~31 bytes.  */
366         .align  4
367 L(medium):
368         /* At least 9 bytes to go.  */
369         andi.   11,10,3
370         clrlwi  0,0,30
371         beq     L(medium_aligned)
373         /* Force 4-bytes alignment for DST.  */
374         mtocrf  0x01,0
375         subf    5,0,5
376 1:      /* Copy 1 byte.  */
377         bf      31,2f
379         stb     4,0(10)
380         addi    10,10,1
381 2:      /* Copy 2 bytes.  */
382         bf      30,L(medium_aligned)
384         sth     4,0(10)
385         addi    10,10,2
387         .align  4
388 L(medium_aligned):
389         /* At least 6 bytes to go, and DST is word-aligned.  */
390         cmplwi  cr1,5,16
391         mtocrf  0x01,5
392         blt     cr1,8f
394         /* Copy 16 bytes.  */
395         stw     4,0(10)
396         stw     4,4(10)
397         stw     4,8(10)
398         stw     4,12(10)
399         addi    10,10,16
400 8:      /* Copy 8 bytes.  */
401         bf      28,4f
403         stw     4,0(10)
404         stw     4,4(10)
405         addi    10,10,8
406 4:      /* Copy 4 bytes.  */
407         bf      29,2f
409         stw     4,0(10)
410         addi    10,10,4
411 2:      /* Copy 2-3 bytes.  */
412         bf      30,1f
414         sth     4,0(10)
415         addi    10,10,2
416 1:      /* Copy 1 byte.  */
417         bflr    31
419         stb     4,0(10)
420         blr
422         /* Handles copies of 0~8 bytes.  */
423         .align  4
424 L(small):
425         mtocrf  0x01,5
426         bne     cr6,L(copy_tail)
428         stw     4,0(10)
429         stw     4,4(10)
430         blr
432 END (BP_SYM (memset))
433 libc_hidden_builtin_def (memset)