Implement optimized strcaecmp for x86-64.
[glibc.git] / sysdeps / x86_64 / strcmp.S
blob7b2b24686625c20b6ba81591a1c652420845dfde
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 #else
64 # define UPDATE_STRNCMP_COUNTER
65 # ifndef STRCMP
66 #  define STRCMP strcmp
67 # endif
68 #endif
70 #ifndef USE_SSSE3
71         .text
72 #else
73         .section .text.ssse3,"ax",@progbits
74 #endif
76 #ifdef USE_AS_STRCASECMP_L
77 ENTRY (__strcasecmp)
78         movq    __libc_tsd_LOCALE@gottpoff(%rip),%rax
79         movq    %fs:(%rax),%rdx
81         /* 5-byte NOP.  */
82         .byte   0x0f,0x1f,0x44,0x00,0x00
83 END (__strcasecmp)
84 weak_alias (__strcasecmp, strcasecmp)
85 libc_hidden_def (__strcasecmp)
86         /* FALLTHROUGH to strcasecmp_l.  */
87 #endif
89 ENTRY (BP_SYM (STRCMP))
90 #ifdef NOT_IN_libc
91 /* Simple version since we can't use SSE registers in ld.so.  */
92 L(oop): movb    (%rdi), %al
93         cmpb    (%rsi), %al
94         jne     L(neq)
95         incq    %rdi
96         incq    %rsi
97         testb   %al, %al
98         jnz     L(oop)
100         xorl    %eax, %eax
101         ret
103 L(neq): movl    $1, %eax
104         movl    $-1, %ecx
105         cmovbl  %ecx, %eax
106         ret
107 END (BP_SYM (STRCMP))
108 #else   /* NOT_IN_libc */
109 # ifdef USE_AS_STRCASECMP_L
110         /* We have to fall back on the C implementation for locales
111            with encodings not matching ASCII for single bytes.  */
112 #  if LOCALE_T___LOCALES != 0 || LC_CTYPE != 0
113         movq    LOCALE_T___LOCALES+LC_CTYPE*8(%rdx), %rax
114 #  else
115         movq    (%rdx), %rax
116 #  endif
117         testl   $0, LOCALE_DATA_VALUES+_NL_CTYPE_NONASCII_CASE*SIZEOF_VALUES(%rax)
118         jne     __strcasecmp_l_nonascii
119 # endif
122  * This implementation uses SSE to compare up to 16 bytes at a time.
123  */
124 # ifdef USE_AS_STRNCMP
125         test    %rdx, %rdx
126         je      LABEL(strcmp_exitz)
127         cmp     $1, %rdx
128         je      LABEL(Byte0)
129         mov     %rdx, %r11
130 # endif
131         mov     %esi, %ecx
132         mov     %edi, %eax
133 /* Use 64bit AND here to avoid long NOP padding.  */
134         and     $0x3f, %rcx             /* rsi alignment in cache line */
135         and     $0x3f, %rax             /* rdi alignment in cache line */
136 # ifdef USE_AS_STRCASECMP_L
137         .section .rodata.cst16,"aM",@progbits,16
138         .align 16
139 .Lbelowupper:
140         .quad   0x4040404040404040
141         .quad   0x4040404040404040
142 .Ltopupper:
143         .quad   0x5b5b5b5b5b5b5b5b
144         .quad   0x5b5b5b5b5b5b5b5b
145 .Ltouppermask:
146         .quad   0x2020202020202020
147         .quad   0x2020202020202020
148         .previous
149         movdqa  .Lbelowupper(%rip), %xmm5
150 # define UCLOW_reg %xmm5
151         movdqa  .Ltopupper(%rip), %xmm6
152 # define UCHIGH_reg %xmm6
153         movdqa  .Ltouppermask(%rip), %xmm7
154 # define LCQWORD_reg %xmm7
155 # endif
156         cmp     $0x30, %ecx
157         ja      LABEL(crosscache)       /* rsi: 16-byte load will cross cache line */
158         cmp     $0x30, %eax
159         ja      LABEL(crosscache)       /* rdi: 16-byte load will cross cache line */
160         movlpd  (%rdi), %xmm1
161         movlpd  (%rsi), %xmm2
162         movhpd  8(%rdi), %xmm1
163         movhpd  8(%rsi), %xmm2
164 # ifdef USE_AS_STRCASECMP_L
165 #  define TOLOWER(reg1, reg2) \
166         movdqa  reg1, %xmm8;                                    \
167         movdqa  UCHIGH_reg, %xmm9;                              \
168         movdqa  reg2, %xmm10;                                   \
169         movdqa  UCHIGH_reg, %xmm11;                             \
170         pcmpgtb UCLOW_reg, %xmm8;                               \
171         pcmpgtb reg1, %xmm9;                                    \
172         pcmpgtb UCLOW_reg, %xmm10;                              \
173         pcmpgtb reg2, %xmm11;                                   \
174         pand    %xmm9, %xmm8;                                   \
175         pand    %xmm11, %xmm10;                                 \
176         pand    LCQWORD_reg, %xmm8;                             \
177         pand    LCQWORD_reg, %xmm10;                            \
178         por     %xmm8, reg1;                                    \
179         por     %xmm10, reg2
180         TOLOWER (%xmm1, %xmm2)
181 # else
182 #  define TOLOWER(reg1, reg2)
183 # endif
184         pxor    %xmm0, %xmm0            /* clear %xmm0 for null char checks */
185         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
186         pcmpeqb %xmm2, %xmm1            /* compare first 16 bytes for equality */
187         psubb   %xmm0, %xmm1            /* packed sub of comparison results*/
188         pmovmskb %xmm1, %edx
189         sub     $0xffff, %edx           /* if first 16 bytes are same, edx == 0xffff */
190         jnz     LABEL(less16bytes)      /* If not, find different value or null char */
191 # ifdef USE_AS_STRNCMP
192         sub     $16, %r11
193         jbe     LABEL(strcmp_exitz)     /* finish comparision */
194 # endif
195         add     $16, %rsi               /* prepare to search next 16 bytes */
196         add     $16, %rdi               /* prepare to search next 16 bytes */
198         /*
199          * Determine source and destination string offsets from 16-byte alignment.
200          * Use relative offset difference between the two to determine which case
201          * below to use.
202          */
203         .p2align 4
204 LABEL(crosscache):
205         and     $0xfffffffffffffff0, %rsi       /* force %rsi is 16 byte aligned */
206         and     $0xfffffffffffffff0, %rdi       /* force %rdi is 16 byte aligned */
207         mov     $0xffff, %edx                   /* for equivalent offset */
208         xor     %r8d, %r8d
209         and     $0xf, %ecx                      /* offset of rsi */
210         and     $0xf, %eax                      /* offset of rdi */
211         cmp     %eax, %ecx
212         je      LABEL(ashr_0)                   /* rsi and rdi relative offset same */
213         ja      LABEL(bigger)
214         mov     %edx, %r8d                      /* r8d is offset flag for exit tail */
215         xchg    %ecx, %eax
216         xchg    %rsi, %rdi
217 LABEL(bigger):
218         lea     15(%rax), %r9
219         sub     %rcx, %r9
220         lea     LABEL(unaligned_table)(%rip), %r10
221         movslq  (%r10, %r9,4), %r9
222         lea     (%r10, %r9), %r10
223         jmp     *%r10                           /* jump to corresponding case */
226  * The following cases will be handled by ashr_0
227  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset  corresponding case
228  *        n(0~15)            n(0~15)           15(15+ n-n)         ashr_0
229  */
230         .p2align 4
231 LABEL(ashr_0):
233         movdqa  (%rsi), %xmm1
234         pxor    %xmm0, %xmm0                    /* clear %xmm0 for null char check */
235         pcmpeqb %xmm1, %xmm0                    /* Any null chars? */
236 # ifndef USE_AS_STRCASECMP_L
237         pcmpeqb (%rdi), %xmm1                   /* compare 16 bytes for equality */
238 # else
239         movdqa  (%rdi), %xmm2
240         TOLOWER (%xmm1, %xmm2)
241         pcmpeqb %xmm2, %xmm1                    /* compare 16 bytes for equality */
242 # endif
243         psubb   %xmm0, %xmm1                    /* packed sub of comparison results*/
244         pmovmskb %xmm1, %r9d
245         shr     %cl, %edx                       /* adjust 0xffff for offset */
246         shr     %cl, %r9d                       /* adjust for 16-byte offset */
247         sub     %r9d, %edx
248         /*
249          * edx must be the same with r9d if in left byte (16-rcx) is equal to
250          * the start from (16-rax) and no null char was seen.
251          */
252         jne     LABEL(less32bytes)              /* mismatch or null char */
253         UPDATE_STRNCMP_COUNTER
254         mov     $16, %rcx
255         mov     $16, %r9
256         pxor    %xmm0, %xmm0                    /* clear xmm0, may have changed above */
258         /*
259          * Now both strings are aligned at 16-byte boundary. Loop over strings
260          * checking 32-bytes per iteration.
261          */
262         .p2align 4
263 LABEL(loop_ashr_0):
264         movdqa  (%rsi, %rcx), %xmm1
265         movdqa  (%rdi, %rcx), %xmm2
266         TOLOWER (%xmm1, %xmm2)
268         pcmpeqb %xmm1, %xmm0
269         pcmpeqb %xmm2, %xmm1
270         psubb   %xmm0, %xmm1
271         pmovmskb %xmm1, %edx
272         sub     $0xffff, %edx
273         jnz     LABEL(exit)             /* mismatch or null char seen */
275 # ifdef USE_AS_STRNCMP
276         sub     $16, %r11
277         jbe     LABEL(strcmp_exitz)
278 # endif
279         add     $16, %rcx
280         movdqa  (%rsi, %rcx), %xmm1
281         movdqa  (%rdi, %rcx), %xmm2
282         TOLOWER (%xmm1, %xmm2)
284         pcmpeqb %xmm1, %xmm0
285         pcmpeqb %xmm2, %xmm1
286         psubb   %xmm0, %xmm1
287         pmovmskb %xmm1, %edx
288         sub     $0xffff, %edx
289         jnz     LABEL(exit)
290 # ifdef USE_AS_STRNCMP
291         sub     $16, %r11
292         jbe     LABEL(strcmp_exitz)
293 # endif
294         add     $16, %rcx
295         jmp     LABEL(loop_ashr_0)
298  * The following cases will be handled by ashr_1
299  * rcx(offset of rsi)  rax(offset of rdi)   relative offset     corresponding case
300  *        n(15)            n -15            0(15 +(n-15) - n)         ashr_1
301  */
302         .p2align 4
303 LABEL(ashr_1):
304         pxor    %xmm0, %xmm0
305         movdqa  (%rdi), %xmm2
306         movdqa  (%rsi), %xmm1
307         pcmpeqb %xmm1, %xmm0            /* Any null chars? */
308         pslldq  $15, %xmm2              /* shift first string to align with second */
309         TOLOWER (%xmm1, %xmm2)
310         pcmpeqb %xmm1, %xmm2            /* compare 16 bytes for equality */
311         psubb   %xmm0, %xmm2            /* packed sub of comparison results*/
312         pmovmskb %xmm2, %r9d
313         shr     %cl, %edx               /* adjust 0xffff for offset */
314         shr     %cl, %r9d               /* adjust for 16-byte offset */
315         sub     %r9d, %edx
316         jnz     LABEL(less32bytes)      /* mismatch or null char seen */
317         movdqa  (%rdi), %xmm3
318         UPDATE_STRNCMP_COUNTER
320         pxor    %xmm0, %xmm0
321         mov     $16, %rcx               /* index for loads*/
322         mov     $1, %r9d                /* byte position left over from less32bytes case */
323         /*
324          * Setup %r10 value allows us to detect crossing a page boundary.
325          * When %r10 goes positive we have crossed a page boundary and
326          * need to do a nibble.
327          */
328         lea     1(%rdi), %r10
329         and     $0xfff, %r10            /* offset into 4K page */
330         sub     $0x1000, %r10           /* subtract 4K pagesize */
332         .p2align 4
333 LABEL(loop_ashr_1):
334         add     $16, %r10
335         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
337 LABEL(gobble_ashr_1):
338         movdqa  (%rsi, %rcx), %xmm1
339         movdqa  (%rdi, %rcx), %xmm2
340         movdqa  %xmm2, %xmm4             /* store for next cycle */
342 # ifndef USE_SSSE3
343         psrldq  $1, %xmm3
344         pslldq  $15, %xmm2
345         por     %xmm3, %xmm2            /* merge into one 16byte value */
346 # else
347         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
348 # endif
349         TOLOWER (%xmm1, %xmm2)
351         pcmpeqb %xmm1, %xmm0
352         pcmpeqb %xmm2, %xmm1
353         psubb   %xmm0, %xmm1
354         pmovmskb %xmm1, %edx
355         sub     $0xffff, %edx
356         jnz     LABEL(exit)
358 # ifdef USE_AS_STRNCMP
359         sub     $16, %r11
360         jbe     LABEL(strcmp_exitz)
361 # endif
362         add     $16, %rcx
363         movdqa  %xmm4, %xmm3
365         add     $16, %r10
366         jg      LABEL(nibble_ashr_1)    /* cross page boundary */
368         movdqa  (%rsi, %rcx), %xmm1
369         movdqa  (%rdi, %rcx), %xmm2
370         movdqa  %xmm2, %xmm4            /* store for next cycle */
372 # ifndef USE_SSSE3
373         psrldq  $1, %xmm3
374         pslldq  $15, %xmm2
375         por     %xmm3, %xmm2            /* merge into one 16byte value */
376 # else
377         palignr $1, %xmm3, %xmm2        /* merge into one 16byte value */
378 # endif
379         TOLOWER (%xmm1, %xmm2)
381         pcmpeqb %xmm1, %xmm0
382         pcmpeqb %xmm2, %xmm1
383         psubb   %xmm0, %xmm1
384         pmovmskb %xmm1, %edx
385         sub     $0xffff, %edx
386         jnz     LABEL(exit)
388 # ifdef USE_AS_STRNCMP
389         sub     $16, %r11
390         jbe     LABEL(strcmp_exitz)
391 # endif
392         add     $16, %rcx
393         movdqa  %xmm4, %xmm3
394         jmp     LABEL(loop_ashr_1)
396         /*
397          * Nibble avoids loads across page boundary. This is to avoid a potential
398          * access into unmapped memory.
399          */
400         .p2align 4
401 LABEL(nibble_ashr_1):
402         pcmpeqb %xmm3, %xmm0             /* check nibble for null char*/
403         pmovmskb %xmm0, %edx
404         test    $0xfffe, %edx
405         jnz     LABEL(ashr_1_exittail)  /* find null char*/
407 # ifdef USE_AS_STRNCMP
408         cmp     $14, %r11
409         jbe     LABEL(ashr_1_exittail)
410 # endif
412         pxor    %xmm0, %xmm0
413         sub     $0x1000, %r10           /* substract 4K from %r10 */
414         jmp     LABEL(gobble_ashr_1)
416         /*
417          * Once find null char, determine if there is a string mismatch
418          * before the null char.
419          */
420         .p2align 4
421 LABEL(ashr_1_exittail):
422         movdqa  (%rsi, %rcx), %xmm1
423         psrldq  $1, %xmm0
424         psrldq  $1, %xmm3
425         jmp     LABEL(aftertail)
428  * The following cases will be handled by ashr_2
429  * rcx(offset of rsi)  rax(offset of rdi)   relative offset   corresponding case
430  *        n(14~15)            n -14         1(15 +(n-14) - n)         ashr_2
431  */
432         .p2align 4
433 LABEL(ashr_2):
434         pxor    %xmm0, %xmm0
435         movdqa  (%rdi), %xmm2
436         movdqa  (%rsi), %xmm1
437         pcmpeqb %xmm1, %xmm0
438         pslldq  $14, %xmm2
439         TOLOWER (%xmm1, %xmm2)
440         pcmpeqb %xmm1, %xmm2
441         psubb   %xmm0, %xmm2
442         pmovmskb %xmm2, %r9d
443         shr     %cl, %edx
444         shr     %cl, %r9d
445         sub     %r9d, %edx
446         jnz     LABEL(less32bytes)
447         movdqa  (%rdi), %xmm3
448         UPDATE_STRNCMP_COUNTER
450         pxor    %xmm0, %xmm0
451         mov     $16, %rcx       /* index for loads */
452         mov     $2, %r9d        /* byte position left over from less32bytes case */
453         /*
454          * Setup %r10 value allows us to detect crossing a page boundary.
455          * When %r10 goes positive we have crossed a page boundary and
456          * need to do a nibble.
457          */
458         lea     2(%rdi), %r10
459         and     $0xfff, %r10    /* offset into 4K page */
460         sub     $0x1000, %r10   /* subtract 4K pagesize */
462         .p2align 4
463 LABEL(loop_ashr_2):
464         add     $16, %r10
465         jg      LABEL(nibble_ashr_2)
467 LABEL(gobble_ashr_2):
468         movdqa  (%rsi, %rcx), %xmm1
469         movdqa  (%rdi, %rcx), %xmm2
470         movdqa  %xmm2, %xmm4
472 # ifndef USE_SSSE3
473         psrldq  $2, %xmm3
474         pslldq  $14, %xmm2
475         por     %xmm3, %xmm2            /* merge into one 16byte value */
476 # else
477         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
478 # endif
479         TOLOWER (%xmm1, %xmm2)
481         pcmpeqb %xmm1, %xmm0
482         pcmpeqb %xmm2, %xmm1
483         psubb   %xmm0, %xmm1
484         pmovmskb %xmm1, %edx
485         sub     $0xffff, %edx
486         jnz     LABEL(exit)
488 # ifdef USE_AS_STRNCMP
489         sub     $16, %r11
490         jbe     LABEL(strcmp_exitz)
491 # endif
493         add     $16, %rcx
494         movdqa  %xmm4, %xmm3
496         add     $16, %r10
497         jg      LABEL(nibble_ashr_2)    /* cross page boundary */
499         movdqa  (%rsi, %rcx), %xmm1
500         movdqa  (%rdi, %rcx), %xmm2
501         movdqa  %xmm2, %xmm4
503 # ifndef USE_SSSE3
504         psrldq  $2, %xmm3
505         pslldq  $14, %xmm2
506         por     %xmm3, %xmm2            /* merge into one 16byte value */
507 # else
508         palignr $2, %xmm3, %xmm2        /* merge into one 16byte value */
509 # endif
510         TOLOWER (%xmm1, %xmm2)
512         pcmpeqb %xmm1, %xmm0
513         pcmpeqb %xmm2, %xmm1
514         psubb   %xmm0, %xmm1
515         pmovmskb %xmm1, %edx
516         sub     $0xffff, %edx
517         jnz     LABEL(exit)
519 # ifdef USE_AS_STRNCMP
520         sub     $16, %r11
521         jbe     LABEL(strcmp_exitz)
522 # endif
524         add     $16, %rcx
525         movdqa  %xmm4, %xmm3
526         jmp     LABEL(loop_ashr_2)
528         .p2align 4
529 LABEL(nibble_ashr_2):
530         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
531         pmovmskb %xmm0, %edx
532         test    $0xfffc, %edx
533         jnz     LABEL(ashr_2_exittail)
535 # ifdef USE_AS_STRNCMP
536         cmp     $13, %r11
537         jbe     LABEL(ashr_2_exittail)
538 # endif
540         pxor    %xmm0, %xmm0
541         sub     $0x1000, %r10
542         jmp     LABEL(gobble_ashr_2)
544         .p2align 4
545 LABEL(ashr_2_exittail):
546         movdqa  (%rsi, %rcx), %xmm1
547         psrldq  $2, %xmm0
548         psrldq  $2, %xmm3
549         jmp     LABEL(aftertail)
552  * The following cases will be handled by ashr_3
553  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
554  *        n(13~15)            n -13         2(15 +(n-13) - n)         ashr_3
555  */
556         .p2align 4
557 LABEL(ashr_3):
558         pxor    %xmm0, %xmm0
559         movdqa  (%rdi), %xmm2
560         movdqa  (%rsi), %xmm1
561         pcmpeqb %xmm1, %xmm0
562         pslldq  $13, %xmm2
563         TOLOWER (%xmm1, %xmm2)
564         pcmpeqb %xmm1, %xmm2
565         psubb   %xmm0, %xmm2
566         pmovmskb %xmm2, %r9d
567         shr     %cl, %edx
568         shr     %cl, %r9d
569         sub     %r9d, %edx
570         jnz     LABEL(less32bytes)
571         movdqa  (%rdi), %xmm3
573         UPDATE_STRNCMP_COUNTER
575         pxor    %xmm0, %xmm0
576         mov     $16, %rcx       /* index for loads */
577         mov     $3, %r9d        /* byte position left over from less32bytes case */
578         /*
579          * Setup %r10 value allows us to detect crossing a page boundary.
580          * When %r10 goes positive we have crossed a page boundary and
581          * need to do a nibble.
582          */
583         lea     3(%rdi), %r10
584         and     $0xfff, %r10    /* offset into 4K page */
585         sub     $0x1000, %r10   /* subtract 4K pagesize */
587         .p2align 4
588 LABEL(loop_ashr_3):
589         add     $16, %r10
590         jg      LABEL(nibble_ashr_3)
592 LABEL(gobble_ashr_3):
593         movdqa  (%rsi, %rcx), %xmm1
594         movdqa  (%rdi, %rcx), %xmm2
595         movdqa  %xmm2, %xmm4
597 # ifndef USE_SSSE3
598         psrldq  $3, %xmm3
599         pslldq  $13, %xmm2
600         por     %xmm3, %xmm2            /* merge into one 16byte value */
601 # else
602         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
603 # endif
604         TOLOWER (%xmm1, %xmm2)
606         pcmpeqb %xmm1, %xmm0
607         pcmpeqb %xmm2, %xmm1
608         psubb   %xmm0, %xmm1
609         pmovmskb %xmm1, %edx
610         sub     $0xffff, %edx
611         jnz     LABEL(exit)
613 # ifdef USE_AS_STRNCMP
614         sub     $16, %r11
615         jbe     LABEL(strcmp_exitz)
616 # endif
618         add     $16, %rcx
619         movdqa  %xmm4, %xmm3
621         add     $16, %r10
622         jg      LABEL(nibble_ashr_3)    /* cross page boundary */
624         movdqa  (%rsi, %rcx), %xmm1
625         movdqa  (%rdi, %rcx), %xmm2
626         movdqa  %xmm2, %xmm4
628 # ifndef USE_SSSE3
629         psrldq  $3, %xmm3
630         pslldq  $13, %xmm2
631         por     %xmm3, %xmm2            /* merge into one 16byte value */
632 # else
633         palignr $3, %xmm3, %xmm2        /* merge into one 16byte value */
634 # endif
635         TOLOWER (%xmm1, %xmm2)
637         pcmpeqb %xmm1, %xmm0
638         pcmpeqb %xmm2, %xmm1
639         psubb   %xmm0, %xmm1
640         pmovmskb %xmm1, %edx
641         sub     $0xffff, %edx
642         jnz     LABEL(exit)
644 # ifdef USE_AS_STRNCMP
645         sub     $16, %r11
646         jbe     LABEL(strcmp_exitz)
647 # endif
649         add     $16, %rcx
650         movdqa  %xmm4, %xmm3
651         jmp     LABEL(loop_ashr_3)
653         .p2align 4
654 LABEL(nibble_ashr_3):
655         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
656         pmovmskb %xmm0, %edx
657         test    $0xfff8, %edx
658         jnz     LABEL(ashr_3_exittail)
660 # ifdef USE_AS_STRNCMP
661         cmp     $12, %r11
662         jbe     LABEL(ashr_3_exittail)
663 # endif
665         pxor    %xmm0, %xmm0
666         sub     $0x1000, %r10
667         jmp     LABEL(gobble_ashr_3)
669         .p2align 4
670 LABEL(ashr_3_exittail):
671         movdqa  (%rsi, %rcx), %xmm1
672         psrldq  $3, %xmm0
673         psrldq  $3, %xmm3
674         jmp     LABEL(aftertail)
677  * The following cases will be handled by ashr_4
678  *  rcx(offset of rsi)  rax(offset of rdi)  relative offset      corresponding case
679  *        n(12~15)            n -12         3(15 +(n-12) - n)         ashr_4
680  */
681         .p2align 4
682 LABEL(ashr_4):
683         pxor    %xmm0, %xmm0
684         movdqa  (%rdi), %xmm2
685         movdqa  (%rsi), %xmm1
686         pcmpeqb %xmm1, %xmm0
687         pslldq  $12, %xmm2
688         TOLOWER (%xmm1, %xmm2)
689         pcmpeqb %xmm1, %xmm2
690         psubb   %xmm0, %xmm2
691         pmovmskb %xmm2, %r9d
692         shr     %cl, %edx
693         shr     %cl, %r9d
694         sub     %r9d, %edx
695         jnz     LABEL(less32bytes)
696         movdqa  (%rdi), %xmm3
698         UPDATE_STRNCMP_COUNTER
700         pxor    %xmm0, %xmm0
701         mov     $16, %rcx       /* index for loads */
702         mov     $4, %r9d        /* byte position left over from less32bytes case */
703         /*
704          * Setup %r10 value allows us to detect crossing a page boundary.
705          * When %r10 goes positive we have crossed a page boundary and
706          * need to do a nibble.
707          */
708         lea     4(%rdi), %r10
709         and     $0xfff, %r10    /* offset into 4K page */
710         sub     $0x1000, %r10   /* subtract 4K pagesize */
712         .p2align 4
713 LABEL(loop_ashr_4):
714         add     $16, %r10
715         jg      LABEL(nibble_ashr_4)
717 LABEL(gobble_ashr_4):
718         movdqa  (%rsi, %rcx), %xmm1
719         movdqa  (%rdi, %rcx), %xmm2
720         movdqa  %xmm2, %xmm4
722 # ifndef USE_SSSE3
723         psrldq  $4, %xmm3
724         pslldq  $12, %xmm2
725         por     %xmm3, %xmm2            /* merge into one 16byte value */
726 # else
727         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
728 # endif
729         TOLOWER (%xmm1, %xmm2)
731         pcmpeqb %xmm1, %xmm0
732         pcmpeqb %xmm2, %xmm1
733         psubb   %xmm0, %xmm1
734         pmovmskb %xmm1, %edx
735         sub     $0xffff, %edx
736         jnz     LABEL(exit)
738 # ifdef USE_AS_STRNCMP
739         sub     $16, %r11
740         jbe     LABEL(strcmp_exitz)
741 # endif
743         add     $16, %rcx
744         movdqa  %xmm4, %xmm3
746         add     $16, %r10
747         jg      LABEL(nibble_ashr_4)    /* cross page boundary */
749         movdqa  (%rsi, %rcx), %xmm1
750         movdqa  (%rdi, %rcx), %xmm2
751         movdqa  %xmm2, %xmm4
753 # ifndef USE_SSSE3
754         psrldq  $4, %xmm3
755         pslldq  $12, %xmm2
756         por     %xmm3, %xmm2            /* merge into one 16byte value */
757 # else
758         palignr $4, %xmm3, %xmm2        /* merge into one 16byte value */
759 # endif
760         TOLOWER (%xmm1, %xmm2)
762         pcmpeqb %xmm1, %xmm0
763         pcmpeqb %xmm2, %xmm1
764         psubb   %xmm0, %xmm1
765         pmovmskb %xmm1, %edx
766         sub     $0xffff, %edx
767         jnz     LABEL(exit)
769 # ifdef USE_AS_STRNCMP
770         sub     $16, %r11
771         jbe     LABEL(strcmp_exitz)
772 # endif
774         add     $16, %rcx
775         movdqa  %xmm4, %xmm3
776         jmp     LABEL(loop_ashr_4)
778         .p2align 4
779 LABEL(nibble_ashr_4):
780         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
781         pmovmskb %xmm0, %edx
782         test    $0xfff0, %edx
783         jnz     LABEL(ashr_4_exittail)
785 # ifdef USE_AS_STRNCMP
786         cmp     $11, %r11
787         jbe     LABEL(ashr_4_exittail)
788 # endif
790         pxor    %xmm0, %xmm0
791         sub     $0x1000, %r10
792         jmp     LABEL(gobble_ashr_4)
794         .p2align 4
795 LABEL(ashr_4_exittail):
796         movdqa  (%rsi, %rcx), %xmm1
797         psrldq  $4, %xmm0
798         psrldq  $4, %xmm3
799         jmp     LABEL(aftertail)
802  * The following cases will be handled by ashr_5
803  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
804  *        n(11~15)          n - 11                4(15 +(n-11) - n)         ashr_5
805  */
806         .p2align 4
807 LABEL(ashr_5):
808         pxor    %xmm0, %xmm0
809         movdqa  (%rdi), %xmm2
810         movdqa  (%rsi), %xmm1
811         pcmpeqb %xmm1, %xmm0
812         pslldq  $11, %xmm2
813         TOLOWER (%xmm1, %xmm2)
814         pcmpeqb %xmm1, %xmm2
815         psubb   %xmm0, %xmm2
816         pmovmskb %xmm2, %r9d
817         shr     %cl, %edx
818         shr     %cl, %r9d
819         sub     %r9d, %edx
820         jnz     LABEL(less32bytes)
821         movdqa  (%rdi), %xmm3
823         UPDATE_STRNCMP_COUNTER
825         pxor    %xmm0, %xmm0
826         mov     $16, %rcx       /* index for loads */
827         mov     $5, %r9d        /* byte position left over from less32bytes case */
828         /*
829          * Setup %r10 value allows us to detect crossing a page boundary.
830          * When %r10 goes positive we have crossed a page boundary and
831          * need to do a nibble.
832          */
833         lea     5(%rdi), %r10
834         and     $0xfff, %r10    /* offset into 4K page */
835         sub     $0x1000, %r10   /* subtract 4K pagesize */
837         .p2align 4
838 LABEL(loop_ashr_5):
839         add     $16, %r10
840         jg      LABEL(nibble_ashr_5)
842 LABEL(gobble_ashr_5):
843         movdqa  (%rsi, %rcx), %xmm1
844         movdqa  (%rdi, %rcx), %xmm2
845         movdqa  %xmm2, %xmm4
847 # ifndef USE_SSSE3
848         psrldq  $5, %xmm3
849         pslldq  $11, %xmm2
850         por     %xmm3, %xmm2            /* merge into one 16byte value */
851 # else
852         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
853 # endif
854         TOLOWER (%xmm1, %xmm2)
856         pcmpeqb %xmm1, %xmm0
857         pcmpeqb %xmm2, %xmm1
858         psubb   %xmm0, %xmm1
859         pmovmskb %xmm1, %edx
860         sub     $0xffff, %edx
861         jnz     LABEL(exit)
863 # ifdef USE_AS_STRNCMP
864         sub     $16, %r11
865         jbe     LABEL(strcmp_exitz)
866 # endif
868         add     $16, %rcx
869         movdqa  %xmm4, %xmm3
871         add     $16, %r10
872         jg      LABEL(nibble_ashr_5)    /* cross page boundary */
874         movdqa  (%rsi, %rcx), %xmm1
875         movdqa  (%rdi, %rcx), %xmm2
876         movdqa  %xmm2, %xmm4
878 # ifndef USE_SSSE3
879         psrldq  $5, %xmm3
880         pslldq  $11, %xmm2
881         por     %xmm3, %xmm2            /* merge into one 16byte value */
882 # else
883         palignr $5, %xmm3, %xmm2        /* merge into one 16byte value */
884 # endif
885         TOLOWER (%xmm1, %xmm2)
887         pcmpeqb %xmm1, %xmm0
888         pcmpeqb %xmm2, %xmm1
889         psubb   %xmm0, %xmm1
890         pmovmskb %xmm1, %edx
891         sub     $0xffff, %edx
892         jnz     LABEL(exit)
894 # ifdef USE_AS_STRNCMP
895         sub     $16, %r11
896         jbe     LABEL(strcmp_exitz)
897 # endif
899         add     $16, %rcx
900         movdqa  %xmm4, %xmm3
901         jmp     LABEL(loop_ashr_5)
903         .p2align 4
904 LABEL(nibble_ashr_5):
905         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
906         pmovmskb %xmm0, %edx
907         test    $0xffe0, %edx
908         jnz     LABEL(ashr_5_exittail)
910 # ifdef USE_AS_STRNCMP
911         cmp     $10, %r11
912         jbe     LABEL(ashr_5_exittail)
913 # endif
915         pxor    %xmm0, %xmm0
916         sub     $0x1000, %r10
917         jmp     LABEL(gobble_ashr_5)
919         .p2align 4
920 LABEL(ashr_5_exittail):
921         movdqa  (%rsi, %rcx), %xmm1
922         psrldq  $5, %xmm0
923         psrldq  $5, %xmm3
924         jmp     LABEL(aftertail)
927  * The following cases will be handled by ashr_6
928  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
929  *        n(10~15)          n - 10                5(15 +(n-10) - n)         ashr_6
930  */
931         .p2align 4
932 LABEL(ashr_6):
933         pxor    %xmm0, %xmm0
934         movdqa  (%rdi), %xmm2
935         movdqa  (%rsi), %xmm1
936         pcmpeqb %xmm1, %xmm0
937         pslldq  $10, %xmm2
938         TOLOWER (%xmm1, %xmm2)
939         pcmpeqb %xmm1, %xmm2
940         psubb   %xmm0, %xmm2
941         pmovmskb %xmm2, %r9d
942         shr     %cl, %edx
943         shr     %cl, %r9d
944         sub     %r9d, %edx
945         jnz     LABEL(less32bytes)
946         movdqa  (%rdi), %xmm3
948         UPDATE_STRNCMP_COUNTER
950         pxor    %xmm0, %xmm0
951         mov     $16, %rcx       /* index for loads */
952         mov     $6, %r9d        /* byte position left over from less32bytes case */
953         /*
954          * Setup %r10 value allows us to detect crossing a page boundary.
955          * When %r10 goes positive we have crossed a page boundary and
956          * need to do a nibble.
957          */
958         lea     6(%rdi), %r10
959         and     $0xfff, %r10    /* offset into 4K page */
960         sub     $0x1000, %r10   /* subtract 4K pagesize */
962         .p2align 4
963 LABEL(loop_ashr_6):
964         add     $16, %r10
965         jg      LABEL(nibble_ashr_6)
967 LABEL(gobble_ashr_6):
968         movdqa  (%rsi, %rcx), %xmm1
969         movdqa  (%rdi, %rcx), %xmm2
970         movdqa  %xmm2, %xmm4
972 # ifndef USE_SSSE3
973         psrldq  $6, %xmm3
974         pslldq  $10, %xmm2
975         por     %xmm3, %xmm2            /* merge into one 16byte value */
976 # else
977         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
978 # endif
979         TOLOWER (%xmm1, %xmm2)
981         pcmpeqb %xmm1, %xmm0
982         pcmpeqb %xmm2, %xmm1
983         psubb   %xmm0, %xmm1
984         pmovmskb %xmm1, %edx
985         sub     $0xffff, %edx
986         jnz     LABEL(exit)
988 # ifdef USE_AS_STRNCMP
989         sub     $16, %r11
990         jbe     LABEL(strcmp_exitz)
991 # endif
993         add     $16, %rcx
994         movdqa  %xmm4, %xmm3
996         add     $16, %r10
997         jg      LABEL(nibble_ashr_6)    /* cross page boundary */
999         movdqa  (%rsi, %rcx), %xmm1
1000         movdqa  (%rdi, %rcx), %xmm2
1001         movdqa  %xmm2, %xmm4
1003 # ifndef USE_SSSE3
1004         psrldq  $6, %xmm3
1005         pslldq  $10, %xmm2
1006         por     %xmm3, %xmm2            /* merge into one 16byte value */
1007 # else
1008         palignr $6, %xmm3, %xmm2        /* merge into one 16byte value */
1009 # endif
1010         TOLOWER (%xmm1, %xmm2)
1012         pcmpeqb %xmm1, %xmm0
1013         pcmpeqb %xmm2, %xmm1
1014         psubb   %xmm0, %xmm1
1015         pmovmskb %xmm1, %edx
1016         sub     $0xffff, %edx
1017         jnz     LABEL(exit)
1019 # ifdef USE_AS_STRNCMP
1020         sub     $16, %r11
1021         jbe     LABEL(strcmp_exitz)
1022 # endif
1024         add     $16, %rcx
1025         movdqa  %xmm4, %xmm3
1026         jmp     LABEL(loop_ashr_6)
1028         .p2align 4
1029 LABEL(nibble_ashr_6):
1030         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1031         pmovmskb %xmm0, %edx
1032         test    $0xffc0, %edx
1033         jnz     LABEL(ashr_6_exittail)
1035 # ifdef USE_AS_STRNCMP
1036         cmp     $9, %r11
1037         jbe     LABEL(ashr_6_exittail)
1038 # endif
1040         pxor    %xmm0, %xmm0
1041         sub     $0x1000, %r10
1042         jmp     LABEL(gobble_ashr_6)
1044         .p2align 4
1045 LABEL(ashr_6_exittail):
1046         movdqa  (%rsi, %rcx), %xmm1
1047         psrldq  $6, %xmm0
1048         psrldq  $6, %xmm3
1049         jmp     LABEL(aftertail)
1052  * The following cases will be handled by ashr_7
1053  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset      corresponding case
1054  *        n(9~15)          n - 9                6(15 +(n - 9) - n)         ashr_7
1055  */
1056         .p2align 4
1057 LABEL(ashr_7):
1058         pxor    %xmm0, %xmm0
1059         movdqa  (%rdi), %xmm2
1060         movdqa  (%rsi), %xmm1
1061         pcmpeqb %xmm1, %xmm0
1062         pslldq  $9, %xmm2
1063         TOLOWER (%xmm1, %xmm2)
1064         pcmpeqb %xmm1, %xmm2
1065         psubb   %xmm0, %xmm2
1066         pmovmskb %xmm2, %r9d
1067         shr     %cl, %edx
1068         shr     %cl, %r9d
1069         sub     %r9d, %edx
1070         jnz     LABEL(less32bytes)
1071         movdqa  (%rdi), %xmm3
1073         UPDATE_STRNCMP_COUNTER
1075         pxor    %xmm0, %xmm0
1076         mov     $16, %rcx       /* index for loads */
1077         mov     $7, %r9d        /* byte position left over from less32bytes case */
1078         /*
1079          * Setup %r10 value allows us to detect crossing a page boundary.
1080          * When %r10 goes positive we have crossed a page boundary and
1081          * need to do a nibble.
1082          */
1083         lea     7(%rdi), %r10
1084         and     $0xfff, %r10    /* offset into 4K page */
1085         sub     $0x1000, %r10   /* subtract 4K pagesize */
1087         .p2align 4
1088 LABEL(loop_ashr_7):
1089         add     $16, %r10
1090         jg      LABEL(nibble_ashr_7)
1092 LABEL(gobble_ashr_7):
1093         movdqa  (%rsi, %rcx), %xmm1
1094         movdqa  (%rdi, %rcx), %xmm2
1095         movdqa  %xmm2, %xmm4
1097 # ifndef USE_SSSE3
1098         psrldq  $7, %xmm3
1099         pslldq  $9, %xmm2
1100         por     %xmm3, %xmm2            /* merge into one 16byte value */
1101 # else
1102         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1103 # endif
1104         TOLOWER (%xmm1, %xmm2)
1106         pcmpeqb %xmm1, %xmm0
1107         pcmpeqb %xmm2, %xmm1
1108         psubb   %xmm0, %xmm1
1109         pmovmskb %xmm1, %edx
1110         sub     $0xffff, %edx
1111         jnz     LABEL(exit)
1113 # ifdef USE_AS_STRNCMP
1114         sub     $16, %r11
1115         jbe     LABEL(strcmp_exitz)
1116 # endif
1118         add     $16, %rcx
1119         movdqa  %xmm4, %xmm3
1121         add     $16, %r10
1122         jg      LABEL(nibble_ashr_7)    /* cross page boundary */
1124         movdqa  (%rsi, %rcx), %xmm1
1125         movdqa  (%rdi, %rcx), %xmm2
1126         movdqa  %xmm2, %xmm4
1128 # ifndef USE_SSSE3
1129         psrldq  $7, %xmm3
1130         pslldq  $9, %xmm2
1131         por     %xmm3, %xmm2            /* merge into one 16byte value */
1132 # else
1133         palignr $7, %xmm3, %xmm2        /* merge into one 16byte value */
1134 # endif
1135         TOLOWER (%xmm1, %xmm2)
1137         pcmpeqb %xmm1, %xmm0
1138         pcmpeqb %xmm2, %xmm1
1139         psubb   %xmm0, %xmm1
1140         pmovmskb %xmm1, %edx
1141         sub     $0xffff, %edx
1142         jnz     LABEL(exit)
1144 # ifdef USE_AS_STRNCMP
1145         sub     $16, %r11
1146         jbe     LABEL(strcmp_exitz)
1147 # endif
1149         add     $16, %rcx
1150         movdqa  %xmm4, %xmm3
1151         jmp     LABEL(loop_ashr_7)
1153         .p2align 4
1154 LABEL(nibble_ashr_7):
1155         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1156         pmovmskb %xmm0, %edx
1157         test    $0xff80, %edx
1158         jnz     LABEL(ashr_7_exittail)
1160 # ifdef USE_AS_STRNCMP
1161         cmp     $8, %r11
1162         jbe     LABEL(ashr_7_exittail)
1163 # endif
1165         pxor    %xmm0, %xmm0
1166         sub     $0x1000, %r10
1167         jmp     LABEL(gobble_ashr_7)
1169         .p2align 4
1170 LABEL(ashr_7_exittail):
1171         movdqa  (%rsi, %rcx), %xmm1
1172         psrldq  $7, %xmm0
1173         psrldq  $7, %xmm3
1174         jmp     LABEL(aftertail)
1177  *  The following cases will be handled by ashr_8
1178  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1179  *        n(8~15)          n - 8                7(15 +(n - 8) - n)         ashr_8
1180  */
1181         .p2align 4
1182 LABEL(ashr_8):
1183         pxor    %xmm0, %xmm0
1184         movdqa  (%rdi), %xmm2
1185         movdqa  (%rsi), %xmm1
1186         pcmpeqb %xmm1, %xmm0
1187         pslldq  $8, %xmm2
1188         TOLOWER (%xmm1, %xmm2)
1189         pcmpeqb %xmm1, %xmm2
1190         psubb   %xmm0, %xmm2
1191         pmovmskb %xmm2, %r9d
1192         shr     %cl, %edx
1193         shr     %cl, %r9d
1194         sub     %r9d, %edx
1195         jnz     LABEL(less32bytes)
1196         movdqa  (%rdi), %xmm3
1198         UPDATE_STRNCMP_COUNTER
1200         pxor    %xmm0, %xmm0
1201         mov     $16, %rcx       /* index for loads */
1202         mov     $8, %r9d        /* byte position left over from less32bytes case */
1203         /*
1204          * Setup %r10 value allows us to detect crossing a page boundary.
1205          * When %r10 goes positive we have crossed a page boundary and
1206          * need to do a nibble.
1207          */
1208         lea     8(%rdi), %r10
1209         and     $0xfff, %r10    /* offset into 4K page */
1210         sub     $0x1000, %r10   /* subtract 4K pagesize */
1212         .p2align 4
1213 LABEL(loop_ashr_8):
1214         add     $16, %r10
1215         jg      LABEL(nibble_ashr_8)
1217 LABEL(gobble_ashr_8):
1218         movdqa  (%rsi, %rcx), %xmm1
1219         movdqa  (%rdi, %rcx), %xmm2
1220         movdqa  %xmm2, %xmm4
1222 # ifndef USE_SSSE3
1223         psrldq  $8, %xmm3
1224         pslldq  $8, %xmm2
1225         por     %xmm3, %xmm2            /* merge into one 16byte value */
1226 # else
1227         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1228 # endif
1229         TOLOWER (%xmm1, %xmm2)
1231         pcmpeqb %xmm1, %xmm0
1232         pcmpeqb %xmm2, %xmm1
1233         psubb   %xmm0, %xmm1
1234         pmovmskb %xmm1, %edx
1235         sub     $0xffff, %edx
1236         jnz     LABEL(exit)
1238 # ifdef USE_AS_STRNCMP
1239         sub     $16, %r11
1240         jbe     LABEL(strcmp_exitz)
1241 # endif
1243         add     $16, %rcx
1244         movdqa  %xmm4, %xmm3
1246         add     $16, %r10
1247         jg      LABEL(nibble_ashr_8)    /* cross page boundary */
1249         movdqa  (%rsi, %rcx), %xmm1
1250         movdqa  (%rdi, %rcx), %xmm2
1251         movdqa  %xmm2, %xmm4
1253 # ifndef USE_SSSE3
1254         psrldq  $8, %xmm3
1255         pslldq  $8, %xmm2
1256         por     %xmm3, %xmm2            /* merge into one 16byte value */
1257 # else
1258         palignr $8, %xmm3, %xmm2        /* merge into one 16byte value */
1259 # endif
1260         TOLOWER (%xmm1, %xmm2)
1262         pcmpeqb %xmm1, %xmm0
1263         pcmpeqb %xmm2, %xmm1
1264         psubb   %xmm0, %xmm1
1265         pmovmskb %xmm1, %edx
1266         sub     $0xffff, %edx
1267         jnz     LABEL(exit)
1269 # ifdef USE_AS_STRNCMP
1270         sub     $16, %r11
1271         jbe     LABEL(strcmp_exitz)
1272 # endif
1274         add     $16, %rcx
1275         movdqa  %xmm4, %xmm3
1276         jmp     LABEL(loop_ashr_8)
1278         .p2align 4
1279 LABEL(nibble_ashr_8):
1280         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1281         pmovmskb %xmm0, %edx
1282         test    $0xff00, %edx
1283         jnz     LABEL(ashr_8_exittail)
1285 # ifdef USE_AS_STRNCMP
1286         cmp     $7, %r11
1287         jbe     LABEL(ashr_8_exittail)
1288 # endif
1290         pxor    %xmm0, %xmm0
1291         sub     $0x1000, %r10
1292         jmp     LABEL(gobble_ashr_8)
1294         .p2align 4
1295 LABEL(ashr_8_exittail):
1296         movdqa  (%rsi, %rcx), %xmm1
1297         psrldq  $8, %xmm0
1298         psrldq  $8, %xmm3
1299         jmp     LABEL(aftertail)
1302  *  The following cases will be handled by ashr_9
1303  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1304  *        n(7~15)          n - 7                8(15 +(n - 7) - n)         ashr_9
1305  */
1306         .p2align 4
1307 LABEL(ashr_9):
1308         pxor    %xmm0, %xmm0
1309         movdqa  (%rdi), %xmm2
1310         movdqa  (%rsi), %xmm1
1311         pcmpeqb %xmm1, %xmm0
1312         pslldq  $7, %xmm2
1313         TOLOWER (%xmm1, %xmm2)
1314         pcmpeqb %xmm1, %xmm2
1315         psubb   %xmm0, %xmm2
1316         pmovmskb %xmm2, %r9d
1317         shr     %cl, %edx
1318         shr     %cl, %r9d
1319         sub     %r9d, %edx
1320         jnz     LABEL(less32bytes)
1321         movdqa  (%rdi), %xmm3
1323         UPDATE_STRNCMP_COUNTER
1325         pxor    %xmm0, %xmm0
1326         mov     $16, %rcx       /* index for loads */
1327         mov     $9, %r9d        /* byte position left over from less32bytes case */
1328         /*
1329          * Setup %r10 value allows us to detect crossing a page boundary.
1330          * When %r10 goes positive we have crossed a page boundary and
1331          * need to do a nibble.
1332          */
1333         lea     9(%rdi), %r10
1334         and     $0xfff, %r10    /* offset into 4K page */
1335         sub     $0x1000, %r10   /* subtract 4K pagesize */
1337         .p2align 4
1338 LABEL(loop_ashr_9):
1339         add     $16, %r10
1340         jg      LABEL(nibble_ashr_9)
1342 LABEL(gobble_ashr_9):
1343         movdqa  (%rsi, %rcx), %xmm1
1344         movdqa  (%rdi, %rcx), %xmm2
1345         movdqa  %xmm2, %xmm4
1347 # ifndef USE_SSSE3
1348         psrldq  $9, %xmm3
1349         pslldq  $7, %xmm2
1350         por     %xmm3, %xmm2            /* merge into one 16byte value */
1351 # else
1352         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1353 # endif
1354         TOLOWER (%xmm1, %xmm2)
1356         pcmpeqb %xmm1, %xmm0
1357         pcmpeqb %xmm2, %xmm1
1358         psubb   %xmm0, %xmm1
1359         pmovmskb %xmm1, %edx
1360         sub     $0xffff, %edx
1361         jnz     LABEL(exit)
1363 # ifdef USE_AS_STRNCMP
1364         sub     $16, %r11
1365         jbe     LABEL(strcmp_exitz)
1366 # endif
1368         add     $16, %rcx
1369         movdqa  %xmm4, %xmm3
1371         add     $16, %r10
1372         jg      LABEL(nibble_ashr_9)    /* cross page boundary */
1374         movdqa  (%rsi, %rcx), %xmm1
1375         movdqa  (%rdi, %rcx), %xmm2
1376         movdqa  %xmm2, %xmm4
1378 # ifndef USE_SSSE3
1379         psrldq  $9, %xmm3
1380         pslldq  $7, %xmm2
1381         por     %xmm3, %xmm2            /* merge into one 16byte value */
1382 # else
1383         palignr $9, %xmm3, %xmm2        /* merge into one 16byte value */
1384 # endif
1385         TOLOWER (%xmm1, %xmm2)
1387         pcmpeqb %xmm1, %xmm0
1388         pcmpeqb %xmm2, %xmm1
1389         psubb   %xmm0, %xmm1
1390         pmovmskb %xmm1, %edx
1391         sub     $0xffff, %edx
1392         jnz     LABEL(exit)
1394 # ifdef USE_AS_STRNCMP
1395         sub     $16, %r11
1396         jbe     LABEL(strcmp_exitz)
1397 # endif
1399         add     $16, %rcx
1400         movdqa  %xmm4, %xmm3            /* store for next cycle */
1401         jmp     LABEL(loop_ashr_9)
1403         .p2align 4
1404 LABEL(nibble_ashr_9):
1405         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1406         pmovmskb %xmm0, %edx
1407         test    $0xfe00, %edx
1408         jnz     LABEL(ashr_9_exittail)
1410 # ifdef USE_AS_STRNCMP
1411         cmp     $6, %r11
1412         jbe     LABEL(ashr_9_exittail)
1413 # endif
1415         pxor    %xmm0, %xmm0
1416         sub     $0x1000, %r10
1417         jmp     LABEL(gobble_ashr_9)
1419         .p2align 4
1420 LABEL(ashr_9_exittail):
1421         movdqa  (%rsi, %rcx), %xmm1
1422         psrldq  $9, %xmm0
1423         psrldq  $9, %xmm3
1424         jmp     LABEL(aftertail)
1427  *  The following cases will be handled by ashr_10
1428  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1429  *        n(6~15)          n - 6                9(15 +(n - 6) - n)         ashr_10
1430  */
1431         .p2align 4
1432 LABEL(ashr_10):
1433         pxor    %xmm0, %xmm0
1434         movdqa  (%rdi), %xmm2
1435         movdqa  (%rsi), %xmm1
1436         pcmpeqb %xmm1, %xmm0
1437         pslldq  $6, %xmm2
1438         TOLOWER (%xmm1, %xmm2)
1439         pcmpeqb %xmm1, %xmm2
1440         psubb   %xmm0, %xmm2
1441         pmovmskb %xmm2, %r9d
1442         shr     %cl, %edx
1443         shr     %cl, %r9d
1444         sub     %r9d, %edx
1445         jnz     LABEL(less32bytes)
1446         movdqa  (%rdi), %xmm3
1448         UPDATE_STRNCMP_COUNTER
1450         pxor    %xmm0, %xmm0
1451         mov     $16, %rcx       /* index for loads */
1452         mov     $10, %r9d       /* byte position left over from less32bytes case */
1453         /*
1454          * Setup %r10 value allows us to detect crossing a page boundary.
1455          * When %r10 goes positive we have crossed a page boundary and
1456          * need to do a nibble.
1457          */
1458         lea     10(%rdi), %r10
1459         and     $0xfff, %r10    /* offset into 4K page */
1460         sub     $0x1000, %r10   /* subtract 4K pagesize */
1462         .p2align 4
1463 LABEL(loop_ashr_10):
1464         add     $16, %r10
1465         jg      LABEL(nibble_ashr_10)
1467 LABEL(gobble_ashr_10):
1468         movdqa  (%rsi, %rcx), %xmm1
1469         movdqa  (%rdi, %rcx), %xmm2
1470         movdqa  %xmm2, %xmm4
1472 # ifndef USE_SSSE3
1473         psrldq  $10, %xmm3
1474         pslldq  $6, %xmm2
1475         por     %xmm3, %xmm2            /* merge into one 16byte value */
1476 # else
1477         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1478 # endif
1479         TOLOWER (%xmm1, %xmm2)
1481         pcmpeqb %xmm1, %xmm0
1482         pcmpeqb %xmm2, %xmm1
1483         psubb   %xmm0, %xmm1
1484         pmovmskb %xmm1, %edx
1485         sub     $0xffff, %edx
1486         jnz     LABEL(exit)
1488 # ifdef USE_AS_STRNCMP
1489         sub     $16, %r11
1490         jbe     LABEL(strcmp_exitz)
1491 # endif
1493         add     $16, %rcx
1494         movdqa  %xmm4, %xmm3
1496         add     $16, %r10
1497         jg      LABEL(nibble_ashr_10)   /* cross page boundary */
1499         movdqa  (%rsi, %rcx), %xmm1
1500         movdqa  (%rdi, %rcx), %xmm2
1501         movdqa  %xmm2, %xmm4
1503 # ifndef USE_SSSE3
1504         psrldq  $10, %xmm3
1505         pslldq  $6, %xmm2
1506         por     %xmm3, %xmm2            /* merge into one 16byte value */
1507 # else
1508         palignr $10, %xmm3, %xmm2       /* merge into one 16byte value */
1509 # endif
1510         TOLOWER (%xmm1, %xmm2)
1512         pcmpeqb %xmm1, %xmm0
1513         pcmpeqb %xmm2, %xmm1
1514         psubb   %xmm0, %xmm1
1515         pmovmskb %xmm1, %edx
1516         sub     $0xffff, %edx
1517         jnz     LABEL(exit)
1519 # ifdef USE_AS_STRNCMP
1520         sub     $16, %r11
1521         jbe     LABEL(strcmp_exitz)
1522 # endif
1524         add     $16, %rcx
1525         movdqa  %xmm4, %xmm3
1526         jmp     LABEL(loop_ashr_10)
1528         .p2align 4
1529 LABEL(nibble_ashr_10):
1530         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1531         pmovmskb %xmm0, %edx
1532         test    $0xfc00, %edx
1533         jnz     LABEL(ashr_10_exittail)
1535 # ifdef USE_AS_STRNCMP
1536         cmp     $5, %r11
1537         jbe     LABEL(ashr_10_exittail)
1538 # endif
1540         pxor    %xmm0, %xmm0
1541         sub     $0x1000, %r10
1542         jmp     LABEL(gobble_ashr_10)
1544         .p2align 4
1545 LABEL(ashr_10_exittail):
1546         movdqa  (%rsi, %rcx), %xmm1
1547         psrldq  $10, %xmm0
1548         psrldq  $10, %xmm3
1549         jmp     LABEL(aftertail)
1552  *  The following cases will be handled by ashr_11
1553  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1554  *        n(5~15)          n - 5               10(15 +(n - 5) - n)         ashr_11
1555  */
1556         .p2align 4
1557 LABEL(ashr_11):
1558         pxor    %xmm0, %xmm0
1559         movdqa  (%rdi), %xmm2
1560         movdqa  (%rsi), %xmm1
1561         pcmpeqb %xmm1, %xmm0
1562         pslldq  $5, %xmm2
1563         TOLOWER (%xmm1, %xmm2)
1564         pcmpeqb %xmm1, %xmm2
1565         psubb   %xmm0, %xmm2
1566         pmovmskb %xmm2, %r9d
1567         shr     %cl, %edx
1568         shr     %cl, %r9d
1569         sub     %r9d, %edx
1570         jnz     LABEL(less32bytes)
1571         movdqa  (%rdi), %xmm3
1573         UPDATE_STRNCMP_COUNTER
1575         pxor    %xmm0, %xmm0
1576         mov     $16, %rcx       /* index for loads */
1577         mov     $11, %r9d       /* byte position left over from less32bytes case */
1578         /*
1579          * Setup %r10 value allows us to detect crossing a page boundary.
1580          * When %r10 goes positive we have crossed a page boundary and
1581          * need to do a nibble.
1582          */
1583         lea     11(%rdi), %r10
1584         and     $0xfff, %r10    /* offset into 4K page */
1585         sub     $0x1000, %r10   /* subtract 4K pagesize */
1587         .p2align 4
1588 LABEL(loop_ashr_11):
1589         add     $16, %r10
1590         jg      LABEL(nibble_ashr_11)
1592 LABEL(gobble_ashr_11):
1593         movdqa  (%rsi, %rcx), %xmm1
1594         movdqa  (%rdi, %rcx), %xmm2
1595         movdqa  %xmm2, %xmm4
1597 # ifndef USE_SSSE3
1598         psrldq  $11, %xmm3
1599         pslldq  $5, %xmm2
1600         por     %xmm3, %xmm2            /* merge into one 16byte value */
1601 # else
1602         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1603 # endif
1604         TOLOWER (%xmm1, %xmm2)
1606         pcmpeqb %xmm1, %xmm0
1607         pcmpeqb %xmm2, %xmm1
1608         psubb   %xmm0, %xmm1
1609         pmovmskb %xmm1, %edx
1610         sub     $0xffff, %edx
1611         jnz     LABEL(exit)
1613 # ifdef USE_AS_STRNCMP
1614         sub     $16, %r11
1615         jbe     LABEL(strcmp_exitz)
1616 # endif
1618         add     $16, %rcx
1619         movdqa  %xmm4, %xmm3
1621         add     $16, %r10
1622         jg      LABEL(nibble_ashr_11)   /* cross page boundary */
1624         movdqa  (%rsi, %rcx), %xmm1
1625         movdqa  (%rdi, %rcx), %xmm2
1626         movdqa  %xmm2, %xmm4
1628 # ifndef USE_SSSE3
1629         psrldq  $11, %xmm3
1630         pslldq  $5, %xmm2
1631         por     %xmm3, %xmm2            /* merge into one 16byte value */
1632 # else
1633         palignr $11, %xmm3, %xmm2       /* merge into one 16byte value */
1634 # endif
1635         TOLOWER (%xmm1, %xmm2)
1637         pcmpeqb %xmm1, %xmm0
1638         pcmpeqb %xmm2, %xmm1
1639         psubb   %xmm0, %xmm1
1640         pmovmskb %xmm1, %edx
1641         sub     $0xffff, %edx
1642         jnz     LABEL(exit)
1644 # ifdef USE_AS_STRNCMP
1645         sub     $16, %r11
1646         jbe     LABEL(strcmp_exitz)
1647 # endif
1649         add     $16, %rcx
1650         movdqa  %xmm4, %xmm3
1651         jmp     LABEL(loop_ashr_11)
1653         .p2align 4
1654 LABEL(nibble_ashr_11):
1655         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1656         pmovmskb %xmm0, %edx
1657         test    $0xf800, %edx
1658         jnz     LABEL(ashr_11_exittail)
1660 # ifdef USE_AS_STRNCMP
1661         cmp     $4, %r11
1662         jbe     LABEL(ashr_11_exittail)
1663 # endif
1665         pxor    %xmm0, %xmm0
1666         sub     $0x1000, %r10
1667         jmp     LABEL(gobble_ashr_11)
1669         .p2align 4
1670 LABEL(ashr_11_exittail):
1671         movdqa  (%rsi, %rcx), %xmm1
1672         psrldq  $11, %xmm0
1673         psrldq  $11, %xmm3
1674         jmp     LABEL(aftertail)
1677  *  The following cases will be handled by ashr_12
1678  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1679  *        n(4~15)          n - 4                11(15 +(n - 4) - n)         ashr_12
1680  */
1681         .p2align 4
1682 LABEL(ashr_12):
1683         pxor    %xmm0, %xmm0
1684         movdqa  (%rdi), %xmm2
1685         movdqa  (%rsi), %xmm1
1686         pcmpeqb %xmm1, %xmm0
1687         pslldq  $4, %xmm2
1688         TOLOWER (%xmm1, %xmm2)
1689         pcmpeqb %xmm1, %xmm2
1690         psubb   %xmm0, %xmm2
1691         pmovmskb %xmm2, %r9d
1692         shr     %cl, %edx
1693         shr     %cl, %r9d
1694         sub     %r9d, %edx
1695         jnz     LABEL(less32bytes)
1696         movdqa  (%rdi), %xmm3
1698         UPDATE_STRNCMP_COUNTER
1700         pxor    %xmm0, %xmm0
1701         mov     $16, %rcx       /* index for loads */
1702         mov     $12, %r9d       /* byte position left over from less32bytes case */
1703         /*
1704          * Setup %r10 value allows us to detect crossing a page boundary.
1705          * When %r10 goes positive we have crossed a page boundary and
1706          * need to do a nibble.
1707          */
1708         lea     12(%rdi), %r10
1709         and     $0xfff, %r10    /* offset into 4K page */
1710         sub     $0x1000, %r10   /* subtract 4K pagesize */
1712         .p2align 4
1713 LABEL(loop_ashr_12):
1714         add     $16, %r10
1715         jg      LABEL(nibble_ashr_12)
1717 LABEL(gobble_ashr_12):
1718         movdqa  (%rsi, %rcx), %xmm1
1719         movdqa  (%rdi, %rcx), %xmm2
1720         movdqa  %xmm2, %xmm4
1722 # ifndef USE_SSSE3
1723         psrldq  $12, %xmm3
1724         pslldq  $4, %xmm2
1725         por     %xmm3, %xmm2            /* merge into one 16byte value */
1726 # else
1727         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1728 # endif
1729         TOLOWER (%xmm1, %xmm2)
1731         pcmpeqb %xmm1, %xmm0
1732         pcmpeqb %xmm2, %xmm1
1733         psubb   %xmm0, %xmm1
1734         pmovmskb %xmm1, %edx
1735         sub     $0xffff, %edx
1736         jnz     LABEL(exit)
1738 # ifdef USE_AS_STRNCMP
1739         sub     $16, %r11
1740         jbe     LABEL(strcmp_exitz)
1741 # endif
1743         add     $16, %rcx
1744         movdqa  %xmm4, %xmm3
1746         add     $16, %r10
1747         jg      LABEL(nibble_ashr_12)   /* cross page boundary */
1749         movdqa  (%rsi, %rcx), %xmm1
1750         movdqa  (%rdi, %rcx), %xmm2
1751         movdqa  %xmm2, %xmm4
1753 # ifndef USE_SSSE3
1754         psrldq  $12, %xmm3
1755         pslldq  $4, %xmm2
1756         por     %xmm3, %xmm2            /* merge into one 16byte value */
1757 # else
1758         palignr $12, %xmm3, %xmm2       /* merge into one 16byte value */
1759 # endif
1760         TOLOWER (%xmm1, %xmm2)
1762         pcmpeqb %xmm1, %xmm0
1763         pcmpeqb %xmm2, %xmm1
1764         psubb   %xmm0, %xmm1
1765         pmovmskb %xmm1, %edx
1766         sub     $0xffff, %edx
1767         jnz     LABEL(exit)
1769 # ifdef USE_AS_STRNCMP
1770         sub     $16, %r11
1771         jbe     LABEL(strcmp_exitz)
1772 # endif
1774         add     $16, %rcx
1775         movdqa  %xmm4, %xmm3
1776         jmp     LABEL(loop_ashr_12)
1778         .p2align 4
1779 LABEL(nibble_ashr_12):
1780         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1781         pmovmskb %xmm0, %edx
1782         test    $0xf000, %edx
1783         jnz     LABEL(ashr_12_exittail)
1785 # ifdef USE_AS_STRNCMP
1786         cmp     $3, %r11
1787         jbe     LABEL(ashr_12_exittail)
1788 # endif
1790         pxor    %xmm0, %xmm0
1791         sub     $0x1000, %r10
1792         jmp     LABEL(gobble_ashr_12)
1794         .p2align 4
1795 LABEL(ashr_12_exittail):
1796         movdqa  (%rsi, %rcx), %xmm1
1797         psrldq  $12, %xmm0
1798         psrldq  $12, %xmm3
1799         jmp     LABEL(aftertail)
1802  *  The following cases will be handled by ashr_13
1803  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1804  *        n(3~15)          n - 3                12(15 +(n - 3) - n)         ashr_13
1805  */
1806         .p2align 4
1807 LABEL(ashr_13):
1808         pxor    %xmm0, %xmm0
1809         movdqa  (%rdi), %xmm2
1810         movdqa  (%rsi), %xmm1
1811         pcmpeqb %xmm1, %xmm0
1812         pslldq  $3, %xmm2
1813         TOLOWER (%xmm1, %xmm2)
1814         pcmpeqb %xmm1, %xmm2
1815         psubb   %xmm0, %xmm2
1816         pmovmskb %xmm2, %r9d
1817         shr     %cl, %edx
1818         shr     %cl, %r9d
1819         sub     %r9d, %edx
1820         jnz     LABEL(less32bytes)
1821         movdqa  (%rdi), %xmm3
1823         UPDATE_STRNCMP_COUNTER
1825         pxor    %xmm0, %xmm0
1826         mov     $16, %rcx       /* index for loads */
1827         mov     $13, %r9d       /* byte position left over from less32bytes case */
1828         /*
1829          * Setup %r10 value allows us to detect crossing a page boundary.
1830          * When %r10 goes positive we have crossed a page boundary and
1831          * need to do a nibble.
1832          */
1833         lea     13(%rdi), %r10
1834         and     $0xfff, %r10    /* offset into 4K page */
1835         sub     $0x1000, %r10   /* subtract 4K pagesize */
1837         .p2align 4
1838 LABEL(loop_ashr_13):
1839         add     $16, %r10
1840         jg      LABEL(nibble_ashr_13)
1842 LABEL(gobble_ashr_13):
1843         movdqa  (%rsi, %rcx), %xmm1
1844         movdqa  (%rdi, %rcx), %xmm2
1845         movdqa  %xmm2, %xmm4
1847 # ifndef USE_SSSE3
1848         psrldq  $13, %xmm3
1849         pslldq  $3, %xmm2
1850         por     %xmm3, %xmm2            /* merge into one 16byte value */
1851 # else
1852         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1853 # endif
1854         TOLOWER (%xmm1, %xmm2)
1856         pcmpeqb %xmm1, %xmm0
1857         pcmpeqb %xmm2, %xmm1
1858         psubb   %xmm0, %xmm1
1859         pmovmskb %xmm1, %edx
1860         sub     $0xffff, %edx
1861         jnz     LABEL(exit)
1863 # ifdef USE_AS_STRNCMP
1864         sub     $16, %r11
1865         jbe     LABEL(strcmp_exitz)
1866 # endif
1868         add     $16, %rcx
1869         movdqa  %xmm4, %xmm3
1871         add     $16, %r10
1872         jg      LABEL(nibble_ashr_13)   /* cross page boundary */
1874         movdqa  (%rsi, %rcx), %xmm1
1875         movdqa  (%rdi, %rcx), %xmm2
1876         movdqa  %xmm2, %xmm4
1878 # ifndef USE_SSSE3
1879         psrldq  $13, %xmm3
1880         pslldq  $3, %xmm2
1881         por     %xmm3, %xmm2            /* merge into one 16byte value */
1882 # else
1883         palignr $13, %xmm3, %xmm2       /* merge into one 16byte value */
1884 # endif
1885         TOLOWER (%xmm1, %xmm2)
1887         pcmpeqb %xmm1, %xmm0
1888         pcmpeqb %xmm2, %xmm1
1889         psubb   %xmm0, %xmm1
1890         pmovmskb %xmm1, %edx
1891         sub     $0xffff, %edx
1892         jnz     LABEL(exit)
1894 # ifdef USE_AS_STRNCMP
1895         sub     $16, %r11
1896         jbe     LABEL(strcmp_exitz)
1897 # endif
1899         add     $16, %rcx
1900         movdqa  %xmm4, %xmm3
1901         jmp     LABEL(loop_ashr_13)
1903         .p2align 4
1904 LABEL(nibble_ashr_13):
1905         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
1906         pmovmskb %xmm0, %edx
1907         test    $0xe000, %edx
1908         jnz     LABEL(ashr_13_exittail)
1910 # ifdef USE_AS_STRNCMP
1911         cmp     $2, %r11
1912         jbe     LABEL(ashr_13_exittail)
1913 # endif
1915         pxor    %xmm0, %xmm0
1916         sub     $0x1000, %r10
1917         jmp     LABEL(gobble_ashr_13)
1919         .p2align 4
1920 LABEL(ashr_13_exittail):
1921         movdqa  (%rsi, %rcx), %xmm1
1922         psrldq  $13, %xmm0
1923         psrldq  $13, %xmm3
1924         jmp     LABEL(aftertail)
1927  *  The following cases will be handled by ashr_14
1928  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
1929  *        n(2~15)          n - 2                13(15 +(n - 2) - n)         ashr_14
1930  */
1931         .p2align 4
1932 LABEL(ashr_14):
1933         pxor    %xmm0, %xmm0
1934         movdqa  (%rdi), %xmm2
1935         movdqa  (%rsi), %xmm1
1936         pcmpeqb %xmm1, %xmm0
1937         pslldq  $2, %xmm2
1938         TOLOWER (%xmm1, %xmm2)
1939         pcmpeqb %xmm1, %xmm2
1940         psubb   %xmm0, %xmm2
1941         pmovmskb %xmm2, %r9d
1942         shr     %cl, %edx
1943         shr     %cl, %r9d
1944         sub     %r9d, %edx
1945         jnz     LABEL(less32bytes)
1946         movdqa  (%rdi), %xmm3
1948         UPDATE_STRNCMP_COUNTER
1950         pxor    %xmm0, %xmm0
1951         mov     $16, %rcx       /* index for loads */
1952         mov     $14, %r9d       /* byte position left over from less32bytes case */
1953         /*
1954          * Setup %r10 value allows us to detect crossing a page boundary.
1955          * When %r10 goes positive we have crossed a page boundary and
1956          * need to do a nibble.
1957          */
1958         lea     14(%rdi), %r10
1959         and     $0xfff, %r10    /* offset into 4K page */
1960         sub     $0x1000, %r10   /* subtract 4K pagesize */
1962         .p2align 4
1963 LABEL(loop_ashr_14):
1964         add     $16, %r10
1965         jg      LABEL(nibble_ashr_14)
1967 LABEL(gobble_ashr_14):
1968         movdqa  (%rsi, %rcx), %xmm1
1969         movdqa  (%rdi, %rcx), %xmm2
1970         movdqa  %xmm2, %xmm4
1972 # ifndef USE_SSSE3
1973         psrldq  $14, %xmm3
1974         pslldq  $2, %xmm2
1975         por     %xmm3, %xmm2            /* merge into one 16byte value */
1976 # else
1977         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
1978 # endif
1979         TOLOWER (%xmm1, %xmm2)
1981         pcmpeqb %xmm1, %xmm0
1982         pcmpeqb %xmm2, %xmm1
1983         psubb   %xmm0, %xmm1
1984         pmovmskb %xmm1, %edx
1985         sub     $0xffff, %edx
1986         jnz     LABEL(exit)
1988 # ifdef USE_AS_STRNCMP
1989         sub     $16, %r11
1990         jbe     LABEL(strcmp_exitz)
1991 # endif
1993         add     $16, %rcx
1994         movdqa  %xmm4, %xmm3
1996         add     $16, %r10
1997         jg      LABEL(nibble_ashr_14)   /* cross page boundary */
1999         movdqa  (%rsi, %rcx), %xmm1
2000         movdqa  (%rdi, %rcx), %xmm2
2001         movdqa  %xmm2, %xmm4
2003 # ifndef USE_SSSE3
2004         psrldq  $14, %xmm3
2005         pslldq  $2, %xmm2
2006         por     %xmm3, %xmm2            /* merge into one 16byte value */
2007 # else
2008         palignr $14, %xmm3, %xmm2       /* merge into one 16byte value */
2009 # endif
2010         TOLOWER (%xmm1, %xmm2)
2012         pcmpeqb %xmm1, %xmm0
2013         pcmpeqb %xmm2, %xmm1
2014         psubb   %xmm0, %xmm1
2015         pmovmskb %xmm1, %edx
2016         sub     $0xffff, %edx
2017         jnz     LABEL(exit)
2019 # ifdef USE_AS_STRNCMP
2020         sub     $16, %r11
2021         jbe     LABEL(strcmp_exitz)
2022 # endif
2024         add     $16, %rcx
2025         movdqa  %xmm4, %xmm3
2026         jmp     LABEL(loop_ashr_14)
2028         .p2align 4
2029 LABEL(nibble_ashr_14):
2030         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2031         pmovmskb %xmm0, %edx
2032         test    $0xc000, %edx
2033         jnz     LABEL(ashr_14_exittail)
2035 # ifdef USE_AS_STRNCMP
2036         cmp     $1, %r11
2037         jbe     LABEL(ashr_14_exittail)
2038 # endif
2040         pxor    %xmm0, %xmm0
2041         sub     $0x1000, %r10
2042         jmp     LABEL(gobble_ashr_14)
2044         .p2align 4
2045 LABEL(ashr_14_exittail):
2046         movdqa  (%rsi, %rcx), %xmm1
2047         psrldq  $14, %xmm0
2048         psrldq  $14, %xmm3
2049         jmp     LABEL(aftertail)
2052  *  The following cases will be handled by ashr_15
2053  *  rcx(offset of rsi)  rax(offset of rdi)        relative offset        corresponding case
2054  *        n(1~15)          n - 1                14(15 +(n - 1) - n)         ashr_15
2055  */
2056         .p2align 4
2057 LABEL(ashr_15):
2058         pxor    %xmm0, %xmm0
2059         movdqa  (%rdi), %xmm2
2060         movdqa  (%rsi), %xmm1
2061         pcmpeqb %xmm1, %xmm0
2062         pslldq  $1, %xmm2
2063         TOLOWER (%xmm1, %xmm2)
2064         pcmpeqb %xmm1, %xmm2
2065         psubb   %xmm0, %xmm2
2066         pmovmskb %xmm2, %r9d
2067         shr     %cl, %edx
2068         shr     %cl, %r9d
2069         sub     %r9d, %edx
2070         jnz     LABEL(less32bytes)
2072         movdqa  (%rdi), %xmm3
2074         UPDATE_STRNCMP_COUNTER
2076         pxor    %xmm0, %xmm0
2077         mov     $16, %rcx       /* index for loads */
2078         mov     $15, %r9d       /* byte position left over from less32bytes case */
2079         /*
2080          * Setup %r10 value allows us to detect crossing a page boundary.
2081          * When %r10 goes positive we have crossed a page boundary and
2082          * need to do a nibble.
2083          */
2084         lea     15(%rdi), %r10
2085         and     $0xfff, %r10    /* offset into 4K page */
2087         sub     $0x1000, %r10   /* subtract 4K pagesize */
2089         .p2align 4
2090 LABEL(loop_ashr_15):
2091         add     $16, %r10
2092         jg      LABEL(nibble_ashr_15)
2094 LABEL(gobble_ashr_15):
2095         movdqa  (%rsi, %rcx), %xmm1
2096         movdqa  (%rdi, %rcx), %xmm2
2097         movdqa  %xmm2, %xmm4
2099 # ifndef USE_SSSE3
2100         psrldq  $15, %xmm3
2101         pslldq  $1, %xmm2
2102         por     %xmm3, %xmm2            /* merge into one 16byte value */
2103 # else
2104         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2105 # endif
2106         TOLOWER (%xmm1, %xmm2)
2108         pcmpeqb %xmm1, %xmm0
2109         pcmpeqb %xmm2, %xmm1
2110         psubb   %xmm0, %xmm1
2111         pmovmskb %xmm1, %edx
2112         sub     $0xffff, %edx
2113         jnz     LABEL(exit)
2115 # ifdef USE_AS_STRNCMP
2116         sub     $16, %r11
2117         jbe     LABEL(strcmp_exitz)
2118 # endif
2120         add     $16, %rcx
2121         movdqa  %xmm4, %xmm3
2123         add     $16, %r10
2124         jg      LABEL(nibble_ashr_15)   /* cross page boundary */
2126         movdqa  (%rsi, %rcx), %xmm1
2127         movdqa  (%rdi, %rcx), %xmm2
2128         movdqa  %xmm2, %xmm4
2130 # ifndef USE_SSSE3
2131         psrldq  $15, %xmm3
2132         pslldq  $1, %xmm2
2133         por     %xmm3, %xmm2            /* merge into one 16byte value */
2134 # else
2135         palignr $15, %xmm3, %xmm2       /* merge into one 16byte value */
2136 # endif
2137         TOLOWER (%xmm1, %xmm2)
2139         pcmpeqb %xmm1, %xmm0
2140         pcmpeqb %xmm2, %xmm1
2141         psubb   %xmm0, %xmm1
2142         pmovmskb %xmm1, %edx
2143         sub     $0xffff, %edx
2144         jnz     LABEL(exit)
2146 # ifdef USE_AS_STRNCMP
2147         sub     $16, %r11
2148         jbe     LABEL(strcmp_exitz)
2149 # endif
2151         add     $16, %rcx
2152         movdqa  %xmm4, %xmm3
2153         jmp     LABEL(loop_ashr_15)
2155         .p2align 4
2156 LABEL(nibble_ashr_15):
2157         pcmpeqb %xmm3, %xmm0            /* check nibble for null char */
2158         pmovmskb %xmm0, %edx
2159         test    $0x8000, %edx
2160         jnz     LABEL(ashr_15_exittail)
2162 # ifdef USE_AS_STRNCMP
2163         test    %r11, %r11
2164         je      LABEL(ashr_15_exittail)
2165 # endif
2167         pxor    %xmm0, %xmm0
2168         sub     $0x1000, %r10
2169         jmp     LABEL(gobble_ashr_15)
2171         .p2align 4
2172 LABEL(ashr_15_exittail):
2173         movdqa  (%rsi, %rcx), %xmm1
2174         psrldq  $15, %xmm3
2175         psrldq  $15, %xmm0
2177         .p2align 4
2178 LABEL(aftertail):
2179         TOLOWER (%xmm1, %xmm3)
2180         pcmpeqb %xmm3, %xmm1
2181         psubb   %xmm0, %xmm1
2182         pmovmskb %xmm1, %edx
2183         not     %edx
2185         .p2align 4
2186 LABEL(exit):
2187         lea     -16(%r9, %rcx), %rax    /* locate the exact offset for rdi */
2188 LABEL(less32bytes):
2189         lea     (%rdi, %rax), %rdi      /* locate the exact address for first operand(rdi) */
2190         lea     (%rsi, %rcx), %rsi      /* locate the exact address for second operand(rsi) */
2191         test    %r8d, %r8d
2192         jz      LABEL(ret)
2193         xchg    %rsi, %rdi              /* recover original order according to flag(%r8d) */
2195         .p2align 4
2196 LABEL(ret):
2197 LABEL(less16bytes):
2198         bsf     %rdx, %rdx              /* find and store bit index in %rdx */
2200 # ifdef USE_AS_STRNCMP
2201         sub     %rdx, %r11
2202         jbe     LABEL(strcmp_exitz)
2203 # endif
2204         movzbl  (%rsi, %rdx), %ecx
2205         movzbl  (%rdi, %rdx), %eax
2207 # ifdef USE_AS_STRCASECMP_L
2208         leaq    _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
2209         movl    (%rdx,%rcx,4), %ecx
2210         movl    (%rdx,%rax,4), %eax
2211 # endif
2213         sub     %ecx, %eax
2214         ret
2216 LABEL(strcmp_exitz):
2217         xor     %eax, %eax
2218         ret
2220         .p2align 4
2221 LABEL(Byte0):
2222         movzx   (%rsi), %ecx
2223         movzx   (%rdi), %eax
2225         sub     %ecx, %eax
2226         ret
2227 END (BP_SYM (STRCMP))
2229         .section .rodata,"a",@progbits
2230         .p2align 3
2231 LABEL(unaligned_table):
2232         .int    LABEL(ashr_1) - LABEL(unaligned_table)
2233         .int    LABEL(ashr_2) - LABEL(unaligned_table)
2234         .int    LABEL(ashr_3) - LABEL(unaligned_table)
2235         .int    LABEL(ashr_4) - LABEL(unaligned_table)
2236         .int    LABEL(ashr_5) - LABEL(unaligned_table)
2237         .int    LABEL(ashr_6) - LABEL(unaligned_table)
2238         .int    LABEL(ashr_7) - LABEL(unaligned_table)
2239         .int    LABEL(ashr_8) - LABEL(unaligned_table)
2240         .int    LABEL(ashr_9) - LABEL(unaligned_table)
2241         .int    LABEL(ashr_10) - LABEL(unaligned_table)
2242         .int    LABEL(ashr_11) - LABEL(unaligned_table)
2243         .int    LABEL(ashr_12) - LABEL(unaligned_table)
2244         .int    LABEL(ashr_13) - LABEL(unaligned_table)
2245         .int    LABEL(ashr_14) - LABEL(unaligned_table)
2246         .int    LABEL(ashr_15) - LABEL(unaligned_table)
2247         .int    LABEL(ashr_0) - LABEL(unaligned_table)
2248 #endif /* NOT_IN_libc */
2249 libc_hidden_builtin_def (STRCMP)