powerpc: Move cache line size to rtld_global_ro
[glibc.git] / sysdeps / powerpc / powerpc32 / a2 / memcpy.S
blob6f4d8a7b34f7702376275b63df10a9283a60648e
1 /* Optimized memcpy implementation for PowerPC A2.
2    Copyright (C) 2010-2020 Free Software Foundation, Inc.
3    Contributed by Michael Brutman <brutman@us.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    <https://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include <rtld-global-offsets.h>
23 #define PREFETCH_AHEAD 4        /* no cache lines SRC prefetching ahead  */
24 #define ZERO_AHEAD 2            /* no cache lines DST zeroing ahead  */
26         .machine  a2
27 EALIGN (memcpy, 5, 0)
28         CALL_MCOUNT
30         dcbt    0,r4            /* Prefetch ONE SRC cacheline  */
31         cmplwi  cr1,r5,16       /* is size < 16 ?  */
32         mr      r6,r3           /* Copy dest reg to r6; */
33         blt+    cr1,L(shortcopy)
36         /* Big copy (16 bytes or more)
38            Figure out how far to the nearest quadword boundary, or if we are
39            on one already.
41            r3 - return value (always)
42            r4 - current source addr
43            r5 - copy length
44            r6 - current dest addr
45         */
47         neg     r8,r3           /* LS 4 bits = # bytes to 8-byte dest bdry  */
48         clrlwi  r8,r8,32-4      /* align to 16byte boundary  */
49         sub     r7,r4,r3        /* compute offset to src from dest */
50         cmplwi  cr0,r8,0        /* Were we aligned on a 16 byte bdy? */
51         beq+    L(dst_aligned)
55         /* Destination is not aligned on quadword boundary.  Get us to one.
57            r3 - return value (always)
58            r4 - current source addr
59            r5 - copy length
60            r6 - current dest addr
61            r7 - offset to src from dest
62            r8 - number of bytes to quadword boundary
63         */
65         mtcrf   0x01,r8         /* put #bytes to boundary into cr7  */
66         subf    r5,r8,r5        /* adjust remaining len */
68         bf      cr7*4+3,1f
69         lbzx    r0,r7,r6        /* copy 1 byte addr */
70         stb     r0,0(r6)
71         addi    r6,r6,1
73         bf      cr7*4+2,2f
74         lhzx    r0,r7,r6        /* copy 2 byte addr */
75         sth     r0,0(r6)
76         addi    r6,r6,2
78         bf      cr7*4+1,4f
79         lwzx    r0,r7,r6        /* copy 4 byte addr */
80         stw     r0,0(r6)
81         addi    r6,r6,4
83         bf      cr7*4+0,8f
84         lfdx    r0,r7,r6        /* copy 8 byte addr */
85         stfd    r0,0(r6)
86         addi    r6,r6,8
88         add     r4,r7,r6        /* update src addr */
92         /* Dest is quadword aligned now.
94            Lots of decisions to make.  If we are copying less than a cache
95            line we won't be here long.  If we are not on a cache line
96            boundary we need to get there.  And then we need to figure out
97            how many cache lines ahead to pre-touch.
99            r3 - return value (always)
100            r4 - current source addr
101            r5 - copy length
102            r6 - current dest addr
103         */
106         .align  4
107 L(dst_aligned):
110 #ifdef PIC
111         mflr    r0
112 /* Establishes GOT addressability so we can load the cache line size
113    from rtld_global_ro.  This value was set from the aux vector during
114    startup.  */
115         SETUP_GOT_ACCESS(r9,got_label)
116         addis   r9,r9,_GLOBAL_OFFSET_TABLE_-got_label@ha
117         addi    r9,r9,_GLOBAL_OFFSET_TABLE_-got_label@l
118         mtlr    r0
119 #endif
120         __GLRO(r9, r9, _dl_cache_line_size,
121                RTLD_GLOBAL_RO_DL_CACHE_LINE_SIZE_OFFSET)
123         cmplwi  cr5, r9, 0
124         bne+    cr5,L(cachelineset)
126 /* Cache line size not set: generic byte copy without much optimization */
127         andi.   r0,r5,1         /* If length is odd copy one byte.  */
128         beq     L(cachelinenotset_align)
129         lbz     r7,0(r4)        /* Read one byte from source.  */
130         addi    r5,r5,-1        /* Update length.  */
131         addi    r4,r4,1         /* Update source pointer address.  */
132         stb     r7,0(r6)        /* Store one byte on dest.  */
133         addi    r6,r6,1         /* Update dest pointer address.  */
134 L(cachelinenotset_align):
135         cmpwi   cr7,r5,0        /* If length is 0 return.  */
136         beqlr   cr7
137         ori     r2,r2,0         /* Force a new dispatch group.  */
138 L(cachelinenotset_loop):
139         addic.  r5,r5,-2        /* Update length.  */
140         lbz     r7,0(r4)        /* Load 2 bytes from source.  */
141         lbz     r8,1(r4)
142         addi    r4,r4,2         /* Update source pointer address.  */
143         stb     r7,0(r6)        /* Store 2 bytes on dest.  */
144         stb     r8,1(r6)
145         addi    r6,r6,2         /* Update dest pointer address.  */
146         bne     L(cachelinenotset_loop)
147         blr
150 L(cachelineset):
152         addi   r10,r9,-1
154         cmpw   cr5,r5,r10       /* Less than a cacheline to go? */
156         neg     r7,r6           /* How far to next cacheline bdy? */
158         addi    r6,r6,-8        /* prepare for stdu  */
159         cmpwi   cr0,r9,128
160         addi    r4,r4,-8        /* prepare for ldu  */
163         ble+    cr5,L(lessthancacheline)
165         beq-    cr0,L(big_lines) /* 128 byte line code */
170         /* More than a cacheline left to go, and using 64 byte cachelines */
172         clrlwi  r7,r7,32-6      /* How far to next cacheline bdy? */
174         cmplwi  cr6,r7,0        /* Are we on a cacheline bdy already? */
176         /* Reduce total len by what it takes to get to the next cache line */
177         subf    r5,r7,r5
178         srwi    r7,r7,4         /* How many qws to get to the line bdy? */
180         /* How many full cache lines to copy after getting to a line bdy? */
181         srwi    r10,r5,6
183         cmplwi  r10,0           /* If no full cache lines to copy ... */
184         li      r11,0           /* number cachelines to copy with prefetch  */
185         beq     L(nocacheprefetch)
188         /* We are here because we have at least one full cache line to copy,
189            and therefore some pre-touching to do. */
191         cmplwi  r10,PREFETCH_AHEAD
192         li      r12,64+8        /* prefetch distance  */
193         ble     L(lessthanmaxprefetch)
195         /* We can only do so much pre-fetching.  R11 will have the count of
196            lines left to prefetch after the initial batch of prefetches
197            are executed. */
199         subi    r11,r10,PREFETCH_AHEAD
200         li      r10,PREFETCH_AHEAD
202 L(lessthanmaxprefetch):
203         mtctr   r10
205         /* At this point r10/ctr hold the number of lines to prefetch in this
206            initial batch, and r11 holds any remainder. */
208 L(prefetchSRC):
209         dcbt    r12,r4
210         addi    r12,r12,64
211         bdnz    L(prefetchSRC)
214         /* Prefetching is done, or was not needed.
216            cr6 - are we on a cacheline boundary already?
217            r7  - number of quadwords to the next cacheline boundary
218         */
220 L(nocacheprefetch):
221         mtctr   r7
223         cmplwi  cr1,r5,64   /* Less than a cache line to copy? */
225         /* How many bytes are left after we copy whatever full
226            cache lines we can get? */
227         clrlwi  r5,r5,32-6
229         beq     cr6,L(cachelinealigned)
232         /* Copy quadwords up to the next cacheline boundary */
234 L(aligntocacheline):
235         lfd     fp9,0x08(r4)
236         lfdu    fp10,0x10(r4)
237         stfd    fp9,0x08(r6)
238         stfdu   fp10,0x10(r6)
239         bdnz    L(aligntocacheline)
242         .align 4
243 L(cachelinealigned):            /* copy while cache lines  */
245         blt-    cr1,L(lessthancacheline) /* size <64  */
247 L(outerloop):
248         cmpwi   r11,0
249         mtctr   r11
250         beq-    L(endloop)
252         li      r11,64*ZERO_AHEAD +8    /* DCBZ dist  */
254         .align  4
255         /* Copy whole cachelines, optimized by prefetching SRC cacheline  */
256 L(loop):                        /* Copy aligned body  */
257         dcbt    r12,r4          /* PREFETCH SOURCE some cache lines ahead  */
258         lfd     fp9,  0x08(r4)
259         dcbz    r11,r6
260         lfd     fp10, 0x10(r4)
261         lfd     fp11, 0x18(r4)
262         lfd     fp12, 0x20(r4)
263         stfd    fp9,  0x08(r6)
264         stfd    fp10, 0x10(r6)
265         stfd    fp11, 0x18(r6)
266         stfd    fp12, 0x20(r6)
267         lfd     fp9,  0x28(r4)
268         lfd     fp10, 0x30(r4)
269         lfd     fp11, 0x38(r4)
270         lfdu    fp12, 0x40(r4)
271         stfd    fp9,  0x28(r6)
272         stfd    fp10, 0x30(r6)
273         stfd    fp11, 0x38(r6)
274         stfdu   fp12, 0x40(r6)
276         bdnz    L(loop)
279 L(endloop):
280         cmpwi   r10,0
281         beq-    L(endloop2)
282         mtctr   r10
284 L(loop2):                       /* Copy aligned body  */
285         lfd     fp9,  0x08(r4)
286         lfd     fp10, 0x10(r4)
287         lfd     fp11, 0x18(r4)
288         lfd     fp12, 0x20(r4)
289         stfd    fp9,  0x08(r6)
290         stfd    fp10, 0x10(r6)
291         stfd    fp11, 0x18(r6)
292         stfd    fp12, 0x20(r6)
293         lfd     fp9,  0x28(r4)
294         lfd     fp10, 0x30(r4)
295         lfd     fp11, 0x38(r4)
296         lfdu    fp12, 0x40(r4)
297         stfd    fp9,  0x28(r6)
298         stfd    fp10, 0x30(r6)
299         stfd    fp11, 0x38(r6)
300         stfdu   fp12, 0x40(r6)
302         bdnz    L(loop2)
303 L(endloop2):
306         .align  4
307 L(lessthancacheline):           /* Was there less than cache to do ?  */
308         cmplwi  cr0,r5,16
309         srwi    r7,r5,4         /* divide size by 16  */
310         blt-    L(do_lt16)
311         mtctr   r7
313 L(copy_remaining):
314         lfd     fp9,  0x08(r4)
315         lfdu    fp10, 0x10(r4)
316         stfd    fp9,  0x08(r6)
317         stfdu   fp10, 0x10(r6)
318         bdnz    L(copy_remaining)
320 L(do_lt16):                     /* less than 16 ?  */
321         cmplwi  cr0,r5,0        /* copy remaining bytes (0-15)  */
322         beqlr+                  /* no rest to copy  */
323         addi    r4,r4,8
324         addi    r6,r6,8
326 L(shortcopy):                   /* SIMPLE COPY to handle size =< 15 bytes  */
327         mtcrf   0x01,r5
328         sub     r7,r4,r6
329         bf-     cr7*4+0,8f
330         lfdx    fp9,r7,r6       /* copy 8 byte  */
331         stfd    fp9,0(r6)
332         addi    r6,r6,8
334         bf      cr7*4+1,4f
335         lwzx    r0,r7,r6        /* copy 4 byte  */
336         stw     r0,0(r6)
337         addi    r6,r6,4
339         bf      cr7*4+2,2f
340         lhzx    r0,r7,r6        /* copy 2 byte  */
341         sth     r0,0(r6)
342         addi    r6,r6,2
344         bf      cr7*4+3,1f
345         lbzx    r0,r7,r6        /* copy 1 byte  */
346         stb     r0,0(r6)
348         blr
354         /* Similar to above, but for use with 128 byte lines. */
357 L(big_lines):
359         clrlwi  r7,r7,32-7      /* How far to next cacheline bdy? */
361         cmplwi  cr6,r7,0        /* Are we on a cacheline bdy already? */
363         /* Reduce total len by what it takes to get to the next cache line */
364         subf    r5,r7,r5
365         srwi    r7,r7,4         /* How many qw to get to the line bdy? */
367         /* How many full cache lines to copy after getting to a line bdy? */
368         srwi    r10,r5,7
370         cmplwi  r10,0           /* If no full cache lines to copy ... */
371         li      r11,0           /* number cachelines to copy with prefetch  */
372         beq     L(nocacheprefetch_128)
375         /* We are here because we have at least one full cache line to copy,
376            and therefore some pre-touching to do. */
378         cmplwi  r10,PREFETCH_AHEAD
379         li      r12,128+8       /* prefetch distance  */
380         ble     L(lessthanmaxprefetch_128)
382         /* We can only do so much pre-fetching.  R11 will have the count of
383            lines left to prefetch after the initial batch of prefetches
384            are executed. */
386         subi    r11,r10,PREFETCH_AHEAD
387         li      r10,PREFETCH_AHEAD
389 L(lessthanmaxprefetch_128):
390         mtctr   r10
392         /* At this point r10/ctr hold the number of lines to prefetch in this
393            initial batch, and r11 holds any remainder. */
395 L(prefetchSRC_128):
396         dcbt    r12,r4
397         addi    r12,r12,128
398         bdnz    L(prefetchSRC_128)
401         /* Prefetching is done, or was not needed.
403            cr6 - are we on a cacheline boundary already?
404            r7  - number of quadwords to the next cacheline boundary
405         */
407 L(nocacheprefetch_128):
408         mtctr   r7
410         cmplwi  cr1,r5,128  /* Less than a cache line to copy? */
412         /* How many bytes are left after we copy whatever full
413            cache lines we can get? */
414         clrlwi  r5,r5,32-7
416         beq     cr6,L(cachelinealigned_128)
419         /* Copy quadwords up to the next cacheline boundary */
421 L(aligntocacheline_128):
422         lfd     fp9,0x08(r4)
423         lfdu    fp10,0x10(r4)
424         stfd    fp9,0x08(r6)
425         stfdu   fp10,0x10(r6)
426         bdnz    L(aligntocacheline_128)
429 L(cachelinealigned_128):        /* copy while cache lines  */
431         blt-    cr1,L(lessthancacheline) /* size <128  */
433 L(outerloop_128):
434         cmpwi   r11,0
435         mtctr   r11
436         beq-    L(endloop_128)
438         li      r11,128*ZERO_AHEAD +8    /* DCBZ dist  */
440         .align  4
441         /* Copy whole cachelines, optimized by prefetching SRC cacheline  */
442 L(loop_128):                    /* Copy aligned body  */
443         dcbt    r12,r4          /* PREFETCH SOURCE some cache lines ahead  */
444         lfd     fp9,  0x08(r4)
445         dcbz    r11,r6
446         lfd     fp10, 0x10(r4)
447         lfd     fp11, 0x18(r4)
448         lfd     fp12, 0x20(r4)
449         stfd    fp9,  0x08(r6)
450         stfd    fp10, 0x10(r6)
451         stfd    fp11, 0x18(r6)
452         stfd    fp12, 0x20(r6)
453         lfd     fp9,  0x28(r4)
454         lfd     fp10, 0x30(r4)
455         lfd     fp11, 0x38(r4)
456         lfd     fp12, 0x40(r4)
457         stfd    fp9,  0x28(r6)
458         stfd    fp10, 0x30(r6)
459         stfd    fp11, 0x38(r6)
460         stfd    fp12, 0x40(r6)
461         lfd     fp9,  0x48(r4)
462         lfd     fp10, 0x50(r4)
463         lfd     fp11, 0x58(r4)
464         lfd     fp12, 0x60(r4)
465         stfd    fp9,  0x48(r6)
466         stfd    fp10, 0x50(r6)
467         stfd    fp11, 0x58(r6)
468         stfd    fp12, 0x60(r6)
469         lfd     fp9,  0x68(r4)
470         lfd     fp10, 0x70(r4)
471         lfd     fp11, 0x78(r4)
472         lfdu    fp12, 0x80(r4)
473         stfd    fp9,  0x68(r6)
474         stfd    fp10, 0x70(r6)
475         stfd    fp11, 0x78(r6)
476         stfdu   fp12, 0x80(r6)
478         bdnz    L(loop_128)
481 L(endloop_128):
482         cmpwi   r10,0
483         beq-    L(endloop2_128)
484         mtctr   r10
486 L(loop2_128):                   /* Copy aligned body  */
487         lfd     fp9,  0x08(r4)
488         lfd     fp10, 0x10(r4)
489         lfd     fp11, 0x18(r4)
490         lfd     fp12, 0x20(r4)
491         stfd    fp9,  0x08(r6)
492         stfd    fp10, 0x10(r6)
493         stfd    fp11, 0x18(r6)
494         stfd    fp12, 0x20(r6)
495         lfd     fp9,  0x28(r4)
496         lfd     fp10, 0x30(r4)
497         lfd     fp11, 0x38(r4)
498         lfd     fp12, 0x40(r4)
499         stfd    fp9,  0x28(r6)
500         stfd    fp10, 0x30(r6)
501         stfd    fp11, 0x38(r6)
502         stfd    fp12, 0x40(r6)
503         lfd     fp9,  0x48(r4)
504         lfd     fp10, 0x50(r4)
505         lfd     fp11, 0x58(r4)
506         lfd     fp12, 0x60(r4)
507         stfd    fp9,  0x48(r6)
508         stfd    fp10, 0x50(r6)
509         stfd    fp11, 0x58(r6)
510         stfd    fp12, 0x60(r6)
511         lfd     fp9,  0x68(r4)
512         lfd     fp10, 0x70(r4)
513         lfd     fp11, 0x78(r4)
514         lfdu    fp12, 0x80(r4)
515         stfd    fp9,  0x68(r6)
516         stfd    fp10, 0x70(r6)
517         stfd    fp11, 0x78(r6)
518         stfdu   fp12, 0x80(r6)
519         bdnz    L(loop2_128)
520 L(endloop2_128):
522         b       L(lessthancacheline)
525 END (memcpy)
526 libc_hidden_builtin_def (memcpy)