2006-02-24 Roland McGrath <roland@redhat.com>
[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 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 /* BEWARE: `#ifdef memset' means that memset is redefined as `bzero' */
28 #define BZERO_P (defined memset)
29
30 /* This is somehow experimental and could made dependend on the cache
31    size.  */
32 #define LARGE $120000
33
34         .text
35 #if !BZERO_P && defined PIC && !defined NOT_IN_libc
36 ENTRY (__memset_chk)
37         cmpq    %rdx, %rcx
38         jb      HIDDEN_JUMPTARGET (__chk_fail)
39 END (__memset_chk)
40 #endif
41 ENTRY (memset)
42 #if BZERO_P
43         mov     %rsi,%rdx       /* Adjust parameter.  */
44         xorl    %esi,%esi       /* Fill with 0s.  */
45 #endif
46         cmp     $0x7,%rdx       /* Check for small length.  */
47         mov     %rdi,%rcx       /* Save ptr as return value.  */
48         jbe     7f
49
50 #if BZERO_P
51         mov     %rsi,%r8        /* Just copy 0.  */
52 #else
53         /* Populate 8 bit data to full 64-bit.  */
54         movabs  $0x0101010101010101,%r8
55         movzbl  %sil,%eax
56         imul    %rax,%r8
57 #endif
58         test    $0x7,%edi       /* Check for alignment.  */
59         je      2f
60
61         .p2align 4
62 1:      /* Align ptr to 8 byte.  */
63         mov     %sil,(%rcx)
64         dec     %rdx
65         inc     %rcx
66         test    $0x7,%ecx
67         jne     1b
68
69 2:      /* Check for really large regions.  */
70         mov     %rdx,%rax
71         shr     $0x6,%rax
72         je      4f
73         cmp     LARGE, %rdx
74         jae     11f
75
76         .p2align 4
77 3:      /* Copy 64 bytes.  */
78         mov     %r8,(%rcx)
79         mov     %r8,0x8(%rcx)
80         mov     %r8,0x10(%rcx)
81         mov     %r8,0x18(%rcx)
82         mov     %r8,0x20(%rcx)
83         mov     %r8,0x28(%rcx)
84         mov     %r8,0x30(%rcx)
85         mov     %r8,0x38(%rcx)
86         add     $0x40,%rcx
87         dec     %rax
88         jne     3b
89
90 4:      /* Copy final bytes.  */
91         and     $0x3f,%edx
92         mov     %rdx,%rax
93         shr     $0x3,%rax
94         je      6f
95
96 5:      /* First in chunks of 8 bytes.  */
97         mov     %r8,(%rcx)
98         add     $0x8,%rcx
99         dec     %rax
100         jne     5b
101 6:
102         and     $0x7,%edx
103 7:
104         test    %rdx,%rdx
105         je      9f
106 8:      /* And finally as bytes (up to 7).  */
107         mov     %sil,(%rcx)
108         inc     %rcx
109         dec     %rdx
110         jne     8b
111 9:
112 #if BZERO_P
113         nop
114 #else
115         /* Load result (only if used as memset).  */
116         mov     %rdi,%rax       /* start address of destination is result */
117 #endif
118         retq
119
120         .p2align 4
121 11:     /* Copy 64 bytes without polluting the cache.  */
122         /* We could use movntdq    %xmm0,(%rcx) here to further
123            speed up for large cases but let's not use XMM registers.  */
124         movnti  %r8,(%rcx)
125         movnti  %r8,0x8(%rcx)
126         movnti  %r8,0x10(%rcx)
127         movnti  %r8,0x18(%rcx)
128         movnti  %r8,0x20(%rcx)
129         movnti  %r8,0x28(%rcx)
130         movnti  %r8,0x30(%rcx)
131         movnti  %r8,0x38(%rcx)
132         add     $0x40,%rcx
133         dec     %rax
134         jne     11b
135         jmp     4b
136
137 END (memset)
138 #if !BZERO_P
139 libc_hidden_builtin_def (memset)
140 #endif
141
142 #if !BZERO_P && defined PIC && !defined NOT_IN_libc
143 strong_alias (__memset_chk, __memset_zero_constant_len_parameter)
144         .section .gnu.warning.__memset_zero_constant_len_parameter
145         .string "memset used with constant zero length parameter; this could be due to transposed parameters"
146 #endif