Add optimized strncasecmp versions for x86-64.
[glibc.git] / sysdeps / x86_64 / strcmp.S
blob5a4346be05839482d3cc72e32897ed5aee30ff90
1 /* Highly optimized version for x86-64.
2    Copyright (C) 1999, 2000, 2002, 2003, 2005, 2009, 2010
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Based on i686 version contributed by Ulrich Drepper
6    <drepper@cygnus.com>, 1999.
7    Updated with SSE2 support contributed by Intel Corporation.
9    The GNU C Library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 2.1 of the License, or (at your option) any later version.
14    The GNU C Library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Lesser General Public License for more details.
19    You should have received a copy of the GNU Lesser General Public
20    License along with the GNU C Library; if not, write to the Free
21    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22    02111-1307 USA.  */
24 #include <sysdep.h>
25 #include "asm-syntax.h"
26 #include "bp-sym.h"
27 #include "bp-asm.h"
29 #undef UPDATE_STRNCMP_COUNTER
31 #ifndef LABEL
32 #define LABEL(l) L(l)
33 #endif
35 #ifdef USE_AS_STRNCMP
36 /* The simplified code below is not set up to handle strncmp() so far.
37    Should this become necessary it has to be implemented.  For now
38    just report the problem.  */
39 # ifdef NOT_IN_lib
40 #  error "strncmp not implemented so far"
41 # endif
43 /* Since the counter, %r11, is unsigned, we branch to strcmp_exitz
44    if the new counter > the old one or is 0.  */
45 # define UPDATE_STRNCMP_COUNTER                         \
46         /* calculate left number to compare */          \
47         lea     -16(%rcx, %r11), %r9;                   \
48         cmp     %r9, %r11;                              \
49         jb      LABEL(strcmp_exitz);                    \
50         test    %r9, %r9;                               \
51         je      LABEL(strcmp_exitz);                    \
52         mov     %r9, %r11
54 #elif defined USE_AS_STRCASECMP_L
55 # include "locale-defines.h"
57 /* No support for strcasecmp outside libc so far since it is not needed.  */
58 # ifdef NOT_IN_lib
59 #  error "strcasecmp_l not implemented so far"
60 # endif
62 # define UPDATE_STRNCMP_COUNTER
63 #elif defined USE_AS_STRNCASECMP_L
64 # include "locale-defines.h"
66 /* No support for strncasecmp outside libc so far since it is not needed.  */
67 # ifdef NOT_IN_lib
68 #  error "strncasecmp_l not implemented so far"
69 # endif
71 # define UPDATE_STRNCMP_COUNTER                         \
72         /* calculate left number to compare */          \
73         lea     -16(%rcx, %r11), %r9;                   \
74         cmp     %r9, %r11;                              \
75         jb      LABEL(strcmp_exitz);                    \
76         test    %r9, %r9;                               \
77         je      LABEL(strcmp_exitz);                    \
78         mov     %r9, %r11
79 #else
80 # define UPDATE_STRNCMP_COUNTER
81 # ifndef STRCMP
82 #  define STRCMP strncasecmp
83 # endif
84 #endif
86 #ifndef USE_SSSE3
87         .text
88 #else
89         .section .text.ssse3,"ax",@progbits
90 #endif
92 #ifdef USE_AS_STRCASECMP_L
93 # ifndef ENTRY2
94 #  define ENTRY2(name) ENTRY (name)
95 #  define END2(name) END (name)
96 # endif
98 ENTRY2 (__strcasecmp)
99         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
100         movq    %fs:(%rax),%rdx
102         // XXX 5 byte should be before the function
103         /* 5-byte NOP.  */
104         .byte   0x0f,0x1f,0x44,0x00,0x00
105 END2 (__strcasecmp)
106 # ifndef NO_NOLOCALE_ALIAS
107 weak_alias (__strcasecmp, strcasecmp)
108 libc_hidden_def (__strcasecmp)
109 # endif
110         /* FALLTHROUGH to strcasecmp_l.  */
111 #elif defined USE_AS_STRNCASECMP_L
112 # ifndef ENTRY2
113 #  define ENTRY2(name) ENTRY (name)
114 #  define END2(name) END (name)
115 # endif
117 ENTRY2 (__strncasecmp)
118         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
119         movq    %fs:(%rax),%r10
121         // XXX 5 byte should be before the function
122         /* 5-byte NOP.  */
123         .byte   0x0f,0x1f,0x44,0x00,0x00
124 END2 (__strncasecmp)
125 # ifndef NO_NOLOCALE_ALIAS
126 weak_alias (__strncasecmp, strncasecmp)
127 libc_hidden_def (__strncasecmp)
128 # endif
129         /* FALLTHROUGH to strncasecmp_l.  */
130 #endif
132 ENTRY (BP_SYM (STRCMP))
133 #ifdef NOT_IN_libc
134 /* Simple version since we can't use SSE registers in ld.so.  */
135 L(oop): movb    (%rdi), %al
136         cmpb    (%rsi), %al
137         jne     L(neq)
138         incq    %rdi
139         incq    %rsi
140         testb   %al, %al
141         jnz     L(oop)
143         xorl    %eax, %eax
144         ret
146 L(neq): movl    $1, %eax
147         movl    $-1, %ecx
148         cmovbl  %ecx, %eax
149         ret
150 END (BP_SYM (STRCMP))
151 #else   /* NOT_IN_libc */
152 # ifdef USE_AS_STRCASECMP_L
153         /* We have to fall back on the C implementation for locales
154            with encodings not matching ASCII for single bytes.  */
155 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
156         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%rdx), %rax
157 #  else
158         movq    (%rdx), %rax
159 #  endif
160         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
161         jne     __strcasecmp_l_nonascii
162 # elif defined USE_AS_STRNCASECMP_L
163         /* We have to fall back on the C implementation for locales
164            with encodings not matching ASCII for single bytes.  */
165 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
166         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%r10), %rax
167 #  else
168         movq    (%r10), %rax
169 #  endif
170         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
171         jne     __strncasecmp_l_nonascii
172 # endif
175  * This implementation uses SSE to compare up to 16 bytes at a time.
176  */
177 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
178         test    %rdx, %rdx
179         je      LABEL(strcmp_exitz)
180         cmp     $1, %rdx
181         je      LABEL(Byte0)
182         mov     %rdx, %r11
183 # endif
184         mov     %esi, %ecx
185         mov     %edi, %eax
186 /* Use 64bit AND here to avoid long NOP padding.  */
187         and     $0x3f, %rcx             /* rsi alignment in cache line */
188         and     $0x3f, %rax             /* rdi alignment in cache line */
189 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
190         .section .rodata.cst16,"aM",@progbits,16
191         .align 16
192 .Lbelowupper:
193         .quad   0x4040404040404040
194         .quad   0x4040404040404040
195 .Ltopupper:
196         .quad   0x5b5b5b5b5b5b5b5b
197         .quad   0x5b5b5b5b5b5b5b5b
198 .Ltouppermask:
199         .quad   0x2020202020202020
200         .quad   0x2020202020202020
201         .previous
202         movdqa  .Lbelowupper(%rip), %xmm5
203 #  define UCLOW_reg %xmm5
204         movdqa  .Ltopupper(%rip), %xmm6
205 #  define UCHIGH_reg %xmm6
206         movdqa  .Ltouppermask(%rip), %xmm7
207 #  define LCQWORD_reg %xmm7
208 # endif
209         cmp     $0x30, %ecx
210         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
211         cmp     $0x30, %eax
212         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
213         movlpd  (%rdi), %xmm1
214         movlpd  (%rsi), %xmm2
215         movhpd  8(%rdi), %xmm1
216         movhpd  8(%rsi), %xmm2
217 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
218 #  define TOLOWER(reg1, reg2) \
219         movdqa  reg1, %xmm8;                                    \
220         movdqa  UCHIGH_reg, %xmm9;                              \
221         movdqa  reg2, %xmm10;                                   \
222         movdqa  UCHIGH_reg, %xmm11;                             \
223         pcmpgtb UCLOW_reg, %xmm8;                               \
224         pcmpgtb reg1, %xmm9;                                    \
225         pcmpgtb UCLOW_reg, %xmm10;                              \
226         pcmpgtb reg2, %xmm11;                                   \
227         pand    %xmm9, %xmm8;                                   \
228         pand    %xmm11, %xmm10;                                 \
229         pand    LCQWORD_reg, %xmm8;                             \
230         pand    LCQWORD_reg, %xmm10;                            \
231         por     %xmm8, reg1;                                    \
232         por     %xmm10, reg2
233         TOLOWER (%xmm1, %xmm2)
234 # else
235 #  define TOLOWER(reg1, reg2)
236 # endif
237         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
238         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
239         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
240         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
241         pmovmskb %xmm1, %edx
242         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
243         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
244 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
245         sub     $16, %r11
246         jbe     LABEL(strcmp_exitz)     /* finish comparision */
247 # endif
248         add     $16, %rsi               /* prepare to search next 16 bytes */
249         add     $16, %rdi               /* prepare to search next 16 bytes */
251         /*
252          * Determine source and destination string offsets from 16-byte alignment.
253          * Use relative offset difference between the two to determine which case
254          * below to use.
255          */
256         .p2align 4
257 LABEL(crosscache):
258         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
259         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
260         mov     $0xffff, %edx                   /* for equivalent offset */
261         xor     %r8d, %r8d
262         and     $0xf, %ecx                      /* offset of rsi */
263         and     $0xf, %eax                      /* offset of rdi */
264         cmp     %eax, %ecx
265         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
266         ja      LABEL(bigger)
267         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
268         xchg    %ecx, %eax
269         xchg    %rsi, %rdi
270 LABEL(bigger):
271         lea     15(%rax), %r9
272         sub     %rcx, %r9
273         lea     LABEL(unaligned_table)(%rip), %r10
274         movslq  (%r10, %r9,4), %r9
275         lea     (%r10, %r9), %r10
276         jmp     *%r10                           /* jump to corresponding case */
279  * The following cases will be handled by ashr_0
280  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
281  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
282  */
283         .p2align 4
284 LABEL(ashr_0):
286         movdqa  (%rsi), %xmm1
287         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
288         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
289 # if !defined USE_AS_STRCASECMP_L && !defined USE_AS_STRNCASECMP_L
290         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
291 # else
292         movdqa  (%rdi), %xmm2
293         TOLOWER (%xmm1, %xmm2)
294         pcmpeqb %xmm2, %xmm1                    /* compare 16 bytes for equality */
295 # endif
296         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
297         pmovmskb %xmm1, %r9d
298         shr     %cl, %edx                       /* adjust 0xffff for offset */
299         shr     %cl, %r9d                       /* adjust for 16-byte offset */
300         sub     %r9d, %edx
301         /*
302          * edx must be the same with r9d if in left byte (16-rcx) is equal to
303          * the start from (16-rax) and no null char was seen.
304          */
305         jne     LABEL(less32bytes)              /* mismatch or null char */
306         UPDATE_STRNCMP_COUNTER
307         mov     $16, %rcx
308         mov     $16, %r9
309         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
311         /*
312          * Now both strings are aligned at 16-byte boundary. Loop over strings
313          * checking 32-bytes per iteration.
314          */
315         .p2align 4
316 LABEL(loop_ashr_0):
317         movdqa  (%rsi, %rcx), %xmm1
318         movdqa  (%rdi, %rcx), %xmm2
319         TOLOWER (%xmm1, %xmm2)
321         pcmpeqb %xmm1, %xmm0
322         pcmpeqb %xmm2, %xmm1
323         psubb   %xmm0, %xmm1
324         pmovmskb %xmm1, %edx
325         sub     $0xffff, %edx
326         jnz     LABEL(exit)             /* mismatch or null char seen */
328 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
329         sub     $16, %r11
330         jbe     LABEL(strcmp_exitz)
331 # endif
332         add     $16, %rcx
333         movdqa  (%rsi, %rcx), %xmm1
334         movdqa  (%rdi, %rcx), %xmm2
335         TOLOWER (%xmm1, %xmm2)
337         pcmpeqb %xmm1, %xmm0
338         pcmpeqb %xmm2, %xmm1
339         psubb   %xmm0, %xmm1
340         pmovmskb %xmm1, %edx
341         sub     $0xffff, %edx
342         jnz     LABEL(exit)
343 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
344         sub     $16, %r11
345         jbe     LABEL(strcmp_exitz)
346 # endif
347         add     $16, %rcx
348         jmp     LABEL(loop_ashr_0)
351  * The following cases will be handled by ashr_1
352  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
353  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
354  */
355         .p2align 4
356 LABEL(ashr_1):
357         pxor    %xmm0, %xmm0
358         movdqa  (%rdi), %xmm2
359         movdqa  (%rsi), %xmm1
360         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
361         pslldq  $15, %xmm2              /* shift first string to align with second */
362         TOLOWER (%xmm1, %xmm2)
363         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
364         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
365         pmovmskb %xmm2, %r9d
366         shr     %cl, %edx               /* adjust 0xffff for offset */
367         shr     %cl, %r9d               /* adjust for 16-byte offset */
368         sub     %r9d, %edx
369         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
370         movdqa  (%rdi), %xmm3
371         UPDATE_STRNCMP_COUNTER
373         pxor    %xmm0, %xmm0
374         mov     $16, %rcx               /* index for loads*/
375         mov     $1, %r9d                /* byte position left over from less32bytes case */
376         /*
377          * Setup %r10 value allows us to detect crossing a page boundary.
378          * When %r10 goes positive we have crossed a page boundary and
379          * need to do a nibble.
380          */
381         lea     1(%rdi), %r10
382         and     $0xfff, %r10            /* offset into 4K page */
383         sub     $0x1000, %r10           /* subtract 4K pagesize */
385         .p2align 4
386 LABEL(loop_ashr_1):
387         add     $16, %r10
388         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
390 LABEL(gobble_ashr_1):
391         movdqa  (%rsi, %rcx), %xmm1
392         movdqa  (%rdi, %rcx), %xmm2
393         movdqa  %xmm2, %xmm4             /* store for next cycle */
395 # ifndef USE_SSSE3
396         psrldq  $1, %xmm3
397         pslldq  $15, %xmm2
398         por     %xmm3, %xmm2            /* merge into one 16byte value */
399 # else
400         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
401 # endif
402         TOLOWER (%xmm1, %xmm2)
404         pcmpeqb %xmm1, %xmm0
405         pcmpeqb %xmm2, %xmm1
406         psubb   %xmm0, %xmm1
407         pmovmskb %xmm1, %edx
408         sub     $0xffff, %edx
409         jnz     LABEL(exit)
411 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
412         sub     $16, %r11
413         jbe     LABEL(strcmp_exitz)
414 # endif
415         add     $16, %rcx
416         movdqa  %xmm4, %xmm3
418         add     $16, %r10
419         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
421         movdqa  (%rsi, %rcx), %xmm1
422         movdqa  (%rdi, %rcx), %xmm2
423         movdqa  %xmm2, %xmm4            /* store for next cycle */
425 # ifndef USE_SSSE3
426         psrldq  $1, %xmm3
427         pslldq  $15, %xmm2
428         por     %xmm3, %xmm2            /* merge into one 16byte value */
429 # else
430         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
431 # endif
432         TOLOWER (%xmm1, %xmm2)
434         pcmpeqb %xmm1, %xmm0
435         pcmpeqb %xmm2, %xmm1
436         psubb   %xmm0, %xmm1
437         pmovmskb %xmm1, %edx
438         sub     $0xffff, %edx
439         jnz     LABEL(exit)
441 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
442         sub     $16, %r11
443         jbe     LABEL(strcmp_exitz)
444 # endif
445         add     $16, %rcx
446         movdqa  %xmm4, %xmm3
447         jmp     LABEL(loop_ashr_1)
449         /*
450          * Nibble avoids loads across page boundary. This is to avoid a potential
451          * access into unmapped memory.
452          */
453         .p2align 4
454 LABEL(nibble_ashr_1):
455         pcmpeqb %xmm3, %xmm0             /* check nibble for null char*/
456         pmovmskb %xmm0, %edx
457         test    $0xfffe, %edx
458         jnz     LABEL(ashr_1_exittail)  /* find null char*/
460 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
461         cmp     $14, %r11
462         jbe     LABEL(ashr_1_exittail)
463 # endif
465         pxor    %xmm0, %xmm0
466         sub     $0x1000, %r10           /* substract 4K from %r10 */
467         jmp     LABEL(gobble_ashr_1)
469         /*
470          * Once find null char, determine if there is a string mismatch
471          * before the null char.
472          */
473         .p2align 4
474 LABEL(ashr_1_exittail):
475         movdqa  (%rsi, %rcx), %xmm1
476         psrldq  $1, %xmm0
477         psrldq  $1, %xmm3
478         jmp     LABEL(aftertail)
481  * The following cases will be handled by ashr_2
482  * rcx(offset of rsi)  rax(offset of rdi)   relative offset   corresponding case
483  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
484  */
485         .p2align 4
486 LABEL(ashr_2):
487         pxor    %xmm0, %xmm0
488         movdqa  (%rdi), %xmm2
489         movdqa  (%rsi), %xmm1
490         pcmpeqb %xmm1, %xmm0
491         pslldq  $14, %xmm2
492         TOLOWER (%xmm1, %xmm2)
493         pcmpeqb %xmm1, %xmm2
494         psubb   %xmm0, %xmm2
495         pmovmskb %xmm2, %r9d
496         shr     %cl, %edx
497         shr     %cl, %r9d
498         sub     %r9d, %edx
499         jnz     LABEL(less32bytes)
500         movdqa  (%rdi), %xmm3
501         UPDATE_STRNCMP_COUNTER
503         pxor    %xmm0, %xmm0
504         mov     $16, %rcx       /* index for loads */
505         mov     $2, %r9d        /* byte position left over from less32bytes case */
506         /*
507          * Setup %r10 value allows us to detect crossing a page boundary.
508          * When %r10 goes positive we have crossed a page boundary and
509          * need to do a nibble.
510          */
511         lea     2(%rdi), %r10
512         and     $0xfff, %r10    /* offset into 4K page */
513         sub     $0x1000, %r10   /* subtract 4K pagesize */
515         .p2align 4
516 LABEL(loop_ashr_2):
517         add     $16, %r10
518         jg      LABEL(nibble_ashr_2)
520 LABEL(gobble_ashr_2):
521         movdqa  (%rsi, %rcx), %xmm1
522         movdqa  (%rdi, %rcx), %xmm2
523         movdqa  %xmm2, %xmm4
525 # ifndef USE_SSSE3
526         psrldq  $2, %xmm3
527         pslldq  $14, %xmm2
528         por     %xmm3, %xmm2            /* merge into one 16byte value */
529 # else
530         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
531 # endif
532         TOLOWER (%xmm1, %xmm2)
534         pcmpeqb %xmm1, %xmm0
535         pcmpeqb %xmm2, %xmm1
536         psubb   %xmm0, %xmm1
537         pmovmskb %xmm1, %edx
538         sub     $0xffff, %edx
539         jnz     LABEL(exit)
541 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
542         sub     $16, %r11
543         jbe     LABEL(strcmp_exitz)
544 # endif
546         add     $16, %rcx
547         movdqa  %xmm4, %xmm3
549         add     $16, %r10
550         jg      LABEL(nibble_ashr_2)    /* cross page boundary */
552         movdqa  (%rsi, %rcx), %xmm1
553         movdqa  (%rdi, %rcx), %xmm2
554         movdqa  %xmm2, %xmm4
556 # ifndef USE_SSSE3
557         psrldq  $2, %xmm3
558         pslldq  $14, %xmm2
559         por     %xmm3, %xmm2            /* merge into one 16byte value */
560 # else
561         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
562 # endif
563         TOLOWER (%xmm1, %xmm2)
565         pcmpeqb %xmm1, %xmm0
566         pcmpeqb %xmm2, %xmm1
567         psubb   %xmm0, %xmm1
568         pmovmskb %xmm1, %edx
569         sub     $0xffff, %edx
570         jnz     LABEL(exit)
572 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
573         sub     $16, %r11
574         jbe     LABEL(strcmp_exitz)
575 # endif
577         add     $16, %rcx
578         movdqa  %xmm4, %xmm3
579         jmp     LABEL(loop_ashr_2)
581         .p2align 4
582 LABEL(nibble_ashr_2):
583         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
584         pmovmskb %xmm0, %edx
585         test    $0xfffc, %edx
586         jnz     LABEL(ashr_2_exittail)
588 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
589         cmp     $13, %r11
590         jbe     LABEL(ashr_2_exittail)
591 # endif
593         pxor    %xmm0, %xmm0
594         sub     $0x1000, %r10
595         jmp     LABEL(gobble_ashr_2)
597         .p2align 4
598 LABEL(ashr_2_exittail):
599         movdqa  (%rsi, %rcx), %xmm1
600         psrldq  $2, %xmm0
601         psrldq  $2, %xmm3
602         jmp     LABEL(aftertail)
605  * The following cases will be handled by ashr_3
606  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
607  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
608  */
609         .p2align 4
610 LABEL(ashr_3):
611         pxor    %xmm0, %xmm0
612         movdqa  (%rdi), %xmm2
613         movdqa  (%rsi), %xmm1
614         pcmpeqb %xmm1, %xmm0
615         pslldq  $13, %xmm2
616         TOLOWER (%xmm1, %xmm2)
617         pcmpeqb %xmm1, %xmm2
618         psubb   %xmm0, %xmm2
619         pmovmskb %xmm2, %r9d
620         shr     %cl, %edx
621         shr     %cl, %r9d
622         sub     %r9d, %edx
623         jnz     LABEL(less32bytes)
624         movdqa  (%rdi), %xmm3
626         UPDATE_STRNCMP_COUNTER
628         pxor    %xmm0, %xmm0
629         mov     $16, %rcx       /* index for loads */
630         mov     $3, %r9d        /* byte position left over from less32bytes case */
631         /*
632          * Setup %r10 value allows us to detect crossing a page boundary.
633          * When %r10 goes positive we have crossed a page boundary and
634          * need to do a nibble.
635          */
636         lea     3(%rdi), %r10
637         and     $0xfff, %r10    /* offset into 4K page */
638         sub     $0x1000, %r10   /* subtract 4K pagesize */
640         .p2align 4
641 LABEL(loop_ashr_3):
642         add     $16, %r10
643         jg      LABEL(nibble_ashr_3)
645 LABEL(gobble_ashr_3):
646         movdqa  (%rsi, %rcx), %xmm1
647         movdqa  (%rdi, %rcx), %xmm2
648         movdqa  %xmm2, %xmm4
650 # ifndef USE_SSSE3
651         psrldq  $3, %xmm3
652         pslldq  $13, %xmm2
653         por     %xmm3, %xmm2            /* merge into one 16byte value */
654 # else
655         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
656 # endif
657         TOLOWER (%xmm1, %xmm2)
659         pcmpeqb %xmm1, %xmm0
660         pcmpeqb %xmm2, %xmm1
661         psubb   %xmm0, %xmm1
662         pmovmskb %xmm1, %edx
663         sub     $0xffff, %edx
664         jnz     LABEL(exit)
666 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
667         sub     $16, %r11
668         jbe     LABEL(strcmp_exitz)
669 # endif
671         add     $16, %rcx
672         movdqa  %xmm4, %xmm3
674         add     $16, %r10
675         jg      LABEL(nibble_ashr_3)    /* cross page boundary */
677         movdqa  (%rsi, %rcx), %xmm1
678         movdqa  (%rdi, %rcx), %xmm2
679         movdqa  %xmm2, %xmm4
681 # ifndef USE_SSSE3
682         psrldq  $3, %xmm3
683         pslldq  $13, %xmm2
684         por     %xmm3, %xmm2            /* merge into one 16byte value */
685 # else
686         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
687 # endif
688         TOLOWER (%xmm1, %xmm2)
690         pcmpeqb %xmm1, %xmm0
691         pcmpeqb %xmm2, %xmm1
692         psubb   %xmm0, %xmm1
693         pmovmskb %xmm1, %edx
694         sub     $0xffff, %edx
695         jnz     LABEL(exit)
697 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
698         sub     $16, %r11
699         jbe     LABEL(strcmp_exitz)
700 # endif
702         add     $16, %rcx
703         movdqa  %xmm4, %xmm3
704         jmp     LABEL(loop_ashr_3)
706         .p2align 4
707 LABEL(nibble_ashr_3):
708         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
709         pmovmskb %xmm0, %edx
710         test    $0xfff8, %edx
711         jnz     LABEL(ashr_3_exittail)
713 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
714         cmp     $12, %r11
715         jbe     LABEL(ashr_3_exittail)
716 # endif
718         pxor    %xmm0, %xmm0
719         sub     $0x1000, %r10
720         jmp     LABEL(gobble_ashr_3)
722         .p2align 4
723 LABEL(ashr_3_exittail):
724         movdqa  (%rsi, %rcx), %xmm1
725         psrldq  $3, %xmm0
726         psrldq  $3, %xmm3
727         jmp     LABEL(aftertail)
730  * The following cases will be handled by ashr_4
731  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
732  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
733  */
734         .p2align 4
735 LABEL(ashr_4):
736         pxor    %xmm0, %xmm0
737         movdqa  (%rdi), %xmm2
738         movdqa  (%rsi), %xmm1
739         pcmpeqb %xmm1, %xmm0
740         pslldq  $12, %xmm2
741         TOLOWER (%xmm1, %xmm2)
742         pcmpeqb %xmm1, %xmm2
743         psubb   %xmm0, %xmm2
744         pmovmskb %xmm2, %r9d
745         shr     %cl, %edx
746         shr     %cl, %r9d
747         sub     %r9d, %edx
748         jnz     LABEL(less32bytes)
749         movdqa  (%rdi), %xmm3
751         UPDATE_STRNCMP_COUNTER
753         pxor    %xmm0, %xmm0
754         mov     $16, %rcx       /* index for loads */
755         mov     $4, %r9d        /* byte position left over from less32bytes case */
756         /*
757          * Setup %r10 value allows us to detect crossing a page boundary.
758          * When %r10 goes positive we have crossed a page boundary and
759          * need to do a nibble.
760          */
761         lea     4(%rdi), %r10
762         and     $0xfff, %r10    /* offset into 4K page */
763         sub     $0x1000, %r10   /* subtract 4K pagesize */
765         .p2align 4
766 LABEL(loop_ashr_4):
767         add     $16, %r10
768         jg      LABEL(nibble_ashr_4)
770 LABEL(gobble_ashr_4):
771         movdqa  (%rsi, %rcx), %xmm1
772         movdqa  (%rdi, %rcx), %xmm2
773         movdqa  %xmm2, %xmm4
775 # ifndef USE_SSSE3
776         psrldq  $4, %xmm3
777         pslldq  $12, %xmm2
778         por     %xmm3, %xmm2            /* merge into one 16byte value */
779 # else
780         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
781 # endif
782         TOLOWER (%xmm1, %xmm2)
784         pcmpeqb %xmm1, %xmm0
785         pcmpeqb %xmm2, %xmm1
786         psubb   %xmm0, %xmm1
787         pmovmskb %xmm1, %edx
788         sub     $0xffff, %edx
789         jnz     LABEL(exit)
791 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
792         sub     $16, %r11
793         jbe     LABEL(strcmp_exitz)
794 # endif
796         add     $16, %rcx
797         movdqa  %xmm4, %xmm3
799         add     $16, %r10
800         jg      LABEL(nibble_ashr_4)    /* cross page boundary */
802         movdqa  (%rsi, %rcx), %xmm1
803         movdqa  (%rdi, %rcx), %xmm2
804         movdqa  %xmm2, %xmm4
806 # ifndef USE_SSSE3
807         psrldq  $4, %xmm3
808         pslldq  $12, %xmm2
809         por     %xmm3, %xmm2            /* merge into one 16byte value */
810 # else
811         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
812 # endif
813         TOLOWER (%xmm1, %xmm2)
815         pcmpeqb %xmm1, %xmm0
816         pcmpeqb %xmm2, %xmm1
817         psubb   %xmm0, %xmm1
818         pmovmskb %xmm1, %edx
819         sub     $0xffff, %edx
820         jnz     LABEL(exit)
822 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
823         sub     $16, %r11
824         jbe     LABEL(strcmp_exitz)
825 # endif
827         add     $16, %rcx
828         movdqa  %xmm4, %xmm3
829         jmp     LABEL(loop_ashr_4)
831         .p2align 4
832 LABEL(nibble_ashr_4):
833         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
834         pmovmskb %xmm0, %edx
835         test    $0xfff0, %edx
836         jnz     LABEL(ashr_4_exittail)
838 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
839         cmp     $11, %r11
840         jbe     LABEL(ashr_4_exittail)
841 # endif
843         pxor    %xmm0, %xmm0
844         sub     $0x1000, %r10
845         jmp     LABEL(gobble_ashr_4)
847         .p2align 4
848 LABEL(ashr_4_exittail):
849         movdqa  (%rsi, %rcx), %xmm1
850         psrldq  $4, %xmm0
851         psrldq  $4, %xmm3
852         jmp     LABEL(aftertail)
855  * The following cases will be handled by ashr_5
856  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
857  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
858  */
859         .p2align 4
860 LABEL(ashr_5):
861         pxor    %xmm0, %xmm0
862         movdqa  (%rdi), %xmm2
863         movdqa  (%rsi), %xmm1
864         pcmpeqb %xmm1, %xmm0
865         pslldq  $11, %xmm2
866         TOLOWER (%xmm1, %xmm2)
867         pcmpeqb %xmm1, %xmm2
868         psubb   %xmm0, %xmm2
869         pmovmskb %xmm2, %r9d
870         shr     %cl, %edx
871         shr     %cl, %r9d
872         sub     %r9d, %edx
873         jnz     LABEL(less32bytes)
874         movdqa  (%rdi), %xmm3
876         UPDATE_STRNCMP_COUNTER
878         pxor    %xmm0, %xmm0
879         mov     $16, %rcx       /* index for loads */
880         mov     $5, %r9d        /* byte position left over from less32bytes case */
881         /*
882          * Setup %r10 value allows us to detect crossing a page boundary.
883          * When %r10 goes positive we have crossed a page boundary and
884          * need to do a nibble.
885          */
886         lea     5(%rdi), %r10
887         and     $0xfff, %r10    /* offset into 4K page */
888         sub     $0x1000, %r10   /* subtract 4K pagesize */
890         .p2align 4
891 LABEL(loop_ashr_5):
892         add     $16, %r10
893         jg      LABEL(nibble_ashr_5)
895 LABEL(gobble_ashr_5):
896         movdqa  (%rsi, %rcx), %xmm1
897         movdqa  (%rdi, %rcx), %xmm2
898         movdqa  %xmm2, %xmm4
900 # ifndef USE_SSSE3
901         psrldq  $5, %xmm3
902         pslldq  $11, %xmm2
903         por     %xmm3, %xmm2            /* merge into one 16byte value */
904 # else
905         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
906 # endif
907         TOLOWER (%xmm1, %xmm2)
909         pcmpeqb %xmm1, %xmm0
910         pcmpeqb %xmm2, %xmm1
911         psubb   %xmm0, %xmm1
912         pmovmskb %xmm1, %edx
913         sub     $0xffff, %edx
914         jnz     LABEL(exit)
916 # if defined USE_AS_STRNCMP || defined USE_AS_STRCASECMP_L
917         sub     $16, %r11
918         jbe     LABEL(strcmp_exitz)
919 # endif
921         add     $16, %rcx
922         movdqa  %xmm4, %xmm3
924         add     $16, %r10
925         jg      LABEL(nibble_ashr_5)    /* cross page boundary */
927         movdqa  (%rsi, %rcx), %xmm1
928         movdqa  (%rdi, %rcx), %xmm2
929         movdqa  %xmm2, %xmm4
931 # ifndef USE_SSSE3
932         psrldq  $5, %xmm3
933         pslldq  $11, %xmm2
934         por     %xmm3, %xmm2            /* merge into one 16byte value */
935 # else
936         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
937 # endif
938         TOLOWER (%xmm1, %xmm2)
940         pcmpeqb %xmm1, %xmm0
941         pcmpeqb %xmm2, %xmm1
942         psubb   %xmm0, %xmm1
943         pmovmskb %xmm1, %edx
944         sub     $0xffff, %edx
945         jnz     LABEL(exit)
947 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
948         sub     $16, %r11
949         jbe     LABEL(strcmp_exitz)
950 # endif
952         add     $16, %rcx
953         movdqa  %xmm4, %xmm3
954         jmp     LABEL(loop_ashr_5)
956         .p2align 4
957 LABEL(nibble_ashr_5):
958         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
959         pmovmskb %xmm0, %edx
960         test    $0xffe0, %edx
961         jnz     LABEL(ashr_5_exittail)
963 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
964         cmp     $10, %r11
965         jbe     LABEL(ashr_5_exittail)
966 # endif
968         pxor    %xmm0, %xmm0
969         sub     $0x1000, %r10
970         jmp     LABEL(gobble_ashr_5)
972         .p2align 4
973 LABEL(ashr_5_exittail):
974         movdqa  (%rsi, %rcx), %xmm1
975         psrldq  $5, %xmm0
976         psrldq  $5, %xmm3
977         jmp     LABEL(aftertail)
980  * The following cases will be handled by ashr_6
981  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
982  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
983  */
984         .p2align 4
985 LABEL(ashr_6):
986         pxor    %xmm0, %xmm0
987         movdqa  (%rdi), %xmm2
988         movdqa  (%rsi), %xmm1
989         pcmpeqb %xmm1, %xmm0
990         pslldq  $10, %xmm2
991         TOLOWER (%xmm1, %xmm2)
992         pcmpeqb %xmm1, %xmm2
993         psubb   %xmm0, %xmm2
994         pmovmskb %xmm2, %r9d
995         shr     %cl, %edx
996         shr     %cl, %r9d
997         sub     %r9d, %edx
998         jnz     LABEL(less32bytes)
999         movdqa  (%rdi), %xmm3
1001         UPDATE_STRNCMP_COUNTER
1003         pxor    %xmm0, %xmm0
1004         mov     $16, %rcx       /* index for loads */
1005         mov     $6, %r9d        /* byte position left over from less32bytes case */
1006         /*
1007          * Setup %r10 value allows us to detect crossing a page boundary.
1008          * When %r10 goes positive we have crossed a page boundary and
1009          * need to do a nibble.
1010          */
1011         lea     6(%rdi), %r10
1012         and     $0xfff, %r10    /* offset into 4K page */
1013         sub     $0x1000, %r10   /* subtract 4K pagesize */
1015         .p2align 4
1016 LABEL(loop_ashr_6):
1017         add     $16, %r10
1018         jg      LABEL(nibble_ashr_6)
1020 LABEL(gobble_ashr_6):
1021         movdqa  (%rsi, %rcx), %xmm1
1022         movdqa  (%rdi, %rcx), %xmm2
1023         movdqa  %xmm2, %xmm4
1025 # ifndef USE_SSSE3
1026         psrldq  $6, %xmm3
1027         pslldq  $10, %xmm2
1028         por     %xmm3, %xmm2            /* merge into one 16byte value */
1029 # else
1030         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
1031 # endif
1032         TOLOWER (%xmm1, %xmm2)
1034         pcmpeqb %xmm1, %xmm0
1035         pcmpeqb %xmm2, %xmm1
1036         psubb   %xmm0, %xmm1
1037         pmovmskb %xmm1, %edx
1038         sub     $0xffff, %edx
1039         jnz     LABEL(exit)
1041 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1042         sub     $16, %r11
1043         jbe     LABEL(strcmp_exitz)
1044 # endif
1046         add     $16, %rcx
1047         movdqa  %xmm4, %xmm3
1049         add     $16, %r10
1050         jg      LABEL(nibble_ashr_6)    /* cross page boundary */
1052         movdqa  (%rsi, %rcx), %xmm1
1053         movdqa  (%rdi, %rcx), %xmm2
1054         movdqa  %xmm2, %xmm4
1056 # ifndef USE_SSSE3
1057         psrldq  $6, %xmm3
1058         pslldq  $10, %xmm2
1059         por     %xmm3, %xmm2            /* merge into one 16byte value */
1060 # else
1061         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
1062 # endif
1063         TOLOWER (%xmm1, %xmm2)
1065         pcmpeqb %xmm1, %xmm0
1066         pcmpeqb %xmm2, %xmm1
1067         psubb   %xmm0, %xmm1
1068         pmovmskb %xmm1, %edx
1069         sub     $0xffff, %edx
1070         jnz     LABEL(exit)
1072 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1073         sub     $16, %r11
1074         jbe     LABEL(strcmp_exitz)
1075 # endif
1077         add     $16, %rcx
1078         movdqa  %xmm4, %xmm3
1079         jmp     LABEL(loop_ashr_6)
1081         .p2align 4
1082 LABEL(nibble_ashr_6):
1083         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1084         pmovmskb %xmm0, %edx
1085         test    $0xffc0, %edx
1086         jnz     LABEL(ashr_6_exittail)
1088 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1089         cmp     $9, %r11
1090         jbe     LABEL(ashr_6_exittail)
1091 # endif
1093         pxor    %xmm0, %xmm0
1094         sub     $0x1000, %r10
1095         jmp     LABEL(gobble_ashr_6)
1097         .p2align 4
1098 LABEL(ashr_6_exittail):
1099         movdqa  (%rsi, %rcx), %xmm1
1100         psrldq  $6, %xmm0
1101         psrldq  $6, %xmm3
1102         jmp     LABEL(aftertail)
1105  * The following cases will be handled by ashr_7
1106  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
1107  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
1108  */
1109         .p2align 4
1110 LABEL(ashr_7):
1111         pxor    %xmm0, %xmm0
1112         movdqa  (%rdi), %xmm2
1113         movdqa  (%rsi), %xmm1
1114         pcmpeqb %xmm1, %xmm0
1115         pslldq  $9, %xmm2
1116         TOLOWER (%xmm1, %xmm2)
1117         pcmpeqb %xmm1, %xmm2
1118         psubb   %xmm0, %xmm2
1119         pmovmskb %xmm2, %r9d
1120         shr     %cl, %edx
1121         shr     %cl, %r9d
1122         sub     %r9d, %edx
1123         jnz     LABEL(less32bytes)
1124         movdqa  (%rdi), %xmm3
1126         UPDATE_STRNCMP_COUNTER
1128         pxor    %xmm0, %xmm0
1129         mov     $16, %rcx       /* index for loads */
1130         mov     $7, %r9d        /* byte position left over from less32bytes case */
1131         /*
1132          * Setup %r10 value allows us to detect crossing a page boundary.
1133          * When %r10 goes positive we have crossed a page boundary and
1134          * need to do a nibble.
1135          */
1136         lea     7(%rdi), %r10
1137         and     $0xfff, %r10    /* offset into 4K page */
1138         sub     $0x1000, %r10   /* subtract 4K pagesize */
1140         .p2align 4
1141 LABEL(loop_ashr_7):
1142         add     $16, %r10
1143         jg      LABEL(nibble_ashr_7)
1145 LABEL(gobble_ashr_7):
1146         movdqa  (%rsi, %rcx), %xmm1
1147         movdqa  (%rdi, %rcx), %xmm2
1148         movdqa  %xmm2, %xmm4
1150 # ifndef USE_SSSE3
1151         psrldq  $7, %xmm3
1152         pslldq  $9, %xmm2
1153         por     %xmm3, %xmm2            /* merge into one 16byte value */
1154 # else
1155         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1156 # endif
1157         TOLOWER (%xmm1, %xmm2)
1159         pcmpeqb %xmm1, %xmm0
1160         pcmpeqb %xmm2, %xmm1
1161         psubb   %xmm0, %xmm1
1162         pmovmskb %xmm1, %edx
1163         sub     $0xffff, %edx
1164         jnz     LABEL(exit)
1166 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1167         sub     $16, %r11
1168         jbe     LABEL(strcmp_exitz)
1169 # endif
1171         add     $16, %rcx
1172         movdqa  %xmm4, %xmm3
1174         add     $16, %r10
1175         jg      LABEL(nibble_ashr_7)    /* cross page boundary */
1177         movdqa  (%rsi, %rcx), %xmm1
1178         movdqa  (%rdi, %rcx), %xmm2
1179         movdqa  %xmm2, %xmm4
1181 # ifndef USE_SSSE3
1182         psrldq  $7, %xmm3
1183         pslldq  $9, %xmm2
1184         por     %xmm3, %xmm2            /* merge into one 16byte value */
1185 # else
1186         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1187 # endif
1188         TOLOWER (%xmm1, %xmm2)
1190         pcmpeqb %xmm1, %xmm0
1191         pcmpeqb %xmm2, %xmm1
1192         psubb   %xmm0, %xmm1
1193         pmovmskb %xmm1, %edx
1194         sub     $0xffff, %edx
1195         jnz     LABEL(exit)
1197 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1198         sub     $16, %r11
1199         jbe     LABEL(strcmp_exitz)
1200 # endif
1202         add     $16, %rcx
1203         movdqa  %xmm4, %xmm3
1204         jmp     LABEL(loop_ashr_7)
1206         .p2align 4
1207 LABEL(nibble_ashr_7):
1208         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1209         pmovmskb %xmm0, %edx
1210         test    $0xff80, %edx
1211         jnz     LABEL(ashr_7_exittail)
1213 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1214         cmp     $8, %r11
1215         jbe     LABEL(ashr_7_exittail)
1216 # endif
1218         pxor    %xmm0, %xmm0
1219         sub     $0x1000, %r10
1220         jmp     LABEL(gobble_ashr_7)
1222         .p2align 4
1223 LABEL(ashr_7_exittail):
1224         movdqa  (%rsi, %rcx), %xmm1
1225         psrldq  $7, %xmm0
1226         psrldq  $7, %xmm3
1227         jmp     LABEL(aftertail)
1230  *  The following cases will be handled by ashr_8
1231  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1232  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
1233  */
1234         .p2align 4
1235 LABEL(ashr_8):
1236         pxor    %xmm0, %xmm0
1237         movdqa  (%rdi), %xmm2
1238         movdqa  (%rsi), %xmm1
1239         pcmpeqb %xmm1, %xmm0
1240         pslldq  $8, %xmm2
1241         TOLOWER (%xmm1, %xmm2)
1242         pcmpeqb %xmm1, %xmm2
1243         psubb   %xmm0, %xmm2
1244         pmovmskb %xmm2, %r9d
1245         shr     %cl, %edx
1246         shr     %cl, %r9d
1247         sub     %r9d, %edx
1248         jnz     LABEL(less32bytes)
1249         movdqa  (%rdi), %xmm3
1251         UPDATE_STRNCMP_COUNTER
1253         pxor    %xmm0, %xmm0
1254         mov     $16, %rcx       /* index for loads */
1255         mov     $8, %r9d        /* byte position left over from less32bytes case */
1256         /*
1257          * Setup %r10 value allows us to detect crossing a page boundary.
1258          * When %r10 goes positive we have crossed a page boundary and
1259          * need to do a nibble.
1260          */
1261         lea     8(%rdi), %r10
1262         and     $0xfff, %r10    /* offset into 4K page */
1263         sub     $0x1000, %r10   /* subtract 4K pagesize */
1265         .p2align 4
1266 LABEL(loop_ashr_8):
1267         add     $16, %r10
1268         jg      LABEL(nibble_ashr_8)
1270 LABEL(gobble_ashr_8):
1271         movdqa  (%rsi, %rcx), %xmm1
1272         movdqa  (%rdi, %rcx), %xmm2
1273         movdqa  %xmm2, %xmm4
1275 # ifndef USE_SSSE3
1276         psrldq  $8, %xmm3
1277         pslldq  $8, %xmm2
1278         por     %xmm3, %xmm2            /* merge into one 16byte value */
1279 # else
1280         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1281 # endif
1282         TOLOWER (%xmm1, %xmm2)
1284         pcmpeqb %xmm1, %xmm0
1285         pcmpeqb %xmm2, %xmm1
1286         psubb   %xmm0, %xmm1
1287         pmovmskb %xmm1, %edx
1288         sub     $0xffff, %edx
1289         jnz     LABEL(exit)
1291 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1292         sub     $16, %r11
1293         jbe     LABEL(strcmp_exitz)
1294 # endif
1296         add     $16, %rcx
1297         movdqa  %xmm4, %xmm3
1299         add     $16, %r10
1300         jg      LABEL(nibble_ashr_8)    /* cross page boundary */
1302         movdqa  (%rsi, %rcx), %xmm1
1303         movdqa  (%rdi, %rcx), %xmm2
1304         movdqa  %xmm2, %xmm4
1306 # ifndef USE_SSSE3
1307         psrldq  $8, %xmm3
1308         pslldq  $8, %xmm2
1309         por     %xmm3, %xmm2            /* merge into one 16byte value */
1310 # else
1311         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1312 # endif
1313         TOLOWER (%xmm1, %xmm2)
1315         pcmpeqb %xmm1, %xmm0
1316         pcmpeqb %xmm2, %xmm1
1317         psubb   %xmm0, %xmm1
1318         pmovmskb %xmm1, %edx
1319         sub     $0xffff, %edx
1320         jnz     LABEL(exit)
1322 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1323         sub     $16, %r11
1324         jbe     LABEL(strcmp_exitz)
1325 # endif
1327         add     $16, %rcx
1328         movdqa  %xmm4, %xmm3
1329         jmp     LABEL(loop_ashr_8)
1331         .p2align 4
1332 LABEL(nibble_ashr_8):
1333         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1334         pmovmskb %xmm0, %edx
1335         test    $0xff00, %edx
1336         jnz     LABEL(ashr_8_exittail)
1338 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1339         cmp     $7, %r11
1340         jbe     LABEL(ashr_8_exittail)
1341 # endif
1343         pxor    %xmm0, %xmm0
1344         sub     $0x1000, %r10
1345         jmp     LABEL(gobble_ashr_8)
1347         .p2align 4
1348 LABEL(ashr_8_exittail):
1349         movdqa  (%rsi, %rcx), %xmm1
1350         psrldq  $8, %xmm0
1351         psrldq  $8, %xmm3
1352         jmp     LABEL(aftertail)
1355  *  The following cases will be handled by ashr_9
1356  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1357  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
1358  */
1359         .p2align 4
1360 LABEL(ashr_9):
1361         pxor    %xmm0, %xmm0
1362         movdqa  (%rdi), %xmm2
1363         movdqa  (%rsi), %xmm1
1364         pcmpeqb %xmm1, %xmm0
1365         pslldq  $7, %xmm2
1366         TOLOWER (%xmm1, %xmm2)
1367         pcmpeqb %xmm1, %xmm2
1368         psubb   %xmm0, %xmm2
1369         pmovmskb %xmm2, %r9d
1370         shr     %cl, %edx
1371         shr     %cl, %r9d
1372         sub     %r9d, %edx
1373         jnz     LABEL(less32bytes)
1374         movdqa  (%rdi), %xmm3
1376         UPDATE_STRNCMP_COUNTER
1378         pxor    %xmm0, %xmm0
1379         mov     $16, %rcx       /* index for loads */
1380         mov     $9, %r9d        /* byte position left over from less32bytes case */
1381         /*
1382          * Setup %r10 value allows us to detect crossing a page boundary.
1383          * When %r10 goes positive we have crossed a page boundary and
1384          * need to do a nibble.
1385          */
1386         lea     9(%rdi), %r10
1387         and     $0xfff, %r10    /* offset into 4K page */
1388         sub     $0x1000, %r10   /* subtract 4K pagesize */
1390         .p2align 4
1391 LABEL(loop_ashr_9):
1392         add     $16, %r10
1393         jg      LABEL(nibble_ashr_9)
1395 LABEL(gobble_ashr_9):
1396         movdqa  (%rsi, %rcx), %xmm1
1397         movdqa  (%rdi, %rcx), %xmm2
1398         movdqa  %xmm2, %xmm4
1400 # ifndef USE_SSSE3
1401         psrldq  $9, %xmm3
1402         pslldq  $7, %xmm2
1403         por     %xmm3, %xmm2            /* merge into one 16byte value */
1404 # else
1405         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1406 # endif
1407         TOLOWER (%xmm1, %xmm2)
1409         pcmpeqb %xmm1, %xmm0
1410         pcmpeqb %xmm2, %xmm1
1411         psubb   %xmm0, %xmm1
1412         pmovmskb %xmm1, %edx
1413         sub     $0xffff, %edx
1414         jnz     LABEL(exit)
1416 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1417         sub     $16, %r11
1418         jbe     LABEL(strcmp_exitz)
1419 # endif
1421         add     $16, %rcx
1422         movdqa  %xmm4, %xmm3
1424         add     $16, %r10
1425         jg      LABEL(nibble_ashr_9)    /* cross page boundary */
1427         movdqa  (%rsi, %rcx), %xmm1
1428         movdqa  (%rdi, %rcx), %xmm2
1429         movdqa  %xmm2, %xmm4
1431 # ifndef USE_SSSE3
1432         psrldq  $9, %xmm3
1433         pslldq  $7, %xmm2
1434         por     %xmm3, %xmm2            /* merge into one 16byte value */
1435 # else
1436         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1437 # endif
1438         TOLOWER (%xmm1, %xmm2)
1440         pcmpeqb %xmm1, %xmm0
1441         pcmpeqb %xmm2, %xmm1
1442         psubb   %xmm0, %xmm1
1443         pmovmskb %xmm1, %edx
1444         sub     $0xffff, %edx
1445         jnz     LABEL(exit)
1447 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1448         sub     $16, %r11
1449         jbe     LABEL(strcmp_exitz)
1450 # endif
1452         add     $16, %rcx
1453         movdqa  %xmm4, %xmm3            /* store for next cycle */
1454         jmp     LABEL(loop_ashr_9)
1456         .p2align 4
1457 LABEL(nibble_ashr_9):
1458         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1459         pmovmskb %xmm0, %edx
1460         test    $0xfe00, %edx
1461         jnz     LABEL(ashr_9_exittail)
1463 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1464         cmp     $6, %r11
1465         jbe     LABEL(ashr_9_exittail)
1466 # endif
1468         pxor    %xmm0, %xmm0
1469         sub     $0x1000, %r10
1470         jmp     LABEL(gobble_ashr_9)
1472         .p2align 4
1473 LABEL(ashr_9_exittail):
1474         movdqa  (%rsi, %rcx), %xmm1
1475         psrldq  $9, %xmm0
1476         psrldq  $9, %xmm3
1477         jmp     LABEL(aftertail)
1480  *  The following cases will be handled by ashr_10
1481  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1482  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
1483  */
1484         .p2align 4
1485 LABEL(ashr_10):
1486         pxor    %xmm0, %xmm0
1487         movdqa  (%rdi), %xmm2
1488         movdqa  (%rsi), %xmm1
1489         pcmpeqb %xmm1, %xmm0
1490         pslldq  $6, %xmm2
1491         TOLOWER (%xmm1, %xmm2)
1492         pcmpeqb %xmm1, %xmm2
1493         psubb   %xmm0, %xmm2
1494         pmovmskb %xmm2, %r9d
1495         shr     %cl, %edx
1496         shr     %cl, %r9d
1497         sub     %r9d, %edx
1498         jnz     LABEL(less32bytes)
1499         movdqa  (%rdi), %xmm3
1501         UPDATE_STRNCMP_COUNTER
1503         pxor    %xmm0, %xmm0
1504         mov     $16, %rcx       /* index for loads */
1505         mov     $10, %r9d       /* byte position left over from less32bytes case */
1506         /*
1507          * Setup %r10 value allows us to detect crossing a page boundary.
1508          * When %r10 goes positive we have crossed a page boundary and
1509          * need to do a nibble.
1510          */
1511         lea     10(%rdi), %r10
1512         and     $0xfff, %r10    /* offset into 4K page */
1513         sub     $0x1000, %r10   /* subtract 4K pagesize */
1515         .p2align 4
1516 LABEL(loop_ashr_10):
1517         add     $16, %r10
1518         jg      LABEL(nibble_ashr_10)
1520 LABEL(gobble_ashr_10):
1521         movdqa  (%rsi, %rcx), %xmm1
1522         movdqa  (%rdi, %rcx), %xmm2
1523         movdqa  %xmm2, %xmm4
1525 # ifndef USE_SSSE3
1526         psrldq  $10, %xmm3
1527         pslldq  $6, %xmm2
1528         por     %xmm3, %xmm2            /* merge into one 16byte value */
1529 # else
1530         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1531 # endif
1532         TOLOWER (%xmm1, %xmm2)
1534         pcmpeqb %xmm1, %xmm0
1535         pcmpeqb %xmm2, %xmm1
1536         psubb   %xmm0, %xmm1
1537         pmovmskb %xmm1, %edx
1538         sub     $0xffff, %edx
1539         jnz     LABEL(exit)
1541 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1542         sub     $16, %r11
1543         jbe     LABEL(strcmp_exitz)
1544 # endif
1546         add     $16, %rcx
1547         movdqa  %xmm4, %xmm3
1549         add     $16, %r10
1550         jg      LABEL(nibble_ashr_10)   /* cross page boundary */
1552         movdqa  (%rsi, %rcx), %xmm1
1553         movdqa  (%rdi, %rcx), %xmm2
1554         movdqa  %xmm2, %xmm4
1556 # ifndef USE_SSSE3
1557         psrldq  $10, %xmm3
1558         pslldq  $6, %xmm2
1559         por     %xmm3, %xmm2            /* merge into one 16byte value */
1560 # else
1561         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1562 # endif
1563         TOLOWER (%xmm1, %xmm2)
1565         pcmpeqb %xmm1, %xmm0
1566         pcmpeqb %xmm2, %xmm1
1567         psubb   %xmm0, %xmm1
1568         pmovmskb %xmm1, %edx
1569         sub     $0xffff, %edx
1570         jnz     LABEL(exit)
1572 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1573         sub     $16, %r11
1574         jbe     LABEL(strcmp_exitz)
1575 # endif
1577         add     $16, %rcx
1578         movdqa  %xmm4, %xmm3
1579         jmp     LABEL(loop_ashr_10)
1581         .p2align 4
1582 LABEL(nibble_ashr_10):
1583         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1584         pmovmskb %xmm0, %edx
1585         test    $0xfc00, %edx
1586         jnz     LABEL(ashr_10_exittail)
1588 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1589         cmp     $5, %r11
1590         jbe     LABEL(ashr_10_exittail)
1591 # endif
1593         pxor    %xmm0, %xmm0
1594         sub     $0x1000, %r10
1595         jmp     LABEL(gobble_ashr_10)
1597         .p2align 4
1598 LABEL(ashr_10_exittail):
1599         movdqa  (%rsi, %rcx), %xmm1
1600         psrldq  $10, %xmm0
1601         psrldq  $10, %xmm3
1602         jmp     LABEL(aftertail)
1605  *  The following cases will be handled by ashr_11
1606  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1607  *        n(5~15)          n - 5               10(15 +(n - 5) - n)         ashr_11
1608  */
1609         .p2align 4
1610 LABEL(ashr_11):
1611         pxor    %xmm0, %xmm0
1612         movdqa  (%rdi), %xmm2
1613         movdqa  (%rsi), %xmm1
1614         pcmpeqb %xmm1, %xmm0
1615         pslldq  $5, %xmm2
1616         TOLOWER (%xmm1, %xmm2)
1617         pcmpeqb %xmm1, %xmm2
1618         psubb   %xmm0, %xmm2
1619         pmovmskb %xmm2, %r9d
1620         shr     %cl, %edx
1621         shr     %cl, %r9d
1622         sub     %r9d, %edx
1623         jnz     LABEL(less32bytes)
1624         movdqa  (%rdi), %xmm3
1626         UPDATE_STRNCMP_COUNTER
1628         pxor    %xmm0, %xmm0
1629         mov     $16, %rcx       /* index for loads */
1630         mov     $11, %r9d       /* byte position left over from less32bytes case */
1631         /*
1632          * Setup %r10 value allows us to detect crossing a page boundary.
1633          * When %r10 goes positive we have crossed a page boundary and
1634          * need to do a nibble.
1635          */
1636         lea     11(%rdi), %r10
1637         and     $0xfff, %r10    /* offset into 4K page */
1638         sub     $0x1000, %r10   /* subtract 4K pagesize */
1640         .p2align 4
1641 LABEL(loop_ashr_11):
1642         add     $16, %r10
1643         jg      LABEL(nibble_ashr_11)
1645 LABEL(gobble_ashr_11):
1646         movdqa  (%rsi, %rcx), %xmm1
1647         movdqa  (%rdi, %rcx), %xmm2
1648         movdqa  %xmm2, %xmm4
1650 # ifndef USE_SSSE3
1651         psrldq  $11, %xmm3
1652         pslldq  $5, %xmm2
1653         por     %xmm3, %xmm2            /* merge into one 16byte value */
1654 # else
1655         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1656 # endif
1657         TOLOWER (%xmm1, %xmm2)
1659         pcmpeqb %xmm1, %xmm0
1660         pcmpeqb %xmm2, %xmm1
1661         psubb   %xmm0, %xmm1
1662         pmovmskb %xmm1, %edx
1663         sub     $0xffff, %edx
1664         jnz     LABEL(exit)
1666 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1667         sub     $16, %r11
1668         jbe     LABEL(strcmp_exitz)
1669 # endif
1671         add     $16, %rcx
1672         movdqa  %xmm4, %xmm3
1674         add     $16, %r10
1675         jg      LABEL(nibble_ashr_11)   /* cross page boundary */
1677         movdqa  (%rsi, %rcx), %xmm1
1678         movdqa  (%rdi, %rcx), %xmm2
1679         movdqa  %xmm2, %xmm4
1681 # ifndef USE_SSSE3
1682         psrldq  $11, %xmm3
1683         pslldq  $5, %xmm2
1684         por     %xmm3, %xmm2            /* merge into one 16byte value */
1685 # else
1686         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1687 # endif
1688         TOLOWER (%xmm1, %xmm2)
1690         pcmpeqb %xmm1, %xmm0
1691         pcmpeqb %xmm2, %xmm1
1692         psubb   %xmm0, %xmm1
1693         pmovmskb %xmm1, %edx
1694         sub     $0xffff, %edx
1695         jnz     LABEL(exit)
1697 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1698         sub     $16, %r11
1699         jbe     LABEL(strcmp_exitz)
1700 # endif
1702         add     $16, %rcx
1703         movdqa  %xmm4, %xmm3
1704         jmp     LABEL(loop_ashr_11)
1706         .p2align 4
1707 LABEL(nibble_ashr_11):
1708         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1709         pmovmskb %xmm0, %edx
1710         test    $0xf800, %edx
1711         jnz     LABEL(ashr_11_exittail)
1713 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1714         cmp     $4, %r11
1715         jbe     LABEL(ashr_11_exittail)
1716 # endif
1718         pxor    %xmm0, %xmm0
1719         sub     $0x1000, %r10
1720         jmp     LABEL(gobble_ashr_11)
1722         .p2align 4
1723 LABEL(ashr_11_exittail):
1724         movdqa  (%rsi, %rcx), %xmm1
1725         psrldq  $11, %xmm0
1726         psrldq  $11, %xmm3
1727         jmp     LABEL(aftertail)
1730  *  The following cases will be handled by ashr_12
1731  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1732  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1733  */
1734         .p2align 4
1735 LABEL(ashr_12):
1736         pxor    %xmm0, %xmm0
1737         movdqa  (%rdi), %xmm2
1738         movdqa  (%rsi), %xmm1
1739         pcmpeqb %xmm1, %xmm0
1740         pslldq  $4, %xmm2
1741         TOLOWER (%xmm1, %xmm2)
1742         pcmpeqb %xmm1, %xmm2
1743         psubb   %xmm0, %xmm2
1744         pmovmskb %xmm2, %r9d
1745         shr     %cl, %edx
1746         shr     %cl, %r9d
1747         sub     %r9d, %edx
1748         jnz     LABEL(less32bytes)
1749         movdqa  (%rdi), %xmm3
1751         UPDATE_STRNCMP_COUNTER
1753         pxor    %xmm0, %xmm0
1754         mov     $16, %rcx       /* index for loads */
1755         mov     $12, %r9d       /* byte position left over from less32bytes case */
1756         /*
1757          * Setup %r10 value allows us to detect crossing a page boundary.
1758          * When %r10 goes positive we have crossed a page boundary and
1759          * need to do a nibble.
1760          */
1761         lea     12(%rdi), %r10
1762         and     $0xfff, %r10    /* offset into 4K page */
1763         sub     $0x1000, %r10   /* subtract 4K pagesize */
1765         .p2align 4
1766 LABEL(loop_ashr_12):
1767         add     $16, %r10
1768         jg      LABEL(nibble_ashr_12)
1770 LABEL(gobble_ashr_12):
1771         movdqa  (%rsi, %rcx), %xmm1
1772         movdqa  (%rdi, %rcx), %xmm2
1773         movdqa  %xmm2, %xmm4
1775 # ifndef USE_SSSE3
1776         psrldq  $12, %xmm3
1777         pslldq  $4, %xmm2
1778         por     %xmm3, %xmm2            /* merge into one 16byte value */
1779 # else
1780         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1781 # endif
1782         TOLOWER (%xmm1, %xmm2)
1784         pcmpeqb %xmm1, %xmm0
1785         pcmpeqb %xmm2, %xmm1
1786         psubb   %xmm0, %xmm1
1787         pmovmskb %xmm1, %edx
1788         sub     $0xffff, %edx
1789         jnz     LABEL(exit)
1791 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1792         sub     $16, %r11
1793         jbe     LABEL(strcmp_exitz)
1794 # endif
1796         add     $16, %rcx
1797         movdqa  %xmm4, %xmm3
1799         add     $16, %r10
1800         jg      LABEL(nibble_ashr_12)   /* cross page boundary */
1802         movdqa  (%rsi, %rcx), %xmm1
1803         movdqa  (%rdi, %rcx), %xmm2
1804         movdqa  %xmm2, %xmm4
1806 # ifndef USE_SSSE3
1807         psrldq  $12, %xmm3
1808         pslldq  $4, %xmm2
1809         por     %xmm3, %xmm2            /* merge into one 16byte value */
1810 # else
1811         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1812 # endif
1813         TOLOWER (%xmm1, %xmm2)
1815         pcmpeqb %xmm1, %xmm0
1816         pcmpeqb %xmm2, %xmm1
1817         psubb   %xmm0, %xmm1
1818         pmovmskb %xmm1, %edx
1819         sub     $0xffff, %edx
1820         jnz     LABEL(exit)
1822 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1823         sub     $16, %r11
1824         jbe     LABEL(strcmp_exitz)
1825 # endif
1827         add     $16, %rcx
1828         movdqa  %xmm4, %xmm3
1829         jmp     LABEL(loop_ashr_12)
1831         .p2align 4
1832 LABEL(nibble_ashr_12):
1833         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1834         pmovmskb %xmm0, %edx
1835         test    $0xf000, %edx
1836         jnz     LABEL(ashr_12_exittail)
1838 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1839         cmp     $3, %r11
1840         jbe     LABEL(ashr_12_exittail)
1841 # endif
1843         pxor    %xmm0, %xmm0
1844         sub     $0x1000, %r10
1845         jmp     LABEL(gobble_ashr_12)
1847         .p2align 4
1848 LABEL(ashr_12_exittail):
1849         movdqa  (%rsi, %rcx), %xmm1
1850         psrldq  $12, %xmm0
1851         psrldq  $12, %xmm3
1852         jmp     LABEL(aftertail)
1855  *  The following cases will be handled by ashr_13
1856  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1857  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1858  */
1859         .p2align 4
1860 LABEL(ashr_13):
1861         pxor    %xmm0, %xmm0
1862         movdqa  (%rdi), %xmm2
1863         movdqa  (%rsi), %xmm1
1864         pcmpeqb %xmm1, %xmm0
1865         pslldq  $3, %xmm2
1866         TOLOWER (%xmm1, %xmm2)
1867         pcmpeqb %xmm1, %xmm2
1868         psubb   %xmm0, %xmm2
1869         pmovmskb %xmm2, %r9d
1870         shr     %cl, %edx
1871         shr     %cl, %r9d
1872         sub     %r9d, %edx
1873         jnz     LABEL(less32bytes)
1874         movdqa  (%rdi), %xmm3
1876         UPDATE_STRNCMP_COUNTER
1878         pxor    %xmm0, %xmm0
1879         mov     $16, %rcx       /* index for loads */
1880         mov     $13, %r9d       /* byte position left over from less32bytes case */
1881         /*
1882          * Setup %r10 value allows us to detect crossing a page boundary.
1883          * When %r10 goes positive we have crossed a page boundary and
1884          * need to do a nibble.
1885          */
1886         lea     13(%rdi), %r10
1887         and     $0xfff, %r10    /* offset into 4K page */
1888         sub     $0x1000, %r10   /* subtract 4K pagesize */
1890         .p2align 4
1891 LABEL(loop_ashr_13):
1892         add     $16, %r10
1893         jg      LABEL(nibble_ashr_13)
1895 LABEL(gobble_ashr_13):
1896         movdqa  (%rsi, %rcx), %xmm1
1897         movdqa  (%rdi, %rcx), %xmm2
1898         movdqa  %xmm2, %xmm4
1900 # ifndef USE_SSSE3
1901         psrldq  $13, %xmm3
1902         pslldq  $3, %xmm2
1903         por     %xmm3, %xmm2            /* merge into one 16byte value */
1904 # else
1905         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1906 # endif
1907         TOLOWER (%xmm1, %xmm2)
1909         pcmpeqb %xmm1, %xmm0
1910         pcmpeqb %xmm2, %xmm1
1911         psubb   %xmm0, %xmm1
1912         pmovmskb %xmm1, %edx
1913         sub     $0xffff, %edx
1914         jnz     LABEL(exit)
1916 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1917         sub     $16, %r11
1918         jbe     LABEL(strcmp_exitz)
1919 # endif
1921         add     $16, %rcx
1922         movdqa  %xmm4, %xmm3
1924         add     $16, %r10
1925         jg      LABEL(nibble_ashr_13)   /* cross page boundary */
1927         movdqa  (%rsi, %rcx), %xmm1
1928         movdqa  (%rdi, %rcx), %xmm2
1929         movdqa  %xmm2, %xmm4
1931 # ifndef USE_SSSE3
1932         psrldq  $13, %xmm3
1933         pslldq  $3, %xmm2
1934         por     %xmm3, %xmm2            /* merge into one 16byte value */
1935 # else
1936         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1937 # endif
1938         TOLOWER (%xmm1, %xmm2)
1940         pcmpeqb %xmm1, %xmm0
1941         pcmpeqb %xmm2, %xmm1
1942         psubb   %xmm0, %xmm1
1943         pmovmskb %xmm1, %edx
1944         sub     $0xffff, %edx
1945         jnz     LABEL(exit)
1947 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1948         sub     $16, %r11
1949         jbe     LABEL(strcmp_exitz)
1950 # endif
1952         add     $16, %rcx
1953         movdqa  %xmm4, %xmm3
1954         jmp     LABEL(loop_ashr_13)
1956         .p2align 4
1957 LABEL(nibble_ashr_13):
1958         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1959         pmovmskb %xmm0, %edx
1960         test    $0xe000, %edx
1961         jnz     LABEL(ashr_13_exittail)
1963 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
1964         cmp     $2, %r11
1965         jbe     LABEL(ashr_13_exittail)
1966 # endif
1968         pxor    %xmm0, %xmm0
1969         sub     $0x1000, %r10
1970         jmp     LABEL(gobble_ashr_13)
1972         .p2align 4
1973 LABEL(ashr_13_exittail):
1974         movdqa  (%rsi, %rcx), %xmm1
1975         psrldq  $13, %xmm0
1976         psrldq  $13, %xmm3
1977         jmp     LABEL(aftertail)
1980  *  The following cases will be handled by ashr_14
1981  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1982  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1983  */
1984         .p2align 4
1985 LABEL(ashr_14):
1986         pxor    %xmm0, %xmm0
1987         movdqa  (%rdi), %xmm2
1988         movdqa  (%rsi), %xmm1
1989         pcmpeqb %xmm1, %xmm0
1990         pslldq  $2, %xmm2
1991         TOLOWER (%xmm1, %xmm2)
1992         pcmpeqb %xmm1, %xmm2
1993         psubb   %xmm0, %xmm2
1994         pmovmskb %xmm2, %r9d
1995         shr     %cl, %edx
1996         shr     %cl, %r9d
1997         sub     %r9d, %edx
1998         jnz     LABEL(less32bytes)
1999         movdqa  (%rdi), %xmm3
2001         UPDATE_STRNCMP_COUNTER
2003         pxor    %xmm0, %xmm0
2004         mov     $16, %rcx       /* index for loads */
2005         mov     $14, %r9d       /* byte position left over from less32bytes case */
2006         /*
2007          * Setup %r10 value allows us to detect crossing a page boundary.
2008          * When %r10 goes positive we have crossed a page boundary and
2009          * need to do a nibble.
2010          */
2011         lea     14(%rdi), %r10
2012         and     $0xfff, %r10    /* offset into 4K page */
2013         sub     $0x1000, %r10   /* subtract 4K pagesize */
2015         .p2align 4
2016 LABEL(loop_ashr_14):
2017         add     $16, %r10
2018         jg      LABEL(nibble_ashr_14)
2020 LABEL(gobble_ashr_14):
2021         movdqa  (%rsi, %rcx), %xmm1
2022         movdqa  (%rdi, %rcx), %xmm2
2023         movdqa  %xmm2, %xmm4
2025 # ifndef USE_SSSE3
2026         psrldq  $14, %xmm3
2027         pslldq  $2, %xmm2
2028         por     %xmm3, %xmm2            /* merge into one 16byte value */
2029 # else
2030         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
2031 # endif
2032         TOLOWER (%xmm1, %xmm2)
2034         pcmpeqb %xmm1, %xmm0
2035         pcmpeqb %xmm2, %xmm1
2036         psubb   %xmm0, %xmm1
2037         pmovmskb %xmm1, %edx
2038         sub     $0xffff, %edx
2039         jnz     LABEL(exit)
2041 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2042         sub     $16, %r11
2043         jbe     LABEL(strcmp_exitz)
2044 # endif
2046         add     $16, %rcx
2047         movdqa  %xmm4, %xmm3
2049         add     $16, %r10
2050         jg      LABEL(nibble_ashr_14)   /* cross page boundary */
2052         movdqa  (%rsi, %rcx), %xmm1
2053         movdqa  (%rdi, %rcx), %xmm2
2054         movdqa  %xmm2, %xmm4
2056 # ifndef USE_SSSE3
2057         psrldq  $14, %xmm3
2058         pslldq  $2, %xmm2
2059         por     %xmm3, %xmm2            /* merge into one 16byte value */
2060 # else
2061         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
2062 # endif
2063         TOLOWER (%xmm1, %xmm2)
2065         pcmpeqb %xmm1, %xmm0
2066         pcmpeqb %xmm2, %xmm1
2067         psubb   %xmm0, %xmm1
2068         pmovmskb %xmm1, %edx
2069         sub     $0xffff, %edx
2070         jnz     LABEL(exit)
2072 # if defined USE_AS_STRNCMP | defined USE_AS_STRNCASECMP_L
2073         sub     $16, %r11
2074         jbe     LABEL(strcmp_exitz)
2075 # endif
2077         add     $16, %rcx
2078         movdqa  %xmm4, %xmm3
2079         jmp     LABEL(loop_ashr_14)
2081         .p2align 4
2082 LABEL(nibble_ashr_14):
2083         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2084         pmovmskb %xmm0, %edx
2085         test    $0xc000, %edx
2086         jnz     LABEL(ashr_14_exittail)
2088 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2089         cmp     $1, %r11
2090         jbe     LABEL(ashr_14_exittail)
2091 # endif
2093         pxor    %xmm0, %xmm0
2094         sub     $0x1000, %r10
2095         jmp     LABEL(gobble_ashr_14)
2097         .p2align 4
2098 LABEL(ashr_14_exittail):
2099         movdqa  (%rsi, %rcx), %xmm1
2100         psrldq  $14, %xmm0
2101         psrldq  $14, %xmm3
2102         jmp     LABEL(aftertail)
2105  *  The following cases will be handled by ashr_15
2106  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
2107  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
2108  */
2109         .p2align 4
2110 LABEL(ashr_15):
2111         pxor    %xmm0, %xmm0
2112         movdqa  (%rdi), %xmm2
2113         movdqa  (%rsi), %xmm1
2114         pcmpeqb %xmm1, %xmm0
2115         pslldq  $1, %xmm2
2116         TOLOWER (%xmm1, %xmm2)
2117         pcmpeqb %xmm1, %xmm2
2118         psubb   %xmm0, %xmm2
2119         pmovmskb %xmm2, %r9d
2120         shr     %cl, %edx
2121         shr     %cl, %r9d
2122         sub     %r9d, %edx
2123         jnz     LABEL(less32bytes)
2125         movdqa  (%rdi), %xmm3
2127         UPDATE_STRNCMP_COUNTER
2129         pxor    %xmm0, %xmm0
2130         mov     $16, %rcx       /* index for loads */
2131         mov     $15, %r9d       /* byte position left over from less32bytes case */
2132         /*
2133          * Setup %r10 value allows us to detect crossing a page boundary.
2134          * When %r10 goes positive we have crossed a page boundary and
2135          * need to do a nibble.
2136          */
2137         lea     15(%rdi), %r10
2138         and     $0xfff, %r10    /* offset into 4K page */
2140         sub     $0x1000, %r10   /* subtract 4K pagesize */
2142         .p2align 4
2143 LABEL(loop_ashr_15):
2144         add     $16, %r10
2145         jg      LABEL(nibble_ashr_15)
2147 LABEL(gobble_ashr_15):
2148         movdqa  (%rsi, %rcx), %xmm1
2149         movdqa  (%rdi, %rcx), %xmm2
2150         movdqa  %xmm2, %xmm4
2152 # ifndef USE_SSSE3
2153         psrldq  $15, %xmm3
2154         pslldq  $1, %xmm2
2155         por     %xmm3, %xmm2            /* merge into one 16byte value */
2156 # else
2157         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2158 # endif
2159         TOLOWER (%xmm1, %xmm2)
2161         pcmpeqb %xmm1, %xmm0
2162         pcmpeqb %xmm2, %xmm1
2163         psubb   %xmm0, %xmm1
2164         pmovmskb %xmm1, %edx
2165         sub     $0xffff, %edx
2166         jnz     LABEL(exit)
2168 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2169         sub     $16, %r11
2170         jbe     LABEL(strcmp_exitz)
2171 # endif
2173         add     $16, %rcx
2174         movdqa  %xmm4, %xmm3
2176         add     $16, %r10
2177         jg      LABEL(nibble_ashr_15)   /* cross page boundary */
2179         movdqa  (%rsi, %rcx), %xmm1
2180         movdqa  (%rdi, %rcx), %xmm2
2181         movdqa  %xmm2, %xmm4
2183 # ifndef USE_SSSE3
2184         psrldq  $15, %xmm3
2185         pslldq  $1, %xmm2
2186         por     %xmm3, %xmm2            /* merge into one 16byte value */
2187 # else
2188         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2189 # endif
2190         TOLOWER (%xmm1, %xmm2)
2192         pcmpeqb %xmm1, %xmm0
2193         pcmpeqb %xmm2, %xmm1
2194         psubb   %xmm0, %xmm1
2195         pmovmskb %xmm1, %edx
2196         sub     $0xffff, %edx
2197         jnz     LABEL(exit)
2199 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2200         sub     $16, %r11
2201         jbe     LABEL(strcmp_exitz)
2202 # endif
2204         add     $16, %rcx
2205         movdqa  %xmm4, %xmm3
2206         jmp     LABEL(loop_ashr_15)
2208         .p2align 4
2209 LABEL(nibble_ashr_15):
2210         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2211         pmovmskb %xmm0, %edx
2212         test    $0x8000, %edx
2213         jnz     LABEL(ashr_15_exittail)
2215 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2216         test    %r11, %r11
2217         je      LABEL(ashr_15_exittail)
2218 # endif
2220         pxor    %xmm0, %xmm0
2221         sub     $0x1000, %r10
2222         jmp     LABEL(gobble_ashr_15)
2224         .p2align 4
2225 LABEL(ashr_15_exittail):
2226         movdqa  (%rsi, %rcx), %xmm1
2227         psrldq  $15, %xmm3
2228         psrldq  $15, %xmm0
2230         .p2align 4
2231 LABEL(aftertail):
2232         TOLOWER (%xmm1, %xmm3)
2233         pcmpeqb %xmm3, %xmm1
2234         psubb   %xmm0, %xmm1
2235         pmovmskb %xmm1, %edx
2236         not     %edx
2238         .p2align 4
2239 LABEL(exit):
2240         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
2241 LABEL(less32bytes):
2242         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
2243         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
2244         test    %r8d, %r8d
2245         jz      LABEL(ret)
2246         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
2248         .p2align 4
2249 LABEL(ret):
2250 LABEL(less16bytes):
2251         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
2253 # if defined USE_AS_STRNCMP || defined USE_AS_STRNCASECMP_L
2254         sub     %rdx, %r11
2255         jbe     LABEL(strcmp_exitz)
2256 # endif
2257         movzbl  (%rsi, %rdx), %ecx
2258         movzbl  (%rdi, %rdx), %eax
2260 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
2261         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
2262         movl    (%rdx,%rcx,4), %ecx
2263         movl    (%rdx,%rax,4), %eax
2264 # endif
2266         sub     %ecx, %eax
2267         ret
2269 LABEL(strcmp_exitz):
2270         xor     %eax, %eax
2271         ret
2273         .p2align 4
2274 LABEL(Byte0):
2275         movzx   (%rsi), %ecx
2276         movzx   (%rdi), %eax
2278 # if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
2279         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
2280         movl    (%rdx,%rcx,4), %ecx
2281         movl    (%rdx,%rax,4), %eax
2282 # endif
2284         sub     %ecx, %eax
2285         ret
2286 END (BP_SYM (STRCMP))
2288         .section .rodata,"a",@progbits
2289         .p2align 3
2290 LABEL(unaligned_table):
2291         .int    LABEL(ashr_1) - LABEL(unaligned_table)
2292         .int    LABEL(ashr_2) - LABEL(unaligned_table)
2293         .int    LABEL(ashr_3) - LABEL(unaligned_table)
2294         .int    LABEL(ashr_4) - LABEL(unaligned_table)
2295         .int    LABEL(ashr_5) - LABEL(unaligned_table)
2296         .int    LABEL(ashr_6) - LABEL(unaligned_table)
2297         .int    LABEL(ashr_7) - LABEL(unaligned_table)
2298         .int    LABEL(ashr_8) - LABEL(unaligned_table)
2299         .int    LABEL(ashr_9) - LABEL(unaligned_table)
2300         .int    LABEL(ashr_10) - LABEL(unaligned_table)
2301         .int    LABEL(ashr_11) - LABEL(unaligned_table)
2302         .int    LABEL(ashr_12) - LABEL(unaligned_table)
2303         .int    LABEL(ashr_13) - LABEL(unaligned_table)
2304         .int    LABEL(ashr_14) - LABEL(unaligned_table)
2305         .int    LABEL(ashr_15) - LABEL(unaligned_table)
2306         .int    LABEL(ashr_0) - LABEL(unaligned_table)
2307 #endif /* NOT_IN_libc */
2308 libc_hidden_builtin_def (STRCMP)