memcpy for ppc/cell.
[glibc.git] / sysdeps / powerpc / powerpc32 / cell / memcpy.S
blobe6c076cbe1f0721e6201a467577cfb150bd1f178
1 /* Optimized memcpy implementation for CELL BE PowerPC.
2    Copyright (C) 2010 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
21 #include <bp-sym.h>
22 #include <bp-asm.h>
24 #define PREFETCH_AHEAD 6        /* no cache lines SRC prefetching ahead  */
25 #define ZERO_AHEAD 4            /* no cache lines DST zeroing ahead  */
27 /* memcpy routine optimized for CELL-BE-PPC     v2.0
28  *
29  * The CELL PPC core has 1 integer unit and 1 load/store unit
30  * CELL:
31  * 1st level data cache = 32K
32  * 2nd level data cache = 512K
33  * 3rd level data cache = 0K
34  * With 3.2 GHz clockrate the latency to 2nd level cache is >36 clocks,
35  * latency to memory is >400 clocks
36  * To improve copy performance we need to prefetch source data
37  * far ahead to hide this latency
38  * For best performance instructionforms ending in "." like "andi."
39  * should be avoided as the are implemented in microcode on CELL.
40  * The below code is loop unrolled for the CELL cache line of 128 bytes
41  */
43 .align  7
45 EALIGN (BP_SYM (memcpy), 5, 0)
46         CALL_MCOUNT
48         dcbt    0,r4            /* Prefetch ONE SRC cacheline  */
49         cmplwi  cr1,r5,16       /* is size < 16 ?  */
50         mr      r6,r3           
51         blt+    cr1,.Lshortcopy
53 .Lbigcopy:
54         neg     r8,r3           /* LS 3 bits = # bytes to 8-byte dest bdry  */
55         clrlwi  r8,r8,32-4      /* aling to 16byte boundary  */
56         sub     r7,r4,r3
57         cmplwi  cr0,r8,0
58         beq+    .Ldst_aligned
60 .Ldst_unaligned:
61         mtcrf   0x01,r8         /* put #bytes to boundary into cr7  */
62         subf    r5,r8,r5
64         bf      cr7*4+3,1f
65         lbzx    r0,r7,r6        /* copy 1 byte  */
66         stb     r0,0(r6)
67         addi    r6,r6,1
68 1:      bf      cr7*4+2,2f
69         lhzx    r0,r7,r6        /* copy 2 byte  */
70         sth     r0,0(r6)
71         addi    r6,r6,2
72 2:      bf      cr7*4+1,4f
73         lwzx    r0,r7,r6        /* copy 4 byte  */
74         stw     r0,0(r6)
75         addi    r6,r6,4
76 4:      bf      cr7*4+0,8f
77         lfdx    fp9,r7,r6       /* copy 8 byte  */
78         stfd    fp9,0(r6)
79         addi    r6,r6,8
81         add     r4,r7,r6
83 .Ldst_aligned:
85         cmpwi   cr5,r5,128-1
87         neg     r7,r6
88         addi    r6,r6,-8        /* prepare for stfdu  */
89         addi    r4,r4,-8        /* prepare for lfdu  */
91         clrlwi  r7,r7,32-7      /* align to cacheline boundary  */
92         ble+    cr5,.Llessthancacheline
94         cmplwi  cr6,r7,0
95         subf    r5,r7,r5
96         srwi    r7,r7,4         /* divide size by 16  */
97         srwi    r10,r5,7        /* number of cache lines to copy  */
99         cmplwi  r10,0
100         li      r11,0           /* number cachelines to copy with prefetch  */
101         beq     .Lnocacheprefetch
103         cmplwi  r10,PREFETCH_AHEAD
104         li      r12,128+8       /* prefetch distance  */
105         ble     .Llessthanmaxprefetch
107         subi    r11,r10,PREFETCH_AHEAD
108         li      r10,PREFETCH_AHEAD
110 .Llessthanmaxprefetch:
111         mtctr   r10
113 .LprefetchSRC:
114         dcbt    r12,r4
115         addi    r12,r12,128
116         bdnz    .LprefetchSRC
118 .Lnocacheprefetch:
119         mtctr   r7
120         cmplwi  cr1,r5,128
121         clrlwi  r5,r5,32-7
122         beq     cr6,.Lcachelinealigned
124 .Laligntocacheline:
125         lfd     fp9,0x08(r4)
126         lfdu    fp10,0x10(r4)
127         stfd    fp9,0x08(r6)
128         stfdu   fp10,0x10(r6)
129         bdnz    .Laligntocacheline
132 .Lcachelinealigned:             /* copy while cache lines  */
134         blt-    cr1,.Llessthancacheline /* size <128  */
136 .Louterloop:
137         cmpwi   r11,0
138         mtctr   r11
139         beq-    .Lendloop
141         li      r11,128*ZERO_AHEAD +8   /* DCBZ dist  */
143 .align  4
144         /* Copy whole cachelines, optimized by prefetching SRC cacheline  */
145 .Lloop:                         /* Copy aligned body  */
146         dcbt    r12,r4          /* PREFETCH SOURCE some cache lines ahead  */
147         lfd     fp9, 0x08(r4)
148         dcbz    r11,r6
149         lfd     fp10, 0x10(r4)  /* 4 register stride copy is optimal  */
150         lfd     fp11, 0x18(r4)  /* to hide 1st level cache lantency.  */
151         lfd     fp12, 0x20(r4)
152         stfd    fp9, 0x08(r6)
153         stfd    fp10, 0x10(r6)
154         stfd    fp11, 0x18(r6)
155         stfd    fp12, 0x20(r6)
156         lfd     fp9, 0x28(r4)
157         lfd     fp10, 0x30(r4)
158         lfd     fp11, 0x38(r4)
159         lfd     fp12, 0x40(r4)
160         stfd    fp9, 0x28(r6)
161         stfd    fp10, 0x30(r6)
162         stfd    fp11, 0x38(r6)
163         stfd    fp12, 0x40(r6)
164         lfd     fp9, 0x48(r4)
165         lfd     fp10, 0x50(r4)
166         lfd     fp11, 0x58(r4)
167         lfd     fp12, 0x60(r4)
168         stfd    fp9, 0x48(r6)
169         stfd    fp10, 0x50(r6)
170         stfd    fp11, 0x58(r6)
171         stfd    fp12, 0x60(r6)
172         lfd     fp9, 0x68(r4)
173         lfd     fp10, 0x70(r4)
174         lfd     fp11, 0x78(r4)
175         lfdu    fp12, 0x80(r4)
176         stfd    fp9, 0x68(r6)
177         stfd    fp10, 0x70(r6)
178         stfd    fp11, 0x78(r6)
179         stfdu   fp12, 0x80(r6)
181         bdnz    .Lloop
183 .Lendloop:
184         cmpwi   r10,0
185         slwi    r10,r10,2       /* adjust from 128 to 32 byte stride  */
186         beq-    .Lendloop2
187         mtctr   r10
189 .Lloop2:                        /* Copy aligned body  */
190         lfd     fp9, 0x08(r4)
191         lfd     fp10, 0x10(r4)
192         lfd     fp11, 0x18(r4)
193         lfdu    fp12, 0x20(r4)
194         stfd    fp9, 0x08(r6)
195         stfd    fp10, 0x10(r6)
196         stfd    fp11, 0x18(r6)
197         stfdu   fp12, 0x20(r6)
199         bdnz    .Lloop2
200 .Lendloop2:
202 .Llessthancacheline:            /* less than cache to do ?  */
203         cmplwi  cr0,r5,16
204         srwi    r7,r5,4         /* divide size by 16  */
205         blt-    .Ldo_lt16
206         mtctr   r7
208 .Lcopy_remaining:
209         lfd     fp9,0x08(r4)
210         lfdu    fp10,0x10(r4)
211         stfd    fp9,0x08(r6)
212         stfdu   fp10,0x10(r6)
213         bdnz    .Lcopy_remaining
215 .Ldo_lt16:                      /* less than 16 ?  */
216         cmplwi  cr0,r5,0        /* copy remaining bytes (0-15)  */
217         beqlr+                  /* no rest to copy  */  
218         addi    r4,r4,8
219         addi    r6,r6,8
221 .Lshortcopy:                    /* SIMPLE COPY to handle size =< 15 bytes  */
222         mtcrf   0x01,r5
223         sub     r7,r4,r6
224         bf-     cr7*4+0,8f
225         lfdx    fp9,r7,r6       /* copy 8 byte  */
226         stfd    fp9,0(r6)
227         addi    r6,r6,8
229         bf      cr7*4+1,4f
230         lwzx    r0,r7,r6        /* copy 4 byte  */
231         stw     r0,0(r6)
232         addi    r6,r6,4
234         bf      cr7*4+2,2f
235         lhzx    r0,r7,r6        /* copy 2 byte  */
236         sth     r0,0(r6)
237         addi    r6,r6,2
239         bf      cr7*4+3,1f
240         lbzx    r0,r7,r6        /* copy 1 byte  */
241         stb     r0,0(r6)
242 1:      blr
244 END (BP_SYM (memcpy))
245 libc_hidden_builtin_def (memcpy)