Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
blobf3e0ca1259f28aaba2ab6e46fd310d3a9413d38d
1 /* Multiple versions of strcmp
2    Copyright (C) 2009-2014 Free Software Foundation, Inc.
3    Contributed by Intel Corporation.
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    <http://www.gnu.org/licenses/>.  */
20 #include <sysdep.h>
21 #include <init-arch.h>
23 #ifdef USE_AS_STRNCMP
24 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
25    if the new counter > the old one or is 0.  */
26 # define UPDATE_STRNCMP_COUNTER                         \
27         /* calculate left number to compare */          \
28         lea     -16(%rcx, %r11), %r9;                   \
29         cmp     %r9, %r11;                              \
30         jb      LABEL(strcmp_exitz);                    \
31         test    %r9, %r9;                               \
32         je      LABEL(strcmp_exitz);                    \
33         mov     %r9, %r11
35 # define STRCMP_SSE42   __strncmp_sse42
36 # define STRCMP_SSSE3   __strncmp_ssse3
37 # define STRCMP_SSE2    __strncmp_sse2
38 # define __GI_STRCMP    __GI_strncmp
39 #elif defined USE_AS_STRCASECMP_L
40 # include "locale-defines.h"
42 # define UPDATE_STRNCMP_COUNTER
44 # define STRCMP_AVX     __strcasecmp_l_avx
45 # define STRCMP_SSE42   __strcasecmp_l_sse42
46 # define STRCMP_SSSE3   __strcasecmp_l_ssse3
47 # define STRCMP_SSE2    __strcasecmp_l_sse2
48 # define __GI_STRCMP    __GI___strcasecmp_l
49 #elif defined USE_AS_STRNCASECMP_L
50 # include "locale-defines.h"
52 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
53    if the new counter > the old one or is 0.  */
54 # define UPDATE_STRNCMP_COUNTER                         \
55         /* calculate left number to compare */          \
56         lea     -16(%rcx, %r11), %r9;                   \
57         cmp     %r9, %r11;                              \
58         jb      LABEL(strcmp_exitz);                    \
59         test    %r9, %r9;                               \
60         je      LABEL(strcmp_exitz);                    \
61         mov     %r9, %r11
63 # define STRCMP_AVX     __strncasecmp_l_avx
64 # define STRCMP_SSE42   __strncasecmp_l_sse42
65 # define STRCMP_SSSE3   __strncasecmp_l_ssse3
66 # define STRCMP_SSE2    __strncasecmp_l_sse2
67 # define __GI_STRCMP    __GI___strncasecmp_l
68 #else
69 # define USE_AS_STRCMP
70 # define UPDATE_STRNCMP_COUNTER
71 # ifndef STRCMP
72 #  define STRCMP        strcmp
73 #  define STRCMP_SSE42  __strcmp_sse42
74 #  define STRCMP_SSSE3  __strcmp_ssse3
75 #  define STRCMP_SSE2   __strcmp_sse2
76 #  define __GI_STRCMP   __GI_strcmp
77 # endif
78 #endif
80 /* Define multiple versions only for the definition in libc.  Don't
81    define multiple versions for strncmp in static library since we
82    need strncmp before the initialization happened.  */
83 #if (defined SHARED || !defined USE_AS_STRNCMP) && !defined NOT_IN_libc
84         .text
85 ENTRY(STRCMP)
86         .type   STRCMP, @gnu_indirect_function
87         /* Manually inlined call to __get_cpu_features.  */
88         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
89         jne     1f
90         call    __init_cpu_features
92 #ifdef USE_AS_STRCMP
93         leaq    __strcmp_sse2_unaligned(%rip), %rax
94         testl   $bit_Fast_Unaligned_Load, __cpu_features+CPUID_OFFSET+index_Fast_Unaligned_Load(%rip)
95         jnz     3f
96 #else
97         testl   $bit_Slow_SSE4_2, __cpu_features+CPUID_OFFSET+index_Slow_SSE4_2(%rip)
98         jnz     2f
99         leaq    STRCMP_SSE42(%rip), %rax
100         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
101         jnz     3f
102 #endif
103 2:      leaq    STRCMP_SSSE3(%rip), %rax
104         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
105         jnz     3f
106         leaq    STRCMP_SSE2(%rip), %rax
107 3:      ret
108 END(STRCMP)
110 # ifdef USE_AS_STRCASECMP_L
111 ENTRY(__strcasecmp)
112         .type   __strcasecmp, @gnu_indirect_function
113         /* Manually inlined call to __get_cpu_features.  */
114         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
115         jne     1f
116         call    __init_cpu_features
118 #  ifdef HAVE_AVX_SUPPORT
119         leaq    __strcasecmp_avx(%rip), %rax
120         testl   $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
121         jnz     3f
122 #  endif
123         testl   $bit_Slow_SSE4_2, __cpu_features+CPUID_OFFSET+index_Slow_SSE4_2(%rip)
124         jnz     2f
125         leaq    __strcasecmp_sse42(%rip), %rax
126         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
127         jnz     3f
128 2:      leaq    __strcasecmp_ssse3(%rip), %rax
129         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
130         jnz     3f
131         leaq    __strcasecmp_sse2(%rip), %rax
132 3:      ret
133 END(__strcasecmp)
134 weak_alias (__strcasecmp, strcasecmp)
135 # endif
136 # ifdef USE_AS_STRNCASECMP_L
137 ENTRY(__strncasecmp)
138         .type   __strncasecmp, @gnu_indirect_function
139         /* Manually inlined call to __get_cpu_features.  */
140         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
141         jne     1f
142         call    __init_cpu_features
144 #  ifdef HAVE_AVX_SUPPORT
145         leaq    __strncasecmp_avx(%rip), %rax
146         testl   $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
147         jnz     3f
148 #  endif
149         testl   $bit_Slow_SSE4_2, __cpu_features+CPUID_OFFSET+index_Slow_SSE4_2(%rip)
150         jnz     2f
151         leaq    __strncasecmp_sse42(%rip), %rax
152         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
153         jnz     3f
154 2:      leaq    __strncasecmp_ssse3(%rip), %rax
155         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
156         jnz     3f
157         leaq    __strncasecmp_sse2(%rip), %rax
158 3:      ret
159 END(__strncasecmp)
160 weak_alias (__strncasecmp, strncasecmp)
161 # endif
163 # undef LABEL
164 # define LABEL(l) .L##l##_sse42
165 # define GLABEL(l) l##_sse42
166 # define SECTION sse4.2
167 # include "strcmp-sse42.S"
170 # ifdef HAVE_AVX_SUPPORT
171 #  if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
172 #   define LABEL(l) .L##l##_avx
173 #   define GLABEL(l) l##_avx
174 #   define USE_AVX 1
175 #   undef STRCMP_SSE42
176 #   define STRCMP_SSE42 STRCMP_AVX
177 #   define SECTION avx
178 #   include "strcmp-sse42.S"
179 #  endif
180 # endif
183 # undef ENTRY
184 # define ENTRY(name) \
185         .type STRCMP_SSE2, @function; \
186         .align 16; \
187         .globl STRCMP_SSE2; \
188         .hidden STRCMP_SSE2; \
189         STRCMP_SSE2: cfi_startproc; \
190         CALL_MCOUNT
191 # undef END
192 # define END(name) \
193         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
195 # ifdef USE_AS_STRCASECMP_L
196 #  define ENTRY2(name) \
197         .type __strcasecmp_sse2, @function; \
198         .align 16; \
199         .globl __strcasecmp_sse2; \
200         .hidden __strcasecmp_sse2; \
201         __strcasecmp_sse2: cfi_startproc; \
202         CALL_MCOUNT
203 #  define END2(name) \
204         cfi_endproc; .size __strcasecmp_sse2, .-__strcasecmp_sse2
205 # endif
207 # ifdef USE_AS_STRNCASECMP_L
208 #  define ENTRY2(name) \
209         .type __strncasecmp_sse2, @function; \
210         .align 16; \
211         .globl __strncasecmp_sse2; \
212         .hidden __strncasecmp_sse2; \
213         __strncasecmp_sse2: cfi_startproc; \
214         CALL_MCOUNT
215 #  define END2(name) \
216         cfi_endproc; .size __strncasecmp_sse2, .-__strncasecmp_sse2
217 # endif
219 # undef libc_hidden_builtin_def
220 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
221    The speedup we get from using SSE4.2 instruction is likely eaten away
222    by the indirect call in the PLT.  */
223 # define libc_hidden_builtin_def(name) \
224         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
225 #endif
227 #include "../strcmp.S"