Add x86-64 __libc_ifunc_impl_list
[glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
blobf64ff46c7a6d600257ac2a8168d2ebe25c78cd75
1 /* Multiple versions of strcmp
2    Copyright (C) 2009-2012 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 UPDATE_STRNCMP_COUNTER
70 # ifndef STRCMP
71 #  define STRCMP        strcmp
72 #  define STRCMP_SSE42  __strcmp_sse42
73 #  define STRCMP_SSSE3  __strcmp_ssse3
74 #  define STRCMP_SSE2   __strcmp_sse2
75 #  define __GI_STRCMP   __GI_strcmp
76 # endif
77 #endif
79 /* Define multiple versions only for the definition in libc.  Don't
80    define multiple versions for strncmp in static library since we
81    need strncmp before the initialization happened.  */
82 #if (defined SHARED || !defined USE_AS_STRNCMP) && !defined NOT_IN_libc
83         .text
84 ENTRY(STRCMP)
85         .type   STRCMP, @gnu_indirect_function
86         /* Manually inlined call to __get_cpu_features.  */
87         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
88         jne     1f
89         call    __init_cpu_features
91         leaq    STRCMP_SSE42(%rip), %rax
92         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
93         jnz     2f
94         leaq    STRCMP_SSSE3(%rip), %rax
95         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
96         jnz     2f
97         leaq    STRCMP_SSE2(%rip), %rax
98 2:      ret
99 END(STRCMP)
101 # ifdef USE_AS_STRCASECMP_L
102 ENTRY(__strcasecmp)
103         .type   __strcasecmp, @gnu_indirect_function
104         /* Manually inlined call to __get_cpu_features.  */
105         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
106         jne     1f
107         call    __init_cpu_features
109 #  ifdef HAVE_AVX_SUPPORT
110         leaq    __strcasecmp_avx(%rip), %rax
111         testl   $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
112         jnz     2f
113 #  endif
114         leaq    __strcasecmp_sse42(%rip), %rax
115         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
116         jnz     2f
117         leaq    __strcasecmp_ssse3(%rip), %rax
118         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
119         jnz     2f
120         leaq    __strcasecmp_sse2(%rip), %rax
121 2:      ret
122 END(__strcasecmp)
123 weak_alias (__strcasecmp, strcasecmp)
124 # endif
125 # ifdef USE_AS_STRNCASECMP_L
126 ENTRY(__strncasecmp)
127         .type   __strncasecmp, @gnu_indirect_function
128         /* Manually inlined call to __get_cpu_features.  */
129         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
130         jne     1f
131         call    __init_cpu_features
133 #  ifdef HAVE_AVX_SUPPORT
134         leaq    __strncasecmp_avx(%rip), %rax
135         testl   $bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
136         jnz     2f
137 #  endif
138         leaq    __strncasecmp_sse42(%rip), %rax
139         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
140         jnz     2f
141         leaq    __strncasecmp_ssse3(%rip), %rax
142         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
143         jnz     2f
144         leaq    __strncasecmp_sse2(%rip), %rax
145 2:      ret
146 END(__strncasecmp)
147 weak_alias (__strncasecmp, strncasecmp)
148 # endif
150 # undef LABEL
151 # define LABEL(l) .L##l##_sse42
152 # define GLABEL(l) l##_sse42
153 # define SECTION sse4.2
154 # include "strcmp-sse42.S"
157 # ifdef HAVE_AVX_SUPPORT
158 #  if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
159 #   define LABEL(l) .L##l##_avx
160 #   define GLABEL(l) l##_avx
161 #   define USE_AVX 1
162 #   undef STRCMP_SSE42
163 #   define STRCMP_SSE42 STRCMP_AVX
164 #   define SECTION avx
165 #   include "strcmp-sse42.S"
166 #  endif
167 # endif
170 # undef ENTRY
171 # define ENTRY(name) \
172         .type STRCMP_SSE2, @function; \
173         .align 16; \
174         .globl STRCMP_SSE2; \
175         .hidden STRCMP_SSE2; \
176         STRCMP_SSE2: cfi_startproc; \
177         CALL_MCOUNT
178 # undef END
179 # define END(name) \
180         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
182 # ifdef USE_AS_STRCASECMP_L
183 #  define ENTRY2(name) \
184         .type __strcasecmp_sse2, @function; \
185         .align 16; \
186         .globl __strcasecmp_sse2; \
187         .hidden __strcasecmp_sse2; \
188         __strcasecmp_sse2: cfi_startproc; \
189         CALL_MCOUNT
190 #  define END2(name) \
191         cfi_endproc; .size __strcasecmp_sse2, .-__strcasecmp_sse2
192 # endif
194 # ifdef USE_AS_STRNCASECMP_L
195 #  define ENTRY2(name) \
196         .type __strncasecmp_sse2, @function; \
197         .align 16; \
198         .globl __strncasecmp_sse2; \
199         .hidden __strncasecmp_sse2; \
200         __strncasecmp_sse2: cfi_startproc; \
201         CALL_MCOUNT
202 #  define END2(name) \
203         cfi_endproc; .size __strncasecmp_sse2, .-__strncasecmp_sse2
204 # endif
206 # undef libc_hidden_builtin_def
207 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
208    The speedup we get from using SSE4.2 instruction is likely eaten away
209    by the indirect call in the PLT.  */
210 # define libc_hidden_builtin_def(name) \
211         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
212 #endif
214 #include "../strcmp.S"