Bug fix
[kopensolaris-gnu/glibc.git] / sysdeps / x86_64 / memset.S
1 /* memset/bzero -- set memory area to CH/0
2    Optimized version for x86-64.
3    Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Andreas Jaeger <aj@suse.de>.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #include <sysdep.h>
23 #include "asm-syntax.h"
24 #include "bp-sym.h"
25 #include "bp-asm.h"
26
27 /* This is somehow experimental and could made dependend on the cache
28    size.  */
29 #define LARGE $120000
30
31         .text
32 #ifndef NOT_IN_libc
33 ENTRY(__bzero)
34         mov     %rsi,%rdx       /* Adjust parameter.  */
35         xorl    %esi,%esi       /* Fill with 0s.  */
36         jmp     L(memset_entry)
37 END(__bzero)
38 weak_alias (__bzero, bzero)
39 #endif
40
41 #if defined PIC && !defined NOT_IN_libc
42 ENTRY (__memset_chk)
43         cmpq    %rdx, %rcx
44         jb      HIDDEN_JUMPTARGET (__chk_fail)
45 END (__memset_chk)
46 #endif
47 ENTRY (memset)
48 L(memset_entry):
49         cmp     $0x7,%rdx       /* Check for small length.  */
50         mov     %rdi,%rcx       /* Save ptr as return value.  */
51         jbe     7f
52
53         /* Populate 8 bit data to full 64-bit.  */
54         movabs  $0x0101010101010101,%r8
55         movzbl  %sil,%eax
56         imul    %rax,%r8
57         test    $0x7,%edi       /* Check for alignment.  */
58         je      2f
59
60         .p2align 4
61 1:      /* Align ptr to 8 byte.  */
62         mov     %sil,(%rcx)
63         dec     %rdx
64         inc     %rcx
65         test    $0x7,%ecx
66         jne     1b
67
68 2:      /* Check for really large regions.  */
69         mov     %rdx,%rax
70         shr     $0x6,%rax
71         je      4f
72         cmp     LARGE, %rdx
73         jae     11f
74
75         .p2align 4
76 3:      /* Copy 64 bytes.  */
77         mov     %r8,(%rcx)
78         mov     %r8,0x8(%rcx)
79         mov     %r8,0x10(%rcx)
80         mov     %r8,0x18(%rcx)
81         mov     %r8,0x20(%rcx)
82         mov     %r8,0x28(%rcx)
83         mov     %r8,0x30(%rcx)
84         mov     %r8,0x38(%rcx)
85         add     $0x40,%rcx
86         dec     %rax
87         jne     3b
88
89 4:      /* Copy final bytes.  */
90         and     $0x3f,%edx
91         mov     %rdx,%rax
92         shr     $0x3,%rax
93         je      6f
94
95 5:      /* First in chunks of 8 bytes.  */
96         mov     %r8,(%rcx)
97         add     $0x8,%rcx
98         dec     %rax
99         jne     5b
100 6:
101         and     $0x7,%edx
102 7:
103         test    %rdx,%rdx
104         je      9f
105 8:      /* And finally as bytes (up to 7).  */
106         mov     %sil,(%rcx)
107         inc     %rcx
108         dec     %rdx
109         jne     8b
110 9:
111         /* Load result (only if used as memset).  */
112         mov     %rdi,%rax       /* start address of destination is result */
113         retq
114
115         .p2align 4
116 11:     /* Copy 64 bytes without polluting the cache.  */
117         /* We could use movntdq    %xmm0,(%rcx) here to further
118            speed up for large cases but let's not use XMM registers.  */
119         movnti  %r8,(%rcx)
120         movnti  %r8,0x8(%rcx)
121         movnti  %r8,0x10(%rcx)
122         movnti  %r8,0x18(%rcx)
123         movnti  %r8,0x20(%rcx)
124         movnti  %r8,0x28(%rcx)
125         movnti  %r8,0x30(%rcx)
126         movnti  %r8,0x38(%rcx)
127         add     $0x40,%rcx
128         dec     %rax
129         jne     11b
130         jmp     4b
131
132 END (memset)
133 libc_hidden_builtin_def (memset)
134
135 #if defined PIC && !defined NOT_IN_libc
136 strong_alias (__memset_chk, __memset_zero_constant_len_parameter)
137         .section .gnu.warning.__memset_zero_constant_len_parameter
138         .string "memset used with constant zero length parameter; this could be due to transposed parameters"
139 #endif