BZ#14059: Fix AVX and FMA4 detection.
[glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
blobd366d09690c6805c58aec775126d156ad9a6436a
1 /* strcmp with SSE4.2
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         STRCMP_SSE2: cfi_startproc; \
175         CALL_MCOUNT
176 # undef END
177 # define END(name) \
178         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
180 # ifdef USE_AS_STRCASECMP_L
181 #  define ENTRY2(name) \
182         .type __strcasecmp_sse2, @function; \
183         .align 16; \
184         __strcasecmp_sse2: cfi_startproc; \
185         CALL_MCOUNT
186 #  define END2(name) \
187         cfi_endproc; .size __strcasecmp_sse2, .-__strcasecmp_sse2
188 # endif
190 # ifdef USE_AS_STRNCASECMP_L
191 #  define ENTRY2(name) \
192         .type __strncasecmp_sse2, @function; \
193         .align 16; \
194         __strncasecmp_sse2: cfi_startproc; \
195         CALL_MCOUNT
196 #  define END2(name) \
197         cfi_endproc; .size __strncasecmp_sse2, .-__strncasecmp_sse2
198 # endif
200 # undef libc_hidden_builtin_def
201 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
202    The speedup we get from using SSE4.2 instruction is likely eaten away
203    by the indirect call in the PLT.  */
204 # define libc_hidden_builtin_def(name) \
205         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
206 #endif
208 #include "../strcmp.S"