Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
blob2b9870ba9361c1143666f4cf1479f037abf87403
1 /* strcmp with SSE4.2
2    Copyright (C) 2009, 2010, 2011 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         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
87         jne     1f
88         call    __init_cpu_features
90         leaq    STRCMP_SSE42(%rip), %rax
91         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
92         jnz     2f
93         leaq    STRCMP_SSSE3(%rip), %rax
94         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
95         jnz     2f
96         leaq    STRCMP_SSE2(%rip), %rax
97 2:      ret
98 END(STRCMP)
100 # ifdef USE_AS_STRCASECMP_L
101 ENTRY(__strcasecmp)
102         .type   __strcasecmp, @gnu_indirect_function
103         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
104         jne     1f
105         call    __init_cpu_features
107 #  ifdef HAVE_AVX_SUPPORT
108         leaq    __strcasecmp_avx(%rip), %rax
109         testl   $bit_AVX, __cpu_features+CPUID_OFFSET+index_AVX(%rip)
110         jnz     2f
111 #  endif
112         leaq    __strcasecmp_sse42(%rip), %rax
113         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
114         jnz     2f
115         leaq    __strcasecmp_ssse3(%rip), %rax
116         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
117         jnz     2f
118         leaq    __strcasecmp_sse2(%rip), %rax
119 2:      ret
120 END(__strcasecmp)
121 weak_alias (__strcasecmp, strcasecmp)
122 # endif
123 # ifdef USE_AS_STRNCASECMP_L
124 ENTRY(__strncasecmp)
125         .type   __strncasecmp, @gnu_indirect_function
126         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
127         jne     1f
128         call    __init_cpu_features
130 #  ifdef HAVE_AVX_SUPPORT
131         leaq    __strncasecmp_avx(%rip), %rax
132         testl   $bit_AVX, __cpu_features+CPUID_OFFSET+index_AVX(%rip)
133         jnz     2f
134 #  endif
135         leaq    __strncasecmp_sse42(%rip), %rax
136         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
137         jnz     2f
138         leaq    __strncasecmp_ssse3(%rip), %rax
139         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
140         jnz     2f
141         leaq    __strncasecmp_sse2(%rip), %rax
142 2:      ret
143 END(__strncasecmp)
144 weak_alias (__strncasecmp, strncasecmp)
145 # endif
147 # undef LABEL
148 # define LABEL(l) .L##l##_sse42
149 # define GLABEL(l) l##_sse42
150 # define SECTION sse4.2
151 # include "strcmp-sse42.S"
154 # ifdef HAVE_AVX_SUPPORT
155 #  if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
156 #   define LABEL(l) .L##l##_avx
157 #   define GLABEL(l) l##_avx
158 #   define USE_AVX 1
159 #   undef STRCMP_SSE42
160 #   define STRCMP_SSE42 STRCMP_AVX
161 #   define SECTION avx
162 #   include "strcmp-sse42.S"
163 #  endif
164 # endif
167 # undef ENTRY
168 # define ENTRY(name) \
169         .type STRCMP_SSE2, @function; \
170         .align 16; \
171         STRCMP_SSE2: cfi_startproc; \
172         CALL_MCOUNT
173 # undef END
174 # define END(name) \
175         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
177 # ifdef USE_AS_STRCASECMP_L
178 #  define ENTRY2(name) \
179         .type __strcasecmp_sse2, @function; \
180         .align 16; \
181         __strcasecmp_sse2: cfi_startproc; \
182         CALL_MCOUNT
183 #  define END2(name) \
184         cfi_endproc; .size __strcasecmp_sse2, .-__strcasecmp_sse2
185 # endif
187 # ifdef USE_AS_STRNCASECMP_L
188 #  define ENTRY2(name) \
189         .type __strncasecmp_sse2, @function; \
190         .align 16; \
191         __strncasecmp_sse2: cfi_startproc; \
192         CALL_MCOUNT
193 #  define END2(name) \
194         cfi_endproc; .size __strncasecmp_sse2, .-__strncasecmp_sse2
195 # endif
197 # undef libc_hidden_builtin_def
198 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
199    The speedup we get from using SSE4.2 instruction is likely eaten away
200    by the indirect call in the PLT.  */
201 # define libc_hidden_builtin_def(name) \
202         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
203 #endif
205 #include "../strcmp.S"