~vorlon/ubuntu/natty/eglibc/multiarch

« back to all changes in this revision

Viewing changes to sysdeps/powerpc/powerpc32/a2/memcpy.S

  • Committer: Steve Langasek
  • Date: 2011-02-18 21:18:44 UTC
  • mfrom: (103.1.7 eglibc)
  • Revision ID: steve.langasek@linaro.org-20110218211844-lodmi8b1qhyq3f3x
Tags: 2.13~pre1-0ubuntu1+multiarch.1
merge from natty

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Optimized memcpy implementation for PowerPC A2.
 
2
   Copyright (C) 2010 Free Software Foundation, Inc.
 
3
   Contributed by Michael Brutman <brutman@us.ibm.com>.
 
4
   This file is part of the GNU C Library.
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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., 59 Temple Place, Suite 330, Boston, MA
 
19
   02111-1307 USA.  */
 
20
 
 
21
#include <sysdep.h>
 
22
#include <bp-sym.h>
 
23
#include <bp-asm.h>
 
24
 
 
25
#define PREFETCH_AHEAD 4        /* no cache lines SRC prefetching ahead  */
 
26
#define ZERO_AHEAD 2            /* no cache lines DST zeroing ahead  */
 
27
 
 
28
        .machine  a2
 
29
EALIGN (BP_SYM (memcpy), 5, 0)
 
30
        CALL_MCOUNT
 
31
 
 
32
        dcbt    0,r4            /* Prefetch ONE SRC cacheline  */
 
33
        cmplwi  cr1,r5,16       /* is size < 16 ?  */
 
34
        mr      r6,r3           /* Copy dest reg to r6; */
 
35
        blt+    cr1,L(shortcopy)
 
36
 
 
37
 
 
38
        /* Big copy (16 bytes or more)
 
39
 
 
40
           Figure out how far to the nearest quadword boundary, or if we are
 
41
           on one already.
 
42
 
 
43
           r3 - return value (always)
 
44
           r4 - current source addr
 
45
           r5 - copy length
 
46
           r6 - current dest addr
 
47
        */
 
48
 
 
49
        neg     r8,r3           /* LS 4 bits = # bytes to 8-byte dest bdry  */
 
50
        clrlwi  r8,r8,32-4      /* align to 16byte boundary  */
 
51
        sub     r7,r4,r3        /* compute offset to src from dest */
 
52
        cmplwi  cr0,r8,0        /* Were we aligned on a 16 byte bdy? */
 
53
        beq+    L(dst_aligned)
 
54
 
 
55
 
 
56
 
 
57
        /* Destination is not aligned on quadword boundary.  Get us to one.
 
58
 
 
59
           r3 - return value (always)
 
60
           r4 - current source addr
 
61
           r5 - copy length
 
62
           r6 - current dest addr
 
63
           r7 - offset to src from dest
 
64
           r8 - number of bytes to quadword boundary
 
65
        */
 
66
 
 
67
        mtcrf   0x01,r8         /* put #bytes to boundary into cr7  */
 
68
        subf    r5,r8,r5        /* adjust remaining len */
 
69
 
 
70
        bf      cr7*4+3,1f
 
71
        lbzx    r0,r7,r6        /* copy 1 byte addr */
 
72
        stb     r0,0(r6)
 
73
        addi    r6,r6,1
 
74
1:
 
75
        bf      cr7*4+2,2f
 
76
        lhzx    r0,r7,r6        /* copy 2 byte addr */
 
77
        sth     r0,0(r6)
 
78
        addi    r6,r6,2
 
79
2:
 
80
        bf      cr7*4+1,4f
 
81
        lwzx    r0,r7,r6        /* copy 4 byte addr */
 
82
        stw     r0,0(r6)
 
83
        addi    r6,r6,4
 
84
4:
 
85
        bf      cr7*4+0,8f
 
86
        lfdx    r0,r7,r6        /* copy 8 byte addr */
 
87
        stfd    r0,0(r6)
 
88
        addi    r6,r6,8
 
89
8:
 
90
        add     r4,r7,r6        /* update src addr */
 
91
 
 
92
 
 
93
 
 
94
        /* Dest is quadword aligned now.
 
95
 
 
96
           Lots of decisions to make.  If we are copying less than a cache
 
97
           line we won't be here long.  If we are not on a cache line
 
98
           boundary we need to get there.  And then we need to figure out
 
99
           how many cache lines ahead to pre-touch.
 
100
 
 
101
           r3 - return value (always)
 
102
           r4 - current source addr
 
103
           r5 - copy length
 
104
           r6 - current dest addr
 
105
        */
 
106
 
 
107
 
 
108
        .align  4
 
109
L(dst_aligned):
 
110
 
 
111
 
 
112
#ifdef SHARED
 
113
        mflr    r0
 
114
/* Establishes GOT addressability so we can load __cache_line_size
 
115
   from static. This value was set from the aux vector during startup.  */
 
116
        bcl     20,31,1f
 
117
1:
 
118
        mflr    r9
 
119
        addis   r9,r9,__cache_line_size-1b@ha
 
120
        lwz     r9,__cache_line_size-1b@l(r9)
 
121
        mtlr    r0
 
122
#else
 
123
/* Load __cache_line_size from static. This value was set from the
 
124
   aux vector during startup.  */
 
125
        lis     r9,__cache_line_size@ha
 
126
        lwz     r9,__cache_line_size@l(r9)
 
127
#endif
 
128
 
 
129
        cmplwi  cr5, r9, 0
 
130
        bne+    cr5,L(cachelineset)
 
131
        li      r9,64
 
132
 
 
133
 
 
134
 
 
135
L(cachelineset):
 
136
 
 
137
        addi   r10,r9,-1
 
138
 
 
139
        cmpw   cr5,r5,r10       /* Less than a cacheline to go? */
 
140
 
 
141
        neg     r7,r6           /* How far to next cacheline bdy? */
 
142
 
 
143
        addi    r6,r6,-8        /* prepare for stdu  */
 
144
        cmpwi   cr0,r9,128
 
145
        addi    r4,r4,-8        /* prepare for ldu  */
 
146
 
 
147
 
 
148
        ble+    cr5,L(lessthancacheline)
 
149
 
 
150
        beq-    cr0,L(big_lines) /* 128 byte line code */
 
151
 
 
152
 
 
153
 
 
154
 
 
155
        /* More than a cacheline left to go, and using 64 byte cachelines */
 
156
 
 
157
        clrlwi  r7,r7,32-6      /* How far to next cacheline bdy? */
 
158
 
 
159
        cmplwi  cr6,r7,0        /* Are we on a cacheline bdy already? */
 
160
 
 
161
        /* Reduce total len by what it takes to get to the next cache line */
 
162
        subf    r5,r7,r5
 
163
        srwi    r7,r7,4         /* How many qws to get to the line bdy? */
 
164
 
 
165
        /* How many full cache lines to copy after getting to a line bdy? */
 
166
        srwi    r10,r5,6
 
167
 
 
168
        cmplwi  r10,0           /* If no full cache lines to copy ... */
 
169
        li      r11,0           /* number cachelines to copy with prefetch  */
 
170
        beq     L(nocacheprefetch)
 
171
 
 
172
 
 
173
        /* We are here because we have at least one full cache line to copy,
 
174
           and therefore some pre-touching to do. */
 
175
 
 
176
        cmplwi  r10,PREFETCH_AHEAD
 
177
        li      r12,64+8        /* prefetch distance  */
 
178
        ble     L(lessthanmaxprefetch)
 
179
 
 
180
        /* We can only do so much pre-fetching.  R11 will have the count of
 
181
           lines left to prefetch after the initial batch of prefetches
 
182
           are executed. */
 
183
 
 
184
        subi    r11,r10,PREFETCH_AHEAD
 
185
        li      r10,PREFETCH_AHEAD
 
186
 
 
187
L(lessthanmaxprefetch):
 
188
        mtctr   r10
 
189
 
 
190
        /* At this point r10/ctr hold the number of lines to prefetch in this
 
191
           initial batch, and r11 holds any remainder. */
 
192
 
 
193
L(prefetchSRC):
 
194
        dcbt    r12,r4
 
195
        addi    r12,r12,64
 
196
        bdnz    L(prefetchSRC)
 
197
 
 
198
 
 
199
        /* Prefetching is done, or was not needed.
 
200
 
 
201
           cr6 - are we on a cacheline boundary already?
 
202
           r7  - number of quadwords to the next cacheline boundary
 
203
        */
 
204
 
 
205
L(nocacheprefetch):
 
206
        mtctr   r7
 
207
 
 
208
        cmplwi  cr1,r5,64   /* Less than a cache line to copy? */
 
209
 
 
210
        /* How many bytes are left after we copy whatever full
 
211
           cache lines we can get? */
 
212
        clrlwi  r5,r5,32-6
 
213
 
 
214
        beq     cr6,L(cachelinealigned)
 
215
 
 
216
 
 
217
        /* Copy quadwords up to the next cacheline boundary */
 
218
 
 
219
L(aligntocacheline):
 
220
        lfd     fp9,0x08(r4)
 
221
        lfdu    fp10,0x10(r4)
 
222
        stfd    fp9,0x08(r6)
 
223
        stfdu   fp10,0x10(r6)
 
224
        bdnz    L(aligntocacheline)
 
225
 
 
226
 
 
227
        .align 4
 
228
L(cachelinealigned):            /* copy while cache lines  */
 
229
 
 
230
        blt-    cr1,L(lessthancacheline) /* size <64  */
 
231
 
 
232
L(outerloop):
 
233
        cmpwi   r11,0
 
234
        mtctr   r11
 
235
        beq-    L(endloop)
 
236
 
 
237
        li      r11,64*ZERO_AHEAD +8    /* DCBZ dist  */
 
238
 
 
239
        .align  4
 
240
        /* Copy whole cachelines, optimized by prefetching SRC cacheline  */
 
241
L(loop):                        /* Copy aligned body  */
 
242
        dcbt    r12,r4          /* PREFETCH SOURCE some cache lines ahead  */
 
243
        lfd     fp9,  0x08(r4)
 
244
        dcbz    r11,r6
 
245
        lfd     fp10, 0x10(r4)
 
246
        lfd     fp11, 0x18(r4)
 
247
        lfd     fp12, 0x20(r4)
 
248
        stfd    fp9,  0x08(r6)
 
249
        stfd    fp10, 0x10(r6)
 
250
        stfd    fp11, 0x18(r6)
 
251
        stfd    fp12, 0x20(r6)
 
252
        lfd     fp9,  0x28(r4)
 
253
        lfd     fp10, 0x30(r4)
 
254
        lfd     fp11, 0x38(r4)
 
255
        lfdu    fp12, 0x40(r4)
 
256
        stfd    fp9,  0x28(r6)
 
257
        stfd    fp10, 0x30(r6)
 
258
        stfd    fp11, 0x38(r6)
 
259
        stfdu   fp12, 0x40(r6)
 
260
 
 
261
        bdnz    L(loop)
 
262
 
 
263
 
 
264
L(endloop):
 
265
        cmpwi   r10,0
 
266
        beq-    L(endloop2)
 
267
        mtctr   r10
 
268
 
 
269
L(loop2):                       /* Copy aligned body  */
 
270
        lfd     fp9,  0x08(r4)
 
271
        lfd     fp10, 0x10(r4)
 
272
        lfd     fp11, 0x18(r4)
 
273
        lfd     fp12, 0x20(r4)
 
274
        stfd    fp9,  0x08(r6)
 
275
        stfd    fp10, 0x10(r6)
 
276
        stfd    fp11, 0x18(r6)
 
277
        stfd    fp12, 0x20(r6)
 
278
        lfd     fp9,  0x28(r4)
 
279
        lfd     fp10, 0x30(r4)
 
280
        lfd     fp11, 0x38(r4)
 
281
        lfdu    fp12, 0x40(r4)
 
282
        stfd    fp9,  0x28(r6)
 
283
        stfd    fp10, 0x30(r6)
 
284
        stfd    fp11, 0x38(r6)
 
285
        stfdu   fp12, 0x40(r6)
 
286
 
 
287
        bdnz    L(loop2)
 
288
L(endloop2):
 
289
 
 
290
 
 
291
        .align  4
 
292
L(lessthancacheline):           /* Was there less than cache to do ?  */
 
293
        cmplwi  cr0,r5,16
 
294
        srwi    r7,r5,4         /* divide size by 16  */
 
295
        blt-    L(do_lt16)
 
296
        mtctr   r7
 
297
 
 
298
L(copy_remaining):
 
299
        lfd     fp9,  0x08(r4)
 
300
        lfdu    fp10, 0x10(r4)
 
301
        stfd    fp9,  0x08(r6)
 
302
        stfdu   fp10, 0x10(r6)
 
303
        bdnz    L(copy_remaining)
 
304
 
 
305
L(do_lt16):                     /* less than 16 ?  */
 
306
        cmplwi  cr0,r5,0        /* copy remaining bytes (0-15)  */
 
307
        beqlr+                  /* no rest to copy  */
 
308
        addi    r4,r4,8
 
309
        addi    r6,r6,8
 
310
 
 
311
L(shortcopy):                   /* SIMPLE COPY to handle size =< 15 bytes  */
 
312
        mtcrf   0x01,r5
 
313
        sub     r7,r4,r6
 
314
        bf-     cr7*4+0,8f
 
315
        lfdx    fp9,r7,r6       /* copy 8 byte  */
 
316
        stfd    fp9,0(r6)
 
317
        addi    r6,r6,8
 
318
8:
 
319
        bf      cr7*4+1,4f
 
320
        lwzx    r0,r7,r6        /* copy 4 byte  */
 
321
        stw     r0,0(r6)
 
322
        addi    r6,r6,4
 
323
4:
 
324
        bf      cr7*4+2,2f
 
325
        lhzx    r0,r7,r6        /* copy 2 byte  */
 
326
        sth     r0,0(r6)
 
327
        addi    r6,r6,2
 
328
2:
 
329
        bf      cr7*4+3,1f
 
330
        lbzx    r0,r7,r6        /* copy 1 byte  */
 
331
        stb     r0,0(r6)
 
332
1:
 
333
        blr
 
334
 
 
335
 
 
336
 
 
337
 
 
338
 
 
339
        /* Similar to above, but for use with 128 byte lines. */
 
340
 
 
341
 
 
342
L(big_lines):
 
343
 
 
344
        clrlwi  r7,r7,32-7      /* How far to next cacheline bdy? */
 
345
 
 
346
        cmplwi  cr6,r7,0        /* Are we on a cacheline bdy already? */
 
347
 
 
348
        /* Reduce total len by what it takes to get to the next cache line */
 
349
        subf    r5,r7,r5
 
350
        srwi    r7,r7,4         /* How many qw to get to the line bdy? */
 
351
 
 
352
        /* How many full cache lines to copy after getting to a line bdy? */
 
353
        srwi    r10,r5,7
 
354
 
 
355
        cmplwi  r10,0           /* If no full cache lines to copy ... */
 
356
        li      r11,0           /* number cachelines to copy with prefetch  */
 
357
        beq     L(nocacheprefetch_128)
 
358
 
 
359
 
 
360
        /* We are here because we have at least one full cache line to copy,
 
361
           and therefore some pre-touching to do. */
 
362
 
 
363
        cmplwi  r10,PREFETCH_AHEAD
 
364
        li      r12,128+8       /* prefetch distance  */
 
365
        ble     L(lessthanmaxprefetch_128)
 
366
 
 
367
        /* We can only do so much pre-fetching.  R11 will have the count of
 
368
           lines left to prefetch after the initial batch of prefetches
 
369
           are executed. */
 
370
 
 
371
        subi    r11,r10,PREFETCH_AHEAD
 
372
        li      r10,PREFETCH_AHEAD
 
373
 
 
374
L(lessthanmaxprefetch_128):
 
375
        mtctr   r10
 
376
 
 
377
        /* At this point r10/ctr hold the number of lines to prefetch in this
 
378
           initial batch, and r11 holds any remainder. */
 
379
 
 
380
L(prefetchSRC_128):
 
381
        dcbt    r12,r4
 
382
        addi    r12,r12,128
 
383
        bdnz    L(prefetchSRC_128)
 
384
 
 
385
 
 
386
        /* Prefetching is done, or was not needed.
 
387
 
 
388
           cr6 - are we on a cacheline boundary already?
 
389
           r7  - number of quadwords to the next cacheline boundary
 
390
        */
 
391
 
 
392
L(nocacheprefetch_128):
 
393
        mtctr   r7
 
394
 
 
395
        cmplwi  cr1,r5,128  /* Less than a cache line to copy? */
 
396
 
 
397
        /* How many bytes are left after we copy whatever full
 
398
           cache lines we can get? */
 
399
        clrlwi  r5,r5,32-7
 
400
 
 
401
        beq     cr6,L(cachelinealigned_128)
 
402
 
 
403
 
 
404
        /* Copy quadwords up to the next cacheline boundary */
 
405
 
 
406
L(aligntocacheline_128):
 
407
        lfd     fp9,0x08(r4)
 
408
        lfdu    fp10,0x10(r4)
 
409
        stfd    fp9,0x08(r6)
 
410
        stfdu   fp10,0x10(r6)
 
411
        bdnz    L(aligntocacheline_128)
 
412
 
 
413
 
 
414
L(cachelinealigned_128):        /* copy while cache lines  */
 
415
 
 
416
        blt-    cr1,L(lessthancacheline) /* size <128  */
 
417
 
 
418
L(outerloop_128):
 
419
        cmpwi   r11,0
 
420
        mtctr   r11
 
421
        beq-    L(endloop_128)
 
422
 
 
423
        li      r11,128*ZERO_AHEAD +8    /* DCBZ dist  */
 
424
 
 
425
        .align  4
 
426
        /* Copy whole cachelines, optimized by prefetching SRC cacheline  */
 
427
L(loop_128):                    /* Copy aligned body  */
 
428
        dcbt    r12,r4          /* PREFETCH SOURCE some cache lines ahead  */
 
429
        lfd     fp9,  0x08(r4)
 
430
        dcbz    r11,r6
 
431
        lfd     fp10, 0x10(r4)
 
432
        lfd     fp11, 0x18(r4)
 
433
        lfd     fp12, 0x20(r4)
 
434
        stfd    fp9,  0x08(r6)
 
435
        stfd    fp10, 0x10(r6)
 
436
        stfd    fp11, 0x18(r6)
 
437
        stfd    fp12, 0x20(r6)
 
438
        lfd     fp9,  0x28(r4)
 
439
        lfd     fp10, 0x30(r4)
 
440
        lfd     fp11, 0x38(r4)
 
441
        lfd     fp12, 0x40(r4)
 
442
        stfd    fp9,  0x28(r6)
 
443
        stfd    fp10, 0x30(r6)
 
444
        stfd    fp11, 0x38(r6)
 
445
        stfd    fp12, 0x40(r6)
 
446
        lfd     fp9,  0x48(r4)
 
447
        lfd     fp10, 0x50(r4)
 
448
        lfd     fp11, 0x58(r4)
 
449
        lfd     fp12, 0x60(r4)
 
450
        stfd    fp9,  0x48(r6)
 
451
        stfd    fp10, 0x50(r6)
 
452
        stfd    fp11, 0x58(r6)
 
453
        stfd    fp12, 0x60(r6)
 
454
        lfd     fp9,  0x68(r4)
 
455
        lfd     fp10, 0x70(r4)
 
456
        lfd     fp11, 0x78(r4)
 
457
        lfdu    fp12, 0x80(r4)
 
458
        stfd    fp9,  0x68(r6)
 
459
        stfd    fp10, 0x70(r6)
 
460
        stfd    fp11, 0x78(r6)
 
461
        stfdu   fp12, 0x80(r6)
 
462
 
 
463
        bdnz    L(loop_128)
 
464
 
 
465
 
 
466
L(endloop_128):
 
467
        cmpwi   r10,0
 
468
        beq-    L(endloop2_128)
 
469
        mtctr   r10
 
470
 
 
471
L(loop2_128):                   /* Copy aligned body  */
 
472
        lfd     fp9,  0x08(r4)
 
473
        lfd     fp10, 0x10(r4)
 
474
        lfd     fp11, 0x18(r4)
 
475
        lfd     fp12, 0x20(r4)
 
476
        stfd    fp9,  0x08(r6)
 
477
        stfd    fp10, 0x10(r6)
 
478
        stfd    fp11, 0x18(r6)
 
479
        stfd    fp12, 0x20(r6)
 
480
        lfd     fp9,  0x28(r4)
 
481
        lfd     fp10, 0x30(r4)
 
482
        lfd     fp11, 0x38(r4)
 
483
        lfd     fp12, 0x40(r4)
 
484
        stfd    fp9,  0x28(r6)
 
485
        stfd    fp10, 0x30(r6)
 
486
        stfd    fp11, 0x38(r6)
 
487
        stfd    fp12, 0x40(r6)
 
488
        lfd     fp9,  0x48(r4)
 
489
        lfd     fp10, 0x50(r4)
 
490
        lfd     fp11, 0x58(r4)
 
491
        lfd     fp12, 0x60(r4)
 
492
        stfd    fp9,  0x48(r6)
 
493
        stfd    fp10, 0x50(r6)
 
494
        stfd    fp11, 0x58(r6)
 
495
        stfd    fp12, 0x60(r6)
 
496
        lfd     fp9,  0x68(r4)
 
497
        lfd     fp10, 0x70(r4)
 
498
        lfd     fp11, 0x78(r4)
 
499
        lfdu    fp12, 0x80(r4)
 
500
        stfd    fp9,  0x68(r6)
 
501
        stfd    fp10, 0x70(r6)
 
502
        stfd    fp11, 0x78(r6)
 
503
        stfdu   fp12, 0x80(r6)
 
504
        bdnz    L(loop2_128)
 
505
L(endloop2_128):
 
506
 
 
507
        b       L(lessthancacheline)
 
508
 
 
509
 
 
510
END (BP_SYM (memcpy))
 
511
libc_hidden_builtin_def (memcpy)