powerpc: POWER7 optimizations
[glibc.git] / sysdeps / powerpc / powerpc32 / power7 / memset.S
blob8aabb49327584f4ce1fdd8247acf0a6ca779528b
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, write to the Free
18    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
19    02110-1301 USA.  */
21 #include <sysdep.h>
22 #include <bp-sym.h>
23 #include <bp-asm.h>
25 /* __ptr_t [r3] memset (__ptr_t s [r3], int c [r4], size_t n [r5]));
26    Returns 's'.  */
28         .machine  power7
29 EALIGN (BP_SYM (memset), 5, 0)
30         CALL_MCOUNT
32         .align  4
33 L(_memset):
34         cmplwi  cr7,5,31
35         cmplwi  cr6,5,8
36         mr      10,3            /* Save original argument for later.  */
37         mr      7,1             /* Save original r1 for later.  */
38         cfi_offset(31,-8)
40         /* Replicate byte to word.  */
41         rlwimi  4,4,8,16,23
42         rlwimi  4,4,16,0,15
44         ble     cr6,L(small)    /* If length <= 8, use short copy code.  */
46         neg     0,3
47         ble     cr7,L(medium)   /* If length < 32, use medium copy code.  */
49         /* Save our word twice to create a doubleword that we will later
50            copy to a FPR.  */
51         stwu    1,-32(1)
52         andi.   11,10,7         /* Check alignment of DST.  */
53         mr      12,5
54         stw     4,24(1)
55         stw     4,28(1)
56         beq     L(big_aligned)
58         clrlwi  0,0,29
59         mtocrf  0x01,0
60         subf    5,0,5
62         /* Get DST aligned to 8 bytes.  */
63 1:      bf      31,2f
65         stb     4,0(10)
66         addi    10,10,1
67 2:      bf      30,4f
69         sth     4,0(10)
70         addi    10,10,2
71 4:      bf      29,L(big_aligned)
73         stw     4,0(10)
74         addi    10,10,4
76         .align  4
77 L(big_aligned):
78         cmplwi  cr5,5,255
79         li      0,32
80         cmplwi  cr1,5,160
81         dcbtst  0,10
82         cmplwi  cr6,4,0
83         srwi    9,5,3           /* Number of full doublewords remaining.  */
84         crand   27,26,21
85         mtocrf  0x01,9
86         bt      27,L(huge)
88         /* From this point on, we'll copy 32+ bytes and the value
89            isn't 0 (so we can't use dcbz).  */
91         srwi    8,5,5
92         clrlwi  11,5,29
93         cmplwi  cr6,11,0
94         cmplwi  cr1,9,4
95         mtctr   8
97         /* Copy 1~3 doublewords so the main loop starts
98         at a multiple of 32 bytes.  */
100         bf      30,1f
102         stw     4,0(10)
103         stw     4,4(10)
104         stw     4,8(10)
105         stw     4,12(10)
106         addi    10,10,16
107         bf      31,L(big_loop)
109         stw     4,0(10)
110         stw     4,4(10)
111         addi    10,10,8
112         mr      12,10
113         blt     cr1,L(tail_bytes)
115         b       L(big_loop)
117         .align  4
118 1:      /* Copy 1 doubleword.  */
119         bf      31,L(big_loop)
121         stw     4,0(10)
122         stw     4,4(10)
123         addi    10,10,8
125         /* First use a 32-bytes loop with stw's to try and avoid the LHS due
126            to the lfd we will do next.  Also, ping-pong through r10 and r12
127            to avoid AGEN delays.  */
128         .align  4
129 L(big_loop):
130         addi    12,10,32
131         stw     4,0(10)
132         stw     4,4(10)
133         stw     4,8(10)
134         stw     4,12(10)
135         stw     4,16(10)
136         stw     4,20(10)
137         stw     4,24(10)
138         stw     4,28(10)
139         bdz     L(tail_bytes)
141         addi    10,10,64
142         stw     4,0(12)
143         stw     4,4(12)
144         stw     4,8(12)
145         stw     4,12(12)
146         stw     4,16(12)
147         stw     4,20(12)
148         stw     4,24(12)
149         stw     4,28(12)
150         bdnz    L(big_loop_fast_setup)
152         mr      12,10
153         b       L(tail_bytes)
155         /* Now that we're probably past the LHS window, use the VSX to
156            speed up the loop.  */
157 L(big_loop_fast_setup):
158         li      11,24
159         li      6,16
160         lxvdsx  4,1,11
162         .align  4
163 L(big_loop_fast):
164         addi    12,10,32
165         stxvd2x 4,0,10
166         stxvd2x 4,10,6
167         bdz     L(tail_bytes)
169         addi    10,10,64
170         stxvd2x 4,0,12
171         stxvd2x 4,12,6
172         bdnz    L(big_loop_fast)
174         mr      12,10
176         .align  4
177 L(tail_bytes):
179         /* Check for tail bytes.  */
180         mr      1,7             /* Restore r1.  */
181         beqlr   cr6
183         clrlwi  0,5,29
184         mtocrf  0x01,0
186         /*  At this point we have a tail of 0-7 bytes and we know that the
187         destination is doubleword-aligned.  */
188 4:      /* Copy 4 bytes.  */
189         bf      29,2f
191         stw     4,0(12)
192         addi    12,12,4
193 2:      /* Copy 2 bytes.  */
194         bf      30,1f
196         sth     4,0(12)
197         addi    12,12,2
198 1:      /* Copy 1 byte.  */
199         bflr    31
201         stb     4,0(12)
202         blr
205         /* Special case when value is 0 and we have a long length to deal
206            with.  Use dcbz to zero out 128-bytes at a time.  Before using
207            dcbz though, we need to get the destination 128-bytes aligned.  */
208         .align  4
209 L(huge):
210         lfd     4,24(1)
211         andi.   11,10,127
212         neg     0,10
213         beq     L(huge_aligned)
215         clrlwi  0,0,25
216         subf    5,0,5
217         srwi    0,0,3
218         mtocrf  0x01,0
220         /* Get DST aligned to 128 bytes.  */
221 8:      bf      28,4f
223         stfd    4,0(10)
224         stfd    4,8(10)
225         stfd    4,16(10)
226         stfd    4,24(10)
227         stfd    4,32(10)
228         stfd    4,40(10)
229         stfd    4,48(10)
230         stfd    4,56(10)
231         addi    10,10,64
232         .align  4
233 4:      bf      29,2f
235         stfd    4,0(10)
236         stfd    4,8(10)
237         stfd    4,16(10)
238         stfd    4,24(10)
239         addi    10,10,32
240         .align  4
241 2:      bf      30,1f
243         stfd    4,0(10)
244         stfd    4,8(10)
245         addi    10,10,16
246         .align  4
247 1:      bf      31,L(huge_aligned)
249         stfd    4,0(10)
250         addi    10,10,8
252 L(huge_aligned):
253         srwi    8,5,7
254         clrlwi  11,5,25
255         cmplwi  cr6,11,0
256         mtctr   8
258         /* Copies 128-bytes at a time.  */
259         .align  4
260 L(huge_loop):
261         dcbz    0,10
262         addi    10,10,128
263         bdnz    L(huge_loop)
265         /* We have a tail of 0~127 bytes to handle.  */
266         mr      1,7             /* Restore r1.  */
267         beqlr   cr6
269         subf    9,3,10
270         subf    5,9,12
271         srwi    8,5,3
272         cmplwi  cr6,8,0
273         mtocrf  0x01,8
275         /* We have a tail o 1~127 bytes. Copy up to 15 doublewords for
276         speed.  We'll handle the resulting tail bytes later.  */
277         beq     cr6,L(tail)
279 8:      bf      28,4f
281         stfd    4,0(10)
282         stfd    4,8(10)
283         stfd    4,16(10)
284         stfd    4,24(10)
285         stfd    4,32(10)
286         stfd    4,40(10)
287         stfd    4,48(10)
288         stfd    4,56(10)
289         addi    10,10,64
290         .align  4
291 4:      bf      29,2f
293         stfd    4,0(10)
294         stfd    4,8(10)
295         stfd    4,16(10)
296         stfd    4,24(10)
297         addi    10,10,32
298         .align  4
299 2:      bf      30,1f
301         stfd    4,0(10)
302         stfd    4,8(10)
303         addi    10,10,16
304         .align  4
305 1:      bf      31,L(tail)
307         stfd    4,0(10)
308         addi    10,10,8
310         /* Handle the rest of the tail bytes here.  */
311 L(tail):
312         mtocrf  0x01,5
314         .align  4
315 4:      bf      29,2f
317         stw     4,0(10)
318         addi    10,10,4
319         .align  4
320 2:      bf      30,1f
322         sth     4,0(10)
323         addi    10,10,2
324         .align  4
325 1:      bflr    31
327         stb     4,0(10)
328         blr
331         /* Expanded tree to copy tail bytes without increments.  */
332         .align  4
333 L(copy_tail):
334         bf      29,L(FXX)
336         stw     4,0(10)
337         bf      30,L(TFX)
339         sth     4,4(10)
340         bflr    31
342         stb     4,6(10)
343         blr
345         .align  4
346 L(FXX): bf      30,L(FFX)
348         sth     4,0(10)
349         bflr    31
351         stb     4,2(10)
352         blr
354         .align  4
355 L(TFX): bflr    31
357         stb     4,4(10)
358         blr
360         .align  4
361 L(FFX): bflr    31
363         stb     4,0(10)
364         blr
366         /* Handle copies of 9~31 bytes.  */
367         .align  4
368 L(medium):
369         /* At least 9 bytes to go.  */
370         andi.   11,10,3
371         clrlwi  0,0,30
372         beq     L(medium_aligned)
374         /* Force 4-bytes alignment for DST.  */
375         mtocrf  0x01,0
376         subf    5,0,5
377 1:      /* Copy 1 byte.  */
378         bf      31,2f
380         stb     4,0(10)
381         addi    10,10,1
382 2:      /* Copy 2 bytes.  */
383         bf      30,L(medium_aligned)
385         sth     4,0(10)
386         addi    10,10,2
388         .align  4
389 L(medium_aligned):
390         /* At least 6 bytes to go, and DST is word-aligned.  */
391         cmplwi  cr1,5,16
392         mtocrf  0x01,5
393         blt     cr1,8f
395         /* Copy 16 bytes.  */
396         stw     4,0(10)
397         stw     4,4(10)
398         stw     4,8(10)
399         stw     4,12(10)
400         addi    10,10,16
401 8:      /* Copy 8 bytes.  */
402         bf      28,4f
404         stw     4,0(10)
405         stw     4,4(10)
406         addi    10,10,8
407 4:      /* Copy 4 bytes.  */
408         bf      29,2f
410         stw     4,0(10)
411         addi    10,10,4
412 2:      /* Copy 2-3 bytes.  */
413         bf      30,1f
415         sth     4,0(10)
416         addi    10,10,2
417 1:      /* Copy 1 byte.  */
418         bflr    31
420         stb     4,0(10)
421         blr
423         /* Handles copies of 0~8 bytes.  */
424         .align  4
425 L(small):
426         mtocrf  0x01,5
427         bne     cr6,L(copy_tail)
429         stw     4,0(10)
430         stw     4,4(10)
431         blr
433 END (BP_SYM (memset))
434 libc_hidden_builtin_def (memset)