1859289572b09855f40dfa3990b11bb5d325345e
[platform/upstream/glibc.git] / sysdeps / x86_64 / multiarch / strcmp.S
1 /* strcmp with SSE4.2
2    Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3    Contributed by Intel Corporation.
4    This file is part of the GNU C Library.
5
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.
10
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.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <sysdep.h>
22 #include <init-arch.h>
23
24 #ifdef USE_AS_STRNCMP
25 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
26    if the new counter > the old one or is 0.  */
27 # define UPDATE_STRNCMP_COUNTER                         \
28         /* calculate left number to compare */          \
29         lea     -16(%rcx, %r11), %r9;                   \
30         cmp     %r9, %r11;                              \
31         jb      LABEL(strcmp_exitz_sse4_2);             \
32         test    %r9, %r9;                               \
33         je      LABEL(strcmp_exitz_sse4_2);             \
34         mov     %r9, %r11
35
36 # define STRCMP_SSE42   __strncmp_sse42
37 # define STRCMP_SSSE3   __strncmp_ssse3
38 # define STRCMP_SSE2    __strncmp_sse2
39 # define __GI_STRCMP    __GI_strncmp
40 #elif defined USE_AS_STRCASECMP_L
41 # include "locale-defines.h"
42
43 # define UPDATE_STRNCMP_COUNTER
44
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"
51
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_sse4_2);             \
59         test    %r9, %r9;                               \
60         je      LABEL(strcmp_exitz_sse4_2);             \
61         mov     %r9, %r11
62
63 # define STRCMP_SSE42   __strncasecmp_l_sse42
64 # define STRCMP_SSSE3   __strncasecmp_l_ssse3
65 # define STRCMP_SSE2    __strncasecmp_l_sse2
66 # define __GI_STRCMP    __GI___strncasecmp_l
67 #else
68 # define UPDATE_STRNCMP_COUNTER
69 # ifndef STRCMP
70 #  define STRCMP        strcmp
71 #  define STRCMP_SSE42  __strcmp_sse42
72 #  define STRCMP_SSSE3  __strcmp_ssse3
73 #  define STRCMP_SSE2   __strcmp_sse2
74 #  define __GI_STRCMP   __GI_strcmp
75 # endif
76 #endif
77
78 #ifndef LABEL
79 # define LABEL(l) L(l)
80 #endif
81
82 /* Define multiple versions only for the definition in libc.  Don't
83    define multiple versions for strncmp in static library since we
84    need strncmp before the initialization happened.  */
85 #if (defined SHARED || !defined USE_AS_STRNCMP) && !defined NOT_IN_libc
86         .text
87 ENTRY(STRCMP)
88         .type   STRCMP, @gnu_indirect_function
89         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
90         jne     1f
91         call    __init_cpu_features
92 1:
93         leaq    STRCMP_SSE42(%rip), %rax
94         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
95         jnz     2f
96         leaq    STRCMP_SSSE3(%rip), %rax
97         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
98         jnz     2f
99         leaq    STRCMP_SSE2(%rip), %rax
100 2:      ret
101 END(STRCMP)
102
103 # ifdef USE_AS_STRCASECMP_L
104 ENTRY(__strcasecmp)
105         .type   __strcasecmp, @gnu_indirect_function
106         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
107         jne     1f
108         call    __init_cpu_features
109 1:
110         leaq    __strcasecmp_sse42(%rip), %rax
111         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
112         jnz     2f
113         leaq    __strcasecmp_ssse3(%rip), %rax
114         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
115         jnz     2f
116         leaq    __strcasecmp_sse2(%rip), %rax
117 2:      ret
118 END(__strcasecmp)
119 weak_alias (__strcasecmp, strcasecmp)
120 # endif
121 # ifdef USE_AS_STRNCASECMP_L
122 ENTRY(__strncasecmp)
123         .type   __strncasecmp, @gnu_indirect_function
124         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
125         jne     1f
126         call    __init_cpu_features
127 1:
128         leaq    __strncasecmp_sse42(%rip), %rax
129         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
130         jnz     2f
131         leaq    __strncasecmp_ssse3(%rip), %rax
132         testl   $bit_SSSE3, __cpu_features+CPUID_OFFSET+index_SSSE3(%rip)
133         jnz     2f
134         leaq    __strncasecmp_sse2(%rip), %rax
135 2:      ret
136 END(__strncasecmp)
137 weak_alias (__strncasecmp, strncasecmp)
138 # endif
139
140 /* We use 0x1a:
141         _SIDD_SBYTE_OPS
142         | _SIDD_CMP_EQUAL_EACH
143         | _SIDD_NEGATIVE_POLARITY
144         | _SIDD_LEAST_SIGNIFICANT
145    on pcmpistri to find out if two 16byte data elements are the same
146    and the offset of the first different byte.  There are 4 cases:
147
148    1. Both 16byte data elements are valid and identical.
149    2. Both 16byte data elements have EOS and identical.
150    3. Both 16byte data elements are valid and they differ at offset X.
151    4. At least one 16byte data element has EOS at offset X.  Two 16byte
152       data elements must differ at or before offset X.
153
154    Here is the table of ECX, CFlag, ZFlag and SFlag for 4 cases:
155
156    case         ECX     CFlag   ZFlag   SFlag
157     1           16        0       0       0
158     2           16        0       1       1
159     3            X        1       0       0
160     4          0 <= X     1      0/1     0/1
161
162    We exit from the loop for cases 2, 3 and 4 with jbe which branches
163    when either CFlag or ZFlag is 1.  If CFlag == 0, we return 0 for
164    case 2.  */
165
166         /* Put all SSE 4.2 functions together.  */
167         .section .text.sse4.2,"ax",@progbits
168         .align  16
169         .type   STRCMP_SSE42, @function
170 # ifdef USE_AS_STRCASECMP_L
171 ENTRY (__strcasecmp_sse42)
172         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
173         movq    %fs:(%rax),%rdx
174
175         // XXX 5 byte should be before the function
176         /* 5-byte NOP.  */
177         .byte   0x0f,0x1f,0x44,0x00,0x00
178 END (__strcasecmp_sse42)
179         /* FALLTHROUGH to strcasecmp_l.  */
180 # endif
181 # ifdef USE_AS_STRNCASECMP_L
182 ENTRY (__strncasecmp_sse42)
183         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
184         movq    %fs:(%rax),%rcx
185
186         // XXX 5 byte should be before the function
187         /* 5-byte NOP.  */
188         .byte   0x0f,0x1f,0x44,0x00,0x00
189 END (__strncasecmp_sse42)
190         /* FALLTHROUGH to strncasecmp_l.  */
191 # endif
192
193 STRCMP_SSE42:
194         cfi_startproc
195         CALL_MCOUNT
196
197 /*
198  * This implementation uses SSE to compare up to 16 bytes at a time.
199  */
200 # ifdef USE_AS_STRCASECMP_L
201         /* We have to fall back on the C implementation for locales
202            with encodings not matching ASCII for single bytes.  */
203 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
204         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%rdx), %rax
205 #  else
206         movq    (%rdx), %rax
207 #  endif
208         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
209         jne     __strcasecmp_l_nonascii
210 # endif
211 # ifdef USE_AS_STRNCASECMP_L
212         /* We have to fall back on the C implementation for locales
213            with encodings not matching ASCII for single bytes.  */
214 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
215         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%rcx), %rax
216 #  else
217         movq    (%rcx), %rax
218 #  endif
219         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
220         jne     __strncasecmp_l_nonascii
221 # endif
222
223 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
224         test    %rdx, %rdx
225         je      LABEL(strcmp_exitz_sse4_2)
226         cmp     $1, %rdx
227         je      LABEL(Byte0_sse4_2)
228         mov     %rdx, %r11
229 # endif
230         mov     %esi, %ecx
231         mov     %edi, %eax
232 /* Use 64bit AND here to avoid long NOP padding.  */
233         and     $0x3f, %rcx             /* rsi alignment in cache line */
234         and     $0x3f, %rax             /* rdi alignment in cache line */
235 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
236         .section .rodata.cst16,"aM",@progbits,16
237         .align 16
238 .Lbelowupper_sse4:
239         .quad   0x4040404040404040
240         .quad   0x4040404040404040
241 .Ltopupper_sse4:
242         .quad   0x5b5b5b5b5b5b5b5b
243         .quad   0x5b5b5b5b5b5b5b5b
244 .Ltouppermask_sse4:
245         .quad   0x2020202020202020
246         .quad   0x2020202020202020
247         .previous
248         movdqa  .Lbelowupper_sse4(%rip), %xmm4
249 #  define UCLOW_reg %xmm4
250         movdqa  .Ltopupper_sse4(%rip), %xmm5
251 #  define UCHIGH_reg %xmm5
252         movdqa  .Ltouppermask_sse4(%rip), %xmm6
253 #  define LCQWORD_reg %xmm6
254 # endif
255         cmp     $0x30, %ecx
256         ja      LABEL(crosscache_sse4_2)/* rsi: 16-byte load will cross cache line */
257         cmp     $0x30, %eax
258         ja      LABEL(crosscache_sse4_2)/* rdi: 16-byte load will cross cache line */
259         movdqu  (%rdi), %xmm1
260         movdqu  (%rsi), %xmm2
261 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
262 #  define TOLOWER(reg1, reg2) \
263         movdqa  reg1, %xmm7;                                    \
264         movdqa  UCHIGH_reg, %xmm8;                              \
265         movdqa  reg2, %xmm9;                                    \
266         movdqa  UCHIGH_reg, %xmm10;                             \
267         pcmpgtb UCLOW_reg, %xmm7;                               \
268         pcmpgtb reg1, %xmm8;                                    \
269         pcmpgtb UCLOW_reg, %xmm9;                               \
270         pcmpgtb reg2, %xmm10;                                   \
271         pand    %xmm8, %xmm7;                                   \
272         pand    %xmm10, %xmm9;                                  \
273         pand    LCQWORD_reg, %xmm7;                             \
274         pand    LCQWORD_reg, %xmm9;                             \
275         por     %xmm7, reg1;                                    \
276         por     %xmm9, reg2
277         TOLOWER (%xmm1, %xmm2)
278 # else
279 #  define TOLOWER(reg1, reg2)
280 # endif
281         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
282         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
283         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
284         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
285         pmovmskb %xmm1, %edx
286         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
287         jnz     LABEL(less16bytes_sse4_2)/* If not, find different value or null char */
288 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
289         sub     $16, %r11
290         jbe     LABEL(strcmp_exitz_sse4_2)/* finish comparision */
291 # endif
292         add     $16, %rsi               /* prepare to search next 16 bytes */
293         add     $16, %rdi               /* prepare to search next 16 bytes */
294
295         /*
296          * Determine source and destination string offsets from 16-byte alignment.
297          * Use relative offset difference between the two to determine which case
298          * below to use.
299          */
300         .p2align 4
301 LABEL(crosscache_sse4_2):
302         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
303         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
304         mov     $0xffff, %edx                   /* for equivalent offset */
305         xor     %r8d, %r8d
306         and     $0xf, %ecx                      /* offset of rsi */
307         and     $0xf, %eax                      /* offset of rdi */
308         cmp     %eax, %ecx
309         je      LABEL(ashr_0_sse4_2)            /* rsi and rdi relative offset same */
310         ja      LABEL(bigger_sse4_2)
311         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
312         xchg    %ecx, %eax
313         xchg    %rsi, %rdi
314 LABEL(bigger_sse4_2):
315         lea     15(%rax), %r9
316         sub     %rcx, %r9
317         lea     LABEL(unaligned_table_sse4_2)(%rip), %r10
318         movslq  (%r10, %r9,4), %r9
319         lea     (%r10, %r9), %r10
320         jmp     *%r10                           /* jump to corresponding case */
321
322 /*
323  * The following cases will be handled by ashr_0
324  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
325  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
326  */
327         .p2align 4
328 LABEL(ashr_0_sse4_2):
329
330         movdqa  (%rsi), %xmm1
331         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
332         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
333 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
334         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
335 # else
336         movdqa  (%rdi), %xmm2
337         TOLOWER (%xmm1, %xmm2)
338         pcmpeqb %xmm2, %xmm1                    /* compare 16 bytes for equality */
339 # endif
340         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
341         pmovmskb %xmm1, %r9d
342         shr     %cl, %edx                       /* adjust 0xffff for offset */
343         shr     %cl, %r9d                       /* adjust for 16-byte offset */
344         sub     %r9d, %edx
345         /*
346          * edx must be the same with r9d if in left byte (16-rcx) is equal to
347          * the start from (16-rax) and no null char was seen.
348          */
349         jne     LABEL(less32bytes_sse4_2)       /* mismatch or null char */
350         UPDATE_STRNCMP_COUNTER
351         mov     $16, %rcx
352         mov     $16, %r9
353         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
354
355         /*
356          * Now both strings are aligned at 16-byte boundary. Loop over strings
357          * checking 32-bytes per iteration.
358          */
359         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
360         .p2align 4
361 LABEL(ashr_0_use_sse4_2):
362         movdqa  (%rdi,%rdx), %xmm0
363 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
364         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
365 # else
366         movdqa  (%rsi,%rdx), %xmm1
367         TOLOWER (%xmm0, %xmm1)
368         pcmpistri $0x1a, %xmm1, %xmm0
369 # endif
370         lea     16(%rdx), %rdx
371         jbe     LABEL(ashr_0_use_sse4_2_exit)
372 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
373         sub     $16, %r11
374         jbe     LABEL(strcmp_exitz_sse4_2)
375 # endif
376
377         movdqa  (%rdi,%rdx), %xmm0
378 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
379         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
380 # else
381         movdqa  (%rsi,%rdx), %xmm1
382         TOLOWER (%xmm0, %xmm1)
383         pcmpistri $0x1a, %xmm1, %xmm0
384 # endif
385         lea     16(%rdx), %rdx
386         jbe     LABEL(ashr_0_use_sse4_2_exit)
387 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
388         sub     $16, %r11
389         jbe     LABEL(strcmp_exitz_sse4_2)
390 # endif
391         jmp     LABEL(ashr_0_use_sse4_2)
392
393
394         .p2align 4
395 LABEL(ashr_0_use_sse4_2_exit):
396         jnc     LABEL(strcmp_exitz_sse4_2)
397 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
398         sub     %rcx, %r11
399         jbe     LABEL(strcmp_exitz_sse4_2)
400 # endif
401         lea     -16(%rdx, %rcx), %rcx
402         movzbl  (%rdi, %rcx), %eax
403         movzbl  (%rsi, %rcx), %edx
404 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
405         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rcx
406         movl    (%rcx,%rax,4), %eax
407         movl    (%rcx,%rdx,4), %edx
408 # endif
409         sub     %edx, %eax
410         ret
411
412
413
414 /*
415  * The following cases will be handled by ashr_1
416  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
417  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
418  */
419         .p2align 4
420 LABEL(ashr_1_sse4_2):
421         pxor    %xmm0, %xmm0
422         movdqa  (%rdi), %xmm2
423         movdqa  (%rsi), %xmm1
424         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
425         pslldq  $15, %xmm2              /* shift first string to align with second */
426         TOLOWER (%xmm1, %xmm2)
427         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
428         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
429         pmovmskb %xmm2, %r9d
430         shr     %cl, %edx               /* adjust 0xffff for offset */
431         shr     %cl, %r9d               /* adjust for 16-byte offset */
432         sub     %r9d, %edx
433         jnz     LABEL(less32bytes_sse4_2)/* mismatch or null char seen */
434         movdqa  (%rdi), %xmm3
435         UPDATE_STRNCMP_COUNTER
436
437         pxor    %xmm0, %xmm0
438         mov     $16, %rcx               /* index for loads*/
439         mov     $1, %r9d                /* byte position left over from less32bytes case */
440         /*
441          * Setup %r10 value allows us to detect crossing a page boundary.
442          * When %r10 goes positive we have crossed a page boundary and
443          * need to do a nibble.
444          */
445         lea     1(%rdi), %r10
446         and     $0xfff, %r10            /* offset into 4K page */
447         sub     $0x1000, %r10           /* subtract 4K pagesize */
448         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
449
450         .p2align 4
451 LABEL(loop_ashr_1_use_sse4_2):
452         add     $16, %r10
453         jg      LABEL(nibble_ashr_1_use_sse4_2)
454
455         movdqa  (%rdi, %rdx), %xmm0
456         palignr $1, -16(%rdi, %rdx), %xmm0
457 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
458         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
459 # else
460         movdqa  (%rsi,%rdx), %xmm1
461         TOLOWER (%xmm0, %xmm1)
462         pcmpistri $0x1a, %xmm1, %xmm0
463 # endif
464         jbe     LABEL(use_sse4_2_exit)
465 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
466         sub     $16, %r11
467         jbe     LABEL(strcmp_exitz_sse4_2)
468 # endif
469
470         add     $16, %rdx
471         add     $16, %r10
472         jg      LABEL(nibble_ashr_1_use_sse4_2)
473
474         movdqa  (%rdi, %rdx), %xmm0
475         palignr $1, -16(%rdi, %rdx), %xmm0
476 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
477         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
478 # else
479         movdqa  (%rsi,%rdx), %xmm1
480         TOLOWER (%xmm0, %xmm1)
481         pcmpistri $0x1a, %xmm1, %xmm0
482 # endif
483         jbe     LABEL(use_sse4_2_exit)
484 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
485         sub     $16, %r11
486         jbe     LABEL(strcmp_exitz_sse4_2)
487 # endif
488         add     $16, %rdx
489         jmp     LABEL(loop_ashr_1_use_sse4_2)
490
491         .p2align 4
492 LABEL(nibble_ashr_1_use_sse4_2):
493         sub     $0x1000, %r10
494         movdqa  -16(%rdi, %rdx), %xmm0
495         psrldq  $1, %xmm0
496         pcmpistri      $0x3a,%xmm0, %xmm0
497 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
498         cmp     %r11, %rcx
499         jae     LABEL(nibble_ashr_use_sse4_2_exit)
500 # endif
501         cmp     $14, %ecx
502         ja      LABEL(loop_ashr_1_use_sse4_2)
503
504         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
505
506 /*
507  * The following cases will be handled by ashr_2
508  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
509  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
510  */
511         .p2align 4
512 LABEL(ashr_2_sse4_2):
513         pxor    %xmm0, %xmm0
514         movdqa  (%rdi), %xmm2
515         movdqa  (%rsi), %xmm1
516         pcmpeqb %xmm1, %xmm0
517         pslldq  $14, %xmm2
518         TOLOWER (%xmm1, %xmm2)
519         pcmpeqb %xmm1, %xmm2
520         psubb   %xmm0, %xmm2
521         pmovmskb %xmm2, %r9d
522         shr     %cl, %edx
523         shr     %cl, %r9d
524         sub     %r9d, %edx
525         jnz     LABEL(less32bytes_sse4_2)
526         movdqa  (%rdi), %xmm3
527         UPDATE_STRNCMP_COUNTER
528
529         pxor    %xmm0, %xmm0
530         mov     $16, %rcx       /* index for loads */
531         mov     $2, %r9d        /* byte position left over from less32bytes case */
532         /*
533          * Setup %r10 value allows us to detect crossing a page boundary.
534          * When %r10 goes positive we have crossed a page boundary and
535          * need to do a nibble.
536          */
537         lea     2(%rdi), %r10
538         and     $0xfff, %r10    /* offset into 4K page */
539         sub     $0x1000, %r10   /* subtract 4K pagesize */
540         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
541
542         .p2align 4
543 LABEL(loop_ashr_2_use_sse4_2):
544         add     $16, %r10
545         jg      LABEL(nibble_ashr_2_use_sse4_2)
546
547         movdqa  (%rdi, %rdx), %xmm0
548         palignr $2, -16(%rdi, %rdx), %xmm0
549 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
550         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
551 # else
552         movdqa  (%rsi,%rdx), %xmm1
553         TOLOWER (%xmm0, %xmm1)
554         pcmpistri $0x1a, %xmm1, %xmm0
555 # endif
556         jbe     LABEL(use_sse4_2_exit)
557 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
558         sub     $16, %r11
559         jbe     LABEL(strcmp_exitz_sse4_2)
560 # endif
561
562         add     $16, %rdx
563         add     $16, %r10
564         jg      LABEL(nibble_ashr_2_use_sse4_2)
565
566         movdqa  (%rdi, %rdx), %xmm0
567         palignr $2, -16(%rdi, %rdx), %xmm0
568 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
569         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
570 # else
571         movdqa  (%rsi,%rdx), %xmm1
572         TOLOWER (%xmm0, %xmm1)
573         pcmpistri $0x1a, %xmm1, %xmm0
574 # endif
575         jbe     LABEL(use_sse4_2_exit)
576 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
577         sub     $16, %r11
578         jbe     LABEL(strcmp_exitz_sse4_2)
579 # endif
580         add     $16, %rdx
581         jmp     LABEL(loop_ashr_2_use_sse4_2)
582
583         .p2align 4
584 LABEL(nibble_ashr_2_use_sse4_2):
585         sub     $0x1000, %r10
586         movdqa  -16(%rdi, %rdx), %xmm0
587         psrldq  $2, %xmm0
588         pcmpistri      $0x3a,%xmm0, %xmm0
589 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
590         cmp     %r11, %rcx
591         jae     LABEL(nibble_ashr_use_sse4_2_exit)
592 # endif
593         cmp     $13, %ecx
594         ja      LABEL(loop_ashr_2_use_sse4_2)
595
596         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
597
598 /*
599  * The following cases will be handled by ashr_3
600  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
601  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
602  */
603         .p2align 4
604 LABEL(ashr_3_sse4_2):
605         pxor    %xmm0, %xmm0
606         movdqa  (%rdi), %xmm2
607         movdqa  (%rsi), %xmm1
608         pcmpeqb %xmm1, %xmm0
609         pslldq  $13, %xmm2
610         TOLOWER (%xmm1, %xmm2)
611         pcmpeqb %xmm1, %xmm2
612         psubb   %xmm0, %xmm2
613         pmovmskb %xmm2, %r9d
614         shr     %cl, %edx
615         shr     %cl, %r9d
616         sub     %r9d, %edx
617         jnz     LABEL(less32bytes_sse4_2)
618         movdqa  (%rdi), %xmm3
619
620         UPDATE_STRNCMP_COUNTER
621
622         pxor    %xmm0, %xmm0
623         mov     $16, %rcx       /* index for loads */
624         mov     $3, %r9d        /* byte position left over from less32bytes case */
625         /*
626          * Setup %r10 value allows us to detect crossing a page boundary.
627          * When %r10 goes positive we have crossed a page boundary and
628          * need to do a nibble.
629          */
630         lea     3(%rdi), %r10
631         and     $0xfff, %r10    /* offset into 4K page */
632         sub     $0x1000, %r10   /* subtract 4K pagesize */
633         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
634
635 LABEL(loop_ashr_3_use_sse4_2):
636         add     $16, %r10
637         jg      LABEL(nibble_ashr_3_use_sse4_2)
638
639         movdqa  (%rdi, %rdx), %xmm0
640         palignr $3, -16(%rdi, %rdx), %xmm0
641 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
642         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
643 # else
644         movdqa  (%rsi,%rdx), %xmm1
645         TOLOWER (%xmm0, %xmm1)
646         pcmpistri $0x1a, %xmm1, %xmm0
647 # endif
648         jbe     LABEL(use_sse4_2_exit)
649 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
650         sub     $16, %r11
651         jbe     LABEL(strcmp_exitz_sse4_2)
652 # endif
653
654         add     $16, %rdx
655         add     $16, %r10
656         jg      LABEL(nibble_ashr_3_use_sse4_2)
657
658         movdqa  (%rdi, %rdx), %xmm0
659         palignr $3, -16(%rdi, %rdx), %xmm0
660 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
661         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
662 # else
663         movdqa  (%rsi,%rdx), %xmm1
664         TOLOWER (%xmm0, %xmm1)
665         pcmpistri $0x1a, %xmm1, %xmm0
666 # endif
667         jbe     LABEL(use_sse4_2_exit)
668 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
669         sub     $16, %r11
670         jbe     LABEL(strcmp_exitz_sse4_2)
671 # endif
672         add     $16, %rdx
673         jmp     LABEL(loop_ashr_3_use_sse4_2)
674
675         .p2align 4
676 LABEL(nibble_ashr_3_use_sse4_2):
677         sub     $0x1000, %r10
678         movdqa  -16(%rdi, %rdx), %xmm0
679         psrldq  $3, %xmm0
680         pcmpistri      $0x3a,%xmm0, %xmm0
681 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
682         cmp     %r11, %rcx
683         jae     LABEL(nibble_ashr_use_sse4_2_exit)
684 # endif
685         cmp     $12, %ecx
686         ja      LABEL(loop_ashr_3_use_sse4_2)
687
688         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
689
690 /*
691  * The following cases will be handled by ashr_4
692  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
693  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
694  */
695         .p2align 4
696 LABEL(ashr_4_sse4_2):
697         pxor    %xmm0, %xmm0
698         movdqa  (%rdi), %xmm2
699         movdqa  (%rsi), %xmm1
700         pcmpeqb %xmm1, %xmm0
701         pslldq  $12, %xmm2
702         TOLOWER (%xmm1, %xmm2)
703         pcmpeqb %xmm1, %xmm2
704         psubb   %xmm0, %xmm2
705         pmovmskb %xmm2, %r9d
706         shr     %cl, %edx
707         shr     %cl, %r9d
708         sub     %r9d, %edx
709         jnz     LABEL(less32bytes_sse4_2)
710         movdqa  (%rdi), %xmm3
711
712         UPDATE_STRNCMP_COUNTER
713
714         pxor    %xmm0, %xmm0
715         mov     $16, %rcx       /* index for loads */
716         mov     $4, %r9d        /* byte position left over from less32bytes case */
717         /*
718          * Setup %r10 value allows us to detect crossing a page boundary.
719          * When %r10 goes positive we have crossed a page boundary and
720          * need to do a nibble.
721          */
722         lea     4(%rdi), %r10
723         and     $0xfff, %r10    /* offset into 4K page */
724         sub     $0x1000, %r10   /* subtract 4K pagesize */
725         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
726
727         .p2align 4
728 LABEL(loop_ashr_4_use_sse4_2):
729         add     $16, %r10
730         jg      LABEL(nibble_ashr_4_use_sse4_2)
731
732         movdqa  (%rdi, %rdx), %xmm0
733         palignr $4, -16(%rdi, %rdx), %xmm0
734 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
735         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
736 # else
737         movdqa  (%rsi,%rdx), %xmm1
738         TOLOWER (%xmm0, %xmm1)
739         pcmpistri $0x1a, %xmm1, %xmm0
740 # endif
741         jbe     LABEL(use_sse4_2_exit)
742 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
743         sub     $16, %r11
744         jbe     LABEL(strcmp_exitz_sse4_2)
745 # endif
746
747         add     $16, %rdx
748         add     $16, %r10
749         jg      LABEL(nibble_ashr_4_use_sse4_2)
750
751         movdqa  (%rdi, %rdx), %xmm0
752         palignr $4, -16(%rdi, %rdx), %xmm0
753 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
754         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
755 # else
756         movdqa  (%rsi,%rdx), %xmm1
757         TOLOWER (%xmm0, %xmm1)
758         pcmpistri $0x1a, %xmm1, %xmm0
759 # endif
760         jbe     LABEL(use_sse4_2_exit)
761 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
762         sub     $16, %r11
763         jbe     LABEL(strcmp_exitz_sse4_2)
764 # endif
765         add     $16, %rdx
766         jmp     LABEL(loop_ashr_4_use_sse4_2)
767
768         .p2align 4
769 LABEL(nibble_ashr_4_use_sse4_2):
770         sub     $0x1000, %r10
771         movdqa  -16(%rdi, %rdx), %xmm0
772         psrldq  $4, %xmm0
773         pcmpistri      $0x3a,%xmm0, %xmm0
774 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
775         cmp     %r11, %rcx
776         jae     LABEL(nibble_ashr_use_sse4_2_exit)
777 # endif
778         cmp     $11, %ecx
779         ja      LABEL(loop_ashr_4_use_sse4_2)
780
781         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
782
783 /*
784  * The following cases will be handled by ashr_5
785  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
786  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
787  */
788         .p2align 4
789 LABEL(ashr_5_sse4_2):
790         pxor    %xmm0, %xmm0
791         movdqa  (%rdi), %xmm2
792         movdqa  (%rsi), %xmm1
793         pcmpeqb %xmm1, %xmm0
794         pslldq  $11, %xmm2
795         TOLOWER (%xmm1, %xmm2)
796         pcmpeqb %xmm1, %xmm2
797         psubb   %xmm0, %xmm2
798         pmovmskb %xmm2, %r9d
799         shr     %cl, %edx
800         shr     %cl, %r9d
801         sub     %r9d, %edx
802         jnz     LABEL(less32bytes_sse4_2)
803         movdqa  (%rdi), %xmm3
804
805         UPDATE_STRNCMP_COUNTER
806
807         pxor    %xmm0, %xmm0
808         mov     $16, %rcx       /* index for loads */
809         mov     $5, %r9d        /* byte position left over from less32bytes case */
810         /*
811          * Setup %r10 value allows us to detect crossing a page boundary.
812          * When %r10 goes positive we have crossed a page boundary and
813          * need to do a nibble.
814          */
815         lea     5(%rdi), %r10
816         and     $0xfff, %r10    /* offset into 4K page */
817         sub     $0x1000, %r10   /* subtract 4K pagesize */
818         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
819
820         .p2align 4
821 LABEL(loop_ashr_5_use_sse4_2):
822         add     $16, %r10
823         jg      LABEL(nibble_ashr_5_use_sse4_2)
824
825         movdqa  (%rdi, %rdx), %xmm0
826         palignr $5, -16(%rdi, %rdx), %xmm0
827 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
828         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
829 # else
830         movdqa  (%rsi,%rdx), %xmm1
831         TOLOWER (%xmm0, %xmm1)
832         pcmpistri $0x1a, %xmm1, %xmm0
833 # endif
834         jbe     LABEL(use_sse4_2_exit)
835 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
836         sub     $16, %r11
837         jbe     LABEL(strcmp_exitz_sse4_2)
838 # endif
839
840         add     $16, %rdx
841         add     $16, %r10
842         jg      LABEL(nibble_ashr_5_use_sse4_2)
843
844         movdqa  (%rdi, %rdx), %xmm0
845
846         palignr $5, -16(%rdi, %rdx), %xmm0
847 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
848         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
849 # else
850         movdqa  (%rsi,%rdx), %xmm1
851         TOLOWER (%xmm0, %xmm1)
852         pcmpistri $0x1a, %xmm1, %xmm0
853 # endif
854         jbe     LABEL(use_sse4_2_exit)
855 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
856         sub     $16, %r11
857         jbe     LABEL(strcmp_exitz_sse4_2)
858 # endif
859         add     $16, %rdx
860         jmp     LABEL(loop_ashr_5_use_sse4_2)
861
862         .p2align 4
863 LABEL(nibble_ashr_5_use_sse4_2):
864         sub     $0x1000, %r10
865         movdqa  -16(%rdi, %rdx), %xmm0
866         psrldq  $5, %xmm0
867         pcmpistri      $0x3a,%xmm0, %xmm0
868 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
869         cmp     %r11, %rcx
870         jae     LABEL(nibble_ashr_use_sse4_2_exit)
871 # endif
872         cmp     $10, %ecx
873         ja      LABEL(loop_ashr_5_use_sse4_2)
874
875         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
876
877 /*
878  * The following cases will be handled by ashr_6
879  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
880  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
881  */
882         .p2align 4
883 LABEL(ashr_6_sse4_2):
884         pxor    %xmm0, %xmm0
885         movdqa  (%rdi), %xmm2
886         movdqa  (%rsi), %xmm1
887         pcmpeqb %xmm1, %xmm0
888         pslldq  $10, %xmm2
889         TOLOWER (%xmm1, %xmm2)
890         pcmpeqb %xmm1, %xmm2
891         psubb   %xmm0, %xmm2
892         pmovmskb %xmm2, %r9d
893         shr     %cl, %edx
894         shr     %cl, %r9d
895         sub     %r9d, %edx
896         jnz     LABEL(less32bytes_sse4_2)
897         movdqa  (%rdi), %xmm3
898
899         UPDATE_STRNCMP_COUNTER
900
901         pxor    %xmm0, %xmm0
902         mov     $16, %rcx       /* index for loads */
903         mov     $6, %r9d        /* byte position left over from less32bytes case */
904         /*
905          * Setup %r10 value allows us to detect crossing a page boundary.
906          * When %r10 goes positive we have crossed a page boundary and
907          * need to do a nibble.
908          */
909         lea     6(%rdi), %r10
910         and     $0xfff, %r10    /* offset into 4K page */
911         sub     $0x1000, %r10   /* subtract 4K pagesize */
912         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
913
914         .p2align 4
915 LABEL(loop_ashr_6_use_sse4_2):
916         add     $16, %r10
917         jg      LABEL(nibble_ashr_6_use_sse4_2)
918
919         movdqa  (%rdi, %rdx), %xmm0
920         palignr $6, -16(%rdi, %rdx), %xmm0
921 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
922         pcmpistri $0x1a,(%rsi,%rdx), %xmm0
923 # else
924         movdqa  (%rsi,%rdx), %xmm1
925         TOLOWER (%xmm0, %xmm1)
926         pcmpistri $0x1a, %xmm1, %xmm0
927 # endif
928         jbe     LABEL(use_sse4_2_exit)
929 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
930         sub     $16, %r11
931         jbe     LABEL(strcmp_exitz_sse4_2)
932 # endif
933
934         add     $16, %rdx
935         add     $16, %r10
936         jg      LABEL(nibble_ashr_6_use_sse4_2)
937
938         movdqa  (%rdi, %rdx), %xmm0
939         palignr $6, -16(%rdi, %rdx), %xmm0
940 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
941         pcmpistri $0x1a,(%rsi,%rdx), %xmm0
942 # else
943         movdqa  (%rsi,%rdx), %xmm1
944         TOLOWER (%xmm0, %xmm1)
945         pcmpistri $0x1a, %xmm1, %xmm0
946 # endif
947         jbe     LABEL(use_sse4_2_exit)
948 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
949         sub     $16, %r11
950         jbe     LABEL(strcmp_exitz_sse4_2)
951 # endif
952         add     $16, %rdx
953         jmp     LABEL(loop_ashr_6_use_sse4_2)
954
955         .p2align 4
956 LABEL(nibble_ashr_6_use_sse4_2):
957         sub     $0x1000, %r10
958         movdqa  -16(%rdi, %rdx), %xmm0
959         psrldq  $6, %xmm0
960         pcmpistri      $0x3a,%xmm0, %xmm0
961 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
962         cmp     %r11, %rcx
963         jae     LABEL(nibble_ashr_use_sse4_2_exit)
964 # endif
965         cmp     $9, %ecx
966         ja      LABEL(loop_ashr_6_use_sse4_2)
967
968         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
969
970 /*
971  * The following cases will be handled by ashr_7
972  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
973  *        n(9~15)          n - 9                  6(15 +(n - 9) - n)         ashr_7
974  */
975         .p2align 4
976 LABEL(ashr_7_sse4_2):
977         pxor    %xmm0, %xmm0
978         movdqa  (%rdi), %xmm2
979         movdqa  (%rsi), %xmm1
980         pcmpeqb %xmm1, %xmm0
981         pslldq  $9, %xmm2
982         TOLOWER (%xmm1, %xmm2)
983         pcmpeqb %xmm1, %xmm2
984         psubb   %xmm0, %xmm2
985         pmovmskb %xmm2, %r9d
986         shr     %cl, %edx
987         shr     %cl, %r9d
988         sub     %r9d, %edx
989         jnz     LABEL(less32bytes_sse4_2)
990         movdqa  (%rdi), %xmm3
991
992         UPDATE_STRNCMP_COUNTER
993
994         pxor    %xmm0, %xmm0
995         mov     $16, %rcx       /* index for loads */
996         mov     $7, %r9d        /* byte position left over from less32bytes case */
997         /*
998          * Setup %r10 value allows us to detect crossing a page boundary.
999          * When %r10 goes positive we have crossed a page boundary and
1000          * need to do a nibble.
1001          */
1002         lea     7(%rdi), %r10
1003         and     $0xfff, %r10    /* offset into 4K page */
1004         sub     $0x1000, %r10   /* subtract 4K pagesize */
1005         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1006
1007         .p2align 4
1008 LABEL(loop_ashr_7_use_sse4_2):
1009         add     $16, %r10
1010         jg      LABEL(nibble_ashr_7_use_sse4_2)
1011
1012         movdqa  (%rdi, %rdx), %xmm0
1013         palignr $7, -16(%rdi, %rdx), %xmm0
1014 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1015         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1016 # else
1017         movdqa  (%rsi,%rdx), %xmm1
1018         TOLOWER (%xmm0, %xmm1)
1019         pcmpistri $0x1a, %xmm1, %xmm0
1020 # endif
1021         jbe     LABEL(use_sse4_2_exit)
1022 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1023         sub     $16, %r11
1024         jbe     LABEL(strcmp_exitz_sse4_2)
1025 # endif
1026
1027         add     $16, %rdx
1028         add     $16, %r10
1029         jg      LABEL(nibble_ashr_7_use_sse4_2)
1030
1031         movdqa  (%rdi, %rdx), %xmm0
1032         palignr $7, -16(%rdi, %rdx), %xmm0
1033 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1034         pcmpistri       $0x1a,(%rsi,%rdx), %xmm0
1035 # else
1036         movdqa  (%rsi,%rdx), %xmm1
1037         TOLOWER (%xmm0, %xmm1)
1038         pcmpistri $0x1a, %xmm1, %xmm0
1039 # endif
1040         jbe     LABEL(use_sse4_2_exit)
1041 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1042         sub     $16, %r11
1043         jbe     LABEL(strcmp_exitz_sse4_2)
1044 # endif
1045         add     $16, %rdx
1046         jmp     LABEL(loop_ashr_7_use_sse4_2)
1047
1048         .p2align 4
1049 LABEL(nibble_ashr_7_use_sse4_2):
1050         sub     $0x1000, %r10
1051         movdqa  -16(%rdi, %rdx), %xmm0
1052         psrldq  $7, %xmm0
1053         pcmpistri      $0x3a,%xmm0, %xmm0
1054 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1055         cmp     %r11, %rcx
1056         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1057 # endif
1058         cmp     $8, %ecx
1059         ja      LABEL(loop_ashr_7_use_sse4_2)
1060
1061         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1062
1063 /*
1064  *  The following cases will be handled by ashr_8
1065  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1066  *        n(8~15)          n - 8                  7(15 +(n - 8) - n)         ashr_8
1067  */
1068         .p2align 4
1069 LABEL(ashr_8_sse4_2):
1070         pxor    %xmm0, %xmm0
1071         movdqa  (%rdi), %xmm2
1072         movdqa  (%rsi), %xmm1
1073         pcmpeqb %xmm1, %xmm0
1074         pslldq  $8, %xmm2
1075         TOLOWER (%xmm1, %xmm2)
1076         pcmpeqb %xmm1, %xmm2
1077         psubb   %xmm0, %xmm2
1078         pmovmskb %xmm2, %r9d
1079         shr     %cl, %edx
1080         shr     %cl, %r9d
1081         sub     %r9d, %edx
1082         jnz     LABEL(less32bytes_sse4_2)
1083         movdqa  (%rdi), %xmm3
1084
1085         UPDATE_STRNCMP_COUNTER
1086
1087         pxor    %xmm0, %xmm0
1088         mov     $16, %rcx       /* index for loads */
1089         mov     $8, %r9d        /* byte position left over from less32bytes case */
1090         /*
1091          * Setup %r10 value allows us to detect crossing a page boundary.
1092          * When %r10 goes positive we have crossed a page boundary and
1093          * need to do a nibble.
1094          */
1095         lea     8(%rdi), %r10
1096         and     $0xfff, %r10    /* offset into 4K page */
1097         sub     $0x1000, %r10   /* subtract 4K pagesize */
1098         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1099
1100         .p2align 4
1101 LABEL(loop_ashr_8_use_sse4_2):
1102         add     $16, %r10
1103         jg      LABEL(nibble_ashr_8_use_sse4_2)
1104
1105         movdqa  (%rdi, %rdx), %xmm0
1106         palignr $8, -16(%rdi, %rdx), %xmm0
1107 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1108         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1109 # else
1110         movdqa  (%rsi,%rdx), %xmm1
1111         TOLOWER (%xmm0, %xmm1)
1112         pcmpistri $0x1a, %xmm1, %xmm0
1113 # endif
1114         jbe     LABEL(use_sse4_2_exit)
1115 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1116         sub     $16, %r11
1117         jbe     LABEL(strcmp_exitz_sse4_2)
1118 # endif
1119
1120         add     $16, %rdx
1121         add     $16, %r10
1122         jg      LABEL(nibble_ashr_8_use_sse4_2)
1123
1124         movdqa  (%rdi, %rdx), %xmm0
1125         palignr $8, -16(%rdi, %rdx), %xmm0
1126 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1127         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1128 # else
1129         movdqa  (%rsi,%rdx), %xmm1
1130         TOLOWER (%xmm0, %xmm1)
1131         pcmpistri $0x1a, %xmm1, %xmm0
1132 # endif
1133         jbe     LABEL(use_sse4_2_exit)
1134 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1135         sub     $16, %r11
1136         jbe     LABEL(strcmp_exitz_sse4_2)
1137 # endif
1138         add     $16, %rdx
1139         jmp     LABEL(loop_ashr_8_use_sse4_2)
1140
1141         .p2align 4
1142 LABEL(nibble_ashr_8_use_sse4_2):
1143         sub     $0x1000, %r10
1144         movdqa  -16(%rdi, %rdx), %xmm0
1145         psrldq  $8, %xmm0
1146         pcmpistri      $0x3a,%xmm0, %xmm0
1147 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1148         cmp     %r11, %rcx
1149         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1150 # endif
1151         cmp     $7, %ecx
1152         ja      LABEL(loop_ashr_8_use_sse4_2)
1153
1154         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1155
1156 /*
1157  *  The following cases will be handled by ashr_9
1158  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1159  *        n(7~15)          n - 7                  8(15 +(n - 7) - n)         ashr_9
1160  */
1161         .p2align 4
1162 LABEL(ashr_9_sse4_2):
1163         pxor    %xmm0, %xmm0
1164         movdqa  (%rdi), %xmm2
1165         movdqa  (%rsi), %xmm1
1166         pcmpeqb %xmm1, %xmm0
1167         pslldq  $7, %xmm2
1168         TOLOWER (%xmm1, %xmm2)
1169         pcmpeqb %xmm1, %xmm2
1170         psubb   %xmm0, %xmm2
1171         pmovmskb %xmm2, %r9d
1172         shr     %cl, %edx
1173         shr     %cl, %r9d
1174         sub     %r9d, %edx
1175         jnz     LABEL(less32bytes_sse4_2)
1176         movdqa  (%rdi), %xmm3
1177
1178         UPDATE_STRNCMP_COUNTER
1179
1180         pxor    %xmm0, %xmm0
1181         mov     $16, %rcx       /* index for loads */
1182         mov     $9, %r9d        /* byte position left over from less32bytes case */
1183         /*
1184          * Setup %r10 value allows us to detect crossing a page boundary.
1185          * When %r10 goes positive we have crossed a page boundary and
1186          * need to do a nibble.
1187          */
1188         lea     9(%rdi), %r10
1189         and     $0xfff, %r10    /* offset into 4K page */
1190         sub     $0x1000, %r10   /* subtract 4K pagesize */
1191         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1192
1193         .p2align 4
1194 LABEL(loop_ashr_9_use_sse4_2):
1195         add     $16, %r10
1196         jg      LABEL(nibble_ashr_9_use_sse4_2)
1197
1198         movdqa  (%rdi, %rdx), %xmm0
1199
1200         palignr $9, -16(%rdi, %rdx), %xmm0
1201 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1202         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1203 # else
1204         movdqa  (%rsi,%rdx), %xmm1
1205         TOLOWER (%xmm0, %xmm1)
1206         pcmpistri $0x1a, %xmm1, %xmm0
1207 # endif
1208         jbe     LABEL(use_sse4_2_exit)
1209 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1210         sub     $16, %r11
1211         jbe     LABEL(strcmp_exitz_sse4_2)
1212 # endif
1213
1214         add     $16, %rdx
1215         add     $16, %r10
1216         jg      LABEL(nibble_ashr_9_use_sse4_2)
1217
1218         movdqa  (%rdi, %rdx), %xmm0
1219         palignr $9, -16(%rdi, %rdx), %xmm0
1220 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1221         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1222 # else
1223         movdqa  (%rsi,%rdx), %xmm1
1224         TOLOWER (%xmm0, %xmm1)
1225         pcmpistri $0x1a, %xmm1, %xmm0
1226 # endif
1227         jbe     LABEL(use_sse4_2_exit)
1228 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1229         sub     $16, %r11
1230         jbe     LABEL(strcmp_exitz_sse4_2)
1231 # endif
1232         add     $16, %rdx
1233         jmp     LABEL(loop_ashr_9_use_sse4_2)
1234
1235         .p2align 4
1236 LABEL(nibble_ashr_9_use_sse4_2):
1237         sub     $0x1000, %r10
1238         movdqa  -16(%rdi, %rdx), %xmm0
1239         psrldq  $9, %xmm0
1240         pcmpistri      $0x3a,%xmm0, %xmm0
1241 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1242         cmp     %r11, %rcx
1243         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1244 # endif
1245         cmp     $6, %ecx
1246         ja      LABEL(loop_ashr_9_use_sse4_2)
1247
1248         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1249
1250 /*
1251  *  The following cases will be handled by ashr_10
1252  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1253  *        n(6~15)          n - 6                  9(15 +(n - 6) - n)         ashr_10
1254  */
1255         .p2align 4
1256 LABEL(ashr_10_sse4_2):
1257         pxor    %xmm0, %xmm0
1258         movdqa  (%rdi), %xmm2
1259         movdqa  (%rsi), %xmm1
1260         pcmpeqb %xmm1, %xmm0
1261         pslldq  $6, %xmm2
1262         TOLOWER (%xmm1, %xmm2)
1263         pcmpeqb %xmm1, %xmm2
1264         psubb   %xmm0, %xmm2
1265         pmovmskb %xmm2, %r9d
1266         shr     %cl, %edx
1267         shr     %cl, %r9d
1268         sub     %r9d, %edx
1269         jnz     LABEL(less32bytes_sse4_2)
1270         movdqa  (%rdi), %xmm3
1271
1272         UPDATE_STRNCMP_COUNTER
1273
1274         pxor    %xmm0, %xmm0
1275         mov     $16, %rcx       /* index for loads */
1276         mov     $10, %r9d       /* byte position left over from less32bytes case */
1277         /*
1278          * Setup %r10 value allows us to detect crossing a page boundary.
1279          * When %r10 goes positive we have crossed a page boundary and
1280          * need to do a nibble.
1281          */
1282         lea     10(%rdi), %r10
1283         and     $0xfff, %r10    /* offset into 4K page */
1284         sub     $0x1000, %r10   /* subtract 4K pagesize */
1285         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1286
1287         .p2align 4
1288 LABEL(loop_ashr_10_use_sse4_2):
1289         add     $16, %r10
1290         jg      LABEL(nibble_ashr_10_use_sse4_2)
1291
1292         movdqa  (%rdi, %rdx), %xmm0
1293         palignr $10, -16(%rdi, %rdx), %xmm0
1294 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1295         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1296 # else
1297         movdqa  (%rsi,%rdx), %xmm1
1298         TOLOWER (%xmm0, %xmm1)
1299         pcmpistri $0x1a, %xmm1, %xmm0
1300 # endif
1301         jbe     LABEL(use_sse4_2_exit)
1302 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1303         sub     $16, %r11
1304         jbe     LABEL(strcmp_exitz_sse4_2)
1305 # endif
1306
1307         add     $16, %rdx
1308         add     $16, %r10
1309         jg      LABEL(nibble_ashr_10_use_sse4_2)
1310
1311         movdqa  (%rdi, %rdx), %xmm0
1312         palignr $10, -16(%rdi, %rdx), %xmm0
1313 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1314         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1315 # else
1316         movdqa  (%rsi,%rdx), %xmm1
1317         TOLOWER (%xmm0, %xmm1)
1318         pcmpistri $0x1a, %xmm1, %xmm0
1319 # endif
1320         jbe     LABEL(use_sse4_2_exit)
1321 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1322         sub     $16, %r11
1323         jbe     LABEL(strcmp_exitz_sse4_2)
1324 # endif
1325         add     $16, %rdx
1326         jmp     LABEL(loop_ashr_10_use_sse4_2)
1327
1328         .p2align 4
1329 LABEL(nibble_ashr_10_use_sse4_2):
1330         sub     $0x1000, %r10
1331         movdqa  -16(%rdi, %rdx), %xmm0
1332         psrldq  $10, %xmm0
1333         pcmpistri      $0x3a,%xmm0, %xmm0
1334 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1335         cmp     %r11, %rcx
1336         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1337 # endif
1338         cmp     $5, %ecx
1339         ja      LABEL(loop_ashr_10_use_sse4_2)
1340
1341         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1342
1343 /*
1344  *  The following cases will be handled by ashr_11
1345  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1346  *        n(5~15)          n - 5                  10(15 +(n - 5) - n)         ashr_11
1347  */
1348         .p2align 4
1349 LABEL(ashr_11_sse4_2):
1350         pxor    %xmm0, %xmm0
1351         movdqa  (%rdi), %xmm2
1352         movdqa  (%rsi), %xmm1
1353         pcmpeqb %xmm1, %xmm0
1354         pslldq  $5, %xmm2
1355         TOLOWER (%xmm1, %xmm2)
1356         pcmpeqb %xmm1, %xmm2
1357         psubb   %xmm0, %xmm2
1358         pmovmskb %xmm2, %r9d
1359         shr     %cl, %edx
1360         shr     %cl, %r9d
1361         sub     %r9d, %edx
1362         jnz     LABEL(less32bytes_sse4_2)
1363         movdqa  (%rdi), %xmm3
1364
1365         UPDATE_STRNCMP_COUNTER
1366
1367         pxor    %xmm0, %xmm0
1368         mov     $16, %rcx       /* index for loads */
1369         mov     $11, %r9d       /* byte position left over from less32bytes case */
1370         /*
1371          * Setup %r10 value allows us to detect crossing a page boundary.
1372          * When %r10 goes positive we have crossed a page boundary and
1373          * need to do a nibble.
1374          */
1375         lea     11(%rdi), %r10
1376         and     $0xfff, %r10    /* offset into 4K page */
1377         sub     $0x1000, %r10   /* subtract 4K pagesize */
1378         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1379
1380         .p2align 4
1381 LABEL(loop_ashr_11_use_sse4_2):
1382         add     $16, %r10
1383         jg      LABEL(nibble_ashr_11_use_sse4_2)
1384
1385         movdqa  (%rdi, %rdx), %xmm0
1386         palignr $11, -16(%rdi, %rdx), %xmm0
1387 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1388         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1389 # else
1390         movdqa  (%rsi,%rdx), %xmm1
1391         TOLOWER (%xmm0, %xmm1)
1392         pcmpistri $0x1a, %xmm1, %xmm0
1393 # endif
1394         jbe     LABEL(use_sse4_2_exit)
1395 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1396         sub     $16, %r11
1397         jbe     LABEL(strcmp_exitz_sse4_2)
1398 # endif
1399
1400         add     $16, %rdx
1401         add     $16, %r10
1402         jg      LABEL(nibble_ashr_11_use_sse4_2)
1403
1404         movdqa  (%rdi, %rdx), %xmm0
1405         palignr $11, -16(%rdi, %rdx), %xmm0
1406 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1407         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1408 # else
1409         movdqa  (%rsi,%rdx), %xmm1
1410         TOLOWER (%xmm0, %xmm1)
1411         pcmpistri $0x1a, %xmm1, %xmm0
1412 # endif
1413         jbe     LABEL(use_sse4_2_exit)
1414 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1415         sub     $16, %r11
1416         jbe     LABEL(strcmp_exitz_sse4_2)
1417 # endif
1418         add     $16, %rdx
1419         jmp     LABEL(loop_ashr_11_use_sse4_2)
1420
1421         .p2align 4
1422 LABEL(nibble_ashr_11_use_sse4_2):
1423         sub     $0x1000, %r10
1424         movdqa  -16(%rdi, %rdx), %xmm0
1425         psrldq  $11, %xmm0
1426         pcmpistri      $0x3a,%xmm0, %xmm0
1427 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1428         cmp     %r11, %rcx
1429         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1430 # endif
1431         cmp     $4, %ecx
1432         ja      LABEL(loop_ashr_11_use_sse4_2)
1433
1434         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1435
1436 /*
1437  *  The following cases will be handled by ashr_12
1438  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1439  *        n(4~15)          n - 4                  11(15 +(n - 4) - n)         ashr_12
1440  */
1441         .p2align 4
1442 LABEL(ashr_12_sse4_2):
1443         pxor    %xmm0, %xmm0
1444         movdqa  (%rdi), %xmm2
1445         movdqa  (%rsi), %xmm1
1446         pcmpeqb %xmm1, %xmm0
1447         pslldq  $4, %xmm2
1448         TOLOWER (%xmm1, %xmm2)
1449         pcmpeqb %xmm1, %xmm2
1450         psubb   %xmm0, %xmm2
1451         pmovmskb %xmm2, %r9d
1452         shr     %cl, %edx
1453         shr     %cl, %r9d
1454         sub     %r9d, %edx
1455         jnz     LABEL(less32bytes_sse4_2)
1456         movdqa  (%rdi), %xmm3
1457
1458         UPDATE_STRNCMP_COUNTER
1459
1460         pxor    %xmm0, %xmm0
1461         mov     $16, %rcx       /* index for loads */
1462         mov     $12, %r9d       /* byte position left over from less32bytes case */
1463         /*
1464          * Setup %r10 value allows us to detect crossing a page boundary.
1465          * When %r10 goes positive we have crossed a page boundary and
1466          * need to do a nibble.
1467          */
1468         lea     12(%rdi), %r10
1469         and     $0xfff, %r10    /* offset into 4K page */
1470         sub     $0x1000, %r10   /* subtract 4K pagesize */
1471         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1472
1473         .p2align 4
1474 LABEL(loop_ashr_12_use_sse4_2):
1475         add     $16, %r10
1476         jg      LABEL(nibble_ashr_12_use_sse4_2)
1477
1478         movdqa  (%rdi, %rdx), %xmm0
1479         palignr $12, -16(%rdi, %rdx), %xmm0
1480 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1481         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1482 # else
1483         movdqa  (%rsi,%rdx), %xmm1
1484         TOLOWER (%xmm0, %xmm1)
1485         pcmpistri $0x1a, %xmm1, %xmm0
1486 # endif
1487         jbe     LABEL(use_sse4_2_exit)
1488 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1489         sub     $16, %r11
1490         jbe     LABEL(strcmp_exitz_sse4_2)
1491 # endif
1492
1493         add     $16, %rdx
1494         add     $16, %r10
1495         jg      LABEL(nibble_ashr_12_use_sse4_2)
1496
1497         movdqa  (%rdi, %rdx), %xmm0
1498         palignr $12, -16(%rdi, %rdx), %xmm0
1499 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1500         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1501 # else
1502         movdqa  (%rsi,%rdx), %xmm1
1503         TOLOWER (%xmm0, %xmm1)
1504         pcmpistri $0x1a, %xmm1, %xmm0
1505 # endif
1506         jbe     LABEL(use_sse4_2_exit)
1507 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1508         sub     $16, %r11
1509         jbe     LABEL(strcmp_exitz_sse4_2)
1510 # endif
1511         add     $16, %rdx
1512         jmp     LABEL(loop_ashr_12_use_sse4_2)
1513
1514         .p2align 4
1515 LABEL(nibble_ashr_12_use_sse4_2):
1516         sub     $0x1000, %r10
1517         movdqa  -16(%rdi, %rdx), %xmm0
1518         psrldq  $12, %xmm0
1519         pcmpistri      $0x3a,%xmm0, %xmm0
1520 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1521         cmp     %r11, %rcx
1522         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1523 # endif
1524         cmp     $3, %ecx
1525         ja      LABEL(loop_ashr_12_use_sse4_2)
1526
1527         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1528
1529 /*
1530  *  The following cases will be handled by ashr_13
1531  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1532  *        n(3~15)          n - 3                  12(15 +(n - 3) - n)         ashr_13
1533  */
1534         .p2align 4
1535 LABEL(ashr_13_sse4_2):
1536         pxor    %xmm0, %xmm0
1537         movdqa  (%rdi), %xmm2
1538         movdqa  (%rsi), %xmm1
1539         pcmpeqb %xmm1, %xmm0
1540         pslldq  $3, %xmm2
1541         TOLOWER (%xmm1, %xmm2)
1542         pcmpeqb %xmm1, %xmm2
1543         psubb   %xmm0, %xmm2
1544         pmovmskb %xmm2, %r9d
1545         shr     %cl, %edx
1546         shr     %cl, %r9d
1547         sub     %r9d, %edx
1548         jnz     LABEL(less32bytes_sse4_2)
1549         movdqa  (%rdi), %xmm3
1550
1551         UPDATE_STRNCMP_COUNTER
1552
1553         pxor    %xmm0, %xmm0
1554         mov     $16, %rcx       /* index for loads */
1555         mov     $13, %r9d       /* byte position left over from less32bytes case */
1556         /*
1557          * Setup %r10 value allows us to detect crossing a page boundary.
1558          * When %r10 goes positive we have crossed a page boundary and
1559          * need to do a nibble.
1560          */
1561         lea     13(%rdi), %r10
1562         and     $0xfff, %r10    /* offset into 4K page */
1563         sub     $0x1000, %r10   /* subtract 4K pagesize */
1564
1565         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1566
1567         .p2align 4
1568 LABEL(loop_ashr_13_use_sse4_2):
1569         add     $16, %r10
1570         jg      LABEL(nibble_ashr_13_use_sse4_2)
1571
1572         movdqa  (%rdi, %rdx), %xmm0
1573         palignr $13, -16(%rdi, %rdx), %xmm0
1574 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1575         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1576 # else
1577         movdqa  (%rsi,%rdx), %xmm1
1578         TOLOWER (%xmm0, %xmm1)
1579         pcmpistri $0x1a, %xmm1, %xmm0
1580 # endif
1581         jbe     LABEL(use_sse4_2_exit)
1582 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1583         sub     $16, %r11
1584         jbe     LABEL(strcmp_exitz_sse4_2)
1585 # endif
1586
1587         add     $16, %rdx
1588         add     $16, %r10
1589         jg      LABEL(nibble_ashr_13_use_sse4_2)
1590
1591         movdqa  (%rdi, %rdx), %xmm0
1592         palignr $13, -16(%rdi, %rdx), %xmm0
1593 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1594         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1595 # else
1596         movdqa  (%rsi,%rdx), %xmm1
1597         TOLOWER (%xmm0, %xmm1)
1598         pcmpistri $0x1a, %xmm1, %xmm0
1599 # endif
1600         jbe     LABEL(use_sse4_2_exit)
1601 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1602         sub     $16, %r11
1603         jbe     LABEL(strcmp_exitz_sse4_2)
1604 # endif
1605         add     $16, %rdx
1606         jmp     LABEL(loop_ashr_13_use_sse4_2)
1607
1608         .p2align 4
1609 LABEL(nibble_ashr_13_use_sse4_2):
1610         sub     $0x1000, %r10
1611         movdqa  -16(%rdi, %rdx), %xmm0
1612         psrldq  $13, %xmm0
1613         pcmpistri      $0x3a,%xmm0, %xmm0
1614 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1615         cmp     %r11, %rcx
1616         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1617 # endif
1618         cmp     $2, %ecx
1619         ja      LABEL(loop_ashr_13_use_sse4_2)
1620
1621         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1622
1623 /*
1624  *  The following cases will be handled by ashr_14
1625  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1626  *        n(2~15)          n - 2                  13(15 +(n - 2) - n)         ashr_14
1627  */
1628         .p2align 4
1629 LABEL(ashr_14_sse4_2):
1630         pxor    %xmm0, %xmm0
1631         movdqa  (%rdi), %xmm2
1632         movdqa  (%rsi), %xmm1
1633         pcmpeqb %xmm1, %xmm0
1634         pslldq  $2, %xmm2
1635         TOLOWER (%xmm1, %xmm2)
1636         pcmpeqb %xmm1, %xmm2
1637         psubb   %xmm0, %xmm2
1638         pmovmskb %xmm2, %r9d
1639         shr     %cl, %edx
1640         shr     %cl, %r9d
1641         sub     %r9d, %edx
1642         jnz     LABEL(less32bytes_sse4_2)
1643         movdqa  (%rdi), %xmm3
1644
1645         UPDATE_STRNCMP_COUNTER
1646
1647         pxor    %xmm0, %xmm0
1648         mov     $16, %rcx       /* index for loads */
1649         mov     $14, %r9d       /* byte position left over from less32bytes case */
1650         /*
1651          * Setup %r10 value allows us to detect crossing a page boundary.
1652          * When %r10 goes positive we have crossed a page boundary and
1653          * need to do a nibble.
1654          */
1655         lea     14(%rdi), %r10
1656         and     $0xfff, %r10    /* offset into 4K page */
1657         sub     $0x1000, %r10   /* subtract 4K pagesize */
1658
1659         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1660
1661         .p2align 4
1662 LABEL(loop_ashr_14_use_sse4_2):
1663         add     $16, %r10
1664         jg      LABEL(nibble_ashr_14_use_sse4_2)
1665
1666         movdqa  (%rdi, %rdx), %xmm0
1667         palignr $14, -16(%rdi, %rdx), %xmm0
1668 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1669         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1670 # else
1671         movdqa  (%rsi,%rdx), %xmm1
1672         TOLOWER (%xmm0, %xmm1)
1673         pcmpistri $0x1a, %xmm1, %xmm0
1674 # endif
1675         jbe     LABEL(use_sse4_2_exit)
1676 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1677         sub     $16, %r11
1678         jbe     LABEL(strcmp_exitz_sse4_2)
1679 # endif
1680
1681         add     $16, %rdx
1682         add     $16, %r10
1683         jg      LABEL(nibble_ashr_14_use_sse4_2)
1684
1685         movdqa  (%rdi, %rdx), %xmm0
1686         palignr $14, -16(%rdi, %rdx), %xmm0
1687 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1688         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1689 # else
1690         movdqa  (%rsi,%rdx), %xmm1
1691         TOLOWER (%xmm0, %xmm1)
1692         pcmpistri $0x1a, %xmm1, %xmm0
1693 # endif
1694         jbe     LABEL(use_sse4_2_exit)
1695 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1696         sub     $16, %r11
1697         jbe     LABEL(strcmp_exitz_sse4_2)
1698 # endif
1699         add     $16, %rdx
1700         jmp     LABEL(loop_ashr_14_use_sse4_2)
1701
1702         .p2align 4
1703 LABEL(nibble_ashr_14_use_sse4_2):
1704         sub     $0x1000, %r10
1705         movdqa  -16(%rdi, %rdx), %xmm0
1706         psrldq  $14, %xmm0
1707         pcmpistri      $0x3a,%xmm0, %xmm0
1708 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1709         cmp     %r11, %rcx
1710         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1711 # endif
1712         cmp     $1, %ecx
1713         ja      LABEL(loop_ashr_14_use_sse4_2)
1714
1715         jmp     LABEL(nibble_ashr_use_sse4_2_exit)
1716
1717 /*
1718  *  The following cases will be handled by ashr_15
1719  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1720  *        n(1~15)          n - 1                  14(15 +(n - 1) - n)         ashr_15
1721  */
1722         .p2align 4
1723 LABEL(ashr_15_sse4_2):
1724         pxor    %xmm0, %xmm0
1725         movdqa  (%rdi), %xmm2
1726         movdqa  (%rsi), %xmm1
1727         pcmpeqb %xmm1, %xmm0
1728         pslldq  $1, %xmm2
1729         TOLOWER (%xmm1, %xmm2)
1730         pcmpeqb %xmm1, %xmm2
1731         psubb   %xmm0, %xmm2
1732         pmovmskb %xmm2, %r9d
1733         shr     %cl, %edx
1734         shr     %cl, %r9d
1735         sub     %r9d, %edx
1736         jnz     LABEL(less32bytes_sse4_2)
1737
1738         movdqa  (%rdi), %xmm3
1739
1740         UPDATE_STRNCMP_COUNTER
1741
1742         pxor    %xmm0, %xmm0
1743         mov     $16, %rcx       /* index for loads */
1744         mov     $15, %r9d       /* byte position left over from less32bytes case */
1745         /*
1746          * Setup %r10 value allows us to detect crossing a page boundary.
1747          * When %r10 goes positive we have crossed a page boundary and
1748          * need to do a nibble.
1749          */
1750         lea     15(%rdi), %r10
1751         and     $0xfff, %r10    /* offset into 4K page */
1752
1753         sub     $0x1000, %r10   /* subtract 4K pagesize */
1754
1755         mov     %rcx, %rdx      /* only for offset of sse4 instruction loop*/
1756
1757         .p2align 4
1758 LABEL(loop_ashr_15_use_sse4_2):
1759         add     $16, %r10
1760         jg      LABEL(nibble_ashr_15_use_sse4_2)
1761
1762         movdqa  (%rdi, %rdx), %xmm0
1763         palignr $15, -16(%rdi, %rdx), %xmm0
1764 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1765         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1766 # else
1767         movdqa  (%rsi,%rdx), %xmm1
1768         TOLOWER (%xmm0, %xmm1)
1769         pcmpistri $0x1a, %xmm1, %xmm0
1770 # endif
1771         jbe     LABEL(use_sse4_2_exit)
1772 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1773         sub     $16, %r11
1774         jbe     LABEL(strcmp_exitz_sse4_2)
1775 # endif
1776
1777         add     $16, %rdx
1778         add     $16, %r10
1779         jg      LABEL(nibble_ashr_15_use_sse4_2)
1780
1781         movdqa  (%rdi, %rdx), %xmm0
1782         palignr $15, -16(%rdi, %rdx), %xmm0
1783 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1784         pcmpistri $0x1a, (%rsi,%rdx), %xmm0
1785 # else
1786         movdqa  (%rsi,%rdx), %xmm1
1787         TOLOWER (%xmm0, %xmm1)
1788         pcmpistri $0x1a, %xmm1, %xmm0
1789 # endif
1790         jbe     LABEL(use_sse4_2_exit)
1791 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1792         sub     $16, %r11
1793         jbe     LABEL(strcmp_exitz_sse4_2)
1794 # endif
1795         add     $16, %rdx
1796         jmp     LABEL(loop_ashr_15_use_sse4_2)
1797
1798         .p2align 4
1799 LABEL(nibble_ashr_15_use_sse4_2):
1800         sub     $0x1000, %r10
1801         movdqa  -16(%rdi, %rdx), %xmm0
1802         psrldq  $15, %xmm0
1803         pcmpistri      $0x3a,%xmm0, %xmm0
1804 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1805         cmp     %r11, %rcx
1806         jae     LABEL(nibble_ashr_use_sse4_2_exit)
1807 # endif
1808         cmp     $0, %ecx
1809         ja      LABEL(loop_ashr_15_use_sse4_2)
1810
1811 LABEL(nibble_ashr_use_sse4_2_exit):
1812 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
1813         pcmpistri      $0x1a,(%rsi,%rdx), %xmm0
1814 # else
1815         movdqa  (%rsi,%rdx), %xmm1
1816         TOLOWER (%xmm0, %xmm1)
1817         pcmpistri $0x1a, %xmm1, %xmm0
1818 # endif
1819         .p2align 4
1820 LABEL(use_sse4_2_exit):
1821         jnc     LABEL(strcmp_exitz_sse4_2)
1822 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1823         sub     %rcx, %r11
1824         jbe     LABEL(strcmp_exitz_sse4_2)
1825 # endif
1826         add     %rcx, %rdx
1827         lea     -16(%rdi, %r9), %rdi
1828         movzbl  (%rdi, %rdx), %eax
1829         movzbl  (%rsi, %rdx), %edx
1830         test    %r8d, %r8d
1831         jz      LABEL(use_sse4_2_ret_sse4_2)
1832         xchg    %eax, %edx
1833 LABEL(use_sse4_2_ret_sse4_2):
1834 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
1835         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rcx
1836         movl    (%rcx,%rdx,4), %edx
1837         movl    (%rcx,%rax,4), %eax
1838 # endif
1839
1840         sub     %edx, %eax
1841         ret
1842
1843 LABEL(less32bytes_sse4_2):
1844         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
1845         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
1846         test    %r8d, %r8d
1847         jz      LABEL(ret_sse4_2)
1848         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
1849
1850         .p2align 4
1851 LABEL(ret_sse4_2):
1852 LABEL(less16bytes_sse4_2):
1853         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
1854
1855 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1856         sub     %rdx, %r11
1857         jbe     LABEL(strcmp_exitz_sse4_2)
1858 # endif
1859         movzbl  (%rsi, %rdx), %ecx
1860         movzbl  (%rdi, %rdx), %eax
1861
1862 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
1863         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
1864         movl    (%rdx,%rcx,4), %ecx
1865         movl    (%rdx,%rax,4), %eax
1866 # endif
1867
1868         sub     %ecx, %eax
1869         ret
1870
1871 LABEL(strcmp_exitz_sse4_2):
1872         xor     %eax, %eax
1873         ret
1874
1875         .p2align 4
1876         // XXX Same as code above
1877 LABEL(Byte0_sse4_2):
1878         movzx   (%rsi), %ecx
1879         movzx   (%rdi), %eax
1880
1881 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
1882         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
1883         movl    (%rdx,%rcx,4), %ecx
1884         movl    (%rdx,%rax,4), %eax
1885 # endif
1886
1887         sub     %ecx, %eax
1888         ret
1889         cfi_endproc
1890         .size   STRCMP_SSE42, .-STRCMP_SSE42
1891
1892 # undef UCLOW_reg
1893 # undef UCHIGH_reg
1894 # undef LCQWORD_reg
1895 # undef TOLOWER
1896
1897         /* Put all SSE 4.2 functions together.  */
1898         .section .rodata.sse4.2,"a",@progbits
1899         .p2align 3
1900 LABEL(unaligned_table_sse4_2):
1901         .int    LABEL(ashr_1_sse4_2) - LABEL(unaligned_table_sse4_2)
1902         .int    LABEL(ashr_2_sse4_2) - LABEL(unaligned_table_sse4_2)
1903         .int    LABEL(ashr_3_sse4_2) - LABEL(unaligned_table_sse4_2)
1904         .int    LABEL(ashr_4_sse4_2) - LABEL(unaligned_table_sse4_2)
1905         .int    LABEL(ashr_5_sse4_2) - LABEL(unaligned_table_sse4_2)
1906         .int    LABEL(ashr_6_sse4_2) - LABEL(unaligned_table_sse4_2)
1907         .int    LABEL(ashr_7_sse4_2) - LABEL(unaligned_table_sse4_2)
1908         .int    LABEL(ashr_8_sse4_2) - LABEL(unaligned_table_sse4_2)
1909         .int    LABEL(ashr_9_sse4_2) - LABEL(unaligned_table_sse4_2)
1910         .int    LABEL(ashr_10_sse4_2) - LABEL(unaligned_table_sse4_2)
1911         .int    LABEL(ashr_11_sse4_2) - LABEL(unaligned_table_sse4_2)
1912         .int    LABEL(ashr_12_sse4_2) - LABEL(unaligned_table_sse4_2)
1913         .int    LABEL(ashr_13_sse4_2) - LABEL(unaligned_table_sse4_2)
1914         .int    LABEL(ashr_14_sse4_2) - LABEL(unaligned_table_sse4_2)
1915         .int    LABEL(ashr_15_sse4_2) - LABEL(unaligned_table_sse4_2)
1916         .int    LABEL(ashr_0_sse4_2) - LABEL(unaligned_table_sse4_2)
1917
1918
1919 # undef ENTRY
1920 # define ENTRY(name) \
1921         .type STRCMP_SSE2, @function; \
1922         .align 16; \
1923         STRCMP_SSE2: cfi_startproc; \
1924         CALL_MCOUNT
1925 # undef END
1926 # define END(name) \
1927         cfi_endproc; .size STRCMP_SSE2, .-STRCMP_SSE2
1928
1929 # ifdef USE_AS_STRCASECMP_L
1930 #  define ENTRY2(name) \
1931         .type __strcasecmp_sse2, @function; \
1932         .align 16; \
1933         __strcasecmp_sse2: cfi_startproc; \
1934         CALL_MCOUNT
1935 #  define END2(name) \
1936         cfi_endproc; .size __strcasecmp_sse2, .-__strcasecmp_sse2
1937 # endif
1938
1939 # ifdef USE_AS_STRNCASECMP_L
1940 #  define ENTRY2(name) \
1941         .type __strncasecmp_sse2, @function; \
1942         .align 16; \
1943         __strncasecmp_sse2: cfi_startproc; \
1944         CALL_MCOUNT
1945 #  define END2(name) \
1946         cfi_endproc; .size __strncasecmp_sse2, .-__strncasecmp_sse2
1947 # endif
1948
1949 # undef libc_hidden_builtin_def
1950 /* It doesn't make sense to send libc-internal strcmp calls through a PLT.
1951    The speedup we get from using SSE4.2 instruction is likely eaten away
1952    by the indirect call in the PLT.  */
1953 # define libc_hidden_builtin_def(name) \
1954         .globl __GI_STRCMP; __GI_STRCMP = STRCMP_SSE2
1955 #endif
1956
1957 #include "../strcmp.S"