b4545ac9f704deb1b11e44be8ffa4bce03c9aab3
[glibc.git] / sysdeps / x86_64 / memcpy.S
blobb4545ac9f704deb1b11e44be8ffa4bce03c9aab3
1 /*
2    Optimized memcpy for x86-64.
4    Copyright (C) 2007 Free Software Foundation, Inc.
5    Contributed by Evandro Menezes <evandro.menezes@amd.com>, 2007.
7    This file is part of the GNU C Library.
9    The GNU C Library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 2.1 of the License, or (at your option) any later version.
14    The GNU C Library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Lesser General Public License for more details.
19    You should have received a copy of the GNU Lesser General Public
20    License along with the GNU C Library; if not, write to the Free
21    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22    02111-1307 USA.
25 #include <sysdep.h>
26 #include "asm-syntax.h"
28 /* Stack slots in the red-zone. */
30 #ifdef USE_AS_MEMPCPY
31 #  define RETVAL        (0)
32 #else
33 #  define RETVAL        (-8)
34 #endif
35 #define SAVE0   (RETVAL - 8)
36 #define SAVE1   (SAVE0  - 8)
37 #define SAVE2   (SAVE1  - 8)
38 #define SAVE3   (SAVE2  - 8)
40         .text
42 #if defined PIC && !defined NOT_IN_libc
43 ENTRY_CHK (__memcpy_chk)
45         cmpq    %rdx, %rcx
46         jb      HIDDEN_JUMPTARGET (__chk_fail)
48 END_CHK (__memcpy_chk)
49 #endif
51 ENTRY(memcpy)                           /* (void *, const void*, size_t) */
53 /* Handle tiny blocks. */
55 L(1try):                                /* up to 32B */
56         cmpq    $32, %rdx
57 #ifndef USE_AS_MEMPCPY
58         movq    %rdi, %rax              /* save return value */
59 #endif
60         jae     L(1after)
62 L(1):                                   /* 1-byte once */
63         testb   $1, %dl
64         jz      L(1a)
66         movzbl  (%rsi), %ecx
67         movb    %cl, (%rdi)
69         incq    %rsi
70         incq    %rdi
72         .p2align 4,, 4
74 L(1a):                                  /* 2-byte once */
75         testb   $2, %dl
76         jz      L(1b)
78         movzwl  (%rsi), %ecx
79         movw    %cx, (%rdi)
81         addq    $2, %rsi
82         addq    $2, %rdi
84         .p2align 4,, 4
86 L(1b):                                  /* 4-byte once */
87         testb   $4, %dl
88         jz      L(1c)
90         movl    (%rsi), %ecx
91         movl    %ecx, (%rdi)
93         addq    $4, %rsi
94         addq    $4, %rdi
96         .p2align 4,, 4
98 L(1c):                                  /* 8-byte once */
99         testb   $8, %dl
100         jz      L(1d)
102         movq    (%rsi), %rcx
103         movq    %rcx, (%rdi)
105         addq    $8, %rsi
106         addq    $8, %rdi
108         .p2align 4,, 4
110 L(1d):                                  /* 16-byte loop */
111         andl    $0xf0, %edx
112         jz      L(exit)
114         .p2align 4
116 L(1loop):
117         movq     (%rsi), %rcx
118         movq    8(%rsi), %r8
119         movq    %rcx,  (%rdi)
120         movq     %r8, 8(%rdi)
122         subl    $16, %edx
124         leaq    16(%rsi), %rsi
125         leaq    16(%rdi), %rdi
127         jnz     L(1loop)
129         .p2align 4,, 4
131 L(exit):                                /* exit */
132 #ifdef USE_AS_MEMPCPY
133         movq    %rdi, %rax              /* return value */
134 #else
135         rep
136 #endif
137         retq
139         .p2align 4
141 L(1after):
142 #ifndef USE_AS_MEMPCPY
143         movq    %rax, RETVAL(%rsp)      /* save return value */
144 #endif
146 /* Align to the natural word size. */
148 L(aligntry):
149         movl    %esi, %ecx              /* align by source */
151         andl    $7, %ecx
152         jz      L(alignafter)           /* already aligned */
154 L(align):                               /* align */
155         leaq    -8(%rcx, %rdx), %rdx    /* calculate remaining bytes */
156         subl    $8, %ecx
158         .p2align 4
160 L(alignloop):                           /* 1-byte alignment loop */
161         movzbl  (%rsi), %eax
162         movb    %al, (%rdi)
164         incl    %ecx
166         leaq    1(%rsi), %rsi
167         leaq    1(%rdi), %rdi
169         jnz     L(alignloop)
171         .p2align 4
173 L(alignafter):
175 /* Handle mid-sized blocks. */
177 L(32try):                               /* up to 1KB */
178         cmpq    $1024, %rdx
179         ja      L(32after)
181 L(32):                                  /* 32-byte loop */
182         movl    %edx, %ecx
183         shrl    $5, %ecx
184         jz      L(32skip)
186         .p2align 4
188 L(32loop):
189         decl    %ecx
191         movq      (%rsi), %rax
192         movq     8(%rsi), %r8
193         movq    16(%rsi), %r9
194         movq    24(%rsi), %r10
196         movq    %rax,   (%rdi)
197         movq     %r8,  8(%rdi)
198         movq     %r9, 16(%rdi)
199         movq    %r10, 24(%rdi)
201         leaq    32(%rsi), %rsi
202         leaq    32(%rdi), %rdi
204         jz      L(32skip)               /* help out smaller blocks */
206         decl    %ecx
208         movq      (%rsi), %rax
209         movq     8(%rsi), %r8
210         movq    16(%rsi), %r9
211         movq    24(%rsi), %r10
213         movq    %rax,   (%rdi)
214         movq     %r8,  8(%rdi)
215         movq     %r9, 16(%rdi)
216         movq    %r10, 24(%rdi)
218         leaq    32(%rsi), %rsi
219         leaq    32(%rdi), %rdi
221         jnz     L(32loop)
223         .p2align 4
225 L(32skip):
226         andl    $31, %edx               /* check for left overs */
227 #ifdef USE_AS_MEMPCPY
228         jnz     L(1)
230         movq    %rdi, %rax
231 #else
232         movq    RETVAL(%rsp), %rax
233         jnz     L(1)
235         rep
236 #endif
237         retq                            /* exit */
239         .p2align 4
241 L(32after):
244         In order to minimize code-size in RTLD, algorithms specific for
245         larger blocks are excluded when building for RTLD.
248 /* Handle blocks smaller than 1/2 L1. */
250 L(fasttry):                             /* first 1/2 L1 */
251 #ifndef NOT_IN_libc                     /* only up to this algorithm outside of libc.so */
252         movq    __x86_64_data_cache_size_half(%rip), %r11
253         cmpq    %rdx, %r11              /* calculate the smaller of */
254         cmovaq  %rdx, %r11              /* remaining bytes and 1/2 L1 */
255 #endif
257 L(fast):                                /* good ol' MOVS */
258 #ifndef NOT_IN_libc
259         movq    %r11, %rcx
260         andq    $-8, %r11
261 #else
262         movq    %rdx, %rcx
263 #endif
264         shrq    $3, %rcx
265         jz      L(fastskip)
267         rep
268         movsq
270         .p2align 4,, 4
272 L(fastskip):
273 #ifndef NOT_IN_libc
274         subq    %r11, %rdx              /* check for more */
275         testq   $-8, %rdx
276         jnz     L(fastafter)
277 #endif
279         andl    $7, %edx                /* check for left overs */
280 #ifdef USE_AS_MEMPCPY
281         jnz     L(1)
283         movq    %rdi, %rax
284 #else
285         movq    RETVAL(%rsp), %rax
286         jnz     L(1)
288         rep
289 #endif
290         retq                            /* exit */
292 #ifndef NOT_IN_libc                     /* none of the algorithms below for RTLD */
294         .p2align 4
296 L(fastafter):
298 /* Handle large blocks smaller than 1/2 L2. */
300 L(pretry):                              /* first 1/2 L2 */
301         movq    __x86_64_shared_cache_size_half (%rip), %r8
302         cmpq    %rdx, %r8               /* calculate the lesser of */
303         cmovaq  %rdx, %r8               /* remaining bytes and 1/2 L2 */
305 L(pre):                                 /* 64-byte with prefetching */
306         movq    %r8, %rcx
307         andq    $-64, %r8
308         shrq    $6, %rcx
309         jz      L(preskip)
311         movq    %r14, SAVE0(%rsp)
312         cfi_rel_offset (%r14, SAVE0)
313         movq    %r13, SAVE1(%rsp)
314         cfi_rel_offset (%r13, SAVE1)
315         movq    %r12, SAVE2(%rsp)
316         cfi_rel_offset (%r12, SAVE2)
317         movq    %rbx, SAVE3(%rsp)
318         cfi_rel_offset (%rbx, SAVE3)
320         cmpl    $0, __x86_64_prefetchw(%rip)
321         jz      L(preloop)              /* check if PREFETCHW OK */
323         .p2align 4
325 /* ... when PREFETCHW is available (less cache-probe traffic in MP systems). */
327 L(prewloop):                            /* cache-line in state M */
328         decq    %rcx
330         movq       (%rsi), %rax
331         movq     8 (%rsi), %rbx
332         movq    16 (%rsi), %r9
333         movq    24 (%rsi), %r10
334         movq    32 (%rsi), %r11
335         movq    40 (%rsi), %r12
336         movq    48 (%rsi), %r13
337         movq    56 (%rsi), %r14
339         prefetcht0       0 + 896 (%rsi)
340         prefetcht0      64 + 896 (%rsi)
342         movq    %rax,   (%rdi)
343         movq    %rbx,  8(%rdi)
344         movq     %r9, 16(%rdi)
345         movq    %r10, 24(%rdi)
346         movq    %r11, 32(%rdi)
347         movq    %r12, 40(%rdi)
348         movq    %r13, 48(%rdi)
349         movq    %r14, 56(%rdi)
351         leaq    64(%rsi), %rsi
352         leaq    64(%rdi), %rdi
354         jz      L(prebail)
356         decq    %rcx
358         movq      (%rsi), %rax
359         movq     8(%rsi), %rbx
360         movq    16(%rsi), %r9
361         movq    24(%rsi), %r10
362         movq    32(%rsi), %r11
363         movq    40(%rsi), %r12
364         movq    48(%rsi), %r13
365         movq    56(%rsi), %r14
367         movq    %rax,   (%rdi)
368         movq    %rbx,  8(%rdi)
369         movq     %r9, 16(%rdi)
370         movq    %r10, 24(%rdi)
371         movq    %r11, 32(%rdi)
372         movq    %r12, 40(%rdi)
373         movq    %r13, 48(%rdi)
374         movq    %r14, 56(%rdi)
376         prefetchw       896 - 64(%rdi)
377         prefetchw       896 -  0(%rdi)
379         leaq    64(%rsi), %rsi
380         leaq    64(%rdi), %rdi
382         jnz     L(prewloop)
383         jmp     L(prebail)
385         .p2align 4
387 /* ... when PREFETCHW is not available. */
389 L(preloop):                             /* cache-line in state E */
390         decq    %rcx
392         movq      (%rsi), %rax
393         movq     8(%rsi), %rbx
394         movq    16(%rsi), %r9
395         movq    24(%rsi), %r10
396         movq    32(%rsi), %r11
397         movq    40(%rsi), %r12
398         movq    48(%rsi), %r13
399         movq    56(%rsi), %r14
401         prefetcht0      896 +  0(%rsi)
402         prefetcht0      896 + 64(%rsi)
404         movq    %rax,   (%rdi)
405         movq    %rbx,  8(%rdi)
406         movq     %r9, 16(%rdi)
407         movq    %r10, 24(%rdi)
408         movq    %r11, 32(%rdi)
409         movq    %r12, 40(%rdi)
410         movq    %r13, 48(%rdi)
411         movq    %r14, 56(%rdi)
413         leaq    64 (%rsi), %rsi
414         leaq    64 (%rdi), %rdi
416         jz      L(prebail)
418         decq    %rcx
420         movq      (%rsi), %rax
421         movq     8(%rsi), %rbx
422         movq    16(%rsi), %r9
423         movq    24(%rsi), %r10
424         movq    32(%rsi), %r11
425         movq    40(%rsi), %r12
426         movq    48(%rsi), %r13
427         movq    56(%rsi), %r14
429         prefetcht0      896 - 64(%rdi)
430         prefetcht0      896 -  0(%rdi)
432         movq    %rax,   (%rdi)
433         movq    %rbx,  8(%rdi)
434         movq     %r9, 16(%rdi)
435         movq    %r10, 24(%rdi)
436         movq    %r11, 32(%rdi)
437         movq    %r12, 40(%rdi)
438         movq    %r13, 48(%rdi)
439         movq    %r14, 56(%rdi)
441         leaq    64(%rsi), %rsi
442         leaq    64(%rdi), %rdi
444         jnz     L(preloop)
446 L(prebail):
447         movq    SAVE3(%rsp), %rbx
448         cfi_restore (%rbx)
449         movq    SAVE2(%rsp), %r12
450         cfi_restore (%r12)
451         movq    SAVE1(%rsp), %r13
452         cfi_restore (%r13)
453         movq    SAVE0(%rsp), %r14
454         cfi_restore (%r14)
456 /*       .p2align 4 */
458 L(preskip):
459         subq    %r8, %rdx               /* check for more */
460         testq   $-64, %rdx
461         jnz     L(preafter)
463         andl    $63, %edx               /* check for left overs */
464 #ifdef USE_AS_MEMPCPY
465         jnz     L(1)
467         movq    %rdi, %rax
468 #else
469         movq    RETVAL(%rsp), %rax
470         jnz     L(1)
472         rep
473 #endif
474         retq                            /* exit */
476         .p2align 4
478 L(preafter):
480 /* Handle huge blocks. */
482 L(NTtry):
484 L(NT):                                  /* non-temporal 128-byte */
485         movq    %rdx, %rcx
486         shrq    $7, %rcx
487         jz      L(NTskip)
489         movq    %r14, SAVE0(%rsp)
490         cfi_rel_offset (%r14, SAVE0)
491         movq    %r13, SAVE1(%rsp)
492         cfi_rel_offset (%r13, SAVE1)
493         movq    %r12, SAVE2(%rsp)
494         cfi_rel_offset (%r12, SAVE2)
496        .p2align 4
498 L(NTloop):
499         prefetchnta     768(%rsi)
500         prefetchnta     832(%rsi)
502         decq    %rcx
504         movq      (%rsi), %rax
505         movq     8(%rsi), %r8
506         movq    16(%rsi), %r9
507         movq    24(%rsi), %r10
508         movq    32(%rsi), %r11
509         movq    40(%rsi), %r12
510         movq    48(%rsi), %r13
511         movq    56(%rsi), %r14
513         movntiq %rax,   (%rdi)
514         movntiq  %r8,  8(%rdi)
515         movntiq  %r9, 16(%rdi)
516         movntiq %r10, 24(%rdi)
517         movntiq %r11, 32(%rdi)
518         movntiq %r12, 40(%rdi)
519         movntiq %r13, 48(%rdi)
520         movntiq %r14, 56(%rdi)
522         movq     64(%rsi), %rax
523         movq     72(%rsi), %r8
524         movq     80(%rsi), %r9
525         movq     88(%rsi), %r10
526         movq     96(%rsi), %r11
527         movq    104(%rsi), %r12
528         movq    112(%rsi), %r13
529         movq    120(%rsi), %r14
531         movntiq %rax,  64(%rdi)
532         movntiq  %r8,  72(%rdi)
533         movntiq  %r9,  80(%rdi)
534         movntiq %r10,  88(%rdi)
535         movntiq %r11,  96(%rdi)
536         movntiq %r12, 104(%rdi)
537         movntiq %r13, 112(%rdi)
538         movntiq %r14, 120(%rdi)
540         leaq    128(%rsi), %rsi
541         leaq    128(%rdi), %rdi
543         jnz     L(NTloop)
545         sfence                          /* serialize memory stores */
547         movq    SAVE2(%rsp), %r12
548         cfi_restore (%r12)
549         movq    SAVE1(%rsp), %r13
550         cfi_restore (%r13)
551         movq    SAVE0(%rsp), %r14
552         cfi_restore (%r14)
554 L(NTskip):
555         andl    $127, %edx              /* check for left overs */
556 #ifdef USE_AS_MEMPCPY
557         jnz     L(1)
559         movq    %rdi, %rax
560 #else
561         movq    RETVAL(%rsp), %rax
562         jnz     L(1)
564         rep
565 #endif
566         retq                            /* exit */
568 #endif /* !NOT_IN_libc */
570 END(memcpy)
572 #ifndef USE_AS_MEMPCPY
573 libc_hidden_builtin_def (memcpy)
574 #endif